update msi wine regtest
authorGed Murphy <gedmurphy@reactos.org>
Wed, 30 Aug 2006 20:37:49 +0000 (20:37 +0000)
committerGed Murphy <gedmurphy@reactos.org>
Wed, 30 Aug 2006 20:37:49 +0000 (20:37 +0000)
svn path=/trunk/; revision=23821

reactos/regtests/winetests/msi/db.c
reactos/regtests/winetests/msi/format.c
reactos/regtests/winetests/msi/install.c
reactos/regtests/winetests/msi/package.c

index 3143f0f..86edc32 100644 (file)
@@ -458,7 +458,7 @@ static void test_msibadqueries(void)
     ok(r == TRUE, "file didn't exist after commit\n");
 }
 
-static UINT run_query( MSIHANDLE hdb, const char *query )
+static UINT run_query( MSIHANDLE hdb, MSIHANDLE hrec, const char *query )
 {
     MSIHANDLE hview = 0;
     UINT r;
@@ -467,7 +467,7 @@ static UINT run_query( MSIHANDLE hdb, const char *query )
     if( r != ERROR_SUCCESS )
         return r;
 
-    r = MsiViewExecute(hview, 0);
+    r = MsiViewExecute(hview, hrec);
     if( r == ERROR_SUCCESS )
         r = MsiViewClose(hview);
     MsiCloseHandle(hview);
@@ -491,7 +491,7 @@ static void test_viewmodify(void)
     query = "CREATE TABLE `phone` ( "
             "`id` INT, `name` CHAR(32), `number` CHAR(32) "
             "PRIMARY KEY `id`)";
-    r = run_query( hdb, query );
+    r = run_query( hdb, 0, query );
     ok(r == ERROR_SUCCESS, "query failed\n");
 
     /* check what the error function reports without doing anything */
@@ -718,7 +718,7 @@ static UINT get_columns_table_type(MSIHANDLE hdb, const char *table, UINT field)
     return type;
 }
 
