/*++ 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 ); } #define TRACE_FILE_SIZE MAX_PATH+1 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; BOOL browserTraceLockHeld = FALSE; va_list ParmPtr; // Pointer to stack parms. if ( (BrInfo.BrowserDebug == 0) || (!BrowserTraceInitialized) ) { return; } // // If we aren't debugging this functionality, just return. // if ( DebugFlag != 0 && (BrInfo.BrowserDebug & DebugFlag) == 0 ) { return; } EnterCriticalSection(&BrowserTraceLock); browserTraceLockHeld = TRUE; length = 0; try { if (BrowserTraceLogHandle == NULL) { // // We've not opened the trace log file yet, so open it. // BrOpenTraceLogFile(); } if (BrowserTraceLogHandle == INVALID_HANDLE_VALUE) { if (browserTraceLockHeld) { LeaveCriticalSection(&BrowserTraceLock); browserTraceLockHeld = FALSE; } 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_CLIENT_OP: Text = "[CLNT OP]"; 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 { if (browserTraceLockHeld) { LeaveCriticalSection(&BrowserTraceLock); browserTraceLockHeld = FALSE; } } } 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) == 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() { if (!BrowserTraceInitialized) { return; } 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; }