442 lines
13 KiB
C++
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;
|
||
|
}
|