windows-nt/Source/XPSP1/NT/inetsrv/query/setupqry/setupqry.cxx
2020-09-26 16:20:57 +08:00

2931 lines
84 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1997 - 2000.
//
// File: setupqry.cxx
//
// Contents: Indexing Service ocmgr installation routines
//
// Wish-list: Seek and destroy old webhits.exe files
// Migrate all existing catalogs + virtual server catalogs
//
// History: 8-Jan-97 dlee Created
// 7-7-97 mohamedn changed to work with NT setup.
//
//--------------------------------------------------------------------------
#include "pch.cxx"
#pragma hdrstop
#include <xolemem.hxx>
#include "catcnfg.hxx"
DECLARE_INFOLEVEL( is )
#define COPY_FILES_EVEN_IF_INSTALLED
extern "C" ULONG DbgPrint( LPSTR Format, ... );
//
// external exported routines.
//
extern "C"
{
BOOL WINAPI DllMain( IN HANDLE DllHandle,
IN DWORD Reason,
IN LPVOID Reserved );
DWORD IndexSrv( IN LPCWSTR ComponentId,
IN LPCWSTR SubcomponentId,
IN UINT Function,
IN UINT Param1,
IN OUT PVOID Param2 );
}
//
// DLL module instance handle
//
HINSTANCE MyModuleHandle;
//
// Utility routines
//
void GetPreviousISSetupVersion(void);
DWORD CompleteInstallation(CError &Err);
DWORD QueueConfigurationParams( HINF hInf,
HSPFILEQ Param2,
WCHAR const * pwszSectionName,
CError &Err );
DWORD SetDefaultCatalog(CError &Err);
void UpgradeIS1toIS3(CError & Err);
DWORD SetFilterRegistryInfo( BOOL fUnRegister,CError &Err );
DWORD SetDLLsToRegister(CError & Err);
void ExcludeSpecialLocations( CCatalogConfig & Cat );
void OcCleanup( CError & Err );
void SetupW3Svc(CError &Err);
void DeleteNTOPStartMenu();
DWORD AddPerfData( CError &Err );
DWORD RemovePerfData(void);
DWORD LoadCounterAndDelete( WCHAR const * pwcINI,
WCHAR const * pwcH,
CError &Err );
void CreateSharedDllRegSubKey(void);
DWORD AddRefSharedDll( WCHAR const * pwszDllName );
WCHAR * AppendMultiSZString(WCHAR * pwcTo, WCHAR const * pwcFrom );
DWORD RegisterDll(WCHAR const * pwcDLL, CError &Err );
BOOL IsSufficientMemory(void);
void AddCiSvc(CError &Err);
DWORD RenameCiSvc( SC_HANDLE hSC, CError &Err );
void StopService( WCHAR const * pwszServiceName );
void StartService( WCHAR const * pwszServiceName );
void MyStartService( CServiceHandle & xSC,
WCHAR const * pwcSVC );
BOOL MyStopService( CServiceHandle & xSC,
WCHAR const * pwcSVC,
BOOL & fStopped );
void DeleteService( WCHAR const * pwszServiceName );
DWORD SetRegBasedOnMachine(CError &Err);
DWORD SetRegBasedOnArchitecture(CError &Err);
void GetMachineInfo(BOOL & fLotsOfMem, DWORD & cCPU );
void DeleteShellLink( WCHAR const * pwcGroup,
WCHAR const * pwcName );
//
// hardcoded globals, obtained from is30.INF file
//
// [indexsrv]
INT g_MajorVersion = 3;
INT g_dwPrevISVersion = 0;
BOOL g_fNT4_To_NT5_Upgrade = FALSE;
BOOL g_fIS1x_To_NT5_Upgrade = FALSE;
BOOL g_fCiSvcWasRunning = FALSE;
BOOL g_fCiSvcIsRequested = FALSE;
WCHAR g_awcSystemDir[MAX_PATH]; // system32 directory
WCHAR g_awcSourcePath[MAX_PATH * 2]; // inf source location.
WCHAR g_awcIS1Path[MAX_PATH+1];
OCMANAGER_ROUTINES g_HelperRoutines;
//
// globals needed for OCM
//
SETUP_INIT_COMPONENT gSetupInitComponent;
BOOL g_fBatchInstall = FALSE;
BOOL g_fInstallCancelled = TRUE; // Similar to aborted, but caused by user cancel, not internal exception
BOOL g_fInstallAborted = FALSE;
BOOL g_fComponentInitialized = FALSE;
BOOL g_fUnattended = FALSE;
BOOL g_fUpgrade = FALSE;
BOOL g_fNtGuiMode = TRUE;
DWORD g_NtType = -1;
BOOL g_fLocallyOpened = FALSE;
WCHAR g_awcProfilePath[MAX_PATH];
//
// keep track if we're selected or not selected
//
BOOL g_fFalseAlready = FALSE;
unsigned g_cChangeSelection = 0;
//
// frequently used constants
//
const WCHAR wcsIndexsrvSystem[] = L"indexsrv_system";
//
// frequently used registry keys.
//
const WCHAR wcsRegAdminSubKey[] =
L"System\\CurrentControlSet\\Control\\ContentIndex";
const WCHAR wcsRegCatalogsSubKey[] =
L"System\\CurrentControlSet\\Control\\ContentIndex\\Catalogs";
const WCHAR wcsRegCatalogsWebSubKey[] =
L"System\\CurrentControlSet\\Control\\ContentIndex\\Catalogs\\web";
const WCHAR wcsRegCatalogsWebPropertiesSubKey[] =
L"System\\CurrentControlSet\\Control\\ContentIndex\\Catalogs\\web\\properties";
const WCHAR wcsAllowedPaths[] =
L"System\\CurrentControlSet\\Control\\SecurePipeServers\\winreg\\AllowedPaths";
const WCHAR wcsPreventCisvcParam[] = L"DonotStartCiSvc";
const WCHAR wcsISDefaultCatalogDirectory[] = L"IsapiDefaultCatalogDirectory";
const WCHAR wszRegProfileKey[] =
L"Software\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList";
const WCHAR wszRegProfileValue[] = L"ProfilesDirectory";
const WCHAR wszProperties[] = L"properties";
//
// Directory name where system catalog will be placed
//
const WCHAR wszSysVolInfoDirectory[] = L"x:\\System Volume Information";
//
// Array of Dlls to register
//
static WCHAR * apwcDlls[] = {
L"query.dll",
L"ciadmin.dll",
L"ixsso.dll",
L"nlhtml.dll",
L"offfilt.dll",
L"ciodm.dll",
L"infosoft.dll",
L"mimefilt.dll",
L"LangWrbk.dll",
};
const int cDlls = NUMELEM( apwcDlls );
static WCHAR * apwcOldDlls[] = {
L"cifrmwrk.dll",
L"fsci.dll",
};
const int cOldDlls = NUMELEM( apwcOldDlls );
//
// utility routines
//
BOOL OpenInfFile(CError & Err);
CError::CError( )
{
SetupOpenLog(FALSE); /* don't overwrite existing log file */
}
CError::~CError( )
{
SetupCloseLog();
}
//+-------------------------------------------------------------------------
//
// Member: CError::Report
//
// Synopsis: reports a message to various destinations
//
// Arguments: [LogSeverity] -- message severity
// [dwErr] -- The error code
// [MessageString]-- printf format string for message
// [...] -- variable arguments for message params
//
// Returns: none. don't throw.
//
// History: 2-9-98 mohamedn
//
//--------------------------------------------------------------------------
void CError::Report(
LogSeverity Severity,
DWORD dwErr,
WCHAR const * MessageString,
...)
{
WCHAR awcMsgTemp[MAX_PATH * 2];
awcMsgTemp[0] = _awcMsg[0] = L'\0';
va_list va;
va_start(va, MessageString);
wvsprintf(awcMsgTemp, MessageString, va);
va_end(va);
// prepend on Our modules information.
wsprintf(_awcMsg, L"setupqry: (%#x) %s\r\n", dwErr, awcMsgTemp);
if ( !SetupLogError(_awcMsg, Severity) )
{
isDebugOut(( DEB_ERROR, "SetupLogError Failed: %d\n", GetLastError() ));
}
}
//+-------------------------------------------------------------------------
//
// Function: DllMain
//
// Synopsis: The usual suspect
//
// Return: TRUE - Initialization succeeded
// FALSE - Initialization failed
//
// History: 8-Jan-97 dlee Created
//
//--------------------------------------------------------------------------
BOOL WINAPI DllMain(
IN HANDLE DllHandle,
IN DWORD Reason,
IN LPVOID Reserved )
{
UNREFERENCED_PARAMETER(Reserved);
switch( Reason )
{
WCHAR DllName[MAX_PATH];
case DLL_PROCESS_ATTACH:
MyModuleHandle = (HINSTANCE)DllHandle;
DisableThreadLibraryCalls( MyModuleHandle );
if (!GetModuleFileName(MyModuleHandle, DllName, MAX_PATH) ||
!LoadLibrary( DllName ))
{
return FALSE;
}
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
} //DllMain
//+-------------------------------------------------------------------------
//
// Function: IndexSrv
//
// Synopsis: Called by the ocmgr when things happen
//
// Arguments: ComponentId -- "indexsrv_system"
// SubcomponentId -- the .inf section being operated on
// Function -- the operation
// Param1 -- operation paramater
// Param2 -- operation paramater
//
// Returns: Win32 error code (usually), depends on Function
//
//
//--------------------------------------------------------------------------
DWORD IndexSrv(
IN LPCWSTR ComponentId,
IN LPCWSTR SubcomponentId,
IN UINT Function,
IN UINT Param1,
IN OUT PVOID Param2 )
{
DWORD dwRetVal = NO_ERROR;
isDebugOut(( "IndexSrv, Function %d\n", Function ));
//
// if we're aborted, do nothing.
//
if ( g_fInstallAborted )
return dwRetVal;
CError Err;
CSmartException xSmartException;
TRY
{
switch(Function)
{
case OC_PREINITIALIZE:
isDebugOut(( "OC_PREINITIALIZE\n" ));
GetSystemDirectory( g_awcSystemDir,
sizeof g_awcSystemDir / sizeof WCHAR );
return OCFLAG_UNICODE;
break;
case OC_SET_LANGUAGE:
isDebugOut(( "OC_SET_LANGUAGE\n" ));
//
// Param1 = low 16 bits specify Win32 LANG
// Param2 = unused
//
// Return code is a boolean indicating whether we think we
// support the requested language. We remember the language id
// and say we support the language. A more exact check might involve
// looking through our resources via EnumResourcesLnguages() for
// example, or checking our inf to see whether there is a matching
// or closely matching [strings] section. We don't bother with
// any of that here.
//
// Locate the component and remember the language id for later use.
//
return TRUE;
case OC_INIT_COMPONENT:
isDebugOut(( "OC_INIT_COMPONENT\n" ));
isDebugOut(( DEB_TRACE, "init_component: '%ws'\n", ComponentId ));
if (OCMANAGER_VERSION <= ((PSETUP_INIT_COMPONENT)Param2)->OCManagerVersion)
{
((PSETUP_INIT_COMPONENT)Param2)->ComponentVersion = OCMANAGER_VERSION;
}
else
{
ISError( IS_MSG_INVALID_OCM_VERSION, Err, LogSevFatalError );
isDebugOut(( "wrong ocmgr version!\n" ));
return ERROR_CALL_NOT_IMPLEMENTED;
}
if ( g_fInstallAborted )
{
ISError( IS_MSG_ABORT, Err, LogSevFatalError );
dwRetVal = ERROR_CANCELLED;
break;
}
//
// Param1 = unused
// Param2 = points to SETUP_INIT_COMPONENT structure
//
// Return code is Win32 error indicating outcome.
// ERROR_CANCELLED means this component's install will be aborted.
//
// Even though this call happens once for each component that this
// dll installs, we really only need to do our thing once. This is
// because the data that OCM passes is the same for all calls.
//
if (!g_fComponentInitialized)
{
PSETUP_INIT_COMPONENT InitComponent = (PSETUP_INIT_COMPONENT)Param2;
g_HelperRoutines = InitComponent->HelperRoutines;
CopyMemory( &gSetupInitComponent, (LPVOID)Param2, sizeof(SETUP_INIT_COMPONENT) );
g_fUnattended = (gSetupInitComponent.SetupData.OperationFlags & SETUPOP_BATCH) != 0;
g_fUpgrade = (gSetupInitComponent.SetupData.OperationFlags & SETUPOP_NTUPGRADE) != 0;
g_fNtGuiMode = (gSetupInitComponent.SetupData.OperationFlags & SETUPOP_STANDALONE) == 0;
g_NtType = gSetupInitComponent.SetupData.ProductType;
isDebugOut(( DEB_TRACE, "g_fUnattended: %d\n", g_fUnattended ));
isDebugOut(( DEB_TRACE, "g_fUpgrade: %d\n", g_fUpgrade ));
isDebugOut(( DEB_TRACE, "g_fNtGuiMode: %d\n", g_fNtGuiMode ));
isDebugOut(( DEB_TRACE, "g_NtType: %d\n", g_NtType ));
if (gSetupInitComponent.ComponentInfHandle == NULL)
{
if ( !OpenInfFile(Err) )
{
ISError(IS_MSG_INVALID_INF_HANDLE, Err, LogSevFatalError);
dwRetVal = ERROR_CANCELLED;
}
else
{
g_fComponentInitialized = TRUE;
dwRetVal = NO_ERROR;
}
}
//
// determine if this an NT4-->NT5 upgrade
//
GetPreviousISSetupVersion();
if ( g_dwPrevISVersion > 0 && g_dwPrevISVersion < g_MajorVersion )
{
g_fNT4_To_NT5_Upgrade = TRUE;
// g_dwPrevIsVersion is 0 if the ContentIndex key doesn't exist
if ( 1 == g_dwPrevISVersion )
g_fIS1x_To_NT5_Upgrade = TRUE;
}
}
break;
case OC_QUERY_STATE:
isDebugOut(( "OC_QUERY_STATE\n" ));
if ( !SubcomponentId || _wcsicmp(SubcomponentId,wcsIndexsrvSystem) )
return NO_ERROR;
//
// We can't return SubcompUseOcManagerDefault if 1.x is installed
// the ocmgr registry key for index server won't be set if 1.x was
// installed using the non-ocmgr installation. In this case, check
// if the ContentIndex key exists and if so return SubcompOn.
//
if ( ( OCSELSTATETYPE_ORIGINAL == Param1 ) && g_fIS1x_To_NT5_Upgrade )
{
isDebugOut(( "Upgrading from 1.x to NT 5, turning on IS by default\n" ));
isDebugOut(( DEB_ITRACE, "Upgrading from 1.x to NT 5, turning on IS by default\n" ));
dwRetVal = SubcompOn;
}
else
dwRetVal = SubcompUseOcManagerDefault;
break;
case OC_REQUEST_PAGES:
isDebugOut(( "OC_REQUEST_PAGES\n" ));
return 0; // no pages
// break;
case OC_QUERY_CHANGE_SEL_STATE:
isDebugOut(( "OC_QUERY_CHANGE_SEL_STATE\n" ));
isDebugOut(( "queryChangeSelState %#x, %#x, %#x\n", SubcomponentId, Param1, Param2 ));
if ( !SubcomponentId || _wcsicmp(SubcomponentId,wcsIndexsrvSystem) )
{
return NO_ERROR;
}
if ( Param1 == 0 )
{
//
// we're not selected
//
if ( 0 == g_cChangeSelection || !g_fFalseAlready )
{
g_cChangeSelection++;
g_fFalseAlready = TRUE;
}
g_fCiSvcIsRequested = FALSE;
}
else
{
//
// we are selected
//
if ( 0 == g_cChangeSelection || g_fFalseAlready )
{
g_cChangeSelection++;
g_fFalseAlready = FALSE;
}
g_fCiSvcIsRequested = TRUE;
}
dwRetVal = TRUE;
break;
case OC_CALC_DISK_SPACE:
isDebugOut(( "OC_CALC_DISK_SPACE\n" ));
//
// skip, no files are copied.
//
if ( NO_ERROR != dwRetVal )
{
isDebugOut(( DEB_ERROR, "Calc Disk Space Failed: %d\n", dwRetVal ));
ISError( IS_MSG_CALC_DISK_SPACE_FAILED, Err, LogSevError );
}
break;
case OC_QUEUE_FILE_OPS:
isDebugOut(( "OC_QUEUE_FILE_OPS\n" ));
//
// Param1 = unused
// Param2 = HSPFILEQ to operate on
//
// Return value is Win32 error code indicating outcome.
//
// OC Manager calls this routine when it is ready for files to be
// copied to effect the changes the user requested. The component
// DLL must figure out whether it is being installed or uninstalled
// and take appropriate action.
// For this sample, we look in the private data section for this
// component/subcomponent pair, and get the name of an uninstall
// section for the uninstall case.
//
// Note that OC Manager calls us once for the *entire* component
// and then once per subcomponent.
//
if ( NO_ERROR != dwRetVal )
{
isDebugOut(( DEB_ERROR, "Queue File Operations Failed: %d\n", dwRetVal ));
ISError( IS_MSG_QUEUE_FILE_OPS_FAILED, Err, LogSevError );
}
break;
case OC_QUERY_STEP_COUNT:
isDebugOut(( "OC_QUERY_STEP_COUNT\n" ));
//
// Param1 = unused
// Param2 = unused
//
// Return value is an arbitrary 'step' count or -1 if error.
//
// OC Manager calls this routine when it wants to find out how much
// work the component wants to perform for nonfile operations to
// install/uninstall a component/subcomponent.
// It is called once for the *entire* component and then once for
// each subcomponent in the component.
//
// One could get arbitrarily fancy here but we simply return 1 step
// per subcomponent. We ignore the "entire component" case.
//
if ( !SubcomponentId || _wcsicmp( SubcomponentId,wcsIndexsrvSystem ) )
{
return NO_ERROR;
}
dwRetVal = 1;
break;
case OC_ABOUT_TO_COMMIT_QUEUE:
isDebugOut(( "OC_ABOUT_TO_COMMIT_QUEUE\n" ));
if ( !SubcomponentId || _wcsicmp( wcsIndexsrvSystem,SubcomponentId ) )
{
return NO_ERROR;
}
dwRetVal = QueueConfigurationParams( gSetupInitComponent.ComponentInfHandle,
(HSPFILEQ) Param2,
SubcomponentId,
Err );
if ( NO_ERROR != dwRetVal )
{
isDebugOut((DEB_ERROR,"QueueConfigurationParams Failed: %d\n",dwRetVal ));
ISError( IS_MSG_QUEUE_CONFIG_PARAMS_FAILED, Err, LogSevError, dwRetVal );
return ERROR_CANCELLED;
}
dwRetVal = SetRegBasedOnMachine(Err);
if ( NO_ERROR != dwRetVal )
{
isDebugOut(( DEB_ERROR, "SetRegBasedOnMachine Failed: %d\n", dwRetVal ));
ISError( IS_MSG_SetRegBasedOnMachine_FAILED, Err, LogSevError, dwRetVal );
}
dwRetVal = SetRegBasedOnArchitecture(Err);
if ( NO_ERROR != dwRetVal )
{
isDebugOut(( DEB_ERROR, "SetRegBasedOnArchitecture Failed: %d\n", dwRetVal ));
Err.Report(LogSevError, dwRetVal, L"SetRegBasedOnArchitecture FAILED");
}
break;
case OC_COMPLETE_INSTALLATION:
isDebugOut(( "OC_COMPLETE_INSTALLATION\n" ));
if ( !SubcomponentId || _wcsicmp(SubcomponentId,wcsIndexsrvSystem) )
{
return NO_ERROR;
}
dwRetVal = CompleteInstallation(Err);
if ( NO_ERROR != dwRetVal )
{
isDebugOut(( DEB_ERROR, "CompleteInstallation Failed: %d\n", dwRetVal ));
ISError( IS_MSG_COMPLETE_INSTALLATION_FAILED, Err, LogSevError, dwRetVal );
}
if ( g_fLocallyOpened &&
INVALID_HANDLE_VALUE != gSetupInitComponent.ComponentInfHandle )
{
SetupCloseInfFile(gSetupInitComponent.ComponentInfHandle);
gSetupInitComponent.ComponentInfHandle = INVALID_HANDLE_VALUE;
}
g_fInstallCancelled = FALSE;
break;
case OC_CLEANUP:
isDebugOut(( "OC_CLEANUP\n" ));
//
// Do last-minute work now that the metabase is installed
//
OcCleanup( Err );
break;
case OC_QUERY_IMAGE:
isDebugOut(( "OC_QUERY_IMAGE\n" ));
//
// not used
//
break;
default:
isDebugOut(( "OC_ message ignored\n" ));
break;
}
isDebugOut(( "IndexSrv is returning %d\n", dwRetVal ));
return dwRetVal;
}
CATCH (CException, e)
{
isDebugOut(( "install is aborted, error %#x\n", e.GetErrorCode() ));
g_fInstallAborted = TRUE;
if ( g_fLocallyOpened &&
INVALID_HANDLE_VALUE != gSetupInitComponent.ComponentInfHandle )
{
SetupCloseInfFile(gSetupInitComponent.ComponentInfHandle);
gSetupInitComponent.ComponentInfHandle = INVALID_HANDLE_VALUE;
}
ISError( IS_MSG_EXCEPTION_CAUGHT, Err, LogSevError, e.GetErrorCode() );
dwRetVal = e.GetErrorCode();
}
END_CATCH
return dwRetVal;
}
//+-------------------------------------------------------------------------
//
// Function: OcCleanup
//
// Synopsis: Finish setup work now that everything else is installed. It
// would be better to do this in OC_COMPLETE_INSTALLATION, but
// there is no guarantee IIS is installed by that point.
//
// History: 11-3-98 dlee Created
//
//--------------------------------------------------------------------------
void OcCleanup( CError & Err )
{
//
// Add metabase settings if IIS is around
//
TRY
{
if ( !g_fInstallCancelled )
SetupW3Svc(Err);
}
CATCH( CException, e )
{
// If IIS isn't installed then setting up w3svc will fail. Ignore
isDebugOut(( "caught %#x adding w3svc stuff\n", e.GetErrorCode() ));
}
END_CATCH
//
// Start cisvc service if it was running, we're selected, and not in
// NT setup mode.
//
TRY
{
if ( ( g_fCiSvcWasRunning && !g_cChangeSelection ) ||
( g_fCiSvcIsRequested && !g_fNtGuiMode && !g_fInstallCancelled ) )
{
StartService(L"CiSvc");
}
}
CATCH( CException, e )
{
// Don't hose the install if we can't start the service
isDebugOut(( "caught %#x starting service\n", e.GetErrorCode() ));
}
END_CATCH
} //OcCleanup
//+-------------------------------------------------------------------------
//
// Function: OpenInfFile
//
// Synopsis: opens a handle to setupqry.inf file
//
// Returns: True upon success, False upon failure.
//
// History: 6-28-97 mohamedn created
//
//--------------------------------------------------------------------------
BOOL OpenInfFile(CError & Err)
{
WCHAR InfPath[MAX_PATH];
DWORD dwRetVal = GetModuleFileName( MyModuleHandle, InfPath, NUMELEM(InfPath));
if ( 0 == dwRetVal )
{
isDebugOut(( DEB_ERROR, "GetModuleFileName() Failed: %d\n", GetLastError() ));
return FALSE;
}
LPWSTR p = wcsrchr( InfPath, L'\\' );
if (p)
{
wcscpy( p+1, L"setupqry.inf" );
gSetupInitComponent.ComponentInfHandle = SetupOpenInfFile( InfPath, NULL, INF_STYLE_WIN4, NULL );
if (gSetupInitComponent.ComponentInfHandle == INVALID_HANDLE_VALUE)
{
isDebugOut(( DEB_ERROR, "SetupOpenInfFile(%ws) Failed: %d\n", InfPath, GetLastError() ));
return FALSE;
}
}
else
{
return FALSE;
}
g_fLocallyOpened = TRUE;
return TRUE;
}
//+-------------------------------------------------------------------------
//
// Function: QueueConfigurationParams
//
// Synopsis: queue-up an inf section to install
//
// Returns: NO_ERROR upon success, win32 error upon failure
//
// History: 6-28-97 mohamedn created
//
//--------------------------------------------------------------------------
DWORD QueueConfigurationParams( HINF hInf, HSPFILEQ Param2, WCHAR const * pwszSectionName, CError &Err )
{
BOOL fOk = SetupInstallFromInfSection( 0,
hInf,
pwszSectionName,
SPINST_REGISTRY,
0,
0,
0,
0,
0,
0,
0 );
if ( !fOk )
{
isDebugOut(( DEB_ERROR, "SetupInstallFromInfSection(%ws) Failed: %d\n",
pwszSectionName, GetLastError() ));
ISError( IS_MSG_SETUP_INSTALL_FROM_INFSECTION_FAILED, Err,
LogSevError, GetLastError() );
}
return ( fOk ? NO_ERROR : GetLastError() );
}
//+-------------------------------------------------------------------------
//
// Function: SetupW3Svc
//
// Synopsis: Setup catalogs and script mappings for IIS
//
// Arguments: [Err] -- Error reporting object
//
// History: 13-May-1998 KyleP Created
//
//--------------------------------------------------------------------------
void SetupW3Svc(CError &Err)
{
BOOL fCurrentlyChecked = g_HelperRoutines.QuerySelectionState(
g_HelperRoutines.OcManagerContext,
wcsIndexsrvSystem,
OCSELSTATETYPE_CURRENT );
isDebugOut(( "currently checked: %d\n", fCurrentlyChecked ));
TRY
{
do
{
//
// Initialize/Uninitialize COM. Allow any old mode, and allow
// for the fact that some other broken component may have left
// COM initialized.
//
XCom xcom( TRUE );
WCHAR awc[MAX_PATH];
isDebugOut(( "SetupW3Svc\n" ));
isDebugOut(( " g_fCiSvcIsRequested: %d\n", g_fCiSvcIsRequested ));
isDebugOut(( " g_fNtGuiMode: %d\n", g_fNtGuiMode ));
isDebugOut(( " g_cChangeSelection: %d\n", g_cChangeSelection ));
isDebugOut(( " g_dwPrevISVersion: %d \n", g_dwPrevISVersion ));
isDebugOut(( " g_fUpgrade: %d\n", g_fUpgrade ));
{
//
// Is W3Svc even installed?
//
CMetaDataMgr mdMgr( TRUE, W3VRoot );
//
// Guess so. We didn't throw. Now, add the script mappings if
// if appropriate:
//
// If the checkbox is selected, add scriptmaps if
// clean install or
// add/remove and they changed the state of the checkbox
// upgrade and scriptmaps weren't deleted by hand by the user
//
// Delete scriptmaps if
// Checkbox is unchecked and there was a change in the selection state
//
// Note the state of the checked/unchecked variable g_fCiSvcIsRequested
// is only valid in add/remove AND if the user has changed the selection.
// So this code uses fCurrentlyChecked instead.
//
if ( ( fCurrentlyChecked ) &&
( g_fNtGuiMode || ( 0 != g_cChangeSelection ) ) )
{
//
// IDQ and WEBHITS are always in System32
//
if ( (MAX_PATH - wcslen(g_awcSystemDir)) < 30 ) // DLL won't fit
break;
wcscpy( awc, L".idq," );
wcscat( awc, g_awcSystemDir );
//
// Add IDQ if add/remove OR
// clean install OR
// there is already a scriptmap OR
// there already is a (possibly old) scriptmap pointing at the expected dll
//
//
// Note: the "IIS lockdown" tool points our scriptmaps at
// 404.dll; it doesn't delete them. I have no idea why.
//
//
// scriptmap flags -- 0x2 is obsolete (apparently)
//
// #define MD_SCRIPTMAPFLAG_SCRIPT 0x00000001
// #define MD_SCRIPTMAPFLAG_CHECK_PATH_INFO 0x00000004
//
// Can't check path info for .htw due to null.htw support
//
wcscat( awc, L"\\idq.dll,7,GET,HEAD,POST" );
if ( ( !g_fNtGuiMode ) ||
( g_fNtGuiMode && !g_fUpgrade ) ||
( 0 == g_dwPrevISVersion ) ||
( mdMgr.ExtensionHasTargetScriptMap( L".idq", L"idq.dll" ) ) )
mdMgr.AddScriptMap( awc );
//
// Add IDA if add/remove or there is already a valid scriptmap
//
awc[3] = L'a';
if ( ( !g_fNtGuiMode ) ||
( g_fNtGuiMode && !g_fUpgrade ) ||
( 0 == g_dwPrevISVersion ) ||
( mdMgr.ExtensionHasTargetScriptMap( L".ida", L"idq.dll" ) ) )
mdMgr.AddScriptMap( awc );
//
// Add HTW if add/remove or there is already a valid scriptmap
//
wcscpy( awc, L".htw," );
wcscat( awc, g_awcSystemDir );
wcscat( awc, L"\\webhits.dll,3,GET,HEAD,POST" );
if ( ( !g_fNtGuiMode ) ||
( g_fNtGuiMode && !g_fUpgrade ) ||
( 0 == g_dwPrevISVersion ) ||
( mdMgr.ExtensionHasTargetScriptMap( L".htw", L"webhits.dll" ) ) )
mdMgr.AddScriptMap( awc );
//
// Add IS script maps as in-process. Always do this.
//
wcscpy( awc, g_awcSystemDir );
wcscat( awc, L"\\idq.dll" );
mdMgr.AddInProcessIsapiApp( awc );
//
// By default, run this OOP. The user can run in IP if they need to
// webhit files on remote virtual roots.
//
#if 0
wcscpy( awc, g_awcSystemDir );
wcscat( awc, L"\\webhits.dll" );
mdMgr.AddInProcessIsapiApp( awc );
#endif
}
if ( ( !fCurrentlyChecked ) && ( 0 != g_cChangeSelection ) )
{
mdMgr.RemoveScriptMap( L".idq" );
mdMgr.RemoveScriptMap( L".ida" );
mdMgr.RemoveScriptMap( L".htw" );
}
//
// Make sure it makes it out to disk
//
mdMgr.Flush();
}
//
// Only create a web catalog if everything looks like a new install...
//
BOOL fNew = FALSE;
TRY
{
CWin32RegAccess reg( HKEY_LOCAL_MACHINE, wcsRegCatalogsWebSubKey );
if ( reg.Ok() )
{
WCHAR wcsSubKeyName[MAX_PATH+1];
DWORD cwcName = sizeof wcsSubKeyName / sizeof WCHAR;
if ( reg.Enum( wcsSubKeyName, cwcName ) )
{
// There is at least one subkey
do
{
//
// if there is a subkey other than properties,
// we're not createing a new web catalog
//
if ( 0 != _wcsicmp( wcsSubKeyName, wszProperties ) )
{
fNew = FALSE;
break;
}
else
fNew = TRUE;
} while ( reg.Enum( wcsSubKeyName, cwcName ) );
}
else
fNew = TRUE;
}
else
fNew = TRUE;
}
CATCH( CException, e )
{
fNew = TRUE;
}
END_CATCH
if ( !fNew )
break;
//
// Must look like a default install...
//
CMetaDataMgr mdMgrDefaultServer( FALSE, W3VRoot, 1 );
mdMgrDefaultServer.GetVRoot( L"/", awc );
unsigned ccRoot = wcslen(awc) - 8; // <path> - "\wwwroot"
if ( 0 != _wcsicmp( awc + ccRoot, L"\\wwwroot" ) )
break;
awc[ccRoot] = 0;
//
// Add a web catalog.
//
CCatReg CatReg(Err);
CatReg.Init( L"Web", awc );
CatReg.TrackW3Svc();
//
// set ISAPIDefaultCatalogDirectory to Web
//
CWin32RegAccess reg( HKEY_LOCAL_MACHINE, wcsRegAdminSubKey );
if ( !reg.Set( wcsISDefaultCatalogDirectory, L"Web" ) )
{
ISError( IS_MSG_COULD_NOT_MODIFY_REGISTRY, Err,
LogSevWarning, GetLastError() );
return;
}
} while(FALSE);
isDebugOut(( "successfully added w3svc stuff\n" ));
}
CATCH( CException, e )
{
isDebugOut(( "caught %x in SetupW3Svc\n", e.GetErrorCode() ));
}
END_CATCH
}
//+-------------------------------------------------------------------------
//
// Function: CompleteInstallation
//
// Synopsis: called by NT setup to cofigure Index server for operation.
//
// Returns: SCODE, S_OK upon success, other values upon failure
//
// History: 6-28-97 mohamedn created
//
//--------------------------------------------------------------------------
DWORD CompleteInstallation(CError &Err)
{
SCODE sc = S_OK;
DWORD dwRetVal = 0;
DWORD dwLastError = 0;
//MessageBox(NULL, L"BREAK HERE", NULL, MB_OK);
TRY
{
//
// Delete the "DonotStartCiSvc" registry parameter
//
CWin32RegAccess reg( HKEY_LOCAL_MACHINE, wcsRegAdminSubKey );
reg.Remove(wcsPreventCisvcParam);
dwRetVal = SetDLLsToRegister (Err);
if ( NO_ERROR != dwRetVal )
{
isDebugOut(( DEB_ERROR, "SetDllsToRegister Failed: %d", dwRetVal ));
ISError( IS_MSG_SetDllsToRegister_FAILED, Err, LogSevError, dwRetVal );
THROW(CException(HRESULT_FROM_WIN32(dwRetVal)) );
}
dwRetVal = SetFilterRegistryInfo(FALSE, Err);
if ( NO_ERROR != dwRetVal )
{
isDebugOut(( DEB_ERROR, "SetFilterRegistryInfo Failed: %d", dwRetVal ));
ISError( IS_MSG_SetFilterRegistryInfo_FAILED, Err, LogSevError, dwRetVal );
THROW(CException(HRESULT_FROM_WIN32(dwRetVal)) );
}
dwRetVal = AddPerfData(Err);
if ( NO_ERROR != dwRetVal )
{
isDebugOut(( DEB_ERROR, "AddPerfData Failed: %d\n",dwRetVal));
THROW(CException(HRESULT_FROM_WIN32(dwRetVal)) );
}
//
// stop cisvc
//
StopService(L"cisvc");
//
// Upgrade 1.1 to 3.0 if needed. Must happen *before* AddCiSvc().
//
UpgradeIS1toIS3(Err);
//
// Delete the NTOP start menu items IS created
//
DeleteNTOPStartMenu();
//
// configure catalogs
//
dwRetVal = SetDefaultCatalog(Err);
if ( NO_ERROR != dwRetVal )
{
isDebugOut(( DEB_ERROR, "SetDefaultCatalog Failed: %d\n",dwRetVal));
ISError( IS_MSG_SetDefaultCatalog_FAILED, Err, LogSevError, dwRetVal );
THROW(CException(HRESULT_FROM_WIN32(dwRetVal)) );
}
//
// if selection count is odd (user changed the selection),
// delete the service to create a new one. Also delete and
// re-create if we're upgrading IS 1.x.
//
if ( ( !g_fUpgrade && ( g_cChangeSelection & 0x1 ) ) ||
1 == g_dwPrevISVersion )
DeleteService(L"cisvc");
//
// add the service
//
AddCiSvc(Err);
}
CATCH( CException, e )
{
isDebugOut(( DEB_ERROR, "Caught Exception in CompleteInstallation: %d\n",e.GetErrorCode() ));
ISError( IS_MSG_EXCEPTION_CAUGHT, Err, LogSevError, e.GetErrorCode() );
sc = e.GetErrorCode();
isDebugOut(( "Caught Exception in CompleteInstallation: %#x\n", sc ));
}
END_CATCH
return sc;
} //CompleteInstallation
//+-------------------------------------------------------------------------
//
// Function: UpgradeIS1toIS3
//
// Synopsis: sets ISapiDefaultCatalogDirectory param if we're upgrading
// from 1.0 or 1.1 to 3.0
//
// Returns: none.
//
// History: 01-May-1998 mohamedn created
// 05-Sep-1998 KyleP Start service on upgrade
//
// Notes: This *must* be called before AddCisvc, since the decision
// about whether to start the service may be changed in
// this function.
//
//--------------------------------------------------------------------------
void UpgradeIS1toIS3(CError &Err)
{
if ( !g_fNT4_To_NT5_Upgrade || g_dwPrevISVersion >= 2 )
{
return;
}
g_awcIS1Path[0] = L'\0';
{
CWin32RegAccess reg( HKEY_LOCAL_MACHINE, wcsRegAdminSubKey );
reg.Get( wcsISDefaultCatalogDirectory, g_awcIS1Path, NUMELEM( g_awcIS1Path ) );
if ( 0 == wcslen(g_awcIS1Path) || g_awcIS1Path[1] != L':' )
{
//
// nothing to do.
//
g_awcIS1Path[0] = L'\0';
return;
}
}
//
// The 'Catalogs' key needs to be created.
//
{
CWin32RegAccess reg( HKEY_LOCAL_MACHINE, wcsRegAdminSubKey );
BOOL fExisted;
if ( !reg.CreateKey( L"Catalogs", fExisted ) )
{
DWORD dw = GetLastError();
isDebugOut(( DEB_ERROR, "created catalogs subkey Failed: %d\n", dw ));
ISError( IS_MSG_COULD_NOT_CONFIGURE_CATALOGS, Err , LogSevFatalError, dw );
return;
}
}
//
// create the web catalog
//
CCatReg CatReg(Err);
CatReg.Init( L"Web", g_awcIS1Path );
CatReg.TrackW3Svc();
//
// set ISAPIDefaultCatalogDirectory to Web
//
CWin32RegAccess reg( HKEY_LOCAL_MACHINE, wcsRegAdminSubKey );
if ( !reg.Set( wcsISDefaultCatalogDirectory, L"Web" ) )
{
ISError(IS_MSG_COULD_NOT_MODIFY_REGISTRY , Err, LogSevWarning, GetLastError() );
return;
}
//
// CI was running before the upgrade, so make sure it is running after
// the upgrade as well.
//
g_fCiSvcIsRequested = TRUE;
}
//+-------------------------------------------------------------------------
//
// Function: GetPreviousISSetupVersion
//
// Synopsis: gets version of previous installed IS, if any.
//
// Arguments: none
//
// Returns: none
//
// History: 10-16-97 mohamedn created
//
//--------------------------------------------------------------------------
void GetPreviousISSetupVersion(void)
{
HKEY hKey = 0;
DWORD dwType = 0;
DWORD dwVal = 0;
DWORD cb = sizeof DWORD;
//
// If it's not an upgrade, don't try to get the previous version as someone is
// now writing contentindex\DoNotStartCisvc to the registry so we would
// otherwise assume it's an upgrade without this check.
//
if ( !g_fUpgrade )
return;
LONG lRetVal = RegOpenKeyEx( HKEY_LOCAL_MACHINE, wcsRegAdminSubKey, 0, KEY_READ, &hKey );
if ( ERROR_SUCCESS == lRetVal )
{
lRetVal = RegQueryValueEx( hKey,
L"MajorVersion",
0,
&dwType,
(BYTE *)&dwVal,
&cb );
if ( ERROR_SUCCESS == lRetVal )
g_dwPrevISVersion = dwVal;
else
g_dwPrevISVersion = 1; // We didn't write this key in V1.
RegCloseKey( hKey );
}
}
//+-------------------------------------------------------------------------
//
// Function: SetDefaultCatalog
//
// Synopsis: Configures IS catalog for indexing local file system based on
// available disk space.
//
// Arguments: none
//
// Returns: ErrorSuccess upon success, error value upon failure.
//
// History: 9-10-97 mohamedn
//
//--------------------------------------------------------------------------
DWORD SetDefaultCatalog(CError &Err)
{
BOOL fExisted;
DWORD dwRetVal = NO_ERROR;
if ( !IsSufficientMemory() )
{
ISError( IS_MSG_BAD_MACHINE, Err, LogSevError );
ISError( IS_MSG_NEEDED_HARDWARE, Err, LogSevError );
return ERROR_SUCCESS;
}
{
CWin32RegAccess reg( HKEY_LOCAL_MACHINE, wcsRegAdminSubKey );
if (!reg.CreateKey( L"Catalogs", fExisted ) )
{
DWORD dw = GetLastError();
isDebugOut(( DEB_ERROR, "created catalogs subkey Failed: %d\n", dw ));
ISError( IS_MSG_COULD_NOT_CONFIGURE_CATALOGS, Err , LogSevFatalError, dw );
return dw;
}
}
//
// return if Catalogs key exists, don't overwrite existing configuration
//
if ( fExisted && !g_fNT4_To_NT5_Upgrade )
{
return ERROR_SUCCESS;
}
//
// Find the default profile path (Usually %windir%\Profiles)
//
CWin32RegAccess regProfileKey( HKEY_LOCAL_MACHINE, wszRegProfileKey );
g_awcProfilePath[0] = L'\0';
WCHAR wcTemp[MAX_PATH+1];
if ( regProfileKey.Get( wszRegProfileValue, wcTemp, NUMELEM(wcTemp) ) )
{
unsigned ccTemp2 = ExpandEnvironmentStrings( wcTemp,
g_awcProfilePath,
NUMELEM(g_awcProfilePath) );
}
CCatalogConfig Cat(Err);
Cat.SetName( L"System" );
if ( !Cat.InitDriveList() )
{
ISError( IS_MSG_DRIVE_ENUMERATION_FAILED, Err, LogSevError, GetLastError() );
return ERROR_INSTALL_FAILURE;
}
BOOL bRetVal = Cat.ConfigureDefaultCatalog( g_awcProfilePath );
if (bRetVal)
{
//
// add paths to exclude indexing IE temp files.
//
ExcludeSpecialLocations( Cat );
//
// Set the catalog location
wcsncpy(wcTemp, wszSysVolInfoDirectory, sizeof wcTemp / sizeof WCHAR);
wcTemp[ (sizeof wcTemp / sizeof WCHAR) - 1 ] = 0;
wcTemp[0] = *(Cat.GetCatalogDrive());
Cat.SetLocation( wcTemp );
// NOTE: The catalog path will be created when first accessed by
// CClientDocStore.
Cat.SaveState();
}
return ( bRetVal ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE );
}
//+-------------------------------------------------------------------------
//
// Function: SetDLLsToRegister
//
// Synopsis: Sets the "DLLsToRegister" value in the registry
//
// History: 19-Jun-97 t-elainc Created
//
//--------------------------------------------------------------------------
DWORD SetDLLsToRegister(CError &Err)
{
WCHAR * apwc2[cDlls];
unsigned cwcTotal = 1;
// store full pathnames in array 2
for (int i = 0; i < cDlls; i++)
{
unsigned cwc = wcslen( g_awcSystemDir ) + 1 + wcslen( apwcDlls[i] );
if ( cwc >= MAX_PATH )
return 0;
WCHAR filepath[MAX_PATH];
wcscpy(filepath, g_awcSystemDir );
wcscat(filepath, L"\\" );
wcscat(filepath, apwcDlls[i] );
cwcTotal += ( cwc + 1 );
apwc2[i] = new WCHAR[MAX_PATH];
wcscpy(apwc2[i], filepath);
}
WCHAR * apwc2Old[cOldDlls];
// store full old pathnames in array 2
for (i = 0; i < cOldDlls; i++)
{
unsigned cwc = wcslen( g_awcSystemDir ) + 1 + wcslen( apwcOldDlls[i] );
if ( cwc >= MAX_PATH )
return 0;
WCHAR filepath[MAX_PATH];
wcscpy(filepath, g_awcSystemDir );
wcscat(filepath, L"\\" );
wcscat(filepath, apwcOldDlls[i] );
apwc2Old[i] = new WCHAR[MAX_PATH];
wcscpy(apwc2Old[i], filepath);
}
if ( cwcTotal >= 4096 )
return 0;
unsigned cwcRemaining = 4096 - cwcTotal;
WCHAR awc[4096]; //buffer for new list
WCHAR *pwc = awc; //pointer to list
*pwc = 0; //set first slot in array to null
// put our dlls in the beginning
for (int i = 0; i < cDlls; i++)
pwc = AppendMultiSZString(pwc, apwc2[i]);
CWin32RegAccess reg( HKEY_LOCAL_MACHINE, wcsRegAdminSubKey );
{
WCHAR awcOld[4096]; //the old buffer list of files to register
if ( reg.Get( L"DLLsToRegister",
awcOld,
sizeof awcOld / sizeof WCHAR ) )
{
WCHAR *p = awcOld;
while ( 0 != *p )
{
// Leave dlls not in our list -- 3rd party dlls
BOOL fFound = FALSE;
for ( int i = 0; i < cDlls; i++ )
{
if (!_wcsicmp(p, apwc2[i]) )
{
fFound = TRUE;
break;
}
}
// Remove old dlls from the list (fsci & cifrmwrk)
if ( !fFound )
{
for ( int i = 0; i < cOldDlls; i++ )
{
if (!_wcsicmp(p, apwc2Old[i]) )
{
fFound = TRUE;
break;
}
}
}
if (!fFound)
{
cwcTotal += ( wcslen( p ) + 1 );
if ( cwcTotal >= 4096 )
return 0;
pwc = AppendMultiSZString(pwc, p);
}
p += ( wcslen(p) + 1 );
}
}
*pwc++ = 0;
}
for (int j = 0; j < cDlls; j++)
delete apwc2[j];
for (j = 0; j < cOldDlls; j++)
delete apwc2Old[j];
if ( !reg.SetMultiSZ( L"DLLsToRegister",
awc,
(ULONG)(pwc-awc) * sizeof WCHAR ) )
{
DWORD dw = GetLastError();
ISError( IS_MSG_COULD_NOT_MODIFY_REGISTRY, Err, LogSevFatalError, dw );
return dw;
}
return NO_ERROR;
} //SetDLLsToRegister
//+-------------------------------------------------------------------------
//
// Function: AppendMultiSZString
//
// Synopsis: Copies one string to another.
//
// Returns: Pointer to one wchar beyond the end of the copy
//
// History: 8-Jan-97 dlee Created
//
//--------------------------------------------------------------------------
WCHAR * AppendMultiSZString(
WCHAR * pwcTo,
WCHAR const * pwcFrom )
{
isDebugOut((DEB_TRACE, "language or dll installed: '%ws'\n", pwcFrom ));
unsigned x = wcslen( pwcFrom );
wcscpy( pwcTo, pwcFrom );
return pwcTo + x + 1;
} //AppendMultiSZString
//+-------------------------------------------------------------------------
//
// Function: ExcludeSpecialLocations, private
//
// Synopsis: Writes profile-based exclude scopes into the registry
//
// Arguments: none
//
// History: 28-Aug-1998 KyleP Created
//
//--------------------------------------------------------------------------
WCHAR const wszRegShellSpecialPathsKey[] =
L".DEFAULT\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders";
WCHAR const * const awszRegShellSpecialPathsValue[] = {
L"AppData",
L"Local Settings"
};
WCHAR const wszUserProfile[] = L"%USERPROFILE%";
void ExcludeSpecialLocations( CCatalogConfig & Cat )
{
//
// First, find the default profile path (Usually %windir%\Profiles)
//
WCHAR wcTemp[MAX_PATH+1];
if ( g_awcProfilePath[0] )
{
WCHAR wcTemp2[MAX_PATH+1];
wcsncpy( wcTemp2, g_awcProfilePath, sizeof wcTemp2 / sizeof WCHAR );
wcTemp2[ (sizeof wcTemp2 / sizeof WCHAR) - 1 ] = 0;
unsigned ccTemp2 = wcslen( wcTemp2 );
//
// Append the wildcard, for user profile directory
//
wcscpy( wcTemp2 + ccTemp2, L"\\*\\" );
ccTemp2 += 3;
//
// Go through and look for special shell paths, which just happen
// to include all our special cases too.
//
CWin32RegAccess regShellSpecialPathsKey( HKEY_USERS, wszRegShellSpecialPathsKey );
for ( unsigned i = 0;
i < NUMELEM(awszRegShellSpecialPathsValue);
i++ )
{
if ( regShellSpecialPathsKey.Get( awszRegShellSpecialPathsValue[i],
wcTemp, NUMELEM(wcTemp), FALSE) )
{
if ( RtlEqualMemory( wszUserProfile, wcTemp,
sizeof(wszUserProfile) - sizeof(WCHAR) ) )
{
wcscpy( wcTemp2 + ccTemp2, wcTemp + NUMELEM(wszUserProfile) );
wcscpy( wcTemp, wcTemp2 );
}
if ( wcschr( wcTemp, L'%' ) != 0 )
{
WCHAR wcTemp3[MAX_PATH+1];
unsigned ccTemp3 = ExpandEnvironmentStrings(
wcTemp,
wcTemp3,
NUMELEM(wcTemp3) );
if ( 0 != ccTemp3 )
wcscpy( wcTemp, wcTemp3 );
}
wcscat( wcTemp, L"\\*" );
isDebugOut(( DEB_TRACE, "Exclude: %ws\n", wcTemp ));
Cat.AddExcludedDirOrPattern( wcTemp );
}
}
}
}
//+-------------------------------------------------------------------------
//
// Function: AddPerfData
//
// Synopsis: Runs unlodctr and lodctr on Index Server perf data
//
// History: 8-Jan-97 dlee Created
//
//--------------------------------------------------------------------------
DWORD AddPerfData(CError &Err)
{
// add counters if installing
DWORD dwError = NO_ERROR;
// remove existing counters (if they exist)
RemovePerfData();
isDebugOut((DEB_TRACE, "Installing perf data\n" ));
dwError = LoadCounterAndDelete( L"perfci.ini", L"perfci.h", Err );
if ( ERROR_SUCCESS == dwError )
{
dwError = LoadCounterAndDelete( L"perffilt.ini", L"perffilt.h", Err );
if ( ERROR_SUCCESS == dwError )
{
dwError = LoadCounterAndDelete( L"perfwci.ini", L"perfwci.h", Err );
}
}
return NO_ERROR; // Ignore failures return dwError;
} //AddPerfData
//+-------------------------------------------------------------------------
//
// Function: LoadCounterAndDelete
//
// Synopsis: Loads perf counters for a .ini and a .h, then deletes
// the files. Assumes the files are in system32.
//
// Arguments: [pwcINI] -- Name w/o path of .ini file.
// [pwcH] -- Name w/o path of .h file.
//
// History: 30-Jan-97 dlee Created
// 23-May-97 KyleP Use LoadPerfCounterTextStrings API
//
//--------------------------------------------------------------------------
DWORD LoadCounterAndDelete(
WCHAR const * pwcINI,
WCHAR const * pwcH,
CError &Err)
{
unsigned cwc = wcslen( L"lodctr " ) + wcslen( g_awcSystemDir ) + 1 + wcslen( pwcINI );
if ( cwc >= MAX_PATH )
return 0;
WCHAR awc[MAX_PATH];
WCHAR const awcLodctr[] = L"lodctr ";
wcscpy( awc, awcLodctr );
wcscat( awc, g_awcSystemDir );
wcscat( awc, L"\\" );
wcscat( awc, pwcINI );
DWORD dwError = (DWORD)LoadPerfCounterTextStrings( awc, // .INI file
TRUE ); // Quiet mode
if ( ERROR_SUCCESS != dwError )
{
isDebugOut(( DEB_ERROR, "Error %d from LoadPerfCounterTextStrings %ws\n", dwError, awc ));
isDebugOut(( "Error %d from LoadPerfCounterTextStrings %ws\n", dwError, awc ));
ISError( IS_MSG_LoadPerfCounterTextStrings_FAILED, Err, LogSevError, dwError );
return dwError;
}
return dwError;
} //LoadCounterAndDelete
//+-------------------------------------------------------------------------
//
// Function: RemovePerfData
//
// Synopsis: Runs unlodctr and lodctr on Index Server perf data
//
// History: 08-Jan-97 dlee Created
// 23-May-97 KyleP Use UnloadPerfCounterTextStrings API
//
//--------------------------------------------------------------------------
DWORD RemovePerfData()
{
// remove existing counters (if they exist )
DWORD dw0 = (DWORD)UnloadPerfCounterTextStrings( L"unlodctr ContentIndex", // Key
TRUE ); // Quiet mode
DWORD dw1 = (DWORD)UnloadPerfCounterTextStrings( L"unlodctr ContentFilter", // Key
TRUE ); // Quiet mode
DWORD dw2 = (DWORD)UnloadPerfCounterTextStrings( L"unlodctr ISAPISearch", // Key
TRUE ); // Quiet mode
if ( NO_ERROR != dw0 )
{
isDebugOut(( DEB_ERROR, "RemovePerfData: unlodctr ContentIndex failed with 0x%x\n", dw0));
return dw0;
}
else if ( NO_ERROR != dw1 )
{
isDebugOut(( DEB_ERROR, "RemovePerfData: unlodctr ContentFilter failed with 0x%x\n", dw1));
return dw1;
}
else
{
if ( NO_ERROR != dw2 )
{
isDebugOut(( DEB_ERROR, "RemovePerfData: unlodctr ISAPISearch failed with 0x%x\n", dw0));
}
return dw2;
}
} //RemovePerfData
//+-------------------------------------------------------------------------
//
// Function: IsSufficientMemory
//
// Synopsis: Determines available physical memory
//
// Arguments: none
//
// Returns: TRUE if physical memory > required phys. memory
// FALSE otherwise.
//
// History: 6-27-97 mohamedn created
//
//--------------------------------------------------------------------------
BOOL IsSufficientMemory(void)
{
// 32MB RAM.machine, taking into account up to 1M used by the system.
const ULONGLONG MIN_PHYSICAL_MEMORY = 30*ONE_MB;
MEMORYSTATUSEX memoryStatus;
RtlZeroMemory(&memoryStatus, sizeof memoryStatus );
memoryStatus.dwLength = sizeof memoryStatus;
GlobalMemoryStatusEx(&memoryStatus);
return ( MIN_PHYSICAL_MEMORY <= memoryStatus.ullTotalPhys );
}
//+-------------------------------------------------------------------------
//
// Function: AddCiSvc
//
// Synopsis: Creates the cisvc service
//
// Arguments: [Err] -- The error object to update
//
// Returns: none - throws upon fatal failure
//
// History: 6-29-97 mohamedn created
//
//--------------------------------------------------------------------------
void AddCiSvc(CError &Err)
{
DWORD dwLastError = 0;
SC_HANDLE hSC = OpenSCManager( 0, 0, SC_MANAGER_CREATE_SERVICE );
CServiceHandle xhSC(hSC);
if( 0 == hSC )
{
dwLastError = GetLastError();
isDebugOut(( DEB_ITRACE, "OpenSCManager() Failed: %x\n", dwLastError ));
THROW( CException(HRESULT_FROM_WIN32(dwLastError)) );
}
WCHAR wszServiceDependencyList[MAX_PATH];
RtlZeroMemory(wszServiceDependencyList, MAX_PATH * sizeof WCHAR );
wcscpy( wszServiceDependencyList, L"RPCSS" );
WCHAR wszServicePath[300];
unsigned cwc = wcslen( g_awcSystemDir ) + wcslen( L"\\cisvc.exe" );
if ( cwc >= ( sizeof wszServicePath / sizeof WCHAR ) )
return;
wcscpy(wszServicePath, g_awcSystemDir );
wcscat(wszServicePath, L"\\cisvc.exe" );
do
{
dwLastError = 0;
CResString strSvcDisplayName(IS_SERVICE_NAME);
SC_HANDLE hNewSC = CreateService( hSC, // handle to SCM database
TEXT("cisvc"), // pointer to name of service to start
strSvcDisplayName.Get(), // pointer to display name
SERVICE_ALL_ACCESS, // type of access to service
SERVICE_WIN32_SHARE_PROCESS, // type of service
g_fCiSvcIsRequested ?
SERVICE_AUTO_START :
SERVICE_DISABLED, // when to start service
SERVICE_ERROR_NORMAL, // severity if service fails to start
wszServicePath,
NULL, // pointer to name of load ordering group
NULL, // pointer to variable to get tag identifier
wszServiceDependencyList, // pointer to array of dependency names
NULL, // pointer to account name of service
NULL // pointer to password for service account
);
CServiceHandle xService( hNewSC );
if ( 0 == hNewSC )
{
dwLastError = GetLastError();
if ( ERROR_SERVICE_EXISTS == dwLastError )
dwLastError = RenameCiSvc( hSC, Err );
else if ( ERROR_SERVICE_MARKED_FOR_DELETE != dwLastError )
{
isDebugOut(( DEB_ERROR, "CreateService() Failed: %x\n", dwLastError ));
ISError( IS_MSG_CreateService_FAILED, Err, LogSevError, dwLastError );
THROW( CException(HRESULT_FROM_WIN32(dwLastError)) );
}
}
else
{
xService.Free();
// We added the service, now set the description.
RenameCiSvc( hSC, Err );
}
} while ( ERROR_SERVICE_MARKED_FOR_DELETE == dwLastError );
} //AddCiSvc
//+-------------------------------------------------------------------------
//
// Function: RenameCiSvc
//
// Synopsis: Renames the cisvc service to "Indexing Service".
//
// History: 05-Sep-1998 KyleP Created
//
//--------------------------------------------------------------------------
DWORD RenameCiSvc( SC_HANDLE hSC, CError &Err)
{
DWORD dwLastError = 0;
SC_HANDLE hCisvc = OpenService( hSC, L"cisvc", SERVICE_CHANGE_CONFIG );
CServiceHandle xhCisvc( hCisvc );
if( 0 == hCisvc )
{
dwLastError = GetLastError();
isDebugOut(( DEB_ERROR, "OpenService(cisvc) Failed: 0x%x\n", dwLastError ));
THROW( CException(HRESULT_FROM_WIN32(dwLastError)) );
}
CResString strSvcDisplayName(IS_SERVICE_NAME);
if ( !ChangeServiceConfig( hCisvc, // handle to service
SERVICE_NO_CHANGE, // type of service
SERVICE_NO_CHANGE, // when to start service
SERVICE_NO_CHANGE, // severity if service fails to start
0, // pointer to service binary file name
0, // pointer to load ordering group name
0, // pointer to variable to get tag identifier
0, // pointer to array of dependency names
0, // pointer to account name of service
0, // pointer to password for service account
strSvcDisplayName.Get() ) ) // pointer to display name);
{
dwLastError = GetLastError();
}
SERVICE_DESCRIPTION sd;
CResString strSvcDescription(IS_SERVICE_DESCRIPTION);
sd.lpDescription = (WCHAR *)strSvcDescription.Get();
if ( !ChangeServiceConfig2( hCisvc,
SERVICE_CONFIG_DESCRIPTION,
(LPVOID)&sd
)
)
dwLastError = GetLastError();
return dwLastError;
}
//+-------------------------------------------------------------------------
//
// Function: StopService
//
// Synopsis: stops service by name
//
// Arguments: pwszServiceName - name of service to stop.
//
// Returns: none - throws upon fatal failure
//
// History: 6-29-97 mohamedn created
//
//--------------------------------------------------------------------------
void StopService( WCHAR const * pwszServiceName )
{
DWORD dwLastError = 0;
SC_HANDLE hSC = OpenSCManager( 0, 0, SC_MANAGER_ALL_ACCESS );
CServiceHandle xhSC(hSC);
if( 0 == hSC )
{
dwLastError = GetLastError();
isDebugOut(( DEB_ERROR, "OpenSCManager() Failed: %x\n", dwLastError ));
THROW( CException(HRESULT_FROM_WIN32(dwLastError)) );
}
//
// stop cisvc
//
BOOL fStopped = FALSE;
if ( !MyStopService( xhSC, pwszServiceName, fStopped ) && !fStopped )
{
//
// don't throw here
//
isDebugOut(( DEB_ERROR, "Failed to stop cisvc service" ));
}
}
//+-------------------------------------------------------------------------
//
// Function: StartService
//
// Synopsis: start service by name
//
// Arguments: pwszServiceName - name of service to stop.
//
// Returns: none
//
// History: 6-29-97 mohamedn created
//
//--------------------------------------------------------------------------
void StartService( WCHAR const * pwszServiceName )
{
DWORD dwLastError = 0;
SC_HANDLE hSC = OpenSCManager( 0, 0, SC_MANAGER_ALL_ACCESS );
CServiceHandle xhSC(hSC);
if( 0 == hSC )
{
isDebugOut(( DEB_ERROR, "OpenSCManager() Failed: %x\n", GetLastError() ));
}
else
{
//
// start cisvc
//
MyStartService( xhSC, pwszServiceName );
}
}
//+-------------------------------------------------------------------------
//
// Function: MyStartService
//
// Synopsis: Starts a given service
//
// Arguments: xSC -- the service control manager
// pwcService -- name of the service to start
//
// History: 8-Jan-97 dlee Created
//
//--------------------------------------------------------------------------
void MyStartService(
CServiceHandle & xSC,
WCHAR const * pwcService )
{
CServiceHandle xSVC( OpenService( xSC.Get(),
pwcService,
SERVICE_START |
GENERIC_READ | GENERIC_WRITE ) );
if ( 0 != xSVC.Get() )
{
if ( !StartService( xSVC.Get(), 0, 0 ) )
{
isDebugOut(( DEB_ERROR, "Failed to start '%ws': %d\n", pwcService, GetLastError() ));
}
}
} //MyStartService
//+-------------------------------------------------------------------------
//
// Function: IsSvcRunning
//
// Synopsis: Determines if a service is running
//
// Arguments: xSC -- the service control manager
//
// Returns: TRUE if the service is running, FALSE otherwise
//
// History: 8-Jan-97 dlee Created
//
//--------------------------------------------------------------------------
BOOL IsSvcRunning( CServiceHandle &x )
{
SERVICE_STATUS svcStatus;
if ( QueryServiceStatus( x.Get(), &svcStatus ) )
return SERVICE_STOP_PENDING == svcStatus.dwCurrentState ||
SERVICE_RUNNING == svcStatus.dwCurrentState ||
SERVICE_PAUSED == svcStatus.dwCurrentState;
return FALSE;
} //IsSvcRunning
//+-------------------------------------------------------------------------
//
// Function: MyStopService
//
// Synopsis: Stops a given service
//
// Arguments: xSC -- the service control manager
// pwcSVC -- name of the service to stop
//
// Returns: TRUE if the service was stopped
//
// History: 8-Jan-97 dlee Created
//
//--------------------------------------------------------------------------
BOOL MyStopService(
CServiceHandle & xSC,
WCHAR const * pwcSVC,
BOOL & fStopped )
{
fStopped = FALSE;
BOOL fOK = TRUE;
CServiceHandle xSVC( OpenService( xSC.Get(),
pwcSVC,
SERVICE_STOP |
GENERIC_READ | GENERIC_WRITE ) );
if ( 0 != xSVC.Get() )
{
SERVICE_STATUS svcStatus;
if ( IsSvcRunning( xSVC ) )
{
g_fCiSvcWasRunning = TRUE;
if ( ControlService( xSVC.Get(),
SERVICE_CONTROL_STOP,
&svcStatus ) )
{
for ( unsigned i = 0; i < 30 && IsSvcRunning( xSVC ); i++ )
{
isDebugOut(( DEB_ITRACE, "sleeping waiting for service '%ws' to stop\n", pwcSVC ));
Sleep( 1000 );
}
if ( IsSvcRunning( xSVC ) )
{
THROW( CException( E_FAIL ) );
}
isDebugOut(( DEB_TRACE, "stopped service '%ws'\n", pwcSVC ));
fStopped = TRUE;
}
else
{
DWORD dw = GetLastError();
isDebugOut(( DEB_ERROR, "can't stop service '%ws', error %d\n", pwcSVC, dw ));
// failures other than timeout and out-of-control are ok
if ( ERROR_SERVICE_REQUEST_TIMEOUT == dw ||
ERROR_SERVICE_CANNOT_ACCEPT_CTRL == dw )
fOK = FALSE;
}
}
}
return fOK;
} //MyStopService
//+-------------------------------------------------------------------------
//
// Function: DeleteService
//
// Synopsis: deletes a service by name
//
// Arguments: pwszServiceName - name of service to delete
//
// Returns: none - throws upon fatal failure
//
// History: 6-29-97 mohamedn created
//
//--------------------------------------------------------------------------
void DeleteService( WCHAR const * pwszServiceName )
{
DWORD dwLastError = 0;
SC_HANDLE hSC = OpenSCManager( 0, 0, SC_MANAGER_ALL_ACCESS );
CServiceHandle xhSC(hSC);
if( 0 == hSC )
{
dwLastError = GetLastError();
isDebugOut(( DEB_ERROR, "OpenSCManager() Failed: %x\n", dwLastError ));
THROW( CException(HRESULT_FROM_WIN32(dwLastError)) );
}
SC_HANDLE hCiSvc = OpenService( hSC, pwszServiceName, DELETE );
CServiceHandle xhCiSvc( hCiSvc );
if ( 0 == hCiSvc )
{
dwLastError = GetLastError();
isDebugOut(( DEB_ERROR, "OpenService(Cisvc for delete) Failed: %x\n", dwLastError ));
}
else if ( !DeleteService(hCiSvc) )
{
dwLastError = GetLastError();
isDebugOut(( DEB_ERROR, "DeleteService(Cisvc) Failed: %x\n", dwLastError ));
THROW( CException(HRESULT_FROM_WIN32(dwLastError)) );
}
}
//+-------------------------------------------------------------------------
//
// Function: ISError
//
// Synopsis: Reports a non-recoverable Index Server Install error
//
// Arguments: id -- resource identifier for the error string
//
// History: 8-Jan-97 dlee Created
//
//--------------------------------------------------------------------------
void ISError( UINT id, CError &Err, LogSeverity Severity, DWORD dwErr )
{
CResString msg( id );
CResString title( IS_MSG_INDEX_SERVER );
Err.Report( Severity, dwErr, msg.Get() );
if ( LogSevFatalError == Severity )
{
isDebugOut(( "ISError, error %#x abort install: '%ws'\n",
dwErr, msg.Get() ));
isDebugOut(( DEB_ERROR, "ISError, error %#x abort install: '%ws'\n",
dwErr, msg.Get() ));
g_fInstallAborted = TRUE;
}
} //ISError
//+-------------------------------------------------------------------------
//
// Function: Exec
//
// Synopsis: Runs an app and waits for it to complete
//
// History: 8-Jan-97 dlee Created from cistp.dll code
//
//--------------------------------------------------------------------------
void Exec(
WCHAR * pwc )
{
isDebugOut(( "exec: '%ws'\n", pwc ));
STARTUPINFO si;
RtlZeroMemory( &si, sizeof si );
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
PROCESS_INFORMATION pi;
if ( CreateProcess( 0, // pointer to name of executable module
pwc, // pointer to command line string
0, // pointer to process security attributes
0, // pointer to thread security attributes
FALSE, // handle inheritance flag
0, // creation flags
0, // pointer to new environment block
0, // pointer to current directory name
&si, // pointer to STARTUPINFO
&pi ) ) // pointer to PROCESS_INFORMATION
{
WaitForSingleObject( pi.hProcess, 0xFFFFFFFF );
}
} //Exec
//+-------------------------------------------------------------------------
//
// Function: RegisterDll
//
// Synopsis: Calls DllRegisterServer on a given dll
//
// Returns: Win32 error code
//
// History: 21-Jan-97 dlee Created
//
//--------------------------------------------------------------------------
DWORD RegisterDll(WCHAR const * pwcDLL, CError &Err )
{
DWORD dwErr = NO_ERROR;
// All Index Server dlls are currently in system32
TRY
{
unsigned cwc = wcslen( g_awcSystemDir ) + 1 + wcslen( pwcDLL );
if ( cwc >= MAX_PATH )
return 0;
WCHAR awcPath[ MAX_PATH ];
wcscpy( awcPath, g_awcSystemDir );
wcscat( awcPath, L"\\" );
wcscat( awcPath, pwcDLL );
HINSTANCE hDll = LoadLibraryEx( awcPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH );
if( 0 != hDll )
{
SCODE (STDAPICALLTYPE *pfnDllRegisterServer)();
pfnDllRegisterServer = (HRESULT (STDAPICALLTYPE *)())
GetProcAddress(hDll, "DllRegisterServer");
if ( 0 != pfnDllRegisterServer )
{
SCODE sc = (*pfnDllRegisterServer)();
if ( S_OK != sc )
{
isDebugOut(( DEB_ERROR, "dllregister server '%ws' failed 0x%x\n",
awcPath, sc));
ISError(IS_MSG_DllRegisterServer_FAILED ,Err, LogSevError, sc );
// no way to map a scode to a win32 error
dwErr = sc; // kylep suggested this would be valuable.
}
}
else
dwErr = GetLastError();
FreeLibrary( hDll );
}
else
{
dwErr = GetLastError();
}
isDebugOut((DEB_TRACE, "result of registering '%ws': %d\n", awcPath, dwErr ));
#ifdef _WIN64
//
// Register the 32 bit version of the DLL
//
WCHAR awcSysWow64[ MAX_PATH ];
cwc = GetSystemWow64Directory( awcSysWow64, sizeof awcSysWow64 / sizeof WCHAR );
if ( 0 == cwc )
return GetLastError();
if ( L'\\' != awcSysWow64[ cwc - 1 ] )
{
awcSysWow64[ cwc++ ] = '\\';
awcSysWow64[ cwc ] = 0;
}
WCHAR awcCmd[ MAX_PATH * 2 ];
wcscpy( awcCmd, awcSysWow64 );
wcscat( awcCmd, L"regsvr32 /s " );
wcscat( awcCmd, awcSysWow64 );
wcscat( awcCmd, pwcDLL );
Exec( awcCmd );
#endif //_WIN64
}
CATCH( CException, e )
{
// ignore, since it's probably the new html filter
isDebugOut(( "caught %#x registering '%ws'\n",
e.GetErrorCode(),
pwcDLL ));
}
END_CATCH
return dwErr; // used to return 0 to avoid returning error!
} //RegisterDll
//+-------------------------------------------------------------------------
//
// Function: UnregisterDll
//
// Synopsis: Calls DllUnregisterServer on a given dll
//
// Returns: Win32 error code
//
// History: 21-Jan-97 dlee Created
//
//--------------------------------------------------------------------------
DWORD UnregisterDll(
WCHAR const * pwcDLL )
{
UINT uiOld = SetErrorMode( SEM_NOOPENFILEERRORBOX |
SEM_FAILCRITICALERRORS );
TRY
{
// All Index Server dlls are currently in system32
unsigned cwc = wcslen( g_awcSystemDir ) + 1 + wcslen( pwcDLL );
if ( cwc >= MAX_PATH )
return 0;
WCHAR awcPath[ MAX_PATH ];
wcscpy( awcPath, g_awcSystemDir );
wcscat( awcPath, L"\\" );
wcscat( awcPath, pwcDLL );
// don't display popups if a dll can't be loaded when trying to
// unregister.
DWORD dwErr = NO_ERROR;
HINSTANCE hDll = LoadLibraryEx( awcPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH );
if( 0 != hDll )
{
SCODE (STDAPICALLTYPE *pfnDllUnregisterServer)();
pfnDllUnregisterServer = (HRESULT (STDAPICALLTYPE *)())
GetProcAddress(hDll, "DllUnregisterServer");
if ( 0 != pfnDllUnregisterServer )
{
SCODE sc = (*pfnDllUnregisterServer)();
if ( S_OK != sc )
dwErr = ERROR_INVALID_FUNCTION;
}
else
dwErr = GetLastError();
FreeLibrary( hDll );
}
else
{
dwErr = GetLastError();
}
isDebugOut((DEB_TRACE, "result of unregistering '%ws': %d\n", awcPath, dwErr ));
}
CATCH( CException, e )
{
// ignore, since it's probably the new html filter
}
END_CATCH
SetErrorMode( uiOld );
return 0; // explicitly ignore unregister errors
} //UnregisterDll
//+-------------------------------------------------------------------------
//
// Function: SetFilterRegistryInfo
//
// Synopsis: Installs registry info for Index Server filters
//
// Returns: Win32 error code
//
// History: 8-Jan-97 dlee Created
// 7-01-97 mohamedn cleanedup for IS3.0 with NT5.0 setup.
//
//--------------------------------------------------------------------------
DWORD SetFilterRegistryInfo( BOOL fUnRegister, CError &Err )
{
if ( fUnRegister )
{
// try to unregister old dlls
UnregisterDll( L"query.dll" );
UnregisterDll( L"htmlfilt.dll" );
UnregisterDll( L"nlfilt.dll" );
UnregisterDll( L"sccifilt.dll" );
UnregisterDll( L"ciadmin.dll" );
UnregisterDll( L"cifrmwrk.dll" );
UnregisterDll( L"fsci.dll" );
UnregisterDll( L"OffFilt.dll" );
UnregisterDll( L"ixsso.dll" );
UnregisterDll( L"ciodm.dll" );
UnregisterDll( L"infosoft.dll" );
UnregisterDll( L"mimefilt.dll" );
UnregisterDll( L"LangWrBk.dll" );
}
else
{
// call the .dlls to have them registered
for ( unsigned i = 0; i < cDlls; i++ )
{
DWORD dwErr = RegisterDll( apwcDlls[i], Err );
if ( NO_ERROR != dwErr )
{
isDebugOut(( DEB_ERROR, "Failed to register(%ws): error code: %d\n",
apwcDlls[i], dwErr ));
ISError(IS_MSG_DLL_REGISTRATION_FAILED , Err, LogSevError, dwErr );
return dwErr;
}
}
}
return NO_ERROR;
} //SetFilterregistryInfo
//+-------------------------------------------------------------------------
//
// Function: SetRegBasedOnMachine
//
// Synopsis: Sets Index Server registry tuning paramaters based on the
// capabilities of the machine. Uninstall is .inf-based.
//
// History: 8-Jan-97 dlee Created
//
//--------------------------------------------------------------------------
DWORD SetRegBasedOnMachine(CError &Err)
{
if ( 0 == gSetupInitComponent.ComponentInfHandle )
{
ISError( IS_MSG_INVALID_INF_HANDLE, Err, LogSevError );
return NO_ERROR;
}
WCHAR * pwcInf = 0;
BOOL fServer = FALSE;
switch(g_NtType)
{
case PRODUCT_SERVER_STANDALONE:
case PRODUCT_SERVER_PRIMARY:
case PRODUCT_SERVER_SECONDARY:
{
BOOL fLotsOfMem;
DWORD cCpu;
GetMachineInfo( fLotsOfMem, cCpu );
if ( fLotsOfMem )
{
if ( 1 == cCpu )
pwcInf = L"IndexSrv_Large";
else if ( 2 == cCpu )
pwcInf = L"IndexSrv_LargeMP2";
else
pwcInf = L"IndexSrv_LargeMPMany";
}
else
{
if ( 1 == cCpu )
pwcInf = L"IndexSrv_Small";
else
pwcInf = L"IndexSrv_SmallMP2";
}
}
fServer = TRUE;
break;
case PRODUCT_WORKSTATION:
default:
pwcInf = L"IndexSrv_Workstation";
}
if ( !SetupInstallFromInfSection( 0,
gSetupInitComponent.ComponentInfHandle,
pwcInf,
SPINST_REGISTRY,
0, 0, 0, 0, 0, 0, 0 ) )
return GetLastError();
// If a server, allow catalogs key to be read-only visible
// to the world. See KB Q155363
// Note: In Win2k, the professional version requires this as well,
// so I commented out the fServer check.
// if ( fServer )
{
CWin32RegAccess regAllowed( HKEY_LOCAL_MACHINE, wcsAllowedPaths );
WCHAR awcValue[ 8192 ];
if ( regAllowed.Get( L"Machine",
awcValue,
sizeof awcValue / sizeof WCHAR ) )
{
// don't re-add it if it already exists
BOOL fFound = FALSE;
WCHAR *p = awcValue;
while ( 0 != *p )
{
if ( !_wcsicmp( p, wcsRegAdminSubKey ) )
{
fFound = TRUE;
break;
}
while ( 0 != *p )
p++;
p++;
}
if ( !fFound )
{
wcscpy( p, wcsRegAdminSubKey );
p += ( 1 + wcslen( wcsRegAdminSubKey ) );
*p++ = 0;
if ( !regAllowed.SetMultiSZ( L"Machine",
awcValue,
(ULONG)(p-awcValue) * sizeof WCHAR ) )
{
DWORD dw = GetLastError();
ISError( IS_MSG_COULD_NOT_MODIFY_REGISTRY, Err, LogSevFatalError, dw );
return dw;
}
}
}
}
return NO_ERROR;
} //SetRegBasedOnMachine
//+-------------------------------------------------------------------------
//
// Function: SetRegBasedOnArchitecture
//
// Synopsis: Sets Index Server registry tuning paramaters based on the
// architecture. Uninstall is .inf-based.
//
// History: 24-Feb-98 KrishnaN Created
//
//--------------------------------------------------------------------------
DWORD SetRegBasedOnArchitecture(CError &Err)
{
if ( 0 == gSetupInitComponent.ComponentInfHandle )
{
Err.Report(LogSevError,0,L"Couldn't set registry based on architecture, Invalid Inf Handle");
return NO_ERROR;
}
WCHAR * pwcInf = 0;
#if defined (_X86_)
pwcInf = L"IndexSrv_X86";
#else
pwcInf = L"IndexSrv_RISC";
#endif
if ( !SetupInstallFromInfSection( 0,
gSetupInitComponent.ComponentInfHandle,
pwcInf,
SPINST_REGISTRY,
0, 0, 0, 0, 0, 0, 0 ) )
return GetLastError();
return NO_ERROR;
} //SetRegBasedOnArchitecture
//+-------------------------------------------------------------------------
//
// Function: GetMachineInfo
//
// Synopsis: Retrieves stats about the machine
//
// Arguments: fLotsOfMem -- returns TRUE if the machine has "lots" of mem
// cCPU -- returns a count of CPUs
//
// History: 8-Jan-97 dlee Created
//
//--------------------------------------------------------------------------
void GetMachineInfo(
BOOL & fLotsOfMem,
DWORD & cCPU )
{
SYSTEM_INFO si;
GetSystemInfo( &si );
cCPU = si.dwNumberOfProcessors;
MEMORYSTATUSEX memStatus;
memStatus.dwLength = sizeof( memStatus );
GlobalMemoryStatusEx( &memStatus );
fLotsOfMem = ( memStatus.ullTotalPhys >= 64000000 );
} //GetMachineInfo
//+-------------------------------------------------------------------------
//
// Function: isLogString
//
// Synopsis: Logs the string to %windir%\setupqry.log
//
// Arguments: pc -- ansi string
//
// History: 11-Nov-98 dlee Created
//
//--------------------------------------------------------------------------
BOOL g_fCalledYet = FALSE;
void isLogString( const char * pc )
{
WCHAR awc[ MAX_PATH ];
UINT ui = GetWindowsDirectory( awc, sizeof awc / sizeof WCHAR );
if ( 0 == ui )
return;
wcscat( awc, L"\\setupqry.log" );
WCHAR const * pwcOpen = L"a";
if ( !g_fCalledYet )
{
g_fCalledYet = TRUE;
pwcOpen = L"w";
}
FILE *fp = _wfopen( awc, pwcOpen );
if ( 0 != fp )
{
fprintf( fp, "%s", pc );
fclose( fp );
}
} //isLogString
//+-------------------------------------------------------------------------
//
// Function: SystemExceptionTranslator
//
// Synopsis: Translates system exceptions into C++ exceptions
//
// History: 1-Dec-98 dlee Copied from query.dll's version
//
//--------------------------------------------------------------------------
void _cdecl SystemExceptionTranslator(
unsigned int uiWhat,
struct _EXCEPTION_POINTERS * pexcept )
{
throw CException( uiWhat );
} //SystemExceptionTranslator
//+-------------------------------------------------------------------------
//
// Function: DeleteNTOPStartMenu
//
// Synopsis: Deletes start menu items created by IS in the NTOP
//
// History: 6-Jan-99 dlee Created
//
//--------------------------------------------------------------------------
void DeleteNTOPStartMenu()
{
//
// Ignore all failures here -- it's ok if the link don't exist
//
CWin32RegAccess reg( HKEY_LOCAL_MACHINE,
L"software\\microsoft\\windows\\currentversion\\explorer\\shell folders" );
WCHAR awc[MAX_PATH];
if ( reg.Get( L"common programs",
awc,
MAX_PATH ) )
{
//
// Build the directory where the links are located
//
wcscat( awc, L"\\" );
CResString strNTOP( IS_MSG_NTOP );
wcscat( awc, strNTOP.Get() );
wcscat( awc, L"\\" );
CResString strMIS( IS_MSG_START_MENU_NAME );
wcscat( awc, strMIS.Get() );
isDebugOut(( "NTOP start menu location: '%ws'\n", awc ));
//
// Delete the links
//
CResString strSample( IS_MSG_LINK_SAMPLE_NAME );
DeleteShellLink( awc, strSample.Get() );
isDebugOut(( "deleting NTOP item '%ws'\n", strSample.Get() ));
CResString strAdmin( IS_MSG_LINK_ADMIN_NAME );
DeleteShellLink( awc, strAdmin.Get() );
isDebugOut(( "deleting NTOP item '%ws'\n", strAdmin.Get() ));
CResString strMMC( IS_MSG_LINK_MMC_NAME );
DeleteShellLink( awc, strMMC.Get() );
isDebugOut(( "deleting NTOP item '%ws'\n", strMMC.Get() ));
//
// Note: when the last item is deleted, DeleteShellLink deletes
// the directory
//
}
} //DeleteNTOPStartMenu