|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: errlog.cpp
//
// Contents: generic error logging
//
// History: 19-Jun-00 reidk created
//
//--------------------------------------------------------------------------
#include <windows.h>
#include <string.h>
#include "errlog.h"
#include "unicode.h"
#define WSZ_ERROR_LOGFILE L"%SystemRoot%\\System32\\CatRoot2\\dberr.txt"
#define REG_CRYPTOGRAPHY_KEY L"Software\\Microsoft\\Cryptography"
#define REG_CATDB_LOGGING_VALUE L"CatDBLogging"
#define CATDB_LOG_ERRORS_TO_FILE 0x00000001
#define CATDB_LOG_ERRORS_TO_DEBUGGER 0x00000002
#define CATDB_LOG_WARNINGS 0x00000004
#define MAX_LOGFILE_SIZE 100000
#define TIME_DATE_SIZE 256
#define WRITE_BUFFER_SIZE 512
BOOL g_fErrLogInitialized = FALSE;
BOOL g_fLogErrorsToFile = TRUE; BOOL g_fLogErrorsToDebugger = FALSE; BOOL g_fLogWarnings = FALSE;
#define WSZ_TIME_STAMP_FILE L"TimeStamp"
#define TIME_ALLOWANCE ((ULONGLONG) 10000000 * (ULONGLONG) 60 * (ULONGLONG) 5) // 5 minutes
#define TIMESTAMP_LOGERR_LASTERR() ErrLog_LogError(NULL, \
ERRLOG_CLIENT_ID_TIMESTAMP, \ __LINE__, \ 0, \ FALSE, \ FALSE);
#define NAME_VALUE_SIZE 28
void ErrLog_Initialize() { HKEY hKey; DWORD dwDisposition; WCHAR wszValueName[NAME_VALUE_SIZE]; DWORD dwValueNameSize = NAME_VALUE_SIZE; DWORD dwType; DWORD dwValue; DWORD dwValueSize = sizeof(DWORD); DWORD dwIndex; LONG lRet;
g_fErrLogInitialized = TRUE;
//
// See if there is a CatDBLogging value
//
if (RegCreateKeyExU( HKEY_LOCAL_MACHINE, REG_CRYPTOGRAPHY_KEY, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ, NULL, &hKey, &dwDisposition) == ERROR_SUCCESS) { dwIndex = 0;
lRet = RegEnumValueU( hKey, dwIndex, wszValueName, &dwValueNameSize, NULL, &dwType, (BYTE *) &dwValue, &dwValueSize);
while ((lRet == ERROR_SUCCESS) || (lRet == ERROR_MORE_DATA)) { if ((lRet == ERROR_SUCCESS) && (dwType == REG_DWORD) && (_wcsicmp(wszValueName, REG_CATDB_LOGGING_VALUE) == 0)) { g_fLogErrorsToFile = (dwValue & CATDB_LOG_ERRORS_TO_FILE) != 0; g_fLogErrorsToDebugger = (dwValue & CATDB_LOG_ERRORS_TO_DEBUGGER) != 0; g_fLogWarnings = (dwValue & CATDB_LOG_WARNINGS) != 0; break; } else { dwValueNameSize = NAME_VALUE_SIZE; dwValueSize = sizeof(DWORD); dwIndex++; lRet = RegEnumValueU( hKey, dwIndex, wszValueName, &dwValueNameSize, NULL, &dwType, (BYTE *) &dwValue, &dwValueSize); } }
RegCloseKey(hKey); } }
void _WriteErrorOut( LPWSTR pwszLogFileName, LPSTR pwszError, BOOL fLogToFileOnly) { LPWSTR pwszFileNameToExpand = pwszLogFileName; LPWSTR pwszExpandedFileName = NULL; DWORD dwExpanded = 0; HANDLE hFile = INVALID_HANDLE_VALUE; DWORD dwFileSize = 0; DWORD dwNumBytesWritten = 0;
//
// Output the error string to the debugger
//
if (g_fLogErrorsToDebugger && !fLogToFileOnly) { OutputDebugStringA(pwszError); }
//
// Log string to file
//
if (g_fLogErrorsToFile) { if (pwszFileNameToExpand == NULL) { pwszFileNameToExpand = WSZ_ERROR_LOGFILE; }
//
// expand the filename if needed
//
dwExpanded = ExpandEnvironmentStringsU(pwszFileNameToExpand, NULL, 0);
if (dwExpanded == 0) { goto Return; }
pwszExpandedFileName = (LPWSTR) malloc(dwExpanded * sizeof(WCHAR)); if (pwszExpandedFileName == NULL) { goto Return; }
if (0 == ExpandEnvironmentStringsU( pwszFileNameToExpand, pwszExpandedFileName, dwExpanded)) { goto Return; }
//
// Get a handle to the file and make sure it isn't took big
//
hFile = CreateFileU( pwszExpandedFileName, GENERIC_READ | GENERIC_WRITE, 0, //dwShareMode
NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) { goto Return; }
dwFileSize = GetFileSize(hFile, NULL); if (dwFileSize >= MAX_LOGFILE_SIZE) { //
// Just nuke the whole thing
//
if (SetFilePointer( hFile, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { goto Return; }
if (!SetEndOfFile(hFile)) { goto Return; } }
//
// Write the new error
//
if (SetFilePointer(hFile, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER) { goto Return; }
WriteFile( hFile, (void *) pwszError, strlen(pwszError), &dwNumBytesWritten, NULL); }
Return:
if (pwszExpandedFileName != NULL) { free(pwszExpandedFileName); }
if (hFile != INVALID_HANDLE_VALUE) { CloseHandle(hFile); } }
#define SZ_ERROR_FORMAT "CatalogDB: %s: File #%u at line #%u encountered error 0x%.8lx\r\n"
#define SZ_LOGSTRING1_FORMAT "CatalogDB: %s: %S %S\r\n"
#define SZ_LOGSTRING2_FORMAT "CatalogDB: %s: %S\r\n"
void ErrLog_LogError( LPWSTR pwszLogFileName, DWORD dwClient, DWORD dwLine, DWORD dwErr, BOOL fWarning, BOOL fLogToFileOnly) { DWORD dwLastError = GetLastError(); int numChars = 0; char szTimeDate[TIME_DATE_SIZE]; char szWriteBuffer[WRITE_BUFFER_SIZE]; SYSTEMTIME st;
if (!g_fErrLogInitialized) { ErrLog_Initialize(); }
//
// Get out if this is a warning and we are not logging warnings
//
if (!g_fLogWarnings && fWarning) { return; }
//
// Create the error string to log
//
GetLocalTime(&st);
numChars = GetTimeFormatA( LOCALE_USER_DEFAULT, 0, &st, NULL, szTimeDate, TIME_DATE_SIZE);
szTimeDate[numChars-1] = ' ';
GetDateFormatA( LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, &szTimeDate[numChars], TIME_DATE_SIZE-numChars);
//
// Using 8 characters max for each of dwClient, dwLine, and dwErr
// dwClient - there are only 4 client files, so this is actually only 1 digit
// dwLine - there is no way the file line number will exceed 99,999,999
// dwErr - the format string puts this in hex, so 8 characters is max
//
if ((strlen(SZ_ERROR_FORMAT) + strlen(szTimeDate) + 8 + 8 + 8 + 1) > WRITE_BUFFER_SIZE) { SetLastError(dwLastError); return; }
wsprintf( szWriteBuffer, SZ_ERROR_FORMAT, szTimeDate, dwClient, dwLine, (dwErr == 0) ? dwLastError : dwErr);
//
// Log it
//
_WriteErrorOut(pwszLogFileName, szWriteBuffer, fLogToFileOnly);
//
// Make sure last error is the same as when we were called
//
SetLastError(dwLastError); }
void ErrLog_LogString( LPWSTR pwszLogFileName, LPWSTR pwszMessageString, LPWSTR pwszExtraString, BOOL fLogToFileOnly) { DWORD dwLastError = GetLastError(); int numChars = 0; char szTimeDate[TIME_DATE_SIZE]; SYSTEMTIME st; char szWriteBuffer[WRITE_BUFFER_SIZE];
if (!g_fErrLogInitialized) { ErrLog_Initialize(); }
//
// Create the error string to log
//
GetLocalTime(&st);
numChars = GetTimeFormatA( LOCALE_USER_DEFAULT, 0, &st, NULL, szTimeDate, TIME_DATE_SIZE);
szTimeDate[numChars-1] = ' ';
GetDateFormatA( LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, &szTimeDate[numChars], TIME_DATE_SIZE-numChars);
if (pwszExtraString != NULL) { if ((strlen(SZ_LOGSTRING1_FORMAT) + strlen(szTimeDate) + wcslen(pwszMessageString) + wcslen(pwszExtraString) + 1) > WRITE_BUFFER_SIZE) { SetLastError(dwLastError); return; }
wsprintf( szWriteBuffer, SZ_LOGSTRING1_FORMAT, szTimeDate, pwszMessageString, pwszExtraString); } else { if ((strlen(SZ_LOGSTRING2_FORMAT) + strlen(szTimeDate) + wcslen(pwszMessageString) + 1) > WRITE_BUFFER_SIZE) { SetLastError(dwLastError); return; }
wsprintf( szWriteBuffer, SZ_LOGSTRING2_FORMAT, szTimeDate, pwszMessageString); }
//
// Log it
//
_WriteErrorOut(pwszLogFileName, szWriteBuffer, fLogToFileOnly);
//
// Make sure last error is the same as when we were called
//
SetLastError(dwLastError); }
BOOL TimeStampFile_Touch( LPWSTR pwszDir) { BOOL fRet = TRUE; LPWSTR pwszFile = NULL; HANDLE hFile = INVALID_HANDLE_VALUE; DWORD dwNumBytesWritten = 0; SYSTEMTIME st; FILETIME ft; DWORD dwErr; DWORD dwRetry = 0;
//
// Create fully qaulified file name
//
if (NULL == (pwszFile = (LPWSTR) malloc(( wcslen(pwszDir) + wcslen(WSZ_TIME_STAMP_FILE) + 2) * sizeof(WCHAR)))) { SetLastError(E_OUTOFMEMORY); TIMESTAMP_LOGERR_LASTERR() goto ErrorReturn; } wcscpy(pwszFile, pwszDir); if (pwszFile[wcslen(pwszFile)-1] != L'\\') { wcscat(pwszFile, L"\\"); } wcscat(pwszFile, WSZ_TIME_STAMP_FILE);
//
// Get a handle to the file
//
while (dwRetry < 10) { hFile = CreateFileU( pwszFile, GENERIC_READ | GENERIC_WRITE, 0, //dwShareMode
NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) { TIMESTAMP_LOGERR_LASTERR() Sleep(1); } else { break; }
dwRetry++; }
if (hFile == INVALID_HANDLE_VALUE) { goto ErrorReturn; }
SetLastError(0);
//
// Get the current time
//
GetLocalTime(&st);
if (!SystemTimeToFileTime(&st, &ft)) { TIMESTAMP_LOGERR_LASTERR() goto ErrorReturn; }
//
// Write the time
//
if (SetFilePointer(hFile, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { TIMESTAMP_LOGERR_LASTERR() goto ErrorReturn; }
if (!SetEndOfFile(hFile)) { TIMESTAMP_LOGERR_LASTERR() goto ErrorReturn; }
if (!WriteFile( hFile, (void *) &ft, sizeof(ft), &dwNumBytesWritten, NULL)) { TIMESTAMP_LOGERR_LASTERR() goto ErrorReturn; }
CommonReturn:
if (hFile != INVALID_HANDLE_VALUE) { CloseHandle(hFile); }
if (pwszFile != NULL) { free(pwszFile); }
return (fRet);
ErrorReturn:
dwErr = GetLastError();
if (pwszFile != NULL) { DeleteFileW(pwszFile); }
SetLastError(dwErr);
fRet = FALSE;
goto CommonReturn; }
BOOL TimeStampFile_InSync( LPWSTR pwszDir1, LPWSTR pwszDir2, BOOL *pfInSync) { BOOL fRet = TRUE; LPWSTR pwszFile1 = NULL; HANDLE hFile1 = INVALID_HANDLE_VALUE; LPWSTR pwszFile2 = NULL; HANDLE hFile2 = INVALID_HANDLE_VALUE; DWORD dwNumBytesRead; FILETIME ft1; FILETIME ft2; ULARGE_INTEGER ul1; ULARGE_INTEGER ul2; DWORD dwRetryCount = 0;
//
// Initialize out param
//
*pfInSync = FALSE;
//
// Create fully qaulified file names
//
if (NULL == (pwszFile1 = (LPWSTR) malloc(( wcslen(pwszDir1) + wcslen(WSZ_TIME_STAMP_FILE) + 2) * sizeof(WCHAR)))) { SetLastError(E_OUTOFMEMORY); TIMESTAMP_LOGERR_LASTERR() goto ErrorReturn; } wcscpy(pwszFile1, pwszDir1); if (pwszFile1[wcslen(pwszFile1)-1] != L'\\') { wcscat(pwszFile1, L"\\"); } wcscat(pwszFile1, WSZ_TIME_STAMP_FILE);
if (NULL == (pwszFile2 = (LPWSTR) malloc(( wcslen(pwszDir2) + wcslen(WSZ_TIME_STAMP_FILE) + 2) * sizeof(WCHAR)))) { SetLastError(E_OUTOFMEMORY); TIMESTAMP_LOGERR_LASTERR() goto ErrorReturn; } wcscpy(pwszFile2, pwszDir2); if (pwszFile2[wcslen(pwszFile2)-1] != L'\\') { wcscat(pwszFile2, L"\\"); } wcscat(pwszFile2, WSZ_TIME_STAMP_FILE);
//
// Get a handle to the first file
//
while (dwRetryCount < 10) { hFile1 = CreateFileU( pwszFile1, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile1 == INVALID_HANDLE_VALUE) { if (GetLastError() == ERROR_FILE_NOT_FOUND) { SetLastError(0); goto CommonReturn; // not an error, a legitimate out of sync
} else { TIMESTAMP_LOGERR_LASTERR() Sleep(1); } } else { break; }
dwRetryCount++; }
//
// See if we were able to open the file
//
if (hFile1 == INVALID_HANDLE_VALUE) { TIMESTAMP_LOGERR_LASTERR() goto ErrorReturn; }
if (SetFilePointer(hFile1, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { TIMESTAMP_LOGERR_LASTERR() goto ErrorReturn; }
//
// Get a handle to the second file
//
dwRetryCount = 0; while (dwRetryCount < 10) { hFile2 = CreateFileU( pwszFile2, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile2 == INVALID_HANDLE_VALUE) { if (GetLastError() == ERROR_FILE_NOT_FOUND) { SetLastError(0); goto CommonReturn; // not an error, a legitimate out of sync
} else { TIMESTAMP_LOGERR_LASTERR() Sleep(1); } } else { break; }
dwRetryCount++; }
//
// See if we were able to open the file
//
if (hFile2 == INVALID_HANDLE_VALUE) { TIMESTAMP_LOGERR_LASTERR() goto ErrorReturn; }
if (SetFilePointer(hFile2, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { TIMESTAMP_LOGERR_LASTERR() goto ErrorReturn; }
//
// Get the times out of the files
//
if (!ReadFile( hFile1, &ft1, sizeof(ft1), &dwNumBytesRead, NULL)) { TIMESTAMP_LOGERR_LASTERR() goto ErrorReturn; }
if (dwNumBytesRead != sizeof(ft1)) { TIMESTAMP_LOGERR_LASTERR()
//
// This is really an error, but there is no reason to fail,
// just say they are out of sync since that will reinit the time
// stamp file during the catdb rebuild
//
goto CommonReturn; }
if (!ReadFile( hFile2, &ft2, sizeof(ft2), &dwNumBytesRead, NULL)) { TIMESTAMP_LOGERR_LASTERR() goto ErrorReturn; }
if (dwNumBytesRead != sizeof(ft2)) { TIMESTAMP_LOGERR_LASTERR() //
// This is really an error, but there is no reason to fail,
// just say they are out of sync since that will reinit the time
// stamp file during the catdb rebuild
//
goto CommonReturn; }
memcpy(&ul1, &ft1, sizeof(ft1)); memcpy(&ul2, &ft2, sizeof(ft2));
if ((ul1.QuadPart <= (ul2.QuadPart + TIME_ALLOWANCE)) && (ul2.QuadPart <= (ul1.QuadPart + TIME_ALLOWANCE))) { *pfInSync = TRUE; }
CommonReturn:
if (hFile1 != INVALID_HANDLE_VALUE) { CloseHandle(hFile1); }
if (pwszFile1 != NULL) { free(pwszFile1); }
if (hFile2 != INVALID_HANDLE_VALUE) { CloseHandle(hFile2); }
if (pwszFile2 != NULL) { free(pwszFile2); }
return (fRet);
ErrorReturn:
fRet = FALSE;
goto CommonReturn; }
|