From dc3060c542661173937d3aa948f51ced7bbbdd5b Mon Sep 17 00:00:00 2001 From: James Hawkins Date: Mon, 16 Jul 2007 14:45:29 -0700 Subject: [PATCH] msi: Load the AdminProperties stream if the package is an Admin package. --- dlls/msi/action.c | 2 +- dlls/msi/msipriv.h | 3 +- dlls/msi/package.c | 20 +++++++++++ dlls/msi/string.c | 4 +-- dlls/msi/table.c | 8 ++--- dlls/msi/tests/install.c | 71 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 100 insertions(+), 8 deletions(-) diff --git a/dlls/msi/action.c b/dlls/msi/action.c index 10443c6f4f8..953ecb52283 100644 --- a/dlls/msi/action.c +++ b/dlls/msi/action.c @@ -293,7 +293,7 @@ static void ui_actioninfo(MSIPACKAGE *package, LPCWSTR action, BOOL start, msiobj_release(&row->hdr); } -static UINT msi_parse_command_line( MSIPACKAGE *package, LPCWSTR szCommandLine ) +UINT msi_parse_command_line( MSIPACKAGE *package, LPCWSTR szCommandLine ) { LPCWSTR ptr,ptr2; BOOL quote; diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index 3253a5dc630..a94866aef82 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -605,7 +605,7 @@ extern MSICONDITION MSI_DatabaseIsTablePersistent( MSIDATABASE *db, LPCWSTR tabl extern UINT read_raw_stream_data( MSIDATABASE *db, LPCWSTR stname, USHORT **pdata, UINT *psz ); -extern UINT read_stream_data( IStorage *stg, LPCWSTR stname, +extern UINT read_stream_data( IStorage *stg, LPCWSTR stname, BOOL table, BYTE **pdata, UINT *psz ); extern UINT write_stream_data( IStorage *stg, LPCWSTR stname, LPCVOID data, UINT sz, BOOL bTable ); @@ -623,6 +623,7 @@ extern UINT ACTION_DialogBox( MSIPACKAGE*, LPCWSTR); extern UINT ACTION_ForceReboot(MSIPACKAGE *package); extern UINT MSI_Sequence( MSIPACKAGE *package, LPCWSTR szTable, INT iSequenceMode ); extern UINT MSI_SetFeatureStates( MSIPACKAGE *package ); +extern UINT msi_parse_command_line( MSIPACKAGE *package, LPCWSTR szCommandLine ); /* record internals */ extern UINT MSI_RecordSetIStream( MSIRECORD *, unsigned int, IStream *); diff --git a/dlls/msi/package.c b/dlls/msi/package.c index 2fb7fbeda03..0309dc38609 100644 --- a/dlls/msi/package.c +++ b/dlls/msi/package.c @@ -720,6 +720,23 @@ static MSIPACKAGE *msi_alloc_package( void ) return package; } +static UINT msi_load_admin_properties(MSIPACKAGE *package) +{ + BYTE *data; + UINT r, sz; + + static const WCHAR stmname[] = {'A','d','m','i','n','P','r','o','p','e','r','t','i','e','s',0}; + + r = read_stream_data(package->db->storage, stmname, FALSE, &data, &sz); + if (r != ERROR_SUCCESS) + return r; + + r = msi_parse_command_line(package, (WCHAR *)data); + + msi_free(data); + return r; +} + MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db, LPCWSTR base_url ) { static const WCHAR szLevel[] = { 'U','I','L','e','v','e','l',0 }; @@ -750,6 +767,9 @@ MSIPACKAGE *MSI_CreatePackage( MSIDATABASE *db, LPCWSTR base_url ) package->ProductCode = msi_dup_property( package, szProductCode ); set_installed_prop( package ); msi_load_summary_properties( package ); + + if (package->WordCount & MSIWORDCOUNT_ADMINISTRATIVE) + msi_load_admin_properties( package ); } return package; diff --git a/dlls/msi/string.c b/dlls/msi/string.c index fe1f5cc7c1b..0cacf1e64bd 100644 --- a/dlls/msi/string.c +++ b/dlls/msi/string.c @@ -521,10 +521,10 @@ string_table *msi_load_string_table( IStorage *stg, UINT *bytes_per_strref ) UINT r, datasize = 0, poolsize = 0, codepage; DWORD i, count, offset, len, n, refs; - r = read_stream_data( stg, szStringPool, (BYTE **)&pool, &poolsize ); + r = read_stream_data( stg, szStringPool, TRUE, (BYTE **)&pool, &poolsize ); if( r != ERROR_SUCCESS) goto end; - r = read_stream_data( stg, szStringData, (BYTE **)&data, &datasize ); + r = read_stream_data( stg, szStringData, TRUE, (BYTE **)&data, &datasize ); if( r != ERROR_SUCCESS) goto end; diff --git a/dlls/msi/table.c b/dlls/msi/table.c index fb414a2f9b4..69a033cda06 100644 --- a/dlls/msi/table.c +++ b/dlls/msi/table.c @@ -262,7 +262,7 @@ void enum_stream_names( IStorage *stg ) IEnumSTATSTG_Release( stgenum ); } -UINT read_stream_data( IStorage *stg, LPCWSTR stname, +UINT read_stream_data( IStorage *stg, LPCWSTR stname, BOOL table, BYTE **pdata, UINT *psz ) { HRESULT r; @@ -273,7 +273,7 @@ UINT read_stream_data( IStorage *stg, LPCWSTR stname, STATSTG stat; LPWSTR encname; - encname = encode_streamname(TRUE, stname); + encname = encode_streamname(table, stname); TRACE("%s -> %s\n",debugstr_w(stname),debugstr_w(encname)); @@ -506,7 +506,7 @@ static UINT read_table_from_storage( MSITABLE *t, IStorage *stg ) row_size = msi_table_get_row_size( t->colinfo, t->col_count ); /* if we can't read the table, just assume that it's empty */ - read_stream_data( stg, t->name, &rawdata, &rawsize ); + read_stream_data( stg, t->name, TRUE, &rawdata, &rawsize ); if( !rawdata ) return ERROR_SUCCESS; @@ -1992,7 +1992,7 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg, TRACE("%p %p %p %s\n", db, stg, st, debugstr_w(name) ); /* read the transform data */ - read_stream_data( stg, name, &rawdata, &rawsize ); + read_stream_data( stg, name, TRUE, &rawdata, &rawsize ); if ( !rawdata ) { TRACE("table %s empty\n", debugstr_w(name) ); diff --git a/dlls/msi/tests/install.c b/dlls/msi/tests/install.c index 0d9d7034a2b..164040f5d81 100644 --- a/dlls/msi/tests/install.c +++ b/dlls/msi/tests/install.c @@ -443,6 +443,11 @@ static const CHAR adm_admin_exec_seq_dat[] = "Action\tCondition\tSequence\n" "InstallValidate\t\t1400\n" "LaunchConditions\t\t100"; +static const CHAR amp_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n" + "s72\tS38\ts72\ti2\tS255\tS72\n" + "Component\tComponent\n" + "augustus\t\tMSITESTDIR\t0\tMYPROP=2718\taugustus\n"; + typedef struct _msi_table { const CHAR *filename; @@ -667,6 +672,18 @@ static const msi_table adm_tables[] = ADD_TABLE(adm_admin_exec_seq), }; +static const msi_table amp_tables[] = +{ + ADD_TABLE(amp_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 */ @@ -2635,6 +2652,59 @@ static void test_admin(void) RemoveDirectory("msitest"); } +static void set_admin_property_stream(LPCSTR file) +{ + IStorage *stg; + IStream *stm; + WCHAR fileW[MAX_PATH]; + HRESULT hr; + DWORD count; + const DWORD mode = STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE; + + /* AdminProperties */ + static const WCHAR stmname[] = {0x41ca,0x4330,0x3e71,0x44b5,0x4233,0x45f5,0x422c,0x4836,0}; + static const WCHAR data[] = {'M','Y','P','R','O','P','=','2','7','1','8',0}; + + MultiByteToWideChar(CP_ACP, 0, file, -1, fileW, MAX_PATH); + + hr = StgOpenStorage(fileW, NULL, mode, NULL, 0, &stg); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + if (!stg) + return; + + hr = IStorage_CreateStream(stg, stmname, STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + + hr = IStream_Write(stm, data, sizeof(data) - 1, &count); + ok(hr == S_OK, "Expected S_OK, got %d\n", hr); + + IStream_Release(stm); + IStorage_Release(stg); +} + +static void test_adminprops(void) +{ + UINT r; + + CreateDirectoryA("msitest", NULL); + create_file("msitest\\augustus", 500); + + create_database(msifile, amp_tables, sizeof(amp_tables) / sizeof(msi_table)); + set_admin_summary_info(msifile); + set_admin_property_stream(msifile); + + 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"); + + DeleteFile(msifile); + DeleteFile("msitest\\augustus"); + RemoveDirectory("msitest"); +} + START_TEST(install) { DWORD len; @@ -2670,6 +2740,7 @@ START_TEST(install) test_transformprop(); test_currentworkingdir(); test_admin(); + test_adminprops(); SetCurrentDirectoryA(prev_path); }