1 /*
2  * tests for Microsoft Installer functionality
3  *
4  * Copyright 2005 Mike McCormack for CodeWeavers
5  * Copyright 2005 Aric Stewart for CodeWeavers
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21 
22 #define COBJMACROS
23 
24 #include <assert.h>
25 #include <stdio.h>
26 #include <windows.h>
27 #include <msidefs.h>
28 #include <msi.h>
29 #include <msiquery.h>
30 #include <srrestoreptapi.h>
31 #include <shlobj.h>
32 
33 #include "wine/test.h"
34 
35 static BOOL is_wow64;
36 static const char msifile[] = "winetest-package.msi";
37 static const WCHAR msifileW[] =
38     {'w','i','n','e','t','e','s','t','-','p','a','c','k','a','g','e','.','m','s','i',0};
39 static char CURR_DIR[MAX_PATH];
40 
41 static INSTALLSTATE (WINAPI *pMsiGetComponentPathExA)(LPCSTR, LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPSTR, LPDWORD);
42 static HRESULT (WINAPI *pSHGetFolderPathA)(HWND, int, HANDLE, DWORD, LPSTR);
43 
44 static BOOL (WINAPI *pCheckTokenMembership)(HANDLE,PSID,PBOOL);
45 static BOOL (WINAPI *pConvertSidToStringSidA)(PSID, LPSTR*);
46 static BOOL (WINAPI *pOpenProcessToken)( HANDLE, DWORD, PHANDLE );
47 static LONG (WINAPI *pRegDeleteKeyExA)(HKEY, LPCSTR, REGSAM, DWORD);
48 static LONG (WINAPI *pRegDeleteKeyExW)(HKEY, LPCWSTR, REGSAM, DWORD);
49 static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
50 static void (WINAPI *pGetSystemInfo)(LPSYSTEM_INFO);
51 static void (WINAPI *pGetNativeSystemInfo)(LPSYSTEM_INFO);
52 static UINT (WINAPI *pGetSystemWow64DirectoryA)(LPSTR, UINT);
53 
54 static BOOL (WINAPI *pSRRemoveRestorePoint)(DWORD);
55 static BOOL (WINAPI *pSRSetRestorePointA)(RESTOREPOINTINFOA*, STATEMGRSTATUS*);
56 
57 static void init_functionpointers(void)
58 {
59     HMODULE hmsi = GetModuleHandleA("msi.dll");
60     HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
61     HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
62     HMODULE hshell32 = GetModuleHandleA("shell32.dll");
63     HMODULE hsrclient;
64 
65 #define GET_PROC(mod, func) \
66     p ## func = (void*)GetProcAddress(mod, #func);
67 
68     GET_PROC(hmsi, MsiGetComponentPathExA);
69     GET_PROC(hshell32, SHGetFolderPathA);
70 
71     GET_PROC(hadvapi32, CheckTokenMembership);
72     GET_PROC(hadvapi32, ConvertSidToStringSidA);
73     GET_PROC(hadvapi32, OpenProcessToken);
74     GET_PROC(hadvapi32, RegDeleteKeyExA)
75     GET_PROC(hadvapi32, RegDeleteKeyExW)
76     GET_PROC(hkernel32, IsWow64Process)
77     GET_PROC(hkernel32, GetNativeSystemInfo)
78     GET_PROC(hkernel32, GetSystemInfo)
79     GET_PROC(hkernel32, GetSystemWow64DirectoryA)
80 
81     hsrclient = LoadLibraryA("srclient.dll");
82     GET_PROC(hsrclient, SRRemoveRestorePoint);
83     GET_PROC(hsrclient, SRSetRestorePointA);
84 #undef GET_PROC
85 }
86 
87 static BOOL is_process_limited(void)
88 {
89     SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
90     PSID Group = NULL;
91     BOOL IsInGroup;
92     HANDLE token;
93 
94     if (!pCheckTokenMembership || !pOpenProcessToken) return FALSE;
95 
96     if (!AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
97                                   DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &Group) ||
98         !pCheckTokenMembership(NULL, Group, &IsInGroup))
99     {
100         trace("Could not check if the current user is an administrator\n");
101         FreeSid(Group);
102         return FALSE;
103     }
104     FreeSid(Group);
105 
106     if (!IsInGroup)
107     {
108         if (!AllocateAndInitializeSid(&NtAuthority, 2,
109                                       SECURITY_BUILTIN_DOMAIN_RID,
110                                       DOMAIN_ALIAS_RID_POWER_USERS,
111                                       0, 0, 0, 0, 0, 0, &Group) ||
112             !pCheckTokenMembership(NULL, Group, &IsInGroup))
113         {
114             trace("Could not check if the current user is a power user\n");
115             return FALSE;
116         }
117         if (!IsInGroup)
118         {
119             /* Only administrators and power users can be powerful */
120             return TRUE;
121         }
122     }
123 
124     if (pOpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
125     {
126         BOOL ret;
127         TOKEN_ELEVATION_TYPE type = TokenElevationTypeDefault;
128         DWORD size;
129 
130         ret = GetTokenInformation(token, TokenElevationType, &type, sizeof(type), &size);
131         CloseHandle(token);
132         return (ret && type == TokenElevationTypeLimited);
133     }
134     return FALSE;
135 }
136 
137 static LONG delete_key( HKEY key, LPCSTR subkey, REGSAM access )
138 {
139     if (pRegDeleteKeyExA)
140         return pRegDeleteKeyExA( key, subkey, access, 0 );
141     return RegDeleteKeyA( key, subkey );
142 }
143 
144 static char *get_user_sid(void)
145 {
146     HANDLE token;
147     DWORD size = 0;
148     TOKEN_USER *user;
149     char *usersid = NULL;
150 
151     if (!pConvertSidToStringSidA)
152     {
153         win_skip("ConvertSidToStringSidA is not available\n");
154         return NULL;
155     }
156     OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
157     GetTokenInformation(token, TokenUser, NULL, size, &size);
158 
159     user = HeapAlloc(GetProcessHeap(), 0, size);
160     GetTokenInformation(token, TokenUser, user, size, &size);
161     pConvertSidToStringSidA(user->User.Sid, &usersid);
162     HeapFree(GetProcessHeap(), 0, user);
163 
164     CloseHandle(token);
165     return usersid;
166 }
167 
168 /* RegDeleteTreeW from dlls/advapi32/registry.c */
169 static LSTATUS package_RegDeleteTreeW(HKEY hKey, LPCWSTR lpszSubKey, REGSAM access)
170 {
171     LONG ret;
172     DWORD dwMaxSubkeyLen, dwMaxValueLen;
173     DWORD dwMaxLen, dwSize;
174     WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
175     HKEY hSubKey = hKey;
176 
177     if(lpszSubKey)
178     {
179         ret = RegOpenKeyExW(hKey, lpszSubKey, 0, access, &hSubKey);
180         if (ret) return ret;
181     }
182 
183     ret = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL,
184             &dwMaxSubkeyLen, NULL, NULL, &dwMaxValueLen, NULL, NULL, NULL);
185     if (ret) goto cleanup;
186 
187     dwMaxSubkeyLen++;
188     dwMaxValueLen++;
189     dwMaxLen = max(dwMaxSubkeyLen, dwMaxValueLen);
190     if (dwMaxLen > sizeof(szNameBuf)/sizeof(WCHAR))
191     {
192         /* Name too big: alloc a buffer for it */
193         if (!(lpszName = HeapAlloc( GetProcessHeap(), 0, dwMaxLen*sizeof(WCHAR))))
194         {
195             ret = ERROR_NOT_ENOUGH_MEMORY;
196             goto cleanup;
197         }
198     }
199 
200     /* Recursively delete all the subkeys */
201     while (TRUE)
202     {
203         dwSize = dwMaxLen;
204         if (RegEnumKeyExW(hSubKey, 0, lpszName, &dwSize, NULL,
205                           NULL, NULL, NULL)) break;
206 
207         ret = package_RegDeleteTreeW(hSubKey, lpszName, access);
208         if (ret) goto cleanup;
209     }
210 
211     if (lpszSubKey)
212     {
213         if (pRegDeleteKeyExW)
214             ret = pRegDeleteKeyExW(hKey, lpszSubKey, access, 0);
215         else
216             ret = RegDeleteKeyW(hKey, lpszSubKey);
217     }
218     else
219         while (TRUE)
220         {
221             dwSize = dwMaxLen;
222             if (RegEnumValueW(hKey, 0, lpszName, &dwSize,
223                   NULL, NULL, NULL, NULL)) break;
224 
225             ret = RegDeleteValueW(hKey, lpszName);
226             if (ret) goto cleanup;
227         }
228 
229 cleanup:
230     if (lpszName != szNameBuf)
231         HeapFree(GetProcessHeap(), 0, lpszName);
232     if(lpszSubKey)
233         RegCloseKey(hSubKey);
234     return ret;
235 }
236 
237 static BOOL squash_guid(LPCWSTR in, LPWSTR out)
238 {
239     DWORD i,n=1;
240     GUID guid;
241 
242     if (FAILED(CLSIDFromString((LPCOLESTR)in, &guid)))
243         return FALSE;
244 
245     for(i=0; i<8; i++)
246         out[7-i] = in[n++];
247     n++;
248     for(i=0; i<4; i++)
249         out[11-i] = in[n++];
250     n++;
251     for(i=0; i<4; i++)
252         out[15-i] = in[n++];
253     n++;
254     for(i=0; i<2; i++)
255     {
256         out[17+i*2] = in[n++];
257         out[16+i*2] = in[n++];
258     }
259     n++;
260     for( ; i<8; i++)
261     {
262         out[17+i*2] = in[n++];
263         out[16+i*2] = in[n++];
264     }
265     out[32]=0;
266     return TRUE;
267 }
268 
269 static void create_test_guid(LPSTR prodcode, LPSTR squashed)
270 {
271     WCHAR guidW[MAX_PATH];
272     WCHAR squashedW[MAX_PATH];
273     GUID guid;
274     HRESULT hr;
275     int size;
276 
277     hr = CoCreateGuid(&guid);
278     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
279 
280     size = StringFromGUID2(&guid, guidW, MAX_PATH);
281     ok(size == 39, "Expected 39, got %d\n", hr);
282 
283     WideCharToMultiByte(CP_ACP, 0, guidW, size, prodcode, MAX_PATH, NULL, NULL);
284     squash_guid(guidW, squashedW);
285     WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
286 }
287 
288 static void set_component_path(LPCSTR filename, MSIINSTALLCONTEXT context,
289                                LPCSTR guid, LPSTR usersid, BOOL dir)
290 {
291     WCHAR guidW[MAX_PATH];
292     WCHAR squashedW[MAX_PATH];
293     CHAR squashed[MAX_PATH];
294     CHAR comppath[MAX_PATH];
295     CHAR prodpath[MAX_PATH];
296     CHAR path[MAX_PATH];
297     LPCSTR prod = NULL;
298     HKEY hkey;
299     REGSAM access = KEY_ALL_ACCESS;
300 
301     if (is_wow64)
302         access |= KEY_WOW64_64KEY;
303 
304     MultiByteToWideChar(CP_ACP, 0, guid, -1, guidW, MAX_PATH);
305     squash_guid(guidW, squashedW);
306     WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
307 
308     if (context == MSIINSTALLCONTEXT_MACHINE)
309     {
310         prod = "3D0DAE300FACA1300AD792060BCDAA92";
311         sprintf(comppath,
312                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
313                 "Installer\\UserData\\S-1-5-18\\Components\\%s", squashed);
314         lstrcpyA(prodpath,
315                  "SOFTWARE\\Classes\\Installer\\"
316                  "Products\\3D0DAE300FACA1300AD792060BCDAA92");
317     }
318     else if (context == MSIINSTALLCONTEXT_USERUNMANAGED)
319     {
320         prod = "7D2F387510109040002000060BECB6AB";
321         sprintf(comppath,
322                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
323                 "Installer\\UserData\\%s\\Components\\%s", usersid, squashed);
324         sprintf(prodpath,
325                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
326                 "Installer\\%s\\Installer\\Products\\"
327                 "7D2F387510109040002000060BECB6AB", usersid);
328     }
329     else if (context == MSIINSTALLCONTEXT_USERMANAGED)
330     {
331         prod = "7D2F387510109040002000060BECB6AB";
332         sprintf(comppath,
333                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
334                 "Installer\\UserData\\%s\\Components\\%s", usersid, squashed);
335         sprintf(prodpath,
336                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
337                 "Installer\\Managed\\%s\\Installer\\Products\\"
338                 "7D2F387510109040002000060BECB6AB", usersid);
339     }
340 
341     RegCreateKeyExA(HKEY_LOCAL_MACHINE, comppath, 0, NULL, 0, access, NULL, &hkey, NULL);
342 
343     lstrcpyA(path, CURR_DIR);
344     lstrcatA(path, "\\");
345     if (!dir) lstrcatA(path, filename);
346 
347     RegSetValueExA(hkey, prod, 0, REG_SZ, (LPBYTE)path, lstrlenA(path));
348     RegCloseKey(hkey);
349 
350     RegCreateKeyExA(HKEY_LOCAL_MACHINE, prodpath, 0, NULL, 0, access, NULL, &hkey, NULL);
351     RegCloseKey(hkey);
352 }
353 
354 static void delete_component_path(LPCSTR guid, MSIINSTALLCONTEXT context, LPSTR usersid)
355 {
356     WCHAR guidW[MAX_PATH];
357     WCHAR squashedW[MAX_PATH];
358     WCHAR substrW[MAX_PATH];
359     CHAR squashed[MAX_PATH];
360     CHAR comppath[MAX_PATH];
361     CHAR prodpath[MAX_PATH];
362     REGSAM access = KEY_ALL_ACCESS;
363 
364     if (is_wow64)
365         access |= KEY_WOW64_64KEY;
366 
367     MultiByteToWideChar(CP_ACP, 0, guid, -1, guidW, MAX_PATH);
368     squash_guid(guidW, squashedW);
369     WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
370 
371     if (context == MSIINSTALLCONTEXT_MACHINE)
372     {
373         sprintf(comppath,
374                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
375                 "Installer\\UserData\\S-1-5-18\\Components\\%s", squashed);
376         lstrcpyA(prodpath,
377                  "SOFTWARE\\Classes\\Installer\\"
378                  "Products\\3D0DAE300FACA1300AD792060BCDAA92");
379     }
380     else if (context == MSIINSTALLCONTEXT_USERUNMANAGED)
381     {
382         sprintf(comppath,
383                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
384                 "Installer\\UserData\\%s\\Components\\%s", usersid, squashed);
385         sprintf(prodpath,
386                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
387                 "Installer\\%s\\Installer\\Products\\"
388                 "7D2F387510109040002000060BECB6AB", usersid);
389     }
390     else if (context == MSIINSTALLCONTEXT_USERMANAGED)
391     {
392         sprintf(comppath,
393                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
394                 "Installer\\UserData\\%s\\Components\\%s", usersid, squashed);
395         sprintf(prodpath,
396                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
397                 "Installer\\Managed\\%s\\Installer\\Products\\"
398                 "7D2F387510109040002000060BECB6AB", usersid);
399     }
400 
401     MultiByteToWideChar(CP_ACP, 0, comppath, -1, substrW, MAX_PATH);
402     package_RegDeleteTreeW(HKEY_LOCAL_MACHINE, substrW, access);
403 
404     MultiByteToWideChar(CP_ACP, 0, prodpath, -1, substrW, MAX_PATH);
405     package_RegDeleteTreeW(HKEY_LOCAL_MACHINE, substrW, access);
406 }
407 
408 static UINT do_query(MSIHANDLE hdb, const char *query, MSIHANDLE *phrec)
409 {
410     MSIHANDLE hview = 0;
411     UINT r, ret;
412 
413     /* open a select query */
414     r = MsiDatabaseOpenViewA(hdb, query, &hview);
415     if (r != ERROR_SUCCESS)
416         return r;
417     r = MsiViewExecute(hview, 0);
418     if (r != ERROR_SUCCESS)
419         return r;
420     ret = MsiViewFetch(hview, phrec);
421     r = MsiViewClose(hview);
422     if (r != ERROR_SUCCESS)
423         return r;
424     r = MsiCloseHandle(hview);
425     if (r != ERROR_SUCCESS)
426         return r;
427     return ret;
428 }
429 
430 static UINT run_query( MSIHANDLE hdb, const char *query )
431 {
432     MSIHANDLE hview = 0;
433     UINT r;
434 
435     r = MsiDatabaseOpenViewA(hdb, query, &hview);
436     if( r != ERROR_SUCCESS )
437         return r;
438 
439     r = MsiViewExecute(hview, 0);
440     if( r == ERROR_SUCCESS )
441         r = MsiViewClose(hview);
442     MsiCloseHandle(hview);
443     return r;
444 }
445 
446 static UINT create_component_table( MSIHANDLE hdb )
447 {
448     return run_query( hdb,
449             "CREATE TABLE `Component` ( "
450             "`Component` CHAR(72) NOT NULL, "
451             "`ComponentId` CHAR(38), "
452             "`Directory_` CHAR(72) NOT NULL, "
453             "`Attributes` SHORT NOT NULL, "
454             "`Condition` CHAR(255), "
455             "`KeyPath` CHAR(72) "
456             "PRIMARY KEY `Component`)" );
457 }
458 
459 static UINT create_feature_table( MSIHANDLE hdb )
460 {
461     return run_query( hdb,
462             "CREATE TABLE `Feature` ( "
463             "`Feature` CHAR(38) NOT NULL, "
464             "`Feature_Parent` CHAR(38), "
465             "`Title` CHAR(64), "
466             "`Description` CHAR(255), "
467             "`Display` SHORT NOT NULL, "
468             "`Level` SHORT NOT NULL, "
469             "`Directory_` CHAR(72), "
470             "`Attributes` SHORT NOT NULL "
471             "PRIMARY KEY `Feature`)" );
472 }
473 
474 static UINT create_feature_components_table( MSIHANDLE hdb )
475 {
476     return run_query( hdb,
477             "CREATE TABLE `FeatureComponents` ( "
478             "`Feature_` CHAR(38) NOT NULL, "
479             "`Component_` CHAR(72) NOT NULL "
480             "PRIMARY KEY `Feature_`, `Component_` )" );
481 }
482 
483 static UINT create_file_table( MSIHANDLE hdb )
484 {
485     return run_query( hdb,
486             "CREATE TABLE `File` ("
487             "`File` CHAR(72) NOT NULL, "
488             "`Component_` CHAR(72) NOT NULL, "
489             "`FileName` CHAR(255) NOT NULL, "
490             "`FileSize` LONG NOT NULL, "
491             "`Version` CHAR(72), "
492             "`Language` CHAR(20), "
493             "`Attributes` SHORT, "
494             "`Sequence` SHORT NOT NULL "
495             "PRIMARY KEY `File`)" );
496 }
497 
498 static UINT create_remove_file_table( MSIHANDLE hdb )
499 {
500     return run_query( hdb,
501             "CREATE TABLE `RemoveFile` ("
502             "`FileKey` CHAR(72) NOT NULL, "
503             "`Component_` CHAR(72) NOT NULL, "
504             "`FileName` CHAR(255) LOCALIZABLE, "
505             "`DirProperty` CHAR(72) NOT NULL, "
506             "`InstallMode` SHORT NOT NULL "
507             "PRIMARY KEY `FileKey`)" );
508 }
509 
510 static UINT create_appsearch_table( MSIHANDLE hdb )
511 {
512     return run_query( hdb,
513             "CREATE TABLE `AppSearch` ("
514             "`Property` CHAR(72) NOT NULL, "
515             "`Signature_` CHAR(72) NOT NULL "
516             "PRIMARY KEY `Property`, `Signature_`)" );
517 }
518 
519 static UINT create_reglocator_table( MSIHANDLE hdb )
520 {
521     return run_query( hdb,
522             "CREATE TABLE `RegLocator` ("
523             "`Signature_` CHAR(72) NOT NULL, "
524             "`Root` SHORT NOT NULL, "
525             "`Key` CHAR(255) NOT NULL, "
526             "`Name` CHAR(255), "
527             "`Type` SHORT "
528             "PRIMARY KEY `Signature_`)" );
529 }
530 
531 static UINT create_signature_table( MSIHANDLE hdb )
532 {
533     return run_query( hdb,
534             "CREATE TABLE `Signature` ("
535             "`Signature` CHAR(72) NOT NULL, "
536             "`FileName` CHAR(255) NOT NULL, "
537             "`MinVersion` CHAR(20), "
538             "`MaxVersion` CHAR(20), "
539             "`MinSize` LONG, "
540             "`MaxSize` LONG, "
541             "`MinDate` LONG, "
542             "`MaxDate` LONG, "
543             "`Languages` CHAR(255) "
544             "PRIMARY KEY `Signature`)" );
545 }
546 
547 static UINT create_launchcondition_table( MSIHANDLE hdb )
548 {
549     return run_query( hdb,
550             "CREATE TABLE `LaunchCondition` ("
551             "`Condition` CHAR(255) NOT NULL, "
552             "`Description` CHAR(255) NOT NULL "
553             "PRIMARY KEY `Condition`)" );
554 }
555 
556 static UINT create_property_table( MSIHANDLE hdb )
557 {
558     return run_query( hdb,
559             "CREATE TABLE `Property` ("
560             "`Property` CHAR(72) NOT NULL, "
561             "`Value` CHAR(0) "
562             "PRIMARY KEY `Property`)" );
563 }
564 
565 static UINT create_install_execute_sequence_table( MSIHANDLE hdb )
566 {
567     return run_query( hdb,
568             "CREATE TABLE `InstallExecuteSequence` ("
569             "`Action` CHAR(72) NOT NULL, "
570             "`Condition` CHAR(255), "
571             "`Sequence` SHORT "
572             "PRIMARY KEY `Action`)" );
573 }
574 
575 static UINT create_media_table( MSIHANDLE hdb )
576 {
577     return run_query( hdb,
578             "CREATE TABLE `Media` ("
579             "`DiskId` SHORT NOT NULL, "
580             "`LastSequence` SHORT NOT NULL, "
581             "`DiskPrompt` CHAR(64), "
582             "`Cabinet` CHAR(255), "
583             "`VolumeLabel` CHAR(32), "
584             "`Source` CHAR(72) "
585             "PRIMARY KEY `DiskId`)" );
586 }
587 
588 static UINT create_ccpsearch_table( MSIHANDLE hdb )
589 {
590     return run_query( hdb,
591             "CREATE TABLE `CCPSearch` ("
592             "`Signature_` CHAR(72) NOT NULL "
593             "PRIMARY KEY `Signature_`)" );
594 }
595 
596 static UINT create_drlocator_table( MSIHANDLE hdb )
597 {
598     return run_query( hdb,
599             "CREATE TABLE `DrLocator` ("
600             "`Signature_` CHAR(72) NOT NULL, "
601             "`Parent` CHAR(72), "
602             "`Path` CHAR(255), "
603             "`Depth` SHORT "
604             "PRIMARY KEY `Signature_`, `Parent`, `Path`)" );
605 }
606 
607 static UINT create_complocator_table( MSIHANDLE hdb )
608 {
609     return run_query( hdb,
610             "CREATE TABLE `CompLocator` ("
611             "`Signature_` CHAR(72) NOT NULL, "
612             "`ComponentId` CHAR(38) NOT NULL, "
613             "`Type` SHORT "
614             "PRIMARY KEY `Signature_`)" );
615 }
616 
617 static UINT create_inilocator_table( MSIHANDLE hdb )
618 {
619     return run_query( hdb,
620             "CREATE TABLE `IniLocator` ("
621             "`Signature_` CHAR(72) NOT NULL, "
622             "`FileName` CHAR(255) NOT NULL, "
623             "`Section` CHAR(96)NOT NULL, "
624             "`Key` CHAR(128)NOT NULL, "
625             "`Field` SHORT, "
626             "`Type` SHORT "
627             "PRIMARY KEY `Signature_`)" );
628 }
629 
630 static UINT create_custom_action_table( MSIHANDLE hdb )
631 {
632     return run_query( hdb,
633             "CREATE TABLE `CustomAction` ("
634             "`Action` CHAR(72) NOT NULL, "
635             "`Type` SHORT NOT NULL, "
636             "`Source` CHAR(75), "
637             "`Target` CHAR(255) "
638             "PRIMARY KEY `Action`)" );
639 }
640 
641 static UINT create_dialog_table( MSIHANDLE hdb )
642 {
643     return run_query(hdb,
644             "CREATE TABLE `Dialog` ("
645             "`Dialog` CHAR(72) NOT NULL, "
646             "`HCentering` SHORT NOT NULL, "
647             "`VCentering` SHORT NOT NULL, "
648             "`Width` SHORT NOT NULL, "
649             "`Height` SHORT NOT NULL, "
650             "`Attributes` LONG, "
651             "`Title` CHAR(128) LOCALIZABLE, "
652             "`Control_First` CHAR(50) NOT NULL, "
653             "`Control_Default` CHAR(50), "
654             "`Control_Cancel` CHAR(50) "
655             "PRIMARY KEY `Dialog`)");
656 }
657 
658 static UINT create_control_table( MSIHANDLE hdb )
659 {
660     return run_query(hdb,
661             "CREATE TABLE `Control` ("
662             "`Dialog_` CHAR(72) NOT NULL, "
663             "`Control` CHAR(50) NOT NULL, "
664             "`Type` CHAR(20) NOT NULL, "
665             "`X` SHORT NOT NULL, "
666             "`Y` SHORT NOT NULL, "
667             "`Width` SHORT NOT NULL, "
668             "`Height` SHORT NOT NULL, "
669             "`Attributes` LONG, "
670             "`Property` CHAR(50), "
671             "`Text` CHAR(0) LOCALIZABLE, "
672             "`Control_Next` CHAR(50), "
673             "`Help` CHAR(255) LOCALIZABLE "
674             "PRIMARY KEY `Dialog_`, `Control`)");
675 }
676 
677 static UINT create_controlevent_table( MSIHANDLE hdb )
678 {
679     return run_query(hdb,
680             "CREATE TABLE `ControlEvent` ("
681             "`Dialog_` CHAR(72) NOT NULL, "
682             "`Control_` CHAR(50) NOT NULL, "
683             "`Event` CHAR(50) NOT NULL, "
684             "`Argument` CHAR(255) NOT NULL, "
685             "`Condition` CHAR(255), "
686             "`Ordering` SHORT "
687             "PRIMARY KEY `Dialog_`, `Control_`, `Event`, `Argument`, `Condition`)");
688 }
689 
690 static UINT create_actiontext_table( MSIHANDLE hdb )
691 {
692     return run_query(hdb,
693             "CREATE TABLE `ActionText` ("
694             "`Action` CHAR(72) NOT NULL, "
695             "`Description` CHAR(64) LOCALIZABLE, "
696             "`Template` CHAR(128) LOCALIZABLE "
697             "PRIMARY KEY `Action`)");
698 }
699 
700 #define make_add_entry(type, qtext) \
701     static UINT add##_##type##_##entry( MSIHANDLE hdb, const char *values ) \
702     { \
703         char insert[] = qtext; \
704         char *query; \
705         UINT sz, r; \
706         sz = strlen(values) + sizeof insert; \
707         query = HeapAlloc(GetProcessHeap(),0,sz); \
708         sprintf(query,insert,values); \
709         r = run_query( hdb, query ); \
710         HeapFree(GetProcessHeap(), 0, query); \
711         return r; \
712     }
713 
714 make_add_entry(component,
715                "INSERT INTO `Component`  "
716                "(`Component`, `ComponentId`, `Directory_`, "
717                "`Attributes`, `Condition`, `KeyPath`) VALUES( %s )")
718 
719 make_add_entry(directory,
720                "INSERT INTO `Directory` "
721                "(`Directory`,`Directory_Parent`,`DefaultDir`) VALUES( %s )")
722 
723 make_add_entry(feature,
724                "INSERT INTO `Feature` "
725                "(`Feature`, `Feature_Parent`, `Title`, `Description`, "
726                "`Display`, `Level`, `Directory_`, `Attributes`) VALUES( %s )")
727 
728 make_add_entry(feature_components,
729                "INSERT INTO `FeatureComponents` "
730                "(`Feature_`, `Component_`) VALUES( %s )")
731 
732 make_add_entry(file,
733                "INSERT INTO `File` "
734                "(`File`, `Component_`, `FileName`, `FileSize`, "
735                "`Version`, `Language`, `Attributes`, `Sequence`) VALUES( %s )")
736 
737 make_add_entry(appsearch,
738                "INSERT INTO `AppSearch` "
739                "(`Property`, `Signature_`) VALUES( %s )")
740 
741 make_add_entry(signature,
742                "INSERT INTO `Signature` "
743                "(`Signature`, `FileName`, `MinVersion`, `MaxVersion`,"
744                " `MinSize`, `MaxSize`, `MinDate`, `MaxDate`, `Languages`) "
745                "VALUES( %s )")
746 
747 make_add_entry(launchcondition,
748                "INSERT INTO `LaunchCondition` "
749                "(`Condition`, `Description`) VALUES( %s )")
750 
751 make_add_entry(property,
752                "INSERT INTO `Property` (`Property`, `Value`) VALUES( %s )")
753 
754 make_add_entry(install_execute_sequence,
755                "INSERT INTO `InstallExecuteSequence` "
756                "(`Action`, `Condition`, `Sequence`) VALUES( %s )")
757 
758 make_add_entry(media,
759                "INSERT INTO `Media` "
760                "(`DiskId`, `LastSequence`, `DiskPrompt`, "
761                "`Cabinet`, `VolumeLabel`, `Source`) VALUES( %s )")
762 
763 make_add_entry(ccpsearch,
764                "INSERT INTO `CCPSearch` (`Signature_`) VALUES( %s )")
765 
766 make_add_entry(drlocator,
767                "INSERT INTO `DrLocator` "
768                "(`Signature_`, `Parent`, `Path`, `Depth`) VALUES( %s )")
769 
770 make_add_entry(complocator,
771                "INSERT INTO `CompLocator` "
772                "(`Signature_`, `ComponentId`, `Type`) VALUES( %s )")
773 
774 make_add_entry(inilocator,
775                "INSERT INTO `IniLocator` "
776                "(`Signature_`, `FileName`, `Section`, `Key`, `Field`, `Type`) "
777                "VALUES( %s )")
778 
779 make_add_entry(custom_action,
780                "INSERT INTO `CustomAction`  "
781                "(`Action`, `Type`, `Source`, `Target`) VALUES( %s )")
782 
783 make_add_entry(dialog,
784                "INSERT INTO `Dialog` "
785                "(`Dialog`, `HCentering`, `VCentering`, `Width`, `Height`, `Attributes`, `Control_First`) VALUES ( %s )")
786 
787 make_add_entry(control,
788                "INSERT INTO `Control` "
789                "(`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, `Attributes`, `Text`) VALUES( %s )");
790 
791 make_add_entry(controlevent,
792                "INSERT INTO `ControlEvent` "
793                "(`Dialog_`, `Control_`, `Event`, `Argument`, `Condition`, `Ordering`) VALUES( %s )");
794 
795 make_add_entry(actiontext,
796                "INSERT INTO `ActionText` "
797                "(`Action`, `Description`, `Template`) VALUES( %s )");
798 
799 static UINT add_reglocator_entry( MSIHANDLE hdb, const char *sig, UINT root, const char *path,
800                                   const char *name, UINT type )
801 {
802     const char insert[] =
803         "INSERT INTO `RegLocator` (`Signature_`, `Root`, `Key`, `Name`, `Type`) "
804         "VALUES( '%s', %u, '%s', '%s', %u )";
805     char *query;
806     UINT sz, r;
807 
808     sz = strlen( sig ) + 10 + strlen( path ) + strlen( name ) + 10 + sizeof( insert );
809     query = HeapAlloc( GetProcessHeap(), 0, sz );
810     sprintf( query, insert, sig, root, path, name, type );
811     r = run_query( hdb, query );
812     HeapFree( GetProcessHeap(), 0, query );
813     return r;
814 }
815 
816 static UINT set_summary_info(MSIHANDLE hdb)
817 {
818     UINT res;
819     MSIHANDLE suminfo;
820 
821     /* build summary info */
822     res = MsiGetSummaryInformationA(hdb, NULL, 7, &suminfo);
823     ok( res == ERROR_SUCCESS , "Failed to open summaryinfo\n" );
824 
825     res = MsiSummaryInfoSetPropertyA(suminfo,2, VT_LPSTR, 0,NULL,
826                         "Installation Database");
827     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
828 
829     res = MsiSummaryInfoSetPropertyA(suminfo,3, VT_LPSTR, 0,NULL,
830                         "Installation Database");
831     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
832 
833     res = MsiSummaryInfoSetPropertyA(suminfo,4, VT_LPSTR, 0,NULL,
834                         "Wine Hackers");
835     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
836 
837     res = MsiSummaryInfoSetPropertyA(suminfo,7, VT_LPSTR, 0,NULL,
838                     ";1033");
839     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
840 
841     res = MsiSummaryInfoSetPropertyA(suminfo,9, VT_LPSTR, 0,NULL,
842                     "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}");
843     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
844 
845     res = MsiSummaryInfoSetPropertyA(suminfo, 14, VT_I4, 100, NULL, NULL);
846     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
847 
848     res = MsiSummaryInfoSetPropertyA(suminfo, 15, VT_I4, 0, NULL, NULL);
849     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
850 
851     res = MsiSummaryInfoPersist(suminfo);
852     ok( res == ERROR_SUCCESS , "Failed to make summary info persist\n" );
853 
854     res = MsiCloseHandle( suminfo);
855     ok( res == ERROR_SUCCESS , "Failed to close suminfo\n" );
856 
857     return res;
858 }
859 
860 
861 static MSIHANDLE create_package_db(void)
862 {
863     MSIHANDLE hdb = 0;
864     UINT res;
865 
866     DeleteFileA(msifile);
867 
868     /* create an empty database */
869     res = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb );
870     ok( res == ERROR_SUCCESS , "Failed to create database %u\n", res );
871     if( res != ERROR_SUCCESS )
872         return hdb;
873 
874     res = MsiDatabaseCommit( hdb );
875     ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
876 
877     res = set_summary_info(hdb);
878     ok( res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", res);
879 
880     res = run_query( hdb,
881             "CREATE TABLE `Directory` ( "
882             "`Directory` CHAR(255) NOT NULL, "
883             "`Directory_Parent` CHAR(255), "
884             "`DefaultDir` CHAR(255) NOT NULL "
885             "PRIMARY KEY `Directory`)" );
886     ok( res == ERROR_SUCCESS , "Failed to create directory table\n" );
887 
888     return hdb;
889 }
890 
891 static UINT package_from_db(MSIHANDLE hdb, MSIHANDLE *handle)
892 {
893     UINT res;
894     CHAR szPackage[12];
895     MSIHANDLE hPackage;
896 
897     sprintf(szPackage, "#%u", hdb);
898     res = MsiOpenPackageA(szPackage, &hPackage);
899     if (res != ERROR_SUCCESS)
900     {
901         MsiCloseHandle(hdb);
902         return res;
903     }
904 
905     res = MsiCloseHandle(hdb);
906     if (res != ERROR_SUCCESS)
907     {
908         MsiCloseHandle(hPackage);
909         return res;
910     }
911 
912     *handle = hPackage;
913     return ERROR_SUCCESS;
914 }
915 
916 static void create_file_data(LPCSTR name, LPCSTR data)
917 {
918     HANDLE file;
919     DWORD written;
920 
921     file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
922     ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
923     if (file == INVALID_HANDLE_VALUE)
924         return;
925 
926     WriteFile(file, data, strlen(data), &written, NULL);
927     WriteFile(file, "\n", strlen("\n"), &written, NULL);
928 
929     CloseHandle(file);
930 }
931 
932 static void create_test_file(const CHAR *name)
933 {
934     create_file_data(name, name);
935 }
936 
937 typedef struct _tagVS_VERSIONINFO
938 {
939     WORD wLength;
940     WORD wValueLength;
941     WORD wType;
942     WCHAR szKey[1];
943     WORD wPadding1[1];
944     VS_FIXEDFILEINFO Value;
945     WORD wPadding2[1];
946     WORD wChildren[1];
947 } VS_VERSIONINFO;
948 
949 #define roundoffs(a, b, r) (((BYTE *)(b) - (BYTE *)(a) + ((r) - 1)) & ~((r) - 1))
950 #define roundpos(a, b, r) (((BYTE *)(a)) + roundoffs(a, b, r))
951 
952 static BOOL create_file_with_version(const CHAR *name, LONG ms, LONG ls)
953 {
954     VS_VERSIONINFO *pVerInfo;
955     VS_FIXEDFILEINFO *pFixedInfo;
956     LPBYTE buffer, ofs;
957     CHAR path[MAX_PATH];
958     DWORD handle, size;
959     HANDLE resource;
960     BOOL ret = FALSE;
961 
962     GetSystemDirectoryA(path, MAX_PATH);
963     /* Some dlls can't be updated on Vista/W2K8 */
964     lstrcatA(path, "\\version.dll");
965 
966     CopyFileA(path, name, FALSE);
967 
968     size = GetFileVersionInfoSizeA(path, &handle);
969     buffer = HeapAlloc(GetProcessHeap(), 0, size);
970 
971     GetFileVersionInfoA(path, 0, size, buffer);
972 
973     pVerInfo = (VS_VERSIONINFO *)buffer;
974     ofs = (BYTE *)&pVerInfo->szKey[lstrlenW(pVerInfo->szKey) + 1];
975     pFixedInfo = (VS_FIXEDFILEINFO *)roundpos(pVerInfo, ofs, 4);
976 
977     pFixedInfo->dwFileVersionMS = ms;
978     pFixedInfo->dwFileVersionLS = ls;
979     pFixedInfo->dwProductVersionMS = ms;
980     pFixedInfo->dwProductVersionLS = ls;
981 
982     resource = BeginUpdateResourceA(name, FALSE);
983     if (!resource)
984         goto done;
985 
986     if (!UpdateResourceA(resource, (LPCSTR)RT_VERSION, (LPCSTR)MAKEINTRESOURCE(VS_VERSION_INFO),
987                          MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), buffer, size))
988         goto done;
989 
990     if (!EndUpdateResourceA(resource, FALSE))
991         goto done;
992 
993     ret = TRUE;
994 
995 done:
996     HeapFree(GetProcessHeap(), 0, buffer);
997     return ret;
998 }
999 
1000 static BOOL notify_system_change(DWORD event_type, STATEMGRSTATUS *status)
1001 {
1002     RESTOREPOINTINFOA spec;
1003 
1004     spec.dwEventType = event_type;
1005     spec.dwRestorePtType = APPLICATION_INSTALL;
1006     spec.llSequenceNumber = status->llSequenceNumber;
1007     lstrcpyA(spec.szDescription, "msitest restore point");
1008 
1009     return pSRSetRestorePointA(&spec, status);
1010 }
1011 
1012 static void remove_restore_point(DWORD seq_number)
1013 {
1014     DWORD res;
1015 
1016     res = pSRRemoveRestorePoint(seq_number);
1017     if (res != ERROR_SUCCESS)
1018         trace("Failed to remove the restore point : %08x\n", res);
1019 }
1020 
1021 static BOOL is_root(const char *path)
1022 {
1023     return (isalpha(path[0]) && path[1] == ':' && path[2] == '\\' && !path[3]);
1024 }
1025 
1026 static void test_createpackage(void)
1027 {
1028     MSIHANDLE hPackage = 0;
1029     UINT res;
1030 
1031     res = package_from_db(create_package_db(), &hPackage);
1032     if (res == ERROR_INSTALL_PACKAGE_REJECTED)
1033     {
1034         skip("Not enough rights to perform tests\n");
1035         DeleteFileA(msifile);
1036         return;
1037     }
1038     ok( res == ERROR_SUCCESS, " Failed to create package %u\n", res );
1039 
1040     res = MsiCloseHandle( hPackage);
1041     ok( res == ERROR_SUCCESS , "Failed to close package\n" );
1042     DeleteFileA(msifile);
1043 }
1044 
1045 static void test_doaction( void )
1046 {
1047     MSIHANDLE hpkg;
1048     UINT r;
1049 
1050     r = MsiDoActionA( -1, NULL );
1051     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1052 
1053     r = package_from_db(create_package_db(), &hpkg);
1054     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1055     {
1056         skip("Not enough rights to perform tests\n");
1057         DeleteFileA(msifile);
1058         return;
1059     }
1060     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1061 
1062     r = MsiDoActionA(hpkg, NULL);
1063     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1064 
1065     r = MsiDoActionA(0, "boo");
1066     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1067 
1068     r = MsiDoActionA(hpkg, "boo");
1069     ok( r == ERROR_FUNCTION_NOT_CALLED, "wrong return val\n");
1070 
1071     MsiCloseHandle( hpkg );
1072     DeleteFileA(msifile);
1073 }
1074 
1075 static void test_gettargetpath_bad(void)
1076 {
1077     static const WCHAR boo[] = {'b','o','o',0};
1078     static const WCHAR empty[] = {0};
1079     char buffer[0x80];
1080     WCHAR bufferW[0x80];
1081     MSIHANDLE hpkg;
1082     DWORD sz;
1083     UINT r;
1084 
1085     r = package_from_db(create_package_db(), &hpkg);
1086     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1087     {
1088         skip("Not enough rights to perform tests\n");
1089         DeleteFileA(msifile);
1090         return;
1091     }
1092     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1093 
1094     r = MsiGetTargetPathA( 0, NULL, NULL, NULL );
1095     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1096 
1097     r = MsiGetTargetPathA( 0, NULL, NULL, &sz );
1098     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1099 
1100     r = MsiGetTargetPathA( 0, "boo", NULL, NULL );
1101     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1102 
1103     r = MsiGetTargetPathA( 0, "boo", NULL, NULL );
1104     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1105 
1106     r = MsiGetTargetPathA( hpkg, "boo", NULL, NULL );
1107     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1108 
1109     r = MsiGetTargetPathA( hpkg, "boo", buffer, NULL );
1110     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1111 
1112     sz = 0;
1113     r = MsiGetTargetPathA( hpkg, "", buffer, &sz );
1114     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1115 
1116     r = MsiGetTargetPathW( 0, NULL, NULL, NULL );
1117     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1118 
1119     r = MsiGetTargetPathW( 0, NULL, NULL, &sz );
1120     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1121 
1122     r = MsiGetTargetPathW( 0, boo, NULL, NULL );
1123     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1124 
1125     r = MsiGetTargetPathW( 0, boo, NULL, NULL );
1126     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1127 
1128     r = MsiGetTargetPathW( hpkg, boo, NULL, NULL );
1129     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1130 
1131     r = MsiGetTargetPathW( hpkg, boo, bufferW, NULL );
1132     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1133 
1134     sz = 0;
1135     r = MsiGetTargetPathW( hpkg, empty, bufferW, &sz );
1136     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1137 
1138     MsiCloseHandle( hpkg );
1139     DeleteFileA(msifile);
1140 }
1141 
1142 static void query_file_path(MSIHANDLE hpkg, LPCSTR file, LPSTR buff)
1143 {
1144     UINT r;
1145     DWORD size;
1146     MSIHANDLE rec;
1147 
1148     rec = MsiCreateRecord( 1 );
1149     ok(rec, "MsiCreate record failed\n");
1150 
1151     r = MsiRecordSetStringA( rec, 0, file );
1152     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
1153 
1154     size = MAX_PATH;
1155     r = MsiFormatRecordA( hpkg, rec, buff, &size );
1156     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
1157 
1158     MsiCloseHandle( rec );
1159 }
1160 
1161 static void test_settargetpath(void)
1162 {
1163     char tempdir[MAX_PATH+8], buffer[MAX_PATH], file[MAX_PATH];
1164     DWORD sz;
1165     MSIHANDLE hpkg;
1166     UINT r;
1167     MSIHANDLE hdb;
1168 
1169     hdb = create_package_db();
1170     ok ( hdb, "failed to create package database\n" );
1171 
1172     r = add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'" );
1173     ok( r == S_OK, "failed to add directory entry: %d\n" , r );
1174 
1175     r = create_component_table( hdb );
1176     ok( r == S_OK, "cannot create Component table: %d\n", r );
1177 
1178     r = add_component_entry( hdb, "'RootComp', '{83e2694d-0864-4124-9323-6d37630912a1}', 'TARGETDIR', 8, '', 'RootFile'" );
1179     ok( r == S_OK, "cannot add dummy component: %d\n", r );
1180 
1181     r = add_component_entry( hdb, "'TestComp', '{A3FB59C8-C293-4F7E-B8C5-F0E1D8EEE4E5}', 'TestDir', 0, '', 'TestFile'" );
1182     ok( r == S_OK, "cannot add test component: %d\n", r );
1183 
1184     r = create_feature_table( hdb );
1185     ok( r == S_OK, "cannot create Feature table: %d\n", r );
1186 
1187     r = add_feature_entry( hdb, "'TestFeature', '', '', '', 0, 1, '', 0" );
1188     ok( r == ERROR_SUCCESS, "cannot add TestFeature to Feature table: %d\n", r );
1189 
1190     r = create_feature_components_table( hdb );
1191     ok( r == S_OK, "cannot create FeatureComponents table: %d\n", r );
1192 
1193     r = add_feature_components_entry( hdb, "'TestFeature', 'RootComp'" );
1194     ok( r == S_OK, "cannot insert component into FeatureComponents table: %d\n", r );
1195 
1196     r = add_feature_components_entry( hdb, "'TestFeature', 'TestComp'" );
1197     ok( r == S_OK, "cannot insert component into FeatureComponents table: %d\n", r );
1198 
1199     add_directory_entry( hdb, "'TestParent', 'TARGETDIR', 'TestParent'" );
1200     add_directory_entry( hdb, "'TestDir', 'TestParent', 'TestDir'" );
1201 
1202     r = create_file_table( hdb );
1203     ok( r == S_OK, "cannot create File table: %d\n", r );
1204 
1205     r = add_file_entry( hdb, "'RootFile', 'RootComp', 'rootfile.txt', 0, '', '1033', 8192, 1" );
1206     ok( r == S_OK, "cannot add file to the File table: %d\n", r );
1207 
1208     r = add_file_entry( hdb, "'TestFile', 'TestComp', 'testfile.txt', 0, '', '1033', 8192, 1" );
1209     ok( r == S_OK, "cannot add file to the File table: %d\n", r );
1210 
1211     r = package_from_db( hdb, &hpkg );
1212     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1213     {
1214         skip("Not enough rights to perform tests\n");
1215         DeleteFileA(msifile);
1216         return;
1217     }
1218     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1219 
1220     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1221 
1222     r = MsiDoActionA( hpkg, "CostInitialize");
1223     ok( r == ERROR_SUCCESS, "cost init failed\n");
1224 
1225     r = MsiDoActionA( hpkg, "FileCost");
1226     ok( r == ERROR_SUCCESS, "file cost failed\n");
1227 
1228     r = MsiDoActionA( hpkg, "CostFinalize");
1229     ok( r == ERROR_SUCCESS, "cost finalize failed\n");
1230 
1231     buffer[0] = 0;
1232     sz = sizeof(buffer);
1233     r = MsiGetPropertyA( hpkg, "OutOfNoRbDiskSpace", buffer, &sz );
1234     ok( r == ERROR_SUCCESS, "MsiGetProperty returned %u\n", r );
1235     trace( "OutOfNoRbDiskSpace = \"%s\"\n", buffer );
1236 
1237     r = MsiSetTargetPathA( 0, NULL, NULL );
1238     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1239 
1240     r = MsiSetTargetPathA( 0, "boo", "C:\\bogusx" );
1241     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1242 
1243     r = MsiSetTargetPathA( hpkg, "boo", NULL );
1244     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1245 
1246     r = MsiSetTargetPathA( hpkg, "boo", "c:\\bogusx" );
1247     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1248 
1249     sz = sizeof tempdir - 1;
1250     r = MsiGetTargetPathA( hpkg, "TARGETDIR", tempdir, &sz );
1251     sprintf( file, "%srootfile.txt", tempdir );
1252     buffer[0] = 0;
1253     query_file_path( hpkg, "[#RootFile]", buffer );
1254     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1255     ok( !lstrcmpA(buffer, file), "Expected %s, got %s\n", file, buffer );
1256 
1257     GetTempFileNameA( tempdir, "_wt", 0, buffer );
1258     sprintf( tempdir, "%s\\subdir", buffer );
1259 
1260     r = MsiSetTargetPathA( hpkg, "TARGETDIR", buffer );
1261     ok( r == ERROR_SUCCESS || r == ERROR_DIRECTORY,
1262         "MsiSetTargetPath on file returned %d\n", r );
1263 
1264     r = MsiSetTargetPathA( hpkg, "TARGETDIR", tempdir );
1265     ok( r == ERROR_SUCCESS || r == ERROR_DIRECTORY,
1266         "MsiSetTargetPath on 'subdir' of file returned %d\n", r );
1267 
1268     DeleteFileA( buffer );
1269 
1270     r = MsiSetTargetPathA( hpkg, "TARGETDIR", buffer );
1271     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1272 
1273     r = GetFileAttributesA( buffer );
1274     ok ( r == INVALID_FILE_ATTRIBUTES, "file/directory exists after MsiSetTargetPath. Attributes: %08X\n", r );
1275 
1276     r = MsiSetTargetPathA( hpkg, "TARGETDIR", tempdir );
1277     ok( r == ERROR_SUCCESS, "MsiSetTargetPath on subsubdir returned %d\n", r );
1278 
1279     buffer[0] = 0;
1280     sz = sizeof buffer - 1;
1281     lstrcatA( tempdir, "\\" );
1282     r = MsiGetTargetPathA( hpkg, "TARGETDIR", buffer, &sz );
1283     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1284     ok( !lstrcmpA(buffer, tempdir), "Expected %s, got %s\n", tempdir, buffer);
1285 
1286     sprintf( file, "%srootfile.txt", tempdir );
1287     query_file_path( hpkg, "[#RootFile]", buffer );
1288     ok( !lstrcmpA(buffer, file), "Expected %s, got %s\n", file, buffer);
1289 
1290     buffer[0] = 0;
1291     sz = sizeof(buffer);
1292     r = MsiGetPropertyA( hpkg, "TestParent", buffer, &sz );
1293     ok( r == ERROR_SUCCESS, "MsiGetProperty returned %u\n", r );
1294     lstrcatA( tempdir, "TestParent\\" );
1295     ok( !lstrcmpiA(buffer, tempdir), "Expected \"%s\", got \"%s\"\n", tempdir, buffer );
1296 
1297     r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\one\\two" );
1298     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1299 
1300     buffer[0] = 0;
1301     sz = sizeof(buffer);
1302     r = MsiGetPropertyA( hpkg, "TestParent", buffer, &sz );
1303     ok( r == ERROR_SUCCESS, "MsiGetProperty returned %u\n", r );
1304     ok( lstrcmpiA(buffer, "C:\\one\\two\\TestDir\\"),
1305         "Expected \"C:\\one\\two\\TestDir\\\", got \"%s\"\n", buffer );
1306 
1307     buffer[0] = 0;
1308     query_file_path( hpkg, "[#TestFile]", buffer );
1309     ok( !lstrcmpiA(buffer, "C:\\one\\two\\TestDir\\testfile.txt"),
1310         "Expected C:\\one\\two\\TestDir\\testfile.txt, got %s\n", buffer );
1311 
1312     buffer[0] = 0;
1313     sz = sizeof buffer - 1;
1314     r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1315     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1316     ok( !lstrcmpiA(buffer, "C:\\one\\two\\"), "Expected C:\\one\\two\\, got %s\n", buffer);
1317 
1318     r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\one\\two\\three" );
1319     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1320 
1321     buffer[0] = 0;
1322     sz = sizeof buffer - 1;
1323     r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1324     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1325     ok( !lstrcmpiA(buffer, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", buffer);
1326 
1327     r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\\\one\\\\two  " );
1328     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1329 
1330     buffer[0] = 0;
1331     sz = sizeof buffer - 1;
1332     r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1333     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1334     ok( !lstrcmpiA(buffer, "C:\\one\\two\\"), "Expected \"C:\\one\\two\\\", got %s\n", buffer);
1335 
1336     r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\\\ Program Files \\\\ " );
1337     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1338 
1339     buffer[0] = 0;
1340     sz = sizeof buffer - 1;
1341     r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1342     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1343     ok( !lstrcmpiA(buffer, "C:\\Program Files\\"), "Expected \"C:\\Program Files\\\", got %s\n", buffer);
1344 
1345     MsiCloseHandle( hpkg );
1346 }
1347 
1348 static void test_condition(void)
1349 {
1350     static const WCHAR cond1[] = {'\"','a',0x30a,'\"','<','\"',0xe5,'\"',0};
1351     static const WCHAR cond2[] = {'\"','a',0x30a,'\"','>','\"',0xe5,'\"',0};
1352     static const WCHAR cond3[] = {'\"','a',0x30a,'\"','<','>','\"',0xe5,'\"',0};
1353     static const WCHAR cond4[] = {'\"','a',0x30a,'\"','=','\"',0xe5,'\"',0};
1354     MSICONDITION r;
1355     MSIHANDLE hpkg;
1356 
1357     r = package_from_db(create_package_db(), &hpkg);
1358     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1359     {
1360         skip("Not enough rights to perform tests\n");
1361         DeleteFileA(msifile);
1362         return;
1363     }
1364     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1365 
1366     r = MsiEvaluateConditionA(0, NULL);
1367     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1368 
1369     r = MsiEvaluateConditionA(hpkg, NULL);
1370     ok( r == MSICONDITION_NONE, "wrong return val\n");
1371 
1372     r = MsiEvaluateConditionA(hpkg, "");
1373     ok( r == MSICONDITION_NONE, "wrong return val\n");
1374 
1375     r = MsiEvaluateConditionA(hpkg, "1");
1376     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1377 
1378     r = MsiEvaluateConditionA(hpkg, "0");
1379     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1380 
1381     r = MsiEvaluateConditionA(hpkg, "-1");
1382     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1383 
1384     r = MsiEvaluateConditionA(hpkg, "0 = 0");
1385     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1386 
1387     r = MsiEvaluateConditionA(hpkg, "0 <> 0");
1388     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1389 
1390     r = MsiEvaluateConditionA(hpkg, "0 = 1");
1391     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1392 
1393     r = MsiEvaluateConditionA(hpkg, "0 > 1");
1394     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1395 
1396     r = MsiEvaluateConditionA(hpkg, "0 ~> 1");
1397     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1398 
1399     r = MsiEvaluateConditionA(hpkg, "1 > 1");
1400     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1401 
1402     r = MsiEvaluateConditionA(hpkg, "1 ~> 1");
1403     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1404 
1405     r = MsiEvaluateConditionA(hpkg, "0 >= 1");
1406     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1407 
1408     r = MsiEvaluateConditionA(hpkg, "0 ~>= 1");
1409     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1410 
1411     r = MsiEvaluateConditionA(hpkg, "1 >= 1");
1412     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1413 
1414     r = MsiEvaluateConditionA(hpkg, "1 ~>= 1");
1415     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1416 
1417     r = MsiEvaluateConditionA(hpkg, "0 < 1");
1418     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1419 
1420     r = MsiEvaluateConditionA(hpkg, "0 ~< 1");
1421     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1422 
1423     r = MsiEvaluateConditionA(hpkg, "1 < 1");
1424     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1425 
1426     r = MsiEvaluateConditionA(hpkg, "1 ~< 1");
1427     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1428 
1429     r = MsiEvaluateConditionA(hpkg, "0 <= 1");
1430     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1431 
1432     r = MsiEvaluateConditionA(hpkg, "0 ~<= 1");
1433     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1434 
1435     r = MsiEvaluateConditionA(hpkg, "1 <= 1");
1436     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1437 
1438     r = MsiEvaluateConditionA(hpkg, "1 ~<= 1");
1439     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1440 
1441     r = MsiEvaluateConditionA(hpkg, "0 >=");
1442     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1443 
1444     r = MsiEvaluateConditionA(hpkg, " ");
1445     ok( r == MSICONDITION_NONE, "wrong return val\n");
1446 
1447     r = MsiEvaluateConditionA(hpkg, "LicView <> \"1\"");
1448     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1449 
1450     r = MsiEvaluateConditionA(hpkg, "LicView <> \"0\"");
1451     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1452 
1453     r = MsiEvaluateConditionA(hpkg, "LicView <> LicView");
1454     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1455 
1456     r = MsiEvaluateConditionA(hpkg, "not 0");
1457     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1458 
1459     r = MsiEvaluateConditionA(hpkg, "not LicView");
1460     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1461 
1462     r = MsiEvaluateConditionA(hpkg, "\"Testing\" ~<< \"Testing\"");
1463     ok (r == MSICONDITION_TRUE, "wrong return val\n");
1464 
1465     r = MsiEvaluateConditionA(hpkg, "LicView ~<< \"Testing\"");
1466     ok (r == MSICONDITION_FALSE, "wrong return val\n");
1467 
1468     r = MsiEvaluateConditionA(hpkg, "Not LicView ~<< \"Testing\"");
1469     ok (r == MSICONDITION_TRUE, "wrong return val\n");
1470 
1471     r = MsiEvaluateConditionA(hpkg, "not \"A\"");
1472     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1473 
1474     r = MsiEvaluateConditionA(hpkg, "~not \"A\"");
1475     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1476 
1477     r = MsiEvaluateConditionA(hpkg, "\"0\"");
1478     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1479 
1480     r = MsiEvaluateConditionA(hpkg, "1 and 2");
1481     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1482 
1483     r = MsiEvaluateConditionA(hpkg, "not 0 and 3");
1484     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1485 
1486     r = MsiEvaluateConditionA(hpkg, "not 0 and 0");
1487     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1488 
1489     r = MsiEvaluateConditionA(hpkg, "not 0 or 1");
1490     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1491 
1492     r = MsiEvaluateConditionA(hpkg, "(0)");
1493     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1494 
1495     r = MsiEvaluateConditionA(hpkg, "(((((1))))))");
1496     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1497 
1498     r = MsiEvaluateConditionA(hpkg, "(((((1)))))");
1499     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1500 
1501     r = MsiEvaluateConditionA(hpkg, " \"A\" < \"B\" ");
1502     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1503 
1504     r = MsiEvaluateConditionA(hpkg, " \"A\" > \"B\" ");
1505     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1506 
1507     r = MsiEvaluateConditionA(hpkg, " \"1\" > \"12\" ");
1508     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1509 
1510     r = MsiEvaluateConditionA(hpkg, " \"100\" < \"21\" ");
1511     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1512 
1513     r = MsiEvaluateConditionA(hpkg, "0 < > 0");
1514     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1515 
1516     r = MsiEvaluateConditionA(hpkg, "(1<<1) == 2");
1517     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1518 
1519     r = MsiEvaluateConditionA(hpkg, " \"A\" = \"a\" ");
1520     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1521 
1522     r = MsiEvaluateConditionA(hpkg, " \"A\" ~ = \"a\" ");
1523     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1524 
1525     r = MsiEvaluateConditionA(hpkg, " \"A\" ~= \"a\" ");
1526     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1527 
1528     r = MsiEvaluateConditionA(hpkg, " \"A\" ~= 1 ");
1529     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1530 
1531     r = MsiEvaluateConditionA(hpkg, " \"A\" = 1 ");
1532     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1533 
1534     r = MsiEvaluateConditionA(hpkg, " 1 ~= 1 ");
1535     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1536 
1537     r = MsiEvaluateConditionA(hpkg, " 1 ~= \"1\" ");
1538     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1539 
1540     r = MsiEvaluateConditionA(hpkg, " 1 = \"1\" ");
1541     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1542 
1543     r = MsiEvaluateConditionA(hpkg, " 0 = \"1\" ");
1544     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1545 
1546     r = MsiEvaluateConditionA(hpkg, " 0 < \"100\" ");
1547     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1548 
1549     r = MsiEvaluateConditionA(hpkg, " 100 > \"0\" ");
1550     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1551 
1552     r = MsiEvaluateConditionA(hpkg, "1 XOR 1");
1553     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1554 
1555     r = MsiEvaluateConditionA(hpkg, "1 IMP 1");
1556     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1557 
1558     r = MsiEvaluateConditionA(hpkg, "1 IMP 0");
1559     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1560 
1561     r = MsiEvaluateConditionA(hpkg, "0 IMP 0");
1562     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1563 
1564     r = MsiEvaluateConditionA(hpkg, "0 EQV 0");
1565     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1566 
1567     r = MsiEvaluateConditionA(hpkg, "0 EQV 1");
1568     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1569 
1570     r = MsiEvaluateConditionA(hpkg, "1 IMP 1 OR 0");
1571     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1572 
1573     r = MsiEvaluateConditionA(hpkg, "1 IMPL 1");
1574     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1575 
1576     r = MsiEvaluateConditionA(hpkg, "\"ASFD\" >< \"S\" ");
1577     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1578 
1579     r = MsiEvaluateConditionA(hpkg, "\"ASFD\" ~>< \"s\" ");
1580     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1581 
1582     r = MsiEvaluateConditionA(hpkg, "\"ASFD\" ~>< \"\" ");
1583     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1584 
1585     r = MsiEvaluateConditionA(hpkg, "\"ASFD\" ~>< \"sss\" ");
1586     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1587 
1588     MsiSetPropertyA(hpkg, "mm", "5" );
1589 
1590     r = MsiEvaluateConditionA(hpkg, "mm = 5");
1591     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1592 
1593     r = MsiEvaluateConditionA(hpkg, "mm < 6");
1594     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1595 
1596     r = MsiEvaluateConditionA(hpkg, "mm <= 5");
1597     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1598 
1599     r = MsiEvaluateConditionA(hpkg, "mm > 4");
1600     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1601 
1602     r = MsiEvaluateConditionA(hpkg, "mm < 12");
1603     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1604 
1605     r = MsiEvaluateConditionA(hpkg, "mm = \"5\"");
1606     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1607 
1608     r = MsiEvaluateConditionA(hpkg, "0 = \"\"");
1609     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1610 
1611     r = MsiEvaluateConditionA(hpkg, "0 AND \"\"");
1612     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1613 
1614     r = MsiEvaluateConditionA(hpkg, "1 AND \"\"");
1615     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1616 
1617     r = MsiEvaluateConditionA(hpkg, "1 AND \"1\"");
1618     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1619 
1620     r = MsiEvaluateConditionA(hpkg, "3 >< 1");
1621     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1622 
1623     r = MsiEvaluateConditionA(hpkg, "3 >< 4");
1624     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1625 
1626     r = MsiEvaluateConditionA(hpkg, "NOT 0 AND 0");
1627     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1628 
1629     r = MsiEvaluateConditionA(hpkg, "NOT 0 AND 1");
1630     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1631 
1632     r = MsiEvaluateConditionA(hpkg, "NOT 1 OR 0");
1633     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1634 
1635     r = MsiEvaluateConditionA(hpkg, "0 AND 1 OR 1");
1636     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1637 
1638     r = MsiEvaluateConditionA(hpkg, "0 AND 0 OR 1");
1639     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1640 
1641     r = MsiEvaluateConditionA(hpkg, "NOT 0 AND 1 OR 0");
1642     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1643 
1644     r = MsiEvaluateConditionA(hpkg, "_1 = _1");
1645     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1646 
1647     r = MsiEvaluateConditionA(hpkg, "( 1 AND 1 ) = 2");
1648     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1649 
1650     r = MsiEvaluateConditionA(hpkg, "NOT ( 1 AND 1 )");
1651     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1652 
1653     r = MsiEvaluateConditionA(hpkg, "NOT A AND (BBBBBBBBBB=2 OR CCC=1) AND Ddddddddd");
1654     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1655 
1656     r = MsiEvaluateConditionA(hpkg, "Installed<>\"\"");
1657     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1658 
1659     r = MsiEvaluateConditionA(hpkg, "NOT 1 AND 0");
1660     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1661 
1662     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1663     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1664 
1665     r = MsiEvaluateConditionA(hpkg, "bandalmael<>0");
1666     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1667 
1668     r = MsiEvaluateConditionA(hpkg, "bandalmael<0");
1669     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1670 
1671     r = MsiEvaluateConditionA(hpkg, "bandalmael>0");
1672     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1673 
1674     r = MsiEvaluateConditionA(hpkg, "bandalmael>=0");
1675     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1676 
1677     r = MsiEvaluateConditionA(hpkg, "bandalmael<=0");
1678     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1679 
1680     r = MsiEvaluateConditionA(hpkg, "bandalmael~<>0");
1681     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1682 
1683     MsiSetPropertyA(hpkg, "bandalmael", "0" );
1684     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1685     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1686 
1687     MsiSetPropertyA(hpkg, "bandalmael", "" );
1688     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1689     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1690 
1691     MsiSetPropertyA(hpkg, "bandalmael", "asdf" );
1692     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1693     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1694 
1695     MsiSetPropertyA(hpkg, "bandalmael", "0asdf" );
1696     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1697     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1698 
1699     MsiSetPropertyA(hpkg, "bandalmael", "0 " );
1700     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1701     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1702 
1703     MsiSetPropertyA(hpkg, "bandalmael", "-0" );
1704     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1705     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1706 
1707     MsiSetPropertyA(hpkg, "bandalmael", "0000000000000" );
1708     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1709     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1710 
1711     MsiSetPropertyA(hpkg, "bandalmael", "--0" );
1712     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1713     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1714 
1715     MsiSetPropertyA(hpkg, "bandalmael", "0x00" );
1716     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1717     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1718 
1719     MsiSetPropertyA(hpkg, "bandalmael", "-" );
1720     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1721     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1722 
1723     MsiSetPropertyA(hpkg, "bandalmael", "+0" );
1724     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1725     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1726 
1727     MsiSetPropertyA(hpkg, "bandalmael", "0.0" );
1728     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1729     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1730     r = MsiEvaluateConditionA(hpkg, "bandalmael<>0");
1731     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1732 
1733     MsiSetPropertyA(hpkg, "one", "hi");
1734     MsiSetPropertyA(hpkg, "two", "hithere");
1735     r = MsiEvaluateConditionA(hpkg, "one >< two");
1736     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1737 
1738     MsiSetPropertyA(hpkg, "one", "hithere");
1739     MsiSetPropertyA(hpkg, "two", "hi");
1740     r = MsiEvaluateConditionA(hpkg, "one >< two");
1741     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1742 
1743     MsiSetPropertyA(hpkg, "one", "hello");
1744     MsiSetPropertyA(hpkg, "two", "hi");
1745     r = MsiEvaluateConditionA(hpkg, "one >< two");
1746     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1747 
1748     MsiSetPropertyA(hpkg, "one", "hellohithere");
1749     MsiSetPropertyA(hpkg, "two", "hi");
1750     r = MsiEvaluateConditionA(hpkg, "one >< two");
1751     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1752 
1753     MsiSetPropertyA(hpkg, "one", "");
1754     MsiSetPropertyA(hpkg, "two", "hi");
1755     r = MsiEvaluateConditionA(hpkg, "one >< two");
1756     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1757 
1758     MsiSetPropertyA(hpkg, "one", "hi");
1759     MsiSetPropertyA(hpkg, "two", "");
1760     r = MsiEvaluateConditionA(hpkg, "one >< two");
1761     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1762 
1763     MsiSetPropertyA(hpkg, "one", "");
1764     MsiSetPropertyA(hpkg, "two", "");
1765     r = MsiEvaluateConditionA(hpkg, "one >< two");
1766     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1767 
1768     MsiSetPropertyA(hpkg, "one", "1234");
1769     MsiSetPropertyA(hpkg, "two", "1");
1770     r = MsiEvaluateConditionA(hpkg, "one >< two");
1771     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1772 
1773     MsiSetPropertyA(hpkg, "one", "one 1234");
1774     MsiSetPropertyA(hpkg, "two", "1");
1775     r = MsiEvaluateConditionA(hpkg, "one >< two");
1776     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1777 
1778     MsiSetPropertyA(hpkg, "one", "hithere");
1779     MsiSetPropertyA(hpkg, "two", "hi");
1780     r = MsiEvaluateConditionA(hpkg, "one << two");
1781     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1782 
1783     MsiSetPropertyA(hpkg, "one", "hi");
1784     MsiSetPropertyA(hpkg, "two", "hithere");
1785     r = MsiEvaluateConditionA(hpkg, "one << two");
1786     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1787 
1788     MsiSetPropertyA(hpkg, "one", "hi");
1789     MsiSetPropertyA(hpkg, "two", "hi");
1790     r = MsiEvaluateConditionA(hpkg, "one << two");
1791     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1792 
1793     MsiSetPropertyA(hpkg, "one", "abcdhithere");
1794     MsiSetPropertyA(hpkg, "two", "hi");
1795     r = MsiEvaluateConditionA(hpkg, "one << two");
1796     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1797 
1798     MsiSetPropertyA(hpkg, "one", "");
1799     MsiSetPropertyA(hpkg, "two", "hi");
1800     r = MsiEvaluateConditionA(hpkg, "one << two");
1801     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1802 
1803     MsiSetPropertyA(hpkg, "one", "hithere");
1804     MsiSetPropertyA(hpkg, "two", "");
1805     r = MsiEvaluateConditionA(hpkg, "one << two");
1806     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1807 
1808     MsiSetPropertyA(hpkg, "one", "");
1809     MsiSetPropertyA(hpkg, "two", "");
1810     r = MsiEvaluateConditionA(hpkg, "one << two");
1811     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1812 
1813     MsiSetPropertyA(hpkg, "one", "1234");
1814     MsiSetPropertyA(hpkg, "two", "1");
1815     r = MsiEvaluateConditionA(hpkg, "one << two");
1816     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1817 
1818     MsiSetPropertyA(hpkg, "one", "1234 one");
1819     MsiSetPropertyA(hpkg, "two", "1");
1820     r = MsiEvaluateConditionA(hpkg, "one << two");
1821     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1822 
1823     MsiSetPropertyA(hpkg, "one", "hithere");
1824     MsiSetPropertyA(hpkg, "two", "there");
1825     r = MsiEvaluateConditionA(hpkg, "one >> two");
1826     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1827 
1828     MsiSetPropertyA(hpkg, "one", "hithere");
1829     MsiSetPropertyA(hpkg, "two", "hi");
1830     r = MsiEvaluateConditionA(hpkg, "one >> two");
1831     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1832 
1833     MsiSetPropertyA(hpkg, "one", "there");
1834     MsiSetPropertyA(hpkg, "two", "hithere");
1835     r = MsiEvaluateConditionA(hpkg, "one >> two");
1836     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1837 
1838     MsiSetPropertyA(hpkg, "one", "there");
1839     MsiSetPropertyA(hpkg, "two", "there");
1840     r = MsiEvaluateConditionA(hpkg, "one >> two");
1841     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1842 
1843     MsiSetPropertyA(hpkg, "one", "abcdhithere");
1844     MsiSetPropertyA(hpkg, "two", "hi");
1845     r = MsiEvaluateConditionA(hpkg, "one >> two");
1846     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1847 
1848     MsiSetPropertyA(hpkg, "one", "");
1849     MsiSetPropertyA(hpkg, "two", "there");
1850     r = MsiEvaluateConditionA(hpkg, "one >> two");
1851     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1852 
1853     MsiSetPropertyA(hpkg, "one", "there");
1854     MsiSetPropertyA(hpkg, "two", "");
1855     r = MsiEvaluateConditionA(hpkg, "one >> two");
1856     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1857 
1858     MsiSetPropertyA(hpkg, "one", "");
1859     MsiSetPropertyA(hpkg, "two", "");
1860     r = MsiEvaluateConditionA(hpkg, "one >> two");
1861     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1862 
1863     MsiSetPropertyA(hpkg, "one", "1234");
1864     MsiSetPropertyA(hpkg, "two", "4");
1865     r = MsiEvaluateConditionA(hpkg, "one >> two");
1866     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1867 
1868     MsiSetPropertyA(hpkg, "one", "one 1234");
1869     MsiSetPropertyA(hpkg, "two", "4");
1870     r = MsiEvaluateConditionA(hpkg, "one >> two");
1871     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1872 
1873     MsiSetPropertyA(hpkg, "MsiNetAssemblySupport", NULL);  /* make sure it's empty */
1874 
1875     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322\"");
1876     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1877 
1878     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport > \"1.1.4322\"");
1879     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1880 
1881     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport >= \"1.1.4322\"");
1882     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1883 
1884     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport <= \"1.1.4322\"");
1885     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1886 
1887     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport <> \"1.1.4322\"");
1888     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1889 
1890     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport ~< \"1.1.4322\"");
1891     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1892 
1893     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"abcd\"");
1894     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1895 
1896     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a1.1.4322\"");
1897     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1898 
1899     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322a\"");
1900     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1901 
1902     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"0000001.1.4322\"");
1903     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1904 
1905     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322.1\"");
1906     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1907 
1908     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322.1.1\"");
1909     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1910 
1911     r = MsiEvaluateConditionA(hpkg, "\"2\" < \"1.1");
1912     ok( r == MSICONDITION_ERROR, "wrong return val (%d)\n", r);
1913 
1914     r = MsiEvaluateConditionA(hpkg, "\"2\" < \"1.1\"");
1915     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1916 
1917     r = MsiEvaluateConditionA(hpkg, "\"2\" < \"12.1\"");
1918     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1919 
1920     r = MsiEvaluateConditionA(hpkg, "\"02.1\" < \"2.11\"");
1921     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1922 
1923     r = MsiEvaluateConditionA(hpkg, "\"02.1.1\" < \"2.1\"");
1924     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1925 
1926     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1\"");
1927     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1928 
1929     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1\"");
1930     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1931 
1932     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"0\"");
1933     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1934 
1935     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"-1\"");
1936     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1937 
1938     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a\"");
1939     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1940 
1941     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"!\"");
1942     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1943 
1944     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"!\"");
1945     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1946 
1947     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"/\"");
1948     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1949 
1950     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \" \"");
1951     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1952 
1953     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"azAZ_\"");
1954     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1955 
1956     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a[a]\"");
1957     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1958 
1959     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a[a]a\"");
1960     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1961 
1962     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"[a]\"");
1963     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1964 
1965     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"[a]a\"");
1966     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1967 
1968     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"{a}\"");
1969     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1970 
1971     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"{a\"");
1972     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1973 
1974     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"[a\"");
1975     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1976 
1977     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a{\"");
1978     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1979 
1980     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a]\"");
1981     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1982 
1983     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"A\"");
1984     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1985 
1986     MsiSetPropertyA(hpkg, "MsiNetAssemblySupport", "1.1.4322");
1987     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322\"");
1988     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1989 
1990     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.14322\"");
1991     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1992 
1993     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.5\"");
1994     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1995 
1996     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1\"");
1997     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1998 
1999     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1\"");
2000     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2001 
2002     MsiSetPropertyA(hpkg, "one", "1");
2003     r = MsiEvaluateConditionA(hpkg, "one < \"1\"");
2004     ok( r == MSICONDITION_FALSE, "wrong return val\n");
2005 
2006     MsiSetPropertyA(hpkg, "X", "5.0");
2007 
2008     r = MsiEvaluateConditionA(hpkg, "X != \"\"");
2009     ok( r == MSICONDITION_ERROR, "wrong return val (%d)\n", r);
2010 
2011     r = MsiEvaluateConditionA(hpkg, "X =\"5.0\"");
2012     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2013 
2014     r = MsiEvaluateConditionA(hpkg, "X =\"5.1\"");
2015     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2016 
2017     r = MsiEvaluateConditionA(hpkg, "X =\"6.0\"");
2018     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2019 
2020     r = MsiEvaluateConditionA(hpkg, "X =\"5.0\" or X =\"5.1\" or X =\"6.0\"");
2021     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2022 
2023     r = MsiEvaluateConditionA(hpkg, "(X =\"5.0\" or X =\"5.1\" or X =\"6.0\")");
2024     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2025 
2026     r = MsiEvaluateConditionA(hpkg, "X !=\"\" and (X =\"5.0\" or X =\"5.1\" or X =\"6.0\")");
2027     ok( r == MSICONDITION_ERROR, "wrong return val (%d)\n", r);
2028 
2029     /* feature doesn't exist */
2030     r = MsiEvaluateConditionA(hpkg, "&nofeature");
2031     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2032 
2033     MsiSetPropertyA(hpkg, "A", "2");
2034     MsiSetPropertyA(hpkg, "X", "50");
2035 
2036     r = MsiEvaluateConditionA(hpkg, "2 <= X");
2037     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2038 
2039     r = MsiEvaluateConditionA(hpkg, "A <= X");
2040     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2041 
2042     r = MsiEvaluateConditionA(hpkg, "A <= 50");
2043     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2044 
2045     MsiSetPropertyA(hpkg, "X", "50val");
2046 
2047     r = MsiEvaluateConditionA(hpkg, "2 <= X");
2048     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2049 
2050     r = MsiEvaluateConditionA(hpkg, "A <= X");
2051     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2052 
2053     MsiSetPropertyA(hpkg, "A", "7");
2054     MsiSetPropertyA(hpkg, "X", "50");
2055 
2056     r = MsiEvaluateConditionA(hpkg, "7 <= X");
2057     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2058 
2059     r = MsiEvaluateConditionA(hpkg, "A <= X");
2060     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2061 
2062     r = MsiEvaluateConditionA(hpkg, "A <= 50");
2063     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2064 
2065     MsiSetPropertyA(hpkg, "X", "50val");
2066 
2067     r = MsiEvaluateConditionA(hpkg, "2 <= X");
2068     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2069 
2070     r = MsiEvaluateConditionA(hpkg, "A <= X");
2071     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2072 
2073     r = MsiEvaluateConditionW(hpkg, cond1);
2074     ok( r == MSICONDITION_TRUE || broken(r == MSICONDITION_FALSE),
2075         "wrong return val (%d)\n", r);
2076 
2077     r = MsiEvaluateConditionW(hpkg, cond2);
2078     ok( r == MSICONDITION_FALSE || broken(r == MSICONDITION_TRUE),
2079         "wrong return val (%d)\n", r);
2080 
2081     r = MsiEvaluateConditionW(hpkg, cond3);
2082     ok( r == MSICONDITION_TRUE || broken(r == MSICONDITION_FALSE),
2083         "wrong return val (%d)\n", r);
2084 
2085     r = MsiEvaluateConditionW(hpkg, cond4);
2086     ok( r == MSICONDITION_FALSE || broken(r == MSICONDITION_TRUE),
2087         "wrong return val (%d)\n", r);
2088 
2089     MsiCloseHandle( hpkg );
2090     DeleteFileA(msifile);
2091 }
2092 
2093 static BOOL check_prop_empty( MSIHANDLE hpkg, const char * prop)
2094 {
2095     UINT r;
2096     DWORD sz;
2097     char buffer[2];
2098 
2099     sz = sizeof buffer;
2100     strcpy(buffer,"x");
2101     r = MsiGetPropertyA( hpkg, prop, buffer, &sz );
2102     return r == ERROR_SUCCESS && buffer[0] == 0 && sz == 0;
2103 }
2104 
2105 static void test_props(void)
2106 {
2107     MSIHANDLE hpkg, hdb;
2108     UINT r;
2109     DWORD sz;
2110     char buffer[0x100];
2111 
2112     hdb = create_package_db();
2113     r = run_query( hdb,
2114             "CREATE TABLE `Property` ( "
2115             "`Property` CHAR(255) NOT NULL, "
2116             "`Value` CHAR(255) "
2117             "PRIMARY KEY `Property`)" );
2118     ok( r == ERROR_SUCCESS , "Failed\n" );
2119 
2120     r = run_query(hdb,
2121             "INSERT INTO `Property` "
2122             "(`Property`, `Value`) "
2123             "VALUES( 'MetadataCompName', 'Photoshop.dll' )");
2124     ok( r == ERROR_SUCCESS , "Failed\n" );
2125 
2126     r = package_from_db( hdb, &hpkg );
2127     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2128     {
2129         skip("Not enough rights to perform tests\n");
2130         DeleteFileA(msifile);
2131         return;
2132     }
2133     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
2134 
2135     /* test invalid values */
2136     r = MsiGetPropertyA( 0, NULL, NULL, NULL );
2137     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
2138 
2139     r = MsiGetPropertyA( hpkg, NULL, NULL, NULL );
2140     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
2141 
2142     r = MsiGetPropertyA( hpkg, "boo", NULL, NULL );
2143     ok( r == ERROR_SUCCESS, "wrong return val\n");
2144 
2145     r = MsiGetPropertyA( hpkg, "boo", buffer, NULL );
2146     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
2147 
2148     /* test retrieving an empty/nonexistent property */
2149     sz = sizeof buffer;
2150     r = MsiGetPropertyA( hpkg, "boo", NULL, &sz );
2151     ok( r == ERROR_SUCCESS, "wrong return val\n");
2152     ok( sz == 0, "wrong size returned\n");
2153 
2154     check_prop_empty( hpkg, "boo");
2155     sz = 0;
2156     strcpy(buffer,"x");
2157     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2158     ok( r == ERROR_MORE_DATA, "wrong return val\n");
2159     ok( !strcmp(buffer,"x"), "buffer was changed\n");
2160     ok( sz == 0, "wrong size returned\n");
2161 
2162     sz = 1;
2163     strcpy(buffer,"x");
2164     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2165     ok( r == ERROR_SUCCESS, "wrong return val\n");
2166     ok( buffer[0] == 0, "buffer was not changed\n");
2167     ok( sz == 0, "wrong size returned\n");
2168 
2169     /* set the property to something */
2170     r = MsiSetPropertyA( 0, NULL, NULL );
2171     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
2172 
2173     r = MsiSetPropertyA( hpkg, NULL, NULL );
2174     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
2175 
2176     r = MsiSetPropertyA( hpkg, "", NULL );
2177     ok( r == ERROR_SUCCESS, "wrong return val\n");
2178 
2179     /* try set and get some illegal property identifiers */
2180     r = MsiSetPropertyA( hpkg, "", "asdf" );
2181     ok( r == ERROR_FUNCTION_FAILED, "wrong return val\n");
2182 
2183     r = MsiSetPropertyA( hpkg, "=", "asdf" );
2184     ok( r == ERROR_SUCCESS, "wrong return val\n");
2185 
2186     r = MsiSetPropertyA( hpkg, " ", "asdf" );
2187     ok( r == ERROR_SUCCESS, "wrong return val\n");
2188 
2189     r = MsiSetPropertyA( hpkg, "'", "asdf" );
2190     ok( r == ERROR_SUCCESS, "wrong return val\n");
2191 
2192     sz = sizeof buffer;
2193     buffer[0]=0;
2194     r = MsiGetPropertyA( hpkg, "'", buffer, &sz );
2195     ok( r == ERROR_SUCCESS, "wrong return val\n");
2196     ok( !strcmp(buffer,"asdf"), "buffer was not changed\n");
2197 
2198     /* set empty values */
2199     r = MsiSetPropertyA( hpkg, "boo", NULL );
2200     ok( r == ERROR_SUCCESS, "wrong return val\n");
2201     ok( check_prop_empty( hpkg, "boo"), "prop wasn't empty\n");
2202 
2203     r = MsiSetPropertyA( hpkg, "boo", "" );
2204     ok( r == ERROR_SUCCESS, "wrong return val\n");
2205     ok( check_prop_empty( hpkg, "boo"), "prop wasn't empty\n");
2206 
2207     /* set a non-empty value */
2208     r = MsiSetPropertyA( hpkg, "boo", "xyz" );
2209     ok( r == ERROR_SUCCESS, "wrong return val\n");
2210 
2211     sz = 1;
2212     strcpy(buffer,"x");
2213     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2214     ok( r == ERROR_MORE_DATA, "wrong return val\n");
2215     ok( buffer[0] == 0, "buffer was not changed\n");
2216     ok( sz == 3, "wrong size returned\n");
2217 
2218     sz = 4;
2219     strcpy(buffer,"x");
2220     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2221     ok( r == ERROR_SUCCESS, "wrong return val\n");
2222     ok( !strcmp(buffer,"xyz"), "buffer was not changed\n");
2223     ok( sz == 3, "wrong size returned\n");
2224 
2225     sz = 3;
2226     strcpy(buffer,"x");
2227     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2228     ok( r == ERROR_MORE_DATA, "wrong return val\n");
2229     ok( !strcmp(buffer,"xy"), "buffer was not changed\n");
2230     ok( sz == 3, "wrong size returned\n");
2231 
2232     r = MsiSetPropertyA(hpkg, "SourceDir", "foo");
2233     ok( r == ERROR_SUCCESS, "wrong return val\n");
2234 
2235     sz = 4;
2236     r = MsiGetPropertyA(hpkg, "SOURCEDIR", buffer, &sz);
2237     ok( r == ERROR_SUCCESS, "wrong return val\n");
2238     ok( !strcmp(buffer,""), "buffer wrong\n");
2239     ok( sz == 0, "wrong size returned\n");
2240 
2241     sz = 4;
2242     r = MsiGetPropertyA(hpkg, "SOMERANDOMNAME", buffer, &sz);
2243     ok( r == ERROR_SUCCESS, "wrong return val\n");
2244     ok( !strcmp(buffer,""), "buffer wrong\n");
2245     ok( sz == 0, "wrong size returned\n");
2246 
2247     sz = 4;
2248     r = MsiGetPropertyA(hpkg, "SourceDir", buffer, &sz);
2249     ok( r == ERROR_SUCCESS, "wrong return val\n");
2250     ok( !strcmp(buffer,"foo"), "buffer wrong\n");
2251     ok( sz == 3, "wrong size returned\n");
2252 
2253     r = MsiSetPropertyA(hpkg, "MetadataCompName", "Photoshop.dll");
2254     ok( r == ERROR_SUCCESS, "wrong return val\n");
2255 
2256     sz = 0;
2257     r = MsiGetPropertyA(hpkg, "MetadataCompName", NULL, &sz );
2258     ok( r == ERROR_SUCCESS, "return wrong\n");
2259     ok( sz == 13, "size wrong (%d)\n", sz);
2260 
2261     sz = 13;
2262     r = MsiGetPropertyA(hpkg, "MetadataCompName", buffer, &sz );
2263     ok( r == ERROR_MORE_DATA, "return wrong\n");
2264     ok( !strcmp(buffer,"Photoshop.dl"), "buffer wrong\n");
2265 
2266     r = MsiSetPropertyA(hpkg, "property", "value");
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( !strcmp(buffer, "value"), "Expected value, got %s\n", buffer);
2273 
2274     r = MsiSetPropertyA(hpkg, "property", NULL);
2275     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2276 
2277     sz = 6;
2278     r = MsiGetPropertyA(hpkg, "property", buffer, &sz);
2279     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2280     ok(!buffer[0], "Expected empty string, got %s\n", buffer);
2281 
2282     MsiCloseHandle( hpkg );
2283     DeleteFileA(msifile);
2284 }
2285 
2286 static BOOL find_prop_in_property(MSIHANDLE hdb, LPCSTR prop, LPCSTR val, int len)
2287 {
2288     MSIHANDLE hview, hrec;
2289     BOOL found = FALSE;
2290     CHAR buffer[MAX_PATH];
2291     DWORD sz;
2292     UINT r;
2293 
2294     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Property`", &hview);
2295     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
2296     r = MsiViewExecute(hview, 0);
2297     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
2298 
2299     if (len < 0) len = lstrlenA(val);
2300 
2301     while (r == ERROR_SUCCESS && !found)
2302     {
2303         r = MsiViewFetch(hview, &hrec);
2304         if (r != ERROR_SUCCESS) break;
2305 
2306         sz = MAX_PATH;
2307         r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
2308         if (r == ERROR_SUCCESS && !lstrcmpA(buffer, prop))
2309         {
2310             sz = MAX_PATH;
2311             r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
2312             if (r == ERROR_SUCCESS && !memcmp(buffer, val, len) && !buffer[len])
2313             {
2314                 ok(sz == len, "wrong size %u\n", sz);
2315                 found = TRUE;
2316             }
2317         }
2318 
2319         MsiCloseHandle(hrec);
2320     }
2321     MsiViewClose(hview);
2322     MsiCloseHandle(hview);
2323     return found;
2324 }
2325 
2326 static void test_property_table(void)
2327 {
2328     const char *query;
2329     UINT r;
2330     MSIHANDLE hpkg, hdb, hrec;
2331     char buffer[MAX_PATH], package[10];
2332     DWORD sz;
2333     BOOL found;
2334 
2335     hdb = create_package_db();
2336     ok( hdb, "failed to create package\n");
2337 
2338     r = package_from_db(hdb, &hpkg);
2339     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2340     {
2341         skip("Not enough rights to perform tests\n");
2342         DeleteFileA(msifile);
2343         return;
2344     }
2345     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
2346 
2347     MsiCloseHandle(hdb);
2348 
2349     hdb = MsiGetActiveDatabase(hpkg);
2350 
2351     query = "CREATE TABLE `_Property` ( "
2352         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
2353     r = run_query(hdb, query);
2354     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2355 
2356     MsiCloseHandle(hdb);
2357     MsiCloseHandle(hpkg);
2358     DeleteFileA(msifile);
2359 
2360     hdb = create_package_db();
2361     ok( hdb, "failed to create package\n");
2362 
2363     query = "CREATE TABLE `_Property` ( "
2364         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
2365     r = run_query(hdb, query);
2366     ok(r == ERROR_SUCCESS, "failed to create table\n");
2367 
2368     query = "ALTER `_Property` ADD `foo` INTEGER";
2369     r = run_query(hdb, query);
2370     ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to add column\n");
2371 
2372     query = "ALTER TABLE `_Property` ADD `foo` INTEGER";
2373     r = run_query(hdb, query);
2374     ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to add column\n");
2375 
2376     query = "ALTER TABLE `_Property` ADD `extra` INTEGER";
2377     r = run_query(hdb, query);
2378     ok(r == ERROR_SUCCESS, "failed to add column\n");
2379 
2380     sprintf(package, "#%i", hdb);
2381     r = MsiOpenPackageA(package, &hpkg);
2382     ok(r != ERROR_SUCCESS, "MsiOpenPackage succeeded\n");
2383     if (r == ERROR_SUCCESS)
2384         MsiCloseHandle(hpkg);
2385 
2386     r = MsiCloseHandle(hdb);
2387     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed %u\n", r);
2388 
2389     hdb = create_package_db();
2390     ok (hdb, "failed to create package database\n");
2391 
2392     r = create_property_table(hdb);
2393     ok(r == ERROR_SUCCESS, "cannot create Property table: %d\n", r);
2394 
2395     r = add_property_entry(hdb, "'prop', 'val'");
2396     ok(r == ERROR_SUCCESS, "cannot add property: %d\n", r);
2397 
2398     r = create_custom_action_table(hdb);
2399     ok(r == ERROR_SUCCESS, "cannot create CustomAction table: %d\n", r);
2400 
2401     r = add_custom_action_entry( hdb, "'EmbedNull', 51, 'prop2', '[~]np'" );
2402     ok( r == ERROR_SUCCESS, "cannot add custom action: %d\n", r);
2403 
2404     r = package_from_db(hdb, &hpkg);
2405     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
2406 
2407     MsiCloseHandle(hdb);
2408 
2409     sz = MAX_PATH;
2410     r = MsiGetPropertyA(hpkg, "prop", buffer, &sz);
2411     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2412     ok(!lstrcmpA(buffer, "val"), "Expected val, got %s\n", buffer);
2413 
2414     hdb = MsiGetActiveDatabase(hpkg);
2415 
2416     found = find_prop_in_property(hdb, "prop", "val", -1);
2417     ok(found, "prop should be in the _Property table\n");
2418 
2419     r = add_property_entry(hdb, "'dantes', 'mercedes'");
2420     ok(r == ERROR_SUCCESS, "cannot add property: %d\n", r);
2421 
2422     query = "SELECT * FROM `_Property` WHERE `Property` = 'dantes'";
2423     r = do_query(hdb, query, &hrec);
2424     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2425 
2426     found = find_prop_in_property(hdb, "dantes", "mercedes", -1);
2427     ok(found == FALSE, "dantes should not be in the _Property table\n");
2428 
2429     sz = MAX_PATH;
2430     lstrcpyA(buffer, "aaa");
2431     r = MsiGetPropertyA(hpkg, "dantes", buffer, &sz);
2432     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2433     ok(!buffer[0], "Expected empty string, got %s\n", buffer);
2434 
2435     r = MsiSetPropertyA(hpkg, "dantes", "mercedes");
2436     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2437 
2438     found = find_prop_in_property(hdb, "dantes", "mercedes", -1);
2439     ok(found == TRUE, "dantes should be in the _Property table\n");
2440 
2441     r = MsiDoActionA( hpkg, "EmbedNull" );
2442     ok( r == ERROR_SUCCESS, "EmbedNull failed: %d\n", r);
2443 
2444     sz = MAX_PATH;
2445     memset( buffer, 'a', sizeof(buffer) );
2446     r = MsiGetPropertyA( hpkg, "prop2", buffer, &sz );
2447     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2448     ok( !memcmp( buffer, "\0np", sizeof("\0np") ), "wrong value\n");
2449     ok( sz == sizeof("\0np") - 1, "got %u\n", sz );
2450 
2451     found = find_prop_in_property(hdb, "prop2", "\0np", 3);
2452     ok(found == TRUE, "prop2 should be in the _Property table\n");
2453 
2454     MsiCloseHandle(hdb);
2455     MsiCloseHandle(hpkg);
2456     DeleteFileA(msifile);
2457 }
2458 
2459 static UINT try_query_param( MSIHANDLE hdb, LPCSTR szQuery, MSIHANDLE hrec )
2460 {
2461     MSIHANDLE htab = 0;
2462     UINT res;
2463 
2464     res = MsiDatabaseOpenViewA( hdb, szQuery, &htab );
2465     if( res == ERROR_SUCCESS )
2466     {
2467         UINT r;
2468 
2469         r = MsiViewExecute( htab, hrec );
2470         if( r != ERROR_SUCCESS )
2471         {
2472             res = r;
2473             fprintf(stderr,"MsiViewExecute failed %08x\n", res);
2474         }
2475 
2476         r = MsiViewClose( htab );
2477         if( r != ERROR_SUCCESS )
2478             res = r;
2479 
2480         r = MsiCloseHandle( htab );
2481         if( r != ERROR_SUCCESS )
2482             res = r;
2483     }
2484     return res;
2485 }
2486 
2487 static UINT try_query( MSIHANDLE hdb, LPCSTR szQuery )
2488 {
2489     return try_query_param( hdb, szQuery, 0 );
2490 }
2491 
2492 static void set_summary_str(MSIHANDLE hdb, DWORD pid, LPCSTR value)
2493 {
2494     MSIHANDLE summary;
2495     UINT r;
2496 
2497     r = MsiGetSummaryInformationA(hdb, NULL, 1, &summary);
2498     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2499 
2500     r = MsiSummaryInfoSetPropertyA(summary, pid, VT_LPSTR, 0, NULL, value);
2501     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2502 
2503     r = MsiSummaryInfoPersist(summary);
2504     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2505 
2506     MsiCloseHandle(summary);
2507 }
2508 
2509 static void set_summary_dword(MSIHANDLE hdb, DWORD pid, DWORD value)
2510 {
2511     MSIHANDLE summary;
2512     UINT r;
2513 
2514     r = MsiGetSummaryInformationA(hdb, NULL, 1, &summary);
2515     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2516 
2517     r = MsiSummaryInfoSetPropertyA(summary, pid, VT_I4, value, NULL, NULL);
2518     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2519 
2520     r = MsiSummaryInfoPersist(summary);
2521     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2522 
2523     MsiCloseHandle(summary);
2524 }
2525 
2526 static void test_msipackage(void)
2527 {
2528     MSIHANDLE hdb = 0, hpack = 100;
2529     UINT r;
2530     const char *query;
2531     char name[10];
2532 
2533     /* NULL szPackagePath */
2534     r = MsiOpenPackageA(NULL, &hpack);
2535     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2536 
2537     /* empty szPackagePath */
2538     r = MsiOpenPackageA("", &hpack);
2539     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2540     {
2541         skip("Not enough rights to perform tests\n");
2542         return;
2543     }
2544     todo_wine
2545     {
2546         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2547     }
2548 
2549     if (r == ERROR_SUCCESS)
2550         MsiCloseHandle(hpack);
2551 
2552     /* nonexistent szPackagePath */
2553     r = MsiOpenPackageA("nonexistent", &hpack);
2554     ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
2555 
2556     /* NULL hProduct */
2557     r = MsiOpenPackageA(msifile, NULL);
2558     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2559 
2560     name[0]='#';
2561     name[1]=0;
2562     r = MsiOpenPackageA(name, &hpack);
2563     ok(r == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", r);
2564 
2565     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
2566     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2567 
2568     /* database exists, but is empty */
2569     sprintf(name, "#%d", hdb);
2570     r = MsiOpenPackageA(name, &hpack);
2571     ok(r == ERROR_INSTALL_PACKAGE_INVALID,
2572        "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
2573 
2574     query = "CREATE TABLE `Property` ( "
2575             "`Property` CHAR(72), `Value` CHAR(0) "
2576             "PRIMARY KEY `Property`)";
2577     r = try_query(hdb, query);
2578     ok(r == ERROR_SUCCESS, "failed to create Properties table\n");
2579 
2580     query = "CREATE TABLE `InstallExecuteSequence` ("
2581             "`Action` CHAR(72), `Condition` CHAR(0), `Sequence` INTEGER "
2582             "PRIMARY KEY `Action`)";
2583     r = try_query(hdb, query);
2584     ok(r == ERROR_SUCCESS, "failed to create InstallExecuteSequence table\n");
2585 
2586     /* a few key tables exist */
2587     sprintf(name, "#%d", hdb);
2588     r = MsiOpenPackageA(name, &hpack);
2589     ok(r == ERROR_INSTALL_PACKAGE_INVALID,
2590        "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
2591 
2592     MsiCloseHandle(hdb);
2593     DeleteFileA(msifile);
2594 
2595     /* start with a clean database to show what constitutes a valid package */
2596     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
2597     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2598 
2599     sprintf(name, "#%d", hdb);
2600 
2601     /* The following summary information props must exist:
2602      *  - PID_REVNUMBER
2603      *  - PID_PAGECOUNT
2604      */
2605 
2606     set_summary_dword(hdb, PID_PAGECOUNT, 100);
2607     r = MsiOpenPackageA(name, &hpack);
2608     ok(r == ERROR_INSTALL_PACKAGE_INVALID,
2609        "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
2610 
2611     set_summary_str(hdb, PID_REVNUMBER, "{004757CD-5092-49C2-AD20-28E1CE0DF5F2}");
2612     r = MsiOpenPackageA(name, &hpack);
2613     ok(r == ERROR_SUCCESS,
2614        "Expected ERROR_SUCCESS, got %d\n", r);
2615 
2616     MsiCloseHandle(hpack);
2617     MsiCloseHandle(hdb);
2618     DeleteFileA(msifile);
2619 }
2620 
2621 static void test_formatrecord2(void)
2622 {
2623     MSIHANDLE hpkg, hrec ;
2624     char buffer[0x100];
2625     DWORD sz;
2626     UINT r;
2627 
2628     r = package_from_db(create_package_db(), &hpkg);
2629     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2630     {
2631         skip("Not enough rights to perform tests\n");
2632         DeleteFileA(msifile);
2633         return;
2634     }
2635     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
2636 
2637     r = MsiSetPropertyA(hpkg, "Manufacturer", " " );
2638     ok( r == ERROR_SUCCESS, "set property failed\n");
2639 
2640     hrec = MsiCreateRecord(2);
2641     ok(hrec, "create record failed\n");
2642 
2643     r = MsiRecordSetStringA( hrec, 0, "[ProgramFilesFolder][Manufacturer]\\asdf");
2644     ok( r == ERROR_SUCCESS, "format record failed\n");
2645 
2646     buffer[0] = 0;
2647     sz = sizeof buffer;
2648     r = MsiFormatRecordA( hpkg, hrec, buffer, &sz );
2649     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2650 
2651     r = MsiRecordSetStringA(hrec, 0, "[foo][1]");
2652     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2653     r = MsiRecordSetStringA(hrec, 1, "hoo");
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,"hoo"), "wrong output %s\n",buffer);
2659     ok( r == ERROR_SUCCESS, "format failed\n");
2660 
2661     r = MsiRecordSetStringA(hrec, 0, "x[~]x");
2662     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2663     sz = sizeof buffer;
2664     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2665     ok( sz == 3, "size wrong\n");
2666     ok( 0 == strcmp(buffer,"x"), "wrong output %s\n",buffer);
2667     ok( r == ERROR_SUCCESS, "format failed\n");
2668 
2669     r = MsiRecordSetStringA(hrec, 0, "[foo.$%}][1]");
2670     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2671     r = MsiRecordSetStringA(hrec, 1, "hoo");
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 == 3, "size wrong\n");
2676     ok( 0 == strcmp(buffer,"hoo"), "wrong output %s\n",buffer);
2677     ok( r == ERROR_SUCCESS, "format failed\n");
2678 
2679     r = MsiRecordSetStringA(hrec, 0, "[\\[]");
2680     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2681     sz = sizeof buffer;
2682     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2683     ok( sz == 1, "size wrong\n");
2684     ok( 0 == strcmp(buffer,"["), "wrong output %s\n",buffer);
2685     ok( r == ERROR_SUCCESS, "format failed\n");
2686 
2687     SetEnvironmentVariableA("FOO", "BAR");
2688     r = MsiRecordSetStringA(hrec, 0, "[%FOO]");
2689     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2690     sz = sizeof buffer;
2691     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2692     ok( sz == 3, "size wrong\n");
2693     ok( 0 == strcmp(buffer,"BAR"), "wrong output %s\n",buffer);
2694     ok( r == ERROR_SUCCESS, "format failed\n");
2695 
2696     r = MsiRecordSetStringA(hrec, 0, "[[1]]");
2697     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2698     r = MsiRecordSetStringA(hrec, 1, "%FOO");
2699     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2700     sz = sizeof buffer;
2701     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2702     ok( sz == 3, "size wrong\n");
2703     ok( 0 == strcmp(buffer,"BAR"), "wrong output %s\n",buffer);
2704     ok( r == ERROR_SUCCESS, "format failed\n");
2705 
2706     MsiCloseHandle( hrec );
2707     MsiCloseHandle( hpkg );
2708     DeleteFileA(msifile);
2709 }
2710 
2711 static void test_feature_states( UINT line, MSIHANDLE package, const char *feature, UINT error,
2712                                  INSTALLSTATE expected_state, INSTALLSTATE expected_action, BOOL todo )
2713 {
2714     UINT r;
2715     INSTALLSTATE state = 0xdeadbee;
2716     INSTALLSTATE action = 0xdeadbee;
2717 
2718     r = MsiGetFeatureStateA( package, feature, &state, &action );
2719     ok( r == error, "%u: expected %d got %d\n", line, error, r );
2720     if (r == ERROR_SUCCESS)
2721     {
2722         ok( state == expected_state, "%u: expected state %d got %d\n",
2723             line, expected_state, state );
2724         todo_wine_if (todo)
2725             ok( action == expected_action, "%u: expected action %d got %d\n",
2726                 line, expected_action, action );
2727     }
2728     else
2729     {
2730         ok( state == 0xdeadbee, "%u: expected state 0xdeadbee got %d\n", line, state );
2731         todo_wine_if (todo)
2732             ok( action == 0xdeadbee, "%u: expected action 0xdeadbee got %d\n", line, action );
2733 
2734     }
2735 }
2736 
2737 static void test_component_states( UINT line, MSIHANDLE package, const char *component, UINT error,
2738                                    INSTALLSTATE expected_state, INSTALLSTATE expected_action, BOOL todo )
2739 {
2740     UINT r;
2741     INSTALLSTATE state = 0xdeadbee;
2742     INSTALLSTATE action = 0xdeadbee;
2743 
2744     r = MsiGetComponentStateA( package, component, &state, &action );
2745     ok( r == error, "%u: expected %d got %d\n", line, error, r );
2746     if (r == ERROR_SUCCESS)
2747     {
2748         ok( state == expected_state, "%u: expected state %d got %d\n",
2749             line, expected_state, state );
2750         todo_wine_if (todo)
2751             ok( action == expected_action, "%u: expected action %d got %d\n",
2752                 line, expected_action, action );
2753     }
2754     else
2755     {
2756         ok( state == 0xdeadbee, "%u: expected state 0xdeadbee got %d\n",
2757             line, state );
2758         todo_wine_if (todo)
2759             ok( action == 0xdeadbee, "%u: expected action 0xdeadbee got %d\n",
2760                 line, action );
2761     }
2762 }
2763 
2764 static void test_states(void)
2765 {
2766     static const char msifile2[] = "winetest2-package.msi";
2767     static const char msifile3[] = "winetest3-package.msi";
2768     static const char msifile4[] = "winetest4-package.msi";
2769     static const WCHAR msifile2W[] =
2770         {'w','i','n','e','t','e','s','t','2','-','p','a','c','k','a','g','e','.','m','s','i',0};
2771     static const WCHAR msifile3W[] =
2772         {'w','i','n','e','t','e','s','t','3','-','p','a','c','k','a','g','e','.','m','s','i',0};
2773     static const WCHAR msifile4W[] =
2774         {'w','i','n','e','t','e','s','t','4','-','p','a','c','k','a','g','e','.','m','s','i',0};
2775     INSTALLSTATE state;
2776     MSIHANDLE hpkg;
2777     UINT r;
2778     MSIHANDLE hdb;
2779 
2780     if (is_process_limited())
2781     {
2782         skip("process is limited\n");
2783         return;
2784     }
2785 
2786     hdb = create_package_db();
2787     ok ( hdb, "failed to create package database\n" );
2788 
2789     r = add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'");
2790     ok( r == ERROR_SUCCESS, "cannot add directory: %d\n", r );
2791 
2792     r = create_property_table( hdb );
2793     ok( r == ERROR_SUCCESS, "cannot create Property table: %d\n", r );
2794 
2795     r = add_property_entry( hdb, "'ProductCode', '{7262AC98-EEBD-4364-8CE3-D654F6A425B9}'" );
2796     ok( r == ERROR_SUCCESS, "cannot add property entry: %d\n", r );
2797 
2798     r = add_property_entry( hdb, "'ProductLanguage', '1033'" );
2799     ok( r == ERROR_SUCCESS, "cannot add property entry: %d\n", r );
2800 
2801     r = add_property_entry( hdb, "'ProductName', 'MSITEST'" );
2802     ok( r == ERROR_SUCCESS, "cannot add property entry: %d\n", r );
2803 
2804     r = add_property_entry( hdb, "'ProductVersion', '1.1.1'" );
2805     ok( r == ERROR_SUCCESS, "cannot add property entry: %d\n", r );
2806 
2807     r = add_property_entry( hdb, "'MSIFASTINSTALL', '1'" );
2808     ok( r == ERROR_SUCCESS, "cannot add property entry: %d\n", r );
2809 
2810     r = create_install_execute_sequence_table( hdb );
2811     ok( r == ERROR_SUCCESS, "cannot create InstallExecuteSequence table: %d\n", r );
2812 
2813     r = add_install_execute_sequence_entry( hdb, "'CostInitialize', '', '800'" );
2814     ok( r == ERROR_SUCCESS, "cannot add install execute sequence entry: %d\n", r );
2815 
2816     r = add_install_execute_sequence_entry( hdb, "'FileCost', '', '900'" );
2817     ok( r == ERROR_SUCCESS, "cannot add install execute sequence entry: %d\n", r );
2818 
2819     r = add_install_execute_sequence_entry( hdb, "'CostFinalize', '', '1000'" );
2820     ok( r == ERROR_SUCCESS, "cannot add install execute sequence entry: %d\n", r );
2821 
2822     r = add_install_execute_sequence_entry( hdb, "'InstallValidate', '', '1400'" );
2823     ok( r == ERROR_SUCCESS, "cannot add install execute sequence entry: %d\n", r );
2824 
2825     r = add_install_execute_sequence_entry( hdb, "'InstallInitialize', '', '1500'" );
2826     ok( r == ERROR_SUCCESS, "cannot add install execute sequence entry: %d\n", r );
2827 
2828     r = add_install_execute_sequence_entry( hdb, "'ProcessComponents', '', '1600'" );
2829     ok( r == ERROR_SUCCESS, "cannot add install execute sequence entry: %d\n", r );
2830 
2831     r = add_install_execute_sequence_entry( hdb, "'UnpublishFeatures', '', '1800'" );
2832     ok( r == ERROR_SUCCESS, "cannot add install execute sequence entry: %d\n", r );
2833 
2834     r = add_install_execute_sequence_entry( hdb, "'RegisterProduct', '', '6100'" );
2835     ok( r == ERROR_SUCCESS, "cannot add install execute sequence entry: %d\n", r );
2836 
2837     r = add_install_execute_sequence_entry( hdb, "'PublishFeatures', '', '6300'" );
2838     ok( r == ERROR_SUCCESS, "cannot add install execute sequence entry: %d\n", r );
2839 
2840     r = add_install_execute_sequence_entry( hdb, "'PublishProduct', '', '6400'" );
2841     ok( r == ERROR_SUCCESS, "cannot add install execute sequence entry: %d\n", r );
2842 
2843     r = add_install_execute_sequence_entry( hdb, "'InstallFinalize', '', '6600'" );
2844     ok( r == ERROR_SUCCESS, "cannot add install execute sequence entry: %d\n", r );
2845 
2846     r = create_media_table( hdb );
2847     ok( r == ERROR_SUCCESS, "cannot create media table: %d\n", r );
2848 
2849     r = add_media_entry( hdb, "'1', '3', '', '', 'DISK1', ''");
2850     ok( r == ERROR_SUCCESS, "cannot add media entry: %d\n", r );
2851 
2852     r = create_feature_table( hdb );
2853     ok( r == ERROR_SUCCESS, "cannot create Feature table: %d\n", r );
2854 
2855     r = create_component_table( hdb );
2856     ok( r == ERROR_SUCCESS, "cannot create Component table: %d\n", r );
2857 
2858     /* msidbFeatureAttributesFavorLocal */
2859     r = add_feature_entry( hdb, "'one', '', '', '', 2, 1, '', 0" );
2860     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
2861 
2862     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesLocalOnly */
2863     r = add_component_entry( hdb, "'alpha', '{467EC132-739D-4784-A37B-677AA43DBC94}', 'TARGETDIR', 0, '', 'alpha_file'" );
2864     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2865 
2866     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSourceOnly */
2867     r = add_component_entry( hdb, "'beta', '{2C1F189C-24A6-4C34-B26B-994A6C026506}', 'TARGETDIR', 1, '', 'beta_file'" );
2868     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2869 
2870     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesOptional */
2871     r = add_component_entry( hdb, "'gamma', '{C271E2A4-DE2E-4F70-86D1-6984AF7DE2CA}', 'TARGETDIR', 2, '', 'gamma_file'" );
2872     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2873 
2874     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSharedDllRefCount */
2875     r = add_component_entry( hdb, "'theta', '{4EB3129D-81A8-48D5-9801-75600FED3DD9}', 'TARGETDIR', 8, '', 'theta_file'" );
2876     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2877 
2878     /* msidbFeatureAttributesFavorSource */
2879     r = add_feature_entry( hdb, "'two', '', '', '', 2, 1, '', 1" );
2880     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
2881 
2882     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesLocalOnly */
2883     r = add_component_entry( hdb, "'delta', '{938FD4F2-C648-4259-A03C-7AA3B45643F3}', 'TARGETDIR', 0, '', 'delta_file'" );
2884     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2885 
2886     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSourceOnly */
2887     r = add_component_entry( hdb, "'epsilon', '{D59713B6-C11D-47F2-A395-1E5321781190}', 'TARGETDIR', 1, '', 'epsilon_file'" );
2888     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2889 
2890     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesOptional */
2891     r = add_component_entry( hdb, "'zeta', '{377D33AB-2FAA-42B9-A629-0C0DAE9B9C7A}', 'TARGETDIR', 2, '', 'zeta_file'" );
2892     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2893 
2894     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSharedDllRefCount */
2895     r = add_component_entry( hdb, "'iota', '{5D36F871-B5ED-4801-9E0F-C46B9E5C9669}', 'TARGETDIR', 8, '', 'iota_file'" );
2896     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2897 
2898     /* msidbFeatureAttributesFavorSource */
2899     r = add_feature_entry( hdb, "'three', '', '', '', 2, 1, '', 1" );
2900     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
2901 
2902     /* msidbFeatureAttributesFavorLocal */
2903     r = add_feature_entry( hdb, "'four', '', '', '', 2, 1, '', 0" );
2904     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
2905 
2906     /* disabled */
2907     r = add_feature_entry( hdb, "'five', '', '', '', 2, 0, '', 1" );
2908     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
2909 
2910     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSourceOnly */
2911     r = add_component_entry( hdb, "'eta', '{DD89003F-0DD4-41B8-81C0-3411A7DA2695}', 'TARGETDIR', 1, '', 'eta_file'" );
2912     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2913 
2914     /* no feature parent:msidbComponentAttributesLocalOnly */
2915     r = add_component_entry( hdb, "'kappa', '{D6B93DC3-8DA5-4769-9888-42BFE156BB8B}', 'TARGETDIR', 1, '', 'kappa_file'" );
2916     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2917 
2918     /* msidbFeatureAttributesFavorLocal:removed */
2919     r = add_feature_entry( hdb, "'six', '', '', '', 2, 1, '', 0" );
2920     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
2921 
2922     /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesLocalOnly */
2923     r = add_component_entry( hdb, "'lambda', '{6528C5E4-02A4-4636-A214-7A66A6C35B64}', 'TARGETDIR', 0, '', 'lambda_file'" );
2924     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2925 
2926     /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesSourceOnly */
2927     r = add_component_entry( hdb, "'mu', '{97014BAB-6C56-4013-9A63-2BF913B42519}', 'TARGETDIR', 1, '', 'mu_file'" );
2928     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2929 
2930     /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesOptional */
2931     r = add_component_entry( hdb, "'nu', '{943DD0D8-5808-4954-8526-3B8493FEDDCD}', 'TARGETDIR', 2, '', 'nu_file'" );
2932     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2933 
2934     /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesSharedDllRefCount */
2935     r = add_component_entry( hdb, "'xi', '{D6CF9EF7-6FCF-4930-B34B-F938AEFF9BDB}', 'TARGETDIR', 8, '', 'xi_file'" );
2936     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2937 
2938     /* msidbFeatureAttributesFavorSource:removed */
2939     r = add_feature_entry( hdb, "'seven', '', '', '', 2, 1, '', 1" );
2940     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
2941 
2942     /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesLocalOnly */
2943     r = add_component_entry( hdb, "'omicron', '{7B57521D-15DB-4141-9AA6-01D934A4433F}', 'TARGETDIR', 0, '', 'omicron_file'" );
2944     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2945 
2946     /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesSourceOnly */
2947     r = add_component_entry( hdb, "'pi', '{FB85346B-378E-4492-8769-792305471C81}', 'TARGETDIR', 1, '', 'pi_file'" );
2948     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2949 
2950     /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesOptional */
2951     r = add_component_entry( hdb, "'rho', '{798F2047-7B0C-4783-8BB0-D703E554114B}', 'TARGETDIR', 2, '', 'rho_file'" );
2952     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2953 
2954     /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesSharedDllRefCount */
2955     r = add_component_entry( hdb, "'sigma', '{5CE9DDA8-B67B-4736-9D93-99D61C5B93E7}', 'TARGETDIR', 8, '', 'sigma_file'" );
2956     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2957 
2958     /* msidbFeatureAttributesFavorLocal */
2959     r = add_feature_entry( hdb, "'eight', '', '', '', 2, 1, '', 0" );
2960     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
2961 
2962     r = add_component_entry( hdb, "'tau', '{07DEB510-677C-4A6F-A0A6-7CD8EFEA77ED}', 'TARGETDIR', 1, '', 'tau_file'" );
2963     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2964 
2965     /* msidbFeatureAttributesFavorSource */
2966     r = add_feature_entry( hdb, "'nine', '', '', '', 2, 1, '', 1" );
2967     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
2968 
2969     r = add_component_entry( hdb, "'phi', '{9F0594C5-35AD-43EA-94DD-8DF73FAA664D}', 'TARGETDIR', 1, '', 'phi_file'" );
2970     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2971 
2972     /* msidbFeatureAttributesFavorAdvertise */
2973     r = add_feature_entry( hdb, "'ten', '', '', '', 2, 1, '', 4" );
2974     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
2975 
2976     r = add_component_entry( hdb, "'chi', '{E6B539AB-5DA9-4236-A2D2-E341A50B4C38}', 'TARGETDIR', 1, '', 'chi_file'" );
2977     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2978 
2979     /* msidbFeatureAttributesUIDisallowAbsent */
2980     r = add_feature_entry( hdb, "'eleven', '', '', '', 2, 1, '', 16" );
2981     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
2982 
2983     r = add_component_entry( hdb, "'psi', '{A06B23B5-746B-427A-8A6E-FD6AC8F46A95}', 'TARGETDIR', 1, '', 'psi_file'" );
2984     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2985 
2986     /* high install level */
2987     r = add_feature_entry( hdb, "'twelve', '', '', '', 2, 2, '', 0" );
2988     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
2989 
2990     r = add_component_entry( hdb, "'upsilon', '{557e0c04-ceba-4c58-86a9-4a73352e8cf6}', 'TARGETDIR', 1, '', 'upsilon_file'" );
2991     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2992 
2993     /* msidbFeatureAttributesFollowParent */
2994     r = add_feature_entry( hdb, "'thirteen', '', '', '', 2, 2, '', 2" );
2995     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
2996 
2997     r = create_feature_components_table( hdb );
2998     ok( r == ERROR_SUCCESS, "cannot create FeatureComponents table: %d\n", r );
2999 
3000     r = add_feature_components_entry( hdb, "'one', 'alpha'" );
3001     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3002 
3003     r = add_feature_components_entry( hdb, "'one', 'beta'" );
3004     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3005 
3006     r = add_feature_components_entry( hdb, "'one', 'gamma'" );
3007     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3008 
3009     r = add_feature_components_entry( hdb, "'one', 'theta'" );
3010     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3011 
3012     r = add_feature_components_entry( hdb, "'two', 'delta'" );
3013     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3014 
3015     r = add_feature_components_entry( hdb, "'two', 'epsilon'" );
3016     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3017 
3018     r = add_feature_components_entry( hdb, "'two', 'zeta'" );
3019     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3020 
3021     r = add_feature_components_entry( hdb, "'two', 'iota'" );
3022     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3023 
3024     r = add_feature_components_entry( hdb, "'three', 'eta'" );
3025     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3026 
3027     r = add_feature_components_entry( hdb, "'four', 'eta'" );
3028     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3029 
3030     r = add_feature_components_entry( hdb, "'five', 'eta'" );
3031     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3032 
3033     r = add_feature_components_entry( hdb, "'six', 'lambda'" );
3034     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3035 
3036     r = add_feature_components_entry( hdb, "'six', 'mu'" );
3037     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3038 
3039     r = add_feature_components_entry( hdb, "'six', 'nu'" );
3040     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3041 
3042     r = add_feature_components_entry( hdb, "'six', 'xi'" );
3043     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3044 
3045     r = add_feature_components_entry( hdb, "'seven', 'omicron'" );
3046     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3047 
3048     r = add_feature_components_entry( hdb, "'seven', 'pi'" );
3049     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3050 
3051     r = add_feature_components_entry( hdb, "'seven', 'rho'" );
3052     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3053 
3054     r = add_feature_components_entry( hdb, "'seven', 'sigma'" );
3055     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3056 
3057     r = add_feature_components_entry( hdb, "'eight', 'tau'" );
3058     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3059 
3060     r = add_feature_components_entry( hdb, "'nine', 'phi'" );
3061     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3062 
3063     r = add_feature_components_entry( hdb, "'ten', 'chi'" );
3064     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3065 
3066     r = add_feature_components_entry( hdb, "'eleven', 'psi'" );
3067     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3068 
3069     r = add_feature_components_entry( hdb, "'twelve', 'upsilon'" );
3070     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3071 
3072     r = add_feature_components_entry( hdb, "'thirteen', 'upsilon'" );
3073     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3074 
3075     r = create_file_table( hdb );
3076     ok( r == ERROR_SUCCESS, "cannot create File table: %d\n", r );
3077 
3078     r = add_file_entry( hdb, "'alpha_file', 'alpha', 'alpha.txt', 100, '', '1033', 8192, 1" );
3079     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3080 
3081     r = add_file_entry( hdb, "'beta_file', 'beta', 'beta.txt', 0, '', '1033', 8192, 1" );
3082     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3083 
3084     r = add_file_entry( hdb, "'gamma_file', 'gamma', 'gamma.txt', 0, '', '1033', 8192, 1" );
3085     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3086 
3087     r = add_file_entry( hdb, "'theta_file', 'theta', 'theta.txt', 0, '', '1033', 8192, 1" );
3088     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3089 
3090     r = add_file_entry( hdb, "'delta_file', 'delta', 'delta.txt', 0, '', '1033', 8192, 1" );
3091     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3092 
3093     r = add_file_entry( hdb, "'epsilon_file', 'epsilon', 'epsilon.txt', 0, '', '1033', 8192, 1" );
3094     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3095 
3096     r = add_file_entry( hdb, "'zeta_file', 'zeta', 'zeta.txt', 0, '', '1033', 8192, 1" );
3097     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3098 
3099     r = add_file_entry( hdb, "'iota_file', 'iota', 'iota.txt', 0, '', '1033', 8192, 1" );
3100     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3101 
3102     /* compressed file */
3103     r = add_file_entry( hdb, "'eta_file', 'eta', 'eta.txt', 0, '', '1033', 16384, 1" );
3104     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3105 
3106     r = add_file_entry( hdb, "'kappa_file', 'kappa', 'kappa.txt', 0, '', '1033', 8192, 1" );
3107     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3108 
3109     r = add_file_entry( hdb, "'lambda_file', 'lambda', 'lambda.txt', 100, '', '1033', 8192, 1" );
3110     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3111 
3112     r = add_file_entry( hdb, "'mu_file', 'mu', 'mu.txt', 100, '', '1033', 8192, 1" );
3113     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3114 
3115     r = add_file_entry( hdb, "'nu_file', 'nu', 'nu.txt', 100, '', '1033', 8192, 1" );
3116     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3117 
3118     r = add_file_entry( hdb, "'xi_file', 'xi', 'xi.txt', 100, '', '1033', 8192, 1" );
3119     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3120 
3121     r = add_file_entry( hdb, "'omicron_file', 'omicron', 'omicron.txt', 100, '', '1033', 8192, 1" );
3122     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3123 
3124     r = add_file_entry( hdb, "'pi_file', 'pi', 'pi.txt', 100, '', '1033', 8192, 1" );
3125     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3126 
3127     r = add_file_entry( hdb, "'rho_file', 'rho', 'rho.txt', 100, '', '1033', 8192, 1" );
3128     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3129 
3130     r = add_file_entry( hdb, "'sigma_file', 'sigma', 'sigma.txt', 100, '', '1033', 8192, 1" );
3131     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3132 
3133     r = add_file_entry( hdb, "'tau_file', 'tau', 'tau.txt', 100, '', '1033', 8192, 1" );
3134     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3135 
3136     r = add_file_entry( hdb, "'phi_file', 'phi', 'phi.txt', 100, '', '1033', 8192, 1" );
3137     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3138 
3139     r = add_file_entry( hdb, "'chi_file', 'chi', 'chi.txt', 100, '', '1033', 8192, 1" );
3140     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3141 
3142     r = add_file_entry( hdb, "'psi_file', 'psi', 'psi.txt', 100, '', '1033', 8192, 1" );
3143     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3144 
3145     r = add_file_entry( hdb, "'upsilon_file', 'upsilon', 'upsilon.txt', 0, '', '1033', 16384, 1" );
3146     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3147 
3148     MsiDatabaseCommit(hdb);
3149 
3150     /* these properties must not be in the saved msi file */
3151     r = add_property_entry( hdb, "'ADDLOCAL', 'one,four'");
3152     ok( r == ERROR_SUCCESS, "cannot add property: %d\n", r );
3153 
3154     r = add_property_entry( hdb, "'ADDSOURCE', 'two,three'");
3155     ok( r == ERROR_SUCCESS, "cannot add property: %d\n", r );
3156 
3157     r = add_property_entry( hdb, "'REMOVE', 'six,seven'");
3158     ok( r == ERROR_SUCCESS, "cannot add property: %d\n", r );
3159 
3160     r = add_property_entry( hdb, "'REINSTALL', 'eight,nine,ten'");
3161     ok( r == ERROR_SUCCESS, "cannot add property: %d\n", r );
3162 
3163     r = add_property_entry( hdb, "'REINSTALLMODE', 'omus'");
3164     ok( r == ERROR_SUCCESS, "cannot add property: %d\n", r );
3165 
3166     r = package_from_db( hdb, &hpkg );
3167     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
3168     {
3169         skip("Not enough rights to perform tests\n");
3170         DeleteFileA(msifile);
3171         return;
3172     }
3173     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3174 
3175     MsiCloseHandle(hdb);
3176 
3177     CopyFileA(msifile, msifile2, FALSE);
3178     CopyFileA(msifile, msifile3, FALSE);
3179     CopyFileA(msifile, msifile4, FALSE);
3180 
3181     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3182     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3183 
3184     r = MsiDoActionA( hpkg, "CostInitialize");
3185     ok( r == ERROR_SUCCESS, "cost init 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     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3191 
3192     r = MsiDoActionA( hpkg, "FileCost");
3193     ok( r == ERROR_SUCCESS, "file cost failed\n");
3194 
3195     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3196     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3197 
3198     r = MsiDoActionA( hpkg, "CostFinalize");
3199     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3200 
3201     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3202     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
3203     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3204     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3205     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3206     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3207     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3208     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3209     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3210     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3211     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3212     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3213     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3214 
3215     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3216     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
3217     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3218     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3219     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3220     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
3221     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
3222     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3223     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3224     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3225     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3226     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3227     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3228     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3229     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3230     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3231     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3232     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3233     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3234     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3235     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3236     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3237     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3238 
3239     MsiCloseHandle( hpkg );
3240 
3241     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3242 
3243     /* publish the features and components */
3244     r = MsiInstallProductA(msifile, "ADDLOCAL=one,four ADDSOURCE=two,three REMOVE=six,seven REINSTALL=eight,nine,ten");
3245     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3246 
3247     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb);
3248     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3249 
3250     /* these properties must not be in the saved msi file */
3251     r = add_property_entry( hdb, "'ADDLOCAL', 'one,four'");
3252     ok( r == ERROR_SUCCESS, "cannot add property: %d\n", r );
3253 
3254     r = add_property_entry( hdb, "'ADDSOURCE', 'two,three'");
3255     ok( r == ERROR_SUCCESS, "cannot add property: %d\n", r );
3256 
3257     r = add_property_entry( hdb, "'REMOVE', 'six,seven'");
3258     ok( r == ERROR_SUCCESS, "cannot add property: %d\n", r );
3259 
3260     r = add_property_entry( hdb, "'REINSTALL', 'eight,nine,ten'");
3261     ok( r == ERROR_SUCCESS, "cannot add property: %d\n", r );
3262 
3263     r = package_from_db( hdb, &hpkg );
3264     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3265 
3266     MsiCloseHandle(hdb);
3267 
3268     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3269     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3270 
3271     r = MsiDoActionA( hpkg, "CostInitialize");
3272     ok( r == ERROR_SUCCESS, "cost init failed\n");
3273 
3274     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3275     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3276 
3277     r = MsiDoActionA( hpkg, "FileCost");
3278     ok( r == ERROR_SUCCESS, "file cost failed\n");
3279 
3280     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3281     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3282 
3283     r = MsiDoActionA( hpkg, "CostFinalize");
3284     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3285 
3286     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3287     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3288     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3289     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3290     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3291     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3292     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3293     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3294     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3295     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3296     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3297     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3298     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3299 
3300     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3301     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3302     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3303     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3304     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3305     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3306     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3307     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3308     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3309     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3310     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3311     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3312     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3313     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3314     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3315     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3316     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3317     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3318     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3319     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3320     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3321     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3322     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3323 
3324     MsiCloseHandle(hpkg);
3325 
3326     /* uninstall the product */
3327     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3328     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3329 
3330     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3331     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3332     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3333     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3334 
3335     /* all features installed locally */
3336     r = MsiInstallProductA(msifile2, "ADDLOCAL=ALL");
3337     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3338 
3339     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3340     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3341     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3342     ok(state == INSTALLSTATE_LOCAL, "state = %d\n", state);
3343 
3344     r = MsiOpenDatabaseW(msifile2W, MSIDBOPEN_DIRECT, &hdb);
3345     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3346 
3347     /* these properties must not be in the saved msi file */
3348     r = add_property_entry( hdb, "'ADDLOCAL', 'one,two,three,four,five,six,seven,eight,nine,ten,twelve'");
3349     ok( r == ERROR_SUCCESS, "cannot add property: %d\n", r );
3350 
3351     r = package_from_db( hdb, &hpkg );
3352     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3353 
3354     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3355     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3356 
3357     r = MsiDoActionA( hpkg, "CostInitialize");
3358     ok( r == ERROR_SUCCESS, "cost init failed\n");
3359 
3360     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3361     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3362 
3363     r = MsiDoActionA( hpkg, "CostFinalize");
3364     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3365 
3366     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3367     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3368     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3369     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3370     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3371     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3372     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3373     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, TRUE );
3374     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, TRUE );
3375     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, TRUE );
3376     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3377     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3378     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3379 
3380     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3381     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3382     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3383     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3384     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3385     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3386     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3387     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3388     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3389     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3390     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3391     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3392     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3393     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3394     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3395     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3396     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3397     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3398     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3399     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3400     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3401     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3402     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3403 
3404     MsiCloseHandle(hpkg);
3405 
3406     /* uninstall the product */
3407     r = MsiInstallProductA(msifile2, "REMOVE=ALL");
3408     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3409 
3410     /* all features installed from source */
3411     r = MsiInstallProductA(msifile3, "ADDSOURCE=ALL");
3412     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3413 
3414     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3415     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3416     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3417     ok(state == INSTALLSTATE_LOCAL, "state = %d\n", state);
3418 
3419     r = MsiOpenDatabaseW(msifile3W, MSIDBOPEN_DIRECT, &hdb);
3420     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3421 
3422     /* this property must not be in the saved msi file */
3423     r = add_property_entry( hdb, "'ADDSOURCE', 'one,two,three,four,five,six,seven,eight,nine,ten'");
3424     ok( r == ERROR_SUCCESS, "cannot add property: %d\n", r );
3425 
3426     r = package_from_db( hdb, &hpkg );
3427     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3428 
3429     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3430     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3431 
3432     r = MsiDoActionA( hpkg, "CostInitialize");
3433     ok( r == ERROR_SUCCESS, "cost init failed\n");
3434 
3435     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3436     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3437 
3438     r = MsiDoActionA( hpkg, "FileCost");
3439     ok( r == ERROR_SUCCESS, "file cost failed\n");
3440 
3441     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3442     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3443 
3444     r = MsiDoActionA( hpkg, "CostFinalize");
3445     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3446 
3447     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3448     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3449     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3450     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3451     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3452     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3453     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3454     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3455     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3456     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3457     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3458     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3459     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3460 
3461     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3462     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3463     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3464     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3465     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3466     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3467     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3468     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3469     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3470     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3471     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3472     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3473     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3474     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3475     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3476     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3477     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3478     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3479     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3480     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3481     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3482     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3483     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, TRUE );
3484 
3485     MsiCloseHandle(hpkg);
3486 
3487     /* reinstall the product */
3488     r = MsiInstallProductA(msifile3, "REINSTALL=ALL");
3489     ok(r == ERROR_SUCCESS || broken(r == ERROR_INSTALL_FAILURE) /* win2k3 */, "Expected ERROR_SUCCESS, got %d\n", r);
3490 
3491     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3492     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3493     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3494     ok(state == INSTALLSTATE_LOCAL, "state = %d\n", state);
3495 
3496     r = MsiOpenDatabaseW(msifile4W, MSIDBOPEN_DIRECT, &hdb);
3497     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3498 
3499     /* this property must not be in the saved msi file */
3500     r = add_property_entry( hdb, "'ADDSOURCE', 'one,two,three,four,five,six,seven,eight,nine,ten'");
3501     ok( r == ERROR_SUCCESS, "cannot add property: %d\n", r );
3502 
3503     r = package_from_db( hdb, &hpkg );
3504     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3505 
3506     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3507     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3508 
3509     r = MsiDoActionA( hpkg, "CostInitialize");
3510     ok( r == ERROR_SUCCESS, "cost init failed\n");
3511 
3512     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3513     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3514 
3515     r = MsiDoActionA( hpkg, "FileCost");
3516     ok( r == ERROR_SUCCESS, "file cost failed\n");
3517 
3518     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3519     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3520 
3521     r = MsiDoActionA( hpkg, "CostFinalize");
3522     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3523 
3524     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3525     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3526     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3527     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3528     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3529     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3530     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3531     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3532     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3533     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3534     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3535     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3536     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3537 
3538     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3539     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3540     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3541     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3542     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3543     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3544     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3545     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3546     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3547     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3548     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3549     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3550     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3551     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3552     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3553     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3554     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3555     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3556     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3557     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3558     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3559     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3560     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, TRUE );
3561 
3562     MsiCloseHandle(hpkg);
3563 
3564     /* uninstall the product */
3565     r = MsiInstallProductA(msifile4, "REMOVE=ALL");
3566     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3567 
3568     DeleteFileA(msifile);
3569     DeleteFileA(msifile2);
3570     DeleteFileA(msifile3);
3571     DeleteFileA(msifile4);
3572 }
3573 
3574 static void test_getproperty(void)
3575 {
3576     MSIHANDLE hPackage = 0;
3577     char prop[100];
3578     static CHAR empty[] = "";
3579     DWORD size;
3580     UINT r;
3581 
3582     r = package_from_db(create_package_db(), &hPackage);
3583     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
3584     {
3585         skip("Not enough rights to perform tests\n");
3586         DeleteFileA(msifile);
3587         return;
3588     }
3589     ok( r == ERROR_SUCCESS, "Failed to create package %u\n", r );
3590 
3591     /* set the property */
3592     r = MsiSetPropertyA(hPackage, "Name", "Value");
3593     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3594 
3595     /* retrieve the size, NULL pointer */
3596     size = 0;
3597     r = MsiGetPropertyA(hPackage, "Name", NULL, &size);
3598     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3599     ok( size == 5, "Expected 5, got %d\n", size);
3600 
3601     /* retrieve the size, empty string */
3602     size = 0;
3603     r = MsiGetPropertyA(hPackage, "Name", empty, &size);
3604     ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
3605     ok( size == 5, "Expected 5, got %d\n", size);
3606 
3607     /* don't change size */
3608     r = MsiGetPropertyA(hPackage, "Name", prop, &size);
3609     ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
3610     ok( size == 5, "Expected 5, got %d\n", size);
3611     ok( !lstrcmpA(prop, "Valu"), "Expected Valu, got %s\n", prop);
3612 
3613     /* increase the size by 1 */
3614     size++;
3615     r = MsiGetPropertyA(hPackage, "Name", prop, &size);
3616     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3617     ok( size == 5, "Expected 5, got %d\n", size);
3618     ok( !lstrcmpA(prop, "Value"), "Expected Value, got %s\n", prop);
3619 
3620     r = MsiCloseHandle( hPackage);
3621     ok( r == ERROR_SUCCESS , "Failed to close package\n" );
3622     DeleteFileA(msifile);
3623 }
3624 
3625 static void test_removefiles(void)
3626 {
3627     MSIHANDLE hpkg;
3628     UINT r;
3629     MSIHANDLE hdb;
3630     INSTALLSTATE installed, action;
3631 
3632     hdb = create_package_db();
3633     ok ( hdb, "failed to create package database\n" );
3634 
3635     r = add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'");
3636     ok( r == ERROR_SUCCESS, "cannot add directory: %d\n", r );
3637 
3638     r = create_feature_table( hdb );
3639     ok( r == ERROR_SUCCESS, "cannot create Feature table: %d\n", r );
3640 
3641     r = create_component_table( hdb );
3642     ok( r == ERROR_SUCCESS, "cannot create Component table: %d\n", r );
3643 
3644     r = add_feature_entry( hdb, "'one', '', '', '', 2, 1, '', 0" );
3645     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
3646 
3647     r = add_component_entry( hdb, "'hydrogen', '', 'TARGETDIR', 0, '', 'hydrogen_file'" );
3648     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3649 
3650     r = add_component_entry( hdb, "'helium', '', 'TARGETDIR', 0, '', 'helium_file'" );
3651     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3652 
3653     r = add_component_entry( hdb, "'lithium', '', 'TARGETDIR', 0, '', 'lithium_file'" );
3654     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3655 
3656     r = add_component_entry( hdb, "'beryllium', '', 'TARGETDIR', 0, '', 'beryllium_file'" );
3657     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3658 
3659     r = add_component_entry( hdb, "'boron', '', 'TARGETDIR', 0, '', 'boron_file'" );
3660     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3661 
3662     r = add_component_entry( hdb, "'carbon', '', 'TARGETDIR', 0, '', 'carbon_file'" );
3663     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3664 
3665     r = add_component_entry( hdb, "'oxygen', '', 'TARGETDIR', 0, '0', 'oxygen_file'" );
3666     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
3667 
3668     r = create_feature_components_table( hdb );
3669     ok( r == ERROR_SUCCESS, "cannot create FeatureComponents table: %d\n", r );
3670 
3671     r = add_feature_components_entry( hdb, "'one', 'hydrogen'" );
3672     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3673 
3674     r = add_feature_components_entry( hdb, "'one', 'helium'" );
3675     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3676 
3677     r = add_feature_components_entry( hdb, "'one', 'lithium'" );
3678     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3679 
3680     r = add_feature_components_entry( hdb, "'one', 'beryllium'" );
3681     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3682 
3683     r = add_feature_components_entry( hdb, "'one', 'boron'" );
3684     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3685 
3686     r = add_feature_components_entry( hdb, "'one', 'carbon'" );
3687     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3688 
3689     r = add_feature_components_entry( hdb, "'one', 'oxygen'" );
3690     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
3691 
3692     r = create_file_table( hdb );
3693     ok( r == ERROR_SUCCESS, "cannot create File table: %d\n", r );
3694 
3695     r = add_file_entry( hdb, "'hydrogen_file', 'hydrogen', 'hydrogen.txt', 0, '', '1033', 8192, 1" );
3696     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3697 
3698     r = add_file_entry( hdb, "'helium_file', 'helium', 'helium.txt', 0, '', '1033', 8192, 1" );
3699     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3700 
3701     r = add_file_entry( hdb, "'lithium_file', 'lithium', 'lithium.txt', 0, '', '1033', 8192, 1" );
3702     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3703 
3704     r = add_file_entry( hdb, "'beryllium_file', 'beryllium', 'beryllium.txt', 0, '', '1033', 16384, 1" );
3705     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3706 
3707     r = add_file_entry( hdb, "'boron_file', 'boron', 'boron.txt', 0, '', '1033', 16384, 1" );
3708     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3709 
3710     r = add_file_entry( hdb, "'carbon_file', 'carbon', 'carbon.txt', 0, '', '1033', 16384, 1" );
3711     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3712 
3713     r = add_file_entry( hdb, "'oxygen_file', 'oxygen', 'oxygen.txt', 0, '', '1033', 16384, 1" );
3714     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
3715 
3716     r = create_remove_file_table( hdb );
3717     ok( r == ERROR_SUCCESS, "cannot create Remove File table: %d\n", r);
3718 
3719     r = package_from_db( hdb, &hpkg );
3720     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
3721     {
3722         skip("Not enough rights to perform tests\n");
3723         DeleteFileA(msifile);
3724         return;
3725     }
3726     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3727 
3728     MsiCloseHandle( hdb );
3729 
3730     create_test_file( "hydrogen.txt" );
3731     create_test_file( "helium.txt" );
3732     create_test_file( "lithium.txt" );
3733     create_test_file( "beryllium.txt" );
3734     create_test_file( "boron.txt" );
3735     create_test_file( "carbon.txt" );
3736     create_test_file( "oxygen.txt" );
3737 
3738     r = MsiSetPropertyA( hpkg, "TARGETDIR", CURR_DIR );
3739     ok( r == ERROR_SUCCESS, "set property failed\n");
3740 
3741     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3742 
3743     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3744     ok( r == ERROR_UNKNOWN_COMPONENT, "expected ERROR_UNKNOWN_COMPONENT, got %u\n", r );
3745 
3746     r = MsiDoActionA( hpkg, "CostInitialize");
3747     ok( r == ERROR_SUCCESS, "cost init failed\n");
3748 
3749     r = MsiDoActionA( hpkg, "FileCost");
3750     ok( r == ERROR_SUCCESS, "file cost failed\n");
3751 
3752     installed = action = 0xdeadbeef;
3753     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3754     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3755     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3756     ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3757 
3758     r = MsiDoActionA( hpkg, "CostFinalize");
3759     ok( r == ERROR_SUCCESS, "cost finalize failed\n");
3760 
3761     r = MsiDoActionA( hpkg, "InstallValidate");
3762     ok( r == ERROR_SUCCESS, "install validate failed\n");
3763 
3764     r = MsiSetComponentStateA( hpkg, "hydrogen", INSTALLSTATE_ABSENT );
3765     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3766 
3767     installed = action = 0xdeadbeef;
3768     r = MsiGetComponentStateA( hpkg, "hydrogen", &installed, &action );
3769     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3770     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3771     todo_wine ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3772 
3773     r = MsiSetComponentStateA( hpkg, "helium", INSTALLSTATE_LOCAL );
3774     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3775 
3776     r = MsiSetComponentStateA( hpkg, "lithium", INSTALLSTATE_SOURCE );
3777     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3778 
3779     r = MsiSetComponentStateA( hpkg, "beryllium", INSTALLSTATE_ABSENT );
3780     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3781 
3782     r = MsiSetComponentStateA( hpkg, "boron", INSTALLSTATE_LOCAL );
3783     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3784 
3785     r = MsiSetComponentStateA( hpkg, "carbon", INSTALLSTATE_SOURCE );
3786     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3787 
3788     installed = action = 0xdeadbeef;
3789     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3790     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3791     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3792     ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3793 
3794     r = MsiSetComponentStateA( hpkg, "oxygen", INSTALLSTATE_ABSENT );
3795     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3796 
3797     installed = action = 0xdeadbeef;
3798     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3799     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3800     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3801     ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3802 
3803     r = MsiDoActionA( hpkg, "RemoveFiles");
3804     ok( r == ERROR_SUCCESS, "remove files failed\n");
3805 
3806     installed = action = 0xdeadbeef;
3807     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3808     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3809     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3810     ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3811 
3812     ok(DeleteFileA("hydrogen.txt"), "Expected hydrogen.txt to exist\n");
3813     ok(DeleteFileA("lithium.txt"), "Expected lithium.txt to exist\n");
3814     ok(DeleteFileA("beryllium.txt"), "Expected beryllium.txt to exist\n");
3815     ok(DeleteFileA("carbon.txt"), "Expected carbon.txt to exist\n");
3816     ok(DeleteFileA("helium.txt"), "Expected helium.txt to exist\n");
3817     ok(DeleteFileA("boron.txt"), "Expected boron.txt to exist\n");
3818     ok(DeleteFileA("oxygen.txt"), "Expected oxygen.txt to exist\n");
3819 
3820     MsiCloseHandle( hpkg );
3821     DeleteFileA(msifile);
3822 }
3823 
3824 static void test_appsearch(void)
3825 {
3826     MSIHANDLE hpkg;
3827     UINT r;
3828     MSIHANDLE hdb;
3829     CHAR prop[MAX_PATH];
3830     DWORD size;
3831     HKEY hkey;
3832     const char reg_expand_value[] = "%systemroot%\\system32\\notepad.exe";
3833 
3834     hdb = create_package_db();
3835     ok ( hdb, "failed to create package database\n" );
3836 
3837     r = create_appsearch_table( hdb );
3838     ok( r == ERROR_SUCCESS, "cannot create AppSearch table: %d\n", r );
3839 
3840     r = add_appsearch_entry( hdb, "'WEBBROWSERPROG', 'NewSignature1'" );
3841     ok( r == ERROR_SUCCESS, "cannot add entry: %d\n", r );
3842 
3843     r = add_appsearch_entry( hdb, "'NOTEPAD', 'NewSignature2'" );
3844     ok( r == ERROR_SUCCESS, "cannot add entry: %d\n", r );
3845 
3846     r = add_appsearch_entry( hdb, "'REGEXPANDVAL', 'NewSignature3'" );
3847     ok( r == ERROR_SUCCESS, "cannot add entry: %d\n", r );
3848 
3849     r = create_reglocator_table( hdb );
3850     ok( r == ERROR_SUCCESS, "cannot create RegLocator table: %d\n", r );
3851 
3852     r = add_reglocator_entry( hdb, "NewSignature1", 0, "htmlfile\\shell\\open\\command", "", 1 );
3853     ok( r == ERROR_SUCCESS, "cannot create RegLocator table: %d\n", r );
3854 
3855     r = RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Winetest_msi", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, NULL);
3856     ok( r == ERROR_SUCCESS, "Could not create key: %d.\n", r );
3857     r = RegSetValueExA(hkey, NULL, 0, REG_EXPAND_SZ, (const BYTE*)reg_expand_value, strlen(reg_expand_value) + 1);
3858     ok( r == ERROR_SUCCESS, "Could not set key value: %d.\n", r);
3859     RegCloseKey(hkey);
3860     r = add_reglocator_entry( hdb, "NewSignature3", 1, "Software\\Winetest_msi", "", 1 );
3861     ok( r == ERROR_SUCCESS, "cannot create RegLocator table: %d\n", r );
3862 
3863     r = create_drlocator_table( hdb );
3864     ok( r == ERROR_SUCCESS, "cannot create DrLocator table: %d\n", r );
3865 
3866     r = add_drlocator_entry( hdb, "'NewSignature2', 0, 'c:\\windows\\system32', 0" );
3867     ok( r == ERROR_SUCCESS, "cannot create RegLocator table: %d\n", r );
3868 
3869     r = create_signature_table( hdb );
3870     ok( r == ERROR_SUCCESS, "cannot create Signature table: %d\n", r );
3871 
3872     r = add_signature_entry( hdb, "'NewSignature1', 'FileName', '', '', '', '', '', '', ''" );
3873     ok( r == ERROR_SUCCESS, "cannot add signature: %d\n", r );
3874 
3875     r = add_signature_entry( hdb, "'NewSignature2', 'NOTEPAD.EXE|notepad.exe', '', '', '', '', '', '', ''" );
3876     ok( r == ERROR_SUCCESS, "cannot add signature: %d\n", r );
3877 
3878     r = add_signature_entry( hdb, "'NewSignature3', 'NOTEPAD.EXE|notepad.exe', '', '', '', '', '', '', ''" );
3879     ok( r == ERROR_SUCCESS, "cannot add signature: %d\n", r );
3880 
3881     r = package_from_db( hdb, &hpkg );
3882     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
3883     {
3884         skip("Not enough rights to perform tests\n");
3885         DeleteFileA(msifile);
3886         return;
3887     }
3888     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3889     MsiCloseHandle( hdb );
3890     if (r != ERROR_SUCCESS)
3891         goto done;
3892 
3893     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3894 
3895     r = MsiDoActionA( hpkg, "AppSearch" );
3896     ok( r == ERROR_SUCCESS, "AppSearch failed: %d\n", r);
3897 
3898     size = sizeof(prop);
3899     r = MsiGetPropertyA( hpkg, "WEBBROWSERPROG", prop, &size );
3900     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
3901     ok( lstrlenA(prop) != 0, "Expected non-zero length\n");
3902 
3903     size = sizeof(prop);
3904     r = MsiGetPropertyA( hpkg, "NOTEPAD", prop, &size );
3905     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
3906 
3907     size = sizeof(prop);
3908     r = MsiGetPropertyA( hpkg, "REGEXPANDVAL", prop, &size );
3909     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
3910     ok( lstrlenA(prop) != 0, "Expected non-zero length\n");
3911 
3912 done:
3913     MsiCloseHandle( hpkg );
3914     DeleteFileA(msifile);
3915     RegDeleteKeyA(HKEY_CURRENT_USER, "Software\\Winetest_msi");
3916 }
3917 
3918 static void test_appsearch_complocator(void)
3919 {
3920     MSIHANDLE hpkg, hdb;
3921     char path[MAX_PATH], expected[MAX_PATH], prop[MAX_PATH];
3922     LPSTR usersid;
3923     DWORD size;
3924     UINT r;
3925 
3926     if (!(usersid = get_user_sid()))
3927         return;
3928 
3929     if (is_process_limited())
3930     {
3931         skip("process is limited\n");
3932         return;
3933     }
3934 
3935     create_test_file("FileName1");
3936     create_test_file("FileName4");
3937     set_component_path("FileName1", MSIINSTALLCONTEXT_MACHINE,
3938                        "{A8AE6692-96BA-4198-8399-145D7D1D0D0E}", NULL, FALSE);
3939 
3940     create_test_file("FileName2");
3941     set_component_path("FileName2", MSIINSTALLCONTEXT_USERUNMANAGED,
3942                        "{1D2CE6F3-E81C-4949-AB81-78D7DAD2AF2E}", usersid, FALSE);
3943 
3944     create_test_file("FileName3");
3945     set_component_path("FileName3", MSIINSTALLCONTEXT_USERMANAGED,
3946                        "{19E0B999-85F5-4973-A61B-DBE4D66ECB1D}", usersid, FALSE);
3947 
3948     create_test_file("FileName5");
3949     set_component_path("FileName5", MSIINSTALLCONTEXT_MACHINE,
3950                        "{F0CCA976-27A3-4808-9DDD-1A6FD50A0D5A}", NULL, TRUE);
3951 
3952     create_test_file("FileName6");
3953     set_component_path("FileName6", MSIINSTALLCONTEXT_MACHINE,
3954                        "{C0ECD96F-7898-4410-9667-194BD8C1B648}", NULL, TRUE);
3955 
3956     create_test_file("FileName7");
3957     set_component_path("FileName7", MSIINSTALLCONTEXT_MACHINE,
3958                        "{DB20F535-9C26-4127-9C2B-CC45A8B51DA1}", NULL, FALSE);
3959 
3960     /* dir is FALSE, but we're pretending it's a directory */
3961     set_component_path("IDontExist\\", MSIINSTALLCONTEXT_MACHINE,
3962                        "{91B7359B-07F2-4221-AA8D-DE102BB87A5F}", NULL, FALSE);
3963 
3964     create_file_with_version("FileName8.dll", MAKELONG(2, 1), MAKELONG(4, 3));
3965     set_component_path("FileName8.dll", MSIINSTALLCONTEXT_MACHINE,
3966                        "{4A2E1B5B-4034-4177-833B-8CC35F1B3EF1}", NULL, FALSE);
3967 
3968     create_file_with_version("FileName9.dll", MAKELONG(1, 2), MAKELONG(3, 4));
3969     set_component_path("FileName9.dll", MSIINSTALLCONTEXT_MACHINE,
3970                        "{A204DF48-7346-4635-BA2E-66247DBAC9DF}", NULL, FALSE);
3971 
3972     create_file_with_version("FileName10.dll", MAKELONG(2, 1), MAKELONG(4, 3));
3973     set_component_path("FileName10.dll", MSIINSTALLCONTEXT_MACHINE,
3974                        "{EC30CE73-4CF9-4908-BABD-1ED82E1515FD}", NULL, FALSE);
3975 
3976     hdb = create_package_db();
3977     ok(hdb, "Expected a valid database handle\n");
3978 
3979     r = create_appsearch_table(hdb);
3980     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3981 
3982     r = add_appsearch_entry(hdb, "'SIGPROP1', 'NewSignature1'");
3983     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3984 
3985     r = add_appsearch_entry(hdb, "'SIGPROP2', 'NewSignature2'");
3986     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3987 
3988     r = add_appsearch_entry(hdb, "'SIGPROP3', 'NewSignature3'");
3989     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3990 
3991     r = add_appsearch_entry(hdb, "'SIGPROP4', 'NewSignature4'");
3992     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3993 
3994     r = add_appsearch_entry(hdb, "'SIGPROP5', 'NewSignature5'");
3995     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3996 
3997     r = add_appsearch_entry(hdb, "'SIGPROP6', 'NewSignature6'");
3998     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3999 
4000     r = add_appsearch_entry(hdb, "'SIGPROP7', 'NewSignature7'");
4001     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4002 
4003     r = add_appsearch_entry(hdb, "'SIGPROP8', 'NewSignature8'");
4004     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4005 
4006     r = add_appsearch_entry(hdb, "'SIGPROP9', 'NewSignature9'");
4007     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4008 
4009     r = add_appsearch_entry(hdb, "'SIGPROP10', 'NewSignature10'");
4010     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4011 
4012     r = add_appsearch_entry(hdb, "'SIGPROP11', 'NewSignature11'");
4013     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4014 
4015     r = add_appsearch_entry(hdb, "'SIGPROP12', 'NewSignature12'");
4016     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4017 
4018     r = create_complocator_table(hdb);
4019     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4020 
4021     /* published component, machine, file, signature, misdbLocatorTypeFile */
4022     r = add_complocator_entry(hdb, "'NewSignature1', '{A8AE6692-96BA-4198-8399-145D7D1D0D0E}', 1");
4023     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4024 
4025     /* published component, user-unmanaged, file, signature, misdbLocatorTypeFile */
4026     r = add_complocator_entry(hdb, "'NewSignature2', '{1D2CE6F3-E81C-4949-AB81-78D7DAD2AF2E}', 1");
4027     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4028 
4029     /* published component, user-managed, file, signature, misdbLocatorTypeFile */
4030     r = add_complocator_entry(hdb, "'NewSignature3', '{19E0B999-85F5-4973-A61B-DBE4D66ECB1D}', 1");
4031     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4032 
4033     /* published component, machine, file, signature, misdbLocatorTypeDirectory */
4034     r = add_complocator_entry(hdb, "'NewSignature4', '{A8AE6692-96BA-4198-8399-145D7D1D0D0E}', 0");
4035     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4036 
4037     /* published component, machine, dir, signature, misdbLocatorTypeDirectory */
4038     r = add_complocator_entry(hdb, "'NewSignature5', '{F0CCA976-27A3-4808-9DDD-1A6FD50A0D5A}', 0");
4039     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4040 
4041     /* published component, machine, dir, no signature, misdbLocatorTypeDirectory */
4042     r = add_complocator_entry(hdb, "'NewSignature6', '{C0ECD96F-7898-4410-9667-194BD8C1B648}', 0");
4043     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4044 
4045     /* published component, machine, file, no signature, misdbLocatorTypeFile */
4046     r = add_complocator_entry(hdb, "'NewSignature7', '{DB20F535-9C26-4127-9C2B-CC45A8B51DA1}', 1");
4047     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4048 
4049     /* unpublished component, no signature, misdbLocatorTypeDir */
4050     r = add_complocator_entry(hdb, "'NewSignature8', '{FB671D5B-5083-4048-90E0-481C48D8F3A5}', 0");
4051     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4052 
4053     /* published component, no signature, dir does not exist misdbLocatorTypeDir */
4054     r = add_complocator_entry(hdb, "'NewSignature9', '{91B7359B-07F2-4221-AA8D-DE102BB87A5F}', 0");
4055     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4056 
4057     /* published component, signature w/ ver, misdbLocatorTypeFile */
4058     r = add_complocator_entry(hdb, "'NewSignature10', '{4A2E1B5B-4034-4177-833B-8CC35F1B3EF1}', 1");
4059     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4060 
4061     /* published component, signature w/ ver, ver > max, misdbLocatorTypeFile */
4062     r = add_complocator_entry(hdb, "'NewSignature11', '{A204DF48-7346-4635-BA2E-66247DBAC9DF}', 1");
4063     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4064 
4065     /* published component, signature w/ ver, sig->name ignored, misdbLocatorTypeFile */
4066     r = add_complocator_entry(hdb, "'NewSignature12', '{EC30CE73-4CF9-4908-BABD-1ED82E1515FD}', 1");
4067     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4068 
4069     r = create_signature_table(hdb);
4070     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4071 
4072     r = add_signature_entry(hdb, "'NewSignature1', 'FileName1', '', '', '', '', '', '', ''");
4073     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4074 
4075     r = add_signature_entry(hdb, "'NewSignature2', 'FileName2', '', '', '', '', '', '', ''");
4076     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4077 
4078     r = add_signature_entry(hdb, "'NewSignature3', 'FileName3', '', '', '', '', '', '', ''");
4079     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4080 
4081     r = add_signature_entry(hdb, "'NewSignature4', 'FileName4', '', '', '', '', '', '', ''");
4082     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4083 
4084     r = add_signature_entry(hdb, "'NewSignature5', 'FileName5', '', '', '', '', '', '', ''");
4085     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4086 
4087     r = add_signature_entry(hdb, "'NewSignature10', 'FileName8.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4088     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4089 
4090     r = add_signature_entry(hdb, "'NewSignature11', 'FileName9.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4091     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4092 
4093     r = add_signature_entry(hdb, "'NewSignature12', 'ignored', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4094     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4095 
4096     r = package_from_db(hdb, &hpkg);
4097     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
4098     {
4099         skip("Not enough rights to perform tests\n");
4100         goto error;
4101     }
4102     ok(r == ERROR_SUCCESS, "Expected a valid package handle %u\n", r);
4103 
4104     r = MsiSetPropertyA(hpkg, "SIGPROP8", "october");
4105     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4106 
4107     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4108 
4109     r = MsiDoActionA(hpkg, "AppSearch");
4110     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4111 
4112     strcpy(expected, CURR_DIR);
4113     if (is_root(CURR_DIR)) expected[2] = 0;
4114 
4115     size = MAX_PATH;
4116     sprintf(path, "%s\\FileName1", expected);
4117     r = MsiGetPropertyA(hpkg, "SIGPROP1", prop, &size);
4118     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4119     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4120 
4121     size = MAX_PATH;
4122     sprintf(path, "%s\\FileName2", expected);
4123     r = MsiGetPropertyA(hpkg, "SIGPROP2", prop, &size);
4124     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4125     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4126 
4127     size = MAX_PATH;
4128     sprintf(path, "%s\\FileName3", expected);
4129     r = MsiGetPropertyA(hpkg, "SIGPROP3", prop, &size);
4130     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4131     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4132 
4133     size = MAX_PATH;
4134     sprintf(path, "%s\\FileName4", expected);
4135     r = MsiGetPropertyA(hpkg, "SIGPROP4", prop, &size);
4136     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4137     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4138 
4139     size = MAX_PATH;
4140     sprintf(path, "%s\\FileName5", expected);
4141     r = MsiGetPropertyA(hpkg, "SIGPROP5", prop, &size);
4142     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4143     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4144 
4145     size = MAX_PATH;
4146     sprintf(path, "%s\\", expected);
4147     r = MsiGetPropertyA(hpkg, "SIGPROP6", prop, &size);
4148     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4149     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4150 
4151     size = MAX_PATH;
4152     sprintf(path, "%s\\", expected);
4153     r = MsiGetPropertyA(hpkg, "SIGPROP7", prop, &size);
4154     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4155     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4156 
4157     size = MAX_PATH;
4158     r = MsiGetPropertyA(hpkg, "SIGPROP8", prop, &size);
4159     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4160     ok(!lstrcmpA(prop, "october"), "Expected \"october\", got \"%s\"\n", prop);
4161 
4162     size = MAX_PATH;
4163     r = MsiGetPropertyA(hpkg, "SIGPROP9", prop, &size);
4164     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4165     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4166 
4167     size = MAX_PATH;
4168     sprintf(path, "%s\\FileName8.dll", expected);
4169     r = MsiGetPropertyA(hpkg, "SIGPROP10", prop, &size);
4170     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4171     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4172 
4173     size = MAX_PATH;
4174     r = MsiGetPropertyA(hpkg, "SIGPROP11", prop, &size);
4175     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4176     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4177 
4178     size = MAX_PATH;
4179     sprintf(path, "%s\\FileName10.dll", expected);
4180     r = MsiGetPropertyA(hpkg, "SIGPROP12", prop, &size);
4181     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4182     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4183 
4184     delete_component_path("{A8AE6692-96BA-4198-8399-145D7D1D0D0E}",
4185                           MSIINSTALLCONTEXT_MACHINE, NULL);
4186     delete_component_path("{1D2CE6F3-E81C-4949-AB81-78D7DAD2AF2E}",
4187                           MSIINSTALLCONTEXT_USERUNMANAGED, usersid);
4188     delete_component_path("{19E0B999-85F5-4973-A61B-DBE4D66ECB1D}",
4189                           MSIINSTALLCONTEXT_USERMANAGED, usersid);
4190     delete_component_path("{F0CCA976-27A3-4808-9DDD-1A6FD50A0D5A}",
4191                           MSIINSTALLCONTEXT_MACHINE, NULL);
4192     delete_component_path("{C0ECD96F-7898-4410-9667-194BD8C1B648}",
4193                           MSIINSTALLCONTEXT_MACHINE, NULL);
4194     delete_component_path("{DB20F535-9C26-4127-9C2B-CC45A8B51DA1}",
4195                           MSIINSTALLCONTEXT_MACHINE, NULL);
4196     delete_component_path("{91B7359B-07F2-4221-AA8D-DE102BB87A5F}",
4197                           MSIINSTALLCONTEXT_MACHINE, NULL);
4198     delete_component_path("{4A2E1B5B-4034-4177-833B-8CC35F1B3EF1}",
4199                           MSIINSTALLCONTEXT_MACHINE, NULL);
4200     delete_component_path("{A204DF48-7346-4635-BA2E-66247DBAC9DF}",
4201                           MSIINSTALLCONTEXT_MACHINE, NULL);
4202     delete_component_path("{EC30CE73-4CF9-4908-BABD-1ED82E1515FD}",
4203                           MSIINSTALLCONTEXT_MACHINE, NULL);
4204 
4205     MsiCloseHandle(hpkg);
4206 
4207 error:
4208     DeleteFileA("FileName1");
4209     DeleteFileA("FileName2");
4210     DeleteFileA("FileName3");
4211     DeleteFileA("FileName4");
4212     DeleteFileA("FileName5");
4213     DeleteFileA("FileName6");
4214     DeleteFileA("FileName7");
4215     DeleteFileA("FileName8.dll");
4216     DeleteFileA("FileName9.dll");
4217     DeleteFileA("FileName10.dll");
4218     DeleteFileA(msifile);
4219     LocalFree(usersid);
4220 }
4221 
4222 static void test_appsearch_reglocator(void)
4223 {
4224     MSIHANDLE hpkg, hdb;
4225     char path[MAX_PATH], expected[MAX_PATH], prop[MAX_PATH];
4226     DWORD binary[2], size, val;
4227     BOOL space, version, is_64bit = sizeof(void *) > sizeof(int);
4228     HKEY hklm, classes, hkcu, users;
4229     LPSTR pathdata, pathvar, ptr;
4230     LPCSTR str;
4231     LONG res;
4232     UINT r, type = 0;
4233     SYSTEM_INFO si;
4234 
4235     version = TRUE;
4236     if (!create_file_with_version("test.dll", MAKELONG(2, 1), MAKELONG(4, 3)))
4237         version = FALSE;
4238 
4239     DeleteFileA("test.dll");
4240 
4241     res = RegCreateKeyA(HKEY_CLASSES_ROOT, "Software\\Wine", &classes);
4242     if (res == ERROR_ACCESS_DENIED)
4243     {
4244         skip("Not enough rights to perform tests\n");
4245         return;
4246     }
4247     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4248 
4249     res = RegSetValueExA(classes, "Value1", 0, REG_SZ,
4250                          (const BYTE *)"regszdata", 10);
4251     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4252 
4253     res = RegCreateKeyA(HKEY_CURRENT_USER, "Software\\Wine", &hkcu);
4254     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4255 
4256     res = RegSetValueExA(hkcu, "Value1", 0, REG_SZ,
4257                          (const BYTE *)"regszdata", 10);
4258     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4259 
4260     users = 0;
4261     res = RegCreateKeyA(HKEY_USERS, "S-1-5-18\\Software\\Wine", &users);
4262     ok(res == ERROR_SUCCESS ||
4263        broken(res == ERROR_INVALID_PARAMETER),
4264        "Expected ERROR_SUCCESS, got %d\n", res);
4265 
4266     if (res == ERROR_SUCCESS)
4267     {
4268         res = RegSetValueExA(users, "Value1", 0, REG_SZ,
4269                              (const BYTE *)"regszdata", 10);
4270         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4271     }
4272 
4273     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine", &hklm);
4274     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4275 
4276     res = RegSetValueA(hklm, NULL, REG_SZ, "defvalue", 8);
4277     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4278 
4279     res = RegSetValueExA(hklm, "Value1", 0, REG_SZ,
4280                          (const BYTE *)"regszdata", 10);
4281     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4282 
4283     val = 42;
4284     res = RegSetValueExA(hklm, "Value2", 0, REG_DWORD,
4285                          (const BYTE *)&val, sizeof(DWORD));
4286     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4287 
4288     val = -42;
4289     res = RegSetValueExA(hklm, "Value3", 0, REG_DWORD,
4290                          (const BYTE *)&val, sizeof(DWORD));
4291     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4292 
4293     res = RegSetValueExA(hklm, "Value4", 0, REG_EXPAND_SZ,
4294                          (const BYTE *)"%PATH%", 7);
4295     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4296 
4297     res = RegSetValueExA(hklm, "Value5", 0, REG_EXPAND_SZ,
4298                          (const BYTE *)"my%NOVAR%", 10);
4299     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4300 
4301     res = RegSetValueExA(hklm, "Value6", 0, REG_MULTI_SZ,
4302                          (const BYTE *)"one\0two\0", 9);
4303     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4304 
4305     binary[0] = 0x1234abcd;
4306     binary[1] = 0x567890ef;
4307     res = RegSetValueExA(hklm, "Value7", 0, REG_BINARY,
4308                          (const BYTE *)binary, sizeof(binary));
4309     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4310 
4311     res = RegSetValueExA(hklm, "Value8", 0, REG_SZ,
4312                          (const BYTE *)"#regszdata", 11);
4313     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4314 
4315     strcpy(expected, CURR_DIR);
4316     if (is_root(CURR_DIR)) expected[2] = 0;
4317 
4318     create_test_file("FileName1");
4319     sprintf(path, "%s\\FileName1", expected);
4320     res = RegSetValueExA(hklm, "Value9", 0, REG_SZ,
4321                          (const BYTE *)path, lstrlenA(path) + 1);
4322     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4323 
4324     sprintf(path, "%s\\FileName2", expected);
4325     res = RegSetValueExA(hklm, "Value10", 0, REG_SZ,
4326                          (const BYTE *)path, lstrlenA(path) + 1);
4327     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4328 
4329     lstrcpyA(path, expected);
4330     res = RegSetValueExA(hklm, "Value11", 0, REG_SZ,
4331                          (const BYTE *)path, lstrlenA(path) + 1);
4332     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4333 
4334     res = RegSetValueExA(hklm, "Value12", 0, REG_SZ,
4335                          (const BYTE *)"", 1);
4336     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4337 
4338     create_file_with_version("FileName3.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4339     sprintf(path, "%s\\FileName3.dll", expected);
4340     res = RegSetValueExA(hklm, "Value13", 0, REG_SZ,
4341                          (const BYTE *)path, lstrlenA(path) + 1);
4342     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4343 
4344     create_file_with_version("FileName4.dll", MAKELONG(1, 2), MAKELONG(3, 4));
4345     sprintf(path, "%s\\FileName4.dll", expected);
4346     res = RegSetValueExA(hklm, "Value14", 0, REG_SZ,
4347                          (const BYTE *)path, lstrlenA(path) + 1);
4348     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4349 
4350     create_file_with_version("FileName5.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4351     sprintf(path, "%s\\FileName5.dll", expected);
4352     res = RegSetValueExA(hklm, "Value15", 0, REG_SZ,
4353                          (const BYTE *)path, lstrlenA(path) + 1);
4354     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4355 
4356     sprintf(path, "\"%s\\FileName1\" -option", expected);
4357     res = RegSetValueExA(hklm, "value16", 0, REG_SZ,
4358                          (const BYTE *)path, lstrlenA(path) + 1);
4359     ok( res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", res);
4360 
4361     space = strchr(expected, ' ') != NULL;
4362     sprintf(path, "%s\\FileName1 -option", expected);
4363     res = RegSetValueExA(hklm, "value17", 0, REG_SZ,
4364                          (const BYTE *)path, lstrlenA(path) + 1);
4365     ok( res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", res);
4366 
4367     hdb = create_package_db();
4368     ok(hdb, "Expected a valid database handle\n");
4369 
4370     r = create_appsearch_table(hdb);
4371     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4372 
4373     r = add_appsearch_entry(hdb, "'SIGPROP1', 'NewSignature1'");
4374     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4375 
4376     r = add_appsearch_entry(hdb, "'SIGPROP2', 'NewSignature2'");
4377     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4378 
4379     r = add_appsearch_entry(hdb, "'SIGPROP3', 'NewSignature3'");
4380     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4381 
4382     r = add_appsearch_entry(hdb, "'SIGPROP4', 'NewSignature4'");
4383     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4384 
4385     r = add_appsearch_entry(hdb, "'SIGPROP5', 'NewSignature5'");
4386     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4387 
4388     r = add_appsearch_entry(hdb, "'SIGPROP6', 'NewSignature6'");
4389     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4390 
4391     r = add_appsearch_entry(hdb, "'SIGPROP7', 'NewSignature7'");
4392     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4393 
4394     r = add_appsearch_entry(hdb, "'SIGPROP8', 'NewSignature8'");
4395     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4396 
4397     r = add_appsearch_entry(hdb, "'SIGPROP9', 'NewSignature9'");
4398     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4399 
4400     r = add_appsearch_entry(hdb, "'SIGPROP10', 'NewSignature10'");
4401     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4402 
4403     r = add_appsearch_entry(hdb, "'SIGPROP11', 'NewSignature11'");
4404     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4405 
4406     r = add_appsearch_entry(hdb, "'SIGPROP12', 'NewSignature12'");
4407     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4408 
4409     r = add_appsearch_entry(hdb, "'SIGPROP13', 'NewSignature13'");
4410     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4411 
4412     r = add_appsearch_entry(hdb, "'SIGPROP14', 'NewSignature14'");
4413     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4414 
4415     r = add_appsearch_entry(hdb, "'SIGPROP15', 'NewSignature15'");
4416     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4417 
4418     r = add_appsearch_entry(hdb, "'SIGPROP16', 'NewSignature16'");
4419     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4420 
4421     r = add_appsearch_entry(hdb, "'SIGPROP17', 'NewSignature17'");
4422     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4423 
4424     r = add_appsearch_entry(hdb, "'SIGPROP18', 'NewSignature18'");
4425     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4426 
4427     r = add_appsearch_entry(hdb, "'SIGPROP19', 'NewSignature19'");
4428     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4429 
4430     r = add_appsearch_entry(hdb, "'SIGPROP20', 'NewSignature20'");
4431     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4432 
4433     r = add_appsearch_entry(hdb, "'SIGPROP21', 'NewSignature21'");
4434     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4435 
4436     r = add_appsearch_entry(hdb, "'SIGPROP22', 'NewSignature22'");
4437     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4438 
4439     r = add_appsearch_entry(hdb, "'SIGPROP23', 'NewSignature23'");
4440     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4441 
4442     r = add_appsearch_entry(hdb, "'SIGPROP24', 'NewSignature24'");
4443     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4444 
4445     r = add_appsearch_entry(hdb, "'SIGPROP25', 'NewSignature25'");
4446     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4447 
4448     r = add_appsearch_entry(hdb, "'SIGPROP26', 'NewSignature26'");
4449     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4450 
4451     r = add_appsearch_entry(hdb, "'SIGPROP27', 'NewSignature27'");
4452     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4453 
4454     r = add_appsearch_entry(hdb, "'SIGPROP28', 'NewSignature28'");
4455     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4456 
4457     r = add_appsearch_entry(hdb, "'SIGPROP29', 'NewSignature29'");
4458     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4459 
4460     r = add_appsearch_entry(hdb, "'SIGPROP30', 'NewSignature30'");
4461     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4462 
4463     r = create_reglocator_table(hdb);
4464     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4465 
4466     type = msidbLocatorTypeRawValue;
4467     if (is_64bit)
4468         type |= msidbLocatorType64bit;
4469 
4470     /* HKLM, msidbLocatorTypeRawValue, REG_SZ */
4471     r = add_reglocator_entry(hdb, "NewSignature1", 2, "Software\\Wine", "Value1", type);
4472     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4473 
4474     /* HKLM, msidbLocatorTypeRawValue, positive DWORD */
4475     r = add_reglocator_entry(hdb, "NewSignature2", 2, "Software\\Wine", "Value2", type);
4476     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4477 
4478     /* HKLM, msidbLocatorTypeRawValue, negative DWORD */
4479     r = add_reglocator_entry(hdb, "NewSignature3", 2, "Software\\Wine", "Value3", type);
4480     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4481 
4482     /* HKLM, msidbLocatorTypeRawValue, REG_EXPAND_SZ */
4483     r = add_reglocator_entry(hdb, "NewSignature4", 2, "Software\\Wine", "Value4", type);
4484     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4485 
4486     /* HKLM, msidbLocatorTypeRawValue, REG_EXPAND_SZ */
4487     r = add_reglocator_entry(hdb, "NewSignature5", 2, "Software\\Wine", "Value5", type);
4488     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4489 
4490     /* HKLM, msidbLocatorTypeRawValue, REG_MULTI_SZ */
4491     r = add_reglocator_entry(hdb, "NewSignature6", 2, "Software\\Wine", "Value6", type);
4492     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4493 
4494     /* HKLM, msidbLocatorTypeRawValue, REG_BINARY */
4495     r = add_reglocator_entry(hdb, "NewSignature7", 2, "Software\\Wine", "Value7", type);
4496     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4497 
4498     /* HKLM, msidbLocatorTypeRawValue, REG_SZ first char is # */
4499     r = add_reglocator_entry(hdb, "NewSignature8", 2, "Software\\Wine", "Value8", type);
4500     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4501 
4502     type = msidbLocatorTypeFileName;
4503     if (is_64bit)
4504         type |= msidbLocatorType64bit;
4505 
4506     /* HKLM, msidbLocatorTypeFileName, signature, file exists */
4507     r = add_reglocator_entry(hdb, "NewSignature9", 2, "Software\\Wine", "Value9", type);
4508     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4509 
4510     /* HKLM, msidbLocatorTypeFileName, signature, file does not exist */
4511     r = add_reglocator_entry(hdb, "NewSignature10", 2, "Software\\Wine", "Value10", type);
4512     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4513 
4514     /* HKLM, msidbLocatorTypeFileName, no signature */
4515     r = add_reglocator_entry(hdb, "NewSignature11", 2, "Software\\Wine", "Value9", type);
4516     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4517 
4518     type = msidbLocatorTypeDirectory;
4519     if (is_64bit)
4520         type |= msidbLocatorType64bit;
4521 
4522     /* HKLM, msidbLocatorTypeDirectory, no signature, file exists */
4523     r = add_reglocator_entry(hdb, "NewSignature12", 2, "Software\\Wine", "Value9", type);
4524     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4525 
4526     /* HKLM, msidbLocatorTypeDirectory, no signature, directory exists */
4527     r = add_reglocator_entry(hdb, "NewSignature13", 2, "Software\\Wine", "Value11", type);
4528     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4529 
4530     /* HKLM, msidbLocatorTypeDirectory, signature, file exists */
4531     r = add_reglocator_entry(hdb, "NewSignature14", 2, "Software\\Wine", "Value9", type);
4532     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4533 
4534     type = msidbLocatorTypeRawValue;
4535     if (is_64bit)
4536         type |= msidbLocatorType64bit;
4537 
4538     /* HKCR, msidbLocatorTypeRawValue, REG_SZ */
4539     r = add_reglocator_entry(hdb, "NewSignature15", 0, "Software\\Wine", "Value1", type);
4540     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4541 
4542     /* HKCU, msidbLocatorTypeRawValue, REG_SZ */
4543     r = add_reglocator_entry(hdb, "NewSignature16", 1, "Software\\Wine", "Value1", type);
4544     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4545 
4546     /* HKU, msidbLocatorTypeRawValue, REG_SZ */
4547     r = add_reglocator_entry(hdb, "NewSignature17", 3, "S-1-5-18\\Software\\Wine", "Value1", type);
4548     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4549 
4550     /* HKLM, msidbLocatorTypeRawValue, REG_SZ, NULL Name */
4551     r = add_reglocator_entry(hdb, "NewSignature18", 2, "Software\\Wine", "", type);
4552     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4553 
4554     /* HKLM, msidbLocatorTypeRawValue, REG_SZ, key does not exist */
4555     r = add_reglocator_entry(hdb, "NewSignature19", 2, "Software\\IDontExist", "", type);
4556     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4557 
4558     /* HKLM, msidbLocatorTypeRawValue, REG_SZ, value is empty */
4559     r = add_reglocator_entry(hdb, "NewSignature20", 2, "Software\\Wine", "Value12", type);
4560     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4561 
4562     type = msidbLocatorTypeFileName;
4563     if (is_64bit)
4564         type |= msidbLocatorType64bit;
4565 
4566     /* HKLM, msidbLocatorTypeFileName, signature, file exists w/ version */
4567     r = add_reglocator_entry(hdb, "NewSignature21", 2, "Software\\Wine", "Value13", type);
4568     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4569 
4570     /* HKLM, msidbLocatorTypeFileName, file exists w/ version, version > max */
4571     r = add_reglocator_entry(hdb, "NewSignature22", 2, "Software\\Wine", "Value14", type);
4572     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4573 
4574     /* HKLM, msidbLocatorTypeFileName, file exists w/ version, sig->name ignored */
4575     r = add_reglocator_entry(hdb, "NewSignature23", 2, "Software\\Wine", "Value15", type);
4576     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4577 
4578     /* HKLM, msidbLocatorTypeFileName, no signature, directory exists */
4579     r = add_reglocator_entry(hdb, "NewSignature24", 2, "Software\\Wine", "Value11", type);
4580     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4581 
4582     /* HKLM, msidbLocatorTypeFileName, no signature, file does not exist */
4583     r = add_reglocator_entry(hdb, "NewSignature25", 2, "Software\\Wine", "Value10", type);
4584     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4585 
4586     type = msidbLocatorTypeDirectory;
4587     if (is_64bit)
4588         type |= msidbLocatorType64bit;
4589 
4590     /* HKLM, msidbLocatorTypeDirectory, signature, directory exists */
4591     r = add_reglocator_entry(hdb, "NewSignature26", 2, "Software\\Wine", "Value11", type);
4592     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4593 
4594     /* HKLM, msidbLocatorTypeDirectory, signature, file does not exist */
4595     r = add_reglocator_entry(hdb, "NewSignature27", 2, "Software\\Wine", "Value10", type);
4596     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4597 
4598     /* HKLM, msidbLocatorTypeDirectory, no signature, file does not exist */
4599     r = add_reglocator_entry(hdb, "NewSignature28", 2, "Software\\Wine", "Value10", type);
4600     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4601 
4602     type = msidbLocatorTypeFileName;
4603     if (is_64bit)
4604         type |= msidbLocatorType64bit;
4605 
4606     /* HKLM, msidbLocatorTypeFile, file exists, in quotes */
4607     r = add_reglocator_entry(hdb, "NewSignature29", 2, "Software\\Wine", "Value16", type);
4608     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4609 
4610     /* HKLM, msidbLocatorTypeFile, file exists, no quotes */
4611     r = add_reglocator_entry(hdb, "NewSignature30", 2, "Software\\Wine", "Value17", type);
4612     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4613 
4614     r = create_signature_table(hdb);
4615     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4616 
4617     str = "'NewSignature9', 'FileName1', '', '', '', '', '', '', ''";
4618     r = add_signature_entry(hdb, str);
4619     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4620 
4621     str = "'NewSignature10', 'FileName2', '', '', '', '', '', '', ''";
4622     r = add_signature_entry(hdb, str);
4623     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4624 
4625     str = "'NewSignature14', 'FileName1', '', '', '', '', '', '', ''";
4626     r = add_signature_entry(hdb, str);
4627     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4628 
4629     str = "'NewSignature21', 'FileName3.dll', '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     str = "'NewSignature22', 'FileName4.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''";
4634     r = add_signature_entry(hdb, str);
4635     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4636 
4637     str = "'NewSignature23', 'ignored', '1.1.1.1', '2.1.1.1', '', '', '', '', ''";
4638     r = add_signature_entry(hdb, str);
4639     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4640 
4641     if (!is_root(CURR_DIR))
4642     {
4643         ptr = strrchr(expected, '\\') + 1;
4644         sprintf(path, "'NewSignature26', '%s', '', '', '', '', '', '', ''", ptr);
4645         r = add_signature_entry(hdb, path);
4646         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4647     }
4648     str = "'NewSignature27', 'FileName2', '', '', '', '', '', '', ''";
4649     r = add_signature_entry(hdb, str);
4650     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4651 
4652     str = "'NewSignature29', 'FileName1', '', '', '', '', '', '', ''";
4653     r = add_signature_entry(hdb, str);
4654     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4655 
4656     str = "'NewSignature30', 'FileName1', '', '', '', '', '', '', ''";
4657     r = add_signature_entry(hdb, str);
4658     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4659 
4660     r = package_from_db(hdb, &hpkg);
4661     ok(r == ERROR_SUCCESS, "Expected a valid package handle %u\n", r);
4662 
4663     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4664 
4665     r = MsiDoActionA(hpkg, "AppSearch");
4666     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4667 
4668     size = MAX_PATH;
4669     r = MsiGetPropertyA(hpkg, "SIGPROP1", prop, &size);
4670     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4671     ok(!lstrcmpA(prop, "regszdata"),
4672        "Expected \"regszdata\", got \"%s\"\n", prop);
4673 
4674     size = MAX_PATH;
4675     r = MsiGetPropertyA(hpkg, "SIGPROP2", prop, &size);
4676     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4677     ok(!lstrcmpA(prop, "#42"), "Expected \"#42\", got \"%s\"\n", prop);
4678 
4679     size = MAX_PATH;
4680     r = MsiGetPropertyA(hpkg, "SIGPROP3", prop, &size);
4681     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4682     ok(!lstrcmpA(prop, "#-42"), "Expected \"#-42\", got \"%s\"\n", prop);
4683 
4684     memset(&si, 0, sizeof(si));
4685     if (pGetNativeSystemInfo) pGetNativeSystemInfo(&si);
4686 
4687     if (S(U(si)).wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
4688     {
4689         size = ExpandEnvironmentStringsA("%PATH%", NULL, 0);
4690         pathvar = HeapAlloc(GetProcessHeap(), 0, size);
4691         ExpandEnvironmentStringsA("%PATH%", pathvar, size);
4692 
4693         size = 0;
4694         r = MsiGetPropertyA(hpkg, "SIGPROP4", NULL, &size);
4695         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4696 
4697         pathdata = HeapAlloc(GetProcessHeap(), 0, ++size);
4698         r = MsiGetPropertyA(hpkg, "SIGPROP4", pathdata, &size);
4699         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4700         ok(!lstrcmpA(pathdata, pathvar),
4701             "Expected \"%s\", got \"%s\"\n", pathvar, pathdata);
4702 
4703         HeapFree(GetProcessHeap(), 0, pathvar);
4704         HeapFree(GetProcessHeap(), 0, pathdata);
4705     }
4706 
4707     size = MAX_PATH;
4708     r = MsiGetPropertyA(hpkg, "SIGPROP5", prop, &size);
4709     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4710     ok(!lstrcmpA(prop,
4711        "my%NOVAR%"), "Expected \"my%%NOVAR%%\", got \"%s\"\n", prop);
4712 
4713     size = MAX_PATH;
4714     r = MsiGetPropertyA(hpkg, "SIGPROP6", prop, &size);
4715     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4716     todo_wine
4717     {
4718         ok(!memcmp(prop, "\0one\0two\0\0", 10),
4719            "Expected \"\\0one\\0two\\0\\0\"\n");
4720     }
4721 
4722     size = MAX_PATH;
4723     lstrcpyA(path, "#xCDAB3412EF907856");
4724     r = MsiGetPropertyA(hpkg, "SIGPROP7", prop, &size);
4725     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4726     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4727 
4728     size = MAX_PATH;
4729     r = MsiGetPropertyA(hpkg, "SIGPROP8", prop, &size);
4730     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4731     ok(!lstrcmpA(prop, "##regszdata"),
4732        "Expected \"##regszdata\", got \"%s\"\n", prop);
4733 
4734     size = MAX_PATH;
4735     sprintf(path, "%s\\FileName1", expected);
4736     r = MsiGetPropertyA(hpkg, "SIGPROP9", prop, &size);
4737     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4738     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4739 
4740     size = MAX_PATH;
4741     r = MsiGetPropertyA(hpkg, "SIGPROP10", prop, &size);
4742     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4743     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4744 
4745     size = MAX_PATH;
4746     sprintf(path, "%s\\", expected);
4747     r = MsiGetPropertyA(hpkg, "SIGPROP11", prop, &size);
4748     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4749     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4750 
4751     size = MAX_PATH;
4752     r = MsiGetPropertyA(hpkg, "SIGPROP12", prop, &size);
4753     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4754     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4755 
4756     size = MAX_PATH;
4757     sprintf(path, "%s\\", expected);
4758     r = MsiGetPropertyA(hpkg, "SIGPROP13", prop, &size);
4759     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4760     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4761 
4762     size = MAX_PATH;
4763     r = MsiGetPropertyA(hpkg, "SIGPROP14", prop, &size);
4764     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4765     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4766 
4767     size = MAX_PATH;
4768     r = MsiGetPropertyA(hpkg, "SIGPROP15", prop, &size);
4769     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4770     ok(!lstrcmpA(prop, "regszdata"),
4771        "Expected \"regszdata\", got \"%s\"\n", prop);
4772 
4773     size = MAX_PATH;
4774     r = MsiGetPropertyA(hpkg, "SIGPROP16", 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     if (users)
4780     {
4781         size = MAX_PATH;
4782         r = MsiGetPropertyA(hpkg, "SIGPROP17", prop, &size);
4783         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4784         ok(!lstrcmpA(prop, "regszdata"),
4785            "Expected \"regszdata\", got \"%s\"\n", prop);
4786     }
4787 
4788     size = MAX_PATH;
4789     r = MsiGetPropertyA(hpkg, "SIGPROP18", prop, &size);
4790     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4791     ok(!lstrcmpA(prop, "defvalue"),
4792        "Expected \"defvalue\", got \"%s\"\n", prop);
4793 
4794     size = MAX_PATH;
4795     r = MsiGetPropertyA(hpkg, "SIGPROP19", prop, &size);
4796     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4797     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4798 
4799     size = MAX_PATH;
4800     r = MsiGetPropertyA(hpkg, "SIGPROP20", prop, &size);
4801     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4802     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4803 
4804     if (version)
4805     {
4806         size = MAX_PATH;
4807         sprintf(path, "%s\\FileName3.dll", expected);
4808         r = MsiGetPropertyA(hpkg, "SIGPROP21", prop, &size);
4809         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4810         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4811 
4812         size = MAX_PATH;
4813         r = MsiGetPropertyA(hpkg, "SIGPROP22", prop, &size);
4814         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4815         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4816 
4817         size = MAX_PATH;
4818         sprintf(path, "%s\\FileName5.dll", expected);
4819         r = MsiGetPropertyA(hpkg, "SIGPROP23", prop, &size);
4820         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4821         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4822     }
4823 
4824     if (!is_root(CURR_DIR))
4825     {
4826         size = MAX_PATH;
4827         lstrcpyA(path, expected);
4828         ptr = strrchr(path, '\\') + 1;
4829         *ptr = '\0';
4830         r = MsiGetPropertyA(hpkg, "SIGPROP24", prop, &size);
4831         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4832         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4833     }
4834     size = MAX_PATH;
4835     sprintf(path, "%s\\", expected);
4836     r = MsiGetPropertyA(hpkg, "SIGPROP25", prop, &size);
4837     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4838     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4839 
4840     size = MAX_PATH;
4841     r = MsiGetPropertyA(hpkg, "SIGPROP26", prop, &size);
4842     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4843     if (is_root(CURR_DIR))
4844         ok(!lstrcmpA(prop, CURR_DIR), "Expected \"%s\", got \"%s\"\n", CURR_DIR, prop);
4845     else
4846         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4847 
4848     size = MAX_PATH;
4849     r = MsiGetPropertyA(hpkg, "SIGPROP27", prop, &size);
4850     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4851     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4852 
4853     size = MAX_PATH;
4854     r = MsiGetPropertyA(hpkg, "SIGPROP28", prop, &size);
4855     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4856     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4857 
4858     size = MAX_PATH;
4859     sprintf(path, "%s\\FileName1", expected);
4860     r = MsiGetPropertyA(hpkg, "SIGPROP29", prop, &size);
4861     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4862     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4863 
4864     size = MAX_PATH;
4865     sprintf(path, "%s\\FileName1", expected);
4866     r = MsiGetPropertyA(hpkg, "SIGPROP30", prop, &size);
4867     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4868     if (space)
4869         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4870     else
4871         todo_wine ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4872 
4873     RegSetValueA(hklm, NULL, REG_SZ, "", 0);
4874     RegDeleteValueA(hklm, "Value1");
4875     RegDeleteValueA(hklm, "Value2");
4876     RegDeleteValueA(hklm, "Value3");
4877     RegDeleteValueA(hklm, "Value4");
4878     RegDeleteValueA(hklm, "Value5");
4879     RegDeleteValueA(hklm, "Value6");
4880     RegDeleteValueA(hklm, "Value7");
4881     RegDeleteValueA(hklm, "Value8");
4882     RegDeleteValueA(hklm, "Value9");
4883     RegDeleteValueA(hklm, "Value10");
4884     RegDeleteValueA(hklm, "Value11");
4885     RegDeleteValueA(hklm, "Value12");
4886     RegDeleteValueA(hklm, "Value13");
4887     RegDeleteValueA(hklm, "Value14");
4888     RegDeleteValueA(hklm, "Value15");
4889     RegDeleteValueA(hklm, "Value16");
4890     RegDeleteValueA(hklm, "Value17");
4891     RegDeleteKeyA(hklm, "");
4892     RegCloseKey(hklm);
4893 
4894     RegDeleteValueA(classes, "Value1");
4895     RegDeleteKeyA(classes, "");
4896     RegCloseKey(classes);
4897 
4898     RegDeleteValueA(hkcu, "Value1");
4899     RegDeleteKeyA(hkcu, "");
4900     RegCloseKey(hkcu);
4901 
4902     RegDeleteValueA(users, "Value1");
4903     RegDeleteKeyA(users, "");
4904     RegCloseKey(users);
4905 
4906     DeleteFileA("FileName1");
4907     DeleteFileA("FileName3.dll");
4908     DeleteFileA("FileName4.dll");
4909     DeleteFileA("FileName5.dll");
4910     MsiCloseHandle(hpkg);
4911     DeleteFileA(msifile);
4912 }
4913 
4914 static void delete_win_ini(LPCSTR file)
4915 {
4916     CHAR path[MAX_PATH];
4917 
4918     GetWindowsDirectoryA(path, MAX_PATH);
4919     lstrcatA(path, "\\");
4920     lstrcatA(path, file);
4921 
4922     DeleteFileA(path);
4923 }
4924 
4925 static void test_appsearch_inilocator(void)
4926 {
4927     MSIHANDLE hpkg, hdb;
4928     char path[MAX_PATH], expected[MAX_PATH], prop[MAX_PATH];
4929     BOOL version;
4930     LPCSTR str;
4931     LPSTR ptr;
4932     DWORD size;
4933     UINT r;
4934 
4935     version = TRUE;
4936     if (!create_file_with_version("test.dll", MAKELONG(2, 1), MAKELONG(4, 3)))
4937         version = FALSE;
4938 
4939     DeleteFileA("test.dll");
4940 
4941     WritePrivateProfileStringA("Section", "Key", "keydata,field2", "IniFile.ini");
4942 
4943     strcpy(expected, CURR_DIR);
4944     if (is_root(CURR_DIR)) expected[2] = 0;
4945 
4946     create_test_file("FileName1");
4947     sprintf(path, "%s\\FileName1", expected);
4948     WritePrivateProfileStringA("Section", "Key2", path, "IniFile.ini");
4949 
4950     WritePrivateProfileStringA("Section", "Key3", expected, "IniFile.ini");
4951 
4952     sprintf(path, "%s\\IDontExist", expected);
4953     WritePrivateProfileStringA("Section", "Key4", path, "IniFile.ini");
4954 
4955     create_file_with_version("FileName2.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4956     sprintf(path, "%s\\FileName2.dll", expected);
4957     WritePrivateProfileStringA("Section", "Key5", path, "IniFile.ini");
4958 
4959     create_file_with_version("FileName3.dll", MAKELONG(1, 2), MAKELONG(3, 4));
4960     sprintf(path, "%s\\FileName3.dll", expected);
4961     WritePrivateProfileStringA("Section", "Key6", path, "IniFile.ini");
4962 
4963     create_file_with_version("FileName4.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4964     sprintf(path, "%s\\FileName4.dll", expected);
4965     WritePrivateProfileStringA("Section", "Key7", path, "IniFile.ini");
4966 
4967     hdb = create_package_db();
4968     ok(hdb, "Expected a valid database handle\n");
4969 
4970     r = create_appsearch_table(hdb);
4971     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4972 
4973     r = add_appsearch_entry(hdb, "'SIGPROP1', 'NewSignature1'");
4974     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4975 
4976     r = add_appsearch_entry(hdb, "'SIGPROP2', 'NewSignature2'");
4977     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4978 
4979     r = add_appsearch_entry(hdb, "'SIGPROP3', 'NewSignature3'");
4980     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4981 
4982     r = add_appsearch_entry(hdb, "'SIGPROP4', 'NewSignature4'");
4983     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4984 
4985     r = add_appsearch_entry(hdb, "'SIGPROP5', 'NewSignature5'");
4986     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4987 
4988     r = add_appsearch_entry(hdb, "'SIGPROP6', 'NewSignature6'");
4989     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4990 
4991     r = add_appsearch_entry(hdb, "'SIGPROP7', 'NewSignature7'");
4992     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4993 
4994     r = add_appsearch_entry(hdb, "'SIGPROP8', 'NewSignature8'");
4995     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4996 
4997     r = add_appsearch_entry(hdb, "'SIGPROP9', 'NewSignature9'");
4998     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4999 
5000     r = add_appsearch_entry(hdb, "'SIGPROP10', 'NewSignature10'");
5001     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5002 
5003     r = add_appsearch_entry(hdb, "'SIGPROP11', 'NewSignature11'");
5004     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5005 
5006     r = add_appsearch_entry(hdb, "'SIGPROP12', 'NewSignature12'");
5007     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5008 
5009     r = create_inilocator_table(hdb);
5010     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5011 
5012     /* msidbLocatorTypeRawValue, field 1 */
5013     str = "'NewSignature1', 'IniFile.ini', 'Section', 'Key', 1, 2";
5014     r = add_inilocator_entry(hdb, str);
5015     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5016 
5017     /* msidbLocatorTypeRawValue, field 2 */
5018     str = "'NewSignature2', 'IniFile.ini', 'Section', 'Key', 2, 2";
5019     r = add_inilocator_entry(hdb, str);
5020     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5021 
5022     /* msidbLocatorTypeRawValue, entire field */
5023     str = "'NewSignature3', 'IniFile.ini', 'Section', 'Key', 0, 2";
5024     r = add_inilocator_entry(hdb, str);
5025     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5026 
5027     /* msidbLocatorTypeFile */
5028     str = "'NewSignature4', 'IniFile.ini', 'Section', 'Key2', 1, 1";
5029     r = add_inilocator_entry(hdb, str);
5030     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5031 
5032     /* msidbLocatorTypeDirectory, file */
5033     str = "'NewSignature5', 'IniFile.ini', 'Section', 'Key2', 1, 0";
5034     r = add_inilocator_entry(hdb, str);
5035     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5036 
5037     /* msidbLocatorTypeDirectory, directory */
5038     str = "'NewSignature6', 'IniFile.ini', 'Section', 'Key3', 1, 0";
5039     r = add_inilocator_entry(hdb, str);
5040     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5041 
5042     /* msidbLocatorTypeFile, file, no signature */
5043     str = "'NewSignature7', 'IniFile.ini', 'Section', 'Key2', 1, 1";
5044     r = add_inilocator_entry(hdb, str);
5045     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5046 
5047     /* msidbLocatorTypeFile, dir, no signature */
5048     str = "'NewSignature8', 'IniFile.ini', 'Section', 'Key3', 1, 1";
5049     r = add_inilocator_entry(hdb, str);
5050     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5051 
5052     /* msidbLocatorTypeFile, file does not exist */
5053     str = "'NewSignature9', 'IniFile.ini', 'Section', 'Key4', 1, 1";
5054     r = add_inilocator_entry(hdb, str);
5055     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5056 
5057     /* msidbLocatorTypeFile, signature with version */
5058     str = "'NewSignature10', 'IniFile.ini', 'Section', 'Key5', 1, 1";
5059     r = add_inilocator_entry(hdb, str);
5060     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5061 
5062     /* msidbLocatorTypeFile, signature with version, ver > max */
5063     str = "'NewSignature11', 'IniFile.ini', 'Section', 'Key6', 1, 1";
5064     r = add_inilocator_entry(hdb, str);
5065     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5066 
5067     /* msidbLocatorTypeFile, signature with version, sig->name ignored */
5068     str = "'NewSignature12', 'IniFile.ini', 'Section', 'Key7', 1, 1";
5069     r = add_inilocator_entry(hdb, str);
5070     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5071 
5072     r = create_signature_table(hdb);
5073     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5074 
5075     r = add_signature_entry(hdb, "'NewSignature4', 'FileName1', '', '', '', '', '', '', ''");
5076     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5077 
5078     r = add_signature_entry(hdb, "'NewSignature9', 'IDontExist', '', '', '', '', '', '', ''");
5079     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5080 
5081     r = add_signature_entry(hdb, "'NewSignature10', 'FileName2.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
5082     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5083 
5084     r = add_signature_entry(hdb, "'NewSignature11', 'FileName3.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
5085     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5086 
5087     r = add_signature_entry(hdb, "'NewSignature12', 'ignored', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
5088     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5089 
5090     r = package_from_db(hdb, &hpkg);
5091     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5092     {
5093         skip("Not enough rights to perform tests\n");
5094         goto error;
5095     }
5096     ok(r == ERROR_SUCCESS, "Expected a valid package handle %u\n", r);
5097 
5098     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5099 
5100     r = MsiDoActionA(hpkg, "AppSearch");
5101     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5102 
5103     size = MAX_PATH;
5104     r = MsiGetPropertyA(hpkg, "SIGPROP1", prop, &size);
5105     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5106     ok(!lstrcmpA(prop, "keydata"), "Expected \"keydata\", got \"%s\"\n", prop);
5107 
5108     size = MAX_PATH;
5109     r = MsiGetPropertyA(hpkg, "SIGPROP2", prop, &size);
5110     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5111     ok(!lstrcmpA(prop, "field2"), "Expected \"field2\", got \"%s\"\n", prop);
5112 
5113     size = MAX_PATH;
5114     r = MsiGetPropertyA(hpkg, "SIGPROP3", prop, &size);
5115     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5116     ok(!lstrcmpA(prop, "keydata,field2"),
5117        "Expected \"keydata,field2\", got \"%s\"\n", prop);
5118 
5119     size = MAX_PATH;
5120     sprintf(path, "%s\\FileName1", expected);
5121     r = MsiGetPropertyA(hpkg, "SIGPROP4", prop, &size);
5122     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5123     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5124 
5125     size = MAX_PATH;
5126     r = MsiGetPropertyA(hpkg, "SIGPROP5", prop, &size);
5127     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5128     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5129 
5130     size = MAX_PATH;
5131     sprintf(path, "%s\\", expected);
5132     r = MsiGetPropertyA(hpkg, "SIGPROP6", prop, &size);
5133     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5134     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5135 
5136     size = MAX_PATH;
5137     sprintf(path, "%s\\", expected);
5138     r = MsiGetPropertyA(hpkg, "SIGPROP7", prop, &size);
5139     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5140     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5141 
5142     if (!is_root(CURR_DIR))
5143     {
5144         size = MAX_PATH;
5145         lstrcpyA(path, expected);
5146         ptr = strrchr(path, '\\');
5147         *(ptr + 1) = 0;
5148         r = MsiGetPropertyA(hpkg, "SIGPROP8", prop, &size);
5149         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5150         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5151     }
5152     size = MAX_PATH;
5153     r = MsiGetPropertyA(hpkg, "SIGPROP9", prop, &size);
5154     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5155     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5156 
5157     if (version)
5158     {
5159         size = MAX_PATH;
5160         sprintf(path, "%s\\FileName2.dll", expected);
5161         r = MsiGetPropertyA(hpkg, "SIGPROP10", prop, &size);
5162         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5163         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5164 
5165         size = MAX_PATH;
5166         r = MsiGetPropertyA(hpkg, "SIGPROP11", prop, &size);
5167         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5168         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5169 
5170         size = MAX_PATH;
5171         sprintf(path, "%s\\FileName4.dll", expected);
5172         r = MsiGetPropertyA(hpkg, "SIGPROP12", prop, &size);
5173         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5174         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5175     }
5176 
5177     MsiCloseHandle(hpkg);
5178 
5179 error:
5180     delete_win_ini("IniFile.ini");
5181     DeleteFileA("FileName1");
5182     DeleteFileA("FileName2.dll");
5183     DeleteFileA("FileName3.dll");
5184     DeleteFileA("FileName4.dll");
5185     DeleteFileA(msifile);
5186 }
5187 
5188 /*
5189  * MSI AppSearch action on DrLocator table always returns absolute paths.
5190  * If a relative path was set, it returns the first absolute path that
5191  * matches or an empty string if it didn't find anything.
5192  * This helper function replicates this behaviour.
5193  */
5194 static void search_absolute_directory(LPSTR absolute, LPCSTR relative)
5195 {
5196     int i, size;
5197     DWORD attr, drives;
5198 
5199     size = lstrlenA(relative);
5200     drives = GetLogicalDrives();
5201     lstrcpyA(absolute, "A:\\");
5202     for (i = 0; i < 26; absolute[0] = '\0', i++)
5203     {
5204         if (!(drives & (1 << i)))
5205             continue;
5206 
5207         absolute[0] = 'A' + i;
5208         if (GetDriveTypeA(absolute) != DRIVE_FIXED)
5209             continue;
5210 
5211         lstrcpynA(absolute + 3, relative, size + 1);
5212         attr = GetFileAttributesA(absolute);
5213         if (attr != INVALID_FILE_ATTRIBUTES &&
5214             (attr & FILE_ATTRIBUTE_DIRECTORY))
5215         {
5216             if (absolute[3 + size - 1] != '\\')
5217                 lstrcatA(absolute, "\\");
5218             break;
5219         }
5220         absolute[3] = '\0';
5221     }
5222 }
5223 
5224 static void test_appsearch_drlocator(void)
5225 {
5226     MSIHANDLE hpkg, hdb;
5227     char path[MAX_PATH], expected[MAX_PATH], prop[MAX_PATH];
5228     BOOL version;
5229     LPCSTR str;
5230     DWORD size;
5231     UINT r;
5232 
5233     version = TRUE;
5234     if (!create_file_with_version("test.dll", MAKELONG(2, 1), MAKELONG(4, 3)))
5235         version = FALSE;
5236 
5237     DeleteFileA("test.dll");
5238 
5239     create_test_file("FileName1");
5240     CreateDirectoryA("one", NULL);
5241     CreateDirectoryA("one\\two", NULL);
5242     CreateDirectoryA("one\\two\\three", NULL);
5243     create_test_file("one\\two\\three\\FileName2");
5244     CreateDirectoryA("another", NULL);
5245     create_file_with_version("FileName3.dll", MAKELONG(2, 1), MAKELONG(4, 3));
5246     create_file_with_version("FileName4.dll", MAKELONG(1, 2), MAKELONG(3, 4));
5247     create_file_with_version("FileName5.dll", MAKELONG(2, 1), MAKELONG(4, 3));
5248 
5249     hdb = create_package_db();
5250     ok(hdb, "Expected a valid database handle\n");
5251 
5252     r = create_appsearch_table(hdb);
5253     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5254 
5255     r = add_appsearch_entry(hdb, "'SIGPROP1', 'NewSignature1'");
5256     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5257 
5258     r = add_appsearch_entry(hdb, "'SIGPROP2', 'NewSignature2'");
5259     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5260 
5261     r = add_appsearch_entry(hdb, "'SIGPROP3', 'NewSignature3'");
5262     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5263 
5264     r = add_appsearch_entry(hdb, "'SIGPROP4', 'NewSignature4'");
5265     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5266 
5267     r = add_appsearch_entry(hdb, "'SIGPROP5', 'NewSignature5'");
5268     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5269 
5270     r = add_appsearch_entry(hdb, "'SIGPROP6', 'NewSignature6'");
5271     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5272 
5273     r = add_appsearch_entry(hdb, "'SIGPROP7', 'NewSignature7'");
5274     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5275 
5276     r = add_appsearch_entry(hdb, "'SIGPROP8', 'NewSignature8'");
5277     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5278 
5279     r = add_appsearch_entry(hdb, "'SIGPROP9', 'NewSignature9'");
5280     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5281 
5282     r = add_appsearch_entry(hdb, "'SIGPROP10', 'NewSignature10'");
5283     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5284 
5285     r = add_appsearch_entry(hdb, "'SIGPROP11', 'NewSignature11'");
5286     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5287 
5288     r = add_appsearch_entry(hdb, "'SIGPROP13', 'NewSignature13'");
5289     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5290 
5291     r = create_drlocator_table(hdb);
5292     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5293 
5294     strcpy(expected, CURR_DIR);
5295     if (is_root(CURR_DIR)) expected[2] = 0;
5296 
5297     /* no parent, full path, depth 0, signature */
5298     sprintf(path, "'NewSignature1', '', '%s', 0", expected);
5299     r = add_drlocator_entry(hdb, path);
5300     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5301 
5302     /* no parent, full path, depth 0, no signature */
5303     sprintf(path, "'NewSignature2', '', '%s', 0", expected);
5304     r = add_drlocator_entry(hdb, path);
5305     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5306 
5307     /* no parent, relative path, depth 0, no signature */
5308     sprintf(path, "'NewSignature3', '', '%s', 0", expected + 3);
5309     r = add_drlocator_entry(hdb, path);
5310     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5311 
5312     /* no parent, full path, depth 2, signature */
5313     sprintf(path, "'NewSignature4', '', '%s', 2", expected);
5314     r = add_drlocator_entry(hdb, path);
5315     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5316 
5317     /* no parent, full path, depth 3, signature */
5318     sprintf(path, "'NewSignature5', '', '%s', 3", expected);
5319     r = add_drlocator_entry(hdb, path);
5320     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5321 
5322     /* no parent, full path, depth 1, signature is dir */
5323     sprintf(path, "'NewSignature6', '', '%s', 1", expected);
5324     r = add_drlocator_entry(hdb, path);
5325     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5326 
5327     /* parent is in DrLocator, relative path, depth 0, signature */
5328     sprintf(path, "'NewSignature7', 'NewSignature1', 'one\\two\\three', 1");
5329     r = add_drlocator_entry(hdb, path);
5330     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5331 
5332     /* no parent, full path, depth 0, signature w/ version */
5333     sprintf(path, "'NewSignature8', '', '%s', 0", expected);
5334     r = add_drlocator_entry(hdb, path);
5335     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5336 
5337     /* no parent, full path, depth 0, signature w/ version, ver > max */
5338     sprintf(path, "'NewSignature9', '', '%s', 0", expected);
5339     r = add_drlocator_entry(hdb, path);
5340     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5341 
5342     /* no parent, full path, depth 0, signature w/ version, sig->name not ignored */
5343     sprintf(path, "'NewSignature10', '', '%s', 0", expected);
5344     r = add_drlocator_entry(hdb, path);
5345     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5346 
5347     /* no parent, relative empty path, depth 0, no signature */
5348     sprintf(path, "'NewSignature11', '', '', 0");
5349     r = add_drlocator_entry(hdb, path);
5350     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5351 
5352     r = create_reglocator_table(hdb);
5353     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5354 
5355     /* parent */
5356     r = add_reglocator_entry(hdb, "NewSignature12", 2, "htmlfile\\shell\\open\\nonexistent", "", 1);
5357     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5358 
5359     /* parent is in RegLocator, no path, depth 0, no signature */
5360     sprintf(path, "'NewSignature13', 'NewSignature12', '', 0");
5361     r = add_drlocator_entry(hdb, path);
5362     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5363 
5364     r = create_signature_table(hdb);
5365     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5366 
5367     str = "'NewSignature1', 'FileName1', '', '', '', '', '', '', ''";
5368     r = add_signature_entry(hdb, str);
5369     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5370 
5371     str = "'NewSignature4', 'FileName2', '', '', '', '', '', '', ''";
5372     r = add_signature_entry(hdb, str);
5373     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5374 
5375     str = "'NewSignature5', 'FileName2', '', '', '', '', '', '', ''";
5376     r = add_signature_entry(hdb, str);
5377     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5378 
5379     str = "'NewSignature6', 'another', '', '', '', '', '', '', ''";
5380     r = add_signature_entry(hdb, str);
5381     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5382 
5383     str = "'NewSignature7', 'FileName2', '', '', '', '', '', '', ''";
5384     r = add_signature_entry(hdb, str);
5385     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5386 
5387     str = "'NewSignature8', 'FileName3.dll', '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     str = "'NewSignature9', 'FileName4.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''";
5392     r = add_signature_entry(hdb, str);
5393     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5394 
5395     str = "'NewSignature10', 'necessary', '1.1.1.1', '2.1.1.1', '', '', '', '', ''";
5396     r = add_signature_entry(hdb, str);
5397     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5398 
5399     r = package_from_db(hdb, &hpkg);
5400     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5401     {
5402         skip("Not enough rights to perform tests\n");
5403         goto error;
5404     }
5405     ok(r == ERROR_SUCCESS, "Expected a valid package handle %u\n", r);
5406 
5407     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5408 
5409     r = MsiDoActionA(hpkg, "AppSearch");
5410     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5411 
5412     size = MAX_PATH;
5413     sprintf(path, "%s\\FileName1", expected);
5414     r = MsiGetPropertyA(hpkg, "SIGPROP1", prop, &size);
5415     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5416     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5417 
5418     size = MAX_PATH;
5419     sprintf(path, "%s\\", expected);
5420     r = MsiGetPropertyA(hpkg, "SIGPROP2", prop, &size);
5421     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5422     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5423 
5424     size = MAX_PATH;
5425     search_absolute_directory(path, expected + 3);
5426     r = MsiGetPropertyA(hpkg, "SIGPROP3", prop, &size);
5427     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5428     ok(!lstrcmpiA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5429 
5430     size = MAX_PATH;
5431     r = MsiGetPropertyA(hpkg, "SIGPROP4", prop, &size);
5432     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5433     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5434 
5435     size = MAX_PATH;
5436     sprintf(path, "%s\\one\\two\\three\\FileName2", expected);
5437     r = MsiGetPropertyA(hpkg, "SIGPROP5", prop, &size);
5438     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5439     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5440 
5441     size = MAX_PATH;
5442     r = MsiGetPropertyA(hpkg, "SIGPROP6", prop, &size);
5443     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5444     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5445 
5446     size = MAX_PATH;
5447     sprintf(path, "%s\\one\\two\\three\\FileName2", expected);
5448     r = MsiGetPropertyA(hpkg, "SIGPROP7", 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     if (version)
5453     {
5454         size = MAX_PATH;
5455         sprintf(path, "%s\\FileName3.dll", expected);
5456         r = MsiGetPropertyA(hpkg, "SIGPROP8", prop, &size);
5457         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5458         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5459 
5460         size = MAX_PATH;
5461         r = MsiGetPropertyA(hpkg, "SIGPROP9", prop, &size);
5462         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5463         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5464 
5465         size = MAX_PATH;
5466         r = MsiGetPropertyA(hpkg, "SIGPROP10", prop, &size);
5467         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5468         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5469     }
5470 
5471     size = MAX_PATH;
5472     search_absolute_directory(path, "");
5473     r = MsiGetPropertyA(hpkg, "SIGPROP11", prop, &size);
5474     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5475     ok(!lstrcmpiA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5476 
5477     size = MAX_PATH;
5478     strcpy(path, "c:\\");
5479     r = MsiGetPropertyA(hpkg, "SIGPROP13", prop, &size);
5480     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5481     ok(!prop[0], "Expected \"\", got \"%s\"\n", prop);
5482 
5483     MsiCloseHandle(hpkg);
5484 
5485 error:
5486     DeleteFileA("FileName1");
5487     DeleteFileA("FileName3.dll");
5488     DeleteFileA("FileName4.dll");
5489     DeleteFileA("FileName5.dll");
5490     DeleteFileA("one\\two\\three\\FileName2");
5491     RemoveDirectoryA("one\\two\\three");
5492     RemoveDirectoryA("one\\two");
5493     RemoveDirectoryA("one");
5494     RemoveDirectoryA("another");
5495     DeleteFileA(msifile);
5496 }
5497 
5498 static void test_featureparents(void)
5499 {
5500     MSIHANDLE hpkg;
5501     UINT r;
5502     MSIHANDLE hdb;
5503 
5504     hdb = create_package_db();
5505     ok ( hdb, "failed to create package database\n" );
5506 
5507     r = add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'");
5508     ok( r == ERROR_SUCCESS, "cannot add directory: %d\n", r );
5509 
5510     r = create_feature_table( hdb );
5511     ok( r == ERROR_SUCCESS, "cannot create Feature table: %d\n", r );
5512 
5513     r = create_component_table( hdb );
5514     ok( r == ERROR_SUCCESS, "cannot create Component table: %d\n", r );
5515 
5516     r = create_feature_components_table( hdb );
5517     ok( r == ERROR_SUCCESS, "cannot create FeatureComponents table: %d\n", r );
5518 
5519     r = create_file_table( hdb );
5520     ok( r == ERROR_SUCCESS, "cannot create File table: %d\n", r );
5521 
5522     /* msidbFeatureAttributesFavorLocal */
5523     r = add_feature_entry( hdb, "'zodiac', '', '', '', 2, 1, '', 0" );
5524     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
5525 
5526     /* msidbFeatureAttributesFavorSource */
5527     r = add_feature_entry( hdb, "'perseus', '', '', '', 2, 1, '', 1" );
5528     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
5529 
5530     /* msidbFeatureAttributesFavorLocal */
5531     r = add_feature_entry( hdb, "'orion', '', '', '', 2, 1, '', 0" );
5532     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
5533 
5534     /* msidbFeatureAttributesUIDisallowAbsent */
5535     r = add_feature_entry( hdb, "'lyra', '', '', '', 2, 1, '', 16" );
5536     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
5537 
5538     /* disabled because of install level */
5539     r = add_feature_entry( hdb, "'waters', '', '', '', 15, 101, '', 9" );
5540     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
5541 
5542     /* child feature of disabled feature */
5543     r = add_feature_entry( hdb, "'bayer', 'waters', '', '', 14, 1, '', 9" );
5544     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
5545 
5546     /* component of disabled feature (install level) */
5547     r = add_component_entry( hdb, "'delphinus', '', 'TARGETDIR', 0, '', 'delphinus_file'" );
5548     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
5549 
5550     /* component of disabled child feature (install level) */
5551     r = add_component_entry( hdb, "'hydrus', '', 'TARGETDIR', 0, '', 'hydrus_file'" );
5552     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
5553 
5554     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesLocalOnly */
5555     r = add_component_entry( hdb, "'leo', '', 'TARGETDIR', 0, '', 'leo_file'" );
5556     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
5557 
5558     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSourceOnly */
5559     r = add_component_entry( hdb, "'virgo', '', 'TARGETDIR', 1, '', 'virgo_file'" );
5560     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
5561 
5562     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesOptional */
5563     r = add_component_entry( hdb, "'libra', '', 'TARGETDIR', 2, '', 'libra_file'" );
5564     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
5565 
5566     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesLocalOnly */
5567     r = add_component_entry( hdb, "'cassiopeia', '', 'TARGETDIR', 0, '', 'cassiopeia_file'" );
5568     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
5569 
5570     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSourceOnly */
5571     r = add_component_entry( hdb, "'cepheus', '', 'TARGETDIR', 1, '', 'cepheus_file'" );
5572     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
5573 
5574     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesOptional */
5575     r = add_component_entry( hdb, "'andromeda', '', 'TARGETDIR', 2, '', 'andromeda_file'" );
5576     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
5577 
5578     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesLocalOnly */
5579     r = add_component_entry( hdb, "'canis', '', 'TARGETDIR', 0, '', 'canis_file'" );
5580     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
5581 
5582     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSourceOnly */
5583     r = add_component_entry( hdb, "'monoceros', '', 'TARGETDIR', 1, '', 'monoceros_file'" );
5584     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
5585 
5586     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesOptional */
5587     r = add_component_entry( hdb, "'lepus', '', 'TARGETDIR', 2, '', 'lepus_file'" );
5588     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
5589 
5590     r = add_feature_components_entry( hdb, "'zodiac', 'leo'" );
5591     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
5592 
5593     r = add_feature_components_entry( hdb, "'zodiac', 'virgo'" );
5594     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
5595 
5596     r = add_feature_components_entry( hdb, "'zodiac', 'libra'" );
5597     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
5598 
5599     r = add_feature_components_entry( hdb, "'perseus', 'cassiopeia'" );
5600     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
5601 
5602     r = add_feature_components_entry( hdb, "'perseus', 'cepheus'" );
5603     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
5604 
5605     r = add_feature_components_entry( hdb, "'perseus', 'andromeda'" );
5606     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
5607 
5608     r = add_feature_components_entry( hdb, "'orion', 'leo'" );
5609     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
5610 
5611     r = add_feature_components_entry( hdb, "'orion', 'virgo'" );
5612     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
5613 
5614     r = add_feature_components_entry( hdb, "'orion', 'libra'" );
5615     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
5616 
5617     r = add_feature_components_entry( hdb, "'orion', 'cassiopeia'" );
5618     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
5619 
5620     r = add_feature_components_entry( hdb, "'orion', 'cepheus'" );
5621     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
5622 
5623     r = add_feature_components_entry( hdb, "'orion', 'andromeda'" );
5624     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
5625 
5626     r = add_feature_components_entry( hdb, "'orion', 'canis'" );
5627     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
5628 
5629     r = add_feature_components_entry( hdb, "'orion', 'monoceros'" );
5630     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
5631 
5632     r = add_feature_components_entry( hdb, "'orion', 'lepus'" );
5633     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
5634 
5635     r = add_feature_components_entry( hdb, "'waters', 'delphinus'" );
5636     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
5637 
5638     r = add_feature_components_entry( hdb, "'bayer', 'hydrus'" );
5639     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
5640 
5641     r = add_file_entry( hdb, "'leo_file', 'leo', 'leo.txt', 100, '', '1033', 8192, 1" );
5642     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
5643 
5644     r = add_file_entry( hdb, "'virgo_file', 'virgo', 'virgo.txt', 0, '', '1033', 8192, 1" );
5645     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
5646 
5647     r = add_file_entry( hdb, "'libra_file', 'libra', 'libra.txt', 0, '', '1033', 8192, 1" );
5648     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
5649 
5650     r = add_file_entry( hdb, "'cassiopeia_file', 'cassiopeia', 'cassiopeia.txt', 0, '', '1033', 8192, 1" );
5651     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
5652 
5653     r = add_file_entry( hdb, "'cepheus_file', 'cepheus', 'cepheus.txt', 0, '', '1033', 8192, 1" );
5654     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
5655 
5656     r = add_file_entry( hdb, "'andromeda_file', 'andromeda', 'andromeda.txt', 0, '', '1033', 8192, 1" );
5657     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
5658 
5659     r = add_file_entry( hdb, "'canis_file', 'canis', 'canis.txt', 0, '', '1033', 8192, 1" );
5660     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
5661 
5662     r = add_file_entry( hdb, "'monoceros_file', 'monoceros', 'monoceros.txt', 0, '', '1033', 8192, 1" );
5663     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
5664 
5665     r = add_file_entry( hdb, "'lepus_file', 'lepus', 'lepus.txt', 0, '', '1033', 8192, 1" );
5666     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
5667 
5668     r = add_file_entry( hdb, "'delphinus_file', 'delphinus', 'delphinus.txt', 0, '', '1033', 8192, 1" );
5669     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
5670 
5671     r = add_file_entry( hdb, "'hydrus_file', 'hydrus', 'hydrus.txt', 0, '', '1033', 8192, 1" );
5672     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
5673 
5674     r = package_from_db( hdb, &hpkg );
5675     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5676     {
5677         skip("Not enough rights to perform tests\n");
5678         DeleteFileA(msifile);
5679         return;
5680     }
5681     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
5682 
5683     MsiCloseHandle( hdb );
5684 
5685     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5686 
5687     r = MsiDoActionA( hpkg, "CostInitialize");
5688     ok( r == ERROR_SUCCESS, "cost init failed\n");
5689 
5690     r = MsiDoActionA( hpkg, "FileCost");
5691     ok( r == ERROR_SUCCESS, "file cost failed\n");
5692 
5693     r = MsiDoActionA( hpkg, "CostFinalize");
5694     ok( r == ERROR_SUCCESS, "cost finalize failed\n");
5695 
5696     test_feature_states( __LINE__, hpkg, "zodiac", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
5697     test_feature_states( __LINE__, hpkg, "perseus", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
5698     test_feature_states( __LINE__, hpkg, "orion", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
5699     test_feature_states( __LINE__, hpkg, "lyra", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
5700     test_feature_states( __LINE__, hpkg, "waters", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
5701     test_feature_states( __LINE__, hpkg, "bayer", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
5702 
5703     test_component_states( __LINE__, hpkg, "leo", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5704     test_component_states( __LINE__, hpkg, "virgo", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5705     test_component_states( __LINE__, hpkg, "libra", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5706     test_component_states( __LINE__, hpkg, "cassiopeia", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5707     test_component_states( __LINE__, hpkg, "cepheus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5708     test_component_states( __LINE__, hpkg, "andromeda", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5709     test_component_states( __LINE__, hpkg, "canis", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5710     test_component_states( __LINE__, hpkg, "monoceros", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5711     test_component_states( __LINE__, hpkg, "lepus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5712     test_component_states( __LINE__, hpkg, "delphinus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5713     test_component_states( __LINE__, hpkg, "hydrus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5714 
5715     r = MsiSetFeatureStateA(hpkg, "orion", INSTALLSTATE_ABSENT);
5716     ok( r == ERROR_SUCCESS, "failed to set feature state: %d\n", r);
5717 
5718     r = MsiSetFeatureStateA(hpkg, "lyra", INSTALLSTATE_ABSENT);
5719     ok( r == ERROR_SUCCESS, "failed to set feature state: %d\n", r);
5720 
5721     r = MsiSetFeatureStateA(hpkg, "nosuchfeature", INSTALLSTATE_ABSENT);
5722     ok( r == ERROR_UNKNOWN_FEATURE, "Expected ERROR_UNKNOWN_FEATURE, got %u\n", r);
5723 
5724     test_feature_states( __LINE__, hpkg, "zodiac", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
5725     test_feature_states( __LINE__, hpkg, "perseus", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
5726     test_feature_states( __LINE__, hpkg, "orion", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_ABSENT, FALSE );
5727     test_feature_states( __LINE__, hpkg, "lyra", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_ABSENT, FALSE );
5728     test_feature_states( __LINE__, hpkg, "waters", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
5729     test_feature_states( __LINE__, hpkg, "bayer", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
5730 
5731     test_component_states( __LINE__, hpkg, "leo", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5732     test_component_states( __LINE__, hpkg, "virgo", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5733     test_component_states( __LINE__, hpkg, "libra", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5734     test_component_states( __LINE__, hpkg, "cassiopeia", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5735     test_component_states( __LINE__, hpkg, "cepheus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5736     test_component_states( __LINE__, hpkg, "andromeda", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5737     test_component_states( __LINE__, hpkg, "canis", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5738     test_component_states( __LINE__, hpkg, "monoceros", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5739     test_component_states( __LINE__, hpkg, "lepus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5740     test_component_states( __LINE__, hpkg, "delphinus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5741     test_component_states( __LINE__, hpkg, "hydrus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5742 
5743     MsiCloseHandle(hpkg);
5744     DeleteFileA(msifile);
5745 }
5746 
5747 static void test_installprops(void)
5748 {
5749     MSIHANDLE hpkg, hdb;
5750     CHAR path[MAX_PATH], buf[MAX_PATH];
5751     DWORD size, type;
5752     LANGID langid;
5753     HKEY hkey1, hkey2;
5754     int res;
5755     UINT r;
5756     REGSAM access = KEY_ALL_ACCESS;
5757     SYSTEM_INFO si;
5758     INSTALLUILEVEL uilevel;
5759 
5760     if (is_wow64)
5761         access |= KEY_WOW64_64KEY;
5762 
5763     lstrcpyA(path, CURR_DIR);
5764     if (!is_root(CURR_DIR)) lstrcatA(path, "\\");
5765     lstrcatA(path, msifile);
5766 
5767     uilevel = MsiSetInternalUI(INSTALLUILEVEL_BASIC|INSTALLUILEVEL_SOURCERESONLY, NULL);
5768 
5769     hdb = create_package_db();
5770     ok( hdb, "failed to create database\n");
5771 
5772     r = package_from_db(hdb, &hpkg);
5773     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5774     {
5775         skip("Not enough rights to perform tests\n");
5776         MsiSetInternalUI(uilevel, NULL);
5777         DeleteFileA(msifile);
5778         return;
5779     }
5780     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
5781 
5782     MsiCloseHandle(hdb);
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     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5791 
5792     buf[0] = 0;
5793     size = MAX_PATH;
5794     r = MsiGetPropertyA(hpkg, "UILevel", buf, &size);
5795     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5796     ok( !lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
5797 
5798     buf[0] = 0;
5799     size = MAX_PATH;
5800     r = MsiGetPropertyA(hpkg, "DATABASE", buf, &size);
5801     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5802     ok( !lstrcmpA(buf, path), "Expected %s, got %s\n", path, buf);
5803 
5804     RegOpenKeyA(HKEY_CURRENT_USER, "SOFTWARE\\Microsoft\\MS Setup (ACME)\\User Info", &hkey1);
5805     RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, access, &hkey2);
5806 
5807     size = MAX_PATH;
5808     type = REG_SZ;
5809     *path = '\0';
5810     if (RegQueryValueExA(hkey1, "DefName", NULL, &type, (LPBYTE)path, &size) != ERROR_SUCCESS)
5811     {
5812         size = MAX_PATH;
5813         type = REG_SZ;
5814         RegQueryValueExA(hkey2, "RegisteredOwner", NULL, &type, (LPBYTE)path, &size);
5815     }
5816 
5817     buf[0] = 0;
5818     size = MAX_PATH;
5819     r = MsiGetPropertyA(hpkg, "USERNAME", buf, &size);
5820     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5821     ok( !lstrcmpA(buf, path), "Expected %s, got %s\n", path, buf);
5822 
5823     size = MAX_PATH;
5824     type = REG_SZ;
5825     *path = '\0';
5826     if (RegQueryValueExA(hkey1, "DefCompany", NULL, &type, (LPBYTE)path, &size) != ERROR_SUCCESS)
5827     {
5828         size = MAX_PATH;
5829         type = REG_SZ;
5830         RegQueryValueExA(hkey2, "RegisteredOrganization", NULL, &type, (LPBYTE)path, &size);
5831     }
5832 
5833     if (*path)
5834     {
5835         buf[0] = 0;
5836         size = MAX_PATH;
5837         r = MsiGetPropertyA(hpkg, "COMPANYNAME", buf, &size);
5838         ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5839         ok( !lstrcmpA(buf, path), "Expected %s, got %s\n", path, buf);
5840     }
5841 
5842     buf[0] = 0;
5843     size = MAX_PATH;
5844     r = MsiGetPropertyA(hpkg, "VersionDatabase", buf, &size);
5845     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5846     trace("VersionDatabase = %s\n", buf);
5847 
5848     buf[0] = 0;
5849     size = MAX_PATH;
5850     r = MsiGetPropertyA(hpkg, "VersionMsi", buf, &size);
5851     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5852     trace("VersionMsi = %s\n", buf);
5853 
5854     buf[0] = 0;
5855     size = MAX_PATH;
5856     r = MsiGetPropertyA(hpkg, "Date", buf, &size);
5857     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5858     trace("Date = %s\n", buf);
5859 
5860     buf[0] = 0;
5861     size = MAX_PATH;
5862     r = MsiGetPropertyA(hpkg, "Time", buf, &size);
5863     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5864     trace("Time = %s\n", buf);
5865 
5866     buf[0] = 0;
5867     size = MAX_PATH;
5868     r = MsiGetPropertyA(hpkg, "PackageCode", buf, &size);
5869     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5870     trace("PackageCode = %s\n", buf);
5871 
5872     buf[0] = 0;
5873     size = MAX_PATH;
5874     r = MsiGetPropertyA(hpkg, "ComputerName", buf, &size);
5875     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
5876     trace("ComputerName = %s\n", buf);
5877 
5878     langid = GetUserDefaultLangID();
5879     sprintf(path, "%d", langid);
5880 
5881     buf[0] = 0;
5882     size = MAX_PATH;
5883     r = MsiGetPropertyA(hpkg, "UserLanguageID", buf, &size);
5884     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
5885     ok( !lstrcmpA(buf, path), "Expected \"%s\", got \"%s\"\n", path, buf);
5886 
5887     res = GetSystemMetrics(SM_CXSCREEN);
5888     buf[0] = 0;
5889     size = MAX_PATH;
5890     r = MsiGetPropertyA(hpkg, "ScreenX", buf, &size);
5891     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
5892     ok(atol(buf) == res, "Expected %d, got %ld\n", res, atol(buf));
5893 
5894     res = GetSystemMetrics(SM_CYSCREEN);
5895     buf[0] = 0;
5896     size = MAX_PATH;
5897     r = MsiGetPropertyA(hpkg, "ScreenY", buf, &size);
5898     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
5899     ok(atol(buf) == res, "Expected %d, got %ld\n", res, atol(buf));
5900 
5901     if (pGetSystemInfo && pSHGetFolderPathA)
5902     {
5903         pGetSystemInfo(&si);
5904         if (S(U(si)).wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
5905         {
5906             buf[0] = 0;
5907             size = MAX_PATH;
5908             r = MsiGetPropertyA(hpkg, "Intel", buf, &size);
5909             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5910             ok(buf[0], "property not set\n");
5911 
5912             buf[0] = 0;
5913             size = MAX_PATH;
5914             r = MsiGetPropertyA(hpkg, "MsiAMD64", buf, &size);
5915             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5916             ok(buf[0], "property not set\n");
5917 
5918             buf[0] = 0;
5919             size = MAX_PATH;
5920             r = MsiGetPropertyA(hpkg, "Msix64", buf, &size);
5921             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5922             ok(buf[0], "property not set\n");
5923 
5924             buf[0] = 0;
5925             size = MAX_PATH;
5926             r = MsiGetPropertyA(hpkg, "System64Folder", buf, &size);
5927             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5928             GetSystemDirectoryA(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, "SystemFolder", buf, &size);
5935             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5936             pGetSystemWow64DirectoryA(path, MAX_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, "ProgramFiles64Folder", buf, &size);
5943             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5944             pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES, 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, "ProgramFilesFolder", buf, &size);
5951             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5952             pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILESX86, 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, "CommonFiles64Folder", buf, &size);
5959             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5960             pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES_COMMON, 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, "CommonFilesFolder", buf, &size);
5967             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5968             pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES_COMMONX86, NULL, 0, path);
5969             if (size) buf[size - 1] = 0;
5970             ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5971 
5972             buf[0] = 0;
5973             size = MAX_PATH;
5974             r = MsiGetPropertyA(hpkg, "VersionNT64", buf, &size);
5975             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5976             ok(buf[0], "property not set\n");
5977         }
5978         else if (S(U(si)).wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
5979         {
5980             if (!is_wow64)
5981             {
5982                 buf[0] = 0;
5983                 size = MAX_PATH;
5984                 r = MsiGetPropertyA(hpkg, "Intel", buf, &size);
5985                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5986                 ok(buf[0], "property not set\n");
5987 
5988                 buf[0] = 0;
5989                 size = MAX_PATH;
5990                 r = MsiGetPropertyA(hpkg, "MsiAMD64", buf, &size);
5991                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5992                 ok(!buf[0], "property set\n");
5993 
5994                 buf[0] = 0;
5995                 size = MAX_PATH;
5996                 r = MsiGetPropertyA(hpkg, "Msix64", buf, &size);
5997                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5998                 ok(!buf[0], "property set\n");
5999 
6000                 buf[0] = 0;
6001                 size = MAX_PATH;
6002                 r = MsiGetPropertyA(hpkg, "System64Folder", buf, &size);
6003                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
6004                 ok(!buf[0], "property set\n");
6005 
6006                 buf[0] = 0;
6007                 size = MAX_PATH;
6008                 r = MsiGetPropertyA(hpkg, "SystemFolder", buf, &size);
6009                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
6010                 GetSystemDirectoryA(path, MAX_PATH);
6011                 if (size) buf[size - 1] = 0;
6012                 ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
6013 
6014                 buf[0] = 0;
6015                 size = MAX_PATH;
6016                 r = MsiGetPropertyA(hpkg, "ProgramFiles64Folder", buf, &size);
6017                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
6018                 ok(!buf[0], "property set\n");
6019 
6020                 buf[0] = 0;
6021                 size = MAX_PATH;
6022                 r = MsiGetPropertyA(hpkg, "ProgramFilesFolder", buf, &size);
6023                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
6024                 pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES, NULL, 0, path);
6025                 if (size) buf[size - 1] = 0;
6026                 ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
6027 
6028                 buf[0] = 0;
6029                 size = MAX_PATH;
6030                 r = MsiGetPropertyA(hpkg, "CommonFiles64Folder", buf, &size);
6031                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
6032                 ok(!buf[0], "property set\n");
6033 
6034                 buf[0] = 0;
6035                 size = MAX_PATH;
6036                 r = MsiGetPropertyA(hpkg, "CommonFilesFolder", buf, &size);
6037                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
6038                 pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES_COMMON, NULL, 0, path);
6039                 if (size) buf[size - 1] = 0;
6040                 ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
6041 
6042                 buf[0] = 0;
6043                 size = MAX_PATH;
6044                 r = MsiGetPropertyA(hpkg, "VersionNT64", buf, &size);
6045                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
6046                 ok(!buf[0], "property set\n");
6047             }
6048             else
6049             {
6050                 buf[0] = 0;
6051                 size = MAX_PATH;
6052                 r = MsiGetPropertyA(hpkg, "Intel", buf, &size);
6053                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
6054                 ok(buf[0], "property not set\n");
6055 
6056                 buf[0] = 0;
6057                 size = MAX_PATH;
6058                 r = MsiGetPropertyA(hpkg, "MsiAMD64", buf, &size);
6059                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
6060                 ok(buf[0], "property not set\n");
6061 
6062                 buf[0] = 0;
6063                 size = MAX_PATH;
6064                 r = MsiGetPropertyA(hpkg, "Msix64", buf, &size);
6065                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
6066                 ok(buf[0], "property not set\n");
6067 
6068                 buf[0] = 0;
6069                 size = MAX_PATH;
6070                 r = MsiGetPropertyA(hpkg, "System64Folder", buf, &size);
6071                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
6072                 GetSystemDirectoryA(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, "SystemFolder", buf, &size);
6079                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
6080                 pGetSystemWow64DirectoryA(path, MAX_PATH);
6081                 if (size) buf[size - 1] = 0;
6082                 ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
6083 
6084                 buf[0] = 0;
6085                 size = MAX_PATH;
6086                 r = MsiGetPropertyA(hpkg, "ProgramFilesFolder64", buf, &size);
6087                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
6088                 ok(!buf[0], "property set\n");
6089 
6090                 buf[0] = 0;
6091                 size = MAX_PATH;
6092                 r = MsiGetPropertyA(hpkg, "ProgramFilesFolder", buf, &size);
6093                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
6094                 pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILESX86, NULL, 0, path);
6095                 if (size) buf[size - 1] = 0;
6096                 ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
6097 
6098                 buf[0] = 0;
6099                 size = MAX_PATH;
6100                 r = MsiGetPropertyA(hpkg, "CommonFilesFolder64", buf, &size);
6101                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
6102                 ok(!buf[0], "property set\n");
6103 
6104                 buf[0] = 0;
6105                 size = MAX_PATH;
6106                 r = MsiGetPropertyA(hpkg, "CommonFilesFolder", buf, &size);
6107                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
6108                 pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES_COMMONX86, NULL, 0, path);
6109                 if (size) buf[size - 1] = 0;
6110                 ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
6111 
6112                 buf[0] = 0;
6113                 size = MAX_PATH;
6114                 r = MsiGetPropertyA(hpkg, "VersionNT64", buf, &size);
6115                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
6116                 ok(buf[0], "property not set\n");
6117             }
6118         }
6119     }
6120 
6121     CloseHandle(hkey1);
6122     CloseHandle(hkey2);
6123     MsiCloseHandle(hpkg);
6124     DeleteFileA(msifile);
6125     MsiSetInternalUI(uilevel, NULL);
6126 }
6127 
6128 static void test_launchconditions(void)
6129 {
6130     MSIHANDLE hpkg;
6131     MSIHANDLE hdb;
6132     UINT r;
6133 
6134     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
6135 
6136     hdb = create_package_db();
6137     ok( hdb, "failed to create package database\n" );
6138 
6139     r = create_launchcondition_table( hdb );
6140     ok( r == ERROR_SUCCESS, "cannot create LaunchCondition table: %d\n", r );
6141 
6142     r = add_launchcondition_entry( hdb, "'X = \"1\"', 'one'" );
6143     ok( r == ERROR_SUCCESS, "cannot add launch condition: %d\n", r );
6144 
6145     /* invalid condition */
6146     r = add_launchcondition_entry( hdb, "'X != \"1\"', 'one'" );
6147     ok( r == ERROR_SUCCESS, "cannot add launch condition: %d\n", r );
6148 
6149     r = package_from_db( hdb, &hpkg );
6150     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
6151     {
6152         skip("Not enough rights to perform tests\n");
6153         DeleteFileA(msifile);
6154         return;
6155     }
6156     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
6157 
6158     MsiCloseHandle( hdb );
6159 
6160     r = MsiSetPropertyA( hpkg, "X", "1" );
6161     ok( r == ERROR_SUCCESS, "failed to set property\n" );
6162 
6163     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
6164 
6165     /* invalid conditions are ignored */
6166     r = MsiDoActionA( hpkg, "LaunchConditions" );
6167     ok( r == ERROR_SUCCESS, "cost init failed\n" );
6168 
6169     /* verify LaunchConditions still does some verification */
6170     r = MsiSetPropertyA( hpkg, "X", "2" );
6171     ok( r == ERROR_SUCCESS, "failed to set property\n" );
6172 
6173     r = MsiDoActionA( hpkg, "LaunchConditions" );
6174     ok( r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %d\n", r );
6175 
6176     MsiCloseHandle( hpkg );
6177     DeleteFileA( msifile );
6178 }
6179 
6180 static void test_ccpsearch(void)
6181 {
6182     MSIHANDLE hdb, hpkg;
6183     CHAR prop[MAX_PATH];
6184     DWORD size = MAX_PATH;
6185     UINT r;
6186 
6187     hdb = create_package_db();
6188     ok(hdb, "failed to create package database\n");
6189 
6190     r = create_ccpsearch_table(hdb);
6191     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6192 
6193     r = add_ccpsearch_entry(hdb, "'CCP_random'");
6194     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6195 
6196     r = add_ccpsearch_entry(hdb, "'RMCCP_random'");
6197     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6198 
6199     r = create_reglocator_table(hdb);
6200     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6201 
6202     r = add_reglocator_entry(hdb, "CCP_random", 0, "htmlfile\\shell\\open\\nonexistent", "", 1);
6203     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6204 
6205     r = create_drlocator_table(hdb);
6206     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6207 
6208     r = add_drlocator_entry(hdb, "'RMCCP_random', '', 'C:\\', '0'");
6209     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6210 
6211     r = create_signature_table(hdb);
6212     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6213 
6214     r = package_from_db(hdb, &hpkg);
6215     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
6216     {
6217         skip("Not enough rights to perform tests\n");
6218         DeleteFileA(msifile);
6219         return;
6220     }
6221     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
6222 
6223     MsiCloseHandle(hdb);
6224 
6225     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
6226 
6227     r = MsiDoActionA(hpkg, "CCPSearch");
6228     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6229 
6230     r = MsiGetPropertyA(hpkg, "CCP_Success", prop, &size);
6231     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6232     ok(!lstrcmpA(prop, "1"), "Expected 1, got %s\n", prop);
6233 
6234     MsiCloseHandle(hpkg);
6235     DeleteFileA(msifile);
6236 }
6237 
6238 static void test_complocator(void)
6239 {
6240     MSIHANDLE hdb, hpkg;
6241     UINT r;
6242     CHAR prop[MAX_PATH];
6243     CHAR expected[MAX_PATH];
6244     DWORD size = MAX_PATH;
6245 
6246     hdb = create_package_db();
6247     ok(hdb, "failed to create package database\n");
6248 
6249     r = create_appsearch_table(hdb);
6250     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6251 
6252     r = add_appsearch_entry(hdb, "'ABELISAURUS', 'abelisaurus'");
6253     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6254 
6255     r = add_appsearch_entry(hdb, "'BACTROSAURUS', 'bactrosaurus'");
6256     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6257 
6258     r = add_appsearch_entry(hdb, "'CAMELOTIA', 'camelotia'");
6259     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6260 
6261     r = add_appsearch_entry(hdb, "'DICLONIUS', 'diclonius'");
6262     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6263 
6264     r = add_appsearch_entry(hdb, "'ECHINODON', 'echinodon'");
6265     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6266 
6267     r = add_appsearch_entry(hdb, "'FALCARIUS', 'falcarius'");
6268     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6269 
6270     r = add_appsearch_entry(hdb, "'GALLIMIMUS', 'gallimimus'");
6271     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6272 
6273     r = add_appsearch_entry(hdb, "'HAGRYPHUS', 'hagryphus'");
6274     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6275 
6276     r = add_appsearch_entry(hdb, "'IGUANODON', 'iguanodon'");
6277     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6278 
6279     r = add_appsearch_entry(hdb, "'JOBARIA', 'jobaria'");
6280     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6281 
6282     r = add_appsearch_entry(hdb, "'KAKURU', 'kakuru'");
6283     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6284 
6285     r = add_appsearch_entry(hdb, "'LABOCANIA', 'labocania'");
6286     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6287 
6288     r = add_appsearch_entry(hdb, "'MEGARAPTOR', 'megaraptor'");
6289     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6290 
6291     r = add_appsearch_entry(hdb, "'NEOSODON', 'neosodon'");
6292     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6293 
6294     r = add_appsearch_entry(hdb, "'OLOROTITAN', 'olorotitan'");
6295     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6296 
6297     r = add_appsearch_entry(hdb, "'PANTYDRACO', 'pantydraco'");
6298     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6299 
6300     r = create_complocator_table(hdb);
6301     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6302 
6303     r = add_complocator_entry(hdb, "'abelisaurus', '{E3619EED-305A-418C-B9C7-F7D7377F0934}', 1");
6304     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6305 
6306     r = add_complocator_entry(hdb, "'bactrosaurus', '{D56B688D-542F-42Ef-90FD-B6DA76EE8119}', 0");
6307     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6308 
6309     r = add_complocator_entry(hdb, "'camelotia', '{8211BE36-2466-47E3-AFB7-6AC72E51AED2}', 1");
6310     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6311 
6312     r = add_complocator_entry(hdb, "'diclonius', '{5C767B20-A33C-45A4-B80B-555E512F01AE}', 0");
6313     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6314 
6315     r = add_complocator_entry(hdb, "'echinodon', '{A19E16C5-C75D-4699-8111-C4338C40C3CB}', 1");
6316     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6317 
6318     r = add_complocator_entry(hdb, "'falcarius', '{17762FA1-A7AE-4CC6-8827-62873C35361D}', 0");
6319     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6320 
6321     r = add_complocator_entry(hdb, "'gallimimus', '{75EBF568-C959-41E0-A99E-9050638CF5FB}', 1");
6322     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6323 
6324     r = add_complocator_entry(hdb, "'hagrphus', '{D4969B72-17D9-4AB6-BE49-78F2FEE857AC}', 0");
6325     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6326 
6327     r = add_complocator_entry(hdb, "'iguanodon', '{8E0DA02E-F6A7-4A8F-B25D-6F564C492308}', 1");
6328     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6329 
6330     r = add_complocator_entry(hdb, "'jobaria', '{243C22B1-8C51-4151-B9D1-1AE5265E079E}', 0");
6331     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6332 
6333     r = add_complocator_entry(hdb, "'kakuru', '{5D0F03BA-50BC-44F2-ABB1-72C972F4E514}', 1");
6334     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6335 
6336     r = add_complocator_entry(hdb, "'labocania', '{C7DDB60C-7828-4046-A6F8-699D5E92F1ED}', 0");
6337     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6338 
6339     r = add_complocator_entry(hdb, "'megaraptor', '{8B1034B7-BD5E-41ac-B52C-0105D3DFD74D}', 1");
6340     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6341 
6342     r = add_complocator_entry(hdb, "'neosodon', '{0B499649-197A-48EF-93D2-AF1C17ED6E90}', 0");
6343     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6344 
6345     r = add_complocator_entry(hdb, "'olorotitan', '{54E9E91F-AED2-46D5-A25A-7E50AFA24513}', 1");
6346     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6347 
6348     r = add_complocator_entry(hdb, "'pantydraco', '{2A989951-5565-4FA7-93A7-E800A3E67D71}', 0");
6349     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6350 
6351     r = create_signature_table(hdb);
6352     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6353 
6354     r = add_signature_entry(hdb, "'abelisaurus', 'abelisaurus', '', '', '', '', '', '', ''");
6355     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6356 
6357     r = add_signature_entry(hdb, "'bactrosaurus', 'bactrosaurus', '', '', '', '', '', '', ''");
6358     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6359 
6360     r = add_signature_entry(hdb, "'camelotia', 'camelotia', '', '', '', '', '', '', ''");
6361     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6362 
6363     r = add_signature_entry(hdb, "'diclonius', 'diclonius', '', '', '', '', '', '', ''");
6364     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6365 
6366     r = add_signature_entry(hdb, "'iguanodon', 'iguanodon', '', '', '', '', '', '', ''");
6367     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6368 
6369     r = add_signature_entry(hdb, "'jobaria', 'jobaria', '', '', '', '', '', '', ''");
6370     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6371 
6372     r = add_signature_entry(hdb, "'kakuru', 'kakuru', '', '', '', '', '', '', ''");
6373     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6374 
6375     r = add_signature_entry(hdb, "'labocania', 'labocania', '', '', '', '', '', '', ''");
6376     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6377 
6378     r = package_from_db(hdb, &hpkg);
6379     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
6380     {
6381         skip("Not enough rights to perform tests\n");
6382         DeleteFileA(msifile);
6383         return;
6384     }
6385     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
6386 
6387     MsiCloseHandle(hdb);
6388 
6389     create_test_file("abelisaurus");
6390     create_test_file("bactrosaurus");
6391     create_test_file("camelotia");
6392     create_test_file("diclonius");
6393     create_test_file("echinodon");
6394     create_test_file("falcarius");
6395     create_test_file("gallimimus");
6396     create_test_file("hagryphus");
6397     CreateDirectoryA("iguanodon", NULL);
6398     CreateDirectoryA("jobaria", NULL);
6399     CreateDirectoryA("kakuru", NULL);
6400     CreateDirectoryA("labocania", NULL);
6401     CreateDirectoryA("megaraptor", NULL);
6402     CreateDirectoryA("neosodon", NULL);
6403     CreateDirectoryA("olorotitan", NULL);
6404     CreateDirectoryA("pantydraco", NULL);
6405 
6406     set_component_path("abelisaurus", MSIINSTALLCONTEXT_MACHINE,
6407                        "{E3619EED-305A-418C-B9C7-F7D7377F0934}", NULL, FALSE);
6408     set_component_path("bactrosaurus", MSIINSTALLCONTEXT_MACHINE,
6409                        "{D56B688D-542F-42Ef-90FD-B6DA76EE8119}", NULL, FALSE);
6410     set_component_path("echinodon", MSIINSTALLCONTEXT_MACHINE,
6411                        "{A19E16C5-C75D-4699-8111-C4338C40C3CB}", NULL, FALSE);
6412     set_component_path("falcarius", MSIINSTALLCONTEXT_MACHINE,
6413                        "{17762FA1-A7AE-4CC6-8827-62873C35361D}", NULL, FALSE);
6414     set_component_path("iguanodon", MSIINSTALLCONTEXT_MACHINE,
6415                        "{8E0DA02E-F6A7-4A8F-B25D-6F564C492308}", NULL, FALSE);
6416     set_component_path("jobaria", MSIINSTALLCONTEXT_MACHINE,
6417                        "{243C22B1-8C51-4151-B9D1-1AE5265E079E}", NULL, FALSE);
6418     set_component_path("megaraptor", MSIINSTALLCONTEXT_MACHINE,
6419                        "{8B1034B7-BD5E-41ac-B52C-0105D3DFD74D}", NULL, FALSE);
6420     set_component_path("neosodon", MSIINSTALLCONTEXT_MACHINE,
6421                        "{0B499649-197A-48EF-93D2-AF1C17ED6E90}", NULL, FALSE);
6422 
6423     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
6424 
6425     r = MsiDoActionA(hpkg, "AppSearch");
6426     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6427 
6428     size = MAX_PATH;
6429     r = MsiGetPropertyA(hpkg, "ABELISAURUS", prop, &size);
6430     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6431 
6432     lstrcpyA(expected, CURR_DIR);
6433     if (!is_root(CURR_DIR)) lstrcatA(expected, "\\");
6434     lstrcatA(expected, "abelisaurus");
6435     ok(!lstrcmpA(prop, expected) || !lstrcmpA(prop, ""),
6436        "Expected %s or empty string, got %s\n", expected, prop);
6437 
6438     size = MAX_PATH;
6439     r = MsiGetPropertyA(hpkg, "BACTROSAURUS", prop, &size);
6440     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6441     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6442 
6443     size = MAX_PATH;
6444     r = MsiGetPropertyA(hpkg, "CAMELOTIA", prop, &size);
6445     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6446     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6447 
6448     size = MAX_PATH;
6449     r = MsiGetPropertyA(hpkg, "DICLONIUS", prop, &size);
6450     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6451     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6452 
6453     size = MAX_PATH;
6454     r = MsiGetPropertyA(hpkg, "ECHINODON", prop, &size);
6455     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6456 
6457     lstrcpyA(expected, CURR_DIR);
6458     if (!is_root(CURR_DIR)) lstrcatA(expected, "\\");
6459     ok(!lstrcmpA(prop, expected) || !lstrcmpA(prop, ""),
6460        "Expected %s or empty string, got %s\n", expected, prop);
6461 
6462     size = MAX_PATH;
6463     r = MsiGetPropertyA(hpkg, "FALCARIUS", prop, &size);
6464     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6465     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6466 
6467     size = MAX_PATH;
6468     r = MsiGetPropertyA(hpkg, "GALLIMIMUS", prop, &size);
6469     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6470     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6471 
6472     size = MAX_PATH;
6473     r = MsiGetPropertyA(hpkg, "HAGRYPHUS", prop, &size);
6474     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6475     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6476 
6477     size = MAX_PATH;
6478     r = MsiGetPropertyA(hpkg, "IGUANODON", prop, &size);
6479     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6480     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6481 
6482     size = MAX_PATH;
6483     r = MsiGetPropertyA(hpkg, "JOBARIA", prop, &size);
6484     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6485     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6486 
6487     size = MAX_PATH;
6488     r = MsiGetPropertyA(hpkg, "KAKURU", prop, &size);
6489     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6490     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6491 
6492     size = MAX_PATH;
6493     r = MsiGetPropertyA(hpkg, "LABOCANIA", prop, &size);
6494     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6495     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6496 
6497     size = MAX_PATH;
6498     r = MsiGetPropertyA(hpkg, "MEGARAPTOR", prop, &size);
6499     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6500 
6501     lstrcpyA(expected, CURR_DIR);
6502     if (!is_root(CURR_DIR)) lstrcatA(expected, "\\");
6503     ok(!lstrcmpA(prop, expected) || !lstrcmpA(prop, ""),
6504        "Expected %s or empty string, got %s\n", expected, prop);
6505 
6506     size = MAX_PATH;
6507     r = MsiGetPropertyA(hpkg, "NEOSODON", prop, &size);
6508     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6509 
6510     lstrcpyA(expected, CURR_DIR);
6511     if (!is_root(CURR_DIR)) lstrcatA(expected, "\\");
6512     lstrcatA(expected, "neosodon\\");
6513     ok(!lstrcmpA(prop, expected) || !lstrcmpA(prop, ""),
6514        "Expected %s or empty string, got %s\n", expected, prop);
6515 
6516     size = MAX_PATH;
6517     r = MsiGetPropertyA(hpkg, "OLOROTITAN", prop, &size);
6518     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6519     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6520 
6521     size = MAX_PATH;
6522     r = MsiGetPropertyA(hpkg, "PANTYDRACO", prop, &size);
6523     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6524     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6525 
6526     MsiCloseHandle(hpkg);
6527     DeleteFileA("abelisaurus");
6528     DeleteFileA("bactrosaurus");
6529     DeleteFileA("camelotia");
6530     DeleteFileA("diclonius");
6531     DeleteFileA("echinodon");
6532     DeleteFileA("falcarius");
6533     DeleteFileA("gallimimus");
6534     DeleteFileA("hagryphus");
6535     RemoveDirectoryA("iguanodon");
6536     RemoveDirectoryA("jobaria");
6537     RemoveDirectoryA("kakuru");
6538     RemoveDirectoryA("labocania");
6539     RemoveDirectoryA("megaraptor");
6540     RemoveDirectoryA("neosodon");
6541     RemoveDirectoryA("olorotitan");
6542     RemoveDirectoryA("pantydraco");
6543     delete_component_path("{E3619EED-305A-418C-B9C7-F7D7377F0934}",
6544                           MSIINSTALLCONTEXT_MACHINE, NULL);
6545     delete_component_path("{D56B688D-542F-42Ef-90FD-B6DA76EE8119}",
6546                           MSIINSTALLCONTEXT_MACHINE, NULL);
6547     delete_component_path("{A19E16C5-C75D-4699-8111-C4338C40C3CB}",
6548                           MSIINSTALLCONTEXT_MACHINE, NULL);
6549     delete_component_path("{17762FA1-A7AE-4CC6-8827-62873C35361D}",
6550                           MSIINSTALLCONTEXT_MACHINE, NULL);
6551     delete_component_path("{8E0DA02E-F6A7-4A8F-B25D-6F564C492308}",
6552                           MSIINSTALLCONTEXT_MACHINE, NULL);
6553     delete_component_path("{243C22B1-8C51-4151-B9D1-1AE5265E079E}",
6554                           MSIINSTALLCONTEXT_MACHINE, NULL);
6555     delete_component_path("{8B1034B7-BD5E-41ac-B52C-0105D3DFD74D}",
6556                           MSIINSTALLCONTEXT_MACHINE, NULL);
6557     delete_component_path("{0B499649-197A-48EF-93D2-AF1C17ED6E90}",
6558                           MSIINSTALLCONTEXT_MACHINE, NULL);
6559     DeleteFileA(msifile);
6560 }
6561 
6562 static void set_suminfo_prop(MSIHANDLE db, DWORD prop, DWORD val)
6563 {
6564     MSIHANDLE summary;
6565     UINT r;
6566 
6567     r = MsiGetSummaryInformationA(db, NULL, 1, &summary);
6568     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6569 
6570     r = MsiSummaryInfoSetPropertyA(summary, prop, VT_I4, val, NULL, NULL);
6571     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6572 
6573     r = MsiSummaryInfoPersist(summary);
6574     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
6575 
6576     MsiCloseHandle(summary);
6577 }
6578 
6579 static void test_MsiGetSourcePath(void)
6580 {
6581     MSIHANDLE hdb, hpkg;
6582     CHAR path[MAX_PATH];
6583     CHAR cwd[MAX_PATH];
6584     CHAR subsrc[MAX_PATH];
6585     CHAR sub2[MAX_PATH];
6586     DWORD size;
6587     UINT r;
6588 
6589     lstrcpyA(cwd, CURR_DIR);
6590     if (!is_root(CURR_DIR)) lstrcatA(cwd, "\\");
6591 
6592     lstrcpyA(subsrc, cwd);
6593     lstrcatA(subsrc, "subsource");
6594     lstrcatA(subsrc, "\\");
6595 
6596     lstrcpyA(sub2, subsrc);
6597     lstrcatA(sub2, "sub2");
6598     lstrcatA(sub2, "\\");
6599 
6600     /* uncompressed source */
6601 
6602     hdb = create_package_db();
6603     ok( hdb, "failed to create database\n");
6604 
6605     set_suminfo_prop(hdb, PID_WORDCOUNT, 0);
6606 
6607     r = add_directory_entry(hdb, "'TARGETDIR', '', 'SourceDir'");
6608     ok(r == S_OK, "failed\n");
6609 
6610     r = add_directory_entry(hdb, "'SubDir', 'TARGETDIR', 'subtarget:subsource'");
6611     ok(r == S_OK, "failed\n");
6612 
6613     r = add_directory_entry(hdb, "'SubDir2', 'SubDir', 'sub2'");
6614     ok(r == S_OK, "failed\n");
6615 
6616     r = MsiDatabaseCommit(hdb);
6617     ok(r == ERROR_SUCCESS , "Failed to commit database\n");
6618 
6619     r = package_from_db(hdb, &hpkg);
6620     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
6621     {
6622         skip("Not enough rights to perform tests\n");
6623         DeleteFileA(msifile);
6624         return;
6625     }
6626     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
6627 
6628     MsiCloseHandle(hdb);
6629 
6630     /* invalid database handle */
6631     size = MAX_PATH;
6632     lstrcpyA(path, "kiwi");
6633     r = MsiGetSourcePathA(-1, "TARGETDIR", path, &size);
6634     ok(r == ERROR_INVALID_HANDLE,
6635        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
6636     ok(!lstrcmpA(path, "kiwi"),
6637        "Expected path to be unchanged, got \"%s\"\n", path);
6638     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6639 
6640     /* NULL szFolder */
6641     size = MAX_PATH;
6642     lstrcpyA(path, "kiwi");
6643     r = MsiGetSourcePathA(hpkg, NULL, path, &size);
6644     ok(r == ERROR_INVALID_PARAMETER,
6645        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6646     ok(!lstrcmpA(path, "kiwi"),
6647        "Expected path to be unchanged, got \"%s\"\n", path);
6648     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6649 
6650     /* empty szFolder */
6651     size = MAX_PATH;
6652     lstrcpyA(path, "kiwi");
6653     r = MsiGetSourcePathA(hpkg, "", path, &size);
6654     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6655     ok(!lstrcmpA(path, "kiwi"),
6656        "Expected path to be unchanged, got \"%s\"\n", path);
6657     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6658 
6659     /* try TARGETDIR */
6660     size = MAX_PATH;
6661     lstrcpyA(path, "kiwi");
6662     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6663     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6664     ok(!lstrcmpA(path, "kiwi"),
6665        "Expected path to be unchanged, got \"%s\"\n", path);
6666     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6667 
6668     size = MAX_PATH;
6669     lstrcpyA(path, "kiwi");
6670     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6671     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6672     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6673     ok(size == 0, "Expected 0, got %d\n", size);
6674 
6675     size = MAX_PATH;
6676     lstrcpyA(path, "kiwi");
6677     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6678     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6679     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6680     ok(size == 0, "Expected 0, got %d\n", size);
6681 
6682     /* try SourceDir */
6683     size = MAX_PATH;
6684     lstrcpyA(path, "kiwi");
6685     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6686     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6687     ok(!lstrcmpA(path, "kiwi"),
6688        "Expected path to be unchanged, got \"%s\"\n", path);
6689     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6690 
6691     /* try SOURCEDIR */
6692     size = MAX_PATH;
6693     lstrcpyA(path, "kiwi");
6694     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6695     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6696     ok(!lstrcmpA(path, "kiwi"),
6697        "Expected path to be unchanged, got \"%s\"\n", path);
6698     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6699 
6700     /* source path does not exist, but the property exists */
6701     size = MAX_PATH;
6702     lstrcpyA(path, "kiwi");
6703     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6704     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6705     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6706     ok(size == 0, "Expected 0, got %d\n", size);
6707 
6708     size = MAX_PATH;
6709     lstrcpyA(path, "kiwi");
6710     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6711     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6712     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6713     ok(size == 0, "Expected 0, got %d\n", size);
6714 
6715     /* try SubDir */
6716     size = MAX_PATH;
6717     lstrcpyA(path, "kiwi");
6718     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6719     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6720     ok(!lstrcmpA(path, "kiwi"),
6721        "Expected path to be unchanged, got \"%s\"\n", path);
6722     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6723 
6724     /* try SubDir2 */
6725     size = MAX_PATH;
6726     lstrcpyA(path, "kiwi");
6727     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6728     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6729     ok(!lstrcmpA(path, "kiwi"),
6730        "Expected path to be unchanged, got \"%s\"\n", path);
6731     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6732 
6733     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
6734 
6735     r = MsiDoActionA(hpkg, "CostInitialize");
6736     ok(r == ERROR_SUCCESS, "cost init failed\n");
6737 
6738     /* try TARGETDIR after CostInitialize */
6739     size = MAX_PATH;
6740     lstrcpyA(path, "kiwi");
6741     r = MsiGetSourcePathA(hpkg, "TARGETDIR", 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_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6751     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6752     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6753 
6754     /* try SOURCEDIR after CostInitialize */
6755     size = MAX_PATH;
6756     lstrcpyA(path, "kiwi");
6757     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6758     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6759     ok(!lstrcmpA(path, "kiwi"),
6760        "Expected path to be unchanged, got \"%s\"\n", path);
6761     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6762 
6763     /* source path does not exist, but the property exists */
6764     size = MAX_PATH;
6765     lstrcpyA(path, "kiwi");
6766     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6767     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6768     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6769     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6770 
6771     size = MAX_PATH;
6772     lstrcpyA(path, "kiwi");
6773     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6774     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6775     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6776     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6777 
6778     /* try SubDir after CostInitialize */
6779     size = MAX_PATH;
6780     lstrcpyA(path, "kiwi");
6781     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6782     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6783     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6784     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
6785 
6786     /* try SubDir2 after CostInitialize */
6787     size = MAX_PATH;
6788     lstrcpyA(path, "kiwi");
6789     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6790     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6791     ok(!lstrcmpA(path, sub2), "Expected \"%s\", got \"%s\"\n", sub2, path);
6792     ok(size == lstrlenA(sub2), "Expected %d, got %d\n", lstrlenA(sub2), size);
6793 
6794     r = MsiDoActionA(hpkg, "ResolveSource");
6795     ok(r == ERROR_SUCCESS, "file cost failed\n");
6796 
6797     /* try TARGETDIR after ResolveSource */
6798     size = MAX_PATH;
6799     lstrcpyA(path, "kiwi");
6800     r = MsiGetSourcePathA(hpkg, "TARGETDIR", 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_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6810     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6811     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6812 
6813     /* try SOURCEDIR after ResolveSource */
6814     size = MAX_PATH;
6815     lstrcpyA(path, "kiwi");
6816     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6817     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6818     ok(!lstrcmpA(path, "kiwi"),
6819        "Expected path to be unchanged, got \"%s\"\n", path);
6820     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6821 
6822     /* source path does not exist, but the property exists */
6823     size = MAX_PATH;
6824     lstrcpyA(path, "kiwi");
6825     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6826     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6827     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6828     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6829 
6830     size = MAX_PATH;
6831     lstrcpyA(path, "kiwi");
6832     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6833     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6834     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6835     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6836 
6837     /* try SubDir after ResolveSource */
6838     size = MAX_PATH;
6839     lstrcpyA(path, "kiwi");
6840     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6841     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6842     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6843     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
6844 
6845     /* try SubDir2 after ResolveSource */
6846     size = MAX_PATH;
6847     lstrcpyA(path, "kiwi");
6848     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6849     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6850     ok(!lstrcmpA(path, sub2), "Expected \"%s\", got \"%s\"\n", sub2, path);
6851     ok(size == lstrlenA(sub2), "Expected %d, got %d\n", lstrlenA(sub2), size);
6852 
6853     r = MsiDoActionA(hpkg, "FileCost");
6854     ok(r == ERROR_SUCCESS, "file cost failed\n");
6855 
6856     /* try TARGETDIR after FileCost */
6857     size = MAX_PATH;
6858     lstrcpyA(path, "kiwi");
6859     r = MsiGetSourcePathA(hpkg, "TARGETDIR", 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_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6869     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6870     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6871 
6872     /* try SOURCEDIR after FileCost */
6873     size = MAX_PATH;
6874     lstrcpyA(path, "kiwi");
6875     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6876     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6877     ok(!lstrcmpA(path, "kiwi"),
6878        "Expected path to be unchanged, got \"%s\"\n", path);
6879     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6880 
6881     /* source path does not exist, but the property exists */
6882     size = MAX_PATH;
6883     lstrcpyA(path, "kiwi");
6884     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6885     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6886     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6887     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6888 
6889     size = MAX_PATH;
6890     lstrcpyA(path, "kiwi");
6891     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6892     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6893     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6894     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6895 
6896     /* try SubDir after FileCost */
6897     size = MAX_PATH;
6898     lstrcpyA(path, "kiwi");
6899     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6900     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6901     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6902     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
6903 
6904     /* try SubDir2 after FileCost */
6905     size = MAX_PATH;
6906     lstrcpyA(path, "kiwi");
6907     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6908     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6909     ok(!lstrcmpA(path, sub2), "Expected \"%s\", got \"%s\"\n", sub2, path);
6910     ok(size == lstrlenA(sub2), "Expected %d, got %d\n", lstrlenA(sub2), size);
6911 
6912     r = MsiDoActionA(hpkg, "CostFinalize");
6913     ok(r == ERROR_SUCCESS, "file cost failed\n");
6914 
6915     /* try TARGETDIR after CostFinalize */
6916     size = MAX_PATH;
6917     lstrcpyA(path, "kiwi");
6918     r = MsiGetSourcePathA(hpkg, "TARGETDIR", 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_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6928     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6929     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6930 
6931     /* try SOURCEDIR after CostFinalize */
6932     size = MAX_PATH;
6933     lstrcpyA(path, "kiwi");
6934     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6935     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6936     ok(!lstrcmpA(path, "kiwi"),
6937        "Expected path to be unchanged, got \"%s\"\n", path);
6938     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6939 
6940     /* source path does not exist, but the property exists */
6941     size = MAX_PATH;
6942     lstrcpyA(path, "kiwi");
6943     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6944     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6945     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6946     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6947 
6948     size = MAX_PATH;
6949     lstrcpyA(path, "kiwi");
6950     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6951     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6952     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6953     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6954 
6955     /* try SubDir after CostFinalize */
6956     size = MAX_PATH;
6957     lstrcpyA(path, "kiwi");
6958     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6959     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6960     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6961     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
6962 
6963     /* try SubDir2 after CostFinalize */
6964     size = MAX_PATH;
6965     lstrcpyA(path, "kiwi");
6966     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6967     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6968     ok(!lstrcmpA(path, sub2), "Expected \"%s\", got \"%s\"\n", sub2, path);
6969     ok(size == lstrlenA(sub2), "Expected %d, got %d\n", lstrlenA(sub2), size);
6970 
6971     /* nonexistent directory */
6972     size = MAX_PATH;
6973     lstrcpyA(path, "kiwi");
6974     r = MsiGetSourcePathA(hpkg, "IDontExist", path, &size);
6975     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6976     ok(!lstrcmpA(path, "kiwi"),
6977        "Expected path to be unchanged, got \"%s\"\n", path);
6978     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6979 
6980     /* NULL szPathBuf */
6981     size = MAX_PATH;
6982     r = MsiGetSourcePathA(hpkg, "SourceDir", NULL, &size);
6983     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6984     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6985 
6986     /* NULL pcchPathBuf */
6987     lstrcpyA(path, "kiwi");
6988     r = MsiGetSourcePathA(hpkg, "SourceDir", path, NULL);
6989     ok(r == ERROR_INVALID_PARAMETER,
6990        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6991     ok(!lstrcmpA(path, "kiwi"),
6992        "Expected path to be unchanged, got \"%s\"\n", path);
6993 
6994     /* pcchPathBuf is 0 */
6995     size = 0;
6996     lstrcpyA(path, "kiwi");
6997     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6998     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
6999     ok(!lstrcmpA(path, "kiwi"),
7000        "Expected path to be unchanged, got \"%s\"\n", path);
7001     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7002 
7003     /* pcchPathBuf does not have room for NULL terminator */
7004     size = lstrlenA(cwd);
7005     lstrcpyA(path, "kiwi");
7006     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
7007     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
7008     ok(!strncmp(path, cwd, lstrlenA(cwd) - 1),
7009        "Expected path with no backslash, got \"%s\"\n", path);
7010     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7011 
7012     /* pcchPathBuf has room for NULL terminator */
7013     size = lstrlenA(cwd) + 1;
7014     lstrcpyA(path, "kiwi");
7015     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
7016     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7017     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7018     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7019 
7020     /* remove property */
7021     r = MsiSetPropertyA(hpkg, "SourceDir", NULL);
7022     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7023 
7024     /* try SourceDir again */
7025     size = MAX_PATH;
7026     lstrcpyA(path, "kiwi");
7027     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
7028     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7029     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7030     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7031 
7032     /* set property to a valid directory */
7033     r = MsiSetPropertyA(hpkg, "SOURCEDIR", cwd);
7034     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7035 
7036     /* try SOURCEDIR again */
7037     size = MAX_PATH;
7038     lstrcpyA(path, "kiwi");
7039     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7040     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7041     ok(!lstrcmpA(path, "kiwi"),
7042        "Expected path to be unchanged, got \"%s\"\n", path);
7043     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7044 
7045     MsiCloseHandle(hpkg);
7046 
7047     /* compressed source */
7048 
7049     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb);
7050     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7051 
7052     set_suminfo_prop(hdb, PID_WORDCOUNT, msidbSumInfoSourceTypeCompressed);
7053 
7054     r = package_from_db(hdb, &hpkg);
7055     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
7056 
7057     /* try TARGETDIR */
7058     size = MAX_PATH;
7059     lstrcpyA(path, "kiwi");
7060     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
7061     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7062     ok(!lstrcmpA(path, "kiwi"),
7063        "Expected path to be unchanged, got \"%s\"\n", path);
7064     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7065 
7066     /* try SourceDir */
7067     size = MAX_PATH;
7068     lstrcpyA(path, "kiwi");
7069     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
7070     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7071     ok(!lstrcmpA(path, "kiwi"),
7072        "Expected path to be unchanged, got \"%s\"\n", path);
7073     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7074 
7075     /* try SOURCEDIR */
7076     size = MAX_PATH;
7077     lstrcpyA(path, "kiwi");
7078     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7079     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7080     ok(!lstrcmpA(path, "kiwi"),
7081        "Expected path to be unchanged, got \"%s\"\n", path);
7082     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7083 
7084     /* source path nor the property exist */
7085     size = MAX_PATH;
7086     lstrcpyA(path, "kiwi");
7087     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7088     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7089     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7090     ok(size == 0, "Expected 0, got %d\n", size);
7091 
7092     size = MAX_PATH;
7093     lstrcpyA(path, "kiwi");
7094     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7095     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7096     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7097     ok(size == 0, "Expected 0, got %d\n", size);
7098 
7099     /* try SubDir */
7100     size = MAX_PATH;
7101     lstrcpyA(path, "kiwi");
7102     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7103     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7104     ok(!lstrcmpA(path, "kiwi"),
7105        "Expected path to be unchanged, got \"%s\"\n", path);
7106     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7107 
7108     /* try SubDir2 */
7109     size = MAX_PATH;
7110     lstrcpyA(path, "kiwi");
7111     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
7112     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7113     ok(!lstrcmpA(path, "kiwi"),
7114        "Expected path to be unchanged, got \"%s\"\n", path);
7115     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7116 
7117     r = MsiDoActionA(hpkg, "CostInitialize");
7118     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7119 
7120     /* try TARGETDIR after CostInitialize */
7121     size = MAX_PATH;
7122     lstrcpyA(path, "kiwi");
7123     r = MsiGetSourcePathA(hpkg, "TARGETDIR", 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     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7133     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7134     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7135 
7136     /* try SOURCEDIR after CostInitialize */
7137     size = MAX_PATH;
7138     lstrcpyA(path, "kiwi");
7139     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7140     todo_wine
7141     {
7142         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7143         ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7144         ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7145     }
7146 
7147     /* source path does not exist, but the property exists */
7148     size = MAX_PATH;
7149     lstrcpyA(path, "kiwi");
7150     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7151     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7152     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7153     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7154 
7155     size = MAX_PATH;
7156     lstrcpyA(path, "kiwi");
7157     r = MsiGetPropertyA(hpkg, "SOURCEDIR", 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 SubDir after CostInitialize */
7163     size = MAX_PATH;
7164     lstrcpyA(path, "kiwi");
7165     r = MsiGetSourcePathA(hpkg, "SubDir", 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     /* try SubDir2 after CostInitialize */
7171     size = MAX_PATH;
7172     lstrcpyA(path, "kiwi");
7173     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
7174     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7175     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7176     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7177 
7178     r = MsiDoActionA(hpkg, "ResolveSource");
7179     ok(r == ERROR_SUCCESS, "file cost failed\n");
7180 
7181     /* try TARGETDIR after ResolveSource */
7182     size = MAX_PATH;
7183     lstrcpyA(path, "kiwi");
7184     r = MsiGetSourcePathA(hpkg, "TARGETDIR", 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     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7194     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7195     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7196 
7197     /* try SOURCEDIR after ResolveSource */
7198     size = MAX_PATH;
7199     lstrcpyA(path, "kiwi");
7200     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7201     todo_wine
7202     {
7203         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7204         ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7205         ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7206     }
7207 
7208     /* source path and the property exist */
7209     size = MAX_PATH;
7210     lstrcpyA(path, "kiwi");
7211     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7212     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7213     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7214     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7215 
7216     size = MAX_PATH;
7217     lstrcpyA(path, "kiwi");
7218     r = MsiGetPropertyA(hpkg, "SOURCEDIR", 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 SubDir after ResolveSource */
7224     size = MAX_PATH;
7225     lstrcpyA(path, "kiwi");
7226     r = MsiGetSourcePathA(hpkg, "SubDir", 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     /* try SubDir2 after ResolveSource */
7232     size = MAX_PATH;
7233     lstrcpyA(path, "kiwi");
7234     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
7235     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7236     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7237     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7238 
7239     r = MsiDoActionA(hpkg, "FileCost");
7240     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7241 
7242     /* try TARGETDIR after CostFinalize */
7243     size = MAX_PATH;
7244     lstrcpyA(path, "kiwi");
7245     r = MsiGetSourcePathA(hpkg, "TARGETDIR", 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     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7255     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7256     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7257 
7258     /* try SOURCEDIR after CostFinalize */
7259     size = MAX_PATH;
7260     lstrcpyA(path, "kiwi");
7261     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7262     todo_wine
7263     {
7264         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7265         ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7266         ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7267     }
7268 
7269     /* source path and the property exist */
7270     size = MAX_PATH;
7271     lstrcpyA(path, "kiwi");
7272     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7273     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7274     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7275     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7276 
7277     size = MAX_PATH;
7278     lstrcpyA(path, "kiwi");
7279     r = MsiGetPropertyA(hpkg, "SOURCEDIR", 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 SubDir after CostFinalize */
7285     size = MAX_PATH;
7286     lstrcpyA(path, "kiwi");
7287     r = MsiGetSourcePathA(hpkg, "SubDir", 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     /* try SubDir2 after CostFinalize */
7293     size = MAX_PATH;
7294     lstrcpyA(path, "kiwi");
7295     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
7296     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7297     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7298     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7299 
7300     r = MsiDoActionA(hpkg, "CostFinalize");
7301     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7302 
7303     /* try TARGETDIR after CostFinalize */
7304     size = MAX_PATH;
7305     lstrcpyA(path, "kiwi");
7306     r = MsiGetSourcePathA(hpkg, "TARGETDIR", 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     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7316     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7317     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7318 
7319     /* try SOURCEDIR after CostFinalize */
7320     size = MAX_PATH;
7321     lstrcpyA(path, "kiwi");
7322     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7323     todo_wine
7324     {
7325         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7326         ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7327         ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7328     }
7329 
7330     /* source path and the property exist */
7331     size = MAX_PATH;
7332     lstrcpyA(path, "kiwi");
7333     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7334     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7335     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7336     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7337 
7338     size = MAX_PATH;
7339     lstrcpyA(path, "kiwi");
7340     r = MsiGetPropertyA(hpkg, "SOURCEDIR", 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 SubDir after CostFinalize */
7346     size = MAX_PATH;
7347     lstrcpyA(path, "kiwi");
7348     r = MsiGetSourcePathA(hpkg, "SubDir", 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     /* try SubDir2 after CostFinalize */
7354     size = MAX_PATH;
7355     lstrcpyA(path, "kiwi");
7356     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
7357     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7358     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7359     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7360 
7361     MsiCloseHandle(hpkg);
7362     DeleteFileA(msifile);
7363 }
7364 
7365 static void test_shortlongsource(void)
7366 {
7367     MSIHANDLE hdb, hpkg;
7368     CHAR path[MAX_PATH];
7369     CHAR cwd[MAX_PATH];
7370     CHAR subsrc[MAX_PATH];
7371     DWORD size;
7372     UINT r;
7373 
7374     lstrcpyA(cwd, CURR_DIR);
7375     if (!is_root(CURR_DIR)) lstrcatA(cwd, "\\");
7376 
7377     lstrcpyA(subsrc, cwd);
7378     lstrcatA(subsrc, "long");
7379     lstrcatA(subsrc, "\\");
7380 
7381     /* long file names */
7382 
7383     hdb = create_package_db();
7384     ok( hdb, "failed to create database\n");
7385 
7386     set_suminfo_prop(hdb, PID_WORDCOUNT, 0);
7387 
7388     r = add_directory_entry(hdb, "'TARGETDIR', '', 'SourceDir'");
7389     ok(r == S_OK, "failed\n");
7390 
7391     r = add_directory_entry(hdb, "'SubDir', 'TARGETDIR', 'short|long'");
7392     ok(r == S_OK, "failed\n");
7393 
7394     /* CostInitialize:short */
7395     r = add_directory_entry(hdb, "'SubDir2', 'TARGETDIR', 'one|two'");
7396     ok(r == S_OK, "failed\n");
7397 
7398     /* CostInitialize:long */
7399     r = add_directory_entry(hdb, "'SubDir3', 'TARGETDIR', 'three|four'");
7400     ok(r == S_OK, "failed\n");
7401 
7402     /* FileCost:short */
7403     r = add_directory_entry(hdb, "'SubDir4', 'TARGETDIR', 'five|six'");
7404     ok(r == S_OK, "failed\n");
7405 
7406     /* FileCost:long */
7407     r = add_directory_entry(hdb, "'SubDir5', 'TARGETDIR', 'seven|eight'");
7408     ok(r == S_OK, "failed\n");
7409 
7410     /* CostFinalize:short */
7411     r = add_directory_entry(hdb, "'SubDir6', 'TARGETDIR', 'nine|ten'");
7412     ok(r == S_OK, "failed\n");
7413 
7414     /* CostFinalize:long */
7415     r = add_directory_entry(hdb, "'SubDir7', 'TARGETDIR', 'eleven|twelve'");
7416     ok(r == S_OK, "failed\n");
7417 
7418     MsiDatabaseCommit(hdb);
7419 
7420     r = package_from_db(hdb, &hpkg);
7421     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
7422     {
7423         skip("Not enough rights to perform tests\n");
7424         DeleteFileA(msifile);
7425         return;
7426     }
7427     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
7428 
7429     MsiCloseHandle(hdb);
7430 
7431     CreateDirectoryA("one", NULL);
7432     CreateDirectoryA("four", NULL);
7433 
7434     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
7435 
7436     r = MsiDoActionA(hpkg, "CostInitialize");
7437     ok(r == ERROR_SUCCESS, "file cost failed\n");
7438 
7439     CreateDirectoryA("five", NULL);
7440     CreateDirectoryA("eight", NULL);
7441 
7442     r = MsiDoActionA(hpkg, "FileCost");
7443     ok(r == ERROR_SUCCESS, "file cost failed\n");
7444 
7445     CreateDirectoryA("nine", NULL);
7446     CreateDirectoryA("twelve", NULL);
7447 
7448     r = MsiDoActionA(hpkg, "CostFinalize");
7449     ok(r == ERROR_SUCCESS, "file cost failed\n");
7450 
7451     /* neither short nor long source directories exist */
7452     size = MAX_PATH;
7453     lstrcpyA(path, "kiwi");
7454     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7455     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7456     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7457     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7458 
7459     CreateDirectoryA("short", NULL);
7460 
7461     /* short source directory exists */
7462     size = MAX_PATH;
7463     lstrcpyA(path, "kiwi");
7464     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7465     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7466     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7467     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7468 
7469     CreateDirectoryA("long", NULL);
7470 
7471     /* both short and long source directories exist */
7472     size = MAX_PATH;
7473     lstrcpyA(path, "kiwi");
7474     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7475     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7476     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7477     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7478 
7479     lstrcpyA(subsrc, cwd);
7480     lstrcatA(subsrc, "two");
7481     lstrcatA(subsrc, "\\");
7482 
7483     /* short dir exists before CostInitialize */
7484     size = MAX_PATH;
7485     lstrcpyA(path, "kiwi");
7486     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
7487     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7488     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7489     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7490 
7491     lstrcpyA(subsrc, cwd);
7492     lstrcatA(subsrc, "four");
7493     lstrcatA(subsrc, "\\");
7494 
7495     /* long dir exists before CostInitialize */
7496     size = MAX_PATH;
7497     lstrcpyA(path, "kiwi");
7498     r = MsiGetSourcePathA(hpkg, "SubDir3", path, &size);
7499     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7500     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7501     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7502 
7503     lstrcpyA(subsrc, cwd);
7504     lstrcatA(subsrc, "six");
7505     lstrcatA(subsrc, "\\");
7506 
7507     /* short dir exists before FileCost */
7508     size = MAX_PATH;
7509     lstrcpyA(path, "kiwi");
7510     r = MsiGetSourcePathA(hpkg, "SubDir4", path, &size);
7511     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7512     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7513     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7514 
7515     lstrcpyA(subsrc, cwd);
7516     lstrcatA(subsrc, "eight");
7517     lstrcatA(subsrc, "\\");
7518 
7519     /* long dir exists before FileCost */
7520     size = MAX_PATH;
7521     lstrcpyA(path, "kiwi");
7522     r = MsiGetSourcePathA(hpkg, "SubDir5", path, &size);
7523     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7524     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7525     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7526 
7527     lstrcpyA(subsrc, cwd);
7528     lstrcatA(subsrc, "ten");
7529     lstrcatA(subsrc, "\\");
7530 
7531     /* short dir exists before CostFinalize */
7532     size = MAX_PATH;
7533     lstrcpyA(path, "kiwi");
7534     r = MsiGetSourcePathA(hpkg, "SubDir6", path, &size);
7535     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7536     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7537     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7538 
7539     lstrcpyA(subsrc, cwd);
7540     lstrcatA(subsrc, "twelve");
7541     lstrcatA(subsrc, "\\");
7542 
7543     /* long dir exists before CostFinalize */
7544     size = MAX_PATH;
7545     lstrcpyA(path, "kiwi");
7546     r = MsiGetSourcePathA(hpkg, "SubDir7", path, &size);
7547     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7548     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7549     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7550 
7551     MsiCloseHandle(hpkg);
7552     RemoveDirectoryA("short");
7553     RemoveDirectoryA("long");
7554     RemoveDirectoryA("one");
7555     RemoveDirectoryA("four");
7556     RemoveDirectoryA("five");
7557     RemoveDirectoryA("eight");
7558     RemoveDirectoryA("nine");
7559     RemoveDirectoryA("twelve");
7560 
7561     /* short file names */
7562 
7563     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb);
7564     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7565 
7566     set_suminfo_prop(hdb, PID_WORDCOUNT, msidbSumInfoSourceTypeSFN);
7567 
7568     r = package_from_db(hdb, &hpkg);
7569     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
7570 
7571     MsiCloseHandle(hdb);
7572 
7573     CreateDirectoryA("one", NULL);
7574     CreateDirectoryA("four", NULL);
7575 
7576     r = MsiDoActionA(hpkg, "CostInitialize");
7577     ok(r == ERROR_SUCCESS, "file cost failed\n");
7578 
7579     CreateDirectoryA("five", NULL);
7580     CreateDirectoryA("eight", NULL);
7581 
7582     r = MsiDoActionA(hpkg, "FileCost");
7583     ok(r == ERROR_SUCCESS, "file cost failed\n");
7584 
7585     CreateDirectoryA("nine", NULL);
7586     CreateDirectoryA("twelve", NULL);
7587 
7588     r = MsiDoActionA(hpkg, "CostFinalize");
7589     ok(r == ERROR_SUCCESS, "file cost failed\n");
7590 
7591     lstrcpyA(subsrc, cwd);
7592     lstrcatA(subsrc, "short");
7593     lstrcatA(subsrc, "\\");
7594 
7595     /* neither short nor long source directories exist */
7596     size = MAX_PATH;
7597     lstrcpyA(path, "kiwi");
7598     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7599     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7600     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7601     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7602 
7603     CreateDirectoryA("short", NULL);
7604 
7605     /* short source directory exists */
7606     size = MAX_PATH;
7607     lstrcpyA(path, "kiwi");
7608     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7609     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7610     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7611     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7612 
7613     CreateDirectoryA("long", NULL);
7614 
7615     /* both short and long source directories exist */
7616     size = MAX_PATH;
7617     lstrcpyA(path, "kiwi");
7618     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7619     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7620     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7621     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7622 
7623     lstrcpyA(subsrc, cwd);
7624     lstrcatA(subsrc, "one");
7625     lstrcatA(subsrc, "\\");
7626 
7627     /* short dir exists before CostInitialize */
7628     size = MAX_PATH;
7629     lstrcpyA(path, "kiwi");
7630     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
7631     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7632     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7633     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7634 
7635     lstrcpyA(subsrc, cwd);
7636     lstrcatA(subsrc, "three");
7637     lstrcatA(subsrc, "\\");
7638 
7639     /* long dir exists before CostInitialize */
7640     size = MAX_PATH;
7641     lstrcpyA(path, "kiwi");
7642     r = MsiGetSourcePathA(hpkg, "SubDir3", path, &size);
7643     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7644     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7645     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7646 
7647     lstrcpyA(subsrc, cwd);
7648     lstrcatA(subsrc, "five");
7649     lstrcatA(subsrc, "\\");
7650 
7651     /* short dir exists before FileCost */
7652     size = MAX_PATH;
7653     lstrcpyA(path, "kiwi");
7654     r = MsiGetSourcePathA(hpkg, "SubDir4", path, &size);
7655     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7656     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7657     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7658 
7659     lstrcpyA(subsrc, cwd);
7660     lstrcatA(subsrc, "seven");
7661     lstrcatA(subsrc, "\\");
7662 
7663     /* long dir exists before FileCost */
7664     size = MAX_PATH;
7665     lstrcpyA(path, "kiwi");
7666     r = MsiGetSourcePathA(hpkg, "SubDir5", path, &size);
7667     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7668     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7669     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7670 
7671     lstrcpyA(subsrc, cwd);
7672     lstrcatA(subsrc, "nine");
7673     lstrcatA(subsrc, "\\");
7674 
7675     /* short dir exists before CostFinalize */
7676     size = MAX_PATH;
7677     lstrcpyA(path, "kiwi");
7678     r = MsiGetSourcePathA(hpkg, "SubDir6", path, &size);
7679     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7680     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7681     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7682 
7683     lstrcpyA(subsrc, cwd);
7684     lstrcatA(subsrc, "eleven");
7685     lstrcatA(subsrc, "\\");
7686 
7687     /* long dir exists before CostFinalize */
7688     size = MAX_PATH;
7689     lstrcpyA(path, "kiwi");
7690     r = MsiGetSourcePathA(hpkg, "SubDir7", path, &size);
7691     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7692     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7693     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7694 
7695     MsiCloseHandle(hpkg);
7696     RemoveDirectoryA("short");
7697     RemoveDirectoryA("long");
7698     RemoveDirectoryA("one");
7699     RemoveDirectoryA("four");
7700     RemoveDirectoryA("five");
7701     RemoveDirectoryA("eight");
7702     RemoveDirectoryA("nine");
7703     RemoveDirectoryA("twelve");
7704     DeleteFileA(msifile);
7705 }
7706 
7707 static void test_sourcedir(void)
7708 {
7709     MSIHANDLE hdb, hpkg;
7710     CHAR package[12];
7711     CHAR path[MAX_PATH];
7712     CHAR cwd[MAX_PATH];
7713     CHAR subsrc[MAX_PATH];
7714     DWORD size;
7715     UINT r;
7716 
7717     lstrcpyA(cwd, CURR_DIR);
7718     if (!is_root(CURR_DIR)) lstrcatA(cwd, "\\");
7719 
7720     lstrcpyA(subsrc, cwd);
7721     lstrcatA(subsrc, "long");
7722     lstrcatA(subsrc, "\\");
7723 
7724     hdb = create_package_db();
7725     ok( hdb, "failed to create database\n");
7726 
7727     r = add_directory_entry(hdb, "'TARGETDIR', '', 'SourceDir'");
7728     ok(r == S_OK, "failed\n");
7729 
7730     sprintf(package, "#%u", hdb);
7731     r = MsiOpenPackageA(package, &hpkg);
7732     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
7733     {
7734         skip("Not enough rights to perform tests\n");
7735         goto error;
7736     }
7737     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7738 
7739     /* properties only */
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     /* SOURCEDIR prop */
7750     size = MAX_PATH;
7751     lstrcpyA(path, "kiwi");
7752     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7753     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7754     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7755     ok(size == 0, "Expected 0, got %d\n", size);
7756 
7757     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
7758 
7759     r = MsiDoActionA(hpkg, "CostInitialize");
7760     ok(r == ERROR_SUCCESS, "file cost failed\n");
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     /* SOURCEDIR after CostInitialize */
7771     size = MAX_PATH;
7772     lstrcpyA(path, "kiwi");
7773     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7774     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7775     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7776     ok(size == 0, "Expected 0, got %d\n", size);
7777 
7778     r = MsiDoActionA(hpkg, "FileCost");
7779     ok(r == ERROR_SUCCESS, "file cost failed\n");
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     /* SOURCEDIR after FileCost */
7790     size = MAX_PATH;
7791     lstrcpyA(path, "kiwi");
7792     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7793     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7794     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7795     ok(size == 0, "Expected 0, got %d\n", size);
7796 
7797     r = MsiDoActionA(hpkg, "CostFinalize");
7798     ok(r == ERROR_SUCCESS, "file cost failed\n");
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     /* SOURCEDIR after CostFinalize */
7809     size = MAX_PATH;
7810     lstrcpyA(path, "kiwi");
7811     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7812     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7813     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7814     ok(size == 0, "Expected 0, got %d\n", size);
7815 
7816     size = MAX_PATH;
7817     lstrcpyA(path, "kiwi");
7818     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7819     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7820     ok(!lstrcmpA(path, "kiwi"), "Expected \"kiwi\", got \"%s\"\n", path);
7821     ok(size == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, size);
7822 
7823     /* SOURCEDIR after calling MsiGetSourcePath */
7824     size = MAX_PATH;
7825     lstrcpyA(path, "kiwi");
7826     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7827     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7828     todo_wine {
7829     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7830     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7831     }
7832 
7833     r = MsiDoActionA(hpkg, "ResolveSource");
7834     ok(r == ERROR_SUCCESS, "file cost failed\n");
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     /* SOURCEDIR after ResolveSource */
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, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7850     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7851 
7852     /* random casing */
7853     size = MAX_PATH;
7854     lstrcpyA(path, "kiwi");
7855     r = MsiGetPropertyA(hpkg, "SoUrCeDiR", path, &size);
7856     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7857     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7858     ok(size == 0, "Expected 0, got %d\n", size);
7859 
7860     MsiCloseHandle(hpkg);
7861 
7862     /* reset the package state */
7863     sprintf(package, "#%i", hdb);
7864     r = MsiOpenPackageA(package, &hpkg);
7865     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7866 
7867     /* test how MsiGetSourcePath affects the properties */
7868 
7869     /* SourceDir prop */
7870     size = MAX_PATH;
7871     lstrcpyA(path, "kiwi");
7872     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7873     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7874     todo_wine
7875     {
7876         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7877         ok(size == 0, "Expected 0, got %d\n", size);
7878     }
7879 
7880     size = MAX_PATH;
7881     lstrcpyA(path, "kiwi");
7882     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
7883     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7884     ok(!lstrcmpA(path, "kiwi"),
7885        "Expected path to be unchanged, got \"%s\"\n", path);
7886     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7887 
7888     /* SourceDir after MsiGetSourcePath */
7889     size = MAX_PATH;
7890     lstrcpyA(path, "kiwi");
7891     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7892     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7893     todo_wine
7894     {
7895         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7896         ok(size == 0, "Expected 0, got %d\n", size);
7897     }
7898 
7899     /* SOURCEDIR prop */
7900     size = MAX_PATH;
7901     lstrcpyA(path, "kiwi");
7902     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7903     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7904     todo_wine
7905     {
7906         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7907         ok(size == 0, "Expected 0, got %d\n", size);
7908     }
7909 
7910     size = MAX_PATH;
7911     lstrcpyA(path, "kiwi");
7912     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7913     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7914     ok(!lstrcmpA(path, "kiwi"),
7915        "Expected path to be unchanged, got \"%s\"\n", path);
7916     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7917 
7918     /* SOURCEDIR prop after MsiGetSourcePath */
7919     size = MAX_PATH;
7920     lstrcpyA(path, "kiwi");
7921     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7922     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7923     todo_wine
7924     {
7925         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7926         ok(size == 0, "Expected 0, got %d\n", size);
7927     }
7928 
7929     r = MsiDoActionA(hpkg, "CostInitialize");
7930     ok(r == ERROR_SUCCESS, "file cost failed\n");
7931 
7932     /* SourceDir after CostInitialize */
7933     size = MAX_PATH;
7934     lstrcpyA(path, "kiwi");
7935     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7936     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7937     todo_wine
7938     {
7939         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7940         ok(size == 0, "Expected 0, got %d\n", size);
7941     }
7942 
7943     size = MAX_PATH;
7944     lstrcpyA(path, "kiwi");
7945     r = MsiGetSourcePathA(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 MsiGetSourcePath */
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 after CostInitialize */
7959     size = MAX_PATH;
7960     lstrcpyA(path, "kiwi");
7961     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7962     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7963     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7964     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7965 
7966     /* SOURCEDIR source path still does not exist */
7967     size = MAX_PATH;
7968     lstrcpyA(path, "kiwi");
7969     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7970     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7971     ok(!lstrcmpA(path, "kiwi"),
7972        "Expected path to be unchanged, got \"%s\"\n", path);
7973     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7974 
7975     r = MsiDoActionA(hpkg, "FileCost");
7976     ok(r == ERROR_SUCCESS, "file cost failed\n");
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 after FileCost */
7987     size = MAX_PATH;
7988     lstrcpyA(path, "kiwi");
7989     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7990     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7991     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7992     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7993 
7994     /* SOURCEDIR source path still does not exist */
7995     size = MAX_PATH;
7996     lstrcpyA(path, "kiwi");
7997     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7998     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7999     ok(!lstrcmpA(path, "kiwi"),
8000        "Expected path to be unchanged, got \"%s\"\n", path);
8001     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8002 
8003     r = MsiDoActionA(hpkg, "CostFinalize");
8004     ok(r == ERROR_SUCCESS, "file cost failed\n");
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 after CostFinalize */
8015     size = MAX_PATH;
8016     lstrcpyA(path, "kiwi");
8017     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
8018     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8019     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
8020     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
8021 
8022     /* SOURCEDIR source path still does not exist */
8023     size = MAX_PATH;
8024     lstrcpyA(path, "kiwi");
8025     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
8026     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
8027     ok(!lstrcmpA(path, "kiwi"),
8028        "Expected path to be unchanged, got \"%s\"\n", path);
8029     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8030 
8031     r = MsiDoActionA(hpkg, "ResolveSource");
8032     ok(r == ERROR_SUCCESS, "file cost failed\n");
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 after ResolveSource */
8043     size = MAX_PATH;
8044     lstrcpyA(path, "kiwi");
8045     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
8046     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8047     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
8048     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
8049 
8050     /* SOURCEDIR source path still does not exist */
8051     size = MAX_PATH;
8052     lstrcpyA(path, "kiwi");
8053     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
8054     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
8055     ok(!lstrcmpA(path, "kiwi"),
8056        "Expected path to be unchanged, got \"%s\"\n", path);
8057     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8058 
8059     MsiCloseHandle(hpkg);
8060 
8061 error:
8062     MsiCloseHandle(hdb);
8063     DeleteFileA(msifile);
8064 }
8065 
8066 struct access_res
8067 {
8068     BOOL gothandle;
8069     DWORD lasterr;
8070     BOOL ignore;
8071 };
8072 
8073 static const struct access_res create[16] =
8074 {
8075     { TRUE, ERROR_SUCCESS, TRUE },
8076     { TRUE, ERROR_SUCCESS, TRUE },
8077     { TRUE, ERROR_SUCCESS, FALSE },
8078     { TRUE, ERROR_SUCCESS, FALSE },
8079     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
8080     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
8081     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
8082     { TRUE, ERROR_SUCCESS, FALSE },
8083     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
8084     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
8085     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
8086     { TRUE, ERROR_SUCCESS, TRUE },
8087     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
8088     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
8089     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
8090     { TRUE, ERROR_SUCCESS, TRUE }
8091 };
8092 
8093 static const struct access_res create_commit[16] =
8094 {
8095     { TRUE, ERROR_SUCCESS, TRUE },
8096     { TRUE, ERROR_SUCCESS, TRUE },
8097     { TRUE, ERROR_SUCCESS, FALSE },
8098     { TRUE, ERROR_SUCCESS, FALSE },
8099     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
8100     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
8101     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
8102     { TRUE, ERROR_SUCCESS, FALSE },
8103     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
8104     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
8105     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
8106     { TRUE, ERROR_SUCCESS, TRUE },
8107     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
8108     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
8109     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
8110     { TRUE, ERROR_SUCCESS, TRUE }
8111 };
8112 
8113 static const struct access_res create_close[16] =
8114 {
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, FALSE },
8123     { TRUE, ERROR_SUCCESS, FALSE },
8124     { TRUE, ERROR_SUCCESS, FALSE },
8125     { TRUE, ERROR_SUCCESS, FALSE },
8126     { TRUE, ERROR_SUCCESS, FALSE },
8127     { TRUE, ERROR_SUCCESS, FALSE },
8128     { TRUE, ERROR_SUCCESS, FALSE },
8129     { TRUE, ERROR_SUCCESS, FALSE },
8130     { TRUE, ERROR_SUCCESS }
8131 };
8132 
8133 static void _test_file_access(LPCSTR file, const struct access_res *ares, DWORD line)
8134 {
8135     DWORD access = 0, share = 0;
8136     DWORD lasterr;
8137     HANDLE hfile;
8138     int i, j, idx = 0;
8139 
8140     for (i = 0; i < 4; i++)
8141     {
8142         if (i == 0) access = 0;
8143         if (i == 1) access = GENERIC_READ;
8144         if (i == 2) access = GENERIC_WRITE;
8145         if (i == 3) access = GENERIC_READ | GENERIC_WRITE;
8146 
8147         for (j = 0; j < 4; j++)
8148         {
8149             if (ares[idx].ignore)
8150                 continue;
8151 
8152             if (j == 0) share = 0;
8153             if (j == 1) share = FILE_SHARE_READ;
8154             if (j == 2) share = FILE_SHARE_WRITE;
8155             if (j == 3) share = FILE_SHARE_READ | FILE_SHARE_WRITE;
8156 
8157             SetLastError(0xdeadbeef);
8158             hfile = CreateFileA(file, access, share, NULL, OPEN_EXISTING,
8159                                 FILE_ATTRIBUTE_NORMAL, 0);
8160             lasterr = GetLastError();
8161 
8162             ok((hfile != INVALID_HANDLE_VALUE) == ares[idx].gothandle,
8163                "(%d, handle, %d): Expected %d, got %d\n",
8164                line, idx, ares[idx].gothandle,
8165                (hfile != INVALID_HANDLE_VALUE));
8166 
8167             ok(lasterr == ares[idx].lasterr, "(%d, lasterr, %d): Expected %d, got %d\n",
8168                line, idx, ares[idx].lasterr, lasterr);
8169 
8170             CloseHandle(hfile);
8171             idx++;
8172         }
8173     }
8174 }
8175 
8176 #define test_file_access(file, ares) _test_file_access(file, ares, __LINE__)
8177 
8178 static void test_access(void)
8179 {
8180     MSIHANDLE hdb;
8181     UINT r;
8182 
8183     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
8184     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8185 
8186     test_file_access(msifile, create);
8187 
8188     r = MsiDatabaseCommit(hdb);
8189     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8190 
8191     test_file_access(msifile, create_commit);
8192     MsiCloseHandle(hdb);
8193 
8194     test_file_access(msifile, create_close);
8195     DeleteFileA(msifile);
8196 
8197     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATEDIRECT, &hdb);
8198     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8199 
8200     test_file_access(msifile, create);
8201 
8202     r = MsiDatabaseCommit(hdb);
8203     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8204 
8205     test_file_access(msifile, create_commit);
8206     MsiCloseHandle(hdb);
8207 
8208     test_file_access(msifile, create_close);
8209     DeleteFileA(msifile);
8210 }
8211 
8212 static void test_emptypackage(void)
8213 {
8214     MSIHANDLE hpkg = 0, hdb = 0, hsuminfo = 0;
8215     MSIHANDLE hview = 0, hrec = 0;
8216     MSICONDITION condition;
8217     CHAR buffer[MAX_PATH];
8218     DWORD size;
8219     UINT r;
8220 
8221     r = MsiOpenPackageA("", &hpkg);
8222     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
8223     {
8224         skip("Not enough rights to perform tests\n");
8225         return;
8226     }
8227     todo_wine
8228     {
8229         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8230     }
8231 
8232     hdb = MsiGetActiveDatabase(hpkg);
8233     todo_wine
8234     {
8235         ok(hdb != 0, "Expected a valid database handle\n");
8236     }
8237 
8238     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Tables`", &hview);
8239     todo_wine
8240     {
8241         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8242     }
8243     r = MsiViewExecute(hview, 0);
8244     todo_wine
8245     {
8246         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8247     }
8248 
8249     r = MsiViewFetch(hview, &hrec);
8250     todo_wine
8251     {
8252         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8253     }
8254 
8255     buffer[0] = 0;
8256     size = MAX_PATH;
8257     r = MsiRecordGetStringA(hrec, 1, buffer, &size);
8258     todo_wine
8259     {
8260         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8261         ok(!lstrcmpA(buffer, "_Property"),
8262            "Expected \"_Property\", got \"%s\"\n", buffer);
8263     }
8264 
8265     MsiCloseHandle(hrec);
8266 
8267     r = MsiViewFetch(hview, &hrec);
8268     todo_wine
8269     {
8270         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8271     }
8272 
8273     size = MAX_PATH;
8274     r = MsiRecordGetStringA(hrec, 1, buffer, &size);
8275     todo_wine
8276     {
8277         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8278         ok(!lstrcmpA(buffer, "#_FolderCache"),
8279            "Expected \"_Property\", got \"%s\"\n", buffer);
8280     }
8281 
8282     MsiCloseHandle(hrec);
8283     MsiViewClose(hview);
8284     MsiCloseHandle(hview);
8285 
8286     condition = MsiDatabaseIsTablePersistentA(hdb, "_Property");
8287     todo_wine
8288     {
8289         ok(condition == MSICONDITION_FALSE,
8290            "Expected MSICONDITION_FALSE, got %d\n", condition);
8291     }
8292 
8293     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Property`", &hview);
8294     todo_wine
8295     {
8296         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8297     }
8298     r = MsiViewExecute(hview, 0);
8299     todo_wine
8300     {
8301         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8302     }
8303 
8304     /* _Property table is not empty */
8305     r = MsiViewFetch(hview, &hrec);
8306     todo_wine
8307     {
8308         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8309     }
8310 
8311     MsiCloseHandle(hrec);
8312     MsiViewClose(hview);
8313     MsiCloseHandle(hview);
8314 
8315     condition = MsiDatabaseIsTablePersistentA(hdb, "#_FolderCache");
8316     todo_wine
8317     {
8318         ok(condition == MSICONDITION_FALSE,
8319            "Expected MSICONDITION_FALSE, got %d\n", condition);
8320     }
8321 
8322     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `#_FolderCache`", &hview);
8323     todo_wine
8324     {
8325         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8326     }
8327     r = MsiViewExecute(hview, 0);
8328     todo_wine
8329     {
8330         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8331     }
8332 
8333     /* #_FolderCache is not empty */
8334     r = MsiViewFetch(hview, &hrec);
8335     todo_wine
8336     {
8337         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8338     }
8339 
8340     MsiCloseHandle(hrec);
8341     MsiViewClose(hview);
8342     MsiCloseHandle(hview);
8343 
8344     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Streams`", &hview);
8345     todo_wine
8346     {
8347         ok(r == ERROR_BAD_QUERY_SYNTAX,
8348            "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8349     }
8350 
8351     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Storages`", &hview);
8352     todo_wine
8353     {
8354         ok(r == ERROR_BAD_QUERY_SYNTAX,
8355            "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8356     }
8357 
8358     r = MsiGetSummaryInformationA(hdb, NULL, 0, &hsuminfo);
8359     todo_wine
8360     {
8361         ok(r == ERROR_INSTALL_PACKAGE_INVALID,
8362            "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
8363     }
8364 
8365     MsiCloseHandle(hsuminfo);
8366 
8367     r = MsiDatabaseCommit(hdb);
8368     todo_wine
8369     {
8370         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8371     }
8372 
8373     MsiCloseHandle(hdb);
8374     MsiCloseHandle(hpkg);
8375 }
8376 
8377 static void test_MsiGetProductProperty(void)
8378 {
8379     static const WCHAR prodcode_propW[] = {'P','r','o','d','u','c','t','C','o','d','e',0};
8380     static const WCHAR nonexistentW[] = {'I','D','o','n','t','E','x','i','s','t',0};
8381     static const WCHAR newpropW[] = {'N','e','w','P','r','o','p','e','r','t','y',0};
8382     static const WCHAR appleW[] = {'a','p','p','l','e',0};
8383     static const WCHAR emptyW[] = {0};
8384     WCHAR valW[MAX_PATH];
8385     MSIHANDLE hprod, hdb;
8386     CHAR val[MAX_PATH];
8387     CHAR path[MAX_PATH];
8388     CHAR query[MAX_PATH];
8389     CHAR keypath[MAX_PATH*2];
8390     CHAR prodcode[MAX_PATH];
8391     WCHAR prodcodeW[MAX_PATH];
8392     CHAR prod_squashed[MAX_PATH];
8393     WCHAR prod_squashedW[MAX_PATH];
8394     HKEY prodkey, userkey, props;
8395     DWORD size;
8396     LONG res;
8397     UINT r;
8398     REGSAM access = KEY_ALL_ACCESS;
8399 
8400     GetCurrentDirectoryA(MAX_PATH, path);
8401     lstrcatA(path, "\\");
8402 
8403     create_test_guid(prodcode, prod_squashed);
8404     MultiByteToWideChar(CP_ACP, 0, prodcode, -1, prodcodeW, MAX_PATH);
8405     squash_guid(prodcodeW, prod_squashedW);
8406 
8407     if (is_wow64)
8408         access |= KEY_WOW64_64KEY;
8409 
8410     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
8411     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8412 
8413     r = MsiDatabaseCommit(hdb);
8414     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8415 
8416     r = set_summary_info(hdb);
8417     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8418 
8419     r = run_query(hdb,
8420             "CREATE TABLE `Directory` ( "
8421             "`Directory` CHAR(255) NOT NULL, "
8422             "`Directory_Parent` CHAR(255), "
8423             "`DefaultDir` CHAR(255) NOT NULL "
8424             "PRIMARY KEY `Directory`)");
8425     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8426 
8427     r = run_query(hdb,
8428             "CREATE TABLE `Property` ( "
8429             "`Property` CHAR(72) NOT NULL, "
8430             "`Value` CHAR(255) "
8431             "PRIMARY KEY `Property`)");
8432     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8433 
8434     sprintf(query, "INSERT INTO `Property` "
8435             "(`Property`, `Value`) "
8436             "VALUES( 'ProductCode', '%s' )", prodcode);
8437     r = run_query(hdb, query);
8438     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8439 
8440     r = MsiDatabaseCommit(hdb);
8441     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8442 
8443     MsiCloseHandle(hdb);
8444 
8445     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
8446     lstrcatA(keypath, prod_squashed);
8447 
8448     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
8449     if (res == ERROR_ACCESS_DENIED)
8450     {
8451         skip("Not enough rights to perform tests\n");
8452         DeleteFileA(msifile);
8453         return;
8454     }
8455     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8456 
8457     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
8458     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
8459     lstrcatA(keypath, prod_squashed);
8460 
8461     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
8462     if (res == ERROR_ACCESS_DENIED)
8463     {
8464         skip("Not enough rights to perform tests\n");
8465         RegDeleteKeyA(prodkey, "");
8466         RegCloseKey(prodkey);
8467         return;
8468     }
8469     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8470 
8471     res = RegCreateKeyExA(userkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
8472     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8473 
8474     lstrcpyA(val, path);
8475     lstrcatA(val, "\\");
8476     lstrcatA(val, msifile);
8477     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
8478                          (const BYTE *)val, lstrlenA(val) + 1);
8479     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8480 
8481     hprod = 0xdeadbeef;
8482     r = MsiOpenProductA(prodcode, &hprod);
8483     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8484     ok(hprod != 0 && hprod != 0xdeadbeef, "Expected a valid product handle\n");
8485 
8486     /* hProduct is invalid */
8487     size = MAX_PATH;
8488     lstrcpyA(val, "apple");
8489     r = MsiGetProductPropertyA(0xdeadbeef, "ProductCode", val, &size);
8490     ok(r == ERROR_INVALID_HANDLE,
8491        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
8492     ok(!lstrcmpA(val, "apple"),
8493        "Expected val to be unchanged, got \"%s\"\n", val);
8494     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8495 
8496     size = MAX_PATH;
8497     lstrcpyW(valW, appleW);
8498     r = MsiGetProductPropertyW(0xdeadbeef, prodcode_propW, valW, &size);
8499     ok(r == ERROR_INVALID_HANDLE,
8500        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
8501     ok(!lstrcmpW(valW, appleW),
8502        "Expected val to be unchanged, got %s\n", wine_dbgstr_w(valW));
8503     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8504 
8505     /* szProperty is NULL */
8506     size = MAX_PATH;
8507     lstrcpyA(val, "apple");
8508     r = MsiGetProductPropertyA(hprod, NULL, val, &size);
8509     ok(r == ERROR_INVALID_PARAMETER,
8510        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8511     ok(!lstrcmpA(val, "apple"),
8512        "Expected val to be unchanged, got \"%s\"\n", val);
8513     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8514 
8515     size = MAX_PATH;
8516     lstrcpyW(valW, appleW);
8517     r = MsiGetProductPropertyW(hprod, NULL, valW, &size);
8518     ok(r == ERROR_INVALID_PARAMETER,
8519        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8520     ok(!lstrcmpW(valW, appleW),
8521        "Expected val to be unchanged, got %s\n", wine_dbgstr_w(valW));
8522     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8523 
8524     /* szProperty is empty */
8525     size = MAX_PATH;
8526     lstrcpyA(val, "apple");
8527     r = MsiGetProductPropertyA(hprod, "", val, &size);
8528     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8529     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
8530     ok(size == 0, "Expected 0, got %d\n", size);
8531 
8532     size = MAX_PATH;
8533     lstrcpyW(valW, appleW);
8534     r = MsiGetProductPropertyW(hprod, emptyW, valW, &size);
8535     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8536     ok(*valW == 0, "Expected \"\", got %s\n", wine_dbgstr_w(valW));
8537     ok(size == 0, "Expected 0, got %d\n", size);
8538 
8539     /* get the property */
8540     size = MAX_PATH;
8541     lstrcpyA(val, "apple");
8542     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8543     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8544     ok(!lstrcmpA(val, prodcode),
8545        "Expected \"%s\", got \"%s\"\n", prodcode, val);
8546     ok(size == lstrlenA(prodcode),
8547        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8548 
8549     size = MAX_PATH;
8550     lstrcpyW(valW, appleW);
8551     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, &size);
8552     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8553     ok(!lstrcmpW(valW, prodcodeW),
8554        "Expected %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8555     ok(size == lstrlenW(prodcodeW),
8556        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8557 
8558     /* lpValueBuf is NULL */
8559     size = MAX_PATH;
8560     r = MsiGetProductPropertyA(hprod, "ProductCode", NULL, &size);
8561     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8562     ok(size == lstrlenA(prodcode),
8563        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8564 
8565     size = MAX_PATH;
8566     r = MsiGetProductPropertyW(hprod, prodcode_propW, NULL, &size);
8567     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8568     ok(size == lstrlenW(prodcodeW),
8569        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8570 
8571     /* pcchValueBuf is NULL */
8572     lstrcpyA(val, "apple");
8573     r = MsiGetProductPropertyA(hprod, "ProductCode", val, NULL);
8574     ok(r == ERROR_INVALID_PARAMETER,
8575        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8576     ok(!lstrcmpA(val, "apple"),
8577        "Expected val to be unchanged, got \"%s\"\n", val);
8578     ok(size == lstrlenA(prodcode),
8579        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8580 
8581     lstrcpyW(valW, appleW);
8582     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, NULL);
8583     ok(r == ERROR_INVALID_PARAMETER,
8584        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8585     ok(!lstrcmpW(valW, appleW),
8586        "Expected val to be unchanged, got %s\n", wine_dbgstr_w(valW));
8587     ok(size == lstrlenW(prodcodeW),
8588        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8589 
8590     /* pcchValueBuf is too small */
8591     size = 4;
8592     lstrcpyA(val, "apple");
8593     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8594     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
8595     ok(!strncmp(val, prodcode, 3),
8596        "Expected first 3 chars of \"%s\", got \"%s\"\n", prodcode, val);
8597     ok(size == lstrlenA(prodcode),
8598        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8599 
8600     size = 4;
8601     lstrcpyW(valW, appleW);
8602     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, &size);
8603     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
8604     ok(!memcmp(valW, prodcodeW, 3 * sizeof(WCHAR)),
8605        "Expected first 3 chars of %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8606     ok(size == lstrlenW(prodcodeW),
8607        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8608 
8609     /* pcchValueBuf does not leave room for NULL terminator */
8610     size = lstrlenA(prodcode);
8611     lstrcpyA(val, "apple");
8612     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8613     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
8614     ok(!strncmp(val, prodcode, lstrlenA(prodcode) - 1),
8615        "Expected first 37 chars of \"%s\", got \"%s\"\n", prodcode, val);
8616     ok(size == lstrlenA(prodcode),
8617        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8618 
8619     size = lstrlenW(prodcodeW);
8620     lstrcpyW(valW, appleW);
8621     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, &size);
8622     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
8623     ok(!memcmp(valW, prodcodeW, lstrlenW(prodcodeW) - 1),
8624        "Expected first 37 chars of %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8625     ok(size == lstrlenW(prodcodeW),
8626        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8627 
8628     /* pcchValueBuf has enough room for NULL terminator */
8629     size = lstrlenA(prodcode) + 1;
8630     lstrcpyA(val, "apple");
8631     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8632     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8633     ok(!lstrcmpA(val, prodcode),
8634        "Expected \"%s\", got \"%s\"\n", prodcode, val);
8635     ok(size == lstrlenA(prodcode),
8636        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8637 
8638     size = lstrlenW(prodcodeW) + 1;
8639     lstrcpyW(valW, appleW);
8640     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, &size);
8641     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8642     ok(!lstrcmpW(valW, prodcodeW),
8643        "Expected %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8644     ok(size == lstrlenW(prodcodeW),
8645        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8646 
8647     /* nonexistent property */
8648     size = MAX_PATH;
8649     lstrcpyA(val, "apple");
8650     r = MsiGetProductPropertyA(hprod, "IDontExist", val, &size);
8651     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8652     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
8653     ok(size == 0, "Expected 0, got %d\n", size);
8654 
8655     size = MAX_PATH;
8656     lstrcpyW(valW, appleW);
8657     r = MsiGetProductPropertyW(hprod, nonexistentW, valW, &size);
8658     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8659     ok(!lstrcmpW(valW, emptyW), "Expected \"\", got %s\n", wine_dbgstr_w(valW));
8660     ok(size == 0, "Expected 0, got %d\n", size);
8661 
8662     r = MsiSetPropertyA(hprod, "NewProperty", "value");
8663     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8664 
8665     /* non-product property set */
8666     size = MAX_PATH;
8667     lstrcpyA(val, "apple");
8668     r = MsiGetProductPropertyA(hprod, "NewProperty", val, &size);
8669     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8670     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
8671     ok(size == 0, "Expected 0, got %d\n", size);
8672 
8673     size = MAX_PATH;
8674     lstrcpyW(valW, appleW);
8675     r = MsiGetProductPropertyW(hprod, newpropW, valW, &size);
8676     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8677     ok(!lstrcmpW(valW, emptyW), "Expected \"\", got %s\n", wine_dbgstr_w(valW));
8678     ok(size == 0, "Expected 0, got %d\n", size);
8679 
8680     r = MsiSetPropertyA(hprod, "ProductCode", "value");
8681     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8682 
8683     /* non-product property that is also a product property set */
8684     size = MAX_PATH;
8685     lstrcpyA(val, "apple");
8686     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8687     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8688     ok(!lstrcmpA(val, prodcode),
8689        "Expected \"%s\", got \"%s\"\n", prodcode, val);
8690     ok(size == lstrlenA(prodcode),
8691        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8692 
8693     size = MAX_PATH;
8694     lstrcpyW(valW, appleW);
8695     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, &size);
8696     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8697     ok(!lstrcmpW(valW, prodcodeW),
8698        "Expected %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8699     ok(size == lstrlenW(prodcodeW),
8700        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8701 
8702     MsiCloseHandle(hprod);
8703 
8704     RegDeleteValueA(props, "LocalPackage");
8705     delete_key(props, "", access);
8706     RegCloseKey(props);
8707     delete_key(userkey, "", access);
8708     RegCloseKey(userkey);
8709     delete_key(prodkey, "", access);
8710     RegCloseKey(prodkey);
8711     DeleteFileA(msifile);
8712 }
8713 
8714 static void test_MsiSetProperty(void)
8715 {
8716     MSIHANDLE hpkg, hdb, hrec;
8717     CHAR buf[MAX_PATH];
8718     LPCSTR query;
8719     DWORD size;
8720     UINT r;
8721 
8722     r = package_from_db(create_package_db(), &hpkg);
8723     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
8724     {
8725         skip("Not enough rights to perform tests\n");
8726         DeleteFileA(msifile);
8727         return;
8728     }
8729     ok(r == ERROR_SUCCESS, "Expected a valid package %u\n", r);
8730 
8731     /* invalid hInstall */
8732     r = MsiSetPropertyA(0, "Prop", "Val");
8733     ok(r == ERROR_INVALID_HANDLE,
8734        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
8735 
8736     /* invalid hInstall */
8737     r = MsiSetPropertyA(0xdeadbeef, "Prop", "Val");
8738     ok(r == ERROR_INVALID_HANDLE,
8739        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
8740 
8741     /* szName is NULL */
8742     r = MsiSetPropertyA(hpkg, NULL, "Val");
8743     ok(r == ERROR_INVALID_PARAMETER,
8744        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8745 
8746     /* both szName and szValue are NULL */
8747     r = MsiSetPropertyA(hpkg, NULL, NULL);
8748     ok(r == ERROR_INVALID_PARAMETER,
8749        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8750 
8751     /* szName is empty */
8752     r = MsiSetPropertyA(hpkg, "", "Val");
8753     ok(r == ERROR_FUNCTION_FAILED,
8754        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
8755 
8756     /* szName is empty and szValue is NULL */
8757     r = MsiSetPropertyA(hpkg, "", NULL);
8758     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8759 
8760     /* set a property */
8761     r = MsiSetPropertyA(hpkg, "Prop", "Val");
8762     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8763 
8764     /* get the property */
8765     size = MAX_PATH;
8766     r = MsiGetPropertyA(hpkg, "Prop", buf, &size);
8767     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8768     ok(!lstrcmpA(buf, "Val"), "Expected \"Val\", got \"%s\"\n", buf);
8769     ok(size == 3, "Expected 3, got %d\n", size);
8770 
8771     /* update the property */
8772     r = MsiSetPropertyA(hpkg, "Prop", "Nuvo");
8773     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8774 
8775     /* get the property */
8776     size = MAX_PATH;
8777     r = MsiGetPropertyA(hpkg, "Prop", buf, &size);
8778     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8779     ok(!lstrcmpA(buf, "Nuvo"), "Expected \"Nuvo\", got \"%s\"\n", buf);
8780     ok(size == 4, "Expected 4, got %d\n", size);
8781 
8782     hdb = MsiGetActiveDatabase(hpkg);
8783     ok(hdb != 0, "Expected a valid database handle\n");
8784 
8785     /* set prop is not in the _Property table */
8786     query = "SELECT * FROM `_Property` WHERE `Property` = 'Prop'";
8787     r = do_query(hdb, query, &hrec);
8788     ok(r == ERROR_BAD_QUERY_SYNTAX,
8789        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8790 
8791     /* set prop is not in the Property table */
8792     query = "SELECT * FROM `Property` WHERE `Property` = 'Prop'";
8793     r = do_query(hdb, query, &hrec);
8794     ok(r == ERROR_BAD_QUERY_SYNTAX,
8795        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8796 
8797     MsiCloseHandle(hdb);
8798 
8799     /* szValue is an empty string */
8800     r = MsiSetPropertyA(hpkg, "Prop", "");
8801     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8802 
8803     /* try to get the property */
8804     size = MAX_PATH;
8805     r = MsiGetPropertyA(hpkg, "Prop", buf, &size);
8806     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8807     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
8808     ok(size == 0, "Expected 0, got %d\n", size);
8809 
8810     /* reset the property */
8811     r = MsiSetPropertyA(hpkg, "Prop", "BlueTap");
8812     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8813 
8814     /* delete the property */
8815     r = MsiSetPropertyA(hpkg, "Prop", NULL);
8816     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8817 
8818     /* try to get the property */
8819     size = MAX_PATH;
8820     r = MsiGetPropertyA(hpkg, "Prop", buf, &size);
8821     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8822     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
8823     ok(size == 0, "Expected 0, got %d\n", size);
8824 
8825     MsiCloseHandle(hpkg);
8826     DeleteFileA(msifile);
8827 }
8828 
8829 static void test_MsiApplyMultiplePatches(void)
8830 {
8831     UINT r, type = GetDriveTypeW(NULL);
8832 
8833     r = MsiApplyMultiplePatchesA(NULL, NULL, NULL);
8834     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
8835 
8836     r = MsiApplyMultiplePatchesA("", NULL, NULL);
8837     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
8838 
8839     r = MsiApplyMultiplePatchesA(";", NULL, NULL);
8840     if (type == DRIVE_FIXED)
8841         todo_wine ok(r == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %u\n", r);
8842     else
8843         ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
8844 
8845     r = MsiApplyMultiplePatchesA("  ;", NULL, NULL);
8846     if (type == DRIVE_FIXED)
8847         todo_wine ok(r == ERROR_PATCH_PACKAGE_OPEN_FAILED, "Expected ERROR_PATCH_PACKAGE_OPEN_FAILED, got %u\n", r);
8848     else
8849         ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
8850 
8851     r = MsiApplyMultiplePatchesA(";;", NULL, NULL);
8852     if (type == DRIVE_FIXED)
8853         todo_wine ok(r == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %u\n", r);
8854     else
8855         ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
8856 
8857     r = MsiApplyMultiplePatchesA("nosuchpatchpackage;", NULL, NULL);
8858     todo_wine ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
8859 
8860     r = MsiApplyMultiplePatchesA(";nosuchpatchpackage", NULL, NULL);
8861     if (type == DRIVE_FIXED)
8862         todo_wine ok(r == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %u\n", r);
8863     else
8864         ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
8865 
8866     r = MsiApplyMultiplePatchesA("nosuchpatchpackage;nosuchpatchpackage", NULL, NULL);
8867     todo_wine ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
8868 
8869     r = MsiApplyMultiplePatchesA("  nosuchpatchpackage  ;  nosuchpatchpackage  ", NULL, NULL);
8870     todo_wine ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
8871 }
8872 
8873 static void test_MsiApplyPatch(void)
8874 {
8875     UINT r;
8876 
8877     r = MsiApplyPatchA(NULL, NULL, INSTALLTYPE_DEFAULT, NULL);
8878     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
8879 
8880     r = MsiApplyPatchA("", NULL, INSTALLTYPE_DEFAULT, NULL);
8881     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
8882 }
8883 
8884 static void test_MsiEnumComponentCosts(void)
8885 {
8886     MSIHANDLE hdb, hpkg;
8887     char package[12], drive[3];
8888     DWORD len;
8889     UINT r;
8890     int cost, temp;
8891 
8892     hdb = create_package_db();
8893     ok( hdb, "failed to create database\n" );
8894 
8895     r = create_property_table( hdb );
8896     ok( r == ERROR_SUCCESS, "cannot create Property table %u\n", r );
8897 
8898     r = add_property_entry( hdb, "'ProductCode', '{379B1C47-40C1-42FA-A9BB-BEBB6F1B0172}'" );
8899     ok( r == ERROR_SUCCESS, "cannot add property entry %u\n", r );
8900 
8901     r = add_property_entry( hdb, "'MSIFASTINSTALL', '1'" );
8902     ok( r == ERROR_SUCCESS, "cannot add property entry %u\n", r );
8903 
8904     r = add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'" );
8905     ok( r == ERROR_SUCCESS, "failed to add directory entry %u\n" , r );
8906 
8907     r = create_media_table( hdb );
8908     ok( r == ERROR_SUCCESS, "cannot create Media table %u\n", r );
8909 
8910     r = add_media_entry( hdb, "'1', '2', 'cabinet', '', '', ''");
8911     ok( r == ERROR_SUCCESS, "cannot add media entry %u\n", r );
8912 
8913     r = create_file_table( hdb );
8914     ok( r == ERROR_SUCCESS, "cannot create File table %u\n", r );
8915 
8916     r = add_file_entry( hdb, "'one.txt', 'one', 'one.txt', 4096, '', '', 8192, 1" );
8917     ok( r == ERROR_SUCCESS, "cannot add file %u\n", r );
8918 
8919     r = create_component_table( hdb );
8920     ok( r == ERROR_SUCCESS, "cannot create Component table %u\n", r );
8921 
8922     r = add_component_entry( hdb, "'one', '{B2F86B9D-8447-4BC5-8883-750C45AA31CA}', 'TARGETDIR', 0, '', 'one.txt'" );
8923     ok( r == ERROR_SUCCESS, "cannot add component %u\n", r );
8924 
8925     r = add_component_entry( hdb, "'two', '{62A09F6E-0B74-4829-BDB7-CAB66F42CCE8}', 'TARGETDIR', 0, '', ''" );
8926     ok( r == ERROR_SUCCESS, "cannot add component %u\n", r );
8927 
8928     r = create_feature_table( hdb );
8929     ok( r == ERROR_SUCCESS, "cannot create Feature table %u\n", r );
8930 
8931     r = add_feature_entry( hdb, "'one', '', '', '', 0, 1, '', 0" );
8932     ok( r == ERROR_SUCCESS, "cannot add feature %u\n", r );
8933 
8934     r = add_feature_entry( hdb, "'two', '', '', '', 0, 1, '', 0" );
8935     ok( r == ERROR_SUCCESS, "cannot add feature %u\n", r );
8936 
8937     r = create_feature_components_table( hdb );
8938     ok( r == ERROR_SUCCESS, "cannot create FeatureComponents table %u\n", r );
8939 
8940     r = add_feature_components_entry( hdb, "'one', 'one'" );
8941     ok( r == ERROR_SUCCESS, "cannot add feature/component pair %u\n", r );
8942 
8943     r = add_feature_components_entry( hdb, "'two', 'two'" );
8944     ok( r == ERROR_SUCCESS, "cannot add feature/component pair %u\n", r );
8945 
8946     r = create_install_execute_sequence_table( hdb );
8947     ok( r == ERROR_SUCCESS, "cannot create InstallExecuteSequence table %u\n", r );
8948 
8949     r = add_install_execute_sequence_entry( hdb, "'CostInitialize', '', '800'" );
8950     ok( r == ERROR_SUCCESS, "cannot add install execute sequence entry %u\n", r );
8951 
8952     r = add_install_execute_sequence_entry( hdb, "'FileCost', '', '900'" );
8953     ok( r == ERROR_SUCCESS, "cannot add install execute sequence entry %u\n", r );
8954 
8955     r = add_install_execute_sequence_entry( hdb, "'CostFinalize', '', '1000'" );
8956     ok( r == ERROR_SUCCESS, "cannot add install execute sequence entry %u\n", r );
8957 
8958     r = add_install_execute_sequence_entry( hdb, "'InstallValidate', '', '1100'" );
8959     ok( r == ERROR_SUCCESS, "cannot add install execute sequence entry %u\n", r );
8960 
8961     MsiDatabaseCommit( hdb );
8962 
8963     sprintf( package, "#%u", hdb );
8964     r = MsiOpenPackageA( package, &hpkg );
8965     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
8966     {
8967         skip("Not enough rights to perform tests\n");
8968         goto error;
8969     }
8970     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8971 
8972     r = MsiEnumComponentCostsA( 0, NULL, 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8973     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8974 
8975     r = MsiEnumComponentCostsA( hpkg, NULL, 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8976     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8977 
8978     r = MsiEnumComponentCostsA( hpkg, NULL, 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8979     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8980 
8981     r = MsiEnumComponentCostsA( hpkg, "", 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8982     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8983 
8984     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8985     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8986 
8987     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, NULL, NULL, NULL, NULL );
8988     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8989 
8990     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, NULL, NULL, 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, NULL, NULL );
8995     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8996 
8997     len = sizeof(drive);
8998     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, NULL );
8999     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
9000 
9001     len = sizeof(drive);
9002     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
9003     todo_wine ok( r == ERROR_INVALID_HANDLE_STATE, "Expected ERROR_INVALID_HANDLE_STATE, got %u\n", r );
9004 
9005     len = sizeof(drive);
9006     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, NULL, &len, &cost, &temp );
9007     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
9008 
9009     MsiSetInternalUI( INSTALLUILEVEL_NONE, NULL );
9010 
9011     r = MsiDoActionA( hpkg, "CostInitialize" );
9012     ok( r == ERROR_SUCCESS, "CostInitialize failed %u\n", r );
9013 
9014     r = MsiDoActionA( hpkg, "FileCost" );
9015     ok( r == ERROR_SUCCESS, "FileCost failed %u\n", r );
9016 
9017     len = sizeof(drive);
9018     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
9019     ok( r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %u\n", r );
9020 
9021     r = MsiDoActionA( hpkg, "CostFinalize" );
9022     ok( r == ERROR_SUCCESS, "CostFinalize failed %u\n", r );
9023 
9024     /* contrary to what msdn says InstallValidate must be called too */
9025     len = sizeof(drive);
9026     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
9027     todo_wine ok( r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %u\n", r );
9028 
9029     r = MsiDoActionA( hpkg, "InstallValidate" );
9030     ok( r == ERROR_SUCCESS, "InstallValidate failed %u\n", r );
9031 
9032     len = 0;
9033     r = MsiEnumComponentCostsA( hpkg, "three", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
9034     ok( r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %u\n", r );
9035 
9036     len = 0;
9037     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
9038     ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %u\n", r );
9039     ok( len == 2, "expected len == 2, got %u\n", len );
9040 
9041     len = 2;
9042     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
9043     ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %u\n", r );
9044     ok( len == 2, "expected len == 2, got %u\n", len );
9045 
9046     len = 2;
9047     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_UNKNOWN, drive, &len, &cost, &temp );
9048     ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %u\n", r );
9049     ok( len == 2, "expected len == 2, got %u\n", len );
9050 
9051     /* install state doesn't seem to matter */
9052     len = sizeof(drive);
9053     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_UNKNOWN, drive, &len, &cost, &temp );
9054     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
9055 
9056     len = sizeof(drive);
9057     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_ABSENT, drive, &len, &cost, &temp );
9058     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
9059 
9060     len = sizeof(drive);
9061     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_SOURCE, drive, &len, &cost, &temp );
9062     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
9063 
9064     len = sizeof(drive);
9065     drive[0] = 0;
9066     cost = temp = 0xdead;
9067     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
9068     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
9069     ok( len == 2, "expected len == 2, got %u\n", len );
9070     ok( drive[0], "expected a drive\n" );
9071     ok( cost && cost != 0xdead, "expected cost > 0, got %d\n", cost );
9072     ok( !temp, "expected temp == 0, got %d\n", temp );
9073 
9074     len = sizeof(drive);
9075     drive[0] = 0;
9076     cost = temp = 0xdead;
9077     r = MsiEnumComponentCostsA( hpkg, "two", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
9078     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
9079     ok( len == 2, "expected len == 2, got %u\n", len );
9080     ok( drive[0], "expected a drive\n" );
9081     ok( !cost, "expected cost == 0, got %d\n", cost );
9082     ok( !temp, "expected temp == 0, got %d\n", temp );
9083 
9084     len = sizeof(drive);
9085     drive[0] = 0;
9086     cost = temp = 0xdead;
9087     r = MsiEnumComponentCostsA( hpkg, "", 0, INSTALLSTATE_UNKNOWN, drive, &len, &cost, &temp );
9088     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
9089     ok( len == 2, "expected len == 2, got %u\n", len );
9090     ok( drive[0], "expected a drive\n" );
9091     ok( !cost, "expected cost == 0, got %d\n", cost );
9092     ok( temp && temp != 0xdead, "expected temp > 0, got %d\n", temp );
9093 
9094     /* increased index */
9095     len = sizeof(drive);
9096     r = MsiEnumComponentCostsA( hpkg, "one", 1, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
9097     ok( r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %u\n", r );
9098 
9099     len = sizeof(drive);
9100     r = MsiEnumComponentCostsA( hpkg, "", 1, INSTALLSTATE_UNKNOWN, drive, &len, &cost, &temp );
9101     ok( r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %u\n", r );
9102 
9103     MsiCloseHandle( hpkg );
9104 error:
9105     MsiCloseHandle( hdb );
9106     DeleteFileA( msifile );
9107 }
9108 
9109 static void test_MsiDatabaseCommit(void)
9110 {
9111     UINT r;
9112     MSIHANDLE hdb, hpkg = 0;
9113     char buf[32], package[12];
9114     DWORD sz;
9115 
9116     hdb = create_package_db();
9117     ok( hdb, "failed to create database\n" );
9118 
9119     r = create_property_table( hdb );
9120     ok( r == ERROR_SUCCESS, "can't create Property table %u\n", r );
9121 
9122     sprintf( package, "#%u", hdb );
9123     r = MsiOpenPackageA( package, &hpkg );
9124     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
9125     {
9126         skip("Not enough rights to perform tests\n");
9127         goto error;
9128     }
9129     ok( r == ERROR_SUCCESS, "got %u\n", r );
9130 
9131     r = MsiSetPropertyA( hpkg, "PROP", "value" );
9132     ok( r == ERROR_SUCCESS, "got %u\n", r );
9133 
9134     buf[0] = 0;
9135     sz = sizeof(buf);
9136     r = MsiGetPropertyA( hpkg, "PROP", buf, &sz );
9137     ok( r == ERROR_SUCCESS, "MsiGetPropertyA returned %u\n", r );
9138     ok( !lstrcmpA( buf, "value" ), "got \"%s\"\n", buf );
9139 
9140     r = MsiDatabaseCommit( hdb );
9141     ok( r == ERROR_SUCCESS, "MsiDatabaseCommit returned %u\n", r );
9142 
9143     buf[0] = 0;
9144     sz = sizeof(buf);
9145     r = MsiGetPropertyA( hpkg, "PROP", buf, &sz );
9146     ok( r == ERROR_SUCCESS, "MsiGetPropertyA returned %u\n", r );
9147     ok( !lstrcmpA( buf, "value" ), "got \"%s\"\n", buf );
9148 
9149     MsiCloseHandle( hpkg );
9150 error:
9151     MsiCloseHandle( hdb );
9152     DeleteFileA( msifile );
9153 }
9154 
9155 static int externalui_ran;
9156 
9157 static INT CALLBACK externalui_callback(void *context, UINT message_type, LPCSTR message)
9158 {
9159     externalui_ran = 1;
9160     ok(message_type == INSTALLMESSAGE_USER, "expected INSTALLMESSAGE_USER, got %08x\n", message_type);
9161     return 0;
9162 }
9163 
9164 static int externalui_record_ran;
9165 
9166 static INT CALLBACK externalui_record_callback(void *context, UINT message_type, MSIHANDLE hrecord)
9167 {
9168     INT retval = context ? *((INT *)context) : 0;
9169     UINT r;
9170     externalui_record_ran = 1;
9171     ok(message_type == INSTALLMESSAGE_USER, "expected INSTALLMESSAGE_USER, got %08x\n", message_type);
9172     r = MsiRecordGetFieldCount(hrecord);
9173     ok(r == 1, "expected 1, got %u\n", r);
9174     r = MsiRecordGetInteger(hrecord, 1);
9175     ok(r == 12345, "expected 12345, got %u\n", r);
9176     return retval;
9177 }
9178 
9179 static void test_externalui(void)
9180 {
9181     /* test that external UI handlers work correctly */
9182 
9183     INSTALLUI_HANDLERA prev;
9184     INSTALLUI_HANDLER_RECORD prev_record;
9185     MSIHANDLE hpkg, hrecord;
9186     UINT r;
9187     INT retval = 0;
9188 
9189     prev = MsiSetExternalUIA(externalui_callback, INSTALLLOGMODE_USER, NULL);
9190 
9191     r = package_from_db(create_package_db(), &hpkg);
9192     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
9193     {
9194         skip("Not enough rights to perform tests\n");
9195         DeleteFileA(msifile);
9196         return;
9197     }
9198     ok(r == ERROR_SUCCESS, "Expected a valid package %u\n", r);
9199 
9200     hrecord = MsiCreateRecord(1);
9201     ok(hrecord, "Expected a valid record\n");
9202     r = MsiRecordSetStringA(hrecord, 0, "test message [1]");
9203     ok(r == ERROR_SUCCESS, "MsiSetString failed %u\n", r);
9204     r = MsiRecordSetInteger(hrecord, 1, 12345);
9205     ok(r == ERROR_SUCCESS, "MsiSetInteger failed %u\n", r);
9206 
9207     externalui_ran = 0;
9208     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
9209     ok(r == 0, "expected 0, got %u\n", r);
9210     ok(externalui_ran == 1, "external UI callback did not run\n");
9211 
9212     prev = MsiSetExternalUIA(prev, 0, NULL);
9213     ok(prev == externalui_callback, "wrong callback function %p\n", prev);
9214     r = MsiSetExternalUIRecord(externalui_record_callback, INSTALLLOGMODE_USER, &retval, &prev_record);
9215     ok(r == ERROR_SUCCESS, "MsiSetExternalUIRecord failed %u\n", r);
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 == 0, "external UI callback should not have run\n");
9221     ok(externalui_record_ran == 1, "external UI record callback did not run\n");
9222 
9223     MsiSetExternalUIA(externalui_callback, INSTALLLOGMODE_USER, NULL);
9224 
9225     externalui_ran = externalui_record_ran = 0;
9226     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
9227     ok(r == 0, "expected 0, got %u\n", r);
9228     ok(externalui_ran == 1, "external UI callback did not run\n");
9229     ok(externalui_record_ran == 1, "external UI record callback did not run\n");
9230 
9231     retval = 1;
9232     externalui_ran = externalui_record_ran = 0;
9233     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
9234     ok(r == 1, "expected 1, got %u\n", r);
9235     ok(externalui_ran == 0, "external UI callback should not have run\n");
9236     ok(externalui_record_ran == 1, "external UI record callback did not run\n");
9237 
9238     /* filter and context should be kept separately */
9239     r = MsiSetExternalUIRecord(externalui_record_callback, INSTALLLOGMODE_ERROR, &retval, &prev_record);
9240     ok(r == ERROR_SUCCESS, "MsiSetExternalUIRecord failed %u\n", r);
9241 
9242     externalui_ran = externalui_record_ran = 0;
9243     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
9244     ok(r == 0, "expected 0, got %u\n", r);
9245     ok(externalui_ran == 1, "external UI callback did not run\n");
9246     ok(externalui_record_ran == 0, "external UI record callback should not have run\n");
9247 
9248     MsiCloseHandle(hpkg);
9249     DeleteFileA(msifile);
9250 }
9251 
9252 struct externalui_message {
9253     UINT message;
9254     int field_count;
9255     char field[4][100];
9256     int match[4]; /* should we test for a match */
9257     int optional;
9258 };
9259 
9260 static struct externalui_message *sequence;
9261 static int sequence_count, sequence_size;
9262 
9263 static void add_message(const struct externalui_message *msg)
9264 {
9265     if (!sequence)
9266     {
9267         sequence_size = 10;
9268         sequence = HeapAlloc(GetProcessHeap(), 0, sequence_size * sizeof(*sequence));
9269     }
9270     if (sequence_count == sequence_size)
9271     {
9272         sequence_size *= 2;
9273         sequence = HeapReAlloc(GetProcessHeap(), 0, sequence, sequence_size * sizeof(*sequence));
9274     }
9275 
9276     assert(sequence);
9277 
9278     sequence[sequence_count++] = *msg;
9279 }
9280 
9281 static void flush_sequence(void)
9282 {
9283     HeapFree(GetProcessHeap(), 0, sequence);
9284     sequence = NULL;
9285     sequence_count = sequence_size = 0;
9286 }
9287 
9288 static void ok_sequence_(const struct externalui_message *expected, const char *context, BOOL todo,
9289                          const char *file, int line)
9290 {
9291     static const struct externalui_message end_of_sequence = {0};
9292     const struct externalui_message *actual;
9293     int failcount = 0;
9294     int i;
9295 
9296     add_message(&end_of_sequence);
9297 
9298     actual = sequence;
9299 
9300     while (expected->message && actual->message)
9301     {
9302         if (expected->message == actual->message)
9303         {
9304             if (expected->field_count != actual->field_count)
9305             {
9306                 todo_wine_if (todo)
9307                     ok_(file, line) (FALSE, "%s: in msg 0x%08x expecting field count %d got %d\n",
9308                                      context, expected->message, expected->field_count, actual->field_count);
9309                 failcount++;
9310             }
9311 
9312             for (i = 0; i <= actual->field_count; i++)
9313             {
9314                 if (expected->match[i] && strcmp(expected->field[i], actual->field[i]))
9315                 {
9316                     todo_wine_if (todo)
9317                         ok_(file, line) (FALSE, "%s: in msg 0x%08x field %d: expected \"%s\", got \"%s\"\n",
9318                                          context, expected->message, i, expected->field[i], actual->field[i]);
9319                     failcount++;
9320                 }
9321             }
9322 
9323             expected++;
9324             actual++;
9325         }
9326         else
9327         {
9328             todo_wine_if (todo)
9329                 ok_(file, line) (FALSE, "%s: the msg 0x%08x was expected, but got msg 0x%08x instead\n",
9330                                  context, expected->message, actual->message);
9331             failcount++;
9332             if (todo)
9333                 goto done;
9334             expected++;
9335             actual++;
9336         }
9337     }
9338 
9339     if (expected->message || actual->message)
9340     {
9341         todo_wine_if (todo)
9342             ok_(file, line) (FALSE, "%s: the msg sequence is not complete: expected %08x - actual %08x\n",
9343                              context, expected->message, actual->message);
9344         failcount++;
9345     }
9346 
9347     if(todo && !failcount) /* succeeded yet marked todo */
9348     {
9349         todo_wine
9350             ok_(file, line)(TRUE, "%s: marked \"todo_wine\" but succeeds\n", context);
9351     }
9352 
9353 done:
9354     flush_sequence();
9355 }
9356 
9357 #define ok_sequence(exp, contx, todo) \
9358         ok_sequence_((exp), (contx), (todo), __FILE__, __LINE__)
9359 
9360 static const struct externalui_message empty_sequence[] = {
9361     {0}
9362 };
9363 
9364 static const struct externalui_message openpackage_nonexistent_sequence[] = {
9365     {INSTALLMESSAGE_INITIALIZE, -1},
9366     {INSTALLMESSAGE_TERMINATE, -1},
9367     {0}
9368 };
9369 
9370 static const struct externalui_message openpackage_sequence[] = {
9371     {INSTALLMESSAGE_INITIALIZE, -1},
9372     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9373     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
9374     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9375     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9376     {0}
9377 };
9378 
9379 static const struct externalui_message processmessage_info_sequence[] = {
9380     {INSTALLMESSAGE_INFO, 3, {"zero", "one", "two", "three"}, {1, 1, 1, 1}},
9381     {0}
9382 };
9383 
9384 static const struct externalui_message processmessage_actionstart_sequence[] = {
9385     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "name", "description", "template"}, {0, 1, 1, 1}},
9386     {0}
9387 };
9388 
9389 static const struct externalui_message processmessage_actiondata_sequence[] = {
9390     {INSTALLMESSAGE_ACTIONDATA, 3, {"{{name: }}template", "cherry", "banana", "guava"}, {1, 1, 1, 1}},
9391     {0}
9392 };
9393 
9394 static const struct externalui_message processmessage_error_sequence[] = {
9395     {INSTALLMESSAGE_USER, 3, {"", "1311", "banana", "guava"}, {0, 1, 1, 1}},
9396     {0}
9397 };
9398 
9399 static const struct externalui_message processmessage_internal_error_sequence[] = {
9400     {INSTALLMESSAGE_INFO, 3, {"DEBUG: Error [1]:  Action not found: [2]", "2726", "banana", "guava"}, {1, 1, 1, 1}},
9401     {INSTALLMESSAGE_USER, 3, {"internal error", "2726", "banana", "guava"}, {1, 1, 1, 1}},
9402     {0}
9403 };
9404 
9405 static const struct externalui_message processmessage_error_format_sequence[] = {
9406     {INSTALLMESSAGE_USER, 3, {"", "2726", "banana", "guava"}, {0, 1, 1, 1}},
9407     {0}
9408 };
9409 
9410 static const struct externalui_message doaction_costinitialize_sequence[] = {
9411     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostInitialize", "cost description", "cost template"}, {0, 1, 1, 1}},
9412     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", ""}, {0, 1, 1}},
9413     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", "1"}, {0, 1, 1}},
9414     {0}
9415 };
9416 
9417 static const struct externalui_message doaction_custom_sequence[] = {
9418     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "description", "template"}, {0, 1, 1, 1}},
9419     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
9420     {INSTALLMESSAGE_INFO, 2, {"", "custom", "0"}, {0, 1, 1}},
9421     {0}
9422 };
9423 
9424 static const struct externalui_message doaction_custom_fullui_sequence[] = {
9425     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
9426     {INSTALLMESSAGE_INFO, 2, {"", "custom", ""}, {0, 1, 1}},
9427     {INSTALLMESSAGE_SHOWDIALOG, 0, {"custom"}, {1}},
9428     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
9429     {0}
9430 };
9431 
9432 static const struct externalui_message doaction_custom_cancel_sequence[] = {
9433     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
9434     {0}
9435 };
9436 
9437 static const struct externalui_message doaction_dialog_nonexistent_sequence[] = {
9438     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
9439     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
9440     {INSTALLMESSAGE_SHOWDIALOG, 0, {"custom"}, {1}},
9441     {INSTALLMESSAGE_INFO, 2, {"DEBUG: Error [1]:  Action not found: [2]", "2726", "custom"}, {1, 1, 1}},
9442     {INSTALLMESSAGE_INFO, 2, {"", "2726", "custom"}, {0, 1, 1}},
9443     {INSTALLMESSAGE_INFO, 2, {"", "custom", "0"}, {0, 1, 1}},
9444     {0}
9445 };
9446 
9447 static const struct externalui_message doaction_dialog_sequence[] = {
9448     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "dialog", "", ""}, {0, 1, 1, 1}},
9449     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "0"}, {0, 1, 1}},
9450     {INSTALLMESSAGE_SHOWDIALOG, 0, {"dialog"}, {1}},
9451     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "dialog", "Dialog created"}, {0, 1, 1}},
9452     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "1"}, {0, 1, 1}},
9453     {0}
9454 };
9455 
9456 static const struct externalui_message doaction_dialog_error_sequence[] = {
9457     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "error", "", ""}, {0, 1, 1, 1}},
9458     {INSTALLMESSAGE_INFO, 2, {"", "error", "1"}, {0, 1, 1}},
9459     {INSTALLMESSAGE_SHOWDIALOG, 0, {"error"}, {1}},
9460     {0}
9461 };
9462 
9463 static const struct externalui_message doaction_dialog_3_sequence[] = {
9464     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "dialog", "", ""}, {0, 1, 1, 1}},
9465     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "0"}, {0, 1, 1}},
9466     {INSTALLMESSAGE_SHOWDIALOG, 0, {"dialog"}, {1}},
9467     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "3"}, {0, 1, 1}},
9468     {0}
9469 };
9470 
9471 static const struct externalui_message doaction_dialog_12345_sequence[] = {
9472     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "dialog", "", ""}, {0, 1, 1, 1}},
9473     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "3"}, {0, 1, 1}},
9474     {INSTALLMESSAGE_SHOWDIALOG, 0, {"dialog"}, {1}},
9475     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "12345"}, {0, 1, 1}},
9476     {0}
9477 };
9478 
9479 static const struct externalui_message closehandle_sequence[] = {
9480     {INSTALLMESSAGE_TERMINATE, -1},
9481     {0}
9482 };
9483 
9484 static INT CALLBACK externalui_message_string_callback(void *context, UINT message, LPCSTR string)
9485 {
9486     INT retval = context ? *((INT *)context) : 0;
9487     struct externalui_message msg;
9488 
9489     msg.message = message;
9490     msg.field_count = 0;
9491     strcpy(msg.field[0], string);
9492     add_message(&msg);
9493 
9494     return retval;
9495 }
9496 
9497 static INT CALLBACK externalui_message_callback(void *context, UINT message, MSIHANDLE hrecord)
9498 {
9499     INT retval = context ? *((INT *)context) : 0;
9500     struct externalui_message msg;
9501     char buffer[100];
9502     DWORD length = 100;
9503     int i;
9504 
9505     msg.message = message;
9506     if (message == INSTALLMESSAGE_TERMINATE)
9507     {
9508         /* trying to access the record seems to hang on some versions of Windows */
9509         msg.field_count = -1;
9510         add_message(&msg);
9511         return 1;
9512     }
9513     msg.field_count = MsiRecordGetFieldCount(hrecord);
9514     for (i = 0; i <= msg.field_count; i++)
9515     {
9516         length = 100;
9517         MsiRecordGetStringA(hrecord, i, buffer, &length);
9518         memcpy(msg.field[i], buffer, min(100, length+1));
9519     }
9520 
9521     add_message(&msg);
9522 
9523     return retval;
9524 }
9525 
9526 static void test_externalui_message(void)
9527 {
9528     /* test that events trigger the correct sequence of messages */
9529 
9530     INSTALLUI_HANDLER_RECORD prev;
9531     MSIHANDLE hdb, hpkg, hrecord;
9532     INT retval = 1;
9533     UINT r;
9534 
9535     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
9536 
9537     /* processing SHOWDIALOG with a record handler causes a crash on XP */
9538     MsiSetExternalUIA(externalui_message_string_callback, INSTALLLOGMODE_SHOWDIALOG, &retval);
9539     r = MsiSetExternalUIRecord(externalui_message_callback, 0xffffffff ^ INSTALLLOGMODE_PROGRESS ^ INSTALLLOGMODE_SHOWDIALOG, &retval, &prev);
9540 
9541     flush_sequence();
9542 
9543     CoInitialize(NULL);
9544 
9545     hdb = create_package_db();
9546     ok(hdb, "failed to create database\n");
9547 
9548     create_file_data("forcecodepage.idt", "\r\n\r\n1252\t_ForceCodepage\r\n");
9549     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
9550     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9551 
9552     r = run_query(hdb, "CREATE TABLE `Error` (`Error` SHORT NOT NULL, `Message` CHAR(0) PRIMARY KEY `Error`)");
9553     ok(r == ERROR_SUCCESS, "Failed to create Error table: %u\n", r);
9554     r = run_query(hdb, "INSERT INTO `Error` (`Error`, `Message`) VALUES (5, 'internal error')");
9555     ok(r == ERROR_SUCCESS, "Failed to insert into Error table: %u\n", r);
9556 
9557     r = create_actiontext_table(hdb);
9558     ok(r == ERROR_SUCCESS, "Failed to create ActionText table: %u\n", r);
9559     r = add_actiontext_entry(hdb, "'custom', 'description', 'template'");
9560     ok(r == ERROR_SUCCESS, "Failed to insert into ActionText table: %u\n", r);
9561     r = add_actiontext_entry(hdb, "'CostInitialize', 'cost description', 'cost template'");
9562     ok(r == ERROR_SUCCESS, "Failed to insert into ActionText table: %u\n", r);
9563 
9564     r = MsiOpenPackageA(NULL, &hpkg);
9565     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9566     ok_sequence(empty_sequence, "MsiOpenPackage with NULL db", FALSE);
9567 
9568     r = MsiOpenPackageA("nonexistent", &hpkg);
9569     ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
9570     ok_sequence(openpackage_nonexistent_sequence, "MsiOpenPackage with nonexistent db", FALSE);
9571 
9572     r = package_from_db(hdb, &hpkg);
9573     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
9574     {
9575         skip("Not enough rights to perform tests\n");
9576         DeleteFileA(msifile);
9577         return;
9578     }
9579     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
9580     ok_sequence(openpackage_sequence, "MsiOpenPackage with valid db", FALSE);
9581 
9582     /* Test MsiProcessMessage */
9583     hrecord = MsiCreateRecord(3);
9584     ok(hrecord, "failed to create record\n");
9585 
9586     MsiRecordSetStringA(hrecord, 0, "zero");
9587     MsiRecordSetStringA(hrecord, 1, "one");
9588     MsiRecordSetStringA(hrecord, 2, "two");
9589     MsiRecordSetStringA(hrecord, 3, "three");
9590     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_INFO, hrecord);
9591     ok(r == 1, "Expected 1, got %d\n", r);
9592     ok_sequence(processmessage_info_sequence, "MsiProcessMessage(INSTALLMESSAGE_INFO)", FALSE);
9593 
9594     MsiRecordSetStringA(hrecord, 1, "name");
9595     MsiRecordSetStringA(hrecord, 2, "description");
9596     MsiRecordSetStringA(hrecord, 3, "template");
9597     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_ACTIONSTART, hrecord);
9598     ok(r == 1, "Expected 1, got %d\n", r);
9599     ok_sequence(processmessage_actionstart_sequence, "MsiProcessMessage(INSTALLMESSAGE_ACTIONSTART)", FALSE);
9600 
9601     MsiRecordSetStringA(hrecord, 0, "apple");
9602     MsiRecordSetStringA(hrecord, 1, "cherry");
9603     MsiRecordSetStringA(hrecord, 2, "banana");
9604     MsiRecordSetStringA(hrecord, 3, "guava");
9605     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_ACTIONDATA, hrecord);
9606     ok(r == 1, "Expected 1, got %d\n", r);
9607     ok_sequence(processmessage_actiondata_sequence, "MsiProcessMessage(INSTALLMESSAGE_ACTIONDATA)", FALSE);
9608 
9609     /* non-internal error */
9610     MsiRecordSetStringA(hrecord, 0, NULL);
9611     MsiRecordSetInteger(hrecord, 1, 1311);
9612     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
9613     ok(r == 1, "Expected 1, got %d\n", r);
9614     ok_sequence(processmessage_error_sequence, "MsiProcessMessage non-internal error", FALSE);
9615 
9616     /* internal error */
9617     MsiRecordSetStringA(hrecord, 0, NULL);
9618     MsiRecordSetInteger(hrecord, 1, 2726);
9619     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
9620     ok(r == 0, "Expected 0, got %d\n", r);
9621     ok_sequence(processmessage_internal_error_sequence, "MsiProcessMessage internal error", FALSE);
9622 
9623     /* with format field */
9624     MsiRecordSetStringA(hrecord, 0, "starfruit");
9625     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
9626     ok(r == 1, "Expected 1, got %d\n", r);
9627     ok_sequence(processmessage_error_format_sequence, "MsiProcessMessage error", FALSE);
9628 
9629     /* Test a standard action */
9630     r = MsiDoActionA(hpkg, "CostInitialize");
9631     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9632     ok_sequence(doaction_costinitialize_sequence, "MsiDoAction(\"CostInitialize\")", FALSE);
9633 
9634     /* Test a custom action */
9635     r = MsiDoActionA(hpkg, "custom");
9636     ok(r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %d\n", r);
9637     ok_sequence(doaction_custom_sequence, "MsiDoAction(\"custom\")", FALSE);
9638 
9639     /* close the package */
9640     MsiCloseHandle(hpkg);
9641     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
9642 
9643     /* Test dialogs */
9644     hdb = create_package_db();
9645     ok(hdb, "failed to create database\n");
9646 
9647     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
9648     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9649 
9650     r = create_dialog_table(hdb);
9651     ok(r == ERROR_SUCCESS, "failed to create dialog table %u\n", r);
9652     r = add_dialog_entry(hdb, "'dialog', 50, 50, 100, 100, 0, 'dummy'");
9653     ok(r == ERROR_SUCCESS, "failed to insert into dialog table %u\n", r);
9654 
9655     r = create_control_table(hdb);
9656     ok(r == ERROR_SUCCESS, "failed to create control table %u\n", r);
9657     r = add_control_entry(hdb, "'dialog', 'dummy', 'Text', 5, 5, 5, 5, 3, 'dummy'");
9658     ok(r == ERROR_SUCCESS, "failed to insert into control table %u\n", r);
9659 
9660     r = package_from_db(hdb, &hpkg);
9661     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
9662     ok_sequence(openpackage_sequence, "MsiOpenPackage with valid db", FALSE);
9663 
9664     /* Test a custom action */
9665     r = MsiDoActionA(hpkg, "custom");
9666     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9667     ok_sequence(doaction_custom_fullui_sequence, "MsiDoAction(\"custom\")", FALSE);
9668 
9669     retval = 2;
9670     r = MsiDoActionA(hpkg, "custom");
9671     ok(r == ERROR_INSTALL_USEREXIT, "Expected ERROR_INSTALL_USEREXIT, got %d\n", r);
9672     ok_sequence(doaction_custom_cancel_sequence, "MsiDoAction(\"custom\")", FALSE);
9673 
9674     retval = 0;
9675     r = MsiDoActionA(hpkg, "custom");
9676     ok(r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %d\n", r);
9677     ok_sequence(doaction_dialog_nonexistent_sequence, "MsiDoAction(\"custom\")", FALSE);
9678 
9679     r = MsiDoActionA(hpkg, "dialog");
9680     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9681     ok_sequence(doaction_dialog_sequence, "MsiDoAction(\"dialog\")", FALSE);
9682 
9683     retval = -1;
9684     r = MsiDoActionA(hpkg, "error");
9685     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9686     ok_sequence(doaction_dialog_error_sequence, "MsiDoAction(\"error\")", FALSE);
9687 
9688     r = MsiDoActionA(hpkg, "error");
9689     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9690     ok_sequence(doaction_dialog_error_sequence, "MsiDoAction(\"error\")", FALSE);
9691 
9692     retval = -2;
9693     r = MsiDoActionA(hpkg, "custom");
9694     ok(r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %d\n", r);
9695     ok_sequence(doaction_dialog_nonexistent_sequence, "MsiDoAction(\"custom\")", FALSE);
9696 
9697     retval = 3;
9698     r = MsiDoActionA(hpkg, "dialog");
9699     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %d\n", r);
9700     ok_sequence(doaction_dialog_3_sequence, "MsiDoAction(\"dialog\")", FALSE);
9701 
9702     retval = 12345;
9703     r = MsiDoActionA(hpkg, "dialog");
9704     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_INSTALL_FAILURE, got %d\n", r);
9705     ok_sequence(doaction_dialog_12345_sequence, "MsiDoAction(\"dialog\")", FALSE);
9706 
9707     MsiCloseHandle(hpkg);
9708     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
9709 
9710     MsiCloseHandle(hrecord);
9711     CoUninitialize();
9712     DeleteFileA(msifile);
9713     DeleteFileA("forcecodepage.idt");
9714 }
9715 
9716 static const struct externalui_message controlevent_spawn_sequence[] = {
9717     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "spawn", "", ""}, {0, 1, 1, 1}},
9718     {INSTALLMESSAGE_INFO, 2, {"", "spawn", ""}, {0, 1, 1}},
9719     {INSTALLMESSAGE_SHOWDIALOG, 0, {"spawn"}, {1}},
9720     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "spawn", "Dialog created"}, {0, 1, 1}},
9721 
9722     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
9723     {INSTALLMESSAGE_INFO, 2, {"", "custom", ""}, {0, 1, 1}},
9724     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
9725 
9726     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "child1", "Dialog created"}, {0, 1, 1}},
9727 
9728     {INSTALLMESSAGE_INFO, 2, {"", "spawn", "2"}, {0, 1, 1}},
9729     {0}
9730 };
9731 
9732 static const struct externalui_message controlevent_spawn2_sequence[] = {
9733     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "spawn2", "", ""}, {0, 1, 1, 1}},
9734     {INSTALLMESSAGE_INFO, 2, {"", "spawn2", "2"}, {0, 1, 1}},
9735     {INSTALLMESSAGE_SHOWDIALOG, 0, {"spawn2"}, {1}},
9736     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "spawn2", "Dialog created"}, {0, 1, 1}},
9737 
9738     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
9739     {INSTALLMESSAGE_INFO, 2, {"", "custom", "2"}, {0, 1, 1}},
9740     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
9741 
9742     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "child2", "Dialog created"}, {0, 1, 1}},
9743 
9744     {INSTALLMESSAGE_INFO, 2, {"", "spawn2", "2"}, {0, 1, 1}},
9745     {0}
9746 };
9747 
9748 static void test_controlevent(void)
9749 {
9750     INSTALLUI_HANDLER_RECORD prev;
9751     MSIHANDLE hdb, hpkg;
9752     UINT r;
9753 
9754     if (!winetest_interactive)
9755     {
9756         skip("interactive ControlEvent tests\n");
9757         return;
9758     }
9759 
9760     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
9761 
9762     /* processing SHOWDIALOG with a record handler causes a crash on XP */
9763     MsiSetExternalUIA(externalui_message_string_callback, INSTALLLOGMODE_SHOWDIALOG, NULL);
9764     r = MsiSetExternalUIRecord(externalui_message_callback, 0xffffffff ^ INSTALLLOGMODE_PROGRESS ^ INSTALLLOGMODE_SHOWDIALOG, NULL, &prev);
9765 
9766     flush_sequence();
9767 
9768     CoInitialize(NULL);
9769 
9770     hdb = create_package_db();
9771     ok(hdb, "failed to create database\n");
9772 
9773     create_file_data("forcecodepage.idt", "\r\n\r\n1252\t_ForceCodepage\r\n");
9774     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
9775     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9776 
9777     r = create_dialog_table(hdb);
9778     ok(r == ERROR_SUCCESS, "failed to create Dialog table: %u\n", r);
9779     r = add_dialog_entry(hdb, "'spawn', 50, 50, 100, 100, 3, 'button'");
9780     ok(r == ERROR_SUCCESS, "failed to insert into Dialog table: %u\n", r);
9781     r = add_dialog_entry(hdb, "'spawn2', 50, 50, 100, 100, 3, 'button'");
9782     ok(r == ERROR_SUCCESS, "failed to insert into Dialog table: %u\n", r);
9783     r = add_dialog_entry(hdb, "'child1', 50, 50, 80, 40, 3, 'exit'");
9784     ok(r == ERROR_SUCCESS, "failed to insert into Dialog table: %u\n", r);
9785     r = add_dialog_entry(hdb, "'child2', 50, 50, 80, 40, 3, 'exit'");
9786     ok(r == ERROR_SUCCESS, "failed to insert into Dialog table: %u\n", r);
9787 
9788     r = create_control_table(hdb);
9789     ok(r == ERROR_SUCCESS, "failed to create Control table: %u\n", r);
9790     r = add_control_entry(hdb, "'spawn', 'button', 'PushButton', 10, 10, 66, 17, 3, 'Click me'");
9791     ok(r == ERROR_SUCCESS, "failed to insert into Control table: %u\n", r);
9792     r = add_control_entry(hdb, "'spawn2', 'button', 'PushButton', 10, 10, 66, 17, 3, 'Click me'");
9793     ok(r == ERROR_SUCCESS, "failed to insert into Control table: %u\n", r);
9794     r = add_control_entry(hdb, "'child1', 'exit', 'PushButton', 10, 10, 66, 17, 3, 'Click me'");
9795     ok(r == ERROR_SUCCESS, "failed to insert into Control table: %u\n", r);
9796     r = add_control_entry(hdb, "'child2', 'exit', 'PushButton', 10, 10, 66, 17, 3, 'Click me'");
9797     ok(r == ERROR_SUCCESS, "failed to insert into Control table: %u\n", r);
9798 
9799     r = create_controlevent_table(hdb);
9800     ok(r == ERROR_SUCCESS, "failed to create ControlEvent table: %u\n", r);
9801     r = add_controlevent_entry(hdb, "'child1', 'exit', 'EndDialog', 'Exit', 1, 1");
9802     ok(r == ERROR_SUCCESS, "failed to insert into ControlEvent table: %u\n", r);
9803     r = add_controlevent_entry(hdb, "'child2', 'exit', 'EndDialog', 'Exit', 1, 1");
9804     ok(r == ERROR_SUCCESS, "failed to insert into ControlEvent table: %u\n", r);
9805 
9806     r = create_custom_action_table(hdb);
9807     ok(r == ERROR_SUCCESS, "failed to create CustomAction table: %u\n", r);
9808     r = add_custom_action_entry(hdb, "'custom', 51, 'dummy', 'dummy value'");
9809     ok(r == ERROR_SUCCESS, "failed to insert into CustomAction table: %u\n", r);
9810 
9811     /* SpawnDialog and EndDialog should trigger after all other events */
9812     r = add_controlevent_entry(hdb, "'spawn', 'button', 'SpawnDialog', 'child1', 1, 1");
9813     ok(r == ERROR_SUCCESS, "failed to insert into ControlEvent table: %u\n", r);
9814     r = add_controlevent_entry(hdb, "'spawn', 'button', 'DoAction', 'custom', 1, 2");
9815     ok(r == ERROR_SUCCESS, "failed to insert into ControlEvent table: %u\n", r);
9816 
9817     /* Multiple dialog events cause only the last one to be triggered */
9818     r = add_controlevent_entry(hdb, "'spawn2', 'button', 'SpawnDialog', 'child1', 1, 1");
9819     ok(r == ERROR_SUCCESS, "failed to insert into ControlEvent table: %u\n", r);
9820     r = add_controlevent_entry(hdb, "'spawn2', 'button', 'SpawnDialog', 'child2', 1, 2");
9821     ok(r == ERROR_SUCCESS, "failed to insert into ControlEvent table: %u\n", r);
9822     r = add_controlevent_entry(hdb, "'spawn2', 'button', 'DoAction', 'custom', 1, 3");
9823     ok(r == ERROR_SUCCESS, "failed to insert into ControlEvent table: %u\n", r);
9824 
9825     r = package_from_db(hdb, &hpkg);
9826     ok(r == ERROR_SUCCESS, "failed to create package: %u\n", r);
9827     ok_sequence(openpackage_sequence, "MsiOpenPackage()", FALSE);
9828 
9829     r = MsiDoActionA(hpkg, "spawn");
9830     ok(r == ERROR_INSTALL_USEREXIT, "expected ERROR_INSTALL_USEREXIT, got %u\n", r);
9831     ok_sequence(controlevent_spawn_sequence, "control event: spawn", FALSE);
9832 
9833     r = MsiDoActionA(hpkg, "spawn2");
9834     ok(r == ERROR_INSTALL_USEREXIT, "expected ERROR_INSTALL_USEREXIT, got %u\n", r);
9835     ok_sequence(controlevent_spawn2_sequence, "control event: spawn2", FALSE);
9836 
9837     MsiCloseHandle(hpkg);
9838     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
9839 
9840     CoUninitialize();
9841     DeleteFileA(msifile);
9842     DeleteFileA("forcecodepage.idt");
9843 }
9844 
9845 START_TEST(package)
9846 {
9847     STATEMGRSTATUS status;
9848     BOOL ret = FALSE;
9849 
9850     init_functionpointers();
9851 
9852     if (pIsWow64Process)
9853         pIsWow64Process(GetCurrentProcess(), &is_wow64);
9854 
9855     GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
9856 
9857     /* Create a restore point ourselves so we circumvent the multitude of restore points
9858      * that would have been created by all the installation and removal tests.
9859      *
9860      * This is not needed on version 5.0 where setting MSIFASTINSTALL prevents the
9861      * creation of restore points.
9862      */
9863     if (pSRSetRestorePointA && !pMsiGetComponentPathExA)
9864     {
9865         memset(&status, 0, sizeof(status));
9866         ret = notify_system_change(BEGIN_NESTED_SYSTEM_CHANGE, &status);
9867     }
9868 
9869     test_createpackage();
9870     test_doaction();
9871     test_gettargetpath_bad();
9872     test_settargetpath();
9873     test_props();
9874     test_property_table();
9875     test_condition();
9876     test_msipackage();
9877     test_formatrecord2();
9878     test_states();
9879     test_getproperty();
9880     test_removefiles();
9881     test_appsearch();
9882     test_appsearch_complocator();
9883     test_appsearch_reglocator();
9884     test_appsearch_inilocator();
9885     test_appsearch_drlocator();
9886     test_featureparents();
9887     test_installprops();
9888     test_launchconditions();
9889     test_ccpsearch();
9890     test_complocator();
9891     test_MsiGetSourcePath();
9892     test_shortlongsource();
9893     test_sourcedir();
9894     test_access();
9895     test_emptypackage();
9896     test_MsiGetProductProperty();
9897     test_MsiSetProperty();
9898     test_MsiApplyMultiplePatches();
9899     test_MsiApplyPatch();
9900     test_MsiEnumComponentCosts();
9901     test_MsiDatabaseCommit();
9902     test_externalui();
9903     test_externalui_message();
9904     test_controlevent();
9905 
9906     if (pSRSetRestorePointA && !pMsiGetComponentPathExA && ret)
9907     {
9908         ret = notify_system_change(END_NESTED_SYSTEM_CHANGE, &status);
9909         if (ret)
9910             remove_restore_point(status.llSequenceNumber);
9911     }
9912 }
9913