534 lines
12 KiB
C
534 lines
12 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1991 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
brutil.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module contains miscellaneous utility routines used by the
|
|||
|
Browser service.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Rita Wong (ritaw) 01-Mar-1991
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "precomp.h"
|
|||
|
#pragma hdrstop
|
|||
|
|
|||
|
//-------------------------------------------------------------------//
|
|||
|
// //
|
|||
|
// Local function prototypes //
|
|||
|
// //
|
|||
|
//-------------------------------------------------------------------//
|
|||
|
|
|||
|
|
|||
|
//-------------------------------------------------------------------//
|
|||
|
// //
|
|||
|
// Global variables //
|
|||
|
// //
|
|||
|
//-------------------------------------------------------------------//
|
|||
|
|
|||
|
|
|||
|
|
|||
|
NET_API_STATUS
|
|||
|
BrMapStatus(
|
|||
|
IN NTSTATUS NtStatus
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function takes an NT status code and maps it to the appropriate
|
|||
|
error code expected from calling a LAN Man API.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
NtStatus - Supplies the NT status.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Returns the appropriate LAN Man error code for the NT status.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
//
|
|||
|
// A small optimization for the most common case.
|
|||
|
//
|
|||
|
if (NT_SUCCESS(NtStatus)) {
|
|||
|
return NERR_Success;
|
|||
|
}
|
|||
|
|
|||
|
switch (NtStatus) {
|
|||
|
case STATUS_OBJECT_NAME_COLLISION:
|
|||
|
return ERROR_ALREADY_ASSIGNED;
|
|||
|
|
|||
|
case STATUS_OBJECT_NAME_NOT_FOUND:
|
|||
|
return NERR_UseNotFound;
|
|||
|
|
|||
|
case STATUS_REDIRECTOR_STARTED:
|
|||
|
return NERR_ServiceInstalled;
|
|||
|
|
|||
|
default:
|
|||
|
return NetpNtStatusToApiStatus(NtStatus);
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
ULONG
|
|||
|
BrCurrentSystemTime()
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
SYSTEM_TIMEOFDAY_INFORMATION TODInformation;
|
|||
|
LARGE_INTEGER CurrentTime;
|
|||
|
ULONG TimeInSecondsSince1980 = 0; // happy prefix 112576
|
|||
|
ULONG BootTimeInSecondsSince1980 = 0; // ""
|
|||
|
|
|||
|
Status = NtQuerySystemInformation(SystemTimeOfDayInformation,
|
|||
|
&TODInformation,
|
|||
|
sizeof(TODInformation),
|
|||
|
NULL);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
return(0);
|
|||
|
}
|
|||
|
|
|||
|
Status = NtQuerySystemTime(&CurrentTime);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
return(0);
|
|||
|
}
|
|||
|
|
|||
|
RtlTimeToSecondsSince1980(&CurrentTime, &TimeInSecondsSince1980);
|
|||
|
RtlTimeToSecondsSince1980(&TODInformation.BootTime, &BootTimeInSecondsSince1980);
|
|||
|
|
|||
|
return(TimeInSecondsSince1980 - BootTimeInSecondsSince1980);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
BrLogEvent(
|
|||
|
IN ULONG MessageId,
|
|||
|
IN ULONG ErrorCode,
|
|||
|
IN ULONG NumberOfSubStrings,
|
|||
|
IN LPWSTR *SubStrings
|
|||
|
)
|
|||
|
{
|
|||
|
DWORD Severity;
|
|||
|
WORD Type;
|
|||
|
PVOID RawData;
|
|||
|
ULONG RawDataSize;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Log the error code specified
|
|||
|
//
|
|||
|
|
|||
|
Severity = (MessageId & 0xc0000000) >> 30;
|
|||
|
|
|||
|
if (Severity == STATUS_SEVERITY_WARNING) {
|
|||
|
Type = EVENTLOG_WARNING_TYPE;
|
|||
|
} else if (Severity == STATUS_SEVERITY_SUCCESS) {
|
|||
|
Type = EVENTLOG_SUCCESS;
|
|||
|
} else if (Severity == STATUS_SEVERITY_INFORMATIONAL) {
|
|||
|
Type = EVENTLOG_INFORMATION_TYPE;
|
|||
|
} else if (Severity == STATUS_SEVERITY_ERROR) {
|
|||
|
Type = EVENTLOG_ERROR_TYPE;
|
|||
|
} else {
|
|||
|
// prefix uninit var consistency.
|
|||
|
ASSERT(!"Unknown event log type!!");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (ErrorCode == NERR_Success) {
|
|||
|
RawData = NULL;
|
|||
|
RawDataSize = 0;
|
|||
|
} else {
|
|||
|
RawData = &ErrorCode;
|
|||
|
RawDataSize = sizeof(DWORD);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Use netlogon's routine to write eventlog messages.
|
|||
|
// (It ditches duplicate events.)
|
|||
|
//
|
|||
|
|
|||
|
NetpEventlogWrite (
|
|||
|
BrGlobalEventlogHandle,
|
|||
|
MessageId,
|
|||
|
Type,
|
|||
|
RawData,
|
|||
|
RawDataSize,
|
|||
|
SubStrings,
|
|||
|
NumberOfSubStrings );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
#if DBG
|
|||
|
|
|||
|
#define TRACE_FILE_SIZE 256
|
|||
|
|
|||
|
VOID
|
|||
|
BrResetTraceLogFile(
|
|||
|
VOID
|
|||
|
);
|
|||
|
|
|||
|
CRITICAL_SECTION
|
|||
|
BrowserTraceLock = {0};
|
|||
|
|
|||
|
HANDLE
|
|||
|
BrowserTraceLogHandle = NULL;
|
|||
|
|
|||
|
DWORD
|
|||
|
BrTraceLogFileSize = 0;
|
|||
|
|
|||
|
BOOLEAN BrowserTraceInitialized = {0};
|
|||
|
|
|||
|
VOID
|
|||
|
BrowserTrace(
|
|||
|
ULONG DebugFlag,
|
|||
|
PCHAR FormatString,
|
|||
|
...
|
|||
|
)
|
|||
|
#define LAST_NAMED_ARGUMENT FormatString
|
|||
|
|
|||
|
{
|
|||
|
CHAR OutputString[4096];
|
|||
|
ULONG length;
|
|||
|
ULONG BytesWritten;
|
|||
|
static BeginningOfLine = TRUE;
|
|||
|
|
|||
|
va_list ParmPtr; // Pointer to stack parms.
|
|||
|
|
|||
|
if (!BrowserTraceInitialized) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If we aren't debugging this functionality, just return.
|
|||
|
//
|
|||
|
if ( DebugFlag != 0 && (BrInfo.BrowserDebug & DebugFlag) == 0 ) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
EnterCriticalSection(&BrowserTraceLock);
|
|||
|
length = 0;
|
|||
|
|
|||
|
try {
|
|||
|
|
|||
|
if (BrowserTraceLogHandle == NULL) {
|
|||
|
//
|
|||
|
// We've not opened the trace log file yet, so open it.
|
|||
|
//
|
|||
|
|
|||
|
BrOpenTraceLogFile();
|
|||
|
}
|
|||
|
|
|||
|
if (BrowserTraceLogHandle == INVALID_HANDLE_VALUE) {
|
|||
|
LeaveCriticalSection(&BrowserTraceLock);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Attempt to catch bad trace.
|
|||
|
//
|
|||
|
|
|||
|
for (BytesWritten = 0; BytesWritten < strlen(FormatString) ; BytesWritten += 1) {
|
|||
|
if (FormatString[BytesWritten] > 0x7f) {
|
|||
|
DbgBreakPoint();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Handle the beginning of a new line.
|
|||
|
//
|
|||
|
//
|
|||
|
|
|||
|
if ( BeginningOfLine ) {
|
|||
|
SYSTEMTIME SystemTime;
|
|||
|
|
|||
|
//
|
|||
|
// Put the timestamp at the begining of the line.
|
|||
|
//
|
|||
|
GetLocalTime( &SystemTime );
|
|||
|
length += (ULONG) sprintf( &OutputString[length],
|
|||
|
"%02u/%02u %02u:%02u:%02u ",
|
|||
|
SystemTime.wMonth,
|
|||
|
SystemTime.wDay,
|
|||
|
SystemTime.wHour,
|
|||
|
SystemTime.wMinute,
|
|||
|
SystemTime.wSecond );
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Indicate the type of message on the line
|
|||
|
//
|
|||
|
{
|
|||
|
char *Text;
|
|||
|
|
|||
|
switch (DebugFlag) {
|
|||
|
case BR_CRITICAL:
|
|||
|
Text = "[CRITICAL]"; break;
|
|||
|
case BR_INIT:
|
|||
|
Text = "[INIT] "; break;
|
|||
|
case BR_SERVER_ENUM:
|
|||
|
Text = "[ENUM] "; break;
|
|||
|
case BR_UTIL:
|
|||
|
Text = "[UTIL] "; break;
|
|||
|
case BR_CONFIG:
|
|||
|
Text = "[CONFIG] "; break;
|
|||
|
case BR_MAIN:
|
|||
|
Text = "[MAIN] "; break;
|
|||
|
case BR_BACKUP:
|
|||
|
Text = "[BACKUP] "; break;
|
|||
|
case BR_MASTER:
|
|||
|
Text = "[MASTER] "; break;
|
|||
|
case BR_DOMAIN:
|
|||
|
Text = "[DOMAIN] "; break;
|
|||
|
case BR_NETWORK:
|
|||
|
Text = "[NETWORK]"; break;
|
|||
|
case BR_TIMER:
|
|||
|
Text = "[TIMER]"; break;
|
|||
|
case BR_QUEUE:
|
|||
|
Text = "[QUEUE]"; break;
|
|||
|
case BR_LOCKS:
|
|||
|
Text = "[LOCKS]"; break;
|
|||
|
default:
|
|||
|
Text = "[UNKNOWN]"; break;
|
|||
|
}
|
|||
|
length += (ULONG) sprintf( &OutputString[length], "%s ", Text );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Put a the information requested by the caller onto the line
|
|||
|
//
|
|||
|
|
|||
|
va_start(ParmPtr, FormatString);
|
|||
|
|
|||
|
length += (ULONG) vsprintf(&OutputString[length], FormatString, ParmPtr);
|
|||
|
BeginningOfLine = (length > 0 && OutputString[length-1] == '\n' );
|
|||
|
if ( BeginningOfLine ) {
|
|||
|
OutputString[length-1] = '\r';
|
|||
|
OutputString[length] = '\n';
|
|||
|
OutputString[length+1] = '\0';
|
|||
|
length++;
|
|||
|
}
|
|||
|
|
|||
|
va_end(ParmPtr);
|
|||
|
|
|||
|
ASSERT(length <= sizeof(OutputString));
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Actually write the bytes.
|
|||
|
//
|
|||
|
|
|||
|
if (!WriteFile(BrowserTraceLogHandle, OutputString, length, &BytesWritten, NULL)) {
|
|||
|
KdPrint(("Error writing to Browser log file: %ld\n", GetLastError()));
|
|||
|
KdPrint(("%s", OutputString));
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (BytesWritten != length) {
|
|||
|
KdPrint(("Error writing time to Browser log file: %ld\n", GetLastError()));
|
|||
|
KdPrint(("%s", OutputString));
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If the file has grown too large,
|
|||
|
// truncate it.
|
|||
|
//
|
|||
|
|
|||
|
BrTraceLogFileSize += BytesWritten;
|
|||
|
|
|||
|
if (BrTraceLogFileSize > BrInfo.BrowserDebugFileLimit) {
|
|||
|
BrResetTraceLogFile();
|
|||
|
}
|
|||
|
|
|||
|
} finally {
|
|||
|
LeaveCriticalSection(&BrowserTraceLock);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
BrInitializeTraceLog()
|
|||
|
{
|
|||
|
|
|||
|
try {
|
|||
|
InitializeCriticalSection(&BrowserTraceLock);
|
|||
|
BrowserTraceInitialized = TRUE;
|
|||
|
} except ( EXCEPTION_EXECUTE_HANDLER ) {
|
|||
|
#if DBG
|
|||
|
KdPrint( ("[Browser.dll]: Exception <%lu>. Failed to initialize trace log\n",
|
|||
|
_exception_code() ) );
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
BrGetTraceLogRoot(
|
|||
|
IN PWCHAR TraceFile
|
|||
|
)
|
|||
|
{
|
|||
|
PSHARE_INFO_502 ShareInfo;
|
|||
|
|
|||
|
//
|
|||
|
// If the DEBUG share exists, put the log file in that directory,
|
|||
|
// otherwise, use the system root.
|
|||
|
//
|
|||
|
// This way, if the browser is running on an NTAS server, we can always
|
|||
|
// get access to the log file.
|
|||
|
//
|
|||
|
|
|||
|
if (NetShareGetInfo(NULL, L"DEBUG", 502, (PCHAR *)&ShareInfo) != NERR_Success) {
|
|||
|
|
|||
|
if (GetSystemDirectory(TraceFile, TRACE_FILE_SIZE*sizeof(WCHAR)) == 0) {
|
|||
|
KdPrint(("Unable to get system directory: %ld\n", GetLastError()));
|
|||
|
}
|
|||
|
|
|||
|
if (TraceFile[wcslen(TraceFile)] != L'\\') {
|
|||
|
TraceFile[wcslen(TraceFile)+1] = L'\0';
|
|||
|
TraceFile[wcslen(TraceFile)] = L'\\';
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
//
|
|||
|
// Seed the trace file buffer with the local path of the netlogon
|
|||
|
// share if it exists.
|
|||
|
//
|
|||
|
|
|||
|
wcscpy(TraceFile, ShareInfo->shi502_path);
|
|||
|
|
|||
|
TraceFile[wcslen(ShareInfo->shi502_path)] = L'\\';
|
|||
|
TraceFile[wcslen(ShareInfo->shi502_path)+1] = L'\0';
|
|||
|
|
|||
|
NetApiBufferFree(ShareInfo);
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
BrResetTraceLogFile(
|
|||
|
VOID
|
|||
|
)
|
|||
|
{
|
|||
|
WCHAR OldTraceFile[TRACE_FILE_SIZE];
|
|||
|
WCHAR NewTraceFile[TRACE_FILE_SIZE];
|
|||
|
|
|||
|
if (BrowserTraceLogHandle != NULL) {
|
|||
|
CloseHandle(BrowserTraceLogHandle);
|
|||
|
}
|
|||
|
|
|||
|
BrowserTraceLogHandle = NULL;
|
|||
|
|
|||
|
BrGetTraceLogRoot(OldTraceFile);
|
|||
|
|
|||
|
wcscpy(NewTraceFile, OldTraceFile);
|
|||
|
|
|||
|
wcscat(OldTraceFile, L"Browser.Log");
|
|||
|
|
|||
|
wcscat(NewTraceFile, L"Browser.Bak");
|
|||
|
|
|||
|
//
|
|||
|
// Delete the old log
|
|||
|
//
|
|||
|
|
|||
|
DeleteFile(NewTraceFile);
|
|||
|
|
|||
|
//
|
|||
|
// Rename the current log to the new log.
|
|||
|
//
|
|||
|
|
|||
|
MoveFile(OldTraceFile, NewTraceFile);
|
|||
|
|
|||
|
BrOpenTraceLogFile();
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
BrOpenTraceLogFile(
|
|||
|
VOID
|
|||
|
)
|
|||
|
{
|
|||
|
WCHAR TraceFile[TRACE_FILE_SIZE];
|
|||
|
|
|||
|
BrGetTraceLogRoot(TraceFile);
|
|||
|
|
|||
|
wcscat(TraceFile, L"Browser.Log");
|
|||
|
|
|||
|
BrowserTraceLogHandle = CreateFile(TraceFile,
|
|||
|
GENERIC_WRITE,
|
|||
|
FILE_SHARE_READ,
|
|||
|
NULL,
|
|||
|
OPEN_ALWAYS,
|
|||
|
FILE_ATTRIBUTE_NORMAL,
|
|||
|
NULL);
|
|||
|
|
|||
|
|
|||
|
if (BrowserTraceLogHandle == INVALID_HANDLE_VALUE) {
|
|||
|
KdPrint(("Error creating trace file %ws: %ld\n", TraceFile, GetLastError()));
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
BrTraceLogFileSize = SetFilePointer(BrowserTraceLogHandle, 0, NULL, FILE_END);
|
|||
|
|
|||
|
if (BrTraceLogFileSize == 0xffffffff) {
|
|||
|
KdPrint(("Error setting trace file pointer: %ld\n", GetLastError()));
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
BrUninitializeTraceLog()
|
|||
|
{
|
|||
|
DeleteCriticalSection(&BrowserTraceLock);
|
|||
|
|
|||
|
if (BrowserTraceLogHandle != NULL) {
|
|||
|
CloseHandle(BrowserTraceLogHandle);
|
|||
|
}
|
|||
|
|
|||
|
BrowserTraceLogHandle = NULL;
|
|||
|
|
|||
|
BrowserTraceInitialized = FALSE;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
NET_API_STATUS
|
|||
|
BrTruncateLog()
|
|||
|
{
|
|||
|
if (BrowserTraceLogHandle == NULL) {
|
|||
|
BrOpenTraceLogFile();
|
|||
|
}
|
|||
|
|
|||
|
if (BrowserTraceLogHandle == INVALID_HANDLE_VALUE) {
|
|||
|
return ERROR_GEN_FAILURE;
|
|||
|
}
|
|||
|
|
|||
|
if (SetFilePointer(BrowserTraceLogHandle, 0, NULL, FILE_BEGIN) == 0xffffffff) {
|
|||
|
return GetLastError();
|
|||
|
}
|
|||
|
|
|||
|
if (!SetEndOfFile(BrowserTraceLogHandle)) {
|
|||
|
return GetLastError();
|
|||
|
}
|
|||
|
|
|||
|
return NO_ERROR;
|
|||
|
}
|
|||
|
|
|||
|
#endif
|