1 /*
2  * tests for Microsoft Installer functionality
3  *
4  * Copyright 2005 Mike McCormack for CodeWeavers
5  * Copyright 2005 Aric Stewart for CodeWeavers
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21 
22 #define COBJMACROS
23 
24 #include <assert.h>
25 #include <stdio.h>
26 #include <windows.h>
27 #include <msidefs.h>
28 #include <msi.h>
29 #include <msiquery.h>
30 #include <srrestoreptapi.h>
31 #include <shlobj.h>
32 #include <sddl.h>
33 
34 #include "wine/test.h"
35 #include "utils.h"
36 
37 static BOOL is_wow64;
38 static const char msifile[] = "winetest-package.msi";
39 static const WCHAR msifileW[] = L"winetest-package.msi";
40 
41 static char *get_user_sid(void)
42 {
43     HANDLE token;
44     DWORD size = 0;
45     TOKEN_USER *user;
46     char *usersid = NULL;
47 
48     OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
49     GetTokenInformation(token, TokenUser, NULL, size, &size);
50 
51     user = malloc(size);
52     GetTokenInformation(token, TokenUser, user, size, &size);
53     ConvertSidToStringSidA(user->User.Sid, &usersid);
54     free(user);
55 
56     CloseHandle(token);
57     return usersid;
58 }
59 
60 /* RegDeleteTreeW from dlls/advapi32/registry.c */
61 static LSTATUS package_RegDeleteTreeW(HKEY hKey, LPCWSTR lpszSubKey, REGSAM access)
62 {
63     LONG ret;
64     DWORD dwMaxSubkeyLen, dwMaxValueLen;
65     DWORD dwMaxLen, dwSize;
66     WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
67     HKEY hSubKey = hKey;
68 
69     if(lpszSubKey)
70     {
71         ret = RegOpenKeyExW(hKey, lpszSubKey, 0, access, &hSubKey);
72         if (ret) return ret;
73     }
74 
75     ret = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL,
76             &dwMaxSubkeyLen, NULL, NULL, &dwMaxValueLen, NULL, NULL, NULL);
77     if (ret) goto cleanup;
78 
79     dwMaxSubkeyLen++;
80     dwMaxValueLen++;
81     dwMaxLen = max(dwMaxSubkeyLen, dwMaxValueLen);
82     if (dwMaxLen > ARRAY_SIZE(szNameBuf))
83     {
84         /* Name too big: alloc a buffer for it */
85         if (!(lpszName = malloc(dwMaxLen * sizeof(WCHAR))))
86         {
87             ret = ERROR_NOT_ENOUGH_MEMORY;
88             goto cleanup;
89         }
90     }
91 
92     /* Recursively delete all the subkeys */
93     while (TRUE)
94     {
95         dwSize = dwMaxLen;
96         if (RegEnumKeyExW(hSubKey, 0, lpszName, &dwSize, NULL,
97                           NULL, NULL, NULL)) break;
98 
99         ret = package_RegDeleteTreeW(hSubKey, lpszName, access);
100         if (ret) goto cleanup;
101     }
102 
103     if (lpszSubKey)
104         ret = RegDeleteKeyExW(hKey, lpszSubKey, access, 0);
105     else
106         while (TRUE)
107         {
108             dwSize = dwMaxLen;
109             if (RegEnumValueW(hKey, 0, lpszName, &dwSize,
110                   NULL, NULL, NULL, NULL)) break;
111 
112             ret = RegDeleteValueW(hKey, lpszName);
113             if (ret) goto cleanup;
114         }
115 
116 cleanup:
117     if (lpszName != szNameBuf) free(lpszName);
118     if (lpszSubKey) RegCloseKey(hSubKey);
119     return ret;
120 }
121 
122 static BOOL squash_guid(LPCWSTR in, LPWSTR out)
123 {
124     DWORD i,n=1;
125     GUID guid;
126 
127     if (FAILED(CLSIDFromString((LPCOLESTR)in, &guid)))
128         return FALSE;
129 
130     for(i=0; i<8; i++)
131         out[7-i] = in[n++];
132     n++;
133     for(i=0; i<4; i++)
134         out[11-i] = in[n++];
135     n++;
136     for(i=0; i<4; i++)
137         out[15-i] = in[n++];
138     n++;
139     for(i=0; i<2; i++)
140     {
141         out[17+i*2] = in[n++];
142         out[16+i*2] = in[n++];
143     }
144     n++;
145     for( ; i<8; i++)
146     {
147         out[17+i*2] = in[n++];
148         out[16+i*2] = in[n++];
149     }
150     out[32]=0;
151     return TRUE;
152 }
153 
154 static void create_test_guid(LPSTR prodcode, LPSTR squashed)
155 {
156     WCHAR guidW[MAX_PATH];
157     WCHAR squashedW[MAX_PATH];
158     GUID guid;
159     HRESULT hr;
160     int size;
161 
162     hr = CoCreateGuid(&guid);
163     ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr);
164 
165     size = StringFromGUID2(&guid, guidW, MAX_PATH);
166     ok(size == 39, "Expected 39, got %#lx\n", hr);
167 
168     WideCharToMultiByte(CP_ACP, 0, guidW, size, prodcode, MAX_PATH, NULL, NULL);
169     squash_guid(guidW, squashedW);
170     WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
171 }
172 
173 static void set_component_path(LPCSTR filename, MSIINSTALLCONTEXT context,
174                                LPCSTR guid, LPSTR usersid, BOOL dir)
175 {
176     WCHAR guidW[MAX_PATH];
177     WCHAR squashedW[MAX_PATH];
178     CHAR squashed[MAX_PATH];
179     CHAR comppath[MAX_PATH + 81];
180     CHAR prodpath[MAX_PATH];
181     CHAR path[MAX_PATH];
182     LPCSTR prod = NULL;
183     HKEY hkey;
184     REGSAM access = KEY_ALL_ACCESS;
185 
186     if (is_wow64)
187         access |= KEY_WOW64_64KEY;
188 
189     MultiByteToWideChar(CP_ACP, 0, guid, -1, guidW, MAX_PATH);
190     squash_guid(guidW, squashedW);
191     WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
192 
193     if (context == MSIINSTALLCONTEXT_MACHINE)
194     {
195         prod = "3D0DAE300FACA1300AD792060BCDAA92";
196         sprintf(comppath,
197                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
198                 "Installer\\UserData\\S-1-5-18\\Components\\%s", squashed);
199         lstrcpyA(prodpath,
200                  "SOFTWARE\\Classes\\Installer\\"
201                  "Products\\3D0DAE300FACA1300AD792060BCDAA92");
202     }
203     else if (context == MSIINSTALLCONTEXT_USERUNMANAGED)
204     {
205         prod = "7D2F387510109040002000060BECB6AB";
206         sprintf(comppath,
207                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
208                 "Installer\\UserData\\%s\\Components\\%s", usersid, squashed);
209         sprintf(prodpath,
210                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
211                 "Installer\\%s\\Installer\\Products\\"
212                 "7D2F387510109040002000060BECB6AB", usersid);
213     }
214     else if (context == MSIINSTALLCONTEXT_USERMANAGED)
215     {
216         prod = "7D2F387510109040002000060BECB6AB";
217         sprintf(comppath,
218                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
219                 "Installer\\UserData\\%s\\Components\\%s", usersid, squashed);
220         sprintf(prodpath,
221                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
222                 "Installer\\Managed\\%s\\Installer\\Products\\"
223                 "7D2F387510109040002000060BECB6AB", usersid);
224     }
225 
226     RegCreateKeyExA(HKEY_LOCAL_MACHINE, comppath, 0, NULL, 0, access, NULL, &hkey, NULL);
227 
228     lstrcpyA(path, CURR_DIR);
229     lstrcatA(path, "\\");
230     if (!dir) lstrcatA(path, filename);
231 
232     RegSetValueExA(hkey, prod, 0, REG_SZ, (LPBYTE)path, lstrlenA(path));
233     RegCloseKey(hkey);
234 
235     RegCreateKeyExA(HKEY_LOCAL_MACHINE, prodpath, 0, NULL, 0, access, NULL, &hkey, NULL);
236     RegCloseKey(hkey);
237 }
238 
239 static void delete_component_path(LPCSTR guid, MSIINSTALLCONTEXT context, LPSTR usersid)
240 {
241     WCHAR guidW[MAX_PATH];
242     WCHAR squashedW[MAX_PATH];
243     WCHAR substrW[MAX_PATH];
244     CHAR squashed[MAX_PATH];
245     CHAR comppath[MAX_PATH + 81];
246     CHAR prodpath[MAX_PATH];
247     REGSAM access = KEY_ALL_ACCESS;
248 
249     if (is_wow64)
250         access |= KEY_WOW64_64KEY;
251 
252     MultiByteToWideChar(CP_ACP, 0, guid, -1, guidW, MAX_PATH);
253     squash_guid(guidW, squashedW);
254     WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
255 
256     if (context == MSIINSTALLCONTEXT_MACHINE)
257     {
258         sprintf(comppath,
259                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
260                 "Installer\\UserData\\S-1-5-18\\Components\\%s", squashed);
261         lstrcpyA(prodpath,
262                  "SOFTWARE\\Classes\\Installer\\"
263                  "Products\\3D0DAE300FACA1300AD792060BCDAA92");
264     }
265     else if (context == MSIINSTALLCONTEXT_USERUNMANAGED)
266     {
267         sprintf(comppath,
268                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
269                 "Installer\\UserData\\%s\\Components\\%s", usersid, squashed);
270         sprintf(prodpath,
271                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
272                 "Installer\\%s\\Installer\\Products\\"
273                 "7D2F387510109040002000060BECB6AB", usersid);
274     }
275     else if (context == MSIINSTALLCONTEXT_USERMANAGED)
276     {
277         sprintf(comppath,
278                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
279                 "Installer\\UserData\\%s\\Components\\%s", usersid, squashed);
280         sprintf(prodpath,
281                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
282                 "Installer\\Managed\\%s\\Installer\\Products\\"
283                 "7D2F387510109040002000060BECB6AB", usersid);
284     }
285 
286     MultiByteToWideChar(CP_ACP, 0, comppath, -1, substrW, MAX_PATH);
287     package_RegDeleteTreeW(HKEY_LOCAL_MACHINE, substrW, access);
288 
289     MultiByteToWideChar(CP_ACP, 0, prodpath, -1, substrW, MAX_PATH);
290     package_RegDeleteTreeW(HKEY_LOCAL_MACHINE, substrW, access);
291 }
292 
293 static UINT do_query(MSIHANDLE hdb, const char *query, MSIHANDLE *phrec)
294 {
295     MSIHANDLE hview = 0;
296     UINT r, ret;
297 
298     /* open a select query */
299     r = MsiDatabaseOpenViewA(hdb, query, &hview);
300     if (r != ERROR_SUCCESS)
301         return r;
302     r = MsiViewExecute(hview, 0);
303     if (r != ERROR_SUCCESS)
304         return r;
305     ret = MsiViewFetch(hview, phrec);
306     r = MsiViewClose(hview);
307     if (r != ERROR_SUCCESS)
308         return r;
309     r = MsiCloseHandle(hview);
310     if (r != ERROR_SUCCESS)
311         return r;
312     return ret;
313 }
314 
315 static UINT create_component_table( MSIHANDLE hdb )
316 {
317     UINT r = run_query( hdb, 0,
318             "CREATE TABLE `Component` ( "
319             "`Component` CHAR(72) NOT NULL, "
320             "`ComponentId` CHAR(38), "
321             "`Directory_` CHAR(72) NOT NULL, "
322             "`Attributes` SHORT NOT NULL, "
323             "`Condition` CHAR(255), "
324             "`KeyPath` CHAR(72) "
325             "PRIMARY KEY `Component`)" );
326     ok(r == ERROR_SUCCESS, "Failed to create Component table: %u\n", r);
327     return r;
328 }
329 
330 static UINT create_feature_table( MSIHANDLE hdb )
331 {
332     UINT r = run_query( hdb, 0,
333             "CREATE TABLE `Feature` ( "
334             "`Feature` CHAR(38) NOT NULL, "
335             "`Feature_Parent` CHAR(38), "
336             "`Title` CHAR(64), "
337             "`Description` CHAR(255), "
338             "`Display` SHORT NOT NULL, "
339             "`Level` SHORT NOT NULL, "
340             "`Directory_` CHAR(72), "
341             "`Attributes` SHORT NOT NULL "
342             "PRIMARY KEY `Feature`)" );
343     ok(r == ERROR_SUCCESS, "Failed to create Feature table: %u\n", r);
344     return r;
345 }
346 
347 static UINT create_feature_components_table( MSIHANDLE hdb )
348 {
349     UINT r = run_query( hdb, 0,
350             "CREATE TABLE `FeatureComponents` ( "
351             "`Feature_` CHAR(38) NOT NULL, "
352             "`Component_` CHAR(72) NOT NULL "
353             "PRIMARY KEY `Feature_`, `Component_` )" );
354     ok(r == ERROR_SUCCESS, "Failed to create FeatureComponents table: %u\n", r);
355     return r;
356 }
357 
358 static UINT create_file_table( MSIHANDLE hdb )
359 {
360     UINT r = run_query( hdb, 0,
361             "CREATE TABLE `File` ("
362             "`File` CHAR(72) NOT NULL, "
363             "`Component_` CHAR(72) NOT NULL, "
364             "`FileName` CHAR(255) NOT NULL, "
365             "`FileSize` LONG NOT NULL, "
366             "`Version` CHAR(72), "
367             "`Language` CHAR(20), "
368             "`Attributes` SHORT, "
369             "`Sequence` SHORT NOT NULL "
370             "PRIMARY KEY `File`)" );
371     ok(r == ERROR_SUCCESS, "Failed to create File table: %u\n", r);
372     return r;
373 }
374 
375 static UINT create_remove_file_table( MSIHANDLE hdb )
376 {
377     UINT r = run_query( hdb, 0,
378             "CREATE TABLE `RemoveFile` ("
379             "`FileKey` CHAR(72) NOT NULL, "
380             "`Component_` CHAR(72) NOT NULL, "
381             "`FileName` CHAR(255) LOCALIZABLE, "
382             "`DirProperty` CHAR(72) NOT NULL, "
383             "`InstallMode` SHORT NOT NULL "
384             "PRIMARY KEY `FileKey`)" );
385     ok(r == ERROR_SUCCESS, "Failed to create RemoveFile table: %u\n", r);
386     return r;
387 }
388 
389 static UINT create_appsearch_table( MSIHANDLE hdb )
390 {
391     UINT r = run_query( hdb, 0,
392             "CREATE TABLE `AppSearch` ("
393             "`Property` CHAR(72) NOT NULL, "
394             "`Signature_` CHAR(72) NOT NULL "
395             "PRIMARY KEY `Property`, `Signature_`)" );
396     ok(r == ERROR_SUCCESS, "Failed to create AppSearch table: %u\n", r);
397     return r;
398 }
399 
400 static UINT create_reglocator_table( MSIHANDLE hdb )
401 {
402     UINT r = run_query( hdb, 0,
403             "CREATE TABLE `RegLocator` ("
404             "`Signature_` CHAR(72) NOT NULL, "
405             "`Root` SHORT NOT NULL, "
406             "`Key` CHAR(255) NOT NULL, "
407             "`Name` CHAR(255), "
408             "`Type` SHORT "
409             "PRIMARY KEY `Signature_`)" );
410     ok(r == ERROR_SUCCESS, "Failed to create RegLocator table: %u\n", r);
411     return r;
412 }
413 
414 static UINT create_signature_table( MSIHANDLE hdb )
415 {
416     UINT r = run_query( hdb, 0,
417             "CREATE TABLE `Signature` ("
418             "`Signature` CHAR(72) NOT NULL, "
419             "`FileName` CHAR(255) NOT NULL, "
420             "`MinVersion` CHAR(20), "
421             "`MaxVersion` CHAR(20), "
422             "`MinSize` LONG, "
423             "`MaxSize` LONG, "
424             "`MinDate` LONG, "
425             "`MaxDate` LONG, "
426             "`Languages` CHAR(255) "
427             "PRIMARY KEY `Signature`)" );
428     ok(r == ERROR_SUCCESS, "Failed to create Signature table: %u\n", r);
429     return r;
430 }
431 
432 static UINT create_launchcondition_table( MSIHANDLE hdb )
433 {
434     UINT r = run_query( hdb, 0,
435             "CREATE TABLE `LaunchCondition` ("
436             "`Condition` CHAR(255) NOT NULL, "
437             "`Description` CHAR(255) NOT NULL "
438             "PRIMARY KEY `Condition`)" );
439     ok(r == ERROR_SUCCESS, "Failed to create LaunchCondition table: %u\n", r);
440     return r;
441 }
442 
443 static UINT create_property_table( MSIHANDLE hdb )
444 {
445     UINT r = run_query( hdb, 0,
446             "CREATE TABLE `Property` ("
447             "`Property` CHAR(72) NOT NULL, "
448             "`Value` CHAR(0) "
449             "PRIMARY KEY `Property`)" );
450     ok(r == ERROR_SUCCESS, "Failed to create Property table: %u\n", r);
451     return r;
452 }
453 
454 static UINT create_install_execute_sequence_table( MSIHANDLE hdb )
455 {
456     UINT r = run_query( hdb, 0,
457             "CREATE TABLE `InstallExecuteSequence` ("
458             "`Action` CHAR(72) NOT NULL, "
459             "`Condition` CHAR(255), "
460             "`Sequence` SHORT "
461             "PRIMARY KEY `Action`)" );
462     ok(r == ERROR_SUCCESS, "Failed to create InstallExecuteSequence table: %u\n", r);
463     return r;
464 }
465 
466 static UINT create_install_ui_sequence_table( MSIHANDLE hdb )
467 {
468     UINT r = run_query( hdb, 0,
469             "CREATE TABLE `InstallUISequence` ("
470             "`Action` CHAR(72) NOT NULL, "
471             "`Condition` CHAR(255), "
472             "`Sequence` SHORT "
473             "PRIMARY KEY `Action`)" );
474     ok(r == ERROR_SUCCESS, "Failed to create InstallUISequence table: %u\n", r);
475     return r;
476 }
477 
478 static UINT create_media_table( MSIHANDLE hdb )
479 {
480     UINT r = run_query( hdb, 0,
481             "CREATE TABLE `Media` ("
482             "`DiskId` SHORT NOT NULL, "
483             "`LastSequence` SHORT NOT NULL, "
484             "`DiskPrompt` CHAR(64), "
485             "`Cabinet` CHAR(255), "
486             "`VolumeLabel` CHAR(32), "
487             "`Source` CHAR(72) "
488             "PRIMARY KEY `DiskId`)" );
489     ok(r == ERROR_SUCCESS, "Failed to create Media table: %u\n", r);
490     return r;
491 }
492 
493 static UINT create_ccpsearch_table( MSIHANDLE hdb )
494 {
495     UINT r = run_query( hdb, 0,
496             "CREATE TABLE `CCPSearch` ("
497             "`Signature_` CHAR(72) NOT NULL "
498             "PRIMARY KEY `Signature_`)" );
499     ok(r == ERROR_SUCCESS, "Failed to create CCPSearch table: %u\n", r);
500     return r;
501 }
502 
503 static UINT create_drlocator_table( MSIHANDLE hdb )
504 {
505     UINT r = run_query( hdb, 0,
506             "CREATE TABLE `DrLocator` ("
507             "`Signature_` CHAR(72) NOT NULL, "
508             "`Parent` CHAR(72), "
509             "`Path` CHAR(255), "
510             "`Depth` SHORT "
511             "PRIMARY KEY `Signature_`, `Parent`, `Path`)" );
512     ok(r == ERROR_SUCCESS, "Failed to create DrLocator table: %u\n", r);
513     return r;
514 }
515 
516 static UINT create_complocator_table( MSIHANDLE hdb )
517 {
518     UINT r = run_query( hdb, 0,
519             "CREATE TABLE `CompLocator` ("
520             "`Signature_` CHAR(72) NOT NULL, "
521             "`ComponentId` CHAR(38) NOT NULL, "
522             "`Type` SHORT "
523             "PRIMARY KEY `Signature_`)" );
524     ok(r == ERROR_SUCCESS, "Failed to create CompLocator table: %u\n", r);
525     return r;
526 }
527 
528 static UINT create_inilocator_table( MSIHANDLE hdb )
529 {
530     UINT r = run_query( hdb, 0,
531             "CREATE TABLE `IniLocator` ("
532             "`Signature_` CHAR(72) NOT NULL, "
533             "`FileName` CHAR(255) NOT NULL, "
534             "`Section` CHAR(96)NOT NULL, "
535             "`Key` CHAR(128)NOT NULL, "
536             "`Field` SHORT, "
537             "`Type` SHORT "
538             "PRIMARY KEY `Signature_`)" );
539     ok(r == ERROR_SUCCESS, "Failed to create IniLocator table: %u\n", r);
540     return r;
541 }
542 
543 static UINT create_custom_action_table( MSIHANDLE hdb )
544 {
545     UINT r = run_query( hdb, 0,
546             "CREATE TABLE `CustomAction` ("
547             "`Action` CHAR(72) NOT NULL, "
548             "`Type` SHORT NOT NULL, "
549             "`Source` CHAR(75), "
550             "`Target` CHAR(255) "
551             "PRIMARY KEY `Action`)" );
552     ok(r == ERROR_SUCCESS, "Failed to create CustomAction table: %u\n", r);
553     return r;
554 }
555 
556 static UINT create_dialog_table( MSIHANDLE hdb )
557 {
558     UINT r = run_query(hdb, 0,
559             "CREATE TABLE `Dialog` ("
560             "`Dialog` CHAR(72) NOT NULL, "
561             "`HCentering` SHORT NOT NULL, "
562             "`VCentering` SHORT NOT NULL, "
563             "`Width` SHORT NOT NULL, "
564             "`Height` SHORT NOT NULL, "
565             "`Attributes` LONG, "
566             "`Title` CHAR(128) LOCALIZABLE, "
567             "`Control_First` CHAR(50) NOT NULL, "
568             "`Control_Default` CHAR(50), "
569             "`Control_Cancel` CHAR(50) "
570             "PRIMARY KEY `Dialog`)");
571     ok(r == ERROR_SUCCESS, "Failed to create Dialog table: %u\n", r);
572     return r;
573 }
574 
575 static UINT create_control_table( MSIHANDLE hdb )
576 {
577     UINT r = run_query(hdb, 0,
578             "CREATE TABLE `Control` ("
579             "`Dialog_` CHAR(72) NOT NULL, "
580             "`Control` CHAR(50) NOT NULL, "
581             "`Type` CHAR(20) NOT NULL, "
582             "`X` SHORT NOT NULL, "
583             "`Y` SHORT NOT NULL, "
584             "`Width` SHORT NOT NULL, "
585             "`Height` SHORT NOT NULL, "
586             "`Attributes` LONG, "
587             "`Property` CHAR(50), "
588             "`Text` CHAR(0) LOCALIZABLE, "
589             "`Control_Next` CHAR(50), "
590             "`Help` CHAR(255) LOCALIZABLE "
591             "PRIMARY KEY `Dialog_`, `Control`)");
592     ok(r == ERROR_SUCCESS, "Failed to create Control table: %u\n", r);
593     return r;
594 }
595 
596 static UINT create_controlevent_table( MSIHANDLE hdb )
597 {
598     UINT r = run_query(hdb, 0,
599             "CREATE TABLE `ControlEvent` ("
600             "`Dialog_` CHAR(72) NOT NULL, "
601             "`Control_` CHAR(50) NOT NULL, "
602             "`Event` CHAR(50) NOT NULL, "
603             "`Argument` CHAR(255) NOT NULL, "
604             "`Condition` CHAR(255), "
605             "`Ordering` SHORT "
606             "PRIMARY KEY `Dialog_`, `Control_`, `Event`, `Argument`, `Condition`)");
607     ok(r == ERROR_SUCCESS, "Failed to create ControlEvent table: %u\n", r);
608     return r;
609 }
610 
611 static UINT create_actiontext_table( MSIHANDLE hdb )
612 {
613     UINT r = run_query(hdb, 0,
614             "CREATE TABLE `ActionText` ("
615             "`Action` CHAR(72) NOT NULL, "
616             "`Description` CHAR(64) LOCALIZABLE, "
617             "`Template` CHAR(128) LOCALIZABLE "
618             "PRIMARY KEY `Action`)");
619     ok(r == ERROR_SUCCESS, "Failed to create ActionText table: %u\n", r);
620     return r;
621 }
622 
623 static UINT create_upgrade_table( MSIHANDLE hdb )
624 {
625     UINT r = run_query( hdb, 0,
626             "CREATE TABLE `Upgrade` ("
627             "`UpgradeCode` CHAR(38) NOT NULL, "
628             "`VersionMin` CHAR(20), "
629             "`VersionMax` CHAR(20), "
630             "`Language` CHAR(255), "
631             "`Attributes` SHORT, "
632             "`Remove` CHAR(255), "
633             "`ActionProperty` CHAR(72) NOT NULL "
634             "PRIMARY KEY `UpgradeCode`, `VersionMin`, `VersionMax`, `Language`)" );
635     ok(r == ERROR_SUCCESS, "Failed to create Upgrade table: %u\n", r);
636     return r;
637 }
638 
639 static inline UINT add_entry(const char *file, int line, const char *type, MSIHANDLE hdb, const char *values, const char *insert)
640 {
641     char *query;
642     UINT sz, r;
643 
644     sz = strlen(values) + strlen(insert) + 1;
645     query = malloc(sz);
646     sprintf(query, insert, values);
647     r = run_query(hdb, 0, query);
648     free(query);
649     ok_(file, line)(r == ERROR_SUCCESS, "failed to insert into %s table: %u\n", type, r);
650     return r;
651 }
652 
653 #define add_component_entry(hdb, values) add_entry(__FILE__, __LINE__, "Component", hdb, values, \
654                "INSERT INTO `Component`  " \
655                "(`Component`, `ComponentId`, `Directory_`, " \
656                "`Attributes`, `Condition`, `KeyPath`) VALUES( %s )")
657 
658 #define add_directory_entry(hdb, values) add_entry(__FILE__, __LINE__, "Directory", hdb, values, \
659                "INSERT INTO `Directory` " \
660                "(`Directory`,`Directory_Parent`,`DefaultDir`) VALUES( %s )")
661 
662 #define add_feature_entry(hdb, values) add_entry(__FILE__, __LINE__, "Feature", hdb, values, \
663                "INSERT INTO `Feature` " \
664                "(`Feature`, `Feature_Parent`, `Title`, `Description`, " \
665                "`Display`, `Level`, `Directory_`, `Attributes`) VALUES( %s )")
666 
667 #define add_feature_components_entry(hdb, values) add_entry(__FILE__, __LINE__, "FeatureComponents", hdb, values, \
668                "INSERT INTO `FeatureComponents` " \
669                "(`Feature_`, `Component_`) VALUES( %s )")
670 
671 #define add_file_entry(hdb, values) add_entry(__FILE__, __LINE__, "File", hdb, values, \
672                "INSERT INTO `File` " \
673                "(`File`, `Component_`, `FileName`, `FileSize`, " \
674                "`Version`, `Language`, `Attributes`, `Sequence`) VALUES( %s )")
675 
676 #define add_appsearch_entry(hdb, values) add_entry(__FILE__, __LINE__, "AppSearch", hdb, values, \
677                "INSERT INTO `AppSearch` " \
678                "(`Property`, `Signature_`) VALUES( %s )")
679 
680 #define add_signature_entry(hdb, values) add_entry(__FILE__, __LINE__, "Signature", hdb, values, \
681                "INSERT INTO `Signature` " \
682                "(`Signature`, `FileName`, `MinVersion`, `MaxVersion`," \
683                " `MinSize`, `MaxSize`, `MinDate`, `MaxDate`, `Languages`) " \
684                "VALUES( %s )")
685 
686 #define add_launchcondition_entry(hdb, values) add_entry(__FILE__, __LINE__, "LaunchCondition", hdb, values, \
687                "INSERT INTO `LaunchCondition` " \
688                "(`Condition`, `Description`) VALUES( %s )")
689 
690 #define add_property_entry(hdb, values) add_entry(__FILE__, __LINE__, "Property", hdb, values, \
691                "INSERT INTO `Property` (`Property`, `Value`) VALUES( %s )")
692 
693 #define update_ProductVersion_property(hdb, value) add_entry(__FILE__, __LINE__, "Property", hdb, value, \
694                "UPDATE `Property` SET `Value` = '%s' WHERE `Property` = 'ProductVersion'")
695 
696 #define update_ProductCode_property(hdb, value) add_entry(__FILE__, __LINE__, "Property", hdb, value, \
697                "UPDATE `Property` SET `Value` = '%s' WHERE `Property` = 'ProductCode'")
698 
699 #define add_install_execute_sequence_entry(hdb, values) add_entry(__FILE__, __LINE__, "InstallExecuteSequence", hdb, values, \
700                "INSERT INTO `InstallExecuteSequence` " \
701                "(`Action`, `Condition`, `Sequence`) VALUES( %s )")
702 
703 #define add_install_ui_sequence_entry(hdb, values) add_entry(__FILE__, __LINE__, "InstallUISequence", hdb, values, \
704                "INSERT INTO `InstallUISequence` " \
705                "(`Action`, `Condition`, `Sequence`) VALUES( %s )")
706 
707 #define add_media_entry(hdb, values) add_entry(__FILE__, __LINE__, "Media", hdb, values, \
708                "INSERT INTO `Media` " \
709                "(`DiskId`, `LastSequence`, `DiskPrompt`, " \
710                "`Cabinet`, `VolumeLabel`, `Source`) VALUES( %s )")
711 
712 #define add_ccpsearch_entry(hdb, values) add_entry(__FILE__, __LINE__, "CCPSearch", hdb, values, \
713                "INSERT INTO `CCPSearch` (`Signature_`) VALUES( %s )")
714 
715 #define add_drlocator_entry(hdb, values) add_entry(__FILE__, __LINE__, "DrLocator", hdb, values, \
716                "INSERT INTO `DrLocator` " \
717                "(`Signature_`, `Parent`, `Path`, `Depth`) VALUES( %s )")
718 
719 #define add_complocator_entry(hdb, values) add_entry(__FILE__, __LINE__, "CompLocator", hdb, values, \
720                "INSERT INTO `CompLocator` " \
721                "(`Signature_`, `ComponentId`, `Type`) VALUES( %s )")
722 
723 #define add_inilocator_entry(hdb, values) add_entry(__FILE__, __LINE__, "IniLocator", hdb, values, \
724                "INSERT INTO `IniLocator` " \
725                "(`Signature_`, `FileName`, `Section`, `Key`, `Field`, `Type`) " \
726                "VALUES( %s )")
727 
728 #define add_custom_action_entry(hdb, values) add_entry(__FILE__, __LINE__, "CustomAction", hdb, values, \
729                "INSERT INTO `CustomAction`  " \
730                "(`Action`, `Type`, `Source`, `Target`) VALUES( %s )")
731 
732 #define add_dialog_entry(hdb, values) add_entry(__FILE__, __LINE__, "Dialog", hdb, values, \
733                "INSERT INTO `Dialog` " \
734                "(`Dialog`, `HCentering`, `VCentering`, `Width`, `Height`, `Attributes`, `Control_First`) VALUES ( %s )")
735 
736 #define add_control_entry(hdb, values) add_entry(__FILE__, __LINE__, "Control", hdb, values, \
737                "INSERT INTO `Control` " \
738                "(`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, `Attributes`, `Text`) VALUES( %s )");
739 
740 #define add_controlevent_entry(hdb, values) add_entry(__FILE__, __LINE__, "ControlEvent", hdb, values, \
741                "INSERT INTO `ControlEvent` " \
742                "(`Dialog_`, `Control_`, `Event`, `Argument`, `Condition`, `Ordering`) VALUES( %s )");
743 
744 #define add_actiontext_entry(hdb, values) add_entry(__FILE__, __LINE__, "ActionText", hdb, values, \
745                "INSERT INTO `ActionText` " \
746                "(`Action`, `Description`, `Template`) VALUES( %s )");
747 
748 #define add_upgrade_entry(hdb, values) add_entry(__FILE__, __LINE__, "Upgrade", hdb, values, \
749                "INSERT INTO `Upgrade` " \
750                "(`UpgradeCode`, `VersionMin`, `VersionMax`, `Language`, `Attributes`, `Remove`, `ActionProperty`) VALUES( %s )");
751 
752 static UINT add_reglocator_entry( MSIHANDLE hdb, const char *sig, UINT root, const char *path,
753                                   const char *name, UINT type )
754 {
755     const char insert[] =
756         "INSERT INTO `RegLocator` (`Signature_`, `Root`, `Key`, `Name`, `Type`) "
757         "VALUES( '%s', %u, '%s', '%s', %u )";
758     char *query;
759     UINT sz, r;
760 
761     sz = strlen( sig ) + 10 + strlen( path ) + strlen( name ) + 10 + sizeof( insert );
762     query = malloc( sz );
763     sprintf( query, insert, sig, root, path, name, type );
764     r = run_query( hdb, 0, query );
765     free( query );
766     ok(r == ERROR_SUCCESS, "failed to insert into reglocator table: %u\n", r); \
767     return r;
768 }
769 
770 static UINT set_summary_info(MSIHANDLE hdb)
771 {
772     UINT res;
773     MSIHANDLE suminfo;
774 
775     /* build summary info */
776     res = MsiGetSummaryInformationA(hdb, NULL, 7, &suminfo);
777     ok( res == ERROR_SUCCESS , "Failed to open summaryinfo\n" );
778 
779     res = MsiSummaryInfoSetPropertyA(suminfo,2, VT_LPSTR, 0,NULL,
780                         "Installation Database");
781     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
782 
783     res = MsiSummaryInfoSetPropertyA(suminfo,3, VT_LPSTR, 0,NULL,
784                         "Installation Database");
785     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
786 
787     res = MsiSummaryInfoSetPropertyA(suminfo,4, VT_LPSTR, 0,NULL,
788                         "Wine Hackers");
789     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
790 
791     res = MsiSummaryInfoSetPropertyA(suminfo,7, VT_LPSTR, 0,NULL,
792                     ";1033");
793     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
794 
795     res = MsiSummaryInfoSetPropertyA(suminfo,9, VT_LPSTR, 0,NULL,
796                     "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}");
797     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
798 
799     res = MsiSummaryInfoSetPropertyA(suminfo, 14, VT_I4, 100, NULL, NULL);
800     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
801 
802     res = MsiSummaryInfoSetPropertyA(suminfo, 15, VT_I4, 0, NULL, NULL);
803     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
804 
805     res = MsiSummaryInfoPersist(suminfo);
806     ok( res == ERROR_SUCCESS , "Failed to make summary info persist\n" );
807 
808     res = MsiCloseHandle( suminfo);
809     ok( res == ERROR_SUCCESS , "Failed to close suminfo\n" );
810 
811     return res;
812 }
813 
814 
815 static MSIHANDLE create_package_db(void)
816 {
817     MSIHANDLE hdb = 0;
818     UINT res;
819 
820     DeleteFileA(msifile);
821 
822     /* create an empty database */
823     res = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb );
824     ok( res == ERROR_SUCCESS , "Failed to create database %u\n", res );
825     if( res != ERROR_SUCCESS )
826         return hdb;
827 
828     res = MsiDatabaseCommit( hdb );
829     ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
830 
831     res = set_summary_info(hdb);
832     ok( res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", res);
833 
834     res = run_query( hdb, 0,
835             "CREATE TABLE `Directory` ( "
836             "`Directory` CHAR(255) NOT NULL, "
837             "`Directory_Parent` CHAR(255), "
838             "`DefaultDir` CHAR(255) NOT NULL "
839             "PRIMARY KEY `Directory`)" );
840     ok( res == ERROR_SUCCESS , "Failed to create directory table\n" );
841 
842     return hdb;
843 }
844 
845 static UINT package_from_db(MSIHANDLE hdb, MSIHANDLE *handle)
846 {
847     UINT res;
848     CHAR szPackage[12];
849     MSIHANDLE hPackage;
850 
851     sprintf(szPackage, "#%lu", hdb);
852     res = MsiOpenPackageA(szPackage, &hPackage);
853     if (res != ERROR_SUCCESS)
854     {
855         MsiCloseHandle(hdb);
856         return res;
857     }
858 
859     res = MsiCloseHandle(hdb);
860     if (res != ERROR_SUCCESS)
861     {
862         MsiCloseHandle(hPackage);
863         return res;
864     }
865 
866     *handle = hPackage;
867     return ERROR_SUCCESS;
868 }
869 
870 static void create_test_file(const CHAR *name)
871 {
872     create_file_data(name, name, strlen(name));
873 }
874 
875 typedef struct _tagVS_VERSIONINFO
876 {
877     WORD wLength;
878     WORD wValueLength;
879     WORD wType;
880     WCHAR szKey[1];
881     WORD wPadding1[1];
882     VS_FIXEDFILEINFO Value;
883     WORD wPadding2[1];
884     WORD wChildren[1];
885 } VS_VERSIONINFO;
886 
887 #define roundoffs(a, b, r) (((BYTE *)(b) - (BYTE *)(a) + ((r) - 1)) & ~((r) - 1))
888 #define roundpos(a, b, r) (((BYTE *)(a)) + roundoffs(a, b, r))
889 
890 static BOOL create_file_with_version(const CHAR *name, LONG ms, LONG ls)
891 {
892     VS_VERSIONINFO *pVerInfo;
893     VS_FIXEDFILEINFO *pFixedInfo;
894     LPBYTE buffer, ofs;
895     CHAR path[MAX_PATH];
896     DWORD handle, size;
897     HANDLE resource;
898     BOOL ret = FALSE;
899 
900     GetSystemDirectoryA(path, MAX_PATH);
901     /* Some dlls can't be updated on Vista/W2K8 */
902     lstrcatA(path, "\\version.dll");
903 
904     CopyFileA(path, name, FALSE);
905 
906     size = GetFileVersionInfoSizeA(path, &handle);
907     buffer = malloc(size);
908 
909     GetFileVersionInfoA(path, 0, size, buffer);
910 
911     pVerInfo = (VS_VERSIONINFO *)buffer;
912     ofs = (BYTE *)&pVerInfo->szKey[lstrlenW(pVerInfo->szKey) + 1];
913     pFixedInfo = (VS_FIXEDFILEINFO *)roundpos(pVerInfo, ofs, 4);
914 
915     pFixedInfo->dwFileVersionMS = ms;
916     pFixedInfo->dwFileVersionLS = ls;
917     pFixedInfo->dwProductVersionMS = ms;
918     pFixedInfo->dwProductVersionLS = ls;
919 
920     resource = BeginUpdateResourceA(name, FALSE);
921     if (!resource)
922         goto done;
923 
924     if (!UpdateResourceA(resource, (LPCSTR)RT_VERSION, (LPCSTR)MAKEINTRESOURCE(VS_VERSION_INFO),
925                          MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), buffer, size))
926         goto done;
927 
928     if (!EndUpdateResourceA(resource, FALSE))
929         goto done;
930 
931     ret = TRUE;
932 
933 done:
934     free(buffer);
935     return ret;
936 }
937 
938 static BOOL is_root(const char *path)
939 {
940     return (isalpha(path[0]) && path[1] == ':' && path[2] == '\\' && !path[3]);
941 }
942 
943 static void test_createpackage(void)
944 {
945     MSIHANDLE hPackage = 0;
946     UINT res;
947 
948     res = package_from_db(create_package_db(), &hPackage);
949     if (res == ERROR_INSTALL_PACKAGE_REJECTED)
950     {
951         skip("Not enough rights to perform tests\n");
952         DeleteFileA(msifile);
953         return;
954     }
955     ok( res == ERROR_SUCCESS, " Failed to create package %u\n", res );
956 
957     res = MsiCloseHandle( hPackage);
958     ok( res == ERROR_SUCCESS , "Failed to close package\n" );
959     DeleteFileA(msifile);
960 }
961 
962 static void test_doaction( void )
963 {
964     MSIHANDLE hpkg;
965     UINT r;
966 
967     r = MsiDoActionA( -1, NULL );
968     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
969 
970     r = package_from_db(create_package_db(), &hpkg);
971     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
972     {
973         skip("Not enough rights to perform tests\n");
974         DeleteFileA(msifile);
975         return;
976     }
977     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
978 
979     r = MsiDoActionA(hpkg, NULL);
980     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
981 
982     r = MsiDoActionA(0, "boo");
983     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
984 
985     r = MsiDoActionA(hpkg, "boo");
986     ok( r == ERROR_FUNCTION_NOT_CALLED, "wrong return val\n");
987 
988     MsiCloseHandle( hpkg );
989     DeleteFileA(msifile);
990 }
991 
992 static void test_gettargetpath_bad(void)
993 {
994     char buffer[0x80];
995     WCHAR bufferW[0x80];
996     MSIHANDLE hpkg;
997     DWORD sz;
998     UINT r;
999 
1000     r = package_from_db(create_package_db(), &hpkg);
1001     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1002     {
1003         skip("Not enough rights to perform tests\n");
1004         DeleteFileA(msifile);
1005         return;
1006     }
1007     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1008 
1009     r = MsiGetTargetPathA( 0, NULL, NULL, NULL );
1010     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1011 
1012     r = MsiGetTargetPathA( 0, NULL, NULL, &sz );
1013     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1014 
1015     r = MsiGetTargetPathA( 0, "boo", NULL, NULL );
1016     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1017 
1018     r = MsiGetTargetPathA( 0, "boo", NULL, NULL );
1019     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1020 
1021     r = MsiGetTargetPathA( hpkg, "boo", NULL, NULL );
1022     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1023 
1024     r = MsiGetTargetPathA( hpkg, "boo", buffer, NULL );
1025     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1026 
1027     sz = 0;
1028     r = MsiGetTargetPathA( hpkg, "", buffer, &sz );
1029     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1030 
1031     r = MsiGetTargetPathW( 0, NULL, NULL, NULL );
1032     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1033 
1034     r = MsiGetTargetPathW( 0, NULL, NULL, &sz );
1035     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1036 
1037     r = MsiGetTargetPathW( 0, L"boo", NULL, NULL );
1038     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1039 
1040     r = MsiGetTargetPathW( 0, L"boo", NULL, NULL );
1041     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1042 
1043     r = MsiGetTargetPathW( hpkg, L"boo", NULL, NULL );
1044     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1045 
1046     r = MsiGetTargetPathW( hpkg, L"boo", bufferW, NULL );
1047     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1048 
1049     sz = 0;
1050     r = MsiGetTargetPathW( hpkg, L"", bufferW, &sz );
1051     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1052 
1053     MsiCloseHandle( hpkg );
1054     DeleteFileA(msifile);
1055 }
1056 
1057 static void query_file_path(MSIHANDLE hpkg, LPCSTR file, LPSTR buff)
1058 {
1059     UINT r;
1060     DWORD size;
1061     MSIHANDLE rec;
1062 
1063     rec = MsiCreateRecord( 1 );
1064     ok(rec, "MsiCreate record failed\n");
1065 
1066     r = MsiRecordSetStringA( rec, 0, file );
1067     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
1068 
1069     size = MAX_PATH;
1070     r = MsiFormatRecordA( hpkg, rec, buff, &size );
1071     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
1072 
1073     MsiCloseHandle( rec );
1074 }
1075 
1076 static void test_settargetpath(void)
1077 {
1078     char tempdir[MAX_PATH+8], buffer[MAX_PATH], file[MAX_PATH + 20];
1079     DWORD sz;
1080     MSIHANDLE hpkg;
1081     UINT r;
1082     MSIHANDLE hdb;
1083 
1084     hdb = create_package_db();
1085     ok ( hdb, "failed to create package database\n" );
1086 
1087     add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'" );
1088 
1089     create_component_table( hdb );
1090     add_component_entry( hdb, "'RootComp', '{83e2694d-0864-4124-9323-6d37630912a1}', 'TARGETDIR', 8, '', 'RootFile'" );
1091     add_component_entry( hdb, "'TestComp', '{A3FB59C8-C293-4F7E-B8C5-F0E1D8EEE4E5}', 'TestDir', 0, '', 'TestFile'" );
1092 
1093     create_feature_table( hdb );
1094     add_feature_entry( hdb, "'TestFeature', '', '', '', 0, 1, '', 0" );
1095 
1096     create_feature_components_table( hdb );
1097     add_feature_components_entry( hdb, "'TestFeature', 'RootComp'" );
1098     add_feature_components_entry( hdb, "'TestFeature', 'TestComp'" );
1099 
1100     add_directory_entry( hdb, "'TestParent', 'TARGETDIR', 'TestParent'" );
1101     add_directory_entry( hdb, "'TestDir', 'TestParent', 'TestDir'" );
1102 
1103     create_file_table( hdb );
1104     add_file_entry( hdb, "'RootFile', 'RootComp', 'rootfile.txt', 0, '', '1033', 8192, 1" );
1105     add_file_entry( hdb, "'TestFile', 'TestComp', 'testfile.txt', 0, '', '1033', 8192, 1" );
1106 
1107     r = package_from_db( hdb, &hpkg );
1108     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1109     {
1110         skip("Not enough rights to perform tests\n");
1111         DeleteFileA(msifile);
1112         return;
1113     }
1114     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1115 
1116     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1117 
1118     r = MsiDoActionA( hpkg, "CostInitialize");
1119     ok( r == ERROR_SUCCESS, "cost init failed\n");
1120 
1121     r = MsiDoActionA( hpkg, "FileCost");
1122     ok( r == ERROR_SUCCESS, "file cost failed\n");
1123 
1124     r = MsiDoActionA( hpkg, "CostFinalize");
1125     ok( r == ERROR_SUCCESS, "cost finalize failed\n");
1126 
1127     buffer[0] = 0;
1128     sz = sizeof(buffer);
1129     r = MsiGetPropertyA( hpkg, "OutOfNoRbDiskSpace", buffer, &sz );
1130     ok( r == ERROR_SUCCESS, "MsiGetProperty returned %u\n", r );
1131     trace( "OutOfNoRbDiskSpace = \"%s\"\n", buffer );
1132 
1133     r = MsiSetTargetPathA( 0, NULL, NULL );
1134     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1135 
1136     r = MsiSetTargetPathA( 0, "boo", "C:\\bogusx" );
1137     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1138 
1139     r = MsiSetTargetPathA( hpkg, "boo", NULL );
1140     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1141 
1142     r = MsiSetTargetPathA( hpkg, "boo", "c:\\bogusx" );
1143     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1144 
1145     sz = sizeof tempdir - 1;
1146     r = MsiGetTargetPathA( hpkg, "TARGETDIR", tempdir, &sz );
1147     sprintf( file, "%srootfile.txt", tempdir );
1148     buffer[0] = 0;
1149     query_file_path( hpkg, "[#RootFile]", buffer );
1150     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1151     ok( !lstrcmpA(buffer, file), "Expected %s, got %s\n", file, buffer );
1152 
1153     GetTempFileNameA( tempdir, "_wt", 0, buffer );
1154     sprintf( tempdir, "%s\\subdir", buffer );
1155 
1156     r = MsiSetTargetPathA( hpkg, "TARGETDIR", buffer );
1157     ok( r == ERROR_SUCCESS || r == ERROR_DIRECTORY,
1158         "MsiSetTargetPath on file returned %d\n", r );
1159 
1160     r = MsiSetTargetPathA( hpkg, "TARGETDIR", tempdir );
1161     ok( r == ERROR_SUCCESS || r == ERROR_DIRECTORY,
1162         "MsiSetTargetPath on 'subdir' of file returned %d\n", r );
1163 
1164     DeleteFileA( buffer );
1165 
1166     r = MsiSetTargetPathA( hpkg, "TARGETDIR", buffer );
1167     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1168 
1169     r = GetFileAttributesA( buffer );
1170     ok ( r == INVALID_FILE_ATTRIBUTES, "file/directory exists after MsiSetTargetPath. Attributes: %08X\n", r );
1171 
1172     r = MsiSetTargetPathA( hpkg, "TARGETDIR", tempdir );
1173     ok( r == ERROR_SUCCESS, "MsiSetTargetPath on subsubdir returned %d\n", r );
1174 
1175     buffer[0] = 0;
1176     sz = sizeof buffer - 1;
1177     lstrcatA( tempdir, "\\" );
1178     r = MsiGetTargetPathA( hpkg, "TARGETDIR", buffer, &sz );
1179     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1180     ok( !lstrcmpA(buffer, tempdir), "Expected %s, got %s\n", tempdir, buffer);
1181 
1182     sprintf( file, "%srootfile.txt", tempdir );
1183     query_file_path( hpkg, "[#RootFile]", buffer );
1184     ok( !lstrcmpA(buffer, file), "Expected %s, got %s\n", file, buffer);
1185 
1186     buffer[0] = 0;
1187     sz = sizeof(buffer);
1188     r = MsiGetPropertyA( hpkg, "TestParent", buffer, &sz );
1189     ok( r == ERROR_SUCCESS, "MsiGetProperty returned %u\n", r );
1190     lstrcatA( tempdir, "TestParent\\" );
1191     ok( !lstrcmpiA(buffer, tempdir), "Expected \"%s\", got \"%s\"\n", tempdir, buffer );
1192 
1193     r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\one\\two" );
1194     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1195 
1196     buffer[0] = 0;
1197     sz = sizeof(buffer);
1198     r = MsiGetPropertyA( hpkg, "TestParent", buffer, &sz );
1199     ok( r == ERROR_SUCCESS, "MsiGetProperty returned %u\n", r );
1200     ok( lstrcmpiA(buffer, "C:\\one\\two\\TestDir\\"),
1201         "Expected \"C:\\one\\two\\TestDir\\\", got \"%s\"\n", buffer );
1202 
1203     buffer[0] = 0;
1204     query_file_path( hpkg, "[#TestFile]", buffer );
1205     ok( !lstrcmpiA(buffer, "C:\\one\\two\\TestDir\\testfile.txt"),
1206         "Expected C:\\one\\two\\TestDir\\testfile.txt, got %s\n", buffer );
1207 
1208     buffer[0] = 0;
1209     sz = sizeof buffer - 1;
1210     r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1211     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1212     ok( !lstrcmpiA(buffer, "C:\\one\\two\\"), "Expected C:\\one\\two\\, got %s\n", buffer);
1213 
1214     r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\one\\two\\three" );
1215     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1216 
1217     buffer[0] = 0;
1218     sz = sizeof buffer - 1;
1219     r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1220     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1221     ok( !lstrcmpiA(buffer, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", buffer);
1222 
1223     r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\\\one\\\\two  " );
1224     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1225 
1226     buffer[0] = 0;
1227     sz = sizeof buffer - 1;
1228     r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1229     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1230     ok( !lstrcmpiA(buffer, "C:\\one\\two\\"), "Expected \"C:\\one\\two\\\", got %s\n", buffer);
1231 
1232     r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\\\ Program Files \\\\ " );
1233     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1234 
1235     buffer[0] = 0;
1236     sz = sizeof buffer - 1;
1237     r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1238     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1239     ok( !lstrcmpiA(buffer, "C:\\Program Files\\"), "Expected \"C:\\Program Files\\\", got %s\n", buffer);
1240 
1241     MsiCloseHandle( hpkg );
1242 }
1243 
1244 static void test_condition(void)
1245 {
1246     MSICONDITION r;
1247     MSIHANDLE hpkg;
1248 
1249     r = package_from_db(create_package_db(), &hpkg);
1250     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1251     {
1252         skip("Not enough rights to perform tests\n");
1253         DeleteFileA(msifile);
1254         return;
1255     }
1256     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1257 
1258     r = MsiEvaluateConditionA(0, NULL);
1259     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1260 
1261     r = MsiEvaluateConditionA(hpkg, NULL);
1262     ok( r == MSICONDITION_NONE, "wrong return val\n");
1263 
1264     r = MsiEvaluateConditionA(hpkg, "");
1265     ok( r == MSICONDITION_NONE, "wrong return val\n");
1266 
1267     r = MsiEvaluateConditionA(hpkg, "1");
1268     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1269 
1270     r = MsiEvaluateConditionA(hpkg, "0");
1271     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1272 
1273     r = MsiEvaluateConditionA(hpkg, "-1");
1274     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1275 
1276     r = MsiEvaluateConditionA(hpkg, "0 = 0");
1277     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1278 
1279     r = MsiEvaluateConditionA(hpkg, "0 <> 0");
1280     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1281 
1282     r = MsiEvaluateConditionA(hpkg, "0 = 1");
1283     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1284 
1285     r = MsiEvaluateConditionA(hpkg, "0 > 1");
1286     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1287 
1288     r = MsiEvaluateConditionA(hpkg, "0 ~> 1");
1289     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1290 
1291     r = MsiEvaluateConditionA(hpkg, "1 > 1");
1292     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1293 
1294     r = MsiEvaluateConditionA(hpkg, "1 ~> 1");
1295     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1296 
1297     r = MsiEvaluateConditionA(hpkg, "0 >= 1");
1298     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1299 
1300     r = MsiEvaluateConditionA(hpkg, "0 ~>= 1");
1301     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1302 
1303     r = MsiEvaluateConditionA(hpkg, "1 >= 1");
1304     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1305 
1306     r = MsiEvaluateConditionA(hpkg, "1 ~>= 1");
1307     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1308 
1309     r = MsiEvaluateConditionA(hpkg, "0 < 1");
1310     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1311 
1312     r = MsiEvaluateConditionA(hpkg, "0 ~< 1");
1313     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1314 
1315     r = MsiEvaluateConditionA(hpkg, "1 < 1");
1316     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1317 
1318     r = MsiEvaluateConditionA(hpkg, "1 ~< 1");
1319     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1320 
1321     r = MsiEvaluateConditionA(hpkg, "0 <= 1");
1322     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1323 
1324     r = MsiEvaluateConditionA(hpkg, "0 ~<= 1");
1325     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1326 
1327     r = MsiEvaluateConditionA(hpkg, "1 <= 1");
1328     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1329 
1330     r = MsiEvaluateConditionA(hpkg, "1 ~<= 1");
1331     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1332 
1333     r = MsiEvaluateConditionA(hpkg, "0 >=");
1334     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1335 
1336     r = MsiEvaluateConditionA(hpkg, " ");
1337     ok( r == MSICONDITION_NONE, "wrong return val\n");
1338 
1339     r = MsiEvaluateConditionA(hpkg, "LicView <> \"1\"");
1340     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1341 
1342     r = MsiEvaluateConditionA(hpkg, "LicView <> \"0\"");
1343     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1344 
1345     r = MsiEvaluateConditionA(hpkg, "LicView <> LicView");
1346     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1347 
1348     r = MsiEvaluateConditionA(hpkg, "not 0");
1349     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1350 
1351     r = MsiEvaluateConditionA(hpkg, "not LicView");
1352     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1353 
1354     r = MsiEvaluateConditionA(hpkg, "\"Testing\" ~<< \"Testing\"");
1355     ok (r == MSICONDITION_TRUE, "wrong return val\n");
1356 
1357     r = MsiEvaluateConditionA(hpkg, "LicView ~<< \"Testing\"");
1358     ok (r == MSICONDITION_FALSE, "wrong return val\n");
1359 
1360     r = MsiEvaluateConditionA(hpkg, "Not LicView ~<< \"Testing\"");
1361     ok (r == MSICONDITION_TRUE, "wrong return val\n");
1362 
1363     r = MsiEvaluateConditionA(hpkg, "not \"A\"");
1364     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1365 
1366     r = MsiEvaluateConditionA(hpkg, "~not \"A\"");
1367     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1368 
1369     r = MsiEvaluateConditionA(hpkg, "\"0\"");
1370     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1371 
1372     r = MsiEvaluateConditionA(hpkg, "1 and 2");
1373     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1374 
1375     r = MsiEvaluateConditionA(hpkg, "not 0 and 3");
1376     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1377 
1378     r = MsiEvaluateConditionA(hpkg, "not 0 and 0");
1379     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1380 
1381     r = MsiEvaluateConditionA(hpkg, "not 0 or 1");
1382     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1383 
1384     r = MsiEvaluateConditionA(hpkg, "(0)");
1385     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1386 
1387     r = MsiEvaluateConditionA(hpkg, "(((((1))))))");
1388     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1389 
1390     r = MsiEvaluateConditionA(hpkg, "(((((1)))))");
1391     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1392 
1393     r = MsiEvaluateConditionA(hpkg, " \"A\" < \"B\" ");
1394     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1395 
1396     r = MsiEvaluateConditionA(hpkg, " \"A\" > \"B\" ");
1397     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1398 
1399     r = MsiEvaluateConditionA(hpkg, " \"1\" > \"12\" ");
1400     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1401 
1402     r = MsiEvaluateConditionA(hpkg, " \"100\" < \"21\" ");
1403     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1404 
1405     r = MsiEvaluateConditionA(hpkg, "0 < > 0");
1406     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1407 
1408     r = MsiEvaluateConditionA(hpkg, "(1<<1) == 2");
1409     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1410 
1411     r = MsiEvaluateConditionA(hpkg, " \"A\" = \"a\" ");
1412     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1413 
1414     r = MsiEvaluateConditionA(hpkg, " \"A\" ~ = \"a\" ");
1415     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1416 
1417     r = MsiEvaluateConditionA(hpkg, " \"A\" ~= \"a\" ");
1418     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1419 
1420     r = MsiEvaluateConditionA(hpkg, " \"A\" ~= 1 ");
1421     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1422 
1423     r = MsiEvaluateConditionA(hpkg, " \"A\" = 1 ");
1424     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1425 
1426     r = MsiEvaluateConditionA(hpkg, " 1 ~= 1 ");
1427     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1428 
1429     r = MsiEvaluateConditionA(hpkg, " 1 ~= \"1\" ");
1430     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1431 
1432     r = MsiEvaluateConditionA(hpkg, " 1 = \"1\" ");
1433     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1434 
1435     r = MsiEvaluateConditionA(hpkg, " 0 = \"1\" ");
1436     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1437 
1438     r = MsiEvaluateConditionA(hpkg, " 0 < \"100\" ");
1439     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1440 
1441     r = MsiEvaluateConditionA(hpkg, " 100 > \"0\" ");
1442     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1443 
1444     r = MsiEvaluateConditionA(hpkg, "1 XOR 1");
1445     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1446 
1447     r = MsiEvaluateConditionA(hpkg, "1 IMP 1");
1448     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1449 
1450     r = MsiEvaluateConditionA(hpkg, "1 IMP 0");
1451     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1452 
1453     r = MsiEvaluateConditionA(hpkg, "0 IMP 0");
1454     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1455 
1456     r = MsiEvaluateConditionA(hpkg, "0 EQV 0");
1457     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1458 
1459     r = MsiEvaluateConditionA(hpkg, "0 EQV 1");
1460     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1461 
1462     r = MsiEvaluateConditionA(hpkg, "1 IMP 1 OR 0");
1463     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1464 
1465     r = MsiEvaluateConditionA(hpkg, "1 IMPL 1");
1466     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1467 
1468     r = MsiEvaluateConditionA(hpkg, "\"ASFD\" >< \"S\" ");
1469     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1470 
1471     r = MsiEvaluateConditionA(hpkg, "\"ASFD\" ~>< \"s\" ");
1472     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1473 
1474     r = MsiEvaluateConditionA(hpkg, "\"ASFD\" ~>< \"\" ");
1475     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1476 
1477     r = MsiEvaluateConditionA(hpkg, "\"ASFD\" ~>< \"sss\" ");
1478     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1479 
1480     MsiSetPropertyA(hpkg, "mm", "5" );
1481 
1482     r = MsiEvaluateConditionA(hpkg, "mm = 5");
1483     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1484 
1485     r = MsiEvaluateConditionA(hpkg, "mm < 6");
1486     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1487 
1488     r = MsiEvaluateConditionA(hpkg, "mm <= 5");
1489     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1490 
1491     r = MsiEvaluateConditionA(hpkg, "mm > 4");
1492     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1493 
1494     r = MsiEvaluateConditionA(hpkg, "mm < 12");
1495     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1496 
1497     r = MsiEvaluateConditionA(hpkg, "mm = \"5\"");
1498     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1499 
1500     r = MsiEvaluateConditionA(hpkg, "0 = \"\"");
1501     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1502 
1503     r = MsiEvaluateConditionA(hpkg, "0 AND \"\"");
1504     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1505 
1506     r = MsiEvaluateConditionA(hpkg, "1 AND \"\"");
1507     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1508 
1509     r = MsiEvaluateConditionA(hpkg, "1 AND \"1\"");
1510     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1511 
1512     r = MsiEvaluateConditionA(hpkg, "3 >< 1");
1513     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1514 
1515     r = MsiEvaluateConditionA(hpkg, "3 >< 4");
1516     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1517 
1518     r = MsiEvaluateConditionA(hpkg, "NOT 0 AND 0");
1519     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1520 
1521     r = MsiEvaluateConditionA(hpkg, "NOT 0 AND 1");
1522     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1523 
1524     r = MsiEvaluateConditionA(hpkg, "NOT 1 OR 0");
1525     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1526 
1527     r = MsiEvaluateConditionA(hpkg, "0 AND 1 OR 1");
1528     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1529 
1530     r = MsiEvaluateConditionA(hpkg, "0 AND 0 OR 1");
1531     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1532 
1533     r = MsiEvaluateConditionA(hpkg, "NOT 0 AND 1 OR 0");
1534     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1535 
1536     r = MsiEvaluateConditionA(hpkg, "_1 = _1");
1537     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1538 
1539     r = MsiEvaluateConditionA(hpkg, "( 1 AND 1 ) = 2");
1540     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1541 
1542     r = MsiEvaluateConditionA(hpkg, "NOT ( 1 AND 1 )");
1543     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1544 
1545     r = MsiEvaluateConditionA(hpkg, "NOT A AND (BBBBBBBBBB=2 OR CCC=1) AND Ddddddddd");
1546     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1547 
1548     r = MsiEvaluateConditionA(hpkg, "Installed<>\"\"");
1549     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1550 
1551     r = MsiEvaluateConditionA(hpkg, "NOT 1 AND 0");
1552     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1553 
1554     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1555     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1556 
1557     r = MsiEvaluateConditionA(hpkg, "bandalmael<>0");
1558     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1559 
1560     r = MsiEvaluateConditionA(hpkg, "bandalmael<0");
1561     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1562 
1563     r = MsiEvaluateConditionA(hpkg, "bandalmael>0");
1564     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1565 
1566     r = MsiEvaluateConditionA(hpkg, "bandalmael>=0");
1567     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1568 
1569     r = MsiEvaluateConditionA(hpkg, "bandalmael<=0");
1570     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1571 
1572     r = MsiEvaluateConditionA(hpkg, "bandalmael~<>0");
1573     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1574 
1575     MsiSetPropertyA(hpkg, "bandalmael", "0" );
1576     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1577     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1578 
1579     MsiSetPropertyA(hpkg, "bandalmael", "" );
1580     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1581     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1582 
1583     MsiSetPropertyA(hpkg, "bandalmael", "asdf" );
1584     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1585     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1586 
1587     MsiSetPropertyA(hpkg, "bandalmael", "0asdf" );
1588     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1589     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1590 
1591     MsiSetPropertyA(hpkg, "bandalmael", "0 " );
1592     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1593     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1594 
1595     MsiSetPropertyA(hpkg, "bandalmael", "-0" );
1596     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1597     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1598 
1599     MsiSetPropertyA(hpkg, "bandalmael", "0000000000000" );
1600     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1601     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1602 
1603     MsiSetPropertyA(hpkg, "bandalmael", "--0" );
1604     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1605     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1606 
1607     MsiSetPropertyA(hpkg, "bandalmael", "0x00" );
1608     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1609     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1610 
1611     MsiSetPropertyA(hpkg, "bandalmael", "-" );
1612     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1613     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1614 
1615     MsiSetPropertyA(hpkg, "bandalmael", "+0" );
1616     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1617     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1618 
1619     MsiSetPropertyA(hpkg, "bandalmael", "0.0" );
1620     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1621     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1622     r = MsiEvaluateConditionA(hpkg, "bandalmael<>0");
1623     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1624 
1625     MsiSetPropertyA(hpkg, "one", "hi");
1626     MsiSetPropertyA(hpkg, "two", "hithere");
1627     r = MsiEvaluateConditionA(hpkg, "one >< two");
1628     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1629 
1630     MsiSetPropertyA(hpkg, "one", "hithere");
1631     MsiSetPropertyA(hpkg, "two", "hi");
1632     r = MsiEvaluateConditionA(hpkg, "one >< two");
1633     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1634 
1635     MsiSetPropertyA(hpkg, "one", "hello");
1636     MsiSetPropertyA(hpkg, "two", "hi");
1637     r = MsiEvaluateConditionA(hpkg, "one >< two");
1638     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1639 
1640     MsiSetPropertyA(hpkg, "one", "hellohithere");
1641     MsiSetPropertyA(hpkg, "two", "hi");
1642     r = MsiEvaluateConditionA(hpkg, "one >< two");
1643     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1644 
1645     MsiSetPropertyA(hpkg, "one", "");
1646     MsiSetPropertyA(hpkg, "two", "hi");
1647     r = MsiEvaluateConditionA(hpkg, "one >< two");
1648     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1649 
1650     MsiSetPropertyA(hpkg, "one", "hi");
1651     MsiSetPropertyA(hpkg, "two", "");
1652     r = MsiEvaluateConditionA(hpkg, "one >< two");
1653     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1654 
1655     MsiSetPropertyA(hpkg, "one", "");
1656     MsiSetPropertyA(hpkg, "two", "");
1657     r = MsiEvaluateConditionA(hpkg, "one >< two");
1658     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1659 
1660     MsiSetPropertyA(hpkg, "one", "1234");
1661     MsiSetPropertyA(hpkg, "two", "1");
1662     r = MsiEvaluateConditionA(hpkg, "one >< two");
1663     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1664 
1665     MsiSetPropertyA(hpkg, "one", "one 1234");
1666     MsiSetPropertyA(hpkg, "two", "1");
1667     r = MsiEvaluateConditionA(hpkg, "one >< two");
1668     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1669 
1670     MsiSetPropertyA(hpkg, "one", "hithere");
1671     MsiSetPropertyA(hpkg, "two", "hi");
1672     r = MsiEvaluateConditionA(hpkg, "one << two");
1673     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1674 
1675     MsiSetPropertyA(hpkg, "one", "hi");
1676     MsiSetPropertyA(hpkg, "two", "hithere");
1677     r = MsiEvaluateConditionA(hpkg, "one << two");
1678     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1679 
1680     MsiSetPropertyA(hpkg, "one", "hi");
1681     MsiSetPropertyA(hpkg, "two", "hi");
1682     r = MsiEvaluateConditionA(hpkg, "one << two");
1683     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1684 
1685     MsiSetPropertyA(hpkg, "one", "abcdhithere");
1686     MsiSetPropertyA(hpkg, "two", "hi");
1687     r = MsiEvaluateConditionA(hpkg, "one << two");
1688     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1689 
1690     MsiSetPropertyA(hpkg, "one", "");
1691     MsiSetPropertyA(hpkg, "two", "hi");
1692     r = MsiEvaluateConditionA(hpkg, "one << two");
1693     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1694 
1695     MsiSetPropertyA(hpkg, "one", "hithere");
1696     MsiSetPropertyA(hpkg, "two", "");
1697     r = MsiEvaluateConditionA(hpkg, "one << two");
1698     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1699 
1700     MsiSetPropertyA(hpkg, "one", "");
1701     MsiSetPropertyA(hpkg, "two", "");
1702     r = MsiEvaluateConditionA(hpkg, "one << two");
1703     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1704 
1705     MsiSetPropertyA(hpkg, "one", "1234");
1706     MsiSetPropertyA(hpkg, "two", "1");
1707     r = MsiEvaluateConditionA(hpkg, "one << two");
1708     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1709 
1710     MsiSetPropertyA(hpkg, "one", "1234 one");
1711     MsiSetPropertyA(hpkg, "two", "1");
1712     r = MsiEvaluateConditionA(hpkg, "one << two");
1713     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1714 
1715     MsiSetPropertyA(hpkg, "one", "hithere");
1716     MsiSetPropertyA(hpkg, "two", "there");
1717     r = MsiEvaluateConditionA(hpkg, "one >> two");
1718     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1719 
1720     MsiSetPropertyA(hpkg, "one", "hithere");
1721     MsiSetPropertyA(hpkg, "two", "hi");
1722     r = MsiEvaluateConditionA(hpkg, "one >> two");
1723     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1724 
1725     MsiSetPropertyA(hpkg, "one", "there");
1726     MsiSetPropertyA(hpkg, "two", "hithere");
1727     r = MsiEvaluateConditionA(hpkg, "one >> two");
1728     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1729 
1730     MsiSetPropertyA(hpkg, "one", "there");
1731     MsiSetPropertyA(hpkg, "two", "there");
1732     r = MsiEvaluateConditionA(hpkg, "one >> two");
1733     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1734 
1735     MsiSetPropertyA(hpkg, "one", "abcdhithere");
1736     MsiSetPropertyA(hpkg, "two", "hi");
1737     r = MsiEvaluateConditionA(hpkg, "one >> two");
1738     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1739 
1740     MsiSetPropertyA(hpkg, "one", "");
1741     MsiSetPropertyA(hpkg, "two", "there");
1742     r = MsiEvaluateConditionA(hpkg, "one >> two");
1743     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1744 
1745     MsiSetPropertyA(hpkg, "one", "there");
1746     MsiSetPropertyA(hpkg, "two", "");
1747     r = MsiEvaluateConditionA(hpkg, "one >> two");
1748     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1749 
1750     MsiSetPropertyA(hpkg, "one", "");
1751     MsiSetPropertyA(hpkg, "two", "");
1752     r = MsiEvaluateConditionA(hpkg, "one >> two");
1753     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1754 
1755     MsiSetPropertyA(hpkg, "one", "1234");
1756     MsiSetPropertyA(hpkg, "two", "4");
1757     r = MsiEvaluateConditionA(hpkg, "one >> two");
1758     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1759 
1760     MsiSetPropertyA(hpkg, "one", "one 1234");
1761     MsiSetPropertyA(hpkg, "two", "4");
1762     r = MsiEvaluateConditionA(hpkg, "one >> two");
1763     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1764 
1765     MsiSetPropertyA(hpkg, "MsiNetAssemblySupport", NULL);  /* make sure it's empty */
1766 
1767     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322\"");
1768     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1769 
1770     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport > \"1.1.4322\"");
1771     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1772 
1773     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport >= \"1.1.4322\"");
1774     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1775 
1776     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport <= \"1.1.4322\"");
1777     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1778 
1779     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport <> \"1.1.4322\"");
1780     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1781 
1782     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport ~< \"1.1.4322\"");
1783     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1784 
1785     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"abcd\"");
1786     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1787 
1788     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a1.1.4322\"");
1789     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1790 
1791     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322a\"");
1792     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1793 
1794     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"0000001.1.4322\"");
1795     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1796 
1797     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322.1\"");
1798     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1799 
1800     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322.1.1\"");
1801     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1802 
1803     r = MsiEvaluateConditionA(hpkg, "\"2\" < \"1.1");
1804     ok( r == MSICONDITION_ERROR, "wrong return val (%d)\n", r);
1805 
1806     r = MsiEvaluateConditionA(hpkg, "\"2\" < \"1.1\"");
1807     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1808 
1809     r = MsiEvaluateConditionA(hpkg, "\"2\" < \"12.1\"");
1810     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1811 
1812     r = MsiEvaluateConditionA(hpkg, "\"02.1\" < \"2.11\"");
1813     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1814 
1815     r = MsiEvaluateConditionA(hpkg, "\"02.1.1\" < \"2.1\"");
1816     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1817 
1818     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1\"");
1819     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1820 
1821     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1\"");
1822     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1823 
1824     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"0\"");
1825     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1826 
1827     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"-1\"");
1828     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1829 
1830     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a\"");
1831     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1832 
1833     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"!\"");
1834     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1835 
1836     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"!\"");
1837     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1838 
1839     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"/\"");
1840     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1841 
1842     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \" \"");
1843     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1844 
1845     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"azAZ_\"");
1846     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1847 
1848     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a[a]\"");
1849     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1850 
1851     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a[a]a\"");
1852     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1853 
1854     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"[a]\"");
1855     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1856 
1857     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"[a]a\"");
1858     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1859 
1860     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"{a}\"");
1861     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1862 
1863     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"{a\"");
1864     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1865 
1866     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"[a\"");
1867     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1868 
1869     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a{\"");
1870     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1871 
1872     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a]\"");
1873     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1874 
1875     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"A\"");
1876     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1877 
1878     MsiSetPropertyA(hpkg, "MsiNetAssemblySupport", "1.1.4322");
1879     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322\"");
1880     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1881 
1882     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.14322\"");
1883     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1884 
1885     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.5\"");
1886     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1887 
1888     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1\"");
1889     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1890 
1891     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1\"");
1892     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1893 
1894     MsiSetPropertyA(hpkg, "one", "1");
1895     r = MsiEvaluateConditionA(hpkg, "one < \"1\"");
1896     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1897 
1898     MsiSetPropertyA(hpkg, "X", "5.0");
1899 
1900     r = MsiEvaluateConditionA(hpkg, "X != \"\"");
1901     ok( r == MSICONDITION_ERROR, "wrong return val (%d)\n", r);
1902 
1903     r = MsiEvaluateConditionA(hpkg, "X =\"5.0\"");
1904     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1905 
1906     r = MsiEvaluateConditionA(hpkg, "X =\"5.1\"");
1907     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1908 
1909     r = MsiEvaluateConditionA(hpkg, "X =\"6.0\"");
1910     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1911 
1912     r = MsiEvaluateConditionA(hpkg, "X =\"5.0\" or X =\"5.1\" or X =\"6.0\"");
1913     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1914 
1915     r = MsiEvaluateConditionA(hpkg, "(X =\"5.0\" or X =\"5.1\" or X =\"6.0\")");
1916     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1917 
1918     r = MsiEvaluateConditionA(hpkg, "X !=\"\" and (X =\"5.0\" or X =\"5.1\" or X =\"6.0\")");
1919     ok( r == MSICONDITION_ERROR, "wrong return val (%d)\n", r);
1920 
1921     /* feature doesn't exist */
1922     r = MsiEvaluateConditionA(hpkg, "&nofeature");
1923     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1924     r = MsiEvaluateConditionA(hpkg, "&nofeature=\"\"");
1925     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1926     r = MsiEvaluateConditionA(hpkg, "&nofeature<>3");
1927     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1928     r = MsiEvaluateConditionA(hpkg, "\"\"<>3");
1929     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1930     r = MsiEvaluateConditionA(hpkg, "!nofeature=\"\"");
1931     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1932     r = MsiEvaluateConditionA(hpkg, "$nocomponent=\"\"");
1933     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1934     r = MsiEvaluateConditionA(hpkg, "?nocomponent=\"\"");
1935     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1936 
1937     MsiSetPropertyA(hpkg, "A", "2");
1938     MsiSetPropertyA(hpkg, "X", "50");
1939 
1940     r = MsiEvaluateConditionA(hpkg, "2 <= X");
1941     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1942 
1943     r = MsiEvaluateConditionA(hpkg, "A <= X");
1944     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1945 
1946     r = MsiEvaluateConditionA(hpkg, "A <= 50");
1947     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1948 
1949     MsiSetPropertyA(hpkg, "X", "50val");
1950 
1951     r = MsiEvaluateConditionA(hpkg, "2 <= X");
1952     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1953 
1954     r = MsiEvaluateConditionA(hpkg, "A <= X");
1955     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1956 
1957     MsiSetPropertyA(hpkg, "A", "7");
1958     MsiSetPropertyA(hpkg, "X", "50");
1959 
1960     r = MsiEvaluateConditionA(hpkg, "7 <= X");
1961     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1962 
1963     r = MsiEvaluateConditionA(hpkg, "A <= X");
1964     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1965 
1966     r = MsiEvaluateConditionA(hpkg, "A <= 50");
1967     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1968 
1969     MsiSetPropertyA(hpkg, "X", "50val");
1970 
1971     r = MsiEvaluateConditionA(hpkg, "2 <= X");
1972     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1973 
1974     r = MsiEvaluateConditionA(hpkg, "A <= X");
1975     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1976 
1977     r = MsiEvaluateConditionW(hpkg, L"\"a\x30a\"<\"\xe5\"");
1978     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1979 
1980     r = MsiEvaluateConditionW(hpkg, L"\"a\x30a\">\"\xe5\"");
1981     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1982 
1983     r = MsiEvaluateConditionW(hpkg, L"\"a\x30a\"<>\"\xe5\"");
1984     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1985 
1986     r = MsiEvaluateConditionW(hpkg, L"\"a\x30a\"=\"\xe5\"");
1987     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1988 
1989     MsiCloseHandle( hpkg );
1990     DeleteFileA(msifile);
1991 }
1992 
1993 static void check_prop(MSIHANDLE hpkg, const char *prop, const char *expect, int match_case, int todo_value)
1994 {
1995     char buffer[MAX_PATH] = "x";
1996     DWORD sz = sizeof(buffer);
1997     UINT r = MsiGetPropertyA(hpkg, prop, buffer, &sz);
1998     ok(!r, "'%s': got %u\n", prop, r);
1999     ok(sz == lstrlenA(buffer), "'%s': expected %u, got %lu\n", prop, lstrlenA(buffer), sz);
2000     if (match_case)
2001         todo_wine_if (todo_value) ok(!strcmp(buffer, expect), "'%s': expected '%s', got '%s'\n", prop, expect, buffer);
2002     else
2003         todo_wine_if (todo_value) ok(!_stricmp(buffer, expect), "'%s': expected '%s', got '%s'\n", prop, expect, buffer);
2004 }
2005 
2006 static void test_props(void)
2007 {
2008     MSIHANDLE hpkg, hdb;
2009     UINT r;
2010     DWORD sz;
2011     char buffer[0x100];
2012     WCHAR bufferW[10];
2013 
2014     hdb = create_package_db();
2015 
2016     create_property_table(hdb);
2017     add_property_entry(hdb, "'MetadataCompName', 'Photoshop.dll'");
2018 
2019     r = package_from_db( hdb, &hpkg );
2020     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2021     {
2022         skip("Not enough rights to perform tests\n");
2023         DeleteFileA(msifile);
2024         return;
2025     }
2026     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
2027 
2028     /* test invalid values */
2029     r = MsiGetPropertyA( 0, NULL, NULL, NULL );
2030     ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
2031 
2032     r = MsiGetPropertyA( hpkg, NULL, NULL, NULL );
2033     ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
2034 
2035     r = MsiGetPropertyA( hpkg, "boo", NULL, NULL );
2036     ok(!r, "got %u\n", r);
2037 
2038     r = MsiGetPropertyA( hpkg, "boo", buffer, NULL );
2039     ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
2040 
2041     /* test retrieving an empty/nonexistent property */
2042     sz = sizeof buffer;
2043     r = MsiGetPropertyA( hpkg, "boo", NULL, &sz );
2044     ok(!r, "got %u\n", r);
2045     ok(sz == 0, "got size %lu\n", sz);
2046 
2047     sz = 0;
2048     strcpy(buffer,"x");
2049     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2050     ok(r == ERROR_MORE_DATA, "got %u\n", r);
2051     ok(!strcmp(buffer,"x"), "got \"%s\"\n", buffer);
2052     ok(sz == 0, "got size %lu\n", sz);
2053 
2054     sz = 1;
2055     strcpy(buffer,"x");
2056     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2057     ok(!r, "got %u\n", r);
2058     ok(!buffer[0], "got \"%s\"\n", buffer);
2059     ok(sz == 0, "got size %lu\n", sz);
2060 
2061     /* set the property to something */
2062     r = MsiSetPropertyA( 0, NULL, NULL );
2063     ok(r == ERROR_INVALID_HANDLE, "got %u\n", r);
2064 
2065     r = MsiSetPropertyA( hpkg, NULL, NULL );
2066     ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
2067 
2068     r = MsiSetPropertyA( hpkg, "", NULL );
2069     ok(!r, "got %u\n", r);
2070 
2071     r = MsiSetPropertyA( hpkg, "", "asdf" );
2072     ok(r == ERROR_FUNCTION_FAILED, "got %u\n", r);
2073 
2074     r = MsiSetPropertyA( hpkg, "=", "asdf" );
2075     ok(!r, "got %u\n", r);
2076     check_prop(hpkg, "=", "asdf", 1, 0);
2077 
2078     r = MsiSetPropertyA( hpkg, " ", "asdf" );
2079     ok(!r, "got %u\n", r);
2080     check_prop(hpkg, " ", "asdf", 1, 0);
2081 
2082     r = MsiSetPropertyA( hpkg, "'", "asdf" );
2083     ok(!r, "got %u\n", r);
2084     check_prop(hpkg, "'", "asdf", 1, 0);
2085 
2086     /* set empty values */
2087     r = MsiSetPropertyA( hpkg, "boo", NULL );
2088     ok(!r, "got %u\n", r);
2089     check_prop(hpkg, "boo", "", 1, 0);
2090 
2091     r = MsiSetPropertyA( hpkg, "boo", "" );
2092     ok(!r, "got %u\n", r);
2093     check_prop(hpkg, "boo", "", 1, 0);
2094 
2095     /* set a non-empty value */
2096     r = MsiSetPropertyA( hpkg, "boo", "xyz" );
2097     ok(!r, "got %u\n", r);
2098     check_prop(hpkg, "boo", "xyz", 1, 0);
2099 
2100     r = MsiGetPropertyA(hpkg, "boo", NULL, NULL);
2101     ok(!r, "got %u\n", r);
2102 
2103     r = MsiGetPropertyA(hpkg, "boo", buffer, NULL);
2104     ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
2105 
2106     sz = 0;
2107     r = MsiGetPropertyA(hpkg, "boo", NULL, &sz);
2108     ok(!r, "got %u\n", r);
2109     ok(sz == 3, "got size %lu\n", sz);
2110 
2111     sz = 0;
2112     strcpy(buffer, "q");
2113     r = MsiGetPropertyA(hpkg, "boo", buffer, &sz);
2114     ok(r == ERROR_MORE_DATA, "got %u\n", r);
2115     ok(!strcmp(buffer, "q"), "got \"%s\"", buffer);
2116     ok(sz == 3, "got size %lu\n", sz);
2117 
2118     sz = 1;
2119     strcpy(buffer,"x");
2120     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2121     ok(r == ERROR_MORE_DATA, "got %u\n", r);
2122     ok(!buffer[0], "got \"%s\"\n", buffer);
2123     ok(sz == 3, "got size %lu\n", sz);
2124 
2125     sz = 3;
2126     strcpy(buffer,"x");
2127     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2128     ok(r == ERROR_MORE_DATA, "got %u\n", r);
2129     ok(!strcmp(buffer,"xy"), "got \"%s\"\n", buffer);
2130     ok(sz == 3, "got size %lu\n", sz);
2131 
2132     sz = 4;
2133     strcpy(buffer,"x");
2134     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2135     ok(!r, "got %u\n", r);
2136     ok(!strcmp(buffer,"xyz"), "got \"%s\"\n", buffer);
2137     ok(sz == 3, "got size %lu\n", sz);
2138 
2139     sz = 0;
2140     r = MsiGetPropertyW(hpkg, L"boo", NULL, &sz);
2141     ok(!r, "got %u\n", r);
2142     ok(sz == 3, "got size %lu\n", sz);
2143 
2144     sz = 0;
2145     lstrcpyW(bufferW, L"boo");
2146     r = MsiGetPropertyW(hpkg, L"boo", bufferW, &sz);
2147     ok(r == ERROR_MORE_DATA, "got %u\n", r);
2148     ok(!lstrcmpW(bufferW, L"boo"), "got %s\n", wine_dbgstr_w(bufferW));
2149     ok(sz == 3, "got size %lu\n", sz);
2150 
2151     sz = 1;
2152     lstrcpyW(bufferW, L"boo");
2153     r = MsiGetPropertyW(hpkg, L"boo", bufferW, &sz );
2154     ok(r == ERROR_MORE_DATA, "got %u\n", r);
2155     ok(!bufferW[0], "got %s\n", wine_dbgstr_w(bufferW));
2156     ok(sz == 3, "got size %lu\n", sz);
2157 
2158     sz = 3;
2159     lstrcpyW(bufferW, L"boo");
2160     r = MsiGetPropertyW(hpkg, L"boo", bufferW, &sz );
2161     ok(r == ERROR_MORE_DATA, "got %u\n", r);
2162     ok(!lstrcmpW(bufferW, L"xy"), "got %s\n", wine_dbgstr_w(bufferW));
2163     ok(sz == 3, "got size %lu\n", sz);
2164 
2165     sz = 4;
2166     lstrcpyW(bufferW, L"boo");
2167     r = MsiGetPropertyW(hpkg, L"boo", bufferW, &sz );
2168     ok(!r, "got %u\n", r);
2169     ok(!lstrcmpW(bufferW, L"xyz"), "got %s\n", wine_dbgstr_w(bufferW));
2170     ok(sz == 3, "got size %lu\n", sz);
2171 
2172     /* properties are case-sensitive */
2173     check_prop(hpkg, "BOO", "", 1, 0);
2174 
2175     /* properties set in Property table should work */
2176     check_prop(hpkg, "MetadataCompName", "Photoshop.dll", 1, 0);
2177 
2178     MsiCloseHandle( hpkg );
2179     DeleteFileA(msifile);
2180 }
2181 
2182 static BOOL find_prop_in_property(MSIHANDLE hdb, LPCSTR prop, LPCSTR val, int len)
2183 {
2184     MSIHANDLE hview, hrec;
2185     BOOL found = FALSE;
2186     CHAR buffer[MAX_PATH];
2187     DWORD sz;
2188     UINT r;
2189 
2190     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Property`", &hview);
2191     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
2192     r = MsiViewExecute(hview, 0);
2193     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
2194 
2195     if (len < 0) len = lstrlenA(val);
2196 
2197     while (r == ERROR_SUCCESS && !found)
2198     {
2199         r = MsiViewFetch(hview, &hrec);
2200         if (r != ERROR_SUCCESS) break;
2201 
2202         sz = MAX_PATH;
2203         r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
2204         if (r == ERROR_SUCCESS && !lstrcmpA(buffer, prop))
2205         {
2206             sz = MAX_PATH;
2207             r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
2208             if (r == ERROR_SUCCESS && !memcmp(buffer, val, len) && !buffer[len])
2209             {
2210                 ok(sz == len, "wrong size %lu\n", sz);
2211                 found = TRUE;
2212             }
2213         }
2214 
2215         MsiCloseHandle(hrec);
2216     }
2217     MsiViewClose(hview);
2218     MsiCloseHandle(hview);
2219     return found;
2220 }
2221 
2222 static void test_property_table(void)
2223 {
2224     const char *query;
2225     UINT r;
2226     MSIHANDLE hpkg, hdb, hrec;
2227     char buffer[MAX_PATH], package[10];
2228     DWORD sz;
2229     BOOL found;
2230 
2231     hdb = create_package_db();
2232     ok( hdb, "failed to create package\n");
2233 
2234     r = package_from_db(hdb, &hpkg);
2235     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2236     {
2237         skip("Not enough rights to perform tests\n");
2238         DeleteFileA(msifile);
2239         return;
2240     }
2241     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
2242 
2243     MsiCloseHandle(hdb);
2244 
2245     hdb = MsiGetActiveDatabase(hpkg);
2246 
2247     query = "CREATE TABLE `_Property` ( "
2248         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
2249     r = run_query(hdb, 0, query);
2250     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2251 
2252     MsiCloseHandle(hdb);
2253     MsiCloseHandle(hpkg);
2254     DeleteFileA(msifile);
2255 
2256     hdb = create_package_db();
2257     ok( hdb, "failed to create package\n");
2258 
2259     query = "CREATE TABLE `_Property` ( "
2260         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
2261     r = run_query(hdb, 0, query);
2262     ok(r == ERROR_SUCCESS, "failed to create table\n");
2263 
2264     query = "ALTER `_Property` ADD `foo` INTEGER";
2265     r = run_query(hdb, 0, query);
2266     ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to add column\n");
2267 
2268     query = "ALTER TABLE `_Property` ADD `foo` INTEGER";
2269     r = run_query(hdb, 0, query);
2270     ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to add column\n");
2271 
2272     query = "ALTER TABLE `_Property` ADD `extra` INTEGER";
2273     r = run_query(hdb, 0, query);
2274     ok(r == ERROR_SUCCESS, "failed to add column\n");
2275 
2276     sprintf(package, "#%lu", hdb);
2277     r = MsiOpenPackageA(package, &hpkg);
2278     ok(r != ERROR_SUCCESS, "MsiOpenPackage succeeded\n");
2279     if (r == ERROR_SUCCESS)
2280         MsiCloseHandle(hpkg);
2281 
2282     r = MsiCloseHandle(hdb);
2283     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed %u\n", r);
2284 
2285     hdb = create_package_db();
2286     ok (hdb, "failed to create package database\n");
2287 
2288     create_property_table(hdb);
2289     add_property_entry(hdb, "'prop', 'val'");
2290 
2291     create_custom_action_table(hdb);
2292     add_custom_action_entry( hdb, "'EmbedNull', 51, 'prop2', '[~]np'" );
2293 
2294     r = package_from_db(hdb, &hpkg);
2295     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
2296 
2297     MsiCloseHandle(hdb);
2298 
2299     sz = MAX_PATH;
2300     r = MsiGetPropertyA(hpkg, "prop", buffer, &sz);
2301     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2302     ok(!lstrcmpA(buffer, "val"), "Expected val, got %s\n", buffer);
2303 
2304     hdb = MsiGetActiveDatabase(hpkg);
2305 
2306     found = find_prop_in_property(hdb, "prop", "val", -1);
2307     ok(found, "prop should be in the _Property table\n");
2308 
2309     add_property_entry(hdb, "'dantes', 'mercedes'");
2310 
2311     query = "SELECT * FROM `_Property` WHERE `Property` = 'dantes'";
2312     r = do_query(hdb, query, &hrec);
2313     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2314 
2315     found = find_prop_in_property(hdb, "dantes", "mercedes", -1);
2316     ok(found == FALSE, "dantes should not be in the _Property table\n");
2317 
2318     sz = MAX_PATH;
2319     lstrcpyA(buffer, "aaa");
2320     r = MsiGetPropertyA(hpkg, "dantes", buffer, &sz);
2321     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2322     ok(!buffer[0], "Expected empty string, got %s\n", buffer);
2323 
2324     r = MsiSetPropertyA(hpkg, "dantes", "mercedes");
2325     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2326 
2327     found = find_prop_in_property(hdb, "dantes", "mercedes", -1);
2328     ok(found == TRUE, "dantes should be in the _Property table\n");
2329 
2330     r = MsiDoActionA( hpkg, "EmbedNull" );
2331     ok( r == ERROR_SUCCESS, "EmbedNull failed: %d\n", r);
2332 
2333     sz = MAX_PATH;
2334     memset( buffer, 'a', sizeof(buffer) );
2335     r = MsiGetPropertyA( hpkg, "prop2", buffer, &sz );
2336     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2337     ok( !memcmp( buffer, "\0np", sizeof("\0np") ), "wrong value\n");
2338     ok( sz == sizeof("\0np") - 1, "got %lu\n", sz );
2339 
2340     found = find_prop_in_property(hdb, "prop2", "\0np", 3);
2341     ok(found == TRUE, "prop2 should be in the _Property table\n");
2342 
2343     MsiCloseHandle(hdb);
2344     MsiCloseHandle(hpkg);
2345     DeleteFileA(msifile);
2346 }
2347 
2348 static UINT try_query_param( MSIHANDLE hdb, LPCSTR szQuery, MSIHANDLE hrec )
2349 {
2350     MSIHANDLE htab = 0;
2351     UINT res;
2352 
2353     res = MsiDatabaseOpenViewA( hdb, szQuery, &htab );
2354     if( res == ERROR_SUCCESS )
2355     {
2356         UINT r;
2357 
2358         r = MsiViewExecute( htab, hrec );
2359         if( r != ERROR_SUCCESS )
2360         {
2361             res = r;
2362             fprintf(stderr,"MsiViewExecute failed %08x\n", res);
2363         }
2364 
2365         r = MsiViewClose( htab );
2366         if( r != ERROR_SUCCESS )
2367             res = r;
2368 
2369         r = MsiCloseHandle( htab );
2370         if( r != ERROR_SUCCESS )
2371             res = r;
2372     }
2373     return res;
2374 }
2375 
2376 static UINT try_query( MSIHANDLE hdb, LPCSTR szQuery )
2377 {
2378     return try_query_param( hdb, szQuery, 0 );
2379 }
2380 
2381 static void set_summary_str(MSIHANDLE hdb, DWORD pid, LPCSTR value)
2382 {
2383     MSIHANDLE summary;
2384     UINT r;
2385 
2386     r = MsiGetSummaryInformationA(hdb, NULL, 1, &summary);
2387     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2388 
2389     r = MsiSummaryInfoSetPropertyA(summary, pid, VT_LPSTR, 0, NULL, value);
2390     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2391 
2392     r = MsiSummaryInfoPersist(summary);
2393     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2394 
2395     MsiCloseHandle(summary);
2396 }
2397 
2398 static void set_summary_dword(MSIHANDLE hdb, DWORD pid, DWORD value)
2399 {
2400     MSIHANDLE summary;
2401     UINT r;
2402 
2403     r = MsiGetSummaryInformationA(hdb, NULL, 1, &summary);
2404     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2405 
2406     r = MsiSummaryInfoSetPropertyA(summary, pid, VT_I4, value, NULL, NULL);
2407     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2408 
2409     r = MsiSummaryInfoPersist(summary);
2410     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2411 
2412     MsiCloseHandle(summary);
2413 }
2414 
2415 static void test_msipackage(void)
2416 {
2417     MSIHANDLE hdb = 0, hpack = 100;
2418     UINT r;
2419     const char *query;
2420     char name[10];
2421 
2422     /* NULL szPackagePath */
2423     r = MsiOpenPackageA(NULL, &hpack);
2424     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2425 
2426     /* empty szPackagePath */
2427     r = MsiOpenPackageA("", &hpack);
2428     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2429     {
2430         skip("Not enough rights to perform tests\n");
2431         return;
2432     }
2433     todo_wine
2434     {
2435         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2436     }
2437 
2438     if (r == ERROR_SUCCESS)
2439         MsiCloseHandle(hpack);
2440 
2441     /* nonexistent szPackagePath */
2442     r = MsiOpenPackageA("nonexistent", &hpack);
2443     ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
2444 
2445     /* NULL hProduct */
2446     r = MsiOpenPackageA(msifile, NULL);
2447     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2448 
2449     name[0]='#';
2450     name[1]=0;
2451     r = MsiOpenPackageA(name, &hpack);
2452     ok(r == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", r);
2453 
2454     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
2455     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2456 
2457     /* database exists, but is empty */
2458     sprintf(name, "#%lu", hdb);
2459     r = MsiOpenPackageA(name, &hpack);
2460     ok(r == ERROR_INSTALL_PACKAGE_INVALID,
2461        "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
2462 
2463     query = "CREATE TABLE `Property` ( "
2464             "`Property` CHAR(72), `Value` CHAR(0) "
2465             "PRIMARY KEY `Property`)";
2466     r = try_query(hdb, query);
2467     ok(r == ERROR_SUCCESS, "failed to create Properties table\n");
2468 
2469     query = "CREATE TABLE `InstallExecuteSequence` ("
2470             "`Action` CHAR(72), `Condition` CHAR(0), `Sequence` INTEGER "
2471             "PRIMARY KEY `Action`)";
2472     r = try_query(hdb, query);
2473     ok(r == ERROR_SUCCESS, "failed to create InstallExecuteSequence table\n");
2474 
2475     /* a few key tables exist */
2476     sprintf(name, "#%lu", hdb);
2477     r = MsiOpenPackageA(name, &hpack);
2478     ok(r == ERROR_INSTALL_PACKAGE_INVALID,
2479        "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
2480 
2481     MsiCloseHandle(hdb);
2482     DeleteFileA(msifile);
2483 
2484     /* start with a clean database to show what constitutes a valid package */
2485     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
2486     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2487 
2488     sprintf(name, "#%lu", hdb);
2489 
2490     /* The following summary information props must exist:
2491      *  - PID_REVNUMBER
2492      *  - PID_PAGECOUNT
2493      */
2494 
2495     set_summary_dword(hdb, PID_PAGECOUNT, 100);
2496     r = MsiOpenPackageA(name, &hpack);
2497     ok(r == ERROR_INSTALL_PACKAGE_INVALID,
2498        "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
2499 
2500     set_summary_str(hdb, PID_REVNUMBER, "{004757CD-5092-49C2-AD20-28E1CE0DF5F2}");
2501     r = MsiOpenPackageA(name, &hpack);
2502     ok(r == ERROR_SUCCESS,
2503        "Expected ERROR_SUCCESS, got %d\n", r);
2504 
2505     MsiCloseHandle(hpack);
2506     MsiCloseHandle(hdb);
2507     DeleteFileA(msifile);
2508 }
2509 
2510 static void test_formatrecord2(void)
2511 {
2512     MSIHANDLE hpkg, hrec ;
2513     char buffer[0x100];
2514     DWORD sz;
2515     UINT r;
2516 
2517     r = package_from_db(create_package_db(), &hpkg);
2518     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2519     {
2520         skip("Not enough rights to perform tests\n");
2521         DeleteFileA(msifile);
2522         return;
2523     }
2524     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
2525 
2526     r = MsiSetPropertyA(hpkg, "Manufacturer", " " );
2527     ok( r == ERROR_SUCCESS, "set property failed\n");
2528 
2529     hrec = MsiCreateRecord(2);
2530     ok(hrec, "create record failed\n");
2531 
2532     r = MsiRecordSetStringA( hrec, 0, "[ProgramFilesFolder][Manufacturer]\\asdf");
2533     ok( r == ERROR_SUCCESS, "format record failed\n");
2534 
2535     buffer[0] = 0;
2536     sz = sizeof buffer;
2537     r = MsiFormatRecordA( hpkg, hrec, buffer, &sz );
2538     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2539 
2540     r = MsiRecordSetStringA(hrec, 0, "[foo][1]");
2541     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2542     r = MsiRecordSetStringA(hrec, 1, "hoo");
2543     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2544     sz = sizeof buffer;
2545     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2546     ok( sz == 3, "size wrong\n");
2547     ok( 0 == strcmp(buffer,"hoo"), "wrong output %s\n",buffer);
2548     ok( r == ERROR_SUCCESS, "format failed\n");
2549 
2550     r = MsiRecordSetStringA(hrec, 0, "x[~]x");
2551     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2552     sz = sizeof buffer;
2553     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2554     ok( sz == 3, "size wrong\n");
2555     ok( 0 == strcmp(buffer,"x"), "wrong output %s\n",buffer);
2556     ok( r == ERROR_SUCCESS, "format failed\n");
2557 
2558     r = MsiRecordSetStringA(hrec, 0, "[foo.$%}][1]");
2559     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2560     r = MsiRecordSetStringA(hrec, 1, "hoo");
2561     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2562     sz = sizeof buffer;
2563     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2564     ok( sz == 3, "size wrong\n");
2565     ok( 0 == strcmp(buffer,"hoo"), "wrong output %s\n",buffer);
2566     ok( r == ERROR_SUCCESS, "format failed\n");
2567 
2568     r = MsiRecordSetStringA(hrec, 0, "[\\[]");
2569     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2570     sz = sizeof buffer;
2571     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2572     ok( sz == 1, "size wrong\n");
2573     ok( 0 == strcmp(buffer,"["), "wrong output %s\n",buffer);
2574     ok( r == ERROR_SUCCESS, "format failed\n");
2575 
2576     SetEnvironmentVariableA("FOO", "BAR");
2577     r = MsiRecordSetStringA(hrec, 0, "[%FOO]");
2578     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2579     sz = sizeof buffer;
2580     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2581     ok( sz == 3, "size wrong\n");
2582     ok( 0 == strcmp(buffer,"BAR"), "wrong output %s\n",buffer);
2583     ok( r == ERROR_SUCCESS, "format failed\n");
2584 
2585     r = MsiRecordSetStringA(hrec, 0, "[[1]]");
2586     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2587     r = MsiRecordSetStringA(hrec, 1, "%FOO");
2588     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2589     sz = sizeof buffer;
2590     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2591     ok( sz == 3, "size wrong\n");
2592     ok( 0 == strcmp(buffer,"BAR"), "wrong output %s\n",buffer);
2593     ok( r == ERROR_SUCCESS, "format failed\n");
2594 
2595     MsiCloseHandle( hrec );
2596     MsiCloseHandle( hpkg );
2597     DeleteFileA(msifile);
2598 }
2599 
2600 static void test_formatrecord_tables(void)
2601 {
2602     MSIHANDLE hdb, hrec, hpkg = 0;
2603     CHAR buf[MAX_PATH + 41];
2604     CHAR curr_dir[MAX_PATH];
2605     CHAR expected[MAX_PATH + 45];
2606     CHAR root[MAX_PATH];
2607     DWORD size;
2608     UINT r;
2609 
2610     GetCurrentDirectoryA( MAX_PATH, curr_dir );
2611 
2612     hdb = create_package_db();
2613     ok ( hdb, "failed to create package database\n");
2614 
2615     add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'" );
2616     add_directory_entry( hdb, "'ReallyLongDir', 'TARGETDIR', "
2617                              "'I am a really long directory'" );
2618 
2619     create_feature_table( hdb );
2620     add_feature_entry( hdb, "'occipitofrontalis', '', '', '', 2, 1, '', 0" );
2621 
2622     create_component_table( hdb );
2623     add_component_entry( hdb, "'frontal', '', 'TARGETDIR', 0, '', 'frontal_file'" );
2624     add_component_entry( hdb, "'parietal', '', 'TARGETDIR', 1, '', 'parietal_file'" );
2625     add_component_entry( hdb, "'temporal', '', 'ReallyLongDir', 0, '', 'temporal_file'" );
2626 
2627     create_feature_components_table( hdb );
2628     add_feature_components_entry( hdb, "'occipitofrontalis', 'frontal'" );
2629     add_feature_components_entry( hdb, "'occipitofrontalis', 'parietal'" );
2630     add_feature_components_entry( hdb, "'occipitofrontalis', 'temporal'" );
2631 
2632     create_file_table( hdb );
2633     add_file_entry( hdb, "'frontal_file', 'frontal', 'frontal.txt', 0, '', '1033', 8192, 1" );
2634     add_file_entry( hdb, "'parietal_file', 'parietal', 'parietal.txt', 0, '', '1033', 8192, 1" );
2635     add_file_entry( hdb, "'temporal_file', 'temporal', 'temporal.txt', 0, '', '1033', 8192, 1" );
2636 
2637     create_custom_action_table( hdb );
2638     add_custom_action_entry( hdb, "'MyCustom', 51, 'prop', '[!temporal_file]'" );
2639     add_custom_action_entry( hdb, "'EscapeIt1', 51, 'prop', '[\\[]Bracket Text[\\]]'" );
2640     add_custom_action_entry( hdb, "'EscapeIt2', 51, 'prop', '[\\xabcd]'" );
2641     add_custom_action_entry( hdb, "'EscapeIt3', 51, 'prop', '[abcd\\xefgh]'" );
2642     add_custom_action_entry( hdb, "'EmbedNull', 51, 'prop', '[~]np'" );
2643 
2644     r = package_from_db( hdb, &hpkg );
2645     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2646     {
2647         skip("Not enough rights to perform tests\n");
2648         MsiCloseHandle( hdb );
2649         DeleteFileA( msifile );
2650         return;
2651     }
2652     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
2653 
2654     MsiCloseHandle( hdb );
2655 
2656     r = MsiSetPropertyA( hpkg, "imaprop", "ringer" );
2657     ok( r == ERROR_SUCCESS, "cannot set property: %d\n", r);
2658 
2659     hrec = MsiCreateRecord( 1 );
2660 
2661     /* property doesn't exist */
2662     size = MAX_PATH;
2663     /*MsiRecordSetStringA( hrec, 0, "[1]" ); */
2664     MsiRecordSetStringA( hrec, 1, "[idontexist]" );
2665     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2666     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2667     ok( !lstrcmpA( buf, "1:  " ), "Expected '1:  ', got %s\n", buf );
2668 
2669     /* property exists */
2670     size = MAX_PATH;
2671     MsiRecordSetStringA( hrec, 1, "[imaprop]" );
2672     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2673     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2674     ok( !lstrcmpA( buf, "1: ringer " ), "Expected '1: ringer ', got %s\n", buf );
2675 
2676     size = MAX_PATH;
2677     MsiRecordSetStringA( hrec, 0, "1: [1] " );
2678     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2679     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2680     ok( !lstrcmpA( buf, "1: ringer " ), "Expected '1: ringer ', got %s\n", buf );
2681 
2682     /* environment variable doesn't exist */
2683     size = MAX_PATH;
2684     MsiRecordSetStringA( hrec, 1, "[%idontexist]" );
2685     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2686     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2687     ok( !lstrcmpA( buf, "1:  " ), "Expected '1:  ', got %s\n", buf );
2688 
2689     /* environment variable exists */
2690     size = MAX_PATH;
2691     SetEnvironmentVariableA( "crazyvar", "crazyval" );
2692     MsiRecordSetStringA( hrec, 1, "[%crazyvar]" );
2693     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2694     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2695     ok( !lstrcmpA( buf, "1: crazyval " ), "Expected '1: crazyval ', got %s\n", buf );
2696 
2697     /* file key before CostInitialize */
2698     size = MAX_PATH;
2699     MsiRecordSetStringA( hrec, 1, "[#frontal_file]" );
2700     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2701     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2702     ok( !lstrcmpA( buf, "1:  " ), "Expected '1:  ', got %s\n", buf );
2703 
2704     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2705 
2706     r = MsiDoActionA(hpkg, "CostInitialize");
2707     ok( r == ERROR_SUCCESS, "CostInitialize failed: %d\n", r);
2708 
2709     r = MsiDoActionA(hpkg, "FileCost");
2710     ok( r == ERROR_SUCCESS, "FileCost failed: %d\n", r);
2711 
2712     r = MsiDoActionA(hpkg, "CostFinalize");
2713     ok( r == ERROR_SUCCESS, "CostFinalize failed: %d\n", r);
2714 
2715     size = MAX_PATH;
2716     MsiGetPropertyA( hpkg, "ROOTDRIVE", root, &size );
2717 
2718     sprintf( expected, "1: %sfrontal.txt ", root);
2719 
2720     /* frontal full file key */
2721     size = MAX_PATH;
2722     MsiRecordSetStringA( hrec, 1, "[#frontal_file]" );
2723     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2724     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2725     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2726 
2727     /* frontal short file key */
2728     size = MAX_PATH;
2729     MsiRecordSetStringA( hrec, 1, "[!frontal_file]" );
2730     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2731     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2732     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2733 
2734     sprintf( expected, "1: %sI am a really long directory\\temporal.txt ", root);
2735 
2736     /* temporal full file key */
2737     size = MAX_PATH;
2738     MsiRecordSetStringA( hrec, 1, "[#temporal_file]" );
2739     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2740     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2741     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2742 
2743     /* temporal short file key */
2744     size = MAX_PATH;
2745     MsiRecordSetStringA( hrec, 1, "[!temporal_file]" );
2746     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2747     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2748     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2749 
2750     /* custom action 51, files don't exist */
2751     r = MsiDoActionA( hpkg, "MyCustom" );
2752     ok( r == ERROR_SUCCESS, "MyCustom failed: %d\n", r);
2753 
2754     sprintf( expected, "%sI am a really long directory\\temporal.txt", root);
2755 
2756     size = MAX_PATH;
2757     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2758     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2759     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2760 
2761     sprintf( buf, "%sI am a really long directory", root );
2762     CreateDirectoryA( buf, NULL );
2763 
2764     lstrcatA( buf, "\\temporal.txt" );
2765     create_test_file( buf );
2766 
2767     /* custom action 51, files exist */
2768     r = MsiDoActionA( hpkg, "MyCustom" );
2769     ok( r == ERROR_SUCCESS, "MyCustom failed: %d\n", r);
2770 
2771     size = MAX_PATH;
2772     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2773     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2774     todo_wine
2775     {
2776         ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2777     }
2778 
2779     /* custom action 51, escaped text 1 */
2780     r = MsiDoActionA( hpkg, "EscapeIt1" );
2781     ok( r == ERROR_SUCCESS, "EscapeIt1 failed: %d\n", r);
2782 
2783     size = MAX_PATH;
2784     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2785     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2786     ok( !lstrcmpA( buf, "[Bracket Text]" ), "Expected '[Bracket Text]', got %s\n", buf);
2787 
2788     /* custom action 51, escaped text 2 */
2789     r = MsiDoActionA( hpkg, "EscapeIt2" );
2790     ok( r == ERROR_SUCCESS, "EscapeIt2 failed: %d\n", r);
2791 
2792     size = MAX_PATH;
2793     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2794     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2795     ok( !lstrcmpA( buf, "x" ), "Expected 'x', got %s\n", buf);
2796 
2797     /* custom action 51, escaped text 3 */
2798     r = MsiDoActionA( hpkg, "EscapeIt3" );
2799     ok( r == ERROR_SUCCESS, "EscapeIt3 failed: %d\n", r);
2800 
2801     size = MAX_PATH;
2802     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2803     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2804     ok( !lstrcmpA( buf, "" ), "Expected '', got %s\n", buf);
2805 
2806     /* custom action 51, embedded null */
2807     r = MsiDoActionA( hpkg, "EmbedNull" );
2808     ok( r == ERROR_SUCCESS, "EmbedNull failed: %d\n", r);
2809 
2810     size = MAX_PATH;
2811     memset( buf, 'a', sizeof(buf) );
2812     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2813     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2814     ok( !memcmp( buf, "\0np", sizeof("\0np") ), "wrong value\n");
2815     ok( size == sizeof("\0np") - 1, "got %lu\n", size );
2816 
2817     r = MsiSetPropertyA( hpkg, "prop", "[~]np" );
2818     ok( r == ERROR_SUCCESS, "cannot set property: %d\n", r);
2819 
2820     size = MAX_PATH;
2821     memset( buf, 'a', sizeof(buf) );
2822     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2823     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2824     ok( !lstrcmpA( buf, "[~]np" ), "Expected '[~]np', got %s\n", buf);
2825 
2826     sprintf( expected, "1: %sI am a really long directory\\ ", root);
2827 
2828     /* component with INSTALLSTATE_LOCAL */
2829     size = MAX_PATH;
2830     MsiRecordSetStringA( hrec, 1, "[$temporal]" );
2831     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2832     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2833     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2834 
2835     r = MsiSetComponentStateA( hpkg, "temporal", INSTALLSTATE_SOURCE );
2836     ok( r == ERROR_SUCCESS, "failed to set install state: %d\n", r);
2837 
2838     /* component with INSTALLSTATE_SOURCE */
2839     lstrcpyA( expected, "1: " );
2840     lstrcatA( expected, curr_dir );
2841     if (strlen(curr_dir) > 3) lstrcatA( expected, "\\" );
2842     lstrcatA( expected, " " );
2843     size = MAX_PATH;
2844     MsiRecordSetStringA( hrec, 1, "[$parietal]" );
2845     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2846     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2847     ok( !lstrcmpA( buf, expected ), "Expected '%s', got '%s'\n", expected, buf);
2848 
2849     sprintf( buf, "%sI am a really long directory\\temporal.txt", root );
2850     DeleteFileA( buf );
2851 
2852     sprintf( buf, "%sI am a really long directory", root );
2853     RemoveDirectoryA( buf );
2854 
2855     MsiCloseHandle( hrec );
2856     MsiCloseHandle( hpkg );
2857     DeleteFileA( msifile );
2858 }
2859 
2860 static void test_feature_states( UINT line, MSIHANDLE package, const char *feature, UINT error,
2861                                  INSTALLSTATE expected_state, INSTALLSTATE expected_action, BOOL todo )
2862 {
2863     UINT r;
2864     INSTALLSTATE state = 0xdeadbee;
2865     INSTALLSTATE action = 0xdeadbee;
2866 
2867     r = MsiGetFeatureStateA( package, feature, &state, &action );
2868     ok( r == error, "%u: expected %d got %d\n", line, error, r );
2869     if (r == ERROR_SUCCESS)
2870     {
2871         ok( state == expected_state, "%u: expected state %d got %d\n",
2872             line, expected_state, state );
2873         todo_wine_if (todo)
2874             ok( action == expected_action, "%u: expected action %d got %d\n",
2875                 line, expected_action, action );
2876     }
2877     else
2878     {
2879         ok( state == 0xdeadbee, "%u: expected state 0xdeadbee got %d\n", line, state );
2880         todo_wine_if (todo)
2881             ok( action == 0xdeadbee, "%u: expected action 0xdeadbee got %d\n", line, action );
2882 
2883     }
2884 }
2885 
2886 static void test_component_states( UINT line, MSIHANDLE package, const char *component, UINT error,
2887                                    INSTALLSTATE expected_state, INSTALLSTATE expected_action, BOOL todo )
2888 {
2889     UINT r;
2890     INSTALLSTATE state = 0xdeadbee;
2891     INSTALLSTATE action = 0xdeadbee;
2892 
2893     r = MsiGetComponentStateA( package, component, &state, &action );
2894     ok( r == error, "%u: expected %d got %d\n", line, error, r );
2895     if (r == ERROR_SUCCESS)
2896     {
2897         ok( state == expected_state, "%u: expected state %d got %d\n",
2898             line, expected_state, state );
2899         todo_wine_if (todo)
2900             ok( action == expected_action, "%u: expected action %d got %d\n",
2901                 line, expected_action, action );
2902     }
2903     else
2904     {
2905         ok( state == 0xdeadbee, "%u: expected state 0xdeadbee got %d\n",
2906             line, state );
2907         todo_wine_if (todo)
2908             ok( action == 0xdeadbee, "%u: expected action 0xdeadbee got %d\n",
2909                 line, action );
2910     }
2911 }
2912 
2913 static void test_states(void)
2914 {
2915     static const char msifile2[] = "winetest2-package.msi";
2916     static const char msifile3[] = "winetest3-package.msi";
2917     static const char msifile4[] = "winetest4-package.msi";
2918     static const WCHAR msifile2W[] = L"winetest2-package.msi";
2919     static const WCHAR msifile3W[] = L"winetest3-package.msi";
2920     static const WCHAR msifile4W[] = L"winetest4-package.msi";
2921     char msi_cache_file[MAX_PATH];
2922     DWORD cache_file_name_len;
2923     INSTALLSTATE state;
2924     MSIHANDLE hpkg, hprod;
2925     UINT r;
2926     MSIHANDLE hdb;
2927     char value[MAX_PATH];
2928     DWORD size;
2929 
2930     if (!is_process_elevated())
2931     {
2932         skip("process is limited\n");
2933         return;
2934     }
2935 
2936     hdb = create_package_db();
2937     ok ( hdb, "failed to create package database\n" );
2938 
2939     add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'");
2940 
2941     create_property_table( hdb );
2942     add_property_entry( hdb, "'ProductCode', '{7262AC98-EEBD-4364-8CE3-D654F6A425B9}'" );
2943     add_property_entry( hdb, "'ProductLanguage', '1033'" );
2944     add_property_entry( hdb, "'ProductName', 'MSITEST'" );
2945     add_property_entry( hdb, "'ProductVersion', '1.1.1'" );
2946     add_property_entry( hdb, "'MSIFASTINSTALL', '1'" );
2947     add_property_entry( hdb, "'UpgradeCode', '{3494EEEA-4221-4A66-802E-DED8916BC5C5}'" );
2948 
2949     create_install_execute_sequence_table( hdb );
2950     add_install_execute_sequence_entry( hdb, "'CostInitialize', '', '800'" );
2951     add_install_execute_sequence_entry( hdb, "'FileCost', '', '900'" );
2952     add_install_execute_sequence_entry( hdb, "'CostFinalize', '', '1000'" );
2953     add_install_execute_sequence_entry( hdb, "'InstallValidate', '', '1400'" );
2954     add_install_execute_sequence_entry( hdb, "'InstallInitialize', '', '1500'" );
2955     add_install_execute_sequence_entry( hdb, "'ProcessComponents', '', '1600'" );
2956     add_install_execute_sequence_entry( hdb, "'UnpublishFeatures', '', '1800'" );
2957     add_install_execute_sequence_entry( hdb, "'RegisterProduct', '', '6100'" );
2958     add_install_execute_sequence_entry( hdb, "'PublishFeatures', '', '6300'" );
2959     add_install_execute_sequence_entry( hdb, "'PublishProduct', '', '6400'" );
2960     add_install_execute_sequence_entry( hdb, "'InstallFinalize', '', '6600'" );
2961 
2962     create_media_table( hdb );
2963     add_media_entry( hdb, "'1', '3', '', '', 'DISK1', ''");
2964 
2965     create_feature_table( hdb );
2966 
2967     create_component_table( hdb );
2968 
2969     /* msidbFeatureAttributesFavorLocal */
2970     add_feature_entry( hdb, "'one', '', '', '', 2, 1, '', 0" );
2971 
2972     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesLocalOnly */
2973     add_component_entry( hdb, "'alpha', '{467EC132-739D-4784-A37B-677AA43DBC94}', 'TARGETDIR', 0, '', 'alpha_file'" );
2974 
2975     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSourceOnly */
2976     add_component_entry( hdb, "'beta', '{2C1F189C-24A6-4C34-B26B-994A6C026506}', 'TARGETDIR', 1, '', 'beta_file'" );
2977 
2978     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesOptional */
2979     add_component_entry( hdb, "'gamma', '{C271E2A4-DE2E-4F70-86D1-6984AF7DE2CA}', 'TARGETDIR', 2, '', 'gamma_file'" );
2980 
2981     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSharedDllRefCount */
2982     add_component_entry( hdb, "'theta', '{4EB3129D-81A8-48D5-9801-75600FED3DD9}', 'TARGETDIR', 8, '', 'theta_file'" );
2983 
2984     /* msidbFeatureAttributesFavorSource */
2985     add_feature_entry( hdb, "'two', '', '', '', 2, 1, '', 1" );
2986 
2987     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesLocalOnly */
2988     add_component_entry( hdb, "'delta', '{938FD4F2-C648-4259-A03C-7AA3B45643F3}', 'TARGETDIR', 0, '', 'delta_file'" );
2989 
2990     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSourceOnly */
2991     add_component_entry( hdb, "'epsilon', '{D59713B6-C11D-47F2-A395-1E5321781190}', 'TARGETDIR', 1, '', 'epsilon_file'" );
2992 
2993     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesOptional */
2994     add_component_entry( hdb, "'zeta', '{377D33AB-2FAA-42B9-A629-0C0DAE9B9C7A}', 'TARGETDIR', 2, '', 'zeta_file'" );
2995 
2996     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSharedDllRefCount */
2997     add_component_entry( hdb, "'iota', '{5D36F871-B5ED-4801-9E0F-C46B9E5C9669}', 'TARGETDIR', 8, '', 'iota_file'" );
2998 
2999     /* msidbFeatureAttributesFavorSource */
3000     add_feature_entry( hdb, "'three', '', '', '', 2, 1, '', 1" );
3001 
3002     /* msidbFeatureAttributesFavorLocal */
3003     add_feature_entry( hdb, "'four', '', '', '', 2, 1, '', 0" );
3004 
3005     /* disabled */
3006     add_feature_entry( hdb, "'five', '', '', '', 2, 0, '', 1" );
3007 
3008     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSourceOnly */
3009     add_component_entry( hdb, "'eta', '{DD89003F-0DD4-41B8-81C0-3411A7DA2695}', 'TARGETDIR', 1, '', 'eta_file'" );
3010 
3011     /* no feature parent:msidbComponentAttributesLocalOnly */
3012     add_component_entry( hdb, "'kappa', '{D6B93DC3-8DA5-4769-9888-42BFE156BB8B}', 'TARGETDIR', 1, '', 'kappa_file'" );
3013 
3014     /* msidbFeatureAttributesFavorLocal:removed */
3015     add_feature_entry( hdb, "'six', '', '', '', 2, 1, '', 0" );
3016 
3017     /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesLocalOnly */
3018     add_component_entry( hdb, "'lambda', '{6528C5E4-02A4-4636-A214-7A66A6C35B64}', 'TARGETDIR', 0, '', 'lambda_file'" );
3019 
3020     /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesSourceOnly */
3021     add_component_entry( hdb, "'mu', '{97014BAB-6C56-4013-9A63-2BF913B42519}', 'TARGETDIR', 1, '', 'mu_file'" );
3022 
3023     /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesOptional */
3024     add_component_entry( hdb, "'nu', '{943DD0D8-5808-4954-8526-3B8493FEDDCD}', 'TARGETDIR', 2, '', 'nu_file'" );
3025 
3026     /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesSharedDllRefCount */
3027     add_component_entry( hdb, "'xi', '{D6CF9EF7-6FCF-4930-B34B-F938AEFF9BDB}', 'TARGETDIR', 8, '', 'xi_file'" );
3028 
3029     /* msidbFeatureAttributesFavorSource:removed */
3030     add_feature_entry( hdb, "'seven', '', '', '', 2, 1, '', 1" );
3031 
3032     /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesLocalOnly */
3033     add_component_entry( hdb, "'omicron', '{7B57521D-15DB-4141-9AA6-01D934A4433F}', 'TARGETDIR', 0, '', 'omicron_file'" );
3034 
3035     /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesSourceOnly */
3036     add_component_entry( hdb, "'pi', '{FB85346B-378E-4492-8769-792305471C81}', 'TARGETDIR', 1, '', 'pi_file'" );
3037 
3038     /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesOptional */
3039     add_component_entry( hdb, "'rho', '{798F2047-7B0C-4783-8BB0-D703E554114B}', 'TARGETDIR', 2, '', 'rho_file'" );
3040 
3041     /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesSharedDllRefCount */
3042     add_component_entry( hdb, "'sigma', '{5CE9DDA8-B67B-4736-9D93-99D61C5B93E7}', 'TARGETDIR', 8, '', 'sigma_file'" );
3043 
3044     /* msidbFeatureAttributesFavorLocal */
3045     add_feature_entry( hdb, "'eight', '', '', '', 2, 1, '', 0" );
3046 
3047     add_component_entry( hdb, "'tau', '{07DEB510-677C-4A6F-A0A6-7CD8EFEA77ED}', 'TARGETDIR', 1, '', 'tau_file'" );
3048 
3049     /* msidbFeatureAttributesFavorSource */
3050     add_feature_entry( hdb, "'nine', '', '', '', 2, 1, '', 1" );
3051 
3052     add_component_entry( hdb, "'phi', '{9F0594C5-35AD-43EA-94DD-8DF73FAA664D}', 'TARGETDIR', 1, '', 'phi_file'" );
3053 
3054     /* msidbFeatureAttributesFavorAdvertise */
3055     add_feature_entry( hdb, "'ten', '', '', '', 2, 1, '', 4" );
3056 
3057     add_component_entry( hdb, "'chi', '{E6B539AB-5DA9-4236-A2D2-E341A50B4C38}', 'TARGETDIR', 1, '', 'chi_file'" );
3058 
3059     /* msidbFeatureAttributesUIDisallowAbsent */
3060     add_feature_entry( hdb, "'eleven', '', '', '', 2, 1, '', 16" );
3061 
3062     add_component_entry( hdb, "'psi', '{A06B23B5-746B-427A-8A6E-FD6AC8F46A95}', 'TARGETDIR', 1, '', 'psi_file'" );
3063 
3064     /* high install level */
3065     add_feature_entry( hdb, "'twelve', '', '', '', 2, 2, '', 0" );
3066 
3067     add_component_entry( hdb, "'upsilon', '{557e0c04-ceba-4c58-86a9-4a73352e8cf6}', 'TARGETDIR', 1, '', 'upsilon_file'" );
3068 
3069     /* msidbFeatureAttributesFollowParent */
3070     add_feature_entry( hdb, "'thirteen', '', '', '', 2, 2, '', 2" );
3071 
3072     create_feature_components_table( hdb );
3073     add_feature_components_entry( hdb, "'one', 'alpha'" );
3074     add_feature_components_entry( hdb, "'one', 'beta'" );
3075     add_feature_components_entry( hdb, "'one', 'gamma'" );
3076     add_feature_components_entry( hdb, "'one', 'theta'" );
3077     add_feature_components_entry( hdb, "'two', 'delta'" );
3078     add_feature_components_entry( hdb, "'two', 'epsilon'" );
3079     add_feature_components_entry( hdb, "'two', 'zeta'" );
3080     add_feature_components_entry( hdb, "'two', 'iota'" );
3081     add_feature_components_entry( hdb, "'three', 'eta'" );
3082     add_feature_components_entry( hdb, "'four', 'eta'" );
3083     add_feature_components_entry( hdb, "'five', 'eta'" );
3084     add_feature_components_entry( hdb, "'six', 'lambda'" );
3085     add_feature_components_entry( hdb, "'six', 'mu'" );
3086     add_feature_components_entry( hdb, "'six', 'nu'" );
3087     add_feature_components_entry( hdb, "'six', 'xi'" );
3088     add_feature_components_entry( hdb, "'seven', 'omicron'" );
3089     add_feature_components_entry( hdb, "'seven', 'pi'" );
3090     add_feature_components_entry( hdb, "'seven', 'rho'" );
3091     add_feature_components_entry( hdb, "'seven', 'sigma'" );
3092     add_feature_components_entry( hdb, "'eight', 'tau'" );
3093     add_feature_components_entry( hdb, "'nine', 'phi'" );
3094     add_feature_components_entry( hdb, "'ten', 'chi'" );
3095     add_feature_components_entry( hdb, "'eleven', 'psi'" );
3096     add_feature_components_entry( hdb, "'twelve', 'upsilon'" );
3097     add_feature_components_entry( hdb, "'thirteen', 'upsilon'" );
3098 
3099     create_file_table( hdb );
3100     add_file_entry( hdb, "'alpha_file', 'alpha', 'alpha.txt', 100, '', '1033', 8192, 1" );
3101     add_file_entry( hdb, "'beta_file', 'beta', 'beta.txt', 0, '', '1033', 8192, 1" );
3102     add_file_entry( hdb, "'gamma_file', 'gamma', 'gamma.txt', 0, '', '1033', 8192, 1" );
3103     add_file_entry( hdb, "'theta_file', 'theta', 'theta.txt', 0, '', '1033', 8192, 1" );
3104     add_file_entry( hdb, "'delta_file', 'delta', 'delta.txt', 0, '', '1033', 8192, 1" );
3105     add_file_entry( hdb, "'epsilon_file', 'epsilon', 'epsilon.txt', 0, '', '1033', 8192, 1" );
3106     add_file_entry( hdb, "'zeta_file', 'zeta', 'zeta.txt', 0, '', '1033', 8192, 1" );
3107     add_file_entry( hdb, "'iota_file', 'iota', 'iota.txt', 0, '', '1033', 8192, 1" );
3108 
3109     /* compressed file */
3110     add_file_entry( hdb, "'eta_file', 'eta', 'eta.txt', 0, '', '1033', 16384, 1" );
3111 
3112     add_file_entry( hdb, "'kappa_file', 'kappa', 'kappa.txt', 0, '', '1033', 8192, 1" );
3113     add_file_entry( hdb, "'lambda_file', 'lambda', 'lambda.txt', 100, '', '1033', 8192, 1" );
3114     add_file_entry( hdb, "'mu_file', 'mu', 'mu.txt', 100, '', '1033', 8192, 1" );
3115     add_file_entry( hdb, "'nu_file', 'nu', 'nu.txt', 100, '', '1033', 8192, 1" );
3116     add_file_entry( hdb, "'xi_file', 'xi', 'xi.txt', 100, '', '1033', 8192, 1" );
3117     add_file_entry( hdb, "'omicron_file', 'omicron', 'omicron.txt', 100, '', '1033', 8192, 1" );
3118     add_file_entry( hdb, "'pi_file', 'pi', 'pi.txt', 100, '', '1033', 8192, 1" );
3119     add_file_entry( hdb, "'rho_file', 'rho', 'rho.txt', 100, '', '1033', 8192, 1" );
3120     add_file_entry( hdb, "'sigma_file', 'sigma', 'sigma.txt', 100, '', '1033', 8192, 1" );
3121     add_file_entry( hdb, "'tau_file', 'tau', 'tau.txt', 100, '', '1033', 8192, 1" );
3122     add_file_entry( hdb, "'phi_file', 'phi', 'phi.txt', 100, '', '1033', 8192, 1" );
3123     add_file_entry( hdb, "'chi_file', 'chi', 'chi.txt', 100, '', '1033', 8192, 1" );
3124     add_file_entry( hdb, "'psi_file', 'psi', 'psi.txt', 100, '', '1033', 8192, 1" );
3125     add_file_entry( hdb, "'upsilon_file', 'upsilon', 'upsilon.txt', 0, '', '1033', 16384, 1" );
3126 
3127     r = MsiDatabaseCommit(hdb);
3128     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
3129 
3130     /* these properties must not be in the saved msi file */
3131     add_property_entry( hdb, "'ADDLOCAL', 'one,four'");
3132     add_property_entry( hdb, "'ADDSOURCE', 'two,three'");
3133     add_property_entry( hdb, "'REMOVE', 'six,seven'");
3134     add_property_entry( hdb, "'REINSTALL', 'eight,nine,ten'");
3135     add_property_entry( hdb, "'REINSTALLMODE', 'omus'");
3136 
3137     r = package_from_db( hdb, &hpkg );
3138     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
3139     {
3140         skip("Not enough rights to perform tests\n");
3141         DeleteFileA(msifile);
3142         return;
3143     }
3144     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3145 
3146     MsiCloseHandle(hdb);
3147 
3148     CopyFileA(msifile, msifile2, FALSE);
3149     CopyFileA(msifile, msifile3, FALSE);
3150     CopyFileA(msifile, msifile4, FALSE);
3151 
3152     size = sizeof(value);
3153     memset(value, 0, sizeof(value));
3154     r = MsiGetPropertyA(hpkg, "ProductToBeRegistered", value, &size);
3155     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
3156     ok(!value[0], "ProductToBeRegistered = %s\n", value);
3157 
3158     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3159     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3160 
3161     r = MsiDoActionA( hpkg, "CostInitialize");
3162     ok( r == ERROR_SUCCESS, "cost init failed\n");
3163 
3164     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3165     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3166 
3167     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3168 
3169     r = MsiDoActionA( hpkg, "FileCost");
3170     ok( r == ERROR_SUCCESS, "file cost failed\n");
3171 
3172     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3173     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3174 
3175     r = MsiDoActionA( hpkg, "CostFinalize");
3176     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3177 
3178     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3179     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
3180     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3181     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3182     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3183     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3184     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3185     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3186     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3187     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3188     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3189     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3190     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3191 
3192     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3193     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
3194     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3195     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3196     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3197     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
3198     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
3199     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3200     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3201     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3202     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3203     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3204     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3205     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3206     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3207     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3208     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3209     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3210     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3211     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3212     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3213     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3214     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3215 
3216     MsiCloseHandle( hpkg );
3217 
3218     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3219 
3220     /* publish the features and components */
3221     r = MsiInstallProductA(msifile, "ADDLOCAL=one,four ADDSOURCE=two,three REMOVE=six,seven REINSTALL=eight,nine,ten");
3222     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3223 
3224     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb);
3225     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3226 
3227     /* these properties must not be in the saved msi file */
3228     add_property_entry( hdb, "'ADDLOCAL', 'one,four'");
3229     add_property_entry( hdb, "'ADDSOURCE', 'two,three'");
3230     add_property_entry( hdb, "'REMOVE', 'six,seven'");
3231     add_property_entry( hdb, "'REINSTALL', 'eight,nine,ten'");
3232 
3233     r = package_from_db( hdb, &hpkg );
3234     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3235 
3236     MsiCloseHandle(hdb);
3237 
3238     size = sizeof(value);
3239     memset(value, 0, sizeof(value));
3240     r = MsiGetPropertyA(hpkg, "ProductToBeRegistered", value, &size);
3241     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
3242     ok(value[0]=='1' && !value[1], "ProductToBeRegistered = %s\n", value);
3243 
3244     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3245     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3246 
3247     r = MsiDoActionA( hpkg, "CostInitialize");
3248     ok( r == ERROR_SUCCESS, "cost init failed\n");
3249 
3250     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3251     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3252 
3253     r = MsiDoActionA( hpkg, "FileCost");
3254     ok( r == ERROR_SUCCESS, "file cost failed\n");
3255 
3256     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3257     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3258 
3259     r = MsiDoActionA( hpkg, "CostFinalize");
3260     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3261 
3262     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3263     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3264     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3265     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3266     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3267     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3268     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3269     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3270     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3271     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3272     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3273     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3274     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3275 
3276     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3277     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3278     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3279     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3280     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3281     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3282     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3283     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3284     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3285     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3286     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3287     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3288     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3289     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3290     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3291     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3292     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3293     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3294     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3295     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3296     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3297     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3298     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3299 
3300     MsiCloseHandle(hpkg);
3301 
3302     /* uninstall the product */
3303     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3304     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3305 
3306     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3307     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3308     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3309     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3310 
3311     /* all features installed locally */
3312     r = MsiInstallProductA(msifile2, "ADDLOCAL=ALL");
3313     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3314 
3315     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3316     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3317     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3318     ok(state == INSTALLSTATE_LOCAL, "state = %d\n", state);
3319 
3320     r = MsiOpenDatabaseW(msifile2W, MSIDBOPEN_DIRECT, &hdb);
3321     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3322 
3323     /* these properties must not be in the saved msi file */
3324     add_property_entry( hdb, "'ADDLOCAL', 'one,two,three,four,five,six,seven,eight,nine,ten,twelve'");
3325 
3326     r = package_from_db( hdb, &hpkg );
3327     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3328 
3329     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3330     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3331 
3332     r = MsiDoActionA( hpkg, "CostInitialize");
3333     ok( r == ERROR_SUCCESS, "cost init failed\n");
3334 
3335     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3336     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3337 
3338     r = MsiDoActionA( hpkg, "CostFinalize");
3339     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3340 
3341     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3342     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3343     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3344     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3345     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3346     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3347     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3348     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, TRUE );
3349     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, TRUE );
3350     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, TRUE );
3351     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3352     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3353     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3354 
3355     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3356     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3357     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3358     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3359     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3360     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3361     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3362     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3363     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3364     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3365     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3366     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3367     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3368     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3369     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3370     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3371     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3372     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3373     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3374     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3375     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3376     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3377     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3378 
3379     MsiCloseHandle(hpkg);
3380 
3381     /* uninstall the product */
3382     r = MsiInstallProductA(msifile2, "REMOVE=ALL");
3383     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3384 
3385     /* all features installed from source */
3386     r = MsiInstallProductA(msifile3, "ADDSOURCE=ALL");
3387     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3388 
3389     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3390     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3391     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3392     ok(state == INSTALLSTATE_LOCAL, "state = %d\n", state);
3393 
3394     r = MsiOpenDatabaseW(msifile3W, MSIDBOPEN_DIRECT, &hdb);
3395     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3396 
3397     /* this property must not be in the saved msi file */
3398     add_property_entry( hdb, "'ADDSOURCE', 'one,two,three,four,five,six,seven,eight,nine,ten'");
3399 
3400     r = package_from_db( hdb, &hpkg );
3401     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3402 
3403     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3404     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3405 
3406     r = MsiDoActionA( hpkg, "CostInitialize");
3407     ok( r == ERROR_SUCCESS, "cost init failed\n");
3408 
3409     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3410     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3411 
3412     r = MsiDoActionA( hpkg, "FileCost");
3413     ok( r == ERROR_SUCCESS, "file cost failed\n");
3414 
3415     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3416     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3417 
3418     r = MsiDoActionA( hpkg, "CostFinalize");
3419     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3420 
3421     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3422     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3423     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3424     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3425     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3426     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3427     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3428     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3429     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3430     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3431     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3432     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3433     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3434 
3435     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3436     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3437     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3438     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3439     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3440     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3441     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3442     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3443     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3444     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3445     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3446     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3447     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3448     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3449     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3450     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3451     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3452     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3453     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3454     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3455     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3456     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3457     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3458 
3459     MsiCloseHandle(hpkg);
3460 
3461     /* reinstall the product */
3462     r = MsiInstallProductA(msifile3, "REINSTALL=ALL");
3463     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3464 
3465     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3466     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3467     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3468     ok(state == INSTALLSTATE_LOCAL, "state = %d\n", state);
3469 
3470     r = MsiOpenDatabaseW(msifile4W, MSIDBOPEN_DIRECT, &hdb);
3471     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3472 
3473     /* this property must not be in the saved msi file */
3474     add_property_entry( hdb, "'ADDSOURCE', 'one,two,three,four,five,six,seven,eight,nine,ten'");
3475 
3476     r = package_from_db( hdb, &hpkg );
3477     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3478 
3479     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3480     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3481 
3482     r = MsiDoActionA( hpkg, "CostInitialize");
3483     ok( r == ERROR_SUCCESS, "cost init failed\n");
3484 
3485     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3486     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3487 
3488     r = MsiDoActionA( hpkg, "FileCost");
3489     ok( r == ERROR_SUCCESS, "file cost failed\n");
3490 
3491     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3492     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3493 
3494     r = MsiDoActionA( hpkg, "CostFinalize");
3495     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3496 
3497     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3498     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3499     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3500     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3501     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3502     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3503     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3504     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3505     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3506     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3507     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3508     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3509     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3510 
3511     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3512     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3513     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3514     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3515     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3516     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3517     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3518     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3519     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3520     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3521     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3522     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3523     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3524     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3525     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3526     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3527     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3528     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3529     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3530     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3531     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3532     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3533     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3534 
3535     MsiCloseHandle(hpkg);
3536 
3537     /* test source only install */
3538     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3539     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3540     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "one");
3541     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3542     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "two");
3543     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3544 
3545     r = MsiInstallProductA(msifile, "ADDSOURCE=one");
3546     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3547     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "one");
3548     ok(state == INSTALLSTATE_SOURCE, "state = %d\n", state);
3549     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "two");
3550     ok(state == INSTALLSTATE_ABSENT, "state = %d\n", state);
3551 
3552     /* no arguments test */
3553     cache_file_name_len = sizeof(msi_cache_file);
3554     r = MsiGetProductInfoA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}",
3555             INSTALLPROPERTY_LOCALPACKAGEA, msi_cache_file, &cache_file_name_len);
3556     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3557     r = MsiOpenDatabaseA(msi_cache_file, (const char*)MSIDBOPEN_DIRECT, &hdb);
3558     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3559 
3560     create_custom_action_table( hdb );
3561     add_custom_action_entry( hdb, "'ConditionCheck1', 19, '', 'Condition check failed (1)'" );
3562     add_custom_action_entry( hdb, "'ConditionCheck2', 19, '', 'Condition check failed (2)'" );
3563     add_custom_action_entry( hdb, "'ConditionCheck3', 19, '', 'Condition check failed (3)'" );
3564     add_custom_action_entry( hdb, "'ConditionCheck4', 19, '', 'Condition check failed (4)'" );
3565     add_custom_action_entry( hdb, "'ConditionCheck5', 19, '', 'Condition check failed (5)'" );
3566     add_custom_action_entry( hdb, "'ConditionCheck6', 19, '', 'Condition check failed (6)'" );
3567     add_custom_action_entry( hdb, "'ConditionCheck7', 19, '', 'Condition check failed (7)'" );
3568     add_custom_action_entry( hdb, "'ConditionCheck8', 19, '', 'Condition check failed (8)'" );
3569     add_custom_action_entry( hdb,
3570             "'VBFeatureRequest', 38, NULL, 'Session.FeatureRequestState(\"three\") = 3'" );
3571 
3572     add_install_execute_sequence_entry( hdb, "'ConditionCheck1', 'REINSTALL', '798'" );
3573     add_install_execute_sequence_entry( hdb, "'ConditionCheck2', 'NOT REMOVE AND Preselected', '799'" );
3574     add_install_execute_sequence_entry( hdb, "'VBFeatureRequest', 'NOT REMOVE', '1001'" );
3575     add_install_execute_sequence_entry( hdb, "'ConditionCheck3', 'REINSTALL', '6598'" );
3576     add_install_execute_sequence_entry( hdb, "'ConditionCheck4', 'NOT REMOVE AND Preselected', '6599'" );
3577     add_install_execute_sequence_entry( hdb, "'ConditionCheck5', 'REINSTALL', '6601'" );
3578     add_install_execute_sequence_entry( hdb, "'ConditionCheck6', 'NOT REMOVE AND Preselected', '6601'" );
3579     /* Add "one" feature action tests */
3580     add_install_execute_sequence_entry( hdb, "'ConditionCheck7', 'NOT REMOVE AND NOT(&one=-1)', '1501'" );
3581     add_install_execute_sequence_entry( hdb, "'ConditionCheck8', 'NOT REMOVE AND NOT(&one=-1)', '6602'" );
3582     r = MsiDatabaseCommit(hdb);
3583     ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed: %d\n", r);
3584     r = package_from_db( hdb, &hpkg );
3585     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3586     MsiCloseHandle(hdb);
3587 
3588     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3589     test_feature_states( __LINE__, hpkg, "two", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3590     r = MsiDoActionA( hpkg, "CostInitialize");
3591     ok( r == ERROR_SUCCESS, "CostInitialize failed\n");
3592     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3593     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3594 
3595     r = MsiDoActionA( hpkg, "FileCost");
3596     ok( r == ERROR_SUCCESS, "FileCost failed\n");
3597     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3598     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3599 
3600     r = MsiDoActionA( hpkg, "CostFinalize");
3601     ok( r == ERROR_SUCCESS, "CostFinalize failed\n");
3602     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3603     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3604     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3605     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3606     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3607     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3608     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3609     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3610     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3611     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3612     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3613     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3614     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3615     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3616     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3617     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3618     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3619     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3620     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3621     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3622     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3623     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3624     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3625     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3626     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3627 
3628     r = MsiDoActionA( hpkg, "InstallValidate");
3629     ok( r == ERROR_SUCCESS, "InstallValidate failed %d\n", r);
3630     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3631     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3632     MsiCloseHandle( hpkg );
3633 
3634     r = MsiInstallProductA(msifile, "");
3635     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3636     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "one");
3637     ok(state == INSTALLSTATE_SOURCE, "state = %d\n", state);
3638     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "two");
3639     ok(state == INSTALLSTATE_ABSENT, "state = %d\n", state);
3640     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "three");
3641     ok(state == INSTALLSTATE_LOCAL, "state = %d\n", state);
3642 
3643     /* minor upgrade test with no REINSTALL argument */
3644     r = MsiOpenProductA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", &hprod);
3645     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3646     size = MAX_PATH;
3647     r = MsiGetProductPropertyA(hprod, "ProductVersion", value, &size);
3648     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3649     ok(!strcmp(value, "1.1.1"), "ProductVersion = %s\n", value);
3650     MsiCloseHandle(hprod);
3651 
3652     r = MsiOpenDatabaseA(msifile2, (const char*)MSIDBOPEN_DIRECT, &hdb);
3653     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3654     update_ProductVersion_property( hdb, "1.1.2" );
3655     set_summary_str(hdb, PID_REVNUMBER, "{A219A62A-D931-4F1B-89DB-FF1C300A8D43}");
3656     r = MsiDatabaseCommit(hdb);
3657     ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed: %d\n", r);
3658     MsiCloseHandle(hdb);
3659 
3660     r = MsiInstallProductA(msifile2, "");
3661     ok(r == ERROR_PRODUCT_VERSION, "Expected ERROR_PRODUCT_VERSION, got %d\n", r);
3662 
3663     r = MsiInstallProductA(msifile2, "REINSTALLMODe=V");
3664     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3665 
3666     r = MsiOpenProductA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", &hprod);
3667     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3668     size = MAX_PATH;
3669     r = MsiGetProductPropertyA(hprod, "ProductVersion", value, &size);
3670     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3671     ok(!strcmp(value, "1.1.2"), "ProductVersion = %s\n", value);
3672     MsiCloseHandle(hprod);
3673 
3674     /* major upgrade test */
3675     r = MsiOpenDatabaseA(msifile2, (const char*)MSIDBOPEN_DIRECT, &hdb);
3676     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3677     add_install_execute_sequence_entry( hdb, "'FindRelatedProducts', '', '100'" );
3678     add_install_execute_sequence_entry( hdb, "'RemoveExistingProducts', '', '1401'" );
3679     create_upgrade_table( hdb );
3680     add_upgrade_entry( hdb, "'{3494EEEA-4221-4A66-802E-DED8916BC5C5}', NULL, '1.1.3', NULL, 0, NULL, 'OLDERVERSIONBEINGUPGRADED'");
3681     update_ProductCode_property( hdb, "{333DB27A-C25E-4EBC-9BEC-0F49546C19A6}" );
3682     update_ProductVersion_property( hdb, "1.1.3" );
3683     set_summary_str(hdb, PID_REVNUMBER, "{5F99011C-02E6-48BD-8B8D-DE7CFABC7A09}");
3684     r = MsiDatabaseCommit(hdb);
3685     ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed: %d\n", r);
3686     MsiCloseHandle(hdb);
3687 
3688     r = MsiInstallProductA(msifile2, "");
3689     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3690 
3691     r = MsiOpenProductA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", &hprod);
3692     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3693     r = MsiOpenProductA("{333DB27A-C25E-4EBC-9BEC-0F49546C19A6}", &hprod);
3694     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3695     size = MAX_PATH;
3696     r = MsiGetProductPropertyA(hprod, "ProductVersion", value, &size);
3697     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3698     ok(!strcmp(value, "1.1.3"), "ProductVersion = %s\n", value);
3699     MsiCloseHandle(hprod);
3700 
3701     /* uninstall the product */
3702     r = MsiInstallProductA(msifile2, "REMOVE=ALL");
3703     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3704 
3705     DeleteFileA(msifile);
3706     DeleteFileA(msifile2);
3707     DeleteFileA(msifile3);
3708     DeleteFileA(msifile4);
3709 }
3710 
3711 static void test_removefiles(void)
3712 {
3713     MSIHANDLE hpkg;
3714     UINT r;
3715     MSIHANDLE hdb;
3716     INSTALLSTATE installed, action;
3717 
3718     hdb = create_package_db();
3719     ok ( hdb, "failed to create package database\n" );
3720 
3721     add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'");
3722 
3723     create_feature_table( hdb );
3724     add_feature_entry( hdb, "'one', '', '', '', 2, 1, '', 0" );
3725 
3726     create_component_table( hdb );
3727     add_component_entry( hdb, "'hydrogen', '', 'TARGETDIR', 0, '', 'hydrogen_file'" );
3728     add_component_entry( hdb, "'helium', '', 'TARGETDIR', 0, '', 'helium_file'" );
3729     add_component_entry( hdb, "'lithium', '', 'TARGETDIR', 0, '', 'lithium_file'" );
3730     add_component_entry( hdb, "'beryllium', '', 'TARGETDIR', 0, '', 'beryllium_file'" );
3731     add_component_entry( hdb, "'boron', '', 'TARGETDIR', 0, '', 'boron_file'" );
3732     add_component_entry( hdb, "'carbon', '', 'TARGETDIR', 0, '', 'carbon_file'" );
3733     add_component_entry( hdb, "'oxygen', '', 'TARGETDIR', 0, '0', 'oxygen_file'" );
3734 
3735     create_feature_components_table( hdb );
3736     add_feature_components_entry( hdb, "'one', 'hydrogen'" );
3737     add_feature_components_entry( hdb, "'one', 'helium'" );
3738     add_feature_components_entry( hdb, "'one', 'lithium'" );
3739     add_feature_components_entry( hdb, "'one', 'beryllium'" );
3740     add_feature_components_entry( hdb, "'one', 'boron'" );
3741     add_feature_components_entry( hdb, "'one', 'carbon'" );
3742     add_feature_components_entry( hdb, "'one', 'oxygen'" );
3743 
3744     create_file_table( hdb );
3745     add_file_entry( hdb, "'hydrogen_file', 'hydrogen', 'hydrogen.txt', 0, '', '1033', 8192, 1" );
3746     add_file_entry( hdb, "'helium_file', 'helium', 'helium.txt', 0, '', '1033', 8192, 1" );
3747     add_file_entry( hdb, "'lithium_file', 'lithium', 'lithium.txt', 0, '', '1033', 8192, 1" );
3748     add_file_entry( hdb, "'beryllium_file', 'beryllium', 'beryllium.txt', 0, '', '1033', 16384, 1" );
3749     add_file_entry( hdb, "'boron_file', 'boron', 'boron.txt', 0, '', '1033', 16384, 1" );
3750     add_file_entry( hdb, "'carbon_file', 'carbon', 'carbon.txt', 0, '', '1033', 16384, 1" );
3751     add_file_entry( hdb, "'oxygen_file', 'oxygen', 'oxygen.txt', 0, '', '1033', 16384, 1" );
3752 
3753     create_remove_file_table( hdb );
3754 
3755     r = package_from_db( hdb, &hpkg );
3756     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
3757     {
3758         skip("Not enough rights to perform tests\n");
3759         DeleteFileA(msifile);
3760         return;
3761     }
3762     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3763 
3764     MsiCloseHandle( hdb );
3765 
3766     create_test_file( "hydrogen.txt" );
3767     create_test_file( "helium.txt" );
3768     create_test_file( "lithium.txt" );
3769     create_test_file( "beryllium.txt" );
3770     create_test_file( "boron.txt" );
3771     create_test_file( "carbon.txt" );
3772     create_test_file( "oxygen.txt" );
3773 
3774     r = MsiSetPropertyA( hpkg, "TARGETDIR", CURR_DIR );
3775     ok( r == ERROR_SUCCESS, "set property failed\n");
3776 
3777     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3778 
3779     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3780     ok( r == ERROR_UNKNOWN_COMPONENT, "expected ERROR_UNKNOWN_COMPONENT, got %u\n", r );
3781 
3782     r = MsiDoActionA( hpkg, "CostInitialize");
3783     ok( r == ERROR_SUCCESS, "cost init failed\n");
3784 
3785     r = MsiDoActionA( hpkg, "FileCost");
3786     ok( r == ERROR_SUCCESS, "file cost failed\n");
3787 
3788     installed = action = 0xdeadbeef;
3789     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3790     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3791     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3792     ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3793 
3794     r = MsiDoActionA( hpkg, "CostFinalize");
3795     ok( r == ERROR_SUCCESS, "cost finalize failed\n");
3796 
3797     r = MsiDoActionA( hpkg, "InstallValidate");
3798     ok( r == ERROR_SUCCESS, "install validate failed\n");
3799 
3800     r = MsiSetComponentStateA( hpkg, "hydrogen", INSTALLSTATE_ABSENT );
3801     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3802 
3803     installed = action = 0xdeadbeef;
3804     r = MsiGetComponentStateA( hpkg, "hydrogen", &installed, &action );
3805     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3806     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3807     todo_wine ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3808 
3809     r = MsiSetComponentStateA( hpkg, "helium", INSTALLSTATE_LOCAL );
3810     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3811 
3812     r = MsiSetComponentStateA( hpkg, "lithium", INSTALLSTATE_SOURCE );
3813     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3814 
3815     r = MsiSetComponentStateA( hpkg, "beryllium", INSTALLSTATE_ABSENT );
3816     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3817 
3818     r = MsiSetComponentStateA( hpkg, "boron", INSTALLSTATE_LOCAL );
3819     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3820 
3821     r = MsiSetComponentStateA( hpkg, "carbon", INSTALLSTATE_SOURCE );
3822     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3823 
3824     installed = action = 0xdeadbeef;
3825     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3826     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3827     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3828     ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3829 
3830     r = MsiSetComponentStateA( hpkg, "oxygen", INSTALLSTATE_ABSENT );
3831     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3832 
3833     installed = action = 0xdeadbeef;
3834     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3835     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3836     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3837     ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3838 
3839     r = MsiDoActionA( hpkg, "RemoveFiles");
3840     ok( r == ERROR_SUCCESS, "remove files failed\n");
3841 
3842     installed = action = 0xdeadbeef;
3843     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3844     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3845     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3846     ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3847 
3848     ok(DeleteFileA("hydrogen.txt"), "Expected hydrogen.txt to exist\n");
3849     ok(DeleteFileA("lithium.txt"), "Expected lithium.txt to exist\n");
3850     ok(DeleteFileA("beryllium.txt"), "Expected beryllium.txt to exist\n");
3851     ok(DeleteFileA("carbon.txt"), "Expected carbon.txt to exist\n");
3852     ok(DeleteFileA("helium.txt"), "Expected helium.txt to exist\n");
3853     ok(DeleteFileA("boron.txt"), "Expected boron.txt to exist\n");
3854     ok(DeleteFileA("oxygen.txt"), "Expected oxygen.txt to exist\n");
3855 
3856     MsiCloseHandle( hpkg );
3857     DeleteFileA(msifile);
3858 }
3859 
3860 static void test_appsearch(void)
3861 {
3862     MSIHANDLE hpkg;
3863     UINT r;
3864     MSIHANDLE hdb;
3865     CHAR prop[MAX_PATH];
3866     DWORD size;
3867     HKEY hkey;
3868     const char reg_expand_value[] = "%systemroot%\\system32\\notepad.exe";
3869 
3870     hdb = create_package_db();
3871     ok ( hdb, "failed to create package database\n" );
3872 
3873     create_appsearch_table( hdb );
3874     add_appsearch_entry( hdb, "'WEBBROWSERPROG', 'NewSignature1'" );
3875     add_appsearch_entry( hdb, "'NOTEPAD', 'NewSignature2'" );
3876     add_appsearch_entry( hdb, "'REGEXPANDVAL', 'NewSignature3'" );
3877     add_appsearch_entry( hdb, "'32KEYVAL', 'NewSignature4'" );
3878     add_appsearch_entry( hdb, "'64KEYVAL', 'NewSignature5'" );
3879 
3880     create_reglocator_table( hdb );
3881     add_reglocator_entry( hdb, "NewSignature1", 0, "htmlfile\\shell\\open\\command", "", 1 );
3882 
3883     r = RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Winetest_msi", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, NULL);
3884     ok( r == ERROR_SUCCESS, "Could not create key: %d.\n", r );
3885     r = RegSetValueExA(hkey, NULL, 0, REG_EXPAND_SZ, (const BYTE*)reg_expand_value, strlen(reg_expand_value) + 1);
3886     ok( r == ERROR_SUCCESS, "Could not set key value: %d.\n", r);
3887     RegCloseKey(hkey);
3888     add_reglocator_entry( hdb, "NewSignature3", 1, "Software\\Winetest_msi", "", msidbLocatorTypeFileName );
3889 
3890     r = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\Winetest_msi", 0, NULL, 0, KEY_ALL_ACCESS|KEY_WOW64_32KEY,
3891                         NULL, &hkey, NULL);
3892     if (r == ERROR_ACCESS_DENIED)
3893     {
3894         skip("insufficient rights\n");
3895         RegDeleteKeyA(HKEY_CURRENT_USER, "Software\\Winetest_msi");
3896         MsiCloseHandle(hdb);
3897         DeleteFileA(msifile);
3898         return;
3899     }
3900     ok( r == ERROR_SUCCESS, "Could not create key: %d.\n", r );
3901 
3902     r = RegSetValueExA(hkey, NULL, 0, REG_SZ, (const BYTE *)"c:\\windows\\system32\\notepad.exe",
3903                        sizeof("c:\\windows\\system32\\notepad.exe"));
3904     ok( r == ERROR_SUCCESS, "Could not set key value: %d.\n", r);
3905     RegCloseKey(hkey);
3906     add_reglocator_entry( hdb, "NewSignature4", 2, "Software\\Winetest_msi", "", msidbLocatorTypeFileName );
3907 
3908     r = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\Winetest_msi", 0, NULL, 0, KEY_ALL_ACCESS|KEY_WOW64_64KEY,
3909                         NULL, &hkey, NULL);
3910     ok( r == ERROR_SUCCESS, "Could not create key: %d.\n", r );
3911     r = RegSetValueExA(hkey, NULL, 0, REG_SZ, (const BYTE *)"c:\\windows\\system32\\notepad.exe",
3912                        sizeof("c:\\windows\\system32\\notepad.exe"));
3913     ok( r == ERROR_SUCCESS, "Could not set key value: %d.\n", r);
3914     RegCloseKey(hkey);
3915     add_reglocator_entry( hdb, "NewSignature5", 2, "Software\\Winetest_msi", "",
3916                           msidbLocatorTypeFileName|msidbLocatorType64bit );
3917 
3918     create_drlocator_table( hdb );
3919     add_drlocator_entry( hdb, "'NewSignature2', 0, 'c:\\windows\\system32', 0" );
3920 
3921     create_signature_table( hdb );
3922     add_signature_entry( hdb, "'NewSignature1', 'FileName', '', '', '', '', '', '', ''" );
3923     add_signature_entry( hdb, "'NewSignature2', 'NOTEPAD.EXE|notepad.exe', '', '', '', '', '', '', ''" );
3924     add_signature_entry( hdb, "'NewSignature3', 'NOTEPAD.EXE|notepad.exe', '', '', '', '', '', '', ''" );
3925     add_signature_entry( hdb, "'NewSignature4', 'NOTEPAD.EXE|notepad.exe', '', '', '', '', '', '', ''" );
3926     add_signature_entry( hdb, "'NewSignature5', 'NOTEPAD.EXE|notepad.exe', '', '', '', '', '', '', ''" );
3927 
3928     r = package_from_db( hdb, &hpkg );
3929     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
3930     {
3931         skip("Not enough rights to perform tests\n");
3932         DeleteFileA(msifile);
3933         return;
3934     }
3935     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3936     MsiCloseHandle( hdb );
3937     if (r != ERROR_SUCCESS)
3938         goto done;
3939 
3940     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3941 
3942     r = MsiDoActionA( hpkg, "AppSearch" );
3943     ok( r == ERROR_SUCCESS, "AppSearch failed: %d\n", r);
3944 
3945     size = sizeof(prop);
3946     r = MsiGetPropertyA( hpkg, "WEBBROWSERPROG", prop, &size );
3947     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
3948     ok( lstrlenA(prop) != 0, "Expected non-zero length\n");
3949 
3950     size = sizeof(prop);
3951     r = MsiGetPropertyA( hpkg, "NOTEPAD", prop, &size );
3952     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
3953 
3954     size = sizeof(prop);
3955     r = MsiGetPropertyA( hpkg, "REGEXPANDVAL", prop, &size );
3956     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
3957     ok( lstrlenA(prop) != 0, "Expected non-zero length\n");
3958 
3959     size = sizeof(prop);
3960     r = MsiGetPropertyA( hpkg, "32KEYVAL", prop, &size );
3961     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
3962     ok( lstrlenA(prop) != 0, "Expected non-zero length\n");
3963 
3964     size = sizeof(prop);
3965     r = MsiGetPropertyA( hpkg, "64KEYVAL", prop, &size );
3966     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
3967     ok( lstrlenA(prop) != 0, "Expected non-zero length\n");
3968 
3969 done:
3970     MsiCloseHandle( hpkg );
3971     DeleteFileA(msifile);
3972     RegDeleteKeyA(HKEY_CURRENT_USER, "Software\\Winetest_msi");
3973     RegDeleteKeyExA(HKEY_LOCAL_MACHINE, "Software\\Winetest_msi", KEY_WOW64_32KEY, 0);
3974     RegDeleteKeyExA(HKEY_LOCAL_MACHINE, "Software\\Winetest_msi", KEY_WOW64_64KEY, 0);
3975 }
3976 
3977 static void test_appsearch_complocator(void)
3978 {
3979     MSIHANDLE hpkg, hdb;
3980     char path[MAX_PATH + 15], expected[MAX_PATH], prop[MAX_PATH];
3981     LPSTR usersid;
3982     DWORD size;
3983     UINT r;
3984 
3985     if (!(usersid = get_user_sid()))
3986         return;
3987 
3988     if (!is_process_elevated())
3989     {
3990         skip("process is limited\n");
3991         return;
3992     }
3993 
3994     create_test_file("FileName1");
3995     create_test_file("FileName4");
3996     set_component_path("FileName1", MSIINSTALLCONTEXT_MACHINE,
3997                        "{A8AE6692-96BA-4198-8399-145D7D1D0D0E}", NULL, FALSE);
3998 
3999     create_test_file("FileName2");
4000     set_component_path("FileName2", MSIINSTALLCONTEXT_USERUNMANAGED,
4001                        "{1D2CE6F3-E81C-4949-AB81-78D7DAD2AF2E}", usersid, FALSE);
4002 
4003     create_test_file("FileName3");
4004     set_component_path("FileName3", MSIINSTALLCONTEXT_USERMANAGED,
4005                        "{19E0B999-85F5-4973-A61B-DBE4D66ECB1D}", usersid, FALSE);
4006 
4007     create_test_file("FileName5");
4008     set_component_path("FileName5", MSIINSTALLCONTEXT_MACHINE,
4009                        "{F0CCA976-27A3-4808-9DDD-1A6FD50A0D5A}", NULL, TRUE);
4010 
4011     create_test_file("FileName6");
4012     set_component_path("FileName6", MSIINSTALLCONTEXT_MACHINE,
4013                        "{C0ECD96F-7898-4410-9667-194BD8C1B648}", NULL, TRUE);
4014 
4015     create_test_file("FileName7");
4016     set_component_path("FileName7", MSIINSTALLCONTEXT_MACHINE,
4017                        "{DB20F535-9C26-4127-9C2B-CC45A8B51DA1}", NULL, FALSE);
4018 
4019     /* dir is FALSE, but we're pretending it's a directory */
4020     set_component_path("IDontExist\\", MSIINSTALLCONTEXT_MACHINE,
4021                        "{91B7359B-07F2-4221-AA8D-DE102BB87A5F}", NULL, FALSE);
4022 
4023     create_file_with_version("FileName8.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4024     set_component_path("FileName8.dll", MSIINSTALLCONTEXT_MACHINE,
4025                        "{4A2E1B5B-4034-4177-833B-8CC35F1B3EF1}", NULL, FALSE);
4026 
4027     create_file_with_version("FileName9.dll", MAKELONG(1, 2), MAKELONG(3, 4));
4028     set_component_path("FileName9.dll", MSIINSTALLCONTEXT_MACHINE,
4029                        "{A204DF48-7346-4635-BA2E-66247DBAC9DF}", NULL, FALSE);
4030 
4031     create_file_with_version("FileName10.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4032     set_component_path("FileName10.dll", MSIINSTALLCONTEXT_MACHINE,
4033                        "{EC30CE73-4CF9-4908-BABD-1ED82E1515FD}", NULL, FALSE);
4034 
4035     hdb = create_package_db();
4036     ok(hdb, "Expected a valid database handle\n");
4037 
4038     create_appsearch_table(hdb);
4039     add_appsearch_entry(hdb, "'SIGPROP1', 'NewSignature1'");
4040     add_appsearch_entry(hdb, "'SIGPROP2', 'NewSignature2'");
4041     add_appsearch_entry(hdb, "'SIGPROP3', 'NewSignature3'");
4042     add_appsearch_entry(hdb, "'SIGPROP4', 'NewSignature4'");
4043     add_appsearch_entry(hdb, "'SIGPROP5', 'NewSignature5'");
4044     add_appsearch_entry(hdb, "'SIGPROP6', 'NewSignature6'");
4045     add_appsearch_entry(hdb, "'SIGPROP7', 'NewSignature7'");
4046     add_appsearch_entry(hdb, "'SIGPROP8', 'NewSignature8'");
4047     add_appsearch_entry(hdb, "'SIGPROP9', 'NewSignature9'");
4048     add_appsearch_entry(hdb, "'SIGPROP10', 'NewSignature10'");
4049     add_appsearch_entry(hdb, "'SIGPROP11', 'NewSignature11'");
4050     add_appsearch_entry(hdb, "'SIGPROP12', 'NewSignature12'");
4051 
4052     create_complocator_table(hdb);
4053 
4054     /* published component, machine, file, signature, misdbLocatorTypeFile */
4055     add_complocator_entry(hdb, "'NewSignature1', '{A8AE6692-96BA-4198-8399-145D7D1D0D0E}', 1");
4056 
4057     /* published component, user-unmanaged, file, signature, misdbLocatorTypeFile */
4058     add_complocator_entry(hdb, "'NewSignature2', '{1D2CE6F3-E81C-4949-AB81-78D7DAD2AF2E}', 1");
4059 
4060     /* published component, user-managed, file, signature, misdbLocatorTypeFile */
4061     add_complocator_entry(hdb, "'NewSignature3', '{19E0B999-85F5-4973-A61B-DBE4D66ECB1D}', 1");
4062 
4063     /* published component, machine, file, signature, misdbLocatorTypeDirectory */
4064     add_complocator_entry(hdb, "'NewSignature4', '{A8AE6692-96BA-4198-8399-145D7D1D0D0E}', 0");
4065 
4066     /* published component, machine, dir, signature, misdbLocatorTypeDirectory */
4067     add_complocator_entry(hdb, "'NewSignature5', '{F0CCA976-27A3-4808-9DDD-1A6FD50A0D5A}', 0");
4068 
4069     /* published component, machine, dir, no signature, misdbLocatorTypeDirectory */
4070     add_complocator_entry(hdb, "'NewSignature6', '{C0ECD96F-7898-4410-9667-194BD8C1B648}', 0");
4071 
4072     /* published component, machine, file, no signature, misdbLocatorTypeFile */
4073     add_complocator_entry(hdb, "'NewSignature7', '{DB20F535-9C26-4127-9C2B-CC45A8B51DA1}', 1");
4074 
4075     /* unpublished component, no signature, misdbLocatorTypeDir */
4076     add_complocator_entry(hdb, "'NewSignature8', '{FB671D5B-5083-4048-90E0-481C48D8F3A5}', 0");
4077 
4078     /* published component, no signature, dir does not exist misdbLocatorTypeDir */
4079     add_complocator_entry(hdb, "'NewSignature9', '{91B7359B-07F2-4221-AA8D-DE102BB87A5F}', 0");
4080 
4081     /* published component, signature w/ ver, misdbLocatorTypeFile */
4082     add_complocator_entry(hdb, "'NewSignature10', '{4A2E1B5B-4034-4177-833B-8CC35F1B3EF1}', 1");
4083 
4084     /* published component, signature w/ ver, ver > max, misdbLocatorTypeFile */
4085     add_complocator_entry(hdb, "'NewSignature11', '{A204DF48-7346-4635-BA2E-66247DBAC9DF}', 1");
4086 
4087     /* published component, signature w/ ver, sig->name ignored, misdbLocatorTypeFile */
4088     add_complocator_entry(hdb, "'NewSignature12', '{EC30CE73-4CF9-4908-BABD-1ED82E1515FD}', 1");
4089 
4090     create_signature_table(hdb);
4091     add_signature_entry(hdb, "'NewSignature1', 'FileName1', '', '', '', '', '', '', ''");
4092     add_signature_entry(hdb, "'NewSignature2', 'FileName2', '', '', '', '', '', '', ''");
4093     add_signature_entry(hdb, "'NewSignature3', 'FileName3', '', '', '', '', '', '', ''");
4094     add_signature_entry(hdb, "'NewSignature4', 'FileName4', '', '', '', '', '', '', ''");
4095     add_signature_entry(hdb, "'NewSignature5', 'FileName5', '', '', '', '', '', '', ''");
4096     add_signature_entry(hdb, "'NewSignature10', 'FileName8.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4097     add_signature_entry(hdb, "'NewSignature11', 'FileName9.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4098     add_signature_entry(hdb, "'NewSignature12', 'ignored', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4099 
4100     r = package_from_db(hdb, &hpkg);
4101     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
4102     {
4103         skip("Not enough rights to perform tests\n");
4104         goto error;
4105     }
4106     ok(r == ERROR_SUCCESS, "Expected a valid package handle %u\n", r);
4107 
4108     r = MsiSetPropertyA(hpkg, "SIGPROP8", "october");
4109     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4110 
4111     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4112 
4113     r = MsiDoActionA(hpkg, "AppSearch");
4114     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4115 
4116     strcpy(expected, CURR_DIR);
4117     if (is_root(CURR_DIR)) expected[2] = 0;
4118 
4119     size = MAX_PATH;
4120     sprintf(path, "%s\\FileName1", expected);
4121     r = MsiGetPropertyA(hpkg, "SIGPROP1", prop, &size);
4122     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4123     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4124 
4125     size = MAX_PATH;
4126     sprintf(path, "%s\\FileName2", expected);
4127     r = MsiGetPropertyA(hpkg, "SIGPROP2", prop, &size);
4128     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4129     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4130 
4131     size = MAX_PATH;
4132     sprintf(path, "%s\\FileName3", expected);
4133     r = MsiGetPropertyA(hpkg, "SIGPROP3", prop, &size);
4134     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4135     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4136 
4137     size = MAX_PATH;
4138     sprintf(path, "%s\\FileName4", expected);
4139     r = MsiGetPropertyA(hpkg, "SIGPROP4", prop, &size);
4140     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4141     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4142 
4143     size = MAX_PATH;
4144     sprintf(path, "%s\\FileName5", expected);
4145     r = MsiGetPropertyA(hpkg, "SIGPROP5", prop, &size);
4146     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4147     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4148 
4149     size = MAX_PATH;
4150     sprintf(path, "%s\\", expected);
4151     r = MsiGetPropertyA(hpkg, "SIGPROP6", prop, &size);
4152     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4153     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4154 
4155     size = MAX_PATH;
4156     sprintf(path, "%s\\", expected);
4157     r = MsiGetPropertyA(hpkg, "SIGPROP7", prop, &size);
4158     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4159     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4160 
4161     size = MAX_PATH;
4162     r = MsiGetPropertyA(hpkg, "SIGPROP8", prop, &size);
4163     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4164     ok(!lstrcmpA(prop, "october"), "Expected \"october\", got \"%s\"\n", prop);
4165 
4166     size = MAX_PATH;
4167     r = MsiGetPropertyA(hpkg, "SIGPROP9", prop, &size);
4168     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4169     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4170 
4171     size = MAX_PATH;
4172     sprintf(path, "%s\\FileName8.dll", expected);
4173     r = MsiGetPropertyA(hpkg, "SIGPROP10", prop, &size);
4174     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4175     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4176 
4177     size = MAX_PATH;
4178     r = MsiGetPropertyA(hpkg, "SIGPROP11", prop, &size);
4179     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4180     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4181 
4182     size = MAX_PATH;
4183     sprintf(path, "%s\\FileName10.dll", expected);
4184     r = MsiGetPropertyA(hpkg, "SIGPROP12", prop, &size);
4185     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4186     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4187 
4188     delete_component_path("{A8AE6692-96BA-4198-8399-145D7D1D0D0E}",
4189                           MSIINSTALLCONTEXT_MACHINE, NULL);
4190     delete_component_path("{1D2CE6F3-E81C-4949-AB81-78D7DAD2AF2E}",
4191                           MSIINSTALLCONTEXT_USERUNMANAGED, usersid);
4192     delete_component_path("{19E0B999-85F5-4973-A61B-DBE4D66ECB1D}",
4193                           MSIINSTALLCONTEXT_USERMANAGED, usersid);
4194     delete_component_path("{F0CCA976-27A3-4808-9DDD-1A6FD50A0D5A}",
4195                           MSIINSTALLCONTEXT_MACHINE, NULL);
4196     delete_component_path("{C0ECD96F-7898-4410-9667-194BD8C1B648}",
4197                           MSIINSTALLCONTEXT_MACHINE, NULL);
4198     delete_component_path("{DB20F535-9C26-4127-9C2B-CC45A8B51DA1}",
4199                           MSIINSTALLCONTEXT_MACHINE, NULL);
4200     delete_component_path("{91B7359B-07F2-4221-AA8D-DE102BB87A5F}",
4201                           MSIINSTALLCONTEXT_MACHINE, NULL);
4202     delete_component_path("{4A2E1B5B-4034-4177-833B-8CC35F1B3EF1}",
4203                           MSIINSTALLCONTEXT_MACHINE, NULL);
4204     delete_component_path("{A204DF48-7346-4635-BA2E-66247DBAC9DF}",
4205                           MSIINSTALLCONTEXT_MACHINE, NULL);
4206     delete_component_path("{EC30CE73-4CF9-4908-BABD-1ED82E1515FD}",
4207                           MSIINSTALLCONTEXT_MACHINE, NULL);
4208 
4209     MsiCloseHandle(hpkg);
4210 
4211 error:
4212     DeleteFileA("FileName1");
4213     DeleteFileA("FileName2");
4214     DeleteFileA("FileName3");
4215     DeleteFileA("FileName4");
4216     DeleteFileA("FileName5");
4217     DeleteFileA("FileName6");
4218     DeleteFileA("FileName7");
4219     DeleteFileA("FileName8.dll");
4220     DeleteFileA("FileName9.dll");
4221     DeleteFileA("FileName10.dll");
4222     DeleteFileA(msifile);
4223     LocalFree(usersid);
4224 }
4225 
4226 static void test_appsearch_reglocator(void)
4227 {
4228     MSIHANDLE hpkg, hdb;
4229     char path[MAX_PATH + 20], expected[MAX_PATH], prop[MAX_PATH];
4230     DWORD binary[2], size, val;
4231     BOOL space, version, is_64bit = sizeof(void *) > sizeof(int);
4232     HKEY hklm, classes, hkcu, users;
4233     LPSTR pathdata, pathvar, ptr;
4234     LONG res;
4235     UINT r, type = 0;
4236     SYSTEM_INFO si;
4237 
4238     version = TRUE;
4239     if (!create_file_with_version("test.dll", MAKELONG(2, 1), MAKELONG(4, 3)))
4240         version = FALSE;
4241 
4242     DeleteFileA("test.dll");
4243 
4244     res = RegCreateKeyA(HKEY_CLASSES_ROOT, "Software\\Wine", &classes);
4245     if (res == ERROR_ACCESS_DENIED)
4246     {
4247         skip("Not enough rights to perform tests\n");
4248         return;
4249     }
4250     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4251 
4252     res = RegSetValueExA(classes, "Value1", 0, REG_SZ,
4253                          (const BYTE *)"regszdata", 10);
4254     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4255 
4256     res = RegCreateKeyA(HKEY_CURRENT_USER, "Software\\Wine", &hkcu);
4257     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4258 
4259     res = RegSetValueExA(hkcu, "Value1", 0, REG_SZ,
4260                          (const BYTE *)"regszdata", 10);
4261     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4262 
4263     users = 0;
4264     res = RegCreateKeyA(HKEY_USERS, "S-1-5-18\\Software\\Wine", &users);
4265     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4266 
4267     if (res == ERROR_SUCCESS)
4268     {
4269         res = RegSetValueExA(users, "Value1", 0, REG_SZ,
4270                              (const BYTE *)"regszdata", 10);
4271         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4272     }
4273 
4274     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine", &hklm);
4275     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4276 
4277     res = RegSetValueA(hklm, NULL, REG_SZ, "defvalue", 8);
4278     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4279 
4280     res = RegSetValueExA(hklm, "Value1", 0, REG_SZ,
4281                          (const BYTE *)"regszdata", 10);
4282     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4283 
4284     val = 42;
4285     res = RegSetValueExA(hklm, "Value2", 0, REG_DWORD,
4286                          (const BYTE *)&val, sizeof(DWORD));
4287     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4288 
4289     val = -42;
4290     res = RegSetValueExA(hklm, "Value3", 0, REG_DWORD,
4291                          (const BYTE *)&val, sizeof(DWORD));
4292     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4293 
4294     res = RegSetValueExA(hklm, "Value4", 0, REG_EXPAND_SZ,
4295                          (const BYTE *)"%PATH%", 7);
4296     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4297 
4298     res = RegSetValueExA(hklm, "Value5", 0, REG_EXPAND_SZ,
4299                          (const BYTE *)"my%NOVAR%", 10);
4300     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4301 
4302     res = RegSetValueExA(hklm, "Value6", 0, REG_MULTI_SZ,
4303                          (const BYTE *)"one\0two\0", 9);
4304     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4305 
4306     binary[0] = 0x1234abcd;
4307     binary[1] = 0x567890ef;
4308     res = RegSetValueExA(hklm, "Value7", 0, REG_BINARY,
4309                          (const BYTE *)binary, sizeof(binary));
4310     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4311 
4312     res = RegSetValueExA(hklm, "Value8", 0, REG_SZ,
4313                          (const BYTE *)"#regszdata", 11);
4314     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4315 
4316     strcpy(expected, CURR_DIR);
4317     if (is_root(CURR_DIR)) expected[2] = 0;
4318 
4319     create_test_file("FileName1");
4320     sprintf(path, "%s\\FileName1", expected);
4321     res = RegSetValueExA(hklm, "Value9", 0, REG_SZ,
4322                          (const BYTE *)path, lstrlenA(path) + 1);
4323     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4324 
4325     sprintf(path, "%s\\FileName2", expected);
4326     res = RegSetValueExA(hklm, "Value10", 0, REG_SZ,
4327                          (const BYTE *)path, lstrlenA(path) + 1);
4328     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4329 
4330     lstrcpyA(path, expected);
4331     res = RegSetValueExA(hklm, "Value11", 0, REG_SZ,
4332                          (const BYTE *)path, lstrlenA(path) + 1);
4333     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4334 
4335     res = RegSetValueExA(hklm, "Value12", 0, REG_SZ,
4336                          (const BYTE *)"", 1);
4337     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4338 
4339     create_file_with_version("FileName3.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4340     sprintf(path, "%s\\FileName3.dll", expected);
4341     res = RegSetValueExA(hklm, "Value13", 0, REG_SZ,
4342                          (const BYTE *)path, lstrlenA(path) + 1);
4343     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4344 
4345     create_file_with_version("FileName4.dll", MAKELONG(1, 2), MAKELONG(3, 4));
4346     sprintf(path, "%s\\FileName4.dll", expected);
4347     res = RegSetValueExA(hklm, "Value14", 0, REG_SZ,
4348                          (const BYTE *)path, lstrlenA(path) + 1);
4349     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4350 
4351     create_file_with_version("FileName5.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4352     sprintf(path, "%s\\FileName5.dll", expected);
4353     res = RegSetValueExA(hklm, "Value15", 0, REG_SZ,
4354                          (const BYTE *)path, lstrlenA(path) + 1);
4355     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
4356 
4357     sprintf(path, "\"%s\\FileName1\" -option", expected);
4358     res = RegSetValueExA(hklm, "value16", 0, REG_SZ,
4359                          (const BYTE *)path, lstrlenA(path) + 1);
4360     ok( res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %ld\n", res);
4361 
4362     space = strchr(expected, ' ') != NULL;
4363     sprintf(path, "%s\\FileName1 -option", expected);
4364     res = RegSetValueExA(hklm, "value17", 0, REG_SZ,
4365                          (const BYTE *)path, lstrlenA(path) + 1);
4366     ok( res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %ld\n", res);
4367 
4368     hdb = create_package_db();
4369     ok(hdb, "Expected a valid database handle\n");
4370 
4371     create_appsearch_table(hdb);
4372     add_appsearch_entry(hdb, "'SIGPROP1', 'NewSignature1'");
4373     add_appsearch_entry(hdb, "'SIGPROP2', 'NewSignature2'");
4374     add_appsearch_entry(hdb, "'SIGPROP3', 'NewSignature3'");
4375     add_appsearch_entry(hdb, "'SIGPROP4', 'NewSignature4'");
4376     add_appsearch_entry(hdb, "'SIGPROP5', 'NewSignature5'");
4377     add_appsearch_entry(hdb, "'SIGPROP6', 'NewSignature6'");
4378     add_appsearch_entry(hdb, "'SIGPROP7', 'NewSignature7'");
4379     add_appsearch_entry(hdb, "'SIGPROP8', 'NewSignature8'");
4380     add_appsearch_entry(hdb, "'SIGPROP9', 'NewSignature9'");
4381     add_appsearch_entry(hdb, "'SIGPROP10', 'NewSignature10'");
4382     add_appsearch_entry(hdb, "'SIGPROP11', 'NewSignature11'");
4383     add_appsearch_entry(hdb, "'SIGPROP12', 'NewSignature12'");
4384     add_appsearch_entry(hdb, "'SIGPROP13', 'NewSignature13'");
4385     add_appsearch_entry(hdb, "'SIGPROP14', 'NewSignature14'");
4386     add_appsearch_entry(hdb, "'SIGPROP15', 'NewSignature15'");
4387     add_appsearch_entry(hdb, "'SIGPROP16', 'NewSignature16'");
4388     add_appsearch_entry(hdb, "'SIGPROP17', 'NewSignature17'");
4389     add_appsearch_entry(hdb, "'SIGPROP18', 'NewSignature18'");
4390     add_appsearch_entry(hdb, "'SIGPROP19', 'NewSignature19'");
4391     add_appsearch_entry(hdb, "'SIGPROP20', 'NewSignature20'");
4392     add_appsearch_entry(hdb, "'SIGPROP21', 'NewSignature21'");
4393     add_appsearch_entry(hdb, "'SIGPROP22', 'NewSignature22'");
4394     add_appsearch_entry(hdb, "'SIGPROP23', 'NewSignature23'");
4395     add_appsearch_entry(hdb, "'SIGPROP24', 'NewSignature24'");
4396     add_appsearch_entry(hdb, "'SIGPROP25', 'NewSignature25'");
4397     add_appsearch_entry(hdb, "'SIGPROP26', 'NewSignature26'");
4398     add_appsearch_entry(hdb, "'SIGPROP27', 'NewSignature27'");
4399     add_appsearch_entry(hdb, "'SIGPROP28', 'NewSignature28'");
4400     add_appsearch_entry(hdb, "'SIGPROP29', 'NewSignature29'");
4401     add_appsearch_entry(hdb, "'SIGPROP30', 'NewSignature30'");
4402 
4403     create_reglocator_table(hdb);
4404 
4405     type = msidbLocatorTypeRawValue;
4406     if (is_64bit)
4407         type |= msidbLocatorType64bit;
4408 
4409     /* HKLM, msidbLocatorTypeRawValue, REG_SZ */
4410     add_reglocator_entry(hdb, "NewSignature1", 2, "Software\\Wine", "Value1", type);
4411 
4412     /* HKLM, msidbLocatorTypeRawValue, positive DWORD */
4413     add_reglocator_entry(hdb, "NewSignature2", 2, "Software\\Wine", "Value2", type);
4414 
4415     /* HKLM, msidbLocatorTypeRawValue, negative DWORD */
4416     add_reglocator_entry(hdb, "NewSignature3", 2, "Software\\Wine", "Value3", type);
4417 
4418     /* HKLM, msidbLocatorTypeRawValue, REG_EXPAND_SZ */
4419     add_reglocator_entry(hdb, "NewSignature4", 2, "Software\\Wine", "Value4", type);
4420 
4421     /* HKLM, msidbLocatorTypeRawValue, REG_EXPAND_SZ */
4422     add_reglocator_entry(hdb, "NewSignature5", 2, "Software\\Wine", "Value5", type);
4423 
4424     /* HKLM, msidbLocatorTypeRawValue, REG_MULTI_SZ */
4425     add_reglocator_entry(hdb, "NewSignature6", 2, "Software\\Wine", "Value6", type);
4426 
4427     /* HKLM, msidbLocatorTypeRawValue, REG_BINARY */
4428     add_reglocator_entry(hdb, "NewSignature7", 2, "Software\\Wine", "Value7", type);
4429 
4430     /* HKLM, msidbLocatorTypeRawValue, REG_SZ first char is # */
4431     add_reglocator_entry(hdb, "NewSignature8", 2, "Software\\Wine", "Value8", type);
4432 
4433     type = msidbLocatorTypeFileName;
4434     if (is_64bit)
4435         type |= msidbLocatorType64bit;
4436 
4437     /* HKLM, msidbLocatorTypeFileName, signature, file exists */
4438     add_reglocator_entry(hdb, "NewSignature9", 2, "Software\\Wine", "Value9", type);
4439 
4440     /* HKLM, msidbLocatorTypeFileName, signature, file does not exist */
4441     add_reglocator_entry(hdb, "NewSignature10", 2, "Software\\Wine", "Value10", type);
4442 
4443     /* HKLM, msidbLocatorTypeFileName, no signature */
4444     add_reglocator_entry(hdb, "NewSignature11", 2, "Software\\Wine", "Value9", type);
4445 
4446     type = msidbLocatorTypeDirectory;
4447     if (is_64bit)
4448         type |= msidbLocatorType64bit;
4449 
4450     /* HKLM, msidbLocatorTypeDirectory, no signature, file exists */
4451     add_reglocator_entry(hdb, "NewSignature12", 2, "Software\\Wine", "Value9", type);
4452 
4453     /* HKLM, msidbLocatorTypeDirectory, no signature, directory exists */
4454     add_reglocator_entry(hdb, "NewSignature13", 2, "Software\\Wine", "Value11", type);
4455 
4456     /* HKLM, msidbLocatorTypeDirectory, signature, file exists */
4457     add_reglocator_entry(hdb, "NewSignature14", 2, "Software\\Wine", "Value9", type);
4458 
4459     type = msidbLocatorTypeRawValue;
4460     if (is_64bit)
4461         type |= msidbLocatorType64bit;
4462 
4463     /* HKCR, msidbLocatorTypeRawValue, REG_SZ */
4464     add_reglocator_entry(hdb, "NewSignature15", 0, "Software\\Wine", "Value1", type);
4465 
4466     /* HKCU, msidbLocatorTypeRawValue, REG_SZ */
4467     add_reglocator_entry(hdb, "NewSignature16", 1, "Software\\Wine", "Value1", type);
4468 
4469     /* HKU, msidbLocatorTypeRawValue, REG_SZ */
4470     add_reglocator_entry(hdb, "NewSignature17", 3, "S-1-5-18\\Software\\Wine", "Value1", type);
4471 
4472     /* HKLM, msidbLocatorTypeRawValue, REG_SZ, NULL Name */
4473     add_reglocator_entry(hdb, "NewSignature18", 2, "Software\\Wine", "", type);
4474 
4475     /* HKLM, msidbLocatorTypeRawValue, REG_SZ, key does not exist */
4476     add_reglocator_entry(hdb, "NewSignature19", 2, "Software\\IDontExist", "", type);
4477 
4478     /* HKLM, msidbLocatorTypeRawValue, REG_SZ, value is empty */
4479     add_reglocator_entry(hdb, "NewSignature20", 2, "Software\\Wine", "Value12", type);
4480 
4481     type = msidbLocatorTypeFileName;
4482     if (is_64bit)
4483         type |= msidbLocatorType64bit;
4484 
4485     /* HKLM, msidbLocatorTypeFileName, signature, file exists w/ version */
4486     add_reglocator_entry(hdb, "NewSignature21", 2, "Software\\Wine", "Value13", type);
4487 
4488     /* HKLM, msidbLocatorTypeFileName, file exists w/ version, version > max */
4489     add_reglocator_entry(hdb, "NewSignature22", 2, "Software\\Wine", "Value14", type);
4490 
4491     /* HKLM, msidbLocatorTypeFileName, file exists w/ version, sig->name ignored */
4492     add_reglocator_entry(hdb, "NewSignature23", 2, "Software\\Wine", "Value15", type);
4493 
4494     /* HKLM, msidbLocatorTypeFileName, no signature, directory exists */
4495     add_reglocator_entry(hdb, "NewSignature24", 2, "Software\\Wine", "Value11", type);
4496 
4497     /* HKLM, msidbLocatorTypeFileName, no signature, file does not exist */
4498     add_reglocator_entry(hdb, "NewSignature25", 2, "Software\\Wine", "Value10", type);
4499 
4500     type = msidbLocatorTypeDirectory;
4501     if (is_64bit)
4502         type |= msidbLocatorType64bit;
4503 
4504     /* HKLM, msidbLocatorTypeDirectory, signature, directory exists */
4505     add_reglocator_entry(hdb, "NewSignature26", 2, "Software\\Wine", "Value11", type);
4506 
4507     /* HKLM, msidbLocatorTypeDirectory, signature, file does not exist */
4508     add_reglocator_entry(hdb, "NewSignature27", 2, "Software\\Wine", "Value10", type);
4509 
4510     /* HKLM, msidbLocatorTypeDirectory, no signature, file does not exist */
4511     add_reglocator_entry(hdb, "NewSignature28", 2, "Software\\Wine", "Value10", type);
4512 
4513     type = msidbLocatorTypeFileName;
4514     if (is_64bit)
4515         type |= msidbLocatorType64bit;
4516 
4517     /* HKLM, msidbLocatorTypeFile, file exists, in quotes */
4518     add_reglocator_entry(hdb, "NewSignature29", 2, "Software\\Wine", "Value16", type);
4519 
4520     /* HKLM, msidbLocatorTypeFile, file exists, no quotes */
4521     add_reglocator_entry(hdb, "NewSignature30", 2, "Software\\Wine", "Value17", type);
4522 
4523     create_signature_table(hdb);
4524     add_signature_entry(hdb, "'NewSignature9', 'FileName1', '', '', '', '', '', '', ''");
4525     add_signature_entry(hdb, "'NewSignature10', 'FileName2', '', '', '', '', '', '', ''");
4526     add_signature_entry(hdb, "'NewSignature14', 'FileName1', '', '', '', '', '', '', ''");
4527     add_signature_entry(hdb, "'NewSignature21', 'FileName3.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4528     add_signature_entry(hdb, "'NewSignature22', 'FileName4.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4529     add_signature_entry(hdb, "'NewSignature23', 'ignored', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4530 
4531     if (!is_root(CURR_DIR))
4532     {
4533         ptr = strrchr(expected, '\\') + 1;
4534         sprintf(path, "'NewSignature26', '%s', '', '', '', '', '', '', ''", ptr);
4535         add_signature_entry(hdb, path);
4536     }
4537     add_signature_entry(hdb, "'NewSignature27', 'FileName2', '', '', '', '', '', '', ''");
4538     add_signature_entry(hdb, "'NewSignature29', 'FileName1', '', '', '', '', '', '', ''");
4539     add_signature_entry(hdb, "'NewSignature30', 'FileName1', '', '', '', '', '', '', ''");
4540 
4541     r = package_from_db(hdb, &hpkg);
4542     ok(r == ERROR_SUCCESS, "Expected a valid package handle %u\n", r);
4543 
4544     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4545 
4546     r = MsiDoActionA(hpkg, "AppSearch");
4547     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4548 
4549     size = MAX_PATH;
4550     r = MsiGetPropertyA(hpkg, "SIGPROP1", prop, &size);
4551     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4552     ok(!lstrcmpA(prop, "regszdata"),
4553        "Expected \"regszdata\", got \"%s\"\n", prop);
4554 
4555     size = MAX_PATH;
4556     r = MsiGetPropertyA(hpkg, "SIGPROP2", prop, &size);
4557     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4558     ok(!lstrcmpA(prop, "#42"), "Expected \"#42\", got \"%s\"\n", prop);
4559 
4560     size = MAX_PATH;
4561     r = MsiGetPropertyA(hpkg, "SIGPROP3", prop, &size);
4562     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4563     ok(!lstrcmpA(prop, "#-42"), "Expected \"#-42\", got \"%s\"\n", prop);
4564 
4565     memset(&si, 0, sizeof(si));
4566     GetNativeSystemInfo(&si);
4567 
4568     if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
4569     {
4570         size = ExpandEnvironmentStringsA("%PATH%", NULL, 0);
4571         pathvar = malloc(size);
4572         ExpandEnvironmentStringsA("%PATH%", pathvar, size);
4573 
4574         size = 0;
4575         r = MsiGetPropertyA(hpkg, "SIGPROP4", NULL, &size);
4576         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4577 
4578         pathdata = malloc(++size);
4579         r = MsiGetPropertyA(hpkg, "SIGPROP4", pathdata, &size);
4580         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4581         ok(!lstrcmpA(pathdata, pathvar),
4582             "Expected \"%s\", got \"%s\"\n", pathvar, pathdata);
4583 
4584         free(pathvar);
4585         free(pathdata);
4586     }
4587 
4588     size = MAX_PATH;
4589     r = MsiGetPropertyA(hpkg, "SIGPROP5", prop, &size);
4590     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4591     ok(!lstrcmpA(prop,
4592        "my%NOVAR%"), "Expected \"my%%NOVAR%%\", got \"%s\"\n", prop);
4593 
4594     size = MAX_PATH;
4595     r = MsiGetPropertyA(hpkg, "SIGPROP6", prop, &size);
4596     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4597     todo_wine
4598     {
4599         ok(!memcmp(prop, "\0one\0two\0\0", 10),
4600            "Expected \"\\0one\\0two\\0\\0\"\n");
4601     }
4602 
4603     size = MAX_PATH;
4604     lstrcpyA(path, "#xCDAB3412EF907856");
4605     r = MsiGetPropertyA(hpkg, "SIGPROP7", prop, &size);
4606     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4607     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4608 
4609     size = MAX_PATH;
4610     r = MsiGetPropertyA(hpkg, "SIGPROP8", prop, &size);
4611     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4612     ok(!lstrcmpA(prop, "##regszdata"),
4613        "Expected \"##regszdata\", got \"%s\"\n", prop);
4614 
4615     size = MAX_PATH;
4616     sprintf(path, "%s\\FileName1", expected);
4617     r = MsiGetPropertyA(hpkg, "SIGPROP9", prop, &size);
4618     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4619     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4620 
4621     size = MAX_PATH;
4622     r = MsiGetPropertyA(hpkg, "SIGPROP10", prop, &size);
4623     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4624     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4625 
4626     size = MAX_PATH;
4627     sprintf(path, "%s\\", expected);
4628     r = MsiGetPropertyA(hpkg, "SIGPROP11", prop, &size);
4629     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4630     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4631 
4632     size = MAX_PATH;
4633     r = MsiGetPropertyA(hpkg, "SIGPROP12", prop, &size);
4634     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4635     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4636 
4637     size = MAX_PATH;
4638     sprintf(path, "%s\\", expected);
4639     r = MsiGetPropertyA(hpkg, "SIGPROP13", prop, &size);
4640     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4641     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4642 
4643     size = MAX_PATH;
4644     r = MsiGetPropertyA(hpkg, "SIGPROP14", prop, &size);
4645     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4646     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4647 
4648     size = MAX_PATH;
4649     r = MsiGetPropertyA(hpkg, "SIGPROP15", prop, &size);
4650     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4651     ok(!lstrcmpA(prop, "regszdata"),
4652        "Expected \"regszdata\", got \"%s\"\n", prop);
4653 
4654     size = MAX_PATH;
4655     r = MsiGetPropertyA(hpkg, "SIGPROP16", prop, &size);
4656     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4657     ok(!lstrcmpA(prop, "regszdata"),
4658        "Expected \"regszdata\", got \"%s\"\n", prop);
4659 
4660     if (users)
4661     {
4662         size = MAX_PATH;
4663         r = MsiGetPropertyA(hpkg, "SIGPROP17", prop, &size);
4664         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4665         ok(!lstrcmpA(prop, "regszdata"),
4666            "Expected \"regszdata\", got \"%s\"\n", prop);
4667     }
4668 
4669     size = MAX_PATH;
4670     r = MsiGetPropertyA(hpkg, "SIGPROP18", prop, &size);
4671     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4672     ok(!lstrcmpA(prop, "defvalue"),
4673        "Expected \"defvalue\", got \"%s\"\n", prop);
4674 
4675     size = MAX_PATH;
4676     r = MsiGetPropertyA(hpkg, "SIGPROP19", prop, &size);
4677     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4678     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4679 
4680     size = MAX_PATH;
4681     r = MsiGetPropertyA(hpkg, "SIGPROP20", prop, &size);
4682     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4683     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4684 
4685     if (version)
4686     {
4687         size = MAX_PATH;
4688         sprintf(path, "%s\\FileName3.dll", expected);
4689         r = MsiGetPropertyA(hpkg, "SIGPROP21", prop, &size);
4690         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4691         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4692 
4693         size = MAX_PATH;
4694         r = MsiGetPropertyA(hpkg, "SIGPROP22", prop, &size);
4695         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4696         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4697 
4698         size = MAX_PATH;
4699         sprintf(path, "%s\\FileName5.dll", expected);
4700         r = MsiGetPropertyA(hpkg, "SIGPROP23", prop, &size);
4701         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4702         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4703     }
4704 
4705     if (!is_root(CURR_DIR))
4706     {
4707         size = MAX_PATH;
4708         lstrcpyA(path, expected);
4709         ptr = strrchr(path, '\\') + 1;
4710         *ptr = '\0';
4711         r = MsiGetPropertyA(hpkg, "SIGPROP24", prop, &size);
4712         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4713         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4714     }
4715     size = MAX_PATH;
4716     sprintf(path, "%s\\", expected);
4717     r = MsiGetPropertyA(hpkg, "SIGPROP25", prop, &size);
4718     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4719     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4720 
4721     size = MAX_PATH;
4722     r = MsiGetPropertyA(hpkg, "SIGPROP26", prop, &size);
4723     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4724     if (is_root(CURR_DIR))
4725         ok(!lstrcmpA(prop, CURR_DIR), "Expected \"%s\", got \"%s\"\n", CURR_DIR, prop);
4726     else
4727         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4728 
4729     size = MAX_PATH;
4730     r = MsiGetPropertyA(hpkg, "SIGPROP27", prop, &size);
4731     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4732     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4733 
4734     size = MAX_PATH;
4735     r = MsiGetPropertyA(hpkg, "SIGPROP28", prop, &size);
4736     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4737     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4738 
4739     size = MAX_PATH;
4740     sprintf(path, "%s\\FileName1", expected);
4741     r = MsiGetPropertyA(hpkg, "SIGPROP29", prop, &size);
4742     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4743     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4744 
4745     size = MAX_PATH;
4746     sprintf(path, "%s\\FileName1", expected);
4747     r = MsiGetPropertyA(hpkg, "SIGPROP30", prop, &size);
4748     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4749     if (space)
4750         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4751     else
4752         todo_wine ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4753 
4754     RegSetValueA(hklm, NULL, REG_SZ, "", 0);
4755     RegDeleteValueA(hklm, "Value1");
4756     RegDeleteValueA(hklm, "Value2");
4757     RegDeleteValueA(hklm, "Value3");
4758     RegDeleteValueA(hklm, "Value4");
4759     RegDeleteValueA(hklm, "Value5");
4760     RegDeleteValueA(hklm, "Value6");
4761     RegDeleteValueA(hklm, "Value7");
4762     RegDeleteValueA(hklm, "Value8");
4763     RegDeleteValueA(hklm, "Value9");
4764     RegDeleteValueA(hklm, "Value10");
4765     RegDeleteValueA(hklm, "Value11");
4766     RegDeleteValueA(hklm, "Value12");
4767     RegDeleteValueA(hklm, "Value13");
4768     RegDeleteValueA(hklm, "Value14");
4769     RegDeleteValueA(hklm, "Value15");
4770     RegDeleteValueA(hklm, "Value16");
4771     RegDeleteValueA(hklm, "Value17");
4772     RegDeleteKeyA(hklm, "");
4773     RegCloseKey(hklm);
4774 
4775     RegDeleteValueA(classes, "Value1");
4776     RegDeleteKeyA(classes, "");
4777     RegCloseKey(classes);
4778 
4779     RegDeleteValueA(hkcu, "Value1");
4780     RegDeleteKeyA(hkcu, "");
4781     RegCloseKey(hkcu);
4782 
4783     RegDeleteValueA(users, "Value1");
4784     RegDeleteKeyA(users, "");
4785     RegCloseKey(users);
4786 
4787     DeleteFileA("FileName1");
4788     DeleteFileA("FileName3.dll");
4789     DeleteFileA("FileName4.dll");
4790     DeleteFileA("FileName5.dll");
4791     MsiCloseHandle(hpkg);
4792     DeleteFileA(msifile);
4793 }
4794 
4795 static void delete_win_ini(LPCSTR file)
4796 {
4797     CHAR path[MAX_PATH];
4798 
4799     GetWindowsDirectoryA(path, MAX_PATH);
4800     lstrcatA(path, "\\");
4801     lstrcatA(path, file);
4802 
4803     DeleteFileA(path);
4804 }
4805 
4806 static void test_appsearch_inilocator(void)
4807 {
4808     MSIHANDLE hpkg, hdb;
4809     char path[MAX_PATH + 14], expected[MAX_PATH], prop[MAX_PATH];
4810     BOOL version;
4811     LPSTR ptr;
4812     DWORD size;
4813     UINT r;
4814 
4815     version = TRUE;
4816     if (!create_file_with_version("test.dll", MAKELONG(2, 1), MAKELONG(4, 3)))
4817         version = FALSE;
4818 
4819     DeleteFileA("test.dll");
4820 
4821     WritePrivateProfileStringA("Section", "Key", "keydata,field2", "IniFile.ini");
4822 
4823     strcpy(expected, CURR_DIR);
4824     if (is_root(CURR_DIR)) expected[2] = 0;
4825 
4826     create_test_file("FileName1");
4827     sprintf(path, "%s\\FileName1", expected);
4828     WritePrivateProfileStringA("Section", "Key2", path, "IniFile.ini");
4829 
4830     WritePrivateProfileStringA("Section", "Key3", expected, "IniFile.ini");
4831 
4832     sprintf(path, "%s\\IDontExist", expected);
4833     WritePrivateProfileStringA("Section", "Key4", path, "IniFile.ini");
4834 
4835     create_file_with_version("FileName2.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4836     sprintf(path, "%s\\FileName2.dll", expected);
4837     WritePrivateProfileStringA("Section", "Key5", path, "IniFile.ini");
4838 
4839     create_file_with_version("FileName3.dll", MAKELONG(1, 2), MAKELONG(3, 4));
4840     sprintf(path, "%s\\FileName3.dll", expected);
4841     WritePrivateProfileStringA("Section", "Key6", path, "IniFile.ini");
4842 
4843     create_file_with_version("FileName4.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4844     sprintf(path, "%s\\FileName4.dll", expected);
4845     WritePrivateProfileStringA("Section", "Key7", path, "IniFile.ini");
4846 
4847     hdb = create_package_db();
4848     ok(hdb, "Expected a valid database handle\n");
4849 
4850     create_appsearch_table(hdb);
4851     add_appsearch_entry(hdb, "'SIGPROP1', 'NewSignature1'");
4852     add_appsearch_entry(hdb, "'SIGPROP2', 'NewSignature2'");
4853     add_appsearch_entry(hdb, "'SIGPROP3', 'NewSignature3'");
4854     add_appsearch_entry(hdb, "'SIGPROP4', 'NewSignature4'");
4855     add_appsearch_entry(hdb, "'SIGPROP5', 'NewSignature5'");
4856     add_appsearch_entry(hdb, "'SIGPROP6', 'NewSignature6'");
4857     add_appsearch_entry(hdb, "'SIGPROP7', 'NewSignature7'");
4858     add_appsearch_entry(hdb, "'SIGPROP8', 'NewSignature8'");
4859     add_appsearch_entry(hdb, "'SIGPROP9', 'NewSignature9'");
4860     add_appsearch_entry(hdb, "'SIGPROP10', 'NewSignature10'");
4861     add_appsearch_entry(hdb, "'SIGPROP11', 'NewSignature11'");
4862     add_appsearch_entry(hdb, "'SIGPROP12', 'NewSignature12'");
4863 
4864     create_inilocator_table(hdb);
4865 
4866     /* msidbLocatorTypeRawValue, field 1 */
4867     add_inilocator_entry(hdb, "'NewSignature1', 'IniFile.ini', 'Section', 'Key', 1, 2");
4868 
4869     /* msidbLocatorTypeRawValue, field 2 */
4870     add_inilocator_entry(hdb, "'NewSignature2', 'IniFile.ini', 'Section', 'Key', 2, 2");
4871 
4872     /* msidbLocatorTypeRawValue, entire field */
4873     add_inilocator_entry(hdb, "'NewSignature3', 'IniFile.ini', 'Section', 'Key', 0, 2");
4874 
4875     /* msidbLocatorTypeFile */
4876     add_inilocator_entry(hdb, "'NewSignature4', 'IniFile.ini', 'Section', 'Key2', 1, 1");
4877 
4878     /* msidbLocatorTypeDirectory, file */
4879     add_inilocator_entry(hdb, "'NewSignature5', 'IniFile.ini', 'Section', 'Key2', 1, 0");
4880 
4881     /* msidbLocatorTypeDirectory, directory */
4882     add_inilocator_entry(hdb, "'NewSignature6', 'IniFile.ini', 'Section', 'Key3', 1, 0");
4883 
4884     /* msidbLocatorTypeFile, file, no signature */
4885     add_inilocator_entry(hdb, "'NewSignature7', 'IniFile.ini', 'Section', 'Key2', 1, 1");
4886 
4887     /* msidbLocatorTypeFile, dir, no signature */
4888     add_inilocator_entry(hdb, "'NewSignature8', 'IniFile.ini', 'Section', 'Key3', 1, 1");
4889 
4890     /* msidbLocatorTypeFile, file does not exist */
4891     add_inilocator_entry(hdb, "'NewSignature9', 'IniFile.ini', 'Section', 'Key4', 1, 1");
4892 
4893     /* msidbLocatorTypeFile, signature with version */
4894     add_inilocator_entry(hdb, "'NewSignature10', 'IniFile.ini', 'Section', 'Key5', 1, 1");
4895 
4896     /* msidbLocatorTypeFile, signature with version, ver > max */
4897     add_inilocator_entry(hdb, "'NewSignature11', 'IniFile.ini', 'Section', 'Key6', 1, 1");
4898 
4899     /* msidbLocatorTypeFile, signature with version, sig->name ignored */
4900     add_inilocator_entry(hdb, "'NewSignature12', 'IniFile.ini', 'Section', 'Key7', 1, 1");
4901 
4902     create_signature_table(hdb);
4903     add_signature_entry(hdb, "'NewSignature4', 'FileName1', '', '', '', '', '', '', ''");
4904     add_signature_entry(hdb, "'NewSignature9', 'IDontExist', '', '', '', '', '', '', ''");
4905     add_signature_entry(hdb, "'NewSignature10', 'FileName2.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4906     add_signature_entry(hdb, "'NewSignature11', 'FileName3.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4907     add_signature_entry(hdb, "'NewSignature12', 'ignored', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4908 
4909     r = package_from_db(hdb, &hpkg);
4910     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
4911     {
4912         skip("Not enough rights to perform tests\n");
4913         goto error;
4914     }
4915     ok(r == ERROR_SUCCESS, "Expected a valid package handle %u\n", r);
4916 
4917     MsiCloseHandle( hdb );
4918     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4919 
4920     r = MsiDoActionA(hpkg, "AppSearch");
4921     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4922 
4923     size = MAX_PATH;
4924     r = MsiGetPropertyA(hpkg, "SIGPROP1", prop, &size);
4925     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4926     if (!prop[0])
4927     {
4928         win_skip("broken result\n");
4929         MsiCloseHandle(hpkg);
4930         goto error;
4931     }
4932     ok(!lstrcmpA(prop, "keydata"), "Expected \"keydata\", got \"%s\"\n", prop);
4933 
4934     size = MAX_PATH;
4935     r = MsiGetPropertyA(hpkg, "SIGPROP2", prop, &size);
4936     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4937     ok(!lstrcmpA(prop, "field2"), "Expected \"field2\", got \"%s\"\n", prop);
4938 
4939     size = MAX_PATH;
4940     r = MsiGetPropertyA(hpkg, "SIGPROP3", prop, &size);
4941     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4942     ok(!lstrcmpA(prop, "keydata,field2"),
4943        "Expected \"keydata,field2\", got \"%s\"\n", prop);
4944 
4945     size = MAX_PATH;
4946     sprintf(path, "%s\\FileName1", expected);
4947     r = MsiGetPropertyA(hpkg, "SIGPROP4", prop, &size);
4948     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4949     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4950 
4951     size = MAX_PATH;
4952     r = MsiGetPropertyA(hpkg, "SIGPROP5", prop, &size);
4953     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4954     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4955 
4956     size = MAX_PATH;
4957     sprintf(path, "%s\\", expected);
4958     r = MsiGetPropertyA(hpkg, "SIGPROP6", prop, &size);
4959     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4960     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4961 
4962     size = MAX_PATH;
4963     sprintf(path, "%s\\", expected);
4964     r = MsiGetPropertyA(hpkg, "SIGPROP7", prop, &size);
4965     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4966     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4967 
4968     if (!is_root(CURR_DIR))
4969     {
4970         size = MAX_PATH;
4971         lstrcpyA(path, expected);
4972         ptr = strrchr(path, '\\');
4973         *(ptr + 1) = 0;
4974         r = MsiGetPropertyA(hpkg, "SIGPROP8", prop, &size);
4975         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4976         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4977     }
4978     size = MAX_PATH;
4979     r = MsiGetPropertyA(hpkg, "SIGPROP9", prop, &size);
4980     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4981     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4982 
4983     if (version)
4984     {
4985         size = MAX_PATH;
4986         sprintf(path, "%s\\FileName2.dll", expected);
4987         r = MsiGetPropertyA(hpkg, "SIGPROP10", prop, &size);
4988         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4989         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4990 
4991         size = MAX_PATH;
4992         r = MsiGetPropertyA(hpkg, "SIGPROP11", prop, &size);
4993         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4994         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4995 
4996         size = MAX_PATH;
4997         sprintf(path, "%s\\FileName4.dll", expected);
4998         r = MsiGetPropertyA(hpkg, "SIGPROP12", prop, &size);
4999         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5000         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5001     }
5002 
5003     MsiCloseHandle(hpkg);
5004 
5005 error:
5006     delete_win_ini("IniFile.ini");
5007     DeleteFileA("FileName1");
5008     DeleteFileA("FileName2.dll");
5009     DeleteFileA("FileName3.dll");
5010     DeleteFileA("FileName4.dll");
5011     DeleteFileA(msifile);
5012 }
5013 
5014 /*
5015  * MSI AppSearch action on DrLocator table always returns absolute paths.
5016  * If a relative path was set, it returns the first absolute path that
5017  * matches or an empty string if it didn't find anything.
5018  * This helper function replicates this behaviour.
5019  */
5020 static void search_absolute_directory(LPSTR absolute, LPCSTR relative)
5021 {
5022     int i, size;
5023     DWORD attr, drives;
5024 
5025     size = lstrlenA(relative);
5026     drives = GetLogicalDrives();
5027     lstrcpyA(absolute, "A:\\");
5028     for (i = 0; i < 26; absolute[0] = '\0', i++)
5029     {
5030         if (!(drives & (1 << i)))
5031             continue;
5032 
5033         absolute[0] = 'A' + i;
5034         if (GetDriveTypeA(absolute) != DRIVE_FIXED)
5035             continue;
5036 
5037         lstrcpynA(absolute + 3, relative, size + 1);
5038         attr = GetFileAttributesA(absolute);
5039         if (attr != INVALID_FILE_ATTRIBUTES &&
5040             (attr & FILE_ATTRIBUTE_DIRECTORY))
5041         {
5042             if (absolute[3 + size - 1] != '\\')
5043                 lstrcatA(absolute, "\\");
5044             break;
5045         }
5046         absolute[3] = '\0';
5047     }
5048 }
5049 
5050 static void test_appsearch_drlocator(void)
5051 {
5052     MSIHANDLE hpkg, hdb;
5053     char path[MAX_PATH + 27], expected[MAX_PATH], prop[MAX_PATH];
5054     BOOL version;
5055     DWORD size;
5056     UINT r;
5057 
5058     version = TRUE;
5059     if (!create_file_with_version("test.dll", MAKELONG(2, 1), MAKELONG(4, 3)))
5060         version = FALSE;
5061 
5062     DeleteFileA("test.dll");
5063 
5064     create_test_file("FileName1");
5065     CreateDirectoryA("one", NULL);
5066     CreateDirectoryA("one\\two", NULL);
5067     CreateDirectoryA("one\\two\\three", NULL);
5068     create_test_file("one\\two\\three\\FileName2");
5069     CreateDirectoryA("another", NULL);
5070     create_file_with_version("FileName3.dll", MAKELONG(2, 1), MAKELONG(4, 3));
5071     create_file_with_version("FileName4.dll", MAKELONG(1, 2), MAKELONG(3, 4));
5072     create_file_with_version("FileName5.dll", MAKELONG(2, 1), MAKELONG(4, 3));
5073 
5074     hdb = create_package_db();
5075     ok(hdb, "Expected a valid database handle\n");
5076 
5077     create_appsearch_table(hdb);
5078     add_appsearch_entry(hdb, "'SIGPROP1', 'NewSignature1'");
5079     add_appsearch_entry(hdb, "'SIGPROP2', 'NewSignature2'");
5080     add_appsearch_entry(hdb, "'SIGPROP3', 'NewSignature3'");
5081     add_appsearch_entry(hdb, "'SIGPROP4', 'NewSignature4'");
5082     add_appsearch_entry(hdb, "'SIGPROP5', 'NewSignature5'");
5083     add_appsearch_entry(hdb, "'SIGPROP6', 'NewSignature6'");
5084     add_appsearch_entry(hdb, "'SIGPROP7', 'NewSignature7'");
5085     add_appsearch_entry(hdb, "'SIGPROP8', 'NewSignature8'");
5086     add_appsearch_entry(hdb, "'SIGPROP9', 'NewSignature9'");
5087     add_appsearch_entry(hdb, "'SIGPROP10', 'NewSignature10'");
5088     add_appsearch_entry(hdb, "'SIGPROP11', 'NewSignature11'");
5089     add_appsearch_entry(hdb, "'SIGPROP13', 'NewSignature13'");
5090 
5091     create_drlocator_table(hdb);
5092 
5093     strcpy(expected, CURR_DIR);
5094     if (is_root(CURR_DIR)) expected[2] = 0;
5095 
5096     /* no parent, full path, depth 0, signature */
5097     sprintf(path, "'NewSignature1', '', '%s', 0", expected);
5098     add_drlocator_entry(hdb, path);
5099 
5100     /* no parent, full path, depth 0, no signature */
5101     sprintf(path, "'NewSignature2', '', '%s', 0", expected);
5102     add_drlocator_entry(hdb, path);
5103 
5104     /* no parent, relative path, depth 0, no signature */
5105     sprintf(path, "'NewSignature3', '', '%s', 0", expected + 3);
5106     add_drlocator_entry(hdb, path);
5107 
5108     /* no parent, full path, depth 2, signature */
5109     sprintf(path, "'NewSignature4', '', '%s', 2", expected);
5110     add_drlocator_entry(hdb, path);
5111 
5112     /* no parent, full path, depth 3, signature */
5113     sprintf(path, "'NewSignature5', '', '%s', 3", expected);
5114     add_drlocator_entry(hdb, path);
5115 
5116     /* no parent, full path, depth 1, signature is dir */
5117     sprintf(path, "'NewSignature6', '', '%s', 1", expected);
5118     add_drlocator_entry(hdb, path);
5119 
5120     /* parent is in DrLocator, relative path, depth 0, signature */
5121     sprintf(path, "'NewSignature7', 'NewSignature1', 'one\\two\\three', 1");
5122     add_drlocator_entry(hdb, path);
5123 
5124     /* no parent, full path, depth 0, signature w/ version */
5125     sprintf(path, "'NewSignature8', '', '%s', 0", expected);
5126     add_drlocator_entry(hdb, path);
5127 
5128     /* no parent, full path, depth 0, signature w/ version, ver > max */
5129     sprintf(path, "'NewSignature9', '', '%s', 0", expected);
5130     add_drlocator_entry(hdb, path);
5131 
5132     /* no parent, full path, depth 0, signature w/ version, sig->name not ignored */
5133     sprintf(path, "'NewSignature10', '', '%s', 0", expected);
5134     add_drlocator_entry(hdb, path);
5135 
5136     /* no parent, relative empty path, depth 0, no signature */
5137     sprintf(path, "'NewSignature11', '', '', 0");
5138     add_drlocator_entry(hdb, path);
5139 
5140     create_reglocator_table(hdb);
5141 
5142     /* parent */
5143     add_reglocator_entry(hdb, "NewSignature12", 2, "htmlfile\\shell\\open\\nonexistent", "", 1);
5144 
5145     /* parent is in RegLocator, no path, depth 0, no signature */
5146     sprintf(path, "'NewSignature13', 'NewSignature12', '', 0");
5147     add_drlocator_entry(hdb, path);
5148 
5149     create_signature_table(hdb);
5150     add_signature_entry(hdb, "'NewSignature1', 'FileName1', '', '', '', '', '', '', ''");
5151     add_signature_entry(hdb, "'NewSignature4', 'FileName2', '', '', '', '', '', '', ''");
5152     add_signature_entry(hdb, "'NewSignature5', 'FileName2', '', '', '', '', '', '', ''");
5153     add_signature_entry(hdb, "'NewSignature6', 'another', '', '', '', '', '', '', ''");
5154     add_signature_entry(hdb, "'NewSignature7', 'FileName2', '', '', '', '', '', '', ''");
5155     add_signature_entry(hdb, "'NewSignature8', 'FileName3.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
5156     add_signature_entry(hdb, "'NewSignature9', 'FileName4.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
5157     add_signature_entry(hdb, "'NewSignature10', 'necessary', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
5158 
5159     r = package_from_db(hdb, &hpkg);
5160     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5161     {
5162         skip("Not enough rights to perform tests\n");
5163         goto error;
5164     }
5165     ok(r == ERROR_SUCCESS, "Expected a valid package handle %u\n", r);
5166 
5167     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5168 
5169     r = MsiDoActionA(hpkg, "AppSearch");
5170     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5171 
5172     size = MAX_PATH;
5173     sprintf(path, "%s\\FileName1", expected);
5174     r = MsiGetPropertyA(hpkg, "SIGPROP1", prop, &size);
5175     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5176     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5177 
5178     size = MAX_PATH;
5179     sprintf(path, "%s\\", expected);
5180     r = MsiGetPropertyA(hpkg, "SIGPROP2", prop, &size);
5181     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5182     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5183 
5184     size = MAX_PATH;
5185     search_absolute_directory(path, expected + 3);
5186     r = MsiGetPropertyA(hpkg, "SIGPROP3", prop, &size);
5187     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5188     ok(!lstrcmpiA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5189 
5190     size = MAX_PATH;
5191     r = MsiGetPropertyA(hpkg, "SIGPROP4", prop, &size);
5192     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5193     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5194 
5195     size = MAX_PATH;
5196     sprintf(path, "%s\\one\\two\\three\\FileName2", expected);
5197     r = MsiGetPropertyA(hpkg, "SIGPROP5", prop, &size);
5198     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5199     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5200 
5201     size = MAX_PATH;
5202     r = MsiGetPropertyA(hpkg, "SIGPROP6", prop, &size);
5203     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5204     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5205 
5206     size = MAX_PATH;
5207     sprintf(path, "%s\\one\\two\\three\\FileName2", expected);
5208     r = MsiGetPropertyA(hpkg, "SIGPROP7", prop, &size);
5209     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5210     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5211 
5212     if (version)
5213     {
5214         size = MAX_PATH;
5215         sprintf(path, "%s\\FileName3.dll", expected);
5216         r = MsiGetPropertyA(hpkg, "SIGPROP8", prop, &size);
5217         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5218         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5219 
5220         size = MAX_PATH;
5221         r = MsiGetPropertyA(hpkg, "SIGPROP9", prop, &size);
5222         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5223         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5224 
5225         size = MAX_PATH;
5226         r = MsiGetPropertyA(hpkg, "SIGPROP10", prop, &size);
5227         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5228         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5229     }
5230 
5231     size = MAX_PATH;
5232     search_absolute_directory(path, "");
5233     r = MsiGetPropertyA(hpkg, "SIGPROP11", prop, &size);
5234     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5235     ok(!lstrcmpiA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5236 
5237     size = MAX_PATH;
5238     strcpy(path, "c:\\");
5239     r = MsiGetPropertyA(hpkg, "SIGPROP13", prop, &size);
5240     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5241     ok(!prop[0], "Expected \"\", got \"%s\"\n", prop);
5242 
5243     MsiCloseHandle(hpkg);
5244 
5245 error:
5246     DeleteFileA("FileName1");
5247     DeleteFileA("FileName3.dll");
5248     DeleteFileA("FileName4.dll");
5249     DeleteFileA("FileName5.dll");
5250     DeleteFileA("one\\two\\three\\FileName2");
5251     RemoveDirectoryA("one\\two\\three");
5252     RemoveDirectoryA("one\\two");
5253     RemoveDirectoryA("one");
5254     RemoveDirectoryA("another");
5255     DeleteFileA(msifile);
5256 }
5257 
5258 static void test_featureparents(void)
5259 {
5260     MSIHANDLE hpkg;
5261     UINT r;
5262     MSIHANDLE hdb;
5263 
5264     hdb = create_package_db();
5265     ok ( hdb, "failed to create package database\n" );
5266 
5267     add_directory_entry(hdb, "'TARGETDIR', '', 'SourceDir'");
5268 
5269     create_feature_table( hdb );
5270     create_component_table( hdb );
5271     create_feature_components_table( hdb );
5272     create_file_table( hdb );
5273 
5274     /* msidbFeatureAttributesFavorLocal */
5275     add_feature_entry( hdb, "'zodiac', '', '', '', 2, 1, '', 0" );
5276 
5277     /* msidbFeatureAttributesFavorSource */
5278     add_feature_entry( hdb, "'perseus', '', '', '', 2, 1, '', 1" );
5279 
5280     /* msidbFeatureAttributesFavorLocal */
5281     add_feature_entry( hdb, "'orion', '', '', '', 2, 1, '', 0" );
5282 
5283     /* msidbFeatureAttributesUIDisallowAbsent */
5284     add_feature_entry( hdb, "'lyra', '', '', '', 2, 1, '', 16" );
5285 
5286     /* disabled because of install level */
5287     add_feature_entry( hdb, "'waters', '', '', '', 15, 101, '', 9" );
5288 
5289     /* child feature of disabled feature */
5290     add_feature_entry( hdb, "'bayer', 'waters', '', '', 14, 1, '', 9" );
5291 
5292     /* component of disabled feature (install level) */
5293     add_component_entry( hdb, "'delphinus', '', 'TARGETDIR', 0, '', 'delphinus_file'" );
5294 
5295     /* component of disabled child feature (install level) */
5296     add_component_entry( hdb, "'hydrus', '', 'TARGETDIR', 0, '', 'hydrus_file'" );
5297 
5298     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesLocalOnly */
5299     add_component_entry( hdb, "'leo', '', 'TARGETDIR', 0, '', 'leo_file'" );
5300 
5301     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSourceOnly */
5302     add_component_entry( hdb, "'virgo', '', 'TARGETDIR', 1, '', 'virgo_file'" );
5303 
5304     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesOptional */
5305     add_component_entry( hdb, "'libra', '', 'TARGETDIR', 2, '', 'libra_file'" );
5306 
5307     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesLocalOnly */
5308     add_component_entry( hdb, "'cassiopeia', '', 'TARGETDIR', 0, '', 'cassiopeia_file'" );
5309 
5310     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSourceOnly */
5311     add_component_entry( hdb, "'cepheus', '', 'TARGETDIR', 1, '', 'cepheus_file'" );
5312 
5313     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesOptional */
5314     add_component_entry( hdb, "'andromeda', '', 'TARGETDIR', 2, '', 'andromeda_file'" );
5315 
5316     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesLocalOnly */
5317     add_component_entry( hdb, "'canis', '', 'TARGETDIR', 0, '', 'canis_file'" );
5318 
5319     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSourceOnly */
5320     add_component_entry( hdb, "'monoceros', '', 'TARGETDIR', 1, '', 'monoceros_file'" );
5321 
5322     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesOptional */
5323     add_component_entry( hdb, "'lepus', '', 'TARGETDIR', 2, '', 'lepus_file'" );
5324 
5325     add_feature_components_entry( hdb, "'zodiac', 'leo'" );
5326     add_feature_components_entry( hdb, "'zodiac', 'virgo'" );
5327     add_feature_components_entry( hdb, "'zodiac', 'libra'" );
5328     add_feature_components_entry( hdb, "'perseus', 'cassiopeia'" );
5329     add_feature_components_entry( hdb, "'perseus', 'cepheus'" );
5330     add_feature_components_entry( hdb, "'perseus', 'andromeda'" );
5331     add_feature_components_entry( hdb, "'orion', 'leo'" );
5332     add_feature_components_entry( hdb, "'orion', 'virgo'" );
5333     add_feature_components_entry( hdb, "'orion', 'libra'" );
5334     add_feature_components_entry( hdb, "'orion', 'cassiopeia'" );
5335     add_feature_components_entry( hdb, "'orion', 'cepheus'" );
5336     add_feature_components_entry( hdb, "'orion', 'andromeda'" );
5337     add_feature_components_entry( hdb, "'orion', 'canis'" );
5338     add_feature_components_entry( hdb, "'orion', 'monoceros'" );
5339     add_feature_components_entry( hdb, "'orion', 'lepus'" );
5340     add_feature_components_entry( hdb, "'waters', 'delphinus'" );
5341     add_feature_components_entry( hdb, "'bayer', 'hydrus'" );
5342 
5343     add_file_entry( hdb, "'leo_file', 'leo', 'leo.txt', 100, '', '1033', 8192, 1" );
5344     add_file_entry( hdb, "'virgo_file', 'virgo', 'virgo.txt', 0, '', '1033', 8192, 1" );
5345     add_file_entry( hdb, "'libra_file', 'libra', 'libra.txt', 0, '', '1033', 8192, 1" );
5346     add_file_entry( hdb, "'cassiopeia_file', 'cassiopeia', 'cassiopeia.txt', 0, '', '1033', 8192, 1" );
5347     add_file_entry( hdb, "'cepheus_file', 'cepheus', 'cepheus.txt', 0, '', '1033', 8192, 1" );
5348     add_file_entry( hdb, "'andromeda_file', 'andromeda', 'andromeda.txt', 0, '', '1033', 8192, 1" );
5349     add_file_entry( hdb, "'canis_file', 'canis', 'canis.txt', 0, '', '1033', 8192, 1" );
5350     add_file_entry( hdb, "'monoceros_file', 'monoceros', 'monoceros.txt', 0, '', '1033', 8192, 1" );
5351     add_file_entry( hdb, "'lepus_file', 'lepus', 'lepus.txt', 0, '', '1033', 8192, 1" );
5352     add_file_entry( hdb, "'delphinus_file', 'delphinus', 'delphinus.txt', 0, '', '1033', 8192, 1" );
5353     add_file_entry( hdb, "'hydrus_file', 'hydrus', 'hydrus.txt', 0, '', '1033', 8192, 1" );
5354 
5355     r = package_from_db( hdb, &hpkg );
5356     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5357     {
5358         skip("Not enough rights to perform tests\n");
5359         DeleteFileA(msifile);
5360         return;
5361     }
5362     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
5363 
5364     MsiCloseHandle( hdb );
5365 
5366     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5367 
5368     r = MsiDoActionA( hpkg, "CostInitialize");
5369     ok( r == ERROR_SUCCESS, "cost init failed\n");
5370 
5371     r = MsiDoActionA( hpkg, "FileCost");
5372     ok( r == ERROR_SUCCESS, "file cost failed\n");
5373 
5374     r = MsiDoActionA( hpkg, "CostFinalize");
5375     ok( r == ERROR_SUCCESS, "cost finalize failed\n");
5376 
5377     test_feature_states( __LINE__, hpkg, "zodiac", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
5378     test_feature_states( __LINE__, hpkg, "perseus", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
5379     test_feature_states( __LINE__, hpkg, "orion", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
5380     test_feature_states( __LINE__, hpkg, "lyra", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
5381     test_feature_states( __LINE__, hpkg, "waters", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
5382     test_feature_states( __LINE__, hpkg, "bayer", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
5383 
5384     test_component_states( __LINE__, hpkg, "leo", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5385     test_component_states( __LINE__, hpkg, "virgo", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5386     test_component_states( __LINE__, hpkg, "libra", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5387     test_component_states( __LINE__, hpkg, "cassiopeia", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5388     test_component_states( __LINE__, hpkg, "cepheus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5389     test_component_states( __LINE__, hpkg, "andromeda", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5390     test_component_states( __LINE__, hpkg, "canis", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5391     test_component_states( __LINE__, hpkg, "monoceros", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5392     test_component_states( __LINE__, hpkg, "lepus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5393     test_component_states( __LINE__, hpkg, "delphinus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5394     test_component_states( __LINE__, hpkg, "hydrus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5395 
5396     r = MsiSetFeatureStateA(hpkg, "orion", INSTALLSTATE_ABSENT);
5397     ok( r == ERROR_SUCCESS, "failed to set feature state: %d\n", r);
5398 
5399     r = MsiSetFeatureStateA(hpkg, "lyra", INSTALLSTATE_ABSENT);
5400     ok( r == ERROR_SUCCESS, "failed to set feature state: %d\n", r);
5401 
5402     r = MsiSetFeatureStateA(hpkg, "nosuchfeature", INSTALLSTATE_ABSENT);
5403     ok( r == ERROR_UNKNOWN_FEATURE, "Expected ERROR_UNKNOWN_FEATURE, got %u\n", r);
5404 
5405     test_feature_states( __LINE__, hpkg, "zodiac", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
5406     test_feature_states( __LINE__, hpkg, "perseus", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
5407     test_feature_states( __LINE__, hpkg, "orion", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_ABSENT, FALSE );
5408     test_feature_states( __LINE__, hpkg, "lyra", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_ABSENT, FALSE );
5409     test_feature_states( __LINE__, hpkg, "waters", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
5410     test_feature_states( __LINE__, hpkg, "bayer", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
5411 
5412     test_component_states( __LINE__, hpkg, "leo", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5413     test_component_states( __LINE__, hpkg, "virgo", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5414     test_component_states( __LINE__, hpkg, "libra", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5415     test_component_states( __LINE__, hpkg, "cassiopeia", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5416     test_component_states( __LINE__, hpkg, "cepheus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5417     test_component_states( __LINE__, hpkg, "andromeda", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5418     test_component_states( __LINE__, hpkg, "canis", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5419     test_component_states( __LINE__, hpkg, "monoceros", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5420     test_component_states( __LINE__, hpkg, "lepus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5421     test_component_states( __LINE__, hpkg, "delphinus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5422     test_component_states( __LINE__, hpkg, "hydrus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5423 
5424     MsiCloseHandle(hpkg);
5425     DeleteFileA(msifile);
5426 }
5427 
5428 static void test_installprops(void)
5429 {
5430     MSIHANDLE hpkg, hdb;
5431     CHAR path[MAX_PATH], buf[MAX_PATH];
5432     DWORD size, type;
5433     LANGID langid;
5434     HKEY hkey1, hkey2, pathkey = NULL;
5435     int res;
5436     UINT r;
5437     REGSAM access = KEY_ALL_ACCESS;
5438     SYSTEM_INFO si;
5439     INSTALLUILEVEL uilevel;
5440 
5441     if (is_wow64)
5442         access |= KEY_WOW64_64KEY;
5443 
5444     lstrcpyA(path, CURR_DIR);
5445     if (!is_root(CURR_DIR)) lstrcatA(path, "\\");
5446     lstrcatA(path, msifile);
5447 
5448     uilevel = MsiSetInternalUI(INSTALLUILEVEL_BASIC|INSTALLUILEVEL_SOURCERESONLY, NULL);
5449 
5450     hdb = create_package_db();
5451     ok( hdb, "failed to create database\n");
5452 
5453     r = package_from_db(hdb, &hpkg);
5454     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5455     {
5456         skip("Not enough rights to perform tests\n");
5457         MsiSetInternalUI(uilevel, NULL);
5458         DeleteFileA(msifile);
5459         return;
5460     }
5461     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
5462 
5463     MsiCloseHandle(hdb);
5464 
5465     buf[0] = 0;
5466     size = MAX_PATH;
5467     r = MsiGetPropertyA(hpkg, "UILevel", buf, &size);
5468     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5469     ok( !lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
5470 
5471     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5472 
5473     buf[0] = 0;
5474     size = MAX_PATH;
5475     r = MsiGetPropertyA(hpkg, "UILevel", buf, &size);
5476     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5477     ok( !lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
5478 
5479     buf[0] = 0;
5480     size = MAX_PATH;
5481     r = MsiGetPropertyA(hpkg, "DATABASE", buf, &size);
5482     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5483     ok( !lstrcmpA(buf, path), "Expected %s, got %s\n", path, buf);
5484 
5485     RegOpenKeyA(HKEY_CURRENT_USER, "SOFTWARE\\Microsoft\\MS Setup (ACME)\\User Info", &hkey1);
5486     res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, access, &hkey2);
5487     if (res == ERROR_ACCESS_DENIED)
5488     {
5489         win_skip("no access\n");
5490         goto done;
5491     }
5492     RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion",
5493         0, KEY_QUERY_VALUE | KEY_WOW64_64KEY, &pathkey);
5494 
5495     size = MAX_PATH;
5496     type = REG_SZ;
5497     *path = '\0';
5498     if (RegQueryValueExA(hkey1, "DefName", NULL, &type, (LPBYTE)path, &size) != ERROR_SUCCESS)
5499     {
5500         size = MAX_PATH;
5501         type = REG_SZ;
5502         RegQueryValueExA(hkey2, "RegisteredOwner", NULL, &type, (LPBYTE)path, &size);
5503     }
5504 
5505     buf[0] = 0;
5506     size = MAX_PATH;
5507     r = MsiGetPropertyA(hpkg, "USERNAME", buf, &size);
5508     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5509     ok( !lstrcmpA(buf, path), "Expected %s, got %s\n", path, buf);
5510 
5511     size = MAX_PATH;
5512     type = REG_SZ;
5513     *path = '\0';
5514     if (RegQueryValueExA(hkey1, "DefCompany", NULL, &type, (LPBYTE)path, &size) != ERROR_SUCCESS)
5515     {
5516         size = MAX_PATH;
5517         type = REG_SZ;
5518         RegQueryValueExA(hkey2, "RegisteredOrganization", NULL, &type, (LPBYTE)path, &size);
5519     }
5520 
5521     if (*path)
5522     {
5523         buf[0] = 0;
5524         size = MAX_PATH;
5525         r = MsiGetPropertyA(hpkg, "COMPANYNAME", buf, &size);
5526         ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5527         ok( !lstrcmpA(buf, path), "Expected %s, got %s\n", path, buf);
5528     }
5529 
5530     buf[0] = 0;
5531     size = MAX_PATH;
5532     r = MsiGetPropertyA(hpkg, "VersionDatabase", buf, &size);
5533     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5534     trace("VersionDatabase = %s\n", buf);
5535 
5536     buf[0] = 0;
5537     size = MAX_PATH;
5538     r = MsiGetPropertyA(hpkg, "VersionMsi", buf, &size);
5539     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5540     trace("VersionMsi = %s\n", buf);
5541 
5542     buf[0] = 0;
5543     size = MAX_PATH;
5544     r = MsiGetPropertyA(hpkg, "Date", buf, &size);
5545     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5546     trace("Date = %s\n", buf);
5547 
5548     buf[0] = 0;
5549     size = MAX_PATH;
5550     r = MsiGetPropertyA(hpkg, "Time", buf, &size);
5551     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5552     trace("Time = %s\n", buf);
5553 
5554     buf[0] = 0;
5555     size = MAX_PATH;
5556     r = MsiGetPropertyA(hpkg, "PackageCode", buf, &size);
5557     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5558     trace("PackageCode = %s\n", buf);
5559 
5560     buf[0] = 0;
5561     size = MAX_PATH;
5562     r = MsiGetPropertyA(hpkg, "ComputerName", buf, &size);
5563     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
5564     trace("ComputerName = %s\n", buf);
5565 
5566     langid = GetUserDefaultLangID();
5567     sprintf(path, "%d", langid);
5568 
5569     buf[0] = 0;
5570     size = MAX_PATH;
5571     r = MsiGetPropertyA(hpkg, "UserLanguageID", buf, &size);
5572     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
5573     ok( !lstrcmpA(buf, path), "Expected \"%s\", got \"%s\"\n", path, buf);
5574 
5575     res = GetSystemMetrics(SM_CXSCREEN);
5576     buf[0] = 0;
5577     size = MAX_PATH;
5578     r = MsiGetPropertyA(hpkg, "ScreenX", buf, &size);
5579     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
5580     ok(atol(buf) == res, "Expected %d, got %s\n", res, buf);
5581 
5582     res = GetSystemMetrics(SM_CYSCREEN);
5583     buf[0] = 0;
5584     size = MAX_PATH;
5585     r = MsiGetPropertyA(hpkg, "ScreenY", buf, &size);
5586     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
5587     ok(atol(buf) == res, "Expected %d, got %s\n", res, buf);
5588 
5589     buf[0] = 0;
5590     size = MAX_PATH;
5591     r = MsiGetPropertyA(hpkg, "MsiNetAssemblySupport", buf, &size);
5592     if (r == ERROR_SUCCESS) trace( "MsiNetAssemblySupport \"%s\"\n", buf );
5593 
5594     GetNativeSystemInfo(&si);
5595 
5596     sprintf(buf, "%d", LOBYTE(LOWORD(GetVersion())) * 100 + HIBYTE(LOWORD(GetVersion())));
5597     check_prop(hpkg, "VersionNT", buf, 1, 1);
5598 
5599     if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
5600     {
5601         sprintf(buf, "%d", si.wProcessorLevel);
5602         check_prop(hpkg, "Intel", buf, 1, 0);
5603         check_prop(hpkg, "MsiAMD64", buf, 1, 0);
5604         check_prop(hpkg, "Msix64", buf, 1, 0);
5605         sprintf(buf, "%d", LOBYTE(LOWORD(GetVersion())) * 100 + HIBYTE(LOWORD(GetVersion())));
5606         check_prop(hpkg, "VersionNT64", buf, 1, 1);
5607 
5608         GetSystemDirectoryA(path, MAX_PATH);
5609         strcat(path, "\\");
5610         check_prop(hpkg, "System64Folder", path, 0, 0);
5611 
5612         GetSystemWow64DirectoryA(path, MAX_PATH);
5613         strcat(path, "\\");
5614         check_prop(hpkg, "SystemFolder", path, 0, 0);
5615 
5616         size = MAX_PATH;
5617         r = RegQueryValueExA(pathkey, "ProgramFilesDir (x86)", 0, &type, (BYTE *)path, &size);
5618         strcat(path, "\\");
5619         check_prop(hpkg, "ProgramFilesFolder", path, 0, 0);
5620 
5621         size = MAX_PATH;
5622         RegQueryValueExA(pathkey, "ProgramFilesDir", 0, &type, (BYTE *)path, &size);
5623         strcat(path, "\\");
5624         check_prop(hpkg, "ProgramFiles64Folder", path, 0, 0);
5625 
5626         size = MAX_PATH;
5627         RegQueryValueExA(pathkey, "CommonFilesDir (x86)", 0, &type, (BYTE *)path, &size);
5628         strcat(path, "\\");
5629         check_prop(hpkg, "CommonFilesFolder", path, 0, 0);
5630 
5631         size = MAX_PATH;
5632         RegQueryValueExA(pathkey, "CommonFilesDir", 0, &type, (BYTE *)path, &size);
5633         strcat(path, "\\");
5634         check_prop(hpkg, "CommonFiles64Folder", path, 0, 0);
5635     }
5636     else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
5637     {
5638         sprintf(buf, "%d", si.wProcessorLevel);
5639         check_prop(hpkg, "Intel", buf, 1, 0);
5640 
5641         GetSystemDirectoryA(path, MAX_PATH);
5642         strcat(path, "\\");
5643         check_prop(hpkg, "SystemFolder", path, 0, 0);
5644 
5645         size = MAX_PATH;
5646         RegQueryValueExA(pathkey, "ProgramFilesDir", 0, &type, (BYTE *)path, &size);
5647         strcat(path, "\\");
5648         check_prop(hpkg, "ProgramFilesFolder", path, 0, 0);
5649 
5650         size = MAX_PATH;
5651         RegQueryValueExA(pathkey, "CommonFilesDir", 0, &type, (BYTE *)path, &size);
5652         strcat(path, "\\");
5653         check_prop(hpkg, "CommonFilesFolder", path, 0, 0);
5654 
5655         check_prop(hpkg, "MsiAMD64", "", 1, 0);
5656         check_prop(hpkg, "Msix64", "", 1, 0);
5657         check_prop(hpkg, "VersionNT64", "", 1, 0);
5658         check_prop(hpkg, "System64Folder", "", 0, 0);
5659         check_prop(hpkg, "ProgramFiles64Dir", "", 0, 0);
5660         check_prop(hpkg, "CommonFiles64Dir", "", 0, 0);
5661     }
5662 
5663 done:
5664     CloseHandle(hkey1);
5665     CloseHandle(hkey2);
5666     RegCloseKey(pathkey);
5667     MsiCloseHandle(hpkg);
5668     DeleteFileA(msifile);
5669     MsiSetInternalUI(uilevel, NULL);
5670 }
5671 
5672 static void test_launchconditions(void)
5673 {
5674     MSIHANDLE hpkg;
5675     MSIHANDLE hdb;
5676     UINT r;
5677 
5678     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5679 
5680     hdb = create_package_db();
5681     ok( hdb, "failed to create package database\n" );
5682 
5683     create_launchcondition_table( hdb );
5684 
5685     add_launchcondition_entry( hdb, "'X = \"1\"', 'one'" );
5686 
5687     /* invalid condition */
5688     add_launchcondition_entry( hdb, "'X != \"1\"', 'one'" );
5689 
5690     r = package_from_db( hdb, &hpkg );
5691     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5692     {
5693         skip("Not enough rights to perform tests\n");
5694         DeleteFileA(msifile);
5695         return;
5696     }
5697     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
5698 
5699     MsiCloseHandle( hdb );
5700 
5701     r = MsiSetPropertyA( hpkg, "X", "1" );
5702     ok( r == ERROR_SUCCESS, "failed to set property\n" );
5703 
5704     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5705 
5706     /* invalid conditions are ignored */
5707     r = MsiDoActionA( hpkg, "LaunchConditions" );
5708     ok( r == ERROR_SUCCESS, "cost init failed\n" );
5709 
5710     /* verify LaunchConditions still does some verification */
5711     r = MsiSetPropertyA( hpkg, "X", "2" );
5712     ok( r == ERROR_SUCCESS, "failed to set property\n" );
5713 
5714     r = MsiDoActionA( hpkg, "LaunchConditions" );
5715     ok( r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %d\n", r );
5716 
5717     MsiCloseHandle( hpkg );
5718     DeleteFileA( msifile );
5719 }
5720 
5721 static void test_ccpsearch(void)
5722 {
5723     MSIHANDLE hdb, hpkg;
5724     CHAR prop[MAX_PATH];
5725     DWORD size = MAX_PATH;
5726     UINT r;
5727 
5728     hdb = create_package_db();
5729     ok(hdb, "failed to create package database\n");
5730 
5731     create_ccpsearch_table(hdb);
5732     add_ccpsearch_entry(hdb, "'CCP_random'");
5733     add_ccpsearch_entry(hdb, "'RMCCP_random'");
5734 
5735     create_reglocator_table(hdb);
5736     add_reglocator_entry(hdb, "CCP_random", 0, "htmlfile\\shell\\open\\nonexistent", "", 1);
5737 
5738     create_drlocator_table(hdb);
5739     add_drlocator_entry(hdb, "'RMCCP_random', '', 'C:\\', '0'");
5740 
5741     create_signature_table(hdb);
5742 
5743     r = package_from_db(hdb, &hpkg);
5744     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5745     {
5746         skip("Not enough rights to perform tests\n");
5747         DeleteFileA(msifile);
5748         return;
5749     }
5750     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
5751 
5752     MsiCloseHandle(hdb);
5753 
5754     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5755 
5756     r = MsiDoActionA(hpkg, "CCPSearch");
5757     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5758 
5759     r = MsiGetPropertyA(hpkg, "CCP_Success", prop, &size);
5760     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5761     ok(!lstrcmpA(prop, "1"), "Expected 1, got %s\n", prop);
5762 
5763     MsiCloseHandle(hpkg);
5764     DeleteFileA(msifile);
5765 }
5766 
5767 static void test_complocator(void)
5768 {
5769     MSIHANDLE hdb, hpkg;
5770     UINT r;
5771     CHAR prop[MAX_PATH];
5772     CHAR expected[MAX_PATH];
5773     DWORD size = MAX_PATH;
5774 
5775     hdb = create_package_db();
5776     ok(hdb, "failed to create package database\n");
5777 
5778     create_appsearch_table(hdb);
5779     add_appsearch_entry(hdb, "'ABELISAURUS', 'abelisaurus'");
5780     add_appsearch_entry(hdb, "'BACTROSAURUS', 'bactrosaurus'");
5781     add_appsearch_entry(hdb, "'CAMELOTIA', 'camelotia'");
5782     add_appsearch_entry(hdb, "'DICLONIUS', 'diclonius'");
5783     add_appsearch_entry(hdb, "'ECHINODON', 'echinodon'");
5784     add_appsearch_entry(hdb, "'FALCARIUS', 'falcarius'");
5785     add_appsearch_entry(hdb, "'GALLIMIMUS', 'gallimimus'");
5786     add_appsearch_entry(hdb, "'HAGRYPHUS', 'hagryphus'");
5787     add_appsearch_entry(hdb, "'IGUANODON', 'iguanodon'");
5788     add_appsearch_entry(hdb, "'JOBARIA', 'jobaria'");
5789     add_appsearch_entry(hdb, "'KAKURU', 'kakuru'");
5790     add_appsearch_entry(hdb, "'LABOCANIA', 'labocania'");
5791     add_appsearch_entry(hdb, "'MEGARAPTOR', 'megaraptor'");
5792     add_appsearch_entry(hdb, "'NEOSODON', 'neosodon'");
5793     add_appsearch_entry(hdb, "'OLOROTITAN', 'olorotitan'");
5794     add_appsearch_entry(hdb, "'PANTYDRACO', 'pantydraco'");
5795 
5796     create_complocator_table(hdb);
5797     add_complocator_entry(hdb, "'abelisaurus', '{E3619EED-305A-418C-B9C7-F7D7377F0934}', 1");
5798     add_complocator_entry(hdb, "'bactrosaurus', '{D56B688D-542F-42Ef-90FD-B6DA76EE8119}', 0");
5799     add_complocator_entry(hdb, "'camelotia', '{8211BE36-2466-47E3-AFB7-6AC72E51AED2}', 1");
5800     add_complocator_entry(hdb, "'diclonius', '{5C767B20-A33C-45A4-B80B-555E512F01AE}', 0");
5801     add_complocator_entry(hdb, "'echinodon', '{A19E16C5-C75D-4699-8111-C4338C40C3CB}', 1");
5802     add_complocator_entry(hdb, "'falcarius', '{17762FA1-A7AE-4CC6-8827-62873C35361D}', 0");
5803     add_complocator_entry(hdb, "'gallimimus', '{75EBF568-C959-41E0-A99E-9050638CF5FB}', 1");
5804     add_complocator_entry(hdb, "'hagrphus', '{D4969B72-17D9-4AB6-BE49-78F2FEE857AC}', 0");
5805     add_complocator_entry(hdb, "'iguanodon', '{8E0DA02E-F6A7-4A8F-B25D-6F564C492308}', 1");
5806     add_complocator_entry(hdb, "'jobaria', '{243C22B1-8C51-4151-B9D1-1AE5265E079E}', 0");
5807     add_complocator_entry(hdb, "'kakuru', '{5D0F03BA-50BC-44F2-ABB1-72C972F4E514}', 1");
5808     add_complocator_entry(hdb, "'labocania', '{C7DDB60C-7828-4046-A6F8-699D5E92F1ED}', 0");
5809     add_complocator_entry(hdb, "'megaraptor', '{8B1034B7-BD5E-41ac-B52C-0105D3DFD74D}', 1");
5810     add_complocator_entry(hdb, "'neosodon', '{0B499649-197A-48EF-93D2-AF1C17ED6E90}', 0");
5811     add_complocator_entry(hdb, "'olorotitan', '{54E9E91F-AED2-46D5-A25A-7E50AFA24513}', 1");
5812     add_complocator_entry(hdb, "'pantydraco', '{2A989951-5565-4FA7-93A7-E800A3E67D71}', 0");
5813 
5814     create_signature_table(hdb);
5815     add_signature_entry(hdb, "'abelisaurus', 'abelisaurus', '', '', '', '', '', '', ''");
5816     add_signature_entry(hdb, "'bactrosaurus', 'bactrosaurus', '', '', '', '', '', '', ''");
5817     add_signature_entry(hdb, "'camelotia', 'camelotia', '', '', '', '', '', '', ''");
5818     add_signature_entry(hdb, "'diclonius', 'diclonius', '', '', '', '', '', '', ''");
5819     add_signature_entry(hdb, "'iguanodon', 'iguanodon', '', '', '', '', '', '', ''");
5820     add_signature_entry(hdb, "'jobaria', 'jobaria', '', '', '', '', '', '', ''");
5821     add_signature_entry(hdb, "'kakuru', 'kakuru', '', '', '', '', '', '', ''");
5822     add_signature_entry(hdb, "'labocania', 'labocania', '', '', '', '', '', '', ''");
5823 
5824     r = package_from_db(hdb, &hpkg);
5825     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5826     {
5827         skip("Not enough rights to perform tests\n");
5828         DeleteFileA(msifile);
5829         return;
5830     }
5831     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
5832 
5833     MsiCloseHandle(hdb);
5834 
5835     create_test_file("abelisaurus");
5836     create_test_file("bactrosaurus");
5837     create_test_file("camelotia");
5838     create_test_file("diclonius");
5839     create_test_file("echinodon");
5840     create_test_file("falcarius");
5841     create_test_file("gallimimus");
5842     create_test_file("hagryphus");
5843     CreateDirectoryA("iguanodon", NULL);
5844     CreateDirectoryA("jobaria", NULL);
5845     CreateDirectoryA("kakuru", NULL);
5846     CreateDirectoryA("labocania", NULL);
5847     CreateDirectoryA("megaraptor", NULL);
5848     CreateDirectoryA("neosodon", NULL);
5849     CreateDirectoryA("olorotitan", NULL);
5850     CreateDirectoryA("pantydraco", NULL);
5851 
5852     set_component_path("abelisaurus", MSIINSTALLCONTEXT_MACHINE,
5853                        "{E3619EED-305A-418C-B9C7-F7D7377F0934}", NULL, FALSE);
5854     set_component_path("bactrosaurus", MSIINSTALLCONTEXT_MACHINE,
5855                        "{D56B688D-542F-42Ef-90FD-B6DA76EE8119}", NULL, FALSE);
5856     set_component_path("echinodon", MSIINSTALLCONTEXT_MACHINE,
5857                        "{A19E16C5-C75D-4699-8111-C4338C40C3CB}", NULL, FALSE);
5858     set_component_path("falcarius", MSIINSTALLCONTEXT_MACHINE,
5859                        "{17762FA1-A7AE-4CC6-8827-62873C35361D}", NULL, FALSE);
5860     set_component_path("iguanodon", MSIINSTALLCONTEXT_MACHINE,
5861                        "{8E0DA02E-F6A7-4A8F-B25D-6F564C492308}", NULL, FALSE);
5862     set_component_path("jobaria", MSIINSTALLCONTEXT_MACHINE,
5863                        "{243C22B1-8C51-4151-B9D1-1AE5265E079E}", NULL, FALSE);
5864     set_component_path("megaraptor", MSIINSTALLCONTEXT_MACHINE,
5865                        "{8B1034B7-BD5E-41ac-B52C-0105D3DFD74D}", NULL, FALSE);
5866     set_component_path("neosodon", MSIINSTALLCONTEXT_MACHINE,
5867                        "{0B499649-197A-48EF-93D2-AF1C17ED6E90}", NULL, FALSE);
5868 
5869     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5870 
5871     r = MsiDoActionA(hpkg, "AppSearch");
5872     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5873 
5874     size = MAX_PATH;
5875     r = MsiGetPropertyA(hpkg, "ABELISAURUS", prop, &size);
5876     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5877 
5878     lstrcpyA(expected, CURR_DIR);
5879     if (!is_root(CURR_DIR)) lstrcatA(expected, "\\");
5880     lstrcatA(expected, "abelisaurus");
5881     ok(!lstrcmpA(prop, expected) || !lstrcmpA(prop, ""),
5882        "Expected %s or empty string, got %s\n", expected, prop);
5883 
5884     size = MAX_PATH;
5885     r = MsiGetPropertyA(hpkg, "BACTROSAURUS", prop, &size);
5886     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5887     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
5888 
5889     size = MAX_PATH;
5890     r = MsiGetPropertyA(hpkg, "CAMELOTIA", prop, &size);
5891     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5892     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
5893 
5894     size = MAX_PATH;
5895     r = MsiGetPropertyA(hpkg, "DICLONIUS", prop, &size);
5896     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5897     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
5898 
5899     size = MAX_PATH;
5900     r = MsiGetPropertyA(hpkg, "ECHINODON", prop, &size);
5901     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5902 
5903     lstrcpyA(expected, CURR_DIR);
5904     if (!is_root(CURR_DIR)) lstrcatA(expected, "\\");
5905     ok(!lstrcmpA(prop, expected) || !lstrcmpA(prop, ""),
5906        "Expected %s or empty string, got %s\n", expected, prop);
5907 
5908     size = MAX_PATH;
5909     r = MsiGetPropertyA(hpkg, "FALCARIUS", prop, &size);
5910     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5911     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
5912 
5913     size = MAX_PATH;
5914     r = MsiGetPropertyA(hpkg, "GALLIMIMUS", prop, &size);
5915     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5916     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
5917 
5918     size = MAX_PATH;
5919     r = MsiGetPropertyA(hpkg, "HAGRYPHUS", prop, &size);
5920     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5921     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
5922 
5923     size = MAX_PATH;
5924     r = MsiGetPropertyA(hpkg, "IGUANODON", prop, &size);
5925     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5926     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
5927 
5928     size = MAX_PATH;
5929     r = MsiGetPropertyA(hpkg, "JOBARIA", prop, &size);
5930     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5931     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
5932 
5933     size = MAX_PATH;
5934     r = MsiGetPropertyA(hpkg, "KAKURU", prop, &size);
5935     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5936     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
5937 
5938     size = MAX_PATH;
5939     r = MsiGetPropertyA(hpkg, "LABOCANIA", prop, &size);
5940     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5941     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
5942 
5943     size = MAX_PATH;
5944     r = MsiGetPropertyA(hpkg, "MEGARAPTOR", prop, &size);
5945     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5946 
5947     lstrcpyA(expected, CURR_DIR);
5948     if (!is_root(CURR_DIR)) lstrcatA(expected, "\\");
5949     ok(!lstrcmpA(prop, expected) || !lstrcmpA(prop, ""),
5950        "Expected %s or empty string, got %s\n", expected, prop);
5951 
5952     size = MAX_PATH;
5953     r = MsiGetPropertyA(hpkg, "NEOSODON", prop, &size);
5954     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5955 
5956     lstrcpyA(expected, CURR_DIR);
5957     if (!is_root(CURR_DIR)) lstrcatA(expected, "\\");
5958     lstrcatA(expected, "neosodon\\");
5959     ok(!lstrcmpA(prop, expected) || !lstrcmpA(prop, ""),
5960        "Expected %s or empty string, got %s\n", expected, prop);
5961 
5962     size = MAX_PATH;
5963     r = MsiGetPropertyA(hpkg, "OLOROTITAN", prop, &size);
5964     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5965     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
5966 
5967     size = MAX_PATH;
5968     r = MsiGetPropertyA(hpkg, "PANTYDRACO", prop, &size);
5969     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5970     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
5971 
5972     MsiCloseHandle(hpkg);
5973     DeleteFileA("abelisaurus");
5974     DeleteFileA("bactrosaurus");
5975     DeleteFileA("camelotia");
5976     DeleteFileA("diclonius");
5977     DeleteFileA("echinodon");
5978     DeleteFileA("falcarius");
5979     DeleteFileA("gallimimus");
5980     DeleteFileA("hagryphus");
5981     RemoveDirectoryA("iguanodon");
5982     RemoveDirectoryA("jobaria");
5983     RemoveDirectoryA("kakuru");
5984     RemoveDirectoryA("labocania");
5985     RemoveDirectoryA("megaraptor");
5986     RemoveDirectoryA("neosodon");
5987     RemoveDirectoryA("olorotitan");
5988     RemoveDirectoryA("pantydraco");
5989     delete_component_path("{E3619EED-305A-418C-B9C7-F7D7377F0934}",
5990                           MSIINSTALLCONTEXT_MACHINE, NULL);
5991     delete_component_path("{D56B688D-542F-42Ef-90FD-B6DA76EE8119}",
5992                           MSIINSTALLCONTEXT_MACHINE, NULL);
5993     delete_component_path("{A19E16C5-C75D-4699-8111-C4338C40C3CB}",
5994                           MSIINSTALLCONTEXT_MACHINE, NULL);
5995     delete_component_path("{17762FA1-A7AE-4CC6-8827-62873C35361D}",
5996                           MSIINSTALLCONTEXT_MACHINE, NULL);
5997     delete_component_path("{8E0DA02E-F6A7-4A8F-B25D-6F564C492308}",
5998                           MSIINSTALLCONTEXT_MACHINE, NULL);
5999     delete_component_path("{243C22B1-8C51-4151-B9D1-1AE5265E079E}",
6000                           MSIINSTALLCONTEXT_MACHINE, NULL);
6001     delete_component_path("{8B1034B7-BD5E-41ac-B52C-0105D3DFD74D}",
6002                           MSIINSTALLCONTEXT_MACHINE, NULL);
6003     delete_component_path("{0B499649-197A-48EF-93D2-AF1C17ED6E90}",
6004                           MSIINSTALLCONTEXT_MACHINE, NULL);
6005     DeleteFileA(msifile);
6006 }
6007 
6008 static void set_suminfo_prop(MSIHANDLE db, DWORD prop, DWORD val)
6009 {
6010     MSIHANDLE summary;
6011     UINT r;
6012 
6013     r = MsiGetSummaryInformationA(db, NULL, 1, &summary);
6014     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6015 
6016     r = MsiSummaryInfoSetPropertyA(summary, prop, VT_I4, val, NULL, NULL);
6017     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6018 
6019     r = MsiSummaryInfoPersist(summary);
6020     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
6021 
6022     MsiCloseHandle(summary);
6023 }
6024 
6025 static void test_MsiGetSourcePath(void)
6026 {
6027     MSIHANDLE hdb, hpkg;
6028     CHAR path[MAX_PATH];
6029     CHAR cwd[MAX_PATH];
6030     CHAR subsrc[MAX_PATH];
6031     CHAR sub2[MAX_PATH];
6032     DWORD size;
6033     UINT r;
6034 
6035     lstrcpyA(cwd, CURR_DIR);
6036     if (!is_root(CURR_DIR)) lstrcatA(cwd, "\\");
6037 
6038     lstrcpyA(subsrc, cwd);
6039     lstrcatA(subsrc, "subsource");
6040     lstrcatA(subsrc, "\\");
6041 
6042     lstrcpyA(sub2, subsrc);
6043     lstrcatA(sub2, "sub2");
6044     lstrcatA(sub2, "\\");
6045 
6046     /* uncompressed source */
6047 
6048     hdb = create_package_db();
6049     ok( hdb, "failed to create database\n");
6050 
6051     set_suminfo_prop(hdb, PID_WORDCOUNT, 0);
6052 
6053     add_directory_entry(hdb, "'TARGETDIR', '', 'SourceDir'");
6054     add_directory_entry(hdb, "'SubDir', 'TARGETDIR', 'subtarget:subsource'");
6055     add_directory_entry(hdb, "'SubDir2', 'SubDir', 'sub2'");
6056 
6057     r = MsiDatabaseCommit(hdb);
6058     ok(r == ERROR_SUCCESS , "Failed to commit database\n");
6059 
6060     r = package_from_db(hdb, &hpkg);
6061     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
6062     {
6063         skip("Not enough rights to perform tests\n");
6064         DeleteFileA(msifile);
6065         return;
6066     }
6067     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
6068 
6069     MsiCloseHandle(hdb);
6070 
6071     /* invalid database handle */
6072     size = MAX_PATH;
6073     lstrcpyA(path, "kiwi");
6074     r = MsiGetSourcePathA(-1, "TARGETDIR", path, &size);
6075     ok(r == ERROR_INVALID_HANDLE,
6076        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
6077     ok(!lstrcmpA(path, "kiwi"),
6078        "Expected path to be unchanged, got \"%s\"\n", path);
6079     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6080 
6081     /* NULL szFolder */
6082     size = MAX_PATH;
6083     lstrcpyA(path, "kiwi");
6084     r = MsiGetSourcePathA(hpkg, NULL, path, &size);
6085     ok(r == ERROR_INVALID_PARAMETER,
6086        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6087     ok(!lstrcmpA(path, "kiwi"),
6088        "Expected path to be unchanged, got \"%s\"\n", path);
6089     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6090 
6091     /* empty szFolder */
6092     size = MAX_PATH;
6093     lstrcpyA(path, "kiwi");
6094     r = MsiGetSourcePathA(hpkg, "", path, &size);
6095     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6096     ok(!lstrcmpA(path, "kiwi"),
6097        "Expected path to be unchanged, got \"%s\"\n", path);
6098     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6099 
6100     /* try TARGETDIR */
6101     size = MAX_PATH;
6102     lstrcpyA(path, "kiwi");
6103     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6104     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6105     ok(!lstrcmpA(path, "kiwi"),
6106        "Expected path to be unchanged, got \"%s\"\n", path);
6107     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6108 
6109     size = MAX_PATH;
6110     lstrcpyA(path, "kiwi");
6111     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6112     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6113     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6114     ok(size == 0, "Expected 0, got %lu\n", size);
6115 
6116     size = MAX_PATH;
6117     lstrcpyA(path, "kiwi");
6118     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6119     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6120     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6121     ok(size == 0, "Expected 0, got %lu\n", size);
6122 
6123     /* try SourceDir */
6124     size = MAX_PATH;
6125     lstrcpyA(path, "kiwi");
6126     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6127     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6128     ok(!lstrcmpA(path, "kiwi"),
6129        "Expected path to be unchanged, got \"%s\"\n", path);
6130     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6131 
6132     /* try SOURCEDIR */
6133     size = MAX_PATH;
6134     lstrcpyA(path, "kiwi");
6135     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6136     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6137     ok(!lstrcmpA(path, "kiwi"),
6138        "Expected path to be unchanged, got \"%s\"\n", path);
6139     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6140 
6141     /* source path does not exist, but the property exists */
6142     size = MAX_PATH;
6143     lstrcpyA(path, "kiwi");
6144     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6145     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6146     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6147     ok(size == 0, "Expected 0, got %lu\n", size);
6148 
6149     size = MAX_PATH;
6150     lstrcpyA(path, "kiwi");
6151     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6152     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6153     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6154     ok(size == 0, "Expected 0, got %lu\n", size);
6155 
6156     /* try SubDir */
6157     size = MAX_PATH;
6158     lstrcpyA(path, "kiwi");
6159     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6160     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6161     ok(!lstrcmpA(path, "kiwi"),
6162        "Expected path to be unchanged, got \"%s\"\n", path);
6163     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6164 
6165     /* try SubDir2 */
6166     size = MAX_PATH;
6167     lstrcpyA(path, "kiwi");
6168     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6169     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6170     ok(!lstrcmpA(path, "kiwi"),
6171        "Expected path to be unchanged, got \"%s\"\n", path);
6172     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6173 
6174     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
6175 
6176     r = MsiDoActionA(hpkg, "CostInitialize");
6177     ok(r == ERROR_SUCCESS, "cost init failed\n");
6178 
6179     /* try TARGETDIR after CostInitialize */
6180     size = MAX_PATH;
6181     lstrcpyA(path, "kiwi");
6182     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6183     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6184     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6185     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6186 
6187     /* try SourceDir after CostInitialize */
6188     size = MAX_PATH;
6189     lstrcpyA(path, "kiwi");
6190     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6191     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6192     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6193     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6194 
6195     /* try SOURCEDIR after CostInitialize */
6196     size = MAX_PATH;
6197     lstrcpyA(path, "kiwi");
6198     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6199     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6200     ok(!lstrcmpA(path, "kiwi"),
6201        "Expected path to be unchanged, got \"%s\"\n", path);
6202     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6203 
6204     /* source path does not exist, but the property exists */
6205     size = MAX_PATH;
6206     lstrcpyA(path, "kiwi");
6207     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6208     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6209     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6210     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6211 
6212     size = MAX_PATH;
6213     lstrcpyA(path, "kiwi");
6214     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6215     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6216     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6217     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6218 
6219     /* try SubDir after CostInitialize */
6220     size = MAX_PATH;
6221     lstrcpyA(path, "kiwi");
6222     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6223     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6224     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6225     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
6226 
6227     /* try SubDir2 after CostInitialize */
6228     size = MAX_PATH;
6229     lstrcpyA(path, "kiwi");
6230     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6231     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6232     ok(!lstrcmpA(path, sub2), "Expected \"%s\", got \"%s\"\n", sub2, path);
6233     ok(size == lstrlenA(sub2), "Expected %d, got %lu\n", lstrlenA(sub2), size);
6234 
6235     r = MsiDoActionA(hpkg, "ResolveSource");
6236     ok(r == ERROR_SUCCESS, "file cost failed\n");
6237 
6238     /* try TARGETDIR after ResolveSource */
6239     size = MAX_PATH;
6240     lstrcpyA(path, "kiwi");
6241     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6242     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6243     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6244     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6245 
6246     /* try SourceDir after ResolveSource */
6247     size = MAX_PATH;
6248     lstrcpyA(path, "kiwi");
6249     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6250     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6251     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6252     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6253 
6254     /* try SOURCEDIR after ResolveSource */
6255     size = MAX_PATH;
6256     lstrcpyA(path, "kiwi");
6257     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6258     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6259     ok(!lstrcmpA(path, "kiwi"),
6260        "Expected path to be unchanged, got \"%s\"\n", path);
6261     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6262 
6263     /* source path does not exist, but the property exists */
6264     size = MAX_PATH;
6265     lstrcpyA(path, "kiwi");
6266     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6267     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6268     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6269     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6270 
6271     size = MAX_PATH;
6272     lstrcpyA(path, "kiwi");
6273     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6274     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6275     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6276     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6277 
6278     /* try SubDir after ResolveSource */
6279     size = MAX_PATH;
6280     lstrcpyA(path, "kiwi");
6281     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6282     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6283     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6284     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
6285 
6286     /* try SubDir2 after ResolveSource */
6287     size = MAX_PATH;
6288     lstrcpyA(path, "kiwi");
6289     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6290     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6291     ok(!lstrcmpA(path, sub2), "Expected \"%s\", got \"%s\"\n", sub2, path);
6292     ok(size == lstrlenA(sub2), "Expected %d, got %lu\n", lstrlenA(sub2), size);
6293 
6294     r = MsiDoActionA(hpkg, "FileCost");
6295     ok(r == ERROR_SUCCESS, "file cost failed\n");
6296 
6297     /* try TARGETDIR after FileCost */
6298     size = MAX_PATH;
6299     lstrcpyA(path, "kiwi");
6300     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6301     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6302     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6303     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6304 
6305     /* try SourceDir after FileCost */
6306     size = MAX_PATH;
6307     lstrcpyA(path, "kiwi");
6308     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6309     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6310     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6311     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6312 
6313     /* try SOURCEDIR after FileCost */
6314     size = MAX_PATH;
6315     lstrcpyA(path, "kiwi");
6316     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6317     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6318     ok(!lstrcmpA(path, "kiwi"),
6319        "Expected path to be unchanged, got \"%s\"\n", path);
6320     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6321 
6322     /* source path does not exist, but the property exists */
6323     size = MAX_PATH;
6324     lstrcpyA(path, "kiwi");
6325     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6326     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6327     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6328     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6329 
6330     size = MAX_PATH;
6331     lstrcpyA(path, "kiwi");
6332     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6333     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6334     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6335     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6336 
6337     /* try SubDir after FileCost */
6338     size = MAX_PATH;
6339     lstrcpyA(path, "kiwi");
6340     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6341     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6342     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6343     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
6344 
6345     /* try SubDir2 after FileCost */
6346     size = MAX_PATH;
6347     lstrcpyA(path, "kiwi");
6348     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6349     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6350     ok(!lstrcmpA(path, sub2), "Expected \"%s\", got \"%s\"\n", sub2, path);
6351     ok(size == lstrlenA(sub2), "Expected %d, got %lu\n", lstrlenA(sub2), size);
6352 
6353     r = MsiDoActionA(hpkg, "CostFinalize");
6354     ok(r == ERROR_SUCCESS, "file cost failed\n");
6355 
6356     /* try TARGETDIR after CostFinalize */
6357     size = MAX_PATH;
6358     lstrcpyA(path, "kiwi");
6359     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6360     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6361     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6362     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6363 
6364     /* try SourceDir after CostFinalize */
6365     size = MAX_PATH;
6366     lstrcpyA(path, "kiwi");
6367     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6368     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6369     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6370     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6371 
6372     /* try SOURCEDIR after CostFinalize */
6373     size = MAX_PATH;
6374     lstrcpyA(path, "kiwi");
6375     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6376     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6377     ok(!lstrcmpA(path, "kiwi"),
6378        "Expected path to be unchanged, got \"%s\"\n", path);
6379     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6380 
6381     /* source path does not exist, but the property exists */
6382     size = MAX_PATH;
6383     lstrcpyA(path, "kiwi");
6384     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6385     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6386     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6387     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6388 
6389     size = MAX_PATH;
6390     lstrcpyA(path, "kiwi");
6391     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6392     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6393     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6394     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6395 
6396     /* try SubDir after CostFinalize */
6397     size = MAX_PATH;
6398     lstrcpyA(path, "kiwi");
6399     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6400     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6401     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6402     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
6403 
6404     /* try SubDir2 after CostFinalize */
6405     size = MAX_PATH;
6406     lstrcpyA(path, "kiwi");
6407     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6408     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6409     ok(!lstrcmpA(path, sub2), "Expected \"%s\", got \"%s\"\n", sub2, path);
6410     ok(size == lstrlenA(sub2), "Expected %d, got %lu\n", lstrlenA(sub2), size);
6411 
6412     /* nonexistent directory */
6413     size = MAX_PATH;
6414     lstrcpyA(path, "kiwi");
6415     r = MsiGetSourcePathA(hpkg, "IDontExist", path, &size);
6416     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6417     ok(!lstrcmpA(path, "kiwi"),
6418        "Expected path to be unchanged, got \"%s\"\n", path);
6419     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6420 
6421     /* NULL szPathBuf */
6422     size = MAX_PATH;
6423     r = MsiGetSourcePathA(hpkg, "SourceDir", NULL, &size);
6424     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6425     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6426 
6427     /* NULL pcchPathBuf */
6428     lstrcpyA(path, "kiwi");
6429     r = MsiGetSourcePathA(hpkg, "SourceDir", path, NULL);
6430     ok(r == ERROR_INVALID_PARAMETER,
6431        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6432     ok(!lstrcmpA(path, "kiwi"),
6433        "Expected path to be unchanged, got \"%s\"\n", path);
6434 
6435     /* pcchPathBuf is 0 */
6436     size = 0;
6437     lstrcpyA(path, "kiwi");
6438     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6439     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
6440     ok(!lstrcmpA(path, "kiwi"),
6441        "Expected path to be unchanged, got \"%s\"\n", path);
6442     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6443 
6444     /* pcchPathBuf does not have room for NULL terminator */
6445     size = lstrlenA(cwd);
6446     lstrcpyA(path, "kiwi");
6447     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6448     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
6449     ok(!strncmp(path, cwd, lstrlenA(cwd) - 1),
6450        "Expected path with no backslash, got \"%s\"\n", path);
6451     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6452 
6453     /* pcchPathBuf has room for NULL terminator */
6454     size = lstrlenA(cwd) + 1;
6455     lstrcpyA(path, "kiwi");
6456     r = MsiGetSourcePathA(hpkg, "SourceDir", 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 %lu\n", lstrlenA(cwd), size);
6460 
6461     /* remove property */
6462     r = MsiSetPropertyA(hpkg, "SourceDir", NULL);
6463     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6464 
6465     /* try SourceDir again */
6466     size = MAX_PATH;
6467     lstrcpyA(path, "kiwi");
6468     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6469     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6470     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6471     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6472 
6473     /* set property to a valid directory */
6474     r = MsiSetPropertyA(hpkg, "SOURCEDIR", cwd);
6475     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6476 
6477     /* try SOURCEDIR again */
6478     size = MAX_PATH;
6479     lstrcpyA(path, "kiwi");
6480     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6481     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6482     ok(!lstrcmpA(path, "kiwi"),
6483        "Expected path to be unchanged, got \"%s\"\n", path);
6484     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6485 
6486     MsiCloseHandle(hpkg);
6487 
6488     /* compressed source */
6489 
6490     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb);
6491     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6492 
6493     set_suminfo_prop(hdb, PID_WORDCOUNT, msidbSumInfoSourceTypeCompressed);
6494 
6495     r = package_from_db(hdb, &hpkg);
6496     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
6497 
6498     /* try TARGETDIR */
6499     size = MAX_PATH;
6500     lstrcpyA(path, "kiwi");
6501     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6502     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6503     ok(!lstrcmpA(path, "kiwi"),
6504        "Expected path to be unchanged, got \"%s\"\n", path);
6505     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6506 
6507     /* try SourceDir */
6508     size = MAX_PATH;
6509     lstrcpyA(path, "kiwi");
6510     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6511     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6512     ok(!lstrcmpA(path, "kiwi"),
6513        "Expected path to be unchanged, got \"%s\"\n", path);
6514     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6515 
6516     /* try SOURCEDIR */
6517     size = MAX_PATH;
6518     lstrcpyA(path, "kiwi");
6519     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6520     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6521     ok(!lstrcmpA(path, "kiwi"),
6522        "Expected path to be unchanged, got \"%s\"\n", path);
6523     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6524 
6525     /* source path nor the property exist */
6526     size = MAX_PATH;
6527     lstrcpyA(path, "kiwi");
6528     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6529     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6530     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6531     ok(size == 0, "Expected 0, got %lu\n", size);
6532 
6533     size = MAX_PATH;
6534     lstrcpyA(path, "kiwi");
6535     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6536     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6537     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6538     ok(size == 0, "Expected 0, got %lu\n", size);
6539 
6540     /* try SubDir */
6541     size = MAX_PATH;
6542     lstrcpyA(path, "kiwi");
6543     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6544     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6545     ok(!lstrcmpA(path, "kiwi"),
6546        "Expected path to be unchanged, got \"%s\"\n", path);
6547     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6548 
6549     /* try SubDir2 */
6550     size = MAX_PATH;
6551     lstrcpyA(path, "kiwi");
6552     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6553     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6554     ok(!lstrcmpA(path, "kiwi"),
6555        "Expected path to be unchanged, got \"%s\"\n", path);
6556     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
6557 
6558     r = MsiDoActionA(hpkg, "CostInitialize");
6559     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6560 
6561     /* try TARGETDIR after CostInitialize */
6562     size = MAX_PATH;
6563     lstrcpyA(path, "kiwi");
6564     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6565     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6566     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6567     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6568 
6569     /* try SourceDir after CostInitialize */
6570     size = MAX_PATH;
6571     lstrcpyA(path, "kiwi");
6572     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6573     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6574     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6575     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6576 
6577     /* try SOURCEDIR after CostInitialize */
6578     size = MAX_PATH;
6579     lstrcpyA(path, "kiwi");
6580     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6581     todo_wine
6582     {
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 %lu\n", lstrlenA(cwd), size);
6586     }
6587 
6588     /* source path does not exist, but the property exists */
6589     size = MAX_PATH;
6590     lstrcpyA(path, "kiwi");
6591     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6592     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6593     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6594     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6595 
6596     size = MAX_PATH;
6597     lstrcpyA(path, "kiwi");
6598     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6599     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6600     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6601     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6602 
6603     /* try SubDir after CostInitialize */
6604     size = MAX_PATH;
6605     lstrcpyA(path, "kiwi");
6606     r = MsiGetSourcePathA(hpkg, "SubDir", 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 %lu\n", lstrlenA(cwd), size);
6610 
6611     /* try SubDir2 after CostInitialize */
6612     size = MAX_PATH;
6613     lstrcpyA(path, "kiwi");
6614     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6615     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6616     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6617     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6618 
6619     r = MsiDoActionA(hpkg, "ResolveSource");
6620     ok(r == ERROR_SUCCESS, "file cost failed\n");
6621 
6622     /* try TARGETDIR after ResolveSource */
6623     size = MAX_PATH;
6624     lstrcpyA(path, "kiwi");
6625     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6626     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6627     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6628     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6629 
6630     /* try SourceDir after ResolveSource */
6631     size = MAX_PATH;
6632     lstrcpyA(path, "kiwi");
6633     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6634     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6635     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6636     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6637 
6638     /* try SOURCEDIR after ResolveSource */
6639     size = MAX_PATH;
6640     lstrcpyA(path, "kiwi");
6641     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6642     todo_wine
6643     {
6644         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6645         ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6646         ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6647     }
6648 
6649     /* source path and the property exist */
6650     size = MAX_PATH;
6651     lstrcpyA(path, "kiwi");
6652     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6653     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6654     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6655     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6656 
6657     size = MAX_PATH;
6658     lstrcpyA(path, "kiwi");
6659     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6660     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6661     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6662     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6663 
6664     /* try SubDir after ResolveSource */
6665     size = MAX_PATH;
6666     lstrcpyA(path, "kiwi");
6667     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6668     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6669     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6670     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6671 
6672     /* try SubDir2 after ResolveSource */
6673     size = MAX_PATH;
6674     lstrcpyA(path, "kiwi");
6675     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6676     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6677     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6678     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6679 
6680     r = MsiDoActionA(hpkg, "FileCost");
6681     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6682 
6683     /* try TARGETDIR after CostFinalize */
6684     size = MAX_PATH;
6685     lstrcpyA(path, "kiwi");
6686     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6687     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6688     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6689     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6690 
6691     /* try SourceDir after CostFinalize */
6692     size = MAX_PATH;
6693     lstrcpyA(path, "kiwi");
6694     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6695     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6696     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6697     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6698 
6699     /* try SOURCEDIR after CostFinalize */
6700     size = MAX_PATH;
6701     lstrcpyA(path, "kiwi");
6702     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6703     todo_wine
6704     {
6705         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6706         ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6707         ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6708     }
6709 
6710     /* source path and the property exist */
6711     size = MAX_PATH;
6712     lstrcpyA(path, "kiwi");
6713     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6714     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6715     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6716     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6717 
6718     size = MAX_PATH;
6719     lstrcpyA(path, "kiwi");
6720     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6721     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6722     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6723     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6724 
6725     /* try SubDir after CostFinalize */
6726     size = MAX_PATH;
6727     lstrcpyA(path, "kiwi");
6728     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6729     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6730     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6731     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6732 
6733     /* try SubDir2 after CostFinalize */
6734     size = MAX_PATH;
6735     lstrcpyA(path, "kiwi");
6736     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6737     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6738     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6739     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6740 
6741     r = MsiDoActionA(hpkg, "CostFinalize");
6742     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6743 
6744     /* try TARGETDIR after CostFinalize */
6745     size = MAX_PATH;
6746     lstrcpyA(path, "kiwi");
6747     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6748     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6749     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6750     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6751 
6752     /* try SourceDir after CostFinalize */
6753     size = MAX_PATH;
6754     lstrcpyA(path, "kiwi");
6755     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6756     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6757     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6758     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6759 
6760     /* try SOURCEDIR after CostFinalize */
6761     size = MAX_PATH;
6762     lstrcpyA(path, "kiwi");
6763     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6764     todo_wine
6765     {
6766         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6767         ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6768         ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6769     }
6770 
6771     /* source path and the property exist */
6772     size = MAX_PATH;
6773     lstrcpyA(path, "kiwi");
6774     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6775     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6776     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6777     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6778 
6779     size = MAX_PATH;
6780     lstrcpyA(path, "kiwi");
6781     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6782     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6783     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6784     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6785 
6786     /* try SubDir after CostFinalize */
6787     size = MAX_PATH;
6788     lstrcpyA(path, "kiwi");
6789     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6790     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6791     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6792     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
6793 
6794     /* try SubDir2 after CostFinalize */
6795     size = MAX_PATH;
6796     lstrcpyA(path, "kiwi");
6797     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
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 %lu\n", lstrlenA(cwd), size);
6801 
6802     MsiCloseHandle(hpkg);
6803     DeleteFileA(msifile);
6804 }
6805 
6806 static void test_shortlongsource(void)
6807 {
6808     MSIHANDLE hdb, hpkg;
6809     CHAR path[MAX_PATH];
6810     CHAR cwd[MAX_PATH];
6811     CHAR subsrc[MAX_PATH];
6812     DWORD size;
6813     UINT r;
6814 
6815     lstrcpyA(cwd, CURR_DIR);
6816     if (!is_root(CURR_DIR)) lstrcatA(cwd, "\\");
6817 
6818     lstrcpyA(subsrc, cwd);
6819     lstrcatA(subsrc, "long");
6820     lstrcatA(subsrc, "\\");
6821 
6822     /* long file names */
6823 
6824     hdb = create_package_db();
6825     ok( hdb, "failed to create database\n");
6826 
6827     set_suminfo_prop(hdb, PID_WORDCOUNT, 0);
6828 
6829     add_directory_entry(hdb, "'TARGETDIR', '', 'SourceDir'");
6830     add_directory_entry(hdb, "'SubDir', 'TARGETDIR', 'short|long'");
6831 
6832     /* CostInitialize:short */
6833     add_directory_entry(hdb, "'SubDir2', 'TARGETDIR', 'one|two'");
6834 
6835     /* CostInitialize:long */
6836     add_directory_entry(hdb, "'SubDir3', 'TARGETDIR', 'three|four'");
6837 
6838     /* FileCost:short */
6839     add_directory_entry(hdb, "'SubDir4', 'TARGETDIR', 'five|six'");
6840 
6841     /* FileCost:long */
6842     add_directory_entry(hdb, "'SubDir5', 'TARGETDIR', 'seven|eight'");
6843 
6844     /* CostFinalize:short */
6845     add_directory_entry(hdb, "'SubDir6', 'TARGETDIR', 'nine|ten'");
6846 
6847     /* CostFinalize:long */
6848     add_directory_entry(hdb, "'SubDir7', 'TARGETDIR', 'eleven|twelve'");
6849 
6850     r = MsiDatabaseCommit(hdb);
6851     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
6852 
6853     r = package_from_db(hdb, &hpkg);
6854     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
6855     {
6856         skip("Not enough rights to perform tests\n");
6857         DeleteFileA(msifile);
6858         return;
6859     }
6860     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
6861 
6862     MsiCloseHandle(hdb);
6863 
6864     CreateDirectoryA("one", NULL);
6865     CreateDirectoryA("four", NULL);
6866 
6867     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
6868 
6869     r = MsiDoActionA(hpkg, "CostInitialize");
6870     ok(r == ERROR_SUCCESS, "file cost failed\n");
6871 
6872     CreateDirectoryA("five", NULL);
6873     CreateDirectoryA("eight", NULL);
6874 
6875     r = MsiDoActionA(hpkg, "FileCost");
6876     ok(r == ERROR_SUCCESS, "file cost failed\n");
6877 
6878     CreateDirectoryA("nine", NULL);
6879     CreateDirectoryA("twelve", NULL);
6880 
6881     r = MsiDoActionA(hpkg, "CostFinalize");
6882     ok(r == ERROR_SUCCESS, "file cost failed\n");
6883 
6884     /* neither short nor long source directories exist */
6885     size = MAX_PATH;
6886     lstrcpyA(path, "kiwi");
6887     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6888     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6889     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6890     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
6891 
6892     CreateDirectoryA("short", NULL);
6893 
6894     /* short source directory exists */
6895     size = MAX_PATH;
6896     lstrcpyA(path, "kiwi");
6897     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6898     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6899     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6900     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
6901 
6902     CreateDirectoryA("long", NULL);
6903 
6904     /* both short and long source directories exist */
6905     size = MAX_PATH;
6906     lstrcpyA(path, "kiwi");
6907     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6908     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6909     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6910     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
6911 
6912     lstrcpyA(subsrc, cwd);
6913     lstrcatA(subsrc, "two");
6914     lstrcatA(subsrc, "\\");
6915 
6916     /* short dir exists before CostInitialize */
6917     size = MAX_PATH;
6918     lstrcpyA(path, "kiwi");
6919     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6920     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6921     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6922     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
6923 
6924     lstrcpyA(subsrc, cwd);
6925     lstrcatA(subsrc, "four");
6926     lstrcatA(subsrc, "\\");
6927 
6928     /* long dir exists before CostInitialize */
6929     size = MAX_PATH;
6930     lstrcpyA(path, "kiwi");
6931     r = MsiGetSourcePathA(hpkg, "SubDir3", path, &size);
6932     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6933     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6934     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
6935 
6936     lstrcpyA(subsrc, cwd);
6937     lstrcatA(subsrc, "six");
6938     lstrcatA(subsrc, "\\");
6939 
6940     /* short dir exists before FileCost */
6941     size = MAX_PATH;
6942     lstrcpyA(path, "kiwi");
6943     r = MsiGetSourcePathA(hpkg, "SubDir4", path, &size);
6944     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6945     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6946     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
6947 
6948     lstrcpyA(subsrc, cwd);
6949     lstrcatA(subsrc, "eight");
6950     lstrcatA(subsrc, "\\");
6951 
6952     /* long dir exists before FileCost */
6953     size = MAX_PATH;
6954     lstrcpyA(path, "kiwi");
6955     r = MsiGetSourcePathA(hpkg, "SubDir5", path, &size);
6956     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6957     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6958     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
6959 
6960     lstrcpyA(subsrc, cwd);
6961     lstrcatA(subsrc, "ten");
6962     lstrcatA(subsrc, "\\");
6963 
6964     /* short dir exists before CostFinalize */
6965     size = MAX_PATH;
6966     lstrcpyA(path, "kiwi");
6967     r = MsiGetSourcePathA(hpkg, "SubDir6", path, &size);
6968     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6969     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6970     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
6971 
6972     lstrcpyA(subsrc, cwd);
6973     lstrcatA(subsrc, "twelve");
6974     lstrcatA(subsrc, "\\");
6975 
6976     /* long dir exists before CostFinalize */
6977     size = MAX_PATH;
6978     lstrcpyA(path, "kiwi");
6979     r = MsiGetSourcePathA(hpkg, "SubDir7", path, &size);
6980     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6981     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6982     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
6983 
6984     MsiCloseHandle(hpkg);
6985     RemoveDirectoryA("short");
6986     RemoveDirectoryA("long");
6987     RemoveDirectoryA("one");
6988     RemoveDirectoryA("four");
6989     RemoveDirectoryA("five");
6990     RemoveDirectoryA("eight");
6991     RemoveDirectoryA("nine");
6992     RemoveDirectoryA("twelve");
6993 
6994     /* short file names */
6995 
6996     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb);
6997     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6998 
6999     set_suminfo_prop(hdb, PID_WORDCOUNT, msidbSumInfoSourceTypeSFN);
7000 
7001     r = package_from_db(hdb, &hpkg);
7002     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
7003 
7004     MsiCloseHandle(hdb);
7005 
7006     CreateDirectoryA("one", NULL);
7007     CreateDirectoryA("four", NULL);
7008 
7009     r = MsiDoActionA(hpkg, "CostInitialize");
7010     ok(r == ERROR_SUCCESS, "file cost failed\n");
7011 
7012     CreateDirectoryA("five", NULL);
7013     CreateDirectoryA("eight", NULL);
7014 
7015     r = MsiDoActionA(hpkg, "FileCost");
7016     ok(r == ERROR_SUCCESS, "file cost failed\n");
7017 
7018     CreateDirectoryA("nine", NULL);
7019     CreateDirectoryA("twelve", NULL);
7020 
7021     r = MsiDoActionA(hpkg, "CostFinalize");
7022     ok(r == ERROR_SUCCESS, "file cost failed\n");
7023 
7024     lstrcpyA(subsrc, cwd);
7025     lstrcatA(subsrc, "short");
7026     lstrcatA(subsrc, "\\");
7027 
7028     /* neither short nor long source directories exist */
7029     size = MAX_PATH;
7030     lstrcpyA(path, "kiwi");
7031     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7032     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7033     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7034     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
7035 
7036     CreateDirectoryA("short", NULL);
7037 
7038     /* short source directory exists */
7039     size = MAX_PATH;
7040     lstrcpyA(path, "kiwi");
7041     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7042     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7043     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7044     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
7045 
7046     CreateDirectoryA("long", NULL);
7047 
7048     /* both short and long source directories exist */
7049     size = MAX_PATH;
7050     lstrcpyA(path, "kiwi");
7051     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7052     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7053     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7054     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
7055 
7056     lstrcpyA(subsrc, cwd);
7057     lstrcatA(subsrc, "one");
7058     lstrcatA(subsrc, "\\");
7059 
7060     /* short dir exists before CostInitialize */
7061     size = MAX_PATH;
7062     lstrcpyA(path, "kiwi");
7063     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
7064     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7065     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7066     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
7067 
7068     lstrcpyA(subsrc, cwd);
7069     lstrcatA(subsrc, "three");
7070     lstrcatA(subsrc, "\\");
7071 
7072     /* long dir exists before CostInitialize */
7073     size = MAX_PATH;
7074     lstrcpyA(path, "kiwi");
7075     r = MsiGetSourcePathA(hpkg, "SubDir3", path, &size);
7076     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7077     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7078     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
7079 
7080     lstrcpyA(subsrc, cwd);
7081     lstrcatA(subsrc, "five");
7082     lstrcatA(subsrc, "\\");
7083 
7084     /* short dir exists before FileCost */
7085     size = MAX_PATH;
7086     lstrcpyA(path, "kiwi");
7087     r = MsiGetSourcePathA(hpkg, "SubDir4", path, &size);
7088     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7089     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7090     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
7091 
7092     lstrcpyA(subsrc, cwd);
7093     lstrcatA(subsrc, "seven");
7094     lstrcatA(subsrc, "\\");
7095 
7096     /* long dir exists before FileCost */
7097     size = MAX_PATH;
7098     lstrcpyA(path, "kiwi");
7099     r = MsiGetSourcePathA(hpkg, "SubDir5", path, &size);
7100     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7101     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7102     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
7103 
7104     lstrcpyA(subsrc, cwd);
7105     lstrcatA(subsrc, "nine");
7106     lstrcatA(subsrc, "\\");
7107 
7108     /* short dir exists before CostFinalize */
7109     size = MAX_PATH;
7110     lstrcpyA(path, "kiwi");
7111     r = MsiGetSourcePathA(hpkg, "SubDir6", path, &size);
7112     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7113     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7114     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
7115 
7116     lstrcpyA(subsrc, cwd);
7117     lstrcatA(subsrc, "eleven");
7118     lstrcatA(subsrc, "\\");
7119 
7120     /* long dir exists before CostFinalize */
7121     size = MAX_PATH;
7122     lstrcpyA(path, "kiwi");
7123     r = MsiGetSourcePathA(hpkg, "SubDir7", path, &size);
7124     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7125     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7126     ok(size == lstrlenA(subsrc), "Expected %d, got %lu\n", lstrlenA(subsrc), size);
7127 
7128     MsiCloseHandle(hpkg);
7129     RemoveDirectoryA("short");
7130     RemoveDirectoryA("long");
7131     RemoveDirectoryA("one");
7132     RemoveDirectoryA("four");
7133     RemoveDirectoryA("five");
7134     RemoveDirectoryA("eight");
7135     RemoveDirectoryA("nine");
7136     RemoveDirectoryA("twelve");
7137     DeleteFileA(msifile);
7138 }
7139 
7140 static void test_sourcedir(void)
7141 {
7142     MSIHANDLE hdb, hpkg;
7143     CHAR package[12];
7144     CHAR path[MAX_PATH];
7145     CHAR cwd[MAX_PATH];
7146     CHAR subsrc[MAX_PATH];
7147     DWORD size;
7148     UINT r;
7149 
7150     lstrcpyA(cwd, CURR_DIR);
7151     if (!is_root(CURR_DIR)) lstrcatA(cwd, "\\");
7152 
7153     lstrcpyA(subsrc, cwd);
7154     lstrcatA(subsrc, "long");
7155     lstrcatA(subsrc, "\\");
7156 
7157     hdb = create_package_db();
7158     ok( hdb, "failed to create database\n");
7159 
7160     add_directory_entry(hdb, "'TARGETDIR', '', 'SourceDir'");
7161 
7162     sprintf(package, "#%lu", hdb);
7163     r = MsiOpenPackageA(package, &hpkg);
7164     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
7165     {
7166         skip("Not enough rights to perform tests\n");
7167         goto error;
7168     }
7169     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7170 
7171     /* properties only */
7172 
7173     /* SourceDir prop */
7174     size = MAX_PATH;
7175     lstrcpyA(path, "kiwi");
7176     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7177     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7178     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7179     ok(size == 0, "Expected 0, got %lu\n", size);
7180 
7181     /* SOURCEDIR prop */
7182     size = MAX_PATH;
7183     lstrcpyA(path, "kiwi");
7184     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7185     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7186     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7187     ok(size == 0, "Expected 0, got %lu\n", size);
7188 
7189     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
7190 
7191     r = MsiDoActionA(hpkg, "CostInitialize");
7192     ok(r == ERROR_SUCCESS, "file cost failed\n");
7193 
7194     /* SourceDir after CostInitialize */
7195     size = MAX_PATH;
7196     lstrcpyA(path, "kiwi");
7197     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7198     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7199     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7200     ok(size == 0, "Expected 0, got %lu\n", size);
7201 
7202     /* SOURCEDIR after CostInitialize */
7203     size = MAX_PATH;
7204     lstrcpyA(path, "kiwi");
7205     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7206     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7207     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7208     ok(size == 0, "Expected 0, got %lu\n", size);
7209 
7210     r = MsiDoActionA(hpkg, "FileCost");
7211     ok(r == ERROR_SUCCESS, "file cost failed\n");
7212 
7213     /* SourceDir after FileCost */
7214     size = MAX_PATH;
7215     lstrcpyA(path, "kiwi");
7216     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7217     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7218     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7219     ok(size == 0, "Expected 0, got %lu\n", size);
7220 
7221     /* SOURCEDIR after FileCost */
7222     size = MAX_PATH;
7223     lstrcpyA(path, "kiwi");
7224     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7225     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7226     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7227     ok(size == 0, "Expected 0, got %lu\n", size);
7228 
7229     r = MsiDoActionA(hpkg, "CostFinalize");
7230     ok(r == ERROR_SUCCESS, "file cost failed\n");
7231 
7232     /* SourceDir after CostFinalize */
7233     size = MAX_PATH;
7234     lstrcpyA(path, "kiwi");
7235     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7236     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7237     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7238     ok(size == 0, "Expected 0, got %lu\n", size);
7239 
7240     /* SOURCEDIR after CostFinalize */
7241     size = MAX_PATH;
7242     lstrcpyA(path, "kiwi");
7243     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7244     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7245     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7246     ok(size == 0, "Expected 0, got %lu\n", size);
7247 
7248     size = MAX_PATH;
7249     lstrcpyA(path, "kiwi");
7250     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7251     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7252     ok(!lstrcmpA(path, "kiwi"), "Expected \"kiwi\", got \"%s\"\n", path);
7253     ok(size == MAX_PATH, "Expected %d, got %lu\n", MAX_PATH, size);
7254 
7255     /* SOURCEDIR after calling MsiGetSourcePath */
7256     size = MAX_PATH;
7257     lstrcpyA(path, "kiwi");
7258     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7259     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7260     todo_wine {
7261     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7262     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
7263     }
7264 
7265     r = MsiDoActionA(hpkg, "ResolveSource");
7266     ok(r == ERROR_SUCCESS, "file cost failed\n");
7267 
7268     /* SourceDir after ResolveSource */
7269     size = MAX_PATH;
7270     lstrcpyA(path, "kiwi");
7271     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7272     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7273     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7274     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
7275 
7276     /* SOURCEDIR after ResolveSource */
7277     size = MAX_PATH;
7278     lstrcpyA(path, "kiwi");
7279     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7280     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7281     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7282     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
7283 
7284     /* random casing */
7285     size = MAX_PATH;
7286     lstrcpyA(path, "kiwi");
7287     r = MsiGetPropertyA(hpkg, "SoUrCeDiR", path, &size);
7288     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7289     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7290     ok(size == 0, "Expected 0, got %lu\n", size);
7291 
7292     MsiCloseHandle(hpkg);
7293 
7294     /* reset the package state */
7295     sprintf(package, "#%lu", hdb);
7296     r = MsiOpenPackageA(package, &hpkg);
7297     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7298 
7299     /* test how MsiGetSourcePath affects the properties */
7300 
7301     /* SourceDir prop */
7302     size = MAX_PATH;
7303     lstrcpyA(path, "kiwi");
7304     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7305     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7306     todo_wine
7307     {
7308         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7309         ok(size == 0, "Expected 0, got %lu\n", size);
7310     }
7311 
7312     size = MAX_PATH;
7313     lstrcpyA(path, "kiwi");
7314     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
7315     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7316     ok(!lstrcmpA(path, "kiwi"),
7317        "Expected path to be unchanged, got \"%s\"\n", path);
7318     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
7319 
7320     /* SourceDir after MsiGetSourcePath */
7321     size = MAX_PATH;
7322     lstrcpyA(path, "kiwi");
7323     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7324     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7325     todo_wine
7326     {
7327         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7328         ok(size == 0, "Expected 0, got %lu\n", size);
7329     }
7330 
7331     /* SOURCEDIR prop */
7332     size = MAX_PATH;
7333     lstrcpyA(path, "kiwi");
7334     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7335     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7336     todo_wine
7337     {
7338         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7339         ok(size == 0, "Expected 0, got %lu\n", size);
7340     }
7341 
7342     size = MAX_PATH;
7343     lstrcpyA(path, "kiwi");
7344     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7345     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7346     ok(!lstrcmpA(path, "kiwi"),
7347        "Expected path to be unchanged, got \"%s\"\n", path);
7348     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
7349 
7350     /* SOURCEDIR prop after MsiGetSourcePath */
7351     size = MAX_PATH;
7352     lstrcpyA(path, "kiwi");
7353     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7354     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7355     todo_wine
7356     {
7357         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7358         ok(size == 0, "Expected 0, got %lu\n", size);
7359     }
7360 
7361     r = MsiDoActionA(hpkg, "CostInitialize");
7362     ok(r == ERROR_SUCCESS, "file cost failed\n");
7363 
7364     /* SourceDir after CostInitialize */
7365     size = MAX_PATH;
7366     lstrcpyA(path, "kiwi");
7367     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7368     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7369     todo_wine
7370     {
7371         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7372         ok(size == 0, "Expected 0, got %lu\n", size);
7373     }
7374 
7375     size = MAX_PATH;
7376     lstrcpyA(path, "kiwi");
7377     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
7378     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7379     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7380     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
7381 
7382     /* SourceDir after MsiGetSourcePath */
7383     size = MAX_PATH;
7384     lstrcpyA(path, "kiwi");
7385     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7386     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7387     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7388     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
7389 
7390     /* SOURCEDIR after CostInitialize */
7391     size = MAX_PATH;
7392     lstrcpyA(path, "kiwi");
7393     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7394     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7395     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7396     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
7397 
7398     /* SOURCEDIR source path still does not exist */
7399     size = MAX_PATH;
7400     lstrcpyA(path, "kiwi");
7401     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7402     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7403     ok(!lstrcmpA(path, "kiwi"),
7404        "Expected path to be unchanged, got \"%s\"\n", path);
7405     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
7406 
7407     r = MsiDoActionA(hpkg, "FileCost");
7408     ok(r == ERROR_SUCCESS, "file cost failed\n");
7409 
7410     /* SourceDir after FileCost */
7411     size = MAX_PATH;
7412     lstrcpyA(path, "kiwi");
7413     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7414     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7415     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7416     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
7417 
7418     /* SOURCEDIR after FileCost */
7419     size = MAX_PATH;
7420     lstrcpyA(path, "kiwi");
7421     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7422     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7423     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7424     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
7425 
7426     /* SOURCEDIR source path still does not exist */
7427     size = MAX_PATH;
7428     lstrcpyA(path, "kiwi");
7429     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7430     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7431     ok(!lstrcmpA(path, "kiwi"),
7432        "Expected path to be unchanged, got \"%s\"\n", path);
7433     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
7434 
7435     r = MsiDoActionA(hpkg, "CostFinalize");
7436     ok(r == ERROR_SUCCESS, "file cost failed\n");
7437 
7438     /* SourceDir after CostFinalize */
7439     size = MAX_PATH;
7440     lstrcpyA(path, "kiwi");
7441     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7442     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7443     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7444     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
7445 
7446     /* SOURCEDIR after CostFinalize */
7447     size = MAX_PATH;
7448     lstrcpyA(path, "kiwi");
7449     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7450     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7451     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7452     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
7453 
7454     /* SOURCEDIR source path still does not exist */
7455     size = MAX_PATH;
7456     lstrcpyA(path, "kiwi");
7457     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7458     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7459     ok(!lstrcmpA(path, "kiwi"),
7460        "Expected path to be unchanged, got \"%s\"\n", path);
7461     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
7462 
7463     r = MsiDoActionA(hpkg, "ResolveSource");
7464     ok(r == ERROR_SUCCESS, "file cost failed\n");
7465 
7466     /* SourceDir after ResolveSource */
7467     size = MAX_PATH;
7468     lstrcpyA(path, "kiwi");
7469     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7470     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7471     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7472     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
7473 
7474     /* SOURCEDIR after ResolveSource */
7475     size = MAX_PATH;
7476     lstrcpyA(path, "kiwi");
7477     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7478     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7479     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7480     ok(size == lstrlenA(cwd), "Expected %d, got %lu\n", lstrlenA(cwd), size);
7481 
7482     /* SOURCEDIR source path still does not exist */
7483     size = MAX_PATH;
7484     lstrcpyA(path, "kiwi");
7485     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7486     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7487     ok(!lstrcmpA(path, "kiwi"),
7488        "Expected path to be unchanged, got \"%s\"\n", path);
7489     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
7490 
7491     MsiCloseHandle(hpkg);
7492 
7493 error:
7494     MsiCloseHandle(hdb);
7495     DeleteFileA(msifile);
7496 }
7497 
7498 struct access_res
7499 {
7500     BOOL gothandle;
7501     DWORD lasterr;
7502     BOOL ignore;
7503 };
7504 
7505 static const struct access_res create[16] =
7506 {
7507     { TRUE, ERROR_SUCCESS, TRUE },
7508     { TRUE, ERROR_SUCCESS, TRUE },
7509     { TRUE, ERROR_SUCCESS, FALSE },
7510     { TRUE, ERROR_SUCCESS, FALSE },
7511     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7512     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7513     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7514     { TRUE, ERROR_SUCCESS, FALSE },
7515     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7516     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7517     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7518     { TRUE, ERROR_SUCCESS, TRUE },
7519     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7520     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7521     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7522     { TRUE, ERROR_SUCCESS, TRUE }
7523 };
7524 
7525 static const struct access_res create_commit[16] =
7526 {
7527     { TRUE, ERROR_SUCCESS, TRUE },
7528     { TRUE, ERROR_SUCCESS, TRUE },
7529     { TRUE, ERROR_SUCCESS, FALSE },
7530     { TRUE, ERROR_SUCCESS, FALSE },
7531     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7532     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7533     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7534     { TRUE, ERROR_SUCCESS, FALSE },
7535     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7536     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7537     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7538     { TRUE, ERROR_SUCCESS, TRUE },
7539     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7540     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7541     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7542     { TRUE, ERROR_SUCCESS, TRUE }
7543 };
7544 
7545 static const struct access_res create_close[16] =
7546 {
7547     { TRUE, ERROR_SUCCESS, FALSE },
7548     { TRUE, ERROR_SUCCESS, FALSE },
7549     { TRUE, ERROR_SUCCESS, FALSE },
7550     { TRUE, ERROR_SUCCESS, FALSE },
7551     { TRUE, ERROR_SUCCESS, FALSE },
7552     { TRUE, ERROR_SUCCESS, FALSE },
7553     { TRUE, ERROR_SUCCESS, FALSE },
7554     { TRUE, ERROR_SUCCESS, FALSE },
7555     { TRUE, ERROR_SUCCESS, FALSE },
7556     { TRUE, ERROR_SUCCESS, FALSE },
7557     { TRUE, ERROR_SUCCESS, FALSE },
7558     { TRUE, ERROR_SUCCESS, FALSE },
7559     { TRUE, ERROR_SUCCESS, FALSE },
7560     { TRUE, ERROR_SUCCESS, FALSE },
7561     { TRUE, ERROR_SUCCESS, FALSE },
7562     { TRUE, ERROR_SUCCESS }
7563 };
7564 
7565 static void _test_file_access(LPCSTR file, const struct access_res *ares, DWORD line)
7566 {
7567     DWORD access = 0, share = 0;
7568     DWORD lasterr;
7569     HANDLE hfile;
7570     int i, j, idx = 0;
7571 
7572     for (i = 0; i < 4; i++)
7573     {
7574         if (i == 0) access = 0;
7575         if (i == 1) access = GENERIC_READ;
7576         if (i == 2) access = GENERIC_WRITE;
7577         if (i == 3) access = GENERIC_READ | GENERIC_WRITE;
7578 
7579         for (j = 0; j < 4; j++)
7580         {
7581             if (ares[idx].ignore)
7582                 continue;
7583 
7584             if (j == 0) share = 0;
7585             if (j == 1) share = FILE_SHARE_READ;
7586             if (j == 2) share = FILE_SHARE_WRITE;
7587             if (j == 3) share = FILE_SHARE_READ | FILE_SHARE_WRITE;
7588 
7589             SetLastError(0xdeadbeef);
7590             hfile = CreateFileA(file, access, share, NULL, OPEN_EXISTING,
7591                                 FILE_ATTRIBUTE_NORMAL, 0);
7592             lasterr = GetLastError();
7593 
7594             ok((hfile != INVALID_HANDLE_VALUE) == ares[idx].gothandle,
7595                "(%lu, handle, %d): Expected %d, got %d\n",
7596                line, idx, ares[idx].gothandle,
7597                (hfile != INVALID_HANDLE_VALUE));
7598 
7599             ok(lasterr == ares[idx].lasterr, "(%lu, lasterr, %u): Expected %lu, got %lu\n",
7600                line, idx, ares[idx].lasterr, lasterr);
7601 
7602             CloseHandle(hfile);
7603             idx++;
7604         }
7605     }
7606 }
7607 
7608 #define test_file_access(file, ares) _test_file_access(file, ares, __LINE__)
7609 
7610 static void test_access(void)
7611 {
7612     MSIHANDLE hdb;
7613     UINT r;
7614 
7615     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
7616     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7617 
7618     test_file_access(msifile, create);
7619 
7620     r = MsiDatabaseCommit(hdb);
7621     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7622 
7623     test_file_access(msifile, create_commit);
7624     MsiCloseHandle(hdb);
7625 
7626     test_file_access(msifile, create_close);
7627     DeleteFileA(msifile);
7628 
7629     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATEDIRECT, &hdb);
7630     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7631 
7632     test_file_access(msifile, create);
7633 
7634     r = MsiDatabaseCommit(hdb);
7635     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7636 
7637     test_file_access(msifile, create_commit);
7638     MsiCloseHandle(hdb);
7639 
7640     test_file_access(msifile, create_close);
7641     DeleteFileA(msifile);
7642 }
7643 
7644 static void test_emptypackage(void)
7645 {
7646     MSIHANDLE hpkg = 0, hdb = 0, hsuminfo = 0;
7647     MSIHANDLE hview = 0, hrec = 0;
7648     MSICONDITION condition;
7649     CHAR buffer[MAX_PATH];
7650     DWORD size;
7651     UINT r;
7652 
7653     r = MsiOpenPackageA("", &hpkg);
7654     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
7655     {
7656         skip("Not enough rights to perform tests\n");
7657         return;
7658     }
7659     todo_wine
7660     {
7661         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7662     }
7663 
7664     hdb = MsiGetActiveDatabase(hpkg);
7665     todo_wine
7666     {
7667         ok(hdb != 0, "Expected a valid database handle\n");
7668     }
7669 
7670     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Tables`", &hview);
7671     todo_wine
7672     {
7673         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7674     }
7675     r = MsiViewExecute(hview, 0);
7676     todo_wine
7677     {
7678         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7679     }
7680 
7681     r = MsiViewFetch(hview, &hrec);
7682     todo_wine
7683     {
7684         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7685     }
7686 
7687     buffer[0] = 0;
7688     size = MAX_PATH;
7689     r = MsiRecordGetStringA(hrec, 1, buffer, &size);
7690     todo_wine
7691     {
7692         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7693         ok(!lstrcmpA(buffer, "_Property"),
7694            "Expected \"_Property\", got \"%s\"\n", buffer);
7695     }
7696 
7697     MsiCloseHandle(hrec);
7698 
7699     r = MsiViewFetch(hview, &hrec);
7700     todo_wine
7701     {
7702         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7703     }
7704 
7705     size = MAX_PATH;
7706     r = MsiRecordGetStringA(hrec, 1, buffer, &size);
7707     todo_wine
7708     {
7709         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7710         ok(!lstrcmpA(buffer, "#_FolderCache"),
7711            "Expected \"_Property\", got \"%s\"\n", buffer);
7712     }
7713 
7714     MsiCloseHandle(hrec);
7715     MsiViewClose(hview);
7716     MsiCloseHandle(hview);
7717 
7718     condition = MsiDatabaseIsTablePersistentA(hdb, "_Property");
7719     todo_wine
7720     {
7721         ok(condition == MSICONDITION_FALSE,
7722            "Expected MSICONDITION_FALSE, got %d\n", condition);
7723     }
7724 
7725     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Property`", &hview);
7726     todo_wine
7727     {
7728         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7729     }
7730     r = MsiViewExecute(hview, 0);
7731     todo_wine
7732     {
7733         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7734     }
7735 
7736     /* _Property table is not empty */
7737     r = MsiViewFetch(hview, &hrec);
7738     todo_wine
7739     {
7740         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7741     }
7742 
7743     MsiCloseHandle(hrec);
7744     MsiViewClose(hview);
7745     MsiCloseHandle(hview);
7746 
7747     condition = MsiDatabaseIsTablePersistentA(hdb, "#_FolderCache");
7748     todo_wine
7749     {
7750         ok(condition == MSICONDITION_FALSE,
7751            "Expected MSICONDITION_FALSE, got %d\n", condition);
7752     }
7753 
7754     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `#_FolderCache`", &hview);
7755     todo_wine
7756     {
7757         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7758     }
7759     r = MsiViewExecute(hview, 0);
7760     todo_wine
7761     {
7762         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7763     }
7764 
7765     /* #_FolderCache is not empty */
7766     r = MsiViewFetch(hview, &hrec);
7767     todo_wine
7768     {
7769         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7770     }
7771 
7772     MsiCloseHandle(hrec);
7773     MsiViewClose(hview);
7774     MsiCloseHandle(hview);
7775 
7776     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Streams`", &hview);
7777     todo_wine
7778     {
7779         ok(r == ERROR_BAD_QUERY_SYNTAX,
7780            "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7781     }
7782 
7783     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Storages`", &hview);
7784     todo_wine
7785     {
7786         ok(r == ERROR_BAD_QUERY_SYNTAX,
7787            "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7788     }
7789 
7790     r = MsiGetSummaryInformationA(hdb, NULL, 0, &hsuminfo);
7791     todo_wine
7792     {
7793         ok(r == ERROR_INSTALL_PACKAGE_INVALID,
7794            "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
7795     }
7796 
7797     MsiCloseHandle(hsuminfo);
7798 
7799     r = MsiDatabaseCommit(hdb);
7800     todo_wine
7801     {
7802         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7803     }
7804 
7805     MsiCloseHandle(hdb);
7806     MsiCloseHandle(hpkg);
7807 }
7808 
7809 static void test_MsiGetProductProperty(void)
7810 {
7811     WCHAR valW[MAX_PATH];
7812     MSIHANDLE hprod, hdb;
7813     CHAR val[MAX_PATH];
7814     CHAR path[MAX_PATH];
7815     CHAR query[MAX_PATH + 17];
7816     CHAR keypath[MAX_PATH*2];
7817     CHAR prodcode[MAX_PATH];
7818     WCHAR prodcodeW[MAX_PATH];
7819     CHAR prod_squashed[MAX_PATH];
7820     WCHAR prod_squashedW[MAX_PATH];
7821     HKEY prodkey, userkey, props;
7822     DWORD size;
7823     LONG res;
7824     UINT r;
7825     REGSAM access = KEY_ALL_ACCESS;
7826 
7827     GetCurrentDirectoryA(MAX_PATH, path);
7828     lstrcatA(path, "\\");
7829 
7830     create_test_guid(prodcode, prod_squashed);
7831     MultiByteToWideChar(CP_ACP, 0, prodcode, -1, prodcodeW, MAX_PATH);
7832     squash_guid(prodcodeW, prod_squashedW);
7833 
7834     if (is_wow64)
7835         access |= KEY_WOW64_64KEY;
7836 
7837     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
7838     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7839 
7840     r = MsiDatabaseCommit(hdb);
7841     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7842 
7843     r = set_summary_info(hdb);
7844     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7845 
7846     r = run_query(hdb, 0,
7847             "CREATE TABLE `Directory` ( "
7848             "`Directory` CHAR(255) NOT NULL, "
7849             "`Directory_Parent` CHAR(255), "
7850             "`DefaultDir` CHAR(255) NOT NULL "
7851             "PRIMARY KEY `Directory`)");
7852     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7853 
7854     create_property_table(hdb);
7855 
7856     sprintf(query, "'ProductCode', '%s'", prodcode);
7857     r = add_property_entry(hdb, query);
7858 
7859     r = MsiDatabaseCommit(hdb);
7860     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7861 
7862     MsiCloseHandle(hdb);
7863 
7864     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
7865     lstrcatA(keypath, prod_squashed);
7866 
7867     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
7868     if (res == ERROR_ACCESS_DENIED)
7869     {
7870         skip("Not enough rights to perform tests\n");
7871         DeleteFileA(msifile);
7872         return;
7873     }
7874     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7875 
7876     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
7877     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
7878     lstrcatA(keypath, prod_squashed);
7879 
7880     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
7881     if (res == ERROR_ACCESS_DENIED)
7882     {
7883         skip("Not enough rights to perform tests\n");
7884         RegDeleteKeyA(prodkey, "");
7885         RegCloseKey(prodkey);
7886         DeleteFileA(msifile);
7887         return;
7888     }
7889     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7890 
7891     res = RegCreateKeyExA(userkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
7892     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7893 
7894     lstrcpyA(val, path);
7895     lstrcatA(val, "\\");
7896     lstrcatA(val, msifile);
7897     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ, (const BYTE *)val, lstrlenA(val) + 1);
7898     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
7899 
7900     hprod = 0xdeadbeef;
7901     r = MsiOpenProductA(prodcode, &hprod);
7902     if (r == ERROR_UNKNOWN_PRODUCT)
7903     {
7904         win_skip("broken result, skipping tests\n");
7905         goto done;
7906     }
7907     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7908     ok(hprod != 0 && hprod != 0xdeadbeef, "Expected a valid product handle\n");
7909 
7910     /* hProduct is invalid */
7911     size = MAX_PATH;
7912     lstrcpyA(val, "apple");
7913     r = MsiGetProductPropertyA(0xdeadbeef, "ProductCode", val, &size);
7914     ok(r == ERROR_INVALID_HANDLE,
7915        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
7916     ok(!lstrcmpA(val, "apple"),
7917        "Expected val to be unchanged, got \"%s\"\n", val);
7918     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
7919 
7920     size = MAX_PATH;
7921     lstrcpyW(valW, L"apple");
7922     r = MsiGetProductPropertyW(0xdeadbeef, L"ProductCode", valW, &size);
7923     ok(r == ERROR_INVALID_HANDLE,
7924        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
7925     ok(!lstrcmpW(valW, L"apple"),
7926        "Expected val to be unchanged, got %s\n", wine_dbgstr_w(valW));
7927     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
7928 
7929     /* szProperty is NULL */
7930     size = MAX_PATH;
7931     lstrcpyA(val, "apple");
7932     r = MsiGetProductPropertyA(hprod, NULL, val, &size);
7933     ok(r == ERROR_INVALID_PARAMETER,
7934        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
7935     ok(!lstrcmpA(val, "apple"),
7936        "Expected val to be unchanged, got \"%s\"\n", val);
7937     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
7938 
7939     size = MAX_PATH;
7940     lstrcpyW(valW, L"apple");
7941     r = MsiGetProductPropertyW(hprod, NULL, valW, &size);
7942     ok(r == ERROR_INVALID_PARAMETER,
7943        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
7944     ok(!lstrcmpW(valW, L"apple"),
7945        "Expected val to be unchanged, got %s\n", wine_dbgstr_w(valW));
7946     ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
7947 
7948     /* szProperty is empty */
7949     size = MAX_PATH;
7950     lstrcpyA(val, "apple");
7951     r = MsiGetProductPropertyA(hprod, "", val, &size);
7952     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7953     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
7954     ok(size == 0, "Expected 0, got %lu\n", size);
7955 
7956     size = MAX_PATH;
7957     lstrcpyW(valW, L"apple");
7958     r = MsiGetProductPropertyW(hprod, L"", valW, &size);
7959     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7960     ok(*valW == 0, "Expected \"\", got %s\n", wine_dbgstr_w(valW));
7961     ok(size == 0, "Expected 0, got %lu\n", size);
7962 
7963     /* get the property */
7964     size = MAX_PATH;
7965     lstrcpyA(val, "apple");
7966     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
7967     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7968     ok(!lstrcmpA(val, prodcode),
7969        "Expected \"%s\", got \"%s\"\n", prodcode, val);
7970     ok(size == lstrlenA(prodcode),
7971        "Expected %d, got %lu\n", lstrlenA(prodcode), size);
7972 
7973     size = MAX_PATH;
7974     lstrcpyW(valW, L"apple");
7975     r = MsiGetProductPropertyW(hprod, L"ProductCode", valW, &size);
7976     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7977     ok(!lstrcmpW(valW, prodcodeW),
7978        "Expected %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
7979     ok(size == lstrlenW(prodcodeW),
7980        "Expected %d, got %lu\n", lstrlenW(prodcodeW), size);
7981 
7982     /* lpValueBuf is NULL */
7983     size = MAX_PATH;
7984     r = MsiGetProductPropertyA(hprod, "ProductCode", NULL, &size);
7985     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7986     ok(size == lstrlenA(prodcode),
7987        "Expected %d, got %lu\n", lstrlenA(prodcode), size);
7988 
7989     size = MAX_PATH;
7990     r = MsiGetProductPropertyW(hprod, L"ProductCode", NULL, &size);
7991     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7992     ok(size == lstrlenW(prodcodeW),
7993        "Expected %d, got %lu\n", lstrlenW(prodcodeW), size);
7994 
7995     /* pcchValueBuf is NULL */
7996     lstrcpyA(val, "apple");
7997     r = MsiGetProductPropertyA(hprod, "ProductCode", val, NULL);
7998     ok(r == ERROR_INVALID_PARAMETER,
7999        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8000     ok(!lstrcmpA(val, "apple"),
8001        "Expected val to be unchanged, got \"%s\"\n", val);
8002     ok(size == lstrlenA(prodcode),
8003        "Expected %d, got %lu\n", lstrlenA(prodcode), size);
8004 
8005     lstrcpyW(valW, L"apple");
8006     r = MsiGetProductPropertyW(hprod, L"ProductCode", valW, NULL);
8007     ok(r == ERROR_INVALID_PARAMETER,
8008        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8009     ok(!lstrcmpW(valW, L"apple"),
8010        "Expected val to be unchanged, got %s\n", wine_dbgstr_w(valW));
8011     ok(size == lstrlenW(prodcodeW),
8012        "Expected %d, got %lu\n", lstrlenW(prodcodeW), size);
8013 
8014     /* pcchValueBuf is too small */
8015     size = 4;
8016     lstrcpyA(val, "apple");
8017     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8018     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
8019     ok(!strncmp(val, prodcode, 3),
8020        "Expected first 3 chars of \"%s\", got \"%s\"\n", prodcode, val);
8021     ok(size == lstrlenA(prodcode),
8022        "Expected %d, got %lu\n", lstrlenA(prodcode), size);
8023 
8024     size = 4;
8025     lstrcpyW(valW, L"apple");
8026     r = MsiGetProductPropertyW(hprod, L"ProductCode", valW, &size);
8027     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
8028     ok(!memcmp(valW, prodcodeW, 3 * sizeof(WCHAR)),
8029        "Expected first 3 chars of %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8030     ok(size == lstrlenW(prodcodeW),
8031        "Expected %d, got %lu\n", lstrlenW(prodcodeW), size);
8032 
8033     /* pcchValueBuf does not leave room for NULL terminator */
8034     size = lstrlenA(prodcode);
8035     lstrcpyA(val, "apple");
8036     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8037     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
8038     ok(!strncmp(val, prodcode, lstrlenA(prodcode) - 1),
8039        "Expected first 37 chars of \"%s\", got \"%s\"\n", prodcode, val);
8040     ok(size == lstrlenA(prodcode),
8041        "Expected %d, got %lu\n", lstrlenA(prodcode), size);
8042 
8043     size = lstrlenW(prodcodeW);
8044     lstrcpyW(valW, L"apple");
8045     r = MsiGetProductPropertyW(hprod, L"ProductCode", valW, &size);
8046     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
8047     ok(!memcmp(valW, prodcodeW, lstrlenW(prodcodeW) - 1),
8048        "Expected first 37 chars of %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8049     ok(size == lstrlenW(prodcodeW),
8050        "Expected %d, got %lu\n", lstrlenW(prodcodeW), size);
8051 
8052     /* pcchValueBuf has enough room for NULL terminator */
8053     size = lstrlenA(prodcode) + 1;
8054     lstrcpyA(val, "apple");
8055     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8056     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8057     ok(!lstrcmpA(val, prodcode),
8058        "Expected \"%s\", got \"%s\"\n", prodcode, val);
8059     ok(size == lstrlenA(prodcode),
8060        "Expected %d, got %lu\n", lstrlenA(prodcode), size);
8061 
8062     size = lstrlenW(prodcodeW) + 1;
8063     lstrcpyW(valW, L"apple");
8064     r = MsiGetProductPropertyW(hprod, L"ProductCode", valW, &size);
8065     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8066     ok(!lstrcmpW(valW, prodcodeW),
8067        "Expected %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8068     ok(size == lstrlenW(prodcodeW),
8069        "Expected %d, got %lu\n", lstrlenW(prodcodeW), size);
8070 
8071     /* nonexistent property */
8072     size = MAX_PATH;
8073     lstrcpyA(val, "apple");
8074     r = MsiGetProductPropertyA(hprod, "IDontExist", val, &size);
8075     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8076     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
8077     ok(size == 0, "Expected 0, got %lu\n", size);
8078 
8079     size = MAX_PATH;
8080     lstrcpyW(valW, L"apple");
8081     r = MsiGetProductPropertyW(hprod, L"IDontExist", valW, &size);
8082     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8083     ok(!lstrcmpW(valW, L""), "Expected \"\", got %s\n", wine_dbgstr_w(valW));
8084     ok(size == 0, "Expected 0, got %lu\n", size);
8085 
8086     r = MsiSetPropertyA(hprod, "NewProperty", "value");
8087     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8088 
8089     /* non-product property set */
8090     size = MAX_PATH;
8091     lstrcpyA(val, "apple");
8092     r = MsiGetProductPropertyA(hprod, "NewProperty", val, &size);
8093     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8094     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
8095     ok(size == 0, "Expected 0, got %lu\n", size);
8096 
8097     size = MAX_PATH;
8098     lstrcpyW(valW, L"apple");
8099     r = MsiGetProductPropertyW(hprod, L"NewProperty", valW, &size);
8100     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8101     ok(!lstrcmpW(valW, L""), "Expected \"\", got %s\n", wine_dbgstr_w(valW));
8102     ok(size == 0, "Expected 0, got %lu\n", size);
8103 
8104     r = MsiSetPropertyA(hprod, "ProductCode", "value");
8105     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8106 
8107     /* non-product property that is also a product property set */
8108     size = MAX_PATH;
8109     lstrcpyA(val, "apple");
8110     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8111     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8112     ok(!lstrcmpA(val, prodcode),
8113        "Expected \"%s\", got \"%s\"\n", prodcode, val);
8114     ok(size == lstrlenA(prodcode),
8115        "Expected %d, got %lu\n", lstrlenA(prodcode), size);
8116 
8117     size = MAX_PATH;
8118     lstrcpyW(valW, L"apple");
8119     r = MsiGetProductPropertyW(hprod, L"ProductCode", valW, &size);
8120     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8121     ok(!lstrcmpW(valW, prodcodeW),
8122        "Expected %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8123     ok(size == lstrlenW(prodcodeW),
8124        "Expected %d, got %lu\n", lstrlenW(prodcodeW), size);
8125 
8126     MsiCloseHandle(hprod);
8127 done:
8128     RegDeleteValueA(props, "LocalPackage");
8129     RegDeleteKeyExA(props, "", access, 0);
8130     RegCloseKey(props);
8131     RegDeleteKeyExA(userkey, "", access, 0);
8132     RegCloseKey(userkey);
8133     RegDeleteKeyExA(prodkey, "", access, 0);
8134     RegCloseKey(prodkey);
8135     DeleteFileA(msifile);
8136 }
8137 
8138 static void test_MsiSetProperty(void)
8139 {
8140     MSIHANDLE hpkg, hdb, hrec;
8141     CHAR buf[MAX_PATH];
8142     LPCSTR query;
8143     DWORD size;
8144     UINT r;
8145 
8146     r = package_from_db(create_package_db(), &hpkg);
8147     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
8148     {
8149         skip("Not enough rights to perform tests\n");
8150         DeleteFileA(msifile);
8151         return;
8152     }
8153     ok(r == ERROR_SUCCESS, "Expected a valid package %u\n", r);
8154 
8155     /* invalid hInstall */
8156     r = MsiSetPropertyA(0, "Prop", "Val");
8157     ok(r == ERROR_INVALID_HANDLE,
8158        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
8159 
8160     /* invalid hInstall */
8161     r = MsiSetPropertyA(0xdeadbeef, "Prop", "Val");
8162     ok(r == ERROR_INVALID_HANDLE,
8163        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
8164 
8165     /* szName is NULL */
8166     r = MsiSetPropertyA(hpkg, NULL, "Val");
8167     ok(r == ERROR_INVALID_PARAMETER,
8168        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8169 
8170     /* both szName and szValue are NULL */
8171     r = MsiSetPropertyA(hpkg, NULL, NULL);
8172     ok(r == ERROR_INVALID_PARAMETER,
8173        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8174 
8175     /* szName is empty */
8176     r = MsiSetPropertyA(hpkg, "", "Val");
8177     ok(r == ERROR_FUNCTION_FAILED,
8178        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
8179 
8180     /* szName is empty and szValue is NULL */
8181     r = MsiSetPropertyA(hpkg, "", NULL);
8182     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8183 
8184     /* set a property */
8185     r = MsiSetPropertyA(hpkg, "Prop", "Val");
8186     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8187 
8188     /* get the property */
8189     size = MAX_PATH;
8190     r = MsiGetPropertyA(hpkg, "Prop", buf, &size);
8191     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8192     ok(!lstrcmpA(buf, "Val"), "Expected \"Val\", got \"%s\"\n", buf);
8193     ok(size == 3, "Expected 3, got %lu\n", size);
8194 
8195     /* update the property */
8196     r = MsiSetPropertyA(hpkg, "Prop", "Nuvo");
8197     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8198 
8199     /* get the property */
8200     size = MAX_PATH;
8201     r = MsiGetPropertyA(hpkg, "Prop", buf, &size);
8202     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8203     ok(!lstrcmpA(buf, "Nuvo"), "Expected \"Nuvo\", got \"%s\"\n", buf);
8204     ok(size == 4, "Expected 4, got %lu\n", size);
8205 
8206     hdb = MsiGetActiveDatabase(hpkg);
8207     ok(hdb != 0, "Expected a valid database handle\n");
8208 
8209     /* set prop is not in the _Property table */
8210     query = "SELECT * FROM `_Property` WHERE `Property` = 'Prop'";
8211     r = do_query(hdb, query, &hrec);
8212     ok(r == ERROR_BAD_QUERY_SYNTAX,
8213        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8214 
8215     /* set prop is not in the Property table */
8216     query = "SELECT * FROM `Property` WHERE `Property` = 'Prop'";
8217     r = do_query(hdb, query, &hrec);
8218     ok(r == ERROR_BAD_QUERY_SYNTAX,
8219        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8220 
8221     MsiCloseHandle(hdb);
8222 
8223     /* szValue is an empty string */
8224     r = MsiSetPropertyA(hpkg, "Prop", "");
8225     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8226 
8227     /* try to get the property */
8228     size = MAX_PATH;
8229     r = MsiGetPropertyA(hpkg, "Prop", buf, &size);
8230     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8231     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
8232     ok(size == 0, "Expected 0, got %lu\n", size);
8233 
8234     /* reset the property */
8235     r = MsiSetPropertyA(hpkg, "Prop", "BlueTap");
8236     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8237 
8238     /* delete the property */
8239     r = MsiSetPropertyA(hpkg, "Prop", NULL);
8240     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8241 
8242     /* try to get the property */
8243     size = MAX_PATH;
8244     r = MsiGetPropertyA(hpkg, "Prop", buf, &size);
8245     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8246     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
8247     ok(size == 0, "Expected 0, got %lu\n", size);
8248 
8249     MsiCloseHandle(hpkg);
8250     DeleteFileA(msifile);
8251 }
8252 
8253 static void test_MsiApplyMultiplePatches(void)
8254 {
8255     UINT r, type = GetDriveTypeW(NULL);
8256 
8257     r = MsiApplyMultiplePatchesA(NULL, NULL, NULL);
8258     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
8259 
8260     r = MsiApplyMultiplePatchesA("", NULL, NULL);
8261     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
8262 
8263     r = MsiApplyMultiplePatchesA(";", NULL, NULL);
8264     if (type == DRIVE_FIXED)
8265         todo_wine ok(r == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %u\n", r);
8266     else
8267         ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
8268 
8269     r = MsiApplyMultiplePatchesA("  ;", NULL, NULL);
8270     if (type == DRIVE_FIXED)
8271         todo_wine ok(r == ERROR_PATCH_PACKAGE_OPEN_FAILED, "Expected ERROR_PATCH_PACKAGE_OPEN_FAILED, got %u\n", r);
8272     else
8273         ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
8274 
8275     r = MsiApplyMultiplePatchesA(";;", NULL, NULL);
8276     if (type == DRIVE_FIXED)
8277         todo_wine ok(r == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %u\n", r);
8278     else
8279         ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
8280 
8281     r = MsiApplyMultiplePatchesA("nosuchpatchpackage;", NULL, NULL);
8282     todo_wine ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
8283 
8284     r = MsiApplyMultiplePatchesA(";nosuchpatchpackage", NULL, NULL);
8285     if (type == DRIVE_FIXED)
8286         todo_wine ok(r == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %u\n", r);
8287     else
8288         ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
8289 
8290     r = MsiApplyMultiplePatchesA("nosuchpatchpackage;nosuchpatchpackage", NULL, NULL);
8291     todo_wine ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
8292 
8293     r = MsiApplyMultiplePatchesA("  nosuchpatchpackage  ;  nosuchpatchpackage  ", NULL, NULL);
8294     todo_wine ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
8295 }
8296 
8297 static void test_MsiApplyPatch(void)
8298 {
8299     UINT r;
8300 
8301     r = MsiApplyPatchA(NULL, NULL, INSTALLTYPE_DEFAULT, NULL);
8302     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
8303 
8304     r = MsiApplyPatchA("", NULL, INSTALLTYPE_DEFAULT, NULL);
8305     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
8306 }
8307 
8308 static void test_costs(void)
8309 {
8310     MSIHANDLE hdb, hpkg;
8311     char package[12], drive[3];
8312     DWORD len;
8313     UINT r;
8314     int cost, temp;
8315 
8316     hdb = create_package_db();
8317     ok( hdb, "failed to create database\n" );
8318 
8319     create_property_table( hdb );
8320     add_property_entry( hdb, "'ProductCode', '{379B1C47-40C1-42FA-A9BB-BEBB6F1B0172}'" );
8321     add_property_entry( hdb, "'MSIFASTINSTALL', '1'" );
8322     add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'" );
8323 
8324     create_media_table( hdb );
8325     add_media_entry( hdb, "'1', '2', 'cabinet', '', '', ''");
8326 
8327     create_file_table( hdb );
8328     add_file_entry( hdb, "'a.txt', 'one', 'a.txt', 2048000000, '', '', 8192, 1" );
8329     add_file_entry( hdb, "'b.txt', 'one', 'b.txt', 2048000000, '', '', 8192, 1" );
8330     add_file_entry( hdb, "'c.txt', 'one', 'c.txt', 2048000000, '', '', 8192, 1" );
8331     add_file_entry( hdb, "'d.txt', 'one', 'd.txt', 4097, '', '', 8192, 1" );
8332     add_file_entry( hdb, "'e.txt', 'one', 'e.txt', 1, '', '', 8192, 1" );
8333 
8334     create_component_table( hdb );
8335     add_component_entry( hdb, "'one', '{B2F86B9D-8447-4BC5-8883-750C45AA31CA}', 'TARGETDIR', 0, '', 'a.txt'" );
8336     add_component_entry( hdb, "'two', '{62A09F6E-0B74-4829-BDB7-CAB66F42CCE8}', 'TARGETDIR', 0, '', ''" );
8337 
8338     create_feature_table( hdb );
8339     add_feature_entry( hdb, "'one', '', '', '', 0, 1, '', 0" );
8340     add_feature_entry( hdb, "'two', '', '', '', 0, 1, '', 0" );
8341 
8342     create_feature_components_table( hdb );
8343     add_feature_components_entry( hdb, "'one', 'one'" );
8344     add_feature_components_entry( hdb, "'two', 'two'" );
8345 
8346     create_install_execute_sequence_table( hdb );
8347     add_install_execute_sequence_entry( hdb, "'CostInitialize', '', '800'" );
8348     add_install_execute_sequence_entry( hdb, "'FileCost', '', '900'" );
8349     add_install_execute_sequence_entry( hdb, "'CostFinalize', '', '1000'" );
8350     add_install_execute_sequence_entry( hdb, "'InstallValidate', '', '1100'" );
8351 
8352     r = MsiDatabaseCommit( hdb );
8353     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8354 
8355     sprintf( package, "#%lu", hdb );
8356     r = MsiOpenPackageA( package, &hpkg );
8357     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
8358     {
8359         skip("Not enough rights to perform tests\n");
8360         goto error;
8361     }
8362     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8363 
8364     r = MsiEnumComponentCostsA( 0, NULL, 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8365     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8366 
8367     r = MsiEnumComponentCostsA( hpkg, NULL, 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8368     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8369 
8370     r = MsiEnumComponentCostsA( hpkg, NULL, 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8371     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8372 
8373     r = MsiEnumComponentCostsA( hpkg, "", 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8374     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8375 
8376     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8377     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8378 
8379     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, NULL, NULL, NULL, NULL );
8380     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8381 
8382     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, NULL, NULL, NULL );
8383     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8384 
8385     len = sizeof(drive);
8386     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, NULL, NULL );
8387     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8388 
8389     len = sizeof(drive);
8390     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, NULL );
8391     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8392 
8393     len = sizeof(drive);
8394     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8395     todo_wine ok( r == ERROR_INVALID_HANDLE_STATE, "Expected ERROR_INVALID_HANDLE_STATE, got %u\n", r );
8396 
8397     len = sizeof(drive);
8398     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, NULL, &len, &cost, &temp );
8399     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8400 
8401     MsiSetInternalUI( INSTALLUILEVEL_NONE, NULL );
8402 
8403     r = MsiDoActionA( hpkg, "CostInitialize" );
8404     ok( r == ERROR_SUCCESS, "CostInitialize failed %u\n", r );
8405 
8406     r = MsiDoActionA( hpkg, "FileCost" );
8407     ok( r == ERROR_SUCCESS, "FileCost failed %u\n", r );
8408 
8409     len = sizeof(drive);
8410     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8411     ok( r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %u\n", r );
8412 
8413     r = MsiDoActionA( hpkg, "CostFinalize" );
8414     ok( r == ERROR_SUCCESS, "CostFinalize failed %u\n", r );
8415 
8416     /* contrary to what msdn says InstallValidate must be called too */
8417     len = sizeof(drive);
8418     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8419     todo_wine ok( r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %u\n", r );
8420 
8421     r = MsiDoActionA( hpkg, "InstallValidate" );
8422     ok( r == ERROR_SUCCESS, "InstallValidate failed %u\n", r );
8423 
8424     len = 0;
8425     r = MsiEnumComponentCostsA( hpkg, "three", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8426     ok( r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %u\n", r );
8427 
8428     len = 0;
8429     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8430     ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %u\n", r );
8431     ok( len == 2, "expected len == 2, got %lu\n", len );
8432 
8433     len = 2;
8434     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8435     ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %u\n", r );
8436     ok( len == 2, "expected len == 2, got %lu\n", len );
8437 
8438     len = 2;
8439     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_UNKNOWN, drive, &len, &cost, &temp );
8440     ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %u\n", r );
8441     ok( len == 2, "expected len == 2, got %lu\n", len );
8442 
8443     /* install state doesn't seem to matter */
8444     len = sizeof(drive);
8445     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_UNKNOWN, drive, &len, &cost, &temp );
8446     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8447 
8448     len = sizeof(drive);
8449     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_ABSENT, drive, &len, &cost, &temp );
8450     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8451 
8452     len = sizeof(drive);
8453     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_SOURCE, drive, &len, &cost, &temp );
8454     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8455 
8456     len = sizeof(drive);
8457     drive[0] = 0;
8458     cost = temp = 0xdead;
8459     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8460     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8461     ok( len == 2, "expected len == 2, got %lu\n", len );
8462     ok( drive[0], "expected a drive\n" );
8463     ok( cost == 12000024, "got %d\n", cost );
8464     ok( !temp, "expected temp == 0, got %d\n", temp );
8465 
8466     len = sizeof(drive);
8467     drive[0] = 0;
8468     cost = temp = 0xdead;
8469     r = MsiEnumComponentCostsA( hpkg, "two", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8470     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8471     ok( len == 2, "expected len == 2, got %lu\n", len );
8472     ok( drive[0], "expected a drive\n" );
8473     ok( !cost, "expected cost == 0, got %d\n", cost );
8474     ok( !temp, "expected temp == 0, got %d\n", temp );
8475 
8476     len = sizeof(drive);
8477     drive[0] = 0;
8478     cost = temp = 0xdead;
8479     r = MsiEnumComponentCostsA( hpkg, "", 0, INSTALLSTATE_UNKNOWN, drive, &len, &cost, &temp );
8480     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8481     ok( len == 2, "expected len == 2, got %lu\n", len );
8482     ok( drive[0], "expected a drive\n" );
8483     ok( !cost, "expected cost == 0, got %d\n", cost );
8484     todo_wine ok( temp && temp != 0xdead, "expected temp > 0, got %d\n", temp );
8485 
8486     /* increased index */
8487     len = sizeof(drive);
8488     r = MsiEnumComponentCostsA( hpkg, "one", 1, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8489     ok( r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %u\n", r );
8490 
8491     len = sizeof(drive);
8492     r = MsiEnumComponentCostsA( hpkg, "", 1, INSTALLSTATE_UNKNOWN, drive, &len, &cost, &temp );
8493     ok( r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %u\n", r );
8494 
8495     /* test MsiGetFeatureCost */
8496     cost = 0xdead;
8497     r = MsiGetFeatureCostA( hpkg, NULL, MSICOSTTREE_SELFONLY, INSTALLSTATE_LOCAL, &cost );
8498     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r);
8499     ok( cost == 0xdead, "got %d\n", cost );
8500 
8501     r = MsiGetFeatureCostA( hpkg, "one", MSICOSTTREE_SELFONLY, INSTALLSTATE_LOCAL, NULL );
8502     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r);
8503 
8504     cost = 0xdead;
8505     r = MsiGetFeatureCostA( hpkg, "one", MSICOSTTREE_SELFONLY, INSTALLSTATE_LOCAL, &cost );
8506     ok( !r, "got %u\n", r);
8507     ok( cost == 12000024, "got %d\n", cost );
8508 
8509     MsiCloseHandle( hpkg );
8510 error:
8511     MsiCloseHandle( hdb );
8512     DeleteFileA( msifile );
8513 }
8514 
8515 static void test_MsiDatabaseCommit(void)
8516 {
8517     UINT r;
8518     MSIHANDLE hdb, hpkg = 0;
8519     char buf[32], package[12];
8520     DWORD sz;
8521 
8522     hdb = create_package_db();
8523     ok( hdb, "failed to create database\n" );
8524 
8525     create_property_table( hdb );
8526 
8527     sprintf( package, "#%lu", hdb );
8528     r = MsiOpenPackageA( package, &hpkg );
8529     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
8530     {
8531         skip("Not enough rights to perform tests\n");
8532         goto error;
8533     }
8534     ok( r == ERROR_SUCCESS, "got %u\n", r );
8535 
8536     r = MsiSetPropertyA( hpkg, "PROP", "value" );
8537     ok( r == ERROR_SUCCESS, "got %u\n", r );
8538 
8539     buf[0] = 0;
8540     sz = sizeof(buf);
8541     r = MsiGetPropertyA( hpkg, "PROP", buf, &sz );
8542     ok( r == ERROR_SUCCESS, "MsiGetPropertyA returned %u\n", r );
8543     ok( !lstrcmpA( buf, "value" ), "got \"%s\"\n", buf );
8544 
8545     r = MsiDatabaseCommit( hdb );
8546     ok( r == ERROR_SUCCESS, "MsiDatabaseCommit returned %u\n", r );
8547 
8548     buf[0] = 0;
8549     sz = sizeof(buf);
8550     r = MsiGetPropertyA( hpkg, "PROP", buf, &sz );
8551     ok( r == ERROR_SUCCESS, "MsiGetPropertyA returned %u\n", r );
8552     ok( !lstrcmpA( buf, "value" ), "got \"%s\"\n", buf );
8553 
8554     MsiCloseHandle( hpkg );
8555 error:
8556     MsiCloseHandle( hdb );
8557     DeleteFileA( msifile );
8558 }
8559 
8560 static int externalui_ran;
8561 
8562 static INT CALLBACK externalui_callback(void *context, UINT message_type, LPCSTR message)
8563 {
8564     externalui_ran = 1;
8565     ok(message_type == INSTALLMESSAGE_USER, "expected INSTALLMESSAGE_USER, got %08x\n", message_type);
8566     return 0;
8567 }
8568 
8569 static int externalui_record_ran;
8570 
8571 static INT CALLBACK externalui_record_callback(void *context, UINT message_type, MSIHANDLE hrecord)
8572 {
8573     INT retval = context ? *((INT *)context) : 0;
8574     UINT r;
8575     externalui_record_ran = 1;
8576     ok(message_type == INSTALLMESSAGE_USER, "expected INSTALLMESSAGE_USER, got %08x\n", message_type);
8577     r = MsiRecordGetFieldCount(hrecord);
8578     ok(r == 1, "expected 1, got %u\n", r);
8579     r = MsiRecordGetInteger(hrecord, 1);
8580     ok(r == 12345, "expected 12345, got %u\n", r);
8581     return retval;
8582 }
8583 
8584 static void test_externalui(void)
8585 {
8586     /* test that external UI handlers work correctly */
8587 
8588     INSTALLUI_HANDLERA prev;
8589     INSTALLUI_HANDLER_RECORD prev_record;
8590     MSIHANDLE hpkg, hrecord;
8591     UINT r;
8592     INT retval = 0;
8593 
8594     prev = MsiSetExternalUIA(externalui_callback, INSTALLLOGMODE_USER, NULL);
8595 
8596     r = package_from_db(create_package_db(), &hpkg);
8597     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
8598     {
8599         skip("Not enough rights to perform tests\n");
8600         DeleteFileA(msifile);
8601         return;
8602     }
8603     ok(r == ERROR_SUCCESS, "Expected a valid package %u\n", r);
8604 
8605     hrecord = MsiCreateRecord(1);
8606     ok(hrecord, "Expected a valid record\n");
8607     r = MsiRecordSetStringA(hrecord, 0, "test message [1]");
8608     ok(r == ERROR_SUCCESS, "MsiSetString failed %u\n", r);
8609     r = MsiRecordSetInteger(hrecord, 1, 12345);
8610     ok(r == ERROR_SUCCESS, "MsiSetInteger failed %u\n", r);
8611 
8612     externalui_ran = 0;
8613     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
8614     ok(r == 0, "expected 0, got %u\n", r);
8615     ok(externalui_ran == 1, "external UI callback did not run\n");
8616 
8617     prev = MsiSetExternalUIA(prev, 0, NULL);
8618     ok(prev == externalui_callback, "wrong callback function %p\n", prev);
8619     r = MsiSetExternalUIRecord(externalui_record_callback, INSTALLLOGMODE_USER, &retval, &prev_record);
8620     ok(r == ERROR_SUCCESS, "MsiSetExternalUIRecord failed %u\n", r);
8621 
8622     externalui_ran = externalui_record_ran = 0;
8623     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
8624     ok(r == 0, "expected 0, got %u\n", r);
8625     ok(externalui_ran == 0, "external UI callback should not have run\n");
8626     ok(externalui_record_ran == 1, "external UI record callback did not run\n");
8627 
8628     MsiSetExternalUIA(externalui_callback, INSTALLLOGMODE_USER, NULL);
8629 
8630     externalui_ran = externalui_record_ran = 0;
8631     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
8632     ok(r == 0, "expected 0, got %u\n", r);
8633     ok(externalui_ran == 1, "external UI callback did not run\n");
8634     ok(externalui_record_ran == 1, "external UI record callback did not run\n");
8635 
8636     retval = 1;
8637     externalui_ran = externalui_record_ran = 0;
8638     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
8639     ok(r == 1, "expected 1, got %u\n", r);
8640     ok(externalui_ran == 0, "external UI callback should not have run\n");
8641     ok(externalui_record_ran == 1, "external UI record callback did not run\n");
8642 
8643     /* filter and context should be kept separately */
8644     r = MsiSetExternalUIRecord(externalui_record_callback, INSTALLLOGMODE_ERROR, &retval, &prev_record);
8645     ok(r == ERROR_SUCCESS, "MsiSetExternalUIRecord failed %u\n", r);
8646 
8647     externalui_ran = externalui_record_ran = 0;
8648     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
8649     ok(r == 0, "expected 0, got %u\n", r);
8650     ok(externalui_ran == 1, "external UI callback did not run\n");
8651     ok(externalui_record_ran == 0, "external UI record callback should not have run\n");
8652 
8653     MsiCloseHandle(hpkg);
8654     DeleteFileA(msifile);
8655 }
8656 
8657 struct externalui_message {
8658     UINT message;
8659     int field_count;
8660     char field[4][100];
8661     int match[4]; /* should we test for a match */
8662     int optional;
8663 };
8664 
8665 static struct externalui_message *sequence;
8666 static int sequence_count, sequence_size;
8667 
8668 static void add_message(const struct externalui_message *msg)
8669 {
8670     if (!sequence)
8671     {
8672         sequence_size = 10;
8673         sequence = malloc(sequence_size * sizeof(*sequence));
8674     }
8675     if (sequence_count == sequence_size)
8676     {
8677         sequence_size *= 2;
8678         sequence = realloc(sequence, sequence_size * sizeof(*sequence));
8679     }
8680 
8681     assert(sequence);
8682     sequence[sequence_count++] = *msg;
8683 }
8684 
8685 static void flush_sequence(void)
8686 {
8687     free(sequence);
8688     sequence = NULL;
8689     sequence_count = sequence_size = 0;
8690 }
8691 
8692 static void ok_sequence_(const struct externalui_message *expected, const char *context, BOOL todo,
8693                          const char *file, int line)
8694 {
8695     static const struct externalui_message end_of_sequence = {0};
8696     const struct externalui_message *actual;
8697     int failcount = 0;
8698     int i;
8699 
8700     add_message(&end_of_sequence);
8701 
8702     actual = sequence;
8703 
8704     while (expected->message && actual->message)
8705     {
8706         if (expected->message == actual->message)
8707         {
8708             if (expected->field_count < actual->field_count)
8709             {
8710                 todo_wine_if (todo)
8711                     ok_(file, line) (FALSE, "%s: in msg 0x%08x expecting field count %d got %d\n",
8712                                      context, expected->message, expected->field_count, actual->field_count);
8713                 failcount++;
8714             }
8715 
8716             for (i = 0; i <= actual->field_count; i++)
8717             {
8718                 if (expected->match[i] && strcmp(expected->field[i], actual->field[i]))
8719                 {
8720                     todo_wine_if (todo)
8721                         ok_(file, line) (FALSE, "%s: in msg 0x%08x field %d: expected \"%s\", got \"%s\"\n",
8722                                          context, expected->message, i, expected->field[i], actual->field[i]);
8723                     failcount++;
8724                 }
8725             }
8726 
8727             expected++;
8728             actual++;
8729         }
8730         else if (expected->optional)
8731         {
8732             expected++;
8733         }
8734         else
8735         {
8736             todo_wine_if (todo)
8737                 ok_(file, line) (FALSE, "%s: the msg 0x%08x was expected, but got msg 0x%08x instead\n",
8738                                  context, expected->message, actual->message);
8739             failcount++;
8740             if (todo)
8741                 goto done;
8742             expected++;
8743             actual++;
8744         }
8745     }
8746 
8747     if (expected->message || actual->message)
8748     {
8749         todo_wine_if (todo)
8750             ok_(file, line) (FALSE, "%s: the msg sequence is not complete: expected %08x - actual %08x\n",
8751                              context, expected->message, actual->message);
8752         failcount++;
8753     }
8754 
8755     if(todo && !failcount) /* succeeded yet marked todo */
8756     {
8757         todo_wine
8758             ok_(file, line)(TRUE, "%s: marked \"todo_wine\" but succeeds\n", context);
8759     }
8760 
8761 done:
8762     flush_sequence();
8763 }
8764 
8765 #define ok_sequence(exp, contx, todo) \
8766         ok_sequence_((exp), (contx), (todo), __FILE__, __LINE__)
8767 
8768 /* don't use PROGRESS, which is timing-dependent,
8769  * or SHOWDIALOG, which due to a bug causes a hang on XP */
8770 static const INSTALLLOGMODE MSITEST_INSTALLLOGMODE =
8771     INSTALLLOGMODE_FATALEXIT |
8772     INSTALLLOGMODE_ERROR |
8773     INSTALLLOGMODE_WARNING |
8774     INSTALLLOGMODE_USER |
8775     INSTALLLOGMODE_INFO |
8776     INSTALLLOGMODE_FILESINUSE |
8777     INSTALLLOGMODE_RESOLVESOURCE |
8778     INSTALLLOGMODE_OUTOFDISKSPACE |
8779     INSTALLLOGMODE_ACTIONSTART |
8780     INSTALLLOGMODE_ACTIONDATA |
8781     INSTALLLOGMODE_COMMONDATA |
8782     INSTALLLOGMODE_INITIALIZE |
8783     INSTALLLOGMODE_TERMINATE |
8784     INSTALLLOGMODE_RMFILESINUSE |
8785     INSTALLLOGMODE_INSTALLSTART |
8786     INSTALLLOGMODE_INSTALLEND;
8787 
8788 static const struct externalui_message empty_sequence[] = {
8789     {0}
8790 };
8791 
8792 static const struct externalui_message openpackage_nonexistent_sequence[] = {
8793     {INSTALLMESSAGE_INITIALIZE, -1},
8794     {INSTALLMESSAGE_TERMINATE, -1},
8795     {0}
8796 };
8797 
8798 static const struct externalui_message openpackage_sequence[] = {
8799     {INSTALLMESSAGE_INITIALIZE, -1},
8800     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
8801     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
8802     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
8803     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
8804     {0}
8805 };
8806 
8807 static const struct externalui_message processmessage_info_sequence[] = {
8808     {INSTALLMESSAGE_INFO, 3, {"zero", "one", "two", "three"}, {1, 1, 1, 1}},
8809     {0}
8810 };
8811 
8812 static const struct externalui_message processmessage_actionstart_sequence[] = {
8813     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "name", "description", "template"}, {0, 1, 1, 1}},
8814     {0}
8815 };
8816 
8817 static const struct externalui_message processmessage_actiondata_sequence[] = {
8818     {INSTALLMESSAGE_ACTIONDATA, 3, {"{{name: }}template", "cherry", "banana", "guava"}, {1, 1, 1, 1}},
8819     {0}
8820 };
8821 
8822 static const struct externalui_message processmessage_error_sequence[] = {
8823     {INSTALLMESSAGE_USER, 3, {"", "1311", "banana", "guava"}, {0, 1, 1, 1}},
8824     {0}
8825 };
8826 
8827 static const struct externalui_message processmessage_internal_error_sequence[] = {
8828     {INSTALLMESSAGE_INFO, 3, {"DEBUG: Error [1]:  Action not found: [2]", "2726", "banana", "guava"}, {1, 1, 1, 1}},
8829     {INSTALLMESSAGE_USER, 3, {"internal error", "2726", "banana", "guava"}, {1, 1, 1, 1}},
8830     {0}
8831 };
8832 
8833 static const struct externalui_message processmessage_error_format_sequence[] = {
8834     {INSTALLMESSAGE_USER, 3, {"", "2726", "banana", "guava"}, {0, 1, 1, 1}},
8835     {0}
8836 };
8837 
8838 static const struct externalui_message doaction_costinitialize_sequence[] = {
8839     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostInitialize", "cost description", "cost template"}, {0, 1, 1, 1}},
8840     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", ""}, {0, 1, 1}},
8841     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", "1"}, {0, 1, 1}},
8842     {0}
8843 };
8844 
8845 static const struct externalui_message doaction_custom_sequence[] = {
8846     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "description", "template"}, {0, 1, 1, 1}},
8847     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
8848     {INSTALLMESSAGE_INFO, 2, {"", "custom", "0"}, {0, 1, 1}},
8849     {0}
8850 };
8851 
8852 static const struct externalui_message doaction_custom_fullui_sequence[] = {
8853     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
8854     {INSTALLMESSAGE_INFO, 2, {"", "custom", ""}, {0, 1, 1}},
8855     {INSTALLMESSAGE_SHOWDIALOG, 0, {"custom"}, {1}},
8856     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
8857     {0}
8858 };
8859 
8860 static const struct externalui_message doaction_custom_cancel_sequence[] = {
8861     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
8862     {0}
8863 };
8864 
8865 static const struct externalui_message doaction_dialog_nonexistent_sequence[] = {
8866     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
8867     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
8868     {INSTALLMESSAGE_SHOWDIALOG, 0, {"custom"}, {1}},
8869     {INSTALLMESSAGE_INFO, 2, {"DEBUG: Error [1]:  Action not found: [2]", "2726", "custom"}, {1, 1, 1}},
8870     {INSTALLMESSAGE_INFO, 2, {"", "2726", "custom"}, {0, 1, 1}},
8871     {INSTALLMESSAGE_INFO, 2, {"", "custom", "0"}, {0, 1, 1}},
8872     {0}
8873 };
8874 
8875 static const struct externalui_message doaction_dialog_sequence[] = {
8876     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "dialog", "", ""}, {0, 1, 1, 1}},
8877     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "0"}, {0, 1, 1}},
8878     {INSTALLMESSAGE_SHOWDIALOG, 0, {"dialog"}, {1}},
8879     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "dialog", "Dialog created"}, {0, 1, 1}},
8880     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "1"}, {0, 1, 1}},
8881     {0}
8882 };
8883 
8884 static const struct externalui_message doaction_dialog_error_sequence[] = {
8885     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "error", "", ""}, {0, 1, 1, 1}},
8886     {INSTALLMESSAGE_INFO, 2, {"", "error", "1"}, {0, 1, 1}},
8887     {INSTALLMESSAGE_SHOWDIALOG, 0, {"error"}, {1}},
8888     {0}
8889 };
8890 
8891 static const struct externalui_message doaction_dialog_3_sequence[] = {
8892     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "dialog", "", ""}, {0, 1, 1, 1}},
8893     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "0"}, {0, 1, 1}},
8894     {INSTALLMESSAGE_SHOWDIALOG, 0, {"dialog"}, {1}},
8895     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "3"}, {0, 1, 1}},
8896     {0}
8897 };
8898 
8899 static const struct externalui_message doaction_dialog_12345_sequence[] = {
8900     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "dialog", "", ""}, {0, 1, 1, 1}},
8901     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "3"}, {0, 1, 1}},
8902     {INSTALLMESSAGE_SHOWDIALOG, 0, {"dialog"}, {1}},
8903     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "12345"}, {0, 1, 1}},
8904     {0}
8905 };
8906 
8907 static const struct externalui_message closehandle_sequence[] = {
8908     {INSTALLMESSAGE_TERMINATE, -1},
8909     {0}
8910 };
8911 
8912 static INT CALLBACK externalui_message_string_callback(void *context, UINT message, LPCSTR string)
8913 {
8914     INT retval = context ? *((INT *)context) : 0;
8915     struct externalui_message msg;
8916 
8917     msg.message = message;
8918     msg.field_count = 0;
8919     strcpy(msg.field[0], string);
8920     add_message(&msg);
8921 
8922     return retval;
8923 }
8924 
8925 static INT CALLBACK externalui_message_callback(void *context, UINT message, MSIHANDLE hrecord)
8926 {
8927     INT retval = context ? *((INT *)context) : 0;
8928     struct externalui_message msg;
8929     char buffer[256];
8930     DWORD length;
8931     UINT r;
8932     int i;
8933 
8934     msg.message = message;
8935     if (message == INSTALLMESSAGE_TERMINATE)
8936     {
8937         /* trying to access the record seems to hang on some versions of Windows */
8938         msg.field_count = -1;
8939         add_message(&msg);
8940         return 1;
8941     }
8942     msg.field_count = MsiRecordGetFieldCount(hrecord);
8943     for (i = 0; i <= msg.field_count; i++)
8944     {
8945         length = sizeof(buffer);
8946         r = MsiRecordGetStringA(hrecord, i, buffer, &length);
8947         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
8948         memcpy(msg.field[i], buffer, min(100, length+1));
8949     }
8950 
8951     /* top-level actions dump a list of all set properties; skip them since they're inconsistent */
8952     if (message == (INSTALLMESSAGE_INFO|MB_ICONHAND) && msg.field_count > 0 && !strncmp(msg.field[0], "Property", 8))
8953         return retval;
8954 
8955     add_message(&msg);
8956 
8957     return retval;
8958 }
8959 
8960 static void test_externalui_message(void)
8961 {
8962     /* test that events trigger the correct sequence of messages */
8963 
8964     INSTALLUI_HANDLER_RECORD prev;
8965     MSIHANDLE hdb, hpkg, hrecord;
8966     INT retval = 1;
8967     UINT r;
8968 
8969     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
8970 
8971     MsiSetExternalUIA(externalui_message_string_callback, INSTALLLOGMODE_SHOWDIALOG, &retval);
8972     r = MsiSetExternalUIRecord(externalui_message_callback, MSITEST_INSTALLLOGMODE, &retval, &prev);
8973 
8974     flush_sequence();
8975 
8976     CoInitialize(NULL);
8977 
8978     hdb = create_package_db();
8979     ok(hdb, "failed to create database\n");
8980 
8981     create_file_data("forcecodepage.idt", "\r\n\r\n1252\t_ForceCodepage\r\n", sizeof("\r\n\r\n1252\t_ForceCodepage\r\n") - 1);
8982     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
8983     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8984 
8985     r = run_query(hdb, 0, "CREATE TABLE `Error` (`Error` SHORT NOT NULL, `Message` CHAR(0) PRIMARY KEY `Error`)");
8986     ok(r == ERROR_SUCCESS, "Failed to create Error table: %u\n", r);
8987     r = run_query(hdb, 0, "INSERT INTO `Error` (`Error`, `Message`) VALUES (5, 'internal error')");
8988     ok(r == ERROR_SUCCESS, "Failed to insert into Error table: %u\n", r);
8989 
8990     create_actiontext_table(hdb);
8991     add_actiontext_entry(hdb, "'custom', 'description', 'template'");
8992     add_actiontext_entry(hdb, "'CostInitialize', 'cost description', 'cost template'");
8993 
8994     r = MsiOpenPackageA(NULL, &hpkg);
8995     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8996     ok_sequence(empty_sequence, "MsiOpenPackage with NULL db", FALSE);
8997 
8998     r = MsiOpenPackageA("nonexistent", &hpkg);
8999     ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
9000     ok_sequence(openpackage_nonexistent_sequence, "MsiOpenPackage with nonexistent db", FALSE);
9001 
9002     r = package_from_db(hdb, &hpkg);
9003     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
9004     {
9005         skip("Not enough rights to perform tests\n");
9006         DeleteFileA(msifile);
9007         return;
9008     }
9009     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
9010     ok_sequence(openpackage_sequence, "MsiOpenPackage with valid db", FALSE);
9011 
9012     /* Test MsiProcessMessage */
9013     hrecord = MsiCreateRecord(3);
9014     ok(hrecord, "failed to create record\n");
9015 
9016     MsiRecordSetStringA(hrecord, 0, "zero");
9017     MsiRecordSetStringA(hrecord, 1, "one");
9018     MsiRecordSetStringA(hrecord, 2, "two");
9019     MsiRecordSetStringA(hrecord, 3, "three");
9020     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_INFO, hrecord);
9021     ok(r == 1, "Expected 1, got %d\n", r);
9022     ok_sequence(processmessage_info_sequence, "MsiProcessMessage(INSTALLMESSAGE_INFO)", FALSE);
9023 
9024     MsiRecordSetStringA(hrecord, 1, "name");
9025     MsiRecordSetStringA(hrecord, 2, "description");
9026     MsiRecordSetStringA(hrecord, 3, "template");
9027     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_ACTIONSTART, hrecord);
9028     ok(r == 1, "Expected 1, got %d\n", r);
9029     ok_sequence(processmessage_actionstart_sequence, "MsiProcessMessage(INSTALLMESSAGE_ACTIONSTART)", FALSE);
9030 
9031     MsiRecordSetStringA(hrecord, 0, "apple");
9032     MsiRecordSetStringA(hrecord, 1, "cherry");
9033     MsiRecordSetStringA(hrecord, 2, "banana");
9034     MsiRecordSetStringA(hrecord, 3, "guava");
9035     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_ACTIONDATA, hrecord);
9036     ok(r == 1, "Expected 1, got %d\n", r);
9037     ok_sequence(processmessage_actiondata_sequence, "MsiProcessMessage(INSTALLMESSAGE_ACTIONDATA)", FALSE);
9038 
9039     /* non-internal error */
9040     MsiRecordSetStringA(hrecord, 0, NULL);
9041     MsiRecordSetInteger(hrecord, 1, 1311);
9042     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
9043     ok(r == 1, "Expected 1, got %d\n", r);
9044     ok_sequence(processmessage_error_sequence, "MsiProcessMessage non-internal error", FALSE);
9045 
9046     /* internal error */
9047     MsiRecordSetStringA(hrecord, 0, NULL);
9048     MsiRecordSetInteger(hrecord, 1, 2726);
9049     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
9050     ok(r == 0, "Expected 0, got %d\n", r);
9051     ok_sequence(processmessage_internal_error_sequence, "MsiProcessMessage internal error", FALSE);
9052 
9053     /* with format field */
9054     MsiRecordSetStringA(hrecord, 0, "starfruit");
9055     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
9056     ok(r == 1, "Expected 1, got %d\n", r);
9057     ok_sequence(processmessage_error_format_sequence, "MsiProcessMessage error", FALSE);
9058 
9059     /* Test a standard action */
9060     r = MsiDoActionA(hpkg, "CostInitialize");
9061     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9062     ok_sequence(doaction_costinitialize_sequence, "MsiDoAction(\"CostInitialize\")", FALSE);
9063 
9064     /* Test a custom action */
9065     r = MsiDoActionA(hpkg, "custom");
9066     ok(r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %d\n", r);
9067     ok_sequence(doaction_custom_sequence, "MsiDoAction(\"custom\")", FALSE);
9068 
9069     /* close the package */
9070     MsiCloseHandle(hpkg);
9071     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
9072 
9073     /* Test dialogs */
9074     hdb = create_package_db();
9075     ok(hdb, "failed to create database\n");
9076 
9077     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
9078     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9079 
9080     create_dialog_table(hdb);
9081     add_dialog_entry(hdb, "'dialog', 50, 50, 100, 100, 0, 'dummy'");
9082 
9083     create_control_table(hdb);
9084     add_control_entry(hdb, "'dialog', 'dummy', 'Text', 5, 5, 5, 5, 3, 'dummy'");
9085 
9086     r = package_from_db(hdb, &hpkg);
9087     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
9088     ok_sequence(openpackage_sequence, "MsiOpenPackage with valid db", FALSE);
9089 
9090     /* Test a custom action */
9091     r = MsiDoActionA(hpkg, "custom");
9092     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9093     ok_sequence(doaction_custom_fullui_sequence, "MsiDoAction(\"custom\")", FALSE);
9094 
9095     retval = 2;
9096     r = MsiDoActionA(hpkg, "custom");
9097     ok(r == ERROR_INSTALL_USEREXIT, "Expected ERROR_INSTALL_USEREXIT, got %d\n", r);
9098     ok_sequence(doaction_custom_cancel_sequence, "MsiDoAction(\"custom\")", FALSE);
9099 
9100     retval = 0;
9101     r = MsiDoActionA(hpkg, "custom");
9102     ok(r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %d\n", r);
9103     ok_sequence(doaction_dialog_nonexistent_sequence, "MsiDoAction(\"custom\")", FALSE);
9104 
9105     r = MsiDoActionA(hpkg, "dialog");
9106     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9107     ok_sequence(doaction_dialog_sequence, "MsiDoAction(\"dialog\")", FALSE);
9108 
9109     retval = -1;
9110     r = MsiDoActionA(hpkg, "error");
9111     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9112     ok_sequence(doaction_dialog_error_sequence, "MsiDoAction(\"error\")", FALSE);
9113 
9114     r = MsiDoActionA(hpkg, "error");
9115     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9116     ok_sequence(doaction_dialog_error_sequence, "MsiDoAction(\"error\")", FALSE);
9117 
9118     retval = -2;
9119     r = MsiDoActionA(hpkg, "custom");
9120     ok(r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %d\n", r);
9121     ok_sequence(doaction_dialog_nonexistent_sequence, "MsiDoAction(\"custom\")", FALSE);
9122 
9123     retval = 3;
9124     r = MsiDoActionA(hpkg, "dialog");
9125     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %d\n", r);
9126     ok_sequence(doaction_dialog_3_sequence, "MsiDoAction(\"dialog\")", FALSE);
9127 
9128     retval = 12345;
9129     r = MsiDoActionA(hpkg, "dialog");
9130     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_INSTALL_FAILURE, got %d\n", r);
9131     ok_sequence(doaction_dialog_12345_sequence, "MsiDoAction(\"dialog\")", FALSE);
9132 
9133     MsiCloseHandle(hpkg);
9134     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
9135 
9136     MsiCloseHandle(hrecord);
9137     CoUninitialize();
9138     DeleteFileA(msifile);
9139     DeleteFileA("forcecodepage.idt");
9140 }
9141 
9142 static const struct externalui_message controlevent_spawn_sequence[] = {
9143     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "spawn", "", ""}, {0, 1, 1, 1}},
9144     {INSTALLMESSAGE_INFO, 2, {"", "spawn", ""}, {0, 1, 1}},
9145     {INSTALLMESSAGE_SHOWDIALOG, 0, {"spawn"}, {1}},
9146     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "spawn", "Dialog created"}, {0, 1, 1}},
9147 
9148     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
9149     {INSTALLMESSAGE_INFO, 2, {"", "custom", ""}, {0, 1, 1}},
9150     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
9151 
9152     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "child1", "Dialog created"}, {0, 1, 1}},
9153 
9154     {INSTALLMESSAGE_INFO, 2, {"", "spawn", "2"}, {0, 1, 1}},
9155     {0}
9156 };
9157 
9158 static const struct externalui_message controlevent_spawn2_sequence[] = {
9159     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "spawn2", "", ""}, {0, 1, 1, 1}},
9160     {INSTALLMESSAGE_INFO, 2, {"", "spawn2", "2"}, {0, 1, 1}},
9161     {INSTALLMESSAGE_SHOWDIALOG, 0, {"spawn2"}, {1}},
9162     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "spawn2", "Dialog created"}, {0, 1, 1}},
9163 
9164     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
9165     {INSTALLMESSAGE_INFO, 2, {"", "custom", "2"}, {0, 1, 1}},
9166     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
9167 
9168     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "child2", "Dialog created"}, {0, 1, 1}},
9169 
9170     {INSTALLMESSAGE_INFO, 2, {"", "spawn2", "2"}, {0, 1, 1}},
9171     {0}
9172 };
9173 
9174 static void test_controlevent(void)
9175 {
9176     INSTALLUI_HANDLER_RECORD prev;
9177     MSIHANDLE hdb, hpkg;
9178     UINT r;
9179 
9180     if (!winetest_interactive)
9181     {
9182         skip("interactive ControlEvent tests\n");
9183         return;
9184     }
9185 
9186     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
9187 
9188     MsiSetExternalUIA(externalui_message_string_callback, INSTALLLOGMODE_SHOWDIALOG, NULL);
9189     r = MsiSetExternalUIRecord(externalui_message_callback, MSITEST_INSTALLLOGMODE, NULL, &prev);
9190 
9191     flush_sequence();
9192 
9193     CoInitialize(NULL);
9194 
9195     hdb = create_package_db();
9196     ok(hdb, "failed to create database\n");
9197 
9198     create_file_data("forcecodepage.idt", "\r\n\r\n1252\t_ForceCodepage\r\n", sizeof("\r\n\r\n1252\t_ForceCodepage\r\n") - 1);
9199     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
9200     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9201 
9202     create_dialog_table(hdb);
9203     add_dialog_entry(hdb, "'spawn', 50, 50, 100, 100, 3, 'button'");
9204     add_dialog_entry(hdb, "'spawn2', 50, 50, 100, 100, 3, 'button'");
9205     add_dialog_entry(hdb, "'child1', 50, 50, 80, 40, 3, 'exit'");
9206     add_dialog_entry(hdb, "'child2', 50, 50, 80, 40, 3, 'exit'");
9207 
9208     create_control_table(hdb);
9209     add_control_entry(hdb, "'spawn', 'button', 'PushButton', 10, 10, 66, 17, 3, 'Click me'");
9210     add_control_entry(hdb, "'spawn2', 'button', 'PushButton', 10, 10, 66, 17, 3, 'Click me'");
9211     add_control_entry(hdb, "'child1', 'exit', 'PushButton', 10, 10, 66, 17, 3, 'Click me'");
9212     add_control_entry(hdb, "'child2', 'exit', 'PushButton', 10, 10, 66, 17, 3, 'Click me'");
9213 
9214     create_controlevent_table(hdb);
9215     add_controlevent_entry(hdb, "'child1', 'exit', 'EndDialog', 'Exit', 1, 1");
9216     add_controlevent_entry(hdb, "'child2', 'exit', 'EndDialog', 'Exit', 1, 1");
9217 
9218     create_custom_action_table(hdb);
9219     add_custom_action_entry(hdb, "'custom', 51, 'dummy', 'dummy value'");
9220 
9221     /* SpawnDialog and EndDialog should trigger after all other events */
9222     add_controlevent_entry(hdb, "'spawn', 'button', 'SpawnDialog', 'child1', 1, 1");
9223     add_controlevent_entry(hdb, "'spawn', 'button', 'DoAction', 'custom', 1, 2");
9224 
9225     /* Multiple dialog events cause only the last one to be triggered */
9226     add_controlevent_entry(hdb, "'spawn2', 'button', 'SpawnDialog', 'child1', 1, 1");
9227     add_controlevent_entry(hdb, "'spawn2', 'button', 'SpawnDialog', 'child2', 1, 2");
9228     add_controlevent_entry(hdb, "'spawn2', 'button', 'DoAction', 'custom', 1, 3");
9229 
9230     r = package_from_db(hdb, &hpkg);
9231     ok(r == ERROR_SUCCESS, "failed to create package: %u\n", r);
9232     ok_sequence(openpackage_sequence, "MsiOpenPackage()", FALSE);
9233 
9234     r = MsiDoActionA(hpkg, "spawn");
9235     ok(r == ERROR_INSTALL_USEREXIT, "expected ERROR_INSTALL_USEREXIT, got %u\n", r);
9236     ok_sequence(controlevent_spawn_sequence, "control event: spawn", FALSE);
9237 
9238     r = MsiDoActionA(hpkg, "spawn2");
9239     ok(r == ERROR_INSTALL_USEREXIT, "expected ERROR_INSTALL_USEREXIT, got %u\n", r);
9240     ok_sequence(controlevent_spawn2_sequence, "control event: spawn2", FALSE);
9241 
9242     MsiCloseHandle(hpkg);
9243     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
9244 
9245     CoUninitialize();
9246     DeleteFileA(msifile);
9247     DeleteFileA("forcecodepage.idt");
9248 }
9249 
9250 static const struct externalui_message toplevel_install_sequence[] = {
9251     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "INSTALL", "", ""}, {0, 1, 1, 1}},
9252     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", ""}, {0, 1, 1}},
9253 
9254     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9255     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9256     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
9257     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9258     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9259 
9260     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "INSTALL", "", ""}, {0, 1, 1, 1}},
9261     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", ""}, {0, 1, 1}},
9262     {INSTALLMESSAGE_INSTALLSTART, 2, {"", "", "{7262AC98-EEBD-4364-8CE3-D654F6A425B9}"}, {1, 1, 1}, 1},
9263 
9264     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostInitialize", "", ""}, {0, 1, 0, 1}},
9265     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", ""}, {0, 1, 1}},
9266     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", "1"}, {0, 1, 1}},
9267 
9268     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "FileCost", "", ""}, {0, 1, 0, 1}},
9269     {INSTALLMESSAGE_INFO, 2, {"", "FileCost", "1"}, {0, 1, 1}},
9270     {INSTALLMESSAGE_INFO, 2, {"", "FileCost", "1"}, {0, 1, 1}},
9271 
9272     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostFinalize", "", ""}, {0, 1, 0, 1}},
9273     {INSTALLMESSAGE_INFO, 2, {"", "CostFinalize", "1"}, {0, 1, 1}},
9274     {INSTALLMESSAGE_INFO, 2, {"", "CostFinalize", "1"}, {0, 1, 1}},
9275 
9276     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", "1"}, {0, 1, 1}},
9277     {INSTALLMESSAGE_INSTALLEND, 3, {"", "", "{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "1"}, {1, 1, 1, 1}, 1},
9278 
9279     /* property dump */
9280 
9281     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "0"}, {0, 1, 1}, 1},
9282     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "1"}, {0, 1, 1}, 1},
9283     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", "1"}, {0, 1, 1}},
9284     {0}
9285 };
9286 
9287 static const struct externalui_message toplevel_install_ui_sequence[] = {
9288     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "INSTALL", "", ""}, {0, 1, 1, 1}},
9289     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", ""}, {0, 1, 1}},
9290 
9291     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "AppSearch", "", ""}, {0, 1, 0, 0}},
9292     {INSTALLMESSAGE_INFO, 2, {"", "AppSearch", ""}, {0, 1, 1}},
9293     {INSTALLMESSAGE_INFO, 2, {"", "AppSearch", "0"}, {0, 1, 1}},
9294 
9295     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", "1"}, {0, 1, 1}},
9296     {0}
9297 };
9298 
9299 static const struct externalui_message toplevel_executeaction_install_sequence[] = {
9300     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "ExecuteAction", "", ""}, {0, 1, 1, 1}},
9301     {INSTALLMESSAGE_INFO, 2, {"", "ExecuteAction", "1"}, {0, 1, 1}},
9302 
9303     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9304     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9305     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9306     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9307 
9308     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "INSTALL", "", ""}, {0, 1, 1, 1}},
9309     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", ""}, {0, 1, 1}},
9310     {INSTALLMESSAGE_INSTALLSTART, 2, {"", "", "{7262AC98-EEBD-4364-8CE3-D654F6A425B9}"}, {1, 1, 1}, 1},
9311 
9312     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostInitialize", "", ""}, {0, 1, 0, 1}},
9313     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize"}, {0, 1}},
9314     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", "1"}, {0, 1, 1}},
9315 
9316     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "FileCost", "", ""}, {0, 1, 0, 1}},
9317     {INSTALLMESSAGE_INFO, 2, {"", "FileCost", "1"}, {0, 1, 1}},
9318     {INSTALLMESSAGE_INFO, 2, {"", "FileCost", "1"}, {0, 1, 1}},
9319 
9320     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostFinalize", "", ""}, {0, 1, 0, 1}},
9321     {INSTALLMESSAGE_INFO, 2, {"", "CostFinalize", "1"}, {0, 1, 1}},
9322     {INSTALLMESSAGE_INFO, 2, {"", "CostFinalize", "1"}, {0, 1, 1}},
9323 
9324     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", "1"}, {0, 1, 1}},
9325     {INSTALLMESSAGE_INSTALLEND, 3, {"", "", "{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "1"}, {1, 1, 1, 1}, 1},
9326 
9327     /* property dump */
9328 
9329     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "0"}, {0, 1, 1}, 1},
9330     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "1"}, {0, 1, 1}, 1},
9331     {INSTALLMESSAGE_INFO, 2, {"", "ExecuteAction", "1"}, {0, 1, 1}},
9332     {0}
9333 };
9334 
9335 static const struct externalui_message toplevel_executeaction_costinitialize_sequence[] = {
9336     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "ExecuteAction", "", ""}, {0, 1, 1, 1}},
9337     {INSTALLMESSAGE_INFO, 2, {"", "ExecuteAction", "1"}, {0, 1, 1}},
9338 
9339     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9340     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9341     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9342     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9343 
9344     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostInitialize", "", ""}, {0, 1, 0, 1}},
9345     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", ""}, {0, 1}},
9346     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", "1"}, {0, 1, 1}},
9347 
9348     /* property dump */
9349 
9350     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "0"}, {0, 1, 1}, 1},
9351     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "1"}, {0, 1, 1}, 1},
9352     {INSTALLMESSAGE_INFO, 2, {"", "ExecuteAction", "1"}, {0, 1, 1}},
9353     {0}
9354 };
9355 
9356 static const struct externalui_message toplevel_msiinstallproduct_sequence[] = {
9357     {INSTALLMESSAGE_INITIALIZE, -1},
9358 
9359     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9360     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9361     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
9362     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9363     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9364 
9365     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "INSTALL", "", ""}, {0, 1, 1, 1}},
9366     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", ""}, {0, 1, 1}},
9367 
9368     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "AppSearch", "", ""}, {0, 1, 0, 0}},
9369     {INSTALLMESSAGE_INFO, 2, {"", "AppSearch", ""}, {0, 1, 1}},
9370     {INSTALLMESSAGE_INFO, 2, {"", "AppSearch", "0"}, {0, 1, 1}},
9371 
9372     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", "1"}, {0, 1, 1}},
9373 
9374     /* property dump */
9375 
9376     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
9377     {INSTALLMESSAGE_TERMINATE, -1},
9378     {0}
9379 };
9380 
9381 static const struct externalui_message toplevel_msiinstallproduct_custom_sequence[] = {
9382     {INSTALLMESSAGE_INITIALIZE, -1},
9383 
9384     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9385     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9386     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
9387     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9388     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9389 
9390     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CUSTOM", "", ""}, {0, 1, 1, 1}},
9391     {INSTALLMESSAGE_INFO, 2, {"", "CUSTOM", ""}, {0, 1, 1}},
9392     {INSTALLMESSAGE_INFO, 2, {"", "CUSTOM", "0"}, {0, 1, 1}},
9393 
9394     /* property dump */
9395 
9396     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
9397     {INSTALLMESSAGE_TERMINATE, -1},
9398     {0}
9399 };
9400 
9401 /* tests involving top-level actions: INSTALL, ExecuteAction */
9402 static void test_top_level_action(void)
9403 {
9404     INSTALLUI_HANDLER_RECORD prev;
9405     MSIHANDLE hdb, hpkg;
9406     UINT r;
9407     char msifile_absolute[MAX_PATH];
9408 
9409     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
9410 
9411     MsiSetExternalUIA(externalui_message_string_callback, INSTALLLOGMODE_SHOWDIALOG, NULL);
9412     r = MsiSetExternalUIRecord(externalui_message_callback, MSITEST_INSTALLLOGMODE, NULL, &prev);
9413 
9414     flush_sequence();
9415 
9416     CoInitialize(NULL);
9417 
9418     hdb = create_package_db();
9419     ok(hdb, "failed to create database\n");
9420 
9421     create_file_data("forcecodepage.idt", "\r\n\r\n1252\t_ForceCodepage\r\n", sizeof("\r\n\r\n1252\t_ForceCodepage\r\n") -1 );
9422     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
9423     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9424 
9425     create_property_table(hdb);
9426     add_property_entry(hdb, "'ProductCode', '{7262AC98-EEBD-4364-8CE3-D654F6A425B9}'");
9427 
9428     create_install_execute_sequence_table(hdb);
9429     add_install_execute_sequence_entry(hdb, "'CostInitialize', '', 1");
9430     add_install_execute_sequence_entry(hdb, "'FileCost', '', 2");
9431     add_install_execute_sequence_entry(hdb, "'CostFinalize', '', 3");
9432 
9433     create_install_ui_sequence_table(hdb);
9434     add_install_ui_sequence_entry(hdb, "'AppSearch', '', 1");
9435 
9436     MsiDatabaseCommit(hdb);
9437 
9438     /* for some reason we have to open the package from file using an absolute path */
9439     MsiCloseHandle(hdb);
9440     GetFullPathNameA(msifile, MAX_PATH, msifile_absolute, NULL);
9441     r = MsiOpenPackageA(msifile_absolute, &hpkg);
9442     ok(r == ERROR_SUCCESS, "failed to create package: %u\n", r);
9443     ok_sequence(openpackage_sequence, "MsiOpenPackage()", FALSE);
9444 
9445     /* test INSTALL */
9446     r = MsiDoActionA(hpkg, "INSTALL");
9447     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
9448     ok_sequence(toplevel_install_sequence, "INSTALL (no UI)", FALSE);
9449 
9450     /* test INSTALL with reduced+ UI */
9451     /* for some reason we need to re-open the package to change the internal UI */
9452     MsiCloseHandle(hpkg);
9453     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
9454     MsiSetInternalUI(INSTALLUILEVEL_REDUCED, NULL);
9455     r = MsiOpenPackageA(msifile_absolute, &hpkg);
9456     ok(r == ERROR_SUCCESS, "failed to create package: %u\n", r);
9457     ok_sequence(openpackage_sequence, "MsiOpenPackage()", FALSE);
9458 
9459     r = MsiDoActionA(hpkg, "INSTALL");
9460     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
9461     ok_sequence(toplevel_install_ui_sequence, "INSTALL (reduced+ UI)", TRUE);
9462 
9463     /* test ExecuteAction with EXECUTEACTION property unset */
9464     MsiSetPropertyA(hpkg, "EXECUTEACTION", NULL);
9465     r = MsiDoActionA(hpkg, "ExecuteAction");
9466     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
9467     ok_sequence(toplevel_executeaction_install_sequence, "ExecuteAction: INSTALL", FALSE);
9468 
9469     /* test ExecuteAction with EXECUTEACTION property set */
9470     MsiSetPropertyA(hpkg, "EXECUTEACTION", "CostInitialize");
9471     r = MsiDoActionA(hpkg, "ExecuteAction");
9472     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
9473     ok_sequence(toplevel_executeaction_costinitialize_sequence, "ExecuteAction: CostInitialize", FALSE);
9474 
9475     MsiCloseHandle(hpkg);
9476     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
9477 
9478     /* test MsiInstallProduct() */
9479     r = MsiInstallProductA(msifile_absolute, NULL);
9480     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
9481     ok_sequence(toplevel_msiinstallproduct_sequence, "MsiInstallProduct()", TRUE);
9482 
9483     r = MsiInstallProductA(msifile_absolute, "ACTION=custom");
9484     todo_wine
9485     ok(r == ERROR_INSTALL_FAILURE, "expected ERROR_INSTALL_FAILURE, got %u\n", r);
9486     ok_sequence(toplevel_msiinstallproduct_custom_sequence, "MsiInstallProduct(ACTION=custom)", TRUE);
9487 
9488     CoUninitialize();
9489     DeleteFileA(msifile);
9490     DeleteFileA("forcecodepage.idt");
9491 }
9492 
9493 START_TEST(package)
9494 {
9495     char temp_path[MAX_PATH], prev_path[MAX_PATH];
9496     DWORD len;
9497 
9498     if (!is_process_elevated()) restart_as_admin_elevated();
9499 
9500     IsWow64Process(GetCurrentProcess(), &is_wow64);
9501 
9502     GetCurrentDirectoryA(MAX_PATH, prev_path);
9503     GetTempPathA(MAX_PATH, temp_path);
9504     SetCurrentDirectoryA(temp_path);
9505 
9506     lstrcpyA(CURR_DIR, temp_path);
9507     len = lstrlenA(CURR_DIR);
9508 
9509     if (len && (CURR_DIR[len - 1] == '\\'))
9510         CURR_DIR[len - 1] = 0;
9511 
9512     test_createpackage();
9513     test_doaction();
9514     test_gettargetpath_bad();
9515     test_settargetpath();
9516     test_props();
9517     test_property_table();
9518     test_condition();
9519     test_msipackage();
9520     test_formatrecord2();
9521     test_formatrecord_tables();
9522     test_states();
9523     test_removefiles();
9524     test_appsearch();
9525     test_appsearch_complocator();
9526     test_appsearch_reglocator();
9527     test_appsearch_inilocator();
9528     test_appsearch_drlocator();
9529     test_featureparents();
9530     test_installprops();
9531     test_launchconditions();
9532     test_ccpsearch();
9533     test_complocator();
9534     test_MsiGetSourcePath();
9535     test_shortlongsource();
9536     test_sourcedir();
9537     test_access();
9538     test_emptypackage();
9539     test_MsiGetProductProperty();
9540     test_MsiSetProperty();
9541     test_MsiApplyMultiplePatches();
9542     test_MsiApplyPatch();
9543     test_costs();
9544     test_MsiDatabaseCommit();
9545     test_externalui();
9546     test_externalui_message();
9547     test_controlevent();
9548     test_top_level_action();
9549 
9550     SetCurrentDirectoryA(prev_path);
9551 }
9552