1 /*
2  * tests for Microsoft Installer functionality
3  *
4  * Copyright 2005 Mike McCormack for CodeWeavers
5  * Copyright 2005 Aric Stewart for CodeWeavers
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21 
22 #define COBJMACROS
23 
24 #include <assert.h>
25 #include <stdio.h>
26 #include <windows.h>
27 #include <msidefs.h>
28 #include <msi.h>
29 #include <msiquery.h>
30 #include <srrestoreptapi.h>
31 #include <shlobj.h>
32 #include <sddl.h>
33 
34 #include "wine/test.h"
35 
36 static BOOL is_wow64;
37 static const char msifile[] = "winetest-package.msi";
38 static const WCHAR msifileW[] = L"winetest-package.msi";
39 static char CURR_DIR[MAX_PATH];
40 
41 static INSTALLSTATE (WINAPI *pMsiGetComponentPathExA)(LPCSTR, LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPSTR, LPDWORD);
42 
43 static LONG (WINAPI *pRegDeleteKeyExA)(HKEY, LPCSTR, REGSAM, DWORD);
44 static LONG (WINAPI *pRegDeleteKeyExW)(HKEY, LPCWSTR, REGSAM, DWORD);
45 static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
46 static BOOL (WINAPI *pSRRemoveRestorePoint)(DWORD);
47 static BOOL (WINAPI *pSRSetRestorePointA)(RESTOREPOINTINFOA*, STATEMGRSTATUS*);
48 
49 static void init_functionpointers(void)
50 {
51     HMODULE hmsi = GetModuleHandleA("msi.dll");
52     HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
53     HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
54     HMODULE hsrclient = LoadLibraryA("srclient.dll");
55 
56 #define GET_PROC(mod, func) \
57     p ## func = (void*)GetProcAddress(mod, #func);
58 
59     GET_PROC(hmsi, MsiGetComponentPathExA);
60 
61     GET_PROC(hadvapi32, RegDeleteKeyExA)
62     GET_PROC(hadvapi32, RegDeleteKeyExW)
63     GET_PROC(hkernel32, IsWow64Process)
64 
65     GET_PROC(hsrclient, SRRemoveRestorePoint);
66     GET_PROC(hsrclient, SRSetRestorePointA);
67 
68 #undef GET_PROC
69 }
70 
71 static BOOL is_process_limited(void)
72 {
73     SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
74     PSID Group = NULL;
75     BOOL IsInGroup;
76     HANDLE token;
77 
78     if (!AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
79                                   DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &Group) ||
80         !CheckTokenMembership(NULL, Group, &IsInGroup))
81     {
82         trace("Could not check if the current user is an administrator\n");
83         FreeSid(Group);
84         return FALSE;
85     }
86     FreeSid(Group);
87 
88     if (!IsInGroup)
89     {
90         if (!AllocateAndInitializeSid(&NtAuthority, 2,
91                                       SECURITY_BUILTIN_DOMAIN_RID,
92                                       DOMAIN_ALIAS_RID_POWER_USERS,
93                                       0, 0, 0, 0, 0, 0, &Group) ||
94             !CheckTokenMembership(NULL, Group, &IsInGroup))
95         {
96             trace("Could not check if the current user is a power user\n");
97             return FALSE;
98         }
99         if (!IsInGroup)
100         {
101             /* Only administrators and power users can be powerful */
102             return TRUE;
103         }
104     }
105 
106     if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
107     {
108         BOOL ret;
109         TOKEN_ELEVATION_TYPE type = TokenElevationTypeDefault;
110         DWORD size;
111 
112         ret = GetTokenInformation(token, TokenElevationType, &type, sizeof(type), &size);
113         CloseHandle(token);
114         return (ret && type == TokenElevationTypeLimited);
115     }
116     return FALSE;
117 }
118 
119 static LONG delete_key( HKEY key, LPCSTR subkey, REGSAM access )
120 {
121     if (pRegDeleteKeyExA)
122         return pRegDeleteKeyExA( key, subkey, access, 0 );
123     return RegDeleteKeyA( key, subkey );
124 }
125 
126 static char *get_user_sid(void)
127 {
128     HANDLE token;
129     DWORD size = 0;
130     TOKEN_USER *user;
131     char *usersid = NULL;
132 
133     OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
134     GetTokenInformation(token, TokenUser, NULL, size, &size);
135 
136     user = malloc(size);
137     GetTokenInformation(token, TokenUser, user, size, &size);
138     ConvertSidToStringSidA(user->User.Sid, &usersid);
139     free(user);
140 
141     CloseHandle(token);
142     return usersid;
143 }
144 
145 /* RegDeleteTreeW from dlls/advapi32/registry.c */
146 static LSTATUS package_RegDeleteTreeW(HKEY hKey, LPCWSTR lpszSubKey, REGSAM access)
147 {
148     LONG ret;
149     DWORD dwMaxSubkeyLen, dwMaxValueLen;
150     DWORD dwMaxLen, dwSize;
151     WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
152     HKEY hSubKey = hKey;
153 
154     if(lpszSubKey)
155     {
156         ret = RegOpenKeyExW(hKey, lpszSubKey, 0, access, &hSubKey);
157         if (ret) return ret;
158     }
159 
160     ret = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL,
161             &dwMaxSubkeyLen, NULL, NULL, &dwMaxValueLen, NULL, NULL, NULL);
162     if (ret) goto cleanup;
163 
164     dwMaxSubkeyLen++;
165     dwMaxValueLen++;
166     dwMaxLen = max(dwMaxSubkeyLen, dwMaxValueLen);
167     if (dwMaxLen > ARRAY_SIZE(szNameBuf))
168     {
169         /* Name too big: alloc a buffer for it */
170         if (!(lpszName = malloc(dwMaxLen * sizeof(WCHAR))))
171         {
172             ret = ERROR_NOT_ENOUGH_MEMORY;
173             goto cleanup;
174         }
175     }
176 
177     /* Recursively delete all the subkeys */
178     while (TRUE)
179     {
180         dwSize = dwMaxLen;
181         if (RegEnumKeyExW(hSubKey, 0, lpszName, &dwSize, NULL,
182                           NULL, NULL, NULL)) break;
183 
184         ret = package_RegDeleteTreeW(hSubKey, lpszName, access);
185         if (ret) goto cleanup;
186     }
187 
188     if (lpszSubKey)
189     {
190         if (pRegDeleteKeyExW)
191             ret = pRegDeleteKeyExW(hKey, lpszSubKey, access, 0);
192         else
193             ret = RegDeleteKeyW(hKey, lpszSubKey);
194     }
195     else
196         while (TRUE)
197         {
198             dwSize = dwMaxLen;
199             if (RegEnumValueW(hKey, 0, lpszName, &dwSize,
200                   NULL, NULL, NULL, NULL)) break;
201 
202             ret = RegDeleteValueW(hKey, lpszName);
203             if (ret) goto cleanup;
204         }
205 
206 cleanup:
207     if (lpszName != szNameBuf) free(lpszName);
208     if (lpszSubKey) RegCloseKey(hSubKey);
209     return ret;
210 }
211 
212 static BOOL squash_guid(LPCWSTR in, LPWSTR out)
213 {
214     DWORD i,n=1;
215     GUID guid;
216 
217     if (FAILED(CLSIDFromString((LPCOLESTR)in, &guid)))
218         return FALSE;
219 
220     for(i=0; i<8; i++)
221         out[7-i] = in[n++];
222     n++;
223     for(i=0; i<4; i++)
224         out[11-i] = in[n++];
225     n++;
226     for(i=0; i<4; i++)
227         out[15-i] = in[n++];
228     n++;
229     for(i=0; i<2; i++)
230     {
231         out[17+i*2] = in[n++];
232         out[16+i*2] = in[n++];
233     }
234     n++;
235     for( ; i<8; i++)
236     {
237         out[17+i*2] = in[n++];
238         out[16+i*2] = in[n++];
239     }
240     out[32]=0;
241     return TRUE;
242 }
243 
244 static void create_test_guid(LPSTR prodcode, LPSTR squashed)
245 {
246     WCHAR guidW[MAX_PATH];
247     WCHAR squashedW[MAX_PATH];
248     GUID guid;
249     HRESULT hr;
250     int size;
251 
252     hr = CoCreateGuid(&guid);
253     ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr);
254 
255     size = StringFromGUID2(&guid, guidW, MAX_PATH);
256     ok(size == 39, "Expected 39, got %#lx\n", hr);
257 
258     WideCharToMultiByte(CP_ACP, 0, guidW, size, prodcode, MAX_PATH, NULL, NULL);
259     squash_guid(guidW, squashedW);
260     WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
261 }
262 
263 static void set_component_path(LPCSTR filename, MSIINSTALLCONTEXT context,
264                                LPCSTR guid, LPSTR usersid, BOOL dir)
265 {
266     WCHAR guidW[MAX_PATH];
267     WCHAR squashedW[MAX_PATH];
268     CHAR squashed[MAX_PATH];
269     CHAR comppath[MAX_PATH + 81];
270     CHAR prodpath[MAX_PATH];
271     CHAR path[MAX_PATH];
272     LPCSTR prod = NULL;
273     HKEY hkey;
274     REGSAM access = KEY_ALL_ACCESS;
275 
276     if (is_wow64)
277         access |= KEY_WOW64_64KEY;
278 
279     MultiByteToWideChar(CP_ACP, 0, guid, -1, guidW, MAX_PATH);
280     squash_guid(guidW, squashedW);
281     WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
282 
283     if (context == MSIINSTALLCONTEXT_MACHINE)
284     {
285         prod = "3D0DAE300FACA1300AD792060BCDAA92";
286         sprintf(comppath,
287                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
288                 "Installer\\UserData\\S-1-5-18\\Components\\%s", squashed);
289         lstrcpyA(prodpath,
290                  "SOFTWARE\\Classes\\Installer\\"
291                  "Products\\3D0DAE300FACA1300AD792060BCDAA92");
292     }
293     else if (context == MSIINSTALLCONTEXT_USERUNMANAGED)
294     {
295         prod = "7D2F387510109040002000060BECB6AB";
296         sprintf(comppath,
297                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
298                 "Installer\\UserData\\%s\\Components\\%s", usersid, squashed);
299         sprintf(prodpath,
300                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
301                 "Installer\\%s\\Installer\\Products\\"
302                 "7D2F387510109040002000060BECB6AB", usersid);
303     }
304     else if (context == MSIINSTALLCONTEXT_USERMANAGED)
305     {
306         prod = "7D2F387510109040002000060BECB6AB";
307         sprintf(comppath,
308                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
309                 "Installer\\UserData\\%s\\Components\\%s", usersid, squashed);
310         sprintf(prodpath,
311                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
312                 "Installer\\Managed\\%s\\Installer\\Products\\"
313                 "7D2F387510109040002000060BECB6AB", usersid);
314     }
315 
316     RegCreateKeyExA(HKEY_LOCAL_MACHINE, comppath, 0, NULL, 0, access, NULL, &hkey, NULL);
317 
318     lstrcpyA(path, CURR_DIR);
319     lstrcatA(path, "\\");
320     if (!dir) lstrcatA(path, filename);
321 
322     RegSetValueExA(hkey, prod, 0, REG_SZ, (LPBYTE)path, lstrlenA(path));
323     RegCloseKey(hkey);
324 
325     RegCreateKeyExA(HKEY_LOCAL_MACHINE, prodpath, 0, NULL, 0, access, NULL, &hkey, NULL);
326     RegCloseKey(hkey);
327 }
328 
329 static void delete_component_path(LPCSTR guid, MSIINSTALLCONTEXT context, LPSTR usersid)
330 {
331     WCHAR guidW[MAX_PATH];
332     WCHAR squashedW[MAX_PATH];
333     WCHAR substrW[MAX_PATH];
334     CHAR squashed[MAX_PATH];
335     CHAR comppath[MAX_PATH + 81];
336     CHAR prodpath[MAX_PATH];
337     REGSAM access = KEY_ALL_ACCESS;
338 
339     if (is_wow64)
340         access |= KEY_WOW64_64KEY;
341 
342     MultiByteToWideChar(CP_ACP, 0, guid, -1, guidW, MAX_PATH);
343     squash_guid(guidW, squashedW);
344     WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
345 
346     if (context == MSIINSTALLCONTEXT_MACHINE)
347     {
348         sprintf(comppath,
349                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
350                 "Installer\\UserData\\S-1-5-18\\Components\\%s", squashed);
351         lstrcpyA(prodpath,
352                  "SOFTWARE\\Classes\\Installer\\"
353                  "Products\\3D0DAE300FACA1300AD792060BCDAA92");
354     }
355     else if (context == MSIINSTALLCONTEXT_USERUNMANAGED)
356     {
357         sprintf(comppath,
358                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
359                 "Installer\\UserData\\%s\\Components\\%s", usersid, squashed);
360         sprintf(prodpath,
361                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
362                 "Installer\\%s\\Installer\\Products\\"
363                 "7D2F387510109040002000060BECB6AB", usersid);
364     }
365     else if (context == MSIINSTALLCONTEXT_USERMANAGED)
366     {
367         sprintf(comppath,
368                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
369                 "Installer\\UserData\\%s\\Components\\%s", usersid, squashed);
370         sprintf(prodpath,
371                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
372                 "Installer\\Managed\\%s\\Installer\\Products\\"
373                 "7D2F387510109040002000060BECB6AB", usersid);
374     }
375 
376     MultiByteToWideChar(CP_ACP, 0, comppath, -1, substrW, MAX_PATH);
377     package_RegDeleteTreeW(HKEY_LOCAL_MACHINE, substrW, access);
378 
379     MultiByteToWideChar(CP_ACP, 0, prodpath, -1, substrW, MAX_PATH);
380     package_RegDeleteTreeW(HKEY_LOCAL_MACHINE, substrW, access);
381 }
382 
383 static UINT do_query(MSIHANDLE hdb, const char *query, MSIHANDLE *phrec)
384 {
385     MSIHANDLE hview = 0;
386     UINT r, ret;
387 
388     /* open a select query */
389     r = MsiDatabaseOpenViewA(hdb, query, &hview);
390     if (r != ERROR_SUCCESS)
391         return r;
392     r = MsiViewExecute(hview, 0);
393     if (r != ERROR_SUCCESS)
394         return r;
395     ret = MsiViewFetch(hview, phrec);
396     r = MsiViewClose(hview);
397     if (r != ERROR_SUCCESS)
398         return r;
399     r = MsiCloseHandle(hview);
400     if (r != ERROR_SUCCESS)
401         return r;
402     return ret;
403 }
404 
405 static UINT run_query( MSIHANDLE hdb, const char *query )
406 {
407     MSIHANDLE hview = 0;
408     UINT r;
409 
410     r = MsiDatabaseOpenViewA(hdb, query, &hview);
411     if( r != ERROR_SUCCESS )
412         return r;
413 
414     r = MsiViewExecute(hview, 0);
415     if( r == ERROR_SUCCESS )
416         r = MsiViewClose(hview);
417     MsiCloseHandle(hview);
418     return r;
419 }
420 
421 static UINT create_component_table( MSIHANDLE hdb )
422 {
423     UINT r = run_query( hdb,
424             "CREATE TABLE `Component` ( "
425             "`Component` CHAR(72) NOT NULL, "
426             "`ComponentId` CHAR(38), "
427             "`Directory_` CHAR(72) NOT NULL, "
428             "`Attributes` SHORT NOT NULL, "
429             "`Condition` CHAR(255), "
430             "`KeyPath` CHAR(72) "
431             "PRIMARY KEY `Component`)" );
432     ok(r == ERROR_SUCCESS, "Failed to create Component table: %u\n", r);
433     return r;
434 }
435 
436 static UINT create_feature_table( MSIHANDLE hdb )
437 {
438     UINT r = run_query( hdb,
439             "CREATE TABLE `Feature` ( "
440             "`Feature` CHAR(38) NOT NULL, "
441             "`Feature_Parent` CHAR(38), "
442             "`Title` CHAR(64), "
443             "`Description` CHAR(255), "
444             "`Display` SHORT NOT NULL, "
445             "`Level` SHORT NOT NULL, "
446             "`Directory_` CHAR(72), "
447             "`Attributes` SHORT NOT NULL "
448             "PRIMARY KEY `Feature`)" );
449     ok(r == ERROR_SUCCESS, "Failed to create Feature table: %u\n", r);
450     return r;
451 }
452 
453 static UINT create_feature_components_table( MSIHANDLE hdb )
454 {
455     UINT r = run_query( hdb,
456             "CREATE TABLE `FeatureComponents` ( "
457             "`Feature_` CHAR(38) NOT NULL, "
458             "`Component_` CHAR(72) NOT NULL "
459             "PRIMARY KEY `Feature_`, `Component_` )" );
460     ok(r == ERROR_SUCCESS, "Failed to create FeatureComponents table: %u\n", r);
461     return r;
462 }
463 
464 static UINT create_file_table( MSIHANDLE hdb )
465 {
466     UINT r = run_query( hdb,
467             "CREATE TABLE `File` ("
468             "`File` CHAR(72) NOT NULL, "
469             "`Component_` CHAR(72) NOT NULL, "
470             "`FileName` CHAR(255) NOT NULL, "
471             "`FileSize` LONG NOT NULL, "
472             "`Version` CHAR(72), "
473             "`Language` CHAR(20), "
474             "`Attributes` SHORT, "
475             "`Sequence` SHORT NOT NULL "
476             "PRIMARY KEY `File`)" );
477     ok(r == ERROR_SUCCESS, "Failed to create File table: %u\n", r);
478     return r;
479 }
480 
481 static UINT create_remove_file_table( MSIHANDLE hdb )
482 {
483     UINT r = run_query( hdb,
484             "CREATE TABLE `RemoveFile` ("
485             "`FileKey` CHAR(72) NOT NULL, "
486             "`Component_` CHAR(72) NOT NULL, "
487             "`FileName` CHAR(255) LOCALIZABLE, "
488             "`DirProperty` CHAR(72) NOT NULL, "
489             "`InstallMode` SHORT NOT NULL "
490             "PRIMARY KEY `FileKey`)" );
491     ok(r == ERROR_SUCCESS, "Failed to create RemoveFile table: %u\n", r);
492     return r;
493 }
494 
495 static UINT create_appsearch_table( MSIHANDLE hdb )
496 {
497     UINT r = run_query( hdb,
498             "CREATE TABLE `AppSearch` ("
499             "`Property` CHAR(72) NOT NULL, "
500             "`Signature_` CHAR(72) NOT NULL "
501             "PRIMARY KEY `Property`, `Signature_`)" );
502     ok(r == ERROR_SUCCESS, "Failed to create AppSearch table: %u\n", r);
503     return r;
504 }
505 
506 static UINT create_reglocator_table( MSIHANDLE hdb )
507 {
508     UINT r = run_query( hdb,
509             "CREATE TABLE `RegLocator` ("
510             "`Signature_` CHAR(72) NOT NULL, "
511             "`Root` SHORT NOT NULL, "
512             "`Key` CHAR(255) NOT NULL, "
513             "`Name` CHAR(255), "
514             "`Type` SHORT "
515             "PRIMARY KEY `Signature_`)" );
516     ok(r == ERROR_SUCCESS, "Failed to create RegLocator table: %u\n", r);
517     return r;
518 }
519 
520 static UINT create_signature_table( MSIHANDLE hdb )
521 {
522     UINT r = run_query( hdb,
523             "CREATE TABLE `Signature` ("
524             "`Signature` CHAR(72) NOT NULL, "
525             "`FileName` CHAR(255) NOT NULL, "
526             "`MinVersion` CHAR(20), "
527             "`MaxVersion` CHAR(20), "
528             "`MinSize` LONG, "
529             "`MaxSize` LONG, "
530             "`MinDate` LONG, "
531             "`MaxDate` LONG, "
532             "`Languages` CHAR(255) "
533             "PRIMARY KEY `Signature`)" );
534     ok(r == ERROR_SUCCESS, "Failed to create Signature table: %u\n", r);
535     return r;
536 }
537 
538 static UINT create_launchcondition_table( MSIHANDLE hdb )
539 {
540     UINT r = run_query( hdb,
541             "CREATE TABLE `LaunchCondition` ("
542             "`Condition` CHAR(255) NOT NULL, "
543             "`Description` CHAR(255) NOT NULL "
544             "PRIMARY KEY `Condition`)" );
545     ok(r == ERROR_SUCCESS, "Failed to create LaunchCondition table: %u\n", r);
546     return r;
547 }
548 
549 static UINT create_property_table( MSIHANDLE hdb )
550 {
551     UINT r = run_query( hdb,
552             "CREATE TABLE `Property` ("
553             "`Property` CHAR(72) NOT NULL, "
554             "`Value` CHAR(0) "
555             "PRIMARY KEY `Property`)" );
556     ok(r == ERROR_SUCCESS, "Failed to create Property table: %u\n", r);
557     return r;
558 }
559 
560 static UINT create_install_execute_sequence_table( MSIHANDLE hdb )
561 {
562     UINT r = run_query( hdb,
563             "CREATE TABLE `InstallExecuteSequence` ("
564             "`Action` CHAR(72) NOT NULL, "
565             "`Condition` CHAR(255), "
566             "`Sequence` SHORT "
567             "PRIMARY KEY `Action`)" );
568     ok(r == ERROR_SUCCESS, "Failed to create InstallExecuteSequence table: %u\n", r);
569     return r;
570 }
571 
572 static UINT create_install_ui_sequence_table( MSIHANDLE hdb )
573 {
574     UINT r = run_query( hdb,
575             "CREATE TABLE `InstallUISequence` ("
576             "`Action` CHAR(72) NOT NULL, "
577             "`Condition` CHAR(255), "
578             "`Sequence` SHORT "
579             "PRIMARY KEY `Action`)" );
580     ok(r == ERROR_SUCCESS, "Failed to create InstallUISequence table: %u\n", r);
581     return r;
582 }
583 
584 static UINT create_media_table( MSIHANDLE hdb )
585 {
586     UINT r = run_query( hdb,
587             "CREATE TABLE `Media` ("
588             "`DiskId` SHORT NOT NULL, "
589             "`LastSequence` SHORT NOT NULL, "
590             "`DiskPrompt` CHAR(64), "
591             "`Cabinet` CHAR(255), "
592             "`VolumeLabel` CHAR(32), "
593             "`Source` CHAR(72) "
594             "PRIMARY KEY `DiskId`)" );
595     ok(r == ERROR_SUCCESS, "Failed to create Media table: %u\n", r);
596     return r;
597 }
598 
599 static UINT create_ccpsearch_table( MSIHANDLE hdb )
600 {
601     UINT r = run_query( hdb,
602             "CREATE TABLE `CCPSearch` ("
603             "`Signature_` CHAR(72) NOT NULL "
604             "PRIMARY KEY `Signature_`)" );
605     ok(r == ERROR_SUCCESS, "Failed to create CCPSearch table: %u\n", r);
606     return r;
607 }
608 
609 static UINT create_drlocator_table( MSIHANDLE hdb )
610 {
611     UINT r = run_query( hdb,
612             "CREATE TABLE `DrLocator` ("
613             "`Signature_` CHAR(72) NOT NULL, "
614             "`Parent` CHAR(72), "
615             "`Path` CHAR(255), "
616             "`Depth` SHORT "
617             "PRIMARY KEY `Signature_`, `Parent`, `Path`)" );
618     ok(r == ERROR_SUCCESS, "Failed to create DrLocator table: %u\n", r);
619     return r;
620 }
621 
622 static UINT create_complocator_table( MSIHANDLE hdb )
623 {
624     UINT r = run_query( hdb,
625             "CREATE TABLE `CompLocator` ("
626             "`Signature_` CHAR(72) NOT NULL, "
627             "`ComponentId` CHAR(38) NOT NULL, "
628             "`Type` SHORT "
629             "PRIMARY KEY `Signature_`)" );
630     ok(r == ERROR_SUCCESS, "Failed to create CompLocator table: %u\n", r);
631     return r;
632 }
633 
634 static UINT create_inilocator_table( MSIHANDLE hdb )
635 {
636     UINT r = run_query( hdb,
637             "CREATE TABLE `IniLocator` ("
638             "`Signature_` CHAR(72) NOT NULL, "
639             "`FileName` CHAR(255) NOT NULL, "
640             "`Section` CHAR(96)NOT NULL, "
641             "`Key` CHAR(128)NOT NULL, "
642             "`Field` SHORT, "
643             "`Type` SHORT "
644             "PRIMARY KEY `Signature_`)" );
645     ok(r == ERROR_SUCCESS, "Failed to create IniLocator table: %u\n", r);
646     return r;
647 }
648 
649 static UINT create_custom_action_table( MSIHANDLE hdb )
650 {
651     UINT r = run_query( hdb,
652             "CREATE TABLE `CustomAction` ("
653             "`Action` CHAR(72) NOT NULL, "
654             "`Type` SHORT NOT NULL, "
655             "`Source` CHAR(75), "
656             "`Target` CHAR(255) "
657             "PRIMARY KEY `Action`)" );
658     ok(r == ERROR_SUCCESS, "Failed to create CustomAction table: %u\n", r);
659     return r;
660 }
661 
662 static UINT create_dialog_table( MSIHANDLE hdb )
663 {
664     UINT r = run_query(hdb,
665             "CREATE TABLE `Dialog` ("
666             "`Dialog` CHAR(72) NOT NULL, "
667             "`HCentering` SHORT NOT NULL, "
668             "`VCentering` SHORT NOT NULL, "
669             "`Width` SHORT NOT NULL, "
670             "`Height` SHORT NOT NULL, "
671             "`Attributes` LONG, "
672             "`Title` CHAR(128) LOCALIZABLE, "
673             "`Control_First` CHAR(50) NOT NULL, "
674             "`Control_Default` CHAR(50), "
675             "`Control_Cancel` CHAR(50) "
676             "PRIMARY KEY `Dialog`)");
677     ok(r == ERROR_SUCCESS, "Failed to create Dialog table: %u\n", r);
678     return r;
679 }
680 
681 static UINT create_control_table( MSIHANDLE hdb )
682 {
683     UINT r = run_query(hdb,
684             "CREATE TABLE `Control` ("
685             "`Dialog_` CHAR(72) NOT NULL, "
686             "`Control` CHAR(50) NOT NULL, "
687             "`Type` CHAR(20) NOT NULL, "
688             "`X` SHORT NOT NULL, "
689             "`Y` SHORT NOT NULL, "
690             "`Width` SHORT NOT NULL, "
691             "`Height` SHORT NOT NULL, "
692             "`Attributes` LONG, "
693             "`Property` CHAR(50), "
694             "`Text` CHAR(0) LOCALIZABLE, "
695             "`Control_Next` CHAR(50), "
696             "`Help` CHAR(255) LOCALIZABLE "
697             "PRIMARY KEY `Dialog_`, `Control`)");
698     ok(r == ERROR_SUCCESS, "Failed to create Control table: %u\n", r);
699     return r;
700 }
701 
702 static UINT create_controlevent_table( MSIHANDLE hdb )
703 {
704     UINT r = run_query(hdb,
705             "CREATE TABLE `ControlEvent` ("
706             "`Dialog_` CHAR(72) NOT NULL, "
707             "`Control_` CHAR(50) NOT NULL, "
708             "`Event` CHAR(50) NOT NULL, "
709             "`Argument` CHAR(255) NOT NULL, "
710             "`Condition` CHAR(255), "
711             "`Ordering` SHORT "
712             "PRIMARY KEY `Dialog_`, `Control_`, `Event`, `Argument`, `Condition`)");
713     ok(r == ERROR_SUCCESS, "Failed to create ControlEvent table: %u\n", r);
714     return r;
715 }
716 
717 static UINT create_actiontext_table( MSIHANDLE hdb )
718 {
719     UINT r = run_query(hdb,
720             "CREATE TABLE `ActionText` ("
721             "`Action` CHAR(72) NOT NULL, "
722             "`Description` CHAR(64) LOCALIZABLE, "
723             "`Template` CHAR(128) LOCALIZABLE "
724             "PRIMARY KEY `Action`)");
725     ok(r == ERROR_SUCCESS, "Failed to create ActionText table: %u\n", r);
726     return r;
727 }
728 
729 static UINT create_upgrade_table( MSIHANDLE hdb )
730 {
731     UINT r = run_query( hdb,
732             "CREATE TABLE `Upgrade` ("
733             "`UpgradeCode` CHAR(38) NOT NULL, "
734             "`VersionMin` CHAR(20), "
735             "`VersionMax` CHAR(20), "
736             "`Language` CHAR(255), "
737             "`Attributes` SHORT, "
738             "`Remove` CHAR(255), "
739             "`ActionProperty` CHAR(72) NOT NULL "
740             "PRIMARY KEY `UpgradeCode`, `VersionMin`, `VersionMax`, `Language`)" );
741     ok(r == ERROR_SUCCESS, "Failed to create Upgrade table: %u\n", r);
742     return r;
743 }
744 
745 static inline UINT add_entry(const char *file, int line, const char *type, MSIHANDLE hdb, const char *values, const char *insert)
746 {
747     char *query;
748     UINT sz, r;
749 
750     sz = strlen(values) + strlen(insert) + 1;
751     query = malloc(sz);
752     sprintf(query, insert, values);
753     r = run_query(hdb, query);
754     free(query);
755     ok_(file, line)(r == ERROR_SUCCESS, "failed to insert into %s table: %u\n", type, r);
756     return r;
757 }
758 
759 #define add_component_entry(hdb, values) add_entry(__FILE__, __LINE__, "Component", hdb, values, \
760                "INSERT INTO `Component`  " \
761                "(`Component`, `ComponentId`, `Directory_`, " \
762                "`Attributes`, `Condition`, `KeyPath`) VALUES( %s )")
763 
764 #define add_directory_entry(hdb, values) add_entry(__FILE__, __LINE__, "Directory", hdb, values, \
765                "INSERT INTO `Directory` " \
766                "(`Directory`,`Directory_Parent`,`DefaultDir`) VALUES( %s )")
767 
768 #define add_feature_entry(hdb, values) add_entry(__FILE__, __LINE__, "Feature", hdb, values, \
769                "INSERT INTO `Feature` " \
770                "(`Feature`, `Feature_Parent`, `Title`, `Description`, " \
771                "`Display`, `Level`, `Directory_`, `Attributes`) VALUES( %s )")
772 
773 #define add_feature_components_entry(hdb, values) add_entry(__FILE__, __LINE__, "FeatureComponents", hdb, values, \
774                "INSERT INTO `FeatureComponents` " \
775                "(`Feature_`, `Component_`) VALUES( %s )")
776 
777 #define add_file_entry(hdb, values) add_entry(__FILE__, __LINE__, "File", hdb, values, \
778                "INSERT INTO `File` " \
779                "(`File`, `Component_`, `FileName`, `FileSize`, " \
780                "`Version`, `Language`, `Attributes`, `Sequence`) VALUES( %s )")
781 
782 #define add_appsearch_entry(hdb, values) add_entry(__FILE__, __LINE__, "AppSearch", hdb, values, \
783                "INSERT INTO `AppSearch` " \
784                "(`Property`, `Signature_`) VALUES( %s )")
785 
786 #define add_signature_entry(hdb, values) add_entry(__FILE__, __LINE__, "Signature", hdb, values, \
787                "INSERT INTO `Signature` " \
788                "(`Signature`, `FileName`, `MinVersion`, `MaxVersion`," \
789                " `MinSize`, `MaxSize`, `MinDate`, `MaxDate`, `Languages`) " \
790                "VALUES( %s )")
791 
792 #define add_launchcondition_entry(hdb, values) add_entry(__FILE__, __LINE__, "LaunchCondition", hdb, values, \
793                "INSERT INTO `LaunchCondition` " \
794                "(`Condition`, `Description`) VALUES( %s )")
795 
796 #define add_property_entry(hdb, values) add_entry(__FILE__, __LINE__, "Property", hdb, values, \
797                "INSERT INTO `Property` (`Property`, `Value`) VALUES( %s )")
798 
799 #define update_ProductVersion_property(hdb, value) add_entry(__FILE__, __LINE__, "Property", hdb, value, \
800                "UPDATE `Property` SET `Value` = '%s' WHERE `Property` = 'ProductVersion'")
801 
802 #define update_ProductCode_property(hdb, value) add_entry(__FILE__, __LINE__, "Property", hdb, value, \
803                "UPDATE `Property` SET `Value` = '%s' WHERE `Property` = 'ProductCode'")
804 
805 #define add_install_execute_sequence_entry(hdb, values) add_entry(__FILE__, __LINE__, "InstallExecuteSequence", hdb, values, \
806                "INSERT INTO `InstallExecuteSequence` " \
807                "(`Action`, `Condition`, `Sequence`) VALUES( %s )")
808 
809 #define add_install_ui_sequence_entry(hdb, values) add_entry(__FILE__, __LINE__, "InstallUISequence", hdb, values, \
810                "INSERT INTO `InstallUISequence` " \
811                "(`Action`, `Condition`, `Sequence`) VALUES( %s )")
812 
813 #define add_media_entry(hdb, values) add_entry(__FILE__, __LINE__, "Media", hdb, values, \
814                "INSERT INTO `Media` " \
815                "(`DiskId`, `LastSequence`, `DiskPrompt`, " \
816                "`Cabinet`, `VolumeLabel`, `Source`) VALUES( %s )")
817 
818 #define add_ccpsearch_entry(hdb, values) add_entry(__FILE__, __LINE__, "CCPSearch", hdb, values, \
819                "INSERT INTO `CCPSearch` (`Signature_`) VALUES( %s )")
820 
821 #define add_drlocator_entry(hdb, values) add_entry(__FILE__, __LINE__, "DrLocator", hdb, values, \
822                "INSERT INTO `DrLocator` " \
823                "(`Signature_`, `Parent`, `Path`, `Depth`) VALUES( %s )")
824 
825 #define add_complocator_entry(hdb, values) add_entry(__FILE__, __LINE__, "CompLocator", hdb, values, \
826                "INSERT INTO `CompLocator` " \
827                "(`Signature_`, `ComponentId`, `Type`) VALUES( %s )")
828 
829 #define add_inilocator_entry(hdb, values) add_entry(__FILE__, __LINE__, "IniLocator", hdb, values, \
830                "INSERT INTO `IniLocator` " \
831                "(`Signature_`, `FileName`, `Section`, `Key`, `Field`, `Type`) " \
832                "VALUES( %s )")
833 
834 #define add_custom_action_entry(hdb, values) add_entry(__FILE__, __LINE__, "CustomAction", hdb, values, \
835                "INSERT INTO `CustomAction`  " \
836                "(`Action`, `Type`, `Source`, `Target`) VALUES( %s )")
837 
838 #define add_dialog_entry(hdb, values) add_entry(__FILE__, __LINE__, "Dialog", hdb, values, \
839                "INSERT INTO `Dialog` " \
840                "(`Dialog`, `HCentering`, `VCentering`, `Width`, `Height`, `Attributes`, `Control_First`) VALUES ( %s )")
841 
842 #define add_control_entry(hdb, values) add_entry(__FILE__, __LINE__, "Control", hdb, values, \
843                "INSERT INTO `Control` " \
844                "(`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, `Attributes`, `Text`) VALUES( %s )");
845 
846 #define add_controlevent_entry(hdb, values) add_entry(__FILE__, __LINE__, "ControlEvent", hdb, values, \
847                "INSERT INTO `ControlEvent` " \
848                "(`Dialog_`, `Control_`, `Event`, `Argument`, `Condition`, `Ordering`) VALUES( %s )");
849 
850 #define add_actiontext_entry(hdb, values) add_entry(__FILE__, __LINE__, "ActionText", hdb, values, \
851                "INSERT INTO `ActionText` " \
852                "(`Action`, `Description`, `Template`) VALUES( %s )");
853 
854 #define add_upgrade_entry(hdb, values) add_entry(__FILE__, __LINE__, "Upgrade", hdb, values, \
855                "INSERT INTO `Upgrade` " \
856                "(`UpgradeCode`, `VersionMin`, `VersionMax`, `Language`, `Attributes`, `Remove`, `ActionProperty`) VALUES( %s )");
857 
858 static UINT add_reglocator_entry( MSIHANDLE hdb, const char *sig, UINT root, const char *path,
859                                   const char *name, UINT type )
860 {
861     const char insert[] =
862         "INSERT INTO `RegLocator` (`Signature_`, `Root`, `Key`, `Name`, `Type`) "
863         "VALUES( '%s', %u, '%s', '%s', %u )";
864     char *query;
865     UINT sz, r;
866 
867     sz = strlen( sig ) + 10 + strlen( path ) + strlen( name ) + 10 + sizeof( insert );
868     query = malloc( sz );
869     sprintf( query, insert, sig, root, path, name, type );
870     r = run_query( hdb, query );
871     free( query );
872     ok(r == ERROR_SUCCESS, "failed to insert into reglocator table: %u\n", r); \
873     return r;
874 }
875 
876 static UINT set_summary_info(MSIHANDLE hdb)
877 {
878     UINT res;
879     MSIHANDLE suminfo;
880 
881     /* build summary info */
882     res = MsiGetSummaryInformationA(hdb, NULL, 7, &suminfo);
883     ok( res == ERROR_SUCCESS , "Failed to open summaryinfo\n" );
884 
885     res = MsiSummaryInfoSetPropertyA(suminfo,2, VT_LPSTR, 0,NULL,
886                         "Installation Database");
887     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
888 
889     res = MsiSummaryInfoSetPropertyA(suminfo,3, VT_LPSTR, 0,NULL,
890                         "Installation Database");
891     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
892 
893     res = MsiSummaryInfoSetPropertyA(suminfo,4, VT_LPSTR, 0,NULL,
894                         "Wine Hackers");
895     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
896 
897     res = MsiSummaryInfoSetPropertyA(suminfo,7, VT_LPSTR, 0,NULL,
898                     ";1033");
899     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
900 
901     res = MsiSummaryInfoSetPropertyA(suminfo,9, VT_LPSTR, 0,NULL,
902                     "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}");
903     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
904 
905     res = MsiSummaryInfoSetPropertyA(suminfo, 14, VT_I4, 100, NULL, NULL);
906     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
907 
908     res = MsiSummaryInfoSetPropertyA(suminfo, 15, VT_I4, 0, NULL, NULL);
909     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
910 
911     res = MsiSummaryInfoPersist(suminfo);
912     ok( res == ERROR_SUCCESS , "Failed to make summary info persist\n" );
913 
914     res = MsiCloseHandle( suminfo);
915     ok( res == ERROR_SUCCESS , "Failed to close suminfo\n" );
916 
917     return res;
918 }
919 
920 
921 static MSIHANDLE create_package_db(void)
922 {
923     MSIHANDLE hdb = 0;
924     UINT res;
925 
926     DeleteFileA(msifile);
927 
928     /* create an empty database */
929     res = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb );
930     ok( res == ERROR_SUCCESS , "Failed to create database %u\n", res );
931     if( res != ERROR_SUCCESS )
932         return hdb;
933 
934     res = MsiDatabaseCommit( hdb );
935     ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
936 
937     res = set_summary_info(hdb);
938     ok( res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", res);
939 
940     res = run_query( hdb,
941             "CREATE TABLE `Directory` ( "
942             "`Directory` CHAR(255) NOT NULL, "
943             "`Directory_Parent` CHAR(255), "
944             "`DefaultDir` CHAR(255) NOT NULL "
945             "PRIMARY KEY `Directory`)" );
946     ok( res == ERROR_SUCCESS , "Failed to create directory table\n" );
947 
948     return hdb;
949 }
950 
951 static UINT package_from_db(MSIHANDLE hdb, MSIHANDLE *handle)
952 {
953     UINT res;
954     CHAR szPackage[12];
955     MSIHANDLE hPackage;
956 
957     sprintf(szPackage, "#%lu", hdb);
958     res = MsiOpenPackageA(szPackage, &hPackage);
959     if (res != ERROR_SUCCESS)
960     {
961         MsiCloseHandle(hdb);
962         return res;
963     }
964 
965     res = MsiCloseHandle(hdb);
966     if (res != ERROR_SUCCESS)
967     {
968         MsiCloseHandle(hPackage);
969         return res;
970     }
971 
972     *handle = hPackage;
973     return ERROR_SUCCESS;
974 }
975 
976 static void create_file_data(LPCSTR name, LPCSTR data)
977 {
978     HANDLE file;
979     DWORD written;
980 
981     file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
982     ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
983     if (file == INVALID_HANDLE_VALUE)
984         return;
985 
986     WriteFile(file, data, strlen(data), &written, NULL);
987     WriteFile(file, "\n", strlen("\n"), &written, NULL);
988 
989     CloseHandle(file);
990 }
991 
992 static void create_test_file(const CHAR *name)
993 {
994     create_file_data(name, name);
995 }
996 
997 typedef struct _tagVS_VERSIONINFO
998 {
999     WORD wLength;
1000     WORD wValueLength;
1001     WORD wType;
1002     WCHAR szKey[1];
1003     WORD wPadding1[1];
1004     VS_FIXEDFILEINFO Value;
1005     WORD wPadding2[1];
1006     WORD wChildren[1];
1007 } VS_VERSIONINFO;
1008 
1009 #define roundoffs(a, b, r) (((BYTE *)(b) - (BYTE *)(a) + ((r) - 1)) & ~((r) - 1))
1010 #define roundpos(a, b, r) (((BYTE *)(a)) + roundoffs(a, b, r))
1011 
1012 static BOOL create_file_with_version(const CHAR *name, LONG ms, LONG ls)
1013 {
1014     VS_VERSIONINFO *pVerInfo;
1015     VS_FIXEDFILEINFO *pFixedInfo;
1016     LPBYTE buffer, ofs;
1017     CHAR path[MAX_PATH];
1018     DWORD handle, size;
1019     HANDLE resource;
1020     BOOL ret = FALSE;
1021 
1022     GetSystemDirectoryA(path, MAX_PATH);
1023     /* Some dlls can't be updated on Vista/W2K8 */
1024     lstrcatA(path, "\\version.dll");
1025 
1026     CopyFileA(path, name, FALSE);
1027 
1028     size = GetFileVersionInfoSizeA(path, &handle);
1029     buffer = malloc(size);
1030 
1031     GetFileVersionInfoA(path, 0, size, buffer);
1032 
1033     pVerInfo = (VS_VERSIONINFO *)buffer;
1034     ofs = (BYTE *)&pVerInfo->szKey[lstrlenW(pVerInfo->szKey) + 1];
1035     pFixedInfo = (VS_FIXEDFILEINFO *)roundpos(pVerInfo, ofs, 4);
1036 
1037     pFixedInfo->dwFileVersionMS = ms;
1038     pFixedInfo->dwFileVersionLS = ls;
1039     pFixedInfo->dwProductVersionMS = ms;
1040     pFixedInfo->dwProductVersionLS = ls;
1041 
1042     resource = BeginUpdateResourceA(name, FALSE);
1043     if (!resource)
1044         goto done;
1045 
1046     if (!UpdateResourceA(resource, (LPCSTR)RT_VERSION, (LPCSTR)MAKEINTRESOURCE(VS_VERSION_INFO),
1047                          MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), buffer, size))
1048         goto done;
1049 
1050     if (!EndUpdateResourceA(resource, FALSE))
1051         goto done;
1052 
1053     ret = TRUE;
1054 
1055 done:
1056     free(buffer);
1057     return ret;
1058 }
1059 
1060 static BOOL notify_system_change(DWORD event_type, STATEMGRSTATUS *status)
1061 {
1062     RESTOREPOINTINFOA spec;
1063 
1064     spec.dwEventType = event_type;
1065     spec.dwRestorePtType = APPLICATION_INSTALL;
1066     spec.llSequenceNumber = status->llSequenceNumber;
1067     lstrcpyA(spec.szDescription, "msitest restore point");
1068 
1069     return pSRSetRestorePointA(&spec, status);
1070 }
1071 
1072 static void remove_restore_point(DWORD seq_number)
1073 {
1074     DWORD res;
1075 
1076     res = pSRRemoveRestorePoint(seq_number);
1077     if (res != ERROR_SUCCESS)
1078         trace("Failed to remove the restore point: %#lx\n", res);
1079 }
1080 
1081 static BOOL is_root(const char *path)
1082 {
1083     return (isalpha(path[0]) && path[1] == ':' && path[2] == '\\' && !path[3]);
1084 }
1085 
1086 static void test_createpackage(void)
1087 {
1088     MSIHANDLE hPackage = 0;
1089     UINT res;
1090 
1091     res = package_from_db(create_package_db(), &hPackage);
1092     if (res == ERROR_INSTALL_PACKAGE_REJECTED)
1093     {
1094         skip("Not enough rights to perform tests\n");
1095         DeleteFileA(msifile);
1096         return;
1097     }
1098     ok( res == ERROR_SUCCESS, " Failed to create package %u\n", res );
1099 
1100     res = MsiCloseHandle( hPackage);
1101     ok( res == ERROR_SUCCESS , "Failed to close package\n" );
1102     DeleteFileA(msifile);
1103 }
1104 
1105 static void test_doaction( void )
1106 {
1107     MSIHANDLE hpkg;
1108     UINT r;
1109 
1110     r = MsiDoActionA( -1, NULL );
1111     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1112 
1113     r = package_from_db(create_package_db(), &hpkg);
1114     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1115     {
1116         skip("Not enough rights to perform tests\n");
1117         DeleteFileA(msifile);
1118         return;
1119     }
1120     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1121 
1122     r = MsiDoActionA(hpkg, NULL);
1123     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1124 
1125     r = MsiDoActionA(0, "boo");
1126     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1127 
1128     r = MsiDoActionA(hpkg, "boo");
1129     ok( r == ERROR_FUNCTION_NOT_CALLED, "wrong return val\n");
1130 
1131     MsiCloseHandle( hpkg );
1132     DeleteFileA(msifile);
1133 }
1134 
1135 static void test_gettargetpath_bad(void)
1136 {
1137     char buffer[0x80];
1138     WCHAR bufferW[0x80];
1139     MSIHANDLE hpkg;
1140     DWORD sz;
1141     UINT r;
1142 
1143     r = package_from_db(create_package_db(), &hpkg);
1144     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1145     {
1146         skip("Not enough rights to perform tests\n");
1147         DeleteFileA(msifile);
1148         return;
1149     }
1150     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1151 
1152     r = MsiGetTargetPathA( 0, NULL, NULL, NULL );
1153     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1154 
1155     r = MsiGetTargetPathA( 0, NULL, NULL, &sz );
1156     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1157 
1158     r = MsiGetTargetPathA( 0, "boo", NULL, NULL );
1159     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1160 
1161     r = MsiGetTargetPathA( 0, "boo", NULL, NULL );
1162     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1163 
1164     r = MsiGetTargetPathA( hpkg, "boo", NULL, NULL );
1165     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1166 
1167     r = MsiGetTargetPathA( hpkg, "boo", buffer, NULL );
1168     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1169 
1170     sz = 0;
1171     r = MsiGetTargetPathA( hpkg, "", buffer, &sz );
1172     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1173 
1174     r = MsiGetTargetPathW( 0, NULL, NULL, NULL );
1175     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1176 
1177     r = MsiGetTargetPathW( 0, NULL, NULL, &sz );
1178     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1179 
1180     r = MsiGetTargetPathW( 0, L"boo", NULL, NULL );
1181     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1182 
1183     r = MsiGetTargetPathW( 0, L"boo", NULL, NULL );
1184     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1185 
1186     r = MsiGetTargetPathW( hpkg, L"boo", NULL, NULL );
1187     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1188 
1189     r = MsiGetTargetPathW( hpkg, L"boo", bufferW, NULL );
1190     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1191 
1192     sz = 0;
1193     r = MsiGetTargetPathW( hpkg, L"", bufferW, &sz );
1194     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1195 
1196     MsiCloseHandle( hpkg );
1197     DeleteFileA(msifile);
1198 }
1199 
1200 static void query_file_path(MSIHANDLE hpkg, LPCSTR file, LPSTR buff)
1201 {
1202     UINT r;
1203     DWORD size;
1204     MSIHANDLE rec;
1205 
1206     rec = MsiCreateRecord( 1 );
1207     ok(rec, "MsiCreate record failed\n");
1208 
1209     r = MsiRecordSetStringA( rec, 0, file );
1210     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
1211 
1212     size = MAX_PATH;
1213     r = MsiFormatRecordA( hpkg, rec, buff, &size );
1214     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
1215 
1216     MsiCloseHandle( rec );
1217 }
1218 
1219 static void test_settargetpath(void)
1220 {
1221     char tempdir[MAX_PATH+8], buffer[MAX_PATH], file[MAX_PATH + 20];
1222     DWORD sz;
1223     MSIHANDLE hpkg;
1224     UINT r;
1225     MSIHANDLE hdb;
1226 
1227     hdb = create_package_db();
1228     ok ( hdb, "failed to create package database\n" );
1229 
1230     add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'" );
1231 
1232     create_component_table( hdb );
1233     add_component_entry( hdb, "'RootComp', '{83e2694d-0864-4124-9323-6d37630912a1}', 'TARGETDIR', 8, '', 'RootFile'" );
1234     add_component_entry( hdb, "'TestComp', '{A3FB59C8-C293-4F7E-B8C5-F0E1D8EEE4E5}', 'TestDir', 0, '', 'TestFile'" );
1235 
1236     create_feature_table( hdb );
1237     add_feature_entry( hdb, "'TestFeature', '', '', '', 0, 1, '', 0" );
1238 
1239     create_feature_components_table( hdb );
1240     add_feature_components_entry( hdb, "'TestFeature', 'RootComp'" );
1241     add_feature_components_entry( hdb, "'TestFeature', 'TestComp'" );
1242 
1243     add_directory_entry( hdb, "'TestParent', 'TARGETDIR', 'TestParent'" );
1244     add_directory_entry( hdb, "'TestDir', 'TestParent', 'TestDir'" );
1245 
1246     create_file_table( hdb );
1247     add_file_entry( hdb, "'RootFile', 'RootComp', 'rootfile.txt', 0, '', '1033', 8192, 1" );
1248     add_file_entry( hdb, "'TestFile', 'TestComp', 'testfile.txt', 0, '', '1033', 8192, 1" );
1249 
1250     r = package_from_db( hdb, &hpkg );
1251     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1252     {
1253         skip("Not enough rights to perform tests\n");
1254         DeleteFileA(msifile);
1255         return;
1256     }
1257     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1258 
1259     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1260 
1261     r = MsiDoActionA( hpkg, "CostInitialize");
1262     ok( r == ERROR_SUCCESS, "cost init failed\n");
1263 
1264     r = MsiDoActionA( hpkg, "FileCost");
1265     ok( r == ERROR_SUCCESS, "file cost failed\n");
1266 
1267     r = MsiDoActionA( hpkg, "CostFinalize");
1268     ok( r == ERROR_SUCCESS, "cost finalize failed\n");
1269 
1270     buffer[0] = 0;
1271     sz = sizeof(buffer);
1272     r = MsiGetPropertyA( hpkg, "OutOfNoRbDiskSpace", buffer, &sz );
1273     ok( r == ERROR_SUCCESS, "MsiGetProperty returned %u\n", r );
1274     trace( "OutOfNoRbDiskSpace = \"%s\"\n", buffer );
1275 
1276     r = MsiSetTargetPathA( 0, NULL, NULL );
1277     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1278 
1279     r = MsiSetTargetPathA( 0, "boo", "C:\\bogusx" );
1280     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1281 
1282     r = MsiSetTargetPathA( hpkg, "boo", NULL );
1283     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1284 
1285     r = MsiSetTargetPathA( hpkg, "boo", "c:\\bogusx" );
1286     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1287 
1288     sz = sizeof tempdir - 1;
1289     r = MsiGetTargetPathA( hpkg, "TARGETDIR", tempdir, &sz );
1290     sprintf( file, "%srootfile.txt", tempdir );
1291     buffer[0] = 0;
1292     query_file_path( hpkg, "[#RootFile]", buffer );
1293     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1294     ok( !lstrcmpA(buffer, file), "Expected %s, got %s\n", file, buffer );
1295 
1296     GetTempFileNameA( tempdir, "_wt", 0, buffer );
1297     sprintf( tempdir, "%s\\subdir", buffer );
1298 
1299     r = MsiSetTargetPathA( hpkg, "TARGETDIR", buffer );
1300     ok( r == ERROR_SUCCESS || r == ERROR_DIRECTORY,
1301         "MsiSetTargetPath on file returned %d\n", r );
1302 
1303     r = MsiSetTargetPathA( hpkg, "TARGETDIR", tempdir );
1304     ok( r == ERROR_SUCCESS || r == ERROR_DIRECTORY,
1305         "MsiSetTargetPath on 'subdir' of file returned %d\n", r );
1306 
1307     DeleteFileA( buffer );
1308 
1309     r = MsiSetTargetPathA( hpkg, "TARGETDIR", buffer );
1310     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1311 
1312     r = GetFileAttributesA( buffer );
1313     ok ( r == INVALID_FILE_ATTRIBUTES, "file/directory exists after MsiSetTargetPath. Attributes: %08X\n", r );
1314 
1315     r = MsiSetTargetPathA( hpkg, "TARGETDIR", tempdir );
1316     ok( r == ERROR_SUCCESS, "MsiSetTargetPath on subsubdir returned %d\n", r );
1317 
1318     buffer[0] = 0;
1319     sz = sizeof buffer - 1;
1320     lstrcatA( tempdir, "\\" );
1321     r = MsiGetTargetPathA( hpkg, "TARGETDIR", buffer, &sz );
1322     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1323     ok( !lstrcmpA(buffer, tempdir), "Expected %s, got %s\n", tempdir, buffer);
1324 
1325     sprintf( file, "%srootfile.txt", tempdir );
1326     query_file_path( hpkg, "[#RootFile]", buffer );
1327     ok( !lstrcmpA(buffer, file), "Expected %s, got %s\n", file, buffer);
1328 
1329     buffer[0] = 0;
1330     sz = sizeof(buffer);
1331     r = MsiGetPropertyA( hpkg, "TestParent", buffer, &sz );
1332     ok( r == ERROR_SUCCESS, "MsiGetProperty returned %u\n", r );
1333     lstrcatA( tempdir, "TestParent\\" );
1334     ok( !lstrcmpiA(buffer, tempdir), "Expected \"%s\", got \"%s\"\n", tempdir, buffer );
1335 
1336     r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\one\\two" );
1337     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1338 
1339     buffer[0] = 0;
1340     sz = sizeof(buffer);
1341     r = MsiGetPropertyA( hpkg, "TestParent", buffer, &sz );
1342     ok( r == ERROR_SUCCESS, "MsiGetProperty returned %u\n", r );
1343     ok( lstrcmpiA(buffer, "C:\\one\\two\\TestDir\\"),
1344         "Expected \"C:\\one\\two\\TestDir\\\", got \"%s\"\n", buffer );
1345 
1346     buffer[0] = 0;
1347     query_file_path( hpkg, "[#TestFile]", buffer );
1348     ok( !lstrcmpiA(buffer, "C:\\one\\two\\TestDir\\testfile.txt"),
1349         "Expected C:\\one\\two\\TestDir\\testfile.txt, got %s\n", buffer );
1350 
1351     buffer[0] = 0;
1352     sz = sizeof buffer - 1;
1353     r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1354     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1355     ok( !lstrcmpiA(buffer, "C:\\one\\two\\"), "Expected C:\\one\\two\\, got %s\n", buffer);
1356 
1357     r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\one\\two\\three" );
1358     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1359 
1360     buffer[0] = 0;
1361     sz = sizeof buffer - 1;
1362     r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1363     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1364     ok( !lstrcmpiA(buffer, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", buffer);
1365 
1366     r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\\\one\\\\two  " );
1367     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1368 
1369     buffer[0] = 0;
1370     sz = sizeof buffer - 1;
1371     r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1372     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1373     ok( !lstrcmpiA(buffer, "C:\\one\\two\\"), "Expected \"C:\\one\\two\\\", got %s\n", buffer);
1374 
1375     r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\\\ Program Files \\\\ " );
1376     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1377 
1378     buffer[0] = 0;
1379     sz = sizeof buffer - 1;
1380     r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1381     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1382     ok( !lstrcmpiA(buffer, "C:\\Program Files\\"), "Expected \"C:\\Program Files\\\", got %s\n", buffer);
1383 
1384     MsiCloseHandle( hpkg );
1385 }
1386 
1387 static void test_condition(void)
1388 {
1389     MSICONDITION r;
1390     MSIHANDLE hpkg;
1391 
1392     r = package_from_db(create_package_db(), &hpkg);
1393     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1394     {
1395         skip("Not enough rights to perform tests\n");
1396         DeleteFileA(msifile);
1397         return;
1398     }
1399     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1400 
1401     r = MsiEvaluateConditionA(0, NULL);
1402     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1403 
1404     r = MsiEvaluateConditionA(hpkg, NULL);
1405     ok( r == MSICONDITION_NONE, "wrong return val\n");
1406 
1407     r = MsiEvaluateConditionA(hpkg, "");
1408     ok( r == MSICONDITION_NONE, "wrong return val\n");
1409 
1410     r = MsiEvaluateConditionA(hpkg, "1");
1411     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1412 
1413     r = MsiEvaluateConditionA(hpkg, "0");
1414     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1415 
1416     r = MsiEvaluateConditionA(hpkg, "-1");
1417     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1418 
1419     r = MsiEvaluateConditionA(hpkg, "0 = 0");
1420     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1421 
1422     r = MsiEvaluateConditionA(hpkg, "0 <> 0");
1423     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1424 
1425     r = MsiEvaluateConditionA(hpkg, "0 = 1");
1426     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1427 
1428     r = MsiEvaluateConditionA(hpkg, "0 > 1");
1429     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1430 
1431     r = MsiEvaluateConditionA(hpkg, "0 ~> 1");
1432     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1433 
1434     r = MsiEvaluateConditionA(hpkg, "1 > 1");
1435     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1436 
1437     r = MsiEvaluateConditionA(hpkg, "1 ~> 1");
1438     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1439 
1440     r = MsiEvaluateConditionA(hpkg, "0 >= 1");
1441     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1442 
1443     r = MsiEvaluateConditionA(hpkg, "0 ~>= 1");
1444     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1445 
1446     r = MsiEvaluateConditionA(hpkg, "1 >= 1");
1447     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1448 
1449     r = MsiEvaluateConditionA(hpkg, "1 ~>= 1");
1450     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1451 
1452     r = MsiEvaluateConditionA(hpkg, "0 < 1");
1453     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1454 
1455     r = MsiEvaluateConditionA(hpkg, "0 ~< 1");
1456     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1457 
1458     r = MsiEvaluateConditionA(hpkg, "1 < 1");
1459     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1460 
1461     r = MsiEvaluateConditionA(hpkg, "1 ~< 1");
1462     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1463 
1464     r = MsiEvaluateConditionA(hpkg, "0 <= 1");
1465     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1466 
1467     r = MsiEvaluateConditionA(hpkg, "0 ~<= 1");
1468     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1469 
1470     r = MsiEvaluateConditionA(hpkg, "1 <= 1");
1471     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1472 
1473     r = MsiEvaluateConditionA(hpkg, "1 ~<= 1");
1474     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1475 
1476     r = MsiEvaluateConditionA(hpkg, "0 >=");
1477     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1478 
1479     r = MsiEvaluateConditionA(hpkg, " ");
1480     ok( r == MSICONDITION_NONE, "wrong return val\n");
1481 
1482     r = MsiEvaluateConditionA(hpkg, "LicView <> \"1\"");
1483     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1484 
1485     r = MsiEvaluateConditionA(hpkg, "LicView <> \"0\"");
1486     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1487 
1488     r = MsiEvaluateConditionA(hpkg, "LicView <> LicView");
1489     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1490 
1491     r = MsiEvaluateConditionA(hpkg, "not 0");
1492     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1493 
1494     r = MsiEvaluateConditionA(hpkg, "not LicView");
1495     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1496 
1497     r = MsiEvaluateConditionA(hpkg, "\"Testing\" ~<< \"Testing\"");
1498     ok (r == MSICONDITION_TRUE, "wrong return val\n");
1499 
1500     r = MsiEvaluateConditionA(hpkg, "LicView ~<< \"Testing\"");
1501     ok (r == MSICONDITION_FALSE, "wrong return val\n");
1502 
1503     r = MsiEvaluateConditionA(hpkg, "Not LicView ~<< \"Testing\"");
1504     ok (r == MSICONDITION_TRUE, "wrong return val\n");
1505 
1506     r = MsiEvaluateConditionA(hpkg, "not \"A\"");
1507     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1508 
1509     r = MsiEvaluateConditionA(hpkg, "~not \"A\"");
1510     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1511 
1512     r = MsiEvaluateConditionA(hpkg, "\"0\"");
1513     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1514 
1515     r = MsiEvaluateConditionA(hpkg, "1 and 2");
1516     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1517 
1518     r = MsiEvaluateConditionA(hpkg, "not 0 and 3");
1519     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1520 
1521     r = MsiEvaluateConditionA(hpkg, "not 0 and 0");
1522     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1523 
1524     r = MsiEvaluateConditionA(hpkg, "not 0 or 1");
1525     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1526 
1527     r = MsiEvaluateConditionA(hpkg, "(0)");
1528     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1529 
1530     r = MsiEvaluateConditionA(hpkg, "(((((1))))))");
1531     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1532 
1533     r = MsiEvaluateConditionA(hpkg, "(((((1)))))");
1534     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1535 
1536     r = MsiEvaluateConditionA(hpkg, " \"A\" < \"B\" ");
1537     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1538 
1539     r = MsiEvaluateConditionA(hpkg, " \"A\" > \"B\" ");
1540     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1541 
1542     r = MsiEvaluateConditionA(hpkg, " \"1\" > \"12\" ");
1543     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1544 
1545     r = MsiEvaluateConditionA(hpkg, " \"100\" < \"21\" ");
1546     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1547 
1548     r = MsiEvaluateConditionA(hpkg, "0 < > 0");
1549     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1550 
1551     r = MsiEvaluateConditionA(hpkg, "(1<<1) == 2");
1552     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1553 
1554     r = MsiEvaluateConditionA(hpkg, " \"A\" = \"a\" ");
1555     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1556 
1557     r = MsiEvaluateConditionA(hpkg, " \"A\" ~ = \"a\" ");
1558     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1559 
1560     r = MsiEvaluateConditionA(hpkg, " \"A\" ~= \"a\" ");
1561     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1562 
1563     r = MsiEvaluateConditionA(hpkg, " \"A\" ~= 1 ");
1564     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1565 
1566     r = MsiEvaluateConditionA(hpkg, " \"A\" = 1 ");
1567     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1568 
1569     r = MsiEvaluateConditionA(hpkg, " 1 ~= 1 ");
1570     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1571 
1572     r = MsiEvaluateConditionA(hpkg, " 1 ~= \"1\" ");
1573     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1574 
1575     r = MsiEvaluateConditionA(hpkg, " 1 = \"1\" ");
1576     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1577 
1578     r = MsiEvaluateConditionA(hpkg, " 0 = \"1\" ");
1579     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1580 
1581     r = MsiEvaluateConditionA(hpkg, " 0 < \"100\" ");
1582     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1583 
1584     r = MsiEvaluateConditionA(hpkg, " 100 > \"0\" ");
1585     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1586 
1587     r = MsiEvaluateConditionA(hpkg, "1 XOR 1");
1588     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1589 
1590     r = MsiEvaluateConditionA(hpkg, "1 IMP 1");
1591     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1592 
1593     r = MsiEvaluateConditionA(hpkg, "1 IMP 0");
1594     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1595 
1596     r = MsiEvaluateConditionA(hpkg, "0 IMP 0");
1597     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1598 
1599     r = MsiEvaluateConditionA(hpkg, "0 EQV 0");
1600     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1601 
1602     r = MsiEvaluateConditionA(hpkg, "0 EQV 1");
1603     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1604 
1605     r = MsiEvaluateConditionA(hpkg, "1 IMP 1 OR 0");
1606     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1607 
1608     r = MsiEvaluateConditionA(hpkg, "1 IMPL 1");
1609     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1610 
1611     r = MsiEvaluateConditionA(hpkg, "\"ASFD\" >< \"S\" ");
1612     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1613 
1614     r = MsiEvaluateConditionA(hpkg, "\"ASFD\" ~>< \"s\" ");
1615     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1616 
1617     r = MsiEvaluateConditionA(hpkg, "\"ASFD\" ~>< \"\" ");
1618     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1619 
1620     r = MsiEvaluateConditionA(hpkg, "\"ASFD\" ~>< \"sss\" ");
1621     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1622 
1623     MsiSetPropertyA(hpkg, "mm", "5" );
1624 
1625     r = MsiEvaluateConditionA(hpkg, "mm = 5");
1626     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1627 
1628     r = MsiEvaluateConditionA(hpkg, "mm < 6");
1629     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1630 
1631     r = MsiEvaluateConditionA(hpkg, "mm <= 5");
1632     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1633 
1634     r = MsiEvaluateConditionA(hpkg, "mm > 4");
1635     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1636 
1637     r = MsiEvaluateConditionA(hpkg, "mm < 12");
1638     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1639 
1640     r = MsiEvaluateConditionA(hpkg, "mm = \"5\"");
1641     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1642 
1643     r = MsiEvaluateConditionA(hpkg, "0 = \"\"");
1644     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1645 
1646     r = MsiEvaluateConditionA(hpkg, "0 AND \"\"");
1647     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1648 
1649     r = MsiEvaluateConditionA(hpkg, "1 AND \"\"");
1650     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1651 
1652     r = MsiEvaluateConditionA(hpkg, "1 AND \"1\"");
1653     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1654 
1655     r = MsiEvaluateConditionA(hpkg, "3 >< 1");
1656     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1657 
1658     r = MsiEvaluateConditionA(hpkg, "3 >< 4");
1659     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1660 
1661     r = MsiEvaluateConditionA(hpkg, "NOT 0 AND 0");
1662     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1663 
1664     r = MsiEvaluateConditionA(hpkg, "NOT 0 AND 1");
1665     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1666 
1667     r = MsiEvaluateConditionA(hpkg, "NOT 1 OR 0");
1668     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1669 
1670     r = MsiEvaluateConditionA(hpkg, "0 AND 1 OR 1");
1671     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1672 
1673     r = MsiEvaluateConditionA(hpkg, "0 AND 0 OR 1");
1674     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1675 
1676     r = MsiEvaluateConditionA(hpkg, "NOT 0 AND 1 OR 0");
1677     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1678 
1679     r = MsiEvaluateConditionA(hpkg, "_1 = _1");
1680     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1681 
1682     r = MsiEvaluateConditionA(hpkg, "( 1 AND 1 ) = 2");
1683     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1684 
1685     r = MsiEvaluateConditionA(hpkg, "NOT ( 1 AND 1 )");
1686     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1687 
1688     r = MsiEvaluateConditionA(hpkg, "NOT A AND (BBBBBBBBBB=2 OR CCC=1) AND Ddddddddd");
1689     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1690 
1691     r = MsiEvaluateConditionA(hpkg, "Installed<>\"\"");
1692     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1693 
1694     r = MsiEvaluateConditionA(hpkg, "NOT 1 AND 0");
1695     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1696 
1697     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1698     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1699 
1700     r = MsiEvaluateConditionA(hpkg, "bandalmael<>0");
1701     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1702 
1703     r = MsiEvaluateConditionA(hpkg, "bandalmael<0");
1704     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1705 
1706     r = MsiEvaluateConditionA(hpkg, "bandalmael>0");
1707     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1708 
1709     r = MsiEvaluateConditionA(hpkg, "bandalmael>=0");
1710     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1711 
1712     r = MsiEvaluateConditionA(hpkg, "bandalmael<=0");
1713     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1714 
1715     r = MsiEvaluateConditionA(hpkg, "bandalmael~<>0");
1716     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1717 
1718     MsiSetPropertyA(hpkg, "bandalmael", "0" );
1719     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1720     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1721 
1722     MsiSetPropertyA(hpkg, "bandalmael", "" );
1723     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1724     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1725 
1726     MsiSetPropertyA(hpkg, "bandalmael", "asdf" );
1727     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1728     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1729 
1730     MsiSetPropertyA(hpkg, "bandalmael", "0asdf" );
1731     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1732     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1733 
1734     MsiSetPropertyA(hpkg, "bandalmael", "0 " );
1735     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1736     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1737 
1738     MsiSetPropertyA(hpkg, "bandalmael", "-0" );
1739     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1740     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1741 
1742     MsiSetPropertyA(hpkg, "bandalmael", "0000000000000" );
1743     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1744     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1745 
1746     MsiSetPropertyA(hpkg, "bandalmael", "--0" );
1747     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1748     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1749 
1750     MsiSetPropertyA(hpkg, "bandalmael", "0x00" );
1751     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1752     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1753 
1754     MsiSetPropertyA(hpkg, "bandalmael", "-" );
1755     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1756     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1757 
1758     MsiSetPropertyA(hpkg, "bandalmael", "+0" );
1759     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1760     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1761 
1762     MsiSetPropertyA(hpkg, "bandalmael", "0.0" );
1763     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1764     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1765     r = MsiEvaluateConditionA(hpkg, "bandalmael<>0");
1766     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1767 
1768     MsiSetPropertyA(hpkg, "one", "hi");
1769     MsiSetPropertyA(hpkg, "two", "hithere");
1770     r = MsiEvaluateConditionA(hpkg, "one >< two");
1771     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1772 
1773     MsiSetPropertyA(hpkg, "one", "hithere");
1774     MsiSetPropertyA(hpkg, "two", "hi");
1775     r = MsiEvaluateConditionA(hpkg, "one >< two");
1776     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1777 
1778     MsiSetPropertyA(hpkg, "one", "hello");
1779     MsiSetPropertyA(hpkg, "two", "hi");
1780     r = MsiEvaluateConditionA(hpkg, "one >< two");
1781     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1782 
1783     MsiSetPropertyA(hpkg, "one", "hellohithere");
1784     MsiSetPropertyA(hpkg, "two", "hi");
1785     r = MsiEvaluateConditionA(hpkg, "one >< two");
1786     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1787 
1788     MsiSetPropertyA(hpkg, "one", "");
1789     MsiSetPropertyA(hpkg, "two", "hi");
1790     r = MsiEvaluateConditionA(hpkg, "one >< two");
1791     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1792 
1793     MsiSetPropertyA(hpkg, "one", "hi");
1794     MsiSetPropertyA(hpkg, "two", "");
1795     r = MsiEvaluateConditionA(hpkg, "one >< two");
1796     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1797 
1798     MsiSetPropertyA(hpkg, "one", "");
1799     MsiSetPropertyA(hpkg, "two", "");
1800     r = MsiEvaluateConditionA(hpkg, "one >< two");
1801     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1802 
1803     MsiSetPropertyA(hpkg, "one", "1234");
1804     MsiSetPropertyA(hpkg, "two", "1");
1805     r = MsiEvaluateConditionA(hpkg, "one >< two");
1806     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1807 
1808     MsiSetPropertyA(hpkg, "one", "one 1234");
1809     MsiSetPropertyA(hpkg, "two", "1");
1810     r = MsiEvaluateConditionA(hpkg, "one >< two");
1811     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1812 
1813     MsiSetPropertyA(hpkg, "one", "hithere");
1814     MsiSetPropertyA(hpkg, "two", "hi");
1815     r = MsiEvaluateConditionA(hpkg, "one << two");
1816     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1817 
1818     MsiSetPropertyA(hpkg, "one", "hi");
1819     MsiSetPropertyA(hpkg, "two", "hithere");
1820     r = MsiEvaluateConditionA(hpkg, "one << two");
1821     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1822 
1823     MsiSetPropertyA(hpkg, "one", "hi");
1824     MsiSetPropertyA(hpkg, "two", "hi");
1825     r = MsiEvaluateConditionA(hpkg, "one << two");
1826     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1827 
1828     MsiSetPropertyA(hpkg, "one", "abcdhithere");
1829     MsiSetPropertyA(hpkg, "two", "hi");
1830     r = MsiEvaluateConditionA(hpkg, "one << two");
1831     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1832 
1833     MsiSetPropertyA(hpkg, "one", "");
1834     MsiSetPropertyA(hpkg, "two", "hi");
1835     r = MsiEvaluateConditionA(hpkg, "one << two");
1836     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1837 
1838     MsiSetPropertyA(hpkg, "one", "hithere");
1839     MsiSetPropertyA(hpkg, "two", "");
1840     r = MsiEvaluateConditionA(hpkg, "one << two");
1841     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1842 
1843     MsiSetPropertyA(hpkg, "one", "");
1844     MsiSetPropertyA(hpkg, "two", "");
1845     r = MsiEvaluateConditionA(hpkg, "one << two");
1846     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1847 
1848     MsiSetPropertyA(hpkg, "one", "1234");
1849     MsiSetPropertyA(hpkg, "two", "1");
1850     r = MsiEvaluateConditionA(hpkg, "one << two");
1851     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1852 
1853     MsiSetPropertyA(hpkg, "one", "1234 one");
1854     MsiSetPropertyA(hpkg, "two", "1");
1855     r = MsiEvaluateConditionA(hpkg, "one << two");
1856     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1857 
1858     MsiSetPropertyA(hpkg, "one", "hithere");
1859     MsiSetPropertyA(hpkg, "two", "there");
1860     r = MsiEvaluateConditionA(hpkg, "one >> two");
1861     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1862 
1863     MsiSetPropertyA(hpkg, "one", "hithere");
1864     MsiSetPropertyA(hpkg, "two", "hi");
1865     r = MsiEvaluateConditionA(hpkg, "one >> two");
1866     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1867 
1868     MsiSetPropertyA(hpkg, "one", "there");
1869     MsiSetPropertyA(hpkg, "two", "hithere");
1870     r = MsiEvaluateConditionA(hpkg, "one >> two");
1871     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1872 
1873     MsiSetPropertyA(hpkg, "one", "there");
1874     MsiSetPropertyA(hpkg, "two", "there");
1875     r = MsiEvaluateConditionA(hpkg, "one >> two");
1876     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1877 
1878     MsiSetPropertyA(hpkg, "one", "abcdhithere");
1879     MsiSetPropertyA(hpkg, "two", "hi");
1880     r = MsiEvaluateConditionA(hpkg, "one >> two");
1881     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1882 
1883     MsiSetPropertyA(hpkg, "one", "");
1884     MsiSetPropertyA(hpkg, "two", "there");
1885     r = MsiEvaluateConditionA(hpkg, "one >> two");
1886     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1887 
1888     MsiSetPropertyA(hpkg, "one", "there");
1889     MsiSetPropertyA(hpkg, "two", "");
1890     r = MsiEvaluateConditionA(hpkg, "one >> two");
1891     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1892 
1893     MsiSetPropertyA(hpkg, "one", "");
1894     MsiSetPropertyA(hpkg, "two", "");
1895     r = MsiEvaluateConditionA(hpkg, "one >> two");
1896     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1897 
1898     MsiSetPropertyA(hpkg, "one", "1234");
1899     MsiSetPropertyA(hpkg, "two", "4");
1900     r = MsiEvaluateConditionA(hpkg, "one >> two");
1901     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1902 
1903     MsiSetPropertyA(hpkg, "one", "one 1234");
1904     MsiSetPropertyA(hpkg, "two", "4");
1905     r = MsiEvaluateConditionA(hpkg, "one >> two");
1906     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1907 
1908     MsiSetPropertyA(hpkg, "MsiNetAssemblySupport", NULL);  /* make sure it's empty */
1909 
1910     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322\"");
1911     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1912 
1913     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport > \"1.1.4322\"");
1914     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1915 
1916     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport >= \"1.1.4322\"");
1917     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1918 
1919     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport <= \"1.1.4322\"");
1920     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1921 
1922     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport <> \"1.1.4322\"");
1923     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1924 
1925     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport ~< \"1.1.4322\"");
1926     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1927 
1928     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"abcd\"");
1929     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1930 
1931     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a1.1.4322\"");
1932     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1933 
1934     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322a\"");
1935     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1936 
1937     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"0000001.1.4322\"");
1938     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1939 
1940     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322.1\"");
1941     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1942 
1943     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322.1.1\"");
1944     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1945 
1946     r = MsiEvaluateConditionA(hpkg, "\"2\" < \"1.1");
1947     ok( r == MSICONDITION_ERROR, "wrong return val (%d)\n", r);
1948 
1949     r = MsiEvaluateConditionA(hpkg, "\"2\" < \"1.1\"");
1950     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1951 
1952     r = MsiEvaluateConditionA(hpkg, "\"2\" < \"12.1\"");
1953     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1954 
1955     r = MsiEvaluateConditionA(hpkg, "\"02.1\" < \"2.11\"");
1956     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1957 
1958     r = MsiEvaluateConditionA(hpkg, "\"02.1.1\" < \"2.1\"");
1959     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1960 
1961     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1\"");
1962     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1963 
1964     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1\"");
1965     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1966 
1967     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"0\"");
1968     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1969 
1970     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"-1\"");
1971     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1972 
1973     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a\"");
1974     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1975 
1976     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"!\"");
1977     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1978 
1979     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"!\"");
1980     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1981 
1982     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"/\"");
1983     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1984 
1985     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \" \"");
1986     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1987 
1988     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"azAZ_\"");
1989     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1990 
1991     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a[a]\"");
1992     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1993 
1994     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a[a]a\"");
1995     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1996 
1997     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"[a]\"");
1998     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1999 
2000     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"[a]a\"");
2001     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2002 
2003     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"{a}\"");
2004     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2005 
2006     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"{a\"");
2007     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2008 
2009     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"[a\"");
2010     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2011 
2012     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a{\"");
2013     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2014 
2015     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a]\"");
2016     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2017 
2018     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"A\"");
2019     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2020 
2021     MsiSetPropertyA(hpkg, "MsiNetAssemblySupport", "1.1.4322");
2022     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322\"");
2023     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2024 
2025     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.14322\"");
2026     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2027 
2028     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.5\"");
2029     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2030 
2031     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1\"");
2032     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2033 
2034     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1\"");
2035     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2036 
2037     MsiSetPropertyA(hpkg, "one", "1");
2038     r = MsiEvaluateConditionA(hpkg, "one < \"1\"");
2039     ok( r == MSICONDITION_FALSE, "wrong return val\n");
2040 
2041     MsiSetPropertyA(hpkg, "X", "5.0");
2042 
2043     r = MsiEvaluateConditionA(hpkg, "X != \"\"");
2044     ok( r == MSICONDITION_ERROR, "wrong return val (%d)\n", r);
2045 
2046     r = MsiEvaluateConditionA(hpkg, "X =\"5.0\"");
2047     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2048 
2049     r = MsiEvaluateConditionA(hpkg, "X =\"5.1\"");
2050     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2051 
2052     r = MsiEvaluateConditionA(hpkg, "X =\"6.0\"");
2053     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2054 
2055     r = MsiEvaluateConditionA(hpkg, "X =\"5.0\" or X =\"5.1\" or X =\"6.0\"");
2056     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2057 
2058     r = MsiEvaluateConditionA(hpkg, "(X =\"5.0\" or X =\"5.1\" or X =\"6.0\")");
2059     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2060 
2061     r = MsiEvaluateConditionA(hpkg, "X !=\"\" and (X =\"5.0\" or X =\"5.1\" or X =\"6.0\")");
2062     ok( r == MSICONDITION_ERROR, "wrong return val (%d)\n", r);
2063 
2064     /* feature doesn't exist */
2065     r = MsiEvaluateConditionA(hpkg, "&nofeature");
2066     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2067     r = MsiEvaluateConditionA(hpkg, "&nofeature=\"\"");
2068     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2069     r = MsiEvaluateConditionA(hpkg, "&nofeature<>3");
2070     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2071     r = MsiEvaluateConditionA(hpkg, "\"\"<>3");
2072     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2073     r = MsiEvaluateConditionA(hpkg, "!nofeature=\"\"");
2074     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2075     r = MsiEvaluateConditionA(hpkg, "$nocomponent=\"\"");
2076     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2077     r = MsiEvaluateConditionA(hpkg, "?nocomponent=\"\"");
2078     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2079 
2080     MsiSetPropertyA(hpkg, "A", "2");
2081     MsiSetPropertyA(hpkg, "X", "50");
2082 
2083     r = MsiEvaluateConditionA(hpkg, "2 <= X");
2084     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2085 
2086     r = MsiEvaluateConditionA(hpkg, "A <= X");
2087     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2088 
2089     r = MsiEvaluateConditionA(hpkg, "A <= 50");
2090     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2091 
2092     MsiSetPropertyA(hpkg, "X", "50val");
2093 
2094     r = MsiEvaluateConditionA(hpkg, "2 <= X");
2095     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2096 
2097     r = MsiEvaluateConditionA(hpkg, "A <= X");
2098     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2099 
2100     MsiSetPropertyA(hpkg, "A", "7");
2101     MsiSetPropertyA(hpkg, "X", "50");
2102 
2103     r = MsiEvaluateConditionA(hpkg, "7 <= X");
2104     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2105 
2106     r = MsiEvaluateConditionA(hpkg, "A <= X");
2107     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2108 
2109     r = MsiEvaluateConditionA(hpkg, "A <= 50");
2110     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2111 
2112     MsiSetPropertyA(hpkg, "X", "50val");
2113 
2114     r = MsiEvaluateConditionA(hpkg, "2 <= X");
2115     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2116 
2117     r = MsiEvaluateConditionA(hpkg, "A <= X");
2118     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2119 
2120     r = MsiEvaluateConditionW(hpkg, L"\"a\x30a\"<\"\xe5\"");
2121     ok( r == MSICONDITION_TRUE || broken(r == MSICONDITION_FALSE),
2122         "wrong return val (%d)\n", r);
2123 
2124     r = MsiEvaluateConditionW(hpkg, L"\"a\x30a\">\"\xe5\"");
2125     ok( r == MSICONDITION_FALSE || broken(r == MSICONDITION_TRUE),
2126         "wrong return val (%d)\n", r);
2127 
2128     r = MsiEvaluateConditionW(hpkg, L"\"a\x30a\"<>\"\xe5\"");
2129     ok( r == MSICONDITION_TRUE || broken(r == MSICONDITION_FALSE),
2130         "wrong return val (%d)\n", r);
2131 
2132     r = MsiEvaluateConditionW(hpkg, L"\"a\x30a\"=\"\xe5\"");
2133     ok( r == MSICONDITION_FALSE || broken(r == MSICONDITION_TRUE),
2134         "wrong return val (%d)\n", r);
2135 
2136     MsiCloseHandle( hpkg );
2137     DeleteFileA(msifile);
2138 }
2139 
2140 static void check_prop(MSIHANDLE hpkg, const char *prop, const char *expect, int match_case)
2141 {
2142     char buffer[MAX_PATH] = "x";
2143     DWORD sz = sizeof(buffer);
2144     UINT r = MsiGetPropertyA(hpkg, prop, buffer, &sz);
2145     ok(!r, "'%s': got %u\n", prop, r);
2146     ok(sz == lstrlenA(buffer), "'%s': expected %u, got %lu\n", prop, lstrlenA(buffer), sz);
2147     if (match_case)
2148         ok(!strcmp(buffer, expect), "'%s': expected '%s', got '%s'\n", prop, expect, buffer);
2149     else
2150         ok(!_stricmp(buffer, expect), "'%s': expected '%s', got '%s'\n", prop, expect, buffer);
2151 }
2152 
2153 static void test_props(void)
2154 {
2155     MSIHANDLE hpkg, hdb;
2156     UINT r;
2157     DWORD sz;
2158     char buffer[0x100];
2159     WCHAR bufferW[10];
2160 
2161     hdb = create_package_db();
2162 
2163     create_property_table(hdb);
2164     add_property_entry(hdb, "'MetadataCompName', 'Photoshop.dll'");
2165 
2166     r = package_from_db( hdb, &hpkg );
2167     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2168     {
2169         skip("Not enough rights to perform tests\n");
2170         DeleteFileA(msifile);
2171         return;
2172     }
2173     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
2174 
2175     /* test invalid values */
2176     r = MsiGetPropertyA( 0, NULL, NULL, NULL );
2177     ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
2178 
2179     r = MsiGetPropertyA( hpkg, NULL, NULL, NULL );
2180     ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
2181 
2182     r = MsiGetPropertyA( hpkg, "boo", NULL, NULL );
2183     ok(!r, "got %u\n", r);
2184 
2185     r = MsiGetPropertyA( hpkg, "boo", buffer, NULL );
2186     ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
2187 
2188     /* test retrieving an empty/nonexistent property */
2189     sz = sizeof buffer;
2190     r = MsiGetPropertyA( hpkg, "boo", NULL, &sz );
2191     ok(!r, "got %u\n", r);
2192     ok(sz == 0, "got size %lu\n", sz);
2193 
2194     sz = 0;
2195     strcpy(buffer,"x");
2196     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2197     ok(r == ERROR_MORE_DATA, "got %u\n", r);
2198     ok(!strcmp(buffer,"x"), "got \"%s\"\n", buffer);
2199     ok(sz == 0, "got size %lu\n", sz);
2200 
2201     sz = 1;
2202     strcpy(buffer,"x");
2203     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2204     ok(!r, "got %u\n", r);
2205     ok(!buffer[0], "got \"%s\"\n", buffer);
2206     ok(sz == 0, "got size %lu\n", sz);
2207 
2208     /* set the property to something */
2209     r = MsiSetPropertyA( 0, NULL, NULL );
2210     ok(r == ERROR_INVALID_HANDLE, "got %u\n", r);
2211 
2212     r = MsiSetPropertyA( hpkg, NULL, NULL );
2213     ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
2214 
2215     r = MsiSetPropertyA( hpkg, "", NULL );
2216     ok(!r, "got %u\n", r);
2217 
2218     r = MsiSetPropertyA( hpkg, "", "asdf" );
2219     ok(r == ERROR_FUNCTION_FAILED, "got %u\n", r);
2220 
2221     r = MsiSetPropertyA( hpkg, "=", "asdf" );
2222     ok(!r, "got %u\n", r);
2223     check_prop(hpkg, "=", "asdf", 1);
2224 
2225     r = MsiSetPropertyA( hpkg, " ", "asdf" );
2226     ok(!r, "got %u\n", r);
2227     check_prop(hpkg, " ", "asdf", 1);
2228 
2229     r = MsiSetPropertyA( hpkg, "'", "asdf" );
2230     ok(!r, "got %u\n", r);
2231     check_prop(hpkg, "'", "asdf", 1);
2232 
2233     /* set empty values */
2234     r = MsiSetPropertyA( hpkg, "boo", NULL );
2235     ok(!r, "got %u\n", r);
2236     check_prop(hpkg, "boo", "", 1);
2237 
2238     r = MsiSetPropertyA( hpkg, "boo", "" );
2239     ok(!r, "got %u\n", r);
2240     check_prop(hpkg, "boo", "", 1);
2241 
2242     /* set a non-empty value */
2243     r = MsiSetPropertyA( hpkg, "boo", "xyz" );
2244     ok(!r, "got %u\n", r);
2245     check_prop(hpkg, "boo", "xyz", 1);
2246 
2247     r = MsiGetPropertyA(hpkg, "boo", NULL, NULL);
2248     ok(!r, "got %u\n", r);
2249 
2250     r = MsiGetPropertyA(hpkg, "boo", buffer, NULL);
2251     ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
2252 
2253     sz = 0;
2254     r = MsiGetPropertyA(hpkg, "boo", NULL, &sz);
2255     ok(!r, "got %u\n", r);
2256     ok(sz == 3, "got size %lu\n", sz);
2257 
2258     sz = 0;
2259     strcpy(buffer, "q");
2260     r = MsiGetPropertyA(hpkg, "boo", buffer, &sz);
2261     ok(r == ERROR_MORE_DATA, "got %u\n", r);
2262     ok(!strcmp(buffer, "q"), "got \"%s\"", buffer);
2263     ok(sz == 3, "got size %lu\n", sz);
2264 
2265     sz = 1;
2266     strcpy(buffer,"x");
2267     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2268     ok(r == ERROR_MORE_DATA, "got %u\n", r);
2269     ok(!buffer[0], "got \"%s\"\n", buffer);
2270     ok(sz == 3, "got size %lu\n", sz);
2271 
2272     sz = 3;
2273     strcpy(buffer,"x");
2274     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2275     ok(r == ERROR_MORE_DATA, "got %u\n", r);
2276     ok(!strcmp(buffer,"xy"), "got \"%s\"\n", buffer);
2277     ok(sz == 3, "got size %lu\n", sz);
2278 
2279     sz = 4;
2280     strcpy(buffer,"x");
2281     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2282     ok(!r, "got %u\n", r);
2283     ok(!strcmp(buffer,"xyz"), "got \"%s\"\n", buffer);
2284     ok(sz == 3, "got size %lu\n", sz);
2285 
2286     sz = 0;
2287     r = MsiGetPropertyW(hpkg, L"boo", NULL, &sz);
2288     ok(!r, "got %u\n", r);
2289     ok(sz == 3, "got size %lu\n", sz);
2290 
2291     sz = 0;
2292     lstrcpyW(bufferW, L"boo");
2293     r = MsiGetPropertyW(hpkg, L"boo", bufferW, &sz);
2294     ok(r == ERROR_MORE_DATA, "got %u\n", r);
2295     ok(!lstrcmpW(bufferW, L"boo"), "got %s\n", wine_dbgstr_w(bufferW));
2296     ok(sz == 3, "got size %lu\n", sz);
2297 
2298     sz = 1;
2299     lstrcpyW(bufferW, L"boo");
2300     r = MsiGetPropertyW(hpkg, L"boo", bufferW, &sz );
2301     ok(r == ERROR_MORE_DATA, "got %u\n", r);
2302     ok(!bufferW[0], "got %s\n", wine_dbgstr_w(bufferW));
2303     ok(sz == 3, "got size %lu\n", sz);
2304 
2305     sz = 3;
2306     lstrcpyW(bufferW, L"boo");
2307     r = MsiGetPropertyW(hpkg, L"boo", bufferW, &sz );
2308     ok(r == ERROR_MORE_DATA, "got %u\n", r);
2309     ok(!lstrcmpW(bufferW, L"xy"), "got %s\n", wine_dbgstr_w(bufferW));
2310     ok(sz == 3, "got size %lu\n", sz);
2311 
2312     sz = 4;
2313     lstrcpyW(bufferW, L"boo");
2314     r = MsiGetPropertyW(hpkg, L"boo", bufferW, &sz );
2315     ok(!r, "got %u\n", r);
2316     ok(!lstrcmpW(bufferW, L"xyz"), "got %s\n", wine_dbgstr_w(bufferW));
2317     ok(sz == 3, "got size %lu\n", sz);
2318 
2319     /* properties are case-sensitive */
2320     check_prop(hpkg, "BOO", "", 1);
2321 
2322     /* properties set in Property table should work */
2323     check_prop(hpkg, "MetadataCompName", "Photoshop.dll", 1);
2324 
2325     MsiCloseHandle( hpkg );
2326     DeleteFileA(msifile);
2327 }
2328 
2329 static BOOL find_prop_in_property(MSIHANDLE hdb, LPCSTR prop, LPCSTR val, int len)
2330 {
2331     MSIHANDLE hview, hrec;
2332     BOOL found = FALSE;
2333     CHAR buffer[MAX_PATH];
2334     DWORD sz;
2335     UINT r;
2336 
2337     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Property`", &hview);
2338     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
2339     r = MsiViewExecute(hview, 0);
2340     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
2341 
2342     if (len < 0) len = lstrlenA(val);
2343 
2344     while (r == ERROR_SUCCESS && !found)
2345     {
2346         r = MsiViewFetch(hview, &hrec);
2347         if (r != ERROR_SUCCESS) break;
2348 
2349         sz = MAX_PATH;
2350         r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
2351         if (r == ERROR_SUCCESS && !lstrcmpA(buffer, prop))
2352         {
2353             sz = MAX_PATH;
2354             r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
2355             if (r == ERROR_SUCCESS && !memcmp(buffer, val, len) && !buffer[len])
2356             {
2357                 ok(sz == len, "wrong size %lu\n", sz);
2358                 found = TRUE;
2359             }
2360         }
2361 
2362         MsiCloseHandle(hrec);
2363     }
2364     MsiViewClose(hview);
2365     MsiCloseHandle(hview);
2366     return found;
2367 }
2368 
2369 static void test_property_table(void)
2370 {
2371     const char *query;
2372     UINT r;
2373     MSIHANDLE hpkg, hdb, hrec;
2374     char buffer[MAX_PATH], package[10];
2375     DWORD sz;
2376     BOOL found;
2377 
2378     hdb = create_package_db();
2379     ok( hdb, "failed to create package\n");
2380 
2381     r = package_from_db(hdb, &hpkg);
2382     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2383     {
2384         skip("Not enough rights to perform tests\n");
2385         DeleteFileA(msifile);
2386         return;
2387     }
2388     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
2389 
2390     MsiCloseHandle(hdb);
2391 
2392     hdb = MsiGetActiveDatabase(hpkg);
2393 
2394     query = "CREATE TABLE `_Property` ( "
2395         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
2396     r = run_query(hdb, query);
2397     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2398 
2399     MsiCloseHandle(hdb);
2400     MsiCloseHandle(hpkg);
2401     DeleteFileA(msifile);
2402 
2403     hdb = create_package_db();
2404     ok( hdb, "failed to create package\n");
2405 
2406     query = "CREATE TABLE `_Property` ( "
2407         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
2408     r = run_query(hdb, query);
2409     ok(r == ERROR_SUCCESS, "failed to create table\n");
2410 
2411     query = "ALTER `_Property` ADD `foo` INTEGER";
2412     r = run_query(hdb, query);
2413     ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to add column\n");
2414 
2415     query = "ALTER TABLE `_Property` ADD `foo` INTEGER";
2416     r = run_query(hdb, query);
2417     ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to add column\n");
2418 
2419     query = "ALTER TABLE `_Property` ADD `extra` INTEGER";
2420     r = run_query(hdb, query);
2421     ok(r == ERROR_SUCCESS, "failed to add column\n");
2422 
2423     sprintf(package, "#%lu", hdb);
2424     r = MsiOpenPackageA(package, &hpkg);
2425     ok(r != ERROR_SUCCESS, "MsiOpenPackage succeeded\n");
2426     if (r == ERROR_SUCCESS)
2427         MsiCloseHandle(hpkg);
2428 
2429     r = MsiCloseHandle(hdb);
2430     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed %u\n", r);
2431 
2432     hdb = create_package_db();
2433     ok (hdb, "failed to create package database\n");
2434 
2435     create_property_table(hdb);
2436     add_property_entry(hdb, "'prop', 'val'");
2437 
2438     create_custom_action_table(hdb);
2439     add_custom_action_entry( hdb, "'EmbedNull', 51, 'prop2', '[~]np'" );
2440 
2441     r = package_from_db(hdb, &hpkg);
2442     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
2443 
2444     MsiCloseHandle(hdb);
2445 
2446     sz = MAX_PATH;
2447     r = MsiGetPropertyA(hpkg, "prop", buffer, &sz);
2448     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2449     ok(!lstrcmpA(buffer, "val"), "Expected val, got %s\n", buffer);
2450 
2451     hdb = MsiGetActiveDatabase(hpkg);
2452 
2453     found = find_prop_in_property(hdb, "prop", "val", -1);
2454     ok(found, "prop should be in the _Property table\n");
2455 
2456     add_property_entry(hdb, "'dantes', 'mercedes'");
2457 
2458     query = "SELECT * FROM `_Property` WHERE `Property` = 'dantes'";
2459     r = do_query(hdb, query, &hrec);
2460     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2461 
2462     found = find_prop_in_property(hdb, "dantes", "mercedes", -1);
2463     ok(found == FALSE, "dantes should not be in the _Property table\n");
2464 
2465     sz = MAX_PATH;
2466     lstrcpyA(buffer, "aaa");
2467     r = MsiGetPropertyA(hpkg, "dantes", buffer, &sz);
2468     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2469     ok(!buffer[0], "Expected empty string, got %s\n", buffer);
2470 
2471     r = MsiSetPropertyA(hpkg, "dantes", "mercedes");
2472     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2473 
2474     found = find_prop_in_property(hdb, "dantes", "mercedes", -1);
2475     ok(found == TRUE, "dantes should be in the _Property table\n");
2476 
2477     r = MsiDoActionA( hpkg, "EmbedNull" );
2478     ok( r == ERROR_SUCCESS, "EmbedNull failed: %d\n", r);
2479 
2480     sz = MAX_PATH;
2481     memset( buffer, 'a', sizeof(buffer) );
2482     r = MsiGetPropertyA( hpkg, "prop2", buffer, &sz );
2483     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2484     ok( !memcmp( buffer, "\0np", sizeof("\0np") ), "wrong value\n");
2485     ok( sz == sizeof("\0np") - 1, "got %lu\n", sz );
2486 
2487     found = find_prop_in_property(hdb, "prop2", "\0np", 3);
2488     ok(found == TRUE, "prop2 should be in the _Property table\n");
2489 
2490     MsiCloseHandle(hdb);
2491     MsiCloseHandle(hpkg);
2492     DeleteFileA(msifile);
2493 }
2494 
2495 static UINT try_query_param( MSIHANDLE hdb, LPCSTR szQuery, MSIHANDLE hrec )
2496 {
2497     MSIHANDLE htab = 0;
2498     UINT res;
2499 
2500     res = MsiDatabaseOpenViewA( hdb, szQuery, &htab );
2501     if( res == ERROR_SUCCESS )
2502     {
2503         UINT r;
2504 
2505         r = MsiViewExecute( htab, hrec );
2506         if( r != ERROR_SUCCESS )
2507         {
2508             res = r;
2509             fprintf(stderr,"MsiViewExecute failed %08x\n", res);
2510         }
2511 
2512         r = MsiViewClose( htab );
2513         if( r != ERROR_SUCCESS )
2514             res = r;
2515 
2516         r = MsiCloseHandle( htab );
2517         if( r != ERROR_SUCCESS )
2518             res = r;
2519     }
2520     return res;
2521 }
2522 
2523 static UINT try_query( MSIHANDLE hdb, LPCSTR szQuery )
2524 {
2525     return try_query_param( hdb, szQuery, 0 );
2526 }
2527 
2528 static void set_summary_str(MSIHANDLE hdb, DWORD pid, LPCSTR value)
2529 {
2530     MSIHANDLE summary;
2531     UINT r;
2532 
2533     r = MsiGetSummaryInformationA(hdb, NULL, 1, &summary);
2534     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2535 
2536     r = MsiSummaryInfoSetPropertyA(summary, pid, VT_LPSTR, 0, NULL, value);
2537     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2538 
2539     r = MsiSummaryInfoPersist(summary);
2540     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2541 
2542     MsiCloseHandle(summary);
2543 }
2544 
2545 static void set_summary_dword(MSIHANDLE hdb, DWORD pid, DWORD value)
2546 {
2547     MSIHANDLE summary;
2548     UINT r;
2549 
2550     r = MsiGetSummaryInformationA(hdb, NULL, 1, &summary);
2551     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2552 
2553     r = MsiSummaryInfoSetPropertyA(summary, pid, VT_I4, value, NULL, NULL);
2554     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2555 
2556     r = MsiSummaryInfoPersist(summary);
2557     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2558 
2559     MsiCloseHandle(summary);
2560 }
2561 
2562 static void test_msipackage(void)
2563 {
2564     MSIHANDLE hdb = 0, hpack = 100;
2565     UINT r;
2566     const char *query;
2567     char name[10];
2568 
2569     /* NULL szPackagePath */
2570     r = MsiOpenPackageA(NULL, &hpack);
2571     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2572 
2573     /* empty szPackagePath */
2574     r = MsiOpenPackageA("", &hpack);
2575     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2576     {
2577         skip("Not enough rights to perform tests\n");
2578         return;
2579     }
2580     todo_wine
2581     {
2582         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2583     }
2584 
2585     if (r == ERROR_SUCCESS)
2586         MsiCloseHandle(hpack);
2587 
2588     /* nonexistent szPackagePath */
2589     r = MsiOpenPackageA("nonexistent", &hpack);
2590     ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
2591 
2592     /* NULL hProduct */
2593     r = MsiOpenPackageA(msifile, NULL);
2594     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2595 
2596     name[0]='#';
2597     name[1]=0;
2598     r = MsiOpenPackageA(name, &hpack);
2599     ok(r == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", r);
2600 
2601     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
2602     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2603 
2604     /* database exists, but is empty */
2605     sprintf(name, "#%lu", hdb);
2606     r = MsiOpenPackageA(name, &hpack);
2607     ok(r == ERROR_INSTALL_PACKAGE_INVALID,
2608        "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
2609 
2610     query = "CREATE TABLE `Property` ( "
2611             "`Property` CHAR(72), `Value` CHAR(0) "
2612             "PRIMARY KEY `Property`)";
2613     r = try_query(hdb, query);
2614     ok(r == ERROR_SUCCESS, "failed to create Properties table\n");
2615 
2616     query = "CREATE TABLE `InstallExecuteSequence` ("
2617             "`Action` CHAR(72), `Condition` CHAR(0), `Sequence` INTEGER "
2618             "PRIMARY KEY `Action`)";
2619     r = try_query(hdb, query);
2620     ok(r == ERROR_SUCCESS, "failed to create InstallExecuteSequence table\n");
2621 
2622     /* a few key tables exist */
2623     sprintf(name, "#%lu", hdb);
2624     r = MsiOpenPackageA(name, &hpack);
2625     ok(r == ERROR_INSTALL_PACKAGE_INVALID,
2626        "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
2627 
2628     MsiCloseHandle(hdb);
2629     DeleteFileA(msifile);
2630 
2631     /* start with a clean database to show what constitutes a valid package */
2632     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
2633     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2634 
2635     sprintf(name, "#%lu", hdb);
2636 
2637     /* The following summary information props must exist:
2638      *  - PID_REVNUMBER
2639      *  - PID_PAGECOUNT
2640      */
2641 
2642     set_summary_dword(hdb, PID_PAGECOUNT, 100);
2643     r = MsiOpenPackageA(name, &hpack);
2644     ok(r == ERROR_INSTALL_PACKAGE_INVALID,
2645        "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
2646 
2647     set_summary_str(hdb, PID_REVNUMBER, "{004757CD-5092-49C2-AD20-28E1CE0DF5F2}");
2648     r = MsiOpenPackageA(name, &hpack);
2649     ok(r == ERROR_SUCCESS,
2650        "Expected ERROR_SUCCESS, got %d\n", r);
2651 
2652     MsiCloseHandle(hpack);
2653     MsiCloseHandle(hdb);
2654     DeleteFileA(msifile);
2655 }
2656 
2657 static void test_formatrecord2(void)
2658 {
2659     MSIHANDLE hpkg, hrec ;
2660     char buffer[0x100];
2661     DWORD sz;
2662     UINT r;
2663 
2664     r = package_from_db(create_package_db(), &hpkg);
2665     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2666     {
2667         skip("Not enough rights to perform tests\n");
2668         DeleteFileA(msifile);
2669         return;
2670     }
2671     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
2672 
2673     r = MsiSetPropertyA(hpkg, "Manufacturer", " " );
2674     ok( r == ERROR_SUCCESS, "set property failed\n");
2675 
2676     hrec = MsiCreateRecord(2);
2677     ok(hrec, "create record failed\n");
2678 
2679     r = MsiRecordSetStringA( hrec, 0, "[ProgramFilesFolder][Manufacturer]\\asdf");
2680     ok( r == ERROR_SUCCESS, "format record failed\n");
2681 
2682     buffer[0] = 0;
2683     sz = sizeof buffer;
2684     r = MsiFormatRecordA( hpkg, hrec, buffer, &sz );
2685     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2686 
2687     r = MsiRecordSetStringA(hrec, 0, "[foo][1]");
2688     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2689     r = MsiRecordSetStringA(hrec, 1, "hoo");
2690     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2691     sz = sizeof buffer;
2692     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2693     ok( sz == 3, "size wrong\n");
2694     ok( 0 == strcmp(buffer,"hoo"), "wrong output %s\n",buffer);
2695     ok( r == ERROR_SUCCESS, "format failed\n");
2696 
2697     r = MsiRecordSetStringA(hrec, 0, "x[~]x");
2698     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2699     sz = sizeof buffer;
2700     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2701     ok( sz == 3, "size wrong\n");
2702     ok( 0 == strcmp(buffer,"x"), "wrong output %s\n",buffer);
2703     ok( r == ERROR_SUCCESS, "format failed\n");
2704 
2705     r = MsiRecordSetStringA(hrec, 0, "[foo.$%}][1]");
2706     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2707     r = MsiRecordSetStringA(hrec, 1, "hoo");
2708     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2709     sz = sizeof buffer;
2710     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2711     ok( sz == 3, "size wrong\n");
2712     ok( 0 == strcmp(buffer,"hoo"), "wrong output %s\n",buffer);
2713     ok( r == ERROR_SUCCESS, "format failed\n");
2714 
2715     r = MsiRecordSetStringA(hrec, 0, "[\\[]");
2716     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2717     sz = sizeof buffer;
2718     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2719     ok( sz == 1, "size wrong\n");
2720     ok( 0 == strcmp(buffer,"["), "wrong output %s\n",buffer);
2721     ok( r == ERROR_SUCCESS, "format failed\n");
2722 
2723     SetEnvironmentVariableA("FOO", "BAR");
2724     r = MsiRecordSetStringA(hrec, 0, "[%FOO]");
2725     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2726     sz = sizeof buffer;
2727     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2728     ok( sz == 3, "size wrong\n");
2729     ok( 0 == strcmp(buffer,"BAR"), "wrong output %s\n",buffer);
2730     ok( r == ERROR_SUCCESS, "format failed\n");
2731 
2732     r = MsiRecordSetStringA(hrec, 0, "[[1]]");
2733     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2734     r = MsiRecordSetStringA(hrec, 1, "%FOO");
2735     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2736     sz = sizeof buffer;
2737     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2738     ok( sz == 3, "size wrong\n");
2739     ok( 0 == strcmp(buffer,"BAR"), "wrong output %s\n",buffer);
2740     ok( r == ERROR_SUCCESS, "format failed\n");
2741 
2742     MsiCloseHandle( hrec );
2743     MsiCloseHandle( hpkg );
2744     DeleteFileA(msifile);
2745 }
2746 
2747 static void test_formatrecord_tables(void)
2748 {
2749     MSIHANDLE hdb, hrec, hpkg = 0;
2750     CHAR buf[MAX_PATH + 41];
2751     CHAR curr_dir[MAX_PATH];
2752     CHAR expected[MAX_PATH + 45];
2753     CHAR root[MAX_PATH];
2754     DWORD size;
2755     UINT r;
2756 
2757     GetCurrentDirectoryA( MAX_PATH, curr_dir );
2758 
2759     hdb = create_package_db();
2760     ok ( hdb, "failed to create package database\n");
2761 
2762     add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'" );
2763     add_directory_entry( hdb, "'ReallyLongDir', 'TARGETDIR', "
2764                              "'I am a really long directory'" );
2765 
2766     create_feature_table( hdb );
2767     add_feature_entry( hdb, "'occipitofrontalis', '', '', '', 2, 1, '', 0" );
2768 
2769     create_component_table( hdb );
2770     add_component_entry( hdb, "'frontal', '', 'TARGETDIR', 0, '', 'frontal_file'" );
2771     add_component_entry( hdb, "'parietal', '', 'TARGETDIR', 1, '', 'parietal_file'" );
2772     add_component_entry( hdb, "'temporal', '', 'ReallyLongDir', 0, '', 'temporal_file'" );
2773 
2774     create_feature_components_table( hdb );
2775     add_feature_components_entry( hdb, "'occipitofrontalis', 'frontal'" );
2776     add_feature_components_entry( hdb, "'occipitofrontalis', 'parietal'" );
2777     add_feature_components_entry( hdb, "'occipitofrontalis', 'temporal'" );
2778 
2779     create_file_table( hdb );
2780     add_file_entry( hdb, "'frontal_file', 'frontal', 'frontal.txt', 0, '', '1033', 8192, 1" );
2781     add_file_entry( hdb, "'parietal_file', 'parietal', 'parietal.txt', 0, '', '1033', 8192, 1" );
2782     add_file_entry( hdb, "'temporal_file', 'temporal', 'temporal.txt', 0, '', '1033', 8192, 1" );
2783 
2784     create_custom_action_table( hdb );
2785     add_custom_action_entry( hdb, "'MyCustom', 51, 'prop', '[!temporal_file]'" );
2786     add_custom_action_entry( hdb, "'EscapeIt1', 51, 'prop', '[\\[]Bracket Text[\\]]'" );
2787     add_custom_action_entry( hdb, "'EscapeIt2', 51, 'prop', '[\\xabcd]'" );
2788     add_custom_action_entry( hdb, "'EscapeIt3', 51, 'prop', '[abcd\\xefgh]'" );
2789     add_custom_action_entry( hdb, "'EmbedNull', 51, 'prop', '[~]np'" );
2790 
2791     r = package_from_db( hdb, &hpkg );
2792     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2793     {
2794         skip("Not enough rights to perform tests\n");
2795         MsiCloseHandle( hdb );
2796         DeleteFileA( msifile );
2797         return;
2798     }
2799     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
2800 
2801     MsiCloseHandle( hdb );
2802 
2803     r = MsiSetPropertyA( hpkg, "imaprop", "ringer" );
2804     ok( r == ERROR_SUCCESS, "cannot set property: %d\n", r);
2805 
2806     hrec = MsiCreateRecord( 1 );
2807 
2808     /* property doesn't exist */
2809     size = MAX_PATH;
2810     /*MsiRecordSetStringA( hrec, 0, "[1]" ); */
2811     MsiRecordSetStringA( hrec, 1, "[idontexist]" );
2812     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2813     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2814     ok( !lstrcmpA( buf, "1:  " ), "Expected '1:  ', got %s\n", buf );
2815 
2816     /* property exists */
2817     size = MAX_PATH;
2818     MsiRecordSetStringA( hrec, 1, "[imaprop]" );
2819     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2820     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2821     ok( !lstrcmpA( buf, "1: ringer " ), "Expected '1: ringer ', got %s\n", buf );
2822 
2823     size = MAX_PATH;
2824     MsiRecordSetStringA( hrec, 0, "1: [1] " );
2825     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2826     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2827     ok( !lstrcmpA( buf, "1: ringer " ), "Expected '1: ringer ', got %s\n", buf );
2828 
2829     /* environment variable doesn't exist */
2830     size = MAX_PATH;
2831     MsiRecordSetStringA( hrec, 1, "[%idontexist]" );
2832     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2833     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2834     ok( !lstrcmpA( buf, "1:  " ), "Expected '1:  ', got %s\n", buf );
2835 
2836     /* environment variable exists */
2837     size = MAX_PATH;
2838     SetEnvironmentVariableA( "crazyvar", "crazyval" );
2839     MsiRecordSetStringA( hrec, 1, "[%crazyvar]" );
2840     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2841     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2842     ok( !lstrcmpA( buf, "1: crazyval " ), "Expected '1: crazyval ', got %s\n", buf );
2843 
2844     /* file key before CostInitialize */
2845     size = MAX_PATH;
2846     MsiRecordSetStringA( hrec, 1, "[#frontal_file]" );
2847     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2848     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2849     ok( !lstrcmpA( buf, "1:  " ), "Expected '1:  ', got %s\n", buf );
2850 
2851     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2852 
2853     r = MsiDoActionA(hpkg, "CostInitialize");
2854     ok( r == ERROR_SUCCESS, "CostInitialize failed: %d\n", r);
2855 
2856     r = MsiDoActionA(hpkg, "FileCost");
2857     ok( r == ERROR_SUCCESS, "FileCost failed: %d\n", r);
2858 
2859     r = MsiDoActionA(hpkg, "CostFinalize");
2860     ok( r == ERROR_SUCCESS, "CostFinalize failed: %d\n", r);
2861 
2862     size = MAX_PATH;
2863     MsiGetPropertyA( hpkg, "ROOTDRIVE", root, &size );
2864 
2865     sprintf( expected, "1: %sfrontal.txt ", root);
2866 
2867     /* frontal full file key */
2868     size = MAX_PATH;
2869     MsiRecordSetStringA( hrec, 1, "[#frontal_file]" );
2870     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2871     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2872     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2873 
2874     /* frontal short file key */
2875     size = MAX_PATH;
2876     MsiRecordSetStringA( hrec, 1, "[!frontal_file]" );
2877     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2878     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2879     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2880 
2881     sprintf( expected, "1: %sI am a really long directory\\temporal.txt ", root);
2882 
2883     /* temporal full file key */
2884     size = MAX_PATH;
2885     MsiRecordSetStringA( hrec, 1, "[#temporal_file]" );
2886     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2887     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2888     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2889 
2890     /* temporal short file key */
2891     size = MAX_PATH;
2892     MsiRecordSetStringA( hrec, 1, "[!temporal_file]" );
2893     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2894     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2895     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2896 
2897     /* custom action 51, files don't exist */
2898     r = MsiDoActionA( hpkg, "MyCustom" );
2899     ok( r == ERROR_SUCCESS, "MyCustom failed: %d\n", r);
2900 
2901     sprintf( expected, "%sI am a really long directory\\temporal.txt", root);
2902 
2903     size = MAX_PATH;
2904     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2905     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2906     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2907 
2908     sprintf( buf, "%sI am a really long directory", root );
2909     CreateDirectoryA( buf, NULL );
2910 
2911     lstrcatA( buf, "\\temporal.txt" );
2912     create_test_file( buf );
2913 
2914     /* custom action 51, files exist */
2915     r = MsiDoActionA( hpkg, "MyCustom" );
2916     ok( r == ERROR_SUCCESS, "MyCustom failed: %d\n", r);
2917 
2918     size = MAX_PATH;
2919     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2920     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2921     todo_wine
2922     {
2923         ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2924     }
2925 
2926     /* custom action 51, escaped text 1 */
2927     r = MsiDoActionA( hpkg, "EscapeIt1" );
2928     ok( r == ERROR_SUCCESS, "EscapeIt1 failed: %d\n", r);
2929 
2930     size = MAX_PATH;
2931     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2932     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2933     ok( !lstrcmpA( buf, "[Bracket Text]" ), "Expected '[Bracket Text]', got %s\n", buf);
2934 
2935     /* custom action 51, escaped text 2 */
2936     r = MsiDoActionA( hpkg, "EscapeIt2" );
2937     ok( r == ERROR_SUCCESS, "EscapeIt2 failed: %d\n", r);
2938 
2939     size = MAX_PATH;
2940     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2941     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2942     ok( !lstrcmpA( buf, "x" ), "Expected 'x', got %s\n", buf);
2943 
2944     /* custom action 51, escaped text 3 */
2945     r = MsiDoActionA( hpkg, "EscapeIt3" );
2946     ok( r == ERROR_SUCCESS, "EscapeIt3 failed: %d\n", r);
2947 
2948     size = MAX_PATH;
2949     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2950     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2951     ok( !lstrcmpA( buf, "" ), "Expected '', got %s\n", buf);
2952 
2953     /* custom action 51, embedded null */
2954     r = MsiDoActionA( hpkg, "EmbedNull" );
2955     ok( r == ERROR_SUCCESS, "EmbedNull failed: %d\n", r);
2956 
2957     size = MAX_PATH;
2958     memset( buf, 'a', sizeof(buf) );
2959     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2960     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2961     ok( !memcmp( buf, "\0np", sizeof("\0np") ), "wrong value\n");
2962     ok( size == sizeof("\0np") - 1, "got %lu\n", size );
2963 
2964     r = MsiSetPropertyA( hpkg, "prop", "[~]np" );
2965     ok( r == ERROR_SUCCESS, "cannot set property: %d\n", r);
2966 
2967     size = MAX_PATH;
2968     memset( buf, 'a', sizeof(buf) );
2969     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2970     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2971     ok( !lstrcmpA( buf, "[~]np" ), "Expected '[~]np', got %s\n", buf);
2972 
2973     sprintf( expected, "1: %sI am a really long directory\\ ", root);
2974 
2975     /* component with INSTALLSTATE_LOCAL */
2976     size = MAX_PATH;
2977     MsiRecordSetStringA( hrec, 1, "[$temporal]" );
2978     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2979     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2980     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2981 
2982     r = MsiSetComponentStateA( hpkg, "temporal", INSTALLSTATE_SOURCE );
2983     ok( r == ERROR_SUCCESS, "failed to set install state: %d\n", r);
2984 
2985     /* component with INSTALLSTATE_SOURCE */
2986     lstrcpyA( expected, "1: " );
2987     lstrcatA( expected, curr_dir );
2988     if (strlen(curr_dir) > 3) lstrcatA( expected, "\\" );
2989     lstrcatA( expected, " " );
2990     size = MAX_PATH;
2991     MsiRecordSetStringA( hrec, 1, "[$parietal]" );
2992     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2993     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2994     ok( !lstrcmpA( buf, expected ), "Expected '%s', got '%s'\n", expected, buf);
2995 
2996     sprintf( buf, "%sI am a really long directory\\temporal.txt", root );
2997     DeleteFileA( buf );
2998 
2999     sprintf( buf, "%sI am a really long directory", root );
3000     RemoveDirectoryA( buf );
3001 
3002     MsiCloseHandle( hrec );
3003     MsiCloseHandle( hpkg );
3004     DeleteFileA( msifile );
3005 }
3006 
3007 static void test_feature_states( UINT line, MSIHANDLE package, const char *feature, UINT error,
3008                                  INSTALLSTATE expected_state, INSTALLSTATE expected_action, BOOL todo )
3009 {
3010     UINT r;
3011     INSTALLSTATE state = 0xdeadbee;
3012     INSTALLSTATE action = 0xdeadbee;
3013 
3014     r = MsiGetFeatureStateA( package, feature, &state, &action );
3015     ok( r == error, "%u: expected %d got %d\n", line, error, r );
3016     if (r == ERROR_SUCCESS)
3017     {
3018         ok( state == expected_state, "%u: expected state %d got %d\n",
3019             line, expected_state, state );
3020         todo_wine_if (todo)
3021             ok( action == expected_action, "%u: expected action %d got %d\n",
3022                 line, expected_action, action );
3023     }
3024     else
3025     {
3026         ok( state == 0xdeadbee, "%u: expected state 0xdeadbee got %d\n", line, state );
3027         todo_wine_if (todo)
3028             ok( action == 0xdeadbee, "%u: expected action 0xdeadbee got %d\n", line, action );
3029 
3030     }
3031 }
3032 
3033 static void test_component_states( UINT line, MSIHANDLE package, const char *component, UINT error,
3034                                    INSTALLSTATE expected_state, INSTALLSTATE expected_action, BOOL todo )
3035 {
3036     UINT r;
3037     INSTALLSTATE state = 0xdeadbee;
3038     INSTALLSTATE action = 0xdeadbee;
3039 
3040     r = MsiGetComponentStateA( package, component, &state, &action );
3041     ok( r == error, "%u: expected %d got %d\n", line, error, r );
3042     if (r == ERROR_SUCCESS)
3043     {
3044         ok( state == expected_state, "%u: expected state %d got %d\n",
3045             line, expected_state, state );
3046         todo_wine_if (todo)
3047             ok( action == expected_action, "%u: expected action %d got %d\n",
3048                 line, expected_action, action );
3049     }
3050     else
3051     {
3052         ok( state == 0xdeadbee, "%u: expected state 0xdeadbee got %d\n",
3053             line, state );
3054         todo_wine_if (todo)
3055             ok( action == 0xdeadbee, "%u: expected action 0xdeadbee got %d\n",
3056                 line, action );
3057     }
3058 }
3059 
3060 static void test_states(void)
3061 {
3062     static const char msifile2[] = "winetest2-package.msi";
3063     static const char msifile3[] = "winetest3-package.msi";
3064     static const char msifile4[] = "winetest4-package.msi";
3065     static const WCHAR msifile2W[] = L"winetest2-package.msi";
3066     static const WCHAR msifile3W[] = L"winetest3-package.msi";
3067     static const WCHAR msifile4W[] = L"winetest4-package.msi";
3068     char msi_cache_file[MAX_PATH];
3069     DWORD cache_file_name_len;
3070     INSTALLSTATE state;
3071     MSIHANDLE hpkg, hprod;
3072     UINT r;
3073     MSIHANDLE hdb;
3074     BOOL is_broken;
3075     char value[MAX_PATH];
3076     DWORD size;
3077 
3078     if (is_process_limited())
3079     {
3080         skip("process is limited\n");
3081         return;
3082     }
3083 
3084     hdb = create_package_db();
3085     ok ( hdb, "failed to create package database\n" );
3086 
3087     add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'");
3088 
3089     create_property_table( hdb );
3090     add_property_entry( hdb, "'ProductCode', '{7262AC98-EEBD-4364-8CE3-D654F6A425B9}'" );
3091     add_property_entry( hdb, "'ProductLanguage', '1033'" );
3092     add_property_entry( hdb, "'ProductName', 'MSITEST'" );
3093     add_property_entry( hdb, "'ProductVersion', '1.1.1'" );
3094     add_property_entry( hdb, "'MSIFASTINSTALL', '1'" );
3095     add_property_entry( hdb, "'UpgradeCode', '{3494EEEA-4221-4A66-802E-DED8916BC5C5}'" );
3096 
3097     create_install_execute_sequence_table( hdb );
3098     add_install_execute_sequence_entry( hdb, "'CostInitialize', '', '800'" );
3099     add_install_execute_sequence_entry( hdb, "'FileCost', '', '900'" );
3100     add_install_execute_sequence_entry( hdb, "'CostFinalize', '', '1000'" );
3101     add_install_execute_sequence_entry( hdb, "'InstallValidate', '', '1400'" );
3102     add_install_execute_sequence_entry( hdb, "'InstallInitialize', '', '1500'" );
3103     add_install_execute_sequence_entry( hdb, "'ProcessComponents', '', '1600'" );
3104     add_install_execute_sequence_entry( hdb, "'UnpublishFeatures', '', '1800'" );
3105     add_install_execute_sequence_entry( hdb, "'RegisterProduct', '', '6100'" );
3106     add_install_execute_sequence_entry( hdb, "'PublishFeatures', '', '6300'" );
3107     add_install_execute_sequence_entry( hdb, "'PublishProduct', '', '6400'" );
3108     add_install_execute_sequence_entry( hdb, "'InstallFinalize', '', '6600'" );
3109 
3110     create_media_table( hdb );
3111     add_media_entry( hdb, "'1', '3', '', '', 'DISK1', ''");
3112 
3113     create_feature_table( hdb );
3114 
3115     create_component_table( hdb );
3116 
3117     /* msidbFeatureAttributesFavorLocal */
3118     add_feature_entry( hdb, "'one', '', '', '', 2, 1, '', 0" );
3119 
3120     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesLocalOnly */
3121     add_component_entry( hdb, "'alpha', '{467EC132-739D-4784-A37B-677AA43DBC94}', 'TARGETDIR', 0, '', 'alpha_file'" );
3122 
3123     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSourceOnly */
3124     add_component_entry( hdb, "'beta', '{2C1F189C-24A6-4C34-B26B-994A6C026506}', 'TARGETDIR', 1, '', 'beta_file'" );
3125 
3126     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesOptional */
3127     add_component_entry( hdb, "'gamma', '{C271E2A4-DE2E-4F70-86D1-6984AF7DE2CA}', 'TARGETDIR', 2, '', 'gamma_file'" );
3128 
3129     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSharedDllRefCount */
3130     add_component_entry( hdb, "'theta', '{4EB3129D-81A8-48D5-9801-75600FED3DD9}', 'TARGETDIR', 8, '', 'theta_file'" );
3131 
3132     /* msidbFeatureAttributesFavorSource */
3133     add_feature_entry( hdb, "'two', '', '', '', 2, 1, '', 1" );
3134 
3135     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesLocalOnly */
3136     add_component_entry( hdb, "'delta', '{938FD4F2-C648-4259-A03C-7AA3B45643F3}', 'TARGETDIR', 0, '', 'delta_file'" );
3137 
3138     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSourceOnly */
3139     add_component_entry( hdb, "'epsilon', '{D59713B6-C11D-47F2-A395-1E5321781190}', 'TARGETDIR', 1, '', 'epsilon_file'" );
3140 
3141     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesOptional */
3142     add_component_entry( hdb, "'zeta', '{377D33AB-2FAA-42B9-A629-0C0DAE9B9C7A}', 'TARGETDIR', 2, '', 'zeta_file'" );
3143 
3144     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSharedDllRefCount */
3145     add_component_entry( hdb, "'iota', '{5D36F871-B5ED-4801-9E0F-C46B9E5C9669}', 'TARGETDIR', 8, '', 'iota_file'" );
3146 
3147     /* msidbFeatureAttributesFavorSource */
3148     add_feature_entry( hdb, "'three', '', '', '', 2, 1, '', 1" );
3149 
3150     /* msidbFeatureAttributesFavorLocal */
3151     add_feature_entry( hdb, "'four', '', '', '', 2, 1, '', 0" );
3152 
3153     /* disabled */
3154     add_feature_entry( hdb, "'five', '', '', '', 2, 0, '', 1" );
3155 
3156     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSourceOnly */
3157     add_component_entry( hdb, "'eta', '{DD89003F-0DD4-41B8-81C0-3411A7DA2695}', 'TARGETDIR', 1, '', 'eta_file'" );
3158 
3159     /* no feature parent:msidbComponentAttributesLocalOnly */
3160     add_component_entry( hdb, "'kappa', '{D6B93DC3-8DA5-4769-9888-42BFE156BB8B}', 'TARGETDIR', 1, '', 'kappa_file'" );
3161 
3162     /* msidbFeatureAttributesFavorLocal:removed */
3163     add_feature_entry( hdb, "'six', '', '', '', 2, 1, '', 0" );
3164 
3165     /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesLocalOnly */
3166     add_component_entry( hdb, "'lambda', '{6528C5E4-02A4-4636-A214-7A66A6C35B64}', 'TARGETDIR', 0, '', 'lambda_file'" );
3167 
3168     /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesSourceOnly */
3169     add_component_entry( hdb, "'mu', '{97014BAB-6C56-4013-9A63-2BF913B42519}', 'TARGETDIR', 1, '', 'mu_file'" );
3170 
3171     /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesOptional */
3172     add_component_entry( hdb, "'nu', '{943DD0D8-5808-4954-8526-3B8493FEDDCD}', 'TARGETDIR', 2, '', 'nu_file'" );
3173 
3174     /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesSharedDllRefCount */
3175     add_component_entry( hdb, "'xi', '{D6CF9EF7-6FCF-4930-B34B-F938AEFF9BDB}', 'TARGETDIR', 8, '', 'xi_file'" );
3176 
3177     /* msidbFeatureAttributesFavorSource:removed */
3178     add_feature_entry( hdb, "'seven', '', '', '', 2, 1, '', 1" );
3179 
3180     /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesLocalOnly */
3181     add_component_entry( hdb, "'omicron', '{7B57521D-15DB-4141-9AA6-01D934A4433F}', 'TARGETDIR', 0, '', 'omicron_file'" );
3182 
3183     /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesSourceOnly */
3184     add_component_entry( hdb, "'pi', '{FB85346B-378E-4492-8769-792305471C81}', 'TARGETDIR', 1, '', 'pi_file'" );
3185 
3186     /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesOptional */
3187     add_component_entry( hdb, "'rho', '{798F2047-7B0C-4783-8BB0-D703E554114B}', 'TARGETDIR', 2, '', 'rho_file'" );
3188 
3189     /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesSharedDllRefCount */
3190     add_component_entry( hdb, "'sigma', '{5CE9DDA8-B67B-4736-9D93-99D61C5B93E7}', 'TARGETDIR', 8, '', 'sigma_file'" );
3191 
3192     /* msidbFeatureAttributesFavorLocal */
3193     add_feature_entry( hdb, "'eight', '', '', '', 2, 1, '', 0" );
3194 
3195     add_component_entry( hdb, "'tau', '{07DEB510-677C-4A6F-A0A6-7CD8EFEA77ED}', 'TARGETDIR', 1, '', 'tau_file'" );
3196 
3197     /* msidbFeatureAttributesFavorSource */
3198     add_feature_entry( hdb, "'nine', '', '', '', 2, 1, '', 1" );
3199 
3200     add_component_entry( hdb, "'phi', '{9F0594C5-35AD-43EA-94DD-8DF73FAA664D}', 'TARGETDIR', 1, '', 'phi_file'" );
3201 
3202     /* msidbFeatureAttributesFavorAdvertise */
3203     add_feature_entry( hdb, "'ten', '', '', '', 2, 1, '', 4" );
3204 
3205     add_component_entry( hdb, "'chi', '{E6B539AB-5DA9-4236-A2D2-E341A50B4C38}', 'TARGETDIR', 1, '', 'chi_file'" );
3206 
3207     /* msidbFeatureAttributesUIDisallowAbsent */
3208     add_feature_entry( hdb, "'eleven', '', '', '', 2, 1, '', 16" );
3209 
3210     add_component_entry( hdb, "'psi', '{A06B23B5-746B-427A-8A6E-FD6AC8F46A95}', 'TARGETDIR', 1, '', 'psi_file'" );
3211 
3212     /* high install level */
3213     add_feature_entry( hdb, "'twelve', '', '', '', 2, 2, '', 0" );
3214 
3215     add_component_entry( hdb, "'upsilon', '{557e0c04-ceba-4c58-86a9-4a73352e8cf6}', 'TARGETDIR', 1, '', 'upsilon_file'" );
3216 
3217     /* msidbFeatureAttributesFollowParent */
3218     add_feature_entry( hdb, "'thirteen', '', '', '', 2, 2, '', 2" );
3219 
3220     create_feature_components_table( hdb );
3221     add_feature_components_entry( hdb, "'one', 'alpha'" );
3222     add_feature_components_entry( hdb, "'one', 'beta'" );
3223     add_feature_components_entry( hdb, "'one', 'gamma'" );
3224     add_feature_components_entry( hdb, "'one', 'theta'" );
3225     add_feature_components_entry( hdb, "'two', 'delta'" );
3226     add_feature_components_entry( hdb, "'two', 'epsilon'" );
3227     add_feature_components_entry( hdb, "'two', 'zeta'" );
3228     add_feature_components_entry( hdb, "'two', 'iota'" );
3229     add_feature_components_entry( hdb, "'three', 'eta'" );
3230     add_feature_components_entry( hdb, "'four', 'eta'" );
3231     add_feature_components_entry( hdb, "'five', 'eta'" );
3232     add_feature_components_entry( hdb, "'six', 'lambda'" );
3233     add_feature_components_entry( hdb, "'six', 'mu'" );
3234     add_feature_components_entry( hdb, "'six', 'nu'" );
3235     add_feature_components_entry( hdb, "'six', 'xi'" );
3236     add_feature_components_entry( hdb, "'seven', 'omicron'" );
3237     add_feature_components_entry( hdb, "'seven', 'pi'" );
3238     add_feature_components_entry( hdb, "'seven', 'rho'" );
3239     add_feature_components_entry( hdb, "'seven', 'sigma'" );
3240     add_feature_components_entry( hdb, "'eight', 'tau'" );
3241     add_feature_components_entry( hdb, "'nine', 'phi'" );
3242     add_feature_components_entry( hdb, "'ten', 'chi'" );
3243     add_feature_components_entry( hdb, "'eleven', 'psi'" );
3244     add_feature_components_entry( hdb, "'twelve', 'upsilon'" );
3245     add_feature_components_entry( hdb, "'thirteen', 'upsilon'" );
3246 
3247     create_file_table( hdb );
3248     add_file_entry( hdb, "'alpha_file', 'alpha', 'alpha.txt', 100, '', '1033', 8192, 1" );
3249     add_file_entry( hdb, "'beta_file', 'beta', 'beta.txt', 0, '', '1033', 8192, 1" );
3250     add_file_entry( hdb, "'gamma_file', 'gamma', 'gamma.txt', 0, '', '1033', 8192, 1" );
3251     add_file_entry( hdb, "'theta_file', 'theta', 'theta.txt', 0, '', '1033', 8192, 1" );
3252     add_file_entry( hdb, "'delta_file', 'delta', 'delta.txt', 0, '', '1033', 8192, 1" );
3253     add_file_entry( hdb, "'epsilon_file', 'epsilon', 'epsilon.txt', 0, '', '1033', 8192, 1" );
3254     add_file_entry( hdb, "'zeta_file', 'zeta', 'zeta.txt', 0, '', '1033', 8192, 1" );
3255     add_file_entry( hdb, "'iota_file', 'iota', 'iota.txt', 0, '', '1033', 8192, 1" );
3256 
3257     /* compressed file */
3258     add_file_entry( hdb, "'eta_file', 'eta', 'eta.txt', 0, '', '1033', 16384, 1" );
3259 
3260     add_file_entry( hdb, "'kappa_file', 'kappa', 'kappa.txt', 0, '', '1033', 8192, 1" );
3261     add_file_entry( hdb, "'lambda_file', 'lambda', 'lambda.txt', 100, '', '1033', 8192, 1" );
3262     add_file_entry( hdb, "'mu_file', 'mu', 'mu.txt', 100, '', '1033', 8192, 1" );
3263     add_file_entry( hdb, "'nu_file', 'nu', 'nu.txt', 100, '', '1033', 8192, 1" );
3264     add_file_entry( hdb, "'xi_file', 'xi', 'xi.txt', 100, '', '1033', 8192, 1" );
3265     add_file_entry( hdb, "'omicron_file', 'omicron', 'omicron.txt', 100, '', '1033', 8192, 1" );
3266     add_file_entry( hdb, "'pi_file', 'pi', 'pi.txt', 100, '', '1033', 8192, 1" );
3267     add_file_entry( hdb, "'rho_file', 'rho', 'rho.txt', 100, '', '1033', 8192, 1" );
3268     add_file_entry( hdb, "'sigma_file', 'sigma', 'sigma.txt', 100, '', '1033', 8192, 1" );
3269     add_file_entry( hdb, "'tau_file', 'tau', 'tau.txt', 100, '', '1033', 8192, 1" );
3270     add_file_entry( hdb, "'phi_file', 'phi', 'phi.txt', 100, '', '1033', 8192, 1" );
3271     add_file_entry( hdb, "'chi_file', 'chi', 'chi.txt', 100, '', '1033', 8192, 1" );
3272     add_file_entry( hdb, "'psi_file', 'psi', 'psi.txt', 100, '', '1033', 8192, 1" );
3273     add_file_entry( hdb, "'upsilon_file', 'upsilon', 'upsilon.txt', 0, '', '1033', 16384, 1" );
3274 
3275     r = MsiDatabaseCommit(hdb);
3276     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
3277 
3278     /* these properties must not be in the saved msi file */
3279     add_property_entry( hdb, "'ADDLOCAL', 'one,four'");
3280     add_property_entry( hdb, "'ADDSOURCE', 'two,three'");
3281     add_property_entry( hdb, "'REMOVE', 'six,seven'");
3282     add_property_entry( hdb, "'REINSTALL', 'eight,nine,ten'");
3283     add_property_entry( hdb, "'REINSTALLMODE', 'omus'");
3284 
3285     r = package_from_db( hdb, &hpkg );
3286     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
3287     {
3288         skip("Not enough rights to perform tests\n");
3289         DeleteFileA(msifile);
3290         return;
3291     }
3292     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3293 
3294     MsiCloseHandle(hdb);
3295 
3296     CopyFileA(msifile, msifile2, FALSE);
3297     CopyFileA(msifile, msifile3, FALSE);
3298     CopyFileA(msifile, msifile4, FALSE);
3299 
3300     size = sizeof(value);
3301     memset(value, 0, sizeof(value));
3302     r = MsiGetPropertyA(hpkg, "ProductToBeRegistered", value, &size);
3303     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
3304     ok(!value[0], "ProductToBeRegistered = %s\n", value);
3305 
3306     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3307     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3308 
3309     r = MsiDoActionA( hpkg, "CostInitialize");
3310     ok( r == ERROR_SUCCESS, "cost init failed\n");
3311 
3312     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3313     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3314 
3315     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3316 
3317     r = MsiDoActionA( hpkg, "FileCost");
3318     ok( r == ERROR_SUCCESS, "file cost failed\n");
3319 
3320     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3321     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3322 
3323     r = MsiDoActionA( hpkg, "CostFinalize");
3324     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3325 
3326     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3327     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
3328     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3329     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3330     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3331     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3332     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3333     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3334     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3335     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3336     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3337     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3338     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3339 
3340     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3341     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
3342     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3343     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3344     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3345     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
3346     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
3347     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3348     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3349     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3350     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3351     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3352     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3353     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3354     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3355     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3356     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3357     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3358     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3359     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3360     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3361     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3362     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3363 
3364     MsiCloseHandle( hpkg );
3365 
3366     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3367 
3368     /* publish the features and components */
3369     r = MsiInstallProductA(msifile, "ADDLOCAL=one,four ADDSOURCE=two,three REMOVE=six,seven REINSTALL=eight,nine,ten");
3370     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3371 
3372     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb);
3373     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3374 
3375     /* these properties must not be in the saved msi file */
3376     add_property_entry( hdb, "'ADDLOCAL', 'one,four'");
3377     add_property_entry( hdb, "'ADDSOURCE', 'two,three'");
3378     add_property_entry( hdb, "'REMOVE', 'six,seven'");
3379     add_property_entry( hdb, "'REINSTALL', 'eight,nine,ten'");
3380 
3381     r = package_from_db( hdb, &hpkg );
3382     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3383 
3384     MsiCloseHandle(hdb);
3385 
3386     size = sizeof(value);
3387     memset(value, 0, sizeof(value));
3388     r = MsiGetPropertyA(hpkg, "ProductToBeRegistered", value, &size);
3389     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
3390     ok(value[0]=='1' && !value[1], "ProductToBeRegistered = %s\n", value);
3391 
3392     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3393     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3394 
3395     r = MsiDoActionA( hpkg, "CostInitialize");
3396     ok( r == ERROR_SUCCESS, "cost init failed\n");
3397 
3398     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3399     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3400 
3401     r = MsiDoActionA( hpkg, "FileCost");
3402     ok( r == ERROR_SUCCESS, "file cost failed\n");
3403 
3404     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3405     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3406 
3407     r = MsiDoActionA( hpkg, "CostFinalize");
3408     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3409 
3410     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3411     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3412     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3413     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3414     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3415     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3416     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3417     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3418     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3419     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3420     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3421     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3422     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3423 
3424     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3425     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3426     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3427     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3428     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3429     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3430     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3431     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3432     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3433     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3434     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3435     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3436     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3437     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3438     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3439     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3440     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3441     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3442     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3443     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3444     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3445     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3446     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3447 
3448     MsiCloseHandle(hpkg);
3449 
3450     /* uninstall the product */
3451     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3452     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3453 
3454     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3455     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3456     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3457     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3458 
3459     /* all features installed locally */
3460     r = MsiInstallProductA(msifile2, "ADDLOCAL=ALL");
3461     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3462 
3463     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3464     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3465     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3466     ok(state == INSTALLSTATE_LOCAL, "state = %d\n", state);
3467 
3468     r = MsiOpenDatabaseW(msifile2W, MSIDBOPEN_DIRECT, &hdb);
3469     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3470 
3471     /* these properties must not be in the saved msi file */
3472     add_property_entry( hdb, "'ADDLOCAL', 'one,two,three,four,five,six,seven,eight,nine,ten,twelve'");
3473 
3474     r = package_from_db( hdb, &hpkg );
3475     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3476 
3477     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3478     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3479 
3480     r = MsiDoActionA( hpkg, "CostInitialize");
3481     ok( r == ERROR_SUCCESS, "cost init failed\n");
3482 
3483     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3484     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3485 
3486     r = MsiDoActionA( hpkg, "CostFinalize");
3487     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3488 
3489     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3490     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3491     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3492     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3493     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3494     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3495     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3496     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, TRUE );
3497     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, TRUE );
3498     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, TRUE );
3499     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3500     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3501     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3502 
3503     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3504     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3505     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3506     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3507     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3508     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3509     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3510     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3511     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3512     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3513     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3514     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3515     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3516     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3517     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3518     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3519     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3520     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3521     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3522     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3523     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3524     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3525     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3526 
3527     MsiCloseHandle(hpkg);
3528 
3529     /* uninstall the product */
3530     r = MsiInstallProductA(msifile2, "REMOVE=ALL");
3531     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3532 
3533     /* all features installed from source */
3534     r = MsiInstallProductA(msifile3, "ADDSOURCE=ALL");
3535     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3536 
3537     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3538     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3539     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3540     ok(state == INSTALLSTATE_LOCAL, "state = %d\n", state);
3541 
3542     r = MsiOpenDatabaseW(msifile3W, MSIDBOPEN_DIRECT, &hdb);
3543     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3544 
3545     /* this property must not be in the saved msi file */
3546     add_property_entry( hdb, "'ADDSOURCE', 'one,two,three,four,five,six,seven,eight,nine,ten'");
3547 
3548     r = package_from_db( hdb, &hpkg );
3549     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3550 
3551     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3552     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3553 
3554     r = MsiDoActionA( hpkg, "CostInitialize");
3555     ok( r == ERROR_SUCCESS, "cost init failed\n");
3556 
3557     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3558     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3559 
3560     r = MsiDoActionA( hpkg, "FileCost");
3561     ok( r == ERROR_SUCCESS, "file cost failed\n");
3562 
3563     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3564     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3565 
3566     r = MsiDoActionA( hpkg, "CostFinalize");
3567     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3568 
3569     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3570     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3571     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3572     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3573     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3574     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3575     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3576     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3577     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3578     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3579     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3580     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3581     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3582 
3583     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3584     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3585     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3586     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3587     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3588     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3589     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3590     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3591     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3592     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3593     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3594     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3595     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3596     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3597     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3598     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3599     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3600     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3601     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3602     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3603     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3604     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3605     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3606 
3607     MsiCloseHandle(hpkg);
3608 
3609     /* reinstall the product */
3610     r = MsiInstallProductA(msifile3, "REINSTALL=ALL");
3611     is_broken = (r == ERROR_INSTALL_FAILURE);
3612     ok(r == ERROR_SUCCESS || broken(is_broken) /* win2k3 */, "Expected ERROR_SUCCESS, got %d\n", r);
3613 
3614     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3615     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3616     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3617     ok(state == INSTALLSTATE_LOCAL, "state = %d\n", state);
3618 
3619     r = MsiOpenDatabaseW(msifile4W, MSIDBOPEN_DIRECT, &hdb);
3620     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3621 
3622     /* this property must not be in the saved msi file */
3623     add_property_entry( hdb, "'ADDSOURCE', 'one,two,three,four,five,six,seven,eight,nine,ten'");
3624 
3625     r = package_from_db( hdb, &hpkg );
3626     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3627 
3628     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3629     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3630 
3631     r = MsiDoActionA( hpkg, "CostInitialize");
3632     ok( r == ERROR_SUCCESS, "cost init failed\n");
3633 
3634     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3635     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3636 
3637     r = MsiDoActionA( hpkg, "FileCost");
3638     ok( r == ERROR_SUCCESS, "file cost failed\n");
3639 
3640     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3641     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3642 
3643     r = MsiDoActionA( hpkg, "CostFinalize");
3644     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3645 
3646     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3647     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3648     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3649     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3650     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3651     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3652     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3653     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3654     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3655     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3656     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3657     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3658     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3659 
3660     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3661     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3662     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3663     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3664     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3665     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3666     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3667     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3668     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3669     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3670     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3671     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3672     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3673     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3674     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3675     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3676     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3677     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3678     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3679     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3680     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3681     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3682     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3683 
3684     MsiCloseHandle(hpkg);
3685 
3686     /* test source only install */
3687     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3688     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3689     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "one");
3690     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3691     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "two");
3692     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3693 
3694     r = MsiInstallProductA(msifile, "ADDSOURCE=one");
3695     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3696     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "one");
3697     ok(state == INSTALLSTATE_SOURCE, "state = %d\n", state);
3698     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "two");
3699     ok(state == INSTALLSTATE_ABSENT, "state = %d\n", state);
3700 
3701     /* no arguments test */
3702     cache_file_name_len = sizeof(msi_cache_file);
3703     r = MsiGetProductInfoA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}",
3704             INSTALLPROPERTY_LOCALPACKAGEA, msi_cache_file, &cache_file_name_len);
3705     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3706     r = MsiOpenDatabaseA(msi_cache_file, (const char*)MSIDBOPEN_DIRECT, &hdb);
3707     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3708 
3709     create_custom_action_table( hdb );
3710     add_custom_action_entry( hdb, "'ConditionCheck1', 19, '', 'Condition check failed (1)'" );
3711     add_custom_action_entry( hdb, "'ConditionCheck2', 19, '', 'Condition check failed (2)'" );
3712     add_custom_action_entry( hdb, "'ConditionCheck3', 19, '', 'Condition check failed (3)'" );
3713     add_custom_action_entry( hdb, "'ConditionCheck4', 19, '', 'Condition check failed (4)'" );
3714     add_custom_action_entry( hdb, "'ConditionCheck5', 19, '', 'Condition check failed (5)'" );
3715     add_custom_action_entry( hdb, "'ConditionCheck6', 19, '', 'Condition check failed (6)'" );
3716     add_custom_action_entry( hdb, "'ConditionCheck7', 19, '', 'Condition check failed (7)'" );
3717     add_custom_action_entry( hdb, "'ConditionCheck8', 19, '', 'Condition check failed (8)'" );
3718     add_custom_action_entry( hdb,
3719             "'VBFeatureRequest', 38, NULL, 'Session.FeatureRequestState(\"three\") = 3'" );
3720 
3721     add_install_execute_sequence_entry( hdb, "'ConditionCheck1', 'REINSTALL', '798'" );
3722     add_install_execute_sequence_entry( hdb, "'ConditionCheck2', 'NOT REMOVE AND Preselected', '799'" );
3723     add_install_execute_sequence_entry( hdb, "'VBFeatureRequest', 'NOT REMOVE', '1001'" );
3724     add_install_execute_sequence_entry( hdb, "'ConditionCheck3', 'REINSTALL', '6598'" );
3725     add_install_execute_sequence_entry( hdb, "'ConditionCheck4', 'NOT REMOVE AND Preselected', '6599'" );
3726     add_install_execute_sequence_entry( hdb, "'ConditionCheck5', 'REINSTALL', '6601'" );
3727     add_install_execute_sequence_entry( hdb, "'ConditionCheck6', 'NOT REMOVE AND Preselected', '6601'" );
3728     /* Add "one" feature action tests */
3729     add_install_execute_sequence_entry( hdb, "'ConditionCheck7', 'NOT REMOVE AND NOT(&one=-1)', '1501'" );
3730     add_install_execute_sequence_entry( hdb, "'ConditionCheck8', 'NOT REMOVE AND NOT(&one=-1)', '6602'" );
3731     r = MsiDatabaseCommit(hdb);
3732     ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed: %d\n", r);
3733     r = package_from_db( hdb, &hpkg );
3734     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3735     MsiCloseHandle(hdb);
3736 
3737     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3738     test_feature_states( __LINE__, hpkg, "two", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3739     r = MsiDoActionA( hpkg, "CostInitialize");
3740     ok( r == ERROR_SUCCESS, "CostInitialize failed\n");
3741     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3742     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3743 
3744     r = MsiDoActionA( hpkg, "FileCost");
3745     ok( r == ERROR_SUCCESS, "FileCost failed\n");
3746     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3747     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3748 
3749     r = MsiDoActionA( hpkg, "CostFinalize");
3750     ok( r == ERROR_SUCCESS, "CostFinalize failed\n");
3751     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3752     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3753     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3754     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3755     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3756     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3757     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3758     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3759     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3760     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3761     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3762     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3763     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3764     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3765     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3766     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3767     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3768     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3769     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3770     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3771     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3772     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3773     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3774     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3775     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3776 
3777     r = MsiDoActionA( hpkg, "InstallValidate");
3778     ok( r == ERROR_SUCCESS, "InstallValidate failed %d\n", r);
3779     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3780     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3781     MsiCloseHandle( hpkg );
3782 
3783     r = MsiInstallProductA(msifile, "");
3784     ok(r == ERROR_SUCCESS || (is_broken && r == ERROR_INSTALL_FAILURE) /* win2k3 */,
3785             "Expected ERROR_SUCCESS, got %d\n", r);
3786     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "one");
3787     ok(state == INSTALLSTATE_SOURCE, "state = %d\n", state);
3788     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "two");
3789     ok(state == INSTALLSTATE_ABSENT, "state = %d\n", state);
3790     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "three");
3791     ok(state == INSTALLSTATE_LOCAL, "state = %d\n", state);
3792 
3793     /* minor upgrade test with no REINSTALL argument */
3794     r = MsiOpenProductA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", &hprod);
3795     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3796     size = MAX_PATH;
3797     r = MsiGetProductPropertyA(hprod, "ProductVersion", value, &size);
3798     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3799     ok(!strcmp(value, "1.1.1"), "ProductVersion = %s\n", value);
3800     MsiCloseHandle(hprod);
3801 
3802     r = MsiOpenDatabaseA(msifile2, (const char*)MSIDBOPEN_DIRECT, &hdb);
3803     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3804     update_ProductVersion_property( hdb, "1.1.2" );
3805     set_summary_str(hdb, PID_REVNUMBER, "{A219A62A-D931-4F1B-89DB-FF1C300A8D43}");
3806     r = MsiDatabaseCommit(hdb);
3807     ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed: %d\n", r);
3808     MsiCloseHandle(hdb);
3809 
3810     r = MsiInstallProductA(msifile2, "");
3811     ok(r == ERROR_PRODUCT_VERSION, "Expected ERROR_PRODUCT_VERSION, got %d\n", r);
3812 
3813     r = MsiInstallProductA(msifile2, "REINSTALLMODe=V");
3814     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3815 
3816     r = MsiOpenProductA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", &hprod);
3817     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3818     size = MAX_PATH;
3819     r = MsiGetProductPropertyA(hprod, "ProductVersion", value, &size);
3820     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3821     ok(!strcmp(value, "1.1.2"), "ProductVersion = %s\n", value);
3822     MsiCloseHandle(hprod);
3823 
3824     /* major upgrade test */
3825     r = MsiOpenDatabaseA(msifile2, (const char*)MSIDBOPEN_DIRECT, &hdb);
3826     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3827     add_install_execute_sequence_entry( hdb, "'FindRelatedProducts', '', '100'" );
3828     add_install_execute_sequence_entry( hdb, "'RemoveExistingProducts', '', '1401'" );
3829     create_upgrade_table( hdb );
3830     add_upgrade_entry( hdb, "'{3494EEEA-4221-4A66-802E-DED8916BC5C5}', NULL, '1.1.3', NULL, 0, NULL, 'OLDERVERSIONBEINGUPGRADED'");
3831     update_ProductCode_property( hdb, "{333DB27A-C25E-4EBC-9BEC-0F49546C19A6}" );
3832     update_ProductVersion_property( hdb, "1.1.3" );
3833     set_summary_str(hdb, PID_REVNUMBER, "{5F99011C-02E6-48BD-8B8D-DE7CFABC7A09}");
3834     r = MsiDatabaseCommit(hdb);
3835     ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed: %d\n", r);
3836     MsiCloseHandle(hdb);
3837 
3838     r = MsiInstallProductA(msifile2, "");
3839     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3840 
3841     r = MsiOpenProductA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", &hprod);
3842     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3843     r = MsiOpenProductA("{333DB27A-C25E-4EBC-9BEC-0F49546C19A6}", &hprod);
3844     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3845     size = MAX_PATH;
3846     r = MsiGetProductPropertyA(hprod, "ProductVersion", value, &size);
3847     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3848     ok(!strcmp(value, "1.1.3"), "ProductVersion = %s\n", value);
3849     MsiCloseHandle(hprod);
3850 
3851     /* uninstall the product */
3852     r = MsiInstallProductA(msifile2, "REMOVE=ALL");
3853     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3854 
3855     DeleteFileA(msifile);
3856     DeleteFileA(msifile2);
3857     DeleteFileA(msifile3);
3858     DeleteFileA(msifile4);
3859 }
3860 
3861 static void test_removefiles(void)
3862 {
3863     MSIHANDLE hpkg;
3864     UINT r;
3865     MSIHANDLE hdb;
3866     INSTALLSTATE installed, action;
3867 
3868     hdb = create_package_db();
3869     ok ( hdb, "failed to create package database\n" );
3870 
3871     add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'");
3872 
3873     create_feature_table( hdb );
3874     add_feature_entry( hdb, "'one', '', '', '', 2, 1, '', 0" );
3875 
3876     create_component_table( hdb );
3877     add_component_entry( hdb, "'hydrogen', '', 'TARGETDIR', 0, '', 'hydrogen_file'" );
3878     add_component_entry( hdb, "'helium', '', 'TARGETDIR', 0, '', 'helium_file'" );
3879     add_component_entry( hdb, "'lithium', '', 'TARGETDIR', 0, '', 'lithium_file'" );
3880     add_component_entry( hdb, "'beryllium', '', 'TARGETDIR', 0, '', 'beryllium_file'" );
3881     add_component_entry( hdb, "'boron', '', 'TARGETDIR', 0, '', 'boron_file'" );
3882     add_component_entry( hdb, "'carbon', '', 'TARGETDIR', 0, '', 'carbon_file'" );
3883     add_component_entry( hdb, "'oxygen', '', 'TARGETDIR', 0, '0', 'oxygen_file'" );
3884 
3885     create_feature_components_table( hdb );
3886     add_feature_components_entry( hdb, "'one', 'hydrogen'" );
3887     add_feature_components_entry( hdb, "'one', 'helium'" );
3888     add_feature_components_entry( hdb, "'one', 'lithium'" );
3889     add_feature_components_entry( hdb, "'one', 'beryllium'" );
3890     add_feature_components_entry( hdb, "'one', 'boron'" );
3891     add_feature_components_entry( hdb, "'one', 'carbon'" );
3892     add_feature_components_entry( hdb, "'one', 'oxygen'" );
3893 
3894     create_file_table( hdb );
3895     add_file_entry( hdb, "'hydrogen_file', 'hydrogen', 'hydrogen.txt', 0, '', '1033', 8192, 1" );
3896     add_file_entry( hdb, "'helium_file', 'helium', 'helium.txt', 0, '', '1033', 8192, 1" );
3897     add_file_entry( hdb, "'lithium_file', 'lithium', 'lithium.txt', 0, '', '1033', 8192, 1" );
3898     add_file_entry( hdb, "'beryllium_file', 'beryllium', 'beryllium.txt', 0, '', '1033', 16384, 1" );
3899     add_file_entry( hdb, "'boron_file', 'boron', 'boron.txt', 0, '', '1033', 16384, 1" );
3900     add_file_entry( hdb, "'carbon_file', 'carbon', 'carbon.txt', 0, '', '1033', 16384, 1" );
3901     add_file_entry( hdb, "'oxygen_file', 'oxygen', 'oxygen.txt', 0, '', '1033', 16384, 1" );
3902 
3903     create_remove_file_table( hdb );
3904 
3905     r = package_from_db( hdb, &hpkg );
3906     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
3907     {
3908         skip("Not enough rights to perform tests\n");
3909         DeleteFileA(msifile);
3910         return;
3911     }
3912     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3913 
3914     MsiCloseHandle( hdb );
3915 
3916     create_test_file( "hydrogen.txt" );
3917     create_test_file( "helium.txt" );
3918     create_test_file( "lithium.txt" );
3919     create_test_file( "beryllium.txt" );
3920     create_test_file( "boron.txt" );
3921     create_test_file( "carbon.txt" );
3922     create_test_file( "oxygen.txt" );
3923 
3924     r = MsiSetPropertyA( hpkg, "TARGETDIR", CURR_DIR );
3925     ok( r == ERROR_SUCCESS, "set property failed\n");
3926 
3927     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3928 
3929     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3930     ok( r == ERROR_UNKNOWN_COMPONENT, "expected ERROR_UNKNOWN_COMPONENT, got %u\n", r );
3931 
3932     r = MsiDoActionA( hpkg, "CostInitialize");
3933     ok( r == ERROR_SUCCESS, "cost init failed\n");
3934 
3935     r = MsiDoActionA( hpkg, "FileCost");
3936     ok( r == ERROR_SUCCESS, "file cost failed\n");
3937 
3938     installed = action = 0xdeadbeef;
3939     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3940     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3941     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3942     ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3943 
3944     r = MsiDoActionA( hpkg, "CostFinalize");
3945     ok( r == ERROR_SUCCESS, "cost finalize failed\n");
3946 
3947     r = MsiDoActionA( hpkg, "InstallValidate");
3948     ok( r == ERROR_SUCCESS, "install validate failed\n");
3949 
3950     r = MsiSetComponentStateA( hpkg, "hydrogen", INSTALLSTATE_ABSENT );
3951     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3952 
3953     installed = action = 0xdeadbeef;
3954     r = MsiGetComponentStateA( hpkg, "hydrogen", &installed, &action );
3955     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3956     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3957     todo_wine ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3958 
3959     r = MsiSetComponentStateA( hpkg, "helium", INSTALLSTATE_LOCAL );
3960     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3961 
3962     r = MsiSetComponentStateA( hpkg, "lithium", INSTALLSTATE_SOURCE );
3963     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3964 
3965     r = MsiSetComponentStateA( hpkg, "beryllium", INSTALLSTATE_ABSENT );
3966     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3967 
3968     r = MsiSetComponentStateA( hpkg, "boron", INSTALLSTATE_LOCAL );
3969     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3970 
3971     r = MsiSetComponentStateA( hpkg, "carbon", INSTALLSTATE_SOURCE );
3972     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3973 
3974     installed = action = 0xdeadbeef;
3975     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3976     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3977     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3978     ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3979 
3980     r = MsiSetComponentStateA( hpkg, "oxygen", INSTALLSTATE_ABSENT );
3981     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3982 
3983     installed = action = 0xdeadbeef;
3984     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3985     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3986     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3987     ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3988 
3989     r = MsiDoActionA( hpkg, "RemoveFiles");
3990     ok( r == ERROR_SUCCESS, "remove files failed\n");
3991 
3992     installed = action = 0xdeadbeef;
3993     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3994     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3995     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3996     ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3997 
3998     ok(DeleteFileA("hydrogen.txt"), "Expected hydrogen.txt to exist\n");
3999     ok(DeleteFileA("lithium.txt"), "Expected lithium.txt to exist\n");
4000     ok(DeleteFileA("beryllium.txt"), "Expected beryllium.txt to exist\n");
4001     ok(DeleteFileA("carbon.txt"), "Expected carbon.txt to exist\n");
4002     ok(DeleteFileA("helium.txt"), "Expected helium.txt to exist\n");
4003     ok(DeleteFileA("boron.txt"), "Expected boron.txt to exist\n");
4004     ok(DeleteFileA("oxygen.txt"), "Expected oxygen.txt to exist\n");
4005 
4006     MsiCloseHandle( hpkg );
4007     DeleteFileA(msifile);
4008 }
4009 
4010 static void test_appsearch(void)
4011 {
4012     MSIHANDLE hpkg;
4013     UINT r;
4014     MSIHANDLE hdb;
4015     CHAR prop[MAX_PATH];
4016     DWORD size;
4017     HKEY hkey;
4018     const char reg_expand_value[] = "%systemroot%\\system32\\notepad.exe";
4019 
4020     hdb = create_package_db();
4021     ok ( hdb, "failed to create package database\n" );
4022 
4023     create_appsearch_table( hdb );
4024     add_appsearch_entry( hdb, "'WEBBROWSERPROG', 'NewSignature1'" );
4025     add_appsearch_entry( hdb, "'NOTEPAD', 'NewSignature2'" );
4026     add_appsearch_entry( hdb, "'REGEXPANDVAL', 'NewSignature3'" );
4027     add_appsearch_entry( hdb, "'32KEYVAL', 'NewSignature4'" );
4028     add_appsearch_entry( hdb, "'64KEYVAL', 'NewSignature5'" );
4029 
4030     create_reglocator_table( hdb );
4031     add_reglocator_entry( hdb, "NewSignature1", 0, "htmlfile\\shell\\open\\command", "", 1 );
4032 
4033     r = RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Winetest_msi", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, NULL);
4034     ok( r == ERROR_SUCCESS, "Could not create key: %d.\n", r );
4035     r = RegSetValueExA(hkey, NULL, 0, REG_EXPAND_SZ, (const BYTE*)reg_expand_value, strlen(reg_expand_value) + 1);
4036     ok( r == ERROR_SUCCESS, "Could not set key value: %d.\n", r);
4037     RegCloseKey(hkey);
4038     add_reglocator_entry( hdb, "NewSignature3", 1, "Software\\Winetest_msi", "", msidbLocatorTypeFileName );
4039 
4040     r = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\Winetest_msi", 0, NULL, 0, KEY_ALL_ACCESS|KEY_WOW64_32KEY,
4041                         NULL, &hkey, NULL);
4042     if (r == ERROR_ACCESS_DENIED)
4043     {
4044         skip("insufficient rights\n");
4045         RegDeleteKeyA(HKEY_CURRENT_USER, "Software\\Winetest_msi");
4046         MsiCloseHandle(hdb);
4047         DeleteFileA(msifile);
4048         return;
4049     }
4050     ok( r == ERROR_SUCCESS, "Could not create key: %d.\n", r );
4051 
4052     r = RegSetValueExA(hkey, NULL, 0, REG_SZ, (const BYTE *)"c:\\windows\\system32\\notepad.exe",
4053                        sizeof("c:\\windows\\system32\\notepad.exe"));
4054     ok( r == ERROR_SUCCESS, "Could not set key value: %d.\n", r);
4055     RegCloseKey(hkey);
4056     add_reglocator_entry( hdb, "NewSignature4", 2, "Software\\Winetest_msi", "", msidbLocatorTypeFileName );
4057 
4058     r = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\Winetest_msi", 0, NULL, 0, KEY_ALL_ACCESS|KEY_WOW64_64KEY,
4059                         NULL, &hkey, NULL);
4060     ok( r == ERROR_SUCCESS, "Could not create key: %d.\n", r );
4061     r = RegSetValueExA(hkey, NULL, 0, REG_SZ, (const BYTE *)"c:\\windows\\system32\\notepad.exe",
4062                        sizeof("c:\\windows\\system32\\notepad.exe"));
4063     ok( r == ERROR_SUCCESS, "Could not set key value: %d.\n", r);
4064     RegCloseKey(hkey);
4065     add_reglocator_entry( hdb, "NewSignature5", 2, "Software\\Winetest_msi", "",
4066                           msidbLocatorTypeFileName|msidbLocatorType64bit );
4067 
4068     create_drlocator_table( hdb );
4069     add_drlocator_entry( hdb, "'NewSignature2', 0, 'c:\\windows\\system32', 0" );
4070 
4071     create_signature_table( hdb );
4072     add_signature_entry( hdb, "'NewSignature1', 'FileName', '', '', '', '', '', '', ''" );
4073     add_signature_entry( hdb, "'NewSignature2', 'NOTEPAD.EXE|notepad.exe', '', '', '', '', '', '', ''" );
4074     add_signature_entry( hdb, "'NewSignature3', 'NOTEPAD.EXE|notepad.exe', '', '', '', '', '', '', ''" );
4075     add_signature_entry( hdb, "'NewSignature4', 'NOTEPAD.EXE|notepad.exe', '', '', '', '', '', '', ''" );
4076     add_signature_entry( hdb, "'NewSignature5', 'NOTEPAD.EXE|notepad.exe', '', '', '', '', '', '', ''" );
4077 
4078     r = package_from_db( hdb, &hpkg );
4079     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
4080     {
4081         skip("Not enough rights to perform tests\n");
4082         DeleteFileA(msifile);
4083         return;
4084     }
4085     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
4086     MsiCloseHandle( hdb );
4087     if (r != ERROR_SUCCESS)
4088         goto done;
4089 
4090     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4091 
4092     r = MsiDoActionA( hpkg, "AppSearch" );
4093     ok( r == ERROR_SUCCESS, "AppSearch failed: %d\n", r);
4094 
4095     size = sizeof(prop);
4096     r = MsiGetPropertyA( hpkg, "WEBBROWSERPROG", prop, &size );
4097     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
4098     ok( lstrlenA(prop) != 0, "Expected non-zero length\n");
4099 
4100     size = sizeof(prop);
4101     r = MsiGetPropertyA( hpkg, "NOTEPAD", prop, &size );
4102     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
4103 
4104     size = sizeof(prop);
4105     r = MsiGetPropertyA( hpkg, "REGEXPANDVAL", prop, &size );
4106     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
4107     ok( lstrlenA(prop) != 0, "Expected non-zero length\n");
4108 
4109     size = sizeof(prop);
4110     r = MsiGetPropertyA( hpkg, "32KEYVAL", prop, &size );
4111     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
4112     ok( lstrlenA(prop) != 0, "Expected non-zero length\n");
4113 
4114     size = sizeof(prop);
4115     r = MsiGetPropertyA( hpkg, "64KEYVAL", prop, &size );
4116     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
4117     ok( lstrlenA(prop) != 0, "Expected non-zero length\n");
4118 
4119 done:
4120     MsiCloseHandle( hpkg );
4121     DeleteFileA(msifile);
4122     RegDeleteKeyA(HKEY_CURRENT_USER, "Software\\Winetest_msi");
4123     delete_key(HKEY_LOCAL_MACHINE, "Software\\Winetest_msi", KEY_WOW64_32KEY);
4124     delete_key(HKEY_LOCAL_MACHINE, "Software\\Winetest_msi", KEY_WOW64_64KEY);
4125 }
4126 
4127 static void test_appsearch_complocator(void)
4128 {
4129     MSIHANDLE hpkg, hdb;
4130     char path[MAX_PATH + 15], expected[MAX_PATH], prop[MAX_PATH];
4131     LPSTR usersid;
4132     DWORD size;
4133     UINT r;
4134 
4135     if (!(usersid = get_user_sid()))
4136         return;
4137 
4138     if (is_process_limited())
4139     {
4140         skip("process is limited\n");
4141         return;
4142     }
4143 
4144     create_test_file("FileName1");
4145     create_test_file("FileName4");
4146     set_component_path("FileName1", MSIINSTALLCONTEXT_MACHINE,
4147                        "{A8AE6692-96BA-4198-8399-145D7D1D0D0E}", NULL, FALSE);
4148 
4149     create_test_file("FileName2");
4150     set_component_path("FileName2", MSIINSTALLCONTEXT_USERUNMANAGED,
4151                        "{1D2CE6F3-E81C-4949-AB81-78D7DAD2AF2E}", usersid, FALSE);
4152 
4153     create_test_file("FileName3");
4154     set_component_path("FileName3", MSIINSTALLCONTEXT_USERMANAGED,
4155                        "{19E0B999-85F5-4973-A61B-DBE4D66ECB1D}", usersid, FALSE);
4156 
4157     create_test_file("FileName5");
4158     set_component_path("FileName5", MSIINSTALLCONTEXT_MACHINE,
4159                        "{F0CCA976-27A3-4808-9DDD-1A6FD50A0D5A}", NULL, TRUE);
4160 
4161     create_test_file("FileName6");
4162     set_component_path("FileName6", MSIINSTALLCONTEXT_MACHINE,
4163                        "{C0ECD96F-7898-4410-9667-194BD8C1B648}", NULL, TRUE);
4164 
4165     create_test_file("FileName7");
4166     set_component_path("FileName7", MSIINSTALLCONTEXT_MACHINE,
4167                        "{DB20F535-9C26-4127-9C2B-CC45A8B51DA1}", NULL, FALSE);
4168 
4169     /* dir is FALSE, but we're pretending it's a directory */
4170     set_component_path("IDontExist\\", MSIINSTALLCONTEXT_MACHINE,
4171                        "{91B7359B-07F2-4221-AA8D-DE102BB87A5F}", NULL, FALSE);
4172 
4173     create_file_with_version("FileName8.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4174     set_component_path("FileName8.dll", MSIINSTALLCONTEXT_MACHINE,
4175                        "{4A2E1B5B-4034-4177-833B-8CC35F1B3EF1}", NULL, FALSE);
4176 
4177     create_file_with_version("FileName9.dll", MAKELONG(1, 2), MAKELONG(3, 4));
4178     set_component_path("FileName9.dll", MSIINSTALLCONTEXT_MACHINE,
4179                        "{A204DF48-7346-4635-BA2E-66247DBAC9DF}", NULL, FALSE);
4180 
4181     create_file_with_version("FileName10.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4182     set_component_path("FileName10.dll", MSIINSTALLCONTEXT_MACHINE,
4183                        "{EC30CE73-4CF9-4908-BABD-1ED82E1515FD}", NULL, FALSE);
4184 
4185     hdb = create_package_db();
4186     ok(hdb, "Expected a valid database handle\n");
4187 
4188     create_appsearch_table(hdb);
4189     add_appsearch_entry(hdb, "'SIGPROP1', 'NewSignature1'");
4190     add_appsearch_entry(hdb, "'SIGPROP2', 'NewSignature2'");
4191     add_appsearch_entry(hdb, "'SIGPROP3', 'NewSignature3'");
4192     add_appsearch_entry(hdb, "'SIGPROP4', 'NewSignature4'");
4193     add_appsearch_entry(hdb, "'SIGPROP5', 'NewSignature5'");
4194     add_appsearch_entry(hdb, "'SIGPROP6', 'NewSignature6'");
4195     add_appsearch_entry(hdb, "'SIGPROP7', 'NewSignature7'");
4196     add_appsearch_entry(hdb, "'SIGPROP8', 'NewSignature8'");
4197     add_appsearch_entry(hdb, "'SIGPROP9', 'NewSignature9'");
4198     add_appsearch_entry(hdb, "'SIGPROP10', 'NewSignature10'");
4199     add_appsearch_entry(hdb, "'SIGPROP11', 'NewSignature11'");
4200     add_appsearch_entry(hdb, "'SIGPROP12', 'NewSignature12'");
4201 
4202     create_complocator_table(hdb);
4203 
4204     /* published component, machine, file, signature, misdbLocatorTypeFile */
4205     add_complocator_entry(hdb, "'NewSignature1', '{A8AE6692-96BA-4198-8399-145D7D1D0D0E}', 1");
4206 
4207     /* published component, user-unmanaged, file, signature, misdbLocatorTypeFile */
4208     add_complocator_entry(hdb, "'NewSignature2', '{1D2CE6F3-E81C-4949-AB81-78D7DAD2AF2E}', 1");
4209 
4210     /* published component, user-managed, file, signature, misdbLocatorTypeFile */
4211     add_complocator_entry(hdb, "'NewSignature3', '{19E0B999-85F5-4973-A61B-DBE4D66ECB1D}', 1");
4212 
4213     /* published component, machine, file, signature, misdbLocatorTypeDirectory */
4214     add_complocator_entry(hdb, "'NewSignature4', '{A8AE6692-96BA-4198-8399-145D7D1D0D0E}', 0");
4215 
4216     /* published component, machine, dir, signature, misdbLocatorTypeDirectory */
4217     add_complocator_entry(hdb, "'NewSignature5', '{F0CCA976-27A3-4808-9DDD-1A6FD50A0D5A}', 0");
4218 
4219     /* published component, machine, dir, no signature, misdbLocatorTypeDirectory */
4220     add_complocator_entry(hdb, "'NewSignature6', '{C0ECD96F-7898-4410-9667-194BD8C1B648}', 0");
4221 
4222     /* published component, machine, file, no signature, misdbLocatorTypeFile */
4223     add_complocator_entry(hdb, "'NewSignature7', '{DB20F535-9C26-4127-9C2B-CC45A8B51DA1}', 1");
4224 
4225     /* unpublished component, no signature, misdbLocatorTypeDir */
4226     add_complocator_entry(hdb, "'NewSignature8', '{FB671D5B-5083-4048-90E0-481C48D8F3A5}', 0");
4227 
4228     /* published component, no signature, dir does not exist misdbLocatorTypeDir */
4229     add_complocator_entry(hdb, "'NewSignature9', '{91B7359B-07F2-4221-AA8D-DE102BB87A5F}', 0");
4230 
4231     /* published component, signature w/ ver, misdbLocatorTypeFile */
4232     add_complocator_entry(hdb, "'NewSignature10', '{4A2E1B5B-4034-4177-833B-8CC35F1B3EF1}', 1");
4233 
4234     /* published component, signature w/ ver, ver > max, misdbLocatorTypeFile */
4235     add_complocator_entry(hdb, "'NewSignature11', '{A204DF48-7346-4635-BA2E-66247DBAC9DF}', 1");
4236 
4237     /* published component, signature w/ ver, sig->name ignored, misdbLocatorTypeFile */
4238     add_complocator_entry(hdb, "'NewSignature12', '{EC30CE73-4CF9-4908-BABD-1ED82E1515FD}', 1");
4239 
4240     create_signature_table(hdb);
4241     add_signature_entry(hdb, "'NewSignature1', 'FileName1', '', '', '', '', '', '', ''");
4242     add_signature_entry(hdb, "'NewSignature2', 'FileName2', '', '', '', '', '', '', ''");
4243     add_signature_entry(hdb, "'NewSignature3', 'FileName3', '', '', '', '', '', '', ''");
4244     add_signature_entry(hdb, "'NewSignature4', 'FileName4', '', '', '', '', '', '', ''");
4245     add_signature_entry(hdb, "'NewSignature5', 'FileName5', '', '', '', '', '', '', ''");
4246     add_signature_entry(hdb, "'NewSignature10', 'FileName8.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4247     add_signature_entry(hdb, "'NewSignature11', 'FileName9.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4248     add_signature_entry(hdb, "'NewSignature12', 'ignored', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4249 
4250     r = package_from_db(hdb, &hpkg);
4251     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
4252     {
4253         skip("Not enough rights to perform tests\n");
4254         goto error;
4255     }
4256     ok(r == ERROR_SUCCESS, "Expected a valid package handle %u\n", r);
4257 
4258     r = MsiSetPropertyA(hpkg, "SIGPROP8", "october");
4259     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4260 
4261     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4262 
4263     r = MsiDoActionA(hpkg, "AppSearch");
4264     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4265 
4266     strcpy(expected, CURR_DIR);
4267     if (is_root(CURR_DIR)) expected[2] = 0;
4268 
4269     size = MAX_PATH;
4270     sprintf(path, "%s\\FileName1", expected);
4271     r = MsiGetPropertyA(hpkg, "SIGPROP1", prop, &size);
4272     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4273     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4274 
4275     size = MAX_PATH;
4276     sprintf(path, "%s\\FileName2", expected);
4277     r = MsiGetPropertyA(hpkg, "SIGPROP2", prop, &size);
4278     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4279     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4280 
4281     size = MAX_PATH;
4282     sprintf(path, "%s\\FileName3", expected);
4283     r = MsiGetPropertyA(hpkg, "SIGPROP3", prop, &size);
4284     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4285     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4286 
4287     size = MAX_PATH;
4288     sprintf(path, "%s\\FileName4", expected);
4289     r = MsiGetPropertyA(hpkg, "SIGPROP4", prop, &size);
4290     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4291     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4292 
4293     size = MAX_PATH;
4294     sprintf(path, "%s\\FileName5", expected);
4295     r = MsiGetPropertyA(hpkg, "SIGPROP5", prop, &size);
4296     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4297     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4298 
4299     size = MAX_PATH;
4300     sprintf(path, "%s\\", expected);
4301     r = MsiGetPropertyA(hpkg, "SIGPROP6", prop, &size);
4302     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4303     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4304 
4305     size = MAX_PATH;
4306     sprintf(path, "%s\\", expected);
4307     r = MsiGetPropertyA(hpkg, "SIGPROP7", prop, &size);
4308     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4309     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4310 
4311     size = MAX_PATH;
4312     r = MsiGetPropertyA(hpkg, "SIGPROP8", prop, &size);
4313     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4314     ok(!lstrcmpA(prop, "october"), "Expected \"october\", got \"%s\"\n", prop);
4315 
4316     size = MAX_PATH;
4317     r = MsiGetPropertyA(hpkg, "SIGPROP9", prop, &size);
4318     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4319     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4320 
4321     size = MAX_PATH;
4322     sprintf(path, "%s\\FileName8.dll", expected);
4323     r = MsiGetPropertyA(hpkg, "SIGPROP10", prop, &size);
4324     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4325     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4326 
4327     size = MAX_PATH;
4328     r = MsiGetPropertyA(hpkg, "SIGPROP11", prop, &size);
4329     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4330     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4331 
4332     size = MAX_PATH;
4333     sprintf(path, "%s\\FileName10.dll", expected);
4334     r = MsiGetPropertyA(hpkg, "SIGPROP12", prop, &size);
4335     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4336     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4337 
4338     delete_component_path("{A8AE6692-96BA-4198-8399-145D7D1D0D0E}",
4339                           MSIINSTALLCONTEXT_MACHINE, NULL);
4340     delete_component_path("{1D2CE6F3-E81C-4949-AB81-78D7DAD2AF2E}",
4341                           MSIINSTALLCONTEXT_USERUNMANAGED, usersid);
4342     delete_component_path("{19E0B999-85F5-4973-A61B-DBE4D66ECB1D}",
4343                           MSIINSTALLCONTEXT_USERMANAGED, usersid);
4344     delete_component_path("{F0CCA976-27A3-4808-9DDD-1A6FD50A0D5A}",
4345                           MSIINSTALLCONTEXT_MACHINE, NULL);
4346     delete_component_path("{C0ECD96F-7898-4410-9667-194BD8C1B648}",
4347                           MSIINSTALLCONTEXT_MACHINE, NULL);
4348     delete_component_path("{DB20F535-9C26-4127-9C2B-CC45A8B51DA1}",
4349                           MSIINSTALLCONTEXT_MACHINE, NULL);
4350     delete_component_path("{91B7359B-07F2-4221-AA8D-DE102BB87A5F}",
4351                           MSIINSTALLCONTEXT_MACHINE, NULL);
4352     delete_component_path("{4A2E1B5B-4034-4177-833B-8CC35F1B3EF1}",
4353                           MSIINSTALLCONTEXT_MACHINE, NULL);
4354     delete_component_path("{A204DF48-7346-4635-BA2E-66247DBAC9DF}",
4355                           MSIINSTALLCONTEXT_MACHINE, NULL);
4356     delete_component_path("{EC30CE73-4CF9-4908-BABD-1ED82E1515FD}",
4357                           MSIINSTALLCONTEXT_MACHINE, NULL);
4358 
4359     MsiCloseHandle(hpkg);
4360 
4361 error:
4362     DeleteFileA("FileName1");
4363     DeleteFileA("FileName2");
4364     DeleteFileA("FileName3");
4365     DeleteFileA("FileName4");
4366     DeleteFileA("FileName5");
4367     DeleteFileA("FileName6");
4368     DeleteFileA("FileName7");
4369     DeleteFileA("FileName8.dll");
4370     DeleteFileA("FileName9.dll");
4371     DeleteFileA("FileName10.dll");
4372     DeleteFileA(msifile);
4373     LocalFree(usersid);
4374 }
4375 
4376 static void test_appsearch_reglocator(void)
4377 {
4378     MSIHANDLE hpkg, hdb;
4379     char path[MAX_PATH + 20], expected[MAX_PATH], prop[MAX_PATH];
4380     DWORD binary[2], size, val;
4381     BOOL space, version, is_64bit = sizeof(void *) > sizeof(int);
4382     HKEY hklm, classes, hkcu, users;
4383     LPSTR pathdata, pathvar, ptr;
4384     LONG res;
4385     UINT r, type = 0;
4386     SYSTEM_INFO si;
4387 
4388     version = TRUE;
4389     if (!create_file_with_version("test.dll", MAKELONG(2, 1), MAKELONG(4, 3)))
4390         version = FALSE;
4391 
4392     DeleteFileA("test.dll");
4393 
4394     res = RegCreateKeyA(HKEY_CLASSES_ROOT, "Software\\Wine", &classes);
4395     if (res == ERROR_ACCESS_DENIED)
4396     {
4397         skip("Not enough rights to perform tests\n");
4398         return;
4399     }
4400     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4401 
4402     res = RegSetValueExA(classes, "Value1", 0, REG_SZ,
4403                          (const BYTE *)"regszdata", 10);
4404     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4405 
4406     res = RegCreateKeyA(HKEY_CURRENT_USER, "Software\\Wine", &hkcu);
4407     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4408 
4409     res = RegSetValueExA(hkcu, "Value1", 0, REG_SZ,
4410                          (const BYTE *)"regszdata", 10);
4411     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4412 
4413     users = 0;
4414     res = RegCreateKeyA(HKEY_USERS, "S-1-5-18\\Software\\Wine", &users);
4415     ok(res == ERROR_SUCCESS ||
4416        broken(res == ERROR_INVALID_PARAMETER),
4417        "Expected ERROR_SUCCESS, got %ld\n", res);
4418 
4419     if (res == ERROR_SUCCESS)
4420     {
4421         res = RegSetValueExA(users, "Value1", 0, REG_SZ,
4422                              (const BYTE *)"regszdata", 10);
4423         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4424     }
4425 
4426     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine", &hklm);
4427     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4428 
4429     res = RegSetValueA(hklm, NULL, REG_SZ, "defvalue", 8);
4430     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4431 
4432     res = RegSetValueExA(hklm, "Value1", 0, REG_SZ,
4433                          (const BYTE *)"regszdata", 10);
4434     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4435 
4436     val = 42;
4437     res = RegSetValueExA(hklm, "Value2", 0, REG_DWORD,
4438                          (const BYTE *)&val, sizeof(DWORD));
4439     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4440 
4441     val = -42;
4442     res = RegSetValueExA(hklm, "Value3", 0, REG_DWORD,
4443                          (const BYTE *)&val, sizeof(DWORD));
4444     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4445 
4446     res = RegSetValueExA(hklm, "Value4", 0, REG_EXPAND_SZ,
4447                          (const BYTE *)"%PATH%", 7);
4448     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4449 
4450     res = RegSetValueExA(hklm, "Value5", 0, REG_EXPAND_SZ,
4451                          (const BYTE *)"my%NOVAR%", 10);
4452     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4453 
4454     res = RegSetValueExA(hklm, "Value6", 0, REG_MULTI_SZ,
4455                          (const BYTE *)"one\0two\0", 9);
4456     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4457 
4458     binary[0] = 0x1234abcd;
4459     binary[1] = 0x567890ef;
4460     res = RegSetValueExA(hklm, "Value7", 0, REG_BINARY,
4461                          (const BYTE *)binary, sizeof(binary));
4462     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4463 
4464     res = RegSetValueExA(hklm, "Value8", 0, REG_SZ,
4465                          (const BYTE *)"#regszdata", 11);
4466     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4467 
4468     strcpy(expected, CURR_DIR);
4469     if (is_root(CURR_DIR)) expected[2] = 0;
4470 
4471     create_test_file("FileName1");
4472     sprintf(path, "%s\\FileName1", expected);
4473     res = RegSetValueExA(hklm, "Value9", 0, REG_SZ,
4474                          (const BYTE *)path, lstrlenA(path) + 1);
4475     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4476 
4477     sprintf(path, "%s\\FileName2", expected);
4478     res = RegSetValueExA(hklm, "Value10", 0, REG_SZ,
4479                          (const BYTE *)path, lstrlenA(path) + 1);
4480     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4481 
4482     lstrcpyA(path, expected);
4483     res = RegSetValueExA(hklm, "Value11", 0, REG_SZ,
4484                          (const BYTE *)path, lstrlenA(path) + 1);
4485     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4486 
4487     res = RegSetValueExA(hklm, "Value12", 0, REG_SZ,
4488                          (const BYTE *)"", 1);
4489     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4490 
4491     create_file_with_version("FileName3.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4492     sprintf(path, "%s\\FileName3.dll", expected);
4493     res = RegSetValueExA(hklm, "Value13", 0, REG_SZ,
4494                          (const BYTE *)path, lstrlenA(path) + 1);
4495     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4496 
4497     create_file_with_version("FileName4.dll", MAKELONG(1, 2), MAKELONG(3, 4));
4498     sprintf(path, "%s\\FileName4.dll", expected);
4499     res = RegSetValueExA(hklm, "Value14", 0, REG_SZ,
4500                          (const BYTE *)path, lstrlenA(path) + 1);
4501     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4502 
4503     create_file_with_version("FileName5.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4504     sprintf(path, "%s\\FileName5.dll", expected);
4505     res = RegSetValueExA(hklm, "Value15", 0, REG_SZ,
4506                          (const BYTE *)path, lstrlenA(path) + 1);
4507     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4508 
4509     sprintf(path, "\"%s\\FileName1\" -option", expected);
4510     res = RegSetValueExA(hklm, "value16", 0, REG_SZ,
4511                          (const BYTE *)path, lstrlenA(path) + 1);
4512     ok( res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %ld\n", res);
4513 
4514     space = strchr(expected, ' ') != NULL;
4515     sprintf(path, "%s\\FileName1 -option", expected);
4516     res = RegSetValueExA(hklm, "value17", 0, REG_SZ,
4517                          (const BYTE *)path, lstrlenA(path) + 1);
4518     ok( res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %ld\n", res);
4519 
4520     hdb = create_package_db();
4521     ok(hdb, "Expected a valid database handle\n");
4522 
4523     create_appsearch_table(hdb);
4524     add_appsearch_entry(hdb, "'SIGPROP1', 'NewSignature1'");
4525     add_appsearch_entry(hdb, "'SIGPROP2', 'NewSignature2'");
4526     add_appsearch_entry(hdb, "'SIGPROP3', 'NewSignature3'");
4527     add_appsearch_entry(hdb, "'SIGPROP4', 'NewSignature4'");
4528     add_appsearch_entry(hdb, "'SIGPROP5', 'NewSignature5'");
4529     add_appsearch_entry(hdb, "'SIGPROP6', 'NewSignature6'");
4530     add_appsearch_entry(hdb, "'SIGPROP7', 'NewSignature7'");
4531     add_appsearch_entry(hdb, "'SIGPROP8', 'NewSignature8'");
4532     add_appsearch_entry(hdb, "'SIGPROP9', 'NewSignature9'");
4533     add_appsearch_entry(hdb, "'SIGPROP10', 'NewSignature10'");
4534     add_appsearch_entry(hdb, "'SIGPROP11', 'NewSignature11'");
4535     add_appsearch_entry(hdb, "'SIGPROP12', 'NewSignature12'");
4536     add_appsearch_entry(hdb, "'SIGPROP13', 'NewSignature13'");
4537     add_appsearch_entry(hdb, "'SIGPROP14', 'NewSignature14'");
4538     add_appsearch_entry(hdb, "'SIGPROP15', 'NewSignature15'");
4539     add_appsearch_entry(hdb, "'SIGPROP16', 'NewSignature16'");
4540     add_appsearch_entry(hdb, "'SIGPROP17', 'NewSignature17'");
4541     add_appsearch_entry(hdb, "'SIGPROP18', 'NewSignature18'");
4542     add_appsearch_entry(hdb, "'SIGPROP19', 'NewSignature19'");
4543     add_appsearch_entry(hdb, "'SIGPROP20', 'NewSignature20'");
4544     add_appsearch_entry(hdb, "'SIGPROP21', 'NewSignature21'");
4545     add_appsearch_entry(hdb, "'SIGPROP22', 'NewSignature22'");
4546     add_appsearch_entry(hdb, "'SIGPROP23', 'NewSignature23'");
4547     add_appsearch_entry(hdb, "'SIGPROP24', 'NewSignature24'");
4548     add_appsearch_entry(hdb, "'SIGPROP25', 'NewSignature25'");
4549     add_appsearch_entry(hdb, "'SIGPROP26', 'NewSignature26'");
4550     add_appsearch_entry(hdb, "'SIGPROP27', 'NewSignature27'");
4551     add_appsearch_entry(hdb, "'SIGPROP28', 'NewSignature28'");
4552     add_appsearch_entry(hdb, "'SIGPROP29', 'NewSignature29'");
4553     add_appsearch_entry(hdb, "'SIGPROP30', 'NewSignature30'");
4554 
4555     create_reglocator_table(hdb);
4556 
4557     type = msidbLocatorTypeRawValue;
4558     if (is_64bit)
4559         type |= msidbLocatorType64bit;
4560 
4561     /* HKLM, msidbLocatorTypeRawValue, REG_SZ */
4562     add_reglocator_entry(hdb, "NewSignature1", 2, "Software\\Wine", "Value1", type);
4563 
4564     /* HKLM, msidbLocatorTypeRawValue, positive DWORD */
4565     add_reglocator_entry(hdb, "NewSignature2", 2, "Software\\Wine", "Value2", type);
4566 
4567     /* HKLM, msidbLocatorTypeRawValue, negative DWORD */
4568     add_reglocator_entry(hdb, "NewSignature3", 2, "Software\\Wine", "Value3", type);
4569 
4570     /* HKLM, msidbLocatorTypeRawValue, REG_EXPAND_SZ */
4571     add_reglocator_entry(hdb, "NewSignature4", 2, "Software\\Wine", "Value4", type);
4572 
4573     /* HKLM, msidbLocatorTypeRawValue, REG_EXPAND_SZ */
4574     add_reglocator_entry(hdb, "NewSignature5", 2, "Software\\Wine", "Value5", type);
4575 
4576     /* HKLM, msidbLocatorTypeRawValue, REG_MULTI_SZ */
4577     add_reglocator_entry(hdb, "NewSignature6", 2, "Software\\Wine", "Value6", type);
4578 
4579     /* HKLM, msidbLocatorTypeRawValue, REG_BINARY */
4580     add_reglocator_entry(hdb, "NewSignature7", 2, "Software\\Wine", "Value7", type);
4581 
4582     /* HKLM, msidbLocatorTypeRawValue, REG_SZ first char is # */
4583     add_reglocator_entry(hdb, "NewSignature8", 2, "Software\\Wine", "Value8", type);
4584 
4585     type = msidbLocatorTypeFileName;
4586     if (is_64bit)
4587         type |= msidbLocatorType64bit;
4588 
4589     /* HKLM, msidbLocatorTypeFileName, signature, file exists */
4590     add_reglocator_entry(hdb, "NewSignature9", 2, "Software\\Wine", "Value9", type);
4591 
4592     /* HKLM, msidbLocatorTypeFileName, signature, file does not exist */
4593     add_reglocator_entry(hdb, "NewSignature10", 2, "Software\\Wine", "Value10", type);
4594 
4595     /* HKLM, msidbLocatorTypeFileName, no signature */
4596     add_reglocator_entry(hdb, "NewSignature11", 2, "Software\\Wine", "Value9", type);
4597 
4598     type = msidbLocatorTypeDirectory;
4599     if (is_64bit)
4600         type |= msidbLocatorType64bit;
4601 
4602     /* HKLM, msidbLocatorTypeDirectory, no signature, file exists */
4603     add_reglocator_entry(hdb, "NewSignature12", 2, "Software\\Wine", "Value9", type);
4604 
4605     /* HKLM, msidbLocatorTypeDirectory, no signature, directory exists */
4606     add_reglocator_entry(hdb, "NewSignature13", 2, "Software\\Wine", "Value11", type);
4607 
4608     /* HKLM, msidbLocatorTypeDirectory, signature, file exists */
4609     add_reglocator_entry(hdb, "NewSignature14", 2, "Software\\Wine", "Value9", type);
4610 
4611     type = msidbLocatorTypeRawValue;
4612     if (is_64bit)
4613         type |= msidbLocatorType64bit;
4614 
4615     /* HKCR, msidbLocatorTypeRawValue, REG_SZ */
4616     add_reglocator_entry(hdb, "NewSignature15", 0, "Software\\Wine", "Value1", type);
4617 
4618     /* HKCU, msidbLocatorTypeRawValue, REG_SZ */
4619     add_reglocator_entry(hdb, "NewSignature16", 1, "Software\\Wine", "Value1", type);
4620 
4621     /* HKU, msidbLocatorTypeRawValue, REG_SZ */
4622     add_reglocator_entry(hdb, "NewSignature17", 3, "S-1-5-18\\Software\\Wine", "Value1", type);
4623 
4624     /* HKLM, msidbLocatorTypeRawValue, REG_SZ, NULL Name */
4625     add_reglocator_entry(hdb, "NewSignature18", 2, "Software\\Wine", "", type);
4626 
4627     /* HKLM, msidbLocatorTypeRawValue, REG_SZ, key does not exist */
4628     add_reglocator_entry(hdb, "NewSignature19", 2, "Software\\IDontExist", "", type);
4629 
4630     /* HKLM, msidbLocatorTypeRawValue, REG_SZ, value is empty */
4631     add_reglocator_entry(hdb, "NewSignature20", 2, "Software\\Wine", "Value12", type);
4632 
4633     type = msidbLocatorTypeFileName;
4634     if (is_64bit)
4635         type |= msidbLocatorType64bit;
4636 
4637     /* HKLM, msidbLocatorTypeFileName, signature, file exists w/ version */
4638     add_reglocator_entry(hdb, "NewSignature21", 2, "Software\\Wine", "Value13", type);
4639 
4640     /* HKLM, msidbLocatorTypeFileName, file exists w/ version, version > max */
4641     add_reglocator_entry(hdb, "NewSignature22", 2, "Software\\Wine", "Value14", type);
4642 
4643     /* HKLM, msidbLocatorTypeFileName, file exists w/ version, sig->name ignored */
4644     add_reglocator_entry(hdb, "NewSignature23", 2, "Software\\Wine", "Value15", type);
4645 
4646     /* HKLM, msidbLocatorTypeFileName, no signature, directory exists */
4647     add_reglocator_entry(hdb, "NewSignature24", 2, "Software\\Wine", "Value11", type);
4648 
4649     /* HKLM, msidbLocatorTypeFileName, no signature, file does not exist */
4650     add_reglocator_entry(hdb, "NewSignature25", 2, "Software\\Wine", "Value10", type);
4651 
4652     type = msidbLocatorTypeDirectory;
4653     if (is_64bit)
4654         type |= msidbLocatorType64bit;
4655 
4656     /* HKLM, msidbLocatorTypeDirectory, signature, directory exists */
4657     add_reglocator_entry(hdb, "NewSignature26", 2, "Software\\Wine", "Value11", type);
4658 
4659     /* HKLM, msidbLocatorTypeDirectory, signature, file does not exist */
4660     add_reglocator_entry(hdb, "NewSignature27", 2, "Software\\Wine", "Value10", type);
4661 
4662     /* HKLM, msidbLocatorTypeDirectory, no signature, file does not exist */
4663     add_reglocator_entry(hdb, "NewSignature28", 2, "Software\\Wine", "Value10", type);
4664 
4665     type = msidbLocatorTypeFileName;
4666     if (is_64bit)
4667         type |= msidbLocatorType64bit;
4668 
4669     /* HKLM, msidbLocatorTypeFile, file exists, in quotes */
4670     add_reglocator_entry(hdb, "NewSignature29", 2, "Software\\Wine", "Value16", type);
4671 
4672     /* HKLM, msidbLocatorTypeFile, file exists, no quotes */
4673     add_reglocator_entry(hdb, "NewSignature30", 2, "Software\\Wine", "Value17", type);
4674 
4675     create_signature_table(hdb);
4676     add_signature_entry(hdb, "'NewSignature9', 'FileName1', '', '', '', '', '', '', ''");
4677     add_signature_entry(hdb, "'NewSignature10', 'FileName2', '', '', '', '', '', '', ''");
4678     add_signature_entry(hdb, "'NewSignature14', 'FileName1', '', '', '', '', '', '', ''");
4679     add_signature_entry(hdb, "'NewSignature21', 'FileName3.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4680     add_signature_entry(hdb, "'NewSignature22', 'FileName4.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4681     add_signature_entry(hdb, "'NewSignature23', 'ignored', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4682 
4683     if (!is_root(CURR_DIR))
4684     {
4685         ptr = strrchr(expected, '\\') + 1;
4686         sprintf(path, "'NewSignature26', '%s', '', '', '', '', '', '', ''", ptr);
4687         add_signature_entry(hdb, path);
4688     }
4689     add_signature_entry(hdb, "'NewSignature27', 'FileName2', '', '', '', '', '', '', ''");
4690     add_signature_entry(hdb, "'NewSignature29', 'FileName1', '', '', '', '', '', '', ''");
4691     add_signature_entry(hdb, "'NewSignature30', 'FileName1', '', '', '', '', '', '', ''");
4692 
4693     r = package_from_db(hdb, &hpkg);
4694     ok(r == ERROR_SUCCESS, "Expected a valid package handle %u\n", r);
4695 
4696     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4697 
4698     r = MsiDoActionA(hpkg, "AppSearch");
4699     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4700 
4701     size = MAX_PATH;
4702     r = MsiGetPropertyA(hpkg, "SIGPROP1", prop, &size);
4703     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4704     ok(!lstrcmpA(prop, "regszdata"),
4705        "Expected \"regszdata\", got \"%s\"\n", prop);
4706 
4707     size = MAX_PATH;
4708     r = MsiGetPropertyA(hpkg, "SIGPROP2", prop, &size);
4709     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4710     ok(!lstrcmpA(prop, "#42"), "Expected \"#42\", got \"%s\"\n", prop);
4711 
4712     size = MAX_PATH;
4713     r = MsiGetPropertyA(hpkg, "SIGPROP3", prop, &size);
4714     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4715     ok(!lstrcmpA(prop, "#-42"), "Expected \"#-42\", got \"%s\"\n", prop);
4716 
4717     memset(&si, 0, sizeof(si));
4718     GetNativeSystemInfo(&si);
4719 
4720     if (S(U(si)).wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
4721     {
4722         size = ExpandEnvironmentStringsA("%PATH%", NULL, 0);
4723         pathvar = malloc(size);
4724         ExpandEnvironmentStringsA("%PATH%", pathvar, size);
4725 
4726         size = 0;
4727         r = MsiGetPropertyA(hpkg, "SIGPROP4", NULL, &size);
4728         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4729 
4730         pathdata = malloc(++size);
4731         r = MsiGetPropertyA(hpkg, "SIGPROP4", pathdata, &size);
4732         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4733         ok(!lstrcmpA(pathdata, pathvar),
4734             "Expected \"%s\", got \"%s\"\n", pathvar, pathdata);
4735 
4736         free(pathvar);
4737         free(pathdata);
4738     }
4739 
4740     size = MAX_PATH;
4741     r = MsiGetPropertyA(hpkg, "SIGPROP5", prop, &size);
4742     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4743     ok(!lstrcmpA(prop,
4744        "my%NOVAR%"), "Expected \"my%%NOVAR%%\", got \"%s\"\n", prop);
4745 
4746     size = MAX_PATH;
4747     r = MsiGetPropertyA(hpkg, "SIGPROP6", prop, &size);
4748     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4749     todo_wine
4750     {
4751         ok(!memcmp(prop, "\0one\0two\0\0", 10),
4752            "Expected \"\\0one\\0two\\0\\0\"\n");
4753     }
4754 
4755     size = MAX_PATH;
4756     lstrcpyA(path, "#xCDAB3412EF907856");
4757     r = MsiGetPropertyA(hpkg, "SIGPROP7", prop, &size);
4758     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4759     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4760 
4761     size = MAX_PATH;
4762     r = MsiGetPropertyA(hpkg, "SIGPROP8", prop, &size);
4763     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4764     ok(!lstrcmpA(prop, "##regszdata"),
4765        "Expected \"##regszdata\", got \"%s\"\n", prop);
4766 
4767     size = MAX_PATH;
4768     sprintf(path, "%s\\FileName1", expected);
4769     r = MsiGetPropertyA(hpkg, "SIGPROP9", prop, &size);
4770     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4771     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4772 
4773     size = MAX_PATH;
4774     r = MsiGetPropertyA(hpkg, "SIGPROP10", prop, &size);
4775     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4776     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4777 
4778     size = MAX_PATH;
4779     sprintf(path, "%s\\", expected);
4780     r = MsiGetPropertyA(hpkg, "SIGPROP11", prop, &size);
4781     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4782     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4783 
4784     size = MAX_PATH;
4785     r = MsiGetPropertyA(hpkg, "SIGPROP12", prop, &size);
4786     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4787     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4788 
4789     size = MAX_PATH;
4790     sprintf(path, "%s\\", expected);
4791     r = MsiGetPropertyA(hpkg, "SIGPROP13", prop, &size);
4792     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4793     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4794 
4795     size = MAX_PATH;
4796     r = MsiGetPropertyA(hpkg, "SIGPROP14", prop, &size);
4797     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4798     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4799 
4800     size = MAX_PATH;
4801     r = MsiGetPropertyA(hpkg, "SIGPROP15", prop, &size);
4802     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4803     ok(!lstrcmpA(prop, "regszdata"),
4804        "Expected \"regszdata\", got \"%s\"\n", prop);
4805 
4806     size = MAX_PATH;
4807     r = MsiGetPropertyA(hpkg, "SIGPROP16", prop, &size);
4808     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4809     ok(!lstrcmpA(prop, "regszdata"),
4810        "Expected \"regszdata\", got \"%s\"\n", prop);
4811 
4812     if (users)
4813     {
4814         size = MAX_PATH;
4815         r = MsiGetPropertyA(hpkg, "SIGPROP17", prop, &size);
4816         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4817         ok(!lstrcmpA(prop, "regszdata"),
4818            "Expected \"regszdata\", got \"%s\"\n", prop);
4819     }
4820 
4821     size = MAX_PATH;
4822     r = MsiGetPropertyA(hpkg, "SIGPROP18", prop, &size);
4823     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4824     ok(!lstrcmpA(prop, "defvalue"),
4825        "Expected \"defvalue\", got \"%s\"\n", prop);
4826 
4827     size = MAX_PATH;
4828     r = MsiGetPropertyA(hpkg, "SIGPROP19", prop, &size);
4829     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4830     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4831 
4832     size = MAX_PATH;
4833     r = MsiGetPropertyA(hpkg, "SIGPROP20", prop, &size);
4834     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4835     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4836 
4837     if (version)
4838     {
4839         size = MAX_PATH;
4840         sprintf(path, "%s\\FileName3.dll", expected);
4841         r = MsiGetPropertyA(hpkg, "SIGPROP21", prop, &size);
4842         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4843         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4844 
4845         size = MAX_PATH;
4846         r = MsiGetPropertyA(hpkg, "SIGPROP22", prop, &size);
4847         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4848         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4849 
4850         size = MAX_PATH;
4851         sprintf(path, "%s\\FileName5.dll", expected);
4852         r = MsiGetPropertyA(hpkg, "SIGPROP23", prop, &size);
4853         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4854         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4855     }
4856 
4857     if (!is_root(CURR_DIR))
4858     {
4859         size = MAX_PATH;
4860         lstrcpyA(path, expected);
4861         ptr = strrchr(path, '\\') + 1;
4862         *ptr = '\0';
4863         r = MsiGetPropertyA(hpkg, "SIGPROP24", prop, &size);
4864         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4865         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4866     }
4867     size = MAX_PATH;
4868     sprintf(path, "%s\\", expected);
4869     r = MsiGetPropertyA(hpkg, "SIGPROP25", prop, &size);
4870     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4871     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4872 
4873     size = MAX_PATH;
4874     r = MsiGetPropertyA(hpkg, "SIGPROP26", prop, &size);
4875     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4876     if (is_root(CURR_DIR))
4877         ok(!lstrcmpA(prop, CURR_DIR), "Expected \"%s\", got \"%s\"\n", CURR_DIR, prop);
4878     else
4879         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4880 
4881     size = MAX_PATH;
4882     r = MsiGetPropertyA(hpkg, "SIGPROP27", prop, &size);
4883     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4884     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4885 
4886     size = MAX_PATH;
4887     r = MsiGetPropertyA(hpkg, "SIGPROP28", prop, &size);
4888     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4889     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4890 
4891     size = MAX_PATH;
4892     sprintf(path, "%s\\FileName1", expected);
4893     r = MsiGetPropertyA(hpkg, "SIGPROP29", prop, &size);
4894     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4895     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4896 
4897     size = MAX_PATH;
4898     sprintf(path, "%s\\FileName1", expected);
4899     r = MsiGetPropertyA(hpkg, "SIGPROP30", prop, &size);
4900     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4901     if (space)
4902         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4903     else
4904         todo_wine ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4905 
4906     RegSetValueA(hklm, NULL, REG_SZ, "", 0);
4907     RegDeleteValueA(hklm, "Value1");
4908     RegDeleteValueA(hklm, "Value2");
4909     RegDeleteValueA(hklm, "Value3");
4910     RegDeleteValueA(hklm, "Value4");
4911     RegDeleteValueA(hklm, "Value5");
4912     RegDeleteValueA(hklm, "Value6");
4913     RegDeleteValueA(hklm, "Value7");
4914     RegDeleteValueA(hklm, "Value8");
4915     RegDeleteValueA(hklm, "Value9");
4916     RegDeleteValueA(hklm, "Value10");
4917     RegDeleteValueA(hklm, "Value11");
4918     RegDeleteValueA(hklm, "Value12");
4919     RegDeleteValueA(hklm, "Value13");
4920     RegDeleteValueA(hklm, "Value14");
4921     RegDeleteValueA(hklm, "Value15");
4922     RegDeleteValueA(hklm, "Value16");
4923     RegDeleteValueA(hklm, "Value17");
4924     RegDeleteKeyA(hklm, "");
4925     RegCloseKey(hklm);
4926 
4927     RegDeleteValueA(classes, "Value1");
4928     RegDeleteKeyA(classes, "");
4929     RegCloseKey(classes);
4930 
4931     RegDeleteValueA(hkcu, "Value1");
4932     RegDeleteKeyA(hkcu, "");
4933     RegCloseKey(hkcu);
4934 
4935     RegDeleteValueA(users, "Value1");
4936     RegDeleteKeyA(users, "");
4937     RegCloseKey(users);
4938 
4939     DeleteFileA("FileName1");
4940     DeleteFileA("FileName3.dll");
4941     DeleteFileA("FileName4.dll");
4942     DeleteFileA("FileName5.dll");
4943     MsiCloseHandle(hpkg);
4944     DeleteFileA(msifile);
4945 }
4946 
4947 static void delete_win_ini(LPCSTR file)
4948 {
4949     CHAR path[MAX_PATH];
4950 
4951     GetWindowsDirectoryA(path, MAX_PATH);
4952     lstrcatA(path, "\\");
4953     lstrcatA(path, file);
4954 
4955     DeleteFileA(path);
4956 }
4957 
4958 static void test_appsearch_inilocator(void)
4959 {
4960     MSIHANDLE hpkg, hdb;
4961     char path[MAX_PATH + 14], expected[MAX_PATH], prop[MAX_PATH];
4962     BOOL version;
4963     LPSTR ptr;
4964     DWORD size;
4965     UINT r;
4966 
4967     version = TRUE;
4968     if (!create_file_with_version("test.dll", MAKELONG(2, 1), MAKELONG(4, 3)))
4969         version = FALSE;
4970 
4971     DeleteFileA("test.dll");
4972 
4973     WritePrivateProfileStringA("Section", "Key", "keydata,field2", "IniFile.ini");
4974 
4975     strcpy(expected, CURR_DIR);
4976     if (is_root(CURR_DIR)) expected[2] = 0;
4977 
4978     create_test_file("FileName1");
4979     sprintf(path, "%s\\FileName1", expected);
4980     WritePrivateProfileStringA("Section", "Key2", path, "IniFile.ini");
4981 
4982     WritePrivateProfileStringA("Section", "Key3", expected, "IniFile.ini");
4983 
4984     sprintf(path, "%s\\IDontExist", expected);
4985     WritePrivateProfileStringA("Section", "Key4", path, "IniFile.ini");
4986 
4987     create_file_with_version("FileName2.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4988     sprintf(path, "%s\\FileName2.dll", expected);
4989     WritePrivateProfileStringA("Section", "Key5", path, "IniFile.ini");
4990 
4991     create_file_with_version("FileName3.dll", MAKELONG(1, 2), MAKELONG(3, 4));
4992     sprintf(path, "%s\\FileName3.dll", expected);
4993     WritePrivateProfileStringA("Section", "Key6", path, "IniFile.ini");
4994 
4995     create_file_with_version("FileName4.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4996     sprintf(path, "%s\\FileName4.dll", expected);
4997     WritePrivateProfileStringA("Section", "Key7", path, "IniFile.ini");
4998 
4999     hdb = create_package_db();
5000     ok(hdb, "Expected a valid database handle\n");
5001 
5002     create_appsearch_table(hdb);
5003     add_appsearch_entry(hdb, "'SIGPROP1', 'NewSignature1'");
5004     add_appsearch_entry(hdb, "'SIGPROP2', 'NewSignature2'");
5005     add_appsearch_entry(hdb, "'SIGPROP3', 'NewSignature3'");
5006     add_appsearch_entry(hdb, "'SIGPROP4', 'NewSignature4'");
5007     add_appsearch_entry(hdb, "'SIGPROP5', 'NewSignature5'");
5008     add_appsearch_entry(hdb, "'SIGPROP6', 'NewSignature6'");
5009     add_appsearch_entry(hdb, "'SIGPROP7', 'NewSignature7'");
5010     add_appsearch_entry(hdb, "'SIGPROP8', 'NewSignature8'");
5011     add_appsearch_entry(hdb, "'SIGPROP9', 'NewSignature9'");
5012     add_appsearch_entry(hdb, "'SIGPROP10', 'NewSignature10'");
5013     add_appsearch_entry(hdb, "'SIGPROP11', 'NewSignature11'");
5014     add_appsearch_entry(hdb, "'SIGPROP12', 'NewSignature12'");
5015 
5016     create_inilocator_table(hdb);
5017 
5018     /* msidbLocatorTypeRawValue, field 1 */
5019     add_inilocator_entry(hdb, "'NewSignature1', 'IniFile.ini', 'Section', 'Key', 1, 2");
5020 
5021     /* msidbLocatorTypeRawValue, field 2 */
5022     add_inilocator_entry(hdb, "'NewSignature2', 'IniFile.ini', 'Section', 'Key', 2, 2");
5023 
5024     /* msidbLocatorTypeRawValue, entire field */
5025     add_inilocator_entry(hdb, "'NewSignature3', 'IniFile.ini', 'Section', 'Key', 0, 2");
5026 
5027     /* msidbLocatorTypeFile */
5028     add_inilocator_entry(hdb, "'NewSignature4', 'IniFile.ini', 'Section', 'Key2', 1, 1");
5029 
5030     /* msidbLocatorTypeDirectory, file */
5031     add_inilocator_entry(hdb, "'NewSignature5', 'IniFile.ini', 'Section', 'Key2', 1, 0");
5032 
5033     /* msidbLocatorTypeDirectory, directory */
5034     add_inilocator_entry(hdb, "'NewSignature6', 'IniFile.ini', 'Section', 'Key3', 1, 0");
5035 
5036     /* msidbLocatorTypeFile, file, no signature */
5037     add_inilocator_entry(hdb, "'NewSignature7', 'IniFile.ini', 'Section', 'Key2', 1, 1");
5038 
5039     /* msidbLocatorTypeFile, dir, no signature */
5040     add_inilocator_entry(hdb, "'NewSignature8', 'IniFile.ini', 'Section', 'Key3', 1, 1");
5041 
5042     /* msidbLocatorTypeFile, file does not exist */
5043     add_inilocator_entry(hdb, "'NewSignature9', 'IniFile.ini', 'Section', 'Key4', 1, 1");
5044 
5045     /* msidbLocatorTypeFile, signature with version */
5046     add_inilocator_entry(hdb, "'NewSignature10', 'IniFile.ini', 'Section', 'Key5', 1, 1");
5047 
5048     /* msidbLocatorTypeFile, signature with version, ver > max */
5049     add_inilocator_entry(hdb, "'NewSignature11', 'IniFile.ini', 'Section', 'Key6', 1, 1");
5050 
5051     /* msidbLocatorTypeFile, signature with version, sig->name ignored */
5052     add_inilocator_entry(hdb, "'NewSignature12', 'IniFile.ini', 'Section', 'Key7', 1, 1");
5053 
5054     create_signature_table(hdb);
5055     add_signature_entry(hdb, "'NewSignature4', 'FileName1', '', '', '', '', '', '', ''");
5056     add_signature_entry(hdb, "'NewSignature9', 'IDontExist', '', '', '', '', '', '', ''");
5057     add_signature_entry(hdb, "'NewSignature10', 'FileName2.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
5058     add_signature_entry(hdb, "'NewSignature11', 'FileName3.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
5059     add_signature_entry(hdb, "'NewSignature12', 'ignored', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
5060 
5061     r = package_from_db(hdb, &hpkg);
5062     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5063     {
5064         skip("Not enough rights to perform tests\n");
5065         goto error;
5066     }
5067     ok(r == ERROR_SUCCESS, "Expected a valid package handle %u\n", r);
5068 
5069     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5070 
5071     r = MsiDoActionA(hpkg, "AppSearch");
5072     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5073 
5074     size = MAX_PATH;
5075     r = MsiGetPropertyA(hpkg, "SIGPROP1", prop, &size);
5076     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5077     ok(!lstrcmpA(prop, "keydata"), "Expected \"keydata\", got \"%s\"\n", prop);
5078 
5079     size = MAX_PATH;
5080     r = MsiGetPropertyA(hpkg, "SIGPROP2", prop, &size);
5081     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5082     ok(!lstrcmpA(prop, "field2"), "Expected \"field2\", got \"%s\"\n", prop);
5083 
5084     size = MAX_PATH;
5085     r = MsiGetPropertyA(hpkg, "SIGPROP3", prop, &size);
5086     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5087     ok(!lstrcmpA(prop, "keydata,field2"),
5088        "Expected \"keydata,field2\", got \"%s\"\n", prop);
5089 
5090     size = MAX_PATH;
5091     sprintf(path, "%s\\FileName1", expected);
5092     r = MsiGetPropertyA(hpkg, "SIGPROP4", prop, &size);
5093     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5094     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5095 
5096     size = MAX_PATH;
5097     r = MsiGetPropertyA(hpkg, "SIGPROP5", prop, &size);
5098     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5099     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5100 
5101     size = MAX_PATH;
5102     sprintf(path, "%s\\", expected);
5103     r = MsiGetPropertyA(hpkg, "SIGPROP6", prop, &size);
5104     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5105     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5106 
5107     size = MAX_PATH;
5108     sprintf(path, "%s\\", expected);
5109     r = MsiGetPropertyA(hpkg, "SIGPROP7", prop, &size);
5110     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5111     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5112 
5113     if (!is_root(CURR_DIR))
5114     {
5115         size = MAX_PATH;
5116         lstrcpyA(path, expected);
5117         ptr = strrchr(path, '\\');
5118         *(ptr + 1) = 0;
5119         r = MsiGetPropertyA(hpkg, "SIGPROP8", prop, &size);
5120         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5121         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5122     }
5123     size = MAX_PATH;
5124     r = MsiGetPropertyA(hpkg, "SIGPROP9", prop, &size);
5125     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5126     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5127 
5128     if (version)
5129     {
5130         size = MAX_PATH;
5131         sprintf(path, "%s\\FileName2.dll", expected);
5132         r = MsiGetPropertyA(hpkg, "SIGPROP10", prop, &size);
5133         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5134         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5135 
5136         size = MAX_PATH;
5137         r = MsiGetPropertyA(hpkg, "SIGPROP11", prop, &size);
5138         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5139         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5140 
5141         size = MAX_PATH;
5142         sprintf(path, "%s\\FileName4.dll", expected);
5143         r = MsiGetPropertyA(hpkg, "SIGPROP12", prop, &size);
5144         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5145         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5146     }
5147 
5148     MsiCloseHandle(hpkg);
5149 
5150 error:
5151     delete_win_ini("IniFile.ini");
5152     DeleteFileA("FileName1");
5153     DeleteFileA("FileName2.dll");
5154     DeleteFileA("FileName3.dll");
5155     DeleteFileA("FileName4.dll");
5156     DeleteFileA(msifile);
5157 }
5158 
5159 /*
5160  * MSI AppSearch action on DrLocator table always returns absolute paths.
5161  * If a relative path was set, it returns the first absolute path that
5162  * matches or an empty string if it didn't find anything.
5163  * This helper function replicates this behaviour.
5164  */
5165 static void search_absolute_directory(LPSTR absolute, LPCSTR relative)
5166 {
5167     int i, size;
5168     DWORD attr, drives;
5169 
5170     size = lstrlenA(relative);
5171     drives = GetLogicalDrives();
5172     lstrcpyA(absolute, "A:\\");
5173     for (i = 0; i < 26; absolute[0] = '\0', i++)
5174     {
5175         if (!(drives & (1 << i)))
5176             continue;
5177 
5178         absolute[0] = 'A' + i;
5179         if (GetDriveTypeA(absolute) != DRIVE_FIXED)
5180             continue;
5181 
5182         lstrcpynA(absolute + 3, relative, size + 1);
5183         attr = GetFileAttributesA(absolute);
5184         if (attr != INVALID_FILE_ATTRIBUTES &&
5185             (attr & FILE_ATTRIBUTE_DIRECTORY))
5186         {
5187             if (absolute[3 + size - 1] != '\\')
5188                 lstrcatA(absolute, "\\");
5189             break;
5190         }
5191         absolute[3] = '\0';
5192     }
5193 }
5194 
5195 static void test_appsearch_drlocator(void)
5196 {
5197     MSIHANDLE hpkg, hdb;
5198     char path[MAX_PATH + 27], expected[MAX_PATH], prop[MAX_PATH];
5199     BOOL version;
5200     DWORD size;
5201     UINT r;
5202 
5203     version = TRUE;
5204     if (!create_file_with_version("test.dll", MAKELONG(2, 1), MAKELONG(4, 3)))
5205         version = FALSE;
5206 
5207     DeleteFileA("test.dll");
5208 
5209     create_test_file("FileName1");
5210     CreateDirectoryA("one", NULL);
5211     CreateDirectoryA("one\\two", NULL);
5212     CreateDirectoryA("one\\two\\three", NULL);
5213     create_test_file("one\\two\\three\\FileName2");
5214     CreateDirectoryA("another", NULL);
5215     create_file_with_version("FileName3.dll", MAKELONG(2, 1), MAKELONG(4, 3));
5216     create_file_with_version("FileName4.dll", MAKELONG(1, 2), MAKELONG(3, 4));
5217     create_file_with_version("FileName5.dll", MAKELONG(2, 1), MAKELONG(4, 3));
5218 
5219     hdb = create_package_db();
5220     ok(hdb, "Expected a valid database handle\n");
5221 
5222     create_appsearch_table(hdb);
5223     add_appsearch_entry(hdb, "'SIGPROP1', 'NewSignature1'");
5224     add_appsearch_entry(hdb, "'SIGPROP2', 'NewSignature2'");
5225     add_appsearch_entry(hdb, "'SIGPROP3', 'NewSignature3'");
5226     add_appsearch_entry(hdb, "'SIGPROP4', 'NewSignature4'");
5227     add_appsearch_entry(hdb, "'SIGPROP5', 'NewSignature5'");
5228     add_appsearch_entry(hdb, "'SIGPROP6', 'NewSignature6'");
5229     add_appsearch_entry(hdb, "'SIGPROP7', 'NewSignature7'");
5230     add_appsearch_entry(hdb, "'SIGPROP8', 'NewSignature8'");
5231     add_appsearch_entry(hdb, "'SIGPROP9', 'NewSignature9'");
5232     add_appsearch_entry(hdb, "'SIGPROP10', 'NewSignature10'");
5233     add_appsearch_entry(hdb, "'SIGPROP11', 'NewSignature11'");
5234     add_appsearch_entry(hdb, "'SIGPROP13', 'NewSignature13'");
5235 
5236     create_drlocator_table(hdb);
5237 
5238     strcpy(expected, CURR_DIR);
5239     if (is_root(CURR_DIR)) expected[2] = 0;
5240 
5241     /* no parent, full path, depth 0, signature */
5242     sprintf(path, "'NewSignature1', '', '%s', 0", expected);
5243     add_drlocator_entry(hdb, path);
5244 
5245     /* no parent, full path, depth 0, no signature */
5246     sprintf(path, "'NewSignature2', '', '%s', 0", expected);
5247     add_drlocator_entry(hdb, path);
5248 
5249     /* no parent, relative path, depth 0, no signature */
5250     sprintf(path, "'NewSignature3', '', '%s', 0", expected + 3);
5251     add_drlocator_entry(hdb, path);
5252 
5253     /* no parent, full path, depth 2, signature */
5254     sprintf(path, "'NewSignature4', '', '%s', 2", expected);
5255     add_drlocator_entry(hdb, path);
5256 
5257     /* no parent, full path, depth 3, signature */
5258     sprintf(path, "'NewSignature5', '', '%s', 3", expected);
5259     add_drlocator_entry(hdb, path);
5260 
5261     /* no parent, full path, depth 1, signature is dir */
5262     sprintf(path, "'NewSignature6', '', '%s', 1", expected);
5263     add_drlocator_entry(hdb, path);
5264 
5265     /* parent is in DrLocator, relative path, depth 0, signature */
5266     sprintf(path, "'NewSignature7', 'NewSignature1', 'one\\two\\three', 1");
5267     add_drlocator_entry(hdb, path);
5268 
5269     /* no parent, full path, depth 0, signature w/ version */
5270     sprintf(path, "'NewSignature8', '', '%s', 0", expected);
5271     add_drlocator_entry(hdb, path);
5272 
5273     /* no parent, full path, depth 0, signature w/ version, ver > max */
5274     sprintf(path, "'NewSignature9', '', '%s', 0", expected);
5275     add_drlocator_entry(hdb, path);
5276 
5277     /* no parent, full path, depth 0, signature w/ version, sig->name not ignored */
5278     sprintf(path, "'NewSignature10', '', '%s', 0", expected);
5279     add_drlocator_entry(hdb, path);
5280 
5281     /* no parent, relative empty path, depth 0, no signature */
5282     sprintf(path, "'NewSignature11', '', '', 0");
5283     add_drlocator_entry(hdb, path);
5284 
5285     create_reglocator_table(hdb);
5286 
5287     /* parent */
5288     add_reglocator_entry(hdb, "NewSignature12", 2, "htmlfile\\shell\\open\\nonexistent", "", 1);
5289 
5290     /* parent is in RegLocator, no path, depth 0, no signature */
5291     sprintf(path, "'NewSignature13', 'NewSignature12', '', 0");
5292     add_drlocator_entry(hdb, path);
5293 
5294     create_signature_table(hdb);
5295     add_signature_entry(hdb, "'NewSignature1', 'FileName1', '', '', '', '', '', '', ''");
5296     add_signature_entry(hdb, "'NewSignature4', 'FileName2', '', '', '', '', '', '', ''");
5297     add_signature_entry(hdb, "'NewSignature5', 'FileName2', '', '', '', '', '', '', ''");
5298     add_signature_entry(hdb, "'NewSignature6', 'another', '', '', '', '', '', '', ''");
5299     add_signature_entry(hdb, "'NewSignature7', 'FileName2', '', '', '', '', '', '', ''");
5300     add_signature_entry(hdb, "'NewSignature8', 'FileName3.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
5301     add_signature_entry(hdb, "'NewSignature9', 'FileName4.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
5302     add_signature_entry(hdb, "'NewSignature10', 'necessary', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
5303 
5304     r = package_from_db(hdb, &hpkg);
5305     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5306     {
5307         skip("Not enough rights to perform tests\n");
5308         goto error;
5309     }
5310     ok(r == ERROR_SUCCESS, "Expected a valid package handle %u\n", r);
5311 
5312     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5313 
5314     r = MsiDoActionA(hpkg, "AppSearch");
5315     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5316 
5317     size = MAX_PATH;
5318     sprintf(path, "%s\\FileName1", expected);
5319     r = MsiGetPropertyA(hpkg, "SIGPROP1", prop, &size);
5320     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5321     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5322 
5323     size = MAX_PATH;
5324     sprintf(path, "%s\\", expected);
5325     r = MsiGetPropertyA(hpkg, "SIGPROP2", prop, &size);
5326     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5327     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5328 
5329     size = MAX_PATH;
5330     search_absolute_directory(path, expected + 3);
5331     r = MsiGetPropertyA(hpkg, "SIGPROP3", prop, &size);
5332     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5333     ok(!lstrcmpiA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5334 
5335     size = MAX_PATH;
5336     r = MsiGetPropertyA(hpkg, "SIGPROP4", prop, &size);
5337     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5338     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5339 
5340     size = MAX_PATH;
5341     sprintf(path, "%s\\one\\two\\three\\FileName2", expected);
5342     r = MsiGetPropertyA(hpkg, "SIGPROP5", prop, &size);
5343     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5344     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5345 
5346     size = MAX_PATH;
5347     r = MsiGetPropertyA(hpkg, "SIGPROP6", prop, &size);
5348     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5349     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5350 
5351     size = MAX_PATH;
5352     sprintf(path, "%s\\one\\two\\three\\FileName2", expected);
5353     r = MsiGetPropertyA(hpkg, "SIGPROP7", prop, &size);
5354     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5355     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5356 
5357     if (version)
5358     {
5359         size = MAX_PATH;
5360         sprintf(path, "%s\\FileName3.dll", expected);
5361         r = MsiGetPropertyA(hpkg, "SIGPROP8", prop, &size);
5362         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5363         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5364 
5365         size = MAX_PATH;
5366         r = MsiGetPropertyA(hpkg, "SIGPROP9", prop, &size);
5367         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5368         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5369 
5370         size = MAX_PATH;
5371         r = MsiGetPropertyA(hpkg, "SIGPROP10", prop, &size);
5372         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5373         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5374     }
5375 
5376     size = MAX_PATH;
5377     search_absolute_directory(path, "");
5378     r = MsiGetPropertyA(hpkg, "SIGPROP11", prop, &size);
5379     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5380     ok(!lstrcmpiA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5381 
5382     size = MAX_PATH;
5383     strcpy(path, "c:\\");
5384     r = MsiGetPropertyA(hpkg, "SIGPROP13", prop, &size);
5385     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5386     ok(!prop[0], "Expected \"\", got \"%s\"\n", prop);
5387 
5388     MsiCloseHandle(hpkg);
5389 
5390 error:
5391     DeleteFileA("FileName1");
5392     DeleteFileA("FileName3.dll");
5393     DeleteFileA("FileName4.dll");
5394     DeleteFileA("FileName5.dll");
5395     DeleteFileA("one\\two\\three\\FileName2");
5396     RemoveDirectoryA("one\\two\\three");
5397     RemoveDirectoryA("one\\two");
5398     RemoveDirectoryA("one");
5399     RemoveDirectoryA("another");
5400     DeleteFileA(msifile);
5401 }
5402 
5403 static void test_featureparents(void)
5404 {
5405     MSIHANDLE hpkg;
5406     UINT r;
5407     MSIHANDLE hdb;
5408 
5409     hdb = create_package_db();
5410     ok ( hdb, "failed to create package database\n" );
5411 
5412     add_directory_entry(hdb, "'TARGETDIR', '', 'SourceDir'");
5413 
5414     create_feature_table( hdb );
5415     create_component_table( hdb );
5416     create_feature_components_table( hdb );
5417     create_file_table( hdb );
5418 
5419     /* msidbFeatureAttributesFavorLocal */
5420     add_feature_entry( hdb, "'zodiac', '', '', '', 2, 1, '', 0" );
5421 
5422     /* msidbFeatureAttributesFavorSource */
5423     add_feature_entry( hdb, "'perseus', '', '', '', 2, 1, '', 1" );
5424 
5425     /* msidbFeatureAttributesFavorLocal */
5426     add_feature_entry( hdb, "'orion', '', '', '', 2, 1, '', 0" );
5427 
5428     /* msidbFeatureAttributesUIDisallowAbsent */
5429     add_feature_entry( hdb, "'lyra', '', '', '', 2, 1, '', 16" );
5430 
5431     /* disabled because of install level */
5432     add_feature_entry( hdb, "'waters', '', '', '', 15, 101, '', 9" );
5433 
5434     /* child feature of disabled feature */
5435     add_feature_entry( hdb, "'bayer', 'waters', '', '', 14, 1, '', 9" );
5436 
5437     /* component of disabled feature (install level) */
5438     add_component_entry( hdb, "'delphinus', '', 'TARGETDIR', 0, '', 'delphinus_file'" );
5439 
5440     /* component of disabled child feature (install level) */
5441     add_component_entry( hdb, "'hydrus', '', 'TARGETDIR', 0, '', 'hydrus_file'" );
5442 
5443     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesLocalOnly */
5444     add_component_entry( hdb, "'leo', '', 'TARGETDIR', 0, '', 'leo_file'" );
5445 
5446     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSourceOnly */
5447     add_component_entry( hdb, "'virgo', '', 'TARGETDIR', 1, '', 'virgo_file'" );
5448 
5449     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesOptional */
5450     add_component_entry( hdb, "'libra', '', 'TARGETDIR', 2, '', 'libra_file'" );
5451 
5452     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesLocalOnly */
5453     add_component_entry( hdb, "'cassiopeia', '', 'TARGETDIR', 0, '', 'cassiopeia_file'" );
5454 
5455     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSourceOnly */
5456     add_component_entry( hdb, "'cepheus', '', 'TARGETDIR', 1, '', 'cepheus_file'" );
5457 
5458     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesOptional */
5459     add_component_entry( hdb, "'andromeda', '', 'TARGETDIR', 2, '', 'andromeda_file'" );
5460 
5461     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesLocalOnly */
5462     add_component_entry( hdb, "'canis', '', 'TARGETDIR', 0, '', 'canis_file'" );
5463 
5464     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSourceOnly */
5465     add_component_entry( hdb, "'monoceros', '', 'TARGETDIR', 1, '', 'monoceros_file'" );
5466 
5467     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesOptional */
5468     add_component_entry( hdb, "'lepus', '', 'TARGETDIR', 2, '', 'lepus_file'" );
5469 
5470     add_feature_components_entry( hdb, "'zodiac', 'leo'" );
5471     add_feature_components_entry( hdb, "'zodiac', 'virgo'" );
5472     add_feature_components_entry( hdb, "'zodiac', 'libra'" );
5473     add_feature_components_entry( hdb, "'perseus', 'cassiopeia'" );
5474     add_feature_components_entry( hdb, "'perseus', 'cepheus'" );
5475     add_feature_components_entry( hdb, "'perseus', 'andromeda'" );
5476     add_feature_components_entry( hdb, "'orion', 'leo'" );
5477     add_feature_components_entry( hdb, "'orion', 'virgo'" );
5478     add_feature_components_entry( hdb, "'orion', 'libra'" );
5479     add_feature_components_entry( hdb, "'orion', 'cassiopeia'" );
5480     add_feature_components_entry( hdb, "'orion', 'cepheus'" );
5481     add_feature_components_entry( hdb, "'orion', 'andromeda'" );
5482     add_feature_components_entry( hdb, "'orion', 'canis'" );
5483     add_feature_components_entry( hdb, "'orion', 'monoceros'" );
5484     add_feature_components_entry( hdb, "'orion', 'lepus'" );
5485     add_feature_components_entry( hdb, "'waters', 'delphinus'" );
5486     add_feature_components_entry( hdb, "'bayer', 'hydrus'" );
5487 
5488     add_file_entry( hdb, "'leo_file', 'leo', 'leo.txt', 100, '', '1033', 8192, 1" );
5489     add_file_entry( hdb, "'virgo_file', 'virgo', 'virgo.txt', 0, '', '1033', 8192, 1" );
5490     add_file_entry( hdb, "'libra_file', 'libra', 'libra.txt', 0, '', '1033', 8192, 1" );
5491     add_file_entry( hdb, "'cassiopeia_file', 'cassiopeia', 'cassiopeia.txt', 0, '', '1033', 8192, 1" );
5492     add_file_entry( hdb, "'cepheus_file', 'cepheus', 'cepheus.txt', 0, '', '1033', 8192, 1" );
5493     add_file_entry( hdb, "'andromeda_file', 'andromeda', 'andromeda.txt', 0, '', '1033', 8192, 1" );
5494     add_file_entry( hdb, "'canis_file', 'canis', 'canis.txt', 0, '', '1033', 8192, 1" );
5495     add_file_entry( hdb, "'monoceros_file', 'monoceros', 'monoceros.txt', 0, '', '1033', 8192, 1" );
5496     add_file_entry( hdb, "'lepus_file', 'lepus', 'lepus.txt', 0, '', '1033', 8192, 1" );
5497     add_file_entry( hdb, "'delphinus_file', 'delphinus', 'delphinus.txt', 0, '', '1033', 8192, 1" );
5498     add_file_entry( hdb, "'hydrus_file', 'hydrus', 'hydrus.txt', 0, '', '1033', 8192, 1" );
5499 
5500     r = package_from_db( hdb, &hpkg );
5501     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5502     {
5503         skip("Not enough rights to perform tests\n");
5504         DeleteFileA(msifile);
5505         return;
5506     }
5507     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
5508 
5509     MsiCloseHandle( hdb );
5510 
5511     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5512 
5513     r = MsiDoActionA( hpkg, "CostInitialize");
5514     ok( r == ERROR_SUCCESS, "cost init failed\n");
5515 
5516     r = MsiDoActionA( hpkg, "FileCost");
5517     ok( r == ERROR_SUCCESS, "file cost failed\n");
5518 
5519     r = MsiDoActionA( hpkg, "CostFinalize");
5520     ok( r == ERROR_SUCCESS, "cost finalize failed\n");
5521 
5522     test_feature_states( __LINE__, hpkg, "zodiac", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
5523     test_feature_states( __LINE__, hpkg, "perseus", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
5524     test_feature_states( __LINE__, hpkg, "orion", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
5525     test_feature_states( __LINE__, hpkg, "lyra", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
5526     test_feature_states( __LINE__, hpkg, "waters", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
5527     test_feature_states( __LINE__, hpkg, "bayer", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
5528 
5529     test_component_states( __LINE__, hpkg, "leo", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5530     test_component_states( __LINE__, hpkg, "virgo", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5531     test_component_states( __LINE__, hpkg, "libra", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5532     test_component_states( __LINE__, hpkg, "cassiopeia", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5533     test_component_states( __LINE__, hpkg, "cepheus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5534     test_component_states( __LINE__, hpkg, "andromeda", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5535     test_component_states( __LINE__, hpkg, "canis", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5536     test_component_states( __LINE__, hpkg, "monoceros", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5537     test_component_states( __LINE__, hpkg, "lepus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5538     test_component_states( __LINE__, hpkg, "delphinus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5539     test_component_states( __LINE__, hpkg, "hydrus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5540 
5541     r = MsiSetFeatureStateA(hpkg, "orion", INSTALLSTATE_ABSENT);
5542     ok( r == ERROR_SUCCESS, "failed to set feature state: %d\n", r);
5543 
5544     r = MsiSetFeatureStateA(hpkg, "lyra", INSTALLSTATE_ABSENT);
5545     ok( r == ERROR_SUCCESS, "failed to set feature state: %d\n", r);
5546 
5547     r = MsiSetFeatureStateA(hpkg, "nosuchfeature", INSTALLSTATE_ABSENT);
5548     ok( r == ERROR_UNKNOWN_FEATURE, "Expected ERROR_UNKNOWN_FEATURE, got %u\n", r);
5549 
5550     test_feature_states( __LINE__, hpkg, "zodiac", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
5551     test_feature_states( __LINE__, hpkg, "perseus", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
5552     test_feature_states( __LINE__, hpkg, "orion", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_ABSENT, FALSE );
5553     test_feature_states( __LINE__, hpkg, "lyra", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_ABSENT, FALSE );
5554     test_feature_states( __LINE__, hpkg, "waters", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
5555     test_feature_states( __LINE__, hpkg, "bayer", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
5556 
5557     test_component_states( __LINE__, hpkg, "leo", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5558     test_component_states( __LINE__, hpkg, "virgo", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5559     test_component_states( __LINE__, hpkg, "libra", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5560     test_component_states( __LINE__, hpkg, "cassiopeia", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5561     test_component_states( __LINE__, hpkg, "cepheus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5562     test_component_states( __LINE__, hpkg, "andromeda", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5563     test_component_states( __LINE__, hpkg, "canis", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5564     test_component_states( __LINE__, hpkg, "monoceros", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5565     test_component_states( __LINE__, hpkg, "lepus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5566     test_component_states( __LINE__, hpkg, "delphinus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5567     test_component_states( __LINE__, hpkg, "hydrus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5568 
5569     MsiCloseHandle(hpkg);
5570     DeleteFileA(msifile);
5571 }
5572 
5573 static void test_installprops(void)
5574 {
5575     MSIHANDLE hpkg, hdb;
5576     CHAR path[MAX_PATH], buf[MAX_PATH];
5577     DWORD size, type;
5578     LANGID langid;
5579     HKEY hkey1, hkey2, pathkey;
5580     int res;
5581     UINT r;
5582     REGSAM access = KEY_ALL_ACCESS;
5583     SYSTEM_INFO si;
5584     INSTALLUILEVEL uilevel;
5585 
5586     if (is_wow64)
5587         access |= KEY_WOW64_64KEY;
5588 
5589     lstrcpyA(path, CURR_DIR);
5590     if (!is_root(CURR_DIR)) lstrcatA(path, "\\");
5591     lstrcatA(path, msifile);
5592 
5593     uilevel = MsiSetInternalUI(INSTALLUILEVEL_BASIC|INSTALLUILEVEL_SOURCERESONLY, NULL);
5594 
5595     hdb = create_package_db();
5596     ok( hdb, "failed to create database\n");
5597 
5598     r = package_from_db(hdb, &hpkg);
5599     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5600     {
5601         skip("Not enough rights to perform tests\n");
5602         MsiSetInternalUI(uilevel, NULL);
5603         DeleteFileA(msifile);
5604         return;
5605     }
5606     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
5607 
5608     MsiCloseHandle(hdb);
5609 
5610     buf[0] = 0;
5611     size = MAX_PATH;
5612     r = MsiGetPropertyA(hpkg, "UILevel", buf, &size);
5613     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5614     ok( !lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
5615 
5616     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5617 
5618     buf[0] = 0;
5619     size = MAX_PATH;
5620     r = MsiGetPropertyA(hpkg, "UILevel", buf, &size);
5621     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5622     ok( !lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
5623 
5624     buf[0] = 0;
5625     size = MAX_PATH;
5626     r = MsiGetPropertyA(hpkg, "DATABASE", buf, &size);
5627     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5628     ok( !lstrcmpA(buf, path), "Expected %s, got %s\n", path, buf);
5629 
5630     RegOpenKeyA(HKEY_CURRENT_USER, "SOFTWARE\\Microsoft\\MS Setup (ACME)\\User Info", &hkey1);
5631     RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, access, &hkey2);
5632     RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion",
5633         0, KEY_QUERY_VALUE | KEY_WOW64_64KEY, &pathkey);
5634 
5635     size = MAX_PATH;
5636     type = REG_SZ;
5637     *path = '\0';
5638     if (RegQueryValueExA(hkey1, "DefName", NULL, &type, (LPBYTE)path, &size) != ERROR_SUCCESS)
5639     {
5640         size = MAX_PATH;
5641         type = REG_SZ;
5642         RegQueryValueExA(hkey2, "RegisteredOwner", NULL, &type, (LPBYTE)path, &size);
5643     }
5644 
5645     buf[0] = 0;
5646     size = MAX_PATH;
5647     r = MsiGetPropertyA(hpkg, "USERNAME", buf, &size);
5648     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5649     ok( !lstrcmpA(buf, path), "Expected %s, got %s\n", path, buf);
5650 
5651     size = MAX_PATH;
5652     type = REG_SZ;
5653     *path = '\0';
5654     if (RegQueryValueExA(hkey1, "DefCompany", NULL, &type, (LPBYTE)path, &size) != ERROR_SUCCESS)
5655     {
5656         size = MAX_PATH;
5657         type = REG_SZ;
5658         RegQueryValueExA(hkey2, "RegisteredOrganization", NULL, &type, (LPBYTE)path, &size);
5659     }
5660 
5661     if (*path)
5662     {
5663         buf[0] = 0;
5664         size = MAX_PATH;
5665         r = MsiGetPropertyA(hpkg, "COMPANYNAME", buf, &size);
5666         ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5667         ok( !lstrcmpA(buf, path), "Expected %s, got %s\n", path, buf);
5668     }
5669 
5670     buf[0] = 0;
5671     size = MAX_PATH;
5672     r = MsiGetPropertyA(hpkg, "VersionDatabase", buf, &size);
5673     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5674     trace("VersionDatabase = %s\n", buf);
5675 
5676     buf[0] = 0;
5677     size = MAX_PATH;
5678     r = MsiGetPropertyA(hpkg, "VersionMsi", buf, &size);
5679     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5680     trace("VersionMsi = %s\n", buf);
5681 
5682     buf[0] = 0;
5683     size = MAX_PATH;
5684     r = MsiGetPropertyA(hpkg, "Date", buf, &size);
5685     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5686     trace("Date = %s\n", buf);
5687 
5688     buf[0] = 0;
5689     size = MAX_PATH;
5690     r = MsiGetPropertyA(hpkg, "Time", buf, &size);
5691     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5692     trace("Time = %s\n", buf);
5693 
5694     buf[0] = 0;
5695     size = MAX_PATH;
5696     r = MsiGetPropertyA(hpkg, "PackageCode", buf, &size);
5697     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5698     trace("PackageCode = %s\n", buf);
5699 
5700     buf[0] = 0;
5701     size = MAX_PATH;
5702     r = MsiGetPropertyA(hpkg, "ComputerName", buf, &size);
5703     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
5704     trace("ComputerName = %s\n", buf);
5705 
5706     langid = GetUserDefaultLangID();
5707     sprintf(path, "%d", langid);
5708 
5709     buf[0] = 0;
5710     size = MAX_PATH;
5711     r = MsiGetPropertyA(hpkg, "UserLanguageID", buf, &size);
5712     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
5713     ok( !lstrcmpA(buf, path), "Expected \"%s\", got \"%s\"\n", path, buf);
5714 
5715     res = GetSystemMetrics(SM_CXSCREEN);
5716     buf[0] = 0;
5717     size = MAX_PATH;
5718     r = MsiGetPropertyA(hpkg, "ScreenX", buf, &size);
5719     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
5720     ok(atol(buf) == res, "Expected %d, got %s\n", res, buf);
5721 
5722     res = GetSystemMetrics(SM_CYSCREEN);
5723     buf[0] = 0;
5724     size = MAX_PATH;
5725     r = MsiGetPropertyA(hpkg, "ScreenY", buf, &size);
5726     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
5727     ok(atol(buf) == res, "Expected %d, got %s\n", res, buf);
5728 
5729     buf[0] = 0;
5730     size = MAX_PATH;
5731     r = MsiGetPropertyA(hpkg, "MsiNetAssemblySupport", buf, &size);
5732     if (r == ERROR_SUCCESS) trace( "MsiNetAssemblySupport \"%s\"\n", buf );
5733 
5734     GetNativeSystemInfo(&si);
5735 
5736     sprintf(buf, "%d", LOBYTE(LOWORD(GetVersion())) * 100 + HIBYTE(LOWORD(GetVersion())));
5737     check_prop(hpkg, "VersionNT", buf, 1);
5738 
5739     if (S(U(si)).wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
5740     {
5741         sprintf(buf, "%d", si.wProcessorLevel);
5742         check_prop(hpkg, "Intel", buf, 1);
5743         check_prop(hpkg, "MsiAMD64", buf, 1);
5744         check_prop(hpkg, "Msix64", buf, 1);
5745         sprintf(buf, "%d", LOBYTE(LOWORD(GetVersion())) * 100 + HIBYTE(LOWORD(GetVersion())));
5746         check_prop(hpkg, "VersionNT64", buf, 1);
5747 
5748         GetSystemDirectoryA(path, MAX_PATH);
5749         strcat(path, "\\");
5750         check_prop(hpkg, "System64Folder", path, 0);
5751 
5752         GetSystemWow64DirectoryA(path, MAX_PATH);
5753         strcat(path, "\\");
5754         check_prop(hpkg, "SystemFolder", path, 0);
5755 
5756         size = MAX_PATH;
5757         r = RegQueryValueExA(pathkey, "ProgramFilesDir (x86)", 0, &type, (BYTE *)path, &size);
5758         strcat(path, "\\");
5759         check_prop(hpkg, "ProgramFilesFolder", path, 0);
5760 
5761         size = MAX_PATH;
5762         RegQueryValueExA(pathkey, "ProgramFilesDir", 0, &type, (BYTE *)path, &size);
5763         strcat(path, "\\");
5764         check_prop(hpkg, "ProgramFiles64Folder", path, 0);
5765 
5766         size = MAX_PATH;
5767         RegQueryValueExA(pathkey, "CommonFilesDir (x86)", 0, &type, (BYTE *)path, &size);
5768         strcat(path, "\\");
5769         check_prop(hpkg, "CommonFilesFolder", path, 0);
5770 
5771         size = MAX_PATH;
5772         RegQueryValueExA(pathkey, "CommonFilesDir", 0, &type, (BYTE *)path, &size);
5773         strcat(path, "\\");
5774         check_prop(hpkg, "CommonFiles64Folder", path, 0);
5775     }
5776     else if (S(U(si)).wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
5777     {
5778         sprintf(buf, "%d", si.wProcessorLevel);
5779         check_prop(hpkg, "Intel", buf, 1);
5780 
5781         GetSystemDirectoryA(path, MAX_PATH);
5782         strcat(path, "\\");
5783         check_prop(hpkg, "SystemFolder", path, 0);
5784 
5785         size = MAX_PATH;
5786         RegQueryValueExA(pathkey, "ProgramFilesDir", 0, &type, (BYTE *)path, &size);
5787         strcat(path, "\\");
5788         check_prop(hpkg, "ProgramFilesFolder", path, 0);
5789 
5790         size = MAX_PATH;
5791         RegQueryValueExA(pathkey, "CommonFilesDir", 0, &type, (BYTE *)path, &size);
5792         strcat(path, "\\");
5793         check_prop(hpkg, "CommonFilesFolder", path, 0);
5794 
5795         check_prop(hpkg, "MsiAMD64", "", 1);
5796         check_prop(hpkg, "Msix64", "", 1);
5797         check_prop(hpkg, "VersionNT64", "", 1);
5798         check_prop(hpkg, "System64Folder", "", 0);
5799         check_prop(hpkg, "ProgramFiles64Dir", "", 0);
5800         check_prop(hpkg, "CommonFiles64Dir", "", 0);
5801     }
5802 
5803     CloseHandle(hkey1);
5804     CloseHandle(hkey2);
5805     RegCloseKey(pathkey);
5806     MsiCloseHandle(hpkg);
5807     DeleteFileA(msifile);
5808     MsiSetInternalUI(uilevel, NULL);
5809 }
5810 
5811 static void test_launchconditions(void)
5812 {
5813     MSIHANDLE hpkg;
5814     MSIHANDLE hdb;
5815     UINT r;
5816 
5817     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5818 
5819     hdb = create_package_db();
5820     ok( hdb, "failed to create package database\n" );
5821 
5822     create_launchcondition_table( hdb );
5823 
5824     add_launchcondition_entry( hdb, "'X = \"1\"', 'one'" );
5825 
5826     /* invalid condition */
5827     add_launchcondition_entry( hdb, "'X != \"1\"', 'one'" );
5828 
5829     r = package_from_db( hdb, &hpkg );
5830     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5831     {
5832         skip("Not enough rights to perform tests\n");
5833         DeleteFileA(msifile);
5834         return;
5835     }
5836     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
5837 
5838     MsiCloseHandle( hdb );
5839 
5840     r = MsiSetPropertyA( hpkg, "X", "1" );
5841     ok( r == ERROR_SUCCESS, "failed to set property\n" );
5842 
5843     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5844 
5845     /* invalid conditions are ignored */
5846     r = MsiDoActionA( hpkg, "LaunchConditions" );
5847     ok( r == ERROR_SUCCESS, "cost init failed\n" );
5848 
5849     /* verify LaunchConditions still does some verification */
5850     r = MsiSetPropertyA( hpkg, "X", "2" );
5851     ok( r == ERROR_SUCCESS, "failed to set property\n" );
5852 
5853     r = MsiDoActionA( hpkg, "LaunchConditions" );
5854     ok( r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %d\n", r );
5855 
5856     MsiCloseHandle( hpkg );
5857     DeleteFileA( msifile );
5858 }
5859 
5860 static void test_ccpsearch(void)
5861 {
5862     MSIHANDLE hdb, hpkg;
5863     CHAR prop[MAX_PATH];
5864     DWORD size = MAX_PATH;
5865     UINT r;
5866 
5867     hdb = create_package_db();
5868     ok(hdb, "failed to create package database\n");
5869 
5870     create_ccpsearch_table(hdb);
5871     add_ccpsearch_entry(hdb, "'CCP_random'");
5872     add_ccpsearch_entry(hdb, "'RMCCP_random'");
5873 
5874     create_reglocator_table(hdb);
5875     add_reglocator_entry(hdb, "CCP_random", 0, "htmlfile\\shell\\open\\nonexistent", "", 1);
5876 
5877     create_drlocator_table(hdb);
5878     add_drlocator_entry(hdb, "'RMCCP_random', '', 'C:\\', '0'");
5879 
5880     create_signature_table(hdb);
5881 
5882     r = package_from_db(hdb, &hpkg);
5883     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5884     {
5885         skip("Not enough rights to perform tests\n");
5886         DeleteFileA(msifile);
5887         return;
5888     }
5889     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
5890 
5891     MsiCloseHandle(hdb);
5892 
5893     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5894 
5895     r = MsiDoActionA(hpkg, "CCPSearch");
5896     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5897 
5898     r = MsiGetPropertyA(hpkg, "CCP_Success", prop, &size);
5899     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5900     ok(!lstrcmpA(prop, "1"), "Expected 1, got %s\n", prop);
5901 
5902     MsiCloseHandle(hpkg);
5903     DeleteFileA(msifile);
5904 }
5905 
5906 static void test_complocator(void)
5907 {
5908     MSIHANDLE hdb, hpkg;
5909     UINT r;
5910     CHAR prop[MAX_PATH];
5911     CHAR expected[MAX_PATH];
5912     DWORD size = MAX_PATH;
5913 
5914     hdb = create_package_db();
5915     ok(hdb, "failed to create package database\n");
5916 
5917     create_appsearch_table(hdb);
5918     add_appsearch_entry(hdb, "'ABELISAURUS', 'abelisaurus'");
5919     add_appsearch_entry(hdb, "'BACTROSAURUS', 'bactrosaurus'");
5920     add_appsearch_entry(hdb, "'CAMELOTIA', 'camelotia'");
5921     add_appsearch_entry(hdb, "'DICLONIUS', 'diclonius'");
5922     add_appsearch_entry(hdb, "'ECHINODON', 'echinodon'");
5923     add_appsearch_entry(hdb, "'FALCARIUS', 'falcarius'");
5924     add_appsearch_entry(hdb, "'GALLIMIMUS', 'gallimimus'");
5925     add_appsearch_entry(hdb, "'HAGRYPHUS', 'hagryphus'");
5926     add_appsearch_entry(hdb, "'IGUANODON', 'iguanodon'");
5927     add_appsearch_entry(hdb, "'JOBARIA', 'jobaria'");
5928     add_appsearch_entry(hdb, "'KAKURU', 'kakuru'");
5929     add_appsearch_entry(hdb, "'LABOCANIA', 'labocania'");
5930     add_appsearch_entry(hdb, "'MEGARAPTOR', 'megaraptor'");
5931     add_appsearch_entry(hdb, "'NEOSODON', 'neosodon'");
5932     add_appsearch_entry(hdb, "'OLOROTITAN', 'olorotitan'");
5933     add_appsearch_entry(hdb, "'PANTYDRACO', 'pantydraco'");
5934 
5935     create_complocator_table(hdb);
5936     add_complocator_entry(hdb, "'abelisaurus', '{E3619EED-305A-418C-B9C7-F7D7377F0934}', 1");
5937     add_complocator_entry(hdb, "'bactrosaurus', '{D56B688D-542F-42Ef-90FD-B6DA76EE8119}', 0");
5938     add_complocator_entry(hdb, "'camelotia', '{8211BE36-2466-47E3-AFB7-6AC72E51AED2}', 1");
5939     add_complocator_entry(hdb, "'diclonius', '{5C767B20-A33C-45A4-B80B-555E512F01AE}', 0");
5940     add_complocator_entry(hdb, "'echinodon', '{A19E16C5-C75D-4699-8111-C4338C40C3CB}', 1");
5941     add_complocator_entry(hdb, "'falcarius', '{17762FA1-A7AE-4CC6-8827-62873C35361D}', 0");
5942     add_complocator_entry(hdb, "'gallimimus', '{75EBF568-C959-41E0-A99E-9050638CF5FB}', 1");
5943     add_complocator_entry(hdb, "'hagrphus', '{D4969B72-17D9-4AB6-BE49-78F2FEE857AC}', 0");
5944     add_complocator_entry(hdb, "'iguanodon', '{8E0DA02E-F6A7-4A8F-B25D-6F564C492308}', 1");
5945     add_complocator_entry(hdb, "'jobaria', '{243C22B1-8C51-4151-B9D1-1AE5265E079E}', 0");
5946     add_complocator_entry(hdb, "'kakuru', '{5D0F03BA-50BC-44F2-ABB1-72C972F4E514}', 1");
5947     add_complocator_entry(hdb, "'labocania', '{C7DDB60C-7828-4046-A6F8-699D5E92F1ED}', 0");
5948     add_complocator_entry(hdb, "'megaraptor', '{8B1034B7-BD5E-41ac-B52C-0105D3DFD74D}', 1");
5949     add_complocator_entry(hdb, "'neosodon', '{0B499649-197A-48EF-93D2-AF1C17ED6E90}', 0");
5950     add_complocator_entry(hdb, "'olorotitan', '{54E9E91F-AED2-46D5-A25A-7E50AFA24513}', 1");
5951     add_complocator_entry(hdb, "'pantydraco', '{2A989951-5565-4FA7-93A7-E800A3E67D71}', 0");
5952 
5953     create_signature_table(hdb);
5954     add_signature_entry(hdb, "'abelisaurus', 'abelisaurus', '', '', '', '', '', '', ''");
5955     add_signature_entry(hdb, "'bactrosaurus', 'bactrosaurus', '', '', '', '', '', '', ''");
5956     add_signature_entry(hdb, "'camelotia', 'camelotia', '', '', '', '', '', '', ''");
5957     add_signature_entry(hdb, "'diclonius', 'diclonius', '', '', '', '', '', '', ''");
5958     add_signature_entry(hdb, "'iguanodon', 'iguanodon', '', '', '', '', '', '', ''");
5959     add_signature_entry(hdb, "'jobaria', 'jobaria', '', '', '', '', '', '', ''");
5960     add_signature_entry(hdb, "'kakuru', 'kakuru', '', '', '', '', '', '', ''");
5961     add_signature_entry(hdb, "'labocania', 'labocania', '', '', '', '', '', '', ''");
5962 
5963     r = package_from_db(hdb, &hpkg);
5964     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5965     {
5966         skip("Not enough rights to perform tests\n");
5967         DeleteFileA(msifile);
5968         return;
5969     }
5970     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
5971 
5972     MsiCloseHandle(hdb);
5973 
5974     create_test_file("abelisaurus");
5975     create_test_file("bactrosaurus");
5976     create_test_file("camelotia");
5977     create_test_file("diclonius");
5978     create_test_file("echinodon");
5979     create_test_file("falcarius");
5980     create_test_file("gallimimus");
5981     create_test_file("hagryphus");
5982     CreateDirectoryA("iguanodon", NULL);
5983     CreateDirectoryA("jobaria", NULL);
5984     CreateDirectoryA("kakuru", NULL);
5985     CreateDirectoryA("labocania", NULL);
5986     CreateDirectoryA("megaraptor", NULL);
5987     CreateDirectoryA("neosodon", NULL);
5988     CreateDirectoryA("olorotitan", NULL);
5989     CreateDirectoryA("pantydraco", NULL);
5990 
5991     set_component_path("abelisaurus", MSIINSTALLCONTEXT_MACHINE,
5992                        "{E3619EED-305A-418C-B9C7-F7D7377F0934}", NULL, FALSE);
5993     set_component_path("bactrosaurus", MSIINSTALLCONTEXT_MACHINE,
5994                        "{D56B688D-542F-42Ef-90FD-B6DA76EE8119}", NULL, FALSE);
5995     set_component_path("echinodon", MSIINSTALLCONTEXT_MACHINE,
5996                        "{A19E16C5-C75D-4699-8111-C4338C40C3CB}", NULL, FALSE);
5997     set_component_path("falcarius", MSIINSTALLCONTEXT_MACHINE,
5998                        "{17762FA1-A7AE-4CC6-8827-62873C35361D}", NULL, FALSE);
5999     set_component_path("iguanodon", MSIINSTALLCONTEXT_MACHINE,
6000                        "{8E0DA02E-F6A7-4A8F-B25D-6F564C492308}", NULL, FALSE);
6001     set_component_path("jobaria", MSIINSTALLCONTEXT_MACHINE,
6002                        "{243C22B1-8C51-4151-B9D1-1AE5265E079E}", NULL, FALSE);
6003     set_component_path("megaraptor", MSIINSTALLCONTEXT_MACHINE,
6004                        "{8B1034B7-BD5E-41ac-B52C-0105D3DFD74D}", NULL, FALSE);
6005     set_component_path("neosodon", MSIINSTALLCONTEXT_MACHINE,
6006                        "{0B499649-197A-48EF-93D2-AF1C17ED6E90}", NULL, FALSE);
6007 
6008     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
6009 
6010     r = MsiDoActionA(hpkg, "AppSearch");
6011     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6012 
6013     size = MAX_PATH;
6014     r = MsiGetPropertyA(hpkg, "ABELISAURUS", prop, &size);
6015     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6016 
6017     lstrcpyA(expected, CURR_DIR);
6018     if (!is_root(CURR_DIR)) lstrcatA(expected, "\\");
6019     lstrcatA(expected, "abelisaurus");
6020     ok(!lstrcmpA(prop, expected) || !lstrcmpA(prop, ""),
6021        "Expected %s or empty string, got %s\n", expected, prop);
6022 
6023     size = MAX_PATH;
6024     r = MsiGetPropertyA(hpkg, "BACTROSAURUS", prop, &size);
6025     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6026     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6027 
6028     size = MAX_PATH;
6029     r = MsiGetPropertyA(hpkg, "CAMELOTIA", prop, &size);
6030     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6031     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6032 
6033     size = MAX_PATH;
6034     r = MsiGetPropertyA(hpkg, "DICLONIUS", prop, &size);
6035     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6036     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6037 
6038     size = MAX_PATH;
6039     r = MsiGetPropertyA(hpkg, "ECHINODON", prop, &size);
6040     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6041 
6042     lstrcpyA(expected, CURR_DIR);
6043     if (!is_root(CURR_DIR)) lstrcatA(expected, "\\");
6044     ok(!lstrcmpA(prop, expected) || !lstrcmpA(prop, ""),
6045        "Expected %s or empty string, got %s\n", expected, prop);
6046 
6047     size = MAX_PATH;
6048     r = MsiGetPropertyA(hpkg, "FALCARIUS", prop, &size);
6049     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6050     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6051 
6052     size = MAX_PATH;
6053     r = MsiGetPropertyA(hpkg, "GALLIMIMUS", prop, &size);
6054     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6055     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6056 
6057     size = MAX_PATH;
6058     r = MsiGetPropertyA(hpkg, "HAGRYPHUS", prop, &size);
6059     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6060     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6061 
6062     size = MAX_PATH;
6063     r = MsiGetPropertyA(hpkg, "IGUANODON", prop, &size);
6064     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6065     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6066 
6067     size = MAX_PATH;
6068     r = MsiGetPropertyA(hpkg, "JOBARIA", prop, &size);
6069     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6070     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6071 
6072     size = MAX_PATH;
6073     r = MsiGetPropertyA(hpkg, "KAKURU", prop, &size);
6074     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6075     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6076 
6077     size = MAX_PATH;
6078     r = MsiGetPropertyA(hpkg, "LABOCANIA", prop, &size);
6079     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6080     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6081 
6082     size = MAX_PATH;
6083     r = MsiGetPropertyA(hpkg, "MEGARAPTOR", prop, &size);
6084     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6085 
6086     lstrcpyA(expected, CURR_DIR);
6087     if (!is_root(CURR_DIR)) lstrcatA(expected, "\\");
6088     ok(!lstrcmpA(prop, expected) || !lstrcmpA(prop, ""),
6089        "Expected %s or empty string, got %s\n", expected, prop);
6090 
6091     size = MAX_PATH;
6092     r = MsiGetPropertyA(hpkg, "NEOSODON", prop, &size);
6093     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6094 
6095     lstrcpyA(expected, CURR_DIR);
6096     if (!is_root(CURR_DIR)) lstrcatA(expected, "\\");
6097     lstrcatA(expected, "neosodon\\");
6098     ok(!lstrcmpA(prop, expected) || !lstrcmpA(prop, ""),
6099        "Expected %s or empty string, got %s\n", expected, prop);
6100 
6101     size = MAX_PATH;
6102     r = MsiGetPropertyA(hpkg, "OLOROTITAN", prop, &size);
6103     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6104     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6105 
6106     size = MAX_PATH;
6107     r = MsiGetPropertyA(hpkg, "PANTYDRACO", prop, &size);
6108     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6109     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6110 
6111     MsiCloseHandle(hpkg);
6112     DeleteFileA("abelisaurus");
6113     DeleteFileA("bactrosaurus");
6114     DeleteFileA("camelotia");
6115     DeleteFileA("diclonius");
6116     DeleteFileA("echinodon");
6117     DeleteFileA("falcarius");
6118     DeleteFileA("gallimimus");
6119     DeleteFileA("hagryphus");
6120     RemoveDirectoryA("iguanodon");
6121     RemoveDirectoryA("jobaria");
6122     RemoveDirectoryA("kakuru");
6123     RemoveDirectoryA("labocania");
6124     RemoveDirectoryA("megaraptor");
6125     RemoveDirectoryA("neosodon");
6126     RemoveDirectoryA("olorotitan");
6127     RemoveDirectoryA("pantydraco");
6128     delete_component_path("{E3619EED-305A-418C-B9C7-F7D7377F0934}",
6129                           MSIINSTALLCONTEXT_MACHINE, NULL);
6130     delete_component_path("{D56B688D-542F-42Ef-90FD-B6DA76EE8119}",
6131                           MSIINSTALLCONTEXT_MACHINE, NULL);
6132     delete_component_path("{A19E16C5-C75D-4699-8111-C4338C40C3CB}",
6133                           MSIINSTALLCONTEXT_MACHINE, NULL);
6134     delete_component_path("{17762FA1-A7AE-4CC6-8827-62873C35361D}",
6135                           MSIINSTALLCONTEXT_MACHINE, NULL);
6136     delete_component_path("{8E0DA02E-F6A7-4A8F-B25D-6F564C492308}",
6137                           MSIINSTALLCONTEXT_MACHINE, NULL);
6138     delete_component_path("{243C22B1-8C51-4151-B9D1-1AE5265E079E}",
6139                           MSIINSTALLCONTEXT_MACHINE, NULL);
6140     delete_component_path("{8B1034B7-BD5E-41ac-B52C-0105D3DFD74D}",
6141                           MSIINSTALLCONTEXT_MACHINE, NULL);
6142     delete_component_path("{0B499649-197A-48EF-93D2-AF1C17ED6E90}",
6143                           MSIINSTALLCONTEXT_MACHINE, NULL);
6144     DeleteFileA(msifile);
6145 }
6146 
6147 static void set_suminfo_prop(MSIHANDLE db, DWORD prop, DWORD val)
6148 {
6149     MSIHANDLE summary;
6150     UINT r;
6151 
6152     r = MsiGetSummaryInformationA(db, NULL, 1, &summary);
6153     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6154 
6155     r = MsiSummaryInfoSetPropertyA(summary, prop, VT_I4, val, NULL, NULL);
6156     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6157 
6158     r = MsiSummaryInfoPersist(summary);
6159     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
6160 
6161     MsiCloseHandle(summary);
6162 }
6163 
6164 static void test_MsiGetSourcePath(void)
6165 {
6166     MSIHANDLE hdb, hpkg;
6167     CHAR path[MAX_PATH];
6168     CHAR cwd[MAX_PATH];
6169     CHAR subsrc[MAX_PATH];
6170     CHAR sub2[MAX_PATH];
6171     DWORD size;
6172     UINT r;
6173 
6174     lstrcpyA(cwd, CURR_DIR);
6175     if (!is_root(CURR_DIR)) lstrcatA(cwd, "\\");
6176 
6177     lstrcpyA(subsrc, cwd);
6178     lstrcatA(subsrc, "subsource");
6179     lstrcatA(subsrc, "\\");
6180 
6181     lstrcpyA(sub2, subsrc);
6182     lstrcatA(sub2, "sub2");
6183     lstrcatA(sub2, "\\");
6184 
6185     /* uncompressed source */
6186 
6187     hdb = create_package_db();
6188     ok( hdb, "failed to create database\n");
6189 
6190     set_suminfo_prop(hdb, PID_WORDCOUNT, 0);
6191 
6192     add_directory_entry(hdb, "'TARGETDIR', '', 'SourceDir'");
6193     add_directory_entry(hdb, "'SubDir', 'TARGETDIR', 'subtarget:subsource'");
6194     add_directory_entry(hdb, "'SubDir2', 'SubDir', 'sub2'");
6195 
6196     r = MsiDatabaseCommit(hdb);
6197     ok(r == ERROR_SUCCESS , "Failed to commit database\n");
6198 
6199     r = package_from_db(hdb, &hpkg);
6200     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
6201     {
6202         skip("Not enough rights to perform tests\n");
6203         DeleteFileA(msifile);
6204         return;
6205     }
6206     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
6207 
6208     MsiCloseHandle(hdb);
6209 
6210     /* invalid database handle */
6211     size = MAX_PATH;
6212     lstrcpyA(path, "kiwi");
6213     r = MsiGetSourcePathA(-1, "TARGETDIR", path, &size);
6214     ok(r == ERROR_INVALID_HANDLE,
6215        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
6216     ok(!lstrcmpA(path, "kiwi"),
6217        "Expected path to be unchanged, got \"%s\"\n", path);
6218     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6219 
6220     /* NULL szFolder */
6221     size = MAX_PATH;
6222     lstrcpyA(path, "kiwi");
6223     r = MsiGetSourcePathA(hpkg, NULL, path, &size);
6224     ok(r == ERROR_INVALID_PARAMETER,
6225        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6226     ok(!lstrcmpA(path, "kiwi"),
6227        "Expected path to be unchanged, got \"%s\"\n", path);
6228     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6229 
6230     /* empty szFolder */
6231     size = MAX_PATH;
6232     lstrcpyA(path, "kiwi");
6233     r = MsiGetSourcePathA(hpkg, "", path, &size);
6234     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6235     ok(!lstrcmpA(path, "kiwi"),
6236        "Expected path to be unchanged, got \"%s\"\n", path);
6237     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6238 
6239     /* try TARGETDIR */
6240     size = MAX_PATH;
6241     lstrcpyA(path, "kiwi");
6242     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6243     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6244     ok(!lstrcmpA(path, "kiwi"),
6245        "Expected path to be unchanged, got \"%s\"\n", path);
6246     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6247 
6248     size = MAX_PATH;
6249     lstrcpyA(path, "kiwi");
6250     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6251     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6252     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6253     ok(size == 0, "Expected 0, got %lu\n", size);
6254 
6255     size = MAX_PATH;
6256     lstrcpyA(path, "kiwi");
6257     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6258     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6259     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6260     ok(size == 0, "Expected 0, got %lu\n", size);
6261 
6262     /* try SourceDir */
6263     size = MAX_PATH;
6264     lstrcpyA(path, "kiwi");
6265     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6266     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6267     ok(!lstrcmpA(path, "kiwi"),
6268        "Expected path to be unchanged, got \"%s\"\n", path);
6269     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6270 
6271     /* try SOURCEDIR */
6272     size = MAX_PATH;
6273     lstrcpyA(path, "kiwi");
6274     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6275     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6276     ok(!lstrcmpA(path, "kiwi"),
6277        "Expected path to be unchanged, got \"%s\"\n", path);
6278     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6279 
6280     /* source path does not exist, but the property exists */
6281     size = MAX_PATH;
6282     lstrcpyA(path, "kiwi");
6283     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6284     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6285     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6286     ok(size == 0, "Expected 0, got %lu\n", size);
6287 
6288     size = MAX_PATH;
6289     lstrcpyA(path, "kiwi");
6290     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6291     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6292     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6293     ok(size == 0, "Expected 0, got %lu\n", size);
6294 
6295     /* try SubDir */
6296     size = MAX_PATH;
6297     lstrcpyA(path, "kiwi");
6298     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6299     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6300     ok(!lstrcmpA(path, "kiwi"),
6301        "Expected path to be unchanged, got \"%s\"\n", path);
6302     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6303 
6304     /* try SubDir2 */
6305     size = MAX_PATH;
6306     lstrcpyA(path, "kiwi");
6307     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6308     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6309     ok(!lstrcmpA(path, "kiwi"),
6310        "Expected path to be unchanged, got \"%s\"\n", path);
6311     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6312 
6313     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
6314 
6315     r = MsiDoActionA(hpkg, "CostInitialize");
6316     ok(r == ERROR_SUCCESS, "cost init failed\n");
6317 
6318     /* try TARGETDIR after CostInitialize */
6319     size = MAX_PATH;
6320     lstrcpyA(path, "kiwi");
6321     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6322     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6323     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6324     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6325 
6326     /* try SourceDir after CostInitialize */
6327     size = MAX_PATH;
6328     lstrcpyA(path, "kiwi");
6329     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6330     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6331     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6332     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6333 
6334     /* try SOURCEDIR after CostInitialize */
6335     size = MAX_PATH;
6336     lstrcpyA(path, "kiwi");
6337     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6338     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6339     ok(!lstrcmpA(path, "kiwi"),
6340        "Expected path to be unchanged, got \"%s\"\n", path);
6341     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6342 
6343     /* source path does not exist, but the property exists */
6344     size = MAX_PATH;
6345     lstrcpyA(path, "kiwi");
6346     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6347     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6348     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6349     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6350 
6351     size = MAX_PATH;
6352     lstrcpyA(path, "kiwi");
6353     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6354     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6355     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6356     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6357 
6358     /* try SubDir after CostInitialize */
6359     size = MAX_PATH;
6360     lstrcpyA(path, "kiwi");
6361     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6362     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6363     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6364     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
6365 
6366     /* try SubDir2 after CostInitialize */
6367     size = MAX_PATH;
6368     lstrcpyA(path, "kiwi");
6369     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6370     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6371     ok(!lstrcmpA(path, sub2), "Expected \"%s\", got \"%s\"\n", sub2, path);
6372     ok(size == lstrlenA(sub2), "Expected %d, got %lu\n", lstrlenA(sub2), size);
6373 
6374     r = MsiDoActionA(hpkg, "ResolveSource");
6375     ok(r == ERROR_SUCCESS, "file cost failed\n");
6376 
6377     /* try TARGETDIR after ResolveSource */
6378     size = MAX_PATH;
6379     lstrcpyA(path, "kiwi");
6380     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6381     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6382     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6383     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6384 
6385     /* try SourceDir after ResolveSource */
6386     size = MAX_PATH;
6387     lstrcpyA(path, "kiwi");
6388     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6389     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6390     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6391     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6392 
6393     /* try SOURCEDIR after ResolveSource */
6394     size = MAX_PATH;
6395     lstrcpyA(path, "kiwi");
6396     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6397     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6398     ok(!lstrcmpA(path, "kiwi"),
6399        "Expected path to be unchanged, got \"%s\"\n", path);
6400     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6401 
6402     /* source path does not exist, but the property exists */
6403     size = MAX_PATH;
6404     lstrcpyA(path, "kiwi");
6405     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6406     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6407     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6408     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6409 
6410     size = MAX_PATH;
6411     lstrcpyA(path, "kiwi");
6412     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6413     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6414     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6415     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6416 
6417     /* try SubDir after ResolveSource */
6418     size = MAX_PATH;
6419     lstrcpyA(path, "kiwi");
6420     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6421     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6422     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6423     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
6424 
6425     /* try SubDir2 after ResolveSource */
6426     size = MAX_PATH;
6427     lstrcpyA(path, "kiwi");
6428     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6429     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6430     ok(!lstrcmpA(path, sub2), "Expected \"%s\", got \"%s\"\n", sub2, path);
6431     ok(size == lstrlenA(sub2), "Expected %d, got %lu\n", lstrlenA(sub2), size);
6432 
6433     r = MsiDoActionA(hpkg, "FileCost");
6434     ok(r == ERROR_SUCCESS, "file cost failed\n");
6435 
6436     /* try TARGETDIR after FileCost */
6437     size = MAX_PATH;
6438     lstrcpyA(path, "kiwi");
6439     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6440     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6441     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6442     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6443 
6444     /* try SourceDir after FileCost */
6445     size = MAX_PATH;
6446     lstrcpyA(path, "kiwi");
6447     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6448     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6449     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6450     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6451 
6452     /* try SOURCEDIR after FileCost */
6453     size = MAX_PATH;
6454     lstrcpyA(path, "kiwi");
6455     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6456     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6457     ok(!lstrcmpA(path, "kiwi"),
6458        "Expected path to be unchanged, got \"%s\"\n", path);
6459     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6460 
6461     /* source path does not exist, but the property exists */
6462     size = MAX_PATH;
6463     lstrcpyA(path, "kiwi");
6464     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6465     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6466     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6467     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6468 
6469     size = MAX_PATH;
6470     lstrcpyA(path, "kiwi");
6471     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6472     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6473     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6474     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6475 
6476     /* try SubDir after FileCost */
6477     size = MAX_PATH;
6478     lstrcpyA(path, "kiwi");
6479     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6480     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6481     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6482     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
6483 
6484     /* try SubDir2 after FileCost */
6485     size = MAX_PATH;
6486     lstrcpyA(path, "kiwi");
6487     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6488     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6489     ok(!lstrcmpA(path, sub2), "Expected \"%s\", got \"%s\"\n", sub2, path);
6490     ok(size == lstrlenA(sub2), "Expected %d, got %lu\n", lstrlenA(sub2), size);
6491 
6492     r = MsiDoActionA(hpkg, "CostFinalize");
6493     ok(r == ERROR_SUCCESS, "file cost failed\n");
6494 
6495     /* try TARGETDIR after CostFinalize */
6496     size = MAX_PATH;
6497     lstrcpyA(path, "kiwi");
6498     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6499     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6500     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6501     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6502 
6503     /* try SourceDir after CostFinalize */
6504     size = MAX_PATH;
6505     lstrcpyA(path, "kiwi");
6506     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6507     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6508     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6509     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6510 
6511     /* try SOURCEDIR after CostFinalize */
6512     size = MAX_PATH;
6513     lstrcpyA(path, "kiwi");
6514     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6515     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6516     ok(!lstrcmpA(path, "kiwi"),
6517        "Expected path to be unchanged, got \"%s\"\n", path);
6518     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6519 
6520     /* source path does not exist, but the property exists */
6521     size = MAX_PATH;
6522     lstrcpyA(path, "kiwi");
6523     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6524     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6525     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6526     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6527 
6528     size = MAX_PATH;
6529     lstrcpyA(path, "kiwi");
6530     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6531     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6532     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6533     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6534 
6535     /* try SubDir after CostFinalize */
6536     size = MAX_PATH;
6537     lstrcpyA(path, "kiwi");
6538     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6539     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6540     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6541     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
6542 
6543     /* try SubDir2 after CostFinalize */
6544     size = MAX_PATH;
6545     lstrcpyA(path, "kiwi");
6546     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6547     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6548     ok(!lstrcmpA(path, sub2), "Expected \"%s\", got \"%s\"\n", sub2, path);
6549     ok(size == lstrlenA(sub2), "Expected %d, got %lu\n", lstrlenA(sub2), size);
6550 
6551     /* nonexistent directory */
6552     size = MAX_PATH;
6553     lstrcpyA(path, "kiwi");
6554     r = MsiGetSourcePathA(hpkg, "IDontExist", path, &size);
6555     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6556     ok(!lstrcmpA(path, "kiwi"),
6557        "Expected path to be unchanged, got \"%s\"\n", path);
6558     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6559 
6560     /* NULL szPathBuf */
6561     size = MAX_PATH;
6562     r = MsiGetSourcePathA(hpkg, "SourceDir", NULL, &size);
6563     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6564     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6565 
6566     /* NULL pcchPathBuf */
6567     lstrcpyA(path, "kiwi");
6568     r = MsiGetSourcePathA(hpkg, "SourceDir", path, NULL);
6569     ok(r == ERROR_INVALID_PARAMETER,
6570        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6571     ok(!lstrcmpA(path, "kiwi"),
6572        "Expected path to be unchanged, got \"%s\"\n", path);
6573 
6574     /* pcchPathBuf is 0 */
6575     size = 0;
6576     lstrcpyA(path, "kiwi");
6577     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6578     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
6579     ok(!lstrcmpA(path, "kiwi"),
6580        "Expected path to be unchanged, got \"%s\"\n", path);
6581     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6582 
6583     /* pcchPathBuf does not have room for NULL terminator */
6584     size = lstrlenA(cwd);
6585     lstrcpyA(path, "kiwi");
6586     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6587     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
6588     ok(!strncmp(path, cwd, lstrlenA(cwd) - 1),
6589        "Expected path with no backslash, got \"%s\"\n", path);
6590     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6591 
6592     /* pcchPathBuf has room for NULL terminator */
6593     size = lstrlenA(cwd) + 1;
6594     lstrcpyA(path, "kiwi");
6595     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6596     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6597     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6598     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6599 
6600     /* remove property */
6601     r = MsiSetPropertyA(hpkg, "SourceDir", NULL);
6602     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6603 
6604     /* try SourceDir again */
6605     size = MAX_PATH;
6606     lstrcpyA(path, "kiwi");
6607     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6608     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6609     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6610     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6611 
6612     /* set property to a valid directory */
6613     r = MsiSetPropertyA(hpkg, "SOURCEDIR", cwd);
6614     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6615 
6616     /* try SOURCEDIR again */
6617     size = MAX_PATH;
6618     lstrcpyA(path, "kiwi");
6619     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6620     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6621     ok(!lstrcmpA(path, "kiwi"),
6622        "Expected path to be unchanged, got \"%s\"\n", path);
6623     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6624 
6625     MsiCloseHandle(hpkg);
6626 
6627     /* compressed source */
6628 
6629     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb);
6630     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6631 
6632     set_suminfo_prop(hdb, PID_WORDCOUNT, msidbSumInfoSourceTypeCompressed);
6633 
6634     r = package_from_db(hdb, &hpkg);
6635     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
6636 
6637     /* try TARGETDIR */
6638     size = MAX_PATH;
6639     lstrcpyA(path, "kiwi");
6640     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6641     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6642     ok(!lstrcmpA(path, "kiwi"),
6643        "Expected path to be unchanged, got \"%s\"\n", path);
6644     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6645 
6646     /* try SourceDir */
6647     size = MAX_PATH;
6648     lstrcpyA(path, "kiwi");
6649     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6650     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6651     ok(!lstrcmpA(path, "kiwi"),
6652        "Expected path to be unchanged, got \"%s\"\n", path);
6653     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6654 
6655     /* try SOURCEDIR */
6656     size = MAX_PATH;
6657     lstrcpyA(path, "kiwi");
6658     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6659     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6660     ok(!lstrcmpA(path, "kiwi"),
6661        "Expected path to be unchanged, got \"%s\"\n", path);
6662     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6663 
6664     /* source path nor the property exist */
6665     size = MAX_PATH;
6666     lstrcpyA(path, "kiwi");
6667     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6668     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6669     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6670     ok(size == 0, "Expected 0, got %lu\n", size);
6671 
6672     size = MAX_PATH;
6673     lstrcpyA(path, "kiwi");
6674     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6675     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6676     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6677     ok(size == 0, "Expected 0, got %lu\n", size);
6678 
6679     /* try SubDir */
6680     size = MAX_PATH;
6681     lstrcpyA(path, "kiwi");
6682     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6683     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6684     ok(!lstrcmpA(path, "kiwi"),
6685        "Expected path to be unchanged, got \"%s\"\n", path);
6686     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6687 
6688     /* try SubDir2 */
6689     size = MAX_PATH;
6690     lstrcpyA(path, "kiwi");
6691     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6692     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6693     ok(!lstrcmpA(path, "kiwi"),
6694        "Expected path to be unchanged, got \"%s\"\n", path);
6695     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6696 
6697     r = MsiDoActionA(hpkg, "CostInitialize");
6698     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6699 
6700     /* try TARGETDIR after CostInitialize */
6701     size = MAX_PATH;
6702     lstrcpyA(path, "kiwi");
6703     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6704     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6705     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6706     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6707 
6708     /* try SourceDir after CostInitialize */
6709     size = MAX_PATH;
6710     lstrcpyA(path, "kiwi");
6711     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6712     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6713     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6714     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6715 
6716     /* try SOURCEDIR after CostInitialize */
6717     size = MAX_PATH;
6718     lstrcpyA(path, "kiwi");
6719     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6720     todo_wine
6721     {
6722         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6723         ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6724         ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6725     }
6726 
6727     /* source path does not exist, but the property exists */
6728     size = MAX_PATH;
6729     lstrcpyA(path, "kiwi");
6730     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6731     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6732     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6733     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6734 
6735     size = MAX_PATH;
6736     lstrcpyA(path, "kiwi");
6737     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6738     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6739     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6740     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6741 
6742     /* try SubDir after CostInitialize */
6743     size = MAX_PATH;
6744     lstrcpyA(path, "kiwi");
6745     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6746     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6747     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6748     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6749 
6750     /* try SubDir2 after CostInitialize */
6751     size = MAX_PATH;
6752     lstrcpyA(path, "kiwi");
6753     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6754     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6755     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6756     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6757 
6758     r = MsiDoActionA(hpkg, "ResolveSource");
6759     ok(r == ERROR_SUCCESS, "file cost failed\n");
6760 
6761     /* try TARGETDIR after ResolveSource */
6762     size = MAX_PATH;
6763     lstrcpyA(path, "kiwi");
6764     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6765     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6766     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6767     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6768 
6769     /* try SourceDir after ResolveSource */
6770     size = MAX_PATH;
6771     lstrcpyA(path, "kiwi");
6772     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6773     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6774     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6775     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6776 
6777     /* try SOURCEDIR after ResolveSource */
6778     size = MAX_PATH;
6779     lstrcpyA(path, "kiwi");
6780     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6781     todo_wine
6782     {
6783         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6784         ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6785         ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6786     }
6787 
6788     /* source path and the property exist */
6789     size = MAX_PATH;
6790     lstrcpyA(path, "kiwi");
6791     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6792     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6793     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6794     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6795 
6796     size = MAX_PATH;
6797     lstrcpyA(path, "kiwi");
6798     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6799     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6800     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6801     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6802 
6803     /* try SubDir after ResolveSource */
6804     size = MAX_PATH;
6805     lstrcpyA(path, "kiwi");
6806     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6807     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6808     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6809     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6810 
6811     /* try SubDir2 after ResolveSource */
6812     size = MAX_PATH;
6813     lstrcpyA(path, "kiwi");
6814     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6815     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6816     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6817     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6818 
6819     r = MsiDoActionA(hpkg, "FileCost");
6820     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6821 
6822     /* try TARGETDIR after CostFinalize */
6823     size = MAX_PATH;
6824     lstrcpyA(path, "kiwi");
6825     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6826     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6827     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6828     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6829 
6830     /* try SourceDir after CostFinalize */
6831     size = MAX_PATH;
6832     lstrcpyA(path, "kiwi");
6833     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6834     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6835     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6836     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6837 
6838     /* try SOURCEDIR after CostFinalize */
6839     size = MAX_PATH;
6840     lstrcpyA(path, "kiwi");
6841     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6842     todo_wine
6843     {
6844         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6845         ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6846         ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6847     }
6848 
6849     /* source path and the property exist */
6850     size = MAX_PATH;
6851     lstrcpyA(path, "kiwi");
6852     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6853     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6854     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6855     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6856 
6857     size = MAX_PATH;
6858     lstrcpyA(path, "kiwi");
6859     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6860     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6861     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6862     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6863 
6864     /* try SubDir after CostFinalize */
6865     size = MAX_PATH;
6866     lstrcpyA(path, "kiwi");
6867     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6868     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6869     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6870     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6871 
6872     /* try SubDir2 after CostFinalize */
6873     size = MAX_PATH;
6874     lstrcpyA(path, "kiwi");
6875     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6876     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6877     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6878     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6879 
6880     r = MsiDoActionA(hpkg, "CostFinalize");
6881     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6882 
6883     /* try TARGETDIR after CostFinalize */
6884     size = MAX_PATH;
6885     lstrcpyA(path, "kiwi");
6886     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6887     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6888     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6889     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6890 
6891     /* try SourceDir after CostFinalize */
6892     size = MAX_PATH;
6893     lstrcpyA(path, "kiwi");
6894     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6895     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6896     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6897     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6898 
6899     /* try SOURCEDIR after CostFinalize */
6900     size = MAX_PATH;
6901     lstrcpyA(path, "kiwi");
6902     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6903     todo_wine
6904     {
6905         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6906         ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6907         ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6908     }
6909 
6910     /* source path and the property exist */
6911     size = MAX_PATH;
6912     lstrcpyA(path, "kiwi");
6913     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6914     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6915     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6916     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6917 
6918     size = MAX_PATH;
6919     lstrcpyA(path, "kiwi");
6920     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6921     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6922     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6923     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6924 
6925     /* try SubDir after CostFinalize */
6926     size = MAX_PATH;
6927     lstrcpyA(path, "kiwi");
6928     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6929     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6930     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6931     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6932 
6933     /* try SubDir2 after CostFinalize */
6934     size = MAX_PATH;
6935     lstrcpyA(path, "kiwi");
6936     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6937     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6938     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6939     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6940 
6941     MsiCloseHandle(hpkg);
6942     DeleteFileA(msifile);
6943 }
6944 
6945 static void test_shortlongsource(void)
6946 {
6947     MSIHANDLE hdb, hpkg;
6948     CHAR path[MAX_PATH];
6949     CHAR cwd[MAX_PATH];
6950     CHAR subsrc[MAX_PATH];
6951     DWORD size;
6952     UINT r;
6953 
6954     lstrcpyA(cwd, CURR_DIR);
6955     if (!is_root(CURR_DIR)) lstrcatA(cwd, "\\");
6956 
6957     lstrcpyA(subsrc, cwd);
6958     lstrcatA(subsrc, "long");
6959     lstrcatA(subsrc, "\\");
6960 
6961     /* long file names */
6962 
6963     hdb = create_package_db();
6964     ok( hdb, "failed to create database\n");
6965 
6966     set_suminfo_prop(hdb, PID_WORDCOUNT, 0);
6967 
6968     add_directory_entry(hdb, "'TARGETDIR', '', 'SourceDir'");
6969     add_directory_entry(hdb, "'SubDir', 'TARGETDIR', 'short|long'");
6970 
6971     /* CostInitialize:short */
6972     add_directory_entry(hdb, "'SubDir2', 'TARGETDIR', 'one|two'");
6973 
6974     /* CostInitialize:long */
6975     add_directory_entry(hdb, "'SubDir3', 'TARGETDIR', 'three|four'");
6976 
6977     /* FileCost:short */
6978     add_directory_entry(hdb, "'SubDir4', 'TARGETDIR', 'five|six'");
6979 
6980     /* FileCost:long */
6981     add_directory_entry(hdb, "'SubDir5', 'TARGETDIR', 'seven|eight'");
6982 
6983     /* CostFinalize:short */
6984     add_directory_entry(hdb, "'SubDir6', 'TARGETDIR', 'nine|ten'");
6985 
6986     /* CostFinalize:long */
6987     add_directory_entry(hdb, "'SubDir7', 'TARGETDIR', 'eleven|twelve'");
6988 
6989     r = MsiDatabaseCommit(hdb);
6990     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
6991 
6992     r = package_from_db(hdb, &hpkg);
6993     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
6994     {
6995         skip("Not enough rights to perform tests\n");
6996         DeleteFileA(msifile);
6997         return;
6998     }
6999     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
7000 
7001     MsiCloseHandle(hdb);
7002 
7003     CreateDirectoryA("one", NULL);
7004     CreateDirectoryA("four", NULL);
7005 
7006     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
7007 
7008     r = MsiDoActionA(hpkg, "CostInitialize");
7009     ok(r == ERROR_SUCCESS, "file cost failed\n");
7010 
7011     CreateDirectoryA("five", NULL);
7012     CreateDirectoryA("eight", NULL);
7013 
7014     r = MsiDoActionA(hpkg, "FileCost");
7015     ok(r == ERROR_SUCCESS, "file cost failed\n");
7016 
7017     CreateDirectoryA("nine", NULL);
7018     CreateDirectoryA("twelve", NULL);
7019 
7020     r = MsiDoActionA(hpkg, "CostFinalize");
7021     ok(r == ERROR_SUCCESS, "file cost failed\n");
7022 
7023     /* neither short nor long source directories exist */
7024     size = MAX_PATH;
7025     lstrcpyA(path, "kiwi");
7026     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7027     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7028     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7029     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
7030 
7031     CreateDirectoryA("short", NULL);
7032 
7033     /* short source directory exists */
7034     size = MAX_PATH;
7035     lstrcpyA(path, "kiwi");
7036     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7037     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7038     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7039     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
7040 
7041     CreateDirectoryA("long", NULL);
7042 
7043     /* both short and long source directories exist */
7044     size = MAX_PATH;
7045     lstrcpyA(path, "kiwi");
7046     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7047     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7048     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7049     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
7050 
7051     lstrcpyA(subsrc, cwd);
7052     lstrcatA(subsrc, "two");
7053     lstrcatA(subsrc, "\\");
7054 
7055     /* short dir exists before CostInitialize */
7056     size = MAX_PATH;
7057     lstrcpyA(path, "kiwi");
7058     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
7059     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7060     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7061     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
7062 
7063     lstrcpyA(subsrc, cwd);
7064     lstrcatA(subsrc, "four");
7065     lstrcatA(subsrc, "\\");
7066 
7067     /* long dir exists before CostInitialize */
7068     size = MAX_PATH;
7069     lstrcpyA(path, "kiwi");
7070     r = MsiGetSourcePathA(hpkg, "SubDir3", path, &size);
7071     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7072     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7073     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
7074 
7075     lstrcpyA(subsrc, cwd);
7076     lstrcatA(subsrc, "six");
7077     lstrcatA(subsrc, "\\");
7078 
7079     /* short dir exists before FileCost */
7080     size = MAX_PATH;
7081     lstrcpyA(path, "kiwi");
7082     r = MsiGetSourcePathA(hpkg, "SubDir4", path, &size);
7083     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7084     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7085     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
7086 
7087     lstrcpyA(subsrc, cwd);
7088     lstrcatA(subsrc, "eight");
7089     lstrcatA(subsrc, "\\");
7090 
7091     /* long dir exists before FileCost */
7092     size = MAX_PATH;
7093     lstrcpyA(path, "kiwi");
7094     r = MsiGetSourcePathA(hpkg, "SubDir5", path, &size);
7095     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7096     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7097     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
7098 
7099     lstrcpyA(subsrc, cwd);
7100     lstrcatA(subsrc, "ten");
7101     lstrcatA(subsrc, "\\");
7102 
7103     /* short dir exists before CostFinalize */
7104     size = MAX_PATH;
7105     lstrcpyA(path, "kiwi");
7106     r = MsiGetSourcePathA(hpkg, "SubDir6", path, &size);
7107     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7108     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7109     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
7110 
7111     lstrcpyA(subsrc, cwd);
7112     lstrcatA(subsrc, "twelve");
7113     lstrcatA(subsrc, "\\");
7114 
7115     /* long dir exists before CostFinalize */
7116     size = MAX_PATH;
7117     lstrcpyA(path, "kiwi");
7118     r = MsiGetSourcePathA(hpkg, "SubDir7", path, &size);
7119     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7120     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7121     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
7122 
7123     MsiCloseHandle(hpkg);
7124     RemoveDirectoryA("short");
7125     RemoveDirectoryA("long");
7126     RemoveDirectoryA("one");
7127     RemoveDirectoryA("four");
7128     RemoveDirectoryA("five");
7129     RemoveDirectoryA("eight");
7130     RemoveDirectoryA("nine");
7131     RemoveDirectoryA("twelve");
7132 
7133     /* short file names */
7134 
7135     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb);
7136     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7137 
7138     set_suminfo_prop(hdb, PID_WORDCOUNT, msidbSumInfoSourceTypeSFN);
7139 
7140     r = package_from_db(hdb, &hpkg);
7141     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
7142 
7143     MsiCloseHandle(hdb);
7144 
7145     CreateDirectoryA("one", NULL);
7146     CreateDirectoryA("four", NULL);
7147 
7148     r = MsiDoActionA(hpkg, "CostInitialize");
7149     ok(r == ERROR_SUCCESS, "file cost failed\n");
7150 
7151     CreateDirectoryA("five", NULL);
7152     CreateDirectoryA("eight", NULL);
7153 
7154     r = MsiDoActionA(hpkg, "FileCost");
7155     ok(r == ERROR_SUCCESS, "file cost failed\n");
7156 
7157     CreateDirectoryA("nine", NULL);
7158     CreateDirectoryA("twelve", NULL);
7159 
7160     r = MsiDoActionA(hpkg, "CostFinalize");
7161     ok(r == ERROR_SUCCESS, "file cost failed\n");
7162 
7163     lstrcpyA(subsrc, cwd);
7164     lstrcatA(subsrc, "short");
7165     lstrcatA(subsrc, "\\");
7166 
7167     /* neither short nor long source directories exist */
7168     size = MAX_PATH;
7169     lstrcpyA(path, "kiwi");
7170     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7171     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7172     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7173     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
7174 
7175     CreateDirectoryA("short", NULL);
7176 
7177     /* short source directory exists */
7178     size = MAX_PATH;
7179     lstrcpyA(path, "kiwi");
7180     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7181     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7182     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7183     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
7184 
7185     CreateDirectoryA("long", NULL);
7186 
7187     /* both short and long source directories exist */
7188     size = MAX_PATH;
7189     lstrcpyA(path, "kiwi");
7190     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7191     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7192     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7193     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
7194 
7195     lstrcpyA(subsrc, cwd);
7196     lstrcatA(subsrc, "one");
7197     lstrcatA(subsrc, "\\");
7198 
7199     /* short dir exists before CostInitialize */
7200     size = MAX_PATH;
7201     lstrcpyA(path, "kiwi");
7202     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
7203     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7204     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7205     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
7206 
7207     lstrcpyA(subsrc, cwd);
7208     lstrcatA(subsrc, "three");
7209     lstrcatA(subsrc, "\\");
7210 
7211     /* long dir exists before CostInitialize */
7212     size = MAX_PATH;
7213     lstrcpyA(path, "kiwi");
7214     r = MsiGetSourcePathA(hpkg, "SubDir3", path, &size);
7215     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7216     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7217     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
7218 
7219     lstrcpyA(subsrc, cwd);
7220     lstrcatA(subsrc, "five");
7221     lstrcatA(subsrc, "\\");
7222 
7223     /* short dir exists before FileCost */
7224     size = MAX_PATH;
7225     lstrcpyA(path, "kiwi");
7226     r = MsiGetSourcePathA(hpkg, "SubDir4", path, &size);
7227     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7228     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7229     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
7230 
7231     lstrcpyA(subsrc, cwd);
7232     lstrcatA(subsrc, "seven");
7233     lstrcatA(subsrc, "\\");
7234 
7235     /* long dir exists before FileCost */
7236     size = MAX_PATH;
7237     lstrcpyA(path, "kiwi");
7238     r = MsiGetSourcePathA(hpkg, "SubDir5", path, &size);
7239     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7240     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7241     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
7242 
7243     lstrcpyA(subsrc, cwd);
7244     lstrcatA(subsrc, "nine");
7245     lstrcatA(subsrc, "\\");
7246 
7247     /* short dir exists before CostFinalize */
7248     size = MAX_PATH;
7249     lstrcpyA(path, "kiwi");
7250     r = MsiGetSourcePathA(hpkg, "SubDir6", path, &size);
7251     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7252     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7253     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
7254 
7255     lstrcpyA(subsrc, cwd);
7256     lstrcatA(subsrc, "eleven");
7257     lstrcatA(subsrc, "\\");
7258 
7259     /* long dir exists before CostFinalize */
7260     size = MAX_PATH;
7261     lstrcpyA(path, "kiwi");
7262     r = MsiGetSourcePathA(hpkg, "SubDir7", path, &size);
7263     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7264     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7265     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
7266 
7267     MsiCloseHandle(hpkg);
7268     RemoveDirectoryA("short");
7269     RemoveDirectoryA("long");
7270     RemoveDirectoryA("one");
7271     RemoveDirectoryA("four");
7272     RemoveDirectoryA("five");
7273     RemoveDirectoryA("eight");
7274     RemoveDirectoryA("nine");
7275     RemoveDirectoryA("twelve");
7276     DeleteFileA(msifile);
7277 }
7278 
7279 static void test_sourcedir(void)
7280 {
7281     MSIHANDLE hdb, hpkg;
7282     CHAR package[12];
7283     CHAR path[MAX_PATH];
7284     CHAR cwd[MAX_PATH];
7285     CHAR subsrc[MAX_PATH];
7286     DWORD size;
7287     UINT r;
7288 
7289     lstrcpyA(cwd, CURR_DIR);
7290     if (!is_root(CURR_DIR)) lstrcatA(cwd, "\\");
7291 
7292     lstrcpyA(subsrc, cwd);
7293     lstrcatA(subsrc, "long");
7294     lstrcatA(subsrc, "\\");
7295 
7296     hdb = create_package_db();
7297     ok( hdb, "failed to create database\n");
7298 
7299     add_directory_entry(hdb, "'TARGETDIR', '', 'SourceDir'");
7300 
7301     sprintf(package, "#%lu", hdb);
7302     r = MsiOpenPackageA(package, &hpkg);
7303     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
7304     {
7305         skip("Not enough rights to perform tests\n");
7306         goto error;
7307     }
7308     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7309 
7310     /* properties only */
7311 
7312     /* SourceDir prop */
7313     size = MAX_PATH;
7314     lstrcpyA(path, "kiwi");
7315     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7316     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7317     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7318     ok(size == 0, "Expected 0, got %lu\n", size);
7319 
7320     /* SOURCEDIR prop */
7321     size = MAX_PATH;
7322     lstrcpyA(path, "kiwi");
7323     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7324     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7325     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7326     ok(size == 0, "Expected 0, got %lu\n", size);
7327 
7328     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
7329 
7330     r = MsiDoActionA(hpkg, "CostInitialize");
7331     ok(r == ERROR_SUCCESS, "file cost failed\n");
7332 
7333     /* SourceDir after CostInitialize */
7334     size = MAX_PATH;
7335     lstrcpyA(path, "kiwi");
7336     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7337     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7338     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7339     ok(size == 0, "Expected 0, got %lu\n", size);
7340 
7341     /* SOURCEDIR after CostInitialize */
7342     size = MAX_PATH;
7343     lstrcpyA(path, "kiwi");
7344     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7345     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7346     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7347     ok(size == 0, "Expected 0, got %lu\n", size);
7348 
7349     r = MsiDoActionA(hpkg, "FileCost");
7350     ok(r == ERROR_SUCCESS, "file cost failed\n");
7351 
7352     /* SourceDir after FileCost */
7353     size = MAX_PATH;
7354     lstrcpyA(path, "kiwi");
7355     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7356     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7357     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7358     ok(size == 0, "Expected 0, got %lu\n", size);
7359 
7360     /* SOURCEDIR after FileCost */
7361     size = MAX_PATH;
7362     lstrcpyA(path, "kiwi");
7363     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7364     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7365     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7366     ok(size == 0, "Expected 0, got %lu\n", size);
7367 
7368     r = MsiDoActionA(hpkg, "CostFinalize");
7369     ok(r == ERROR_SUCCESS, "file cost failed\n");
7370 
7371     /* SourceDir after CostFinalize */
7372     size = MAX_PATH;
7373     lstrcpyA(path, "kiwi");
7374     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7375     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7376     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7377     ok(size == 0, "Expected 0, got %lu\n", size);
7378 
7379     /* SOURCEDIR after CostFinalize */
7380     size = MAX_PATH;
7381     lstrcpyA(path, "kiwi");
7382     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7383     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7384     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7385     ok(size == 0, "Expected 0, got %lu\n", size);
7386 
7387     size = MAX_PATH;
7388     lstrcpyA(path, "kiwi");
7389     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7390     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7391     ok(!lstrcmpA(path, "kiwi"), "Expected \"kiwi\", got \"%s\"\n", path);
7392     ok(size == MAX_PATH, "Expected %d, got %lu\n", MAX_PATH, size);
7393 
7394     /* SOURCEDIR after calling MsiGetSourcePath */
7395     size = MAX_PATH;
7396     lstrcpyA(path, "kiwi");
7397     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7398     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7399     todo_wine {
7400     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7401     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
7402     }
7403 
7404     r = MsiDoActionA(hpkg, "ResolveSource");
7405     ok(r == ERROR_SUCCESS, "file cost failed\n");
7406 
7407     /* SourceDir after ResolveSource */
7408     size = MAX_PATH;
7409     lstrcpyA(path, "kiwi");
7410     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7411     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7412     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7413     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
7414 
7415     /* SOURCEDIR after ResolveSource */
7416     size = MAX_PATH;
7417     lstrcpyA(path, "kiwi");
7418     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7419     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7420     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7421     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
7422 
7423     /* random casing */
7424     size = MAX_PATH;
7425     lstrcpyA(path, "kiwi");
7426     r = MsiGetPropertyA(hpkg, "SoUrCeDiR", path, &size);
7427     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7428     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7429     ok(size == 0, "Expected 0, got %lu\n", size);
7430 
7431     MsiCloseHandle(hpkg);
7432 
7433     /* reset the package state */
7434     sprintf(package, "#%lu", hdb);
7435     r = MsiOpenPackageA(package, &hpkg);
7436     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7437 
7438     /* test how MsiGetSourcePath affects the properties */
7439 
7440     /* SourceDir prop */
7441     size = MAX_PATH;
7442     lstrcpyA(path, "kiwi");
7443     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7444     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7445     todo_wine
7446     {
7447         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7448         ok(size == 0, "Expected 0, got %lu\n", size);
7449     }
7450 
7451     size = MAX_PATH;
7452     lstrcpyA(path, "kiwi");
7453     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
7454     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7455     ok(!lstrcmpA(path, "kiwi"),
7456        "Expected path to be unchanged, got \"%s\"\n", path);
7457     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
7458 
7459     /* SourceDir after MsiGetSourcePath */
7460     size = MAX_PATH;
7461     lstrcpyA(path, "kiwi");
7462     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7463     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7464     todo_wine
7465     {
7466         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7467         ok(size == 0, "Expected 0, got %lu\n", size);
7468     }
7469 
7470     /* SOURCEDIR prop */
7471     size = MAX_PATH;
7472     lstrcpyA(path, "kiwi");
7473     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7474     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7475     todo_wine
7476     {
7477         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7478         ok(size == 0, "Expected 0, got %lu\n", size);
7479     }
7480 
7481     size = MAX_PATH;
7482     lstrcpyA(path, "kiwi");
7483     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7484     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7485     ok(!lstrcmpA(path, "kiwi"),
7486        "Expected path to be unchanged, got \"%s\"\n", path);
7487     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
7488 
7489     /* SOURCEDIR prop after MsiGetSourcePath */
7490     size = MAX_PATH;
7491     lstrcpyA(path, "kiwi");
7492     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7493     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7494     todo_wine
7495     {
7496         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7497         ok(size == 0, "Expected 0, got %lu\n", size);
7498     }
7499 
7500     r = MsiDoActionA(hpkg, "CostInitialize");
7501     ok(r == ERROR_SUCCESS, "file cost failed\n");
7502 
7503     /* SourceDir after CostInitialize */
7504     size = MAX_PATH;
7505     lstrcpyA(path, "kiwi");
7506     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7507     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7508     todo_wine
7509     {
7510         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7511         ok(size == 0, "Expected 0, got %lu\n", size);
7512     }
7513 
7514     size = MAX_PATH;
7515     lstrcpyA(path, "kiwi");
7516     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
7517     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7518     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7519     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
7520 
7521     /* SourceDir after MsiGetSourcePath */
7522     size = MAX_PATH;
7523     lstrcpyA(path, "kiwi");
7524     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7525     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7526     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7527     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
7528 
7529     /* SOURCEDIR after CostInitialize */
7530     size = MAX_PATH;
7531     lstrcpyA(path, "kiwi");
7532     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7533     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7534     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7535     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
7536 
7537     /* SOURCEDIR source path still does not exist */
7538     size = MAX_PATH;
7539     lstrcpyA(path, "kiwi");
7540     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7541     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7542     ok(!lstrcmpA(path, "kiwi"),
7543        "Expected path to be unchanged, got \"%s\"\n", path);
7544     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
7545 
7546     r = MsiDoActionA(hpkg, "FileCost");
7547     ok(r == ERROR_SUCCESS, "file cost failed\n");
7548 
7549     /* SourceDir after FileCost */
7550     size = MAX_PATH;
7551     lstrcpyA(path, "kiwi");
7552     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7553     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7554     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7555     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
7556 
7557     /* SOURCEDIR after FileCost */
7558     size = MAX_PATH;
7559     lstrcpyA(path, "kiwi");
7560     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7561     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7562     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7563     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
7564 
7565     /* SOURCEDIR source path still does not exist */
7566     size = MAX_PATH;
7567     lstrcpyA(path, "kiwi");
7568     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7569     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7570     ok(!lstrcmpA(path, "kiwi"),
7571        "Expected path to be unchanged, got \"%s\"\n", path);
7572     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
7573 
7574     r = MsiDoActionA(hpkg, "CostFinalize");
7575     ok(r == ERROR_SUCCESS, "file cost failed\n");
7576 
7577     /* SourceDir after CostFinalize */
7578     size = MAX_PATH;
7579     lstrcpyA(path, "kiwi");
7580     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7581     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7582     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7583     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
7584 
7585     /* SOURCEDIR after CostFinalize */
7586     size = MAX_PATH;
7587     lstrcpyA(path, "kiwi");
7588     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7589     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7590     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7591     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
7592 
7593     /* SOURCEDIR source path still does not exist */
7594     size = MAX_PATH;
7595     lstrcpyA(path, "kiwi");
7596     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7597     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7598     ok(!lstrcmpA(path, "kiwi"),
7599        "Expected path to be unchanged, got \"%s\"\n", path);
7600     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
7601 
7602     r = MsiDoActionA(hpkg, "ResolveSource");
7603     ok(r == ERROR_SUCCESS, "file cost failed\n");
7604 
7605     /* SourceDir after ResolveSource */
7606     size = MAX_PATH;
7607     lstrcpyA(path, "kiwi");
7608     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7609     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7610     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7611     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
7612 
7613     /* SOURCEDIR after ResolveSource */
7614     size = MAX_PATH;
7615     lstrcpyA(path, "kiwi");
7616     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7617     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7618     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7619     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
7620 
7621     /* SOURCEDIR source path still does not exist */
7622     size = MAX_PATH;
7623     lstrcpyA(path, "kiwi");
7624     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7625     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7626     ok(!lstrcmpA(path, "kiwi"),
7627        "Expected path to be unchanged, got \"%s\"\n", path);
7628     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
7629 
7630     MsiCloseHandle(hpkg);
7631 
7632 error:
7633     MsiCloseHandle(hdb);
7634     DeleteFileA(msifile);
7635 }
7636 
7637 struct access_res
7638 {
7639     BOOL gothandle;
7640     DWORD lasterr;
7641     BOOL ignore;
7642 };
7643 
7644 static const struct access_res create[16] =
7645 {
7646     { TRUE, ERROR_SUCCESS, TRUE },
7647     { TRUE, ERROR_SUCCESS, TRUE },
7648     { TRUE, ERROR_SUCCESS, FALSE },
7649     { TRUE, ERROR_SUCCESS, FALSE },
7650     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7651     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7652     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7653     { TRUE, ERROR_SUCCESS, FALSE },
7654     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7655     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7656     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7657     { TRUE, ERROR_SUCCESS, TRUE },
7658     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7659     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7660     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7661     { TRUE, ERROR_SUCCESS, TRUE }
7662 };
7663 
7664 static const struct access_res create_commit[16] =
7665 {
7666     { TRUE, ERROR_SUCCESS, TRUE },
7667     { TRUE, ERROR_SUCCESS, TRUE },
7668     { TRUE, ERROR_SUCCESS, FALSE },
7669     { TRUE, ERROR_SUCCESS, FALSE },
7670     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7671     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7672     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7673     { TRUE, ERROR_SUCCESS, FALSE },
7674     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7675     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7676     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7677     { TRUE, ERROR_SUCCESS, TRUE },
7678     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7679     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7680     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7681     { TRUE, ERROR_SUCCESS, TRUE }
7682 };
7683 
7684 static const struct access_res create_close[16] =
7685 {
7686     { TRUE, ERROR_SUCCESS, FALSE },
7687     { TRUE, ERROR_SUCCESS, FALSE },
7688     { TRUE, ERROR_SUCCESS, FALSE },
7689     { TRUE, ERROR_SUCCESS, FALSE },
7690     { TRUE, ERROR_SUCCESS, FALSE },
7691     { TRUE, ERROR_SUCCESS, FALSE },
7692     { TRUE, ERROR_SUCCESS, FALSE },
7693     { TRUE, ERROR_SUCCESS, FALSE },
7694     { TRUE, ERROR_SUCCESS, FALSE },
7695     { TRUE, ERROR_SUCCESS, FALSE },
7696     { TRUE, ERROR_SUCCESS, FALSE },
7697     { TRUE, ERROR_SUCCESS, FALSE },
7698     { TRUE, ERROR_SUCCESS, FALSE },
7699     { TRUE, ERROR_SUCCESS, FALSE },
7700     { TRUE, ERROR_SUCCESS, FALSE },
7701     { TRUE, ERROR_SUCCESS }
7702 };
7703 
7704 static void _test_file_access(LPCSTR file, const struct access_res *ares, DWORD line)
7705 {
7706     DWORD access = 0, share = 0;
7707     DWORD lasterr;
7708     HANDLE hfile;
7709     int i, j, idx = 0;
7710 
7711     for (i = 0; i < 4; i++)
7712     {
7713         if (i == 0) access = 0;
7714         if (i == 1) access = GENERIC_READ;
7715         if (i == 2) access = GENERIC_WRITE;
7716         if (i == 3) access = GENERIC_READ | GENERIC_WRITE;
7717 
7718         for (j = 0; j < 4; j++)
7719         {
7720             if (ares[idx].ignore)
7721                 continue;
7722 
7723             if (j == 0) share = 0;
7724             if (j == 1) share = FILE_SHARE_READ;
7725             if (j == 2) share = FILE_SHARE_WRITE;
7726             if (j == 3) share = FILE_SHARE_READ | FILE_SHARE_WRITE;
7727 
7728             SetLastError(0xdeadbeef);
7729             hfile = CreateFileA(file, access, share, NULL, OPEN_EXISTING,
7730                                 FILE_ATTRIBUTE_NORMAL, 0);
7731             lasterr = GetLastError();
7732 
7733             ok((hfile != INVALID_HANDLE_VALUE) == ares[idx].gothandle,
7734                "(%lu, handle, %d): Expected %d, got %d\n",
7735                line, idx, ares[idx].gothandle,
7736                (hfile != INVALID_HANDLE_VALUE));
7737 
7738             ok(lasterr == ares[idx].lasterr, "(%lu, lasterr, %u): Expected %lu, got %lu\n",
7739                line, idx, ares[idx].lasterr, lasterr);
7740 
7741             CloseHandle(hfile);
7742             idx++;
7743         }
7744     }
7745 }
7746 
7747 #define test_file_access(file, ares) _test_file_access(file, ares, __LINE__)
7748 
7749 static void test_access(void)
7750 {
7751     MSIHANDLE hdb;
7752     UINT r;
7753 
7754     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
7755     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7756 
7757     test_file_access(msifile, create);
7758 
7759     r = MsiDatabaseCommit(hdb);
7760     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7761 
7762     test_file_access(msifile, create_commit);
7763     MsiCloseHandle(hdb);
7764 
7765     test_file_access(msifile, create_close);
7766     DeleteFileA(msifile);
7767 
7768     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATEDIRECT, &hdb);
7769     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7770 
7771     test_file_access(msifile, create);
7772 
7773     r = MsiDatabaseCommit(hdb);
7774     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7775 
7776     test_file_access(msifile, create_commit);
7777     MsiCloseHandle(hdb);
7778 
7779     test_file_access(msifile, create_close);
7780     DeleteFileA(msifile);
7781 }
7782 
7783 static void test_emptypackage(void)
7784 {
7785     MSIHANDLE hpkg = 0, hdb = 0, hsuminfo = 0;
7786     MSIHANDLE hview = 0, hrec = 0;
7787     MSICONDITION condition;
7788     CHAR buffer[MAX_PATH];
7789     DWORD size;
7790     UINT r;
7791 
7792     r = MsiOpenPackageA("", &hpkg);
7793     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
7794     {
7795         skip("Not enough rights to perform tests\n");
7796         return;
7797     }
7798     todo_wine
7799     {
7800         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7801     }
7802 
7803     hdb = MsiGetActiveDatabase(hpkg);
7804     todo_wine
7805     {
7806         ok(hdb != 0, "Expected a valid database handle\n");
7807     }
7808 
7809     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Tables`", &hview);
7810     todo_wine
7811     {
7812         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7813     }
7814     r = MsiViewExecute(hview, 0);
7815     todo_wine
7816     {
7817         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7818     }
7819 
7820     r = MsiViewFetch(hview, &hrec);
7821     todo_wine
7822     {
7823         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7824     }
7825 
7826     buffer[0] = 0;
7827     size = MAX_PATH;
7828     r = MsiRecordGetStringA(hrec, 1, buffer, &size);
7829     todo_wine
7830     {
7831         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7832         ok(!lstrcmpA(buffer, "_Property"),
7833            "Expected \"_Property\", got \"%s\"\n", buffer);
7834     }
7835 
7836     MsiCloseHandle(hrec);
7837 
7838     r = MsiViewFetch(hview, &hrec);
7839     todo_wine
7840     {
7841         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7842     }
7843 
7844     size = MAX_PATH;
7845     r = MsiRecordGetStringA(hrec, 1, buffer, &size);
7846     todo_wine
7847     {
7848         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7849         ok(!lstrcmpA(buffer, "#_FolderCache"),
7850            "Expected \"_Property\", got \"%s\"\n", buffer);
7851     }
7852 
7853     MsiCloseHandle(hrec);
7854     MsiViewClose(hview);
7855     MsiCloseHandle(hview);
7856 
7857     condition = MsiDatabaseIsTablePersistentA(hdb, "_Property");
7858     todo_wine
7859     {
7860         ok(condition == MSICONDITION_FALSE,
7861            "Expected MSICONDITION_FALSE, got %d\n", condition);
7862     }
7863 
7864     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Property`", &hview);
7865     todo_wine
7866     {
7867         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7868     }
7869     r = MsiViewExecute(hview, 0);
7870     todo_wine
7871     {
7872         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7873     }
7874 
7875     /* _Property table is not empty */
7876     r = MsiViewFetch(hview, &hrec);
7877     todo_wine
7878     {
7879         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7880     }
7881 
7882     MsiCloseHandle(hrec);
7883     MsiViewClose(hview);
7884     MsiCloseHandle(hview);
7885 
7886     condition = MsiDatabaseIsTablePersistentA(hdb, "#_FolderCache");
7887     todo_wine
7888     {
7889         ok(condition == MSICONDITION_FALSE,
7890            "Expected MSICONDITION_FALSE, got %d\n", condition);
7891     }
7892 
7893     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `#_FolderCache`", &hview);
7894     todo_wine
7895     {
7896         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7897     }
7898     r = MsiViewExecute(hview, 0);
7899     todo_wine
7900     {
7901         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7902     }
7903 
7904     /* #_FolderCache is not empty */
7905     r = MsiViewFetch(hview, &hrec);
7906     todo_wine
7907     {
7908         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7909     }
7910 
7911     MsiCloseHandle(hrec);
7912     MsiViewClose(hview);
7913     MsiCloseHandle(hview);
7914 
7915     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Streams`", &hview);
7916     todo_wine
7917     {
7918         ok(r == ERROR_BAD_QUERY_SYNTAX,
7919            "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7920     }
7921 
7922     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Storages`", &hview);
7923     todo_wine
7924     {
7925         ok(r == ERROR_BAD_QUERY_SYNTAX,
7926            "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7927     }
7928 
7929     r = MsiGetSummaryInformationA(hdb, NULL, 0, &hsuminfo);
7930     todo_wine
7931     {
7932         ok(r == ERROR_INSTALL_PACKAGE_INVALID,
7933            "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
7934     }
7935 
7936     MsiCloseHandle(hsuminfo);
7937 
7938     r = MsiDatabaseCommit(hdb);
7939     todo_wine
7940     {
7941         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7942     }
7943 
7944     MsiCloseHandle(hdb);
7945     MsiCloseHandle(hpkg);
7946 }
7947 
7948 static void test_MsiGetProductProperty(void)
7949 {
7950     WCHAR valW[MAX_PATH];
7951     MSIHANDLE hprod, hdb;
7952     CHAR val[MAX_PATH];
7953     CHAR path[MAX_PATH];
7954     CHAR query[MAX_PATH + 17];
7955     CHAR keypath[MAX_PATH*2];
7956     CHAR prodcode[MAX_PATH];
7957     WCHAR prodcodeW[MAX_PATH];
7958     CHAR prod_squashed[MAX_PATH];
7959     WCHAR prod_squashedW[MAX_PATH];
7960     HKEY prodkey, userkey, props;
7961     DWORD size;
7962     LONG res;
7963     UINT r;
7964     REGSAM access = KEY_ALL_ACCESS;
7965 
7966     GetCurrentDirectoryA(MAX_PATH, path);
7967     lstrcatA(path, "\\");
7968 
7969     create_test_guid(prodcode, prod_squashed);
7970     MultiByteToWideChar(CP_ACP, 0, prodcode, -1, prodcodeW, MAX_PATH);
7971     squash_guid(prodcodeW, prod_squashedW);
7972 
7973     if (is_wow64)
7974         access |= KEY_WOW64_64KEY;
7975 
7976     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
7977     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7978 
7979     r = MsiDatabaseCommit(hdb);
7980     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7981 
7982     r = set_summary_info(hdb);
7983     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7984 
7985     r = run_query(hdb,
7986             "CREATE TABLE `Directory` ( "
7987             "`Directory` CHAR(255) NOT NULL, "
7988             "`Directory_Parent` CHAR(255), "
7989             "`DefaultDir` CHAR(255) NOT NULL "
7990             "PRIMARY KEY `Directory`)");
7991     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7992 
7993     create_property_table(hdb);
7994 
7995     sprintf(query, "'ProductCode', '%s'", prodcode);
7996     r = add_property_entry(hdb, query);
7997 
7998     r = MsiDatabaseCommit(hdb);
7999     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8000 
8001     MsiCloseHandle(hdb);
8002 
8003     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
8004     lstrcatA(keypath, prod_squashed);
8005 
8006     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
8007     if (res == ERROR_ACCESS_DENIED)
8008     {
8009         skip("Not enough rights to perform tests\n");
8010         DeleteFileA(msifile);
8011         return;
8012     }
8013     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8014 
8015     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
8016     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
8017     lstrcatA(keypath, prod_squashed);
8018 
8019     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
8020     if (res == ERROR_ACCESS_DENIED)
8021     {
8022         skip("Not enough rights to perform tests\n");
8023         RegDeleteKeyA(prodkey, "");
8024         RegCloseKey(prodkey);
8025         return;
8026     }
8027     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8028 
8029     res = RegCreateKeyExA(userkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
8030     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8031 
8032     lstrcpyA(val, path);
8033     lstrcatA(val, "\\");
8034     lstrcatA(val, msifile);
8035     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
8036                          (const BYTE *)val, lstrlenA(val) + 1);
8037     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
8038 
8039     hprod = 0xdeadbeef;
8040     r = MsiOpenProductA(prodcode, &hprod);
8041     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8042     ok(hprod != 0 && hprod != 0xdeadbeef, "Expected a valid product handle\n");
8043 
8044     /* hProduct is invalid */
8045     size = MAX_PATH;
8046     lstrcpyA(val, "apple");
8047     r = MsiGetProductPropertyA(0xdeadbeef, "ProductCode", val, &size);
8048     ok(r == ERROR_INVALID_HANDLE,
8049        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
8050     ok(!lstrcmpA(val, "apple"),
8051        "Expected val to be unchanged, got \"%s\"\n", val);
8052     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
8053 
8054     size = MAX_PATH;
8055     lstrcpyW(valW, L"apple");
8056     r = MsiGetProductPropertyW(0xdeadbeef, L"ProductCode", valW, &size);
8057     ok(r == ERROR_INVALID_HANDLE,
8058        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
8059     ok(!lstrcmpW(valW, L"apple"),
8060        "Expected val to be unchanged, got %s\n", wine_dbgstr_w(valW));
8061     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
8062 
8063     /* szProperty is NULL */
8064     size = MAX_PATH;
8065     lstrcpyA(val, "apple");
8066     r = MsiGetProductPropertyA(hprod, NULL, val, &size);
8067     ok(r == ERROR_INVALID_PARAMETER,
8068        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8069     ok(!lstrcmpA(val, "apple"),
8070        "Expected val to be unchanged, got \"%s\"\n", val);
8071     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
8072 
8073     size = MAX_PATH;
8074     lstrcpyW(valW, L"apple");
8075     r = MsiGetProductPropertyW(hprod, NULL, valW, &size);
8076     ok(r == ERROR_INVALID_PARAMETER,
8077        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8078     ok(!lstrcmpW(valW, L"apple"),
8079        "Expected val to be unchanged, got %s\n", wine_dbgstr_w(valW));
8080     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
8081 
8082     /* szProperty is empty */
8083     size = MAX_PATH;
8084     lstrcpyA(val, "apple");
8085     r = MsiGetProductPropertyA(hprod, "", val, &size);
8086     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8087     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
8088     ok(size == 0, "Expected 0, got %lu\n", size);
8089 
8090     size = MAX_PATH;
8091     lstrcpyW(valW, L"apple");
8092     r = MsiGetProductPropertyW(hprod, L"", valW, &size);
8093     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8094     ok(*valW == 0, "Expected \"\", got %s\n", wine_dbgstr_w(valW));
8095     ok(size == 0, "Expected 0, got %lu\n", size);
8096 
8097     /* get the property */
8098     size = MAX_PATH;
8099     lstrcpyA(val, "apple");
8100     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8101     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8102     ok(!lstrcmpA(val, prodcode),
8103        "Expected \"%s\", got \"%s\"\n", prodcode, val);
8104     ok(size == lstrlenA(prodcode),
8105        "Expected %d, got %lu\n", lstrlenA(prodcode), size);
8106 
8107     size = MAX_PATH;
8108     lstrcpyW(valW, L"apple");
8109     r = MsiGetProductPropertyW(hprod, L"ProductCode", valW, &size);
8110     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8111     ok(!lstrcmpW(valW, prodcodeW),
8112        "Expected %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8113     ok(size == lstrlenW(prodcodeW),
8114        "Expected %d, got %lu\n", lstrlenW(prodcodeW), size);
8115 
8116     /* lpValueBuf is NULL */
8117     size = MAX_PATH;
8118     r = MsiGetProductPropertyA(hprod, "ProductCode", NULL, &size);
8119     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8120     ok(size == lstrlenA(prodcode),
8121        "Expected %d, got %lu\n", lstrlenA(prodcode), size);
8122 
8123     size = MAX_PATH;
8124     r = MsiGetProductPropertyW(hprod, L"ProductCode", NULL, &size);
8125     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8126     ok(size == lstrlenW(prodcodeW),
8127        "Expected %d, got %lu\n", lstrlenW(prodcodeW), size);
8128 
8129     /* pcchValueBuf is NULL */
8130     lstrcpyA(val, "apple");
8131     r = MsiGetProductPropertyA(hprod, "ProductCode", val, NULL);
8132     ok(r == ERROR_INVALID_PARAMETER,
8133        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8134     ok(!lstrcmpA(val, "apple"),
8135        "Expected val to be unchanged, got \"%s\"\n", val);
8136     ok(size == lstrlenA(prodcode),
8137        "Expected %d, got %lu\n", lstrlenA(prodcode), size);
8138 
8139     lstrcpyW(valW, L"apple");
8140     r = MsiGetProductPropertyW(hprod, L"ProductCode", valW, NULL);
8141     ok(r == ERROR_INVALID_PARAMETER,
8142        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8143     ok(!lstrcmpW(valW, L"apple"),
8144        "Expected val to be unchanged, got %s\n", wine_dbgstr_w(valW));
8145     ok(size == lstrlenW(prodcodeW),
8146        "Expected %d, got %lu\n", lstrlenW(prodcodeW), size);
8147 
8148     /* pcchValueBuf is too small */
8149     size = 4;
8150     lstrcpyA(val, "apple");
8151     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8152     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
8153     ok(!strncmp(val, prodcode, 3),
8154        "Expected first 3 chars of \"%s\", got \"%s\"\n", prodcode, val);
8155     ok(size == lstrlenA(prodcode),
8156        "Expected %d, got %lu\n", lstrlenA(prodcode), size);
8157 
8158     size = 4;
8159     lstrcpyW(valW, L"apple");
8160     r = MsiGetProductPropertyW(hprod, L"ProductCode", valW, &size);
8161     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
8162     ok(!memcmp(valW, prodcodeW, 3 * sizeof(WCHAR)),
8163        "Expected first 3 chars of %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8164     ok(size == lstrlenW(prodcodeW),
8165        "Expected %d, got %lu\n", lstrlenW(prodcodeW), size);
8166 
8167     /* pcchValueBuf does not leave room for NULL terminator */
8168     size = lstrlenA(prodcode);
8169     lstrcpyA(val, "apple");
8170     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8171     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
8172     ok(!strncmp(val, prodcode, lstrlenA(prodcode) - 1),
8173        "Expected first 37 chars of \"%s\", got \"%s\"\n", prodcode, val);
8174     ok(size == lstrlenA(prodcode),
8175        "Expected %d, got %lu\n", lstrlenA(prodcode), size);
8176 
8177     size = lstrlenW(prodcodeW);
8178     lstrcpyW(valW, L"apple");
8179     r = MsiGetProductPropertyW(hprod, L"ProductCode", valW, &size);
8180     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
8181     ok(!memcmp(valW, prodcodeW, lstrlenW(prodcodeW) - 1),
8182        "Expected first 37 chars of %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8183     ok(size == lstrlenW(prodcodeW),
8184        "Expected %d, got %lu\n", lstrlenW(prodcodeW), size);
8185 
8186     /* pcchValueBuf has enough room for NULL terminator */
8187     size = lstrlenA(prodcode) + 1;
8188     lstrcpyA(val, "apple");
8189     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8190     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8191     ok(!lstrcmpA(val, prodcode),
8192        "Expected \"%s\", got \"%s\"\n", prodcode, val);
8193     ok(size == lstrlenA(prodcode),
8194        "Expected %d, got %lu\n", lstrlenA(prodcode), size);
8195 
8196     size = lstrlenW(prodcodeW) + 1;
8197     lstrcpyW(valW, L"apple");
8198     r = MsiGetProductPropertyW(hprod, L"ProductCode", valW, &size);
8199     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8200     ok(!lstrcmpW(valW, prodcodeW),
8201        "Expected %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8202     ok(size == lstrlenW(prodcodeW),
8203        "Expected %d, got %lu\n", lstrlenW(prodcodeW), size);
8204 
8205     /* nonexistent property */
8206     size = MAX_PATH;
8207     lstrcpyA(val, "apple");
8208     r = MsiGetProductPropertyA(hprod, "IDontExist", val, &size);
8209     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8210     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
8211     ok(size == 0, "Expected 0, got %lu\n", size);
8212 
8213     size = MAX_PATH;
8214     lstrcpyW(valW, L"apple");
8215     r = MsiGetProductPropertyW(hprod, L"IDontExist", valW, &size);
8216     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8217     ok(!lstrcmpW(valW, L""), "Expected \"\", got %s\n", wine_dbgstr_w(valW));
8218     ok(size == 0, "Expected 0, got %lu\n", size);
8219 
8220     r = MsiSetPropertyA(hprod, "NewProperty", "value");
8221     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8222 
8223     /* non-product property set */
8224     size = MAX_PATH;
8225     lstrcpyA(val, "apple");
8226     r = MsiGetProductPropertyA(hprod, "NewProperty", val, &size);
8227     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8228     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
8229     ok(size == 0, "Expected 0, got %lu\n", size);
8230 
8231     size = MAX_PATH;
8232     lstrcpyW(valW, L"apple");
8233     r = MsiGetProductPropertyW(hprod, L"NewProperty", valW, &size);
8234     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8235     ok(!lstrcmpW(valW, L""), "Expected \"\", got %s\n", wine_dbgstr_w(valW));
8236     ok(size == 0, "Expected 0, got %lu\n", size);
8237 
8238     r = MsiSetPropertyA(hprod, "ProductCode", "value");
8239     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8240 
8241     /* non-product property that is also a product property set */
8242     size = MAX_PATH;
8243     lstrcpyA(val, "apple");
8244     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8245     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8246     ok(!lstrcmpA(val, prodcode),
8247        "Expected \"%s\", got \"%s\"\n", prodcode, val);
8248     ok(size == lstrlenA(prodcode),
8249        "Expected %d, got %lu\n", lstrlenA(prodcode), size);
8250 
8251     size = MAX_PATH;
8252     lstrcpyW(valW, L"apple");
8253     r = MsiGetProductPropertyW(hprod, L"ProductCode", valW, &size);
8254     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8255     ok(!lstrcmpW(valW, prodcodeW),
8256        "Expected %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8257     ok(size == lstrlenW(prodcodeW),
8258        "Expected %d, got %lu\n", lstrlenW(prodcodeW), size);
8259 
8260     MsiCloseHandle(hprod);
8261 
8262     RegDeleteValueA(props, "LocalPackage");
8263     delete_key(props, "", access);
8264     RegCloseKey(props);
8265     delete_key(userkey, "", access);
8266     RegCloseKey(userkey);
8267     delete_key(prodkey, "", access);
8268     RegCloseKey(prodkey);
8269     DeleteFileA(msifile);
8270 }
8271 
8272 static void test_MsiSetProperty(void)
8273 {
8274     MSIHANDLE hpkg, hdb, hrec;
8275     CHAR buf[MAX_PATH];
8276     LPCSTR query;
8277     DWORD size;
8278     UINT r;
8279 
8280     r = package_from_db(create_package_db(), &hpkg);
8281     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
8282     {
8283         skip("Not enough rights to perform tests\n");
8284         DeleteFileA(msifile);
8285         return;
8286     }
8287     ok(r == ERROR_SUCCESS, "Expected a valid package %u\n", r);
8288 
8289     /* invalid hInstall */
8290     r = MsiSetPropertyA(0, "Prop", "Val");
8291     ok(r == ERROR_INVALID_HANDLE,
8292        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
8293 
8294     /* invalid hInstall */
8295     r = MsiSetPropertyA(0xdeadbeef, "Prop", "Val");
8296     ok(r == ERROR_INVALID_HANDLE,
8297        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
8298 
8299     /* szName is NULL */
8300     r = MsiSetPropertyA(hpkg, NULL, "Val");
8301     ok(r == ERROR_INVALID_PARAMETER,
8302        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8303 
8304     /* both szName and szValue are NULL */
8305     r = MsiSetPropertyA(hpkg, NULL, NULL);
8306     ok(r == ERROR_INVALID_PARAMETER,
8307        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8308 
8309     /* szName is empty */
8310     r = MsiSetPropertyA(hpkg, "", "Val");
8311     ok(r == ERROR_FUNCTION_FAILED,
8312        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
8313 
8314     /* szName is empty and szValue is NULL */
8315     r = MsiSetPropertyA(hpkg, "", NULL);
8316     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8317 
8318     /* set a property */
8319     r = MsiSetPropertyA(hpkg, "Prop", "Val");
8320     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8321 
8322     /* get the property */
8323     size = MAX_PATH;
8324     r = MsiGetPropertyA(hpkg, "Prop", buf, &size);
8325     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8326     ok(!lstrcmpA(buf, "Val"), "Expected \"Val\", got \"%s\"\n", buf);
8327     ok(size == 3, "Expected 3, got %lu\n", size);
8328 
8329     /* update the property */
8330     r = MsiSetPropertyA(hpkg, "Prop", "Nuvo");
8331     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8332 
8333     /* get the property */
8334     size = MAX_PATH;
8335     r = MsiGetPropertyA(hpkg, "Prop", buf, &size);
8336     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8337     ok(!lstrcmpA(buf, "Nuvo"), "Expected \"Nuvo\", got \"%s\"\n", buf);
8338     ok(size == 4, "Expected 4, got %lu\n", size);
8339 
8340     hdb = MsiGetActiveDatabase(hpkg);
8341     ok(hdb != 0, "Expected a valid database handle\n");
8342 
8343     /* set prop is not in the _Property table */
8344     query = "SELECT * FROM `_Property` WHERE `Property` = 'Prop'";
8345     r = do_query(hdb, query, &hrec);
8346     ok(r == ERROR_BAD_QUERY_SYNTAX,
8347        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8348 
8349     /* set prop is not in the Property table */
8350     query = "SELECT * FROM `Property` WHERE `Property` = 'Prop'";
8351     r = do_query(hdb, query, &hrec);
8352     ok(r == ERROR_BAD_QUERY_SYNTAX,
8353        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8354 
8355     MsiCloseHandle(hdb);
8356 
8357     /* szValue is an empty string */
8358     r = MsiSetPropertyA(hpkg, "Prop", "");
8359     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8360 
8361     /* try to get the property */
8362     size = MAX_PATH;
8363     r = MsiGetPropertyA(hpkg, "Prop", buf, &size);
8364     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8365     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
8366     ok(size == 0, "Expected 0, got %lu\n", size);
8367 
8368     /* reset the property */
8369     r = MsiSetPropertyA(hpkg, "Prop", "BlueTap");
8370     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8371 
8372     /* delete the property */
8373     r = MsiSetPropertyA(hpkg, "Prop", NULL);
8374     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8375 
8376     /* try to get the property */
8377     size = MAX_PATH;
8378     r = MsiGetPropertyA(hpkg, "Prop", buf, &size);
8379     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8380     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
8381     ok(size == 0, "Expected 0, got %lu\n", size);
8382 
8383     MsiCloseHandle(hpkg);
8384     DeleteFileA(msifile);
8385 }
8386 
8387 static void test_MsiApplyMultiplePatches(void)
8388 {
8389     UINT r, type = GetDriveTypeW(NULL);
8390 
8391     r = MsiApplyMultiplePatchesA(NULL, NULL, NULL);
8392     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
8393 
8394     r = MsiApplyMultiplePatchesA("", NULL, NULL);
8395     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
8396 
8397     r = MsiApplyMultiplePatchesA(";", NULL, NULL);
8398     if (type == DRIVE_FIXED)
8399         todo_wine ok(r == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %u\n", r);
8400     else
8401         ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
8402 
8403     r = MsiApplyMultiplePatchesA("  ;", NULL, NULL);
8404     if (type == DRIVE_FIXED)
8405         todo_wine ok(r == ERROR_PATCH_PACKAGE_OPEN_FAILED, "Expected ERROR_PATCH_PACKAGE_OPEN_FAILED, got %u\n", r);
8406     else
8407         ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
8408 
8409     r = MsiApplyMultiplePatchesA(";;", NULL, NULL);
8410     if (type == DRIVE_FIXED)
8411         todo_wine ok(r == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %u\n", r);
8412     else
8413         ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
8414 
8415     r = MsiApplyMultiplePatchesA("nosuchpatchpackage;", NULL, NULL);
8416     todo_wine ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
8417 
8418     r = MsiApplyMultiplePatchesA(";nosuchpatchpackage", NULL, NULL);
8419     if (type == DRIVE_FIXED)
8420         todo_wine ok(r == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %u\n", r);
8421     else
8422         ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
8423 
8424     r = MsiApplyMultiplePatchesA("nosuchpatchpackage;nosuchpatchpackage", NULL, NULL);
8425     todo_wine ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
8426 
8427     r = MsiApplyMultiplePatchesA("  nosuchpatchpackage  ;  nosuchpatchpackage  ", NULL, NULL);
8428     todo_wine ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
8429 }
8430 
8431 static void test_MsiApplyPatch(void)
8432 {
8433     UINT r;
8434 
8435     r = MsiApplyPatchA(NULL, NULL, INSTALLTYPE_DEFAULT, NULL);
8436     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
8437 
8438     r = MsiApplyPatchA("", NULL, INSTALLTYPE_DEFAULT, NULL);
8439     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
8440 }
8441 
8442 static void test_costs(void)
8443 {
8444     MSIHANDLE hdb, hpkg;
8445     char package[12], drive[3];
8446     DWORD len;
8447     UINT r;
8448     int cost, temp;
8449 
8450     hdb = create_package_db();
8451     ok( hdb, "failed to create database\n" );
8452 
8453     create_property_table( hdb );
8454     add_property_entry( hdb, "'ProductCode', '{379B1C47-40C1-42FA-A9BB-BEBB6F1B0172}'" );
8455     add_property_entry( hdb, "'MSIFASTINSTALL', '1'" );
8456     add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'" );
8457 
8458     create_media_table( hdb );
8459     add_media_entry( hdb, "'1', '2', 'cabinet', '', '', ''");
8460 
8461     create_file_table( hdb );
8462     add_file_entry( hdb, "'one.txt', 'one', 'one.txt', 4096, '', '', 8192, 1" );
8463 
8464     create_component_table( hdb );
8465     add_component_entry( hdb, "'one', '{B2F86B9D-8447-4BC5-8883-750C45AA31CA}', 'TARGETDIR', 0, '', 'one.txt'" );
8466     add_component_entry( hdb, "'two', '{62A09F6E-0B74-4829-BDB7-CAB66F42CCE8}', 'TARGETDIR', 0, '', ''" );
8467 
8468     create_feature_table( hdb );
8469     add_feature_entry( hdb, "'one', '', '', '', 0, 1, '', 0" );
8470     add_feature_entry( hdb, "'two', '', '', '', 0, 1, '', 0" );
8471 
8472     create_feature_components_table( hdb );
8473     add_feature_components_entry( hdb, "'one', 'one'" );
8474     add_feature_components_entry( hdb, "'two', 'two'" );
8475 
8476     create_install_execute_sequence_table( hdb );
8477     add_install_execute_sequence_entry( hdb, "'CostInitialize', '', '800'" );
8478     add_install_execute_sequence_entry( hdb, "'FileCost', '', '900'" );
8479     add_install_execute_sequence_entry( hdb, "'CostFinalize', '', '1000'" );
8480     add_install_execute_sequence_entry( hdb, "'InstallValidate', '', '1100'" );
8481 
8482     r = MsiDatabaseCommit( hdb );
8483     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8484 
8485     sprintf( package, "#%lu", hdb );
8486     r = MsiOpenPackageA( package, &hpkg );
8487     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
8488     {
8489         skip("Not enough rights to perform tests\n");
8490         goto error;
8491     }
8492     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8493 
8494     r = MsiEnumComponentCostsA( 0, NULL, 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8495     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8496 
8497     r = MsiEnumComponentCostsA( hpkg, NULL, 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8498     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8499 
8500     r = MsiEnumComponentCostsA( hpkg, NULL, 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8501     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8502 
8503     r = MsiEnumComponentCostsA( hpkg, "", 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8504     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8505 
8506     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8507     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8508 
8509     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, NULL, NULL, NULL, NULL );
8510     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8511 
8512     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, NULL, NULL, NULL );
8513     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8514 
8515     len = sizeof(drive);
8516     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, NULL, NULL );
8517     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8518 
8519     len = sizeof(drive);
8520     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, NULL );
8521     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8522 
8523     len = sizeof(drive);
8524     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8525     todo_wine ok( r == ERROR_INVALID_HANDLE_STATE, "Expected ERROR_INVALID_HANDLE_STATE, got %u\n", r );
8526 
8527     len = sizeof(drive);
8528     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, NULL, &len, &cost, &temp );
8529     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8530 
8531     MsiSetInternalUI( INSTALLUILEVEL_NONE, NULL );
8532 
8533     r = MsiDoActionA( hpkg, "CostInitialize" );
8534     ok( r == ERROR_SUCCESS, "CostInitialize failed %u\n", r );
8535 
8536     r = MsiDoActionA( hpkg, "FileCost" );
8537     ok( r == ERROR_SUCCESS, "FileCost failed %u\n", r );
8538 
8539     len = sizeof(drive);
8540     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8541     ok( r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %u\n", r );
8542 
8543     r = MsiDoActionA( hpkg, "CostFinalize" );
8544     ok( r == ERROR_SUCCESS, "CostFinalize failed %u\n", r );
8545 
8546     /* contrary to what msdn says InstallValidate must be called too */
8547     len = sizeof(drive);
8548     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8549     todo_wine ok( r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %u\n", r );
8550 
8551     r = MsiDoActionA( hpkg, "InstallValidate" );
8552     ok( r == ERROR_SUCCESS, "InstallValidate failed %u\n", r );
8553 
8554     len = 0;
8555     r = MsiEnumComponentCostsA( hpkg, "three", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8556     ok( r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %u\n", r );
8557 
8558     len = 0;
8559     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8560     ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %u\n", r );
8561     ok( len == 2, "expected len == 2, got %lu\n", len );
8562 
8563     len = 2;
8564     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8565     ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %u\n", r );
8566     ok( len == 2, "expected len == 2, got %lu\n", len );
8567 
8568     len = 2;
8569     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_UNKNOWN, drive, &len, &cost, &temp );
8570     ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %u\n", r );
8571     ok( len == 2, "expected len == 2, got %lu\n", len );
8572 
8573     /* install state doesn't seem to matter */
8574     len = sizeof(drive);
8575     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_UNKNOWN, drive, &len, &cost, &temp );
8576     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8577 
8578     len = sizeof(drive);
8579     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_ABSENT, drive, &len, &cost, &temp );
8580     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8581 
8582     len = sizeof(drive);
8583     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_SOURCE, drive, &len, &cost, &temp );
8584     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8585 
8586     len = sizeof(drive);
8587     drive[0] = 0;
8588     cost = temp = 0xdead;
8589     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8590     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8591     ok( len == 2, "expected len == 2, got %lu\n", len );
8592     ok( drive[0], "expected a drive\n" );
8593     ok( cost && cost != 0xdead, "expected cost > 0, got %d\n", cost );
8594     ok( !temp, "expected temp == 0, got %d\n", temp );
8595 
8596     len = sizeof(drive);
8597     drive[0] = 0;
8598     cost = temp = 0xdead;
8599     r = MsiEnumComponentCostsA( hpkg, "two", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8600     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8601     ok( len == 2, "expected len == 2, got %lu\n", len );
8602     ok( drive[0], "expected a drive\n" );
8603     ok( !cost, "expected cost == 0, got %d\n", cost );
8604     ok( !temp, "expected temp == 0, got %d\n", temp );
8605 
8606     len = sizeof(drive);
8607     drive[0] = 0;
8608     cost = temp = 0xdead;
8609     r = MsiEnumComponentCostsA( hpkg, "", 0, INSTALLSTATE_UNKNOWN, drive, &len, &cost, &temp );
8610     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8611     ok( len == 2, "expected len == 2, got %lu\n", len );
8612     ok( drive[0], "expected a drive\n" );
8613     ok( !cost, "expected cost == 0, got %d\n", cost );
8614     ok( temp && temp != 0xdead, "expected temp > 0, got %d\n", temp );
8615 
8616     /* increased index */
8617     len = sizeof(drive);
8618     r = MsiEnumComponentCostsA( hpkg, "one", 1, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8619     ok( r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %u\n", r );
8620 
8621     len = sizeof(drive);
8622     r = MsiEnumComponentCostsA( hpkg, "", 1, INSTALLSTATE_UNKNOWN, drive, &len, &cost, &temp );
8623     ok( r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %u\n", r );
8624 
8625     /* test MsiGetFeatureCost */
8626     cost = 0xdead;
8627     r = MsiGetFeatureCostA( hpkg, NULL, MSICOSTTREE_SELFONLY, INSTALLSTATE_LOCAL, &cost );
8628     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r);
8629     ok( cost == 0xdead, "got %d\n", cost );
8630 
8631     r = MsiGetFeatureCostA( hpkg, "one", MSICOSTTREE_SELFONLY, INSTALLSTATE_LOCAL, NULL );
8632     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r);
8633 
8634     cost = 0xdead;
8635     r = MsiGetFeatureCostA( hpkg, "one", MSICOSTTREE_SELFONLY, INSTALLSTATE_LOCAL, &cost );
8636     ok( !r, "got %u\n", r);
8637     ok( cost == 8, "got %d\n", cost );
8638 
8639     MsiCloseHandle( hpkg );
8640 error:
8641     MsiCloseHandle( hdb );
8642     DeleteFileA( msifile );
8643 }
8644 
8645 static void test_MsiDatabaseCommit(void)
8646 {
8647     UINT r;
8648     MSIHANDLE hdb, hpkg = 0;
8649     char buf[32], package[12];
8650     DWORD sz;
8651 
8652     hdb = create_package_db();
8653     ok( hdb, "failed to create database\n" );
8654 
8655     create_property_table( hdb );
8656 
8657     sprintf( package, "#%lu", hdb );
8658     r = MsiOpenPackageA( package, &hpkg );
8659     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
8660     {
8661         skip("Not enough rights to perform tests\n");
8662         goto error;
8663     }
8664     ok( r == ERROR_SUCCESS, "got %u\n", r );
8665 
8666     r = MsiSetPropertyA( hpkg, "PROP", "value" );
8667     ok( r == ERROR_SUCCESS, "got %u\n", r );
8668 
8669     buf[0] = 0;
8670     sz = sizeof(buf);
8671     r = MsiGetPropertyA( hpkg, "PROP", buf, &sz );
8672     ok( r == ERROR_SUCCESS, "MsiGetPropertyA returned %u\n", r );
8673     ok( !lstrcmpA( buf, "value" ), "got \"%s\"\n", buf );
8674 
8675     r = MsiDatabaseCommit( hdb );
8676     ok( r == ERROR_SUCCESS, "MsiDatabaseCommit returned %u\n", r );
8677 
8678     buf[0] = 0;
8679     sz = sizeof(buf);
8680     r = MsiGetPropertyA( hpkg, "PROP", buf, &sz );
8681     ok( r == ERROR_SUCCESS, "MsiGetPropertyA returned %u\n", r );
8682     ok( !lstrcmpA( buf, "value" ), "got \"%s\"\n", buf );
8683 
8684     MsiCloseHandle( hpkg );
8685 error:
8686     MsiCloseHandle( hdb );
8687     DeleteFileA( msifile );
8688 }
8689 
8690 static int externalui_ran;
8691 
8692 static INT CALLBACK externalui_callback(void *context, UINT message_type, LPCSTR message)
8693 {
8694     externalui_ran = 1;
8695     ok(message_type == INSTALLMESSAGE_USER, "expected INSTALLMESSAGE_USER, got %08x\n", message_type);
8696     return 0;
8697 }
8698 
8699 static int externalui_record_ran;
8700 
8701 static INT CALLBACK externalui_record_callback(void *context, UINT message_type, MSIHANDLE hrecord)
8702 {
8703     INT retval = context ? *((INT *)context) : 0;
8704     UINT r;
8705     externalui_record_ran = 1;
8706     ok(message_type == INSTALLMESSAGE_USER, "expected INSTALLMESSAGE_USER, got %08x\n", message_type);
8707     r = MsiRecordGetFieldCount(hrecord);
8708     ok(r == 1, "expected 1, got %u\n", r);
8709     r = MsiRecordGetInteger(hrecord, 1);
8710     ok(r == 12345, "expected 12345, got %u\n", r);
8711     return retval;
8712 }
8713 
8714 static void test_externalui(void)
8715 {
8716     /* test that external UI handlers work correctly */
8717 
8718     INSTALLUI_HANDLERA prev;
8719     INSTALLUI_HANDLER_RECORD prev_record;
8720     MSIHANDLE hpkg, hrecord;
8721     UINT r;
8722     INT retval = 0;
8723 
8724     prev = MsiSetExternalUIA(externalui_callback, INSTALLLOGMODE_USER, NULL);
8725 
8726     r = package_from_db(create_package_db(), &hpkg);
8727     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
8728     {
8729         skip("Not enough rights to perform tests\n");
8730         DeleteFileA(msifile);
8731         return;
8732     }
8733     ok(r == ERROR_SUCCESS, "Expected a valid package %u\n", r);
8734 
8735     hrecord = MsiCreateRecord(1);
8736     ok(hrecord, "Expected a valid record\n");
8737     r = MsiRecordSetStringA(hrecord, 0, "test message [1]");
8738     ok(r == ERROR_SUCCESS, "MsiSetString failed %u\n", r);
8739     r = MsiRecordSetInteger(hrecord, 1, 12345);
8740     ok(r == ERROR_SUCCESS, "MsiSetInteger failed %u\n", r);
8741 
8742     externalui_ran = 0;
8743     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
8744     ok(r == 0, "expected 0, got %u\n", r);
8745     ok(externalui_ran == 1, "external UI callback did not run\n");
8746 
8747     prev = MsiSetExternalUIA(prev, 0, NULL);
8748     ok(prev == externalui_callback, "wrong callback function %p\n", prev);
8749     r = MsiSetExternalUIRecord(externalui_record_callback, INSTALLLOGMODE_USER, &retval, &prev_record);
8750     ok(r == ERROR_SUCCESS, "MsiSetExternalUIRecord failed %u\n", r);
8751 
8752     externalui_ran = externalui_record_ran = 0;
8753     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
8754     ok(r == 0, "expected 0, got %u\n", r);
8755     ok(externalui_ran == 0, "external UI callback should not have run\n");
8756     ok(externalui_record_ran == 1, "external UI record callback did not run\n");
8757 
8758     MsiSetExternalUIA(externalui_callback, INSTALLLOGMODE_USER, NULL);
8759 
8760     externalui_ran = externalui_record_ran = 0;
8761     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
8762     ok(r == 0, "expected 0, got %u\n", r);
8763     ok(externalui_ran == 1, "external UI callback did not run\n");
8764     ok(externalui_record_ran == 1, "external UI record callback did not run\n");
8765 
8766     retval = 1;
8767     externalui_ran = externalui_record_ran = 0;
8768     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
8769     ok(r == 1, "expected 1, got %u\n", r);
8770     ok(externalui_ran == 0, "external UI callback should not have run\n");
8771     ok(externalui_record_ran == 1, "external UI record callback did not run\n");
8772 
8773     /* filter and context should be kept separately */
8774     r = MsiSetExternalUIRecord(externalui_record_callback, INSTALLLOGMODE_ERROR, &retval, &prev_record);
8775     ok(r == ERROR_SUCCESS, "MsiSetExternalUIRecord failed %u\n", r);
8776 
8777     externalui_ran = externalui_record_ran = 0;
8778     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
8779     ok(r == 0, "expected 0, got %u\n", r);
8780     ok(externalui_ran == 1, "external UI callback did not run\n");
8781     ok(externalui_record_ran == 0, "external UI record callback should not have run\n");
8782 
8783     MsiCloseHandle(hpkg);
8784     DeleteFileA(msifile);
8785 }
8786 
8787 struct externalui_message {
8788     UINT message;
8789     int field_count;
8790     char field[4][100];
8791     int match[4]; /* should we test for a match */
8792     int optional;
8793 };
8794 
8795 static struct externalui_message *sequence;
8796 static int sequence_count, sequence_size;
8797 
8798 static void add_message(const struct externalui_message *msg)
8799 {
8800     if (!sequence)
8801     {
8802         sequence_size = 10;
8803         sequence = malloc(sequence_size * sizeof(*sequence));
8804     }
8805     if (sequence_count == sequence_size)
8806     {
8807         sequence_size *= 2;
8808         sequence = realloc(sequence, sequence_size * sizeof(*sequence));
8809     }
8810 
8811     assert(sequence);
8812     sequence[sequence_count++] = *msg;
8813 }
8814 
8815 static void flush_sequence(void)
8816 {
8817     free(sequence);
8818     sequence = NULL;
8819     sequence_count = sequence_size = 0;
8820 }
8821 
8822 static void ok_sequence_(const struct externalui_message *expected, const char *context, BOOL todo,
8823                          const char *file, int line)
8824 {
8825     static const struct externalui_message end_of_sequence = {0};
8826     const struct externalui_message *actual;
8827     int failcount = 0;
8828     int i;
8829 
8830     add_message(&end_of_sequence);
8831 
8832     actual = sequence;
8833 
8834     while (expected->message && actual->message)
8835     {
8836         if (expected->message == actual->message)
8837         {
8838             if (expected->field_count < actual->field_count)
8839             {
8840                 todo_wine_if (todo)
8841                     ok_(file, line) (FALSE, "%s: in msg 0x%08x expecting field count %d got %d\n",
8842                                      context, expected->message, expected->field_count, actual->field_count);
8843                 failcount++;
8844             }
8845 
8846             for (i = 0; i <= actual->field_count; i++)
8847             {
8848                 if (expected->match[i] && strcmp(expected->field[i], actual->field[i]))
8849                 {
8850                     todo_wine_if (todo)
8851                         ok_(file, line) (FALSE, "%s: in msg 0x%08x field %d: expected \"%s\", got \"%s\"\n",
8852                                          context, expected->message, i, expected->field[i], actual->field[i]);
8853                     failcount++;
8854                 }
8855             }
8856 
8857             expected++;
8858             actual++;
8859         }
8860         else if (expected->optional)
8861         {
8862             expected++;
8863         }
8864         else
8865         {
8866             todo_wine_if (todo)
8867                 ok_(file, line) (FALSE, "%s: the msg 0x%08x was expected, but got msg 0x%08x instead\n",
8868                                  context, expected->message, actual->message);
8869             failcount++;
8870             if (todo)
8871                 goto done;
8872             expected++;
8873             actual++;
8874         }
8875     }
8876 
8877     if (expected->message || actual->message)
8878     {
8879         todo_wine_if (todo)
8880             ok_(file, line) (FALSE, "%s: the msg sequence is not complete: expected %08x - actual %08x\n",
8881                              context, expected->message, actual->message);
8882         failcount++;
8883     }
8884 
8885     if(todo && !failcount) /* succeeded yet marked todo */
8886     {
8887         todo_wine
8888             ok_(file, line)(TRUE, "%s: marked \"todo_wine\" but succeeds\n", context);
8889     }
8890 
8891 done:
8892     flush_sequence();
8893 }
8894 
8895 #define ok_sequence(exp, contx, todo) \
8896         ok_sequence_((exp), (contx), (todo), __FILE__, __LINE__)
8897 
8898 /* don't use PROGRESS, which is timing-dependent,
8899  * or SHOWDIALOG, which due to a bug causes a hang on XP */
8900 static const INSTALLLOGMODE MSITEST_INSTALLLOGMODE =
8901     INSTALLLOGMODE_FATALEXIT |
8902     INSTALLLOGMODE_ERROR |
8903     INSTALLLOGMODE_WARNING |
8904     INSTALLLOGMODE_USER |
8905     INSTALLLOGMODE_INFO |
8906     INSTALLLOGMODE_FILESINUSE |
8907     INSTALLLOGMODE_RESOLVESOURCE |
8908     INSTALLLOGMODE_OUTOFDISKSPACE |
8909     INSTALLLOGMODE_ACTIONSTART |
8910     INSTALLLOGMODE_ACTIONDATA |
8911     INSTALLLOGMODE_COMMONDATA |
8912     INSTALLLOGMODE_INITIALIZE |
8913     INSTALLLOGMODE_TERMINATE |
8914     INSTALLLOGMODE_RMFILESINUSE |
8915     INSTALLLOGMODE_INSTALLSTART |
8916     INSTALLLOGMODE_INSTALLEND;
8917 
8918 static const struct externalui_message empty_sequence[] = {
8919     {0}
8920 };
8921 
8922 static const struct externalui_message openpackage_nonexistent_sequence[] = {
8923     {INSTALLMESSAGE_INITIALIZE, -1},
8924     {INSTALLMESSAGE_TERMINATE, -1},
8925     {0}
8926 };
8927 
8928 static const struct externalui_message openpackage_sequence[] = {
8929     {INSTALLMESSAGE_INITIALIZE, -1},
8930     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
8931     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
8932     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
8933     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
8934     {0}
8935 };
8936 
8937 static const struct externalui_message processmessage_info_sequence[] = {
8938     {INSTALLMESSAGE_INFO, 3, {"zero", "one", "two", "three"}, {1, 1, 1, 1}},
8939     {0}
8940 };
8941 
8942 static const struct externalui_message processmessage_actionstart_sequence[] = {
8943     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "name", "description", "template"}, {0, 1, 1, 1}},
8944     {0}
8945 };
8946 
8947 static const struct externalui_message processmessage_actiondata_sequence[] = {
8948     {INSTALLMESSAGE_ACTIONDATA, 3, {"{{name: }}template", "cherry", "banana", "guava"}, {1, 1, 1, 1}},
8949     {0}
8950 };
8951 
8952 static const struct externalui_message processmessage_error_sequence[] = {
8953     {INSTALLMESSAGE_USER, 3, {"", "1311", "banana", "guava"}, {0, 1, 1, 1}},
8954     {0}
8955 };
8956 
8957 static const struct externalui_message processmessage_internal_error_sequence[] = {
8958     {INSTALLMESSAGE_INFO, 3, {"DEBUG: Error [1]:  Action not found: [2]", "2726", "banana", "guava"}, {1, 1, 1, 1}},
8959     {INSTALLMESSAGE_USER, 3, {"internal error", "2726", "banana", "guava"}, {1, 1, 1, 1}},
8960     {0}
8961 };
8962 
8963 static const struct externalui_message processmessage_error_format_sequence[] = {
8964     {INSTALLMESSAGE_USER, 3, {"", "2726", "banana", "guava"}, {0, 1, 1, 1}},
8965     {0}
8966 };
8967 
8968 static const struct externalui_message doaction_costinitialize_sequence[] = {
8969     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostInitialize", "cost description", "cost template"}, {0, 1, 1, 1}},
8970     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", ""}, {0, 1, 1}},
8971     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", "1"}, {0, 1, 1}},
8972     {0}
8973 };
8974 
8975 static const struct externalui_message doaction_custom_sequence[] = {
8976     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "description", "template"}, {0, 1, 1, 1}},
8977     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
8978     {INSTALLMESSAGE_INFO, 2, {"", "custom", "0"}, {0, 1, 1}},
8979     {0}
8980 };
8981 
8982 static const struct externalui_message doaction_custom_fullui_sequence[] = {
8983     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
8984     {INSTALLMESSAGE_INFO, 2, {"", "custom", ""}, {0, 1, 1}},
8985     {INSTALLMESSAGE_SHOWDIALOG, 0, {"custom"}, {1}},
8986     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
8987     {0}
8988 };
8989 
8990 static const struct externalui_message doaction_custom_cancel_sequence[] = {
8991     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
8992     {0}
8993 };
8994 
8995 static const struct externalui_message doaction_dialog_nonexistent_sequence[] = {
8996     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
8997     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
8998     {INSTALLMESSAGE_SHOWDIALOG, 0, {"custom"}, {1}},
8999     {INSTALLMESSAGE_INFO, 2, {"DEBUG: Error [1]:  Action not found: [2]", "2726", "custom"}, {1, 1, 1}},
9000     {INSTALLMESSAGE_INFO, 2, {"", "2726", "custom"}, {0, 1, 1}},
9001     {INSTALLMESSAGE_INFO, 2, {"", "custom", "0"}, {0, 1, 1}},
9002     {0}
9003 };
9004 
9005 static const struct externalui_message doaction_dialog_sequence[] = {
9006     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "dialog", "", ""}, {0, 1, 1, 1}},
9007     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "0"}, {0, 1, 1}},
9008     {INSTALLMESSAGE_SHOWDIALOG, 0, {"dialog"}, {1}},
9009     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "dialog", "Dialog created"}, {0, 1, 1}},
9010     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "1"}, {0, 1, 1}},
9011     {0}
9012 };
9013 
9014 static const struct externalui_message doaction_dialog_error_sequence[] = {
9015     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "error", "", ""}, {0, 1, 1, 1}},
9016     {INSTALLMESSAGE_INFO, 2, {"", "error", "1"}, {0, 1, 1}},
9017     {INSTALLMESSAGE_SHOWDIALOG, 0, {"error"}, {1}},
9018     {0}
9019 };
9020 
9021 static const struct externalui_message doaction_dialog_3_sequence[] = {
9022     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "dialog", "", ""}, {0, 1, 1, 1}},
9023     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "0"}, {0, 1, 1}},
9024     {INSTALLMESSAGE_SHOWDIALOG, 0, {"dialog"}, {1}},
9025     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "3"}, {0, 1, 1}},
9026     {0}
9027 };
9028 
9029 static const struct externalui_message doaction_dialog_12345_sequence[] = {
9030     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "dialog", "", ""}, {0, 1, 1, 1}},
9031     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "3"}, {0, 1, 1}},
9032     {INSTALLMESSAGE_SHOWDIALOG, 0, {"dialog"}, {1}},
9033     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "12345"}, {0, 1, 1}},
9034     {0}
9035 };
9036 
9037 static const struct externalui_message closehandle_sequence[] = {
9038     {INSTALLMESSAGE_TERMINATE, -1},
9039     {0}
9040 };
9041 
9042 static INT CALLBACK externalui_message_string_callback(void *context, UINT message, LPCSTR string)
9043 {
9044     INT retval = context ? *((INT *)context) : 0;
9045     struct externalui_message msg;
9046 
9047     msg.message = message;
9048     msg.field_count = 0;
9049     strcpy(msg.field[0], string);
9050     add_message(&msg);
9051 
9052     return retval;
9053 }
9054 
9055 static INT CALLBACK externalui_message_callback(void *context, UINT message, MSIHANDLE hrecord)
9056 {
9057     INT retval = context ? *((INT *)context) : 0;
9058     struct externalui_message msg;
9059     char buffer[256];
9060     DWORD length;
9061     UINT r;
9062     int i;
9063 
9064     msg.message = message;
9065     if (message == INSTALLMESSAGE_TERMINATE)
9066     {
9067         /* trying to access the record seems to hang on some versions of Windows */
9068         msg.field_count = -1;
9069         add_message(&msg);
9070         return 1;
9071     }
9072     msg.field_count = MsiRecordGetFieldCount(hrecord);
9073     for (i = 0; i <= msg.field_count; i++)
9074     {
9075         length = sizeof(buffer);
9076         r = MsiRecordGetStringA(hrecord, i, buffer, &length);
9077         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
9078         memcpy(msg.field[i], buffer, min(100, length+1));
9079     }
9080 
9081     /* top-level actions dump a list of all set properties; skip them since they're inconsistent */
9082     if (message == (INSTALLMESSAGE_INFO|MB_ICONHAND) && msg.field_count > 0 && !strncmp(msg.field[0], "Property", 8))
9083         return retval;
9084 
9085     add_message(&msg);
9086 
9087     return retval;
9088 }
9089 
9090 static void test_externalui_message(void)
9091 {
9092     /* test that events trigger the correct sequence of messages */
9093 
9094     INSTALLUI_HANDLER_RECORD prev;
9095     MSIHANDLE hdb, hpkg, hrecord;
9096     INT retval = 1;
9097     UINT r;
9098 
9099     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
9100 
9101     MsiSetExternalUIA(externalui_message_string_callback, INSTALLLOGMODE_SHOWDIALOG, &retval);
9102     r = MsiSetExternalUIRecord(externalui_message_callback, MSITEST_INSTALLLOGMODE, &retval, &prev);
9103 
9104     flush_sequence();
9105 
9106     CoInitialize(NULL);
9107 
9108     hdb = create_package_db();
9109     ok(hdb, "failed to create database\n");
9110 
9111     create_file_data("forcecodepage.idt", "\r\n\r\n1252\t_ForceCodepage\r\n");
9112     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
9113     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9114 
9115     r = run_query(hdb, "CREATE TABLE `Error` (`Error` SHORT NOT NULL, `Message` CHAR(0) PRIMARY KEY `Error`)");
9116     ok(r == ERROR_SUCCESS, "Failed to create Error table: %u\n", r);
9117     r = run_query(hdb, "INSERT INTO `Error` (`Error`, `Message`) VALUES (5, 'internal error')");
9118     ok(r == ERROR_SUCCESS, "Failed to insert into Error table: %u\n", r);
9119 
9120     create_actiontext_table(hdb);
9121     add_actiontext_entry(hdb, "'custom', 'description', 'template'");
9122     add_actiontext_entry(hdb, "'CostInitialize', 'cost description', 'cost template'");
9123 
9124     r = MsiOpenPackageA(NULL, &hpkg);
9125     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9126     ok_sequence(empty_sequence, "MsiOpenPackage with NULL db", FALSE);
9127 
9128     r = MsiOpenPackageA("nonexistent", &hpkg);
9129     ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
9130     ok_sequence(openpackage_nonexistent_sequence, "MsiOpenPackage with nonexistent db", FALSE);
9131 
9132     r = package_from_db(hdb, &hpkg);
9133     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
9134     {
9135         skip("Not enough rights to perform tests\n");
9136         DeleteFileA(msifile);
9137         return;
9138     }
9139     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
9140     ok_sequence(openpackage_sequence, "MsiOpenPackage with valid db", FALSE);
9141 
9142     /* Test MsiProcessMessage */
9143     hrecord = MsiCreateRecord(3);
9144     ok(hrecord, "failed to create record\n");
9145 
9146     MsiRecordSetStringA(hrecord, 0, "zero");
9147     MsiRecordSetStringA(hrecord, 1, "one");
9148     MsiRecordSetStringA(hrecord, 2, "two");
9149     MsiRecordSetStringA(hrecord, 3, "three");
9150     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_INFO, hrecord);
9151     ok(r == 1, "Expected 1, got %d\n", r);
9152     ok_sequence(processmessage_info_sequence, "MsiProcessMessage(INSTALLMESSAGE_INFO)", FALSE);
9153 
9154     MsiRecordSetStringA(hrecord, 1, "name");
9155     MsiRecordSetStringA(hrecord, 2, "description");
9156     MsiRecordSetStringA(hrecord, 3, "template");
9157     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_ACTIONSTART, hrecord);
9158     ok(r == 1, "Expected 1, got %d\n", r);
9159     ok_sequence(processmessage_actionstart_sequence, "MsiProcessMessage(INSTALLMESSAGE_ACTIONSTART)", FALSE);
9160 
9161     MsiRecordSetStringA(hrecord, 0, "apple");
9162     MsiRecordSetStringA(hrecord, 1, "cherry");
9163     MsiRecordSetStringA(hrecord, 2, "banana");
9164     MsiRecordSetStringA(hrecord, 3, "guava");
9165     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_ACTIONDATA, hrecord);
9166     ok(r == 1, "Expected 1, got %d\n", r);
9167     ok_sequence(processmessage_actiondata_sequence, "MsiProcessMessage(INSTALLMESSAGE_ACTIONDATA)", FALSE);
9168 
9169     /* non-internal error */
9170     MsiRecordSetStringA(hrecord, 0, NULL);
9171     MsiRecordSetInteger(hrecord, 1, 1311);
9172     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
9173     ok(r == 1, "Expected 1, got %d\n", r);
9174     ok_sequence(processmessage_error_sequence, "MsiProcessMessage non-internal error", FALSE);
9175 
9176     /* internal error */
9177     MsiRecordSetStringA(hrecord, 0, NULL);
9178     MsiRecordSetInteger(hrecord, 1, 2726);
9179     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
9180     ok(r == 0, "Expected 0, got %d\n", r);
9181     ok_sequence(processmessage_internal_error_sequence, "MsiProcessMessage internal error", FALSE);
9182 
9183     /* with format field */
9184     MsiRecordSetStringA(hrecord, 0, "starfruit");
9185     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
9186     ok(r == 1, "Expected 1, got %d\n", r);
9187     ok_sequence(processmessage_error_format_sequence, "MsiProcessMessage error", FALSE);
9188 
9189     /* Test a standard action */
9190     r = MsiDoActionA(hpkg, "CostInitialize");
9191     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9192     ok_sequence(doaction_costinitialize_sequence, "MsiDoAction(\"CostInitialize\")", FALSE);
9193 
9194     /* Test a custom action */
9195     r = MsiDoActionA(hpkg, "custom");
9196     ok(r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %d\n", r);
9197     ok_sequence(doaction_custom_sequence, "MsiDoAction(\"custom\")", FALSE);
9198 
9199     /* close the package */
9200     MsiCloseHandle(hpkg);
9201     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
9202 
9203     /* Test dialogs */
9204     hdb = create_package_db();
9205     ok(hdb, "failed to create database\n");
9206 
9207     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
9208     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9209 
9210     create_dialog_table(hdb);
9211     add_dialog_entry(hdb, "'dialog', 50, 50, 100, 100, 0, 'dummy'");
9212 
9213     create_control_table(hdb);
9214     add_control_entry(hdb, "'dialog', 'dummy', 'Text', 5, 5, 5, 5, 3, 'dummy'");
9215 
9216     r = package_from_db(hdb, &hpkg);
9217     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
9218     ok_sequence(openpackage_sequence, "MsiOpenPackage with valid db", FALSE);
9219 
9220     /* Test a custom action */
9221     r = MsiDoActionA(hpkg, "custom");
9222     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9223     ok_sequence(doaction_custom_fullui_sequence, "MsiDoAction(\"custom\")", FALSE);
9224 
9225     retval = 2;
9226     r = MsiDoActionA(hpkg, "custom");
9227     ok(r == ERROR_INSTALL_USEREXIT, "Expected ERROR_INSTALL_USEREXIT, got %d\n", r);
9228     ok_sequence(doaction_custom_cancel_sequence, "MsiDoAction(\"custom\")", FALSE);
9229 
9230     retval = 0;
9231     r = MsiDoActionA(hpkg, "custom");
9232     ok(r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %d\n", r);
9233     ok_sequence(doaction_dialog_nonexistent_sequence, "MsiDoAction(\"custom\")", FALSE);
9234 
9235     r = MsiDoActionA(hpkg, "dialog");
9236     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9237     ok_sequence(doaction_dialog_sequence, "MsiDoAction(\"dialog\")", FALSE);
9238 
9239     retval = -1;
9240     r = MsiDoActionA(hpkg, "error");
9241     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9242     ok_sequence(doaction_dialog_error_sequence, "MsiDoAction(\"error\")", FALSE);
9243 
9244     r = MsiDoActionA(hpkg, "error");
9245     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9246     ok_sequence(doaction_dialog_error_sequence, "MsiDoAction(\"error\")", FALSE);
9247 
9248     retval = -2;
9249     r = MsiDoActionA(hpkg, "custom");
9250     ok(r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %d\n", r);
9251     ok_sequence(doaction_dialog_nonexistent_sequence, "MsiDoAction(\"custom\")", FALSE);
9252 
9253     retval = 3;
9254     r = MsiDoActionA(hpkg, "dialog");
9255     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %d\n", r);
9256     ok_sequence(doaction_dialog_3_sequence, "MsiDoAction(\"dialog\")", FALSE);
9257 
9258     retval = 12345;
9259     r = MsiDoActionA(hpkg, "dialog");
9260     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_INSTALL_FAILURE, got %d\n", r);
9261     ok_sequence(doaction_dialog_12345_sequence, "MsiDoAction(\"dialog\")", FALSE);
9262 
9263     MsiCloseHandle(hpkg);
9264     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
9265 
9266     MsiCloseHandle(hrecord);
9267     CoUninitialize();
9268     DeleteFileA(msifile);
9269     DeleteFileA("forcecodepage.idt");
9270 }
9271 
9272 static const struct externalui_message controlevent_spawn_sequence[] = {
9273     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "spawn", "", ""}, {0, 1, 1, 1}},
9274     {INSTALLMESSAGE_INFO, 2, {"", "spawn", ""}, {0, 1, 1}},
9275     {INSTALLMESSAGE_SHOWDIALOG, 0, {"spawn"}, {1}},
9276     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "spawn", "Dialog created"}, {0, 1, 1}},
9277 
9278     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
9279     {INSTALLMESSAGE_INFO, 2, {"", "custom", ""}, {0, 1, 1}},
9280     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
9281 
9282     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "child1", "Dialog created"}, {0, 1, 1}},
9283 
9284     {INSTALLMESSAGE_INFO, 2, {"", "spawn", "2"}, {0, 1, 1}},
9285     {0}
9286 };
9287 
9288 static const struct externalui_message controlevent_spawn2_sequence[] = {
9289     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "spawn2", "", ""}, {0, 1, 1, 1}},
9290     {INSTALLMESSAGE_INFO, 2, {"", "spawn2", "2"}, {0, 1, 1}},
9291     {INSTALLMESSAGE_SHOWDIALOG, 0, {"spawn2"}, {1}},
9292     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "spawn2", "Dialog created"}, {0, 1, 1}},
9293 
9294     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
9295     {INSTALLMESSAGE_INFO, 2, {"", "custom", "2"}, {0, 1, 1}},
9296     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
9297 
9298     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "child2", "Dialog created"}, {0, 1, 1}},
9299 
9300     {INSTALLMESSAGE_INFO, 2, {"", "spawn2", "2"}, {0, 1, 1}},
9301     {0}
9302 };
9303 
9304 static void test_controlevent(void)
9305 {
9306     INSTALLUI_HANDLER_RECORD prev;
9307     MSIHANDLE hdb, hpkg;
9308     UINT r;
9309 
9310     if (!winetest_interactive)
9311     {
9312         skip("interactive ControlEvent tests\n");
9313         return;
9314     }
9315 
9316     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
9317 
9318     MsiSetExternalUIA(externalui_message_string_callback, INSTALLLOGMODE_SHOWDIALOG, NULL);
9319     r = MsiSetExternalUIRecord(externalui_message_callback, MSITEST_INSTALLLOGMODE, NULL, &prev);
9320 
9321     flush_sequence();
9322 
9323     CoInitialize(NULL);
9324 
9325     hdb = create_package_db();
9326     ok(hdb, "failed to create database\n");
9327 
9328     create_file_data("forcecodepage.idt", "\r\n\r\n1252\t_ForceCodepage\r\n");
9329     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
9330     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9331 
9332     create_dialog_table(hdb);
9333     add_dialog_entry(hdb, "'spawn', 50, 50, 100, 100, 3, 'button'");
9334     add_dialog_entry(hdb, "'spawn2', 50, 50, 100, 100, 3, 'button'");
9335     add_dialog_entry(hdb, "'child1', 50, 50, 80, 40, 3, 'exit'");
9336     add_dialog_entry(hdb, "'child2', 50, 50, 80, 40, 3, 'exit'");
9337 
9338     create_control_table(hdb);
9339     add_control_entry(hdb, "'spawn', 'button', 'PushButton', 10, 10, 66, 17, 3, 'Click me'");
9340     add_control_entry(hdb, "'spawn2', 'button', 'PushButton', 10, 10, 66, 17, 3, 'Click me'");
9341     add_control_entry(hdb, "'child1', 'exit', 'PushButton', 10, 10, 66, 17, 3, 'Click me'");
9342     add_control_entry(hdb, "'child2', 'exit', 'PushButton', 10, 10, 66, 17, 3, 'Click me'");
9343 
9344     create_controlevent_table(hdb);
9345     add_controlevent_entry(hdb, "'child1', 'exit', 'EndDialog', 'Exit', 1, 1");
9346     add_controlevent_entry(hdb, "'child2', 'exit', 'EndDialog', 'Exit', 1, 1");
9347 
9348     create_custom_action_table(hdb);
9349     add_custom_action_entry(hdb, "'custom', 51, 'dummy', 'dummy value'");
9350 
9351     /* SpawnDialog and EndDialog should trigger after all other events */
9352     add_controlevent_entry(hdb, "'spawn', 'button', 'SpawnDialog', 'child1', 1, 1");
9353     add_controlevent_entry(hdb, "'spawn', 'button', 'DoAction', 'custom', 1, 2");
9354 
9355     /* Multiple dialog events cause only the last one to be triggered */
9356     add_controlevent_entry(hdb, "'spawn2', 'button', 'SpawnDialog', 'child1', 1, 1");
9357     add_controlevent_entry(hdb, "'spawn2', 'button', 'SpawnDialog', 'child2', 1, 2");
9358     add_controlevent_entry(hdb, "'spawn2', 'button', 'DoAction', 'custom', 1, 3");
9359 
9360     r = package_from_db(hdb, &hpkg);
9361     ok(r == ERROR_SUCCESS, "failed to create package: %u\n", r);
9362     ok_sequence(openpackage_sequence, "MsiOpenPackage()", FALSE);
9363 
9364     r = MsiDoActionA(hpkg, "spawn");
9365     ok(r == ERROR_INSTALL_USEREXIT, "expected ERROR_INSTALL_USEREXIT, got %u\n", r);
9366     ok_sequence(controlevent_spawn_sequence, "control event: spawn", FALSE);
9367 
9368     r = MsiDoActionA(hpkg, "spawn2");
9369     ok(r == ERROR_INSTALL_USEREXIT, "expected ERROR_INSTALL_USEREXIT, got %u\n", r);
9370     ok_sequence(controlevent_spawn2_sequence, "control event: spawn2", FALSE);
9371 
9372     MsiCloseHandle(hpkg);
9373     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
9374 
9375     CoUninitialize();
9376     DeleteFileA(msifile);
9377     DeleteFileA("forcecodepage.idt");
9378 }
9379 
9380 static const struct externalui_message toplevel_install_sequence[] = {
9381     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "INSTALL", "", ""}, {0, 1, 1, 1}},
9382     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", ""}, {0, 1, 1}},
9383 
9384     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9385     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9386     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
9387     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9388     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9389 
9390     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "INSTALL", "", ""}, {0, 1, 1, 1}},
9391     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", ""}, {0, 1, 1}},
9392     {INSTALLMESSAGE_INSTALLSTART, 2, {"", "", "{7262AC98-EEBD-4364-8CE3-D654F6A425B9}"}, {1, 1, 1}, 1},
9393 
9394     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostInitialize", "", ""}, {0, 1, 0, 1}},
9395     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", ""}, {0, 1, 1}},
9396     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", "1"}, {0, 1, 1}},
9397 
9398     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "FileCost", "", ""}, {0, 1, 0, 1}},
9399     {INSTALLMESSAGE_INFO, 2, {"", "FileCost", "1"}, {0, 1, 1}},
9400     {INSTALLMESSAGE_INFO, 2, {"", "FileCost", "1"}, {0, 1, 1}},
9401 
9402     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostFinalize", "", ""}, {0, 1, 0, 1}},
9403     {INSTALLMESSAGE_INFO, 2, {"", "CostFinalize", "1"}, {0, 1, 1}},
9404     {INSTALLMESSAGE_INFO, 2, {"", "CostFinalize", "1"}, {0, 1, 1}},
9405 
9406     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", "1"}, {0, 1, 1}},
9407     {INSTALLMESSAGE_INSTALLEND, 3, {"", "", "{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "1"}, {1, 1, 1, 1}, 1},
9408 
9409     /* property dump */
9410 
9411     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "0"}, {0, 1, 1}, 1},
9412     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "1"}, {0, 1, 1}, 1},
9413     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", "1"}, {0, 1, 1}},
9414     {0}
9415 };
9416 
9417 static const struct externalui_message toplevel_install_ui_sequence[] = {
9418     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "INSTALL", "", ""}, {0, 1, 1, 1}},
9419     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", ""}, {0, 1, 1}},
9420 
9421     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "AppSearch", "", ""}, {0, 1, 0, 0}},
9422     {INSTALLMESSAGE_INFO, 2, {"", "AppSearch", ""}, {0, 1, 1}},
9423     {INSTALLMESSAGE_INFO, 2, {"", "AppSearch", "0"}, {0, 1, 1}},
9424 
9425     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", "1"}, {0, 1, 1}},
9426     {0}
9427 };
9428 
9429 static const struct externalui_message toplevel_executeaction_install_sequence[] = {
9430     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "ExecuteAction", "", ""}, {0, 1, 1, 1}},
9431     {INSTALLMESSAGE_INFO, 2, {"", "ExecuteAction", "1"}, {0, 1, 1}},
9432 
9433     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9434     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9435     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9436     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9437 
9438     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "INSTALL", "", ""}, {0, 1, 1, 1}},
9439     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", ""}, {0, 1, 1}},
9440     {INSTALLMESSAGE_INSTALLSTART, 2, {"", "", "{7262AC98-EEBD-4364-8CE3-D654F6A425B9}"}, {1, 1, 1}, 1},
9441 
9442     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostInitialize", "", ""}, {0, 1, 0, 1}},
9443     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize"}, {0, 1}},
9444     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", "1"}, {0, 1, 1}},
9445 
9446     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "FileCost", "", ""}, {0, 1, 0, 1}},
9447     {INSTALLMESSAGE_INFO, 2, {"", "FileCost", "1"}, {0, 1, 1}},
9448     {INSTALLMESSAGE_INFO, 2, {"", "FileCost", "1"}, {0, 1, 1}},
9449 
9450     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostFinalize", "", ""}, {0, 1, 0, 1}},
9451     {INSTALLMESSAGE_INFO, 2, {"", "CostFinalize", "1"}, {0, 1, 1}},
9452     {INSTALLMESSAGE_INFO, 2, {"", "CostFinalize", "1"}, {0, 1, 1}},
9453 
9454     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", "1"}, {0, 1, 1}},
9455     {INSTALLMESSAGE_INSTALLEND, 3, {"", "", "{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "1"}, {1, 1, 1, 1}, 1},
9456 
9457     /* property dump */
9458 
9459     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "0"}, {0, 1, 1}, 1},
9460     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "1"}, {0, 1, 1}, 1},
9461     {INSTALLMESSAGE_INFO, 2, {"", "ExecuteAction", "1"}, {0, 1, 1}},
9462     {0}
9463 };
9464 
9465 static const struct externalui_message toplevel_executeaction_costinitialize_sequence[] = {
9466     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "ExecuteAction", "", ""}, {0, 1, 1, 1}},
9467     {INSTALLMESSAGE_INFO, 2, {"", "ExecuteAction", "1"}, {0, 1, 1}},
9468 
9469     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9470     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9471     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9472     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9473 
9474     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostInitialize", "", ""}, {0, 1, 0, 1}},
9475     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", ""}, {0, 1}},
9476     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", "1"}, {0, 1, 1}},
9477 
9478     /* property dump */
9479 
9480     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "0"}, {0, 1, 1}, 1},
9481     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "1"}, {0, 1, 1}, 1},
9482     {INSTALLMESSAGE_INFO, 2, {"", "ExecuteAction", "1"}, {0, 1, 1}},
9483     {0}
9484 };
9485 
9486 static const struct externalui_message toplevel_msiinstallproduct_sequence[] = {
9487     {INSTALLMESSAGE_INITIALIZE, -1},
9488 
9489     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9490     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9491     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
9492     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9493     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9494 
9495     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "INSTALL", "", ""}, {0, 1, 1, 1}},
9496     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", ""}, {0, 1, 1}},
9497 
9498     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "AppSearch", "", ""}, {0, 1, 0, 0}},
9499     {INSTALLMESSAGE_INFO, 2, {"", "AppSearch", ""}, {0, 1, 1}},
9500     {INSTALLMESSAGE_INFO, 2, {"", "AppSearch", "0"}, {0, 1, 1}},
9501 
9502     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", "1"}, {0, 1, 1}},
9503 
9504     /* property dump */
9505 
9506     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
9507     {INSTALLMESSAGE_TERMINATE, -1},
9508     {0}
9509 };
9510 
9511 static const struct externalui_message toplevel_msiinstallproduct_custom_sequence[] = {
9512     {INSTALLMESSAGE_INITIALIZE, -1},
9513 
9514     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9515     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9516     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
9517     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9518     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9519 
9520     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CUSTOM", "", ""}, {0, 1, 1, 1}},
9521     {INSTALLMESSAGE_INFO, 2, {"", "CUSTOM", ""}, {0, 1, 1}},
9522     {INSTALLMESSAGE_INFO, 2, {"", "CUSTOM", "0"}, {0, 1, 1}},
9523 
9524     /* property dump */
9525 
9526     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
9527     {INSTALLMESSAGE_TERMINATE, -1},
9528     {0}
9529 };
9530 
9531 /* tests involving top-level actions: INSTALL, ExecuteAction */
9532 static void test_top_level_action(void)
9533 {
9534     INSTALLUI_HANDLER_RECORD prev;
9535     MSIHANDLE hdb, hpkg;
9536     UINT r;
9537     char msifile_absolute[MAX_PATH];
9538 
9539     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
9540 
9541     MsiSetExternalUIA(externalui_message_string_callback, INSTALLLOGMODE_SHOWDIALOG, NULL);
9542     r = MsiSetExternalUIRecord(externalui_message_callback, MSITEST_INSTALLLOGMODE, NULL, &prev);
9543 
9544     flush_sequence();
9545 
9546     CoInitialize(NULL);
9547 
9548     hdb = create_package_db();
9549     ok(hdb, "failed to create database\n");
9550 
9551     create_file_data("forcecodepage.idt", "\r\n\r\n1252\t_ForceCodepage\r\n");
9552     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
9553     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9554 
9555     create_property_table(hdb);
9556     add_property_entry(hdb, "'ProductCode', '{7262AC98-EEBD-4364-8CE3-D654F6A425B9}'");
9557 
9558     create_install_execute_sequence_table(hdb);
9559     add_install_execute_sequence_entry(hdb, "'CostInitialize', '', 1");
9560     add_install_execute_sequence_entry(hdb, "'FileCost', '', 2");
9561     add_install_execute_sequence_entry(hdb, "'CostFinalize', '', 3");
9562 
9563     create_install_ui_sequence_table(hdb);
9564     add_install_ui_sequence_entry(hdb, "'AppSearch', '', 1");
9565 
9566     MsiDatabaseCommit(hdb);
9567 
9568     /* for some reason we have to open the package from file using an absolute path */
9569     MsiCloseHandle(hdb);
9570     GetFullPathNameA(msifile, MAX_PATH, msifile_absolute, NULL);
9571     r = MsiOpenPackageA(msifile_absolute, &hpkg);
9572     ok(r == ERROR_SUCCESS, "failed to create package: %u\n", r);
9573     ok_sequence(openpackage_sequence, "MsiOpenPackage()", FALSE);
9574 
9575     /* test INSTALL */
9576     r = MsiDoActionA(hpkg, "INSTALL");
9577     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
9578     ok_sequence(toplevel_install_sequence, "INSTALL (no UI)", FALSE);
9579 
9580     /* test INSTALL with reduced+ UI */
9581     /* for some reason we need to re-open the package to change the internal UI */
9582     MsiCloseHandle(hpkg);
9583     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
9584     MsiSetInternalUI(INSTALLUILEVEL_REDUCED, NULL);
9585     r = MsiOpenPackageA(msifile_absolute, &hpkg);
9586     ok(r == ERROR_SUCCESS, "failed to create package: %u\n", r);
9587     ok_sequence(openpackage_sequence, "MsiOpenPackage()", FALSE);
9588 
9589     r = MsiDoActionA(hpkg, "INSTALL");
9590     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
9591     ok_sequence(toplevel_install_ui_sequence, "INSTALL (reduced+ UI)", TRUE);
9592 
9593     /* test ExecuteAction with EXECUTEACTION property unset */
9594     MsiSetPropertyA(hpkg, "EXECUTEACTION", NULL);
9595     r = MsiDoActionA(hpkg, "ExecuteAction");
9596     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
9597     ok_sequence(toplevel_executeaction_install_sequence, "ExecuteAction: INSTALL", FALSE);
9598 
9599     /* test ExecuteAction with EXECUTEACTION property set */
9600     MsiSetPropertyA(hpkg, "EXECUTEACTION", "CostInitialize");
9601     r = MsiDoActionA(hpkg, "ExecuteAction");
9602     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
9603     ok_sequence(toplevel_executeaction_costinitialize_sequence, "ExecuteAction: CostInitialize", FALSE);
9604 
9605     MsiCloseHandle(hpkg);
9606     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
9607 
9608     /* test MsiInstallProduct() */
9609     r = MsiInstallProductA(msifile_absolute, NULL);
9610     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
9611     ok_sequence(toplevel_msiinstallproduct_sequence, "MsiInstallProduct()", TRUE);
9612 
9613     r = MsiInstallProductA(msifile_absolute, "ACTION=custom");
9614     todo_wine
9615     ok(r == ERROR_INSTALL_FAILURE, "expected ERROR_INSTALL_FAILURE, got %u\n", r);
9616     ok_sequence(toplevel_msiinstallproduct_custom_sequence, "MsiInstallProduct(ACTION=custom)", TRUE);
9617 
9618     CoUninitialize();
9619     DeleteFileA(msifile);
9620     DeleteFileA("forcecodepage.idt");
9621 }
9622 
9623 START_TEST(package)
9624 {
9625     char temp_path[MAX_PATH], prev_path[MAX_PATH];
9626     STATEMGRSTATUS status;
9627     BOOL ret = FALSE;
9628     DWORD len;
9629 
9630     init_functionpointers();
9631 
9632     if (pIsWow64Process)
9633         pIsWow64Process(GetCurrentProcess(), &is_wow64);
9634 
9635     GetCurrentDirectoryA(MAX_PATH, prev_path);
9636     GetTempPathA(MAX_PATH, temp_path);
9637     SetCurrentDirectoryA(temp_path);
9638 
9639     lstrcpyA(CURR_DIR, temp_path);
9640     len = lstrlenA(CURR_DIR);
9641 
9642     if (len && (CURR_DIR[len - 1] == '\\'))
9643         CURR_DIR[len - 1] = 0;
9644 
9645     /* Create a restore point ourselves so we circumvent the multitude of restore points
9646      * that would have been created by all the installation and removal tests.
9647      *
9648      * This is not needed on version 5.0 where setting MSIFASTINSTALL prevents the
9649      * creation of restore points.
9650      */
9651     if (pSRSetRestorePointA && !pMsiGetComponentPathExA)
9652     {
9653         memset(&status, 0, sizeof(status));
9654         ret = notify_system_change(BEGIN_NESTED_SYSTEM_CHANGE, &status);
9655     }
9656 
9657     test_createpackage();
9658     test_doaction();
9659     test_gettargetpath_bad();
9660     test_settargetpath();
9661     test_props();
9662     test_property_table();
9663     test_condition();
9664     test_msipackage();
9665     test_formatrecord2();
9666     test_formatrecord_tables();
9667     test_states();
9668     test_removefiles();
9669     test_appsearch();
9670     test_appsearch_complocator();
9671     test_appsearch_reglocator();
9672     test_appsearch_inilocator();
9673     test_appsearch_drlocator();
9674     test_featureparents();
9675     test_installprops();
9676     test_launchconditions();
9677     test_ccpsearch();
9678     test_complocator();
9679     test_MsiGetSourcePath();
9680     test_shortlongsource();
9681     test_sourcedir();
9682     test_access();
9683     test_emptypackage();
9684     test_MsiGetProductProperty();
9685     test_MsiSetProperty();
9686     test_MsiApplyMultiplePatches();
9687     test_MsiApplyPatch();
9688     test_costs();
9689     test_MsiDatabaseCommit();
9690     test_externalui();
9691     test_externalui_message();
9692     test_controlevent();
9693     test_top_level_action();
9694 
9695     if (pSRSetRestorePointA && !pMsiGetComponentPathExA && ret)
9696     {
9697         ret = notify_system_change(END_NESTED_SYSTEM_CHANGE, &status);
9698         if (ret)
9699             remove_restore_point(status.llSequenceNumber);
9700     }
9701 
9702     SetCurrentDirectoryA(prev_path);
9703 }
9704