/******************************************************************************* * * (C) COPYRIGHT MICROSOFT CORP., 1997 * * TITLE: WiaLog.cpp * * VERSION: 1.0 * * AUTHOR: CoopP * * DATE: 20 Aug, 1999 * * DESCRIPTION: * Class implementation for WIA Logging. * *******************************************************************************/ #include "cplusinc.h" #include "sticomm.h" static const TCHAR szServiceName[] = TEXT("WIASERVC"); static const TCHAR szDefaultName[] = TEXT("WIASERVC.LOG"); static const TCHAR szDefaultKeyName[] = TEXT("WIASERVC"); static const TCHAR szDefaultDLLName[] = TEXT("noname.dll"); static const TCHAR szOpenedLog[] = TEXT("[%s] Opened log at %s %s"); static const TCHAR szClosedLog[] = TEXT("[%s] Closed log on %s %s"); static const WCHAR szFormatSignature[]= L"F9762DD2679F"; //#define DEBUG_WIALOG /**************************************************************************\ * CWiaLog::CreateInstance * * Create the CWiaLog object. * * Arguments: * * iid - iid of Logging interface * ppv - return interface pointer * * Return Value: * * status * * History: * * 8/20/1999 Original Version * \**************************************************************************/ HRESULT CWiaLog::CreateInstance(const IID& iid, void** ppv) { HRESULT hr; // // Create the WIA Logging component. // CWiaLog* pWiaLog = new CWiaLog(); if (!pWiaLog) { return E_OUTOFMEMORY; } // // Initialize the WIA logging component. // hr = pWiaLog->Initialize(); if (FAILED(hr)) { delete pWiaLog; return hr; } // // Get the requested interface from the logging component. // hr = pWiaLog->QueryInterface(iid, ppv); if (FAILED(hr)) { #ifdef DEBUG_WIALOG OutputDebugString(TEXT("CWiaLog::CreateInstance, Unkown interface\n")); #endif delete pWiaLog; return hr; } #ifdef DEBUG_WIALOG OutputDebugString(TEXT("CWiaLog::CreateInstance, Created WiaLog\n")); #endif return hr; } /**************************************************************************\ * QueryInterface * AddRef * Release * * CWiaLog IUnknown Interface * * Arguments: * * * * Return Value: * * * * History: * * 8/20/1999 Original Version * \**************************************************************************/ HRESULT __stdcall CWiaLog::QueryInterface(const IID& iid, void** ppv) { if (ppv == NULL) { return E_POINTER; } *ppv = NULL; if ((iid == IID_IUnknown) || (iid == IID_IWiaLog)) { *ppv = (IWiaLog*) this; } else if (iid == IID_IWiaLogEx) { *ppv = (IWiaLogEx*) this; } else { return E_NOINTERFACE; } AddRef(); return S_OK; } ULONG __stdcall CWiaLog::AddRef() { InterlockedIncrement((long*) &m_cRef); //DPRINTF(DM_TRACE,TEXT("CWiaLog::AddRef() m_cRef = %d"),m_cRef); return m_cRef; } ULONG __stdcall CWiaLog::Release() { ULONG ulRefCount = m_cRef - 1; if (InterlockedDecrement((long*) &m_cRef) == 0) { //DPRINTF(DM_TRACE,TEXT("CWiaLog::Release() m_cRef = %d"),m_cRef); delete this; return 0; } //DPRINTF(DM_TRACE,TEXT("CWiaLog::Release() m_cRef = %d"),m_cRef); return ulRefCount; } /******************************************************************************* * * CWiaLog * ~CWiaLog * * CWiaLog Constructor/Initialize/Destructor Methods. * * History: * * 8/20/1999 Original Version * \**************************************************************************/ CWiaLog::CWiaLog():m_cRef(0) { m_cRef = 0; // Initialize Reference count to zero m_pITypeInfo = NULL; // Initialize InfoType to NULL m_dwReportMode = 0; // Initialize Report Type to zero m_dwMaxSize = WIA_MAX_LOG_SIZE; // Initialize File Max size to default m_hLogFile = NULL; // Initialize File handle to NULL m_lDetail = 0; // Initialize TRACE detail level to zero (off) m_bLogToDebugger = FALSE; // Initialize Logging to DEBUGGER to FALSE m_bLoggerInitialized = FALSE; // Initialize Logger to UNINITIALIZED m_bTruncate = FALSE; // Initialize Truncation to FALSE m_bClear = TRUE; // Initialize Clear Log file to TRUE (Don't want to make huge log files for no reason :) ) ZeroMemory(m_szLogFilePath, // Initialize Path buffer sizeof(m_szLogFilePath)); ZeroMemory(m_szModeText, // Initialize formatted mode text buffer sizeof(m_szModeText)); } CWiaLog::~CWiaLog() { //DPRINTF(DM_TRACE,TEXT("CWiaLog::Destroy")); if (m_pITypeInfo != NULL) { m_pITypeInfo->Release(); } // // Flush buffers to disk // //DPRINTF(DM_TRACE,TEXT("Flushing final buffers")); FlushFileBuffers(m_hLogFile); // // close log file on destruction of log object // //DPRINTF(DM_TRACE,TEXT("Closing file handle")); CloseHandle(m_hLogFile); // // mark handle as invalid // m_hLogFile = INVALID_HANDLE_VALUE; } //////////////////////////////////////////////////////////////////////////////////// // IWiaLog private methods (exposed to the client) // //////////////////////////////////////////////////////////////////////////////////// /**************************************************************************\ * CWiaLog::InitializeLog * * Initializes the Logging component * * Arguments: * * none * * Return Value: * * status * * History: * * 8/20/1999 Original Version * \**************************************************************************/ HRESULT _stdcall CWiaLog::InitializeLog (LONG hInstance) { HRESULT hr = S_OK; // // set instance handle // m_hInstance = (HINSTANCE) ULongToPtr(hInstance); // // set DLL's name // if(!FormatDLLName(m_hInstance,m_szFmtDLLName,sizeof(m_szFmtDLLName)/sizeof(m_szFmtDLLName[0]))) { // // if this there is no DLL name created, use a default one // lstrcpy(m_szFmtDLLName, szDefaultDLLName); hr = E_INVALIDARG; } // // Create Registry Key name // lstrcpyn(m_szKeyName,m_szFmtDLLName, (sizeof(m_szKeyName)/sizeof(m_szKeyName[0])) - 1); m_szKeyName[(sizeof(m_szKeyName)/sizeof(m_szKeyName[0])) - 1] = TEXT('\0'); // // open log file // if (OpenLogFile()) { if (m_hLogFile != NULL) { // // query logging settings from registry, to // setup logging system // QueryLoggingSettings(); if(m_bTruncate) { ProcessTruncation(); } if(m_bClear) { // // clear log file // ::SetFilePointer(m_hLogFile, 0, NULL, FILE_BEGIN ); ::SetEndOfFile(m_hLogFile ); } WriteLogSessionHeader(); m_bLoggerInitialized = TRUE; } } else { // // Log file failed to Open... this is really bad // hr = E_FAIL; } return hr; } /**************************************************************************\ * CWiaLog::InitializeLogEx * * Initializes the Logging component. * * Arguments: * * hInstance - Handle of the caller's HINSTANCE * * Return Value: * * status * * History: * * 3/28/2000 Original Version * \**************************************************************************/ HRESULT _stdcall CWiaLog::InitializeLogEx(BYTE* hInstance) { HRESULT hr = S_OK; // // set instance handle // m_hInstance = (HINSTANCE) hInstance; // // set DLL's name // if(!FormatDLLName(m_hInstance,m_szFmtDLLName,sizeof(m_szFmtDLLName)/sizeof(m_szFmtDLLName[0]))) { // // if this there is no DLL name created, use a default one // lstrcpy(m_szFmtDLLName, szDefaultDLLName); hr = E_INVALIDARG; } // // Create Registry Key name // lstrcpyn(m_szKeyName,m_szFmtDLLName, (sizeof(m_szKeyName)/sizeof(m_szKeyName[0])) - 1); m_szKeyName[(sizeof(m_szKeyName)/sizeof(m_szKeyName[0])) - 1] = TEXT('\0'); // // open log file // if (OpenLogFile()) { if (m_hLogFile != NULL) { // // query logging settings from registry, to // setup logging system // QueryLoggingSettings(); if(m_bTruncate) { ProcessTruncation(); } if(m_bClear) { // // clear log file // ::SetFilePointer(m_hLogFile, 0, NULL, FILE_BEGIN ); ::SetEndOfFile(m_hLogFile ); } WriteLogSessionHeader(); m_bLoggerInitialized = TRUE; } } else { // // Log file failed to Open... this is really bad // hr = E_FAIL; } return hr; } /**************************************************************************\ * Log() * * Handles Logging, TRACE,ERROR,and WARNING optional call logging * * Arguments: * * lFlags - Flag to determine which type of logging to use * hInstance - Instance of the calling module * lResID - Resource ID of the wiaservc.dll resource file * lDetail - Logging detail level * bstrText - string for display * * * Return Value: * * status * * History: * * 8/20/1999 Original Version * \**************************************************************************/ HRESULT __stdcall CWiaLog::Log (LONG lFlags, LONG lResID, LONG lDetail, BSTR bstrText) { HRESULT hr = E_FAIL; // // check string for 'free signature' and remove signature if it exists. // BOOL bFreeString = NeedsToBeFreed(&bstrText); if (m_bLoggerInitialized) { // Find another way of updating the settings without querying the // Registry every time // QueryLoggingSettings(); /* // // NOTE: revisit this, How can you load a string resource ID from the service, // if you don't have the service's HINSTANCE????? // if(lResID != WIALOG_NO_RESOURCE_ID) { if (lResID < 35000) { // // Load the resource string from caller's resource // if (LoadString(g_hInstance,lResID,pBuffer, sizeof(pBuffer)) != 0) { bstrText = SysAllocString(pBuffer); bFreeString = TRUE; } } else { // // pull string from service's resource // } } */ switch (lFlags) { case WIALOG_ERROR: if(m_dwReportMode & WIALOG_ERROR) hr = Error(bstrText); break; case WIALOG_WARNING: if(m_dwReportMode & WIALOG_WARNING) hr = Warning(bstrText); break; case WIALOG_TRACE: default: if(m_dwReportMode & WIALOG_TRACE) hr = Trace(bstrText,lDetail); break; } } if(bFreeString) { SysFreeString(bstrText); } return hr; } /**************************************************************************\ * LogEx() * * Handles Logging, TRACE,ERROR,and WARNING optional call logging. This * is almost the same as the Log() call, but it contains a MethodId which * can be used for more specific filtering. * * Arguments: * * lMethodId - Integer indicating the uniqeu ID associated with the * calling method. * lFlags - Flag to determine which type of logging to use * hInstance - Instance of the calling module * lResID - Resource ID of the wiaservc.dll resource file * lDetail - Logging detail level * bstrText - string for display * * * Return Value: * * status * * History: * * 3/28/2000 Original Version * \**************************************************************************/ HRESULT _stdcall CWiaLog::LogEx(LONG lMethodId, LONG lFlags, LONG lResID, LONG lDetail, BSTR bstrText) { HRESULT hr = E_FAIL; // // check string for 'free signature' and remove signature if it exists. // BOOL bFreeString = NeedsToBeFreed(&bstrText); if (m_bLoggerInitialized) { switch (lFlags) { case WIALOG_ERROR: if(m_dwReportMode & WIALOG_ERROR) hr = Error(bstrText, lMethodId); break; case WIALOG_WARNING: if(m_dwReportMode & WIALOG_WARNING) hr = Warning(bstrText, lMethodId); break; case WIALOG_TRACE: default: if(m_dwReportMode & WIALOG_TRACE) hr = Trace(bstrText,lDetail, lMethodId); break; } } if(bFreeString) { SysFreeString(bstrText); } return hr; } /**************************************************************************\ * hResult() * * Handles hResult translating for Error call logging * * Arguments: * * hInstance - Instance of the calling module * hr - HRESULT to be translated * * Return Value: * * status * * History: * * 8/20/1999 Original Version * \**************************************************************************/ HRESULT __stdcall CWiaLog::hResult (HRESULT hr) { HRESULT hRes = E_FAIL; if (m_bLoggerInitialized) { // Find another way of updating the settings without querying the // Registry every time // QueryLoggingSettings(); // // we are initialized, so set the return to S_OK // hRes = S_OK; if (m_dwReportMode & WIALOG_ERROR) { #define NUM_CHARS_FOR_HRESULT 150 TCHAR szhResultText[NUM_CHARS_FOR_HRESULT]; ULONG ulLen = 0; memset(szhResultText, 0, sizeof(szhResultText)); ulLen = ::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, NULL, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)szhResultText, NUM_CHARS_FOR_HRESULT, NULL); if (ulLen) { szhResultText[NUM_CHARS_FOR_HRESULT - 1] = TEXT('\0'); memset(m_szTextBuffer,0,sizeof(m_szTextBuffer)); ConstructText(); _sntprintf(m_szTextBuffer, (sizeof(m_szTextBuffer)/sizeof(m_szTextBuffer[0])) - 1, TEXT("%s HRESULT: %s"), m_szModeText, szhResultText); WriteStringToLog(m_szTextBuffer, FLUSH_STATE); } } } return hRes; } HRESULT _stdcall CWiaLog::hResultEx(LONG lMethodId, HRESULT hr) { HRESULT hRes = E_FAIL; if (m_bLoggerInitialized) { // Find another way of updating the settings without querying the // Registry every time // QueryLoggingSettings(); // // we are initialized, so set the return to S_OK // hRes = S_OK; if (m_dwReportMode & WIALOG_ERROR) { #define NUM_CHARS_FOR_HRESULT 150 TCHAR szhResultText[NUM_CHARS_FOR_HRESULT]; ULONG ulLen = 0; memset(szhResultText, 0, sizeof(szhResultText)); ulLen = ::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, NULL, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)szhResultText, NUM_CHARS_FOR_HRESULT, NULL); if (ulLen) { szhResultText[NUM_CHARS_FOR_HRESULT - 1] = TEXT('\0'); memset(m_szTextBuffer,0,sizeof(m_szTextBuffer)); ConstructText(); _sntprintf(m_szTextBuffer, (sizeof(m_szTextBuffer)/sizeof(m_szTextBuffer[0])) - 1, TEXT("#0x%08X %s HRESULT: %s"), lMethodId, m_szModeText, szhResultText); WriteStringToLog(m_szTextBuffer, FLUSH_STATE); } } } return hRes; } HRESULT _stdcall CWiaLog::UpdateSettingsEx(LONG lCount, LONG *plMethodIds) { return E_NOTIMPL; } HRESULT _stdcall CWiaLog::ExportMappingTableEx(MappingTable **ppTable) { return E_NOTIMPL; } //////////////////////////////////////////////////////////////////////////////////// // IWiaLog private methods (not exposed to the client) // //////////////////////////////////////////////////////////////////////////////////// /**************************************************************************\ * CWiaLog::Initialize * * Initializes the CWiaLog class object (does nothing at the moment) * * Arguments: * * none * * Return Value: * * status * * History: * * 8/20/1999 Original Version * \**************************************************************************/ HRESULT CWiaLog::Initialize() { //DPRINTF(DM_TRACE,TEXT("CWiaLog::Initialize")); return S_OK; } /**************************************************************************\ * Trace() * * Handles Trace call logging * * Arguments: * * hInstance - Instance of the calling module * lResID - Resource ID of the wiaservc.dll resource file * bstrText - string for display * lDetail - Logging detail level * * Return Value: * * status * * History: * * 8/20/1999 Original Version * \**************************************************************************/ HRESULT CWiaLog::Trace (BSTR bstrText, LONG lDetail, LONG lMethodId) { memset(m_szTextBuffer,0,sizeof(m_szTextBuffer)); // // Turn off if lDetail level is zero // TODO: Only don't log if both detail level = 0, and the lMethodId doesn't // match one in our list // if(m_lDetail == 0) { return S_OK; } if (lDetail <= m_lDetail) { ConstructText(); _sntprintf(m_szTextBuffer, sizeof(m_szTextBuffer) / sizeof(m_szTextBuffer[0]) - 1, TEXT("#0x%08X %s TRACE: %ws"), lMethodId, m_szModeText, bstrText); WriteStringToLog(m_szTextBuffer, FLUSH_STATE); } return S_OK; } /**************************************************************************\ * Warning() * * Handles Warning call logging * * Arguments: * * hInstance - Instance of the calling module * lResID - Resource ID of the wiaservc.dll resource file * bstrText - string for display * * Return Value: * * status * * History: * * 8/20/1999 Original Version * \**************************************************************************/ HRESULT CWiaLog::Warning(BSTR bstrText, LONG lMethodId) { memset(m_szTextBuffer,0,sizeof(m_szTextBuffer)); ConstructText(); _sntprintf(m_szTextBuffer, sizeof(m_szTextBuffer) / sizeof(m_szTextBuffer[0]) - 1, TEXT("#0x%08X %s WARNING: %ws"), lMethodId, m_szModeText, bstrText); WriteStringToLog(m_szTextBuffer, FLUSH_STATE); return S_OK; } /**************************************************************************\ * Error() * * Handles Error call logging * * Arguments: * * hInstance - Instance of the calling module * lResID - Resource ID of the wiaservc.dll resource file * bstrText - string for display * * Return Value: * * status * * History: * * 8/20/1999 Original Version * \**************************************************************************/ HRESULT CWiaLog::Error (BSTR bstrText, LONG lMethodId) { memset(m_szTextBuffer,0,sizeof(m_szTextBuffer)); ConstructText(); _sntprintf(m_szTextBuffer, sizeof(m_szTextBuffer) / sizeof(m_szTextBuffer[0]) - 1, TEXT("#0x%08X %s ERROR: %ws"), lMethodId, m_szModeText, bstrText); WriteStringToLog(m_szTextBuffer, FLUSH_STATE); return S_OK; } //////////////////////////////////////////////////////////////////////////////////// // IWiaLog private helpers (not exposed to the client) // //////////////////////////////////////////////////////////////////////////////////// /**************************************************************************\ * OpenLogFile() * * Open the log file for logging * * * Arguments: * * none * * Return Value: * * status * * History: * * 8/23/1999 Original Version * \**************************************************************************/ BOOL CWiaLog::OpenLogFile() { // // Open log file // DWORD dwLength = 0; CSimpleString csName; m_hLogFile = INVALID_HANDLE_VALUE; // // Get Windows Directory // dwLength = ExpandEnvironmentStrings(TEXT("%USERPROFILE%"), m_szLogFilePath, sizeof(m_szLogFilePath) / sizeof(m_szLogFilePath[0])); if (( dwLength == 0) || !*m_szLogFilePath ) { //DPRINTF(DM_TRACE,TEXT("Could not GetWindowsDirectory()")); return FALSE; } m_szLogFilePath[(sizeof(m_szLogFilePath)/sizeof(m_szLogFilePath[0]) - 1)] = TEXT('\0'); // // Add log file name to Windows Directory // csName = m_szLogFilePath; csName += TEXT("\\"); csName += TEXT("wiaservc.log"); // // Create / open Log file // m_hLogFile = ::CreateFile(m_szLogFilePath, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, // security attributes OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); // template file handle if (m_hLogFile == INVALID_HANDLE_VALUE) return FALSE; return TRUE; } /**************************************************************************\ * WriteStringToLog() * * Writed formatted TEXT to a log file * * * Arguments: * * pszTextBuffer - Buffer of TEXT to write to file * fFlush - TRUE = FLUSH file on write, * FALSE = DON'T FLUSH file on write * * Return Value: * * status * * History: * * 8/23/1999 Original Version * \**************************************************************************/ VOID CWiaLog::WriteStringToLog(LPTSTR pszTextBuffer,BOOL fFlush) { DWORD dwcbWritten; BY_HANDLE_FILE_INFORMATION fi; if (!GetFileInformationByHandle(m_hLogFile,&fi)) { //DPRINTF(DM_TRACE,TEXT("WIALOG could not get file size for log file. ")); return; } // // check to see if our log file has exceeded it's MAX SIZE // If it has, reset the file pointer, and start writing from the // TOP. // //if ( fi.nFileSizeHigh !=0 || (fi.nFileSizeLow > m_dwMaxSize) ){ // ::SetFilePointer( m_hLogFile, 0, NULL, FILE_END); // ::SetEndOfFile( m_hLogFile ); // ::GetFileInformationByHandle(m_hLogFile,&fi); //} #ifdef USE_FILE_LOCK ::LockFile(m_hLogFile, fi.nFileSizeLow, fi.nFileSizeHigh, NUM_BYTES_TO_LOCK_LOW, NUM_BYTES_TO_LOCK_HIGH); #endif ::SetFilePointer( m_hLogFile, 0, NULL, FILE_END); #ifdef UNICODE // // convert to ANSI if we are UNICODE, and write string to log. // CHAR buffer[MAX_PATH]; WideCharToMultiByte(CP_ACP,WC_NO_BEST_FIT_CHARS,pszTextBuffer,-1,buffer,MAX_PATH,NULL,NULL); ::WriteFile(m_hLogFile, buffer, lstrlen(pszTextBuffer), &dwcbWritten, NULL); #else // // we are ANSI so write string to log. // ::WriteFile(m_hLogFile, pszTextBuffer, lstrlen(pszTextBuffer), &dwcbWritten, NULL); #endif ::WriteFile(m_hLogFile, "\r\n", 2, &dwcbWritten, NULL); #ifdef USE_FILE_LOCK ::UnlockFile(m_hLogFile, fi.nFileSizeLow, fi.nFileSizeHigh, NUM_BYTES_TO_LOCK_LOW, NUM_BYTES_TO_LOCK_HIGH); #endif // // Flush buffers to disk if requested (should always be TRUE on Millenium) // if (fFlush) { FlushFileBuffers(m_hLogFile); } // // Log to a Debugger // if (m_bLogToDebugger) { ::OutputDebugString(pszTextBuffer); ::OutputDebugString(TEXT("\n")); } // // Log to a Window / UI // if (m_bLogToUI) { // // Log to some window...or UI // } } /**************************************************************************\ * FormatStdTime() * * Formats the TIME to be added to a LOG file * * * Arguments: * * pstNow - System Time NOW * pchBuffer - buffer for the formatted time * cbBuffer - Buffer size * * * Return Value: * * status * * History: * * 8/23/1999 Original Version * \**************************************************************************/ BOOL CWiaLog::FormatStdTime(const SYSTEMTIME *pstNow,TCHAR *pchBuffer) { ::wsprintf(pchBuffer, TEXT("%02d:%02d:%02d.%03d"), pstNow->wHour, pstNow->wMinute, pstNow->wSecond, pstNow->wMilliseconds); return TRUE; } /**************************************************************************\ * FormatStdDate() * * Formats the DATE to be added to a LOG file * * * Arguments: * * pstNow - System TIME NOW * pchBuffer - buffer for the formatted time * cbBuffer - Buffer size * * * Return Value: * * status * * History: * * 8/23/1999 Original Version * \**************************************************************************/ inline BOOL FormatStdDate(const SYSTEMTIME *pstNow,TCHAR *pchBuffer,INT cchBuffer) { return (GetDateFormat(LOCALE_SYSTEM_DEFAULT, LOCALE_NOUSEROVERRIDE, pstNow, NULL, pchBuffer, cchBuffer)!= 0); } /**************************************************************************\ * WriteLogSessionHeader() * * Writes a header to the log file * * * Arguments: * * none * * Return Value: * * void * * History: * * 8/23/1999 Original Version * \**************************************************************************/ VOID CWiaLog::WriteLogSessionHeader() { SYSTEMTIME stCurrentTime; TCHAR szFmtDate[64] = {0}; TCHAR szFmtTime[64] = {0}; TCHAR szTextBuffer[128]; // // Format TIME and DATE // GetLocalTime(&stCurrentTime); FormatStdDate( &stCurrentTime, szFmtDate, sizeof(szFmtDate) / sizeof(szFmtDate[0]) - 1); FormatStdTime( &stCurrentTime, szFmtTime); // // write formatted data to TEXT buffer // _sntprintf(szTextBuffer, sizeof(szTextBuffer)/sizeof(szTextBuffer[0]), szOpenedLog, m_szFmtDLLName, szFmtDate, szFmtTime); szTextBuffer[sizeof(szTextBuffer)/sizeof(szTextBuffer[0]) - 1] = TEXT('\0'); // // write TEXT buffer to log // WriteStringToLog(szTextBuffer, FLUSH_STATE); } /**************************************************************************\ * QueryLoggingSettings() * * Read the registry and set the logging settings. * * * Arguments: * * none * * Return Value: * * status * * History: * * 8/23/1999 Original Version * \**************************************************************************/ BOOL CWiaLog::QueryLoggingSettings() { DWORD dwLevel = 0; DWORD dwMode = 0; // // read settings from the registry // RegEntry re(REGSTR_PATH_STICONTROL REGSTR_PATH_LOGGING,HKEY_LOCAL_MACHINE); if (re.IsValid()) { m_dwMaxSize = re.GetNumber(REGSTR_VAL_LOG_MAXSIZE,WIA_MAX_LOG_SIZE); } // // read report mode flags // re.MoveToSubKey(m_szKeyName); if (re.IsValid()) { dwLevel = re.GetNumber(REGSTR_VAL_LOG_LEVEL,WIALOG_ERROR) & WIALOG_MESSAGE_TYPE_MASK; dwMode = re.GetNumber(REGSTR_VAL_LOG_MODE,WIALOG_ADD_THREAD|WIALOG_ADD_MODULE) & WIALOG_MESSAGE_FLAGS_MASK; m_lDetail = re.GetNumber(REGSTR_VAL_LOG_DETAIL,WIALOG_NO_LEVEL); // // set truncate log on boot options // DWORD dwTruncate = -1; dwTruncate = re.GetNumber(REGSTR_VAL_LOG_TRUNCATE_ON_BOOT,FALSE); if (dwTruncate == 0) m_bTruncate = FALSE; else m_bTruncate = TRUE; // // set clear log on boot options // DWORD dwClear = -1; dwClear = re.GetNumber(REGSTR_VAL_LOG_CLEARLOG_ON_BOOT,TRUE); if (dwClear == 0) m_bClear = FALSE; else m_bClear = TRUE; // // set debugger logging options // DWORD dwDebugLogging = -1; dwDebugLogging = re.GetNumber(REGSTR_VAL_LOG_TO_DEBUGGER,FALSE); if (dwDebugLogging == 0) m_bLogToDebugger = FALSE; else m_bLogToDebugger = TRUE; } // // set report mode // m_dwReportMode = dwLevel | dwMode; // // set UI (window) logging options // if(m_dwReportMode & WIALOG_UI) m_bLogToUI = TRUE; else m_bLogToUI = FALSE; return TRUE; } /**************************************************************************\ * ConstructText() * * Constructs TEXT according to Logging settings * * * Arguments: * * pchBuffer - buffer for the formatted text * cbBuffer - Buffer size * * * Return Value: * * status * * History: * * 8/23/1999 Original Version * \**************************************************************************/ VOID CWiaLog::ConstructText() { // // set string constructor to zero // CSimpleString csHeader; CSimpleString csBuffer; CSimpleString csModeText; // // add thread id // if(m_dwReportMode & WIALOG_ADD_THREAD) { csBuffer.Format(TEXT("[%08X] "), ::GetCurrentThreadId()); csModeText += csBuffer; csHeader += TEXT("[ Thread ] "); } // // add module name // if(m_dwReportMode & WIALOG_ADD_MODULE) { csBuffer.Format(TEXT("%s "), m_szFmtDLLName); csModeText += csBuffer; csHeader += TEXT("[ Module ] "); } // // add time // if(m_dwReportMode & WIALOG_ADD_TIME) { SYSTEMTIME stCurrentTime; TCHAR szFmtTime[40]; GetLocalTime(&stCurrentTime); FormatStdTime(&stCurrentTime, szFmtTime); csBuffer.Format(TEXT(" %s "), szFmtTime); csModeText += csBuffer; csHeader += TEXT("[ HH:MM:SS.ms ] "); } // // Copy the log text into m_szModeText // lstrcpyn(m_szModeText, csModeText.String(), sizeof(m_szColumnHeader)/sizeof(m_szColumnHeader[0])); m_szModeText[sizeof(m_szModeText)/sizeof(m_szModeText[0]) - 1] = TEXT('\0'); // // add column header if needed // if(csHeader.Compare(m_szColumnHeader) != 0) { lstrcpyn(m_szColumnHeader,csHeader.String(), sizeof(m_szColumnHeader)/sizeof(m_szColumnHeader[0])); m_szColumnHeader[sizeof(m_szColumnHeader)/sizeof(m_szColumnHeader[0]) - 1] = TEXT('\0'); WriteStringToLog(TEXT(" "), FLUSH_STATE); WriteStringToLog(TEXT("============================================================================="), FLUSH_STATE); WriteStringToLog(m_szColumnHeader, FLUSH_STATE); WriteStringToLog(TEXT("============================================================================="), FLUSH_STATE); WriteStringToLog(TEXT(" "), FLUSH_STATE); } } /**************************************************************************\ * FormatDLLName() * * Formats the DLL name to be added to a LOG file * * * Arguments: * * hInstance - Instance of the calling DLL * pchBuffer - buffer for the formatted name * cbBuffer - Buffer size * * * Return Value: * * status * * History: * * 8/23/1999 Original Version * \**************************************************************************/ BOOL CWiaLog::FormatDLLName(HINSTANCE hInstance, TCHAR *pchBuffer, INT cchBuffer) { TCHAR lpfullpath[255]; TCHAR szModuleName[255]; // We know that the module name has to be <= ModuleFileName, so // by having szModuleName be the same size, we are guranteed to have enough // room (assuming lpFullPath is large enough for the ModuleFileName). DWORD dwLength = 0; dwLength = GetModuleFileName(hInstance,lpfullpath,sizeof(lpfullpath)/sizeof(lpfullpath[0])); lpfullpath[sizeof(lpfullpath)/sizeof(lpfullpath[0]) - 1] = TEXT('\0'); if(dwLength == 0) return FALSE; // // extract the file name from the full path // _tsplitpath(lpfullpath, NULL, NULL, szModuleName, NULL); lstrcpyn(pchBuffer, szModuleName, cchBuffer); pchBuffer[cchBuffer - 1] = TEXT('\0'); return TRUE; } /**************************************************************************\ * NeedsToBeFreed() * * Determines if the logger should free the allocated string. * If the signature is found, it is stripped off the beginning of the string * and the return of TRUE is set. * * Arguments: * * pBSTR - buffer for BSTRING * * * Return Value: * * status * * History: * * 8/23/1999 Original Version * \**************************************************************************/ BOOL CWiaLog::NeedsToBeFreed(BSTR* pBSTR) { // // NOTE: MAX_SIG_LEN *must* be larger than the string length of // the signature!!! // WCHAR wszSig[MAX_SIG_LEN]; // // check string to see if it is NULL, user may want to use a resource ID instead // if(*pBSTR == NULL) { return FALSE; } // // extract a possible signature from the beginning of the BSTR // wcsncpy(wszSig, *pBSTR, wcslen(szFormatSignature)); wszSig[wcslen(szFormatSignature)] = '\0'; // // do they match? // if(wcscmp(wszSig,szFormatSignature) == 0) { // // They match, so strip off the signature from the BSTR, and // return TRUE, (string can be freed by us). // wcscpy(*pBSTR,*pBSTR + wcslen(szFormatSignature)); return TRUE; } // // signature did not match, must not be allocated by US // return FALSE; } /**************************************************************************\ * ProcessTruncation() * * Determines if the logger should truncate the file. * The bottom part of the log file is copied, and copied back to the log file * after the file has been truncated. * * * Arguments: * * none * * * Return Value: * * void * * History: * * 9/09/1999 Original Version * \**************************************************************************/ VOID CWiaLog::ProcessTruncation() { // // determine file size // DWORD dwFileSize = 0; BY_HANDLE_FILE_INFORMATION fi; if (!GetFileInformationByHandle(m_hLogFile,&fi)) { //DPRINTF(DM_TRACE,TEXT("WIALOG could not get file size for log file. ")); return; } dwFileSize = fi.nFileSizeLow; if (dwFileSize > MAX_TRUNCATE_SIZE) { // // Allocate a temporary buffer // BYTE *pBuffer = NULL; DWORD dwBytesRead = 0; DWORD dwBytesWritten = 0; pBuffer = (BYTE*)LocalAlloc(LPTR,MAX_TRUNCATE_SIZE); if (pBuffer != NULL) { BOOL bRead = FALSE; // // read buffered data // ::SetFilePointer(m_hLogFile,dwFileSize - MAX_TRUNCATE_SIZE,NULL,FILE_BEGIN); bRead = ::ReadFile(m_hLogFile,(VOID*)pBuffer,MAX_TRUNCATE_SIZE,&dwBytesRead,NULL); // // nuke existing file // ::SetFilePointer(m_hLogFile, 0, NULL, FILE_BEGIN ); ::SetEndOfFile(m_hLogFile ); if (bRead) { // // Write buffer to file // ::WriteFile(m_hLogFile,pBuffer,MAX_TRUNCATE_SIZE,&dwBytesWritten,NULL); // // Write Truncation Header // WriteStringToLog(TEXT(" "), FLUSH_STATE); WriteStringToLog(TEXT("============================================================================="), FLUSH_STATE); TCHAR szHeader[MAX_PATH]; lstrcpy(szHeader,m_szFmtDLLName); lstrcat(szHeader,TEXT(" REQUESTED A FILE TRUNCATION")); WriteStringToLog(TEXT(" (Data above this marker is saved from a previous session)"), FLUSH_STATE); WriteStringToLog(TEXT("============================================================================="), FLUSH_STATE); WriteStringToLog(TEXT(" "), FLUSH_STATE); } LocalFree(pBuffer); } } else { // // File is too small, and does not need to be truncated // return; } }