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.

1724 lines
44 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: debug.c
  7. //
  8. // Contents:
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 3-14-95 RichardW Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include "debuglib.h"
  18. PDebugHeader DbgpHeader = NULL;
  19. DebugModule * * DbgpFixupModules[] = { &__pAssertModule,
  20. &__pExceptionModule,
  21. NULL };
  22. CHAR szDebugSection[] = "DSysDebug";
  23. CHAR szDebugFlags[] = "DebugFlags";
  24. DEBUG_KEY DbgpKeys[] = { {DEBUG_NO_DEBUGIO, "NoDebugger"},
  25. {DEBUG_TIMESTAMP, "TimeStamp"},
  26. {DEBUG_DEBUGGER_OK, "DebuggerOk"},
  27. {DEBUG_LOGFILE, "Logfile"},
  28. {DEBUG_AUTO_DEBUG, "AutoDebug"},
  29. {DEBUG_USE_KDEBUG, "UseKD"},
  30. {DEBUG_HEAP_CHECK, "HeapCheck"},
  31. {DEBUG_MULTI_THREAD, "MultiThread"},
  32. {DEBUG_DISABLE_ASRT, "DisableAssert"},
  33. {DEBUG_PROMPTS, "AssertPrompts"},
  34. {DEBUG_BREAK_ON_ERROR,"BreakOnError"},
  35. {0, NULL }
  36. };
  37. #define DEBUG_NUMBER_OF_KEYS ((sizeof(DbgpKeys) / sizeof(DEBUG_KEY)) - 1)
  38. #define _ALIGN(x,a) ((x) & ((a)-1) ? ((x) + (a)) & ~((a) - 1) : (x));
  39. #define ALIGN_8(x) _ALIGN(x, 8)
  40. #define ALIGN_16(x) _ALIGN(x, 16)
  41. #ifdef WIN64
  42. #define DBG_ALIGN ALIGN_16
  43. #else
  44. #define DBG_ALIGN ALIGN_8
  45. #endif
  46. #define DEBUGMEM_ALLOCATED 0x00000001
  47. typedef struct _DebugMemory {
  48. struct _DebugMemory * pNext;
  49. DWORD Size;
  50. DWORD Flags;
  51. } DebugMemory, * PDebugMemory;
  52. #ifdef DEBUG_DEBUG
  53. #define LockDebugHeader(p) EnterCriticalSection(&((p)->csDebug)); OutputDebugStringA("Lock")
  54. #define UnlockDebugHeader(p) LeaveCriticalSection(&((p)->csDebug)); OutputDebugStringA("Unlock")
  55. #else
  56. #define LockDebugHeader(p) EnterCriticalSection(&((p)->csDebug))
  57. #define UnlockDebugHeader(p) LeaveCriticalSection(&((p)->csDebug))
  58. #endif
  59. //+---------------------------------------------------------------------------
  60. //
  61. // Function: DbgpComputeMappingName
  62. //
  63. // Synopsis: Computes the mapping object name
  64. //
  65. // Arguments: [pszName] -- place to stick the name (no more than 32 wchars)
  66. //
  67. // History: 3-22-95 RichardW Created
  68. //
  69. // Notes:
  70. //
  71. //----------------------------------------------------------------------------
  72. void
  73. DbgpComputeMappingName(
  74. IN PWSTR pszName,
  75. IN SIZE_T NameLen
  76. )
  77. {
  78. _snwprintf(pszName, NameLen, TEXT("Debug.Memory.%x"), GetCurrentProcessId());
  79. }
  80. //+---------------------------------------------------------------------------
  81. //
  82. // Function: DbgpInitializeMM
  83. //
  84. // Synopsis: Initializes our simple memory manager within the shared mem
  85. // section.
  86. //
  87. // Arguments: [pHeader] -- Header to initialize
  88. //
  89. // History: 3-22-95 RichardW Created
  90. //
  91. // Notes:
  92. //
  93. //----------------------------------------------------------------------------
  94. VOID
  95. DbgpInitializeMM(PDebugHeader pHeader)
  96. {
  97. PDebugMemory pMem;
  98. pMem = (PDebugMemory) (pHeader + 1);
  99. pMem->pNext = NULL;
  100. pMem->Size = pHeader->CommitRange - (sizeof(DebugHeader) + sizeof(DebugMemory));
  101. pHeader->pFreeList = pMem;
  102. }
  103. //+---------------------------------------------------------------------------
  104. //
  105. // Function: DbgpAlloc
  106. //
  107. // Synopsis: Very, very simple allocator
  108. //
  109. // Arguments: [pHeader] -- Header from which to allocate
  110. // [cSize] -- size to allocate
  111. //
  112. // History: 3-22-95 RichardW Created
  113. //
  114. // Notes:
  115. //
  116. //----------------------------------------------------------------------------
  117. PVOID
  118. DbgpAlloc(
  119. PDebugHeader pHeader,
  120. DWORD cSize)
  121. {
  122. PDebugMemory pSearch;
  123. PDebugMemory pLargest = NULL;
  124. PDebugMemory pNew;
  125. DWORD cLargest;
  126. cLargest = 0;
  127. cSize = DBG_ALIGN(cSize);
  128. //
  129. // Very, very simple allocator. Search free list for an exact match,
  130. //
  131. pSearch = (PDebugMemory) pHeader->pFreeList;
  132. while (pSearch)
  133. {
  134. if ( ( pSearch->Flags & DEBUGMEM_ALLOCATED ) == 0 )
  135. {
  136. if ( pSearch->Size == cSize )
  137. {
  138. break;
  139. }
  140. if (pSearch->Size > cLargest)
  141. {
  142. pLargest = pSearch;
  143. cLargest = pSearch->Size;
  144. }
  145. }
  146. pSearch = pSearch->pNext;
  147. }
  148. //
  149. // If no match yet
  150. //
  151. if (!pSearch)
  152. {
  153. //
  154. // If the largest free block is still too small,
  155. //
  156. if (cLargest < (cSize + sizeof(DebugMemory) * 2))
  157. {
  158. //
  159. // Extend the mapped range
  160. //
  161. if (pHeader->CommitRange < pHeader->ReserveRange)
  162. {
  163. if ( VirtualAlloc(
  164. (PUCHAR) pHeader + pHeader->CommitRange,
  165. pHeader->PageSize,
  166. MEM_COMMIT,
  167. PAGE_READWRITE ) )
  168. {
  169. pNew = (PDebugMemory) ((PUCHAR) pHeader + pHeader->CommitRange );
  170. pHeader->CommitRange += pHeader->PageSize ;
  171. pNew->Size = pHeader->PageSize - sizeof( DebugMemory );
  172. pNew->pNext = pHeader->pFreeList ;
  173. pHeader->pFreeList = pNew ;
  174. return DbgpAlloc( pHeader, cSize );
  175. }
  176. else
  177. {
  178. return NULL ;
  179. }
  180. }
  181. return(NULL);
  182. }
  183. //
  184. // Otherwise, split the largest block into something better...
  185. //
  186. pNew = (PDebugMemory) ((PUCHAR) pLargest + (cSize + sizeof(DebugMemory)) );
  187. pNew->Size = pLargest->Size - (cSize + sizeof(DebugMemory) * 2);
  188. pNew->pNext = pLargest->pNext ;
  189. pNew->Flags = 0;
  190. pLargest->Size = cSize;
  191. pLargest->Flags |= DEBUGMEM_ALLOCATED;
  192. pLargest->pNext = pNew;
  193. return((PVOID) (pLargest + 1) );
  194. }
  195. else
  196. {
  197. pSearch->Flags |= DEBUGMEM_ALLOCATED ;
  198. return((PVOID) (pSearch + 1) );
  199. }
  200. return(NULL);
  201. }
  202. //+---------------------------------------------------------------------------
  203. //
  204. // Function: DbgpFree
  205. //
  206. // Synopsis: Returns memory to the shared mem segment
  207. //
  208. // Arguments: [pHeader] -- Shared memory header
  209. // [pMemory] -- Memory to free
  210. //
  211. // History: 3-22-95 RichardW Created
  212. //
  213. // Notes: No compaction.
  214. //
  215. //----------------------------------------------------------------------------
  216. VOID
  217. DbgpFree(
  218. PDebugHeader pHeader,
  219. PVOID pMemory)
  220. {
  221. PDebugMemory pMem;
  222. pMem = (PDebugMemory) ((PUCHAR) pMemory - sizeof(DebugMemory));
  223. pMem->Flags &= ~DEBUGMEM_ALLOCATED;
  224. ZeroMemory( pMemory, pMem->Size );
  225. }
  226. //+---------------------------------------------------------------------------
  227. //
  228. // Function: DbgpFindModule
  229. //
  230. // Synopsis: Locates a module based on a name
  231. //
  232. // Arguments: [pHeader] -- Header to search
  233. // [pszName] -- module to find
  234. //
  235. // History: 3-22-95 RichardW Created
  236. //
  237. // Notes:
  238. //
  239. //----------------------------------------------------------------------------
  240. PDebugModule
  241. DbgpFindModule(
  242. PDebugHeader pHeader,
  243. CHAR * pszName)
  244. {
  245. PDebugModule pSearch;
  246. pSearch = pHeader->pModules;
  247. while (pSearch)
  248. {
  249. if (_strcmpi(pSearch->pModuleName, pszName) == 0)
  250. {
  251. return(pSearch);
  252. }
  253. pSearch = pSearch->pNext;
  254. }
  255. return(NULL);
  256. }
  257. //+---------------------------------------------------------------------------
  258. //
  259. // Function: DbgpCopyModule
  260. //
  261. // Synopsis: Copies a module into a new module. Used for the builtins.
  262. // note, no references to the code module that the builtin lived
  263. // in is kept. This way, the module can unload.
  264. //
  265. // Arguments: [pHeader] --
  266. // [pSource] --
  267. // [ppDest] --
  268. //
  269. // Requires: Header must be locked.
  270. //
  271. // Returns: 0 for failure, non-zero for success
  272. //
  273. // History: 7-19-95 RichardW Created
  274. //
  275. // Notes:
  276. //
  277. //----------------------------------------------------------------------------
  278. DWORD
  279. DbgpCopyModule(
  280. PDebugHeader pHeader,
  281. PDebugModule pSource,
  282. PDebugModule * ppDest)
  283. {
  284. PDebugModule pModule;
  285. DWORD i;
  286. DWORD cStringSpace;
  287. PCHAR pStrings;
  288. *ppDest = NULL;
  289. cStringSpace = strlen(pSource->pModuleName) + 1;
  290. for (i = 0; i < 32 ; i++ )
  291. {
  292. if (pSource->TagLevels[i])
  293. {
  294. cStringSpace += (strlen(pSource->TagLevels[i]) + 1);
  295. }
  296. }
  297. //
  298. // Allocate an extra DWORD to store the infolevel.
  299. //
  300. pModule = DbgpAlloc(pHeader, sizeof(DebugModule) + sizeof( DWORD ) );
  301. if (!pModule)
  302. {
  303. return(0);
  304. }
  305. pStrings = DbgpAlloc(pHeader, cStringSpace);
  306. if ( !pStrings )
  307. {
  308. DbgpFree( pHeader, pModule );
  309. return 0 ;
  310. }
  311. pModule->pModuleName = pStrings;
  312. cStringSpace = strlen(pSource->pModuleName) + 1;
  313. strcpy(pModule->pModuleName, pSource->pModuleName);
  314. pStrings += cStringSpace;
  315. for (i = 0; i < 32 ; i++ )
  316. {
  317. if (pSource->TagLevels[i])
  318. {
  319. pModule->TagLevels[i] = pStrings;
  320. cStringSpace = strlen(pSource->TagLevels[i]) + 1;
  321. strcpy(pStrings, pSource->TagLevels[i]);
  322. pStrings += cStringSpace;
  323. }
  324. else
  325. {
  326. pSource->TagLevels[i] = NULL;
  327. }
  328. }
  329. //
  330. // Add this in to the global list
  331. //
  332. pModule->pNext = pHeader->pModules;
  333. pHeader->pModules = pModule;
  334. //
  335. // Do not increment module count - this is a builtin
  336. //
  337. //
  338. // Copy the rest of the interesting stuff
  339. //
  340. pModule->pInfoLevel = (PDWORD) (pModule + 1);
  341. *pModule->pInfoLevel = *pSource->pInfoLevel;
  342. pModule->InfoLevel = pSource->InfoLevel;
  343. pModule->fModule = pSource->fModule | DEBUGMOD_BUILTIN_MODULE ;
  344. pModule->pHeader = pHeader;
  345. pModule->TotalOutput = pSource->TotalOutput;
  346. pModule->Reserved = 0;
  347. *ppDest = pModule;
  348. return(1);
  349. }
  350. //+---------------------------------------------------------------------------
  351. //
  352. // Function: DbgpAttachBuiltinModules
  353. //
  354. // Synopsis: Attaches the builtin library modules to the global shared
  355. // list
  356. //
  357. // Arguments: [pHeader] --
  358. //
  359. // History: 7-19-95 RichardW Created
  360. //
  361. // Notes:
  362. //
  363. //----------------------------------------------------------------------------
  364. BOOL
  365. DbgpAttachBuiltinModules(
  366. PDebugHeader pHeader)
  367. {
  368. PDebugModule pModule;
  369. PDebugModule pFixup;
  370. DWORD i;
  371. BOOL Success = FALSE;
  372. i = 0;
  373. while (DbgpFixupModules[i])
  374. {
  375. pFixup = *DbgpFixupModules[i];
  376. pModule = DbgpFindModule(pHeader, pFixup->pModuleName);
  377. if (pModule)
  378. {
  379. *DbgpFixupModules[i] = pModule;
  380. Success = TRUE;
  381. }
  382. else
  383. {
  384. if (DbgpCopyModule(pHeader, pFixup, &pModule))
  385. {
  386. *DbgpFixupModules[i] = pModule;
  387. Success = TRUE;
  388. }
  389. }
  390. i++;
  391. }
  392. return(Success);
  393. }
  394. //+---------------------------------------------------------------------------
  395. //
  396. // Function: DbgpBuildModule
  397. //
  398. // Synopsis: Initializes a Module, builds the string table
  399. //
  400. // Arguments: [pModule] -- Module pointer
  401. // [pHeader] -- Header
  402. // [pKeys] -- Key table
  403. // [pszName] -- Name
  404. // [pInfoLevel] -- Pointer to info level
  405. //
  406. // History: 4-03-95 RichardW Created
  407. //
  408. // Notes:
  409. //
  410. //----------------------------------------------------------------------------
  411. DWORD
  412. DbgpBuildModule(
  413. PDebugModule pModule,
  414. PDebugHeader pHeader,
  415. PDEBUG_KEY pKeys,
  416. PCHAR pszName,
  417. PDWORD pInfoLevel)
  418. {
  419. PCHAR pStringData;
  420. DWORD cStringData;
  421. DWORD cKeys;
  422. DWORD i;
  423. DWORD KeyIndex;
  424. DWORD BitScan;
  425. //
  426. // Easy stuff to start..
  427. //
  428. pModule->pInfoLevel = pInfoLevel;
  429. pModule->pHeader = pHeader;
  430. cStringData = strlen(pszName) + 1;
  431. //
  432. // Search through the list of masks and string tags, computing
  433. // the size needed for containing them all. If a tag has more
  434. // than one bit set, reject it.
  435. //
  436. for (i = 0; i < 32 ; i++ )
  437. {
  438. if (pKeys[i].Mask)
  439. {
  440. if (pKeys[i].Mask & (pKeys[i].Mask - 1))
  441. {
  442. continue;
  443. }
  444. }
  445. if (pKeys[i].Tag)
  446. {
  447. cStringData += strlen(pKeys[i].Tag) + 1;
  448. }
  449. else
  450. {
  451. break;
  452. }
  453. }
  454. //
  455. // We know how many keys there are, and how big a space they need.
  456. //
  457. cKeys = i;
  458. pStringData = DbgpAlloc(pHeader, cStringData);
  459. if ( !pStringData )
  460. {
  461. return 0 ;
  462. }
  463. pModule->pModuleName = pStringData;
  464. strcpy(pStringData, pszName);
  465. pStringData += strlen(pStringData) + 1;
  466. for (i = 0, KeyIndex = 0; i < cKeys ; i++ )
  467. {
  468. if (pKeys[i].Mask & (pKeys[i].Mask - 1))
  469. {
  470. continue;
  471. }
  472. if (!(pKeys[i].Mask & (1 << KeyIndex)))
  473. {
  474. //
  475. // Grr, out of order. Do a bit-wise scan.
  476. //
  477. KeyIndex = 0;
  478. BitScan = 1;
  479. while ((pKeys[i].Mask & BitScan) == 0)
  480. {
  481. BitScan <<= 1;
  482. KeyIndex ++;
  483. }
  484. }
  485. pModule->TagLevels[KeyIndex] = pStringData;
  486. strcpy(pStringData, pKeys[i].Tag);
  487. pStringData += strlen(pKeys[i].Tag) + 1;
  488. KeyIndex++;
  489. }
  490. return(cKeys);
  491. }
  492. //+---------------------------------------------------------------------------
  493. //
  494. // Function: DbgpGetBitmask
  495. //
  496. // Synopsis: Based on a parameter line and a key table, builds the bitmask
  497. //
  498. // Arguments: [pKeys] --
  499. // [cKeys] --
  500. // [pszLine] --
  501. // [ParameterIndex] --
  502. // [ParameterValue] --
  503. //
  504. // History: 4-03-95 RichardW Created
  505. //
  506. // Notes:
  507. //
  508. //----------------------------------------------------------------------------
  509. DWORD
  510. DbgpGetBitmask(
  511. DEBUG_KEY * pKeys,
  512. DWORD cKeys,
  513. PCHAR pszLine,
  514. DWORD ParameterIndex,
  515. PCHAR ParameterValue)
  516. {
  517. PCHAR pszSearch;
  518. PCHAR pszParam;
  519. PCHAR pszScan;
  520. DWORD i;
  521. DWORD Mask;
  522. DWORD cbParameter = 0;
  523. DWORD Compare;
  524. CHAR Saved;
  525. if (ParameterIndex < cKeys)
  526. {
  527. cbParameter = strlen(pKeys[ParameterIndex].Tag);
  528. }
  529. Mask = 0;
  530. pszSearch = pszLine;
  531. //
  532. // Scan through the line, searching for flags. Note: do NOT use strtok,
  533. // since that is not exported by ntdll, and we would not be able to make
  534. // security.dll
  535. //
  536. while (*pszSearch)
  537. {
  538. pszScan = pszSearch;
  539. while ((*pszScan) && (*pszScan != ','))
  540. {
  541. pszScan++;
  542. }
  543. Saved = *pszScan;
  544. *pszScan = '\0';
  545. for (i = 0; i < cKeys ; i++ )
  546. {
  547. if (i == ParameterIndex)
  548. {
  549. if (_strnicmp(pKeys[i].Tag, pszSearch, cbParameter) == 0)
  550. {
  551. pszParam = strchr(pszSearch, ':');
  552. if (pszParam)
  553. {
  554. strcpy(ParameterValue, pszParam + 1);
  555. }
  556. Mask |= pKeys[i].Mask;
  557. }
  558. }
  559. else
  560. {
  561. if (_strcmpi(pKeys[i].Tag, pszSearch) == 0)
  562. {
  563. Mask |= pKeys[i].Mask;
  564. }
  565. }
  566. }
  567. *pszScan = Saved;
  568. if (Saved)
  569. {
  570. while ((*pszScan) && ((*pszScan == ',') || (*pszScan == ' ')))
  571. {
  572. pszScan++;
  573. }
  574. }
  575. pszSearch = pszScan;
  576. }
  577. return(Mask);
  578. }
  579. //+---------------------------------------------------------------------------
  580. //
  581. // Function: DbgpInitializeDebug
  582. //
  583. // Synopsis: Initialize the base memory
  584. //
  585. // Arguments: [pHeader] --
  586. //
  587. // History: 4-03-95 RichardW Created
  588. //
  589. // Notes:
  590. //
  591. //----------------------------------------------------------------------------
  592. VOID
  593. DbgpInitializeDebug(
  594. PDebugHeader pHeader)
  595. {
  596. CHAR szExeName[MAX_PATH] = {0};
  597. PCHAR pszExeName;
  598. PCHAR dot;
  599. DWORD cbExeName;
  600. CHAR LogFile[MAX_PATH + 4] = {0}; // add 4 for ".log"
  601. CHAR Line[MAX_PATH] = {0};
  602. PDebugModule pModule;
  603. HANDLE Token;
  604. TOKEN_STATISTICS TokenStat;
  605. ULONG Size;
  606. LUID LocalSys = SYSTEM_LUID;
  607. //
  608. // Plug the debug section in first
  609. //
  610. pModule = DbgpAlloc(pHeader, sizeof(DebugModule));
  611. if (!pModule)
  612. {
  613. return;
  614. }
  615. DbgpBuildModule(pModule,
  616. pHeader,
  617. DbgpKeys,
  618. DEBUG_MODULE_NAME,
  619. &pHeader->fDebug);
  620. GetModuleFileNameA(NULL, szExeName, RTL_NUMBER_OF(szExeName) - 1);
  621. pszExeName = strrchr(szExeName, '\\');
  622. if (pszExeName)
  623. {
  624. pszExeName++;
  625. }
  626. else
  627. {
  628. pszExeName = szExeName;
  629. }
  630. dot = strrchr(pszExeName, '.');
  631. if (dot)
  632. {
  633. *dot = '\0';
  634. }
  635. cbExeName = (DWORD) (dot - pszExeName);
  636. pHeader->pszExeName = DbgpAlloc(pHeader, cbExeName + 1);
  637. if (pHeader->pszExeName)
  638. {
  639. strcpy(pHeader->pszExeName, pszExeName);
  640. }
  641. LogFile[0] = '\0';
  642. if (GetProfileStringA( szDebugSection,
  643. pszExeName,
  644. "",
  645. Line,
  646. RTL_NUMBER_OF(Line) - 1))
  647. {
  648. pHeader->fDebug = DbgpGetBitmask( DbgpKeys,
  649. DEBUG_NUMBER_OF_KEYS,
  650. Line,
  651. 3,
  652. LogFile);
  653. }
  654. //
  655. // If running as local system, turn on the kd flag. That
  656. // way,
  657. if ( OpenProcessToken( GetCurrentProcess(),
  658. TOKEN_QUERY,
  659. &Token ) )
  660. {
  661. if ( GetTokenInformation( Token,
  662. TokenStatistics,
  663. &TokenStat,
  664. sizeof( TokenStat ),
  665. &Size ) )
  666. {
  667. if ( (TokenStat.AuthenticationId.LowPart == LocalSys.LowPart ) &&
  668. (TokenStat.AuthenticationId.HighPart == LocalSys.HighPart ) )
  669. {
  670. pHeader->fDebug |= DEBUG_USE_KDEBUG ;
  671. }
  672. }
  673. CloseHandle( Token );
  674. }
  675. if (GetProfileStringA( szDebugSection,
  676. szDebugFlags,
  677. "",
  678. Line,
  679. RTL_NUMBER_OF(Line) - 1))
  680. {
  681. pHeader->fDebug |= DbgpGetBitmask( DbgpKeys,
  682. DEBUG_NUMBER_OF_KEYS,
  683. Line,
  684. 3,
  685. LogFile);
  686. }
  687. if ( pHeader->fDebug & DEBUG_USE_KDEBUG )
  688. {
  689. //
  690. // Verify that there is a kernel debugger
  691. //
  692. SYSTEM_KERNEL_DEBUGGER_INFORMATION KdInfo ;
  693. NTSTATUS Status ;
  694. Status = NtQuerySystemInformation(
  695. SystemKernelDebuggerInformation,
  696. &KdInfo,
  697. sizeof( KdInfo ),
  698. NULL );
  699. if ( NT_SUCCESS( Status ) )
  700. {
  701. if ( !KdInfo.KernelDebuggerEnabled )
  702. {
  703. pHeader->fDebug &= ~(DEBUG_USE_KDEBUG) ;
  704. }
  705. }
  706. }
  707. if (pHeader->fDebug & DEBUG_LOGFILE)
  708. {
  709. if (LogFile[0] == '\0')
  710. {
  711. strcpy(LogFile, szExeName);
  712. strcat(LogFile, ".log");
  713. }
  714. pHeader->hLogFile = CreateFileA(LogFile,
  715. GENERIC_READ | GENERIC_WRITE,
  716. FILE_SHARE_READ,
  717. NULL, //&sa,
  718. CREATE_ALWAYS,
  719. FILE_ATTRIBUTE_NORMAL |
  720. FILE_FLAG_WRITE_THROUGH,
  721. NULL);
  722. }
  723. pHeader->pModules = pModule;
  724. pHeader->pGlobalModule = pModule;
  725. pModule->pInfoLevel = &pHeader->fDebug;
  726. pModule->InfoLevel = pHeader->fDebug;
  727. DbgpAttachBuiltinModules(pHeader);
  728. }
  729. //+---------------------------------------------------------------------------
  730. //
  731. // Function: DbgpOpenLogFileRandom
  732. //
  733. // Synopsis: Opens the logfile dynamically
  734. //
  735. // Arguments: [pHeader] --
  736. //
  737. // History: 4-27-95 RichardW Created
  738. //
  739. // Notes:
  740. //
  741. //----------------------------------------------------------------------------
  742. BOOL
  743. DbgpOpenLogFileRandom(
  744. PDebugHeader pHeader)
  745. {
  746. WCHAR szLogPath[MAX_PATH + 4] = {0}; // add 4 for ".log"
  747. DWORD dwPath;
  748. PWSTR pszDot;
  749. dwPath = GetModuleFileName(NULL, szLogPath, RTL_NUMBER_OF(szLogPath) - 4 - 1);
  750. pszDot = wcsrchr(szLogPath, L'.');
  751. if (!pszDot)
  752. {
  753. pszDot = &szLogPath[dwPath];
  754. }
  755. wcscpy(pszDot, L".log");
  756. LockDebugHeader(pHeader);
  757. pHeader->hLogFile = CreateFileW(szLogPath,
  758. GENERIC_READ | GENERIC_WRITE,
  759. FILE_SHARE_READ,
  760. NULL, //&sa,
  761. CREATE_ALWAYS,
  762. FILE_ATTRIBUTE_NORMAL |
  763. FILE_FLAG_WRITE_THROUGH,
  764. NULL);
  765. if (pHeader->hLogFile == INVALID_HANDLE_VALUE)
  766. {
  767. pHeader->fDebug &= ~(DEBUG_LOGFILE);
  768. UnlockDebugHeader(pHeader);
  769. return(FALSE);
  770. }
  771. UnlockDebugHeader(pHeader);
  772. return(TRUE);
  773. }
  774. //+---------------------------------------------------------------------------
  775. //
  776. // Function: _DbgSetLoggingFile
  777. //
  778. // Synopsis: Sets the passed in file handle as the logging file handle.
  779. // This function should be called in combination with
  780. // _DbgSetLoggingOption since this function actually enables/disables
  781. // file logging. Note that if _DbgSetLoggingOption is called
  782. // with the On parameter as FALSE then the file handle will be
  783. // closed.
  784. //
  785. // Arguments: [pHeader] --
  786. // [hLogFile] --
  787. //
  788. // History: 7-16-02 jeffspel Created
  789. //
  790. // Notes:
  791. //
  792. //----------------------------------------------------------------------------
  793. VOID
  794. _DbgSetLoggingFile(
  795. PVOID pControl,
  796. HANDLE hLogFile
  797. )
  798. {
  799. PDebugModule pModule;
  800. pModule = (PDebugModule)pControl;
  801. if ( pModule )
  802. {
  803. LockDebugHeader(pModule->pHeader);
  804. pModule->pHeader->hLogFile = hLogFile;
  805. UnlockDebugHeader(pModule->pHeader);
  806. }
  807. }
  808. //+---------------------------------------------------------------------------
  809. //
  810. // Function: DbgpOpenOrCreateSharedMem
  811. //
  812. // Synopsis: Returns a pointer to the shared memory segment,
  813. // creating it if necessary. Header is LOCKED on return
  814. //
  815. // Arguments: (none)
  816. //
  817. // History: 3-22-95 RichardW Created
  818. //
  819. // Notes:
  820. //
  821. //----------------------------------------------------------------------------
  822. PVOID
  823. DbgpOpenOrCreateSharedMem(DWORD Flags)
  824. {
  825. HANDLE hMapping;
  826. WCHAR szMappingName[32] = {0};
  827. PDebugHeader pHeader;
  828. SYSTEM_INFO SysInfo;
  829. if (DbgpHeader)
  830. {
  831. LockDebugHeader(DbgpHeader);
  832. return(DbgpHeader);
  833. }
  834. GetSystemInfo(&SysInfo);
  835. DbgpComputeMappingName(szMappingName, RTL_NUMBER_OF( szMappingName ) - 1);
  836. hMapping = OpenFileMapping( FILE_MAP_ALL_ACCESS,
  837. FALSE,
  838. szMappingName);
  839. if (hMapping)
  840. {
  841. //
  842. // Ok, someone else has created the section. So, we just need to map
  843. // it.
  844. //
  845. pHeader = MapViewOfFileEx( hMapping,
  846. FILE_MAP_READ | FILE_MAP_WRITE,
  847. 0,
  848. 0,
  849. SysInfo.dwPageSize,
  850. NULL);
  851. if ( pHeader )
  852. {
  853. if (pHeader != pHeader->pvSection)
  854. {
  855. DbgpHeader = pHeader->pvSection;
  856. }
  857. else
  858. {
  859. DbgpHeader = pHeader;
  860. }
  861. UnmapViewOfFile(pHeader);
  862. }
  863. else
  864. {
  865. DbgpHeader = NULL ;
  866. }
  867. //
  868. // Now that we have the other guy's address, we can throw away this
  869. // one.
  870. //
  871. CloseHandle(hMapping);
  872. if ( DbgpHeader )
  873. {
  874. LockDebugHeader(DbgpHeader);
  875. DbgpAttachBuiltinModules(DbgpHeader);
  876. }
  877. return(DbgpHeader);
  878. }
  879. if (Flags & DSYSDBG_OPEN_ONLY)
  880. {
  881. return(NULL);
  882. }
  883. hMapping = CreateFileMapping( INVALID_HANDLE_VALUE,
  884. NULL, //&sa,
  885. PAGE_READWRITE | SEC_RESERVE,
  886. 0,
  887. SysInfo.dwAllocationGranularity,
  888. szMappingName);
  889. if (hMapping)
  890. {
  891. PDebugHeader pMappedHeader;
  892. pMappedHeader = MapViewOfFileEx(hMapping,
  893. FILE_MAP_READ | FILE_MAP_WRITE,
  894. 0,
  895. 0,
  896. SysInfo.dwAllocationGranularity,
  897. NULL);
  898. if (!pMappedHeader)
  899. {
  900. return NULL;
  901. }
  902. //
  903. // Commit the view, so we can initialize the header
  904. //
  905. pHeader = (PDebugHeader) VirtualAlloc(pMappedHeader,
  906. SysInfo.dwPageSize,
  907. MEM_COMMIT,
  908. PAGE_READWRITE);
  909. if (pHeader == NULL)
  910. {
  911. UnmapViewOfFile(pMappedHeader);
  912. return NULL;
  913. }
  914. pHeader->Tag = DEBUG_TAG;
  915. pHeader->pvSection = pHeader;
  916. pHeader->hMapping = hMapping;
  917. pHeader->hLogFile = INVALID_HANDLE_VALUE;
  918. pHeader->CommitRange = SysInfo.dwPageSize;
  919. pHeader->ReserveRange = SysInfo.dwAllocationGranularity;
  920. pHeader->PageSize = SysInfo.dwPageSize;
  921. pHeader->pModules = NULL;
  922. pHeader->pFreeList = NULL;
  923. pHeader->pBufferList = &pHeader->DefaultBuffer ;
  924. pHeader->DefaultBuffer.Next = NULL ;
  925. InitializeCriticalSection(&pHeader->csDebug);
  926. LockDebugHeader(pHeader);
  927. DbgpInitializeMM(pHeader);
  928. DbgpInitializeDebug(pHeader);
  929. DbgpHeader = pHeader;
  930. return(pHeader);
  931. }
  932. return(NULL);
  933. }
  934. //+---------------------------------------------------------------------------
  935. //
  936. // Function: DbgpLoadValidateRoutine
  937. //
  938. // Synopsis: Loads RtlValidateProcessHeaps() from ntdll
  939. //
  940. // Arguments: [pHeader] --
  941. //
  942. // History: 5-02-95 RichardW Created
  943. //
  944. // Notes:
  945. //
  946. //----------------------------------------------------------------------------
  947. VOID
  948. DbgpLoadValidateRoutine(PDebugHeader pHeader)
  949. {
  950. HMODULE hNtDll;
  951. hNtDll = LoadLibrary(TEXT("ntdll.dll"));
  952. if (hNtDll)
  953. {
  954. pHeader->pfnValidate = (HEAPVALIDATE) GetProcAddress(hNtDll, "RtlValidateProcessHeaps");
  955. if (!pHeader->pfnValidate)
  956. {
  957. pHeader->fDebug &= ~(DEBUG_HEAP_CHECK);
  958. }
  959. //
  960. // We can safely free this handle, since kernel32 and advapi32 DLLs
  961. // both use ntdll, so the refcount won't go to zero.
  962. //
  963. FreeLibrary(hNtDll);
  964. }
  965. }
  966. //+---------------------------------------------------------------------------
  967. //
  968. // Function: _InitDebug
  969. //
  970. // Synopsis: Workhorse of the initializers
  971. //
  972. // Arguments: [pInfoLevel] -- Pointer to module specific infolevel
  973. // [ppControlBlock] -- Pointer to module specific control pointer
  974. // [szName] -- Name
  975. // [pKeys] -- Key data
  976. //
  977. // History: 3-22-95 RichardW Created
  978. //
  979. // Notes:
  980. //
  981. //----------------------------------------------------------------------------
  982. VOID
  983. _InitDebug(
  984. DWORD Flags,
  985. DWORD * pInfoLevel,
  986. PVOID * ppControlBlock,
  987. CHAR * szName,
  988. PDEBUG_KEY pKeys)
  989. {
  990. PDebugHeader pHeader;
  991. PDebugModule pModule;
  992. CHAR Line[MAX_PATH] = {0};
  993. DWORD cKeys;
  994. DWORD i;
  995. if ( (*ppControlBlock) && (*ppControlBlock != INVALID_HANDLE_VALUE) )
  996. {
  997. //
  998. // Already Initialized
  999. //
  1000. return ;
  1001. }
  1002. *ppControlBlock = NULL;
  1003. //
  1004. // Find the shared section.
  1005. //
  1006. pHeader = DbgpOpenOrCreateSharedMem(Flags);
  1007. if (!pHeader)
  1008. {
  1009. if (Flags & DSYSDBG_DEMAND_OPEN)
  1010. {
  1011. *ppControlBlock = (PVOID) INVALID_HANDLE_VALUE;
  1012. }
  1013. return;
  1014. }
  1015. //
  1016. // See if we have already registered (dll being loaded several times)
  1017. // if not, allocate a new module.
  1018. //
  1019. pModule = DbgpFindModule(pHeader, szName);
  1020. if (!pModule)
  1021. {
  1022. pModule = DbgpAlloc(pHeader, sizeof(DebugModule) );
  1023. if (!pModule)
  1024. {
  1025. UnlockDebugHeader(pHeader);
  1026. return;
  1027. }
  1028. }
  1029. else
  1030. {
  1031. //
  1032. // Found module already loaded. Check to see that everything
  1033. // lines up:
  1034. //
  1035. if ( pModule->pInfoLevel != pInfoLevel )
  1036. {
  1037. //
  1038. // Uh oh, there's a module with our name already loaded,
  1039. // but the pointers don't match. So, let's create our
  1040. // own now.
  1041. //
  1042. pModule = DbgpAlloc( pHeader, sizeof( DebugModule ) );
  1043. if ( !pModule )
  1044. {
  1045. UnlockDebugHeader( pHeader );
  1046. return;
  1047. }
  1048. }
  1049. else
  1050. {
  1051. *ppControlBlock = pModule;
  1052. UnlockDebugHeader(pHeader);
  1053. return;
  1054. }
  1055. }
  1056. //
  1057. // Initialize module
  1058. //
  1059. cKeys = DbgpBuildModule(pModule,
  1060. pHeader,
  1061. pKeys,
  1062. szName,
  1063. pInfoLevel);
  1064. //
  1065. // Now, load up info levels from ini or registry
  1066. // First, try a module specific entry.
  1067. //
  1068. if (GetProfileStringA(szName, szDebugFlags, "", Line, RTL_NUMBER_OF(Line) - 1))
  1069. {
  1070. pModule->InfoLevel = DbgpGetBitmask(pKeys,
  1071. cKeys,
  1072. Line,
  1073. 0xFFFFFFFF,
  1074. NULL );
  1075. }
  1076. if (pHeader->pszExeName)
  1077. {
  1078. if (GetProfileStringA(szName, pHeader->pszExeName, "", Line, RTL_NUMBER_OF(Line) - 1))
  1079. {
  1080. pModule->InfoLevel = DbgpGetBitmask(pKeys,
  1081. cKeys,
  1082. Line,
  1083. 0xFFFFFFFF,
  1084. NULL );
  1085. }
  1086. }
  1087. // HACK - Make Default DBG / DEBUG_SUPPORT dependent. See dsysdbg.h
  1088. if (GetProfileStringA(szDebugSection, szName, SZ_DEFAULT_PROFILE_STRING, Line, RTL_NUMBER_OF(Line) - 1))
  1089. {
  1090. pModule->InfoLevel |= DbgpGetBitmask( pKeys,
  1091. cKeys,
  1092. Line,
  1093. 0xFFFFFFFF,
  1094. NULL );
  1095. }
  1096. *pModule->pInfoLevel = pModule->InfoLevel;
  1097. pModule->pNext = pHeader->pModules;
  1098. pHeader->pModules = pModule;
  1099. pHeader->ModuleCount++ ;
  1100. *ppControlBlock = pModule;
  1101. UnlockDebugHeader(pHeader);
  1102. }
  1103. VOID
  1104. _UnloadDebug(
  1105. PVOID pControlBlock
  1106. )
  1107. {
  1108. PDebugHeader pHeader;
  1109. PDebugModule pModule;
  1110. PDebugModule pScan ;
  1111. BOOL FreeIt = FALSE ;
  1112. pModule = (PDebugModule) pControlBlock ;
  1113. if ( !pModule )
  1114. {
  1115. return ;
  1116. }
  1117. if ( pModule->pInfoLevel == NULL )
  1118. {
  1119. return ;
  1120. }
  1121. pHeader = pModule->pHeader ;
  1122. LockDebugHeader( pHeader );
  1123. pScan = pHeader->pModules ;
  1124. if ( pScan == pModule )
  1125. {
  1126. pHeader->pModules = pModule->pNext ;
  1127. }
  1128. else
  1129. {
  1130. while ( pScan && ( pScan->pNext != pModule ) )
  1131. {
  1132. pScan = pScan->pNext ;
  1133. }
  1134. if ( pScan )
  1135. {
  1136. pScan->pNext = pModule->pNext ;
  1137. }
  1138. pModule->pNext = NULL ;
  1139. }
  1140. DbgpFree( pHeader, pModule->pModuleName );
  1141. DbgpFree( pHeader, pModule );
  1142. pHeader->ModuleCount-- ;
  1143. if ( pHeader->ModuleCount == 0 )
  1144. {
  1145. FreeIt = TRUE ;
  1146. }
  1147. UnlockDebugHeader( pHeader );
  1148. if ( FreeIt )
  1149. {
  1150. if ( pHeader->hLogFile != INVALID_HANDLE_VALUE )
  1151. {
  1152. CloseHandle( pHeader->hLogFile );
  1153. }
  1154. if ( pHeader->hMapping )
  1155. {
  1156. CloseHandle( pHeader->hMapping );
  1157. }
  1158. DeleteCriticalSection( &pHeader->csDebug );
  1159. UnmapViewOfFile( pHeader );
  1160. }
  1161. }
  1162. //+---------------------------------------------------------------------------
  1163. //
  1164. // Function: DbgpGetTextBuffer
  1165. //
  1166. // Synopsis: Gets a text buffer from the header, allocating if necessary
  1167. //
  1168. // Arguments: [pHeader] --
  1169. //
  1170. // History: 3-19-98 RichardW Created
  1171. //
  1172. // Notes:
  1173. //
  1174. //----------------------------------------------------------------------------
  1175. PDEBUG_TEXT_BUFFER
  1176. DbgpGetTextBuffer(
  1177. PDebugHeader pHeader
  1178. )
  1179. {
  1180. PDEBUG_TEXT_BUFFER pBuffer ;
  1181. LockDebugHeader( pHeader );
  1182. if ( pHeader->pBufferList )
  1183. {
  1184. pBuffer = pHeader->pBufferList ;
  1185. pHeader->pBufferList = pBuffer->Next ;
  1186. }
  1187. else
  1188. {
  1189. pBuffer = DbgpAlloc( pHeader, sizeof( DEBUG_TEXT_BUFFER ) );
  1190. }
  1191. UnlockDebugHeader( pHeader );
  1192. if ( pBuffer )
  1193. {
  1194. pBuffer->Next = NULL ;
  1195. }
  1196. return pBuffer ;
  1197. }
  1198. //+---------------------------------------------------------------------------
  1199. //
  1200. // Function: DbgpReleaseTextBuffer
  1201. //
  1202. // Synopsis: Releases a text buffer back to the pool of buffers
  1203. //
  1204. // Arguments: [pHeader] --
  1205. // [pBuffer] --
  1206. //
  1207. // History: 3-19-98 RichardW Created
  1208. //
  1209. // Notes:
  1210. //
  1211. //----------------------------------------------------------------------------
  1212. VOID
  1213. DbgpReleaseTextBuffer(
  1214. PDebugHeader pHeader,
  1215. PDEBUG_TEXT_BUFFER pBuffer
  1216. )
  1217. {
  1218. LockDebugHeader( pHeader );
  1219. pBuffer->Next = pHeader->pBufferList ;
  1220. pHeader->pBufferList = pBuffer ;
  1221. UnlockDebugHeader( pHeader );
  1222. }
  1223. //+---------------------------------------------------------------------------
  1224. //
  1225. // Function: _DebugOut
  1226. //
  1227. // Synopsis: Workhorse for the debug out functions
  1228. //
  1229. // Arguments: [pControl] -- Control pointer
  1230. // [Mask] -- Event mask
  1231. // [Format] -- format string
  1232. // [ArgList] -- va_list...
  1233. //
  1234. // History: 3-22-95 RichardW Created
  1235. //
  1236. // Notes:
  1237. //
  1238. //----------------------------------------------------------------------------
  1239. VOID
  1240. _DebugOut(
  1241. PVOID pControl,
  1242. ULONG Mask,
  1243. CHAR * Format,
  1244. va_list ArgList)
  1245. {
  1246. PDebugModule pModule;
  1247. int Level = 0;
  1248. int PrefixSize = 0;
  1249. int TotalSize;
  1250. BOOL fLocked;
  1251. BOOL fClean;
  1252. PCHAR Tag;
  1253. BOOL Break = FALSE ;
  1254. PDEBUG_TEXT_BUFFER pBuffer ;
  1255. if ( pControl == NULL )
  1256. {
  1257. return ;
  1258. }
  1259. pModule = (PDebugModule) pControl;
  1260. if ( pModule->pInfoLevel == NULL )
  1261. {
  1262. return ;
  1263. }
  1264. if (!pModule || (pModule == INVALID_HANDLE_VALUE))
  1265. {
  1266. if (Mask & DSYSDBG_FORCE)
  1267. {
  1268. NOTHING ;
  1269. }
  1270. else
  1271. return;
  1272. }
  1273. if (pModule->fModule & DEBUGMOD_CHANGE_INFOLEVEL)
  1274. {
  1275. *pModule->pInfoLevel = pModule->InfoLevel;
  1276. pModule->fModule &= ~(DEBUGMOD_CHANGE_INFOLEVEL);
  1277. }
  1278. if (pModule->pHeader->pGlobalModule->fModule & DEBUGMOD_CHANGE_INFOLEVEL)
  1279. {
  1280. pModule->pHeader->fDebug = pModule->pHeader->pGlobalModule->InfoLevel;
  1281. pModule->pHeader->pGlobalModule->fModule &= ~(DEBUGMOD_CHANGE_INFOLEVEL);
  1282. }
  1283. pModule->InfoLevel = *pModule->pInfoLevel;
  1284. if (pModule->pHeader->fDebug & DEBUG_MULTI_THREAD)
  1285. {
  1286. LockDebugHeader(pModule->pHeader);
  1287. fLocked = TRUE;
  1288. }
  1289. else
  1290. fLocked = FALSE;
  1291. if (pModule->pHeader->fDebug & DEBUG_HEAP_CHECK)
  1292. {
  1293. if (!pModule->pHeader->pfnValidate)
  1294. {
  1295. DbgpLoadValidateRoutine(pModule->pHeader);
  1296. }
  1297. if (pModule->pHeader->pfnValidate)
  1298. {
  1299. pModule->pHeader->pfnValidate();
  1300. }
  1301. }
  1302. fClean = ((Mask & DSYSDBG_CLEAN) != 0);
  1303. if ( ( Mask & DEB_ERROR ) &&
  1304. ( pModule->pHeader->fDebug & DEBUG_BREAK_ON_ERROR ) )
  1305. {
  1306. Break = TRUE ;
  1307. }
  1308. pBuffer = DbgpGetTextBuffer( pModule->pHeader );
  1309. if ( !pBuffer )
  1310. {
  1311. OutputDebugStringA( "_DebugOut : Out of memory\n" );
  1312. if ( fLocked )
  1313. {
  1314. UnlockDebugHeader( pModule->pHeader );
  1315. }
  1316. return;
  1317. }
  1318. if (Mask & (pModule->InfoLevel | DSYSDBG_FORCE))
  1319. {
  1320. if (Mask & DSYSDBG_FORCE)
  1321. {
  1322. Tag = "FORCE";
  1323. }
  1324. else
  1325. {
  1326. while (!(Mask & 1))
  1327. {
  1328. Level++;
  1329. Mask >>= 1;
  1330. }
  1331. Tag = pModule->TagLevels[Level];
  1332. }
  1333. //
  1334. // Make the prefix first: "Process.Thread> Module-Tag:
  1335. //
  1336. if (!fClean)
  1337. {
  1338. if (pModule->pHeader->fDebug & DEBUG_TIMESTAMP)
  1339. {
  1340. SYSTEMTIME stTime;
  1341. GetLocalTime(&stTime);
  1342. PrefixSize = _snprintf(pBuffer->TextBuffer, RTL_NUMBER_OF(pBuffer->TextBuffer) - 1,
  1343. "[%2d/%2d %02d:%02d:%02d] %d.%d> %s-%s: ",
  1344. stTime.wMonth, stTime.wDay,
  1345. stTime.wHour, stTime.wMinute, stTime.wSecond,
  1346. GetCurrentProcessId(),
  1347. GetCurrentThreadId(), pModule->pModuleName,
  1348. Tag);
  1349. }
  1350. else
  1351. {
  1352. PrefixSize = _snprintf(pBuffer->TextBuffer, RTL_NUMBER_OF(pBuffer->TextBuffer) - 1,
  1353. "%d.%d> %s-%s: ",
  1354. GetCurrentProcessId(), GetCurrentThreadId(),
  1355. pModule->pModuleName, Tag);
  1356. }
  1357. if (PrefixSize < 0)
  1358. {
  1359. PrefixSize = 0; // chop off the prefix
  1360. }
  1361. }
  1362. if ((TotalSize = _vsnprintf(&pBuffer->TextBuffer[PrefixSize],
  1363. DEBUG_TEXT_BUFFER_SIZE - PrefixSize - 1,
  1364. Format, ArgList)) < 0)
  1365. {
  1366. //
  1367. // Less than zero indicates that the string could not be
  1368. // fitted into the buffer. Output a special message indicating
  1369. // that:
  1370. //
  1371. OutputDebugStringA("dsysdbg: Could not pack string into 512 bytes\n");
  1372. }
  1373. else
  1374. {
  1375. TotalSize += PrefixSize;
  1376. if ((pModule->pHeader->fDebug & DEBUG_NO_DEBUGIO) == 0 )
  1377. {
  1378. OutputDebugStringA( pBuffer->TextBuffer );
  1379. }
  1380. if ((pModule->pHeader->fDebug & DEBUG_LOGFILE))
  1381. {
  1382. if (pModule->pHeader->hLogFile == INVALID_HANDLE_VALUE)
  1383. {
  1384. DbgpOpenLogFileRandom(pModule->pHeader);
  1385. }
  1386. if (!WriteFile(
  1387. pModule->pHeader->hLogFile,
  1388. pBuffer->TextBuffer,
  1389. (DWORD) TotalSize,
  1390. (PDWORD) &PrefixSize,
  1391. NULL
  1392. ))
  1393. {
  1394. CHAR szOutput[MAX_PATH] = {0};
  1395. _snprintf(szOutput, RTL_NUMBER_OF(szOutput) - 1, "_DebugOut: WriteFile failed with %#x\n", GetLastError());
  1396. OutputDebugStringA(szOutput);
  1397. }
  1398. }
  1399. pModule->pHeader->TotalWritten += TotalSize;
  1400. pModule->TotalOutput += TotalSize;
  1401. }
  1402. }
  1403. if (fLocked)
  1404. {
  1405. UnlockDebugHeader(pModule->pHeader);
  1406. }
  1407. DbgpReleaseTextBuffer( pModule->pHeader, pBuffer );
  1408. if ( Break )
  1409. {
  1410. OutputDebugStringA( "BreakOnError\n" );
  1411. DebugBreak();
  1412. }
  1413. }
  1414. VOID
  1415. _DbgSetOption(
  1416. PVOID pControl,
  1417. DWORD Option,
  1418. BOOL On,
  1419. BOOL Global
  1420. )
  1421. {
  1422. PDebugModule pModule;
  1423. pModule = (PDebugModule) pControl ;
  1424. if ( pModule )
  1425. {
  1426. if ( Global )
  1427. {
  1428. pModule = pModule->pHeader->pGlobalModule ;
  1429. }
  1430. if ( On )
  1431. {
  1432. pModule->InfoLevel |= Option ;
  1433. *pModule->pInfoLevel |= Option ;
  1434. }
  1435. else
  1436. {
  1437. pModule->InfoLevel &= (~Option) ;
  1438. *pModule->pInfoLevel &= (~Option) ;
  1439. }
  1440. }
  1441. }
  1442. VOID
  1443. _DbgSetLoggingOption(
  1444. PVOID pControl,
  1445. BOOL On
  1446. )
  1447. {
  1448. PDebugModule pModule;
  1449. pModule = (PDebugModule)pControl;
  1450. if ( pModule )
  1451. {
  1452. if (((pModule->pHeader->fDebug & DEBUG_LOGFILE) == 0) && On )// off, turn it on
  1453. {
  1454. pModule->pHeader->fDebug |= DEBUG_LOGFILE;
  1455. }
  1456. else if ((pModule->pHeader->fDebug & DEBUG_LOGFILE) && !On) // on, turn it off
  1457. {
  1458. pModule->pHeader->fDebug &= (~DEBUG_LOGFILE);
  1459. if ( pModule->pHeader->hLogFile != INVALID_HANDLE_VALUE )
  1460. {
  1461. CloseHandle( pModule->pHeader->hLogFile );
  1462. pModule->pHeader->hLogFile = INVALID_HANDLE_VALUE;
  1463. }
  1464. }
  1465. }
  1466. }