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>
2008-07-08 16:17:17 +02:00
# include <initguid.h>
2007-04-29 03:12:09 +02:00
# include <windows.h>
# include <msiquery.h>
# include <msidefs.h>
# include <msi.h>
# include <fci.h>
# include "wine/test.h"
2008-07-08 16:17:17 +02:00
DEFINE_GUID ( GUID_NULL , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ) ;
2007-04-29 03:12:09 +02:00
static const char * msifile = " winetest.msi " ;
static const WCHAR szMsifile [ ] = { ' w ' , ' i ' , ' n ' , ' e ' , ' t ' , ' e ' , ' s ' , ' t ' , ' . ' , ' m ' , ' s ' , ' i ' , 0 } ;
2007-05-16 02:30:09 +02:00
static const WCHAR szMSITEST [ ] = { ' M ' , ' S ' , ' I ' , ' T ' , ' E ' , ' S ' , ' T ' , 0 } ;
2007-05-14 19:14:42 +02:00
static const 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-05-14 19:15:02 +02:00
static const WCHAR szUpgradeCode [ ] = { ' { ' , ' C ' , ' E ' , ' 0 ' , ' 6 ' , ' 7 ' , ' E ' , ' 8 ' , ' D ' , ' - ' , ' 2 ' , ' E ' , ' 1 ' , ' A ' , ' - ' , ' 4 ' , ' 3 ' , ' 6 ' , ' 7 ' , ' - ' , ' B ' , ' 7 ' , ' 3 ' , ' 4 ' , ' - ' , ' 4 ' , ' E ' , ' B ' , ' 2 ' , ' B ' , ' D ' , ' A ' , ' D ' , ' 6 ' , ' 5 ' , ' 6 ' , ' 5 ' , ' } ' , 0 } ;
2007-05-16 02:30:09 +02:00
static const WCHAR szProductInfoException [ ] = { ' P ' , ' r ' , ' o ' , ' d ' , ' u ' , ' c ' , ' t ' , ' I ' , ' n ' , ' f ' , ' o ' , ' , ' , ' P ' , ' r ' , ' o ' , ' d ' , ' u ' , ' c ' , ' t ' , ' , ' , ' A ' , ' t ' , ' t ' , ' r ' , ' i ' , ' b ' , ' u ' , ' t ' , ' e ' , 0 } ;
2007-07-13 05:04:19 +02:00
static const WCHAR WINE_INSTALLPROPERTY_PACKAGENAMEW [ ] = { ' P ' , ' a ' , ' c ' , ' k ' , ' a ' , ' g ' , ' e ' , ' N ' , ' a ' , ' m ' , ' e ' , 0 } ;
static const WCHAR WINE_INSTALLPROPERTY_PRODUCTNAMEW [ ] = { ' P ' , ' r ' , ' o ' , ' d ' , ' u ' , ' c ' , ' t ' , ' N ' , ' a ' , ' m ' , ' e ' , 0 } ;
2007-06-02 03:06:46 +02:00
static FILETIME systemtime ;
static CHAR CURR_DIR [ MAX_PATH ] ;
static EXCEPINFO excepinfo ;
2007-04-29 03:12:09 +02:00
/*
* 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 "
2008-08-27 17:08:35 +02:00
" component \t \t MSITESTDIR \t 0 \t 1 \t file \n " ;
2007-04-29 03:12:09 +02:00
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 "
2008-08-27 17:08:35 +02:00
" feature \t \t \t \t 2 \t 1 \t TARGETDIR \t 0 \n " ;
2007-04-29 03:12:09 +02:00
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 "
2008-08-27 17:08:35 +02:00
" feature \t component \n " ;
2007-04-29 03:12:09 +02:00
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 "
2007-05-14 19:14:42 +02:00
" five.txt \t Five \t five.txt \t 1000 \t \t \t 0 \t 5 \n "
" four.txt \t Four \t four.txt \t 1000 \t \t \t 0 \t 4 \n "
2007-04-29 03:12:09 +02:00
" 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 "
2008-08-27 17:08:35 +02:00
" file \t component \t filename \t 100 \t \t \t 8192 \t 1 \n " ;
2007-04-29 03:12:09 +02:00
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 "
2007-05-14 19:14:42 +02:00
" RegisterProduct \t \t 6100 \n "
" PublishProduct \t \t 6400 \n "
2007-04-29 03:12:09 +02:00
" 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 "
2007-05-14 19:14:42 +02:00
" 1 \t 5 \t \t \t DISK1 \t \n " ;
2007-04-29 03:12:09 +02:00
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 " ;
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 ) ,
2008-08-27 17:08:35 +02:00
ADD_TABLE ( registry )
2007-04-29 03:12:09 +02:00
} ;
2007-06-02 03:06:46 +02:00
typedef struct _msi_summary_info
{
UINT property ;
UINT datatype ;
INT iValue ;
FILETIME * pftValue ;
const CHAR * szValue ;
} msi_summary_info ;
# define ADD_INFO_I2(property, iValue) {property, VT_I2, iValue, NULL, NULL}
# define ADD_INFO_I4(property, iValue) {property, VT_I4, iValue, NULL, NULL}
# define ADD_INFO_LPSTR(property, szValue) {property, VT_LPSTR, 0, NULL, szValue}
# define ADD_INFO_FILETIME(property, pftValue) {property, VT_FILETIME, 0, pftValue, NULL}
static const msi_summary_info summary_info [ ] =
{
ADD_INFO_LPSTR ( PID_TEMPLATE , " ;1033 " ) ,
ADD_INFO_LPSTR ( PID_REVNUMBER , " {004757CA-5092-49c2-AD20-28E1CE0DF5F2} " ) ,
ADD_INFO_I4 ( PID_PAGECOUNT , 100 ) ,
ADD_INFO_I4 ( PID_WORDCOUNT , 0 ) ,
ADD_INFO_FILETIME ( PID_CREATE_DTM , & systemtime ) ,
ADD_INFO_FILETIME ( PID_LASTPRINTED , & systemtime )
} ;
2007-04-29 03:12:09 +02:00
/*
* 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 ) ;
}
2007-06-02 03:06:46 +02:00
static void write_msi_summary_info ( MSIHANDLE db , const msi_summary_info * info , int num_info )
2007-04-29 03:12:09 +02:00
{
MSIHANDLE summary ;
UINT r ;
2007-06-02 03:06:46 +02:00
int j ;
2007-04-29 03:12:09 +02:00
2007-06-02 03:06:46 +02:00
r = MsiGetSummaryInformationA ( db , NULL , num_info , & summary ) ;
2007-04-29 03:12:09 +02:00
ok ( r = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %u \n " , r ) ;
2007-06-02 03:06:46 +02:00
/* import summary information into the stream */
for ( j = 0 ; j < num_info ; j + + )
{
const msi_summary_info * entry = & info [ j ] ;
2007-04-29 03:12:09 +02:00
2007-06-02 03:06:46 +02:00
r = MsiSummaryInfoSetPropertyA ( summary , entry - > property , entry - > datatype ,
entry - > iValue , entry - > pftValue , entry - > szValue ) ;
ok ( r = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %u \n " , r ) ;
}
2007-04-29 03:12:09 +02:00
/* write the summary changes back to the stream */
r = MsiSummaryInfoPersist ( summary ) ;
ok ( r = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %u \n " , r ) ;
MsiCloseHandle ( summary ) ;
}
2007-06-02 03:06:46 +02:00
static void create_database ( const CHAR * name , const msi_table * tables , int num_tables ,
const msi_summary_info * info , int num_info )
2007-04-29 03:12:09 +02:00
{
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 ) ;
}
2007-06-02 03:06:46 +02:00
write_msi_summary_info ( db , info , num_info ) ;
2007-04-29 03:12:09 +02:00
r = MsiDatabaseCommit ( db ) ;
ok ( r = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %u \n " , r ) ;
MsiCloseHandle ( db ) ;
}
2007-05-14 19:14:42 +02:00
/*
* Installation helpers
*/
static char PROG_FILES_DIR [ MAX_PATH ] ;
static BOOL get_program_files_dir ( LPSTR buf )
{
HKEY hkey ;
DWORD type = REG_EXPAND_SZ , size ;
if ( RegOpenKey ( HKEY_LOCAL_MACHINE ,
" Software \\ Microsoft \\ Windows \\ CurrentVersion " , & hkey ) )
return FALSE ;
size = MAX_PATH ;
if ( RegQueryValueEx ( hkey , " ProgramFilesDir " , 0 , & type , ( LPBYTE ) buf , & size ) )
return FALSE ;
RegCloseKey ( hkey ) ;
return TRUE ;
}
static void create_file ( const CHAR * name , DWORD size )
{
HANDLE file ;
DWORD written , left ;
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 ) ;
left = size - lstrlen ( name ) - 1 ;
SetFilePointer ( file , left , NULL , FILE_CURRENT ) ;
SetEndOfFile ( file ) ;
CloseHandle ( file ) ;
}
static void create_test_files ( void )
{
CreateDirectoryA ( " msitest " , NULL ) ;
create_file ( " msitest \\ one.txt " , 100 ) ;
CreateDirectoryA ( " msitest \\ first " , NULL ) ;
create_file ( " msitest \\ first \\ two.txt " , 100 ) ;
CreateDirectoryA ( " msitest \\ second " , NULL ) ;
create_file ( " msitest \\ second \\ three.txt " , 100 ) ;
CreateDirectoryA ( " msitest \\ cabout " , NULL ) ;
create_file ( " msitest \\ cabout \\ four.txt " , 100 ) ;
CreateDirectoryA ( " msitest \\ cabout \\ new " , NULL ) ;
create_file ( " msitest \\ cabout \\ new \\ five.txt " , 100 ) ;
create_file ( " msitest \\ filename " , 100 ) ;
}
static BOOL delete_pf ( const CHAR * rel_path , BOOL is_file )
{
CHAR path [ MAX_PATH ] ;
lstrcpyA ( path , PROG_FILES_DIR ) ;
lstrcatA ( path , " \\ " ) ;
lstrcatA ( path , rel_path ) ;
if ( is_file )
return DeleteFileA ( path ) ;
else
return RemoveDirectoryA ( path ) ;
}
static void delete_test_files ( void )
{
DeleteFileA ( msifile ) ;
DeleteFileA ( " msitest \\ cabout \\ new \\ five.txt " ) ;
DeleteFileA ( " msitest \\ cabout \\ four.txt " ) ;
DeleteFileA ( " msitest \\ second \\ three.txt " ) ;
DeleteFileA ( " msitest \\ first \\ two.txt " ) ;
DeleteFileA ( " msitest \\ one.txt " ) ;
DeleteFileA ( " msitest \\ filename " ) ;
RemoveDirectoryA ( " msitest \\ cabout \\ new " ) ;
RemoveDirectoryA ( " msitest \\ cabout " ) ;
RemoveDirectoryA ( " msitest \\ second " ) ;
RemoveDirectoryA ( " msitest \\ first " ) ;
RemoveDirectoryA ( " msitest " ) ;
}
2007-04-29 03:12:09 +02:00
/*
* Automation helpers and tests
*/
2007-06-02 03:06:46 +02:00
/* ok-like statement which takes two unicode strings or one unicode and one ANSI string as arguments */
2007-04-29 03:12:09 +02:00
static CHAR string1 [ MAX_PATH ] , string2 [ MAX_PATH ] ;
# define ok_w2(format, szString1, szString2) \
\
if ( lstrcmpW ( szString1 , szString2 ) ! = 0 ) \
{ \
2007-05-08 00:51:36 +02:00
WideCharToMultiByte ( CP_ACP , 0 , szString1 , - 1 , string1 , MAX_PATH , NULL , NULL ) ; \
WideCharToMultiByte ( CP_ACP , 0 , szString2 , - 1 , string2 , MAX_PATH , NULL , NULL ) ; \
2007-04-29 03:12:09 +02:00
ok ( 0 , format , string1 , string2 ) ; \
}
2008-09-02 08:04:59 +02:00
# define ok_w2n(format, szString1, szString2, len) \
\
if ( memcmp ( szString1 , szString2 , len * sizeof ( WCHAR ) ) ! = 0 ) \
{ \
WideCharToMultiByte ( CP_ACP , 0 , szString1 , - 1 , string1 , MAX_PATH , NULL , NULL ) ; \
WideCharToMultiByte ( CP_ACP , 0 , szString2 , - 1 , string2 , MAX_PATH , NULL , NULL ) ; \
ok ( 0 , format , string1 , string2 ) ; \
}
2007-06-02 03:06:46 +02:00
# define ok_aw(format, aString, wString) \
\
WideCharToMultiByte ( CP_ACP , 0 , wString , - 1 , string1 , MAX_PATH , NULL , NULL ) ; \
if ( lstrcmpA ( string1 , aString ) ! = 0 ) \
ok ( 0 , format , string1 , aString ) ; \
# define ok_awplus(format, extra, aString, wString) \
\
WideCharToMultiByte ( CP_ACP , 0 , wString , - 1 , string1 , MAX_PATH , NULL , NULL ) ; \
if ( lstrcmpA ( string1 , aString ) ! = 0 ) \
ok ( 0 , format , extra , string1 , aString ) ; \
2007-04-29 03:12:09 +02:00
/* 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-08 00:52:07 +02:00
if ( excepinfo . bstrDescription ) \
ok_w2 ( " Exception description was \" %s \" but expected to be \" %s \" \n " , excepinfo . bstrDescription , szDescription ) ; \
2007-07-28 06:51:47 +02:00
\
SysFreeString ( excepinfo . bstrSource ) ; \
SysFreeString ( excepinfo . bstrDescription ) ; \
SysFreeString ( excepinfo . bstrHelpFile ) ; \
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 )
{
2008-03-17 22:57:42 +01:00
DISPID dispid ;
2007-05-01 03:53:26 +02:00
2008-03-17 22:57:42 +01:00
dispid = get_dispid ( pInstaller , " CreateRecord " ) ;
ok ( dispid = = 1 , " Expected 1, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " OpenPackage " ) ;
ok ( dispid = = 2 , " Expected 2, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " OpenDatabase " ) ;
ok ( dispid = = 4 , " Expected 4, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " UILevel " ) ;
ok ( dispid = = 6 , " Expected 6, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " InstallProduct " ) ;
ok ( dispid = = 8 , " Expected 8, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " Version " ) ;
ok ( dispid = = 9 , " Expected 9, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " RegistryValue " ) ;
ok ( dispid = = 11 , " Expected 11, got %d \n " , dispid ) ;
todo_wine
{
dispid = get_dispid ( pInstaller , " OpenProduct " ) ;
ok ( dispid = = 3 , " Expected 3, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " SummaryInformation " ) ;
ok ( dispid = = 5 , " Expected 5, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " EnableLog " ) ;
ok ( dispid = = 7 , " Expected 7, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " LastErrorRecord " ) ;
ok ( dispid = = 10 , " Expected 10, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " Environment " ) ;
ok ( dispid = = 12 , " Expected 12, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " FileAttributes " ) ;
ok ( dispid = = 13 , " Expected 13, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " FileSize " ) ;
ok ( dispid = = 15 , " Expected 15, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " FileVersion " ) ;
ok ( dispid = = 16 , " Expected 16, got %d \n " , dispid ) ;
2007-05-08 00:50:30 +02:00
}
2008-03-17 22:57:42 +01:00
dispid = get_dispid ( pInstaller , " ProductState " ) ;
ok ( dispid = = 17 , " Expected 17, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " ProductInfo " ) ;
ok ( dispid = = 18 , " Expected 18, got %d \n " , dispid ) ;
todo_wine
{
dispid = get_dispid ( pInstaller , " ConfigureProduct " ) ;
ok ( dispid = = 19 , " Expected 19, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " ReinstallProduct " ) ;
ok ( dispid = = 20 , " Expected 20, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " CollectUserInfo " ) ;
ok ( dispid = = 21 , " Expected 21, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " ApplyPatch " ) ;
ok ( dispid = = 22 , " Expected 22, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " FeatureParent " ) ;
ok ( dispid = = 23 , " Expected 23, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " FeatureState " ) ;
ok ( dispid = = 24 , " Expected 24, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " UseFeature " ) ;
ok ( dispid = = 25 , " Expected 25, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " FeatureUsageCount " ) ;
ok ( dispid = = 26 , " Expected 26, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " FeatureUsageDate " ) ;
ok ( dispid = = 27 , " Expected 27, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " ConfigureFeature " ) ;
ok ( dispid = = 28 , " Expected 28, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " ReinstallFeature " ) ;
ok ( dispid = = 29 , " Expected 29, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " ProvideComponent " ) ;
ok ( dispid = = 30 , " Expected 30, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " ComponentPath " ) ;
ok ( dispid = = 31 , " Expected 31, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " ProvideQualifiedComponent " ) ;
ok ( dispid = = 32 , " Expected 32, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " QualifierDescription " ) ;
ok ( dispid = = 33 , " Expected 33, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " ComponentQualifiers " ) ;
ok ( dispid = = 34 , " Expected 34, got %d \n " , dispid ) ;
2007-05-08 00:50:30 +02:00
}
2008-03-17 22:57:42 +01:00
dispid = get_dispid ( pInstaller , " Products " ) ;
ok ( dispid = = 35 , " Expected 35, got %d \n " , dispid ) ;
todo_wine
{
dispid = get_dispid ( pInstaller , " Features " ) ;
ok ( dispid = = 36 , " Expected 36, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " Components " ) ;
ok ( dispid = = 37 , " Expected 37, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " ComponentClients " ) ;
ok ( dispid = = 38 , " Expected 38, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " Patches " ) ;
ok ( dispid = = 39 , " Expected 39, got %d \n " , dispid ) ;
2007-05-14 19:15:13 +02:00
}
2008-03-17 22:57:42 +01:00
dispid = get_dispid ( pInstaller , " RelatedProducts " ) ;
ok ( dispid = = 40 , " Expected 40, got %d \n " , dispid ) ;
todo_wine
{
dispid = get_dispid ( pInstaller , " PatchInfo " ) ;
ok ( dispid = = 41 , " Expected 41, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " PatchTransforms " ) ;
ok ( dispid = = 42 , " Expected 42, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " AddSource " ) ;
ok ( dispid = = 43 , " Expected 43, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " ClearSourceList " ) ;
ok ( dispid = = 44 , " Expected 44, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " ForceSourceListResolution " ) ;
ok ( dispid = = 45 , " Expected 45, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " ShortcutTarget " ) ;
ok ( dispid = = 46 , " Expected 46, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " FileHash " ) ;
ok ( dispid = = 47 , " Expected 47, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " FileSignatureInfo " ) ;
ok ( dispid = = 48 , " Expected 48, got %d \n " , dispid ) ;
2007-05-01 03:53:26 +02:00
}
2008-06-19 10:32:42 +02:00
dispid = get_dispid ( pInstaller , " RemovePatches " ) ;
ok ( dispid = = 49 | | dispid = = - 1 , " Expected 49 or -1, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " ApplyMultiplePatches " ) ;
ok ( dispid = = 51 | | dispid = = - 1 , " Expected 51 or -1, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " ProductsEx " ) ;
ok ( dispid = = 52 | | dispid = = - 1 , " Expected 52 or -1, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " PatchesEx " ) ;
ok ( dispid = = 55 | | dispid = = - 1 , " Expected 55 or -1, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " ExtractPatchXMLData " ) ;
ok ( dispid = = 57 | | dispid = = - 1 , " Expected 57 or -1, got %d \n " , dispid ) ;
2008-03-17 22:57:42 +01:00
dispid = get_dispid ( pInstaller , " ProductElevated " ) ;
2008-06-19 10:32:42 +02:00
ok ( dispid = = 59 | | dispid = = - 1 , " Expected 59 or -1, got %d \n " , dispid ) ;
2008-03-17 22:57:42 +01:00
dispid = get_dispid ( pInstaller , " ProvideAssembly " ) ;
2008-06-19 10:32:42 +02:00
ok ( dispid = = 60 | | dispid = = - 1 , " Expected 60 or -1, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " ProductInfoFromScript " ) ;
ok ( dispid = = 61 | | dispid = = - 1 , " Expected 61 or -1, got %d \n " , dispid ) ;
2008-03-17 22:57:42 +01:00
dispid = get_dispid ( pInstaller , " AdvertiseProduct " ) ;
2008-06-19 10:32:42 +02:00
ok ( dispid = = 62 | | dispid = = - 1 , " Expected 62 or -1, got %d \n " , dispid ) ;
dispid = get_dispid ( pInstaller , " CreateAdvertiseScript " ) ;
ok ( dispid = = 63 | | dispid = = - 1 , " Expected 63 or -1, got %d \n " , dispid ) ;
2008-03-17 22:57:42 +01:00
dispid = get_dispid ( pInstaller , " PatchFiles " ) ;
2008-06-19 10:32:42 +02:00
ok ( dispid = = 65 | | dispid = = - 1 , " Expected 65 or -1, got %d \n " , dispid ) ;
2007-05-01 03:53:26 +02:00
}
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 } ;
2007-05-11 21:08:04 +02:00
static WCHAR szProductState [ ] = { ' P ' , ' r ' , ' o ' , ' d ' , ' u ' , ' c ' , ' t ' , ' S ' , ' t ' , ' a ' , ' t ' , ' e ' , 0 } ;
2007-04-29 03:12:09 +02:00
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 */
2009-01-15 09:44:57 +01:00
name = szOpenPackage ;
2007-04-29 03:12:09 +02:00
hr = IDispatch_GetIDsOfNames ( pInstaller , & IID_NULL , & name , 1 , LOCALE_USER_DEFAULT , & dispid ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " IDispatch::GetIDsOfNames returned 0x%08x \n " , hr ) ;
2007-04-29 03:12:09 +02:00
/* 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 ) ;
2007-05-11 21:08:04 +02:00
/* Test invoking a method as a DISPATCH_PROPERTYGET or DISPATCH_PROPERTYPUT */
VariantInit ( & vararg [ 0 ] ) ;
hr = IDispatch_Invoke ( pInstaller , dispid , & IID_NULL , LOCALE_NEUTRAL , DISPATCH_PROPERTYGET , & dispparams , & varresult , & excepinfo , NULL ) ;
2007-05-11 21:08:08 +02:00
ok ( hr = = DISP_E_MEMBERNOTFOUND , " IDispatch::Invoke returned 0x%08x \n " , hr ) ;
2007-05-11 21:08:04 +02:00
VariantInit ( & vararg [ 0 ] ) ;
hr = IDispatch_Invoke ( pInstaller , dispid , & IID_NULL , LOCALE_NEUTRAL , DISPATCH_PROPERTYPUT , & dispparams , & varresult , & excepinfo , NULL ) ;
2007-05-11 21:08:08 +02:00
ok ( hr = = DISP_E_MEMBERNOTFOUND , " IDispatch::Invoke returned 0x%08x \n " , hr ) ;
2007-05-11 21:08:04 +02:00
/* Test invoking a read-only property as DISPATCH_PROPERTYPUT or as a DISPATCH_METHOD */
2009-01-15 09:44:57 +01:00
name = szProductState ;
2007-05-11 21:08:04 +02:00
hr = IDispatch_GetIDsOfNames ( pInstaller , & IID_NULL , & name , 1 , LOCALE_USER_DEFAULT , & dispid ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " IDispatch::GetIDsOfNames returned 0x%08x \n " , hr ) ;
2007-05-11 21:08:04 +02:00
dispparams . rgvarg = NULL ;
dispparams . cArgs = 0 ;
hr = IDispatch_Invoke ( pInstaller , dispid , & IID_NULL , LOCALE_NEUTRAL , DISPATCH_PROPERTYPUT , & dispparams , & varresult , & excepinfo , NULL ) ;
2007-05-11 21:08:08 +02:00
ok ( hr = = DISP_E_MEMBERNOTFOUND , " IDispatch::Invoke returned 0x%08x \n " , hr ) ;
2007-05-11 21:08:04 +02:00
dispparams . rgvarg = NULL ;
dispparams . cArgs = 0 ;
hr = IDispatch_Invoke ( pInstaller , dispid , & IID_NULL , LOCALE_NEUTRAL , DISPATCH_METHOD , & dispparams , & varresult , & excepinfo , NULL ) ;
2007-05-11 21:08:08 +02:00
ok ( hr = = DISP_E_MEMBERNOTFOUND , " IDispatch::Invoke returned 0x%08x \n " , hr ) ;
2007-04-29 03:12:09 +02:00
}
/* invocation helper function */
2007-06-02 03:06:46 +02:00
static int _invoke_todo_vtResult = 0 ;
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 ;
2007-05-27 13:18:49 +02:00
UINT 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-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " IDispatch::GetIDsOfNames returned 0x%08x \n " , hr ) ;
if ( ! hr = = S_OK ) return hr ;
2007-04-29 03:12:09 +02:00
memset ( & excepinfo , 0 , sizeof ( excepinfo ) ) ;
hr = IDispatch_Invoke ( pDispatch , dispid , & IID_NULL , LOCALE_NEUTRAL , wFlags , pDispParams , pVarResult , & excepinfo , NULL ) ;
2007-05-17 18:36:09 +02:00
if ( hr = = S_OK )
2007-04-29 03:12:09 +02:00
{
2007-06-02 03:06:46 +02:00
if ( _invoke_todo_vtResult ) todo_wine
ok ( V_VT ( pVarResult ) = = vtResult , " Variant result type is %d, expected %d \n " , V_VT ( pVarResult ) , vtResult ) ;
else
ok ( V_VT ( pVarResult ) = = vtResult , " Variant result type is %d, expected %d \n " , V_VT ( pVarResult ) , vtResult ) ;
2007-04-29 03:12:09 +02:00
if ( vtResult ! = VT_EMPTY )
{
hr = VariantChangeTypeEx ( pVarResult , pVarResult , LOCALE_NEUTRAL , 0 , vtResult ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " VariantChangeTypeEx returned 0x%08x \n " , hr ) ;
2007-04-29 03:12:09 +02:00
}
}
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-05-09 14:56:44 +02:00
static HRESULT Installer_RegistryValue ( HKEY hkey , LPCWSTR szKey , VARIANT vValue , VARIANT * pVarResult , VARTYPE vtExpect )
2007-05-08 00:51:36 +02:00
{
VARIANTARG vararg [ 3 ] ;
DISPPARAMS dispparams = { vararg , NULL , sizeof ( vararg ) / sizeof ( VARIANTARG ) , 0 } ;
VariantInit ( & vararg [ 2 ] ) ;
V_VT ( & vararg [ 2 ] ) = VT_I4 ;
2009-01-03 20:13:45 +01:00
V_I4 ( & vararg [ 2 ] ) = ( INT_PTR ) hkey ;
2007-05-08 00:51:36 +02:00
VariantInit ( & vararg [ 1 ] ) ;
V_VT ( & vararg [ 1 ] ) = VT_BSTR ;
V_BSTR ( & vararg [ 1 ] ) = SysAllocString ( szKey ) ;
VariantInit ( & vararg [ 0 ] ) ;
2007-05-09 14:56:44 +02:00
VariantCopy ( & vararg [ 0 ] , & vValue ) ;
VariantClear ( & vValue ) ;
return invoke ( pInstaller , " RegistryValue " , DISPATCH_METHOD , & dispparams , pVarResult , vtExpect ) ;
}
static HRESULT Installer_RegistryValueE ( HKEY hkey , LPCWSTR szKey , BOOL * pBool )
{
VARIANT varresult ;
VARIANTARG vararg ;
HRESULT hr ;
2007-05-08 00:51:36 +02:00
2007-05-09 14:56:44 +02:00
VariantInit ( & vararg ) ;
V_VT ( & vararg ) = VT_EMPTY ;
hr = Installer_RegistryValue ( hkey , szKey , vararg , & varresult , VT_BOOL ) ;
2007-05-08 00:51:36 +02:00
* pBool = V_BOOL ( & varresult ) ;
VariantClear ( & varresult ) ;
return hr ;
}
static HRESULT Installer_RegistryValueW ( HKEY hkey , LPCWSTR szKey , LPCWSTR szValue , LPWSTR szString )
{
VARIANT varresult ;
2007-05-09 14:56:44 +02:00
VARIANTARG vararg ;
2007-05-08 00:51:36 +02:00
HRESULT hr ;
2007-05-09 14:56:44 +02:00
VariantInit ( & vararg ) ;
V_VT ( & vararg ) = VT_BSTR ;
V_BSTR ( & vararg ) = SysAllocString ( szValue ) ;
2007-05-08 00:51:36 +02:00
2007-05-09 14:56:44 +02:00
hr = Installer_RegistryValue ( hkey , szKey , vararg , & varresult , VT_BSTR ) ;
2007-05-17 18:35:48 +02:00
if ( V_BSTR ( & varresult ) ) lstrcpyW ( szString , V_BSTR ( & varresult ) ) ;
2007-05-08 00:51:36 +02:00
VariantClear ( & varresult ) ;
return hr ;
}
static HRESULT Installer_RegistryValueI ( HKEY hkey , LPCWSTR szKey , int iValue , LPWSTR szString , VARTYPE vtResult )
{
VARIANT varresult ;
2007-05-09 14:56:44 +02:00
VARIANTARG vararg ;
2007-05-08 00:51:36 +02:00
HRESULT hr ;
2007-05-09 14:56:44 +02:00
VariantInit ( & vararg ) ;
V_VT ( & vararg ) = VT_I4 ;
V_I4 ( & vararg ) = iValue ;
2007-05-08 00:51:36 +02:00
2007-05-09 14:56:44 +02:00
hr = Installer_RegistryValue ( hkey , szKey , vararg , & varresult , vtResult ) ;
2008-07-09 06:56:26 +02:00
if ( SUCCEEDED ( hr ) & & vtResult = = VT_BSTR ) lstrcpyW ( szString , V_BSTR ( & varresult ) ) ;
2007-05-08 00:51:36 +02:00
VariantClear ( & 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-06-04 16:26:33 +02:00
static HRESULT Installer_OpenDatabase ( LPCWSTR szDatabasePath , int openmode , IDispatch * * pDatabase )
{
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 ( szDatabasePath ) ;
VariantInit ( & vararg [ 0 ] ) ;
V_VT ( & vararg [ 0 ] ) = VT_I4 ;
V_I4 ( & vararg [ 0 ] ) = openmode ;
hr = invoke ( pInstaller , " OpenDatabase " , DISPATCH_METHOD , & dispparams , & varresult , VT_DISPATCH ) ;
* pDatabase = V_DISPATCH ( & varresult ) ;
return hr ;
}
2007-05-14 19:14:42 +02:00
static HRESULT Installer_InstallProduct ( LPCWSTR szPackagePath , LPCWSTR szPropertyValues )
{
VARIANT varresult ;
VARIANTARG vararg [ 2 ] ;
DISPPARAMS dispparams = { vararg , NULL , sizeof ( vararg ) / sizeof ( VARIANTARG ) , 0 } ;
VariantInit ( & vararg [ 1 ] ) ;
V_VT ( & vararg [ 1 ] ) = VT_BSTR ;
V_BSTR ( & vararg [ 1 ] ) = SysAllocString ( szPackagePath ) ;
VariantInit ( & vararg [ 0 ] ) ;
V_VT ( & vararg [ 0 ] ) = VT_BSTR ;
V_BSTR ( & vararg [ 0 ] ) = SysAllocString ( szPropertyValues ) ;
return invoke ( pInstaller , " InstallProduct " , DISPATCH_METHOD , & dispparams , & varresult , VT_EMPTY ) ;
}
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 ;
}
2007-05-16 02:30:09 +02:00
static HRESULT Installer_ProductInfo ( LPCWSTR szProduct , LPCWSTR szAttribute , LPWSTR szString )
{
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 ( szProduct ) ;
VariantInit ( & vararg [ 0 ] ) ;
V_VT ( & vararg [ 0 ] ) = VT_BSTR ;
V_BSTR ( & vararg [ 0 ] ) = SysAllocString ( szAttribute ) ;
hr = invoke ( pInstaller , " ProductInfo " , DISPATCH_PROPERTYGET , & dispparams , & varresult , VT_BSTR ) ;
if ( V_BSTR ( & varresult ) ) lstrcpyW ( szString , V_BSTR ( & varresult ) ) ;
VariantClear ( & varresult ) ;
return hr ;
}
2007-05-08 00:50:05 +02:00
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-14 19:15:02 +02:00
static HRESULT Installer_RelatedProducts ( LPCWSTR szProduct , IDispatch * * pStringList )
{
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 , " RelatedProducts " , DISPATCH_PROPERTYGET , & dispparams , & varresult , VT_DISPATCH ) ;
* pStringList = V_DISPATCH ( & varresult ) ;
return hr ;
}
2007-05-17 18:35:43 +02:00
static HRESULT Installer_VersionGet ( LPWSTR szVersion )
2007-05-04 02:02:31 +02:00
{
VARIANT varresult ;
DISPPARAMS dispparams = { NULL , NULL , 0 , 0 } ;
HRESULT hr ;
hr = invoke ( pInstaller , " Version " , DISPATCH_PROPERTYGET , & dispparams , & varresult , VT_BSTR ) ;
2007-05-17 18:35:48 +02:00
if ( V_BSTR ( & varresult ) ) lstrcpyW ( szVersion , V_BSTR ( & varresult ) ) ;
2007-05-04 02:02:31 +02:00
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-05-17 18:35:43 +02:00
static HRESULT Session_PropertyGet ( IDispatch * pSession , LPCWSTR szName , LPWSTR szReturn )
2007-04-29 03:12:09 +02:00
{
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-05-17 18:35:48 +02:00
if ( V_BSTR ( & varresult ) ) lstrcpyW ( szReturn , V_BSTR ( & varresult ) ) ;
2007-04-29 03:12:09 +02:00
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 ;
}
2007-05-11 21:07:41 +02:00
static HRESULT Session_EvaluateCondition ( IDispatch * pSession , LPCWSTR szCondition , 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 ( szCondition ) ;
hr = invoke ( pSession , " EvaluateCondition " , DISPATCH_METHOD , & dispparams , & varresult , VT_I4 ) ;
* iReturn = V_I4 ( & varresult ) ;
VariantClear ( & varresult ) ;
return hr ;
}
2008-07-16 18:47:08 +02:00
static HRESULT Session_Message ( IDispatch * pSession , long kind , IDispatch * record , int * ret )
{
VARIANT varresult ;
VARIANTARG vararg [ 2 ] ;
DISPPARAMS dispparams = { vararg , NULL , sizeof ( vararg ) / sizeof ( VARIANTARG ) , 0 } ;
HRESULT hr ;
VariantInit ( & varresult ) ;
V_VT ( vararg ) = VT_DISPATCH ;
V_DISPATCH ( vararg ) = record ;
V_VT ( vararg + 1 ) = VT_I4 ;
V_I4 ( vararg + 1 ) = kind ;
hr = invoke ( pSession , " Message " , DISPATCH_METHOD , & dispparams , & varresult , VT_I4 ) ;
ok ( V_VT ( & varresult ) = = VT_I4 , " V_VT(varresult) = %d \n " , V_VT ( & varresult ) ) ;
* ret = V_I4 ( & varresult ) ;
return hr ;
}
2007-04-29 03:12:09 +02:00
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 ;
}
2007-06-02 03:06:46 +02:00
static HRESULT Database_SummaryInformation ( IDispatch * pDatabase , int iUpdateCount , IDispatch * * pSummaryInfo )
{
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 ] ) = iUpdateCount ;
hr = invoke ( pDatabase , " SummaryInformation " , DISPATCH_PROPERTYGET , & dispparams , & varresult , VT_DISPATCH ) ;
* pSummaryInfo = V_DISPATCH ( & varresult ) ;
return hr ;
}
2007-04-29 03:12:09 +02:00
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 ;
}
2007-05-11 21:08:38 +02:00
static HRESULT View_Modify ( IDispatch * pView , int iMode , IDispatch * pRecord )
{
VARIANT varresult ;
VARIANTARG vararg [ 2 ] ;
DISPPARAMS dispparams = { vararg , NULL , sizeof ( vararg ) / sizeof ( VARIANTARG ) , 0 } ;
VariantInit ( & vararg [ 1 ] ) ;
V_VT ( & vararg [ 1 ] ) = VT_I4 ;
V_I4 ( & vararg [ 1 ] ) = iMode ;
VariantInit ( & vararg [ 0 ] ) ;
V_VT ( & vararg [ 0 ] ) = VT_DISPATCH ;
V_DISPATCH ( & vararg [ 0 ] ) = pRecord ;
if ( pRecord )
IDispatch_AddRef ( pRecord ) ; /* VariantClear in invoke will call IDispatch_Release */
return invoke ( pView , " Modify " , DISPATCH_METHOD , & dispparams , & varresult , VT_EMPTY ) ;
}
2007-04-29 03:12:09 +02:00
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-05-17 18:35:43 +02:00
static HRESULT Record_StringDataGet ( IDispatch * pRecord , int iField , LPWSTR szString )
2007-04-29 03:12:09 +02:00
{
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-05-17 18:35:48 +02:00
if ( V_BSTR ( & varresult ) ) lstrcpyW ( szString , V_BSTR ( & varresult ) ) ;
2007-04-29 03:12:09 +02:00
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-11 21:08:22 +02:00
return invoke ( pRecord , " StringData " , DISPATCH_PROPERTYPUT , & dispparams , & varresult , VT_EMPTY ) ;
2007-04-29 03:12:09 +02:00
}
2007-05-11 21:08:27 +02:00
static HRESULT Record_IntegerDataGet ( IDispatch * pRecord , int iField , int * pValue )
{
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 ;
hr = invoke ( pRecord , " IntegerData " , DISPATCH_PROPERTYGET , & dispparams , & varresult , VT_I4 ) ;
* pValue = V_I4 ( & varresult ) ;
VariantClear ( & varresult ) ;
return hr ;
}
static HRESULT Record_IntegerDataPut ( IDispatch * pRecord , int iField , int iValue )
{
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_I4 ;
V_I4 ( & vararg [ 0 ] ) = iValue ;
return invoke ( pRecord , " IntegerData " , DISPATCH_PROPERTYPUT , & dispparams , & varresult , VT_EMPTY ) ;
}
2007-05-18 18:22:36 +02:00
static HRESULT StringList__NewEnum ( IDispatch * pList , IUnknown * * ppEnumVARIANT )
{
VARIANT varresult ;
DISPPARAMS dispparams = { NULL , NULL , 0 , 0 } ;
HRESULT hr = invoke ( pList , " _NewEnum " , DISPATCH_METHOD , & dispparams , & varresult , VT_UNKNOWN ) ;
* ppEnumVARIANT = V_UNKNOWN ( & varresult ) ;
return hr ;
}
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 ) ;
2007-05-17 18:35:48 +02:00
if ( V_BSTR ( & varresult ) ) lstrcpyW ( szString , V_BSTR ( & varresult ) ) ;
2007-05-08 00:50:05 +02:00
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-06-02 03:06:46 +02:00
static HRESULT SummaryInfo_PropertyGet ( IDispatch * pSummaryInfo , int pid , VARIANT * pVarResult , VARTYPE vtExpect )
{
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 ] ) = pid ;
return invoke ( pSummaryInfo , " Property " , DISPATCH_PROPERTYGET , & dispparams , pVarResult , vtExpect ) ;
}
2007-06-04 16:26:42 +02:00
static HRESULT SummaryInfo_PropertyPut ( IDispatch * pSummaryInfo , int pid , VARIANT * pVariant )
{
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 ] ) = pid ;
VariantInit ( & vararg [ 0 ] ) ;
VariantCopyInd ( vararg , pVariant ) ;
return invoke ( pSummaryInfo , " Property " , DISPATCH_PROPERTYPUT , & dispparams , & varresult , VT_EMPTY ) ;
}
2007-06-04 16:26:48 +02:00
static HRESULT SummaryInfo_PropertyCountGet ( IDispatch * pSummaryInfo , int * pCount )
{
VARIANT varresult ;
DISPPARAMS dispparams = { NULL , NULL , 0 , 0 } ;
HRESULT hr ;
hr = invoke ( pSummaryInfo , " PropertyCount " , 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 */
2007-06-04 16:26:42 +02:00
# define TEST_SUMMARYINFO_PROPERTIES_MODIFIED 4
2007-06-04 16:26:33 +02:00
static void test_SummaryInfo ( IDispatch * pSummaryInfo , const msi_summary_info * info , int num_info , BOOL readonly )
2007-06-02 03:06:46 +02:00
{
static const WCHAR szPropertyException [ ] = { ' P ' , ' r ' , ' o ' , ' p ' , ' e ' , ' r ' , ' t ' , ' y ' , ' , ' , ' P ' , ' i ' , ' d ' , 0 } ;
2007-06-04 16:26:42 +02:00
static const WCHAR szTitle [ ] = { ' T ' , ' i ' , ' t ' , ' l ' , ' e ' , 0 } ;
VARIANT varresult , var ;
SYSTEMTIME st ;
2007-06-02 03:06:46 +02:00
HRESULT hr ;
int j ;
2007-06-04 16:26:48 +02:00
/* SummaryInfo::PropertyCount */
2007-06-04 16:26:51 +02:00
hr = SummaryInfo_PropertyCountGet ( pSummaryInfo , & j ) ;
ok ( hr = = S_OK , " SummaryInfo_PropertyCount failed, hresult 0x%08x \n " , hr ) ;
ok ( j = = num_info , " SummaryInfo_PropertyCount returned %d, expected %d \n " , j , num_info ) ;
2007-06-04 16:26:48 +02:00
2007-06-02 03:06:46 +02:00
/* SummaryInfo::Property, get for properties we have set */
for ( j = 0 ; j < num_info ; j + + )
{
const msi_summary_info * entry = & info [ j ] ;
int vt = entry - > datatype ;
if ( vt = = VT_LPSTR ) vt = VT_BSTR ;
else if ( vt = = VT_FILETIME ) vt = VT_DATE ;
2007-06-04 16:26:42 +02:00
else if ( vt = = VT_I2 ) vt = VT_I4 ;
2007-06-02 03:06:46 +02:00
hr = SummaryInfo_PropertyGet ( pSummaryInfo , entry - > property , & varresult , vt ) ;
ok ( hr = = S_OK , " SummaryInfo_Property (pid %d) failed, hresult 0x%08x \n " , entry - > property , hr ) ;
if ( V_VT ( & varresult ) ! = vt )
skip ( " Skipping property tests due to type mismatch \n " ) ;
else if ( vt = = VT_I4 )
ok ( V_I4 ( & varresult ) = = entry - > iValue , " SummaryInfo_Property (pid %d) I4 result expected to be %d, but was %d \n " ,
entry - > property , entry - > iValue , V_I4 ( & varresult ) ) ;
2007-06-02 03:06:55 +02:00
else if ( vt = = VT_DATE )
2007-06-02 03:06:46 +02:00
{
FILETIME ft ;
DATE d ;
FileTimeToLocalFileTime ( entry - > pftValue , & ft ) ;
FileTimeToSystemTime ( & ft , & st ) ;
SystemTimeToVariantTime ( & st , & d ) ;
ok ( d = = V_DATE ( & varresult ) , " SummaryInfo_Property (pid %d) DATE result expected to be %lf, but was %lf \n " , entry - > property , d , V_DATE ( & varresult ) ) ;
}
else if ( vt = = VT_BSTR )
{
ok_awplus ( " SummaryInfo_Property (pid %d) BSTR result expected to be %s, but was %s \n " , entry - > property , entry - > szValue , V_BSTR ( & varresult ) ) ;
}
else
skip ( " SummaryInfo_Property (pid %d) unhandled result type %d \n " , entry - > property , vt ) ;
2007-11-19 06:37:01 +01:00
VariantClear ( & varresult ) ;
2007-06-02 03:06:46 +02:00
}
/* SummaryInfo::Property, get; invalid arguments */
/* Invalid pids */
hr = SummaryInfo_PropertyGet ( pSummaryInfo , - 1 , & varresult , VT_EMPTY ) ;
2007-06-02 03:06:55 +02:00
ok ( hr = = DISP_E_EXCEPTION , " SummaryInfo_PropertyGet failed, hresult 0x%08x \n " , hr ) ;
2007-06-02 03:06:46 +02:00
ok_exception ( hr , szPropertyException ) ;
hr = SummaryInfo_PropertyGet ( pSummaryInfo , 1000 , & varresult , VT_EMPTY ) ;
2007-06-02 03:06:55 +02:00
ok ( hr = = DISP_E_EXCEPTION , " SummaryInfo_PropertyGet failed, hresult 0x%08x \n " , hr ) ;
2007-06-02 03:06:46 +02:00
ok_exception ( hr , szPropertyException ) ;
/* Unsupported pids */
hr = SummaryInfo_PropertyGet ( pSummaryInfo , PID_DICTIONARY , & varresult , VT_EMPTY ) ;
ok ( hr = = S_OK , " SummaryInfo_PropertyGet failed, hresult 0x%08x \n " , hr ) ;
hr = SummaryInfo_PropertyGet ( pSummaryInfo , PID_THUMBNAIL , & varresult , VT_EMPTY ) ;
ok ( hr = = S_OK , " SummaryInfo_PropertyGet failed, hresult 0x%08x \n " , hr ) ;
/* Pids we have not set, one for each type */
hr = SummaryInfo_PropertyGet ( pSummaryInfo , PID_CODEPAGE , & varresult , VT_EMPTY ) ;
ok ( hr = = S_OK , " SummaryInfo_PropertyGet failed, hresult 0x%08x \n " , hr ) ;
hr = SummaryInfo_PropertyGet ( pSummaryInfo , PID_TITLE , & varresult , VT_EMPTY ) ;
2007-06-02 03:06:55 +02:00
ok ( hr = = S_OK , " SummaryInfo_PropertyGet failed, hresult 0x%08x \n " , hr ) ;
2007-06-02 03:06:46 +02:00
hr = SummaryInfo_PropertyGet ( pSummaryInfo , PID_EDITTIME , & varresult , VT_EMPTY ) ;
ok ( hr = = S_OK , " SummaryInfo_PropertyGet failed, hresult 0x%08x \n " , hr ) ;
hr = SummaryInfo_PropertyGet ( pSummaryInfo , PID_CHARCOUNT , & varresult , VT_EMPTY ) ;
ok ( hr = = S_OK , " SummaryInfo_PropertyGet failed, hresult 0x%08x \n " , hr ) ;
2007-06-04 16:26:42 +02:00
if ( ! readonly )
{
/* SummaryInfo::Property, put; one for each type */
/* VT_I2 */
VariantInit ( & var ) ;
V_VT ( & var ) = VT_I2 ;
V_I2 ( & var ) = 1 ;
hr = SummaryInfo_PropertyPut ( pSummaryInfo , PID_CODEPAGE , & var ) ;
2007-06-04 16:26:45 +02:00
ok ( hr = = S_OK , " SummaryInfo_PropertyPut failed, hresult 0x%08x \n " , hr ) ;
2007-06-04 16:26:42 +02:00
hr = SummaryInfo_PropertyGet ( pSummaryInfo , PID_CODEPAGE , & varresult , VT_I4 /* NOT VT_I2 */ ) ;
ok ( hr = = S_OK , " SummaryInfo_PropertyGet failed, hresult 0x%08x \n " , hr ) ;
2007-06-04 16:26:45 +02:00
ok ( V_I2 ( & var ) = = V_I2 ( & varresult ) , " SummaryInfo_PropertyGet expected %d, but returned %d \n " , V_I2 ( & var ) , V_I2 ( & varresult ) ) ;
2007-06-04 16:26:42 +02:00
VariantClear ( & varresult ) ;
VariantClear ( & var ) ;
/* VT_BSTR */
V_VT ( & var ) = VT_BSTR ;
V_BSTR ( & var ) = SysAllocString ( szTitle ) ;
hr = SummaryInfo_PropertyPut ( pSummaryInfo , PID_TITLE , & var ) ;
2007-06-04 16:26:45 +02:00
ok ( hr = = S_OK , " SummaryInfo_PropertyPut failed, hresult 0x%08x \n " , hr ) ;
2007-06-04 16:26:42 +02:00
hr = SummaryInfo_PropertyGet ( pSummaryInfo , PID_TITLE , & varresult , V_VT ( & var ) ) ;
ok ( hr = = S_OK , " SummaryInfo_PropertyGet failed, hresult 0x%08x \n " , hr ) ;
2007-06-04 16:26:45 +02:00
ok_w2 ( " SummaryInfo_PropertyGet expected %s, but returned %s \n " , V_BSTR ( & var ) , V_BSTR ( & varresult ) ) ;
2007-06-04 16:26:42 +02:00
VariantClear ( & varresult ) ;
VariantClear ( & var ) ;
/* VT_DATE */
V_VT ( & var ) = VT_DATE ;
FileTimeToSystemTime ( & systemtime , & st ) ;
SystemTimeToVariantTime ( & st , & V_DATE ( & var ) ) ;
hr = SummaryInfo_PropertyPut ( pSummaryInfo , PID_LASTSAVE_DTM , & var ) ;
2007-06-04 16:26:45 +02:00
ok ( hr = = S_OK , " SummaryInfo_PropertyPut failed, hresult 0x%08x \n " , hr ) ;
2007-06-04 16:26:42 +02:00
hr = SummaryInfo_PropertyGet ( pSummaryInfo , PID_LASTSAVE_DTM , & varresult , V_VT ( & var ) ) ;
ok ( hr = = S_OK , " SummaryInfo_PropertyGet failed, hresult 0x%08x \n " , hr ) ;
2007-06-04 16:26:45 +02:00
/* FIXME: Off by one second */
2007-06-04 16:26:42 +02:00
todo_wine ok ( V_DATE ( & var ) = = V_DATE ( & varresult ) , " SummaryInfo_PropertyGet expected %lf, but returned %lf \n " , V_DATE ( & var ) , V_DATE ( & varresult ) ) ;
VariantClear ( & varresult ) ;
VariantClear ( & var ) ;
/* VT_I4 */
V_VT ( & var ) = VT_I4 ;
V_I4 ( & var ) = 1000 ;
hr = SummaryInfo_PropertyPut ( pSummaryInfo , PID_CHARCOUNT , & var ) ;
2007-06-04 16:26:45 +02:00
ok ( hr = = S_OK , " SummaryInfo_PropertyPut failed, hresult 0x%08x \n " , hr ) ;
2007-06-04 16:26:42 +02:00
hr = SummaryInfo_PropertyGet ( pSummaryInfo , PID_CHARCOUNT , & varresult , V_VT ( & var ) ) ;
ok ( hr = = S_OK , " SummaryInfo_PropertyGet failed, hresult 0x%08x \n " , hr ) ;
2007-06-04 16:26:45 +02:00
ok ( V_I4 ( & var ) = = V_I4 ( & varresult ) , " SummaryInfo_PropertyGet expected %d, but returned %d \n " , V_I4 ( & var ) , V_I4 ( & varresult ) ) ;
2007-06-04 16:26:42 +02:00
VariantClear ( & varresult ) ;
VariantClear ( & var ) ;
2007-06-04 16:26:48 +02:00
/* SummaryInfo::PropertyCount */
2007-06-04 16:26:51 +02:00
hr = SummaryInfo_PropertyCountGet ( pSummaryInfo , & j ) ;
ok ( hr = = S_OK , " SummaryInfo_PropertyCount failed, hresult 0x%08x \n " , hr ) ;
ok ( j = = num_info + 4 , " SummaryInfo_PropertyCount returned %d, expected %d \n " , j , num_info ) ;
2007-06-04 16:26:42 +02:00
}
2007-06-02 03:06:46 +02:00
}
2007-06-04 16:26:33 +02:00
static void test_Database ( IDispatch * pDatabase , BOOL readonly )
2007-04-29 03:12:09 +02:00
{
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 } ;
2007-05-11 21:08:38 +02:00
static WCHAR szModifyModeRecord [ ] = { ' M ' , ' o ' , ' d ' , ' i ' , ' f ' , ' y ' , ' , ' , ' M ' , ' o ' , ' d ' , ' e ' , ' , ' , ' R ' , ' e ' , ' c ' , ' o ' , ' r ' , ' d ' , 0 } ;
2007-06-02 03:06:46 +02:00
IDispatch * pView = NULL , * pSummaryInfo = NULL ;
2007-04-29 03:12:09 +02:00
HRESULT hr ;
hr = Database_OpenView ( pDatabase , szSql , & pView ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Database_OpenView failed, hresult 0x%08x \n " , hr ) ;
if ( hr = = S_OK )
2007-04-29 03:12:09 +02:00
{
IDispatch * pRecord = NULL ;
WCHAR szString [ MAX_PATH ] ;
/* View::Execute */
hr = View_Execute ( pView , NULL ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " View_Execute failed, hresult 0x%08x \n " , hr ) ;
2007-04-29 03:12:09 +02:00
/* View::Fetch */
hr = View_Fetch ( pView , & pRecord ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " View_Fetch failed, hresult 0x%08x \n " , hr ) ;
2007-04-29 03:12:09 +02:00
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 ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Record_StringDataGet failed, hresult 0x%08x \n " , hr ) ;
2007-04-29 03:12:09 +02:00
ok_w2 ( " Record_StringDataGet result was %s but expected %s \n " , szString , szThree ) ;
2007-05-11 21:08:22 +02:00
/* Record::StringDataPut with correct index */
hr = Record_StringDataPut ( pRecord , 1 , szTwo ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Record_StringDataPut failed, hresult 0x%08x \n " , hr ) ;
2007-05-11 21:08:22 +02:00
/* Record::StringDataGet */
memset ( szString , 0 , sizeof ( szString ) ) ;
hr = Record_StringDataGet ( pRecord , 1 , szString ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Record_StringDataGet failed, hresult 0x%08x \n " , hr ) ;
2007-05-11 21:08:22 +02:00
ok_w2 ( " Record_StringDataGet result was %s but expected %s \n " , szString , szTwo ) ;
2007-04-29 03:12:09 +02:00
/* 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 ) ;
2007-05-11 21:08:38 +02:00
/* View::Modify with incorrect parameters */
2007-05-11 21:08:43 +02:00
hr = View_Modify ( pView , - 5 , NULL ) ;
ok ( hr = = DISP_E_EXCEPTION , " View_Modify failed, hresult 0x%08x \n " , hr ) ;
ok_exception ( hr , szModifyModeRecord ) ;
2007-05-11 21:08:38 +02:00
2007-05-11 21:08:43 +02:00
hr = View_Modify ( pView , - 5 , pRecord ) ;
ok ( hr = = DISP_E_EXCEPTION , " View_Modify failed, hresult 0x%08x \n " , hr ) ;
ok_exception ( hr , szModifyModeRecord ) ;
2007-05-11 21:08:38 +02:00
2007-05-11 21:08:43 +02:00
hr = View_Modify ( pView , MSIMODIFY_REFRESH , NULL ) ;
ok ( hr = = DISP_E_EXCEPTION , " View_Modify failed, hresult 0x%08x \n " , hr ) ;
ok_exception ( hr , szModifyModeRecord ) ;
2007-05-11 21:08:38 +02:00
2007-05-11 21:08:43 +02:00
hr = View_Modify ( pView , MSIMODIFY_REFRESH , pRecord ) ;
2008-02-14 06:36:44 +01:00
ok ( hr = = S_OK , " View_Modify failed, hresult 0x%08x \n " , hr ) ;
2007-05-11 21:08:38 +02:00
/* Record::StringDataGet, confirm that the record is back to its unmodified value */
memset ( szString , 0 , sizeof ( szString ) ) ;
hr = Record_StringDataGet ( pRecord , 1 , szString ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Record_StringDataGet failed, hresult 0x%08x \n " , hr ) ;
2007-05-11 21:08:38 +02:00
todo_wine ok_w2 ( " Record_StringDataGet result was %s but expected %s \n " , szString , szThree ) ;
2007-04-29 03:12:09 +02:00
IDispatch_Release ( pRecord ) ;
}
/* View::Fetch */
hr = View_Fetch ( pView , & pRecord ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " View_Fetch failed, hresult 0x%08x \n " , hr ) ;
2007-04-29 03:12:09 +02:00
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 ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Record_StringDataGet failed, hresult 0x%08x \n " , hr ) ;
2007-04-29 03:12:09 +02:00
ok_w2 ( " Record_StringDataGet result was %s but expected %s \n " , szString , szTwo ) ;
IDispatch_Release ( pRecord ) ;
}
/* View::Fetch */
hr = View_Fetch ( pView , & pRecord ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " View_Fetch failed, hresult 0x%08x \n " , hr ) ;
2007-04-29 03:12:09 +02:00
ok ( pRecord = = NULL , " View_Fetch should have returned NULL record \n " ) ;
if ( pRecord )
IDispatch_Release ( pRecord ) ;
/* View::Close */
hr = View_Close ( pView ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " View_Close failed, hresult 0x%08x \n " , hr ) ;
2007-04-29 03:12:09 +02:00
IDispatch_Release ( pView ) ;
}
2007-06-02 03:06:46 +02:00
/* Database::SummaryInformation */
2007-06-04 16:26:42 +02:00
hr = Database_SummaryInformation ( pDatabase , TEST_SUMMARYINFO_PROPERTIES_MODIFIED , & pSummaryInfo ) ;
2007-06-02 03:06:46 +02:00
ok ( hr = = S_OK , " Database_SummaryInformation failed, hresult 0x%08x \n " , hr ) ;
ok ( pSummaryInfo ! = NULL , " Database_SummaryInformation should not have returned NULL record \n " ) ;
if ( pSummaryInfo )
{
2007-06-04 16:26:33 +02:00
test_SummaryInfo ( pSummaryInfo , summary_info , sizeof ( summary_info ) / sizeof ( msi_summary_info ) , readonly ) ;
2007-06-02 03:06:46 +02:00
IDispatch_Release ( pSummaryInfo ) ;
}
2007-04-29 03:12:09 +02:00
}
static void test_Session ( IDispatch * pSession )
{
static WCHAR szProductName [ ] = { ' P ' , ' r ' , ' o ' , ' d ' , ' u ' , ' c ' , ' t ' , ' N ' , ' a ' , ' m ' , ' e ' , 0 } ;
static WCHAR szOne [ ] = { ' O ' , ' n ' , ' e ' , 0 } ;
2007-05-11 21:07:41 +02:00
static WCHAR szOneStateFalse [ ] = { ' ! ' , ' O ' , ' n ' , ' e ' , ' > ' , ' 0 ' , 0 } ;
static WCHAR szOneStateTrue [ ] = { ' ! ' , ' O ' , ' n ' , ' e ' , ' = ' , ' - ' , ' 1 ' , 0 } ;
static WCHAR szOneActionFalse [ ] = { ' $ ' , ' O ' , ' n ' , ' e ' , ' = ' , ' - ' , ' 1 ' , 0 } ;
static WCHAR szOneActionTrue [ ] = { ' $ ' , ' O ' , ' n ' , ' e ' , ' > ' , ' 0 ' , 0 } ;
2007-04-29 03:12:09 +02:00
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 ;
2008-07-16 18:47:08 +02:00
IDispatch * pDatabase = NULL , * pInst = NULL , * record = 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 ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Session_Installer failed, hresult 0x%08x \n " , hr ) ;
2007-05-05 06:18:40 +02:00
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 ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Session_PropertyGet failed, hresult 0x%08x \n " , hr ) ;
2007-04-29 03:12:09 +02:00
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 ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Session_PropertyPut failed, hresult 0x%08x \n " , hr ) ;
2007-04-29 03:12:09 +02:00
memset ( stringw , 0 , sizeof ( stringw ) ) ;
hr = Session_PropertyGet ( pSession , szProductName , stringw ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Session_PropertyGet failed, hresult 0x%08x \n " , hr ) ;
2007-04-29 03:12:09 +02:00
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 ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Session_PropertyPut failed, hresult 0x%08x \n " , hr ) ;
2007-04-29 03:12:09 +02:00
/* Session::Language, get */
hr = Session_LanguageGet ( pSession , & len ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Session_LanguageGet failed, hresult 0x%08x \n " , hr ) ;
2007-04-29 03:12:09 +02:00
/* Not sure how to check the language is correct */
/* Session::Mode, get */
hr = Session_ModeGet ( pSession , MSIRUNMODE_REBOOTATEND , & bool ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " 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-17 18:36:09 +02:00
todo_wine ok ( hr = = S_OK , " Session_ModePut failed, hresult 0x%08x \n " , hr ) ;
2007-04-29 03:12:09 +02:00
hr = Session_ModeGet ( pSession , MSIRUNMODE_REBOOTATEND , & bool ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Session_ModeGet failed, hresult 0x%08x \n " , hr ) ;
2007-04-29 03:12:09 +02:00
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-17 18:36:09 +02:00
todo_wine ok ( hr = = S_OK , " Session_ModePut failed, hresult 0x%08x \n " , hr ) ;
2007-04-29 03:12:09 +02:00
/* Session::Database, get */
hr = Session_Database ( pSession , & pDatabase ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Session_Database failed, hresult 0x%08x \n " , hr ) ;
if ( hr = = S_OK )
2007-04-29 03:12:09 +02:00
{
2007-06-04 16:26:33 +02:00
test_Database ( pDatabase , TRUE ) ;
2007-04-29 03:12:09 +02:00
IDispatch_Release ( pDatabase ) ;
}
2007-05-11 21:07:41 +02:00
/* Session::EvaluateCondition */
2007-05-11 21:07:48 +02:00
hr = Session_EvaluateCondition ( pSession , NULL , & myint ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Session_EvaluateCondition failed, hresult 0x%08x \n " , hr ) ;
2007-05-11 21:07:48 +02:00
ok ( myint = = MSICONDITION_NONE , " Feature current state was %d but expected %d \n " , myint , INSTALLSTATE_UNKNOWN ) ;
2007-05-11 21:07:41 +02:00
2007-05-11 21:07:48 +02:00
hr = Session_EvaluateCondition ( pSession , szEmpty , & myint ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Session_EvaluateCondition failed, hresult 0x%08x \n " , hr ) ;
2007-05-11 21:07:48 +02:00
ok ( myint = = MSICONDITION_NONE , " Feature current state was %d but expected %d \n " , myint , INSTALLSTATE_UNKNOWN ) ;
2007-05-11 21:07:41 +02:00
2007-05-11 21:07:48 +02:00
hr = Session_EvaluateCondition ( pSession , szEquals , & myint ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Session_EvaluateCondition failed, hresult 0x%08x \n " , hr ) ;
2007-05-11 21:07:48 +02:00
ok ( myint = = MSICONDITION_ERROR , " Feature current state was %d but expected %d \n " , myint , INSTALLSTATE_UNKNOWN ) ;
2007-05-11 21:07:41 +02:00
2007-04-29 03:12:09 +02:00
/* Session::DoAction(CostInitialize) must occur before the next statements */
hr = Session_DoAction ( pSession , szCostInitialize , & myint ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Session_DoAction failed, hresult 0x%08x \n " , hr ) ;
2007-04-29 03:12:09 +02:00
ok ( myint = = IDOK , " DoAction(CostInitialize) returned %d, %d expected \n " , myint , IDOK ) ;
/* Session::SetInstallLevel */
hr = Session_SetInstallLevel ( pSession , INSTALLLEVEL_MINIMUM ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Session_SetInstallLevel failed, hresult 0x%08x \n " , hr ) ;
2007-04-29 03:12:09 +02:00
/* Session::FeatureCurrentState, get */
hr = Session_FeatureCurrentState ( pSession , szOne , & myint ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Session_FeatureCurrentState failed, hresult 0x%08x \n " , hr ) ;
2007-04-29 03:12:09 +02:00
ok ( myint = = INSTALLSTATE_UNKNOWN , " Feature current state was %d but expected %d \n " , myint , INSTALLSTATE_UNKNOWN ) ;
2008-07-16 18:47:08 +02:00
/* Session::Message */
hr = Installer_CreateRecord ( 0 , & record ) ;
ok ( hr = = S_OK , " Installer_CreateRecord failed: %08x \n " , hr ) ;
hr = Session_Message ( pSession , INSTALLMESSAGE_INFO , record , & myint ) ;
ok ( hr = = S_OK , " Session_Message failed: %08x \n " , hr ) ;
ok ( myint = = 0 , " Session_Message returned %x \n " , myint ) ;
2007-05-11 21:07:41 +02:00
/* Session::EvaluateCondition */
2007-05-11 21:07:48 +02:00
hr = Session_EvaluateCondition ( pSession , szOneStateFalse , & myint ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Session_EvaluateCondition failed, hresult 0x%08x \n " , hr ) ;
2007-05-16 02:29:12 +02:00
ok ( myint = = MSICONDITION_FALSE , " Feature current state was %d but expected %d \n " , myint , INSTALLSTATE_UNKNOWN ) ;
2007-05-11 21:07:48 +02:00
hr = Session_EvaluateCondition ( pSession , szOneStateTrue , & myint ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Session_EvaluateCondition failed, hresult 0x%08x \n " , hr ) ;
2007-05-11 21:07:48 +02:00
ok ( myint = = MSICONDITION_TRUE , " Feature current state was %d but expected %d \n " , myint , INSTALLSTATE_UNKNOWN ) ;
2007-05-11 21:07:41 +02:00
2007-04-29 03:12:09 +02:00
/* Session::FeatureRequestState, put */
hr = Session_FeatureRequestStatePut ( pSession , szOne , INSTALLSTATE_ADVERTISED ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Session_FeatureRequestStatePut failed, hresult 0x%08x \n " , hr ) ;
2007-04-29 03:12:09 +02:00
hr = Session_FeatureRequestStateGet ( pSession , szOne , & myint ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Session_FeatureRequestStateGet failed, hresult 0x%08x \n " , hr ) ;
2007-04-29 03:12:09 +02:00
ok ( myint = = INSTALLSTATE_ADVERTISED , " Feature request state was %d but expected %d \n " , myint , INSTALLSTATE_ADVERTISED ) ;
2007-05-11 21:07:41 +02:00
/* Session::EvaluateCondition */
2007-05-11 21:07:48 +02:00
hr = Session_EvaluateCondition ( pSession , szOneActionFalse , & myint ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Session_EvaluateCondition failed, hresult 0x%08x \n " , hr ) ;
2007-05-16 02:29:12 +02:00
ok ( myint = = MSICONDITION_FALSE , " Feature current state was %d but expected %d \n " , myint , INSTALLSTATE_UNKNOWN ) ;
2007-05-11 21:07:48 +02:00
hr = Session_EvaluateCondition ( pSession , szOneActionTrue , & myint ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Session_EvaluateCondition failed, hresult 0x%08x \n " , hr ) ;
2007-05-11 21:07:48 +02:00
ok ( myint = = MSICONDITION_TRUE , " Feature current state was %d but expected %d \n " , myint , INSTALLSTATE_UNKNOWN ) ;
2007-04-29 03:12:09 +02:00
}
2007-05-08 00:51:36 +02:00
/* delete key and all its subkeys */
static DWORD delete_key ( HKEY hkey )
{
char name [ MAX_PATH ] ;
DWORD ret ;
while ( ! ( ret = RegEnumKeyA ( hkey , 0 , name , sizeof ( name ) ) ) )
{
HKEY tmp ;
if ( ! ( ret = RegOpenKeyExA ( hkey , name , 0 , KEY_ENUMERATE_SUB_KEYS , & tmp ) ) )
{
ret = delete_key ( tmp ) ;
RegCloseKey ( tmp ) ;
}
if ( ret ) break ;
}
if ( ret ! = ERROR_NO_MORE_ITEMS ) return ret ;
RegDeleteKeyA ( hkey , " " ) ;
return 0 ;
}
static void test_Installer_RegistryValue ( void )
{
static const DWORD qw [ 2 ] = { 0x12345678 , 0x87654321 } ;
static const WCHAR szKey [ ] = { ' S ' , ' o ' , ' f ' , ' t ' , ' w ' , ' a ' , ' r ' , ' e ' , ' \\ ' , ' W ' , ' i ' , ' n ' , ' e ' , ' \\ ' , ' T ' , ' e ' , ' s ' , ' t ' , 0 } ;
static const WCHAR szOne [ ] = { ' O ' , ' n ' , ' e ' , 0 } ;
static const WCHAR szTwo [ ] = { ' T ' , ' w ' , ' o ' , 0 } ;
static const WCHAR szThree [ ] = { ' T ' , ' h ' , ' r ' , ' e ' , ' e ' , 0 } ;
2007-05-09 14:56:44 +02:00
static const WCHAR szREG_BINARY [ ] = { ' ( ' , ' R ' , ' E ' , ' G ' , ' _ ' , ' B ' , ' I ' , ' N ' , ' A ' , ' R ' , ' Y ' , ' ) ' , 0 } ;
2007-05-08 00:51:36 +02:00
static const WCHAR szFour [ ] = { ' F ' , ' o ' , ' u ' , ' r ' , 0 } ;
2007-05-09 14:56:44 +02:00
static const WCHAR szExpand [ ] = { ' % ' , ' M ' , ' S ' , ' I ' , ' T ' , ' E ' , ' S ' , ' T ' , ' % ' , 0 } ;
static const WCHAR szFive [ ] = { ' F ' , ' i ' , ' v ' , ' e ' , 0 , ' H ' , ' i ' , 0 , 0 } ;
static const WCHAR szFiveHi [ ] = { ' F ' , ' i ' , ' v ' , ' e ' , ' \n ' , ' H ' , ' i ' , 0 } ;
static const WCHAR szSix [ ] = { ' S ' , ' i ' , ' x ' , 0 } ;
static const WCHAR szREG_ [ ] = { ' ( ' , ' R ' , ' E ' , ' G ' , ' _ ' , ' ] ' , 0 } ;
static const WCHAR szSeven [ ] = { ' S ' , ' e ' , ' v ' , ' e ' , ' n ' , 0 } ;
static const WCHAR szEight [ ] = { ' E ' , ' i ' , ' g ' , ' h ' , ' t ' , 0 } ;
2007-05-08 00:51:36 +02:00
static const WCHAR szBlank [ ] = { 0 } ;
2007-05-09 14:56:44 +02:00
VARIANT varresult ;
VARIANTARG vararg ;
2007-05-08 00:51:36 +02:00
WCHAR szString [ MAX_PATH ] ;
HKEY hkey , hkey_sub ;
2008-03-20 08:07:37 +01:00
HKEY curr_user = ( HKEY ) 1 ;
2007-05-08 00:51:36 +02:00
HRESULT hr ;
BOOL bRet ;
2008-11-11 13:37:30 +01:00
LONG lRet ;
2007-05-08 00:51:36 +02:00
/* Delete keys */
2008-11-11 13:37:30 +01:00
SetLastError ( 0xdeadbeef ) ;
lRet = RegOpenKeyW ( HKEY_CURRENT_USER , szKey , & hkey ) ;
if ( ! lRet & & GetLastError ( ) = = ERROR_CALL_NOT_IMPLEMENTED )
{
win_skip ( " Needed W-functions are not implemented \n " ) ;
return ;
}
if ( ! lRet )
delete_key ( hkey ) ;
2007-05-08 00:51:36 +02:00
2007-05-09 14:56:44 +02:00
/* Does our key exist? Shouldn't; check with all three possible value parameter types */
2008-03-20 08:07:37 +01:00
hr = Installer_RegistryValueE ( curr_user , szKey , & bRet ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Installer_RegistryValueE failed, hresult 0x%08x \n " , hr ) ;
2007-05-16 02:29:12 +02:00
ok ( ! bRet , " Registry key expected to not exist, but Installer_RegistryValue claims it does \n " ) ;
2007-05-10 22:40:28 +02:00
memset ( szString , 0 , sizeof ( szString ) ) ;
2008-03-20 08:07:37 +01:00
hr = Installer_RegistryValueW ( curr_user , szKey , NULL , szString ) ;
2007-05-10 22:40:28 +02:00
ok ( hr = = DISP_E_BADINDEX , " Installer_RegistryValueW failed, hresult 0x%08x \n " , hr ) ;
memset ( szString , 0 , sizeof ( szString ) ) ;
2008-03-20 08:07:37 +01:00
hr = Installer_RegistryValueI ( curr_user , szKey , 0 , szString , VT_BSTR ) ;
2007-05-10 22:40:28 +02:00
ok ( hr = = DISP_E_BADINDEX , " Installer_RegistryValueI failed, hresult 0x%08x \n " , hr ) ;
2007-05-08 00:51:36 +02:00
/* Create key */
ok ( ! RegCreateKeyW ( HKEY_CURRENT_USER , szKey , & hkey ) , " RegCreateKeyW failed \n " ) ;
ok ( ! RegSetValueExW ( hkey , szOne , 0 , REG_SZ , ( const BYTE * ) szOne , sizeof ( szOne ) ) ,
" RegSetValueExW failed \n " ) ;
ok ( ! RegSetValueExW ( hkey , szTwo , 0 , REG_DWORD , ( const BYTE * ) qw , 4 ) ,
" RegSetValueExW failed \n " ) ;
ok ( ! RegSetValueExW ( hkey , szThree , 0 , REG_BINARY , ( const BYTE * ) qw , 4 ) ,
" RegSetValueExW failed \n " ) ;
2007-05-09 14:56:44 +02:00
ok ( SetEnvironmentVariableA ( " MSITEST " , " Four " ) , " SetEnvironmentVariableA failed %d \n " , GetLastError ( ) ) ;
ok ( ! RegSetValueExW ( hkey , szFour , 0 , REG_EXPAND_SZ , ( const BYTE * ) szExpand , sizeof ( szExpand ) ) ,
" RegSetValueExW failed \n " ) ;
ok ( ! RegSetValueExW ( hkey , szFive , 0 , REG_MULTI_SZ , ( const BYTE * ) szFive , sizeof ( szFive ) ) ,
" RegSetValueExW failed \n " ) ;
ok ( ! RegSetValueExW ( hkey , szSix , 0 , REG_QWORD , ( const BYTE * ) qw , 8 ) ,
" RegSetValueExW failed \n " ) ;
2008-11-02 00:27:00 +01:00
ok ( ! RegSetValueExW ( hkey , szSeven , 0 , REG_NONE , NULL , 0 ) ,
2007-05-09 14:56:44 +02:00
" RegSetValueExW failed \n " ) ;
2007-05-08 00:51:36 +02:00
ok ( ! RegSetValueExW ( hkey , NULL , 0 , REG_SZ , ( const BYTE * ) szOne , sizeof ( szOne ) ) ,
" RegSetValueExW failed \n " ) ;
2007-05-09 14:56:44 +02:00
ok ( ! RegCreateKeyW ( hkey , szEight , & hkey_sub ) , " RegCreateKeyW failed \n " ) ;
2007-05-08 00:51:36 +02:00
2007-05-10 22:40:28 +02:00
/* Does our key exist? It should, and make sure we retrieve the correct default value */
bRet = FALSE ;
2008-03-20 08:07:37 +01:00
hr = Installer_RegistryValueE ( curr_user , szKey , & bRet ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Installer_RegistryValueE failed, hresult 0x%08x \n " , hr ) ;
2007-05-16 02:29:12 +02:00
ok ( bRet , " Registry key expected to exist, but Installer_RegistryValue claims it does not \n " ) ;
2007-05-10 22:40:28 +02:00
memset ( szString , 0 , sizeof ( szString ) ) ;
2008-03-20 08:07:37 +01:00
hr = Installer_RegistryValueW ( curr_user , szKey , NULL , szString ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Installer_RegistryValueW failed, hresult 0x%08x \n " , hr ) ;
2007-05-10 22:40:28 +02:00
ok_w2 ( " Default registry value \" %s \" does not match expected \" %s \" \n " , szString , szOne ) ;
2007-05-15 14:01:05 +02:00
/* Ask for the value of a nonexistent key */
2007-05-10 22:40:28 +02:00
memset ( szString , 0 , sizeof ( szString ) ) ;
2008-03-20 08:07:37 +01:00
hr = Installer_RegistryValueW ( curr_user , szKey , szExpand , szString ) ;
2007-05-10 22:40:28 +02:00
ok ( hr = = DISP_E_BADINDEX , " Installer_RegistryValueW failed, hresult 0x%08x \n " , hr ) ;
/* Get values of keys */
memset ( szString , 0 , sizeof ( szString ) ) ;
2008-03-20 08:07:37 +01:00
hr = Installer_RegistryValueW ( curr_user , szKey , szOne , szString ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Installer_RegistryValueW failed, hresult 0x%08x \n " , hr ) ;
2007-05-10 22:40:28 +02:00
ok_w2 ( " Registry value \" %s \" does not match expected \" %s \" \n " , szString , szOne ) ;
VariantInit ( & vararg ) ;
V_VT ( & vararg ) = VT_BSTR ;
V_BSTR ( & vararg ) = SysAllocString ( szTwo ) ;
2008-03-20 08:07:37 +01:00
hr = Installer_RegistryValue ( curr_user , szKey , vararg , & varresult , VT_I4 ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Installer_RegistryValue failed, hresult 0x%08x \n " , hr ) ;
2007-05-10 22:40:28 +02:00
ok ( V_I4 ( & varresult ) = = 305419896 , " Registry value %d does not match expected value \n " , V_I4 ( & varresult ) ) ;
VariantClear ( & varresult ) ;
memset ( szString , 0 , sizeof ( szString ) ) ;
2008-03-20 08:07:37 +01:00
hr = Installer_RegistryValueW ( curr_user , szKey , szThree , szString ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Installer_RegistryValueW failed, hresult 0x%08x \n " , hr ) ;
2007-05-10 22:40:28 +02:00
ok_w2 ( " Registry value \" %s \" does not match expected \" %s \" \n " , szString , szREG_BINARY ) ;
memset ( szString , 0 , sizeof ( szString ) ) ;
2008-03-20 08:07:37 +01:00
hr = Installer_RegistryValueW ( curr_user , szKey , szFour , szString ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Installer_RegistryValueW failed, hresult 0x%08x \n " , hr ) ;
2007-05-10 22:40:28 +02:00
ok_w2 ( " Registry value \" %s \" does not match expected \" %s \" \n " , szString , szFour ) ;
2008-09-02 08:04:59 +02:00
/* Vista does not NULL-terminate this case */
2007-05-10 22:40:28 +02:00
memset ( szString , 0 , sizeof ( szString ) ) ;
2008-03-20 08:07:37 +01:00
hr = Installer_RegistryValueW ( curr_user , szKey , szFive , szString ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Installer_RegistryValueW failed, hresult 0x%08x \n " , hr ) ;
2008-09-02 08:04:59 +02:00
ok_w2n ( " Registry value \" %s \" does not match expected \" %s \" \n " ,
szString , szFiveHi , lstrlenW ( szFiveHi ) ) ;
2007-05-10 22:40:28 +02:00
memset ( szString , 0 , sizeof ( szString ) ) ;
2008-03-20 08:07:37 +01:00
hr = Installer_RegistryValueW ( curr_user , szKey , szSix , szString ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Installer_RegistryValueW failed, hresult 0x%08x \n " , hr ) ;
2007-05-10 22:40:28 +02:00
ok_w2 ( " Registry value \" %s \" does not match expected \" %s \" \n " , szString , szREG_ ) ;
VariantInit ( & vararg ) ;
V_VT ( & vararg ) = VT_BSTR ;
V_BSTR ( & vararg ) = SysAllocString ( szSeven ) ;
2008-03-20 08:07:37 +01:00
hr = Installer_RegistryValue ( curr_user , szKey , vararg , & varresult , VT_EMPTY ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Installer_RegistryValue failed, hresult 0x%08x \n " , hr ) ;
2007-05-10 22:40:28 +02:00
/* Get string class name for the key */
memset ( szString , 0 , sizeof ( szString ) ) ;
2008-03-20 08:07:37 +01:00
hr = Installer_RegistryValueI ( curr_user , szKey , 0 , szString , VT_BSTR ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Installer_RegistryValueI failed, hresult 0x%08x \n " , hr ) ;
2007-05-10 22:40:28 +02:00
ok_w2 ( " Registry name \" %s \" does not match expected \" %s \" \n " , szString , szBlank ) ;
/* Get name of a value by positive number (RegEnumValue like), valid index */
memset ( szString , 0 , sizeof ( szString ) ) ;
2008-03-20 08:07:37 +01:00
hr = Installer_RegistryValueI ( curr_user , szKey , 2 , szString , VT_BSTR ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Installer_RegistryValueI failed, hresult 0x%08x \n " , hr ) ;
2007-05-10 22:40:28 +02:00
/* RegEnumValue order seems different on wine */
todo_wine ok_w2 ( " Registry name \" %s \" does not match expected \" %s \" \n " , szString , szTwo ) ;
/* Get name of a value by positive number (RegEnumValue like), invalid index */
memset ( szString , 0 , sizeof ( szString ) ) ;
2008-03-20 08:07:37 +01:00
hr = Installer_RegistryValueI ( curr_user , szKey , 10 , szString , VT_EMPTY ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Installer_RegistryValueI failed, hresult 0x%08x \n " , hr ) ;
2007-05-10 22:40:28 +02:00
/* Get name of a subkey by negative number (RegEnumValue like), valid index */
memset ( szString , 0 , sizeof ( szString ) ) ;
2008-03-20 08:07:37 +01:00
hr = Installer_RegistryValueI ( curr_user , szKey , - 1 , szString , VT_BSTR ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Installer_RegistryValueI failed, hresult 0x%08x \n " , hr ) ;
2007-05-10 22:40:28 +02:00
ok_w2 ( " Registry name \" %s \" does not match expected \" %s \" \n " , szString , szEight ) ;
/* Get name of a subkey by negative number (RegEnumValue like), invalid index */
memset ( szString , 0 , sizeof ( szString ) ) ;
2008-03-20 08:07:37 +01:00
hr = Installer_RegistryValueI ( curr_user , szKey , - 10 , szString , VT_EMPTY ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Installer_RegistryValueI failed, hresult 0x%08x \n " , hr ) ;
2007-05-08 00:51:36 +02:00
/* clean up */
delete_key ( hkey ) ;
}
2007-05-20 21:31:52 +02:00
static void test_Installer_Products ( BOOL bProductInstalled )
{
WCHAR szString [ MAX_PATH ] ;
HRESULT hr ;
int idx ;
IUnknown * pUnk = NULL ;
IEnumVARIANT * pEnum = NULL ;
VARIANT var ;
ULONG celt ;
int iCount , iValue ;
IDispatch * pStringList = NULL ;
BOOL bProductFound = FALSE ;
/* Installer::Products */
hr = Installer_Products ( & pStringList ) ;
ok ( hr = = S_OK , " Installer_Products failed, hresult 0x%08x \n " , hr ) ;
if ( hr = = S_OK )
{
/* StringList::_NewEnum */
hr = StringList__NewEnum ( pStringList , & pUnk ) ;
ok ( hr = = S_OK , " StringList_NewEnum failed, hresult 0x%08x \n " , hr ) ;
if ( hr = = S_OK )
{
hr = IUnknown_QueryInterface ( pUnk , & IID_IEnumVARIANT , ( void * * ) & pEnum ) ;
ok ( hr = = S_OK , " IUnknown::QueryInterface returned 0x%08x \n " , hr ) ;
}
if ( ! pEnum )
skip ( " IEnumVARIANT tests \n " ) ;
/* StringList::Count */
hr = StringList_Count ( pStringList , & iCount ) ;
ok ( hr = = S_OK , " StringList_Count failed, hresult 0x%08x \n " , hr ) ;
for ( idx = 0 ; idx < iCount ; idx + + )
{
/* StringList::Item */
memset ( szString , 0 , sizeof ( szString ) ) ;
hr = StringList_Item ( pStringList , idx , szString ) ;
ok ( hr = = S_OK , " StringList_Item failed (idx %d, count %d), hresult 0x%08x \n " , idx , iCount , hr ) ;
if ( hr = = S_OK )
{
/* Installer::ProductState */
hr = Installer_ProductState ( szString , & iValue ) ;
ok ( hr = = S_OK , " Installer_ProductState failed, hresult 0x%08x \n " , hr ) ;
if ( hr = = S_OK )
ok ( iValue = = INSTALLSTATE_DEFAULT | | iValue = = INSTALLSTATE_ADVERTISED , " Installer_ProductState returned %d, expected %d or %d \n " , iValue , INSTALLSTATE_DEFAULT , INSTALLSTATE_ADVERTISED ) ;
/* Not found our product code yet? Check */
if ( ! bProductFound & & ! lstrcmpW ( szString , szProductCode ) )
bProductFound = TRUE ;
/* IEnumVARIANT::Next */
if ( pEnum )
{
hr = IEnumVARIANT_Next ( pEnum , 1 , & var , & celt ) ;
ok ( hr = = S_OK , " IEnumVARIANT_Next failed (idx %d, count %d), hresult 0x%08x \n " , idx , iCount , hr ) ;
ok ( celt = = 1 , " %d items were retrieved, expected 1 \n " , celt ) ;
ok ( V_VT ( & var ) = = VT_BSTR , " IEnumVARIANT_Next returned variant of type %d, expected %d \n " , V_VT ( & var ) , VT_BSTR ) ;
ok_w2 ( " %s returned by StringList_Item does not match %s returned by IEnumVARIANT_Next \n " , szString , V_BSTR ( & var ) ) ;
VariantClear ( & var ) ;
}
}
}
2008-06-24 05:59:03 +02:00
if ( bProductInstalled ) todo_wine
{
ok ( bProductInstalled = = bProductFound , " Product expected to %s installed but product code was %s \n " ,
bProductInstalled ? " be " : " not be " ,
bProductFound ? " found " : " not found " ) ;
}
2007-05-20 21:31:52 +02:00
if ( pEnum )
{
IEnumVARIANT * pEnum2 = NULL ;
if ( 0 ) /* Crashes on Windows XP */
{
/* IEnumVARIANT::Clone, NULL pointer */
hr = IEnumVARIANT_Clone ( pEnum , NULL ) ;
}
/* IEnumVARIANT::Clone */
hr = IEnumVARIANT_Clone ( pEnum , & pEnum2 ) ;
ok ( hr = = S_OK , " IEnumVARIANT_Clone failed, hresult 0x%08x \n " , hr ) ;
if ( hr = = S_OK )
{
/* IEnumVARIANT::Clone is supposed to save the position, but it actually just goes back to the beginning */
/* IEnumVARIANT::Next of the clone */
if ( iCount )
{
hr = IEnumVARIANT_Next ( pEnum2 , 1 , & var , & celt ) ;
ok ( hr = = S_OK , " IEnumVARIANT_Next failed, hresult 0x%08x \n " , hr ) ;
ok ( celt = = 1 , " %d items were retrieved, expected 0 \n " , celt ) ;
ok ( V_VT ( & var ) = = VT_BSTR , " IEnumVARIANT_Next returned variant of type %d, expected %d \n " , V_VT ( & var ) , VT_BSTR ) ;
VariantClear ( & var ) ;
}
else
skip ( " IEnumVARIANT::Next of clone will not return success with 0 products \n " ) ;
IEnumVARIANT_Release ( pEnum2 ) ;
}
/* IEnumVARIANT::Skip should fail */
hr = IEnumVARIANT_Skip ( pEnum , 1 ) ;
ok ( hr = = S_FALSE , " IEnumVARIANT_Skip failed, hresult 0x%08x \n " , hr ) ;
/* IEnumVARIANT::Next, NULL variant pointer */
hr = IEnumVARIANT_Next ( pEnum , 1 , NULL , & celt ) ;
ok ( hr = = S_FALSE , " IEnumVARIANT_Next failed, hresult 0x%08x \n " , hr ) ;
ok ( celt = = 0 , " %d items were retrieved, expected 0 \n " , celt ) ;
/* IEnumVARIANT::Next, should not return any more items */
hr = IEnumVARIANT_Next ( pEnum , 1 , & var , & celt ) ;
ok ( hr = = S_FALSE , " IEnumVARIANT_Next failed, hresult 0x%08x \n " , hr ) ;
ok ( celt = = 0 , " %d items were retrieved, expected 0 \n " , celt ) ;
VariantClear ( & var ) ;
/* IEnumVARIANT::Reset */
hr = IEnumVARIANT_Reset ( pEnum ) ;
ok ( hr = = S_OK , " IEnumVARIANT_Reset failed, hresult 0x%08x \n " , hr ) ;
if ( iCount )
{
/* IEnumVARIANT::Skip to the last product */
hr = IEnumVARIANT_Skip ( pEnum , iCount - 1 ) ;
ok ( hr = = S_OK , " IEnumVARIANT_Skip failed, hresult 0x%08x \n " , hr ) ;
/* IEnumVARIANT::Next should match the very last retrieved value, also makes sure it works with
* NULL celt pointer . */
hr = IEnumVARIANT_Next ( pEnum , 1 , & var , NULL ) ;
ok ( hr = = S_OK , " IEnumVARIANT_Next failed (idx %d, count %d), hresult 0x%08x \n " , idx , iCount , hr ) ;
ok ( V_VT ( & var ) = = VT_BSTR , " IEnumVARIANT_Next returned variant of type %d, expected %d \n " , V_VT ( & var ) , VT_BSTR ) ;
ok_w2 ( " %s returned by StringList_Item does not match %s returned by IEnumVARIANT_Next \n " , szString , V_BSTR ( & var ) ) ;
VariantClear ( & var ) ;
}
else
skip ( " IEnumVARIANT::Skip impossible for 0 products \n " ) ;
}
/* StringList::Item using an invalid index */
memset ( szString , 0 , sizeof ( szString ) ) ;
hr = StringList_Item ( pStringList , iCount , szString ) ;
ok ( hr = = DISP_E_BADINDEX , " StringList_Item for an invalid index did not return DISP_E_BADINDEX, hresult 0x%08x \n " , hr ) ;
if ( pEnum ) IEnumVARIANT_Release ( pEnum ) ;
if ( pUnk ) IUnknown_Release ( pUnk ) ;
IDispatch_Release ( pStringList ) ;
}
}
2007-05-14 19:14:42 +02:00
/* Delete a registry subkey, including all its subkeys (RegDeleteKey does not work on keys with subkeys without
* deleting the subkeys first ) */
static UINT delete_registry_key ( HKEY hkeyParent , LPCSTR subkey )
{
UINT ret ;
CHAR * string = NULL ;
HKEY hkey ;
DWORD dwSize ;
ret = RegOpenKey ( hkeyParent , subkey , & hkey ) ;
if ( ret ! = ERROR_SUCCESS ) return ret ;
ret = RegQueryInfoKeyA ( hkey , NULL , NULL , NULL , NULL , & dwSize , NULL , NULL , NULL , NULL , NULL , NULL ) ;
if ( ret ! = ERROR_SUCCESS ) return ret ;
if ( ! ( string = HeapAlloc ( GetProcessHeap ( ) , 0 , + + dwSize ) ) ) return ERROR_NOT_ENOUGH_MEMORY ;
while ( RegEnumKeyA ( hkey , 0 , string , dwSize ) = = ERROR_SUCCESS )
delete_registry_key ( hkey , string ) ;
RegCloseKey ( hkey ) ;
HeapFree ( GetProcessHeap ( ) , 0 , string ) ;
RegDeleteKeyA ( hkeyParent , subkey ) ;
return ERROR_SUCCESS ;
}
/* Find a specific registry subkey at any depth within the given key and subkey and return its parent key. */
static UINT find_registry_key ( HKEY hkeyParent , LPCSTR subkey , LPCSTR findkey , HKEY * phkey )
{
UINT ret ;
CHAR * string = NULL ;
int idx = 0 ;
HKEY hkey ;
DWORD dwSize ;
BOOL found = FALSE ;
* phkey = 0 ;
ret = RegOpenKey ( hkeyParent , subkey , & hkey ) ;
if ( ret ! = ERROR_SUCCESS ) return ret ;
ret = RegQueryInfoKeyA ( hkey , NULL , NULL , NULL , NULL , & dwSize , NULL , NULL , NULL , NULL , NULL , NULL ) ;
if ( ret ! = ERROR_SUCCESS ) return ret ;
if ( ! ( string = HeapAlloc ( GetProcessHeap ( ) , 0 , + + dwSize ) ) ) return ERROR_NOT_ENOUGH_MEMORY ;
while ( ! found & &
RegEnumKeyA ( hkey , idx + + , string , dwSize ) = = ERROR_SUCCESS )
{
if ( ! strcmp ( string , findkey ) )
{
* phkey = hkey ;
found = TRUE ;
}
else if ( find_registry_key ( hkey , string , findkey , phkey ) = = ERROR_SUCCESS ) found = TRUE ;
}
if ( * phkey ! = hkey ) RegCloseKey ( hkey ) ;
HeapFree ( GetProcessHeap ( ) , 0 , string ) ;
return ( found ? ERROR_SUCCESS : ERROR_FILE_NOT_FOUND ) ;
}
2007-11-05 10:45:32 +01:00
static void test_Installer_InstallProduct ( void )
2007-05-14 19:14:42 +02:00
{
HRESULT hr ;
CHAR path [ MAX_PATH ] ;
2007-05-14 19:15:02 +02:00
WCHAR szString [ MAX_PATH ] ;
2007-05-14 19:14:42 +02:00
LONG res ;
HKEY hkey ;
DWORD num , size , type ;
2007-05-14 19:15:02 +02:00
int iValue , iCount ;
IDispatch * pStringList = NULL ;
2007-05-14 19:14:42 +02:00
create_test_files ( ) ;
/* Installer::InstallProduct */
2007-05-14 19:14:51 +02:00
hr = Installer_InstallProduct ( szMsifile , NULL ) ;
2008-03-17 22:58:16 +01:00
if ( hr = = DISP_E_EXCEPTION )
{
skip ( " Installer object not supported. \n " ) ;
delete_test_files ( ) ;
return ;
}
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Installer_InstallProduct failed, hresult 0x%08x \n " , hr ) ;
2007-05-14 19:14:42 +02:00
/* Installer::ProductState for our product code, which has been installed */
hr = Installer_ProductState ( szProductCode , & iValue ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Installer_ProductState failed, hresult 0x%08x \n " , hr ) ;
2007-06-27 04:22:46 +02:00
ok ( iValue = = INSTALLSTATE_DEFAULT , " Installer_ProductState returned %d, expected %d \n " , iValue , INSTALLSTATE_DEFAULT ) ;
2007-05-14 19:14:42 +02:00
2007-05-16 02:30:09 +02:00
/* Installer::ProductInfo for our product code */
2007-05-17 07:42:46 +02:00
/* NULL attribute */
memset ( szString , 0 , sizeof ( szString ) ) ;
hr = Installer_ProductInfo ( szProductCode , NULL , szString ) ;
ok ( hr = = DISP_E_EXCEPTION , " Installer_ProductInfo failed, hresult 0x%08x \n " , hr ) ;
ok_exception ( hr , szProductInfoException ) ;
2007-05-16 02:30:09 +02:00
2007-05-28 01:10:17 +02:00
/* Nonexistent attribute */
2007-05-17 07:42:46 +02:00
memset ( szString , 0 , sizeof ( szString ) ) ;
hr = Installer_ProductInfo ( szProductCode , szMsifile , szString ) ;
ok ( hr = = DISP_E_EXCEPTION , " Installer_ProductInfo failed, hresult 0x%08x \n " , hr ) ;
ok_exception ( hr , szProductInfoException ) ;
2007-05-16 02:30:09 +02:00
2007-05-17 07:42:46 +02:00
/* Package name */
memset ( szString , 0 , sizeof ( szString ) ) ;
2007-07-13 05:04:19 +02:00
hr = Installer_ProductInfo ( szProductCode , WINE_INSTALLPROPERTY_PACKAGENAMEW , szString ) ;
2008-02-25 03:06:28 +01:00
ok ( hr = = S_OK , " Installer_ProductInfo failed, hresult 0x%08x \n " , hr ) ;
2007-05-18 18:22:31 +02:00
todo_wine ok_w2 ( " Installer_ProductInfo returned %s but expected %s \n " , szString , szMsifile ) ;
2007-05-17 07:42:46 +02:00
/* Product name */
memset ( szString , 0 , sizeof ( szString ) ) ;
2007-07-13 05:04:19 +02:00
hr = Installer_ProductInfo ( szProductCode , WINE_INSTALLPROPERTY_PRODUCTNAMEW , szString ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Installer_ProductInfo failed, hresult 0x%08x \n " , hr ) ;
2008-02-12 08:35:46 +01:00
todo_wine ok_w2 ( " Installer_ProductInfo returned %s but expected %s \n " , szString , szMSITEST ) ;
2007-05-16 02:30:09 +02:00
2007-05-20 21:31:52 +02:00
/* Installer::Products */
test_Installer_Products ( TRUE ) ;
2007-05-14 19:15:02 +02:00
/* Installer::RelatedProducts for our upgrade code */
2007-05-14 19:15:13 +02:00
hr = Installer_RelatedProducts ( szUpgradeCode , & pStringList ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Installer_RelatedProducts failed, hresult 0x%08x \n " , hr ) ;
if ( hr = = S_OK )
2007-05-14 19:15:13 +02:00
{
/* StringList::Count */
hr = StringList_Count ( pStringList , & iCount ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " StringList_Count failed, hresult 0x%08x \n " , hr ) ;
2007-05-14 19:15:46 +02:00
ok ( iCount = = 1 , " Expected one related product but found %d \n " , iCount ) ;
2007-05-14 19:15:02 +02:00
2007-05-14 19:15:13 +02:00
/* StringList::Item */
memset ( szString , 0 , sizeof ( szString ) ) ;
hr = StringList_Item ( pStringList , 0 , szString ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " StringList_Item failed (idx 0, count %d), hresult 0x%08x \n " , iCount , hr ) ;
2007-05-14 19:15:46 +02:00
ok_w2 ( " StringList_Item returned %s but expected %s \n " , szString , szProductCode ) ;
2007-05-14 19:15:02 +02:00
2007-05-14 19:15:13 +02:00
IDispatch_Release ( pStringList ) ;
2007-05-14 19:15:02 +02:00
}
2007-05-14 19:14:42 +02:00
/* Check & clean up installed files & registry keys */
2007-05-14 19:14:51 +02:00
ok ( delete_pf ( " msitest \\ cabout \\ new \\ five.txt " , TRUE ) , " File not installed \n " ) ;
ok ( delete_pf ( " msitest \\ cabout \\ new " , FALSE ) , " File not installed \n " ) ;
ok ( delete_pf ( " msitest \\ cabout \\ four.txt " , TRUE ) , " File not installed \n " ) ;
ok ( delete_pf ( " msitest \\ cabout " , FALSE ) , " File not installed \n " ) ;
ok ( delete_pf ( " msitest \\ changed \\ three.txt " , TRUE ) , " File not installed \n " ) ;
ok ( delete_pf ( " msitest \\ changed " , FALSE ) , " File not installed \n " ) ;
ok ( delete_pf ( " msitest \\ first \\ two.txt " , TRUE ) , " File not installed \n " ) ;
ok ( delete_pf ( " msitest \\ first " , FALSE ) , " File not installed \n " ) ;
ok ( delete_pf ( " msitest \\ one.txt " , TRUE ) , " File not installed \n " ) ;
ok ( delete_pf ( " msitest \\ filename " , TRUE ) , " File not installed \n " ) ;
ok ( delete_pf ( " msitest " , FALSE ) , " File not installed \n " ) ;
res = RegOpenKey ( HKEY_LOCAL_MACHINE , " SOFTWARE \\ Wine \\ msitest " , & hkey ) ;
ok ( res = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %d \n " , res ) ;
2007-05-14 19:14:42 +02:00
2007-05-14 19:14:51 +02:00
size = MAX_PATH ;
type = REG_SZ ;
res = RegQueryValueExA ( hkey , " Name " , NULL , & type , ( LPBYTE ) path , & size ) ;
ok ( res = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %d \n " , res ) ;
ok ( ! lstrcmpA ( path , " imaname " ) , " Expected imaname, got %s \n " , path ) ;
2007-05-14 19:14:42 +02:00
2007-05-14 19:14:51 +02:00
size = MAX_PATH ;
type = REG_SZ ;
res = RegQueryValueExA ( hkey , " blah " , NULL , & type , ( LPBYTE ) path , & size ) ;
ok ( res = = ERROR_FILE_NOT_FOUND , " Expected ERROR_FILE_NOT_FOUND, got %d \n " , res ) ;
2007-05-14 19:14:42 +02:00
2007-05-14 19:14:51 +02:00
size = sizeof ( num ) ;
type = REG_DWORD ;
res = RegQueryValueExA ( hkey , " number " , NULL , & type , ( LPBYTE ) & num , & size ) ;
ok ( res = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %d \n " , res ) ;
ok ( num = = 314 , " Expected 314, got %d \n " , num ) ;
2007-05-14 19:14:42 +02:00
2007-05-14 19:14:51 +02:00
size = MAX_PATH ;
type = REG_SZ ;
res = RegQueryValueExA ( hkey , " OrderTestName " , NULL , & type , ( LPBYTE ) path , & size ) ;
ok ( res = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %d \n " , res ) ;
ok ( ! lstrcmpA ( path , " OrderTestValue " ) , " Expected imaname, got %s \n " , path ) ;
2007-05-14 19:14:42 +02:00
2007-05-14 19:14:51 +02:00
RegCloseKey ( hkey ) ;
2007-05-14 19:14:42 +02:00
2007-05-14 19:14:51 +02:00
res = RegDeleteKeyA ( HKEY_LOCAL_MACHINE , " SOFTWARE \\ Wine \\ msitest " ) ;
ok ( res = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %d \n " , res ) ;
2007-05-14 19:14:42 +02:00
/* Remove registry keys written by RegisterProduct standard action */
2007-05-14 19:14:51 +02:00
res = RegDeleteKeyA ( HKEY_LOCAL_MACHINE , " SOFTWARE \\ Microsoft \\ Windows \\ CurrentVersion \\ Uninstall \\ {F1C3AF50-8B56-4A69-A00C-00773FE42F30} " ) ;
ok ( res = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %d \n " , res ) ;
2007-05-14 19:14:42 +02:00
2007-05-14 19:14:51 +02:00
res = RegDeleteKeyA ( HKEY_LOCAL_MACHINE , " SOFTWARE \\ Microsoft \\ Windows \\ CurrentVersion \\ Installer \\ UpgradeCodes \\ D8E760ECA1E276347B43E42BDBDA5656 " ) ;
ok ( res = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %d \n " , res ) ;
2007-05-14 19:14:42 +02:00
2007-05-14 19:14:51 +02:00
res = find_registry_key ( HKEY_LOCAL_MACHINE , " SOFTWARE \\ Microsoft \\ Windows \\ CurrentVersion \\ Installer \\ UserData " , " 05FA3C1F65B896A40AC00077F34EF203 " , & hkey ) ;
2009-02-26 06:14:28 +01:00
ok ( res = = ERROR_SUCCESS | |
broken ( res = = ERROR_FILE_NOT_FOUND ) , /* win9x */
" Expected ERROR_SUCCESS, got %d \n " , res ) ;
2007-05-14 19:14:51 +02:00
if ( res = = ERROR_SUCCESS )
{
res = delete_registry_key ( hkey , " 05FA3C1F65B896A40AC00077F34EF203 " ) ;
2007-05-14 19:14:42 +02:00
ok ( res = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %d \n " , res ) ;
2007-05-14 19:14:51 +02:00
RegCloseKey ( hkey ) ;
2009-02-26 06:14:28 +01:00
res = RegDeleteKeyA ( HKEY_LOCAL_MACHINE , " SOFTWARE \\ Microsoft \\ Windows \\ CurrentVersion \\ Installer \\ Products \\ 05FA3C1F65B896A40AC00077F34EF203 " ) ;
ok ( res = = ERROR_FILE_NOT_FOUND , " Expected ERROR_FILE_NOT_FOUND, got %d \n " , res ) ;
}
else
{
/* win9x defaults to a per-machine install. */
RegDeleteKeyA ( HKEY_LOCAL_MACHINE , " SOFTWARE \\ Microsoft \\ Windows \\ CurrentVersion \\ Installer \\ Products \\ 05FA3C1F65B896A40AC00077F34EF203 " ) ;
2007-05-14 19:14:42 +02:00
}
/* Remove registry keys written by PublishProduct standard action */
res = RegOpenKey ( HKEY_CURRENT_USER , " SOFTWARE \\ Microsoft \\ Installer " , & hkey ) ;
ok ( res = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %d \n " , res ) ;
2007-05-14 19:14:51 +02:00
res = delete_registry_key ( hkey , " Products \\ 05FA3C1F65B896A40AC00077F34EF203 " ) ;
ok ( res = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %d \n " , res ) ;
2007-05-14 19:14:42 +02:00
2007-05-14 19:14:51 +02:00
res = RegDeleteKeyA ( hkey , " UpgradeCodes \\ D8E760ECA1E276347B43E42BDBDA5656 " ) ;
2008-06-24 06:02:54 +02:00
ok ( res = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %d \n " , res ) ;
2007-05-14 19:14:42 +02:00
RegCloseKey ( hkey ) ;
/* Delete installation files we installed */
delete_test_files ( ) ;
}
2007-04-29 03:12:09 +02:00
static void test_Installer ( void )
{
static WCHAR szBackslash [ ] = { ' \\ ' , 0 } ;
2007-05-11 21:07:53 +02:00
static WCHAR szCreateRecordException [ ] = { ' C ' , ' r ' , ' e ' , ' a ' , ' t ' , ' e ' , ' R ' , ' e ' , ' c ' , ' o ' , ' r ' , ' d ' , ' , ' , ' C ' , ' o ' , ' u ' , ' n ' , ' t ' , 0 } ;
2007-05-11 21:08:27 +02:00
static WCHAR szIntegerDataException [ ] = { ' I ' , ' n ' , ' t ' , ' e ' , ' g ' , ' e ' , ' r ' , ' D ' , ' a ' , ' t ' , ' a ' , ' , ' , ' F ' , ' i ' , ' e ' , ' l ' , ' d ' , 0 } ;
2007-04-29 03:12:09 +02:00
WCHAR szPath [ MAX_PATH ] ;
HRESULT hr ;
UINT len ;
2007-06-04 16:26:33 +02:00
IDispatch * pSession = NULL , * pDatabase = NULL , * pRecord = NULL , * pStringList = NULL ;
2007-05-14 19:15:02 +02:00
int iValue , iCount ;
2007-04-29 03:12:09 +02:00
if ( ! pInstaller ) return ;
2007-05-04 02:02:31 +02:00
/* Installer::CreateRecord */
2007-05-11 21:07:58 +02:00
/* Test for error */
hr = Installer_CreateRecord ( - 1 , & pRecord ) ;
ok ( hr = = DISP_E_EXCEPTION , " Installer_CreateRecord failed, hresult 0x%08x \n " , hr ) ;
ok_exception ( hr , szCreateRecordException ) ;
/* Test for success */
hr = Installer_CreateRecord ( 1 , & pRecord ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Installer_CreateRecord failed, hresult 0x%08x \n " , hr ) ;
2007-05-11 21:07:58 +02:00
ok ( pRecord ! = NULL , " Installer_CreateRecord should not have returned NULL record \n " ) ;
2007-05-04 02:02:31 +02:00
if ( pRecord )
{
/* Record::FieldCountGet */
2007-05-11 21:08:27 +02:00
hr = Record_FieldCountGet ( pRecord , & iValue ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Record_FiledCountGet failed, hresult 0x%08x \n " , hr ) ;
2007-05-11 21:08:27 +02:00
ok ( iValue = = 1 , " Record_FieldCountGet result was %d but expected 1 \n " , iValue ) ;
2007-05-14 19:14:00 +02:00
/* Record::IntegerDataGet */
hr = Record_IntegerDataGet ( pRecord , 1 , & iValue ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Record_IntegerDataGet failed, hresult 0x%08x \n " , hr ) ;
2007-05-14 19:14:00 +02:00
ok ( iValue = = MSI_NULL_INTEGER , " Record_IntegerDataGet result was %d but expected %d \n " , iValue , MSI_NULL_INTEGER ) ;
/* Record::IntegerDataGet, bad index */
hr = Record_IntegerDataGet ( pRecord , 10 , & iValue ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Record_IntegerDataGet failed, hresult 0x%08x \n " , hr ) ;
2007-05-14 19:14:00 +02:00
ok ( iValue = = MSI_NULL_INTEGER , " Record_IntegerDataGet result was %d but expected %d \n " , iValue , MSI_NULL_INTEGER ) ;
/* Record::IntegerDataPut */
hr = Record_IntegerDataPut ( pRecord , 1 , 100 ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Record_IntegerDataPut failed, hresult 0x%08x \n " , hr ) ;
2007-05-14 19:14:00 +02:00
/* Record::IntegerDataPut, bad index */
hr = Record_IntegerDataPut ( pRecord , 10 , 100 ) ;
ok ( hr = = DISP_E_EXCEPTION , " Record_IntegerDataPut failed, hresult 0x%08x \n " , hr ) ;
ok_exception ( hr , szIntegerDataException ) ;
/* Record::IntegerDataGet */
hr = Record_IntegerDataGet ( pRecord , 1 , & iValue ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Record_IntegerDataGet failed, hresult 0x%08x \n " , hr ) ;
2007-05-14 19:14:00 +02:00
ok ( iValue = = 100 , " Record_IntegerDataGet result was %d but expected 100 \n " , iValue ) ;
2007-05-04 02:02:31 +02:00
IDispatch_Release ( pRecord ) ;
}
/* Prepare package */
2007-06-02 03:06:46 +02:00
create_database ( msifile , tables , sizeof ( tables ) / sizeof ( msi_table ) ,
summary_info , sizeof ( summary_info ) / sizeof ( msi_summary_info ) ) ;
2007-04-29 03:12:09 +02:00
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 ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Installer_OpenPackage failed, hresult 0x%08x \n " , hr ) ;
if ( hr = = S_OK )
2007-04-29 03:12:09 +02:00
{
test_Session ( pSession ) ;
IDispatch_Release ( pSession ) ;
}
2007-06-04 16:26:33 +02:00
/* Installer::OpenDatabase */
2009-01-03 20:13:45 +01:00
hr = Installer_OpenDatabase ( szPath , ( INT_PTR ) MSIDBOPEN_TRANSACT , & pDatabase ) ;
2007-06-04 16:26:33 +02:00
ok ( hr = = S_OK , " Installer_OpenDatabase failed, hresult 0x%08x \n " , hr ) ;
if ( hr = = S_OK )
{
test_Database ( pDatabase , FALSE ) ;
IDispatch_Release ( pDatabase ) ;
}
2007-05-08 00:51:36 +02:00
/* Installer::RegistryValue */
test_Installer_RegistryValue ( ) ;
2007-05-08 00:50:05 +02:00
/* Installer::ProductState for our product code, which should not be installed */
2007-05-11 21:08:27 +02:00
hr = Installer_ProductState ( szProductCode , & iValue ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Installer_ProductState failed, hresult 0x%08x \n " , hr ) ;
2007-05-16 02:29:12 +02:00
ok ( iValue = = INSTALLSTATE_UNKNOWN , " Installer_ProductState returned %d, expected %d \n " , iValue , INSTALLSTATE_UNKNOWN ) ;
2007-05-08 00:50:05 +02:00
2007-05-16 02:30:09 +02:00
/* Installer::ProductInfo for our product code, which should not be installed */
2007-05-17 07:42:46 +02:00
/* Package name */
memset ( szPath , 0 , sizeof ( szPath ) ) ;
2007-07-13 05:04:19 +02:00
hr = Installer_ProductInfo ( szProductCode , WINE_INSTALLPROPERTY_PACKAGENAMEW , szPath ) ;
2007-05-17 07:42:46 +02:00
ok ( hr = = DISP_E_EXCEPTION , " Installer_ProductInfo failed, hresult 0x%08x \n " , hr ) ;
ok_exception ( hr , szProductInfoException ) ;
/* NULL attribute and NULL product code */
memset ( szPath , 0 , sizeof ( szPath ) ) ;
hr = Installer_ProductInfo ( NULL , NULL , szPath ) ;
ok ( hr = = DISP_E_EXCEPTION , " Installer_ProductInfo failed, hresult 0x%08x \n " , hr ) ;
ok_exception ( hr , szProductInfoException ) ;
2007-05-16 02:30:09 +02:00
2007-05-20 21:31:52 +02:00
/* Installer::Products */
test_Installer_Products ( FALSE ) ;
2007-05-14 19:15:02 +02:00
/* Installer::RelatedProducts for our upgrade code, should not find anything */
2007-05-14 19:15:13 +02:00
hr = Installer_RelatedProducts ( szUpgradeCode , & pStringList ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " Installer_RelatedProducts failed, hresult 0x%08x \n " , hr ) ;
if ( hr = = S_OK )
2007-05-14 19:15:13 +02:00
{
/* StringList::Count */
hr = StringList_Count ( pStringList , & iCount ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " StringList_Count failed, hresult 0x%08x \n " , hr ) ;
2007-05-14 19:15:13 +02:00
ok ( ! iCount , " Expected no related products but found %d \n " , iCount ) ;
2007-05-14 19:15:02 +02:00
2007-05-14 19:15:13 +02:00
IDispatch_Release ( pStringList ) ;
2007-05-14 19:15:02 +02:00
}
2007-05-04 02:02:31 +02:00
/* Installer::Version */
2007-12-02 08:35:33 +01:00
memset ( szPath , 0 , sizeof ( szPath ) ) ;
hr = Installer_VersionGet ( szPath ) ;
ok ( hr = = S_OK , " Installer_VersionGet failed, hresult 0x%08x \n " , hr ) ;
2007-05-14 19:14:42 +02:00
/* Installer::InstallProduct and other tests that depend on our product being installed */
2007-11-05 10:45:32 +01:00
test_Installer_InstallProduct ( ) ;
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 ;
2007-06-02 03:06:46 +02:00
GetSystemTimeAsFileTime ( & systemtime ) ;
2007-04-29 03:12:09 +02:00
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 ;
2007-05-14 19:14:42 +02:00
get_program_files_dir ( PROG_FILES_DIR ) ;
2007-04-29 03:12:09 +02:00
hr = OleInitialize ( NULL ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " OleInitialize returned 0x%08x \n " , hr ) ;
2007-04-29 03:12:09 +02:00
hr = CLSIDFromProgID ( szProgId , & clsid ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " CLSIDFromProgID returned 0x%08x \n " , hr ) ;
2007-04-29 03:12:09 +02:00
hr = CoCreateInstance ( & clsid , NULL , CLSCTX_INPROC_SERVER , & IID_IUnknown , ( void * * ) & pUnk ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " CoCreateInstance returned 0x%08x \n " , hr ) ;
2007-04-29 03:12:09 +02:00
if ( pUnk )
{
hr = IUnknown_QueryInterface ( pUnk , & IID_IDispatch , ( void * * ) & pInstaller ) ;
2007-05-17 18:36:09 +02:00
ok ( hr = = S_OK , " IUnknown::QueryInterface returned 0x%08x \n " , hr ) ;
2007-04-29 03:12:09 +02:00
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
2007-05-17 18:36:09 +02:00
IDispatch_Release ( pInstaller ) ;
IUnknown_Release ( pUnk ) ;
2007-04-29 03:12:09 +02:00
}
OleUninitialize ( ) ;
SetCurrentDirectoryA ( prev_path ) ;
}