-static BOOL check_record( MSIHANDLE rec, UINT field, LPSTR val )
+static BOOL check_record( MSIHANDLE rec, UINT field, LPCSTR val )
 {
     CHAR buffer[0x20];
     UINT r;
@@ -737,7 +737,7 @@ static void test_viewgetcolumninfo(void)
     hdb = create_db();
     ok( hdb, "failed to create db\n");
 
-    r = run_query( hdb,
+    r = run_query( hdb, 0,
             "CREATE TABLE `Properties` "
             "( `Property` CHAR(255), `Value` CHAR(1)  PRIMARY KEY `Property`)" );
     ok( r == ERROR_SUCCESS , "Failed to create table\n" );
@@ -764,7 +764,7 @@ static void test_viewgetcolumninfo(void)
 
     MsiCloseHandle( rec );
 
-    r = run_query( hdb,
+    r = run_query( hdb, 0,
             "CREATE TABLE `Binary` "
             "( `Name` CHAR(255), `Data` OBJECT  PRIMARY KEY `Name`)" );
     ok( r == ERROR_SUCCESS , "Failed to create table\n" );
@@ -790,7 +790,7 @@ static void test_viewgetcolumninfo(void)
     ok( check_record( rec, 2, "Data"), "wrong record type\n");
     MsiCloseHandle( rec );
 
-    r = run_query( hdb,
+    r = run_query( hdb, 0,
             "CREATE TABLE `UIText` "
             "( `Key` CHAR(72) NOT NULL, `Text` CHAR(255) LOCALIZABLE PRIMARY KEY `Key`)" );
     ok( r == ERROR_SUCCESS , "Failed to create table\n" );
@@ -958,7 +958,7 @@ static void test_streamtable(void)
     hdb = create_db();
     ok( hdb, "failed to create db\n");
 
-    r = run_query( hdb,
+    r = run_query( hdb, 0,
             "CREATE TABLE `Properties` "
             "( `Property` CHAR(255), `Value` CHAR(1)  PRIMARY KEY `Property`)" );
     ok( r == ERROR_SUCCESS , "Failed to create table\n" );
@@ -997,7 +997,7 @@ static void test_where(void)
     hdb = create_db();
     ok( hdb, "failed to create db\n");
 
-    r = run_query( hdb,
+    r = run_query( hdb, 0,
             "CREATE TABLE `Media` ("
             "`DiskId` SHORT NOT NULL, "
             "`LastSequence` LONG, "
@@ -1008,17 +1008,17 @@ static void test_where(void)
             "PRIMARY KEY `DiskId`)" );
     ok( r == S_OK, "cannot create Media table: %d\n", r );
 
-    r = run_query( hdb, "INSERT INTO `Media` "
+    r = run_query( hdb, 0, "INSERT INTO `Media` "
             "( `DiskId`, `LastSequence`, `DiskPrompt`, `Cabinet`, `VolumeLabel`, `Source` ) "
             "VALUES ( 1, 0, '', 'zero.cab', '', '' )" );
     ok( r == S_OK, "cannot add file to the Media table: %d\n", r );
 
-    r = run_query( hdb, "INSERT INTO `Media` "
+    r = run_query( hdb, 0, "INSERT INTO `Media` "
             "( `DiskId`, `LastSequence`, `DiskPrompt`, `Cabinet`, `VolumeLabel`, `Source` ) "
             "VALUES ( 2, 1, '', 'one.cab', '', '' )" );
     ok( r == S_OK, "cannot add file to the Media table: %d\n", r );
 
-    r = run_query( hdb, "INSERT INTO `Media` "
+    r = run_query( hdb, 0, "INSERT INTO `Media` "
             "( `DiskId`, `LastSequence`, `DiskPrompt`, `Cabinet`, `VolumeLabel`, `Source` ) "
             "VALUES ( 3, 2, '', 'two.cab', '', '' )" );
     ok( r == S_OK, "cannot add file to the Media table: %d\n", r );
@@ -1045,6 +1045,320 @@ static void test_where(void)
     DeleteFile(msifile);
 }
 
+static CHAR CURR_DIR[MAX_PATH];
+
+static const CHAR test_data[] = "FirstPrimaryColumn\tSecondPrimaryColumn\tShortInt\tShortIntNullable\tLongInt\tLongIntNullable\tString\tLocalizableString\tLocalizableStringNullable\n"
+                                "s255\ti2\ti2\tI2\ti4\tI4\tS255\tS0\ts0\n"
+                                "TestTable\tFirstPrimaryColumn\n"
+                                "stringage\t5\t2\t\t2147483640\t-2147483640\tanother string\tlocalizable\tduh\n";
+
+static void write_file(const CHAR *filename, const char *data, int data_size)
+{
+    DWORD size;
+
+    HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
+                           CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+
+    WriteFile(hf, data, data_size, &size, NULL);
+    CloseHandle(hf);
+}
+
+static UINT add_table_to_db(MSIHANDLE hdb, LPCSTR table_data)
+{
+    UINT r;
+
+    write_file("temp_file", table_data, (lstrlen(table_data) - 1) * sizeof(char));
+    r = MsiDatabaseImportA(hdb, CURR_DIR, "temp_file");
+    DeleteFileA("temp_file");
+
+    return r;
+}
+
+static void test_msiimport(void)
+{
+    MSIHANDLE hdb, view, rec;
+    LPCSTR query;
+    UINT r, count;
+    signed int i;
+
+    GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
+
+    r = MsiOpenDatabaseA(msifile, MSIDBOPEN_CREATE, &hdb);
+    ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
+
+    r = add_table_to_db(hdb, test_data);
+    todo_wine
+    {
+        ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
+    }
+
+    query = "SELECT * FROM `TestTable`";
+    r = MsiDatabaseOpenView(hdb, query, &view);
+    todo_wine
+    {
+        ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
+    }
+
+    r = MsiViewGetColumnInfo(view, MSICOLINFO_NAMES, &rec);
+    count = MsiRecordGetFieldCount(rec);
+    todo_wine
+    {
+        ok(count == 9, "Expected 9, got %d\n", count);
+        ok(check_record(rec, 1, "FirstPrimaryColumn"), "Expected FirstPrimaryColumn\n");
+        ok(check_record(rec, 2, "SecondPrimaryColumn"), "Expected SecondPrimaryColumn\n");
+        ok(check_record(rec, 3, "ShortInt"), "Expected ShortInt\n");
+        ok(check_record(rec, 4, "ShortIntNullable"), "Expected ShortIntNullalble\n");
+        ok(check_record(rec, 5, "LongInt"), "Expected LongInt\n");
+        ok(check_record(rec, 6, "LongIntNullable"), "Expected LongIntNullalble\n");
+        ok(check_record(rec, 7, "String"), "Expected String\n");
+        ok(check_record(rec, 8, "LocalizableString"), "Expected LocalizableString\n");
+        ok(check_record(rec, 9, "LocalizableStringNullable"), "Expected LocalizableStringNullable\n");
+    }
+
+    r = MsiViewGetColumnInfo(view, MSICOLINFO_TYPES, &rec);
+    count = MsiRecordGetFieldCount(rec);
+    todo_wine
+    {
+        ok(count == 9, "Expected 9, got %d\n", count);
+        ok(check_record(rec, 1, "s255"), "Expected s255\n");
+        ok(check_record(rec, 2, "i2"), "Expected i2\n");
+        ok(check_record(rec, 3, "i2"), "Expected i2\n");
+        ok(check_record(rec, 4, "I2"), "Expected I2\n");
+        ok(check_record(rec, 5, "i4"), "Expected i4\n");
+        ok(check_record(rec, 6, "I4"), "Expected I4\n");
+        ok(check_record(rec, 7, "S255"), "Expected S255\n");
+        ok(check_record(rec, 8, "S0"), "Expected S0\n");
+        ok(check_record(rec, 9, "s0"), "Expected s0\n");
+    }
+
+    query = "SELECT * FROM `TestTable`";
+    r = do_query(hdb, query, &rec);
+    todo_wine
+    {
+        ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
+    }
+
+    todo_wine
+    {
+        ok(check_record(rec, 1, "stringage"), "Expected 'stringage'\n");
+        ok(check_record(rec, 7, "another string"), "Expected 'another string'\n");
+        ok(check_record(rec, 8, "localizable"), "Expected 'localizable'\n");
+        ok(check_record(rec, 9, "duh"), "Expected 'duh'\n");
+    }
+
+    i = MsiRecordGetInteger(rec, 2);
+    todo_wine
+    {
+        ok(i == 5, "Expected 5, got %d\n", i);
+    }
+
+    i = MsiRecordGetInteger(rec, 3);
+    todo_wine
+    {
+        ok(i == 2, "Expected 2, got %d\n", i);
+    }
+
+    i = MsiRecordGetInteger(rec, 4);
+    ok(i == 0x80000000, "Expected 0x80000000, got %d\n", i);
+
+    i = MsiRecordGetInteger(rec, 5);
+    todo_wine
+    {
+        ok(i == 2147483640, "Expected 2147483640, got %d\n", i);
+    }
+
+    i = MsiRecordGetInteger(rec, 6);
+    todo_wine
+    {
+        ok(i == -2147483640, "Expected -2147483640, got %d\n", i);
+    }
+
+    MsiCloseHandle(rec);
+    MsiCloseHandle(view);
+    MsiCloseHandle(hdb);
+    DeleteFileA(msifile);
+}
+
+static void test_markers(void)
+{
+    MSIHANDLE hdb, rec;
+    LPCSTR query;
+    UINT r;
+
+    hdb = create_db();
+    ok( hdb, "failed to create db\n");
+
+    rec = MsiCreateRecord(3);
+    MsiRecordSetString(rec, 1, "Table");
+    MsiRecordSetString(rec, 2, "Apples");
+    MsiRecordSetString(rec, 3, "Oranges");
+
+    /* try a legit create */
+    query = "CREATE TABLE `Table` ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
+    r = run_query(hdb, 0, query);
+    ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
+    MsiCloseHandle(rec);
+
+    /* try table name as marker */
+    rec = MsiCreateRecord(1);
+    MsiRecordSetString(rec, 1, "Fable");
+    query = "CREATE TABLE `?` ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
+    r = run_query(hdb, rec, query);
+    ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
+
+    /* try table name as marker without backticks */
+    MsiRecordSetString(rec, 1, "Mable");
+    query = "CREATE TABLE ? ( `One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
+    r = run_query(hdb, rec, query);
+    ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
+
+    /* try one column name as marker */
+    MsiRecordSetString(rec, 1, "One");
+    query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`)";
+    r = run_query(hdb, rec, query);
+    ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
+
+    /* try column names as markers */
+    MsiCloseHandle(rec);
+    rec = MsiCreateRecord(2);
+    MsiRecordSetString(rec, 1, "One");
+    MsiRecordSetString(rec, 2, "Two");
+    query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `One`)";
+    r = run_query(hdb, rec, query);
+    ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
+
+    /* try names with backticks */
+    MsiCloseHandle(rec);
+    rec = MsiCreateRecord(3);
+    MsiRecordSetString(rec, 1, "One");
+    MsiRecordSetString(rec, 2, "Two");
+    MsiRecordSetString(rec, 3, "One");
+    query = "CREATE TABLE `Mable` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `?`)";
+    r = run_query(hdb, rec, query);
+    todo_wine
+    {
+        ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
+    }
+
+    /* try names with backticks, minus definitions */
+    query = "CREATE TABLE `Mable` ( `?`, `?` PRIMARY KEY `?`)";
+    r = run_query(hdb, rec, query);
+    ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
+
+    /* try names without backticks */
+    query = "CREATE TABLE `Mable` ( ? SHORT NOT NULL, ? CHAR(255) PRIMARY KEY ?)";
+    r = run_query(hdb, rec, query);
+    ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
+
+    /* try one long marker */
+    MsiCloseHandle(rec);
+    rec = MsiCreateRecord(1);
+    MsiRecordSetString(rec, 1, "`One` SHORT NOT NULL, `Two` CHAR(255) PRIMARY KEY `One`");
+    query = "CREATE TABLE `Mable` ( ? )";
+    r = run_query(hdb, rec, query);
+    ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
+
+    /* try all names as markers */
+    MsiCloseHandle(rec);
+    rec = MsiCreateRecord(4);
+    MsiRecordSetString(rec, 1, "Mable");
+    MsiRecordSetString(rec, 2, "One");
+    MsiRecordSetString(rec, 3, "Two");
+    MsiRecordSetString(rec, 4, "One");
+    query = "CREATE TABLE `?` ( `?` SHORT NOT NULL, `?` CHAR(255) PRIMARY KEY `?`)";
+    r = run_query(hdb, rec, query);
+    ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
+
+    /* try a legit insert */
+    query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( 5, 'hello' )";
+    r = run_query(hdb, 0, query);
+    ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
+
+    /* try values as markers */
+    MsiCloseHandle(rec);
+    rec = MsiCreateRecord(2);
+    MsiRecordSetInteger(rec, 1, 4);
+    MsiRecordSetString(rec, 2, "hi");
+    query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, '?' )";
+    r = run_query(hdb, rec, query);
+    ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
+
+    /* try column names and values as markers */
+    MsiCloseHandle(rec);
+    rec = MsiCreateRecord(4);
+    MsiRecordSetString(rec, 1, "One");
+    MsiRecordSetString(rec, 2, "Two");
+    MsiRecordSetInteger(rec, 3, 5);
+    MsiRecordSetString(rec, 4, "hi");
+    query = "INSERT INTO `Table` ( `?`, `?` ) VALUES ( ?, '?' )";
+    r = run_query(hdb, rec, query);
+    ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
+
+    /* try column names as markers */
+    MsiCloseHandle(rec);
+    rec = MsiCreateRecord(2);
+    MsiRecordSetString(rec, 1, "One");
+    MsiRecordSetString(rec, 2, "Two");
+    query = "INSERT INTO `Table` ( `?`, `?` ) VALUES ( 3, 'yellow' )";
+    r = run_query(hdb, rec, query);
+    ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
+
+    /* try table name as a marker */
+    MsiCloseHandle(rec);
+    rec = MsiCreateRecord(1);
+    MsiRecordSetString(rec, 1, "Table");
+    query = "INSERT INTO `?` ( `One`, `Two` ) VALUES ( 2, 'green' )";
+    r = run_query(hdb, rec, query);
+    ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
+
+    /* try table name and values as markers */
+    MsiCloseHandle(rec);
+    rec = MsiCreateRecord(3);
+    MsiRecordSetString(rec, 1, "Table");
+    MsiRecordSetInteger(rec, 2, 10);
+    MsiRecordSetString(rec, 3, "haha");
+    query = "INSERT INTO `?` ( `One`, `Two` ) VALUES ( ?, '?' )";
+    r = run_query(hdb, rec, query);
+    todo_wine
+    {
+        ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
+    }
+
+    /* try all markers */
+    MsiCloseHandle(rec);
+    rec = MsiCreateRecord(5);
+    MsiRecordSetString(rec, 1, "Table");
+    MsiRecordSetString(rec, 1, "One");
+    MsiRecordSetString(rec, 1, "Two");
+    MsiRecordSetInteger(rec, 2, 10);
+    MsiRecordSetString(rec, 3, "haha");
+    query = "INSERT INTO `?` ( `?`, `?` ) VALUES ( ?, '?' )";
+    r = run_query(hdb, rec, query);
+    ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
+
+    /* insert an integer as a string */
+    MsiCloseHandle(rec);
+    rec = MsiCreateRecord(2);
+    MsiRecordSetString(rec, 1, "11");
+    MsiRecordSetString(rec, 2, "hi");
+    query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, '?' )";
+    r = run_query(hdb, rec, query);
+    ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
+
+    /* leave off the '' for the string */
+    MsiCloseHandle(rec);
+    rec = MsiCreateRecord(2);
+    MsiRecordSetInteger(rec, 1, 12);
+    MsiRecordSetString(rec, 2, "hi");
+    query = "INSERT INTO `Table` ( `One`, `Two` ) VALUES ( ?, ? )";
+    r = run_query(hdb, rec, query);
+    ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
+    MsiCloseHandle(rec);
+
+    MsiCloseHandle(hdb);
+    DeleteFileA(msifile);
+}
+
 START_TEST(db)
 {
     test_msidatabase();
@@ -1058,4 +1372,6 @@ START_TEST(db)
     test_longstrings();
     test_streamtable();
     test_where();
+    test_msiimport();
+    test_markers();
 }
index a187c65..99fbc0b 100644 (file)
@@ -1361,9 +1361,35 @@ static void test_formatrecord_package(void)
     DeleteFile( filename );
 }
 
+static void test_processmessage(void)
+{
+    static const CHAR filename[] = "winetest.msi";
+    MSIHANDLE hrec;
+    MSIHANDLE package;
+    int r;
+
+    package = helper_createpackage( filename );
+    ok(package!=0, "Unable to create package\n");
+
+    hrec = MsiCreateRecord(3);
+    ok( hrec, "failed to create record\n");
+
+    r = MsiRecordSetString(hrec, 1, "");
+    ok( r == ERROR_SUCCESS, "set string failed\n");
+
+    r = MsiProcessMessage(package, INSTALLMESSAGE_ACTIONSTART, hrec);
+    ok( r == IDOK, "expected IDOK, got %i\n", r);
+
+    MsiCloseHandle(hrec);
+    MsiCloseHandle(package);
+
+    DeleteFile(filename);
+}
+
 START_TEST(format)
 {
     test_createpackage();
     test_formatrecord();
     test_formatrecord_package();
+    test_processmessage();
 }
index 880d01d..5a57ef1 100644 (file)
@@ -317,7 +317,7 @@ static int fci_delete(char *pszFile, int *err, void *pv)
     return 0;
 }
 
-static BOOL check_record(MSIHANDLE rec, UINT field, LPSTR val)
+static BOOL check_record(MSIHANDLE rec, UINT field, LPCSTR val)
 {
     CHAR buffer[0x20];
     UINT r;
@@ -404,6 +404,8 @@ static void create_cab_file(const CHAR *name)
     CCAB cabParams;
     HFCI hfci;
     ERF erf;
+    static CHAR four_txt[] = "four.txt",
+                five_txt[] = "five.txt";
     BOOL res;
 
     set_cab_parameters(&cabParams, name);
@@ -414,8 +416,8 @@ static void create_cab_file(const CHAR *name)
 
     ok(hfci != NULL, "Failed to create an FCI context\n");
 
-    add_file(hfci, "four.txt");
-    add_file(hfci, "five.txt");
+    add_file(hfci, four_txt);
+    add_file(hfci, five_txt);
 
     res = FCIFlushCabinet(hfci, FALSE, get_next_cabinet, progress);
     ok(res, "Failed to flush the cabinet\n");
@@ -695,7 +697,7 @@ static void test_packagecoltypes(void)
 {
     MSIHANDLE hdb, view, rec;
     char path[MAX_PATH];
-    LPSTR query;
+    LPCSTR query;
     UINT r, count;
 
     CoInitialize(NULL);
index a66bfdc..4b9d24d 100644 (file)
@@ -99,7 +99,56 @@ static UINT create_file_table( MSIHANDLE hdb )
             "PRIMARY KEY `File`)" );
 }
 
-static UINT add_component_entry( MSIHANDLE hdb, char *values )
+static UINT create_remove_file_table( MSIHANDLE hdb )
+{
+    return run_query( hdb,
+            "CREATE TABLE `RemoveFile` ("
+            "`FileKey` CHAR(72) NOT NULL, "
+            "`Component_` CHAR(72) NOT NULL, "
+            "`FileName` CHAR(255) LOCALIZABLE, "
+            "`DirProperty` CHAR(72) NOT NULL, "
+            "`InstallMode` SHORT NOT NULL "
+            "PRIMARY KEY `FileKey`)" );
+}
+
+static UINT create_appsearch_table( MSIHANDLE hdb )
+{
+    return run_query( hdb,
+            "CREATE TABLE `AppSearch` ("
+            "`Property` CHAR(72) NOT NULL, "
+            "`Signature_` CHAR(72) NOT NULL "
+            "PRIMARY KEY `Property`, `Signature_`)" );
+}
+
+static UINT create_reglocator_table( MSIHANDLE hdb )
+{
+    return run_query( hdb,
+            "CREATE TABLE `RegLocator` ("
+            "`Signature_` CHAR(72) NOT NULL, "
+            "`Root` SHORT NOT NULL, "
+            "`Key` CHAR(255) NOT NULL, "
+            "`Name` CHAR(255), "
+            "`Type` SHORT "
+            "PRIMARY KEY `Signature_`)" );
+}
+
+static UINT create_signature_table( MSIHANDLE hdb )
+{
+    return run_query( hdb,
+            "CREATE TABLE `Signature` ("
+            "`Signature` CHAR(72) NOT NULL, "
+            "`FileName` CHAR(255) NOT NULL, "
+            "`MinVersion` CHAR(20), "
+            "`MaxVersion` CHAR(20), "
+            "`MinSize` LONG, "
+            "`MaxSize` LONG, "
+            "`MinDate` LONG, "
+            "`MaxDate` LONG, "
+            "`Languages` CHAR(255) "
+            "PRIMARY KEY `Signature`)" );
+}
+
+static UINT add_component_entry( MSIHANDLE hdb, const char *values )
 {
     char insert[] = "INSERT INTO `Component`  "
             "(`Component`, `ComponentId`, `Directory_`, `Attributes`, `Condition`, `KeyPath`) "
@@ -115,10 +164,10 @@ static UINT add_component_entry( MSIHANDLE hdb, char *values )
     return r;
 }
 
-static UINT add_feature_entry( MSIHANDLE hdb, char *values )
+static UINT add_feature_entry( MSIHANDLE hdb, const char *values )
 {
     char insert[] = "INSERT INTO `Feature` (`Feature`, `Feature_Parent`, "
-                    "`Display`, `Level`, `Attributes`) VALUES( %s )";
+                    "`Title`, `Description`, `Display`, `Level`, `Directory_`, `Attributes`) VALUES( %s )";
     char *query;
     UINT sz, r;
 
@@ -130,7 +179,7 @@ static UINT add_feature_entry( MSIHANDLE hdb, char *values )
     return r;
 }
 
-static UINT add_feature_components_entry( MSIHANDLE hdb, char *values )
+static UINT add_feature_components_entry( MSIHANDLE hdb, const char *values )
 {
     char insert[] = "INSERT INTO `FeatureComponents` "
             "(`Feature_`, `Component_`) "
@@ -146,7 +195,7 @@ static UINT add_feature_components_entry( MSIHANDLE hdb, char *values )
     return r;
 }
 
-static UINT add_file_entry( MSIHANDLE hdb, char *values )
+static UINT add_file_entry( MSIHANDLE hdb, const char *values )
 {
     char insert[] = "INSERT INTO `File` "
             "(`File`, `Component_`, `FileName`, `FileSize`, `Version`, `Language`, `Attributes`, `Sequence`) "
@@ -162,6 +211,55 @@ static UINT add_file_entry( MSIHANDLE hdb, char *values )
     return r;
 }
 
+static UINT add_appsearch_entry( MSIHANDLE hdb, const char *values )
+{
+    char insert[] = "INSERT INTO `AppSearch` "
+            "(`Property`, `Signature_`) "
+            "VALUES( %s )";
+    char *query;
+    UINT sz, r;
+
+    sz = strlen(values) + sizeof insert;
+    query = HeapAlloc(GetProcessHeap(),0,sz);
+    sprintf(query,insert,values);
+    r = run_query( hdb, query );
+    HeapFree(GetProcessHeap(), 0, query);
+    return r;
+}
+
+static UINT add_reglocator_entry( MSIHANDLE hdb, const char *values )
+{
+    char insert[] = "INSERT INTO `RegLocator` "
+            "(`Signature_`, `Root`, `Key`, `Name`, `Type`) "
+            "VALUES( %s )";
+    char *query;
+    UINT sz, r;
+
+    sz = strlen(values) + sizeof insert;
+    query = HeapAlloc(GetProcessHeap(),0,sz);
+    sprintf(query,insert,values);
+    r = run_query( hdb, query );
+    HeapFree(GetProcessHeap(), 0, query);
+    return r;
+}
+
+static UINT add_signature_entry( MSIHANDLE hdb, const char *values )
+{
+    char insert[] = "INSERT INTO `Signature` "
+            "(`Signature`, `FileName`, `MinVersion`, `MaxVersion`,"
+            " `MinSize`, `MaxSize`, `MinDate`, `MaxDate`, `Languages`) "
+            "VALUES( %s )";
+    char *query;
+    UINT sz, r;
+
+    sz = strlen(values) + sizeof insert;
+    query = HeapAlloc(GetProcessHeap(),0,sz);
+    sprintf(query,insert,values);
+    r = run_query( hdb, query );
+    HeapFree(GetProcessHeap(), 0, query);
+    return r;
+}
+
 static UINT set_summary_info(MSIHANDLE hdb)
 {
     UINT res;
@@ -252,6 +350,18 @@ MSIHANDLE package_from_db(MSIHANDLE hdb)
     return hPackage;
 }
 
+static void create_test_file(const CHAR *name)
+{
+    HANDLE file;
+    DWORD written;
+
+    file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
+    ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
+    WriteFile(file, name, strlen(name), &written, NULL);
+    WriteFile(file, "\n", strlen("\n"), &written, NULL);
+    CloseHandle(file);
+}
+
 static void test_createpackage(void)
 {
     MSIHANDLE hPackage = 0;
@@ -292,7 +402,7 @@ static void test_getsourcepath_bad( void )
     ok( r == ERROR_INVALID_HANDLE, "return value wrong\n");
 }
 
-static UINT add_directory_entry( MSIHANDLE hdb, char *values )
+static UINT add_directory_entry( MSIHANDLE hdb, const char *values )
 {
     char insert[] = "INSERT INTO `Directory` (`Directory`,`Directory_Parent`,`DefaultDir`) VALUES( %s )";
     char *query;
@@ -335,7 +445,7 @@ static void test_getsourcepath( void )
     /* another test but try create a directory this time */
     hdb = create_package_db();
     ok( hdb, "failed to create database\n");
-    
+
     r = add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'");
     ok( r == S_OK, "failed\n");
 
@@ -471,7 +581,7 @@ static void test_settargetpath(void)
     MSIHANDLE hpkg;
     UINT r;
     MSIHANDLE hdb;
-    
+
     hdb = create_package_db();
     ok ( hdb, "failed to create package database\n" );
 
@@ -982,11 +1092,151 @@ static void test_condition(void)
     r = MsiEvaluateCondition(hpkg, "bandalmael<>0");
     ok( r == MSICONDITION_TRUE, "wrong return val\n");
 
+    MsiSetProperty(hpkg, "one", "hi");
+    MsiSetProperty(hpkg, "two", "hithere");
+    r = MsiEvaluateCondition(hpkg, "one >< two");
+    ok( r == MSICONDITION_FALSE, "wrong return val\n");
+
+    MsiSetProperty(hpkg, "one", "hithere");
+    MsiSetProperty(hpkg, "two", "hi");
+    r = MsiEvaluateCondition(hpkg, "one >< two");
+    ok( r == MSICONDITION_TRUE, "wrong return val\n");
+
+    MsiSetProperty(hpkg, "one", "hello");
+    MsiSetProperty(hpkg, "two", "hi");
+    r = MsiEvaluateCondition(hpkg, "one >< two");
+    ok( r == MSICONDITION_FALSE, "wrong return val\n");
+
+    MsiSetProperty(hpkg, "one", "hellohithere");
+    MsiSetProperty(hpkg, "two", "hi");
+    r = MsiEvaluateCondition(hpkg, "one >< two");
+    ok( r == MSICONDITION_TRUE, "wrong return val\n");
+
+    MsiSetProperty(hpkg, "one", "");
+    MsiSetProperty(hpkg, "two", "hi");
+    r = MsiEvaluateCondition(hpkg, "one >< two");
+    ok( r == MSICONDITION_FALSE, "wrong return val\n");
+
+    MsiSetProperty(hpkg, "one", "hi");
+    MsiSetProperty(hpkg, "two", "");
+    r = MsiEvaluateCondition(hpkg, "one >< two");
+    ok( r == MSICONDITION_TRUE, "wrong return val\n");
+
+    MsiSetProperty(hpkg, "one", "");
+    MsiSetProperty(hpkg, "two", "");
+    r = MsiEvaluateCondition(hpkg, "one >< two");
+    ok( r == MSICONDITION_FALSE, "wrong return val\n");
+
+    MsiSetProperty(hpkg, "one", "1234");
+    MsiSetProperty(hpkg, "two", "1");
+    r = MsiEvaluateCondition(hpkg, "one >< two");
+    ok( r == MSICONDITION_FALSE, "wrong return val\n");
+
+    MsiSetProperty(hpkg, "one", "one 1234");
+    MsiSetProperty(hpkg, "two", "1");
+    r = MsiEvaluateCondition(hpkg, "one >< two");
+    ok( r == MSICONDITION_TRUE, "wrong return val\n");
+
+    MsiSetProperty(hpkg, "one", "hithere");
+    MsiSetProperty(hpkg, "two", "hi");
+    r = MsiEvaluateCondition(hpkg, "one << two");
+    ok( r == MSICONDITION_TRUE, "wrong return val\n");
+
+    MsiSetProperty(hpkg, "one", "hi");
+    MsiSetProperty(hpkg, "two", "hithere");
+    r = MsiEvaluateCondition(hpkg, "one << two");
+    ok( r == MSICONDITION_FALSE, "wrong return val\n");
+
+    MsiSetProperty(hpkg, "one", "hi");
+    MsiSetProperty(hpkg, "two", "hi");
+    r = MsiEvaluateCondition(hpkg, "one << two");
+    ok( r == MSICONDITION_TRUE, "wrong return val\n");
+
+    MsiSetProperty(hpkg, "one", "abcdhithere");
+    MsiSetProperty(hpkg, "two", "hi");
+    r = MsiEvaluateCondition(hpkg, "one << two");
+    ok( r == MSICONDITION_FALSE, "wrong return val\n");
+
+    MsiSetProperty(hpkg, "one", "");
+    MsiSetProperty(hpkg, "two", "hi");
+    r = MsiEvaluateCondition(hpkg, "one << two");
+    ok( r == MSICONDITION_FALSE, "wrong return val\n");
+
+    MsiSetProperty(hpkg, "one", "hithere");
+    MsiSetProperty(hpkg, "two", "");
+    r = MsiEvaluateCondition(hpkg, "one << two");
+    ok( r == MSICONDITION_TRUE, "wrong return val\n");
+
+    MsiSetProperty(hpkg, "one", "");
+    MsiSetProperty(hpkg, "two", "");
+    r = MsiEvaluateCondition(hpkg, "one << two");
+    ok( r == MSICONDITION_FALSE, "wrong return val\n");
+
+    MsiSetProperty(hpkg, "one", "1234");
+    MsiSetProperty(hpkg, "two", "1");
+    r = MsiEvaluateCondition(hpkg, "one << two");
+    ok( r == MSICONDITION_FALSE, "wrong return val\n");
+
+    MsiSetProperty(hpkg, "one", "1234 one");
+    MsiSetProperty(hpkg, "two", "1");
+    r = MsiEvaluateCondition(hpkg, "one << two");
+    ok( r == MSICONDITION_TRUE, "wrong return val\n");
+
+    MsiSetProperty(hpkg, "one", "hithere");
+    MsiSetProperty(hpkg, "two", "there");
+    r = MsiEvaluateCondition(hpkg, "one >> two");
+    ok( r == MSICONDITION_TRUE, "wrong return val\n");
+
+    MsiSetProperty(hpkg, "one", "hithere");
+    MsiSetProperty(hpkg, "two", "hi");
+    r = MsiEvaluateCondition(hpkg, "one >> two");
+    ok( r == MSICONDITION_FALSE, "wrong return val\n");
+
+    MsiSetProperty(hpkg, "one", "there");
+    MsiSetProperty(hpkg, "two", "hithere");
+    r = MsiEvaluateCondition(hpkg, "one >> two");
+    ok( r == MSICONDITION_FALSE, "wrong return val\n");
+
+    MsiSetProperty(hpkg, "one", "there");
+    MsiSetProperty(hpkg, "two", "there");
+    r = MsiEvaluateCondition(hpkg, "one >> two");
+    ok( r == MSICONDITION_TRUE, "wrong return val\n");
+
+    MsiSetProperty(hpkg, "one", "abcdhithere");
+    MsiSetProperty(hpkg, "two", "hi");
+    r = MsiEvaluateCondition(hpkg, "one >> two");
+    ok( r == MSICONDITION_FALSE, "wrong return val\n");
+
+    MsiSetProperty(hpkg, "one", "");
+    MsiSetProperty(hpkg, "two", "there");
+    r = MsiEvaluateCondition(hpkg, "one >> two");
+    ok( r == MSICONDITION_FALSE, "wrong return val\n");
+
+    MsiSetProperty(hpkg, "one", "there");
+    MsiSetProperty(hpkg, "two", "");
+    r = MsiEvaluateCondition(hpkg, "one >> two");
+    ok( r == MSICONDITION_TRUE, "wrong return val\n");
+
+    MsiSetProperty(hpkg, "one", "");
+    MsiSetProperty(hpkg, "two", "");
+    r = MsiEvaluateCondition(hpkg, "one >> two");
+    ok( r == MSICONDITION_FALSE, "wrong return val\n");
+
+    MsiSetProperty(hpkg, "one", "1234");
+    MsiSetProperty(hpkg, "two", "4");
+    r = MsiEvaluateCondition(hpkg, "one >> two");
+    ok( r == MSICONDITION_FALSE, "wrong return val\n");
+
+    MsiSetProperty(hpkg, "one", "one 1234");
+    MsiSetProperty(hpkg, "two", "4");
+    r = MsiEvaluateCondition(hpkg, "one >> two");
+    ok( r == MSICONDITION_TRUE, "wrong return val\n");
+
     MsiCloseHandle( hpkg );
     DeleteFile(msifile);
 }
 
-static BOOL check_prop_empty( MSIHANDLE hpkg, char * prop)
+static BOOL check_prop_empty( MSIHANDLE hpkg, const char * prop)
 {
     UINT r;
     DWORD sz;
@@ -1295,7 +1545,7 @@ static void test_states(void)
     ok( r == ERROR_SUCCESS, "cannot create Component table: %d\n", r );
 
     /* msidbFeatureAttributesFavorLocal */
-    r = add_feature_entry( hdb, "'one', '', 2, 1, 0" );
+    r = add_feature_entry( hdb, "'one', '', '', '', 2, 1, '', 0" );
     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
 
     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesLocalOnly */
@@ -1310,8 +1560,12 @@ static void test_states(void)
     r = add_component_entry( hdb, "'gamma', '{C271E2A4-DE2E-4F70-86D1-6984AF7DE2CA}', 'TARGETDIR', 2, '', 'gamma_file'" );
     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
 
+    /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSharedDllRefCount */
+    r = add_component_entry( hdb, "'theta', '{4EB3129D-81A8-48D5-9801-75600FED3DD9}', 'TARGETDIR', 8, '', 'theta_file'" );
+    ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
+
     /* msidbFeatureAttributesFavorSource */
-    r = add_feature_entry( hdb, "'two', '', 2, 1, 1" );
+    r = add_feature_entry( hdb, "'two', '', '', '', 2, 1, '', 1" );
     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
 
     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesLocalOnly */
@@ -1326,8 +1580,12 @@ static void test_states(void)
     r = add_component_entry( hdb, "'zeta', '{377D33AB-2FAA-42B9-A629-0C0DAE9B9C7A}', 'TARGETDIR', 2, '', 'zeta_file'" );
     ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
 
+    /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSharedDllRefCount */
+    r = add_component_entry( hdb, "'iota', '{5D36F871-B5ED-4801-9E0F-C46B9E5C9669}', 'TARGETDIR', 8, '', 'iota_file'" );
+    ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
+
     /* msidbFeatureAttributesFavorSource */
-    r = add_feature_entry( hdb, "'three', '', 2, 1, 1" );
+    r = add_feature_entry( hdb, "'three', '', '', '', 2, 1, '', 1" );
     ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
 
     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSourceOnly */
@@ -1346,6 +1604,9 @@ static void test_states(void)
     r = add_feature_components_entry( hdb, "'one', 'gamma'" );
     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
 
+    r = add_feature_components_entry( hdb, "'one', 'theta'" );
+    ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
+
     r = add_feature_components_entry( hdb, "'two', 'delta'" );
     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
 
@@ -1355,6 +1616,9 @@ static void test_states(void)
     r = add_feature_components_entry( hdb, "'two', 'zeta'" );
     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
 
+    r = add_feature_components_entry( hdb, "'two', 'iota'" );
+    ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
+
     r = add_feature_components_entry( hdb, "'three', 'eta'" );
     ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
 
@@ -1370,6 +1634,9 @@ static void test_states(void)
     r = add_file_entry( hdb, "'gamma_file', 'gamma', 'gamma.txt', 0, '', '1033', 8192, 1" );
     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
 
+    r = add_file_entry( hdb, "'theta_file', 'theta', 'theta.txt', 0, '', '1033', 8192, 1" );
+    ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
+
     r = add_file_entry( hdb, "'delta_file', 'delta', 'delta.txt', 0, '', '1033', 8192, 1" );
     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
 
@@ -1379,6 +1646,9 @@ static void test_states(void)
     r = add_file_entry( hdb, "'zeta_file', 'zeta', 'zeta.txt', 0, '', '1033', 8192, 1" );
     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
 
+    r = add_file_entry( hdb, "'iota_file', 'iota', 'iota.txt', 0, '', '1033', 8192, 1" );
+    ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
+
     /* compressed file */
     r = add_file_entry( hdb, "'eta_file', 'eta', 'eta.txt', 0, '', '1033', 16384, 1" );
     ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
@@ -1386,81 +1656,95 @@ static void test_states(void)
     hpkg = package_from_db( hdb );
     ok( hpkg, "failed to create package\n");
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetFeatureState(hpkg, "one", &state, &action);
     ok( r == ERROR_UNKNOWN_FEATURE, "Expected ERROR_UNKNOWN_FEATURE, got %d\n", r );
-    ok( state == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", state);
-    ok( action == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", action);
+    ok( state == 0xdeadbee, "Expected 0xdeadbee, got %d\n", state);
+    ok( action == 0xdeadbee, "Expected 0xdeadbee, got %d\n", action);
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetFeatureState(hpkg, "two", &state, &action);
     ok( r == ERROR_UNKNOWN_FEATURE, "Expected ERROR_UNKNOWN_FEATURE, got %d\n", r );
-    ok( state == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", state);
-    ok( action == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", action);
+    ok( state == 0xdeadbee, "Expected 0xdeadbee, got %d\n", state);
+    ok( action == 0xdeadbee, "Expected 0xdeadbee, got %d\n", action);
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetFeatureState(hpkg, "three", &state, &action);
     ok( r == ERROR_UNKNOWN_FEATURE, "Expected ERROR_UNKNOWN_FEATURE, got %d\n", r );
-    ok( state == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", state);
-    ok( action == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", action);
+    ok( state == 0xdeadbee, "Expected 0xdeadbee, got %d\n", state);
+    ok( action == 0xdeadbee, "Expected 0xdeadbee, got %d\n", action);
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetComponentState(hpkg, "alpha", &state, &action);
     ok( r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r );
-    ok( state == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", state);
-    ok( action == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", action);
+    ok( state == 0xdeadbee, "Expected 0xdeadbee, got %d\n", state);
+    ok( action == 0xdeadbee, "Expected 0xdeadbee, got %d\n", action);
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetComponentState(hpkg, "beta", &state, &action);
     ok( r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r );
-    ok( state == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", state);
-    ok( action == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", action);
+    ok( state == 0xdeadbee, "Expected 0xdeadbee, got %d\n", state);
+    ok( action == 0xdeadbee, "Expected 0xdeadbee, got %d\n", action);
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetComponentState(hpkg, "gamma", &state, &action);
     ok( r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r );
-    ok( state == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", state);
-    ok( action == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", action);
+    ok( state == 0xdeadbee, "Expected 0xdeadbee, got %d\n", state);
+    ok( action == 0xdeadbee, "Expected 0xdeadbee, got %d\n", action);
+
+    state = 0xdeadbee;
+    action = 0xdeadbee;
+    r = MsiGetComponentState(hpkg, "theta", &state, &action);
+    ok( r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r );
+    ok( state == 0xdeadbee, "Expected 0xdeadbee, got %d\n", state);
+    ok( action == 0xdeadbee, "Expected 0xdeadbee, got %d\n", action);
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetComponentState(hpkg, "delta", &state, &action);
     ok( r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r );
-    ok( state == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", state);
-    ok( action == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", action);
+    ok( state == 0xdeadbee, "Expected 0xdeadbee, got %d\n", state);
+    ok( action == 0xdeadbee, "Expected 0xdeadbee, got %d\n", action);
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetComponentState(hpkg, "epsilon", &state, &action);
     ok( r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r );
-    ok( state == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", state);
-    ok( action == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", action);
+    ok( state == 0xdeadbee, "Expected 0xdeadbee, got %d\n", state);
+    ok( action == 0xdeadbee, "Expected 0xdeadbee, got %d\n", action);
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetComponentState(hpkg, "zeta", &state, &action);
     ok( r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r );
-    ok( state == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", state);
-    ok( action == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", action);
+    ok( state == 0xdeadbee, "Expected 0xdeadbee, got %d\n", state);
+    ok( action == 0xdeadbee, "Expected 0xdeadbee, got %d\n", action);
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
+    r = MsiGetComponentState(hpkg, "iota", &state, &action);
+    ok( r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r );
+    ok( state == 0xdeadbee, "Expected 0xdeadbee, got %d\n", state);
+    ok( action == 0xdeadbee, "Expected 0xdeadbee, got %d\n", action);
+
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetComponentState(hpkg, "eta", &state, &action);
     ok( r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r );
-    ok( state == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", state);
-    ok( action == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", action);
+    ok( state == 0xdeadbee, "Expected 0xdeadbee, got %d\n", state);
+    ok( action == 0xdeadbee, "Expected 0xdeadbee, got %d\n", action);
 
     r = MsiDoAction( hpkg, "CostInitialize");
     ok( r == ERROR_SUCCESS, "cost init failed\n");
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetFeatureState(hpkg, "one", &state, &action);
     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
     todo_wine
@@ -1469,8 +1753,8 @@ static void test_states(void)
     }
     ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetFeatureState(hpkg, "two", &state, &action);
     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
     todo_wine
@@ -1479,8 +1763,8 @@ static void test_states(void)
     }
     ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetFeatureState(hpkg, "three", &state, &action);
     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
     todo_wine
@@ -1489,8 +1773,8 @@ static void test_states(void)
     }
     ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetComponentState(hpkg, "alpha", &state, &action);
     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
     todo_wine
@@ -1499,8 +1783,8 @@ static void test_states(void)
         ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
     }
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetComponentState(hpkg, "beta", &state, &action);
     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
     todo_wine
@@ -1509,8 +1793,8 @@ static void test_states(void)
         ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
     }
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetComponentState(hpkg, "gamma", &state, &action);
     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
     todo_wine
@@ -1519,8 +1803,18 @@ static void test_states(void)
         ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
     }
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
+    r = MsiGetComponentState(hpkg, "theta", &state, &action);
+    ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
+    todo_wine
+    {
+        ok( state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
+        ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
+    }
+
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetComponentState(hpkg, "delta", &state, &action);
     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
     todo_wine
@@ -1529,8 +1823,8 @@ static void test_states(void)
         ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
     }
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetComponentState(hpkg, "epsilon", &state, &action);
     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
     todo_wine
@@ -1539,8 +1833,8 @@ static void test_states(void)
         ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
     }
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetComponentState(hpkg, "zeta", &state, &action);
     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
     todo_wine
@@ -1549,8 +1843,18 @@ static void test_states(void)
         ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
     }
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
+    r = MsiGetComponentState(hpkg, "iota", &state, &action);
+    ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
+    todo_wine
+    {
+        ok( state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
+        ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
+    }
+
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetComponentState(hpkg, "eta", &state, &action);
     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
     todo_wine
@@ -1562,8 +1866,8 @@ static void test_states(void)
     r = MsiDoAction( hpkg, "FileCost");
     ok( r == ERROR_SUCCESS, "file cost failed\n");
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetFeatureState(hpkg, "one", &state, &action);
     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
     todo_wine
@@ -1572,8 +1876,8 @@ static void test_states(void)
     }
     ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetFeatureState(hpkg, "two", &state, &action);
     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
     todo_wine
@@ -1582,8 +1886,8 @@ static void test_states(void)
     }
     ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetFeatureState(hpkg, "three", &state, &action);
     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
     todo_wine
@@ -1592,8 +1896,8 @@ static void test_states(void)
     }
     ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetComponentState(hpkg, "alpha", &state, &action);
     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
     todo_wine
@@ -1602,8 +1906,8 @@ static void test_states(void)
         ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
     }
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetComponentState(hpkg, "beta", &state, &action);
     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
     todo_wine
@@ -1612,8 +1916,8 @@ static void test_states(void)
         ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
     }
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetComponentState(hpkg, "gamma", &state, &action);
     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
     todo_wine
@@ -1622,8 +1926,18 @@ static void test_states(void)
         ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
     }
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
+    r = MsiGetComponentState(hpkg, "theta", &state, &action);
+    ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
+    todo_wine
+    {
+        ok( state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
+        ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
+    }
+
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetComponentState(hpkg, "delta", &state, &action);
     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
     todo_wine
@@ -1632,8 +1946,8 @@ static void test_states(void)
         ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
     }
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetComponentState(hpkg, "epsilon", &state, &action);
     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
     todo_wine
@@ -1642,8 +1956,8 @@ static void test_states(void)
         ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
     }
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetComponentState(hpkg, "zeta", &state, &action);
     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
     todo_wine
@@ -1652,8 +1966,18 @@ static void test_states(void)
         ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
     }
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
+    r = MsiGetComponentState(hpkg, "iota", &state, &action);
+    ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
+    todo_wine
+    {
+        ok( state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
+        ok( action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
+    }
+
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetComponentState(hpkg, "eta", &state, &action);
     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
     todo_wine
@@ -1665,92 +1989,326 @@ static void test_states(void)
     r = MsiDoAction( hpkg, "CostFinalize");
     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetFeatureState(hpkg, "one", &state, &action);
     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
     ok( state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
-    todo_wine
-    {
-        ok( action == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", action);
-    }
+    ok( action == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", action);
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetFeatureState(hpkg, "two", &state, &action);
     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
     ok( state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
-    todo_wine
-    {
-        ok( action == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", action);
-    }
+    ok( action == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", action);
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetFeatureState(hpkg, "three", &state, &action);
     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
     ok( state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
-    todo_wine
-    {
-        ok( action == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", action);
-    }
+    ok( action == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", action);
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetComponentState(hpkg, "alpha", &state, &action);
     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
     ok( state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
     ok( action == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", action);
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetComponentState(hpkg, "beta", &state, &action);
     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
     ok( state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
     ok( action == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", action);
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetComponentState(hpkg, "gamma", &state, &action);
     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
     ok( state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
     ok( action == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", action);
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
+    r = MsiGetComponentState(hpkg, "theta", &state, &action);
+    ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
+    ok( state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
+    ok( action == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", action);
+
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetComponentState(hpkg, "delta", &state, &action);
     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
     ok( state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
     ok( action == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", action);
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetComponentState(hpkg, "epsilon", &state, &action);
     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
     ok( state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
     ok( action == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", action);
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetComponentState(hpkg, "zeta", &state, &action);
     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
     ok( state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
-    todo_wine
-    {
-        ok( action == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", action);
-    }
+    ok( action == INSTALLSTATE_SOURCE, "Expected INSTALLSTATE_SOURCE, got %d\n", action);
+
+    state = 0xdeadbee;
+    action = 0xdeadbee;
+    r = MsiGetComponentState(hpkg, "iota", &state, &action);
+    ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
+    ok( state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
+    ok( action == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", action);
 
-    state = 0xdeadbeef;
-    action = 0xdeadbeef;
+    state = 0xdeadbee;
+    action = 0xdeadbee;
     r = MsiGetComponentState(hpkg, "eta", &state, &action);
     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
     ok( state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
+    ok( action == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", action);
+    
+    MsiCloseHandle( hpkg );
+}
+
+static void test_getproperty(void)
+{
+    MSIHANDLE hPackage = 0;
+    char prop[100];
+    static CHAR empty[] = "";
+    DWORD size;
+    UINT r;
+
+    hPackage = package_from_db(create_package_db());
+    ok( hPackage != 0, " Failed to create package\n");
+
+    /* set the property */
+    r = MsiSetProperty(hPackage, "Name", "Value");
+    ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
+
+    /* retrieve the size, NULL pointer */
+    size = 0;
+    r = MsiGetProperty(hPackage, "Name", NULL, &size);
+    ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
+    ok( size == 5, "Expected 5, got %ld\n", size);
+
+    /* retrieve the size, empty string */
+    size = 0;
+    r = MsiGetProperty(hPackage, "Name", empty, &size);
+    ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
+    ok( size == 5, "Expected 5, got %ld\n", size);
+
+    /* don't change size */
+    r = MsiGetProperty(hPackage, "Name", prop, &size);
+    ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
+    ok( size == 5, "Expected 5, got %ld\n", size);
+    ok( !lstrcmp(prop, "Valu"), "Expected Valu, got %s\n", prop);
+
+    /* increase the size by 1 */
+    size++;
+    r = MsiGetProperty(hPackage, "Name", prop, &size);
+    ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
+    ok( size == 5, "Expected 5, got %ld\n", size);
+    ok( !lstrcmp(prop, "Value"), "Expected Value, got %s\n", prop);
+
+    r = MsiCloseHandle( hPackage);
+    ok( r == ERROR_SUCCESS , "Failed to close package\n" );
+    DeleteFile(msifile);
+}
+
+static void test_removefiles(void)
+{
+    MSIHANDLE hpkg;
+    UINT r;
+    MSIHANDLE hdb;
+    char CURR_DIR[MAX_PATH];
+
+    GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
+
+    hdb = create_package_db();
+    ok ( hdb, "failed to create package database\n" );
+
+    r = add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'");
+    ok( r == ERROR_SUCCESS, "cannot add directory: %d\n", r );
+
+    r = create_feature_table( hdb );
+    ok( r == ERROR_SUCCESS, "cannot create Feature table: %d\n", r );
+
+    r = create_component_table( hdb );
+    ok( r == ERROR_SUCCESS, "cannot create Component table: %d\n", r );
+
+    r = add_feature_entry( hdb, "'one', '', '', '', 2, 1, '', 0" );
+    ok( r == ERROR_SUCCESS, "cannot add feature: %d\n", r );
+
+    r = add_component_entry( hdb, "'hydrogen', '', 'TARGETDIR', 0, '', 'hydrogen_file'" );
+    ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
+
+    r = add_component_entry( hdb, "'helium', '', 'TARGETDIR', 0, '', 'helium_file'" );
+    ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
+
+    r = add_component_entry( hdb, "'lithium', '', 'TARGETDIR', 0, '', 'lithium_file'" );
+    ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
+
+    r = add_component_entry( hdb, "'beryllium', '', 'TARGETDIR', 0, '', 'beryllium_file'" );
+    ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
+
+    r = add_component_entry( hdb, "'boron', '', 'TARGETDIR', 0, '', 'boron_file'" );
+    ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
+
+    r = add_component_entry( hdb, "'carbon', '', 'TARGETDIR', 0, '', 'carbon_file'" );
+    ok( r == ERROR_SUCCESS, "cannot add component: %d\n", r );
+
+    r = create_feature_components_table( hdb );
+    ok( r == ERROR_SUCCESS, "cannot create FeatureComponents table: %d\n", r );
+
+    r = add_feature_components_entry( hdb, "'one', 'hydrogen'" );
+    ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
+
+    r = add_feature_components_entry( hdb, "'one', 'helium'" );
+    ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
+
+    r = add_feature_components_entry( hdb, "'one', 'lithium'" );
+    ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
+
+    r = add_feature_components_entry( hdb, "'one', 'beryllium'" );
+    ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
+
+    r = add_feature_components_entry( hdb, "'one', 'boron'" );
+    ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
+
+    r = add_feature_components_entry( hdb, "'one', 'carbon'" );
+    ok( r == ERROR_SUCCESS, "cannot add feature components: %d\n", r );
+
+    r = create_file_table( hdb );
+    ok( r == ERROR_SUCCESS, "cannot create File table: %d\n", r );
+
+    r = add_file_entry( hdb, "'hydrogen_file', 'hydrogen', 'hydrogen.txt', 0, '', '1033', 8192, 1" );
+    ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
+
+    r = add_file_entry( hdb, "'helium_file', 'helium', 'helium.txt', 0, '', '1033', 8192, 1" );
+    ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
+
+    r = add_file_entry( hdb, "'lithium_file', 'lithium', 'lithium.txt', 0, '', '1033', 8192, 1" );
+    ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
+
+    r = add_file_entry( hdb, "'beryllium_file', 'beryllium', 'beryllium.txt', 0, '', '1033', 16384, 1" );
+    ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
+
+    r = add_file_entry( hdb, "'boron_file', 'boron', 'boron.txt', 0, '', '1033', 16384, 1" );
+    ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
+
+    r = add_file_entry( hdb, "'carbon_file', 'carbon', 'carbon.txt', 0, '', '1033', 16384, 1" );
+    ok( r == ERROR_SUCCESS, "cannot add file: %d\n", r);
+
+    r = create_remove_file_table( hdb );
+    ok( r == ERROR_SUCCESS, "cannot create Remove File table: %d\n", r);
+
+    hpkg = package_from_db( hdb );
+    ok( hpkg, "failed to create package\n");
+
+    create_test_file( "hydrogen.txt" );
+    create_test_file( "helium.txt" );
+    create_test_file( "lithium.txt" );
+    create_test_file( "beryllium.txt" );
+    create_test_file( "boron.txt" );
+    create_test_file( "carbon.txt" );
+
+    r = MsiSetProperty( hpkg, "TARGETDIR", CURR_DIR );
+    ok( r == ERROR_SUCCESS, "set property failed\n");
+
+    r = MsiDoAction( hpkg, "CostInitialize");
+    ok( r == ERROR_SUCCESS, "cost init failed\n");
+
+    r = MsiDoAction( hpkg, "FileCost");
+    ok( r == ERROR_SUCCESS, "cost finalize failed\n");
+
+    r = MsiDoAction( hpkg, "CostFinalize");
+    ok( r == ERROR_SUCCESS, "cost finalize failed\n");
+
+    r = MsiDoAction( hpkg, "InstallValidate");
+    ok( r == ERROR_SUCCESS, "cost finalize failed\n");
+
+    r = MsiSetComponentState( hpkg, "hydrogen", INSTALLSTATE_ABSENT );
+    ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
+
+    r = MsiSetComponentState( hpkg, "helium", INSTALLSTATE_LOCAL );
+    ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
+
+    r = MsiSetComponentState( hpkg, "lithium", INSTALLSTATE_SOURCE );
+    ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
+
+    r = MsiSetComponentState( hpkg, "beryllium", INSTALLSTATE_ABSENT );
+    ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
+
+    r = MsiSetComponentState( hpkg, "boron", INSTALLSTATE_LOCAL );
+    ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
+
+    r = MsiSetComponentState( hpkg, "carbon", INSTALLSTATE_SOURCE );
+    ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
+
+    r = MsiDoAction( hpkg, "RemoveFiles");
+    ok( r == ERROR_SUCCESS, "remove files failed\n");
+
+    ok(DeleteFileA("hydrogen.txt"), "Expected hydrogen.txt to exist\n");
+    ok(DeleteFileA("lithium.txt"), "Expected lithium.txt to exist\n");    
+    ok(DeleteFileA("beryllium.txt"), "Expected beryllium.txt to exist\n");
+    ok(DeleteFileA("carbon.txt"), "Expected carbon.txt to exist\n");
+    ok(DeleteFileA("helium.txt"), "Expected helium.txt to exist\n");
+    ok(DeleteFileA("boron.txt"), "Expected boron.txt to exist\n");
+
+    MsiCloseHandle( hpkg );
+    DeleteFileA(msifile);
+}
+
+static void test_appsearch(void)
+{
+    MSIHANDLE hpkg;
+    UINT r;
+    MSIHANDLE hdb;
+    CHAR prop[MAX_PATH];
+    DWORD size = MAX_PATH;
+
+    hdb = create_package_db();
+    ok ( hdb, "failed to create package database\n" );
+
+    r = create_appsearch_table( hdb );
+    ok( r == ERROR_SUCCESS, "cannot create AppSearch table: %d\n", r );
+
+    r = add_appsearch_entry( hdb, "'WEBBROWSERPROG', 'NewSignature1'" );
+    ok( r == ERROR_SUCCESS, "cannot add entry: %d\n", r );
+
+    r = create_reglocator_table( hdb );
+    ok( r == ERROR_SUCCESS, "cannot create RegLocator table: %d\n", r );
+
+    r = add_reglocator_entry( hdb, "'NewSignature1', 0, 'htmlfile\\shell\\open\\command', '', 1" );
+    ok( r == ERROR_SUCCESS, "cannot create RegLocator table: %d\n", r );
+
+    r = create_signature_table( hdb );
+    ok( r == ERROR_SUCCESS, "cannot create Signature table: %d\n", r );
+
+    r = add_signature_entry( hdb, "'NewSignature1', 'FileName', '', '', '', '', '', '', ''" );
+    ok( r == ERROR_SUCCESS, "cannot create Signature table: %d\n", r );
+
+    hpkg = package_from_db( hdb );
+    ok( hpkg, "failed to create package\n");
+
+    r = MsiDoAction( hpkg, "AppSearch" );
+    ok( r == ERROR_SUCCESS, "AppSearch failed: %d\n", r);
+
+    r = MsiGetPropertyA( hpkg, "WEBBROWSERPROG", prop, &size );
+    ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
     todo_wine
     {
-        ok( action == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", action);
+        ok( lstrlenA(prop) != 0, "Expected non-zero length\n");
     }
-    
+
     MsiCloseHandle( hpkg );
+    DeleteFileA(msifile);
 }
 
 START_TEST(package)
@@ -1766,4 +2324,7 @@ START_TEST(package)
     test_msipackage();
     test_formatrecord2();
     test_states();
+    test_getproperty();
+    test_removefiles();
+    test_appsearch();
 }