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     UINT r = 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     ok(r == ERROR_SUCCESS, "Failed to create Component table: %u\n", r);
458     return r;
459 }
460 
461 static UINT create_feature_table( MSIHANDLE hdb )
462 {
463     UINT r = run_query( hdb,
464             "CREATE TABLE `Feature` ( "
465             "`Feature` CHAR(38) NOT NULL, "
466             "`Feature_Parent` CHAR(38), "
467             "`Title` CHAR(64), "
468             "`Description` CHAR(255), "
469             "`Display` SHORT NOT NULL, "
470             "`Level` SHORT NOT NULL, "
471             "`Directory_` CHAR(72), "
472             "`Attributes` SHORT NOT NULL "
473             "PRIMARY KEY `Feature`)" );
474     ok(r == ERROR_SUCCESS, "Failed to create Feature table: %u\n", r);
475     return r;
476 }
477 
478 static UINT create_feature_components_table( MSIHANDLE hdb )
479 {
480     UINT r = run_query( hdb,
481             "CREATE TABLE `FeatureComponents` ( "
482             "`Feature_` CHAR(38) NOT NULL, "
483             "`Component_` CHAR(72) NOT NULL "
484             "PRIMARY KEY `Feature_`, `Component_` )" );
485     ok(r == ERROR_SUCCESS, "Failed to create FeatureComponents table: %u\n", r);
486     return r;
487 }
488 
489 static UINT create_file_table( MSIHANDLE hdb )
490 {
491     UINT r = run_query( hdb,
492             "CREATE TABLE `File` ("
493             "`File` CHAR(72) NOT NULL, "
494             "`Component_` CHAR(72) NOT NULL, "
495             "`FileName` CHAR(255) NOT NULL, "
496             "`FileSize` LONG NOT NULL, "
497             "`Version` CHAR(72), "
498             "`Language` CHAR(20), "
499             "`Attributes` SHORT, "
500             "`Sequence` SHORT NOT NULL "
501             "PRIMARY KEY `File`)" );
502     ok(r == ERROR_SUCCESS, "Failed to create File table: %u\n", r);
503     return r;
504 }
505 
506 static UINT create_remove_file_table( MSIHANDLE hdb )
507 {
508     UINT r = run_query( hdb,
509             "CREATE TABLE `RemoveFile` ("
510             "`FileKey` CHAR(72) NOT NULL, "
511             "`Component_` CHAR(72) NOT NULL, "
512             "`FileName` CHAR(255) LOCALIZABLE, "
513             "`DirProperty` CHAR(72) NOT NULL, "
514             "`InstallMode` SHORT NOT NULL "
515             "PRIMARY KEY `FileKey`)" );
516     ok(r == ERROR_SUCCESS, "Failed to create RemoveFile table: %u\n", r);
517     return r;
518 }
519 
520 static UINT create_appsearch_table( MSIHANDLE hdb )
521 {
522     UINT r = run_query( hdb,
523             "CREATE TABLE `AppSearch` ("
524             "`Property` CHAR(72) NOT NULL, "
525             "`Signature_` CHAR(72) NOT NULL "
526             "PRIMARY KEY `Property`, `Signature_`)" );
527     ok(r == ERROR_SUCCESS, "Failed to create AppSearch table: %u\n", r);
528     return r;
529 }
530 
531 static UINT create_reglocator_table( MSIHANDLE hdb )
532 {
533     UINT r = run_query( hdb,
534             "CREATE TABLE `RegLocator` ("
535             "`Signature_` CHAR(72) NOT NULL, "
536             "`Root` SHORT NOT NULL, "
537             "`Key` CHAR(255) NOT NULL, "
538             "`Name` CHAR(255), "
539             "`Type` SHORT "
540             "PRIMARY KEY `Signature_`)" );
541     ok(r == ERROR_SUCCESS, "Failed to create RegLocator table: %u\n", r);
542     return r;
543 }
544 
545 static UINT create_signature_table( MSIHANDLE hdb )
546 {
547     UINT r = run_query( hdb,
548             "CREATE TABLE `Signature` ("
549             "`Signature` CHAR(72) NOT NULL, "
550             "`FileName` CHAR(255) NOT NULL, "
551             "`MinVersion` CHAR(20), "
552             "`MaxVersion` CHAR(20), "
553             "`MinSize` LONG, "
554             "`MaxSize` LONG, "
555             "`MinDate` LONG, "
556             "`MaxDate` LONG, "
557             "`Languages` CHAR(255) "
558             "PRIMARY KEY `Signature`)" );
559     ok(r == ERROR_SUCCESS, "Failed to create Signature table: %u\n", r);
560     return r;
561 }
562 
563 static UINT create_launchcondition_table( MSIHANDLE hdb )
564 {
565     UINT r = run_query( hdb,
566             "CREATE TABLE `LaunchCondition` ("
567             "`Condition` CHAR(255) NOT NULL, "
568             "`Description` CHAR(255) NOT NULL "
569             "PRIMARY KEY `Condition`)" );
570     ok(r == ERROR_SUCCESS, "Failed to create LaunchCondition table: %u\n", r);
571     return r;
572 }
573 
574 static UINT create_property_table( MSIHANDLE hdb )
575 {
576     UINT r = run_query( hdb,
577             "CREATE TABLE `Property` ("
578             "`Property` CHAR(72) NOT NULL, "
579             "`Value` CHAR(0) "
580             "PRIMARY KEY `Property`)" );
581     ok(r == ERROR_SUCCESS, "Failed to create Property table: %u\n", r);
582     return r;
583 }
584 
585 static UINT create_install_execute_sequence_table( MSIHANDLE hdb )
586 {
587     UINT r = run_query( hdb,
588             "CREATE TABLE `InstallExecuteSequence` ("
589             "`Action` CHAR(72) NOT NULL, "
590             "`Condition` CHAR(255), "
591             "`Sequence` SHORT "
592             "PRIMARY KEY `Action`)" );
593     ok(r == ERROR_SUCCESS, "Failed to create InstallExecuteSequence table: %u\n", r);
594     return r;
595 }
596 
597 static UINT create_install_ui_sequence_table( MSIHANDLE hdb )
598 {
599     UINT r = run_query( hdb,
600             "CREATE TABLE `InstallUISequence` ("
601             "`Action` CHAR(72) NOT NULL, "
602             "`Condition` CHAR(255), "
603             "`Sequence` SHORT "
604             "PRIMARY KEY `Action`)" );
605     ok(r == ERROR_SUCCESS, "Failed to create InstallUISequence table: %u\n", r);
606     return r;
607 }
608 
609 static UINT create_media_table( MSIHANDLE hdb )
610 {
611     UINT r = run_query( hdb,
612             "CREATE TABLE `Media` ("
613             "`DiskId` SHORT NOT NULL, "
614             "`LastSequence` SHORT NOT NULL, "
615             "`DiskPrompt` CHAR(64), "
616             "`Cabinet` CHAR(255), "
617             "`VolumeLabel` CHAR(32), "
618             "`Source` CHAR(72) "
619             "PRIMARY KEY `DiskId`)" );
620     ok(r == ERROR_SUCCESS, "Failed to create Media table: %u\n", r);
621     return r;
622 }
623 
624 static UINT create_ccpsearch_table( MSIHANDLE hdb )
625 {
626     UINT r = run_query( hdb,
627             "CREATE TABLE `CCPSearch` ("
628             "`Signature_` CHAR(72) NOT NULL "
629             "PRIMARY KEY `Signature_`)" );
630     ok(r == ERROR_SUCCESS, "Failed to create CCPSearch table: %u\n", r);
631     return r;
632 }
633 
634 static UINT create_drlocator_table( MSIHANDLE hdb )
635 {
636     UINT r = run_query( hdb,
637             "CREATE TABLE `DrLocator` ("
638             "`Signature_` CHAR(72) NOT NULL, "
639             "`Parent` CHAR(72), "
640             "`Path` CHAR(255), "
641             "`Depth` SHORT "
642             "PRIMARY KEY `Signature_`, `Parent`, `Path`)" );
643     ok(r == ERROR_SUCCESS, "Failed to create DrLocator table: %u\n", r);
644     return r;
645 }
646 
647 static UINT create_complocator_table( MSIHANDLE hdb )
648 {
649     UINT r = run_query( hdb,
650             "CREATE TABLE `CompLocator` ("
651             "`Signature_` CHAR(72) NOT NULL, "
652             "`ComponentId` CHAR(38) NOT NULL, "
653             "`Type` SHORT "
654             "PRIMARY KEY `Signature_`)" );
655     ok(r == ERROR_SUCCESS, "Failed to create CompLocator table: %u\n", r);
656     return r;
657 }
658 
659 static UINT create_inilocator_table( MSIHANDLE hdb )
660 {
661     UINT r = run_query( hdb,
662             "CREATE TABLE `IniLocator` ("
663             "`Signature_` CHAR(72) NOT NULL, "
664             "`FileName` CHAR(255) NOT NULL, "
665             "`Section` CHAR(96)NOT NULL, "
666             "`Key` CHAR(128)NOT NULL, "
667             "`Field` SHORT, "
668             "`Type` SHORT "
669             "PRIMARY KEY `Signature_`)" );
670     ok(r == ERROR_SUCCESS, "Failed to create IniLocator table: %u\n", r);
671     return r;
672 }
673 
674 static UINT create_custom_action_table( MSIHANDLE hdb )
675 {
676     UINT r = run_query( hdb,
677             "CREATE TABLE `CustomAction` ("
678             "`Action` CHAR(72) NOT NULL, "
679             "`Type` SHORT NOT NULL, "
680             "`Source` CHAR(75), "
681             "`Target` CHAR(255) "
682             "PRIMARY KEY `Action`)" );
683     ok(r == ERROR_SUCCESS, "Failed to create CustomAction table: %u\n", r);
684     return r;
685 }
686 
687 static UINT create_dialog_table( MSIHANDLE hdb )
688 {
689     UINT r = run_query(hdb,
690             "CREATE TABLE `Dialog` ("
691             "`Dialog` CHAR(72) NOT NULL, "
692             "`HCentering` SHORT NOT NULL, "
693             "`VCentering` SHORT NOT NULL, "
694             "`Width` SHORT NOT NULL, "
695             "`Height` SHORT NOT NULL, "
696             "`Attributes` LONG, "
697             "`Title` CHAR(128) LOCALIZABLE, "
698             "`Control_First` CHAR(50) NOT NULL, "
699             "`Control_Default` CHAR(50), "
700             "`Control_Cancel` CHAR(50) "
701             "PRIMARY KEY `Dialog`)");
702     ok(r == ERROR_SUCCESS, "Failed to create Dialog table: %u\n", r);
703     return r;
704 }
705 
706 static UINT create_control_table( MSIHANDLE hdb )
707 {
708     UINT r = run_query(hdb,
709             "CREATE TABLE `Control` ("
710             "`Dialog_` CHAR(72) NOT NULL, "
711             "`Control` CHAR(50) NOT NULL, "
712             "`Type` CHAR(20) NOT NULL, "
713             "`X` SHORT NOT NULL, "
714             "`Y` SHORT NOT NULL, "
715             "`Width` SHORT NOT NULL, "
716             "`Height` SHORT NOT NULL, "
717             "`Attributes` LONG, "
718             "`Property` CHAR(50), "
719             "`Text` CHAR(0) LOCALIZABLE, "
720             "`Control_Next` CHAR(50), "
721             "`Help` CHAR(255) LOCALIZABLE "
722             "PRIMARY KEY `Dialog_`, `Control`)");
723     ok(r == ERROR_SUCCESS, "Failed to create Control table: %u\n", r);
724     return r;
725 }
726 
727 static UINT create_controlevent_table( MSIHANDLE hdb )
728 {
729     UINT r = run_query(hdb,
730             "CREATE TABLE `ControlEvent` ("
731             "`Dialog_` CHAR(72) NOT NULL, "
732             "`Control_` CHAR(50) NOT NULL, "
733             "`Event` CHAR(50) NOT NULL, "
734             "`Argument` CHAR(255) NOT NULL, "
735             "`Condition` CHAR(255), "
736             "`Ordering` SHORT "
737             "PRIMARY KEY `Dialog_`, `Control_`, `Event`, `Argument`, `Condition`)");
738     ok(r == ERROR_SUCCESS, "Failed to create ControlEvent table: %u\n", r);
739     return r;
740 }
741 
742 static UINT create_actiontext_table( MSIHANDLE hdb )
743 {
744     UINT r = run_query(hdb,
745             "CREATE TABLE `ActionText` ("
746             "`Action` CHAR(72) NOT NULL, "
747             "`Description` CHAR(64) LOCALIZABLE, "
748             "`Template` CHAR(128) LOCALIZABLE "
749             "PRIMARY KEY `Action`)");
750     ok(r == ERROR_SUCCESS, "Failed to create ActionText table: %u\n", r);
751     return r;
752 }
753 
754 static inline UINT add_entry(const char *file, int line, const char *type, MSIHANDLE hdb, const char *values, const char *insert)
755 {
756     char *query;
757     UINT sz, r;
758 
759     sz = strlen(values) + strlen(insert) + 1;
760     query = HeapAlloc(GetProcessHeap(), 0, sz);
761     sprintf(query, insert, values);
762     r = run_query(hdb, query);
763     HeapFree(GetProcessHeap(), 0, query);
764     ok_(file, line)(r == ERROR_SUCCESS, "failed to insert into %s table: %u\n", type, r);
765     return r;
766 }
767 
768 #define add_component_entry(hdb, values) add_entry(__FILE__, __LINE__, "Component", hdb, values, \
769                "INSERT INTO `Component`  " \
770                "(`Component`, `ComponentId`, `Directory_`, " \
771                "`Attributes`, `Condition`, `KeyPath`) VALUES( %s )")
772 
773 #define add_directory_entry(hdb, values) add_entry(__FILE__, __LINE__, "Directory", hdb, values, \
774                "INSERT INTO `Directory` " \
775                "(`Directory`,`Directory_Parent`,`DefaultDir`) VALUES( %s )")
776 
777 #define add_feature_entry(hdb, values) add_entry(__FILE__, __LINE__, "Feature", hdb, values, \
778                "INSERT INTO `Feature` " \
779                "(`Feature`, `Feature_Parent`, `Title`, `Description`, " \
780                "`Display`, `Level`, `Directory_`, `Attributes`) VALUES( %s )")
781 
782 #define add_feature_components_entry(hdb, values) add_entry(__FILE__, __LINE__, "FeatureComponents", hdb, values, \
783                "INSERT INTO `FeatureComponents` " \
784                "(`Feature_`, `Component_`) VALUES( %s )")
785 
786 #define add_file_entry(hdb, values) add_entry(__FILE__, __LINE__, "File", hdb, values, \
787                "INSERT INTO `File` " \
788                "(`File`, `Component_`, `FileName`, `FileSize`, " \
789                "`Version`, `Language`, `Attributes`, `Sequence`) VALUES( %s )")
790 
791 #define add_appsearch_entry(hdb, values) add_entry(__FILE__, __LINE__, "AppSearch", hdb, values, \
792                "INSERT INTO `AppSearch` " \
793                "(`Property`, `Signature_`) VALUES( %s )")
794 
795 #define add_signature_entry(hdb, values) add_entry(__FILE__, __LINE__, "Signature", hdb, values, \
796                "INSERT INTO `Signature` " \
797                "(`Signature`, `FileName`, `MinVersion`, `MaxVersion`," \
798                " `MinSize`, `MaxSize`, `MinDate`, `MaxDate`, `Languages`) " \
799                "VALUES( %s )")
800 
801 #define add_launchcondition_entry(hdb, values) add_entry(__FILE__, __LINE__, "LaunchCondition", hdb, values, \
802                "INSERT INTO `LaunchCondition` " \
803                "(`Condition`, `Description`) VALUES( %s )")
804 
805 #define add_property_entry(hdb, values) add_entry(__FILE__, __LINE__, "Property", hdb, values, \
806                "INSERT INTO `Property` (`Property`, `Value`) VALUES( %s )")
807 
808 #define add_install_execute_sequence_entry(hdb, values) add_entry(__FILE__, __LINE__, "InstallExecuteSequence", hdb, values, \
809                "INSERT INTO `InstallExecuteSequence` " \
810                "(`Action`, `Condition`, `Sequence`) VALUES( %s )")
811 
812 #define add_install_ui_sequence_entry(hdb, values) add_entry(__FILE__, __LINE__, "InstallUISequence", hdb, values, \
813                "INSERT INTO `InstallUISequence` " \
814                "(`Action`, `Condition`, `Sequence`) VALUES( %s )")
815 
816 #define add_media_entry(hdb, values) add_entry(__FILE__, __LINE__, "Media", hdb, values, \
817                "INSERT INTO `Media` " \
818                "(`DiskId`, `LastSequence`, `DiskPrompt`, " \
819                "`Cabinet`, `VolumeLabel`, `Source`) VALUES( %s )")
820 
821 #define add_ccpsearch_entry(hdb, values) add_entry(__FILE__, __LINE__, "CCPSearch", hdb, values, \
822                "INSERT INTO `CCPSearch` (`Signature_`) VALUES( %s )")
823 
824 #define add_drlocator_entry(hdb, values) add_entry(__FILE__, __LINE__, "DrLocator", hdb, values, \
825                "INSERT INTO `DrLocator` " \
826                "(`Signature_`, `Parent`, `Path`, `Depth`) VALUES( %s )")
827 
828 #define add_complocator_entry(hdb, values) add_entry(__FILE__, __LINE__, "CompLocator", hdb, values, \
829                "INSERT INTO `CompLocator` " \
830                "(`Signature_`, `ComponentId`, `Type`) VALUES( %s )")
831 
832 #define add_inilocator_entry(hdb, values) add_entry(__FILE__, __LINE__, "IniLocator", hdb, values, \
833                "INSERT INTO `IniLocator` " \
834                "(`Signature_`, `FileName`, `Section`, `Key`, `Field`, `Type`) " \
835                "VALUES( %s )")
836 
837 #define add_custom_action_entry(hdb, values) add_entry(__FILE__, __LINE__, "CustomAction", hdb, values, \
838                "INSERT INTO `CustomAction`  " \
839                "(`Action`, `Type`, `Source`, `Target`) VALUES( %s )")
840 
841 #define add_dialog_entry(hdb, values) add_entry(__FILE__, __LINE__, "Dialog", hdb, values, \
842                "INSERT INTO `Dialog` " \
843                "(`Dialog`, `HCentering`, `VCentering`, `Width`, `Height`, `Attributes`, `Control_First`) VALUES ( %s )")
844 
845 #define add_control_entry(hdb, values) add_entry(__FILE__, __LINE__, "Control", hdb, values, \
846                "INSERT INTO `Control` " \
847                "(`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, `Attributes`, `Text`) VALUES( %s )");
848 
849 #define add_controlevent_entry(hdb, values) add_entry(__FILE__, __LINE__, "ControlEvent", hdb, values, \
850                "INSERT INTO `ControlEvent` " \
851                "(`Dialog_`, `Control_`, `Event`, `Argument`, `Condition`, `Ordering`) VALUES( %s )");
852 
853 #define add_actiontext_entry(hdb, values) add_entry(__FILE__, __LINE__, "ActionText", hdb, values, \
854                "INSERT INTO `ActionText` " \
855                "(`Action`, `Description`, `Template`) VALUES( %s )");
856 
857 static UINT add_reglocator_entry( MSIHANDLE hdb, const char *sig, UINT root, const char *path,
858                                   const char *name, UINT type )
859 {
860     const char insert[] =
861         "INSERT INTO `RegLocator` (`Signature_`, `Root`, `Key`, `Name`, `Type`) "
862         "VALUES( '%s', %u, '%s', '%s', %u )";
863     char *query;
864     UINT sz, r;
865 
866     sz = strlen( sig ) + 10 + strlen( path ) + strlen( name ) + 10 + sizeof( insert );
867     query = HeapAlloc( GetProcessHeap(), 0, sz );
868     sprintf( query, insert, sig, root, path, name, type );
869     r = run_query( hdb, query );
870     HeapFree( GetProcessHeap(), 0, query );
871     ok(r == ERROR_SUCCESS, "failed to insert into reglocator table: %u\n", r); \
872     return r;
873 }
874 
875 static UINT set_summary_info(MSIHANDLE hdb)
876 {
877     UINT res;
878     MSIHANDLE suminfo;
879 
880     /* build summary info */
881     res = MsiGetSummaryInformationA(hdb, NULL, 7, &suminfo);
882     ok( res == ERROR_SUCCESS , "Failed to open summaryinfo\n" );
883 
884     res = MsiSummaryInfoSetPropertyA(suminfo,2, VT_LPSTR, 0,NULL,
885                         "Installation Database");
886     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
887 
888     res = MsiSummaryInfoSetPropertyA(suminfo,3, VT_LPSTR, 0,NULL,
889                         "Installation Database");
890     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
891 
892     res = MsiSummaryInfoSetPropertyA(suminfo,4, VT_LPSTR, 0,NULL,
893                         "Wine Hackers");
894     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
895 
896     res = MsiSummaryInfoSetPropertyA(suminfo,7, VT_LPSTR, 0,NULL,
897                     ";1033");
898     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
899 
900     res = MsiSummaryInfoSetPropertyA(suminfo,9, VT_LPSTR, 0,NULL,
901                     "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}");
902     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
903 
904     res = MsiSummaryInfoSetPropertyA(suminfo, 14, VT_I4, 100, NULL, NULL);
905     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
906 
907     res = MsiSummaryInfoSetPropertyA(suminfo, 15, VT_I4, 0, NULL, NULL);
908     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
909 
910     res = MsiSummaryInfoPersist(suminfo);
911     ok( res == ERROR_SUCCESS , "Failed to make summary info persist\n" );
912 
913     res = MsiCloseHandle( suminfo);
914     ok( res == ERROR_SUCCESS , "Failed to close suminfo\n" );
915 
916     return res;
917 }
918 
919 
920 static MSIHANDLE create_package_db(void)
921 {
922     MSIHANDLE hdb = 0;
923     UINT res;
924 
925     DeleteFileA(msifile);
926 
927     /* create an empty database */
928     res = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb );
929     ok( res == ERROR_SUCCESS , "Failed to create database %u\n", res );
930     if( res != ERROR_SUCCESS )
931         return hdb;
932 
933     res = MsiDatabaseCommit( hdb );
934     ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
935 
936     res = set_summary_info(hdb);
937     ok( res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", res);
938 
939     res = run_query( hdb,
940             "CREATE TABLE `Directory` ( "
941             "`Directory` CHAR(255) NOT NULL, "
942             "`Directory_Parent` CHAR(255), "
943             "`DefaultDir` CHAR(255) NOT NULL "
944             "PRIMARY KEY `Directory`)" );
945     ok( res == ERROR_SUCCESS , "Failed to create directory table\n" );
946 
947     return hdb;
948 }
949 
950 static UINT package_from_db(MSIHANDLE hdb, MSIHANDLE *handle)
951 {
952     UINT res;
953     CHAR szPackage[12];
954     MSIHANDLE hPackage;
955 
956     sprintf(szPackage, "#%u", hdb);
957     res = MsiOpenPackageA(szPackage, &hPackage);
958     if (res != ERROR_SUCCESS)
959     {
960         MsiCloseHandle(hdb);
961         return res;
962     }
963 
964     res = MsiCloseHandle(hdb);
965     if (res != ERROR_SUCCESS)
966     {
967         MsiCloseHandle(hPackage);
968         return res;
969     }
970 
971     *handle = hPackage;
972     return ERROR_SUCCESS;
973 }
974 
975 static void create_file_data(LPCSTR name, LPCSTR data)
976 {
977     HANDLE file;
978     DWORD written;
979 
980     file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
981     ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
982     if (file == INVALID_HANDLE_VALUE)
983         return;
984 
985     WriteFile(file, data, strlen(data), &written, NULL);
986     WriteFile(file, "\n", strlen("\n"), &written, NULL);
987 
988     CloseHandle(file);
989 }
990 
991 static void create_test_file(const CHAR *name)
992 {
993     create_file_data(name, name);
994 }
995 
996 typedef struct _tagVS_VERSIONINFO
997 {
998     WORD wLength;
999     WORD wValueLength;
1000     WORD wType;
1001     WCHAR szKey[1];
1002     WORD wPadding1[1];
1003     VS_FIXEDFILEINFO Value;
1004     WORD wPadding2[1];
1005     WORD wChildren[1];
1006 } VS_VERSIONINFO;
1007 
1008 #define roundoffs(a, b, r) (((BYTE *)(b) - (BYTE *)(a) + ((r) - 1)) & ~((r) - 1))
1009 #define roundpos(a, b, r) (((BYTE *)(a)) + roundoffs(a, b, r))
1010 
1011 static BOOL create_file_with_version(const CHAR *name, LONG ms, LONG ls)
1012 {
1013     VS_VERSIONINFO *pVerInfo;
1014     VS_FIXEDFILEINFO *pFixedInfo;
1015     LPBYTE buffer, ofs;
1016     CHAR path[MAX_PATH];
1017     DWORD handle, size;
1018     HANDLE resource;
1019     BOOL ret = FALSE;
1020 
1021     GetSystemDirectoryA(path, MAX_PATH);
1022     /* Some dlls can't be updated on Vista/W2K8 */
1023     lstrcatA(path, "\\version.dll");
1024 
1025     CopyFileA(path, name, FALSE);
1026 
1027     size = GetFileVersionInfoSizeA(path, &handle);
1028     buffer = HeapAlloc(GetProcessHeap(), 0, size);
1029 
1030     GetFileVersionInfoA(path, 0, size, buffer);
1031 
1032     pVerInfo = (VS_VERSIONINFO *)buffer;
1033     ofs = (BYTE *)&pVerInfo->szKey[lstrlenW(pVerInfo->szKey) + 1];
1034     pFixedInfo = (VS_FIXEDFILEINFO *)roundpos(pVerInfo, ofs, 4);
1035 
1036     pFixedInfo->dwFileVersionMS = ms;
1037     pFixedInfo->dwFileVersionLS = ls;
1038     pFixedInfo->dwProductVersionMS = ms;
1039     pFixedInfo->dwProductVersionLS = ls;
1040 
1041     resource = BeginUpdateResourceA(name, FALSE);
1042     if (!resource)
1043         goto done;
1044 
1045     if (!UpdateResourceA(resource, (LPCSTR)RT_VERSION, (LPCSTR)MAKEINTRESOURCE(VS_VERSION_INFO),
1046                          MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), buffer, size))
1047         goto done;
1048 
1049     if (!EndUpdateResourceA(resource, FALSE))
1050         goto done;
1051 
1052     ret = TRUE;
1053 
1054 done:
1055     HeapFree(GetProcessHeap(), 0, buffer);
1056     return ret;
1057 }
1058 
1059 static BOOL notify_system_change(DWORD event_type, STATEMGRSTATUS *status)
1060 {
1061     RESTOREPOINTINFOA spec;
1062 
1063     spec.dwEventType = event_type;
1064     spec.dwRestorePtType = APPLICATION_INSTALL;
1065     spec.llSequenceNumber = status->llSequenceNumber;
1066     lstrcpyA(spec.szDescription, "msitest restore point");
1067 
1068     return pSRSetRestorePointA(&spec, status);
1069 }
1070 
1071 static void remove_restore_point(DWORD seq_number)
1072 {
1073     DWORD res;
1074 
1075     res = pSRRemoveRestorePoint(seq_number);
1076     if (res != ERROR_SUCCESS)
1077         trace("Failed to remove the restore point : %08x\n", res);
1078 }
1079 
1080 static BOOL is_root(const char *path)
1081 {
1082     return (isalpha(path[0]) && path[1] == ':' && path[2] == '\\' && !path[3]);
1083 }
1084 
1085 static void test_createpackage(void)
1086 {
1087     MSIHANDLE hPackage = 0;
1088     UINT res;
1089 
1090     res = package_from_db(create_package_db(), &hPackage);
1091     if (res == ERROR_INSTALL_PACKAGE_REJECTED)
1092     {
1093         skip("Not enough rights to perform tests\n");
1094         DeleteFileA(msifile);
1095         return;
1096     }
1097     ok( res == ERROR_SUCCESS, " Failed to create package %u\n", res );
1098 
1099     res = MsiCloseHandle( hPackage);
1100     ok( res == ERROR_SUCCESS , "Failed to close package\n" );
1101     DeleteFileA(msifile);
1102 }
1103 
1104 static void test_doaction( void )
1105 {
1106     MSIHANDLE hpkg;
1107     UINT r;
1108 
1109     r = MsiDoActionA( -1, NULL );
1110     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1111 
1112     r = package_from_db(create_package_db(), &hpkg);
1113     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1114     {
1115         skip("Not enough rights to perform tests\n");
1116         DeleteFileA(msifile);
1117         return;
1118     }
1119     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1120 
1121     r = MsiDoActionA(hpkg, NULL);
1122     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1123 
1124     r = MsiDoActionA(0, "boo");
1125     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1126 
1127     r = MsiDoActionA(hpkg, "boo");
1128     ok( r == ERROR_FUNCTION_NOT_CALLED, "wrong return val\n");
1129 
1130     MsiCloseHandle( hpkg );
1131     DeleteFileA(msifile);
1132 }
1133 
1134 static void test_gettargetpath_bad(void)
1135 {
1136     static const WCHAR boo[] = {'b','o','o',0};
1137     static const WCHAR empty[] = {0};
1138     char buffer[0x80];
1139     WCHAR bufferW[0x80];
1140     MSIHANDLE hpkg;
1141     DWORD sz;
1142     UINT r;
1143 
1144     r = package_from_db(create_package_db(), &hpkg);
1145     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1146     {
1147         skip("Not enough rights to perform tests\n");
1148         DeleteFileA(msifile);
1149         return;
1150     }
1151     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1152 
1153     r = MsiGetTargetPathA( 0, NULL, NULL, NULL );
1154     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1155 
1156     r = MsiGetTargetPathA( 0, NULL, NULL, &sz );
1157     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1158 
1159     r = MsiGetTargetPathA( 0, "boo", NULL, NULL );
1160     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1161 
1162     r = MsiGetTargetPathA( 0, "boo", NULL, NULL );
1163     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1164 
1165     r = MsiGetTargetPathA( hpkg, "boo", NULL, NULL );
1166     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1167 
1168     r = MsiGetTargetPathA( hpkg, "boo", buffer, NULL );
1169     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1170 
1171     sz = 0;
1172     r = MsiGetTargetPathA( hpkg, "", buffer, &sz );
1173     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1174 
1175     r = MsiGetTargetPathW( 0, NULL, NULL, NULL );
1176     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1177 
1178     r = MsiGetTargetPathW( 0, NULL, NULL, &sz );
1179     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1180 
1181     r = MsiGetTargetPathW( 0, boo, NULL, NULL );
1182     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1183 
1184     r = MsiGetTargetPathW( 0, boo, NULL, NULL );
1185     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1186 
1187     r = MsiGetTargetPathW( hpkg, boo, NULL, NULL );
1188     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1189 
1190     r = MsiGetTargetPathW( hpkg, boo, bufferW, NULL );
1191     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1192 
1193     sz = 0;
1194     r = MsiGetTargetPathW( hpkg, empty, bufferW, &sz );
1195     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1196 
1197     MsiCloseHandle( hpkg );
1198     DeleteFileA(msifile);
1199 }
1200 
1201 static void query_file_path(MSIHANDLE hpkg, LPCSTR file, LPSTR buff)
1202 {
1203     UINT r;
1204     DWORD size;
1205     MSIHANDLE rec;
1206 
1207     rec = MsiCreateRecord( 1 );
1208     ok(rec, "MsiCreate record failed\n");
1209 
1210     r = MsiRecordSetStringA( rec, 0, file );
1211     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
1212 
1213     size = MAX_PATH;
1214     r = MsiFormatRecordA( hpkg, rec, buff, &size );
1215     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
1216 
1217     MsiCloseHandle( rec );
1218 }
1219 
1220 static void test_settargetpath(void)
1221 {
1222     char tempdir[MAX_PATH+8], buffer[MAX_PATH], file[MAX_PATH];
1223     DWORD sz;
1224     MSIHANDLE hpkg;
1225     UINT r;
1226     MSIHANDLE hdb;
1227 
1228     hdb = create_package_db();
1229     ok ( hdb, "failed to create package database\n" );
1230 
1231     add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'" );
1232 
1233     create_component_table( hdb );
1234     add_component_entry( hdb, "'RootComp', '{83e2694d-0864-4124-9323-6d37630912a1}', 'TARGETDIR', 8, '', 'RootFile'" );
1235     add_component_entry( hdb, "'TestComp', '{A3FB59C8-C293-4F7E-B8C5-F0E1D8EEE4E5}', 'TestDir', 0, '', 'TestFile'" );
1236 
1237     create_feature_table( hdb );
1238     add_feature_entry( hdb, "'TestFeature', '', '', '', 0, 1, '', 0" );
1239 
1240     create_feature_components_table( hdb );
1241     add_feature_components_entry( hdb, "'TestFeature', 'RootComp'" );
1242     add_feature_components_entry( hdb, "'TestFeature', 'TestComp'" );
1243 
1244     add_directory_entry( hdb, "'TestParent', 'TARGETDIR', 'TestParent'" );
1245     add_directory_entry( hdb, "'TestDir', 'TestParent', 'TestDir'" );
1246 
1247     create_file_table( hdb );
1248     add_file_entry( hdb, "'RootFile', 'RootComp', 'rootfile.txt', 0, '', '1033', 8192, 1" );
1249     add_file_entry( hdb, "'TestFile', 'TestComp', 'testfile.txt', 0, '', '1033', 8192, 1" );
1250 
1251     r = package_from_db( hdb, &hpkg );
1252     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1253     {
1254         skip("Not enough rights to perform tests\n");
1255         DeleteFileA(msifile);
1256         return;
1257     }
1258     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1259 
1260     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1261 
1262     r = MsiDoActionA( hpkg, "CostInitialize");
1263     ok( r == ERROR_SUCCESS, "cost init failed\n");
1264 
1265     r = MsiDoActionA( hpkg, "FileCost");
1266     ok( r == ERROR_SUCCESS, "file cost failed\n");
1267 
1268     r = MsiDoActionA( hpkg, "CostFinalize");
1269     ok( r == ERROR_SUCCESS, "cost finalize failed\n");
1270 
1271     buffer[0] = 0;
1272     sz = sizeof(buffer);
1273     r = MsiGetPropertyA( hpkg, "OutOfNoRbDiskSpace", buffer, &sz );
1274     ok( r == ERROR_SUCCESS, "MsiGetProperty returned %u\n", r );
1275     trace( "OutOfNoRbDiskSpace = \"%s\"\n", buffer );
1276 
1277     r = MsiSetTargetPathA( 0, NULL, NULL );
1278     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1279 
1280     r = MsiSetTargetPathA( 0, "boo", "C:\\bogusx" );
1281     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1282 
1283     r = MsiSetTargetPathA( hpkg, "boo", NULL );
1284     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1285 
1286     r = MsiSetTargetPathA( hpkg, "boo", "c:\\bogusx" );
1287     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1288 
1289     sz = sizeof tempdir - 1;
1290     r = MsiGetTargetPathA( hpkg, "TARGETDIR", tempdir, &sz );
1291     sprintf( file, "%srootfile.txt", tempdir );
1292     buffer[0] = 0;
1293     query_file_path( hpkg, "[#RootFile]", buffer );
1294     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1295     ok( !lstrcmpA(buffer, file), "Expected %s, got %s\n", file, buffer );
1296 
1297     GetTempFileNameA( tempdir, "_wt", 0, buffer );
1298     sprintf( tempdir, "%s\\subdir", buffer );
1299 
1300     r = MsiSetTargetPathA( hpkg, "TARGETDIR", buffer );
1301     ok( r == ERROR_SUCCESS || r == ERROR_DIRECTORY,
1302         "MsiSetTargetPath on file returned %d\n", r );
1303 
1304     r = MsiSetTargetPathA( hpkg, "TARGETDIR", tempdir );
1305     ok( r == ERROR_SUCCESS || r == ERROR_DIRECTORY,
1306         "MsiSetTargetPath on 'subdir' of file returned %d\n", r );
1307 
1308     DeleteFileA( buffer );
1309 
1310     r = MsiSetTargetPathA( hpkg, "TARGETDIR", buffer );
1311     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1312 
1313     r = GetFileAttributesA( buffer );
1314     ok ( r == INVALID_FILE_ATTRIBUTES, "file/directory exists after MsiSetTargetPath. Attributes: %08X\n", r );
1315 
1316     r = MsiSetTargetPathA( hpkg, "TARGETDIR", tempdir );
1317     ok( r == ERROR_SUCCESS, "MsiSetTargetPath on subsubdir returned %d\n", r );
1318 
1319     buffer[0] = 0;
1320     sz = sizeof buffer - 1;
1321     lstrcatA( tempdir, "\\" );
1322     r = MsiGetTargetPathA( hpkg, "TARGETDIR", buffer, &sz );
1323     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1324     ok( !lstrcmpA(buffer, tempdir), "Expected %s, got %s\n", tempdir, buffer);
1325 
1326     sprintf( file, "%srootfile.txt", tempdir );
1327     query_file_path( hpkg, "[#RootFile]", buffer );
1328     ok( !lstrcmpA(buffer, file), "Expected %s, got %s\n", file, buffer);
1329 
1330     buffer[0] = 0;
1331     sz = sizeof(buffer);
1332     r = MsiGetPropertyA( hpkg, "TestParent", buffer, &sz );
1333     ok( r == ERROR_SUCCESS, "MsiGetProperty returned %u\n", r );
1334     lstrcatA( tempdir, "TestParent\\" );
1335     ok( !lstrcmpiA(buffer, tempdir), "Expected \"%s\", got \"%s\"\n", tempdir, buffer );
1336 
1337     r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\one\\two" );
1338     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1339 
1340     buffer[0] = 0;
1341     sz = sizeof(buffer);
1342     r = MsiGetPropertyA( hpkg, "TestParent", buffer, &sz );
1343     ok( r == ERROR_SUCCESS, "MsiGetProperty returned %u\n", r );
1344     ok( lstrcmpiA(buffer, "C:\\one\\two\\TestDir\\"),
1345         "Expected \"C:\\one\\two\\TestDir\\\", got \"%s\"\n", buffer );
1346 
1347     buffer[0] = 0;
1348     query_file_path( hpkg, "[#TestFile]", buffer );
1349     ok( !lstrcmpiA(buffer, "C:\\one\\two\\TestDir\\testfile.txt"),
1350         "Expected C:\\one\\two\\TestDir\\testfile.txt, got %s\n", buffer );
1351 
1352     buffer[0] = 0;
1353     sz = sizeof buffer - 1;
1354     r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1355     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1356     ok( !lstrcmpiA(buffer, "C:\\one\\two\\"), "Expected C:\\one\\two\\, got %s\n", buffer);
1357 
1358     r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\one\\two\\three" );
1359     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1360 
1361     buffer[0] = 0;
1362     sz = sizeof buffer - 1;
1363     r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1364     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1365     ok( !lstrcmpiA(buffer, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", buffer);
1366 
1367     r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\\\one\\\\two  " );
1368     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1369 
1370     buffer[0] = 0;
1371     sz = sizeof buffer - 1;
1372     r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1373     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1374     ok( !lstrcmpiA(buffer, "C:\\one\\two\\"), "Expected \"C:\\one\\two\\\", got %s\n", buffer);
1375 
1376     r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\\\ Program Files \\\\ " );
1377     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1378 
1379     buffer[0] = 0;
1380     sz = sizeof buffer - 1;
1381     r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1382     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1383     ok( !lstrcmpiA(buffer, "C:\\Program Files\\"), "Expected \"C:\\Program Files\\\", got %s\n", buffer);
1384 
1385     MsiCloseHandle( hpkg );
1386 }
1387 
1388 static void test_condition(void)
1389 {
1390     static const WCHAR cond1[] = {'\"','a',0x30a,'\"','<','\"',0xe5,'\"',0};
1391     static const WCHAR cond2[] = {'\"','a',0x30a,'\"','>','\"',0xe5,'\"',0};
1392     static const WCHAR cond3[] = {'\"','a',0x30a,'\"','<','>','\"',0xe5,'\"',0};
1393     static const WCHAR cond4[] = {'\"','a',0x30a,'\"','=','\"',0xe5,'\"',0};
1394     MSICONDITION r;
1395     MSIHANDLE hpkg;
1396 
1397     r = package_from_db(create_package_db(), &hpkg);
1398     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1399     {
1400         skip("Not enough rights to perform tests\n");
1401         DeleteFileA(msifile);
1402         return;
1403     }
1404     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1405 
1406     r = MsiEvaluateConditionA(0, NULL);
1407     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1408 
1409     r = MsiEvaluateConditionA(hpkg, NULL);
1410     ok( r == MSICONDITION_NONE, "wrong return val\n");
1411 
1412     r = MsiEvaluateConditionA(hpkg, "");
1413     ok( r == MSICONDITION_NONE, "wrong return val\n");
1414 
1415     r = MsiEvaluateConditionA(hpkg, "1");
1416     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1417 
1418     r = MsiEvaluateConditionA(hpkg, "0");
1419     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1420 
1421     r = MsiEvaluateConditionA(hpkg, "-1");
1422     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1423 
1424     r = MsiEvaluateConditionA(hpkg, "0 = 0");
1425     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1426 
1427     r = MsiEvaluateConditionA(hpkg, "0 <> 0");
1428     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1429 
1430     r = MsiEvaluateConditionA(hpkg, "0 = 1");
1431     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1432 
1433     r = MsiEvaluateConditionA(hpkg, "0 > 1");
1434     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1435 
1436     r = MsiEvaluateConditionA(hpkg, "0 ~> 1");
1437     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1438 
1439     r = MsiEvaluateConditionA(hpkg, "1 > 1");
1440     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1441 
1442     r = MsiEvaluateConditionA(hpkg, "1 ~> 1");
1443     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1444 
1445     r = MsiEvaluateConditionA(hpkg, "0 >= 1");
1446     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1447 
1448     r = MsiEvaluateConditionA(hpkg, "0 ~>= 1");
1449     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1450 
1451     r = MsiEvaluateConditionA(hpkg, "1 >= 1");
1452     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1453 
1454     r = MsiEvaluateConditionA(hpkg, "1 ~>= 1");
1455     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1456 
1457     r = MsiEvaluateConditionA(hpkg, "0 < 1");
1458     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1459 
1460     r = MsiEvaluateConditionA(hpkg, "0 ~< 1");
1461     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1462 
1463     r = MsiEvaluateConditionA(hpkg, "1 < 1");
1464     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1465 
1466     r = MsiEvaluateConditionA(hpkg, "1 ~< 1");
1467     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1468 
1469     r = MsiEvaluateConditionA(hpkg, "0 <= 1");
1470     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1471 
1472     r = MsiEvaluateConditionA(hpkg, "0 ~<= 1");
1473     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1474 
1475     r = MsiEvaluateConditionA(hpkg, "1 <= 1");
1476     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1477 
1478     r = MsiEvaluateConditionA(hpkg, "1 ~<= 1");
1479     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1480 
1481     r = MsiEvaluateConditionA(hpkg, "0 >=");
1482     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1483 
1484     r = MsiEvaluateConditionA(hpkg, " ");
1485     ok( r == MSICONDITION_NONE, "wrong return val\n");
1486 
1487     r = MsiEvaluateConditionA(hpkg, "LicView <> \"1\"");
1488     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1489 
1490     r = MsiEvaluateConditionA(hpkg, "LicView <> \"0\"");
1491     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1492 
1493     r = MsiEvaluateConditionA(hpkg, "LicView <> LicView");
1494     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1495 
1496     r = MsiEvaluateConditionA(hpkg, "not 0");
1497     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1498 
1499     r = MsiEvaluateConditionA(hpkg, "not LicView");
1500     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1501 
1502     r = MsiEvaluateConditionA(hpkg, "\"Testing\" ~<< \"Testing\"");
1503     ok (r == MSICONDITION_TRUE, "wrong return val\n");
1504 
1505     r = MsiEvaluateConditionA(hpkg, "LicView ~<< \"Testing\"");
1506     ok (r == MSICONDITION_FALSE, "wrong return val\n");
1507 
1508     r = MsiEvaluateConditionA(hpkg, "Not LicView ~<< \"Testing\"");
1509     ok (r == MSICONDITION_TRUE, "wrong return val\n");
1510 
1511     r = MsiEvaluateConditionA(hpkg, "not \"A\"");
1512     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1513 
1514     r = MsiEvaluateConditionA(hpkg, "~not \"A\"");
1515     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1516 
1517     r = MsiEvaluateConditionA(hpkg, "\"0\"");
1518     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1519 
1520     r = MsiEvaluateConditionA(hpkg, "1 and 2");
1521     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1522 
1523     r = MsiEvaluateConditionA(hpkg, "not 0 and 3");
1524     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1525 
1526     r = MsiEvaluateConditionA(hpkg, "not 0 and 0");
1527     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1528 
1529     r = MsiEvaluateConditionA(hpkg, "not 0 or 1");
1530     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1531 
1532     r = MsiEvaluateConditionA(hpkg, "(0)");
1533     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1534 
1535     r = MsiEvaluateConditionA(hpkg, "(((((1))))))");
1536     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1537 
1538     r = MsiEvaluateConditionA(hpkg, "(((((1)))))");
1539     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1540 
1541     r = MsiEvaluateConditionA(hpkg, " \"A\" < \"B\" ");
1542     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1543 
1544     r = MsiEvaluateConditionA(hpkg, " \"A\" > \"B\" ");
1545     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1546 
1547     r = MsiEvaluateConditionA(hpkg, " \"1\" > \"12\" ");
1548     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1549 
1550     r = MsiEvaluateConditionA(hpkg, " \"100\" < \"21\" ");
1551     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1552 
1553     r = MsiEvaluateConditionA(hpkg, "0 < > 0");
1554     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1555 
1556     r = MsiEvaluateConditionA(hpkg, "(1<<1) == 2");
1557     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1558 
1559     r = MsiEvaluateConditionA(hpkg, " \"A\" = \"a\" ");
1560     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1561 
1562     r = MsiEvaluateConditionA(hpkg, " \"A\" ~ = \"a\" ");
1563     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1564 
1565     r = MsiEvaluateConditionA(hpkg, " \"A\" ~= \"a\" ");
1566     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1567 
1568     r = MsiEvaluateConditionA(hpkg, " \"A\" ~= 1 ");
1569     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1570 
1571     r = MsiEvaluateConditionA(hpkg, " \"A\" = 1 ");
1572     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1573 
1574     r = MsiEvaluateConditionA(hpkg, " 1 ~= 1 ");
1575     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1576 
1577     r = MsiEvaluateConditionA(hpkg, " 1 ~= \"1\" ");
1578     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1579 
1580     r = MsiEvaluateConditionA(hpkg, " 1 = \"1\" ");
1581     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1582 
1583     r = MsiEvaluateConditionA(hpkg, " 0 = \"1\" ");
1584     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1585 
1586     r = MsiEvaluateConditionA(hpkg, " 0 < \"100\" ");
1587     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1588 
1589     r = MsiEvaluateConditionA(hpkg, " 100 > \"0\" ");
1590     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1591 
1592     r = MsiEvaluateConditionA(hpkg, "1 XOR 1");
1593     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1594 
1595     r = MsiEvaluateConditionA(hpkg, "1 IMP 1");
1596     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1597 
1598     r = MsiEvaluateConditionA(hpkg, "1 IMP 0");
1599     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1600 
1601     r = MsiEvaluateConditionA(hpkg, "0 IMP 0");
1602     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1603 
1604     r = MsiEvaluateConditionA(hpkg, "0 EQV 0");
1605     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1606 
1607     r = MsiEvaluateConditionA(hpkg, "0 EQV 1");
1608     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1609 
1610     r = MsiEvaluateConditionA(hpkg, "1 IMP 1 OR 0");
1611     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1612 
1613     r = MsiEvaluateConditionA(hpkg, "1 IMPL 1");
1614     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1615 
1616     r = MsiEvaluateConditionA(hpkg, "\"ASFD\" >< \"S\" ");
1617     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1618 
1619     r = MsiEvaluateConditionA(hpkg, "\"ASFD\" ~>< \"s\" ");
1620     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1621 
1622     r = MsiEvaluateConditionA(hpkg, "\"ASFD\" ~>< \"\" ");
1623     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1624 
1625     r = MsiEvaluateConditionA(hpkg, "\"ASFD\" ~>< \"sss\" ");
1626     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1627 
1628     MsiSetPropertyA(hpkg, "mm", "5" );
1629 
1630     r = MsiEvaluateConditionA(hpkg, "mm = 5");
1631     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1632 
1633     r = MsiEvaluateConditionA(hpkg, "mm < 6");
1634     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1635 
1636     r = MsiEvaluateConditionA(hpkg, "mm <= 5");
1637     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1638 
1639     r = MsiEvaluateConditionA(hpkg, "mm > 4");
1640     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1641 
1642     r = MsiEvaluateConditionA(hpkg, "mm < 12");
1643     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1644 
1645     r = MsiEvaluateConditionA(hpkg, "mm = \"5\"");
1646     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1647 
1648     r = MsiEvaluateConditionA(hpkg, "0 = \"\"");
1649     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1650 
1651     r = MsiEvaluateConditionA(hpkg, "0 AND \"\"");
1652     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1653 
1654     r = MsiEvaluateConditionA(hpkg, "1 AND \"\"");
1655     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1656 
1657     r = MsiEvaluateConditionA(hpkg, "1 AND \"1\"");
1658     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1659 
1660     r = MsiEvaluateConditionA(hpkg, "3 >< 1");
1661     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1662 
1663     r = MsiEvaluateConditionA(hpkg, "3 >< 4");
1664     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1665 
1666     r = MsiEvaluateConditionA(hpkg, "NOT 0 AND 0");
1667     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1668 
1669     r = MsiEvaluateConditionA(hpkg, "NOT 0 AND 1");
1670     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1671 
1672     r = MsiEvaluateConditionA(hpkg, "NOT 1 OR 0");
1673     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1674 
1675     r = MsiEvaluateConditionA(hpkg, "0 AND 1 OR 1");
1676     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1677 
1678     r = MsiEvaluateConditionA(hpkg, "0 AND 0 OR 1");
1679     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1680 
1681     r = MsiEvaluateConditionA(hpkg, "NOT 0 AND 1 OR 0");
1682     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1683 
1684     r = MsiEvaluateConditionA(hpkg, "_1 = _1");
1685     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1686 
1687     r = MsiEvaluateConditionA(hpkg, "( 1 AND 1 ) = 2");
1688     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1689 
1690     r = MsiEvaluateConditionA(hpkg, "NOT ( 1 AND 1 )");
1691     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1692 
1693     r = MsiEvaluateConditionA(hpkg, "NOT A AND (BBBBBBBBBB=2 OR CCC=1) AND Ddddddddd");
1694     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1695 
1696     r = MsiEvaluateConditionA(hpkg, "Installed<>\"\"");
1697     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1698 
1699     r = MsiEvaluateConditionA(hpkg, "NOT 1 AND 0");
1700     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1701 
1702     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1703     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1704 
1705     r = MsiEvaluateConditionA(hpkg, "bandalmael<>0");
1706     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1707 
1708     r = MsiEvaluateConditionA(hpkg, "bandalmael<0");
1709     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1710 
1711     r = MsiEvaluateConditionA(hpkg, "bandalmael>0");
1712     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1713 
1714     r = MsiEvaluateConditionA(hpkg, "bandalmael>=0");
1715     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1716 
1717     r = MsiEvaluateConditionA(hpkg, "bandalmael<=0");
1718     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1719 
1720     r = MsiEvaluateConditionA(hpkg, "bandalmael~<>0");
1721     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1722 
1723     MsiSetPropertyA(hpkg, "bandalmael", "0" );
1724     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1725     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1726 
1727     MsiSetPropertyA(hpkg, "bandalmael", "" );
1728     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1729     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1730 
1731     MsiSetPropertyA(hpkg, "bandalmael", "asdf" );
1732     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1733     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1734 
1735     MsiSetPropertyA(hpkg, "bandalmael", "0asdf" );
1736     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1737     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1738 
1739     MsiSetPropertyA(hpkg, "bandalmael", "0 " );
1740     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1741     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1742 
1743     MsiSetPropertyA(hpkg, "bandalmael", "-0" );
1744     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1745     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1746 
1747     MsiSetPropertyA(hpkg, "bandalmael", "0000000000000" );
1748     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1749     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1750 
1751     MsiSetPropertyA(hpkg, "bandalmael", "--0" );
1752     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1753     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1754 
1755     MsiSetPropertyA(hpkg, "bandalmael", "0x00" );
1756     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1757     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1758 
1759     MsiSetPropertyA(hpkg, "bandalmael", "-" );
1760     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1761     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1762 
1763     MsiSetPropertyA(hpkg, "bandalmael", "+0" );
1764     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1765     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1766 
1767     MsiSetPropertyA(hpkg, "bandalmael", "0.0" );
1768     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1769     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1770     r = MsiEvaluateConditionA(hpkg, "bandalmael<>0");
1771     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1772 
1773     MsiSetPropertyA(hpkg, "one", "hi");
1774     MsiSetPropertyA(hpkg, "two", "hithere");
1775     r = MsiEvaluateConditionA(hpkg, "one >< two");
1776     ok( r == MSICONDITION_FALSE, "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", "hello");
1784     MsiSetPropertyA(hpkg, "two", "hi");
1785     r = MsiEvaluateConditionA(hpkg, "one >< two");
1786     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1787 
1788     MsiSetPropertyA(hpkg, "one", "hellohithere");
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", "");
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", "hi");
1799     MsiSetPropertyA(hpkg, "two", "");
1800     r = MsiEvaluateConditionA(hpkg, "one >< two");
1801     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1802 
1803     MsiSetPropertyA(hpkg, "one", "");
1804     MsiSetPropertyA(hpkg, "two", "");
1805     r = MsiEvaluateConditionA(hpkg, "one >< two");
1806     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1807 
1808     MsiSetPropertyA(hpkg, "one", "1234");
1809     MsiSetPropertyA(hpkg, "two", "1");
1810     r = MsiEvaluateConditionA(hpkg, "one >< two");
1811     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1812 
1813     MsiSetPropertyA(hpkg, "one", "one 1234");
1814     MsiSetPropertyA(hpkg, "two", "1");
1815     r = MsiEvaluateConditionA(hpkg, "one >< two");
1816     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1817 
1818     MsiSetPropertyA(hpkg, "one", "hithere");
1819     MsiSetPropertyA(hpkg, "two", "hi");
1820     r = MsiEvaluateConditionA(hpkg, "one << two");
1821     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1822 
1823     MsiSetPropertyA(hpkg, "one", "hi");
1824     MsiSetPropertyA(hpkg, "two", "hithere");
1825     r = MsiEvaluateConditionA(hpkg, "one << two");
1826     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1827 
1828     MsiSetPropertyA(hpkg, "one", "hi");
1829     MsiSetPropertyA(hpkg, "two", "hi");
1830     r = MsiEvaluateConditionA(hpkg, "one << two");
1831     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1832 
1833     MsiSetPropertyA(hpkg, "one", "abcdhithere");
1834     MsiSetPropertyA(hpkg, "two", "hi");
1835     r = MsiEvaluateConditionA(hpkg, "one << two");
1836     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1837 
1838     MsiSetPropertyA(hpkg, "one", "");
1839     MsiSetPropertyA(hpkg, "two", "hi");
1840     r = MsiEvaluateConditionA(hpkg, "one << two");
1841     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1842 
1843     MsiSetPropertyA(hpkg, "one", "hithere");
1844     MsiSetPropertyA(hpkg, "two", "");
1845     r = MsiEvaluateConditionA(hpkg, "one << two");
1846     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1847 
1848     MsiSetPropertyA(hpkg, "one", "");
1849     MsiSetPropertyA(hpkg, "two", "");
1850     r = MsiEvaluateConditionA(hpkg, "one << two");
1851     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1852 
1853     MsiSetPropertyA(hpkg, "one", "1234");
1854     MsiSetPropertyA(hpkg, "two", "1");
1855     r = MsiEvaluateConditionA(hpkg, "one << two");
1856     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1857 
1858     MsiSetPropertyA(hpkg, "one", "1234 one");
1859     MsiSetPropertyA(hpkg, "two", "1");
1860     r = MsiEvaluateConditionA(hpkg, "one << two");
1861     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1862 
1863     MsiSetPropertyA(hpkg, "one", "hithere");
1864     MsiSetPropertyA(hpkg, "two", "there");
1865     r = MsiEvaluateConditionA(hpkg, "one >> two");
1866     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1867 
1868     MsiSetPropertyA(hpkg, "one", "hithere");
1869     MsiSetPropertyA(hpkg, "two", "hi");
1870     r = MsiEvaluateConditionA(hpkg, "one >> two");
1871     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1872 
1873     MsiSetPropertyA(hpkg, "one", "there");
1874     MsiSetPropertyA(hpkg, "two", "hithere");
1875     r = MsiEvaluateConditionA(hpkg, "one >> two");
1876     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1877 
1878     MsiSetPropertyA(hpkg, "one", "there");
1879     MsiSetPropertyA(hpkg, "two", "there");
1880     r = MsiEvaluateConditionA(hpkg, "one >> two");
1881     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1882 
1883     MsiSetPropertyA(hpkg, "one", "abcdhithere");
1884     MsiSetPropertyA(hpkg, "two", "hi");
1885     r = MsiEvaluateConditionA(hpkg, "one >> two");
1886     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1887 
1888     MsiSetPropertyA(hpkg, "one", "");
1889     MsiSetPropertyA(hpkg, "two", "there");
1890     r = MsiEvaluateConditionA(hpkg, "one >> two");
1891     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1892 
1893     MsiSetPropertyA(hpkg, "one", "there");
1894     MsiSetPropertyA(hpkg, "two", "");
1895     r = MsiEvaluateConditionA(hpkg, "one >> two");
1896     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1897 
1898     MsiSetPropertyA(hpkg, "one", "");
1899     MsiSetPropertyA(hpkg, "two", "");
1900     r = MsiEvaluateConditionA(hpkg, "one >> two");
1901     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1902 
1903     MsiSetPropertyA(hpkg, "one", "1234");
1904     MsiSetPropertyA(hpkg, "two", "4");
1905     r = MsiEvaluateConditionA(hpkg, "one >> two");
1906     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1907 
1908     MsiSetPropertyA(hpkg, "one", "one 1234");
1909     MsiSetPropertyA(hpkg, "two", "4");
1910     r = MsiEvaluateConditionA(hpkg, "one >> two");
1911     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1912 
1913     MsiSetPropertyA(hpkg, "MsiNetAssemblySupport", NULL);  /* make sure it's empty */
1914 
1915     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322\"");
1916     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1917 
1918     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport > \"1.1.4322\"");
1919     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1920 
1921     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport >= \"1.1.4322\"");
1922     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1923 
1924     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport <= \"1.1.4322\"");
1925     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1926 
1927     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport <> \"1.1.4322\"");
1928     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1929 
1930     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport ~< \"1.1.4322\"");
1931     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1932 
1933     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"abcd\"");
1934     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1935 
1936     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a1.1.4322\"");
1937     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1938 
1939     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322a\"");
1940     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1941 
1942     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"0000001.1.4322\"");
1943     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1944 
1945     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322.1\"");
1946     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1947 
1948     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322.1.1\"");
1949     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1950 
1951     r = MsiEvaluateConditionA(hpkg, "\"2\" < \"1.1");
1952     ok( r == MSICONDITION_ERROR, "wrong return val (%d)\n", r);
1953 
1954     r = MsiEvaluateConditionA(hpkg, "\"2\" < \"1.1\"");
1955     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1956 
1957     r = MsiEvaluateConditionA(hpkg, "\"2\" < \"12.1\"");
1958     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1959 
1960     r = MsiEvaluateConditionA(hpkg, "\"02.1\" < \"2.11\"");
1961     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1962 
1963     r = MsiEvaluateConditionA(hpkg, "\"02.1.1\" < \"2.1\"");
1964     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1965 
1966     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1\"");
1967     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1968 
1969     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1\"");
1970     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1971 
1972     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"0\"");
1973     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1974 
1975     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"-1\"");
1976     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1977 
1978     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a\"");
1979     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1980 
1981     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"!\"");
1982     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1983 
1984     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"!\"");
1985     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1986 
1987     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"/\"");
1988     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1989 
1990     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \" \"");
1991     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1992 
1993     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"azAZ_\"");
1994     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1995 
1996     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a[a]\"");
1997     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1998 
1999     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a[a]a\"");
2000     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2001 
2002     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"[a]\"");
2003     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2004 
2005     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"[a]a\"");
2006     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2007 
2008     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"{a}\"");
2009     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2010 
2011     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"{a\"");
2012     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2013 
2014     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"[a\"");
2015     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2016 
2017     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a{\"");
2018     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2019 
2020     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a]\"");
2021     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2022 
2023     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"A\"");
2024     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2025 
2026     MsiSetPropertyA(hpkg, "MsiNetAssemblySupport", "1.1.4322");
2027     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322\"");
2028     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2029 
2030     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.14322\"");
2031     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2032 
2033     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.5\"");
2034     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2035 
2036     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1\"");
2037     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2038 
2039     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1\"");
2040     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2041 
2042     MsiSetPropertyA(hpkg, "one", "1");
2043     r = MsiEvaluateConditionA(hpkg, "one < \"1\"");
2044     ok( r == MSICONDITION_FALSE, "wrong return val\n");
2045 
2046     MsiSetPropertyA(hpkg, "X", "5.0");
2047 
2048     r = MsiEvaluateConditionA(hpkg, "X != \"\"");
2049     ok( r == MSICONDITION_ERROR, "wrong return val (%d)\n", r);
2050 
2051     r = MsiEvaluateConditionA(hpkg, "X =\"5.0\"");
2052     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2053 
2054     r = MsiEvaluateConditionA(hpkg, "X =\"5.1\"");
2055     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2056 
2057     r = MsiEvaluateConditionA(hpkg, "X =\"6.0\"");
2058     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2059 
2060     r = MsiEvaluateConditionA(hpkg, "X =\"5.0\" or X =\"5.1\" or X =\"6.0\"");
2061     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2062 
2063     r = MsiEvaluateConditionA(hpkg, "(X =\"5.0\" or X =\"5.1\" or X =\"6.0\")");
2064     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2065 
2066     r = MsiEvaluateConditionA(hpkg, "X !=\"\" and (X =\"5.0\" or X =\"5.1\" or X =\"6.0\")");
2067     ok( r == MSICONDITION_ERROR, "wrong return val (%d)\n", r);
2068 
2069     /* feature doesn't exist */
2070     r = MsiEvaluateConditionA(hpkg, "&nofeature");
2071     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2072     r = MsiEvaluateConditionA(hpkg, "&nofeature=\"\"");
2073     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2074     r = MsiEvaluateConditionA(hpkg, "!nofeature=\"\"");
2075     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2076     MsiEvaluateConditionA(hpkg, "$nocomponent=\"\"");
2077     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2078     MsiEvaluateConditionA(hpkg, "?nocomponent=\"\"");
2079     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2080 
2081     MsiSetPropertyA(hpkg, "A", "2");
2082     MsiSetPropertyA(hpkg, "X", "50");
2083 
2084     r = MsiEvaluateConditionA(hpkg, "2 <= X");
2085     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2086 
2087     r = MsiEvaluateConditionA(hpkg, "A <= X");
2088     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2089 
2090     r = MsiEvaluateConditionA(hpkg, "A <= 50");
2091     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2092 
2093     MsiSetPropertyA(hpkg, "X", "50val");
2094 
2095     r = MsiEvaluateConditionA(hpkg, "2 <= X");
2096     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2097 
2098     r = MsiEvaluateConditionA(hpkg, "A <= X");
2099     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2100 
2101     MsiSetPropertyA(hpkg, "A", "7");
2102     MsiSetPropertyA(hpkg, "X", "50");
2103 
2104     r = MsiEvaluateConditionA(hpkg, "7 <= X");
2105     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2106 
2107     r = MsiEvaluateConditionA(hpkg, "A <= X");
2108     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2109 
2110     r = MsiEvaluateConditionA(hpkg, "A <= 50");
2111     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2112 
2113     MsiSetPropertyA(hpkg, "X", "50val");
2114 
2115     r = MsiEvaluateConditionA(hpkg, "2 <= X");
2116     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2117 
2118     r = MsiEvaluateConditionA(hpkg, "A <= X");
2119     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2120 
2121     r = MsiEvaluateConditionW(hpkg, cond1);
2122     ok( r == MSICONDITION_TRUE || broken(r == MSICONDITION_FALSE),
2123         "wrong return val (%d)\n", r);
2124 
2125     r = MsiEvaluateConditionW(hpkg, cond2);
2126     ok( r == MSICONDITION_FALSE || broken(r == MSICONDITION_TRUE),
2127         "wrong return val (%d)\n", r);
2128 
2129     r = MsiEvaluateConditionW(hpkg, cond3);
2130     ok( r == MSICONDITION_TRUE || broken(r == MSICONDITION_FALSE),
2131         "wrong return val (%d)\n", r);
2132 
2133     r = MsiEvaluateConditionW(hpkg, cond4);
2134     ok( r == MSICONDITION_FALSE || broken(r == MSICONDITION_TRUE),
2135         "wrong return val (%d)\n", r);
2136 
2137     MsiCloseHandle( hpkg );
2138     DeleteFileA(msifile);
2139 }
2140 
2141 static BOOL check_prop_empty( MSIHANDLE hpkg, const char * prop)
2142 {
2143     UINT r;
2144     DWORD sz;
2145     char buffer[2];
2146 
2147     sz = sizeof buffer;
2148     strcpy(buffer,"x");
2149     r = MsiGetPropertyA( hpkg, prop, buffer, &sz );
2150     return r == ERROR_SUCCESS && buffer[0] == 0 && sz == 0;
2151 }
2152 
2153 static void test_props(void)
2154 {
2155     MSIHANDLE hpkg, hdb;
2156     UINT r;
2157     DWORD sz;
2158     char buffer[0x100];
2159 
2160     hdb = create_package_db();
2161 
2162     create_property_table(hdb);
2163     add_property_entry(hdb, "'MetadataCompName', 'Photoshop.dll'");
2164 
2165     r = package_from_db( hdb, &hpkg );
2166     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2167     {
2168         skip("Not enough rights to perform tests\n");
2169         DeleteFileA(msifile);
2170         return;
2171     }
2172     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
2173 
2174     /* test invalid values */
2175     r = MsiGetPropertyA( 0, NULL, NULL, NULL );
2176     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
2177 
2178     r = MsiGetPropertyA( hpkg, NULL, NULL, NULL );
2179     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
2180 
2181     r = MsiGetPropertyA( hpkg, "boo", NULL, NULL );
2182     ok( r == ERROR_SUCCESS, "wrong return val\n");
2183 
2184     r = MsiGetPropertyA( hpkg, "boo", buffer, NULL );
2185     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
2186 
2187     /* test retrieving an empty/nonexistent property */
2188     sz = sizeof buffer;
2189     r = MsiGetPropertyA( hpkg, "boo", NULL, &sz );
2190     ok( r == ERROR_SUCCESS, "wrong return val\n");
2191     ok( sz == 0, "wrong size returned\n");
2192 
2193     check_prop_empty( hpkg, "boo");
2194     sz = 0;
2195     strcpy(buffer,"x");
2196     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2197     ok( r == ERROR_MORE_DATA, "wrong return val\n");
2198     ok( !strcmp(buffer,"x"), "buffer was changed\n");
2199     ok( sz == 0, "wrong size returned\n");
2200 
2201     sz = 1;
2202     strcpy(buffer,"x");
2203     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2204     ok( r == ERROR_SUCCESS, "wrong return val\n");
2205     ok( buffer[0] == 0, "buffer was not changed\n");
2206     ok( sz == 0, "wrong size returned\n");
2207 
2208     /* set the property to something */
2209     r = MsiSetPropertyA( 0, NULL, NULL );
2210     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
2211 
2212     r = MsiSetPropertyA( hpkg, NULL, NULL );
2213     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
2214 
2215     r = MsiSetPropertyA( hpkg, "", NULL );
2216     ok( r == ERROR_SUCCESS, "wrong return val\n");
2217 
2218     /* try set and get some illegal property identifiers */
2219     r = MsiSetPropertyA( hpkg, "", "asdf" );
2220     ok( r == ERROR_FUNCTION_FAILED, "wrong return val\n");
2221 
2222     r = MsiSetPropertyA( hpkg, "=", "asdf" );
2223     ok( r == ERROR_SUCCESS, "wrong return val\n");
2224 
2225     r = MsiSetPropertyA( hpkg, " ", "asdf" );
2226     ok( r == ERROR_SUCCESS, "wrong return val\n");
2227 
2228     r = MsiSetPropertyA( hpkg, "'", "asdf" );
2229     ok( r == ERROR_SUCCESS, "wrong return val\n");
2230 
2231     sz = sizeof buffer;
2232     buffer[0]=0;
2233     r = MsiGetPropertyA( hpkg, "'", buffer, &sz );
2234     ok( r == ERROR_SUCCESS, "wrong return val\n");
2235     ok( !strcmp(buffer,"asdf"), "buffer was not changed\n");
2236 
2237     /* set empty values */
2238     r = MsiSetPropertyA( hpkg, "boo", NULL );
2239     ok( r == ERROR_SUCCESS, "wrong return val\n");
2240     ok( check_prop_empty( hpkg, "boo"), "prop wasn't empty\n");
2241 
2242     r = MsiSetPropertyA( hpkg, "boo", "" );
2243     ok( r == ERROR_SUCCESS, "wrong return val\n");
2244     ok( check_prop_empty( hpkg, "boo"), "prop wasn't empty\n");
2245 
2246     /* set a non-empty value */
2247     r = MsiSetPropertyA( hpkg, "boo", "xyz" );
2248     ok( r == ERROR_SUCCESS, "wrong return val\n");
2249 
2250     sz = 1;
2251     strcpy(buffer,"x");
2252     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2253     ok( r == ERROR_MORE_DATA, "wrong return val\n");
2254     ok( buffer[0] == 0, "buffer was not changed\n");
2255     ok( sz == 3, "wrong size returned\n");
2256 
2257     sz = 4;
2258     strcpy(buffer,"x");
2259     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2260     ok( r == ERROR_SUCCESS, "wrong return val\n");
2261     ok( !strcmp(buffer,"xyz"), "buffer was not changed\n");
2262     ok( sz == 3, "wrong size returned\n");
2263 
2264     sz = 3;
2265     strcpy(buffer,"x");
2266     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2267     ok( r == ERROR_MORE_DATA, "wrong return val\n");
2268     ok( !strcmp(buffer,"xy"), "buffer was not changed\n");
2269     ok( sz == 3, "wrong size returned\n");
2270 
2271     r = MsiSetPropertyA(hpkg, "SourceDir", "foo");
2272     ok( r == ERROR_SUCCESS, "wrong return val\n");
2273 
2274     sz = 4;
2275     r = MsiGetPropertyA(hpkg, "SOURCEDIR", buffer, &sz);
2276     ok( r == ERROR_SUCCESS, "wrong return val\n");
2277     ok( !strcmp(buffer,""), "buffer wrong\n");
2278     ok( sz == 0, "wrong size returned\n");
2279 
2280     sz = 4;
2281     r = MsiGetPropertyA(hpkg, "SOMERANDOMNAME", buffer, &sz);
2282     ok( r == ERROR_SUCCESS, "wrong return val\n");
2283     ok( !strcmp(buffer,""), "buffer wrong\n");
2284     ok( sz == 0, "wrong size returned\n");
2285 
2286     sz = 4;
2287     r = MsiGetPropertyA(hpkg, "SourceDir", buffer, &sz);
2288     ok( r == ERROR_SUCCESS, "wrong return val\n");
2289     ok( !strcmp(buffer,"foo"), "buffer wrong\n");
2290     ok( sz == 3, "wrong size returned\n");
2291 
2292     r = MsiSetPropertyA(hpkg, "MetadataCompName", "Photoshop.dll");
2293     ok( r == ERROR_SUCCESS, "wrong return val\n");
2294 
2295     sz = 0;
2296     r = MsiGetPropertyA(hpkg, "MetadataCompName", NULL, &sz );
2297     ok( r == ERROR_SUCCESS, "return wrong\n");
2298     ok( sz == 13, "size wrong (%d)\n", sz);
2299 
2300     sz = 13;
2301     r = MsiGetPropertyA(hpkg, "MetadataCompName", buffer, &sz );
2302     ok( r == ERROR_MORE_DATA, "return wrong\n");
2303     ok( !strcmp(buffer,"Photoshop.dl"), "buffer wrong\n");
2304 
2305     r = MsiSetPropertyA(hpkg, "property", "value");
2306     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2307 
2308     sz = 6;
2309     r = MsiGetPropertyA(hpkg, "property", buffer, &sz);
2310     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2311     ok( !strcmp(buffer, "value"), "Expected value, got %s\n", buffer);
2312 
2313     r = MsiSetPropertyA(hpkg, "property", NULL);
2314     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2315 
2316     sz = 6;
2317     r = MsiGetPropertyA(hpkg, "property", buffer, &sz);
2318     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2319     ok(!buffer[0], "Expected empty string, got %s\n", buffer);
2320 
2321     MsiCloseHandle( hpkg );
2322     DeleteFileA(msifile);
2323 }
2324 
2325 static BOOL find_prop_in_property(MSIHANDLE hdb, LPCSTR prop, LPCSTR val, int len)
2326 {
2327     MSIHANDLE hview, hrec;
2328     BOOL found = FALSE;
2329     CHAR buffer[MAX_PATH];
2330     DWORD sz;
2331     UINT r;
2332 
2333     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Property`", &hview);
2334     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
2335     r = MsiViewExecute(hview, 0);
2336     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
2337 
2338     if (len < 0) len = lstrlenA(val);
2339 
2340     while (r == ERROR_SUCCESS && !found)
2341     {
2342         r = MsiViewFetch(hview, &hrec);
2343         if (r != ERROR_SUCCESS) break;
2344 
2345         sz = MAX_PATH;
2346         r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
2347         if (r == ERROR_SUCCESS && !lstrcmpA(buffer, prop))
2348         {
2349             sz = MAX_PATH;
2350             r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
2351             if (r == ERROR_SUCCESS && !memcmp(buffer, val, len) && !buffer[len])
2352             {
2353                 ok(sz == len, "wrong size %u\n", sz);
2354                 found = TRUE;
2355             }
2356         }
2357 
2358         MsiCloseHandle(hrec);
2359     }
2360     MsiViewClose(hview);
2361     MsiCloseHandle(hview);
2362     return found;
2363 }
2364 
2365 static void test_property_table(void)
2366 {
2367     const char *query;
2368     UINT r;
2369     MSIHANDLE hpkg, hdb, hrec;
2370     char buffer[MAX_PATH], package[10];
2371     DWORD sz;
2372     BOOL found;
2373 
2374     hdb = create_package_db();
2375     ok( hdb, "failed to create package\n");
2376 
2377     r = package_from_db(hdb, &hpkg);
2378     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2379     {
2380         skip("Not enough rights to perform tests\n");
2381         DeleteFileA(msifile);
2382         return;
2383     }
2384     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
2385 
2386     MsiCloseHandle(hdb);
2387 
2388     hdb = MsiGetActiveDatabase(hpkg);
2389 
2390     query = "CREATE TABLE `_Property` ( "
2391         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
2392     r = run_query(hdb, query);
2393     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2394 
2395     MsiCloseHandle(hdb);
2396     MsiCloseHandle(hpkg);
2397     DeleteFileA(msifile);
2398 
2399     hdb = create_package_db();
2400     ok( hdb, "failed to create package\n");
2401 
2402     query = "CREATE TABLE `_Property` ( "
2403         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
2404     r = run_query(hdb, query);
2405     ok(r == ERROR_SUCCESS, "failed to create table\n");
2406 
2407     query = "ALTER `_Property` ADD `foo` INTEGER";
2408     r = run_query(hdb, query);
2409     ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to add column\n");
2410 
2411     query = "ALTER TABLE `_Property` ADD `foo` INTEGER";
2412     r = run_query(hdb, query);
2413     ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to add column\n");
2414 
2415     query = "ALTER TABLE `_Property` ADD `extra` INTEGER";
2416     r = run_query(hdb, query);
2417     ok(r == ERROR_SUCCESS, "failed to add column\n");
2418 
2419     sprintf(package, "#%i", hdb);
2420     r = MsiOpenPackageA(package, &hpkg);
2421     ok(r != ERROR_SUCCESS, "MsiOpenPackage succeeded\n");
2422     if (r == ERROR_SUCCESS)
2423         MsiCloseHandle(hpkg);
2424 
2425     r = MsiCloseHandle(hdb);
2426     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed %u\n", r);
2427 
2428     hdb = create_package_db();
2429     ok (hdb, "failed to create package database\n");
2430 
2431     create_property_table(hdb);
2432     add_property_entry(hdb, "'prop', 'val'");
2433 
2434     create_custom_action_table(hdb);
2435     add_custom_action_entry( hdb, "'EmbedNull', 51, 'prop2', '[~]np'" );
2436 
2437     r = package_from_db(hdb, &hpkg);
2438     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
2439 
2440     MsiCloseHandle(hdb);
2441 
2442     sz = MAX_PATH;
2443     r = MsiGetPropertyA(hpkg, "prop", buffer, &sz);
2444     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2445     ok(!lstrcmpA(buffer, "val"), "Expected val, got %s\n", buffer);
2446 
2447     hdb = MsiGetActiveDatabase(hpkg);
2448 
2449     found = find_prop_in_property(hdb, "prop", "val", -1);
2450     ok(found, "prop should be in the _Property table\n");
2451 
2452     add_property_entry(hdb, "'dantes', 'mercedes'");
2453 
2454     query = "SELECT * FROM `_Property` WHERE `Property` = 'dantes'";
2455     r = do_query(hdb, query, &hrec);
2456     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2457 
2458     found = find_prop_in_property(hdb, "dantes", "mercedes", -1);
2459     ok(found == FALSE, "dantes should not be in the _Property table\n");
2460 
2461     sz = MAX_PATH;
2462     lstrcpyA(buffer, "aaa");
2463     r = MsiGetPropertyA(hpkg, "dantes", buffer, &sz);
2464     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2465     ok(!buffer[0], "Expected empty string, got %s\n", buffer);
2466 
2467     r = MsiSetPropertyA(hpkg, "dantes", "mercedes");
2468     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2469 
2470     found = find_prop_in_property(hdb, "dantes", "mercedes", -1);
2471     ok(found == TRUE, "dantes should be in the _Property table\n");
2472 
2473     r = MsiDoActionA( hpkg, "EmbedNull" );
2474     ok( r == ERROR_SUCCESS, "EmbedNull failed: %d\n", r);
2475 
2476     sz = MAX_PATH;
2477     memset( buffer, 'a', sizeof(buffer) );
2478     r = MsiGetPropertyA( hpkg, "prop2", buffer, &sz );
2479     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2480     ok( !memcmp( buffer, "\0np", sizeof("\0np") ), "wrong value\n");
2481     ok( sz == sizeof("\0np") - 1, "got %u\n", sz );
2482 
2483     found = find_prop_in_property(hdb, "prop2", "\0np", 3);
2484     ok(found == TRUE, "prop2 should be in the _Property table\n");
2485 
2486     MsiCloseHandle(hdb);
2487     MsiCloseHandle(hpkg);
2488     DeleteFileA(msifile);
2489 }
2490 
2491 static UINT try_query_param( MSIHANDLE hdb, LPCSTR szQuery, MSIHANDLE hrec )
2492 {
2493     MSIHANDLE htab = 0;
2494     UINT res;
2495 
2496     res = MsiDatabaseOpenViewA( hdb, szQuery, &htab );
2497     if( res == ERROR_SUCCESS )
2498     {
2499         UINT r;
2500 
2501         r = MsiViewExecute( htab, hrec );
2502         if( r != ERROR_SUCCESS )
2503         {
2504             res = r;
2505             fprintf(stderr,"MsiViewExecute failed %08x\n", res);
2506         }
2507 
2508         r = MsiViewClose( htab );
2509         if( r != ERROR_SUCCESS )
2510             res = r;
2511 
2512         r = MsiCloseHandle( htab );
2513         if( r != ERROR_SUCCESS )
2514             res = r;
2515     }
2516     return res;
2517 }
2518 
2519 static UINT try_query( MSIHANDLE hdb, LPCSTR szQuery )
2520 {
2521     return try_query_param( hdb, szQuery, 0 );
2522 }
2523 
2524 static void set_summary_str(MSIHANDLE hdb, DWORD pid, LPCSTR value)
2525 {
2526     MSIHANDLE summary;
2527     UINT r;
2528 
2529     r = MsiGetSummaryInformationA(hdb, NULL, 1, &summary);
2530     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2531 
2532     r = MsiSummaryInfoSetPropertyA(summary, pid, VT_LPSTR, 0, NULL, value);
2533     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2534 
2535     r = MsiSummaryInfoPersist(summary);
2536     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2537 
2538     MsiCloseHandle(summary);
2539 }
2540 
2541 static void set_summary_dword(MSIHANDLE hdb, DWORD pid, DWORD value)
2542 {
2543     MSIHANDLE summary;
2544     UINT r;
2545 
2546     r = MsiGetSummaryInformationA(hdb, NULL, 1, &summary);
2547     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2548 
2549     r = MsiSummaryInfoSetPropertyA(summary, pid, VT_I4, value, NULL, NULL);
2550     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2551 
2552     r = MsiSummaryInfoPersist(summary);
2553     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2554 
2555     MsiCloseHandle(summary);
2556 }
2557 
2558 static void test_msipackage(void)
2559 {
2560     MSIHANDLE hdb = 0, hpack = 100;
2561     UINT r;
2562     const char *query;
2563     char name[10];
2564 
2565     /* NULL szPackagePath */
2566     r = MsiOpenPackageA(NULL, &hpack);
2567     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2568 
2569     /* empty szPackagePath */
2570     r = MsiOpenPackageA("", &hpack);
2571     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2572     {
2573         skip("Not enough rights to perform tests\n");
2574         return;
2575     }
2576     todo_wine
2577     {
2578         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2579     }
2580 
2581     if (r == ERROR_SUCCESS)
2582         MsiCloseHandle(hpack);
2583 
2584     /* nonexistent szPackagePath */
2585     r = MsiOpenPackageA("nonexistent", &hpack);
2586     ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
2587 
2588     /* NULL hProduct */
2589     r = MsiOpenPackageA(msifile, NULL);
2590     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2591 
2592     name[0]='#';
2593     name[1]=0;
2594     r = MsiOpenPackageA(name, &hpack);
2595     ok(r == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", r);
2596 
2597     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
2598     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2599 
2600     /* database exists, but is empty */
2601     sprintf(name, "#%d", hdb);
2602     r = MsiOpenPackageA(name, &hpack);
2603     ok(r == ERROR_INSTALL_PACKAGE_INVALID,
2604        "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
2605 
2606     query = "CREATE TABLE `Property` ( "
2607             "`Property` CHAR(72), `Value` CHAR(0) "
2608             "PRIMARY KEY `Property`)";
2609     r = try_query(hdb, query);
2610     ok(r == ERROR_SUCCESS, "failed to create Properties table\n");
2611 
2612     query = "CREATE TABLE `InstallExecuteSequence` ("
2613             "`Action` CHAR(72), `Condition` CHAR(0), `Sequence` INTEGER "
2614             "PRIMARY KEY `Action`)";
2615     r = try_query(hdb, query);
2616     ok(r == ERROR_SUCCESS, "failed to create InstallExecuteSequence table\n");
2617 
2618     /* a few key tables exist */
2619     sprintf(name, "#%d", hdb);
2620     r = MsiOpenPackageA(name, &hpack);
2621     ok(r == ERROR_INSTALL_PACKAGE_INVALID,
2622        "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
2623 
2624     MsiCloseHandle(hdb);
2625     DeleteFileA(msifile);
2626 
2627     /* start with a clean database to show what constitutes a valid package */
2628     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
2629     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2630 
2631     sprintf(name, "#%d", hdb);
2632 
2633     /* The following summary information props must exist:
2634      *  - PID_REVNUMBER
2635      *  - PID_PAGECOUNT
2636      */
2637 
2638     set_summary_dword(hdb, PID_PAGECOUNT, 100);
2639     r = MsiOpenPackageA(name, &hpack);
2640     ok(r == ERROR_INSTALL_PACKAGE_INVALID,
2641        "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
2642 
2643     set_summary_str(hdb, PID_REVNUMBER, "{004757CD-5092-49C2-AD20-28E1CE0DF5F2}");
2644     r = MsiOpenPackageA(name, &hpack);
2645     ok(r == ERROR_SUCCESS,
2646        "Expected ERROR_SUCCESS, got %d\n", r);
2647 
2648     MsiCloseHandle(hpack);
2649     MsiCloseHandle(hdb);
2650     DeleteFileA(msifile);
2651 }
2652 
2653 static void test_formatrecord2(void)
2654 {
2655     MSIHANDLE hpkg, hrec ;
2656     char buffer[0x100];
2657     DWORD sz;
2658     UINT r;
2659 
2660     r = package_from_db(create_package_db(), &hpkg);
2661     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2662     {
2663         skip("Not enough rights to perform tests\n");
2664         DeleteFileA(msifile);
2665         return;
2666     }
2667     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
2668 
2669     r = MsiSetPropertyA(hpkg, "Manufacturer", " " );
2670     ok( r == ERROR_SUCCESS, "set property failed\n");
2671 
2672     hrec = MsiCreateRecord(2);
2673     ok(hrec, "create record failed\n");
2674 
2675     r = MsiRecordSetStringA( hrec, 0, "[ProgramFilesFolder][Manufacturer]\\asdf");
2676     ok( r == ERROR_SUCCESS, "format record failed\n");
2677 
2678     buffer[0] = 0;
2679     sz = sizeof buffer;
2680     r = MsiFormatRecordA( hpkg, hrec, buffer, &sz );
2681     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2682 
2683     r = MsiRecordSetStringA(hrec, 0, "[foo][1]");
2684     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2685     r = MsiRecordSetStringA(hrec, 1, "hoo");
2686     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2687     sz = sizeof buffer;
2688     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2689     ok( sz == 3, "size wrong\n");
2690     ok( 0 == strcmp(buffer,"hoo"), "wrong output %s\n",buffer);
2691     ok( r == ERROR_SUCCESS, "format failed\n");
2692 
2693     r = MsiRecordSetStringA(hrec, 0, "x[~]x");
2694     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2695     sz = sizeof buffer;
2696     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2697     ok( sz == 3, "size wrong\n");
2698     ok( 0 == strcmp(buffer,"x"), "wrong output %s\n",buffer);
2699     ok( r == ERROR_SUCCESS, "format failed\n");
2700 
2701     r = MsiRecordSetStringA(hrec, 0, "[foo.$%}][1]");
2702     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2703     r = MsiRecordSetStringA(hrec, 1, "hoo");
2704     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2705     sz = sizeof buffer;
2706     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2707     ok( sz == 3, "size wrong\n");
2708     ok( 0 == strcmp(buffer,"hoo"), "wrong output %s\n",buffer);
2709     ok( r == ERROR_SUCCESS, "format failed\n");
2710 
2711     r = MsiRecordSetStringA(hrec, 0, "[\\[]");
2712     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2713     sz = sizeof buffer;
2714     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2715     ok( sz == 1, "size wrong\n");
2716     ok( 0 == strcmp(buffer,"["), "wrong output %s\n",buffer);
2717     ok( r == ERROR_SUCCESS, "format failed\n");
2718 
2719     SetEnvironmentVariableA("FOO", "BAR");
2720     r = MsiRecordSetStringA(hrec, 0, "[%FOO]");
2721     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2722     sz = sizeof buffer;
2723     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2724     ok( sz == 3, "size wrong\n");
2725     ok( 0 == strcmp(buffer,"BAR"), "wrong output %s\n",buffer);
2726     ok( r == ERROR_SUCCESS, "format failed\n");
2727 
2728     r = MsiRecordSetStringA(hrec, 0, "[[1]]");
2729     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2730     r = MsiRecordSetStringA(hrec, 1, "%FOO");
2731     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2732     sz = sizeof buffer;
2733     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2734     ok( sz == 3, "size wrong\n");
2735     ok( 0 == strcmp(buffer,"BAR"), "wrong output %s\n",buffer);
2736     ok( r == ERROR_SUCCESS, "format failed\n");
2737 
2738     MsiCloseHandle( hrec );
2739     MsiCloseHandle( hpkg );
2740     DeleteFileA(msifile);
2741 }
2742 
2743 static void test_formatrecord_tables(void)
2744 {
2745     MSIHANDLE hdb, hrec, hpkg = 0;
2746     CHAR buf[MAX_PATH];
2747     CHAR curr_dir[MAX_PATH];
2748     CHAR expected[MAX_PATH];
2749     CHAR root[MAX_PATH];
2750     DWORD size;
2751     UINT r;
2752 
2753     GetCurrentDirectoryA( MAX_PATH, curr_dir );
2754 
2755     hdb = create_package_db();
2756     ok ( hdb, "failed to create package database\n");
2757 
2758     add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'" );
2759     add_directory_entry( hdb, "'ReallyLongDir', 'TARGETDIR', "
2760                              "'I am a really long directory'" );
2761 
2762     create_feature_table( hdb );
2763     add_feature_entry( hdb, "'occipitofrontalis', '', '', '', 2, 1, '', 0" );
2764 
2765     create_component_table( hdb );
2766     add_component_entry( hdb, "'frontal', '', 'TARGETDIR', 0, '', 'frontal_file'" );
2767     add_component_entry( hdb, "'parietal', '', 'TARGETDIR', 1, '', 'parietal_file'" );
2768     add_component_entry( hdb, "'temporal', '', 'ReallyLongDir', 0, '', 'temporal_file'" );
2769 
2770     create_feature_components_table( hdb );
2771     add_feature_components_entry( hdb, "'occipitofrontalis', 'frontal'" );
2772     add_feature_components_entry( hdb, "'occipitofrontalis', 'parietal'" );
2773     add_feature_components_entry( hdb, "'occipitofrontalis', 'temporal'" );
2774 
2775     create_file_table( hdb );
2776     add_file_entry( hdb, "'frontal_file', 'frontal', 'frontal.txt', 0, '', '1033', 8192, 1" );
2777     add_file_entry( hdb, "'parietal_file', 'parietal', 'parietal.txt', 0, '', '1033', 8192, 1" );
2778     add_file_entry( hdb, "'temporal_file', 'temporal', 'temporal.txt', 0, '', '1033', 8192, 1" );
2779 
2780     create_custom_action_table( hdb );
2781     add_custom_action_entry( hdb, "'MyCustom', 51, 'prop', '[!temporal_file]'" );
2782     add_custom_action_entry( hdb, "'EscapeIt1', 51, 'prop', '[\\[]Bracket Text[\\]]'" );
2783     add_custom_action_entry( hdb, "'EscapeIt2', 51, 'prop', '[\\xabcd]'" );
2784     add_custom_action_entry( hdb, "'EscapeIt3', 51, 'prop', '[abcd\\xefgh]'" );
2785     add_custom_action_entry( hdb, "'EmbedNull', 51, 'prop', '[~]np'" );
2786 
2787     r = package_from_db( hdb, &hpkg );
2788     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2789     {
2790         skip("Not enough rights to perform tests\n");
2791         MsiCloseHandle( hdb );
2792         DeleteFileA( msifile );
2793         return;
2794     }
2795     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
2796 
2797     MsiCloseHandle( hdb );
2798 
2799     r = MsiSetPropertyA( hpkg, "imaprop", "ringer" );
2800     ok( r == ERROR_SUCCESS, "cannot set property: %d\n", r);
2801 
2802     hrec = MsiCreateRecord( 1 );
2803 
2804     /* property doesn't exist */
2805     size = MAX_PATH;
2806     /*MsiRecordSetStringA( hrec, 0, "[1]" ); */
2807     MsiRecordSetStringA( hrec, 1, "[idontexist]" );
2808     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2809     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2810     ok( !lstrcmpA( buf, "1:  " ), "Expected '1:  ', got %s\n", buf );
2811 
2812     /* property exists */
2813     size = MAX_PATH;
2814     MsiRecordSetStringA( hrec, 1, "[imaprop]" );
2815     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2816     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2817     ok( !lstrcmpA( buf, "1: ringer " ), "Expected '1: ringer ', got %s\n", buf );
2818 
2819     size = MAX_PATH;
2820     MsiRecordSetStringA( hrec, 0, "1: [1] " );
2821     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2822     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2823     ok( !lstrcmpA( buf, "1: ringer " ), "Expected '1: ringer ', got %s\n", buf );
2824 
2825     /* environment variable doesn't exist */
2826     size = MAX_PATH;
2827     MsiRecordSetStringA( hrec, 1, "[%idontexist]" );
2828     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2829     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2830     ok( !lstrcmpA( buf, "1:  " ), "Expected '1:  ', got %s\n", buf );
2831 
2832     /* environment variable exists */
2833     size = MAX_PATH;
2834     SetEnvironmentVariableA( "crazyvar", "crazyval" );
2835     MsiRecordSetStringA( hrec, 1, "[%crazyvar]" );
2836     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2837     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2838     ok( !lstrcmpA( buf, "1: crazyval " ), "Expected '1: crazyval ', got %s\n", buf );
2839 
2840     /* file key before CostInitialize */
2841     size = MAX_PATH;
2842     MsiRecordSetStringA( hrec, 1, "[#frontal_file]" );
2843     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2844     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2845     ok( !lstrcmpA( buf, "1:  " ), "Expected '1:  ', got %s\n", buf );
2846 
2847     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2848 
2849     r = MsiDoActionA(hpkg, "CostInitialize");
2850     ok( r == ERROR_SUCCESS, "CostInitialize failed: %d\n", r);
2851 
2852     r = MsiDoActionA(hpkg, "FileCost");
2853     ok( r == ERROR_SUCCESS, "FileCost failed: %d\n", r);
2854 
2855     r = MsiDoActionA(hpkg, "CostFinalize");
2856     ok( r == ERROR_SUCCESS, "CostFinalize failed: %d\n", r);
2857 
2858     size = MAX_PATH;
2859     MsiGetPropertyA( hpkg, "ROOTDRIVE", root, &size );
2860 
2861     sprintf( expected, "1: %sfrontal.txt ", root);
2862 
2863     /* frontal full file key */
2864     size = MAX_PATH;
2865     MsiRecordSetStringA( hrec, 1, "[#frontal_file]" );
2866     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2867     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2868     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2869 
2870     /* frontal short file key */
2871     size = MAX_PATH;
2872     MsiRecordSetStringA( hrec, 1, "[!frontal_file]" );
2873     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2874     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2875     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2876 
2877     sprintf( expected, "1: %sI am a really long directory\\temporal.txt ", root);
2878 
2879     /* temporal full file key */
2880     size = MAX_PATH;
2881     MsiRecordSetStringA( hrec, 1, "[#temporal_file]" );
2882     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2883     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2884     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2885 
2886     /* temporal short file key */
2887     size = MAX_PATH;
2888     MsiRecordSetStringA( hrec, 1, "[!temporal_file]" );
2889     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2890     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2891     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2892 
2893     /* custom action 51, files don't exist */
2894     r = MsiDoActionA( hpkg, "MyCustom" );
2895     ok( r == ERROR_SUCCESS, "MyCustom failed: %d\n", r);
2896 
2897     sprintf( expected, "%sI am a really long directory\\temporal.txt", root);
2898 
2899     size = MAX_PATH;
2900     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2901     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2902     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2903 
2904     sprintf( buf, "%sI am a really long directory", root );
2905     CreateDirectoryA( buf, NULL );
2906 
2907     lstrcatA( buf, "\\temporal.txt" );
2908     create_test_file( buf );
2909 
2910     /* custom action 51, files exist */
2911     r = MsiDoActionA( hpkg, "MyCustom" );
2912     ok( r == ERROR_SUCCESS, "MyCustom failed: %d\n", r);
2913 
2914     size = MAX_PATH;
2915     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2916     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2917     todo_wine
2918     {
2919         ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2920     }
2921 
2922     /* custom action 51, escaped text 1 */
2923     r = MsiDoActionA( hpkg, "EscapeIt1" );
2924     ok( r == ERROR_SUCCESS, "EscapeIt1 failed: %d\n", r);
2925 
2926     size = MAX_PATH;
2927     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2928     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2929     ok( !lstrcmpA( buf, "[Bracket Text]" ), "Expected '[Bracket Text]', got %s\n", buf);
2930 
2931     /* custom action 51, escaped text 2 */
2932     r = MsiDoActionA( hpkg, "EscapeIt2" );
2933     ok( r == ERROR_SUCCESS, "EscapeIt2 failed: %d\n", r);
2934 
2935     size = MAX_PATH;
2936     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2937     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2938     ok( !lstrcmpA( buf, "x" ), "Expected 'x', got %s\n", buf);
2939 
2940     /* custom action 51, escaped text 3 */
2941     r = MsiDoActionA( hpkg, "EscapeIt3" );
2942     ok( r == ERROR_SUCCESS, "EscapeIt3 failed: %d\n", r);
2943 
2944     size = MAX_PATH;
2945     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2946     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2947     ok( !lstrcmpA( buf, "" ), "Expected '', got %s\n", buf);
2948 
2949     /* custom action 51, embedded null */
2950     r = MsiDoActionA( hpkg, "EmbedNull" );
2951     ok( r == ERROR_SUCCESS, "EmbedNull failed: %d\n", r);
2952 
2953     size = MAX_PATH;
2954     memset( buf, 'a', sizeof(buf) );
2955     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2956     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2957     ok( !memcmp( buf, "\0np", sizeof("\0np") ), "wrong value\n");
2958     ok( size == sizeof("\0np") - 1, "got %u\n", size );
2959 
2960     r = MsiSetPropertyA( hpkg, "prop", "[~]np" );
2961     ok( r == ERROR_SUCCESS, "cannot set property: %d\n", r);
2962 
2963     size = MAX_PATH;
2964     memset( buf, 'a', sizeof(buf) );
2965     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2966     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2967     ok( !lstrcmpA( buf, "[~]np" ), "Expected '[~]np', got %s\n", buf);
2968 
2969     sprintf( expected, "1: %sI am a really long directory\\ ", root);
2970 
2971     /* component with INSTALLSTATE_LOCAL */
2972     size = MAX_PATH;
2973     MsiRecordSetStringA( hrec, 1, "[$temporal]" );
2974     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2975     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2976     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2977 
2978     r = MsiSetComponentStateA( hpkg, "temporal", INSTALLSTATE_SOURCE );
2979     ok( r == ERROR_SUCCESS, "failed to set install state: %d\n", r);
2980 
2981     /* component with INSTALLSTATE_SOURCE */
2982     lstrcpyA( expected, "1: " );
2983     lstrcatA( expected, curr_dir );
2984     if (strlen(curr_dir) > 3) lstrcatA( expected, "\\" );
2985     lstrcatA( expected, " " );
2986     size = MAX_PATH;
2987     MsiRecordSetStringA( hrec, 1, "[$parietal]" );
2988     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2989     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2990     ok( !lstrcmpA( buf, expected ), "Expected '%s', got '%s'\n", expected, buf);
2991 
2992     sprintf( buf, "%sI am a really long directory\\temporal.txt", root );
2993     DeleteFileA( buf );
2994 
2995     sprintf( buf, "%sI am a really long directory", root );
2996     RemoveDirectoryA( buf );
2997 
2998     MsiCloseHandle( hrec );
2999     MsiCloseHandle( hpkg );
3000     DeleteFileA( msifile );
3001 }
3002 
3003 static void test_feature_states( UINT line, MSIHANDLE package, const char *feature, UINT error,
3004                                  INSTALLSTATE expected_state, INSTALLSTATE expected_action, BOOL todo )
3005 {
3006     UINT r;
3007     INSTALLSTATE state = 0xdeadbee;
3008     INSTALLSTATE action = 0xdeadbee;
3009 
3010     r = MsiGetFeatureStateA( package, feature, &state, &action );
3011     ok( r == error, "%u: expected %d got %d\n", line, error, r );
3012     if (r == ERROR_SUCCESS)
3013     {
3014         ok( state == expected_state, "%u: expected state %d got %d\n",
3015             line, expected_state, state );
3016         todo_wine_if (todo)
3017             ok( action == expected_action, "%u: expected action %d got %d\n",
3018                 line, expected_action, action );
3019     }
3020     else
3021     {
3022         ok( state == 0xdeadbee, "%u: expected state 0xdeadbee got %d\n", line, state );
3023         todo_wine_if (todo)
3024             ok( action == 0xdeadbee, "%u: expected action 0xdeadbee got %d\n", line, action );
3025 
3026     }
3027 }
3028 
3029 static void test_component_states( UINT line, MSIHANDLE package, const char *component, UINT error,
3030                                    INSTALLSTATE expected_state, INSTALLSTATE expected_action, BOOL todo )
3031 {
3032     UINT r;
3033     INSTALLSTATE state = 0xdeadbee;
3034     INSTALLSTATE action = 0xdeadbee;
3035 
3036     r = MsiGetComponentStateA( package, component, &state, &action );
3037     ok( r == error, "%u: expected %d got %d\n", line, error, r );
3038     if (r == ERROR_SUCCESS)
3039     {
3040         ok( state == expected_state, "%u: expected state %d got %d\n",
3041             line, expected_state, state );
3042         todo_wine_if (todo)
3043             ok( action == expected_action, "%u: expected action %d got %d\n",
3044                 line, expected_action, action );
3045     }
3046     else
3047     {
3048         ok( state == 0xdeadbee, "%u: expected state 0xdeadbee got %d\n",
3049             line, state );
3050         todo_wine_if (todo)
3051             ok( action == 0xdeadbee, "%u: expected action 0xdeadbee got %d\n",
3052                 line, action );
3053     }
3054 }
3055 
3056 static void test_states(void)
3057 {
3058     static const char msifile2[] = "winetest2-package.msi";
3059     static const char msifile3[] = "winetest3-package.msi";
3060     static const char msifile4[] = "winetest4-package.msi";
3061     static const WCHAR msifile2W[] =
3062         {'w','i','n','e','t','e','s','t','2','-','p','a','c','k','a','g','e','.','m','s','i',0};
3063     static const WCHAR msifile3W[] =
3064         {'w','i','n','e','t','e','s','t','3','-','p','a','c','k','a','g','e','.','m','s','i',0};
3065     static const WCHAR msifile4W[] =
3066         {'w','i','n','e','t','e','s','t','4','-','p','a','c','k','a','g','e','.','m','s','i',0};
3067     char msi_cache_file[MAX_PATH];
3068     DWORD cache_file_name_len;
3069     INSTALLSTATE state;
3070     MSIHANDLE hpkg;
3071     UINT r;
3072     MSIHANDLE hdb;
3073     BOOL is_broken;
3074 
3075     if (is_process_limited())
3076     {
3077         skip("process is limited\n");
3078         return;
3079     }
3080 
3081     hdb = create_package_db();
3082     ok ( hdb, "failed to create package database\n" );
3083 
3084     add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'");
3085 
3086     create_property_table( hdb );
3087     add_property_entry( hdb, "'ProductCode', '{7262AC98-EEBD-4364-8CE3-D654F6A425B9}'" );
3088     add_property_entry( hdb, "'ProductLanguage', '1033'" );
3089     add_property_entry( hdb, "'ProductName', 'MSITEST'" );
3090     add_property_entry( hdb, "'ProductVersion', '1.1.1'" );
3091     add_property_entry( hdb, "'MSIFASTINSTALL', '1'" );
3092 
3093     create_install_execute_sequence_table( hdb );
3094     add_install_execute_sequence_entry( hdb, "'CostInitialize', '', '800'" );
3095     add_install_execute_sequence_entry( hdb, "'FileCost', '', '900'" );
3096     add_install_execute_sequence_entry( hdb, "'CostFinalize', '', '1000'" );
3097     add_install_execute_sequence_entry( hdb, "'InstallValidate', '', '1400'" );
3098     add_install_execute_sequence_entry( hdb, "'InstallInitialize', '', '1500'" );
3099     add_install_execute_sequence_entry( hdb, "'ProcessComponents', '', '1600'" );
3100     add_install_execute_sequence_entry( hdb, "'UnpublishFeatures', '', '1800'" );
3101     add_install_execute_sequence_entry( hdb, "'RegisterProduct', '', '6100'" );
3102     add_install_execute_sequence_entry( hdb, "'PublishFeatures', '', '6300'" );
3103     add_install_execute_sequence_entry( hdb, "'PublishProduct', '', '6400'" );
3104     add_install_execute_sequence_entry( hdb, "'InstallFinalize', '', '6600'" );
3105 
3106     create_media_table( hdb );
3107     add_media_entry( hdb, "'1', '3', '', '', 'DISK1', ''");
3108 
3109     create_feature_table( hdb );
3110 
3111     create_component_table( hdb );
3112 
3113     /* msidbFeatureAttributesFavorLocal */
3114     add_feature_entry( hdb, "'one', '', '', '', 2, 1, '', 0" );
3115 
3116     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesLocalOnly */
3117     add_component_entry( hdb, "'alpha', '{467EC132-739D-4784-A37B-677AA43DBC94}', 'TARGETDIR', 0, '', 'alpha_file'" );
3118 
3119     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSourceOnly */
3120     add_component_entry( hdb, "'beta', '{2C1F189C-24A6-4C34-B26B-994A6C026506}', 'TARGETDIR', 1, '', 'beta_file'" );
3121 
3122     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesOptional */
3123     add_component_entry( hdb, "'gamma', '{C271E2A4-DE2E-4F70-86D1-6984AF7DE2CA}', 'TARGETDIR', 2, '', 'gamma_file'" );
3124 
3125     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSharedDllRefCount */
3126     add_component_entry( hdb, "'theta', '{4EB3129D-81A8-48D5-9801-75600FED3DD9}', 'TARGETDIR', 8, '', 'theta_file'" );
3127 
3128     /* msidbFeatureAttributesFavorSource */
3129     add_feature_entry( hdb, "'two', '', '', '', 2, 1, '', 1" );
3130 
3131     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesLocalOnly */
3132     add_component_entry( hdb, "'delta', '{938FD4F2-C648-4259-A03C-7AA3B45643F3}', 'TARGETDIR', 0, '', 'delta_file'" );
3133 
3134     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSourceOnly */
3135     add_component_entry( hdb, "'epsilon', '{D59713B6-C11D-47F2-A395-1E5321781190}', 'TARGETDIR', 1, '', 'epsilon_file'" );
3136 
3137     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesOptional */
3138     add_component_entry( hdb, "'zeta', '{377D33AB-2FAA-42B9-A629-0C0DAE9B9C7A}', 'TARGETDIR', 2, '', 'zeta_file'" );
3139 
3140     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSharedDllRefCount */
3141     add_component_entry( hdb, "'iota', '{5D36F871-B5ED-4801-9E0F-C46B9E5C9669}', 'TARGETDIR', 8, '', 'iota_file'" );
3142 
3143     /* msidbFeatureAttributesFavorSource */
3144     add_feature_entry( hdb, "'three', '', '', '', 2, 1, '', 1" );
3145 
3146     /* msidbFeatureAttributesFavorLocal */
3147     add_feature_entry( hdb, "'four', '', '', '', 2, 1, '', 0" );
3148 
3149     /* disabled */
3150     add_feature_entry( hdb, "'five', '', '', '', 2, 0, '', 1" );
3151 
3152     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSourceOnly */
3153     add_component_entry( hdb, "'eta', '{DD89003F-0DD4-41B8-81C0-3411A7DA2695}', 'TARGETDIR', 1, '', 'eta_file'" );
3154 
3155     /* no feature parent:msidbComponentAttributesLocalOnly */
3156     add_component_entry( hdb, "'kappa', '{D6B93DC3-8DA5-4769-9888-42BFE156BB8B}', 'TARGETDIR', 1, '', 'kappa_file'" );
3157 
3158     /* msidbFeatureAttributesFavorLocal:removed */
3159     add_feature_entry( hdb, "'six', '', '', '', 2, 1, '', 0" );
3160 
3161     /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesLocalOnly */
3162     add_component_entry( hdb, "'lambda', '{6528C5E4-02A4-4636-A214-7A66A6C35B64}', 'TARGETDIR', 0, '', 'lambda_file'" );
3163 
3164     /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesSourceOnly */
3165     add_component_entry( hdb, "'mu', '{97014BAB-6C56-4013-9A63-2BF913B42519}', 'TARGETDIR', 1, '', 'mu_file'" );
3166 
3167     /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesOptional */
3168     add_component_entry( hdb, "'nu', '{943DD0D8-5808-4954-8526-3B8493FEDDCD}', 'TARGETDIR', 2, '', 'nu_file'" );
3169 
3170     /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesSharedDllRefCount */
3171     add_component_entry( hdb, "'xi', '{D6CF9EF7-6FCF-4930-B34B-F938AEFF9BDB}', 'TARGETDIR', 8, '', 'xi_file'" );
3172 
3173     /* msidbFeatureAttributesFavorSource:removed */
3174     add_feature_entry( hdb, "'seven', '', '', '', 2, 1, '', 1" );
3175 
3176     /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesLocalOnly */
3177     add_component_entry( hdb, "'omicron', '{7B57521D-15DB-4141-9AA6-01D934A4433F}', 'TARGETDIR', 0, '', 'omicron_file'" );
3178 
3179     /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesSourceOnly */
3180     add_component_entry( hdb, "'pi', '{FB85346B-378E-4492-8769-792305471C81}', 'TARGETDIR', 1, '', 'pi_file'" );
3181 
3182     /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesOptional */
3183     add_component_entry( hdb, "'rho', '{798F2047-7B0C-4783-8BB0-D703E554114B}', 'TARGETDIR', 2, '', 'rho_file'" );
3184 
3185     /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesSharedDllRefCount */
3186     add_component_entry( hdb, "'sigma', '{5CE9DDA8-B67B-4736-9D93-99D61C5B93E7}', 'TARGETDIR', 8, '', 'sigma_file'" );
3187 
3188     /* msidbFeatureAttributesFavorLocal */
3189     add_feature_entry( hdb, "'eight', '', '', '', 2, 1, '', 0" );
3190 
3191     add_component_entry( hdb, "'tau', '{07DEB510-677C-4A6F-A0A6-7CD8EFEA77ED}', 'TARGETDIR', 1, '', 'tau_file'" );
3192 
3193     /* msidbFeatureAttributesFavorSource */
3194     add_feature_entry( hdb, "'nine', '', '', '', 2, 1, '', 1" );
3195 
3196     add_component_entry( hdb, "'phi', '{9F0594C5-35AD-43EA-94DD-8DF73FAA664D}', 'TARGETDIR', 1, '', 'phi_file'" );
3197 
3198     /* msidbFeatureAttributesFavorAdvertise */
3199     add_feature_entry( hdb, "'ten', '', '', '', 2, 1, '', 4" );
3200 
3201     add_component_entry( hdb, "'chi', '{E6B539AB-5DA9-4236-A2D2-E341A50B4C38}', 'TARGETDIR', 1, '', 'chi_file'" );
3202 
3203     /* msidbFeatureAttributesUIDisallowAbsent */
3204     add_feature_entry( hdb, "'eleven', '', '', '', 2, 1, '', 16" );
3205 
3206     add_component_entry( hdb, "'psi', '{A06B23B5-746B-427A-8A6E-FD6AC8F46A95}', 'TARGETDIR', 1, '', 'psi_file'" );
3207 
3208     /* high install level */
3209     add_feature_entry( hdb, "'twelve', '', '', '', 2, 2, '', 0" );
3210 
3211     add_component_entry( hdb, "'upsilon', '{557e0c04-ceba-4c58-86a9-4a73352e8cf6}', 'TARGETDIR', 1, '', 'upsilon_file'" );
3212 
3213     /* msidbFeatureAttributesFollowParent */
3214     add_feature_entry( hdb, "'thirteen', '', '', '', 2, 2, '', 2" );
3215 
3216     create_feature_components_table( hdb );
3217     add_feature_components_entry( hdb, "'one', 'alpha'" );
3218     add_feature_components_entry( hdb, "'one', 'beta'" );
3219     add_feature_components_entry( hdb, "'one', 'gamma'" );
3220     add_feature_components_entry( hdb, "'one', 'theta'" );
3221     add_feature_components_entry( hdb, "'two', 'delta'" );
3222     add_feature_components_entry( hdb, "'two', 'epsilon'" );
3223     add_feature_components_entry( hdb, "'two', 'zeta'" );
3224     add_feature_components_entry( hdb, "'two', 'iota'" );
3225     add_feature_components_entry( hdb, "'three', 'eta'" );
3226     add_feature_components_entry( hdb, "'four', 'eta'" );
3227     add_feature_components_entry( hdb, "'five', 'eta'" );
3228     add_feature_components_entry( hdb, "'six', 'lambda'" );
3229     add_feature_components_entry( hdb, "'six', 'mu'" );
3230     add_feature_components_entry( hdb, "'six', 'nu'" );
3231     add_feature_components_entry( hdb, "'six', 'xi'" );
3232     add_feature_components_entry( hdb, "'seven', 'omicron'" );
3233     add_feature_components_entry( hdb, "'seven', 'pi'" );
3234     add_feature_components_entry( hdb, "'seven', 'rho'" );
3235     add_feature_components_entry( hdb, "'seven', 'sigma'" );
3236     add_feature_components_entry( hdb, "'eight', 'tau'" );
3237     add_feature_components_entry( hdb, "'nine', 'phi'" );
3238     add_feature_components_entry( hdb, "'ten', 'chi'" );
3239     add_feature_components_entry( hdb, "'eleven', 'psi'" );
3240     add_feature_components_entry( hdb, "'twelve', 'upsilon'" );
3241     add_feature_components_entry( hdb, "'thirteen', 'upsilon'" );
3242 
3243     create_file_table( hdb );
3244     add_file_entry( hdb, "'alpha_file', 'alpha', 'alpha.txt', 100, '', '1033', 8192, 1" );
3245     add_file_entry( hdb, "'beta_file', 'beta', 'beta.txt', 0, '', '1033', 8192, 1" );
3246     add_file_entry( hdb, "'gamma_file', 'gamma', 'gamma.txt', 0, '', '1033', 8192, 1" );
3247     add_file_entry( hdb, "'theta_file', 'theta', 'theta.txt', 0, '', '1033', 8192, 1" );
3248     add_file_entry( hdb, "'delta_file', 'delta', 'delta.txt', 0, '', '1033', 8192, 1" );
3249     add_file_entry( hdb, "'epsilon_file', 'epsilon', 'epsilon.txt', 0, '', '1033', 8192, 1" );
3250     add_file_entry( hdb, "'zeta_file', 'zeta', 'zeta.txt', 0, '', '1033', 8192, 1" );
3251     add_file_entry( hdb, "'iota_file', 'iota', 'iota.txt', 0, '', '1033', 8192, 1" );
3252 
3253     /* compressed file */
3254     add_file_entry( hdb, "'eta_file', 'eta', 'eta.txt', 0, '', '1033', 16384, 1" );
3255 
3256     add_file_entry( hdb, "'kappa_file', 'kappa', 'kappa.txt', 0, '', '1033', 8192, 1" );
3257     add_file_entry( hdb, "'lambda_file', 'lambda', 'lambda.txt', 100, '', '1033', 8192, 1" );
3258     add_file_entry( hdb, "'mu_file', 'mu', 'mu.txt', 100, '', '1033', 8192, 1" );
3259     add_file_entry( hdb, "'nu_file', 'nu', 'nu.txt', 100, '', '1033', 8192, 1" );
3260     add_file_entry( hdb, "'xi_file', 'xi', 'xi.txt', 100, '', '1033', 8192, 1" );
3261     add_file_entry( hdb, "'omicron_file', 'omicron', 'omicron.txt', 100, '', '1033', 8192, 1" );
3262     add_file_entry( hdb, "'pi_file', 'pi', 'pi.txt', 100, '', '1033', 8192, 1" );
3263     add_file_entry( hdb, "'rho_file', 'rho', 'rho.txt', 100, '', '1033', 8192, 1" );
3264     add_file_entry( hdb, "'sigma_file', 'sigma', 'sigma.txt', 100, '', '1033', 8192, 1" );
3265     add_file_entry( hdb, "'tau_file', 'tau', 'tau.txt', 100, '', '1033', 8192, 1" );
3266     add_file_entry( hdb, "'phi_file', 'phi', 'phi.txt', 100, '', '1033', 8192, 1" );
3267     add_file_entry( hdb, "'chi_file', 'chi', 'chi.txt', 100, '', '1033', 8192, 1" );
3268     add_file_entry( hdb, "'psi_file', 'psi', 'psi.txt', 100, '', '1033', 8192, 1" );
3269     add_file_entry( hdb, "'upsilon_file', 'upsilon', 'upsilon.txt', 0, '', '1033', 16384, 1" );
3270 
3271     r = MsiDatabaseCommit(hdb);
3272     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
3273 
3274     /* these properties must not be in the saved msi file */
3275     add_property_entry( hdb, "'ADDLOCAL', 'one,four'");
3276     add_property_entry( hdb, "'ADDSOURCE', 'two,three'");
3277     add_property_entry( hdb, "'REMOVE', 'six,seven'");
3278     add_property_entry( hdb, "'REINSTALL', 'eight,nine,ten'");
3279     add_property_entry( hdb, "'REINSTALLMODE', 'omus'");
3280 
3281     r = package_from_db( hdb, &hpkg );
3282     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
3283     {
3284         skip("Not enough rights to perform tests\n");
3285         DeleteFileA(msifile);
3286         return;
3287     }
3288     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3289 
3290     MsiCloseHandle(hdb);
3291 
3292     CopyFileA(msifile, msifile2, FALSE);
3293     CopyFileA(msifile, msifile3, FALSE);
3294     CopyFileA(msifile, msifile4, FALSE);
3295 
3296     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3297     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3298 
3299     r = MsiDoActionA( hpkg, "CostInitialize");
3300     ok( r == ERROR_SUCCESS, "cost init failed\n");
3301 
3302     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3303     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3304 
3305     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3306 
3307     r = MsiDoActionA( hpkg, "FileCost");
3308     ok( r == ERROR_SUCCESS, "file cost failed\n");
3309 
3310     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3311     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3312 
3313     r = MsiDoActionA( hpkg, "CostFinalize");
3314     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3315 
3316     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3317     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
3318     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3319     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3320     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3321     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3322     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3323     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3324     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3325     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3326     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3327     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3328     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3329 
3330     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3331     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
3332     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3333     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3334     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3335     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
3336     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
3337     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3338     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3339     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3340     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3341     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3342     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3343     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3344     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3345     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3346     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3347     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3348     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3349     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3350     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3351     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3352     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3353 
3354     MsiCloseHandle( hpkg );
3355 
3356     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3357 
3358     /* publish the features and components */
3359     r = MsiInstallProductA(msifile, "ADDLOCAL=one,four ADDSOURCE=two,three REMOVE=six,seven REINSTALL=eight,nine,ten");
3360     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3361 
3362     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb);
3363     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3364 
3365     /* these properties must not be in the saved msi file */
3366     add_property_entry( hdb, "'ADDLOCAL', 'one,four'");
3367     add_property_entry( hdb, "'ADDSOURCE', 'two,three'");
3368     add_property_entry( hdb, "'REMOVE', 'six,seven'");
3369     add_property_entry( hdb, "'REINSTALL', 'eight,nine,ten'");
3370 
3371     r = package_from_db( hdb, &hpkg );
3372     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3373 
3374     MsiCloseHandle(hdb);
3375 
3376     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3377     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3378 
3379     r = MsiDoActionA( hpkg, "CostInitialize");
3380     ok( r == ERROR_SUCCESS, "cost init failed\n");
3381 
3382     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3383     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3384 
3385     r = MsiDoActionA( hpkg, "FileCost");
3386     ok( r == ERROR_SUCCESS, "file cost failed\n");
3387 
3388     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3389     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3390 
3391     r = MsiDoActionA( hpkg, "CostFinalize");
3392     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3393 
3394     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3395     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3396     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3397     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3398     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3399     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3400     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3401     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3402     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3403     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3404     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3405     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3406     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3407 
3408     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3409     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3410     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3411     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3412     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3413     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3414     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3415     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3416     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3417     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3418     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3419     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3420     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3421     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3422     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3423     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3424     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3425     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3426     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3427     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3428     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3429     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3430     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3431 
3432     MsiCloseHandle(hpkg);
3433 
3434     /* uninstall the product */
3435     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3436     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3437 
3438     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3439     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3440     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3441     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3442 
3443     /* all features installed locally */
3444     r = MsiInstallProductA(msifile2, "ADDLOCAL=ALL");
3445     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3446 
3447     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3448     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3449     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3450     ok(state == INSTALLSTATE_LOCAL, "state = %d\n", state);
3451 
3452     r = MsiOpenDatabaseW(msifile2W, MSIDBOPEN_DIRECT, &hdb);
3453     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3454 
3455     /* these properties must not be in the saved msi file */
3456     add_property_entry( hdb, "'ADDLOCAL', 'one,two,three,four,five,six,seven,eight,nine,ten,twelve'");
3457 
3458     r = package_from_db( hdb, &hpkg );
3459     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3460 
3461     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3462     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3463 
3464     r = MsiDoActionA( hpkg, "CostInitialize");
3465     ok( r == ERROR_SUCCESS, "cost init failed\n");
3466 
3467     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3468     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3469 
3470     r = MsiDoActionA( hpkg, "CostFinalize");
3471     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3472 
3473     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3474     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3475     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3476     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3477     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3478     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3479     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3480     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, TRUE );
3481     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, TRUE );
3482     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, TRUE );
3483     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3484     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3485     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3486 
3487     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3488     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3489     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3490     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3491     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3492     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3493     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3494     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3495     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3496     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3497     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3498     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3499     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3500     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3501     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3502     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3503     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3504     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3505     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3506     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3507     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3508     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3509     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3510 
3511     MsiCloseHandle(hpkg);
3512 
3513     /* uninstall the product */
3514     r = MsiInstallProductA(msifile2, "REMOVE=ALL");
3515     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3516 
3517     /* all features installed from source */
3518     r = MsiInstallProductA(msifile3, "ADDSOURCE=ALL");
3519     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3520 
3521     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3522     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3523     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3524     ok(state == INSTALLSTATE_LOCAL, "state = %d\n", state);
3525 
3526     r = MsiOpenDatabaseW(msifile3W, MSIDBOPEN_DIRECT, &hdb);
3527     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3528 
3529     /* this property must not be in the saved msi file */
3530     add_property_entry( hdb, "'ADDSOURCE', 'one,two,three,four,five,six,seven,eight,nine,ten'");
3531 
3532     r = package_from_db( hdb, &hpkg );
3533     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3534 
3535     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3536     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3537 
3538     r = MsiDoActionA( hpkg, "CostInitialize");
3539     ok( r == ERROR_SUCCESS, "cost init failed\n");
3540 
3541     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3542     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3543 
3544     r = MsiDoActionA( hpkg, "FileCost");
3545     ok( r == ERROR_SUCCESS, "file cost failed\n");
3546 
3547     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3548     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3549 
3550     r = MsiDoActionA( hpkg, "CostFinalize");
3551     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3552 
3553     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3554     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3555     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3556     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3557     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3558     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3559     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3560     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3561     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3562     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3563     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3564     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3565     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3566 
3567     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3568     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3569     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3570     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3571     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3572     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3573     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3574     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3575     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3576     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3577     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3578     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3579     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3580     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3581     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3582     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3583     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3584     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3585     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3586     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3587     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3588     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3589     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3590 
3591     MsiCloseHandle(hpkg);
3592 
3593     /* reinstall the product */
3594     r = MsiInstallProductA(msifile3, "REINSTALL=ALL");
3595     is_broken = (r == ERROR_INSTALL_FAILURE);
3596     ok(r == ERROR_SUCCESS || broken(is_broken) /* win2k3 */, "Expected ERROR_SUCCESS, got %d\n", r);
3597 
3598     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3599     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3600     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3601     ok(state == INSTALLSTATE_LOCAL, "state = %d\n", state);
3602 
3603     r = MsiOpenDatabaseW(msifile4W, MSIDBOPEN_DIRECT, &hdb);
3604     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3605 
3606     /* this property must not be in the saved msi file */
3607     add_property_entry( hdb, "'ADDSOURCE', 'one,two,three,four,five,six,seven,eight,nine,ten'");
3608 
3609     r = package_from_db( hdb, &hpkg );
3610     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3611 
3612     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3613     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3614 
3615     r = MsiDoActionA( hpkg, "CostInitialize");
3616     ok( r == ERROR_SUCCESS, "cost init failed\n");
3617 
3618     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3619     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3620 
3621     r = MsiDoActionA( hpkg, "FileCost");
3622     ok( r == ERROR_SUCCESS, "file cost failed\n");
3623 
3624     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3625     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3626 
3627     r = MsiDoActionA( hpkg, "CostFinalize");
3628     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3629 
3630     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3631     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3632     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3633     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3634     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3635     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3636     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3637     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3638     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3639     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3640     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3641     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3642     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3643 
3644     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3645     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3646     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3647     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3648     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3649     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3650     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3651     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3652     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3653     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3654     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3655     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3656     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3657     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3658     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3659     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3660     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3661     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3662     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3663     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3664     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3665     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3666     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3667 
3668     MsiCloseHandle(hpkg);
3669 
3670     /* test source only install */
3671     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3672     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3673     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "one");
3674     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3675     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "two");
3676     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3677 
3678     r = MsiInstallProductA(msifile, "ADDSOURCE=one");
3679     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3680     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "one");
3681     ok(state == INSTALLSTATE_SOURCE, "state = %d\n", state);
3682     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "two");
3683     ok(state == INSTALLSTATE_ABSENT, "state = %d\n", state);
3684 
3685     /* no arguments test */
3686     cache_file_name_len = sizeof(msi_cache_file);
3687     r = MsiGetProductInfoA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}",
3688             INSTALLPROPERTY_LOCALPACKAGEA, msi_cache_file, &cache_file_name_len);
3689     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3690     r = MsiOpenDatabaseA(msi_cache_file, (const char*)MSIDBOPEN_DIRECT, &hdb);
3691     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3692 
3693     create_custom_action_table( hdb );
3694     add_custom_action_entry( hdb, "'ConditionCheck1', 19, '', 'Condition check failed (1)'" );
3695     add_custom_action_entry( hdb, "'ConditionCheck2', 19, '', 'Condition check failed (2)'" );
3696     add_custom_action_entry( hdb, "'ConditionCheck3', 19, '', 'Condition check failed (3)'" );
3697     add_custom_action_entry( hdb, "'ConditionCheck4', 19, '', 'Condition check failed (4)'" );
3698     add_custom_action_entry( hdb, "'ConditionCheck5', 19, '', 'Condition check failed (5)'" );
3699     add_custom_action_entry( hdb, "'ConditionCheck6', 19, '', 'Condition check failed (6)'" );
3700     add_custom_action_entry( hdb, "'ConditionCheck7', 19, '', 'Condition check failed (7)'" );
3701     add_custom_action_entry( hdb, "'ConditionCheck8', 19, '', 'Condition check failed (8)'" );
3702 
3703     add_install_execute_sequence_entry( hdb, "'ConditionCheck1', 'REINSTALL', '798'" );
3704     add_install_execute_sequence_entry( hdb, "'ConditionCheck2', 'NOT REMOVE AND Preselected', '799'" );
3705     add_install_execute_sequence_entry( hdb, "'ConditionCheck3', 'REINSTALL', '6598'" );
3706     add_install_execute_sequence_entry( hdb, "'ConditionCheck4', 'NOT REMOVE AND Preselected', '6599'" );
3707     add_install_execute_sequence_entry( hdb, "'ConditionCheck5', 'REINSTALL', '6601'" );
3708     add_install_execute_sequence_entry( hdb, "'ConditionCheck6', 'NOT REMOVE AND Preselected', '6601'" );
3709     /* Add "one" feature action tests */
3710     add_install_execute_sequence_entry( hdb, "'ConditionCheck7', 'NOT REMOVE AND NOT(&one=-1)', '1501'" );
3711     add_install_execute_sequence_entry( hdb, "'ConditionCheck8', 'NOT REMOVE AND NOT(&one=-1)', '6602'" );
3712     r = MsiDatabaseCommit(hdb);
3713     ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed: %d\n", r);
3714     r = package_from_db( hdb, &hpkg );
3715     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3716     MsiCloseHandle(hdb);
3717 
3718     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3719     test_feature_states( __LINE__, hpkg, "two", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3720     r = MsiDoActionA( hpkg, "CostInitialize");
3721     ok( r == ERROR_SUCCESS, "CostInitialize failed\n");
3722     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3723     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3724 
3725     r = MsiDoActionA( hpkg, "FileCost");
3726     ok( r == ERROR_SUCCESS, "FileCost failed\n");
3727     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3728     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3729 
3730     r = MsiDoActionA( hpkg, "CostFinalize");
3731     ok( r == ERROR_SUCCESS, "CostFinalize failed\n");
3732     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3733     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3734     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3735     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3736     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3737     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3738     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3739     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3740     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3741     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3742     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3743     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3744     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3745     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3746     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3747     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3748     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3749     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3750     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3751     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3752     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3753     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3754     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3755     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3756     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3757 
3758     r = MsiDoActionA( hpkg, "InstallValidate");
3759     ok( r == ERROR_SUCCESS, "InstallValidate failed %d\n", r);
3760     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3761     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3762     MsiCloseHandle( hpkg );
3763 
3764     r = MsiInstallProductA(msifile, "");
3765     ok(r == ERROR_SUCCESS || (is_broken && r == ERROR_INSTALL_FAILURE) /* win2k3 */,
3766             "Expected ERROR_SUCCESS, got %d\n", r);
3767     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "one");
3768     ok(state == INSTALLSTATE_SOURCE, "state = %d\n", state);
3769     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "two");
3770     ok(state == INSTALLSTATE_ABSENT, "state = %d\n", state);
3771 
3772     /* uninstall the product */
3773     r = MsiInstallProductA(msifile4, "REMOVE=ALL");
3774     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3775 
3776     DeleteFileA(msifile);
3777     DeleteFileA(msifile2);
3778     DeleteFileA(msifile3);
3779     DeleteFileA(msifile4);
3780 }
3781 
3782 static void test_getproperty(void)
3783 {
3784     MSIHANDLE hPackage = 0;
3785     char prop[100];
3786     static CHAR empty[] = "";
3787     DWORD size;
3788     UINT r;
3789 
3790     r = package_from_db(create_package_db(), &hPackage);
3791     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
3792     {
3793         skip("Not enough rights to perform tests\n");
3794         DeleteFileA(msifile);
3795         return;
3796     }
3797     ok( r == ERROR_SUCCESS, "Failed to create package %u\n", r );
3798 
3799     /* set the property */
3800     r = MsiSetPropertyA(hPackage, "Name", "Value");
3801     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3802 
3803     /* retrieve the size, NULL pointer */
3804     size = 0;
3805     r = MsiGetPropertyA(hPackage, "Name", NULL, &size);
3806     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3807     ok( size == 5, "Expected 5, got %d\n", size);
3808 
3809     /* retrieve the size, empty string */
3810     size = 0;
3811     r = MsiGetPropertyA(hPackage, "Name", empty, &size);
3812     ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
3813     ok( size == 5, "Expected 5, got %d\n", size);
3814 
3815     /* don't change size */
3816     r = MsiGetPropertyA(hPackage, "Name", prop, &size);
3817     ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
3818     ok( size == 5, "Expected 5, got %d\n", size);
3819     ok( !lstrcmpA(prop, "Valu"), "Expected Valu, got %s\n", prop);
3820 
3821     /* increase the size by 1 */
3822     size++;
3823     r = MsiGetPropertyA(hPackage, "Name", prop, &size);
3824     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3825     ok( size == 5, "Expected 5, got %d\n", size);
3826     ok( !lstrcmpA(prop, "Value"), "Expected Value, got %s\n", prop);
3827 
3828     r = MsiCloseHandle( hPackage);
3829     ok( r == ERROR_SUCCESS , "Failed to close package\n" );
3830     DeleteFileA(msifile);
3831 }
3832 
3833 static void test_removefiles(void)
3834 {
3835     MSIHANDLE hpkg;
3836     UINT r;
3837     MSIHANDLE hdb;
3838     INSTALLSTATE installed, action;
3839 
3840     hdb = create_package_db();
3841     ok ( hdb, "failed to create package database\n" );
3842 
3843     add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'");
3844 
3845     create_feature_table( hdb );
3846     add_feature_entry( hdb, "'one', '', '', '', 2, 1, '', 0" );
3847 
3848     create_component_table( hdb );
3849     add_component_entry( hdb, "'hydrogen', '', 'TARGETDIR', 0, '', 'hydrogen_file'" );
3850     add_component_entry( hdb, "'helium', '', 'TARGETDIR', 0, '', 'helium_file'" );
3851     add_component_entry( hdb, "'lithium', '', 'TARGETDIR', 0, '', 'lithium_file'" );
3852     add_component_entry( hdb, "'beryllium', '', 'TARGETDIR', 0, '', 'beryllium_file'" );
3853     add_component_entry( hdb, "'boron', '', 'TARGETDIR', 0, '', 'boron_file'" );
3854     add_component_entry( hdb, "'carbon', '', 'TARGETDIR', 0, '', 'carbon_file'" );
3855     add_component_entry( hdb, "'oxygen', '', 'TARGETDIR', 0, '0', 'oxygen_file'" );
3856 
3857     create_feature_components_table( hdb );
3858     add_feature_components_entry( hdb, "'one', 'hydrogen'" );
3859     add_feature_components_entry( hdb, "'one', 'helium'" );
3860     add_feature_components_entry( hdb, "'one', 'lithium'" );
3861     add_feature_components_entry( hdb, "'one', 'beryllium'" );
3862     add_feature_components_entry( hdb, "'one', 'boron'" );
3863     add_feature_components_entry( hdb, "'one', 'carbon'" );
3864     add_feature_components_entry( hdb, "'one', 'oxygen'" );
3865 
3866     create_file_table( hdb );
3867     add_file_entry( hdb, "'hydrogen_file', 'hydrogen', 'hydrogen.txt', 0, '', '1033', 8192, 1" );
3868     add_file_entry( hdb, "'helium_file', 'helium', 'helium.txt', 0, '', '1033', 8192, 1" );
3869     add_file_entry( hdb, "'lithium_file', 'lithium', 'lithium.txt', 0, '', '1033', 8192, 1" );
3870     add_file_entry( hdb, "'beryllium_file', 'beryllium', 'beryllium.txt', 0, '', '1033', 16384, 1" );
3871     add_file_entry( hdb, "'boron_file', 'boron', 'boron.txt', 0, '', '1033', 16384, 1" );
3872     add_file_entry( hdb, "'carbon_file', 'carbon', 'carbon.txt', 0, '', '1033', 16384, 1" );
3873     add_file_entry( hdb, "'oxygen_file', 'oxygen', 'oxygen.txt', 0, '', '1033', 16384, 1" );
3874 
3875     create_remove_file_table( hdb );
3876 
3877     r = package_from_db( hdb, &hpkg );
3878     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
3879     {
3880         skip("Not enough rights to perform tests\n");
3881         DeleteFileA(msifile);
3882         return;
3883     }
3884     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3885 
3886     MsiCloseHandle( hdb );
3887 
3888     create_test_file( "hydrogen.txt" );
3889     create_test_file( "helium.txt" );
3890     create_test_file( "lithium.txt" );
3891     create_test_file( "beryllium.txt" );
3892     create_test_file( "boron.txt" );
3893     create_test_file( "carbon.txt" );
3894     create_test_file( "oxygen.txt" );
3895 
3896     r = MsiSetPropertyA( hpkg, "TARGETDIR", CURR_DIR );
3897     ok( r == ERROR_SUCCESS, "set property failed\n");
3898 
3899     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3900 
3901     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3902     ok( r == ERROR_UNKNOWN_COMPONENT, "expected ERROR_UNKNOWN_COMPONENT, got %u\n", r );
3903 
3904     r = MsiDoActionA( hpkg, "CostInitialize");
3905     ok( r == ERROR_SUCCESS, "cost init failed\n");
3906 
3907     r = MsiDoActionA( hpkg, "FileCost");
3908     ok( r == ERROR_SUCCESS, "file cost failed\n");
3909 
3910     installed = action = 0xdeadbeef;
3911     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3912     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3913     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3914     ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3915 
3916     r = MsiDoActionA( hpkg, "CostFinalize");
3917     ok( r == ERROR_SUCCESS, "cost finalize failed\n");
3918 
3919     r = MsiDoActionA( hpkg, "InstallValidate");
3920     ok( r == ERROR_SUCCESS, "install validate failed\n");
3921 
3922     r = MsiSetComponentStateA( hpkg, "hydrogen", INSTALLSTATE_ABSENT );
3923     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3924 
3925     installed = action = 0xdeadbeef;
3926     r = MsiGetComponentStateA( hpkg, "hydrogen", &installed, &action );
3927     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3928     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3929     todo_wine ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3930 
3931     r = MsiSetComponentStateA( hpkg, "helium", INSTALLSTATE_LOCAL );
3932     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3933 
3934     r = MsiSetComponentStateA( hpkg, "lithium", INSTALLSTATE_SOURCE );
3935     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3936 
3937     r = MsiSetComponentStateA( hpkg, "beryllium", INSTALLSTATE_ABSENT );
3938     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3939 
3940     r = MsiSetComponentStateA( hpkg, "boron", INSTALLSTATE_LOCAL );
3941     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3942 
3943     r = MsiSetComponentStateA( hpkg, "carbon", INSTALLSTATE_SOURCE );
3944     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3945 
3946     installed = action = 0xdeadbeef;
3947     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3948     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3949     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3950     ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3951 
3952     r = MsiSetComponentStateA( hpkg, "oxygen", INSTALLSTATE_ABSENT );
3953     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3954 
3955     installed = action = 0xdeadbeef;
3956     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3957     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3958     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3959     ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3960 
3961     r = MsiDoActionA( hpkg, "RemoveFiles");
3962     ok( r == ERROR_SUCCESS, "remove files failed\n");
3963 
3964     installed = action = 0xdeadbeef;
3965     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3966     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3967     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3968     ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3969 
3970     ok(DeleteFileA("hydrogen.txt"), "Expected hydrogen.txt to exist\n");
3971     ok(DeleteFileA("lithium.txt"), "Expected lithium.txt to exist\n");
3972     ok(DeleteFileA("beryllium.txt"), "Expected beryllium.txt to exist\n");
3973     ok(DeleteFileA("carbon.txt"), "Expected carbon.txt to exist\n");
3974     ok(DeleteFileA("helium.txt"), "Expected helium.txt to exist\n");
3975     ok(DeleteFileA("boron.txt"), "Expected boron.txt to exist\n");
3976     ok(DeleteFileA("oxygen.txt"), "Expected oxygen.txt to exist\n");
3977 
3978     MsiCloseHandle( hpkg );
3979     DeleteFileA(msifile);
3980 }
3981 
3982 static void test_appsearch(void)
3983 {
3984     MSIHANDLE hpkg;
3985     UINT r;
3986     MSIHANDLE hdb;
3987     CHAR prop[MAX_PATH];
3988     DWORD size;
3989     HKEY hkey;
3990     const char reg_expand_value[] = "%systemroot%\\system32\\notepad.exe";
3991 
3992     hdb = create_package_db();
3993     ok ( hdb, "failed to create package database\n" );
3994 
3995     create_appsearch_table( hdb );
3996     add_appsearch_entry( hdb, "'WEBBROWSERPROG', 'NewSignature1'" );
3997     add_appsearch_entry( hdb, "'NOTEPAD', 'NewSignature2'" );
3998     add_appsearch_entry( hdb, "'REGEXPANDVAL', 'NewSignature3'" );
3999 
4000     create_reglocator_table( hdb );
4001     add_reglocator_entry( hdb, "NewSignature1", 0, "htmlfile\\shell\\open\\command", "", 1 );
4002 
4003     r = RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Winetest_msi", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, NULL);
4004     ok( r == ERROR_SUCCESS, "Could not create key: %d.\n", r );
4005     r = RegSetValueExA(hkey, NULL, 0, REG_EXPAND_SZ, (const BYTE*)reg_expand_value, strlen(reg_expand_value) + 1);
4006     ok( r == ERROR_SUCCESS, "Could not set key value: %d.\n", r);
4007     RegCloseKey(hkey);
4008     add_reglocator_entry( hdb, "NewSignature3", 1, "Software\\Winetest_msi", "", 1 );
4009 
4010     create_drlocator_table( hdb );
4011     add_drlocator_entry( hdb, "'NewSignature2', 0, 'c:\\windows\\system32', 0" );
4012 
4013     create_signature_table( hdb );
4014     add_signature_entry( hdb, "'NewSignature1', 'FileName', '', '', '', '', '', '', ''" );
4015     add_signature_entry( hdb, "'NewSignature2', 'NOTEPAD.EXE|notepad.exe', '', '', '', '', '', '', ''" );
4016     add_signature_entry( hdb, "'NewSignature3', 'NOTEPAD.EXE|notepad.exe', '', '', '', '', '', '', ''" );
4017 
4018     r = package_from_db( hdb, &hpkg );
4019     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
4020     {
4021         skip("Not enough rights to perform tests\n");
4022         DeleteFileA(msifile);
4023         return;
4024     }
4025     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
4026     MsiCloseHandle( hdb );
4027     if (r != ERROR_SUCCESS)
4028         goto done;
4029 
4030     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4031 
4032     r = MsiDoActionA( hpkg, "AppSearch" );
4033     ok( r == ERROR_SUCCESS, "AppSearch failed: %d\n", r);
4034 
4035     size = sizeof(prop);
4036     r = MsiGetPropertyA( hpkg, "WEBBROWSERPROG", prop, &size );
4037     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
4038     ok( lstrlenA(prop) != 0, "Expected non-zero length\n");
4039 
4040     size = sizeof(prop);
4041     r = MsiGetPropertyA( hpkg, "NOTEPAD", prop, &size );
4042     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
4043 
4044     size = sizeof(prop);
4045     r = MsiGetPropertyA( hpkg, "REGEXPANDVAL", prop, &size );
4046     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
4047     ok( lstrlenA(prop) != 0, "Expected non-zero length\n");
4048 
4049 done:
4050     MsiCloseHandle( hpkg );
4051     DeleteFileA(msifile);
4052     RegDeleteKeyA(HKEY_CURRENT_USER, "Software\\Winetest_msi");
4053 }
4054 
4055 static void test_appsearch_complocator(void)
4056 {
4057     MSIHANDLE hpkg, hdb;
4058     char path[MAX_PATH], expected[MAX_PATH], prop[MAX_PATH];
4059     LPSTR usersid;
4060     DWORD size;
4061     UINT r;
4062 
4063     if (!(usersid = get_user_sid()))
4064         return;
4065 
4066     if (is_process_limited())
4067     {
4068         skip("process is limited\n");
4069         return;
4070     }
4071 
4072     create_test_file("FileName1");
4073     create_test_file("FileName4");
4074     set_component_path("FileName1", MSIINSTALLCONTEXT_MACHINE,
4075                        "{A8AE6692-96BA-4198-8399-145D7D1D0D0E}", NULL, FALSE);
4076 
4077     create_test_file("FileName2");
4078     set_component_path("FileName2", MSIINSTALLCONTEXT_USERUNMANAGED,
4079                        "{1D2CE6F3-E81C-4949-AB81-78D7DAD2AF2E}", usersid, FALSE);
4080 
4081     create_test_file("FileName3");
4082     set_component_path("FileName3", MSIINSTALLCONTEXT_USERMANAGED,
4083                        "{19E0B999-85F5-4973-A61B-DBE4D66ECB1D}", usersid, FALSE);
4084 
4085     create_test_file("FileName5");
4086     set_component_path("FileName5", MSIINSTALLCONTEXT_MACHINE,
4087                        "{F0CCA976-27A3-4808-9DDD-1A6FD50A0D5A}", NULL, TRUE);
4088 
4089     create_test_file("FileName6");
4090     set_component_path("FileName6", MSIINSTALLCONTEXT_MACHINE,
4091                        "{C0ECD96F-7898-4410-9667-194BD8C1B648}", NULL, TRUE);
4092 
4093     create_test_file("FileName7");
4094     set_component_path("FileName7", MSIINSTALLCONTEXT_MACHINE,
4095                        "{DB20F535-9C26-4127-9C2B-CC45A8B51DA1}", NULL, FALSE);
4096 
4097     /* dir is FALSE, but we're pretending it's a directory */
4098     set_component_path("IDontExist\\", MSIINSTALLCONTEXT_MACHINE,
4099                        "{91B7359B-07F2-4221-AA8D-DE102BB87A5F}", NULL, FALSE);
4100 
4101     create_file_with_version("FileName8.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4102     set_component_path("FileName8.dll", MSIINSTALLCONTEXT_MACHINE,
4103                        "{4A2E1B5B-4034-4177-833B-8CC35F1B3EF1}", NULL, FALSE);
4104 
4105     create_file_with_version("FileName9.dll", MAKELONG(1, 2), MAKELONG(3, 4));
4106     set_component_path("FileName9.dll", MSIINSTALLCONTEXT_MACHINE,
4107                        "{A204DF48-7346-4635-BA2E-66247DBAC9DF}", NULL, FALSE);
4108 
4109     create_file_with_version("FileName10.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4110     set_component_path("FileName10.dll", MSIINSTALLCONTEXT_MACHINE,
4111                        "{EC30CE73-4CF9-4908-BABD-1ED82E1515FD}", NULL, FALSE);
4112 
4113     hdb = create_package_db();
4114     ok(hdb, "Expected a valid database handle\n");
4115 
4116     create_appsearch_table(hdb);
4117     add_appsearch_entry(hdb, "'SIGPROP1', 'NewSignature1'");
4118     add_appsearch_entry(hdb, "'SIGPROP2', 'NewSignature2'");
4119     add_appsearch_entry(hdb, "'SIGPROP3', 'NewSignature3'");
4120     add_appsearch_entry(hdb, "'SIGPROP4', 'NewSignature4'");
4121     add_appsearch_entry(hdb, "'SIGPROP5', 'NewSignature5'");
4122     add_appsearch_entry(hdb, "'SIGPROP6', 'NewSignature6'");
4123     add_appsearch_entry(hdb, "'SIGPROP7', 'NewSignature7'");
4124     add_appsearch_entry(hdb, "'SIGPROP8', 'NewSignature8'");
4125     add_appsearch_entry(hdb, "'SIGPROP9', 'NewSignature9'");
4126     add_appsearch_entry(hdb, "'SIGPROP10', 'NewSignature10'");
4127     add_appsearch_entry(hdb, "'SIGPROP11', 'NewSignature11'");
4128     add_appsearch_entry(hdb, "'SIGPROP12', 'NewSignature12'");
4129 
4130     create_complocator_table(hdb);
4131 
4132     /* published component, machine, file, signature, misdbLocatorTypeFile */
4133     add_complocator_entry(hdb, "'NewSignature1', '{A8AE6692-96BA-4198-8399-145D7D1D0D0E}', 1");
4134 
4135     /* published component, user-unmanaged, file, signature, misdbLocatorTypeFile */
4136     add_complocator_entry(hdb, "'NewSignature2', '{1D2CE6F3-E81C-4949-AB81-78D7DAD2AF2E}', 1");
4137 
4138     /* published component, user-managed, file, signature, misdbLocatorTypeFile */
4139     add_complocator_entry(hdb, "'NewSignature3', '{19E0B999-85F5-4973-A61B-DBE4D66ECB1D}', 1");
4140 
4141     /* published component, machine, file, signature, misdbLocatorTypeDirectory */
4142     add_complocator_entry(hdb, "'NewSignature4', '{A8AE6692-96BA-4198-8399-145D7D1D0D0E}', 0");
4143 
4144     /* published component, machine, dir, signature, misdbLocatorTypeDirectory */
4145     add_complocator_entry(hdb, "'NewSignature5', '{F0CCA976-27A3-4808-9DDD-1A6FD50A0D5A}', 0");
4146 
4147     /* published component, machine, dir, no signature, misdbLocatorTypeDirectory */
4148     add_complocator_entry(hdb, "'NewSignature6', '{C0ECD96F-7898-4410-9667-194BD8C1B648}', 0");
4149 
4150     /* published component, machine, file, no signature, misdbLocatorTypeFile */
4151     add_complocator_entry(hdb, "'NewSignature7', '{DB20F535-9C26-4127-9C2B-CC45A8B51DA1}', 1");
4152 
4153     /* unpublished component, no signature, misdbLocatorTypeDir */
4154     add_complocator_entry(hdb, "'NewSignature8', '{FB671D5B-5083-4048-90E0-481C48D8F3A5}', 0");
4155 
4156     /* published component, no signature, dir does not exist misdbLocatorTypeDir */
4157     add_complocator_entry(hdb, "'NewSignature9', '{91B7359B-07F2-4221-AA8D-DE102BB87A5F}', 0");
4158 
4159     /* published component, signature w/ ver, misdbLocatorTypeFile */
4160     add_complocator_entry(hdb, "'NewSignature10', '{4A2E1B5B-4034-4177-833B-8CC35F1B3EF1}', 1");
4161 
4162     /* published component, signature w/ ver, ver > max, misdbLocatorTypeFile */
4163     add_complocator_entry(hdb, "'NewSignature11', '{A204DF48-7346-4635-BA2E-66247DBAC9DF}', 1");
4164 
4165     /* published component, signature w/ ver, sig->name ignored, misdbLocatorTypeFile */
4166     add_complocator_entry(hdb, "'NewSignature12', '{EC30CE73-4CF9-4908-BABD-1ED82E1515FD}', 1");
4167 
4168     create_signature_table(hdb);
4169     add_signature_entry(hdb, "'NewSignature1', 'FileName1', '', '', '', '', '', '', ''");
4170     add_signature_entry(hdb, "'NewSignature2', 'FileName2', '', '', '', '', '', '', ''");
4171     add_signature_entry(hdb, "'NewSignature3', 'FileName3', '', '', '', '', '', '', ''");
4172     add_signature_entry(hdb, "'NewSignature4', 'FileName4', '', '', '', '', '', '', ''");
4173     add_signature_entry(hdb, "'NewSignature5', 'FileName5', '', '', '', '', '', '', ''");
4174     add_signature_entry(hdb, "'NewSignature10', 'FileName8.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4175     add_signature_entry(hdb, "'NewSignature11', 'FileName9.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4176     add_signature_entry(hdb, "'NewSignature12', 'ignored', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4177 
4178     r = package_from_db(hdb, &hpkg);
4179     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
4180     {
4181         skip("Not enough rights to perform tests\n");
4182         goto error;
4183     }
4184     ok(r == ERROR_SUCCESS, "Expected a valid package handle %u\n", r);
4185 
4186     r = MsiSetPropertyA(hpkg, "SIGPROP8", "october");
4187     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4188 
4189     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4190 
4191     r = MsiDoActionA(hpkg, "AppSearch");
4192     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4193 
4194     strcpy(expected, CURR_DIR);
4195     if (is_root(CURR_DIR)) expected[2] = 0;
4196 
4197     size = MAX_PATH;
4198     sprintf(path, "%s\\FileName1", expected);
4199     r = MsiGetPropertyA(hpkg, "SIGPROP1", prop, &size);
4200     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4201     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4202 
4203     size = MAX_PATH;
4204     sprintf(path, "%s\\FileName2", expected);
4205     r = MsiGetPropertyA(hpkg, "SIGPROP2", prop, &size);
4206     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4207     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4208 
4209     size = MAX_PATH;
4210     sprintf(path, "%s\\FileName3", expected);
4211     r = MsiGetPropertyA(hpkg, "SIGPROP3", prop, &size);
4212     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4213     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4214 
4215     size = MAX_PATH;
4216     sprintf(path, "%s\\FileName4", expected);
4217     r = MsiGetPropertyA(hpkg, "SIGPROP4", prop, &size);
4218     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4219     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4220 
4221     size = MAX_PATH;
4222     sprintf(path, "%s\\FileName5", expected);
4223     r = MsiGetPropertyA(hpkg, "SIGPROP5", prop, &size);
4224     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4225     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4226 
4227     size = MAX_PATH;
4228     sprintf(path, "%s\\", expected);
4229     r = MsiGetPropertyA(hpkg, "SIGPROP6", prop, &size);
4230     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4231     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4232 
4233     size = MAX_PATH;
4234     sprintf(path, "%s\\", expected);
4235     r = MsiGetPropertyA(hpkg, "SIGPROP7", prop, &size);
4236     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4237     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4238 
4239     size = MAX_PATH;
4240     r = MsiGetPropertyA(hpkg, "SIGPROP8", prop, &size);
4241     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4242     ok(!lstrcmpA(prop, "october"), "Expected \"october\", got \"%s\"\n", prop);
4243 
4244     size = MAX_PATH;
4245     r = MsiGetPropertyA(hpkg, "SIGPROP9", prop, &size);
4246     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4247     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4248 
4249     size = MAX_PATH;
4250     sprintf(path, "%s\\FileName8.dll", expected);
4251     r = MsiGetPropertyA(hpkg, "SIGPROP10", prop, &size);
4252     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4253     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4254 
4255     size = MAX_PATH;
4256     r = MsiGetPropertyA(hpkg, "SIGPROP11", prop, &size);
4257     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4258     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4259 
4260     size = MAX_PATH;
4261     sprintf(path, "%s\\FileName10.dll", expected);
4262     r = MsiGetPropertyA(hpkg, "SIGPROP12", prop, &size);
4263     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4264     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4265 
4266     delete_component_path("{A8AE6692-96BA-4198-8399-145D7D1D0D0E}",
4267                           MSIINSTALLCONTEXT_MACHINE, NULL);
4268     delete_component_path("{1D2CE6F3-E81C-4949-AB81-78D7DAD2AF2E}",
4269                           MSIINSTALLCONTEXT_USERUNMANAGED, usersid);
4270     delete_component_path("{19E0B999-85F5-4973-A61B-DBE4D66ECB1D}",
4271                           MSIINSTALLCONTEXT_USERMANAGED, usersid);
4272     delete_component_path("{F0CCA976-27A3-4808-9DDD-1A6FD50A0D5A}",
4273                           MSIINSTALLCONTEXT_MACHINE, NULL);
4274     delete_component_path("{C0ECD96F-7898-4410-9667-194BD8C1B648}",
4275                           MSIINSTALLCONTEXT_MACHINE, NULL);
4276     delete_component_path("{DB20F535-9C26-4127-9C2B-CC45A8B51DA1}",
4277                           MSIINSTALLCONTEXT_MACHINE, NULL);
4278     delete_component_path("{91B7359B-07F2-4221-AA8D-DE102BB87A5F}",
4279                           MSIINSTALLCONTEXT_MACHINE, NULL);
4280     delete_component_path("{4A2E1B5B-4034-4177-833B-8CC35F1B3EF1}",
4281                           MSIINSTALLCONTEXT_MACHINE, NULL);
4282     delete_component_path("{A204DF48-7346-4635-BA2E-66247DBAC9DF}",
4283                           MSIINSTALLCONTEXT_MACHINE, NULL);
4284     delete_component_path("{EC30CE73-4CF9-4908-BABD-1ED82E1515FD}",
4285                           MSIINSTALLCONTEXT_MACHINE, NULL);
4286 
4287     MsiCloseHandle(hpkg);
4288 
4289 error:
4290     DeleteFileA("FileName1");
4291     DeleteFileA("FileName2");
4292     DeleteFileA("FileName3");
4293     DeleteFileA("FileName4");
4294     DeleteFileA("FileName5");
4295     DeleteFileA("FileName6");
4296     DeleteFileA("FileName7");
4297     DeleteFileA("FileName8.dll");
4298     DeleteFileA("FileName9.dll");
4299     DeleteFileA("FileName10.dll");
4300     DeleteFileA(msifile);
4301     LocalFree(usersid);
4302 }
4303 
4304 static void test_appsearch_reglocator(void)
4305 {
4306     MSIHANDLE hpkg, hdb;
4307     char path[MAX_PATH], expected[MAX_PATH], prop[MAX_PATH];
4308     DWORD binary[2], size, val;
4309     BOOL space, version, is_64bit = sizeof(void *) > sizeof(int);
4310     HKEY hklm, classes, hkcu, users;
4311     LPSTR pathdata, pathvar, ptr;
4312     LONG res;
4313     UINT r, type = 0;
4314     SYSTEM_INFO si;
4315 
4316     version = TRUE;
4317     if (!create_file_with_version("test.dll", MAKELONG(2, 1), MAKELONG(4, 3)))
4318         version = FALSE;
4319 
4320     DeleteFileA("test.dll");
4321 
4322     res = RegCreateKeyA(HKEY_CLASSES_ROOT, "Software\\Wine", &classes);
4323     if (res == ERROR_ACCESS_DENIED)
4324     {
4325         skip("Not enough rights to perform tests\n");
4326         return;
4327     }
4328     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4329 
4330     res = RegSetValueExA(classes, "Value1", 0, REG_SZ,
4331                          (const BYTE *)"regszdata", 10);
4332     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4333 
4334     res = RegCreateKeyA(HKEY_CURRENT_USER, "Software\\Wine", &hkcu);
4335     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4336 
4337     res = RegSetValueExA(hkcu, "Value1", 0, REG_SZ,
4338                          (const BYTE *)"regszdata", 10);
4339     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4340 
4341     users = 0;
4342     res = RegCreateKeyA(HKEY_USERS, "S-1-5-18\\Software\\Wine", &users);
4343     ok(res == ERROR_SUCCESS ||
4344        broken(res == ERROR_INVALID_PARAMETER),
4345        "Expected ERROR_SUCCESS, got %d\n", res);
4346 
4347     if (res == ERROR_SUCCESS)
4348     {
4349         res = RegSetValueExA(users, "Value1", 0, REG_SZ,
4350                              (const BYTE *)"regszdata", 10);
4351         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4352     }
4353 
4354     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine", &hklm);
4355     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4356 
4357     res = RegSetValueA(hklm, NULL, REG_SZ, "defvalue", 8);
4358     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4359 
4360     res = RegSetValueExA(hklm, "Value1", 0, REG_SZ,
4361                          (const BYTE *)"regszdata", 10);
4362     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4363 
4364     val = 42;
4365     res = RegSetValueExA(hklm, "Value2", 0, REG_DWORD,
4366                          (const BYTE *)&val, sizeof(DWORD));
4367     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4368 
4369     val = -42;
4370     res = RegSetValueExA(hklm, "Value3", 0, REG_DWORD,
4371                          (const BYTE *)&val, sizeof(DWORD));
4372     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4373 
4374     res = RegSetValueExA(hklm, "Value4", 0, REG_EXPAND_SZ,
4375                          (const BYTE *)"%PATH%", 7);
4376     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4377 
4378     res = RegSetValueExA(hklm, "Value5", 0, REG_EXPAND_SZ,
4379                          (const BYTE *)"my%NOVAR%", 10);
4380     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4381 
4382     res = RegSetValueExA(hklm, "Value6", 0, REG_MULTI_SZ,
4383                          (const BYTE *)"one\0two\0", 9);
4384     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4385 
4386     binary[0] = 0x1234abcd;
4387     binary[1] = 0x567890ef;
4388     res = RegSetValueExA(hklm, "Value7", 0, REG_BINARY,
4389                          (const BYTE *)binary, sizeof(binary));
4390     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4391 
4392     res = RegSetValueExA(hklm, "Value8", 0, REG_SZ,
4393                          (const BYTE *)"#regszdata", 11);
4394     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4395 
4396     strcpy(expected, CURR_DIR);
4397     if (is_root(CURR_DIR)) expected[2] = 0;
4398 
4399     create_test_file("FileName1");
4400     sprintf(path, "%s\\FileName1", expected);
4401     res = RegSetValueExA(hklm, "Value9", 0, REG_SZ,
4402                          (const BYTE *)path, lstrlenA(path) + 1);
4403     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4404 
4405     sprintf(path, "%s\\FileName2", expected);
4406     res = RegSetValueExA(hklm, "Value10", 0, REG_SZ,
4407                          (const BYTE *)path, lstrlenA(path) + 1);
4408     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4409 
4410     lstrcpyA(path, expected);
4411     res = RegSetValueExA(hklm, "Value11", 0, REG_SZ,
4412                          (const BYTE *)path, lstrlenA(path) + 1);
4413     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4414 
4415     res = RegSetValueExA(hklm, "Value12", 0, REG_SZ,
4416                          (const BYTE *)"", 1);
4417     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4418 
4419     create_file_with_version("FileName3.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4420     sprintf(path, "%s\\FileName3.dll", expected);
4421     res = RegSetValueExA(hklm, "Value13", 0, REG_SZ,
4422                          (const BYTE *)path, lstrlenA(path) + 1);
4423     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4424 
4425     create_file_with_version("FileName4.dll", MAKELONG(1, 2), MAKELONG(3, 4));
4426     sprintf(path, "%s\\FileName4.dll", expected);
4427     res = RegSetValueExA(hklm, "Value14", 0, REG_SZ,
4428                          (const BYTE *)path, lstrlenA(path) + 1);
4429     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4430 
4431     create_file_with_version("FileName5.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4432     sprintf(path, "%s\\FileName5.dll", expected);
4433     res = RegSetValueExA(hklm, "Value15", 0, REG_SZ,
4434                          (const BYTE *)path, lstrlenA(path) + 1);
4435     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4436 
4437     sprintf(path, "\"%s\\FileName1\" -option", expected);
4438     res = RegSetValueExA(hklm, "value16", 0, REG_SZ,
4439                          (const BYTE *)path, lstrlenA(path) + 1);
4440     ok( res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", res);
4441 
4442     space = strchr(expected, ' ') != NULL;
4443     sprintf(path, "%s\\FileName1 -option", expected);
4444     res = RegSetValueExA(hklm, "value17", 0, REG_SZ,
4445                          (const BYTE *)path, lstrlenA(path) + 1);
4446     ok( res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", res);
4447 
4448     hdb = create_package_db();
4449     ok(hdb, "Expected a valid database handle\n");
4450 
4451     create_appsearch_table(hdb);
4452     add_appsearch_entry(hdb, "'SIGPROP1', 'NewSignature1'");
4453     add_appsearch_entry(hdb, "'SIGPROP2', 'NewSignature2'");
4454     add_appsearch_entry(hdb, "'SIGPROP3', 'NewSignature3'");
4455     add_appsearch_entry(hdb, "'SIGPROP4', 'NewSignature4'");
4456     add_appsearch_entry(hdb, "'SIGPROP5', 'NewSignature5'");
4457     add_appsearch_entry(hdb, "'SIGPROP6', 'NewSignature6'");
4458     add_appsearch_entry(hdb, "'SIGPROP7', 'NewSignature7'");
4459     add_appsearch_entry(hdb, "'SIGPROP8', 'NewSignature8'");
4460     add_appsearch_entry(hdb, "'SIGPROP9', 'NewSignature9'");
4461     add_appsearch_entry(hdb, "'SIGPROP10', 'NewSignature10'");
4462     add_appsearch_entry(hdb, "'SIGPROP11', 'NewSignature11'");
4463     add_appsearch_entry(hdb, "'SIGPROP12', 'NewSignature12'");
4464     add_appsearch_entry(hdb, "'SIGPROP13', 'NewSignature13'");
4465     add_appsearch_entry(hdb, "'SIGPROP14', 'NewSignature14'");
4466     add_appsearch_entry(hdb, "'SIGPROP15', 'NewSignature15'");
4467     add_appsearch_entry(hdb, "'SIGPROP16', 'NewSignature16'");
4468     add_appsearch_entry(hdb, "'SIGPROP17', 'NewSignature17'");
4469     add_appsearch_entry(hdb, "'SIGPROP18', 'NewSignature18'");
4470     add_appsearch_entry(hdb, "'SIGPROP19', 'NewSignature19'");
4471     add_appsearch_entry(hdb, "'SIGPROP20', 'NewSignature20'");
4472     add_appsearch_entry(hdb, "'SIGPROP21', 'NewSignature21'");
4473     add_appsearch_entry(hdb, "'SIGPROP22', 'NewSignature22'");
4474     add_appsearch_entry(hdb, "'SIGPROP23', 'NewSignature23'");
4475     add_appsearch_entry(hdb, "'SIGPROP24', 'NewSignature24'");
4476     add_appsearch_entry(hdb, "'SIGPROP25', 'NewSignature25'");
4477     add_appsearch_entry(hdb, "'SIGPROP26', 'NewSignature26'");
4478     add_appsearch_entry(hdb, "'SIGPROP27', 'NewSignature27'");
4479     add_appsearch_entry(hdb, "'SIGPROP28', 'NewSignature28'");
4480     add_appsearch_entry(hdb, "'SIGPROP29', 'NewSignature29'");
4481     add_appsearch_entry(hdb, "'SIGPROP30', 'NewSignature30'");
4482 
4483     create_reglocator_table(hdb);
4484 
4485     type = msidbLocatorTypeRawValue;
4486     if (is_64bit)
4487         type |= msidbLocatorType64bit;
4488 
4489     /* HKLM, msidbLocatorTypeRawValue, REG_SZ */
4490     add_reglocator_entry(hdb, "NewSignature1", 2, "Software\\Wine", "Value1", type);
4491 
4492     /* HKLM, msidbLocatorTypeRawValue, positive DWORD */
4493     add_reglocator_entry(hdb, "NewSignature2", 2, "Software\\Wine", "Value2", type);
4494 
4495     /* HKLM, msidbLocatorTypeRawValue, negative DWORD */
4496     add_reglocator_entry(hdb, "NewSignature3", 2, "Software\\Wine", "Value3", type);
4497 
4498     /* HKLM, msidbLocatorTypeRawValue, REG_EXPAND_SZ */
4499     add_reglocator_entry(hdb, "NewSignature4", 2, "Software\\Wine", "Value4", type);
4500 
4501     /* HKLM, msidbLocatorTypeRawValue, REG_EXPAND_SZ */
4502     add_reglocator_entry(hdb, "NewSignature5", 2, "Software\\Wine", "Value5", type);
4503 
4504     /* HKLM, msidbLocatorTypeRawValue, REG_MULTI_SZ */
4505     add_reglocator_entry(hdb, "NewSignature6", 2, "Software\\Wine", "Value6", type);
4506 
4507     /* HKLM, msidbLocatorTypeRawValue, REG_BINARY */
4508     add_reglocator_entry(hdb, "NewSignature7", 2, "Software\\Wine", "Value7", type);
4509 
4510     /* HKLM, msidbLocatorTypeRawValue, REG_SZ first char is # */
4511     add_reglocator_entry(hdb, "NewSignature8", 2, "Software\\Wine", "Value8", type);
4512 
4513     type = msidbLocatorTypeFileName;
4514     if (is_64bit)
4515         type |= msidbLocatorType64bit;
4516 
4517     /* HKLM, msidbLocatorTypeFileName, signature, file exists */
4518     add_reglocator_entry(hdb, "NewSignature9", 2, "Software\\Wine", "Value9", type);
4519 
4520     /* HKLM, msidbLocatorTypeFileName, signature, file does not exist */
4521     add_reglocator_entry(hdb, "NewSignature10", 2, "Software\\Wine", "Value10", type);
4522 
4523     /* HKLM, msidbLocatorTypeFileName, no signature */
4524     add_reglocator_entry(hdb, "NewSignature11", 2, "Software\\Wine", "Value9", type);
4525 
4526     type = msidbLocatorTypeDirectory;
4527     if (is_64bit)
4528         type |= msidbLocatorType64bit;
4529 
4530     /* HKLM, msidbLocatorTypeDirectory, no signature, file exists */
4531     add_reglocator_entry(hdb, "NewSignature12", 2, "Software\\Wine", "Value9", type);
4532 
4533     /* HKLM, msidbLocatorTypeDirectory, no signature, directory exists */
4534     add_reglocator_entry(hdb, "NewSignature13", 2, "Software\\Wine", "Value11", type);
4535 
4536     /* HKLM, msidbLocatorTypeDirectory, signature, file exists */
4537     add_reglocator_entry(hdb, "NewSignature14", 2, "Software\\Wine", "Value9", type);
4538 
4539     type = msidbLocatorTypeRawValue;
4540     if (is_64bit)
4541         type |= msidbLocatorType64bit;
4542 
4543     /* HKCR, msidbLocatorTypeRawValue, REG_SZ */
4544     add_reglocator_entry(hdb, "NewSignature15", 0, "Software\\Wine", "Value1", type);
4545 
4546     /* HKCU, msidbLocatorTypeRawValue, REG_SZ */
4547     add_reglocator_entry(hdb, "NewSignature16", 1, "Software\\Wine", "Value1", type);
4548 
4549     /* HKU, msidbLocatorTypeRawValue, REG_SZ */
4550     add_reglocator_entry(hdb, "NewSignature17", 3, "S-1-5-18\\Software\\Wine", "Value1", type);
4551 
4552     /* HKLM, msidbLocatorTypeRawValue, REG_SZ, NULL Name */
4553     add_reglocator_entry(hdb, "NewSignature18", 2, "Software\\Wine", "", type);
4554 
4555     /* HKLM, msidbLocatorTypeRawValue, REG_SZ, key does not exist */
4556     add_reglocator_entry(hdb, "NewSignature19", 2, "Software\\IDontExist", "", type);
4557 
4558     /* HKLM, msidbLocatorTypeRawValue, REG_SZ, value is empty */
4559     add_reglocator_entry(hdb, "NewSignature20", 2, "Software\\Wine", "Value12", type);
4560 
4561     type = msidbLocatorTypeFileName;
4562     if (is_64bit)
4563         type |= msidbLocatorType64bit;
4564 
4565     /* HKLM, msidbLocatorTypeFileName, signature, file exists w/ version */
4566     add_reglocator_entry(hdb, "NewSignature21", 2, "Software\\Wine", "Value13", type);
4567 
4568     /* HKLM, msidbLocatorTypeFileName, file exists w/ version, version > max */
4569     add_reglocator_entry(hdb, "NewSignature22", 2, "Software\\Wine", "Value14", type);
4570 
4571     /* HKLM, msidbLocatorTypeFileName, file exists w/ version, sig->name ignored */
4572     add_reglocator_entry(hdb, "NewSignature23", 2, "Software\\Wine", "Value15", type);
4573 
4574     /* HKLM, msidbLocatorTypeFileName, no signature, directory exists */
4575     add_reglocator_entry(hdb, "NewSignature24", 2, "Software\\Wine", "Value11", type);
4576 
4577     /* HKLM, msidbLocatorTypeFileName, no signature, file does not exist */
4578     add_reglocator_entry(hdb, "NewSignature25", 2, "Software\\Wine", "Value10", type);
4579 
4580     type = msidbLocatorTypeDirectory;
4581     if (is_64bit)
4582         type |= msidbLocatorType64bit;
4583 
4584     /* HKLM, msidbLocatorTypeDirectory, signature, directory exists */
4585     add_reglocator_entry(hdb, "NewSignature26", 2, "Software\\Wine", "Value11", type);
4586 
4587     /* HKLM, msidbLocatorTypeDirectory, signature, file does not exist */
4588     add_reglocator_entry(hdb, "NewSignature27", 2, "Software\\Wine", "Value10", type);
4589 
4590     /* HKLM, msidbLocatorTypeDirectory, no signature, file does not exist */
4591     add_reglocator_entry(hdb, "NewSignature28", 2, "Software\\Wine", "Value10", type);
4592 
4593     type = msidbLocatorTypeFileName;
4594     if (is_64bit)
4595         type |= msidbLocatorType64bit;
4596 
4597     /* HKLM, msidbLocatorTypeFile, file exists, in quotes */
4598     add_reglocator_entry(hdb, "NewSignature29", 2, "Software\\Wine", "Value16", type);
4599 
4600     /* HKLM, msidbLocatorTypeFile, file exists, no quotes */
4601     add_reglocator_entry(hdb, "NewSignature30", 2, "Software\\Wine", "Value17", type);
4602 
4603     create_signature_table(hdb);
4604     add_signature_entry(hdb, "'NewSignature9', 'FileName1', '', '', '', '', '', '', ''");
4605     add_signature_entry(hdb, "'NewSignature10', 'FileName2', '', '', '', '', '', '', ''");
4606     add_signature_entry(hdb, "'NewSignature14', 'FileName1', '', '', '', '', '', '', ''");
4607     add_signature_entry(hdb, "'NewSignature21', 'FileName3.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4608     add_signature_entry(hdb, "'NewSignature22', 'FileName4.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4609     add_signature_entry(hdb, "'NewSignature23', 'ignored', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4610 
4611     if (!is_root(CURR_DIR))
4612     {
4613         ptr = strrchr(expected, '\\') + 1;
4614         sprintf(path, "'NewSignature26', '%s', '', '', '', '', '', '', ''", ptr);
4615         add_signature_entry(hdb, path);
4616     }
4617     add_signature_entry(hdb, "'NewSignature27', 'FileName2', '', '', '', '', '', '', ''");
4618     add_signature_entry(hdb, "'NewSignature29', 'FileName1', '', '', '', '', '', '', ''");
4619     add_signature_entry(hdb, "'NewSignature30', 'FileName1', '', '', '', '', '', '', ''");
4620 
4621     r = package_from_db(hdb, &hpkg);
4622     ok(r == ERROR_SUCCESS, "Expected a valid package handle %u\n", r);
4623 
4624     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4625 
4626     r = MsiDoActionA(hpkg, "AppSearch");
4627     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4628 
4629     size = MAX_PATH;
4630     r = MsiGetPropertyA(hpkg, "SIGPROP1", prop, &size);
4631     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4632     ok(!lstrcmpA(prop, "regszdata"),
4633        "Expected \"regszdata\", got \"%s\"\n", prop);
4634 
4635     size = MAX_PATH;
4636     r = MsiGetPropertyA(hpkg, "SIGPROP2", prop, &size);
4637     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4638     ok(!lstrcmpA(prop, "#42"), "Expected \"#42\", got \"%s\"\n", prop);
4639 
4640     size = MAX_PATH;
4641     r = MsiGetPropertyA(hpkg, "SIGPROP3", prop, &size);
4642     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4643     ok(!lstrcmpA(prop, "#-42"), "Expected \"#-42\", got \"%s\"\n", prop);
4644 
4645     memset(&si, 0, sizeof(si));
4646     if (pGetNativeSystemInfo) pGetNativeSystemInfo(&si);
4647 
4648     if (S(U(si)).wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
4649     {
4650         size = ExpandEnvironmentStringsA("%PATH%", NULL, 0);
4651         pathvar = HeapAlloc(GetProcessHeap(), 0, size);
4652         ExpandEnvironmentStringsA("%PATH%", pathvar, size);
4653 
4654         size = 0;
4655         r = MsiGetPropertyA(hpkg, "SIGPROP4", NULL, &size);
4656         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4657 
4658         pathdata = HeapAlloc(GetProcessHeap(), 0, ++size);
4659         r = MsiGetPropertyA(hpkg, "SIGPROP4", pathdata, &size);
4660         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4661         ok(!lstrcmpA(pathdata, pathvar),
4662             "Expected \"%s\", got \"%s\"\n", pathvar, pathdata);
4663 
4664         HeapFree(GetProcessHeap(), 0, pathvar);
4665         HeapFree(GetProcessHeap(), 0, pathdata);
4666     }
4667 
4668     size = MAX_PATH;
4669     r = MsiGetPropertyA(hpkg, "SIGPROP5", prop, &size);
4670     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4671     ok(!lstrcmpA(prop,
4672        "my%NOVAR%"), "Expected \"my%%NOVAR%%\", got \"%s\"\n", prop);
4673 
4674     size = MAX_PATH;
4675     r = MsiGetPropertyA(hpkg, "SIGPROP6", prop, &size);
4676     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4677     todo_wine
4678     {
4679         ok(!memcmp(prop, "\0one\0two\0\0", 10),
4680            "Expected \"\\0one\\0two\\0\\0\"\n");
4681     }
4682 
4683     size = MAX_PATH;
4684     lstrcpyA(path, "#xCDAB3412EF907856");
4685     r = MsiGetPropertyA(hpkg, "SIGPROP7", prop, &size);
4686     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4687     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4688 
4689     size = MAX_PATH;
4690     r = MsiGetPropertyA(hpkg, "SIGPROP8", prop, &size);
4691     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4692     ok(!lstrcmpA(prop, "##regszdata"),
4693        "Expected \"##regszdata\", got \"%s\"\n", prop);
4694 
4695     size = MAX_PATH;
4696     sprintf(path, "%s\\FileName1", expected);
4697     r = MsiGetPropertyA(hpkg, "SIGPROP9", prop, &size);
4698     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4699     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4700 
4701     size = MAX_PATH;
4702     r = MsiGetPropertyA(hpkg, "SIGPROP10", prop, &size);
4703     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4704     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4705 
4706     size = MAX_PATH;
4707     sprintf(path, "%s\\", expected);
4708     r = MsiGetPropertyA(hpkg, "SIGPROP11", prop, &size);
4709     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4710     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4711 
4712     size = MAX_PATH;
4713     r = MsiGetPropertyA(hpkg, "SIGPROP12", prop, &size);
4714     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4715     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4716 
4717     size = MAX_PATH;
4718     sprintf(path, "%s\\", expected);
4719     r = MsiGetPropertyA(hpkg, "SIGPROP13", prop, &size);
4720     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4721     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4722 
4723     size = MAX_PATH;
4724     r = MsiGetPropertyA(hpkg, "SIGPROP14", prop, &size);
4725     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4726     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4727 
4728     size = MAX_PATH;
4729     r = MsiGetPropertyA(hpkg, "SIGPROP15", 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     r = MsiGetPropertyA(hpkg, "SIGPROP16", prop, &size);
4736     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4737     ok(!lstrcmpA(prop, "regszdata"),
4738        "Expected \"regszdata\", got \"%s\"\n", prop);
4739 
4740     if (users)
4741     {
4742         size = MAX_PATH;
4743         r = MsiGetPropertyA(hpkg, "SIGPROP17", prop, &size);
4744         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4745         ok(!lstrcmpA(prop, "regszdata"),
4746            "Expected \"regszdata\", got \"%s\"\n", prop);
4747     }
4748 
4749     size = MAX_PATH;
4750     r = MsiGetPropertyA(hpkg, "SIGPROP18", prop, &size);
4751     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4752     ok(!lstrcmpA(prop, "defvalue"),
4753        "Expected \"defvalue\", got \"%s\"\n", prop);
4754 
4755     size = MAX_PATH;
4756     r = MsiGetPropertyA(hpkg, "SIGPROP19", prop, &size);
4757     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4758     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4759 
4760     size = MAX_PATH;
4761     r = MsiGetPropertyA(hpkg, "SIGPROP20", prop, &size);
4762     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4763     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4764 
4765     if (version)
4766     {
4767         size = MAX_PATH;
4768         sprintf(path, "%s\\FileName3.dll", expected);
4769         r = MsiGetPropertyA(hpkg, "SIGPROP21", prop, &size);
4770         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4771         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4772 
4773         size = MAX_PATH;
4774         r = MsiGetPropertyA(hpkg, "SIGPROP22", prop, &size);
4775         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4776         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4777 
4778         size = MAX_PATH;
4779         sprintf(path, "%s\\FileName5.dll", expected);
4780         r = MsiGetPropertyA(hpkg, "SIGPROP23", prop, &size);
4781         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4782         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4783     }
4784 
4785     if (!is_root(CURR_DIR))
4786     {
4787         size = MAX_PATH;
4788         lstrcpyA(path, expected);
4789         ptr = strrchr(path, '\\') + 1;
4790         *ptr = '\0';
4791         r = MsiGetPropertyA(hpkg, "SIGPROP24", prop, &size);
4792         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4793         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4794     }
4795     size = MAX_PATH;
4796     sprintf(path, "%s\\", expected);
4797     r = MsiGetPropertyA(hpkg, "SIGPROP25", prop, &size);
4798     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4799     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4800 
4801     size = MAX_PATH;
4802     r = MsiGetPropertyA(hpkg, "SIGPROP26", prop, &size);
4803     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4804     if (is_root(CURR_DIR))
4805         ok(!lstrcmpA(prop, CURR_DIR), "Expected \"%s\", got \"%s\"\n", CURR_DIR, prop);
4806     else
4807         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4808 
4809     size = MAX_PATH;
4810     r = MsiGetPropertyA(hpkg, "SIGPROP27", prop, &size);
4811     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4812     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4813 
4814     size = MAX_PATH;
4815     r = MsiGetPropertyA(hpkg, "SIGPROP28", prop, &size);
4816     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4817     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4818 
4819     size = MAX_PATH;
4820     sprintf(path, "%s\\FileName1", expected);
4821     r = MsiGetPropertyA(hpkg, "SIGPROP29", prop, &size);
4822     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4823     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4824 
4825     size = MAX_PATH;
4826     sprintf(path, "%s\\FileName1", expected);
4827     r = MsiGetPropertyA(hpkg, "SIGPROP30", prop, &size);
4828     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4829     if (space)
4830         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4831     else
4832         todo_wine ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4833 
4834     RegSetValueA(hklm, NULL, REG_SZ, "", 0);
4835     RegDeleteValueA(hklm, "Value1");
4836     RegDeleteValueA(hklm, "Value2");
4837     RegDeleteValueA(hklm, "Value3");
4838     RegDeleteValueA(hklm, "Value4");
4839     RegDeleteValueA(hklm, "Value5");
4840     RegDeleteValueA(hklm, "Value6");
4841     RegDeleteValueA(hklm, "Value7");
4842     RegDeleteValueA(hklm, "Value8");
4843     RegDeleteValueA(hklm, "Value9");
4844     RegDeleteValueA(hklm, "Value10");
4845     RegDeleteValueA(hklm, "Value11");
4846     RegDeleteValueA(hklm, "Value12");
4847     RegDeleteValueA(hklm, "Value13");
4848     RegDeleteValueA(hklm, "Value14");
4849     RegDeleteValueA(hklm, "Value15");
4850     RegDeleteValueA(hklm, "Value16");
4851     RegDeleteValueA(hklm, "Value17");
4852     RegDeleteKeyA(hklm, "");
4853     RegCloseKey(hklm);
4854 
4855     RegDeleteValueA(classes, "Value1");
4856     RegDeleteKeyA(classes, "");
4857     RegCloseKey(classes);
4858 
4859     RegDeleteValueA(hkcu, "Value1");
4860     RegDeleteKeyA(hkcu, "");
4861     RegCloseKey(hkcu);
4862 
4863     RegDeleteValueA(users, "Value1");
4864     RegDeleteKeyA(users, "");
4865     RegCloseKey(users);
4866 
4867     DeleteFileA("FileName1");
4868     DeleteFileA("FileName3.dll");
4869     DeleteFileA("FileName4.dll");
4870     DeleteFileA("FileName5.dll");
4871     MsiCloseHandle(hpkg);
4872     DeleteFileA(msifile);
4873 }
4874 
4875 static void delete_win_ini(LPCSTR file)
4876 {
4877     CHAR path[MAX_PATH];
4878 
4879     GetWindowsDirectoryA(path, MAX_PATH);
4880     lstrcatA(path, "\\");
4881     lstrcatA(path, file);
4882 
4883     DeleteFileA(path);
4884 }
4885 
4886 static void test_appsearch_inilocator(void)
4887 {
4888     MSIHANDLE hpkg, hdb;
4889     char path[MAX_PATH], expected[MAX_PATH], prop[MAX_PATH];
4890     BOOL version;
4891     LPSTR ptr;
4892     DWORD size;
4893     UINT r;
4894 
4895     version = TRUE;
4896     if (!create_file_with_version("test.dll", MAKELONG(2, 1), MAKELONG(4, 3)))
4897         version = FALSE;
4898 
4899     DeleteFileA("test.dll");
4900 
4901     WritePrivateProfileStringA("Section", "Key", "keydata,field2", "IniFile.ini");
4902 
4903     strcpy(expected, CURR_DIR);
4904     if (is_root(CURR_DIR)) expected[2] = 0;
4905 
4906     create_test_file("FileName1");
4907     sprintf(path, "%s\\FileName1", expected);
4908     WritePrivateProfileStringA("Section", "Key2", path, "IniFile.ini");
4909 
4910     WritePrivateProfileStringA("Section", "Key3", expected, "IniFile.ini");
4911 
4912     sprintf(path, "%s\\IDontExist", expected);
4913     WritePrivateProfileStringA("Section", "Key4", path, "IniFile.ini");
4914 
4915     create_file_with_version("FileName2.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4916     sprintf(path, "%s\\FileName2.dll", expected);
4917     WritePrivateProfileStringA("Section", "Key5", path, "IniFile.ini");
4918 
4919     create_file_with_version("FileName3.dll", MAKELONG(1, 2), MAKELONG(3, 4));
4920     sprintf(path, "%s\\FileName3.dll", expected);
4921     WritePrivateProfileStringA("Section", "Key6", path, "IniFile.ini");
4922 
4923     create_file_with_version("FileName4.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4924     sprintf(path, "%s\\FileName4.dll", expected);
4925     WritePrivateProfileStringA("Section", "Key7", path, "IniFile.ini");
4926 
4927     hdb = create_package_db();
4928     ok(hdb, "Expected a valid database handle\n");
4929 
4930     create_appsearch_table(hdb);
4931     add_appsearch_entry(hdb, "'SIGPROP1', 'NewSignature1'");
4932     add_appsearch_entry(hdb, "'SIGPROP2', 'NewSignature2'");
4933     add_appsearch_entry(hdb, "'SIGPROP3', 'NewSignature3'");
4934     add_appsearch_entry(hdb, "'SIGPROP4', 'NewSignature4'");
4935     add_appsearch_entry(hdb, "'SIGPROP5', 'NewSignature5'");
4936     add_appsearch_entry(hdb, "'SIGPROP6', 'NewSignature6'");
4937     add_appsearch_entry(hdb, "'SIGPROP7', 'NewSignature7'");
4938     add_appsearch_entry(hdb, "'SIGPROP8', 'NewSignature8'");
4939     add_appsearch_entry(hdb, "'SIGPROP9', 'NewSignature9'");
4940     add_appsearch_entry(hdb, "'SIGPROP10', 'NewSignature10'");
4941     add_appsearch_entry(hdb, "'SIGPROP11', 'NewSignature11'");
4942     add_appsearch_entry(hdb, "'SIGPROP12', 'NewSignature12'");
4943 
4944     create_inilocator_table(hdb);
4945 
4946     /* msidbLocatorTypeRawValue, field 1 */
4947     add_inilocator_entry(hdb, "'NewSignature1', 'IniFile.ini', 'Section', 'Key', 1, 2");
4948 
4949     /* msidbLocatorTypeRawValue, field 2 */
4950     add_inilocator_entry(hdb, "'NewSignature2', 'IniFile.ini', 'Section', 'Key', 2, 2");
4951 
4952     /* msidbLocatorTypeRawValue, entire field */
4953     add_inilocator_entry(hdb, "'NewSignature3', 'IniFile.ini', 'Section', 'Key', 0, 2");
4954 
4955     /* msidbLocatorTypeFile */
4956     add_inilocator_entry(hdb, "'NewSignature4', 'IniFile.ini', 'Section', 'Key2', 1, 1");
4957 
4958     /* msidbLocatorTypeDirectory, file */
4959     add_inilocator_entry(hdb, "'NewSignature5', 'IniFile.ini', 'Section', 'Key2', 1, 0");
4960 
4961     /* msidbLocatorTypeDirectory, directory */
4962     add_inilocator_entry(hdb, "'NewSignature6', 'IniFile.ini', 'Section', 'Key3', 1, 0");
4963 
4964     /* msidbLocatorTypeFile, file, no signature */
4965     add_inilocator_entry(hdb, "'NewSignature7', 'IniFile.ini', 'Section', 'Key2', 1, 1");
4966 
4967     /* msidbLocatorTypeFile, dir, no signature */
4968     add_inilocator_entry(hdb, "'NewSignature8', 'IniFile.ini', 'Section', 'Key3', 1, 1");
4969 
4970     /* msidbLocatorTypeFile, file does not exist */
4971     add_inilocator_entry(hdb, "'NewSignature9', 'IniFile.ini', 'Section', 'Key4', 1, 1");
4972 
4973     /* msidbLocatorTypeFile, signature with version */
4974     add_inilocator_entry(hdb, "'NewSignature10', 'IniFile.ini', 'Section', 'Key5', 1, 1");
4975 
4976     /* msidbLocatorTypeFile, signature with version, ver > max */
4977     add_inilocator_entry(hdb, "'NewSignature11', 'IniFile.ini', 'Section', 'Key6', 1, 1");
4978 
4979     /* msidbLocatorTypeFile, signature with version, sig->name ignored */
4980     add_inilocator_entry(hdb, "'NewSignature12', 'IniFile.ini', 'Section', 'Key7', 1, 1");
4981 
4982     create_signature_table(hdb);
4983     add_signature_entry(hdb, "'NewSignature4', 'FileName1', '', '', '', '', '', '', ''");
4984     add_signature_entry(hdb, "'NewSignature9', 'IDontExist', '', '', '', '', '', '', ''");
4985     add_signature_entry(hdb, "'NewSignature10', 'FileName2.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4986     add_signature_entry(hdb, "'NewSignature11', 'FileName3.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4987     add_signature_entry(hdb, "'NewSignature12', 'ignored', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4988 
4989     r = package_from_db(hdb, &hpkg);
4990     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
4991     {
4992         skip("Not enough rights to perform tests\n");
4993         goto error;
4994     }
4995     ok(r == ERROR_SUCCESS, "Expected a valid package handle %u\n", r);
4996 
4997     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4998 
4999     r = MsiDoActionA(hpkg, "AppSearch");
5000     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5001 
5002     size = MAX_PATH;
5003     r = MsiGetPropertyA(hpkg, "SIGPROP1", prop, &size);
5004     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5005     ok(!lstrcmpA(prop, "keydata"), "Expected \"keydata\", got \"%s\"\n", prop);
5006 
5007     size = MAX_PATH;
5008     r = MsiGetPropertyA(hpkg, "SIGPROP2", prop, &size);
5009     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5010     ok(!lstrcmpA(prop, "field2"), "Expected \"field2\", got \"%s\"\n", prop);
5011 
5012     size = MAX_PATH;
5013     r = MsiGetPropertyA(hpkg, "SIGPROP3", prop, &size);
5014     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5015     ok(!lstrcmpA(prop, "keydata,field2"),
5016        "Expected \"keydata,field2\", got \"%s\"\n", prop);
5017 
5018     size = MAX_PATH;
5019     sprintf(path, "%s\\FileName1", expected);
5020     r = MsiGetPropertyA(hpkg, "SIGPROP4", prop, &size);
5021     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5022     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5023 
5024     size = MAX_PATH;
5025     r = MsiGetPropertyA(hpkg, "SIGPROP5", prop, &size);
5026     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5027     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5028 
5029     size = MAX_PATH;
5030     sprintf(path, "%s\\", expected);
5031     r = MsiGetPropertyA(hpkg, "SIGPROP6", prop, &size);
5032     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5033     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5034 
5035     size = MAX_PATH;
5036     sprintf(path, "%s\\", expected);
5037     r = MsiGetPropertyA(hpkg, "SIGPROP7", prop, &size);
5038     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5039     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5040 
5041     if (!is_root(CURR_DIR))
5042     {
5043         size = MAX_PATH;
5044         lstrcpyA(path, expected);
5045         ptr = strrchr(path, '\\');
5046         *(ptr + 1) = 0;
5047         r = MsiGetPropertyA(hpkg, "SIGPROP8", prop, &size);
5048         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5049         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5050     }
5051     size = MAX_PATH;
5052     r = MsiGetPropertyA(hpkg, "SIGPROP9", prop, &size);
5053     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5054     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5055 
5056     if (version)
5057     {
5058         size = MAX_PATH;
5059         sprintf(path, "%s\\FileName2.dll", expected);
5060         r = MsiGetPropertyA(hpkg, "SIGPROP10", prop, &size);
5061         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5062         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5063 
5064         size = MAX_PATH;
5065         r = MsiGetPropertyA(hpkg, "SIGPROP11", prop, &size);
5066         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5067         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5068 
5069         size = MAX_PATH;
5070         sprintf(path, "%s\\FileName4.dll", expected);
5071         r = MsiGetPropertyA(hpkg, "SIGPROP12", prop, &size);
5072         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5073         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5074     }
5075 
5076     MsiCloseHandle(hpkg);
5077 
5078 error:
5079     delete_win_ini("IniFile.ini");
5080     DeleteFileA("FileName1");
5081     DeleteFileA("FileName2.dll");
5082     DeleteFileA("FileName3.dll");
5083     DeleteFileA("FileName4.dll");
5084     DeleteFileA(msifile);
5085 }
5086 
5087 /*
5088  * MSI AppSearch action on DrLocator table always returns absolute paths.
5089  * If a relative path was set, it returns the first absolute path that
5090  * matches or an empty string if it didn't find anything.
5091  * This helper function replicates this behaviour.
5092  */
5093 static void search_absolute_directory(LPSTR absolute, LPCSTR relative)
5094 {
5095     int i, size;
5096     DWORD attr, drives;
5097 
5098     size = lstrlenA(relative);
5099     drives = GetLogicalDrives();
5100     lstrcpyA(absolute, "A:\\");
5101     for (i = 0; i < 26; absolute[0] = '\0', i++)
5102     {
5103         if (!(drives & (1 << i)))
5104             continue;
5105 
5106         absolute[0] = 'A' + i;
5107         if (GetDriveTypeA(absolute) != DRIVE_FIXED)
5108             continue;
5109 
5110         lstrcpynA(absolute + 3, relative, size + 1);
5111         attr = GetFileAttributesA(absolute);
5112         if (attr != INVALID_FILE_ATTRIBUTES &&
5113             (attr & FILE_ATTRIBUTE_DIRECTORY))
5114         {
5115             if (absolute[3 + size - 1] != '\\')
5116                 lstrcatA(absolute, "\\");
5117             break;
5118         }
5119         absolute[3] = '\0';
5120     }
5121 }
5122 
5123 static void test_appsearch_drlocator(void)
5124 {
5125     MSIHANDLE hpkg, hdb;
5126     char path[MAX_PATH], expected[MAX_PATH], prop[MAX_PATH];
5127     BOOL version;
5128     DWORD size;
5129     UINT r;
5130 
5131     version = TRUE;
5132     if (!create_file_with_version("test.dll", MAKELONG(2, 1), MAKELONG(4, 3)))
5133         version = FALSE;
5134 
5135     DeleteFileA("test.dll");
5136 
5137     create_test_file("FileName1");
5138     CreateDirectoryA("one", NULL);
5139     CreateDirectoryA("one\\two", NULL);
5140     CreateDirectoryA("one\\two\\three", NULL);
5141     create_test_file("one\\two\\three\\FileName2");
5142     CreateDirectoryA("another", NULL);
5143     create_file_with_version("FileName3.dll", MAKELONG(2, 1), MAKELONG(4, 3));
5144     create_file_with_version("FileName4.dll", MAKELONG(1, 2), MAKELONG(3, 4));
5145     create_file_with_version("FileName5.dll", MAKELONG(2, 1), MAKELONG(4, 3));
5146 
5147     hdb = create_package_db();
5148     ok(hdb, "Expected a valid database handle\n");
5149 
5150     create_appsearch_table(hdb);
5151     add_appsearch_entry(hdb, "'SIGPROP1', 'NewSignature1'");
5152     add_appsearch_entry(hdb, "'SIGPROP2', 'NewSignature2'");
5153     add_appsearch_entry(hdb, "'SIGPROP3', 'NewSignature3'");
5154     add_appsearch_entry(hdb, "'SIGPROP4', 'NewSignature4'");
5155     add_appsearch_entry(hdb, "'SIGPROP5', 'NewSignature5'");
5156     add_appsearch_entry(hdb, "'SIGPROP6', 'NewSignature6'");
5157     add_appsearch_entry(hdb, "'SIGPROP7', 'NewSignature7'");
5158     add_appsearch_entry(hdb, "'SIGPROP8', 'NewSignature8'");
5159     add_appsearch_entry(hdb, "'SIGPROP9', 'NewSignature9'");
5160     add_appsearch_entry(hdb, "'SIGPROP10', 'NewSignature10'");
5161     add_appsearch_entry(hdb, "'SIGPROP11', 'NewSignature11'");
5162     add_appsearch_entry(hdb, "'SIGPROP13', 'NewSignature13'");
5163 
5164     create_drlocator_table(hdb);
5165 
5166     strcpy(expected, CURR_DIR);
5167     if (is_root(CURR_DIR)) expected[2] = 0;
5168 
5169     /* no parent, full path, depth 0, signature */
5170     sprintf(path, "'NewSignature1', '', '%s', 0", expected);
5171     add_drlocator_entry(hdb, path);
5172 
5173     /* no parent, full path, depth 0, no signature */
5174     sprintf(path, "'NewSignature2', '', '%s', 0", expected);
5175     add_drlocator_entry(hdb, path);
5176 
5177     /* no parent, relative path, depth 0, no signature */
5178     sprintf(path, "'NewSignature3', '', '%s', 0", expected + 3);
5179     add_drlocator_entry(hdb, path);
5180 
5181     /* no parent, full path, depth 2, signature */
5182     sprintf(path, "'NewSignature4', '', '%s', 2", expected);
5183     add_drlocator_entry(hdb, path);
5184 
5185     /* no parent, full path, depth 3, signature */
5186     sprintf(path, "'NewSignature5', '', '%s', 3", expected);
5187     add_drlocator_entry(hdb, path);
5188 
5189     /* no parent, full path, depth 1, signature is dir */
5190     sprintf(path, "'NewSignature6', '', '%s', 1", expected);
5191     add_drlocator_entry(hdb, path);
5192 
5193     /* parent is in DrLocator, relative path, depth 0, signature */
5194     sprintf(path, "'NewSignature7', 'NewSignature1', 'one\\two\\three', 1");
5195     add_drlocator_entry(hdb, path);
5196 
5197     /* no parent, full path, depth 0, signature w/ version */
5198     sprintf(path, "'NewSignature8', '', '%s', 0", expected);
5199     add_drlocator_entry(hdb, path);
5200 
5201     /* no parent, full path, depth 0, signature w/ version, ver > max */
5202     sprintf(path, "'NewSignature9', '', '%s', 0", expected);
5203     add_drlocator_entry(hdb, path);
5204 
5205     /* no parent, full path, depth 0, signature w/ version, sig->name not ignored */
5206     sprintf(path, "'NewSignature10', '', '%s', 0", expected);
5207     add_drlocator_entry(hdb, path);
5208 
5209     /* no parent, relative empty path, depth 0, no signature */
5210     sprintf(path, "'NewSignature11', '', '', 0");
5211     add_drlocator_entry(hdb, path);
5212 
5213     create_reglocator_table(hdb);
5214 
5215     /* parent */
5216     add_reglocator_entry(hdb, "NewSignature12", 2, "htmlfile\\shell\\open\\nonexistent", "", 1);
5217 
5218     /* parent is in RegLocator, no path, depth 0, no signature */
5219     sprintf(path, "'NewSignature13', 'NewSignature12', '', 0");
5220     add_drlocator_entry(hdb, path);
5221 
5222     create_signature_table(hdb);
5223     add_signature_entry(hdb, "'NewSignature1', 'FileName1', '', '', '', '', '', '', ''");
5224     add_signature_entry(hdb, "'NewSignature4', 'FileName2', '', '', '', '', '', '', ''");
5225     add_signature_entry(hdb, "'NewSignature5', 'FileName2', '', '', '', '', '', '', ''");
5226     add_signature_entry(hdb, "'NewSignature6', 'another', '', '', '', '', '', '', ''");
5227     add_signature_entry(hdb, "'NewSignature7', 'FileName2', '', '', '', '', '', '', ''");
5228     add_signature_entry(hdb, "'NewSignature8', 'FileName3.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
5229     add_signature_entry(hdb, "'NewSignature9', 'FileName4.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
5230     add_signature_entry(hdb, "'NewSignature10', 'necessary', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
5231 
5232     r = package_from_db(hdb, &hpkg);
5233     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5234     {
5235         skip("Not enough rights to perform tests\n");
5236         goto error;
5237     }
5238     ok(r == ERROR_SUCCESS, "Expected a valid package handle %u\n", r);
5239 
5240     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5241 
5242     r = MsiDoActionA(hpkg, "AppSearch");
5243     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5244 
5245     size = MAX_PATH;
5246     sprintf(path, "%s\\FileName1", expected);
5247     r = MsiGetPropertyA(hpkg, "SIGPROP1", prop, &size);
5248     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5249     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5250 
5251     size = MAX_PATH;
5252     sprintf(path, "%s\\", expected);
5253     r = MsiGetPropertyA(hpkg, "SIGPROP2", prop, &size);
5254     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5255     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5256 
5257     size = MAX_PATH;
5258     search_absolute_directory(path, expected + 3);
5259     r = MsiGetPropertyA(hpkg, "SIGPROP3", prop, &size);
5260     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5261     ok(!lstrcmpiA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5262 
5263     size = MAX_PATH;
5264     r = MsiGetPropertyA(hpkg, "SIGPROP4", prop, &size);
5265     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5266     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5267 
5268     size = MAX_PATH;
5269     sprintf(path, "%s\\one\\two\\three\\FileName2", expected);
5270     r = MsiGetPropertyA(hpkg, "SIGPROP5", prop, &size);
5271     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5272     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5273 
5274     size = MAX_PATH;
5275     r = MsiGetPropertyA(hpkg, "SIGPROP6", prop, &size);
5276     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5277     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5278 
5279     size = MAX_PATH;
5280     sprintf(path, "%s\\one\\two\\three\\FileName2", expected);
5281     r = MsiGetPropertyA(hpkg, "SIGPROP7", prop, &size);
5282     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5283     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5284 
5285     if (version)
5286     {
5287         size = MAX_PATH;
5288         sprintf(path, "%s\\FileName3.dll", expected);
5289         r = MsiGetPropertyA(hpkg, "SIGPROP8", prop, &size);
5290         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5291         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5292 
5293         size = MAX_PATH;
5294         r = MsiGetPropertyA(hpkg, "SIGPROP9", prop, &size);
5295         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5296         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5297 
5298         size = MAX_PATH;
5299         r = MsiGetPropertyA(hpkg, "SIGPROP10", prop, &size);
5300         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5301         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5302     }
5303 
5304     size = MAX_PATH;
5305     search_absolute_directory(path, "");
5306     r = MsiGetPropertyA(hpkg, "SIGPROP11", prop, &size);
5307     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5308     ok(!lstrcmpiA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5309 
5310     size = MAX_PATH;
5311     strcpy(path, "c:\\");
5312     r = MsiGetPropertyA(hpkg, "SIGPROP13", prop, &size);
5313     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5314     ok(!prop[0], "Expected \"\", got \"%s\"\n", prop);
5315 
5316     MsiCloseHandle(hpkg);
5317 
5318 error:
5319     DeleteFileA("FileName1");
5320     DeleteFileA("FileName3.dll");
5321     DeleteFileA("FileName4.dll");
5322     DeleteFileA("FileName5.dll");
5323     DeleteFileA("one\\two\\three\\FileName2");
5324     RemoveDirectoryA("one\\two\\three");
5325     RemoveDirectoryA("one\\two");
5326     RemoveDirectoryA("one");
5327     RemoveDirectoryA("another");
5328     DeleteFileA(msifile);
5329 }
5330 
5331 static void test_featureparents(void)
5332 {
5333     MSIHANDLE hpkg;
5334     UINT r;
5335     MSIHANDLE hdb;
5336 
5337     hdb = create_package_db();
5338     ok ( hdb, "failed to create package database\n" );
5339 
5340     add_directory_entry(hdb, "'TARGETDIR', '', 'SourceDir'");
5341 
5342     create_feature_table( hdb );
5343     create_component_table( hdb );
5344     create_feature_components_table( hdb );
5345     create_file_table( hdb );
5346 
5347     /* msidbFeatureAttributesFavorLocal */
5348     add_feature_entry( hdb, "'zodiac', '', '', '', 2, 1, '', 0" );
5349 
5350     /* msidbFeatureAttributesFavorSource */
5351     add_feature_entry( hdb, "'perseus', '', '', '', 2, 1, '', 1" );
5352 
5353     /* msidbFeatureAttributesFavorLocal */
5354     add_feature_entry( hdb, "'orion', '', '', '', 2, 1, '', 0" );
5355 
5356     /* msidbFeatureAttributesUIDisallowAbsent */
5357     add_feature_entry( hdb, "'lyra', '', '', '', 2, 1, '', 16" );
5358 
5359     /* disabled because of install level */
5360     add_feature_entry( hdb, "'waters', '', '', '', 15, 101, '', 9" );
5361 
5362     /* child feature of disabled feature */
5363     add_feature_entry( hdb, "'bayer', 'waters', '', '', 14, 1, '', 9" );
5364 
5365     /* component of disabled feature (install level) */
5366     add_component_entry( hdb, "'delphinus', '', 'TARGETDIR', 0, '', 'delphinus_file'" );
5367 
5368     /* component of disabled child feature (install level) */
5369     add_component_entry( hdb, "'hydrus', '', 'TARGETDIR', 0, '', 'hydrus_file'" );
5370 
5371     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesLocalOnly */
5372     add_component_entry( hdb, "'leo', '', 'TARGETDIR', 0, '', 'leo_file'" );
5373 
5374     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSourceOnly */
5375     add_component_entry( hdb, "'virgo', '', 'TARGETDIR', 1, '', 'virgo_file'" );
5376 
5377     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesOptional */
5378     add_component_entry( hdb, "'libra', '', 'TARGETDIR', 2, '', 'libra_file'" );
5379 
5380     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesLocalOnly */
5381     add_component_entry( hdb, "'cassiopeia', '', 'TARGETDIR', 0, '', 'cassiopeia_file'" );
5382 
5383     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSourceOnly */
5384     add_component_entry( hdb, "'cepheus', '', 'TARGETDIR', 1, '', 'cepheus_file'" );
5385 
5386     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesOptional */
5387     add_component_entry( hdb, "'andromeda', '', 'TARGETDIR', 2, '', 'andromeda_file'" );
5388 
5389     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesLocalOnly */
5390     add_component_entry( hdb, "'canis', '', 'TARGETDIR', 0, '', 'canis_file'" );
5391 
5392     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSourceOnly */
5393     add_component_entry( hdb, "'monoceros', '', 'TARGETDIR', 1, '', 'monoceros_file'" );
5394 
5395     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesOptional */
5396     add_component_entry( hdb, "'lepus', '', 'TARGETDIR', 2, '', 'lepus_file'" );
5397 
5398     add_feature_components_entry( hdb, "'zodiac', 'leo'" );
5399     add_feature_components_entry( hdb, "'zodiac', 'virgo'" );
5400     add_feature_components_entry( hdb, "'zodiac', 'libra'" );
5401     add_feature_components_entry( hdb, "'perseus', 'cassiopeia'" );
5402     add_feature_components_entry( hdb, "'perseus', 'cepheus'" );
5403     add_feature_components_entry( hdb, "'perseus', 'andromeda'" );
5404     add_feature_components_entry( hdb, "'orion', 'leo'" );
5405     add_feature_components_entry( hdb, "'orion', 'virgo'" );
5406     add_feature_components_entry( hdb, "'orion', 'libra'" );
5407     add_feature_components_entry( hdb, "'orion', 'cassiopeia'" );
5408     add_feature_components_entry( hdb, "'orion', 'cepheus'" );
5409     add_feature_components_entry( hdb, "'orion', 'andromeda'" );
5410     add_feature_components_entry( hdb, "'orion', 'canis'" );
5411     add_feature_components_entry( hdb, "'orion', 'monoceros'" );
5412     add_feature_components_entry( hdb, "'orion', 'lepus'" );
5413     add_feature_components_entry( hdb, "'waters', 'delphinus'" );
5414     add_feature_components_entry( hdb, "'bayer', 'hydrus'" );
5415 
5416     add_file_entry( hdb, "'leo_file', 'leo', 'leo.txt', 100, '', '1033', 8192, 1" );
5417     add_file_entry( hdb, "'virgo_file', 'virgo', 'virgo.txt', 0, '', '1033', 8192, 1" );
5418     add_file_entry( hdb, "'libra_file', 'libra', 'libra.txt', 0, '', '1033', 8192, 1" );
5419     add_file_entry( hdb, "'cassiopeia_file', 'cassiopeia', 'cassiopeia.txt', 0, '', '1033', 8192, 1" );
5420     add_file_entry( hdb, "'cepheus_file', 'cepheus', 'cepheus.txt', 0, '', '1033', 8192, 1" );
5421     add_file_entry( hdb, "'andromeda_file', 'andromeda', 'andromeda.txt', 0, '', '1033', 8192, 1" );
5422     add_file_entry( hdb, "'canis_file', 'canis', 'canis.txt', 0, '', '1033', 8192, 1" );
5423     add_file_entry( hdb, "'monoceros_file', 'monoceros', 'monoceros.txt', 0, '', '1033', 8192, 1" );
5424     add_file_entry( hdb, "'lepus_file', 'lepus', 'lepus.txt', 0, '', '1033', 8192, 1" );
5425     add_file_entry( hdb, "'delphinus_file', 'delphinus', 'delphinus.txt', 0, '', '1033', 8192, 1" );
5426     add_file_entry( hdb, "'hydrus_file', 'hydrus', 'hydrus.txt', 0, '', '1033', 8192, 1" );
5427 
5428     r = package_from_db( hdb, &hpkg );
5429     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5430     {
5431         skip("Not enough rights to perform tests\n");
5432         DeleteFileA(msifile);
5433         return;
5434     }
5435     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
5436 
5437     MsiCloseHandle( hdb );
5438 
5439     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5440 
5441     r = MsiDoActionA( hpkg, "CostInitialize");
5442     ok( r == ERROR_SUCCESS, "cost init failed\n");
5443 
5444     r = MsiDoActionA( hpkg, "FileCost");
5445     ok( r == ERROR_SUCCESS, "file cost failed\n");
5446 
5447     r = MsiDoActionA( hpkg, "CostFinalize");
5448     ok( r == ERROR_SUCCESS, "cost finalize failed\n");
5449 
5450     test_feature_states( __LINE__, hpkg, "zodiac", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
5451     test_feature_states( __LINE__, hpkg, "perseus", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
5452     test_feature_states( __LINE__, hpkg, "orion", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
5453     test_feature_states( __LINE__, hpkg, "lyra", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
5454     test_feature_states( __LINE__, hpkg, "waters", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
5455     test_feature_states( __LINE__, hpkg, "bayer", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
5456 
5457     test_component_states( __LINE__, hpkg, "leo", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5458     test_component_states( __LINE__, hpkg, "virgo", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5459     test_component_states( __LINE__, hpkg, "libra", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5460     test_component_states( __LINE__, hpkg, "cassiopeia", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5461     test_component_states( __LINE__, hpkg, "cepheus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5462     test_component_states( __LINE__, hpkg, "andromeda", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5463     test_component_states( __LINE__, hpkg, "canis", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5464     test_component_states( __LINE__, hpkg, "monoceros", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5465     test_component_states( __LINE__, hpkg, "lepus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5466     test_component_states( __LINE__, hpkg, "delphinus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5467     test_component_states( __LINE__, hpkg, "hydrus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5468 
5469     r = MsiSetFeatureStateA(hpkg, "orion", INSTALLSTATE_ABSENT);
5470     ok( r == ERROR_SUCCESS, "failed to set feature state: %d\n", r);
5471 
5472     r = MsiSetFeatureStateA(hpkg, "lyra", INSTALLSTATE_ABSENT);
5473     ok( r == ERROR_SUCCESS, "failed to set feature state: %d\n", r);
5474 
5475     r = MsiSetFeatureStateA(hpkg, "nosuchfeature", INSTALLSTATE_ABSENT);
5476     ok( r == ERROR_UNKNOWN_FEATURE, "Expected ERROR_UNKNOWN_FEATURE, got %u\n", r);
5477 
5478     test_feature_states( __LINE__, hpkg, "zodiac", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
5479     test_feature_states( __LINE__, hpkg, "perseus", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
5480     test_feature_states( __LINE__, hpkg, "orion", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_ABSENT, FALSE );
5481     test_feature_states( __LINE__, hpkg, "lyra", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_ABSENT, FALSE );
5482     test_feature_states( __LINE__, hpkg, "waters", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
5483     test_feature_states( __LINE__, hpkg, "bayer", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
5484 
5485     test_component_states( __LINE__, hpkg, "leo", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5486     test_component_states( __LINE__, hpkg, "virgo", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5487     test_component_states( __LINE__, hpkg, "libra", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5488     test_component_states( __LINE__, hpkg, "cassiopeia", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5489     test_component_states( __LINE__, hpkg, "cepheus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5490     test_component_states( __LINE__, hpkg, "andromeda", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5491     test_component_states( __LINE__, hpkg, "canis", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5492     test_component_states( __LINE__, hpkg, "monoceros", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5493     test_component_states( __LINE__, hpkg, "lepus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5494     test_component_states( __LINE__, hpkg, "delphinus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5495     test_component_states( __LINE__, hpkg, "hydrus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5496 
5497     MsiCloseHandle(hpkg);
5498     DeleteFileA(msifile);
5499 }
5500 
5501 static void test_installprops(void)
5502 {
5503     MSIHANDLE hpkg, hdb;
5504     CHAR path[MAX_PATH], buf[MAX_PATH];
5505     DWORD size, type;
5506     LANGID langid;
5507     HKEY hkey1, hkey2;
5508     int res;
5509     UINT r;
5510     REGSAM access = KEY_ALL_ACCESS;
5511     SYSTEM_INFO si;
5512     INSTALLUILEVEL uilevel;
5513 
5514     if (is_wow64)
5515         access |= KEY_WOW64_64KEY;
5516 
5517     lstrcpyA(path, CURR_DIR);
5518     if (!is_root(CURR_DIR)) lstrcatA(path, "\\");
5519     lstrcatA(path, msifile);
5520 
5521     uilevel = MsiSetInternalUI(INSTALLUILEVEL_BASIC|INSTALLUILEVEL_SOURCERESONLY, NULL);
5522 
5523     hdb = create_package_db();
5524     ok( hdb, "failed to create database\n");
5525 
5526     r = package_from_db(hdb, &hpkg);
5527     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5528     {
5529         skip("Not enough rights to perform tests\n");
5530         MsiSetInternalUI(uilevel, NULL);
5531         DeleteFileA(msifile);
5532         return;
5533     }
5534     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
5535 
5536     MsiCloseHandle(hdb);
5537 
5538     buf[0] = 0;
5539     size = MAX_PATH;
5540     r = MsiGetPropertyA(hpkg, "UILevel", buf, &size);
5541     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5542     ok( !lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
5543 
5544     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5545 
5546     buf[0] = 0;
5547     size = MAX_PATH;
5548     r = MsiGetPropertyA(hpkg, "UILevel", buf, &size);
5549     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5550     ok( !lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
5551 
5552     buf[0] = 0;
5553     size = MAX_PATH;
5554     r = MsiGetPropertyA(hpkg, "DATABASE", buf, &size);
5555     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5556     ok( !lstrcmpA(buf, path), "Expected %s, got %s\n", path, buf);
5557 
5558     RegOpenKeyA(HKEY_CURRENT_USER, "SOFTWARE\\Microsoft\\MS Setup (ACME)\\User Info", &hkey1);
5559     RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, access, &hkey2);
5560 
5561     size = MAX_PATH;
5562     type = REG_SZ;
5563     *path = '\0';
5564     if (RegQueryValueExA(hkey1, "DefName", NULL, &type, (LPBYTE)path, &size) != ERROR_SUCCESS)
5565     {
5566         size = MAX_PATH;
5567         type = REG_SZ;
5568         RegQueryValueExA(hkey2, "RegisteredOwner", NULL, &type, (LPBYTE)path, &size);
5569     }
5570 
5571     buf[0] = 0;
5572     size = MAX_PATH;
5573     r = MsiGetPropertyA(hpkg, "USERNAME", buf, &size);
5574     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5575     ok( !lstrcmpA(buf, path), "Expected %s, got %s\n", path, buf);
5576 
5577     size = MAX_PATH;
5578     type = REG_SZ;
5579     *path = '\0';
5580     if (RegQueryValueExA(hkey1, "DefCompany", NULL, &type, (LPBYTE)path, &size) != ERROR_SUCCESS)
5581     {
5582         size = MAX_PATH;
5583         type = REG_SZ;
5584         RegQueryValueExA(hkey2, "RegisteredOrganization", NULL, &type, (LPBYTE)path, &size);
5585     }
5586 
5587     if (*path)
5588     {
5589         buf[0] = 0;
5590         size = MAX_PATH;
5591         r = MsiGetPropertyA(hpkg, "COMPANYNAME", buf, &size);
5592         ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5593         ok( !lstrcmpA(buf, path), "Expected %s, got %s\n", path, buf);
5594     }
5595 
5596     buf[0] = 0;
5597     size = MAX_PATH;
5598     r = MsiGetPropertyA(hpkg, "VersionDatabase", buf, &size);
5599     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5600     trace("VersionDatabase = %s\n", buf);
5601 
5602     buf[0] = 0;
5603     size = MAX_PATH;
5604     r = MsiGetPropertyA(hpkg, "VersionMsi", buf, &size);
5605     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5606     trace("VersionMsi = %s\n", buf);
5607 
5608     buf[0] = 0;
5609     size = MAX_PATH;
5610     r = MsiGetPropertyA(hpkg, "Date", buf, &size);
5611     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5612     trace("Date = %s\n", buf);
5613 
5614     buf[0] = 0;
5615     size = MAX_PATH;
5616     r = MsiGetPropertyA(hpkg, "Time", buf, &size);
5617     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5618     trace("Time = %s\n", buf);
5619 
5620     buf[0] = 0;
5621     size = MAX_PATH;
5622     r = MsiGetPropertyA(hpkg, "PackageCode", buf, &size);
5623     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5624     trace("PackageCode = %s\n", buf);
5625 
5626     buf[0] = 0;
5627     size = MAX_PATH;
5628     r = MsiGetPropertyA(hpkg, "ComputerName", buf, &size);
5629     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
5630     trace("ComputerName = %s\n", buf);
5631 
5632     langid = GetUserDefaultLangID();
5633     sprintf(path, "%d", langid);
5634 
5635     buf[0] = 0;
5636     size = MAX_PATH;
5637     r = MsiGetPropertyA(hpkg, "UserLanguageID", buf, &size);
5638     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
5639     ok( !lstrcmpA(buf, path), "Expected \"%s\", got \"%s\"\n", path, buf);
5640 
5641     res = GetSystemMetrics(SM_CXSCREEN);
5642     buf[0] = 0;
5643     size = MAX_PATH;
5644     r = MsiGetPropertyA(hpkg, "ScreenX", buf, &size);
5645     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
5646     ok(atol(buf) == res, "Expected %d, got %ld\n", res, atol(buf));
5647 
5648     res = GetSystemMetrics(SM_CYSCREEN);
5649     buf[0] = 0;
5650     size = MAX_PATH;
5651     r = MsiGetPropertyA(hpkg, "ScreenY", buf, &size);
5652     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
5653     ok(atol(buf) == res, "Expected %d, got %ld\n", res, atol(buf));
5654 
5655     buf[0] = 0;
5656     size = MAX_PATH;
5657     r = MsiGetPropertyA(hpkg, "MsiNetAssemblySupport", buf, &size);
5658     if (r == ERROR_SUCCESS) trace( "MsiNetAssemblySupport \"%s\"\n", buf );
5659 
5660     if (pGetSystemInfo && pSHGetFolderPathA)
5661     {
5662         pGetSystemInfo(&si);
5663         if (S(U(si)).wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
5664         {
5665             buf[0] = 0;
5666             size = MAX_PATH;
5667             r = MsiGetPropertyA(hpkg, "Intel", buf, &size);
5668             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5669             ok(buf[0], "property not set\n");
5670 
5671             buf[0] = 0;
5672             size = MAX_PATH;
5673             r = MsiGetPropertyA(hpkg, "MsiAMD64", buf, &size);
5674             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5675             ok(buf[0], "property not set\n");
5676 
5677             buf[0] = 0;
5678             size = MAX_PATH;
5679             r = MsiGetPropertyA(hpkg, "Msix64", buf, &size);
5680             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5681             ok(buf[0], "property not set\n");
5682 
5683             buf[0] = 0;
5684             size = MAX_PATH;
5685             r = MsiGetPropertyA(hpkg, "System64Folder", buf, &size);
5686             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5687             GetSystemDirectoryA(path, MAX_PATH);
5688             if (size) buf[size - 1] = 0;
5689             ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5690 
5691             buf[0] = 0;
5692             size = MAX_PATH;
5693             r = MsiGetPropertyA(hpkg, "SystemFolder", buf, &size);
5694             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5695             pGetSystemWow64DirectoryA(path, MAX_PATH);
5696             if (size) buf[size - 1] = 0;
5697             ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5698 
5699             buf[0] = 0;
5700             size = MAX_PATH;
5701             r = MsiGetPropertyA(hpkg, "ProgramFiles64Folder", buf, &size);
5702             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5703             pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES, NULL, 0, path);
5704             if (size) buf[size - 1] = 0;
5705             ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5706 
5707             buf[0] = 0;
5708             size = MAX_PATH;
5709             r = MsiGetPropertyA(hpkg, "ProgramFilesFolder", buf, &size);
5710             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5711             pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILESX86, NULL, 0, path);
5712             if (size) buf[size - 1] = 0;
5713             ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5714 
5715             buf[0] = 0;
5716             size = MAX_PATH;
5717             r = MsiGetPropertyA(hpkg, "CommonFiles64Folder", buf, &size);
5718             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5719             pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES_COMMON, NULL, 0, path);
5720             if (size) buf[size - 1] = 0;
5721             ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5722 
5723             buf[0] = 0;
5724             size = MAX_PATH;
5725             r = MsiGetPropertyA(hpkg, "CommonFilesFolder", buf, &size);
5726             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5727             pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES_COMMONX86, NULL, 0, path);
5728             if (size) buf[size - 1] = 0;
5729             ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5730 
5731             buf[0] = 0;
5732             size = MAX_PATH;
5733             r = MsiGetPropertyA(hpkg, "VersionNT64", buf, &size);
5734             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5735             ok(buf[0], "property not set\n");
5736         }
5737         else if (S(U(si)).wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
5738         {
5739             if (!is_wow64)
5740             {
5741                 buf[0] = 0;
5742                 size = MAX_PATH;
5743                 r = MsiGetPropertyA(hpkg, "Intel", buf, &size);
5744                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5745                 ok(buf[0], "property not set\n");
5746 
5747                 buf[0] = 0;
5748                 size = MAX_PATH;
5749                 r = MsiGetPropertyA(hpkg, "MsiAMD64", buf, &size);
5750                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5751                 ok(!buf[0], "property set\n");
5752 
5753                 buf[0] = 0;
5754                 size = MAX_PATH;
5755                 r = MsiGetPropertyA(hpkg, "Msix64", buf, &size);
5756                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5757                 ok(!buf[0], "property set\n");
5758 
5759                 buf[0] = 0;
5760                 size = MAX_PATH;
5761                 r = MsiGetPropertyA(hpkg, "System64Folder", buf, &size);
5762                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5763                 ok(!buf[0], "property set\n");
5764 
5765                 buf[0] = 0;
5766                 size = MAX_PATH;
5767                 r = MsiGetPropertyA(hpkg, "SystemFolder", buf, &size);
5768                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5769                 GetSystemDirectoryA(path, MAX_PATH);
5770                 if (size) buf[size - 1] = 0;
5771                 ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5772 
5773                 buf[0] = 0;
5774                 size = MAX_PATH;
5775                 r = MsiGetPropertyA(hpkg, "ProgramFiles64Folder", buf, &size);
5776                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5777                 ok(!buf[0], "property set\n");
5778 
5779                 buf[0] = 0;
5780                 size = MAX_PATH;
5781                 r = MsiGetPropertyA(hpkg, "ProgramFilesFolder", buf, &size);
5782                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5783                 pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES, NULL, 0, path);
5784                 if (size) buf[size - 1] = 0;
5785                 ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5786 
5787                 buf[0] = 0;
5788                 size = MAX_PATH;
5789                 r = MsiGetPropertyA(hpkg, "CommonFiles64Folder", buf, &size);
5790                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5791                 ok(!buf[0], "property set\n");
5792 
5793                 buf[0] = 0;
5794                 size = MAX_PATH;
5795                 r = MsiGetPropertyA(hpkg, "CommonFilesFolder", buf, &size);
5796                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5797                 pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES_COMMON, NULL, 0, path);
5798                 if (size) buf[size - 1] = 0;
5799                 ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5800 
5801                 buf[0] = 0;
5802                 size = MAX_PATH;
5803                 r = MsiGetPropertyA(hpkg, "VersionNT64", buf, &size);
5804                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5805                 ok(!buf[0], "property set\n");
5806             }
5807             else
5808             {
5809                 buf[0] = 0;
5810                 size = MAX_PATH;
5811                 r = MsiGetPropertyA(hpkg, "Intel", buf, &size);
5812                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5813                 ok(buf[0], "property not set\n");
5814 
5815                 buf[0] = 0;
5816                 size = MAX_PATH;
5817                 r = MsiGetPropertyA(hpkg, "MsiAMD64", buf, &size);
5818                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5819                 ok(buf[0], "property not set\n");
5820 
5821                 buf[0] = 0;
5822                 size = MAX_PATH;
5823                 r = MsiGetPropertyA(hpkg, "Msix64", buf, &size);
5824                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5825                 ok(buf[0], "property not set\n");
5826 
5827                 buf[0] = 0;
5828                 size = MAX_PATH;
5829                 r = MsiGetPropertyA(hpkg, "System64Folder", buf, &size);
5830                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5831                 GetSystemDirectoryA(path, MAX_PATH);
5832                 if (size) buf[size - 1] = 0;
5833                 ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5834 
5835                 buf[0] = 0;
5836                 size = MAX_PATH;
5837                 r = MsiGetPropertyA(hpkg, "SystemFolder", buf, &size);
5838                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5839                 pGetSystemWow64DirectoryA(path, MAX_PATH);
5840                 if (size) buf[size - 1] = 0;
5841                 ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5842 
5843                 buf[0] = 0;
5844                 size = MAX_PATH;
5845                 r = MsiGetPropertyA(hpkg, "ProgramFilesFolder64", buf, &size);
5846                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5847                 ok(!buf[0], "property set\n");
5848 
5849                 buf[0] = 0;
5850                 size = MAX_PATH;
5851                 r = MsiGetPropertyA(hpkg, "ProgramFilesFolder", buf, &size);
5852                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5853                 pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILESX86, NULL, 0, path);
5854                 if (size) buf[size - 1] = 0;
5855                 ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5856 
5857                 buf[0] = 0;
5858                 size = MAX_PATH;
5859                 r = MsiGetPropertyA(hpkg, "CommonFilesFolder64", buf, &size);
5860                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5861                 ok(!buf[0], "property set\n");
5862 
5863                 buf[0] = 0;
5864                 size = MAX_PATH;
5865                 r = MsiGetPropertyA(hpkg, "CommonFilesFolder", buf, &size);
5866                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5867                 pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES_COMMONX86, NULL, 0, path);
5868                 if (size) buf[size - 1] = 0;
5869                 ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5870 
5871                 buf[0] = 0;
5872                 size = MAX_PATH;
5873                 r = MsiGetPropertyA(hpkg, "VersionNT64", buf, &size);
5874                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5875                 ok(buf[0], "property not set\n");
5876             }
5877         }
5878     }
5879 
5880     CloseHandle(hkey1);
5881     CloseHandle(hkey2);
5882     MsiCloseHandle(hpkg);
5883     DeleteFileA(msifile);
5884     MsiSetInternalUI(uilevel, NULL);
5885 }
5886 
5887 static void test_launchconditions(void)
5888 {
5889     MSIHANDLE hpkg;
5890     MSIHANDLE hdb;
5891     UINT r;
5892 
5893     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5894 
5895     hdb = create_package_db();
5896     ok( hdb, "failed to create package database\n" );
5897 
5898     create_launchcondition_table( hdb );
5899 
5900     add_launchcondition_entry( hdb, "'X = \"1\"', 'one'" );
5901 
5902     /* invalid condition */
5903     add_launchcondition_entry( hdb, "'X != \"1\"', 'one'" );
5904 
5905     r = package_from_db( hdb, &hpkg );
5906     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5907     {
5908         skip("Not enough rights to perform tests\n");
5909         DeleteFileA(msifile);
5910         return;
5911     }
5912     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
5913 
5914     MsiCloseHandle( hdb );
5915 
5916     r = MsiSetPropertyA( hpkg, "X", "1" );
5917     ok( r == ERROR_SUCCESS, "failed to set property\n" );
5918 
5919     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5920 
5921     /* invalid conditions are ignored */
5922     r = MsiDoActionA( hpkg, "LaunchConditions" );
5923     ok( r == ERROR_SUCCESS, "cost init failed\n" );
5924 
5925     /* verify LaunchConditions still does some verification */
5926     r = MsiSetPropertyA( hpkg, "X", "2" );
5927     ok( r == ERROR_SUCCESS, "failed to set property\n" );
5928 
5929     r = MsiDoActionA( hpkg, "LaunchConditions" );
5930     ok( r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %d\n", r );
5931 
5932     MsiCloseHandle( hpkg );
5933     DeleteFileA( msifile );
5934 }
5935 
5936 static void test_ccpsearch(void)
5937 {
5938     MSIHANDLE hdb, hpkg;
5939     CHAR prop[MAX_PATH];
5940     DWORD size = MAX_PATH;
5941     UINT r;
5942 
5943     hdb = create_package_db();
5944     ok(hdb, "failed to create package database\n");
5945 
5946     create_ccpsearch_table(hdb);
5947     add_ccpsearch_entry(hdb, "'CCP_random'");
5948     add_ccpsearch_entry(hdb, "'RMCCP_random'");
5949 
5950     create_reglocator_table(hdb);
5951     add_reglocator_entry(hdb, "CCP_random", 0, "htmlfile\\shell\\open\\nonexistent", "", 1);
5952 
5953     create_drlocator_table(hdb);
5954     add_drlocator_entry(hdb, "'RMCCP_random', '', 'C:\\', '0'");
5955 
5956     create_signature_table(hdb);
5957 
5958     r = package_from_db(hdb, &hpkg);
5959     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5960     {
5961         skip("Not enough rights to perform tests\n");
5962         DeleteFileA(msifile);
5963         return;
5964     }
5965     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
5966 
5967     MsiCloseHandle(hdb);
5968 
5969     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5970 
5971     r = MsiDoActionA(hpkg, "CCPSearch");
5972     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5973 
5974     r = MsiGetPropertyA(hpkg, "CCP_Success", prop, &size);
5975     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5976     ok(!lstrcmpA(prop, "1"), "Expected 1, got %s\n", prop);
5977 
5978     MsiCloseHandle(hpkg);
5979     DeleteFileA(msifile);
5980 }
5981 
5982 static void test_complocator(void)
5983 {
5984     MSIHANDLE hdb, hpkg;
5985     UINT r;
5986     CHAR prop[MAX_PATH];
5987     CHAR expected[MAX_PATH];
5988     DWORD size = MAX_PATH;
5989 
5990     hdb = create_package_db();
5991     ok(hdb, "failed to create package database\n");
5992 
5993     create_appsearch_table(hdb);
5994     add_appsearch_entry(hdb, "'ABELISAURUS', 'abelisaurus'");
5995     add_appsearch_entry(hdb, "'BACTROSAURUS', 'bactrosaurus'");
5996     add_appsearch_entry(hdb, "'CAMELOTIA', 'camelotia'");
5997     add_appsearch_entry(hdb, "'DICLONIUS', 'diclonius'");
5998     add_appsearch_entry(hdb, "'ECHINODON', 'echinodon'");
5999     add_appsearch_entry(hdb, "'FALCARIUS', 'falcarius'");
6000     add_appsearch_entry(hdb, "'GALLIMIMUS', 'gallimimus'");
6001     add_appsearch_entry(hdb, "'HAGRYPHUS', 'hagryphus'");
6002     add_appsearch_entry(hdb, "'IGUANODON', 'iguanodon'");
6003     add_appsearch_entry(hdb, "'JOBARIA', 'jobaria'");
6004     add_appsearch_entry(hdb, "'KAKURU', 'kakuru'");
6005     add_appsearch_entry(hdb, "'LABOCANIA', 'labocania'");
6006     add_appsearch_entry(hdb, "'MEGARAPTOR', 'megaraptor'");
6007     add_appsearch_entry(hdb, "'NEOSODON', 'neosodon'");
6008     add_appsearch_entry(hdb, "'OLOROTITAN', 'olorotitan'");
6009     add_appsearch_entry(hdb, "'PANTYDRACO', 'pantydraco'");
6010 
6011     create_complocator_table(hdb);
6012     add_complocator_entry(hdb, "'abelisaurus', '{E3619EED-305A-418C-B9C7-F7D7377F0934}', 1");
6013     add_complocator_entry(hdb, "'bactrosaurus', '{D56B688D-542F-42Ef-90FD-B6DA76EE8119}', 0");
6014     add_complocator_entry(hdb, "'camelotia', '{8211BE36-2466-47E3-AFB7-6AC72E51AED2}', 1");
6015     add_complocator_entry(hdb, "'diclonius', '{5C767B20-A33C-45A4-B80B-555E512F01AE}', 0");
6016     add_complocator_entry(hdb, "'echinodon', '{A19E16C5-C75D-4699-8111-C4338C40C3CB}', 1");
6017     add_complocator_entry(hdb, "'falcarius', '{17762FA1-A7AE-4CC6-8827-62873C35361D}', 0");
6018     add_complocator_entry(hdb, "'gallimimus', '{75EBF568-C959-41E0-A99E-9050638CF5FB}', 1");
6019     add_complocator_entry(hdb, "'hagrphus', '{D4969B72-17D9-4AB6-BE49-78F2FEE857AC}', 0");
6020     add_complocator_entry(hdb, "'iguanodon', '{8E0DA02E-F6A7-4A8F-B25D-6F564C492308}', 1");
6021     add_complocator_entry(hdb, "'jobaria', '{243C22B1-8C51-4151-B9D1-1AE5265E079E}', 0");
6022     add_complocator_entry(hdb, "'kakuru', '{5D0F03BA-50BC-44F2-ABB1-72C972F4E514}', 1");
6023     add_complocator_entry(hdb, "'labocania', '{C7DDB60C-7828-4046-A6F8-699D5E92F1ED}', 0");
6024     add_complocator_entry(hdb, "'megaraptor', '{8B1034B7-BD5E-41ac-B52C-0105D3DFD74D}', 1");
6025     add_complocator_entry(hdb, "'neosodon', '{0B499649-197A-48EF-93D2-AF1C17ED6E90}', 0");
6026     add_complocator_entry(hdb, "'olorotitan', '{54E9E91F-AED2-46D5-A25A-7E50AFA24513}', 1");
6027     add_complocator_entry(hdb, "'pantydraco', '{2A989951-5565-4FA7-93A7-E800A3E67D71}', 0");
6028 
6029     create_signature_table(hdb);
6030     add_signature_entry(hdb, "'abelisaurus', 'abelisaurus', '', '', '', '', '', '', ''");
6031     add_signature_entry(hdb, "'bactrosaurus', 'bactrosaurus', '', '', '', '', '', '', ''");
6032     add_signature_entry(hdb, "'camelotia', 'camelotia', '', '', '', '', '', '', ''");
6033     add_signature_entry(hdb, "'diclonius', 'diclonius', '', '', '', '', '', '', ''");
6034     add_signature_entry(hdb, "'iguanodon', 'iguanodon', '', '', '', '', '', '', ''");
6035     add_signature_entry(hdb, "'jobaria', 'jobaria', '', '', '', '', '', '', ''");
6036     add_signature_entry(hdb, "'kakuru', 'kakuru', '', '', '', '', '', '', ''");
6037     add_signature_entry(hdb, "'labocania', 'labocania', '', '', '', '', '', '', ''");
6038 
6039     r = package_from_db(hdb, &hpkg);
6040     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
6041     {
6042         skip("Not enough rights to perform tests\n");
6043         DeleteFileA(msifile);
6044         return;
6045     }
6046     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
6047 
6048     MsiCloseHandle(hdb);
6049 
6050     create_test_file("abelisaurus");
6051     create_test_file("bactrosaurus");
6052     create_test_file("camelotia");
6053     create_test_file("diclonius");
6054     create_test_file("echinodon");
6055     create_test_file("falcarius");
6056     create_test_file("gallimimus");
6057     create_test_file("hagryphus");
6058     CreateDirectoryA("iguanodon", NULL);
6059     CreateDirectoryA("jobaria", NULL);
6060     CreateDirectoryA("kakuru", NULL);
6061     CreateDirectoryA("labocania", NULL);
6062     CreateDirectoryA("megaraptor", NULL);
6063     CreateDirectoryA("neosodon", NULL);
6064     CreateDirectoryA("olorotitan", NULL);
6065     CreateDirectoryA("pantydraco", NULL);
6066 
6067     set_component_path("abelisaurus", MSIINSTALLCONTEXT_MACHINE,
6068                        "{E3619EED-305A-418C-B9C7-F7D7377F0934}", NULL, FALSE);
6069     set_component_path("bactrosaurus", MSIINSTALLCONTEXT_MACHINE,
6070                        "{D56B688D-542F-42Ef-90FD-B6DA76EE8119}", NULL, FALSE);
6071     set_component_path("echinodon", MSIINSTALLCONTEXT_MACHINE,
6072                        "{A19E16C5-C75D-4699-8111-C4338C40C3CB}", NULL, FALSE);
6073     set_component_path("falcarius", MSIINSTALLCONTEXT_MACHINE,
6074                        "{17762FA1-A7AE-4CC6-8827-62873C35361D}", NULL, FALSE);
6075     set_component_path("iguanodon", MSIINSTALLCONTEXT_MACHINE,
6076                        "{8E0DA02E-F6A7-4A8F-B25D-6F564C492308}", NULL, FALSE);
6077     set_component_path("jobaria", MSIINSTALLCONTEXT_MACHINE,
6078                        "{243C22B1-8C51-4151-B9D1-1AE5265E079E}", NULL, FALSE);
6079     set_component_path("megaraptor", MSIINSTALLCONTEXT_MACHINE,
6080                        "{8B1034B7-BD5E-41ac-B52C-0105D3DFD74D}", NULL, FALSE);
6081     set_component_path("neosodon", MSIINSTALLCONTEXT_MACHINE,
6082                        "{0B499649-197A-48EF-93D2-AF1C17ED6E90}", NULL, FALSE);
6083 
6084     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
6085 
6086     r = MsiDoActionA(hpkg, "AppSearch");
6087     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6088 
6089     size = MAX_PATH;
6090     r = MsiGetPropertyA(hpkg, "ABELISAURUS", prop, &size);
6091     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6092 
6093     lstrcpyA(expected, CURR_DIR);
6094     if (!is_root(CURR_DIR)) lstrcatA(expected, "\\");
6095     lstrcatA(expected, "abelisaurus");
6096     ok(!lstrcmpA(prop, expected) || !lstrcmpA(prop, ""),
6097        "Expected %s or empty string, got %s\n", expected, prop);
6098 
6099     size = MAX_PATH;
6100     r = MsiGetPropertyA(hpkg, "BACTROSAURUS", prop, &size);
6101     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6102     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6103 
6104     size = MAX_PATH;
6105     r = MsiGetPropertyA(hpkg, "CAMELOTIA", prop, &size);
6106     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6107     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6108 
6109     size = MAX_PATH;
6110     r = MsiGetPropertyA(hpkg, "DICLONIUS", prop, &size);
6111     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6112     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6113 
6114     size = MAX_PATH;
6115     r = MsiGetPropertyA(hpkg, "ECHINODON", prop, &size);
6116     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6117 
6118     lstrcpyA(expected, CURR_DIR);
6119     if (!is_root(CURR_DIR)) lstrcatA(expected, "\\");
6120     ok(!lstrcmpA(prop, expected) || !lstrcmpA(prop, ""),
6121        "Expected %s or empty string, got %s\n", expected, prop);
6122 
6123     size = MAX_PATH;
6124     r = MsiGetPropertyA(hpkg, "FALCARIUS", prop, &size);
6125     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6126     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6127 
6128     size = MAX_PATH;
6129     r = MsiGetPropertyA(hpkg, "GALLIMIMUS", prop, &size);
6130     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6131     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6132 
6133     size = MAX_PATH;
6134     r = MsiGetPropertyA(hpkg, "HAGRYPHUS", prop, &size);
6135     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6136     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6137 
6138     size = MAX_PATH;
6139     r = MsiGetPropertyA(hpkg, "IGUANODON", prop, &size);
6140     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6141     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6142 
6143     size = MAX_PATH;
6144     r = MsiGetPropertyA(hpkg, "JOBARIA", prop, &size);
6145     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6146     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6147 
6148     size = MAX_PATH;
6149     r = MsiGetPropertyA(hpkg, "KAKURU", prop, &size);
6150     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6151     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6152 
6153     size = MAX_PATH;
6154     r = MsiGetPropertyA(hpkg, "LABOCANIA", prop, &size);
6155     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6156     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6157 
6158     size = MAX_PATH;
6159     r = MsiGetPropertyA(hpkg, "MEGARAPTOR", prop, &size);
6160     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6161 
6162     lstrcpyA(expected, CURR_DIR);
6163     if (!is_root(CURR_DIR)) lstrcatA(expected, "\\");
6164     ok(!lstrcmpA(prop, expected) || !lstrcmpA(prop, ""),
6165        "Expected %s or empty string, got %s\n", expected, prop);
6166 
6167     size = MAX_PATH;
6168     r = MsiGetPropertyA(hpkg, "NEOSODON", prop, &size);
6169     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6170 
6171     lstrcpyA(expected, CURR_DIR);
6172     if (!is_root(CURR_DIR)) lstrcatA(expected, "\\");
6173     lstrcatA(expected, "neosodon\\");
6174     ok(!lstrcmpA(prop, expected) || !lstrcmpA(prop, ""),
6175        "Expected %s or empty string, got %s\n", expected, prop);
6176 
6177     size = MAX_PATH;
6178     r = MsiGetPropertyA(hpkg, "OLOROTITAN", prop, &size);
6179     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6180     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6181 
6182     size = MAX_PATH;
6183     r = MsiGetPropertyA(hpkg, "PANTYDRACO", prop, &size);
6184     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6185     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6186 
6187     MsiCloseHandle(hpkg);
6188     DeleteFileA("abelisaurus");
6189     DeleteFileA("bactrosaurus");
6190     DeleteFileA("camelotia");
6191     DeleteFileA("diclonius");
6192     DeleteFileA("echinodon");
6193     DeleteFileA("falcarius");
6194     DeleteFileA("gallimimus");
6195     DeleteFileA("hagryphus");
6196     RemoveDirectoryA("iguanodon");
6197     RemoveDirectoryA("jobaria");
6198     RemoveDirectoryA("kakuru");
6199     RemoveDirectoryA("labocania");
6200     RemoveDirectoryA("megaraptor");
6201     RemoveDirectoryA("neosodon");
6202     RemoveDirectoryA("olorotitan");
6203     RemoveDirectoryA("pantydraco");
6204     delete_component_path("{E3619EED-305A-418C-B9C7-F7D7377F0934}",
6205                           MSIINSTALLCONTEXT_MACHINE, NULL);
6206     delete_component_path("{D56B688D-542F-42Ef-90FD-B6DA76EE8119}",
6207                           MSIINSTALLCONTEXT_MACHINE, NULL);
6208     delete_component_path("{A19E16C5-C75D-4699-8111-C4338C40C3CB}",
6209                           MSIINSTALLCONTEXT_MACHINE, NULL);
6210     delete_component_path("{17762FA1-A7AE-4CC6-8827-62873C35361D}",
6211                           MSIINSTALLCONTEXT_MACHINE, NULL);
6212     delete_component_path("{8E0DA02E-F6A7-4A8F-B25D-6F564C492308}",
6213                           MSIINSTALLCONTEXT_MACHINE, NULL);
6214     delete_component_path("{243C22B1-8C51-4151-B9D1-1AE5265E079E}",
6215                           MSIINSTALLCONTEXT_MACHINE, NULL);
6216     delete_component_path("{8B1034B7-BD5E-41ac-B52C-0105D3DFD74D}",
6217                           MSIINSTALLCONTEXT_MACHINE, NULL);
6218     delete_component_path("{0B499649-197A-48EF-93D2-AF1C17ED6E90}",
6219                           MSIINSTALLCONTEXT_MACHINE, NULL);
6220     DeleteFileA(msifile);
6221 }
6222 
6223 static void set_suminfo_prop(MSIHANDLE db, DWORD prop, DWORD val)
6224 {
6225     MSIHANDLE summary;
6226     UINT r;
6227 
6228     r = MsiGetSummaryInformationA(db, NULL, 1, &summary);
6229     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6230 
6231     r = MsiSummaryInfoSetPropertyA(summary, prop, VT_I4, val, NULL, NULL);
6232     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6233 
6234     r = MsiSummaryInfoPersist(summary);
6235     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
6236 
6237     MsiCloseHandle(summary);
6238 }
6239 
6240 static void test_MsiGetSourcePath(void)
6241 {
6242     MSIHANDLE hdb, hpkg;
6243     CHAR path[MAX_PATH];
6244     CHAR cwd[MAX_PATH];
6245     CHAR subsrc[MAX_PATH];
6246     CHAR sub2[MAX_PATH];
6247     DWORD size;
6248     UINT r;
6249 
6250     lstrcpyA(cwd, CURR_DIR);
6251     if (!is_root(CURR_DIR)) lstrcatA(cwd, "\\");
6252 
6253     lstrcpyA(subsrc, cwd);
6254     lstrcatA(subsrc, "subsource");
6255     lstrcatA(subsrc, "\\");
6256 
6257     lstrcpyA(sub2, subsrc);
6258     lstrcatA(sub2, "sub2");
6259     lstrcatA(sub2, "\\");
6260 
6261     /* uncompressed source */
6262 
6263     hdb = create_package_db();
6264     ok( hdb, "failed to create database\n");
6265 
6266     set_suminfo_prop(hdb, PID_WORDCOUNT, 0);
6267 
6268     add_directory_entry(hdb, "'TARGETDIR', '', 'SourceDir'");
6269     add_directory_entry(hdb, "'SubDir', 'TARGETDIR', 'subtarget:subsource'");
6270     add_directory_entry(hdb, "'SubDir2', 'SubDir', 'sub2'");
6271 
6272     r = MsiDatabaseCommit(hdb);
6273     ok(r == ERROR_SUCCESS , "Failed to commit database\n");
6274 
6275     r = package_from_db(hdb, &hpkg);
6276     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
6277     {
6278         skip("Not enough rights to perform tests\n");
6279         DeleteFileA(msifile);
6280         return;
6281     }
6282     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
6283 
6284     MsiCloseHandle(hdb);
6285 
6286     /* invalid database handle */
6287     size = MAX_PATH;
6288     lstrcpyA(path, "kiwi");
6289     r = MsiGetSourcePathA(-1, "TARGETDIR", path, &size);
6290     ok(r == ERROR_INVALID_HANDLE,
6291        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
6292     ok(!lstrcmpA(path, "kiwi"),
6293        "Expected path to be unchanged, got \"%s\"\n", path);
6294     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6295 
6296     /* NULL szFolder */
6297     size = MAX_PATH;
6298     lstrcpyA(path, "kiwi");
6299     r = MsiGetSourcePathA(hpkg, NULL, path, &size);
6300     ok(r == ERROR_INVALID_PARAMETER,
6301        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6302     ok(!lstrcmpA(path, "kiwi"),
6303        "Expected path to be unchanged, got \"%s\"\n", path);
6304     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6305 
6306     /* empty szFolder */
6307     size = MAX_PATH;
6308     lstrcpyA(path, "kiwi");
6309     r = MsiGetSourcePathA(hpkg, "", path, &size);
6310     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6311     ok(!lstrcmpA(path, "kiwi"),
6312        "Expected path to be unchanged, got \"%s\"\n", path);
6313     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6314 
6315     /* try TARGETDIR */
6316     size = MAX_PATH;
6317     lstrcpyA(path, "kiwi");
6318     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6319     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6320     ok(!lstrcmpA(path, "kiwi"),
6321        "Expected path to be unchanged, got \"%s\"\n", path);
6322     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6323 
6324     size = MAX_PATH;
6325     lstrcpyA(path, "kiwi");
6326     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6327     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6328     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6329     ok(size == 0, "Expected 0, got %d\n", size);
6330 
6331     size = MAX_PATH;
6332     lstrcpyA(path, "kiwi");
6333     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6334     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6335     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6336     ok(size == 0, "Expected 0, got %d\n", size);
6337 
6338     /* try SourceDir */
6339     size = MAX_PATH;
6340     lstrcpyA(path, "kiwi");
6341     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6342     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6343     ok(!lstrcmpA(path, "kiwi"),
6344        "Expected path to be unchanged, got \"%s\"\n", path);
6345     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6346 
6347     /* try SOURCEDIR */
6348     size = MAX_PATH;
6349     lstrcpyA(path, "kiwi");
6350     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6351     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6352     ok(!lstrcmpA(path, "kiwi"),
6353        "Expected path to be unchanged, got \"%s\"\n", path);
6354     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6355 
6356     /* source path does not exist, but the property exists */
6357     size = MAX_PATH;
6358     lstrcpyA(path, "kiwi");
6359     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6360     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6361     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6362     ok(size == 0, "Expected 0, got %d\n", size);
6363 
6364     size = MAX_PATH;
6365     lstrcpyA(path, "kiwi");
6366     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6367     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6368     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6369     ok(size == 0, "Expected 0, got %d\n", size);
6370 
6371     /* try SubDir */
6372     size = MAX_PATH;
6373     lstrcpyA(path, "kiwi");
6374     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6375     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6376     ok(!lstrcmpA(path, "kiwi"),
6377        "Expected path to be unchanged, got \"%s\"\n", path);
6378     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6379 
6380     /* try SubDir2 */
6381     size = MAX_PATH;
6382     lstrcpyA(path, "kiwi");
6383     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6384     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6385     ok(!lstrcmpA(path, "kiwi"),
6386        "Expected path to be unchanged, got \"%s\"\n", path);
6387     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6388 
6389     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
6390 
6391     r = MsiDoActionA(hpkg, "CostInitialize");
6392     ok(r == ERROR_SUCCESS, "cost init failed\n");
6393 
6394     /* try TARGETDIR after CostInitialize */
6395     size = MAX_PATH;
6396     lstrcpyA(path, "kiwi");
6397     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6398     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6399     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6400     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6401 
6402     /* try SourceDir after CostInitialize */
6403     size = MAX_PATH;
6404     lstrcpyA(path, "kiwi");
6405     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6406     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6407     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6408     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6409 
6410     /* try SOURCEDIR after CostInitialize */
6411     size = MAX_PATH;
6412     lstrcpyA(path, "kiwi");
6413     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6414     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6415     ok(!lstrcmpA(path, "kiwi"),
6416        "Expected path to be unchanged, got \"%s\"\n", path);
6417     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6418 
6419     /* source path does not exist, but the property exists */
6420     size = MAX_PATH;
6421     lstrcpyA(path, "kiwi");
6422     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6423     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6424     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6425     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6426 
6427     size = MAX_PATH;
6428     lstrcpyA(path, "kiwi");
6429     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6430     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6431     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6432     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6433 
6434     /* try SubDir after CostInitialize */
6435     size = MAX_PATH;
6436     lstrcpyA(path, "kiwi");
6437     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6438     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6439     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6440     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
6441 
6442     /* try SubDir2 after CostInitialize */
6443     size = MAX_PATH;
6444     lstrcpyA(path, "kiwi");
6445     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6446     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6447     ok(!lstrcmpA(path, sub2), "Expected \"%s\", got \"%s\"\n", sub2, path);
6448     ok(size == lstrlenA(sub2), "Expected %d, got %d\n", lstrlenA(sub2), size);
6449 
6450     r = MsiDoActionA(hpkg, "ResolveSource");
6451     ok(r == ERROR_SUCCESS, "file cost failed\n");
6452 
6453     /* try TARGETDIR after ResolveSource */
6454     size = MAX_PATH;
6455     lstrcpyA(path, "kiwi");
6456     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6457     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6458     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6459     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6460 
6461     /* try SourceDir after ResolveSource */
6462     size = MAX_PATH;
6463     lstrcpyA(path, "kiwi");
6464     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6465     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6466     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6467     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6468 
6469     /* try SOURCEDIR after ResolveSource */
6470     size = MAX_PATH;
6471     lstrcpyA(path, "kiwi");
6472     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6473     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6474     ok(!lstrcmpA(path, "kiwi"),
6475        "Expected path to be unchanged, got \"%s\"\n", path);
6476     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6477 
6478     /* source path does not exist, but the property exists */
6479     size = MAX_PATH;
6480     lstrcpyA(path, "kiwi");
6481     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6482     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6483     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6484     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6485 
6486     size = MAX_PATH;
6487     lstrcpyA(path, "kiwi");
6488     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6489     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6490     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6491     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6492 
6493     /* try SubDir after ResolveSource */
6494     size = MAX_PATH;
6495     lstrcpyA(path, "kiwi");
6496     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6497     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6498     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6499     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
6500 
6501     /* try SubDir2 after ResolveSource */
6502     size = MAX_PATH;
6503     lstrcpyA(path, "kiwi");
6504     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6505     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6506     ok(!lstrcmpA(path, sub2), "Expected \"%s\", got \"%s\"\n", sub2, path);
6507     ok(size == lstrlenA(sub2), "Expected %d, got %d\n", lstrlenA(sub2), size);
6508 
6509     r = MsiDoActionA(hpkg, "FileCost");
6510     ok(r == ERROR_SUCCESS, "file cost failed\n");
6511 
6512     /* try TARGETDIR after FileCost */
6513     size = MAX_PATH;
6514     lstrcpyA(path, "kiwi");
6515     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6516     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6517     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6518     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6519 
6520     /* try SourceDir after FileCost */
6521     size = MAX_PATH;
6522     lstrcpyA(path, "kiwi");
6523     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6524     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6525     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6526     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6527 
6528     /* try SOURCEDIR after FileCost */
6529     size = MAX_PATH;
6530     lstrcpyA(path, "kiwi");
6531     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6532     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6533     ok(!lstrcmpA(path, "kiwi"),
6534        "Expected path to be unchanged, got \"%s\"\n", path);
6535     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6536 
6537     /* source path does not exist, but the property exists */
6538     size = MAX_PATH;
6539     lstrcpyA(path, "kiwi");
6540     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6541     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6542     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6543     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6544 
6545     size = MAX_PATH;
6546     lstrcpyA(path, "kiwi");
6547     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6548     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6549     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6550     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6551 
6552     /* try SubDir after FileCost */
6553     size = MAX_PATH;
6554     lstrcpyA(path, "kiwi");
6555     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6556     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6557     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6558     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
6559 
6560     /* try SubDir2 after FileCost */
6561     size = MAX_PATH;
6562     lstrcpyA(path, "kiwi");
6563     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6564     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6565     ok(!lstrcmpA(path, sub2), "Expected \"%s\", got \"%s\"\n", sub2, path);
6566     ok(size == lstrlenA(sub2), "Expected %d, got %d\n", lstrlenA(sub2), size);
6567 
6568     r = MsiDoActionA(hpkg, "CostFinalize");
6569     ok(r == ERROR_SUCCESS, "file cost failed\n");
6570 
6571     /* try TARGETDIR after CostFinalize */
6572     size = MAX_PATH;
6573     lstrcpyA(path, "kiwi");
6574     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6575     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6576     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6577     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6578 
6579     /* try SourceDir after CostFinalize */
6580     size = MAX_PATH;
6581     lstrcpyA(path, "kiwi");
6582     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6583     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6584     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6585     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6586 
6587     /* try SOURCEDIR after CostFinalize */
6588     size = MAX_PATH;
6589     lstrcpyA(path, "kiwi");
6590     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6591     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6592     ok(!lstrcmpA(path, "kiwi"),
6593        "Expected path to be unchanged, got \"%s\"\n", path);
6594     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6595 
6596     /* source path does not exist, but the property exists */
6597     size = MAX_PATH;
6598     lstrcpyA(path, "kiwi");
6599     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6600     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6601     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6602     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6603 
6604     size = MAX_PATH;
6605     lstrcpyA(path, "kiwi");
6606     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6607     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6608     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6609     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6610 
6611     /* try SubDir after CostFinalize */
6612     size = MAX_PATH;
6613     lstrcpyA(path, "kiwi");
6614     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6615     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6616     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6617     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
6618 
6619     /* try SubDir2 after CostFinalize */
6620     size = MAX_PATH;
6621     lstrcpyA(path, "kiwi");
6622     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6623     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6624     ok(!lstrcmpA(path, sub2), "Expected \"%s\", got \"%s\"\n", sub2, path);
6625     ok(size == lstrlenA(sub2), "Expected %d, got %d\n", lstrlenA(sub2), size);
6626 
6627     /* nonexistent directory */
6628     size = MAX_PATH;
6629     lstrcpyA(path, "kiwi");
6630     r = MsiGetSourcePathA(hpkg, "IDontExist", path, &size);
6631     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6632     ok(!lstrcmpA(path, "kiwi"),
6633        "Expected path to be unchanged, got \"%s\"\n", path);
6634     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6635 
6636     /* NULL szPathBuf */
6637     size = MAX_PATH;
6638     r = MsiGetSourcePathA(hpkg, "SourceDir", NULL, &size);
6639     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6640     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6641 
6642     /* NULL pcchPathBuf */
6643     lstrcpyA(path, "kiwi");
6644     r = MsiGetSourcePathA(hpkg, "SourceDir", path, NULL);
6645     ok(r == ERROR_INVALID_PARAMETER,
6646        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6647     ok(!lstrcmpA(path, "kiwi"),
6648        "Expected path to be unchanged, got \"%s\"\n", path);
6649 
6650     /* pcchPathBuf is 0 */
6651     size = 0;
6652     lstrcpyA(path, "kiwi");
6653     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6654     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
6655     ok(!lstrcmpA(path, "kiwi"),
6656        "Expected path to be unchanged, got \"%s\"\n", path);
6657     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6658 
6659     /* pcchPathBuf does not have room for NULL terminator */
6660     size = lstrlenA(cwd);
6661     lstrcpyA(path, "kiwi");
6662     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6663     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
6664     ok(!strncmp(path, cwd, lstrlenA(cwd) - 1),
6665        "Expected path with no backslash, got \"%s\"\n", path);
6666     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6667 
6668     /* pcchPathBuf has room for NULL terminator */
6669     size = lstrlenA(cwd) + 1;
6670     lstrcpyA(path, "kiwi");
6671     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6672     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6673     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6674     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6675 
6676     /* remove property */
6677     r = MsiSetPropertyA(hpkg, "SourceDir", NULL);
6678     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6679 
6680     /* try SourceDir again */
6681     size = MAX_PATH;
6682     lstrcpyA(path, "kiwi");
6683     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6684     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6685     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6686     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6687 
6688     /* set property to a valid directory */
6689     r = MsiSetPropertyA(hpkg, "SOURCEDIR", cwd);
6690     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6691 
6692     /* try SOURCEDIR again */
6693     size = MAX_PATH;
6694     lstrcpyA(path, "kiwi");
6695     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6696     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6697     ok(!lstrcmpA(path, "kiwi"),
6698        "Expected path to be unchanged, got \"%s\"\n", path);
6699     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6700 
6701     MsiCloseHandle(hpkg);
6702 
6703     /* compressed source */
6704 
6705     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb);
6706     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6707 
6708     set_suminfo_prop(hdb, PID_WORDCOUNT, msidbSumInfoSourceTypeCompressed);
6709 
6710     r = package_from_db(hdb, &hpkg);
6711     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
6712 
6713     /* try TARGETDIR */
6714     size = MAX_PATH;
6715     lstrcpyA(path, "kiwi");
6716     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6717     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6718     ok(!lstrcmpA(path, "kiwi"),
6719        "Expected path to be unchanged, got \"%s\"\n", path);
6720     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6721 
6722     /* try SourceDir */
6723     size = MAX_PATH;
6724     lstrcpyA(path, "kiwi");
6725     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6726     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6727     ok(!lstrcmpA(path, "kiwi"),
6728        "Expected path to be unchanged, got \"%s\"\n", path);
6729     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6730 
6731     /* try SOURCEDIR */
6732     size = MAX_PATH;
6733     lstrcpyA(path, "kiwi");
6734     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6735     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6736     ok(!lstrcmpA(path, "kiwi"),
6737        "Expected path to be unchanged, got \"%s\"\n", path);
6738     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6739 
6740     /* source path nor the property exist */
6741     size = MAX_PATH;
6742     lstrcpyA(path, "kiwi");
6743     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6744     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6745     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6746     ok(size == 0, "Expected 0, got %d\n", size);
6747 
6748     size = MAX_PATH;
6749     lstrcpyA(path, "kiwi");
6750     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6751     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6752     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6753     ok(size == 0, "Expected 0, got %d\n", size);
6754 
6755     /* try SubDir */
6756     size = MAX_PATH;
6757     lstrcpyA(path, "kiwi");
6758     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6759     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6760     ok(!lstrcmpA(path, "kiwi"),
6761        "Expected path to be unchanged, got \"%s\"\n", path);
6762     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6763 
6764     /* try SubDir2 */
6765     size = MAX_PATH;
6766     lstrcpyA(path, "kiwi");
6767     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6768     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6769     ok(!lstrcmpA(path, "kiwi"),
6770        "Expected path to be unchanged, got \"%s\"\n", path);
6771     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6772 
6773     r = MsiDoActionA(hpkg, "CostInitialize");
6774     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6775 
6776     /* try TARGETDIR after CostInitialize */
6777     size = MAX_PATH;
6778     lstrcpyA(path, "kiwi");
6779     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6780     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6781     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6782     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6783 
6784     /* try SourceDir after CostInitialize */
6785     size = MAX_PATH;
6786     lstrcpyA(path, "kiwi");
6787     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6788     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6789     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6790     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6791 
6792     /* try SOURCEDIR after CostInitialize */
6793     size = MAX_PATH;
6794     lstrcpyA(path, "kiwi");
6795     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6796     todo_wine
6797     {
6798         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6799         ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6800         ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6801     }
6802 
6803     /* source path does not exist, but the property exists */
6804     size = MAX_PATH;
6805     lstrcpyA(path, "kiwi");
6806     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6807     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6808     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6809     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6810 
6811     size = MAX_PATH;
6812     lstrcpyA(path, "kiwi");
6813     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6814     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6815     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6816     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6817 
6818     /* try SubDir after CostInitialize */
6819     size = MAX_PATH;
6820     lstrcpyA(path, "kiwi");
6821     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6822     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6823     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6824     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6825 
6826     /* try SubDir2 after CostInitialize */
6827     size = MAX_PATH;
6828     lstrcpyA(path, "kiwi");
6829     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6830     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6831     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6832     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6833 
6834     r = MsiDoActionA(hpkg, "ResolveSource");
6835     ok(r == ERROR_SUCCESS, "file cost failed\n");
6836 
6837     /* try TARGETDIR after ResolveSource */
6838     size = MAX_PATH;
6839     lstrcpyA(path, "kiwi");
6840     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6841     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6842     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6843     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6844 
6845     /* try SourceDir after ResolveSource */
6846     size = MAX_PATH;
6847     lstrcpyA(path, "kiwi");
6848     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6849     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6850     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6851     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6852 
6853     /* try SOURCEDIR after ResolveSource */
6854     size = MAX_PATH;
6855     lstrcpyA(path, "kiwi");
6856     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6857     todo_wine
6858     {
6859         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6860         ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6861         ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6862     }
6863 
6864     /* source path and the property exist */
6865     size = MAX_PATH;
6866     lstrcpyA(path, "kiwi");
6867     r = MsiGetPropertyA(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     size = MAX_PATH;
6873     lstrcpyA(path, "kiwi");
6874     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6875     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6876     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6877     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6878 
6879     /* try SubDir after ResolveSource */
6880     size = MAX_PATH;
6881     lstrcpyA(path, "kiwi");
6882     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6883     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6884     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6885     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6886 
6887     /* try SubDir2 after ResolveSource */
6888     size = MAX_PATH;
6889     lstrcpyA(path, "kiwi");
6890     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6891     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6892     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6893     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6894 
6895     r = MsiDoActionA(hpkg, "FileCost");
6896     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6897 
6898     /* try TARGETDIR after CostFinalize */
6899     size = MAX_PATH;
6900     lstrcpyA(path, "kiwi");
6901     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6902     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6903     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6904     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6905 
6906     /* try SourceDir after CostFinalize */
6907     size = MAX_PATH;
6908     lstrcpyA(path, "kiwi");
6909     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6910     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6911     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6912     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6913 
6914     /* try SOURCEDIR after CostFinalize */
6915     size = MAX_PATH;
6916     lstrcpyA(path, "kiwi");
6917     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6918     todo_wine
6919     {
6920         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6921         ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6922         ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6923     }
6924 
6925     /* source path and the property exist */
6926     size = MAX_PATH;
6927     lstrcpyA(path, "kiwi");
6928     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6929     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6930     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6931     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6932 
6933     size = MAX_PATH;
6934     lstrcpyA(path, "kiwi");
6935     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6936     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6937     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6938     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6939 
6940     /* try SubDir after CostFinalize */
6941     size = MAX_PATH;
6942     lstrcpyA(path, "kiwi");
6943     r = MsiGetSourcePathA(hpkg, "SubDir", 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     /* try SubDir2 after CostFinalize */
6949     size = MAX_PATH;
6950     lstrcpyA(path, "kiwi");
6951     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6952     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6953     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6954     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6955 
6956     r = MsiDoActionA(hpkg, "CostFinalize");
6957     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6958 
6959     /* try TARGETDIR after CostFinalize */
6960     size = MAX_PATH;
6961     lstrcpyA(path, "kiwi");
6962     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6963     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6964     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6965     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6966 
6967     /* try SourceDir after CostFinalize */
6968     size = MAX_PATH;
6969     lstrcpyA(path, "kiwi");
6970     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6971     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6972     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6973     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6974 
6975     /* try SOURCEDIR after CostFinalize */
6976     size = MAX_PATH;
6977     lstrcpyA(path, "kiwi");
6978     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6979     todo_wine
6980     {
6981         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6982         ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6983         ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6984     }
6985 
6986     /* source path and the property exist */
6987     size = MAX_PATH;
6988     lstrcpyA(path, "kiwi");
6989     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6990     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6991     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6992     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6993 
6994     size = MAX_PATH;
6995     lstrcpyA(path, "kiwi");
6996     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6997     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6998     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6999     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7000 
7001     /* try SubDir after CostFinalize */
7002     size = MAX_PATH;
7003     lstrcpyA(path, "kiwi");
7004     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7005     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7006     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7007     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7008 
7009     /* try SubDir2 after CostFinalize */
7010     size = MAX_PATH;
7011     lstrcpyA(path, "kiwi");
7012     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
7013     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7014     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7015     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7016 
7017     MsiCloseHandle(hpkg);
7018     DeleteFileA(msifile);
7019 }
7020 
7021 static void test_shortlongsource(void)
7022 {
7023     MSIHANDLE hdb, hpkg;
7024     CHAR path[MAX_PATH];
7025     CHAR cwd[MAX_PATH];
7026     CHAR subsrc[MAX_PATH];
7027     DWORD size;
7028     UINT r;
7029 
7030     lstrcpyA(cwd, CURR_DIR);
7031     if (!is_root(CURR_DIR)) lstrcatA(cwd, "\\");
7032 
7033     lstrcpyA(subsrc, cwd);
7034     lstrcatA(subsrc, "long");
7035     lstrcatA(subsrc, "\\");
7036 
7037     /* long file names */
7038 
7039     hdb = create_package_db();
7040     ok( hdb, "failed to create database\n");
7041 
7042     set_suminfo_prop(hdb, PID_WORDCOUNT, 0);
7043 
7044     add_directory_entry(hdb, "'TARGETDIR', '', 'SourceDir'");
7045     add_directory_entry(hdb, "'SubDir', 'TARGETDIR', 'short|long'");
7046 
7047     /* CostInitialize:short */
7048     add_directory_entry(hdb, "'SubDir2', 'TARGETDIR', 'one|two'");
7049 
7050     /* CostInitialize:long */
7051     add_directory_entry(hdb, "'SubDir3', 'TARGETDIR', 'three|four'");
7052 
7053     /* FileCost:short */
7054     add_directory_entry(hdb, "'SubDir4', 'TARGETDIR', 'five|six'");
7055 
7056     /* FileCost:long */
7057     add_directory_entry(hdb, "'SubDir5', 'TARGETDIR', 'seven|eight'");
7058 
7059     /* CostFinalize:short */
7060     add_directory_entry(hdb, "'SubDir6', 'TARGETDIR', 'nine|ten'");
7061 
7062     /* CostFinalize:long */
7063     add_directory_entry(hdb, "'SubDir7', 'TARGETDIR', 'eleven|twelve'");
7064 
7065     r = MsiDatabaseCommit(hdb);
7066     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
7067 
7068     r = package_from_db(hdb, &hpkg);
7069     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
7070     {
7071         skip("Not enough rights to perform tests\n");
7072         DeleteFileA(msifile);
7073         return;
7074     }
7075     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
7076 
7077     MsiCloseHandle(hdb);
7078 
7079     CreateDirectoryA("one", NULL);
7080     CreateDirectoryA("four", NULL);
7081 
7082     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
7083 
7084     r = MsiDoActionA(hpkg, "CostInitialize");
7085     ok(r == ERROR_SUCCESS, "file cost failed\n");
7086 
7087     CreateDirectoryA("five", NULL);
7088     CreateDirectoryA("eight", NULL);
7089 
7090     r = MsiDoActionA(hpkg, "FileCost");
7091     ok(r == ERROR_SUCCESS, "file cost failed\n");
7092 
7093     CreateDirectoryA("nine", NULL);
7094     CreateDirectoryA("twelve", NULL);
7095 
7096     r = MsiDoActionA(hpkg, "CostFinalize");
7097     ok(r == ERROR_SUCCESS, "file cost failed\n");
7098 
7099     /* neither short nor long source directories exist */
7100     size = MAX_PATH;
7101     lstrcpyA(path, "kiwi");
7102     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7103     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7104     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7105     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7106 
7107     CreateDirectoryA("short", NULL);
7108 
7109     /* short source directory exists */
7110     size = MAX_PATH;
7111     lstrcpyA(path, "kiwi");
7112     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7113     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7114     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7115     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7116 
7117     CreateDirectoryA("long", NULL);
7118 
7119     /* both short and long source directories exist */
7120     size = MAX_PATH;
7121     lstrcpyA(path, "kiwi");
7122     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7123     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7124     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7125     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7126 
7127     lstrcpyA(subsrc, cwd);
7128     lstrcatA(subsrc, "two");
7129     lstrcatA(subsrc, "\\");
7130 
7131     /* short dir exists before CostInitialize */
7132     size = MAX_PATH;
7133     lstrcpyA(path, "kiwi");
7134     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
7135     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7136     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7137     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7138 
7139     lstrcpyA(subsrc, cwd);
7140     lstrcatA(subsrc, "four");
7141     lstrcatA(subsrc, "\\");
7142 
7143     /* long dir exists before CostInitialize */
7144     size = MAX_PATH;
7145     lstrcpyA(path, "kiwi");
7146     r = MsiGetSourcePathA(hpkg, "SubDir3", path, &size);
7147     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7148     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7149     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7150 
7151     lstrcpyA(subsrc, cwd);
7152     lstrcatA(subsrc, "six");
7153     lstrcatA(subsrc, "\\");
7154 
7155     /* short dir exists before FileCost */
7156     size = MAX_PATH;
7157     lstrcpyA(path, "kiwi");
7158     r = MsiGetSourcePathA(hpkg, "SubDir4", path, &size);
7159     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7160     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7161     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7162 
7163     lstrcpyA(subsrc, cwd);
7164     lstrcatA(subsrc, "eight");
7165     lstrcatA(subsrc, "\\");
7166 
7167     /* long dir exists before FileCost */
7168     size = MAX_PATH;
7169     lstrcpyA(path, "kiwi");
7170     r = MsiGetSourcePathA(hpkg, "SubDir5", path, &size);
7171     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7172     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7173     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7174 
7175     lstrcpyA(subsrc, cwd);
7176     lstrcatA(subsrc, "ten");
7177     lstrcatA(subsrc, "\\");
7178 
7179     /* short dir exists before CostFinalize */
7180     size = MAX_PATH;
7181     lstrcpyA(path, "kiwi");
7182     r = MsiGetSourcePathA(hpkg, "SubDir6", path, &size);
7183     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7184     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7185     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7186 
7187     lstrcpyA(subsrc, cwd);
7188     lstrcatA(subsrc, "twelve");
7189     lstrcatA(subsrc, "\\");
7190 
7191     /* long dir exists before CostFinalize */
7192     size = MAX_PATH;
7193     lstrcpyA(path, "kiwi");
7194     r = MsiGetSourcePathA(hpkg, "SubDir7", path, &size);
7195     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7196     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7197     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7198 
7199     MsiCloseHandle(hpkg);
7200     RemoveDirectoryA("short");
7201     RemoveDirectoryA("long");
7202     RemoveDirectoryA("one");
7203     RemoveDirectoryA("four");
7204     RemoveDirectoryA("five");
7205     RemoveDirectoryA("eight");
7206     RemoveDirectoryA("nine");
7207     RemoveDirectoryA("twelve");
7208 
7209     /* short file names */
7210 
7211     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb);
7212     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7213 
7214     set_suminfo_prop(hdb, PID_WORDCOUNT, msidbSumInfoSourceTypeSFN);
7215 
7216     r = package_from_db(hdb, &hpkg);
7217     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
7218 
7219     MsiCloseHandle(hdb);
7220 
7221     CreateDirectoryA("one", NULL);
7222     CreateDirectoryA("four", NULL);
7223 
7224     r = MsiDoActionA(hpkg, "CostInitialize");
7225     ok(r == ERROR_SUCCESS, "file cost failed\n");
7226 
7227     CreateDirectoryA("five", NULL);
7228     CreateDirectoryA("eight", NULL);
7229 
7230     r = MsiDoActionA(hpkg, "FileCost");
7231     ok(r == ERROR_SUCCESS, "file cost failed\n");
7232 
7233     CreateDirectoryA("nine", NULL);
7234     CreateDirectoryA("twelve", NULL);
7235 
7236     r = MsiDoActionA(hpkg, "CostFinalize");
7237     ok(r == ERROR_SUCCESS, "file cost failed\n");
7238 
7239     lstrcpyA(subsrc, cwd);
7240     lstrcatA(subsrc, "short");
7241     lstrcatA(subsrc, "\\");
7242 
7243     /* neither short nor long source directories exist */
7244     size = MAX_PATH;
7245     lstrcpyA(path, "kiwi");
7246     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7247     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7248     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7249     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7250 
7251     CreateDirectoryA("short", NULL);
7252 
7253     /* short source directory exists */
7254     size = MAX_PATH;
7255     lstrcpyA(path, "kiwi");
7256     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7257     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7258     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7259     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7260 
7261     CreateDirectoryA("long", NULL);
7262 
7263     /* both short and long source directories exist */
7264     size = MAX_PATH;
7265     lstrcpyA(path, "kiwi");
7266     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7267     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7268     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7269     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7270 
7271     lstrcpyA(subsrc, cwd);
7272     lstrcatA(subsrc, "one");
7273     lstrcatA(subsrc, "\\");
7274 
7275     /* short dir exists before CostInitialize */
7276     size = MAX_PATH;
7277     lstrcpyA(path, "kiwi");
7278     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
7279     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7280     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7281     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7282 
7283     lstrcpyA(subsrc, cwd);
7284     lstrcatA(subsrc, "three");
7285     lstrcatA(subsrc, "\\");
7286 
7287     /* long dir exists before CostInitialize */
7288     size = MAX_PATH;
7289     lstrcpyA(path, "kiwi");
7290     r = MsiGetSourcePathA(hpkg, "SubDir3", path, &size);
7291     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7292     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7293     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7294 
7295     lstrcpyA(subsrc, cwd);
7296     lstrcatA(subsrc, "five");
7297     lstrcatA(subsrc, "\\");
7298 
7299     /* short dir exists before FileCost */
7300     size = MAX_PATH;
7301     lstrcpyA(path, "kiwi");
7302     r = MsiGetSourcePathA(hpkg, "SubDir4", path, &size);
7303     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7304     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7305     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7306 
7307     lstrcpyA(subsrc, cwd);
7308     lstrcatA(subsrc, "seven");
7309     lstrcatA(subsrc, "\\");
7310 
7311     /* long dir exists before FileCost */
7312     size = MAX_PATH;
7313     lstrcpyA(path, "kiwi");
7314     r = MsiGetSourcePathA(hpkg, "SubDir5", path, &size);
7315     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7316     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7317     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7318 
7319     lstrcpyA(subsrc, cwd);
7320     lstrcatA(subsrc, "nine");
7321     lstrcatA(subsrc, "\\");
7322 
7323     /* short dir exists before CostFinalize */
7324     size = MAX_PATH;
7325     lstrcpyA(path, "kiwi");
7326     r = MsiGetSourcePathA(hpkg, "SubDir6", path, &size);
7327     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7328     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7329     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7330 
7331     lstrcpyA(subsrc, cwd);
7332     lstrcatA(subsrc, "eleven");
7333     lstrcatA(subsrc, "\\");
7334 
7335     /* long dir exists before CostFinalize */
7336     size = MAX_PATH;
7337     lstrcpyA(path, "kiwi");
7338     r = MsiGetSourcePathA(hpkg, "SubDir7", path, &size);
7339     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7340     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7341     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7342 
7343     MsiCloseHandle(hpkg);
7344     RemoveDirectoryA("short");
7345     RemoveDirectoryA("long");
7346     RemoveDirectoryA("one");
7347     RemoveDirectoryA("four");
7348     RemoveDirectoryA("five");
7349     RemoveDirectoryA("eight");
7350     RemoveDirectoryA("nine");
7351     RemoveDirectoryA("twelve");
7352     DeleteFileA(msifile);
7353 }
7354 
7355 static void test_sourcedir(void)
7356 {
7357     MSIHANDLE hdb, hpkg;
7358     CHAR package[12];
7359     CHAR path[MAX_PATH];
7360     CHAR cwd[MAX_PATH];
7361     CHAR subsrc[MAX_PATH];
7362     DWORD size;
7363     UINT r;
7364 
7365     lstrcpyA(cwd, CURR_DIR);
7366     if (!is_root(CURR_DIR)) lstrcatA(cwd, "\\");
7367 
7368     lstrcpyA(subsrc, cwd);
7369     lstrcatA(subsrc, "long");
7370     lstrcatA(subsrc, "\\");
7371 
7372     hdb = create_package_db();
7373     ok( hdb, "failed to create database\n");
7374 
7375     add_directory_entry(hdb, "'TARGETDIR', '', 'SourceDir'");
7376 
7377     sprintf(package, "#%u", hdb);
7378     r = MsiOpenPackageA(package, &hpkg);
7379     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
7380     {
7381         skip("Not enough rights to perform tests\n");
7382         goto error;
7383     }
7384     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7385 
7386     /* properties only */
7387 
7388     /* SourceDir prop */
7389     size = MAX_PATH;
7390     lstrcpyA(path, "kiwi");
7391     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7392     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7393     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7394     ok(size == 0, "Expected 0, got %d\n", size);
7395 
7396     /* SOURCEDIR prop */
7397     size = MAX_PATH;
7398     lstrcpyA(path, "kiwi");
7399     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7400     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7401     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7402     ok(size == 0, "Expected 0, got %d\n", size);
7403 
7404     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
7405 
7406     r = MsiDoActionA(hpkg, "CostInitialize");
7407     ok(r == ERROR_SUCCESS, "file cost failed\n");
7408 
7409     /* SourceDir after CostInitialize */
7410     size = MAX_PATH;
7411     lstrcpyA(path, "kiwi");
7412     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7413     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7414     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7415     ok(size == 0, "Expected 0, got %d\n", size);
7416 
7417     /* SOURCEDIR after CostInitialize */
7418     size = MAX_PATH;
7419     lstrcpyA(path, "kiwi");
7420     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7421     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7422     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7423     ok(size == 0, "Expected 0, got %d\n", size);
7424 
7425     r = MsiDoActionA(hpkg, "FileCost");
7426     ok(r == ERROR_SUCCESS, "file cost failed\n");
7427 
7428     /* SourceDir after FileCost */
7429     size = MAX_PATH;
7430     lstrcpyA(path, "kiwi");
7431     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7432     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7433     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7434     ok(size == 0, "Expected 0, got %d\n", size);
7435 
7436     /* SOURCEDIR after FileCost */
7437     size = MAX_PATH;
7438     lstrcpyA(path, "kiwi");
7439     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7440     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7441     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7442     ok(size == 0, "Expected 0, got %d\n", size);
7443 
7444     r = MsiDoActionA(hpkg, "CostFinalize");
7445     ok(r == ERROR_SUCCESS, "file cost failed\n");
7446 
7447     /* SourceDir after CostFinalize */
7448     size = MAX_PATH;
7449     lstrcpyA(path, "kiwi");
7450     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7451     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7452     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7453     ok(size == 0, "Expected 0, got %d\n", size);
7454 
7455     /* SOURCEDIR after CostFinalize */
7456     size = MAX_PATH;
7457     lstrcpyA(path, "kiwi");
7458     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7459     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7460     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7461     ok(size == 0, "Expected 0, got %d\n", size);
7462 
7463     size = MAX_PATH;
7464     lstrcpyA(path, "kiwi");
7465     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7466     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7467     ok(!lstrcmpA(path, "kiwi"), "Expected \"kiwi\", got \"%s\"\n", path);
7468     ok(size == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, size);
7469 
7470     /* SOURCEDIR after calling MsiGetSourcePath */
7471     size = MAX_PATH;
7472     lstrcpyA(path, "kiwi");
7473     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7474     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7475     todo_wine {
7476     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7477     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7478     }
7479 
7480     r = MsiDoActionA(hpkg, "ResolveSource");
7481     ok(r == ERROR_SUCCESS, "file cost failed\n");
7482 
7483     /* SourceDir after ResolveSource */
7484     size = MAX_PATH;
7485     lstrcpyA(path, "kiwi");
7486     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7487     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7488     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7489     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7490 
7491     /* SOURCEDIR after ResolveSource */
7492     size = MAX_PATH;
7493     lstrcpyA(path, "kiwi");
7494     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7495     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7496     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7497     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7498 
7499     /* random casing */
7500     size = MAX_PATH;
7501     lstrcpyA(path, "kiwi");
7502     r = MsiGetPropertyA(hpkg, "SoUrCeDiR", path, &size);
7503     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7504     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7505     ok(size == 0, "Expected 0, got %d\n", size);
7506 
7507     MsiCloseHandle(hpkg);
7508 
7509     /* reset the package state */
7510     sprintf(package, "#%i", hdb);
7511     r = MsiOpenPackageA(package, &hpkg);
7512     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7513 
7514     /* test how MsiGetSourcePath affects the properties */
7515 
7516     /* SourceDir prop */
7517     size = MAX_PATH;
7518     lstrcpyA(path, "kiwi");
7519     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7520     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7521     todo_wine
7522     {
7523         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7524         ok(size == 0, "Expected 0, got %d\n", size);
7525     }
7526 
7527     size = MAX_PATH;
7528     lstrcpyA(path, "kiwi");
7529     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
7530     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7531     ok(!lstrcmpA(path, "kiwi"),
7532        "Expected path to be unchanged, got \"%s\"\n", path);
7533     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7534 
7535     /* SourceDir after MsiGetSourcePath */
7536     size = MAX_PATH;
7537     lstrcpyA(path, "kiwi");
7538     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7539     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7540     todo_wine
7541     {
7542         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7543         ok(size == 0, "Expected 0, got %d\n", size);
7544     }
7545 
7546     /* SOURCEDIR prop */
7547     size = MAX_PATH;
7548     lstrcpyA(path, "kiwi");
7549     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7550     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7551     todo_wine
7552     {
7553         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7554         ok(size == 0, "Expected 0, got %d\n", size);
7555     }
7556 
7557     size = MAX_PATH;
7558     lstrcpyA(path, "kiwi");
7559     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7560     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7561     ok(!lstrcmpA(path, "kiwi"),
7562        "Expected path to be unchanged, got \"%s\"\n", path);
7563     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7564 
7565     /* SOURCEDIR prop after MsiGetSourcePath */
7566     size = MAX_PATH;
7567     lstrcpyA(path, "kiwi");
7568     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7569     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7570     todo_wine
7571     {
7572         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7573         ok(size == 0, "Expected 0, got %d\n", size);
7574     }
7575 
7576     r = MsiDoActionA(hpkg, "CostInitialize");
7577     ok(r == ERROR_SUCCESS, "file cost failed\n");
7578 
7579     /* SourceDir after CostInitialize */
7580     size = MAX_PATH;
7581     lstrcpyA(path, "kiwi");
7582     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7583     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7584     todo_wine
7585     {
7586         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7587         ok(size == 0, "Expected 0, got %d\n", size);
7588     }
7589 
7590     size = MAX_PATH;
7591     lstrcpyA(path, "kiwi");
7592     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
7593     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7594     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7595     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7596 
7597     /* SourceDir after MsiGetSourcePath */
7598     size = MAX_PATH;
7599     lstrcpyA(path, "kiwi");
7600     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7601     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7602     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7603     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7604 
7605     /* SOURCEDIR after CostInitialize */
7606     size = MAX_PATH;
7607     lstrcpyA(path, "kiwi");
7608     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7609     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7610     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7611     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7612 
7613     /* SOURCEDIR source path still does not exist */
7614     size = MAX_PATH;
7615     lstrcpyA(path, "kiwi");
7616     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7617     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7618     ok(!lstrcmpA(path, "kiwi"),
7619        "Expected path to be unchanged, got \"%s\"\n", path);
7620     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7621 
7622     r = MsiDoActionA(hpkg, "FileCost");
7623     ok(r == ERROR_SUCCESS, "file cost failed\n");
7624 
7625     /* SourceDir after FileCost */
7626     size = MAX_PATH;
7627     lstrcpyA(path, "kiwi");
7628     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7629     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7630     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7631     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7632 
7633     /* SOURCEDIR after FileCost */
7634     size = MAX_PATH;
7635     lstrcpyA(path, "kiwi");
7636     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7637     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7638     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7639     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7640 
7641     /* SOURCEDIR source path still does not exist */
7642     size = MAX_PATH;
7643     lstrcpyA(path, "kiwi");
7644     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7645     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7646     ok(!lstrcmpA(path, "kiwi"),
7647        "Expected path to be unchanged, got \"%s\"\n", path);
7648     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7649 
7650     r = MsiDoActionA(hpkg, "CostFinalize");
7651     ok(r == ERROR_SUCCESS, "file cost failed\n");
7652 
7653     /* SourceDir after CostFinalize */
7654     size = MAX_PATH;
7655     lstrcpyA(path, "kiwi");
7656     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7657     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7658     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7659     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7660 
7661     /* SOURCEDIR after CostFinalize */
7662     size = MAX_PATH;
7663     lstrcpyA(path, "kiwi");
7664     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7665     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7666     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7667     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7668 
7669     /* SOURCEDIR source path still does not exist */
7670     size = MAX_PATH;
7671     lstrcpyA(path, "kiwi");
7672     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7673     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7674     ok(!lstrcmpA(path, "kiwi"),
7675        "Expected path to be unchanged, got \"%s\"\n", path);
7676     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7677 
7678     r = MsiDoActionA(hpkg, "ResolveSource");
7679     ok(r == ERROR_SUCCESS, "file cost failed\n");
7680 
7681     /* SourceDir after ResolveSource */
7682     size = MAX_PATH;
7683     lstrcpyA(path, "kiwi");
7684     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7685     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7686     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7687     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7688 
7689     /* SOURCEDIR after ResolveSource */
7690     size = MAX_PATH;
7691     lstrcpyA(path, "kiwi");
7692     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7693     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7694     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7695     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7696 
7697     /* SOURCEDIR source path still does not exist */
7698     size = MAX_PATH;
7699     lstrcpyA(path, "kiwi");
7700     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7701     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7702     ok(!lstrcmpA(path, "kiwi"),
7703        "Expected path to be unchanged, got \"%s\"\n", path);
7704     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7705 
7706     MsiCloseHandle(hpkg);
7707 
7708 error:
7709     MsiCloseHandle(hdb);
7710     DeleteFileA(msifile);
7711 }
7712 
7713 struct access_res
7714 {
7715     BOOL gothandle;
7716     DWORD lasterr;
7717     BOOL ignore;
7718 };
7719 
7720 static const struct access_res create[16] =
7721 {
7722     { TRUE, ERROR_SUCCESS, TRUE },
7723     { TRUE, ERROR_SUCCESS, TRUE },
7724     { TRUE, ERROR_SUCCESS, FALSE },
7725     { TRUE, ERROR_SUCCESS, FALSE },
7726     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7727     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7728     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7729     { TRUE, ERROR_SUCCESS, FALSE },
7730     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7731     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7732     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7733     { TRUE, ERROR_SUCCESS, TRUE },
7734     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7735     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7736     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7737     { TRUE, ERROR_SUCCESS, TRUE }
7738 };
7739 
7740 static const struct access_res create_commit[16] =
7741 {
7742     { TRUE, ERROR_SUCCESS, TRUE },
7743     { TRUE, ERROR_SUCCESS, TRUE },
7744     { TRUE, ERROR_SUCCESS, FALSE },
7745     { TRUE, ERROR_SUCCESS, FALSE },
7746     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7747     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7748     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7749     { TRUE, ERROR_SUCCESS, FALSE },
7750     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7751     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7752     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7753     { TRUE, ERROR_SUCCESS, TRUE },
7754     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7755     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7756     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7757     { TRUE, ERROR_SUCCESS, TRUE }
7758 };
7759 
7760 static const struct access_res create_close[16] =
7761 {
7762     { TRUE, ERROR_SUCCESS, FALSE },
7763     { TRUE, ERROR_SUCCESS, FALSE },
7764     { TRUE, ERROR_SUCCESS, FALSE },
7765     { TRUE, ERROR_SUCCESS, FALSE },
7766     { TRUE, ERROR_SUCCESS, FALSE },
7767     { TRUE, ERROR_SUCCESS, FALSE },
7768     { TRUE, ERROR_SUCCESS, FALSE },
7769     { TRUE, ERROR_SUCCESS, FALSE },
7770     { TRUE, ERROR_SUCCESS, FALSE },
7771     { TRUE, ERROR_SUCCESS, FALSE },
7772     { TRUE, ERROR_SUCCESS, FALSE },
7773     { TRUE, ERROR_SUCCESS, FALSE },
7774     { TRUE, ERROR_SUCCESS, FALSE },
7775     { TRUE, ERROR_SUCCESS, FALSE },
7776     { TRUE, ERROR_SUCCESS, FALSE },
7777     { TRUE, ERROR_SUCCESS }
7778 };
7779 
7780 static void _test_file_access(LPCSTR file, const struct access_res *ares, DWORD line)
7781 {
7782     DWORD access = 0, share = 0;
7783     DWORD lasterr;
7784     HANDLE hfile;
7785     int i, j, idx = 0;
7786 
7787     for (i = 0; i < 4; i++)
7788     {
7789         if (i == 0) access = 0;
7790         if (i == 1) access = GENERIC_READ;
7791         if (i == 2) access = GENERIC_WRITE;
7792         if (i == 3) access = GENERIC_READ | GENERIC_WRITE;
7793 
7794         for (j = 0; j < 4; j++)
7795         {
7796             if (ares[idx].ignore)
7797                 continue;
7798 
7799             if (j == 0) share = 0;
7800             if (j == 1) share = FILE_SHARE_READ;
7801             if (j == 2) share = FILE_SHARE_WRITE;
7802             if (j == 3) share = FILE_SHARE_READ | FILE_SHARE_WRITE;
7803 
7804             SetLastError(0xdeadbeef);
7805             hfile = CreateFileA(file, access, share, NULL, OPEN_EXISTING,
7806                                 FILE_ATTRIBUTE_NORMAL, 0);
7807             lasterr = GetLastError();
7808 
7809             ok((hfile != INVALID_HANDLE_VALUE) == ares[idx].gothandle,
7810                "(%d, handle, %d): Expected %d, got %d\n",
7811                line, idx, ares[idx].gothandle,
7812                (hfile != INVALID_HANDLE_VALUE));
7813 
7814             ok(lasterr == ares[idx].lasterr, "(%d, lasterr, %d): Expected %d, got %d\n",
7815                line, idx, ares[idx].lasterr, lasterr);
7816 
7817             CloseHandle(hfile);
7818             idx++;
7819         }
7820     }
7821 }
7822 
7823 #define test_file_access(file, ares) _test_file_access(file, ares, __LINE__)
7824 
7825 static void test_access(void)
7826 {
7827     MSIHANDLE hdb;
7828     UINT r;
7829 
7830     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
7831     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7832 
7833     test_file_access(msifile, create);
7834 
7835     r = MsiDatabaseCommit(hdb);
7836     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7837 
7838     test_file_access(msifile, create_commit);
7839     MsiCloseHandle(hdb);
7840 
7841     test_file_access(msifile, create_close);
7842     DeleteFileA(msifile);
7843 
7844     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATEDIRECT, &hdb);
7845     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7846 
7847     test_file_access(msifile, create);
7848 
7849     r = MsiDatabaseCommit(hdb);
7850     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7851 
7852     test_file_access(msifile, create_commit);
7853     MsiCloseHandle(hdb);
7854 
7855     test_file_access(msifile, create_close);
7856     DeleteFileA(msifile);
7857 }
7858 
7859 static void test_emptypackage(void)
7860 {
7861     MSIHANDLE hpkg = 0, hdb = 0, hsuminfo = 0;
7862     MSIHANDLE hview = 0, hrec = 0;
7863     MSICONDITION condition;
7864     CHAR buffer[MAX_PATH];
7865     DWORD size;
7866     UINT r;
7867 
7868     r = MsiOpenPackageA("", &hpkg);
7869     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
7870     {
7871         skip("Not enough rights to perform tests\n");
7872         return;
7873     }
7874     todo_wine
7875     {
7876         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7877     }
7878 
7879     hdb = MsiGetActiveDatabase(hpkg);
7880     todo_wine
7881     {
7882         ok(hdb != 0, "Expected a valid database handle\n");
7883     }
7884 
7885     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Tables`", &hview);
7886     todo_wine
7887     {
7888         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7889     }
7890     r = MsiViewExecute(hview, 0);
7891     todo_wine
7892     {
7893         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7894     }
7895 
7896     r = MsiViewFetch(hview, &hrec);
7897     todo_wine
7898     {
7899         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7900     }
7901 
7902     buffer[0] = 0;
7903     size = MAX_PATH;
7904     r = MsiRecordGetStringA(hrec, 1, buffer, &size);
7905     todo_wine
7906     {
7907         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7908         ok(!lstrcmpA(buffer, "_Property"),
7909            "Expected \"_Property\", got \"%s\"\n", buffer);
7910     }
7911 
7912     MsiCloseHandle(hrec);
7913 
7914     r = MsiViewFetch(hview, &hrec);
7915     todo_wine
7916     {
7917         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7918     }
7919 
7920     size = MAX_PATH;
7921     r = MsiRecordGetStringA(hrec, 1, buffer, &size);
7922     todo_wine
7923     {
7924         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7925         ok(!lstrcmpA(buffer, "#_FolderCache"),
7926            "Expected \"_Property\", got \"%s\"\n", buffer);
7927     }
7928 
7929     MsiCloseHandle(hrec);
7930     MsiViewClose(hview);
7931     MsiCloseHandle(hview);
7932 
7933     condition = MsiDatabaseIsTablePersistentA(hdb, "_Property");
7934     todo_wine
7935     {
7936         ok(condition == MSICONDITION_FALSE,
7937            "Expected MSICONDITION_FALSE, got %d\n", condition);
7938     }
7939 
7940     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Property`", &hview);
7941     todo_wine
7942     {
7943         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7944     }
7945     r = MsiViewExecute(hview, 0);
7946     todo_wine
7947     {
7948         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7949     }
7950 
7951     /* _Property table is not empty */
7952     r = MsiViewFetch(hview, &hrec);
7953     todo_wine
7954     {
7955         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7956     }
7957 
7958     MsiCloseHandle(hrec);
7959     MsiViewClose(hview);
7960     MsiCloseHandle(hview);
7961 
7962     condition = MsiDatabaseIsTablePersistentA(hdb, "#_FolderCache");
7963     todo_wine
7964     {
7965         ok(condition == MSICONDITION_FALSE,
7966            "Expected MSICONDITION_FALSE, got %d\n", condition);
7967     }
7968 
7969     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `#_FolderCache`", &hview);
7970     todo_wine
7971     {
7972         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7973     }
7974     r = MsiViewExecute(hview, 0);
7975     todo_wine
7976     {
7977         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7978     }
7979 
7980     /* #_FolderCache is not empty */
7981     r = MsiViewFetch(hview, &hrec);
7982     todo_wine
7983     {
7984         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7985     }
7986 
7987     MsiCloseHandle(hrec);
7988     MsiViewClose(hview);
7989     MsiCloseHandle(hview);
7990 
7991     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Streams`", &hview);
7992     todo_wine
7993     {
7994         ok(r == ERROR_BAD_QUERY_SYNTAX,
7995            "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7996     }
7997 
7998     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Storages`", &hview);
7999     todo_wine
8000     {
8001         ok(r == ERROR_BAD_QUERY_SYNTAX,
8002            "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8003     }
8004 
8005     r = MsiGetSummaryInformationA(hdb, NULL, 0, &hsuminfo);
8006     todo_wine
8007     {
8008         ok(r == ERROR_INSTALL_PACKAGE_INVALID,
8009            "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
8010     }
8011 
8012     MsiCloseHandle(hsuminfo);
8013 
8014     r = MsiDatabaseCommit(hdb);
8015     todo_wine
8016     {
8017         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8018     }
8019 
8020     MsiCloseHandle(hdb);
8021     MsiCloseHandle(hpkg);
8022 }
8023 
8024 static void test_MsiGetProductProperty(void)
8025 {
8026     static const WCHAR prodcode_propW[] = {'P','r','o','d','u','c','t','C','o','d','e',0};
8027     static const WCHAR nonexistentW[] = {'I','D','o','n','t','E','x','i','s','t',0};
8028     static const WCHAR newpropW[] = {'N','e','w','P','r','o','p','e','r','t','y',0};
8029     static const WCHAR appleW[] = {'a','p','p','l','e',0};
8030     static const WCHAR emptyW[] = {0};
8031     WCHAR valW[MAX_PATH];
8032     MSIHANDLE hprod, hdb;
8033     CHAR val[MAX_PATH];
8034     CHAR path[MAX_PATH];
8035     CHAR query[MAX_PATH];
8036     CHAR keypath[MAX_PATH*2];
8037     CHAR prodcode[MAX_PATH];
8038     WCHAR prodcodeW[MAX_PATH];
8039     CHAR prod_squashed[MAX_PATH];
8040     WCHAR prod_squashedW[MAX_PATH];
8041     HKEY prodkey, userkey, props;
8042     DWORD size;
8043     LONG res;
8044     UINT r;
8045     REGSAM access = KEY_ALL_ACCESS;
8046 
8047     GetCurrentDirectoryA(MAX_PATH, path);
8048     lstrcatA(path, "\\");
8049 
8050     create_test_guid(prodcode, prod_squashed);
8051     MultiByteToWideChar(CP_ACP, 0, prodcode, -1, prodcodeW, MAX_PATH);
8052     squash_guid(prodcodeW, prod_squashedW);
8053 
8054     if (is_wow64)
8055         access |= KEY_WOW64_64KEY;
8056 
8057     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
8058     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8059 
8060     r = MsiDatabaseCommit(hdb);
8061     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8062 
8063     r = set_summary_info(hdb);
8064     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8065 
8066     r = run_query(hdb,
8067             "CREATE TABLE `Directory` ( "
8068             "`Directory` CHAR(255) NOT NULL, "
8069             "`Directory_Parent` CHAR(255), "
8070             "`DefaultDir` CHAR(255) NOT NULL "
8071             "PRIMARY KEY `Directory`)");
8072     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8073 
8074     create_property_table(hdb);
8075 
8076     sprintf(query, "'ProductCode', '%s'", prodcode);
8077     r = add_property_entry(hdb, query);
8078 
8079     r = MsiDatabaseCommit(hdb);
8080     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8081 
8082     MsiCloseHandle(hdb);
8083 
8084     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
8085     lstrcatA(keypath, prod_squashed);
8086 
8087     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
8088     if (res == ERROR_ACCESS_DENIED)
8089     {
8090         skip("Not enough rights to perform tests\n");
8091         DeleteFileA(msifile);
8092         return;
8093     }
8094     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8095 
8096     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
8097     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
8098     lstrcatA(keypath, prod_squashed);
8099 
8100     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
8101     if (res == ERROR_ACCESS_DENIED)
8102     {
8103         skip("Not enough rights to perform tests\n");
8104         RegDeleteKeyA(prodkey, "");
8105         RegCloseKey(prodkey);
8106         return;
8107     }
8108     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8109 
8110     res = RegCreateKeyExA(userkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
8111     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8112 
8113     lstrcpyA(val, path);
8114     lstrcatA(val, "\\");
8115     lstrcatA(val, msifile);
8116     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
8117                          (const BYTE *)val, lstrlenA(val) + 1);
8118     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8119 
8120     hprod = 0xdeadbeef;
8121     r = MsiOpenProductA(prodcode, &hprod);
8122     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8123     ok(hprod != 0 && hprod != 0xdeadbeef, "Expected a valid product handle\n");
8124 
8125     /* hProduct is invalid */
8126     size = MAX_PATH;
8127     lstrcpyA(val, "apple");
8128     r = MsiGetProductPropertyA(0xdeadbeef, "ProductCode", val, &size);
8129     ok(r == ERROR_INVALID_HANDLE,
8130        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
8131     ok(!lstrcmpA(val, "apple"),
8132        "Expected val to be unchanged, got \"%s\"\n", val);
8133     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8134 
8135     size = MAX_PATH;
8136     lstrcpyW(valW, appleW);
8137     r = MsiGetProductPropertyW(0xdeadbeef, prodcode_propW, valW, &size);
8138     ok(r == ERROR_INVALID_HANDLE,
8139        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
8140     ok(!lstrcmpW(valW, appleW),
8141        "Expected val to be unchanged, got %s\n", wine_dbgstr_w(valW));
8142     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8143 
8144     /* szProperty is NULL */
8145     size = MAX_PATH;
8146     lstrcpyA(val, "apple");
8147     r = MsiGetProductPropertyA(hprod, NULL, val, &size);
8148     ok(r == ERROR_INVALID_PARAMETER,
8149        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8150     ok(!lstrcmpA(val, "apple"),
8151        "Expected val to be unchanged, got \"%s\"\n", val);
8152     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8153 
8154     size = MAX_PATH;
8155     lstrcpyW(valW, appleW);
8156     r = MsiGetProductPropertyW(hprod, NULL, valW, &size);
8157     ok(r == ERROR_INVALID_PARAMETER,
8158        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8159     ok(!lstrcmpW(valW, appleW),
8160        "Expected val to be unchanged, got %s\n", wine_dbgstr_w(valW));
8161     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8162 
8163     /* szProperty is empty */
8164     size = MAX_PATH;
8165     lstrcpyA(val, "apple");
8166     r = MsiGetProductPropertyA(hprod, "", val, &size);
8167     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8168     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
8169     ok(size == 0, "Expected 0, got %d\n", size);
8170 
8171     size = MAX_PATH;
8172     lstrcpyW(valW, appleW);
8173     r = MsiGetProductPropertyW(hprod, emptyW, valW, &size);
8174     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8175     ok(*valW == 0, "Expected \"\", got %s\n", wine_dbgstr_w(valW));
8176     ok(size == 0, "Expected 0, got %d\n", size);
8177 
8178     /* get the property */
8179     size = MAX_PATH;
8180     lstrcpyA(val, "apple");
8181     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8182     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8183     ok(!lstrcmpA(val, prodcode),
8184        "Expected \"%s\", got \"%s\"\n", prodcode, val);
8185     ok(size == lstrlenA(prodcode),
8186        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8187 
8188     size = MAX_PATH;
8189     lstrcpyW(valW, appleW);
8190     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, &size);
8191     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8192     ok(!lstrcmpW(valW, prodcodeW),
8193        "Expected %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8194     ok(size == lstrlenW(prodcodeW),
8195        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8196 
8197     /* lpValueBuf is NULL */
8198     size = MAX_PATH;
8199     r = MsiGetProductPropertyA(hprod, "ProductCode", NULL, &size);
8200     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8201     ok(size == lstrlenA(prodcode),
8202        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8203 
8204     size = MAX_PATH;
8205     r = MsiGetProductPropertyW(hprod, prodcode_propW, NULL, &size);
8206     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8207     ok(size == lstrlenW(prodcodeW),
8208        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8209 
8210     /* pcchValueBuf is NULL */
8211     lstrcpyA(val, "apple");
8212     r = MsiGetProductPropertyA(hprod, "ProductCode", val, NULL);
8213     ok(r == ERROR_INVALID_PARAMETER,
8214        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8215     ok(!lstrcmpA(val, "apple"),
8216        "Expected val to be unchanged, got \"%s\"\n", val);
8217     ok(size == lstrlenA(prodcode),
8218        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8219 
8220     lstrcpyW(valW, appleW);
8221     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, NULL);
8222     ok(r == ERROR_INVALID_PARAMETER,
8223        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8224     ok(!lstrcmpW(valW, appleW),
8225        "Expected val to be unchanged, got %s\n", wine_dbgstr_w(valW));
8226     ok(size == lstrlenW(prodcodeW),
8227        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8228 
8229     /* pcchValueBuf is too small */
8230     size = 4;
8231     lstrcpyA(val, "apple");
8232     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8233     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
8234     ok(!strncmp(val, prodcode, 3),
8235        "Expected first 3 chars of \"%s\", got \"%s\"\n", prodcode, val);
8236     ok(size == lstrlenA(prodcode),
8237        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8238 
8239     size = 4;
8240     lstrcpyW(valW, appleW);
8241     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, &size);
8242     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
8243     ok(!memcmp(valW, prodcodeW, 3 * sizeof(WCHAR)),
8244        "Expected first 3 chars of %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8245     ok(size == lstrlenW(prodcodeW),
8246        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8247 
8248     /* pcchValueBuf does not leave room for NULL terminator */
8249     size = lstrlenA(prodcode);
8250     lstrcpyA(val, "apple");
8251     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8252     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
8253     ok(!strncmp(val, prodcode, lstrlenA(prodcode) - 1),
8254        "Expected first 37 chars of \"%s\", got \"%s\"\n", prodcode, val);
8255     ok(size == lstrlenA(prodcode),
8256        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8257 
8258     size = lstrlenW(prodcodeW);
8259     lstrcpyW(valW, appleW);
8260     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, &size);
8261     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
8262     ok(!memcmp(valW, prodcodeW, lstrlenW(prodcodeW) - 1),
8263        "Expected first 37 chars of %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8264     ok(size == lstrlenW(prodcodeW),
8265        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8266 
8267     /* pcchValueBuf has enough room for NULL terminator */
8268     size = lstrlenA(prodcode) + 1;
8269     lstrcpyA(val, "apple");
8270     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8271     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8272     ok(!lstrcmpA(val, prodcode),
8273        "Expected \"%s\", got \"%s\"\n", prodcode, val);
8274     ok(size == lstrlenA(prodcode),
8275        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8276 
8277     size = lstrlenW(prodcodeW) + 1;
8278     lstrcpyW(valW, appleW);
8279     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, &size);
8280     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8281     ok(!lstrcmpW(valW, prodcodeW),
8282        "Expected %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8283     ok(size == lstrlenW(prodcodeW),
8284        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8285 
8286     /* nonexistent property */
8287     size = MAX_PATH;
8288     lstrcpyA(val, "apple");
8289     r = MsiGetProductPropertyA(hprod, "IDontExist", val, &size);
8290     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8291     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
8292     ok(size == 0, "Expected 0, got %d\n", size);
8293 
8294     size = MAX_PATH;
8295     lstrcpyW(valW, appleW);
8296     r = MsiGetProductPropertyW(hprod, nonexistentW, valW, &size);
8297     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8298     ok(!lstrcmpW(valW, emptyW), "Expected \"\", got %s\n", wine_dbgstr_w(valW));
8299     ok(size == 0, "Expected 0, got %d\n", size);
8300 
8301     r = MsiSetPropertyA(hprod, "NewProperty", "value");
8302     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8303 
8304     /* non-product property set */
8305     size = MAX_PATH;
8306     lstrcpyA(val, "apple");
8307     r = MsiGetProductPropertyA(hprod, "NewProperty", val, &size);
8308     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8309     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
8310     ok(size == 0, "Expected 0, got %d\n", size);
8311 
8312     size = MAX_PATH;
8313     lstrcpyW(valW, appleW);
8314     r = MsiGetProductPropertyW(hprod, newpropW, valW, &size);
8315     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8316     ok(!lstrcmpW(valW, emptyW), "Expected \"\", got %s\n", wine_dbgstr_w(valW));
8317     ok(size == 0, "Expected 0, got %d\n", size);
8318 
8319     r = MsiSetPropertyA(hprod, "ProductCode", "value");
8320     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8321 
8322     /* non-product property that is also a product property set */
8323     size = MAX_PATH;
8324     lstrcpyA(val, "apple");
8325     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8326     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8327     ok(!lstrcmpA(val, prodcode),
8328        "Expected \"%s\", got \"%s\"\n", prodcode, val);
8329     ok(size == lstrlenA(prodcode),
8330        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8331 
8332     size = MAX_PATH;
8333     lstrcpyW(valW, appleW);
8334     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, &size);
8335     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8336     ok(!lstrcmpW(valW, prodcodeW),
8337        "Expected %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8338     ok(size == lstrlenW(prodcodeW),
8339        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8340 
8341     MsiCloseHandle(hprod);
8342 
8343     RegDeleteValueA(props, "LocalPackage");
8344     delete_key(props, "", access);
8345     RegCloseKey(props);
8346     delete_key(userkey, "", access);
8347     RegCloseKey(userkey);
8348     delete_key(prodkey, "", access);
8349     RegCloseKey(prodkey);
8350     DeleteFileA(msifile);
8351 }
8352 
8353 static void test_MsiSetProperty(void)
8354 {
8355     MSIHANDLE hpkg, hdb, hrec;
8356     CHAR buf[MAX_PATH];
8357     LPCSTR query;
8358     DWORD size;
8359     UINT r;
8360 
8361     r = package_from_db(create_package_db(), &hpkg);
8362     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
8363     {
8364         skip("Not enough rights to perform tests\n");
8365         DeleteFileA(msifile);
8366         return;
8367     }
8368     ok(r == ERROR_SUCCESS, "Expected a valid package %u\n", r);
8369 
8370     /* invalid hInstall */
8371     r = MsiSetPropertyA(0, "Prop", "Val");
8372     ok(r == ERROR_INVALID_HANDLE,
8373        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
8374 
8375     /* invalid hInstall */
8376     r = MsiSetPropertyA(0xdeadbeef, "Prop", "Val");
8377     ok(r == ERROR_INVALID_HANDLE,
8378        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
8379 
8380     /* szName is NULL */
8381     r = MsiSetPropertyA(hpkg, NULL, "Val");
8382     ok(r == ERROR_INVALID_PARAMETER,
8383        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8384 
8385     /* both szName and szValue are NULL */
8386     r = MsiSetPropertyA(hpkg, NULL, NULL);
8387     ok(r == ERROR_INVALID_PARAMETER,
8388        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8389 
8390     /* szName is empty */
8391     r = MsiSetPropertyA(hpkg, "", "Val");
8392     ok(r == ERROR_FUNCTION_FAILED,
8393        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
8394 
8395     /* szName is empty and szValue is NULL */
8396     r = MsiSetPropertyA(hpkg, "", NULL);
8397     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8398 
8399     /* set a property */
8400     r = MsiSetPropertyA(hpkg, "Prop", "Val");
8401     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8402 
8403     /* get the property */
8404     size = MAX_PATH;
8405     r = MsiGetPropertyA(hpkg, "Prop", buf, &size);
8406     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8407     ok(!lstrcmpA(buf, "Val"), "Expected \"Val\", got \"%s\"\n", buf);
8408     ok(size == 3, "Expected 3, got %d\n", size);
8409 
8410     /* update the property */
8411     r = MsiSetPropertyA(hpkg, "Prop", "Nuvo");
8412     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8413 
8414     /* get the property */
8415     size = MAX_PATH;
8416     r = MsiGetPropertyA(hpkg, "Prop", buf, &size);
8417     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8418     ok(!lstrcmpA(buf, "Nuvo"), "Expected \"Nuvo\", got \"%s\"\n", buf);
8419     ok(size == 4, "Expected 4, got %d\n", size);
8420 
8421     hdb = MsiGetActiveDatabase(hpkg);
8422     ok(hdb != 0, "Expected a valid database handle\n");
8423 
8424     /* set prop is not in the _Property table */
8425     query = "SELECT * FROM `_Property` WHERE `Property` = 'Prop'";
8426     r = do_query(hdb, query, &hrec);
8427     ok(r == ERROR_BAD_QUERY_SYNTAX,
8428        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8429 
8430     /* set prop is not in the Property table */
8431     query = "SELECT * FROM `Property` WHERE `Property` = 'Prop'";
8432     r = do_query(hdb, query, &hrec);
8433     ok(r == ERROR_BAD_QUERY_SYNTAX,
8434        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8435 
8436     MsiCloseHandle(hdb);
8437 
8438     /* szValue is an empty string */
8439     r = MsiSetPropertyA(hpkg, "Prop", "");
8440     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8441 
8442     /* try to get the property */
8443     size = MAX_PATH;
8444     r = MsiGetPropertyA(hpkg, "Prop", buf, &size);
8445     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8446     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
8447     ok(size == 0, "Expected 0, got %d\n", size);
8448 
8449     /* reset the property */
8450     r = MsiSetPropertyA(hpkg, "Prop", "BlueTap");
8451     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8452 
8453     /* delete the property */
8454     r = MsiSetPropertyA(hpkg, "Prop", NULL);
8455     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8456 
8457     /* try to get the property */
8458     size = MAX_PATH;
8459     r = MsiGetPropertyA(hpkg, "Prop", buf, &size);
8460     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8461     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
8462     ok(size == 0, "Expected 0, got %d\n", size);
8463 
8464     MsiCloseHandle(hpkg);
8465     DeleteFileA(msifile);
8466 }
8467 
8468 static void test_MsiApplyMultiplePatches(void)
8469 {
8470     UINT r, type = GetDriveTypeW(NULL);
8471 
8472     r = MsiApplyMultiplePatchesA(NULL, NULL, NULL);
8473     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
8474 
8475     r = MsiApplyMultiplePatchesA("", NULL, NULL);
8476     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
8477 
8478     r = MsiApplyMultiplePatchesA(";", NULL, NULL);
8479     if (type == DRIVE_FIXED)
8480         todo_wine ok(r == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %u\n", r);
8481     else
8482         ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
8483 
8484     r = MsiApplyMultiplePatchesA("  ;", NULL, NULL);
8485     if (type == DRIVE_FIXED)
8486         todo_wine ok(r == ERROR_PATCH_PACKAGE_OPEN_FAILED, "Expected ERROR_PATCH_PACKAGE_OPEN_FAILED, got %u\n", r);
8487     else
8488         ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
8489 
8490     r = MsiApplyMultiplePatchesA(";;", NULL, NULL);
8491     if (type == DRIVE_FIXED)
8492         todo_wine ok(r == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %u\n", r);
8493     else
8494         ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
8495 
8496     r = MsiApplyMultiplePatchesA("nosuchpatchpackage;", NULL, NULL);
8497     todo_wine ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
8498 
8499     r = MsiApplyMultiplePatchesA(";nosuchpatchpackage", NULL, NULL);
8500     if (type == DRIVE_FIXED)
8501         todo_wine ok(r == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %u\n", r);
8502     else
8503         ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
8504 
8505     r = MsiApplyMultiplePatchesA("nosuchpatchpackage;nosuchpatchpackage", NULL, NULL);
8506     todo_wine ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
8507 
8508     r = MsiApplyMultiplePatchesA("  nosuchpatchpackage  ;  nosuchpatchpackage  ", NULL, NULL);
8509     todo_wine ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
8510 }
8511 
8512 static void test_MsiApplyPatch(void)
8513 {
8514     UINT r;
8515 
8516     r = MsiApplyPatchA(NULL, NULL, INSTALLTYPE_DEFAULT, NULL);
8517     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
8518 
8519     r = MsiApplyPatchA("", NULL, INSTALLTYPE_DEFAULT, NULL);
8520     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
8521 }
8522 
8523 static void test_MsiEnumComponentCosts(void)
8524 {
8525     MSIHANDLE hdb, hpkg;
8526     char package[12], drive[3];
8527     DWORD len;
8528     UINT r;
8529     int cost, temp;
8530 
8531     hdb = create_package_db();
8532     ok( hdb, "failed to create database\n" );
8533 
8534     create_property_table( hdb );
8535     add_property_entry( hdb, "'ProductCode', '{379B1C47-40C1-42FA-A9BB-BEBB6F1B0172}'" );
8536     add_property_entry( hdb, "'MSIFASTINSTALL', '1'" );
8537     add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'" );
8538 
8539     create_media_table( hdb );
8540     add_media_entry( hdb, "'1', '2', 'cabinet', '', '', ''");
8541 
8542     create_file_table( hdb );
8543     add_file_entry( hdb, "'one.txt', 'one', 'one.txt', 4096, '', '', 8192, 1" );
8544 
8545     create_component_table( hdb );
8546     add_component_entry( hdb, "'one', '{B2F86B9D-8447-4BC5-8883-750C45AA31CA}', 'TARGETDIR', 0, '', 'one.txt'" );
8547     add_component_entry( hdb, "'two', '{62A09F6E-0B74-4829-BDB7-CAB66F42CCE8}', 'TARGETDIR', 0, '', ''" );
8548 
8549     create_feature_table( hdb );
8550     add_feature_entry( hdb, "'one', '', '', '', 0, 1, '', 0" );
8551     add_feature_entry( hdb, "'two', '', '', '', 0, 1, '', 0" );
8552 
8553     create_feature_components_table( hdb );
8554     add_feature_components_entry( hdb, "'one', 'one'" );
8555     add_feature_components_entry( hdb, "'two', 'two'" );
8556 
8557     create_install_execute_sequence_table( hdb );
8558     add_install_execute_sequence_entry( hdb, "'CostInitialize', '', '800'" );
8559     add_install_execute_sequence_entry( hdb, "'FileCost', '', '900'" );
8560     add_install_execute_sequence_entry( hdb, "'CostFinalize', '', '1000'" );
8561     add_install_execute_sequence_entry( hdb, "'InstallValidate', '', '1100'" );
8562 
8563     r = MsiDatabaseCommit( hdb );
8564     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8565 
8566     sprintf( package, "#%u", hdb );
8567     r = MsiOpenPackageA( package, &hpkg );
8568     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
8569     {
8570         skip("Not enough rights to perform tests\n");
8571         goto error;
8572     }
8573     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8574 
8575     r = MsiEnumComponentCostsA( 0, NULL, 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8576     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8577 
8578     r = MsiEnumComponentCostsA( hpkg, NULL, 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8579     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8580 
8581     r = MsiEnumComponentCostsA( hpkg, NULL, 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8582     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8583 
8584     r = MsiEnumComponentCostsA( hpkg, "", 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8585     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8586 
8587     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8588     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8589 
8590     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, NULL, NULL, NULL, NULL );
8591     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8592 
8593     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, NULL, NULL, NULL );
8594     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8595 
8596     len = sizeof(drive);
8597     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, NULL, NULL );
8598     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8599 
8600     len = sizeof(drive);
8601     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, NULL );
8602     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8603 
8604     len = sizeof(drive);
8605     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8606     todo_wine ok( r == ERROR_INVALID_HANDLE_STATE, "Expected ERROR_INVALID_HANDLE_STATE, got %u\n", r );
8607 
8608     len = sizeof(drive);
8609     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, NULL, &len, &cost, &temp );
8610     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8611 
8612     MsiSetInternalUI( INSTALLUILEVEL_NONE, NULL );
8613 
8614     r = MsiDoActionA( hpkg, "CostInitialize" );
8615     ok( r == ERROR_SUCCESS, "CostInitialize failed %u\n", r );
8616 
8617     r = MsiDoActionA( hpkg, "FileCost" );
8618     ok( r == ERROR_SUCCESS, "FileCost failed %u\n", r );
8619 
8620     len = sizeof(drive);
8621     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8622     ok( r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %u\n", r );
8623 
8624     r = MsiDoActionA( hpkg, "CostFinalize" );
8625     ok( r == ERROR_SUCCESS, "CostFinalize failed %u\n", r );
8626 
8627     /* contrary to what msdn says InstallValidate must be called too */
8628     len = sizeof(drive);
8629     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8630     todo_wine ok( r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %u\n", r );
8631 
8632     r = MsiDoActionA( hpkg, "InstallValidate" );
8633     ok( r == ERROR_SUCCESS, "InstallValidate failed %u\n", r );
8634 
8635     len = 0;
8636     r = MsiEnumComponentCostsA( hpkg, "three", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8637     ok( r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %u\n", r );
8638 
8639     len = 0;
8640     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8641     ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %u\n", r );
8642     ok( len == 2, "expected len == 2, got %u\n", len );
8643 
8644     len = 2;
8645     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8646     ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %u\n", r );
8647     ok( len == 2, "expected len == 2, got %u\n", len );
8648 
8649     len = 2;
8650     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_UNKNOWN, drive, &len, &cost, &temp );
8651     ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %u\n", r );
8652     ok( len == 2, "expected len == 2, got %u\n", len );
8653 
8654     /* install state doesn't seem to matter */
8655     len = sizeof(drive);
8656     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_UNKNOWN, drive, &len, &cost, &temp );
8657     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8658 
8659     len = sizeof(drive);
8660     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_ABSENT, drive, &len, &cost, &temp );
8661     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8662 
8663     len = sizeof(drive);
8664     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_SOURCE, drive, &len, &cost, &temp );
8665     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8666 
8667     len = sizeof(drive);
8668     drive[0] = 0;
8669     cost = temp = 0xdead;
8670     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8671     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8672     ok( len == 2, "expected len == 2, got %u\n", len );
8673     ok( drive[0], "expected a drive\n" );
8674     ok( cost && cost != 0xdead, "expected cost > 0, got %d\n", cost );
8675     ok( !temp, "expected temp == 0, got %d\n", temp );
8676 
8677     len = sizeof(drive);
8678     drive[0] = 0;
8679     cost = temp = 0xdead;
8680     r = MsiEnumComponentCostsA( hpkg, "two", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8681     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8682     ok( len == 2, "expected len == 2, got %u\n", len );
8683     ok( drive[0], "expected a drive\n" );
8684     ok( !cost, "expected cost == 0, got %d\n", cost );
8685     ok( !temp, "expected temp == 0, got %d\n", temp );
8686 
8687     len = sizeof(drive);
8688     drive[0] = 0;
8689     cost = temp = 0xdead;
8690     r = MsiEnumComponentCostsA( hpkg, "", 0, INSTALLSTATE_UNKNOWN, drive, &len, &cost, &temp );
8691     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8692     ok( len == 2, "expected len == 2, got %u\n", len );
8693     ok( drive[0], "expected a drive\n" );
8694     ok( !cost, "expected cost == 0, got %d\n", cost );
8695     ok( temp && temp != 0xdead, "expected temp > 0, got %d\n", temp );
8696 
8697     /* increased index */
8698     len = sizeof(drive);
8699     r = MsiEnumComponentCostsA( hpkg, "one", 1, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8700     ok( r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %u\n", r );
8701 
8702     len = sizeof(drive);
8703     r = MsiEnumComponentCostsA( hpkg, "", 1, INSTALLSTATE_UNKNOWN, drive, &len, &cost, &temp );
8704     ok( r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %u\n", r );
8705 
8706     MsiCloseHandle( hpkg );
8707 error:
8708     MsiCloseHandle( hdb );
8709     DeleteFileA( msifile );
8710 }
8711 
8712 static void test_MsiDatabaseCommit(void)
8713 {
8714     UINT r;
8715     MSIHANDLE hdb, hpkg = 0;
8716     char buf[32], package[12];
8717     DWORD sz;
8718 
8719     hdb = create_package_db();
8720     ok( hdb, "failed to create database\n" );
8721 
8722     create_property_table( hdb );
8723 
8724     sprintf( package, "#%u", hdb );
8725     r = MsiOpenPackageA( package, &hpkg );
8726     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
8727     {
8728         skip("Not enough rights to perform tests\n");
8729         goto error;
8730     }
8731     ok( r == ERROR_SUCCESS, "got %u\n", r );
8732 
8733     r = MsiSetPropertyA( hpkg, "PROP", "value" );
8734     ok( r == ERROR_SUCCESS, "got %u\n", r );
8735 
8736     buf[0] = 0;
8737     sz = sizeof(buf);
8738     r = MsiGetPropertyA( hpkg, "PROP", buf, &sz );
8739     ok( r == ERROR_SUCCESS, "MsiGetPropertyA returned %u\n", r );
8740     ok( !lstrcmpA( buf, "value" ), "got \"%s\"\n", buf );
8741 
8742     r = MsiDatabaseCommit( hdb );
8743     ok( r == ERROR_SUCCESS, "MsiDatabaseCommit returned %u\n", r );
8744 
8745     buf[0] = 0;
8746     sz = sizeof(buf);
8747     r = MsiGetPropertyA( hpkg, "PROP", buf, &sz );
8748     ok( r == ERROR_SUCCESS, "MsiGetPropertyA returned %u\n", r );
8749     ok( !lstrcmpA( buf, "value" ), "got \"%s\"\n", buf );
8750 
8751     MsiCloseHandle( hpkg );
8752 error:
8753     MsiCloseHandle( hdb );
8754     DeleteFileA( msifile );
8755 }
8756 
8757 static int externalui_ran;
8758 
8759 static INT CALLBACK externalui_callback(void *context, UINT message_type, LPCSTR message)
8760 {
8761     externalui_ran = 1;
8762     ok(message_type == INSTALLMESSAGE_USER, "expected INSTALLMESSAGE_USER, got %08x\n", message_type);
8763     return 0;
8764 }
8765 
8766 static int externalui_record_ran;
8767 
8768 static INT CALLBACK externalui_record_callback(void *context, UINT message_type, MSIHANDLE hrecord)
8769 {
8770     INT retval = context ? *((INT *)context) : 0;
8771     UINT r;
8772     externalui_record_ran = 1;
8773     ok(message_type == INSTALLMESSAGE_USER, "expected INSTALLMESSAGE_USER, got %08x\n", message_type);
8774     r = MsiRecordGetFieldCount(hrecord);
8775     ok(r == 1, "expected 1, got %u\n", r);
8776     r = MsiRecordGetInteger(hrecord, 1);
8777     ok(r == 12345, "expected 12345, got %u\n", r);
8778     return retval;
8779 }
8780 
8781 static void test_externalui(void)
8782 {
8783     /* test that external UI handlers work correctly */
8784 
8785     INSTALLUI_HANDLERA prev;
8786     INSTALLUI_HANDLER_RECORD prev_record;
8787     MSIHANDLE hpkg, hrecord;
8788     UINT r;
8789     INT retval = 0;
8790 
8791     prev = MsiSetExternalUIA(externalui_callback, INSTALLLOGMODE_USER, NULL);
8792 
8793     r = package_from_db(create_package_db(), &hpkg);
8794     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
8795     {
8796         skip("Not enough rights to perform tests\n");
8797         DeleteFileA(msifile);
8798         return;
8799     }
8800     ok(r == ERROR_SUCCESS, "Expected a valid package %u\n", r);
8801 
8802     hrecord = MsiCreateRecord(1);
8803     ok(hrecord, "Expected a valid record\n");
8804     r = MsiRecordSetStringA(hrecord, 0, "test message [1]");
8805     ok(r == ERROR_SUCCESS, "MsiSetString failed %u\n", r);
8806     r = MsiRecordSetInteger(hrecord, 1, 12345);
8807     ok(r == ERROR_SUCCESS, "MsiSetInteger failed %u\n", r);
8808 
8809     externalui_ran = 0;
8810     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
8811     ok(r == 0, "expected 0, got %u\n", r);
8812     ok(externalui_ran == 1, "external UI callback did not run\n");
8813 
8814     prev = MsiSetExternalUIA(prev, 0, NULL);
8815     ok(prev == externalui_callback, "wrong callback function %p\n", prev);
8816     r = MsiSetExternalUIRecord(externalui_record_callback, INSTALLLOGMODE_USER, &retval, &prev_record);
8817     ok(r == ERROR_SUCCESS, "MsiSetExternalUIRecord failed %u\n", r);
8818 
8819     externalui_ran = externalui_record_ran = 0;
8820     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
8821     ok(r == 0, "expected 0, got %u\n", r);
8822     ok(externalui_ran == 0, "external UI callback should not have run\n");
8823     ok(externalui_record_ran == 1, "external UI record callback did not run\n");
8824 
8825     MsiSetExternalUIA(externalui_callback, INSTALLLOGMODE_USER, NULL);
8826 
8827     externalui_ran = externalui_record_ran = 0;
8828     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
8829     ok(r == 0, "expected 0, got %u\n", r);
8830     ok(externalui_ran == 1, "external UI callback did not run\n");
8831     ok(externalui_record_ran == 1, "external UI record callback did not run\n");
8832 
8833     retval = 1;
8834     externalui_ran = externalui_record_ran = 0;
8835     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
8836     ok(r == 1, "expected 1, got %u\n", r);
8837     ok(externalui_ran == 0, "external UI callback should not have run\n");
8838     ok(externalui_record_ran == 1, "external UI record callback did not run\n");
8839 
8840     /* filter and context should be kept separately */
8841     r = MsiSetExternalUIRecord(externalui_record_callback, INSTALLLOGMODE_ERROR, &retval, &prev_record);
8842     ok(r == ERROR_SUCCESS, "MsiSetExternalUIRecord failed %u\n", r);
8843 
8844     externalui_ran = externalui_record_ran = 0;
8845     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
8846     ok(r == 0, "expected 0, got %u\n", r);
8847     ok(externalui_ran == 1, "external UI callback did not run\n");
8848     ok(externalui_record_ran == 0, "external UI record callback should not have run\n");
8849 
8850     MsiCloseHandle(hpkg);
8851     DeleteFileA(msifile);
8852 }
8853 
8854 struct externalui_message {
8855     UINT message;
8856     int field_count;
8857     char field[4][100];
8858     int match[4]; /* should we test for a match */
8859     int optional;
8860 };
8861 
8862 static struct externalui_message *sequence;
8863 static int sequence_count, sequence_size;
8864 
8865 static void add_message(const struct externalui_message *msg)
8866 {
8867     if (!sequence)
8868     {
8869         sequence_size = 10;
8870         sequence = HeapAlloc(GetProcessHeap(), 0, sequence_size * sizeof(*sequence));
8871     }
8872     if (sequence_count == sequence_size)
8873     {
8874         sequence_size *= 2;
8875         sequence = HeapReAlloc(GetProcessHeap(), 0, sequence, sequence_size * sizeof(*sequence));
8876     }
8877 
8878     assert(sequence);
8879 
8880     sequence[sequence_count++] = *msg;
8881 }
8882 
8883 static void flush_sequence(void)
8884 {
8885     HeapFree(GetProcessHeap(), 0, sequence);
8886     sequence = NULL;
8887     sequence_count = sequence_size = 0;
8888 }
8889 
8890 static void ok_sequence_(const struct externalui_message *expected, const char *context, BOOL todo,
8891                          const char *file, int line)
8892 {
8893     static const struct externalui_message end_of_sequence = {0};
8894     const struct externalui_message *actual;
8895     int failcount = 0;
8896     int i;
8897 
8898     add_message(&end_of_sequence);
8899 
8900     actual = sequence;
8901 
8902     while (expected->message && actual->message)
8903     {
8904         if (expected->message == actual->message)
8905         {
8906             if (expected->field_count < actual->field_count)
8907             {
8908                 todo_wine_if (todo)
8909                     ok_(file, line) (FALSE, "%s: in msg 0x%08x expecting field count %d got %d\n",
8910                                      context, expected->message, expected->field_count, actual->field_count);
8911                 failcount++;
8912             }
8913 
8914             for (i = 0; i <= actual->field_count; i++)
8915             {
8916                 if (expected->match[i] && strcmp(expected->field[i], actual->field[i]))
8917                 {
8918                     todo_wine_if (todo)
8919                         ok_(file, line) (FALSE, "%s: in msg 0x%08x field %d: expected \"%s\", got \"%s\"\n",
8920                                          context, expected->message, i, expected->field[i], actual->field[i]);
8921                     failcount++;
8922                 }
8923             }
8924 
8925             expected++;
8926             actual++;
8927         }
8928         else if (expected->optional)
8929         {
8930             expected++;
8931         }
8932         else
8933         {
8934             todo_wine_if (todo)
8935                 ok_(file, line) (FALSE, "%s: the msg 0x%08x was expected, but got msg 0x%08x instead\n",
8936                                  context, expected->message, actual->message);
8937             failcount++;
8938             if (todo)
8939                 goto done;
8940             expected++;
8941             actual++;
8942         }
8943     }
8944 
8945     if (expected->message || actual->message)
8946     {
8947         todo_wine_if (todo)
8948             ok_(file, line) (FALSE, "%s: the msg sequence is not complete: expected %08x - actual %08x\n",
8949                              context, expected->message, actual->message);
8950         failcount++;
8951     }
8952 
8953     if(todo && !failcount) /* succeeded yet marked todo */
8954     {
8955         todo_wine
8956             ok_(file, line)(TRUE, "%s: marked \"todo_wine\" but succeeds\n", context);
8957     }
8958 
8959 done:
8960     flush_sequence();
8961 }
8962 
8963 #define ok_sequence(exp, contx, todo) \
8964         ok_sequence_((exp), (contx), (todo), __FILE__, __LINE__)
8965 
8966 /* don't use PROGRESS, which is timing-dependent,
8967  * or SHOWDIALOG, which due to a bug causes a hang on XP */
8968 static const INSTALLLOGMODE MSITEST_INSTALLLOGMODE =
8969     INSTALLLOGMODE_FATALEXIT |
8970     INSTALLLOGMODE_ERROR |
8971     INSTALLLOGMODE_WARNING |
8972     INSTALLLOGMODE_USER |
8973     INSTALLLOGMODE_INFO |
8974     INSTALLLOGMODE_FILESINUSE |
8975     INSTALLLOGMODE_RESOLVESOURCE |
8976     INSTALLLOGMODE_OUTOFDISKSPACE |
8977     INSTALLLOGMODE_ACTIONSTART |
8978     INSTALLLOGMODE_ACTIONDATA |
8979     INSTALLLOGMODE_COMMONDATA |
8980     INSTALLLOGMODE_INITIALIZE |
8981     INSTALLLOGMODE_TERMINATE |
8982     INSTALLLOGMODE_RMFILESINUSE |
8983     INSTALLLOGMODE_INSTALLSTART |
8984     INSTALLLOGMODE_INSTALLEND;
8985 
8986 static const struct externalui_message empty_sequence[] = {
8987     {0}
8988 };
8989 
8990 static const struct externalui_message openpackage_nonexistent_sequence[] = {
8991     {INSTALLMESSAGE_INITIALIZE, -1},
8992     {INSTALLMESSAGE_TERMINATE, -1},
8993     {0}
8994 };
8995 
8996 static const struct externalui_message openpackage_sequence[] = {
8997     {INSTALLMESSAGE_INITIALIZE, -1},
8998     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
8999     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
9000     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9001     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9002     {0}
9003 };
9004 
9005 static const struct externalui_message processmessage_info_sequence[] = {
9006     {INSTALLMESSAGE_INFO, 3, {"zero", "one", "two", "three"}, {1, 1, 1, 1}},
9007     {0}
9008 };
9009 
9010 static const struct externalui_message processmessage_actionstart_sequence[] = {
9011     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "name", "description", "template"}, {0, 1, 1, 1}},
9012     {0}
9013 };
9014 
9015 static const struct externalui_message processmessage_actiondata_sequence[] = {
9016     {INSTALLMESSAGE_ACTIONDATA, 3, {"{{name: }}template", "cherry", "banana", "guava"}, {1, 1, 1, 1}},
9017     {0}
9018 };
9019 
9020 static const struct externalui_message processmessage_error_sequence[] = {
9021     {INSTALLMESSAGE_USER, 3, {"", "1311", "banana", "guava"}, {0, 1, 1, 1}},
9022     {0}
9023 };
9024 
9025 static const struct externalui_message processmessage_internal_error_sequence[] = {
9026     {INSTALLMESSAGE_INFO, 3, {"DEBUG: Error [1]:  Action not found: [2]", "2726", "banana", "guava"}, {1, 1, 1, 1}},
9027     {INSTALLMESSAGE_USER, 3, {"internal error", "2726", "banana", "guava"}, {1, 1, 1, 1}},
9028     {0}
9029 };
9030 
9031 static const struct externalui_message processmessage_error_format_sequence[] = {
9032     {INSTALLMESSAGE_USER, 3, {"", "2726", "banana", "guava"}, {0, 1, 1, 1}},
9033     {0}
9034 };
9035 
9036 static const struct externalui_message doaction_costinitialize_sequence[] = {
9037     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostInitialize", "cost description", "cost template"}, {0, 1, 1, 1}},
9038     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", ""}, {0, 1, 1}},
9039     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", "1"}, {0, 1, 1}},
9040     {0}
9041 };
9042 
9043 static const struct externalui_message doaction_custom_sequence[] = {
9044     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "description", "template"}, {0, 1, 1, 1}},
9045     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
9046     {INSTALLMESSAGE_INFO, 2, {"", "custom", "0"}, {0, 1, 1}},
9047     {0}
9048 };
9049 
9050 static const struct externalui_message doaction_custom_fullui_sequence[] = {
9051     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
9052     {INSTALLMESSAGE_INFO, 2, {"", "custom", ""}, {0, 1, 1}},
9053     {INSTALLMESSAGE_SHOWDIALOG, 0, {"custom"}, {1}},
9054     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
9055     {0}
9056 };
9057 
9058 static const struct externalui_message doaction_custom_cancel_sequence[] = {
9059     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
9060     {0}
9061 };
9062 
9063 static const struct externalui_message doaction_dialog_nonexistent_sequence[] = {
9064     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
9065     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
9066     {INSTALLMESSAGE_SHOWDIALOG, 0, {"custom"}, {1}},
9067     {INSTALLMESSAGE_INFO, 2, {"DEBUG: Error [1]:  Action not found: [2]", "2726", "custom"}, {1, 1, 1}},
9068     {INSTALLMESSAGE_INFO, 2, {"", "2726", "custom"}, {0, 1, 1}},
9069     {INSTALLMESSAGE_INFO, 2, {"", "custom", "0"}, {0, 1, 1}},
9070     {0}
9071 };
9072 
9073 static const struct externalui_message doaction_dialog_sequence[] = {
9074     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "dialog", "", ""}, {0, 1, 1, 1}},
9075     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "0"}, {0, 1, 1}},
9076     {INSTALLMESSAGE_SHOWDIALOG, 0, {"dialog"}, {1}},
9077     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "dialog", "Dialog created"}, {0, 1, 1}},
9078     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "1"}, {0, 1, 1}},
9079     {0}
9080 };
9081 
9082 static const struct externalui_message doaction_dialog_error_sequence[] = {
9083     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "error", "", ""}, {0, 1, 1, 1}},
9084     {INSTALLMESSAGE_INFO, 2, {"", "error", "1"}, {0, 1, 1}},
9085     {INSTALLMESSAGE_SHOWDIALOG, 0, {"error"}, {1}},
9086     {0}
9087 };
9088 
9089 static const struct externalui_message doaction_dialog_3_sequence[] = {
9090     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "dialog", "", ""}, {0, 1, 1, 1}},
9091     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "0"}, {0, 1, 1}},
9092     {INSTALLMESSAGE_SHOWDIALOG, 0, {"dialog"}, {1}},
9093     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "3"}, {0, 1, 1}},
9094     {0}
9095 };
9096 
9097 static const struct externalui_message doaction_dialog_12345_sequence[] = {
9098     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "dialog", "", ""}, {0, 1, 1, 1}},
9099     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "3"}, {0, 1, 1}},
9100     {INSTALLMESSAGE_SHOWDIALOG, 0, {"dialog"}, {1}},
9101     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "12345"}, {0, 1, 1}},
9102     {0}
9103 };
9104 
9105 static const struct externalui_message closehandle_sequence[] = {
9106     {INSTALLMESSAGE_TERMINATE, -1},
9107     {0}
9108 };
9109 
9110 static INT CALLBACK externalui_message_string_callback(void *context, UINT message, LPCSTR string)
9111 {
9112     INT retval = context ? *((INT *)context) : 0;
9113     struct externalui_message msg;
9114 
9115     msg.message = message;
9116     msg.field_count = 0;
9117     strcpy(msg.field[0], string);
9118     add_message(&msg);
9119 
9120     return retval;
9121 }
9122 
9123 static INT CALLBACK externalui_message_callback(void *context, UINT message, MSIHANDLE hrecord)
9124 {
9125     INT retval = context ? *((INT *)context) : 0;
9126     struct externalui_message msg;
9127     char buffer[256];
9128     DWORD length;
9129     UINT r;
9130     int i;
9131 
9132     msg.message = message;
9133     if (message == INSTALLMESSAGE_TERMINATE)
9134     {
9135         /* trying to access the record seems to hang on some versions of Windows */
9136         msg.field_count = -1;
9137         add_message(&msg);
9138         return 1;
9139     }
9140     msg.field_count = MsiRecordGetFieldCount(hrecord);
9141     for (i = 0; i <= msg.field_count; i++)
9142     {
9143         length = sizeof(buffer);
9144         r = MsiRecordGetStringA(hrecord, i, buffer, &length);
9145         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
9146         memcpy(msg.field[i], buffer, min(100, length+1));
9147     }
9148 
9149     /* top-level actions dump a list of all set properties; skip them since they're inconsistent */
9150     if (message == (INSTALLMESSAGE_INFO|MB_ICONHAND) && msg.field_count > 0 && !strncmp(msg.field[0], "Property", 8))
9151         return retval;
9152 
9153     add_message(&msg);
9154 
9155     return retval;
9156 }
9157 
9158 static void test_externalui_message(void)
9159 {
9160     /* test that events trigger the correct sequence of messages */
9161 
9162     INSTALLUI_HANDLER_RECORD prev;
9163     MSIHANDLE hdb, hpkg, hrecord;
9164     INT retval = 1;
9165     UINT r;
9166 
9167     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
9168 
9169     MsiSetExternalUIA(externalui_message_string_callback, INSTALLLOGMODE_SHOWDIALOG, &retval);
9170     r = MsiSetExternalUIRecord(externalui_message_callback, MSITEST_INSTALLLOGMODE, &retval, &prev);
9171 
9172     flush_sequence();
9173 
9174     CoInitialize(NULL);
9175 
9176     hdb = create_package_db();
9177     ok(hdb, "failed to create database\n");
9178 
9179     create_file_data("forcecodepage.idt", "\r\n\r\n1252\t_ForceCodepage\r\n");
9180     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
9181     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9182 
9183     r = run_query(hdb, "CREATE TABLE `Error` (`Error` SHORT NOT NULL, `Message` CHAR(0) PRIMARY KEY `Error`)");
9184     ok(r == ERROR_SUCCESS, "Failed to create Error table: %u\n", r);
9185     r = run_query(hdb, "INSERT INTO `Error` (`Error`, `Message`) VALUES (5, 'internal error')");
9186     ok(r == ERROR_SUCCESS, "Failed to insert into Error table: %u\n", r);
9187 
9188     create_actiontext_table(hdb);
9189     add_actiontext_entry(hdb, "'custom', 'description', 'template'");
9190     add_actiontext_entry(hdb, "'CostInitialize', 'cost description', 'cost template'");
9191 
9192     r = MsiOpenPackageA(NULL, &hpkg);
9193     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
9194     ok_sequence(empty_sequence, "MsiOpenPackage with NULL db", FALSE);
9195 
9196     r = MsiOpenPackageA("nonexistent", &hpkg);
9197     ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
9198     ok_sequence(openpackage_nonexistent_sequence, "MsiOpenPackage with nonexistent db", FALSE);
9199 
9200     r = package_from_db(hdb, &hpkg);
9201     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
9202     {
9203         skip("Not enough rights to perform tests\n");
9204         DeleteFileA(msifile);
9205         return;
9206     }
9207     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
9208     ok_sequence(openpackage_sequence, "MsiOpenPackage with valid db", FALSE);
9209 
9210     /* Test MsiProcessMessage */
9211     hrecord = MsiCreateRecord(3);
9212     ok(hrecord, "failed to create record\n");
9213 
9214     MsiRecordSetStringA(hrecord, 0, "zero");
9215     MsiRecordSetStringA(hrecord, 1, "one");
9216     MsiRecordSetStringA(hrecord, 2, "two");
9217     MsiRecordSetStringA(hrecord, 3, "three");
9218     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_INFO, hrecord);
9219     ok(r == 1, "Expected 1, got %d\n", r);
9220     ok_sequence(processmessage_info_sequence, "MsiProcessMessage(INSTALLMESSAGE_INFO)", FALSE);
9221 
9222     MsiRecordSetStringA(hrecord, 1, "name");
9223     MsiRecordSetStringA(hrecord, 2, "description");
9224     MsiRecordSetStringA(hrecord, 3, "template");
9225     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_ACTIONSTART, hrecord);
9226     ok(r == 1, "Expected 1, got %d\n", r);
9227     ok_sequence(processmessage_actionstart_sequence, "MsiProcessMessage(INSTALLMESSAGE_ACTIONSTART)", FALSE);
9228 
9229     MsiRecordSetStringA(hrecord, 0, "apple");
9230     MsiRecordSetStringA(hrecord, 1, "cherry");
9231     MsiRecordSetStringA(hrecord, 2, "banana");
9232     MsiRecordSetStringA(hrecord, 3, "guava");
9233     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_ACTIONDATA, hrecord);
9234     ok(r == 1, "Expected 1, got %d\n", r);
9235     ok_sequence(processmessage_actiondata_sequence, "MsiProcessMessage(INSTALLMESSAGE_ACTIONDATA)", FALSE);
9236 
9237     /* non-internal error */
9238     MsiRecordSetStringA(hrecord, 0, NULL);
9239     MsiRecordSetInteger(hrecord, 1, 1311);
9240     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
9241     ok(r == 1, "Expected 1, got %d\n", r);
9242     ok_sequence(processmessage_error_sequence, "MsiProcessMessage non-internal error", FALSE);
9243 
9244     /* internal error */
9245     MsiRecordSetStringA(hrecord, 0, NULL);
9246     MsiRecordSetInteger(hrecord, 1, 2726);
9247     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
9248     ok(r == 0, "Expected 0, got %d\n", r);
9249     ok_sequence(processmessage_internal_error_sequence, "MsiProcessMessage internal error", FALSE);
9250 
9251     /* with format field */
9252     MsiRecordSetStringA(hrecord, 0, "starfruit");
9253     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
9254     ok(r == 1, "Expected 1, got %d\n", r);
9255     ok_sequence(processmessage_error_format_sequence, "MsiProcessMessage error", FALSE);
9256 
9257     /* Test a standard action */
9258     r = MsiDoActionA(hpkg, "CostInitialize");
9259     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9260     ok_sequence(doaction_costinitialize_sequence, "MsiDoAction(\"CostInitialize\")", FALSE);
9261 
9262     /* Test a custom action */
9263     r = MsiDoActionA(hpkg, "custom");
9264     ok(r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %d\n", r);
9265     ok_sequence(doaction_custom_sequence, "MsiDoAction(\"custom\")", FALSE);
9266 
9267     /* close the package */
9268     MsiCloseHandle(hpkg);
9269     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
9270 
9271     /* Test dialogs */
9272     hdb = create_package_db();
9273     ok(hdb, "failed to create database\n");
9274 
9275     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
9276     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9277 
9278     create_dialog_table(hdb);
9279     add_dialog_entry(hdb, "'dialog', 50, 50, 100, 100, 0, 'dummy'");
9280 
9281     create_control_table(hdb);
9282     add_control_entry(hdb, "'dialog', 'dummy', 'Text', 5, 5, 5, 5, 3, 'dummy'");
9283 
9284     r = package_from_db(hdb, &hpkg);
9285     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
9286     ok_sequence(openpackage_sequence, "MsiOpenPackage with valid db", FALSE);
9287 
9288     /* Test a custom action */
9289     r = MsiDoActionA(hpkg, "custom");
9290     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9291     ok_sequence(doaction_custom_fullui_sequence, "MsiDoAction(\"custom\")", FALSE);
9292 
9293     retval = 2;
9294     r = MsiDoActionA(hpkg, "custom");
9295     ok(r == ERROR_INSTALL_USEREXIT, "Expected ERROR_INSTALL_USEREXIT, got %d\n", r);
9296     ok_sequence(doaction_custom_cancel_sequence, "MsiDoAction(\"custom\")", FALSE);
9297 
9298     retval = 0;
9299     r = MsiDoActionA(hpkg, "custom");
9300     ok(r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %d\n", r);
9301     ok_sequence(doaction_dialog_nonexistent_sequence, "MsiDoAction(\"custom\")", FALSE);
9302 
9303     r = MsiDoActionA(hpkg, "dialog");
9304     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9305     ok_sequence(doaction_dialog_sequence, "MsiDoAction(\"dialog\")", FALSE);
9306 
9307     retval = -1;
9308     r = MsiDoActionA(hpkg, "error");
9309     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9310     ok_sequence(doaction_dialog_error_sequence, "MsiDoAction(\"error\")", FALSE);
9311 
9312     r = MsiDoActionA(hpkg, "error");
9313     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9314     ok_sequence(doaction_dialog_error_sequence, "MsiDoAction(\"error\")", FALSE);
9315 
9316     retval = -2;
9317     r = MsiDoActionA(hpkg, "custom");
9318     ok(r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %d\n", r);
9319     ok_sequence(doaction_dialog_nonexistent_sequence, "MsiDoAction(\"custom\")", FALSE);
9320 
9321     retval = 3;
9322     r = MsiDoActionA(hpkg, "dialog");
9323     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %d\n", r);
9324     ok_sequence(doaction_dialog_3_sequence, "MsiDoAction(\"dialog\")", FALSE);
9325 
9326     retval = 12345;
9327     r = MsiDoActionA(hpkg, "dialog");
9328     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_INSTALL_FAILURE, got %d\n", r);
9329     ok_sequence(doaction_dialog_12345_sequence, "MsiDoAction(\"dialog\")", FALSE);
9330 
9331     MsiCloseHandle(hpkg);
9332     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
9333 
9334     MsiCloseHandle(hrecord);
9335     CoUninitialize();
9336     DeleteFileA(msifile);
9337     DeleteFileA("forcecodepage.idt");
9338 }
9339 
9340 static const struct externalui_message controlevent_spawn_sequence[] = {
9341     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "spawn", "", ""}, {0, 1, 1, 1}},
9342     {INSTALLMESSAGE_INFO, 2, {"", "spawn", ""}, {0, 1, 1}},
9343     {INSTALLMESSAGE_SHOWDIALOG, 0, {"spawn"}, {1}},
9344     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "spawn", "Dialog created"}, {0, 1, 1}},
9345 
9346     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
9347     {INSTALLMESSAGE_INFO, 2, {"", "custom", ""}, {0, 1, 1}},
9348     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
9349 
9350     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "child1", "Dialog created"}, {0, 1, 1}},
9351 
9352     {INSTALLMESSAGE_INFO, 2, {"", "spawn", "2"}, {0, 1, 1}},
9353     {0}
9354 };
9355 
9356 static const struct externalui_message controlevent_spawn2_sequence[] = {
9357     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "spawn2", "", ""}, {0, 1, 1, 1}},
9358     {INSTALLMESSAGE_INFO, 2, {"", "spawn2", "2"}, {0, 1, 1}},
9359     {INSTALLMESSAGE_SHOWDIALOG, 0, {"spawn2"}, {1}},
9360     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "spawn2", "Dialog created"}, {0, 1, 1}},
9361 
9362     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
9363     {INSTALLMESSAGE_INFO, 2, {"", "custom", "2"}, {0, 1, 1}},
9364     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
9365 
9366     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "child2", "Dialog created"}, {0, 1, 1}},
9367 
9368     {INSTALLMESSAGE_INFO, 2, {"", "spawn2", "2"}, {0, 1, 1}},
9369     {0}
9370 };
9371 
9372 static void test_controlevent(void)
9373 {
9374     INSTALLUI_HANDLER_RECORD prev;
9375     MSIHANDLE hdb, hpkg;
9376     UINT r;
9377 
9378     if (!winetest_interactive)
9379     {
9380         skip("interactive ControlEvent tests\n");
9381         return;
9382     }
9383 
9384     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
9385 
9386     MsiSetExternalUIA(externalui_message_string_callback, INSTALLLOGMODE_SHOWDIALOG, NULL);
9387     r = MsiSetExternalUIRecord(externalui_message_callback, MSITEST_INSTALLLOGMODE, NULL, &prev);
9388 
9389     flush_sequence();
9390 
9391     CoInitialize(NULL);
9392 
9393     hdb = create_package_db();
9394     ok(hdb, "failed to create database\n");
9395 
9396     create_file_data("forcecodepage.idt", "\r\n\r\n1252\t_ForceCodepage\r\n");
9397     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
9398     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9399 
9400     create_dialog_table(hdb);
9401     add_dialog_entry(hdb, "'spawn', 50, 50, 100, 100, 3, 'button'");
9402     add_dialog_entry(hdb, "'spawn2', 50, 50, 100, 100, 3, 'button'");
9403     add_dialog_entry(hdb, "'child1', 50, 50, 80, 40, 3, 'exit'");
9404     add_dialog_entry(hdb, "'child2', 50, 50, 80, 40, 3, 'exit'");
9405 
9406     create_control_table(hdb);
9407     add_control_entry(hdb, "'spawn', 'button', 'PushButton', 10, 10, 66, 17, 3, 'Click me'");
9408     add_control_entry(hdb, "'spawn2', 'button', 'PushButton', 10, 10, 66, 17, 3, 'Click me'");
9409     add_control_entry(hdb, "'child1', 'exit', 'PushButton', 10, 10, 66, 17, 3, 'Click me'");
9410     add_control_entry(hdb, "'child2', 'exit', 'PushButton', 10, 10, 66, 17, 3, 'Click me'");
9411 
9412     create_controlevent_table(hdb);
9413     add_controlevent_entry(hdb, "'child1', 'exit', 'EndDialog', 'Exit', 1, 1");
9414     add_controlevent_entry(hdb, "'child2', 'exit', 'EndDialog', 'Exit', 1, 1");
9415 
9416     create_custom_action_table(hdb);
9417     add_custom_action_entry(hdb, "'custom', 51, 'dummy', 'dummy value'");
9418 
9419     /* SpawnDialog and EndDialog should trigger after all other events */
9420     add_controlevent_entry(hdb, "'spawn', 'button', 'SpawnDialog', 'child1', 1, 1");
9421     add_controlevent_entry(hdb, "'spawn', 'button', 'DoAction', 'custom', 1, 2");
9422 
9423     /* Multiple dialog events cause only the last one to be triggered */
9424     add_controlevent_entry(hdb, "'spawn2', 'button', 'SpawnDialog', 'child1', 1, 1");
9425     add_controlevent_entry(hdb, "'spawn2', 'button', 'SpawnDialog', 'child2', 1, 2");
9426     add_controlevent_entry(hdb, "'spawn2', 'button', 'DoAction', 'custom', 1, 3");
9427 
9428     r = package_from_db(hdb, &hpkg);
9429     ok(r == ERROR_SUCCESS, "failed to create package: %u\n", r);
9430     ok_sequence(openpackage_sequence, "MsiOpenPackage()", FALSE);
9431 
9432     r = MsiDoActionA(hpkg, "spawn");
9433     ok(r == ERROR_INSTALL_USEREXIT, "expected ERROR_INSTALL_USEREXIT, got %u\n", r);
9434     ok_sequence(controlevent_spawn_sequence, "control event: spawn", FALSE);
9435 
9436     r = MsiDoActionA(hpkg, "spawn2");
9437     ok(r == ERROR_INSTALL_USEREXIT, "expected ERROR_INSTALL_USEREXIT, got %u\n", r);
9438     ok_sequence(controlevent_spawn2_sequence, "control event: spawn2", FALSE);
9439 
9440     MsiCloseHandle(hpkg);
9441     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
9442 
9443     CoUninitialize();
9444     DeleteFileA(msifile);
9445     DeleteFileA("forcecodepage.idt");
9446 }
9447 
9448 static const struct externalui_message toplevel_install_sequence[] = {
9449     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "INSTALL", "", ""}, {0, 1, 1, 1}},
9450     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", ""}, {0, 1, 1}},
9451 
9452     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9453     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9454     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
9455     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9456     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9457 
9458     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "INSTALL", "", ""}, {0, 1, 1, 1}},
9459     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", ""}, {0, 1, 1}},
9460     {INSTALLMESSAGE_INSTALLSTART, 2, {"", "", "{7262AC98-EEBD-4364-8CE3-D654F6A425B9}"}, {1, 1, 1}, 1},
9461 
9462     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostInitialize", "", ""}, {0, 1, 0, 1}},
9463     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", ""}, {0, 1, 1}},
9464     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", "1"}, {0, 1, 1}},
9465 
9466     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "FileCost", "", ""}, {0, 1, 0, 1}},
9467     {INSTALLMESSAGE_INFO, 2, {"", "FileCost", "1"}, {0, 1, 1}},
9468     {INSTALLMESSAGE_INFO, 2, {"", "FileCost", "1"}, {0, 1, 1}},
9469 
9470     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostFinalize", "", ""}, {0, 1, 0, 1}},
9471     {INSTALLMESSAGE_INFO, 2, {"", "CostFinalize", "1"}, {0, 1, 1}},
9472     {INSTALLMESSAGE_INFO, 2, {"", "CostFinalize", "1"}, {0, 1, 1}},
9473 
9474     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", "1"}, {0, 1, 1}},
9475     {INSTALLMESSAGE_INSTALLEND, 3, {"", "", "{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "1"}, {1, 1, 1, 1}, 1},
9476 
9477     /* property dump */
9478 
9479     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "0"}, {0, 1, 1}, 1},
9480     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "1"}, {0, 1, 1}, 1},
9481     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", "1"}, {0, 1, 1}},
9482     {0}
9483 };
9484 
9485 static const struct externalui_message toplevel_install_ui_sequence[] = {
9486     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "INSTALL", "", ""}, {0, 1, 1, 1}},
9487     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", ""}, {0, 1, 1}},
9488 
9489     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "AppSearch", "", ""}, {0, 1, 0, 0}},
9490     {INSTALLMESSAGE_INFO, 2, {"", "AppSearch", ""}, {0, 1, 1}},
9491     {INSTALLMESSAGE_INFO, 2, {"", "AppSearch", "0"}, {0, 1, 1}},
9492 
9493     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", "1"}, {0, 1, 1}},
9494     {0}
9495 };
9496 
9497 static const struct externalui_message toplevel_executeaction_install_sequence[] = {
9498     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "ExecuteAction", "", ""}, {0, 1, 1, 1}},
9499     {INSTALLMESSAGE_INFO, 2, {"", "ExecuteAction", "1"}, {0, 1, 1}},
9500 
9501     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9502     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9503     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9504     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9505 
9506     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "INSTALL", "", ""}, {0, 1, 1, 1}},
9507     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", ""}, {0, 1, 1}},
9508     {INSTALLMESSAGE_INSTALLSTART, 2, {"", "", "{7262AC98-EEBD-4364-8CE3-D654F6A425B9}"}, {1, 1, 1}, 1},
9509 
9510     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostInitialize", "", ""}, {0, 1, 0, 1}},
9511     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize"}, {0, 1}},
9512     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", "1"}, {0, 1, 1}},
9513 
9514     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "FileCost", "", ""}, {0, 1, 0, 1}},
9515     {INSTALLMESSAGE_INFO, 2, {"", "FileCost", "1"}, {0, 1, 1}},
9516     {INSTALLMESSAGE_INFO, 2, {"", "FileCost", "1"}, {0, 1, 1}},
9517 
9518     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostFinalize", "", ""}, {0, 1, 0, 1}},
9519     {INSTALLMESSAGE_INFO, 2, {"", "CostFinalize", "1"}, {0, 1, 1}},
9520     {INSTALLMESSAGE_INFO, 2, {"", "CostFinalize", "1"}, {0, 1, 1}},
9521 
9522     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", "1"}, {0, 1, 1}},
9523     {INSTALLMESSAGE_INSTALLEND, 3, {"", "", "{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "1"}, {1, 1, 1, 1}, 1},
9524 
9525     /* property dump */
9526 
9527     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "0"}, {0, 1, 1}, 1},
9528     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "1"}, {0, 1, 1}, 1},
9529     {INSTALLMESSAGE_INFO, 2, {"", "ExecuteAction", "1"}, {0, 1, 1}},
9530     {0}
9531 };
9532 
9533 static const struct externalui_message toplevel_executeaction_costinitialize_sequence[] = {
9534     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "ExecuteAction", "", ""}, {0, 1, 1, 1}},
9535     {INSTALLMESSAGE_INFO, 2, {"", "ExecuteAction", "1"}, {0, 1, 1}},
9536 
9537     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9538     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9539     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9540     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9541 
9542     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostInitialize", "", ""}, {0, 1, 0, 1}},
9543     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", ""}, {0, 1}},
9544     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", "1"}, {0, 1, 1}},
9545 
9546     /* property dump */
9547 
9548     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "0"}, {0, 1, 1}, 1},
9549     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "1"}, {0, 1, 1}, 1},
9550     {INSTALLMESSAGE_INFO, 2, {"", "ExecuteAction", "1"}, {0, 1, 1}},
9551     {0}
9552 };
9553 
9554 static const struct externalui_message toplevel_msiinstallproduct_sequence[] = {
9555     {INSTALLMESSAGE_INITIALIZE, -1},
9556 
9557     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9558     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9559     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
9560     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9561     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9562 
9563     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "INSTALL", "", ""}, {0, 1, 1, 1}},
9564     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", ""}, {0, 1, 1}},
9565 
9566     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "AppSearch", "", ""}, {0, 1, 0, 0}},
9567     {INSTALLMESSAGE_INFO, 2, {"", "AppSearch", ""}, {0, 1, 1}},
9568     {INSTALLMESSAGE_INFO, 2, {"", "AppSearch", "0"}, {0, 1, 1}},
9569 
9570     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", "1"}, {0, 1, 1}},
9571 
9572     /* property dump */
9573 
9574     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
9575     {INSTALLMESSAGE_TERMINATE, -1},
9576     {0}
9577 };
9578 
9579 static const struct externalui_message toplevel_msiinstallproduct_custom_sequence[] = {
9580     {INSTALLMESSAGE_INITIALIZE, -1},
9581 
9582     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9583     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9584     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
9585     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9586     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9587 
9588     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CUSTOM", "", ""}, {0, 1, 1, 1}},
9589     {INSTALLMESSAGE_INFO, 2, {"", "CUSTOM", ""}, {0, 1, 1}},
9590     {INSTALLMESSAGE_INFO, 2, {"", "CUSTOM", "0"}, {0, 1, 1}},
9591 
9592     /* property dump */
9593 
9594     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
9595     {INSTALLMESSAGE_TERMINATE, -1},
9596     {0}
9597 };
9598 
9599 /* tests involving top-level actions: INSTALL, ExecuteAction */
9600 static void test_top_level_action(void)
9601 {
9602     INSTALLUI_HANDLER_RECORD prev;
9603     MSIHANDLE hdb, hpkg;
9604     UINT r;
9605     char msifile_absolute[MAX_PATH];
9606 
9607     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
9608 
9609     MsiSetExternalUIA(externalui_message_string_callback, INSTALLLOGMODE_SHOWDIALOG, NULL);
9610     r = MsiSetExternalUIRecord(externalui_message_callback, MSITEST_INSTALLLOGMODE, NULL, &prev);
9611 
9612     flush_sequence();
9613 
9614     CoInitialize(NULL);
9615 
9616     hdb = create_package_db();
9617     ok(hdb, "failed to create database\n");
9618 
9619     create_file_data("forcecodepage.idt", "\r\n\r\n1252\t_ForceCodepage\r\n");
9620     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
9621     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9622 
9623     create_property_table(hdb);
9624     add_property_entry(hdb, "'ProductCode', '{7262AC98-EEBD-4364-8CE3-D654F6A425B9}'");
9625 
9626     create_install_execute_sequence_table(hdb);
9627     add_install_execute_sequence_entry(hdb, "'CostInitialize', '', 1");
9628     add_install_execute_sequence_entry(hdb, "'FileCost', '', 2");
9629     add_install_execute_sequence_entry(hdb, "'CostFinalize', '', 3");
9630 
9631     create_install_ui_sequence_table(hdb);
9632     add_install_ui_sequence_entry(hdb, "'AppSearch', '', 1");
9633 
9634     MsiDatabaseCommit(hdb);
9635 
9636     /* for some reason we have to open the package from file using an absolute path */
9637     MsiCloseHandle(hdb);
9638     GetFullPathNameA(msifile, MAX_PATH, msifile_absolute, NULL);
9639     r = MsiOpenPackageA(msifile_absolute, &hpkg);
9640     ok(r == ERROR_SUCCESS, "failed to create package: %u\n", r);
9641     ok_sequence(openpackage_sequence, "MsiOpenPackage()", FALSE);
9642 
9643     /* test INSTALL */
9644     r = MsiDoActionA(hpkg, "INSTALL");
9645     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
9646     ok_sequence(toplevel_install_sequence, "INSTALL (no UI)", FALSE);
9647 
9648     /* test INSTALL with reduced+ UI */
9649     /* for some reason we need to re-open the package to change the internal UI */
9650     MsiCloseHandle(hpkg);
9651     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
9652     MsiSetInternalUI(INSTALLUILEVEL_REDUCED, NULL);
9653     r = MsiOpenPackageA(msifile_absolute, &hpkg);
9654     ok(r == ERROR_SUCCESS, "failed to create package: %u\n", r);
9655     ok_sequence(openpackage_sequence, "MsiOpenPackage()", FALSE);
9656 
9657     r = MsiDoActionA(hpkg, "INSTALL");
9658     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
9659     ok_sequence(toplevel_install_ui_sequence, "INSTALL (reduced+ UI)", TRUE);
9660 
9661     /* test ExecuteAction with EXECUTEACTION property unset */
9662     MsiSetPropertyA(hpkg, "EXECUTEACTION", NULL);
9663     r = MsiDoActionA(hpkg, "ExecuteAction");
9664     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
9665     ok_sequence(toplevel_executeaction_install_sequence, "ExecuteAction: INSTALL", FALSE);
9666 
9667     /* test ExecuteAction with EXECUTEACTION property set */
9668     MsiSetPropertyA(hpkg, "EXECUTEACTION", "CostInitialize");
9669     r = MsiDoActionA(hpkg, "ExecuteAction");
9670     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
9671     ok_sequence(toplevel_executeaction_costinitialize_sequence, "ExecuteAction: CostInitialize", FALSE);
9672 
9673     MsiCloseHandle(hpkg);
9674     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
9675 
9676     /* test MsiInstallProduct() */
9677     r = MsiInstallProductA(msifile_absolute, NULL);
9678     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
9679     ok_sequence(toplevel_msiinstallproduct_sequence, "MsiInstallProduct()", TRUE);
9680 
9681     r = MsiInstallProductA(msifile_absolute, "ACTION=custom");
9682     todo_wine
9683     ok(r == ERROR_INSTALL_FAILURE, "expected ERROR_INSTALL_FAILURE, got %u\n", r);
9684     ok_sequence(toplevel_msiinstallproduct_custom_sequence, "MsiInstallProduct(ACTION=custom)", TRUE);
9685 
9686     CoUninitialize();
9687     DeleteFileA(msifile);
9688     DeleteFileA("forcecodepage.idt");
9689 }
9690 
9691 START_TEST(package)
9692 {
9693     STATEMGRSTATUS status;
9694     BOOL ret = FALSE;
9695 
9696     init_functionpointers();
9697 
9698     if (pIsWow64Process)
9699         pIsWow64Process(GetCurrentProcess(), &is_wow64);
9700 
9701     GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
9702 
9703     /* Create a restore point ourselves so we circumvent the multitude of restore points
9704      * that would have been created by all the installation and removal tests.
9705      *
9706      * This is not needed on version 5.0 where setting MSIFASTINSTALL prevents the
9707      * creation of restore points.
9708      */
9709     if (pSRSetRestorePointA && !pMsiGetComponentPathExA)
9710     {
9711         memset(&status, 0, sizeof(status));
9712         ret = notify_system_change(BEGIN_NESTED_SYSTEM_CHANGE, &status);
9713     }
9714 
9715     test_createpackage();
9716     test_doaction();
9717     test_gettargetpath_bad();
9718     test_settargetpath();
9719     test_props();
9720     test_property_table();
9721     test_condition();
9722     test_msipackage();
9723     test_formatrecord2();
9724     test_formatrecord_tables();
9725     test_states();
9726     test_getproperty();
9727     test_removefiles();
9728     test_appsearch();
9729     test_appsearch_complocator();
9730     test_appsearch_reglocator();
9731     test_appsearch_inilocator();
9732     test_appsearch_drlocator();
9733     test_featureparents();
9734     test_installprops();
9735     test_launchconditions();
9736     test_ccpsearch();
9737     test_complocator();
9738     test_MsiGetSourcePath();
9739     test_shortlongsource();
9740     test_sourcedir();
9741     test_access();
9742     test_emptypackage();
9743     test_MsiGetProductProperty();
9744     test_MsiSetProperty();
9745     test_MsiApplyMultiplePatches();
9746     test_MsiApplyPatch();
9747     test_MsiEnumComponentCosts();
9748     test_MsiDatabaseCommit();
9749     test_externalui();
9750     test_externalui_message();
9751     test_controlevent();
9752     test_top_level_action();
9753 
9754     if (pSRSetRestorePointA && !pMsiGetComponentPathExA && ret)
9755     {
9756         ret = notify_system_change(END_NESTED_SYSTEM_CHANGE, &status);
9757         if (ret)
9758             remove_restore_point(status.llSequenceNumber);
9759     }
9760 }
9761