Source code of Windows XP (NT5)
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.

227 lines
4.7 KiB

  1. //
  2. // MODULE: APGTSLOG.CPP
  3. //
  4. // PURPOSE: User Activity Logging Utility
  5. // Fully implements class CHTMLLog
  6. //
  7. // PROJECT: Generic Troubleshooter DLL for Microsoft AnswerPoint
  8. //
  9. // COMPANY: Saltmine Creative, Inc. (206)-284-7511 [email protected]
  10. //
  11. // AUTHOR: Roman Mach
  12. //
  13. // ORIGINAL DATE: 8-2-96
  14. //
  15. // NOTES:
  16. // 1. Based on Print Troubleshooter DLL
  17. //
  18. // Version Date By Comments
  19. //--------------------------------------------------------------------
  20. // V0.1 - RM Original
  21. //
  22. #include "stdafx.h"
  23. #include "apgtslog.h"
  24. #include "event.h"
  25. #include "apgts.h"
  26. #include "baseexception.h"
  27. #include "CharConv.h"
  28. #include <vector>
  29. using namespace std;
  30. bool CHTMLLog::s_bUseHTMLLog = false;// Online Troubleshooter, will promptly set this
  31. // true in DLLMain. For Local Troubleshooter,
  32. // we leave this false.
  33. /*static*/ void CHTMLLog::SetUseLog(bool bUseLog)
  34. {
  35. s_bUseHTMLLog = bUseLog;
  36. }
  37. // INPUT dirpath: directory where we write log files
  38. // If can't allocate memory, sets some m_buffer[i] values to NULL, sets m_dwErr
  39. // EV_GTS_ERROR_LOG_FILE_MEM, but still returns normally. Consequently, there's really
  40. // no way for the caller to spot a problem, except by calling CHTMLLog::GetStatus after
  41. // _every_ call to this function.
  42. CHTMLLog::CHTMLLog(const TCHAR *dirpath) :
  43. m_bufindex(0),
  44. m_dwErr(0),
  45. m_strDirPath(dirpath)
  46. {
  47. ::InitializeCriticalSection( &m_csLogLock );
  48. for (UINT i=0;i<MAXLOGSBEFOREFLUSH;i++)
  49. {
  50. try
  51. {
  52. m_buffer[i] = new CString();
  53. }
  54. catch (bad_alloc&)
  55. {
  56. CBuildSrcFileLinenoStr SrcLoc( __FILE__, __LINE__ );
  57. CEvent::ReportWFEvent( SrcLoc.GetSrcFileLineStr(),
  58. SrcLoc.GetSrcFileLineStr(),
  59. _T(""), _T(""), EV_GTS_CANT_ALLOC );
  60. m_dwErr = EV_GTS_ERROR_LOG_FILE_MEM;
  61. // note that once this error is set we cannot log at all, not even using
  62. // the previous positions in m_buffer
  63. break;
  64. }
  65. }
  66. }
  67. //
  68. //
  69. CHTMLLog::~CHTMLLog()
  70. {
  71. FlushLogs();
  72. for (UINT i=0;i<MAXLOGSBEFOREFLUSH;i++)
  73. if (m_buffer[i] != NULL)
  74. delete m_buffer[i];
  75. ::DeleteCriticalSection( &m_csLogLock );
  76. }
  77. //
  78. //
  79. DWORD CHTMLLog::GetStatus()
  80. {
  81. return m_dwErr;
  82. }
  83. //
  84. // Write *data to log buffer, flush if max'd
  85. DWORD CHTMLLog::NewLog(LPCTSTR data)
  86. {
  87. DWORD dwErr = 0;
  88. if (m_dwErr)
  89. return m_dwErr;
  90. Lock();
  91. // copy data
  92. *m_buffer[m_bufindex] += data;
  93. m_bufindex++;
  94. if (m_bufindex == MAXLOGSBEFOREFLUSH) {
  95. // flush logs
  96. dwErr = FlushLogs();
  97. m_bufindex = 0;
  98. }
  99. Unlock();
  100. return dwErr;
  101. }
  102. // Flush to a log file. Name of log file is based on date/time of write.
  103. // RETURNS a (possibly preexisting) error status
  104. // NOTE: does not reset m_bufindex. Caller must do that.
  105. DWORD CHTMLLog::FlushLogs()
  106. {
  107. if (!s_bUseHTMLLog)
  108. return (0);
  109. if (m_dwErr)
  110. return m_dwErr;
  111. if (m_bufindex) {
  112. UINT i;
  113. FILE *fp;
  114. TCHAR filepath[300];
  115. SYSTEMTIME SysTime;
  116. // get time (used to be System Time, use local)
  117. GetLocalTime(&SysTime);
  118. _stprintf(filepath,_T("%s%s%02d%02d%02d.log"),
  119. (LPCTSTR)m_strDirPath,
  120. LOGFILEPREFACE,
  121. SysTime.wYear % 100,
  122. SysTime.wMonth,
  123. SysTime.wDay);
  124. fp = _tfopen(filepath,_T("a+"));
  125. if (fp) {
  126. for (i=0;i<m_bufindex;i++)
  127. {
  128. // Don't totally understand why the following needs a GetBuffer (after all,
  129. // it just reads the CString) but Bug#1204 arose when we tried
  130. // (const void*)(LPCTSTR)m_buffer[i] instead of m_buffer[i]->GetBuffer(0).
  131. // Leave it this way: can't be bad. JM/RAB 3/2/99
  132. fwrite( m_buffer[i]->GetBuffer(0), m_buffer[i]->GetLength(), 1, fp );
  133. m_buffer[i]->ReleaseBuffer();
  134. m_buffer[i]->Empty();
  135. }
  136. fclose(fp);
  137. }
  138. else
  139. return EV_GTS_ERROR_LOG_FILE_OPEN;
  140. }
  141. return (0);
  142. }
  143. //
  144. // Access function to enable the registry monitor to change the logging file directory.
  145. //
  146. void CHTMLLog::SetLogDirectory( const CString &strNewLogDir )
  147. {
  148. Lock();
  149. m_strDirPath= strNewLogDir;
  150. Unlock();
  151. return;
  152. }
  153. //
  154. // for testing only
  155. //
  156. // initially place 0 into dwThreadID
  157. //
  158. DWORD CHTMLLog::WriteTestLog(LPCTSTR szAPIName, DWORD dwThreadID)
  159. {
  160. TCHAR filepath[MAX_PATH];
  161. SYSTEMTIME SysTime;
  162. DWORD dwRetThreadID = GetCurrentThreadId();
  163. GetLocalTime(&SysTime);
  164. _stprintf(filepath,_T("%sAX%02d%02d%02d.log"),
  165. m_strDirPath,
  166. SysTime.wYear % 100,
  167. SysTime.wMonth,
  168. SysTime.wDay);
  169. Lock();
  170. FILE *fp = _tfopen(filepath, _T("a"));
  171. if (fp)
  172. {
  173. if (!dwThreadID)
  174. fprintf(fp, "(Start %s,%d)", szAPIName, dwRetThreadID);
  175. else
  176. {
  177. if (dwThreadID == dwRetThreadID)
  178. fprintf(fp, "(%d End)\n", dwThreadID);
  179. else
  180. fprintf(fp, "(%d End FAIL)\n", dwThreadID);
  181. }
  182. fclose(fp);
  183. }
  184. Unlock();
  185. return dwRetThreadID;
  186. }
  187. void CHTMLLog::Lock()
  188. {
  189. ::EnterCriticalSection( &m_csLogLock );
  190. }
  191. void CHTMLLog::Unlock()
  192. {
  193. ::LeaveCriticalSection( &m_csLogLock );
  194. }