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     return 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 }
450 
451 static UINT create_feature_table( MSIHANDLE hdb )
452 {
453     return run_query( hdb,
454             "CREATE TABLE `Feature` ( "
455             "`Feature` CHAR(38) NOT NULL, "
456             "`Feature_Parent` CHAR(38), "
457             "`Title` CHAR(64), "
458             "`Description` CHAR(255), "
459             "`Display` SHORT NOT NULL, "
460             "`Level` SHORT NOT NULL, "
461             "`Directory_` CHAR(72), "
462             "`Attributes` SHORT NOT NULL "
463             "PRIMARY KEY `Feature`)" );
464 }
465 
466 static UINT create_feature_components_table( MSIHANDLE hdb )
467 {
468     return run_query( hdb,
469             "CREATE TABLE `FeatureComponents` ( "
470             "`Feature_` CHAR(38) NOT NULL, "
471             "`Component_` CHAR(72) NOT NULL "
472             "PRIMARY KEY `Feature_`, `Component_` )" );
473 }
474 
475 static UINT create_file_table( MSIHANDLE hdb )
476 {
477     return run_query( hdb,
478             "CREATE TABLE `File` ("
479             "`File` CHAR(72) NOT NULL, "
480             "`Component_` CHAR(72) NOT NULL, "
481             "`FileName` CHAR(255) NOT NULL, "
482             "`FileSize` LONG NOT NULL, "
483             "`Version` CHAR(72), "
484             "`Language` CHAR(20), "
485             "`Attributes` SHORT, "
486             "`Sequence` SHORT NOT NULL "
487             "PRIMARY KEY `File`)" );
488 }
489 
490 static UINT create_remove_file_table( MSIHANDLE hdb )
491 {
492     return run_query( hdb,
493             "CREATE TABLE `RemoveFile` ("
494             "`FileKey` CHAR(72) NOT NULL, "
495             "`Component_` CHAR(72) NOT NULL, "
496             "`FileName` CHAR(255) LOCALIZABLE, "
497             "`DirProperty` CHAR(72) NOT NULL, "
498             "`InstallMode` SHORT NOT NULL "
499             "PRIMARY KEY `FileKey`)" );
500 }
501 
502 static UINT create_appsearch_table( MSIHANDLE hdb )
503 {
504     return run_query( hdb,
505             "CREATE TABLE `AppSearch` ("
506             "`Property` CHAR(72) NOT NULL, "
507             "`Signature_` CHAR(72) NOT NULL "
508             "PRIMARY KEY `Property`, `Signature_`)" );
509 }
510 
511 static UINT create_reglocator_table( MSIHANDLE hdb )
512 {
513     return run_query( hdb,
514             "CREATE TABLE `RegLocator` ("
515             "`Signature_` CHAR(72) NOT NULL, "
516             "`Root` SHORT NOT NULL, "
517             "`Key` CHAR(255) NOT NULL, "
518             "`Name` CHAR(255), "
519             "`Type` SHORT "
520             "PRIMARY KEY `Signature_`)" );
521 }
522 
523 static UINT create_signature_table( MSIHANDLE hdb )
524 {
525     return run_query( hdb,
526             "CREATE TABLE `Signature` ("
527             "`Signature` CHAR(72) NOT NULL, "
528             "`FileName` CHAR(255) NOT NULL, "
529             "`MinVersion` CHAR(20), "
530             "`MaxVersion` CHAR(20), "
531             "`MinSize` LONG, "
532             "`MaxSize` LONG, "
533             "`MinDate` LONG, "
534             "`MaxDate` LONG, "
535             "`Languages` CHAR(255) "
536             "PRIMARY KEY `Signature`)" );
537 }
538 
539 static UINT create_launchcondition_table( MSIHANDLE hdb )
540 {
541     return run_query( hdb,
542             "CREATE TABLE `LaunchCondition` ("
543             "`Condition` CHAR(255) NOT NULL, "
544             "`Description` CHAR(255) NOT NULL "
545             "PRIMARY KEY `Condition`)" );
546 }
547 
548 static UINT create_property_table( MSIHANDLE hdb )
549 {
550     return run_query( hdb,
551             "CREATE TABLE `Property` ("
552             "`Property` CHAR(72) NOT NULL, "
553             "`Value` CHAR(0) "
554             "PRIMARY KEY `Property`)" );
555 }
556 
557 static UINT create_install_execute_sequence_table( MSIHANDLE hdb )
558 {
559     return run_query( hdb,
560             "CREATE TABLE `InstallExecuteSequence` ("
561             "`Action` CHAR(72) NOT NULL, "
562             "`Condition` CHAR(255), "
563             "`Sequence` SHORT "
564             "PRIMARY KEY `Action`)" );
565 }
566 
567 static UINT create_media_table( MSIHANDLE hdb )
568 {
569     return run_query( hdb,
570             "CREATE TABLE `Media` ("
571             "`DiskId` SHORT NOT NULL, "
572             "`LastSequence` SHORT NOT NULL, "
573             "`DiskPrompt` CHAR(64), "
574             "`Cabinet` CHAR(255), "
575             "`VolumeLabel` CHAR(32), "
576             "`Source` CHAR(72) "
577             "PRIMARY KEY `DiskId`)" );
578 }
579 
580 static UINT create_ccpsearch_table( MSIHANDLE hdb )
581 {
582     return run_query( hdb,
583             "CREATE TABLE `CCPSearch` ("
584             "`Signature_` CHAR(72) NOT NULL "
585             "PRIMARY KEY `Signature_`)" );
586 }
587 
588 static UINT create_drlocator_table( MSIHANDLE hdb )
589 {
590     return run_query( hdb,
591             "CREATE TABLE `DrLocator` ("
592             "`Signature_` CHAR(72) NOT NULL, "
593             "`Parent` CHAR(72), "
594             "`Path` CHAR(255), "
595             "`Depth` SHORT "
596             "PRIMARY KEY `Signature_`, `Parent`, `Path`)" );
597 }
598 
599 static UINT create_complocator_table( MSIHANDLE hdb )
600 {
601     return run_query( hdb,
602             "CREATE TABLE `CompLocator` ("
603             "`Signature_` CHAR(72) NOT NULL, "
604             "`ComponentId` CHAR(38) NOT NULL, "
605             "`Type` SHORT "
606             "PRIMARY KEY `Signature_`)" );
607 }
608 
609 static UINT create_inilocator_table( MSIHANDLE hdb )
610 {
611     return run_query( hdb,
612             "CREATE TABLE `IniLocator` ("
613             "`Signature_` CHAR(72) NOT NULL, "
614             "`FileName` CHAR(255) NOT NULL, "
615             "`Section` CHAR(96)NOT NULL, "
616             "`Key` CHAR(128)NOT NULL, "
617             "`Field` SHORT, "
618             "`Type` SHORT "
619             "PRIMARY KEY `Signature_`)" );
620 }
621 
622 static UINT create_custom_action_table( MSIHANDLE hdb )
623 {
624     return run_query( hdb,
625             "CREATE TABLE `CustomAction` ("
626             "`Action` CHAR(72) NOT NULL, "
627             "`Type` SHORT NOT NULL, "
628             "`Source` CHAR(75), "
629             "`Target` CHAR(255) "
630             "PRIMARY KEY `Action`)" );
631 }
632 
633 static UINT create_dialog_table( MSIHANDLE hdb )
634 {
635     return run_query(hdb,
636             "CREATE TABLE `Dialog` ("
637             "`Dialog` CHAR(72) NOT NULL, "
638             "`HCentering` SHORT NOT NULL, "
639             "`VCentering` SHORT NOT NULL, "
640             "`Width` SHORT NOT NULL, "
641             "`Height` SHORT NOT NULL, "
642             "`Attributes` LONG, "
643             "`Title` CHAR(128) LOCALIZABLE, "
644             "`Control_First` CHAR(50) NOT NULL, "
645             "`Control_Default` CHAR(50), "
646             "`Control_Cancel` CHAR(50) "
647             "PRIMARY KEY `Dialog`)");
648 }
649 
650 static UINT create_control_table( MSIHANDLE hdb )
651 {
652     return run_query(hdb,
653             "CREATE TABLE `Control` ("
654             "`Dialog_` CHAR(72) NOT NULL, "
655             "`Control` CHAR(50) NOT NULL, "
656             "`Type` CHAR(20) NOT NULL, "
657             "`X` SHORT NOT NULL, "
658             "`Y` SHORT NOT NULL, "
659             "`Width` SHORT NOT NULL, "
660             "`Height` SHORT NOT NULL, "
661             "`Attributes` LONG, "
662             "`Property` CHAR(50), "
663             "`Text` CHAR(0) LOCALIZABLE, "
664             "`Control_Next` CHAR(50), "
665             "`Help` CHAR(255) LOCALIZABLE "
666             "PRIMARY KEY `Dialog_`, `Control`)");
667 }
668 
669 static UINT create_controlevent_table( MSIHANDLE hdb )
670 {
671     return run_query(hdb,
672             "CREATE TABLE `ControlEvent` ("
673             "`Dialog_` CHAR(72) NOT NULL, "
674             "`Control_` CHAR(50) NOT NULL, "
675             "`Event` CHAR(50) NOT NULL, "
676             "`Argument` CHAR(255) NOT NULL, "
677             "`Condition` CHAR(255), "
678             "`Ordering` SHORT "
679             "PRIMARY KEY `Dialog_`, `Control_`, `Event`, `Argument`, `Condition`)");
680 }
681 
682 static UINT create_actiontext_table( MSIHANDLE hdb )
683 {
684     return run_query(hdb,
685             "CREATE TABLE `ActionText` ("
686             "`Action` CHAR(72) NOT NULL, "
687             "`Description` CHAR(64) LOCALIZABLE, "
688             "`Template` CHAR(128) LOCALIZABLE "
689             "PRIMARY KEY `Action`)");
690 }
691 
692 #define make_add_entry(type, qtext) \
693     static UINT add##_##type##_##entry( MSIHANDLE hdb, const char *values ) \
694     { \
695         char insert[] = qtext; \
696         char *query; \
697         UINT sz, r; \
698         sz = strlen(values) + sizeof insert; \
699         query = HeapAlloc(GetProcessHeap(),0,sz); \
700         sprintf(query,insert,values); \
701         r = run_query( hdb, query ); \
702         HeapFree(GetProcessHeap(), 0, query); \
703         return r; \
704     }
705 
706 make_add_entry(component,
707                "INSERT INTO `Component`  "
708                "(`Component`, `ComponentId`, `Directory_`, "
709                "`Attributes`, `Condition`, `KeyPath`) VALUES( %s )")
710 
711 make_add_entry(directory,
712                "INSERT INTO `Directory` "
713                "(`Directory`,`Directory_Parent`,`DefaultDir`) VALUES( %s )")
714 
715 make_add_entry(feature,
716                "INSERT INTO `Feature` "
717                "(`Feature`, `Feature_Parent`, `Title`, `Description`, "
718                "`Display`, `Level`, `Directory_`, `Attributes`) VALUES( %s )")
719 
720 make_add_entry(feature_components,
721                "INSERT INTO `FeatureComponents` "
722                "(`Feature_`, `Component_`) VALUES( %s )")
723 
724 make_add_entry(file,
725                "INSERT INTO `File` "
726                "(`File`, `Component_`, `FileName`, `FileSize`, "
727                "`Version`, `Language`, `Attributes`, `Sequence`) VALUES( %s )")
728 
729 make_add_entry(appsearch,
730                "INSERT INTO `AppSearch` "
731                "(`Property`, `Signature_`) VALUES( %s )")
732 
733 make_add_entry(signature,
734                "INSERT INTO `Signature` "
735                "(`Signature`, `FileName`, `MinVersion`, `MaxVersion`,"
736                " `MinSize`, `MaxSize`, `MinDate`, `MaxDate`, `Languages`) "
737                "VALUES( %s )")
738 
739 make_add_entry(launchcondition,
740                "INSERT INTO `LaunchCondition` "
741                "(`Condition`, `Description`) VALUES( %s )")
742 
743 make_add_entry(property,
744                "INSERT INTO `Property` (`Property`, `Value`) VALUES( %s )")
745 
746 make_add_entry(install_execute_sequence,
747                "INSERT INTO `InstallExecuteSequence` "
748                "(`Action`, `Condition`, `Sequence`) VALUES( %s )")
749 
750 make_add_entry(media,
751                "INSERT INTO `Media` "
752                "(`DiskId`, `LastSequence`, `DiskPrompt`, "
753                "`Cabinet`, `VolumeLabel`, `Source`) VALUES( %s )")
754 
755 make_add_entry(ccpsearch,
756                "INSERT INTO `CCPSearch` (`Signature_`) VALUES( %s )")
757 
758 make_add_entry(drlocator,
759                "INSERT INTO `DrLocator` "
760                "(`Signature_`, `Parent`, `Path`, `Depth`) VALUES( %s )")
761 
762 make_add_entry(complocator,
763                "INSERT INTO `CompLocator` "
764                "(`Signature_`, `ComponentId`, `Type`) VALUES( %s )")
765 
766 make_add_entry(inilocator,
767                "INSERT INTO `IniLocator` "
768                "(`Signature_`, `FileName`, `Section`, `Key`, `Field`, `Type`) "
769                "VALUES( %s )")
770 
771 make_add_entry(custom_action,
772                "INSERT INTO `CustomAction`  "
773                "(`Action`, `Type`, `Source`, `Target`) VALUES( %s )")
774 
775 make_add_entry(dialog,
776                "INSERT INTO `Dialog` "
777                "(`Dialog`, `HCentering`, `VCentering`, `Width`, `Height`, `Attributes`, `Control_First`) VALUES ( %s )")
778 
779 make_add_entry(control,
780                "INSERT INTO `Control` "
781                "(`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, `Attributes`, `Text`) VALUES( %s )");
782 
783 make_add_entry(controlevent,
784                "INSERT INTO `ControlEvent` "
785                "(`Dialog_`, `Control_`, `Event`, `Argument`, `Condition`, `Ordering`) VALUES( %s )");
786 
787 make_add_entry(actiontext,
788                "INSERT INTO `ActionText` "
789                "(`Action`, `Description`, `Template`) VALUES( %s )");
790 
791 static UINT add_reglocator_entry( MSIHANDLE hdb, const char *sig, UINT root, const char *path,
792                                   const char *name, UINT type )
793 {
794     const char insert[] =
795         "INSERT INTO `RegLocator` (`Signature_`, `Root`, `Key`, `Name`, `Type`) "
796         "VALUES( '%s', %u, '%s', '%s', %u )";
797     char *query;
798     UINT sz, r;
799 
800     sz = strlen( sig ) + 10 + strlen( path ) + strlen( name ) + 10 + sizeof( insert );
801     query = HeapAlloc( GetProcessHeap(), 0, sz );
802     sprintf( query, insert, sig, root, path, name, type );
803     r = run_query( hdb, query );
804     HeapFree( GetProcessHeap(), 0, query );
805     return r;
806 }
807 
808 static UINT set_summary_info(MSIHANDLE hdb)
809 {
810     UINT res;
811     MSIHANDLE suminfo;
812 
813     /* build summary info */
814     res = MsiGetSummaryInformationA(hdb, NULL, 7, &suminfo);
815     ok( res == ERROR_SUCCESS , "Failed to open summaryinfo\n" );
816 
817     res = MsiSummaryInfoSetPropertyA(suminfo,2, VT_LPSTR, 0,NULL,
818                         "Installation Database");
819     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
820 
821     res = MsiSummaryInfoSetPropertyA(suminfo,3, VT_LPSTR, 0,NULL,
822                         "Installation Database");
823     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
824 
825     res = MsiSummaryInfoSetPropertyA(suminfo,4, VT_LPSTR, 0,NULL,
826                         "Wine Hackers");
827     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
828 
829     res = MsiSummaryInfoSetPropertyA(suminfo,7, VT_LPSTR, 0,NULL,
830                     ";1033");
831     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
832 
833     res = MsiSummaryInfoSetPropertyA(suminfo,9, VT_LPSTR, 0,NULL,
834                     "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}");
835     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
836 
837     res = MsiSummaryInfoSetPropertyA(suminfo, 14, VT_I4, 100, NULL, NULL);
838     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
839 
840     res = MsiSummaryInfoSetPropertyA(suminfo, 15, VT_I4, 0, NULL, NULL);
841     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
842 
843     res = MsiSummaryInfoPersist(suminfo);
844     ok( res == ERROR_SUCCESS , "Failed to make summary info persist\n" );
845 
846     res = MsiCloseHandle( suminfo);
847     ok( res == ERROR_SUCCESS , "Failed to close suminfo\n" );
848 
849     return res;
850 }
851 
852 
853 static MSIHANDLE create_package_db(void)
854 {
855     MSIHANDLE hdb = 0;
856     UINT res;
857 
858     DeleteFileA(msifile);
859 
860     /* create an empty database */
861     res = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb );
862     ok( res == ERROR_SUCCESS , "Failed to create database %u\n", res );
863     if( res != ERROR_SUCCESS )
864         return hdb;
865 
866     res = MsiDatabaseCommit( hdb );
867     ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
868 
869     res = set_summary_info(hdb);
870     ok( res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", res);
871 
872     res = run_query( hdb,
873             "CREATE TABLE `Directory` ( "
874             "`Directory` CHAR(255) NOT NULL, "
875             "`Directory_Parent` CHAR(255), "
876             "`DefaultDir` CHAR(255) NOT NULL "
877             "PRIMARY KEY `Directory`)" );
878     ok( res == ERROR_SUCCESS , "Failed to create directory table\n" );
879 
880     return hdb;
881 }
882 
883 static UINT package_from_db(MSIHANDLE hdb, MSIHANDLE *handle)
884 {
885     UINT res;
886     CHAR szPackage[12];
887     MSIHANDLE hPackage;
888 
889     sprintf(szPackage, "#%u", hdb);
890     res = MsiOpenPackageA(szPackage, &hPackage);
891     if (res != ERROR_SUCCESS)
892     {
893         MsiCloseHandle(hdb);
894         return res;
895     }
896 
897     res = MsiCloseHandle(hdb);
898     if (res != ERROR_SUCCESS)
899     {
900         MsiCloseHandle(hPackage);
901         return res;
902     }
903 
904     *handle = hPackage;
905     return ERROR_SUCCESS;
906 }
907 
908 static void create_file_data(LPCSTR name, LPCSTR data)
909 {
910     HANDLE file;
911     DWORD written;
912 
913     file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
914     ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
915     if (file == INVALID_HANDLE_VALUE)
916         return;
917 
918     WriteFile(file, data, strlen(data), &written, NULL);
919     WriteFile(file, "\n", strlen("\n"), &written, NULL);
920 
921     CloseHandle(file);
922 }
923 
924 static void create_test_file(const CHAR *name)
925 {
926     create_file_data(name, name);
927 }
928 
929 typedef struct _tagVS_VERSIONINFO
930 {
931     WORD wLength;
932     WORD wValueLength;
933     WORD wType;
934     WCHAR szKey[1];
935     WORD wPadding1[1];
936     VS_FIXEDFILEINFO Value;
937     WORD wPadding2[1];
938     WORD wChildren[1];
939 } VS_VERSIONINFO;
940 
941 #define roundoffs(a, b, r) (((BYTE *)(b) - (BYTE *)(a) + ((r) - 1)) & ~((r) - 1))
942 #define roundpos(a, b, r) (((BYTE *)(a)) + roundoffs(a, b, r))
943 
944 static BOOL create_file_with_version(const CHAR *name, LONG ms, LONG ls)
945 {
946     VS_VERSIONINFO *pVerInfo;
947     VS_FIXEDFILEINFO *pFixedInfo;
948     LPBYTE buffer, ofs;
949     CHAR path[MAX_PATH];
950     DWORD handle, size;
951     HANDLE resource;
952     BOOL ret = FALSE;
953 
954     GetSystemDirectoryA(path, MAX_PATH);
955     /* Some dlls can't be updated on Vista/W2K8 */
956     lstrcatA(path, "\\version.dll");
957 
958     CopyFileA(path, name, FALSE);
959 
960     size = GetFileVersionInfoSizeA(path, &handle);
961     buffer = HeapAlloc(GetProcessHeap(), 0, size);
962 
963     GetFileVersionInfoA(path, 0, size, buffer);
964 
965     pVerInfo = (VS_VERSIONINFO *)buffer;
966     ofs = (BYTE *)&pVerInfo->szKey[lstrlenW(pVerInfo->szKey) + 1];
967     pFixedInfo = (VS_FIXEDFILEINFO *)roundpos(pVerInfo, ofs, 4);
968 
969     pFixedInfo->dwFileVersionMS = ms;
970     pFixedInfo->dwFileVersionLS = ls;
971     pFixedInfo->dwProductVersionMS = ms;
972     pFixedInfo->dwProductVersionLS = ls;
973 
974     resource = BeginUpdateResourceA(name, FALSE);
975     if (!resource)
976         goto done;
977 
978     if (!UpdateResourceA(resource, (LPCSTR)RT_VERSION, (LPCSTR)MAKEINTRESOURCE(VS_VERSION_INFO),
979                          MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), buffer, size))
980         goto done;
981 
982     if (!EndUpdateResourceA(resource, FALSE))
983         goto done;
984 
985     ret = TRUE;
986 
987 done:
988     HeapFree(GetProcessHeap(), 0, buffer);
989     return ret;
990 }
991 
992 static BOOL notify_system_change(DWORD event_type, STATEMGRSTATUS *status)
993 {
994     RESTOREPOINTINFOA spec;
995 
996     spec.dwEventType = event_type;
997     spec.dwRestorePtType = APPLICATION_INSTALL;
998     spec.llSequenceNumber = status->llSequenceNumber;
999     lstrcpyA(spec.szDescription, "msitest restore point");
1000 
1001     return pSRSetRestorePointA(&spec, status);
1002 }
1003 
1004 static void remove_restore_point(DWORD seq_number)
1005 {
1006     DWORD res;
1007 
1008     res = pSRRemoveRestorePoint(seq_number);
1009     if (res != ERROR_SUCCESS)
1010         trace("Failed to remove the restore point : %08x\n", res);
1011 }
1012 
1013 static BOOL is_root(const char *path)
1014 {
1015     return (isalpha(path[0]) && path[1] == ':' && path[2] == '\\' && !path[3]);
1016 }
1017 
1018 static void test_createpackage(void)
1019 {
1020     MSIHANDLE hPackage = 0;
1021     UINT res;
1022 
1023     res = package_from_db(create_package_db(), &hPackage);
1024     if (res == ERROR_INSTALL_PACKAGE_REJECTED)
1025     {
1026         skip("Not enough rights to perform tests\n");
1027         DeleteFileA(msifile);
1028         return;
1029     }
1030     ok( res == ERROR_SUCCESS, " Failed to create package %u\n", res );
1031 
1032     res = MsiCloseHandle( hPackage);
1033     ok( res == ERROR_SUCCESS , "Failed to close package\n" );
1034     DeleteFileA(msifile);
1035 }
1036 
1037 static void test_doaction( void )
1038 {
1039     MSIHANDLE hpkg;
1040     UINT r;
1041 
1042     r = MsiDoActionA( -1, NULL );
1043     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1044 
1045     r = package_from_db(create_package_db(), &hpkg);
1046     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1047     {
1048         skip("Not enough rights to perform tests\n");
1049         DeleteFileA(msifile);
1050         return;
1051     }
1052     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1053 
1054     r = MsiDoActionA(hpkg, NULL);
1055     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1056 
1057     r = MsiDoActionA(0, "boo");
1058     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1059 
1060     r = MsiDoActionA(hpkg, "boo");
1061     ok( r == ERROR_FUNCTION_NOT_CALLED, "wrong return val\n");
1062 
1063     MsiCloseHandle( hpkg );
1064     DeleteFileA(msifile);
1065 }
1066 
1067 static void test_gettargetpath_bad(void)
1068 {
1069     static const WCHAR boo[] = {'b','o','o',0};
1070     static const WCHAR empty[] = {0};
1071     char buffer[0x80];
1072     WCHAR bufferW[0x80];
1073     MSIHANDLE hpkg;
1074     DWORD sz;
1075     UINT r;
1076 
1077     r = package_from_db(create_package_db(), &hpkg);
1078     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1079     {
1080         skip("Not enough rights to perform tests\n");
1081         DeleteFileA(msifile);
1082         return;
1083     }
1084     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1085 
1086     r = MsiGetTargetPathA( 0, NULL, NULL, NULL );
1087     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1088 
1089     r = MsiGetTargetPathA( 0, NULL, NULL, &sz );
1090     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1091 
1092     r = MsiGetTargetPathA( 0, "boo", NULL, NULL );
1093     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1094 
1095     r = MsiGetTargetPathA( 0, "boo", NULL, NULL );
1096     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1097 
1098     r = MsiGetTargetPathA( hpkg, "boo", NULL, NULL );
1099     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1100 
1101     r = MsiGetTargetPathA( hpkg, "boo", buffer, NULL );
1102     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1103 
1104     sz = 0;
1105     r = MsiGetTargetPathA( hpkg, "", buffer, &sz );
1106     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1107 
1108     r = MsiGetTargetPathW( 0, NULL, NULL, NULL );
1109     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1110 
1111     r = MsiGetTargetPathW( 0, NULL, NULL, &sz );
1112     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1113 
1114     r = MsiGetTargetPathW( 0, boo, NULL, NULL );
1115     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1116 
1117     r = MsiGetTargetPathW( 0, boo, NULL, NULL );
1118     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1119 
1120     r = MsiGetTargetPathW( hpkg, boo, NULL, NULL );
1121     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1122 
1123     r = MsiGetTargetPathW( hpkg, boo, bufferW, NULL );
1124     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1125 
1126     sz = 0;
1127     r = MsiGetTargetPathW( hpkg, empty, bufferW, &sz );
1128     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1129 
1130     MsiCloseHandle( hpkg );
1131     DeleteFileA(msifile);
1132 }
1133 
1134 static void query_file_path(MSIHANDLE hpkg, LPCSTR file, LPSTR buff)
1135 {
1136     UINT r;
1137     DWORD size;
1138     MSIHANDLE rec;
1139 
1140     rec = MsiCreateRecord( 1 );
1141     ok(rec, "MsiCreate record failed\n");
1142 
1143     r = MsiRecordSetStringA( rec, 0, file );
1144     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
1145 
1146     size = MAX_PATH;
1147     r = MsiFormatRecordA( hpkg, rec, buff, &size );
1148     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
1149 
1150     MsiCloseHandle( rec );
1151 }
1152 
1153 static void test_settargetpath(void)
1154 {
1155     char tempdir[MAX_PATH+8], buffer[MAX_PATH], file[MAX_PATH];
1156     DWORD sz;
1157     MSIHANDLE hpkg;
1158     UINT r;
1159     MSIHANDLE hdb;
1160 
1161     hdb = create_package_db();
1162     ok ( hdb, "failed to create package database\n" );
1163 
1164     r = add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'" );
1165     ok( r == S_OK, "failed to add directory entry: %d\n" , r );
1166 
1167     r = create_component_table( hdb );
1168     ok( r == S_OK, "cannot create Component table: %d\n", r );
1169 
1170     r = add_component_entry( hdb, "'RootComp', '{83e2694d-0864-4124-9323-6d37630912a1}', 'TARGETDIR', 8, '', 'RootFile'" );
1171     ok( r == S_OK, "cannot add dummy component: %d\n", r );
1172 
1173     r = add_component_entry( hdb, "'TestComp', '{A3FB59C8-C293-4F7E-B8C5-F0E1D8EEE4E5}', 'TestDir', 0, '', 'TestFile'" );
1174     ok( r == S_OK, "cannot add test component: %d\n", r );
1175 
1176     r = create_feature_table( hdb );
1177     ok( r == S_OK, "cannot create Feature table: %d\n", r );
1178 
1179     r = add_feature_entry( hdb, "'TestFeature', '', '', '', 0, 1, '', 0" );
1180     ok( r == ERROR_SUCCESS, "cannot add TestFeature to Feature table: %d\n", r );
1181 
1182     r = create_feature_components_table( hdb );
1183     ok( r == S_OK, "cannot create FeatureComponents table: %d\n", r );
1184 
1185     r = add_feature_components_entry( hdb, "'TestFeature', 'RootComp'" );
1186     ok( r == S_OK, "cannot insert component into FeatureComponents table: %d\n", r );
1187 
1188     r = add_feature_components_entry( hdb, "'TestFeature', 'TestComp'" );
1189     ok( r == S_OK, "cannot insert component into FeatureComponents table: %d\n", r );
1190 
1191     add_directory_entry( hdb, "'TestParent', 'TARGETDIR', 'TestParent'" );
1192     add_directory_entry( hdb, "'TestDir', 'TestParent', 'TestDir'" );
1193 
1194     r = create_file_table( hdb );
1195     ok( r == S_OK, "cannot create File table: %d\n", r );
1196 
1197     r = add_file_entry( hdb, "'RootFile', 'RootComp', 'rootfile.txt', 0, '', '1033', 8192, 1" );
1198     ok( r == S_OK, "cannot add file to the File table: %d\n", r );
1199 
1200     r = add_file_entry( hdb, "'TestFile', 'TestComp', 'testfile.txt', 0, '', '1033', 8192, 1" );
1201     ok( r == S_OK, "cannot add file to the File table: %d\n", r );
1202 
1203     r = package_from_db( hdb, &hpkg );
1204     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1205     {
1206         skip("Not enough rights to perform tests\n");
1207         DeleteFileA(msifile);
1208         return;
1209     }
1210     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1211 
1212     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1213 
1214     r = MsiDoActionA( hpkg, "CostInitialize");
1215     ok( r == ERROR_SUCCESS, "cost init failed\n");
1216 
1217     r = MsiDoActionA( hpkg, "FileCost");
1218     ok( r == ERROR_SUCCESS, "file cost failed\n");
1219 
1220     r = MsiDoActionA( hpkg, "CostFinalize");
1221     ok( r == ERROR_SUCCESS, "cost finalize failed\n");
1222 
1223     buffer[0] = 0;
1224     sz = sizeof(buffer);
1225     r = MsiGetPropertyA( hpkg, "OutOfNoRbDiskSpace", buffer, &sz );
1226     ok( r == ERROR_SUCCESS, "MsiGetProperty returned %u\n", r );
1227     trace( "OutOfNoRbDiskSpace = \"%s\"\n", buffer );
1228 
1229     r = MsiSetTargetPathA( 0, NULL, NULL );
1230     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1231 
1232     r = MsiSetTargetPathA( 0, "boo", "C:\\bogusx" );
1233     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1234 
1235     r = MsiSetTargetPathA( hpkg, "boo", NULL );
1236     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1237 
1238     r = MsiSetTargetPathA( hpkg, "boo", "c:\\bogusx" );
1239     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1240 
1241     sz = sizeof tempdir - 1;
1242     r = MsiGetTargetPathA( hpkg, "TARGETDIR", tempdir, &sz );
1243     sprintf( file, "%srootfile.txt", tempdir );
1244     buffer[0] = 0;
1245     query_file_path( hpkg, "[#RootFile]", buffer );
1246     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1247     ok( !lstrcmpA(buffer, file), "Expected %s, got %s\n", file, buffer );
1248 
1249     GetTempFileNameA( tempdir, "_wt", 0, buffer );
1250     sprintf( tempdir, "%s\\subdir", buffer );
1251 
1252     r = MsiSetTargetPathA( hpkg, "TARGETDIR", buffer );
1253     ok( r == ERROR_SUCCESS || r == ERROR_DIRECTORY,
1254         "MsiSetTargetPath on file returned %d\n", r );
1255 
1256     r = MsiSetTargetPathA( hpkg, "TARGETDIR", tempdir );
1257     ok( r == ERROR_SUCCESS || r == ERROR_DIRECTORY,
1258         "MsiSetTargetPath on 'subdir' of file returned %d\n", r );
1259 
1260     DeleteFileA( buffer );
1261 
1262     r = MsiSetTargetPathA( hpkg, "TARGETDIR", buffer );
1263     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1264 
1265     r = GetFileAttributesA( buffer );
1266     ok ( r == INVALID_FILE_ATTRIBUTES, "file/directory exists after MsiSetTargetPath. Attributes: %08X\n", r );
1267 
1268     r = MsiSetTargetPathA( hpkg, "TARGETDIR", tempdir );
1269     ok( r == ERROR_SUCCESS, "MsiSetTargetPath on subsubdir returned %d\n", r );
1270 
1271     buffer[0] = 0;
1272     sz = sizeof buffer - 1;
1273     lstrcatA( tempdir, "\\" );
1274     r = MsiGetTargetPathA( hpkg, "TARGETDIR", buffer, &sz );
1275     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1276     ok( !lstrcmpA(buffer, tempdir), "Expected %s, got %s\n", tempdir, buffer);
1277 
1278     sprintf( file, "%srootfile.txt", tempdir );
1279     query_file_path( hpkg, "[#RootFile]", buffer );
1280     ok( !lstrcmpA(buffer, file), "Expected %s, got %s\n", file, buffer);
1281 
1282     buffer[0] = 0;
1283     sz = sizeof(buffer);
1284     r = MsiGetPropertyA( hpkg, "TestParent", buffer, &sz );
1285     ok( r == ERROR_SUCCESS, "MsiGetProperty returned %u\n", r );
1286     lstrcatA( tempdir, "TestParent\\" );
1287     ok( !lstrcmpiA(buffer, tempdir), "Expected \"%s\", got \"%s\"\n", tempdir, buffer );
1288 
1289     r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\one\\two" );
1290     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1291 
1292     buffer[0] = 0;
1293     sz = sizeof(buffer);
1294     r = MsiGetPropertyA( hpkg, "TestParent", buffer, &sz );
1295     ok( r == ERROR_SUCCESS, "MsiGetProperty returned %u\n", r );
1296     ok( lstrcmpiA(buffer, "C:\\one\\two\\TestDir\\"),
1297         "Expected \"C:\\one\\two\\TestDir\\\", got \"%s\"\n", buffer );
1298 
1299     buffer[0] = 0;
1300     query_file_path( hpkg, "[#TestFile]", buffer );
1301     ok( !lstrcmpiA(buffer, "C:\\one\\two\\TestDir\\testfile.txt"),
1302         "Expected C:\\one\\two\\TestDir\\testfile.txt, got %s\n", buffer );
1303 
1304     buffer[0] = 0;
1305     sz = sizeof buffer - 1;
1306     r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1307     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1308     ok( !lstrcmpiA(buffer, "C:\\one\\two\\"), "Expected C:\\one\\two\\, got %s\n", buffer);
1309 
1310     r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\one\\two\\three" );
1311     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1312 
1313     buffer[0] = 0;
1314     sz = sizeof buffer - 1;
1315     r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1316     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1317     ok( !lstrcmpiA(buffer, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", buffer);
1318 
1319     r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\\\one\\\\two  " );
1320     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1321 
1322     buffer[0] = 0;
1323     sz = sizeof buffer - 1;
1324     r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1325     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1326     ok( !lstrcmpiA(buffer, "C:\\one\\two\\"), "Expected \"C:\\one\\two\\\", got %s\n", buffer);
1327 
1328     r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\\\ Program Files \\\\ " );
1329     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1330 
1331     buffer[0] = 0;
1332     sz = sizeof buffer - 1;
1333     r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1334     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1335     ok( !lstrcmpiA(buffer, "C:\\Program Files\\"), "Expected \"C:\\Program Files\\\", got %s\n", buffer);
1336 
1337     MsiCloseHandle( hpkg );
1338 }
1339 
1340 static void test_condition(void)
1341 {
1342     static const WCHAR cond1[] = {'\"','a',0x30a,'\"','<','\"',0xe5,'\"',0};
1343     static const WCHAR cond2[] = {'\"','a',0x30a,'\"','>','\"',0xe5,'\"',0};
1344     static const WCHAR cond3[] = {'\"','a',0x30a,'\"','<','>','\"',0xe5,'\"',0};
1345     static const WCHAR cond4[] = {'\"','a',0x30a,'\"','=','\"',0xe5,'\"',0};
1346     MSICONDITION r;
1347     MSIHANDLE hpkg;
1348 
1349     r = package_from_db(create_package_db(), &hpkg);
1350     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1351     {
1352         skip("Not enough rights to perform tests\n");
1353         DeleteFileA(msifile);
1354         return;
1355     }
1356     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1357 
1358     r = MsiEvaluateConditionA(0, NULL);
1359     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1360 
1361     r = MsiEvaluateConditionA(hpkg, NULL);
1362     ok( r == MSICONDITION_NONE, "wrong return val\n");
1363 
1364     r = MsiEvaluateConditionA(hpkg, "");
1365     ok( r == MSICONDITION_NONE, "wrong return val\n");
1366 
1367     r = MsiEvaluateConditionA(hpkg, "1");
1368     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1369 
1370     r = MsiEvaluateConditionA(hpkg, "0");
1371     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1372 
1373     r = MsiEvaluateConditionA(hpkg, "-1");
1374     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1375 
1376     r = MsiEvaluateConditionA(hpkg, "0 = 0");
1377     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1378 
1379     r = MsiEvaluateConditionA(hpkg, "0 <> 0");
1380     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1381 
1382     r = MsiEvaluateConditionA(hpkg, "0 = 1");
1383     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1384 
1385     r = MsiEvaluateConditionA(hpkg, "0 > 1");
1386     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1387 
1388     r = MsiEvaluateConditionA(hpkg, "0 ~> 1");
1389     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1390 
1391     r = MsiEvaluateConditionA(hpkg, "1 > 1");
1392     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1393 
1394     r = MsiEvaluateConditionA(hpkg, "1 ~> 1");
1395     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1396 
1397     r = MsiEvaluateConditionA(hpkg, "0 >= 1");
1398     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1399 
1400     r = MsiEvaluateConditionA(hpkg, "0 ~>= 1");
1401     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1402 
1403     r = MsiEvaluateConditionA(hpkg, "1 >= 1");
1404     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1405 
1406     r = MsiEvaluateConditionA(hpkg, "1 ~>= 1");
1407     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1408 
1409     r = MsiEvaluateConditionA(hpkg, "0 < 1");
1410     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1411 
1412     r = MsiEvaluateConditionA(hpkg, "0 ~< 1");
1413     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1414 
1415     r = MsiEvaluateConditionA(hpkg, "1 < 1");
1416     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1417 
1418     r = MsiEvaluateConditionA(hpkg, "1 ~< 1");
1419     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1420 
1421     r = MsiEvaluateConditionA(hpkg, "0 <= 1");
1422     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1423 
1424     r = MsiEvaluateConditionA(hpkg, "0 ~<= 1");
1425     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1426 
1427     r = MsiEvaluateConditionA(hpkg, "1 <= 1");
1428     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1429 
1430     r = MsiEvaluateConditionA(hpkg, "1 ~<= 1");
1431     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1432 
1433     r = MsiEvaluateConditionA(hpkg, "0 >=");
1434     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1435 
1436     r = MsiEvaluateConditionA(hpkg, " ");
1437     ok( r == MSICONDITION_NONE, "wrong return val\n");
1438 
1439     r = MsiEvaluateConditionA(hpkg, "LicView <> \"1\"");
1440     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1441 
1442     r = MsiEvaluateConditionA(hpkg, "LicView <> \"0\"");
1443     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1444 
1445     r = MsiEvaluateConditionA(hpkg, "LicView <> LicView");
1446     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1447 
1448     r = MsiEvaluateConditionA(hpkg, "not 0");
1449     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1450 
1451     r = MsiEvaluateConditionA(hpkg, "not LicView");
1452     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1453 
1454     r = MsiEvaluateConditionA(hpkg, "\"Testing\" ~<< \"Testing\"");
1455     ok (r == MSICONDITION_TRUE, "wrong return val\n");
1456 
1457     r = MsiEvaluateConditionA(hpkg, "LicView ~<< \"Testing\"");
1458     ok (r == MSICONDITION_FALSE, "wrong return val\n");
1459 
1460     r = MsiEvaluateConditionA(hpkg, "Not LicView ~<< \"Testing\"");
1461     ok (r == MSICONDITION_TRUE, "wrong return val\n");
1462 
1463     r = MsiEvaluateConditionA(hpkg, "not \"A\"");
1464     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1465 
1466     r = MsiEvaluateConditionA(hpkg, "~not \"A\"");
1467     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1468 
1469     r = MsiEvaluateConditionA(hpkg, "\"0\"");
1470     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1471 
1472     r = MsiEvaluateConditionA(hpkg, "1 and 2");
1473     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1474 
1475     r = MsiEvaluateConditionA(hpkg, "not 0 and 3");
1476     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1477 
1478     r = MsiEvaluateConditionA(hpkg, "not 0 and 0");
1479     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1480 
1481     r = MsiEvaluateConditionA(hpkg, "not 0 or 1");
1482     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1483 
1484     r = MsiEvaluateConditionA(hpkg, "(0)");
1485     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1486 
1487     r = MsiEvaluateConditionA(hpkg, "(((((1))))))");
1488     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1489 
1490     r = MsiEvaluateConditionA(hpkg, "(((((1)))))");
1491     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1492 
1493     r = MsiEvaluateConditionA(hpkg, " \"A\" < \"B\" ");
1494     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1495 
1496     r = MsiEvaluateConditionA(hpkg, " \"A\" > \"B\" ");
1497     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1498 
1499     r = MsiEvaluateConditionA(hpkg, " \"1\" > \"12\" ");
1500     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1501 
1502     r = MsiEvaluateConditionA(hpkg, " \"100\" < \"21\" ");
1503     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1504 
1505     r = MsiEvaluateConditionA(hpkg, "0 < > 0");
1506     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1507 
1508     r = MsiEvaluateConditionA(hpkg, "(1<<1) == 2");
1509     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1510 
1511     r = MsiEvaluateConditionA(hpkg, " \"A\" = \"a\" ");
1512     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1513 
1514     r = MsiEvaluateConditionA(hpkg, " \"A\" ~ = \"a\" ");
1515     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1516 
1517     r = MsiEvaluateConditionA(hpkg, " \"A\" ~= \"a\" ");
1518     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1519 
1520     r = MsiEvaluateConditionA(hpkg, " \"A\" ~= 1 ");
1521     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1522 
1523     r = MsiEvaluateConditionA(hpkg, " \"A\" = 1 ");
1524     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1525 
1526     r = MsiEvaluateConditionA(hpkg, " 1 ~= 1 ");
1527     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1528 
1529     r = MsiEvaluateConditionA(hpkg, " 1 ~= \"1\" ");
1530     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1531 
1532     r = MsiEvaluateConditionA(hpkg, " 1 = \"1\" ");
1533     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1534 
1535     r = MsiEvaluateConditionA(hpkg, " 0 = \"1\" ");
1536     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1537 
1538     r = MsiEvaluateConditionA(hpkg, " 0 < \"100\" ");
1539     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1540 
1541     r = MsiEvaluateConditionA(hpkg, " 100 > \"0\" ");
1542     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1543 
1544     r = MsiEvaluateConditionA(hpkg, "1 XOR 1");
1545     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1546 
1547     r = MsiEvaluateConditionA(hpkg, "1 IMP 1");
1548     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1549 
1550     r = MsiEvaluateConditionA(hpkg, "1 IMP 0");
1551     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1552 
1553     r = MsiEvaluateConditionA(hpkg, "0 IMP 0");
1554     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1555 
1556     r = MsiEvaluateConditionA(hpkg, "0 EQV 0");
1557     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1558 
1559     r = MsiEvaluateConditionA(hpkg, "0 EQV 1");
1560     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1561 
1562     r = MsiEvaluateConditionA(hpkg, "1 IMP 1 OR 0");
1563     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1564 
1565     r = MsiEvaluateConditionA(hpkg, "1 IMPL 1");
1566     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1567 
1568     r = MsiEvaluateConditionA(hpkg, "\"ASFD\" >< \"S\" ");
1569     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1570 
1571     r = MsiEvaluateConditionA(hpkg, "\"ASFD\" ~>< \"s\" ");
1572     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1573 
1574     r = MsiEvaluateConditionA(hpkg, "\"ASFD\" ~>< \"\" ");
1575     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1576 
1577     r = MsiEvaluateConditionA(hpkg, "\"ASFD\" ~>< \"sss\" ");
1578     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1579 
1580     MsiSetPropertyA(hpkg, "mm", "5" );
1581 
1582     r = MsiEvaluateConditionA(hpkg, "mm = 5");
1583     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1584 
1585     r = MsiEvaluateConditionA(hpkg, "mm < 6");
1586     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1587 
1588     r = MsiEvaluateConditionA(hpkg, "mm <= 5");
1589     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1590 
1591     r = MsiEvaluateConditionA(hpkg, "mm > 4");
1592     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1593 
1594     r = MsiEvaluateConditionA(hpkg, "mm < 12");
1595     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1596 
1597     r = MsiEvaluateConditionA(hpkg, "mm = \"5\"");
1598     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1599 
1600     r = MsiEvaluateConditionA(hpkg, "0 = \"\"");
1601     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1602 
1603     r = MsiEvaluateConditionA(hpkg, "0 AND \"\"");
1604     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1605 
1606     r = MsiEvaluateConditionA(hpkg, "1 AND \"\"");
1607     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1608 
1609     r = MsiEvaluateConditionA(hpkg, "1 AND \"1\"");
1610     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1611 
1612     r = MsiEvaluateConditionA(hpkg, "3 >< 1");
1613     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1614 
1615     r = MsiEvaluateConditionA(hpkg, "3 >< 4");
1616     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1617 
1618     r = MsiEvaluateConditionA(hpkg, "NOT 0 AND 0");
1619     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1620 
1621     r = MsiEvaluateConditionA(hpkg, "NOT 0 AND 1");
1622     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1623 
1624     r = MsiEvaluateConditionA(hpkg, "NOT 1 OR 0");
1625     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1626 
1627     r = MsiEvaluateConditionA(hpkg, "0 AND 1 OR 1");
1628     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1629 
1630     r = MsiEvaluateConditionA(hpkg, "0 AND 0 OR 1");
1631     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1632 
1633     r = MsiEvaluateConditionA(hpkg, "NOT 0 AND 1 OR 0");
1634     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1635 
1636     r = MsiEvaluateConditionA(hpkg, "_1 = _1");
1637     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1638 
1639     r = MsiEvaluateConditionA(hpkg, "( 1 AND 1 ) = 2");
1640     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1641 
1642     r = MsiEvaluateConditionA(hpkg, "NOT ( 1 AND 1 )");
1643     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1644 
1645     r = MsiEvaluateConditionA(hpkg, "NOT A AND (BBBBBBBBBB=2 OR CCC=1) AND Ddddddddd");
1646     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1647 
1648     r = MsiEvaluateConditionA(hpkg, "Installed<>\"\"");
1649     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1650 
1651     r = MsiEvaluateConditionA(hpkg, "NOT 1 AND 0");
1652     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1653 
1654     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1655     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1656 
1657     r = MsiEvaluateConditionA(hpkg, "bandalmael<>0");
1658     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1659 
1660     r = MsiEvaluateConditionA(hpkg, "bandalmael<0");
1661     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1662 
1663     r = MsiEvaluateConditionA(hpkg, "bandalmael>0");
1664     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1665 
1666     r = MsiEvaluateConditionA(hpkg, "bandalmael>=0");
1667     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1668 
1669     r = MsiEvaluateConditionA(hpkg, "bandalmael<=0");
1670     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1671 
1672     r = MsiEvaluateConditionA(hpkg, "bandalmael~<>0");
1673     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1674 
1675     MsiSetPropertyA(hpkg, "bandalmael", "0" );
1676     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1677     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1678 
1679     MsiSetPropertyA(hpkg, "bandalmael", "" );
1680     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1681     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1682 
1683     MsiSetPropertyA(hpkg, "bandalmael", "asdf" );
1684     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1685     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1686 
1687     MsiSetPropertyA(hpkg, "bandalmael", "0asdf" );
1688     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1689     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1690 
1691     MsiSetPropertyA(hpkg, "bandalmael", "0 " );
1692     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1693     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1694 
1695     MsiSetPropertyA(hpkg, "bandalmael", "-0" );
1696     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1697     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1698 
1699     MsiSetPropertyA(hpkg, "bandalmael", "0000000000000" );
1700     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1701     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1702 
1703     MsiSetPropertyA(hpkg, "bandalmael", "--0" );
1704     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1705     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1706 
1707     MsiSetPropertyA(hpkg, "bandalmael", "0x00" );
1708     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1709     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1710 
1711     MsiSetPropertyA(hpkg, "bandalmael", "-" );
1712     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1713     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1714 
1715     MsiSetPropertyA(hpkg, "bandalmael", "+0" );
1716     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1717     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1718 
1719     MsiSetPropertyA(hpkg, "bandalmael", "0.0" );
1720     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1721     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1722     r = MsiEvaluateConditionA(hpkg, "bandalmael<>0");
1723     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1724 
1725     MsiSetPropertyA(hpkg, "one", "hi");
1726     MsiSetPropertyA(hpkg, "two", "hithere");
1727     r = MsiEvaluateConditionA(hpkg, "one >< two");
1728     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1729 
1730     MsiSetPropertyA(hpkg, "one", "hithere");
1731     MsiSetPropertyA(hpkg, "two", "hi");
1732     r = MsiEvaluateConditionA(hpkg, "one >< two");
1733     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1734 
1735     MsiSetPropertyA(hpkg, "one", "hello");
1736     MsiSetPropertyA(hpkg, "two", "hi");
1737     r = MsiEvaluateConditionA(hpkg, "one >< two");
1738     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1739 
1740     MsiSetPropertyA(hpkg, "one", "hellohithere");
1741     MsiSetPropertyA(hpkg, "two", "hi");
1742     r = MsiEvaluateConditionA(hpkg, "one >< two");
1743     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1744 
1745     MsiSetPropertyA(hpkg, "one", "");
1746     MsiSetPropertyA(hpkg, "two", "hi");
1747     r = MsiEvaluateConditionA(hpkg, "one >< two");
1748     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1749 
1750     MsiSetPropertyA(hpkg, "one", "hi");
1751     MsiSetPropertyA(hpkg, "two", "");
1752     r = MsiEvaluateConditionA(hpkg, "one >< two");
1753     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1754 
1755     MsiSetPropertyA(hpkg, "one", "");
1756     MsiSetPropertyA(hpkg, "two", "");
1757     r = MsiEvaluateConditionA(hpkg, "one >< two");
1758     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1759 
1760     MsiSetPropertyA(hpkg, "one", "1234");
1761     MsiSetPropertyA(hpkg, "two", "1");
1762     r = MsiEvaluateConditionA(hpkg, "one >< two");
1763     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1764 
1765     MsiSetPropertyA(hpkg, "one", "one 1234");
1766     MsiSetPropertyA(hpkg, "two", "1");
1767     r = MsiEvaluateConditionA(hpkg, "one >< two");
1768     ok( r == MSICONDITION_TRUE, "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", "hi");
1776     MsiSetPropertyA(hpkg, "two", "hithere");
1777     r = MsiEvaluateConditionA(hpkg, "one << two");
1778     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1779 
1780     MsiSetPropertyA(hpkg, "one", "hi");
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", "abcdhithere");
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", "");
1791     MsiSetPropertyA(hpkg, "two", "hi");
1792     r = MsiEvaluateConditionA(hpkg, "one << two");
1793     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1794 
1795     MsiSetPropertyA(hpkg, "one", "hithere");
1796     MsiSetPropertyA(hpkg, "two", "");
1797     r = MsiEvaluateConditionA(hpkg, "one << two");
1798     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1799 
1800     MsiSetPropertyA(hpkg, "one", "");
1801     MsiSetPropertyA(hpkg, "two", "");
1802     r = MsiEvaluateConditionA(hpkg, "one << two");
1803     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1804 
1805     MsiSetPropertyA(hpkg, "one", "1234");
1806     MsiSetPropertyA(hpkg, "two", "1");
1807     r = MsiEvaluateConditionA(hpkg, "one << two");
1808     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1809 
1810     MsiSetPropertyA(hpkg, "one", "1234 one");
1811     MsiSetPropertyA(hpkg, "two", "1");
1812     r = MsiEvaluateConditionA(hpkg, "one << two");
1813     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1814 
1815     MsiSetPropertyA(hpkg, "one", "hithere");
1816     MsiSetPropertyA(hpkg, "two", "there");
1817     r = MsiEvaluateConditionA(hpkg, "one >> two");
1818     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1819 
1820     MsiSetPropertyA(hpkg, "one", "hithere");
1821     MsiSetPropertyA(hpkg, "two", "hi");
1822     r = MsiEvaluateConditionA(hpkg, "one >> two");
1823     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1824 
1825     MsiSetPropertyA(hpkg, "one", "there");
1826     MsiSetPropertyA(hpkg, "two", "hithere");
1827     r = MsiEvaluateConditionA(hpkg, "one >> two");
1828     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1829 
1830     MsiSetPropertyA(hpkg, "one", "there");
1831     MsiSetPropertyA(hpkg, "two", "there");
1832     r = MsiEvaluateConditionA(hpkg, "one >> two");
1833     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1834 
1835     MsiSetPropertyA(hpkg, "one", "abcdhithere");
1836     MsiSetPropertyA(hpkg, "two", "hi");
1837     r = MsiEvaluateConditionA(hpkg, "one >> two");
1838     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1839 
1840     MsiSetPropertyA(hpkg, "one", "");
1841     MsiSetPropertyA(hpkg, "two", "there");
1842     r = MsiEvaluateConditionA(hpkg, "one >> two");
1843     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1844 
1845     MsiSetPropertyA(hpkg, "one", "there");
1846     MsiSetPropertyA(hpkg, "two", "");
1847     r = MsiEvaluateConditionA(hpkg, "one >> two");
1848     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1849 
1850     MsiSetPropertyA(hpkg, "one", "");
1851     MsiSetPropertyA(hpkg, "two", "");
1852     r = MsiEvaluateConditionA(hpkg, "one >> two");
1853     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1854 
1855     MsiSetPropertyA(hpkg, "one", "1234");
1856     MsiSetPropertyA(hpkg, "two", "4");
1857     r = MsiEvaluateConditionA(hpkg, "one >> two");
1858     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1859 
1860     MsiSetPropertyA(hpkg, "one", "one 1234");
1861     MsiSetPropertyA(hpkg, "two", "4");
1862     r = MsiEvaluateConditionA(hpkg, "one >> two");
1863     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1864 
1865     MsiSetPropertyA(hpkg, "MsiNetAssemblySupport", NULL);  /* make sure it's empty */
1866 
1867     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322\"");
1868     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1869 
1870     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport > \"1.1.4322\"");
1871     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1872 
1873     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport >= \"1.1.4322\"");
1874     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1875 
1876     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport <= \"1.1.4322\"");
1877     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1878 
1879     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport <> \"1.1.4322\"");
1880     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1881 
1882     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport ~< \"1.1.4322\"");
1883     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1884 
1885     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"abcd\"");
1886     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1887 
1888     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a1.1.4322\"");
1889     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1890 
1891     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322a\"");
1892     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1893 
1894     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"0000001.1.4322\"");
1895     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1896 
1897     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322.1\"");
1898     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1899 
1900     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322.1.1\"");
1901     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1902 
1903     r = MsiEvaluateConditionA(hpkg, "\"2\" < \"1.1");
1904     ok( r == MSICONDITION_ERROR, "wrong return val (%d)\n", r);
1905 
1906     r = MsiEvaluateConditionA(hpkg, "\"2\" < \"1.1\"");
1907     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1908 
1909     r = MsiEvaluateConditionA(hpkg, "\"2\" < \"12.1\"");
1910     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1911 
1912     r = MsiEvaluateConditionA(hpkg, "\"02.1\" < \"2.11\"");
1913     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1914 
1915     r = MsiEvaluateConditionA(hpkg, "\"02.1.1\" < \"2.1\"");
1916     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1917 
1918     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1\"");
1919     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1920 
1921     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1\"");
1922     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1923 
1924     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"0\"");
1925     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1926 
1927     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"-1\"");
1928     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1929 
1930     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a\"");
1931     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1932 
1933     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"!\"");
1934     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1935 
1936     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"!\"");
1937     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1938 
1939     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"/\"");
1940     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1941 
1942     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \" \"");
1943     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1944 
1945     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"azAZ_\"");
1946     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1947 
1948     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a[a]\"");
1949     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1950 
1951     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a[a]a\"");
1952     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1953 
1954     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"[a]\"");
1955     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1956 
1957     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"[a]a\"");
1958     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1959 
1960     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"{a}\"");
1961     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1962 
1963     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"{a\"");
1964     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1965 
1966     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"[a\"");
1967     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1968 
1969     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a{\"");
1970     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1971 
1972     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a]\"");
1973     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1974 
1975     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"A\"");
1976     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1977 
1978     MsiSetPropertyA(hpkg, "MsiNetAssemblySupport", "1.1.4322");
1979     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322\"");
1980     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1981 
1982     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.14322\"");
1983     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1984 
1985     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.5\"");
1986     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1987 
1988     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1\"");
1989     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1990 
1991     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1\"");
1992     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1993 
1994     MsiSetPropertyA(hpkg, "one", "1");
1995     r = MsiEvaluateConditionA(hpkg, "one < \"1\"");
1996     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1997 
1998     MsiSetPropertyA(hpkg, "X", "5.0");
1999 
2000     r = MsiEvaluateConditionA(hpkg, "X != \"\"");
2001     ok( r == MSICONDITION_ERROR, "wrong return val (%d)\n", r);
2002 
2003     r = MsiEvaluateConditionA(hpkg, "X =\"5.0\"");
2004     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2005 
2006     r = MsiEvaluateConditionA(hpkg, "X =\"5.1\"");
2007     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2008 
2009     r = MsiEvaluateConditionA(hpkg, "X =\"6.0\"");
2010     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2011 
2012     r = MsiEvaluateConditionA(hpkg, "X =\"5.0\" or X =\"5.1\" or X =\"6.0\"");
2013     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2014 
2015     r = MsiEvaluateConditionA(hpkg, "(X =\"5.0\" or X =\"5.1\" or X =\"6.0\")");
2016     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2017 
2018     r = MsiEvaluateConditionA(hpkg, "X !=\"\" and (X =\"5.0\" or X =\"5.1\" or X =\"6.0\")");
2019     ok( r == MSICONDITION_ERROR, "wrong return val (%d)\n", r);
2020 
2021     /* feature doesn't exist */
2022     r = MsiEvaluateConditionA(hpkg, "&nofeature");
2023     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2024 
2025     MsiSetPropertyA(hpkg, "A", "2");
2026     MsiSetPropertyA(hpkg, "X", "50");
2027 
2028     r = MsiEvaluateConditionA(hpkg, "2 <= X");
2029     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2030 
2031     r = MsiEvaluateConditionA(hpkg, "A <= X");
2032     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2033 
2034     r = MsiEvaluateConditionA(hpkg, "A <= 50");
2035     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2036 
2037     MsiSetPropertyA(hpkg, "X", "50val");
2038 
2039     r = MsiEvaluateConditionA(hpkg, "2 <= X");
2040     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2041 
2042     r = MsiEvaluateConditionA(hpkg, "A <= X");
2043     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2044 
2045     MsiSetPropertyA(hpkg, "A", "7");
2046     MsiSetPropertyA(hpkg, "X", "50");
2047 
2048     r = MsiEvaluateConditionA(hpkg, "7 <= X");
2049     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2050 
2051     r = MsiEvaluateConditionA(hpkg, "A <= X");
2052     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2053 
2054     r = MsiEvaluateConditionA(hpkg, "A <= 50");
2055     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2056 
2057     MsiSetPropertyA(hpkg, "X", "50val");
2058 
2059     r = MsiEvaluateConditionA(hpkg, "2 <= X");
2060     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2061 
2062     r = MsiEvaluateConditionA(hpkg, "A <= X");
2063     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2064 
2065     r = MsiEvaluateConditionW(hpkg, cond1);
2066     ok( r == MSICONDITION_TRUE || broken(r == MSICONDITION_FALSE),
2067         "wrong return val (%d)\n", r);
2068 
2069     r = MsiEvaluateConditionW(hpkg, cond2);
2070     ok( r == MSICONDITION_FALSE || broken(r == MSICONDITION_TRUE),
2071         "wrong return val (%d)\n", r);
2072 
2073     r = MsiEvaluateConditionW(hpkg, cond3);
2074     ok( r == MSICONDITION_TRUE || broken(r == MSICONDITION_FALSE),
2075         "wrong return val (%d)\n", r);
2076 
2077     r = MsiEvaluateConditionW(hpkg, cond4);
2078     ok( r == MSICONDITION_FALSE || broken(r == MSICONDITION_TRUE),
2079         "wrong return val (%d)\n", r);
2080 
2081     MsiCloseHandle( hpkg );
2082     DeleteFileA(msifile);
2083 }
2084 
2085 static BOOL check_prop_empty( MSIHANDLE hpkg, const char * prop)
2086 {
2087     UINT r;
2088     DWORD sz;
2089     char buffer[2];
2090 
2091     sz = sizeof buffer;
2092     strcpy(buffer,"x");
2093     r = MsiGetPropertyA( hpkg, prop, buffer, &sz );
2094     return r == ERROR_SUCCESS && buffer[0] == 0 && sz == 0;
2095 }
2096 
2097 static void test_props(void)
2098 {
2099     MSIHANDLE hpkg, hdb;
2100     UINT r;
2101     DWORD sz;
2102     char buffer[0x100];
2103 
2104     hdb = create_package_db();
2105     r = run_query( hdb,
2106             "CREATE TABLE `Property` ( "
2107             "`Property` CHAR(255) NOT NULL, "
2108             "`Value` CHAR(255) "
2109             "PRIMARY KEY `Property`)" );
2110     ok( r == ERROR_SUCCESS , "Failed\n" );
2111 
2112     r = run_query(hdb,
2113             "INSERT INTO `Property` "
2114             "(`Property`, `Value`) "
2115             "VALUES( 'MetadataCompName', 'Photoshop.dll' )");
2116     ok( r == ERROR_SUCCESS , "Failed\n" );
2117 
2118     r = package_from_db( hdb, &hpkg );
2119     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2120     {
2121         skip("Not enough rights to perform tests\n");
2122         DeleteFileA(msifile);
2123         return;
2124     }
2125     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
2126 
2127     /* test invalid values */
2128     r = MsiGetPropertyA( 0, NULL, NULL, NULL );
2129     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
2130 
2131     r = MsiGetPropertyA( hpkg, NULL, NULL, NULL );
2132     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
2133 
2134     r = MsiGetPropertyA( hpkg, "boo", NULL, NULL );
2135     ok( r == ERROR_SUCCESS, "wrong return val\n");
2136 
2137     r = MsiGetPropertyA( hpkg, "boo", buffer, NULL );
2138     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
2139 
2140     /* test retrieving an empty/nonexistent property */
2141     sz = sizeof buffer;
2142     r = MsiGetPropertyA( hpkg, "boo", NULL, &sz );
2143     ok( r == ERROR_SUCCESS, "wrong return val\n");
2144     ok( sz == 0, "wrong size returned\n");
2145 
2146     check_prop_empty( hpkg, "boo");
2147     sz = 0;
2148     strcpy(buffer,"x");
2149     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2150     ok( r == ERROR_MORE_DATA, "wrong return val\n");
2151     ok( !strcmp(buffer,"x"), "buffer was changed\n");
2152     ok( sz == 0, "wrong size returned\n");
2153 
2154     sz = 1;
2155     strcpy(buffer,"x");
2156     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2157     ok( r == ERROR_SUCCESS, "wrong return val\n");
2158     ok( buffer[0] == 0, "buffer was not changed\n");
2159     ok( sz == 0, "wrong size returned\n");
2160 
2161     /* set the property to something */
2162     r = MsiSetPropertyA( 0, NULL, NULL );
2163     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
2164 
2165     r = MsiSetPropertyA( hpkg, NULL, NULL );
2166     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
2167 
2168     r = MsiSetPropertyA( hpkg, "", NULL );
2169     ok( r == ERROR_SUCCESS, "wrong return val\n");
2170 
2171     /* try set and get some illegal property identifiers */
2172     r = MsiSetPropertyA( hpkg, "", "asdf" );
2173     ok( r == ERROR_FUNCTION_FAILED, "wrong return val\n");
2174 
2175     r = MsiSetPropertyA( hpkg, "=", "asdf" );
2176     ok( r == ERROR_SUCCESS, "wrong return val\n");
2177 
2178     r = MsiSetPropertyA( hpkg, " ", "asdf" );
2179     ok( r == ERROR_SUCCESS, "wrong return val\n");
2180 
2181     r = MsiSetPropertyA( hpkg, "'", "asdf" );
2182     ok( r == ERROR_SUCCESS, "wrong return val\n");
2183 
2184     sz = sizeof buffer;
2185     buffer[0]=0;
2186     r = MsiGetPropertyA( hpkg, "'", buffer, &sz );
2187     ok( r == ERROR_SUCCESS, "wrong return val\n");
2188     ok( !strcmp(buffer,"asdf"), "buffer was not changed\n");
2189 
2190     /* set empty values */
2191     r = MsiSetPropertyA( hpkg, "boo", NULL );
2192     ok( r == ERROR_SUCCESS, "wrong return val\n");
2193     ok( check_prop_empty( hpkg, "boo"), "prop wasn't empty\n");
2194 
2195     r = MsiSetPropertyA( hpkg, "boo", "" );
2196     ok( r == ERROR_SUCCESS, "wrong return val\n");
2197     ok( check_prop_empty( hpkg, "boo"), "prop wasn't empty\n");
2198 
2199     /* set a non-empty value */
2200     r = MsiSetPropertyA( hpkg, "boo", "xyz" );
2201     ok( r == ERROR_SUCCESS, "wrong return val\n");
2202 
2203     sz = 1;
2204     strcpy(buffer,"x");
2205     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2206     ok( r == ERROR_MORE_DATA, "wrong return val\n");
2207     ok( buffer[0] == 0, "buffer was not changed\n");
2208     ok( sz == 3, "wrong size returned\n");
2209 
2210     sz = 4;
2211     strcpy(buffer,"x");
2212     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2213     ok( r == ERROR_SUCCESS, "wrong return val\n");
2214     ok( !strcmp(buffer,"xyz"), "buffer was not changed\n");
2215     ok( sz == 3, "wrong size returned\n");
2216 
2217     sz = 3;
2218     strcpy(buffer,"x");
2219     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2220     ok( r == ERROR_MORE_DATA, "wrong return val\n");
2221     ok( !strcmp(buffer,"xy"), "buffer was not changed\n");
2222     ok( sz == 3, "wrong size returned\n");
2223 
2224     r = MsiSetPropertyA(hpkg, "SourceDir", "foo");
2225     ok( r == ERROR_SUCCESS, "wrong return val\n");
2226 
2227     sz = 4;
2228     r = MsiGetPropertyA(hpkg, "SOURCEDIR", buffer, &sz);
2229     ok( r == ERROR_SUCCESS, "wrong return val\n");
2230     ok( !strcmp(buffer,""), "buffer wrong\n");
2231     ok( sz == 0, "wrong size returned\n");
2232 
2233     sz = 4;
2234     r = MsiGetPropertyA(hpkg, "SOMERANDOMNAME", buffer, &sz);
2235     ok( r == ERROR_SUCCESS, "wrong return val\n");
2236     ok( !strcmp(buffer,""), "buffer wrong\n");
2237     ok( sz == 0, "wrong size returned\n");
2238 
2239     sz = 4;
2240     r = MsiGetPropertyA(hpkg, "SourceDir", buffer, &sz);
2241     ok( r == ERROR_SUCCESS, "wrong return val\n");
2242     ok( !strcmp(buffer,"foo"), "buffer wrong\n");
2243     ok( sz == 3, "wrong size returned\n");
2244 
2245     r = MsiSetPropertyA(hpkg, "MetadataCompName", "Photoshop.dll");
2246     ok( r == ERROR_SUCCESS, "wrong return val\n");
2247 
2248     sz = 0;
2249     r = MsiGetPropertyA(hpkg, "MetadataCompName", NULL, &sz );
2250     ok( r == ERROR_SUCCESS, "return wrong\n");
2251     ok( sz == 13, "size wrong (%d)\n", sz);
2252 
2253     sz = 13;
2254     r = MsiGetPropertyA(hpkg, "MetadataCompName", buffer, &sz );
2255     ok( r == ERROR_MORE_DATA, "return wrong\n");
2256     ok( !strcmp(buffer,"Photoshop.dl"), "buffer wrong\n");
2257 
2258     r = MsiSetPropertyA(hpkg, "property", "value");
2259     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2260 
2261     sz = 6;
2262     r = MsiGetPropertyA(hpkg, "property", buffer, &sz);
2263     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2264     ok( !strcmp(buffer, "value"), "Expected value, got %s\n", buffer);
2265 
2266     r = MsiSetPropertyA(hpkg, "property", NULL);
2267     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2268 
2269     sz = 6;
2270     r = MsiGetPropertyA(hpkg, "property", buffer, &sz);
2271     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2272     ok(!buffer[0], "Expected empty string, got %s\n", buffer);
2273 
2274     MsiCloseHandle( hpkg );
2275     DeleteFileA(msifile);
2276 }
2277 
2278 static BOOL find_prop_in_property(MSIHANDLE hdb, LPCSTR prop, LPCSTR val, int len)
2279 {
2280     MSIHANDLE hview, hrec;
2281     BOOL found = FALSE;
2282     CHAR buffer[MAX_PATH];
2283     DWORD sz;
2284     UINT r;
2285 
2286     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Property`", &hview);
2287     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
2288     r = MsiViewExecute(hview, 0);
2289     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
2290 
2291     if (len < 0) len = lstrlenA(val);
2292 
2293     while (r == ERROR_SUCCESS && !found)
2294     {
2295         r = MsiViewFetch(hview, &hrec);
2296         if (r != ERROR_SUCCESS) break;
2297 
2298         sz = MAX_PATH;
2299         r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
2300         if (r == ERROR_SUCCESS && !lstrcmpA(buffer, prop))
2301         {
2302             sz = MAX_PATH;
2303             r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
2304             if (r == ERROR_SUCCESS && !memcmp(buffer, val, len) && !buffer[len])
2305             {
2306                 ok(sz == len, "wrong size %u\n", sz);
2307                 found = TRUE;
2308             }
2309         }
2310 
2311         MsiCloseHandle(hrec);
2312     }
2313     MsiViewClose(hview);
2314     MsiCloseHandle(hview);
2315     return found;
2316 }
2317 
2318 static void test_property_table(void)
2319 {
2320     const char *query;
2321     UINT r;
2322     MSIHANDLE hpkg, hdb, hrec;
2323     char buffer[MAX_PATH], package[10];
2324     DWORD sz;
2325     BOOL found;
2326 
2327     hdb = create_package_db();
2328     ok( hdb, "failed to create package\n");
2329 
2330     r = package_from_db(hdb, &hpkg);
2331     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2332     {
2333         skip("Not enough rights to perform tests\n");
2334         DeleteFileA(msifile);
2335         return;
2336     }
2337     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
2338 
2339     MsiCloseHandle(hdb);
2340 
2341     hdb = MsiGetActiveDatabase(hpkg);
2342 
2343     query = "CREATE TABLE `_Property` ( "
2344         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
2345     r = run_query(hdb, query);
2346     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2347 
2348     MsiCloseHandle(hdb);
2349     MsiCloseHandle(hpkg);
2350     DeleteFileA(msifile);
2351 
2352     hdb = create_package_db();
2353     ok( hdb, "failed to create package\n");
2354 
2355     query = "CREATE TABLE `_Property` ( "
2356         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
2357     r = run_query(hdb, query);
2358     ok(r == ERROR_SUCCESS, "failed to create table\n");
2359 
2360     query = "ALTER `_Property` ADD `foo` INTEGER";
2361     r = run_query(hdb, query);
2362     ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to add column\n");
2363 
2364     query = "ALTER TABLE `_Property` ADD `foo` INTEGER";
2365     r = run_query(hdb, query);
2366     ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to add column\n");
2367 
2368     query = "ALTER TABLE `_Property` ADD `extra` INTEGER";
2369     r = run_query(hdb, query);
2370     ok(r == ERROR_SUCCESS, "failed to add column\n");
2371 
2372     sprintf(package, "#%i", hdb);
2373     r = MsiOpenPackageA(package, &hpkg);
2374     ok(r != ERROR_SUCCESS, "MsiOpenPackage succeeded\n");
2375     if (r == ERROR_SUCCESS)
2376         MsiCloseHandle(hpkg);
2377 
2378     r = MsiCloseHandle(hdb);
2379     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed %u\n", r);
2380 
2381     hdb = create_package_db();
2382     ok (hdb, "failed to create package database\n");
2383 
2384     r = create_property_table(hdb);
2385     ok(r == ERROR_SUCCESS, "cannot create Property table: %d\n", r);
2386 
2387     r = add_property_entry(hdb, "'prop', 'val'");
2388     ok(r == ERROR_SUCCESS, "cannot add property: %d\n", r);
2389 
2390     r = create_custom_action_table(hdb);
2391     ok(r == ERROR_SUCCESS, "cannot create CustomAction table: %d\n", r);
2392 
2393     r = add_custom_action_entry( hdb, "'EmbedNull', 51, 'prop2', '[~]np'" );
2394     ok( r == ERROR_SUCCESS, "cannot add custom action: %d\n", r);
2395 
2396     r = package_from_db(hdb, &hpkg);
2397     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
2398 
2399     MsiCloseHandle(hdb);
2400 
2401     sz = MAX_PATH;
2402     r = MsiGetPropertyA(hpkg, "prop", buffer, &sz);
2403     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2404     ok(!lstrcmpA(buffer, "val"), "Expected val, got %s\n", buffer);
2405 
2406     hdb = MsiGetActiveDatabase(hpkg);
2407 
2408     found = find_prop_in_property(hdb, "prop", "val", -1);
2409     ok(found, "prop should be in the _Property table\n");
2410 
2411     r = add_property_entry(hdb, "'dantes', 'mercedes'");
2412     ok(r == ERROR_SUCCESS, "cannot add property: %d\n", r);
2413 
2414     query = "SELECT * FROM `_Property` WHERE `Property` = 'dantes'";
2415     r = do_query(hdb, query, &hrec);
2416     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2417 
2418     found = find_prop_in_property(hdb, "dantes", "mercedes", -1);
2419     ok(found == FALSE, "dantes should not be in the _Property table\n");
2420 
2421     sz = MAX_PATH;
2422     lstrcpyA(buffer, "aaa");
2423     r = MsiGetPropertyA(hpkg, "dantes", buffer, &sz);
2424     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2425     ok(!buffer[0], "Expected empty string, got %s\n", buffer);
2426 
2427     r = MsiSetPropertyA(hpkg, "dantes", "mercedes");
2428     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2429 
2430     found = find_prop_in_property(hdb, "dantes", "mercedes", -1);
2431     ok(found == TRUE, "dantes should be in the _Property table\n");
2432 
2433     r = MsiDoActionA( hpkg, "EmbedNull" );
2434     ok( r == ERROR_SUCCESS, "EmbedNull failed: %d\n", r);
2435 
2436     sz = MAX_PATH;
2437     memset( buffer, 'a', sizeof(buffer) );
2438     r = MsiGetPropertyA( hpkg, "prop2", buffer, &sz );
2439     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2440     ok( !memcmp( buffer, "\0np", sizeof("\0np") ), "wrong value\n");
2441     ok( sz == sizeof("\0np") - 1, "got %u\n", sz );
2442 
2443     found = find_prop_in_property(hdb, "prop2", "\0np", 3);
2444     ok(found == TRUE, "prop2 should be in the _Property table\n");
2445 
2446     MsiCloseHandle(hdb);
2447     MsiCloseHandle(hpkg);
2448     DeleteFileA(msifile);
2449 }
2450 
2451 static UINT try_query_param( MSIHANDLE hdb, LPCSTR szQuery, MSIHANDLE hrec )
2452 {
2453     MSIHANDLE htab = 0;
2454     UINT res;
2455 
2456     res = MsiDatabaseOpenViewA( hdb, szQuery, &htab );
2457     if( res == ERROR_SUCCESS )
2458     {
2459         UINT r;
2460 
2461         r = MsiViewExecute( htab, hrec );
2462         if( r != ERROR_SUCCESS )
2463         {
2464             res = r;
2465             fprintf(stderr,"MsiViewExecute failed %08x\n", res);
2466         }
2467 
2468         r = MsiViewClose( htab );
2469         if( r != ERROR_SUCCESS )
2470             res = r;
2471 
2472         r = MsiCloseHandle( htab );
2473         if( r != ERROR_SUCCESS )
2474             res = r;
2475     }
2476     return res;
2477 }
2478 
2479 static UINT try_query( MSIHANDLE hdb, LPCSTR szQuery )
2480 {
2481     return try_query_param( hdb, szQuery, 0 );
2482 }
2483 
2484 static void set_summary_str(MSIHANDLE hdb, DWORD pid, LPCSTR value)
2485 {
2486     MSIHANDLE summary;
2487     UINT r;
2488 
2489     r = MsiGetSummaryInformationA(hdb, NULL, 1, &summary);
2490     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2491 
2492     r = MsiSummaryInfoSetPropertyA(summary, pid, VT_LPSTR, 0, NULL, value);
2493     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2494 
2495     r = MsiSummaryInfoPersist(summary);
2496     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2497 
2498     MsiCloseHandle(summary);
2499 }
2500 
2501 static void set_summary_dword(MSIHANDLE hdb, DWORD pid, DWORD value)
2502 {
2503     MSIHANDLE summary;
2504     UINT r;
2505 
2506     r = MsiGetSummaryInformationA(hdb, NULL, 1, &summary);
2507     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2508 
2509     r = MsiSummaryInfoSetPropertyA(summary, pid, VT_I4, value, NULL, NULL);
2510     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2511 
2512     r = MsiSummaryInfoPersist(summary);
2513     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2514 
2515     MsiCloseHandle(summary);
2516 }
2517 
2518 static void test_msipackage(void)
2519 {
2520     MSIHANDLE hdb = 0, hpack = 100;
2521     UINT r;
2522     const char *query;
2523     char name[10];
2524 
2525     /* NULL szPackagePath */
2526     r = MsiOpenPackageA(NULL, &hpack);
2527     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2528 
2529     /* empty szPackagePath */
2530     r = MsiOpenPackageA("", &hpack);
2531     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2532     {
2533         skip("Not enough rights to perform tests\n");
2534         return;
2535     }
2536     todo_wine
2537     {
2538         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2539     }
2540 
2541     if (r == ERROR_SUCCESS)
2542         MsiCloseHandle(hpack);
2543 
2544     /* nonexistent szPackagePath */
2545     r = MsiOpenPackageA("nonexistent", &hpack);
2546     ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
2547 
2548     /* NULL hProduct */
2549     r = MsiOpenPackageA(msifile, NULL);
2550     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2551 
2552     name[0]='#';
2553     name[1]=0;
2554     r = MsiOpenPackageA(name, &hpack);
2555     ok(r == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", r);
2556 
2557     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
2558     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2559 
2560     /* database exists, but is empty */
2561     sprintf(name, "#%d", hdb);
2562     r = MsiOpenPackageA(name, &hpack);
2563     ok(r == ERROR_INSTALL_PACKAGE_INVALID,
2564        "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
2565 
2566     query = "CREATE TABLE `Property` ( "
2567             "`Property` CHAR(72), `Value` CHAR(0) "
2568             "PRIMARY KEY `Property`)";
2569     r = try_query(hdb, query);
2570     ok(r == ERROR_SUCCESS, "failed to create Properties table\n");
2571 
2572     query = "CREATE TABLE `InstallExecuteSequence` ("
2573             "`Action` CHAR(72), `Condition` CHAR(0), `Sequence` INTEGER "
2574             "PRIMARY KEY `Action`)";
2575     r = try_query(hdb, query);
2576     ok(r == ERROR_SUCCESS, "failed to create InstallExecuteSequence table\n");
2577 
2578     /* a few key tables exist */
2579     sprintf(name, "#%d", hdb);
2580     r = MsiOpenPackageA(name, &hpack);
2581     ok(r == ERROR_INSTALL_PACKAGE_INVALID,
2582        "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
2583 
2584     MsiCloseHandle(hdb);
2585     DeleteFileA(msifile);
2586 
2587     /* start with a clean database to show what constitutes a valid package */
2588     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
2589     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2590 
2591     sprintf(name, "#%d", hdb);
2592 
2593     /* The following summary information props must exist:
2594      *  - PID_REVNUMBER
2595      *  - PID_PAGECOUNT
2596      */
2597 
2598     set_summary_dword(hdb, PID_PAGECOUNT, 100);
2599     r = MsiOpenPackageA(name, &hpack);
2600     ok(r == ERROR_INSTALL_PACKAGE_INVALID,
2601        "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
2602 
2603     set_summary_str(hdb, PID_REVNUMBER, "{004757CD-5092-49C2-AD20-28E1CE0DF5F2}");
2604     r = MsiOpenPackageA(name, &hpack);
2605     ok(r == ERROR_SUCCESS,
2606        "Expected ERROR_SUCCESS, got %d\n", r);
2607 
2608     MsiCloseHandle(hpack);
2609     MsiCloseHandle(hdb);
2610     DeleteFileA(msifile);
2611 }
2612 
2613 static void test_formatrecord2(void)
2614 {
2615     MSIHANDLE hpkg, hrec ;
2616     char buffer[0x100];
2617     DWORD sz;
2618     UINT r;
2619 
2620     r = package_from_db(create_package_db(), &hpkg);
2621     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2622     {
2623         skip("Not enough rights to perform tests\n");
2624         DeleteFileA(msifile);
2625         return;
2626     }
2627     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
2628 
2629     r = MsiSetPropertyA(hpkg, "Manufacturer", " " );
2630     ok( r == ERROR_SUCCESS, "set property failed\n");
2631 
2632     hrec = MsiCreateRecord(2);
2633     ok(hrec, "create record failed\n");
2634 
2635     r = MsiRecordSetStringA( hrec, 0, "[ProgramFilesFolder][Manufacturer]\\asdf");
2636     ok( r == ERROR_SUCCESS, "format record failed\n");
2637 
2638     buffer[0] = 0;
2639     sz = sizeof buffer;
2640     r = MsiFormatRecordA( hpkg, hrec, buffer, &sz );
2641     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2642 
2643     r = MsiRecordSetStringA(hrec, 0, "[foo][1]");
2644     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2645     r = MsiRecordSetStringA(hrec, 1, "hoo");
2646     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2647     sz = sizeof buffer;
2648     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2649     ok( sz == 3, "size wrong\n");
2650     ok( 0 == strcmp(buffer,"hoo"), "wrong output %s\n",buffer);
2651     ok( r == ERROR_SUCCESS, "format failed\n");
2652 
2653     r = MsiRecordSetStringA(hrec, 0, "x[~]x");
2654     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2655     sz = sizeof buffer;
2656     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2657     ok( sz == 3, "size wrong\n");
2658     ok( 0 == strcmp(buffer,"x"), "wrong output %s\n",buffer);
2659     ok( r == ERROR_SUCCESS, "format failed\n");
2660 
2661     r = MsiRecordSetStringA(hrec, 0, "[foo.$%}][1]");
2662     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2663     r = MsiRecordSetStringA(hrec, 1, "hoo");
2664     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2665     sz = sizeof buffer;
2666     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2667     ok( sz == 3, "size wrong\n");
2668     ok( 0 == strcmp(buffer,"hoo"), "wrong output %s\n",buffer);
2669     ok( r == ERROR_SUCCESS, "format failed\n");
2670 
2671     r = MsiRecordSetStringA(hrec, 0, "[\\[]");
2672     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2673     sz = sizeof buffer;
2674     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2675     ok( sz == 1, "size wrong\n");
2676     ok( 0 == strcmp(buffer,"["), "wrong output %s\n",buffer);
2677     ok( r == ERROR_SUCCESS, "format failed\n");
2678 
2679     SetEnvironmentVariableA("FOO", "BAR");
2680     r = MsiRecordSetStringA(hrec, 0, "[%FOO]");
2681     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2682     sz = sizeof buffer;
2683     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2684     ok( sz == 3, "size wrong\n");
2685     ok( 0 == strcmp(buffer,"BAR"), "wrong output %s\n",buffer);
2686     ok( r == ERROR_SUCCESS, "format failed\n");
2687 
2688     r = MsiRecordSetStringA(hrec, 0, "[[1]]");
2689     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2690     r = MsiRecordSetStringA(hrec, 1, "%FOO");
2691     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2692     sz = sizeof buffer;
2693     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2694     ok( sz == 3, "size wrong\n");
2695     ok( 0 == strcmp(buffer,"BAR"), "wrong output %s\n",buffer);
2696     ok( r == ERROR_SUCCESS, "format failed\n");
2697 
2698     MsiCloseHandle( hrec );
2699     MsiCloseHandle( hpkg );
2700     DeleteFileA(msifile);
2701 }
2702 
2703 static void test_feature_states( UINT line, MSIHANDLE package, const char *feature, UINT error,
2704                                  INSTALLSTATE expected_state, INSTALLSTATE expected_action, BOOL todo )
2705 {
2706     UINT r;
2707     INSTALLSTATE state = 0xdeadbee;
2708     INSTALLSTATE action = 0xdeadbee;
2709 
2710     r = MsiGetFeatureStateA( package, feature, &state, &action );
2711     ok( r == error, "%u: expected %d got %d\n", line, error, r );
2712     if (r == ERROR_SUCCESS)
2713     {
2714         ok( state == expected_state, "%u: expected state %d got %d\n",
2715             line, expected_state, state );
2716         todo_wine_if (todo)
2717             ok( action == expected_action, "%u: expected action %d got %d\n",
2718                 line, expected_action, action );
2719     }
2720     else
2721     {
2722         ok( state == 0xdeadbee, "%u: expected state 0xdeadbee got %d\n", line, state );
2723         todo_wine_if (todo)
2724             ok( action == 0xdeadbee, "%u: expected action 0xdeadbee got %d\n", line, action );
2725 
2726     }
2727 }
2728 
2729 static void test_component_states( UINT line, MSIHANDLE package, const char *component, UINT error,
2730                                    INSTALLSTATE expected_state, INSTALLSTATE expected_action, BOOL todo )
2731 {
2732     UINT r;
2733     INSTALLSTATE state = 0xdeadbee;
2734     INSTALLSTATE action = 0xdeadbee;
2735 
2736     r = MsiGetComponentStateA( package, component, &state, &action );
2737     ok( r == error, "%u: expected %d got %d\n", line, error, r );
2738     if (r == ERROR_SUCCESS)
2739     {
2740         ok( state == expected_state, "%u: expected state %d got %d\n",
2741             line, expected_state, state );
2742         todo_wine_if (todo)
2743             ok( action == expected_action, "%u: expected action %d got %d\n",
2744                 line, expected_action, action );
2745     }
2746     else
2747     {
2748         ok( state == 0xdeadbee, "%u: expected state 0xdeadbee got %d\n",
2749             line, state );
2750         todo_wine_if (todo)
2751             ok( action == 0xdeadbee, "%u: expected action 0xdeadbee got %d\n",
2752                 line, action );
2753     }
2754 }
2755 
2756 static void test_states(void)
2757 {
2758     static const char msifile2[] = "winetest2-package.msi";
2759     static const char msifile3[] = "winetest3-package.msi";
2760     static const char msifile4[] = "winetest4-package.msi";
2761     static const WCHAR msifile2W[] =
2762         {'w','i','n','e','t','e','s','t','2','-','p','a','c','k','a','g','e','.','m','s','i',0};
2763     static const WCHAR msifile3W[] =
2764         {'w','i','n','e','t','e','s','t','3','-','p','a','c','k','a','g','e','.','m','s','i',0};
2765     static const WCHAR msifile4W[] =
2766         {'w','i','n','e','t','e','s','t','4','-','p','a','c','k','a','g','e','.','m','s','i',0};
2767     INSTALLSTATE state;
2768     MSIHANDLE hpkg;
2769     UINT r;
2770     MSIHANDLE hdb;
2771 
2772     if (is_process_limited())
2773     {
2774         skip("process is limited\n");
2775         return;
2776     }
2777 
2778     hdb = create_package_db();
2779     ok ( hdb, "failed to create package database\n" );
2780 
2781     r = add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'");
2782     ok( r == ERROR_SUCCESS, "cannot add directory: %d\n", r );
2783 
2784     r = create_property_table( hdb );
2785     ok( r == ERROR_SUCCESS, "cannot create Property table: %d\n", r );
2786 
2787     r = add_property_entry( hdb, "'ProductCode', '{7262AC98-EEBD-4364-8CE3-D654F6A425B9}'" );
2788     ok( r == ERROR_SUCCESS, "cannot add property entry: %d\n", r );
2789 
2790     r = add_property_entry( hdb, "'ProductLanguage', '1033'" );
2791     ok( r == ERROR_SUCCESS, "cannot add property entry: %d\n", r );
2792 
2793     r = add_property_entry( hdb, "'ProductName', 'MSITEST'" );
2794     ok( r == ERROR_SUCCESS, "cannot add property entry: %d\n", r );
2795 
2796     r = add_property_entry( hdb, "'ProductVersion', '1.1.1'" );
2797     ok( r == ERROR_SUCCESS, "cannot add property entry: %d\n", r );
2798 
2799     r = add_property_entry( hdb, "'MSIFASTINSTALL', '1'" );
2800     ok( r == ERROR_SUCCESS, "cannot add property entry: %d\n", r );
2801 
2802     r = create_install_execute_sequence_table( hdb );
2803     ok( r == ERROR_SUCCESS, "cannot create InstallExecuteSequence table: %d\n", r );
2804 
2805     r = add_install_execute_sequence_entry( hdb, "'CostInitialize', '', '800'" );
2806     ok( r == ERROR_SUCCESS, "cannot add install execute sequence entry: %d\n", r );
2807 
2808     r = add_install_execute_sequence_entry( hdb, "'FileCost', '', '900'" );
2809     ok( r == ERROR_SUCCESS, "cannot add install execute sequence entry: %d\n", r );
2810 
2811     r = add_install_execute_sequence_entry( hdb, "'CostFinalize', '', '1000'" );
2812     ok( r == ERROR_SUCCESS, "cannot add install execute sequence entry: %d\n", r );
2813 
2814     r = add_install_execute_sequence_entry( hdb, "'InstallValidate', '', '1400'" );
2815     ok( r == ERROR_SUCCESS, "cannot add install execute sequence entry: %d\n", r );
2816 
2817     r = add_install_execute_sequence_entry( hdb, "'InstallInitialize', '', '1500'" );
2818     ok( r == ERROR_SUCCESS, "cannot add install execute sequence entry: %d\n", r );
2819 
2820     r = add_install_execute_sequence_entry( hdb, "'ProcessComponents', '', '1600'" );
2821     ok( r == ERROR_SUCCESS, "cannot add install execute sequence entry: %d\n", r );
2822 
2823     r = add_install_execute_sequence_entry( hdb, "'UnpublishFeatures', '', '1800'" );
2824     ok( r == ERROR_SUCCESS, "cannot add install execute sequence entry: %d\n", r );
2825 
2826     r = add_install_execute_sequence_entry( hdb, "'RegisterProduct', '', '6100'" );
2827     ok( r == ERROR_SUCCESS, "cannot add install execute sequence entry: %d\n", r );
2828 
2829     r = add_install_execute_sequence_entry( hdb, "'PublishFeatures', '', '6300'" );
2830     ok( r == ERROR_SUCCESS, "cannot add install execute sequence entry: %d\n", r );
2831 
2832     r = add_install_execute_sequence_entry( hdb, "'PublishProduct', '', '6400'" );
2833     ok( r == ERROR_SUCCESS, "cannot add install execute sequence entry: %d\n", r );
2834 
2835     r = add_install_execute_sequence_entry( hdb, "'InstallFinalize', '', '6600'" );
2836     ok( r == ERROR_SUCCESS, "cannot add install execute sequence entry: %d\n", r );
2837 
2838     r = create_media_table( hdb );
2839     ok( r == ERROR_SUCCESS, "cannot create media table: %d\n", r );
2840 
2841     r = add_media_entry( hdb, "'1', '3', '', '', 'DISK1', ''");
2842     ok( r == ERROR_SUCCESS, "cannot add media entry: %d\n", r );
2843 
2844     r = create_feature_table( hdb );
2845     ok( r == ERROR_SUCCESS, "cannot create Feature table: %d\n", r );
2846 
2847     r = create_component_table( hdb );
2848     ok( r == ERROR_SUCCESS, "cannot create Component table: %d\n", r );
2849 
2850     /* msidbFeatureAttributesFavorLocal */
2851     r = add_feature_entry( hdb, "'one', '', '', '', 2, 1, '', 0" );
2852     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
2853 
2854     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesLocalOnly */
2855     r = add_component_entry( hdb, "'alpha', '{467EC132-739D-4784-A37B-677AA43DBC94}', 'TARGETDIR', 0, '', 'alpha_file'" );
2856     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2857 
2858     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSourceOnly */
2859     r = add_component_entry( hdb, "'beta', '{2C1F189C-24A6-4C34-B26B-994A6C026506}', 'TARGETDIR', 1, '', 'beta_file'" );
2860     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2861 
2862     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesOptional */
2863     r = add_component_entry( hdb, "'gamma', '{C271E2A4-DE2E-4F70-86D1-6984AF7DE2CA}', 'TARGETDIR', 2, '', 'gamma_file'" );
2864     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2865 
2866     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSharedDllRefCount */
2867     r = add_component_entry( hdb, "'theta', '{4EB3129D-81A8-48D5-9801-75600FED3DD9}', 'TARGETDIR', 8, '', 'theta_file'" );
2868     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2869 
2870     /* msidbFeatureAttributesFavorSource */
2871     r = add_feature_entry( hdb, "'two', '', '', '', 2, 1, '', 1" );
2872     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
2873 
2874     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesLocalOnly */
2875     r = add_component_entry( hdb, "'delta', '{938FD4F2-C648-4259-A03C-7AA3B45643F3}', 'TARGETDIR', 0, '', 'delta_file'" );
2876     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2877 
2878     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSourceOnly */
2879     r = add_component_entry( hdb, "'epsilon', '{D59713B6-C11D-47F2-A395-1E5321781190}', 'TARGETDIR', 1, '', 'epsilon_file'" );
2880     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2881 
2882     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesOptional */
2883     r = add_component_entry( hdb, "'zeta', '{377D33AB-2FAA-42B9-A629-0C0DAE9B9C7A}', 'TARGETDIR', 2, '', 'zeta_file'" );
2884     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2885 
2886     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSharedDllRefCount */
2887     r = add_component_entry( hdb, "'iota', '{5D36F871-B5ED-4801-9E0F-C46B9E5C9669}', 'TARGETDIR', 8, '', 'iota_file'" );
2888     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2889 
2890     /* msidbFeatureAttributesFavorSource */
2891     r = add_feature_entry( hdb, "'three', '', '', '', 2, 1, '', 1" );
2892     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
2893 
2894     /* msidbFeatureAttributesFavorLocal */
2895     r = add_feature_entry( hdb, "'four', '', '', '', 2, 1, '', 0" );
2896     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
2897 
2898     /* disabled */
2899     r = add_feature_entry( hdb, "'five', '', '', '', 2, 0, '', 1" );
2900     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
2901 
2902     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSourceOnly */
2903     r = add_component_entry( hdb, "'eta', '{DD89003F-0DD4-41B8-81C0-3411A7DA2695}', 'TARGETDIR', 1, '', 'eta_file'" );
2904     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2905 
2906     /* no feature parent:msidbComponentAttributesLocalOnly */
2907     r = add_component_entry( hdb, "'kappa', '{D6B93DC3-8DA5-4769-9888-42BFE156BB8B}', 'TARGETDIR', 1, '', 'kappa_file'" );
2908     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2909 
2910     /* msidbFeatureAttributesFavorLocal:removed */
2911     r = add_feature_entry( hdb, "'six', '', '', '', 2, 1, '', 0" );
2912     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
2913 
2914     /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesLocalOnly */
2915     r = add_component_entry( hdb, "'lambda', '{6528C5E4-02A4-4636-A214-7A66A6C35B64}', 'TARGETDIR', 0, '', 'lambda_file'" );
2916     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2917 
2918     /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesSourceOnly */
2919     r = add_component_entry( hdb, "'mu', '{97014BAB-6C56-4013-9A63-2BF913B42519}', 'TARGETDIR', 1, '', 'mu_file'" );
2920     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2921 
2922     /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesOptional */
2923     r = add_component_entry( hdb, "'nu', '{943DD0D8-5808-4954-8526-3B8493FEDDCD}', 'TARGETDIR', 2, '', 'nu_file'" );
2924     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2925 
2926     /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesSharedDllRefCount */
2927     r = add_component_entry( hdb, "'xi', '{D6CF9EF7-6FCF-4930-B34B-F938AEFF9BDB}', 'TARGETDIR', 8, '', 'xi_file'" );
2928     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2929 
2930     /* msidbFeatureAttributesFavorSource:removed */
2931     r = add_feature_entry( hdb, "'seven', '', '', '', 2, 1, '', 1" );
2932     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
2933 
2934     /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesLocalOnly */
2935     r = add_component_entry( hdb, "'omicron', '{7B57521D-15DB-4141-9AA6-01D934A4433F}', 'TARGETDIR', 0, '', 'omicron_file'" );
2936     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2937 
2938     /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesSourceOnly */
2939     r = add_component_entry( hdb, "'pi', '{FB85346B-378E-4492-8769-792305471C81}', 'TARGETDIR', 1, '', 'pi_file'" );
2940     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2941 
2942     /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesOptional */
2943     r = add_component_entry( hdb, "'rho', '{798F2047-7B0C-4783-8BB0-D703E554114B}', 'TARGETDIR', 2, '', 'rho_file'" );
2944     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2945 
2946     /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesSharedDllRefCount */
2947     r = add_component_entry( hdb, "'sigma', '{5CE9DDA8-B67B-4736-9D93-99D61C5B93E7}', 'TARGETDIR', 8, '', 'sigma_file'" );
2948     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2949 
2950     /* msidbFeatureAttributesFavorLocal */
2951     r = add_feature_entry( hdb, "'eight', '', '', '', 2, 1, '', 0" );
2952     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
2953 
2954     r = add_component_entry( hdb, "'tau', '{07DEB510-677C-4A6F-A0A6-7CD8EFEA77ED}', 'TARGETDIR', 1, '', 'tau_file'" );
2955     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2956 
2957     /* msidbFeatureAttributesFavorSource */
2958     r = add_feature_entry( hdb, "'nine', '', '', '', 2, 1, '', 1" );
2959     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
2960 
2961     r = add_component_entry( hdb, "'phi', '{9F0594C5-35AD-43EA-94DD-8DF73FAA664D}', 'TARGETDIR', 1, '', 'phi_file'" );
2962     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2963 
2964     /* msidbFeatureAttributesFavorAdvertise */
2965     r = add_feature_entry( hdb, "'ten', '', '', '', 2, 1, '', 4" );
2966     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
2967 
2968     r = add_component_entry( hdb, "'chi', '{E6B539AB-5DA9-4236-A2D2-E341A50B4C38}', 'TARGETDIR', 1, '', 'chi_file'" );
2969     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2970 
2971     /* msidbFeatureAttributesUIDisallowAbsent */
2972     r = add_feature_entry( hdb, "'eleven', '', '', '', 2, 1, '', 16" );
2973     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
2974 
2975     r = add_component_entry( hdb, "'psi', '{A06B23B5-746B-427A-8A6E-FD6AC8F46A95}', 'TARGETDIR', 1, '', 'psi_file'" );
2976     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2977 
2978     /* high install level */
2979     r = add_feature_entry( hdb, "'twelve', '', '', '', 2, 2, '', 0" );
2980     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
2981 
2982     r = add_component_entry( hdb, "'upsilon', '{557e0c04-ceba-4c58-86a9-4a73352e8cf6}', 'TARGETDIR', 1, '', 'upsilon_file'" );
2983     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2984 
2985     /* msidbFeatureAttributesFollowParent */
2986     r = add_feature_entry( hdb, "'thirteen', '', '', '', 2, 2, '', 2" );
2987     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
2988 
2989     r = create_feature_components_table( hdb );
2990     ok( r == ERROR_SUCCESS, "cannot create FeatureComponents table: %d\n", r );
2991 
2992     r = add_feature_components_entry( hdb, "'one', 'alpha'" );
2993     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
2994 
2995     r = add_feature_components_entry( hdb, "'one', 'beta'" );
2996     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
2997 
2998     r = add_feature_components_entry( hdb, "'one', 'gamma'" );
2999     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3000 
3001     r = add_feature_components_entry( hdb, "'one', 'theta'" );
3002     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3003 
3004     r = add_feature_components_entry( hdb, "'two', 'delta'" );
3005     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3006 
3007     r = add_feature_components_entry( hdb, "'two', 'epsilon'" );
3008     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3009 
3010     r = add_feature_components_entry( hdb, "'two', 'zeta'" );
3011     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3012 
3013     r = add_feature_components_entry( hdb, "'two', 'iota'" );
3014     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3015 
3016     r = add_feature_components_entry( hdb, "'three', 'eta'" );
3017     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3018 
3019     r = add_feature_components_entry( hdb, "'four', 'eta'" );
3020     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3021 
3022     r = add_feature_components_entry( hdb, "'five', 'eta'" );
3023     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3024 
3025     r = add_feature_components_entry( hdb, "'six', 'lambda'" );
3026     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3027 
3028     r = add_feature_components_entry( hdb, "'six', 'mu'" );
3029     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3030 
3031     r = add_feature_components_entry( hdb, "'six', 'nu'" );
3032     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3033 
3034     r = add_feature_components_entry( hdb, "'six', 'xi'" );
3035     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3036 
3037     r = add_feature_components_entry( hdb, "'seven', 'omicron'" );
3038     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3039 
3040     r = add_feature_components_entry( hdb, "'seven', 'pi'" );
3041     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3042 
3043     r = add_feature_components_entry( hdb, "'seven', 'rho'" );
3044     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3045 
3046     r = add_feature_components_entry( hdb, "'seven', 'sigma'" );
3047     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3048 
3049     r = add_feature_components_entry( hdb, "'eight', 'tau'" );
3050     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3051 
3052     r = add_feature_components_entry( hdb, "'nine', 'phi'" );
3053     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3054 
3055     r = add_feature_components_entry( hdb, "'ten', 'chi'" );
3056     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3057 
3058     r = add_feature_components_entry( hdb, "'eleven', 'psi'" );
3059     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3060 
3061     r = add_feature_components_entry( hdb, "'twelve', 'upsilon'" );
3062     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3063 
3064     r = add_feature_components_entry( hdb, "'thirteen', 'upsilon'" );
3065     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3066 
3067     r = create_file_table( hdb );
3068     ok( r == ERROR_SUCCESS, "cannot create File table: %d\n", r );
3069 
3070     r = add_file_entry( hdb, "'alpha_file', 'alpha', 'alpha.txt', 100, '', '1033', 8192, 1" );
3071     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3072 
3073     r = add_file_entry( hdb, "'beta_file', 'beta', 'beta.txt', 0, '', '1033', 8192, 1" );
3074     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3075 
3076     r = add_file_entry( hdb, "'gamma_file', 'gamma', 'gamma.txt', 0, '', '1033', 8192, 1" );
3077     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3078 
3079     r = add_file_entry( hdb, "'theta_file', 'theta', 'theta.txt', 0, '', '1033', 8192, 1" );
3080     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3081 
3082     r = add_file_entry( hdb, "'delta_file', 'delta', 'delta.txt', 0, '', '1033', 8192, 1" );
3083     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3084 
3085     r = add_file_entry( hdb, "'epsilon_file', 'epsilon', 'epsilon.txt', 0, '', '1033', 8192, 1" );
3086     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3087 
3088     r = add_file_entry( hdb, "'zeta_file', 'zeta', 'zeta.txt', 0, '', '1033', 8192, 1" );
3089     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3090 
3091     r = add_file_entry( hdb, "'iota_file', 'iota', 'iota.txt', 0, '', '1033', 8192, 1" );
3092     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3093 
3094     /* compressed file */
3095     r = add_file_entry( hdb, "'eta_file', 'eta', 'eta.txt', 0, '', '1033', 16384, 1" );
3096     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3097 
3098     r = add_file_entry( hdb, "'kappa_file', 'kappa', 'kappa.txt', 0, '', '1033', 8192, 1" );
3099     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3100 
3101     r = add_file_entry( hdb, "'lambda_file', 'lambda', 'lambda.txt', 100, '', '1033', 8192, 1" );
3102     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3103 
3104     r = add_file_entry( hdb, "'mu_file', 'mu', 'mu.txt', 100, '', '1033', 8192, 1" );
3105     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3106 
3107     r = add_file_entry( hdb, "'nu_file', 'nu', 'nu.txt', 100, '', '1033', 8192, 1" );
3108     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3109 
3110     r = add_file_entry( hdb, "'xi_file', 'xi', 'xi.txt', 100, '', '1033', 8192, 1" );
3111     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3112 
3113     r = add_file_entry( hdb, "'omicron_file', 'omicron', 'omicron.txt', 100, '', '1033', 8192, 1" );
3114     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3115 
3116     r = add_file_entry( hdb, "'pi_file', 'pi', 'pi.txt', 100, '', '1033', 8192, 1" );
3117     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3118 
3119     r = add_file_entry( hdb, "'rho_file', 'rho', 'rho.txt', 100, '', '1033', 8192, 1" );
3120     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3121 
3122     r = add_file_entry( hdb, "'sigma_file', 'sigma', 'sigma.txt', 100, '', '1033', 8192, 1" );
3123     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3124 
3125     r = add_file_entry( hdb, "'tau_file', 'tau', 'tau.txt', 100, '', '1033', 8192, 1" );
3126     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3127 
3128     r = add_file_entry( hdb, "'phi_file', 'phi', 'phi.txt', 100, '', '1033', 8192, 1" );
3129     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3130 
3131     r = add_file_entry( hdb, "'chi_file', 'chi', 'chi.txt', 100, '', '1033', 8192, 1" );
3132     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3133 
3134     r = add_file_entry( hdb, "'psi_file', 'psi', 'psi.txt', 100, '', '1033', 8192, 1" );
3135     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3136 
3137     r = add_file_entry( hdb, "'upsilon_file', 'upsilon', 'upsilon.txt', 0, '', '1033', 16384, 1" );
3138     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3139 
3140     MsiDatabaseCommit(hdb);
3141 
3142     /* these properties must not be in the saved msi file */
3143     r = add_property_entry( hdb, "'ADDLOCAL', 'one,four'");
3144     ok( r == ERROR_SUCCESS, "cannot add property: %d\n", r );
3145 
3146     r = add_property_entry( hdb, "'ADDSOURCE', 'two,three'");
3147     ok( r == ERROR_SUCCESS, "cannot add property: %d\n", r );
3148 
3149     r = add_property_entry( hdb, "'REMOVE', 'six,seven'");
3150     ok( r == ERROR_SUCCESS, "cannot add property: %d\n", r );
3151 
3152     r = add_property_entry( hdb, "'REINSTALL', 'eight,nine,ten'");
3153     ok( r == ERROR_SUCCESS, "cannot add property: %d\n", r );
3154 
3155     r = add_property_entry( hdb, "'REINSTALLMODE', 'omus'");
3156     ok( r == ERROR_SUCCESS, "cannot add property: %d\n", r );
3157 
3158     r = package_from_db( hdb, &hpkg );
3159     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
3160     {
3161         skip("Not enough rights to perform tests\n");
3162         DeleteFileA(msifile);
3163         return;
3164     }
3165     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3166 
3167     MsiCloseHandle(hdb);
3168 
3169     CopyFileA(msifile, msifile2, FALSE);
3170     CopyFileA(msifile, msifile3, FALSE);
3171     CopyFileA(msifile, msifile4, FALSE);
3172 
3173     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3174     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3175 
3176     r = MsiDoActionA( hpkg, "CostInitialize");
3177     ok( r == ERROR_SUCCESS, "cost init failed\n");
3178 
3179     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3180     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3181 
3182     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3183 
3184     r = MsiDoActionA( hpkg, "FileCost");
3185     ok( r == ERROR_SUCCESS, "file cost failed\n");
3186 
3187     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3188     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3189 
3190     r = MsiDoActionA( hpkg, "CostFinalize");
3191     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3192 
3193     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3194     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
3195     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3196     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3197     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3198     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3199     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3200     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3201     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3202     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3203     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3204     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3205     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3206 
3207     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3208     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
3209     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3210     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3211     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3212     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
3213     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
3214     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3215     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3216     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3217     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3218     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3219     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3220     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3221     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3222     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3223     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3224     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3225     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3226     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3227     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3228     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3229     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3230 
3231     MsiCloseHandle( hpkg );
3232 
3233     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3234 
3235     /* publish the features and components */
3236     r = MsiInstallProductA(msifile, "ADDLOCAL=one,four ADDSOURCE=two,three REMOVE=six,seven REINSTALL=eight,nine,ten");
3237     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3238 
3239     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb);
3240     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3241 
3242     /* these properties must not be in the saved msi file */
3243     r = add_property_entry( hdb, "'ADDLOCAL', 'one,four'");
3244     ok( r == ERROR_SUCCESS, "cannot add property: %d\n", r );
3245 
3246     r = add_property_entry( hdb, "'ADDSOURCE', 'two,three'");
3247     ok( r == ERROR_SUCCESS, "cannot add property: %d\n", r );
3248 
3249     r = add_property_entry( hdb, "'REMOVE', 'six,seven'");
3250     ok( r == ERROR_SUCCESS, "cannot add property: %d\n", r );
3251 
3252     r = add_property_entry( hdb, "'REINSTALL', 'eight,nine,ten'");
3253     ok( r == ERROR_SUCCESS, "cannot add property: %d\n", r );
3254 
3255     r = package_from_db( hdb, &hpkg );
3256     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3257 
3258     MsiCloseHandle(hdb);
3259 
3260     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3261     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3262 
3263     r = MsiDoActionA( hpkg, "CostInitialize");
3264     ok( r == ERROR_SUCCESS, "cost init failed\n");
3265 
3266     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3267     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3268 
3269     r = MsiDoActionA( hpkg, "FileCost");
3270     ok( r == ERROR_SUCCESS, "file cost failed\n");
3271 
3272     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3273     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3274 
3275     r = MsiDoActionA( hpkg, "CostFinalize");
3276     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3277 
3278     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3279     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3280     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3281     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3282     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3283     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3284     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3285     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3286     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3287     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3288     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3289     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3290     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3291 
3292     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3293     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3294     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3295     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3296     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3297     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3298     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3299     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3300     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3301     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3302     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3303     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3304     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3305     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3306     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3307     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3308     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3309     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3310     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3311     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3312     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3313     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3314     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3315 
3316     MsiCloseHandle(hpkg);
3317 
3318     /* uninstall the product */
3319     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3320     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3321 
3322     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3323     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3324     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3325     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3326 
3327     /* all features installed locally */
3328     r = MsiInstallProductA(msifile2, "ADDLOCAL=ALL");
3329     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3330 
3331     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3332     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3333     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3334     ok(state == INSTALLSTATE_LOCAL, "state = %d\n", state);
3335 
3336     r = MsiOpenDatabaseW(msifile2W, MSIDBOPEN_DIRECT, &hdb);
3337     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3338 
3339     /* these properties must not be in the saved msi file */
3340     r = add_property_entry( hdb, "'ADDLOCAL', 'one,two,three,four,five,six,seven,eight,nine,ten,twelve'");
3341     ok( r == ERROR_SUCCESS, "cannot add property: %d\n", r );
3342 
3343     r = package_from_db( hdb, &hpkg );
3344     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3345 
3346     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3347     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3348 
3349     r = MsiDoActionA( hpkg, "CostInitialize");
3350     ok( r == ERROR_SUCCESS, "cost init failed\n");
3351 
3352     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3353     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3354 
3355     r = MsiDoActionA( hpkg, "CostFinalize");
3356     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3357 
3358     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3359     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3360     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3361     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3362     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3363     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3364     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3365     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, TRUE );
3366     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, TRUE );
3367     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, TRUE );
3368     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3369     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3370     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3371 
3372     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3373     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3374     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3375     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3376     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3377     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3378     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3379     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3380     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3381     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3382     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3383     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3384     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3385     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3386     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3387     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3388     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3389     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3390     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3391     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3392     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3393     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3394     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3395 
3396     MsiCloseHandle(hpkg);
3397 
3398     /* uninstall the product */
3399     r = MsiInstallProductA(msifile2, "REMOVE=ALL");
3400     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3401 
3402     /* all features installed from source */
3403     r = MsiInstallProductA(msifile3, "ADDSOURCE=ALL");
3404     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3405 
3406     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3407     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3408     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3409     ok(state == INSTALLSTATE_LOCAL, "state = %d\n", state);
3410 
3411     r = MsiOpenDatabaseW(msifile3W, MSIDBOPEN_DIRECT, &hdb);
3412     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3413 
3414     /* this property must not be in the saved msi file */
3415     r = add_property_entry( hdb, "'ADDSOURCE', 'one,two,three,four,five,six,seven,eight,nine,ten'");
3416     ok( r == ERROR_SUCCESS, "cannot add property: %d\n", r );
3417 
3418     r = package_from_db( hdb, &hpkg );
3419     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3420 
3421     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3422     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3423 
3424     r = MsiDoActionA( hpkg, "CostInitialize");
3425     ok( r == ERROR_SUCCESS, "cost init failed\n");
3426 
3427     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3428     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3429 
3430     r = MsiDoActionA( hpkg, "FileCost");
3431     ok( r == ERROR_SUCCESS, "file cost failed\n");
3432 
3433     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3434     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3435 
3436     r = MsiDoActionA( hpkg, "CostFinalize");
3437     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3438 
3439     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3440     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3441     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3442     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3443     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3444     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3445     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3446     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3447     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3448     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3449     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3450     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3451     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3452 
3453     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3454     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3455     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3456     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3457     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3458     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3459     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3460     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3461     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3462     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3463     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3464     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3465     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3466     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3467     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3468     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3469     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3470     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3471     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3472     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3473     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3474     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3475     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, TRUE );
3476 
3477     MsiCloseHandle(hpkg);
3478 
3479     /* reinstall the product */
3480     r = MsiInstallProductA(msifile3, "REINSTALL=ALL");
3481     ok(r == ERROR_SUCCESS || broken(r == ERROR_INSTALL_FAILURE) /* win2k3 */, "Expected ERROR_SUCCESS, got %d\n", r);
3482 
3483     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3484     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3485     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3486     ok(state == INSTALLSTATE_LOCAL, "state = %d\n", state);
3487 
3488     r = MsiOpenDatabaseW(msifile4W, MSIDBOPEN_DIRECT, &hdb);
3489     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3490 
3491     /* this property must not be in the saved msi file */
3492     r = add_property_entry( hdb, "'ADDSOURCE', 'one,two,three,four,five,six,seven,eight,nine,ten'");
3493     ok( r == ERROR_SUCCESS, "cannot add property: %d\n", r );
3494 
3495     r = package_from_db( hdb, &hpkg );
3496     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3497 
3498     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3499     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3500 
3501     r = MsiDoActionA( hpkg, "CostInitialize");
3502     ok( r == ERROR_SUCCESS, "cost init failed\n");
3503 
3504     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3505     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3506 
3507     r = MsiDoActionA( hpkg, "FileCost");
3508     ok( r == ERROR_SUCCESS, "file cost failed\n");
3509 
3510     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3511     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3512 
3513     r = MsiDoActionA( hpkg, "CostFinalize");
3514     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3515 
3516     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3517     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3518     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3519     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3520     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3521     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3522     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3523     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3524     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3525     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3526     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3527     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3528     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3529 
3530     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3531     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3532     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3533     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3534     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3535     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3536     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3537     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3538     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3539     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3540     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3541     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3542     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3543     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3544     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3545     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3546     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3547     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3548     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3549     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3550     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3551     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3552     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, TRUE );
3553 
3554     MsiCloseHandle(hpkg);
3555 
3556     /* uninstall the product */
3557     r = MsiInstallProductA(msifile4, "REMOVE=ALL");
3558     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3559 
3560     DeleteFileA(msifile);
3561     DeleteFileA(msifile2);
3562     DeleteFileA(msifile3);
3563     DeleteFileA(msifile4);
3564 }
3565 
3566 static void test_getproperty(void)
3567 {
3568     MSIHANDLE hPackage = 0;
3569     char prop[100];
3570     static CHAR empty[] = "";
3571     DWORD size;
3572     UINT r;
3573 
3574     r = package_from_db(create_package_db(), &hPackage);
3575     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
3576     {
3577         skip("Not enough rights to perform tests\n");
3578         DeleteFileA(msifile);
3579         return;
3580     }
3581     ok( r == ERROR_SUCCESS, "Failed to create package %u\n", r );
3582 
3583     /* set the property */
3584     r = MsiSetPropertyA(hPackage, "Name", "Value");
3585     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3586 
3587     /* retrieve the size, NULL pointer */
3588     size = 0;
3589     r = MsiGetPropertyA(hPackage, "Name", NULL, &size);
3590     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3591     ok( size == 5, "Expected 5, got %d\n", size);
3592 
3593     /* retrieve the size, empty string */
3594     size = 0;
3595     r = MsiGetPropertyA(hPackage, "Name", empty, &size);
3596     ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
3597     ok( size == 5, "Expected 5, got %d\n", size);
3598 
3599     /* don't change size */
3600     r = MsiGetPropertyA(hPackage, "Name", prop, &size);
3601     ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
3602     ok( size == 5, "Expected 5, got %d\n", size);
3603     ok( !lstrcmpA(prop, "Valu"), "Expected Valu, got %s\n", prop);
3604 
3605     /* increase the size by 1 */
3606     size++;
3607     r = MsiGetPropertyA(hPackage, "Name", prop, &size);
3608     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3609     ok( size == 5, "Expected 5, got %d\n", size);
3610     ok( !lstrcmpA(prop, "Value"), "Expected Value, got %s\n", prop);
3611 
3612     r = MsiCloseHandle( hPackage);
3613     ok( r == ERROR_SUCCESS , "Failed to close package\n" );
3614     DeleteFileA(msifile);
3615 }
3616 
3617 static void test_removefiles(void)
3618 {
3619     MSIHANDLE hpkg;
3620     UINT r;
3621     MSIHANDLE hdb;
3622     INSTALLSTATE installed, action;
3623 
3624     hdb = create_package_db();
3625     ok ( hdb, "failed to create package database\n" );
3626 
3627     r = add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'");
3628     ok( r == ERROR_SUCCESS, "cannot add directory: %d\n", r );
3629 
3630     r = create_feature_table( hdb );
3631     ok( r == ERROR_SUCCESS, "cannot create Feature table: %d\n", r );
3632 
3633     r = create_component_table( hdb );
3634     ok( r == ERROR_SUCCESS, "cannot create Component table: %d\n", r );
3635 
3636     r = add_feature_entry( hdb, "'one', '', '', '', 2, 1, '', 0" );
3637     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
3638 
3639     r = add_component_entry( hdb, "'hydrogen', '', 'TARGETDIR', 0, '', 'hydrogen_file'" );
3640     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3641 
3642     r = add_component_entry( hdb, "'helium', '', 'TARGETDIR', 0, '', 'helium_file'" );
3643     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3644 
3645     r = add_component_entry( hdb, "'lithium', '', 'TARGETDIR', 0, '', 'lithium_file'" );
3646     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3647 
3648     r = add_component_entry( hdb, "'beryllium', '', 'TARGETDIR', 0, '', 'beryllium_file'" );
3649     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3650 
3651     r = add_component_entry( hdb, "'boron', '', 'TARGETDIR', 0, '', 'boron_file'" );
3652     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3653 
3654     r = add_component_entry( hdb, "'carbon', '', 'TARGETDIR', 0, '', 'carbon_file'" );
3655     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3656 
3657     r = add_component_entry( hdb, "'oxygen', '', 'TARGETDIR', 0, '0', 'oxygen_file'" );
3658     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3659 
3660     r = create_feature_components_table( hdb );
3661     ok( r == ERROR_SUCCESS, "cannot create FeatureComponents table: %d\n", r );
3662 
3663     r = add_feature_components_entry( hdb, "'one', 'hydrogen'" );
3664     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3665 
3666     r = add_feature_components_entry( hdb, "'one', 'helium'" );
3667     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3668 
3669     r = add_feature_components_entry( hdb, "'one', 'lithium'" );
3670     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3671 
3672     r = add_feature_components_entry( hdb, "'one', 'beryllium'" );
3673     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3674 
3675     r = add_feature_components_entry( hdb, "'one', 'boron'" );
3676     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3677 
3678     r = add_feature_components_entry( hdb, "'one', 'carbon'" );
3679     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3680 
3681     r = add_feature_components_entry( hdb, "'one', 'oxygen'" );
3682     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3683 
3684     r = create_file_table( hdb );
3685     ok( r == ERROR_SUCCESS, "cannot create File table: %d\n", r );
3686 
3687     r = add_file_entry( hdb, "'hydrogen_file', 'hydrogen', 'hydrogen.txt', 0, '', '1033', 8192, 1" );
3688     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3689 
3690     r = add_file_entry( hdb, "'helium_file', 'helium', 'helium.txt', 0, '', '1033', 8192, 1" );
3691     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3692 
3693     r = add_file_entry( hdb, "'lithium_file', 'lithium', 'lithium.txt', 0, '', '1033', 8192, 1" );
3694     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3695 
3696     r = add_file_entry( hdb, "'beryllium_file', 'beryllium', 'beryllium.txt', 0, '', '1033', 16384, 1" );
3697     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3698 
3699     r = add_file_entry( hdb, "'boron_file', 'boron', 'boron.txt', 0, '', '1033', 16384, 1" );
3700     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3701 
3702     r = add_file_entry( hdb, "'carbon_file', 'carbon', 'carbon.txt', 0, '', '1033', 16384, 1" );
3703     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3704 
3705     r = add_file_entry( hdb, "'oxygen_file', 'oxygen', 'oxygen.txt', 0, '', '1033', 16384, 1" );
3706     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3707 
3708     r = create_remove_file_table( hdb );
3709     ok( r == ERROR_SUCCESS, "cannot create Remove File table: %d\n", r);
3710 
3711     r = package_from_db( hdb, &hpkg );
3712     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
3713     {
3714         skip("Not enough rights to perform tests\n");
3715         DeleteFileA(msifile);
3716         return;
3717     }
3718     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3719 
3720     MsiCloseHandle( hdb );
3721 
3722     create_test_file( "hydrogen.txt" );
3723     create_test_file( "helium.txt" );
3724     create_test_file( "lithium.txt" );
3725     create_test_file( "beryllium.txt" );
3726     create_test_file( "boron.txt" );
3727     create_test_file( "carbon.txt" );
3728     create_test_file( "oxygen.txt" );
3729 
3730     r = MsiSetPropertyA( hpkg, "TARGETDIR", CURR_DIR );
3731     ok( r == ERROR_SUCCESS, "set property failed\n");
3732 
3733     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3734 
3735     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3736     ok( r == ERROR_UNKNOWN_COMPONENT, "expected ERROR_UNKNOWN_COMPONENT, got %u\n", r );
3737 
3738     r = MsiDoActionA( hpkg, "CostInitialize");
3739     ok( r == ERROR_SUCCESS, "cost init failed\n");
3740 
3741     r = MsiDoActionA( hpkg, "FileCost");
3742     ok( r == ERROR_SUCCESS, "file cost failed\n");
3743 
3744     installed = action = 0xdeadbeef;
3745     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3746     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3747     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3748     ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3749 
3750     r = MsiDoActionA( hpkg, "CostFinalize");
3751     ok( r == ERROR_SUCCESS, "cost finalize failed\n");
3752 
3753     r = MsiDoActionA( hpkg, "InstallValidate");
3754     ok( r == ERROR_SUCCESS, "install validate failed\n");
3755 
3756     r = MsiSetComponentStateA( hpkg, "hydrogen", INSTALLSTATE_ABSENT );
3757     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3758 
3759     installed = action = 0xdeadbeef;
3760     r = MsiGetComponentStateA( hpkg, "hydrogen", &installed, &action );
3761     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3762     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3763     todo_wine ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3764 
3765     r = MsiSetComponentStateA( hpkg, "helium", INSTALLSTATE_LOCAL );
3766     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3767 
3768     r = MsiSetComponentStateA( hpkg, "lithium", INSTALLSTATE_SOURCE );
3769     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3770 
3771     r = MsiSetComponentStateA( hpkg, "beryllium", INSTALLSTATE_ABSENT );
3772     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3773 
3774     r = MsiSetComponentStateA( hpkg, "boron", INSTALLSTATE_LOCAL );
3775     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3776 
3777     r = MsiSetComponentStateA( hpkg, "carbon", INSTALLSTATE_SOURCE );
3778     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3779 
3780     installed = action = 0xdeadbeef;
3781     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3782     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3783     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3784     ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3785 
3786     r = MsiSetComponentStateA( hpkg, "oxygen", INSTALLSTATE_ABSENT );
3787     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3788 
3789     installed = action = 0xdeadbeef;
3790     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3791     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3792     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3793     ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3794 
3795     r = MsiDoActionA( hpkg, "RemoveFiles");
3796     ok( r == ERROR_SUCCESS, "remove files failed\n");
3797 
3798     installed = action = 0xdeadbeef;
3799     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3800     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3801     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3802     ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3803 
3804     ok(DeleteFileA("hydrogen.txt"), "Expected hydrogen.txt to exist\n");
3805     ok(DeleteFileA("lithium.txt"), "Expected lithium.txt to exist\n");
3806     ok(DeleteFileA("beryllium.txt"), "Expected beryllium.txt to exist\n");
3807     ok(DeleteFileA("carbon.txt"), "Expected carbon.txt to exist\n");
3808     ok(DeleteFileA("helium.txt"), "Expected helium.txt to exist\n");
3809     ok(DeleteFileA("boron.txt"), "Expected boron.txt to exist\n");
3810     ok(DeleteFileA("oxygen.txt"), "Expected oxygen.txt to exist\n");
3811 
3812     MsiCloseHandle( hpkg );
3813     DeleteFileA(msifile);
3814 }
3815 
3816 static void test_appsearch(void)
3817 {
3818     MSIHANDLE hpkg;
3819     UINT r;
3820     MSIHANDLE hdb;
3821     CHAR prop[MAX_PATH];
3822     DWORD size;
3823     HKEY hkey;
3824     const char reg_expand_value[] = "%systemroot%\\system32\\notepad.exe";
3825 
3826     hdb = create_package_db();
3827     ok ( hdb, "failed to create package database\n" );
3828 
3829     r = create_appsearch_table( hdb );
3830     ok( r == ERROR_SUCCESS, "cannot create AppSearch table: %d\n", r );
3831 
3832     r = add_appsearch_entry( hdb, "'WEBBROWSERPROG', 'NewSignature1'" );
3833     ok( r == ERROR_SUCCESS, "cannot add entry: %d\n", r );
3834 
3835     r = add_appsearch_entry( hdb, "'NOTEPAD', 'NewSignature2'" );
3836     ok( r == ERROR_SUCCESS, "cannot add entry: %d\n", r );
3837 
3838     r = add_appsearch_entry( hdb, "'REGEXPANDVAL', 'NewSignature3'" );
3839     ok( r == ERROR_SUCCESS, "cannot add entry: %d\n", r );
3840 
3841     r = create_reglocator_table( hdb );
3842     ok( r == ERROR_SUCCESS, "cannot create RegLocator table: %d\n", r );
3843 
3844     r = add_reglocator_entry( hdb, "NewSignature1", 0, "htmlfile\\shell\\open\\command", "", 1 );
3845     ok( r == ERROR_SUCCESS, "cannot create RegLocator table: %d\n", r );
3846 
3847     r = RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Winetest_msi", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, NULL);
3848     ok( r == ERROR_SUCCESS, "Could not create key: %d.\n", r );
3849     r = RegSetValueExA(hkey, NULL, 0, REG_EXPAND_SZ, (const BYTE*)reg_expand_value, strlen(reg_expand_value) + 1);
3850     ok( r == ERROR_SUCCESS, "Could not set key value: %d.\n", r);
3851     RegCloseKey(hkey);
3852     r = add_reglocator_entry( hdb, "NewSignature3", 1, "Software\\Winetest_msi", "", 1 );
3853     ok( r == ERROR_SUCCESS, "cannot create RegLocator table: %d\n", r );
3854 
3855     r = create_drlocator_table( hdb );
3856     ok( r == ERROR_SUCCESS, "cannot create DrLocator table: %d\n", r );
3857 
3858     r = add_drlocator_entry( hdb, "'NewSignature2', 0, 'c:\\windows\\system32', 0" );
3859     ok( r == ERROR_SUCCESS, "cannot create RegLocator table: %d\n", r );
3860 
3861     r = create_signature_table( hdb );
3862     ok( r == ERROR_SUCCESS, "cannot create Signature table: %d\n", r );
3863 
3864     r = add_signature_entry( hdb, "'NewSignature1', 'FileName', '', '', '', '', '', '', ''" );
3865     ok( r == ERROR_SUCCESS, "cannot add signature: %d\n", r );
3866 
3867     r = add_signature_entry( hdb, "'NewSignature2', 'NOTEPAD.EXE|notepad.exe', '', '', '', '', '', '', ''" );
3868     ok( r == ERROR_SUCCESS, "cannot add signature: %d\n", r );
3869 
3870     r = add_signature_entry( hdb, "'NewSignature3', 'NOTEPAD.EXE|notepad.exe', '', '', '', '', '', '', ''" );
3871     ok( r == ERROR_SUCCESS, "cannot add signature: %d\n", r );
3872 
3873     r = package_from_db( hdb, &hpkg );
3874     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
3875     {
3876         skip("Not enough rights to perform tests\n");
3877         DeleteFileA(msifile);
3878         return;
3879     }
3880     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3881     MsiCloseHandle( hdb );
3882     if (r != ERROR_SUCCESS)
3883         goto done;
3884 
3885     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3886 
3887     r = MsiDoActionA( hpkg, "AppSearch" );
3888     ok( r == ERROR_SUCCESS, "AppSearch failed: %d\n", r);
3889 
3890     size = sizeof(prop);
3891     r = MsiGetPropertyA( hpkg, "WEBBROWSERPROG", prop, &size );
3892     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
3893     ok( lstrlenA(prop) != 0, "Expected non-zero length\n");
3894 
3895     size = sizeof(prop);
3896     r = MsiGetPropertyA( hpkg, "NOTEPAD", prop, &size );
3897     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
3898 
3899     size = sizeof(prop);
3900     r = MsiGetPropertyA( hpkg, "REGEXPANDVAL", prop, &size );
3901     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
3902     ok( lstrlenA(prop) != 0, "Expected non-zero length\n");
3903 
3904 done:
3905     MsiCloseHandle( hpkg );
3906     DeleteFileA(msifile);
3907     RegDeleteKeyA(HKEY_CURRENT_USER, "Software\\Winetest_msi");
3908 }
3909 
3910 static void test_appsearch_complocator(void)
3911 {
3912     MSIHANDLE hpkg, hdb;
3913     char path[MAX_PATH], expected[MAX_PATH], prop[MAX_PATH];
3914     LPSTR usersid;
3915     DWORD size;
3916     UINT r;
3917 
3918     if (!(usersid = get_user_sid()))
3919         return;
3920 
3921     if (is_process_limited())
3922     {
3923         skip("process is limited\n");
3924         return;
3925     }
3926 
3927     create_test_file("FileName1");
3928     create_test_file("FileName4");
3929     set_component_path("FileName1", MSIINSTALLCONTEXT_MACHINE,
3930                        "{A8AE6692-96BA-4198-8399-145D7D1D0D0E}", NULL, FALSE);
3931 
3932     create_test_file("FileName2");
3933     set_component_path("FileName2", MSIINSTALLCONTEXT_USERUNMANAGED,
3934                        "{1D2CE6F3-E81C-4949-AB81-78D7DAD2AF2E}", usersid, FALSE);
3935 
3936     create_test_file("FileName3");
3937     set_component_path("FileName3", MSIINSTALLCONTEXT_USERMANAGED,
3938                        "{19E0B999-85F5-4973-A61B-DBE4D66ECB1D}", usersid, FALSE);
3939 
3940     create_test_file("FileName5");
3941     set_component_path("FileName5", MSIINSTALLCONTEXT_MACHINE,
3942                        "{F0CCA976-27A3-4808-9DDD-1A6FD50A0D5A}", NULL, TRUE);
3943 
3944     create_test_file("FileName6");
3945     set_component_path("FileName6", MSIINSTALLCONTEXT_MACHINE,
3946                        "{C0ECD96F-7898-4410-9667-194BD8C1B648}", NULL, TRUE);
3947 
3948     create_test_file("FileName7");
3949     set_component_path("FileName7", MSIINSTALLCONTEXT_MACHINE,
3950                        "{DB20F535-9C26-4127-9C2B-CC45A8B51DA1}", NULL, FALSE);
3951 
3952     /* dir is FALSE, but we're pretending it's a directory */
3953     set_component_path("IDontExist\\", MSIINSTALLCONTEXT_MACHINE,
3954                        "{91B7359B-07F2-4221-AA8D-DE102BB87A5F}", NULL, FALSE);
3955 
3956     create_file_with_version("FileName8.dll", MAKELONG(2, 1), MAKELONG(4, 3));
3957     set_component_path("FileName8.dll", MSIINSTALLCONTEXT_MACHINE,
3958                        "{4A2E1B5B-4034-4177-833B-8CC35F1B3EF1}", NULL, FALSE);
3959 
3960     create_file_with_version("FileName9.dll", MAKELONG(1, 2), MAKELONG(3, 4));
3961     set_component_path("FileName9.dll", MSIINSTALLCONTEXT_MACHINE,
3962                        "{A204DF48-7346-4635-BA2E-66247DBAC9DF}", NULL, FALSE);
3963 
3964     create_file_with_version("FileName10.dll", MAKELONG(2, 1), MAKELONG(4, 3));
3965     set_component_path("FileName10.dll", MSIINSTALLCONTEXT_MACHINE,
3966                        "{EC30CE73-4CF9-4908-BABD-1ED82E1515FD}", NULL, FALSE);
3967 
3968     hdb = create_package_db();
3969     ok(hdb, "Expected a valid database handle\n");
3970 
3971     r = create_appsearch_table(hdb);
3972     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3973 
3974     r = add_appsearch_entry(hdb, "'SIGPROP1', 'NewSignature1'");
3975     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3976 
3977     r = add_appsearch_entry(hdb, "'SIGPROP2', 'NewSignature2'");
3978     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3979 
3980     r = add_appsearch_entry(hdb, "'SIGPROP3', 'NewSignature3'");
3981     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3982 
3983     r = add_appsearch_entry(hdb, "'SIGPROP4', 'NewSignature4'");
3984     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3985 
3986     r = add_appsearch_entry(hdb, "'SIGPROP5', 'NewSignature5'");
3987     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3988 
3989     r = add_appsearch_entry(hdb, "'SIGPROP6', 'NewSignature6'");
3990     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3991 
3992     r = add_appsearch_entry(hdb, "'SIGPROP7', 'NewSignature7'");
3993     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3994 
3995     r = add_appsearch_entry(hdb, "'SIGPROP8', 'NewSignature8'");
3996     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3997 
3998     r = add_appsearch_entry(hdb, "'SIGPROP9', 'NewSignature9'");
3999     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4000 
4001     r = add_appsearch_entry(hdb, "'SIGPROP10', 'NewSignature10'");
4002     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4003 
4004     r = add_appsearch_entry(hdb, "'SIGPROP11', 'NewSignature11'");
4005     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4006 
4007     r = add_appsearch_entry(hdb, "'SIGPROP12', 'NewSignature12'");
4008     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4009 
4010     r = create_complocator_table(hdb);
4011     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4012 
4013     /* published component, machine, file, signature, misdbLocatorTypeFile */
4014     r = add_complocator_entry(hdb, "'NewSignature1', '{A8AE6692-96BA-4198-8399-145D7D1D0D0E}', 1");
4015     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4016 
4017     /* published component, user-unmanaged, file, signature, misdbLocatorTypeFile */
4018     r = add_complocator_entry(hdb, "'NewSignature2', '{1D2CE6F3-E81C-4949-AB81-78D7DAD2AF2E}', 1");
4019     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4020 
4021     /* published component, user-managed, file, signature, misdbLocatorTypeFile */
4022     r = add_complocator_entry(hdb, "'NewSignature3', '{19E0B999-85F5-4973-A61B-DBE4D66ECB1D}', 1");
4023     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4024 
4025     /* published component, machine, file, signature, misdbLocatorTypeDirectory */
4026     r = add_complocator_entry(hdb, "'NewSignature4', '{A8AE6692-96BA-4198-8399-145D7D1D0D0E}', 0");
4027     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4028 
4029     /* published component, machine, dir, signature, misdbLocatorTypeDirectory */
4030     r = add_complocator_entry(hdb, "'NewSignature5', '{F0CCA976-27A3-4808-9DDD-1A6FD50A0D5A}', 0");
4031     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4032 
4033     /* published component, machine, dir, no signature, misdbLocatorTypeDirectory */
4034     r = add_complocator_entry(hdb, "'NewSignature6', '{C0ECD96F-7898-4410-9667-194BD8C1B648}', 0");
4035     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4036 
4037     /* published component, machine, file, no signature, misdbLocatorTypeFile */
4038     r = add_complocator_entry(hdb, "'NewSignature7', '{DB20F535-9C26-4127-9C2B-CC45A8B51DA1}', 1");
4039     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4040 
4041     /* unpublished component, no signature, misdbLocatorTypeDir */
4042     r = add_complocator_entry(hdb, "'NewSignature8', '{FB671D5B-5083-4048-90E0-481C48D8F3A5}', 0");
4043     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4044 
4045     /* published component, no signature, dir does not exist misdbLocatorTypeDir */
4046     r = add_complocator_entry(hdb, "'NewSignature9', '{91B7359B-07F2-4221-AA8D-DE102BB87A5F}', 0");
4047     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4048 
4049     /* published component, signature w/ ver, misdbLocatorTypeFile */
4050     r = add_complocator_entry(hdb, "'NewSignature10', '{4A2E1B5B-4034-4177-833B-8CC35F1B3EF1}', 1");
4051     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4052 
4053     /* published component, signature w/ ver, ver > max, misdbLocatorTypeFile */
4054     r = add_complocator_entry(hdb, "'NewSignature11', '{A204DF48-7346-4635-BA2E-66247DBAC9DF}', 1");
4055     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4056 
4057     /* published component, signature w/ ver, sig->name ignored, misdbLocatorTypeFile */
4058     r = add_complocator_entry(hdb, "'NewSignature12', '{EC30CE73-4CF9-4908-BABD-1ED82E1515FD}', 1");
4059     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4060 
4061     r = create_signature_table(hdb);
4062     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4063 
4064     r = add_signature_entry(hdb, "'NewSignature1', 'FileName1', '', '', '', '', '', '', ''");
4065     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4066 
4067     r = add_signature_entry(hdb, "'NewSignature2', 'FileName2', '', '', '', '', '', '', ''");
4068     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4069 
4070     r = add_signature_entry(hdb, "'NewSignature3', 'FileName3', '', '', '', '', '', '', ''");
4071     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4072 
4073     r = add_signature_entry(hdb, "'NewSignature4', 'FileName4', '', '', '', '', '', '', ''");
4074     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4075 
4076     r = add_signature_entry(hdb, "'NewSignature5', 'FileName5', '', '', '', '', '', '', ''");
4077     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4078 
4079     r = add_signature_entry(hdb, "'NewSignature10', 'FileName8.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4080     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4081 
4082     r = add_signature_entry(hdb, "'NewSignature11', 'FileName9.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4083     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4084 
4085     r = add_signature_entry(hdb, "'NewSignature12', 'ignored', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4086     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4087 
4088     r = package_from_db(hdb, &hpkg);
4089     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
4090     {
4091         skip("Not enough rights to perform tests\n");
4092         goto error;
4093     }
4094     ok(r == ERROR_SUCCESS, "Expected a valid package handle %u\n", r);
4095 
4096     r = MsiSetPropertyA(hpkg, "SIGPROP8", "october");
4097     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4098 
4099     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4100 
4101     r = MsiDoActionA(hpkg, "AppSearch");
4102     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4103 
4104     strcpy(expected, CURR_DIR);
4105     if (is_root(CURR_DIR)) expected[2] = 0;
4106 
4107     size = MAX_PATH;
4108     sprintf(path, "%s\\FileName1", expected);
4109     r = MsiGetPropertyA(hpkg, "SIGPROP1", prop, &size);
4110     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4111     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4112 
4113     size = MAX_PATH;
4114     sprintf(path, "%s\\FileName2", expected);
4115     r = MsiGetPropertyA(hpkg, "SIGPROP2", prop, &size);
4116     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4117     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4118 
4119     size = MAX_PATH;
4120     sprintf(path, "%s\\FileName3", expected);
4121     r = MsiGetPropertyA(hpkg, "SIGPROP3", prop, &size);
4122     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4123     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4124 
4125     size = MAX_PATH;
4126     sprintf(path, "%s\\FileName4", expected);
4127     r = MsiGetPropertyA(hpkg, "SIGPROP4", prop, &size);
4128     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4129     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4130 
4131     size = MAX_PATH;
4132     sprintf(path, "%s\\FileName5", expected);
4133     r = MsiGetPropertyA(hpkg, "SIGPROP5", prop, &size);
4134     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4135     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4136 
4137     size = MAX_PATH;
4138     sprintf(path, "%s\\", expected);
4139     r = MsiGetPropertyA(hpkg, "SIGPROP6", prop, &size);
4140     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4141     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4142 
4143     size = MAX_PATH;
4144     sprintf(path, "%s\\", expected);
4145     r = MsiGetPropertyA(hpkg, "SIGPROP7", prop, &size);
4146     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4147     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4148 
4149     size = MAX_PATH;
4150     r = MsiGetPropertyA(hpkg, "SIGPROP8", prop, &size);
4151     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4152     ok(!lstrcmpA(prop, "october"), "Expected \"october\", got \"%s\"\n", prop);
4153 
4154     size = MAX_PATH;
4155     r = MsiGetPropertyA(hpkg, "SIGPROP9", prop, &size);
4156     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4157     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4158 
4159     size = MAX_PATH;
4160     sprintf(path, "%s\\FileName8.dll", expected);
4161     r = MsiGetPropertyA(hpkg, "SIGPROP10", prop, &size);
4162     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4163     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4164 
4165     size = MAX_PATH;
4166     r = MsiGetPropertyA(hpkg, "SIGPROP11", prop, &size);
4167     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4168     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4169 
4170     size = MAX_PATH;
4171     sprintf(path, "%s\\FileName10.dll", expected);
4172     r = MsiGetPropertyA(hpkg, "SIGPROP12", prop, &size);
4173     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4174     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4175 
4176     delete_component_path("{A8AE6692-96BA-4198-8399-145D7D1D0D0E}",
4177                           MSIINSTALLCONTEXT_MACHINE, NULL);
4178     delete_component_path("{1D2CE6F3-E81C-4949-AB81-78D7DAD2AF2E}",
4179                           MSIINSTALLCONTEXT_USERUNMANAGED, usersid);
4180     delete_component_path("{19E0B999-85F5-4973-A61B-DBE4D66ECB1D}",
4181                           MSIINSTALLCONTEXT_USERMANAGED, usersid);
4182     delete_component_path("{F0CCA976-27A3-4808-9DDD-1A6FD50A0D5A}",
4183                           MSIINSTALLCONTEXT_MACHINE, NULL);
4184     delete_component_path("{C0ECD96F-7898-4410-9667-194BD8C1B648}",
4185                           MSIINSTALLCONTEXT_MACHINE, NULL);
4186     delete_component_path("{DB20F535-9C26-4127-9C2B-CC45A8B51DA1}",
4187                           MSIINSTALLCONTEXT_MACHINE, NULL);
4188     delete_component_path("{91B7359B-07F2-4221-AA8D-DE102BB87A5F}",
4189                           MSIINSTALLCONTEXT_MACHINE, NULL);
4190     delete_component_path("{4A2E1B5B-4034-4177-833B-8CC35F1B3EF1}",
4191                           MSIINSTALLCONTEXT_MACHINE, NULL);
4192     delete_component_path("{A204DF48-7346-4635-BA2E-66247DBAC9DF}",
4193                           MSIINSTALLCONTEXT_MACHINE, NULL);
4194     delete_component_path("{EC30CE73-4CF9-4908-BABD-1ED82E1515FD}",
4195                           MSIINSTALLCONTEXT_MACHINE, NULL);
4196 
4197     MsiCloseHandle(hpkg);
4198 
4199 error:
4200     DeleteFileA("FileName1");
4201     DeleteFileA("FileName2");
4202     DeleteFileA("FileName3");
4203     DeleteFileA("FileName4");
4204     DeleteFileA("FileName5");
4205     DeleteFileA("FileName6");
4206     DeleteFileA("FileName7");
4207     DeleteFileA("FileName8.dll");
4208     DeleteFileA("FileName9.dll");
4209     DeleteFileA("FileName10.dll");
4210     DeleteFileA(msifile);
4211     LocalFree(usersid);
4212 }
4213 
4214 static void test_appsearch_reglocator(void)
4215 {
4216     MSIHANDLE hpkg, hdb;
4217     char path[MAX_PATH], expected[MAX_PATH], prop[MAX_PATH];
4218     DWORD binary[2], size, val;
4219     BOOL space, version, is_64bit = sizeof(void *) > sizeof(int);
4220     HKEY hklm, classes, hkcu, users;
4221     LPSTR pathdata, pathvar, ptr;
4222     LPCSTR str;
4223     LONG res;
4224     UINT r, type = 0;
4225     SYSTEM_INFO si;
4226 
4227     version = TRUE;
4228     if (!create_file_with_version("test.dll", MAKELONG(2, 1), MAKELONG(4, 3)))
4229         version = FALSE;
4230 
4231     DeleteFileA("test.dll");
4232 
4233     res = RegCreateKeyA(HKEY_CLASSES_ROOT, "Software\\Wine", &classes);
4234     if (res == ERROR_ACCESS_DENIED)
4235     {
4236         skip("Not enough rights to perform tests\n");
4237         return;
4238     }
4239     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4240 
4241     res = RegSetValueExA(classes, "Value1", 0, REG_SZ,
4242                          (const BYTE *)"regszdata", 10);
4243     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4244 
4245     res = RegCreateKeyA(HKEY_CURRENT_USER, "Software\\Wine", &hkcu);
4246     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4247 
4248     res = RegSetValueExA(hkcu, "Value1", 0, REG_SZ,
4249                          (const BYTE *)"regszdata", 10);
4250     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4251 
4252     users = 0;
4253     res = RegCreateKeyA(HKEY_USERS, "S-1-5-18\\Software\\Wine", &users);
4254     ok(res == ERROR_SUCCESS ||
4255        broken(res == ERROR_INVALID_PARAMETER),
4256        "Expected ERROR_SUCCESS, got %d\n", res);
4257 
4258     if (res == ERROR_SUCCESS)
4259     {
4260         res = RegSetValueExA(users, "Value1", 0, REG_SZ,
4261                              (const BYTE *)"regszdata", 10);
4262         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4263     }
4264 
4265     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine", &hklm);
4266     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4267 
4268     res = RegSetValueA(hklm, NULL, REG_SZ, "defvalue", 8);
4269     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4270 
4271     res = RegSetValueExA(hklm, "Value1", 0, REG_SZ,
4272                          (const BYTE *)"regszdata", 10);
4273     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4274 
4275     val = 42;
4276     res = RegSetValueExA(hklm, "Value2", 0, REG_DWORD,
4277                          (const BYTE *)&val, sizeof(DWORD));
4278     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4279 
4280     val = -42;
4281     res = RegSetValueExA(hklm, "Value3", 0, REG_DWORD,
4282                          (const BYTE *)&val, sizeof(DWORD));
4283     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4284 
4285     res = RegSetValueExA(hklm, "Value4", 0, REG_EXPAND_SZ,
4286                          (const BYTE *)"%PATH%", 7);
4287     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4288 
4289     res = RegSetValueExA(hklm, "Value5", 0, REG_EXPAND_SZ,
4290                          (const BYTE *)"my%NOVAR%", 10);
4291     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4292 
4293     res = RegSetValueExA(hklm, "Value6", 0, REG_MULTI_SZ,
4294                          (const BYTE *)"one\0two\0", 9);
4295     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4296 
4297     binary[0] = 0x1234abcd;
4298     binary[1] = 0x567890ef;
4299     res = RegSetValueExA(hklm, "Value7", 0, REG_BINARY,
4300                          (const BYTE *)binary, sizeof(binary));
4301     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4302 
4303     res = RegSetValueExA(hklm, "Value8", 0, REG_SZ,
4304                          (const BYTE *)"#regszdata", 11);
4305     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4306 
4307     strcpy(expected, CURR_DIR);
4308     if (is_root(CURR_DIR)) expected[2] = 0;
4309 
4310     create_test_file("FileName1");
4311     sprintf(path, "%s\\FileName1", expected);
4312     res = RegSetValueExA(hklm, "Value9", 0, REG_SZ,
4313                          (const BYTE *)path, lstrlenA(path) + 1);
4314     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4315 
4316     sprintf(path, "%s\\FileName2", expected);
4317     res = RegSetValueExA(hklm, "Value10", 0, REG_SZ,
4318                          (const BYTE *)path, lstrlenA(path) + 1);
4319     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4320 
4321     lstrcpyA(path, expected);
4322     res = RegSetValueExA(hklm, "Value11", 0, REG_SZ,
4323                          (const BYTE *)path, lstrlenA(path) + 1);
4324     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4325 
4326     res = RegSetValueExA(hklm, "Value12", 0, REG_SZ,
4327                          (const BYTE *)"", 1);
4328     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4329 
4330     create_file_with_version("FileName3.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4331     sprintf(path, "%s\\FileName3.dll", expected);
4332     res = RegSetValueExA(hklm, "Value13", 0, REG_SZ,
4333                          (const BYTE *)path, lstrlenA(path) + 1);
4334     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4335 
4336     create_file_with_version("FileName4.dll", MAKELONG(1, 2), MAKELONG(3, 4));
4337     sprintf(path, "%s\\FileName4.dll", expected);
4338     res = RegSetValueExA(hklm, "Value14", 0, REG_SZ,
4339                          (const BYTE *)path, lstrlenA(path) + 1);
4340     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4341 
4342     create_file_with_version("FileName5.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4343     sprintf(path, "%s\\FileName5.dll", expected);
4344     res = RegSetValueExA(hklm, "Value15", 0, REG_SZ,
4345                          (const BYTE *)path, lstrlenA(path) + 1);
4346     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4347 
4348     sprintf(path, "\"%s\\FileName1\" -option", expected);
4349     res = RegSetValueExA(hklm, "value16", 0, REG_SZ,
4350                          (const BYTE *)path, lstrlenA(path) + 1);
4351     ok( res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", res);
4352 
4353     space = strchr(expected, ' ') != NULL;
4354     sprintf(path, "%s\\FileName1 -option", expected);
4355     res = RegSetValueExA(hklm, "value17", 0, REG_SZ,
4356                          (const BYTE *)path, lstrlenA(path) + 1);
4357     ok( res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", res);
4358 
4359     hdb = create_package_db();
4360     ok(hdb, "Expected a valid database handle\n");
4361 
4362     r = create_appsearch_table(hdb);
4363     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4364 
4365     r = add_appsearch_entry(hdb, "'SIGPROP1', 'NewSignature1'");
4366     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4367 
4368     r = add_appsearch_entry(hdb, "'SIGPROP2', 'NewSignature2'");
4369     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4370 
4371     r = add_appsearch_entry(hdb, "'SIGPROP3', 'NewSignature3'");
4372     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4373 
4374     r = add_appsearch_entry(hdb, "'SIGPROP4', 'NewSignature4'");
4375     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4376 
4377     r = add_appsearch_entry(hdb, "'SIGPROP5', 'NewSignature5'");
4378     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4379 
4380     r = add_appsearch_entry(hdb, "'SIGPROP6', 'NewSignature6'");
4381     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4382 
4383     r = add_appsearch_entry(hdb, "'SIGPROP7', 'NewSignature7'");
4384     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4385 
4386     r = add_appsearch_entry(hdb, "'SIGPROP8', 'NewSignature8'");
4387     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4388 
4389     r = add_appsearch_entry(hdb, "'SIGPROP9', 'NewSignature9'");
4390     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4391 
4392     r = add_appsearch_entry(hdb, "'SIGPROP10', 'NewSignature10'");
4393     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4394 
4395     r = add_appsearch_entry(hdb, "'SIGPROP11', 'NewSignature11'");
4396     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4397 
4398     r = add_appsearch_entry(hdb, "'SIGPROP12', 'NewSignature12'");
4399     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4400 
4401     r = add_appsearch_entry(hdb, "'SIGPROP13', 'NewSignature13'");
4402     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4403 
4404     r = add_appsearch_entry(hdb, "'SIGPROP14', 'NewSignature14'");
4405     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4406 
4407     r = add_appsearch_entry(hdb, "'SIGPROP15', 'NewSignature15'");
4408     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4409 
4410     r = add_appsearch_entry(hdb, "'SIGPROP16', 'NewSignature16'");
4411     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4412 
4413     r = add_appsearch_entry(hdb, "'SIGPROP17', 'NewSignature17'");
4414     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4415 
4416     r = add_appsearch_entry(hdb, "'SIGPROP18', 'NewSignature18'");
4417     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4418 
4419     r = add_appsearch_entry(hdb, "'SIGPROP19', 'NewSignature19'");
4420     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4421 
4422     r = add_appsearch_entry(hdb, "'SIGPROP20', 'NewSignature20'");
4423     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4424 
4425     r = add_appsearch_entry(hdb, "'SIGPROP21', 'NewSignature21'");
4426     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4427 
4428     r = add_appsearch_entry(hdb, "'SIGPROP22', 'NewSignature22'");
4429     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4430 
4431     r = add_appsearch_entry(hdb, "'SIGPROP23', 'NewSignature23'");
4432     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4433 
4434     r = add_appsearch_entry(hdb, "'SIGPROP24', 'NewSignature24'");
4435     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4436 
4437     r = add_appsearch_entry(hdb, "'SIGPROP25', 'NewSignature25'");
4438     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4439 
4440     r = add_appsearch_entry(hdb, "'SIGPROP26', 'NewSignature26'");
4441     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4442 
4443     r = add_appsearch_entry(hdb, "'SIGPROP27', 'NewSignature27'");
4444     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4445 
4446     r = add_appsearch_entry(hdb, "'SIGPROP28', 'NewSignature28'");
4447     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4448 
4449     r = add_appsearch_entry(hdb, "'SIGPROP29', 'NewSignature29'");
4450     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4451 
4452     r = add_appsearch_entry(hdb, "'SIGPROP30', 'NewSignature30'");
4453     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4454 
4455     r = create_reglocator_table(hdb);
4456     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4457 
4458     type = msidbLocatorTypeRawValue;
4459     if (is_64bit)
4460         type |= msidbLocatorType64bit;
4461 
4462     /* HKLM, msidbLocatorTypeRawValue, REG_SZ */
4463     r = add_reglocator_entry(hdb, "NewSignature1", 2, "Software\\Wine", "Value1", type);
4464     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4465 
4466     /* HKLM, msidbLocatorTypeRawValue, positive DWORD */
4467     r = add_reglocator_entry(hdb, "NewSignature2", 2, "Software\\Wine", "Value2", type);
4468     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4469 
4470     /* HKLM, msidbLocatorTypeRawValue, negative DWORD */
4471     r = add_reglocator_entry(hdb, "NewSignature3", 2, "Software\\Wine", "Value3", type);
4472     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4473 
4474     /* HKLM, msidbLocatorTypeRawValue, REG_EXPAND_SZ */
4475     r = add_reglocator_entry(hdb, "NewSignature4", 2, "Software\\Wine", "Value4", type);
4476     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4477 
4478     /* HKLM, msidbLocatorTypeRawValue, REG_EXPAND_SZ */
4479     r = add_reglocator_entry(hdb, "NewSignature5", 2, "Software\\Wine", "Value5", type);
4480     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4481 
4482     /* HKLM, msidbLocatorTypeRawValue, REG_MULTI_SZ */
4483     r = add_reglocator_entry(hdb, "NewSignature6", 2, "Software\\Wine", "Value6", type);
4484     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4485 
4486     /* HKLM, msidbLocatorTypeRawValue, REG_BINARY */
4487     r = add_reglocator_entry(hdb, "NewSignature7", 2, "Software\\Wine", "Value7", type);
4488     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4489 
4490     /* HKLM, msidbLocatorTypeRawValue, REG_SZ first char is # */
4491     r = add_reglocator_entry(hdb, "NewSignature8", 2, "Software\\Wine", "Value8", type);
4492     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4493 
4494     type = msidbLocatorTypeFileName;
4495     if (is_64bit)
4496         type |= msidbLocatorType64bit;
4497 
4498     /* HKLM, msidbLocatorTypeFileName, signature, file exists */
4499     r = add_reglocator_entry(hdb, "NewSignature9", 2, "Software\\Wine", "Value9", type);
4500     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4501 
4502     /* HKLM, msidbLocatorTypeFileName, signature, file does not exist */
4503     r = add_reglocator_entry(hdb, "NewSignature10", 2, "Software\\Wine", "Value10", type);
4504     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4505 
4506     /* HKLM, msidbLocatorTypeFileName, no signature */
4507     r = add_reglocator_entry(hdb, "NewSignature11", 2, "Software\\Wine", "Value9", type);
4508     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4509 
4510     type = msidbLocatorTypeDirectory;
4511     if (is_64bit)
4512         type |= msidbLocatorType64bit;
4513 
4514     /* HKLM, msidbLocatorTypeDirectory, no signature, file exists */
4515     r = add_reglocator_entry(hdb, "NewSignature12", 2, "Software\\Wine", "Value9", type);
4516     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4517 
4518     /* HKLM, msidbLocatorTypeDirectory, no signature, directory exists */
4519     r = add_reglocator_entry(hdb, "NewSignature13", 2, "Software\\Wine", "Value11", type);
4520     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4521 
4522     /* HKLM, msidbLocatorTypeDirectory, signature, file exists */
4523     r = add_reglocator_entry(hdb, "NewSignature14", 2, "Software\\Wine", "Value9", type);
4524     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4525 
4526     type = msidbLocatorTypeRawValue;
4527     if (is_64bit)
4528         type |= msidbLocatorType64bit;
4529 
4530     /* HKCR, msidbLocatorTypeRawValue, REG_SZ */
4531     r = add_reglocator_entry(hdb, "NewSignature15", 0, "Software\\Wine", "Value1", type);
4532     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4533 
4534     /* HKCU, msidbLocatorTypeRawValue, REG_SZ */
4535     r = add_reglocator_entry(hdb, "NewSignature16", 1, "Software\\Wine", "Value1", type);
4536     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4537 
4538     /* HKU, msidbLocatorTypeRawValue, REG_SZ */
4539     r = add_reglocator_entry(hdb, "NewSignature17", 3, "S-1-5-18\\Software\\Wine", "Value1", type);
4540     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4541 
4542     /* HKLM, msidbLocatorTypeRawValue, REG_SZ, NULL Name */
4543     r = add_reglocator_entry(hdb, "NewSignature18", 2, "Software\\Wine", "", type);
4544     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4545 
4546     /* HKLM, msidbLocatorTypeRawValue, REG_SZ, key does not exist */
4547     r = add_reglocator_entry(hdb, "NewSignature19", 2, "Software\\IDontExist", "", type);
4548     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4549 
4550     /* HKLM, msidbLocatorTypeRawValue, REG_SZ, value is empty */
4551     r = add_reglocator_entry(hdb, "NewSignature20", 2, "Software\\Wine", "Value12", type);
4552     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4553 
4554     type = msidbLocatorTypeFileName;
4555     if (is_64bit)
4556         type |= msidbLocatorType64bit;
4557 
4558     /* HKLM, msidbLocatorTypeFileName, signature, file exists w/ version */
4559     r = add_reglocator_entry(hdb, "NewSignature21", 2, "Software\\Wine", "Value13", type);
4560     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4561 
4562     /* HKLM, msidbLocatorTypeFileName, file exists w/ version, version > max */
4563     r = add_reglocator_entry(hdb, "NewSignature22", 2, "Software\\Wine", "Value14", type);
4564     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4565 
4566     /* HKLM, msidbLocatorTypeFileName, file exists w/ version, sig->name ignored */
4567     r = add_reglocator_entry(hdb, "NewSignature23", 2, "Software\\Wine", "Value15", type);
4568     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4569 
4570     /* HKLM, msidbLocatorTypeFileName, no signature, directory exists */
4571     r = add_reglocator_entry(hdb, "NewSignature24", 2, "Software\\Wine", "Value11", type);
4572     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4573 
4574     /* HKLM, msidbLocatorTypeFileName, no signature, file does not exist */
4575     r = add_reglocator_entry(hdb, "NewSignature25", 2, "Software\\Wine", "Value10", type);
4576     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4577 
4578     type = msidbLocatorTypeDirectory;
4579     if (is_64bit)
4580         type |= msidbLocatorType64bit;
4581 
4582     /* HKLM, msidbLocatorTypeDirectory, signature, directory exists */
4583     r = add_reglocator_entry(hdb, "NewSignature26", 2, "Software\\Wine", "Value11", type);
4584     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4585 
4586     /* HKLM, msidbLocatorTypeDirectory, signature, file does not exist */
4587     r = add_reglocator_entry(hdb, "NewSignature27", 2, "Software\\Wine", "Value10", type);
4588     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4589 
4590     /* HKLM, msidbLocatorTypeDirectory, no signature, file does not exist */
4591     r = add_reglocator_entry(hdb, "NewSignature28", 2, "Software\\Wine", "Value10", type);
4592     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4593 
4594     type = msidbLocatorTypeFileName;
4595     if (is_64bit)
4596         type |= msidbLocatorType64bit;
4597 
4598     /* HKLM, msidbLocatorTypeFile, file exists, in quotes */
4599     r = add_reglocator_entry(hdb, "NewSignature29", 2, "Software\\Wine", "Value16", type);
4600     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4601 
4602     /* HKLM, msidbLocatorTypeFile, file exists, no quotes */
4603     r = add_reglocator_entry(hdb, "NewSignature30", 2, "Software\\Wine", "Value17", type);
4604     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4605 
4606     r = create_signature_table(hdb);
4607     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4608 
4609     str = "'NewSignature9', 'FileName1', '', '', '', '', '', '', ''";
4610     r = add_signature_entry(hdb, str);
4611     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4612 
4613     str = "'NewSignature10', 'FileName2', '', '', '', '', '', '', ''";
4614     r = add_signature_entry(hdb, str);
4615     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4616 
4617     str = "'NewSignature14', 'FileName1', '', '', '', '', '', '', ''";
4618     r = add_signature_entry(hdb, str);
4619     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4620 
4621     str = "'NewSignature21', 'FileName3.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''";
4622     r = add_signature_entry(hdb, str);
4623     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4624 
4625     str = "'NewSignature22', 'FileName4.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''";
4626     r = add_signature_entry(hdb, str);
4627     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4628 
4629     str = "'NewSignature23', 'ignored', '1.1.1.1', '2.1.1.1', '', '', '', '', ''";
4630     r = add_signature_entry(hdb, str);
4631     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4632 
4633     if (!is_root(CURR_DIR))
4634     {
4635         ptr = strrchr(expected, '\\') + 1;
4636         sprintf(path, "'NewSignature26', '%s', '', '', '', '', '', '', ''", ptr);
4637         r = add_signature_entry(hdb, path);
4638         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4639     }
4640     str = "'NewSignature27', 'FileName2', '', '', '', '', '', '', ''";
4641     r = add_signature_entry(hdb, str);
4642     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4643 
4644     str = "'NewSignature29', 'FileName1', '', '', '', '', '', '', ''";
4645     r = add_signature_entry(hdb, str);
4646     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4647 
4648     str = "'NewSignature30', 'FileName1', '', '', '', '', '', '', ''";
4649     r = add_signature_entry(hdb, str);
4650     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4651 
4652     r = package_from_db(hdb, &hpkg);
4653     ok(r == ERROR_SUCCESS, "Expected a valid package handle %u\n", r);
4654 
4655     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4656 
4657     r = MsiDoActionA(hpkg, "AppSearch");
4658     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4659 
4660     size = MAX_PATH;
4661     r = MsiGetPropertyA(hpkg, "SIGPROP1", prop, &size);
4662     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4663     ok(!lstrcmpA(prop, "regszdata"),
4664        "Expected \"regszdata\", got \"%s\"\n", prop);
4665 
4666     size = MAX_PATH;
4667     r = MsiGetPropertyA(hpkg, "SIGPROP2", prop, &size);
4668     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4669     ok(!lstrcmpA(prop, "#42"), "Expected \"#42\", got \"%s\"\n", prop);
4670 
4671     size = MAX_PATH;
4672     r = MsiGetPropertyA(hpkg, "SIGPROP3", prop, &size);
4673     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4674     ok(!lstrcmpA(prop, "#-42"), "Expected \"#-42\", got \"%s\"\n", prop);
4675 
4676     memset(&si, 0, sizeof(si));
4677     if (pGetNativeSystemInfo) pGetNativeSystemInfo(&si);
4678 
4679     if (S(U(si)).wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
4680     {
4681         size = ExpandEnvironmentStringsA("%PATH%", NULL, 0);
4682         pathvar = HeapAlloc(GetProcessHeap(), 0, size);
4683         ExpandEnvironmentStringsA("%PATH%", pathvar, size);
4684 
4685         size = 0;
4686         r = MsiGetPropertyA(hpkg, "SIGPROP4", NULL, &size);
4687         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4688 
4689         pathdata = HeapAlloc(GetProcessHeap(), 0, ++size);
4690         r = MsiGetPropertyA(hpkg, "SIGPROP4", pathdata, &size);
4691         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4692         ok(!lstrcmpA(pathdata, pathvar),
4693             "Expected \"%s\", got \"%s\"\n", pathvar, pathdata);
4694 
4695         HeapFree(GetProcessHeap(), 0, pathvar);
4696         HeapFree(GetProcessHeap(), 0, pathdata);
4697     }
4698 
4699     size = MAX_PATH;
4700     r = MsiGetPropertyA(hpkg, "SIGPROP5", prop, &size);
4701     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4702     ok(!lstrcmpA(prop,
4703        "my%NOVAR%"), "Expected \"my%%NOVAR%%\", got \"%s\"\n", prop);
4704 
4705     size = MAX_PATH;
4706     r = MsiGetPropertyA(hpkg, "SIGPROP6", prop, &size);
4707     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4708     todo_wine
4709     {
4710         ok(!memcmp(prop, "\0one\0two\0\0", 10),
4711            "Expected \"\\0one\\0two\\0\\0\"\n");
4712     }
4713 
4714     size = MAX_PATH;
4715     lstrcpyA(path, "#xCDAB3412EF907856");
4716     r = MsiGetPropertyA(hpkg, "SIGPROP7", prop, &size);
4717     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4718     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4719 
4720     size = MAX_PATH;
4721     r = MsiGetPropertyA(hpkg, "SIGPROP8", 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     sprintf(path, "%s\\FileName1", expected);
4728     r = MsiGetPropertyA(hpkg, "SIGPROP9", prop, &size);
4729     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4730     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4731 
4732     size = MAX_PATH;
4733     r = MsiGetPropertyA(hpkg, "SIGPROP10", prop, &size);
4734     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4735     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4736 
4737     size = MAX_PATH;
4738     sprintf(path, "%s\\", expected);
4739     r = MsiGetPropertyA(hpkg, "SIGPROP11", prop, &size);
4740     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4741     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4742 
4743     size = MAX_PATH;
4744     r = MsiGetPropertyA(hpkg, "SIGPROP12", prop, &size);
4745     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4746     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4747 
4748     size = MAX_PATH;
4749     sprintf(path, "%s\\", expected);
4750     r = MsiGetPropertyA(hpkg, "SIGPROP13", prop, &size);
4751     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4752     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4753 
4754     size = MAX_PATH;
4755     r = MsiGetPropertyA(hpkg, "SIGPROP14", prop, &size);
4756     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4757     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4758 
4759     size = MAX_PATH;
4760     r = MsiGetPropertyA(hpkg, "SIGPROP15", prop, &size);
4761     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4762     ok(!lstrcmpA(prop, "regszdata"),
4763        "Expected \"regszdata\", got \"%s\"\n", prop);
4764 
4765     size = MAX_PATH;
4766     r = MsiGetPropertyA(hpkg, "SIGPROP16", prop, &size);
4767     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4768     ok(!lstrcmpA(prop, "regszdata"),
4769        "Expected \"regszdata\", got \"%s\"\n", prop);
4770 
4771     if (users)
4772     {
4773         size = MAX_PATH;
4774         r = MsiGetPropertyA(hpkg, "SIGPROP17", prop, &size);
4775         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4776         ok(!lstrcmpA(prop, "regszdata"),
4777            "Expected \"regszdata\", got \"%s\"\n", prop);
4778     }
4779 
4780     size = MAX_PATH;
4781     r = MsiGetPropertyA(hpkg, "SIGPROP18", prop, &size);
4782     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4783     ok(!lstrcmpA(prop, "defvalue"),
4784        "Expected \"defvalue\", got \"%s\"\n", prop);
4785 
4786     size = MAX_PATH;
4787     r = MsiGetPropertyA(hpkg, "SIGPROP19", prop, &size);
4788     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4789     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4790 
4791     size = MAX_PATH;
4792     r = MsiGetPropertyA(hpkg, "SIGPROP20", prop, &size);
4793     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4794     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4795 
4796     if (version)
4797     {
4798         size = MAX_PATH;
4799         sprintf(path, "%s\\FileName3.dll", expected);
4800         r = MsiGetPropertyA(hpkg, "SIGPROP21", prop, &size);
4801         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4802         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4803 
4804         size = MAX_PATH;
4805         r = MsiGetPropertyA(hpkg, "SIGPROP22", prop, &size);
4806         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4807         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4808 
4809         size = MAX_PATH;
4810         sprintf(path, "%s\\FileName5.dll", expected);
4811         r = MsiGetPropertyA(hpkg, "SIGPROP23", prop, &size);
4812         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4813         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4814     }
4815 
4816     if (!is_root(CURR_DIR))
4817     {
4818         size = MAX_PATH;
4819         lstrcpyA(path, expected);
4820         ptr = strrchr(path, '\\') + 1;
4821         *ptr = '\0';
4822         r = MsiGetPropertyA(hpkg, "SIGPROP24", prop, &size);
4823         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4824         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4825     }
4826     size = MAX_PATH;
4827     sprintf(path, "%s\\", expected);
4828     r = MsiGetPropertyA(hpkg, "SIGPROP25", prop, &size);
4829     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4830     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4831 
4832     size = MAX_PATH;
4833     r = MsiGetPropertyA(hpkg, "SIGPROP26", prop, &size);
4834     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4835     if (is_root(CURR_DIR))
4836         ok(!lstrcmpA(prop, CURR_DIR), "Expected \"%s\", got \"%s\"\n", CURR_DIR, prop);
4837     else
4838         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4839 
4840     size = MAX_PATH;
4841     r = MsiGetPropertyA(hpkg, "SIGPROP27", prop, &size);
4842     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4843     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4844 
4845     size = MAX_PATH;
4846     r = MsiGetPropertyA(hpkg, "SIGPROP28", prop, &size);
4847     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4848     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4849 
4850     size = MAX_PATH;
4851     sprintf(path, "%s\\FileName1", expected);
4852     r = MsiGetPropertyA(hpkg, "SIGPROP29", prop, &size);
4853     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4854     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4855 
4856     size = MAX_PATH;
4857     sprintf(path, "%s\\FileName1", expected);
4858     r = MsiGetPropertyA(hpkg, "SIGPROP30", prop, &size);
4859     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4860     if (space)
4861         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4862     else
4863         todo_wine ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4864 
4865     RegSetValueA(hklm, NULL, REG_SZ, "", 0);
4866     RegDeleteValueA(hklm, "Value1");
4867     RegDeleteValueA(hklm, "Value2");
4868     RegDeleteValueA(hklm, "Value3");
4869     RegDeleteValueA(hklm, "Value4");
4870     RegDeleteValueA(hklm, "Value5");
4871     RegDeleteValueA(hklm, "Value6");
4872     RegDeleteValueA(hklm, "Value7");
4873     RegDeleteValueA(hklm, "Value8");
4874     RegDeleteValueA(hklm, "Value9");
4875     RegDeleteValueA(hklm, "Value10");
4876     RegDeleteValueA(hklm, "Value11");
4877     RegDeleteValueA(hklm, "Value12");
4878     RegDeleteValueA(hklm, "Value13");
4879     RegDeleteValueA(hklm, "Value14");
4880     RegDeleteValueA(hklm, "Value15");
4881     RegDeleteValueA(hklm, "Value16");
4882     RegDeleteValueA(hklm, "Value17");
4883     RegDeleteKeyA(hklm, "");
4884     RegCloseKey(hklm);
4885 
4886     RegDeleteValueA(classes, "Value1");
4887     RegDeleteKeyA(classes, "");
4888     RegCloseKey(classes);
4889 
4890     RegDeleteValueA(hkcu, "Value1");
4891     RegDeleteKeyA(hkcu, "");
4892     RegCloseKey(hkcu);
4893 
4894     RegDeleteValueA(users, "Value1");
4895     RegDeleteKeyA(users, "");
4896     RegCloseKey(users);
4897 
4898     DeleteFileA("FileName1");
4899     DeleteFileA("FileName3.dll");
4900     DeleteFileA("FileName4.dll");
4901     DeleteFileA("FileName5.dll");
4902     MsiCloseHandle(hpkg);
4903     DeleteFileA(msifile);
4904 }
4905 
4906 static void delete_win_ini(LPCSTR file)
4907 {
4908     CHAR path[MAX_PATH];
4909 
4910     GetWindowsDirectoryA(path, MAX_PATH);
4911     lstrcatA(path, "\\");
4912     lstrcatA(path, file);
4913 
4914     DeleteFileA(path);
4915 }
4916 
4917 static void test_appsearch_inilocator(void)
4918 {
4919     MSIHANDLE hpkg, hdb;
4920     char path[MAX_PATH], expected[MAX_PATH], prop[MAX_PATH];
4921     BOOL version;
4922     LPCSTR str;
4923     LPSTR ptr;
4924     DWORD size;
4925     UINT r;
4926 
4927     version = TRUE;
4928     if (!create_file_with_version("test.dll", MAKELONG(2, 1), MAKELONG(4, 3)))
4929         version = FALSE;
4930 
4931     DeleteFileA("test.dll");
4932 
4933     WritePrivateProfileStringA("Section", "Key", "keydata,field2", "IniFile.ini");
4934 
4935     strcpy(expected, CURR_DIR);
4936     if (is_root(CURR_DIR)) expected[2] = 0;
4937 
4938     create_test_file("FileName1");
4939     sprintf(path, "%s\\FileName1", expected);
4940     WritePrivateProfileStringA("Section", "Key2", path, "IniFile.ini");
4941 
4942     WritePrivateProfileStringA("Section", "Key3", expected, "IniFile.ini");
4943 
4944     sprintf(path, "%s\\IDontExist", expected);
4945     WritePrivateProfileStringA("Section", "Key4", path, "IniFile.ini");
4946 
4947     create_file_with_version("FileName2.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4948     sprintf(path, "%s\\FileName2.dll", expected);
4949     WritePrivateProfileStringA("Section", "Key5", path, "IniFile.ini");
4950 
4951     create_file_with_version("FileName3.dll", MAKELONG(1, 2), MAKELONG(3, 4));
4952     sprintf(path, "%s\\FileName3.dll", expected);
4953     WritePrivateProfileStringA("Section", "Key6", path, "IniFile.ini");
4954 
4955     create_file_with_version("FileName4.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4956     sprintf(path, "%s\\FileName4.dll", expected);
4957     WritePrivateProfileStringA("Section", "Key7", path, "IniFile.ini");
4958 
4959     hdb = create_package_db();
4960     ok(hdb, "Expected a valid database handle\n");
4961 
4962     r = create_appsearch_table(hdb);
4963     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4964 
4965     r = add_appsearch_entry(hdb, "'SIGPROP1', 'NewSignature1'");
4966     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4967 
4968     r = add_appsearch_entry(hdb, "'SIGPROP2', 'NewSignature2'");
4969     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4970 
4971     r = add_appsearch_entry(hdb, "'SIGPROP3', 'NewSignature3'");
4972     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4973 
4974     r = add_appsearch_entry(hdb, "'SIGPROP4', 'NewSignature4'");
4975     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4976 
4977     r = add_appsearch_entry(hdb, "'SIGPROP5', 'NewSignature5'");
4978     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4979 
4980     r = add_appsearch_entry(hdb, "'SIGPROP6', 'NewSignature6'");
4981     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4982 
4983     r = add_appsearch_entry(hdb, "'SIGPROP7', 'NewSignature7'");
4984     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4985 
4986     r = add_appsearch_entry(hdb, "'SIGPROP8', 'NewSignature8'");
4987     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4988 
4989     r = add_appsearch_entry(hdb, "'SIGPROP9', 'NewSignature9'");
4990     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4991 
4992     r = add_appsearch_entry(hdb, "'SIGPROP10', 'NewSignature10'");
4993     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4994 
4995     r = add_appsearch_entry(hdb, "'SIGPROP11', 'NewSignature11'");
4996     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4997 
4998     r = add_appsearch_entry(hdb, "'SIGPROP12', 'NewSignature12'");
4999     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5000 
5001     r = create_inilocator_table(hdb);
5002     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5003 
5004     /* msidbLocatorTypeRawValue, field 1 */
5005     str = "'NewSignature1', 'IniFile.ini', 'Section', 'Key', 1, 2";
5006     r = add_inilocator_entry(hdb, str);
5007     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5008 
5009     /* msidbLocatorTypeRawValue, field 2 */
5010     str = "'NewSignature2', 'IniFile.ini', 'Section', 'Key', 2, 2";
5011     r = add_inilocator_entry(hdb, str);
5012     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5013 
5014     /* msidbLocatorTypeRawValue, entire field */
5015     str = "'NewSignature3', 'IniFile.ini', 'Section', 'Key', 0, 2";
5016     r = add_inilocator_entry(hdb, str);
5017     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5018 
5019     /* msidbLocatorTypeFile */
5020     str = "'NewSignature4', 'IniFile.ini', 'Section', 'Key2', 1, 1";
5021     r = add_inilocator_entry(hdb, str);
5022     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5023 
5024     /* msidbLocatorTypeDirectory, file */
5025     str = "'NewSignature5', 'IniFile.ini', 'Section', 'Key2', 1, 0";
5026     r = add_inilocator_entry(hdb, str);
5027     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5028 
5029     /* msidbLocatorTypeDirectory, directory */
5030     str = "'NewSignature6', 'IniFile.ini', 'Section', 'Key3', 1, 0";
5031     r = add_inilocator_entry(hdb, str);
5032     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5033 
5034     /* msidbLocatorTypeFile, file, no signature */
5035     str = "'NewSignature7', 'IniFile.ini', 'Section', 'Key2', 1, 1";
5036     r = add_inilocator_entry(hdb, str);
5037     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5038 
5039     /* msidbLocatorTypeFile, dir, no signature */
5040     str = "'NewSignature8', 'IniFile.ini', 'Section', 'Key3', 1, 1";
5041     r = add_inilocator_entry(hdb, str);
5042     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5043 
5044     /* msidbLocatorTypeFile, file does not exist */
5045     str = "'NewSignature9', 'IniFile.ini', 'Section', 'Key4', 1, 1";
5046     r = add_inilocator_entry(hdb, str);
5047     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5048 
5049     /* msidbLocatorTypeFile, signature with version */
5050     str = "'NewSignature10', 'IniFile.ini', 'Section', 'Key5', 1, 1";
5051     r = add_inilocator_entry(hdb, str);
5052     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5053 
5054     /* msidbLocatorTypeFile, signature with version, ver > max */
5055     str = "'NewSignature11', 'IniFile.ini', 'Section', 'Key6', 1, 1";
5056     r = add_inilocator_entry(hdb, str);
5057     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5058 
5059     /* msidbLocatorTypeFile, signature with version, sig->name ignored */
5060     str = "'NewSignature12', 'IniFile.ini', 'Section', 'Key7', 1, 1";
5061     r = add_inilocator_entry(hdb, str);
5062     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5063 
5064     r = create_signature_table(hdb);
5065     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5066 
5067     r = add_signature_entry(hdb, "'NewSignature4', 'FileName1', '', '', '', '', '', '', ''");
5068     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5069 
5070     r = add_signature_entry(hdb, "'NewSignature9', 'IDontExist', '', '', '', '', '', '', ''");
5071     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5072 
5073     r = add_signature_entry(hdb, "'NewSignature10', 'FileName2.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
5074     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5075 
5076     r = add_signature_entry(hdb, "'NewSignature11', 'FileName3.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
5077     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5078 
5079     r = add_signature_entry(hdb, "'NewSignature12', 'ignored', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
5080     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5081 
5082     r = package_from_db(hdb, &hpkg);
5083     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5084     {
5085         skip("Not enough rights to perform tests\n");
5086         goto error;
5087     }
5088     ok(r == ERROR_SUCCESS, "Expected a valid package handle %u\n", r);
5089 
5090     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5091 
5092     r = MsiDoActionA(hpkg, "AppSearch");
5093     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5094 
5095     size = MAX_PATH;
5096     r = MsiGetPropertyA(hpkg, "SIGPROP1", prop, &size);
5097     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5098     ok(!lstrcmpA(prop, "keydata"), "Expected \"keydata\", got \"%s\"\n", prop);
5099 
5100     size = MAX_PATH;
5101     r = MsiGetPropertyA(hpkg, "SIGPROP2", prop, &size);
5102     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5103     ok(!lstrcmpA(prop, "field2"), "Expected \"field2\", got \"%s\"\n", prop);
5104 
5105     size = MAX_PATH;
5106     r = MsiGetPropertyA(hpkg, "SIGPROP3", prop, &size);
5107     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5108     ok(!lstrcmpA(prop, "keydata,field2"),
5109        "Expected \"keydata,field2\", got \"%s\"\n", prop);
5110 
5111     size = MAX_PATH;
5112     sprintf(path, "%s\\FileName1", expected);
5113     r = MsiGetPropertyA(hpkg, "SIGPROP4", prop, &size);
5114     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5115     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5116 
5117     size = MAX_PATH;
5118     r = MsiGetPropertyA(hpkg, "SIGPROP5", prop, &size);
5119     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5120     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5121 
5122     size = MAX_PATH;
5123     sprintf(path, "%s\\", expected);
5124     r = MsiGetPropertyA(hpkg, "SIGPROP6", prop, &size);
5125     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5126     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5127 
5128     size = MAX_PATH;
5129     sprintf(path, "%s\\", expected);
5130     r = MsiGetPropertyA(hpkg, "SIGPROP7", prop, &size);
5131     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5132     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5133 
5134     if (!is_root(CURR_DIR))
5135     {
5136         size = MAX_PATH;
5137         lstrcpyA(path, expected);
5138         ptr = strrchr(path, '\\');
5139         *(ptr + 1) = 0;
5140         r = MsiGetPropertyA(hpkg, "SIGPROP8", prop, &size);
5141         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5142         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5143     }
5144     size = MAX_PATH;
5145     r = MsiGetPropertyA(hpkg, "SIGPROP9", prop, &size);
5146     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5147     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5148 
5149     if (version)
5150     {
5151         size = MAX_PATH;
5152         sprintf(path, "%s\\FileName2.dll", expected);
5153         r = MsiGetPropertyA(hpkg, "SIGPROP10", prop, &size);
5154         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5155         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5156 
5157         size = MAX_PATH;
5158         r = MsiGetPropertyA(hpkg, "SIGPROP11", prop, &size);
5159         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5160         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5161 
5162         size = MAX_PATH;
5163         sprintf(path, "%s\\FileName4.dll", expected);
5164         r = MsiGetPropertyA(hpkg, "SIGPROP12", prop, &size);
5165         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5166         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5167     }
5168 
5169     MsiCloseHandle(hpkg);
5170 
5171 error:
5172     delete_win_ini("IniFile.ini");
5173     DeleteFileA("FileName1");
5174     DeleteFileA("FileName2.dll");
5175     DeleteFileA("FileName3.dll");
5176     DeleteFileA("FileName4.dll");
5177     DeleteFileA(msifile);
5178 }
5179 
5180 /*
5181  * MSI AppSearch action on DrLocator table always returns absolute paths.
5182  * If a relative path was set, it returns the first absolute path that
5183  * matches or an empty string if it didn't find anything.
5184  * This helper function replicates this behaviour.
5185  */
5186 static void search_absolute_directory(LPSTR absolute, LPCSTR relative)
5187 {
5188     int i, size;
5189     DWORD attr, drives;
5190 
5191     size = lstrlenA(relative);
5192     drives = GetLogicalDrives();
5193     lstrcpyA(absolute, "A:\\");
5194     for (i = 0; i < 26; absolute[0] = '\0', i++)
5195     {
5196         if (!(drives & (1 << i)))
5197             continue;
5198 
5199         absolute[0] = 'A' + i;
5200         if (GetDriveTypeA(absolute) != DRIVE_FIXED)
5201             continue;
5202 
5203         lstrcpynA(absolute + 3, relative, size + 1);
5204         attr = GetFileAttributesA(absolute);
5205         if (attr != INVALID_FILE_ATTRIBUTES &&
5206             (attr & FILE_ATTRIBUTE_DIRECTORY))
5207         {
5208             if (absolute[3 + size - 1] != '\\')
5209                 lstrcatA(absolute, "\\");
5210             break;
5211         }
5212         absolute[3] = '\0';
5213     }
5214 }
5215 
5216 static void test_appsearch_drlocator(void)
5217 {
5218     MSIHANDLE hpkg, hdb;
5219     char path[MAX_PATH], expected[MAX_PATH], prop[MAX_PATH];
5220     BOOL version;
5221     LPCSTR str;
5222     DWORD size;
5223     UINT r;
5224 
5225     version = TRUE;
5226     if (!create_file_with_version("test.dll", MAKELONG(2, 1), MAKELONG(4, 3)))
5227         version = FALSE;
5228 
5229     DeleteFileA("test.dll");
5230 
5231     create_test_file("FileName1");
5232     CreateDirectoryA("one", NULL);
5233     CreateDirectoryA("one\\two", NULL);
5234     CreateDirectoryA("one\\two\\three", NULL);
5235     create_test_file("one\\two\\three\\FileName2");
5236     CreateDirectoryA("another", NULL);
5237     create_file_with_version("FileName3.dll", MAKELONG(2, 1), MAKELONG(4, 3));
5238     create_file_with_version("FileName4.dll", MAKELONG(1, 2), MAKELONG(3, 4));
5239     create_file_with_version("FileName5.dll", MAKELONG(2, 1), MAKELONG(4, 3));
5240 
5241     hdb = create_package_db();
5242     ok(hdb, "Expected a valid database handle\n");
5243 
5244     r = create_appsearch_table(hdb);
5245     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5246 
5247     r = add_appsearch_entry(hdb, "'SIGPROP1', 'NewSignature1'");
5248     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5249 
5250     r = add_appsearch_entry(hdb, "'SIGPROP2', 'NewSignature2'");
5251     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5252 
5253     r = add_appsearch_entry(hdb, "'SIGPROP3', 'NewSignature3'");
5254     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5255 
5256     r = add_appsearch_entry(hdb, "'SIGPROP4', 'NewSignature4'");
5257     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5258 
5259     r = add_appsearch_entry(hdb, "'SIGPROP5', 'NewSignature5'");
5260     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5261 
5262     r = add_appsearch_entry(hdb, "'SIGPROP6', 'NewSignature6'");
5263     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5264 
5265     r = add_appsearch_entry(hdb, "'SIGPROP7', 'NewSignature7'");
5266     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5267 
5268     r = add_appsearch_entry(hdb, "'SIGPROP8', 'NewSignature8'");
5269     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5270 
5271     r = add_appsearch_entry(hdb, "'SIGPROP9', 'NewSignature9'");
5272     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5273 
5274     r = add_appsearch_entry(hdb, "'SIGPROP10', 'NewSignature10'");
5275     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5276 
5277     r = add_appsearch_entry(hdb, "'SIGPROP11', 'NewSignature11'");
5278     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5279 
5280     r = add_appsearch_entry(hdb, "'SIGPROP13', 'NewSignature13'");
5281     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5282 
5283     r = create_drlocator_table(hdb);
5284     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5285 
5286     strcpy(expected, CURR_DIR);
5287     if (is_root(CURR_DIR)) expected[2] = 0;
5288 
5289     /* no parent, full path, depth 0, signature */
5290     sprintf(path, "'NewSignature1', '', '%s', 0", expected);
5291     r = add_drlocator_entry(hdb, path);
5292     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5293 
5294     /* no parent, full path, depth 0, no signature */
5295     sprintf(path, "'NewSignature2', '', '%s', 0", expected);
5296     r = add_drlocator_entry(hdb, path);
5297     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5298 
5299     /* no parent, relative path, depth 0, no signature */
5300     sprintf(path, "'NewSignature3', '', '%s', 0", expected + 3);
5301     r = add_drlocator_entry(hdb, path);
5302     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5303 
5304     /* no parent, full path, depth 2, signature */
5305     sprintf(path, "'NewSignature4', '', '%s', 2", expected);
5306     r = add_drlocator_entry(hdb, path);
5307     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5308 
5309     /* no parent, full path, depth 3, signature */
5310     sprintf(path, "'NewSignature5', '', '%s', 3", expected);
5311     r = add_drlocator_entry(hdb, path);
5312     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5313 
5314     /* no parent, full path, depth 1, signature is dir */
5315     sprintf(path, "'NewSignature6', '', '%s', 1", expected);
5316     r = add_drlocator_entry(hdb, path);
5317     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5318 
5319     /* parent is in DrLocator, relative path, depth 0, signature */
5320     sprintf(path, "'NewSignature7', 'NewSignature1', 'one\\two\\three', 1");
5321     r = add_drlocator_entry(hdb, path);
5322     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5323 
5324     /* no parent, full path, depth 0, signature w/ version */
5325     sprintf(path, "'NewSignature8', '', '%s', 0", expected);
5326     r = add_drlocator_entry(hdb, path);
5327     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5328 
5329     /* no parent, full path, depth 0, signature w/ version, ver > max */
5330     sprintf(path, "'NewSignature9', '', '%s', 0", expected);
5331     r = add_drlocator_entry(hdb, path);
5332     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5333 
5334     /* no parent, full path, depth 0, signature w/ version, sig->name not ignored */
5335     sprintf(path, "'NewSignature10', '', '%s', 0", expected);
5336     r = add_drlocator_entry(hdb, path);
5337     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5338 
5339     /* no parent, relative empty path, depth 0, no signature */
5340     sprintf(path, "'NewSignature11', '', '', 0");
5341     r = add_drlocator_entry(hdb, path);
5342     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5343 
5344     r = create_reglocator_table(hdb);
5345     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5346 
5347     /* parent */
5348     r = add_reglocator_entry(hdb, "NewSignature12", 2, "htmlfile\\shell\\open\\nonexistent", "", 1);
5349     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5350 
5351     /* parent is in RegLocator, no path, depth 0, no signature */
5352     sprintf(path, "'NewSignature13', 'NewSignature12', '', 0");
5353     r = add_drlocator_entry(hdb, path);
5354     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5355 
5356     r = create_signature_table(hdb);
5357     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5358 
5359     str = "'NewSignature1', 'FileName1', '', '', '', '', '', '', ''";
5360     r = add_signature_entry(hdb, str);
5361     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5362 
5363     str = "'NewSignature4', 'FileName2', '', '', '', '', '', '', ''";
5364     r = add_signature_entry(hdb, str);
5365     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5366 
5367     str = "'NewSignature5', 'FileName2', '', '', '', '', '', '', ''";
5368     r = add_signature_entry(hdb, str);
5369     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5370 
5371     str = "'NewSignature6', 'another', '', '', '', '', '', '', ''";
5372     r = add_signature_entry(hdb, str);
5373     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5374 
5375     str = "'NewSignature7', 'FileName2', '', '', '', '', '', '', ''";
5376     r = add_signature_entry(hdb, str);
5377     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5378 
5379     str = "'NewSignature8', 'FileName3.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''";
5380     r = add_signature_entry(hdb, str);
5381     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5382 
5383     str = "'NewSignature9', 'FileName4.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''";
5384     r = add_signature_entry(hdb, str);
5385     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5386 
5387     str = "'NewSignature10', 'necessary', '1.1.1.1', '2.1.1.1', '', '', '', '', ''";
5388     r = add_signature_entry(hdb, str);
5389     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5390 
5391     r = package_from_db(hdb, &hpkg);
5392     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5393     {
5394         skip("Not enough rights to perform tests\n");
5395         goto error;
5396     }
5397     ok(r == ERROR_SUCCESS, "Expected a valid package handle %u\n", r);
5398 
5399     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5400 
5401     r = MsiDoActionA(hpkg, "AppSearch");
5402     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5403 
5404     size = MAX_PATH;
5405     sprintf(path, "%s\\FileName1", expected);
5406     r = MsiGetPropertyA(hpkg, "SIGPROP1", prop, &size);
5407     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5408     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5409 
5410     size = MAX_PATH;
5411     sprintf(path, "%s\\", expected);
5412     r = MsiGetPropertyA(hpkg, "SIGPROP2", prop, &size);
5413     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5414     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5415 
5416     size = MAX_PATH;
5417     search_absolute_directory(path, expected + 3);
5418     r = MsiGetPropertyA(hpkg, "SIGPROP3", prop, &size);
5419     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5420     ok(!lstrcmpiA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5421 
5422     size = MAX_PATH;
5423     r = MsiGetPropertyA(hpkg, "SIGPROP4", prop, &size);
5424     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5425     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5426 
5427     size = MAX_PATH;
5428     sprintf(path, "%s\\one\\two\\three\\FileName2", expected);
5429     r = MsiGetPropertyA(hpkg, "SIGPROP5", prop, &size);
5430     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5431     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5432 
5433     size = MAX_PATH;
5434     r = MsiGetPropertyA(hpkg, "SIGPROP6", prop, &size);
5435     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5436     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5437 
5438     size = MAX_PATH;
5439     sprintf(path, "%s\\one\\two\\three\\FileName2", expected);
5440     r = MsiGetPropertyA(hpkg, "SIGPROP7", prop, &size);
5441     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5442     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5443 
5444     if (version)
5445     {
5446         size = MAX_PATH;
5447         sprintf(path, "%s\\FileName3.dll", expected);
5448         r = MsiGetPropertyA(hpkg, "SIGPROP8", prop, &size);
5449         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5450         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5451 
5452         size = MAX_PATH;
5453         r = MsiGetPropertyA(hpkg, "SIGPROP9", prop, &size);
5454         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5455         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5456 
5457         size = MAX_PATH;
5458         r = MsiGetPropertyA(hpkg, "SIGPROP10", prop, &size);
5459         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5460         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5461     }
5462 
5463     size = MAX_PATH;
5464     search_absolute_directory(path, "");
5465     r = MsiGetPropertyA(hpkg, "SIGPROP11", prop, &size);
5466     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5467     ok(!lstrcmpiA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5468 
5469     size = MAX_PATH;
5470     strcpy(path, "c:\\");
5471     r = MsiGetPropertyA(hpkg, "SIGPROP13", prop, &size);
5472     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5473     ok(!prop[0], "Expected \"\", got \"%s\"\n", prop);
5474 
5475     MsiCloseHandle(hpkg);
5476 
5477 error:
5478     DeleteFileA("FileName1");
5479     DeleteFileA("FileName3.dll");
5480     DeleteFileA("FileName4.dll");
5481     DeleteFileA("FileName5.dll");
5482     DeleteFileA("one\\two\\three\\FileName2");
5483     RemoveDirectoryA("one\\two\\three");
5484     RemoveDirectoryA("one\\two");
5485     RemoveDirectoryA("one");
5486     RemoveDirectoryA("another");
5487     DeleteFileA(msifile);
5488 }
5489 
5490 static void test_featureparents(void)
5491 {
5492     MSIHANDLE hpkg;
5493     UINT r;
5494     MSIHANDLE hdb;
5495 
5496     hdb = create_package_db();
5497     ok ( hdb, "failed to create package database\n" );
5498 
5499     r = add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'");
5500     ok( r == ERROR_SUCCESS, "cannot add directory: %d\n", r );
5501 
5502     r = create_feature_table( hdb );
5503     ok( r == ERROR_SUCCESS, "cannot create Feature table: %d\n", r );
5504 
5505     r = create_component_table( hdb );
5506     ok( r == ERROR_SUCCESS, "cannot create Component table: %d\n", r );
5507 
5508     r = create_feature_components_table( hdb );
5509     ok( r == ERROR_SUCCESS, "cannot create FeatureComponents table: %d\n", r );
5510 
5511     r = create_file_table( hdb );
5512     ok( r == ERROR_SUCCESS, "cannot create File table: %d\n", r );
5513 
5514     /* msidbFeatureAttributesFavorLocal */
5515     r = add_feature_entry( hdb, "'zodiac', '', '', '', 2, 1, '', 0" );
5516     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
5517 
5518     /* msidbFeatureAttributesFavorSource */
5519     r = add_feature_entry( hdb, "'perseus', '', '', '', 2, 1, '', 1" );
5520     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
5521 
5522     /* msidbFeatureAttributesFavorLocal */
5523     r = add_feature_entry( hdb, "'orion', '', '', '', 2, 1, '', 0" );
5524     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
5525 
5526     /* msidbFeatureAttributesUIDisallowAbsent */
5527     r = add_feature_entry( hdb, "'lyra', '', '', '', 2, 1, '', 16" );
5528     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
5529 
5530     /* disabled because of install level */
5531     r = add_feature_entry( hdb, "'waters', '', '', '', 15, 101, '', 9" );
5532     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
5533 
5534     /* child feature of disabled feature */
5535     r = add_feature_entry( hdb, "'bayer', 'waters', '', '', 14, 1, '', 9" );
5536     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
5537 
5538     /* component of disabled feature (install level) */
5539     r = add_component_entry( hdb, "'delphinus', '', 'TARGETDIR', 0, '', 'delphinus_file'" );
5540     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
5541 
5542     /* component of disabled child feature (install level) */
5543     r = add_component_entry( hdb, "'hydrus', '', 'TARGETDIR', 0, '', 'hydrus_file'" );
5544     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
5545 
5546     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesLocalOnly */
5547     r = add_component_entry( hdb, "'leo', '', 'TARGETDIR', 0, '', 'leo_file'" );
5548     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
5549 
5550     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSourceOnly */
5551     r = add_component_entry( hdb, "'virgo', '', 'TARGETDIR', 1, '', 'virgo_file'" );
5552     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
5553 
5554     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesOptional */
5555     r = add_component_entry( hdb, "'libra', '', 'TARGETDIR', 2, '', 'libra_file'" );
5556     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
5557 
5558     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesLocalOnly */
5559     r = add_component_entry( hdb, "'cassiopeia', '', 'TARGETDIR', 0, '', 'cassiopeia_file'" );
5560     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
5561 
5562     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSourceOnly */
5563     r = add_component_entry( hdb, "'cepheus', '', 'TARGETDIR', 1, '', 'cepheus_file'" );
5564     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
5565 
5566     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesOptional */
5567     r = add_component_entry( hdb, "'andromeda', '', 'TARGETDIR', 2, '', 'andromeda_file'" );
5568     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
5569 
5570     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesLocalOnly */
5571     r = add_component_entry( hdb, "'canis', '', 'TARGETDIR', 0, '', 'canis_file'" );
5572     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
5573 
5574     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSourceOnly */
5575     r = add_component_entry( hdb, "'monoceros', '', 'TARGETDIR', 1, '', 'monoceros_file'" );
5576     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
5577 
5578     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesOptional */
5579     r = add_component_entry( hdb, "'lepus', '', 'TARGETDIR', 2, '', 'lepus_file'" );
5580     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
5581 
5582     r = add_feature_components_entry( hdb, "'zodiac', 'leo'" );
5583     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
5584 
5585     r = add_feature_components_entry( hdb, "'zodiac', 'virgo'" );
5586     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
5587 
5588     r = add_feature_components_entry( hdb, "'zodiac', 'libra'" );
5589     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
5590 
5591     r = add_feature_components_entry( hdb, "'perseus', 'cassiopeia'" );
5592     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
5593 
5594     r = add_feature_components_entry( hdb, "'perseus', 'cepheus'" );
5595     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
5596 
5597     r = add_feature_components_entry( hdb, "'perseus', 'andromeda'" );
5598     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
5599 
5600     r = add_feature_components_entry( hdb, "'orion', 'leo'" );
5601     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
5602 
5603     r = add_feature_components_entry( hdb, "'orion', 'virgo'" );
5604     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
5605 
5606     r = add_feature_components_entry( hdb, "'orion', 'libra'" );
5607     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
5608 
5609     r = add_feature_components_entry( hdb, "'orion', 'cassiopeia'" );
5610     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
5611 
5612     r = add_feature_components_entry( hdb, "'orion', 'cepheus'" );
5613     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
5614 
5615     r = add_feature_components_entry( hdb, "'orion', 'andromeda'" );
5616     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
5617 
5618     r = add_feature_components_entry( hdb, "'orion', 'canis'" );
5619     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
5620 
5621     r = add_feature_components_entry( hdb, "'orion', 'monoceros'" );
5622     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
5623 
5624     r = add_feature_components_entry( hdb, "'orion', 'lepus'" );
5625     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
5626 
5627     r = add_feature_components_entry( hdb, "'waters', 'delphinus'" );
5628     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
5629 
5630     r = add_feature_components_entry( hdb, "'bayer', 'hydrus'" );
5631     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
5632 
5633     r = add_file_entry( hdb, "'leo_file', 'leo', 'leo.txt', 100, '', '1033', 8192, 1" );
5634     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
5635 
5636     r = add_file_entry( hdb, "'virgo_file', 'virgo', 'virgo.txt', 0, '', '1033', 8192, 1" );
5637     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
5638 
5639     r = add_file_entry( hdb, "'libra_file', 'libra', 'libra.txt', 0, '', '1033', 8192, 1" );
5640     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
5641 
5642     r = add_file_entry( hdb, "'cassiopeia_file', 'cassiopeia', 'cassiopeia.txt', 0, '', '1033', 8192, 1" );
5643     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
5644 
5645     r = add_file_entry( hdb, "'cepheus_file', 'cepheus', 'cepheus.txt', 0, '', '1033', 8192, 1" );
5646     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
5647 
5648     r = add_file_entry( hdb, "'andromeda_file', 'andromeda', 'andromeda.txt', 0, '', '1033', 8192, 1" );
5649     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
5650 
5651     r = add_file_entry( hdb, "'canis_file', 'canis', 'canis.txt', 0, '', '1033', 8192, 1" );
5652     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
5653 
5654     r = add_file_entry( hdb, "'monoceros_file', 'monoceros', 'monoceros.txt', 0, '', '1033', 8192, 1" );
5655     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
5656 
5657     r = add_file_entry( hdb, "'lepus_file', 'lepus', 'lepus.txt', 0, '', '1033', 8192, 1" );
5658     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
5659 
5660     r = add_file_entry( hdb, "'delphinus_file', 'delphinus', 'delphinus.txt', 0, '', '1033', 8192, 1" );
5661     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
5662 
5663     r = add_file_entry( hdb, "'hydrus_file', 'hydrus', 'hydrus.txt', 0, '', '1033', 8192, 1" );
5664     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
5665 
5666     r = package_from_db( hdb, &hpkg );
5667     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5668     {
5669         skip("Not enough rights to perform tests\n");
5670         DeleteFileA(msifile);
5671         return;
5672     }
5673     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
5674 
5675     MsiCloseHandle( hdb );
5676 
5677     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5678 
5679     r = MsiDoActionA( hpkg, "CostInitialize");
5680     ok( r == ERROR_SUCCESS, "cost init failed\n");
5681 
5682     r = MsiDoActionA( hpkg, "FileCost");
5683     ok( r == ERROR_SUCCESS, "file cost failed\n");
5684 
5685     r = MsiDoActionA( hpkg, "CostFinalize");
5686     ok( r == ERROR_SUCCESS, "cost finalize failed\n");
5687 
5688     test_feature_states( __LINE__, hpkg, "zodiac", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
5689     test_feature_states( __LINE__, hpkg, "perseus", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
5690     test_feature_states( __LINE__, hpkg, "orion", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
5691     test_feature_states( __LINE__, hpkg, "lyra", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
5692     test_feature_states( __LINE__, hpkg, "waters", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
5693     test_feature_states( __LINE__, hpkg, "bayer", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
5694 
5695     test_component_states( __LINE__, hpkg, "leo", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5696     test_component_states( __LINE__, hpkg, "virgo", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5697     test_component_states( __LINE__, hpkg, "libra", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5698     test_component_states( __LINE__, hpkg, "cassiopeia", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5699     test_component_states( __LINE__, hpkg, "cepheus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5700     test_component_states( __LINE__, hpkg, "andromeda", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5701     test_component_states( __LINE__, hpkg, "canis", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5702     test_component_states( __LINE__, hpkg, "monoceros", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5703     test_component_states( __LINE__, hpkg, "lepus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5704     test_component_states( __LINE__, hpkg, "delphinus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5705     test_component_states( __LINE__, hpkg, "hydrus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5706 
5707     r = MsiSetFeatureStateA(hpkg, "orion", INSTALLSTATE_ABSENT);
5708     ok( r == ERROR_SUCCESS, "failed to set feature state: %d\n", r);
5709 
5710     r = MsiSetFeatureStateA(hpkg, "lyra", INSTALLSTATE_ABSENT);
5711     ok( r == ERROR_SUCCESS, "failed to set feature state: %d\n", r);
5712 
5713     r = MsiSetFeatureStateA(hpkg, "nosuchfeature", INSTALLSTATE_ABSENT);
5714     ok( r == ERROR_UNKNOWN_FEATURE, "Expected ERROR_UNKNOWN_FEATURE, got %u\n", r);
5715 
5716     test_feature_states( __LINE__, hpkg, "zodiac", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
5717     test_feature_states( __LINE__, hpkg, "perseus", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
5718     test_feature_states( __LINE__, hpkg, "orion", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_ABSENT, FALSE );
5719     test_feature_states( __LINE__, hpkg, "lyra", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_ABSENT, FALSE );
5720     test_feature_states( __LINE__, hpkg, "waters", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
5721     test_feature_states( __LINE__, hpkg, "bayer", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
5722 
5723     test_component_states( __LINE__, hpkg, "leo", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5724     test_component_states( __LINE__, hpkg, "virgo", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5725     test_component_states( __LINE__, hpkg, "libra", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5726     test_component_states( __LINE__, hpkg, "cassiopeia", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5727     test_component_states( __LINE__, hpkg, "cepheus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5728     test_component_states( __LINE__, hpkg, "andromeda", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5729     test_component_states( __LINE__, hpkg, "canis", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5730     test_component_states( __LINE__, hpkg, "monoceros", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5731     test_component_states( __LINE__, hpkg, "lepus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5732     test_component_states( __LINE__, hpkg, "delphinus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5733     test_component_states( __LINE__, hpkg, "hydrus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5734 
5735     MsiCloseHandle(hpkg);
5736     DeleteFileA(msifile);
5737 }
5738 
5739 static void test_installprops(void)
5740 {
5741     MSIHANDLE hpkg, hdb;
5742     CHAR path[MAX_PATH], buf[MAX_PATH];
5743     DWORD size, type;
5744     LANGID langid;
5745     HKEY hkey1, hkey2;
5746     int res;
5747     UINT r;
5748     REGSAM access = KEY_ALL_ACCESS;
5749     SYSTEM_INFO si;
5750     INSTALLUILEVEL uilevel;
5751 
5752     if (is_wow64)
5753         access |= KEY_WOW64_64KEY;
5754 
5755     lstrcpyA(path, CURR_DIR);
5756     if (!is_root(CURR_DIR)) lstrcatA(path, "\\");
5757     lstrcatA(path, msifile);
5758 
5759     uilevel = MsiSetInternalUI(INSTALLUILEVEL_BASIC|INSTALLUILEVEL_SOURCERESONLY, NULL);
5760 
5761     hdb = create_package_db();
5762     ok( hdb, "failed to create database\n");
5763 
5764     r = package_from_db(hdb, &hpkg);
5765     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5766     {
5767         skip("Not enough rights to perform tests\n");
5768         MsiSetInternalUI(uilevel, NULL);
5769         DeleteFileA(msifile);
5770         return;
5771     }
5772     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
5773 
5774     MsiCloseHandle(hdb);
5775 
5776     buf[0] = 0;
5777     size = MAX_PATH;
5778     r = MsiGetPropertyA(hpkg, "UILevel", buf, &size);
5779     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5780     ok( !lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
5781 
5782     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5783 
5784     buf[0] = 0;
5785     size = MAX_PATH;
5786     r = MsiGetPropertyA(hpkg, "UILevel", buf, &size);
5787     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5788     ok( !lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
5789 
5790     buf[0] = 0;
5791     size = MAX_PATH;
5792     r = MsiGetPropertyA(hpkg, "DATABASE", buf, &size);
5793     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5794     ok( !lstrcmpA(buf, path), "Expected %s, got %s\n", path, buf);
5795 
5796     RegOpenKeyA(HKEY_CURRENT_USER, "SOFTWARE\\Microsoft\\MS Setup (ACME)\\User Info", &hkey1);
5797     RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, access, &hkey2);
5798 
5799     size = MAX_PATH;
5800     type = REG_SZ;
5801     *path = '\0';
5802     if (RegQueryValueExA(hkey1, "DefName", NULL, &type, (LPBYTE)path, &size) != ERROR_SUCCESS)
5803     {
5804         size = MAX_PATH;
5805         type = REG_SZ;
5806         RegQueryValueExA(hkey2, "RegisteredOwner", NULL, &type, (LPBYTE)path, &size);
5807     }
5808 
5809     buf[0] = 0;
5810     size = MAX_PATH;
5811     r = MsiGetPropertyA(hpkg, "USERNAME", buf, &size);
5812     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5813     ok( !lstrcmpA(buf, path), "Expected %s, got %s\n", path, buf);
5814 
5815     size = MAX_PATH;
5816     type = REG_SZ;
5817     *path = '\0';
5818     if (RegQueryValueExA(hkey1, "DefCompany", NULL, &type, (LPBYTE)path, &size) != ERROR_SUCCESS)
5819     {
5820         size = MAX_PATH;
5821         type = REG_SZ;
5822         RegQueryValueExA(hkey2, "RegisteredOrganization", NULL, &type, (LPBYTE)path, &size);
5823     }
5824 
5825     if (*path)
5826     {
5827         buf[0] = 0;
5828         size = MAX_PATH;
5829         r = MsiGetPropertyA(hpkg, "COMPANYNAME", buf, &size);
5830         ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5831         ok( !lstrcmpA(buf, path), "Expected %s, got %s\n", path, buf);
5832     }
5833 
5834     buf[0] = 0;
5835     size = MAX_PATH;
5836     r = MsiGetPropertyA(hpkg, "VersionDatabase", buf, &size);
5837     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5838     trace("VersionDatabase = %s\n", buf);
5839 
5840     buf[0] = 0;
5841     size = MAX_PATH;
5842     r = MsiGetPropertyA(hpkg, "VersionMsi", buf, &size);
5843     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5844     trace("VersionMsi = %s\n", buf);
5845 
5846     buf[0] = 0;
5847     size = MAX_PATH;
5848     r = MsiGetPropertyA(hpkg, "Date", buf, &size);
5849     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5850     trace("Date = %s\n", buf);
5851 
5852     buf[0] = 0;
5853     size = MAX_PATH;
5854     r = MsiGetPropertyA(hpkg, "Time", buf, &size);
5855     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5856     trace("Time = %s\n", buf);
5857 
5858     buf[0] = 0;
5859     size = MAX_PATH;
5860     r = MsiGetPropertyA(hpkg, "PackageCode", buf, &size);
5861     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5862     trace("PackageCode = %s\n", buf);
5863 
5864     buf[0] = 0;
5865     size = MAX_PATH;
5866     r = MsiGetPropertyA(hpkg, "ComputerName", buf, &size);
5867     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
5868     trace("ComputerName = %s\n", buf);
5869 
5870     langid = GetUserDefaultLangID();
5871     sprintf(path, "%d", langid);
5872 
5873     buf[0] = 0;
5874     size = MAX_PATH;
5875     r = MsiGetPropertyA(hpkg, "UserLanguageID", buf, &size);
5876     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
5877     ok( !lstrcmpA(buf, path), "Expected \"%s\", got \"%s\"\n", path, buf);
5878 
5879     res = GetSystemMetrics(SM_CXSCREEN);
5880     buf[0] = 0;
5881     size = MAX_PATH;
5882     r = MsiGetPropertyA(hpkg, "ScreenX", buf, &size);
5883     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
5884     ok(atol(buf) == res, "Expected %d, got %ld\n", res, atol(buf));
5885 
5886     res = GetSystemMetrics(SM_CYSCREEN);
5887     buf[0] = 0;
5888     size = MAX_PATH;
5889     r = MsiGetPropertyA(hpkg, "ScreenY", buf, &size);
5890     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
5891     ok(atol(buf) == res, "Expected %d, got %ld\n", res, atol(buf));
5892 
5893     if (pGetSystemInfo && pSHGetFolderPathA)
5894     {
5895         pGetSystemInfo(&si);
5896         if (S(U(si)).wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
5897         {
5898             buf[0] = 0;
5899             size = MAX_PATH;
5900             r = MsiGetPropertyA(hpkg, "Intel", buf, &size);
5901             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5902             ok(buf[0], "property not set\n");
5903 
5904             buf[0] = 0;
5905             size = MAX_PATH;
5906             r = MsiGetPropertyA(hpkg, "MsiAMD64", buf, &size);
5907             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5908             ok(buf[0], "property not set\n");
5909 
5910             buf[0] = 0;
5911             size = MAX_PATH;
5912             r = MsiGetPropertyA(hpkg, "Msix64", buf, &size);
5913             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5914             ok(buf[0], "property not set\n");
5915 
5916             buf[0] = 0;
5917             size = MAX_PATH;
5918             r = MsiGetPropertyA(hpkg, "System64Folder", buf, &size);
5919             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5920             GetSystemDirectoryA(path, MAX_PATH);
5921             if (size) buf[size - 1] = 0;
5922             ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5923 
5924             buf[0] = 0;
5925             size = MAX_PATH;
5926             r = MsiGetPropertyA(hpkg, "SystemFolder", buf, &size);
5927             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5928             pGetSystemWow64DirectoryA(path, MAX_PATH);
5929             if (size) buf[size - 1] = 0;
5930             ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5931 
5932             buf[0] = 0;
5933             size = MAX_PATH;
5934             r = MsiGetPropertyA(hpkg, "ProgramFiles64Folder", buf, &size);
5935             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5936             pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES, NULL, 0, path);
5937             if (size) buf[size - 1] = 0;
5938             ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5939 
5940             buf[0] = 0;
5941             size = MAX_PATH;
5942             r = MsiGetPropertyA(hpkg, "ProgramFilesFolder", buf, &size);
5943             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5944             pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILESX86, NULL, 0, path);
5945             if (size) buf[size - 1] = 0;
5946             ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5947 
5948             buf[0] = 0;
5949             size = MAX_PATH;
5950             r = MsiGetPropertyA(hpkg, "CommonFiles64Folder", buf, &size);
5951             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5952             pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES_COMMON, NULL, 0, path);
5953             if (size) buf[size - 1] = 0;
5954             ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5955 
5956             buf[0] = 0;
5957             size = MAX_PATH;
5958             r = MsiGetPropertyA(hpkg, "CommonFilesFolder", buf, &size);
5959             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5960             pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES_COMMONX86, NULL, 0, path);
5961             if (size) buf[size - 1] = 0;
5962             ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5963 
5964             buf[0] = 0;
5965             size = MAX_PATH;
5966             r = MsiGetPropertyA(hpkg, "VersionNT64", buf, &size);
5967             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5968             ok(buf[0], "property not set\n");
5969         }
5970         else if (S(U(si)).wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
5971         {
5972             if (!is_wow64)
5973             {
5974                 buf[0] = 0;
5975                 size = MAX_PATH;
5976                 r = MsiGetPropertyA(hpkg, "Intel", buf, &size);
5977                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5978                 ok(buf[0], "property not set\n");
5979 
5980                 buf[0] = 0;
5981                 size = MAX_PATH;
5982                 r = MsiGetPropertyA(hpkg, "MsiAMD64", buf, &size);
5983                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5984                 ok(!buf[0], "property set\n");
5985 
5986                 buf[0] = 0;
5987                 size = MAX_PATH;
5988                 r = MsiGetPropertyA(hpkg, "Msix64", buf, &size);
5989                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5990                 ok(!buf[0], "property set\n");
5991 
5992                 buf[0] = 0;
5993                 size = MAX_PATH;
5994                 r = MsiGetPropertyA(hpkg, "System64Folder", buf, &size);
5995                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5996                 ok(!buf[0], "property set\n");
5997 
5998                 buf[0] = 0;
5999                 size = MAX_PATH;
6000                 r = MsiGetPropertyA(hpkg, "SystemFolder", buf, &size);
6001                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
6002                 GetSystemDirectoryA(path, MAX_PATH);
6003                 if (size) buf[size - 1] = 0;
6004                 ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
6005 
6006                 buf[0] = 0;
6007                 size = MAX_PATH;
6008                 r = MsiGetPropertyA(hpkg, "ProgramFiles64Folder", buf, &size);
6009                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
6010                 ok(!buf[0], "property set\n");
6011 
6012                 buf[0] = 0;
6013                 size = MAX_PATH;
6014                 r = MsiGetPropertyA(hpkg, "ProgramFilesFolder", buf, &size);
6015                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
6016                 pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES, NULL, 0, path);
6017                 if (size) buf[size - 1] = 0;
6018                 ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
6019 
6020                 buf[0] = 0;
6021                 size = MAX_PATH;
6022                 r = MsiGetPropertyA(hpkg, "CommonFiles64Folder", buf, &size);
6023                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
6024                 ok(!buf[0], "property set\n");
6025 
6026                 buf[0] = 0;
6027                 size = MAX_PATH;
6028                 r = MsiGetPropertyA(hpkg, "CommonFilesFolder", buf, &size);
6029                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
6030                 pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES_COMMON, NULL, 0, path);
6031                 if (size) buf[size - 1] = 0;
6032                 ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
6033 
6034                 buf[0] = 0;
6035                 size = MAX_PATH;
6036                 r = MsiGetPropertyA(hpkg, "VersionNT64", buf, &size);
6037                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
6038                 ok(!buf[0], "property set\n");
6039             }
6040             else
6041             {
6042                 buf[0] = 0;
6043                 size = MAX_PATH;
6044                 r = MsiGetPropertyA(hpkg, "Intel", buf, &size);
6045                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
6046                 ok(buf[0], "property not set\n");
6047 
6048                 buf[0] = 0;
6049                 size = MAX_PATH;
6050                 r = MsiGetPropertyA(hpkg, "MsiAMD64", buf, &size);
6051                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
6052                 ok(buf[0], "property not set\n");
6053 
6054                 buf[0] = 0;
6055                 size = MAX_PATH;
6056                 r = MsiGetPropertyA(hpkg, "Msix64", buf, &size);
6057                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
6058                 ok(buf[0], "property not set\n");
6059 
6060                 buf[0] = 0;
6061                 size = MAX_PATH;
6062                 r = MsiGetPropertyA(hpkg, "System64Folder", buf, &size);
6063                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
6064                 GetSystemDirectoryA(path, MAX_PATH);
6065                 if (size) buf[size - 1] = 0;
6066                 ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
6067 
6068                 buf[0] = 0;
6069                 size = MAX_PATH;
6070                 r = MsiGetPropertyA(hpkg, "SystemFolder", buf, &size);
6071                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
6072                 pGetSystemWow64DirectoryA(path, MAX_PATH);
6073                 if (size) buf[size - 1] = 0;
6074                 ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
6075 
6076                 buf[0] = 0;
6077                 size = MAX_PATH;
6078                 r = MsiGetPropertyA(hpkg, "ProgramFilesFolder64", buf, &size);
6079                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
6080                 ok(!buf[0], "property set\n");
6081 
6082                 buf[0] = 0;
6083                 size = MAX_PATH;
6084                 r = MsiGetPropertyA(hpkg, "ProgramFilesFolder", buf, &size);
6085                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
6086                 pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILESX86, NULL, 0, path);
6087                 if (size) buf[size - 1] = 0;
6088                 ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
6089 
6090                 buf[0] = 0;
6091                 size = MAX_PATH;
6092                 r = MsiGetPropertyA(hpkg, "CommonFilesFolder64", buf, &size);
6093                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
6094                 ok(!buf[0], "property set\n");
6095 
6096                 buf[0] = 0;
6097                 size = MAX_PATH;
6098                 r = MsiGetPropertyA(hpkg, "CommonFilesFolder", buf, &size);
6099                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
6100                 pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES_COMMONX86, NULL, 0, path);
6101                 if (size) buf[size - 1] = 0;
6102                 ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
6103 
6104                 buf[0] = 0;
6105                 size = MAX_PATH;
6106                 r = MsiGetPropertyA(hpkg, "VersionNT64", buf, &size);
6107                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
6108                 ok(buf[0], "property not set\n");
6109             }
6110         }
6111     }
6112 
6113     CloseHandle(hkey1);
6114     CloseHandle(hkey2);
6115     MsiCloseHandle(hpkg);
6116     DeleteFileA(msifile);
6117     MsiSetInternalUI(uilevel, NULL);
6118 }
6119 
6120 static void test_launchconditions(void)
6121 {
6122     MSIHANDLE hpkg;
6123     MSIHANDLE hdb;
6124     UINT r;
6125 
6126     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
6127 
6128     hdb = create_package_db();
6129     ok( hdb, "failed to create package database\n" );
6130 
6131     r = create_launchcondition_table( hdb );
6132     ok( r == ERROR_SUCCESS, "cannot create LaunchCondition table: %d\n", r );
6133 
6134     r = add_launchcondition_entry( hdb, "'X = \"1\"', 'one'" );
6135     ok( r == ERROR_SUCCESS, "cannot add launch condition: %d\n", r );
6136 
6137     /* invalid condition */
6138     r = add_launchcondition_entry( hdb, "'X != \"1\"', 'one'" );
6139     ok( r == ERROR_SUCCESS, "cannot add launch condition: %d\n", r );
6140 
6141     r = package_from_db( hdb, &hpkg );
6142     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
6143     {
6144         skip("Not enough rights to perform tests\n");
6145         DeleteFileA(msifile);
6146         return;
6147     }
6148     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
6149 
6150     MsiCloseHandle( hdb );
6151 
6152     r = MsiSetPropertyA( hpkg, "X", "1" );
6153     ok( r == ERROR_SUCCESS, "failed to set property\n" );
6154 
6155     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
6156 
6157     /* invalid conditions are ignored */
6158     r = MsiDoActionA( hpkg, "LaunchConditions" );
6159     ok( r == ERROR_SUCCESS, "cost init failed\n" );
6160 
6161     /* verify LaunchConditions still does some verification */
6162     r = MsiSetPropertyA( hpkg, "X", "2" );
6163     ok( r == ERROR_SUCCESS, "failed to set property\n" );
6164 
6165     r = MsiDoActionA( hpkg, "LaunchConditions" );
6166     ok( r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %d\n", r );
6167 
6168     MsiCloseHandle( hpkg );
6169     DeleteFileA( msifile );
6170 }
6171 
6172 static void test_ccpsearch(void)
6173 {
6174     MSIHANDLE hdb, hpkg;
6175     CHAR prop[MAX_PATH];
6176     DWORD size = MAX_PATH;
6177     UINT r;
6178 
6179     hdb = create_package_db();
6180     ok(hdb, "failed to create package database\n");
6181 
6182     r = create_ccpsearch_table(hdb);
6183     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6184 
6185     r = add_ccpsearch_entry(hdb, "'CCP_random'");
6186     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6187 
6188     r = add_ccpsearch_entry(hdb, "'RMCCP_random'");
6189     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6190 
6191     r = create_reglocator_table(hdb);
6192     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6193 
6194     r = add_reglocator_entry(hdb, "CCP_random", 0, "htmlfile\\shell\\open\\nonexistent", "", 1);
6195     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6196 
6197     r = create_drlocator_table(hdb);
6198     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6199 
6200     r = add_drlocator_entry(hdb, "'RMCCP_random', '', 'C:\\', '0'");
6201     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6202 
6203     r = create_signature_table(hdb);
6204     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6205 
6206     r = package_from_db(hdb, &hpkg);
6207     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
6208     {
6209         skip("Not enough rights to perform tests\n");
6210         DeleteFileA(msifile);
6211         return;
6212     }
6213     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
6214 
6215     MsiCloseHandle(hdb);
6216 
6217     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
6218 
6219     r = MsiDoActionA(hpkg, "CCPSearch");
6220     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6221 
6222     r = MsiGetPropertyA(hpkg, "CCP_Success", prop, &size);
6223     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6224     ok(!lstrcmpA(prop, "1"), "Expected 1, got %s\n", prop);
6225 
6226     MsiCloseHandle(hpkg);
6227     DeleteFileA(msifile);
6228 }
6229 
6230 static void test_complocator(void)
6231 {
6232     MSIHANDLE hdb, hpkg;
6233     UINT r;
6234     CHAR prop[MAX_PATH];
6235     CHAR expected[MAX_PATH];
6236     DWORD size = MAX_PATH;
6237 
6238     hdb = create_package_db();
6239     ok(hdb, "failed to create package database\n");
6240 
6241     r = create_appsearch_table(hdb);
6242     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6243 
6244     r = add_appsearch_entry(hdb, "'ABELISAURUS', 'abelisaurus'");
6245     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6246 
6247     r = add_appsearch_entry(hdb, "'BACTROSAURUS', 'bactrosaurus'");
6248     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6249 
6250     r = add_appsearch_entry(hdb, "'CAMELOTIA', 'camelotia'");
6251     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6252 
6253     r = add_appsearch_entry(hdb, "'DICLONIUS', 'diclonius'");
6254     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6255 
6256     r = add_appsearch_entry(hdb, "'ECHINODON', 'echinodon'");
6257     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6258 
6259     r = add_appsearch_entry(hdb, "'FALCARIUS', 'falcarius'");
6260     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6261 
6262     r = add_appsearch_entry(hdb, "'GALLIMIMUS', 'gallimimus'");
6263     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6264 
6265     r = add_appsearch_entry(hdb, "'HAGRYPHUS', 'hagryphus'");
6266     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6267 
6268     r = add_appsearch_entry(hdb, "'IGUANODON', 'iguanodon'");
6269     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6270 
6271     r = add_appsearch_entry(hdb, "'JOBARIA', 'jobaria'");
6272     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6273 
6274     r = add_appsearch_entry(hdb, "'KAKURU', 'kakuru'");
6275     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6276 
6277     r = add_appsearch_entry(hdb, "'LABOCANIA', 'labocania'");
6278     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6279 
6280     r = add_appsearch_entry(hdb, "'MEGARAPTOR', 'megaraptor'");
6281     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6282 
6283     r = add_appsearch_entry(hdb, "'NEOSODON', 'neosodon'");
6284     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6285 
6286     r = add_appsearch_entry(hdb, "'OLOROTITAN', 'olorotitan'");
6287     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6288 
6289     r = add_appsearch_entry(hdb, "'PANTYDRACO', 'pantydraco'");
6290     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6291 
6292     r = create_complocator_table(hdb);
6293     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6294 
6295     r = add_complocator_entry(hdb, "'abelisaurus', '{E3619EED-305A-418C-B9C7-F7D7377F0934}', 1");
6296     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6297 
6298     r = add_complocator_entry(hdb, "'bactrosaurus', '{D56B688D-542F-42Ef-90FD-B6DA76EE8119}', 0");
6299     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6300 
6301     r = add_complocator_entry(hdb, "'camelotia', '{8211BE36-2466-47E3-AFB7-6AC72E51AED2}', 1");
6302     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6303 
6304     r = add_complocator_entry(hdb, "'diclonius', '{5C767B20-A33C-45A4-B80B-555E512F01AE}', 0");
6305     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6306 
6307     r = add_complocator_entry(hdb, "'echinodon', '{A19E16C5-C75D-4699-8111-C4338C40C3CB}', 1");
6308     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6309 
6310     r = add_complocator_entry(hdb, "'falcarius', '{17762FA1-A7AE-4CC6-8827-62873C35361D}', 0");
6311     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6312 
6313     r = add_complocator_entry(hdb, "'gallimimus', '{75EBF568-C959-41E0-A99E-9050638CF5FB}', 1");
6314     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6315 
6316     r = add_complocator_entry(hdb, "'hagrphus', '{D4969B72-17D9-4AB6-BE49-78F2FEE857AC}', 0");
6317     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6318 
6319     r = add_complocator_entry(hdb, "'iguanodon', '{8E0DA02E-F6A7-4A8F-B25D-6F564C492308}', 1");
6320     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6321 
6322     r = add_complocator_entry(hdb, "'jobaria', '{243C22B1-8C51-4151-B9D1-1AE5265E079E}', 0");
6323     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6324 
6325     r = add_complocator_entry(hdb, "'kakuru', '{5D0F03BA-50BC-44F2-ABB1-72C972F4E514}', 1");
6326     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6327 
6328     r = add_complocator_entry(hdb, "'labocania', '{C7DDB60C-7828-4046-A6F8-699D5E92F1ED}', 0");
6329     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6330 
6331     r = add_complocator_entry(hdb, "'megaraptor', '{8B1034B7-BD5E-41ac-B52C-0105D3DFD74D}', 1");
6332     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6333 
6334     r = add_complocator_entry(hdb, "'neosodon', '{0B499649-197A-48EF-93D2-AF1C17ED6E90}', 0");
6335     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6336 
6337     r = add_complocator_entry(hdb, "'olorotitan', '{54E9E91F-AED2-46D5-A25A-7E50AFA24513}', 1");
6338     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6339 
6340     r = add_complocator_entry(hdb, "'pantydraco', '{2A989951-5565-4FA7-93A7-E800A3E67D71}', 0");
6341     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6342 
6343     r = create_signature_table(hdb);
6344     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6345 
6346     r = add_signature_entry(hdb, "'abelisaurus', 'abelisaurus', '', '', '', '', '', '', ''");
6347     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6348 
6349     r = add_signature_entry(hdb, "'bactrosaurus', 'bactrosaurus', '', '', '', '', '', '', ''");
6350     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6351 
6352     r = add_signature_entry(hdb, "'camelotia', 'camelotia', '', '', '', '', '', '', ''");
6353     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6354 
6355     r = add_signature_entry(hdb, "'diclonius', 'diclonius', '', '', '', '', '', '', ''");
6356     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6357 
6358     r = add_signature_entry(hdb, "'iguanodon', 'iguanodon', '', '', '', '', '', '', ''");
6359     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6360 
6361     r = add_signature_entry(hdb, "'jobaria', 'jobaria', '', '', '', '', '', '', ''");
6362     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6363 
6364     r = add_signature_entry(hdb, "'kakuru', 'kakuru', '', '', '', '', '', '', ''");
6365     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6366 
6367     r = add_signature_entry(hdb, "'labocania', 'labocania', '', '', '', '', '', '', ''");
6368     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6369 
6370     r = package_from_db(hdb, &hpkg);
6371     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
6372     {
6373         skip("Not enough rights to perform tests\n");
6374         DeleteFileA(msifile);
6375         return;
6376     }
6377     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
6378 
6379     MsiCloseHandle(hdb);
6380 
6381     create_test_file("abelisaurus");
6382     create_test_file("bactrosaurus");
6383     create_test_file("camelotia");
6384     create_test_file("diclonius");
6385     create_test_file("echinodon");
6386     create_test_file("falcarius");
6387     create_test_file("gallimimus");
6388     create_test_file("hagryphus");
6389     CreateDirectoryA("iguanodon", NULL);
6390     CreateDirectoryA("jobaria", NULL);
6391     CreateDirectoryA("kakuru", NULL);
6392     CreateDirectoryA("labocania", NULL);
6393     CreateDirectoryA("megaraptor", NULL);
6394     CreateDirectoryA("neosodon", NULL);
6395     CreateDirectoryA("olorotitan", NULL);
6396     CreateDirectoryA("pantydraco", NULL);
6397 
6398     set_component_path("abelisaurus", MSIINSTALLCONTEXT_MACHINE,
6399                        "{E3619EED-305A-418C-B9C7-F7D7377F0934}", NULL, FALSE);
6400     set_component_path("bactrosaurus", MSIINSTALLCONTEXT_MACHINE,
6401                        "{D56B688D-542F-42Ef-90FD-B6DA76EE8119}", NULL, FALSE);
6402     set_component_path("echinodon", MSIINSTALLCONTEXT_MACHINE,
6403                        "{A19E16C5-C75D-4699-8111-C4338C40C3CB}", NULL, FALSE);
6404     set_component_path("falcarius", MSIINSTALLCONTEXT_MACHINE,
6405                        "{17762FA1-A7AE-4CC6-8827-62873C35361D}", NULL, FALSE);
6406     set_component_path("iguanodon", MSIINSTALLCONTEXT_MACHINE,
6407                        "{8E0DA02E-F6A7-4A8F-B25D-6F564C492308}", NULL, FALSE);
6408     set_component_path("jobaria", MSIINSTALLCONTEXT_MACHINE,
6409                        "{243C22B1-8C51-4151-B9D1-1AE5265E079E}", NULL, FALSE);
6410     set_component_path("megaraptor", MSIINSTALLCONTEXT_MACHINE,
6411                        "{8B1034B7-BD5E-41ac-B52C-0105D3DFD74D}", NULL, FALSE);
6412     set_component_path("neosodon", MSIINSTALLCONTEXT_MACHINE,
6413                        "{0B499649-197A-48EF-93D2-AF1C17ED6E90}", NULL, FALSE);
6414 
6415     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
6416 
6417     r = MsiDoActionA(hpkg, "AppSearch");
6418     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6419 
6420     size = MAX_PATH;
6421     r = MsiGetPropertyA(hpkg, "ABELISAURUS", prop, &size);
6422     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6423 
6424     lstrcpyA(expected, CURR_DIR);
6425     if (!is_root(CURR_DIR)) lstrcatA(expected, "\\");
6426     lstrcatA(expected, "abelisaurus");
6427     ok(!lstrcmpA(prop, expected) || !lstrcmpA(prop, ""),
6428        "Expected %s or empty string, got %s\n", expected, prop);
6429 
6430     size = MAX_PATH;
6431     r = MsiGetPropertyA(hpkg, "BACTROSAURUS", prop, &size);
6432     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6433     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6434 
6435     size = MAX_PATH;
6436     r = MsiGetPropertyA(hpkg, "CAMELOTIA", prop, &size);
6437     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6438     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6439 
6440     size = MAX_PATH;
6441     r = MsiGetPropertyA(hpkg, "DICLONIUS", prop, &size);
6442     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6443     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6444 
6445     size = MAX_PATH;
6446     r = MsiGetPropertyA(hpkg, "ECHINODON", prop, &size);
6447     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6448 
6449     lstrcpyA(expected, CURR_DIR);
6450     if (!is_root(CURR_DIR)) lstrcatA(expected, "\\");
6451     ok(!lstrcmpA(prop, expected) || !lstrcmpA(prop, ""),
6452        "Expected %s or empty string, got %s\n", expected, prop);
6453 
6454     size = MAX_PATH;
6455     r = MsiGetPropertyA(hpkg, "FALCARIUS", prop, &size);
6456     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6457     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6458 
6459     size = MAX_PATH;
6460     r = MsiGetPropertyA(hpkg, "GALLIMIMUS", prop, &size);
6461     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6462     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6463 
6464     size = MAX_PATH;
6465     r = MsiGetPropertyA(hpkg, "HAGRYPHUS", prop, &size);
6466     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6467     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6468 
6469     size = MAX_PATH;
6470     r = MsiGetPropertyA(hpkg, "IGUANODON", prop, &size);
6471     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6472     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6473 
6474     size = MAX_PATH;
6475     r = MsiGetPropertyA(hpkg, "JOBARIA", prop, &size);
6476     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6477     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6478 
6479     size = MAX_PATH;
6480     r = MsiGetPropertyA(hpkg, "KAKURU", prop, &size);
6481     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6482     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6483 
6484     size = MAX_PATH;
6485     r = MsiGetPropertyA(hpkg, "LABOCANIA", prop, &size);
6486     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6487     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6488 
6489     size = MAX_PATH;
6490     r = MsiGetPropertyA(hpkg, "MEGARAPTOR", prop, &size);
6491     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6492 
6493     lstrcpyA(expected, CURR_DIR);
6494     if (!is_root(CURR_DIR)) lstrcatA(expected, "\\");
6495     ok(!lstrcmpA(prop, expected) || !lstrcmpA(prop, ""),
6496        "Expected %s or empty string, got %s\n", expected, prop);
6497 
6498     size = MAX_PATH;
6499     r = MsiGetPropertyA(hpkg, "NEOSODON", prop, &size);
6500     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6501 
6502     lstrcpyA(expected, CURR_DIR);
6503     if (!is_root(CURR_DIR)) lstrcatA(expected, "\\");
6504     lstrcatA(expected, "neosodon\\");
6505     ok(!lstrcmpA(prop, expected) || !lstrcmpA(prop, ""),
6506        "Expected %s or empty string, got %s\n", expected, prop);
6507 
6508     size = MAX_PATH;
6509     r = MsiGetPropertyA(hpkg, "OLOROTITAN", prop, &size);
6510     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6511     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6512 
6513     size = MAX_PATH;
6514     r = MsiGetPropertyA(hpkg, "PANTYDRACO", prop, &size);
6515     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6516     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6517 
6518     MsiCloseHandle(hpkg);
6519     DeleteFileA("abelisaurus");
6520     DeleteFileA("bactrosaurus");
6521     DeleteFileA("camelotia");
6522     DeleteFileA("diclonius");
6523     DeleteFileA("echinodon");
6524     DeleteFileA("falcarius");
6525     DeleteFileA("gallimimus");
6526     DeleteFileA("hagryphus");
6527     RemoveDirectoryA("iguanodon");
6528     RemoveDirectoryA("jobaria");
6529     RemoveDirectoryA("kakuru");
6530     RemoveDirectoryA("labocania");
6531     RemoveDirectoryA("megaraptor");
6532     RemoveDirectoryA("neosodon");
6533     RemoveDirectoryA("olorotitan");
6534     RemoveDirectoryA("pantydraco");
6535     delete_component_path("{E3619EED-305A-418C-B9C7-F7D7377F0934}",
6536                           MSIINSTALLCONTEXT_MACHINE, NULL);
6537     delete_component_path("{D56B688D-542F-42Ef-90FD-B6DA76EE8119}",
6538                           MSIINSTALLCONTEXT_MACHINE, NULL);
6539     delete_component_path("{A19E16C5-C75D-4699-8111-C4338C40C3CB}",
6540                           MSIINSTALLCONTEXT_MACHINE, NULL);
6541     delete_component_path("{17762FA1-A7AE-4CC6-8827-62873C35361D}",
6542                           MSIINSTALLCONTEXT_MACHINE, NULL);
6543     delete_component_path("{8E0DA02E-F6A7-4A8F-B25D-6F564C492308}",
6544                           MSIINSTALLCONTEXT_MACHINE, NULL);
6545     delete_component_path("{243C22B1-8C51-4151-B9D1-1AE5265E079E}",
6546                           MSIINSTALLCONTEXT_MACHINE, NULL);
6547     delete_component_path("{8B1034B7-BD5E-41ac-B52C-0105D3DFD74D}",
6548                           MSIINSTALLCONTEXT_MACHINE, NULL);
6549     delete_component_path("{0B499649-197A-48EF-93D2-AF1C17ED6E90}",
6550                           MSIINSTALLCONTEXT_MACHINE, NULL);
6551     DeleteFileA(msifile);
6552 }
6553 
6554 static void set_suminfo_prop(MSIHANDLE db, DWORD prop, DWORD val)
6555 {
6556     MSIHANDLE summary;
6557     UINT r;
6558 
6559     r = MsiGetSummaryInformationA(db, NULL, 1, &summary);
6560     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6561 
6562     r = MsiSummaryInfoSetPropertyA(summary, prop, VT_I4, val, NULL, NULL);
6563     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6564 
6565     r = MsiSummaryInfoPersist(summary);
6566     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
6567 
6568     MsiCloseHandle(summary);
6569 }
6570 
6571 static void test_MsiGetSourcePath(void)
6572 {
6573     MSIHANDLE hdb, hpkg;
6574     CHAR path[MAX_PATH];
6575     CHAR cwd[MAX_PATH];
6576     CHAR subsrc[MAX_PATH];
6577     CHAR sub2[MAX_PATH];
6578     DWORD size;
6579     UINT r;
6580 
6581     lstrcpyA(cwd, CURR_DIR);
6582     if (!is_root(CURR_DIR)) lstrcatA(cwd, "\\");
6583 
6584     lstrcpyA(subsrc, cwd);
6585     lstrcatA(subsrc, "subsource");
6586     lstrcatA(subsrc, "\\");
6587 
6588     lstrcpyA(sub2, subsrc);
6589     lstrcatA(sub2, "sub2");
6590     lstrcatA(sub2, "\\");
6591 
6592     /* uncompressed source */
6593 
6594     hdb = create_package_db();
6595     ok( hdb, "failed to create database\n");
6596 
6597     set_suminfo_prop(hdb, PID_WORDCOUNT, 0);
6598 
6599     r = add_directory_entry(hdb, "'TARGETDIR', '', 'SourceDir'");
6600     ok(r == S_OK, "failed\n");
6601 
6602     r = add_directory_entry(hdb, "'SubDir', 'TARGETDIR', 'subtarget:subsource'");
6603     ok(r == S_OK, "failed\n");
6604 
6605     r = add_directory_entry(hdb, "'SubDir2', 'SubDir', 'sub2'");
6606     ok(r == S_OK, "failed\n");
6607 
6608     r = MsiDatabaseCommit(hdb);
6609     ok(r == ERROR_SUCCESS , "Failed to commit database\n");
6610 
6611     r = package_from_db(hdb, &hpkg);
6612     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
6613     {
6614         skip("Not enough rights to perform tests\n");
6615         DeleteFileA(msifile);
6616         return;
6617     }
6618     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
6619 
6620     MsiCloseHandle(hdb);
6621 
6622     /* invalid database handle */
6623     size = MAX_PATH;
6624     lstrcpyA(path, "kiwi");
6625     r = MsiGetSourcePathA(-1, "TARGETDIR", path, &size);
6626     ok(r == ERROR_INVALID_HANDLE,
6627        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
6628     ok(!lstrcmpA(path, "kiwi"),
6629        "Expected path to be unchanged, got \"%s\"\n", path);
6630     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6631 
6632     /* NULL szFolder */
6633     size = MAX_PATH;
6634     lstrcpyA(path, "kiwi");
6635     r = MsiGetSourcePathA(hpkg, NULL, path, &size);
6636     ok(r == ERROR_INVALID_PARAMETER,
6637        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6638     ok(!lstrcmpA(path, "kiwi"),
6639        "Expected path to be unchanged, got \"%s\"\n", path);
6640     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6641 
6642     /* empty szFolder */
6643     size = MAX_PATH;
6644     lstrcpyA(path, "kiwi");
6645     r = MsiGetSourcePathA(hpkg, "", path, &size);
6646     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6647     ok(!lstrcmpA(path, "kiwi"),
6648        "Expected path to be unchanged, got \"%s\"\n", path);
6649     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6650 
6651     /* try TARGETDIR */
6652     size = MAX_PATH;
6653     lstrcpyA(path, "kiwi");
6654     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6655     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6656     ok(!lstrcmpA(path, "kiwi"),
6657        "Expected path to be unchanged, got \"%s\"\n", path);
6658     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6659 
6660     size = MAX_PATH;
6661     lstrcpyA(path, "kiwi");
6662     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6663     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6664     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6665     ok(size == 0, "Expected 0, got %d\n", size);
6666 
6667     size = MAX_PATH;
6668     lstrcpyA(path, "kiwi");
6669     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6670     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6671     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6672     ok(size == 0, "Expected 0, got %d\n", size);
6673 
6674     /* try SourceDir */
6675     size = MAX_PATH;
6676     lstrcpyA(path, "kiwi");
6677     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6678     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6679     ok(!lstrcmpA(path, "kiwi"),
6680        "Expected path to be unchanged, got \"%s\"\n", path);
6681     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6682 
6683     /* try SOURCEDIR */
6684     size = MAX_PATH;
6685     lstrcpyA(path, "kiwi");
6686     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6687     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6688     ok(!lstrcmpA(path, "kiwi"),
6689        "Expected path to be unchanged, got \"%s\"\n", path);
6690     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6691 
6692     /* source path does not exist, but the property exists */
6693     size = MAX_PATH;
6694     lstrcpyA(path, "kiwi");
6695     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6696     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6697     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6698     ok(size == 0, "Expected 0, got %d\n", size);
6699 
6700     size = MAX_PATH;
6701     lstrcpyA(path, "kiwi");
6702     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6703     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6704     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6705     ok(size == 0, "Expected 0, got %d\n", size);
6706 
6707     /* try SubDir */
6708     size = MAX_PATH;
6709     lstrcpyA(path, "kiwi");
6710     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6711     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6712     ok(!lstrcmpA(path, "kiwi"),
6713        "Expected path to be unchanged, got \"%s\"\n", path);
6714     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6715 
6716     /* try SubDir2 */
6717     size = MAX_PATH;
6718     lstrcpyA(path, "kiwi");
6719     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6720     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6721     ok(!lstrcmpA(path, "kiwi"),
6722        "Expected path to be unchanged, got \"%s\"\n", path);
6723     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6724 
6725     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
6726 
6727     r = MsiDoActionA(hpkg, "CostInitialize");
6728     ok(r == ERROR_SUCCESS, "cost init failed\n");
6729 
6730     /* try TARGETDIR after CostInitialize */
6731     size = MAX_PATH;
6732     lstrcpyA(path, "kiwi");
6733     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6734     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6735     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6736     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6737 
6738     /* try SourceDir after CostInitialize */
6739     size = MAX_PATH;
6740     lstrcpyA(path, "kiwi");
6741     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6742     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6743     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6744     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6745 
6746     /* try SOURCEDIR after CostInitialize */
6747     size = MAX_PATH;
6748     lstrcpyA(path, "kiwi");
6749     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6750     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6751     ok(!lstrcmpA(path, "kiwi"),
6752        "Expected path to be unchanged, got \"%s\"\n", path);
6753     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6754 
6755     /* source path does not exist, but the property exists */
6756     size = MAX_PATH;
6757     lstrcpyA(path, "kiwi");
6758     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6759     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6760     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6761     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6762 
6763     size = MAX_PATH;
6764     lstrcpyA(path, "kiwi");
6765     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6766     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6767     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6768     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6769 
6770     /* try SubDir after CostInitialize */
6771     size = MAX_PATH;
6772     lstrcpyA(path, "kiwi");
6773     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6774     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6775     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6776     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
6777 
6778     /* try SubDir2 after CostInitialize */
6779     size = MAX_PATH;
6780     lstrcpyA(path, "kiwi");
6781     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6782     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6783     ok(!lstrcmpA(path, sub2), "Expected \"%s\", got \"%s\"\n", sub2, path);
6784     ok(size == lstrlenA(sub2), "Expected %d, got %d\n", lstrlenA(sub2), size);
6785 
6786     r = MsiDoActionA(hpkg, "ResolveSource");
6787     ok(r == ERROR_SUCCESS, "file cost failed\n");
6788 
6789     /* try TARGETDIR after ResolveSource */
6790     size = MAX_PATH;
6791     lstrcpyA(path, "kiwi");
6792     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6793     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6794     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6795     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6796 
6797     /* try SourceDir after ResolveSource */
6798     size = MAX_PATH;
6799     lstrcpyA(path, "kiwi");
6800     r = MsiGetSourcePathA(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 SOURCEDIR after ResolveSource */
6806     size = MAX_PATH;
6807     lstrcpyA(path, "kiwi");
6808     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6809     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6810     ok(!lstrcmpA(path, "kiwi"),
6811        "Expected path to be unchanged, got \"%s\"\n", path);
6812     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6813 
6814     /* source path does not exist, but the property exists */
6815     size = MAX_PATH;
6816     lstrcpyA(path, "kiwi");
6817     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6818     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6819     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6820     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6821 
6822     size = MAX_PATH;
6823     lstrcpyA(path, "kiwi");
6824     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6825     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6826     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6827     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6828 
6829     /* try SubDir after ResolveSource */
6830     size = MAX_PATH;
6831     lstrcpyA(path, "kiwi");
6832     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6833     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6834     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6835     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
6836 
6837     /* try SubDir2 after ResolveSource */
6838     size = MAX_PATH;
6839     lstrcpyA(path, "kiwi");
6840     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6841     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6842     ok(!lstrcmpA(path, sub2), "Expected \"%s\", got \"%s\"\n", sub2, path);
6843     ok(size == lstrlenA(sub2), "Expected %d, got %d\n", lstrlenA(sub2), size);
6844 
6845     r = MsiDoActionA(hpkg, "FileCost");
6846     ok(r == ERROR_SUCCESS, "file cost failed\n");
6847 
6848     /* try TARGETDIR after FileCost */
6849     size = MAX_PATH;
6850     lstrcpyA(path, "kiwi");
6851     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6852     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6853     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6854     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6855 
6856     /* try SourceDir after FileCost */
6857     size = MAX_PATH;
6858     lstrcpyA(path, "kiwi");
6859     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6860     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6861     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6862     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6863 
6864     /* try SOURCEDIR after FileCost */
6865     size = MAX_PATH;
6866     lstrcpyA(path, "kiwi");
6867     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6868     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6869     ok(!lstrcmpA(path, "kiwi"),
6870        "Expected path to be unchanged, got \"%s\"\n", path);
6871     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6872 
6873     /* source path does not exist, but the property exists */
6874     size = MAX_PATH;
6875     lstrcpyA(path, "kiwi");
6876     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6877     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6878     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6879     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6880 
6881     size = MAX_PATH;
6882     lstrcpyA(path, "kiwi");
6883     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6884     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6885     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6886     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6887 
6888     /* try SubDir after FileCost */
6889     size = MAX_PATH;
6890     lstrcpyA(path, "kiwi");
6891     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6892     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6893     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6894     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
6895 
6896     /* try SubDir2 after FileCost */
6897     size = MAX_PATH;
6898     lstrcpyA(path, "kiwi");
6899     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6900     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6901     ok(!lstrcmpA(path, sub2), "Expected \"%s\", got \"%s\"\n", sub2, path);
6902     ok(size == lstrlenA(sub2), "Expected %d, got %d\n", lstrlenA(sub2), size);
6903 
6904     r = MsiDoActionA(hpkg, "CostFinalize");
6905     ok(r == ERROR_SUCCESS, "file cost failed\n");
6906 
6907     /* try TARGETDIR after CostFinalize */
6908     size = MAX_PATH;
6909     lstrcpyA(path, "kiwi");
6910     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6911     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6912     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6913     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6914 
6915     /* try SourceDir after CostFinalize */
6916     size = MAX_PATH;
6917     lstrcpyA(path, "kiwi");
6918     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6919     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6920     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6921     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6922 
6923     /* try SOURCEDIR after CostFinalize */
6924     size = MAX_PATH;
6925     lstrcpyA(path, "kiwi");
6926     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6927     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6928     ok(!lstrcmpA(path, "kiwi"),
6929        "Expected path to be unchanged, got \"%s\"\n", path);
6930     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6931 
6932     /* source path does not exist, but the property exists */
6933     size = MAX_PATH;
6934     lstrcpyA(path, "kiwi");
6935     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6936     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6937     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6938     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6939 
6940     size = MAX_PATH;
6941     lstrcpyA(path, "kiwi");
6942     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6943     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6944     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6945     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6946 
6947     /* try SubDir after CostFinalize */
6948     size = MAX_PATH;
6949     lstrcpyA(path, "kiwi");
6950     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6951     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6952     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6953     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
6954 
6955     /* try SubDir2 after CostFinalize */
6956     size = MAX_PATH;
6957     lstrcpyA(path, "kiwi");
6958     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6959     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6960     ok(!lstrcmpA(path, sub2), "Expected \"%s\", got \"%s\"\n", sub2, path);
6961     ok(size == lstrlenA(sub2), "Expected %d, got %d\n", lstrlenA(sub2), size);
6962 
6963     /* nonexistent directory */
6964     size = MAX_PATH;
6965     lstrcpyA(path, "kiwi");
6966     r = MsiGetSourcePathA(hpkg, "IDontExist", path, &size);
6967     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6968     ok(!lstrcmpA(path, "kiwi"),
6969        "Expected path to be unchanged, got \"%s\"\n", path);
6970     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6971 
6972     /* NULL szPathBuf */
6973     size = MAX_PATH;
6974     r = MsiGetSourcePathA(hpkg, "SourceDir", NULL, &size);
6975     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6976     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6977 
6978     /* NULL pcchPathBuf */
6979     lstrcpyA(path, "kiwi");
6980     r = MsiGetSourcePathA(hpkg, "SourceDir", path, NULL);
6981     ok(r == ERROR_INVALID_PARAMETER,
6982        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6983     ok(!lstrcmpA(path, "kiwi"),
6984        "Expected path to be unchanged, got \"%s\"\n", path);
6985 
6986     /* pcchPathBuf is 0 */
6987     size = 0;
6988     lstrcpyA(path, "kiwi");
6989     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6990     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
6991     ok(!lstrcmpA(path, "kiwi"),
6992        "Expected path to be unchanged, got \"%s\"\n", path);
6993     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6994 
6995     /* pcchPathBuf does not have room for NULL terminator */
6996     size = lstrlenA(cwd);
6997     lstrcpyA(path, "kiwi");
6998     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6999     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
7000     ok(!strncmp(path, cwd, lstrlenA(cwd) - 1),
7001        "Expected path with no backslash, got \"%s\"\n", path);
7002     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7003 
7004     /* pcchPathBuf has room for NULL terminator */
7005     size = lstrlenA(cwd) + 1;
7006     lstrcpyA(path, "kiwi");
7007     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
7008     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7009     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7010     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7011 
7012     /* remove property */
7013     r = MsiSetPropertyA(hpkg, "SourceDir", NULL);
7014     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7015 
7016     /* try SourceDir again */
7017     size = MAX_PATH;
7018     lstrcpyA(path, "kiwi");
7019     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
7020     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7021     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7022     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7023 
7024     /* set property to a valid directory */
7025     r = MsiSetPropertyA(hpkg, "SOURCEDIR", cwd);
7026     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7027 
7028     /* try SOURCEDIR again */
7029     size = MAX_PATH;
7030     lstrcpyA(path, "kiwi");
7031     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7032     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7033     ok(!lstrcmpA(path, "kiwi"),
7034        "Expected path to be unchanged, got \"%s\"\n", path);
7035     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7036 
7037     MsiCloseHandle(hpkg);
7038 
7039     /* compressed source */
7040 
7041     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb);
7042     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7043 
7044     set_suminfo_prop(hdb, PID_WORDCOUNT, msidbSumInfoSourceTypeCompressed);
7045 
7046     r = package_from_db(hdb, &hpkg);
7047     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
7048 
7049     /* try TARGETDIR */
7050     size = MAX_PATH;
7051     lstrcpyA(path, "kiwi");
7052     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
7053     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7054     ok(!lstrcmpA(path, "kiwi"),
7055        "Expected path to be unchanged, got \"%s\"\n", path);
7056     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7057 
7058     /* try SourceDir */
7059     size = MAX_PATH;
7060     lstrcpyA(path, "kiwi");
7061     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
7062     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7063     ok(!lstrcmpA(path, "kiwi"),
7064        "Expected path to be unchanged, got \"%s\"\n", path);
7065     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7066 
7067     /* try SOURCEDIR */
7068     size = MAX_PATH;
7069     lstrcpyA(path, "kiwi");
7070     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7071     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7072     ok(!lstrcmpA(path, "kiwi"),
7073        "Expected path to be unchanged, got \"%s\"\n", path);
7074     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7075 
7076     /* source path nor the property exist */
7077     size = MAX_PATH;
7078     lstrcpyA(path, "kiwi");
7079     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7080     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7081     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7082     ok(size == 0, "Expected 0, got %d\n", size);
7083 
7084     size = MAX_PATH;
7085     lstrcpyA(path, "kiwi");
7086     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7087     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7088     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7089     ok(size == 0, "Expected 0, got %d\n", size);
7090 
7091     /* try SubDir */
7092     size = MAX_PATH;
7093     lstrcpyA(path, "kiwi");
7094     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7095     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7096     ok(!lstrcmpA(path, "kiwi"),
7097        "Expected path to be unchanged, got \"%s\"\n", path);
7098     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7099 
7100     /* try SubDir2 */
7101     size = MAX_PATH;
7102     lstrcpyA(path, "kiwi");
7103     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
7104     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7105     ok(!lstrcmpA(path, "kiwi"),
7106        "Expected path to be unchanged, got \"%s\"\n", path);
7107     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7108 
7109     r = MsiDoActionA(hpkg, "CostInitialize");
7110     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7111 
7112     /* try TARGETDIR after CostInitialize */
7113     size = MAX_PATH;
7114     lstrcpyA(path, "kiwi");
7115     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
7116     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7117     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7118     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7119 
7120     /* try SourceDir after CostInitialize */
7121     size = MAX_PATH;
7122     lstrcpyA(path, "kiwi");
7123     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
7124     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7125     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7126     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7127 
7128     /* try SOURCEDIR after CostInitialize */
7129     size = MAX_PATH;
7130     lstrcpyA(path, "kiwi");
7131     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7132     todo_wine
7133     {
7134         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7135         ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7136         ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7137     }
7138 
7139     /* source path does not exist, but the property exists */
7140     size = MAX_PATH;
7141     lstrcpyA(path, "kiwi");
7142     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7143     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7144     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7145     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7146 
7147     size = MAX_PATH;
7148     lstrcpyA(path, "kiwi");
7149     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7150     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7151     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7152     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7153 
7154     /* try SubDir after CostInitialize */
7155     size = MAX_PATH;
7156     lstrcpyA(path, "kiwi");
7157     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7158     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7159     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7160     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7161 
7162     /* try SubDir2 after CostInitialize */
7163     size = MAX_PATH;
7164     lstrcpyA(path, "kiwi");
7165     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
7166     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7167     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7168     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7169 
7170     r = MsiDoActionA(hpkg, "ResolveSource");
7171     ok(r == ERROR_SUCCESS, "file cost failed\n");
7172 
7173     /* try TARGETDIR after ResolveSource */
7174     size = MAX_PATH;
7175     lstrcpyA(path, "kiwi");
7176     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
7177     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7178     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7179     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7180 
7181     /* try SourceDir after ResolveSource */
7182     size = MAX_PATH;
7183     lstrcpyA(path, "kiwi");
7184     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
7185     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7186     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7187     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7188 
7189     /* try SOURCEDIR after ResolveSource */
7190     size = MAX_PATH;
7191     lstrcpyA(path, "kiwi");
7192     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7193     todo_wine
7194     {
7195         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7196         ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7197         ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7198     }
7199 
7200     /* source path and the property exist */
7201     size = MAX_PATH;
7202     lstrcpyA(path, "kiwi");
7203     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7204     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7205     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7206     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7207 
7208     size = MAX_PATH;
7209     lstrcpyA(path, "kiwi");
7210     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7211     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7212     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7213     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7214 
7215     /* try SubDir after ResolveSource */
7216     size = MAX_PATH;
7217     lstrcpyA(path, "kiwi");
7218     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7219     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7220     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7221     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7222 
7223     /* try SubDir2 after ResolveSource */
7224     size = MAX_PATH;
7225     lstrcpyA(path, "kiwi");
7226     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
7227     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7228     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7229     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7230 
7231     r = MsiDoActionA(hpkg, "FileCost");
7232     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7233 
7234     /* try TARGETDIR after CostFinalize */
7235     size = MAX_PATH;
7236     lstrcpyA(path, "kiwi");
7237     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
7238     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7239     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7240     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7241 
7242     /* try SourceDir after CostFinalize */
7243     size = MAX_PATH;
7244     lstrcpyA(path, "kiwi");
7245     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
7246     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7247     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7248     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7249 
7250     /* try SOURCEDIR after CostFinalize */
7251     size = MAX_PATH;
7252     lstrcpyA(path, "kiwi");
7253     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7254     todo_wine
7255     {
7256         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7257         ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7258         ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7259     }
7260 
7261     /* source path and the property exist */
7262     size = MAX_PATH;
7263     lstrcpyA(path, "kiwi");
7264     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7265     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7266     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7267     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7268 
7269     size = MAX_PATH;
7270     lstrcpyA(path, "kiwi");
7271     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7272     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7273     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7274     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7275 
7276     /* try SubDir after CostFinalize */
7277     size = MAX_PATH;
7278     lstrcpyA(path, "kiwi");
7279     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7280     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7281     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7282     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7283 
7284     /* try SubDir2 after CostFinalize */
7285     size = MAX_PATH;
7286     lstrcpyA(path, "kiwi");
7287     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
7288     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7289     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7290     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7291 
7292     r = MsiDoActionA(hpkg, "CostFinalize");
7293     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7294 
7295     /* try TARGETDIR after CostFinalize */
7296     size = MAX_PATH;
7297     lstrcpyA(path, "kiwi");
7298     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
7299     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7300     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7301     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7302 
7303     /* try SourceDir after CostFinalize */
7304     size = MAX_PATH;
7305     lstrcpyA(path, "kiwi");
7306     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
7307     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7308     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7309     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7310 
7311     /* try SOURCEDIR after CostFinalize */
7312     size = MAX_PATH;
7313     lstrcpyA(path, "kiwi");
7314     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7315     todo_wine
7316     {
7317         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7318         ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7319         ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7320     }
7321 
7322     /* source path and the property exist */
7323     size = MAX_PATH;
7324     lstrcpyA(path, "kiwi");
7325     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7326     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7327     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7328     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7329 
7330     size = MAX_PATH;
7331     lstrcpyA(path, "kiwi");
7332     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7333     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7334     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7335     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7336 
7337     /* try SubDir after CostFinalize */
7338     size = MAX_PATH;
7339     lstrcpyA(path, "kiwi");
7340     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7341     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7342     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7343     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7344 
7345     /* try SubDir2 after CostFinalize */
7346     size = MAX_PATH;
7347     lstrcpyA(path, "kiwi");
7348     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
7349     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7350     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7351     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7352 
7353     MsiCloseHandle(hpkg);
7354     DeleteFileA(msifile);
7355 }
7356 
7357 static void test_shortlongsource(void)
7358 {
7359     MSIHANDLE hdb, hpkg;
7360     CHAR path[MAX_PATH];
7361     CHAR cwd[MAX_PATH];
7362     CHAR subsrc[MAX_PATH];
7363     DWORD size;
7364     UINT r;
7365 
7366     lstrcpyA(cwd, CURR_DIR);
7367     if (!is_root(CURR_DIR)) lstrcatA(cwd, "\\");
7368 
7369     lstrcpyA(subsrc, cwd);
7370     lstrcatA(subsrc, "long");
7371     lstrcatA(subsrc, "\\");
7372 
7373     /* long file names */
7374 
7375     hdb = create_package_db();
7376     ok( hdb, "failed to create database\n");
7377 
7378     set_suminfo_prop(hdb, PID_WORDCOUNT, 0);
7379 
7380     r = add_directory_entry(hdb, "'TARGETDIR', '', 'SourceDir'");
7381     ok(r == S_OK, "failed\n");
7382 
7383     r = add_directory_entry(hdb, "'SubDir', 'TARGETDIR', 'short|long'");
7384     ok(r == S_OK, "failed\n");
7385 
7386     /* CostInitialize:short */
7387     r = add_directory_entry(hdb, "'SubDir2', 'TARGETDIR', 'one|two'");
7388     ok(r == S_OK, "failed\n");
7389 
7390     /* CostInitialize:long */
7391     r = add_directory_entry(hdb, "'SubDir3', 'TARGETDIR', 'three|four'");
7392     ok(r == S_OK, "failed\n");
7393 
7394     /* FileCost:short */
7395     r = add_directory_entry(hdb, "'SubDir4', 'TARGETDIR', 'five|six'");
7396     ok(r == S_OK, "failed\n");
7397 
7398     /* FileCost:long */
7399     r = add_directory_entry(hdb, "'SubDir5', 'TARGETDIR', 'seven|eight'");
7400     ok(r == S_OK, "failed\n");
7401 
7402     /* CostFinalize:short */
7403     r = add_directory_entry(hdb, "'SubDir6', 'TARGETDIR', 'nine|ten'");
7404     ok(r == S_OK, "failed\n");
7405 
7406     /* CostFinalize:long */
7407     r = add_directory_entry(hdb, "'SubDir7', 'TARGETDIR', 'eleven|twelve'");
7408     ok(r == S_OK, "failed\n");
7409 
7410     MsiDatabaseCommit(hdb);
7411 
7412     r = package_from_db(hdb, &hpkg);
7413     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
7414     {
7415         skip("Not enough rights to perform tests\n");
7416         DeleteFileA(msifile);
7417         return;
7418     }
7419     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
7420 
7421     MsiCloseHandle(hdb);
7422 
7423     CreateDirectoryA("one", NULL);
7424     CreateDirectoryA("four", NULL);
7425 
7426     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
7427 
7428     r = MsiDoActionA(hpkg, "CostInitialize");
7429     ok(r == ERROR_SUCCESS, "file cost failed\n");
7430 
7431     CreateDirectoryA("five", NULL);
7432     CreateDirectoryA("eight", NULL);
7433 
7434     r = MsiDoActionA(hpkg, "FileCost");
7435     ok(r == ERROR_SUCCESS, "file cost failed\n");
7436 
7437     CreateDirectoryA("nine", NULL);
7438     CreateDirectoryA("twelve", NULL);
7439 
7440     r = MsiDoActionA(hpkg, "CostFinalize");
7441     ok(r == ERROR_SUCCESS, "file cost failed\n");
7442 
7443     /* neither short nor long source directories exist */
7444     size = MAX_PATH;
7445     lstrcpyA(path, "kiwi");
7446     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7447     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7448     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7449     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7450 
7451     CreateDirectoryA("short", NULL);
7452 
7453     /* short source directory exists */
7454     size = MAX_PATH;
7455     lstrcpyA(path, "kiwi");
7456     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7457     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7458     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7459     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7460 
7461     CreateDirectoryA("long", NULL);
7462 
7463     /* both short and long source directories exist */
7464     size = MAX_PATH;
7465     lstrcpyA(path, "kiwi");
7466     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7467     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7468     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7469     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7470 
7471     lstrcpyA(subsrc, cwd);
7472     lstrcatA(subsrc, "two");
7473     lstrcatA(subsrc, "\\");
7474 
7475     /* short dir exists before CostInitialize */
7476     size = MAX_PATH;
7477     lstrcpyA(path, "kiwi");
7478     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
7479     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7480     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7481     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7482 
7483     lstrcpyA(subsrc, cwd);
7484     lstrcatA(subsrc, "four");
7485     lstrcatA(subsrc, "\\");
7486 
7487     /* long dir exists before CostInitialize */
7488     size = MAX_PATH;
7489     lstrcpyA(path, "kiwi");
7490     r = MsiGetSourcePathA(hpkg, "SubDir3", path, &size);
7491     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7492     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7493     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7494 
7495     lstrcpyA(subsrc, cwd);
7496     lstrcatA(subsrc, "six");
7497     lstrcatA(subsrc, "\\");
7498 
7499     /* short dir exists before FileCost */
7500     size = MAX_PATH;
7501     lstrcpyA(path, "kiwi");
7502     r = MsiGetSourcePathA(hpkg, "SubDir4", path, &size);
7503     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7504     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7505     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7506 
7507     lstrcpyA(subsrc, cwd);
7508     lstrcatA(subsrc, "eight");
7509     lstrcatA(subsrc, "\\");
7510 
7511     /* long dir exists before FileCost */
7512     size = MAX_PATH;
7513     lstrcpyA(path, "kiwi");
7514     r = MsiGetSourcePathA(hpkg, "SubDir5", path, &size);
7515     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7516     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7517     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7518 
7519     lstrcpyA(subsrc, cwd);
7520     lstrcatA(subsrc, "ten");
7521     lstrcatA(subsrc, "\\");
7522 
7523     /* short dir exists before CostFinalize */
7524     size = MAX_PATH;
7525     lstrcpyA(path, "kiwi");
7526     r = MsiGetSourcePathA(hpkg, "SubDir6", path, &size);
7527     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7528     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7529     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7530 
7531     lstrcpyA(subsrc, cwd);
7532     lstrcatA(subsrc, "twelve");
7533     lstrcatA(subsrc, "\\");
7534 
7535     /* long dir exists before CostFinalize */
7536     size = MAX_PATH;
7537     lstrcpyA(path, "kiwi");
7538     r = MsiGetSourcePathA(hpkg, "SubDir7", path, &size);
7539     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7540     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7541     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7542 
7543     MsiCloseHandle(hpkg);
7544     RemoveDirectoryA("short");
7545     RemoveDirectoryA("long");
7546     RemoveDirectoryA("one");
7547     RemoveDirectoryA("four");
7548     RemoveDirectoryA("five");
7549     RemoveDirectoryA("eight");
7550     RemoveDirectoryA("nine");
7551     RemoveDirectoryA("twelve");
7552 
7553     /* short file names */
7554 
7555     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb);
7556     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7557 
7558     set_suminfo_prop(hdb, PID_WORDCOUNT, msidbSumInfoSourceTypeSFN);
7559 
7560     r = package_from_db(hdb, &hpkg);
7561     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
7562 
7563     MsiCloseHandle(hdb);
7564 
7565     CreateDirectoryA("one", NULL);
7566     CreateDirectoryA("four", NULL);
7567 
7568     r = MsiDoActionA(hpkg, "CostInitialize");
7569     ok(r == ERROR_SUCCESS, "file cost failed\n");
7570 
7571     CreateDirectoryA("five", NULL);
7572     CreateDirectoryA("eight", NULL);
7573 
7574     r = MsiDoActionA(hpkg, "FileCost");
7575     ok(r == ERROR_SUCCESS, "file cost failed\n");
7576 
7577     CreateDirectoryA("nine", NULL);
7578     CreateDirectoryA("twelve", NULL);
7579 
7580     r = MsiDoActionA(hpkg, "CostFinalize");
7581     ok(r == ERROR_SUCCESS, "file cost failed\n");
7582 
7583     lstrcpyA(subsrc, cwd);
7584     lstrcatA(subsrc, "short");
7585     lstrcatA(subsrc, "\\");
7586 
7587     /* neither short nor long source directories exist */
7588     size = MAX_PATH;
7589     lstrcpyA(path, "kiwi");
7590     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7591     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7592     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7593     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7594 
7595     CreateDirectoryA("short", NULL);
7596 
7597     /* short source directory exists */
7598     size = MAX_PATH;
7599     lstrcpyA(path, "kiwi");
7600     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7601     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7602     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7603     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7604 
7605     CreateDirectoryA("long", NULL);
7606 
7607     /* both short and long source directories exist */
7608     size = MAX_PATH;
7609     lstrcpyA(path, "kiwi");
7610     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7611     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7612     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7613     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7614 
7615     lstrcpyA(subsrc, cwd);
7616     lstrcatA(subsrc, "one");
7617     lstrcatA(subsrc, "\\");
7618 
7619     /* short dir exists before CostInitialize */
7620     size = MAX_PATH;
7621     lstrcpyA(path, "kiwi");
7622     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
7623     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7624     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7625     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7626 
7627     lstrcpyA(subsrc, cwd);
7628     lstrcatA(subsrc, "three");
7629     lstrcatA(subsrc, "\\");
7630 
7631     /* long dir exists before CostInitialize */
7632     size = MAX_PATH;
7633     lstrcpyA(path, "kiwi");
7634     r = MsiGetSourcePathA(hpkg, "SubDir3", path, &size);
7635     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7636     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7637     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7638 
7639     lstrcpyA(subsrc, cwd);
7640     lstrcatA(subsrc, "five");
7641     lstrcatA(subsrc, "\\");
7642 
7643     /* short dir exists before FileCost */
7644     size = MAX_PATH;
7645     lstrcpyA(path, "kiwi");
7646     r = MsiGetSourcePathA(hpkg, "SubDir4", path, &size);
7647     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7648     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7649     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7650 
7651     lstrcpyA(subsrc, cwd);
7652     lstrcatA(subsrc, "seven");
7653     lstrcatA(subsrc, "\\");
7654 
7655     /* long dir exists before FileCost */
7656     size = MAX_PATH;
7657     lstrcpyA(path, "kiwi");
7658     r = MsiGetSourcePathA(hpkg, "SubDir5", path, &size);
7659     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7660     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7661     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7662 
7663     lstrcpyA(subsrc, cwd);
7664     lstrcatA(subsrc, "nine");
7665     lstrcatA(subsrc, "\\");
7666 
7667     /* short dir exists before CostFinalize */
7668     size = MAX_PATH;
7669     lstrcpyA(path, "kiwi");
7670     r = MsiGetSourcePathA(hpkg, "SubDir6", path, &size);
7671     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7672     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7673     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7674 
7675     lstrcpyA(subsrc, cwd);
7676     lstrcatA(subsrc, "eleven");
7677     lstrcatA(subsrc, "\\");
7678 
7679     /* long dir exists before CostFinalize */
7680     size = MAX_PATH;
7681     lstrcpyA(path, "kiwi");
7682     r = MsiGetSourcePathA(hpkg, "SubDir7", path, &size);
7683     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7684     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7685     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7686 
7687     MsiCloseHandle(hpkg);
7688     RemoveDirectoryA("short");
7689     RemoveDirectoryA("long");
7690     RemoveDirectoryA("one");
7691     RemoveDirectoryA("four");
7692     RemoveDirectoryA("five");
7693     RemoveDirectoryA("eight");
7694     RemoveDirectoryA("nine");
7695     RemoveDirectoryA("twelve");
7696     DeleteFileA(msifile);
7697 }
7698 
7699 static void test_sourcedir(void)
7700 {
7701     MSIHANDLE hdb, hpkg;
7702     CHAR package[12];
7703     CHAR path[MAX_PATH];
7704     CHAR cwd[MAX_PATH];
7705     CHAR subsrc[MAX_PATH];
7706     DWORD size;
7707     UINT r;
7708 
7709     lstrcpyA(cwd, CURR_DIR);
7710     if (!is_root(CURR_DIR)) lstrcatA(cwd, "\\");
7711 
7712     lstrcpyA(subsrc, cwd);
7713     lstrcatA(subsrc, "long");
7714     lstrcatA(subsrc, "\\");
7715 
7716     hdb = create_package_db();
7717     ok( hdb, "failed to create database\n");
7718 
7719     r = add_directory_entry(hdb, "'TARGETDIR', '', 'SourceDir'");
7720     ok(r == S_OK, "failed\n");
7721 
7722     sprintf(package, "#%u", hdb);
7723     r = MsiOpenPackageA(package, &hpkg);
7724     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
7725     {
7726         skip("Not enough rights to perform tests\n");
7727         goto error;
7728     }
7729     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7730 
7731     /* properties only */
7732 
7733     /* SourceDir prop */
7734     size = MAX_PATH;
7735     lstrcpyA(path, "kiwi");
7736     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7737     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7738     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7739     ok(size == 0, "Expected 0, got %d\n", size);
7740 
7741     /* SOURCEDIR prop */
7742     size = MAX_PATH;
7743     lstrcpyA(path, "kiwi");
7744     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7745     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7746     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7747     ok(size == 0, "Expected 0, got %d\n", size);
7748 
7749     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
7750 
7751     r = MsiDoActionA(hpkg, "CostInitialize");
7752     ok(r == ERROR_SUCCESS, "file cost failed\n");
7753 
7754     /* SourceDir after CostInitialize */
7755     size = MAX_PATH;
7756     lstrcpyA(path, "kiwi");
7757     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7758     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7759     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7760     ok(size == 0, "Expected 0, got %d\n", size);
7761 
7762     /* SOURCEDIR after CostInitialize */
7763     size = MAX_PATH;
7764     lstrcpyA(path, "kiwi");
7765     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7766     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7767     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7768     ok(size == 0, "Expected 0, got %d\n", size);
7769 
7770     r = MsiDoActionA(hpkg, "FileCost");
7771     ok(r == ERROR_SUCCESS, "file cost failed\n");
7772 
7773     /* SourceDir after FileCost */
7774     size = MAX_PATH;
7775     lstrcpyA(path, "kiwi");
7776     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7777     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7778     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7779     ok(size == 0, "Expected 0, got %d\n", size);
7780 
7781     /* SOURCEDIR after FileCost */
7782     size = MAX_PATH;
7783     lstrcpyA(path, "kiwi");
7784     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7785     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7786     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7787     ok(size == 0, "Expected 0, got %d\n", size);
7788 
7789     r = MsiDoActionA(hpkg, "CostFinalize");
7790     ok(r == ERROR_SUCCESS, "file cost failed\n");
7791 
7792     /* SourceDir after CostFinalize */
7793     size = MAX_PATH;
7794     lstrcpyA(path, "kiwi");
7795     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7796     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7797     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7798     ok(size == 0, "Expected 0, got %d\n", size);
7799 
7800     /* SOURCEDIR after CostFinalize */
7801     size = MAX_PATH;
7802     lstrcpyA(path, "kiwi");
7803     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7804     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7805     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7806     ok(size == 0, "Expected 0, got %d\n", size);
7807 
7808     size = MAX_PATH;
7809     lstrcpyA(path, "kiwi");
7810     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7811     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7812     ok(!lstrcmpA(path, "kiwi"), "Expected \"kiwi\", got \"%s\"\n", path);
7813     ok(size == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, size);
7814 
7815     /* SOURCEDIR after calling MsiGetSourcePath */
7816     size = MAX_PATH;
7817     lstrcpyA(path, "kiwi");
7818     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7819     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7820     todo_wine {
7821     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7822     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7823     }
7824 
7825     r = MsiDoActionA(hpkg, "ResolveSource");
7826     ok(r == ERROR_SUCCESS, "file cost failed\n");
7827 
7828     /* SourceDir after ResolveSource */
7829     size = MAX_PATH;
7830     lstrcpyA(path, "kiwi");
7831     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7832     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7833     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7834     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7835 
7836     /* SOURCEDIR after ResolveSource */
7837     size = MAX_PATH;
7838     lstrcpyA(path, "kiwi");
7839     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7840     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7841     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7842     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7843 
7844     /* random casing */
7845     size = MAX_PATH;
7846     lstrcpyA(path, "kiwi");
7847     r = MsiGetPropertyA(hpkg, "SoUrCeDiR", path, &size);
7848     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7849     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7850     ok(size == 0, "Expected 0, got %d\n", size);
7851 
7852     MsiCloseHandle(hpkg);
7853 
7854     /* reset the package state */
7855     sprintf(package, "#%i", hdb);
7856     r = MsiOpenPackageA(package, &hpkg);
7857     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7858 
7859     /* test how MsiGetSourcePath affects the properties */
7860 
7861     /* SourceDir prop */
7862     size = MAX_PATH;
7863     lstrcpyA(path, "kiwi");
7864     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7865     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7866     todo_wine
7867     {
7868         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7869         ok(size == 0, "Expected 0, got %d\n", size);
7870     }
7871 
7872     size = MAX_PATH;
7873     lstrcpyA(path, "kiwi");
7874     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
7875     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7876     ok(!lstrcmpA(path, "kiwi"),
7877        "Expected path to be unchanged, got \"%s\"\n", path);
7878     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7879 
7880     /* SourceDir after MsiGetSourcePath */
7881     size = MAX_PATH;
7882     lstrcpyA(path, "kiwi");
7883     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7884     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7885     todo_wine
7886     {
7887         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7888         ok(size == 0, "Expected 0, got %d\n", size);
7889     }
7890 
7891     /* SOURCEDIR prop */
7892     size = MAX_PATH;
7893     lstrcpyA(path, "kiwi");
7894     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7895     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7896     todo_wine
7897     {
7898         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7899         ok(size == 0, "Expected 0, got %d\n", size);
7900     }
7901 
7902     size = MAX_PATH;
7903     lstrcpyA(path, "kiwi");
7904     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7905     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7906     ok(!lstrcmpA(path, "kiwi"),
7907        "Expected path to be unchanged, got \"%s\"\n", path);
7908     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7909 
7910     /* SOURCEDIR prop after MsiGetSourcePath */
7911     size = MAX_PATH;
7912     lstrcpyA(path, "kiwi");
7913     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7914     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7915     todo_wine
7916     {
7917         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7918         ok(size == 0, "Expected 0, got %d\n", size);
7919     }
7920 
7921     r = MsiDoActionA(hpkg, "CostInitialize");
7922     ok(r == ERROR_SUCCESS, "file cost failed\n");
7923 
7924     /* SourceDir after CostInitialize */
7925     size = MAX_PATH;
7926     lstrcpyA(path, "kiwi");
7927     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7928     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7929     todo_wine
7930     {
7931         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7932         ok(size == 0, "Expected 0, got %d\n", size);
7933     }
7934 
7935     size = MAX_PATH;
7936     lstrcpyA(path, "kiwi");
7937     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
7938     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7939     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7940     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7941 
7942     /* SourceDir after MsiGetSourcePath */
7943     size = MAX_PATH;
7944     lstrcpyA(path, "kiwi");
7945     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7946     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7947     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7948     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7949 
7950     /* SOURCEDIR after CostInitialize */
7951     size = MAX_PATH;
7952     lstrcpyA(path, "kiwi");
7953     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7954     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7955     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7956     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7957 
7958     /* SOURCEDIR source path still does not exist */
7959     size = MAX_PATH;
7960     lstrcpyA(path, "kiwi");
7961     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7962     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7963     ok(!lstrcmpA(path, "kiwi"),
7964        "Expected path to be unchanged, got \"%s\"\n", path);
7965     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7966 
7967     r = MsiDoActionA(hpkg, "FileCost");
7968     ok(r == ERROR_SUCCESS, "file cost failed\n");
7969 
7970     /* SourceDir after FileCost */
7971     size = MAX_PATH;
7972     lstrcpyA(path, "kiwi");
7973     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7974     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7975     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7976     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7977 
7978     /* SOURCEDIR after FileCost */
7979     size = MAX_PATH;
7980     lstrcpyA(path, "kiwi");
7981     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7982     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7983     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7984     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7985 
7986     /* SOURCEDIR source path still does not exist */
7987     size = MAX_PATH;
7988     lstrcpyA(path, "kiwi");
7989     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7990     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7991     ok(!lstrcmpA(path, "kiwi"),
7992        "Expected path to be unchanged, got \"%s\"\n", path);
7993     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7994 
7995     r = MsiDoActionA(hpkg, "CostFinalize");
7996     ok(r == ERROR_SUCCESS, "file cost failed\n");
7997 
7998     /* SourceDir after CostFinalize */
7999     size = MAX_PATH;
8000     lstrcpyA(path, "kiwi");
8001     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
8002     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8003     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
8004     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
8005 
8006     /* SOURCEDIR after CostFinalize */
8007     size = MAX_PATH;
8008     lstrcpyA(path, "kiwi");
8009     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
8010     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8011     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
8012     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
8013 
8014     /* SOURCEDIR source path still does not exist */
8015     size = MAX_PATH;
8016     lstrcpyA(path, "kiwi");
8017     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
8018     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
8019     ok(!lstrcmpA(path, "kiwi"),
8020        "Expected path to be unchanged, got \"%s\"\n", path);
8021     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8022 
8023     r = MsiDoActionA(hpkg, "ResolveSource");
8024     ok(r == ERROR_SUCCESS, "file cost failed\n");
8025 
8026     /* SourceDir after ResolveSource */
8027     size = MAX_PATH;
8028     lstrcpyA(path, "kiwi");
8029     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
8030     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8031     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
8032     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
8033 
8034     /* SOURCEDIR after ResolveSource */
8035     size = MAX_PATH;
8036     lstrcpyA(path, "kiwi");
8037     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
8038     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8039     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
8040     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
8041 
8042     /* SOURCEDIR source path still does not exist */
8043     size = MAX_PATH;
8044     lstrcpyA(path, "kiwi");
8045     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
8046     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
8047     ok(!lstrcmpA(path, "kiwi"),
8048        "Expected path to be unchanged, got \"%s\"\n", path);
8049     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8050 
8051     MsiCloseHandle(hpkg);
8052 
8053 error:
8054     MsiCloseHandle(hdb);
8055     DeleteFileA(msifile);
8056 }
8057 
8058 struct access_res
8059 {
8060     BOOL gothandle;
8061     DWORD lasterr;
8062     BOOL ignore;
8063 };
8064 
8065 static const struct access_res create[16] =
8066 {
8067     { TRUE, ERROR_SUCCESS, TRUE },
8068     { TRUE, ERROR_SUCCESS, TRUE },
8069     { TRUE, ERROR_SUCCESS, FALSE },
8070     { TRUE, ERROR_SUCCESS, FALSE },
8071     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
8072     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
8073     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
8074     { TRUE, ERROR_SUCCESS, FALSE },
8075     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
8076     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
8077     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
8078     { TRUE, ERROR_SUCCESS, TRUE },
8079     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
8080     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
8081     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
8082     { TRUE, ERROR_SUCCESS, TRUE }
8083 };
8084 
8085 static const struct access_res create_commit[16] =
8086 {
8087     { TRUE, ERROR_SUCCESS, TRUE },
8088     { TRUE, ERROR_SUCCESS, TRUE },
8089     { TRUE, ERROR_SUCCESS, FALSE },
8090     { TRUE, ERROR_SUCCESS, FALSE },
8091     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
8092     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
8093     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
8094     { TRUE, ERROR_SUCCESS, FALSE },
8095     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
8096     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
8097     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
8098     { TRUE, ERROR_SUCCESS, TRUE },
8099     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
8100     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
8101     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
8102     { TRUE, ERROR_SUCCESS, TRUE }
8103 };
8104 
8105 static const struct access_res create_close[16] =
8106 {
8107     { TRUE, ERROR_SUCCESS, FALSE },
8108     { TRUE, ERROR_SUCCESS, FALSE },
8109     { TRUE, ERROR_SUCCESS, FALSE },
8110     { TRUE, ERROR_SUCCESS, FALSE },
8111     { TRUE, ERROR_SUCCESS, FALSE },
8112     { TRUE, ERROR_SUCCESS, FALSE },
8113     { TRUE, ERROR_SUCCESS, FALSE },
8114     { TRUE, ERROR_SUCCESS, FALSE },
8115     { TRUE, ERROR_SUCCESS, FALSE },
8116     { TRUE, ERROR_SUCCESS, FALSE },
8117     { TRUE, ERROR_SUCCESS, FALSE },
8118     { TRUE, ERROR_SUCCESS, FALSE },
8119     { TRUE, ERROR_SUCCESS, FALSE },
8120     { TRUE, ERROR_SUCCESS, FALSE },
8121     { TRUE, ERROR_SUCCESS, FALSE },
8122     { TRUE, ERROR_SUCCESS }
8123 };
8124 
8125 static void _test_file_access(LPCSTR file, const struct access_res *ares, DWORD line)
8126 {
8127     DWORD access = 0, share = 0;
8128     DWORD lasterr;
8129     HANDLE hfile;
8130     int i, j, idx = 0;
8131 
8132     for (i = 0; i < 4; i++)
8133     {
8134         if (i == 0) access = 0;
8135         if (i == 1) access = GENERIC_READ;
8136         if (i == 2) access = GENERIC_WRITE;
8137         if (i == 3) access = GENERIC_READ | GENERIC_WRITE;
8138 
8139         for (j = 0; j < 4; j++)
8140         {
8141             if (ares[idx].ignore)
8142                 continue;
8143 
8144             if (j == 0) share = 0;
8145             if (j == 1) share = FILE_SHARE_READ;
8146             if (j == 2) share = FILE_SHARE_WRITE;
8147             if (j == 3) share = FILE_SHARE_READ | FILE_SHARE_WRITE;
8148 
8149             SetLastError(0xdeadbeef);
8150             hfile = CreateFileA(file, access, share, NULL, OPEN_EXISTING,
8151                                 FILE_ATTRIBUTE_NORMAL, 0);
8152             lasterr = GetLastError();
8153 
8154             ok((hfile != INVALID_HANDLE_VALUE) == ares[idx].gothandle,
8155                "(%d, handle, %d): Expected %d, got %d\n",
8156                line, idx, ares[idx].gothandle,
8157                (hfile != INVALID_HANDLE_VALUE));
8158 
8159             ok(lasterr == ares[idx].lasterr, "(%d, lasterr, %d): Expected %d, got %d\n",
8160                line, idx, ares[idx].lasterr, lasterr);
8161 
8162             CloseHandle(hfile);
8163             idx++;
8164         }
8165     }
8166 }
8167 
8168 #define test_file_access(file, ares) _test_file_access(file, ares, __LINE__)
8169 
8170 static void test_access(void)
8171 {
8172     MSIHANDLE hdb;
8173     UINT r;
8174 
8175     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
8176     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8177 
8178     test_file_access(msifile, create);
8179 
8180     r = MsiDatabaseCommit(hdb);
8181     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8182 
8183     test_file_access(msifile, create_commit);
8184     MsiCloseHandle(hdb);
8185 
8186     test_file_access(msifile, create_close);
8187     DeleteFileA(msifile);
8188 
8189     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATEDIRECT, &hdb);
8190     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8191 
8192     test_file_access(msifile, create);
8193 
8194     r = MsiDatabaseCommit(hdb);
8195     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8196 
8197     test_file_access(msifile, create_commit);
8198     MsiCloseHandle(hdb);
8199 
8200     test_file_access(msifile, create_close);
8201     DeleteFileA(msifile);
8202 }
8203 
8204 static void test_emptypackage(void)
8205 {
8206     MSIHANDLE hpkg = 0, hdb = 0, hsuminfo = 0;
8207     MSIHANDLE hview = 0, hrec = 0;
8208     MSICONDITION condition;
8209     CHAR buffer[MAX_PATH];
8210     DWORD size;
8211     UINT r;
8212 
8213     r = MsiOpenPackageA("", &hpkg);
8214     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
8215     {
8216         skip("Not enough rights to perform tests\n");
8217         return;
8218     }
8219     todo_wine
8220     {
8221         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8222     }
8223 
8224     hdb = MsiGetActiveDatabase(hpkg);
8225     todo_wine
8226     {
8227         ok(hdb != 0, "Expected a valid database handle\n");
8228     }
8229 
8230     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Tables`", &hview);
8231     todo_wine
8232     {
8233         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8234     }
8235     r = MsiViewExecute(hview, 0);
8236     todo_wine
8237     {
8238         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8239     }
8240 
8241     r = MsiViewFetch(hview, &hrec);
8242     todo_wine
8243     {
8244         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8245     }
8246 
8247     buffer[0] = 0;
8248     size = MAX_PATH;
8249     r = MsiRecordGetStringA(hrec, 1, buffer, &size);
8250     todo_wine
8251     {
8252         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8253         ok(!lstrcmpA(buffer, "_Property"),
8254            "Expected \"_Property\", got \"%s\"\n", buffer);
8255     }
8256 
8257     MsiCloseHandle(hrec);
8258 
8259     r = MsiViewFetch(hview, &hrec);
8260     todo_wine
8261     {
8262         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8263     }
8264 
8265     size = MAX_PATH;
8266     r = MsiRecordGetStringA(hrec, 1, buffer, &size);
8267     todo_wine
8268     {
8269         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8270         ok(!lstrcmpA(buffer, "#_FolderCache"),
8271            "Expected \"_Property\", got \"%s\"\n", buffer);
8272     }
8273 
8274     MsiCloseHandle(hrec);
8275     MsiViewClose(hview);
8276     MsiCloseHandle(hview);
8277 
8278     condition = MsiDatabaseIsTablePersistentA(hdb, "_Property");
8279     todo_wine
8280     {
8281         ok(condition == MSICONDITION_FALSE,
8282            "Expected MSICONDITION_FALSE, got %d\n", condition);
8283     }
8284 
8285     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Property`", &hview);
8286     todo_wine
8287     {
8288         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8289     }
8290     r = MsiViewExecute(hview, 0);
8291     todo_wine
8292     {
8293         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8294     }
8295 
8296     /* _Property table is not empty */
8297     r = MsiViewFetch(hview, &hrec);
8298     todo_wine
8299     {
8300         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8301     }
8302 
8303     MsiCloseHandle(hrec);
8304     MsiViewClose(hview);
8305     MsiCloseHandle(hview);
8306 
8307     condition = MsiDatabaseIsTablePersistentA(hdb, "#_FolderCache");
8308     todo_wine
8309     {
8310         ok(condition == MSICONDITION_FALSE,
8311            "Expected MSICONDITION_FALSE, got %d\n", condition);
8312     }
8313 
8314     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `#_FolderCache`", &hview);
8315     todo_wine
8316     {
8317         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8318     }
8319     r = MsiViewExecute(hview, 0);
8320     todo_wine
8321     {
8322         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8323     }
8324 
8325     /* #_FolderCache is not empty */
8326     r = MsiViewFetch(hview, &hrec);
8327     todo_wine
8328     {
8329         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8330     }
8331 
8332     MsiCloseHandle(hrec);
8333     MsiViewClose(hview);
8334     MsiCloseHandle(hview);
8335 
8336     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Streams`", &hview);
8337     todo_wine
8338     {
8339         ok(r == ERROR_BAD_QUERY_SYNTAX,
8340            "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8341     }
8342 
8343     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Storages`", &hview);
8344     todo_wine
8345     {
8346         ok(r == ERROR_BAD_QUERY_SYNTAX,
8347            "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8348     }
8349 
8350     r = MsiGetSummaryInformationA(hdb, NULL, 0, &hsuminfo);
8351     todo_wine
8352     {
8353         ok(r == ERROR_INSTALL_PACKAGE_INVALID,
8354            "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
8355     }
8356 
8357     MsiCloseHandle(hsuminfo);
8358 
8359     r = MsiDatabaseCommit(hdb);
8360     todo_wine
8361     {
8362         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8363     }
8364 
8365     MsiCloseHandle(hdb);
8366     MsiCloseHandle(hpkg);
8367 }
8368 
8369 static void test_MsiGetProductProperty(void)
8370 {
8371     static const WCHAR prodcode_propW[] = {'P','r','o','d','u','c','t','C','o','d','e',0};
8372     static const WCHAR nonexistentW[] = {'I','D','o','n','t','E','x','i','s','t',0};
8373     static const WCHAR newpropW[] = {'N','e','w','P','r','o','p','e','r','t','y',0};
8374     static const WCHAR appleW[] = {'a','p','p','l','e',0};
8375     static const WCHAR emptyW[] = {0};
8376     WCHAR valW[MAX_PATH];
8377     MSIHANDLE hprod, hdb;
8378     CHAR val[MAX_PATH];
8379     CHAR path[MAX_PATH];
8380     CHAR query[MAX_PATH];
8381     CHAR keypath[MAX_PATH*2];
8382     CHAR prodcode[MAX_PATH];
8383     WCHAR prodcodeW[MAX_PATH];
8384     CHAR prod_squashed[MAX_PATH];
8385     WCHAR prod_squashedW[MAX_PATH];
8386     HKEY prodkey, userkey, props;
8387     DWORD size;
8388     LONG res;
8389     UINT r;
8390     REGSAM access = KEY_ALL_ACCESS;
8391 
8392     GetCurrentDirectoryA(MAX_PATH, path);
8393     lstrcatA(path, "\\");
8394 
8395     create_test_guid(prodcode, prod_squashed);
8396     MultiByteToWideChar(CP_ACP, 0, prodcode, -1, prodcodeW, MAX_PATH);
8397     squash_guid(prodcodeW, prod_squashedW);
8398 
8399     if (is_wow64)
8400         access |= KEY_WOW64_64KEY;
8401 
8402     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
8403     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8404 
8405     r = MsiDatabaseCommit(hdb);
8406     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8407 
8408     r = set_summary_info(hdb);
8409     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8410 
8411     r = run_query(hdb,
8412             "CREATE TABLE `Directory` ( "
8413             "`Directory` CHAR(255) NOT NULL, "
8414             "`Directory_Parent` CHAR(255), "
8415             "`DefaultDir` CHAR(255) NOT NULL "
8416             "PRIMARY KEY `Directory`)");
8417     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8418 
8419     r = run_query(hdb,
8420             "CREATE TABLE `Property` ( "
8421             "`Property` CHAR(72) NOT NULL, "
8422             "`Value` CHAR(255) "
8423             "PRIMARY KEY `Property`)");
8424     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8425 
8426     sprintf(query, "INSERT INTO `Property` "
8427             "(`Property`, `Value`) "
8428             "VALUES( 'ProductCode', '%s' )", prodcode);
8429     r = run_query(hdb, query);
8430     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8431 
8432     r = MsiDatabaseCommit(hdb);
8433     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8434 
8435     MsiCloseHandle(hdb);
8436 
8437     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
8438     lstrcatA(keypath, prod_squashed);
8439 
8440     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
8441     if (res == ERROR_ACCESS_DENIED)
8442     {
8443         skip("Not enough rights to perform tests\n");
8444         DeleteFileA(msifile);
8445         return;
8446     }
8447     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8448 
8449     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
8450     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
8451     lstrcatA(keypath, prod_squashed);
8452 
8453     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
8454     if (res == ERROR_ACCESS_DENIED)
8455     {
8456         skip("Not enough rights to perform tests\n");
8457         RegDeleteKeyA(prodkey, "");
8458         RegCloseKey(prodkey);
8459         return;
8460     }
8461     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8462 
8463     res = RegCreateKeyExA(userkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
8464     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8465 
8466     lstrcpyA(val, path);
8467     lstrcatA(val, "\\");
8468     lstrcatA(val, msifile);
8469     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
8470                          (const BYTE *)val, lstrlenA(val) + 1);
8471     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8472 
8473     hprod = 0xdeadbeef;
8474     r = MsiOpenProductA(prodcode, &hprod);
8475     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8476     ok(hprod != 0 && hprod != 0xdeadbeef, "Expected a valid product handle\n");
8477 
8478     /* hProduct is invalid */
8479     size = MAX_PATH;
8480     lstrcpyA(val, "apple");
8481     r = MsiGetProductPropertyA(0xdeadbeef, "ProductCode", val, &size);
8482     ok(r == ERROR_INVALID_HANDLE,
8483        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
8484     ok(!lstrcmpA(val, "apple"),
8485        "Expected val to be unchanged, got \"%s\"\n", val);
8486     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8487 
8488     size = MAX_PATH;
8489     lstrcpyW(valW, appleW);
8490     r = MsiGetProductPropertyW(0xdeadbeef, prodcode_propW, valW, &size);
8491     ok(r == ERROR_INVALID_HANDLE,
8492        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
8493     ok(!lstrcmpW(valW, appleW),
8494        "Expected val to be unchanged, got %s\n", wine_dbgstr_w(valW));
8495     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8496 
8497     /* szProperty is NULL */
8498     size = MAX_PATH;
8499     lstrcpyA(val, "apple");
8500     r = MsiGetProductPropertyA(hprod, NULL, val, &size);
8501     ok(r == ERROR_INVALID_PARAMETER,
8502        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8503     ok(!lstrcmpA(val, "apple"),
8504        "Expected val to be unchanged, got \"%s\"\n", val);
8505     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8506 
8507     size = MAX_PATH;
8508     lstrcpyW(valW, appleW);
8509     r = MsiGetProductPropertyW(hprod, NULL, valW, &size);
8510     ok(r == ERROR_INVALID_PARAMETER,
8511        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8512     ok(!lstrcmpW(valW, appleW),
8513        "Expected val to be unchanged, got %s\n", wine_dbgstr_w(valW));
8514     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8515 
8516     /* szProperty is empty */
8517     size = MAX_PATH;
8518     lstrcpyA(val, "apple");
8519     r = MsiGetProductPropertyA(hprod, "", val, &size);
8520     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8521     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
8522     ok(size == 0, "Expected 0, got %d\n", size);
8523 
8524     size = MAX_PATH;
8525     lstrcpyW(valW, appleW);
8526     r = MsiGetProductPropertyW(hprod, emptyW, valW, &size);
8527     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8528     ok(*valW == 0, "Expected \"\", got %s\n", wine_dbgstr_w(valW));
8529     ok(size == 0, "Expected 0, got %d\n", size);
8530 
8531     /* get the property */
8532     size = MAX_PATH;
8533     lstrcpyA(val, "apple");
8534     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8535     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8536     ok(!lstrcmpA(val, prodcode),
8537        "Expected \"%s\", got \"%s\"\n", prodcode, val);
8538     ok(size == lstrlenA(prodcode),
8539        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8540 
8541     size = MAX_PATH;
8542     lstrcpyW(valW, appleW);
8543     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, &size);
8544     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8545     ok(!lstrcmpW(valW, prodcodeW),
8546        "Expected %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8547     ok(size == lstrlenW(prodcodeW),
8548        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8549 
8550     /* lpValueBuf is NULL */
8551     size = MAX_PATH;
8552     r = MsiGetProductPropertyA(hprod, "ProductCode", NULL, &size);
8553     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8554     ok(size == lstrlenA(prodcode),
8555        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8556 
8557     size = MAX_PATH;
8558     r = MsiGetProductPropertyW(hprod, prodcode_propW, NULL, &size);
8559     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8560     ok(size == lstrlenW(prodcodeW),
8561        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8562 
8563     /* pcchValueBuf is NULL */
8564     lstrcpyA(val, "apple");
8565     r = MsiGetProductPropertyA(hprod, "ProductCode", val, NULL);
8566     ok(r == ERROR_INVALID_PARAMETER,
8567        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8568     ok(!lstrcmpA(val, "apple"),
8569        "Expected val to be unchanged, got \"%s\"\n", val);
8570     ok(size == lstrlenA(prodcode),
8571        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8572 
8573     lstrcpyW(valW, appleW);
8574     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, NULL);
8575     ok(r == ERROR_INVALID_PARAMETER,
8576        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8577     ok(!lstrcmpW(valW, appleW),
8578        "Expected val to be unchanged, got %s\n", wine_dbgstr_w(valW));
8579     ok(size == lstrlenW(prodcodeW),
8580        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8581 
8582     /* pcchValueBuf is too small */
8583     size = 4;
8584     lstrcpyA(val, "apple");
8585     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8586     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
8587     ok(!strncmp(val, prodcode, 3),
8588        "Expected first 3 chars of \"%s\", got \"%s\"\n", prodcode, val);
8589     ok(size == lstrlenA(prodcode),
8590        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8591 
8592     size = 4;
8593     lstrcpyW(valW, appleW);
8594     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, &size);
8595     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
8596     ok(!memcmp(valW, prodcodeW, 3 * sizeof(WCHAR)),
8597        "Expected first 3 chars of %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8598     ok(size == lstrlenW(prodcodeW),
8599        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8600 
8601     /* pcchValueBuf does not leave room for NULL terminator */
8602     size = lstrlenA(prodcode);
8603     lstrcpyA(val, "apple");
8604     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8605     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
8606     ok(!strncmp(val, prodcode, lstrlenA(prodcode) - 1),
8607        "Expected first 37 chars of \"%s\", got \"%s\"\n", prodcode, val);
8608     ok(size == lstrlenA(prodcode),
8609        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8610 
8611     size = lstrlenW(prodcodeW);
8612     lstrcpyW(valW, appleW);
8613     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, &size);
8614     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
8615     ok(!memcmp(valW, prodcodeW, lstrlenW(prodcodeW) - 1),
8616        "Expected first 37 chars of %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8617     ok(size == lstrlenW(prodcodeW),
8618        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8619 
8620     /* pcchValueBuf has enough room for NULL terminator */
8621     size = lstrlenA(prodcode) + 1;
8622     lstrcpyA(val, "apple");
8623     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8624     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8625     ok(!lstrcmpA(val, prodcode),
8626        "Expected \"%s\", got \"%s\"\n", prodcode, val);
8627     ok(size == lstrlenA(prodcode),
8628        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8629 
8630     size = lstrlenW(prodcodeW) + 1;
8631     lstrcpyW(valW, appleW);
8632     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, &size);
8633     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8634     ok(!lstrcmpW(valW, prodcodeW),
8635        "Expected %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8636     ok(size == lstrlenW(prodcodeW),
8637        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8638 
8639     /* nonexistent property */
8640     size = MAX_PATH;
8641     lstrcpyA(val, "apple");
8642     r = MsiGetProductPropertyA(hprod, "IDontExist", val, &size);
8643     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8644     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
8645     ok(size == 0, "Expected 0, got %d\n", size);
8646 
8647     size = MAX_PATH;
8648     lstrcpyW(valW, appleW);
8649     r = MsiGetProductPropertyW(hprod, nonexistentW, valW, &size);
8650     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8651     ok(!lstrcmpW(valW, emptyW), "Expected \"\", got %s\n", wine_dbgstr_w(valW));
8652     ok(size == 0, "Expected 0, got %d\n", size);
8653 
8654     r = MsiSetPropertyA(hprod, "NewProperty", "value");
8655     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8656 
8657     /* non-product property set */
8658     size = MAX_PATH;
8659     lstrcpyA(val, "apple");
8660     r = MsiGetProductPropertyA(hprod, "NewProperty", val, &size);
8661     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8662     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
8663     ok(size == 0, "Expected 0, got %d\n", size);
8664 
8665     size = MAX_PATH;
8666     lstrcpyW(valW, appleW);
8667     r = MsiGetProductPropertyW(hprod, newpropW, valW, &size);
8668     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8669     ok(!lstrcmpW(valW, emptyW), "Expected \"\", got %s\n", wine_dbgstr_w(valW));
8670     ok(size == 0, "Expected 0, got %d\n", size);
8671 
8672     r = MsiSetPropertyA(hprod, "ProductCode", "value");
8673     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8674 
8675     /* non-product property that is also a product property set */
8676     size = MAX_PATH;
8677     lstrcpyA(val, "apple");
8678     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8679     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8680     ok(!lstrcmpA(val, prodcode),
8681        "Expected \"%s\", got \"%s\"\n", prodcode, val);
8682     ok(size == lstrlenA(prodcode),
8683        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8684 
8685     size = MAX_PATH;
8686     lstrcpyW(valW, appleW);
8687     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, &size);
8688     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8689     ok(!lstrcmpW(valW, prodcodeW),
8690        "Expected %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8691     ok(size == lstrlenW(prodcodeW),
8692        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8693 
8694     MsiCloseHandle(hprod);
8695 
8696     RegDeleteValueA(props, "LocalPackage");
8697     delete_key(props, "", access);
8698     RegCloseKey(props);
8699     delete_key(userkey, "", access);
8700     RegCloseKey(userkey);
8701     delete_key(prodkey, "", access);
8702     RegCloseKey(prodkey);
8703     DeleteFileA(msifile);
8704 }
8705 
8706 static void test_MsiSetProperty(void)
8707 {
8708     MSIHANDLE hpkg, hdb, hrec;
8709     CHAR buf[MAX_PATH];
8710     LPCSTR query;
8711     DWORD size;
8712     UINT r;
8713 
8714     r = package_from_db(create_package_db(), &hpkg);
8715     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
8716     {
8717         skip("Not enough rights to perform tests\n");
8718         DeleteFileA(msifile);
8719         return;
8720     }
8721     ok(r == ERROR_SUCCESS, "Expected a valid package %u\n", r);
8722 
8723     /* invalid hInstall */
8724     r = MsiSetPropertyA(0, "Prop", "Val");
8725     ok(r == ERROR_INVALID_HANDLE,
8726        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
8727 
8728     /* invalid hInstall */
8729     r = MsiSetPropertyA(0xdeadbeef, "Prop", "Val");
8730     ok(r == ERROR_INVALID_HANDLE,
8731        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
8732 
8733     /* szName is NULL */
8734     r = MsiSetPropertyA(hpkg, NULL, "Val");
8735     ok(r == ERROR_INVALID_PARAMETER,
8736        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8737 
8738     /* both szName and szValue are NULL */
8739     r = MsiSetPropertyA(hpkg, NULL, NULL);
8740     ok(r == ERROR_INVALID_PARAMETER,
8741        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8742 
8743     /* szName is empty */
8744     r = MsiSetPropertyA(hpkg, "", "Val");
8745     ok(r == ERROR_FUNCTION_FAILED,
8746        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
8747 
8748     /* szName is empty and szValue is NULL */
8749     r = MsiSetPropertyA(hpkg, "", NULL);
8750     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8751 
8752     /* set a property */
8753     r = MsiSetPropertyA(hpkg, "Prop", "Val");
8754     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8755 
8756     /* get the property */
8757     size = MAX_PATH;
8758     r = MsiGetPropertyA(hpkg, "Prop", buf, &size);
8759     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8760     ok(!lstrcmpA(buf, "Val"), "Expected \"Val\", got \"%s\"\n", buf);
8761     ok(size == 3, "Expected 3, got %d\n", size);
8762 
8763     /* update the property */
8764     r = MsiSetPropertyA(hpkg, "Prop", "Nuvo");
8765     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8766 
8767     /* get the property */
8768     size = MAX_PATH;
8769     r = MsiGetPropertyA(hpkg, "Prop", buf, &size);
8770     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8771     ok(!lstrcmpA(buf, "Nuvo"), "Expected \"Nuvo\", got \"%s\"\n", buf);
8772     ok(size == 4, "Expected 4, got %d\n", size);
8773 
8774     hdb = MsiGetActiveDatabase(hpkg);
8775     ok(hdb != 0, "Expected a valid database handle\n");
8776 
8777     /* set prop is not in the _Property table */
8778     query = "SELECT * FROM `_Property` WHERE `Property` = 'Prop'";
8779     r = do_query(hdb, query, &hrec);
8780     ok(r == ERROR_BAD_QUERY_SYNTAX,
8781        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8782 
8783     /* set prop is not in the Property table */
8784     query = "SELECT * FROM `Property` WHERE `Property` = 'Prop'";
8785     r = do_query(hdb, query, &hrec);
8786     ok(r == ERROR_BAD_QUERY_SYNTAX,
8787        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8788 
8789     MsiCloseHandle(hdb);
8790 
8791     /* szValue is an empty string */
8792     r = MsiSetPropertyA(hpkg, "Prop", "");
8793     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8794 
8795     /* try to get the property */
8796     size = MAX_PATH;
8797     r = MsiGetPropertyA(hpkg, "Prop", buf, &size);
8798     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8799     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
8800     ok(size == 0, "Expected 0, got %d\n", size);
8801 
8802     /* reset the property */
8803     r = MsiSetPropertyA(hpkg, "Prop", "BlueTap");
8804     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8805 
8806     /* delete the property */
8807     r = MsiSetPropertyA(hpkg, "Prop", NULL);
8808     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8809 
8810     /* try to get the property */
8811     size = MAX_PATH;
8812     r = MsiGetPropertyA(hpkg, "Prop", buf, &size);
8813     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8814     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
8815     ok(size == 0, "Expected 0, got %d\n", size);
8816 
8817     MsiCloseHandle(hpkg);
8818     DeleteFileA(msifile);
8819 }
8820 
8821 static void test_MsiApplyMultiplePatches(void)
8822 {
8823     UINT r, type = GetDriveTypeW(NULL);
8824 
8825     r = MsiApplyMultiplePatchesA(NULL, NULL, NULL);
8826     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
8827 
8828     r = MsiApplyMultiplePatchesA("", NULL, NULL);
8829     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
8830 
8831     r = MsiApplyMultiplePatchesA(";", NULL, NULL);
8832     if (type == DRIVE_FIXED)
8833         todo_wine ok(r == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %u\n", r);
8834     else
8835         ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
8836 
8837     r = MsiApplyMultiplePatchesA("  ;", NULL, NULL);
8838     if (type == DRIVE_FIXED)
8839         todo_wine ok(r == ERROR_PATCH_PACKAGE_OPEN_FAILED, "Expected ERROR_PATCH_PACKAGE_OPEN_FAILED, got %u\n", r);
8840     else
8841         ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
8842 
8843     r = MsiApplyMultiplePatchesA(";;", NULL, NULL);
8844     if (type == DRIVE_FIXED)
8845         todo_wine ok(r == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %u\n", r);
8846     else
8847         ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
8848 
8849     r = MsiApplyMultiplePatchesA("nosuchpatchpackage;", NULL, NULL);
8850     todo_wine ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
8851 
8852     r = MsiApplyMultiplePatchesA(";nosuchpatchpackage", NULL, NULL);
8853     if (type == DRIVE_FIXED)
8854         todo_wine ok(r == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %u\n", r);
8855     else
8856         ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
8857 
8858     r = MsiApplyMultiplePatchesA("nosuchpatchpackage;nosuchpatchpackage", NULL, NULL);
8859     todo_wine ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
8860 
8861     r = MsiApplyMultiplePatchesA("  nosuchpatchpackage  ;  nosuchpatchpackage  ", NULL, NULL);
8862     todo_wine ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
8863 }
8864 
8865 static void test_MsiApplyPatch(void)
8866 {
8867     UINT r;
8868 
8869     r = MsiApplyPatchA(NULL, NULL, INSTALLTYPE_DEFAULT, NULL);
8870     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
8871 
8872     r = MsiApplyPatchA("", NULL, INSTALLTYPE_DEFAULT, NULL);
8873     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
8874 }
8875 
8876 static void test_MsiEnumComponentCosts(void)
8877 {
8878     MSIHANDLE hdb, hpkg;
8879     char package[12], drive[3];
8880     DWORD len;
8881     UINT r;
8882     int cost, temp;
8883 
8884     hdb = create_package_db();
8885     ok( hdb, "failed to create database\n" );
8886 
8887     r = create_property_table( hdb );
8888     ok( r == ERROR_SUCCESS, "cannot create Property table %u\n", r );
8889 
8890     r = add_property_entry( hdb, "'ProductCode', '{379B1C47-40C1-42FA-A9BB-BEBB6F1B0172}'" );
8891     ok( r == ERROR_SUCCESS, "cannot add property entry %u\n", r );
8892 
8893     r = add_property_entry( hdb, "'MSIFASTINSTALL', '1'" );
8894     ok( r == ERROR_SUCCESS, "cannot add property entry %u\n", r );
8895 
8896     r = add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'" );
8897     ok( r == ERROR_SUCCESS, "failed to add directory entry %u\n" , r );
8898 
8899     r = create_media_table( hdb );
8900     ok( r == ERROR_SUCCESS, "cannot create Media table %u\n", r );
8901 
8902     r = add_media_entry( hdb, "'1', '2', 'cabinet', '', '', ''");
8903     ok( r == ERROR_SUCCESS, "cannot add media entry %u\n", r );
8904 
8905     r = create_file_table( hdb );
8906     ok( r == ERROR_SUCCESS, "cannot create File table %u\n", r );
8907 
8908     r = add_file_entry( hdb, "'one.txt', 'one', 'one.txt', 4096, '', '', 8192, 1" );
8909     ok( r == ERROR_SUCCESS, "cannot add file %u\n", r );
8910 
8911     r = create_component_table( hdb );
8912     ok( r == ERROR_SUCCESS, "cannot create Component table %u\n", r );
8913 
8914     r = add_component_entry( hdb, "'one', '{B2F86B9D-8447-4BC5-8883-750C45AA31CA}', 'TARGETDIR', 0, '', 'one.txt'" );
8915     ok( r == ERROR_SUCCESS, "cannot add component %u\n", r );
8916 
8917     r = add_component_entry( hdb, "'two', '{62A09F6E-0B74-4829-BDB7-CAB66F42CCE8}', 'TARGETDIR', 0, '', ''" );
8918     ok( r == ERROR_SUCCESS, "cannot add component %u\n", r );
8919 
8920     r = create_feature_table( hdb );
8921     ok( r == ERROR_SUCCESS, "cannot create Feature table %u\n", r );
8922 
8923     r = add_feature_entry( hdb, "'one', '', '', '', 0, 1, '', 0" );
8924     ok( r == ERROR_SUCCESS, "cannot add feature %u\n", r );
8925 
8926     r = add_feature_entry( hdb, "'two', '', '', '', 0, 1, '', 0" );
8927     ok( r == ERROR_SUCCESS, "cannot add feature %u\n", r );
8928 
8929     r = create_feature_components_table( hdb );
8930     ok( r == ERROR_SUCCESS, "cannot create FeatureComponents table %u\n", r );
8931 
8932     r = add_feature_components_entry( hdb, "'one', 'one'" );
8933     ok( r == ERROR_SUCCESS, "cannot add feature/component pair %u\n", r );
8934 
8935     r = add_feature_components_entry( hdb, "'two', 'two'" );
8936     ok( r == ERROR_SUCCESS, "cannot add feature/component pair %u\n", r );
8937 
8938     r = create_install_execute_sequence_table( hdb );
8939     ok( r == ERROR_SUCCESS, "cannot create InstallExecuteSequence table %u\n", r );
8940 
8941     r = add_install_execute_sequence_entry( hdb, "'CostInitialize', '', '800'" );
8942     ok( r == ERROR_SUCCESS, "cannot add install execute sequence entry %u\n", r );
8943 
8944     r = add_install_execute_sequence_entry( hdb, "'FileCost', '', '900'" );
8945     ok( r == ERROR_SUCCESS, "cannot add install execute sequence entry %u\n", r );
8946 
8947     r = add_install_execute_sequence_entry( hdb, "'CostFinalize', '', '1000'" );
8948     ok( r == ERROR_SUCCESS, "cannot add install execute sequence entry %u\n", r );
8949 
8950     r = add_install_execute_sequence_entry( hdb, "'InstallValidate', '', '1100'" );
8951     ok( r == ERROR_SUCCESS, "cannot add install execute sequence entry %u\n", r );
8952 
8953     MsiDatabaseCommit( hdb );
8954 
8955     sprintf( package, "#%u", hdb );
8956     r = MsiOpenPackageA( package, &hpkg );
8957     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
8958     {
8959         skip("Not enough rights to perform tests\n");
8960         goto error;
8961     }
8962     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8963 
8964     r = MsiEnumComponentCostsA( 0, NULL, 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8965     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8966 
8967     r = MsiEnumComponentCostsA( hpkg, NULL, 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8968     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8969 
8970     r = MsiEnumComponentCostsA( hpkg, NULL, 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8971     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8972 
8973     r = MsiEnumComponentCostsA( hpkg, "", 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8974     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8975 
8976     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8977     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8978 
8979     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, NULL, NULL, NULL, NULL );
8980     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8981 
8982     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, NULL, NULL, NULL );
8983     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8984 
8985     len = sizeof(drive);
8986     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, NULL, NULL );
8987     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8988 
8989     len = sizeof(drive);
8990     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, NULL );
8991     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8992 
8993     len = sizeof(drive);
8994     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8995     todo_wine ok( r == ERROR_INVALID_HANDLE_STATE, "Expected ERROR_INVALID_HANDLE_STATE, got %u\n", r );
8996 
8997     len = sizeof(drive);
8998     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, NULL, &len, &cost, &temp );
8999     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
9000 
9001     MsiSetInternalUI( INSTALLUILEVEL_NONE, NULL );
9002 
9003     r = MsiDoActionA( hpkg, "CostInitialize" );
9004     ok( r == ERROR_SUCCESS, "CostInitialize failed %u\n", r );
9005 
9006     r = MsiDoActionA( hpkg, "FileCost" );
9007     ok( r == ERROR_SUCCESS, "FileCost failed %u\n", r );
9008 
9009     len = sizeof(drive);
9010     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
9011     ok( r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %u\n", r );
9012 
9013     r = MsiDoActionA( hpkg, "CostFinalize" );
9014     ok( r == ERROR_SUCCESS, "CostFinalize failed %u\n", r );
9015 
9016     /* contrary to what msdn says InstallValidate must be called too */
9017     len = sizeof(drive);
9018     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
9019     todo_wine ok( r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %u\n", r );
9020 
9021     r = MsiDoActionA( hpkg, "InstallValidate" );
9022     ok( r == ERROR_SUCCESS, "InstallValidate failed %u\n", r );
9023 
9024     len = 0;
9025     r = MsiEnumComponentCostsA( hpkg, "three", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
9026     ok( r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %u\n", r );
9027 
9028     len = 0;
9029     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
9030     ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %u\n", r );
9031     ok( len == 2, "expected len == 2, got %u\n", len );
9032 
9033     len = 2;
9034     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
9035     ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %u\n", r );
9036     ok( len == 2, "expected len == 2, got %u\n", len );
9037 
9038     len = 2;
9039     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_UNKNOWN, drive, &len, &cost, &temp );
9040     ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %u\n", r );
9041     ok( len == 2, "expected len == 2, got %u\n", len );
9042 
9043     /* install state doesn't seem to matter */
9044     len = sizeof(drive);
9045     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_UNKNOWN, drive, &len, &cost, &temp );
9046     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
9047 
9048     len = sizeof(drive);
9049     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_ABSENT, drive, &len, &cost, &temp );
9050     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
9051 
9052     len = sizeof(drive);
9053     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_SOURCE, drive, &len, &cost, &temp );
9054     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
9055 
9056     len = sizeof(drive);
9057     drive[0] = 0;
9058     cost = temp = 0xdead;
9059     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
9060     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
9061     ok( len == 2, "expected len == 2, got %u\n", len );
9062     ok( drive[0], "expected a drive\n" );
9063     ok( cost && cost != 0xdead, "expected cost > 0, got %d\n", cost );
9064     ok( !temp, "expected temp == 0, got %d\n", temp );
9065 
9066     len = sizeof(drive);
9067     drive[0] = 0;
9068     cost = temp = 0xdead;
9069     r = MsiEnumComponentCostsA( hpkg, "two", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
9070     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
9071     ok( len == 2, "expected len == 2, got %u\n", len );
9072     ok( drive[0], "expected a drive\n" );
9073     ok( !cost, "expected cost == 0, got %d\n", cost );
9074     ok( !temp, "expected temp == 0, got %d\n", temp );
9075 
9076     len = sizeof(drive);
9077     drive[0] = 0;
9078     cost = temp = 0xdead;
9079     r = MsiEnumComponentCostsA( hpkg, "", 0, INSTALLSTATE_UNKNOWN, drive, &len, &cost, &temp );
9080     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
9081     ok( len == 2, "expected len == 2, got %u\n", len );
9082     ok( drive[0], "expected a drive\n" );
9083     ok( !cost, "expected cost == 0, got %d\n", cost );
9084     ok( temp && temp != 0xdead, "expected temp > 0, got %d\n", temp );
9085 
9086     /* increased index */
9087     len = sizeof(drive);
9088     r = MsiEnumComponentCostsA( hpkg, "one", 1, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
9089     ok( r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %u\n", r );
9090 
9091     len = sizeof(drive);
9092     r = MsiEnumComponentCostsA( hpkg, "", 1, INSTALLSTATE_UNKNOWN, drive, &len, &cost, &temp );
9093     ok( r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %u\n", r );
9094 
9095     MsiCloseHandle( hpkg );
9096 error:
9097     MsiCloseHandle( hdb );
9098     DeleteFileA( msifile );
9099 }
9100 
9101 static void test_MsiDatabaseCommit(void)
9102 {
9103     UINT r;
9104     MSIHANDLE hdb, hpkg = 0;
9105     char buf[32], package[12];
9106     DWORD sz;
9107 
9108     hdb = create_package_db();
9109     ok( hdb, "failed to create database\n" );
9110 
9111     r = create_property_table( hdb );
9112     ok( r == ERROR_SUCCESS, "can't create Property table %u\n", r );
9113 
9114     sprintf( package, "#%u", hdb );
9115     r = MsiOpenPackageA( package, &hpkg );
9116     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
9117     {
9118         skip("Not enough rights to perform tests\n");
9119         goto error;
9120     }
9121     ok( r == ERROR_SUCCESS, "got %u\n", r );
9122 
9123     r = MsiSetPropertyA( hpkg, "PROP", "value" );
9124     ok( r == ERROR_SUCCESS, "got %u\n", r );
9125 
9126     buf[0] = 0;
9127     sz = sizeof(buf);
9128     r = MsiGetPropertyA( hpkg, "PROP", buf, &sz );
9129     ok( r == ERROR_SUCCESS, "MsiGetPropertyA returned %u\n", r );
9130     ok( !lstrcmpA( buf, "value" ), "got \"%s\"\n", buf );
9131 
9132     r = MsiDatabaseCommit( hdb );
9133     ok( r == ERROR_SUCCESS, "MsiDatabaseCommit returned %u\n", r );
9134 
9135     buf[0] = 0;
9136     sz = sizeof(buf);
9137     r = MsiGetPropertyA( hpkg, "PROP", buf, &sz );
9138     ok( r == ERROR_SUCCESS, "MsiGetPropertyA returned %u\n", r );
9139     ok( !lstrcmpA( buf, "value" ), "got \"%s\"\n", buf );
9140 
9141     MsiCloseHandle( hpkg );
9142 error:
9143     MsiCloseHandle( hdb );
9144     DeleteFileA( msifile );
9145 }
9146 
9147 static int externalui_ran;
9148 
9149 static INT CALLBACK externalui_callback(void *context, UINT message_type, LPCSTR message)
9150 {
9151     externalui_ran = 1;
9152     ok(message_type == INSTALLMESSAGE_USER, "expected INSTALLMESSAGE_USER, got %08x\n", message_type);
9153     return 0;
9154 }
9155 
9156 static int externalui_record_ran;
9157 
9158 static INT CALLBACK externalui_record_callback(void *context, UINT message_type, MSIHANDLE hrecord)
9159 {
9160     INT retval = context ? *((INT *)context) : 0;
9161     UINT r;
9162     externalui_record_ran = 1;
9163     ok(message_type == INSTALLMESSAGE_USER, "expected INSTALLMESSAGE_USER, got %08x\n", message_type);
9164     r = MsiRecordGetFieldCount(hrecord);
9165     ok(r == 1, "expected 1, got %u\n", r);
9166     r = MsiRecordGetInteger(hrecord, 1);
9167     ok(r == 12345, "expected 12345, got %u\n", r);
9168     return retval;
9169 }
9170 
9171 static void test_externalui(void)
9172 {
9173     /* test that external UI handlers work correctly */
9174 
9175     INSTALLUI_HANDLERA prev;
9176     INSTALLUI_HANDLER_RECORD prev_record;
9177     MSIHANDLE hpkg, hrecord;
9178     UINT r;
9179     INT retval = 0;
9180 
9181     prev = MsiSetExternalUIA(externalui_callback, INSTALLLOGMODE_USER, NULL);
9182 
9183     r = package_from_db(create_package_db(), &hpkg);
9184     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
9185     {
9186         skip("Not enough rights to perform tests\n");
9187         DeleteFileA(msifile);
9188         return;
9189     }
9190     ok(r == ERROR_SUCCESS, "Expected a valid package %u\n", r);
9191 
9192     hrecord = MsiCreateRecord(1);
9193     ok(hrecord, "Expected a valid record\n");
9194     r = MsiRecordSetStringA(hrecord, 0, "test message [1]");
9195     ok(r == ERROR_SUCCESS, "MsiSetString failed %u\n", r);
9196     r = MsiRecordSetInteger(hrecord, 1, 12345);
9197     ok(r == ERROR_SUCCESS, "MsiSetInteger failed %u\n", r);
9198 
9199     externalui_ran = 0;
9200     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
9201     ok(r == 0, "expected 0, got %u\n", r);
9202     ok(externalui_ran == 1, "external UI callback did not run\n");
9203 
9204     prev = MsiSetExternalUIA(prev, 0, NULL);
9205     ok(prev == externalui_callback, "wrong callback function %p\n", prev);
9206     r = MsiSetExternalUIRecord(externalui_record_callback, INSTALLLOGMODE_USER, &retval, &prev_record);
9207     ok(r == ERROR_SUCCESS, "MsiSetExternalUIRecord failed %u\n", r);
9208 
9209     externalui_ran = externalui_record_ran = 0;
9210     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
9211     ok(r == 0, "expected 0, got %u\n", r);
9212     ok(externalui_ran == 0, "external UI callback should not have run\n");
9213     ok(externalui_record_ran == 1, "external UI record callback did not run\n");
9214 
9215     MsiSetExternalUIA(externalui_callback, INSTALLLOGMODE_USER, NULL);
9216 
9217     externalui_ran = externalui_record_ran = 0;
9218     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
9219     ok(r == 0, "expected 0, got %u\n", r);
9220     ok(externalui_ran == 1, "external UI callback did not run\n");
9221     ok(externalui_record_ran == 1, "external UI record callback did not run\n");
9222 
9223     retval = 1;
9224     externalui_ran = externalui_record_ran = 0;
9225     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
9226     ok(r == 1, "expected 1, got %u\n", r);
9227     ok(externalui_ran == 0, "external UI callback should not have run\n");
9228     ok(externalui_record_ran == 1, "external UI record callback did not run\n");
9229 
9230     /* filter and context should be kept separately */
9231     r = MsiSetExternalUIRecord(externalui_record_callback, INSTALLLOGMODE_ERROR, &retval, &prev_record);
9232     ok(r == ERROR_SUCCESS, "MsiSetExternalUIRecord failed %u\n", r);
9233 
9234     externalui_ran = externalui_record_ran = 0;
9235     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
9236     ok(r == 0, "expected 0, got %u\n", r);
9237     ok(externalui_ran == 1, "external UI callback did not run\n");
9238     ok(externalui_record_ran == 0, "external UI record callback should not have run\n");
9239 
9240     MsiCloseHandle(hpkg);
9241     DeleteFileA(msifile);
9242 }
9243 
9244 struct externalui_message {
9245     UINT message;
9246     int field_count;
9247     char field[4][100];
9248     int match[4]; /* should we test for a match */
9249     int optional;
9250 };
9251 
9252 static struct externalui_message *sequence;
9253 static int sequence_count, sequence_size;
9254 
9255 static void add_message(const struct externalui_message *msg)
9256 {
9257     if (!sequence)
9258     {
9259         sequence_size = 10;
9260         sequence = HeapAlloc(GetProcessHeap(), 0, sequence_size * sizeof(*sequence));
9261     }
9262     if (sequence_count == sequence_size)
9263     {
9264         sequence_size *= 2;
9265         sequence = HeapReAlloc(GetProcessHeap(), 0, sequence, sequence_size * sizeof(*sequence));
9266     }
9267 
9268     assert(sequence);
9269 
9270     sequence[sequence_count++] = *msg;
9271 }
9272 
9273 static void flush_sequence(void)
9274 {
9275     HeapFree(GetProcessHeap(), 0, sequence);
9276     sequence = NULL;
9277     sequence_count = sequence_size = 0;
9278 }
9279 
9280 static void ok_sequence_(const struct externalui_message *expected, const char *context, BOOL todo,
9281                          const char *file, int line)
9282 {
9283     static const struct externalui_message end_of_sequence = {0};
9284     const struct externalui_message *actual;
9285     int failcount = 0;
9286     int i;
9287 
9288     add_message(&end_of_sequence);
9289 
9290     actual = sequence;
9291 
9292     while (expected->message && actual->message)
9293     {
9294         if (expected->message == actual->message)
9295         {
9296             if (expected->field_count != actual->field_count)
9297             {
9298                 todo_wine_if (todo)
9299                     ok_(file, line) (FALSE, "%s: in msg 0x%08x expecting field count %d got %d\n",
9300                                      context, expected->message, expected->field_count, actual->field_count);
9301                 failcount++;
9302             }
9303 
9304             for (i = 0; i <= actual->field_count; i++)
9305             {
9306                 if (expected->match[i] && strcmp(expected->field[i], actual->field[i]))
9307                 {
9308                     todo_wine_if (todo)
9309                         ok_(file, line) (FALSE, "%s: in msg 0x%08x field %d: expected \"%s\", got \"%s\"\n",
9310                                          context, expected->message, i, expected->field[i], actual->field[i]);
9311                     failcount++;
9312                 }
9313             }
9314 
9315             expected++;
9316             actual++;
9317         }
9318         else
9319         {
9320             todo_wine_if (todo)
9321                 ok_(file, line) (FALSE, "%s: the msg 0x%08x was expected, but got msg 0x%08x instead\n",
9322                                  context, expected->message, actual->message);
9323             failcount++;
9324             if (todo)
9325                 goto done;
9326             expected++;
9327             actual++;
9328         }
9329     }
9330 
9331     if (expected->message || actual->message)
9332     {
9333         todo_wine_if (todo)
9334             ok_(file, line) (FALSE, "%s: the msg sequence is not complete: expected %08x - actual %08x\n",
9335                              context, expected->message, actual->message);
9336         failcount++;
9337     }
9338 
9339     if(todo && !failcount) /* succeeded yet marked todo */
9340     {
9341         todo_wine
9342             ok_(file, line)(TRUE, "%s: marked \"todo_wine\" but succeeds\n", context);
9343     }
9344 
9345 done:
9346     flush_sequence();
9347 }
9348 
9349 #define ok_sequence(exp, contx, todo) \
9350         ok_sequence_((exp), (contx), (todo), __FILE__, __LINE__)
9351 
9352 static const struct externalui_message empty_sequence[] = {
9353     {0}
9354 };
9355 
9356 static const struct externalui_message openpackage_nonexistent_sequence[] = {
9357     {INSTALLMESSAGE_INITIALIZE, -1},
9358     {INSTALLMESSAGE_TERMINATE, -1},
9359     {0}
9360 };
9361 
9362 static const struct externalui_message openpackage_sequence[] = {
9363     {INSTALLMESSAGE_INITIALIZE, -1},
9364     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9365     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
9366     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9367     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9368     {0}
9369 };
9370 
9371 static const struct externalui_message processmessage_info_sequence[] = {
9372     {INSTALLMESSAGE_INFO, 3, {"zero", "one", "two", "three"}, {1, 1, 1, 1}},
9373     {0}
9374 };
9375 
9376 static const struct externalui_message processmessage_actionstart_sequence[] = {
9377     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "name", "description", "template"}, {0, 1, 1, 1}},
9378     {0}
9379 };
9380 
9381 static const struct externalui_message processmessage_actiondata_sequence[] = {
9382     {INSTALLMESSAGE_ACTIONDATA, 3, {"{{name: }}template", "cherry", "banana", "guava"}, {1, 1, 1, 1}},
9383     {0}
9384 };
9385 
9386 static const struct externalui_message processmessage_error_sequence[] = {
9387     {INSTALLMESSAGE_USER, 3, {"", "1311", "banana", "guava"}, {0, 1, 1, 1}},
9388     {0}
9389 };
9390 
9391 static const struct externalui_message processmessage_internal_error_sequence[] = {
9392     {INSTALLMESSAGE_INFO, 3, {"DEBUG: Error [1]:  Action not found: [2]", "2726", "banana", "guava"}, {1, 1, 1, 1}},
9393     {INSTALLMESSAGE_USER, 3, {"internal error", "2726", "banana", "guava"}, {1, 1, 1, 1}},
9394     {0}
9395 };
9396 
9397 static const struct externalui_message processmessage_error_format_sequence[] = {
9398     {INSTALLMESSAGE_USER, 3, {"", "2726", "banana", "guava"}, {0, 1, 1, 1}},
9399     {0}
9400 };
9401 
9402 static const struct externalui_message doaction_costinitialize_sequence[] = {
9403     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostInitialize", "cost description", "cost template"}, {0, 1, 1, 1}},
9404     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", ""}, {0, 1, 1}},
9405     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", "1"}, {0, 1, 1}},
9406     {0}
9407 };
9408 
9409 static const struct externalui_message doaction_custom_sequence[] = {
9410     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "description", "template"}, {0, 1, 1, 1}},
9411     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
9412     {INSTALLMESSAGE_INFO, 2, {"", "custom", "0"}, {0, 1, 1}},
9413     {0}
9414 };
9415 
9416 static const struct externalui_message doaction_custom_fullui_sequence[] = {
9417     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
9418     {INSTALLMESSAGE_INFO, 2, {"", "custom", ""}, {0, 1, 1}},
9419     {INSTALLMESSAGE_SHOWDIALOG, 0, {"custom"}, {1}},
9420     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
9421     {0}
9422 };
9423 
9424 static const struct externalui_message doaction_custom_cancel_sequence[] = {
9425     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
9426     {0}
9427 };
9428 
9429 static const struct externalui_message doaction_dialog_nonexistent_sequence[] = {
9430     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
9431     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
9432     {INSTALLMESSAGE_SHOWDIALOG, 0, {"custom"}, {1}},
9433     {INSTALLMESSAGE_INFO, 2, {"DEBUG: Error [1]:  Action not found: [2]", "2726", "custom"}, {1, 1, 1}},
9434     {INSTALLMESSAGE_INFO, 2, {"", "2726", "custom"}, {0, 1, 1}},
9435     {INSTALLMESSAGE_INFO, 2, {"", "custom", "0"}, {0, 1, 1}},
9436     {0}
9437 };
9438 
9439 static const struct externalui_message doaction_dialog_sequence[] = {
9440     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "dialog", "", ""}, {0, 1, 1, 1}},
9441     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "0"}, {0, 1, 1}},
9442     {INSTALLMESSAGE_SHOWDIALOG, 0, {"dialog"}, {1}},
9443     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "dialog", "Dialog created"}, {0, 1, 1}},
9444     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "1"}, {0, 1, 1}},
9445     {0}
9446 };
9447 
9448 static const struct externalui_message doaction_dialog_error_sequence[] = {
9449     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "error", "", ""}, {0, 1, 1, 1}},
9450     {INSTALLMESSAGE_INFO, 2, {"", "error", "1"}, {0, 1, 1}},
9451     {INSTALLMESSAGE_SHOWDIALOG, 0, {"error"}, {1}},
9452     {0}
9453 };
9454 
9455 static const struct externalui_message doaction_dialog_3_sequence[] = {
9456     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "dialog", "", ""}, {0, 1, 1, 1}},
9457     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "0"}, {0, 1, 1}},
9458     {INSTALLMESSAGE_SHOWDIALOG, 0, {"dialog"}, {1}},
9459     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "3"}, {0, 1, 1}},
9460     {0}
9461 };
9462 
9463 static const struct externalui_message doaction_dialog_12345_sequence[] = {
9464     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "dialog", "", ""}, {0, 1, 1, 1}},
9465     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "3"}, {0, 1, 1}},
9466     {INSTALLMESSAGE_SHOWDIALOG, 0, {"dialog"}, {1}},
9467     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "12345"}, {0, 1, 1}},
9468     {0}
9469 };
9470 
9471 static const struct externalui_message closehandle_sequence[] = {
9472     {INSTALLMESSAGE_TERMINATE, -1},
9473     {0}
9474 };
9475 
9476 static INT CALLBACK externalui_message_string_callback(void *context, UINT message, LPCSTR string)
9477 {
9478     INT retval = context ? *((INT *)context) : 0;
9479     struct externalui_message msg;
9480 
9481     msg.message = message;
9482     msg.field_count = 0;
9483     strcpy(msg.field[0], string);
9484     add_message(&msg);
9485 
9486     return retval;
9487 }
9488 
9489 static INT CALLBACK externalui_message_callback(void *context, UINT message, MSIHANDLE hrecord)
9490 {
9491     INT retval = context ? *((INT *)context) : 0;
9492     struct externalui_message msg;
9493     char buffer[100];
9494     DWORD length = 100;
9495     int i;
9496 
9497     msg.message = message;
9498     if (message == INSTALLMESSAGE_TERMINATE)
9499     {
9500         /* trying to access the record seems to hang on some versions of Windows */
9501         msg.field_count = -1;
9502         add_message(&msg);
9503         return 1;
9504     }
9505     msg.field_count = MsiRecordGetFieldCount(hrecord);
9506     for (i = 0; i <= msg.field_count; i++)
9507     {
9508         length = 100;
9509         MsiRecordGetStringA(hrecord, i, buffer, &length);
9510         memcpy(msg.field[i], buffer, min(100, length+1));
9511     }
9512 
9513     add_message(&msg);
9514 
9515     return retval;
9516 }
9517 
9518 static void test_externalui_message(void)
9519 {
9520     /* test that events trigger the correct sequence of messages */
9521 
9522     INSTALLUI_HANDLER_RECORD prev;
9523     MSIHANDLE hdb, hpkg, hrecord;
9524     INT retval = 1;
9525     UINT r;
9526 
9527     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
9528 
9529     /* processing SHOWDIALOG with a record handler causes a crash on XP */
9530     MsiSetExternalUIA(externalui_message_string_callback, INSTALLLOGMODE_SHOWDIALOG, &retval);
9531     r = MsiSetExternalUIRecord(externalui_message_callback, 0xffffffff ^ INSTALLLOGMODE_PROGRESS ^ INSTALLLOGMODE_SHOWDIALOG, &retval, &prev);
9532 
9533     flush_sequence();
9534 
9535     CoInitialize(NULL);
9536 
9537     hdb = create_package_db();
9538     ok(hdb, "failed to create database\n");
9539 
9540     create_file_data("forcecodepage.idt", "\r\n\r\n1252\t_ForceCodepage\r\n");
9541     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
9542     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9543 
9544     r = run_query(hdb, "CREATE TABLE `Error` (`Error` SHORT NOT NULL, `Message` CHAR(0) PRIMARY KEY `Error`)");
9545     ok(r == ERROR_SUCCESS, "Failed to create Error table: %u\n", r);
9546     r = run_query(hdb, "INSERT INTO `Error` (`Error`, `Message`) VALUES (5, 'internal error')");
9547     ok(r == ERROR_SUCCESS, "Failed to insert into Error table: %u\n", r);
9548 
9549     r = create_actiontext_table(hdb);
9550     ok(r == ERROR_SUCCESS, "Failed to create ActionText table: %u\n", r);
9551     r = add_actiontext_entry(hdb, "'custom', 'description', 'template'");
9552     ok(r == ERROR_SUCCESS, "Failed to insert into ActionText table: %u\n", r);
9553     r = add_actiontext_entry(hdb, "'CostInitialize', 'cost description', 'cost template'");
9554     ok(r == ERROR_SUCCESS, "Failed to insert into ActionText table: %u\n", r);
9555 
9556     r = MsiOpenPackageA(NULL, &hpkg);
9557     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9558     ok_sequence(empty_sequence, "MsiOpenPackage with NULL db", FALSE);
9559 
9560     r = MsiOpenPackageA("nonexistent", &hpkg);
9561     ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
9562     ok_sequence(openpackage_nonexistent_sequence, "MsiOpenPackage with nonexistent db", FALSE);
9563 
9564     r = package_from_db(hdb, &hpkg);
9565     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
9566     {
9567         skip("Not enough rights to perform tests\n");
9568         DeleteFileA(msifile);
9569         return;
9570     }
9571     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
9572     ok_sequence(openpackage_sequence, "MsiOpenPackage with valid db", FALSE);
9573 
9574     /* Test MsiProcessMessage */
9575     hrecord = MsiCreateRecord(3);
9576     ok(hrecord, "failed to create record\n");
9577 
9578     MsiRecordSetStringA(hrecord, 0, "zero");
9579     MsiRecordSetStringA(hrecord, 1, "one");
9580     MsiRecordSetStringA(hrecord, 2, "two");
9581     MsiRecordSetStringA(hrecord, 3, "three");
9582     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_INFO, hrecord);
9583     ok(r == 1, "Expected 1, got %d\n", r);
9584     ok_sequence(processmessage_info_sequence, "MsiProcessMessage(INSTALLMESSAGE_INFO)", FALSE);
9585 
9586     MsiRecordSetStringA(hrecord, 1, "name");
9587     MsiRecordSetStringA(hrecord, 2, "description");
9588     MsiRecordSetStringA(hrecord, 3, "template");
9589     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_ACTIONSTART, hrecord);
9590     ok(r == 1, "Expected 1, got %d\n", r);
9591     ok_sequence(processmessage_actionstart_sequence, "MsiProcessMessage(INSTALLMESSAGE_ACTIONSTART)", FALSE);
9592 
9593     MsiRecordSetStringA(hrecord, 0, "apple");
9594     MsiRecordSetStringA(hrecord, 1, "cherry");
9595     MsiRecordSetStringA(hrecord, 2, "banana");
9596     MsiRecordSetStringA(hrecord, 3, "guava");
9597     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_ACTIONDATA, hrecord);
9598     ok(r == 1, "Expected 1, got %d\n", r);
9599     ok_sequence(processmessage_actiondata_sequence, "MsiProcessMessage(INSTALLMESSAGE_ACTIONDATA)", FALSE);
9600 
9601     /* non-internal error */
9602     MsiRecordSetStringA(hrecord, 0, NULL);
9603     MsiRecordSetInteger(hrecord, 1, 1311);
9604     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
9605     ok(r == 1, "Expected 1, got %d\n", r);
9606     ok_sequence(processmessage_error_sequence, "MsiProcessMessage non-internal error", FALSE);
9607 
9608     /* internal error */
9609     MsiRecordSetStringA(hrecord, 0, NULL);
9610     MsiRecordSetInteger(hrecord, 1, 2726);
9611     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
9612     ok(r == 0, "Expected 0, got %d\n", r);
9613     ok_sequence(processmessage_internal_error_sequence, "MsiProcessMessage internal error", FALSE);
9614 
9615     /* with format field */
9616     MsiRecordSetStringA(hrecord, 0, "starfruit");
9617     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
9618     ok(r == 1, "Expected 1, got %d\n", r);
9619     ok_sequence(processmessage_error_format_sequence, "MsiProcessMessage error", FALSE);
9620 
9621     /* Test a standard action */
9622     r = MsiDoActionA(hpkg, "CostInitialize");
9623     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9624     ok_sequence(doaction_costinitialize_sequence, "MsiDoAction(\"CostInitialize\")", FALSE);
9625 
9626     /* Test a custom action */
9627     r = MsiDoActionA(hpkg, "custom");
9628     ok(r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %d\n", r);
9629     ok_sequence(doaction_custom_sequence, "MsiDoAction(\"custom\")", FALSE);
9630 
9631     /* close the package */
9632     MsiCloseHandle(hpkg);
9633     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
9634 
9635     /* Test dialogs */
9636     hdb = create_package_db();
9637     ok(hdb, "failed to create database\n");
9638 
9639     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
9640     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9641 
9642     r = create_dialog_table(hdb);
9643     ok(r == ERROR_SUCCESS, "failed to create dialog table %u\n", r);
9644     r = add_dialog_entry(hdb, "'dialog', 50, 50, 100, 100, 0, 'dummy'");
9645     ok(r == ERROR_SUCCESS, "failed to insert into dialog table %u\n", r);
9646 
9647     r = create_control_table(hdb);
9648     ok(r == ERROR_SUCCESS, "failed to create control table %u\n", r);
9649     r = add_control_entry(hdb, "'dialog', 'dummy', 'Text', 5, 5, 5, 5, 3, 'dummy'");
9650     ok(r == ERROR_SUCCESS, "failed to insert into control table %u\n", r);
9651 
9652     r = package_from_db(hdb, &hpkg);
9653     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
9654     ok_sequence(openpackage_sequence, "MsiOpenPackage with valid db", FALSE);
9655 
9656     /* Test a custom action */
9657     r = MsiDoActionA(hpkg, "custom");
9658     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9659     ok_sequence(doaction_custom_fullui_sequence, "MsiDoAction(\"custom\")", FALSE);
9660 
9661     retval = 2;
9662     r = MsiDoActionA(hpkg, "custom");
9663     ok(r == ERROR_INSTALL_USEREXIT, "Expected ERROR_INSTALL_USEREXIT, got %d\n", r);
9664     ok_sequence(doaction_custom_cancel_sequence, "MsiDoAction(\"custom\")", FALSE);
9665 
9666     retval = 0;
9667     r = MsiDoActionA(hpkg, "custom");
9668     ok(r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %d\n", r);
9669     ok_sequence(doaction_dialog_nonexistent_sequence, "MsiDoAction(\"custom\")", FALSE);
9670 
9671     r = MsiDoActionA(hpkg, "dialog");
9672     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9673     ok_sequence(doaction_dialog_sequence, "MsiDoAction(\"dialog\")", FALSE);
9674 
9675     retval = -1;
9676     r = MsiDoActionA(hpkg, "error");
9677     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9678     ok_sequence(doaction_dialog_error_sequence, "MsiDoAction(\"error\")", FALSE);
9679 
9680     r = MsiDoActionA(hpkg, "error");
9681     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9682     ok_sequence(doaction_dialog_error_sequence, "MsiDoAction(\"error\")", FALSE);
9683 
9684     retval = -2;
9685     r = MsiDoActionA(hpkg, "custom");
9686     ok(r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %d\n", r);
9687     ok_sequence(doaction_dialog_nonexistent_sequence, "MsiDoAction(\"custom\")", FALSE);
9688 
9689     retval = 3;
9690     r = MsiDoActionA(hpkg, "dialog");
9691     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %d\n", r);
9692     ok_sequence(doaction_dialog_3_sequence, "MsiDoAction(\"dialog\")", FALSE);
9693 
9694     retval = 12345;
9695     r = MsiDoActionA(hpkg, "dialog");
9696     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_INSTALL_FAILURE, got %d\n", r);
9697     ok_sequence(doaction_dialog_12345_sequence, "MsiDoAction(\"dialog\")", FALSE);
9698 
9699     MsiCloseHandle(hpkg);
9700     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
9701 
9702     MsiCloseHandle(hrecord);
9703     CoUninitialize();
9704     DeleteFileA(msifile);
9705     DeleteFileA("forcecodepage.idt");
9706 }
9707 
9708 static const struct externalui_message controlevent_spawn_sequence[] = {
9709     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "spawn", "", ""}, {0, 1, 1, 1}},
9710     {INSTALLMESSAGE_INFO, 2, {"", "spawn", ""}, {0, 1, 1}},
9711     {INSTALLMESSAGE_SHOWDIALOG, 0, {"spawn"}, {1}},
9712     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "spawn", "Dialog created"}, {0, 1, 1}},
9713 
9714     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
9715     {INSTALLMESSAGE_INFO, 2, {"", "custom", ""}, {0, 1, 1}},
9716     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
9717 
9718     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "child1", "Dialog created"}, {0, 1, 1}},
9719 
9720     {INSTALLMESSAGE_INFO, 2, {"", "spawn", "2"}, {0, 1, 1}},
9721     {0}
9722 };
9723 
9724 static const struct externalui_message controlevent_spawn2_sequence[] = {
9725     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "spawn2", "", ""}, {0, 1, 1, 1}},
9726     {INSTALLMESSAGE_INFO, 2, {"", "spawn2", "2"}, {0, 1, 1}},
9727     {INSTALLMESSAGE_SHOWDIALOG, 0, {"spawn2"}, {1}},
9728     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "spawn2", "Dialog created"}, {0, 1, 1}},
9729 
9730     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
9731     {INSTALLMESSAGE_INFO, 2, {"", "custom", "2"}, {0, 1, 1}},
9732     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
9733 
9734     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "child2", "Dialog created"}, {0, 1, 1}},
9735 
9736     {INSTALLMESSAGE_INFO, 2, {"", "spawn2", "2"}, {0, 1, 1}},
9737     {0}
9738 };
9739 
9740 static void test_controlevent(void)
9741 {
9742     INSTALLUI_HANDLER_RECORD prev;
9743     MSIHANDLE hdb, hpkg;
9744     UINT r;
9745 
9746     if (!winetest_interactive)
9747     {
9748         skip("interactive ControlEvent tests\n");
9749         return;
9750     }
9751 
9752     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
9753 
9754     /* processing SHOWDIALOG with a record handler causes a crash on XP */
9755     MsiSetExternalUIA(externalui_message_string_callback, INSTALLLOGMODE_SHOWDIALOG, NULL);
9756     r = MsiSetExternalUIRecord(externalui_message_callback, 0xffffffff ^ INSTALLLOGMODE_PROGRESS ^ INSTALLLOGMODE_SHOWDIALOG, NULL, &prev);
9757 
9758     flush_sequence();
9759 
9760     CoInitialize(NULL);
9761 
9762     hdb = create_package_db();
9763     ok(hdb, "failed to create database\n");
9764 
9765     create_file_data("forcecodepage.idt", "\r\n\r\n1252\t_ForceCodepage\r\n");
9766     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
9767     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9768 
9769     r = create_dialog_table(hdb);
9770     ok(r == ERROR_SUCCESS, "failed to create Dialog table: %u\n", r);
9771     r = add_dialog_entry(hdb, "'spawn', 50, 50, 100, 100, 3, 'button'");
9772     ok(r == ERROR_SUCCESS, "failed to insert into Dialog table: %u\n", r);
9773     r = add_dialog_entry(hdb, "'spawn2', 50, 50, 100, 100, 3, 'button'");
9774     ok(r == ERROR_SUCCESS, "failed to insert into Dialog table: %u\n", r);
9775     r = add_dialog_entry(hdb, "'child1', 50, 50, 80, 40, 3, 'exit'");
9776     ok(r == ERROR_SUCCESS, "failed to insert into Dialog table: %u\n", r);
9777     r = add_dialog_entry(hdb, "'child2', 50, 50, 80, 40, 3, 'exit'");
9778     ok(r == ERROR_SUCCESS, "failed to insert into Dialog table: %u\n", r);
9779 
9780     r = create_control_table(hdb);
9781     ok(r == ERROR_SUCCESS, "failed to create Control table: %u\n", r);
9782     r = add_control_entry(hdb, "'spawn', 'button', 'PushButton', 10, 10, 66, 17, 3, 'Click me'");
9783     ok(r == ERROR_SUCCESS, "failed to insert into Control table: %u\n", r);
9784     r = add_control_entry(hdb, "'spawn2', 'button', 'PushButton', 10, 10, 66, 17, 3, 'Click me'");
9785     ok(r == ERROR_SUCCESS, "failed to insert into Control table: %u\n", r);
9786     r = add_control_entry(hdb, "'child1', 'exit', 'PushButton', 10, 10, 66, 17, 3, 'Click me'");
9787     ok(r == ERROR_SUCCESS, "failed to insert into Control table: %u\n", r);
9788     r = add_control_entry(hdb, "'child2', 'exit', 'PushButton', 10, 10, 66, 17, 3, 'Click me'");
9789     ok(r == ERROR_SUCCESS, "failed to insert into Control table: %u\n", r);
9790 
9791     r = create_controlevent_table(hdb);
9792     ok(r == ERROR_SUCCESS, "failed to create ControlEvent table: %u\n", r);
9793     r = add_controlevent_entry(hdb, "'child1', 'exit', 'EndDialog', 'Exit', 1, 1");
9794     ok(r == ERROR_SUCCESS, "failed to insert into ControlEvent table: %u\n", r);
9795     r = add_controlevent_entry(hdb, "'child2', 'exit', 'EndDialog', 'Exit', 1, 1");
9796     ok(r == ERROR_SUCCESS, "failed to insert into ControlEvent table: %u\n", r);
9797 
9798     r = create_custom_action_table(hdb);
9799     ok(r == ERROR_SUCCESS, "failed to create CustomAction table: %u\n", r);
9800     r = add_custom_action_entry(hdb, "'custom', 51, 'dummy', 'dummy value'");
9801     ok(r == ERROR_SUCCESS, "failed to insert into CustomAction table: %u\n", r);
9802 
9803     /* SpawnDialog and EndDialog should trigger after all other events */
9804     r = add_controlevent_entry(hdb, "'spawn', 'button', 'SpawnDialog', 'child1', 1, 1");
9805     ok(r == ERROR_SUCCESS, "failed to insert into ControlEvent table: %u\n", r);
9806     r = add_controlevent_entry(hdb, "'spawn', 'button', 'DoAction', 'custom', 1, 2");
9807     ok(r == ERROR_SUCCESS, "failed to insert into ControlEvent table: %u\n", r);
9808 
9809     /* Multiple dialog events cause only the last one to be triggered */
9810     r = add_controlevent_entry(hdb, "'spawn2', 'button', 'SpawnDialog', 'child1', 1, 1");
9811     ok(r == ERROR_SUCCESS, "failed to insert into ControlEvent table: %u\n", r);
9812     r = add_controlevent_entry(hdb, "'spawn2', 'button', 'SpawnDialog', 'child2', 1, 2");
9813     ok(r == ERROR_SUCCESS, "failed to insert into ControlEvent table: %u\n", r);
9814     r = add_controlevent_entry(hdb, "'spawn2', 'button', 'DoAction', 'custom', 1, 3");
9815     ok(r == ERROR_SUCCESS, "failed to insert into ControlEvent table: %u\n", r);
9816 
9817     r = package_from_db(hdb, &hpkg);
9818     ok(r == ERROR_SUCCESS, "failed to create package: %u\n", r);
9819     ok_sequence(openpackage_sequence, "MsiOpenPackage()", FALSE);
9820 
9821     r = MsiDoActionA(hpkg, "spawn");
9822     ok(r == ERROR_INSTALL_USEREXIT, "expected ERROR_INSTALL_USEREXIT, got %u\n", r);
9823     ok_sequence(controlevent_spawn_sequence, "control event: spawn", FALSE);
9824 
9825     r = MsiDoActionA(hpkg, "spawn2");
9826     ok(r == ERROR_INSTALL_USEREXIT, "expected ERROR_INSTALL_USEREXIT, got %u\n", r);
9827     ok_sequence(controlevent_spawn2_sequence, "control event: spawn2", FALSE);
9828 
9829     MsiCloseHandle(hpkg);
9830     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
9831 
9832     CoUninitialize();
9833     DeleteFileA(msifile);
9834     DeleteFileA("forcecodepage.idt");
9835 }
9836 
9837 START_TEST(package)
9838 {
9839     STATEMGRSTATUS status;
9840     BOOL ret = FALSE;
9841 
9842     init_functionpointers();
9843 
9844     if (pIsWow64Process)
9845         pIsWow64Process(GetCurrentProcess(), &is_wow64);
9846 
9847     GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
9848 
9849     /* Create a restore point ourselves so we circumvent the multitude of restore points
9850      * that would have been created by all the installation and removal tests.
9851      *
9852      * This is not needed on version 5.0 where setting MSIFASTINSTALL prevents the
9853      * creation of restore points.
9854      */
9855     if (pSRSetRestorePointA && !pMsiGetComponentPathExA)
9856     {
9857         memset(&status, 0, sizeof(status));
9858         ret = notify_system_change(BEGIN_NESTED_SYSTEM_CHANGE, &status);
9859     }
9860 
9861     test_createpackage();
9862     test_doaction();
9863     test_gettargetpath_bad();
9864     test_settargetpath();
9865     test_props();
9866     test_property_table();
9867     test_condition();
9868     test_msipackage();
9869     test_formatrecord2();
9870     test_states();
9871     test_getproperty();
9872     test_removefiles();
9873     test_appsearch();
9874     test_appsearch_complocator();
9875     test_appsearch_reglocator();
9876     test_appsearch_inilocator();
9877     test_appsearch_drlocator();
9878     test_featureparents();
9879     test_installprops();
9880     test_launchconditions();
9881     test_ccpsearch();
9882     test_complocator();
9883     test_MsiGetSourcePath();
9884     test_shortlongsource();
9885     test_sourcedir();
9886     test_access();
9887     test_emptypackage();
9888     test_MsiGetProductProperty();
9889     test_MsiSetProperty();
9890     test_MsiApplyMultiplePatches();
9891     test_MsiApplyPatch();
9892     test_MsiEnumComponentCosts();
9893     test_MsiDatabaseCommit();
9894     test_externalui();
9895     test_externalui_message();
9896     test_controlevent();
9897 
9898     if (pSRSetRestorePointA && !pMsiGetComponentPathExA && ret)
9899     {
9900         ret = notify_system_change(END_NESTED_SYSTEM_CHANGE, &status);
9901         if (ret)
9902             remove_restore_point(status.llSequenceNumber);
9903     }
9904 }
9905