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.

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