Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

448 lines
12 KiB

/*++
Copyright (c) 2000-2001 Microsoft Corporation
Module Name:
errlogp.h driver wide Error Logging module
Abstract:
Private header file for the Error Logging.
Author:
Ali E. Turkoglu (aliTu) 30-Jan-2002
Revision History:
---
--*/
#ifndef _ERRLOGP_H_
#define _ERRLOGP_H_
///////////////////////////////////////////////////////////////////////////////
//
// Private definitions for the HTTP Error Logging Module
//
///////////////////////////////////////////////////////////////////////////////
//
// Version numbers for the original raw binary format.
//
#define MAJOR_ERROR_LOG_FILE_VERSION (1)
#define MINOR_ERROR_LOG_FILE_VERSION (0)
//
// FileName specific constants
//
#define ERROR_LOG_FILE_NAME_PREFIX L"\\httperr"
#define ERROR_LOG_FILE_NAME_EXTENSION L"log"
#define ERROR_LOG_FILE_NAME_EXTENSION_PLUS_DOT L".log"
#define ERROR_LOG_FIELD_SEPERATOR_CHAR ' '
#define ERROR_LOG_FIELD_NOT_EXISTS_CHAR '-'
#define ERROR_LOG_FIELD_BAD_CHAR '+'
//
// Macro for a max err log file (i.e. "\httperr1234567890.log")
//
#define ERROR_LOG_MAX_FULL_FILE_NAME_LENGTH \
( \
WCSLEN_LIT(ERROR_LOG_FILE_NAME_PREFIX) \
+ \
MAX_ULONG_STR \
+ \
WCSLEN_LIT(ERROR_LOG_FILE_NAME_EXTENSION_PLUS_DOT) \
)
#define ERROR_LOG_MAX_FULL_FILE_NAME_SIZE \
(ERROR_LOG_MAX_FULL_FILE_NAME_LENGTH * sizeof(WCHAR))
C_ASSERT(UL_MAX_FILE_NAME_SUFFIX_LENGTH >= ERROR_LOG_MAX_FULL_FILE_NAME_LENGTH);
C_ASSERT(WCSLEN_LIT(DEFAULT_ERROR_LOGGING_DIR) <= MAX_PATH);
#define ERR_DATE_FIELD_LEN (10)
#define ERR_TIME_FIELD_LEN (8)
/*
Error logging Format
1. Date-Time (W3C Format)
2. Client IP:port
3. Server IP:port
4. Protocol-version
5. Verb
6. URL & Query
7. Protocol-status-code (401, etc)
8. SiteId
9. Information field
10. \r\n
*/
#define MAX_ERROR_LOG_FIX_FIELD_OVERHEAD \
( ERR_DATE_FIELD_LEN + 1 /* Date */ \
+ ERR_TIME_FIELD_LEN + 1 /* Time */ \
+ UL_HTTP_VERSION_LENGTH + 1 /* Protocol Version */ \
+ MAX_VERB_LENGTH + 1 /* Verb */ \
+ 3 + 1 /* Protocol Status */ \
+ MAX_IP_ADDR_STRING_LEN + 1 + MAX_PORT_LENGTH + 1 /* Client Ip Port */ \
+ MAX_IP_ADDR_STRING_LEN + 1 + MAX_PORT_LENGTH + 1 /* Server Ip Port */ \
+ 1 + 1 /* For empty Uri plus seperator */ \
+ MAX_ULONG_STR + 1 /* For SiteId plus seperator */ \
+ 1 + 1 /* For empty Info plus seperator */ \
+ 2 /* \r\n */ \
)
//
// Error Log file entry
//
typedef struct _UL_ERROR_LOG_FILE_ENTRY
{
//
// Must be UL_ERROR_LOG_FILE_ENTRY_POOL_TAG.
//
ULONG Signature;
//
// This lock protects the shared writes and exclusive flushes.
// It has to be push lock since the ZwWrite operation
// cannot run at APC_LEVEL.
//
UL_PUSH_LOCK PushLock;
//
// The name of the file. Full path including the directory.
//
UNICODE_STRING FileName;
PWSTR pShortName;
//
// Following will be NULL until a request comes in to the
// site that this entry represents.
//
PUL_LOG_FILE_HANDLE pLogFile;
//
// Recycling information.
//
ULONG TruncateSize;
ULONG SequenceNumber;
ULARGE_INTEGER TotalWritten;
//
// For Log File ReCycling based on GMT time.
// And periodic buffer flushing.
//
UL_LOG_TIMER BufferTimer;
UL_WORK_ITEM WorkItem; // For the pasive worker
LONG WorkItemScheduled; // To protect against multiple queueing
union
{
//
// Flags to show the entry states mostly. Used by
// recycling.
//
ULONG Value;
struct
{
ULONG StaleSequenceNumber:1;
ULONG RecyclePending:1;
ULONG Active:1;
ULONG WriteFailureLogged:1;
ULONG CreateFileFailureLogged:1;
};
} Flags;
//
// The default buffer size is g_AllocationGranularity.
// The operating system's allocation granularity.
//
PUL_LOG_FILE_BUFFER LogBuffer;
} UL_ERROR_LOG_FILE_ENTRY, *PUL_ERROR_LOG_FILE_ENTRY;
#define IS_VALID_ERROR_LOG_FILE_ENTRY( pEntry ) \
( (pEntry != NULL) && ((pEntry)->Signature == UL_ERROR_LOG_FILE_ENTRY_POOL_TAG) )
///////////////////////////////////////////////////////////////////////////////
//
// Private function calls
//
///////////////////////////////////////////////////////////////////////////////
VOID
UlpErrorLogBufferTimerDpcRoutine(
PKDPC Dpc,
PVOID DeferredContext,
PVOID SystemArgument1,
PVOID SystemArgument2
);
VOID
UlpErrorLogBufferTimerHandler(
IN PUL_WORK_ITEM pWorkItem
);
NTSTATUS
UlpCreateErrorLogFile(
IN OUT PUL_ERROR_LOG_FILE_ENTRY pEntry
);
NTSTATUS
UlpFlushErrorLogFile(
IN PUL_ERROR_LOG_FILE_ENTRY pEntry
);
NTSTATUS
UlpDisableErrorLogEntry(
IN OUT PUL_ERROR_LOG_FILE_ENTRY pEntry
);
NTSTATUS
UlpRecycleErrorLogFile(
IN OUT PUL_ERROR_LOG_FILE_ENTRY pEntry
);
NTSTATUS
UlpHandleErrorLogFileRecycle(
IN OUT PVOID pContext
);
PUL_ERROR_LOG_BUFFER
UlpAllocErrorLogBuffer(
IN ULONG BufferSize
);
VOID
UlpFreeErrorLogBuffer(
IN OUT PUL_ERROR_LOG_BUFFER pErrorLogBuffer
);
NTSTATUS
UlpBuildErrorLogRecord(
IN PUL_ERROR_LOG_INFO pLogInfo
);
NTSTATUS
UlpWriteToErrorLogFileDebug(
IN PUL_ERROR_LOG_FILE_ENTRY pEntry,
IN ULONG RecordSize,
IN PUCHAR pUserRecord
);
NTSTATUS
UlpWriteToErrorLogFileShared(
IN PUL_ERROR_LOG_FILE_ENTRY pEntry,
IN ULONG RecordSize,
IN PUCHAR pUserRecord
);
NTSTATUS
UlpWriteToErrorLogFileExclusive(
IN PUL_ERROR_LOG_FILE_ENTRY pEntry,
IN ULONG RecordSize,
IN PUCHAR pUserRecord
);
NTSTATUS
UlpWriteToErrorLogFile(
IN PUL_ERROR_LOG_FILE_ENTRY pEntry,
IN ULONG RecordSize,
IN PUCHAR pUserRecord
);
/***************************************************************************++
Routine Description:
Error log files are always recycled based on size.
Arguments:
pEntry: The error log file entry.
NewRecordSize: The size of the new record going to the buffer. (Bytes)
--***************************************************************************/
__inline
BOOLEAN
UlpIsErrorLogFileOverFlow(
IN PUL_ERROR_LOG_FILE_ENTRY pEntry,
IN ULONG NewRecordSize
)
{
//
// If infinite then no rollover.
//
if (pEntry->TruncateSize == HTTP_LIMIT_INFINITE)
{
return FALSE;
}
else
{
//
// BufferUsed: Amount of log buffer we are >currently< using.
//
ULONG BufferUsed = 0;
if (pEntry->LogBuffer)
{
BufferUsed = pEntry->LogBuffer->BufferUsed;
}
//
// TotalWritten get updated >only< with buffer flush. Therefore
// we have to pay attention to the buffer used.
//
if ((pEntry->TotalWritten.QuadPart
+ (ULONGLONG) BufferUsed
+ (ULONGLONG) NewRecordSize
) >= (ULONGLONG) pEntry->TruncateSize)
{
UlTrace(ERROR_LOGGING,
("Http!UlpIsErrorLogFileOverFlow: pEntry %p FileBuffer %p "
"TW:%I64d B:%d R:%d T:%d\n",
pEntry,
pEntry->LogBuffer,
pEntry->TotalWritten.QuadPart,
BufferUsed,
NewRecordSize,
pEntry->TruncateSize
));
return TRUE;
}
else
{
return FALSE;
}
}
}
/***************************************************************************++
Routine Description:
Error log files are always recycled based on size.
Arguments:
pRequest: Internal request structure.
Returns
# of bytes of the picked url. Zero if nothing needs to be logged.
--***************************************************************************/
__inline
ULONG
UlpCalculateUrlSize(
IN PUL_INTERNAL_REQUEST pRequest,
OUT PBOOLEAN pbLogRawUrl
)
{
//
// Following macro is to test whether Abs Path is really pointing to
// the original Url buffer rather than to an arbitrary buffer like g_SlashPath.
// See 527947 and 765769.
//
#define ABS_PATH_SAFE(pUrl,pAbs,length) \
((pAbs) && \
(pUrl) && \
((pAbs) >= (pUrl)) && \
(((ULONG_PTR) (length)) > \
DIFF_ULONGPTR((PUCHAR)(pAbs) - (PUCHAR)(pUrl)) ) \
)
ULONG UrlSize = 0;
//
// CookedUrl length and UrlLength are in bytes. Pick cooked url if it
// exists. Otherwise use the raw url, but only if it is clean enough
// for us (State >= ParseVersionState) and pAbsPath is really pointing
// into Url buffer. In raw url case, parser sometimes init the pAbsPath
// to a global string. (when there's no abs path in the raw url).
//
ASSERT(UL_IS_VALID_INTERNAL_REQUEST(pRequest));
if (pRequest->CookedUrl.pAbsPath)
{
ASSERT(pRequest->CookedUrl.pUrl);
UrlSize = pRequest->CookedUrl.Length
-
(ULONG) (DIFF(pRequest->CookedUrl.pAbsPath
-
pRequest->CookedUrl.pUrl
) * sizeof(WCHAR));
ASSERT(wcslen(pRequest->CookedUrl.pAbsPath)
== UrlSize/sizeof(WCHAR));
*pbLogRawUrl = FALSE;
}
else if (pRequest->RawUrl.pAbsPath)
{
if (pRequest->ParseState > ParseUrlState)
{
ASSERT(pRequest->RawUrl.pUrl);
if (ABS_PATH_SAFE(pRequest->RawUrl.pUrl,
pRequest->RawUrl.pAbsPath,
pRequest->RawUrl.Length))
{
UrlSize = pRequest->RawUrl.Length
-
(ULONG) DIFF(pRequest->RawUrl.pAbsPath
-
pRequest->RawUrl.pUrl
);
*pbLogRawUrl = TRUE;
}
}
}
UrlSize = MIN(UrlSize, MAX_LOG_EXTEND_FIELD_LEN);
return UrlSize;
}
#endif // _ERRLOGP_H_