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.

1313 lines
33 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. debug.c
  5. Abstract:
  6. This file contains debugging macros for the BINL server.
  7. Author:
  8. Madan Appiah (madana) 10-Sep-1993
  9. Environment:
  10. User Mode - Win32
  11. Revision History:
  12. --*/
  13. #include "binl.h"
  14. #pragma hdrstop
  15. const char g_szTrue[] = "True";
  16. const char g_szFalse[] = "False";
  17. VOID
  18. DebugInitialize (
  19. VOID
  20. )
  21. {
  22. DWORD dwErr;
  23. HKEY KeyHandle;
  24. InitializeCriticalSection(&BinlGlobalDebugFileCritSect);
  25. BinlGlobalDebugFileHandle = NULL;
  26. BinlGlobalDebugFileMaxSize = DEFAULT_MAXIMUM_DEBUGFILE_SIZE;
  27. BinlGlobalDebugSharePath = NULL;
  28. // Read DebugFlags value
  29. dwErr = RegOpenKeyEx(
  30. HKEY_LOCAL_MACHINE,
  31. BINL_PARAMETERS_KEY,
  32. 0,
  33. KEY_QUERY_VALUE,
  34. &KeyHandle );
  35. if ( dwErr == ERROR_SUCCESS ) {
  36. BinlGlobalDebugFlag = ReadDWord( KeyHandle, BINL_DEBUG_KEY, 0 );
  37. BinlPrintDbg(( DEBUG_OPTIONS, "Debug Flags = 0x%08x.\n", BinlGlobalDebugFlag ));
  38. RegCloseKey( KeyHandle );
  39. }
  40. #if DBG
  41. // break in the debugger if we are asked to do so.
  42. if(BinlGlobalDebugFlag & DEBUG_STARTUP_BRK) {
  43. BinlPrintDbg(( 0, "Stopping at DebugInitialize()'s DebugBreak( ).\n" ));
  44. DebugBreak();
  45. }
  46. #endif
  47. //
  48. // Open debug log file.
  49. //
  50. if ( BinlGlobalDebugFlag & DEBUG_LOG_IN_FILE ) {
  51. BinlOpenDebugFile( FALSE ); // not a reopen.
  52. }
  53. } // DebugInitialize
  54. VOID
  55. DebugUninitialize (
  56. VOID
  57. )
  58. {
  59. EnterCriticalSection( &BinlGlobalDebugFileCritSect );
  60. if ( BinlGlobalDebugFileHandle != NULL ) {
  61. CloseHandle( BinlGlobalDebugFileHandle );
  62. BinlGlobalDebugFileHandle = NULL;
  63. }
  64. if( BinlGlobalDebugSharePath != NULL ) {
  65. BinlFreeMemory( BinlGlobalDebugSharePath );
  66. BinlGlobalDebugSharePath = NULL;
  67. }
  68. LeaveCriticalSection( &BinlGlobalDebugFileCritSect );
  69. DeleteCriticalSection( &BinlGlobalDebugFileCritSect );
  70. } // DebugUninitialize
  71. VOID
  72. BinlOpenDebugFile(
  73. IN BOOL ReopenFlag
  74. )
  75. /*++
  76. Routine Description:
  77. Opens or re-opens the debug file
  78. Arguments:
  79. ReopenFlag - TRUE to indicate the debug file is to be closed, renamed,
  80. and recreated.
  81. Return Value:
  82. None
  83. --*/
  84. {
  85. WCHAR LogFileName[500];
  86. WCHAR BakFileName[500];
  87. DWORD FileAttributes;
  88. DWORD PathLength;
  89. DWORD WinError;
  90. //
  91. // Close the handle to the debug file, if it is currently open
  92. //
  93. EnterCriticalSection( &BinlGlobalDebugFileCritSect );
  94. if ( BinlGlobalDebugFileHandle != NULL ) {
  95. CloseHandle( BinlGlobalDebugFileHandle );
  96. BinlGlobalDebugFileHandle = NULL;
  97. }
  98. LeaveCriticalSection( &BinlGlobalDebugFileCritSect );
  99. //
  100. // make debug directory path first, if it is not made before.
  101. //
  102. if( BinlGlobalDebugSharePath == NULL ) {
  103. if ( !GetWindowsDirectoryW(
  104. LogFileName,
  105. sizeof(LogFileName)/sizeof(WCHAR) ) ) {
  106. BinlPrintDbg((DEBUG_ERRORS, "Window Directory Path can't be "
  107. "retrieved, %lu.\n", GetLastError() ));
  108. return;
  109. }
  110. //
  111. // check debug path length.
  112. //
  113. PathLength = wcslen(LogFileName) * sizeof(WCHAR) +
  114. sizeof(DEBUG_DIR) + sizeof(WCHAR);
  115. if( (PathLength + sizeof(DEBUG_FILE) > sizeof(LogFileName) ) ||
  116. (PathLength + sizeof(DEBUG_BAK_FILE) > sizeof(BakFileName) ) ) {
  117. BinlPrintDbg((DEBUG_ERRORS, "Debug directory path (%ws) length is too long.\n",
  118. LogFileName));
  119. goto ErrorReturn;
  120. }
  121. wcscat(LogFileName, DEBUG_DIR);
  122. //
  123. // copy debug directory name to global var.
  124. //
  125. BinlGlobalDebugSharePath =
  126. BinlAllocateMemory( (wcslen(LogFileName) + 1) * sizeof(WCHAR) );
  127. if( BinlGlobalDebugSharePath == NULL ) {
  128. BinlPrintDbg((DEBUG_ERRORS, "Can't allocate memory for debug share "
  129. "(%ws).\n", LogFileName));
  130. goto ErrorReturn;
  131. }
  132. wcscpy(BinlGlobalDebugSharePath, LogFileName);
  133. }
  134. else {
  135. wcscpy(LogFileName, BinlGlobalDebugSharePath);
  136. }
  137. //
  138. // Check this path exists.
  139. //
  140. FileAttributes = GetFileAttributesW( LogFileName );
  141. if( FileAttributes == 0xFFFFFFFF ) {
  142. WinError = GetLastError();
  143. if( WinError == ERROR_FILE_NOT_FOUND ) {
  144. //
  145. // Create debug directory.
  146. //
  147. if( !CreateDirectoryW( LogFileName, NULL) ) {
  148. BinlPrintDbg((DEBUG_ERRORS, "Can't create Debug directory (%ws), "
  149. "%lu.\n", LogFileName, GetLastError() ));
  150. goto ErrorReturn;
  151. }
  152. }
  153. else {
  154. BinlPrintDbg((DEBUG_ERRORS, "Can't Get File attributes(%ws), "
  155. "%lu.\n", LogFileName, WinError ));
  156. goto ErrorReturn;
  157. }
  158. }
  159. else {
  160. //
  161. // if this is not a directory.
  162. //
  163. if(!(FileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
  164. BinlPrintDbg((DEBUG_ERRORS, "Debug directory path (%ws) exists "
  165. "as file.\n", LogFileName));
  166. goto ErrorReturn;
  167. }
  168. }
  169. //
  170. // Create the name of the old and new log file names
  171. //
  172. (VOID) wcscpy( BakFileName, LogFileName );
  173. (VOID) wcscat( LogFileName, DEBUG_FILE );
  174. (VOID) wcscat( BakFileName, DEBUG_BAK_FILE );
  175. //
  176. // If this is a re-open,
  177. // delete the backup file,
  178. // rename the current file to the backup file.
  179. //
  180. if ( ReopenFlag ) {
  181. if ( !DeleteFile( BakFileName ) ) {
  182. WinError = GetLastError();
  183. if ( WinError != ERROR_FILE_NOT_FOUND ) {
  184. BinlPrintDbg((DEBUG_ERRORS,
  185. "Cannot delete %ws (%ld)\n",
  186. BakFileName,
  187. WinError ));
  188. BinlPrintDbg((DEBUG_ERRORS, " Try to re-open the file.\n"));
  189. ReopenFlag = FALSE; // Don't truncate the file
  190. }
  191. }
  192. }
  193. if ( ReopenFlag ) {
  194. if ( !MoveFile( LogFileName, BakFileName ) ) {
  195. BinlPrintDbg((DEBUG_ERRORS,
  196. "Cannot rename %ws to %ws (%ld)\n",
  197. LogFileName,
  198. BakFileName,
  199. GetLastError() ));
  200. BinlPrintDbg((DEBUG_ERRORS,
  201. " Try to re-open the file.\n"));
  202. ReopenFlag = FALSE; // Don't truncate the file
  203. }
  204. }
  205. //
  206. // Open the file.
  207. //
  208. EnterCriticalSection( &BinlGlobalDebugFileCritSect );
  209. BinlGlobalDebugFileHandle = CreateFileW( LogFileName,
  210. GENERIC_WRITE,
  211. FILE_SHARE_READ | FILE_SHARE_WRITE,
  212. NULL,
  213. ReopenFlag ? CREATE_ALWAYS : OPEN_ALWAYS,
  214. FILE_ATTRIBUTE_NORMAL,
  215. NULL );
  216. if ( BinlGlobalDebugFileHandle == INVALID_HANDLE_VALUE ) {
  217. BinlPrintDbg((DEBUG_ERRORS, "cannot open %ws ,\n",
  218. LogFileName ));
  219. LeaveCriticalSection( &BinlGlobalDebugFileCritSect );
  220. goto ErrorReturn;
  221. } else {
  222. // Position the log file at the end
  223. (VOID) SetFilePointer( BinlGlobalDebugFileHandle,
  224. 0,
  225. NULL,
  226. FILE_END );
  227. }
  228. LeaveCriticalSection( &BinlGlobalDebugFileCritSect );
  229. return;
  230. ErrorReturn:
  231. BinlPrintDbg((DEBUG_ERRORS,
  232. " Debug output will be written to debug terminal.\n"));
  233. return;
  234. }
  235. VOID
  236. BinlPrintRoutine(
  237. IN DWORD DebugFlag,
  238. IN LPSTR Format,
  239. ...
  240. )
  241. {
  242. #define MAX_PRINTF_LEN 1024 // Arbitrary.
  243. va_list arglist;
  244. char OutputBuffer[MAX_PRINTF_LEN];
  245. ULONG length;
  246. DWORD BytesWritten;
  247. static BeginningOfLine = TRUE;
  248. static LineCount = 0;
  249. static TruncateLogFileInProgress = FALSE;
  250. LPSTR Text;
  251. //
  252. // If we aren't debugging this functionality, just return.
  253. //
  254. if ( DebugFlag != 0 && (BinlGlobalDebugFlag & DebugFlag) == 0 ) {
  255. return;
  256. }
  257. //
  258. // vsprintf isn't multithreaded + we don't want to intermingle output
  259. // from different threads.
  260. //
  261. EnterCriticalSection( &BinlGlobalDebugFileCritSect );
  262. length = 0;
  263. //
  264. // Handle the beginning of a new line.
  265. //
  266. //
  267. if ( BeginningOfLine ) {
  268. //
  269. // If the log file is getting huge,
  270. // truncate it.
  271. //
  272. if ( BinlGlobalDebugFileHandle != NULL &&
  273. !TruncateLogFileInProgress ) {
  274. //
  275. // Only check every 50 lines,
  276. //
  277. LineCount++;
  278. if ( LineCount >= 50 ) {
  279. DWORD FileSize;
  280. LineCount = 0;
  281. //
  282. // Is the log file too big?
  283. //
  284. FileSize = GetFileSize( BinlGlobalDebugFileHandle, NULL );
  285. if ( FileSize == 0xFFFFFFFF ) {
  286. (void) DbgPrint( "[BinlServer] Cannot GetFileSize %ld\n",
  287. GetLastError() );
  288. } else if ( FileSize > BinlGlobalDebugFileMaxSize ) {
  289. TruncateLogFileInProgress = TRUE;
  290. LeaveCriticalSection( &BinlGlobalDebugFileCritSect );
  291. BinlOpenDebugFile( TRUE );
  292. BinlPrint(( DEBUG_MISC,
  293. "Logfile truncated because it was larger than %ld bytes\n",
  294. BinlGlobalDebugFileMaxSize ));
  295. EnterCriticalSection( &BinlGlobalDebugFileCritSect );
  296. TruncateLogFileInProgress = FALSE;
  297. }
  298. }
  299. }
  300. // Indicate this is a BINL server's message.
  301. length += (ULONG) sprintf( &OutputBuffer[length], "[BinlServer] " );
  302. //
  303. // Put the thread id at the begining of the line.
  304. //
  305. if (BinlGlobalDebugFlag & DEBUG_THREAD) {
  306. DWORD threadId = GetCurrentThreadId();
  307. length += (ULONG) sprintf( &OutputBuffer[length],
  308. "%08x ", threadId );
  309. }
  310. //
  311. // Put the timestamp at the begining of the line.
  312. //
  313. if (BinlGlobalDebugFlag & DEBUG_TIMESTAMP) {
  314. SYSTEMTIME SystemTime;
  315. GetLocalTime( &SystemTime );
  316. length += (ULONG) sprintf( &OutputBuffer[length],
  317. "%02u/%02u %02u:%02u:%02u ",
  318. SystemTime.wMonth,
  319. SystemTime.wDay,
  320. SystemTime.wHour,
  321. SystemTime.wMinute,
  322. SystemTime.wSecond );
  323. }
  324. //
  325. // Indicate the type of message on the line
  326. //
  327. switch (DebugFlag) {
  328. case DEBUG_OPTIONS:
  329. Text = "OPTIONS";
  330. break;
  331. case DEBUG_ERRORS:
  332. Text = "ERRORS";
  333. break;
  334. case DEBUG_STOC:
  335. Text = "STOC";
  336. break;
  337. case DEBUG_INIT:
  338. Text = "INIT";
  339. break;
  340. case DEBUG_SCAVENGER:
  341. Text = "SCAVENGER";
  342. break;
  343. case DEBUG_REGISTRY:
  344. Text = "REGISTRY";
  345. break;
  346. case DEBUG_NETINF:
  347. Text = "NETINF";
  348. break;
  349. case DEBUG_MISC:
  350. Text = "MISC";
  351. break;
  352. case DEBUG_MESSAGE:
  353. Text = "MESSAGE";
  354. break;
  355. case DEBUG_LOG_IN_FILE:
  356. Text = "LOG_IN_FILE";
  357. break;
  358. default:
  359. Text = NULL;
  360. break;
  361. }
  362. if ( Text != NULL ) {
  363. length += (ULONG) sprintf( &OutputBuffer[length], "[%s] ", Text );
  364. }
  365. }
  366. //
  367. // Put a the information requested by the caller onto the line
  368. //
  369. va_start(arglist, Format);
  370. length += (ULONG) vsprintf(&OutputBuffer[length], Format, arglist);
  371. BeginningOfLine = (length > 0 && OutputBuffer[length-1] == '\n' );
  372. va_end(arglist);
  373. // Add in the fix for notepad users and fixing the assert
  374. BinlAssert(length < MAX_PRINTF_LEN - 1);
  375. if(BeginningOfLine){
  376. OutputBuffer[length-1] = '\r';
  377. OutputBuffer[length] = '\n';
  378. length++;
  379. OutputBuffer[length] = '\0';
  380. }
  381. //
  382. // Output to the debug terminal,
  383. // if the log file isn't open or we are asked to do so.
  384. //
  385. if ( (BinlGlobalDebugFileHandle == NULL) ||
  386. !(BinlGlobalDebugFlag & DEBUG_LOG_IN_FILE) ) {
  387. //
  388. // Don't use DbgPrint(OutputBuffer) here because the buffer
  389. // might contain strings that printf will try to interpret
  390. // (e.g., NewMachineNamingPolicy = %1Fist%Last%#).
  391. //
  392. (void) DbgPrint( "%s", (PCH)OutputBuffer);
  393. //
  394. // Write the debug info to the log file.
  395. //
  396. } else {
  397. if ( !WriteFile( BinlGlobalDebugFileHandle,
  398. OutputBuffer,
  399. lstrlenA( OutputBuffer ),
  400. &BytesWritten,
  401. NULL ) ) {
  402. (void) DbgPrint( "%s", (PCH) OutputBuffer);
  403. }
  404. }
  405. LeaveCriticalSection( &BinlGlobalDebugFileCritSect );
  406. }
  407. #if DBG
  408. VOID
  409. BinlAssertFailed(
  410. LPSTR FailedAssertion,
  411. LPSTR FileName,
  412. DWORD LineNumber,
  413. LPSTR Message
  414. )
  415. /*++
  416. Routine Description:
  417. Assertion failed.
  418. Arguments:
  419. FailedAssertion :
  420. FileName :
  421. LineNumber :
  422. Message :
  423. Return Value:
  424. none.
  425. --*/
  426. {
  427. RtlAssert(
  428. FailedAssertion,
  429. FileName,
  430. (ULONG) LineNumber,
  431. (PCHAR) Message);
  432. BinlPrintDbg(( 0, "Assert @ %s \n", FailedAssertion ));
  433. BinlPrintDbg(( 0, "Assert Filename, %s \n", FileName ));
  434. BinlPrintDbg(( 0, "Line Num. = %ld.\n", LineNumber ));
  435. BinlPrintDbg(( 0, "Message is %s\n", Message ));
  436. #if DBG
  437. DebugBreak( );
  438. #endif
  439. }
  440. VOID
  441. BinlDumpMessage(
  442. DWORD BinlDebugFlag,
  443. LPDHCP_MESSAGE BinlMessage
  444. )
  445. /*++
  446. Routine Description:
  447. This function dumps a DHCP packet in human readable form.
  448. Arguments:
  449. BinlDebugFlag - debug flag that indicates what we are debugging.
  450. BinlMessage - A pointer to a DHCP message.
  451. Return Value:
  452. None.
  453. --*/
  454. {
  455. LPOPTION option;
  456. BYTE i;
  457. BinlPrintDbg(( BinlDebugFlag, "Binl message: \n\n"));
  458. BinlPrintDbg(( BinlDebugFlag, "Operation :"));
  459. if ( BinlMessage->Operation == BOOT_REQUEST ) {
  460. BinlPrintDbg(( BinlDebugFlag, "BootRequest\n"));
  461. } else if ( BinlMessage->Operation == BOOT_REPLY ) {
  462. BinlPrintDbg(( BinlDebugFlag, "BootReply\n"));
  463. } else {
  464. BinlPrintDbg(( BinlDebugFlag, "Unknown %x\n", BinlMessage->Operation));
  465. return;
  466. }
  467. BinlPrintDbg(( BinlDebugFlag, "Hardware Address type : %d\n", BinlMessage->HardwareAddressType));
  468. BinlPrintDbg(( BinlDebugFlag, "Hardware Address Length: %d\n", BinlMessage->HardwareAddressLength));
  469. BinlPrintDbg(( BinlDebugFlag, "Hop Count : %d\n", BinlMessage->HopCount ));
  470. BinlPrintDbg(( BinlDebugFlag, "Transaction ID : %lx\n", BinlMessage->TransactionID ));
  471. BinlPrintDbg(( BinlDebugFlag, "Seconds Since Boot : %d\n", BinlMessage->SecondsSinceBoot ));
  472. BinlPrintDbg(( BinlDebugFlag, "Client IP Address : " ));
  473. BinlPrintDbg(( BinlDebugFlag, "%s\n",
  474. inet_ntoa(*(struct in_addr *)&BinlMessage->ClientIpAddress ) ));
  475. BinlPrintDbg(( BinlDebugFlag, "Your IP Address : " ));
  476. BinlPrintDbg(( BinlDebugFlag, "%s\n",
  477. inet_ntoa(*(struct in_addr *)&BinlMessage->YourIpAddress ) ));
  478. BinlPrintDbg(( BinlDebugFlag, "Server IP Address : " ));
  479. BinlPrintDbg(( BinlDebugFlag, "%s\n",
  480. inet_ntoa(*(struct in_addr *)&BinlMessage->BootstrapServerAddress ) ));
  481. BinlPrintDbg(( BinlDebugFlag, "Relay Agent IP Address : " ));
  482. BinlPrintDbg(( BinlDebugFlag, "%s\n",
  483. inet_ntoa(*(struct in_addr *)&BinlMessage->RelayAgentIpAddress ) ));
  484. BinlPrintDbg(( BinlDebugFlag, "Hardware Address : "));
  485. for ( i = 0; i < BinlMessage->HardwareAddressLength; i++ ) {
  486. BinlPrintDbg(( BinlDebugFlag, "%2.2x", BinlMessage->HardwareAddress[i] ));
  487. }
  488. option = &BinlMessage->Option;
  489. BinlPrintDbg(( BinlDebugFlag, "\n\n"));
  490. BinlPrintDbg(( BinlDebugFlag, "Magic Cookie: "));
  491. for ( i = 0; i < 4; i++ ) {
  492. BinlPrintDbg(( BinlDebugFlag, "%d ", *((LPBYTE)option)++ ));
  493. }
  494. BinlPrintDbg(( BinlDebugFlag, "\n\n"));
  495. BinlPrintDbg(( BinlDebugFlag, "Options:\n"));
  496. while ( option->OptionType != 255 ) {
  497. BinlPrintDbg(( BinlDebugFlag, "\tType = %d ", option->OptionType ));
  498. for ( i = 0; i < option->OptionLength; i++ ) {
  499. BinlPrintDbg(( BinlDebugFlag, "%2.2x", option->OptionValue[i] ));
  500. }
  501. BinlPrintDbg(( BinlDebugFlag, "\n"));
  502. if ( option->OptionType == OPTION_PAD ||
  503. option->OptionType == OPTION_END ) {
  504. option = (LPOPTION)( (LPBYTE)(option) + 1);
  505. } else {
  506. option = (LPOPTION)( (LPBYTE)(option) + option->OptionLength + 2);
  507. }
  508. if ( (LPBYTE)option - (LPBYTE)BinlMessage > DHCP_MESSAGE_SIZE ) {
  509. BinlPrintDbg(( BinlDebugFlag, "End of message, but no trailer found!\n"));
  510. break;
  511. }
  512. }
  513. }
  514. #endif // DBG
  515. DWORD
  516. BinlReportEventW(
  517. DWORD EventID,
  518. DWORD EventType,
  519. DWORD NumStrings,
  520. DWORD DataLength,
  521. LPWSTR *Strings,
  522. LPVOID Data
  523. )
  524. /*++
  525. Routine Description:
  526. This function writes the specified (EventID) log at the end of the
  527. eventlog.
  528. Arguments:
  529. EventID - The specific event identifier. This identifies the
  530. message that goes with this event.
  531. EventType - Specifies the type of event being logged. This
  532. parameter can have one of the following
  533. values:
  534. Value Meaning
  535. EVENTLOG_ERROR_TYPE Error event
  536. EVENTLOG_WARNING_TYPE Warning event
  537. EVENTLOG_INFORMATION_TYPE Information event
  538. NumStrings - Specifies the number of strings that are in the array
  539. at 'Strings'. A value of zero indicates no strings
  540. are present.
  541. DataLength - Specifies the number of bytes of event-specific raw
  542. (binary) data to write to the log. If cbData is
  543. zero, no event-specific data is present.
  544. Strings - Points to a buffer containing an array of null-terminated
  545. strings that are merged into the message before
  546. displaying to the user. This parameter must be a valid
  547. pointer (or NULL), even if cStrings is zero.
  548. Data - Buffer containing the raw data. This parameter must be a
  549. valid pointer (or NULL), even if cbData is zero.
  550. Return Value:
  551. Returns the WIN32 extended error obtained by GetLastError().
  552. NOTE : This function works slow since it calls the open and close
  553. eventlog source everytime.
  554. --*/
  555. {
  556. HANDLE EventlogHandle;
  557. DWORD ReturnCode;
  558. //
  559. // open eventlog section.
  560. //
  561. EventlogHandle = RegisterEventSourceW(NULL, BINL_SERVER);
  562. if (EventlogHandle == NULL) {
  563. ReturnCode = GetLastError();
  564. goto Cleanup;
  565. }
  566. //
  567. // Log the error code specified
  568. //
  569. if( !ReportEventW(
  570. EventlogHandle,
  571. (WORD)EventType,
  572. 0, // event category
  573. EventID,
  574. NULL,
  575. (WORD)NumStrings,
  576. DataLength,
  577. Strings,
  578. Data
  579. ) ) {
  580. ReturnCode = GetLastError();
  581. goto Cleanup;
  582. }
  583. ReturnCode = NO_ERROR;
  584. Cleanup:
  585. if( EventlogHandle != NULL ) {
  586. DeregisterEventSource(EventlogHandle);
  587. }
  588. return ReturnCode;
  589. }
  590. DWORD
  591. BinlReportEventA(
  592. DWORD EventID,
  593. DWORD EventType,
  594. DWORD NumStrings,
  595. DWORD DataLength,
  596. LPSTR *Strings,
  597. LPVOID Data
  598. )
  599. /*++
  600. Routine Description:
  601. This function writes the specified (EventID) log at the end of the
  602. eventlog.
  603. Arguments:
  604. Source - Points to a null-terminated string that specifies the name
  605. of the module referenced. The node must exist in the
  606. registration database, and the module name has the
  607. following format:
  608. \EventLog\System\Lanmanworkstation
  609. EventID - The specific event identifier. This identifies the
  610. message that goes with this event.
  611. EventType - Specifies the type of event being logged. This
  612. parameter can have one of the following
  613. values:
  614. Value Meaning
  615. EVENTLOG_ERROR_TYPE Error event
  616. EVENTLOG_WARNING_TYPE Warning event
  617. EVENTLOG_INFORMATION_TYPE Information event
  618. NumStrings - Specifies the number of strings that are in the array
  619. at 'Strings'. A value of zero indicates no strings
  620. are present.
  621. DataLength - Specifies the number of bytes of event-specific raw
  622. (binary) data to write to the log. If cbData is
  623. zero, no event-specific data is present.
  624. Strings - Points to a buffer containing an array of null-terminated
  625. strings that are merged into the message before
  626. displaying to the user. This parameter must be a valid
  627. pointer (or NULL), even if cStrings is zero.
  628. Data - Buffer containing the raw data. This parameter must be a
  629. valid pointer (or NULL), even if cbData is zero.
  630. Return Value:
  631. Returns the WIN32 extended error obtained by GetLastError().
  632. NOTE : This function works slow since it calls the open and close
  633. eventlog source everytime.
  634. --*/
  635. {
  636. HANDLE EventlogHandle;
  637. DWORD ReturnCode;
  638. //
  639. // open eventlog section.
  640. //
  641. EventlogHandle = RegisterEventSourceW(
  642. NULL,
  643. BINL_SERVER
  644. );
  645. if (EventlogHandle == NULL) {
  646. ReturnCode = GetLastError();
  647. goto Cleanup;
  648. }
  649. //
  650. // Log the error code specified
  651. //
  652. if( !ReportEventA(
  653. EventlogHandle,
  654. (WORD)EventType,
  655. 0, // event category
  656. EventID,
  657. NULL,
  658. (WORD)NumStrings,
  659. DataLength,
  660. Strings,
  661. Data
  662. ) ) {
  663. ReturnCode = GetLastError();
  664. goto Cleanup;
  665. }
  666. ReturnCode = NO_ERROR;
  667. Cleanup:
  668. if( EventlogHandle != NULL ) {
  669. DeregisterEventSource(EventlogHandle);
  670. }
  671. return ReturnCode;
  672. }
  673. VOID
  674. BinlServerEventLog(
  675. DWORD EventID,
  676. DWORD EventType,
  677. DWORD ErrorCode
  678. )
  679. /*++
  680. Routine Description:
  681. Logs an event in EventLog.
  682. Arguments:
  683. EventID - The specific event identifier. This identifies the
  684. message that goes with this event.
  685. EventType - Specifies the type of event being logged. This
  686. parameter can have one of the following
  687. values:
  688. Value Meaning
  689. EVENTLOG_ERROR_TYPE Error event
  690. EVENTLOG_WARNING_TYPE Warning event
  691. EVENTLOG_INFORMATION_TYPE Information event
  692. ErrorCode - Error Code to be Logged.
  693. Return Value:
  694. None.
  695. --*/
  696. {
  697. DWORD Error;
  698. LPSTR Strings[1];
  699. CHAR ErrorCodeOemString[32 + 1];
  700. wsprintfA( ErrorCodeOemString, "%lu", ErrorCode );
  701. Strings[0] = ErrorCodeOemString;
  702. Error = BinlReportEventA(
  703. EventID,
  704. EventType,
  705. 1,
  706. sizeof(ErrorCode),
  707. Strings,
  708. &ErrorCode );
  709. if( Error != ERROR_SUCCESS ) {
  710. BinlPrintDbg(( DEBUG_ERRORS,
  711. "BinlReportEventW failed, %ld.\n", Error ));
  712. }
  713. return;
  714. }
  715. #if DBG==1
  716. //
  717. // Memory allocation and tracking
  718. //
  719. LPVOID g_TraceMemoryTable = NULL;
  720. CRITICAL_SECTION g_TraceMemoryCS;
  721. #define DEBUG_OUTPUT_BUFFER_SIZE 1024
  722. typedef struct _MEMORYBLOCK {
  723. HGLOBAL hglobal;
  724. struct _MEMORYBLOCK *pNext;
  725. LPCSTR pszModule;
  726. LPCSTR pszComment;
  727. LPCSTR pszFile;
  728. DWORD dwBytes;
  729. UINT uFlags;
  730. UINT uLine;
  731. } MEMORYBLOCK, *LPMEMORYBLOCK;
  732. //
  733. // Takes the filename and line number and put them into a string buffer.
  734. //
  735. // NOTE: the buffer is assumed to be of size DEBUG_OUTPUT_BUFFER_SIZE.
  736. //
  737. LPSTR
  738. dbgmakefilelinestring(
  739. LPSTR pszBuf,
  740. LPCSTR pszFile,
  741. UINT uLine )
  742. {
  743. LPVOID args[2];
  744. args[0] = (LPVOID) pszFile;
  745. args[1] = (LPVOID) UintToPtr( uLine );
  746. FormatMessageA(
  747. FORMAT_MESSAGE_FROM_STRING |
  748. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  749. "%1(%2!u!):",
  750. 0, // error code
  751. 0, // default language
  752. (LPSTR) pszBuf, // output buffer
  753. DEBUG_OUTPUT_BUFFER_SIZE, // size of buffer
  754. (va_list*) &args ); // arguments
  755. return pszBuf;
  756. }
  757. //
  758. // Adds a MEMORYBLOCK to the memory tracking list.
  759. //
  760. HGLOBAL
  761. DebugMemoryAdd(
  762. HGLOBAL hglobal,
  763. LPCSTR pszFile,
  764. UINT uLine,
  765. LPCSTR pszModule,
  766. UINT uFlags,
  767. DWORD dwBytes,
  768. LPCSTR pszComment )
  769. {
  770. if ( hglobal )
  771. {
  772. LPMEMORYBLOCK pmb = (LPMEMORYBLOCK) GlobalAlloc(
  773. GMEM_FIXED,
  774. sizeof(MEMORYBLOCK) );
  775. if ( !pmb )
  776. {
  777. GlobalFree( hglobal );
  778. return NULL;
  779. }
  780. pmb->hglobal = hglobal;
  781. pmb->dwBytes = dwBytes;
  782. pmb->uFlags = uFlags;
  783. pmb->pszFile = pszFile;
  784. pmb->uLine = uLine;
  785. pmb->pszModule = pszModule;
  786. pmb->pszComment = pszComment;
  787. EnterCriticalSection( &g_TraceMemoryCS );
  788. pmb->pNext = g_TraceMemoryTable;
  789. g_TraceMemoryTable = pmb;
  790. BinlPrintDbg((DEBUG_MEMORY, "DebugAlloc: 0x%08x alloced (%s)\n", hglobal, pmb->pszComment ));
  791. LeaveCriticalSection( &g_TraceMemoryCS );
  792. }
  793. return hglobal;
  794. }
  795. //
  796. // Removes a MEMORYBLOCK to the memory tracking list.
  797. //
  798. void
  799. DebugMemoryDelete(
  800. HGLOBAL hglobal )
  801. {
  802. if ( hglobal )
  803. {
  804. LPMEMORYBLOCK pmbHead;
  805. LPMEMORYBLOCK pmbLast = NULL;
  806. EnterCriticalSection( &g_TraceMemoryCS );
  807. pmbHead = g_TraceMemoryTable;
  808. while ( pmbHead && pmbHead->hglobal != hglobal )
  809. {
  810. pmbLast = pmbHead;
  811. pmbHead = pmbLast->pNext;
  812. }
  813. if ( pmbHead )
  814. {
  815. HGLOBAL *p;
  816. if ( pmbLast )
  817. {
  818. pmbLast->pNext = pmbHead->pNext;
  819. }
  820. else
  821. {
  822. g_TraceMemoryTable = pmbHead->pNext;
  823. }
  824. BinlPrintDbg((DEBUG_MEMORY, "DebugFree: 0x%08x freed (%s)\n", hglobal,
  825. pmbHead->pszComment ));
  826. p = (HGLOBAL)((LPBYTE)hglobal + pmbHead->dwBytes - sizeof(HGLOBAL));
  827. if ( *p != hglobal )
  828. {
  829. BinlPrintDbg(((DEBUG_ERRORS|DEBUG_MEMORY), "DebugFree: Heap check FAILED for %0x08x %u bytes (%s).\n",
  830. hglobal, pmbHead->dwBytes, pmbHead->pszComment));
  831. BinlPrintDbg(((DEBUG_ERRORS|DEBUG_MEMORY), "DebugFree: %s, Line: %u\n",
  832. pmbHead->pszFile, pmbHead->uLine ));
  833. BinlAssert( *p == hglobal );
  834. }
  835. memset( hglobal, 0xFE, pmbHead->dwBytes );
  836. memset( pmbHead, 0xFD, sizeof(sizeof(MEMORYBLOCK)) );
  837. LocalFree( pmbHead );
  838. }
  839. else
  840. {
  841. HGLOBAL *p;
  842. BinlPrintDbg(((DEBUG_ERRORS|DEBUG_MEMORY), "DebugFree: 0x%08x not found in memory table\n", hglobal ));
  843. memset( hglobal, 0xFE, (int)LocalSize( hglobal ));
  844. }
  845. LeaveCriticalSection( &g_TraceMemoryCS );
  846. }
  847. }
  848. //
  849. // Allocates memory and adds the MEMORYBLOCK to the memory tracking list.
  850. //
  851. HGLOBAL
  852. DebugAlloc(
  853. LPCSTR pszFile,
  854. UINT uLine,
  855. LPCSTR pszModule,
  856. UINT uFlags,
  857. DWORD dwBytes,
  858. LPCSTR pszComment )
  859. {
  860. HGLOBAL hglobal;
  861. DWORD dwBytesToAlloc = ROUND_UP_COUNT( dwBytes + sizeof(HGLOBAL), ALIGN_WORST);
  862. HGLOBAL *p;
  863. hglobal = GlobalAlloc( uFlags, dwBytesToAlloc );
  864. if (hglobal == NULL) {
  865. return NULL;
  866. }
  867. p = (HGLOBAL)((LPBYTE)hglobal + dwBytesToAlloc - sizeof(HGLOBAL));
  868. *p = hglobal;
  869. return DebugMemoryAdd( hglobal, pszFile, uLine, pszModule, uFlags, dwBytesToAlloc, pszComment );
  870. }
  871. //
  872. // Remove the MEMORYBLOCK to the memory tracking list, memsets the
  873. // memory to 0xFE and then frees the memory.
  874. //
  875. HGLOBAL
  876. DebugFree(
  877. HGLOBAL hglobal )
  878. {
  879. DebugMemoryDelete( hglobal );
  880. return GlobalFree( hglobal );
  881. }
  882. //
  883. // Checks the memory tracking list. If it is not empty, it will dump the
  884. // list and break.
  885. //
  886. void
  887. DebugMemoryCheck( )
  888. {
  889. BOOL fFoundLeak = FALSE;
  890. LPMEMORYBLOCK pmb;
  891. EnterCriticalSection( &g_TraceMemoryCS );
  892. pmb = g_TraceMemoryTable;
  893. while ( pmb )
  894. {
  895. LPMEMORYBLOCK pTemp;
  896. LPVOID args[ 5 ];
  897. CHAR szOutput[ DEBUG_OUTPUT_BUFFER_SIZE ];
  898. CHAR szFileLine[ DEBUG_OUTPUT_BUFFER_SIZE ];
  899. if ( fFoundLeak == FALSE )
  900. {
  901. BinlPrintRoutine( 0, "\n***************************** Memory leak detected *****************************\n\n");
  902. //BinlPrintRoutine( 0, "1234567890123456789012345678901234567890 1234567890 X 0x12345678 12345 1...");
  903. BinlPrintRoutine( 0, "Filename(Line Number): Module Addr/HGLOBAL Size String\n");
  904. fFoundLeak = TRUE;
  905. }
  906. args[0] = (LPVOID) pmb->hglobal;
  907. args[1] = (LPVOID) &szFileLine;
  908. args[2] = (LPVOID) pmb->pszComment;
  909. args[3] = (LPVOID) ULongToPtr( pmb->dwBytes );
  910. args[4] = (LPVOID) pmb->pszModule;
  911. dbgmakefilelinestring( szFileLine, pmb->pszFile, pmb->uLine );
  912. if ( !!(pmb->uFlags & GMEM_MOVEABLE) )
  913. {
  914. FormatMessageA(
  915. FORMAT_MESSAGE_FROM_STRING |
  916. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  917. "%2!-40s! %5!-10s! H 0x%1!08x! %4!-5u! \"%3\"\n",
  918. 0, // error code
  919. 0, // default language
  920. (LPSTR) &szOutput, // output buffer
  921. DEBUG_OUTPUT_BUFFER_SIZE, // size of buffer
  922. (va_list*) &args ); // arguments
  923. }
  924. else
  925. {
  926. FormatMessageA(
  927. FORMAT_MESSAGE_FROM_STRING |
  928. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  929. "%2!-40s! %5!-10s! A 0x%1!08x! %4!-5u! \"%3\"\n",
  930. 0, // error code
  931. 0, // default language
  932. (LPSTR) &szOutput, // output buffer
  933. DEBUG_OUTPUT_BUFFER_SIZE, // size of buffer
  934. (va_list*) &args ); // arguments
  935. }
  936. BinlPrintRoutine( 0, szOutput );
  937. pTemp = pmb;
  938. pmb = pmb->pNext;
  939. memset( pTemp, 0xFD, sizeof(MEMORYBLOCK) );
  940. LocalFree( pTemp );
  941. }
  942. if ( fFoundLeak == TRUE )
  943. {
  944. BinlPrintRoutine( 0, "\n***************************** Memory leak detected *****************************\n\n");
  945. }
  946. LeaveCriticalSection( &g_TraceMemoryCS );
  947. //BinlAssert( !fFoundLeak );
  948. }
  949. VOID
  950. DumpBuffer(
  951. PVOID Buffer,
  952. ULONG BufferSize
  953. )
  954. /*++
  955. Routine Description:
  956. Dumps the buffer content on to the debugger output.
  957. Arguments:
  958. Buffer: buffer pointer.
  959. BufferSize: size of the buffer.
  960. Return Value:
  961. none
  962. --*/
  963. {
  964. #define NUM_CHARS 16
  965. ULONG i, limit;
  966. CHAR TextBuffer[NUM_CHARS + 1];
  967. PUCHAR BufferPtr = Buffer;
  968. DbgPrint("------------------------------------\n");
  969. //
  970. // Hex dump of the bytes
  971. //
  972. limit = ((BufferSize - 1) / NUM_CHARS + 1) * NUM_CHARS;
  973. for (i = 0; i < limit; i++) {
  974. if (i < BufferSize) {
  975. DbgPrint("%02x ", (UCHAR)BufferPtr[i]);
  976. if (BufferPtr[i] < 31 ) {
  977. TextBuffer[i % NUM_CHARS] = '.';
  978. } else if (BufferPtr[i] == '\0') {
  979. TextBuffer[i % NUM_CHARS] = ' ';
  980. } else {
  981. TextBuffer[i % NUM_CHARS] = (CHAR) BufferPtr[i];
  982. }
  983. } else {
  984. DbgPrint(" ");
  985. TextBuffer[i % NUM_CHARS] = ' ';
  986. }
  987. if ((i + 1) % NUM_CHARS == 0) {
  988. TextBuffer[NUM_CHARS] = 0;
  989. DbgPrint(" %s\n", TextBuffer);
  990. }
  991. }
  992. DbgPrint("------------------------------------\n");
  993. }
  994. #endif // DBG==1