//+------------------------------------------------------------------------- // // 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 #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; // - "\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