2008-02-10 13:22:36 +00:00
/*
* Copyright ( C ) 2007 Mike McCormack for CodeWeavers
* Copyright ( C ) 2007 Misha Koshelev
*
* A test program for Microsoft Installer OLE automation functionality .
*
* 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-12-28 10:25:32 +00:00
# include <initguid.h>
2008-02-10 13:22:36 +00:00
# include <windows.h>
# include <msiquery.h>
# include <msidefs.h>
# include <msi.h>
# include <fci.h>
# include "wine/test.h"
2012-01-21 17:21:57 +00:00
static BOOL is_wow64 ;
2014-04-23 14:49:34 +00:00
static BOOL ( WINAPI * pCheckTokenMembership ) ( HANDLE , PSID , PBOOL ) ;
static BOOL ( WINAPI * pOpenProcessToken ) ( HANDLE , DWORD , PHANDLE ) ;
2012-01-21 17:21:57 +00:00
static LONG ( WINAPI * pRegDeleteKeyExA ) ( HKEY , LPCSTR , REGSAM , DWORD ) ;
static BOOL ( WINAPI * pIsWow64Process ) ( HANDLE , PBOOL ) ;
2008-12-28 10:25:32 +00:00
DEFINE_GUID ( GUID_NULL , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ) ;
2009-12-22 09:14:17 +00:00
static const char * msifile = " winetest-automation.msi " ;
static const WCHAR szMsifile [ ] = { ' w ' , ' i ' , ' n ' , ' e ' , ' t ' , ' e ' , ' s ' , ' t ' , ' - ' , ' a ' , ' u ' , ' t ' , ' o ' , ' m ' , ' a ' , ' t ' , ' i ' , ' o ' , ' n ' , ' . ' , ' m ' , ' s ' , ' i ' , 0 } ;
2008-02-10 13:22:36 +00:00
static const WCHAR szMSITEST [ ] = { ' M ' , ' S ' , ' I ' , ' T ' , ' E ' , ' S ' , ' T ' , 0 } ;
2012-01-21 17:21:57 +00:00
static const WCHAR szProductCode [ ] = { ' { ' , ' 8 ' , ' 3 ' , ' 7 ' , ' 4 ' , ' 5 ' , ' 0 ' , ' f ' , ' a ' , ' - ' , ' a ' , ' 3 ' , ' 9 ' , ' b ' , ' - ' , ' 4 ' , ' b ' , ' c ' , ' 8 ' , ' - ' , ' b ' , ' 3 ' , ' 2 ' , ' 1 ' , ' - ' , ' 0 ' , ' 8 ' , ' b ' , ' 3 ' , ' 9 ' , ' 3 ' , ' f ' , ' 7 ' , ' 8 ' , ' 4 ' , ' b ' , ' 3 ' , ' } ' , 0 } ;
2008-02-10 13:22:36 +00: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 } ;
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 } ;
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 } ;
2012-01-21 17:21:57 +00:00
static const WCHAR WINE_INSTALLPROPERTY_LOCALPACKAGEW [ ] = { ' L ' , ' o ' , ' c ' , ' a ' , ' l ' , ' P ' , ' a ' , ' c ' , ' k ' , ' a ' , ' g ' , ' e ' , 0 } ;
2008-02-10 13:22:36 +00:00
static FILETIME systemtime ;
static CHAR CURR_DIR [ MAX_PATH ] ;
static EXCEPINFO excepinfo ;
/*
* OLE automation data
* */
static const WCHAR szProgId [ ] = { ' W ' , ' i ' , ' n ' , ' d ' , ' o ' , ' w ' , ' s ' , ' I ' , ' n ' , ' s ' , ' t ' , ' a ' , ' l ' , ' l ' , ' e ' , ' r ' , ' . ' , ' I ' , ' n ' , ' s ' , ' t ' , ' a ' , ' l ' , ' l ' , ' e ' , ' r ' , 0 } ;
static IDispatch * pInstaller ;
/* msi database data */
static const CHAR component_dat [ ] = " Component \t ComponentId \t Directory_ \t Attributes \t Condition \t KeyPath \n "
" s72 \t S38 \t s72 \t i2 \t S255 \t S72 \n "
" Component \t Component \n "
" Five \t {8CC92E9D-14B2-4CA4-B2AA-B11D02078087} \t NEWDIR \t 2 \t \t five.txt \n "
" Four \t {FD37B4EA-7209-45C0-8917-535F35A2F080} \t CABOUTDIR \t 2 \t \t four.txt \n "
" One \t {783B242E-E185-4A56-AF86-C09815EC053C} \t MSITESTDIR \t 2 \t \t one.txt \n "
" Three \t {010B6ADD-B27D-4EDD-9B3D-34C4F7D61684} \t CHANGEDDIR \t 2 \t \t three.txt \n "
" Two \t {BF03D1A6-20DA-4A65-82F3-6CAC995915CE} \t FIRSTDIR \t 2 \t \t two.txt \n "
" dangler \t {6091DF25-EF96-45F1-B8E9-A9B1420C7A3C} \t TARGETDIR \t 4 \t \t regdata \n "
2008-12-28 10:25:32 +00:00
" component \t \t MSITESTDIR \t 0 \t 1 \t file \n " ;
2008-02-10 13:22:36 +00: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 "
2012-01-21 17:21:57 +00:00
" TARGETDIR \t \t SourceDir \n " ;
2008-02-10 13:22:36 +00:00
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-12-28 10:25:32 +00:00
" feature \t \t \t \t 2 \t 1 \t TARGETDIR \t 0 \n " ;
2008-02-10 13:22:36 +00: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-12-28 10:25:32 +00:00
" feature \t component \n " ;
2008-02-10 13:22:36 +00: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 "
" 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 "
" 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-12-28 10:25:32 +00:00
" file \t component \t filename \t 100 \t \t \t 8192 \t 1 \n " ;
2008-02-10 13:22:36 +00: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 "
" RegisterProduct \t \t 6100 \n "
" PublishProduct \t \t 6400 \n "
" InstallFinalize \t \t 6600 \n "
" InstallInitialize \t \t 1500 \n "
" InstallValidate \t \t 1400 \n "
" LaunchConditions \t \t 100 \n "
2012-01-21 17:21:57 +00:00
" WriteRegistryValues \t SourceDir And SOURCEDIR \t 5000 \n " ;
2008-02-10 13:22:36 +00:00
static const CHAR media_dat [ ] = " DiskId \t LastSequence \t DiskPrompt \t Cabinet \t VolumeLabel \t Source \n "
" i2 \t i4 \t L64 \t S255 \t S32 \t S72 \n "
" Media \t DiskId \n "
" 1 \t 5 \t \t \t DISK1 \t \n " ;
static const CHAR property_dat [ ] = " Property \t Value \n "
" s72 \t l0 \n "
" Property \t Property \n "
" DefaultUIFont \t DlgFont8 \n "
" HASUIRUN \t 0 \n "
" INSTALLLEVEL \t 3 \n "
" InstallMode \t Typical \n "
" Manufacturer \t Wine \n "
" PIDTemplate \t 12345<###-%%%%%%%>@@@@@ \n "
2012-01-21 17:21:57 +00:00
" ProductCode \t {837450fa-a39b-4bc8-b321-08b393f784b3} \n "
2008-02-10 13:22:36 +00:00
" 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 "
2012-01-21 17:21:57 +00:00
" UpgradeCode \t {CE067E8D-2E1A-4367-B734-4EB2BDAD6565} \n "
" MSIFASTINSTALL \t 1 \n " ;
2008-02-10 13:22:36 +00:00
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 "
2012-01-21 17:21:57 +00:00
" Apples \t 1 \t SOFTWARE \\ Wine \\ msitest \t Name \t imaname \t One \n "
" Oranges \t 1 \t SOFTWARE \\ Wine \\ msitest \t number \t #314 \t Two \n "
" regdata \t 1 \t SOFTWARE \\ Wine \\ msitest \t blah \t bad \t dangler \n "
" OrderTest \t 1 \t SOFTWARE \\ Wine \\ msitest \t OrderTestName \t OrderTestValue \t component \n " ;
2008-02-10 13:22:36 +00:00
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-12-28 10:25:32 +00:00
ADD_TABLE ( registry )
2008-02-10 13:22:36 +00: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 " ) ,
2012-08-13 16:18:14 +00:00
ADD_INFO_LPSTR ( PID_REVNUMBER , " {004757CA-5092-49C2-AD20-28E1CE0DF5F2} " ) ,
2008-02-10 13:22:36 +00:00
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 )
} ;
2012-01-21 17:21:57 +00:00
static void init_functionpointers ( void )
{
HMODULE hadvapi32 = GetModuleHandleA ( " advapi32.dll " ) ;
HMODULE hkernel32 = GetModuleHandleA ( " kernel32.dll " ) ;
# define GET_PROC(dll, func) \
p # # func = ( void * ) GetProcAddress ( dll , # func ) ; \
if ( ! p # # func ) \
trace ( " GetProcAddress(%s) failed \n " , # func ) ;
2014-04-23 14:49:34 +00:00
GET_PROC ( hadvapi32 , CheckTokenMembership ) ;
GET_PROC ( hadvapi32 , OpenProcessToken ) ;
2012-01-21 17:21:57 +00:00
GET_PROC ( hadvapi32 , RegDeleteKeyExA )
GET_PROC ( hkernel32 , IsWow64Process )
# undef GET_PROC
}
2014-04-23 14:49:34 +00:00
static BOOL is_process_limited ( void )
{
SID_IDENTIFIER_AUTHORITY NtAuthority = { SECURITY_NT_AUTHORITY } ;
2014-09-23 18:33:25 +00:00
PSID Group = NULL ;
2014-04-23 14:49:34 +00:00
BOOL IsInGroup ;
HANDLE token ;
if ( ! pCheckTokenMembership | | ! pOpenProcessToken ) return FALSE ;
if ( ! AllocateAndInitializeSid ( & NtAuthority , 2 , SECURITY_BUILTIN_DOMAIN_RID ,
2014-09-23 18:33:25 +00:00
DOMAIN_ALIAS_RID_ADMINS , 0 , 0 , 0 , 0 , 0 , 0 , & Group ) | |
2014-04-23 14:49:34 +00:00
! pCheckTokenMembership ( NULL , Group , & IsInGroup ) )
{
trace ( " Could not check if the current user is an administrator \n " ) ;
2014-09-23 18:33:25 +00:00
FreeSid ( Group ) ;
2014-04-23 14:49:34 +00:00
return FALSE ;
}
2014-09-23 18:33:25 +00:00
FreeSid ( Group ) ;
2014-04-23 14:49:34 +00:00
if ( ! IsInGroup )
{
/* Only administrators have enough privileges for these tests */
return TRUE ;
}
if ( pOpenProcessToken ( GetCurrentProcess ( ) , TOKEN_QUERY , & token ) )
{
BOOL ret ;
TOKEN_ELEVATION_TYPE type = TokenElevationTypeDefault ;
DWORD size ;
ret = GetTokenInformation ( token , TokenElevationType , & type , sizeof ( type ) , & size ) ;
CloseHandle ( token ) ;
return ( ret & & type = = TokenElevationTypeLimited ) ;
}
return FALSE ;
}
2012-01-21 17:21:57 +00:00
static LONG delete_key_portable ( HKEY key , LPCSTR subkey , REGSAM access )
{
if ( pRegDeleteKeyExA )
return pRegDeleteKeyExA ( key , subkey , access , 0 ) ;
return RegDeleteKeyA ( key , subkey ) ;
}
2008-02-10 13:22:36 +00:00
/*
* Database Helpers
*/
static void write_file ( const CHAR * filename , const char * data , int data_size )
{
DWORD size ;
2014-04-23 14:49:34 +00:00
HANDLE hf = CreateFileA ( filename , GENERIC_WRITE , 0 , NULL ,
CREATE_ALWAYS , FILE_ATTRIBUTE_NORMAL , NULL ) ;
2008-02-10 13:22:36 +00:00
WriteFile ( hf , data , data_size , & size , NULL ) ;
CloseHandle ( hf ) ;
}
static void write_msi_summary_info ( MSIHANDLE db , const msi_summary_info * info , int num_info )
{
MSIHANDLE summary ;
UINT r ;
int j ;
r = MsiGetSummaryInformationA ( db , NULL , num_info , & summary ) ;
ok ( r = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %u \n " , r ) ;
/* import summary information into the stream */
for ( j = 0 ; j < num_info ; j + + )
{
const msi_summary_info * entry = & info [ j ] ;
r = MsiSummaryInfoSetPropertyA ( summary , entry - > property , entry - > datatype ,
entry - > iValue , entry - > pftValue , entry - > szValue ) ;
ok ( r = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %u \n " , r ) ;
}
/* write the summary changes back to the stream */
r = MsiSummaryInfoPersist ( summary ) ;
ok ( r = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %u \n " , r ) ;
MsiCloseHandle ( summary ) ;
}
static void create_database ( const CHAR * name , const msi_table * tables , int num_tables ,
const msi_summary_info * info , int num_info )
{
MSIHANDLE db ;
UINT r ;
2014-04-23 14:49:34 +00:00
WCHAR * nameW ;
int j , len ;
len = MultiByteToWideChar ( CP_ACP , 0 , name , - 1 , NULL , 0 ) ;
if ( ! ( nameW = HeapAlloc ( GetProcessHeap ( ) , 0 , len * sizeof ( WCHAR ) ) ) ) return ;
MultiByteToWideChar ( CP_ACP , 0 , name , - 1 , nameW , len ) ;
2008-02-10 13:22:36 +00:00
2014-04-23 14:49:34 +00:00
r = MsiOpenDatabaseW ( nameW , MSIDBOPEN_CREATE , & db ) ;
2008-02-10 13:22:36 +00:00
ok ( r = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %u \n " , r ) ;
/* import the tables into the database */
for ( j = 0 ; j < num_tables ; j + + )
{
const msi_table * table = & tables [ j ] ;
write_file ( table - > filename , table - > data , ( table - > size - 1 ) * sizeof ( char ) ) ;
r = MsiDatabaseImportA ( db , CURR_DIR , table - > filename ) ;
ok ( r = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %u \n " , r ) ;
DeleteFileA ( table - > filename ) ;
}
write_msi_summary_info ( db , info , num_info ) ;
r = MsiDatabaseCommit ( db ) ;
ok ( r = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %u \n " , r ) ;
MsiCloseHandle ( db ) ;
2014-04-23 14:49:34 +00:00
HeapFree ( GetProcessHeap ( ) , 0 , nameW ) ;
2008-02-10 13:22:36 +00:00
}
2009-12-22 09:14:17 +00:00
static BOOL create_package ( LPWSTR path )
{
2012-01-21 17:21:57 +00:00
static const WCHAR slashW [ ] = { ' \\ ' , 0 } ;
2009-12-22 09:14:17 +00:00
DWORD len ;
/* Prepare package */
create_database ( msifile , tables ,
sizeof ( tables ) / sizeof ( msi_table ) , summary_info ,
sizeof ( summary_info ) / sizeof ( msi_summary_info ) ) ;
len = MultiByteToWideChar ( CP_ACP , MB_PRECOMPOSED ,
CURR_DIR , - 1 , path , MAX_PATH ) ;
ok ( len , " MultiByteToWideChar returned error %d \n " , GetLastError ( ) ) ;
if ( ! len )
return FALSE ;
2012-01-21 17:21:57 +00:00
lstrcatW ( path , slashW ) ;
lstrcatW ( path , szMsifile ) ;
2009-12-22 09:14:17 +00:00
return TRUE ;
}
2008-02-10 13:22:36 +00: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 ;
2014-04-23 14:49:34 +00:00
if ( RegOpenKeyA ( HKEY_LOCAL_MACHINE , " Software \\ Microsoft \\ Windows \\ CurrentVersion " , & hkey ) )
2008-02-10 13:22:36 +00:00
return FALSE ;
size = MAX_PATH ;
2014-04-23 14:49:34 +00:00
if ( RegQueryValueExA ( hkey , " ProgramFilesDir (x86) " , 0 , & type , ( LPBYTE ) buf , & size ) & &
RegQueryValueExA ( hkey , " ProgramFilesDir " , 0 , & type , ( LPBYTE ) buf , & size ) )
2008-02-10 13:22:36 +00:00
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 ) ;
2014-04-23 14:49:34 +00:00
left = size - lstrlenA ( name ) - 1 ;
2008-02-10 13:22:36 +00:00
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 " ) ;
}
/*
* Automation helpers and tests
*/
/* ok-like statement which takes two unicode strings or one unicode and one ANSI string as arguments */
static CHAR string1 [ MAX_PATH ] , string2 [ MAX_PATH ] ;
# define ok_w2(format, szString1, szString2) \
\
2009-08-08 12:48:20 +00:00
do { \
WideCharToMultiByte ( CP_ACP , 0 , szString1 , - 1 , string1 , MAX_PATH , NULL , NULL ) ; \
WideCharToMultiByte ( CP_ACP , 0 , szString2 , - 1 , string2 , MAX_PATH , NULL , NULL ) ; \
if ( lstrcmpA ( string1 , string2 ) ! = 0 ) \
2008-02-10 13:22:36 +00:00
ok ( 0 , format , string1 , string2 ) ; \
2009-08-08 12:48:20 +00:00
} while ( 0 ) ;
2008-02-10 13:22:36 +00:00
2008-12-28 10:25:32 +00: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 ) ; \
}
2008-02-10 13:22:36 +00: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 ) ; \
/* exception checker */
2014-04-23 14:49:34 +00:00
static const WCHAR szSource [ ] = { ' M ' , ' s ' , ' i ' , ' ' , ' A ' , ' P ' , ' I ' , ' ' , ' E ' , ' r ' , ' r ' , ' o ' , ' r ' , 0 } ;
2008-02-10 13:22:36 +00:00
# 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 " ) ; \
if ( excepinfo . bstrDescription ) \
ok_w2 ( " Exception description was \" %s \" but expected to be \" %s \" \n " , excepinfo . bstrDescription , szDescription ) ; \
\
SysFreeString ( excepinfo . bstrSource ) ; \
SysFreeString ( excepinfo . bstrDescription ) ; \
SysFreeString ( excepinfo . bstrHelpFile ) ; \
}
static DISPID get_dispid ( IDispatch * disp , const char * name )
{
LPOLESTR str ;
UINT len ;
DISPID id = - 1 ;
HRESULT r ;
len = MultiByteToWideChar ( CP_ACP , 0 , name , - 1 , NULL , 0 ) ;
str = HeapAlloc ( GetProcessHeap ( ) , 0 , len * sizeof ( WCHAR ) ) ;
if ( str )
{
2012-01-21 17:21:57 +00:00
MultiByteToWideChar ( CP_ACP , 0 , name , - 1 , str , len ) ;
2008-02-10 13:22:36 +00:00
r = IDispatch_GetIDsOfNames ( disp , & IID_NULL , & str , 1 , 0 , & id ) ;
HeapFree ( GetProcessHeap ( ) , 0 , str ) ;
if ( r ! = S_OK )
return - 1 ;
}
return id ;
}
2012-05-14 21:41:45 +00:00
typedef struct {
DISPID did ;
const char * name ;
BOOL todo ;
} get_did_t ;
static const get_did_t get_did_data [ ] = {
{ 1 , " CreateRecord " } ,
{ 2 , " OpenPackage " } ,
{ 3 , " OpenProduct " } ,
{ 4 , " OpenDatabase " } ,
{ 5 , " SummaryInformation " } ,
{ 6 , " UILevel " } ,
{ 7 , " EnableLog " } ,
{ 8 , " InstallProduct " } ,
{ 9 , " Version " } ,
{ 10 , " LastErrorRecord " } ,
{ 11 , " RegistryValue " } ,
{ 12 , " Environment " } ,
{ 13 , " FileAttributes " } ,
{ 15 , " FileSize " } ,
{ 16 , " FileVersion " } ,
{ 17 , " ProductState " } ,
{ 18 , " ProductInfo " } ,
{ 19 , " ConfigureProduct " , TRUE } ,
{ 20 , " ReinstallProduct " , TRUE } ,
{ 21 , " CollectUserInfo " , TRUE } ,
{ 22 , " ApplyPatch " , TRUE } ,
{ 23 , " FeatureParent " , TRUE } ,
{ 24 , " FeatureState " , TRUE } ,
{ 25 , " UseFeature " , TRUE } ,
{ 26 , " FeatureUsageCount " , TRUE } ,
{ 27 , " FeatureUsageDate " , TRUE } ,
{ 28 , " ConfigureFeature " , TRUE } ,
{ 29 , " ReinstallFeature " , TRUE } ,
{ 30 , " ProvideComponent " , TRUE } ,
{ 31 , " ComponentPath " , TRUE } ,
{ 32 , " ProvideQualifiedComponent " , TRUE } ,
{ 33 , " QualifierDescription " , TRUE } ,
{ 34 , " ComponentQualifiers " , TRUE } ,
{ 35 , " Products " } ,
{ 36 , " Features " , TRUE } ,
{ 37 , " Components " , TRUE } ,
{ 38 , " ComponentClients " , TRUE } ,
{ 39 , " Patches " , TRUE } ,
{ 40 , " RelatedProducts " } ,
{ 41 , " PatchInfo " , TRUE } ,
{ 42 , " PatchTransforms " , TRUE } ,
{ 43 , " AddSource " , TRUE } ,
{ 44 , " ClearSourceList " , TRUE } ,
{ 45 , " ForceSourceListResolution " , TRUE } ,
{ 46 , " ShortcutTarget " , TRUE } ,
{ 47 , " FileHash " , TRUE } ,
{ 48 , " FileSignatureInfo " , TRUE } ,
{ 0 }
} ;
2008-02-10 13:22:36 +00:00
static void test_dispid ( void )
{
2012-05-14 21:41:45 +00:00
const get_did_t * ptr = get_did_data ;
2008-04-04 16:43:16 +00:00
DISPID dispid ;
2008-02-10 13:22:36 +00:00
2012-05-14 21:41:45 +00:00
while ( ptr - > name )
2012-02-06 20:43:38 +00:00
{
2012-05-14 21:41:45 +00:00
dispid = get_dispid ( pInstaller , ptr - > name ) ;
if ( ptr - > todo )
todo_wine
ok ( dispid = = ptr - > did , " %s: expected %d, got %d \n " , ptr - > name , ptr - > did , dispid ) ;
else
ok ( dispid = = ptr - > did , " %s: expected %d, got %d \n " , ptr - > name , ptr - > did , dispid ) ;
ptr + + ;
2008-02-10 13:22:36 +00:00
}
2012-05-14 21:41:45 +00:00
2008-07-09 11:34:20 +00: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-04-04 16:43:16 +00:00
dispid = get_dispid ( pInstaller , " ProductElevated " ) ;
2008-07-09 11:34:20 +00:00
ok ( dispid = = 59 | | dispid = = - 1 , " Expected 59 or -1, got %d \n " , dispid ) ;
2008-04-04 16:43:16 +00:00
dispid = get_dispid ( pInstaller , " ProvideAssembly " ) ;
2008-07-09 11:34:20 +00: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-04-04 16:43:16 +00:00
dispid = get_dispid ( pInstaller , " AdvertiseProduct " ) ;
2008-07-09 11:34:20 +00: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-04-04 16:43:16 +00:00
dispid = get_dispid ( pInstaller , " PatchFiles " ) ;
2008-07-09 11:34:20 +00:00
ok ( dispid = = 65 | | dispid = = - 1 , " Expected 65 or -1, got %d \n " , dispid ) ;
2008-02-10 13:22:36 +00:00
}
/* Test basic IDispatch functions */
static void test_dispatch ( void )
{
static WCHAR szOpenPackage [ ] = { ' O ' , ' p ' , ' e ' , ' n ' , ' P ' , ' a ' , ' c ' , ' k ' , ' a ' , ' g ' , ' e ' , 0 } ;
2014-04-23 14:49:34 +00:00
static const 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 } ;
2008-02-10 13:22:36 +00:00
static WCHAR szProductState [ ] = { ' P ' , ' r ' , ' o ' , ' d ' , ' u ' , ' c ' , ' t ' , ' S ' , ' t ' , ' a ' , ' t ' , ' e ' , 0 } ;
HRESULT hr ;
DISPID dispid ;
OLECHAR * name ;
VARIANT varresult ;
2009-12-22 09:14:17 +00:00
VARIANTARG vararg [ 3 ] ;
WCHAR path [ MAX_PATH ] ;
2008-02-10 13:22:36 +00:00
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-18 09:03:44 +00:00
name = szOpenPackage ;
2008-02-10 13:22:36 +00:00
hr = IDispatch_GetIDsOfNames ( pInstaller , & IID_NULL , & name , 1 , LOCALE_USER_DEFAULT , & dispid ) ;
ok ( hr = = S_OK , " IDispatch::GetIDsOfNames returned 0x%08x \n " , hr ) ;
/* Test invoking this function (without parameters passed) */
if ( 0 ) /* All of these crash MSI on Windows XP */
{
2012-01-21 17:21:57 +00:00
IDispatch_Invoke ( pInstaller , dispid , & IID_NULL , LOCALE_NEUTRAL , DISPATCH_METHOD , NULL , NULL , NULL , NULL ) ;
IDispatch_Invoke ( pInstaller , dispid , & IID_NULL , LOCALE_NEUTRAL , DISPATCH_METHOD , NULL , NULL , & excepinfo , NULL ) ;
2008-02-10 13:22:36 +00:00
VariantInit ( & varresult ) ;
2012-01-21 17:21:57 +00:00
IDispatch_Invoke ( pInstaller , dispid , & IID_NULL , LOCALE_NEUTRAL , DISPATCH_METHOD , NULL , & varresult , & excepinfo , NULL ) ;
2008-02-10 13:22:36 +00:00
}
/* Try with NULL params */
hr = IDispatch_Invoke ( pInstaller , dispid , & IID_NULL , LOCALE_NEUTRAL , DISPATCH_METHOD , & dispparams , & varresult , & excepinfo , NULL ) ;
2009-12-22 09:14:17 +00:00
ok ( hr = = DISP_E_TYPEMISMATCH , " IDispatch::Invoke returned 0x%08x \n " , hr ) ;
2008-02-10 13:22:36 +00: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 ) ;
2009-12-22 09:14:17 +00:00
ok ( hr = = DISP_E_TYPEMISMATCH , " IDispatch::Invoke returned 0x%08x \n " , hr ) ;
2008-02-10 13:22:36 +00:00
2009-12-22 09:14:17 +00:00
/* Try two empty parameters */
dispparams . cArgs = 2 ;
VariantInit ( & vararg [ 0 ] ) ;
VariantInit ( & vararg [ 1 ] ) ;
hr = IDispatch_Invoke ( pInstaller , dispid , & IID_NULL , LOCALE_NEUTRAL , DISPATCH_METHOD , & dispparams , & varresult , & excepinfo , NULL ) ;
ok ( hr = = DISP_E_TYPEMISMATCH , " IDispatch::Invoke returned 0x%08x \n " , hr ) ;
/* Try one parameter, the required BSTR. Second parameter is optional.
* NOTE : The specified package does not exist , which is why the call fails .
*/
dispparams . cArgs = 1 ;
2008-02-10 13:22:36 +00:00
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 ) ;
2009-12-22 09:14:17 +00:00
ok ( hr = = DISP_E_EXCEPTION , " IDispatch::Invoke returned 0x%08x \n " , hr ) ;
ok_exception ( hr , szOpenPackageException ) ;
2008-02-10 13:22:36 +00:00
VariantClear ( & vararg [ 0 ] ) ;
2009-12-22 09:14:17 +00:00
/* Provide the required BSTR and an empty second parameter.
* NOTE : The specified package does not exist , which is why the call fails .
*/
dispparams . cArgs = 2 ;
VariantInit ( & vararg [ 1 ] ) ;
V_VT ( & vararg [ 1 ] ) = VT_BSTR ;
V_BSTR ( & vararg [ 1 ] ) = SysAllocString ( szMsifile ) ;
VariantInit ( & vararg [ 0 ] ) ;
hr = IDispatch_Invoke ( pInstaller , dispid , & IID_NULL , LOCALE_NEUTRAL , DISPATCH_METHOD , & dispparams , & varresult , & excepinfo , NULL ) ;
ok ( hr = = DISP_E_EXCEPTION , " IDispatch::Invoke returned 0x%08x \n " , hr ) ;
ok_exception ( hr , szOpenPackageException ) ;
VariantClear ( & vararg [ 1 ] ) ;
/* Provide the required BSTR and two empty parameters.
* NOTE : The specified package does not exist , which is why the call fails .
*/
dispparams . cArgs = 3 ;
VariantInit ( & vararg [ 2 ] ) ;
V_VT ( & vararg [ 2 ] ) = VT_BSTR ;
V_BSTR ( & vararg [ 2 ] ) = SysAllocString ( szMsifile ) ;
VariantInit ( & vararg [ 1 ] ) ;
VariantInit ( & vararg [ 0 ] ) ;
hr = IDispatch_Invoke ( pInstaller , dispid , & IID_NULL , LOCALE_NEUTRAL , DISPATCH_METHOD , & dispparams , & varresult , & excepinfo , NULL ) ;
2008-02-10 13:22:36 +00:00
ok ( hr = = DISP_E_EXCEPTION , " IDispatch::Invoke returned 0x%08x \n " , hr ) ;
ok_exception ( hr , szOpenPackageException ) ;
2009-12-22 09:14:17 +00:00
VariantClear ( & vararg [ 2 ] ) ;
/* Provide the required BSTR and a second parameter with the wrong type. */
dispparams . cArgs = 2 ;
VariantInit ( & vararg [ 1 ] ) ;
V_VT ( & vararg [ 1 ] ) = VT_BSTR ;
V_BSTR ( & vararg [ 1 ] ) = SysAllocString ( szMsifile ) ;
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 ) ;
ok ( hr = = DISP_E_TYPEMISMATCH , " IDispatch::Invoke returned 0x%08x \n " , hr ) ;
VariantClear ( & vararg [ 0 ] ) ;
VariantClear ( & vararg [ 1 ] ) ;
/* Create a proper installer package. */
create_package ( path ) ;
/* Try one parameter, the required BSTR. Second parameter is optional.
* Proper installer package exists . Path to the package is relative .
*/
dispparams . cArgs = 1 ;
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 ) ;
todo_wine ok ( hr = = DISP_E_EXCEPTION , " IDispatch::Invoke returned 0x%08x \n " , hr ) ;
ok_exception ( hr , szOpenPackageException ) ;
VariantClear ( & vararg [ 0 ] ) ;
if ( hr ! = DISP_E_EXCEPTION )
VariantClear ( & varresult ) ;
/* Try one parameter, the required BSTR. Second parameter is optional.
* Proper installer package exists . Path to the package is absolute .
*/
dispparams . cArgs = 1 ;
VariantInit ( & vararg [ 0 ] ) ;
V_VT ( & vararg [ 0 ] ) = VT_BSTR ;
V_BSTR ( & vararg [ 0 ] ) = SysAllocString ( path ) ;
hr = IDispatch_Invoke ( pInstaller , dispid , & IID_NULL , LOCALE_NEUTRAL , DISPATCH_METHOD , & dispparams , & varresult , & excepinfo , NULL ) ;
2012-01-21 17:21:57 +00:00
if ( hr = = DISP_E_EXCEPTION )
{
skip ( " OpenPackage failed, insufficient rights? \n " ) ;
DeleteFileW ( path ) ;
return ;
}
2009-12-22 09:14:17 +00:00
ok ( hr = = S_OK , " IDispatch::Invoke returned 0x%08x \n " , hr ) ;
VariantClear ( & vararg [ 0 ] ) ;
VariantClear ( & varresult ) ;
/* Provide the required BSTR and an empty second parameter. Proper
* installation package exists .
*/
dispparams . cArgs = 2 ;
VariantInit ( & vararg [ 1 ] ) ;
V_VT ( & vararg [ 1 ] ) = VT_BSTR ;
V_BSTR ( & vararg [ 1 ] ) = SysAllocString ( path ) ;
VariantInit ( & vararg [ 0 ] ) ;
hr = IDispatch_Invoke ( pInstaller , dispid , & IID_NULL , LOCALE_NEUTRAL , DISPATCH_METHOD , & dispparams , & varresult , & excepinfo , NULL ) ;
ok ( hr = = S_OK , " IDispatch::Invoke returned 0x%08x \n " , hr ) ;
VariantClear ( & vararg [ 1 ] ) ;
VariantClear ( & varresult ) ;
/* Provide the required BSTR and two empty parameters. Proper
* installation package exists .
*/
dispparams . cArgs = 3 ;
VariantInit ( & vararg [ 2 ] ) ;
V_VT ( & vararg [ 2 ] ) = VT_BSTR ;
V_BSTR ( & vararg [ 2 ] ) = SysAllocString ( path ) ;
VariantInit ( & vararg [ 1 ] ) ;
VariantInit ( & vararg [ 0 ] ) ;
hr = IDispatch_Invoke ( pInstaller , dispid , & IID_NULL , LOCALE_NEUTRAL , DISPATCH_METHOD , & dispparams , & varresult , & excepinfo , NULL ) ;
ok ( hr = = S_OK , " IDispatch::Invoke returned 0x%08x \n " , hr ) ;
VariantClear ( & vararg [ 2 ] ) ;
VariantClear ( & varresult ) ;
/* Provide the required BSTR and a second parameter with the wrong type. */
dispparams . cArgs = 2 ;
VariantInit ( & vararg [ 1 ] ) ;
V_VT ( & vararg [ 1 ] ) = VT_BSTR ;
V_BSTR ( & vararg [ 1 ] ) = SysAllocString ( path ) ;
VariantInit ( & vararg [ 0 ] ) ;
V_VT ( & vararg [ 0 ] ) = VT_BSTR ;
V_BSTR ( & vararg [ 0 ] ) = SysAllocString ( path ) ;
hr = IDispatch_Invoke ( pInstaller , dispid , & IID_NULL , LOCALE_NEUTRAL , DISPATCH_METHOD , & dispparams , & varresult , & excepinfo , NULL ) ;
ok ( hr = = DISP_E_TYPEMISMATCH , " IDispatch::Invoke returned 0x%08x \n " , hr ) ;
VariantClear ( & vararg [ 0 ] ) ;
VariantClear ( & vararg [ 1 ] ) ;
/* Provide the required BSTR and a second parameter that can be coerced to
* VT_I4 .
*/
dispparams . cArgs = 2 ;
VariantInit ( & vararg [ 1 ] ) ;
V_VT ( & vararg [ 1 ] ) = VT_BSTR ;
V_BSTR ( & vararg [ 1 ] ) = SysAllocString ( path ) ;
VariantInit ( & vararg [ 0 ] ) ;
V_VT ( & vararg [ 0 ] ) = VT_I2 ;
V_BSTR ( & vararg [ 0 ] ) = 0 ;
hr = IDispatch_Invoke ( pInstaller , dispid , & IID_NULL , LOCALE_NEUTRAL , DISPATCH_METHOD , & dispparams , & varresult , & excepinfo , NULL ) ;
ok ( hr = = S_OK , " IDispatch::Invoke returned 0x%08x \n " , hr ) ;
VariantClear ( & vararg [ 1 ] ) ;
VariantClear ( & varresult ) ;
DeleteFileW ( path ) ;
2008-02-10 13:22:36 +00: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 ) ;
ok ( hr = = DISP_E_MEMBERNOTFOUND , " IDispatch::Invoke returned 0x%08x \n " , hr ) ;
VariantInit ( & vararg [ 0 ] ) ;
hr = IDispatch_Invoke ( pInstaller , dispid , & IID_NULL , LOCALE_NEUTRAL , DISPATCH_PROPERTYPUT , & dispparams , & varresult , & excepinfo , NULL ) ;
ok ( hr = = DISP_E_MEMBERNOTFOUND , " IDispatch::Invoke returned 0x%08x \n " , hr ) ;
/* Test invoking a read-only property as DISPATCH_PROPERTYPUT or as a DISPATCH_METHOD */
2009-01-18 09:03:44 +00:00
name = szProductState ;
2008-02-10 13:22:36 +00:00
hr = IDispatch_GetIDsOfNames ( pInstaller , & IID_NULL , & name , 1 , LOCALE_USER_DEFAULT , & dispid ) ;
ok ( hr = = S_OK , " IDispatch::GetIDsOfNames returned 0x%08x \n " , hr ) ;
dispparams . rgvarg = NULL ;
dispparams . cArgs = 0 ;
hr = IDispatch_Invoke ( pInstaller , dispid , & IID_NULL , LOCALE_NEUTRAL , DISPATCH_PROPERTYPUT , & dispparams , & varresult , & excepinfo , NULL ) ;
ok ( hr = = DISP_E_MEMBERNOTFOUND , " IDispatch::Invoke returned 0x%08x \n " , hr ) ;
dispparams . rgvarg = NULL ;
dispparams . cArgs = 0 ;
hr = IDispatch_Invoke ( pInstaller , dispid , & IID_NULL , LOCALE_NEUTRAL , DISPATCH_METHOD , & dispparams , & varresult , & excepinfo , NULL ) ;
ok ( hr = = DISP_E_MEMBERNOTFOUND , " IDispatch::Invoke returned 0x%08x \n " , hr ) ;
}
/* invocation helper function */
static int _invoke_todo_vtResult = 0 ;
static HRESULT invoke ( IDispatch * pDispatch , LPCSTR szName , WORD wFlags , DISPPARAMS * pDispParams , VARIANT * pVarResult , VARTYPE vtResult )
{
OLECHAR * name = NULL ;
DISPID dispid ;
HRESULT hr ;
UINT i ;
UINT len ;
memset ( pVarResult , 0 , sizeof ( VARIANT ) ) ;
VariantInit ( pVarResult ) ;
len = MultiByteToWideChar ( CP_ACP , 0 , szName , - 1 , NULL , 0 ) ;
name = HeapAlloc ( GetProcessHeap ( ) , 0 , len * sizeof ( WCHAR ) ) ;
if ( ! name ) return E_FAIL ;
2012-01-21 17:21:57 +00:00
MultiByteToWideChar ( CP_ACP , 0 , szName , - 1 , name , len ) ;
2008-02-10 13:22:36 +00:00
hr = IDispatch_GetIDsOfNames ( pDispatch , & IID_NULL , & name , 1 , LOCALE_USER_DEFAULT , & dispid ) ;
HeapFree ( GetProcessHeap ( ) , 0 , name ) ;
ok ( hr = = S_OK , " IDispatch::GetIDsOfNames returned 0x%08x \n " , hr ) ;
if ( ! hr = = S_OK ) return hr ;
memset ( & excepinfo , 0 , sizeof ( excepinfo ) ) ;
hr = IDispatch_Invoke ( pDispatch , dispid , & IID_NULL , LOCALE_NEUTRAL , wFlags , pDispParams , pVarResult , & excepinfo , NULL ) ;
if ( hr = = S_OK )
{
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 ) ;
if ( vtResult ! = VT_EMPTY )
{
hr = VariantChangeTypeEx ( pVarResult , pVarResult , LOCALE_NEUTRAL , 0 , vtResult ) ;
ok ( hr = = S_OK , " VariantChangeTypeEx returned 0x%08x \n " , hr ) ;
}
}
for ( i = 0 ; i < pDispParams - > cArgs ; i + + )
VariantClear ( & pDispParams - > rgvarg [ i ] ) ;
return hr ;
}
/* Object_Property helper functions */
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 ;
}
static HRESULT Installer_RegistryValue ( HKEY hkey , LPCWSTR szKey , VARIANT vValue , VARIANT * pVarResult , VARTYPE vtExpect )
{
VARIANTARG vararg [ 3 ] ;
DISPPARAMS dispparams = { vararg , NULL , sizeof ( vararg ) / sizeof ( VARIANTARG ) , 0 } ;
VariantInit ( & vararg [ 2 ] ) ;
V_VT ( & vararg [ 2 ] ) = VT_I4 ;
2009-01-18 09:03:44 +00:00
V_I4 ( & vararg [ 2 ] ) = ( INT_PTR ) hkey ;
2008-02-10 13:22:36 +00:00
VariantInit ( & vararg [ 1 ] ) ;
V_VT ( & vararg [ 1 ] ) = VT_BSTR ;
V_BSTR ( & vararg [ 1 ] ) = SysAllocString ( szKey ) ;
VariantInit ( & vararg [ 0 ] ) ;
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 ;
VariantInit ( & vararg ) ;
V_VT ( & vararg ) = VT_EMPTY ;
hr = Installer_RegistryValue ( hkey , szKey , vararg , & varresult , VT_BOOL ) ;
* pBool = V_BOOL ( & varresult ) ;
VariantClear ( & varresult ) ;
return hr ;
}
static HRESULT Installer_RegistryValueW ( HKEY hkey , LPCWSTR szKey , LPCWSTR szValue , LPWSTR szString )
{
VARIANT varresult ;
VARIANTARG vararg ;
HRESULT hr ;
VariantInit ( & vararg ) ;
V_VT ( & vararg ) = VT_BSTR ;
V_BSTR ( & vararg ) = SysAllocString ( szValue ) ;
hr = Installer_RegistryValue ( hkey , szKey , vararg , & varresult , VT_BSTR ) ;
2012-01-21 17:21:57 +00:00
if ( V_BSTR ( & varresult ) ) lstrcpyW ( szString , V_BSTR ( & varresult ) ) ;
2008-02-10 13:22:36 +00:00
VariantClear ( & varresult ) ;
return hr ;
}
static HRESULT Installer_RegistryValueI ( HKEY hkey , LPCWSTR szKey , int iValue , LPWSTR szString , VARTYPE vtResult )
{
VARIANT varresult ;
VARIANTARG vararg ;
HRESULT hr ;
VariantInit ( & vararg ) ;
V_VT ( & vararg ) = VT_I4 ;
V_I4 ( & vararg ) = iValue ;
hr = Installer_RegistryValue ( hkey , szKey , vararg , & varresult , vtResult ) ;
2012-01-21 17:21:57 +00:00
if ( SUCCEEDED ( hr ) & & vtResult = = VT_BSTR ) lstrcpyW ( szString , V_BSTR ( & varresult ) ) ;
2008-02-10 13:22:36 +00:00
VariantClear ( & varresult ) ;
return hr ;
}
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 ;
hr = invoke ( pInstaller , " OpenPackage " , DISPATCH_METHOD , & dispparams , & varresult , VT_DISPATCH ) ;
* pSession = V_DISPATCH ( & varresult ) ;
return hr ;
}
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 ;
}
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 ) ;
}
static HRESULT Installer_ProductState ( LPCWSTR szProduct , int * pInstallState )
{
VARIANT varresult ;
VARIANTARG vararg [ 1 ] ;
DISPPARAMS dispparams = { vararg , NULL , sizeof ( vararg ) / sizeof ( VARIANTARG ) , 0 } ;
HRESULT hr ;
VariantInit ( & vararg [ 0 ] ) ;
V_VT ( & vararg [ 0 ] ) = VT_BSTR ;
V_BSTR ( & vararg [ 0 ] ) = SysAllocString ( szProduct ) ;
hr = invoke ( pInstaller , " ProductState " , DISPATCH_PROPERTYGET , & dispparams , & varresult , VT_I4 ) ;
* pInstallState = V_I4 ( & varresult ) ;
VariantClear ( & varresult ) ;
return hr ;
}
static HRESULT Installer_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 ) ;
2012-01-21 17:21:57 +00:00
if ( V_BSTR ( & varresult ) ) lstrcpyW ( szString , V_BSTR ( & varresult ) ) ;
2008-02-10 13:22:36 +00:00
VariantClear ( & varresult ) ;
return hr ;
}
static HRESULT Installer_Products ( IDispatch * * pStringList )
{
VARIANT varresult ;
DISPPARAMS dispparams = { NULL , NULL , 0 , 0 } ;
HRESULT hr ;
hr = invoke ( pInstaller , " Products " , DISPATCH_PROPERTYGET , & dispparams , & varresult , VT_DISPATCH ) ;
* pStringList = V_DISPATCH ( & varresult ) ;
return hr ;
}
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 ;
}
static HRESULT Installer_VersionGet ( LPWSTR szVersion )
{
VARIANT varresult ;
DISPPARAMS dispparams = { NULL , NULL , 0 , 0 } ;
HRESULT hr ;
hr = invoke ( pInstaller , " Version " , DISPATCH_PROPERTYGET , & dispparams , & varresult , VT_BSTR ) ;
2012-01-21 17:21:57 +00:00
if ( V_BSTR ( & varresult ) ) lstrcpyW ( szVersion , V_BSTR ( & varresult ) ) ;
2008-02-10 13:22:36 +00:00
VariantClear ( & varresult ) ;
return hr ;
}
2012-01-21 17:21:57 +00:00
static HRESULT Installer_UILevelPut ( int level )
{
VARIANT varresult ;
VARIANTARG vararg ;
DISPID dispid = DISPID_PROPERTYPUT ;
DISPPARAMS dispparams = { & vararg , & dispid , sizeof ( vararg ) / sizeof ( VARIANTARG ) , 1 } ;
VariantInit ( & vararg ) ;
V_VT ( & vararg ) = VT_I4 ;
V_I4 ( & vararg ) = level ;
return invoke ( pInstaller , " UILevel " , DISPATCH_PROPERTYPUT , & dispparams , & varresult , VT_EMPTY ) ;
}
2008-02-10 13:22:36 +00: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 ;
}
static HRESULT Session_PropertyGet ( IDispatch * pSession , LPCWSTR szName , LPWSTR szReturn )
{
VARIANT varresult ;
VARIANTARG vararg [ 1 ] ;
DISPPARAMS dispparams = { vararg , NULL , sizeof ( vararg ) / sizeof ( VARIANTARG ) , 0 } ;
HRESULT hr ;
VariantInit ( & vararg [ 0 ] ) ;
V_VT ( & vararg [ 0 ] ) = VT_BSTR ;
V_BSTR ( & vararg [ 0 ] ) = SysAllocString ( szName ) ;
hr = invoke ( pSession , " Property " , DISPATCH_PROPERTYGET , & dispparams , & varresult , VT_BSTR ) ;
2012-01-21 17:21:57 +00:00
if ( V_BSTR ( & varresult ) ) lstrcpyW ( szReturn , V_BSTR ( & varresult ) ) ;
2008-02-10 13:22:36 +00: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 ) ;
return invoke ( pSession , " Property " , DISPATCH_PROPERTYPUT , & dispparams , & varresult , VT_EMPTY ) ;
}
static HRESULT Session_LanguageGet ( IDispatch * pSession , UINT * pLangId )
{
VARIANT varresult ;
DISPPARAMS dispparams = { NULL , NULL , 0 , 0 } ;
HRESULT hr ;
hr = invoke ( pSession , " Language " , DISPATCH_PROPERTYGET , & dispparams , & varresult , VT_I4 ) ;
* 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 ;
hr = invoke ( pSession , " Mode " , DISPATCH_PROPERTYGET , & dispparams , & varresult , VT_BOOL ) ;
* 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 ;
return invoke ( pSession , " Mode " , DISPATCH_PROPERTYPUT , & dispparams , & varresult , VT_EMPTY ) ;
}
static HRESULT Session_Database ( IDispatch * pSession , IDispatch * * pDatabase )
{
VARIANT varresult ;
DISPPARAMS dispparams = { NULL , NULL , 0 , 0 } ;
HRESULT hr ;
hr = invoke ( pSession , " Database " , DISPATCH_PROPERTYGET , & dispparams , & varresult , VT_DISPATCH ) ;
* 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 ) ;
hr = invoke ( pSession , " DoAction " , DISPATCH_METHOD , & dispparams , & varresult , VT_I4 ) ;
* iReturn = V_I4 ( & varresult ) ;
VariantClear ( & varresult ) ;
return hr ;
}
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 ;
}
2009-05-17 07:05:22 +00:00
static HRESULT Session_Message ( IDispatch * pSession , LONG kind , IDispatch * record , int * ret )
2008-12-28 10:25:32 +00:00
{
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 ;
}
2009-05-17 07:05:22 +00:00
static HRESULT Session_SetInstallLevel ( IDispatch * pSession , LONG iInstallLevel )
2008-02-10 13:22:36 +00:00
{
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 ;
return invoke ( pSession , " SetInstallLevel " , DISPATCH_METHOD , & dispparams , & varresult , VT_EMPTY ) ;
}
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 ) ;
hr = invoke ( pSession , " FeatureCurrentState " , DISPATCH_PROPERTYGET , & dispparams , & varresult , VT_I4 ) ;
* 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 ) ;
hr = invoke ( pSession , " FeatureRequestState " , DISPATCH_PROPERTYGET , & dispparams , & varresult , VT_I4 ) ;
* 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 ;
return invoke ( pSession , " FeatureRequestState " , DISPATCH_PROPERTYPUT , & dispparams , & varresult , VT_EMPTY ) ;
}
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 ) ;
hr = invoke ( pDatabase , " OpenView " , DISPATCH_METHOD , & dispparams , & varresult , VT_DISPATCH ) ;
* pView = V_DISPATCH ( & varresult ) ;
return hr ;
}
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 ;
}
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 ;
return invoke ( pView , " Execute " , DISPATCH_METHOD , & dispparams , & varresult , VT_EMPTY ) ;
}
static HRESULT View_Fetch ( IDispatch * pView , IDispatch * * ppRecord )
{
VARIANT varresult ;
DISPPARAMS dispparams = { NULL , NULL , 0 , 0 } ;
HRESULT hr = invoke ( pView , " Fetch " , DISPATCH_METHOD , & dispparams , & varresult , VT_DISPATCH ) ;
* ppRecord = V_DISPATCH ( & varresult ) ;
return hr ;
}
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 ) ;
}
static HRESULT View_Close ( IDispatch * pView )
{
VARIANT varresult ;
DISPPARAMS dispparams = { NULL , NULL , 0 , 0 } ;
return invoke ( pView , " Close " , DISPATCH_METHOD , & dispparams , & varresult , VT_EMPTY ) ;
}
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 ;
}
static HRESULT Record_StringDataGet ( IDispatch * pRecord , int iField , 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 ] ) = iField ;
hr = invoke ( pRecord , " StringData " , DISPATCH_PROPERTYGET , & dispparams , & varresult , VT_BSTR ) ;
2012-01-21 17:21:57 +00:00
if ( V_BSTR ( & varresult ) ) lstrcpyW ( szString , V_BSTR ( & varresult ) ) ;
2008-02-10 13:22:36 +00: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 ) ;
return invoke ( pRecord , " StringData " , DISPATCH_PROPERTYPUT , & dispparams , & varresult , VT_EMPTY ) ;
}
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 ) ;
}
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 ;
}
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 ) ;
2012-01-21 17:21:57 +00:00
if ( V_BSTR ( & varresult ) ) lstrcpyW ( szString , V_BSTR ( & varresult ) ) ;
2008-02-10 13:22:36 +00: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 ;
}
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 ) ;
}
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 ) ;
}
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 ;
}
/* Test the various objects */
# define TEST_SUMMARYINFO_PROPERTIES_MODIFIED 4
static void test_SummaryInfo ( IDispatch * pSummaryInfo , const msi_summary_info * info , int num_info , BOOL readonly )
{
static const WCHAR szPropertyException [ ] = { ' P ' , ' r ' , ' o ' , ' p ' , ' e ' , ' r ' , ' t ' , ' y ' , ' , ' , ' P ' , ' i ' , ' d ' , 0 } ;
static const WCHAR szTitle [ ] = { ' T ' , ' i ' , ' t ' , ' l ' , ' e ' , 0 } ;
VARIANT varresult , var ;
SYSTEMTIME st ;
HRESULT hr ;
int j ;
/* SummaryInfo::PropertyCount */
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 ) ;
/* 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 ;
else if ( vt = = VT_I2 ) vt = VT_I4 ;
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 ) ) ;
else if ( vt = = VT_DATE )
{
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 ) ;
VariantClear ( & varresult ) ;
}
/* SummaryInfo::Property, get; invalid arguments */
/* Invalid pids */
hr = SummaryInfo_PropertyGet ( pSummaryInfo , - 1 , & varresult , VT_EMPTY ) ;
ok ( hr = = DISP_E_EXCEPTION , " SummaryInfo_PropertyGet failed, hresult 0x%08x \n " , hr ) ;
ok_exception ( hr , szPropertyException ) ;
hr = SummaryInfo_PropertyGet ( pSummaryInfo , 1000 , & varresult , VT_EMPTY ) ;
ok ( hr = = DISP_E_EXCEPTION , " SummaryInfo_PropertyGet failed, hresult 0x%08x \n " , hr ) ;
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 ) ;
ok ( hr = = S_OK , " SummaryInfo_PropertyGet failed, hresult 0x%08x \n " , hr ) ;
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 ) ;
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 ) ;
ok ( hr = = S_OK , " SummaryInfo_PropertyPut failed, hresult 0x%08x \n " , hr ) ;
hr = SummaryInfo_PropertyGet ( pSummaryInfo , PID_CODEPAGE , & varresult , VT_I4 /* NOT VT_I2 */ ) ;
ok ( hr = = S_OK , " SummaryInfo_PropertyGet failed, hresult 0x%08x \n " , hr ) ;
ok ( V_I2 ( & var ) = = V_I2 ( & varresult ) , " SummaryInfo_PropertyGet expected %d, but returned %d \n " , V_I2 ( & var ) , V_I2 ( & varresult ) ) ;
VariantClear ( & varresult ) ;
VariantClear ( & var ) ;
/* VT_BSTR */
V_VT ( & var ) = VT_BSTR ;
V_BSTR ( & var ) = SysAllocString ( szTitle ) ;
hr = SummaryInfo_PropertyPut ( pSummaryInfo , PID_TITLE , & var ) ;
ok ( hr = = S_OK , " SummaryInfo_PropertyPut failed, hresult 0x%08x \n " , hr ) ;
hr = SummaryInfo_PropertyGet ( pSummaryInfo , PID_TITLE , & varresult , V_VT ( & var ) ) ;
ok ( hr = = S_OK , " SummaryInfo_PropertyGet failed, hresult 0x%08x \n " , hr ) ;
ok_w2 ( " SummaryInfo_PropertyGet expected %s, but returned %s \n " , V_BSTR ( & var ) , V_BSTR ( & varresult ) ) ;
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 ) ;
ok ( hr = = S_OK , " SummaryInfo_PropertyPut failed, hresult 0x%08x \n " , hr ) ;
hr = SummaryInfo_PropertyGet ( pSummaryInfo , PID_LASTSAVE_DTM , & varresult , V_VT ( & var ) ) ;
ok ( hr = = S_OK , " SummaryInfo_PropertyGet failed, hresult 0x%08x \n " , hr ) ;
2009-12-06 14:46:53 +00:00
ok ( V_DATE ( & var ) = = V_DATE ( & varresult ) , " SummaryInfo_PropertyGet expected %lf, but returned %lf \n " , V_DATE ( & var ) , V_DATE ( & varresult ) ) ;
2008-02-10 13:22:36 +00:00
VariantClear ( & varresult ) ;
VariantClear ( & var ) ;
/* VT_I4 */
V_VT ( & var ) = VT_I4 ;
V_I4 ( & var ) = 1000 ;
hr = SummaryInfo_PropertyPut ( pSummaryInfo , PID_CHARCOUNT , & var ) ;
ok ( hr = = S_OK , " SummaryInfo_PropertyPut failed, hresult 0x%08x \n " , hr ) ;
hr = SummaryInfo_PropertyGet ( pSummaryInfo , PID_CHARCOUNT , & varresult , V_VT ( & var ) ) ;
ok ( hr = = S_OK , " SummaryInfo_PropertyGet failed, hresult 0x%08x \n " , hr ) ;
ok ( V_I4 ( & var ) = = V_I4 ( & varresult ) , " SummaryInfo_PropertyGet expected %d, but returned %d \n " , V_I4 ( & var ) , V_I4 ( & varresult ) ) ;
VariantClear ( & varresult ) ;
VariantClear ( & var ) ;
/* SummaryInfo::PropertyCount */
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 ) ;
}
}
static void test_Database ( IDispatch * pDatabase , BOOL readonly )
{
2014-04-23 14:49:34 +00:00
static const 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 const WCHAR szThree [ ] = { ' T ' , ' h ' , ' r ' , ' e ' , ' e ' , 0 } ;
static const WCHAR szTwo [ ] = { ' T ' , ' w ' , ' o ' , 0 } ;
static const WCHAR szStringDataField [ ] = { ' S ' , ' t ' , ' r ' , ' i ' , ' n ' , ' g ' , ' D ' , ' a ' , ' t ' , ' a ' , ' , ' , ' F ' , ' i ' , ' e ' , ' l ' , ' d ' , 0 } ;
static const WCHAR szModifyModeRecord [ ] = { ' M ' , ' o ' , ' d ' , ' i ' , ' f ' , ' y ' , ' , ' , ' M ' , ' o ' , ' d ' , ' e ' , ' , ' , ' R ' , ' e ' , ' c ' , ' o ' , ' r ' , ' d ' , 0 } ;
2008-02-10 13:22:36 +00:00
IDispatch * pView = NULL , * pSummaryInfo = NULL ;
HRESULT hr ;
hr = Database_OpenView ( pDatabase , szSql , & pView ) ;
ok ( hr = = S_OK , " Database_OpenView failed, hresult 0x%08x \n " , hr ) ;
if ( hr = = S_OK )
{
IDispatch * pRecord = NULL ;
WCHAR szString [ MAX_PATH ] ;
/* View::Execute */
hr = View_Execute ( pView , NULL ) ;
ok ( hr = = S_OK , " View_Execute failed, hresult 0x%08x \n " , hr ) ;
/* View::Fetch */
hr = View_Fetch ( pView , & pRecord ) ;
ok ( hr = = S_OK , " View_Fetch failed, hresult 0x%08x \n " , hr ) ;
ok ( pRecord ! = NULL , " View_Fetch should not have returned NULL record \n " ) ;
if ( pRecord )
{
/* Record::StringDataGet */
memset ( szString , 0 , sizeof ( szString ) ) ;
hr = Record_StringDataGet ( pRecord , 1 , szString ) ;
ok ( hr = = S_OK , " Record_StringDataGet failed, hresult 0x%08x \n " , hr ) ;
ok_w2 ( " Record_StringDataGet result was %s but expected %s \n " , szString , szThree ) ;
/* Record::StringDataPut with correct index */
hr = Record_StringDataPut ( pRecord , 1 , szTwo ) ;
ok ( hr = = S_OK , " Record_StringDataPut failed, hresult 0x%08x \n " , hr ) ;
/* Record::StringDataGet */
memset ( szString , 0 , sizeof ( szString ) ) ;
hr = Record_StringDataGet ( pRecord , 1 , szString ) ;
ok ( hr = = S_OK , " Record_StringDataGet failed, hresult 0x%08x \n " , hr ) ;
ok_w2 ( " Record_StringDataGet result was %s but expected %s \n " , szString , szTwo ) ;
/* 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 ) ;
/* View::Modify with incorrect parameters */
hr = View_Modify ( pView , - 5 , NULL ) ;
ok ( hr = = DISP_E_EXCEPTION , " View_Modify failed, hresult 0x%08x \n " , hr ) ;
ok_exception ( hr , szModifyModeRecord ) ;
hr = View_Modify ( pView , - 5 , pRecord ) ;
ok ( hr = = DISP_E_EXCEPTION , " View_Modify failed, hresult 0x%08x \n " , hr ) ;
ok_exception ( hr , szModifyModeRecord ) ;
hr = View_Modify ( pView , MSIMODIFY_REFRESH , NULL ) ;
ok ( hr = = DISP_E_EXCEPTION , " View_Modify failed, hresult 0x%08x \n " , hr ) ;
ok_exception ( hr , szModifyModeRecord ) ;
hr = View_Modify ( pView , MSIMODIFY_REFRESH , pRecord ) ;
2008-04-04 16:43:16 +00:00
ok ( hr = = S_OK , " View_Modify failed, hresult 0x%08x \n " , hr ) ;
2008-02-10 13:22:36 +00:00
/* Record::StringDataGet, confirm that the record is back to its unmodified value */
memset ( szString , 0 , sizeof ( szString ) ) ;
hr = Record_StringDataGet ( pRecord , 1 , szString ) ;
ok ( hr = = S_OK , " Record_StringDataGet failed, hresult 0x%08x \n " , hr ) ;
todo_wine ok_w2 ( " Record_StringDataGet result was %s but expected %s \n " , szString , szThree ) ;
IDispatch_Release ( pRecord ) ;
}
/* View::Fetch */
hr = View_Fetch ( pView , & pRecord ) ;
ok ( hr = = S_OK , " View_Fetch failed, hresult 0x%08x \n " , hr ) ;
ok ( pRecord ! = NULL , " View_Fetch should not have returned NULL record \n " ) ;
if ( pRecord )
{
/* Record::StringDataGet */
memset ( szString , 0 , sizeof ( szString ) ) ;
hr = Record_StringDataGet ( pRecord , 1 , szString ) ;
ok ( hr = = S_OK , " Record_StringDataGet failed, hresult 0x%08x \n " , hr ) ;
ok_w2 ( " Record_StringDataGet result was %s but expected %s \n " , szString , szTwo ) ;
IDispatch_Release ( pRecord ) ;
}
/* View::Fetch */
hr = View_Fetch ( pView , & pRecord ) ;
ok ( hr = = S_OK , " View_Fetch failed, hresult 0x%08x \n " , hr ) ;
ok ( pRecord = = NULL , " View_Fetch should have returned NULL record \n " ) ;
if ( pRecord )
IDispatch_Release ( pRecord ) ;
/* View::Close */
hr = View_Close ( pView ) ;
ok ( hr = = S_OK , " View_Close failed, hresult 0x%08x \n " , hr ) ;
IDispatch_Release ( pView ) ;
}
/* Database::SummaryInformation */
hr = Database_SummaryInformation ( pDatabase , TEST_SUMMARYINFO_PROPERTIES_MODIFIED , & pSummaryInfo ) ;
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 )
{
test_SummaryInfo ( pSummaryInfo , summary_info , sizeof ( summary_info ) / sizeof ( msi_summary_info ) , readonly ) ;
IDispatch_Release ( pSummaryInfo ) ;
}
}
static void test_Session ( IDispatch * pSession )
{
2014-04-23 14:49:34 +00:00
static const WCHAR szProductName [ ] = { ' P ' , ' r ' , ' o ' , ' d ' , ' u ' , ' c ' , ' t ' , ' N ' , ' a ' , ' m ' , ' e ' , 0 } ;
static const WCHAR szOne [ ] = { ' O ' , ' n ' , ' e ' , 0 } ;
static const WCHAR szOneStateFalse [ ] = { ' ! ' , ' O ' , ' n ' , ' e ' , ' > ' , ' 0 ' , 0 } ;
static const WCHAR szOneStateTrue [ ] = { ' ! ' , ' O ' , ' n ' , ' e ' , ' = ' , ' - ' , ' 1 ' , 0 } ;
static const WCHAR szOneActionFalse [ ] = { ' $ ' , ' O ' , ' n ' , ' e ' , ' = ' , ' - ' , ' 1 ' , 0 } ;
static const WCHAR szOneActionTrue [ ] = { ' $ ' , ' O ' , ' n ' , ' e ' , ' > ' , ' 0 ' , 0 } ;
static const WCHAR szCostInitialize [ ] = { ' C ' , ' o ' , ' s ' , ' t ' , ' I ' , ' n ' , ' i ' , ' t ' , ' i ' , ' a ' , ' l ' , ' i ' , ' z ' , ' e ' , 0 } ;
static const WCHAR szEmpty [ ] = { 0 } ;
static const WCHAR szEquals [ ] = { ' = ' , 0 } ;
static const WCHAR szPropertyName [ ] = { ' P ' , ' r ' , ' o ' , ' p ' , ' e ' , ' r ' , ' t ' , ' y ' , ' , ' , ' N ' , ' a ' , ' m ' , ' e ' , 0 } ;
static const WCHAR szModeFlag [ ] = { ' M ' , ' o ' , ' d ' , ' e ' , ' , ' , ' F ' , ' l ' , ' a ' , ' g ' , 0 } ;
2008-02-10 13:22:36 +00:00
WCHAR stringw [ MAX_PATH ] ;
CHAR string [ MAX_PATH ] ;
UINT len ;
BOOL bool ;
int myint ;
2008-12-28 10:25:32 +00:00
IDispatch * pDatabase = NULL , * pInst = NULL , * record = NULL ;
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
ULONG refs_before , refs_after ;
2008-02-10 13:22:36 +00:00
HRESULT hr ;
/* Session::Installer */
hr = Session_Installer ( pSession , & pInst ) ;
ok ( hr = = S_OK , " Session_Installer failed, hresult 0x%08x \n " , hr ) ;
ok ( pInst ! = NULL , " Session_Installer returned NULL IDispatch pointer \n " ) ;
ok ( pInst = = pInstaller , " Session_Installer does not match Installer instance from CoCreateInstance \n " ) ;
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
refs_before = IDispatch_AddRef ( pInst ) ;
hr = Session_Installer ( pSession , & pInst ) ;
ok ( hr = = S_OK , " Session_Installer failed, hresult 0x%08x \n " , hr ) ;
ok ( pInst ! = NULL , " Session_Installer returned NULL IDispatch pointer \n " ) ;
ok ( pInst = = pInstaller , " Session_Installer does not match Installer instance from CoCreateInstance \n " ) ;
refs_after = IDispatch_Release ( pInst ) ;
ok ( refs_before = = refs_after , " got %u and %u \n " , refs_before , refs_after ) ;
2008-02-10 13:22:36 +00:00
/* Session::Property, get */
memset ( stringw , 0 , sizeof ( stringw ) ) ;
hr = Session_PropertyGet ( pSession , szProductName , stringw ) ;
ok ( hr = = S_OK , " Session_PropertyGet failed, hresult 0x%08x \n " , hr ) ;
2012-01-21 17:21:57 +00:00
if ( lstrcmpW ( stringw , szMSITEST ) ! = 0 )
2008-02-10 13:22:36 +00:00
{
len = WideCharToMultiByte ( CP_ACP , 0 , stringw , - 1 , string , MAX_PATH , NULL , NULL ) ;
ok ( len , " WideCharToMultiByteChar returned error %d \n " , GetLastError ( ) ) ;
ok ( 0 , " Property \" ProductName \" expected to be \" MSITEST \" but was \" %s \" \n " , string ) ;
}
/* Session::Property, put */
hr = Session_PropertyPut ( pSession , szProductName , szProductName ) ;
ok ( hr = = S_OK , " Session_PropertyPut failed, hresult 0x%08x \n " , hr ) ;
memset ( stringw , 0 , sizeof ( stringw ) ) ;
hr = Session_PropertyGet ( pSession , szProductName , stringw ) ;
ok ( hr = = S_OK , " Session_PropertyGet failed, hresult 0x%08x \n " , hr ) ;
2012-01-21 17:21:57 +00:00
if ( lstrcmpW ( stringw , szProductName ) ! = 0 )
2008-02-10 13:22:36 +00:00
{
len = WideCharToMultiByte ( CP_ACP , 0 , stringw , - 1 , string , MAX_PATH , NULL , NULL ) ;
ok ( len , " WideCharToMultiByteChar returned error %d \n " , GetLastError ( ) ) ;
ok ( 0 , " Property \" ProductName \" expected to be \" ProductName \" but was \" %s \" \n " , string ) ;
}
/* Try putting a property using empty property identifier */
hr = Session_PropertyPut ( pSession , szEmpty , szProductName ) ;
ok ( hr = = DISP_E_EXCEPTION , " Session_PropertyPut failed, hresult 0x%08x \n " , hr ) ;
ok_exception ( hr , szPropertyName ) ;
/* Try putting a property using illegal property identifier */
hr = Session_PropertyPut ( pSession , szEquals , szProductName ) ;
ok ( hr = = S_OK , " Session_PropertyPut failed, hresult 0x%08x \n " , hr ) ;
/* Session::Language, get */
hr = Session_LanguageGet ( pSession , & len ) ;
ok ( hr = = S_OK , " Session_LanguageGet failed, hresult 0x%08x \n " , hr ) ;
/* Not sure how to check the language is correct */
/* Session::Mode, get */
hr = Session_ModeGet ( pSession , MSIRUNMODE_REBOOTATEND , & bool ) ;
ok ( hr = = S_OK , " Session_ModeGet failed, hresult 0x%08x \n " , hr ) ;
2010-03-01 12:03:29 +00:00
ok ( ! bool , " Reboot at end session mode is %d \n " , bool ) ;
hr = Session_ModeGet ( pSession , MSIRUNMODE_MAINTENANCE , & bool ) ;
ok ( hr = = S_OK , " Session_ModeGet failed, hresult 0x%08x \n " , hr ) ;
ok ( ! bool , " Maintenance mode is %d \n " , bool ) ;
2008-02-10 13:22:36 +00:00
/* Session::Mode, put */
hr = Session_ModePut ( pSession , MSIRUNMODE_REBOOTATEND , TRUE ) ;
2009-12-06 14:46:53 +00:00
ok ( hr = = S_OK , " Session_ModePut failed, hresult 0x%08x \n " , hr ) ;
2008-02-10 13:22:36 +00:00
hr = Session_ModeGet ( pSession , MSIRUNMODE_REBOOTATEND , & bool ) ;
ok ( hr = = S_OK , " Session_ModeGet failed, hresult 0x%08x \n " , hr ) ;
ok ( bool , " Reboot at end session mode is %d, expected 1 \n " , bool ) ;
hr = Session_ModePut ( pSession , MSIRUNMODE_REBOOTATEND , FALSE ) ; /* set it again so we don't reboot */
2009-12-06 14:46:53 +00:00
ok ( hr = = S_OK , " Session_ModePut failed, hresult 0x%08x \n " , hr ) ;
2008-02-10 13:22:36 +00:00
2010-03-01 12:03:29 +00:00
hr = Session_ModePut ( pSession , MSIRUNMODE_REBOOTNOW , TRUE ) ;
2012-05-14 21:41:45 +00:00
ok ( hr = = S_OK , " Session_ModePut failed, hresult 0x%08x \n " , hr ) ;
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
if ( hr = = DISP_E_EXCEPTION ) ok_exception ( hr , szModeFlag ) ;
2010-03-01 12:03:29 +00:00
hr = Session_ModeGet ( pSession , MSIRUNMODE_REBOOTNOW , & bool ) ;
ok ( hr = = S_OK , " Session_ModeGet failed, hresult 0x%08x \n " , hr ) ;
ok ( bool , " Reboot now mode is %d, expected 1 \n " , bool ) ;
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
2010-03-01 12:03:29 +00:00
hr = Session_ModePut ( pSession , MSIRUNMODE_REBOOTNOW , FALSE ) ; /* set it again so we don't reboot */
2012-05-14 21:41:45 +00:00
ok ( hr = = S_OK , " Session_ModePut failed, hresult 0x%08x \n " , hr ) ;
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
if ( hr = = DISP_E_EXCEPTION ) ok_exception ( hr , szModeFlag ) ;
2010-03-01 12:03:29 +00:00
hr = Session_ModePut ( pSession , MSIRUNMODE_MAINTENANCE , TRUE ) ;
ok ( hr = = DISP_E_EXCEPTION , " Session_ModePut failed, hresult 0x%08x \n " , hr ) ;
Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink, imm32, jscript, kernel32, localspl, msacm32, mscms, msi, mstask, msvcrtd, msxml3, ntdll, ole32, pdh, psapi, quartz, rasapi32, riched20 AND rsaenh Winetests.
TBD mshtml, shell32, oleaut32 which still fail to build here
svn path=/trunk/; revision=47931
2010-07-03 12:45:23 +00:00
ok_exception ( hr , szModeFlag ) ;
2010-03-01 12:03:29 +00:00
2008-02-10 13:22:36 +00:00
/* Session::Database, get */
hr = Session_Database ( pSession , & pDatabase ) ;
ok ( hr = = S_OK , " Session_Database failed, hresult 0x%08x \n " , hr ) ;
if ( hr = = S_OK )
{
test_Database ( pDatabase , TRUE ) ;
IDispatch_Release ( pDatabase ) ;
}
/* Session::EvaluateCondition */
hr = Session_EvaluateCondition ( pSession , NULL , & myint ) ;
ok ( hr = = S_OK , " Session_EvaluateCondition failed, hresult 0x%08x \n " , hr ) ;
ok ( myint = = MSICONDITION_NONE , " Feature current state was %d but expected %d \n " , myint , INSTALLSTATE_UNKNOWN ) ;
hr = Session_EvaluateCondition ( pSession , szEmpty , & myint ) ;
ok ( hr = = S_OK , " Session_EvaluateCondition failed, hresult 0x%08x \n " , hr ) ;
ok ( myint = = MSICONDITION_NONE , " Feature current state was %d but expected %d \n " , myint , INSTALLSTATE_UNKNOWN ) ;
hr = Session_EvaluateCondition ( pSession , szEquals , & myint ) ;
ok ( hr = = S_OK , " Session_EvaluateCondition failed, hresult 0x%08x \n " , hr ) ;
ok ( myint = = MSICONDITION_ERROR , " Feature current state was %d but expected %d \n " , myint , INSTALLSTATE_UNKNOWN ) ;
/* Session::DoAction(CostInitialize) must occur before the next statements */
hr = Session_DoAction ( pSession , szCostInitialize , & myint ) ;
ok ( hr = = S_OK , " Session_DoAction failed, hresult 0x%08x \n " , hr ) ;
ok ( myint = = IDOK , " DoAction(CostInitialize) returned %d, %d expected \n " , myint , IDOK ) ;
/* Session::SetInstallLevel */
hr = Session_SetInstallLevel ( pSession , INSTALLLEVEL_MINIMUM ) ;
ok ( hr = = S_OK , " Session_SetInstallLevel failed, hresult 0x%08x \n " , hr ) ;
/* Session::FeatureCurrentState, get */
hr = Session_FeatureCurrentState ( pSession , szOne , & myint ) ;
ok ( hr = = S_OK , " Session_FeatureCurrentState failed, hresult 0x%08x \n " , hr ) ;
ok ( myint = = INSTALLSTATE_UNKNOWN , " Feature current state was %d but expected %d \n " , myint , INSTALLSTATE_UNKNOWN ) ;
2008-12-28 10:25:32 +00: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 ) ;
2008-02-10 13:22:36 +00:00
/* Session::EvaluateCondition */
hr = Session_EvaluateCondition ( pSession , szOneStateFalse , & myint ) ;
ok ( hr = = S_OK , " Session_EvaluateCondition failed, hresult 0x%08x \n " , hr ) ;
ok ( myint = = MSICONDITION_FALSE , " Feature current state was %d but expected %d \n " , myint , INSTALLSTATE_UNKNOWN ) ;
hr = Session_EvaluateCondition ( pSession , szOneStateTrue , & myint ) ;
ok ( hr = = S_OK , " Session_EvaluateCondition failed, hresult 0x%08x \n " , hr ) ;
ok ( myint = = MSICONDITION_TRUE , " Feature current state was %d but expected %d \n " , myint , INSTALLSTATE_UNKNOWN ) ;
/* Session::FeatureRequestState, put */
hr = Session_FeatureRequestStatePut ( pSession , szOne , INSTALLSTATE_ADVERTISED ) ;
ok ( hr = = S_OK , " Session_FeatureRequestStatePut failed, hresult 0x%08x \n " , hr ) ;
hr = Session_FeatureRequestStateGet ( pSession , szOne , & myint ) ;
ok ( hr = = S_OK , " Session_FeatureRequestStateGet failed, hresult 0x%08x \n " , hr ) ;
ok ( myint = = INSTALLSTATE_ADVERTISED , " Feature request state was %d but expected %d \n " , myint , INSTALLSTATE_ADVERTISED ) ;
/* Session::EvaluateCondition */
hr = Session_EvaluateCondition ( pSession , szOneActionFalse , & myint ) ;
ok ( hr = = S_OK , " Session_EvaluateCondition failed, hresult 0x%08x \n " , hr ) ;
ok ( myint = = MSICONDITION_FALSE , " Feature current state was %d but expected %d \n " , myint , INSTALLSTATE_UNKNOWN ) ;
hr = Session_EvaluateCondition ( pSession , szOneActionTrue , & myint ) ;
ok ( hr = = S_OK , " Session_EvaluateCondition failed, hresult 0x%08x \n " , hr ) ;
ok ( myint = = MSICONDITION_TRUE , " Feature current state was %d but expected %d \n " , myint , INSTALLSTATE_UNKNOWN ) ;
}
/* 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 } ;
static const WCHAR szREG_BINARY [ ] = { ' ( ' , ' R ' , ' E ' , ' G ' , ' _ ' , ' B ' , ' I ' , ' N ' , ' A ' , ' R ' , ' Y ' , ' ) ' , 0 } ;
static const WCHAR szFour [ ] = { ' F ' , ' o ' , ' u ' , ' r ' , 0 } ;
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 } ;
2013-04-03 21:58:14 +00:00
static const WCHAR szREG_2 [ ] = { ' ( ' , ' R ' , ' E ' , ' G ' , ' _ ' , ' ? ' , ' ? ' , ' ) ' , 0 } ;
2008-02-10 13:22:36 +00:00
static const WCHAR szSeven [ ] = { ' S ' , ' e ' , ' v ' , ' e ' , ' n ' , 0 } ;
static const WCHAR szEight [ ] = { ' E ' , ' i ' , ' g ' , ' h ' , ' t ' , 0 } ;
static const WCHAR szBlank [ ] = { 0 } ;
VARIANT varresult ;
VARIANTARG vararg ;
WCHAR szString [ MAX_PATH ] ;
HKEY hkey , hkey_sub ;
2008-04-04 16:43:16 +00:00
HKEY curr_user = ( HKEY ) 1 ;
2008-02-10 13:22:36 +00:00
HRESULT hr ;
BOOL bRet ;
2008-12-28 10:25:32 +00:00
LONG lRet ;
2008-02-10 13:22:36 +00:00
/* Delete keys */
2008-12-28 10:25:32 +00: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 ) ;
2008-02-10 13:22:36 +00:00
/* Does our key exist? Shouldn't; check with all three possible value parameter types */
2008-04-04 16:43:16 +00:00
hr = Installer_RegistryValueE ( curr_user , szKey , & bRet ) ;
2008-02-10 13:22:36 +00:00
ok ( hr = = S_OK , " Installer_RegistryValueE failed, hresult 0x%08x \n " , hr ) ;
ok ( ! bRet , " Registry key expected to not exist, but Installer_RegistryValue claims it does \n " ) ;
memset ( szString , 0 , sizeof ( szString ) ) ;
2008-04-04 16:43:16 +00:00
hr = Installer_RegistryValueW ( curr_user , szKey , NULL , szString ) ;
2008-02-10 13:22:36 +00:00
ok ( hr = = DISP_E_BADINDEX , " Installer_RegistryValueW failed, hresult 0x%08x \n " , hr ) ;
memset ( szString , 0 , sizeof ( szString ) ) ;
2008-04-04 16:43:16 +00:00
hr = Installer_RegistryValueI ( curr_user , szKey , 0 , szString , VT_BSTR ) ;
2008-02-10 13:22:36 +00:00
ok ( hr = = DISP_E_BADINDEX , " Installer_RegistryValueI failed, hresult 0x%08x \n " , hr ) ;
/* 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 " ) ;
2012-01-21 17:21:57 +00:00
bRet = SetEnvironmentVariableA ( " MSITEST " , " Four " ) ;
ok ( bRet , " SetEnvironmentVariableA failed %d \n " , GetLastError ( ) ) ;
2008-02-10 13:22:36 +00:00
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-12-28 10:25:32 +00:00
ok ( ! RegSetValueExW ( hkey , szSeven , 0 , REG_NONE , NULL , 0 ) ,
2008-02-10 13:22:36 +00:00
" RegSetValueExW failed \n " ) ;
ok ( ! RegSetValueExW ( hkey , NULL , 0 , REG_SZ , ( const BYTE * ) szOne , sizeof ( szOne ) ) ,
" RegSetValueExW failed \n " ) ;
ok ( ! RegCreateKeyW ( hkey , szEight , & hkey_sub ) , " RegCreateKeyW failed \n " ) ;
/* Does our key exist? It should, and make sure we retrieve the correct default value */
bRet = FALSE ;
2008-04-04 16:43:16 +00:00
hr = Installer_RegistryValueE ( curr_user , szKey , & bRet ) ;
2008-02-10 13:22:36 +00:00
ok ( hr = = S_OK , " Installer_RegistryValueE failed, hresult 0x%08x \n " , hr ) ;
ok ( bRet , " Registry key expected to exist, but Installer_RegistryValue claims it does not \n " ) ;
memset ( szString , 0 , sizeof ( szString ) ) ;
2008-04-04 16:43:16 +00:00
hr = Installer_RegistryValueW ( curr_user , szKey , NULL , szString ) ;
2008-02-10 13:22:36 +00:00
ok ( hr = = S_OK , " Installer_RegistryValueW failed, hresult 0x%08x \n " , hr ) ;
ok_w2 ( " Default registry value \" %s \" does not match expected \" %s \" \n " , szString , szOne ) ;
/* Ask for the value of a nonexistent key */
memset ( szString , 0 , sizeof ( szString ) ) ;
2008-04-04 16:43:16 +00:00
hr = Installer_RegistryValueW ( curr_user , szKey , szExpand , szString ) ;
2008-02-10 13:22:36 +00:00
ok ( hr = = DISP_E_BADINDEX , " Installer_RegistryValueW failed, hresult 0x%08x \n " , hr ) ;
/* Get values of keys */
memset ( szString , 0 , sizeof ( szString ) ) ;
2008-04-04 16:43:16 +00:00
hr = Installer_RegistryValueW ( curr_user , szKey , szOne , szString ) ;
2008-02-10 13:22:36 +00:00
ok ( hr = = S_OK , " Installer_RegistryValueW failed, hresult 0x%08x \n " , hr ) ;
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-04-04 16:43:16 +00:00
hr = Installer_RegistryValue ( curr_user , szKey , vararg , & varresult , VT_I4 ) ;
2008-02-10 13:22:36 +00:00
ok ( hr = = S_OK , " Installer_RegistryValue failed, hresult 0x%08x \n " , hr ) ;
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-04-04 16:43:16 +00:00
hr = Installer_RegistryValueW ( curr_user , szKey , szThree , szString ) ;
2008-02-10 13:22:36 +00:00
ok ( hr = = S_OK , " Installer_RegistryValueW failed, hresult 0x%08x \n " , hr ) ;
ok_w2 ( " Registry value \" %s \" does not match expected \" %s \" \n " , szString , szREG_BINARY ) ;
memset ( szString , 0 , sizeof ( szString ) ) ;
2008-04-04 16:43:16 +00:00
hr = Installer_RegistryValueW ( curr_user , szKey , szFour , szString ) ;
2008-02-10 13:22:36 +00:00
ok ( hr = = S_OK , " Installer_RegistryValueW failed, hresult 0x%08x \n " , hr ) ;
ok_w2 ( " Registry value \" %s \" does not match expected \" %s \" \n " , szString , szFour ) ;
2008-12-28 10:25:32 +00:00
/* Vista does not NULL-terminate this case */
2008-02-10 13:22:36 +00:00
memset ( szString , 0 , sizeof ( szString ) ) ;
2008-04-04 16:43:16 +00:00
hr = Installer_RegistryValueW ( curr_user , szKey , szFive , szString ) ;
2008-02-10 13:22:36 +00:00
ok ( hr = = S_OK , " Installer_RegistryValueW failed, hresult 0x%08x \n " , hr ) ;
2008-12-28 10:25:32 +00:00
ok_w2n ( " Registry value \" %s \" does not match expected \" %s \" \n " ,
szString , szFiveHi , lstrlenW ( szFiveHi ) ) ;
2008-02-10 13:22:36 +00:00
memset ( szString , 0 , sizeof ( szString ) ) ;
2008-04-04 16:43:16 +00:00
hr = Installer_RegistryValueW ( curr_user , szKey , szSix , szString ) ;
2008-02-10 13:22:36 +00:00
ok ( hr = = S_OK , " Installer_RegistryValueW failed, hresult 0x%08x \n " , hr ) ;
2013-04-03 21:58:14 +00:00
ok ( ! lstrcmpW ( szString , szREG_2 ) | | broken ( ! lstrcmpW ( szString , szREG_ ) ) ,
" Registry value does not match \n " ) ;
2008-02-10 13:22:36 +00:00
VariantInit ( & vararg ) ;
V_VT ( & vararg ) = VT_BSTR ;
V_BSTR ( & vararg ) = SysAllocString ( szSeven ) ;
2008-04-04 16:43:16 +00:00
hr = Installer_RegistryValue ( curr_user , szKey , vararg , & varresult , VT_EMPTY ) ;
2008-02-10 13:22:36 +00:00
ok ( hr = = S_OK , " Installer_RegistryValue failed, hresult 0x%08x \n " , hr ) ;
/* Get string class name for the key */
memset ( szString , 0 , sizeof ( szString ) ) ;
2008-04-04 16:43:16 +00:00
hr = Installer_RegistryValueI ( curr_user , szKey , 0 , szString , VT_BSTR ) ;
2008-02-10 13:22:36 +00:00
ok ( hr = = S_OK , " Installer_RegistryValueI failed, hresult 0x%08x \n " , hr ) ;
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-04-04 16:43:16 +00:00
hr = Installer_RegistryValueI ( curr_user , szKey , 2 , szString , VT_BSTR ) ;
2008-02-10 13:22:36 +00:00
ok ( hr = = S_OK , " Installer_RegistryValueI failed, hresult 0x%08x \n " , hr ) ;
/* 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-04-04 16:43:16 +00:00
hr = Installer_RegistryValueI ( curr_user , szKey , 10 , szString , VT_EMPTY ) ;
2008-02-10 13:22:36 +00:00
ok ( hr = = S_OK , " Installer_RegistryValueI failed, hresult 0x%08x \n " , hr ) ;
/* Get name of a subkey by negative number (RegEnumValue like), valid index */
memset ( szString , 0 , sizeof ( szString ) ) ;
2008-04-04 16:43:16 +00:00
hr = Installer_RegistryValueI ( curr_user , szKey , - 1 , szString , VT_BSTR ) ;
2008-02-10 13:22:36 +00:00
ok ( hr = = S_OK , " Installer_RegistryValueI failed, hresult 0x%08x \n " , hr ) ;
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-04-04 16:43:16 +00:00
hr = Installer_RegistryValueI ( curr_user , szKey , - 10 , szString , VT_EMPTY ) ;
2008-02-10 13:22:36 +00:00
ok ( hr = = S_OK , " Installer_RegistryValueI failed, hresult 0x%08x \n " , hr ) ;
/* clean up */
delete_key ( hkey ) ;
}
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 */
2012-01-21 17:21:57 +00:00
if ( ! bProductFound & & ! lstrcmpW ( szString , szProductCode ) )
2008-02-10 13:22:36 +00:00
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 ) ;
}
}
}
2009-05-17 07:05:22 +00:00
if ( bProductInstalled )
2008-07-09 11:34:20 +00:00
{
ok ( bProductInstalled = = bProductFound , " Product expected to %s installed but product code was %s \n " ,
bProductInstalled ? " be " : " not be " ,
bProductFound ? " found " : " not found " ) ;
}
2008-02-10 13:22:36 +00:00
if ( pEnum )
{
IEnumVARIANT * pEnum2 = NULL ;
if ( 0 ) /* Crashes on Windows XP */
{
/* IEnumVARIANT::Clone, NULL pointer */
2012-01-21 17:21:57 +00:00
IEnumVARIANT_Clone ( pEnum , NULL ) ;
2008-02-10 13:22:36 +00:00
}
/* 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 ) ;
}
}
/* Delete a registry subkey, including all its subkeys (RegDeleteKey does not work on keys with subkeys without
* deleting the subkeys first ) */
2012-01-21 17:21:57 +00:00
static UINT delete_registry_key ( HKEY hkeyParent , LPCSTR subkey , REGSAM access )
2008-02-10 13:22:36 +00:00
{
UINT ret ;
CHAR * string = NULL ;
HKEY hkey ;
DWORD dwSize ;
2014-04-23 14:49:34 +00:00
ret = RegOpenKeyExA ( hkeyParent , subkey , 0 , access , & hkey ) ;
2008-02-10 13:22:36 +00:00
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 )
2012-01-21 17:21:57 +00:00
delete_registry_key ( hkey , string , access ) ;
2008-02-10 13:22:36 +00:00
RegCloseKey ( hkey ) ;
HeapFree ( GetProcessHeap ( ) , 0 , string ) ;
2012-01-21 17:21:57 +00:00
delete_key_portable ( hkeyParent , subkey , access ) ;
2008-02-10 13:22:36 +00:00
return ERROR_SUCCESS ;
}
/* Find a specific registry subkey at any depth within the given key and subkey and return its parent key. */
2012-01-21 17:21:57 +00:00
static UINT find_registry_key ( HKEY hkeyParent , LPCSTR subkey , LPCSTR findkey , REGSAM access , HKEY * phkey )
2008-02-10 13:22:36 +00:00
{
UINT ret ;
CHAR * string = NULL ;
int idx = 0 ;
HKEY hkey ;
DWORD dwSize ;
BOOL found = FALSE ;
* phkey = 0 ;
2014-04-23 14:49:34 +00:00
ret = RegOpenKeyExA ( hkeyParent , subkey , 0 , access , & hkey ) ;
2008-02-10 13:22:36 +00:00
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 ;
}
2012-01-21 17:21:57 +00:00
else if ( find_registry_key ( hkey , string , findkey , access , phkey ) = = ERROR_SUCCESS ) found = TRUE ;
2008-02-10 13:22:36 +00:00
}
if ( * phkey ! = hkey ) RegCloseKey ( hkey ) ;
HeapFree ( GetProcessHeap ( ) , 0 , string ) ;
return ( found ? ERROR_SUCCESS : ERROR_FILE_NOT_FOUND ) ;
}
static void test_Installer_InstallProduct ( void )
{
HRESULT hr ;
CHAR path [ MAX_PATH ] ;
WCHAR szString [ MAX_PATH ] ;
LONG res ;
HKEY hkey ;
DWORD num , size , type ;
int iValue , iCount ;
IDispatch * pStringList = NULL ;
2012-01-21 17:21:57 +00:00
REGSAM access = KEY_ALL_ACCESS ;
2014-04-23 14:49:34 +00:00
if ( is_process_limited ( ) )
{
/* In fact InstallProduct would succeed but then Windows XP
* would not allow us to clean up the registry !
*/
skip ( " Installer_InstallProduct (insufficient privileges) \n " ) ;
return ;
}
2012-01-21 17:21:57 +00:00
if ( is_wow64 )
access | = KEY_WOW64_64KEY ;
2008-02-10 13:22:36 +00:00
create_test_files ( ) ;
2012-01-21 17:21:57 +00:00
/* Avoid an interactive dialog in case of insufficient privileges. */
hr = Installer_UILevelPut ( INSTALLUILEVEL_NONE ) ;
ok ( hr = = S_OK , " Expected UILevel property put invoke to return S_OK, got 0x%08x \n " , hr ) ;
2008-02-10 13:22:36 +00:00
/* Installer::InstallProduct */
hr = Installer_InstallProduct ( szMsifile , NULL ) ;
2008-04-04 16:43:16 +00:00
if ( hr = = DISP_E_EXCEPTION )
{
2012-01-21 17:21:57 +00:00
skip ( " InstallProduct failed, insufficient rights? \n " ) ;
2008-04-04 16:43:16 +00:00
delete_test_files ( ) ;
return ;
}
2008-02-10 13:22:36 +00:00
ok ( hr = = S_OK , " Installer_InstallProduct failed, hresult 0x%08x \n " , hr ) ;
/* Installer::ProductState for our product code, which has been installed */
hr = Installer_ProductState ( szProductCode , & iValue ) ;
ok ( hr = = S_OK , " Installer_ProductState failed, hresult 0x%08x \n " , hr ) ;
ok ( iValue = = INSTALLSTATE_DEFAULT , " Installer_ProductState returned %d, expected %d \n " , iValue , INSTALLSTATE_DEFAULT ) ;
/* Installer::ProductInfo for our product code */
/* 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 ) ;
/* Nonexistent attribute */
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 ) ;
/* Package name */
memset ( szString , 0 , sizeof ( szString ) ) ;
hr = Installer_ProductInfo ( szProductCode , WINE_INSTALLPROPERTY_PACKAGENAMEW , szString ) ;
2008-04-04 16:43:16 +00:00
ok ( hr = = S_OK , " Installer_ProductInfo failed, hresult 0x%08x \n " , hr ) ;
2008-02-10 13:22:36 +00:00
todo_wine ok_w2 ( " Installer_ProductInfo returned %s but expected %s \n " , szString , szMsifile ) ;
/* Product name */
memset ( szString , 0 , sizeof ( szString ) ) ;
hr = Installer_ProductInfo ( szProductCode , WINE_INSTALLPROPERTY_PRODUCTNAMEW , szString ) ;
ok ( hr = = S_OK , " Installer_ProductInfo failed, hresult 0x%08x \n " , hr ) ;
2008-04-04 16:43:16 +00:00
todo_wine ok_w2 ( " Installer_ProductInfo returned %s but expected %s \n " , szString , szMSITEST ) ;
2008-02-10 13:22:36 +00:00
/* Installer::Products */
test_Installer_Products ( TRUE ) ;
/* Installer::RelatedProducts for our upgrade code */
hr = Installer_RelatedProducts ( szUpgradeCode , & pStringList ) ;
ok ( hr = = S_OK , " Installer_RelatedProducts failed, hresult 0x%08x \n " , hr ) ;
if ( hr = = S_OK )
{
/* StringList::Count */
hr = StringList_Count ( pStringList , & iCount ) ;
ok ( hr = = S_OK , " StringList_Count failed, hresult 0x%08x \n " , hr ) ;
ok ( iCount = = 1 , " Expected one related product but found %d \n " , iCount ) ;
/* StringList::Item */
memset ( szString , 0 , sizeof ( szString ) ) ;
hr = StringList_Item ( pStringList , 0 , szString ) ;
ok ( hr = = S_OK , " StringList_Item failed (idx 0, count %d), hresult 0x%08x \n " , iCount , hr ) ;
ok_w2 ( " StringList_Item returned %s but expected %s \n " , szString , szProductCode ) ;
IDispatch_Release ( pStringList ) ;
}
2012-01-21 17:21:57 +00:00
hr = Installer_ProductInfo ( szProductCode , WINE_INSTALLPROPERTY_LOCALPACKAGEW , szString ) ;
ok ( hr = = S_OK , " Installer_ProductInfo failed, hresult 0x%08x \n " , hr ) ;
DeleteFileW ( szString ) ;
2008-02-10 13:22:36 +00:00
/* Check & clean up installed files & registry keys */
ok ( delete_pf ( " msitest \\ cabout \\ new \\ five.txt " , TRUE ) , " File not installed \n " ) ;
2012-01-21 17:21:57 +00:00
ok ( delete_pf ( " msitest \\ cabout \\ new " , FALSE ) , " Directory not created \n " ) ;
2008-02-10 13:22:36 +00:00
ok ( delete_pf ( " msitest \\ cabout \\ four.txt " , TRUE ) , " File not installed \n " ) ;
2012-01-21 17:21:57 +00:00
ok ( delete_pf ( " msitest \\ cabout " , FALSE ) , " Directory not created \n " ) ;
2008-02-10 13:22:36 +00:00
ok ( delete_pf ( " msitest \\ changed \\ three.txt " , TRUE ) , " File not installed \n " ) ;
2012-01-21 17:21:57 +00:00
ok ( delete_pf ( " msitest \\ changed " , FALSE ) , " Directory not created \n " ) ;
2008-02-10 13:22:36 +00:00
ok ( delete_pf ( " msitest \\ first \\ two.txt " , TRUE ) , " File not installed \n " ) ;
2012-01-21 17:21:57 +00:00
ok ( delete_pf ( " msitest \\ first " , FALSE ) , " Directory not created \n " ) ;
2008-02-10 13:22:36 +00:00
ok ( delete_pf ( " msitest \\ one.txt " , TRUE ) , " File not installed \n " ) ;
ok ( delete_pf ( " msitest \\ filename " , TRUE ) , " File not installed \n " ) ;
2012-01-21 17:21:57 +00:00
ok ( delete_pf ( " msitest " , FALSE ) , " Directory not created \n " ) ;
2008-02-10 13:22:36 +00:00
2012-01-21 17:21:57 +00:00
res = RegOpenKeyA ( HKEY_CURRENT_USER , " SOFTWARE \\ Wine \\ msitest " , & hkey ) ;
2008-02-10 13:22:36 +00:00
ok ( res = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %d \n " , res ) ;
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 ) ;
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 ) ;
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 ) ;
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 ) ;
RegCloseKey ( hkey ) ;
2012-01-21 17:21:57 +00:00
res = RegDeleteKeyA ( HKEY_CURRENT_USER , " SOFTWARE \\ Wine \\ msitest " ) ;
2008-02-10 13:22:36 +00:00
ok ( res = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %d \n " , res ) ;
/* Remove registry keys written by RegisterProduct standard action */
2012-01-21 17:21:57 +00:00
res = delete_key_portable ( HKEY_LOCAL_MACHINE ,
" SOFTWARE \\ Microsoft \\ Windows \\ CurrentVersion \\ Uninstall \\ {837450fa-a39b-4bc8-b321-08b393f784b3} " ,
KEY_WOW64_32KEY ) ;
2008-02-10 13:22:36 +00:00
ok ( res = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %d \n " , res ) ;
2012-01-21 17:21:57 +00:00
res = delete_key_portable ( HKEY_LOCAL_MACHINE ,
" SOFTWARE \\ Microsoft \\ Windows \\ CurrentVersion \\ Installer \\ UpgradeCodes \\ D8E760ECA1E276347B43E42BDBDA5656 " , access ) ;
2008-02-10 13:22:36 +00:00
ok ( res = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %d \n " , res ) ;
2012-01-21 17:21:57 +00:00
res = find_registry_key ( HKEY_LOCAL_MACHINE ,
" SOFTWARE \\ Microsoft \\ Windows \\ CurrentVersion \\ Installer \\ UserData " , " af054738b93a8cb43b12803b397f483b " , access , & hkey ) ;
ok ( res = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %d \n " , res ) ;
2009-05-17 07:05:22 +00:00
2012-01-21 17:21:57 +00:00
res = delete_registry_key ( hkey , " af054738b93a8cb43b12803b397f483b " , access ) ;
ok ( res = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %d \n " , res ) ;
RegCloseKey ( hkey ) ;
res = delete_key_portable ( HKEY_LOCAL_MACHINE ,
" SOFTWARE \\ Microsoft \\ Windows \\ CurrentVersion \\ Installer \\ Products \\ af054738b93a8cb43b12803b397f483b " , access ) ;
ok ( res = = ERROR_FILE_NOT_FOUND , " Expected ERROR_FILE_NOT_FOUND, got %d \n " , res ) ;
2008-02-10 13:22:36 +00:00
/* Remove registry keys written by PublishProduct standard action */
2014-04-23 14:49:34 +00:00
res = RegOpenKeyA ( HKEY_CURRENT_USER , " SOFTWARE \\ Microsoft \\ Installer " , & hkey ) ;
2008-02-10 13:22:36 +00:00
ok ( res = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %d \n " , res ) ;
2012-01-21 17:21:57 +00:00
res = delete_registry_key ( hkey , " Products \\ af054738b93a8cb43b12803b397f483b " , KEY_ALL_ACCESS ) ;
2008-02-10 13:22:36 +00:00
ok ( res = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %d \n " , res ) ;
res = RegDeleteKeyA ( hkey , " UpgradeCodes \\ D8E760ECA1E276347B43E42BDBDA5656 " ) ;
ok ( res = = ERROR_SUCCESS , " Expected ERROR_SUCCESS, got %d \n " , res ) ;
RegCloseKey ( hkey ) ;
2012-01-21 17:21:57 +00:00
/* Delete installation files we created */
2008-02-10 13:22:36 +00:00
delete_test_files ( ) ;
}
static void test_Installer ( void )
{
2014-04-23 14:49:34 +00:00
static const WCHAR szCreateRecordException [ ] = { ' C ' , ' r ' , ' e ' , ' a ' , ' t ' , ' e ' , ' R ' , ' e ' , ' c ' , ' o ' , ' r ' , ' d ' , ' , ' , ' C ' , ' o ' , ' u ' , ' n ' , ' t ' , 0 } ;
static const WCHAR szIntegerDataException [ ] = { ' I ' , ' n ' , ' t ' , ' e ' , ' g ' , ' e ' , ' r ' , ' D ' , ' a ' , ' t ' , ' a ' , ' , ' , ' F ' , ' i ' , ' e ' , ' l ' , ' d ' , 0 } ;
2008-02-10 13:22:36 +00:00
WCHAR szPath [ MAX_PATH ] ;
HRESULT hr ;
IDispatch * pSession = NULL , * pDatabase = NULL , * pRecord = NULL , * pStringList = NULL ;
int iValue , iCount ;
if ( ! pInstaller ) return ;
/* Installer::CreateRecord */
/* 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 ) ;
ok ( hr = = S_OK , " Installer_CreateRecord failed, hresult 0x%08x \n " , hr ) ;
ok ( pRecord ! = NULL , " Installer_CreateRecord should not have returned NULL record \n " ) ;
if ( pRecord )
{
/* Record::FieldCountGet */
hr = Record_FieldCountGet ( pRecord , & iValue ) ;
ok ( hr = = S_OK , " Record_FiledCountGet failed, hresult 0x%08x \n " , hr ) ;
ok ( iValue = = 1 , " Record_FieldCountGet result was %d but expected 1 \n " , iValue ) ;
/* Record::IntegerDataGet */
hr = Record_IntegerDataGet ( pRecord , 1 , & iValue ) ;
ok ( hr = = S_OK , " Record_IntegerDataGet failed, hresult 0x%08x \n " , hr ) ;
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 ) ;
ok ( hr = = S_OK , " Record_IntegerDataGet failed, hresult 0x%08x \n " , hr ) ;
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 ) ;
ok ( hr = = S_OK , " Record_IntegerDataPut failed, hresult 0x%08x \n " , hr ) ;
/* 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 ) ;
ok ( hr = = S_OK , " Record_IntegerDataGet failed, hresult 0x%08x \n " , hr ) ;
ok ( iValue = = 100 , " Record_IntegerDataGet result was %d but expected 100 \n " , iValue ) ;
IDispatch_Release ( pRecord ) ;
}
2009-12-22 09:14:17 +00:00
create_package ( szPath ) ;
2008-02-10 13:22:36 +00:00
/* Installer::OpenPackage */
hr = Installer_OpenPackage ( szPath , 0 , & pSession ) ;
2012-01-21 17:21:57 +00:00
if ( hr = = DISP_E_EXCEPTION )
{
skip ( " OpenPackage failed, insufficient rights? \n " ) ;
DeleteFileW ( szPath ) ;
return ;
}
2008-02-10 13:22:36 +00:00
ok ( hr = = S_OK , " Installer_OpenPackage failed, hresult 0x%08x \n " , hr ) ;
if ( hr = = S_OK )
{
test_Session ( pSession ) ;
IDispatch_Release ( pSession ) ;
}
/* Installer::OpenDatabase */
2009-01-18 09:03:44 +00:00
hr = Installer_OpenDatabase ( szPath , ( INT_PTR ) MSIDBOPEN_TRANSACT , & pDatabase ) ;
2008-02-10 13:22:36 +00:00
ok ( hr = = S_OK , " Installer_OpenDatabase failed, hresult 0x%08x \n " , hr ) ;
if ( hr = = S_OK )
{
test_Database ( pDatabase , FALSE ) ;
IDispatch_Release ( pDatabase ) ;
}
/* Installer::RegistryValue */
test_Installer_RegistryValue ( ) ;
/* Installer::ProductState for our product code, which should not be installed */
hr = Installer_ProductState ( szProductCode , & iValue ) ;
ok ( hr = = S_OK , " Installer_ProductState failed, hresult 0x%08x \n " , hr ) ;
ok ( iValue = = INSTALLSTATE_UNKNOWN , " Installer_ProductState returned %d, expected %d \n " , iValue , INSTALLSTATE_UNKNOWN ) ;
/* Installer::ProductInfo for our product code, which should not be installed */
/* Package name */
memset ( szPath , 0 , sizeof ( szPath ) ) ;
hr = Installer_ProductInfo ( szProductCode , WINE_INSTALLPROPERTY_PACKAGENAMEW , szPath ) ;
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 ) ;
/* Installer::Products */
test_Installer_Products ( FALSE ) ;
/* Installer::RelatedProducts for our upgrade code, should not find anything */
hr = Installer_RelatedProducts ( szUpgradeCode , & pStringList ) ;
ok ( hr = = S_OK , " Installer_RelatedProducts failed, hresult 0x%08x \n " , hr ) ;
if ( hr = = S_OK )
{
/* StringList::Count */
hr = StringList_Count ( pStringList , & iCount ) ;
ok ( hr = = S_OK , " StringList_Count failed, hresult 0x%08x \n " , hr ) ;
ok ( ! iCount , " Expected no related products but found %d \n " , iCount ) ;
IDispatch_Release ( pStringList ) ;
}
/* Installer::Version */
memset ( szPath , 0 , sizeof ( szPath ) ) ;
hr = Installer_VersionGet ( szPath ) ;
ok ( hr = = S_OK , " Installer_VersionGet failed, hresult 0x%08x \n " , hr ) ;
/* Installer::InstallProduct and other tests that depend on our product being installed */
test_Installer_InstallProduct ( ) ;
}
START_TEST ( automation )
{
DWORD len ;
char temp_path [ MAX_PATH ] , prev_path [ MAX_PATH ] ;
HRESULT hr ;
CLSID clsid ;
IUnknown * pUnk ;
2012-01-21 17:21:57 +00:00
init_functionpointers ( ) ;
if ( pIsWow64Process )
pIsWow64Process ( GetCurrentProcess ( ) , & is_wow64 ) ;
2008-02-10 13:22:36 +00:00
GetSystemTimeAsFileTime ( & systemtime ) ;
GetCurrentDirectoryA ( MAX_PATH , prev_path ) ;
2014-04-23 14:49:34 +00:00
GetTempPathA ( MAX_PATH , temp_path ) ;
2008-02-10 13:22:36 +00:00
SetCurrentDirectoryA ( temp_path ) ;
lstrcpyA ( CURR_DIR , temp_path ) ;
len = lstrlenA ( CURR_DIR ) ;
if ( len & & ( CURR_DIR [ len - 1 ] = = ' \\ ' ) )
CURR_DIR [ len - 1 ] = 0 ;
get_program_files_dir ( PROG_FILES_DIR ) ;
hr = OleInitialize ( NULL ) ;
ok ( hr = = S_OK , " OleInitialize returned 0x%08x \n " , hr ) ;
hr = CLSIDFromProgID ( szProgId , & clsid ) ;
ok ( hr = = S_OK , " CLSIDFromProgID returned 0x%08x \n " , hr ) ;
hr = CoCreateInstance ( & clsid , NULL , CLSCTX_INPROC_SERVER , & IID_IUnknown , ( void * * ) & pUnk ) ;
ok ( hr = = S_OK , " CoCreateInstance returned 0x%08x \n " , hr ) ;
if ( pUnk )
{
hr = IUnknown_QueryInterface ( pUnk , & IID_IDispatch , ( void * * ) & pInstaller ) ;
ok ( hr = = S_OK , " IUnknown::QueryInterface returned 0x%08x \n " , hr ) ;
test_dispid ( ) ;
test_dispatch ( ) ;
test_Installer ( ) ;
IDispatch_Release ( pInstaller ) ;
IUnknown_Release ( pUnk ) ;
}
OleUninitialize ( ) ;
SetCurrentDirectoryA ( prev_path ) ;
}