windows-nt/Source/XPSP1/NT/inetsrv/iis/iisrearc/iisplus/ulw3/logging.cxx
2020-09-26 16:20:57 +08:00

442 lines
13 KiB
C++

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name :
logging.cxx
Abstract:
Handle Logging
Author:
Anil Ruia (AnilR) 1-Jul-2000
Environment:
Win32 - User Mode
Project:
w3core.dll
--*/
#include "precomp.hxx"
CONTEXT_STATUS W3_STATE_LOG::DoWork(
W3_MAIN_CONTEXT *pMainContext,
DWORD,
DWORD)
/*++
Routine Description:
Log the request (and call the END_OF_REQUEST notification)
Arguments:
pMainContext - W3_MAIN_CONTEXT representing an execution of the
state machine
Return Value:
CONTEXT_STATUS_CONTINUE - if we should continue in state machine
else stop executing the machine and free up the current thread
--*/
{
BOOL fUnused = FALSE;
if (pMainContext->QueryNeedFinalDone())
{
//
// Clear remaining chunks from handle/response state
//
pMainContext->QueryResponse()->Clear();
//
// End of request notifications happen BEFORE logging.
//
if ( pMainContext->IsNotificationNeeded( SF_NOTIFY_END_OF_REQUEST ) )
{
pMainContext->NotifyFilters( SF_NOTIFY_END_OF_REQUEST,
NULL,
&fUnused );
}
//
// Clear any crud from the last write from END_OF_REQUEST filter
//
pMainContext->QueryResponse()->Clear();
//
// Do the final send
//
pMainContext->SendEntity(W3_FLAG_PAST_END_OF_REQ);
}
if (pMainContext->QueryDoCustomLogging())
{
if (FAILED(pMainContext->CollectLoggingData(FALSE)))
{
goto Exit;
}
pMainContext->QuerySite()->LogInformation(pMainContext->QueryLogContext());
}
Exit:
return CONTEXT_STATUS_CONTINUE;
}
CONTEXT_STATUS W3_STATE_LOG::OnCompletion(
W3_MAIN_CONTEXT *pMainContext,
DWORD,
DWORD)
/*++
Routine Description:
Completion for the W3_STATE_LOG state
Arguments:
pMainContext - W3_MAIN_CONTEXT representing an execution of the
state machine
Return Value:
CONTEXT_STATUS_CONTINUE - if we should continue in state machine
else stop executing the machine and free up the current thread
--*/
{
//
// This code should never get hit
//
DBG_ASSERT(FALSE);
return CONTEXT_STATUS_CONTINUE;
}
HRESULT W3_MAIN_CONTEXT::CollectLoggingData(BOOL fCollectForULLogging)
/*++
Routine Description:
Routine which collects all the logging data
Arguments:
None
Return Value:
HRESULT
--*/
{
STACK_STRA(strVal, 64);
STACK_STRU(strValW, 64);
HRESULT hr = S_OK;
DWORD dwLength;
HTTP_LOG_FIELDS_DATA *pUlLogData = QueryUlLogData();
W3_REQUEST *pRequest = QueryRequest();
if (IsNotificationNeeded(SF_NOTIFY_LOG))
{
//
// There is a SF_NOTIFY_LOG filter, collect the data for the
// notification
//
HTTP_FILTER_LOG filtLog;
ZeroMemory(&filtLog, sizeof filtLog);
if (SUCCEEDED(GetServerVariableRemoteHost(this, &strVal)))
{
dwLength = strVal.QueryCCH() + 1;
if (FAILED(hr = _HeaderBuffer.AllocateSpace(
dwLength,
(PCHAR *)&filtLog.pszClientHostName)))
{
goto Exit;
}
strVal.CopyToBuffer((LPSTR)filtLog.pszClientHostName,
&dwLength);
}
if (SUCCEEDED(GetServerVariableLogonUser(this, &strVal)))
{
dwLength = strVal.QueryCCH() + 1;
if (FAILED(hr = _HeaderBuffer.AllocateSpace(
dwLength,
(PCHAR *)&filtLog.pszClientUserName)))
{
goto Exit;
}
strVal.CopyToBuffer((LPSTR)filtLog.pszClientUserName,
&dwLength);
}
else
{
filtLog.pszClientUserName = "";
}
if (SUCCEEDED(GetServerVariableLocalAddr(this, &strVal)))
{
dwLength = strVal.QueryCCH() + 1;
if (FAILED(hr = _HeaderBuffer.AllocateSpace(
dwLength,
(PCHAR *)&filtLog.pszServerName)))
{
goto Exit;
}
strVal.CopyToBuffer((LPSTR)filtLog.pszServerName,
&dwLength);
}
pRequest->QueryVerb((CHAR **)&filtLog.pszOperation, (USHORT *)&dwLength);
if (FAILED(hr = pRequest->GetUrl(&strValW)) ||
FAILED(hr = strVal.CopyWToUTF8(strValW)) ||
FAILED(hr = _HeaderBuffer.AllocateSpace(
strVal.QueryStr(),
strVal.QueryCCH(),
(CHAR **)&filtLog.pszTarget)))
{
goto Exit;
}
//
// If an ISAPI used HSE_APPEND_LOG_PARAMETER use it
//
if (_LogContext.m_strLogParam.IsEmpty())
{
pRequest->GetQueryStringA(&_LogContext.m_strLogParam);
}
filtLog.pszParameters = _LogContext.m_strLogParam.QueryStr();
filtLog.dwHttpStatus = QueryResponse()->QueryStatusCode();
if ( HRESULT_FACILITY( QueryErrorStatus() ) == FACILITY_WIN32 )
{
filtLog.dwWin32Status = WIN32_FROM_HRESULT( QueryErrorStatus() );
}
else
{
filtLog.dwWin32Status = QueryErrorStatus();
}
filtLog.dwBytesSent = _LogContext.m_dwBytesSent;
filtLog.dwBytesRecvd = _LogContext.m_dwBytesRecvd;
filtLog.msTimeForProcessing = GetTickCount() - _LogContext.m_msStartTickCount;
NotifyFilters(SF_NOTIFY_LOG, &filtLog, NULL);
//
// The filter may have changed some the data, copy it back to our
// logging structure
//
pUlLogData->ClientIp = (CHAR *)filtLog.pszClientHostName;
pUlLogData->ClientIpLength = (USHORT) strlen(filtLog.pszClientHostName);
if (FAILED(hr = strValW.CopyA(filtLog.pszClientUserName)) ||
FAILED(hr = _HeaderBuffer.AllocateSpace(
strValW.QueryStr(),
strValW.QueryCCH(),
&pUlLogData->UserName)))
{
goto Exit;
}
pUlLogData->UserNameLength =
(USHORT)(strValW.QueryCCH() * sizeof(WCHAR));
pUlLogData->ServerIp = (CHAR *)filtLog.pszServerName;
pUlLogData->ServerIpLength = (USHORT) strlen(filtLog.pszServerName);
pUlLogData->Method = (CHAR *)filtLog.pszOperation;
pUlLogData->MethodLength = (USHORT) strlen(filtLog.pszOperation);
if (FAILED(hr = strValW.CopyA(filtLog.pszTarget)) ||
FAILED(hr = _HeaderBuffer.AllocateSpace(
strValW.QueryStr(),
strValW.QueryCCH(),
&pUlLogData->UriStem)))
{
goto Exit;
}
pUlLogData->UriStemLength =
(USHORT)(strValW.QueryCCH() * sizeof(WCHAR));
pUlLogData->UriQuery = (CHAR *)filtLog.pszParameters;
pUlLogData->UriQueryLength = (USHORT) strlen(filtLog.pszParameters);
pUlLogData->ProtocolStatus = filtLog.dwHttpStatus;
pUlLogData->Win32Status = filtLog.dwWin32Status;
_LogContext.m_dwBytesSent = filtLog.dwBytesSent;
_LogContext.m_dwBytesRecvd = filtLog.dwBytesRecvd;
_LogContext.m_msProcessingTime = filtLog.msTimeForProcessing;
}
else
{
//
// No filter, just get the logging data
//
if (SUCCEEDED(GetServerVariableRemoteHost(this, &strVal)))
{
if (FAILED(hr = _HeaderBuffer.AllocateSpace(
strVal.QueryStr(),
strVal.QueryCCH(),
&pUlLogData->ClientIp)))
{
goto Exit;
}
pUlLogData->ClientIpLength = (USHORT)strVal.QueryCCH();
}
if ( QueryUserContext() == NULL )
{
if (FAILED(hr = pRequest->GetRequestUserName(&strVal)))
{
goto Exit;
}
if (strVal.IsEmpty())
{
pUlLogData->UserName = L"";
pUlLogData->UserNameLength = 0;
}
else
{
if (FAILED(hr = strValW.CopyA(strVal.QueryStr())) ||
FAILED(hr = _HeaderBuffer.AllocateSpace(
strValW.QueryStr(),
strValW.QueryCCH(),
&pUlLogData->UserName)))
{
goto Exit;
}
pUlLogData->UserNameLength = (USHORT)strValW.QueryCB();
}
}
else
{
pUlLogData->UserName = QueryUserContext()->QueryUserName();
if (pUlLogData->UserName)
{
pUlLogData->UserNameLength = wcslen(pUlLogData->UserName) * sizeof(WCHAR);
}
}
if (SUCCEEDED(GetServerVariableLocalAddr(this, &strVal)))
{
if (FAILED(hr = _HeaderBuffer.AllocateSpace(
strVal.QueryStr(),
strVal.QueryCCH(),
&pUlLogData->ServerIp)))
{
goto Exit;
}
pUlLogData->ServerIpLength =
(USHORT)strVal.QueryCCH();
}
pRequest->QueryVerb(&pUlLogData->Method,
&pUlLogData->MethodLength);
pRequest->QueryUrl(&pUlLogData->UriStem,
&pUlLogData->UriStemLength);
//
// If an ISAPI used HSE_APPEND_LOG_PARAMETER use it
//
if (_LogContext.m_strLogParam.IsEmpty())
{
pRequest->GetQueryStringA(&_LogContext.m_strLogParam);
}
pUlLogData->UriQuery = _LogContext.m_strLogParam.QueryStr();
pUlLogData->UriQueryLength = (USHORT)_LogContext.m_strLogParam.QueryCCH();
pUlLogData->ProtocolStatus = QueryResponse()->QueryStatusCode();
if ( HRESULT_FACILITY( QueryErrorStatus() ) == FACILITY_WIN32 )
{
pUlLogData->Win32Status = WIN32_FROM_HRESULT( QueryErrorStatus() );
}
else
{
pUlLogData->Win32Status = QueryErrorStatus();
}
}
//
// Now get data unaffected by any SF_NOTIFY_LOG filter
//
pUlLogData->ServerPort = pRequest->QueryLocalPort();
pUlLogData->ServiceName = QuerySite()->QueryName()->QueryStr();
pUlLogData->ServiceNameLength = (USHORT)QuerySite()->QueryName()->QueryCCH();
pUlLogData->ServerName = g_pW3Server->QueryComputerName();
pUlLogData->ServerNameLength = g_pW3Server->QueryComputerNameLength();
if (fCollectForULLogging)
{
pUlLogData->Host = pRequest->GetHeader(HttpHeaderHost,
&pUlLogData->HostLength);
pUlLogData->UserAgent = pRequest->GetHeader(HttpHeaderUserAgent,
&pUlLogData->UserAgentLength);
pUlLogData->Cookie = pRequest->GetHeader(HttpHeaderCookie,
&pUlLogData->CookieLength);
pUlLogData->Referrer = pRequest->GetHeader(HttpHeaderReferer,
&pUlLogData->ReferrerLength);
}
else
{
_LogContext.m_msProcessingTime =
GetTickCount() - _LogContext.m_msStartTickCount;
GetServerVariableHttpVersion(this,
&_LogContext.m_strVersion);
if (QuerySite()->IsRequiredExtraLoggingFields())
{
//
// If the custom logging module needs extra logging fields, get them
//
const MULTISZA *pmszExtraLoggingFields =
QuerySite()->QueryExtraLoggingFields();
LPSTR pszHeaderName = (LPSTR)pmszExtraLoggingFields->First();
while (pszHeaderName != NULL)
{
hr = SERVER_VARIABLE_HASH::GetServerVariable(
this,
pszHeaderName,
&strVal);
if (FAILED(hr))
{
goto Exit;
}
if (!_LogContext.m_mszHTTPHeaders.Append(strVal.QueryStr()))
{
hr = E_OUTOFMEMORY;
goto Exit;
}
pszHeaderName = (LPSTR)pmszExtraLoggingFields->Next(pszHeaderName);
}
}
}
Exit:
return hr;
}