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 #include "precomp.h"
23 
24 #include <assert.h>
25 #include <shlobj.h>
26 
27 static BOOL is_wow64;
28 static const char msifile[] = "winetest-package.msi";
29 static const WCHAR msifileW[] =
30     {'w','i','n','e','t','e','s','t','-','p','a','c','k','a','g','e','.','m','s','i',0};
31 static char CURR_DIR[MAX_PATH];
32 
33 static INSTALLSTATE (WINAPI *pMsiGetComponentPathExA)(LPCSTR, LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPSTR, LPDWORD);
34 static HRESULT (WINAPI *pSHGetFolderPathA)(HWND, int, HANDLE, DWORD, LPSTR);
35 
36 static BOOL (WINAPI *pCheckTokenMembership)(HANDLE,PSID,PBOOL);
37 static BOOL (WINAPI *pConvertSidToStringSidA)(PSID, LPSTR*);
38 static BOOL (WINAPI *pOpenProcessToken)( HANDLE, DWORD, PHANDLE );
39 static LONG (WINAPI *pRegDeleteKeyExA)(HKEY, LPCSTR, REGSAM, DWORD);
40 static LONG (WINAPI *pRegDeleteKeyExW)(HKEY, LPCWSTR, REGSAM, DWORD);
41 static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
42 static void (WINAPI *pGetSystemInfo)(LPSYSTEM_INFO);
43 static void (WINAPI *pGetNativeSystemInfo)(LPSYSTEM_INFO);
44 static UINT (WINAPI *pGetSystemWow64DirectoryA)(LPSTR, UINT);
45 
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 hshell32 = GetModuleHandleA("shell32.dll");
55     HMODULE hsrclient;
56 
57 #define GET_PROC(mod, func) \
58     p ## func = (void*)GetProcAddress(mod, #func);
59 
60     GET_PROC(hmsi, MsiGetComponentPathExA);
61     GET_PROC(hshell32, SHGetFolderPathA);
62 
63     GET_PROC(hadvapi32, CheckTokenMembership);
64     GET_PROC(hadvapi32, ConvertSidToStringSidA);
65     GET_PROC(hadvapi32, OpenProcessToken);
66     GET_PROC(hadvapi32, RegDeleteKeyExA)
67     GET_PROC(hadvapi32, RegDeleteKeyExW)
68     GET_PROC(hkernel32, IsWow64Process)
69     GET_PROC(hkernel32, GetNativeSystemInfo)
70     GET_PROC(hkernel32, GetSystemInfo)
71     GET_PROC(hkernel32, GetSystemWow64DirectoryA)
72 
73     hsrclient = LoadLibraryA("srclient.dll");
74     GET_PROC(hsrclient, SRRemoveRestorePoint);
75     GET_PROC(hsrclient, SRSetRestorePointA);
76 #undef GET_PROC
77 }
78 
79 static BOOL is_process_limited(void)
80 {
81     SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
82     PSID Group = NULL;
83     BOOL IsInGroup;
84     HANDLE token;
85 
86     if (!pCheckTokenMembership || !pOpenProcessToken) return FALSE;
87 
88     if (!AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
89                                   DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &Group) ||
90         !pCheckTokenMembership(NULL, Group, &IsInGroup))
91     {
92         trace("Could not check if the current user is an administrator\n");
93         FreeSid(Group);
94         return FALSE;
95     }
96     FreeSid(Group);
97 
98     if (!IsInGroup)
99     {
100         if (!AllocateAndInitializeSid(&NtAuthority, 2,
101                                       SECURITY_BUILTIN_DOMAIN_RID,
102                                       DOMAIN_ALIAS_RID_POWER_USERS,
103                                       0, 0, 0, 0, 0, 0, &Group) ||
104             !pCheckTokenMembership(NULL, Group, &IsInGroup))
105         {
106             trace("Could not check if the current user is a power user\n");
107             return FALSE;
108         }
109         if (!IsInGroup)
110         {
111             /* Only administrators and power users can be powerful */
112             return TRUE;
113         }
114     }
115 
116     if (pOpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
117     {
118         BOOL ret;
119         TOKEN_ELEVATION_TYPE type = TokenElevationTypeDefault;
120         DWORD size;
121 
122         ret = GetTokenInformation(token, TokenElevationType, &type, sizeof(type), &size);
123         CloseHandle(token);
124         return (ret && type == TokenElevationTypeLimited);
125     }
126     return FALSE;
127 }
128 
129 static LONG delete_key( HKEY key, LPCSTR subkey, REGSAM access )
130 {
131     if (pRegDeleteKeyExA)
132         return pRegDeleteKeyExA( key, subkey, access, 0 );
133     return RegDeleteKeyA( key, subkey );
134 }
135 
136 static char *get_user_sid(void)
137 {
138     HANDLE token;
139     DWORD size = 0;
140     TOKEN_USER *user;
141     char *usersid = NULL;
142 
143     if (!pConvertSidToStringSidA)
144     {
145         win_skip("ConvertSidToStringSidA is not available\n");
146         return NULL;
147     }
148     OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
149     GetTokenInformation(token, TokenUser, NULL, size, &size);
150 
151     user = HeapAlloc(GetProcessHeap(), 0, size);
152     GetTokenInformation(token, TokenUser, user, size, &size);
153     pConvertSidToStringSidA(user->User.Sid, &usersid);
154     HeapFree(GetProcessHeap(), 0, user);
155 
156     CloseHandle(token);
157     return usersid;
158 }
159 
160 /* RegDeleteTreeW from dlls/advapi32/registry.c */
161 static LSTATUS package_RegDeleteTreeW(HKEY hKey, LPCWSTR lpszSubKey, REGSAM access)
162 {
163     LONG ret;
164     DWORD dwMaxSubkeyLen, dwMaxValueLen;
165     DWORD dwMaxLen, dwSize;
166     WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
167     HKEY hSubKey = hKey;
168 
169     if(lpszSubKey)
170     {
171         ret = RegOpenKeyExW(hKey, lpszSubKey, 0, access, &hSubKey);
172         if (ret) return ret;
173     }
174 
175     ret = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL,
176             &dwMaxSubkeyLen, NULL, NULL, &dwMaxValueLen, NULL, NULL, NULL);
177     if (ret) goto cleanup;
178 
179     dwMaxSubkeyLen++;
180     dwMaxValueLen++;
181     dwMaxLen = max(dwMaxSubkeyLen, dwMaxValueLen);
182     if (dwMaxLen > sizeof(szNameBuf)/sizeof(WCHAR))
183     {
184         /* Name too big: alloc a buffer for it */
185         if (!(lpszName = HeapAlloc( GetProcessHeap(), 0, dwMaxLen*sizeof(WCHAR))))
186         {
187             ret = ERROR_NOT_ENOUGH_MEMORY;
188             goto cleanup;
189         }
190     }
191 
192     /* Recursively delete all the subkeys */
193     while (TRUE)
194     {
195         dwSize = dwMaxLen;
196         if (RegEnumKeyExW(hSubKey, 0, lpszName, &dwSize, NULL,
197                           NULL, NULL, NULL)) break;
198 
199         ret = package_RegDeleteTreeW(hSubKey, lpszName, access);
200         if (ret) goto cleanup;
201     }
202 
203     if (lpszSubKey)
204     {
205         if (pRegDeleteKeyExW)
206             ret = pRegDeleteKeyExW(hKey, lpszSubKey, access, 0);
207         else
208             ret = RegDeleteKeyW(hKey, lpszSubKey);
209     }
210     else
211         while (TRUE)
212         {
213             dwSize = dwMaxLen;
214             if (RegEnumValueW(hKey, 0, lpszName, &dwSize,
215                   NULL, NULL, NULL, NULL)) break;
216 
217             ret = RegDeleteValueW(hKey, lpszName);
218             if (ret) goto cleanup;
219         }
220 
221 cleanup:
222     if (lpszName != szNameBuf)
223         HeapFree(GetProcessHeap(), 0, lpszName);
224     if(lpszSubKey)
225         RegCloseKey(hSubKey);
226     return ret;
227 }
228 
229 static BOOL squash_guid(LPCWSTR in, LPWSTR out)
230 {
231     DWORD i,n=1;
232     GUID guid;
233 
234     if (FAILED(CLSIDFromString((LPCOLESTR)in, &guid)))
235         return FALSE;
236 
237     for(i=0; i<8; i++)
238         out[7-i] = in[n++];
239     n++;
240     for(i=0; i<4; i++)
241         out[11-i] = in[n++];
242     n++;
243     for(i=0; i<4; i++)
244         out[15-i] = in[n++];
245     n++;
246     for(i=0; i<2; i++)
247     {
248         out[17+i*2] = in[n++];
249         out[16+i*2] = in[n++];
250     }
251     n++;
252     for( ; i<8; i++)
253     {
254         out[17+i*2] = in[n++];
255         out[16+i*2] = in[n++];
256     }
257     out[32]=0;
258     return TRUE;
259 }
260 
261 static void create_test_guid(LPSTR prodcode, LPSTR squashed)
262 {
263     WCHAR guidW[MAX_PATH];
264     WCHAR squashedW[MAX_PATH];
265     GUID guid;
266     HRESULT hr;
267     int size;
268 
269     hr = CoCreateGuid(&guid);
270     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
271 
272     size = StringFromGUID2(&guid, guidW, MAX_PATH);
273     ok(size == 39, "Expected 39, got %d\n", hr);
274 
275     WideCharToMultiByte(CP_ACP, 0, guidW, size, prodcode, MAX_PATH, NULL, NULL);
276     squash_guid(guidW, squashedW);
277     WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
278 }
279 
280 static void set_component_path(LPCSTR filename, MSIINSTALLCONTEXT context,
281                                LPCSTR guid, LPSTR usersid, BOOL dir)
282 {
283     WCHAR guidW[MAX_PATH];
284     WCHAR squashedW[MAX_PATH];
285     CHAR squashed[MAX_PATH];
286     CHAR comppath[MAX_PATH];
287     CHAR prodpath[MAX_PATH];
288     CHAR path[MAX_PATH];
289     LPCSTR prod = NULL;
290     HKEY hkey;
291     REGSAM access = KEY_ALL_ACCESS;
292 
293     if (is_wow64)
294         access |= KEY_WOW64_64KEY;
295 
296     MultiByteToWideChar(CP_ACP, 0, guid, -1, guidW, MAX_PATH);
297     squash_guid(guidW, squashedW);
298     WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
299 
300     if (context == MSIINSTALLCONTEXT_MACHINE)
301     {
302         prod = "3D0DAE300FACA1300AD792060BCDAA92";
303         sprintf(comppath,
304                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
305                 "Installer\\UserData\\S-1-5-18\\Components\\%s", squashed);
306         lstrcpyA(prodpath,
307                  "SOFTWARE\\Classes\\Installer\\"
308                  "Products\\3D0DAE300FACA1300AD792060BCDAA92");
309     }
310     else if (context == MSIINSTALLCONTEXT_USERUNMANAGED)
311     {
312         prod = "7D2F387510109040002000060BECB6AB";
313         sprintf(comppath,
314                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
315                 "Installer\\UserData\\%s\\Components\\%s", usersid, squashed);
316         sprintf(prodpath,
317                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
318                 "Installer\\%s\\Installer\\Products\\"
319                 "7D2F387510109040002000060BECB6AB", usersid);
320     }
321     else if (context == MSIINSTALLCONTEXT_USERMANAGED)
322     {
323         prod = "7D2F387510109040002000060BECB6AB";
324         sprintf(comppath,
325                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
326                 "Installer\\UserData\\%s\\Components\\%s", usersid, squashed);
327         sprintf(prodpath,
328                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
329                 "Installer\\Managed\\%s\\Installer\\Products\\"
330                 "7D2F387510109040002000060BECB6AB", usersid);
331     }
332 
333     RegCreateKeyExA(HKEY_LOCAL_MACHINE, comppath, 0, NULL, 0, access, NULL, &hkey, NULL);
334 
335     lstrcpyA(path, CURR_DIR);
336     lstrcatA(path, "\\");
337     if (!dir) lstrcatA(path, filename);
338 
339     RegSetValueExA(hkey, prod, 0, REG_SZ, (LPBYTE)path, lstrlenA(path));
340     RegCloseKey(hkey);
341 
342     RegCreateKeyExA(HKEY_LOCAL_MACHINE, prodpath, 0, NULL, 0, access, NULL, &hkey, NULL);
343     RegCloseKey(hkey);
344 }
345 
346 static void delete_component_path(LPCSTR guid, MSIINSTALLCONTEXT context, LPSTR usersid)
347 {
348     WCHAR guidW[MAX_PATH];
349     WCHAR squashedW[MAX_PATH];
350     WCHAR substrW[MAX_PATH];
351     CHAR squashed[MAX_PATH];
352     CHAR comppath[MAX_PATH];
353     CHAR prodpath[MAX_PATH];
354     REGSAM access = KEY_ALL_ACCESS;
355 
356     if (is_wow64)
357         access |= KEY_WOW64_64KEY;
358 
359     MultiByteToWideChar(CP_ACP, 0, guid, -1, guidW, MAX_PATH);
360     squash_guid(guidW, squashedW);
361     WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
362 
363     if (context == MSIINSTALLCONTEXT_MACHINE)
364     {
365         sprintf(comppath,
366                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
367                 "Installer\\UserData\\S-1-5-18\\Components\\%s", squashed);
368         lstrcpyA(prodpath,
369                  "SOFTWARE\\Classes\\Installer\\"
370                  "Products\\3D0DAE300FACA1300AD792060BCDAA92");
371     }
372     else if (context == MSIINSTALLCONTEXT_USERUNMANAGED)
373     {
374         sprintf(comppath,
375                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
376                 "Installer\\UserData\\%s\\Components\\%s", usersid, squashed);
377         sprintf(prodpath,
378                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
379                 "Installer\\%s\\Installer\\Products\\"
380                 "7D2F387510109040002000060BECB6AB", usersid);
381     }
382     else if (context == MSIINSTALLCONTEXT_USERMANAGED)
383     {
384         sprintf(comppath,
385                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
386                 "Installer\\UserData\\%s\\Components\\%s", usersid, squashed);
387         sprintf(prodpath,
388                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
389                 "Installer\\Managed\\%s\\Installer\\Products\\"
390                 "7D2F387510109040002000060BECB6AB", usersid);
391     }
392 
393     MultiByteToWideChar(CP_ACP, 0, comppath, -1, substrW, MAX_PATH);
394     package_RegDeleteTreeW(HKEY_LOCAL_MACHINE, substrW, access);
395 
396     MultiByteToWideChar(CP_ACP, 0, prodpath, -1, substrW, MAX_PATH);
397     package_RegDeleteTreeW(HKEY_LOCAL_MACHINE, substrW, access);
398 }
399 
400 static UINT do_query(MSIHANDLE hdb, const char *query, MSIHANDLE *phrec)
401 {
402     MSIHANDLE hview = 0;
403     UINT r, ret;
404 
405     /* open a select query */
406     r = MsiDatabaseOpenViewA(hdb, query, &hview);
407     if (r != ERROR_SUCCESS)
408         return r;
409     r = MsiViewExecute(hview, 0);
410     if (r != ERROR_SUCCESS)
411         return r;
412     ret = MsiViewFetch(hview, phrec);
413     r = MsiViewClose(hview);
414     if (r != ERROR_SUCCESS)
415         return r;
416     r = MsiCloseHandle(hview);
417     if (r != ERROR_SUCCESS)
418         return r;
419     return ret;
420 }
421 
422 static UINT run_query( MSIHANDLE hdb, const char *query )
423 {
424     MSIHANDLE hview = 0;
425     UINT r;
426 
427     r = MsiDatabaseOpenViewA(hdb, query, &hview);
428     if( r != ERROR_SUCCESS )
429         return r;
430 
431     r = MsiViewExecute(hview, 0);
432     if( r == ERROR_SUCCESS )
433         r = MsiViewClose(hview);
434     MsiCloseHandle(hview);
435     return r;
436 }
437 
438 static UINT create_component_table( MSIHANDLE hdb )
439 {
440     UINT r = run_query( hdb,
441             "CREATE TABLE `Component` ( "
442             "`Component` CHAR(72) NOT NULL, "
443             "`ComponentId` CHAR(38), "
444             "`Directory_` CHAR(72) NOT NULL, "
445             "`Attributes` SHORT NOT NULL, "
446             "`Condition` CHAR(255), "
447             "`KeyPath` CHAR(72) "
448             "PRIMARY KEY `Component`)" );
449     ok(r == ERROR_SUCCESS, "Failed to create Component table: %u\n", r);
450     return r;
451 }
452 
453 static UINT create_feature_table( MSIHANDLE hdb )
454 {
455     UINT r = run_query( hdb,
456             "CREATE TABLE `Feature` ( "
457             "`Feature` CHAR(38) NOT NULL, "
458             "`Feature_Parent` CHAR(38), "
459             "`Title` CHAR(64), "
460             "`Description` CHAR(255), "
461             "`Display` SHORT NOT NULL, "
462             "`Level` SHORT NOT NULL, "
463             "`Directory_` CHAR(72), "
464             "`Attributes` SHORT NOT NULL "
465             "PRIMARY KEY `Feature`)" );
466     ok(r == ERROR_SUCCESS, "Failed to create Feature table: %u\n", r);
467     return r;
468 }
469 
470 static UINT create_feature_components_table( MSIHANDLE hdb )
471 {
472     UINT r = run_query( hdb,
473             "CREATE TABLE `FeatureComponents` ( "
474             "`Feature_` CHAR(38) NOT NULL, "
475             "`Component_` CHAR(72) NOT NULL "
476             "PRIMARY KEY `Feature_`, `Component_` )" );
477     ok(r == ERROR_SUCCESS, "Failed to create FeatureComponents table: %u\n", r);
478     return r;
479 }
480 
481 static UINT create_file_table( MSIHANDLE hdb )
482 {
483     UINT r = run_query( hdb,
484             "CREATE TABLE `File` ("
485             "`File` CHAR(72) NOT NULL, "
486             "`Component_` CHAR(72) NOT NULL, "
487             "`FileName` CHAR(255) NOT NULL, "
488             "`FileSize` LONG NOT NULL, "
489             "`Version` CHAR(72), "
490             "`Language` CHAR(20), "
491             "`Attributes` SHORT, "
492             "`Sequence` SHORT NOT NULL "
493             "PRIMARY KEY `File`)" );
494     ok(r == ERROR_SUCCESS, "Failed to create File table: %u\n", r);
495     return r;
496 }
497 
498 static UINT create_remove_file_table( MSIHANDLE hdb )
499 {
500     UINT r = run_query( hdb,
501             "CREATE TABLE `RemoveFile` ("
502             "`FileKey` CHAR(72) NOT NULL, "
503             "`Component_` CHAR(72) NOT NULL, "
504             "`FileName` CHAR(255) LOCALIZABLE, "
505             "`DirProperty` CHAR(72) NOT NULL, "
506             "`InstallMode` SHORT NOT NULL "
507             "PRIMARY KEY `FileKey`)" );
508     ok(r == ERROR_SUCCESS, "Failed to create RemoveFile table: %u\n", r);
509     return r;
510 }
511 
512 static UINT create_appsearch_table( MSIHANDLE hdb )
513 {
514     UINT r = run_query( hdb,
515             "CREATE TABLE `AppSearch` ("
516             "`Property` CHAR(72) NOT NULL, "
517             "`Signature_` CHAR(72) NOT NULL "
518             "PRIMARY KEY `Property`, `Signature_`)" );
519     ok(r == ERROR_SUCCESS, "Failed to create AppSearch table: %u\n", r);
520     return r;
521 }
522 
523 static UINT create_reglocator_table( MSIHANDLE hdb )
524 {
525     UINT r = run_query( hdb,
526             "CREATE TABLE `RegLocator` ("
527             "`Signature_` CHAR(72) NOT NULL, "
528             "`Root` SHORT NOT NULL, "
529             "`Key` CHAR(255) NOT NULL, "
530             "`Name` CHAR(255), "
531             "`Type` SHORT "
532             "PRIMARY KEY `Signature_`)" );
533     ok(r == ERROR_SUCCESS, "Failed to create RegLocator table: %u\n", r);
534     return r;
535 }
536 
537 static UINT create_signature_table( MSIHANDLE hdb )
538 {
539     UINT r = run_query( hdb,
540             "CREATE TABLE `Signature` ("
541             "`Signature` CHAR(72) NOT NULL, "
542             "`FileName` CHAR(255) NOT NULL, "
543             "`MinVersion` CHAR(20), "
544             "`MaxVersion` CHAR(20), "
545             "`MinSize` LONG, "
546             "`MaxSize` LONG, "
547             "`MinDate` LONG, "
548             "`MaxDate` LONG, "
549             "`Languages` CHAR(255) "
550             "PRIMARY KEY `Signature`)" );
551     ok(r == ERROR_SUCCESS, "Failed to create Signature table: %u\n", r);
552     return r;
553 }
554 
555 static UINT create_launchcondition_table( MSIHANDLE hdb )
556 {
557     UINT r = run_query( hdb,
558             "CREATE TABLE `LaunchCondition` ("
559             "`Condition` CHAR(255) NOT NULL, "
560             "`Description` CHAR(255) NOT NULL "
561             "PRIMARY KEY `Condition`)" );
562     ok(r == ERROR_SUCCESS, "Failed to create LaunchCondition table: %u\n", r);
563     return r;
564 }
565 
566 static UINT create_property_table( MSIHANDLE hdb )
567 {
568     UINT r = run_query( hdb,
569             "CREATE TABLE `Property` ("
570             "`Property` CHAR(72) NOT NULL, "
571             "`Value` CHAR(0) "
572             "PRIMARY KEY `Property`)" );
573     ok(r == ERROR_SUCCESS, "Failed to create Property table: %u\n", r);
574     return r;
575 }
576 
577 static UINT create_install_execute_sequence_table( MSIHANDLE hdb )
578 {
579     UINT r = run_query( hdb,
580             "CREATE TABLE `InstallExecuteSequence` ("
581             "`Action` CHAR(72) NOT NULL, "
582             "`Condition` CHAR(255), "
583             "`Sequence` SHORT "
584             "PRIMARY KEY `Action`)" );
585     ok(r == ERROR_SUCCESS, "Failed to create InstallExecuteSequence table: %u\n", r);
586     return r;
587 }
588 
589 static UINT create_install_ui_sequence_table( MSIHANDLE hdb )
590 {
591     UINT r = run_query( hdb,
592             "CREATE TABLE `InstallUISequence` ("
593             "`Action` CHAR(72) NOT NULL, "
594             "`Condition` CHAR(255), "
595             "`Sequence` SHORT "
596             "PRIMARY KEY `Action`)" );
597     ok(r == ERROR_SUCCESS, "Failed to create InstallUISequence table: %u\n", r);
598     return r;
599 }
600 
601 static UINT create_media_table( MSIHANDLE hdb )
602 {
603     UINT r = run_query( hdb,
604             "CREATE TABLE `Media` ("
605             "`DiskId` SHORT NOT NULL, "
606             "`LastSequence` SHORT NOT NULL, "
607             "`DiskPrompt` CHAR(64), "
608             "`Cabinet` CHAR(255), "
609             "`VolumeLabel` CHAR(32), "
610             "`Source` CHAR(72) "
611             "PRIMARY KEY `DiskId`)" );
612     ok(r == ERROR_SUCCESS, "Failed to create Media table: %u\n", r);
613     return r;
614 }
615 
616 static UINT create_ccpsearch_table( MSIHANDLE hdb )
617 {
618     UINT r = run_query( hdb,
619             "CREATE TABLE `CCPSearch` ("
620             "`Signature_` CHAR(72) NOT NULL "
621             "PRIMARY KEY `Signature_`)" );
622     ok(r == ERROR_SUCCESS, "Failed to create CCPSearch table: %u\n", r);
623     return r;
624 }
625 
626 static UINT create_drlocator_table( MSIHANDLE hdb )
627 {
628     UINT r = run_query( hdb,
629             "CREATE TABLE `DrLocator` ("
630             "`Signature_` CHAR(72) NOT NULL, "
631             "`Parent` CHAR(72), "
632             "`Path` CHAR(255), "
633             "`Depth` SHORT "
634             "PRIMARY KEY `Signature_`, `Parent`, `Path`)" );
635     ok(r == ERROR_SUCCESS, "Failed to create DrLocator table: %u\n", r);
636     return r;
637 }
638 
639 static UINT create_complocator_table( MSIHANDLE hdb )
640 {
641     UINT r = run_query( hdb,
642             "CREATE TABLE `CompLocator` ("
643             "`Signature_` CHAR(72) NOT NULL, "
644             "`ComponentId` CHAR(38) NOT NULL, "
645             "`Type` SHORT "
646             "PRIMARY KEY `Signature_`)" );
647     ok(r == ERROR_SUCCESS, "Failed to create CompLocator table: %u\n", r);
648     return r;
649 }
650 
651 static UINT create_inilocator_table( MSIHANDLE hdb )
652 {
653     UINT r = run_query( hdb,
654             "CREATE TABLE `IniLocator` ("
655             "`Signature_` CHAR(72) NOT NULL, "
656             "`FileName` CHAR(255) NOT NULL, "
657             "`Section` CHAR(96)NOT NULL, "
658             "`Key` CHAR(128)NOT NULL, "
659             "`Field` SHORT, "
660             "`Type` SHORT "
661             "PRIMARY KEY `Signature_`)" );
662     ok(r == ERROR_SUCCESS, "Failed to create IniLocator table: %u\n", r);
663     return r;
664 }
665 
666 static UINT create_custom_action_table( MSIHANDLE hdb )
667 {
668     UINT r = run_query( hdb,
669             "CREATE TABLE `CustomAction` ("
670             "`Action` CHAR(72) NOT NULL, "
671             "`Type` SHORT NOT NULL, "
672             "`Source` CHAR(75), "
673             "`Target` CHAR(255) "
674             "PRIMARY KEY `Action`)" );
675     ok(r == ERROR_SUCCESS, "Failed to create CustomAction table: %u\n", r);
676     return r;
677 }
678 
679 static UINT create_dialog_table( MSIHANDLE hdb )
680 {
681     UINT r = run_query(hdb,
682             "CREATE TABLE `Dialog` ("
683             "`Dialog` CHAR(72) NOT NULL, "
684             "`HCentering` SHORT NOT NULL, "
685             "`VCentering` SHORT NOT NULL, "
686             "`Width` SHORT NOT NULL, "
687             "`Height` SHORT NOT NULL, "
688             "`Attributes` LONG, "
689             "`Title` CHAR(128) LOCALIZABLE, "
690             "`Control_First` CHAR(50) NOT NULL, "
691             "`Control_Default` CHAR(50), "
692             "`Control_Cancel` CHAR(50) "
693             "PRIMARY KEY `Dialog`)");
694     ok(r == ERROR_SUCCESS, "Failed to create Dialog table: %u\n", r);
695     return r;
696 }
697 
698 static UINT create_control_table( MSIHANDLE hdb )
699 {
700     UINT r = run_query(hdb,
701             "CREATE TABLE `Control` ("
702             "`Dialog_` CHAR(72) NOT NULL, "
703             "`Control` CHAR(50) NOT NULL, "
704             "`Type` CHAR(20) NOT NULL, "
705             "`X` SHORT NOT NULL, "
706             "`Y` SHORT NOT NULL, "
707             "`Width` SHORT NOT NULL, "
708             "`Height` SHORT NOT NULL, "
709             "`Attributes` LONG, "
710             "`Property` CHAR(50), "
711             "`Text` CHAR(0) LOCALIZABLE, "
712             "`Control_Next` CHAR(50), "
713             "`Help` CHAR(255) LOCALIZABLE "
714             "PRIMARY KEY `Dialog_`, `Control`)");
715     ok(r == ERROR_SUCCESS, "Failed to create Control table: %u\n", r);
716     return r;
717 }
718 
719 static UINT create_controlevent_table( MSIHANDLE hdb )
720 {
721     UINT r = run_query(hdb,
722             "CREATE TABLE `ControlEvent` ("
723             "`Dialog_` CHAR(72) NOT NULL, "
724             "`Control_` CHAR(50) NOT NULL, "
725             "`Event` CHAR(50) NOT NULL, "
726             "`Argument` CHAR(255) NOT NULL, "
727             "`Condition` CHAR(255), "
728             "`Ordering` SHORT "
729             "PRIMARY KEY `Dialog_`, `Control_`, `Event`, `Argument`, `Condition`)");
730     ok(r == ERROR_SUCCESS, "Failed to create ControlEvent table: %u\n", r);
731     return r;
732 }
733 
734 static UINT create_actiontext_table( MSIHANDLE hdb )
735 {
736     UINT r = run_query(hdb,
737             "CREATE TABLE `ActionText` ("
738             "`Action` CHAR(72) NOT NULL, "
739             "`Description` CHAR(64) LOCALIZABLE, "
740             "`Template` CHAR(128) LOCALIZABLE "
741             "PRIMARY KEY `Action`)");
742     ok(r == ERROR_SUCCESS, "Failed to create ActionText table: %u\n", r);
743     return r;
744 }
745 
746 static inline UINT add_entry(const char *file, int line, const char *type, MSIHANDLE hdb, const char *values, const char *insert)
747 {
748     char *query;
749     UINT sz, r;
750 
751     sz = strlen(values) + strlen(insert) + 1;
752     query = HeapAlloc(GetProcessHeap(), 0, sz);
753     sprintf(query, insert, values);
754     r = run_query(hdb, query);
755     HeapFree(GetProcessHeap(), 0, query);
756     ok_(file, line)(r == ERROR_SUCCESS, "failed to insert into %s table: %u\n", type, r);
757     return r;
758 }
759 
760 #define add_component_entry(hdb, values) add_entry(__FILE__, __LINE__, "Component", hdb, values, \
761                "INSERT INTO `Component`  " \
762                "(`Component`, `ComponentId`, `Directory_`, " \
763                "`Attributes`, `Condition`, `KeyPath`) VALUES( %s )")
764 
765 #define add_directory_entry(hdb, values) add_entry(__FILE__, __LINE__, "Directory", hdb, values, \
766                "INSERT INTO `Directory` " \
767                "(`Directory`,`Directory_Parent`,`DefaultDir`) VALUES( %s )")
768 
769 #define add_feature_entry(hdb, values) add_entry(__FILE__, __LINE__, "Feature", hdb, values, \
770                "INSERT INTO `Feature` " \
771                "(`Feature`, `Feature_Parent`, `Title`, `Description`, " \
772                "`Display`, `Level`, `Directory_`, `Attributes`) VALUES( %s )")
773 
774 #define add_feature_components_entry(hdb, values) add_entry(__FILE__, __LINE__, "FeatureComponents", hdb, values, \
775                "INSERT INTO `FeatureComponents` " \
776                "(`Feature_`, `Component_`) VALUES( %s )")
777 
778 #define add_file_entry(hdb, values) add_entry(__FILE__, __LINE__, "File", hdb, values, \
779                "INSERT INTO `File` " \
780                "(`File`, `Component_`, `FileName`, `FileSize`, " \
781                "`Version`, `Language`, `Attributes`, `Sequence`) VALUES( %s )")
782 
783 #define add_appsearch_entry(hdb, values) add_entry(__FILE__, __LINE__, "AppSearch", hdb, values, \
784                "INSERT INTO `AppSearch` " \
785                "(`Property`, `Signature_`) VALUES( %s )")
786 
787 #define add_signature_entry(hdb, values) add_entry(__FILE__, __LINE__, "Signature", hdb, values, \
788                "INSERT INTO `Signature` " \
789                "(`Signature`, `FileName`, `MinVersion`, `MaxVersion`," \
790                " `MinSize`, `MaxSize`, `MinDate`, `MaxDate`, `Languages`) " \
791                "VALUES( %s )")
792 
793 #define add_launchcondition_entry(hdb, values) add_entry(__FILE__, __LINE__, "LaunchCondition", hdb, values, \
794                "INSERT INTO `LaunchCondition` " \
795                "(`Condition`, `Description`) VALUES( %s )")
796 
797 #define add_property_entry(hdb, values) add_entry(__FILE__, __LINE__, "Property", hdb, values, \
798                "INSERT INTO `Property` (`Property`, `Value`) VALUES( %s )")
799 
800 #define add_install_execute_sequence_entry(hdb, values) add_entry(__FILE__, __LINE__, "InstallExecuteSequence", hdb, values, \
801                "INSERT INTO `InstallExecuteSequence` " \
802                "(`Action`, `Condition`, `Sequence`) VALUES( %s )")
803 
804 #define add_install_ui_sequence_entry(hdb, values) add_entry(__FILE__, __LINE__, "InstallUISequence", hdb, values, \
805                "INSERT INTO `InstallUISequence` " \
806                "(`Action`, `Condition`, `Sequence`) VALUES( %s )")
807 
808 #define add_media_entry(hdb, values) add_entry(__FILE__, __LINE__, "Media", hdb, values, \
809                "INSERT INTO `Media` " \
810                "(`DiskId`, `LastSequence`, `DiskPrompt`, " \
811                "`Cabinet`, `VolumeLabel`, `Source`) VALUES( %s )")
812 
813 #define add_ccpsearch_entry(hdb, values) add_entry(__FILE__, __LINE__, "CCPSearch", hdb, values, \
814                "INSERT INTO `CCPSearch` (`Signature_`) VALUES( %s )")
815 
816 #define add_drlocator_entry(hdb, values) add_entry(__FILE__, __LINE__, "DrLocator", hdb, values, \
817                "INSERT INTO `DrLocator` " \
818                "(`Signature_`, `Parent`, `Path`, `Depth`) VALUES( %s )")
819 
820 #define add_complocator_entry(hdb, values) add_entry(__FILE__, __LINE__, "CompLocator", hdb, values, \
821                "INSERT INTO `CompLocator` " \
822                "(`Signature_`, `ComponentId`, `Type`) VALUES( %s )")
823 
824 #define add_inilocator_entry(hdb, values) add_entry(__FILE__, __LINE__, "IniLocator", hdb, values, \
825                "INSERT INTO `IniLocator` " \
826                "(`Signature_`, `FileName`, `Section`, `Key`, `Field`, `Type`) " \
827                "VALUES( %s )")
828 
829 #define add_custom_action_entry(hdb, values) add_entry(__FILE__, __LINE__, "CustomAction", hdb, values, \
830                "INSERT INTO `CustomAction`  " \
831                "(`Action`, `Type`, `Source`, `Target`) VALUES( %s )")
832 
833 #define add_dialog_entry(hdb, values) add_entry(__FILE__, __LINE__, "Dialog", hdb, values, \
834                "INSERT INTO `Dialog` " \
835                "(`Dialog`, `HCentering`, `VCentering`, `Width`, `Height`, `Attributes`, `Control_First`) VALUES ( %s )")
836 
837 #define add_control_entry(hdb, values) add_entry(__FILE__, __LINE__, "Control", hdb, values, \
838                "INSERT INTO `Control` " \
839                "(`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, `Attributes`, `Text`) VALUES( %s )");
840 
841 #define add_controlevent_entry(hdb, values) add_entry(__FILE__, __LINE__, "ControlEvent", hdb, values, \
842                "INSERT INTO `ControlEvent` " \
843                "(`Dialog_`, `Control_`, `Event`, `Argument`, `Condition`, `Ordering`) VALUES( %s )");
844 
845 #define add_actiontext_entry(hdb, values) add_entry(__FILE__, __LINE__, "ActionText", hdb, values, \
846                "INSERT INTO `ActionText` " \
847                "(`Action`, `Description`, `Template`) VALUES( %s )");
848 
849 static UINT add_reglocator_entry( MSIHANDLE hdb, const char *sig, UINT root, const char *path,
850                                   const char *name, UINT type )
851 {
852     const char insert[] =
853         "INSERT INTO `RegLocator` (`Signature_`, `Root`, `Key`, `Name`, `Type`) "
854         "VALUES( '%s', %u, '%s', '%s', %u )";
855     char *query;
856     UINT sz, r;
857 
858     sz = strlen( sig ) + 10 + strlen( path ) + strlen( name ) + 10 + sizeof( insert );
859     query = HeapAlloc( GetProcessHeap(), 0, sz );
860     sprintf( query, insert, sig, root, path, name, type );
861     r = run_query( hdb, query );
862     HeapFree( GetProcessHeap(), 0, query );
863     ok(r == ERROR_SUCCESS, "failed to insert into reglocator table: %u\n", r); \
864     return r;
865 }
866 
867 static UINT set_summary_info(MSIHANDLE hdb)
868 {
869     UINT res;
870     MSIHANDLE suminfo;
871 
872     /* build summary info */
873     res = MsiGetSummaryInformationA(hdb, NULL, 7, &suminfo);
874     ok( res == ERROR_SUCCESS , "Failed to open summaryinfo\n" );
875 
876     res = MsiSummaryInfoSetPropertyA(suminfo,2, VT_LPSTR, 0,NULL,
877                         "Installation Database");
878     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
879 
880     res = MsiSummaryInfoSetPropertyA(suminfo,3, VT_LPSTR, 0,NULL,
881                         "Installation Database");
882     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
883 
884     res = MsiSummaryInfoSetPropertyA(suminfo,4, VT_LPSTR, 0,NULL,
885                         "Wine Hackers");
886     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
887 
888     res = MsiSummaryInfoSetPropertyA(suminfo,7, VT_LPSTR, 0,NULL,
889                     ";1033");
890     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
891 
892     res = MsiSummaryInfoSetPropertyA(suminfo,9, VT_LPSTR, 0,NULL,
893                     "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}");
894     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
895 
896     res = MsiSummaryInfoSetPropertyA(suminfo, 14, VT_I4, 100, NULL, NULL);
897     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
898 
899     res = MsiSummaryInfoSetPropertyA(suminfo, 15, VT_I4, 0, NULL, NULL);
900     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
901 
902     res = MsiSummaryInfoPersist(suminfo);
903     ok( res == ERROR_SUCCESS , "Failed to make summary info persist\n" );
904 
905     res = MsiCloseHandle( suminfo);
906     ok( res == ERROR_SUCCESS , "Failed to close suminfo\n" );
907 
908     return res;
909 }
910 
911 
912 static MSIHANDLE create_package_db(void)
913 {
914     MSIHANDLE hdb = 0;
915     UINT res;
916 
917     DeleteFileA(msifile);
918 
919     /* create an empty database */
920     res = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb );
921     ok( res == ERROR_SUCCESS , "Failed to create database %u\n", res );
922     if( res != ERROR_SUCCESS )
923         return hdb;
924 
925     res = MsiDatabaseCommit( hdb );
926     ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
927 
928     res = set_summary_info(hdb);
929     ok( res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", res);
930 
931     res = run_query( hdb,
932             "CREATE TABLE `Directory` ( "
933             "`Directory` CHAR(255) NOT NULL, "
934             "`Directory_Parent` CHAR(255), "
935             "`DefaultDir` CHAR(255) NOT NULL "
936             "PRIMARY KEY `Directory`)" );
937     ok( res == ERROR_SUCCESS , "Failed to create directory table\n" );
938 
939     return hdb;
940 }
941 
942 static UINT package_from_db(MSIHANDLE hdb, MSIHANDLE *handle)
943 {
944     UINT res;
945     CHAR szPackage[12];
946     MSIHANDLE hPackage;
947 
948     sprintf(szPackage, "#%u", hdb);
949     res = MsiOpenPackageA(szPackage, &hPackage);
950     if (res != ERROR_SUCCESS)
951     {
952         MsiCloseHandle(hdb);
953         return res;
954     }
955 
956     res = MsiCloseHandle(hdb);
957     if (res != ERROR_SUCCESS)
958     {
959         MsiCloseHandle(hPackage);
960         return res;
961     }
962 
963     *handle = hPackage;
964     return ERROR_SUCCESS;
965 }
966 
967 static void create_file_data(LPCSTR name, LPCSTR data)
968 {
969     HANDLE file;
970     DWORD written;
971 
972     file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
973     ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
974     if (file == INVALID_HANDLE_VALUE)
975         return;
976 
977     WriteFile(file, data, strlen(data), &written, NULL);
978     WriteFile(file, "\n", strlen("\n"), &written, NULL);
979 
980     CloseHandle(file);
981 }
982 
983 static void create_test_file(const CHAR *name)
984 {
985     create_file_data(name, name);
986 }
987 
988 typedef struct _tagVS_VERSIONINFO
989 {
990     WORD wLength;
991     WORD wValueLength;
992     WORD wType;
993     WCHAR szKey[1];
994     WORD wPadding1[1];
995     VS_FIXEDFILEINFO Value;
996     WORD wPadding2[1];
997     WORD wChildren[1];
998 } VS_VERSIONINFO;
999 
1000 #define roundoffs(a, b, r) (((BYTE *)(b) - (BYTE *)(a) + ((r) - 1)) & ~((r) - 1))
1001 #define roundpos(a, b, r) (((BYTE *)(a)) + roundoffs(a, b, r))
1002 
1003 static BOOL create_file_with_version(const CHAR *name, LONG ms, LONG ls)
1004 {
1005     VS_VERSIONINFO *pVerInfo;
1006     VS_FIXEDFILEINFO *pFixedInfo;
1007     LPBYTE buffer, ofs;
1008     CHAR path[MAX_PATH];
1009     DWORD handle, size;
1010     HANDLE resource;
1011     BOOL ret = FALSE;
1012 
1013     GetSystemDirectoryA(path, MAX_PATH);
1014     /* Some dlls can't be updated on Vista/W2K8 */
1015     lstrcatA(path, "\\version.dll");
1016 
1017     CopyFileA(path, name, FALSE);
1018 
1019     size = GetFileVersionInfoSizeA(path, &handle);
1020     buffer = HeapAlloc(GetProcessHeap(), 0, size);
1021 
1022     GetFileVersionInfoA(path, 0, size, buffer);
1023 
1024     pVerInfo = (VS_VERSIONINFO *)buffer;
1025     ofs = (BYTE *)&pVerInfo->szKey[lstrlenW(pVerInfo->szKey) + 1];
1026     pFixedInfo = (VS_FIXEDFILEINFO *)roundpos(pVerInfo, ofs, 4);
1027 
1028     pFixedInfo->dwFileVersionMS = ms;
1029     pFixedInfo->dwFileVersionLS = ls;
1030     pFixedInfo->dwProductVersionMS = ms;
1031     pFixedInfo->dwProductVersionLS = ls;
1032 
1033     resource = BeginUpdateResourceA(name, FALSE);
1034     if (!resource)
1035         goto done;
1036 
1037     if (!UpdateResourceA(resource, (LPCSTR)RT_VERSION, (LPCSTR)MAKEINTRESOURCE(VS_VERSION_INFO),
1038                          MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), buffer, size))
1039         goto done;
1040 
1041     if (!EndUpdateResourceA(resource, FALSE))
1042         goto done;
1043 
1044     ret = TRUE;
1045 
1046 done:
1047     HeapFree(GetProcessHeap(), 0, buffer);
1048     return ret;
1049 }
1050 
1051 static BOOL notify_system_change(DWORD event_type, STATEMGRSTATUS *status)
1052 {
1053     RESTOREPOINTINFOA spec;
1054 
1055     spec.dwEventType = event_type;
1056     spec.dwRestorePtType = APPLICATION_INSTALL;
1057     spec.llSequenceNumber = status->llSequenceNumber;
1058     lstrcpyA(spec.szDescription, "msitest restore point");
1059 
1060     return pSRSetRestorePointA(&spec, status);
1061 }
1062 
1063 static void remove_restore_point(DWORD seq_number)
1064 {
1065     DWORD res;
1066 
1067     res = pSRRemoveRestorePoint(seq_number);
1068     if (res != ERROR_SUCCESS)
1069         trace("Failed to remove the restore point : %08x\n", res);
1070 }
1071 
1072 static BOOL is_root(const char *path)
1073 {
1074     return (isalpha(path[0]) && path[1] == ':' && path[2] == '\\' && !path[3]);
1075 }
1076 
1077 static void test_createpackage(void)
1078 {
1079     MSIHANDLE hPackage = 0;
1080     UINT res;
1081 
1082     res = package_from_db(create_package_db(), &hPackage);
1083     if (res == ERROR_INSTALL_PACKAGE_REJECTED)
1084     {
1085         skip("Not enough rights to perform tests\n");
1086         DeleteFileA(msifile);
1087         return;
1088     }
1089     ok( res == ERROR_SUCCESS, " Failed to create package %u\n", res );
1090 
1091     res = MsiCloseHandle( hPackage);
1092     ok( res == ERROR_SUCCESS , "Failed to close package\n" );
1093     DeleteFileA(msifile);
1094 }
1095 
1096 static void test_doaction( void )
1097 {
1098     MSIHANDLE hpkg;
1099     UINT r;
1100 
1101     r = MsiDoActionA( -1, NULL );
1102     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1103 
1104     r = package_from_db(create_package_db(), &hpkg);
1105     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1106     {
1107         skip("Not enough rights to perform tests\n");
1108         DeleteFileA(msifile);
1109         return;
1110     }
1111     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1112 
1113     r = MsiDoActionA(hpkg, NULL);
1114     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1115 
1116     r = MsiDoActionA(0, "boo");
1117     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1118 
1119     r = MsiDoActionA(hpkg, "boo");
1120     ok( r == ERROR_FUNCTION_NOT_CALLED, "wrong return val\n");
1121 
1122     MsiCloseHandle( hpkg );
1123     DeleteFileA(msifile);
1124 }
1125 
1126 static void test_gettargetpath_bad(void)
1127 {
1128     static const WCHAR boo[] = {'b','o','o',0};
1129     static const WCHAR empty[] = {0};
1130     char buffer[0x80];
1131     WCHAR bufferW[0x80];
1132     MSIHANDLE hpkg;
1133     DWORD sz;
1134     UINT r;
1135 
1136     r = package_from_db(create_package_db(), &hpkg);
1137     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1138     {
1139         skip("Not enough rights to perform tests\n");
1140         DeleteFileA(msifile);
1141         return;
1142     }
1143     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1144 
1145     r = MsiGetTargetPathA( 0, NULL, NULL, NULL );
1146     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1147 
1148     r = MsiGetTargetPathA( 0, NULL, NULL, &sz );
1149     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1150 
1151     r = MsiGetTargetPathA( 0, "boo", NULL, NULL );
1152     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1153 
1154     r = MsiGetTargetPathA( 0, "boo", NULL, NULL );
1155     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1156 
1157     r = MsiGetTargetPathA( hpkg, "boo", NULL, NULL );
1158     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1159 
1160     r = MsiGetTargetPathA( hpkg, "boo", buffer, NULL );
1161     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1162 
1163     sz = 0;
1164     r = MsiGetTargetPathA( hpkg, "", buffer, &sz );
1165     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1166 
1167     r = MsiGetTargetPathW( 0, NULL, NULL, NULL );
1168     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1169 
1170     r = MsiGetTargetPathW( 0, NULL, NULL, &sz );
1171     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1172 
1173     r = MsiGetTargetPathW( 0, boo, NULL, NULL );
1174     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1175 
1176     r = MsiGetTargetPathW( 0, boo, NULL, NULL );
1177     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1178 
1179     r = MsiGetTargetPathW( hpkg, boo, NULL, NULL );
1180     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1181 
1182     r = MsiGetTargetPathW( hpkg, boo, bufferW, NULL );
1183     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1184 
1185     sz = 0;
1186     r = MsiGetTargetPathW( hpkg, empty, bufferW, &sz );
1187     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1188 
1189     MsiCloseHandle( hpkg );
1190     DeleteFileA(msifile);
1191 }
1192 
1193 static void query_file_path(MSIHANDLE hpkg, LPCSTR file, LPSTR buff)
1194 {
1195     UINT r;
1196     DWORD size;
1197     MSIHANDLE rec;
1198 
1199     rec = MsiCreateRecord( 1 );
1200     ok(rec, "MsiCreate record failed\n");
1201 
1202     r = MsiRecordSetStringA( rec, 0, file );
1203     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
1204 
1205     size = MAX_PATH;
1206     r = MsiFormatRecordA( hpkg, rec, buff, &size );
1207     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
1208 
1209     MsiCloseHandle( rec );
1210 }
1211 
1212 static void test_settargetpath(void)
1213 {
1214     char tempdir[MAX_PATH+8], buffer[MAX_PATH], file[MAX_PATH];
1215     DWORD sz;
1216     MSIHANDLE hpkg;
1217     UINT r;
1218     MSIHANDLE hdb;
1219 
1220     hdb = create_package_db();
1221     ok ( hdb, "failed to create package database\n" );
1222 
1223     add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'" );
1224 
1225     create_component_table( hdb );
1226     add_component_entry( hdb, "'RootComp', '{83e2694d-0864-4124-9323-6d37630912a1}', 'TARGETDIR', 8, '', 'RootFile'" );
1227     add_component_entry( hdb, "'TestComp', '{A3FB59C8-C293-4F7E-B8C5-F0E1D8EEE4E5}', 'TestDir', 0, '', 'TestFile'" );
1228 
1229     create_feature_table( hdb );
1230     add_feature_entry( hdb, "'TestFeature', '', '', '', 0, 1, '', 0" );
1231 
1232     create_feature_components_table( hdb );
1233     add_feature_components_entry( hdb, "'TestFeature', 'RootComp'" );
1234     add_feature_components_entry( hdb, "'TestFeature', 'TestComp'" );
1235 
1236     add_directory_entry( hdb, "'TestParent', 'TARGETDIR', 'TestParent'" );
1237     add_directory_entry( hdb, "'TestDir', 'TestParent', 'TestDir'" );
1238 
1239     create_file_table( hdb );
1240     add_file_entry( hdb, "'RootFile', 'RootComp', 'rootfile.txt', 0, '', '1033', 8192, 1" );
1241     add_file_entry( hdb, "'TestFile', 'TestComp', 'testfile.txt', 0, '', '1033', 8192, 1" );
1242 
1243     r = package_from_db( hdb, &hpkg );
1244     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1245     {
1246         skip("Not enough rights to perform tests\n");
1247         DeleteFileA(msifile);
1248         return;
1249     }
1250     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1251 
1252     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1253 
1254     r = MsiDoActionA( hpkg, "CostInitialize");
1255     ok( r == ERROR_SUCCESS, "cost init failed\n");
1256 
1257     r = MsiDoActionA( hpkg, "FileCost");
1258     ok( r == ERROR_SUCCESS, "file cost failed\n");
1259 
1260     r = MsiDoActionA( hpkg, "CostFinalize");
1261     ok( r == ERROR_SUCCESS, "cost finalize failed\n");
1262 
1263     buffer[0] = 0;
1264     sz = sizeof(buffer);
1265     r = MsiGetPropertyA( hpkg, "OutOfNoRbDiskSpace", buffer, &sz );
1266     ok( r == ERROR_SUCCESS, "MsiGetProperty returned %u\n", r );
1267     trace( "OutOfNoRbDiskSpace = \"%s\"\n", buffer );
1268 
1269     r = MsiSetTargetPathA( 0, NULL, NULL );
1270     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1271 
1272     r = MsiSetTargetPathA( 0, "boo", "C:\\bogusx" );
1273     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1274 
1275     r = MsiSetTargetPathA( hpkg, "boo", NULL );
1276     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1277 
1278     r = MsiSetTargetPathA( hpkg, "boo", "c:\\bogusx" );
1279     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1280 
1281     sz = sizeof tempdir - 1;
1282     r = MsiGetTargetPathA( hpkg, "TARGETDIR", tempdir, &sz );
1283     sprintf( file, "%srootfile.txt", tempdir );
1284     buffer[0] = 0;
1285     query_file_path( hpkg, "[#RootFile]", buffer );
1286     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1287     ok( !lstrcmpA(buffer, file), "Expected %s, got %s\n", file, buffer );
1288 
1289     GetTempFileNameA( tempdir, "_wt", 0, buffer );
1290     sprintf( tempdir, "%s\\subdir", buffer );
1291 
1292     r = MsiSetTargetPathA( hpkg, "TARGETDIR", buffer );
1293     ok( r == ERROR_SUCCESS || r == ERROR_DIRECTORY,
1294         "MsiSetTargetPath on file returned %d\n", r );
1295 
1296     r = MsiSetTargetPathA( hpkg, "TARGETDIR", tempdir );
1297     ok( r == ERROR_SUCCESS || r == ERROR_DIRECTORY,
1298         "MsiSetTargetPath on 'subdir' of file returned %d\n", r );
1299 
1300     DeleteFileA( buffer );
1301 
1302     r = MsiSetTargetPathA( hpkg, "TARGETDIR", buffer );
1303     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1304 
1305     r = GetFileAttributesA( buffer );
1306     ok ( r == INVALID_FILE_ATTRIBUTES, "file/directory exists after MsiSetTargetPath. Attributes: %08X\n", r );
1307 
1308     r = MsiSetTargetPathA( hpkg, "TARGETDIR", tempdir );
1309     ok( r == ERROR_SUCCESS, "MsiSetTargetPath on subsubdir returned %d\n", r );
1310 
1311     buffer[0] = 0;
1312     sz = sizeof buffer - 1;
1313     lstrcatA( tempdir, "\\" );
1314     r = MsiGetTargetPathA( hpkg, "TARGETDIR", buffer, &sz );
1315     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1316     ok( !lstrcmpA(buffer, tempdir), "Expected %s, got %s\n", tempdir, buffer);
1317 
1318     sprintf( file, "%srootfile.txt", tempdir );
1319     query_file_path( hpkg, "[#RootFile]", buffer );
1320     ok( !lstrcmpA(buffer, file), "Expected %s, got %s\n", file, buffer);
1321 
1322     buffer[0] = 0;
1323     sz = sizeof(buffer);
1324     r = MsiGetPropertyA( hpkg, "TestParent", buffer, &sz );
1325     ok( r == ERROR_SUCCESS, "MsiGetProperty returned %u\n", r );
1326     lstrcatA( tempdir, "TestParent\\" );
1327     ok( !lstrcmpiA(buffer, tempdir), "Expected \"%s\", got \"%s\"\n", tempdir, buffer );
1328 
1329     r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\one\\two" );
1330     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1331 
1332     buffer[0] = 0;
1333     sz = sizeof(buffer);
1334     r = MsiGetPropertyA( hpkg, "TestParent", buffer, &sz );
1335     ok( r == ERROR_SUCCESS, "MsiGetProperty returned %u\n", r );
1336     ok( lstrcmpiA(buffer, "C:\\one\\two\\TestDir\\"),
1337         "Expected \"C:\\one\\two\\TestDir\\\", got \"%s\"\n", buffer );
1338 
1339     buffer[0] = 0;
1340     query_file_path( hpkg, "[#TestFile]", buffer );
1341     ok( !lstrcmpiA(buffer, "C:\\one\\two\\TestDir\\testfile.txt"),
1342         "Expected C:\\one\\two\\TestDir\\testfile.txt, got %s\n", buffer );
1343 
1344     buffer[0] = 0;
1345     sz = sizeof buffer - 1;
1346     r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1347     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1348     ok( !lstrcmpiA(buffer, "C:\\one\\two\\"), "Expected C:\\one\\two\\, got %s\n", buffer);
1349 
1350     r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\one\\two\\three" );
1351     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1352 
1353     buffer[0] = 0;
1354     sz = sizeof buffer - 1;
1355     r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1356     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1357     ok( !lstrcmpiA(buffer, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", buffer);
1358 
1359     r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\\\one\\\\two  " );
1360     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1361 
1362     buffer[0] = 0;
1363     sz = sizeof buffer - 1;
1364     r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1365     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1366     ok( !lstrcmpiA(buffer, "C:\\one\\two\\"), "Expected \"C:\\one\\two\\\", got %s\n", buffer);
1367 
1368     r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\\\ Program Files \\\\ " );
1369     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1370 
1371     buffer[0] = 0;
1372     sz = sizeof buffer - 1;
1373     r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1374     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1375     ok( !lstrcmpiA(buffer, "C:\\Program Files\\"), "Expected \"C:\\Program Files\\\", got %s\n", buffer);
1376 
1377     MsiCloseHandle( hpkg );
1378 }
1379 
1380 static void test_condition(void)
1381 {
1382     static const WCHAR cond1[] = {'\"','a',0x30a,'\"','<','\"',0xe5,'\"',0};
1383     static const WCHAR cond2[] = {'\"','a',0x30a,'\"','>','\"',0xe5,'\"',0};
1384     static const WCHAR cond3[] = {'\"','a',0x30a,'\"','<','>','\"',0xe5,'\"',0};
1385     static const WCHAR cond4[] = {'\"','a',0x30a,'\"','=','\"',0xe5,'\"',0};
1386     MSICONDITION r;
1387     MSIHANDLE hpkg;
1388 
1389     r = package_from_db(create_package_db(), &hpkg);
1390     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1391     {
1392         skip("Not enough rights to perform tests\n");
1393         DeleteFileA(msifile);
1394         return;
1395     }
1396     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1397 
1398     r = MsiEvaluateConditionA(0, NULL);
1399     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1400 
1401     r = MsiEvaluateConditionA(hpkg, NULL);
1402     ok( r == MSICONDITION_NONE, "wrong return val\n");
1403 
1404     r = MsiEvaluateConditionA(hpkg, "");
1405     ok( r == MSICONDITION_NONE, "wrong return val\n");
1406 
1407     r = MsiEvaluateConditionA(hpkg, "1");
1408     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1409 
1410     r = MsiEvaluateConditionA(hpkg, "0");
1411     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1412 
1413     r = MsiEvaluateConditionA(hpkg, "-1");
1414     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1415 
1416     r = MsiEvaluateConditionA(hpkg, "0 = 0");
1417     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1418 
1419     r = MsiEvaluateConditionA(hpkg, "0 <> 0");
1420     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1421 
1422     r = MsiEvaluateConditionA(hpkg, "0 = 1");
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, "1 > 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, "0 >= 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, "1 >= 1");
1444     ok( r == MSICONDITION_TRUE, "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, "0 < 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, "1 < 1");
1456     ok( r == MSICONDITION_FALSE, "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, "0 <= 1");
1462     ok( r == MSICONDITION_TRUE, "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, "1 <= 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, "0 >=");
1474     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1475 
1476     r = MsiEvaluateConditionA(hpkg, " ");
1477     ok( r == MSICONDITION_NONE, "wrong return val\n");
1478 
1479     r = MsiEvaluateConditionA(hpkg, "LicView <> \"1\"");
1480     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1481 
1482     r = MsiEvaluateConditionA(hpkg, "LicView <> \"0\"");
1483     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1484 
1485     r = MsiEvaluateConditionA(hpkg, "LicView <> LicView");
1486     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1487 
1488     r = MsiEvaluateConditionA(hpkg, "not 0");
1489     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1490 
1491     r = MsiEvaluateConditionA(hpkg, "not LicView");
1492     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1493 
1494     r = MsiEvaluateConditionA(hpkg, "\"Testing\" ~<< \"Testing\"");
1495     ok (r == MSICONDITION_TRUE, "wrong return val\n");
1496 
1497     r = MsiEvaluateConditionA(hpkg, "LicView ~<< \"Testing\"");
1498     ok (r == MSICONDITION_FALSE, "wrong return val\n");
1499 
1500     r = MsiEvaluateConditionA(hpkg, "Not LicView ~<< \"Testing\"");
1501     ok (r == MSICONDITION_TRUE, "wrong return val\n");
1502 
1503     r = MsiEvaluateConditionA(hpkg, "not \"A\"");
1504     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1505 
1506     r = MsiEvaluateConditionA(hpkg, "~not \"A\"");
1507     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1508 
1509     r = MsiEvaluateConditionA(hpkg, "\"0\"");
1510     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1511 
1512     r = MsiEvaluateConditionA(hpkg, "1 and 2");
1513     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1514 
1515     r = MsiEvaluateConditionA(hpkg, "not 0 and 3");
1516     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1517 
1518     r = MsiEvaluateConditionA(hpkg, "not 0 and 0");
1519     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1520 
1521     r = MsiEvaluateConditionA(hpkg, "not 0 or 1");
1522     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1523 
1524     r = MsiEvaluateConditionA(hpkg, "(0)");
1525     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1526 
1527     r = MsiEvaluateConditionA(hpkg, "(((((1))))))");
1528     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1529 
1530     r = MsiEvaluateConditionA(hpkg, "(((((1)))))");
1531     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1532 
1533     r = MsiEvaluateConditionA(hpkg, " \"A\" < \"B\" ");
1534     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1535 
1536     r = MsiEvaluateConditionA(hpkg, " \"A\" > \"B\" ");
1537     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1538 
1539     r = MsiEvaluateConditionA(hpkg, " \"1\" > \"12\" ");
1540     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1541 
1542     r = MsiEvaluateConditionA(hpkg, " \"100\" < \"21\" ");
1543     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1544 
1545     r = MsiEvaluateConditionA(hpkg, "0 < > 0");
1546     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1547 
1548     r = MsiEvaluateConditionA(hpkg, "(1<<1) == 2");
1549     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1550 
1551     r = MsiEvaluateConditionA(hpkg, " \"A\" = \"a\" ");
1552     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1553 
1554     r = MsiEvaluateConditionA(hpkg, " \"A\" ~ = \"a\" ");
1555     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1556 
1557     r = MsiEvaluateConditionA(hpkg, " \"A\" ~= \"a\" ");
1558     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1559 
1560     r = MsiEvaluateConditionA(hpkg, " \"A\" ~= 1 ");
1561     ok( r == MSICONDITION_FALSE, "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, " 1 ~= 1 ");
1567     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1568 
1569     r = MsiEvaluateConditionA(hpkg, " 1 ~= \"1\" ");
1570     ok( r == MSICONDITION_FALSE, "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, " 0 = \"1\" ");
1576     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1577 
1578     r = MsiEvaluateConditionA(hpkg, " 0 < \"100\" ");
1579     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1580 
1581     r = MsiEvaluateConditionA(hpkg, " 100 > \"0\" ");
1582     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1583 
1584     r = MsiEvaluateConditionA(hpkg, "1 XOR 1");
1585     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1586 
1587     r = MsiEvaluateConditionA(hpkg, "1 IMP 1");
1588     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1589 
1590     r = MsiEvaluateConditionA(hpkg, "1 IMP 0");
1591     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1592 
1593     r = MsiEvaluateConditionA(hpkg, "0 IMP 0");
1594     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1595 
1596     r = MsiEvaluateConditionA(hpkg, "0 EQV 0");
1597     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1598 
1599     r = MsiEvaluateConditionA(hpkg, "0 EQV 1");
1600     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1601 
1602     r = MsiEvaluateConditionA(hpkg, "1 IMP 1 OR 0");
1603     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1604 
1605     r = MsiEvaluateConditionA(hpkg, "1 IMPL 1");
1606     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1607 
1608     r = MsiEvaluateConditionA(hpkg, "\"ASFD\" >< \"S\" ");
1609     ok( r == MSICONDITION_TRUE, "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\" ~>< \"\" ");
1615     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1616 
1617     r = MsiEvaluateConditionA(hpkg, "\"ASFD\" ~>< \"sss\" ");
1618     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1619 
1620     MsiSetPropertyA(hpkg, "mm", "5" );
1621 
1622     r = MsiEvaluateConditionA(hpkg, "mm = 5");
1623     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1624 
1625     r = MsiEvaluateConditionA(hpkg, "mm < 6");
1626     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1627 
1628     r = MsiEvaluateConditionA(hpkg, "mm <= 5");
1629     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1630 
1631     r = MsiEvaluateConditionA(hpkg, "mm > 4");
1632     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1633 
1634     r = MsiEvaluateConditionA(hpkg, "mm < 12");
1635     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1636 
1637     r = MsiEvaluateConditionA(hpkg, "mm = \"5\"");
1638     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1639 
1640     r = MsiEvaluateConditionA(hpkg, "0 = \"\"");
1641     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1642 
1643     r = MsiEvaluateConditionA(hpkg, "0 AND \"\"");
1644     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1645 
1646     r = MsiEvaluateConditionA(hpkg, "1 AND \"\"");
1647     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1648 
1649     r = MsiEvaluateConditionA(hpkg, "1 AND \"1\"");
1650     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1651 
1652     r = MsiEvaluateConditionA(hpkg, "3 >< 1");
1653     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1654 
1655     r = MsiEvaluateConditionA(hpkg, "3 >< 4");
1656     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1657 
1658     r = MsiEvaluateConditionA(hpkg, "NOT 0 AND 0");
1659     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1660 
1661     r = MsiEvaluateConditionA(hpkg, "NOT 0 AND 1");
1662     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1663 
1664     r = MsiEvaluateConditionA(hpkg, "NOT 1 OR 0");
1665     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1666 
1667     r = MsiEvaluateConditionA(hpkg, "0 AND 1 OR 1");
1668     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1669 
1670     r = MsiEvaluateConditionA(hpkg, "0 AND 0 OR 1");
1671     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1672 
1673     r = MsiEvaluateConditionA(hpkg, "NOT 0 AND 1 OR 0");
1674     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1675 
1676     r = MsiEvaluateConditionA(hpkg, "_1 = _1");
1677     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1678 
1679     r = MsiEvaluateConditionA(hpkg, "( 1 AND 1 ) = 2");
1680     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1681 
1682     r = MsiEvaluateConditionA(hpkg, "NOT ( 1 AND 1 )");
1683     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1684 
1685     r = MsiEvaluateConditionA(hpkg, "NOT A AND (BBBBBBBBBB=2 OR CCC=1) AND Ddddddddd");
1686     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1687 
1688     r = MsiEvaluateConditionA(hpkg, "Installed<>\"\"");
1689     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1690 
1691     r = MsiEvaluateConditionA(hpkg, "NOT 1 AND 0");
1692     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1693 
1694     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1695     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1696 
1697     r = MsiEvaluateConditionA(hpkg, "bandalmael<>0");
1698     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1699 
1700     r = MsiEvaluateConditionA(hpkg, "bandalmael<0");
1701     ok( r == MSICONDITION_FALSE, "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_TRUE, "wrong return val\n");
1714 
1715     MsiSetPropertyA(hpkg, "bandalmael", "0" );
1716     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1717     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1718 
1719     MsiSetPropertyA(hpkg, "bandalmael", "" );
1720     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1721     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1722 
1723     MsiSetPropertyA(hpkg, "bandalmael", "asdf" );
1724     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1725     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1726 
1727     MsiSetPropertyA(hpkg, "bandalmael", "0asdf" );
1728     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1729     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1730 
1731     MsiSetPropertyA(hpkg, "bandalmael", "0 " );
1732     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1733     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1734 
1735     MsiSetPropertyA(hpkg, "bandalmael", "-0" );
1736     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1737     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1738 
1739     MsiSetPropertyA(hpkg, "bandalmael", "0000000000000" );
1740     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1741     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1742 
1743     MsiSetPropertyA(hpkg, "bandalmael", "--0" );
1744     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1745     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1746 
1747     MsiSetPropertyA(hpkg, "bandalmael", "0x00" );
1748     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1749     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1750 
1751     MsiSetPropertyA(hpkg, "bandalmael", "-" );
1752     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1753     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1754 
1755     MsiSetPropertyA(hpkg, "bandalmael", "+0" );
1756     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1757     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1758 
1759     MsiSetPropertyA(hpkg, "bandalmael", "0.0" );
1760     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1761     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1762     r = MsiEvaluateConditionA(hpkg, "bandalmael<>0");
1763     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1764 
1765     MsiSetPropertyA(hpkg, "one", "hi");
1766     MsiSetPropertyA(hpkg, "two", "hithere");
1767     r = MsiEvaluateConditionA(hpkg, "one >< two");
1768     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1769 
1770     MsiSetPropertyA(hpkg, "one", "hithere");
1771     MsiSetPropertyA(hpkg, "two", "hi");
1772     r = MsiEvaluateConditionA(hpkg, "one >< two");
1773     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1774 
1775     MsiSetPropertyA(hpkg, "one", "hello");
1776     MsiSetPropertyA(hpkg, "two", "hi");
1777     r = MsiEvaluateConditionA(hpkg, "one >< two");
1778     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1779 
1780     MsiSetPropertyA(hpkg, "one", "hellohithere");
1781     MsiSetPropertyA(hpkg, "two", "hi");
1782     r = MsiEvaluateConditionA(hpkg, "one >< two");
1783     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1784 
1785     MsiSetPropertyA(hpkg, "one", "");
1786     MsiSetPropertyA(hpkg, "two", "hi");
1787     r = MsiEvaluateConditionA(hpkg, "one >< two");
1788     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1789 
1790     MsiSetPropertyA(hpkg, "one", "hi");
1791     MsiSetPropertyA(hpkg, "two", "");
1792     r = MsiEvaluateConditionA(hpkg, "one >< two");
1793     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1794 
1795     MsiSetPropertyA(hpkg, "one", "");
1796     MsiSetPropertyA(hpkg, "two", "");
1797     r = MsiEvaluateConditionA(hpkg, "one >< two");
1798     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1799 
1800     MsiSetPropertyA(hpkg, "one", "1234");
1801     MsiSetPropertyA(hpkg, "two", "1");
1802     r = MsiEvaluateConditionA(hpkg, "one >< two");
1803     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1804 
1805     MsiSetPropertyA(hpkg, "one", "one 1234");
1806     MsiSetPropertyA(hpkg, "two", "1");
1807     r = MsiEvaluateConditionA(hpkg, "one >< two");
1808     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1809 
1810     MsiSetPropertyA(hpkg, "one", "hithere");
1811     MsiSetPropertyA(hpkg, "two", "hi");
1812     r = MsiEvaluateConditionA(hpkg, "one << two");
1813     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1814 
1815     MsiSetPropertyA(hpkg, "one", "hi");
1816     MsiSetPropertyA(hpkg, "two", "hithere");
1817     r = MsiEvaluateConditionA(hpkg, "one << two");
1818     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1819 
1820     MsiSetPropertyA(hpkg, "one", "hi");
1821     MsiSetPropertyA(hpkg, "two", "hi");
1822     r = MsiEvaluateConditionA(hpkg, "one << two");
1823     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1824 
1825     MsiSetPropertyA(hpkg, "one", "abcdhithere");
1826     MsiSetPropertyA(hpkg, "two", "hi");
1827     r = MsiEvaluateConditionA(hpkg, "one << two");
1828     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1829 
1830     MsiSetPropertyA(hpkg, "one", "");
1831     MsiSetPropertyA(hpkg, "two", "hi");
1832     r = MsiEvaluateConditionA(hpkg, "one << two");
1833     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1834 
1835     MsiSetPropertyA(hpkg, "one", "hithere");
1836     MsiSetPropertyA(hpkg, "two", "");
1837     r = MsiEvaluateConditionA(hpkg, "one << two");
1838     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1839 
1840     MsiSetPropertyA(hpkg, "one", "");
1841     MsiSetPropertyA(hpkg, "two", "");
1842     r = MsiEvaluateConditionA(hpkg, "one << two");
1843     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1844 
1845     MsiSetPropertyA(hpkg, "one", "1234");
1846     MsiSetPropertyA(hpkg, "two", "1");
1847     r = MsiEvaluateConditionA(hpkg, "one << two");
1848     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1849 
1850     MsiSetPropertyA(hpkg, "one", "1234 one");
1851     MsiSetPropertyA(hpkg, "two", "1");
1852     r = MsiEvaluateConditionA(hpkg, "one << two");
1853     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1854 
1855     MsiSetPropertyA(hpkg, "one", "hithere");
1856     MsiSetPropertyA(hpkg, "two", "there");
1857     r = MsiEvaluateConditionA(hpkg, "one >> two");
1858     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1859 
1860     MsiSetPropertyA(hpkg, "one", "hithere");
1861     MsiSetPropertyA(hpkg, "two", "hi");
1862     r = MsiEvaluateConditionA(hpkg, "one >> two");
1863     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1864 
1865     MsiSetPropertyA(hpkg, "one", "there");
1866     MsiSetPropertyA(hpkg, "two", "hithere");
1867     r = MsiEvaluateConditionA(hpkg, "one >> two");
1868     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1869 
1870     MsiSetPropertyA(hpkg, "one", "there");
1871     MsiSetPropertyA(hpkg, "two", "there");
1872     r = MsiEvaluateConditionA(hpkg, "one >> two");
1873     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1874 
1875     MsiSetPropertyA(hpkg, "one", "abcdhithere");
1876     MsiSetPropertyA(hpkg, "two", "hi");
1877     r = MsiEvaluateConditionA(hpkg, "one >> two");
1878     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1879 
1880     MsiSetPropertyA(hpkg, "one", "");
1881     MsiSetPropertyA(hpkg, "two", "there");
1882     r = MsiEvaluateConditionA(hpkg, "one >> two");
1883     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1884 
1885     MsiSetPropertyA(hpkg, "one", "there");
1886     MsiSetPropertyA(hpkg, "two", "");
1887     r = MsiEvaluateConditionA(hpkg, "one >> two");
1888     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1889 
1890     MsiSetPropertyA(hpkg, "one", "");
1891     MsiSetPropertyA(hpkg, "two", "");
1892     r = MsiEvaluateConditionA(hpkg, "one >> two");
1893     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1894 
1895     MsiSetPropertyA(hpkg, "one", "1234");
1896     MsiSetPropertyA(hpkg, "two", "4");
1897     r = MsiEvaluateConditionA(hpkg, "one >> two");
1898     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1899 
1900     MsiSetPropertyA(hpkg, "one", "one 1234");
1901     MsiSetPropertyA(hpkg, "two", "4");
1902     r = MsiEvaluateConditionA(hpkg, "one >> two");
1903     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1904 
1905     MsiSetPropertyA(hpkg, "MsiNetAssemblySupport", NULL);  /* make sure it's empty */
1906 
1907     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322\"");
1908     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1909 
1910     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport > \"1.1.4322\"");
1911     ok( r == MSICONDITION_FALSE, "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_TRUE, "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 < \"abcd\"");
1926     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1927 
1928     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a1.1.4322\"");
1929     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1930 
1931     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322a\"");
1932     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1933 
1934     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"0000001.1.4322\"");
1935     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1936 
1937     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322.1\"");
1938     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1939 
1940     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322.1.1\"");
1941     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1942 
1943     r = MsiEvaluateConditionA(hpkg, "\"2\" < \"1.1");
1944     ok( r == MSICONDITION_ERROR, "wrong return val (%d)\n", r);
1945 
1946     r = MsiEvaluateConditionA(hpkg, "\"2\" < \"1.1\"");
1947     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1948 
1949     r = MsiEvaluateConditionA(hpkg, "\"2\" < \"12.1\"");
1950     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1951 
1952     r = MsiEvaluateConditionA(hpkg, "\"02.1\" < \"2.11\"");
1953     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1954 
1955     r = MsiEvaluateConditionA(hpkg, "\"02.1.1\" < \"2.1\"");
1956     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1957 
1958     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1\"");
1959     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1960 
1961     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1\"");
1962     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1963 
1964     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"0\"");
1965     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1966 
1967     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"-1\"");
1968     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1969 
1970     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a\"");
1971     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1972 
1973     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"!\"");
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 < \"azAZ_\"");
1986     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1987 
1988     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a[a]\"");
1989     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1990 
1991     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a[a]a\"");
1992     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1993 
1994     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"[a]\"");
1995     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1996 
1997     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"[a]a\"");
1998     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1999 
2000     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"{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     MsiSetPropertyA(hpkg, "MsiNetAssemblySupport", "1.1.4322");
2019     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322\"");
2020     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2021 
2022     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.14322\"");
2023     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2024 
2025     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.5\"");
2026     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2027 
2028     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1\"");
2029     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2030 
2031     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1\"");
2032     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2033 
2034     MsiSetPropertyA(hpkg, "one", "1");
2035     r = MsiEvaluateConditionA(hpkg, "one < \"1\"");
2036     ok( r == MSICONDITION_FALSE, "wrong return val\n");
2037 
2038     MsiSetPropertyA(hpkg, "X", "5.0");
2039 
2040     r = MsiEvaluateConditionA(hpkg, "X != \"\"");
2041     ok( r == MSICONDITION_ERROR, "wrong return val (%d)\n", r);
2042 
2043     r = MsiEvaluateConditionA(hpkg, "X =\"5.0\"");
2044     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2045 
2046     r = MsiEvaluateConditionA(hpkg, "X =\"5.1\"");
2047     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2048 
2049     r = MsiEvaluateConditionA(hpkg, "X =\"6.0\"");
2050     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2051 
2052     r = MsiEvaluateConditionA(hpkg, "X =\"5.0\" or X =\"5.1\" or X =\"6.0\"");
2053     ok( r == MSICONDITION_TRUE, "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 !=\"\" and (X =\"5.0\" or X =\"5.1\" or X =\"6.0\")");
2059     ok( r == MSICONDITION_ERROR, "wrong return val (%d)\n", r);
2060 
2061     /* feature doesn't exist */
2062     r = MsiEvaluateConditionA(hpkg, "&nofeature");
2063     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2064     r = MsiEvaluateConditionA(hpkg, "&nofeature=\"\"");
2065     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2066     r = MsiEvaluateConditionA(hpkg, "!nofeature=\"\"");
2067     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2068     MsiEvaluateConditionA(hpkg, "$nocomponent=\"\"");
2069     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2070     MsiEvaluateConditionA(hpkg, "?nocomponent=\"\"");
2071     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2072 
2073     MsiSetPropertyA(hpkg, "A", "2");
2074     MsiSetPropertyA(hpkg, "X", "50");
2075 
2076     r = MsiEvaluateConditionA(hpkg, "2 <= X");
2077     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2078 
2079     r = MsiEvaluateConditionA(hpkg, "A <= X");
2080     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2081 
2082     r = MsiEvaluateConditionA(hpkg, "A <= 50");
2083     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2084 
2085     MsiSetPropertyA(hpkg, "X", "50val");
2086 
2087     r = MsiEvaluateConditionA(hpkg, "2 <= X");
2088     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2089 
2090     r = MsiEvaluateConditionA(hpkg, "A <= X");
2091     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2092 
2093     MsiSetPropertyA(hpkg, "A", "7");
2094     MsiSetPropertyA(hpkg, "X", "50");
2095 
2096     r = MsiEvaluateConditionA(hpkg, "7 <= X");
2097     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2098 
2099     r = MsiEvaluateConditionA(hpkg, "A <= X");
2100     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2101 
2102     r = MsiEvaluateConditionA(hpkg, "A <= 50");
2103     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2104 
2105     MsiSetPropertyA(hpkg, "X", "50val");
2106 
2107     r = MsiEvaluateConditionA(hpkg, "2 <= X");
2108     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2109 
2110     r = MsiEvaluateConditionA(hpkg, "A <= X");
2111     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2112 
2113     r = MsiEvaluateConditionW(hpkg, cond1);
2114     ok( r == MSICONDITION_TRUE || broken(r == MSICONDITION_FALSE),
2115         "wrong return val (%d)\n", r);
2116 
2117     r = MsiEvaluateConditionW(hpkg, cond2);
2118     ok( r == MSICONDITION_FALSE || broken(r == MSICONDITION_TRUE),
2119         "wrong return val (%d)\n", r);
2120 
2121     r = MsiEvaluateConditionW(hpkg, cond3);
2122     ok( r == MSICONDITION_TRUE || broken(r == MSICONDITION_FALSE),
2123         "wrong return val (%d)\n", r);
2124 
2125     r = MsiEvaluateConditionW(hpkg, cond4);
2126     ok( r == MSICONDITION_FALSE || broken(r == MSICONDITION_TRUE),
2127         "wrong return val (%d)\n", r);
2128 
2129     MsiCloseHandle( hpkg );
2130     DeleteFileA(msifile);
2131 }
2132 
2133 static BOOL check_prop_empty( MSIHANDLE hpkg, const char * prop)
2134 {
2135     UINT r;
2136     DWORD sz;
2137     char buffer[2];
2138 
2139     sz = sizeof buffer;
2140     strcpy(buffer,"x");
2141     r = MsiGetPropertyA( hpkg, prop, buffer, &sz );
2142     return r == ERROR_SUCCESS && buffer[0] == 0 && sz == 0;
2143 }
2144 
2145 static void test_props(void)
2146 {
2147     MSIHANDLE hpkg, hdb;
2148     UINT r;
2149     DWORD sz;
2150     char buffer[0x100];
2151 
2152     hdb = create_package_db();
2153 
2154     create_property_table(hdb);
2155     add_property_entry(hdb, "'MetadataCompName', 'Photoshop.dll'");
2156 
2157     r = package_from_db( hdb, &hpkg );
2158     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2159     {
2160         skip("Not enough rights to perform tests\n");
2161         DeleteFileA(msifile);
2162         return;
2163     }
2164     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
2165 
2166     /* test invalid values */
2167     r = MsiGetPropertyA( 0, NULL, NULL, NULL );
2168     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
2169 
2170     r = MsiGetPropertyA( hpkg, NULL, NULL, NULL );
2171     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
2172 
2173     r = MsiGetPropertyA( hpkg, "boo", NULL, NULL );
2174     ok( r == ERROR_SUCCESS, "wrong return val\n");
2175 
2176     r = MsiGetPropertyA( hpkg, "boo", buffer, NULL );
2177     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
2178 
2179     /* test retrieving an empty/nonexistent property */
2180     sz = sizeof buffer;
2181     r = MsiGetPropertyA( hpkg, "boo", NULL, &sz );
2182     ok( r == ERROR_SUCCESS, "wrong return val\n");
2183     ok( sz == 0, "wrong size returned\n");
2184 
2185     check_prop_empty( hpkg, "boo");
2186     sz = 0;
2187     strcpy(buffer,"x");
2188     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2189     ok( r == ERROR_MORE_DATA, "wrong return val\n");
2190     ok( !strcmp(buffer,"x"), "buffer was changed\n");
2191     ok( sz == 0, "wrong size returned\n");
2192 
2193     sz = 1;
2194     strcpy(buffer,"x");
2195     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2196     ok( r == ERROR_SUCCESS, "wrong return val\n");
2197     ok( buffer[0] == 0, "buffer was not changed\n");
2198     ok( sz == 0, "wrong size returned\n");
2199 
2200     /* set the property to something */
2201     r = MsiSetPropertyA( 0, NULL, NULL );
2202     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
2203 
2204     r = MsiSetPropertyA( hpkg, NULL, NULL );
2205     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
2206 
2207     r = MsiSetPropertyA( hpkg, "", NULL );
2208     ok( r == ERROR_SUCCESS, "wrong return val\n");
2209 
2210     /* try set and get some illegal property identifiers */
2211     r = MsiSetPropertyA( hpkg, "", "asdf" );
2212     ok( r == ERROR_FUNCTION_FAILED, "wrong return val\n");
2213 
2214     r = MsiSetPropertyA( hpkg, "=", "asdf" );
2215     ok( r == ERROR_SUCCESS, "wrong return val\n");
2216 
2217     r = MsiSetPropertyA( hpkg, " ", "asdf" );
2218     ok( r == ERROR_SUCCESS, "wrong return val\n");
2219 
2220     r = MsiSetPropertyA( hpkg, "'", "asdf" );
2221     ok( r == ERROR_SUCCESS, "wrong return val\n");
2222 
2223     sz = sizeof buffer;
2224     buffer[0]=0;
2225     r = MsiGetPropertyA( hpkg, "'", buffer, &sz );
2226     ok( r == ERROR_SUCCESS, "wrong return val\n");
2227     ok( !strcmp(buffer,"asdf"), "buffer was not changed\n");
2228 
2229     /* set empty values */
2230     r = MsiSetPropertyA( hpkg, "boo", NULL );
2231     ok( r == ERROR_SUCCESS, "wrong return val\n");
2232     ok( check_prop_empty( hpkg, "boo"), "prop wasn't empty\n");
2233 
2234     r = MsiSetPropertyA( hpkg, "boo", "" );
2235     ok( r == ERROR_SUCCESS, "wrong return val\n");
2236     ok( check_prop_empty( hpkg, "boo"), "prop wasn't empty\n");
2237 
2238     /* set a non-empty value */
2239     r = MsiSetPropertyA( hpkg, "boo", "xyz" );
2240     ok( r == ERROR_SUCCESS, "wrong return val\n");
2241 
2242     sz = 1;
2243     strcpy(buffer,"x");
2244     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2245     ok( r == ERROR_MORE_DATA, "wrong return val\n");
2246     ok( buffer[0] == 0, "buffer was not changed\n");
2247     ok( sz == 3, "wrong size returned\n");
2248 
2249     sz = 4;
2250     strcpy(buffer,"x");
2251     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2252     ok( r == ERROR_SUCCESS, "wrong return val\n");
2253     ok( !strcmp(buffer,"xyz"), "buffer was not changed\n");
2254     ok( sz == 3, "wrong size returned\n");
2255 
2256     sz = 3;
2257     strcpy(buffer,"x");
2258     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2259     ok( r == ERROR_MORE_DATA, "wrong return val\n");
2260     ok( !strcmp(buffer,"xy"), "buffer was not changed\n");
2261     ok( sz == 3, "wrong size returned\n");
2262 
2263     r = MsiSetPropertyA(hpkg, "SourceDir", "foo");
2264     ok( r == ERROR_SUCCESS, "wrong return val\n");
2265 
2266     sz = 4;
2267     r = MsiGetPropertyA(hpkg, "SOURCEDIR", buffer, &sz);
2268     ok( r == ERROR_SUCCESS, "wrong return val\n");
2269     ok( !strcmp(buffer,""), "buffer wrong\n");
2270     ok( sz == 0, "wrong size returned\n");
2271 
2272     sz = 4;
2273     r = MsiGetPropertyA(hpkg, "SOMERANDOMNAME", buffer, &sz);
2274     ok( r == ERROR_SUCCESS, "wrong return val\n");
2275     ok( !strcmp(buffer,""), "buffer wrong\n");
2276     ok( sz == 0, "wrong size returned\n");
2277 
2278     sz = 4;
2279     r = MsiGetPropertyA(hpkg, "SourceDir", buffer, &sz);
2280     ok( r == ERROR_SUCCESS, "wrong return val\n");
2281     ok( !strcmp(buffer,"foo"), "buffer wrong\n");
2282     ok( sz == 3, "wrong size returned\n");
2283 
2284     r = MsiSetPropertyA(hpkg, "MetadataCompName", "Photoshop.dll");
2285     ok( r == ERROR_SUCCESS, "wrong return val\n");
2286 
2287     sz = 0;
2288     r = MsiGetPropertyA(hpkg, "MetadataCompName", NULL, &sz );
2289     ok( r == ERROR_SUCCESS, "return wrong\n");
2290     ok( sz == 13, "size wrong (%d)\n", sz);
2291 
2292     sz = 13;
2293     r = MsiGetPropertyA(hpkg, "MetadataCompName", buffer, &sz );
2294     ok( r == ERROR_MORE_DATA, "return wrong\n");
2295     ok( !strcmp(buffer,"Photoshop.dl"), "buffer wrong\n");
2296 
2297     r = MsiSetPropertyA(hpkg, "property", "value");
2298     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2299 
2300     sz = 6;
2301     r = MsiGetPropertyA(hpkg, "property", buffer, &sz);
2302     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2303     ok( !strcmp(buffer, "value"), "Expected value, got %s\n", buffer);
2304 
2305     r = MsiSetPropertyA(hpkg, "property", NULL);
2306     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2307 
2308     sz = 6;
2309     r = MsiGetPropertyA(hpkg, "property", buffer, &sz);
2310     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2311     ok(!buffer[0], "Expected empty string, got %s\n", buffer);
2312 
2313     MsiCloseHandle( hpkg );
2314     DeleteFileA(msifile);
2315 }
2316 
2317 static BOOL find_prop_in_property(MSIHANDLE hdb, LPCSTR prop, LPCSTR val, int len)
2318 {
2319     MSIHANDLE hview, hrec;
2320     BOOL found = FALSE;
2321     CHAR buffer[MAX_PATH];
2322     DWORD sz;
2323     UINT r;
2324 
2325     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Property`", &hview);
2326     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
2327     r = MsiViewExecute(hview, 0);
2328     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
2329 
2330     if (len < 0) len = lstrlenA(val);
2331 
2332     while (r == ERROR_SUCCESS && !found)
2333     {
2334         r = MsiViewFetch(hview, &hrec);
2335         if (r != ERROR_SUCCESS) break;
2336 
2337         sz = MAX_PATH;
2338         r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
2339         if (r == ERROR_SUCCESS && !lstrcmpA(buffer, prop))
2340         {
2341             sz = MAX_PATH;
2342             r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
2343             if (r == ERROR_SUCCESS && !memcmp(buffer, val, len) && !buffer[len])
2344             {
2345                 ok(sz == len, "wrong size %u\n", sz);
2346                 found = TRUE;
2347             }
2348         }
2349 
2350         MsiCloseHandle(hrec);
2351     }
2352     MsiViewClose(hview);
2353     MsiCloseHandle(hview);
2354     return found;
2355 }
2356 
2357 static void test_property_table(void)
2358 {
2359     const char *query;
2360     UINT r;
2361     MSIHANDLE hpkg, hdb, hrec;
2362     char buffer[MAX_PATH], package[10];
2363     DWORD sz;
2364     BOOL found;
2365 
2366     hdb = create_package_db();
2367     ok( hdb, "failed to create package\n");
2368 
2369     r = package_from_db(hdb, &hpkg);
2370     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2371     {
2372         skip("Not enough rights to perform tests\n");
2373         DeleteFileA(msifile);
2374         return;
2375     }
2376     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
2377 
2378     MsiCloseHandle(hdb);
2379 
2380     hdb = MsiGetActiveDatabase(hpkg);
2381 
2382     query = "CREATE TABLE `_Property` ( "
2383         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
2384     r = run_query(hdb, query);
2385     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2386 
2387     MsiCloseHandle(hdb);
2388     MsiCloseHandle(hpkg);
2389     DeleteFileA(msifile);
2390 
2391     hdb = create_package_db();
2392     ok( hdb, "failed to create package\n");
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_SUCCESS, "failed to create table\n");
2398 
2399     query = "ALTER `_Property` ADD `foo` INTEGER";
2400     r = run_query(hdb, query);
2401     ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to add column\n");
2402 
2403     query = "ALTER TABLE `_Property` ADD `foo` INTEGER";
2404     r = run_query(hdb, query);
2405     ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to add column\n");
2406 
2407     query = "ALTER TABLE `_Property` ADD `extra` INTEGER";
2408     r = run_query(hdb, query);
2409     ok(r == ERROR_SUCCESS, "failed to add column\n");
2410 
2411     sprintf(package, "#%i", hdb);
2412     r = MsiOpenPackageA(package, &hpkg);
2413     ok(r != ERROR_SUCCESS, "MsiOpenPackage succeeded\n");
2414     if (r == ERROR_SUCCESS)
2415         MsiCloseHandle(hpkg);
2416 
2417     r = MsiCloseHandle(hdb);
2418     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed %u\n", r);
2419 
2420     hdb = create_package_db();
2421     ok (hdb, "failed to create package database\n");
2422 
2423     create_property_table(hdb);
2424     add_property_entry(hdb, "'prop', 'val'");
2425 
2426     create_custom_action_table(hdb);
2427     add_custom_action_entry( hdb, "'EmbedNull', 51, 'prop2', '[~]np'" );
2428 
2429     r = package_from_db(hdb, &hpkg);
2430     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
2431 
2432     MsiCloseHandle(hdb);
2433 
2434     sz = MAX_PATH;
2435     r = MsiGetPropertyA(hpkg, "prop", buffer, &sz);
2436     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2437     ok(!lstrcmpA(buffer, "val"), "Expected val, got %s\n", buffer);
2438 
2439     hdb = MsiGetActiveDatabase(hpkg);
2440 
2441     found = find_prop_in_property(hdb, "prop", "val", -1);
2442     ok(found, "prop should be in the _Property table\n");
2443 
2444     add_property_entry(hdb, "'dantes', 'mercedes'");
2445 
2446     query = "SELECT * FROM `_Property` WHERE `Property` = 'dantes'";
2447     r = do_query(hdb, query, &hrec);
2448     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2449 
2450     found = find_prop_in_property(hdb, "dantes", "mercedes", -1);
2451     ok(found == FALSE, "dantes should not be in the _Property table\n");
2452 
2453     sz = MAX_PATH;
2454     lstrcpyA(buffer, "aaa");
2455     r = MsiGetPropertyA(hpkg, "dantes", buffer, &sz);
2456     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2457     ok(!buffer[0], "Expected empty string, got %s\n", buffer);
2458 
2459     r = MsiSetPropertyA(hpkg, "dantes", "mercedes");
2460     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2461 
2462     found = find_prop_in_property(hdb, "dantes", "mercedes", -1);
2463     ok(found == TRUE, "dantes should be in the _Property table\n");
2464 
2465     r = MsiDoActionA( hpkg, "EmbedNull" );
2466     ok( r == ERROR_SUCCESS, "EmbedNull failed: %d\n", r);
2467 
2468     sz = MAX_PATH;
2469     memset( buffer, 'a', sizeof(buffer) );
2470     r = MsiGetPropertyA( hpkg, "prop2", buffer, &sz );
2471     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2472     ok( !memcmp( buffer, "\0np", sizeof("\0np") ), "wrong value\n");
2473     ok( sz == sizeof("\0np") - 1, "got %u\n", sz );
2474 
2475     found = find_prop_in_property(hdb, "prop2", "\0np", 3);
2476     ok(found == TRUE, "prop2 should be in the _Property table\n");
2477 
2478     MsiCloseHandle(hdb);
2479     MsiCloseHandle(hpkg);
2480     DeleteFileA(msifile);
2481 }
2482 
2483 static UINT try_query_param( MSIHANDLE hdb, LPCSTR szQuery, MSIHANDLE hrec )
2484 {
2485     MSIHANDLE htab = 0;
2486     UINT res;
2487 
2488     res = MsiDatabaseOpenViewA( hdb, szQuery, &htab );
2489     if( res == ERROR_SUCCESS )
2490     {
2491         UINT r;
2492 
2493         r = MsiViewExecute( htab, hrec );
2494         if( r != ERROR_SUCCESS )
2495         {
2496             res = r;
2497             fprintf(stderr,"MsiViewExecute failed %08x\n", res);
2498         }
2499 
2500         r = MsiViewClose( htab );
2501         if( r != ERROR_SUCCESS )
2502             res = r;
2503 
2504         r = MsiCloseHandle( htab );
2505         if( r != ERROR_SUCCESS )
2506             res = r;
2507     }
2508     return res;
2509 }
2510 
2511 static UINT try_query( MSIHANDLE hdb, LPCSTR szQuery )
2512 {
2513     return try_query_param( hdb, szQuery, 0 );
2514 }
2515 
2516 static void set_summary_str(MSIHANDLE hdb, DWORD pid, LPCSTR value)
2517 {
2518     MSIHANDLE summary;
2519     UINT r;
2520 
2521     r = MsiGetSummaryInformationA(hdb, NULL, 1, &summary);
2522     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2523 
2524     r = MsiSummaryInfoSetPropertyA(summary, pid, VT_LPSTR, 0, NULL, value);
2525     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2526 
2527     r = MsiSummaryInfoPersist(summary);
2528     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2529 
2530     MsiCloseHandle(summary);
2531 }
2532 
2533 static void set_summary_dword(MSIHANDLE hdb, DWORD pid, DWORD value)
2534 {
2535     MSIHANDLE summary;
2536     UINT r;
2537 
2538     r = MsiGetSummaryInformationA(hdb, NULL, 1, &summary);
2539     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2540 
2541     r = MsiSummaryInfoSetPropertyA(summary, pid, VT_I4, value, NULL, NULL);
2542     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2543 
2544     r = MsiSummaryInfoPersist(summary);
2545     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2546 
2547     MsiCloseHandle(summary);
2548 }
2549 
2550 static void test_msipackage(void)
2551 {
2552     MSIHANDLE hdb = 0, hpack = 100;
2553     UINT r;
2554     const char *query;
2555     char name[10];
2556 
2557     /* NULL szPackagePath */
2558     r = MsiOpenPackageA(NULL, &hpack);
2559     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2560 
2561     /* empty szPackagePath */
2562     r = MsiOpenPackageA("", &hpack);
2563     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2564     {
2565         skip("Not enough rights to perform tests\n");
2566         return;
2567     }
2568     todo_wine
2569     {
2570         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2571     }
2572 
2573     if (r == ERROR_SUCCESS)
2574         MsiCloseHandle(hpack);
2575 
2576     /* nonexistent szPackagePath */
2577     r = MsiOpenPackageA("nonexistent", &hpack);
2578     ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
2579 
2580     /* NULL hProduct */
2581     r = MsiOpenPackageA(msifile, NULL);
2582     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2583 
2584     name[0]='#';
2585     name[1]=0;
2586     r = MsiOpenPackageA(name, &hpack);
2587     ok(r == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", r);
2588 
2589     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
2590     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2591 
2592     /* database exists, but is empty */
2593     sprintf(name, "#%d", hdb);
2594     r = MsiOpenPackageA(name, &hpack);
2595     ok(r == ERROR_INSTALL_PACKAGE_INVALID,
2596        "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
2597 
2598     query = "CREATE TABLE `Property` ( "
2599             "`Property` CHAR(72), `Value` CHAR(0) "
2600             "PRIMARY KEY `Property`)";
2601     r = try_query(hdb, query);
2602     ok(r == ERROR_SUCCESS, "failed to create Properties table\n");
2603 
2604     query = "CREATE TABLE `InstallExecuteSequence` ("
2605             "`Action` CHAR(72), `Condition` CHAR(0), `Sequence` INTEGER "
2606             "PRIMARY KEY `Action`)";
2607     r = try_query(hdb, query);
2608     ok(r == ERROR_SUCCESS, "failed to create InstallExecuteSequence table\n");
2609 
2610     /* a few key tables exist */
2611     sprintf(name, "#%d", hdb);
2612     r = MsiOpenPackageA(name, &hpack);
2613     ok(r == ERROR_INSTALL_PACKAGE_INVALID,
2614        "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
2615 
2616     MsiCloseHandle(hdb);
2617     DeleteFileA(msifile);
2618 
2619     /* start with a clean database to show what constitutes a valid package */
2620     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
2621     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2622 
2623     sprintf(name, "#%d", hdb);
2624 
2625     /* The following summary information props must exist:
2626      *  - PID_REVNUMBER
2627      *  - PID_PAGECOUNT
2628      */
2629 
2630     set_summary_dword(hdb, PID_PAGECOUNT, 100);
2631     r = MsiOpenPackageA(name, &hpack);
2632     ok(r == ERROR_INSTALL_PACKAGE_INVALID,
2633        "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
2634 
2635     set_summary_str(hdb, PID_REVNUMBER, "{004757CD-5092-49C2-AD20-28E1CE0DF5F2}");
2636     r = MsiOpenPackageA(name, &hpack);
2637     ok(r == ERROR_SUCCESS,
2638        "Expected ERROR_SUCCESS, got %d\n", r);
2639 
2640     MsiCloseHandle(hpack);
2641     MsiCloseHandle(hdb);
2642     DeleteFileA(msifile);
2643 }
2644 
2645 static void test_formatrecord2(void)
2646 {
2647     MSIHANDLE hpkg, hrec ;
2648     char buffer[0x100];
2649     DWORD sz;
2650     UINT r;
2651 
2652     r = package_from_db(create_package_db(), &hpkg);
2653     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2654     {
2655         skip("Not enough rights to perform tests\n");
2656         DeleteFileA(msifile);
2657         return;
2658     }
2659     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
2660 
2661     r = MsiSetPropertyA(hpkg, "Manufacturer", " " );
2662     ok( r == ERROR_SUCCESS, "set property failed\n");
2663 
2664     hrec = MsiCreateRecord(2);
2665     ok(hrec, "create record failed\n");
2666 
2667     r = MsiRecordSetStringA( hrec, 0, "[ProgramFilesFolder][Manufacturer]\\asdf");
2668     ok( r == ERROR_SUCCESS, "format record failed\n");
2669 
2670     buffer[0] = 0;
2671     sz = sizeof buffer;
2672     r = MsiFormatRecordA( hpkg, hrec, buffer, &sz );
2673     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2674 
2675     r = MsiRecordSetStringA(hrec, 0, "[foo][1]");
2676     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2677     r = MsiRecordSetStringA(hrec, 1, "hoo");
2678     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2679     sz = sizeof buffer;
2680     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2681     ok( sz == 3, "size wrong\n");
2682     ok( 0 == strcmp(buffer,"hoo"), "wrong output %s\n",buffer);
2683     ok( r == ERROR_SUCCESS, "format failed\n");
2684 
2685     r = MsiRecordSetStringA(hrec, 0, "x[~]x");
2686     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2687     sz = sizeof buffer;
2688     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2689     ok( sz == 3, "size wrong\n");
2690     ok( 0 == strcmp(buffer,"x"), "wrong output %s\n",buffer);
2691     ok( r == ERROR_SUCCESS, "format failed\n");
2692 
2693     r = MsiRecordSetStringA(hrec, 0, "[foo.$%}][1]");
2694     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2695     r = MsiRecordSetStringA(hrec, 1, "hoo");
2696     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2697     sz = sizeof buffer;
2698     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2699     ok( sz == 3, "size wrong\n");
2700     ok( 0 == strcmp(buffer,"hoo"), "wrong output %s\n",buffer);
2701     ok( r == ERROR_SUCCESS, "format failed\n");
2702 
2703     r = MsiRecordSetStringA(hrec, 0, "[\\[]");
2704     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2705     sz = sizeof buffer;
2706     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2707     ok( sz == 1, "size wrong\n");
2708     ok( 0 == strcmp(buffer,"["), "wrong output %s\n",buffer);
2709     ok( r == ERROR_SUCCESS, "format failed\n");
2710 
2711     SetEnvironmentVariableA("FOO", "BAR");
2712     r = MsiRecordSetStringA(hrec, 0, "[%FOO]");
2713     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2714     sz = sizeof buffer;
2715     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2716     ok( sz == 3, "size wrong\n");
2717     ok( 0 == strcmp(buffer,"BAR"), "wrong output %s\n",buffer);
2718     ok( r == ERROR_SUCCESS, "format failed\n");
2719 
2720     r = MsiRecordSetStringA(hrec, 0, "[[1]]");
2721     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2722     r = MsiRecordSetStringA(hrec, 1, "%FOO");
2723     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2724     sz = sizeof buffer;
2725     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2726     ok( sz == 3, "size wrong\n");
2727     ok( 0 == strcmp(buffer,"BAR"), "wrong output %s\n",buffer);
2728     ok( r == ERROR_SUCCESS, "format failed\n");
2729 
2730     MsiCloseHandle( hrec );
2731     MsiCloseHandle( hpkg );
2732     DeleteFileA(msifile);
2733 }
2734 
2735 static void test_formatrecord_tables(void)
2736 {
2737     MSIHANDLE hdb, hrec, hpkg = 0;
2738     CHAR buf[MAX_PATH];
2739     CHAR curr_dir[MAX_PATH];
2740     CHAR expected[MAX_PATH];
2741     CHAR root[MAX_PATH];
2742     DWORD size;
2743     UINT r;
2744 
2745     GetCurrentDirectoryA( MAX_PATH, curr_dir );
2746 
2747     hdb = create_package_db();
2748     ok ( hdb, "failed to create package database\n");
2749 
2750     add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'" );
2751     add_directory_entry( hdb, "'ReallyLongDir', 'TARGETDIR', "
2752                              "'I am a really long directory'" );
2753 
2754     create_feature_table( hdb );
2755     add_feature_entry( hdb, "'occipitofrontalis', '', '', '', 2, 1, '', 0" );
2756 
2757     create_component_table( hdb );
2758     add_component_entry( hdb, "'frontal', '', 'TARGETDIR', 0, '', 'frontal_file'" );
2759     add_component_entry( hdb, "'parietal', '', 'TARGETDIR', 1, '', 'parietal_file'" );
2760     add_component_entry( hdb, "'temporal', '', 'ReallyLongDir', 0, '', 'temporal_file'" );
2761 
2762     create_feature_components_table( hdb );
2763     add_feature_components_entry( hdb, "'occipitofrontalis', 'frontal'" );
2764     add_feature_components_entry( hdb, "'occipitofrontalis', 'parietal'" );
2765     add_feature_components_entry( hdb, "'occipitofrontalis', 'temporal'" );
2766 
2767     create_file_table( hdb );
2768     add_file_entry( hdb, "'frontal_file', 'frontal', 'frontal.txt', 0, '', '1033', 8192, 1" );
2769     add_file_entry( hdb, "'parietal_file', 'parietal', 'parietal.txt', 0, '', '1033', 8192, 1" );
2770     add_file_entry( hdb, "'temporal_file', 'temporal', 'temporal.txt', 0, '', '1033', 8192, 1" );
2771 
2772     create_custom_action_table( hdb );
2773     add_custom_action_entry( hdb, "'MyCustom', 51, 'prop', '[!temporal_file]'" );
2774     add_custom_action_entry( hdb, "'EscapeIt1', 51, 'prop', '[\\[]Bracket Text[\\]]'" );
2775     add_custom_action_entry( hdb, "'EscapeIt2', 51, 'prop', '[\\xabcd]'" );
2776     add_custom_action_entry( hdb, "'EscapeIt3', 51, 'prop', '[abcd\\xefgh]'" );
2777     add_custom_action_entry( hdb, "'EmbedNull', 51, 'prop', '[~]np'" );
2778 
2779     r = package_from_db( hdb, &hpkg );
2780     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2781     {
2782         skip("Not enough rights to perform tests\n");
2783         MsiCloseHandle( hdb );
2784         DeleteFileA( msifile );
2785         return;
2786     }
2787     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
2788 
2789     MsiCloseHandle( hdb );
2790 
2791     r = MsiSetPropertyA( hpkg, "imaprop", "ringer" );
2792     ok( r == ERROR_SUCCESS, "cannot set property: %d\n", r);
2793 
2794     hrec = MsiCreateRecord( 1 );
2795 
2796     /* property doesn't exist */
2797     size = MAX_PATH;
2798     /*MsiRecordSetStringA( hrec, 0, "[1]" ); */
2799     MsiRecordSetStringA( hrec, 1, "[idontexist]" );
2800     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2801     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2802     ok( !lstrcmpA( buf, "1:  " ), "Expected '1:  ', got %s\n", buf );
2803 
2804     /* property exists */
2805     size = MAX_PATH;
2806     MsiRecordSetStringA( hrec, 1, "[imaprop]" );
2807     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2808     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2809     ok( !lstrcmpA( buf, "1: ringer " ), "Expected '1: ringer ', got %s\n", buf );
2810 
2811     size = MAX_PATH;
2812     MsiRecordSetStringA( hrec, 0, "1: [1] " );
2813     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2814     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2815     ok( !lstrcmpA( buf, "1: ringer " ), "Expected '1: ringer ', got %s\n", buf );
2816 
2817     /* environment variable doesn't exist */
2818     size = MAX_PATH;
2819     MsiRecordSetStringA( hrec, 1, "[%idontexist]" );
2820     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2821     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2822     ok( !lstrcmpA( buf, "1:  " ), "Expected '1:  ', got %s\n", buf );
2823 
2824     /* environment variable exists */
2825     size = MAX_PATH;
2826     SetEnvironmentVariableA( "crazyvar", "crazyval" );
2827     MsiRecordSetStringA( hrec, 1, "[%crazyvar]" );
2828     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2829     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2830     ok( !lstrcmpA( buf, "1: crazyval " ), "Expected '1: crazyval ', got %s\n", buf );
2831 
2832     /* file key before CostInitialize */
2833     size = MAX_PATH;
2834     MsiRecordSetStringA( hrec, 1, "[#frontal_file]" );
2835     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2836     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2837     ok( !lstrcmpA( buf, "1:  " ), "Expected '1:  ', got %s\n", buf );
2838 
2839     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2840 
2841     r = MsiDoActionA(hpkg, "CostInitialize");
2842     ok( r == ERROR_SUCCESS, "CostInitialize failed: %d\n", r);
2843 
2844     r = MsiDoActionA(hpkg, "FileCost");
2845     ok( r == ERROR_SUCCESS, "FileCost failed: %d\n", r);
2846 
2847     r = MsiDoActionA(hpkg, "CostFinalize");
2848     ok( r == ERROR_SUCCESS, "CostFinalize failed: %d\n", r);
2849 
2850     size = MAX_PATH;
2851     MsiGetPropertyA( hpkg, "ROOTDRIVE", root, &size );
2852 
2853     sprintf( expected, "1: %sfrontal.txt ", root);
2854 
2855     /* frontal full file key */
2856     size = MAX_PATH;
2857     MsiRecordSetStringA( hrec, 1, "[#frontal_file]" );
2858     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2859     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2860     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2861 
2862     /* frontal short file key */
2863     size = MAX_PATH;
2864     MsiRecordSetStringA( hrec, 1, "[!frontal_file]" );
2865     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2866     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2867     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2868 
2869     sprintf( expected, "1: %sI am a really long directory\\temporal.txt ", root);
2870 
2871     /* temporal full file key */
2872     size = MAX_PATH;
2873     MsiRecordSetStringA( hrec, 1, "[#temporal_file]" );
2874     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2875     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2876     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2877 
2878     /* temporal short file key */
2879     size = MAX_PATH;
2880     MsiRecordSetStringA( hrec, 1, "[!temporal_file]" );
2881     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2882     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2883     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2884 
2885     /* custom action 51, files don't exist */
2886     r = MsiDoActionA( hpkg, "MyCustom" );
2887     ok( r == ERROR_SUCCESS, "MyCustom failed: %d\n", r);
2888 
2889     sprintf( expected, "%sI am a really long directory\\temporal.txt", root);
2890 
2891     size = MAX_PATH;
2892     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2893     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2894     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2895 
2896     sprintf( buf, "%sI am a really long directory", root );
2897     CreateDirectoryA( buf, NULL );
2898 
2899     lstrcatA( buf, "\\temporal.txt" );
2900     create_test_file( buf );
2901 
2902     /* custom action 51, files exist */
2903     r = MsiDoActionA( hpkg, "MyCustom" );
2904     ok( r == ERROR_SUCCESS, "MyCustom failed: %d\n", r);
2905 
2906     size = MAX_PATH;
2907     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2908     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2909     todo_wine
2910     {
2911         ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2912     }
2913 
2914     /* custom action 51, escaped text 1 */
2915     r = MsiDoActionA( hpkg, "EscapeIt1" );
2916     ok( r == ERROR_SUCCESS, "EscapeIt1 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     ok( !lstrcmpA( buf, "[Bracket Text]" ), "Expected '[Bracket Text]', got %s\n", buf);
2922 
2923     /* custom action 51, escaped text 2 */
2924     r = MsiDoActionA( hpkg, "EscapeIt2" );
2925     ok( r == ERROR_SUCCESS, "EscapeIt2 failed: %d\n", r);
2926 
2927     size = MAX_PATH;
2928     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2929     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2930     ok( !lstrcmpA( buf, "x" ), "Expected 'x', got %s\n", buf);
2931 
2932     /* custom action 51, escaped text 3 */
2933     r = MsiDoActionA( hpkg, "EscapeIt3" );
2934     ok( r == ERROR_SUCCESS, "EscapeIt3 failed: %d\n", r);
2935 
2936     size = MAX_PATH;
2937     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2938     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2939     ok( !lstrcmpA( buf, "" ), "Expected '', got %s\n", buf);
2940 
2941     /* custom action 51, embedded null */
2942     r = MsiDoActionA( hpkg, "EmbedNull" );
2943     ok( r == ERROR_SUCCESS, "EmbedNull failed: %d\n", r);
2944 
2945     size = MAX_PATH;
2946     memset( buf, 'a', sizeof(buf) );
2947     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2948     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2949     ok( !memcmp( buf, "\0np", sizeof("\0np") ), "wrong value\n");
2950     ok( size == sizeof("\0np") - 1, "got %u\n", size );
2951 
2952     r = MsiSetPropertyA( hpkg, "prop", "[~]np" );
2953     ok( r == ERROR_SUCCESS, "cannot set property: %d\n", r);
2954 
2955     size = MAX_PATH;
2956     memset( buf, 'a', sizeof(buf) );
2957     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2958     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2959     ok( !lstrcmpA( buf, "[~]np" ), "Expected '[~]np', got %s\n", buf);
2960 
2961     sprintf( expected, "1: %sI am a really long directory\\ ", root);
2962 
2963     /* component with INSTALLSTATE_LOCAL */
2964     size = MAX_PATH;
2965     MsiRecordSetStringA( hrec, 1, "[$temporal]" );
2966     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2967     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2968     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2969 
2970     r = MsiSetComponentStateA( hpkg, "temporal", INSTALLSTATE_SOURCE );
2971     ok( r == ERROR_SUCCESS, "failed to set install state: %d\n", r);
2972 
2973     /* component with INSTALLSTATE_SOURCE */
2974     lstrcpyA( expected, "1: " );
2975     lstrcatA( expected, curr_dir );
2976     if (strlen(curr_dir) > 3) lstrcatA( expected, "\\" );
2977     lstrcatA( expected, " " );
2978     size = MAX_PATH;
2979     MsiRecordSetStringA( hrec, 1, "[$parietal]" );
2980     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2981     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2982     ok( !lstrcmpA( buf, expected ), "Expected '%s', got '%s'\n", expected, buf);
2983 
2984     sprintf( buf, "%sI am a really long directory\\temporal.txt", root );
2985     DeleteFileA( buf );
2986 
2987     sprintf( buf, "%sI am a really long directory", root );
2988     RemoveDirectoryA( buf );
2989 
2990     MsiCloseHandle( hrec );
2991     MsiCloseHandle( hpkg );
2992     DeleteFileA( msifile );
2993 }
2994 
2995 static void test_feature_states( UINT line, MSIHANDLE package, const char *feature, UINT error,
2996                                  INSTALLSTATE expected_state, INSTALLSTATE expected_action, BOOL todo )
2997 {
2998     UINT r;
2999     INSTALLSTATE state = 0xdeadbee;
3000     INSTALLSTATE action = 0xdeadbee;
3001 
3002     r = MsiGetFeatureStateA( package, feature, &state, &action );
3003     ok( r == error, "%u: expected %d got %d\n", line, error, r );
3004     if (r == ERROR_SUCCESS)
3005     {
3006         ok( state == expected_state, "%u: expected state %d got %d\n",
3007             line, expected_state, state );
3008         todo_wine_if (todo)
3009             ok( action == expected_action, "%u: expected action %d got %d\n",
3010                 line, expected_action, action );
3011     }
3012     else
3013     {
3014         ok( state == 0xdeadbee, "%u: expected state 0xdeadbee got %d\n", line, state );
3015         todo_wine_if (todo)
3016             ok( action == 0xdeadbee, "%u: expected action 0xdeadbee got %d\n", line, action );
3017 
3018     }
3019 }
3020 
3021 static void test_component_states( UINT line, MSIHANDLE package, const char *component, UINT error,
3022                                    INSTALLSTATE expected_state, INSTALLSTATE expected_action, BOOL todo )
3023 {
3024     UINT r;
3025     INSTALLSTATE state = 0xdeadbee;
3026     INSTALLSTATE action = 0xdeadbee;
3027 
3028     r = MsiGetComponentStateA( package, component, &state, &action );
3029     ok( r == error, "%u: expected %d got %d\n", line, error, r );
3030     if (r == ERROR_SUCCESS)
3031     {
3032         ok( state == expected_state, "%u: expected state %d got %d\n",
3033             line, expected_state, state );
3034         todo_wine_if (todo)
3035             ok( action == expected_action, "%u: expected action %d got %d\n",
3036                 line, expected_action, action );
3037     }
3038     else
3039     {
3040         ok( state == 0xdeadbee, "%u: expected state 0xdeadbee got %d\n",
3041             line, state );
3042         todo_wine_if (todo)
3043             ok( action == 0xdeadbee, "%u: expected action 0xdeadbee got %d\n",
3044                 line, action );
3045     }
3046 }
3047 
3048 static void test_states(void)
3049 {
3050     static const char msifile2[] = "winetest2-package.msi";
3051     static const char msifile3[] = "winetest3-package.msi";
3052     static const char msifile4[] = "winetest4-package.msi";
3053     static const WCHAR msifile2W[] =
3054         {'w','i','n','e','t','e','s','t','2','-','p','a','c','k','a','g','e','.','m','s','i',0};
3055     static const WCHAR msifile3W[] =
3056         {'w','i','n','e','t','e','s','t','3','-','p','a','c','k','a','g','e','.','m','s','i',0};
3057     static const WCHAR msifile4W[] =
3058         {'w','i','n','e','t','e','s','t','4','-','p','a','c','k','a','g','e','.','m','s','i',0};
3059     char msi_cache_file[MAX_PATH];
3060     DWORD cache_file_name_len;
3061     INSTALLSTATE state;
3062     MSIHANDLE hpkg;
3063     UINT r;
3064     MSIHANDLE hdb;
3065     BOOL is_broken;
3066 
3067     if (is_process_limited())
3068     {
3069         skip("process is limited\n");
3070         return;
3071     }
3072 
3073     hdb = create_package_db();
3074     ok ( hdb, "failed to create package database\n" );
3075 
3076     add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'");
3077 
3078     create_property_table( hdb );
3079     add_property_entry( hdb, "'ProductCode', '{7262AC98-EEBD-4364-8CE3-D654F6A425B9}'" );
3080     add_property_entry( hdb, "'ProductLanguage', '1033'" );
3081     add_property_entry( hdb, "'ProductName', 'MSITEST'" );
3082     add_property_entry( hdb, "'ProductVersion', '1.1.1'" );
3083     add_property_entry( hdb, "'MSIFASTINSTALL', '1'" );
3084 
3085     create_install_execute_sequence_table( hdb );
3086     add_install_execute_sequence_entry( hdb, "'CostInitialize', '', '800'" );
3087     add_install_execute_sequence_entry( hdb, "'FileCost', '', '900'" );
3088     add_install_execute_sequence_entry( hdb, "'CostFinalize', '', '1000'" );
3089     add_install_execute_sequence_entry( hdb, "'InstallValidate', '', '1400'" );
3090     add_install_execute_sequence_entry( hdb, "'InstallInitialize', '', '1500'" );
3091     add_install_execute_sequence_entry( hdb, "'ProcessComponents', '', '1600'" );
3092     add_install_execute_sequence_entry( hdb, "'UnpublishFeatures', '', '1800'" );
3093     add_install_execute_sequence_entry( hdb, "'RegisterProduct', '', '6100'" );
3094     add_install_execute_sequence_entry( hdb, "'PublishFeatures', '', '6300'" );
3095     add_install_execute_sequence_entry( hdb, "'PublishProduct', '', '6400'" );
3096     add_install_execute_sequence_entry( hdb, "'InstallFinalize', '', '6600'" );
3097 
3098     create_media_table( hdb );
3099     add_media_entry( hdb, "'1', '3', '', '', 'DISK1', ''");
3100 
3101     create_feature_table( hdb );
3102 
3103     create_component_table( hdb );
3104 
3105     /* msidbFeatureAttributesFavorLocal */
3106     add_feature_entry( hdb, "'one', '', '', '', 2, 1, '', 0" );
3107 
3108     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesLocalOnly */
3109     add_component_entry( hdb, "'alpha', '{467EC132-739D-4784-A37B-677AA43DBC94}', 'TARGETDIR', 0, '', 'alpha_file'" );
3110 
3111     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSourceOnly */
3112     add_component_entry( hdb, "'beta', '{2C1F189C-24A6-4C34-B26B-994A6C026506}', 'TARGETDIR', 1, '', 'beta_file'" );
3113 
3114     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesOptional */
3115     add_component_entry( hdb, "'gamma', '{C271E2A4-DE2E-4F70-86D1-6984AF7DE2CA}', 'TARGETDIR', 2, '', 'gamma_file'" );
3116 
3117     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSharedDllRefCount */
3118     add_component_entry( hdb, "'theta', '{4EB3129D-81A8-48D5-9801-75600FED3DD9}', 'TARGETDIR', 8, '', 'theta_file'" );
3119 
3120     /* msidbFeatureAttributesFavorSource */
3121     add_feature_entry( hdb, "'two', '', '', '', 2, 1, '', 1" );
3122 
3123     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesLocalOnly */
3124     add_component_entry( hdb, "'delta', '{938FD4F2-C648-4259-A03C-7AA3B45643F3}', 'TARGETDIR', 0, '', 'delta_file'" );
3125 
3126     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSourceOnly */
3127     add_component_entry( hdb, "'epsilon', '{D59713B6-C11D-47F2-A395-1E5321781190}', 'TARGETDIR', 1, '', 'epsilon_file'" );
3128 
3129     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesOptional */
3130     add_component_entry( hdb, "'zeta', '{377D33AB-2FAA-42B9-A629-0C0DAE9B9C7A}', 'TARGETDIR', 2, '', 'zeta_file'" );
3131 
3132     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSharedDllRefCount */
3133     add_component_entry( hdb, "'iota', '{5D36F871-B5ED-4801-9E0F-C46B9E5C9669}', 'TARGETDIR', 8, '', 'iota_file'" );
3134 
3135     /* msidbFeatureAttributesFavorSource */
3136     add_feature_entry( hdb, "'three', '', '', '', 2, 1, '', 1" );
3137 
3138     /* msidbFeatureAttributesFavorLocal */
3139     add_feature_entry( hdb, "'four', '', '', '', 2, 1, '', 0" );
3140 
3141     /* disabled */
3142     add_feature_entry( hdb, "'five', '', '', '', 2, 0, '', 1" );
3143 
3144     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSourceOnly */
3145     add_component_entry( hdb, "'eta', '{DD89003F-0DD4-41B8-81C0-3411A7DA2695}', 'TARGETDIR', 1, '', 'eta_file'" );
3146 
3147     /* no feature parent:msidbComponentAttributesLocalOnly */
3148     add_component_entry( hdb, "'kappa', '{D6B93DC3-8DA5-4769-9888-42BFE156BB8B}', 'TARGETDIR', 1, '', 'kappa_file'" );
3149 
3150     /* msidbFeatureAttributesFavorLocal:removed */
3151     add_feature_entry( hdb, "'six', '', '', '', 2, 1, '', 0" );
3152 
3153     /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesLocalOnly */
3154     add_component_entry( hdb, "'lambda', '{6528C5E4-02A4-4636-A214-7A66A6C35B64}', 'TARGETDIR', 0, '', 'lambda_file'" );
3155 
3156     /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesSourceOnly */
3157     add_component_entry( hdb, "'mu', '{97014BAB-6C56-4013-9A63-2BF913B42519}', 'TARGETDIR', 1, '', 'mu_file'" );
3158 
3159     /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesOptional */
3160     add_component_entry( hdb, "'nu', '{943DD0D8-5808-4954-8526-3B8493FEDDCD}', 'TARGETDIR', 2, '', 'nu_file'" );
3161 
3162     /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesSharedDllRefCount */
3163     add_component_entry( hdb, "'xi', '{D6CF9EF7-6FCF-4930-B34B-F938AEFF9BDB}', 'TARGETDIR', 8, '', 'xi_file'" );
3164 
3165     /* msidbFeatureAttributesFavorSource:removed */
3166     add_feature_entry( hdb, "'seven', '', '', '', 2, 1, '', 1" );
3167 
3168     /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesLocalOnly */
3169     add_component_entry( hdb, "'omicron', '{7B57521D-15DB-4141-9AA6-01D934A4433F}', 'TARGETDIR', 0, '', 'omicron_file'" );
3170 
3171     /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesSourceOnly */
3172     add_component_entry( hdb, "'pi', '{FB85346B-378E-4492-8769-792305471C81}', 'TARGETDIR', 1, '', 'pi_file'" );
3173 
3174     /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesOptional */
3175     add_component_entry( hdb, "'rho', '{798F2047-7B0C-4783-8BB0-D703E554114B}', 'TARGETDIR', 2, '', 'rho_file'" );
3176 
3177     /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesSharedDllRefCount */
3178     add_component_entry( hdb, "'sigma', '{5CE9DDA8-B67B-4736-9D93-99D61C5B93E7}', 'TARGETDIR', 8, '', 'sigma_file'" );
3179 
3180     /* msidbFeatureAttributesFavorLocal */
3181     add_feature_entry( hdb, "'eight', '', '', '', 2, 1, '', 0" );
3182 
3183     add_component_entry( hdb, "'tau', '{07DEB510-677C-4A6F-A0A6-7CD8EFEA77ED}', 'TARGETDIR', 1, '', 'tau_file'" );
3184 
3185     /* msidbFeatureAttributesFavorSource */
3186     add_feature_entry( hdb, "'nine', '', '', '', 2, 1, '', 1" );
3187 
3188     add_component_entry( hdb, "'phi', '{9F0594C5-35AD-43EA-94DD-8DF73FAA664D}', 'TARGETDIR', 1, '', 'phi_file'" );
3189 
3190     /* msidbFeatureAttributesFavorAdvertise */
3191     add_feature_entry( hdb, "'ten', '', '', '', 2, 1, '', 4" );
3192 
3193     add_component_entry( hdb, "'chi', '{E6B539AB-5DA9-4236-A2D2-E341A50B4C38}', 'TARGETDIR', 1, '', 'chi_file'" );
3194 
3195     /* msidbFeatureAttributesUIDisallowAbsent */
3196     add_feature_entry( hdb, "'eleven', '', '', '', 2, 1, '', 16" );
3197 
3198     add_component_entry( hdb, "'psi', '{A06B23B5-746B-427A-8A6E-FD6AC8F46A95}', 'TARGETDIR', 1, '', 'psi_file'" );
3199 
3200     /* high install level */
3201     add_feature_entry( hdb, "'twelve', '', '', '', 2, 2, '', 0" );
3202 
3203     add_component_entry( hdb, "'upsilon', '{557e0c04-ceba-4c58-86a9-4a73352e8cf6}', 'TARGETDIR', 1, '', 'upsilon_file'" );
3204 
3205     /* msidbFeatureAttributesFollowParent */
3206     add_feature_entry( hdb, "'thirteen', '', '', '', 2, 2, '', 2" );
3207 
3208     create_feature_components_table( hdb );
3209     add_feature_components_entry( hdb, "'one', 'alpha'" );
3210     add_feature_components_entry( hdb, "'one', 'beta'" );
3211     add_feature_components_entry( hdb, "'one', 'gamma'" );
3212     add_feature_components_entry( hdb, "'one', 'theta'" );
3213     add_feature_components_entry( hdb, "'two', 'delta'" );
3214     add_feature_components_entry( hdb, "'two', 'epsilon'" );
3215     add_feature_components_entry( hdb, "'two', 'zeta'" );
3216     add_feature_components_entry( hdb, "'two', 'iota'" );
3217     add_feature_components_entry( hdb, "'three', 'eta'" );
3218     add_feature_components_entry( hdb, "'four', 'eta'" );
3219     add_feature_components_entry( hdb, "'five', 'eta'" );
3220     add_feature_components_entry( hdb, "'six', 'lambda'" );
3221     add_feature_components_entry( hdb, "'six', 'mu'" );
3222     add_feature_components_entry( hdb, "'six', 'nu'" );
3223     add_feature_components_entry( hdb, "'six', 'xi'" );
3224     add_feature_components_entry( hdb, "'seven', 'omicron'" );
3225     add_feature_components_entry( hdb, "'seven', 'pi'" );
3226     add_feature_components_entry( hdb, "'seven', 'rho'" );
3227     add_feature_components_entry( hdb, "'seven', 'sigma'" );
3228     add_feature_components_entry( hdb, "'eight', 'tau'" );
3229     add_feature_components_entry( hdb, "'nine', 'phi'" );
3230     add_feature_components_entry( hdb, "'ten', 'chi'" );
3231     add_feature_components_entry( hdb, "'eleven', 'psi'" );
3232     add_feature_components_entry( hdb, "'twelve', 'upsilon'" );
3233     add_feature_components_entry( hdb, "'thirteen', 'upsilon'" );
3234 
3235     create_file_table( hdb );
3236     add_file_entry( hdb, "'alpha_file', 'alpha', 'alpha.txt', 100, '', '1033', 8192, 1" );
3237     add_file_entry( hdb, "'beta_file', 'beta', 'beta.txt', 0, '', '1033', 8192, 1" );
3238     add_file_entry( hdb, "'gamma_file', 'gamma', 'gamma.txt', 0, '', '1033', 8192, 1" );
3239     add_file_entry( hdb, "'theta_file', 'theta', 'theta.txt', 0, '', '1033', 8192, 1" );
3240     add_file_entry( hdb, "'delta_file', 'delta', 'delta.txt', 0, '', '1033', 8192, 1" );
3241     add_file_entry( hdb, "'epsilon_file', 'epsilon', 'epsilon.txt', 0, '', '1033', 8192, 1" );
3242     add_file_entry( hdb, "'zeta_file', 'zeta', 'zeta.txt', 0, '', '1033', 8192, 1" );
3243     add_file_entry( hdb, "'iota_file', 'iota', 'iota.txt', 0, '', '1033', 8192, 1" );
3244 
3245     /* compressed file */
3246     add_file_entry( hdb, "'eta_file', 'eta', 'eta.txt', 0, '', '1033', 16384, 1" );
3247 
3248     add_file_entry( hdb, "'kappa_file', 'kappa', 'kappa.txt', 0, '', '1033', 8192, 1" );
3249     add_file_entry( hdb, "'lambda_file', 'lambda', 'lambda.txt', 100, '', '1033', 8192, 1" );
3250     add_file_entry( hdb, "'mu_file', 'mu', 'mu.txt', 100, '', '1033', 8192, 1" );
3251     add_file_entry( hdb, "'nu_file', 'nu', 'nu.txt', 100, '', '1033', 8192, 1" );
3252     add_file_entry( hdb, "'xi_file', 'xi', 'xi.txt', 100, '', '1033', 8192, 1" );
3253     add_file_entry( hdb, "'omicron_file', 'omicron', 'omicron.txt', 100, '', '1033', 8192, 1" );
3254     add_file_entry( hdb, "'pi_file', 'pi', 'pi.txt', 100, '', '1033', 8192, 1" );
3255     add_file_entry( hdb, "'rho_file', 'rho', 'rho.txt', 100, '', '1033', 8192, 1" );
3256     add_file_entry( hdb, "'sigma_file', 'sigma', 'sigma.txt', 100, '', '1033', 8192, 1" );
3257     add_file_entry( hdb, "'tau_file', 'tau', 'tau.txt', 100, '', '1033', 8192, 1" );
3258     add_file_entry( hdb, "'phi_file', 'phi', 'phi.txt', 100, '', '1033', 8192, 1" );
3259     add_file_entry( hdb, "'chi_file', 'chi', 'chi.txt', 100, '', '1033', 8192, 1" );
3260     add_file_entry( hdb, "'psi_file', 'psi', 'psi.txt', 100, '', '1033', 8192, 1" );
3261     add_file_entry( hdb, "'upsilon_file', 'upsilon', 'upsilon.txt', 0, '', '1033', 16384, 1" );
3262 
3263     r = MsiDatabaseCommit(hdb);
3264     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
3265 
3266     /* these properties must not be in the saved msi file */
3267     add_property_entry( hdb, "'ADDLOCAL', 'one,four'");
3268     add_property_entry( hdb, "'ADDSOURCE', 'two,three'");
3269     add_property_entry( hdb, "'REMOVE', 'six,seven'");
3270     add_property_entry( hdb, "'REINSTALL', 'eight,nine,ten'");
3271     add_property_entry( hdb, "'REINSTALLMODE', 'omus'");
3272 
3273     r = package_from_db( hdb, &hpkg );
3274     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
3275     {
3276         skip("Not enough rights to perform tests\n");
3277         DeleteFileA(msifile);
3278         return;
3279     }
3280     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3281 
3282     MsiCloseHandle(hdb);
3283 
3284     CopyFileA(msifile, msifile2, FALSE);
3285     CopyFileA(msifile, msifile3, FALSE);
3286     CopyFileA(msifile, msifile4, FALSE);
3287 
3288     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3289     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3290 
3291     r = MsiDoActionA( hpkg, "CostInitialize");
3292     ok( r == ERROR_SUCCESS, "cost init failed\n");
3293 
3294     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3295     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3296 
3297     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3298 
3299     r = MsiDoActionA( hpkg, "FileCost");
3300     ok( r == ERROR_SUCCESS, "file cost failed\n");
3301 
3302     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3303     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3304 
3305     r = MsiDoActionA( hpkg, "CostFinalize");
3306     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3307 
3308     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3309     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
3310     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3311     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3312     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3313     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3314     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3315     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3316     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3317     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3318     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3319     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3320     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3321 
3322     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3323     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
3324     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3325     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3326     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3327     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
3328     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
3329     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3330     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3331     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3332     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3333     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3334     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3335     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3336     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3337     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3338     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3339     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3340     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3341     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3342     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3343     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3344     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3345 
3346     MsiCloseHandle( hpkg );
3347 
3348     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3349 
3350     /* publish the features and components */
3351     r = MsiInstallProductA(msifile, "ADDLOCAL=one,four ADDSOURCE=two,three REMOVE=six,seven REINSTALL=eight,nine,ten");
3352     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3353 
3354     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb);
3355     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3356 
3357     /* these properties must not be in the saved msi file */
3358     add_property_entry( hdb, "'ADDLOCAL', 'one,four'");
3359     add_property_entry( hdb, "'ADDSOURCE', 'two,three'");
3360     add_property_entry( hdb, "'REMOVE', 'six,seven'");
3361     add_property_entry( hdb, "'REINSTALL', 'eight,nine,ten'");
3362 
3363     r = package_from_db( hdb, &hpkg );
3364     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3365 
3366     MsiCloseHandle(hdb);
3367 
3368     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3369     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3370 
3371     r = MsiDoActionA( hpkg, "CostInitialize");
3372     ok( r == ERROR_SUCCESS, "cost init failed\n");
3373 
3374     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3375     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3376 
3377     r = MsiDoActionA( hpkg, "FileCost");
3378     ok( r == ERROR_SUCCESS, "file cost failed\n");
3379 
3380     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3381     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3382 
3383     r = MsiDoActionA( hpkg, "CostFinalize");
3384     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3385 
3386     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3387     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3388     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3389     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3390     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3391     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3392     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3393     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3394     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3395     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3396     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3397     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3398     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3399 
3400     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3401     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3402     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3403     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3404     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3405     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3406     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3407     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3408     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3409     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3410     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3411     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3412     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3413     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3414     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3415     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3416     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3417     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3418     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3419     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3420     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3421     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3422     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3423 
3424     MsiCloseHandle(hpkg);
3425 
3426     /* uninstall the product */
3427     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3428     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3429 
3430     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3431     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3432     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3433     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3434 
3435     /* all features installed locally */
3436     r = MsiInstallProductA(msifile2, "ADDLOCAL=ALL");
3437     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3438 
3439     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3440     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3441     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3442     ok(state == INSTALLSTATE_LOCAL, "state = %d\n", state);
3443 
3444     r = MsiOpenDatabaseW(msifile2W, MSIDBOPEN_DIRECT, &hdb);
3445     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3446 
3447     /* these properties must not be in the saved msi file */
3448     add_property_entry( hdb, "'ADDLOCAL', 'one,two,three,four,five,six,seven,eight,nine,ten,twelve'");
3449 
3450     r = package_from_db( hdb, &hpkg );
3451     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3452 
3453     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3454     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3455 
3456     r = MsiDoActionA( hpkg, "CostInitialize");
3457     ok( r == ERROR_SUCCESS, "cost init failed\n");
3458 
3459     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3460     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3461 
3462     r = MsiDoActionA( hpkg, "CostFinalize");
3463     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3464 
3465     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3466     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3467     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3468     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3469     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3470     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3471     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3472     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, TRUE );
3473     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, TRUE );
3474     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, TRUE );
3475     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3476     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3477     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3478 
3479     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3480     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3481     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3482     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3483     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3484     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3485     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3486     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3487     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3488     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3489     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3490     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3491     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3492     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3493     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3494     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3495     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3496     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3497     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3498     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3499     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3500     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3501     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3502 
3503     MsiCloseHandle(hpkg);
3504 
3505     /* uninstall the product */
3506     r = MsiInstallProductA(msifile2, "REMOVE=ALL");
3507     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3508 
3509     /* all features installed from source */
3510     r = MsiInstallProductA(msifile3, "ADDSOURCE=ALL");
3511     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3512 
3513     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3514     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3515     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3516     ok(state == INSTALLSTATE_LOCAL, "state = %d\n", state);
3517 
3518     r = MsiOpenDatabaseW(msifile3W, MSIDBOPEN_DIRECT, &hdb);
3519     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3520 
3521     /* this property must not be in the saved msi file */
3522     add_property_entry( hdb, "'ADDSOURCE', 'one,two,three,four,five,six,seven,eight,nine,ten'");
3523 
3524     r = package_from_db( hdb, &hpkg );
3525     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3526 
3527     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3528     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3529 
3530     r = MsiDoActionA( hpkg, "CostInitialize");
3531     ok( r == ERROR_SUCCESS, "cost init failed\n");
3532 
3533     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3534     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3535 
3536     r = MsiDoActionA( hpkg, "FileCost");
3537     ok( r == ERROR_SUCCESS, "file cost failed\n");
3538 
3539     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3540     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3541 
3542     r = MsiDoActionA( hpkg, "CostFinalize");
3543     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3544 
3545     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3546     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3547     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3548     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3549     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3550     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3551     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3552     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3553     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3554     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3555     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3556     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3557     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3558 
3559     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3560     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3561     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3562     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3563     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3564     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3565     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3566     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3567     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3568     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3569     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3570     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3571     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3572     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3573     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3574     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3575     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3576     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3577     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3578     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3579     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3580     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3581     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3582 
3583     MsiCloseHandle(hpkg);
3584 
3585     /* reinstall the product */
3586     r = MsiInstallProductA(msifile3, "REINSTALL=ALL");
3587     is_broken = (r == ERROR_INSTALL_FAILURE);
3588     ok(r == ERROR_SUCCESS || broken(is_broken) /* win2k3 */, "Expected ERROR_SUCCESS, got %d\n", r);
3589 
3590     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3591     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3592     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3593     ok(state == INSTALLSTATE_LOCAL, "state = %d\n", state);
3594 
3595     r = MsiOpenDatabaseW(msifile4W, MSIDBOPEN_DIRECT, &hdb);
3596     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3597 
3598     /* this property must not be in the saved msi file */
3599     add_property_entry( hdb, "'ADDSOURCE', 'one,two,three,four,five,six,seven,eight,nine,ten'");
3600 
3601     r = package_from_db( hdb, &hpkg );
3602     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3603 
3604     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3605     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3606 
3607     r = MsiDoActionA( hpkg, "CostInitialize");
3608     ok( r == ERROR_SUCCESS, "cost init failed\n");
3609 
3610     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3611     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3612 
3613     r = MsiDoActionA( hpkg, "FileCost");
3614     ok( r == ERROR_SUCCESS, "file cost failed\n");
3615 
3616     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3617     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3618 
3619     r = MsiDoActionA( hpkg, "CostFinalize");
3620     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3621 
3622     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3623     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3624     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3625     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3626     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3627     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3628     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3629     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3630     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3631     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3632     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3633     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3634     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3635 
3636     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3637     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3638     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3639     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3640     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3641     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3642     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3643     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3644     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3645     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3646     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3647     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3648     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3649     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3650     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3651     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3652     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3653     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3654     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3655     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3656     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3657     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3658     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3659 
3660     MsiCloseHandle(hpkg);
3661 
3662     /* test source only install */
3663     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3664     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3665     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "one");
3666     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3667     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "two");
3668     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3669 
3670     r = MsiInstallProductA(msifile, "ADDSOURCE=one");
3671     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3672     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "one");
3673     ok(state == INSTALLSTATE_SOURCE, "state = %d\n", state);
3674     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "two");
3675     ok(state == INSTALLSTATE_ABSENT, "state = %d\n", state);
3676 
3677     /* no arguments test */
3678     cache_file_name_len = sizeof(msi_cache_file);
3679     r = MsiGetProductInfoA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}",
3680             INSTALLPROPERTY_LOCALPACKAGEA, msi_cache_file, &cache_file_name_len);
3681     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3682     r = MsiOpenDatabaseA(msi_cache_file, (const char*)MSIDBOPEN_DIRECT, &hdb);
3683     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3684 
3685     create_custom_action_table( hdb );
3686     add_custom_action_entry( hdb, "'ConditionCheck1', 19, '', 'Condition check failed (1)'" );
3687     add_custom_action_entry( hdb, "'ConditionCheck2', 19, '', 'Condition check failed (2)'" );
3688     add_custom_action_entry( hdb, "'ConditionCheck3', 19, '', 'Condition check failed (3)'" );
3689     add_custom_action_entry( hdb, "'ConditionCheck4', 19, '', 'Condition check failed (4)'" );
3690     add_custom_action_entry( hdb, "'ConditionCheck5', 19, '', 'Condition check failed (5)'" );
3691     add_custom_action_entry( hdb, "'ConditionCheck6', 19, '', 'Condition check failed (6)'" );
3692     add_custom_action_entry( hdb, "'ConditionCheck7', 19, '', 'Condition check failed (7)'" );
3693     add_custom_action_entry( hdb, "'ConditionCheck8', 19, '', 'Condition check failed (8)'" );
3694 
3695     add_install_execute_sequence_entry( hdb, "'ConditionCheck1', 'REINSTALL', '798'" );
3696     add_install_execute_sequence_entry( hdb, "'ConditionCheck2', 'NOT REMOVE AND Preselected', '799'" );
3697     add_install_execute_sequence_entry( hdb, "'ConditionCheck3', 'REINSTALL', '6598'" );
3698     add_install_execute_sequence_entry( hdb, "'ConditionCheck4', 'NOT REMOVE AND Preselected', '6599'" );
3699     add_install_execute_sequence_entry( hdb, "'ConditionCheck5', 'REINSTALL', '6601'" );
3700     add_install_execute_sequence_entry( hdb, "'ConditionCheck6', 'NOT REMOVE AND Preselected', '6601'" );
3701     /* Add "one" feature action tests */
3702     add_install_execute_sequence_entry( hdb, "'ConditionCheck7', 'NOT REMOVE AND NOT(&one=-1)', '1501'" );
3703     add_install_execute_sequence_entry( hdb, "'ConditionCheck8', 'NOT REMOVE AND NOT(&one=-1)', '6602'" );
3704     r = MsiDatabaseCommit(hdb);
3705     ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed: %d\n", r);
3706     r = package_from_db( hdb, &hpkg );
3707     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3708     MsiCloseHandle(hdb);
3709 
3710     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3711     test_feature_states( __LINE__, hpkg, "two", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3712     r = MsiDoActionA( hpkg, "CostInitialize");
3713     ok( r == ERROR_SUCCESS, "CostInitialize failed\n");
3714     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3715     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3716 
3717     r = MsiDoActionA( hpkg, "FileCost");
3718     ok( r == ERROR_SUCCESS, "FileCost failed\n");
3719     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3720     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3721 
3722     r = MsiDoActionA( hpkg, "CostFinalize");
3723     ok( r == ERROR_SUCCESS, "CostFinalize failed\n");
3724     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3725     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3726     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3727     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3728     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3729     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3730     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3731     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3732     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3733     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3734     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3735     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3736     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3737     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3738     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3739     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3740     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3741     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3742     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3743     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3744     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3745     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3746     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3747     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3748     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3749 
3750     r = MsiDoActionA( hpkg, "InstallValidate");
3751     ok( r == ERROR_SUCCESS, "InstallValidate failed %d\n", r);
3752     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3753     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3754     MsiCloseHandle( hpkg );
3755 
3756     r = MsiInstallProductA(msifile, "");
3757     ok(r == ERROR_SUCCESS || (is_broken && r == ERROR_INSTALL_FAILURE) /* win2k3 */,
3758             "Expected ERROR_SUCCESS, got %d\n", r);
3759     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "one");
3760     ok(state == INSTALLSTATE_SOURCE, "state = %d\n", state);
3761     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "two");
3762     ok(state == INSTALLSTATE_ABSENT, "state = %d\n", state);
3763 
3764     /* uninstall the product */
3765     r = MsiInstallProductA(msifile4, "REMOVE=ALL");
3766     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3767 
3768     DeleteFileA(msifile);
3769     DeleteFileA(msifile2);
3770     DeleteFileA(msifile3);
3771     DeleteFileA(msifile4);
3772 }
3773 
3774 static void test_getproperty(void)
3775 {
3776     MSIHANDLE hPackage = 0;
3777     char prop[100];
3778     static CHAR empty[] = "";
3779     DWORD size;
3780     UINT r;
3781 
3782     r = package_from_db(create_package_db(), &hPackage);
3783     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
3784     {
3785         skip("Not enough rights to perform tests\n");
3786         DeleteFileA(msifile);
3787         return;
3788     }
3789     ok( r == ERROR_SUCCESS, "Failed to create package %u\n", r );
3790 
3791     /* set the property */
3792     r = MsiSetPropertyA(hPackage, "Name", "Value");
3793     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3794 
3795     /* retrieve the size, NULL pointer */
3796     size = 0;
3797     r = MsiGetPropertyA(hPackage, "Name", NULL, &size);
3798     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3799     ok( size == 5, "Expected 5, got %d\n", size);
3800 
3801     /* retrieve the size, empty string */
3802     size = 0;
3803     r = MsiGetPropertyA(hPackage, "Name", empty, &size);
3804     ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
3805     ok( size == 5, "Expected 5, got %d\n", size);
3806 
3807     /* don't change size */
3808     r = MsiGetPropertyA(hPackage, "Name", prop, &size);
3809     ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
3810     ok( size == 5, "Expected 5, got %d\n", size);
3811     ok( !lstrcmpA(prop, "Valu"), "Expected Valu, got %s\n", prop);
3812 
3813     /* increase the size by 1 */
3814     size++;
3815     r = MsiGetPropertyA(hPackage, "Name", prop, &size);
3816     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3817     ok( size == 5, "Expected 5, got %d\n", size);
3818     ok( !lstrcmpA(prop, "Value"), "Expected Value, got %s\n", prop);
3819 
3820     r = MsiCloseHandle( hPackage);
3821     ok( r == ERROR_SUCCESS , "Failed to close package\n" );
3822     DeleteFileA(msifile);
3823 }
3824 
3825 static void test_removefiles(void)
3826 {
3827     MSIHANDLE hpkg;
3828     UINT r;
3829     MSIHANDLE hdb;
3830     INSTALLSTATE installed, action;
3831 
3832     hdb = create_package_db();
3833     ok ( hdb, "failed to create package database\n" );
3834 
3835     add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'");
3836 
3837     create_feature_table( hdb );
3838     add_feature_entry( hdb, "'one', '', '', '', 2, 1, '', 0" );
3839 
3840     create_component_table( hdb );
3841     add_component_entry( hdb, "'hydrogen', '', 'TARGETDIR', 0, '', 'hydrogen_file'" );
3842     add_component_entry( hdb, "'helium', '', 'TARGETDIR', 0, '', 'helium_file'" );
3843     add_component_entry( hdb, "'lithium', '', 'TARGETDIR', 0, '', 'lithium_file'" );
3844     add_component_entry( hdb, "'beryllium', '', 'TARGETDIR', 0, '', 'beryllium_file'" );
3845     add_component_entry( hdb, "'boron', '', 'TARGETDIR', 0, '', 'boron_file'" );
3846     add_component_entry( hdb, "'carbon', '', 'TARGETDIR', 0, '', 'carbon_file'" );
3847     add_component_entry( hdb, "'oxygen', '', 'TARGETDIR', 0, '0', 'oxygen_file'" );
3848 
3849     create_feature_components_table( hdb );
3850     add_feature_components_entry( hdb, "'one', 'hydrogen'" );
3851     add_feature_components_entry( hdb, "'one', 'helium'" );
3852     add_feature_components_entry( hdb, "'one', 'lithium'" );
3853     add_feature_components_entry( hdb, "'one', 'beryllium'" );
3854     add_feature_components_entry( hdb, "'one', 'boron'" );
3855     add_feature_components_entry( hdb, "'one', 'carbon'" );
3856     add_feature_components_entry( hdb, "'one', 'oxygen'" );
3857 
3858     create_file_table( hdb );
3859     add_file_entry( hdb, "'hydrogen_file', 'hydrogen', 'hydrogen.txt', 0, '', '1033', 8192, 1" );
3860     add_file_entry( hdb, "'helium_file', 'helium', 'helium.txt', 0, '', '1033', 8192, 1" );
3861     add_file_entry( hdb, "'lithium_file', 'lithium', 'lithium.txt', 0, '', '1033', 8192, 1" );
3862     add_file_entry( hdb, "'beryllium_file', 'beryllium', 'beryllium.txt', 0, '', '1033', 16384, 1" );
3863     add_file_entry( hdb, "'boron_file', 'boron', 'boron.txt', 0, '', '1033', 16384, 1" );
3864     add_file_entry( hdb, "'carbon_file', 'carbon', 'carbon.txt', 0, '', '1033', 16384, 1" );
3865     add_file_entry( hdb, "'oxygen_file', 'oxygen', 'oxygen.txt', 0, '', '1033', 16384, 1" );
3866 
3867     create_remove_file_table( hdb );
3868 
3869     r = package_from_db( hdb, &hpkg );
3870     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
3871     {
3872         skip("Not enough rights to perform tests\n");
3873         DeleteFileA(msifile);
3874         return;
3875     }
3876     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3877 
3878     MsiCloseHandle( hdb );
3879 
3880     create_test_file( "hydrogen.txt" );
3881     create_test_file( "helium.txt" );
3882     create_test_file( "lithium.txt" );
3883     create_test_file( "beryllium.txt" );
3884     create_test_file( "boron.txt" );
3885     create_test_file( "carbon.txt" );
3886     create_test_file( "oxygen.txt" );
3887 
3888     r = MsiSetPropertyA( hpkg, "TARGETDIR", CURR_DIR );
3889     ok( r == ERROR_SUCCESS, "set property failed\n");
3890 
3891     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3892 
3893     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3894     ok( r == ERROR_UNKNOWN_COMPONENT, "expected ERROR_UNKNOWN_COMPONENT, got %u\n", r );
3895 
3896     r = MsiDoActionA( hpkg, "CostInitialize");
3897     ok( r == ERROR_SUCCESS, "cost init failed\n");
3898 
3899     r = MsiDoActionA( hpkg, "FileCost");
3900     ok( r == ERROR_SUCCESS, "file cost failed\n");
3901 
3902     installed = action = 0xdeadbeef;
3903     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3904     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3905     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3906     ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3907 
3908     r = MsiDoActionA( hpkg, "CostFinalize");
3909     ok( r == ERROR_SUCCESS, "cost finalize failed\n");
3910 
3911     r = MsiDoActionA( hpkg, "InstallValidate");
3912     ok( r == ERROR_SUCCESS, "install validate failed\n");
3913 
3914     r = MsiSetComponentStateA( hpkg, "hydrogen", INSTALLSTATE_ABSENT );
3915     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3916 
3917     installed = action = 0xdeadbeef;
3918     r = MsiGetComponentStateA( hpkg, "hydrogen", &installed, &action );
3919     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3920     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3921     todo_wine ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3922 
3923     r = MsiSetComponentStateA( hpkg, "helium", INSTALLSTATE_LOCAL );
3924     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3925 
3926     r = MsiSetComponentStateA( hpkg, "lithium", INSTALLSTATE_SOURCE );
3927     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3928 
3929     r = MsiSetComponentStateA( hpkg, "beryllium", INSTALLSTATE_ABSENT );
3930     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3931 
3932     r = MsiSetComponentStateA( hpkg, "boron", INSTALLSTATE_LOCAL );
3933     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3934 
3935     r = MsiSetComponentStateA( hpkg, "carbon", INSTALLSTATE_SOURCE );
3936     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
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 = MsiSetComponentStateA( hpkg, "oxygen", INSTALLSTATE_ABSENT );
3945     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3946 
3947     installed = action = 0xdeadbeef;
3948     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3949     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3950     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3951     ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3952 
3953     r = MsiDoActionA( hpkg, "RemoveFiles");
3954     ok( r == ERROR_SUCCESS, "remove files failed\n");
3955 
3956     installed = action = 0xdeadbeef;
3957     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3958     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3959     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3960     ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3961 
3962     ok(DeleteFileA("hydrogen.txt"), "Expected hydrogen.txt to exist\n");
3963     ok(DeleteFileA("lithium.txt"), "Expected lithium.txt to exist\n");
3964     ok(DeleteFileA("beryllium.txt"), "Expected beryllium.txt to exist\n");
3965     ok(DeleteFileA("carbon.txt"), "Expected carbon.txt to exist\n");
3966     ok(DeleteFileA("helium.txt"), "Expected helium.txt to exist\n");
3967     ok(DeleteFileA("boron.txt"), "Expected boron.txt to exist\n");
3968     ok(DeleteFileA("oxygen.txt"), "Expected oxygen.txt to exist\n");
3969 
3970     MsiCloseHandle( hpkg );
3971     DeleteFileA(msifile);
3972 }
3973 
3974 static void test_appsearch(void)
3975 {
3976     MSIHANDLE hpkg;
3977     UINT r;
3978     MSIHANDLE hdb;
3979     CHAR prop[MAX_PATH];
3980     DWORD size;
3981     HKEY hkey;
3982     const char reg_expand_value[] = "%systemroot%\\system32\\notepad.exe";
3983 
3984     hdb = create_package_db();
3985     ok ( hdb, "failed to create package database\n" );
3986 
3987     create_appsearch_table( hdb );
3988     add_appsearch_entry( hdb, "'WEBBROWSERPROG', 'NewSignature1'" );
3989     add_appsearch_entry( hdb, "'NOTEPAD', 'NewSignature2'" );
3990     add_appsearch_entry( hdb, "'REGEXPANDVAL', 'NewSignature3'" );
3991 
3992     create_reglocator_table( hdb );
3993     add_reglocator_entry( hdb, "NewSignature1", 0, "htmlfile\\shell\\open\\command", "", 1 );
3994 
3995     r = RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Winetest_msi", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, NULL);
3996     ok( r == ERROR_SUCCESS, "Could not create key: %d.\n", r );
3997     r = RegSetValueExA(hkey, NULL, 0, REG_EXPAND_SZ, (const BYTE*)reg_expand_value, strlen(reg_expand_value) + 1);
3998     ok( r == ERROR_SUCCESS, "Could not set key value: %d.\n", r);
3999     RegCloseKey(hkey);
4000     add_reglocator_entry( hdb, "NewSignature3", 1, "Software\\Winetest_msi", "", 1 );
4001 
4002     create_drlocator_table( hdb );
4003     add_drlocator_entry( hdb, "'NewSignature2', 0, 'c:\\windows\\system32', 0" );
4004 
4005     create_signature_table( hdb );
4006     add_signature_entry( hdb, "'NewSignature1', 'FileName', '', '', '', '', '', '', ''" );
4007     add_signature_entry( hdb, "'NewSignature2', 'NOTEPAD.EXE|notepad.exe', '', '', '', '', '', '', ''" );
4008     add_signature_entry( hdb, "'NewSignature3', 'NOTEPAD.EXE|notepad.exe', '', '', '', '', '', '', ''" );
4009 
4010     r = package_from_db( hdb, &hpkg );
4011     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
4012     {
4013         skip("Not enough rights to perform tests\n");
4014         DeleteFileA(msifile);
4015         return;
4016     }
4017     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
4018     MsiCloseHandle( hdb );
4019     if (r != ERROR_SUCCESS)
4020         goto done;
4021 
4022     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4023 
4024     r = MsiDoActionA( hpkg, "AppSearch" );
4025     ok( r == ERROR_SUCCESS, "AppSearch failed: %d\n", r);
4026 
4027     size = sizeof(prop);
4028     r = MsiGetPropertyA( hpkg, "WEBBROWSERPROG", prop, &size );
4029     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
4030     ok( lstrlenA(prop) != 0, "Expected non-zero length\n");
4031 
4032     size = sizeof(prop);
4033     r = MsiGetPropertyA( hpkg, "NOTEPAD", prop, &size );
4034     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
4035 
4036     size = sizeof(prop);
4037     r = MsiGetPropertyA( hpkg, "REGEXPANDVAL", prop, &size );
4038     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
4039     ok( lstrlenA(prop) != 0, "Expected non-zero length\n");
4040 
4041 done:
4042     MsiCloseHandle( hpkg );
4043     DeleteFileA(msifile);
4044     RegDeleteKeyA(HKEY_CURRENT_USER, "Software\\Winetest_msi");
4045 }
4046 
4047 static void test_appsearch_complocator(void)
4048 {
4049     MSIHANDLE hpkg, hdb;
4050     char path[MAX_PATH], expected[MAX_PATH], prop[MAX_PATH];
4051     LPSTR usersid;
4052     DWORD size;
4053     UINT r;
4054 
4055     if (!(usersid = get_user_sid()))
4056         return;
4057 
4058     if (is_process_limited())
4059     {
4060         skip("process is limited\n");
4061         return;
4062     }
4063 
4064     create_test_file("FileName1");
4065     create_test_file("FileName4");
4066     set_component_path("FileName1", MSIINSTALLCONTEXT_MACHINE,
4067                        "{A8AE6692-96BA-4198-8399-145D7D1D0D0E}", NULL, FALSE);
4068 
4069     create_test_file("FileName2");
4070     set_component_path("FileName2", MSIINSTALLCONTEXT_USERUNMANAGED,
4071                        "{1D2CE6F3-E81C-4949-AB81-78D7DAD2AF2E}", usersid, FALSE);
4072 
4073     create_test_file("FileName3");
4074     set_component_path("FileName3", MSIINSTALLCONTEXT_USERMANAGED,
4075                        "{19E0B999-85F5-4973-A61B-DBE4D66ECB1D}", usersid, FALSE);
4076 
4077     create_test_file("FileName5");
4078     set_component_path("FileName5", MSIINSTALLCONTEXT_MACHINE,
4079                        "{F0CCA976-27A3-4808-9DDD-1A6FD50A0D5A}", NULL, TRUE);
4080 
4081     create_test_file("FileName6");
4082     set_component_path("FileName6", MSIINSTALLCONTEXT_MACHINE,
4083                        "{C0ECD96F-7898-4410-9667-194BD8C1B648}", NULL, TRUE);
4084 
4085     create_test_file("FileName7");
4086     set_component_path("FileName7", MSIINSTALLCONTEXT_MACHINE,
4087                        "{DB20F535-9C26-4127-9C2B-CC45A8B51DA1}", NULL, FALSE);
4088 
4089     /* dir is FALSE, but we're pretending it's a directory */
4090     set_component_path("IDontExist\\", MSIINSTALLCONTEXT_MACHINE,
4091                        "{91B7359B-07F2-4221-AA8D-DE102BB87A5F}", NULL, FALSE);
4092 
4093     create_file_with_version("FileName8.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4094     set_component_path("FileName8.dll", MSIINSTALLCONTEXT_MACHINE,
4095                        "{4A2E1B5B-4034-4177-833B-8CC35F1B3EF1}", NULL, FALSE);
4096 
4097     create_file_with_version("FileName9.dll", MAKELONG(1, 2), MAKELONG(3, 4));
4098     set_component_path("FileName9.dll", MSIINSTALLCONTEXT_MACHINE,
4099                        "{A204DF48-7346-4635-BA2E-66247DBAC9DF}", NULL, FALSE);
4100 
4101     create_file_with_version("FileName10.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4102     set_component_path("FileName10.dll", MSIINSTALLCONTEXT_MACHINE,
4103                        "{EC30CE73-4CF9-4908-BABD-1ED82E1515FD}", NULL, FALSE);
4104 
4105     hdb = create_package_db();
4106     ok(hdb, "Expected a valid database handle\n");
4107 
4108     create_appsearch_table(hdb);
4109     add_appsearch_entry(hdb, "'SIGPROP1', 'NewSignature1'");
4110     add_appsearch_entry(hdb, "'SIGPROP2', 'NewSignature2'");
4111     add_appsearch_entry(hdb, "'SIGPROP3', 'NewSignature3'");
4112     add_appsearch_entry(hdb, "'SIGPROP4', 'NewSignature4'");
4113     add_appsearch_entry(hdb, "'SIGPROP5', 'NewSignature5'");
4114     add_appsearch_entry(hdb, "'SIGPROP6', 'NewSignature6'");
4115     add_appsearch_entry(hdb, "'SIGPROP7', 'NewSignature7'");
4116     add_appsearch_entry(hdb, "'SIGPROP8', 'NewSignature8'");
4117     add_appsearch_entry(hdb, "'SIGPROP9', 'NewSignature9'");
4118     add_appsearch_entry(hdb, "'SIGPROP10', 'NewSignature10'");
4119     add_appsearch_entry(hdb, "'SIGPROP11', 'NewSignature11'");
4120     add_appsearch_entry(hdb, "'SIGPROP12', 'NewSignature12'");
4121 
4122     create_complocator_table(hdb);
4123 
4124     /* published component, machine, file, signature, misdbLocatorTypeFile */
4125     add_complocator_entry(hdb, "'NewSignature1', '{A8AE6692-96BA-4198-8399-145D7D1D0D0E}', 1");
4126 
4127     /* published component, user-unmanaged, file, signature, misdbLocatorTypeFile */
4128     add_complocator_entry(hdb, "'NewSignature2', '{1D2CE6F3-E81C-4949-AB81-78D7DAD2AF2E}', 1");
4129 
4130     /* published component, user-managed, file, signature, misdbLocatorTypeFile */
4131     add_complocator_entry(hdb, "'NewSignature3', '{19E0B999-85F5-4973-A61B-DBE4D66ECB1D}', 1");
4132 
4133     /* published component, machine, file, signature, misdbLocatorTypeDirectory */
4134     add_complocator_entry(hdb, "'NewSignature4', '{A8AE6692-96BA-4198-8399-145D7D1D0D0E}', 0");
4135 
4136     /* published component, machine, dir, signature, misdbLocatorTypeDirectory */
4137     add_complocator_entry(hdb, "'NewSignature5', '{F0CCA976-27A3-4808-9DDD-1A6FD50A0D5A}', 0");
4138 
4139     /* published component, machine, dir, no signature, misdbLocatorTypeDirectory */
4140     add_complocator_entry(hdb, "'NewSignature6', '{C0ECD96F-7898-4410-9667-194BD8C1B648}', 0");
4141 
4142     /* published component, machine, file, no signature, misdbLocatorTypeFile */
4143     add_complocator_entry(hdb, "'NewSignature7', '{DB20F535-9C26-4127-9C2B-CC45A8B51DA1}', 1");
4144 
4145     /* unpublished component, no signature, misdbLocatorTypeDir */
4146     add_complocator_entry(hdb, "'NewSignature8', '{FB671D5B-5083-4048-90E0-481C48D8F3A5}', 0");
4147 
4148     /* published component, no signature, dir does not exist misdbLocatorTypeDir */
4149     add_complocator_entry(hdb, "'NewSignature9', '{91B7359B-07F2-4221-AA8D-DE102BB87A5F}', 0");
4150 
4151     /* published component, signature w/ ver, misdbLocatorTypeFile */
4152     add_complocator_entry(hdb, "'NewSignature10', '{4A2E1B5B-4034-4177-833B-8CC35F1B3EF1}', 1");
4153 
4154     /* published component, signature w/ ver, ver > max, misdbLocatorTypeFile */
4155     add_complocator_entry(hdb, "'NewSignature11', '{A204DF48-7346-4635-BA2E-66247DBAC9DF}', 1");
4156 
4157     /* published component, signature w/ ver, sig->name ignored, misdbLocatorTypeFile */
4158     add_complocator_entry(hdb, "'NewSignature12', '{EC30CE73-4CF9-4908-BABD-1ED82E1515FD}', 1");
4159 
4160     create_signature_table(hdb);
4161     add_signature_entry(hdb, "'NewSignature1', 'FileName1', '', '', '', '', '', '', ''");
4162     add_signature_entry(hdb, "'NewSignature2', 'FileName2', '', '', '', '', '', '', ''");
4163     add_signature_entry(hdb, "'NewSignature3', 'FileName3', '', '', '', '', '', '', ''");
4164     add_signature_entry(hdb, "'NewSignature4', 'FileName4', '', '', '', '', '', '', ''");
4165     add_signature_entry(hdb, "'NewSignature5', 'FileName5', '', '', '', '', '', '', ''");
4166     add_signature_entry(hdb, "'NewSignature10', 'FileName8.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4167     add_signature_entry(hdb, "'NewSignature11', 'FileName9.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4168     add_signature_entry(hdb, "'NewSignature12', 'ignored', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4169 
4170     r = package_from_db(hdb, &hpkg);
4171     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
4172     {
4173         skip("Not enough rights to perform tests\n");
4174         goto error;
4175     }
4176     ok(r == ERROR_SUCCESS, "Expected a valid package handle %u\n", r);
4177 
4178     r = MsiSetPropertyA(hpkg, "SIGPROP8", "october");
4179     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4180 
4181     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4182 
4183     r = MsiDoActionA(hpkg, "AppSearch");
4184     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4185 
4186     strcpy(expected, CURR_DIR);
4187     if (is_root(CURR_DIR)) expected[2] = 0;
4188 
4189     size = MAX_PATH;
4190     sprintf(path, "%s\\FileName1", expected);
4191     r = MsiGetPropertyA(hpkg, "SIGPROP1", prop, &size);
4192     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4193     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4194 
4195     size = MAX_PATH;
4196     sprintf(path, "%s\\FileName2", expected);
4197     r = MsiGetPropertyA(hpkg, "SIGPROP2", prop, &size);
4198     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4199     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4200 
4201     size = MAX_PATH;
4202     sprintf(path, "%s\\FileName3", expected);
4203     r = MsiGetPropertyA(hpkg, "SIGPROP3", prop, &size);
4204     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4205     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4206 
4207     size = MAX_PATH;
4208     sprintf(path, "%s\\FileName4", expected);
4209     r = MsiGetPropertyA(hpkg, "SIGPROP4", prop, &size);
4210     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4211     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4212 
4213     size = MAX_PATH;
4214     sprintf(path, "%s\\FileName5", expected);
4215     r = MsiGetPropertyA(hpkg, "SIGPROP5", prop, &size);
4216     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4217     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4218 
4219     size = MAX_PATH;
4220     sprintf(path, "%s\\", expected);
4221     r = MsiGetPropertyA(hpkg, "SIGPROP6", prop, &size);
4222     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4223     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4224 
4225     size = MAX_PATH;
4226     sprintf(path, "%s\\", expected);
4227     r = MsiGetPropertyA(hpkg, "SIGPROP7", prop, &size);
4228     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4229     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4230 
4231     size = MAX_PATH;
4232     r = MsiGetPropertyA(hpkg, "SIGPROP8", prop, &size);
4233     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4234     ok(!lstrcmpA(prop, "october"), "Expected \"october\", got \"%s\"\n", prop);
4235 
4236     size = MAX_PATH;
4237     r = MsiGetPropertyA(hpkg, "SIGPROP9", prop, &size);
4238     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4239     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4240 
4241     size = MAX_PATH;
4242     sprintf(path, "%s\\FileName8.dll", expected);
4243     r = MsiGetPropertyA(hpkg, "SIGPROP10", prop, &size);
4244     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4245     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4246 
4247     size = MAX_PATH;
4248     r = MsiGetPropertyA(hpkg, "SIGPROP11", prop, &size);
4249     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4250     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4251 
4252     size = MAX_PATH;
4253     sprintf(path, "%s\\FileName10.dll", expected);
4254     r = MsiGetPropertyA(hpkg, "SIGPROP12", prop, &size);
4255     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4256     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4257 
4258     delete_component_path("{A8AE6692-96BA-4198-8399-145D7D1D0D0E}",
4259                           MSIINSTALLCONTEXT_MACHINE, NULL);
4260     delete_component_path("{1D2CE6F3-E81C-4949-AB81-78D7DAD2AF2E}",
4261                           MSIINSTALLCONTEXT_USERUNMANAGED, usersid);
4262     delete_component_path("{19E0B999-85F5-4973-A61B-DBE4D66ECB1D}",
4263                           MSIINSTALLCONTEXT_USERMANAGED, usersid);
4264     delete_component_path("{F0CCA976-27A3-4808-9DDD-1A6FD50A0D5A}",
4265                           MSIINSTALLCONTEXT_MACHINE, NULL);
4266     delete_component_path("{C0ECD96F-7898-4410-9667-194BD8C1B648}",
4267                           MSIINSTALLCONTEXT_MACHINE, NULL);
4268     delete_component_path("{DB20F535-9C26-4127-9C2B-CC45A8B51DA1}",
4269                           MSIINSTALLCONTEXT_MACHINE, NULL);
4270     delete_component_path("{91B7359B-07F2-4221-AA8D-DE102BB87A5F}",
4271                           MSIINSTALLCONTEXT_MACHINE, NULL);
4272     delete_component_path("{4A2E1B5B-4034-4177-833B-8CC35F1B3EF1}",
4273                           MSIINSTALLCONTEXT_MACHINE, NULL);
4274     delete_component_path("{A204DF48-7346-4635-BA2E-66247DBAC9DF}",
4275                           MSIINSTALLCONTEXT_MACHINE, NULL);
4276     delete_component_path("{EC30CE73-4CF9-4908-BABD-1ED82E1515FD}",
4277                           MSIINSTALLCONTEXT_MACHINE, NULL);
4278 
4279     MsiCloseHandle(hpkg);
4280 
4281 error:
4282     DeleteFileA("FileName1");
4283     DeleteFileA("FileName2");
4284     DeleteFileA("FileName3");
4285     DeleteFileA("FileName4");
4286     DeleteFileA("FileName5");
4287     DeleteFileA("FileName6");
4288     DeleteFileA("FileName7");
4289     DeleteFileA("FileName8.dll");
4290     DeleteFileA("FileName9.dll");
4291     DeleteFileA("FileName10.dll");
4292     DeleteFileA(msifile);
4293     LocalFree(usersid);
4294 }
4295 
4296 static void test_appsearch_reglocator(void)
4297 {
4298     MSIHANDLE hpkg, hdb;
4299     char path[MAX_PATH], expected[MAX_PATH], prop[MAX_PATH];
4300     DWORD binary[2], size, val;
4301     BOOL space, version, is_64bit = sizeof(void *) > sizeof(int);
4302     HKEY hklm, classes, hkcu, users;
4303     LPSTR pathdata, pathvar, ptr;
4304     LONG res;
4305     UINT r, type = 0;
4306     SYSTEM_INFO si;
4307 
4308     version = TRUE;
4309     if (!create_file_with_version("test.dll", MAKELONG(2, 1), MAKELONG(4, 3)))
4310         version = FALSE;
4311 
4312     DeleteFileA("test.dll");
4313 
4314     res = RegCreateKeyA(HKEY_CLASSES_ROOT, "Software\\Wine", &classes);
4315     if (res == ERROR_ACCESS_DENIED)
4316     {
4317         skip("Not enough rights to perform tests\n");
4318         return;
4319     }
4320     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4321 
4322     res = RegSetValueExA(classes, "Value1", 0, REG_SZ,
4323                          (const BYTE *)"regszdata", 10);
4324     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4325 
4326     res = RegCreateKeyA(HKEY_CURRENT_USER, "Software\\Wine", &hkcu);
4327     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4328 
4329     res = RegSetValueExA(hkcu, "Value1", 0, REG_SZ,
4330                          (const BYTE *)"regszdata", 10);
4331     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4332 
4333     users = 0;
4334     res = RegCreateKeyA(HKEY_USERS, "S-1-5-18\\Software\\Wine", &users);
4335     ok(res == ERROR_SUCCESS ||
4336        broken(res == ERROR_INVALID_PARAMETER),
4337        "Expected ERROR_SUCCESS, got %d\n", res);
4338 
4339     if (res == ERROR_SUCCESS)
4340     {
4341         res = RegSetValueExA(users, "Value1", 0, REG_SZ,
4342                              (const BYTE *)"regszdata", 10);
4343         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4344     }
4345 
4346     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine", &hklm);
4347     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4348 
4349     res = RegSetValueA(hklm, NULL, REG_SZ, "defvalue", 8);
4350     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4351 
4352     res = RegSetValueExA(hklm, "Value1", 0, REG_SZ,
4353                          (const BYTE *)"regszdata", 10);
4354     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4355 
4356     val = 42;
4357     res = RegSetValueExA(hklm, "Value2", 0, REG_DWORD,
4358                          (const BYTE *)&val, sizeof(DWORD));
4359     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4360 
4361     val = -42;
4362     res = RegSetValueExA(hklm, "Value3", 0, REG_DWORD,
4363                          (const BYTE *)&val, sizeof(DWORD));
4364     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4365 
4366     res = RegSetValueExA(hklm, "Value4", 0, REG_EXPAND_SZ,
4367                          (const BYTE *)"%PATH%", 7);
4368     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4369 
4370     res = RegSetValueExA(hklm, "Value5", 0, REG_EXPAND_SZ,
4371                          (const BYTE *)"my%NOVAR%", 10);
4372     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4373 
4374     res = RegSetValueExA(hklm, "Value6", 0, REG_MULTI_SZ,
4375                          (const BYTE *)"one\0two\0", 9);
4376     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4377 
4378     binary[0] = 0x1234abcd;
4379     binary[1] = 0x567890ef;
4380     res = RegSetValueExA(hklm, "Value7", 0, REG_BINARY,
4381                          (const BYTE *)binary, sizeof(binary));
4382     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4383 
4384     res = RegSetValueExA(hklm, "Value8", 0, REG_SZ,
4385                          (const BYTE *)"#regszdata", 11);
4386     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4387 
4388     strcpy(expected, CURR_DIR);
4389     if (is_root(CURR_DIR)) expected[2] = 0;
4390 
4391     create_test_file("FileName1");
4392     sprintf(path, "%s\\FileName1", expected);
4393     res = RegSetValueExA(hklm, "Value9", 0, REG_SZ,
4394                          (const BYTE *)path, lstrlenA(path) + 1);
4395     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4396 
4397     sprintf(path, "%s\\FileName2", expected);
4398     res = RegSetValueExA(hklm, "Value10", 0, REG_SZ,
4399                          (const BYTE *)path, lstrlenA(path) + 1);
4400     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4401 
4402     lstrcpyA(path, expected);
4403     res = RegSetValueExA(hklm, "Value11", 0, REG_SZ,
4404                          (const BYTE *)path, lstrlenA(path) + 1);
4405     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4406 
4407     res = RegSetValueExA(hklm, "Value12", 0, REG_SZ,
4408                          (const BYTE *)"", 1);
4409     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4410 
4411     create_file_with_version("FileName3.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4412     sprintf(path, "%s\\FileName3.dll", expected);
4413     res = RegSetValueExA(hklm, "Value13", 0, REG_SZ,
4414                          (const BYTE *)path, lstrlenA(path) + 1);
4415     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4416 
4417     create_file_with_version("FileName4.dll", MAKELONG(1, 2), MAKELONG(3, 4));
4418     sprintf(path, "%s\\FileName4.dll", expected);
4419     res = RegSetValueExA(hklm, "Value14", 0, REG_SZ,
4420                          (const BYTE *)path, lstrlenA(path) + 1);
4421     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4422 
4423     create_file_with_version("FileName5.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4424     sprintf(path, "%s\\FileName5.dll", expected);
4425     res = RegSetValueExA(hklm, "Value15", 0, REG_SZ,
4426                          (const BYTE *)path, lstrlenA(path) + 1);
4427     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4428 
4429     sprintf(path, "\"%s\\FileName1\" -option", expected);
4430     res = RegSetValueExA(hklm, "value16", 0, REG_SZ,
4431                          (const BYTE *)path, lstrlenA(path) + 1);
4432     ok( res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", res);
4433 
4434     space = strchr(expected, ' ') != NULL;
4435     sprintf(path, "%s\\FileName1 -option", expected);
4436     res = RegSetValueExA(hklm, "value17", 0, REG_SZ,
4437                          (const BYTE *)path, lstrlenA(path) + 1);
4438     ok( res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", res);
4439 
4440     hdb = create_package_db();
4441     ok(hdb, "Expected a valid database handle\n");
4442 
4443     create_appsearch_table(hdb);
4444     add_appsearch_entry(hdb, "'SIGPROP1', 'NewSignature1'");
4445     add_appsearch_entry(hdb, "'SIGPROP2', 'NewSignature2'");
4446     add_appsearch_entry(hdb, "'SIGPROP3', 'NewSignature3'");
4447     add_appsearch_entry(hdb, "'SIGPROP4', 'NewSignature4'");
4448     add_appsearch_entry(hdb, "'SIGPROP5', 'NewSignature5'");
4449     add_appsearch_entry(hdb, "'SIGPROP6', 'NewSignature6'");
4450     add_appsearch_entry(hdb, "'SIGPROP7', 'NewSignature7'");
4451     add_appsearch_entry(hdb, "'SIGPROP8', 'NewSignature8'");
4452     add_appsearch_entry(hdb, "'SIGPROP9', 'NewSignature9'");
4453     add_appsearch_entry(hdb, "'SIGPROP10', 'NewSignature10'");
4454     add_appsearch_entry(hdb, "'SIGPROP11', 'NewSignature11'");
4455     add_appsearch_entry(hdb, "'SIGPROP12', 'NewSignature12'");
4456     add_appsearch_entry(hdb, "'SIGPROP13', 'NewSignature13'");
4457     add_appsearch_entry(hdb, "'SIGPROP14', 'NewSignature14'");
4458     add_appsearch_entry(hdb, "'SIGPROP15', 'NewSignature15'");
4459     add_appsearch_entry(hdb, "'SIGPROP16', 'NewSignature16'");
4460     add_appsearch_entry(hdb, "'SIGPROP17', 'NewSignature17'");
4461     add_appsearch_entry(hdb, "'SIGPROP18', 'NewSignature18'");
4462     add_appsearch_entry(hdb, "'SIGPROP19', 'NewSignature19'");
4463     add_appsearch_entry(hdb, "'SIGPROP20', 'NewSignature20'");
4464     add_appsearch_entry(hdb, "'SIGPROP21', 'NewSignature21'");
4465     add_appsearch_entry(hdb, "'SIGPROP22', 'NewSignature22'");
4466     add_appsearch_entry(hdb, "'SIGPROP23', 'NewSignature23'");
4467     add_appsearch_entry(hdb, "'SIGPROP24', 'NewSignature24'");
4468     add_appsearch_entry(hdb, "'SIGPROP25', 'NewSignature25'");
4469     add_appsearch_entry(hdb, "'SIGPROP26', 'NewSignature26'");
4470     add_appsearch_entry(hdb, "'SIGPROP27', 'NewSignature27'");
4471     add_appsearch_entry(hdb, "'SIGPROP28', 'NewSignature28'");
4472     add_appsearch_entry(hdb, "'SIGPROP29', 'NewSignature29'");
4473     add_appsearch_entry(hdb, "'SIGPROP30', 'NewSignature30'");
4474 
4475     create_reglocator_table(hdb);
4476 
4477     type = msidbLocatorTypeRawValue;
4478     if (is_64bit)
4479         type |= msidbLocatorType64bit;
4480 
4481     /* HKLM, msidbLocatorTypeRawValue, REG_SZ */
4482     add_reglocator_entry(hdb, "NewSignature1", 2, "Software\\Wine", "Value1", type);
4483 
4484     /* HKLM, msidbLocatorTypeRawValue, positive DWORD */
4485     add_reglocator_entry(hdb, "NewSignature2", 2, "Software\\Wine", "Value2", type);
4486 
4487     /* HKLM, msidbLocatorTypeRawValue, negative DWORD */
4488     add_reglocator_entry(hdb, "NewSignature3", 2, "Software\\Wine", "Value3", type);
4489 
4490     /* HKLM, msidbLocatorTypeRawValue, REG_EXPAND_SZ */
4491     add_reglocator_entry(hdb, "NewSignature4", 2, "Software\\Wine", "Value4", type);
4492 
4493     /* HKLM, msidbLocatorTypeRawValue, REG_EXPAND_SZ */
4494     add_reglocator_entry(hdb, "NewSignature5", 2, "Software\\Wine", "Value5", type);
4495 
4496     /* HKLM, msidbLocatorTypeRawValue, REG_MULTI_SZ */
4497     add_reglocator_entry(hdb, "NewSignature6", 2, "Software\\Wine", "Value6", type);
4498 
4499     /* HKLM, msidbLocatorTypeRawValue, REG_BINARY */
4500     add_reglocator_entry(hdb, "NewSignature7", 2, "Software\\Wine", "Value7", type);
4501 
4502     /* HKLM, msidbLocatorTypeRawValue, REG_SZ first char is # */
4503     add_reglocator_entry(hdb, "NewSignature8", 2, "Software\\Wine", "Value8", type);
4504 
4505     type = msidbLocatorTypeFileName;
4506     if (is_64bit)
4507         type |= msidbLocatorType64bit;
4508 
4509     /* HKLM, msidbLocatorTypeFileName, signature, file exists */
4510     add_reglocator_entry(hdb, "NewSignature9", 2, "Software\\Wine", "Value9", type);
4511 
4512     /* HKLM, msidbLocatorTypeFileName, signature, file does not exist */
4513     add_reglocator_entry(hdb, "NewSignature10", 2, "Software\\Wine", "Value10", type);
4514 
4515     /* HKLM, msidbLocatorTypeFileName, no signature */
4516     add_reglocator_entry(hdb, "NewSignature11", 2, "Software\\Wine", "Value9", type);
4517 
4518     type = msidbLocatorTypeDirectory;
4519     if (is_64bit)
4520         type |= msidbLocatorType64bit;
4521 
4522     /* HKLM, msidbLocatorTypeDirectory, no signature, file exists */
4523     add_reglocator_entry(hdb, "NewSignature12", 2, "Software\\Wine", "Value9", type);
4524 
4525     /* HKLM, msidbLocatorTypeDirectory, no signature, directory exists */
4526     add_reglocator_entry(hdb, "NewSignature13", 2, "Software\\Wine", "Value11", type);
4527 
4528     /* HKLM, msidbLocatorTypeDirectory, signature, file exists */
4529     add_reglocator_entry(hdb, "NewSignature14", 2, "Software\\Wine", "Value9", type);
4530 
4531     type = msidbLocatorTypeRawValue;
4532     if (is_64bit)
4533         type |= msidbLocatorType64bit;
4534 
4535     /* HKCR, msidbLocatorTypeRawValue, REG_SZ */
4536     add_reglocator_entry(hdb, "NewSignature15", 0, "Software\\Wine", "Value1", type);
4537 
4538     /* HKCU, msidbLocatorTypeRawValue, REG_SZ */
4539     add_reglocator_entry(hdb, "NewSignature16", 1, "Software\\Wine", "Value1", type);
4540 
4541     /* HKU, msidbLocatorTypeRawValue, REG_SZ */
4542     add_reglocator_entry(hdb, "NewSignature17", 3, "S-1-5-18\\Software\\Wine", "Value1", type);
4543 
4544     /* HKLM, msidbLocatorTypeRawValue, REG_SZ, NULL Name */
4545     add_reglocator_entry(hdb, "NewSignature18", 2, "Software\\Wine", "", type);
4546 
4547     /* HKLM, msidbLocatorTypeRawValue, REG_SZ, key does not exist */
4548     add_reglocator_entry(hdb, "NewSignature19", 2, "Software\\IDontExist", "", type);
4549 
4550     /* HKLM, msidbLocatorTypeRawValue, REG_SZ, value is empty */
4551     add_reglocator_entry(hdb, "NewSignature20", 2, "Software\\Wine", "Value12", type);
4552 
4553     type = msidbLocatorTypeFileName;
4554     if (is_64bit)
4555         type |= msidbLocatorType64bit;
4556 
4557     /* HKLM, msidbLocatorTypeFileName, signature, file exists w/ version */
4558     add_reglocator_entry(hdb, "NewSignature21", 2, "Software\\Wine", "Value13", type);
4559 
4560     /* HKLM, msidbLocatorTypeFileName, file exists w/ version, version > max */
4561     add_reglocator_entry(hdb, "NewSignature22", 2, "Software\\Wine", "Value14", type);
4562 
4563     /* HKLM, msidbLocatorTypeFileName, file exists w/ version, sig->name ignored */
4564     add_reglocator_entry(hdb, "NewSignature23", 2, "Software\\Wine", "Value15", type);
4565 
4566     /* HKLM, msidbLocatorTypeFileName, no signature, directory exists */
4567     add_reglocator_entry(hdb, "NewSignature24", 2, "Software\\Wine", "Value11", type);
4568 
4569     /* HKLM, msidbLocatorTypeFileName, no signature, file does not exist */
4570     add_reglocator_entry(hdb, "NewSignature25", 2, "Software\\Wine", "Value10", type);
4571 
4572     type = msidbLocatorTypeDirectory;
4573     if (is_64bit)
4574         type |= msidbLocatorType64bit;
4575 
4576     /* HKLM, msidbLocatorTypeDirectory, signature, directory exists */
4577     add_reglocator_entry(hdb, "NewSignature26", 2, "Software\\Wine", "Value11", type);
4578 
4579     /* HKLM, msidbLocatorTypeDirectory, signature, file does not exist */
4580     add_reglocator_entry(hdb, "NewSignature27", 2, "Software\\Wine", "Value10", type);
4581 
4582     /* HKLM, msidbLocatorTypeDirectory, no signature, file does not exist */
4583     add_reglocator_entry(hdb, "NewSignature28", 2, "Software\\Wine", "Value10", type);
4584 
4585     type = msidbLocatorTypeFileName;
4586     if (is_64bit)
4587         type |= msidbLocatorType64bit;
4588 
4589     /* HKLM, msidbLocatorTypeFile, file exists, in quotes */
4590     add_reglocator_entry(hdb, "NewSignature29", 2, "Software\\Wine", "Value16", type);
4591 
4592     /* HKLM, msidbLocatorTypeFile, file exists, no quotes */
4593     add_reglocator_entry(hdb, "NewSignature30", 2, "Software\\Wine", "Value17", type);
4594 
4595     create_signature_table(hdb);
4596     add_signature_entry(hdb, "'NewSignature9', 'FileName1', '', '', '', '', '', '', ''");
4597     add_signature_entry(hdb, "'NewSignature10', 'FileName2', '', '', '', '', '', '', ''");
4598     add_signature_entry(hdb, "'NewSignature14', 'FileName1', '', '', '', '', '', '', ''");
4599     add_signature_entry(hdb, "'NewSignature21', 'FileName3.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4600     add_signature_entry(hdb, "'NewSignature22', 'FileName4.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4601     add_signature_entry(hdb, "'NewSignature23', 'ignored', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4602 
4603     if (!is_root(CURR_DIR))
4604     {
4605         ptr = strrchr(expected, '\\') + 1;
4606         sprintf(path, "'NewSignature26', '%s', '', '', '', '', '', '', ''", ptr);
4607         add_signature_entry(hdb, path);
4608     }
4609     add_signature_entry(hdb, "'NewSignature27', 'FileName2', '', '', '', '', '', '', ''");
4610     add_signature_entry(hdb, "'NewSignature29', 'FileName1', '', '', '', '', '', '', ''");
4611     add_signature_entry(hdb, "'NewSignature30', 'FileName1', '', '', '', '', '', '', ''");
4612 
4613     r = package_from_db(hdb, &hpkg);
4614     ok(r == ERROR_SUCCESS, "Expected a valid package handle %u\n", r);
4615 
4616     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4617 
4618     r = MsiDoActionA(hpkg, "AppSearch");
4619     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4620 
4621     size = MAX_PATH;
4622     r = MsiGetPropertyA(hpkg, "SIGPROP1", prop, &size);
4623     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4624     ok(!lstrcmpA(prop, "regszdata"),
4625        "Expected \"regszdata\", got \"%s\"\n", prop);
4626 
4627     size = MAX_PATH;
4628     r = MsiGetPropertyA(hpkg, "SIGPROP2", prop, &size);
4629     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4630     ok(!lstrcmpA(prop, "#42"), "Expected \"#42\", got \"%s\"\n", prop);
4631 
4632     size = MAX_PATH;
4633     r = MsiGetPropertyA(hpkg, "SIGPROP3", prop, &size);
4634     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4635     ok(!lstrcmpA(prop, "#-42"), "Expected \"#-42\", got \"%s\"\n", prop);
4636 
4637     memset(&si, 0, sizeof(si));
4638     if (pGetNativeSystemInfo) pGetNativeSystemInfo(&si);
4639 
4640     if (S(U(si)).wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
4641     {
4642         size = ExpandEnvironmentStringsA("%PATH%", NULL, 0);
4643         pathvar = HeapAlloc(GetProcessHeap(), 0, size);
4644         ExpandEnvironmentStringsA("%PATH%", pathvar, size);
4645 
4646         size = 0;
4647         r = MsiGetPropertyA(hpkg, "SIGPROP4", NULL, &size);
4648         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4649 
4650         pathdata = HeapAlloc(GetProcessHeap(), 0, ++size);
4651         r = MsiGetPropertyA(hpkg, "SIGPROP4", pathdata, &size);
4652         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4653         ok(!lstrcmpA(pathdata, pathvar),
4654             "Expected \"%s\", got \"%s\"\n", pathvar, pathdata);
4655 
4656         HeapFree(GetProcessHeap(), 0, pathvar);
4657         HeapFree(GetProcessHeap(), 0, pathdata);
4658     }
4659 
4660     size = MAX_PATH;
4661     r = MsiGetPropertyA(hpkg, "SIGPROP5", prop, &size);
4662     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4663     ok(!lstrcmpA(prop,
4664        "my%NOVAR%"), "Expected \"my%%NOVAR%%\", got \"%s\"\n", prop);
4665 
4666     size = MAX_PATH;
4667     r = MsiGetPropertyA(hpkg, "SIGPROP6", prop, &size);
4668     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4669     todo_wine
4670     {
4671         ok(!memcmp(prop, "\0one\0two\0\0", 10),
4672            "Expected \"\\0one\\0two\\0\\0\"\n");
4673     }
4674 
4675     size = MAX_PATH;
4676     lstrcpyA(path, "#xCDAB3412EF907856");
4677     r = MsiGetPropertyA(hpkg, "SIGPROP7", prop, &size);
4678     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4679     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4680 
4681     size = MAX_PATH;
4682     r = MsiGetPropertyA(hpkg, "SIGPROP8", prop, &size);
4683     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4684     ok(!lstrcmpA(prop, "##regszdata"),
4685        "Expected \"##regszdata\", got \"%s\"\n", prop);
4686 
4687     size = MAX_PATH;
4688     sprintf(path, "%s\\FileName1", expected);
4689     r = MsiGetPropertyA(hpkg, "SIGPROP9", prop, &size);
4690     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4691     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4692 
4693     size = MAX_PATH;
4694     r = MsiGetPropertyA(hpkg, "SIGPROP10", prop, &size);
4695     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4696     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4697 
4698     size = MAX_PATH;
4699     sprintf(path, "%s\\", expected);
4700     r = MsiGetPropertyA(hpkg, "SIGPROP11", prop, &size);
4701     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4702     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4703 
4704     size = MAX_PATH;
4705     r = MsiGetPropertyA(hpkg, "SIGPROP12", prop, &size);
4706     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4707     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4708 
4709     size = MAX_PATH;
4710     sprintf(path, "%s\\", expected);
4711     r = MsiGetPropertyA(hpkg, "SIGPROP13", prop, &size);
4712     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4713     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4714 
4715     size = MAX_PATH;
4716     r = MsiGetPropertyA(hpkg, "SIGPROP14", prop, &size);
4717     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4718     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4719 
4720     size = MAX_PATH;
4721     r = MsiGetPropertyA(hpkg, "SIGPROP15", prop, &size);
4722     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4723     ok(!lstrcmpA(prop, "regszdata"),
4724        "Expected \"regszdata\", got \"%s\"\n", prop);
4725 
4726     size = MAX_PATH;
4727     r = MsiGetPropertyA(hpkg, "SIGPROP16", prop, &size);
4728     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4729     ok(!lstrcmpA(prop, "regszdata"),
4730        "Expected \"regszdata\", got \"%s\"\n", prop);
4731 
4732     if (users)
4733     {
4734         size = MAX_PATH;
4735         r = MsiGetPropertyA(hpkg, "SIGPROP17", prop, &size);
4736         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4737         ok(!lstrcmpA(prop, "regszdata"),
4738            "Expected \"regszdata\", got \"%s\"\n", prop);
4739     }
4740 
4741     size = MAX_PATH;
4742     r = MsiGetPropertyA(hpkg, "SIGPROP18", prop, &size);
4743     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4744     ok(!lstrcmpA(prop, "defvalue"),
4745        "Expected \"defvalue\", got \"%s\"\n", prop);
4746 
4747     size = MAX_PATH;
4748     r = MsiGetPropertyA(hpkg, "SIGPROP19", prop, &size);
4749     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4750     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4751 
4752     size = MAX_PATH;
4753     r = MsiGetPropertyA(hpkg, "SIGPROP20", prop, &size);
4754     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4755     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4756 
4757     if (version)
4758     {
4759         size = MAX_PATH;
4760         sprintf(path, "%s\\FileName3.dll", expected);
4761         r = MsiGetPropertyA(hpkg, "SIGPROP21", prop, &size);
4762         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4763         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4764 
4765         size = MAX_PATH;
4766         r = MsiGetPropertyA(hpkg, "SIGPROP22", prop, &size);
4767         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4768         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4769 
4770         size = MAX_PATH;
4771         sprintf(path, "%s\\FileName5.dll", expected);
4772         r = MsiGetPropertyA(hpkg, "SIGPROP23", prop, &size);
4773         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4774         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4775     }
4776 
4777     if (!is_root(CURR_DIR))
4778     {
4779         size = MAX_PATH;
4780         lstrcpyA(path, expected);
4781         ptr = strrchr(path, '\\') + 1;
4782         *ptr = '\0';
4783         r = MsiGetPropertyA(hpkg, "SIGPROP24", prop, &size);
4784         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4785         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4786     }
4787     size = MAX_PATH;
4788     sprintf(path, "%s\\", expected);
4789     r = MsiGetPropertyA(hpkg, "SIGPROP25", prop, &size);
4790     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4791     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4792 
4793     size = MAX_PATH;
4794     r = MsiGetPropertyA(hpkg, "SIGPROP26", prop, &size);
4795     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4796     if (is_root(CURR_DIR))
4797         ok(!lstrcmpA(prop, CURR_DIR), "Expected \"%s\", got \"%s\"\n", CURR_DIR, prop);
4798     else
4799         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4800 
4801     size = MAX_PATH;
4802     r = MsiGetPropertyA(hpkg, "SIGPROP27", prop, &size);
4803     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4804     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4805 
4806     size = MAX_PATH;
4807     r = MsiGetPropertyA(hpkg, "SIGPROP28", prop, &size);
4808     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4809     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4810 
4811     size = MAX_PATH;
4812     sprintf(path, "%s\\FileName1", expected);
4813     r = MsiGetPropertyA(hpkg, "SIGPROP29", prop, &size);
4814     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4815     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4816 
4817     size = MAX_PATH;
4818     sprintf(path, "%s\\FileName1", expected);
4819     r = MsiGetPropertyA(hpkg, "SIGPROP30", prop, &size);
4820     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4821     if (space)
4822         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4823     else
4824         todo_wine ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4825 
4826     RegSetValueA(hklm, NULL, REG_SZ, "", 0);
4827     RegDeleteValueA(hklm, "Value1");
4828     RegDeleteValueA(hklm, "Value2");
4829     RegDeleteValueA(hklm, "Value3");
4830     RegDeleteValueA(hklm, "Value4");
4831     RegDeleteValueA(hklm, "Value5");
4832     RegDeleteValueA(hklm, "Value6");
4833     RegDeleteValueA(hklm, "Value7");
4834     RegDeleteValueA(hklm, "Value8");
4835     RegDeleteValueA(hklm, "Value9");
4836     RegDeleteValueA(hklm, "Value10");
4837     RegDeleteValueA(hklm, "Value11");
4838     RegDeleteValueA(hklm, "Value12");
4839     RegDeleteValueA(hklm, "Value13");
4840     RegDeleteValueA(hklm, "Value14");
4841     RegDeleteValueA(hklm, "Value15");
4842     RegDeleteValueA(hklm, "Value16");
4843     RegDeleteValueA(hklm, "Value17");
4844     RegDeleteKeyA(hklm, "");
4845     RegCloseKey(hklm);
4846 
4847     RegDeleteValueA(classes, "Value1");
4848     RegDeleteKeyA(classes, "");
4849     RegCloseKey(classes);
4850 
4851     RegDeleteValueA(hkcu, "Value1");
4852     RegDeleteKeyA(hkcu, "");
4853     RegCloseKey(hkcu);
4854 
4855     RegDeleteValueA(users, "Value1");
4856     RegDeleteKeyA(users, "");
4857     RegCloseKey(users);
4858 
4859     DeleteFileA("FileName1");
4860     DeleteFileA("FileName3.dll");
4861     DeleteFileA("FileName4.dll");
4862     DeleteFileA("FileName5.dll");
4863     MsiCloseHandle(hpkg);
4864     DeleteFileA(msifile);
4865 }
4866 
4867 static void delete_win_ini(LPCSTR file)
4868 {
4869     CHAR path[MAX_PATH];
4870 
4871     GetWindowsDirectoryA(path, MAX_PATH);
4872     lstrcatA(path, "\\");
4873     lstrcatA(path, file);
4874 
4875     DeleteFileA(path);
4876 }
4877 
4878 static void test_appsearch_inilocator(void)
4879 {
4880     MSIHANDLE hpkg, hdb;
4881     char path[MAX_PATH], expected[MAX_PATH], prop[MAX_PATH];
4882     BOOL version;
4883     LPSTR ptr;
4884     DWORD size;
4885     UINT r;
4886 
4887     version = TRUE;
4888     if (!create_file_with_version("test.dll", MAKELONG(2, 1), MAKELONG(4, 3)))
4889         version = FALSE;
4890 
4891     DeleteFileA("test.dll");
4892 
4893     WritePrivateProfileStringA("Section", "Key", "keydata,field2", "IniFile.ini");
4894 
4895     strcpy(expected, CURR_DIR);
4896     if (is_root(CURR_DIR)) expected[2] = 0;
4897 
4898     create_test_file("FileName1");
4899     sprintf(path, "%s\\FileName1", expected);
4900     WritePrivateProfileStringA("Section", "Key2", path, "IniFile.ini");
4901 
4902     WritePrivateProfileStringA("Section", "Key3", expected, "IniFile.ini");
4903 
4904     sprintf(path, "%s\\IDontExist", expected);
4905     WritePrivateProfileStringA("Section", "Key4", path, "IniFile.ini");
4906 
4907     create_file_with_version("FileName2.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4908     sprintf(path, "%s\\FileName2.dll", expected);
4909     WritePrivateProfileStringA("Section", "Key5", path, "IniFile.ini");
4910 
4911     create_file_with_version("FileName3.dll", MAKELONG(1, 2), MAKELONG(3, 4));
4912     sprintf(path, "%s\\FileName3.dll", expected);
4913     WritePrivateProfileStringA("Section", "Key6", path, "IniFile.ini");
4914 
4915     create_file_with_version("FileName4.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4916     sprintf(path, "%s\\FileName4.dll", expected);
4917     WritePrivateProfileStringA("Section", "Key7", path, "IniFile.ini");
4918 
4919     hdb = create_package_db();
4920     ok(hdb, "Expected a valid database handle\n");
4921 
4922     create_appsearch_table(hdb);
4923     add_appsearch_entry(hdb, "'SIGPROP1', 'NewSignature1'");
4924     add_appsearch_entry(hdb, "'SIGPROP2', 'NewSignature2'");
4925     add_appsearch_entry(hdb, "'SIGPROP3', 'NewSignature3'");
4926     add_appsearch_entry(hdb, "'SIGPROP4', 'NewSignature4'");
4927     add_appsearch_entry(hdb, "'SIGPROP5', 'NewSignature5'");
4928     add_appsearch_entry(hdb, "'SIGPROP6', 'NewSignature6'");
4929     add_appsearch_entry(hdb, "'SIGPROP7', 'NewSignature7'");
4930     add_appsearch_entry(hdb, "'SIGPROP8', 'NewSignature8'");
4931     add_appsearch_entry(hdb, "'SIGPROP9', 'NewSignature9'");
4932     add_appsearch_entry(hdb, "'SIGPROP10', 'NewSignature10'");
4933     add_appsearch_entry(hdb, "'SIGPROP11', 'NewSignature11'");
4934     add_appsearch_entry(hdb, "'SIGPROP12', 'NewSignature12'");
4935 
4936     create_inilocator_table(hdb);
4937 
4938     /* msidbLocatorTypeRawValue, field 1 */
4939     add_inilocator_entry(hdb, "'NewSignature1', 'IniFile.ini', 'Section', 'Key', 1, 2");
4940 
4941     /* msidbLocatorTypeRawValue, field 2 */
4942     add_inilocator_entry(hdb, "'NewSignature2', 'IniFile.ini', 'Section', 'Key', 2, 2");
4943 
4944     /* msidbLocatorTypeRawValue, entire field */
4945     add_inilocator_entry(hdb, "'NewSignature3', 'IniFile.ini', 'Section', 'Key', 0, 2");
4946 
4947     /* msidbLocatorTypeFile */
4948     add_inilocator_entry(hdb, "'NewSignature4', 'IniFile.ini', 'Section', 'Key2', 1, 1");
4949 
4950     /* msidbLocatorTypeDirectory, file */
4951     add_inilocator_entry(hdb, "'NewSignature5', 'IniFile.ini', 'Section', 'Key2', 1, 0");
4952 
4953     /* msidbLocatorTypeDirectory, directory */
4954     add_inilocator_entry(hdb, "'NewSignature6', 'IniFile.ini', 'Section', 'Key3', 1, 0");
4955 
4956     /* msidbLocatorTypeFile, file, no signature */
4957     add_inilocator_entry(hdb, "'NewSignature7', 'IniFile.ini', 'Section', 'Key2', 1, 1");
4958 
4959     /* msidbLocatorTypeFile, dir, no signature */
4960     add_inilocator_entry(hdb, "'NewSignature8', 'IniFile.ini', 'Section', 'Key3', 1, 1");
4961 
4962     /* msidbLocatorTypeFile, file does not exist */
4963     add_inilocator_entry(hdb, "'NewSignature9', 'IniFile.ini', 'Section', 'Key4', 1, 1");
4964 
4965     /* msidbLocatorTypeFile, signature with version */
4966     add_inilocator_entry(hdb, "'NewSignature10', 'IniFile.ini', 'Section', 'Key5', 1, 1");
4967 
4968     /* msidbLocatorTypeFile, signature with version, ver > max */
4969     add_inilocator_entry(hdb, "'NewSignature11', 'IniFile.ini', 'Section', 'Key6', 1, 1");
4970 
4971     /* msidbLocatorTypeFile, signature with version, sig->name ignored */
4972     add_inilocator_entry(hdb, "'NewSignature12', 'IniFile.ini', 'Section', 'Key7', 1, 1");
4973 
4974     create_signature_table(hdb);
4975     add_signature_entry(hdb, "'NewSignature4', 'FileName1', '', '', '', '', '', '', ''");
4976     add_signature_entry(hdb, "'NewSignature9', 'IDontExist', '', '', '', '', '', '', ''");
4977     add_signature_entry(hdb, "'NewSignature10', 'FileName2.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4978     add_signature_entry(hdb, "'NewSignature11', 'FileName3.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4979     add_signature_entry(hdb, "'NewSignature12', 'ignored', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4980 
4981     r = package_from_db(hdb, &hpkg);
4982     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
4983     {
4984         skip("Not enough rights to perform tests\n");
4985         goto error;
4986     }
4987     ok(r == ERROR_SUCCESS, "Expected a valid package handle %u\n", r);
4988 
4989     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4990 
4991     r = MsiDoActionA(hpkg, "AppSearch");
4992     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4993 
4994     size = MAX_PATH;
4995     r = MsiGetPropertyA(hpkg, "SIGPROP1", prop, &size);
4996     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4997     ok(!lstrcmpA(prop, "keydata"), "Expected \"keydata\", got \"%s\"\n", prop);
4998 
4999     size = MAX_PATH;
5000     r = MsiGetPropertyA(hpkg, "SIGPROP2", prop, &size);
5001     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5002     ok(!lstrcmpA(prop, "field2"), "Expected \"field2\", got \"%s\"\n", prop);
5003 
5004     size = MAX_PATH;
5005     r = MsiGetPropertyA(hpkg, "SIGPROP3", prop, &size);
5006     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5007     ok(!lstrcmpA(prop, "keydata,field2"),
5008        "Expected \"keydata,field2\", got \"%s\"\n", prop);
5009 
5010     size = MAX_PATH;
5011     sprintf(path, "%s\\FileName1", expected);
5012     r = MsiGetPropertyA(hpkg, "SIGPROP4", prop, &size);
5013     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5014     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5015 
5016     size = MAX_PATH;
5017     r = MsiGetPropertyA(hpkg, "SIGPROP5", prop, &size);
5018     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5019     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5020 
5021     size = MAX_PATH;
5022     sprintf(path, "%s\\", expected);
5023     r = MsiGetPropertyA(hpkg, "SIGPROP6", prop, &size);
5024     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5025     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5026 
5027     size = MAX_PATH;
5028     sprintf(path, "%s\\", expected);
5029     r = MsiGetPropertyA(hpkg, "SIGPROP7", prop, &size);
5030     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5031     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5032 
5033     if (!is_root(CURR_DIR))
5034     {
5035         size = MAX_PATH;
5036         lstrcpyA(path, expected);
5037         ptr = strrchr(path, '\\');
5038         *(ptr + 1) = 0;
5039         r = MsiGetPropertyA(hpkg, "SIGPROP8", prop, &size);
5040         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5041         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5042     }
5043     size = MAX_PATH;
5044     r = MsiGetPropertyA(hpkg, "SIGPROP9", prop, &size);
5045     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5046     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5047 
5048     if (version)
5049     {
5050         size = MAX_PATH;
5051         sprintf(path, "%s\\FileName2.dll", expected);
5052         r = MsiGetPropertyA(hpkg, "SIGPROP10", prop, &size);
5053         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5054         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5055 
5056         size = MAX_PATH;
5057         r = MsiGetPropertyA(hpkg, "SIGPROP11", prop, &size);
5058         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5059         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5060 
5061         size = MAX_PATH;
5062         sprintf(path, "%s\\FileName4.dll", expected);
5063         r = MsiGetPropertyA(hpkg, "SIGPROP12", prop, &size);
5064         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5065         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5066     }
5067 
5068     MsiCloseHandle(hpkg);
5069 
5070 error:
5071     delete_win_ini("IniFile.ini");
5072     DeleteFileA("FileName1");
5073     DeleteFileA("FileName2.dll");
5074     DeleteFileA("FileName3.dll");
5075     DeleteFileA("FileName4.dll");
5076     DeleteFileA(msifile);
5077 }
5078 
5079 /*
5080  * MSI AppSearch action on DrLocator table always returns absolute paths.
5081  * If a relative path was set, it returns the first absolute path that
5082  * matches or an empty string if it didn't find anything.
5083  * This helper function replicates this behaviour.
5084  */
5085 static void search_absolute_directory(LPSTR absolute, LPCSTR relative)
5086 {
5087     int i, size;
5088     DWORD attr, drives;
5089 
5090     size = lstrlenA(relative);
5091     drives = GetLogicalDrives();
5092     lstrcpyA(absolute, "A:\\");
5093     for (i = 0; i < 26; absolute[0] = '\0', i++)
5094     {
5095         if (!(drives & (1 << i)))
5096             continue;
5097 
5098         absolute[0] = 'A' + i;
5099         if (GetDriveTypeA(absolute) != DRIVE_FIXED)
5100             continue;
5101 
5102         lstrcpynA(absolute + 3, relative, size + 1);
5103         attr = GetFileAttributesA(absolute);
5104         if (attr != INVALID_FILE_ATTRIBUTES &&
5105             (attr & FILE_ATTRIBUTE_DIRECTORY))
5106         {
5107             if (absolute[3 + size - 1] != '\\')
5108                 lstrcatA(absolute, "\\");
5109             break;
5110         }
5111         absolute[3] = '\0';
5112     }
5113 }
5114 
5115 static void test_appsearch_drlocator(void)
5116 {
5117     MSIHANDLE hpkg, hdb;
5118     char path[MAX_PATH], expected[MAX_PATH], prop[MAX_PATH];
5119     BOOL version;
5120     DWORD size;
5121     UINT r;
5122 
5123     version = TRUE;
5124     if (!create_file_with_version("test.dll", MAKELONG(2, 1), MAKELONG(4, 3)))
5125         version = FALSE;
5126 
5127     DeleteFileA("test.dll");
5128 
5129     create_test_file("FileName1");
5130     CreateDirectoryA("one", NULL);
5131     CreateDirectoryA("one\\two", NULL);
5132     CreateDirectoryA("one\\two\\three", NULL);
5133     create_test_file("one\\two\\three\\FileName2");
5134     CreateDirectoryA("another", NULL);
5135     create_file_with_version("FileName3.dll", MAKELONG(2, 1), MAKELONG(4, 3));
5136     create_file_with_version("FileName4.dll", MAKELONG(1, 2), MAKELONG(3, 4));
5137     create_file_with_version("FileName5.dll", MAKELONG(2, 1), MAKELONG(4, 3));
5138 
5139     hdb = create_package_db();
5140     ok(hdb, "Expected a valid database handle\n");
5141 
5142     create_appsearch_table(hdb);
5143     add_appsearch_entry(hdb, "'SIGPROP1', 'NewSignature1'");
5144     add_appsearch_entry(hdb, "'SIGPROP2', 'NewSignature2'");
5145     add_appsearch_entry(hdb, "'SIGPROP3', 'NewSignature3'");
5146     add_appsearch_entry(hdb, "'SIGPROP4', 'NewSignature4'");
5147     add_appsearch_entry(hdb, "'SIGPROP5', 'NewSignature5'");
5148     add_appsearch_entry(hdb, "'SIGPROP6', 'NewSignature6'");
5149     add_appsearch_entry(hdb, "'SIGPROP7', 'NewSignature7'");
5150     add_appsearch_entry(hdb, "'SIGPROP8', 'NewSignature8'");
5151     add_appsearch_entry(hdb, "'SIGPROP9', 'NewSignature9'");
5152     add_appsearch_entry(hdb, "'SIGPROP10', 'NewSignature10'");
5153     add_appsearch_entry(hdb, "'SIGPROP11', 'NewSignature11'");
5154     add_appsearch_entry(hdb, "'SIGPROP13', 'NewSignature13'");
5155 
5156     create_drlocator_table(hdb);
5157 
5158     strcpy(expected, CURR_DIR);
5159     if (is_root(CURR_DIR)) expected[2] = 0;
5160 
5161     /* no parent, full path, depth 0, signature */
5162     sprintf(path, "'NewSignature1', '', '%s', 0", expected);
5163     add_drlocator_entry(hdb, path);
5164 
5165     /* no parent, full path, depth 0, no signature */
5166     sprintf(path, "'NewSignature2', '', '%s', 0", expected);
5167     add_drlocator_entry(hdb, path);
5168 
5169     /* no parent, relative path, depth 0, no signature */
5170     sprintf(path, "'NewSignature3', '', '%s', 0", expected + 3);
5171     add_drlocator_entry(hdb, path);
5172 
5173     /* no parent, full path, depth 2, signature */
5174     sprintf(path, "'NewSignature4', '', '%s', 2", expected);
5175     add_drlocator_entry(hdb, path);
5176 
5177     /* no parent, full path, depth 3, signature */
5178     sprintf(path, "'NewSignature5', '', '%s', 3", expected);
5179     add_drlocator_entry(hdb, path);
5180 
5181     /* no parent, full path, depth 1, signature is dir */
5182     sprintf(path, "'NewSignature6', '', '%s', 1", expected);
5183     add_drlocator_entry(hdb, path);
5184 
5185     /* parent is in DrLocator, relative path, depth 0, signature */
5186     sprintf(path, "'NewSignature7', 'NewSignature1', 'one\\two\\three', 1");
5187     add_drlocator_entry(hdb, path);
5188 
5189     /* no parent, full path, depth 0, signature w/ version */
5190     sprintf(path, "'NewSignature8', '', '%s', 0", expected);
5191     add_drlocator_entry(hdb, path);
5192 
5193     /* no parent, full path, depth 0, signature w/ version, ver > max */
5194     sprintf(path, "'NewSignature9', '', '%s', 0", expected);
5195     add_drlocator_entry(hdb, path);
5196 
5197     /* no parent, full path, depth 0, signature w/ version, sig->name not ignored */
5198     sprintf(path, "'NewSignature10', '', '%s', 0", expected);
5199     add_drlocator_entry(hdb, path);
5200 
5201     /* no parent, relative empty path, depth 0, no signature */
5202     sprintf(path, "'NewSignature11', '', '', 0");
5203     add_drlocator_entry(hdb, path);
5204 
5205     create_reglocator_table(hdb);
5206 
5207     /* parent */
5208     add_reglocator_entry(hdb, "NewSignature12", 2, "htmlfile\\shell\\open\\nonexistent", "", 1);
5209 
5210     /* parent is in RegLocator, no path, depth 0, no signature */
5211     sprintf(path, "'NewSignature13', 'NewSignature12', '', 0");
5212     add_drlocator_entry(hdb, path);
5213 
5214     create_signature_table(hdb);
5215     add_signature_entry(hdb, "'NewSignature1', 'FileName1', '', '', '', '', '', '', ''");
5216     add_signature_entry(hdb, "'NewSignature4', 'FileName2', '', '', '', '', '', '', ''");
5217     add_signature_entry(hdb, "'NewSignature5', 'FileName2', '', '', '', '', '', '', ''");
5218     add_signature_entry(hdb, "'NewSignature6', 'another', '', '', '', '', '', '', ''");
5219     add_signature_entry(hdb, "'NewSignature7', 'FileName2', '', '', '', '', '', '', ''");
5220     add_signature_entry(hdb, "'NewSignature8', 'FileName3.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
5221     add_signature_entry(hdb, "'NewSignature9', 'FileName4.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
5222     add_signature_entry(hdb, "'NewSignature10', 'necessary', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
5223 
5224     r = package_from_db(hdb, &hpkg);
5225     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5226     {
5227         skip("Not enough rights to perform tests\n");
5228         goto error;
5229     }
5230     ok(r == ERROR_SUCCESS, "Expected a valid package handle %u\n", r);
5231 
5232     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5233 
5234     r = MsiDoActionA(hpkg, "AppSearch");
5235     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5236 
5237     size = MAX_PATH;
5238     sprintf(path, "%s\\FileName1", expected);
5239     r = MsiGetPropertyA(hpkg, "SIGPROP1", prop, &size);
5240     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5241     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5242 
5243     size = MAX_PATH;
5244     sprintf(path, "%s\\", expected);
5245     r = MsiGetPropertyA(hpkg, "SIGPROP2", prop, &size);
5246     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5247     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5248 
5249     size = MAX_PATH;
5250     search_absolute_directory(path, expected + 3);
5251     r = MsiGetPropertyA(hpkg, "SIGPROP3", prop, &size);
5252     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5253     ok(!lstrcmpiA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5254 
5255     size = MAX_PATH;
5256     r = MsiGetPropertyA(hpkg, "SIGPROP4", prop, &size);
5257     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5258     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5259 
5260     size = MAX_PATH;
5261     sprintf(path, "%s\\one\\two\\three\\FileName2", expected);
5262     r = MsiGetPropertyA(hpkg, "SIGPROP5", prop, &size);
5263     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5264     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5265 
5266     size = MAX_PATH;
5267     r = MsiGetPropertyA(hpkg, "SIGPROP6", prop, &size);
5268     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5269     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5270 
5271     size = MAX_PATH;
5272     sprintf(path, "%s\\one\\two\\three\\FileName2", expected);
5273     r = MsiGetPropertyA(hpkg, "SIGPROP7", prop, &size);
5274     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5275     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5276 
5277     if (version)
5278     {
5279         size = MAX_PATH;
5280         sprintf(path, "%s\\FileName3.dll", expected);
5281         r = MsiGetPropertyA(hpkg, "SIGPROP8", prop, &size);
5282         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5283         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5284 
5285         size = MAX_PATH;
5286         r = MsiGetPropertyA(hpkg, "SIGPROP9", prop, &size);
5287         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5288         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5289 
5290         size = MAX_PATH;
5291         r = MsiGetPropertyA(hpkg, "SIGPROP10", prop, &size);
5292         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5293         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5294     }
5295 
5296     size = MAX_PATH;
5297     search_absolute_directory(path, "");
5298     r = MsiGetPropertyA(hpkg, "SIGPROP11", prop, &size);
5299     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5300     ok(!lstrcmpiA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5301 
5302     size = MAX_PATH;
5303     strcpy(path, "c:\\");
5304     r = MsiGetPropertyA(hpkg, "SIGPROP13", prop, &size);
5305     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5306     ok(!prop[0], "Expected \"\", got \"%s\"\n", prop);
5307 
5308     MsiCloseHandle(hpkg);
5309 
5310 error:
5311     DeleteFileA("FileName1");
5312     DeleteFileA("FileName3.dll");
5313     DeleteFileA("FileName4.dll");
5314     DeleteFileA("FileName5.dll");
5315     DeleteFileA("one\\two\\three\\FileName2");
5316     RemoveDirectoryA("one\\two\\three");
5317     RemoveDirectoryA("one\\two");
5318     RemoveDirectoryA("one");
5319     RemoveDirectoryA("another");
5320     DeleteFileA(msifile);
5321 }
5322 
5323 static void test_featureparents(void)
5324 {
5325     MSIHANDLE hpkg;
5326     UINT r;
5327     MSIHANDLE hdb;
5328 
5329     hdb = create_package_db();
5330     ok ( hdb, "failed to create package database\n" );
5331 
5332     add_directory_entry(hdb, "'TARGETDIR', '', 'SourceDir'");
5333 
5334     create_feature_table( hdb );
5335     create_component_table( hdb );
5336     create_feature_components_table( hdb );
5337     create_file_table( hdb );
5338 
5339     /* msidbFeatureAttributesFavorLocal */
5340     add_feature_entry( hdb, "'zodiac', '', '', '', 2, 1, '', 0" );
5341 
5342     /* msidbFeatureAttributesFavorSource */
5343     add_feature_entry( hdb, "'perseus', '', '', '', 2, 1, '', 1" );
5344 
5345     /* msidbFeatureAttributesFavorLocal */
5346     add_feature_entry( hdb, "'orion', '', '', '', 2, 1, '', 0" );
5347 
5348     /* msidbFeatureAttributesUIDisallowAbsent */
5349     add_feature_entry( hdb, "'lyra', '', '', '', 2, 1, '', 16" );
5350 
5351     /* disabled because of install level */
5352     add_feature_entry( hdb, "'waters', '', '', '', 15, 101, '', 9" );
5353 
5354     /* child feature of disabled feature */
5355     add_feature_entry( hdb, "'bayer', 'waters', '', '', 14, 1, '', 9" );
5356 
5357     /* component of disabled feature (install level) */
5358     add_component_entry( hdb, "'delphinus', '', 'TARGETDIR', 0, '', 'delphinus_file'" );
5359 
5360     /* component of disabled child feature (install level) */
5361     add_component_entry( hdb, "'hydrus', '', 'TARGETDIR', 0, '', 'hydrus_file'" );
5362 
5363     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesLocalOnly */
5364     add_component_entry( hdb, "'leo', '', 'TARGETDIR', 0, '', 'leo_file'" );
5365 
5366     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSourceOnly */
5367     add_component_entry( hdb, "'virgo', '', 'TARGETDIR', 1, '', 'virgo_file'" );
5368 
5369     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesOptional */
5370     add_component_entry( hdb, "'libra', '', 'TARGETDIR', 2, '', 'libra_file'" );
5371 
5372     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesLocalOnly */
5373     add_component_entry( hdb, "'cassiopeia', '', 'TARGETDIR', 0, '', 'cassiopeia_file'" );
5374 
5375     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSourceOnly */
5376     add_component_entry( hdb, "'cepheus', '', 'TARGETDIR', 1, '', 'cepheus_file'" );
5377 
5378     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesOptional */
5379     add_component_entry( hdb, "'andromeda', '', 'TARGETDIR', 2, '', 'andromeda_file'" );
5380 
5381     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesLocalOnly */
5382     add_component_entry( hdb, "'canis', '', 'TARGETDIR', 0, '', 'canis_file'" );
5383 
5384     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSourceOnly */
5385     add_component_entry( hdb, "'monoceros', '', 'TARGETDIR', 1, '', 'monoceros_file'" );
5386 
5387     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesOptional */
5388     add_component_entry( hdb, "'lepus', '', 'TARGETDIR', 2, '', 'lepus_file'" );
5389 
5390     add_feature_components_entry( hdb, "'zodiac', 'leo'" );
5391     add_feature_components_entry( hdb, "'zodiac', 'virgo'" );
5392     add_feature_components_entry( hdb, "'zodiac', 'libra'" );
5393     add_feature_components_entry( hdb, "'perseus', 'cassiopeia'" );
5394     add_feature_components_entry( hdb, "'perseus', 'cepheus'" );
5395     add_feature_components_entry( hdb, "'perseus', 'andromeda'" );
5396     add_feature_components_entry( hdb, "'orion', 'leo'" );
5397     add_feature_components_entry( hdb, "'orion', 'virgo'" );
5398     add_feature_components_entry( hdb, "'orion', 'libra'" );
5399     add_feature_components_entry( hdb, "'orion', 'cassiopeia'" );
5400     add_feature_components_entry( hdb, "'orion', 'cepheus'" );
5401     add_feature_components_entry( hdb, "'orion', 'andromeda'" );
5402     add_feature_components_entry( hdb, "'orion', 'canis'" );
5403     add_feature_components_entry( hdb, "'orion', 'monoceros'" );
5404     add_feature_components_entry( hdb, "'orion', 'lepus'" );
5405     add_feature_components_entry( hdb, "'waters', 'delphinus'" );
5406     add_feature_components_entry( hdb, "'bayer', 'hydrus'" );
5407 
5408     add_file_entry( hdb, "'leo_file', 'leo', 'leo.txt', 100, '', '1033', 8192, 1" );
5409     add_file_entry( hdb, "'virgo_file', 'virgo', 'virgo.txt', 0, '', '1033', 8192, 1" );
5410     add_file_entry( hdb, "'libra_file', 'libra', 'libra.txt', 0, '', '1033', 8192, 1" );
5411     add_file_entry( hdb, "'cassiopeia_file', 'cassiopeia', 'cassiopeia.txt', 0, '', '1033', 8192, 1" );
5412     add_file_entry( hdb, "'cepheus_file', 'cepheus', 'cepheus.txt', 0, '', '1033', 8192, 1" );
5413     add_file_entry( hdb, "'andromeda_file', 'andromeda', 'andromeda.txt', 0, '', '1033', 8192, 1" );
5414     add_file_entry( hdb, "'canis_file', 'canis', 'canis.txt', 0, '', '1033', 8192, 1" );
5415     add_file_entry( hdb, "'monoceros_file', 'monoceros', 'monoceros.txt', 0, '', '1033', 8192, 1" );
5416     add_file_entry( hdb, "'lepus_file', 'lepus', 'lepus.txt', 0, '', '1033', 8192, 1" );
5417     add_file_entry( hdb, "'delphinus_file', 'delphinus', 'delphinus.txt', 0, '', '1033', 8192, 1" );
5418     add_file_entry( hdb, "'hydrus_file', 'hydrus', 'hydrus.txt', 0, '', '1033', 8192, 1" );
5419 
5420     r = package_from_db( hdb, &hpkg );
5421     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5422     {
5423         skip("Not enough rights to perform tests\n");
5424         DeleteFileA(msifile);
5425         return;
5426     }
5427     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
5428 
5429     MsiCloseHandle( hdb );
5430 
5431     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5432 
5433     r = MsiDoActionA( hpkg, "CostInitialize");
5434     ok( r == ERROR_SUCCESS, "cost init failed\n");
5435 
5436     r = MsiDoActionA( hpkg, "FileCost");
5437     ok( r == ERROR_SUCCESS, "file cost failed\n");
5438 
5439     r = MsiDoActionA( hpkg, "CostFinalize");
5440     ok( r == ERROR_SUCCESS, "cost finalize failed\n");
5441 
5442     test_feature_states( __LINE__, hpkg, "zodiac", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
5443     test_feature_states( __LINE__, hpkg, "perseus", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
5444     test_feature_states( __LINE__, hpkg, "orion", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
5445     test_feature_states( __LINE__, hpkg, "lyra", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
5446     test_feature_states( __LINE__, hpkg, "waters", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
5447     test_feature_states( __LINE__, hpkg, "bayer", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
5448 
5449     test_component_states( __LINE__, hpkg, "leo", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5450     test_component_states( __LINE__, hpkg, "virgo", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5451     test_component_states( __LINE__, hpkg, "libra", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5452     test_component_states( __LINE__, hpkg, "cassiopeia", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5453     test_component_states( __LINE__, hpkg, "cepheus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5454     test_component_states( __LINE__, hpkg, "andromeda", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5455     test_component_states( __LINE__, hpkg, "canis", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5456     test_component_states( __LINE__, hpkg, "monoceros", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5457     test_component_states( __LINE__, hpkg, "lepus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5458     test_component_states( __LINE__, hpkg, "delphinus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5459     test_component_states( __LINE__, hpkg, "hydrus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5460 
5461     r = MsiSetFeatureStateA(hpkg, "orion", INSTALLSTATE_ABSENT);
5462     ok( r == ERROR_SUCCESS, "failed to set feature state: %d\n", r);
5463 
5464     r = MsiSetFeatureStateA(hpkg, "lyra", INSTALLSTATE_ABSENT);
5465     ok( r == ERROR_SUCCESS, "failed to set feature state: %d\n", r);
5466 
5467     r = MsiSetFeatureStateA(hpkg, "nosuchfeature", INSTALLSTATE_ABSENT);
5468     ok( r == ERROR_UNKNOWN_FEATURE, "Expected ERROR_UNKNOWN_FEATURE, got %u\n", r);
5469 
5470     test_feature_states( __LINE__, hpkg, "zodiac", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
5471     test_feature_states( __LINE__, hpkg, "perseus", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
5472     test_feature_states( __LINE__, hpkg, "orion", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_ABSENT, FALSE );
5473     test_feature_states( __LINE__, hpkg, "lyra", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_ABSENT, FALSE );
5474     test_feature_states( __LINE__, hpkg, "waters", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
5475     test_feature_states( __LINE__, hpkg, "bayer", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
5476 
5477     test_component_states( __LINE__, hpkg, "leo", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5478     test_component_states( __LINE__, hpkg, "virgo", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5479     test_component_states( __LINE__, hpkg, "libra", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5480     test_component_states( __LINE__, hpkg, "cassiopeia", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5481     test_component_states( __LINE__, hpkg, "cepheus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5482     test_component_states( __LINE__, hpkg, "andromeda", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5483     test_component_states( __LINE__, hpkg, "canis", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5484     test_component_states( __LINE__, hpkg, "monoceros", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5485     test_component_states( __LINE__, hpkg, "lepus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5486     test_component_states( __LINE__, hpkg, "delphinus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5487     test_component_states( __LINE__, hpkg, "hydrus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5488 
5489     MsiCloseHandle(hpkg);
5490     DeleteFileA(msifile);
5491 }
5492 
5493 static void test_installprops(void)
5494 {
5495     MSIHANDLE hpkg, hdb;
5496     CHAR path[MAX_PATH], buf[MAX_PATH];
5497     DWORD size, type;
5498     LANGID langid;
5499     HKEY hkey1, hkey2;
5500     int res;
5501     UINT r;
5502     REGSAM access = KEY_ALL_ACCESS;
5503     SYSTEM_INFO si;
5504     INSTALLUILEVEL uilevel;
5505 
5506     if (is_wow64)
5507         access |= KEY_WOW64_64KEY;
5508 
5509     lstrcpyA(path, CURR_DIR);
5510     if (!is_root(CURR_DIR)) lstrcatA(path, "\\");
5511     lstrcatA(path, msifile);
5512 
5513     uilevel = MsiSetInternalUI(INSTALLUILEVEL_BASIC|INSTALLUILEVEL_SOURCERESONLY, NULL);
5514 
5515     hdb = create_package_db();
5516     ok( hdb, "failed to create database\n");
5517 
5518     r = package_from_db(hdb, &hpkg);
5519     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5520     {
5521         skip("Not enough rights to perform tests\n");
5522         MsiSetInternalUI(uilevel, NULL);
5523         DeleteFileA(msifile);
5524         return;
5525     }
5526     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
5527 
5528     MsiCloseHandle(hdb);
5529 
5530     buf[0] = 0;
5531     size = MAX_PATH;
5532     r = MsiGetPropertyA(hpkg, "UILevel", buf, &size);
5533     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5534     ok( !lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
5535 
5536     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5537 
5538     buf[0] = 0;
5539     size = MAX_PATH;
5540     r = MsiGetPropertyA(hpkg, "UILevel", buf, &size);
5541     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5542     ok( !lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
5543 
5544     buf[0] = 0;
5545     size = MAX_PATH;
5546     r = MsiGetPropertyA(hpkg, "DATABASE", buf, &size);
5547     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5548     ok( !lstrcmpA(buf, path), "Expected %s, got %s\n", path, buf);
5549 
5550     RegOpenKeyA(HKEY_CURRENT_USER, "SOFTWARE\\Microsoft\\MS Setup (ACME)\\User Info", &hkey1);
5551     RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, access, &hkey2);
5552 
5553     size = MAX_PATH;
5554     type = REG_SZ;
5555     *path = '\0';
5556     if (RegQueryValueExA(hkey1, "DefName", NULL, &type, (LPBYTE)path, &size) != ERROR_SUCCESS)
5557     {
5558         size = MAX_PATH;
5559         type = REG_SZ;
5560         RegQueryValueExA(hkey2, "RegisteredOwner", NULL, &type, (LPBYTE)path, &size);
5561     }
5562 
5563     buf[0] = 0;
5564     size = MAX_PATH;
5565     r = MsiGetPropertyA(hpkg, "USERNAME", buf, &size);
5566     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5567     ok( !lstrcmpA(buf, path), "Expected %s, got %s\n", path, buf);
5568 
5569     size = MAX_PATH;
5570     type = REG_SZ;
5571     *path = '\0';
5572     if (RegQueryValueExA(hkey1, "DefCompany", NULL, &type, (LPBYTE)path, &size) != ERROR_SUCCESS)
5573     {
5574         size = MAX_PATH;
5575         type = REG_SZ;
5576         RegQueryValueExA(hkey2, "RegisteredOrganization", NULL, &type, (LPBYTE)path, &size);
5577     }
5578 
5579     if (*path)
5580     {
5581         buf[0] = 0;
5582         size = MAX_PATH;
5583         r = MsiGetPropertyA(hpkg, "COMPANYNAME", buf, &size);
5584         ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5585         ok( !lstrcmpA(buf, path), "Expected %s, got %s\n", path, buf);
5586     }
5587 
5588     buf[0] = 0;
5589     size = MAX_PATH;
5590     r = MsiGetPropertyA(hpkg, "VersionDatabase", buf, &size);
5591     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5592     trace("VersionDatabase = %s\n", buf);
5593 
5594     buf[0] = 0;
5595     size = MAX_PATH;
5596     r = MsiGetPropertyA(hpkg, "VersionMsi", buf, &size);
5597     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5598     trace("VersionMsi = %s\n", buf);
5599 
5600     buf[0] = 0;
5601     size = MAX_PATH;
5602     r = MsiGetPropertyA(hpkg, "Date", buf, &size);
5603     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5604     trace("Date = %s\n", buf);
5605 
5606     buf[0] = 0;
5607     size = MAX_PATH;
5608     r = MsiGetPropertyA(hpkg, "Time", buf, &size);
5609     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5610     trace("Time = %s\n", buf);
5611 
5612     buf[0] = 0;
5613     size = MAX_PATH;
5614     r = MsiGetPropertyA(hpkg, "PackageCode", buf, &size);
5615     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5616     trace("PackageCode = %s\n", buf);
5617 
5618     buf[0] = 0;
5619     size = MAX_PATH;
5620     r = MsiGetPropertyA(hpkg, "ComputerName", buf, &size);
5621     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
5622     trace("ComputerName = %s\n", buf);
5623 
5624     langid = GetUserDefaultLangID();
5625     sprintf(path, "%d", langid);
5626 
5627     buf[0] = 0;
5628     size = MAX_PATH;
5629     r = MsiGetPropertyA(hpkg, "UserLanguageID", buf, &size);
5630     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
5631     ok( !lstrcmpA(buf, path), "Expected \"%s\", got \"%s\"\n", path, buf);
5632 
5633     res = GetSystemMetrics(SM_CXSCREEN);
5634     buf[0] = 0;
5635     size = MAX_PATH;
5636     r = MsiGetPropertyA(hpkg, "ScreenX", buf, &size);
5637     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
5638     ok(atol(buf) == res, "Expected %d, got %ld\n", res, atol(buf));
5639 
5640     res = GetSystemMetrics(SM_CYSCREEN);
5641     buf[0] = 0;
5642     size = MAX_PATH;
5643     r = MsiGetPropertyA(hpkg, "ScreenY", buf, &size);
5644     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
5645     ok(atol(buf) == res, "Expected %d, got %ld\n", res, atol(buf));
5646 
5647     if (pGetSystemInfo && pSHGetFolderPathA)
5648     {
5649         pGetSystemInfo(&si);
5650         if (S(U(si)).wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
5651         {
5652             buf[0] = 0;
5653             size = MAX_PATH;
5654             r = MsiGetPropertyA(hpkg, "Intel", buf, &size);
5655             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5656             ok(buf[0], "property not set\n");
5657 
5658             buf[0] = 0;
5659             size = MAX_PATH;
5660             r = MsiGetPropertyA(hpkg, "MsiAMD64", buf, &size);
5661             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5662             ok(buf[0], "property not set\n");
5663 
5664             buf[0] = 0;
5665             size = MAX_PATH;
5666             r = MsiGetPropertyA(hpkg, "Msix64", buf, &size);
5667             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5668             ok(buf[0], "property not set\n");
5669 
5670             buf[0] = 0;
5671             size = MAX_PATH;
5672             r = MsiGetPropertyA(hpkg, "System64Folder", buf, &size);
5673             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5674             GetSystemDirectoryA(path, MAX_PATH);
5675             if (size) buf[size - 1] = 0;
5676             ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5677 
5678             buf[0] = 0;
5679             size = MAX_PATH;
5680             r = MsiGetPropertyA(hpkg, "SystemFolder", buf, &size);
5681             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5682             pGetSystemWow64DirectoryA(path, MAX_PATH);
5683             if (size) buf[size - 1] = 0;
5684             ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5685 
5686             buf[0] = 0;
5687             size = MAX_PATH;
5688             r = MsiGetPropertyA(hpkg, "ProgramFiles64Folder", buf, &size);
5689             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5690             pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES, NULL, 0, path);
5691             if (size) buf[size - 1] = 0;
5692             ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5693 
5694             buf[0] = 0;
5695             size = MAX_PATH;
5696             r = MsiGetPropertyA(hpkg, "ProgramFilesFolder", buf, &size);
5697             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5698             pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILESX86, NULL, 0, path);
5699             if (size) buf[size - 1] = 0;
5700             ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5701 
5702             buf[0] = 0;
5703             size = MAX_PATH;
5704             r = MsiGetPropertyA(hpkg, "CommonFiles64Folder", buf, &size);
5705             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5706             pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES_COMMON, NULL, 0, path);
5707             if (size) buf[size - 1] = 0;
5708             ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5709 
5710             buf[0] = 0;
5711             size = MAX_PATH;
5712             r = MsiGetPropertyA(hpkg, "CommonFilesFolder", buf, &size);
5713             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5714             pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES_COMMONX86, NULL, 0, path);
5715             if (size) buf[size - 1] = 0;
5716             ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5717 
5718             buf[0] = 0;
5719             size = MAX_PATH;
5720             r = MsiGetPropertyA(hpkg, "VersionNT64", buf, &size);
5721             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5722             ok(buf[0], "property not set\n");
5723         }
5724         else if (S(U(si)).wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
5725         {
5726             if (!is_wow64)
5727             {
5728                 buf[0] = 0;
5729                 size = MAX_PATH;
5730                 r = MsiGetPropertyA(hpkg, "Intel", buf, &size);
5731                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5732                 ok(buf[0], "property not set\n");
5733 
5734                 buf[0] = 0;
5735                 size = MAX_PATH;
5736                 r = MsiGetPropertyA(hpkg, "MsiAMD64", buf, &size);
5737                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5738                 ok(!buf[0], "property set\n");
5739 
5740                 buf[0] = 0;
5741                 size = MAX_PATH;
5742                 r = MsiGetPropertyA(hpkg, "Msix64", buf, &size);
5743                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5744                 ok(!buf[0], "property set\n");
5745 
5746                 buf[0] = 0;
5747                 size = MAX_PATH;
5748                 r = MsiGetPropertyA(hpkg, "System64Folder", buf, &size);
5749                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5750                 ok(!buf[0], "property set\n");
5751 
5752                 buf[0] = 0;
5753                 size = MAX_PATH;
5754                 r = MsiGetPropertyA(hpkg, "SystemFolder", buf, &size);
5755                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5756                 GetSystemDirectoryA(path, MAX_PATH);
5757                 if (size) buf[size - 1] = 0;
5758                 ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5759 
5760                 buf[0] = 0;
5761                 size = MAX_PATH;
5762                 r = MsiGetPropertyA(hpkg, "ProgramFiles64Folder", buf, &size);
5763                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5764                 ok(!buf[0], "property set\n");
5765 
5766                 buf[0] = 0;
5767                 size = MAX_PATH;
5768                 r = MsiGetPropertyA(hpkg, "ProgramFilesFolder", buf, &size);
5769                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5770                 pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES, NULL, 0, path);
5771                 if (size) buf[size - 1] = 0;
5772                 ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5773 
5774                 buf[0] = 0;
5775                 size = MAX_PATH;
5776                 r = MsiGetPropertyA(hpkg, "CommonFiles64Folder", buf, &size);
5777                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5778                 ok(!buf[0], "property set\n");
5779 
5780                 buf[0] = 0;
5781                 size = MAX_PATH;
5782                 r = MsiGetPropertyA(hpkg, "CommonFilesFolder", buf, &size);
5783                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5784                 pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES_COMMON, NULL, 0, path);
5785                 if (size) buf[size - 1] = 0;
5786                 ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5787 
5788                 buf[0] = 0;
5789                 size = MAX_PATH;
5790                 r = MsiGetPropertyA(hpkg, "VersionNT64", buf, &size);
5791                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5792                 ok(!buf[0], "property set\n");
5793             }
5794             else
5795             {
5796                 buf[0] = 0;
5797                 size = MAX_PATH;
5798                 r = MsiGetPropertyA(hpkg, "Intel", buf, &size);
5799                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5800                 ok(buf[0], "property not set\n");
5801 
5802                 buf[0] = 0;
5803                 size = MAX_PATH;
5804                 r = MsiGetPropertyA(hpkg, "MsiAMD64", buf, &size);
5805                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5806                 ok(buf[0], "property not set\n");
5807 
5808                 buf[0] = 0;
5809                 size = MAX_PATH;
5810                 r = MsiGetPropertyA(hpkg, "Msix64", buf, &size);
5811                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5812                 ok(buf[0], "property not set\n");
5813 
5814                 buf[0] = 0;
5815                 size = MAX_PATH;
5816                 r = MsiGetPropertyA(hpkg, "System64Folder", buf, &size);
5817                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5818                 GetSystemDirectoryA(path, MAX_PATH);
5819                 if (size) buf[size - 1] = 0;
5820                 ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5821 
5822                 buf[0] = 0;
5823                 size = MAX_PATH;
5824                 r = MsiGetPropertyA(hpkg, "SystemFolder", buf, &size);
5825                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5826                 pGetSystemWow64DirectoryA(path, MAX_PATH);
5827                 if (size) buf[size - 1] = 0;
5828                 ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5829 
5830                 buf[0] = 0;
5831                 size = MAX_PATH;
5832                 r = MsiGetPropertyA(hpkg, "ProgramFilesFolder64", buf, &size);
5833                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5834                 ok(!buf[0], "property set\n");
5835 
5836                 buf[0] = 0;
5837                 size = MAX_PATH;
5838                 r = MsiGetPropertyA(hpkg, "ProgramFilesFolder", buf, &size);
5839                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5840                 pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILESX86, NULL, 0, path);
5841                 if (size) buf[size - 1] = 0;
5842                 ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5843 
5844                 buf[0] = 0;
5845                 size = MAX_PATH;
5846                 r = MsiGetPropertyA(hpkg, "CommonFilesFolder64", buf, &size);
5847                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5848                 ok(!buf[0], "property set\n");
5849 
5850                 buf[0] = 0;
5851                 size = MAX_PATH;
5852                 r = MsiGetPropertyA(hpkg, "CommonFilesFolder", buf, &size);
5853                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5854                 pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES_COMMONX86, NULL, 0, path);
5855                 if (size) buf[size - 1] = 0;
5856                 ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5857 
5858                 buf[0] = 0;
5859                 size = MAX_PATH;
5860                 r = MsiGetPropertyA(hpkg, "VersionNT64", buf, &size);
5861                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5862                 ok(buf[0], "property not set\n");
5863             }
5864         }
5865     }
5866 
5867     CloseHandle(hkey1);
5868     CloseHandle(hkey2);
5869     MsiCloseHandle(hpkg);
5870     DeleteFileA(msifile);
5871     MsiSetInternalUI(uilevel, NULL);
5872 }
5873 
5874 static void test_launchconditions(void)
5875 {
5876     MSIHANDLE hpkg;
5877     MSIHANDLE hdb;
5878     UINT r;
5879 
5880     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5881 
5882     hdb = create_package_db();
5883     ok( hdb, "failed to create package database\n" );
5884 
5885     create_launchcondition_table( hdb );
5886 
5887     add_launchcondition_entry( hdb, "'X = \"1\"', 'one'" );
5888 
5889     /* invalid condition */
5890     add_launchcondition_entry( hdb, "'X != \"1\"', 'one'" );
5891 
5892     r = package_from_db( hdb, &hpkg );
5893     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5894     {
5895         skip("Not enough rights to perform tests\n");
5896         DeleteFileA(msifile);
5897         return;
5898     }
5899     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
5900 
5901     MsiCloseHandle( hdb );
5902 
5903     r = MsiSetPropertyA( hpkg, "X", "1" );
5904     ok( r == ERROR_SUCCESS, "failed to set property\n" );
5905 
5906     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5907 
5908     /* invalid conditions are ignored */
5909     r = MsiDoActionA( hpkg, "LaunchConditions" );
5910     ok( r == ERROR_SUCCESS, "cost init failed\n" );
5911 
5912     /* verify LaunchConditions still does some verification */
5913     r = MsiSetPropertyA( hpkg, "X", "2" );
5914     ok( r == ERROR_SUCCESS, "failed to set property\n" );
5915 
5916     r = MsiDoActionA( hpkg, "LaunchConditions" );
5917     ok( r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %d\n", r );
5918 
5919     MsiCloseHandle( hpkg );
5920     DeleteFileA( msifile );
5921 }
5922 
5923 static void test_ccpsearch(void)
5924 {
5925     MSIHANDLE hdb, hpkg;
5926     CHAR prop[MAX_PATH];
5927     DWORD size = MAX_PATH;
5928     UINT r;
5929 
5930     hdb = create_package_db();
5931     ok(hdb, "failed to create package database\n");
5932 
5933     create_ccpsearch_table(hdb);
5934     add_ccpsearch_entry(hdb, "'CCP_random'");
5935     add_ccpsearch_entry(hdb, "'RMCCP_random'");
5936 
5937     create_reglocator_table(hdb);
5938     add_reglocator_entry(hdb, "CCP_random", 0, "htmlfile\\shell\\open\\nonexistent", "", 1);
5939 
5940     create_drlocator_table(hdb);
5941     add_drlocator_entry(hdb, "'RMCCP_random', '', 'C:\\', '0'");
5942 
5943     create_signature_table(hdb);
5944 
5945     r = package_from_db(hdb, &hpkg);
5946     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5947     {
5948         skip("Not enough rights to perform tests\n");
5949         DeleteFileA(msifile);
5950         return;
5951     }
5952     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
5953 
5954     MsiCloseHandle(hdb);
5955 
5956     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5957 
5958     r = MsiDoActionA(hpkg, "CCPSearch");
5959     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5960 
5961     r = MsiGetPropertyA(hpkg, "CCP_Success", prop, &size);
5962     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5963     ok(!lstrcmpA(prop, "1"), "Expected 1, got %s\n", prop);
5964 
5965     MsiCloseHandle(hpkg);
5966     DeleteFileA(msifile);
5967 }
5968 
5969 static void test_complocator(void)
5970 {
5971     MSIHANDLE hdb, hpkg;
5972     UINT r;
5973     CHAR prop[MAX_PATH];
5974     CHAR expected[MAX_PATH];
5975     DWORD size = MAX_PATH;
5976 
5977     hdb = create_package_db();
5978     ok(hdb, "failed to create package database\n");
5979 
5980     create_appsearch_table(hdb);
5981     add_appsearch_entry(hdb, "'ABELISAURUS', 'abelisaurus'");
5982     add_appsearch_entry(hdb, "'BACTROSAURUS', 'bactrosaurus'");
5983     add_appsearch_entry(hdb, "'CAMELOTIA', 'camelotia'");
5984     add_appsearch_entry(hdb, "'DICLONIUS', 'diclonius'");
5985     add_appsearch_entry(hdb, "'ECHINODON', 'echinodon'");
5986     add_appsearch_entry(hdb, "'FALCARIUS', 'falcarius'");
5987     add_appsearch_entry(hdb, "'GALLIMIMUS', 'gallimimus'");
5988     add_appsearch_entry(hdb, "'HAGRYPHUS', 'hagryphus'");
5989     add_appsearch_entry(hdb, "'IGUANODON', 'iguanodon'");
5990     add_appsearch_entry(hdb, "'JOBARIA', 'jobaria'");
5991     add_appsearch_entry(hdb, "'KAKURU', 'kakuru'");
5992     add_appsearch_entry(hdb, "'LABOCANIA', 'labocania'");
5993     add_appsearch_entry(hdb, "'MEGARAPTOR', 'megaraptor'");
5994     add_appsearch_entry(hdb, "'NEOSODON', 'neosodon'");
5995     add_appsearch_entry(hdb, "'OLOROTITAN', 'olorotitan'");
5996     add_appsearch_entry(hdb, "'PANTYDRACO', 'pantydraco'");
5997 
5998     create_complocator_table(hdb);
5999     add_complocator_entry(hdb, "'abelisaurus', '{E3619EED-305A-418C-B9C7-F7D7377F0934}', 1");
6000     add_complocator_entry(hdb, "'bactrosaurus', '{D56B688D-542F-42Ef-90FD-B6DA76EE8119}', 0");
6001     add_complocator_entry(hdb, "'camelotia', '{8211BE36-2466-47E3-AFB7-6AC72E51AED2}', 1");
6002     add_complocator_entry(hdb, "'diclonius', '{5C767B20-A33C-45A4-B80B-555E512F01AE}', 0");
6003     add_complocator_entry(hdb, "'echinodon', '{A19E16C5-C75D-4699-8111-C4338C40C3CB}', 1");
6004     add_complocator_entry(hdb, "'falcarius', '{17762FA1-A7AE-4CC6-8827-62873C35361D}', 0");
6005     add_complocator_entry(hdb, "'gallimimus', '{75EBF568-C959-41E0-A99E-9050638CF5FB}', 1");
6006     add_complocator_entry(hdb, "'hagrphus', '{D4969B72-17D9-4AB6-BE49-78F2FEE857AC}', 0");
6007     add_complocator_entry(hdb, "'iguanodon', '{8E0DA02E-F6A7-4A8F-B25D-6F564C492308}', 1");
6008     add_complocator_entry(hdb, "'jobaria', '{243C22B1-8C51-4151-B9D1-1AE5265E079E}', 0");
6009     add_complocator_entry(hdb, "'kakuru', '{5D0F03BA-50BC-44F2-ABB1-72C972F4E514}', 1");
6010     add_complocator_entry(hdb, "'labocania', '{C7DDB60C-7828-4046-A6F8-699D5E92F1ED}', 0");
6011     add_complocator_entry(hdb, "'megaraptor', '{8B1034B7-BD5E-41ac-B52C-0105D3DFD74D}', 1");
6012     add_complocator_entry(hdb, "'neosodon', '{0B499649-197A-48EF-93D2-AF1C17ED6E90}', 0");
6013     add_complocator_entry(hdb, "'olorotitan', '{54E9E91F-AED2-46D5-A25A-7E50AFA24513}', 1");
6014     add_complocator_entry(hdb, "'pantydraco', '{2A989951-5565-4FA7-93A7-E800A3E67D71}', 0");
6015 
6016     create_signature_table(hdb);
6017     add_signature_entry(hdb, "'abelisaurus', 'abelisaurus', '', '', '', '', '', '', ''");
6018     add_signature_entry(hdb, "'bactrosaurus', 'bactrosaurus', '', '', '', '', '', '', ''");
6019     add_signature_entry(hdb, "'camelotia', 'camelotia', '', '', '', '', '', '', ''");
6020     add_signature_entry(hdb, "'diclonius', 'diclonius', '', '', '', '', '', '', ''");
6021     add_signature_entry(hdb, "'iguanodon', 'iguanodon', '', '', '', '', '', '', ''");
6022     add_signature_entry(hdb, "'jobaria', 'jobaria', '', '', '', '', '', '', ''");
6023     add_signature_entry(hdb, "'kakuru', 'kakuru', '', '', '', '', '', '', ''");
6024     add_signature_entry(hdb, "'labocania', 'labocania', '', '', '', '', '', '', ''");
6025 
6026     r = package_from_db(hdb, &hpkg);
6027     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
6028     {
6029         skip("Not enough rights to perform tests\n");
6030         DeleteFileA(msifile);
6031         return;
6032     }
6033     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
6034 
6035     MsiCloseHandle(hdb);
6036 
6037     create_test_file("abelisaurus");
6038     create_test_file("bactrosaurus");
6039     create_test_file("camelotia");
6040     create_test_file("diclonius");
6041     create_test_file("echinodon");
6042     create_test_file("falcarius");
6043     create_test_file("gallimimus");
6044     create_test_file("hagryphus");
6045     CreateDirectoryA("iguanodon", NULL);
6046     CreateDirectoryA("jobaria", NULL);
6047     CreateDirectoryA("kakuru", NULL);
6048     CreateDirectoryA("labocania", NULL);
6049     CreateDirectoryA("megaraptor", NULL);
6050     CreateDirectoryA("neosodon", NULL);
6051     CreateDirectoryA("olorotitan", NULL);
6052     CreateDirectoryA("pantydraco", NULL);
6053 
6054     set_component_path("abelisaurus", MSIINSTALLCONTEXT_MACHINE,
6055                        "{E3619EED-305A-418C-B9C7-F7D7377F0934}", NULL, FALSE);
6056     set_component_path("bactrosaurus", MSIINSTALLCONTEXT_MACHINE,
6057                        "{D56B688D-542F-42Ef-90FD-B6DA76EE8119}", NULL, FALSE);
6058     set_component_path("echinodon", MSIINSTALLCONTEXT_MACHINE,
6059                        "{A19E16C5-C75D-4699-8111-C4338C40C3CB}", NULL, FALSE);
6060     set_component_path("falcarius", MSIINSTALLCONTEXT_MACHINE,
6061                        "{17762FA1-A7AE-4CC6-8827-62873C35361D}", NULL, FALSE);
6062     set_component_path("iguanodon", MSIINSTALLCONTEXT_MACHINE,
6063                        "{8E0DA02E-F6A7-4A8F-B25D-6F564C492308}", NULL, FALSE);
6064     set_component_path("jobaria", MSIINSTALLCONTEXT_MACHINE,
6065                        "{243C22B1-8C51-4151-B9D1-1AE5265E079E}", NULL, FALSE);
6066     set_component_path("megaraptor", MSIINSTALLCONTEXT_MACHINE,
6067                        "{8B1034B7-BD5E-41ac-B52C-0105D3DFD74D}", NULL, FALSE);
6068     set_component_path("neosodon", MSIINSTALLCONTEXT_MACHINE,
6069                        "{0B499649-197A-48EF-93D2-AF1C17ED6E90}", NULL, FALSE);
6070 
6071     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
6072 
6073     r = MsiDoActionA(hpkg, "AppSearch");
6074     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6075 
6076     size = MAX_PATH;
6077     r = MsiGetPropertyA(hpkg, "ABELISAURUS", prop, &size);
6078     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6079 
6080     lstrcpyA(expected, CURR_DIR);
6081     if (!is_root(CURR_DIR)) lstrcatA(expected, "\\");
6082     lstrcatA(expected, "abelisaurus");
6083     ok(!lstrcmpA(prop, expected) || !lstrcmpA(prop, ""),
6084        "Expected %s or empty string, got %s\n", expected, prop);
6085 
6086     size = MAX_PATH;
6087     r = MsiGetPropertyA(hpkg, "BACTROSAURUS", prop, &size);
6088     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6089     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6090 
6091     size = MAX_PATH;
6092     r = MsiGetPropertyA(hpkg, "CAMELOTIA", prop, &size);
6093     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6094     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6095 
6096     size = MAX_PATH;
6097     r = MsiGetPropertyA(hpkg, "DICLONIUS", prop, &size);
6098     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6099     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6100 
6101     size = MAX_PATH;
6102     r = MsiGetPropertyA(hpkg, "ECHINODON", prop, &size);
6103     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6104 
6105     lstrcpyA(expected, CURR_DIR);
6106     if (!is_root(CURR_DIR)) lstrcatA(expected, "\\");
6107     ok(!lstrcmpA(prop, expected) || !lstrcmpA(prop, ""),
6108        "Expected %s or empty string, got %s\n", expected, prop);
6109 
6110     size = MAX_PATH;
6111     r = MsiGetPropertyA(hpkg, "FALCARIUS", prop, &size);
6112     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6113     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6114 
6115     size = MAX_PATH;
6116     r = MsiGetPropertyA(hpkg, "GALLIMIMUS", prop, &size);
6117     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6118     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6119 
6120     size = MAX_PATH;
6121     r = MsiGetPropertyA(hpkg, "HAGRYPHUS", prop, &size);
6122     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6123     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6124 
6125     size = MAX_PATH;
6126     r = MsiGetPropertyA(hpkg, "IGUANODON", prop, &size);
6127     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6128     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6129 
6130     size = MAX_PATH;
6131     r = MsiGetPropertyA(hpkg, "JOBARIA", prop, &size);
6132     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6133     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6134 
6135     size = MAX_PATH;
6136     r = MsiGetPropertyA(hpkg, "KAKURU", prop, &size);
6137     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6138     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6139 
6140     size = MAX_PATH;
6141     r = MsiGetPropertyA(hpkg, "LABOCANIA", prop, &size);
6142     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6143     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6144 
6145     size = MAX_PATH;
6146     r = MsiGetPropertyA(hpkg, "MEGARAPTOR", prop, &size);
6147     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6148 
6149     lstrcpyA(expected, CURR_DIR);
6150     if (!is_root(CURR_DIR)) lstrcatA(expected, "\\");
6151     ok(!lstrcmpA(prop, expected) || !lstrcmpA(prop, ""),
6152        "Expected %s or empty string, got %s\n", expected, prop);
6153 
6154     size = MAX_PATH;
6155     r = MsiGetPropertyA(hpkg, "NEOSODON", prop, &size);
6156     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6157 
6158     lstrcpyA(expected, CURR_DIR);
6159     if (!is_root(CURR_DIR)) lstrcatA(expected, "\\");
6160     lstrcatA(expected, "neosodon\\");
6161     ok(!lstrcmpA(prop, expected) || !lstrcmpA(prop, ""),
6162        "Expected %s or empty string, got %s\n", expected, prop);
6163 
6164     size = MAX_PATH;
6165     r = MsiGetPropertyA(hpkg, "OLOROTITAN", prop, &size);
6166     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6167     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6168 
6169     size = MAX_PATH;
6170     r = MsiGetPropertyA(hpkg, "PANTYDRACO", prop, &size);
6171     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6172     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6173 
6174     MsiCloseHandle(hpkg);
6175     DeleteFileA("abelisaurus");
6176     DeleteFileA("bactrosaurus");
6177     DeleteFileA("camelotia");
6178     DeleteFileA("diclonius");
6179     DeleteFileA("echinodon");
6180     DeleteFileA("falcarius");
6181     DeleteFileA("gallimimus");
6182     DeleteFileA("hagryphus");
6183     RemoveDirectoryA("iguanodon");
6184     RemoveDirectoryA("jobaria");
6185     RemoveDirectoryA("kakuru");
6186     RemoveDirectoryA("labocania");
6187     RemoveDirectoryA("megaraptor");
6188     RemoveDirectoryA("neosodon");
6189     RemoveDirectoryA("olorotitan");
6190     RemoveDirectoryA("pantydraco");
6191     delete_component_path("{E3619EED-305A-418C-B9C7-F7D7377F0934}",
6192                           MSIINSTALLCONTEXT_MACHINE, NULL);
6193     delete_component_path("{D56B688D-542F-42Ef-90FD-B6DA76EE8119}",
6194                           MSIINSTALLCONTEXT_MACHINE, NULL);
6195     delete_component_path("{A19E16C5-C75D-4699-8111-C4338C40C3CB}",
6196                           MSIINSTALLCONTEXT_MACHINE, NULL);
6197     delete_component_path("{17762FA1-A7AE-4CC6-8827-62873C35361D}",
6198                           MSIINSTALLCONTEXT_MACHINE, NULL);
6199     delete_component_path("{8E0DA02E-F6A7-4A8F-B25D-6F564C492308}",
6200                           MSIINSTALLCONTEXT_MACHINE, NULL);
6201     delete_component_path("{243C22B1-8C51-4151-B9D1-1AE5265E079E}",
6202                           MSIINSTALLCONTEXT_MACHINE, NULL);
6203     delete_component_path("{8B1034B7-BD5E-41ac-B52C-0105D3DFD74D}",
6204                           MSIINSTALLCONTEXT_MACHINE, NULL);
6205     delete_component_path("{0B499649-197A-48EF-93D2-AF1C17ED6E90}",
6206                           MSIINSTALLCONTEXT_MACHINE, NULL);
6207     DeleteFileA(msifile);
6208 }
6209 
6210 static void set_suminfo_prop(MSIHANDLE db, DWORD prop, DWORD val)
6211 {
6212     MSIHANDLE summary;
6213     UINT r;
6214 
6215     r = MsiGetSummaryInformationA(db, NULL, 1, &summary);
6216     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6217 
6218     r = MsiSummaryInfoSetPropertyA(summary, prop, VT_I4, val, NULL, NULL);
6219     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6220 
6221     r = MsiSummaryInfoPersist(summary);
6222     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
6223 
6224     MsiCloseHandle(summary);
6225 }
6226 
6227 static void test_MsiGetSourcePath(void)
6228 {
6229     MSIHANDLE hdb, hpkg;
6230     CHAR path[MAX_PATH];
6231     CHAR cwd[MAX_PATH];
6232     CHAR subsrc[MAX_PATH];
6233     CHAR sub2[MAX_PATH];
6234     DWORD size;
6235     UINT r;
6236 
6237     lstrcpyA(cwd, CURR_DIR);
6238     if (!is_root(CURR_DIR)) lstrcatA(cwd, "\\");
6239 
6240     lstrcpyA(subsrc, cwd);
6241     lstrcatA(subsrc, "subsource");
6242     lstrcatA(subsrc, "\\");
6243 
6244     lstrcpyA(sub2, subsrc);
6245     lstrcatA(sub2, "sub2");
6246     lstrcatA(sub2, "\\");
6247 
6248     /* uncompressed source */
6249 
6250     hdb = create_package_db();
6251     ok( hdb, "failed to create database\n");
6252 
6253     set_suminfo_prop(hdb, PID_WORDCOUNT, 0);
6254 
6255     add_directory_entry(hdb, "'TARGETDIR', '', 'SourceDir'");
6256     add_directory_entry(hdb, "'SubDir', 'TARGETDIR', 'subtarget:subsource'");
6257     add_directory_entry(hdb, "'SubDir2', 'SubDir', 'sub2'");
6258 
6259     r = MsiDatabaseCommit(hdb);
6260     ok(r == ERROR_SUCCESS , "Failed to commit database\n");
6261 
6262     r = package_from_db(hdb, &hpkg);
6263     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
6264     {
6265         skip("Not enough rights to perform tests\n");
6266         DeleteFileA(msifile);
6267         return;
6268     }
6269     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
6270 
6271     MsiCloseHandle(hdb);
6272 
6273     /* invalid database handle */
6274     size = MAX_PATH;
6275     lstrcpyA(path, "kiwi");
6276     r = MsiGetSourcePathA(-1, "TARGETDIR", path, &size);
6277     ok(r == ERROR_INVALID_HANDLE,
6278        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
6279     ok(!lstrcmpA(path, "kiwi"),
6280        "Expected path to be unchanged, got \"%s\"\n", path);
6281     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6282 
6283     /* NULL szFolder */
6284     size = MAX_PATH;
6285     lstrcpyA(path, "kiwi");
6286     r = MsiGetSourcePathA(hpkg, NULL, path, &size);
6287     ok(r == ERROR_INVALID_PARAMETER,
6288        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6289     ok(!lstrcmpA(path, "kiwi"),
6290        "Expected path to be unchanged, got \"%s\"\n", path);
6291     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6292 
6293     /* empty szFolder */
6294     size = MAX_PATH;
6295     lstrcpyA(path, "kiwi");
6296     r = MsiGetSourcePathA(hpkg, "", path, &size);
6297     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6298     ok(!lstrcmpA(path, "kiwi"),
6299        "Expected path to be unchanged, got \"%s\"\n", path);
6300     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6301 
6302     /* try TARGETDIR */
6303     size = MAX_PATH;
6304     lstrcpyA(path, "kiwi");
6305     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6306     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6307     ok(!lstrcmpA(path, "kiwi"),
6308        "Expected path to be unchanged, got \"%s\"\n", path);
6309     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6310 
6311     size = MAX_PATH;
6312     lstrcpyA(path, "kiwi");
6313     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6314     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6315     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6316     ok(size == 0, "Expected 0, got %d\n", size);
6317 
6318     size = MAX_PATH;
6319     lstrcpyA(path, "kiwi");
6320     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6321     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6322     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6323     ok(size == 0, "Expected 0, got %d\n", size);
6324 
6325     /* try SourceDir */
6326     size = MAX_PATH;
6327     lstrcpyA(path, "kiwi");
6328     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6329     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6330     ok(!lstrcmpA(path, "kiwi"),
6331        "Expected path to be unchanged, got \"%s\"\n", path);
6332     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6333 
6334     /* try SOURCEDIR */
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 %d\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, ""), "Expected \"\", got \"%s\"\n", path);
6349     ok(size == 0, "Expected 0, got %d\n", 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, ""), "Expected \"\", got \"%s\"\n", path);
6356     ok(size == 0, "Expected 0, got %d\n", size);
6357 
6358     /* try SubDir */
6359     size = MAX_PATH;
6360     lstrcpyA(path, "kiwi");
6361     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6362     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6363     ok(!lstrcmpA(path, "kiwi"),
6364        "Expected path to be unchanged, got \"%s\"\n", path);
6365     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6366 
6367     /* try SubDir2 */
6368     size = MAX_PATH;
6369     lstrcpyA(path, "kiwi");
6370     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6371     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6372     ok(!lstrcmpA(path, "kiwi"),
6373        "Expected path to be unchanged, got \"%s\"\n", path);
6374     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6375 
6376     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
6377 
6378     r = MsiDoActionA(hpkg, "CostInitialize");
6379     ok(r == ERROR_SUCCESS, "cost init failed\n");
6380 
6381     /* try TARGETDIR after CostInitialize */
6382     size = MAX_PATH;
6383     lstrcpyA(path, "kiwi");
6384     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6385     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6386     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6387     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6388 
6389     /* try SourceDir after CostInitialize */
6390     size = MAX_PATH;
6391     lstrcpyA(path, "kiwi");
6392     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6393     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6394     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6395     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6396 
6397     /* try SOURCEDIR after CostInitialize */
6398     size = MAX_PATH;
6399     lstrcpyA(path, "kiwi");
6400     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6401     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6402     ok(!lstrcmpA(path, "kiwi"),
6403        "Expected path to be unchanged, got \"%s\"\n", path);
6404     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6405 
6406     /* source path does not exist, but the property exists */
6407     size = MAX_PATH;
6408     lstrcpyA(path, "kiwi");
6409     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6410     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6411     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6412     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6413 
6414     size = MAX_PATH;
6415     lstrcpyA(path, "kiwi");
6416     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6417     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6418     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6419     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6420 
6421     /* try SubDir after CostInitialize */
6422     size = MAX_PATH;
6423     lstrcpyA(path, "kiwi");
6424     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6425     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6426     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6427     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
6428 
6429     /* try SubDir2 after CostInitialize */
6430     size = MAX_PATH;
6431     lstrcpyA(path, "kiwi");
6432     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6433     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6434     ok(!lstrcmpA(path, sub2), "Expected \"%s\", got \"%s\"\n", sub2, path);
6435     ok(size == lstrlenA(sub2), "Expected %d, got %d\n", lstrlenA(sub2), size);
6436 
6437     r = MsiDoActionA(hpkg, "ResolveSource");
6438     ok(r == ERROR_SUCCESS, "file cost failed\n");
6439 
6440     /* try TARGETDIR after ResolveSource */
6441     size = MAX_PATH;
6442     lstrcpyA(path, "kiwi");
6443     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6444     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6445     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6446     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6447 
6448     /* try SourceDir after ResolveSource */
6449     size = MAX_PATH;
6450     lstrcpyA(path, "kiwi");
6451     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6452     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6453     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6454     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6455 
6456     /* try SOURCEDIR after ResolveSource */
6457     size = MAX_PATH;
6458     lstrcpyA(path, "kiwi");
6459     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6460     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6461     ok(!lstrcmpA(path, "kiwi"),
6462        "Expected path to be unchanged, got \"%s\"\n", path);
6463     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6464 
6465     /* source path does not exist, but the property exists */
6466     size = MAX_PATH;
6467     lstrcpyA(path, "kiwi");
6468     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6469     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6470     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6471     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6472 
6473     size = MAX_PATH;
6474     lstrcpyA(path, "kiwi");
6475     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6476     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6477     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6478     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6479 
6480     /* try SubDir after ResolveSource */
6481     size = MAX_PATH;
6482     lstrcpyA(path, "kiwi");
6483     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6484     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6485     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6486     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
6487 
6488     /* try SubDir2 after ResolveSource */
6489     size = MAX_PATH;
6490     lstrcpyA(path, "kiwi");
6491     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6492     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6493     ok(!lstrcmpA(path, sub2), "Expected \"%s\", got \"%s\"\n", sub2, path);
6494     ok(size == lstrlenA(sub2), "Expected %d, got %d\n", lstrlenA(sub2), size);
6495 
6496     r = MsiDoActionA(hpkg, "FileCost");
6497     ok(r == ERROR_SUCCESS, "file cost failed\n");
6498 
6499     /* try TARGETDIR after FileCost */
6500     size = MAX_PATH;
6501     lstrcpyA(path, "kiwi");
6502     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6503     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6504     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6505     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6506 
6507     /* try SourceDir after FileCost */
6508     size = MAX_PATH;
6509     lstrcpyA(path, "kiwi");
6510     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6511     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6512     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6513     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6514 
6515     /* try SOURCEDIR after FileCost */
6516     size = MAX_PATH;
6517     lstrcpyA(path, "kiwi");
6518     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6519     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6520     ok(!lstrcmpA(path, "kiwi"),
6521        "Expected path to be unchanged, got \"%s\"\n", path);
6522     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6523 
6524     /* source path does not exist, but the property exists */
6525     size = MAX_PATH;
6526     lstrcpyA(path, "kiwi");
6527     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6528     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6529     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6530     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6531 
6532     size = MAX_PATH;
6533     lstrcpyA(path, "kiwi");
6534     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6535     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6536     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6537     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6538 
6539     /* try SubDir after FileCost */
6540     size = MAX_PATH;
6541     lstrcpyA(path, "kiwi");
6542     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6543     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6544     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6545     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
6546 
6547     /* try SubDir2 after FileCost */
6548     size = MAX_PATH;
6549     lstrcpyA(path, "kiwi");
6550     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6551     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6552     ok(!lstrcmpA(path, sub2), "Expected \"%s\", got \"%s\"\n", sub2, path);
6553     ok(size == lstrlenA(sub2), "Expected %d, got %d\n", lstrlenA(sub2), size);
6554 
6555     r = MsiDoActionA(hpkg, "CostFinalize");
6556     ok(r == ERROR_SUCCESS, "file cost failed\n");
6557 
6558     /* try TARGETDIR after CostFinalize */
6559     size = MAX_PATH;
6560     lstrcpyA(path, "kiwi");
6561     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6562     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6563     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6564     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6565 
6566     /* try SourceDir after CostFinalize */
6567     size = MAX_PATH;
6568     lstrcpyA(path, "kiwi");
6569     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6570     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6571     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6572     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6573 
6574     /* try SOURCEDIR after CostFinalize */
6575     size = MAX_PATH;
6576     lstrcpyA(path, "kiwi");
6577     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6578     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6579     ok(!lstrcmpA(path, "kiwi"),
6580        "Expected path to be unchanged, got \"%s\"\n", path);
6581     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6582 
6583     /* source path does not exist, but the property exists */
6584     size = MAX_PATH;
6585     lstrcpyA(path, "kiwi");
6586     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6587     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6588     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6589     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6590 
6591     size = MAX_PATH;
6592     lstrcpyA(path, "kiwi");
6593     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6594     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6595     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6596     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6597 
6598     /* try SubDir after CostFinalize */
6599     size = MAX_PATH;
6600     lstrcpyA(path, "kiwi");
6601     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6602     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6603     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6604     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
6605 
6606     /* try SubDir2 after CostFinalize */
6607     size = MAX_PATH;
6608     lstrcpyA(path, "kiwi");
6609     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6610     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6611     ok(!lstrcmpA(path, sub2), "Expected \"%s\", got \"%s\"\n", sub2, path);
6612     ok(size == lstrlenA(sub2), "Expected %d, got %d\n", lstrlenA(sub2), size);
6613 
6614     /* nonexistent directory */
6615     size = MAX_PATH;
6616     lstrcpyA(path, "kiwi");
6617     r = MsiGetSourcePathA(hpkg, "IDontExist", path, &size);
6618     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6619     ok(!lstrcmpA(path, "kiwi"),
6620        "Expected path to be unchanged, got \"%s\"\n", path);
6621     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6622 
6623     /* NULL szPathBuf */
6624     size = MAX_PATH;
6625     r = MsiGetSourcePathA(hpkg, "SourceDir", NULL, &size);
6626     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6627     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6628 
6629     /* NULL pcchPathBuf */
6630     lstrcpyA(path, "kiwi");
6631     r = MsiGetSourcePathA(hpkg, "SourceDir", path, NULL);
6632     ok(r == ERROR_INVALID_PARAMETER,
6633        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6634     ok(!lstrcmpA(path, "kiwi"),
6635        "Expected path to be unchanged, got \"%s\"\n", path);
6636 
6637     /* pcchPathBuf is 0 */
6638     size = 0;
6639     lstrcpyA(path, "kiwi");
6640     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6641     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
6642     ok(!lstrcmpA(path, "kiwi"),
6643        "Expected path to be unchanged, got \"%s\"\n", path);
6644     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6645 
6646     /* pcchPathBuf does not have room for NULL terminator */
6647     size = lstrlenA(cwd);
6648     lstrcpyA(path, "kiwi");
6649     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6650     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
6651     ok(!strncmp(path, cwd, lstrlenA(cwd) - 1),
6652        "Expected path with no backslash, got \"%s\"\n", path);
6653     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6654 
6655     /* pcchPathBuf has room for NULL terminator */
6656     size = lstrlenA(cwd) + 1;
6657     lstrcpyA(path, "kiwi");
6658     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6659     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6660     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6661     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6662 
6663     /* remove property */
6664     r = MsiSetPropertyA(hpkg, "SourceDir", NULL);
6665     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6666 
6667     /* try SourceDir again */
6668     size = MAX_PATH;
6669     lstrcpyA(path, "kiwi");
6670     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6671     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6672     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6673     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6674 
6675     /* set property to a valid directory */
6676     r = MsiSetPropertyA(hpkg, "SOURCEDIR", cwd);
6677     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6678 
6679     /* try SOURCEDIR again */
6680     size = MAX_PATH;
6681     lstrcpyA(path, "kiwi");
6682     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", 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 %d\n", size);
6687 
6688     MsiCloseHandle(hpkg);
6689 
6690     /* compressed source */
6691 
6692     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb);
6693     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6694 
6695     set_suminfo_prop(hdb, PID_WORDCOUNT, msidbSumInfoSourceTypeCompressed);
6696 
6697     r = package_from_db(hdb, &hpkg);
6698     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
6699 
6700     /* try TARGETDIR */
6701     size = MAX_PATH;
6702     lstrcpyA(path, "kiwi");
6703     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6704     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6705     ok(!lstrcmpA(path, "kiwi"),
6706        "Expected path to be unchanged, got \"%s\"\n", path);
6707     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6708 
6709     /* try SourceDir */
6710     size = MAX_PATH;
6711     lstrcpyA(path, "kiwi");
6712     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6713     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6714     ok(!lstrcmpA(path, "kiwi"),
6715        "Expected path to be unchanged, got \"%s\"\n", path);
6716     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6717 
6718     /* try SOURCEDIR */
6719     size = MAX_PATH;
6720     lstrcpyA(path, "kiwi");
6721     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6722     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6723     ok(!lstrcmpA(path, "kiwi"),
6724        "Expected path to be unchanged, got \"%s\"\n", path);
6725     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6726 
6727     /* source path nor the property exist */
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, ""), "Expected \"\", got \"%s\"\n", path);
6733     ok(size == 0, "Expected 0, got %d\n", 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, ""), "Expected \"\", got \"%s\"\n", path);
6740     ok(size == 0, "Expected 0, got %d\n", size);
6741 
6742     /* try SubDir */
6743     size = MAX_PATH;
6744     lstrcpyA(path, "kiwi");
6745     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6746     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6747     ok(!lstrcmpA(path, "kiwi"),
6748        "Expected path to be unchanged, got \"%s\"\n", path);
6749     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6750 
6751     /* try SubDir2 */
6752     size = MAX_PATH;
6753     lstrcpyA(path, "kiwi");
6754     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6755     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6756     ok(!lstrcmpA(path, "kiwi"),
6757        "Expected path to be unchanged, got \"%s\"\n", path);
6758     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6759 
6760     r = MsiDoActionA(hpkg, "CostInitialize");
6761     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6762 
6763     /* try TARGETDIR after CostInitialize */
6764     size = MAX_PATH;
6765     lstrcpyA(path, "kiwi");
6766     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6767     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6768     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6769     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6770 
6771     /* try SourceDir after CostInitialize */
6772     size = MAX_PATH;
6773     lstrcpyA(path, "kiwi");
6774     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6775     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6776     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6777     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6778 
6779     /* try SOURCEDIR after CostInitialize */
6780     size = MAX_PATH;
6781     lstrcpyA(path, "kiwi");
6782     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6783     todo_wine
6784     {
6785         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6786         ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6787         ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6788     }
6789 
6790     /* source path does not exist, but the property exists */
6791     size = MAX_PATH;
6792     lstrcpyA(path, "kiwi");
6793     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6794     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6795     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6796     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6797 
6798     size = MAX_PATH;
6799     lstrcpyA(path, "kiwi");
6800     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6801     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6802     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6803     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6804 
6805     /* try SubDir after CostInitialize */
6806     size = MAX_PATH;
6807     lstrcpyA(path, "kiwi");
6808     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6809     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6810     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6811     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6812 
6813     /* try SubDir2 after CostInitialize */
6814     size = MAX_PATH;
6815     lstrcpyA(path, "kiwi");
6816     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6817     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6818     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6819     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6820 
6821     r = MsiDoActionA(hpkg, "ResolveSource");
6822     ok(r == ERROR_SUCCESS, "file cost failed\n");
6823 
6824     /* try TARGETDIR after ResolveSource */
6825     size = MAX_PATH;
6826     lstrcpyA(path, "kiwi");
6827     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6828     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6829     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6830     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6831 
6832     /* try SourceDir after ResolveSource */
6833     size = MAX_PATH;
6834     lstrcpyA(path, "kiwi");
6835     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6836     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6837     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6838     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6839 
6840     /* try SOURCEDIR after ResolveSource */
6841     size = MAX_PATH;
6842     lstrcpyA(path, "kiwi");
6843     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6844     todo_wine
6845     {
6846         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6847         ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6848         ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6849     }
6850 
6851     /* source path and the property exist */
6852     size = MAX_PATH;
6853     lstrcpyA(path, "kiwi");
6854     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6855     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6856     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6857     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6858 
6859     size = MAX_PATH;
6860     lstrcpyA(path, "kiwi");
6861     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6862     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6863     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6864     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6865 
6866     /* try SubDir after ResolveSource */
6867     size = MAX_PATH;
6868     lstrcpyA(path, "kiwi");
6869     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6870     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6871     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6872     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6873 
6874     /* try SubDir2 after ResolveSource */
6875     size = MAX_PATH;
6876     lstrcpyA(path, "kiwi");
6877     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6878     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6879     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6880     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6881 
6882     r = MsiDoActionA(hpkg, "FileCost");
6883     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6884 
6885     /* try TARGETDIR after CostFinalize */
6886     size = MAX_PATH;
6887     lstrcpyA(path, "kiwi");
6888     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6889     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6890     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6891     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6892 
6893     /* try SourceDir after CostFinalize */
6894     size = MAX_PATH;
6895     lstrcpyA(path, "kiwi");
6896     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6897     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6898     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6899     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6900 
6901     /* try SOURCEDIR after CostFinalize */
6902     size = MAX_PATH;
6903     lstrcpyA(path, "kiwi");
6904     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6905     todo_wine
6906     {
6907         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6908         ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6909         ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6910     }
6911 
6912     /* source path and the property exist */
6913     size = MAX_PATH;
6914     lstrcpyA(path, "kiwi");
6915     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6916     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6917     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6918     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6919 
6920     size = MAX_PATH;
6921     lstrcpyA(path, "kiwi");
6922     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6923     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6924     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6925     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6926 
6927     /* try SubDir after CostFinalize */
6928     size = MAX_PATH;
6929     lstrcpyA(path, "kiwi");
6930     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6931     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6932     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6933     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6934 
6935     /* try SubDir2 after CostFinalize */
6936     size = MAX_PATH;
6937     lstrcpyA(path, "kiwi");
6938     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6939     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6940     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6941     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6942 
6943     r = MsiDoActionA(hpkg, "CostFinalize");
6944     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6945 
6946     /* try TARGETDIR after CostFinalize */
6947     size = MAX_PATH;
6948     lstrcpyA(path, "kiwi");
6949     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6950     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6951     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6952     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6953 
6954     /* try SourceDir after CostFinalize */
6955     size = MAX_PATH;
6956     lstrcpyA(path, "kiwi");
6957     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6958     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6959     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6960     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6961 
6962     /* try SOURCEDIR after CostFinalize */
6963     size = MAX_PATH;
6964     lstrcpyA(path, "kiwi");
6965     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6966     todo_wine
6967     {
6968         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6969         ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6970         ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6971     }
6972 
6973     /* source path and the property exist */
6974     size = MAX_PATH;
6975     lstrcpyA(path, "kiwi");
6976     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6977     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6978     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6979     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6980 
6981     size = MAX_PATH;
6982     lstrcpyA(path, "kiwi");
6983     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6984     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6985     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6986     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6987 
6988     /* try SubDir after CostFinalize */
6989     size = MAX_PATH;
6990     lstrcpyA(path, "kiwi");
6991     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6992     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6993     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6994     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6995 
6996     /* try SubDir2 after CostFinalize */
6997     size = MAX_PATH;
6998     lstrcpyA(path, "kiwi");
6999     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
7000     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7001     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7002     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7003 
7004     MsiCloseHandle(hpkg);
7005     DeleteFileA(msifile);
7006 }
7007 
7008 static void test_shortlongsource(void)
7009 {
7010     MSIHANDLE hdb, hpkg;
7011     CHAR path[MAX_PATH];
7012     CHAR cwd[MAX_PATH];
7013     CHAR subsrc[MAX_PATH];
7014     DWORD size;
7015     UINT r;
7016 
7017     lstrcpyA(cwd, CURR_DIR);
7018     if (!is_root(CURR_DIR)) lstrcatA(cwd, "\\");
7019 
7020     lstrcpyA(subsrc, cwd);
7021     lstrcatA(subsrc, "long");
7022     lstrcatA(subsrc, "\\");
7023 
7024     /* long file names */
7025 
7026     hdb = create_package_db();
7027     ok( hdb, "failed to create database\n");
7028 
7029     set_suminfo_prop(hdb, PID_WORDCOUNT, 0);
7030 
7031     add_directory_entry(hdb, "'TARGETDIR', '', 'SourceDir'");
7032     add_directory_entry(hdb, "'SubDir', 'TARGETDIR', 'short|long'");
7033 
7034     /* CostInitialize:short */
7035     add_directory_entry(hdb, "'SubDir2', 'TARGETDIR', 'one|two'");
7036 
7037     /* CostInitialize:long */
7038     add_directory_entry(hdb, "'SubDir3', 'TARGETDIR', 'three|four'");
7039 
7040     /* FileCost:short */
7041     add_directory_entry(hdb, "'SubDir4', 'TARGETDIR', 'five|six'");
7042 
7043     /* FileCost:long */
7044     add_directory_entry(hdb, "'SubDir5', 'TARGETDIR', 'seven|eight'");
7045 
7046     /* CostFinalize:short */
7047     add_directory_entry(hdb, "'SubDir6', 'TARGETDIR', 'nine|ten'");
7048 
7049     /* CostFinalize:long */
7050     add_directory_entry(hdb, "'SubDir7', 'TARGETDIR', 'eleven|twelve'");
7051 
7052     r = MsiDatabaseCommit(hdb);
7053     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
7054 
7055     r = package_from_db(hdb, &hpkg);
7056     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
7057     {
7058         skip("Not enough rights to perform tests\n");
7059         DeleteFileA(msifile);
7060         return;
7061     }
7062     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
7063 
7064     MsiCloseHandle(hdb);
7065 
7066     CreateDirectoryA("one", NULL);
7067     CreateDirectoryA("four", NULL);
7068 
7069     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
7070 
7071     r = MsiDoActionA(hpkg, "CostInitialize");
7072     ok(r == ERROR_SUCCESS, "file cost failed\n");
7073 
7074     CreateDirectoryA("five", NULL);
7075     CreateDirectoryA("eight", NULL);
7076 
7077     r = MsiDoActionA(hpkg, "FileCost");
7078     ok(r == ERROR_SUCCESS, "file cost failed\n");
7079 
7080     CreateDirectoryA("nine", NULL);
7081     CreateDirectoryA("twelve", NULL);
7082 
7083     r = MsiDoActionA(hpkg, "CostFinalize");
7084     ok(r == ERROR_SUCCESS, "file cost failed\n");
7085 
7086     /* neither short nor long source directories exist */
7087     size = MAX_PATH;
7088     lstrcpyA(path, "kiwi");
7089     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7090     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7091     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7092     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7093 
7094     CreateDirectoryA("short", NULL);
7095 
7096     /* short source directory exists */
7097     size = MAX_PATH;
7098     lstrcpyA(path, "kiwi");
7099     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7100     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7101     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7102     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7103 
7104     CreateDirectoryA("long", NULL);
7105 
7106     /* both short and long source directories exist */
7107     size = MAX_PATH;
7108     lstrcpyA(path, "kiwi");
7109     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7110     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7111     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7112     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7113 
7114     lstrcpyA(subsrc, cwd);
7115     lstrcatA(subsrc, "two");
7116     lstrcatA(subsrc, "\\");
7117 
7118     /* short dir exists before CostInitialize */
7119     size = MAX_PATH;
7120     lstrcpyA(path, "kiwi");
7121     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
7122     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7123     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7124     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7125 
7126     lstrcpyA(subsrc, cwd);
7127     lstrcatA(subsrc, "four");
7128     lstrcatA(subsrc, "\\");
7129 
7130     /* long dir exists before CostInitialize */
7131     size = MAX_PATH;
7132     lstrcpyA(path, "kiwi");
7133     r = MsiGetSourcePathA(hpkg, "SubDir3", path, &size);
7134     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7135     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7136     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7137 
7138     lstrcpyA(subsrc, cwd);
7139     lstrcatA(subsrc, "six");
7140     lstrcatA(subsrc, "\\");
7141 
7142     /* short dir exists before FileCost */
7143     size = MAX_PATH;
7144     lstrcpyA(path, "kiwi");
7145     r = MsiGetSourcePathA(hpkg, "SubDir4", path, &size);
7146     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7147     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7148     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7149 
7150     lstrcpyA(subsrc, cwd);
7151     lstrcatA(subsrc, "eight");
7152     lstrcatA(subsrc, "\\");
7153 
7154     /* long dir exists before FileCost */
7155     size = MAX_PATH;
7156     lstrcpyA(path, "kiwi");
7157     r = MsiGetSourcePathA(hpkg, "SubDir5", path, &size);
7158     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7159     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7160     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7161 
7162     lstrcpyA(subsrc, cwd);
7163     lstrcatA(subsrc, "ten");
7164     lstrcatA(subsrc, "\\");
7165 
7166     /* short dir exists before CostFinalize */
7167     size = MAX_PATH;
7168     lstrcpyA(path, "kiwi");
7169     r = MsiGetSourcePathA(hpkg, "SubDir6", path, &size);
7170     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7171     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7172     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7173 
7174     lstrcpyA(subsrc, cwd);
7175     lstrcatA(subsrc, "twelve");
7176     lstrcatA(subsrc, "\\");
7177 
7178     /* long dir exists before CostFinalize */
7179     size = MAX_PATH;
7180     lstrcpyA(path, "kiwi");
7181     r = MsiGetSourcePathA(hpkg, "SubDir7", path, &size);
7182     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7183     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7184     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7185 
7186     MsiCloseHandle(hpkg);
7187     RemoveDirectoryA("short");
7188     RemoveDirectoryA("long");
7189     RemoveDirectoryA("one");
7190     RemoveDirectoryA("four");
7191     RemoveDirectoryA("five");
7192     RemoveDirectoryA("eight");
7193     RemoveDirectoryA("nine");
7194     RemoveDirectoryA("twelve");
7195 
7196     /* short file names */
7197 
7198     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb);
7199     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7200 
7201     set_suminfo_prop(hdb, PID_WORDCOUNT, msidbSumInfoSourceTypeSFN);
7202 
7203     r = package_from_db(hdb, &hpkg);
7204     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
7205 
7206     MsiCloseHandle(hdb);
7207 
7208     CreateDirectoryA("one", NULL);
7209     CreateDirectoryA("four", NULL);
7210 
7211     r = MsiDoActionA(hpkg, "CostInitialize");
7212     ok(r == ERROR_SUCCESS, "file cost failed\n");
7213 
7214     CreateDirectoryA("five", NULL);
7215     CreateDirectoryA("eight", NULL);
7216 
7217     r = MsiDoActionA(hpkg, "FileCost");
7218     ok(r == ERROR_SUCCESS, "file cost failed\n");
7219 
7220     CreateDirectoryA("nine", NULL);
7221     CreateDirectoryA("twelve", NULL);
7222 
7223     r = MsiDoActionA(hpkg, "CostFinalize");
7224     ok(r == ERROR_SUCCESS, "file cost failed\n");
7225 
7226     lstrcpyA(subsrc, cwd);
7227     lstrcatA(subsrc, "short");
7228     lstrcatA(subsrc, "\\");
7229 
7230     /* neither short nor long source directories exist */
7231     size = MAX_PATH;
7232     lstrcpyA(path, "kiwi");
7233     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7234     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7235     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7236     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7237 
7238     CreateDirectoryA("short", NULL);
7239 
7240     /* short source directory exists */
7241     size = MAX_PATH;
7242     lstrcpyA(path, "kiwi");
7243     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7244     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7245     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7246     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7247 
7248     CreateDirectoryA("long", NULL);
7249 
7250     /* both short and long source directories exist */
7251     size = MAX_PATH;
7252     lstrcpyA(path, "kiwi");
7253     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7254     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7255     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7256     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7257 
7258     lstrcpyA(subsrc, cwd);
7259     lstrcatA(subsrc, "one");
7260     lstrcatA(subsrc, "\\");
7261 
7262     /* short dir exists before CostInitialize */
7263     size = MAX_PATH;
7264     lstrcpyA(path, "kiwi");
7265     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
7266     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7267     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7268     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7269 
7270     lstrcpyA(subsrc, cwd);
7271     lstrcatA(subsrc, "three");
7272     lstrcatA(subsrc, "\\");
7273 
7274     /* long dir exists before CostInitialize */
7275     size = MAX_PATH;
7276     lstrcpyA(path, "kiwi");
7277     r = MsiGetSourcePathA(hpkg, "SubDir3", path, &size);
7278     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7279     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7280     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7281 
7282     lstrcpyA(subsrc, cwd);
7283     lstrcatA(subsrc, "five");
7284     lstrcatA(subsrc, "\\");
7285 
7286     /* short dir exists before FileCost */
7287     size = MAX_PATH;
7288     lstrcpyA(path, "kiwi");
7289     r = MsiGetSourcePathA(hpkg, "SubDir4", path, &size);
7290     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7291     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7292     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7293 
7294     lstrcpyA(subsrc, cwd);
7295     lstrcatA(subsrc, "seven");
7296     lstrcatA(subsrc, "\\");
7297 
7298     /* long dir exists before FileCost */
7299     size = MAX_PATH;
7300     lstrcpyA(path, "kiwi");
7301     r = MsiGetSourcePathA(hpkg, "SubDir5", path, &size);
7302     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7303     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7304     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7305 
7306     lstrcpyA(subsrc, cwd);
7307     lstrcatA(subsrc, "nine");
7308     lstrcatA(subsrc, "\\");
7309 
7310     /* short dir exists before CostFinalize */
7311     size = MAX_PATH;
7312     lstrcpyA(path, "kiwi");
7313     r = MsiGetSourcePathA(hpkg, "SubDir6", path, &size);
7314     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7315     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7316     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7317 
7318     lstrcpyA(subsrc, cwd);
7319     lstrcatA(subsrc, "eleven");
7320     lstrcatA(subsrc, "\\");
7321 
7322     /* long dir exists before CostFinalize */
7323     size = MAX_PATH;
7324     lstrcpyA(path, "kiwi");
7325     r = MsiGetSourcePathA(hpkg, "SubDir7", path, &size);
7326     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7327     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7328     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7329 
7330     MsiCloseHandle(hpkg);
7331     RemoveDirectoryA("short");
7332     RemoveDirectoryA("long");
7333     RemoveDirectoryA("one");
7334     RemoveDirectoryA("four");
7335     RemoveDirectoryA("five");
7336     RemoveDirectoryA("eight");
7337     RemoveDirectoryA("nine");
7338     RemoveDirectoryA("twelve");
7339     DeleteFileA(msifile);
7340 }
7341 
7342 static void test_sourcedir(void)
7343 {
7344     MSIHANDLE hdb, hpkg;
7345     CHAR package[12];
7346     CHAR path[MAX_PATH];
7347     CHAR cwd[MAX_PATH];
7348     CHAR subsrc[MAX_PATH];
7349     DWORD size;
7350     UINT r;
7351 
7352     lstrcpyA(cwd, CURR_DIR);
7353     if (!is_root(CURR_DIR)) lstrcatA(cwd, "\\");
7354 
7355     lstrcpyA(subsrc, cwd);
7356     lstrcatA(subsrc, "long");
7357     lstrcatA(subsrc, "\\");
7358 
7359     hdb = create_package_db();
7360     ok( hdb, "failed to create database\n");
7361 
7362     add_directory_entry(hdb, "'TARGETDIR', '', 'SourceDir'");
7363 
7364     sprintf(package, "#%u", hdb);
7365     r = MsiOpenPackageA(package, &hpkg);
7366     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
7367     {
7368         skip("Not enough rights to perform tests\n");
7369         goto error;
7370     }
7371     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7372 
7373     /* properties only */
7374 
7375     /* SourceDir prop */
7376     size = MAX_PATH;
7377     lstrcpyA(path, "kiwi");
7378     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7379     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7380     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7381     ok(size == 0, "Expected 0, got %d\n", size);
7382 
7383     /* SOURCEDIR prop */
7384     size = MAX_PATH;
7385     lstrcpyA(path, "kiwi");
7386     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7387     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7388     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7389     ok(size == 0, "Expected 0, got %d\n", size);
7390 
7391     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
7392 
7393     r = MsiDoActionA(hpkg, "CostInitialize");
7394     ok(r == ERROR_SUCCESS, "file cost failed\n");
7395 
7396     /* SourceDir after CostInitialize */
7397     size = MAX_PATH;
7398     lstrcpyA(path, "kiwi");
7399     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7400     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7401     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7402     ok(size == 0, "Expected 0, got %d\n", size);
7403 
7404     /* SOURCEDIR after CostInitialize */
7405     size = MAX_PATH;
7406     lstrcpyA(path, "kiwi");
7407     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7408     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7409     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7410     ok(size == 0, "Expected 0, got %d\n", size);
7411 
7412     r = MsiDoActionA(hpkg, "FileCost");
7413     ok(r == ERROR_SUCCESS, "file cost failed\n");
7414 
7415     /* SourceDir after FileCost */
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, ""), "Expected \"\", got \"%s\"\n", path);
7421     ok(size == 0, "Expected 0, got %d\n", size);
7422 
7423     /* SOURCEDIR after FileCost */
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 %d\n", size);
7430 
7431     r = MsiDoActionA(hpkg, "CostFinalize");
7432     ok(r == ERROR_SUCCESS, "file cost failed\n");
7433 
7434     /* SourceDir after CostFinalize */
7435     size = MAX_PATH;
7436     lstrcpyA(path, "kiwi");
7437     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7438     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7439     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7440     ok(size == 0, "Expected 0, got %d\n", size);
7441 
7442     /* SOURCEDIR after CostFinalize */
7443     size = MAX_PATH;
7444     lstrcpyA(path, "kiwi");
7445     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7446     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7447     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7448     ok(size == 0, "Expected 0, got %d\n", size);
7449 
7450     size = MAX_PATH;
7451     lstrcpyA(path, "kiwi");
7452     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7453     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7454     ok(!lstrcmpA(path, "kiwi"), "Expected \"kiwi\", got \"%s\"\n", path);
7455     ok(size == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, size);
7456 
7457     /* SOURCEDIR after calling MsiGetSourcePath */
7458     size = MAX_PATH;
7459     lstrcpyA(path, "kiwi");
7460     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7461     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7462     todo_wine {
7463     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7464     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7465     }
7466 
7467     r = MsiDoActionA(hpkg, "ResolveSource");
7468     ok(r == ERROR_SUCCESS, "file cost failed\n");
7469 
7470     /* SourceDir after ResolveSource */
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     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7476     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7477 
7478     /* SOURCEDIR after ResolveSource */
7479     size = MAX_PATH;
7480     lstrcpyA(path, "kiwi");
7481     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7482     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7483     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7484     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7485 
7486     /* random casing */
7487     size = MAX_PATH;
7488     lstrcpyA(path, "kiwi");
7489     r = MsiGetPropertyA(hpkg, "SoUrCeDiR", path, &size);
7490     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7491     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7492     ok(size == 0, "Expected 0, got %d\n", size);
7493 
7494     MsiCloseHandle(hpkg);
7495 
7496     /* reset the package state */
7497     sprintf(package, "#%i", hdb);
7498     r = MsiOpenPackageA(package, &hpkg);
7499     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7500 
7501     /* test how MsiGetSourcePath affects the properties */
7502 
7503     /* SourceDir prop */
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 %d\n", size);
7512     }
7513 
7514     size = MAX_PATH;
7515     lstrcpyA(path, "kiwi");
7516     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
7517     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7518     ok(!lstrcmpA(path, "kiwi"),
7519        "Expected path to be unchanged, got \"%s\"\n", path);
7520     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7521 
7522     /* SourceDir after MsiGetSourcePath */
7523     size = MAX_PATH;
7524     lstrcpyA(path, "kiwi");
7525     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7526     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7527     todo_wine
7528     {
7529         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7530         ok(size == 0, "Expected 0, got %d\n", size);
7531     }
7532 
7533     /* SOURCEDIR prop */
7534     size = MAX_PATH;
7535     lstrcpyA(path, "kiwi");
7536     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7537     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7538     todo_wine
7539     {
7540         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7541         ok(size == 0, "Expected 0, got %d\n", size);
7542     }
7543 
7544     size = MAX_PATH;
7545     lstrcpyA(path, "kiwi");
7546     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7547     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7548     ok(!lstrcmpA(path, "kiwi"),
7549        "Expected path to be unchanged, got \"%s\"\n", path);
7550     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7551 
7552     /* SOURCEDIR prop after MsiGetSourcePath */
7553     size = MAX_PATH;
7554     lstrcpyA(path, "kiwi");
7555     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7556     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7557     todo_wine
7558     {
7559         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7560         ok(size == 0, "Expected 0, got %d\n", size);
7561     }
7562 
7563     r = MsiDoActionA(hpkg, "CostInitialize");
7564     ok(r == ERROR_SUCCESS, "file cost failed\n");
7565 
7566     /* SourceDir after CostInitialize */
7567     size = MAX_PATH;
7568     lstrcpyA(path, "kiwi");
7569     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7570     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7571     todo_wine
7572     {
7573         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7574         ok(size == 0, "Expected 0, got %d\n", size);
7575     }
7576 
7577     size = MAX_PATH;
7578     lstrcpyA(path, "kiwi");
7579     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
7580     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7581     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7582     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7583 
7584     /* SourceDir after MsiGetSourcePath */
7585     size = MAX_PATH;
7586     lstrcpyA(path, "kiwi");
7587     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7588     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7589     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7590     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7591 
7592     /* SOURCEDIR after CostInitialize */
7593     size = MAX_PATH;
7594     lstrcpyA(path, "kiwi");
7595     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7596     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7597     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7598     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7599 
7600     /* SOURCEDIR source path still does not exist */
7601     size = MAX_PATH;
7602     lstrcpyA(path, "kiwi");
7603     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7604     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7605     ok(!lstrcmpA(path, "kiwi"),
7606        "Expected path to be unchanged, got \"%s\"\n", path);
7607     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7608 
7609     r = MsiDoActionA(hpkg, "FileCost");
7610     ok(r == ERROR_SUCCESS, "file cost failed\n");
7611 
7612     /* SourceDir after FileCost */
7613     size = MAX_PATH;
7614     lstrcpyA(path, "kiwi");
7615     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7616     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7617     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7618     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7619 
7620     /* SOURCEDIR after FileCost */
7621     size = MAX_PATH;
7622     lstrcpyA(path, "kiwi");
7623     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7624     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7625     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7626     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7627 
7628     /* SOURCEDIR source path still does not exist */
7629     size = MAX_PATH;
7630     lstrcpyA(path, "kiwi");
7631     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7632     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7633     ok(!lstrcmpA(path, "kiwi"),
7634        "Expected path to be unchanged, got \"%s\"\n", path);
7635     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7636 
7637     r = MsiDoActionA(hpkg, "CostFinalize");
7638     ok(r == ERROR_SUCCESS, "file cost failed\n");
7639 
7640     /* SourceDir after CostFinalize */
7641     size = MAX_PATH;
7642     lstrcpyA(path, "kiwi");
7643     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7644     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7645     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7646     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7647 
7648     /* SOURCEDIR after CostFinalize */
7649     size = MAX_PATH;
7650     lstrcpyA(path, "kiwi");
7651     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7652     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7653     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7654     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7655 
7656     /* SOURCEDIR source path still does not exist */
7657     size = MAX_PATH;
7658     lstrcpyA(path, "kiwi");
7659     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7660     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7661     ok(!lstrcmpA(path, "kiwi"),
7662        "Expected path to be unchanged, got \"%s\"\n", path);
7663     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7664 
7665     r = MsiDoActionA(hpkg, "ResolveSource");
7666     ok(r == ERROR_SUCCESS, "file cost failed\n");
7667 
7668     /* SourceDir after ResolveSource */
7669     size = MAX_PATH;
7670     lstrcpyA(path, "kiwi");
7671     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7672     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7673     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7674     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7675 
7676     /* SOURCEDIR after ResolveSource */
7677     size = MAX_PATH;
7678     lstrcpyA(path, "kiwi");
7679     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7680     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7681     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7682     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7683 
7684     /* SOURCEDIR source path still does not exist */
7685     size = MAX_PATH;
7686     lstrcpyA(path, "kiwi");
7687     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7688     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7689     ok(!lstrcmpA(path, "kiwi"),
7690        "Expected path to be unchanged, got \"%s\"\n", path);
7691     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7692 
7693     MsiCloseHandle(hpkg);
7694 
7695 error:
7696     MsiCloseHandle(hdb);
7697     DeleteFileA(msifile);
7698 }
7699 
7700 struct access_res
7701 {
7702     BOOL gothandle;
7703     DWORD lasterr;
7704     BOOL ignore;
7705 };
7706 
7707 static const struct access_res create[16] =
7708 {
7709     { TRUE, ERROR_SUCCESS, TRUE },
7710     { TRUE, ERROR_SUCCESS, TRUE },
7711     { TRUE, ERROR_SUCCESS, FALSE },
7712     { TRUE, ERROR_SUCCESS, FALSE },
7713     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7714     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7715     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7716     { TRUE, ERROR_SUCCESS, FALSE },
7717     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7718     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7719     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7720     { TRUE, ERROR_SUCCESS, TRUE },
7721     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7722     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7723     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7724     { TRUE, ERROR_SUCCESS, TRUE }
7725 };
7726 
7727 static const struct access_res create_commit[16] =
7728 {
7729     { TRUE, ERROR_SUCCESS, TRUE },
7730     { TRUE, ERROR_SUCCESS, TRUE },
7731     { TRUE, ERROR_SUCCESS, FALSE },
7732     { TRUE, ERROR_SUCCESS, FALSE },
7733     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7734     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7735     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7736     { TRUE, ERROR_SUCCESS, FALSE },
7737     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7738     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7739     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7740     { TRUE, ERROR_SUCCESS, TRUE },
7741     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7742     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7743     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7744     { TRUE, ERROR_SUCCESS, TRUE }
7745 };
7746 
7747 static const struct access_res create_close[16] =
7748 {
7749     { TRUE, ERROR_SUCCESS, FALSE },
7750     { TRUE, ERROR_SUCCESS, FALSE },
7751     { TRUE, ERROR_SUCCESS, FALSE },
7752     { TRUE, ERROR_SUCCESS, FALSE },
7753     { TRUE, ERROR_SUCCESS, FALSE },
7754     { TRUE, ERROR_SUCCESS, FALSE },
7755     { TRUE, ERROR_SUCCESS, FALSE },
7756     { TRUE, ERROR_SUCCESS, FALSE },
7757     { TRUE, ERROR_SUCCESS, FALSE },
7758     { TRUE, ERROR_SUCCESS, FALSE },
7759     { TRUE, ERROR_SUCCESS, FALSE },
7760     { TRUE, ERROR_SUCCESS, FALSE },
7761     { TRUE, ERROR_SUCCESS, FALSE },
7762     { TRUE, ERROR_SUCCESS, FALSE },
7763     { TRUE, ERROR_SUCCESS, FALSE },
7764     { TRUE, ERROR_SUCCESS }
7765 };
7766 
7767 static void _test_file_access(LPCSTR file, const struct access_res *ares, DWORD line)
7768 {
7769     DWORD access = 0, share = 0;
7770     DWORD lasterr;
7771     HANDLE hfile;
7772     int i, j, idx = 0;
7773 
7774     for (i = 0; i < 4; i++)
7775     {
7776         if (i == 0) access = 0;
7777         if (i == 1) access = GENERIC_READ;
7778         if (i == 2) access = GENERIC_WRITE;
7779         if (i == 3) access = GENERIC_READ | GENERIC_WRITE;
7780 
7781         for (j = 0; j < 4; j++)
7782         {
7783             if (ares[idx].ignore)
7784                 continue;
7785 
7786             if (j == 0) share = 0;
7787             if (j == 1) share = FILE_SHARE_READ;
7788             if (j == 2) share = FILE_SHARE_WRITE;
7789             if (j == 3) share = FILE_SHARE_READ | FILE_SHARE_WRITE;
7790 
7791             SetLastError(0xdeadbeef);
7792             hfile = CreateFileA(file, access, share, NULL, OPEN_EXISTING,
7793                                 FILE_ATTRIBUTE_NORMAL, 0);
7794             lasterr = GetLastError();
7795 
7796             ok((hfile != INVALID_HANDLE_VALUE) == ares[idx].gothandle,
7797                "(%d, handle, %d): Expected %d, got %d\n",
7798                line, idx, ares[idx].gothandle,
7799                (hfile != INVALID_HANDLE_VALUE));
7800 
7801             ok(lasterr == ares[idx].lasterr, "(%d, lasterr, %d): Expected %d, got %d\n",
7802                line, idx, ares[idx].lasterr, lasterr);
7803 
7804             CloseHandle(hfile);
7805             idx++;
7806         }
7807     }
7808 }
7809 
7810 #define test_file_access(file, ares) _test_file_access(file, ares, __LINE__)
7811 
7812 static void test_access(void)
7813 {
7814     MSIHANDLE hdb;
7815     UINT r;
7816 
7817     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
7818     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7819 
7820     test_file_access(msifile, create);
7821 
7822     r = MsiDatabaseCommit(hdb);
7823     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7824 
7825     test_file_access(msifile, create_commit);
7826     MsiCloseHandle(hdb);
7827 
7828     test_file_access(msifile, create_close);
7829     DeleteFileA(msifile);
7830 
7831     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATEDIRECT, &hdb);
7832     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7833 
7834     test_file_access(msifile, create);
7835 
7836     r = MsiDatabaseCommit(hdb);
7837     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7838 
7839     test_file_access(msifile, create_commit);
7840     MsiCloseHandle(hdb);
7841 
7842     test_file_access(msifile, create_close);
7843     DeleteFileA(msifile);
7844 }
7845 
7846 static void test_emptypackage(void)
7847 {
7848     MSIHANDLE hpkg = 0, hdb = 0, hsuminfo = 0;
7849     MSIHANDLE hview = 0, hrec = 0;
7850     MSICONDITION condition;
7851     CHAR buffer[MAX_PATH];
7852     DWORD size;
7853     UINT r;
7854 
7855     r = MsiOpenPackageA("", &hpkg);
7856     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
7857     {
7858         skip("Not enough rights to perform tests\n");
7859         return;
7860     }
7861     todo_wine
7862     {
7863         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7864     }
7865 
7866     hdb = MsiGetActiveDatabase(hpkg);
7867     todo_wine
7868     {
7869         ok(hdb != 0, "Expected a valid database handle\n");
7870     }
7871 
7872     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Tables`", &hview);
7873     todo_wine
7874     {
7875         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7876     }
7877     r = MsiViewExecute(hview, 0);
7878     todo_wine
7879     {
7880         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7881     }
7882 
7883     r = MsiViewFetch(hview, &hrec);
7884     todo_wine
7885     {
7886         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7887     }
7888 
7889     buffer[0] = 0;
7890     size = MAX_PATH;
7891     r = MsiRecordGetStringA(hrec, 1, buffer, &size);
7892     todo_wine
7893     {
7894         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7895         ok(!lstrcmpA(buffer, "_Property"),
7896            "Expected \"_Property\", got \"%s\"\n", buffer);
7897     }
7898 
7899     MsiCloseHandle(hrec);
7900 
7901     r = MsiViewFetch(hview, &hrec);
7902     todo_wine
7903     {
7904         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7905     }
7906 
7907     size = MAX_PATH;
7908     r = MsiRecordGetStringA(hrec, 1, buffer, &size);
7909     todo_wine
7910     {
7911         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7912         ok(!lstrcmpA(buffer, "#_FolderCache"),
7913            "Expected \"_Property\", got \"%s\"\n", buffer);
7914     }
7915 
7916     MsiCloseHandle(hrec);
7917     MsiViewClose(hview);
7918     MsiCloseHandle(hview);
7919 
7920     condition = MsiDatabaseIsTablePersistentA(hdb, "_Property");
7921     todo_wine
7922     {
7923         ok(condition == MSICONDITION_FALSE,
7924            "Expected MSICONDITION_FALSE, got %d\n", condition);
7925     }
7926 
7927     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Property`", &hview);
7928     todo_wine
7929     {
7930         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7931     }
7932     r = MsiViewExecute(hview, 0);
7933     todo_wine
7934     {
7935         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7936     }
7937 
7938     /* _Property table is not empty */
7939     r = MsiViewFetch(hview, &hrec);
7940     todo_wine
7941     {
7942         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7943     }
7944 
7945     MsiCloseHandle(hrec);
7946     MsiViewClose(hview);
7947     MsiCloseHandle(hview);
7948 
7949     condition = MsiDatabaseIsTablePersistentA(hdb, "#_FolderCache");
7950     todo_wine
7951     {
7952         ok(condition == MSICONDITION_FALSE,
7953            "Expected MSICONDITION_FALSE, got %d\n", condition);
7954     }
7955 
7956     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `#_FolderCache`", &hview);
7957     todo_wine
7958     {
7959         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7960     }
7961     r = MsiViewExecute(hview, 0);
7962     todo_wine
7963     {
7964         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7965     }
7966 
7967     /* #_FolderCache is not empty */
7968     r = MsiViewFetch(hview, &hrec);
7969     todo_wine
7970     {
7971         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7972     }
7973 
7974     MsiCloseHandle(hrec);
7975     MsiViewClose(hview);
7976     MsiCloseHandle(hview);
7977 
7978     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Streams`", &hview);
7979     todo_wine
7980     {
7981         ok(r == ERROR_BAD_QUERY_SYNTAX,
7982            "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7983     }
7984 
7985     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Storages`", &hview);
7986     todo_wine
7987     {
7988         ok(r == ERROR_BAD_QUERY_SYNTAX,
7989            "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7990     }
7991 
7992     r = MsiGetSummaryInformationA(hdb, NULL, 0, &hsuminfo);
7993     todo_wine
7994     {
7995         ok(r == ERROR_INSTALL_PACKAGE_INVALID,
7996            "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
7997     }
7998 
7999     MsiCloseHandle(hsuminfo);
8000 
8001     r = MsiDatabaseCommit(hdb);
8002     todo_wine
8003     {
8004         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8005     }
8006 
8007     MsiCloseHandle(hdb);
8008     MsiCloseHandle(hpkg);
8009 }
8010 
8011 static void test_MsiGetProductProperty(void)
8012 {
8013     static const WCHAR prodcode_propW[] = {'P','r','o','d','u','c','t','C','o','d','e',0};
8014     static const WCHAR nonexistentW[] = {'I','D','o','n','t','E','x','i','s','t',0};
8015     static const WCHAR newpropW[] = {'N','e','w','P','r','o','p','e','r','t','y',0};
8016     static const WCHAR appleW[] = {'a','p','p','l','e',0};
8017     static const WCHAR emptyW[] = {0};
8018     WCHAR valW[MAX_PATH];
8019     MSIHANDLE hprod, hdb;
8020     CHAR val[MAX_PATH];
8021     CHAR path[MAX_PATH];
8022     CHAR query[MAX_PATH];
8023     CHAR keypath[MAX_PATH*2];
8024     CHAR prodcode[MAX_PATH];
8025     WCHAR prodcodeW[MAX_PATH];
8026     CHAR prod_squashed[MAX_PATH];
8027     WCHAR prod_squashedW[MAX_PATH];
8028     HKEY prodkey, userkey, props;
8029     DWORD size;
8030     LONG res;
8031     UINT r;
8032     REGSAM access = KEY_ALL_ACCESS;
8033 
8034     GetCurrentDirectoryA(MAX_PATH, path);
8035     lstrcatA(path, "\\");
8036 
8037     create_test_guid(prodcode, prod_squashed);
8038     MultiByteToWideChar(CP_ACP, 0, prodcode, -1, prodcodeW, MAX_PATH);
8039     squash_guid(prodcodeW, prod_squashedW);
8040 
8041     if (is_wow64)
8042         access |= KEY_WOW64_64KEY;
8043 
8044     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
8045     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8046 
8047     r = MsiDatabaseCommit(hdb);
8048     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8049 
8050     r = set_summary_info(hdb);
8051     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8052 
8053     r = run_query(hdb,
8054             "CREATE TABLE `Directory` ( "
8055             "`Directory` CHAR(255) NOT NULL, "
8056             "`Directory_Parent` CHAR(255), "
8057             "`DefaultDir` CHAR(255) NOT NULL "
8058             "PRIMARY KEY `Directory`)");
8059     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8060 
8061     create_property_table(hdb);
8062 
8063     sprintf(query, "'ProductCode', '%s'", prodcode);
8064     r = add_property_entry(hdb, query);
8065 
8066     r = MsiDatabaseCommit(hdb);
8067     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8068 
8069     MsiCloseHandle(hdb);
8070 
8071     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
8072     lstrcatA(keypath, prod_squashed);
8073 
8074     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
8075     if (res == ERROR_ACCESS_DENIED)
8076     {
8077         skip("Not enough rights to perform tests\n");
8078         DeleteFileA(msifile);
8079         return;
8080     }
8081     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8082 
8083     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
8084     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
8085     lstrcatA(keypath, prod_squashed);
8086 
8087     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
8088     if (res == ERROR_ACCESS_DENIED)
8089     {
8090         skip("Not enough rights to perform tests\n");
8091         RegDeleteKeyA(prodkey, "");
8092         RegCloseKey(prodkey);
8093         return;
8094     }
8095     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8096 
8097     res = RegCreateKeyExA(userkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
8098     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8099 
8100     lstrcpyA(val, path);
8101     lstrcatA(val, "\\");
8102     lstrcatA(val, msifile);
8103     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
8104                          (const BYTE *)val, lstrlenA(val) + 1);
8105     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8106 
8107     hprod = 0xdeadbeef;
8108     r = MsiOpenProductA(prodcode, &hprod);
8109     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8110     ok(hprod != 0 && hprod != 0xdeadbeef, "Expected a valid product handle\n");
8111 
8112     /* hProduct is invalid */
8113     size = MAX_PATH;
8114     lstrcpyA(val, "apple");
8115     r = MsiGetProductPropertyA(0xdeadbeef, "ProductCode", val, &size);
8116     ok(r == ERROR_INVALID_HANDLE,
8117        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
8118     ok(!lstrcmpA(val, "apple"),
8119        "Expected val to be unchanged, got \"%s\"\n", val);
8120     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8121 
8122     size = MAX_PATH;
8123     lstrcpyW(valW, appleW);
8124     r = MsiGetProductPropertyW(0xdeadbeef, prodcode_propW, valW, &size);
8125     ok(r == ERROR_INVALID_HANDLE,
8126        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
8127     ok(!lstrcmpW(valW, appleW),
8128        "Expected val to be unchanged, got %s\n", wine_dbgstr_w(valW));
8129     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8130 
8131     /* szProperty is NULL */
8132     size = MAX_PATH;
8133     lstrcpyA(val, "apple");
8134     r = MsiGetProductPropertyA(hprod, NULL, val, &size);
8135     ok(r == ERROR_INVALID_PARAMETER,
8136        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8137     ok(!lstrcmpA(val, "apple"),
8138        "Expected val to be unchanged, got \"%s\"\n", val);
8139     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8140 
8141     size = MAX_PATH;
8142     lstrcpyW(valW, appleW);
8143     r = MsiGetProductPropertyW(hprod, NULL, valW, &size);
8144     ok(r == ERROR_INVALID_PARAMETER,
8145        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8146     ok(!lstrcmpW(valW, appleW),
8147        "Expected val to be unchanged, got %s\n", wine_dbgstr_w(valW));
8148     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8149 
8150     /* szProperty is empty */
8151     size = MAX_PATH;
8152     lstrcpyA(val, "apple");
8153     r = MsiGetProductPropertyA(hprod, "", val, &size);
8154     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8155     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
8156     ok(size == 0, "Expected 0, got %d\n", size);
8157 
8158     size = MAX_PATH;
8159     lstrcpyW(valW, appleW);
8160     r = MsiGetProductPropertyW(hprod, emptyW, valW, &size);
8161     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8162     ok(*valW == 0, "Expected \"\", got %s\n", wine_dbgstr_w(valW));
8163     ok(size == 0, "Expected 0, got %d\n", size);
8164 
8165     /* get the property */
8166     size = MAX_PATH;
8167     lstrcpyA(val, "apple");
8168     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8169     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8170     ok(!lstrcmpA(val, prodcode),
8171        "Expected \"%s\", got \"%s\"\n", prodcode, val);
8172     ok(size == lstrlenA(prodcode),
8173        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8174 
8175     size = MAX_PATH;
8176     lstrcpyW(valW, appleW);
8177     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, &size);
8178     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8179     ok(!lstrcmpW(valW, prodcodeW),
8180        "Expected %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8181     ok(size == lstrlenW(prodcodeW),
8182        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8183 
8184     /* lpValueBuf is NULL */
8185     size = MAX_PATH;
8186     r = MsiGetProductPropertyA(hprod, "ProductCode", NULL, &size);
8187     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8188     ok(size == lstrlenA(prodcode),
8189        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8190 
8191     size = MAX_PATH;
8192     r = MsiGetProductPropertyW(hprod, prodcode_propW, NULL, &size);
8193     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8194     ok(size == lstrlenW(prodcodeW),
8195        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8196 
8197     /* pcchValueBuf is NULL */
8198     lstrcpyA(val, "apple");
8199     r = MsiGetProductPropertyA(hprod, "ProductCode", val, NULL);
8200     ok(r == ERROR_INVALID_PARAMETER,
8201        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8202     ok(!lstrcmpA(val, "apple"),
8203        "Expected val to be unchanged, got \"%s\"\n", val);
8204     ok(size == lstrlenA(prodcode),
8205        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8206 
8207     lstrcpyW(valW, appleW);
8208     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, NULL);
8209     ok(r == ERROR_INVALID_PARAMETER,
8210        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8211     ok(!lstrcmpW(valW, appleW),
8212        "Expected val to be unchanged, got %s\n", wine_dbgstr_w(valW));
8213     ok(size == lstrlenW(prodcodeW),
8214        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8215 
8216     /* pcchValueBuf is too small */
8217     size = 4;
8218     lstrcpyA(val, "apple");
8219     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8220     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
8221     ok(!strncmp(val, prodcode, 3),
8222        "Expected first 3 chars of \"%s\", got \"%s\"\n", prodcode, val);
8223     ok(size == lstrlenA(prodcode),
8224        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8225 
8226     size = 4;
8227     lstrcpyW(valW, appleW);
8228     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, &size);
8229     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
8230     ok(!memcmp(valW, prodcodeW, 3 * sizeof(WCHAR)),
8231        "Expected first 3 chars of %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8232     ok(size == lstrlenW(prodcodeW),
8233        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8234 
8235     /* pcchValueBuf does not leave room for NULL terminator */
8236     size = lstrlenA(prodcode);
8237     lstrcpyA(val, "apple");
8238     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8239     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
8240     ok(!strncmp(val, prodcode, lstrlenA(prodcode) - 1),
8241        "Expected first 37 chars of \"%s\", got \"%s\"\n", prodcode, val);
8242     ok(size == lstrlenA(prodcode),
8243        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8244 
8245     size = lstrlenW(prodcodeW);
8246     lstrcpyW(valW, appleW);
8247     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, &size);
8248     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
8249     ok(!memcmp(valW, prodcodeW, lstrlenW(prodcodeW) - 1),
8250        "Expected first 37 chars of %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8251     ok(size == lstrlenW(prodcodeW),
8252        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8253 
8254     /* pcchValueBuf has enough room for NULL terminator */
8255     size = lstrlenA(prodcode) + 1;
8256     lstrcpyA(val, "apple");
8257     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8258     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8259     ok(!lstrcmpA(val, prodcode),
8260        "Expected \"%s\", got \"%s\"\n", prodcode, val);
8261     ok(size == lstrlenA(prodcode),
8262        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8263 
8264     size = lstrlenW(prodcodeW) + 1;
8265     lstrcpyW(valW, appleW);
8266     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, &size);
8267     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8268     ok(!lstrcmpW(valW, prodcodeW),
8269        "Expected %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8270     ok(size == lstrlenW(prodcodeW),
8271        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8272 
8273     /* nonexistent property */
8274     size = MAX_PATH;
8275     lstrcpyA(val, "apple");
8276     r = MsiGetProductPropertyA(hprod, "IDontExist", val, &size);
8277     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8278     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
8279     ok(size == 0, "Expected 0, got %d\n", size);
8280 
8281     size = MAX_PATH;
8282     lstrcpyW(valW, appleW);
8283     r = MsiGetProductPropertyW(hprod, nonexistentW, valW, &size);
8284     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8285     ok(!lstrcmpW(valW, emptyW), "Expected \"\", got %s\n", wine_dbgstr_w(valW));
8286     ok(size == 0, "Expected 0, got %d\n", size);
8287 
8288     r = MsiSetPropertyA(hprod, "NewProperty", "value");
8289     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8290 
8291     /* non-product property set */
8292     size = MAX_PATH;
8293     lstrcpyA(val, "apple");
8294     r = MsiGetProductPropertyA(hprod, "NewProperty", val, &size);
8295     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8296     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
8297     ok(size == 0, "Expected 0, got %d\n", size);
8298 
8299     size = MAX_PATH;
8300     lstrcpyW(valW, appleW);
8301     r = MsiGetProductPropertyW(hprod, newpropW, valW, &size);
8302     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8303     ok(!lstrcmpW(valW, emptyW), "Expected \"\", got %s\n", wine_dbgstr_w(valW));
8304     ok(size == 0, "Expected 0, got %d\n", size);
8305 
8306     r = MsiSetPropertyA(hprod, "ProductCode", "value");
8307     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8308 
8309     /* non-product property that is also a product property set */
8310     size = MAX_PATH;
8311     lstrcpyA(val, "apple");
8312     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8313     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8314     ok(!lstrcmpA(val, prodcode),
8315        "Expected \"%s\", got \"%s\"\n", prodcode, val);
8316     ok(size == lstrlenA(prodcode),
8317        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8318 
8319     size = MAX_PATH;
8320     lstrcpyW(valW, appleW);
8321     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, &size);
8322     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8323     ok(!lstrcmpW(valW, prodcodeW),
8324        "Expected %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8325     ok(size == lstrlenW(prodcodeW),
8326        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8327 
8328     MsiCloseHandle(hprod);
8329 
8330     RegDeleteValueA(props, "LocalPackage");
8331     delete_key(props, "", access);
8332     RegCloseKey(props);
8333     delete_key(userkey, "", access);
8334     RegCloseKey(userkey);
8335     delete_key(prodkey, "", access);
8336     RegCloseKey(prodkey);
8337     DeleteFileA(msifile);
8338 }
8339 
8340 static void test_MsiSetProperty(void)
8341 {
8342     MSIHANDLE hpkg, hdb, hrec;
8343     CHAR buf[MAX_PATH];
8344     LPCSTR query;
8345     DWORD size;
8346     UINT r;
8347 
8348     r = package_from_db(create_package_db(), &hpkg);
8349     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
8350     {
8351         skip("Not enough rights to perform tests\n");
8352         DeleteFileA(msifile);
8353         return;
8354     }
8355     ok(r == ERROR_SUCCESS, "Expected a valid package %u\n", r);
8356 
8357     /* invalid hInstall */
8358     r = MsiSetPropertyA(0, "Prop", "Val");
8359     ok(r == ERROR_INVALID_HANDLE,
8360        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
8361 
8362     /* invalid hInstall */
8363     r = MsiSetPropertyA(0xdeadbeef, "Prop", "Val");
8364     ok(r == ERROR_INVALID_HANDLE,
8365        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
8366 
8367     /* szName is NULL */
8368     r = MsiSetPropertyA(hpkg, NULL, "Val");
8369     ok(r == ERROR_INVALID_PARAMETER,
8370        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8371 
8372     /* both szName and szValue are NULL */
8373     r = MsiSetPropertyA(hpkg, NULL, NULL);
8374     ok(r == ERROR_INVALID_PARAMETER,
8375        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8376 
8377     /* szName is empty */
8378     r = MsiSetPropertyA(hpkg, "", "Val");
8379     ok(r == ERROR_FUNCTION_FAILED,
8380        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
8381 
8382     /* szName is empty and szValue is NULL */
8383     r = MsiSetPropertyA(hpkg, "", NULL);
8384     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8385 
8386     /* set a property */
8387     r = MsiSetPropertyA(hpkg, "Prop", "Val");
8388     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8389 
8390     /* get the property */
8391     size = MAX_PATH;
8392     r = MsiGetPropertyA(hpkg, "Prop", buf, &size);
8393     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8394     ok(!lstrcmpA(buf, "Val"), "Expected \"Val\", got \"%s\"\n", buf);
8395     ok(size == 3, "Expected 3, got %d\n", size);
8396 
8397     /* update the property */
8398     r = MsiSetPropertyA(hpkg, "Prop", "Nuvo");
8399     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8400 
8401     /* get the property */
8402     size = MAX_PATH;
8403     r = MsiGetPropertyA(hpkg, "Prop", buf, &size);
8404     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8405     ok(!lstrcmpA(buf, "Nuvo"), "Expected \"Nuvo\", got \"%s\"\n", buf);
8406     ok(size == 4, "Expected 4, got %d\n", size);
8407 
8408     hdb = MsiGetActiveDatabase(hpkg);
8409     ok(hdb != 0, "Expected a valid database handle\n");
8410 
8411     /* set prop is not in the _Property table */
8412     query = "SELECT * FROM `_Property` WHERE `Property` = 'Prop'";
8413     r = do_query(hdb, query, &hrec);
8414     ok(r == ERROR_BAD_QUERY_SYNTAX,
8415        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8416 
8417     /* set prop is not in the Property table */
8418     query = "SELECT * FROM `Property` WHERE `Property` = 'Prop'";
8419     r = do_query(hdb, query, &hrec);
8420     ok(r == ERROR_BAD_QUERY_SYNTAX,
8421        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8422 
8423     MsiCloseHandle(hdb);
8424 
8425     /* szValue is an empty string */
8426     r = MsiSetPropertyA(hpkg, "Prop", "");
8427     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8428 
8429     /* try to get the property */
8430     size = MAX_PATH;
8431     r = MsiGetPropertyA(hpkg, "Prop", buf, &size);
8432     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8433     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
8434     ok(size == 0, "Expected 0, got %d\n", size);
8435 
8436     /* reset the property */
8437     r = MsiSetPropertyA(hpkg, "Prop", "BlueTap");
8438     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8439 
8440     /* delete the property */
8441     r = MsiSetPropertyA(hpkg, "Prop", NULL);
8442     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8443 
8444     /* try to get the property */
8445     size = MAX_PATH;
8446     r = MsiGetPropertyA(hpkg, "Prop", buf, &size);
8447     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8448     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
8449     ok(size == 0, "Expected 0, got %d\n", size);
8450 
8451     MsiCloseHandle(hpkg);
8452     DeleteFileA(msifile);
8453 }
8454 
8455 static void test_MsiApplyMultiplePatches(void)
8456 {
8457     UINT r, type = GetDriveTypeW(NULL);
8458 
8459     r = MsiApplyMultiplePatchesA(NULL, NULL, NULL);
8460     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
8461 
8462     r = MsiApplyMultiplePatchesA("", NULL, NULL);
8463     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
8464 
8465     r = MsiApplyMultiplePatchesA(";", NULL, NULL);
8466     if (type == DRIVE_FIXED)
8467         todo_wine ok(r == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %u\n", r);
8468     else
8469         ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
8470 
8471     r = MsiApplyMultiplePatchesA("  ;", NULL, NULL);
8472     if (type == DRIVE_FIXED)
8473         todo_wine ok(r == ERROR_PATCH_PACKAGE_OPEN_FAILED, "Expected ERROR_PATCH_PACKAGE_OPEN_FAILED, got %u\n", r);
8474     else
8475         ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
8476 
8477     r = MsiApplyMultiplePatchesA(";;", NULL, NULL);
8478     if (type == DRIVE_FIXED)
8479         todo_wine ok(r == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %u\n", r);
8480     else
8481         ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
8482 
8483     r = MsiApplyMultiplePatchesA("nosuchpatchpackage;", NULL, NULL);
8484     todo_wine ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
8485 
8486     r = MsiApplyMultiplePatchesA(";nosuchpatchpackage", NULL, NULL);
8487     if (type == DRIVE_FIXED)
8488         todo_wine ok(r == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %u\n", r);
8489     else
8490         ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
8491 
8492     r = MsiApplyMultiplePatchesA("nosuchpatchpackage;nosuchpatchpackage", NULL, NULL);
8493     todo_wine ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
8494 
8495     r = MsiApplyMultiplePatchesA("  nosuchpatchpackage  ;  nosuchpatchpackage  ", NULL, NULL);
8496     todo_wine ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
8497 }
8498 
8499 static void test_MsiApplyPatch(void)
8500 {
8501     UINT r;
8502 
8503     r = MsiApplyPatchA(NULL, NULL, INSTALLTYPE_DEFAULT, NULL);
8504     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
8505 
8506     r = MsiApplyPatchA("", NULL, INSTALLTYPE_DEFAULT, NULL);
8507     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
8508 }
8509 
8510 static void test_MsiEnumComponentCosts(void)
8511 {
8512     MSIHANDLE hdb, hpkg;
8513     char package[12], drive[3];
8514     DWORD len;
8515     UINT r;
8516     int cost, temp;
8517 
8518     hdb = create_package_db();
8519     ok( hdb, "failed to create database\n" );
8520 
8521     create_property_table( hdb );
8522     add_property_entry( hdb, "'ProductCode', '{379B1C47-40C1-42FA-A9BB-BEBB6F1B0172}'" );
8523     add_property_entry( hdb, "'MSIFASTINSTALL', '1'" );
8524     add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'" );
8525 
8526     create_media_table( hdb );
8527     add_media_entry( hdb, "'1', '2', 'cabinet', '', '', ''");
8528 
8529     create_file_table( hdb );
8530     add_file_entry( hdb, "'one.txt', 'one', 'one.txt', 4096, '', '', 8192, 1" );
8531 
8532     create_component_table( hdb );
8533     add_component_entry( hdb, "'one', '{B2F86B9D-8447-4BC5-8883-750C45AA31CA}', 'TARGETDIR', 0, '', 'one.txt'" );
8534     add_component_entry( hdb, "'two', '{62A09F6E-0B74-4829-BDB7-CAB66F42CCE8}', 'TARGETDIR', 0, '', ''" );
8535 
8536     create_feature_table( hdb );
8537     add_feature_entry( hdb, "'one', '', '', '', 0, 1, '', 0" );
8538     add_feature_entry( hdb, "'two', '', '', '', 0, 1, '', 0" );
8539 
8540     create_feature_components_table( hdb );
8541     add_feature_components_entry( hdb, "'one', 'one'" );
8542     add_feature_components_entry( hdb, "'two', 'two'" );
8543 
8544     create_install_execute_sequence_table( hdb );
8545     add_install_execute_sequence_entry( hdb, "'CostInitialize', '', '800'" );
8546     add_install_execute_sequence_entry( hdb, "'FileCost', '', '900'" );
8547     add_install_execute_sequence_entry( hdb, "'CostFinalize', '', '1000'" );
8548     add_install_execute_sequence_entry( hdb, "'InstallValidate', '', '1100'" );
8549 
8550     r = MsiDatabaseCommit( hdb );
8551     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8552 
8553     sprintf( package, "#%u", hdb );
8554     r = MsiOpenPackageA( package, &hpkg );
8555     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
8556     {
8557         skip("Not enough rights to perform tests\n");
8558         goto error;
8559     }
8560     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8561 
8562     r = MsiEnumComponentCostsA( 0, NULL, 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8563     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8564 
8565     r = MsiEnumComponentCostsA( hpkg, NULL, 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8566     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8567 
8568     r = MsiEnumComponentCostsA( hpkg, NULL, 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8569     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8570 
8571     r = MsiEnumComponentCostsA( hpkg, "", 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8572     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8573 
8574     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8575     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8576 
8577     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, NULL, NULL, NULL, NULL );
8578     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8579 
8580     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, NULL, NULL, NULL );
8581     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8582 
8583     len = sizeof(drive);
8584     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, NULL, NULL );
8585     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8586 
8587     len = sizeof(drive);
8588     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, NULL );
8589     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8590 
8591     len = sizeof(drive);
8592     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8593     todo_wine ok( r == ERROR_INVALID_HANDLE_STATE, "Expected ERROR_INVALID_HANDLE_STATE, got %u\n", r );
8594 
8595     len = sizeof(drive);
8596     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, NULL, &len, &cost, &temp );
8597     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8598 
8599     MsiSetInternalUI( INSTALLUILEVEL_NONE, NULL );
8600 
8601     r = MsiDoActionA( hpkg, "CostInitialize" );
8602     ok( r == ERROR_SUCCESS, "CostInitialize failed %u\n", r );
8603 
8604     r = MsiDoActionA( hpkg, "FileCost" );
8605     ok( r == ERROR_SUCCESS, "FileCost failed %u\n", r );
8606 
8607     len = sizeof(drive);
8608     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8609     ok( r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %u\n", r );
8610 
8611     r = MsiDoActionA( hpkg, "CostFinalize" );
8612     ok( r == ERROR_SUCCESS, "CostFinalize failed %u\n", r );
8613 
8614     /* contrary to what msdn says InstallValidate must be called too */
8615     len = sizeof(drive);
8616     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8617     todo_wine ok( r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %u\n", r );
8618 
8619     r = MsiDoActionA( hpkg, "InstallValidate" );
8620     ok( r == ERROR_SUCCESS, "InstallValidate failed %u\n", r );
8621 
8622     len = 0;
8623     r = MsiEnumComponentCostsA( hpkg, "three", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8624     ok( r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %u\n", r );
8625 
8626     len = 0;
8627     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8628     ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %u\n", r );
8629     ok( len == 2, "expected len == 2, got %u\n", len );
8630 
8631     len = 2;
8632     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8633     ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %u\n", r );
8634     ok( len == 2, "expected len == 2, got %u\n", len );
8635 
8636     len = 2;
8637     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_UNKNOWN, drive, &len, &cost, &temp );
8638     ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %u\n", r );
8639     ok( len == 2, "expected len == 2, got %u\n", len );
8640 
8641     /* install state doesn't seem to matter */
8642     len = sizeof(drive);
8643     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_UNKNOWN, drive, &len, &cost, &temp );
8644     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8645 
8646     len = sizeof(drive);
8647     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_ABSENT, drive, &len, &cost, &temp );
8648     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8649 
8650     len = sizeof(drive);
8651     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_SOURCE, drive, &len, &cost, &temp );
8652     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8653 
8654     len = sizeof(drive);
8655     drive[0] = 0;
8656     cost = temp = 0xdead;
8657     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8658     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8659     ok( len == 2, "expected len == 2, got %u\n", len );
8660     ok( drive[0], "expected a drive\n" );
8661     ok( cost && cost != 0xdead, "expected cost > 0, got %d\n", cost );
8662     ok( !temp, "expected temp == 0, got %d\n", temp );
8663 
8664     len = sizeof(drive);
8665     drive[0] = 0;
8666     cost = temp = 0xdead;
8667     r = MsiEnumComponentCostsA( hpkg, "two", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8668     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8669     ok( len == 2, "expected len == 2, got %u\n", len );
8670     ok( drive[0], "expected a drive\n" );
8671     ok( !cost, "expected cost == 0, got %d\n", cost );
8672     ok( !temp, "expected temp == 0, got %d\n", temp );
8673 
8674     len = sizeof(drive);
8675     drive[0] = 0;
8676     cost = temp = 0xdead;
8677     r = MsiEnumComponentCostsA( hpkg, "", 0, INSTALLSTATE_UNKNOWN, drive, &len, &cost, &temp );
8678     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8679     ok( len == 2, "expected len == 2, got %u\n", len );
8680     ok( drive[0], "expected a drive\n" );
8681     ok( !cost, "expected cost == 0, got %d\n", cost );
8682     ok( temp && temp != 0xdead, "expected temp > 0, got %d\n", temp );
8683 
8684     /* increased index */
8685     len = sizeof(drive);
8686     r = MsiEnumComponentCostsA( hpkg, "one", 1, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8687     ok( r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %u\n", r );
8688 
8689     len = sizeof(drive);
8690     r = MsiEnumComponentCostsA( hpkg, "", 1, INSTALLSTATE_UNKNOWN, drive, &len, &cost, &temp );
8691     ok( r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %u\n", r );
8692 
8693     MsiCloseHandle( hpkg );
8694 error:
8695     MsiCloseHandle( hdb );
8696     DeleteFileA( msifile );
8697 }
8698 
8699 static void test_MsiDatabaseCommit(void)
8700 {
8701     UINT r;
8702     MSIHANDLE hdb, hpkg = 0;
8703     char buf[32], package[12];
8704     DWORD sz;
8705 
8706     hdb = create_package_db();
8707     ok( hdb, "failed to create database\n" );
8708 
8709     create_property_table( hdb );
8710 
8711     sprintf( package, "#%u", hdb );
8712     r = MsiOpenPackageA( package, &hpkg );
8713     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
8714     {
8715         skip("Not enough rights to perform tests\n");
8716         goto error;
8717     }
8718     ok( r == ERROR_SUCCESS, "got %u\n", r );
8719 
8720     r = MsiSetPropertyA( hpkg, "PROP", "value" );
8721     ok( r == ERROR_SUCCESS, "got %u\n", r );
8722 
8723     buf[0] = 0;
8724     sz = sizeof(buf);
8725     r = MsiGetPropertyA( hpkg, "PROP", buf, &sz );
8726     ok( r == ERROR_SUCCESS, "MsiGetPropertyA returned %u\n", r );
8727     ok( !lstrcmpA( buf, "value" ), "got \"%s\"\n", buf );
8728 
8729     r = MsiDatabaseCommit( hdb );
8730     ok( r == ERROR_SUCCESS, "MsiDatabaseCommit returned %u\n", r );
8731 
8732     buf[0] = 0;
8733     sz = sizeof(buf);
8734     r = MsiGetPropertyA( hpkg, "PROP", buf, &sz );
8735     ok( r == ERROR_SUCCESS, "MsiGetPropertyA returned %u\n", r );
8736     ok( !lstrcmpA( buf, "value" ), "got \"%s\"\n", buf );
8737 
8738     MsiCloseHandle( hpkg );
8739 error:
8740     MsiCloseHandle( hdb );
8741     DeleteFileA( msifile );
8742 }
8743 
8744 static int externalui_ran;
8745 
8746 static INT CALLBACK externalui_callback(void *context, UINT message_type, LPCSTR message)
8747 {
8748     externalui_ran = 1;
8749     ok(message_type == INSTALLMESSAGE_USER, "expected INSTALLMESSAGE_USER, got %08x\n", message_type);
8750     return 0;
8751 }
8752 
8753 static int externalui_record_ran;
8754 
8755 static INT CALLBACK externalui_record_callback(void *context, UINT message_type, MSIHANDLE hrecord)
8756 {
8757     INT retval = context ? *((INT *)context) : 0;
8758     UINT r;
8759     externalui_record_ran = 1;
8760     ok(message_type == INSTALLMESSAGE_USER, "expected INSTALLMESSAGE_USER, got %08x\n", message_type);
8761     r = MsiRecordGetFieldCount(hrecord);
8762     ok(r == 1, "expected 1, got %u\n", r);
8763     r = MsiRecordGetInteger(hrecord, 1);
8764     ok(r == 12345, "expected 12345, got %u\n", r);
8765     return retval;
8766 }
8767 
8768 static void test_externalui(void)
8769 {
8770     /* test that external UI handlers work correctly */
8771 
8772     INSTALLUI_HANDLERA prev;
8773     INSTALLUI_HANDLER_RECORD prev_record;
8774     MSIHANDLE hpkg, hrecord;
8775     UINT r;
8776     INT retval = 0;
8777 
8778     prev = MsiSetExternalUIA(externalui_callback, INSTALLLOGMODE_USER, NULL);
8779 
8780     r = package_from_db(create_package_db(), &hpkg);
8781     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
8782     {
8783         skip("Not enough rights to perform tests\n");
8784         DeleteFileA(msifile);
8785         return;
8786     }
8787     ok(r == ERROR_SUCCESS, "Expected a valid package %u\n", r);
8788 
8789     hrecord = MsiCreateRecord(1);
8790     ok(hrecord, "Expected a valid record\n");
8791     r = MsiRecordSetStringA(hrecord, 0, "test message [1]");
8792     ok(r == ERROR_SUCCESS, "MsiSetString failed %u\n", r);
8793     r = MsiRecordSetInteger(hrecord, 1, 12345);
8794     ok(r == ERROR_SUCCESS, "MsiSetInteger failed %u\n", r);
8795 
8796     externalui_ran = 0;
8797     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
8798     ok(r == 0, "expected 0, got %u\n", r);
8799     ok(externalui_ran == 1, "external UI callback did not run\n");
8800 
8801     prev = MsiSetExternalUIA(prev, 0, NULL);
8802     ok(prev == externalui_callback, "wrong callback function %p\n", prev);
8803     r = MsiSetExternalUIRecord(externalui_record_callback, INSTALLLOGMODE_USER, &retval, &prev_record);
8804     ok(r == ERROR_SUCCESS, "MsiSetExternalUIRecord failed %u\n", r);
8805 
8806     externalui_ran = externalui_record_ran = 0;
8807     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
8808     ok(r == 0, "expected 0, got %u\n", r);
8809     ok(externalui_ran == 0, "external UI callback should not have run\n");
8810     ok(externalui_record_ran == 1, "external UI record callback did not run\n");
8811 
8812     MsiSetExternalUIA(externalui_callback, INSTALLLOGMODE_USER, NULL);
8813 
8814     externalui_ran = externalui_record_ran = 0;
8815     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
8816     ok(r == 0, "expected 0, got %u\n", r);
8817     ok(externalui_ran == 1, "external UI callback did not run\n");
8818     ok(externalui_record_ran == 1, "external UI record callback did not run\n");
8819 
8820     retval = 1;
8821     externalui_ran = externalui_record_ran = 0;
8822     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
8823     ok(r == 1, "expected 1, got %u\n", r);
8824     ok(externalui_ran == 0, "external UI callback should not have run\n");
8825     ok(externalui_record_ran == 1, "external UI record callback did not run\n");
8826 
8827     /* filter and context should be kept separately */
8828     r = MsiSetExternalUIRecord(externalui_record_callback, INSTALLLOGMODE_ERROR, &retval, &prev_record);
8829     ok(r == ERROR_SUCCESS, "MsiSetExternalUIRecord failed %u\n", r);
8830 
8831     externalui_ran = externalui_record_ran = 0;
8832     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
8833     ok(r == 0, "expected 0, got %u\n", r);
8834     ok(externalui_ran == 1, "external UI callback did not run\n");
8835     ok(externalui_record_ran == 0, "external UI record callback should not have run\n");
8836 
8837     MsiCloseHandle(hpkg);
8838     DeleteFileA(msifile);
8839 }
8840 
8841 struct externalui_message {
8842     UINT message;
8843     int field_count;
8844     char field[4][100];
8845     int match[4]; /* should we test for a match */
8846     int optional;
8847 };
8848 
8849 static struct externalui_message *sequence;
8850 static int sequence_count, sequence_size;
8851 
8852 static void add_message(const struct externalui_message *msg)
8853 {
8854     if (!sequence)
8855     {
8856         sequence_size = 10;
8857         sequence = HeapAlloc(GetProcessHeap(), 0, sequence_size * sizeof(*sequence));
8858     }
8859     if (sequence_count == sequence_size)
8860     {
8861         sequence_size *= 2;
8862         sequence = HeapReAlloc(GetProcessHeap(), 0, sequence, sequence_size * sizeof(*sequence));
8863     }
8864 
8865     assert(sequence);
8866 
8867     sequence[sequence_count++] = *msg;
8868 }
8869 
8870 static void flush_sequence(void)
8871 {
8872     HeapFree(GetProcessHeap(), 0, sequence);
8873     sequence = NULL;
8874     sequence_count = sequence_size = 0;
8875 }
8876 
8877 static void ok_sequence_(const struct externalui_message *expected, const char *context, BOOL todo,
8878                          const char *file, int line)
8879 {
8880     static const struct externalui_message end_of_sequence = {0};
8881     const struct externalui_message *actual;
8882     int failcount = 0;
8883     int i;
8884 
8885     add_message(&end_of_sequence);
8886 
8887     actual = sequence;
8888 
8889     while (expected->message && actual->message)
8890     {
8891         if (expected->message == actual->message)
8892         {
8893             if (expected->field_count < actual->field_count)
8894             {
8895                 todo_wine_if (todo)
8896                     ok_(file, line) (FALSE, "%s: in msg 0x%08x expecting field count %d got %d\n",
8897                                      context, expected->message, expected->field_count, actual->field_count);
8898                 failcount++;
8899             }
8900 
8901             for (i = 0; i <= actual->field_count; i++)
8902             {
8903                 if (expected->match[i] && strcmp(expected->field[i], actual->field[i]))
8904                 {
8905                     todo_wine_if (todo)
8906                         ok_(file, line) (FALSE, "%s: in msg 0x%08x field %d: expected \"%s\", got \"%s\"\n",
8907                                          context, expected->message, i, expected->field[i], actual->field[i]);
8908                     failcount++;
8909                 }
8910             }
8911 
8912             expected++;
8913             actual++;
8914         }
8915         else if (expected->optional)
8916         {
8917             expected++;
8918         }
8919         else
8920         {
8921             todo_wine_if (todo)
8922                 ok_(file, line) (FALSE, "%s: the msg 0x%08x was expected, but got msg 0x%08x instead\n",
8923                                  context, expected->message, actual->message);
8924             failcount++;
8925             if (todo)
8926                 goto done;
8927             expected++;
8928             actual++;
8929         }
8930     }
8931 
8932     if (expected->message || actual->message)
8933     {
8934         todo_wine_if (todo)
8935             ok_(file, line) (FALSE, "%s: the msg sequence is not complete: expected %08x - actual %08x\n",
8936                              context, expected->message, actual->message);
8937         failcount++;
8938     }
8939 
8940     if(todo && !failcount) /* succeeded yet marked todo */
8941     {
8942         todo_wine
8943             ok_(file, line)(TRUE, "%s: marked \"todo_wine\" but succeeds\n", context);
8944     }
8945 
8946 done:
8947     flush_sequence();
8948 }
8949 
8950 #define ok_sequence(exp, contx, todo) \
8951         ok_sequence_((exp), (contx), (todo), __FILE__, __LINE__)
8952 
8953 /* don't use PROGRESS, which is timing-dependent,
8954  * or SHOWDIALOG, which due to a bug causes a hang on XP */
8955 static const INSTALLLOGMODE MSITEST_INSTALLLOGMODE =
8956     INSTALLLOGMODE_FATALEXIT |
8957     INSTALLLOGMODE_ERROR |
8958     INSTALLLOGMODE_WARNING |
8959     INSTALLLOGMODE_USER |
8960     INSTALLLOGMODE_INFO |
8961     INSTALLLOGMODE_FILESINUSE |
8962     INSTALLLOGMODE_RESOLVESOURCE |
8963     INSTALLLOGMODE_OUTOFDISKSPACE |
8964     INSTALLLOGMODE_ACTIONSTART |
8965     INSTALLLOGMODE_ACTIONDATA |
8966     INSTALLLOGMODE_COMMONDATA |
8967     INSTALLLOGMODE_INITIALIZE |
8968     INSTALLLOGMODE_TERMINATE |
8969     INSTALLLOGMODE_RMFILESINUSE |
8970     INSTALLLOGMODE_INSTALLSTART |
8971     INSTALLLOGMODE_INSTALLEND;
8972 
8973 static const struct externalui_message empty_sequence[] = {
8974     {0}
8975 };
8976 
8977 static const struct externalui_message openpackage_nonexistent_sequence[] = {
8978     {INSTALLMESSAGE_INITIALIZE, -1},
8979     {INSTALLMESSAGE_TERMINATE, -1},
8980     {0}
8981 };
8982 
8983 static const struct externalui_message openpackage_sequence[] = {
8984     {INSTALLMESSAGE_INITIALIZE, -1},
8985     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
8986     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
8987     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
8988     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
8989     {0}
8990 };
8991 
8992 static const struct externalui_message processmessage_info_sequence[] = {
8993     {INSTALLMESSAGE_INFO, 3, {"zero", "one", "two", "three"}, {1, 1, 1, 1}},
8994     {0}
8995 };
8996 
8997 static const struct externalui_message processmessage_actionstart_sequence[] = {
8998     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "name", "description", "template"}, {0, 1, 1, 1}},
8999     {0}
9000 };
9001 
9002 static const struct externalui_message processmessage_actiondata_sequence[] = {
9003     {INSTALLMESSAGE_ACTIONDATA, 3, {"{{name: }}template", "cherry", "banana", "guava"}, {1, 1, 1, 1}},
9004     {0}
9005 };
9006 
9007 static const struct externalui_message processmessage_error_sequence[] = {
9008     {INSTALLMESSAGE_USER, 3, {"", "1311", "banana", "guava"}, {0, 1, 1, 1}},
9009     {0}
9010 };
9011 
9012 static const struct externalui_message processmessage_internal_error_sequence[] = {
9013     {INSTALLMESSAGE_INFO, 3, {"DEBUG: Error [1]:  Action not found: [2]", "2726", "banana", "guava"}, {1, 1, 1, 1}},
9014     {INSTALLMESSAGE_USER, 3, {"internal error", "2726", "banana", "guava"}, {1, 1, 1, 1}},
9015     {0}
9016 };
9017 
9018 static const struct externalui_message processmessage_error_format_sequence[] = {
9019     {INSTALLMESSAGE_USER, 3, {"", "2726", "banana", "guava"}, {0, 1, 1, 1}},
9020     {0}
9021 };
9022 
9023 static const struct externalui_message doaction_costinitialize_sequence[] = {
9024     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostInitialize", "cost description", "cost template"}, {0, 1, 1, 1}},
9025     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", ""}, {0, 1, 1}},
9026     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", "1"}, {0, 1, 1}},
9027     {0}
9028 };
9029 
9030 static const struct externalui_message doaction_custom_sequence[] = {
9031     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "description", "template"}, {0, 1, 1, 1}},
9032     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
9033     {INSTALLMESSAGE_INFO, 2, {"", "custom", "0"}, {0, 1, 1}},
9034     {0}
9035 };
9036 
9037 static const struct externalui_message doaction_custom_fullui_sequence[] = {
9038     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
9039     {INSTALLMESSAGE_INFO, 2, {"", "custom", ""}, {0, 1, 1}},
9040     {INSTALLMESSAGE_SHOWDIALOG, 0, {"custom"}, {1}},
9041     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
9042     {0}
9043 };
9044 
9045 static const struct externalui_message doaction_custom_cancel_sequence[] = {
9046     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
9047     {0}
9048 };
9049 
9050 static const struct externalui_message doaction_dialog_nonexistent_sequence[] = {
9051     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
9052     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
9053     {INSTALLMESSAGE_SHOWDIALOG, 0, {"custom"}, {1}},
9054     {INSTALLMESSAGE_INFO, 2, {"DEBUG: Error [1]:  Action not found: [2]", "2726", "custom"}, {1, 1, 1}},
9055     {INSTALLMESSAGE_INFO, 2, {"", "2726", "custom"}, {0, 1, 1}},
9056     {INSTALLMESSAGE_INFO, 2, {"", "custom", "0"}, {0, 1, 1}},
9057     {0}
9058 };
9059 
9060 static const struct externalui_message doaction_dialog_sequence[] = {
9061     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "dialog", "", ""}, {0, 1, 1, 1}},
9062     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "0"}, {0, 1, 1}},
9063     {INSTALLMESSAGE_SHOWDIALOG, 0, {"dialog"}, {1}},
9064     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "dialog", "Dialog created"}, {0, 1, 1}},
9065     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "1"}, {0, 1, 1}},
9066     {0}
9067 };
9068 
9069 static const struct externalui_message doaction_dialog_error_sequence[] = {
9070     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "error", "", ""}, {0, 1, 1, 1}},
9071     {INSTALLMESSAGE_INFO, 2, {"", "error", "1"}, {0, 1, 1}},
9072     {INSTALLMESSAGE_SHOWDIALOG, 0, {"error"}, {1}},
9073     {0}
9074 };
9075 
9076 static const struct externalui_message doaction_dialog_3_sequence[] = {
9077     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "dialog", "", ""}, {0, 1, 1, 1}},
9078     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "0"}, {0, 1, 1}},
9079     {INSTALLMESSAGE_SHOWDIALOG, 0, {"dialog"}, {1}},
9080     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "3"}, {0, 1, 1}},
9081     {0}
9082 };
9083 
9084 static const struct externalui_message doaction_dialog_12345_sequence[] = {
9085     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "dialog", "", ""}, {0, 1, 1, 1}},
9086     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "3"}, {0, 1, 1}},
9087     {INSTALLMESSAGE_SHOWDIALOG, 0, {"dialog"}, {1}},
9088     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "12345"}, {0, 1, 1}},
9089     {0}
9090 };
9091 
9092 static const struct externalui_message closehandle_sequence[] = {
9093     {INSTALLMESSAGE_TERMINATE, -1},
9094     {0}
9095 };
9096 
9097 static INT CALLBACK externalui_message_string_callback(void *context, UINT message, LPCSTR string)
9098 {
9099     INT retval = context ? *((INT *)context) : 0;
9100     struct externalui_message msg;
9101 
9102     msg.message = message;
9103     msg.field_count = 0;
9104     strcpy(msg.field[0], string);
9105     add_message(&msg);
9106 
9107     return retval;
9108 }
9109 
9110 static INT CALLBACK externalui_message_callback(void *context, UINT message, MSIHANDLE hrecord)
9111 {
9112     INT retval = context ? *((INT *)context) : 0;
9113     struct externalui_message msg;
9114     char buffer[256];
9115     DWORD length;
9116     UINT r;
9117     int i;
9118 
9119     msg.message = message;
9120     if (message == INSTALLMESSAGE_TERMINATE)
9121     {
9122         /* trying to access the record seems to hang on some versions of Windows */
9123         msg.field_count = -1;
9124         add_message(&msg);
9125         return 1;
9126     }
9127     msg.field_count = MsiRecordGetFieldCount(hrecord);
9128     for (i = 0; i <= msg.field_count; i++)
9129     {
9130         length = sizeof(buffer);
9131         r = MsiRecordGetStringA(hrecord, i, buffer, &length);
9132         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
9133         memcpy(msg.field[i], buffer, min(100, length+1));
9134     }
9135 
9136     /* top-level actions dump a list of all set properties; skip them since they're inconsistent */
9137     if (message == (INSTALLMESSAGE_INFO|MB_ICONHAND) && msg.field_count > 0 && !strncmp(msg.field[0], "Property", 8))
9138         return retval;
9139 
9140     add_message(&msg);
9141 
9142     return retval;
9143 }
9144 
9145 static void test_externalui_message(void)
9146 {
9147     /* test that events trigger the correct sequence of messages */
9148 
9149     INSTALLUI_HANDLER_RECORD prev;
9150     MSIHANDLE hdb, hpkg, hrecord;
9151     INT retval = 1;
9152     UINT r;
9153 
9154     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
9155 
9156     MsiSetExternalUIA(externalui_message_string_callback, INSTALLLOGMODE_SHOWDIALOG, &retval);
9157     r = MsiSetExternalUIRecord(externalui_message_callback, MSITEST_INSTALLLOGMODE, &retval, &prev);
9158 
9159     flush_sequence();
9160 
9161     CoInitialize(NULL);
9162 
9163     hdb = create_package_db();
9164     ok(hdb, "failed to create database\n");
9165 
9166     create_file_data("forcecodepage.idt", "\r\n\r\n1252\t_ForceCodepage\r\n");
9167     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
9168     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9169 
9170     r = run_query(hdb, "CREATE TABLE `Error` (`Error` SHORT NOT NULL, `Message` CHAR(0) PRIMARY KEY `Error`)");
9171     ok(r == ERROR_SUCCESS, "Failed to create Error table: %u\n", r);
9172     r = run_query(hdb, "INSERT INTO `Error` (`Error`, `Message`) VALUES (5, 'internal error')");
9173     ok(r == ERROR_SUCCESS, "Failed to insert into Error table: %u\n", r);
9174 
9175     create_actiontext_table(hdb);
9176     add_actiontext_entry(hdb, "'custom', 'description', 'template'");
9177     add_actiontext_entry(hdb, "'CostInitialize', 'cost description', 'cost template'");
9178 
9179     r = MsiOpenPackageA(NULL, &hpkg);
9180     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9181     ok_sequence(empty_sequence, "MsiOpenPackage with NULL db", FALSE);
9182 
9183     r = MsiOpenPackageA("nonexistent", &hpkg);
9184     ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
9185     ok_sequence(openpackage_nonexistent_sequence, "MsiOpenPackage with nonexistent db", FALSE);
9186 
9187     r = package_from_db(hdb, &hpkg);
9188     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
9189     {
9190         skip("Not enough rights to perform tests\n");
9191         DeleteFileA(msifile);
9192         return;
9193     }
9194     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
9195     ok_sequence(openpackage_sequence, "MsiOpenPackage with valid db", FALSE);
9196 
9197     /* Test MsiProcessMessage */
9198     hrecord = MsiCreateRecord(3);
9199     ok(hrecord, "failed to create record\n");
9200 
9201     MsiRecordSetStringA(hrecord, 0, "zero");
9202     MsiRecordSetStringA(hrecord, 1, "one");
9203     MsiRecordSetStringA(hrecord, 2, "two");
9204     MsiRecordSetStringA(hrecord, 3, "three");
9205     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_INFO, hrecord);
9206     ok(r == 1, "Expected 1, got %d\n", r);
9207     ok_sequence(processmessage_info_sequence, "MsiProcessMessage(INSTALLMESSAGE_INFO)", FALSE);
9208 
9209     MsiRecordSetStringA(hrecord, 1, "name");
9210     MsiRecordSetStringA(hrecord, 2, "description");
9211     MsiRecordSetStringA(hrecord, 3, "template");
9212     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_ACTIONSTART, hrecord);
9213     ok(r == 1, "Expected 1, got %d\n", r);
9214     ok_sequence(processmessage_actionstart_sequence, "MsiProcessMessage(INSTALLMESSAGE_ACTIONSTART)", FALSE);
9215 
9216     MsiRecordSetStringA(hrecord, 0, "apple");
9217     MsiRecordSetStringA(hrecord, 1, "cherry");
9218     MsiRecordSetStringA(hrecord, 2, "banana");
9219     MsiRecordSetStringA(hrecord, 3, "guava");
9220     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_ACTIONDATA, hrecord);
9221     ok(r == 1, "Expected 1, got %d\n", r);
9222     ok_sequence(processmessage_actiondata_sequence, "MsiProcessMessage(INSTALLMESSAGE_ACTIONDATA)", FALSE);
9223 
9224     /* non-internal error */
9225     MsiRecordSetStringA(hrecord, 0, NULL);
9226     MsiRecordSetInteger(hrecord, 1, 1311);
9227     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
9228     ok(r == 1, "Expected 1, got %d\n", r);
9229     ok_sequence(processmessage_error_sequence, "MsiProcessMessage non-internal error", FALSE);
9230 
9231     /* internal error */
9232     MsiRecordSetStringA(hrecord, 0, NULL);
9233     MsiRecordSetInteger(hrecord, 1, 2726);
9234     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
9235     ok(r == 0, "Expected 0, got %d\n", r);
9236     ok_sequence(processmessage_internal_error_sequence, "MsiProcessMessage internal error", FALSE);
9237 
9238     /* with format field */
9239     MsiRecordSetStringA(hrecord, 0, "starfruit");
9240     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
9241     ok(r == 1, "Expected 1, got %d\n", r);
9242     ok_sequence(processmessage_error_format_sequence, "MsiProcessMessage error", FALSE);
9243 
9244     /* Test a standard action */
9245     r = MsiDoActionA(hpkg, "CostInitialize");
9246     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9247     ok_sequence(doaction_costinitialize_sequence, "MsiDoAction(\"CostInitialize\")", FALSE);
9248 
9249     /* Test a custom action */
9250     r = MsiDoActionA(hpkg, "custom");
9251     ok(r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %d\n", r);
9252     ok_sequence(doaction_custom_sequence, "MsiDoAction(\"custom\")", FALSE);
9253 
9254     /* close the package */
9255     MsiCloseHandle(hpkg);
9256     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
9257 
9258     /* Test dialogs */
9259     hdb = create_package_db();
9260     ok(hdb, "failed to create database\n");
9261 
9262     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
9263     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9264 
9265     create_dialog_table(hdb);
9266     add_dialog_entry(hdb, "'dialog', 50, 50, 100, 100, 0, 'dummy'");
9267 
9268     create_control_table(hdb);
9269     add_control_entry(hdb, "'dialog', 'dummy', 'Text', 5, 5, 5, 5, 3, 'dummy'");
9270 
9271     r = package_from_db(hdb, &hpkg);
9272     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
9273     ok_sequence(openpackage_sequence, "MsiOpenPackage with valid db", FALSE);
9274 
9275     /* Test a custom action */
9276     r = MsiDoActionA(hpkg, "custom");
9277     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9278     ok_sequence(doaction_custom_fullui_sequence, "MsiDoAction(\"custom\")", FALSE);
9279 
9280     retval = 2;
9281     r = MsiDoActionA(hpkg, "custom");
9282     ok(r == ERROR_INSTALL_USEREXIT, "Expected ERROR_INSTALL_USEREXIT, got %d\n", r);
9283     ok_sequence(doaction_custom_cancel_sequence, "MsiDoAction(\"custom\")", FALSE);
9284 
9285     retval = 0;
9286     r = MsiDoActionA(hpkg, "custom");
9287     ok(r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %d\n", r);
9288     ok_sequence(doaction_dialog_nonexistent_sequence, "MsiDoAction(\"custom\")", FALSE);
9289 
9290     r = MsiDoActionA(hpkg, "dialog");
9291     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9292     ok_sequence(doaction_dialog_sequence, "MsiDoAction(\"dialog\")", FALSE);
9293 
9294     retval = -1;
9295     r = MsiDoActionA(hpkg, "error");
9296     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9297     ok_sequence(doaction_dialog_error_sequence, "MsiDoAction(\"error\")", FALSE);
9298 
9299     r = MsiDoActionA(hpkg, "error");
9300     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9301     ok_sequence(doaction_dialog_error_sequence, "MsiDoAction(\"error\")", FALSE);
9302 
9303     retval = -2;
9304     r = MsiDoActionA(hpkg, "custom");
9305     ok(r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %d\n", r);
9306     ok_sequence(doaction_dialog_nonexistent_sequence, "MsiDoAction(\"custom\")", FALSE);
9307 
9308     retval = 3;
9309     r = MsiDoActionA(hpkg, "dialog");
9310     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %d\n", r);
9311     ok_sequence(doaction_dialog_3_sequence, "MsiDoAction(\"dialog\")", FALSE);
9312 
9313     retval = 12345;
9314     r = MsiDoActionA(hpkg, "dialog");
9315     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_INSTALL_FAILURE, got %d\n", r);
9316     ok_sequence(doaction_dialog_12345_sequence, "MsiDoAction(\"dialog\")", FALSE);
9317 
9318     MsiCloseHandle(hpkg);
9319     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
9320 
9321     MsiCloseHandle(hrecord);
9322     CoUninitialize();
9323     DeleteFileA(msifile);
9324     DeleteFileA("forcecodepage.idt");
9325 }
9326 
9327 static const struct externalui_message controlevent_spawn_sequence[] = {
9328     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "spawn", "", ""}, {0, 1, 1, 1}},
9329     {INSTALLMESSAGE_INFO, 2, {"", "spawn", ""}, {0, 1, 1}},
9330     {INSTALLMESSAGE_SHOWDIALOG, 0, {"spawn"}, {1}},
9331     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "spawn", "Dialog created"}, {0, 1, 1}},
9332 
9333     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
9334     {INSTALLMESSAGE_INFO, 2, {"", "custom", ""}, {0, 1, 1}},
9335     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
9336 
9337     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "child1", "Dialog created"}, {0, 1, 1}},
9338 
9339     {INSTALLMESSAGE_INFO, 2, {"", "spawn", "2"}, {0, 1, 1}},
9340     {0}
9341 };
9342 
9343 static const struct externalui_message controlevent_spawn2_sequence[] = {
9344     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "spawn2", "", ""}, {0, 1, 1, 1}},
9345     {INSTALLMESSAGE_INFO, 2, {"", "spawn2", "2"}, {0, 1, 1}},
9346     {INSTALLMESSAGE_SHOWDIALOG, 0, {"spawn2"}, {1}},
9347     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "spawn2", "Dialog created"}, {0, 1, 1}},
9348 
9349     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
9350     {INSTALLMESSAGE_INFO, 2, {"", "custom", "2"}, {0, 1, 1}},
9351     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
9352 
9353     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "child2", "Dialog created"}, {0, 1, 1}},
9354 
9355     {INSTALLMESSAGE_INFO, 2, {"", "spawn2", "2"}, {0, 1, 1}},
9356     {0}
9357 };
9358 
9359 static void test_controlevent(void)
9360 {
9361     INSTALLUI_HANDLER_RECORD prev;
9362     MSIHANDLE hdb, hpkg;
9363     UINT r;
9364 
9365     if (!winetest_interactive)
9366     {
9367         skip("interactive ControlEvent tests\n");
9368         return;
9369     }
9370 
9371     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
9372 
9373     MsiSetExternalUIA(externalui_message_string_callback, INSTALLLOGMODE_SHOWDIALOG, NULL);
9374     r = MsiSetExternalUIRecord(externalui_message_callback, MSITEST_INSTALLLOGMODE, NULL, &prev);
9375 
9376     flush_sequence();
9377 
9378     CoInitialize(NULL);
9379 
9380     hdb = create_package_db();
9381     ok(hdb, "failed to create database\n");
9382 
9383     create_file_data("forcecodepage.idt", "\r\n\r\n1252\t_ForceCodepage\r\n");
9384     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
9385     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9386 
9387     create_dialog_table(hdb);
9388     add_dialog_entry(hdb, "'spawn', 50, 50, 100, 100, 3, 'button'");
9389     add_dialog_entry(hdb, "'spawn2', 50, 50, 100, 100, 3, 'button'");
9390     add_dialog_entry(hdb, "'child1', 50, 50, 80, 40, 3, 'exit'");
9391     add_dialog_entry(hdb, "'child2', 50, 50, 80, 40, 3, 'exit'");
9392 
9393     create_control_table(hdb);
9394     add_control_entry(hdb, "'spawn', 'button', 'PushButton', 10, 10, 66, 17, 3, 'Click me'");
9395     add_control_entry(hdb, "'spawn2', 'button', 'PushButton', 10, 10, 66, 17, 3, 'Click me'");
9396     add_control_entry(hdb, "'child1', 'exit', 'PushButton', 10, 10, 66, 17, 3, 'Click me'");
9397     add_control_entry(hdb, "'child2', 'exit', 'PushButton', 10, 10, 66, 17, 3, 'Click me'");
9398 
9399     create_controlevent_table(hdb);
9400     add_controlevent_entry(hdb, "'child1', 'exit', 'EndDialog', 'Exit', 1, 1");
9401     add_controlevent_entry(hdb, "'child2', 'exit', 'EndDialog', 'Exit', 1, 1");
9402 
9403     create_custom_action_table(hdb);
9404     add_custom_action_entry(hdb, "'custom', 51, 'dummy', 'dummy value'");
9405 
9406     /* SpawnDialog and EndDialog should trigger after all other events */
9407     add_controlevent_entry(hdb, "'spawn', 'button', 'SpawnDialog', 'child1', 1, 1");
9408     add_controlevent_entry(hdb, "'spawn', 'button', 'DoAction', 'custom', 1, 2");
9409 
9410     /* Multiple dialog events cause only the last one to be triggered */
9411     add_controlevent_entry(hdb, "'spawn2', 'button', 'SpawnDialog', 'child1', 1, 1");
9412     add_controlevent_entry(hdb, "'spawn2', 'button', 'SpawnDialog', 'child2', 1, 2");
9413     add_controlevent_entry(hdb, "'spawn2', 'button', 'DoAction', 'custom', 1, 3");
9414 
9415     r = package_from_db(hdb, &hpkg);
9416     ok(r == ERROR_SUCCESS, "failed to create package: %u\n", r);
9417     ok_sequence(openpackage_sequence, "MsiOpenPackage()", FALSE);
9418 
9419     r = MsiDoActionA(hpkg, "spawn");
9420     ok(r == ERROR_INSTALL_USEREXIT, "expected ERROR_INSTALL_USEREXIT, got %u\n", r);
9421     ok_sequence(controlevent_spawn_sequence, "control event: spawn", FALSE);
9422 
9423     r = MsiDoActionA(hpkg, "spawn2");
9424     ok(r == ERROR_INSTALL_USEREXIT, "expected ERROR_INSTALL_USEREXIT, got %u\n", r);
9425     ok_sequence(controlevent_spawn2_sequence, "control event: spawn2", FALSE);
9426 
9427     MsiCloseHandle(hpkg);
9428     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
9429 
9430     CoUninitialize();
9431     DeleteFileA(msifile);
9432     DeleteFileA("forcecodepage.idt");
9433 }
9434 
9435 static const struct externalui_message toplevel_install_sequence[] = {
9436     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "INSTALL", "", ""}, {0, 1, 1, 1}},
9437     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", ""}, {0, 1, 1}},
9438 
9439     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9440     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9441     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
9442     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9443     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9444 
9445     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "INSTALL", "", ""}, {0, 1, 1, 1}},
9446     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", ""}, {0, 1, 1}},
9447     {INSTALLMESSAGE_INSTALLSTART, 2, {"", "", "{7262AC98-EEBD-4364-8CE3-D654F6A425B9}"}, {1, 1, 1}, 1},
9448 
9449     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostInitialize", "", ""}, {0, 1, 0, 1}},
9450     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", ""}, {0, 1, 1}},
9451     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", "1"}, {0, 1, 1}},
9452 
9453     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "FileCost", "", ""}, {0, 1, 0, 1}},
9454     {INSTALLMESSAGE_INFO, 2, {"", "FileCost", "1"}, {0, 1, 1}},
9455     {INSTALLMESSAGE_INFO, 2, {"", "FileCost", "1"}, {0, 1, 1}},
9456 
9457     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostFinalize", "", ""}, {0, 1, 0, 1}},
9458     {INSTALLMESSAGE_INFO, 2, {"", "CostFinalize", "1"}, {0, 1, 1}},
9459     {INSTALLMESSAGE_INFO, 2, {"", "CostFinalize", "1"}, {0, 1, 1}},
9460 
9461     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", "1"}, {0, 1, 1}},
9462     {INSTALLMESSAGE_INSTALLEND, 3, {"", "", "{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "1"}, {1, 1, 1, 1}, 1},
9463 
9464     /* property dump */
9465 
9466     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "0"}, {0, 1, 1}, 1},
9467     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "1"}, {0, 1, 1}, 1},
9468     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", "1"}, {0, 1, 1}},
9469     {0}
9470 };
9471 
9472 static const struct externalui_message toplevel_install_ui_sequence[] = {
9473     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "INSTALL", "", ""}, {0, 1, 1, 1}},
9474     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", ""}, {0, 1, 1}},
9475 
9476     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "AppSearch", "", ""}, {0, 1, 0, 0}},
9477     {INSTALLMESSAGE_INFO, 2, {"", "AppSearch", ""}, {0, 1, 1}},
9478     {INSTALLMESSAGE_INFO, 2, {"", "AppSearch", "0"}, {0, 1, 1}},
9479 
9480     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", "1"}, {0, 1, 1}},
9481     {0}
9482 };
9483 
9484 static const struct externalui_message toplevel_executeaction_install_sequence[] = {
9485     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "ExecuteAction", "", ""}, {0, 1, 1, 1}},
9486     {INSTALLMESSAGE_INFO, 2, {"", "ExecuteAction", "1"}, {0, 1, 1}},
9487 
9488     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9489     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9490     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9491     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9492 
9493     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "INSTALL", "", ""}, {0, 1, 1, 1}},
9494     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", ""}, {0, 1, 1}},
9495     {INSTALLMESSAGE_INSTALLSTART, 2, {"", "", "{7262AC98-EEBD-4364-8CE3-D654F6A425B9}"}, {1, 1, 1}, 1},
9496 
9497     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostInitialize", "", ""}, {0, 1, 0, 1}},
9498     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize"}, {0, 1}},
9499     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", "1"}, {0, 1, 1}},
9500 
9501     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "FileCost", "", ""}, {0, 1, 0, 1}},
9502     {INSTALLMESSAGE_INFO, 2, {"", "FileCost", "1"}, {0, 1, 1}},
9503     {INSTALLMESSAGE_INFO, 2, {"", "FileCost", "1"}, {0, 1, 1}},
9504 
9505     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostFinalize", "", ""}, {0, 1, 0, 1}},
9506     {INSTALLMESSAGE_INFO, 2, {"", "CostFinalize", "1"}, {0, 1, 1}},
9507     {INSTALLMESSAGE_INFO, 2, {"", "CostFinalize", "1"}, {0, 1, 1}},
9508 
9509     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", "1"}, {0, 1, 1}},
9510     {INSTALLMESSAGE_INSTALLEND, 3, {"", "", "{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "1"}, {1, 1, 1, 1}, 1},
9511 
9512     /* property dump */
9513 
9514     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "0"}, {0, 1, 1}, 1},
9515     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "1"}, {0, 1, 1}, 1},
9516     {INSTALLMESSAGE_INFO, 2, {"", "ExecuteAction", "1"}, {0, 1, 1}},
9517     {0}
9518 };
9519 
9520 static const struct externalui_message toplevel_executeaction_costinitialize_sequence[] = {
9521     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "ExecuteAction", "", ""}, {0, 1, 1, 1}},
9522     {INSTALLMESSAGE_INFO, 2, {"", "ExecuteAction", "1"}, {0, 1, 1}},
9523 
9524     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9525     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9526     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9527     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9528 
9529     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostInitialize", "", ""}, {0, 1, 0, 1}},
9530     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", ""}, {0, 1}},
9531     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", "1"}, {0, 1, 1}},
9532 
9533     /* property dump */
9534 
9535     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "0"}, {0, 1, 1}, 1},
9536     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "1"}, {0, 1, 1}, 1},
9537     {INSTALLMESSAGE_INFO, 2, {"", "ExecuteAction", "1"}, {0, 1, 1}},
9538     {0}
9539 };
9540 
9541 static const struct externalui_message toplevel_msiinstallproduct_sequence[] = {
9542     {INSTALLMESSAGE_INITIALIZE, -1},
9543 
9544     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9545     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9546     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
9547     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9548     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9549 
9550     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "INSTALL", "", ""}, {0, 1, 1, 1}},
9551     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", ""}, {0, 1, 1}},
9552 
9553     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "AppSearch", "", ""}, {0, 1, 0, 0}},
9554     {INSTALLMESSAGE_INFO, 2, {"", "AppSearch", ""}, {0, 1, 1}},
9555     {INSTALLMESSAGE_INFO, 2, {"", "AppSearch", "0"}, {0, 1, 1}},
9556 
9557     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", "1"}, {0, 1, 1}},
9558 
9559     /* property dump */
9560 
9561     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
9562     {INSTALLMESSAGE_TERMINATE, -1},
9563     {0}
9564 };
9565 
9566 static const struct externalui_message toplevel_msiinstallproduct_custom_sequence[] = {
9567     {INSTALLMESSAGE_INITIALIZE, -1},
9568 
9569     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9570     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9571     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
9572     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9573     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9574 
9575     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CUSTOM", "", ""}, {0, 1, 1, 1}},
9576     {INSTALLMESSAGE_INFO, 2, {"", "CUSTOM", ""}, {0, 1, 1}},
9577     {INSTALLMESSAGE_INFO, 2, {"", "CUSTOM", "0"}, {0, 1, 1}},
9578 
9579     /* property dump */
9580 
9581     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
9582     {INSTALLMESSAGE_TERMINATE, -1},
9583     {0}
9584 };
9585 
9586 /* tests involving top-level actions: INSTALL, ExecuteAction */
9587 static void test_top_level_action(void)
9588 {
9589     INSTALLUI_HANDLER_RECORD prev;
9590     MSIHANDLE hdb, hpkg;
9591     UINT r;
9592     char msifile_absolute[MAX_PATH];
9593 
9594     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
9595 
9596     MsiSetExternalUIA(externalui_message_string_callback, INSTALLLOGMODE_SHOWDIALOG, NULL);
9597     r = MsiSetExternalUIRecord(externalui_message_callback, MSITEST_INSTALLLOGMODE, NULL, &prev);
9598 
9599     flush_sequence();
9600 
9601     CoInitialize(NULL);
9602 
9603     hdb = create_package_db();
9604     ok(hdb, "failed to create database\n");
9605 
9606     create_file_data("forcecodepage.idt", "\r\n\r\n1252\t_ForceCodepage\r\n");
9607     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
9608     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9609 
9610     create_property_table(hdb);
9611     add_property_entry(hdb, "'ProductCode', '{7262AC98-EEBD-4364-8CE3-D654F6A425B9}'");
9612 
9613     create_install_execute_sequence_table(hdb);
9614     add_install_execute_sequence_entry(hdb, "'CostInitialize', '', 1");
9615     add_install_execute_sequence_entry(hdb, "'FileCost', '', 2");
9616     add_install_execute_sequence_entry(hdb, "'CostFinalize', '', 3");
9617 
9618     create_install_ui_sequence_table(hdb);
9619     add_install_ui_sequence_entry(hdb, "'AppSearch', '', 1");
9620 
9621     MsiDatabaseCommit(hdb);
9622 
9623     /* for some reason we have to open the package from file using an absolute path */
9624     MsiCloseHandle(hdb);
9625     GetFullPathNameA(msifile, MAX_PATH, msifile_absolute, NULL);
9626     r = MsiOpenPackageA(msifile_absolute, &hpkg);
9627     ok(r == ERROR_SUCCESS, "failed to create package: %u\n", r);
9628     ok_sequence(openpackage_sequence, "MsiOpenPackage()", FALSE);
9629 
9630     /* test INSTALL */
9631     r = MsiDoActionA(hpkg, "INSTALL");
9632     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
9633     ok_sequence(toplevel_install_sequence, "INSTALL (no UI)", FALSE);
9634 
9635     /* test INSTALL with reduced+ UI */
9636     /* for some reason we need to re-open the package to change the internal UI */
9637     MsiCloseHandle(hpkg);
9638     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
9639     MsiSetInternalUI(INSTALLUILEVEL_REDUCED, NULL);
9640     r = MsiOpenPackageA(msifile_absolute, &hpkg);
9641     ok(r == ERROR_SUCCESS, "failed to create package: %u\n", r);
9642     ok_sequence(openpackage_sequence, "MsiOpenPackage()", FALSE);
9643 
9644     r = MsiDoActionA(hpkg, "INSTALL");
9645     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
9646     ok_sequence(toplevel_install_ui_sequence, "INSTALL (reduced+ UI)", TRUE);
9647 
9648     /* test ExecuteAction with EXECUTEACTION property unset */
9649     MsiSetPropertyA(hpkg, "EXECUTEACTION", NULL);
9650     r = MsiDoActionA(hpkg, "ExecuteAction");
9651     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
9652     ok_sequence(toplevel_executeaction_install_sequence, "ExecuteAction: INSTALL", FALSE);
9653 
9654     /* test ExecuteAction with EXECUTEACTION property set */
9655     MsiSetPropertyA(hpkg, "EXECUTEACTION", "CostInitialize");
9656     r = MsiDoActionA(hpkg, "ExecuteAction");
9657     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
9658     ok_sequence(toplevel_executeaction_costinitialize_sequence, "ExecuteAction: CostInitialize", FALSE);
9659 
9660     MsiCloseHandle(hpkg);
9661     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
9662 
9663     /* test MsiInstallProduct() */
9664     r = MsiInstallProductA(msifile_absolute, NULL);
9665     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
9666     ok_sequence(toplevel_msiinstallproduct_sequence, "MsiInstallProduct()", TRUE);
9667 
9668     r = MsiInstallProductA(msifile_absolute, "ACTION=custom");
9669     todo_wine
9670     ok(r == ERROR_INSTALL_FAILURE, "expected ERROR_INSTALL_FAILURE, got %u\n", r);
9671     ok_sequence(toplevel_msiinstallproduct_custom_sequence, "MsiInstallProduct(ACTION=custom)", TRUE);
9672 
9673     CoUninitialize();
9674     DeleteFileA(msifile);
9675     DeleteFileA("forcecodepage.idt");
9676 }
9677 
9678 START_TEST(package)
9679 {
9680     STATEMGRSTATUS status;
9681     BOOL ret = FALSE;
9682 
9683     init_functionpointers();
9684 
9685     if (pIsWow64Process)
9686         pIsWow64Process(GetCurrentProcess(), &is_wow64);
9687 
9688     GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
9689 
9690     /* Create a restore point ourselves so we circumvent the multitude of restore points
9691      * that would have been created by all the installation and removal tests.
9692      *
9693      * This is not needed on version 5.0 where setting MSIFASTINSTALL prevents the
9694      * creation of restore points.
9695      */
9696     if (pSRSetRestorePointA && !pMsiGetComponentPathExA)
9697     {
9698         memset(&status, 0, sizeof(status));
9699         ret = notify_system_change(BEGIN_NESTED_SYSTEM_CHANGE, &status);
9700     }
9701 
9702     test_createpackage();
9703     test_doaction();
9704     test_gettargetpath_bad();
9705     test_settargetpath();
9706     test_props();
9707     test_property_table();
9708     test_condition();
9709     test_msipackage();
9710     test_formatrecord2();
9711     test_formatrecord_tables();
9712     test_states();
9713     test_getproperty();
9714     test_removefiles();
9715     test_appsearch();
9716     test_appsearch_complocator();
9717     test_appsearch_reglocator();
9718     test_appsearch_inilocator();
9719     test_appsearch_drlocator();
9720     test_featureparents();
9721     test_installprops();
9722     test_launchconditions();
9723     test_ccpsearch();
9724     test_complocator();
9725     test_MsiGetSourcePath();
9726     test_shortlongsource();
9727     test_sourcedir();
9728     test_access();
9729     test_emptypackage();
9730     test_MsiGetProductProperty();
9731     test_MsiSetProperty();
9732     test_MsiApplyMultiplePatches();
9733     test_MsiApplyPatch();
9734     test_MsiEnumComponentCosts();
9735     test_MsiDatabaseCommit();
9736     test_externalui();
9737     test_externalui_message();
9738     test_controlevent();
9739     test_top_level_action();
9740 
9741     if (pSRSetRestorePointA && !pMsiGetComponentPathExA && ret)
9742     {
9743         ret = notify_system_change(END_NESTED_SYSTEM_CHANGE, &status);
9744         if (ret)
9745             remove_restore_point(status.llSequenceNumber);
9746     }
9747 }
9748