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.
1343 lines
35 KiB
1343 lines
35 KiB
/*++
|
|
|
|
Copyright (c) 1994 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
debug.c
|
|
|
|
Abstract:
|
|
|
|
This file contains debugging macros for the BINL server.
|
|
|
|
Author:
|
|
|
|
Madan Appiah (madana) 10-Sep-1993
|
|
|
|
Environment:
|
|
|
|
User Mode - Win32
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
#include "binl.h"
|
|
#pragma hdrstop
|
|
|
|
const char g_szTrue[] = "True";
|
|
const char g_szFalse[] = "False";
|
|
|
|
DWORD DebugRefCount = 0;
|
|
|
|
VOID
|
|
DebugInitialize (
|
|
VOID
|
|
)
|
|
{
|
|
DWORD dwErr;
|
|
HKEY KeyHandle;
|
|
|
|
//
|
|
// only initialize debugging once.
|
|
//
|
|
InterlockedIncrement(&DebugRefCount);
|
|
if (DebugRefCount > 1) {
|
|
return;
|
|
}
|
|
|
|
InitializeCriticalSection(&BinlGlobalDebugFileCritSect);
|
|
BinlGlobalDebugFileHandle = NULL;
|
|
|
|
BinlGlobalDebugFileMaxSize = DEFAULT_MAXIMUM_DEBUGFILE_SIZE;
|
|
BinlGlobalDebugSharePath = NULL;
|
|
|
|
// Read DebugFlags value
|
|
dwErr = RegOpenKeyEx(
|
|
HKEY_LOCAL_MACHINE,
|
|
BINL_PARAMETERS_KEY,
|
|
0,
|
|
KEY_QUERY_VALUE,
|
|
&KeyHandle );
|
|
if ( dwErr == ERROR_SUCCESS ) {
|
|
BinlGlobalDebugFlag = ReadDWord( KeyHandle, BINL_DEBUG_KEY, 0 );
|
|
BinlPrintDbg(( DEBUG_OPTIONS, "Debug Flags = 0x%08x.\n", BinlGlobalDebugFlag ));
|
|
RegCloseKey( KeyHandle );
|
|
}
|
|
|
|
#if DBG
|
|
// break in the debugger if we are asked to do so.
|
|
if(BinlGlobalDebugFlag & DEBUG_STARTUP_BRK) {
|
|
BinlPrintDbg(( 0, "Stopping at DebugInitialize()'s DebugBreak( ).\n" ));
|
|
DebugBreak();
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Open debug log file.
|
|
//
|
|
|
|
if ( BinlGlobalDebugFlag & DEBUG_LOG_IN_FILE ) {
|
|
BinlOpenDebugFile( FALSE ); // not a reopen.
|
|
}
|
|
|
|
} // DebugInitialize
|
|
|
|
VOID
|
|
DebugUninitialize (
|
|
VOID
|
|
)
|
|
{
|
|
|
|
//
|
|
// Make sure debugging has been initialized before we go
|
|
// uninitializing it.
|
|
//
|
|
if( DebugRefCount == 0 ) {
|
|
// do nothing.
|
|
return;
|
|
}
|
|
|
|
|
|
//
|
|
// Don't uninitialize if there are other's depending on
|
|
// our debugging engine.
|
|
//
|
|
InterlockedDecrement(&DebugRefCount);
|
|
if (DebugRefCount > 0) {
|
|
return;
|
|
}
|
|
|
|
EnterCriticalSection( &BinlGlobalDebugFileCritSect );
|
|
if ( BinlGlobalDebugFileHandle != NULL ) {
|
|
CloseHandle( BinlGlobalDebugFileHandle );
|
|
BinlGlobalDebugFileHandle = NULL;
|
|
}
|
|
|
|
if( BinlGlobalDebugSharePath != NULL ) {
|
|
BinlFreeMemory( BinlGlobalDebugSharePath );
|
|
BinlGlobalDebugSharePath = NULL;
|
|
}
|
|
|
|
LeaveCriticalSection( &BinlGlobalDebugFileCritSect );
|
|
|
|
DeleteCriticalSection( &BinlGlobalDebugFileCritSect );
|
|
|
|
} // DebugUninitialize
|
|
|
|
VOID
|
|
BinlOpenDebugFile(
|
|
IN BOOL ReopenFlag
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Opens or re-opens the debug file
|
|
|
|
Arguments:
|
|
|
|
ReopenFlag - TRUE to indicate the debug file is to be closed, renamed,
|
|
and recreated.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
WCHAR LogFileName[500];
|
|
WCHAR BakFileName[500];
|
|
DWORD FileAttributes;
|
|
DWORD PathLength;
|
|
DWORD WinError;
|
|
|
|
//
|
|
// Close the handle to the debug file, if it is currently open
|
|
//
|
|
|
|
EnterCriticalSection( &BinlGlobalDebugFileCritSect );
|
|
if ( BinlGlobalDebugFileHandle != NULL ) {
|
|
CloseHandle( BinlGlobalDebugFileHandle );
|
|
BinlGlobalDebugFileHandle = NULL;
|
|
}
|
|
LeaveCriticalSection( &BinlGlobalDebugFileCritSect );
|
|
|
|
//
|
|
// make debug directory path first, if it is not made before.
|
|
//
|
|
if( BinlGlobalDebugSharePath == NULL ) {
|
|
|
|
if ( !GetWindowsDirectoryW(
|
|
LogFileName,
|
|
sizeof(LogFileName)/sizeof(WCHAR) ) ) {
|
|
BinlPrintDbg((DEBUG_ERRORS, "Window Directory Path can't be "
|
|
"retrieved, %lu.\n", GetLastError() ));
|
|
return;
|
|
}
|
|
|
|
//
|
|
// check debug path length.
|
|
//
|
|
|
|
PathLength = wcslen(LogFileName) * sizeof(WCHAR) +
|
|
sizeof(DEBUG_DIR) + sizeof(WCHAR);
|
|
|
|
if( (PathLength + sizeof(DEBUG_FILE) > sizeof(LogFileName) ) ||
|
|
(PathLength + sizeof(DEBUG_BAK_FILE) > sizeof(BakFileName) ) ) {
|
|
|
|
BinlPrintDbg((DEBUG_ERRORS, "Debug directory path (%ws) length is too long.\n",
|
|
LogFileName));
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
wcscat(LogFileName, DEBUG_DIR);
|
|
|
|
//
|
|
// copy debug directory name to global var.
|
|
//
|
|
|
|
BinlGlobalDebugSharePath =
|
|
BinlAllocateMemory( (wcslen(LogFileName) + 1) * sizeof(WCHAR) );
|
|
|
|
if( BinlGlobalDebugSharePath == NULL ) {
|
|
BinlPrintDbg((DEBUG_ERRORS, "Can't allocate memory for debug share "
|
|
"(%ws).\n", LogFileName));
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
wcscpy(BinlGlobalDebugSharePath, LogFileName);
|
|
}
|
|
else {
|
|
wcscpy(LogFileName, BinlGlobalDebugSharePath);
|
|
}
|
|
|
|
//
|
|
// Check this path exists.
|
|
//
|
|
|
|
FileAttributes = GetFileAttributesW( LogFileName );
|
|
|
|
if( FileAttributes == 0xFFFFFFFF ) {
|
|
|
|
WinError = GetLastError();
|
|
if( WinError == ERROR_FILE_NOT_FOUND ) {
|
|
|
|
//
|
|
// Create debug directory.
|
|
//
|
|
|
|
if( !CreateDirectoryW( LogFileName, NULL) ) {
|
|
BinlPrintDbg((DEBUG_ERRORS, "Can't create Debug directory (%ws), "
|
|
"%lu.\n", LogFileName, GetLastError() ));
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
}
|
|
else {
|
|
BinlPrintDbg((DEBUG_ERRORS, "Can't Get File attributes(%ws), "
|
|
"%lu.\n", LogFileName, WinError ));
|
|
goto ErrorReturn;
|
|
}
|
|
}
|
|
else {
|
|
|
|
//
|
|
// if this is not a directory.
|
|
//
|
|
|
|
if(!(FileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
|
|
|
BinlPrintDbg((DEBUG_ERRORS, "Debug directory path (%ws) exists "
|
|
"as file.\n", LogFileName));
|
|
goto ErrorReturn;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Create the name of the old and new log file names
|
|
//
|
|
|
|
(VOID) wcscpy( BakFileName, LogFileName );
|
|
(VOID) wcscat( LogFileName, DEBUG_FILE );
|
|
(VOID) wcscat( BakFileName, DEBUG_BAK_FILE );
|
|
|
|
|
|
//
|
|
// If this is a re-open,
|
|
// delete the backup file,
|
|
// rename the current file to the backup file.
|
|
//
|
|
|
|
if ( ReopenFlag ) {
|
|
|
|
if ( !DeleteFile( BakFileName ) ) {
|
|
WinError = GetLastError();
|
|
if ( WinError != ERROR_FILE_NOT_FOUND ) {
|
|
BinlPrintDbg((DEBUG_ERRORS,
|
|
"Cannot delete %ws (%ld)\n",
|
|
BakFileName,
|
|
WinError ));
|
|
BinlPrintDbg((DEBUG_ERRORS, " Try to re-open the file.\n"));
|
|
ReopenFlag = FALSE; // Don't truncate the file
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( ReopenFlag ) {
|
|
if ( !MoveFile( LogFileName, BakFileName ) ) {
|
|
BinlPrintDbg((DEBUG_ERRORS,
|
|
"Cannot rename %ws to %ws (%ld)\n",
|
|
LogFileName,
|
|
BakFileName,
|
|
GetLastError() ));
|
|
BinlPrintDbg((DEBUG_ERRORS,
|
|
" Try to re-open the file.\n"));
|
|
ReopenFlag = FALSE; // Don't truncate the file
|
|
}
|
|
}
|
|
|
|
//
|
|
// Open the file.
|
|
//
|
|
|
|
EnterCriticalSection( &BinlGlobalDebugFileCritSect );
|
|
BinlGlobalDebugFileHandle = CreateFileW( LogFileName,
|
|
GENERIC_WRITE,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
ReopenFlag ? CREATE_ALWAYS : OPEN_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL );
|
|
|
|
|
|
if ( BinlGlobalDebugFileHandle == INVALID_HANDLE_VALUE ) {
|
|
BinlPrintDbg((DEBUG_ERRORS, "cannot open %ws ,\n",
|
|
LogFileName ));
|
|
LeaveCriticalSection( &BinlGlobalDebugFileCritSect );
|
|
goto ErrorReturn;
|
|
} else {
|
|
// Position the log file at the end
|
|
(VOID) SetFilePointer( BinlGlobalDebugFileHandle,
|
|
0,
|
|
NULL,
|
|
FILE_END );
|
|
}
|
|
|
|
LeaveCriticalSection( &BinlGlobalDebugFileCritSect );
|
|
return;
|
|
|
|
ErrorReturn:
|
|
BinlPrintDbg((DEBUG_ERRORS,
|
|
" Debug output will be written to debug terminal.\n"));
|
|
return;
|
|
}
|
|
|
|
#define MAX_PRINTF_LEN 1024 // Arbitrary.
|
|
char OutputBuffer[MAX_PRINTF_LEN]; // protected by BinlGlobalDebugFileCritSect
|
|
|
|
|
|
VOID
|
|
BinlPrintRoutine(
|
|
IN DWORD DebugFlag,
|
|
IN LPSTR Format,
|
|
...
|
|
)
|
|
|
|
{
|
|
va_list arglist;
|
|
|
|
ULONG length;
|
|
DWORD BytesWritten;
|
|
static BeginningOfLine = TRUE;
|
|
static LineCount = 0;
|
|
static TruncateLogFileInProgress = FALSE;
|
|
LPSTR Text;
|
|
|
|
//
|
|
// If we aren't debugging this functionality, just return.
|
|
//
|
|
if ( DebugFlag != 0 && (BinlGlobalDebugFlag & DebugFlag) == 0 ) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// vsprintf isn't multithreaded + we don't want to intermingle output
|
|
// from different threads.
|
|
//
|
|
|
|
EnterCriticalSection( &BinlGlobalDebugFileCritSect );
|
|
length = 0;
|
|
|
|
//
|
|
// Handle the beginning of a new line.
|
|
//
|
|
//
|
|
|
|
if ( BeginningOfLine ) {
|
|
|
|
//
|
|
// If the log file is getting huge,
|
|
// truncate it.
|
|
//
|
|
|
|
if ( BinlGlobalDebugFileHandle != NULL &&
|
|
!TruncateLogFileInProgress ) {
|
|
|
|
//
|
|
// Only check every 50 lines,
|
|
//
|
|
|
|
LineCount++;
|
|
if ( LineCount >= 50 ) {
|
|
DWORD FileSize;
|
|
LineCount = 0;
|
|
|
|
//
|
|
// Is the log file too big?
|
|
//
|
|
|
|
FileSize = GetFileSize( BinlGlobalDebugFileHandle, NULL );
|
|
if ( FileSize == 0xFFFFFFFF ) {
|
|
(void) DbgPrint( "[BinlServer] Cannot GetFileSize %ld\n",
|
|
GetLastError() );
|
|
} else if ( FileSize > BinlGlobalDebugFileMaxSize ) {
|
|
TruncateLogFileInProgress = TRUE;
|
|
LeaveCriticalSection( &BinlGlobalDebugFileCritSect );
|
|
BinlOpenDebugFile( TRUE );
|
|
BinlPrint(( DEBUG_MISC,
|
|
"Logfile truncated because it was larger than %ld bytes\n",
|
|
BinlGlobalDebugFileMaxSize ));
|
|
EnterCriticalSection( &BinlGlobalDebugFileCritSect );
|
|
TruncateLogFileInProgress = FALSE;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
// Indicate this is a BINL server's message.
|
|
|
|
length += (ULONG) sprintf( &OutputBuffer[length], "[BinlServer] " );
|
|
|
|
//
|
|
// Put the thread id at the begining of the line.
|
|
//
|
|
if (BinlGlobalDebugFlag & DEBUG_THREAD) {
|
|
DWORD threadId = GetCurrentThreadId();
|
|
length += (ULONG) sprintf( &OutputBuffer[length],
|
|
"%08x ", threadId );
|
|
}
|
|
|
|
//
|
|
// Put the timestamp at the begining of the line.
|
|
//
|
|
if (BinlGlobalDebugFlag & DEBUG_TIMESTAMP) {
|
|
SYSTEMTIME SystemTime;
|
|
GetLocalTime( &SystemTime );
|
|
length += (ULONG) sprintf( &OutputBuffer[length],
|
|
"%02u/%02u %02u:%02u:%02u ",
|
|
SystemTime.wMonth,
|
|
SystemTime.wDay,
|
|
SystemTime.wHour,
|
|
SystemTime.wMinute,
|
|
SystemTime.wSecond );
|
|
}
|
|
|
|
//
|
|
// Indicate the type of message on the line
|
|
//
|
|
switch (DebugFlag) {
|
|
case DEBUG_OPTIONS:
|
|
Text = "OPTIONS";
|
|
break;
|
|
|
|
case DEBUG_ERRORS:
|
|
Text = "ERRORS";
|
|
break;
|
|
|
|
case DEBUG_STOC:
|
|
Text = "STOC";
|
|
break;
|
|
|
|
case DEBUG_INIT:
|
|
Text = "INIT";
|
|
break;
|
|
|
|
case DEBUG_SCAVENGER:
|
|
Text = "SCAVENGER";
|
|
break;
|
|
|
|
case DEBUG_REGISTRY:
|
|
Text = "REGISTRY";
|
|
break;
|
|
|
|
case DEBUG_NETINF:
|
|
Text = "NETINF";
|
|
break;
|
|
|
|
case DEBUG_MISC:
|
|
Text = "MISC";
|
|
break;
|
|
|
|
case DEBUG_MESSAGE:
|
|
Text = "MESSAGE";
|
|
break;
|
|
|
|
case DEBUG_LOG_IN_FILE:
|
|
Text = "LOG_IN_FILE";
|
|
break;
|
|
|
|
default:
|
|
Text = NULL;
|
|
break;
|
|
}
|
|
|
|
if ( Text != NULL ) {
|
|
length += (ULONG) sprintf( &OutputBuffer[length], "[%s] ", Text );
|
|
}
|
|
}
|
|
|
|
//
|
|
// Put a the information requested by the caller onto the line
|
|
//
|
|
|
|
va_start(arglist, Format);
|
|
|
|
length += (ULONG) vsprintf(&OutputBuffer[length], Format, arglist);
|
|
BeginningOfLine = (length > 0 && OutputBuffer[length-1] == '\n' );
|
|
|
|
va_end(arglist);
|
|
|
|
// Add in the fix for notepad users and fixing the assert
|
|
BinlAssert(length < MAX_PRINTF_LEN - 1);
|
|
if(BeginningOfLine){
|
|
OutputBuffer[length-1] = '\r';
|
|
OutputBuffer[length] = '\n';
|
|
length++;
|
|
OutputBuffer[length] = '\0';
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Output to the debug terminal,
|
|
// if the log file isn't open or we are asked to do so.
|
|
//
|
|
|
|
if ( (BinlGlobalDebugFileHandle == NULL) ||
|
|
!(BinlGlobalDebugFlag & DEBUG_LOG_IN_FILE) ) {
|
|
|
|
//
|
|
// Don't use DbgPrint(OutputBuffer) here because the buffer
|
|
// might contain strings that printf will try to interpret
|
|
// (e.g., NewMachineNamingPolicy = %1Fist%Last%#).
|
|
//
|
|
|
|
(void) DbgPrint( "%s", (PCH)OutputBuffer);
|
|
|
|
//
|
|
// Write the debug info to the log file.
|
|
//
|
|
|
|
} else {
|
|
if ( !WriteFile( BinlGlobalDebugFileHandle,
|
|
OutputBuffer,
|
|
strlen( OutputBuffer ),
|
|
&BytesWritten,
|
|
NULL ) ) {
|
|
(void) DbgPrint( "%s", (PCH) OutputBuffer);
|
|
}
|
|
|
|
}
|
|
|
|
LeaveCriticalSection( &BinlGlobalDebugFileCritSect );
|
|
|
|
}
|
|
|
|
#if DBG
|
|
|
|
VOID
|
|
BinlAssertFailed(
|
|
LPSTR FailedAssertion,
|
|
LPSTR FileName,
|
|
DWORD LineNumber,
|
|
LPSTR Message
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Assertion failed.
|
|
|
|
Arguments:
|
|
|
|
FailedAssertion :
|
|
|
|
FileName :
|
|
|
|
LineNumber :
|
|
|
|
Message :
|
|
|
|
Return Value:
|
|
|
|
none.
|
|
|
|
--*/
|
|
{
|
|
RtlAssert(
|
|
FailedAssertion,
|
|
FileName,
|
|
(ULONG) LineNumber,
|
|
(PCHAR) Message);
|
|
|
|
BinlPrintDbg(( 0, "Assert @ %s \n", FailedAssertion ));
|
|
BinlPrintDbg(( 0, "Assert Filename, %s \n", FileName ));
|
|
BinlPrintDbg(( 0, "Line Num. = %ld.\n", LineNumber ));
|
|
BinlPrintDbg(( 0, "Message is %s\n", Message ));
|
|
#if DBG
|
|
DebugBreak( );
|
|
#endif
|
|
}
|
|
|
|
VOID
|
|
BinlDumpMessage(
|
|
DWORD BinlDebugFlag,
|
|
LPDHCP_MESSAGE BinlMessage
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function dumps a DHCP packet in human readable form.
|
|
|
|
Arguments:
|
|
|
|
BinlDebugFlag - debug flag that indicates what we are debugging.
|
|
|
|
BinlMessage - A pointer to a DHCP message.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
LPOPTION option;
|
|
BYTE i;
|
|
|
|
BinlPrintDbg(( BinlDebugFlag, "Binl message: \n\n"));
|
|
|
|
BinlPrintDbg(( BinlDebugFlag, "Operation :"));
|
|
if ( BinlMessage->Operation == BOOT_REQUEST ) {
|
|
BinlPrintDbg(( BinlDebugFlag, "BootRequest\n"));
|
|
} else if ( BinlMessage->Operation == BOOT_REPLY ) {
|
|
BinlPrintDbg(( BinlDebugFlag, "BootReply\n"));
|
|
} else {
|
|
BinlPrintDbg(( BinlDebugFlag, "Unknown %x\n", BinlMessage->Operation));
|
|
return;
|
|
}
|
|
|
|
BinlPrintDbg(( BinlDebugFlag, "Hardware Address type : %d\n", BinlMessage->HardwareAddressType));
|
|
BinlPrintDbg(( BinlDebugFlag, "Hardware Address Length: %d\n", BinlMessage->HardwareAddressLength));
|
|
BinlPrintDbg(( BinlDebugFlag, "Hop Count : %d\n", BinlMessage->HopCount ));
|
|
BinlPrintDbg(( BinlDebugFlag, "Transaction ID : %lx\n", BinlMessage->TransactionID ));
|
|
BinlPrintDbg(( BinlDebugFlag, "Seconds Since Boot : %d\n", BinlMessage->SecondsSinceBoot ));
|
|
BinlPrintDbg(( BinlDebugFlag, "Client IP Address : " ));
|
|
BinlPrintDbg(( BinlDebugFlag, "%s\n",
|
|
inet_ntoa(*(struct in_addr *)&BinlMessage->ClientIpAddress ) ));
|
|
|
|
BinlPrintDbg(( BinlDebugFlag, "Your IP Address : " ));
|
|
BinlPrintDbg(( BinlDebugFlag, "%s\n",
|
|
inet_ntoa(*(struct in_addr *)&BinlMessage->YourIpAddress ) ));
|
|
|
|
BinlPrintDbg(( BinlDebugFlag, "Server IP Address : " ));
|
|
BinlPrintDbg(( BinlDebugFlag, "%s\n",
|
|
inet_ntoa(*(struct in_addr *)&BinlMessage->BootstrapServerAddress ) ));
|
|
|
|
BinlPrintDbg(( BinlDebugFlag, "Relay Agent IP Address : " ));
|
|
BinlPrintDbg(( BinlDebugFlag, "%s\n",
|
|
inet_ntoa(*(struct in_addr *)&BinlMessage->RelayAgentIpAddress ) ));
|
|
|
|
BinlPrintDbg(( BinlDebugFlag, "Hardware Address : "));
|
|
for ( i = 0; i < BinlMessage->HardwareAddressLength; i++ ) {
|
|
BinlPrintDbg(( BinlDebugFlag, "%2.2x", BinlMessage->HardwareAddress[i] ));
|
|
}
|
|
|
|
option = &BinlMessage->Option;
|
|
|
|
BinlPrintDbg(( BinlDebugFlag, "\n\n"));
|
|
BinlPrintDbg(( BinlDebugFlag, "Magic Cookie: "));
|
|
for ( i = 0; i < 4; i++ ) {
|
|
BinlPrintDbg(( BinlDebugFlag, "%d ", *((LPBYTE)option)++ ));
|
|
}
|
|
BinlPrintDbg(( BinlDebugFlag, "\n\n"));
|
|
|
|
BinlPrintDbg(( BinlDebugFlag, "Options:\n"));
|
|
while ( option->OptionType != 255 ) {
|
|
BinlPrintDbg(( BinlDebugFlag, "\tType = %d ", option->OptionType ));
|
|
for ( i = 0; i < option->OptionLength; i++ ) {
|
|
BinlPrintDbg(( BinlDebugFlag, "%2.2x", option->OptionValue[i] ));
|
|
}
|
|
BinlPrintDbg(( BinlDebugFlag, "\n"));
|
|
|
|
if ( option->OptionType == OPTION_PAD ||
|
|
option->OptionType == OPTION_END ) {
|
|
|
|
option = (LPOPTION)( (LPBYTE)(option) + 1);
|
|
|
|
} else {
|
|
|
|
option = (LPOPTION)( (LPBYTE)(option) + option->OptionLength + 2);
|
|
|
|
}
|
|
|
|
if ( (LPBYTE)option - (LPBYTE)BinlMessage > DHCP_MESSAGE_SIZE ) {
|
|
BinlPrintDbg(( BinlDebugFlag, "End of message, but no trailer found!\n"));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#endif // DBG
|
|
|
|
|
|
DWORD
|
|
BinlReportEventW(
|
|
DWORD EventID,
|
|
DWORD EventType,
|
|
DWORD NumStrings,
|
|
DWORD DataLength,
|
|
LPWSTR *Strings,
|
|
LPVOID Data
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function writes the specified (EventID) log at the end of the
|
|
eventlog.
|
|
|
|
Arguments:
|
|
|
|
EventID - The specific event identifier. This identifies the
|
|
message that goes with this event.
|
|
|
|
EventType - Specifies the type of event being logged. This
|
|
parameter can have one of the following
|
|
|
|
values:
|
|
|
|
Value Meaning
|
|
|
|
EVENTLOG_ERROR_TYPE Error event
|
|
EVENTLOG_WARNING_TYPE Warning event
|
|
EVENTLOG_INFORMATION_TYPE Information event
|
|
|
|
NumStrings - Specifies the number of strings that are in the array
|
|
at 'Strings'. A value of zero indicates no strings
|
|
are present.
|
|
|
|
DataLength - Specifies the number of bytes of event-specific raw
|
|
(binary) data to write to the log. If cbData is
|
|
zero, no event-specific data is present.
|
|
|
|
Strings - Points to a buffer containing an array of null-terminated
|
|
strings that are merged into the message before
|
|
displaying to the user. This parameter must be a valid
|
|
pointer (or NULL), even if cStrings is zero.
|
|
|
|
Data - Buffer containing the raw data. This parameter must be a
|
|
valid pointer (or NULL), even if cbData is zero.
|
|
|
|
|
|
Return Value:
|
|
|
|
Returns the WIN32 extended error obtained by GetLastError().
|
|
|
|
NOTE : This function works slow since it calls the open and close
|
|
eventlog source everytime.
|
|
|
|
--*/
|
|
{
|
|
HANDLE EventlogHandle;
|
|
DWORD ReturnCode;
|
|
|
|
|
|
//
|
|
// open eventlog section.
|
|
//
|
|
|
|
EventlogHandle = RegisterEventSourceW(NULL, BINL_SERVER);
|
|
|
|
if (EventlogHandle == NULL) {
|
|
|
|
ReturnCode = GetLastError();
|
|
goto Cleanup;
|
|
}
|
|
|
|
|
|
//
|
|
// Log the error code specified
|
|
//
|
|
|
|
if( !ReportEventW(
|
|
EventlogHandle,
|
|
(WORD)EventType,
|
|
0, // event category
|
|
EventID,
|
|
NULL,
|
|
(WORD)NumStrings,
|
|
DataLength,
|
|
Strings,
|
|
Data
|
|
) ) {
|
|
|
|
ReturnCode = GetLastError();
|
|
goto Cleanup;
|
|
}
|
|
|
|
ReturnCode = NO_ERROR;
|
|
|
|
Cleanup:
|
|
|
|
if( EventlogHandle != NULL ) {
|
|
|
|
DeregisterEventSource(EventlogHandle);
|
|
}
|
|
|
|
return ReturnCode;
|
|
}
|
|
|
|
|
|
DWORD
|
|
BinlReportEventA(
|
|
DWORD EventID,
|
|
DWORD EventType,
|
|
DWORD NumStrings,
|
|
DWORD DataLength,
|
|
LPSTR *Strings,
|
|
LPVOID Data
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function writes the specified (EventID) log at the end of the
|
|
eventlog.
|
|
|
|
Arguments:
|
|
|
|
Source - Points to a null-terminated string that specifies the name
|
|
of the module referenced. The node must exist in the
|
|
registration database, and the module name has the
|
|
following format:
|
|
|
|
\EventLog\System\Lanmanworkstation
|
|
|
|
EventID - The specific event identifier. This identifies the
|
|
message that goes with this event.
|
|
|
|
EventType - Specifies the type of event being logged. This
|
|
parameter can have one of the following
|
|
|
|
values:
|
|
|
|
Value Meaning
|
|
|
|
EVENTLOG_ERROR_TYPE Error event
|
|
EVENTLOG_WARNING_TYPE Warning event
|
|
EVENTLOG_INFORMATION_TYPE Information event
|
|
|
|
NumStrings - Specifies the number of strings that are in the array
|
|
at 'Strings'. A value of zero indicates no strings
|
|
are present.
|
|
|
|
DataLength - Specifies the number of bytes of event-specific raw
|
|
(binary) data to write to the log. If cbData is
|
|
zero, no event-specific data is present.
|
|
|
|
Strings - Points to a buffer containing an array of null-terminated
|
|
strings that are merged into the message before
|
|
displaying to the user. This parameter must be a valid
|
|
pointer (or NULL), even if cStrings is zero.
|
|
|
|
Data - Buffer containing the raw data. This parameter must be a
|
|
valid pointer (or NULL), even if cbData is zero.
|
|
|
|
|
|
Return Value:
|
|
|
|
Returns the WIN32 extended error obtained by GetLastError().
|
|
|
|
NOTE : This function works slow since it calls the open and close
|
|
eventlog source everytime.
|
|
|
|
--*/
|
|
{
|
|
HANDLE EventlogHandle;
|
|
DWORD ReturnCode;
|
|
|
|
|
|
//
|
|
// open eventlog section.
|
|
//
|
|
|
|
EventlogHandle = RegisterEventSourceW(
|
|
NULL,
|
|
BINL_SERVER
|
|
);
|
|
|
|
if (EventlogHandle == NULL) {
|
|
|
|
ReturnCode = GetLastError();
|
|
goto Cleanup;
|
|
}
|
|
|
|
|
|
//
|
|
// Log the error code specified
|
|
//
|
|
|
|
if( !ReportEventA(
|
|
EventlogHandle,
|
|
(WORD)EventType,
|
|
0, // event category
|
|
EventID,
|
|
NULL,
|
|
(WORD)NumStrings,
|
|
DataLength,
|
|
Strings,
|
|
Data
|
|
) ) {
|
|
|
|
ReturnCode = GetLastError();
|
|
goto Cleanup;
|
|
}
|
|
|
|
ReturnCode = NO_ERROR;
|
|
|
|
Cleanup:
|
|
|
|
if( EventlogHandle != NULL ) {
|
|
|
|
DeregisterEventSource(EventlogHandle);
|
|
}
|
|
|
|
return ReturnCode;
|
|
}
|
|
|
|
VOID
|
|
BinlServerEventLog(
|
|
DWORD EventID,
|
|
DWORD EventType,
|
|
DWORD ErrorCode
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Logs an event in EventLog.
|
|
|
|
Arguments:
|
|
|
|
EventID - The specific event identifier. This identifies the
|
|
message that goes with this event.
|
|
|
|
EventType - Specifies the type of event being logged. This
|
|
parameter can have one of the following
|
|
|
|
values:
|
|
|
|
Value Meaning
|
|
|
|
EVENTLOG_ERROR_TYPE Error event
|
|
EVENTLOG_WARNING_TYPE Warning event
|
|
EVENTLOG_INFORMATION_TYPE Information event
|
|
|
|
|
|
ErrorCode - Error Code to be Logged.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD Error;
|
|
LPSTR Strings[1];
|
|
CHAR ErrorCodeOemString[32 + 1];
|
|
|
|
wsprintfA( ErrorCodeOemString, "%lu", ErrorCode );
|
|
|
|
Strings[0] = ErrorCodeOemString;
|
|
|
|
Error = BinlReportEventA(
|
|
EventID,
|
|
EventType,
|
|
1,
|
|
sizeof(ErrorCode),
|
|
Strings,
|
|
&ErrorCode );
|
|
|
|
if( Error != ERROR_SUCCESS ) {
|
|
BinlPrintDbg(( DEBUG_ERRORS,
|
|
"BinlReportEventW failed, %ld.\n", Error ));
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
#if DBG==1
|
|
|
|
//
|
|
// Memory allocation and tracking
|
|
//
|
|
|
|
LPVOID g_TraceMemoryTable = NULL;
|
|
CRITICAL_SECTION g_TraceMemoryCS;
|
|
|
|
|
|
#define DEBUG_OUTPUT_BUFFER_SIZE 1024
|
|
|
|
typedef struct _MEMORYBLOCK {
|
|
HGLOBAL hglobal;
|
|
struct _MEMORYBLOCK *pNext;
|
|
LPCSTR pszModule;
|
|
LPCSTR pszComment;
|
|
LPCSTR pszFile;
|
|
DWORD dwBytes;
|
|
UINT uFlags;
|
|
UINT uLine;
|
|
} MEMORYBLOCK, *LPMEMORYBLOCK;
|
|
|
|
//
|
|
// Takes the filename and line number and put them into a string buffer.
|
|
//
|
|
// NOTE: the buffer is assumed to be of size DEBUG_OUTPUT_BUFFER_SIZE.
|
|
//
|
|
LPSTR
|
|
dbgmakefilelinestring(
|
|
LPSTR pszBuf,
|
|
LPCSTR pszFile,
|
|
UINT uLine )
|
|
{
|
|
LPVOID args[2];
|
|
|
|
args[0] = (LPVOID) pszFile;
|
|
args[1] = (LPVOID) UintToPtr( uLine );
|
|
|
|
FormatMessageA(
|
|
FORMAT_MESSAGE_FROM_STRING |
|
|
FORMAT_MESSAGE_ARGUMENT_ARRAY,
|
|
"%1(%2!u!):",
|
|
0, // error code
|
|
0, // default language
|
|
(LPSTR) pszBuf, // output buffer
|
|
DEBUG_OUTPUT_BUFFER_SIZE, // size of buffer
|
|
(va_list*) args ); // arguments
|
|
|
|
return pszBuf;
|
|
}
|
|
|
|
//
|
|
// Adds a MEMORYBLOCK to the memory tracking list.
|
|
//
|
|
HGLOBAL
|
|
DebugMemoryAdd(
|
|
HGLOBAL hglobal,
|
|
LPCSTR pszFile,
|
|
UINT uLine,
|
|
LPCSTR pszModule,
|
|
UINT uFlags,
|
|
DWORD dwBytes,
|
|
LPCSTR pszComment )
|
|
{
|
|
if ( hglobal )
|
|
{
|
|
LPMEMORYBLOCK pmb = (LPMEMORYBLOCK) GlobalAlloc(
|
|
GMEM_FIXED,
|
|
sizeof(MEMORYBLOCK) );
|
|
|
|
if ( !pmb )
|
|
{
|
|
GlobalFree( hglobal );
|
|
return NULL;
|
|
}
|
|
|
|
pmb->hglobal = hglobal;
|
|
pmb->dwBytes = dwBytes;
|
|
pmb->uFlags = uFlags;
|
|
pmb->pszFile = pszFile;
|
|
pmb->uLine = uLine;
|
|
pmb->pszModule = pszModule;
|
|
pmb->pszComment = pszComment;
|
|
|
|
EnterCriticalSection( &g_TraceMemoryCS );
|
|
|
|
pmb->pNext = g_TraceMemoryTable;
|
|
g_TraceMemoryTable = pmb;
|
|
|
|
BinlPrintDbg((DEBUG_MEMORY, "DebugAlloc: 0x%08x alloced (%s)\n", hglobal, pmb->pszComment ));
|
|
|
|
LeaveCriticalSection( &g_TraceMemoryCS );
|
|
}
|
|
|
|
return hglobal;
|
|
}
|
|
|
|
//
|
|
// Removes a MEMORYBLOCK to the memory tracking list.
|
|
//
|
|
void
|
|
DebugMemoryDelete(
|
|
HGLOBAL hglobal )
|
|
{
|
|
if ( hglobal )
|
|
{
|
|
LPMEMORYBLOCK pmbHead;
|
|
LPMEMORYBLOCK pmbLast = NULL;
|
|
|
|
EnterCriticalSection( &g_TraceMemoryCS );
|
|
pmbHead = g_TraceMemoryTable;
|
|
|
|
while ( pmbHead && pmbHead->hglobal != hglobal )
|
|
{
|
|
pmbLast = pmbHead;
|
|
pmbHead = pmbLast->pNext;
|
|
}
|
|
|
|
if ( pmbHead )
|
|
{
|
|
HGLOBAL *p;
|
|
if ( pmbLast )
|
|
{
|
|
pmbLast->pNext = pmbHead->pNext;
|
|
}
|
|
else
|
|
{
|
|
g_TraceMemoryTable = pmbHead->pNext;
|
|
}
|
|
|
|
BinlPrintDbg((DEBUG_MEMORY, "DebugFree: 0x%08x freed (%s)\n", hglobal,
|
|
pmbHead->pszComment ));
|
|
|
|
p = (HGLOBAL)((LPBYTE)hglobal + pmbHead->dwBytes - sizeof(HGLOBAL));
|
|
if ( *p != hglobal )
|
|
{
|
|
BinlPrintDbg(((DEBUG_ERRORS|DEBUG_MEMORY), "DebugFree: Heap check FAILED for %0x08x %u bytes (%s).\n",
|
|
hglobal, pmbHead->dwBytes, pmbHead->pszComment));
|
|
BinlPrintDbg(((DEBUG_ERRORS|DEBUG_MEMORY), "DebugFree: %s, Line: %u\n",
|
|
pmbHead->pszFile, pmbHead->uLine ));
|
|
BinlAssert( *p == hglobal );
|
|
}
|
|
|
|
memset( hglobal, 0xFE, pmbHead->dwBytes );
|
|
memset( pmbHead, 0xFD, sizeof(sizeof(MEMORYBLOCK)) );
|
|
|
|
LocalFree( pmbHead );
|
|
}
|
|
else
|
|
{
|
|
HGLOBAL *p;
|
|
|
|
BinlPrintDbg(((DEBUG_ERRORS|DEBUG_MEMORY), "DebugFree: 0x%08x not found in memory table\n", hglobal ));
|
|
memset( hglobal, 0xFE, (int)LocalSize( hglobal ));
|
|
}
|
|
|
|
LeaveCriticalSection( &g_TraceMemoryCS );
|
|
|
|
}
|
|
}
|
|
|
|
//
|
|
// Allocates memory and adds the MEMORYBLOCK to the memory tracking list.
|
|
//
|
|
HGLOBAL
|
|
DebugAlloc(
|
|
LPCSTR pszFile,
|
|
UINT uLine,
|
|
LPCSTR pszModule,
|
|
UINT uFlags,
|
|
DWORD dwBytes,
|
|
LPCSTR pszComment )
|
|
{
|
|
HGLOBAL hglobal;
|
|
DWORD dwBytesToAlloc = ROUND_UP_COUNT( dwBytes + sizeof(HGLOBAL), ALIGN_WORST);
|
|
|
|
HGLOBAL *p;
|
|
hglobal = GlobalAlloc( uFlags, dwBytesToAlloc );
|
|
if (hglobal == NULL) {
|
|
return NULL;
|
|
}
|
|
p = (HGLOBAL)((LPBYTE)hglobal + dwBytesToAlloc - sizeof(HGLOBAL));
|
|
*p = hglobal;
|
|
|
|
return DebugMemoryAdd( hglobal, pszFile, uLine, pszModule, uFlags, dwBytesToAlloc, pszComment );
|
|
}
|
|
|
|
//
|
|
// Remove the MEMORYBLOCK to the memory tracking list, memsets the
|
|
// memory to 0xFE and then frees the memory.
|
|
//
|
|
HGLOBAL
|
|
DebugFree(
|
|
HGLOBAL hglobal )
|
|
{
|
|
DebugMemoryDelete( hglobal );
|
|
|
|
return GlobalFree( hglobal );
|
|
}
|
|
|
|
//
|
|
// Checks the memory tracking list. If it is not empty, it will dump the
|
|
// list and break.
|
|
//
|
|
void
|
|
DebugMemoryCheck( )
|
|
{
|
|
BOOL fFoundLeak = FALSE;
|
|
LPMEMORYBLOCK pmb;
|
|
|
|
EnterCriticalSection( &g_TraceMemoryCS );
|
|
|
|
pmb = g_TraceMemoryTable;
|
|
while ( pmb )
|
|
{
|
|
LPMEMORYBLOCK pTemp;
|
|
LPVOID args[ 5 ];
|
|
CHAR szOutput[ DEBUG_OUTPUT_BUFFER_SIZE ];
|
|
CHAR szFileLine[ DEBUG_OUTPUT_BUFFER_SIZE ];
|
|
|
|
if ( fFoundLeak == FALSE )
|
|
{
|
|
BinlPrintRoutine( 0, "\n***************************** Memory leak detected *****************************\n\n");
|
|
//BinlPrintRoutine( 0, "1234567890123456789012345678901234567890 1234567890 X 0x12345678 12345 1...");
|
|
BinlPrintRoutine( 0, "Filename(Line Number): Module Addr/HGLOBAL Size String\n");
|
|
fFoundLeak = TRUE;
|
|
}
|
|
|
|
args[0] = (LPVOID) pmb->hglobal;
|
|
args[1] = (LPVOID) szFileLine;
|
|
args[2] = (LPVOID) pmb->pszComment;
|
|
args[3] = (LPVOID) ULongToPtr( pmb->dwBytes );
|
|
args[4] = (LPVOID) pmb->pszModule;
|
|
|
|
dbgmakefilelinestring( szFileLine, pmb->pszFile, pmb->uLine );
|
|
|
|
if ( !!(pmb->uFlags & GMEM_MOVEABLE) )
|
|
{
|
|
FormatMessageA(
|
|
FORMAT_MESSAGE_FROM_STRING |
|
|
FORMAT_MESSAGE_ARGUMENT_ARRAY,
|
|
"%2!-40s! %5!-10s! H 0x%1!08x! %4!-5u! \"%3\"\n",
|
|
0, // error code
|
|
0, // default language
|
|
szOutput, // output buffer
|
|
DEBUG_OUTPUT_BUFFER_SIZE, // size of buffer
|
|
(va_list*) args ); // arguments
|
|
}
|
|
else
|
|
{
|
|
FormatMessageA(
|
|
FORMAT_MESSAGE_FROM_STRING |
|
|
FORMAT_MESSAGE_ARGUMENT_ARRAY,
|
|
"%2!-40s! %5!-10s! A 0x%1!08x! %4!-5u! \"%3\"\n",
|
|
0, // error code
|
|
0, // default language
|
|
szOutput, // output buffer
|
|
DEBUG_OUTPUT_BUFFER_SIZE, // size of buffer
|
|
(va_list*) args ); // arguments
|
|
}
|
|
|
|
BinlPrintRoutine( 0, szOutput );
|
|
|
|
pTemp = pmb;
|
|
pmb = pmb->pNext;
|
|
memset( pTemp, 0xFD, sizeof(MEMORYBLOCK) );
|
|
LocalFree( pTemp );
|
|
}
|
|
|
|
if ( fFoundLeak == TRUE )
|
|
{
|
|
BinlPrintRoutine( 0, "\n***************************** Memory leak detected *****************************\n\n");
|
|
}
|
|
|
|
LeaveCriticalSection( &g_TraceMemoryCS );
|
|
|
|
//BinlAssert( !fFoundLeak );
|
|
}
|
|
|
|
VOID
|
|
DumpBuffer(
|
|
PVOID Buffer,
|
|
ULONG BufferSize
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dumps the buffer content on to the debugger output.
|
|
|
|
Arguments:
|
|
|
|
Buffer: buffer pointer.
|
|
|
|
BufferSize: size of the buffer.
|
|
|
|
Return Value:
|
|
|
|
none
|
|
|
|
--*/
|
|
{
|
|
#define NUM_CHARS 16
|
|
|
|
ULONG i, limit;
|
|
CHAR TextBuffer[NUM_CHARS + 1];
|
|
PUCHAR BufferPtr = Buffer;
|
|
|
|
|
|
DbgPrint("------------------------------------\n");
|
|
|
|
//
|
|
// Hex dump of the bytes
|
|
//
|
|
limit = ((BufferSize - 1) / NUM_CHARS + 1) * NUM_CHARS;
|
|
|
|
for (i = 0; i < limit; i++) {
|
|
|
|
if (i < BufferSize) {
|
|
|
|
DbgPrint("%02x ", (UCHAR)BufferPtr[i]);
|
|
|
|
if (BufferPtr[i] < 31 ) {
|
|
TextBuffer[i % NUM_CHARS] = '.';
|
|
} else if (BufferPtr[i] == '\0') {
|
|
TextBuffer[i % NUM_CHARS] = ' ';
|
|
} else {
|
|
TextBuffer[i % NUM_CHARS] = (CHAR) BufferPtr[i];
|
|
}
|
|
|
|
} else {
|
|
|
|
DbgPrint(" ");
|
|
TextBuffer[i % NUM_CHARS] = ' ';
|
|
|
|
}
|
|
|
|
if ((i + 1) % NUM_CHARS == 0) {
|
|
TextBuffer[NUM_CHARS] = 0;
|
|
DbgPrint(" %s\n", TextBuffer);
|
|
}
|
|
|
|
}
|
|
|
|
DbgPrint("------------------------------------\n");
|
|
}
|
|
|
|
|
|
#endif // DBG==1
|