Module: wine Branch: master Commit: 0f6aaf86bd52ec382bc6ecb7982e7701e484c553 URL: http://source.winehq.org/git/wine.git/?a=commit;h=0f6aaf86bd52ec382bc6ecb798...
Author: James Hawkins truiken@gmail.com Date: Wed Jul 11 00:11:53 2007 -0700
msi: Add tests for adding properties with a transform during an install.
---
dlls/msi/tests/install.c | 235 ++++++++++++++++++++++++++++++++++++++++++++++ include/msiquery.h | 4 + 2 files changed, 239 insertions(+), 0 deletions(-)
diff --git a/dlls/msi/tests/install.c b/dlls/msi/tests/install.c index f64b9f7..5f448da 100644 --- a/dlls/msi/tests/install.c +++ b/dlls/msi/tests/install.c @@ -19,6 +19,7 @@ */
#define _WIN32_MSI 300 +#define COBJMACROS
#include <stdio.h>
@@ -27,10 +28,13 @@ #include <msidefs.h> #include <msi.h> #include <fci.h> +#include <objidl.h>
#include "wine/test.h"
static const char *msifile = "msitest.msi"; +static const char *msifile2 = "winetest2.msi"; +static const char *mstfile = "winetest.mst"; CHAR CURR_DIR[MAX_PATH]; CHAR PROG_FILES_DIR[MAX_PATH];
@@ -405,6 +409,11 @@ static const CHAR pp_install_exec_seq_dat[] = "Action\tCondition\tSequence\n" "PublishProduct\tPUBLISH_PRODUCT=1 Or FULL=1\t6400\n" "InstallFinalize\t\t6600";
+static const CHAR tp_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n" + "s72\tS38\ts72\ti2\tS255\tS72\n" + "Component\tComponent\n" + "augustus\t\tMSITESTDIR\t0\tprop="val"\taugustus\n"; + typedef struct _msi_table { const CHAR *filename; @@ -591,6 +600,18 @@ static const msi_table pp_tables[] = ADD_TABLE(property), };
+static const msi_table tp_tables[] = +{ + ADD_TABLE(tp_component), + ADD_TABLE(directory), + ADD_TABLE(rof_feature), + ADD_TABLE(ci2_feature_comp), + ADD_TABLE(ci2_file), + ADD_TABLE(install_exec_seq), + ADD_TABLE(rof_media), + ADD_TABLE(property), +}; + /* cabinet definitions */
/* make the max size large so there is only one cab file */ @@ -2231,6 +2252,219 @@ static void test_publishsourcelist(void) RemoveDirectory("msitest"); }
+static UINT run_query(MSIHANDLE hdb, MSIHANDLE hrec, const char *query) +{ + MSIHANDLE hview = 0; + UINT r; + + r = MsiDatabaseOpenView(hdb, query, &hview); + if(r != ERROR_SUCCESS) + return r; + + r = MsiViewExecute(hview, hrec); + if(r == ERROR_SUCCESS) + r = MsiViewClose(hview); + MsiCloseHandle(hview); + return r; +} + +static void set_transform_summary_info(void) +{ + UINT r; + MSIHANDLE suminfo; + + /* build summmary info */ + r = MsiGetSummaryInformation(0, mstfile, 3, &suminfo); + todo_wine + { + ok(r == ERROR_SUCCESS , "Failed to open summaryinfo\n"); + } + + r = MsiSummaryInfoSetProperty(suminfo, PID_TITLE, VT_LPSTR, 0, NULL, "MSITEST"); + todo_wine + { + ok(r == ERROR_SUCCESS, "Failed to set summary info\n"); + } + + r = MsiSummaryInfoSetProperty(suminfo, PID_REVNUMBER, VT_LPSTR, 0, NULL, + "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}1.1.1;" + "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}1.1.1;" + "{4C0EAA15-0264-4E5A-8758-609EF142B92D}"); + todo_wine + { + ok(r == ERROR_SUCCESS , "Failed to set summary info\n"); + } + + r = MsiSummaryInfoSetProperty(suminfo, PID_PAGECOUNT, VT_I4, 100, NULL, NULL); + todo_wine + { + ok(r == ERROR_SUCCESS, "Failed to set summary info\n"); + } + + r = MsiSummaryInfoPersist(suminfo); + todo_wine + { + ok(r == ERROR_SUCCESS , "Failed to make summary info persist\n"); + } + + r = MsiCloseHandle(suminfo); + todo_wine + { + ok(r == ERROR_SUCCESS , "Failed to close suminfo\n"); + } +} + +static void generate_transform(void) +{ + MSIHANDLE hdb1, hdb2; + LPCSTR query; + UINT r; + + /* start with two identical databases */ + CopyFile(msifile, msifile2, FALSE); + + r = MsiOpenDatabase(msifile2, MSIDBOPEN_TRANSACT, &hdb1); + ok(r == ERROR_SUCCESS , "Failed to create database\n"); + + r = MsiDatabaseCommit(hdb1); + ok(r == ERROR_SUCCESS , "Failed to commit database\n"); + + r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb2); + ok(r == ERROR_SUCCESS , "Failed to create database\n"); + + query = "INSERT INTO `Property` ( `Property`, `Value` ) VALUES ( 'prop', 'val' )"; + r = run_query(hdb1, 0, query); + ok(r == ERROR_SUCCESS, "failed to add property\n"); + + /* database needs to be committed */ + MsiDatabaseCommit(hdb1); + + r = MsiDatabaseGenerateTransform(hdb1, hdb2, mstfile, 0, 0); + ok(r == ERROR_SUCCESS, "return code %d, should be ERROR_SUCCESS\n", r); + + r = MsiCreateTransformSummaryInfo(hdb2, hdb2, mstfile, 0, 0); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + + MsiCloseHandle(hdb1); + MsiCloseHandle(hdb2); +} + +/* data for generating a transform */ + +/* tables transform names - encoded as they would be in an msi database file */ +static const WCHAR name1[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0 }; /* _StringData */ +static const WCHAR name2[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0 }; /* _StringPool */ +static const WCHAR name3[] = { 0x4840, 0x4559, 0x44f2, 0x4568, 0x4737, 0 }; /* Property */ + +/* data in each table */ +static const char data1[] = /* _StringData */ + "propval"; /* all the strings squashed together */ + +static const WCHAR data2[] = { /* _StringPool */ +/* len, refs */ + 0, 0, /* string 0 '' */ + 4, 1, /* string 1 'prop' */ + 3, 1, /* string 2 'val' */ +}; + +static const WCHAR data3[] = { /* Property */ + 0x0201, 0x0001, 0x0002, +}; + +static const struct { + LPCWSTR name; + const void *data; + DWORD size; +} table_transform_data[] = +{ + { name1, data1, sizeof data1 - 1 }, + { name2, data2, sizeof data2 }, + { name3, data3, sizeof data3 }, +}; + +#define NUM_TRANSFORM_TABLES (sizeof table_transform_data/sizeof table_transform_data[0]) + +static void generate_transform_manual(void) +{ + IStorage *stg = NULL; + IStream *stm; + WCHAR name[0x20]; + HRESULT r; + DWORD i, count; + const DWORD mode = STGM_CREATE|STGM_READWRITE|STGM_DIRECT|STGM_SHARE_EXCLUSIVE; + + const CLSID CLSID_MsiTransform = { 0xc1082,0,0,{0xc0,0,0,0,0,0,0,0x46}}; + + MultiByteToWideChar(CP_ACP, 0, mstfile, -1, name, 0x20); + + r = StgCreateDocfile(name, mode, 0, &stg); + ok(r == S_OK, "failed to create storage\n"); + if (!stg) + return; + + r = IStorage_SetClass(stg, &CLSID_MsiTransform); + ok(r == S_OK, "failed to set storage type\n"); + + for (i=0; i<NUM_TRANSFORM_TABLES; i++) + { + r = IStorage_CreateStream(stg, table_transform_data[i].name, + STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm); + if (FAILED(r)) + { + ok(0, "failed to create stream %08x\n", r); + continue; + } + + r = IStream_Write(stm, table_transform_data[i].data, + table_transform_data[i].size, &count); + if (FAILED(r) || count != table_transform_data[i].size) + ok(0, "failed to write stream\n"); + IStream_Release(stm); + } + + IStorage_Release(stg); + + set_transform_summary_info(); +} + +static void test_transformprop(void) +{ + UINT r; + + CreateDirectoryA("msitest", NULL); + CreateDirectoryA("msitest\msitest", NULL); + create_file("msitest\augustus", 500); + + create_database(msifile, tp_tables, sizeof(tp_tables) / sizeof(msi_table)); + + MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL); + + r = MsiInstallProductA(msifile, NULL); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + ok(!delete_pf("msitest\augustus", TRUE), "File installed\n"); + ok(!delete_pf("msitest", FALSE), "File installed\n"); + + if (0) + generate_transform(); + else + generate_transform_manual(); + + r = MsiInstallProductA(msifile, "TRANSFORMS=winetest.mst"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + todo_wine + { + ok(delete_pf("msitest\augustus", TRUE), "File not installed\n"); + ok(delete_pf("msitest", FALSE), "File not installed\n"); + } + + /* Delete the files in the temp (current) folder */ + DeleteFile(msifile); + DeleteFile(msifile2); + DeleteFile(mstfile); + DeleteFile("msitest\augustus"); + RemoveDirectory("msitest"); +} + START_TEST(install) { DWORD len; @@ -2263,6 +2497,7 @@ START_TEST(install) test_setpropertyfolder(); test_publish(); test_publishsourcelist(); + test_transformprop();
SetCurrentDirectoryA(prev_path); } diff --git a/include/msiquery.h b/include/msiquery.h index 5ea654c..5a3f292 100644 --- a/include/msiquery.h +++ b/include/msiquery.h @@ -249,6 +249,10 @@ UINT WINAPI MsiPreviewBillboardA(MSIHANDLE, LPCSTR, LPCSTR); UINT WINAPI MsiPreviewBillboardW(MSIHANDLE, LPCWSTR, LPCWSTR); #define MsiPreviewBillboard WINELIB_NAME_AW(MsiPreviewBillboard)
+UINT WINAPI MsiCreateTransformSummaryInfoA(MSIHANDLE, MSIHANDLE, LPCSTR, int, int); +UINT WINAPI MsiCreateTransformSummaryInfoW(MSIHANDLE, MSIHANDLE, LPCWSTR, int, int); +#define MsiCreateTransformSummaryInfo WINELIB_NAME_AW(MsiCreateTransformSummaryInfo) + UINT WINAPI MsiGetSummaryInformationA(MSIHANDLE, LPCSTR, UINT, MSIHANDLE *); UINT WINAPI MsiGetSummaryInformationW(MSIHANDLE, LPCWSTR, UINT, MSIHANDLE *); #define MsiGetSummaryInformation WINELIB_NAME_AW(MsiGetSummaryInformation)