tests: Moved some compatibility defines to wine/test.h.
[wine] / dlls / msi / tests / package.c
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 <stdio.h>
25 #include <windows.h>
26 #include <msi.h>
27 #include <msiquery.h>
28
29 #include "wine/test.h"
30
31 static const char msifile[] = "winetest.msi";
32
33 static UINT run_query( MSIHANDLE hdb, const char *query )
34 {
35     MSIHANDLE hview = 0;
36     UINT r;
37
38     r = MsiDatabaseOpenView(hdb, query, &hview);
39     if( r != ERROR_SUCCESS )
40         return r;
41
42     r = MsiViewExecute(hview, 0);
43     if( r == ERROR_SUCCESS )
44         r = MsiViewClose(hview);
45     MsiCloseHandle(hview);
46     return r;
47 }
48
49 static UINT create_component_table( MSIHANDLE hdb )
50 {
51     return run_query( hdb,
52             "CREATE TABLE `Component` ( "
53             "`Component` CHAR(72) NOT NULL, "
54             "`ComponentId` CHAR(38), "
55             "`Directory_` CHAR(72) NOT NULL, "
56             "`Attributes` SHORT NOT NULL, "
57             "`Condition` CHAR(255), "
58             "`KeyPath` CHAR(72) "
59             "PRIMARY KEY `Component`)" );
60 }
61
62 static UINT create_feature_table( MSIHANDLE hdb )
63 {
64     return run_query( hdb,
65             "CREATE TABLE `Feature` ( "
66             "`Feature` CHAR(38) NOT NULL, "
67             "`Feature_Parent` CHAR(38), "
68             "`Title` CHAR(64), "
69             "`Description` CHAR(255), "
70             "`Display` SHORT NOT NULL, "
71             "`Level` SHORT NOT NULL, "
72             "`Directory_` CHAR(72), "
73             "`Attributes` SHORT NOT NULL "
74             "PRIMARY KEY `Feature`)" );
75 }
76
77 static UINT create_feature_components_table( MSIHANDLE hdb )
78 {
79     return run_query( hdb,
80             "CREATE TABLE `FeatureComponents` ( "
81             "`Feature_` CHAR(38) NOT NULL, "
82             "`Component_` CHAR(72) NOT NULL "
83             "PRIMARY KEY `Feature_`, `Component_` )" );
84 }
85
86 static UINT create_file_table( MSIHANDLE hdb )
87 {
88     return run_query( hdb,
89             "CREATE TABLE `File` ("
90             "`File` CHAR(72) NOT NULL, "
91             "`Component_` CHAR(72) NOT NULL, "
92             "`FileName` CHAR(255) NOT NULL, "
93             "`FileSize` LONG NOT NULL, "
94             "`Version` CHAR(72), "
95             "`Language` CHAR(20), "
96             "`Attributes` SHORT, "
97             "`Sequence` SHORT NOT NULL "
98             "PRIMARY KEY `File`)" );
99 }
100
101 static UINT create_remove_file_table( MSIHANDLE hdb )
102 {
103     return run_query( hdb,
104             "CREATE TABLE `RemoveFile` ("
105             "`FileKey` CHAR(72) NOT NULL, "
106             "`Component_` CHAR(72) NOT NULL, "
107             "`FileName` CHAR(255) LOCALIZABLE, "
108             "`DirProperty` CHAR(72) NOT NULL, "
109             "`InstallMode` SHORT NOT NULL "
110             "PRIMARY KEY `FileKey`)" );
111 }
112
113 static UINT create_appsearch_table( MSIHANDLE hdb )
114 {
115     return run_query( hdb,
116             "CREATE TABLE `AppSearch` ("
117             "`Property` CHAR(72) NOT NULL, "
118             "`Signature_` CHAR(72) NOT NULL "
119             "PRIMARY KEY `Property`, `Signature_`)" );
120 }
121
122 static UINT create_reglocator_table( MSIHANDLE hdb )
123 {
124     return run_query( hdb,
125             "CREATE TABLE `RegLocator` ("
126             "`Signature_` CHAR(72) NOT NULL, "
127             "`Root` SHORT NOT NULL, "
128             "`Key` CHAR(255) NOT NULL, "
129             "`Name` CHAR(255), "
130             "`Type` SHORT "
131             "PRIMARY KEY `Signature_`)" );
132 }
133
134 static UINT create_signature_table( MSIHANDLE hdb )
135 {
136     return run_query( hdb,
137             "CREATE TABLE `Signature` ("
138             "`Signature` CHAR(72) NOT NULL, "
139             "`FileName` CHAR(255) NOT NULL, "
140             "`MinVersion` CHAR(20), "
141             "`MaxVersion` CHAR(20), "
142             "`MinSize` LONG, "
143             "`MaxSize` LONG, "
144             "`MinDate` LONG, "
145             "`MaxDate` LONG, "
146             "`Languages` CHAR(255) "
147             "PRIMARY KEY `Signature`)" );
148 }
149
150 static UINT add_component_entry( MSIHANDLE hdb, const char *values )
151 {
152     char insert[] = "INSERT INTO `Component`  "
153             "(`Component`, `ComponentId`, `Directory_`, `Attributes`, `Condition`, `KeyPath`) "
154             "VALUES( %s )";
155     char *query;
156     UINT sz, r;
157
158     sz = strlen(values) + sizeof insert;
159     query = HeapAlloc(GetProcessHeap(),0,sz);
160     sprintf(query,insert,values);
161     r = run_query( hdb, query );
162     HeapFree(GetProcessHeap(), 0, query);
163     return r;
164 }
165
166 static UINT add_feature_entry( MSIHANDLE hdb, const char *values )
167 {
168     char insert[] = "INSERT INTO `Feature` (`Feature`, `Feature_Parent`, "
169                     "`Title`, `Description`, `Display`, `Level`, `Directory_`, `Attributes`) VALUES( %s )";
170     char *query;
171     UINT sz, r;
172
173     sz = strlen(values) + sizeof insert;
174     query = HeapAlloc(GetProcessHeap(),0,sz);
175     sprintf(query,insert,values);
176     r = run_query( hdb, query );
177     HeapFree(GetProcessHeap(), 0, query);
178     return r;
179 }
180
181 static UINT add_feature_components_entry( MSIHANDLE hdb, const char *values )
182 {
183     char insert[] = "INSERT INTO `FeatureComponents` "
184             "(`Feature_`, `Component_`) "
185             "VALUES( %s )";
186     char *query;
187     UINT sz, r;
188
189     sz = strlen(values) + sizeof insert;
190     query = HeapAlloc(GetProcessHeap(),0,sz);
191     sprintf(query,insert,values);
192     r = run_query( hdb, query );
193     HeapFree(GetProcessHeap(), 0, query);
194     return r;
195 }
196
197 static UINT add_file_entry( MSIHANDLE hdb, const char *values )
198 {
199     char insert[] = "INSERT INTO `File` "
200             "(`File`, `Component_`, `FileName`, `FileSize`, `Version`, `Language`, `Attributes`, `Sequence`) "
201             "VALUES( %s )";
202     char *query;
203     UINT sz, r;
204
205     sz = strlen(values) + sizeof insert;
206     query = HeapAlloc(GetProcessHeap(),0,sz);
207     sprintf(query,insert,values);
208     r = run_query( hdb, query );
209     HeapFree(GetProcessHeap(), 0, query);
210     return r;
211 }
212
213 static UINT add_appsearch_entry( MSIHANDLE hdb, const char *values )
214 {
215     char insert[] = "INSERT INTO `AppSearch` "
216             "(`Property`, `Signature_`) "
217             "VALUES( %s )";
218     char *query;
219     UINT sz, r;
220
221     sz = strlen(values) + sizeof insert;
222     query = HeapAlloc(GetProcessHeap(),0,sz);
223     sprintf(query,insert,values);
224     r = run_query( hdb, query );
225     HeapFree(GetProcessHeap(), 0, query);
226     return r;
227 }
228
229 static UINT add_reglocator_entry( MSIHANDLE hdb, const char *values )
230 {
231     char insert[] = "INSERT INTO `RegLocator` "
232             "(`Signature_`, `Root`, `Key`, `Name`, `Type`) "
233             "VALUES( %s )";
234     char *query;
235     UINT sz, r;
236
237     sz = strlen(values) + sizeof insert;
238     query = HeapAlloc(GetProcessHeap(),0,sz);
239     sprintf(query,insert,values);
240     r = run_query( hdb, query );
241     HeapFree(GetProcessHeap(), 0, query);
242     return r;
243 }
244
245 static UINT add_signature_entry( MSIHANDLE hdb, const char *values )
246 {
247     char insert[] = "INSERT INTO `Signature` "
248             "(`Signature`, `FileName`, `MinVersion`, `MaxVersion`,"
249             " `MinSize`, `MaxSize`, `MinDate`, `MaxDate`, `Languages`) "
250             "VALUES( %s )";
251     char *query;
252     UINT sz, r;
253
254     sz = strlen(values) + sizeof insert;
255     query = HeapAlloc(GetProcessHeap(),0,sz);
256     sprintf(query,insert,values);
257     r = run_query( hdb, query );
258     HeapFree(GetProcessHeap(), 0, query);
259     return r;
260 }
261
262 static UINT set_summary_info(MSIHANDLE hdb)
263 {
264     UINT res;
265     MSIHANDLE suminfo;
266
267     /* build summmary info */
268     res = MsiGetSummaryInformation(hdb, NULL, 7, &suminfo);
269     ok( res == ERROR_SUCCESS , "Failed to open summaryinfo\n" );
270
271     res = MsiSummaryInfoSetProperty(suminfo,2, VT_LPSTR, 0,NULL,
272                         "Installation Database");
273     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
274
275     res = MsiSummaryInfoSetProperty(suminfo,3, VT_LPSTR, 0,NULL,
276                         "Installation Database");
277     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
278
279     res = MsiSummaryInfoSetProperty(suminfo,4, VT_LPSTR, 0,NULL,
280                         "Wine Hackers");
281     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
282
283     res = MsiSummaryInfoSetProperty(suminfo,7, VT_LPSTR, 0,NULL,
284                     ";1033");
285     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
286
287     res = MsiSummaryInfoSetProperty(suminfo,9, VT_LPSTR, 0,NULL,
288                     "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}");
289     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
290
291     res = MsiSummaryInfoSetProperty(suminfo, 14, VT_I4, 100, NULL, NULL);
292     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
293
294     res = MsiSummaryInfoSetProperty(suminfo, 15, VT_I4, 0, NULL, NULL);
295     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
296
297     res = MsiSummaryInfoPersist(suminfo);
298     ok( res == ERROR_SUCCESS , "Failed to make summary info persist\n" );
299
300     res = MsiCloseHandle( suminfo);
301     ok( res == ERROR_SUCCESS , "Failed to close suminfo\n" );
302
303     return res;
304 }
305
306
307 static MSIHANDLE create_package_db(void)
308 {
309     MSIHANDLE hdb = 0;
310     UINT res;
311
312     DeleteFile(msifile);
313
314     /* create an empty database */
315     res = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb );
316     ok( res == ERROR_SUCCESS , "Failed to create database\n" );
317     if( res != ERROR_SUCCESS )
318         return hdb;
319
320     res = MsiDatabaseCommit( hdb );
321     ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
322
323     res = set_summary_info(hdb);
324
325     res = run_query( hdb,
326             "CREATE TABLE `Directory` ( "
327             "`Directory` CHAR(255) NOT NULL, "
328             "`Directory_Parent` CHAR(255), "
329             "`DefaultDir` CHAR(255) NOT NULL "
330             "PRIMARY KEY `Directory`)" );
331     ok( res == ERROR_SUCCESS , "Failed to create directory table\n" );
332
333     return hdb;
334 }
335
336 static MSIHANDLE package_from_db(MSIHANDLE hdb)
337 {
338     UINT res;
339     CHAR szPackage[10];
340     MSIHANDLE hPackage;
341
342     sprintf(szPackage,"#%li",hdb);
343     res = MsiOpenPackage(szPackage,&hPackage);
344     ok( res == ERROR_SUCCESS , "Failed to open package\n" );
345
346     res = MsiCloseHandle(hdb);
347     ok( res == ERROR_SUCCESS , "Failed to close db handle\n" );
348
349     return hPackage;
350 }
351
352 static void create_test_file(const CHAR *name)
353 {
354     HANDLE file;
355     DWORD written;
356
357     file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
358     ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
359     WriteFile(file, name, strlen(name), &written, NULL);
360     WriteFile(file, "\n", strlen("\n"), &written, NULL);
361     CloseHandle(file);
362 }
363
364 static void test_createpackage(void)
365 {
366     MSIHANDLE hPackage = 0;
367     UINT res;
368
369     hPackage = package_from_db(create_package_db());
370     ok( hPackage != 0, " Failed to create package\n");
371
372     res = MsiCloseHandle( hPackage);
373     ok( res == ERROR_SUCCESS , "Failed to close package\n" );
374     DeleteFile(msifile);
375 }
376
377 static void test_getsourcepath_bad( void )
378 {
379     static const char str[] = { 0 };
380     char buffer[0x80];
381     DWORD sz;
382     UINT r;
383
384     r = MsiGetSourcePath( -1, NULL, NULL, NULL );
385     ok( r == ERROR_INVALID_PARAMETER, "return value wrong\n");
386
387     sz = 0;
388     r = MsiGetSourcePath( -1, NULL, buffer, &sz );
389     ok( r == ERROR_INVALID_PARAMETER, "return value wrong\n");
390
391     sz = 0;
392     r = MsiGetSourcePath( -1, str, NULL, &sz );
393     ok( r == ERROR_INVALID_HANDLE, "return value wrong\n");
394
395     sz = 0;
396     r = MsiGetSourcePath( -1, str, NULL, NULL );
397     ok( r == ERROR_INVALID_HANDLE, "return value wrong\n");
398
399     sz = 0;
400     r = MsiGetSourcePath( -1, str, buffer, &sz );
401     ok( r == ERROR_INVALID_HANDLE, "return value wrong\n");
402 }
403
404 static UINT add_directory_entry( MSIHANDLE hdb, const char *values )
405 {
406     char insert[] = "INSERT INTO `Directory` (`Directory`,`Directory_Parent`,`DefaultDir`) VALUES( %s )";
407     char *query;
408     UINT sz, r;
409
410     sz = strlen(values) + sizeof insert;
411     query = HeapAlloc(GetProcessHeap(),0,sz);
412     sprintf(query,insert,values);
413     r = run_query( hdb, query );
414     HeapFree(GetProcessHeap(), 0, query);
415     return r;
416 }
417
418 static void test_getsourcepath( void )
419 {
420     static const char str[] = { 0 };
421     char buffer[0x80];
422     DWORD sz;
423     UINT r;
424     MSIHANDLE hpkg, hdb;
425
426     hpkg = package_from_db(create_package_db());
427     ok( hpkg, "failed to create package\n");
428
429     sz = 0;
430     buffer[0] = 'x';
431     r = MsiGetSourcePath( hpkg, str, buffer, &sz );
432     ok( r == ERROR_DIRECTORY, "return value wrong\n");
433     ok( buffer[0] == 'x', "buffer modified\n");
434
435     sz = 1;
436     buffer[0] = 'x';
437     r = MsiGetSourcePath( hpkg, str, buffer, &sz );
438     ok( r == ERROR_DIRECTORY, "return value wrong\n");
439     ok( buffer[0] == 'x', "buffer modified\n");
440
441     MsiCloseHandle( hpkg );
442
443
444     /* another test but try create a directory this time */
445     hdb = create_package_db();
446     ok( hdb, "failed to create database\n");
447
448     r = add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'");
449     ok( r == S_OK, "failed\n");
450
451     hpkg = package_from_db(hdb);
452     ok( hpkg, "failed to create package\n");
453
454     sz = sizeof buffer -1;
455     strcpy(buffer,"x bad");
456     r = MsiGetSourcePath( hpkg, "TARGETDIR", buffer, &sz );
457     ok( r == ERROR_DIRECTORY, "return value wrong\n");
458
459     r = MsiDoAction( hpkg, "CostInitialize");
460     ok( r == ERROR_SUCCESS, "cost init failed\n");
461     r = MsiDoAction( hpkg, "CostFinalize");
462     ok( r == ERROR_SUCCESS, "cost finalize failed\n");
463
464     todo_wine {
465     sz = sizeof buffer -1;
466     buffer[0] = 'x';
467     r = MsiGetSourcePath( hpkg, "TARGETDIR", buffer, &sz );
468     ok( r == ERROR_SUCCESS, "return value wrong\n");
469     ok( sz == strlen(buffer), "returned length wrong\n");
470
471     sz = 0;
472     strcpy(buffer,"x bad");
473     r = MsiGetSourcePath( hpkg, "TARGETDIR", buffer, &sz );
474     ok( r == ERROR_MORE_DATA, "return value wrong\n");
475     }
476     ok( buffer[0] == 'x', "buffer modified\n");
477
478     todo_wine {
479     r = MsiGetSourcePath( hpkg, "TARGETDIR", NULL, NULL );
480     ok( r == ERROR_SUCCESS, "return value wrong\n");
481     }
482
483     r = MsiGetSourcePath( hpkg, "TARGETDIR ", NULL, NULL );
484     ok( r == ERROR_DIRECTORY, "return value wrong\n");
485
486     r = MsiGetSourcePath( hpkg, "targetdir", NULL, NULL );
487     ok( r == ERROR_DIRECTORY, "return value wrong\n");
488
489     r = MsiGetSourcePath( hpkg, "TARGETDIR", buffer, NULL );
490     ok( r == ERROR_INVALID_PARAMETER, "return value wrong\n");
491
492     todo_wine {
493     r = MsiGetSourcePath( hpkg, "TARGETDIR", NULL, &sz );
494     ok( r == ERROR_SUCCESS, "return value wrong\n");
495     }
496
497     MsiCloseHandle( hpkg );
498     DeleteFile(msifile);
499 }
500
501 static void test_doaction( void )
502 {
503     MSIHANDLE hpkg;
504     UINT r;
505
506     r = MsiDoAction( -1, NULL );
507     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
508
509     hpkg = package_from_db(create_package_db());
510     ok( hpkg, "failed to create package\n");
511
512     r = MsiDoAction(hpkg, NULL);
513     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
514
515     r = MsiDoAction(0, "boo");
516     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
517
518     r = MsiDoAction(hpkg, "boo");
519     ok( r == ERROR_FUNCTION_NOT_CALLED, "wrong return val\n");
520
521     MsiCloseHandle( hpkg );
522     DeleteFile(msifile);
523 }
524
525 static void test_gettargetpath_bad(void)
526 {
527     char buffer[0x80];
528     MSIHANDLE hpkg;
529     DWORD sz;
530     UINT r;
531
532     hpkg = package_from_db(create_package_db());
533     ok( hpkg, "failed to create package\n");
534
535     r = MsiGetTargetPath( 0, NULL, NULL, NULL );
536     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
537
538     r = MsiGetTargetPath( 0, NULL, NULL, &sz );
539     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
540
541     r = MsiGetTargetPath( 0, "boo", NULL, NULL );
542     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
543
544     r = MsiGetTargetPath( 0, "boo", NULL, NULL );
545     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
546
547     r = MsiGetTargetPath( hpkg, "boo", NULL, NULL );
548     ok( r == ERROR_DIRECTORY, "wrong return val\n");
549
550     r = MsiGetTargetPath( hpkg, "boo", buffer, NULL );
551     ok( r == ERROR_DIRECTORY, "wrong return val\n");
552
553     MsiCloseHandle( hpkg );
554     DeleteFile(msifile);
555 }
556
557 static void query_file_path(MSIHANDLE hpkg, LPCSTR file, LPSTR buff)
558 {
559     UINT r;
560     DWORD size;
561     MSIHANDLE rec;
562
563     rec = MsiCreateRecord( 1 );
564     ok(rec, "MsiCreate record failed\n");
565
566     r = MsiRecordSetString( rec, 0, file );
567     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
568
569     size = MAX_PATH;
570     r = MsiFormatRecord( hpkg, rec, buff, &size );
571     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
572
573     MsiCloseHandle( rec );
574 }
575
576 static void test_settargetpath(void)
577 {
578     char tempdir[MAX_PATH+8], buffer[MAX_PATH];
579     DWORD sz;
580     MSIHANDLE hpkg;
581     UINT r;
582     MSIHANDLE hdb;
583
584     hdb = create_package_db();
585     ok ( hdb, "failed to create package database\n" );
586
587     r = add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'" );
588     ok( r == S_OK, "failed to add directory entry: %d\n" , r );
589
590     r = run_query( hdb, /* these tables required by Windows Installer for MsiSetTargetPath */
591             "CREATE TABLE `Component` ( "
592             "`Component` CHAR(72) NOT NULL, "
593             "`ComponentId` CHAR(38), "
594             "`Directory_` CHAR(72) NOT NULL, "
595             "`Attributes` SHORT NOT NULL, "
596             "`Condition` CHAR(255), "
597             "`KeyPath` CHAR(72) "
598             "PRIMARY KEY `Component`)" );
599     ok( r == S_OK, "cannot create Component table: %d\n", r );
600
601     r = run_query( hdb,
602             "INSERT INTO `Component`  "
603             "(`Component`, `ComponentId`, `Directory_`, `Attributes`, `Condition`, `KeyPath`) "
604             "VALUES( 'WinWorkAround', '{83e2694d-0864-4124-9323-6d37630912a1}', 'TARGETDIR', 8, '', 'FL_dummycomponent')" );
605     ok( r == S_OK, "cannot add dummy component: %d\n", r );
606
607     r = run_query( hdb,
608             "INSERT INTO `Component`  "
609             "(`Component`, `ComponentId`, `Directory_`, `Attributes`, `Condition`, `KeyPath`) "
610             "VALUES( 'TestComp', '{A3FB59C8-C293-4F7E-B8C5-F0E1D8EEE4E5}', 'TestDir', 0, '', 'TestFile')" );
611     ok( r == S_OK, "cannot add test component: %d\n", r );
612
613     r = run_query( hdb,
614             "CREATE TABLE `Feature` ( "
615             "`Feature` CHAR(38) NOT NULL, "
616             "`Feature_Parent` CHAR(38), "
617             "`Title` CHAR(64), "
618             "`Description` CHAR(255), "
619             "`Display` SHORT NOT NULL, "
620             "`Level` SHORT NOT NULL, "
621             "`Directory_` CHAR(72), "
622             "`Attributes` SHORT NOT NULL "
623             "PRIMARY KEY `Feature`)" );
624     ok( r == S_OK, "cannot create Feature table: %d\n", r );
625
626     r = run_query( hdb,
627             "INSERT INTO `Feature` "
628             "(`Feature`, `Feature_Parent`, `Display`, `Level`, `Attributes`) "
629             "VALUES( 'TestFeature', '', 0, 1, 0 )" );
630     ok( r == ERROR_SUCCESS, "cannot add TestFeature to Feature table: %d\n", r );
631
632     r = run_query( hdb,
633             "CREATE TABLE `FeatureComponents` ( "
634             "`Feature_` CHAR(38) NOT NULL, "
635             "`Component_` CHAR(72) NOT NULL "
636             "PRIMARY KEY `Feature_` )" );
637     ok( r == S_OK, "cannot create FeatureComponents table: %d\n", r );
638
639     r = run_query( hdb,
640             "INSERT INTO `FeatureComponents` "
641             "(`Feature_`, `Component_`) "
642             "VALUES( 'TestFeature', 'TestComp' )" );
643     ok( r == S_OK, "cannot insert component into FeatureComponents table: %d\n", r );
644
645     add_directory_entry( hdb, "'TestParent', 'TARGETDIR', 'TestParent'" );
646     add_directory_entry( hdb, "'TestDir', 'TestParent', 'TestDir'" );
647
648     r = run_query( hdb,
649             "CREATE TABLE `File` ("
650             "`File` CHAR(72) NOT NULL, "
651             "`Component_` CHAR(72) NOT NULL, "
652             "`FileName` CHAR(255) NOT NULL, "
653             "`FileSize` LONG NOT NULL, "
654             "`Version` CHAR(72), "
655             "`Language` CHAR(20), "
656             "`Attributes` SHORT, "
657             "`Sequence` SHORT NOT NULL "
658             "PRIMARY KEY `File`)" );
659     ok( r == S_OK, "cannot create File table: %d\n", r );
660
661     r = run_query( hdb,
662             "INSERT INTO `File` "
663             "(`File`, `Component_`, `FileName`, `FileSize`, `Version`, `Language`, `Attributes`, `Sequence`) "
664             "VALUES( 'TestFile', 'TestComp', 'testfile.txt', 0, '', '1033', 8192, 1 )" );
665     ok( r == S_OK, "cannot add file to the File table: %d\n", r );
666
667     hpkg = package_from_db( hdb );
668     ok( hpkg, "failed to create package\n");
669
670     r = MsiDoAction( hpkg, "CostInitialize");
671     ok( r == ERROR_SUCCESS, "cost init failed\n");
672
673     r = MsiDoAction( hpkg, "FileCost");
674     ok( r == ERROR_SUCCESS, "file cost failed\n");
675
676     r = MsiDoAction( hpkg, "CostFinalize");
677     ok( r == ERROR_SUCCESS, "cost finalize failed\n");
678
679     r = MsiSetTargetPath( 0, NULL, NULL );
680     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
681
682     r = MsiSetTargetPath( 0, "boo", "C:\\bogusx" );
683     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
684
685     r = MsiSetTargetPath( hpkg, "boo", NULL );
686     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
687
688     r = MsiSetTargetPath( hpkg, "boo", "c:\\bogusx" );
689     ok( r == ERROR_DIRECTORY, "wrong return val\n");
690
691     sz = sizeof tempdir - 1;
692     r = MsiGetTargetPath( hpkg, "TARGETDIR", tempdir, &sz );
693     if ( r == S_OK )
694     {
695         if ( GetTempFileName( tempdir, "_wt", 0, buffer ) )
696         {
697             sprintf( tempdir, "%s\\subdir", buffer );
698             r = MsiSetTargetPath( hpkg, "TARGETDIR", buffer );
699             ok( r == ERROR_SUCCESS, "MsiSetTargetPath on file returned %d\n", r );
700
701             r = MsiSetTargetPath( hpkg, "TARGETDIR", tempdir );
702             ok( r == ERROR_SUCCESS, "MsiSetTargetPath on 'subdir' of file returned %d\n", r );
703
704             DeleteFile( buffer );
705
706             r = MsiSetTargetPath( hpkg, "TARGETDIR", buffer );
707             ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
708
709             r = GetFileAttributes( buffer );
710             ok ( r == INVALID_FILE_ATTRIBUTES, "file/directory exists after MsiSetTargetPath. Attributes: %08X\n", r );
711
712             r = MsiSetTargetPath( hpkg, "TARGETDIR", tempdir );
713             ok( r == ERROR_SUCCESS, "MsiSetTargetPath on subsubdir returned %d\n", r );
714         } else {
715             trace("GetTempFileName failed, cannot do some tests\n");
716         }
717     } else {
718         trace( "MsiGetTargetPath failed: %d\n", r );
719     }
720
721     r = MsiSetTargetPath( hpkg, "TestParent", "C:\\one\\two" );
722     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
723
724     query_file_path( hpkg, "[#TestFile]", buffer );
725     ok( !lstrcmp(buffer, "C:\\one\\two\\TestDir\\testfile.txt"),
726         "Expected C:\\one\\two\\TestDir\\testfile.txt, got %s\n", buffer );
727     
728     MsiCloseHandle( hpkg );
729 }
730
731 static void test_condition(void)
732 {
733     MSICONDITION r;
734     MSIHANDLE hpkg;
735
736     hpkg = package_from_db(create_package_db());
737     ok( hpkg, "failed to create package\n");
738
739     r = MsiEvaluateCondition(0, NULL);
740     ok( r == MSICONDITION_ERROR, "wrong return val\n");
741
742     r = MsiEvaluateCondition(hpkg, NULL);
743     ok( r == MSICONDITION_NONE, "wrong return val\n");
744
745     r = MsiEvaluateCondition(hpkg, "");
746     ok( r == MSICONDITION_NONE, "wrong return val\n");
747
748     r = MsiEvaluateCondition(hpkg, "1");
749     ok( r == MSICONDITION_TRUE, "wrong return val\n");
750
751     r = MsiEvaluateCondition(hpkg, "0");
752     ok( r == MSICONDITION_FALSE, "wrong return val\n");
753
754     r = MsiEvaluateCondition(hpkg, "0 = 0");
755     ok( r == MSICONDITION_TRUE, "wrong return val\n");
756
757     r = MsiEvaluateCondition(hpkg, "0 <> 0");
758     ok( r == MSICONDITION_FALSE, "wrong return val\n");
759
760     r = MsiEvaluateCondition(hpkg, "0 = 1");
761     ok( r == MSICONDITION_FALSE, "wrong return val\n");
762
763     r = MsiEvaluateCondition(hpkg, "0 > 1");
764     ok( r == MSICONDITION_FALSE, "wrong return val\n");
765
766     r = MsiEvaluateCondition(hpkg, "0 ~> 1");
767     ok( r == MSICONDITION_FALSE, "wrong return val\n");
768
769     r = MsiEvaluateCondition(hpkg, "1 > 1");
770     ok( r == MSICONDITION_FALSE, "wrong return val\n");
771
772     r = MsiEvaluateCondition(hpkg, "1 ~> 1");
773     ok( r == MSICONDITION_FALSE, "wrong return val\n");
774
775     r = MsiEvaluateCondition(hpkg, "0 >= 1");
776     ok( r == MSICONDITION_FALSE, "wrong return val\n");
777
778     r = MsiEvaluateCondition(hpkg, "0 ~>= 1");
779     ok( r == MSICONDITION_FALSE, "wrong return val\n");
780
781     r = MsiEvaluateCondition(hpkg, "1 >= 1");
782     ok( r == MSICONDITION_TRUE, "wrong return val\n");
783
784     r = MsiEvaluateCondition(hpkg, "1 ~>= 1");
785     ok( r == MSICONDITION_TRUE, "wrong return val\n");
786
787     r = MsiEvaluateCondition(hpkg, "0 < 1");
788     ok( r == MSICONDITION_TRUE, "wrong return val\n");
789
790     r = MsiEvaluateCondition(hpkg, "0 ~< 1");
791     ok( r == MSICONDITION_TRUE, "wrong return val\n");
792
793     r = MsiEvaluateCondition(hpkg, "1 < 1");
794     ok( r == MSICONDITION_FALSE, "wrong return val\n");
795
796     r = MsiEvaluateCondition(hpkg, "1 ~< 1");
797     ok( r == MSICONDITION_FALSE, "wrong return val\n");
798
799     r = MsiEvaluateCondition(hpkg, "0 <= 1");
800     ok( r == MSICONDITION_TRUE, "wrong return val\n");
801
802     r = MsiEvaluateCondition(hpkg, "0 ~<= 1");
803     ok( r == MSICONDITION_TRUE, "wrong return val\n");
804
805     r = MsiEvaluateCondition(hpkg, "1 <= 1");
806     ok( r == MSICONDITION_TRUE, "wrong return val\n");
807
808     r = MsiEvaluateCondition(hpkg, "1 ~<= 1");
809     ok( r == MSICONDITION_TRUE, "wrong return val\n");
810
811     r = MsiEvaluateCondition(hpkg, "0 >=");
812     ok( r == MSICONDITION_ERROR, "wrong return val\n");
813
814     r = MsiEvaluateCondition(hpkg, " ");
815     ok( r == MSICONDITION_NONE, "wrong return val\n");
816
817     r = MsiEvaluateCondition(hpkg, "LicView <> \"1\"");
818     ok( r == MSICONDITION_TRUE, "wrong return val\n");
819
820     r = MsiEvaluateCondition(hpkg, "LicView <> \"0\"");
821     ok( r == MSICONDITION_TRUE, "wrong return val\n");
822
823     r = MsiEvaluateCondition(hpkg, "LicView <> LicView");
824     ok( r == MSICONDITION_FALSE, "wrong return val\n");
825
826     r = MsiEvaluateCondition(hpkg, "not 0");
827     ok( r == MSICONDITION_TRUE, "wrong return val\n");
828
829     r = MsiEvaluateCondition(hpkg, "not LicView");
830     ok( r == MSICONDITION_TRUE, "wrong return val\n");
831
832     r = MsiEvaluateCondition(hpkg, "not \"A\"");
833     ok( r == MSICONDITION_FALSE, "wrong return val\n");
834
835     r = MsiEvaluateCondition(hpkg, "~not \"A\"");
836     ok( r == MSICONDITION_ERROR, "wrong return val\n");
837
838     r = MsiEvaluateCondition(hpkg, "\"0\"");
839     ok( r == MSICONDITION_TRUE, "wrong return val\n");
840
841     r = MsiEvaluateCondition(hpkg, "1 and 2");
842     ok( r == MSICONDITION_TRUE, "wrong return val\n");
843
844     r = MsiEvaluateCondition(hpkg, "not 0 and 3");
845     ok( r == MSICONDITION_TRUE, "wrong return val\n");
846
847     r = MsiEvaluateCondition(hpkg, "not 0 and 0");
848     ok( r == MSICONDITION_FALSE, "wrong return val\n");
849
850     r = MsiEvaluateCondition(hpkg, "not 0 or 1");
851     ok( r == MSICONDITION_TRUE, "wrong return val\n");
852
853     r = MsiEvaluateCondition(hpkg, "(0)");
854     ok( r == MSICONDITION_FALSE, "wrong return val\n");
855
856     r = MsiEvaluateCondition(hpkg, "(((((1))))))");
857     ok( r == MSICONDITION_ERROR, "wrong return val\n");
858
859     r = MsiEvaluateCondition(hpkg, "(((((1)))))");
860     ok( r == MSICONDITION_TRUE, "wrong return val\n");
861
862     r = MsiEvaluateCondition(hpkg, " \"A\" < \"B\" ");
863     ok( r == MSICONDITION_TRUE, "wrong return val\n");
864
865     r = MsiEvaluateCondition(hpkg, " \"A\" > \"B\" ");
866     ok( r == MSICONDITION_FALSE, "wrong return val\n");
867
868     r = MsiEvaluateCondition(hpkg, " \"1\" > \"12\" ");
869     ok( r == MSICONDITION_FALSE, "wrong return val\n");
870
871     r = MsiEvaluateCondition(hpkg, " \"100\" < \"21\" ");
872     ok( r == MSICONDITION_TRUE, "wrong return val\n");
873
874     r = MsiEvaluateCondition(hpkg, "0 < > 0");
875     ok( r == MSICONDITION_ERROR, "wrong return val\n");
876
877     r = MsiEvaluateCondition(hpkg, "(1<<1) == 2");
878     ok( r == MSICONDITION_ERROR, "wrong return val\n");
879
880     r = MsiEvaluateCondition(hpkg, " \"A\" = \"a\" ");
881     ok( r == MSICONDITION_FALSE, "wrong return val\n");
882
883     r = MsiEvaluateCondition(hpkg, " \"A\" ~ = \"a\" ");
884     ok( r == MSICONDITION_ERROR, "wrong return val\n");
885
886     r = MsiEvaluateCondition(hpkg, " \"A\" ~= \"a\" ");
887     ok( r == MSICONDITION_TRUE, "wrong return val\n");
888
889     r = MsiEvaluateCondition(hpkg, " \"A\" ~= 1 ");
890     ok( r == MSICONDITION_FALSE, "wrong return val\n");
891
892     r = MsiEvaluateCondition(hpkg, " \"A\" = 1 ");
893     ok( r == MSICONDITION_FALSE, "wrong return val\n");
894
895     r = MsiEvaluateCondition(hpkg, " 1 ~= 1 ");
896     ok( r == MSICONDITION_TRUE, "wrong return val\n");
897
898     r = MsiEvaluateCondition(hpkg, " 1 ~= \"1\" ");
899     ok( r == MSICONDITION_FALSE, "wrong return val\n");
900
901     r = MsiEvaluateCondition(hpkg, " 1 = \"1\" ");
902     ok( r == MSICONDITION_FALSE, "wrong return val\n");
903
904     r = MsiEvaluateCondition(hpkg, " 0 = \"1\" ");
905     ok( r == MSICONDITION_FALSE, "wrong return val\n");
906
907     r = MsiEvaluateCondition(hpkg, " 0 < \"100\" ");
908     ok( r == MSICONDITION_FALSE, "wrong return val\n");
909
910     r = MsiEvaluateCondition(hpkg, " 100 > \"0\" ");
911     ok( r == MSICONDITION_FALSE, "wrong return val\n");
912
913     r = MsiEvaluateCondition(hpkg, "1 XOR 1");
914     ok( r == MSICONDITION_FALSE, "wrong return val\n");
915
916     r = MsiEvaluateCondition(hpkg, "1 IMP 1");
917     ok( r == MSICONDITION_TRUE, "wrong return val\n");
918
919     r = MsiEvaluateCondition(hpkg, "1 IMP 0");
920     ok( r == MSICONDITION_FALSE, "wrong return val\n");
921
922     r = MsiEvaluateCondition(hpkg, "0 IMP 0");
923     ok( r == MSICONDITION_TRUE, "wrong return val\n");
924
925     r = MsiEvaluateCondition(hpkg, "0 EQV 0");
926     ok( r == MSICONDITION_TRUE, "wrong return val\n");
927
928     r = MsiEvaluateCondition(hpkg, "0 EQV 1");
929     ok( r == MSICONDITION_FALSE, "wrong return val\n");
930
931     r = MsiEvaluateCondition(hpkg, "1 IMP 1 OR 0");
932     ok( r == MSICONDITION_TRUE, "wrong return val\n");
933
934     r = MsiEvaluateCondition(hpkg, "1 IMPL 1");
935     ok( r == MSICONDITION_ERROR, "wrong return val\n");
936
937     r = MsiEvaluateCondition(hpkg, "\"ASFD\" >< \"S\" ");
938     ok( r == MSICONDITION_TRUE, "wrong return val\n");
939
940     r = MsiEvaluateCondition(hpkg, "\"ASFD\" ~>< \"s\" ");
941     ok( r == MSICONDITION_TRUE, "wrong return val\n");
942
943     r = MsiEvaluateCondition(hpkg, "\"ASFD\" ~>< \"\" ");
944     ok( r == MSICONDITION_TRUE, "wrong return val\n");
945
946     r = MsiEvaluateCondition(hpkg, "\"ASFD\" ~>< \"sss\" ");
947     ok( r == MSICONDITION_FALSE, "wrong return val\n");
948
949     MsiSetProperty(hpkg, "mm", "5" );
950
951     r = MsiEvaluateCondition(hpkg, "mm = 5");
952     ok( r == MSICONDITION_TRUE, "wrong return val\n");
953
954     r = MsiEvaluateCondition(hpkg, "mm < 6");
955     ok( r == MSICONDITION_TRUE, "wrong return val\n");
956
957     r = MsiEvaluateCondition(hpkg, "mm <= 5");
958     ok( r == MSICONDITION_TRUE, "wrong return val\n");
959
960     r = MsiEvaluateCondition(hpkg, "mm > 4");
961     ok( r == MSICONDITION_TRUE, "wrong return val\n");
962
963     r = MsiEvaluateCondition(hpkg, "mm < 12");
964     ok( r == MSICONDITION_TRUE, "wrong return val\n");
965
966     r = MsiEvaluateCondition(hpkg, "mm = \"5\"");
967     ok( r == MSICONDITION_TRUE, "wrong return val\n");
968
969     r = MsiEvaluateCondition(hpkg, "0 = \"\"");
970     ok( r == MSICONDITION_FALSE, "wrong return val\n");
971
972     r = MsiEvaluateCondition(hpkg, "0 AND \"\"");
973     ok( r == MSICONDITION_FALSE, "wrong return val\n");
974
975     r = MsiEvaluateCondition(hpkg, "1 AND \"\"");
976     ok( r == MSICONDITION_FALSE, "wrong return val\n");
977
978     r = MsiEvaluateCondition(hpkg, "1 AND \"1\"");
979     ok( r == MSICONDITION_TRUE, "wrong return val\n");
980
981     r = MsiEvaluateCondition(hpkg, "3 >< 1");
982     ok( r == MSICONDITION_TRUE, "wrong return val\n");
983
984     r = MsiEvaluateCondition(hpkg, "3 >< 4");
985     ok( r == MSICONDITION_FALSE, "wrong return val\n");
986
987     r = MsiEvaluateCondition(hpkg, "NOT 0 AND 0");
988     ok( r == MSICONDITION_FALSE, "wrong return val\n");
989
990     r = MsiEvaluateCondition(hpkg, "NOT 0 AND 1");
991     ok( r == MSICONDITION_TRUE, "wrong return val\n");
992
993     r = MsiEvaluateCondition(hpkg, "NOT 1 OR 0");
994     ok( r == MSICONDITION_FALSE, "wrong return val\n");
995
996     r = MsiEvaluateCondition(hpkg, "0 AND 1 OR 1");
997     ok( r == MSICONDITION_TRUE, "wrong return val\n");
998
999     r = MsiEvaluateCondition(hpkg, "0 AND 0 OR 1");
1000     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1001
1002     r = MsiEvaluateCondition(hpkg, "NOT 0 AND 1 OR 0");
1003     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1004
1005     r = MsiEvaluateCondition(hpkg, "_1 = _1");
1006     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1007
1008     r = MsiEvaluateCondition(hpkg, "( 1 AND 1 ) = 2");
1009     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1010
1011     r = MsiEvaluateCondition(hpkg, "NOT ( 1 AND 1 )");
1012     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1013
1014     r = MsiEvaluateCondition(hpkg, "NOT A AND (BBBBBBBBBB=2 OR CCC=1) AND Ddddddddd");
1015     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1016
1017     r = MsiEvaluateCondition(hpkg, "Installed<>\"\"");
1018     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1019
1020     r = MsiEvaluateCondition(hpkg, "NOT 1 AND 0");
1021     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1022
1023     r = MsiEvaluateCondition(hpkg, "bandalmael=0");
1024     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1025
1026     r = MsiEvaluateCondition(hpkg, "bandalmael<>0");
1027     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1028
1029     r = MsiEvaluateCondition(hpkg, "bandalmael<0");
1030     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1031
1032     r = MsiEvaluateCondition(hpkg, "bandalmael>0");
1033     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1034
1035     r = MsiEvaluateCondition(hpkg, "bandalmael>=0");
1036     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1037
1038     r = MsiEvaluateCondition(hpkg, "bandalmael<=0");
1039     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1040
1041     r = MsiEvaluateCondition(hpkg, "bandalmael~<>0");
1042     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1043
1044     MsiSetProperty(hpkg, "bandalmael", "0" );
1045     r = MsiEvaluateCondition(hpkg, "bandalmael=0");
1046     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1047
1048     MsiSetProperty(hpkg, "bandalmael", "" );
1049     r = MsiEvaluateCondition(hpkg, "bandalmael=0");
1050     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1051
1052     MsiSetProperty(hpkg, "bandalmael", "asdf" );
1053     r = MsiEvaluateCondition(hpkg, "bandalmael=0");
1054     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1055
1056     MsiSetProperty(hpkg, "bandalmael", "0asdf" );
1057     r = MsiEvaluateCondition(hpkg, "bandalmael=0");
1058     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1059
1060     MsiSetProperty(hpkg, "bandalmael", "0 " );
1061     r = MsiEvaluateCondition(hpkg, "bandalmael=0");
1062     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1063
1064     MsiSetProperty(hpkg, "bandalmael", "-0" );
1065     r = MsiEvaluateCondition(hpkg, "bandalmael=0");
1066     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1067
1068     MsiSetProperty(hpkg, "bandalmael", "0000000000000" );
1069     r = MsiEvaluateCondition(hpkg, "bandalmael=0");
1070     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1071
1072     MsiSetProperty(hpkg, "bandalmael", "--0" );
1073     r = MsiEvaluateCondition(hpkg, "bandalmael=0");
1074     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1075
1076     MsiSetProperty(hpkg, "bandalmael", "0x00" );
1077     r = MsiEvaluateCondition(hpkg, "bandalmael=0");
1078     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1079
1080     MsiSetProperty(hpkg, "bandalmael", "-" );
1081     r = MsiEvaluateCondition(hpkg, "bandalmael=0");
1082     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1083
1084     MsiSetProperty(hpkg, "bandalmael", "+0" );
1085     r = MsiEvaluateCondition(hpkg, "bandalmael=0");
1086     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1087
1088     MsiSetProperty(hpkg, "bandalmael", "0.0" );
1089     r = MsiEvaluateCondition(hpkg, "bandalmael=0");
1090     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1091     r = MsiEvaluateCondition(hpkg, "bandalmael<>0");
1092     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1093
1094     MsiSetProperty(hpkg, "one", "hi");
1095     MsiSetProperty(hpkg, "two", "hithere");
1096     r = MsiEvaluateCondition(hpkg, "one >< two");
1097     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1098
1099     MsiSetProperty(hpkg, "one", "hithere");
1100     MsiSetProperty(hpkg, "two", "hi");
1101     r = MsiEvaluateCondition(hpkg, "one >< two");
1102     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1103
1104     MsiSetProperty(hpkg, "one", "hello");
1105     MsiSetProperty(hpkg, "two", "hi");
1106     r = MsiEvaluateCondition(hpkg, "one >< two");
1107     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1108
1109     MsiSetProperty(hpkg, "one", "hellohithere");
1110     MsiSetProperty(hpkg, "two", "hi");
1111     r = MsiEvaluateCondition(hpkg, "one >< two");
1112     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1113
1114     MsiSetProperty(hpkg, "one", "");
1115     MsiSetProperty(hpkg, "two", "hi");
1116     r = MsiEvaluateCondition(hpkg, "one >< two");
1117     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1118
1119     MsiSetProperty(hpkg, "one", "hi");
1120     MsiSetProperty(hpkg, "two", "");
1121     r = MsiEvaluateCondition(hpkg, "one >< two");
1122     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1123
1124     MsiSetProperty(hpkg, "one", "");
1125     MsiSetProperty(hpkg, "two", "");
1126     r = MsiEvaluateCondition(hpkg, "one >< two");
1127     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1128
1129     MsiSetProperty(hpkg, "one", "1234");
1130     MsiSetProperty(hpkg, "two", "1");
1131     r = MsiEvaluateCondition(hpkg, "one >< two");
1132     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1133
1134     MsiSetProperty(hpkg, "one", "one 1234");
1135     MsiSetProperty(hpkg, "two", "1");
1136     r = MsiEvaluateCondition(hpkg, "one >< two");
1137     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1138
1139     MsiSetProperty(hpkg, "one", "hithere");
1140     MsiSetProperty(hpkg, "two", "hi");
1141     r = MsiEvaluateCondition(hpkg, "one << two");
1142     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1143
1144     MsiSetProperty(hpkg, "one", "hi");
1145     MsiSetProperty(hpkg, "two", "hithere");
1146     r = MsiEvaluateCondition(hpkg, "one << two");
1147     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1148
1149     MsiSetProperty(hpkg, "one", "hi");
1150     MsiSetProperty(hpkg, "two", "hi");
1151     r = MsiEvaluateCondition(hpkg, "one << two");
1152     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1153
1154     MsiSetProperty(hpkg, "one", "abcdhithere");
1155     MsiSetProperty(hpkg, "two", "hi");
1156     r = MsiEvaluateCondition(hpkg, "one << two");
1157     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1158
1159     MsiSetProperty(hpkg, "one", "");
1160     MsiSetProperty(hpkg, "two", "hi");
1161     r = MsiEvaluateCondition(hpkg, "one << two");
1162     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1163
1164     MsiSetProperty(hpkg, "one", "hithere");
1165     MsiSetProperty(hpkg, "two", "");
1166     r = MsiEvaluateCondition(hpkg, "one << two");
1167     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1168
1169     MsiSetProperty(hpkg, "one", "");
1170     MsiSetProperty(hpkg, "two", "");
1171     r = MsiEvaluateCondition(hpkg, "one << two");
1172     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1173
1174     MsiSetProperty(hpkg, "one", "1234");
1175     MsiSetProperty(hpkg, "two", "1");
1176     r = MsiEvaluateCondition(hpkg, "one << two");
1177     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1178
1179     MsiSetProperty(hpkg, "one", "1234 one");
1180     MsiSetProperty(hpkg, "two", "1");
1181     r = MsiEvaluateCondition(hpkg, "one << two");
1182     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1183
1184     MsiSetProperty(hpkg, "one", "hithere");
1185     MsiSetProperty(hpkg, "two", "there");
1186     r = MsiEvaluateCondition(hpkg, "one >> two");
1187     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1188
1189     MsiSetProperty(hpkg, "one", "hithere");
1190     MsiSetProperty(hpkg, "two", "hi");
1191     r = MsiEvaluateCondition(hpkg, "one >> two");
1192     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1193
1194     MsiSetProperty(hpkg, "one", "there");
1195     MsiSetProperty(hpkg, "two", "hithere");
1196     r = MsiEvaluateCondition(hpkg, "one >> two");
1197     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1198
1199     MsiSetProperty(hpkg, "one", "there");
1200     MsiSetProperty(hpkg, "two", "there");
1201     r = MsiEvaluateCondition(hpkg, "one >> two");
1202     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1203
1204     MsiSetProperty(hpkg, "one", "abcdhithere");
1205     MsiSetProperty(hpkg, "two", "hi");
1206     r = MsiEvaluateCondition(hpkg, "one >> two");
1207     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1208
1209     MsiSetProperty(hpkg, "one", "");
1210     MsiSetProperty(hpkg, "two", "there");
1211     r = MsiEvaluateCondition(hpkg, "one >> two");
1212     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1213
1214     MsiSetProperty(hpkg, "one", "there");
1215     MsiSetProperty(hpkg, "two", "");
1216     r = MsiEvaluateCondition(hpkg, "one >> two");
1217     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1218
1219     MsiSetProperty(hpkg, "one", "");
1220     MsiSetProperty(hpkg, "two", "");
1221     r = MsiEvaluateCondition(hpkg, "one >> two");
1222     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1223
1224     MsiSetProperty(hpkg, "one", "1234");
1225     MsiSetProperty(hpkg, "two", "4");
1226     r = MsiEvaluateCondition(hpkg, "one >> two");
1227     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1228
1229     MsiSetProperty(hpkg, "one", "one 1234");
1230     MsiSetProperty(hpkg, "two", "4");
1231     r = MsiEvaluateCondition(hpkg, "one >> two");
1232     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1233
1234     MsiCloseHandle( hpkg );
1235     DeleteFile(msifile);
1236 }
1237
1238 static BOOL check_prop_empty( MSIHANDLE hpkg, const char * prop)
1239 {
1240     UINT r;
1241     DWORD sz;
1242     char buffer[2];
1243
1244     sz = sizeof buffer;
1245     strcpy(buffer,"x");
1246     r = MsiGetProperty( hpkg, prop, buffer, &sz );
1247     return r == ERROR_SUCCESS && buffer[0] == 0 && sz == 0;
1248 }
1249
1250 static void test_props(void)
1251 {
1252     MSIHANDLE hpkg;
1253     UINT r;
1254     DWORD sz;
1255     char buffer[0x100];
1256
1257     hpkg = package_from_db(create_package_db());
1258     ok( hpkg, "failed to create package\n");
1259
1260     /* test invalid values */
1261     r = MsiGetProperty( 0, NULL, NULL, NULL );
1262     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1263
1264     r = MsiGetProperty( hpkg, NULL, NULL, NULL );
1265     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1266
1267     r = MsiGetProperty( hpkg, "boo", NULL, NULL );
1268     ok( r == ERROR_SUCCESS, "wrong return val\n");
1269
1270     r = MsiGetProperty( hpkg, "boo", buffer, NULL );
1271     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1272
1273     /* test retrieving an empty/nonexistent property */
1274     sz = sizeof buffer;
1275     r = MsiGetProperty( hpkg, "boo", NULL, &sz );
1276     ok( r == ERROR_SUCCESS, "wrong return val\n");
1277     ok( sz == 0, "wrong size returned\n");
1278
1279     check_prop_empty( hpkg, "boo");
1280     sz = 0;
1281     strcpy(buffer,"x");
1282     r = MsiGetProperty( hpkg, "boo", buffer, &sz );
1283     ok( r == ERROR_MORE_DATA, "wrong return val\n");
1284     ok( !strcmp(buffer,"x"), "buffer was changed\n");
1285     ok( sz == 0, "wrong size returned\n");
1286
1287     sz = 1;
1288     strcpy(buffer,"x");
1289     r = MsiGetProperty( hpkg, "boo", buffer, &sz );
1290     ok( r == ERROR_SUCCESS, "wrong return val\n");
1291     ok( buffer[0] == 0, "buffer was not changed\n");
1292     ok( sz == 0, "wrong size returned\n");
1293
1294     /* set the property to something */
1295     r = MsiSetProperty( 0, NULL, NULL );
1296     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1297
1298     r = MsiSetProperty( hpkg, NULL, NULL );
1299     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1300
1301     r = MsiSetProperty( hpkg, "", NULL );
1302     ok( r == ERROR_SUCCESS, "wrong return val\n");
1303
1304     /* try set and get some illegal property identifiers */
1305     r = MsiSetProperty( hpkg, "", "asdf" );
1306     ok( r == ERROR_FUNCTION_FAILED, "wrong return val\n");
1307
1308     r = MsiSetProperty( hpkg, "=", "asdf" );
1309     ok( r == ERROR_SUCCESS, "wrong return val\n");
1310
1311     r = MsiSetProperty( hpkg, " ", "asdf" );
1312     ok( r == ERROR_SUCCESS, "wrong return val\n");
1313
1314     r = MsiSetProperty( hpkg, "'", "asdf" );
1315     ok( r == ERROR_SUCCESS, "wrong return val\n");
1316
1317     sz = sizeof buffer;
1318     buffer[0]=0;
1319     r = MsiGetProperty( hpkg, "'", buffer, &sz );
1320     ok( r == ERROR_SUCCESS, "wrong return val\n");
1321     ok( !strcmp(buffer,"asdf"), "buffer was not changed\n");
1322
1323     /* set empty values */
1324     r = MsiSetProperty( hpkg, "boo", NULL );
1325     ok( r == ERROR_SUCCESS, "wrong return val\n");
1326     ok( check_prop_empty( hpkg, "boo"), "prop wasn't empty\n");
1327
1328     r = MsiSetProperty( hpkg, "boo", "" );
1329     ok( r == ERROR_SUCCESS, "wrong return val\n");
1330     ok( check_prop_empty( hpkg, "boo"), "prop wasn't empty\n");
1331
1332     /* set a non-empty value */
1333     r = MsiSetProperty( hpkg, "boo", "xyz" );
1334     ok( r == ERROR_SUCCESS, "wrong return val\n");
1335
1336     sz = 1;
1337     strcpy(buffer,"x");
1338     r = MsiGetProperty( hpkg, "boo", buffer, &sz );
1339     ok( r == ERROR_MORE_DATA, "wrong return val\n");
1340     ok( buffer[0] == 0, "buffer was not changed\n");
1341     ok( sz == 3, "wrong size returned\n");
1342
1343     sz = 4;
1344     strcpy(buffer,"x");
1345     r = MsiGetProperty( hpkg, "boo", buffer, &sz );
1346     ok( r == ERROR_SUCCESS, "wrong return val\n");
1347     ok( !strcmp(buffer,"xyz"), "buffer was not changed\n");
1348     ok( sz == 3, "wrong size returned\n");
1349
1350     sz = 3;
1351     strcpy(buffer,"x");
1352     r = MsiGetProperty( hpkg, "boo", buffer, &sz );
1353     ok( r == ERROR_MORE_DATA, "wrong return val\n");
1354     ok( !strcmp(buffer,"xy"), "buffer was not changed\n");
1355     ok( sz == 3, "wrong size returned\n");
1356
1357     r = MsiSetProperty(hpkg, "SourceDir", "foo");
1358     ok( r == ERROR_SUCCESS, "wrong return val\n");
1359
1360     sz = 4;
1361     r = MsiGetProperty(hpkg, "SOURCEDIR", buffer, &sz);
1362     ok( r == ERROR_SUCCESS, "wrong return val\n");
1363     ok( !strcmp(buffer,""), "buffer wrong\n");
1364     ok( sz == 0, "wrong size returned\n");
1365
1366     sz = 4;
1367     r = MsiGetProperty(hpkg, "SOMERANDOMNAME", buffer, &sz);
1368     ok( r == ERROR_SUCCESS, "wrong return val\n");
1369     ok( !strcmp(buffer,""), "buffer wrong\n");
1370     ok( sz == 0, "wrong size returned\n");
1371
1372     sz = 4;
1373     r = MsiGetProperty(hpkg, "SourceDir", buffer, &sz);
1374     ok( r == ERROR_SUCCESS, "wrong return val\n");
1375     ok( !strcmp(buffer,"foo"), "buffer wrong\n");
1376     ok( sz == 3, "wrong size returned\n");
1377
1378     MsiCloseHandle( hpkg );
1379     DeleteFile(msifile);
1380 }
1381
1382 static UINT try_query_param( MSIHANDLE hdb, LPCSTR szQuery, MSIHANDLE hrec )
1383 {
1384     MSIHANDLE htab = 0;
1385     UINT res;
1386
1387     res = MsiDatabaseOpenView( hdb, szQuery, &htab );
1388     if( res == ERROR_SUCCESS )
1389     {
1390         UINT r;
1391
1392         r = MsiViewExecute( htab, hrec );
1393         if( r != ERROR_SUCCESS )
1394         {
1395             res = r;
1396             fprintf(stderr,"MsiViewExecute failed %08x\n", res);
1397         }
1398
1399         r = MsiViewClose( htab );
1400         if( r != ERROR_SUCCESS )
1401             res = r;
1402
1403         r = MsiCloseHandle( htab );
1404         if( r != ERROR_SUCCESS )
1405             res = r;
1406     }
1407     return res;
1408 }
1409
1410 static UINT try_query( MSIHANDLE hdb, LPCSTR szQuery )
1411 {
1412     return try_query_param( hdb, szQuery, 0 );
1413 }
1414
1415 static void test_msipackage(void)
1416 {
1417     MSIHANDLE hdb = 0, hpack = 100;
1418     UINT r;
1419     const char *query;
1420     char name[10];
1421
1422     DeleteFile(msifile);
1423
1424     todo_wine {
1425     name[0] = 0;
1426     r = MsiOpenPackage(name, &hpack);
1427     ok(r == ERROR_SUCCESS, "failed to open package with no name\n");
1428     r = MsiCloseHandle(hpack);
1429     ok(r == ERROR_SUCCESS, "failed to close package\n");
1430     }
1431
1432     /* just MsiOpenDatabase should not create a file */
1433     r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
1434     ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n");
1435
1436     name[0]='#';
1437     name[1]=0;
1438     r = MsiOpenPackage(name, &hpack);
1439     ok(r == ERROR_INVALID_HANDLE, "MsiOpenPackage returned wrong code\n");
1440
1441     todo_wine {
1442     /* now try again with our empty database */
1443     sprintf(name, "#%ld", hdb);
1444     r = MsiOpenPackage(name, &hpack);
1445     ok(r == ERROR_INSTALL_PACKAGE_INVALID, "MsiOpenPackage returned wrong code\n");
1446     if (!r)    MsiCloseHandle(hpack);
1447     }
1448
1449     /* create a table */
1450     query = "CREATE TABLE `Property` ( "
1451             "`Property` CHAR(72), `Value` CHAR(0) "
1452             "PRIMARY KEY `Property`)";
1453     r = try_query(hdb, query);
1454     ok(r == ERROR_SUCCESS, "failed to create Properties table\n");
1455
1456     todo_wine {
1457     query = "CREATE TABLE `InstallExecuteSequence` ("
1458             "`Action` CHAR(72), `Condition` CHAR(0), `Sequence` INTEGER "
1459             "PRIMARY KEY `Action`)";
1460     r = try_query(hdb, query);
1461     ok(r == ERROR_SUCCESS, "failed to create InstallExecuteSequence table\n");
1462
1463     sprintf(name, "#%ld", hdb);
1464     r = MsiOpenPackage(name, &hpack);
1465     ok(r == ERROR_INSTALL_PACKAGE_INVALID, "MsiOpenPackage returned wrong code\n");
1466     if (!r)    MsiCloseHandle(hpack);
1467     }
1468
1469     r = MsiCloseHandle(hdb);
1470     ok(r == ERROR_SUCCESS, "MsiCloseHandle(database) failed\n");
1471     DeleteFile(msifile);
1472 }
1473
1474 static void test_formatrecord2(void)
1475 {
1476     MSIHANDLE hpkg, hrec ;
1477     char buffer[0x100];
1478     DWORD sz;
1479     UINT r;
1480
1481     hpkg = package_from_db(create_package_db());
1482     ok( hpkg, "failed to create package\n");
1483
1484     r = MsiSetProperty(hpkg, "Manufacturer", " " );
1485     ok( r == ERROR_SUCCESS, "set property failed\n");
1486
1487     hrec = MsiCreateRecord(2);
1488     ok(hrec, "create record failed\n");
1489
1490     r = MsiRecordSetString( hrec, 0, "[ProgramFilesFolder][Manufacturer]\\asdf");
1491     ok( r == ERROR_SUCCESS, "format record failed\n");
1492
1493     buffer[0] = 0;
1494     sz = sizeof buffer;
1495     r = MsiFormatRecord( hpkg, hrec, buffer, &sz );
1496
1497     r = MsiRecordSetString(hrec, 0, "[foo][1]");
1498     r = MsiRecordSetString(hrec, 1, "hoo");
1499     sz = sizeof buffer;
1500     r = MsiFormatRecord(hpkg, hrec, buffer, &sz);
1501     ok( sz == 3, "size wrong\n");
1502     ok( 0 == strcmp(buffer,"hoo"), "wrong output %s\n",buffer);
1503     ok( r == ERROR_SUCCESS, "format failed\n");
1504
1505     r = MsiRecordSetString(hrec, 0, "x[~]x");
1506     sz = sizeof buffer;
1507     r = MsiFormatRecord(hpkg, hrec, buffer, &sz);
1508     ok( sz == 3, "size wrong\n");
1509     ok( 0 == strcmp(buffer,"x"), "wrong output %s\n",buffer);
1510     ok( r == ERROR_SUCCESS, "format failed\n");
1511
1512     r = MsiRecordSetString(hrec, 0, "[foo.$%}][1]");
1513     r = MsiRecordSetString(hrec, 1, "hoo");
1514     sz = sizeof buffer;
1515     r = MsiFormatRecord(hpkg, hrec, buffer, &sz);
1516     ok( sz == 3, "size wrong\n");
1517     ok( 0 == strcmp(buffer,"hoo"), "wrong output %s\n",buffer);
1518     ok( r == ERROR_SUCCESS, "format failed\n");
1519
1520     r = MsiRecordSetString(hrec, 0, "[\\[]");
1521     sz = sizeof buffer;
1522     r = MsiFormatRecord(hpkg, hrec, buffer, &sz);
1523     ok( sz == 1, "size wrong\n");
1524     ok( 0 == strcmp(buffer,"["), "wrong output %s\n",buffer);
1525     ok( r == ERROR_SUCCESS, "format failed\n");
1526
1527     SetEnvironmentVariable("FOO", "BAR");
1528     r = MsiRecordSetString(hrec, 0, "[%FOO]");
1529     sz = sizeof buffer;
1530     r = MsiFormatRecord(hpkg, hrec, buffer, &sz);
1531     ok( sz == 3, "size wrong\n");
1532     ok( 0 == strcmp(buffer,"BAR"), "wrong output %s\n",buffer);
1533     ok( r == ERROR_SUCCESS, "format failed\n");
1534
1535     r = MsiRecordSetString(hrec, 0, "[[1]]");
1536     r = MsiRecordSetString(hrec, 1, "%FOO");
1537     sz = sizeof buffer;
1538     r = MsiFormatRecord(hpkg, hrec, buffer, &sz);
1539     ok( sz == 3, "size wrong\n");
1540     ok( 0 == strcmp(buffer,"BAR"), "wrong output %s\n",buffer);
1541     ok( r == ERROR_SUCCESS, "format failed\n");
1542
1543     MsiCloseHandle( hrec );
1544     MsiCloseHandle( hpkg );
1545     DeleteFile(msifile);
1546 }
1547
1548 static void test_states(void)
1549 {
1550     MSIHANDLE hpkg;
1551     UINT r;
1552     MSIHANDLE hdb;
1553     INSTALLSTATE state, action;
1554
1555     hdb = create_package_db();
1556     ok ( hdb, "failed to create package database\n" );
1557
1558     r = add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'");
1559     ok( r == ERROR_SUCCESS, "cannot add directory: %d\n", r );
1560
1561     r = create_feature_table( hdb );
1562     ok( r == ERROR_SUCCESS, "cannot create Feature table: %d\n", r );
1563
1564     r = create_component_table( hdb );
1565     ok( r == ERROR_SUCCESS, "cannot create Component table: %d\n", r );
1566
1567     /* msidbFeatureAttributesFavorLocal */
1568     r = add_feature_entry( hdb, "'one', '', '', '', 2, 1, '', 0" );
1569     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
1570
1571     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesLocalOnly */
1572     r = add_component_entry( hdb, "'alpha', '{467EC132-739D-4784-A37B-677AA43DBC94}', 'TARGETDIR', 0, '', 'alpha_file'" );
1573     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
1574
1575     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSourceOnly */
1576     r = add_component_entry( hdb, "'beta', '{2C1F189C-24A6-4C34-B26B-994A6C026506}', 'TARGETDIR', 1, '', 'beta_file'" );
1577     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
1578
1579     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesOptional */
1580     r = add_component_entry( hdb, "'gamma', '{C271E2A4-DE2E-4F70-86D1-6984AF7DE2CA}', 'TARGETDIR', 2, '', 'gamma_file'" );
1581     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
1582
1583     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSharedDllRefCount */
1584     r = add_component_entry( hdb, "'theta', '{4EB3129D-81A8-48D5-9801-75600FED3DD9}', 'TARGETDIR', 8, '', 'theta_file'" );
1585     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
1586
1587     /* msidbFeatureAttributesFavorSource */
1588     r = add_feature_entry( hdb, "'two', '', '', '', 2, 1, '', 1" );
1589     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
1590
1591     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesLocalOnly */
1592     r = add_component_entry( hdb, "'delta', '{938FD4F2-C648-4259-A03C-7AA3B45643F3}', 'TARGETDIR', 0, '', 'delta_file'" );
1593     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
1594
1595     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSourceOnly */
1596     r = add_component_entry( hdb, "'epsilon', '{D59713B6-C11D-47F2-A395-1E5321781190}', 'TARGETDIR', 1, '', 'epsilon_file'" );
1597     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
1598
1599     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesOptional */
1600     r = add_component_entry( hdb, "'zeta', '{377D33AB-2FAA-42B9-A629-0C0DAE9B9C7A}', 'TARGETDIR', 2, '', 'zeta_file'" );
1601     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
1602
1603     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSharedDllRefCount */
1604     r = add_component_entry( hdb, "'iota', '{5D36F871-B5ED-4801-9E0F-C46B9E5C9669}', 'TARGETDIR', 8, '', 'iota_file'" );
1605     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
1606
1607     /* msidbFeatureAttributesFavorSource */
1608     r = add_feature_entry( hdb, "'three', '', '', '', 2, 1, '', 1" );
1609     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
1610
1611     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSourceOnly */
1612     r = add_component_entry( hdb, "'eta', '{DD89003F-0DD4-41B8-81C0-3411A7DA2695}', 'TARGETDIR', 1, '', 'eta_file'" );
1613     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
1614
1615     r = create_feature_components_table( hdb );
1616     ok( r == ERROR_SUCCESS, "cannot create FeatureComponents table: %d\n", r );
1617
1618     r = add_feature_components_entry( hdb, "'one', 'alpha'" );
1619     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
1620
1621     r = add_feature_components_entry( hdb, "'one', 'beta'" );
1622     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
1623
1624     r = add_feature_components_entry( hdb, "'one', 'gamma'" );
1625     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
1626
1627     r = add_feature_components_entry( hdb, "'one', 'theta'" );
1628     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
1629
1630     r = add_feature_components_entry( hdb, "'two', 'delta'" );
1631     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
1632
1633     r = add_feature_components_entry( hdb, "'two', 'epsilon'" );
1634     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
1635
1636     r = add_feature_components_entry( hdb, "'two', 'zeta'" );
1637     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
1638
1639     r = add_feature_components_entry( hdb, "'two', 'iota'" );
1640     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
1641
1642     r = add_feature_components_entry( hdb, "'three', 'eta'" );
1643     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
1644
1645     r = create_file_table( hdb );
1646     ok( r == ERROR_SUCCESS, "cannot create File table: %d\n", r );
1647
1648     r = add_file_entry( hdb, "'alpha_file', 'alpha', 'alpha.txt', 100, '', '1033', 8192, 1" );
1649     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
1650
1651     r = add_file_entry( hdb, "'beta_file', 'beta', 'beta.txt', 0, '', '1033', 8192, 1" );
1652     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
1653
1654     r = add_file_entry( hdb, "'gamma_file', 'gamma', 'gamma.txt', 0, '', '1033', 8192, 1" );
1655     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
1656
1657     r = add_file_entry( hdb, "'theta_file', 'theta', 'theta.txt', 0, '', '1033', 8192, 1" );
1658     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
1659
1660     r = add_file_entry( hdb, "'delta_file', 'delta', 'delta.txt', 0, '', '1033', 8192, 1" );
1661     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
1662
1663     r = add_file_entry( hdb, "'epsilon_file', 'epsilon', 'epsilon.txt', 0, '', '1033', 8192, 1" );
1664     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
1665
1666     r = add_file_entry( hdb, "'zeta_file', 'zeta', 'zeta.txt', 0, '', '1033', 8192, 1" );
1667     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
1668
1669     r = add_file_entry( hdb, "'iota_file', 'iota', 'iota.txt', 0, '', '1033', 8192, 1" );
1670     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
1671
1672     /* compressed file */
1673     r = add_file_entry( hdb, "'eta_file', 'eta', 'eta.txt', 0, '', '1033', 16384, 1" );
1674     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
1675
1676     hpkg = package_from_db( hdb );
1677     ok( hpkg, "failed to create package\n");
1678
1679     state = 0xdeadbee;
1680     action = 0xdeadbee;
1681     r = MsiGetFeatureState(hpkg, "one", &state, &action);
1682     ok( r == ERROR_UNKNOWN_FEATURE, "Expected ERROR_UNKNOWN_FEATURE, got %d\n", r );
1683     ok( state == 0xdeadbee, "Expected 0xdeadbee, got %d\n", state);
1684     ok( action == 0xdeadbee, "Expected 0xdeadbee, got %d\n", action);
1685
1686     state = 0xdeadbee;
1687     action = 0xdeadbee;
1688     r = MsiGetFeatureState(hpkg, "two", &state, &action);
1689     ok( r == ERROR_UNKNOWN_FEATURE, "Expected ERROR_UNKNOWN_FEATURE, got %d\n", r );
1690     ok( state == 0xdeadbee, "Expected 0xdeadbee, got %d\n", state);
1691     ok( action == 0xdeadbee, "Expected 0xdeadbee, got %d\n", action);
1692
1693     state = 0xdeadbee;
1694     action = 0xdeadbee;
1695     r = MsiGetFeatureState(hpkg, "three", &state, &action);
1696     ok( r == ERROR_UNKNOWN_FEATURE, "Expected ERROR_UNKNOWN_FEATURE, got %d\n", r );
1697     ok( state == 0xdeadbee, "Expected 0xdeadbee, got %d\n", state);
1698     ok( action == 0xdeadbee, "Expected 0xdeadbee, got %d\n", action);
1699
1700     state = 0xdeadbee;
1701     action = 0xdeadbee;
1702     r = MsiGetComponentState(hpkg, "alpha", &state, &action);
1703     ok( r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r );
1704     ok( state == 0xdeadbee, "Expected 0xdeadbee, got %d\n", state);
1705     ok( action == 0xdeadbee, "Expected 0xdeadbee, got %d\n", action);
1706
1707     state = 0xdeadbee;
1708     action = 0xdeadbee;
1709     r = MsiGetComponentState(hpkg, "beta", &state, &action);
1710     ok( r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r );
1711     ok( state == 0xdeadbee, "Expected 0xdeadbee, got %d\n", state);
1712     ok( action == 0xdeadbee, "Expected 0xdeadbee, got %d\n", action);
1713
1714     state = 0xdeadbee;
1715     action = 0xdeadbee;
1716     r = MsiGetComponentState(hpkg, "gamma", &state, &action);
1717     ok( r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r );
1718     ok( state == 0xdeadbee, "Expected 0xdeadbee, got %d\n", state);
1719     ok( action == 0xdeadbee, "Expected 0xdeadbee, got %d\n", action);
1720
1721     state = 0xdeadbee;
1722     action = 0xdeadbee;
1723     r = MsiGetComponentState(hpkg, "theta", &state, &action);
1724     ok( r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r );
1725     ok( state == 0xdeadbee, "Expected 0xdeadbee, got %d\n", state);
1726     ok( action == 0xdeadbee, "Expected 0xdeadbee, got %d\n", action);
1727
1728     state = 0xdeadbee;
1729     action = 0xdeadbee;
1730     r = MsiGetComponentState(hpkg, "delta", &state, &action);
1731     ok( r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r );
1732     ok( state == 0xdeadbee, "Expected 0xdeadbee, got %d\n", state);
1733     ok( action == 0xdeadbee, "Expected 0xdeadbee, got %d\n", action);
1734
1735     state = 0xdeadbee;
1736     action = 0xdeadbee;
1737     r = MsiGetComponentState(hpkg, "epsilon", &state, &action);
1738     ok( r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r );
1739     ok( state == 0xdeadbee, "Expected 0xdeadbee, got %d\n", state);
1740     ok( action == 0xdeadbee, "Expected 0xdeadbee, got %d\n", action);
1741
1742     state = 0xdeadbee;
1743     action = 0xdeadbee;
1744     r = MsiGetComponentState(hpkg, "zeta", &state, &action);
1745     ok( r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r );
1746     ok( state == 0xdeadbee, "Expected 0xdeadbee, got %d\n", state);
1747     ok( action == 0xdeadbee, "Expected 0xdeadbee, got %d\n", action);
1748
1749     state = 0xdeadbee;
1750     action = 0xdeadbee;
1751     r = MsiGetComponentState(hpkg, "iota", &state, &action);
1752     ok( r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r );
1753     ok( state == 0xdeadbee, "Expected 0xdeadbee, got %d\n", state);
1754     ok( action == 0xdeadbee, "Expected 0xdeadbee, got %d\n", action);
1755
1756     state = 0xdeadbee;
1757     action = 0xdeadbee;
1758     r = MsiGetComponentState(hpkg, "eta", &state, &action);
1759     ok( r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r );
1760     ok( state == 0xdeadbee, "Expected 0xdeadbee, got %d\n", state);
1761     ok( action == 0xdeadbee, "Expected 0xdeadbee, got %d\n", action);
1762
1763     r = MsiDoAction( hpkg, "CostInitialize");
1764     ok( r == ERROR_SUCCESS, "cost init failed\n");
1765
1766     state = 0xdeadbee;
1767     action = 0xdeadbee;
1768     r = MsiGetFeatureState(hpkg, "one", &state, &action);
1769     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
1770     todo_wine
1771     {
1772         ok( state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1773     }
1774     ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
1775
1776     state = 0xdeadbee;
1777     action = 0xdeadbee;
1778     r = MsiGetFeatureState(hpkg, "two", &state, &action);
1779     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
1780     todo_wine
1781     {
1782         ok( state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1783     }
1784     ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
1785
1786     state = 0xdeadbee;
1787     action = 0xdeadbee;
1788     r = MsiGetFeatureState(hpkg, "three", &state, &action);
1789     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
1790     todo_wine
1791     {
1792         ok( state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1793     }
1794     ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
1795
1796     state = 0xdeadbee;
1797     action = 0xdeadbee;
1798     r = MsiGetComponentState(hpkg, "alpha", &state, &action);
1799     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
1800     todo_wine
1801     {
1802         ok( state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1803         ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
1804     }
1805
1806     state = 0xdeadbee;
1807     action = 0xdeadbee;
1808     r = MsiGetComponentState(hpkg, "beta", &state, &action);
1809     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
1810     todo_wine
1811     {
1812         ok( state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1813         ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
1814     }
1815
1816     state = 0xdeadbee;
1817     action = 0xdeadbee;
1818     r = MsiGetComponentState(hpkg, "gamma", &state, &action);
1819     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
1820     todo_wine
1821     {
1822         ok( state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1823         ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
1824     }
1825
1826     state = 0xdeadbee;
1827     action = 0xdeadbee;
1828     r = MsiGetComponentState(hpkg, "theta", &state, &action);
1829     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
1830     todo_wine
1831     {
1832         ok( state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1833         ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
1834     }
1835
1836     state = 0xdeadbee;
1837     action = 0xdeadbee;
1838     r = MsiGetComponentState(hpkg, "delta", &state, &action);
1839     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
1840     todo_wine
1841     {
1842         ok( state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1843         ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
1844     }
1845
1846     state = 0xdeadbee;
1847     action = 0xdeadbee;
1848     r = MsiGetComponentState(hpkg, "epsilon", &state, &action);
1849     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
1850     todo_wine
1851     {
1852         ok( state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1853         ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
1854     }
1855
1856     state = 0xdeadbee;
1857     action = 0xdeadbee;
1858     r = MsiGetComponentState(hpkg, "zeta", &state, &action);
1859     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
1860     todo_wine
1861     {
1862         ok( state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1863         ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
1864     }
1865
1866     state = 0xdeadbee;
1867     action = 0xdeadbee;
1868     r = MsiGetComponentState(hpkg, "iota", &state, &action);
1869     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
1870     todo_wine
1871     {
1872         ok( state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1873         ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
1874     }
1875
1876     state = 0xdeadbee;
1877     action = 0xdeadbee;
1878     r = MsiGetComponentState(hpkg, "eta", &state, &action);
1879     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
1880     todo_wine
1881     {
1882         ok( state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1883         ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
1884     }
1885
1886     r = MsiDoAction( hpkg, "FileCost");
1887     ok( r == ERROR_SUCCESS, "file cost failed\n");
1888
1889     state = 0xdeadbee;
1890     action = 0xdeadbee;
1891     r = MsiGetFeatureState(hpkg, "one", &state, &action);
1892     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
1893     todo_wine
1894     {
1895         ok( state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1896     }
1897     ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
1898
1899     state = 0xdeadbee;
1900     action = 0xdeadbee;
1901     r = MsiGetFeatureState(hpkg, "two", &state, &action);
1902     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
1903     todo_wine
1904     {
1905         ok( state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1906     }
1907     ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
1908
1909     state = 0xdeadbee;
1910     action = 0xdeadbee;
1911     r = MsiGetFeatureState(hpkg, "three", &state, &action);
1912     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
1913     todo_wine
1914     {
1915         ok( state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1916     }
1917     ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
1918
1919     state = 0xdeadbee;
1920     action = 0xdeadbee;
1921     r = MsiGetComponentState(hpkg, "alpha", &state, &action);
1922     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
1923     todo_wine
1924     {
1925         ok( state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1926         ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
1927     }
1928
1929     state = 0xdeadbee;
1930     action = 0xdeadbee;
1931     r = MsiGetComponentState(hpkg, "beta", &state, &action);
1932     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
1933     todo_wine
1934     {
1935         ok( state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1936         ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
1937     }
1938
1939     state = 0xdeadbee;
1940     action = 0xdeadbee;
1941     r = MsiGetComponentState(hpkg, "gamma", &state, &action);
1942     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
1943     todo_wine
1944     {
1945         ok( state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1946         ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
1947     }
1948
1949     state = 0xdeadbee;
1950     action = 0xdeadbee;
1951     r = MsiGetComponentState(hpkg, "theta", &state, &action);
1952     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
1953     todo_wine
1954     {
1955         ok( state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1956         ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
1957     }
1958
1959     state = 0xdeadbee;
1960     action = 0xdeadbee;
1961     r = MsiGetComponentState(hpkg, "delta", &state, &action);
1962     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
1963     todo_wine
1964     {
1965         ok( state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1966         ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
1967     }
1968
1969     state = 0xdeadbee;
1970     action = 0xdeadbee;
1971     r = MsiGetComponentState(hpkg, "epsilon", &state, &action);
1972     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
1973     todo_wine
1974     {
1975         ok( state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1976         ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
1977     }
1978
1979     state = 0xdeadbee;
1980     action = 0xdeadbee;
1981     r = MsiGetComponentState(hpkg, "zeta", &state, &action);
1982     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
1983     todo_wine
1984     {
1985         ok( state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1986         ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
1987     }
1988
1989     state = 0xdeadbee;
1990     action = 0xdeadbee;
1991     r = MsiGetComponentState(hpkg, "iota", &state, &action);
1992     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
1993     todo_wine
1994     {
1995         ok( state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1996         ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
1997     }
1998
1999     state = 0xdeadbee;
2000     action = 0xdeadbee;
2001     r = MsiGetComponentState(hpkg, "eta", &state, &action);
2002     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
2003     todo_wine
2004     {
2005         ok( state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2006         ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
2007     }
2008
2009     r = MsiDoAction( hpkg, "CostFinalize");
2010     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
2011
2012     state = 0xdeadbee;
2013     action = 0xdeadbee;
2014     r = MsiGetFeatureState(hpkg, "one", &state, &action);
2015     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
2016     ok( state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2017     ok( action == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", action);
2018
2019     state = 0xdeadbee;
2020     action = 0xdeadbee;
2021     r = MsiGetFeatureState(hpkg, "two", &state, &action);
2022     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
2023     ok( state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2024     ok( action == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", action);
2025
2026     state = 0xdeadbee;
2027     action = 0xdeadbee;
2028     r = MsiGetFeatureState(hpkg, "three", &state, &action);
2029     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
2030     ok( state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2031     ok( action == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", action);
2032
2033     state = 0xdeadbee;
2034     action = 0xdeadbee;
2035     r = MsiGetComponentState(hpkg, "alpha", &state, &action);
2036     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
2037     ok( state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2038     ok( action == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", action);
2039
2040     state = 0xdeadbee;
2041     action = 0xdeadbee;
2042     r = MsiGetComponentState(hpkg, "beta", &state, &action);
2043     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
2044     ok( state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2045     ok( action == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", action);
2046
2047     state = 0xdeadbee;
2048     action = 0xdeadbee;
2049     r = MsiGetComponentState(hpkg, "gamma", &state, &action);
2050     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
2051     ok( state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2052     ok( action == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", action);
2053
2054     state = 0xdeadbee;
2055     action = 0xdeadbee;
2056     r = MsiGetComponentState(hpkg, "theta", &state, &action);
2057     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
2058     ok( state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2059     ok( action == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", action);
2060
2061     state = 0xdeadbee;
2062     action = 0xdeadbee;
2063     r = MsiGetComponentState(hpkg, "delta", &state, &action);
2064     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
2065     ok( state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2066     ok( action == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", action);
2067
2068     state = 0xdeadbee;
2069     action = 0xdeadbee;
2070     r = MsiGetComponentState(hpkg, "epsilon", &state, &action);
2071     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
2072     ok( state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2073     ok( action == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", action);
2074
2075     state = 0xdeadbee;
2076     action = 0xdeadbee;
2077     r = MsiGetComponentState(hpkg, "zeta", &state, &action);
2078     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
2079     ok( state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2080     ok( action == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", action);
2081
2082     state = 0xdeadbee;
2083     action = 0xdeadbee;
2084     r = MsiGetComponentState(hpkg, "iota", &state, &action);
2085     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
2086     ok( state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2087     ok( action == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", action);
2088
2089     state = 0xdeadbee;
2090     action = 0xdeadbee;
2091     r = MsiGetComponentState(hpkg, "eta", &state, &action);
2092     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
2093     ok( state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2094     ok( action == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", action);
2095     
2096     MsiCloseHandle( hpkg );
2097 }
2098
2099 static void test_getproperty(void)
2100 {
2101     MSIHANDLE hPackage = 0;
2102     char prop[100];
2103     static CHAR empty[] = "";
2104     DWORD size;
2105     UINT r;
2106
2107     hPackage = package_from_db(create_package_db());
2108     ok( hPackage != 0, " Failed to create package\n");
2109
2110     /* set the property */
2111     r = MsiSetProperty(hPackage, "Name", "Value");
2112     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2113
2114     /* retrieve the size, NULL pointer */
2115     size = 0;
2116     r = MsiGetProperty(hPackage, "Name", NULL, &size);
2117     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2118     ok( size == 5, "Expected 5, got %ld\n", size);
2119
2120     /* retrieve the size, empty string */
2121     size = 0;
2122     r = MsiGetProperty(hPackage, "Name", empty, &size);
2123     ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
2124     ok( size == 5, "Expected 5, got %ld\n", size);
2125
2126     /* don't change size */
2127     r = MsiGetProperty(hPackage, "Name", prop, &size);
2128     ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
2129     ok( size == 5, "Expected 5, got %ld\n", size);
2130     ok( !lstrcmp(prop, "Valu"), "Expected Valu, got %s\n", prop);
2131
2132     /* increase the size by 1 */
2133     size++;
2134     r = MsiGetProperty(hPackage, "Name", prop, &size);
2135     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2136     ok( size == 5, "Expected 5, got %ld\n", size);
2137     ok( !lstrcmp(prop, "Value"), "Expected Value, got %s\n", prop);
2138
2139     r = MsiCloseHandle( hPackage);
2140     ok( r == ERROR_SUCCESS , "Failed to close package\n" );
2141     DeleteFile(msifile);
2142 }
2143
2144 static void test_removefiles(void)
2145 {
2146     MSIHANDLE hpkg;
2147     UINT r;
2148     MSIHANDLE hdb;
2149     char CURR_DIR[MAX_PATH];
2150
2151     GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
2152
2153     hdb = create_package_db();
2154     ok ( hdb, "failed to create package database\n" );
2155
2156     r = add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'");
2157     ok( r == ERROR_SUCCESS, "cannot add directory: %d\n", r );
2158
2159     r = create_feature_table( hdb );
2160     ok( r == ERROR_SUCCESS, "cannot create Feature table: %d\n", r );
2161
2162     r = create_component_table( hdb );
2163     ok( r == ERROR_SUCCESS, "cannot create Component table: %d\n", r );
2164
2165     r = add_feature_entry( hdb, "'one', '', '', '', 2, 1, '', 0" );
2166     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
2167
2168     r = add_component_entry( hdb, "'hydrogen', '', 'TARGETDIR', 0, '', 'hydrogen_file'" );
2169     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2170
2171     r = add_component_entry( hdb, "'helium', '', 'TARGETDIR', 0, '', 'helium_file'" );
2172     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2173
2174     r = add_component_entry( hdb, "'lithium', '', 'TARGETDIR', 0, '', 'lithium_file'" );
2175     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2176
2177     r = add_component_entry( hdb, "'beryllium', '', 'TARGETDIR', 0, '', 'beryllium_file'" );
2178     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2179
2180     r = add_component_entry( hdb, "'boron', '', 'TARGETDIR', 0, '', 'boron_file'" );
2181     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2182
2183     r = add_component_entry( hdb, "'carbon', '', 'TARGETDIR', 0, '', 'carbon_file'" );
2184     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
2185
2186     r = create_feature_components_table( hdb );
2187     ok( r == ERROR_SUCCESS, "cannot create FeatureComponents table: %d\n", r );
2188
2189     r = add_feature_components_entry( hdb, "'one', 'hydrogen'" );
2190     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
2191
2192     r = add_feature_components_entry( hdb, "'one', 'helium'" );
2193     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
2194
2195     r = add_feature_components_entry( hdb, "'one', 'lithium'" );
2196     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
2197
2198     r = add_feature_components_entry( hdb, "'one', 'beryllium'" );
2199     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
2200
2201     r = add_feature_components_entry( hdb, "'one', 'boron'" );
2202     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
2203
2204     r = add_feature_components_entry( hdb, "'one', 'carbon'" );
2205     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
2206
2207     r = create_file_table( hdb );
2208     ok( r == ERROR_SUCCESS, "cannot create File table: %d\n", r );
2209
2210     r = add_file_entry( hdb, "'hydrogen_file', 'hydrogen', 'hydrogen.txt', 0, '', '1033', 8192, 1" );
2211     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
2212
2213     r = add_file_entry( hdb, "'helium_file', 'helium', 'helium.txt', 0, '', '1033', 8192, 1" );
2214     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
2215
2216     r = add_file_entry( hdb, "'lithium_file', 'lithium', 'lithium.txt', 0, '', '1033', 8192, 1" );
2217     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
2218
2219     r = add_file_entry( hdb, "'beryllium_file', 'beryllium', 'beryllium.txt', 0, '', '1033', 16384, 1" );
2220     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
2221
2222     r = add_file_entry( hdb, "'boron_file', 'boron', 'boron.txt', 0, '', '1033', 16384, 1" );
2223     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
2224
2225     r = add_file_entry( hdb, "'carbon_file', 'carbon', 'carbon.txt', 0, '', '1033', 16384, 1" );
2226     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
2227
2228     r = create_remove_file_table( hdb );
2229     ok( r == ERROR_SUCCESS, "cannot create Remove File table: %d\n", r);
2230
2231     hpkg = package_from_db( hdb );
2232     ok( hpkg, "failed to create package\n");
2233
2234     create_test_file( "hydrogen.txt" );
2235     create_test_file( "helium.txt" );
2236     create_test_file( "lithium.txt" );
2237     create_test_file( "beryllium.txt" );
2238     create_test_file( "boron.txt" );
2239     create_test_file( "carbon.txt" );
2240
2241     r = MsiSetProperty( hpkg, "TARGETDIR", CURR_DIR );
2242     ok( r == ERROR_SUCCESS, "set property failed\n");
2243
2244     r = MsiDoAction( hpkg, "CostInitialize");
2245     ok( r == ERROR_SUCCESS, "cost init failed\n");
2246
2247     r = MsiDoAction( hpkg, "FileCost");
2248     ok( r == ERROR_SUCCESS, "cost finalize failed\n");
2249
2250     r = MsiDoAction( hpkg, "CostFinalize");
2251     ok( r == ERROR_SUCCESS, "cost finalize failed\n");
2252
2253     r = MsiDoAction( hpkg, "InstallValidate");
2254     ok( r == ERROR_SUCCESS, "cost finalize failed\n");
2255
2256     r = MsiSetComponentState( hpkg, "hydrogen", INSTALLSTATE_ABSENT );
2257     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
2258
2259     r = MsiSetComponentState( hpkg, "helium", INSTALLSTATE_LOCAL );
2260     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
2261
2262     r = MsiSetComponentState( hpkg, "lithium", INSTALLSTATE_SOURCE );
2263     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
2264
2265     r = MsiSetComponentState( hpkg, "beryllium", INSTALLSTATE_ABSENT );
2266     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
2267
2268     r = MsiSetComponentState( hpkg, "boron", INSTALLSTATE_LOCAL );
2269     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
2270
2271     r = MsiSetComponentState( hpkg, "carbon", INSTALLSTATE_SOURCE );
2272     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
2273
2274     r = MsiDoAction( hpkg, "RemoveFiles");
2275     ok( r == ERROR_SUCCESS, "remove files failed\n");
2276
2277     ok(DeleteFileA("hydrogen.txt"), "Expected hydrogen.txt to exist\n");
2278     ok(DeleteFileA("lithium.txt"), "Expected lithium.txt to exist\n");    
2279     ok(DeleteFileA("beryllium.txt"), "Expected beryllium.txt to exist\n");
2280     ok(DeleteFileA("carbon.txt"), "Expected carbon.txt to exist\n");
2281     ok(DeleteFileA("helium.txt"), "Expected helium.txt to exist\n");
2282     ok(DeleteFileA("boron.txt"), "Expected boron.txt to exist\n");
2283
2284     MsiCloseHandle( hpkg );
2285     DeleteFileA(msifile);
2286 }
2287
2288 static void test_appsearch(void)
2289 {
2290     MSIHANDLE hpkg;
2291     UINT r;
2292     MSIHANDLE hdb;
2293     CHAR prop[MAX_PATH];
2294     DWORD size = MAX_PATH;
2295
2296     hdb = create_package_db();
2297     ok ( hdb, "failed to create package database\n" );
2298
2299     r = create_appsearch_table( hdb );
2300     ok( r == ERROR_SUCCESS, "cannot create AppSearch table: %d\n", r );
2301
2302     r = add_appsearch_entry( hdb, "'WEBBROWSERPROG', 'NewSignature1'" );
2303     ok( r == ERROR_SUCCESS, "cannot add entry: %d\n", r );
2304
2305     r = create_reglocator_table( hdb );
2306     ok( r == ERROR_SUCCESS, "cannot create RegLocator table: %d\n", r );
2307
2308     r = add_reglocator_entry( hdb, "'NewSignature1', 0, 'htmlfile\\shell\\open\\command', '', 1" );
2309     ok( r == ERROR_SUCCESS, "cannot create RegLocator table: %d\n", r );
2310
2311     r = create_signature_table( hdb );
2312     ok( r == ERROR_SUCCESS, "cannot create Signature table: %d\n", r );
2313
2314     r = add_signature_entry( hdb, "'NewSignature1', 'FileName', '', '', '', '', '', '', ''" );
2315     ok( r == ERROR_SUCCESS, "cannot create Signature table: %d\n", r );
2316
2317     hpkg = package_from_db( hdb );
2318     ok( hpkg, "failed to create package\n");
2319
2320     r = MsiDoAction( hpkg, "AppSearch" );
2321     ok( r == ERROR_SUCCESS, "AppSearch failed: %d\n", r);
2322
2323     r = MsiGetPropertyA( hpkg, "WEBBROWSERPROG", prop, &size );
2324     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2325     todo_wine
2326     {
2327         ok( lstrlenA(prop) != 0, "Expected non-zero length\n");
2328     }
2329
2330     MsiCloseHandle( hpkg );
2331     DeleteFileA(msifile);
2332 }
2333
2334 START_TEST(package)
2335 {
2336     test_createpackage();
2337     test_getsourcepath_bad();
2338     test_getsourcepath();
2339     test_doaction();
2340     test_gettargetpath_bad();
2341     test_settargetpath();
2342     test_props();
2343     test_condition();
2344     test_msipackage();
2345     test_formatrecord2();
2346     test_states();
2347     test_getproperty();
2348     test_removefiles();
2349     test_appsearch();
2350 }