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.

383 lines
9.6 KiB

  1. #include "precomp.h"
  2. #include "logitem.h"
  3. // utility APIs declarations
  4. // these two are identical to _strdate and _strtime respectively
  5. LPCTSTR StrGetDate(LPTSTR pszDate);
  6. LPCTSTR StrGetTime(LPTSTR pszTime);
  7. // string constants
  8. const TCHAR c_szCRLF[] = TEXT("\r\n");
  9. const TCHAR c_szSpace[] = TEXT(" ");
  10. const TCHAR c_szCommaSpace[] = TEXT(", ");
  11. const TCHAR c_szColonColon[] = TEXT("::");
  12. const TCHAR c_szColonSpace[] = TEXT(": ");
  13. const TCHAR c_szLine[] = TEXT("line %i");
  14. /////////////////////////////////////////////////////////////////////////////
  15. // CLogItem
  16. TCHAR CLogItem::m_szModule[MAX_PATH];
  17. BYTE CLogItem::m_bStep = 4;
  18. CLogItem::CLogItem(DWORD dwFlags /*= LIF_DEFAULT*/, LPBOOL pfLogLevels /*= NULL*/, UINT cLogLevels /*= 0*/)
  19. {
  20. if (m_szModule[0] == TEXT('\0')) {
  21. GetModuleFileName(GetModuleHandle(g_szModule), m_szModule, countof(m_szModule));
  22. CharLower(m_szModule);
  23. }
  24. m_nAbsOffset = 0;
  25. m_iRelOffset = 0;
  26. m_nLine = 0;
  27. m_rgfLogLevels = NULL;
  28. m_cLogLevels = cLogLevels;
  29. if (pfLogLevels != NULL) {
  30. ASSERT(cLogLevels > 0);
  31. m_rgfLogLevels = new BOOL[m_cLogLevels];
  32. memcpy(m_rgfLogLevels, pfLogLevels, m_cLogLevels * sizeof(BOOL));
  33. }
  34. else
  35. ASSERT(cLogLevels == 0);
  36. m_nLevel = 0;
  37. SetFlags(dwFlags);
  38. }
  39. CLogItem::~CLogItem()
  40. {
  41. delete[] m_rgfLogLevels;
  42. }
  43. /////////////////////////////////////////////////////////////////////////////
  44. // CLogItem operations
  45. LPCTSTR WINAPIV CLogItem::Log(int iLine, LPCTSTR pszFormat ...)
  46. {
  47. TCHAR szFormat[3 * MAX_PATH],
  48. szBuffer[MAX_PATH];
  49. LPCTSTR pszAux;
  50. UINT nLen, nAuxLen,
  51. cchCRLF;
  52. BOOL fPreviousToken;
  53. szFormat[0] = TEXT('\0');
  54. nLen = 0;
  55. if (hasFlag(LIF_NONE))
  56. return NULL;
  57. if (m_rgfLogLevels != NULL && m_nLevel < m_cLogLevels) {
  58. ASSERT((int)m_nLevel >= 0);
  59. if (!m_rgfLogLevels[m_nLevel])
  60. return NULL;
  61. }
  62. // prepend any CRLF at the beginning
  63. cchCRLF = StrSpn(pszFormat, c_szCRLF);
  64. if (cchCRLF > 0) {
  65. // special case
  66. if (cchCRLF >= (UINT)StrLen(pszFormat)) {
  67. StrCpy(m_szMessage, pszFormat);
  68. if (hasFlag(LIF_DUPLICATEINODS))
  69. OutputDebugString(m_szMessage);
  70. return m_szMessage;
  71. }
  72. StrCpyN(&szFormat[nLen], pszFormat, cchCRLF + 1);
  73. nLen += cchCRLF;
  74. pszFormat += cchCRLF;
  75. }
  76. fPreviousToken = FALSE;
  77. if (hasFlag(LIF_DATE)) {
  78. StrGetDate(szBuffer);
  79. StrCpy(&szFormat[nLen], szBuffer);
  80. nLen += StrLen(szBuffer);
  81. fPreviousToken = TRUE;
  82. }
  83. if (hasFlag(LIF_TIME)) {
  84. if (fPreviousToken) {
  85. StrCpy(&szFormat[nLen], c_szSpace);
  86. nLen += countof(c_szSpace)-1;
  87. }
  88. StrGetTime(szBuffer);
  89. StrCpy(&szFormat[nLen], szBuffer);
  90. nLen += StrLen(szBuffer);
  91. fPreviousToken = TRUE;
  92. }
  93. if (fPreviousToken) {
  94. StrCpy(&szFormat[nLen], c_szSpace);
  95. nLen += countof(c_szSpace)-1;
  96. }
  97. if ((m_nAbsOffset-1 + m_iRelOffset) > 0) {
  98. ASSERT((m_nAbsOffset-1 + m_iRelOffset) * m_bStep < countof(szBuffer));
  99. for (UINT i = 0; i < (m_nAbsOffset-1 + m_iRelOffset) * m_bStep; i++)
  100. szBuffer[i] = TEXT(' ');
  101. StrCpy(&szFormat[nLen], szBuffer);
  102. nLen += i-1;
  103. }
  104. fPreviousToken = FALSE;
  105. if (hasFlag(LIF_MODULE_ALL)) {
  106. pszAux = szBuffer;
  107. if (!hasFlag(LIF_MODULEPATH))
  108. makeRawFileName(m_szModule, szBuffer, countof(szBuffer));
  109. else
  110. pszAux = m_szModule; // should be lowercase already
  111. StrCpy(&szFormat[nLen], pszAux);
  112. nLen += StrLen(pszAux);
  113. fPreviousToken = TRUE;
  114. }
  115. if (hasFlag(LIF_FILE_ALL)) {
  116. if (fPreviousToken) {
  117. StrCpy(&szFormat[nLen], c_szCommaSpace);
  118. nLen += countof(c_szCommaSpace)-1;
  119. }
  120. if (!hasFlag(LIF_FILEPATH))
  121. makeRawFileName(m_szFile, szBuffer, countof(szBuffer));
  122. else {
  123. StrCpy(szBuffer, m_szFile);
  124. CharLower(szBuffer);
  125. }
  126. StrCpy(&szFormat[nLen], szBuffer);
  127. nLen += StrLen(szBuffer);
  128. fPreviousToken = TRUE;
  129. }
  130. if (hasFlag(LIF_CLASS) && hasFlag(LIF_CLASS2)) {
  131. if (fPreviousToken) {
  132. StrCpy(&szFormat[nLen], c_szCommaSpace);
  133. nLen += countof(c_szCommaSpace)-1;
  134. }
  135. StrCpy(&szFormat[nLen], m_szClass);
  136. nLen += StrLen(m_szClass);
  137. fPreviousToken = TRUE;
  138. }
  139. if (hasFlag(LIF_FUNCTION)) {
  140. if (fPreviousToken) {
  141. pszAux = (hasFlag(LIF_CLASS) && hasFlag(LIF_CLASS2)) ?
  142. c_szColonColon : c_szCommaSpace;
  143. StrCpy(&szFormat[nLen], pszAux);
  144. nLen += StrLen(pszAux);
  145. }
  146. StrCpy(&szFormat[nLen], m_szFunction);
  147. nLen += StrLen(m_szFunction);
  148. fPreviousToken = TRUE;
  149. }
  150. if (hasFlag(LIF_LINE) && iLine > 0) {
  151. if (fPreviousToken) {
  152. StrCpy(&szFormat[nLen], c_szCommaSpace);
  153. nLen += countof(c_szCommaSpace)-1;
  154. }
  155. nAuxLen = wnsprintf(szBuffer, countof(szBuffer), c_szLine, iLine);
  156. StrCpy(&szFormat[nLen], szBuffer);
  157. nLen += nAuxLen;
  158. fPreviousToken = TRUE;
  159. }
  160. if (pszFormat == NULL)
  161. StrCpy(m_szMessage, szFormat);
  162. // nLen stays the same
  163. else {
  164. if (fPreviousToken) {
  165. StrCpy(&szFormat[nLen], c_szColonSpace);
  166. nLen += countof(c_szColonSpace)-1;
  167. }
  168. StrCpy(&szFormat[nLen], pszFormat);
  169. va_list arglist;
  170. va_start(arglist, pszFormat);
  171. nAuxLen = wvnsprintf(m_szMessage, countof(m_szMessage), szFormat, arglist);
  172. va_end(arglist);
  173. nLen = nAuxLen;
  174. }
  175. if (hasFlag(LIF_APPENDCRLF))
  176. StrCpy(&m_szMessage[nLen], c_szCRLF);
  177. if (hasFlag(LIF_DUPLICATEINODS))
  178. OutputDebugString(m_szMessage);
  179. return m_szMessage;
  180. }
  181. CLogItem::operator LPCTSTR() const
  182. {
  183. return m_szMessage;
  184. }
  185. /////////////////////////////////////////////////////////////////////////////
  186. // CLogItem implementation helper routines
  187. LPCTSTR CLogItem::makeRawFileName(LPCTSTR pszPath, LPTSTR pszFile, UINT cchFile)
  188. {
  189. TCHAR szBuffer[MAX_PATH];
  190. LPCTSTR pszRawName;
  191. if (pszFile == NULL || cchFile == 0)
  192. return NULL;
  193. *pszFile = TEXT('\0');
  194. if (pszPath == NULL || StrLen(pszPath) == 0)
  195. return NULL;
  196. pszRawName = PathFindFileName(pszPath);
  197. ASSERT(StrLen(pszRawName) > 0);
  198. StrCpy(szBuffer, pszRawName);
  199. CharLower(szBuffer);
  200. if (cchFile <= (UINT)StrLen(szBuffer))
  201. return NULL;
  202. StrCpy(pszFile, szBuffer);
  203. return pszFile;
  204. }
  205. BOOL CLogItem::setFlag(DWORD dwMask, BOOL fSet /*= TRUE*/)
  206. {
  207. BOOL fIsFlag = ((m_dwFlags & dwMask) != 0L);
  208. if (fIsFlag == fSet)
  209. return FALSE;
  210. if (!fIsFlag && fSet)
  211. m_dwFlags |= dwMask;
  212. else {
  213. ASSERT(fIsFlag && !fSet);
  214. m_dwFlags &= ~dwMask;
  215. }
  216. return TRUE;
  217. }
  218. /////////////////////////////////////////////////////////////////////////////
  219. // Utility functions
  220. // Note. pszDate must point to the buffer of at least 11 characters.
  221. LPCTSTR StrGetDate(LPTSTR pszDate)
  222. {
  223. SYSTEMTIME dt;
  224. UINT nMonth, nDay, nYear;
  225. GetLocalTime(&dt);
  226. nMonth = dt.wMonth;
  227. nDay = dt.wDay;
  228. nYear = dt.wYear;
  229. *(pszDate + 2) = *(pszDate + 5) = TEXT('/');
  230. *(pszDate + 10) = TEXT('\0');
  231. *(pszDate + 0) = (TCHAR)(nMonth / 10 + TEXT('0'));
  232. *(pszDate + 1) = (TCHAR)(nMonth % 10 + TEXT('0'));
  233. *(pszDate + 3) = (TCHAR)(nDay / 10 + TEXT('0'));
  234. *(pszDate + 4) = (TCHAR)(nDay % 10 + TEXT('0'));
  235. *(pszDate + 6) = (TCHAR)(((nYear / 1000) % 10) + TEXT('0'));
  236. *(pszDate + 7) = (TCHAR)(((nYear / 100) % 10) + TEXT('0'));
  237. *(pszDate + 8) = (TCHAR)(((nYear / 10) % 10) + TEXT('0'));
  238. *(pszDate + 9) = (TCHAR)(((nYear / 1) % 10) + TEXT('0'));
  239. return pszDate;
  240. }
  241. // Note. pszTime must point to the buffer of at least 9 characters.
  242. LPCTSTR StrGetTime(LPTSTR pszTime)
  243. {
  244. SYSTEMTIME dt;
  245. int nHours, nMinutes, nSeconds;
  246. GetLocalTime(&dt);
  247. nHours = dt.wHour;
  248. nMinutes = dt.wMinute;
  249. nSeconds = dt.wSecond;
  250. *(pszTime + 2) = *(pszTime + 5) = TEXT(':');
  251. *(pszTime + 8) = TEXT('\0');
  252. *(pszTime + 0) = (TCHAR)(nHours / 10 + TEXT('0'));
  253. *(pszTime + 1) = (TCHAR)(nHours % 10 + TEXT('0'));
  254. *(pszTime + 3) = (TCHAR)(nMinutes / 10 + TEXT('0'));
  255. *(pszTime + 4) = (TCHAR)(nMinutes % 10 + TEXT('0'));
  256. *(pszTime + 6) = (TCHAR)(nSeconds / 10 + TEXT('0'));
  257. *(pszTime + 7) = (TCHAR)(nSeconds % 10 + TEXT('0'));
  258. return pszTime;
  259. }
  260. //----- Testing the stuff -----
  261. /*
  262. struct Test
  263. {
  264. Test();
  265. void foo();
  266. void bar();
  267. };
  268. static Test t;
  269. Test::Test()
  270. { MACRO_LI_Prolog(Test, Test)
  271. MACRO_LI_SetFlags(MACRO_LI_GetFlags() | LIF_DUPLICATEINODS);
  272. LI0("Calling foo and then bar");
  273. foo();
  274. LI0("foo returned");
  275. bar();
  276. LI0("bar returned");
  277. }
  278. void Test::foo()
  279. { MACRO_LI_Prolog(Test, foo);
  280. LI0("Calling bar");
  281. bar();
  282. LI0("bar returned");
  283. }
  284. void Test::bar()
  285. { MACRO_LI_Prolog(Test, bar);
  286. LI0("No arguments");
  287. LI1("One argument: %d", 2*2);
  288. LI2("Two arguments: %i, %s", 15, TEXT("nyah"));
  289. LI3("Three arguments: %d, %s, %x", 5, TEXT("the bar it is"), 0x80FF);
  290. }
  291. */