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.

358 lines
10 KiB

  1. // Ruler
  2. // 1 2 3 4 5 6 7 8
  3. //345678901234567890123456789012345678901234567890123456789012345678901234567890
  4. /********************************************************************/
  5. /* */
  6. /* The standard layout. */
  7. /* */
  8. /* The standard layout for 'cpp' files in this code is as */
  9. /* follows: */
  10. /* */
  11. /* 1. Include files. */
  12. /* 2. Constants local to the class. */
  13. /* 3. Data structures local to the class. */
  14. /* 4. Data initializations. */
  15. /* 5. Static functions. */
  16. /* 6. Class functions. */
  17. /* */
  18. /* The constructor is typically the first function, class */
  19. /* member functions appear in alphabetical order with the */
  20. /* destructor appearing at the end of the file. Any section */
  21. /* or function this is not required is simply omitted. */
  22. /* */
  23. /********************************************************************/
  24. #include "LibraryPCH.hpp"
  25. #include "Global.hpp"
  26. #include "Spinlock.hpp"
  27. /********************************************************************/
  28. /* */
  29. /* Constants local to the class. */
  30. /* */
  31. /* The constants supplied here control various debug settings. */
  32. /* */
  33. /********************************************************************/
  34. CONST SBIT32 MaxDebugFileName = 128;
  35. CONST SBIT32 DebugBufferSize = 512;
  36. #ifdef ENABLE_DEBUG
  37. #ifdef ENABLE_DEBUG_FILE
  38. /********************************************************************/
  39. /* */
  40. /* Static member initialization. */
  41. /* */
  42. /* Static member initialization sets the initial value for all */
  43. /* static members. */
  44. /* */
  45. /********************************************************************/
  46. STATIC CHAR DebugModuleName[ MaxDebugFileName ] = "";
  47. STATIC SPINLOCK Spinlock;
  48. /********************************************************************/
  49. /* */
  50. /* Debug file name. */
  51. /* */
  52. /* We sometimes want to change the debug file name to prevent */
  53. /* the debug file being overwritten by a DLLs output or a later */
  54. /* run of the same application. */
  55. /* */
  56. /********************************************************************/
  57. HANDLE DebugFileHandle( VOID )
  58. {
  59. AUTO CHAR FileName[ MaxDebugFileName ];
  60. STATIC HANDLE DebugFile = INVALID_HANDLE_VALUE;
  61. //
  62. // We will open the debug file if it is not
  63. // already open.
  64. //
  65. if ( DebugFile == INVALID_HANDLE_VALUE )
  66. {
  67. //
  68. // Construct the full file name.
  69. //
  70. sprintf
  71. (
  72. FileName,
  73. "C:\\Temp\\DebugTrace%s.log",
  74. DebugModuleName
  75. );
  76. //
  77. // Now lets try to open the file.
  78. //
  79. DebugFile =
  80. (
  81. CreateFile
  82. (
  83. ((LPCTSTR) FileName),
  84. (GENERIC_READ | GENERIC_WRITE),
  85. FILE_SHARE_READ,
  86. NULL,
  87. CREATE_ALWAYS,
  88. NULL,
  89. NULL
  90. )
  91. );
  92. //
  93. // When the file will not open for some reason
  94. // we try an alternative path.
  95. //
  96. if ( DebugFile == INVALID_HANDLE_VALUE )
  97. {
  98. //
  99. // Construct the alternate file name.
  100. //
  101. sprintf
  102. (
  103. FileName,
  104. "C:\\DebugTrace%s.log",
  105. DebugModuleName
  106. );
  107. //
  108. // Try again using an alternative name.
  109. //
  110. DebugFile =
  111. (
  112. CreateFile
  113. (
  114. ((LPCTSTR) FileName),
  115. (GENERIC_READ | GENERIC_WRITE),
  116. FILE_SHARE_READ,
  117. NULL,
  118. CREATE_ALWAYS,
  119. NULL,
  120. NULL
  121. )
  122. );
  123. }
  124. }
  125. return DebugFile;
  126. }
  127. /********************************************************************/
  128. /* */
  129. /* Debug file name. */
  130. /* */
  131. /* We sometimes want to change the debug file name to prevent */
  132. /* the debug file being overwritten by a DLLs output or a later */
  133. /* run of the same application. */
  134. /* */
  135. /********************************************************************/
  136. VOID DebugFileName( CONST CHAR *FileName )
  137. {
  138. AUTO CHAR EditBuffer[ MaxDebugFileName ];
  139. REGISTER CHAR *Current;
  140. //
  141. // Copy the file name into an edit buffer
  142. // so we can remove any directories or
  143. // trailing names.
  144. //
  145. strncpy( EditBuffer,FileName,MaxDebugFileName );
  146. EditBuffer[ (MaxDebugFileName-1) ] = '\0';
  147. //
  148. // Scan backwards to remove any suffix.
  149. //
  150. for
  151. (
  152. Current = & EditBuffer[ (strlen( EditBuffer )-1) ];
  153. (Current > EditBuffer) && ((*Current) != '.') && ((*Current) != '\\');
  154. Current --
  155. );
  156. if ( (Current > EditBuffer) && (*Current) == '.' )
  157. { (*Current) = '\0'; }
  158. //
  159. // Scan backwards to the first directory name.
  160. //
  161. for
  162. (
  163. Current = & EditBuffer[ (strlen( EditBuffer )-1) ];
  164. (Current > EditBuffer) && ((*Current) != '\\');
  165. Current --
  166. );
  167. if ( (*Current) == '\\' )
  168. { Current ++; }
  169. //
  170. // Copy the edited file name.
  171. //
  172. DebugModuleName[0] = '-';
  173. strncpy( & DebugModuleName[1],Current,(MaxDebugFileName-1) );
  174. }
  175. #endif
  176. #endif
  177. /********************************************************************/
  178. /* */
  179. /* Debug printing. */
  180. /* */
  181. /* We sometimes need to print message during debugging. We */
  182. /* do this using the following 'printf' like function. */
  183. /* */
  184. /********************************************************************/
  185. VOID DebugPrint( CONST CHAR *Format,... )
  186. {
  187. AUTO CHAR Buffer[ DebugBufferSize ];
  188. //
  189. // Start of variable arguments.
  190. //
  191. va_list Arguments;
  192. va_start(Arguments, Format);
  193. //
  194. // Format the string to be printed.
  195. //
  196. _vsnprintf
  197. (
  198. Buffer,
  199. (DebugBufferSize-1),
  200. Format,
  201. Arguments
  202. );
  203. //
  204. // Force null termination.
  205. //
  206. Buffer[ (DebugBufferSize-1) ] = '\0';
  207. #ifdef ENABLE_DEBUG_FILE
  208. //
  209. // Claim a spinlock to prevent multiple
  210. // threads executing overlapping writes.
  211. //
  212. Spinlock.ClaimLock();
  213. //
  214. // We will write to the debug file if there
  215. // is a valid handle.
  216. //
  217. if ( DebugFileHandle() != INVALID_HANDLE_VALUE )
  218. {
  219. REGISTER CHAR *Current = Buffer;
  220. REGISTER SBIT32 Length;
  221. //
  222. // A number of windows applications are too
  223. // stupid to understand a simple '\n'. So
  224. // here we convert all "\n" to "\r\n".
  225. //
  226. for ( /* void */;(*Current) != '\0';Current += Length )
  227. {
  228. STATIC DWORD Written;
  229. //
  230. // Count the characters until the next
  231. // newline or end of string.
  232. //
  233. for
  234. (
  235. Length=0;
  236. ((Current[ Length ] != '\n') && (Current[ Length ] != '\0'));
  237. Length ++
  238. );
  239. //
  240. // Write the string and then add a return
  241. // newline sequence.
  242. //
  243. WriteFile
  244. (
  245. DebugFileHandle(),
  246. ((LPCVOID) Current),
  247. ((DWORD) Length),
  248. & Written,
  249. NULL
  250. );
  251. //
  252. // Generate a newline (if needed).
  253. //
  254. if ( Current[ Length ] == '\n' )
  255. {
  256. WriteFile
  257. (
  258. DebugFileHandle(),
  259. ((LPCVOID) "\r\n"),
  260. ((DWORD) (sizeof("\r\n") - 1)),
  261. & Written,
  262. NULL
  263. );
  264. Length ++;
  265. }
  266. }
  267. //
  268. // Flush the file buffers.
  269. //
  270. FlushFileBuffers( DebugFileHandle() );
  271. }
  272. //
  273. // Release any lock claimed earlier.
  274. //
  275. Spinlock.ReleaseLock();
  276. #else
  277. //
  278. // Write to the debug window.
  279. //
  280. OutputDebugString( Buffer );
  281. #endif
  282. //
  283. // End of variable arguments.
  284. //
  285. va_end( Arguments );
  286. }
  287. /********************************************************************/
  288. /* */
  289. /* Software failure. */
  290. /* */
  291. /* We know that when this function is called the application */
  292. /* has failed so we simply try to cleanly exit in the vain */
  293. /* hope that the failure can be caught and corrected. */
  294. /* */
  295. /********************************************************************/
  296. VOID Failure( char *Message,BOOLEAN Report )
  297. {
  298. #ifdef ENABLE_DEBUG
  299. //
  300. // Report the fault to the debug stream
  301. // (if required).
  302. //
  303. if ( Report )
  304. { DebugPrint( "*** Software Failure: %s ***\n",Message ); }
  305. #endif
  306. //
  307. // Raise an exception.
  308. //
  309. #ifdef DISABLE_STRUCTURED_EXCEPTIONS
  310. throw ((FAULT) Message);
  311. #else
  312. RaiseException( 1,0,1,((CONST DWORD*) Message) );
  313. #endif
  314. }