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.

374 lines
12 KiB

  1. /****************************************************************************/
  2. // ntrcapi.c
  3. //
  4. // RDP Trace helper functions.
  5. //
  6. // Copyright (C) 1997-2000 Microsoft Corporation
  7. /****************************************************************************/
  8. #ifdef __cplusplus
  9. extern "C" {
  10. #endif /* __cplusplus */
  11. #include <precomp.h>
  12. #pragma hdrstop
  13. #ifdef DC_DEBUG
  14. #include <adcg.h>
  15. #include <nwdwapi.h>
  16. #include <atrcapi.h>
  17. /****************************************************************************/
  18. // Main wrapper function to pipe trace into TS stack trace
  19. /****************************************************************************/
  20. void RDPCALL TRC_TraceLine(
  21. PVOID pWD,
  22. UINT32 traceClass,
  23. UINT32 traceType,
  24. char *traceString,
  25. char separator,
  26. unsigned lineNumber,
  27. char *funcName,
  28. char *fileName)
  29. {
  30. // Very occasionally a timing issue occurs where tracing can happen
  31. // before the pTRCWd in each particular WD component is not initialized.
  32. if (pWD != NULL) {
  33. char FinalTraceString[TRC_BUFFER_SIZE];
  34. sprintf(FinalTraceString, "RDP%c%p%c"TRC_FUNC_FMT"%c"TRC_LINE_FMT"%c%s\n",
  35. separator, pWD, separator, TRC_FUNCNAME_LEN, TRC_FUNCNAME_LEN,
  36. funcName, separator, lineNumber, separator, traceString);
  37. IcaStackTrace((PSDCONTEXT)(((PTSHARE_WD)pWD)->pContext), traceClass,
  38. traceType, FinalTraceString);
  39. }
  40. }
  41. /****************************************************************************/
  42. /* TRC_UpdateConfig */
  43. /****************************************************************************/
  44. void RDPCALL TRC_UpdateConfig(PVOID pTSWd, PSD_IOCTL pSdIoctl)
  45. {
  46. PICA_TRACE pTraceInfo;
  47. char traceOptions[64];
  48. ANSI_STRING ansiString;
  49. UNICODE_STRING unicodeString;
  50. char *pStart;
  51. char *pEnd;
  52. unsigned numChars;
  53. unsigned index;
  54. UINT32 startLine;
  55. UINT32 endLine;
  56. pTraceInfo = (PICA_TRACE)(pSdIoctl->InputBuffer);
  57. // Copy trace info to TSWd structure.
  58. ((PTSHARE_WD)pTSWd)->trc.TraceClass = pTraceInfo->TraceClass;
  59. ((PTSHARE_WD)pTSWd)->trc.TraceEnable = pTraceInfo->TraceEnable;
  60. // Handle trace prefix information.
  61. RtlZeroMemory(traceOptions, sizeof(traceOptions));
  62. unicodeString.Length = sizeof(WCHAR) * wcslen(pTraceInfo->TraceOption);
  63. unicodeString.MaximumLength = unicodeString.Length;
  64. unicodeString.Buffer = (pTraceInfo->TraceOption);
  65. ansiString.Length = 0;
  66. ansiString.MaximumLength = sizeof(traceOptions);
  67. ansiString.Buffer = traceOptions;
  68. if (STATUS_SUCCESS != RtlUnicodeStringToAnsiString(&ansiString,
  69. &unicodeString, FALSE)) {
  70. KdPrint(("RDPWD: Couldn't set trace prefix info\n"));
  71. DC_QUIT;
  72. }
  73. RtlZeroMemory(((PTSHARE_WD)pTSWd)->trc.prefix,
  74. TRC_MAX_PREFIX * sizeof(TRC_PREFIX_DATA));
  75. index = 0;
  76. // Ignore any spaces at the start of the string.
  77. pEnd = traceOptions;
  78. while (' ' == *pEnd)
  79. pEnd++;
  80. // Main loop to parse prefix string.
  81. while ('\0' != *pEnd) {
  82. pStart = pEnd;
  83. // Run along the string looking for some sort of delimiter.
  84. while (('\0' != *pEnd) &&
  85. ('=' != *pEnd) &&
  86. (' ' != *pEnd) &&
  87. ('(' != *pEnd) &&
  88. (';' != *pEnd) &&
  89. (',' != *pEnd))
  90. {
  91. pEnd++;
  92. }
  93. // We now have a filename prefix, so save it. Don't need to worry
  94. // about a NULL terminator since we zeroed the array already.
  95. numChars = min((unsigned)(pEnd - pStart), TRC_PREFIX_NAME_LEN - 1);
  96. memcpy(((PTSHARE_WD)pTSWd)->trc.prefix[index].name, pStart, numChars);
  97. // Skip any spaces after this word, which may precede an '('.
  98. while (' ' == *pEnd)
  99. pEnd++;
  100. // Now split out the (optional) line number range.
  101. // Syntax is (aaa-bbb), where aaa is the start line number and bbb
  102. // is the end line number.
  103. // Spaces are allowed - e.g. ( aaa - bbb )
  104. if ('(' == *pEnd) {
  105. pEnd++; /* skip past the open bracket */
  106. startLine = 0;
  107. endLine = 0;
  108. // Skip past blanks.
  109. while (' ' == *pEnd)
  110. pEnd++;
  111. // Extract the start line number.
  112. while (('0' <= *pEnd) &&
  113. ('9' >= *pEnd)) {
  114. startLine = (startLine * 10) + (*pEnd - '0');
  115. pEnd++;
  116. }
  117. // Look for the next delimiter: '-' or ')'.
  118. while (('-' != *pEnd) &&
  119. (')' != *pEnd) &&
  120. ('\0' != *pEnd))
  121. pEnd++;
  122. // Stop now if we've reached the end of the line.
  123. if ('\0' == *pEnd) {
  124. KdPrint(("RDPWD: Unexpected EOL in trace options\n"));
  125. DC_QUIT;
  126. }
  127. // Extract the end line number (if any).
  128. if ('-' == *pEnd) {
  129. pEnd++; /* skip past '-' */
  130. while (' ' == *pEnd)
  131. pEnd++;
  132. while (('0' <= *pEnd) &&
  133. ('9' >= *pEnd)) {
  134. endLine = (endLine * 10) + (*pEnd - '0');
  135. pEnd++;
  136. }
  137. // Look for the closing delimiter: ')'.
  138. while (('\0' != *pEnd) &&
  139. (')' != *pEnd))
  140. pEnd++;
  141. }
  142. else {
  143. // Must be a bracket then - only one number was specified.
  144. endLine = startLine;
  145. }
  146. // Stop now if we've reached the end of the line.
  147. if ('\0' == *pEnd) {
  148. KdPrint(("RDPWD: Unexpected EOL in trace options\n"));
  149. DC_QUIT;
  150. }
  151. pEnd++; /* Jump past close bracket */
  152. // Store the start and end line numbers if they make sense.
  153. if (endLine >= startLine) {
  154. ((PTSHARE_WD)pTSWd)->trc.prefix[index].start = startLine;
  155. ((PTSHARE_WD)pTSWd)->trc.prefix[index].end = endLine;
  156. }
  157. }
  158. // Move on to the next prefix entry in the array.
  159. index++;
  160. if (index >= TRC_MAX_PREFIX) {
  161. // We've overrun the prefix list - so send some trace to the
  162. // debug console and then quit.
  163. KdPrint(("RDPWD: The trace option array is full!\n"));
  164. DC_QUIT;
  165. }
  166. // Skip past any delimiters.
  167. while ((',' == *pEnd) ||
  168. (';' == *pEnd) ||
  169. (' ' == *pEnd))
  170. pEnd++;
  171. }
  172. DC_EXIT_POINT:
  173. // Dump details to debugger.
  174. KdPrint(("RDPWD: New trace config for %p:\n", pTSWd));
  175. KdPrint(("RDPWD: Class: %lx\n",
  176. ((PTSHARE_WD)pTSWd)->trc.TraceClass));
  177. KdPrint(("RDPWD: Enable: %lx\n",
  178. ((PTSHARE_WD)pTSWd)->trc.TraceEnable));
  179. KdPrint(("RDPWD: Prefix info:\n"));
  180. if (((PTSHARE_WD)pTSWd)->trc.prefix[0].name[0] == '\0') {
  181. KdPrint(("RDPWD: None\n"));
  182. }
  183. for (index = 0;
  184. (index < TRC_MAX_PREFIX) &&
  185. (((PTSHARE_WD)pTSWd)->trc.prefix[index].name[0] != '\0');
  186. index++)
  187. {
  188. if ((((PTSHARE_WD)pTSWd)->trc.prefix[index].start == 0) &&
  189. (((PTSHARE_WD)pTSWd)->trc.prefix[index].end == 0)) {
  190. KdPrint(("RDPWD: %s(all lines)\n",
  191. ((PTSHARE_WD)pTSWd)->trc.prefix[index].name));
  192. }
  193. else {
  194. KdPrint(("RDPWD: %s(%lu-%lu)\n",
  195. ((PTSHARE_WD)pTSWd)->trc.prefix[index].name,
  196. ((PTSHARE_WD)pTSWd)->trc.prefix[index].start,
  197. ((PTSHARE_WD)pTSWd)->trc.prefix[index].end));
  198. }
  199. }
  200. ((PTSHARE_WD)pTSWd)->trc.init = TRUE;
  201. ((PTSHARE_WD)pTSWd)->trcShmNeedsUpdate = TRUE;
  202. }
  203. /****************************************************************************/
  204. /* Name: TRC_MaybeCopyConfig */
  205. /* */
  206. /* Purpose: Copies trace config to SHM if necessary */
  207. /****************************************************************************/
  208. void RDPCALL TRC_MaybeCopyConfig(PVOID pTSWd, PTRC_SHARED_DATA pTrc)
  209. {
  210. if (((PTSHARE_WD)pTSWd)->trcShmNeedsUpdate) {
  211. memcpy(pTrc, &(((PTSHARE_WD)pTSWd)->trc), sizeof(TRC_SHARED_DATA));
  212. ((PTSHARE_WD)pTSWd)->trcShmNeedsUpdate = FALSE;
  213. }
  214. } /* TRC_MaybeCopyConfig */
  215. /****************************************************************************/
  216. /* TRCPrefixMatch */
  217. /* */
  218. /* Internal function to compare a component name to a prefix. */
  219. /* - assumes both are the same case */
  220. /* - returns */
  221. /* - TRUE if characters up to end of prefix match */
  222. /* - FALSE otherwise */
  223. /****************************************************************************/
  224. BOOL RDPCALL TRCPrefixMatch(char *cpnt, char *prefix)
  225. {
  226. while ((*cpnt == *prefix) && (*prefix != 0)) {
  227. cpnt++;
  228. prefix++;
  229. }
  230. if (*prefix == 0)
  231. return TRUE;
  232. return FALSE;
  233. }
  234. /****************************************************************************/
  235. // TRC_WillTrace
  236. //
  237. // Determines if a trace line will be traced.
  238. /****************************************************************************/
  239. BOOL RDPCALL TRC_WillTrace(
  240. PVOID pTSWd,
  241. UINT32 traceType,
  242. UINT32 traceClass,
  243. char *fileName,
  244. UINT32 line)
  245. {
  246. BOOL rc;
  247. // Very occasionally a timing issue occurs where tracing can happen
  248. // before the pTRCWd in each particular WD component is not initialized.
  249. if (pTSWd != NULL) {
  250. PTRC_SHARED_DATA pTrc = &(((PTSHARE_WD)pTSWd)->trc);
  251. int i;
  252. // If SHM is not set up, return TRUE and let TermDD decide.
  253. if (!pTrc->init) {
  254. rc = TRUE;
  255. DC_QUIT;
  256. }
  257. // Check whether this type and class are enabled.
  258. if (!(traceType & pTrc->TraceEnable) ||
  259. !(traceClass & pTrc->TraceClass)) {
  260. rc = FALSE;
  261. DC_QUIT;
  262. }
  263. // Always trace errors, irrespective of prefix.
  264. if (traceType & TT_API4) {
  265. rc = TRUE;
  266. DC_QUIT;
  267. }
  268. // Trace all lines if no prefixes are defined.
  269. if (pTrc->prefix[0].name[0] == 0) {
  270. rc = TRUE;
  271. DC_QUIT;
  272. }
  273. // Some prefixes are defined - check whether this line matches any of
  274. // them.
  275. for (i = 0; i < TRC_MAX_PREFIX; i++) {
  276. if (pTrc->prefix[i].name[0] == 0) {
  277. // End of list - break.
  278. break;
  279. }
  280. if (TRCPrefixMatch(&(fileName[1]), pTrc->prefix[i].name)) {
  281. // Found matching filename - is there a line number range
  282. // specified?
  283. if ((pTrc->prefix[i].start == 0) &&
  284. (pTrc->prefix[i].end == 0)) {
  285. // No line number range - trace this line.
  286. rc = TRUE;
  287. DC_QUIT;
  288. }
  289. // There's a line number range - see if this line falls within
  290. // it.
  291. if ((line >= pTrc->prefix[i].start) &&
  292. (line <= pTrc->prefix[i].end)) {
  293. // Line within prefix range - trace it.
  294. rc = TRUE;
  295. DC_QUIT;
  296. }
  297. }
  298. } /* for */
  299. // If we get here, we've searched the list of prefixes and failed to
  300. // find a match - don't trace the line.
  301. rc = FALSE;
  302. }
  303. else {
  304. rc = FALSE;
  305. }
  306. DC_EXIT_POINT:
  307. return rc;
  308. }
  309. #endif // DC_DEBUG
  310. #ifdef __cplusplus
  311. }
  312. #endif // __cplusplus