Leaked source code of windows server 2003
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.

266 lines
7.6 KiB

  1. //---------------------------------------------------------------------------
  2. // MCSDebug.cpp
  3. //
  4. // The classes declared in MCSDebug.h are defined in
  5. // this file.
  6. //
  7. // (c) Copyright 1995-1998, Mission Critical Software, Inc., All Rights Reserved
  8. //
  9. // Proprietary and confidential to Mission Critical Software, Inc.
  10. //---------------------------------------------------------------------------
  11. #ifdef __cplusplus /* C++ */
  12. #ifndef WIN16_VERSION /* Not WIN16_VERSION */
  13. #ifdef USE_STDAFX
  14. # include "stdafx.h"
  15. # include "rpc.h"
  16. #else
  17. # include <windows.h>
  18. # include <stdlib.h>
  19. #endif
  20. #include <time.h>
  21. //#include <strstrea.h>
  22. #include <strstrea.h>
  23. #include "UString.hpp"
  24. #include "McsDebug.h"
  25. // -----------------
  26. // McsDebugException
  27. // -----------------
  28. McsDebugException::McsDebugException
  29. (const McsDebugException &t)
  30. : m_message (0), m_fileName (0), m_lineNum (t.m_lineNum) {
  31. if (t.m_message) {
  32. m_message = new char [UStrLen(t.m_message)+1];
  33. if (m_message) { UStrCpy (m_message, t.m_message); }
  34. }
  35. if (t.m_fileName) {
  36. m_fileName = new char [UStrLen(t.m_fileName)+1];
  37. if (m_fileName) { UStrCpy (m_fileName, t.m_fileName); }
  38. }
  39. }
  40. McsDebugException::McsDebugException
  41. (const char *messageIn,
  42. const char *fileNameIn,
  43. int lineNumIn)
  44. : m_lineNum (lineNumIn) {
  45. if (messageIn) {
  46. m_message = new char [UStrLen (messageIn)+1];
  47. if (m_message) { UStrCpy (m_message, messageIn); }
  48. }
  49. if (fileNameIn) {
  50. m_fileName = new char [UStrLen(fileNameIn)+1];
  51. if (m_fileName) { UStrCpy (m_fileName, fileNameIn); }
  52. }
  53. }
  54. McsDebugException& McsDebugException::operator=
  55. (const McsDebugException &t) {
  56. if (this != &t) {
  57. if (t.m_message) {
  58. m_message = new char [UStrLen(t.m_message)+1];
  59. if (m_message) { UStrCpy (m_message, t.m_message); }
  60. }
  61. if (t.m_fileName) {
  62. m_fileName = new char [UStrLen(t.m_fileName)+1];
  63. if (m_fileName) { UStrCpy (m_fileName, t.m_fileName); }
  64. }
  65. m_lineNum = t.m_lineNum;
  66. }
  67. return *this;
  68. }
  69. // ------------
  70. // McsVerifyLog
  71. // ------------
  72. static McsVerifyLog *pVerifyLog;
  73. static LONG verifyInitFlag;
  74. McsVerifyLog* McsVerifyLog::getLog (void) {
  75. // If pointer not initialized use the cheap
  76. // locking mechanism and set pointer to the
  77. // the static verifyLog object. This required
  78. // to gurantee the correct initialization of
  79. // the verify log class independent of any
  80. // static initialization order dependency.
  81. if (!pVerifyLog) {
  82. while (::InterlockedExchange
  83. (&verifyInitFlag, 1)) {
  84. ::Sleep (10);
  85. }
  86. if (!pVerifyLog) {
  87. static McsVerifyLog verifyLog;
  88. pVerifyLog = &verifyLog;
  89. }
  90. ::InterlockedExchange (&verifyInitFlag, 0);
  91. }
  92. return pVerifyLog;
  93. }
  94. void McsVerifyLog::changeLog (ostream *outStreamIn) {
  95. m_logSec.enter();
  96. m_log.changeLog (outStreamIn);
  97. delete m_outLog;
  98. m_outLog = 0;
  99. m_logSec.leave();
  100. }
  101. void McsVerifyLog::log (const char *messageIn,
  102. const char *fileNameIn,
  103. int lineNumIn) {
  104. m_logSec.enter();
  105. // If the log file has not been set, set it
  106. // to the module name log file.
  107. if (!m_log.isLogSet()) {
  108. m_outLog = new fstream (getLogFileName(),
  109. ios::app);
  110. m_log.changeLog (m_outLog);
  111. }
  112. // Format and write the message.
  113. formatMsg (messageIn, fileNameIn, lineNumIn);
  114. m_log.write (m_msgBuf);
  115. m_logSec.leave();
  116. }
  117. const char* McsVerifyLog::getLogFileName (void) {
  118. const char *MCS_LOG_ENV = "MCS_LOG";
  119. const char *DIR_SEP = "\\";
  120. const char *EXT = ".err";
  121. const char *DEFAULT_NAME = "MCSDEBUG";
  122. static char logFileName[MAX_PATH];
  123. // Get MCS_LOG_ENV, or temp directory path,
  124. // NULL means current directory.
  125. logFileName[0] = 0;
  126. char *mcs_log_path = getenv (MCS_LOG_ENV);
  127. bool isLogPath = false;
  128. if (mcs_log_path) {
  129. DWORD attrib = ::GetFileAttributesA (mcs_log_path);
  130. if ((attrib != 0xFFFFFFFF)
  131. && (attrib & FILE_ATTRIBUTE_DIRECTORY)) {
  132. UStrCpy (logFileName, mcs_log_path, MAX_PATH);
  133. isLogPath = true;
  134. }
  135. }
  136. if (!isLogPath) {
  137. ::GetTempPathA (MAX_PATH, logFileName);
  138. }
  139. // Get file name from the module name. If error
  140. // generate fixed filename.
  141. char fullFilePath [MAX_PATH];
  142. char fileName[MAX_PATH];
  143. if (::GetModuleFileNameA (NULL, fullFilePath,
  144. MAX_PATH)) {
  145. fullFilePath[MAX_PATH - 1] = '\0';
  146. // Get file name out of the path
  147. _splitpath (fullFilePath, NULL, NULL, fileName,
  148. NULL);
  149. // Generate full path name with extension.
  150. int len = UStrLen (logFileName);
  151. if (len) {
  152. UStrCpy (logFileName + len, DIR_SEP, MAX_PATH-len);
  153. UStrCpy (logFileName + UStrLen (logFileName),
  154. fileName,
  155. MAX_PATH-UStrLen(logFileName));
  156. } else {
  157. UStrCpy (logFileName, fileName, MAX_PATH);
  158. }
  159. } else {
  160. UStrCpy (logFileName, DEFAULT_NAME, MAX_PATH);
  161. }
  162. strncat (logFileName + UStrLen (logFileName), EXT, MAX_PATH-UStrLen(logFileName));
  163. logFileName[MAX_PATH-1] = '\0';
  164. return logFileName;
  165. }
  166. void McsVerifyLog::formatMsg (const char *messageIn,
  167. const char *fileNameIn,
  168. int lineNumIn) {
  169. const char *TIME = "TIME : ";
  170. const char *MSG = "MSG : ";
  171. const char *FILE = "FILE : ";
  172. const char *LINE = "LINE : ";
  173. const char *SPACER = ", ";
  174. // Create stream buf object.
  175. strstream msgBufStream (m_msgBuf, MSG_BUF_LEN, ios::out);
  176. // Write time stamp.
  177. time_t cur;
  178. time (&cur);
  179. struct tm *curTm = localtime (&cur);
  180. if (curTm) {
  181. char *tstr = asctime (curTm);
  182. if (tstr) {
  183. msgBufStream << TIME << tstr << SPACER;
  184. }
  185. }
  186. // Write message.
  187. if (messageIn) {
  188. msgBufStream << MSG << messageIn << SPACER;
  189. }
  190. // Write file name.
  191. if (fileNameIn) {
  192. msgBufStream << FILE << fileNameIn << SPACER;
  193. }
  194. // Write line number.
  195. msgBufStream << LINE << lineNumIn << endl;
  196. }
  197. // ----------
  198. // McsTestLog
  199. // ----------
  200. static McsTestLog *pTestLog;
  201. static LONG testInitFlag;
  202. McsTestLog* McsTestLog::getLog (void) {
  203. // If pointer not initialized use the cheap
  204. // locking mechanism and set pointer to the
  205. // the static verifyLog object. This required
  206. // to gurantee the correct initialization of
  207. // the verify log class independent of any
  208. // static initialization order dependency.
  209. if (!pTestLog) {
  210. while (::InterlockedExchange
  211. (&testInitFlag, 1)) {
  212. ::Sleep (10);
  213. }
  214. if (!pTestLog) {
  215. static McsTestLog testLog;
  216. pTestLog = &testLog;
  217. }
  218. ::InterlockedExchange (&testInitFlag, 0);
  219. }
  220. return pTestLog;
  221. }
  222. bool McsTestLog::isTestMode (void) {
  223. const char *TEST_ENV = "MCS_TEST";
  224. // const char *PRE_FIX = "MCS";
  225. // Check if tested.
  226. if (!m_isTested) {
  227. // If not tested lock, test again, and
  228. // initialize test mode flag.
  229. m_testSec.enter();
  230. if (!m_isTested) {
  231. m_isTested = true;
  232. m_isTestMode_ = getenv (TEST_ENV) != NULL;
  233. }
  234. m_testSec.leave();
  235. }
  236. return m_isTestMode_;
  237. }
  238. #endif /* Not WIN16_VERSION */
  239. #endif /* C++ */