2007-04-29 03:12:09 +02:00
/*
2007-05-01 03:53:26 +02:00
* Copyright ( C ) 2007 Mike McCormack for CodeWeavers
2007-04-29 03:12:09 +02:00
* Copyright ( C ) 2007 Misha Koshelev
*
2007-05-01 03:53:26 +02:00
* A test program for Microsoft Installer OLE automation functionality .
2007-04-29 03:12:09 +02:00
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 , USA
*/
# define COBJMACROS
# include <stdio.h>
# include <windows.h>
# include <msiquery.h>
# include <msidefs.h>
# include <msi.h>
# include <fci.h>
# include "wine/test.h"
static const char * msifile = " winetest.msi " ;
static const WCHAR szMsifile [ ] = { ' w ' , ' i ' , ' n ' , ' e ' , ' t ' , ' e ' , ' s ' , ' t ' , ' . ' , ' m ' , ' s ' , ' i ' , 0 } ;
CHAR CURR_DIR [ MAX_PATH ] ;
EXCEPINFO excepinfo ;
/*
* OLE automation data
* */
static const WCHAR szProgId [ ] = { ' W ' , ' i ' , ' n ' , ' d ' , ' o ' , ' w ' , ' s ' , ' I ' , ' n ' , ' s ' , ' t ' , ' a ' , ' l ' , ' l ' , ' e ' , ' r ' , ' . ' , ' I ' , ' n ' , ' s ' , ' t ' , ' a ' , ' l ' , ' l ' , ' e ' , ' r ' , 0 } ;
static IDispatch * pInstaller ;
/* msi database data */
static const CHAR component_dat [ ] = " Component \t ComponentId \t Directory_ \t Attributes \t Condition \t KeyPath \n "
" s72 \t S38 \t s72 \t i2 \t S255 \t S72 \n "
" Component \t Component \n "
" Five \t {8CC92E9D-14B2-4CA4-B2AA-B11D02078087} \t NEWDIR \t 2 \t \t five.txt \n "
" Four \t {FD37B4EA-7209-45C0-8917-535F35A2F080} \t CABOUTDIR \t 2 \t \t four.txt \n "
" One \t {783B242E-E185-4A56-AF86-C09815EC053C} \t MSITESTDIR \t 2 \t \t one.txt \n "
" Three \t {010B6ADD-B27D-4EDD-9B3D-34C4F7D61684} \t CHANGEDDIR \t 2 \t \t three.txt \n "
" Two \t {BF03D1A6-20DA-4A65-82F3-6CAC995915CE} \t FIRSTDIR \t 2 \t \t two.txt \n "
" dangler \t {6091DF25-EF96-45F1-B8E9-A9B1420C7A3C} \t TARGETDIR \t 4 \t \t regdata \n "
" component \t \t MSITESTDIR \t 0 \t 1 \t file \n "
" service_comp \t \t MSITESTDIR \t 0 \t 1 \t service_file " ;
static const CHAR directory_dat [ ] = " Directory \t Directory_Parent \t DefaultDir \n "
" s72 \t S72 \t l255 \n "
" Directory \t Directory \n "
" CABOUTDIR \t MSITESTDIR \t cabout \n "
" CHANGEDDIR \t MSITESTDIR \t changed:second \n "
" FIRSTDIR \t MSITESTDIR \t first \n "
" MSITESTDIR \t ProgramFilesFolder \t msitest \n "
" NEWDIR \t CABOUTDIR \t new \n "
" ProgramFilesFolder \t TARGETDIR \t . \n "
" TARGETDIR \t \t SourceDir " ;
static const CHAR feature_dat [ ] = " Feature \t Feature_Parent \t Title \t Description \t Display \t Level \t Directory_ \t Attributes \n "
" s38 \t S38 \t L64 \t L255 \t I2 \t i2 \t S72 \t i2 \n "
" Feature \t Feature \n "
" Five \t \t Five \t The Five Feature \t 5 \t 3 \t NEWDIR \t 0 \n "
" Four \t \t Four \t The Four Feature \t 4 \t 3 \t CABOUTDIR \t 0 \n "
" One \t \t One \t The One Feature \t 1 \t 3 \t MSITESTDIR \t 0 \n "
" Three \t One \t Three \t The Three Feature \t 3 \t 3 \t CHANGEDDIR \t 0 \n "
" Two \t One \t Two \t The Two Feature \t 2 \t 3 \t FIRSTDIR \t 0 \n "
" feature \t \t \t \t 2 \t 1 \t TARGETDIR \t 0 \n "
" service_feature \t \t \t \t 2 \t 1 \t TARGETDIR \t 0 " ;
static const CHAR feature_comp_dat [ ] = " Feature_ \t Component_ \n "
" s38 \t s72 \n "
" FeatureComponents \t Feature_ \t Component_ \n "
" Five \t Five \n "
" Four \t Four \n "
" One \t One \n "
" Three \t Three \n "
" Two \t Two \n "
" feature \t component \n "
" service_feature \t service_comp \n " ;
static const CHAR file_dat [ ] = " File \t Component_ \t FileName \t FileSize \t Version \t Language \t Attributes \t Sequence \n "
" s72 \t s72 \t l255 \t i4 \t S72 \t S20 \t I2 \t i2 \n "
" File \t File \n "
" five.txt \t Five \t five.txt \t 1000 \t \t \t 16384 \t 5 \n "
" four.txt \t Four \t four.txt \t 1000 \t \t \t 16384 \t 4 \n "
" one.txt \t One \t one.txt \t 1000 \t \t \t 0 \t 1 \n "
" three.txt \t Three \t three.txt \t 1000 \t \t \t 0 \t 3 \n "
" two.txt \t Two \t two.txt \t 1000 \t \t \t 0 \t 2 \n "
" file \t component \t filename \t 100 \t \t \t 8192 \t 1 \n "
" service_file \t service_comp \t service.exe \t 100 \t \t \t 8192 \t 1 " ;
static const CHAR install_exec_seq_dat [ ] = " Action \t Condition \t Sequence \n "
" s72 \t S255 \t I2 \n "
" InstallExecuteSequence \t Action \n "
" AllocateRegistrySpace \t NOT Installed \t 1550 \n "
" CostFinalize \t \t 1000 \n "
" CostInitialize \t \t 800 \n "
" FileCost \t \t 900 \n "
" InstallFiles \t \t 4000 \n "
" InstallServices \t \t 5000 \n "
" InstallFinalize \t \t 6600 \n "
" InstallInitialize \t \t 1500 \n "
" InstallValidate \t \t 1400 \n "
" LaunchConditions \t \t 100 \n "
" WriteRegistryValues \t SourceDir And SOURCEDIR \t 5000 " ;
static const CHAR media_dat [ ] = " DiskId \t LastSequence \t DiskPrompt \t Cabinet \t VolumeLabel \t Source \n "
" i2 \t i4 \t L64 \t S255 \t S32 \t S72 \n "
" Media \t DiskId \n "
" 1 \t 3 \t \t \t DISK1 \t \n "
" 2 \t 5 \t \t msitest.cab \t DISK2 \t \n " ;
static const CHAR property_dat [ ] = " Property \t Value \n "
" s72 \t l0 \n "
" Property \t Property \n "
" DefaultUIFont \t DlgFont8 \n "
" HASUIRUN \t 0 \n "
" INSTALLLEVEL \t 3 \n "
" InstallMode \t Typical \n "
" Manufacturer \t Wine \n "
" PIDTemplate \t 12345<###-%%%%%%%>@@@@@ \n "
" ProductCode \t {F1C3AF50-8B56-4A69-A00C-00773FE42F30} \n "
" ProductID \t none \n "
" ProductLanguage \t 1033 \n "
" ProductName \t MSITEST \n "
" ProductVersion \t 1.1.1 \n "
" PROMPTROLLBACKCOST \t P \n "
" Setup \t Setup \n "
" UpgradeCode \t {CE067E8D-2E1A-4367-B734-4EB2BDAD6565} " ;
static const CHAR registry_dat [ ] = " Registry \t Root \t Key \t Name \t Value \t Component_ \n "
" s72 \t i2 \t l255 \t L255 \t L0 \t s72 \n "
" Registry \t Registry \n "
" Apples \t 2 \t SOFTWARE \\ Wine \\ msitest \t Name \t imaname \t One \n "
" Oranges \t 2 \t SOFTWARE \\ Wine \\ msitest \t number \t #314 \t Two \n "
" regdata \t 2 \t SOFTWARE \\ Wine \\ msitest \t blah \t bad \t dangler \n "
" OrderTest \t 2 \t SOFTWARE \\ Wine \\ msitest \t OrderTestName \t OrderTestValue \t component " ;
static const CHAR service_install_dat [ ] = " ServiceInstall \t Name \t DisplayName \t ServiceType \t StartType \t ErrorControl \t "
" LoadOrderGroup \t Dependencies \t StartName \t Password \t Arguments \t Component_ \t Description \n "
" s72 \t s255 \t L255 \t i4 \t i4 \t i4 \t S255 \t S255 \t S255 \t S255 \t S255 \t s72 \t L255 \n "
" ServiceInstall \t ServiceInstall \n "
" TestService \t TestService \t TestService \t 2 \t 3 \t 0 \t \t \t TestService \t \t \t service_comp \t \t " ;
static const CHAR service_control_dat [ ] = " ServiceControl \t Name \t Event \t Arguments \t Wait \t Component_ \n "
" s72 \t l255 \t i2 \t L255 \t I2 \t s72 \n "
" ServiceControl \t ServiceControl \n "
" ServiceControl \t TestService \t 8 \t \t 0 \t service_comp " ;
typedef struct _msi_table
{
const CHAR * filename ;
const CHAR * data ;
int size ;
} msi_table ;
# define ADD_TABLE(x) {#x".idt", x##_dat, sizeof(x##_dat)}
static const msi_table tables [ ] =
{
ADD_TABLE ( component ) ,
ADD_TABLE ( directory ) ,
ADD_TABLE ( feature ) ,
ADD_TABLE ( feature_comp ) ,
ADD_TABLE ( file ) ,
ADD_TABLE ( install_exec_seq ) ,
ADD_TABLE ( media ) ,
ADD_TABLE ( property ) ,
ADD_TABLE ( registry ) ,
ADD_TABLE ( service_install ) ,
ADD_TABLE ( service_control )
} ;
/*
* Database Helpers
*/
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 void write_msi_summary_info ( MSIHANDLE db )
{
MSIHANDLE summary ;
UINT r ;
r = MsiGetSummaryInformationA ( db , NULL , 4 , & summary ) ;
ok ( r = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %u \n " , r ) ;
r = MsiSummaryInfoSetPropertyA ( summary , PID_TEMPLATE , VT_LPSTR , 0 , NULL , " ;1033 " ) ;
ok ( r = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %u \n " , r ) ;
r = MsiSummaryInfoSetPropertyA ( summary , PID_REVNUMBER , VT_LPSTR , 0 , NULL ,
" {004757CA-5092-49c2-AD20-28E1CE0DF5F2} " ) ;
ok ( r = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %u \n " , r ) ;
r = MsiSummaryInfoSetPropertyA ( summary , PID_PAGECOUNT , VT_I4 , 100 , NULL , NULL ) ;
ok ( r = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %u \n " , r ) ;
r = MsiSummaryInfoSetPropertyA ( summary , PID_WORDCOUNT , VT_I4 , 0 , NULL , NULL ) ;
ok ( r = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %u \n " , r ) ;
/* write the summary changes back to the stream */
r = MsiSummaryInfoPersist ( summary ) ;
ok ( r = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %u \n " , r ) ;
MsiCloseHandle ( summary ) ;
}
static void create_database ( const CHAR * name , const msi_table * tables , int num_tables )
{
MSIHANDLE db ;
UINT r ;
int j ;
r = MsiOpenDatabaseA ( name , MSIDBOPEN_CREATE , & db ) ;
ok ( r = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %u \n " , r ) ;
/* import the tables into the database */
for ( j = 0 ; j < num_tables ; j + + )
{
const msi_table * table = & tables [ j ] ;
write_file ( table - > filename , table - > data , ( table - > size - 1 ) * sizeof ( char ) ) ;
r = MsiDatabaseImportA ( db , CURR_DIR , table - > filename ) ;
ok ( r = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %u \n " , r ) ;
DeleteFileA ( table - > filename ) ;
}
write_msi_summary_info ( db ) ;
r = MsiDatabaseCommit ( db ) ;
ok ( r = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %u \n " , r ) ;
MsiCloseHandle ( db ) ;
}
/*
* Automation helpers and tests
*/
/* ok-like statement which takes two unicode strings as arguments */
static CHAR string1 [ MAX_PATH ] , string2 [ MAX_PATH ] ;
static UINT len ;
# define ok_w2(format, szString1, szString2) \
\
if ( lstrcmpW ( szString1 , szString2 ) ! = 0 ) \
{ \
len = WideCharToMultiByte ( CP_ACP , 0 , szString1 , - 1 , string1 , MAX_PATH , NULL , NULL ) ; \
ok ( len , " WideCharToMultiByteChar returned error %d \n " , GetLastError ( ) ) ; \
\
len = WideCharToMultiByte ( CP_ACP , 0 , szString2 , - 1 , string2 , MAX_PATH , NULL , NULL ) ; \
ok ( len , " WideCharToMultiByteChar returned error %d \n " , GetLastError ( ) ) ; \
\
ok ( 0 , format , string1 , string2 ) ; \
}
/* exception checker */
static WCHAR szSource [ ] = { ' M ' , ' s ' , ' i ' , ' ' , ' A ' , ' P ' , ' I ' , ' ' , ' E ' , ' r ' , ' r ' , ' o ' , ' r ' , 0 } ;
# define ok_exception(hr, szDescription) \
if ( hr = = DISP_E_EXCEPTION ) \
{ \
/* Compare wtype, source, and destination */ \
ok ( excepinfo . wCode = = 1000 , " Exception info was %d, expected 1000 \n " , excepinfo . wCode ) ; \
\
ok ( excepinfo . bstrSource ! = NULL , " Exception source was NULL \n " ) ; \
if ( excepinfo . bstrSource ) \
ok_w2 ( " Exception source was \" %s \" but expected to be \" %s \" \n " , excepinfo . bstrSource , szSource ) ; \
\
ok ( excepinfo . bstrDescription ! = NULL , " Exception description was NULL \n " ) ; \
2007-05-01 03:54:31 +02:00
if ( excepinfo . bstrDescription & & lstrcmpW ( excepinfo . bstrDescription , szDescription ) ! = 0 ) \
{ \
len = WideCharToMultiByte ( CP_ACP , 0 , excepinfo . bstrDescription , - 1 , string1 , MAX_PATH , NULL , NULL ) ; \
ok ( len , " WideCharToMultiByteChar returned error %d \n " , GetLastError ( ) ) ; \
\
len = WideCharToMultiByte ( CP_ACP , 0 , szDescription , - 1 , string2 , MAX_PATH , NULL , NULL ) ; \
ok ( len , " WideCharToMultiByteChar returned error %d \n " , GetLastError ( ) ) ; \
\
2007-05-08 00:49:17 +02:00
ok ( 0 , " Exception description was \" %s \" but expected to be \" %s \" \n " , string1 , string2 ) ; \
2007-05-01 03:54:31 +02:00
} \
2007-04-29 03:12:09 +02:00
}
2007-05-01 03:53:26 +02:00
static DISPID get_dispid ( IDispatch * disp , const char * name )
{
LPOLESTR str ;
UINT len ;
2007-05-04 02:01:10 +02:00
DISPID id = - 1 ;
2007-05-01 03:53:26 +02:00
HRESULT r ;
len = MultiByteToWideChar ( CP_ACP , 0 , name , - 1 , NULL , 0 ) ;
str = HeapAlloc ( GetProcessHeap ( ) , 0 , len * sizeof ( WCHAR ) ) ;
2007-05-04 02:01:10 +02:00
if ( str )
{
len = MultiByteToWideChar ( CP_ACP , 0 , name , - 1 , str , len ) ;
r = IDispatch_GetIDsOfNames ( disp , & IID_NULL , & str , 1 , 0 , & id ) ;
HeapFree ( GetProcessHeap ( ) , 0 , str ) ;
if ( r ! = S_OK )
return - 1 ;
}
2007-05-01 03:53:26 +02:00
return id ;
}
static void test_dispid ( void )
{
todo_wine {
ok ( get_dispid ( pInstaller , " CreateRecord " ) = = 1 , " dispid wrong \n " ) ;
2007-05-08 00:50:30 +02:00
}
ok ( get_dispid ( pInstaller , " OpenPackage " ) = = 2 , " dispid wrong \n " ) ;
todo_wine {
2007-05-01 03:53:26 +02:00
ok ( get_dispid ( pInstaller , " OpenProduct " ) = = 3 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " OpenDatabase " ) = = 4 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " SummaryInformation " ) = = 5 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " UILevel " ) = = 6 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " EnableLog " ) = = 7 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " InstallProduct " ) = = 8 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " Version " ) = = 9 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " LastErrorRecord " ) = = 10 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " RegistryValue " ) = = 11 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " Environment " ) = = 12 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " FileAttributes " ) = = 13 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " FileSize " ) = = 15 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " FileVersion " ) = = 16 , " dispid wrong \n " ) ;
2007-05-08 00:50:30 +02:00
}
2007-05-01 03:53:26 +02:00
ok ( get_dispid ( pInstaller , " ProductState " ) = = 17 , " dispid wrong \n " ) ;
2007-05-08 00:50:30 +02:00
todo_wine {
2007-05-01 03:53:26 +02:00
ok ( get_dispid ( pInstaller , " ProductInfo " ) = = 18 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " ConfigureProduct " ) = = 19 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " ReinstallProduct " ) = = 20 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " CollectUserInfo " ) = = 21 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " ApplyPatch " ) = = 22 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " FeatureParent " ) = = 23 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " FeatureState " ) = = 24 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " UseFeature " ) = = 25 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " FeatureUsageCount " ) = = 26 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " FeatureUsageDate " ) = = 27 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " ConfigureFeature " ) = = 28 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " ReinstallFeature " ) = = 29 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " ProvideComponent " ) = = 30 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " ComponentPath " ) = = 31 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " ProvideQualifiedComponent " ) = = 32 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " QualifierDescription " ) = = 33 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " ComponentQualifiers " ) = = 34 , " dispid wrong \n " ) ;
2007-05-08 00:50:30 +02:00
}
2007-05-01 03:53:26 +02:00
ok ( get_dispid ( pInstaller , " Products " ) = = 35 , " dispid wrong \n " ) ;
2007-05-08 00:50:30 +02:00
todo_wine {
2007-05-01 03:53:26 +02:00
ok ( get_dispid ( pInstaller , " Features " ) = = 36 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " Components " ) = = 37 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " ComponentClients " ) = = 38 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " Patches " ) = = 39 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " RelatedProducts " ) = = 40 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " PatchInfo " ) = = 41 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " PatchTransforms " ) = = 42 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " AddSource " ) = = 43 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " ClearSourceList " ) = = 44 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " ForceSourceListResolution " ) = = 45 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " ShortcutTarget " ) = = 46 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " FileHash " ) = = 47 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " FileSignatureInfo " ) = = 48 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " RemovePatches " ) = = 49 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " ApplyMultiplePatches " ) = = 51 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " ProductsEx " ) = = 52 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " PatchesEx " ) = = 55 , " dispid wrong \n " ) ;
ok ( get_dispid ( pInstaller , " ExtractPatchXMLData " ) = = 57 , " dispid wrong \n " ) ;
}
/* MSDN claims the following functions exist but IDispatch->GetIDsOfNames disagrees */
if ( 0 )
{
get_dispid ( pInstaller , " ProductElevated " ) ;
get_dispid ( pInstaller , " ProductInfoFromScript " ) ;
get_dispid ( pInstaller , " ProvideAssembly " ) ;
get_dispid ( pInstaller , " CreateAdvertiseScript " ) ;
get_dispid ( pInstaller , " AdvertiseProduct " ) ;
get_dispid ( pInstaller , " PatchFiles " ) ;
}
}
2007-04-29 03:12:09 +02:00
/* Test basic IDispatch functions */
static void test_dispatch ( void )
{
2007-05-04 02:02:06 +02:00
static WCHAR szOpenPackage [ ] = { ' O ' , ' p ' , ' e ' , ' n ' , ' P ' , ' a ' , ' c ' , ' k ' , ' a ' , ' g ' , ' e ' , 0 } ;
2007-04-29 03:12:09 +02:00
static WCHAR szOpenPackageException [ ] = { ' O ' , ' p ' , ' e ' , ' n ' , ' P ' , ' a ' , ' c ' , ' k ' , ' a ' , ' g ' , ' e ' , ' , ' , ' P ' , ' a ' , ' c ' , ' k ' , ' a ' , ' g ' , ' e ' , ' P ' , ' a ' , ' t ' , ' h ' , ' , ' , ' O ' , ' p ' , ' t ' , ' i ' , ' o ' , ' n ' , ' s ' , 0 } ;
HRESULT hr ;
DISPID dispid ;
OLECHAR * name ;
VARIANT varresult ;
VARIANTARG vararg [ 2 ] ;
DISPPARAMS dispparams = { NULL , NULL , 0 , 0 } ;
/* Test getting ID of a function name that does not exist */
name = ( WCHAR * ) szMsifile ;
hr = IDispatch_GetIDsOfNames ( pInstaller , & IID_NULL , & name , 1 , LOCALE_USER_DEFAULT , & dispid ) ;
ok ( hr = = DISP_E_UNKNOWNNAME , " IDispatch::GetIDsOfNames returned 0x%08x \n " , hr ) ;
/* Test invoking this function */
hr = IDispatch_Invoke ( pInstaller , dispid , & IID_NULL , LOCALE_NEUTRAL , DISPATCH_METHOD , NULL , NULL , NULL , NULL ) ;
ok ( hr = = DISP_E_MEMBERNOTFOUND , " IDispatch::Invoke returned 0x%08x \n " , hr ) ;
/* Test getting ID of a function name that does exist */
name = ( WCHAR * ) szOpenPackage ;
hr = IDispatch_GetIDsOfNames ( pInstaller , & IID_NULL , & name , 1 , LOCALE_USER_DEFAULT , & dispid ) ;
ok ( SUCCEEDED ( hr ) , " IDispatch::GetIDsOfNames returned 0x%08x \n " , hr ) ;
/* Test invoking this function (without parameters passed) */
if ( 0 ) /* All of these crash MSI on Windows XP */
{
hr = IDispatch_Invoke ( pInstaller , dispid , & IID_NULL , LOCALE_NEUTRAL , DISPATCH_METHOD , NULL , NULL , NULL , NULL ) ;
hr = IDispatch_Invoke ( pInstaller , dispid , & IID_NULL , LOCALE_NEUTRAL , DISPATCH_METHOD , NULL , NULL , & excepinfo , NULL ) ;
VariantInit ( & varresult ) ;
hr = IDispatch_Invoke ( pInstaller , dispid , & IID_NULL , LOCALE_NEUTRAL , DISPATCH_METHOD , NULL , & varresult , & excepinfo , NULL ) ;
}
/* Try with NULL params */
hr = IDispatch_Invoke ( pInstaller , dispid , & IID_NULL , LOCALE_NEUTRAL , DISPATCH_METHOD , & dispparams , & varresult , & excepinfo , NULL ) ;
2007-05-01 03:54:31 +02:00
todo_wine ok ( hr = = DISP_E_TYPEMISMATCH , " IDispatch::Invoke returned 0x%08x \n " , hr ) ;
2007-04-29 03:12:09 +02:00
/* Try one empty parameter */
dispparams . rgvarg = vararg ;
dispparams . cArgs = 1 ;
VariantInit ( & vararg [ 0 ] ) ;
hr = IDispatch_Invoke ( pInstaller , dispid , & IID_NULL , LOCALE_NEUTRAL , DISPATCH_METHOD , & dispparams , & varresult , & excepinfo , NULL ) ;
2007-05-01 03:54:31 +02:00
todo_wine ok ( hr = = DISP_E_TYPEMISMATCH , " IDispatch::Invoke returned 0x%08x \n " , hr ) ;
2007-04-29 03:12:09 +02:00
/* Try one parameter, function requires two */
VariantInit ( & vararg [ 0 ] ) ;
V_VT ( & vararg [ 0 ] ) = VT_BSTR ;
V_BSTR ( & vararg [ 0 ] ) = SysAllocString ( szMsifile ) ;
hr = IDispatch_Invoke ( pInstaller , dispid , & IID_NULL , LOCALE_NEUTRAL , DISPATCH_METHOD , & dispparams , & varresult , & excepinfo , NULL ) ;
VariantClear ( & vararg [ 0 ] ) ;
ok ( hr = = DISP_E_EXCEPTION , " IDispatch::Invoke returned 0x%08x \n " , hr ) ;
ok_exception ( hr , szOpenPackageException ) ;
}
/* invocation helper function */
2007-05-04 02:02:06 +02:00
static HRESULT invoke ( IDispatch * pDispatch , LPCSTR szName , WORD wFlags , DISPPARAMS * pDispParams , VARIANT * pVarResult , VARTYPE vtResult )
2007-04-29 03:12:09 +02:00
{
2007-05-04 02:02:06 +02:00
OLECHAR * name = NULL ;
2007-04-29 03:12:09 +02:00
DISPID dispid ;
HRESULT hr ;
int i ;
2007-05-04 02:02:06 +02:00
UINT len ;
2007-04-29 03:12:09 +02:00
2007-05-04 02:02:31 +02:00
memset ( pVarResult , 0 , sizeof ( VARIANT ) ) ;
VariantInit ( pVarResult ) ;
2007-05-04 02:02:06 +02:00
len = MultiByteToWideChar ( CP_ACP , 0 , szName , - 1 , NULL , 0 ) ;
name = HeapAlloc ( GetProcessHeap ( ) , 0 , len * sizeof ( WCHAR ) ) ;
if ( ! name ) return E_FAIL ;
len = MultiByteToWideChar ( CP_ACP , 0 , szName , - 1 , name , len ) ;
2007-04-29 03:12:09 +02:00
hr = IDispatch_GetIDsOfNames ( pDispatch , & IID_NULL , & name , 1 , LOCALE_USER_DEFAULT , & dispid ) ;
2007-05-04 02:02:06 +02:00
HeapFree ( GetProcessHeap ( ) , 0 , name ) ;
2007-04-29 03:12:09 +02:00
ok ( SUCCEEDED ( hr ) , " IDispatch::GetIDsOfNames returned 0x%08x \n " , hr ) ;
if ( ! SUCCEEDED ( hr ) ) return hr ;
memset ( & excepinfo , 0 , sizeof ( excepinfo ) ) ;
hr = IDispatch_Invoke ( pDispatch , dispid , & IID_NULL , LOCALE_NEUTRAL , wFlags , pDispParams , pVarResult , & excepinfo , NULL ) ;
if ( SUCCEEDED ( hr ) )
{
ok ( V_VT ( pVarResult ) = = vtResult , " Variant result type is %d, expected %d \n " , V_VT ( pVarResult ) , vtResult ) ;
if ( vtResult ! = VT_EMPTY )
{
hr = VariantChangeTypeEx ( pVarResult , pVarResult , LOCALE_NEUTRAL , 0 , vtResult ) ;
ok ( SUCCEEDED ( hr ) , " VariantChangeTypeEx returned 0x%08x \n " , hr ) ;
}
}
for ( i = 0 ; i < pDispParams - > cArgs ; i + + )
VariantClear ( & pDispParams - > rgvarg [ i ] ) ;
return hr ;
}
/* Object_Property helper functions */
2007-05-04 02:02:31 +02:00
static HRESULT Installer_CreateRecord ( int count , IDispatch * * pRecord )
{
VARIANT varresult ;
VARIANTARG vararg [ 1 ] ;
DISPPARAMS dispparams = { vararg , NULL , sizeof ( vararg ) / sizeof ( VARIANTARG ) , 0 } ;
HRESULT hr ;
VariantInit ( & vararg [ 0 ] ) ;
V_VT ( & vararg [ 0 ] ) = VT_I4 ;
V_I4 ( & vararg [ 0 ] ) = count ;
hr = invoke ( pInstaller , " CreateRecord " , DISPATCH_METHOD , & dispparams , & varresult , VT_DISPATCH ) ;
* pRecord = V_DISPATCH ( & varresult ) ;
return hr ;
}
2007-04-29 03:12:09 +02:00
static HRESULT Installer_OpenPackage ( LPCWSTR szPackagePath , int options , IDispatch * * pSession )
{
VARIANT varresult ;
VARIANTARG vararg [ 2 ] ;
DISPPARAMS dispparams = { vararg , NULL , sizeof ( vararg ) / sizeof ( VARIANTARG ) , 0 } ;
HRESULT hr ;
VariantInit ( & vararg [ 1 ] ) ;
V_VT ( & vararg [ 1 ] ) = VT_BSTR ;
V_BSTR ( & vararg [ 1 ] ) = SysAllocString ( szPackagePath ) ;
VariantInit ( & vararg [ 0 ] ) ;
V_VT ( & vararg [ 0 ] ) = VT_I4 ;
V_I4 ( & vararg [ 0 ] ) = options ;
2007-05-04 02:02:06 +02:00
hr = invoke ( pInstaller , " OpenPackage " , DISPATCH_METHOD , & dispparams , & varresult , VT_DISPATCH ) ;
2007-04-29 03:12:09 +02:00
* pSession = V_DISPATCH ( & varresult ) ;
return hr ;
}
2007-05-08 00:50:05 +02:00
static HRESULT Installer_ProductState ( LPCWSTR szProduct , int * pInstallState )
{
VARIANT varresult ;
VARIANTARG vararg [ 1 ] ;
DISPPARAMS dispparams = { vararg , NULL , sizeof ( vararg ) / sizeof ( VARIANTARG ) , 0 } ;
HRESULT hr ;
VariantInit ( & vararg [ 0 ] ) ;
V_VT ( & vararg [ 0 ] ) = VT_BSTR ;
V_BSTR ( & vararg [ 0 ] ) = SysAllocString ( szProduct ) ;
hr = invoke ( pInstaller , " ProductState " , DISPATCH_PROPERTYGET , & dispparams , & varresult , VT_I4 ) ;
* pInstallState = V_I4 ( & varresult ) ;
VariantClear ( & varresult ) ;
return hr ;
}
static HRESULT Installer_Products ( IDispatch * * pStringList )
{
VARIANT varresult ;
DISPPARAMS dispparams = { NULL , NULL , 0 , 0 } ;
HRESULT hr ;
hr = invoke ( pInstaller , " Products " , DISPATCH_PROPERTYGET , & dispparams , & varresult , VT_DISPATCH ) ;
* pStringList = V_DISPATCH ( & varresult ) ;
return hr ;
}
2007-05-04 02:02:31 +02:00
static HRESULT Installer_VersionGet ( LPCWSTR szVersion )
{
VARIANT varresult ;
DISPPARAMS dispparams = { NULL , NULL , 0 , 0 } ;
HRESULT hr ;
hr = invoke ( pInstaller , " Version " , DISPATCH_PROPERTYGET , & dispparams , & varresult , VT_BSTR ) ;
lstrcpyW ( ( WCHAR * ) szVersion , V_BSTR ( & varresult ) ) ;
VariantClear ( & varresult ) ;
return hr ;
}
2007-05-05 06:17:56 +02:00
static HRESULT Session_Installer ( IDispatch * pSession , IDispatch * * pInst )
{
VARIANT varresult ;
DISPPARAMS dispparams = { NULL , NULL , 0 , 0 } ;
HRESULT hr ;
hr = invoke ( pSession , " Installer " , DISPATCH_PROPERTYGET , & dispparams , & varresult , VT_DISPATCH ) ;
* pInst = V_DISPATCH ( & varresult ) ;
return hr ;
}
2007-04-29 03:12:09 +02:00
static HRESULT Session_PropertyGet ( IDispatch * pSession , LPCWSTR szName , LPCWSTR szReturn )
{
VARIANT varresult ;
VARIANTARG vararg [ 1 ] ;
DISPPARAMS dispparams = { vararg , NULL , sizeof ( vararg ) / sizeof ( VARIANTARG ) , 0 } ;
HRESULT hr ;
VariantInit ( & vararg [ 0 ] ) ;
V_VT ( & vararg [ 0 ] ) = VT_BSTR ;
V_BSTR ( & vararg [ 0 ] ) = SysAllocString ( szName ) ;
2007-05-04 02:02:06 +02:00
hr = invoke ( pSession , " Property " , DISPATCH_PROPERTYGET , & dispparams , & varresult , VT_BSTR ) ;
2007-04-29 03:12:09 +02:00
lstrcpyW ( ( WCHAR * ) szReturn , V_BSTR ( & varresult ) ) ;
VariantClear ( & varresult ) ;
return hr ;
}
static HRESULT Session_PropertyPut ( IDispatch * pSession , LPCWSTR szName , LPCWSTR szValue )
{
VARIANT varresult ;
VARIANTARG vararg [ 2 ] ;
DISPID dispid = DISPID_PROPERTYPUT ;
DISPPARAMS dispparams = { vararg , & dispid , sizeof ( vararg ) / sizeof ( VARIANTARG ) , 1 } ;
VariantInit ( & vararg [ 1 ] ) ;
V_VT ( & vararg [ 1 ] ) = VT_BSTR ;
V_BSTR ( & vararg [ 1 ] ) = SysAllocString ( szName ) ;
VariantInit ( & vararg [ 0 ] ) ;
V_VT ( & vararg [ 0 ] ) = VT_BSTR ;
V_BSTR ( & vararg [ 0 ] ) = SysAllocString ( szValue ) ;
2007-05-04 02:02:06 +02:00
return invoke ( pSession , " Property " , DISPATCH_PROPERTYPUT , & dispparams , & varresult , VT_EMPTY ) ;
2007-04-29 03:12:09 +02:00
}
static HRESULT Session_LanguageGet ( IDispatch * pSession , UINT * pLangId )
{
VARIANT varresult ;
DISPPARAMS dispparams = { NULL , NULL , 0 , 0 } ;
HRESULT hr ;
2007-05-04 02:02:06 +02:00
hr = invoke ( pSession , " Language " , DISPATCH_PROPERTYGET , & dispparams , & varresult , VT_I4 ) ;
2007-04-29 03:12:09 +02:00
* pLangId = V_I4 ( & varresult ) ;
VariantClear ( & varresult ) ;
return hr ;
}
static HRESULT Session_ModeGet ( IDispatch * pSession , int iFlag , BOOL * pMode )
{
VARIANT varresult ;
VARIANTARG vararg [ 1 ] ;
DISPPARAMS dispparams = { vararg , NULL , sizeof ( vararg ) / sizeof ( VARIANTARG ) , 0 } ;
HRESULT hr ;
VariantInit ( & vararg [ 0 ] ) ;
V_VT ( & vararg [ 0 ] ) = VT_I4 ;
V_I4 ( & vararg [ 0 ] ) = iFlag ;
2007-05-04 02:02:06 +02:00
hr = invoke ( pSession , " Mode " , DISPATCH_PROPERTYGET , & dispparams , & varresult , VT_BOOL ) ;
2007-04-29 03:12:09 +02:00
* pMode = V_BOOL ( & varresult ) ;
VariantClear ( & varresult ) ;
return hr ;
}
static HRESULT Session_ModePut ( IDispatch * pSession , int iFlag , BOOL bMode )
{
VARIANT varresult ;
VARIANTARG vararg [ 2 ] ;
DISPID dispid = DISPID_PROPERTYPUT ;
DISPPARAMS dispparams = { vararg , & dispid , sizeof ( vararg ) / sizeof ( VARIANTARG ) , 1 } ;
VariantInit ( & vararg [ 1 ] ) ;
V_VT ( & vararg [ 1 ] ) = VT_I4 ;
V_I4 ( & vararg [ 1 ] ) = iFlag ;
VariantInit ( & vararg [ 0 ] ) ;
V_VT ( & vararg [ 0 ] ) = VT_BOOL ;
V_BOOL ( & vararg [ 0 ] ) = bMode ;
2007-05-04 02:02:06 +02:00
return invoke ( pSession , " Mode " , DISPATCH_PROPERTYPUT , & dispparams , & varresult , VT_EMPTY ) ;
2007-04-29 03:12:09 +02:00
}
static HRESULT Session_Database ( IDispatch * pSession , IDispatch * * pDatabase )
{
VARIANT varresult ;
DISPPARAMS dispparams = { NULL , NULL , 0 , 0 } ;
HRESULT hr ;
2007-05-04 02:02:06 +02:00
hr = invoke ( pSession , " Database " , DISPATCH_PROPERTYGET , & dispparams , & varresult , VT_DISPATCH ) ;
2007-04-29 03:12:09 +02:00
* pDatabase = V_DISPATCH ( & varresult ) ;
return hr ;
}
static HRESULT Session_DoAction ( IDispatch * pSession , LPCWSTR szAction , int * iReturn )
{
VARIANT varresult ;
VARIANTARG vararg [ 1 ] ;
DISPPARAMS dispparams = { vararg , NULL , sizeof ( vararg ) / sizeof ( VARIANTARG ) , 0 } ;
HRESULT hr ;
VariantInit ( & vararg [ 0 ] ) ;
V_VT ( & vararg [ 0 ] ) = VT_BSTR ;
V_BSTR ( & vararg [ 0 ] ) = SysAllocString ( szAction ) ;
2007-05-04 02:02:06 +02:00
hr = invoke ( pSession , " DoAction " , DISPATCH_METHOD , & dispparams , & varresult , VT_I4 ) ;
2007-04-29 03:12:09 +02:00
* iReturn = V_I4 ( & varresult ) ;
VariantClear ( & varresult ) ;
return hr ;
}
static HRESULT Session_SetInstallLevel ( IDispatch * pSession , long iInstallLevel )
{
VARIANT varresult ;
VARIANTARG vararg [ 1 ] ;
DISPPARAMS dispparams = { vararg , NULL , sizeof ( vararg ) / sizeof ( VARIANTARG ) , 0 } ;
VariantInit ( & vararg [ 0 ] ) ;
V_VT ( & vararg [ 0 ] ) = VT_I4 ;
V_I4 ( & vararg [ 0 ] ) = iInstallLevel ;
2007-05-04 02:02:06 +02:00
return invoke ( pSession , " SetInstallLevel " , DISPATCH_METHOD , & dispparams , & varresult , VT_EMPTY ) ;
2007-04-29 03:12:09 +02:00
}
static HRESULT Session_FeatureCurrentState ( IDispatch * pSession , LPCWSTR szName , int * pState )
{
VARIANT varresult ;
VARIANTARG vararg [ 1 ] ;
DISPPARAMS dispparams = { vararg , NULL , sizeof ( vararg ) / sizeof ( VARIANTARG ) , 0 } ;
HRESULT hr ;
VariantInit ( & vararg [ 0 ] ) ;
V_VT ( & vararg [ 0 ] ) = VT_BSTR ;
V_BSTR ( & vararg [ 0 ] ) = SysAllocString ( szName ) ;
2007-05-04 02:02:06 +02:00
hr = invoke ( pSession , " FeatureCurrentState " , DISPATCH_PROPERTYGET , & dispparams , & varresult , VT_I4 ) ;
2007-04-29 03:12:09 +02:00
* pState = V_I4 ( & varresult ) ;
VariantClear ( & varresult ) ;
return hr ;
}
static HRESULT Session_FeatureRequestStateGet ( IDispatch * pSession , LPCWSTR szName , int * pState )
{
VARIANT varresult ;
VARIANTARG vararg [ 1 ] ;
DISPPARAMS dispparams = { vararg , NULL , sizeof ( vararg ) / sizeof ( VARIANTARG ) , 0 } ;
HRESULT hr ;
VariantInit ( & vararg [ 0 ] ) ;
V_VT ( & vararg [ 0 ] ) = VT_BSTR ;
V_BSTR ( & vararg [ 0 ] ) = SysAllocString ( szName ) ;
2007-05-04 02:02:06 +02:00
hr = invoke ( pSession , " FeatureRequestState " , DISPATCH_PROPERTYGET , & dispparams , & varresult , VT_I4 ) ;
2007-04-29 03:12:09 +02:00
* pState = V_I4 ( & varresult ) ;
VariantClear ( & varresult ) ;
return hr ;
}
static HRESULT Session_FeatureRequestStatePut ( IDispatch * pSession , LPCWSTR szName , int iState )
{
VARIANT varresult ;
VARIANTARG vararg [ 2 ] ;
DISPID dispid = DISPID_PROPERTYPUT ;
DISPPARAMS dispparams = { vararg , & dispid , sizeof ( vararg ) / sizeof ( VARIANTARG ) , 1 } ;
VariantInit ( & vararg [ 1 ] ) ;
V_VT ( & vararg [ 1 ] ) = VT_BSTR ;
V_BSTR ( & vararg [ 1 ] ) = SysAllocString ( szName ) ;
VariantInit ( & vararg [ 0 ] ) ;
V_VT ( & vararg [ 0 ] ) = VT_I4 ;
V_I4 ( & vararg [ 0 ] ) = iState ;
2007-05-04 02:02:06 +02:00
return invoke ( pSession , " FeatureRequestState " , DISPATCH_PROPERTYPUT , & dispparams , & varresult , VT_EMPTY ) ;
2007-04-29 03:12:09 +02:00
}
static HRESULT Database_OpenView ( IDispatch * pDatabase , LPCWSTR szSql , IDispatch * * pView )
{
VARIANT varresult ;
VARIANTARG vararg [ 1 ] ;
DISPPARAMS dispparams = { vararg , NULL , sizeof ( vararg ) / sizeof ( VARIANTARG ) , 0 } ;
HRESULT hr ;
VariantInit ( & vararg [ 0 ] ) ;
V_VT ( & vararg [ 0 ] ) = VT_BSTR ;
V_BSTR ( & vararg [ 0 ] ) = SysAllocString ( szSql ) ;
2007-05-04 02:02:06 +02:00
hr = invoke ( pDatabase , " OpenView " , DISPATCH_METHOD , & dispparams , & varresult , VT_DISPATCH ) ;
2007-04-29 03:12:09 +02:00
* pView = V_DISPATCH ( & varresult ) ;
return hr ;
}
static HRESULT View_Execute ( IDispatch * pView , IDispatch * pRecord )
{
VARIANT varresult ;
VARIANTARG vararg [ 1 ] ;
DISPPARAMS dispparams = { vararg , NULL , sizeof ( vararg ) / sizeof ( VARIANTARG ) , 0 } ;
VariantInit ( & vararg [ 0 ] ) ;
V_VT ( & vararg [ 0 ] ) = VT_DISPATCH ;
V_DISPATCH ( & vararg [ 0 ] ) = pRecord ;
2007-05-04 02:02:06 +02:00
return invoke ( pView , " Execute " , DISPATCH_METHOD , & dispparams , & varresult , VT_EMPTY ) ;
2007-04-29 03:12:09 +02:00
}
static HRESULT View_Fetch ( IDispatch * pView , IDispatch * * ppRecord )
{
VARIANT varresult ;
DISPPARAMS dispparams = { NULL , NULL , 0 , 0 } ;
2007-05-04 02:02:06 +02:00
HRESULT hr = invoke ( pView , " Fetch " , DISPATCH_METHOD , & dispparams , & varresult , VT_DISPATCH ) ;
2007-04-29 03:12:09 +02:00
* ppRecord = V_DISPATCH ( & varresult ) ;
return hr ;
}
static HRESULT View_Close ( IDispatch * pView )
{
VARIANT varresult ;
DISPPARAMS dispparams = { NULL , NULL , 0 , 0 } ;
2007-05-04 02:02:06 +02:00
return invoke ( pView , " Close " , DISPATCH_METHOD , & dispparams , & varresult , VT_EMPTY ) ;
2007-04-29 03:12:09 +02:00
}
2007-05-04 02:02:31 +02:00
static HRESULT Record_FieldCountGet ( IDispatch * pRecord , int * pFieldCount )
{
VARIANT varresult ;
DISPPARAMS dispparams = { NULL , NULL , 0 , 0 } ;
HRESULT hr = invoke ( pRecord , " FieldCount " , DISPATCH_PROPERTYGET , & dispparams , & varresult , VT_I4 ) ;
* pFieldCount = V_I4 ( & varresult ) ;
VariantClear ( & varresult ) ;
return hr ;
}
2007-04-29 03:12:09 +02:00
static HRESULT Record_StringDataGet ( IDispatch * pRecord , int iField , LPCWSTR szString )
{
VARIANT varresult ;
VARIANTARG vararg [ 1 ] ;
DISPPARAMS dispparams = { vararg , NULL , sizeof ( vararg ) / sizeof ( VARIANTARG ) , 0 } ;
HRESULT hr ;
VariantInit ( & vararg [ 0 ] ) ;
V_VT ( & vararg [ 0 ] ) = VT_I4 ;
V_I4 ( & vararg [ 0 ] ) = iField ;
2007-05-04 02:02:06 +02:00
hr = invoke ( pRecord , " StringData " , DISPATCH_PROPERTYGET , & dispparams , & varresult , VT_BSTR ) ;
2007-04-29 03:12:09 +02:00
lstrcpyW ( ( WCHAR * ) szString , V_BSTR ( & varresult ) ) ;
VariantClear ( & varresult ) ;
return hr ;
}
static HRESULT Record_StringDataPut ( IDispatch * pRecord , int iField , LPCWSTR szString )
{
VARIANT varresult ;
VARIANTARG vararg [ 2 ] ;
DISPID dispid = DISPID_PROPERTYPUT ;
DISPPARAMS dispparams = { vararg , & dispid , sizeof ( vararg ) / sizeof ( VARIANTARG ) , 1 } ;
VariantInit ( & vararg [ 1 ] ) ;
V_VT ( & vararg [ 1 ] ) = VT_I4 ;
V_I4 ( & vararg [ 1 ] ) = iField ;
VariantInit ( & vararg [ 0 ] ) ;
V_VT ( & vararg [ 0 ] ) = VT_BSTR ;
V_BSTR ( & vararg [ 0 ] ) = SysAllocString ( szString ) ;
2007-05-04 02:02:06 +02:00
return invoke ( pRecord , " StringData " , DISPATCH_PROPERTYPUT , & dispparams , & varresult , VT_BSTR ) ;
2007-04-29 03:12:09 +02:00
}
2007-05-08 00:50:05 +02:00
static HRESULT StringList_Item ( IDispatch * pStringList , int iIndex , LPWSTR szString )
{
VARIANT varresult ;
VARIANTARG vararg [ 1 ] ;
DISPPARAMS dispparams = { vararg , NULL , sizeof ( vararg ) / sizeof ( VARIANTARG ) , 0 } ;
HRESULT hr ;
VariantInit ( & vararg [ 0 ] ) ;
V_VT ( & vararg [ 0 ] ) = VT_I4 ;
V_I4 ( & vararg [ 0 ] ) = iIndex ;
hr = invoke ( pStringList , " Item " , DISPATCH_PROPERTYGET , & dispparams , & varresult , VT_BSTR ) ;
lstrcpyW ( szString , V_BSTR ( & varresult ) ) ;
VariantClear ( & varresult ) ;
return hr ;
}
static HRESULT StringList_Count ( IDispatch * pStringList , int * pCount )
{
VARIANT varresult ;
DISPPARAMS dispparams = { NULL , NULL , 0 , 0 } ;
HRESULT hr = invoke ( pStringList , " Count " , DISPATCH_PROPERTYGET , & dispparams , & varresult , VT_I4 ) ;
* pCount = V_I4 ( & varresult ) ;
VariantClear ( & varresult ) ;
return hr ;
}
2007-04-29 03:12:09 +02:00
/* Test the various objects */
static void test_Database ( IDispatch * pDatabase )
{
static WCHAR szSql [ ] = { ' S ' , ' E ' , ' L ' , ' E ' , ' C ' , ' T ' , ' ' , ' ` ' , ' F ' , ' e ' , ' a ' , ' t ' , ' u ' , ' r ' , ' e ' , ' ` ' , ' ' , ' F ' , ' R ' , ' O ' , ' M ' , ' ' , ' ` ' , ' F ' , ' e ' , ' a ' , ' t ' , ' u ' , ' r ' , ' e ' , ' ` ' , ' ' , ' W ' , ' H ' , ' E ' , ' R ' , ' E ' , ' ' , ' ` ' , ' F ' , ' e ' , ' a ' , ' t ' , ' u ' , ' r ' , ' e ' , ' _ ' , ' P ' , ' a ' , ' r ' , ' e ' , ' n ' , ' t ' , ' ` ' , ' = ' , ' \' ' , ' O ' , ' n ' , ' e ' , ' \' ' , 0 } ;
static WCHAR szThree [ ] = { ' T ' , ' h ' , ' r ' , ' e ' , ' e ' , 0 } ;
static WCHAR szTwo [ ] = { ' T ' , ' w ' , ' o ' , 0 } ;
static WCHAR szStringDataField [ ] = { ' S ' , ' t ' , ' r ' , ' i ' , ' n ' , ' g ' , ' D ' , ' a ' , ' t ' , ' a ' , ' , ' , ' F ' , ' i ' , ' e ' , ' l ' , ' d ' , 0 } ;
IDispatch * pView = NULL ;
HRESULT hr ;
hr = Database_OpenView ( pDatabase , szSql , & pView ) ;
ok ( SUCCEEDED ( hr ) , " Database_OpenView failed, hresult 0x%08x \n " , hr ) ;
if ( SUCCEEDED ( hr ) )
{
IDispatch * pRecord = NULL ;
WCHAR szString [ MAX_PATH ] ;
/* View::Execute */
hr = View_Execute ( pView , NULL ) ;
ok ( SUCCEEDED ( hr ) , " View_Execute failed, hresult 0x%08x \n " , hr ) ;
/* View::Fetch */
hr = View_Fetch ( pView , & pRecord ) ;
ok ( SUCCEEDED ( hr ) , " View_Fetch failed, hresult 0x%08x \n " , hr ) ;
ok ( pRecord ! = NULL , " View_Fetch should not have returned NULL record \n " ) ;
if ( pRecord )
{
/* Record::StringDataGet */
memset ( szString , 0 , sizeof ( szString ) ) ;
hr = Record_StringDataGet ( pRecord , 1 , szString ) ;
ok ( SUCCEEDED ( hr ) , " Record_StringDataGet failed, hresult 0x%08x \n " , hr ) ;
ok_w2 ( " Record_StringDataGet result was %s but expected %s \n " , szString , szThree ) ;
/* Record::StringDataPut with incorrect index */
hr = Record_StringDataPut ( pRecord , - 1 , szString ) ;
ok ( hr = = DISP_E_EXCEPTION , " Record_StringDataPut failed, hresult 0x%08x \n " , hr ) ;
ok_exception ( hr , szStringDataField ) ;
IDispatch_Release ( pRecord ) ;
}
/* View::Fetch */
hr = View_Fetch ( pView , & pRecord ) ;
ok ( SUCCEEDED ( hr ) , " View_Fetch failed, hresult 0x%08x \n " , hr ) ;
ok ( pRecord ! = NULL , " View_Fetch should not have returned NULL record \n " ) ;
if ( pRecord )
{
/* Record::StringDataGet */
memset ( szString , 0 , sizeof ( szString ) ) ;
hr = Record_StringDataGet ( pRecord , 1 , szString ) ;
ok ( SUCCEEDED ( hr ) , " Record_StringDataGet failed, hresult 0x%08x \n " , hr ) ;
ok_w2 ( " Record_StringDataGet result was %s but expected %s \n " , szString , szTwo ) ;
IDispatch_Release ( pRecord ) ;
}
/* View::Fetch */
hr = View_Fetch ( pView , & pRecord ) ;
ok ( SUCCEEDED ( hr ) , " View_Fetch failed, hresult 0x%08x \n " , hr ) ;
ok ( pRecord = = NULL , " View_Fetch should have returned NULL record \n " ) ;
if ( pRecord )
IDispatch_Release ( pRecord ) ;
/* View::Close */
hr = View_Close ( pView ) ;
ok ( SUCCEEDED ( hr ) , " View_Close failed, hresult 0x%08x \n " , hr ) ;
IDispatch_Release ( pView ) ;
}
}
static void test_Session ( IDispatch * pSession )
{
static WCHAR szProductName [ ] = { ' P ' , ' r ' , ' o ' , ' d ' , ' u ' , ' c ' , ' t ' , ' N ' , ' a ' , ' m ' , ' e ' , 0 } ;
static WCHAR szMSITEST [ ] = { ' M ' , ' S ' , ' I ' , ' T ' , ' E ' , ' S ' , ' T ' , 0 } ;
static WCHAR szOne [ ] = { ' O ' , ' n ' , ' e ' , 0 } ;
static WCHAR szCostInitialize [ ] = { ' C ' , ' o ' , ' s ' , ' t ' , ' I ' , ' n ' , ' i ' , ' t ' , ' i ' , ' a ' , ' l ' , ' i ' , ' z ' , ' e ' , 0 } ;
static WCHAR szEmpty [ ] = { 0 } ;
static WCHAR szEquals [ ] = { ' = ' , 0 } ;
static WCHAR szPropertyName [ ] = { ' P ' , ' r ' , ' o ' , ' p ' , ' e ' , ' r ' , ' t ' , ' y ' , ' , ' , ' N ' , ' a ' , ' m ' , ' e ' , 0 } ;
WCHAR stringw [ MAX_PATH ] ;
CHAR string [ MAX_PATH ] ;
UINT len ;
BOOL bool ;
int myint ;
2007-05-05 06:17:56 +02:00
IDispatch * pDatabase = NULL , * pInst = NULL ;
2007-04-29 03:12:09 +02:00
HRESULT hr ;
2007-05-05 06:17:56 +02:00
/* Session::Installer */
2007-05-05 06:18:40 +02:00
hr = Session_Installer ( pSession , & pInst ) ;
ok ( SUCCEEDED ( hr ) , " Session_Installer failed, hresult 0x%08x \n " , hr ) ;
ok ( pInst ! = NULL , " Session_Installer returned NULL IDispatch pointer \n " ) ;
ok ( pInst = = pInstaller , " Session_Installer does not match Installer instance from CoCreateInstance \n " ) ;
2007-05-05 06:17:56 +02:00
2007-04-29 03:12:09 +02:00
/* Session::Property, get */
memset ( stringw , 0 , sizeof ( stringw ) ) ;
hr = Session_PropertyGet ( pSession , szProductName , stringw ) ;
ok ( SUCCEEDED ( hr ) , " Session_PropertyGet failed, hresult 0x%08x \n " , hr ) ;
if ( lstrcmpW ( stringw , szMSITEST ) ! = 0 )
{
len = WideCharToMultiByte ( CP_ACP , 0 , stringw , - 1 , string , MAX_PATH , NULL , NULL ) ;
ok ( len , " WideCharToMultiByteChar returned error %d \n " , GetLastError ( ) ) ;
ok ( 0 , " Property \" ProductName \" expected to be \" MSITEST \" but was \" %s \" \n " , string ) ;
}
/* Session::Property, put */
hr = Session_PropertyPut ( pSession , szProductName , szProductName ) ;
ok ( SUCCEEDED ( hr ) , " Session_PropertyPut failed, hresult 0x%08x \n " , hr ) ;
memset ( stringw , 0 , sizeof ( stringw ) ) ;
hr = Session_PropertyGet ( pSession , szProductName , stringw ) ;
ok ( SUCCEEDED ( hr ) , " Session_PropertyGet failed, hresult 0x%08x \n " , hr ) ;
if ( lstrcmpW ( stringw , szProductName ) ! = 0 )
{
len = WideCharToMultiByte ( CP_ACP , 0 , stringw , - 1 , string , MAX_PATH , NULL , NULL ) ;
ok ( len , " WideCharToMultiByteChar returned error %d \n " , GetLastError ( ) ) ;
ok ( 0 , " Property \" ProductName \" expected to be \" ProductName \" but was \" %s \" \n " , string ) ;
}
/* Try putting a property using empty property identifier */
hr = Session_PropertyPut ( pSession , szEmpty , szProductName ) ;
ok ( hr = = DISP_E_EXCEPTION , " Session_PropertyPut failed, hresult 0x%08x \n " , hr ) ;
ok_exception ( hr , szPropertyName ) ;
/* Try putting a property using illegal property identifier */
hr = Session_PropertyPut ( pSession , szEquals , szProductName ) ;
ok ( SUCCEEDED ( hr ) , " Session_PropertyPut failed, hresult 0x%08x \n " , hr ) ;
/* Session::Language, get */
hr = Session_LanguageGet ( pSession , & len ) ;
ok ( SUCCEEDED ( hr ) , " Session_LanguageGet failed, hresult 0x%08x \n " , hr ) ;
/* Not sure how to check the language is correct */
/* Session::Mode, get */
hr = Session_ModeGet ( pSession , MSIRUNMODE_REBOOTATEND , & bool ) ;
ok ( SUCCEEDED ( hr ) , " Session_ModeGet failed, hresult 0x%08x \n " , hr ) ;
2007-05-01 03:54:31 +02:00
todo_wine ok ( ! bool , " Reboot at end session mode is %d \n " , bool ) ;
2007-04-29 03:12:09 +02:00
/* Session::Mode, put */
hr = Session_ModePut ( pSession , MSIRUNMODE_REBOOTATEND , TRUE ) ;
2007-05-01 03:54:31 +02:00
todo_wine ok ( SUCCEEDED ( hr ) , " Session_ModePut failed, hresult 0x%08x \n " , hr ) ;
2007-04-29 03:12:09 +02:00
hr = Session_ModeGet ( pSession , MSIRUNMODE_REBOOTATEND , & bool ) ;
ok ( SUCCEEDED ( hr ) , " Session_ModeGet failed, hresult 0x%08x \n " , hr ) ;
ok ( bool , " Reboot at end session mode is %d, expected 1 \n " , bool ) ;
hr = Session_ModePut ( pSession , MSIRUNMODE_REBOOTATEND , FALSE ) ; /* set it again so we don't reboot */
2007-05-01 03:54:31 +02:00
todo_wine ok ( SUCCEEDED ( hr ) , " Session_ModePut failed, hresult 0x%08x \n " , hr ) ;
2007-04-29 03:12:09 +02:00
/* Session::Database, get */
hr = Session_Database ( pSession , & pDatabase ) ;
ok ( SUCCEEDED ( hr ) , " Session_Database failed, hresult 0x%08x \n " , hr ) ;
if ( SUCCEEDED ( hr ) )
{
test_Database ( pDatabase ) ;
IDispatch_Release ( pDatabase ) ;
}
/* Session::DoAction(CostInitialize) must occur before the next statements */
hr = Session_DoAction ( pSession , szCostInitialize , & myint ) ;
ok ( SUCCEEDED ( hr ) , " Session_DoAction failed, hresult 0x%08x \n " , hr ) ;
ok ( myint = = IDOK , " DoAction(CostInitialize) returned %d, %d expected \n " , myint , IDOK ) ;
/* Session::SetInstallLevel */
hr = Session_SetInstallLevel ( pSession , INSTALLLEVEL_MINIMUM ) ;
ok ( SUCCEEDED ( hr ) , " Session_SetInstallLevel failed, hresult 0x%08x \n " , hr ) ;
/* Session::FeatureCurrentState, get */
hr = Session_FeatureCurrentState ( pSession , szOne , & myint ) ;
ok ( SUCCEEDED ( hr ) , " Session_FeatureCurrentState failed, hresult 0x%08x \n " , hr ) ;
ok ( myint = = INSTALLSTATE_UNKNOWN , " Feature current state was %d but expected %d \n " , myint , INSTALLSTATE_UNKNOWN ) ;
/* Session::FeatureRequestState, put */
hr = Session_FeatureRequestStatePut ( pSession , szOne , INSTALLSTATE_ADVERTISED ) ;
ok ( SUCCEEDED ( hr ) , " Session_FeatureRequestStatePut failed, hresult 0x%08x \n " , hr ) ;
hr = Session_FeatureRequestStateGet ( pSession , szOne , & myint ) ;
ok ( SUCCEEDED ( hr ) , " Session_FeatureRequestStateGet failed, hresult 0x%08x \n " , hr ) ;
ok ( myint = = INSTALLSTATE_ADVERTISED , " Feature request state was %d but expected %d \n " , myint , INSTALLSTATE_ADVERTISED ) ;
}
static void test_Installer ( void )
{
2007-05-08 00:50:05 +02:00
static WCHAR szProductCode [ ] = { ' { ' , ' F ' , ' 1 ' , ' C ' , ' 3 ' , ' A ' , ' F ' , ' 5 ' , ' 0 ' , ' - ' , ' 8 ' , ' B ' , ' 5 ' , ' 6 ' , ' - ' , ' 4 ' , ' A ' , ' 6 ' , ' 9 ' , ' - ' , ' A ' , ' 0 ' , ' 0 ' , ' C ' , ' - ' , ' 0 ' , ' 0 ' , ' 7 ' , ' 7 ' , ' 3 ' , ' F ' , ' E ' , ' 4 ' , ' 2 ' , ' F ' , ' 3 ' , ' 0 ' , ' } ' , 0 } ;
2007-04-29 03:12:09 +02:00
static WCHAR szBackslash [ ] = { ' \\ ' , 0 } ;
WCHAR szPath [ MAX_PATH ] ;
HRESULT hr ;
UINT len ;
2007-05-08 00:50:05 +02:00
IDispatch * pSession = NULL , * pRecord = NULL , * pStringList = NULL ;
int iState ;
2007-04-29 03:12:09 +02:00
if ( ! pInstaller ) return ;
2007-05-04 02:02:31 +02:00
/* Installer::CreateRecord */
todo_wine {
hr = Installer_CreateRecord ( 1 , & pRecord ) ;
ok ( SUCCEEDED ( hr ) , " Installer_CreateRecord failed, hresult 0x%08x \n " , hr ) ;
ok ( pRecord ! = NULL , " Installer_CreateRecord should not have returned NULL record \n " ) ;
}
if ( pRecord )
{
int iFieldCount = 0 ;
/* Record::FieldCountGet */
hr = Record_FieldCountGet ( pRecord , & iFieldCount ) ;
ok ( SUCCEEDED ( hr ) , " Record_FiledCountGet failed, hresult 0x%08x \n " , hr ) ;
ok ( iFieldCount = = 1 , " Record_FieldCountGet result was %d but expected 1 \n " , iFieldCount ) ;
IDispatch_Release ( pRecord ) ;
}
/* Prepare package */
2007-04-29 03:12:09 +02:00
create_database ( msifile , tables , sizeof ( tables ) / sizeof ( msi_table ) ) ;
len = MultiByteToWideChar ( CP_ACP , MB_PRECOMPOSED , CURR_DIR , - 1 , szPath , MAX_PATH ) ;
ok ( len , " MultiByteToWideChar returned error %d \n " , GetLastError ( ) ) ;
if ( ! len ) return ;
lstrcatW ( szPath , szBackslash ) ;
lstrcatW ( szPath , szMsifile ) ;
/* Installer::OpenPackage */
hr = Installer_OpenPackage ( szPath , 0 , & pSession ) ;
ok ( SUCCEEDED ( hr ) , " Installer_OpenPackage failed, hresult 0x%08x \n " , hr ) ;
if ( SUCCEEDED ( hr ) )
{
test_Session ( pSession ) ;
IDispatch_Release ( pSession ) ;
}
DeleteFileA ( msifile ) ;
2007-05-04 02:02:31 +02:00
2007-05-08 00:50:05 +02:00
/* Installer::Products */
2007-05-08 00:50:30 +02:00
hr = Installer_Products ( & pStringList ) ;
ok ( SUCCEEDED ( hr ) , " Installer_Products failed, hresult 0x%08x \n " , hr ) ;
if ( SUCCEEDED ( hr ) )
{
int iCount = 0 , idx ;
2007-05-08 00:50:05 +02:00
2007-05-08 00:50:30 +02:00
/* StringList::Count */
hr = StringList_Count ( pStringList , & iCount ) ;
ok ( SUCCEEDED ( hr ) , " StringList_Count failed, hresult 0x%08x \n " , hr ) ;
2007-05-08 00:50:05 +02:00
2007-05-08 00:50:30 +02:00
for ( idx = 0 ; idx < iCount ; idx + + )
{
/* StringList::Item */
memset ( szPath , 0 , sizeof ( szPath ) ) ;
hr = StringList_Item ( pStringList , idx , szPath ) ;
ok ( SUCCEEDED ( hr ) , " StringList_Item failed (idx %d, count %d), hresult 0x%08x \n " , idx , iCount , hr ) ;
2007-05-08 00:50:05 +02:00
2007-05-08 00:50:30 +02:00
if ( SUCCEEDED ( hr ) )
{
/* Installer::ProductState */
hr = Installer_ProductState ( szPath , & iState ) ;
ok ( SUCCEEDED ( hr ) , " Installer_ProductState failed, hresult 0x%08x \n " , hr ) ;
2007-05-08 00:50:05 +02:00
if ( SUCCEEDED ( hr ) )
2007-05-08 00:50:30 +02:00
ok ( iState = = INSTALLSTATE_DEFAULT | | iState = = INSTALLSTATE_ADVERTISED , " Installer_ProductState returned %d, expected %d or %d " , iState , INSTALLSTATE_DEFAULT , INSTALLSTATE_ADVERTISED ) ;
2007-05-08 00:50:05 +02:00
}
2007-05-08 00:50:30 +02:00
}
2007-05-08 00:50:05 +02:00
2007-05-08 00:50:30 +02:00
/* StringList::Item using an invalid index */
memset ( szPath , 0 , sizeof ( szPath ) ) ;
hr = StringList_Item ( pStringList , iCount , szPath ) ;
ok ( hr = = DISP_E_BADINDEX , " StringList_Item for an invalid index did not return DISP_E_BADINDEX, hresult 0x%08x \n " , hr ) ;
2007-05-08 00:50:05 +02:00
2007-05-08 00:50:30 +02:00
IDispatch_Release ( pStringList ) ;
2007-05-08 00:50:05 +02:00
}
/* Installer::ProductState for our product code, which should not be installed */
2007-05-08 00:50:30 +02:00
hr = Installer_ProductState ( szProductCode , & iState ) ;
ok ( SUCCEEDED ( hr ) , " Installer_ProductState failed, hresult 0x%08x \n " , hr ) ;
if ( SUCCEEDED ( hr ) )
ok ( iState = = INSTALLSTATE_UNKNOWN , " Installer_ProductState returned %d, expected %d " , iState , INSTALLSTATE_UNKNOWN ) ;
2007-05-08 00:50:05 +02:00
2007-05-04 02:02:31 +02:00
/* Installer::Version */
todo_wine {
memset ( szPath , 0 , sizeof ( szPath ) ) ;
hr = Installer_VersionGet ( szPath ) ;
ok ( SUCCEEDED ( hr ) , " Installer_VersionGet failed, hresult 0x%08x \n " , hr ) ;
}
2007-04-29 03:12:09 +02:00
}
START_TEST ( automation )
{
DWORD len ;
char temp_path [ MAX_PATH ] , prev_path [ MAX_PATH ] ;
HRESULT hr ;
CLSID clsid ;
IUnknown * pUnk ;
GetCurrentDirectoryA ( MAX_PATH , prev_path ) ;
GetTempPath ( MAX_PATH , temp_path ) ;
SetCurrentDirectoryA ( temp_path ) ;
lstrcpyA ( CURR_DIR , temp_path ) ;
len = lstrlenA ( CURR_DIR ) ;
if ( len & & ( CURR_DIR [ len - 1 ] = = ' \\ ' ) )
CURR_DIR [ len - 1 ] = 0 ;
hr = OleInitialize ( NULL ) ;
ok ( SUCCEEDED ( hr ) , " OleInitialize returned 0x%08x \n " , hr ) ;
hr = CLSIDFromProgID ( szProgId , & clsid ) ;
ok ( SUCCEEDED ( hr ) , " CLSIDFromProgID returned 0x%08x \n " , hr ) ;
hr = CoCreateInstance ( & clsid , NULL , CLSCTX_INPROC_SERVER , & IID_IUnknown , ( void * * ) & pUnk ) ;
2007-05-01 03:54:31 +02:00
ok ( SUCCEEDED ( hr ) , " CoCreateInstance returned 0x%08x \n " , hr ) ;
2007-04-29 03:12:09 +02:00
if ( pUnk )
{
hr = IUnknown_QueryInterface ( pUnk , & IID_IDispatch , ( void * * ) & pInstaller ) ;
ok ( SUCCEEDED ( hr ) , " IUnknown::QueryInterface returned 0x%08x \n " , hr ) ;
2007-05-01 03:53:26 +02:00
test_dispid ( ) ;
2007-05-01 03:54:31 +02:00
test_dispatch ( ) ;
test_Installer ( ) ;
2007-04-29 03:12:09 +02:00
hr = IUnknown_Release ( pUnk ) ;
ok ( SUCCEEDED ( hr ) , " IUnknown::Release returned 0x%08x \n " , hr ) ;
}
OleUninitialize ( ) ;
SetCurrentDirectoryA ( prev_path ) ;
}