//+------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1996 - 2000. // // File: webhits.cxx // // History: 05-20-96 t-matts Created // 03-03-97 dlee Converted to isapi // // Contents: This is the main() for the hit-highliting feature. The // CGI environment variables are read, yielding the filename // and the textual form of the restriction. The textual form // is then converted to internal form. The document is then // scanned for hits, and the positions contained in those // hits are sorted. Finally, HTML tags are inserted in the order // in which the distinct positions appear in the document, to // allow the user to navigate. // //-------------------------------------------------------------------------- #include #pragma hdrstop #include #include #include #include #include #include #include #include #include #include #include "webhits.hxx" #include "webdbg.hxx" #include "whmsg.h" #include "linkhits.hxx" #define _DECL_DLLMAIN 1 DECLARE_INFOLEVEL (web); DECLARE_INFOLEVEL (ci); const int ERROR_MESSAGE_SIZE=512; BOOL g_fShutdown = TRUE; LONG g_cThreads = 0; CWebhitsInfo * g_pWebhitsInfo = 0; void OutputErrorMessage( CWebServer & webServer, CLanguageInfo & LanguageInfo, DWORD dwMsgId, WCHAR const * pwcIdqPPath, WCHAR const * pwcIdqVPath, WCHAR const * pwcHtwPPath, WCHAR const * pwcHtwVPath, WCHAR const * pwcWebhitsPPath, WCHAR const * pwcWebhitsVPath, WCHAR const * pwszDefaultMsg = 0, WCHAR const * pwszFileName = 0, ULONG ulFileLine = 0 ); //+--------------------------------------------------------------------------- // // Function: GetVPathInfo // // Synopsis: Convers a vpath to a ppath // // Arguments: [webServer] -- Used for the translation // [pwcVPath] -- VPath to translate // [dwAccessMask] -- Access required for file, or 0 for none // [dwFlags] -- Returns vpath flags (HSE_URL_FLAGS_*) // // Returns: pointer to PPath allocated on the heap. // // History: 3-04-97 dlee Created // //---------------------------------------------------------------------------- WCHAR * GetVPathInfo( CWebServer & webServer, WCHAR const * pwcVPath, DWORD dwAccessMask, DWORD & dwFlags ) { WCHAR *pwc = 0; TRY { WCHAR awcPPath[MAX_PATH]; dwFlags = webServer.GetPhysicalPath( pwcVPath, awcPPath, sizeof awcPPath / sizeof WCHAR, dwAccessMask ); if ( ( 0 == wcsstr( awcPPath, L"../" ) ) && ( 0 == wcsstr( awcPPath, L"..\\" ) ) ) { ULONG cwc = wcslen( awcPPath ) + 1; pwc = new WCHAR[ cwc ]; RtlCopyMemory( pwc, awcPPath, cwc * sizeof WCHAR ); } } CATCH( CException, e ) { // returning 0 is sufficient } END_CATCH return pwc; } //GetVPathInfo //+--------------------------------------------------------------------------- // // Function: GetWebhitsVPathInfo // // Synopsis: Converts vpaths to ppaths for the query, template, and // webhits files. // // Arguments: [vars] -- Source of vpaths, sink of ppaths // [webServer] -- Used for the translations // // History: 9-06-96 srikants Created // //---------------------------------------------------------------------------- void GetWebhitsVPathInfo( CGetEnvVars & vars, CWebServer & webServer ) { // Translate the path of the query (idq) file if one is given. DWORD dwFlags; if ( vars.GetQueryFileVPath() ) { WCHAR * pwc = GetVPathInfo( webServer, vars.GetQueryFileVPath(), 0, dwFlags ); if ( 0 == pwc ) THROW( CWTXException( MSG_WEBHITS_IDQ_NOT_FOUND, vars.GetQueryFileVPath(), 0 ) ); vars.AcceptQueryFilePPath( pwc, dwFlags ); webDebugOut(( DEB_ITRACE, "Query file '%ws'\n", pwc )); } // Translate the path of the template (htw) file if one is given. if ( vars.GetTemplateFileVPath() ) { WCHAR * pwc = GetVPathInfo( webServer, vars.GetTemplateFileVPath(), 0, dwFlags ); if ( 0 == pwc ) THROW( CWTXException( MSG_WEBHITS_NO_SUCH_TEMPLATE, vars.GetTemplateFileVPath(), 0 ) ); vars.AcceptTemplateFilePPath( pwc, dwFlags ); webDebugOut(( DEB_ITRACE, "Template file '%ws'\n", pwc )); } // Translate the path of the WebHits file being displayed. Read access // is required for this file. if ( vars.GetWebHitsFileVPath() ) { WCHAR * pwc = GetVPathInfo( webServer, vars.GetWebHitsFileVPath(), HSE_URL_FLAGS_READ, dwFlags ); if ( 0 == pwc ) THROW( CException(MSG_WEBHITS_PATH_INVALID) ); vars.AcceptWebHitsFilePPath( pwc, dwFlags ); webDebugOut(( DEB_ITRACE, "WebHits file '%ws'\n", pwc )); } else { THROW( CException(MSG_WEBHITS_PATH_INVALID) ); } } //GetWebhitsVPathInfo //+--------------------------------------------------------------------------- // // Function: ProcessWebRequest // // Synopsis: Main driver method for webhits. // // Arguments: [webServer] -- web server to use // // History: 9-04-96 srikants Created // //---------------------------------------------------------------------------- DWORD ProcessWebRequest( CWebServer & webServer ) { DWORD hse = HSE_STATUS_SUCCESS; // // Initialize the locale and codepage. // LCID lcid = GetLCID( webServer ); ULONG urlCodePage = GetBrowserCodepage( webServer, lcid ); CLanguageInfo langInfo; // // Set the client and output locale info to be the same as // the client info. If a different value is set // via CiLocale, it will be changed when the querystring is parsed. // langInfo.SetUrlLangInfo( urlCodePage, lcid ); langInfo.SetRestrictionLangInfo( urlCodePage, lcid ); CURLUnescaper unescaper( langInfo.GetUrlCodePage() ); CCollectVar varRetriever( unescaper, webServer ); XArray xwszQueryFile; WCHAR awcWebhitsPPath[ MAX_PATH ]; WCHAR awcWebhitsVPath[ MAX_PATH ]; WCHAR awcIdqPPath[ MAX_PATH ]; WCHAR awcIdqVPath[ MAX_PATH ]; WCHAR awcHtwPPath[ MAX_PATH ]; WCHAR awcHtwVPath[ MAX_PATH ]; WCHAR const * pwcWebhitsPPath = 0; WCHAR const * pwcWebhitsVPath = 0; WCHAR const * pwcIdqPPath = 0; WCHAR const * pwcIdqVPath = 0; WCHAR const * pwcHtwPPath = 0; WCHAR const * pwcHtwVPath = 0; TRY { // // Refresh the registry values if necessary // g_pWebhitsInfo->Refresh(); // // Are there too many threads doing webhits? // if ( g_cThreads > (LONG) g_pWebhitsInfo->GetMaxRunningWebhits() ) { webDebugOut(( DEB_WARN, "%d instances of webhits running\n", g_cThreads )); THROW( CException( MSG_WEBHITS_TOO_MANY_COPIES ) ); } // // Retrieve the necessary environment variables. // CGetEnvVars variables( webServer, langInfo, varRetriever, unescaper ); if (variables.GetQueryFileVPath()) { xwszQueryFile.Init( wcslen(variables.GetQueryFileVPath())+1 ); wcscpy( xwszQueryFile.GetPointer(), variables.GetQueryFileVPath() ); } GetWebhitsVPathInfo( variables, webServer ); // // construct Property List with static properties // XInterface xlist; // // If an idq file was specified, then parse the [NAMES] section of // that file to obtain custom properties // if ( variables.GetQueryFilePPath() ) { Win4Assert( wcslen( variables.GetQueryFilePPath() ) < MAX_PATH ); wcscpy( awcIdqPPath, variables.GetQueryFilePPath() ); pwcIdqPPath = awcIdqPPath; Win4Assert( wcslen( variables.GetQueryFileVPath() ) < MAX_PATH ); wcscpy( awcIdqVPath, variables.GetQueryFileVPath() ); pwcIdqVPath = awcIdqVPath; xlist.Set( new CLocalGlobalPropertyList( GetGlobalStaticPropertyList(), TRUE, variables.GetQueryFilePPath(), langInfo.GetUrlCodePage()) ); ULONG iLine; WCHAR * pwszFile; SCODE sc = ((CLocalGlobalPropertyList *)xlist.GetPointer())->CheckError( iLine, &pwszFile ); if (FAILED(sc)) THROW(CException(sc)); } else xlist.Set(GetGlobalStaticPropertyList()); // // If a template file is specified, it should be parsed. // XPtr xTemplate; if ( variables.GetTemplateFileVPath() ) { Win4Assert( wcslen( variables.GetTemplateFilePPath() ) < MAX_PATH ); wcscpy( awcHtwPPath, variables.GetTemplateFilePPath() ); pwcHtwPPath = awcHtwPPath; Win4Assert( wcslen( variables.GetTemplateFileVPath() ) < MAX_PATH ); wcscpy( awcHtwVPath, variables.GetTemplateFileVPath() ); pwcHtwVPath = awcHtwVPath; CWebhitsTemplate * pTemplate = new CWebhitsTemplate( variables, langInfo.GetOutputCodePage() ); xTemplate.Set( pTemplate ); } // // convert textual query into CDbRestriction // CInternalQuery query( variables, xlist.GetReference(), langInfo.GetQueryLCID() ); Win4Assert( wcslen( variables.GetWebHitsFilePPath() ) < MAX_PATH ); wcscpy( awcWebhitsPPath, variables.GetWebHitsFilePPath() ); pwcWebhitsPPath = awcWebhitsPPath; Win4Assert( wcslen( variables.GetWebHitsFileVPath() ) < MAX_PATH ); wcscpy( awcWebhitsVPath, variables.GetWebHitsFileVPath() ); pwcWebhitsVPath = awcWebhitsVPath; // // Verify a consistent SSL-setting for .htw and webhits files. // This fixes the problem where the webhits file requires SSL, // but the template file doesn't, since a port can't change its // SSL setting on the fly. A work-around would be to do a redirect // to a bogus .htw file in the same virtual directory as the // webhits file to force SSL, but that seemed overkill. // if ( variables.GetTemplateFileVPath() ) { // // This is a complete list of SSL-related flags. // const DWORD dwSSL = HSE_URL_FLAGS_SSL | HSE_URL_FLAGS_NEGO_CERT | HSE_URL_FLAGS_REQUIRE_CERT | HSE_URL_FLAGS_MAP_CERT | HSE_URL_FLAGS_SSL128; DWORD dwTemplate = ( variables.GetTemplateFileFlags() & dwSSL ); DWORD dwWebHits = ( variables.GetWebHitsFileFlags() & dwSSL ); if ( ( dwTemplate != dwWebHits ) && ( 0 != dwWebHits ) ) { webDebugOut(( DEB_WARN, "SSL mismatch template: 0x%x, webhits: 0x%x\n", dwTemplate, dwWebHits )); THROW( CException( MSG_WEBHITS_INCONSISTENT_SSL ) ); } } // // Impersonate if the file being webhit is remote // CImpersonateRemoteAccess imp( 0 ); if ( CImpersonateRemoteAccess::IsNetPath( pwcWebhitsPPath ) ) { CImpersonationTokenCache * pCache = g_pWebhitsInfo->GetTokenCache( webServer ); imp.SetTokenCache( pCache ); // Flip the slashes -- the token cache expects backslashes... unsigned cwc = wcslen( pwcWebhitsVPath ); Win4Assert( cwc < MAX_PATH ); WCHAR awcTempVPath[ MAX_PATH ]; for ( unsigned c = 0; c < cwc; c++ ) { if ( L'/' == pwcWebhitsVPath[c] ) awcTempVPath[c] = L'\\'; else awcTempVPath[c] = pwcWebhitsVPath[c]; } awcTempVPath[ cwc ] = 0; // // If impersonation fails, try rescanning the metabase. // There may have been an update to vroot info. // Note that revocation may take a long time as a result. // It's really unlikely we'll have to reinit very often // unless the server is misconfigured. // if ( !imp.ImpersonateIfNoThrow( pwcWebhitsPPath, awcTempVPath ) ) { pCache->ReInitializeIISScopes(); imp.ImpersonateIf( pwcWebhitsPPath, awcTempVPath ); } } // // construct framework for highlighting, and highlight hits // query.CreateISearch( pwcWebhitsPPath ); // // two cases - either summary or full hit-highlighting // CReleasableLock lock( g_pWebhitsInfo->GetNonThreadedFilterMutex(), FALSE ); if (variables.GetHiliteType() == CGetEnvVars::SUMMARY) { XPtr xDoc( new CDocument( (WCHAR*) pwcWebhitsPPath, CLinkQueryHits::BOGUS_RANK, query.GetISearchRef(), g_pWebhitsInfo->GetMaxWebhitsCpuTime(), lock, xlist.GetReference(), g_pWebhitsInfo->GetDisplayScript() ) ); PHttpOutput httpOutput( webServer, langInfo ); httpOutput.Init( &variables, xTemplate.GetPointer() ); HitIter iterator; iterator.Init( xDoc.GetPointer() ); httpOutput.OutputHTMLHeader(); if ( variables.IsFixedFont() ) httpOutput.OutputPreformattedTag(); CExtractHits hitExtractor( xDoc.GetReference(), iterator, httpOutput ); httpOutput.OutputHTMLFooter(); } else { PHttpFullOutput httpOutput( webServer, langInfo ); httpOutput.Init(&variables, xTemplate.GetPointer()); XPtr xLQH( new CLinkQueryHits( query, variables, httpOutput, g_pWebhitsInfo->GetMaxWebhitsCpuTime(), lock, xlist.GetReference(), g_pWebhitsInfo->GetDisplayScript() ) ); httpOutput.OutputHTMLHeader(); xLQH->InsertLinks(); httpOutput.OutputHTMLFooter(); } } CATCH( CPListException, ple ) { WCHAR wcTempBuffer[ERROR_MESSAGE_SIZE]; wsprintf( wcTempBuffer, L"Property list parsing query file %ls failed with error 0x%X\n", xwszQueryFile.GetPointer(), ple.GetPListError() ); OutputErrorMessage( webServer, langInfo, ple.GetPListError(), pwcIdqPPath, pwcIdqVPath, pwcHtwPPath, pwcHtwVPath, pwcWebhitsPPath, pwcWebhitsVPath, wcTempBuffer, xwszQueryFile.GetPointer(), ple.GetLine() ); } AND_CATCH( CWTXException, we ) { WCHAR wcTempBuffer[ERROR_MESSAGE_SIZE]; wsprintf( wcTempBuffer, L"Parsing template file %ls failed with error 0x%X\n", we.GetFileName(), we.GetErrorCode() ); OutputErrorMessage( webServer, langInfo, we.GetErrorCode(), pwcIdqPPath, pwcIdqVPath, pwcHtwPPath, pwcHtwVPath, pwcWebhitsPPath, pwcWebhitsVPath, wcTempBuffer, we.GetFileName(), we.GetLineNumber() ); } AND_CATCH( CParserException, pe ) { WCHAR wcTempBuffer[ERROR_MESSAGE_SIZE]; wsprintf( wcTempBuffer, L"Parsing of QUERY_STRING failed with error 0x%X\n", pe.GetErrorCode() ); OutputErrorMessage( webServer, langInfo, pe.GetParseError(), pwcIdqPPath, pwcIdqVPath, pwcHtwPPath, pwcHtwVPath, pwcWebhitsPPath, pwcWebhitsVPath, wcTempBuffer ); } AND_CATCH( CException,e ) { OutputErrorMessage( webServer, langInfo, e.GetErrorCode(), pwcIdqPPath, pwcIdqVPath, pwcHtwPPath, pwcHtwVPath, pwcWebhitsPPath, pwcWebhitsVPath ); } END_CATCH return hse; } //ProcessWebRequest //+--------------------------------------------------------------------------- // // Function: OutputErrorMessage // // Synopsis: Outputs an error message based on the msg id given. It first // looks up for the error in webhits.dll, query.dll, then in // kernel32.dll. // If no message is found, it then uses the default message. // // Arguments: [dwMsgId] - Message id // [pwszDefaultMsg] - Pointer to the default message. Will be // used if there is no pre-formatted message. // [pwszFileName] - File name to be printed prior to the error // message. Will not be printed if null. // [ulFileLine] - File line number. Not printed if zero. // // History: 9-04-96 srikants Created // //---------------------------------------------------------------------------- void OutputErrorMessage( CWebServer & webServer, CLanguageInfo & langInfo, DWORD dwMsgId, WCHAR const * pwcIdqPPath, WCHAR const * pwcIdqVPath, WCHAR const * pwcHtwPPath, WCHAR const * pwcHtwVPath, WCHAR const * pwcWebhitsPPath, WCHAR const * pwcWebhitsVPath, WCHAR const * pwszDefaultMsg, WCHAR const * pwszFileName, ULONG ulFileLine ) { CImpersonateSystem system; // // If the error was the result of an access denied problem, then simply // return a 401 error to the browser if the path allows authentication // // Generate the Win32 error code by removing the facility code (7) and // the error bit. // if ( (STATUS_ACCESS_DENIED == dwMsgId) || (STATUS_NETWORK_ACCESS_DENIED == dwMsgId) || (HRESULT_FROM_WIN32( ERROR_ACCESS_DENIED ) == dwMsgId) || (HRESULT_FROM_WIN32( ERROR_INVALID_ACCESS ) == dwMsgId) || (HRESULT_FROM_WIN32( ERROR_NETWORK_ACCESS_DENIED ) == dwMsgId) ) { WCHAR const * pwcVPath = 0; WCHAR const * pwcPPath = 0; if ( 0 != pwcWebhitsVPath ) { pwcPPath = pwcWebhitsPPath; pwcVPath = pwcWebhitsVPath; } else if ( 0 != pwcHtwVPath ) { pwcPPath = pwcHtwPPath; pwcVPath = pwcHtwVPath; } else { pwcPPath = pwcIdqPPath; pwcVPath = pwcIdqVPath; } Win4Assert( 0 != pwcPPath ); Win4Assert( 0 != pwcVPath ); webDebugOut(( DEB_ITRACE, "error P and V paths: '%ws', '%ws'\n", pwcPPath, pwcVPath )); CMetaDataMgr mdMgr( FALSE, W3VRoot, webServer.GetServerInstance() ); ULONG Authorization = mdMgr.GetVPathAuthorization( pwcVPath ); webDebugOut(( DEB_ITRACE, "authorization: 0x%x\n", Authorization )); // If the virtual directory doesn't support just anonymous, // this is not a remote physical path, try to authenticate. if ( 0 != Authorization && MD_AUTH_ANONYMOUS != Authorization && !CImpersonateRemoteAccess::IsNetPath( pwcPPath ) ) { webDebugOut(( DEB_WARN, "mapping 0x%x to 401 access denied\n", dwMsgId )); webServer.WriteHeader( 0, "401 Access denied" ); const char * pcAccessDenied = "Access is denied."; webServer.WriteClient( (BYTE *) pcAccessDenied, strlen( pcAccessDenied ) ); return; } } WCHAR awcTempBuffer[ERROR_MESSAGE_SIZE]; WCHAR * pwszErrorMessage = awcTempBuffer; ULONG cchAvailMessage = ERROR_MESSAGE_SIZE; // // Don't pass a specific lang id to FormatMessage since it will // fail if there's no message in that language. Instead set // the thread locale, which will get FormatMessage to use a search // algorithm to find a message of the appropriate language or // use a reasonable fallback msg if there's none. // LCID SaveLCID = GetThreadLocale(); SetThreadLocale( langInfo.GetQueryLCID() ); if (pwszFileName != 0) { // // These are errors encountered while parsing the [names] section // DWORD_PTR args [] = { (DWORD_PTR) pwszFileName, (DWORD_PTR) ulFileLine, }; NTSTATUS MsgNum = MSG_WEBHITS_FILE_MESSAGE; if ( 0 != ulFileLine ) MsgNum = MSG_WEBHITS_FILE_LINE_MESSAGE; ULONG cchMsg = FormatMessage( FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ARGUMENT_ARRAY, GetModuleHandle(L"webhits.dll"), MsgNum, 0, pwszErrorMessage, cchAvailMessage, (va_list *) args ); pwszErrorMessage += cchMsg; cchAvailMessage -= cchMsg; } if ( !FormatMessage( FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ARGUMENT_ARRAY, GetModuleHandle(L"webhits.dll"), dwMsgId, 0, pwszErrorMessage, cchAvailMessage, 0 ) && !FormatMessage( FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ARGUMENT_ARRAY, GetModuleHandle(L"Query.dll"), dwMsgId, 0, pwszErrorMessage, cchAvailMessage, 0 ) && !FormatMessage( FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ARGUMENT_ARRAY, GetModuleHandle(L"kernel32.dll"), dwMsgId, 0, pwszErrorMessage, cchAvailMessage, 0 ) && !FormatMessage( FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ARGUMENT_ARRAY, GetModuleHandle(L"kernel32.dll"), HRESULT_CODE(dwMsgId), 0, pwszErrorMessage, cchAvailMessage, 0 ) ) { DWORD dwError = GetLastError(); webDebugOut(( DEB_ERROR, "Format Message failed with error 0x%X\n", dwError )); if ( !pwszDefaultMsg ) { wsprintf( pwszErrorMessage, L"Error 0x%X occurred while running webhits \n", dwMsgId ); } else { Win4Assert( wcslen( pwszDefaultMsg ) < cchAvailMessage ); wsprintf( pwszErrorMessage, L"%ws\n", pwszDefaultMsg ); } } SetThreadLocale(SaveLCID); PHttpOutput httpOutput( webServer, langInfo ); httpOutput.OutputErrorHeader(); httpOutput.OutputErrorMessage( awcTempBuffer, wcslen(awcTempBuffer) ); httpOutput.OutputHTMLFooter(); } //OutputErrorMessage //+--------------------------------------------------------------------------- // // Function: GetExtensionVersion - public // // Synposis: Returns extension info to the server. This is called before // HttpExtensionProc is called, and it is called in System // context, so any initialization that requires this context // must be handled here. // // Arguments: [pVer] - where the info goes // // History: 96-Apr-15 dlee Added header // //---------------------------------------------------------------------------- BOOL WINAPI GetExtensionVersion( HSE_VERSION_INFO * pVer ) { BOOL fOK = TRUE; TRANSLATE_EXCEPTIONS; TRY { Win4Assert( g_fShutdown ); Win4Assert( 0 == g_pWebhitsInfo ); pVer->dwExtensionVersion = MAKELONG( 0, 3 ); strcpy( pVer->lpszExtensionDesc, "Indexing Service webhits extension" ); g_pWebhitsInfo = new CWebhitsInfo(); g_fShutdown = FALSE; } CATCH( CException, e ) { fOK = FALSE; webDebugOut(( DEB_WARN, "GetExtensionVersion failed 0x%x\n", e.GetErrorCode() )); } END_CATCH UNTRANSLATE_EXCEPTIONS; return fOK; } //GetExtensionVersion //+--------------------------------------------------------------------------- // // Function: TerminateExtension, public // // Synposis: Called by IIS during shutdown // // History: 3-Mar-97 dlee Created // //---------------------------------------------------------------------------- BOOL WINAPI TerminateExtension( DWORD dwFlags ) { TRANSLATE_EXCEPTIONS; BOOL fOK = FALSE; if ( dwFlags & HSE_TERM_MUST_UNLOAD ) { TRY { Win4Assert( !g_fShutdown ); g_fShutdown = TRUE; webDebugOut(( DEB_WARN, "Mandatory extension unload. Shutting down webhits.\n" )); // wait for all the isapi request threads to finish while ( 0 != g_cThreads ) Sleep( 50 ); delete g_pWebhitsInfo; g_pWebhitsInfo = 0; CIShutdown(); } CATCH( CException, e ) { // ignore } END_CATCH fOK = TRUE; } webDebugOut(( DEB_WARN, "webhits extension unload: 0x%x. Flags = 0x%x\n", fOK, dwFlags )); UNTRANSLATE_EXCEPTIONS; return fOK; } //TerminateExtension //+--------------------------------------------------------------------------- // // Function: HttpExtensionProc, public // // Synposis: Handles a request from the web server // // Arguments: [pEcb] -- block from the server // // History: 3-Mar-97 dlee Created // //---------------------------------------------------------------------------- DWORD WINAPI HttpExtensionProc( EXTENSION_CONTROL_BLOCK * pEcb ) { if ( g_fShutdown ) { pEcb->dwHttpStatusCode = HTTP_STATUS_SERVER_ERROR; return HSE_STATUS_ERROR; } InterlockedIncrement( & g_cThreads ); CWebServer webServer( pEcb ); DWORD hseStatus = HSE_STATUS_ERROR; webServer.SetHttpStatus( HTTP_STATUS_OK ); TRANSLATE_EXCEPTIONS; TRY { XCom xcom; hseStatus = ProcessWebRequest( webServer ); } CATCH( CException, e ) { hseStatus = HSE_STATUS_ERROR; webServer.SetHttpStatus( HTTP_STATUS_SERVER_ERROR ); } END_CATCH UNTRANSLATE_EXCEPTIONS; Win4Assert( HSE_STATUS_PENDING != hseStatus ); InterlockedDecrement( & g_cThreads ); return hseStatus; } //HttpExtensionProc //+--------------------------------------------------------------------------- // // Method: CWebhitsInfo::CWebhitsInfo, public // // Synposis: Constructs a webhits info object // // History: 18-Aug-97 dlee Created // //---------------------------------------------------------------------------- CWebhitsInfo::CWebhitsInfo() : _regChangeEvent( wcsRegAdminTree ) { ReadRegValues(); } //CWebhitsInfo //+--------------------------------------------------------------------------- // // Method: CWebhitsInfo::Refresh, public // // Synposis: Checks to see if the registry has changed and refreshes it // // History: 18-Aug-97 dlee Created // //---------------------------------------------------------------------------- void CWebhitsInfo::Refresh() { CLock lock( _mutex ); ULONG res = WaitForSingleObject( _regChangeEvent.GetEventHandle(), 0 ); if ( WAIT_OBJECT_0 == res ) { ReadRegValues(); _regChangeEvent.Reset(); } } //Refresh //+--------------------------------------------------------------------------- // // Method: CWebhitsInfo::ReadRegValues // // Synposis: Reads webhits registry info // // History: 18-Aug-97 dlee Created // //---------------------------------------------------------------------------- void CWebhitsInfo::ReadRegValues() { CRegAccess reg( RTL_REGISTRY_CONTROL, wcsRegAdmin ); const ULONG CI_RUNNING_WEBHITS_DEFAULT = 20; const ULONG CI_RUNNING_WEBHITS_MIN = 1; const ULONG CI_RUNNING_WEBHITS_MAX = 200; ULONG ul = reg.Read( wcsMaxRunningWebhits, CI_RUNNING_WEBHITS_DEFAULT ); _cMaxRunningWebhits = Range( ul, CI_RUNNING_WEBHITS_MIN, CI_RUNNING_WEBHITS_MAX ); const ULONG CI_WEBHITS_DISPLAY_SCRIPT_DEFAULT = DISPLAY_SCRIPT_KNOWN_FILTER; const ULONG CI_WEBHITS_DISPLAY_SCRIPT_MIN = 0; const ULONG CI_WEBHITS_DISPLAY_SCRIPT_MAX = 2; ul = reg.Read( wcsWebhitsDisplayScript, CI_WEBHITS_DISPLAY_SCRIPT_DEFAULT ); _ulDisplayScript = Range( ul, CI_WEBHITS_DISPLAY_SCRIPT_MIN, CI_WEBHITS_DISPLAY_SCRIPT_MAX ); const ULONG CI_WEBHITS_TIMEOUT_DEFAULT = 30; const ULONG CI_WEBHITS_TIMEOUT_MIN = 5; const ULONG CI_WEBHITS_TIMEOUT_MAX = 7200; ul = reg.Read( wcsMaxWebhitsCpuTime, CI_WEBHITS_TIMEOUT_DEFAULT ); _cmsMaxWebhitsCpuTime = Range( ul, CI_WEBHITS_TIMEOUT_MIN, CI_WEBHITS_TIMEOUT_MAX ); } //ReadRegValues //+--------------------------------------------------------------------------- // // Method: GetTokenCache, public // // Synposis: Retrieves the appropriate token cache for the web server // // Arguments: [webServer] -- The web server instance // // History: 18-Aug-97 dlee Created // //---------------------------------------------------------------------------- CImpersonationTokenCache * CWebhitsInfo::GetTokenCache( CWebServer & webServer ) { // // Get the server instance of this ISAPI request // ULONG ulInstance = webServer.GetServerInstance(); // // Look for a token cache for this server instance // CLock lock( _mutex ); for ( unsigned x = 0; x < _aTokenCache.Count(); x++ ) { Win4Assert( 0 != _aTokenCache[ x ] ); if ( _aTokenCache[ x ]->GetW3Instance() == ulInstance ) return _aTokenCache[ x ]; } // // Not found, so create a new token cache // CImpersonateSystem system; XPtr xCache( new CImpersonationTokenCache( L"" ) ); xCache->Initialize( L"webhits", // arbitrary name of token cache TRUE, // w3svc FALSE, // not nntp FALSE, // not imap ulInstance, // virtual server instance number 0, // no nntp vserver instance 0 ); // no imap vserver instance _aTokenCache[ _aTokenCache.Count() ] = xCache.GetPointer(); return xCache.Acquire(); } //GetTokenCache