windows-nt/Source/XPSP1/NT/base/fs/hsm/gui/rsoptcom/optcom.cpp
2020-09-26 16:20:57 +08:00

754 lines
17 KiB
C++

/*++
© 1998 Seagate Software, Inc. All rights reserved.
Module Name:
OptCom.cpp
Abstract:
Base Class for optional component work.
Author:
Rohde Wakefield [rohde] 09-Oct-1997
Revision History:
--*/
#include "stdafx.h"
#include "rsoptcom.h"
#include "OptCom.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CRsOptCom::CRsOptCom()
{
TRACEFN( "CRsOptCom::CRsOptCom" );
}
CRsOptCom::~CRsOptCom()
{
TRACEFN( "CRsOptCom::CRsOptCom" );
}
DWORD
CRsOptCom::SetupProc(
IN LPCVOID /*ComponentId*/,
IN LPCVOID SubcomponentId,
IN UINT Function,
IN UINT_PTR Param1,
IN OUT PVOID Param2
)
{
TRACEFN( "CRsOptCom::SetupProc" );
TRACE( L"Function = <%ls><%p>", StringFromFunction( Function ), Function );
SHORT subcomponentId = IdFromString( (LPCTSTR)SubcomponentId );
DWORD dwRet = 0;
switch( Function ) {
case OC_PREINITIALIZE:
dwRet = PreInitialize( (DWORD)Param1 );
break;
case OC_INIT_COMPONENT:
dwRet = InitComponent( (PSETUP_INIT_COMPONENT)Param2 );
break;
case OC_SET_LANGUAGE:
dwRet = (DWORD)SetLanguage( (WORD)Param1 );
break;
#ifndef _WIN64
case OC_QUERY_IMAGE:
// Note: The casting of the return value from HBITMAP to DWORD is broken on IA64,
// however, Setup avoids calling with OC_QUERY_IMAGE on IA64, rather it uses OC_QUERY_IMAGE_EX
dwRet = (DWORD)QueryImage( subcomponentId, (SubComponentInfo)Param1, LOWORD(Param2), HIWORD(Param2) );
break;
#endif
#ifdef _WIN64
case OC_QUERY_IMAGE_EX:
dwRet = (DWORD)QueryImageEx( subcomponentId, (OC_QUERY_IMAGE_INFO *)Param1, (HBITMAP *)Param2 );
break;
#endif
case OC_REQUEST_PAGES:
dwRet = (DWORD)RequestPages( (WizardPagesType)Param1, (PSETUP_REQUEST_PAGES)Param2 );
break;
case OC_QUERY_CHANGE_SEL_STATE:
dwRet = (DWORD)QueryChangeSelState( subcomponentId, Param1 != 0, (ULONG)((ULONG_PTR)Param2) );
break;
case OC_CALC_DISK_SPACE:
dwRet = CalcDiskSpace( subcomponentId, Param1 != 0, (HDSKSPC)Param2 );
break;
case OC_QUEUE_FILE_OPS:
dwRet = QueueFileOps( subcomponentId, (HSPFILEQ)Param2 );
break;
case OC_QUERY_STEP_COUNT:
dwRet = (DWORD)QueryStepCount( subcomponentId );
break;
case OC_COMPLETE_INSTALLATION:
dwRet = CompleteInstallation( subcomponentId );
break;
case OC_CLEANUP:
CleanUp( );
break;
case OC_ABOUT_TO_COMMIT_QUEUE:
dwRet = AboutToCommitQueue( subcomponentId );
break;
case OC_QUERY_SKIP_PAGE:
dwRet = (DWORD)QuerySkipPage( (OcManagerPage)Param1 );
break;
case OC_QUERY_STATE:
dwRet = (DWORD)QueryState( subcomponentId );
break;
case OC_NOTIFICATION_FROM_QUEUE:
case OC_NEED_MEDIA:
case OC_WIZARD_CREATED:
break;
default:
break;
}
return( dwRet );
}
DWORD
CRsOptCom::PreInitialize(
IN DWORD /*Flags*/
)
{
TRACEFNDW( "CRsOptCom::PreInitialize" );
#ifdef UNICODE
dwRet = OCFLAG_UNICODE;
#else
dwRet = OCFLAG_ANSI;
#endif
return( dwRet );
}
DWORD
CRsOptCom::InitComponent(
IN PSETUP_INIT_COMPONENT SetupInitComponent )
{
TRACEFNDW( "CRsOptCom::InitComponent" );
dwRet = NO_ERROR;
m_OCManagerVersion = SetupInitComponent->OCManagerVersion;
m_ComponentVersion = SetupInitComponent->ComponentVersion;
m_OCInfHandle = SetupInitComponent->OCInfHandle;
m_ComponentInfHandle = SetupInitComponent->ComponentInfHandle;
m_SetupData = SetupInitComponent->SetupData;
m_HelperRoutines = SetupInitComponent->HelperRoutines;
return( dwRet );
}
SubComponentState
CRsOptCom::DetectInitialState(
IN SHORT /*SubcomponentId*/
)
{
TRACEFN( "CRsOptCom::DetectInitialState" );
SubComponentState retval = SubcompUseOcManagerDefault;
return( retval );
}
SubComponentState
CRsOptCom::QueryState(
IN SHORT /*SubcomponentId*/
)
{
TRACEFN( "CRsOptCom::QueryState" );
SubComponentState retval = SubcompUseOcManagerDefault;
return( retval );
}
BOOL
CRsOptCom::SetLanguage(
WORD /*LangId*/
)
{
TRACEFNBOOL( "CRsOptCom::SetLanguage" );
boolRet = TRUE;
return( boolRet );
}
HBITMAP
CRsOptCom::QueryImage(
IN SHORT /*SubcomponentId*/,
IN SubComponentInfo /*WhichImage*/,
IN WORD /*Width*/,
IN WORD /*Height*/
)
{
TRACEFN( "CRsOptCom::QueryImage" );
HBITMAP retval = 0;
return( retval );
}
BOOL
CRsOptCom::QueryImageEx(
IN SHORT /*SubcomponentId*/,
IN OC_QUERY_IMAGE_INFO* /*pQueryImageInfo*/,
OUT HBITMAP *phBitmap
)
{
TRACEFNBOOL( "CRsOptCom::QueryImageEx" );
if (phBitmap) {
*phBitmap = NULL;
}
boolRet = FALSE;
return( boolRet );
}
LONG
CRsOptCom::RequestPages(
IN WizardPagesType /*Type*/,
IN OUT PSETUP_REQUEST_PAGES /*RequestPages*/
)
{
TRACEFNLONG( "CRsOptCom::RequestPages" );
lRet = 0;
return( lRet );
}
BOOL
CRsOptCom::QuerySkipPage(
IN OcManagerPage /*Page*/
)
{
TRACEFNBOOL( "CRsOptCom::QuerySkipPage" );
boolRet = FALSE;
return( boolRet );
}
BOOL
CRsOptCom::QueryChangeSelState(
IN SHORT /*SubcomponentId*/,
IN BOOL /*NewState*/,
IN DWORD /*Flags*/
)
{
TRACEFNBOOL( "CRsOptCom::QueryChangeSelState" );
boolRet = TRUE;
return( boolRet );
}
DWORD
CRsOptCom::CalcDiskSpace(
IN SHORT /*SubcomponentId*/,
IN BOOL /*AddSpace*/,
IN HDSKSPC /*hDiskSpace*/
)
{
TRACEFNDW( "CRsOptCom::CalcDiskSpace" );
dwRet = 0;
return( dwRet );
}
DWORD
CRsOptCom::QueueFileOps(
IN SHORT /*SubcomponentId*/,
IN HSPFILEQ /*hFileQueue*/
)
{
TRACEFNDW( "CRsOptCom::QueueFileOps" );
dwRet = 0;
return( dwRet );
}
LONG
CRsOptCom::QueryStepCount(
IN SHORT /*SubcomponentId*/
)
{
TRACEFNLONG( "CRsOptCom::QueryStepCount" );
lRet = 0;
return( lRet );
}
DWORD
CRsOptCom::AboutToCommitQueue(
IN SHORT /*SubcomponentId*/
)
{
TRACEFNDW( "CRsOptCom::AboutToCommitQueue" );
dwRet = 0;
return( dwRet );
}
DWORD
CRsOptCom::CompleteInstallation(
IN SHORT /*SubcomponentId*/
)
{
TRACEFNDW( "CRsOptCom::CompleteInstallation" );
dwRet = 0;
return( dwRet );
}
void
CRsOptCom::CleanUp(
void
)
{
TRACEFN( "CRsOptCom::CleanUp" );
}
DWORD
CRsOptCom::DoCalcDiskSpace(
IN BOOL AddSpace,
IN HDSKSPC hDiskSpace,
IN LPCTSTR SectionName
)
{
TRACEFNDW( "CRsOptCom::DoCalcDiskSpace" );
dwRet = NO_ERROR;
HINF hLayoutInf = SetupOpenInfFile( L"layout.inf", 0, INF_STYLE_WIN4 | INF_STYLE_OLDNT , 0 );
if( INVALID_HANDLE_VALUE == hLayoutInf) {
dwRet = GetLastError( );
TRACE( _T("CRsOptCom::AboutToCommitQueue Error opening LAYOUT.INF") );
}
if( NO_ERROR == dwRet ) {
if( AddSpace ) {
if( SetupAddInstallSectionToDiskSpaceList( hDiskSpace, m_ComponentInfHandle, hLayoutInf, SectionName, 0, 0 ) ) {
dwRet = GetLastError( );
}
} else {
if ( SetupRemoveInstallSectionFromDiskSpaceList( hDiskSpace, m_ComponentInfHandle, hLayoutInf, SectionName, 0, 0 ) ) {
dwRet = GetLastError( );
}
}
}
if( INVALID_HANDLE_VALUE != hLayoutInf) {
SetupCloseInfFile( hLayoutInf );
}
return( dwRet );
}
DWORD
CRsOptCom::DoQueueFileOps(
IN SHORT SubcomponentId,
IN HSPFILEQ hFileQueue,
IN LPCTSTR InstallSectionName,
IN LPCTSTR UninstallSectionName
)
{
TRACEFNDW( "CRsOptCom::DoQueueFileOps" );
BOOL success = TRUE;
RSOPTCOM_ACTION action = GetSubAction( SubcomponentId );
switch( action ) {
case ACTION_INSTALL:
success = SetupInstallFilesFromInfSection( m_ComponentInfHandle, 0, hFileQueue, InstallSectionName, 0, SP_COPY_FORCE_NEWER );
break;
case ACTION_UNINSTALL:
success = SetupInstallFilesFromInfSection( m_ComponentInfHandle, 0, hFileQueue, UninstallSectionName, 0, 0 );
break;
case ACTION_UPGRADE:
success = SetupInstallFilesFromInfSection( m_ComponentInfHandle, 0, hFileQueue, InstallSectionName, 0, SP_COPY_FORCE_NEWER );
break;
}
dwRet = success ? NO_ERROR : GetLastError( );
return( dwRet );
}
DWORD
CRsOptCom::DoRegistryOps(
IN SHORT SubcomponentId,
IN RSOPTCOM_ACTION actionForReg,
IN LPCTSTR SectionName
)
{
TRACEFNDW( "CRsOptCom::DoRegistryOps" );
BOOL success = TRUE;
RSOPTCOM_ACTION action = GetSubAction( SubcomponentId );
if ( action == actionForReg ) {
success = SetupInstallFromInfSection(
NULL, m_ComponentInfHandle, SectionName,
SPINST_REGISTRY, NULL, NULL,
0, NULL, NULL, NULL, NULL );
}
dwRet = success ? NO_ERROR : GetLastError( );
return( dwRet );
}
LPCWSTR
CRsOptCom::StringFromFunction(
UINT Function
)
{
#define CASE_FUNCTION( a ) case a: return( OLESTR( #a ) );
switch( Function ) {
CASE_FUNCTION( OC_PREINITIALIZE )
CASE_FUNCTION( OC_INIT_COMPONENT )
CASE_FUNCTION( OC_SET_LANGUAGE )
CASE_FUNCTION( OC_QUERY_IMAGE )
CASE_FUNCTION( OC_REQUEST_PAGES )
CASE_FUNCTION( OC_QUERY_CHANGE_SEL_STATE )
CASE_FUNCTION( OC_CALC_DISK_SPACE )
CASE_FUNCTION( OC_QUEUE_FILE_OPS )
CASE_FUNCTION( OC_NOTIFICATION_FROM_QUEUE )
CASE_FUNCTION( OC_QUERY_STEP_COUNT )
CASE_FUNCTION( OC_COMPLETE_INSTALLATION )
CASE_FUNCTION( OC_CLEANUP )
CASE_FUNCTION( OC_QUERY_STATE )
CASE_FUNCTION( OC_NEED_MEDIA )
CASE_FUNCTION( OC_ABOUT_TO_COMMIT_QUEUE )
CASE_FUNCTION( OC_QUERY_SKIP_PAGE )
CASE_FUNCTION( OC_WIZARD_CREATED )
}
return( TEXT( "Unknown" ) );
}
LPCWSTR
CRsOptCom::StringFromPageType(
WizardPagesType PageType
)
{
#define CASE_PAGETYPE( a ) case a: return( OLESTR( #a ) );
switch( PageType ) {
CASE_PAGETYPE( WizPagesWelcome )
CASE_PAGETYPE( WizPagesMode )
CASE_PAGETYPE( WizPagesEarly )
CASE_PAGETYPE( WizPagesPrenet )
CASE_PAGETYPE( WizPagesPostnet )
CASE_PAGETYPE( WizPagesLate )
CASE_PAGETYPE( WizPagesFinal )
CASE_PAGETYPE( WizPagesTypeMax )
}
return( TEXT( "Unknown" ) );
}
LPCWSTR
CRsOptCom::StringFromAction(
RSOPTCOM_ACTION Action
)
{
#define CASE_ACTION( a ) case a: return( OLESTR( #a ) );
switch( Action ) {
CASE_ACTION( ACTION_NONE )
CASE_ACTION( ACTION_INSTALL )
CASE_ACTION( ACTION_UNINSTALL )
CASE_ACTION( ACTION_REINSTALL )
CASE_ACTION( ACTION_UPGRADE )
}
return( TEXT( "Unknown" ) );
}
RSOPTCOM_ACTION
CRsOptCom::GetSubAction(
SHORT SubcomponentId
)
{
TRACEFN( "CRsOptCom::GetSubAction" );
RSOPTCOM_ACTION retval = ACTION_NONE;
UINT setupMode = GetSetupMode( );
DWORDLONG operationFlags = m_SetupData.OperationFlags;
BOOL originalState = QuerySelectionState( SubcomponentId, OCSELSTATETYPE_ORIGINAL );
BOOL currentState = QuerySelectionState( SubcomponentId, OCSELSTATETYPE_CURRENT );
if( !originalState && currentState ) {
retval = ACTION_INSTALL;
} else if( originalState && !currentState ) {
retval = ACTION_UNINSTALL;
} else if( ( SETUPOP_NTUPGRADE & operationFlags ) && originalState && currentState ) {
retval = ACTION_UPGRADE;
}
TRACE( L"SubcomponentId = <%hd>, originalState = <%hs>, currentState = <%hs>", SubcomponentId, RsBoolAsString( originalState ), RsBoolAsString( currentState ) );
TRACE( L"OperationsFlags = <0x%0.16I64x>, setupMode = <0x%p>", operationFlags, setupMode );
TRACE( L"retval = <%ls>", StringFromAction( retval ) );
return( retval );
}
HRESULT
CRsOptCom::CreateLink(
LPCTSTR lpszProgram,
LPCTSTR lpszArgs,
LPTSTR lpszLink,
LPCTSTR lpszDir,
LPCTSTR lpszDesc,
int nItemDescId,
int nDescId,
LPCTSTR lpszIconPath,
int iIconIndex
)
{
TRACEFNHR( "CRsOptCom::CreateLink" );
CComPtr<IShellLink> pShellLink;
TCHAR szSystemPath[MAX_PATH];
TCHAR szResourceString[MAX_PATH+128];
UINT uLen = 0;
szSystemPath[0] = _T('\0');
szResourceString[0] = _T('\0');
// CoInitialize must be called before this
// Get a pointer to the IShellLink interface.
hrRet = CoInitialize( 0 );
if( SUCCEEDED( hrRet ) ) {
hrRet = CoCreateInstance( CLSID_ShellLink, 0, CLSCTX_SERVER, IID_IShellLink, (void**)&pShellLink );
if( SUCCEEDED( hrRet ) ) {
CComPtr<IPersistFile> pPersistFile;
// Set the path to the shortcut target, and add the description.
pShellLink->SetPath( lpszProgram );
pShellLink->SetArguments( lpszArgs );
pShellLink->SetWorkingDirectory( lpszDir );
pShellLink->SetIconLocation( lpszIconPath, iIconIndex );
// Description should be set using the resource id in order to support MUI
uLen = GetSystemDirectory(szSystemPath, MAX_PATH);
if ((uLen > 0) && (uLen < MAX_PATH)) {
wsprintf(szResourceString, TEXT("@%s\\setup\\RsOptCom.dll,-%d"), szSystemPath, nDescId);
pShellLink->SetDescription(szResourceString);
} else {
// Set English description
pShellLink->SetDescription(lpszDesc);
}
// Query IShellLink for the IPersistFile interface for saving the
// shortcut in persistent storage.
hrRet = pShellLink->QueryInterface( IID_IPersistFile, (void**)&pPersistFile );
if( SUCCEEDED( hrRet ) ) {
CComBSTR wsz = lpszLink;
// Save the link by calling IPersistFile::Save.
hrRet = pPersistFile->Save( wsz, TRUE );
if( SUCCEEDED(hrRet) && (uLen > 0) && (uLen < MAX_PATH)) {
// Shortcut created - set MUI name.
wsprintf(szResourceString, TEXT("%s\\setup\\RsOptCom.dll"), szSystemPath);
hrRet = SHSetLocalizedName(lpszLink, szResourceString, nItemDescId);
}
}
}
CoUninitialize();
}
return( hrRet );
}
BOOL
CRsOptCom::DeleteLink(
LPTSTR lpszShortcut
)
{
TRACEFNBOOL( "CRsOptCom::DeleteLink" );
boolRet = TRUE;
TCHAR szFile[_MAX_PATH];
SHFILEOPSTRUCT fos;
ZeroMemory( szFile, sizeof(szFile) );
lstrcpy( szFile, lpszShortcut );
if( DoesFileExist( szFile ) ) {
ZeroMemory( &fos, sizeof(fos) );
fos.hwnd = NULL;
fos.wFunc = FO_DELETE;
fos.pFrom = szFile;
fos.fFlags = FOF_SILENT | FOF_NOCONFIRMATION;
SHFileOperation( &fos );
}
return( boolRet );
}
HRESULT
CRsOptCom::GetGroupPath(
int nFolder,
LPTSTR szPath
)
{
TRACEFNHR( "CRsOptCom::GetGroupPath" );
szPath[0] = _T('\0');
hrRet = SHGetFolderPath( 0, nFolder | CSIDL_FLAG_CREATE, 0, 0, szPath );
TRACE( L"szPath = <%ls>", szPath );
return( hrRet );
}
void
CRsOptCom::AddItem(
int nFolder,
LPCTSTR szItemDesc,
LPCTSTR szProgram,
LPCTSTR szArgs,
LPCTSTR szDir,
LPCTSTR szDesc,
int nItemDescId,
int nDescId,
LPCTSTR szIconPath,
int iIconIndex
)
{
TRACEFN( "CRsOptCom::AddItem" );
TCHAR szPath[_MAX_PATH];
if( S_OK == GetGroupPath( nFolder, szPath ) ) {
lstrcat( szPath, _T("\\") );
lstrcat( szPath, szItemDesc );
lstrcat( szPath, _T(".lnk") );
CreateLink( szProgram, szArgs, szPath, szDir, szDesc, nItemDescId, nDescId, szIconPath, iIconIndex );
}
}
void
CRsOptCom::DeleteItem(
int nFolder,
LPCTSTR szAppName
)
{
TRACEFN( "CRsOptCom::DeleteItem" );
TCHAR szPath[_MAX_PATH];
if( S_OK == GetGroupPath( nFolder, szPath ) ) {
lstrcat( szPath, _T("\\") );
lstrcat( szPath, szAppName );
lstrcat( szPath, _T(".lnk") );
DeleteLink( szPath );
}
}
typedef
HRESULT
(WINAPI *PFN_DLLENTRYPOINT)(
void
);
HRESULT
CRsOptCom::CallDllEntryPoint(
LPCTSTR pszDLLName,
LPCSTR pszEntryPoint
)
{
TRACEFNHR( "CRsOptCom::CallDllEntryPoint" );
TRACE( _T("Dll <%s> Func <%hs>"), pszDLLName, pszEntryPoint );
HINSTANCE hDLL = 0;
PFN_DLLENTRYPOINT pfnEntryPoint;
try {
hDLL = LoadLibrary( pszDLLName );
RsOptAffirmStatus( hDLL );
pfnEntryPoint = (PFN_DLLENTRYPOINT)GetProcAddress( hDLL, pszEntryPoint );
RsOptAffirmStatus( pfnEntryPoint );
hrRet = pfnEntryPoint();
} RsOptCatch( hrRet );
if( hDLL ) FreeLibrary( hDLL );
return( hrRet );
}