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.

3028 lines
80 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Extension DLL support.
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997-2002.
  6. //
  7. //----------------------------------------------------------------------------
  8. #include "ntsdp.hpp"
  9. #include <time.h>
  10. /*
  11. * _NT_DEBUG_OPTIONS support. Each option in g_EnvDbgOptionNames must have a
  12. * corresponding OPTION_* define, in the same order.
  13. */
  14. DWORD g_EnvDbgOptions;
  15. char* g_EnvDbgOptionNames[OPTION_COUNT] =
  16. {
  17. "NOEXTWARNING",
  18. "NOVERSIONCHECK",
  19. };
  20. EXTDLL *g_ExtDlls;
  21. LPTSTR g_BaseExtensionSearchPath = NULL;
  22. ULONG64 g_ExtThread;
  23. ULONG g_ExtGetExpressionRemainderIndex;
  24. BOOL g_ExtGetExpressionSuccess;
  25. WOW64EXTSPROC g_Wow64exts;
  26. EXTDLL* g_Wow64ExtDll;
  27. WMI_FORMAT_TRACE_DATA g_WmiFormatTraceData;
  28. EXTDLL* g_WmiExtDll;
  29. DEBUG_SCOPE g_ExtThreadSavedScope;
  30. BOOL g_ExtThreadScopeSaved;
  31. //
  32. // Functions prototyped specifically for compatibility with extension
  33. // callback prototypes.
  34. //
  35. VOID WDBGAPIV
  36. ExtOutput64(
  37. PCSTR lpFormat,
  38. ...
  39. );
  40. VOID WDBGAPIV
  41. ExtOutput32(
  42. PCSTR lpFormat,
  43. ...
  44. );
  45. ULONG64
  46. ExtGetExpression(
  47. PCSTR CommandString
  48. );
  49. ULONG
  50. ExtGetExpression32(
  51. PCSTR CommandString
  52. );
  53. void
  54. ExtGetSymbol(
  55. ULONG64 Offset,
  56. PCHAR Buffer,
  57. PULONG64 Displacement
  58. );
  59. void
  60. ExtGetSymbol32(
  61. ULONG Offset,
  62. PCHAR Buffer,
  63. PULONG Displacement
  64. );
  65. DWORD
  66. ExtDisasm(
  67. PULONG64 lpOffset,
  68. PCSTR lpBuffer,
  69. ULONG fShowEA
  70. );
  71. DWORD
  72. ExtDisasm32(
  73. PULONG lpOffset,
  74. PCSTR lpBuffer,
  75. ULONG fShowEA
  76. );
  77. BOOL
  78. ExtReadVirtualMemory(
  79. IN ULONG64 Address,
  80. OUT PUCHAR Buffer,
  81. IN ULONG Length,
  82. OUT PULONG BytesRead
  83. );
  84. BOOL
  85. ExtReadVirtualMemory32(
  86. IN ULONG Address,
  87. OUT PUCHAR Buffer,
  88. IN ULONG Length,
  89. OUT PULONG BytesRead
  90. );
  91. ULONG
  92. ExtWriteVirtualMemory(
  93. IN ULONG64 Address,
  94. IN LPCVOID Buffer,
  95. IN ULONG Length,
  96. OUT PULONG BytesWritten
  97. );
  98. ULONG
  99. ExtWriteVirtualMemory32(
  100. IN ULONG Address,
  101. IN LPCVOID Buffer,
  102. IN ULONG Length,
  103. OUT PULONG BytesWritten
  104. );
  105. BOOL ExtGetThreadContext(DWORD Processor,
  106. PVOID Context,
  107. DWORD SizeOfContext);
  108. BOOL ExtSetThreadContext(DWORD Processor,
  109. PVOID Context,
  110. DWORD SizeOfContext);
  111. BOOL
  112. ExtIoctl(
  113. USHORT IoctlType,
  114. LPVOID lpvData,
  115. DWORD cbSize
  116. );
  117. BOOL
  118. ExtIoctl32(
  119. USHORT IoctlType,
  120. LPVOID lpvData,
  121. DWORD cbSize
  122. );
  123. DWORD
  124. ExtCallStack(
  125. DWORD64 FramePointer,
  126. DWORD64 StackPointer,
  127. DWORD64 ProgramCounter,
  128. PEXTSTACKTRACE64 StackFrames,
  129. DWORD Frames
  130. );
  131. DWORD
  132. ExtCallStack32(
  133. DWORD FramePointer,
  134. DWORD StackPointer,
  135. DWORD ProgramCounter,
  136. PEXTSTACKTRACE32 StackFrames,
  137. DWORD Frames
  138. );
  139. BOOL
  140. ExtReadPhysicalMemory(
  141. ULONGLONG Address,
  142. PVOID Buffer,
  143. ULONG Length,
  144. PULONG BytesRead
  145. );
  146. BOOL
  147. ExtWritePhysicalMemory(
  148. ULONGLONG Address,
  149. LPCVOID Buffer,
  150. ULONG Length,
  151. PULONG BytesWritten
  152. );
  153. WINDBG_EXTENSION_APIS64 g_WindbgExtensions64 =
  154. {
  155. sizeof(g_WindbgExtensions64),
  156. ExtOutput64,
  157. ExtGetExpression,
  158. ExtGetSymbol,
  159. ExtDisasm,
  160. CheckUserInterrupt,
  161. (PWINDBG_READ_PROCESS_MEMORY_ROUTINE64)ExtReadVirtualMemory,
  162. ExtWriteVirtualMemory,
  163. (PWINDBG_GET_THREAD_CONTEXT_ROUTINE)ExtGetThreadContext,
  164. (PWINDBG_SET_THREAD_CONTEXT_ROUTINE)ExtSetThreadContext,
  165. (PWINDBG_IOCTL_ROUTINE)ExtIoctl,
  166. ExtCallStack
  167. };
  168. WINDBG_EXTENSION_APIS32 g_WindbgExtensions32 =
  169. {
  170. sizeof(g_WindbgExtensions32),
  171. ExtOutput32,
  172. ExtGetExpression32,
  173. ExtGetSymbol32,
  174. ExtDisasm32,
  175. CheckUserInterrupt,
  176. (PWINDBG_READ_PROCESS_MEMORY_ROUTINE32)ExtReadVirtualMemory32,
  177. ExtWriteVirtualMemory32,
  178. (PWINDBG_GET_THREAD_CONTEXT_ROUTINE)ExtGetThreadContext,
  179. (PWINDBG_SET_THREAD_CONTEXT_ROUTINE)ExtSetThreadContext,
  180. (PWINDBG_IOCTL_ROUTINE)ExtIoctl32,
  181. ExtCallStack32
  182. };
  183. WINDBG_OLDKD_EXTENSION_APIS g_KdExtensions =
  184. {
  185. sizeof(g_KdExtensions),
  186. ExtOutput32,
  187. ExtGetExpression32,
  188. ExtGetSymbol32,
  189. ExtDisasm32,
  190. CheckUserInterrupt,
  191. (PWINDBG_READ_PROCESS_MEMORY_ROUTINE32)ExtReadVirtualMemory32,
  192. ExtWriteVirtualMemory32,
  193. (PWINDBG_OLDKD_READ_PHYSICAL_MEMORY)ExtReadPhysicalMemory,
  194. (PWINDBG_OLDKD_WRITE_PHYSICAL_MEMORY)ExtWritePhysicalMemory
  195. };
  196. //----------------------------------------------------------------------------
  197. //
  198. // Callback functions for extensions.
  199. //
  200. //----------------------------------------------------------------------------
  201. VOID WDBGAPIV
  202. ExtOutput64(
  203. PCSTR lpFormat,
  204. ...
  205. )
  206. {
  207. va_list Args;
  208. va_start(Args, lpFormat);
  209. MaskOutVa(DEBUG_OUTPUT_NORMAL, lpFormat, Args, TRUE);
  210. va_end(Args);
  211. // Make sure output for long-running extensions appears regularly.
  212. TimedFlushCallbacks();
  213. }
  214. VOID WDBGAPIV
  215. ExtOutput32(
  216. PCSTR lpFormat,
  217. ...
  218. )
  219. {
  220. va_list Args;
  221. va_start(Args, lpFormat);
  222. MaskOutVa(DEBUG_OUTPUT_NORMAL, lpFormat, Args, FALSE);
  223. va_end(Args);
  224. // Make sure output for long-running extensions appears regularly.
  225. TimedFlushCallbacks();
  226. }
  227. ULONG64
  228. ExtGetExpression(
  229. PCSTR CommandString
  230. )
  231. {
  232. g_ExtGetExpressionSuccess = FALSE;
  233. if (CommandString == NULL)
  234. {
  235. return 0;
  236. }
  237. ULONG64 ReturnValue;
  238. PSTR SaveCommand = g_CurCmd;
  239. PSTR SaveStart = g_CommandStart;
  240. if (IS_USER_TARGET(g_Target))
  241. {
  242. if ( strcmp(CommandString, "WOW_BIG_BDE_HACK") == 0 )
  243. {
  244. return( (ULONG_PTR)(&segtable[0]) );
  245. }
  246. //
  247. // this is because the kdexts MUST include the address-of operator
  248. // on all getexpression calls for windbg/c expression evaluators
  249. //
  250. if (*CommandString == '&')
  251. {
  252. CommandString++;
  253. }
  254. }
  255. g_CurCmd = (PSTR)CommandString;
  256. g_CommandStart = (PSTR)CommandString;
  257. g_DisableErrorPrint++;
  258. EvalExpression* RelChain = g_EvalReleaseChain;
  259. g_EvalReleaseChain = NULL;
  260. __try
  261. {
  262. // ntsd/windbg extensions always use the MASM-style
  263. // expression evaluator for compatibility.
  264. EvalExpression* Eval = GetEvaluator(DEBUG_EXPR_MASM, FALSE);
  265. ReturnValue = Eval->EvalCurNum();
  266. ReleaseEvaluator(Eval);
  267. g_ExtGetExpressionSuccess = TRUE;
  268. }
  269. __except(CommandExceptionFilter(GetExceptionInformation()))
  270. {
  271. ReturnValue = 0;
  272. }
  273. g_ExtGetExpressionRemainderIndex =
  274. (ULONG)(g_CurCmd - g_CommandStart);
  275. g_EvalReleaseChain = RelChain;
  276. g_DisableErrorPrint--;
  277. g_CurCmd = SaveCommand;
  278. g_CommandStart = SaveStart;
  279. // Make sure output for long-running extensions appears regularly.
  280. TimedFlushCallbacks();
  281. return ReturnValue;
  282. }
  283. ULONG
  284. ExtGetExpression32(
  285. LPCSTR CommandString
  286. )
  287. {
  288. return (ULONG)ExtGetExpression(CommandString);
  289. }
  290. void
  291. ExtGetSymbol (
  292. ULONG64 offset,
  293. PCHAR pchBuffer,
  294. PULONG64 pDisplacement
  295. )
  296. {
  297. // No way to know how much space we're given, so
  298. // just assume 256, which many extensions pass in
  299. GetSymbol(offset, pchBuffer, 256, pDisplacement);
  300. // Make sure output for long-running extensions appears regularly.
  301. TimedFlushCallbacks();
  302. }
  303. void
  304. ExtGetSymbol32(
  305. ULONG offset,
  306. PCHAR pchBuffer,
  307. PULONG pDisplacement
  308. )
  309. {
  310. ULONG64 Displacement;
  311. // No way to know how much space we're given, so
  312. // just assume 256, which many extensions pass in
  313. GetSymbol(EXTEND64(offset), pchBuffer, 256, &Displacement);
  314. *pDisplacement = (ULONG)Displacement;
  315. // Make sure output for long-running extensions appears regularly.
  316. TimedFlushCallbacks();
  317. }
  318. DWORD
  319. ExtDisasm(
  320. ULONG64 *lpOffset,
  321. PCSTR lpBuffer,
  322. ULONG fShowEA
  323. )
  324. {
  325. if (!IS_CUR_MACHINE_ACCESSIBLE())
  326. {
  327. ErrOut("ExtDisasm called before debugger initialized\n");
  328. return FALSE;
  329. }
  330. ADDR tempAddr;
  331. BOOL ret;
  332. Type(tempAddr) = ADDR_FLAT | FLAT_COMPUTED;
  333. Off(tempAddr) = Flat(tempAddr) = *lpOffset;
  334. ret = g_Machine->
  335. Disassemble(g_Process, &tempAddr, (PSTR)lpBuffer, (BOOL) fShowEA);
  336. *lpOffset = Flat(tempAddr);
  337. return ret;
  338. }
  339. DWORD
  340. ExtDisasm32(
  341. ULONG *lpOffset,
  342. PCSTR lpBuffer,
  343. ULONG fShowEA
  344. )
  345. {
  346. ULONG64 Offset = EXTEND64(*lpOffset);
  347. DWORD rval = ExtDisasm(&Offset, lpBuffer, fShowEA);
  348. *lpOffset = (ULONG)Offset;
  349. return rval;
  350. }
  351. BOOL
  352. ExtGetThreadContext(DWORD Processor,
  353. PVOID Context,
  354. DWORD SizeOfContext)
  355. {
  356. if (!IS_CUR_MACHINE_ACCESSIBLE())
  357. {
  358. return FALSE;
  359. }
  360. // This get may be getting the context of the thread
  361. // currently cached by the register code. Make sure
  362. // the cache is flushed.
  363. g_Target->FlushRegContext();
  364. CROSS_PLATFORM_CONTEXT TargetContext;
  365. g_Target->m_Machine->
  366. InitializeContextFlags(&TargetContext, g_Target->m_SystemVersion);
  367. if (g_Target->GetContext(IS_KERNEL_TARGET(g_Target) ?
  368. VIRTUAL_THREAD_HANDLE(Processor) : Processor,
  369. &TargetContext) == S_OK &&
  370. g_Machine->ConvertContextTo(&TargetContext, g_Target->m_SystemVersion,
  371. SizeOfContext, Context) == S_OK)
  372. {
  373. return TRUE;
  374. }
  375. return FALSE;
  376. }
  377. BOOL
  378. ExtSetThreadContext(DWORD Processor,
  379. PVOID Context,
  380. DWORD SizeOfContext)
  381. {
  382. if (!IS_CUR_MACHINE_ACCESSIBLE())
  383. {
  384. return FALSE;
  385. }
  386. BOOL Status;
  387. // This set may be setting the context of the thread
  388. // currently cached by the register code. Make sure
  389. // the cache is invalidated.
  390. g_Target->ChangeRegContext(NULL);
  391. CROSS_PLATFORM_CONTEXT TargetContext;
  392. if (g_Machine->
  393. ConvertContextFrom(&TargetContext, g_Target->m_SystemVersion,
  394. SizeOfContext, Context) == S_OK &&
  395. g_Target->SetContext(IS_KERNEL_TARGET(g_Target) ?
  396. VIRTUAL_THREAD_HANDLE(Processor) : Processor,
  397. &TargetContext) == S_OK)
  398. {
  399. Status = TRUE;
  400. }
  401. else
  402. {
  403. Status = FALSE;
  404. }
  405. // Reset the current thread.
  406. g_Target->ChangeRegContext(g_Thread);
  407. return Status;
  408. }
  409. BOOL
  410. ExtReadVirtualMemory(
  411. IN ULONG64 pBufSrc,
  412. OUT PUCHAR pBufDest,
  413. IN ULONG count,
  414. OUT PULONG pcTotalBytesRead
  415. )
  416. {
  417. // Make sure output for long-running extensions appears regularly.
  418. TimedFlushCallbacks();
  419. ULONG BytesTemp;
  420. return g_Target->
  421. ReadVirtual(g_Process,
  422. pBufSrc, pBufDest, count, pcTotalBytesRead != NULL ?
  423. pcTotalBytesRead : &BytesTemp) == S_OK;
  424. }
  425. BOOL
  426. ExtReadVirtualMemory32(
  427. IN ULONG pBufSrc,
  428. OUT PUCHAR pBufDest,
  429. IN ULONG count,
  430. OUT PULONG pcTotalBytesRead
  431. )
  432. {
  433. // Make sure output for long-running extensions appears regularly.
  434. TimedFlushCallbacks();
  435. ULONG BytesTemp;
  436. return g_Target->
  437. ReadVirtual(g_Process, EXTEND64(pBufSrc), pBufDest, count,
  438. pcTotalBytesRead != NULL ?
  439. pcTotalBytesRead : &BytesTemp) == S_OK;
  440. }
  441. DWORD
  442. ExtWriteVirtualMemory(
  443. IN ULONG64 addr,
  444. IN LPCVOID buffer,
  445. IN ULONG count,
  446. OUT PULONG pcBytesWritten
  447. )
  448. {
  449. ULONG BytesTemp;
  450. return (g_Target->WriteVirtual(g_Process, addr, (PVOID)buffer, count,
  451. pcBytesWritten != NULL ?
  452. pcBytesWritten : &BytesTemp) == S_OK);
  453. }
  454. ULONG
  455. ExtWriteVirtualMemory32 (
  456. IN ULONG addr,
  457. IN LPCVOID buffer,
  458. IN ULONG count,
  459. OUT PULONG pcBytesWritten
  460. )
  461. {
  462. ULONG BytesTemp;
  463. return (g_Target->WriteVirtual(g_Process, EXTEND64(addr),
  464. (PVOID)buffer, count,
  465. pcBytesWritten != NULL ?
  466. pcBytesWritten : &BytesTemp) == S_OK);
  467. }
  468. BOOL
  469. ExtReadPhysicalMemory(
  470. ULONGLONG pBufSrc,
  471. PVOID pBufDest,
  472. ULONG count,
  473. PULONG TotalBytesRead
  474. )
  475. {
  476. // Make sure output for long-running extensions appears regularly.
  477. TimedFlushCallbacks();
  478. if (ARGUMENT_PRESENT(TotalBytesRead))
  479. {
  480. *TotalBytesRead = 0;
  481. }
  482. ULONG BytesTemp;
  483. return g_Target->ReadPhysical(pBufSrc, pBufDest, count,
  484. PHYS_FLAG_DEFAULT,
  485. TotalBytesRead != NULL ?
  486. TotalBytesRead : &BytesTemp) == S_OK;
  487. }
  488. BOOL
  489. ExtWritePhysicalMemory (
  490. ULONGLONG pBufDest,
  491. LPCVOID pBufSrc,
  492. ULONG count,
  493. PULONG TotalBytesWritten
  494. )
  495. {
  496. if (ARGUMENT_PRESENT(TotalBytesWritten))
  497. {
  498. *TotalBytesWritten = 0;
  499. }
  500. ULONG BytesTemp;
  501. return g_Target->WritePhysical(pBufDest, (PVOID)pBufSrc, count,
  502. PHYS_FLAG_DEFAULT,
  503. TotalBytesWritten != NULL ?
  504. TotalBytesWritten : &BytesTemp) == S_OK;
  505. }
  506. BOOL
  507. ExtReadPhysicalMemoryWithFlags(
  508. ULONGLONG pBufSrc,
  509. PVOID pBufDest,
  510. ULONG count,
  511. ULONG Flags,
  512. PULONG TotalBytesRead
  513. )
  514. {
  515. // Make sure output for long-running extensions appears regularly.
  516. TimedFlushCallbacks();
  517. if (ARGUMENT_PRESENT(TotalBytesRead))
  518. {
  519. *TotalBytesRead = 0;
  520. }
  521. ULONG BytesTemp;
  522. return g_Target->ReadPhysical(pBufSrc, pBufDest, count, Flags,
  523. TotalBytesRead != NULL ?
  524. TotalBytesRead : &BytesTemp) == S_OK;
  525. }
  526. BOOL
  527. ExtWritePhysicalMemoryWithFlags(
  528. ULONGLONG pBufDest,
  529. LPCVOID pBufSrc,
  530. ULONG count,
  531. ULONG Flags,
  532. PULONG TotalBytesWritten
  533. )
  534. {
  535. if (ARGUMENT_PRESENT(TotalBytesWritten))
  536. {
  537. *TotalBytesWritten = 0;
  538. }
  539. ULONG BytesTemp;
  540. return g_Target->WritePhysical(pBufDest, (PVOID)pBufSrc, count, Flags,
  541. TotalBytesWritten != NULL ?
  542. TotalBytesWritten : &BytesTemp) == S_OK;
  543. }
  544. DWORD
  545. ExtCallStack(
  546. DWORD64 FramePointer,
  547. DWORD64 StackPointer,
  548. DWORD64 ProgramCounter,
  549. PEXTSTACKTRACE64 ExtStackFrames,
  550. DWORD Frames
  551. )
  552. {
  553. PDEBUG_STACK_FRAME StackFrames;
  554. DWORD FrameCount;
  555. DWORD i;
  556. StackFrames = (PDEBUG_STACK_FRAME)
  557. malloc( sizeof(StackFrames[0]) * Frames );
  558. if (!StackFrames)
  559. {
  560. return 0;
  561. }
  562. ULONG PtrDef =
  563. (!ProgramCounter ? STACK_INSTR_DEFAULT : 0) |
  564. (!StackPointer ? STACK_STACK_DEFAULT : 0) |
  565. (!FramePointer ? STACK_FRAME_DEFAULT : 0);
  566. FrameCount = StackTrace( NULL,
  567. FramePointer, StackPointer, ProgramCounter,
  568. PtrDef, StackFrames, Frames,
  569. g_ExtThread, 0, FALSE );
  570. for (i = 0; i < FrameCount; i++)
  571. {
  572. ExtStackFrames[i].FramePointer = StackFrames[i].FrameOffset;
  573. ExtStackFrames[i].ProgramCounter = StackFrames[i].InstructionOffset;
  574. ExtStackFrames[i].ReturnAddress = StackFrames[i].ReturnOffset;
  575. ExtStackFrames[i].Args[0] = StackFrames[i].Params[0];
  576. ExtStackFrames[i].Args[1] = StackFrames[i].Params[1];
  577. ExtStackFrames[i].Args[2] = StackFrames[i].Params[2];
  578. ExtStackFrames[i].Args[3] = StackFrames[i].Params[3];
  579. }
  580. free( StackFrames );
  581. if (g_ExtThreadScopeSaved)
  582. {
  583. PopScope(&g_ExtThreadSavedScope);
  584. g_ExtThreadScopeSaved = FALSE;
  585. }
  586. g_ExtThread = 0;
  587. return FrameCount;
  588. }
  589. DWORD
  590. ExtCallStack32(
  591. DWORD FramePointer,
  592. DWORD StackPointer,
  593. DWORD ProgramCounter,
  594. PEXTSTACKTRACE32 ExtStackFrames,
  595. DWORD Frames
  596. )
  597. {
  598. PDEBUG_STACK_FRAME StackFrames;
  599. DWORD FrameCount;
  600. DWORD i;
  601. StackFrames = (PDEBUG_STACK_FRAME)
  602. malloc( sizeof(StackFrames[0]) * Frames );
  603. if (!StackFrames)
  604. {
  605. return 0;
  606. }
  607. ULONG PtrDef =
  608. (!ProgramCounter ? STACK_INSTR_DEFAULT : 0) |
  609. (!StackPointer ? STACK_STACK_DEFAULT : 0) |
  610. (!FramePointer ? STACK_FRAME_DEFAULT : 0);
  611. FrameCount = StackTrace(NULL,
  612. EXTEND64(FramePointer),
  613. EXTEND64(StackPointer),
  614. EXTEND64(ProgramCounter),
  615. PtrDef,
  616. StackFrames,
  617. Frames,
  618. g_ExtThread,
  619. 0,
  620. FALSE);
  621. for (i=0; i<FrameCount; i++)
  622. {
  623. ExtStackFrames[i].FramePointer = (ULONG)StackFrames[i].FrameOffset;
  624. ExtStackFrames[i].ProgramCounter = (ULONG)StackFrames[i].InstructionOffset;
  625. ExtStackFrames[i].ReturnAddress = (ULONG)StackFrames[i].ReturnOffset;
  626. ExtStackFrames[i].Args[0] = (ULONG)StackFrames[i].Params[0];
  627. ExtStackFrames[i].Args[1] = (ULONG)StackFrames[i].Params[1];
  628. ExtStackFrames[i].Args[2] = (ULONG)StackFrames[i].Params[2];
  629. ExtStackFrames[i].Args[3] = (ULONG)StackFrames[i].Params[3];
  630. }
  631. free( StackFrames );
  632. if (g_ExtThreadScopeSaved)
  633. {
  634. PopScope(&g_ExtThreadSavedScope);
  635. g_ExtThreadScopeSaved = FALSE;
  636. }
  637. g_ExtThread = 0;
  638. return FrameCount;
  639. }
  640. BOOL
  641. ExtIoctl(
  642. USHORT IoctlType,
  643. LPVOID lpvData,
  644. DWORD cbSize
  645. )
  646. {
  647. HRESULT Status;
  648. BOOL Bool;
  649. DWORD cb = 0;
  650. PPHYSICAL phy;
  651. PPHYSICAL_WITH_FLAGS phyf;
  652. PIOSPACE64 is;
  653. PIOSPACE_EX64 isex;
  654. PBUSDATA busdata;
  655. PREAD_WRITE_MSR msr;
  656. PREADCONTROLSPACE64 prc;
  657. PPROCESSORINFO pi;
  658. PSEARCHMEMORY psr;
  659. PSYM_DUMP_PARAM pSym;
  660. PGET_CURRENT_THREAD_ADDRESS pct;
  661. PGET_CURRENT_PROCESS_ADDRESS pcp;
  662. // Make sure output for long-running extensions appears regularly.
  663. TimedFlushCallbacks();
  664. if (!g_Target)
  665. {
  666. return FALSE;
  667. }
  668. switch( IoctlType )
  669. {
  670. case IG_KD_CONTEXT:
  671. if (!g_Target)
  672. {
  673. return FALSE;
  674. }
  675. pi = (PPROCESSORINFO) lpvData;
  676. pi->Processor = (USHORT)CURRENT_PROC;
  677. pi->NumberProcessors = (USHORT) g_Target->m_NumProcessors;
  678. return TRUE;
  679. case IG_READ_CONTROL_SPACE:
  680. // KSPECIAL_REGISTER content is kept in control space
  681. // so accessing control space may touch data that's
  682. // cached in the current machine KSPECIAL_REGISTERS.
  683. // Flush the current machine to maintain consistency.
  684. if (IS_CUR_MACHINE_ACCESSIBLE())
  685. {
  686. g_Target->FlushRegContext();
  687. }
  688. prc = (PREADCONTROLSPACE64)lpvData;
  689. Status = g_Target->ReadControl( prc->Processor,
  690. prc->Address,
  691. prc->Buf,
  692. prc->BufLen,
  693. &cb
  694. );
  695. prc->BufLen = cb;
  696. return Status == S_OK;
  697. case IG_WRITE_CONTROL_SPACE:
  698. // KSPECIAL_REGISTER content is kept in control space
  699. // so accessing control space may touch data that's
  700. // cached in the current machine KSPECIAL_REGISTERS.
  701. // Flush the current machine to maintain consistency.
  702. if (IS_CUR_MACHINE_ACCESSIBLE())
  703. {
  704. g_Target->FlushRegContext();
  705. }
  706. prc = (PREADCONTROLSPACE64)lpvData;
  707. Status = g_Target->WriteControl( prc->Processor,
  708. prc->Address,
  709. prc->Buf,
  710. prc->BufLen,
  711. &cb
  712. );
  713. prc->BufLen = cb;
  714. return Status == S_OK;
  715. case IG_READ_IO_SPACE:
  716. is = (PIOSPACE64)lpvData;
  717. Status = g_Target->ReadIo( Isa, 0, 1, is->Address, &is->Data,
  718. is->Length, &cb );
  719. return Status == S_OK;
  720. case IG_WRITE_IO_SPACE:
  721. is = (PIOSPACE64)lpvData;
  722. Status = g_Target->WriteIo( Isa, 0, 1, is->Address, &is->Data,
  723. is->Length, &cb );
  724. return Status == S_OK;
  725. case IG_READ_IO_SPACE_EX:
  726. isex = (PIOSPACE_EX64)lpvData;
  727. Status = g_Target->ReadIo( isex->InterfaceType,
  728. isex->BusNumber,
  729. isex->AddressSpace,
  730. isex->Address,
  731. &isex->Data,
  732. isex->Length,
  733. &cb
  734. );
  735. return Status == S_OK;
  736. case IG_WRITE_IO_SPACE_EX:
  737. isex = (PIOSPACE_EX64)lpvData;
  738. Status = g_Target->WriteIo( isex->InterfaceType,
  739. isex->BusNumber,
  740. isex->AddressSpace,
  741. isex->Address,
  742. &isex->Data,
  743. isex->Length,
  744. &cb
  745. );
  746. return Status == S_OK;
  747. case IG_READ_PHYSICAL:
  748. phy = (PPHYSICAL)lpvData;
  749. Bool =
  750. ExtReadPhysicalMemory( phy->Address, phy->Buf, phy->BufLen, &cb );
  751. phy->BufLen = cb;
  752. return Bool;
  753. case IG_WRITE_PHYSICAL:
  754. phy = (PPHYSICAL)lpvData;
  755. Bool =
  756. ExtWritePhysicalMemory( phy->Address, phy->Buf, phy->BufLen, &cb );
  757. phy->BufLen = cb;
  758. return Bool;
  759. case IG_READ_PHYSICAL_WITH_FLAGS:
  760. phyf = (PPHYSICAL_WITH_FLAGS)lpvData;
  761. Bool =
  762. ExtReadPhysicalMemoryWithFlags( phyf->Address, phyf->Buf,
  763. phyf->BufLen, phyf->Flags,
  764. &cb );
  765. phyf->BufLen = cb;
  766. return Bool;
  767. case IG_WRITE_PHYSICAL_WITH_FLAGS:
  768. phyf = (PPHYSICAL_WITH_FLAGS)lpvData;
  769. Bool =
  770. ExtWritePhysicalMemoryWithFlags( phyf->Address, phyf->Buf,
  771. phyf->BufLen, phyf->Flags,
  772. &cb );
  773. phyf->BufLen = cb;
  774. return Bool;
  775. case IG_LOWMEM_CHECK:
  776. Status = g_Target->CheckLowMemory();
  777. return Status == S_OK;
  778. case IG_SEARCH_MEMORY:
  779. psr = (PSEARCHMEMORY)lpvData;
  780. Status = g_Target->SearchVirtual(g_Process,
  781. psr->SearchAddress,
  782. psr->SearchLength,
  783. psr->Pattern,
  784. psr->PatternLength,
  785. 1,
  786. &psr->FoundAddress);
  787. return Status == S_OK;
  788. case IG_SET_THREAD:
  789. Bool = FALSE;
  790. if (IS_KERNEL_TARGET(g_Target))
  791. {
  792. // Turn off engine notifications since this setthread is temporary
  793. g_EngNotify++;
  794. PushScope(&g_ExtThreadSavedScope);
  795. g_ExtThread = *(PULONG64)lpvData;
  796. Bool = SetScopeContextFromThreadData(g_ExtThread, FALSE) == S_OK;
  797. g_ExtThreadScopeSaved = TRUE;
  798. g_EngNotify--;
  799. }
  800. return Bool;
  801. case IG_READ_MSR:
  802. msr = (PREAD_WRITE_MSR)lpvData;
  803. Status = g_Target->ReadMsr(msr->Msr, (PULONG64)&msr->Value);
  804. return Status == S_OK;
  805. case IG_WRITE_MSR:
  806. msr = (PREAD_WRITE_MSR)lpvData;
  807. Status = g_Target->WriteMsr(msr->Msr, msr->Value);
  808. return Status == S_OK;
  809. case IG_GET_KERNEL_VERSION:
  810. if (!g_Target)
  811. {
  812. return FALSE;
  813. }
  814. *((PDBGKD_GET_VERSION64)lpvData) = g_Target->m_KdVersion;
  815. return TRUE;
  816. case IG_GET_BUS_DATA:
  817. busdata = (PBUSDATA)lpvData;
  818. Status = g_Target->ReadBusData( busdata->BusDataType,
  819. busdata->BusNumber,
  820. busdata->SlotNumber,
  821. busdata->Offset,
  822. busdata->Buffer,
  823. busdata->Length,
  824. &cb
  825. );
  826. busdata->Length = cb;
  827. return Status == S_OK;
  828. case IG_SET_BUS_DATA:
  829. busdata = (PBUSDATA)lpvData;
  830. Status = g_Target->WriteBusData( busdata->BusDataType,
  831. busdata->BusNumber,
  832. busdata->SlotNumber,
  833. busdata->Offset,
  834. busdata->Buffer,
  835. busdata->Length,
  836. &cb
  837. );
  838. busdata->Length = cb;
  839. return Status == S_OK;
  840. case IG_GET_CURRENT_THREAD:
  841. if (!g_Target)
  842. {
  843. return FALSE;
  844. }
  845. pct = (PGET_CURRENT_THREAD_ADDRESS) lpvData;
  846. return g_Target->
  847. GetThreadInfoDataOffset(NULL,
  848. VIRTUAL_THREAD_HANDLE(pct->Processor),
  849. &pct->Address) == S_OK;
  850. case IG_GET_CURRENT_PROCESS:
  851. if (!g_Target)
  852. {
  853. return FALSE;
  854. }
  855. pcp = (PGET_CURRENT_PROCESS_ADDRESS) lpvData;
  856. return g_Target->
  857. GetProcessInfoDataOffset(NULL,
  858. pcp->Processor,
  859. pcp->CurrentThread,
  860. &pcp->Address) == S_OK;
  861. case IG_GET_DEBUGGER_DATA:
  862. if (!IS_KERNEL_TARGET(g_Target) ||
  863. !g_Target ||
  864. ((PDBGKD_DEBUG_DATA_HEADER64)lpvData)->OwnerTag != KDBG_TAG)
  865. {
  866. return FALSE;
  867. }
  868. // Don't refresh if asking for the kernel header.
  869. memcpy(lpvData, &g_Target->m_KdDebuggerData,
  870. min(sizeof(g_Target->m_KdDebuggerData), cbSize));
  871. return TRUE;
  872. case IG_RELOAD_SYMBOLS:
  873. PCSTR ArgsRet;
  874. return g_Target->Reload(g_Thread, (PCHAR)lpvData, &ArgsRet) == S_OK;
  875. case IG_GET_SET_SYMPATH:
  876. PGET_SET_SYMPATH pgs;
  877. pgs = (PGET_SET_SYMPATH)lpvData;
  878. ChangeSymPath((PCHAR)pgs->Args, FALSE, (PCHAR)pgs->Result,
  879. pgs->Length);
  880. return TRUE;
  881. case IG_IS_PTR64:
  882. if (!g_Target)
  883. {
  884. return FALSE;
  885. }
  886. *((PBOOL)lpvData) = g_Target->m_Machine->m_Ptr64;
  887. return TRUE;
  888. case IG_DUMP_SYMBOL_INFO:
  889. if (!g_Process)
  890. {
  891. return FALSE;
  892. }
  893. pSym = (PSYM_DUMP_PARAM) lpvData;
  894. SymbolTypeDump(g_Process->m_SymHandle,
  895. g_Process->m_ImageHead,
  896. pSym, (PULONG)&Status);
  897. return (BOOL)(ULONG)Status;
  898. case IG_GET_TYPE_SIZE:
  899. if (!g_Process)
  900. {
  901. return FALSE;
  902. }
  903. pSym = (PSYM_DUMP_PARAM) lpvData;
  904. return SymbolTypeDump(g_Process->m_SymHandle,
  905. g_Process->m_ImageHead,
  906. pSym, (PULONG)&Status);
  907. case IG_GET_TEB_ADDRESS:
  908. if (!g_Target)
  909. {
  910. return FALSE;
  911. }
  912. PGET_TEB_ADDRESS pTeb;
  913. pTeb = (PGET_TEB_ADDRESS) lpvData;
  914. return g_Target->
  915. GetThreadInfoTeb(g_Thread,
  916. CURRENT_PROC,
  917. 0,
  918. &pTeb->Address) == S_OK;
  919. case IG_GET_PEB_ADDRESS:
  920. if (!g_Target)
  921. {
  922. return FALSE;
  923. }
  924. PGET_PEB_ADDRESS pPeb;
  925. pPeb = (PGET_PEB_ADDRESS) lpvData;
  926. return g_Target->
  927. GetProcessInfoPeb(g_Thread,
  928. CURRENT_PROC,
  929. pPeb->CurrentThread,
  930. &pPeb->Address) == S_OK;
  931. case IG_GET_CURRENT_PROCESS_HANDLE:
  932. if (!g_Process)
  933. {
  934. return FALSE;
  935. }
  936. *(PHANDLE)lpvData = OS_HANDLE(g_Process->m_SysHandle);
  937. return TRUE;
  938. case IG_GET_INPUT_LINE:
  939. PGET_INPUT_LINE Gil;
  940. Gil = (PGET_INPUT_LINE)lpvData;
  941. Gil->InputSize = GetInput(Gil->Prompt, Gil->Buffer, Gil->BufferSize,
  942. GETIN_LOG_INPUT_LINE);
  943. return TRUE;
  944. case IG_GET_EXPRESSION_EX:
  945. PGET_EXPRESSION_EX Gee;
  946. Gee = (PGET_EXPRESSION_EX)lpvData;
  947. Gee->Value = ExtGetExpression(Gee->Expression);
  948. Gee->Remainder = Gee->Expression + g_ExtGetExpressionRemainderIndex;
  949. return g_ExtGetExpressionSuccess;
  950. case IG_TRANSLATE_VIRTUAL_TO_PHYSICAL:
  951. if (!IS_CUR_MACHINE_ACCESSIBLE())
  952. {
  953. return FALSE;
  954. }
  955. PTRANSLATE_VIRTUAL_TO_PHYSICAL Tvtp;
  956. Tvtp = (PTRANSLATE_VIRTUAL_TO_PHYSICAL)lpvData;
  957. ULONG Levels, PfIndex;
  958. return g_Machine->
  959. GetVirtualTranslationPhysicalOffsets(g_Thread,
  960. Tvtp->Virtual, NULL, 0,
  961. &Levels, &PfIndex,
  962. &Tvtp->Physical) == S_OK;
  963. case IG_GET_CACHE_SIZE:
  964. if (!g_Process)
  965. {
  966. return FALSE;
  967. }
  968. PULONG64 pCacheSize;
  969. pCacheSize = (PULONG64)lpvData;
  970. if (IS_KERNEL_TARGET(g_Target))
  971. {
  972. *pCacheSize = g_Process->m_VirtualCache.m_MaxSize;
  973. return TRUE;
  974. }
  975. return FALSE;
  976. case IG_POINTER_SEARCH_PHYSICAL:
  977. if (!IS_CUR_MACHINE_ACCESSIBLE())
  978. {
  979. return FALSE;
  980. }
  981. PPOINTER_SEARCH_PHYSICAL Psp;
  982. Psp = (PPOINTER_SEARCH_PHYSICAL)lpvData;
  983. return g_Target->PointerSearchPhysical(Psp->Offset,
  984. Psp->Length,
  985. Psp->PointerMin,
  986. Psp->PointerMax,
  987. Psp->Flags,
  988. Psp->MatchOffsets,
  989. Psp->MatchOffsetsSize,
  990. &Psp->MatchOffsetsCount) ==
  991. S_OK;
  992. case IG_GET_COR_DATA_ACCESS:
  993. if (cbSize != sizeof(void*) ||
  994. !g_Process ||
  995. g_Process->LoadCorDebugDll() != S_OK)
  996. {
  997. return FALSE;
  998. }
  999. *(ICorDataAccess**)lpvData = g_Process->m_CorAccess;
  1000. return TRUE;
  1001. default:
  1002. ErrOut( "\n*** Bad IOCTL request from an extension [%d]\n\n",
  1003. IoctlType );
  1004. return FALSE;
  1005. }
  1006. // NOTREACHED.
  1007. DBG_ASSERT(FALSE);
  1008. return FALSE;
  1009. }
  1010. BOOL
  1011. ExtIoctl32(
  1012. USHORT IoctlType,
  1013. LPVOID lpvData,
  1014. DWORD cbSize
  1015. )
  1016. /*++
  1017. Routine Description:
  1018. This is the extension Ioctl routine for backward compatibility with
  1019. old extension dlls. This routine is frozen, and new ioctl support
  1020. should not be added to it.
  1021. Arguments:
  1022. Return Value:
  1023. --*/
  1024. {
  1025. HRESULT Status;
  1026. DWORD cb = 0;
  1027. PIOSPACE32 is;
  1028. PIOSPACE_EX32 isex;
  1029. PREADCONTROLSPACE prc;
  1030. PDBGKD_GET_VERSION32 pv32;
  1031. PKDDEBUGGER_DATA32 pdbg32;
  1032. // Make sure output for long-running extensions appears regularly.
  1033. TimedFlushCallbacks();
  1034. switch( IoctlType )
  1035. {
  1036. case IG_READ_CONTROL_SPACE:
  1037. // KSPECIAL_REGISTER content is kept in control space
  1038. // so accessing control space may touch data that's
  1039. // cached in the current machine KSPECIAL_REGISTERS.
  1040. // Flush the current machine to maintain consistency.
  1041. if (IS_CUR_MACHINE_ACCESSIBLE())
  1042. {
  1043. g_Target->FlushRegContext();
  1044. }
  1045. prc = (PREADCONTROLSPACE)lpvData;
  1046. Status = g_Target->ReadControl( prc->Processor,
  1047. prc->Address,
  1048. prc->Buf,
  1049. prc->BufLen,
  1050. &cb
  1051. );
  1052. prc->BufLen = cb;
  1053. return Status == S_OK;
  1054. case IG_WRITE_CONTROL_SPACE:
  1055. // KSPECIAL_REGISTER content is kept in control space
  1056. // so accessing control space may touch data that's
  1057. // cached in the current machine KSPECIAL_REGISTERS.
  1058. // Flush the current machine to maintain consistency.
  1059. if (IS_CUR_MACHINE_ACCESSIBLE())
  1060. {
  1061. g_Target->FlushRegContext();
  1062. }
  1063. prc = (PREADCONTROLSPACE)lpvData;
  1064. Status = g_Target->WriteControl( prc->Processor,
  1065. prc->Address,
  1066. prc->Buf,
  1067. prc->BufLen,
  1068. &cb
  1069. );
  1070. prc->BufLen = cb;
  1071. return Status == S_OK;
  1072. case IG_READ_IO_SPACE:
  1073. is = (PIOSPACE32)lpvData;
  1074. Status = g_Target->ReadIo( Isa, 0, 1, is->Address, &is->Data,
  1075. is->Length, &cb );
  1076. return Status == S_OK;
  1077. case IG_WRITE_IO_SPACE:
  1078. is = (PIOSPACE32)lpvData;
  1079. Status = g_Target->WriteIo( Isa, 0, 1, is->Address, &is->Data,
  1080. is->Length, &cb );
  1081. return Status == S_OK;
  1082. case IG_READ_IO_SPACE_EX:
  1083. isex = (PIOSPACE_EX32)lpvData;
  1084. Status = g_Target->ReadIo( isex->InterfaceType,
  1085. isex->BusNumber,
  1086. isex->AddressSpace,
  1087. isex->Address,
  1088. &isex->Data,
  1089. isex->Length,
  1090. &cb
  1091. );
  1092. return Status == S_OK;
  1093. case IG_WRITE_IO_SPACE_EX:
  1094. isex = (PIOSPACE_EX32)lpvData;
  1095. Status = g_Target->WriteIo( isex->InterfaceType,
  1096. isex->BusNumber,
  1097. isex->AddressSpace,
  1098. isex->Address,
  1099. &isex->Data,
  1100. isex->Length,
  1101. &cb
  1102. );
  1103. return Status == S_OK;
  1104. case IG_SET_THREAD:
  1105. if (IS_KERNEL_TARGET(g_Target))
  1106. {
  1107. g_EngNotify++; // Turn off engine notifications since this setthread is temporary
  1108. g_ExtThread = EXTEND64(*(PULONG)lpvData);
  1109. PushScope(&g_ExtThreadSavedScope);
  1110. SetScopeContextFromThreadData(g_ExtThread, FALSE);
  1111. g_ExtThreadScopeSaved = TRUE;
  1112. g_EngNotify--;
  1113. return TRUE;
  1114. }
  1115. else
  1116. {
  1117. return FALSE;
  1118. }
  1119. case IG_GET_KERNEL_VERSION:
  1120. if (!g_Target)
  1121. {
  1122. return FALSE;
  1123. }
  1124. //
  1125. // Convert to 32 bit
  1126. //
  1127. pv32 = (PDBGKD_GET_VERSION32)lpvData;
  1128. pv32->MajorVersion = g_Target->m_KdVersion.MajorVersion;
  1129. pv32->MinorVersion = g_Target->m_KdVersion.MinorVersion;
  1130. pv32->ProtocolVersion = g_Target->m_KdVersion.ProtocolVersion;
  1131. pv32->Flags = g_Target->m_KdVersion.Flags;
  1132. pv32->KernBase =
  1133. (ULONG)g_Target->m_KdVersion.KernBase;
  1134. pv32->PsLoadedModuleList =
  1135. (ULONG)g_Target->m_KdVersion.PsLoadedModuleList;
  1136. pv32->MachineType =
  1137. g_Target->m_KdVersion.MachineType;
  1138. pv32->DebuggerDataList =
  1139. (ULONG)g_Target->m_KdVersion.DebuggerDataList;
  1140. pv32->ThCallbackStack = g_Target->m_KdDebuggerData.ThCallbackStack;
  1141. pv32->NextCallback = g_Target->m_KdDebuggerData.NextCallback;
  1142. pv32->FramePointer = g_Target->m_KdDebuggerData.FramePointer;
  1143. pv32->KiCallUserMode =
  1144. (ULONG)g_Target->m_KdDebuggerData.KiCallUserMode;
  1145. pv32->KeUserCallbackDispatcher =
  1146. (ULONG)g_Target->m_KdDebuggerData.KeUserCallbackDispatcher;
  1147. pv32->BreakpointWithStatus =
  1148. (ULONG)g_Target->m_KdDebuggerData.BreakpointWithStatus;
  1149. return TRUE;
  1150. case IG_GET_DEBUGGER_DATA:
  1151. if (!IS_KERNEL_TARGET(g_Target) ||
  1152. !g_Target ||
  1153. ((PDBGKD_DEBUG_DATA_HEADER32)lpvData)->OwnerTag != KDBG_TAG)
  1154. {
  1155. return FALSE;
  1156. }
  1157. // Don't refresh if asking for the kernel header.
  1158. pdbg32 = (PKDDEBUGGER_DATA32)lpvData;
  1159. pdbg32->Header.List.Flink =
  1160. (ULONG)g_Target->m_KdDebuggerData.Header.List.Flink;
  1161. pdbg32->Header.List.Blink =
  1162. (ULONG)g_Target->m_KdDebuggerData.Header.List.Blink;
  1163. pdbg32->Header.OwnerTag = KDBG_TAG;
  1164. pdbg32->Header.Size = sizeof(KDDEBUGGER_DATA32);
  1165. #undef UIP
  1166. #undef CP
  1167. #define UIP(f) pdbg32->f = (ULONG)(g_Target->m_KdDebuggerData.f)
  1168. #define CP(f) pdbg32->f = (g_Target->m_KdDebuggerData.f)
  1169. UIP(KernBase);
  1170. UIP(BreakpointWithStatus);
  1171. UIP(SavedContext);
  1172. CP(ThCallbackStack);
  1173. CP(NextCallback);
  1174. CP(FramePointer);
  1175. CP(PaeEnabled);
  1176. UIP(KiCallUserMode);
  1177. UIP(KeUserCallbackDispatcher);
  1178. UIP(PsLoadedModuleList);
  1179. UIP(PsActiveProcessHead);
  1180. UIP(PspCidTable);
  1181. UIP(ExpSystemResourcesList);
  1182. UIP(ExpPagedPoolDescriptor);
  1183. UIP(ExpNumberOfPagedPools);
  1184. UIP(KeTimeIncrement);
  1185. UIP(KeBugCheckCallbackListHead);
  1186. UIP(KiBugcheckData);
  1187. UIP(IopErrorLogListHead);
  1188. UIP(ObpRootDirectoryObject);
  1189. UIP(ObpTypeObjectType);
  1190. UIP(MmSystemCacheStart);
  1191. UIP(MmSystemCacheEnd);
  1192. UIP(MmSystemCacheWs);
  1193. UIP(MmPfnDatabase);
  1194. UIP(MmSystemPtesStart);
  1195. UIP(MmSystemPtesEnd);
  1196. UIP(MmSubsectionBase);
  1197. UIP(MmNumberOfPagingFiles);
  1198. UIP(MmLowestPhysicalPage);
  1199. UIP(MmHighestPhysicalPage);
  1200. UIP(MmNumberOfPhysicalPages);
  1201. UIP(MmMaximumNonPagedPoolInBytes);
  1202. UIP(MmNonPagedSystemStart);
  1203. UIP(MmNonPagedPoolStart);
  1204. UIP(MmNonPagedPoolEnd);
  1205. UIP(MmPagedPoolStart);
  1206. UIP(MmPagedPoolEnd);
  1207. UIP(MmPagedPoolInformation);
  1208. UIP(MmPageSize);
  1209. UIP(MmSizeOfPagedPoolInBytes);
  1210. UIP(MmTotalCommitLimit);
  1211. UIP(MmTotalCommittedPages);
  1212. UIP(MmSharedCommit);
  1213. UIP(MmDriverCommit);
  1214. UIP(MmProcessCommit);
  1215. UIP(MmPagedPoolCommit);
  1216. UIP(MmExtendedCommit);
  1217. UIP(MmZeroedPageListHead);
  1218. UIP(MmFreePageListHead);
  1219. UIP(MmStandbyPageListHead);
  1220. UIP(MmModifiedPageListHead);
  1221. UIP(MmModifiedNoWritePageListHead);
  1222. UIP(MmAvailablePages);
  1223. UIP(MmResidentAvailablePages);
  1224. UIP(PoolTrackTable);
  1225. UIP(NonPagedPoolDescriptor);
  1226. UIP(MmHighestUserAddress);
  1227. UIP(MmSystemRangeStart);
  1228. UIP(MmUserProbeAddress);
  1229. UIP(KdPrintCircularBuffer);
  1230. UIP(KdPrintCircularBufferEnd);
  1231. UIP(KdPrintWritePointer);
  1232. UIP(KdPrintRolloverCount);
  1233. UIP(MmLoadedUserImageList);
  1234. //
  1235. // DO NOT ADD ANY FIELDS HERE
  1236. // The 32 bit structure should not be changed
  1237. //
  1238. return TRUE;
  1239. case IG_KD_CONTEXT:
  1240. case IG_READ_PHYSICAL:
  1241. case IG_WRITE_PHYSICAL:
  1242. case IG_READ_PHYSICAL_WITH_FLAGS:
  1243. case IG_WRITE_PHYSICAL_WITH_FLAGS:
  1244. case IG_LOWMEM_CHECK:
  1245. case IG_SEARCH_MEMORY:
  1246. case IG_READ_MSR:
  1247. case IG_WRITE_MSR:
  1248. case IG_GET_BUS_DATA:
  1249. case IG_SET_BUS_DATA:
  1250. case IG_GET_CURRENT_THREAD:
  1251. case IG_GET_CURRENT_PROCESS:
  1252. case IG_RELOAD_SYMBOLS:
  1253. case IG_GET_SET_SYMPATH:
  1254. case IG_IS_PTR64:
  1255. case IG_DUMP_SYMBOL_INFO:
  1256. case IG_GET_TYPE_SIZE:
  1257. case IG_GET_TEB_ADDRESS:
  1258. case IG_GET_PEB_ADDRESS:
  1259. case IG_GET_INPUT_LINE:
  1260. case IG_GET_EXPRESSION_EX:
  1261. case IG_TRANSLATE_VIRTUAL_TO_PHYSICAL:
  1262. case IG_POINTER_SEARCH_PHYSICAL:
  1263. case IG_GET_COR_DATA_ACCESS:
  1264. // All of these ioctls are handled identically for
  1265. // 32 and 64 bits. Avoid duplicating all the code.
  1266. return ExtIoctl(IoctlType, lpvData, cbSize);
  1267. default:
  1268. ErrOut( "\n*** Bad IOCTL32 request from an extension [%d]\n\n",
  1269. IoctlType );
  1270. return FALSE;
  1271. }
  1272. // NOTREACHED.
  1273. DBG_ASSERT(FALSE);
  1274. return FALSE;
  1275. }
  1276. //----------------------------------------------------------------------------
  1277. //
  1278. // Extension management.
  1279. //
  1280. //----------------------------------------------------------------------------
  1281. DebugClient*
  1282. FindExtClient(void)
  1283. {
  1284. DebugClient* Client;
  1285. //
  1286. // Try to find the most appropriate client for
  1287. // executing an extension command on. The first
  1288. // choice is the session client, then any local
  1289. // primary client, then any primary client.
  1290. //
  1291. if (!(Client = FindClient(g_SessionThread, CLIENT_PRIMARY, 0)) &&
  1292. !(Client = FindClient(0, CLIENT_PRIMARY, CLIENT_REMOTE)) &&
  1293. !(Client = FindClient(0, CLIENT_PRIMARY, 0)))
  1294. {
  1295. Client = g_Clients;
  1296. }
  1297. return Client;
  1298. }
  1299. LONG
  1300. ExtensionExceptionFilter(struct _EXCEPTION_POINTERS *ExceptionInfo,
  1301. PCSTR Module,
  1302. PCSTR Func)
  1303. {
  1304. // Any references to objects will be leaked.
  1305. // There's not much the engine can do about this, although
  1306. // it would be possible to record old refcounts and
  1307. // try to restore them.
  1308. if (Module != NULL && Func != NULL)
  1309. {
  1310. ErrOut("%08x Exception in %s.%s debugger extension.\n",
  1311. ExceptionInfo->ExceptionRecord->ExceptionCode,
  1312. Module,
  1313. Func
  1314. );
  1315. }
  1316. else
  1317. {
  1318. ErrOut("%08x Exception in debugger client %s callback.\n",
  1319. ExceptionInfo->ExceptionRecord->ExceptionCode,
  1320. Func
  1321. );
  1322. }
  1323. ErrOut(" PC: %s VA: %s R/W: %x Parameter: %s\n",
  1324. FormatAddr64((ULONG_PTR)ExceptionInfo->ExceptionRecord->ExceptionAddress),
  1325. FormatAddr64(ExceptionInfo->ExceptionRecord->ExceptionInformation[1]),
  1326. ExceptionInfo->ExceptionRecord->ExceptionInformation[0],
  1327. FormatAddr64(ExceptionInfo->ExceptionRecord->ExceptionInformation[2])
  1328. );
  1329. return EXCEPTION_EXECUTE_HANDLER;
  1330. }
  1331. BOOL
  1332. CallExtension(DebugClient* Client,
  1333. EXTDLL *Ext,
  1334. PSTR Func,
  1335. PCSTR Args,
  1336. HRESULT* ExtStatus)
  1337. {
  1338. FARPROC Routine;
  1339. ADDR TempAddr;
  1340. if (IS_KERNEL_TARGET(g_Target))
  1341. {
  1342. _strlwr(Func);
  1343. }
  1344. Routine = GetProcAddress(Ext->Dll, Func);
  1345. if (Routine == NULL)
  1346. {
  1347. return FALSE;
  1348. }
  1349. if (!(g_EnvDbgOptions & OPTION_NOVERSIONCHECK) && Ext->CheckVersionRoutine)
  1350. {
  1351. Ext->CheckVersionRoutine();
  1352. }
  1353. if (IS_KERNEL_TARGET(g_Target) && !strcmp(Func, "version"))
  1354. {
  1355. //
  1356. // This is a bit of a hack to avoid a problem with the
  1357. // extension version checking. Extension version checking
  1358. // comes before the KD connection is established so there's
  1359. // no register context. If the version checking fails it
  1360. // prints out version information, which tries to call
  1361. // version extensions, which will get here when there's
  1362. // no register context.
  1363. //
  1364. // To work around this, just pass zero to the version extension
  1365. // function since it presumably doesn't care about the
  1366. // address.
  1367. //
  1368. ADDRFLAT(&TempAddr, 0);
  1369. }
  1370. else if (IS_CONTEXT_POSSIBLE(g_Target))
  1371. {
  1372. g_Machine->GetPC(&TempAddr);
  1373. }
  1374. else
  1375. {
  1376. if (!IS_LOCAL_KERNEL_TARGET(g_Target))
  1377. {
  1378. WarnOut("Extension called without current PC\n");
  1379. }
  1380. ADDRFLAT(&TempAddr, 0);
  1381. }
  1382. *ExtStatus = S_OK;
  1383. __try
  1384. {
  1385. HANDLE ProcHandle, ThreadHandle;
  1386. if (g_Process)
  1387. {
  1388. ProcHandle = OS_HANDLE(g_Process->m_SysHandle);
  1389. }
  1390. else
  1391. {
  1392. ProcHandle = NULL;
  1393. }
  1394. if (g_Thread)
  1395. {
  1396. ThreadHandle = OS_HANDLE(g_Thread->m_Handle);
  1397. }
  1398. else
  1399. {
  1400. ThreadHandle = NULL;
  1401. }
  1402. switch(Ext->ExtensionType)
  1403. {
  1404. case NTSD_EXTENSION_TYPE:
  1405. //
  1406. // NOTE:
  1407. // Eventhough this type should receive an NTSD_EXTENSION_API
  1408. // structure, ntsdexts.dll (and possibly others) depend on
  1409. // receiving the WinDBG version of the extensions, because they
  1410. // check the size of the structure, and actually use some of the
  1411. // newer exports. This works because the WinDBG extension API was
  1412. // a superset of the NTSD version.
  1413. //
  1414. ((PNTSD_EXTENSION_ROUTINE)Routine)
  1415. (ProcHandle,
  1416. ThreadHandle,
  1417. (ULONG)Flat(TempAddr),
  1418. g_Target->m_Machine->m_Ptr64 ?
  1419. (PNTSD_EXTENSION_APIS)&g_WindbgExtensions64 :
  1420. (PNTSD_EXTENSION_APIS)&g_WindbgExtensions32,
  1421. (PSTR)Args
  1422. );
  1423. break;
  1424. case DEBUG_EXTENSION_TYPE:
  1425. if (Client == NULL)
  1426. {
  1427. Client = FindExtClient();
  1428. }
  1429. if (Client == NULL)
  1430. {
  1431. ErrOut("Unable to call client-style extension "
  1432. "without a client\n");
  1433. }
  1434. else
  1435. {
  1436. *ExtStatus = ((PDEBUG_EXTENSION_CALL)Routine)
  1437. ((PDEBUG_CLIENT)(IDebugClientN *)Client, Args);
  1438. }
  1439. break;
  1440. case WINDBG_EXTENSION_TYPE:
  1441. //
  1442. // Support Windbg type extensions for ntsd too
  1443. //
  1444. if (Ext->ApiVersion.Revision < 6 )
  1445. {
  1446. ((PWINDBG_EXTENSION_ROUTINE32)Routine) (
  1447. ProcHandle,
  1448. ThreadHandle,
  1449. (ULONG)Flat(TempAddr),
  1450. CURRENT_PROC,
  1451. Args
  1452. );
  1453. }
  1454. else
  1455. {
  1456. ((PWINDBG_EXTENSION_ROUTINE64)Routine) (
  1457. ProcHandle,
  1458. ThreadHandle,
  1459. Flat(TempAddr),
  1460. CURRENT_PROC,
  1461. Args
  1462. );
  1463. }
  1464. break;
  1465. case WINDBG_OLDKD_EXTENSION_TYPE:
  1466. ((PWINDBG_OLDKD_EXTENSION_ROUTINE)Routine) (
  1467. (ULONG)Flat(TempAddr),
  1468. &g_KdExtensions,
  1469. Args
  1470. );
  1471. break;
  1472. }
  1473. }
  1474. __except(ExtensionExceptionFilter(GetExceptionInformation(),
  1475. Ext->Name, Func))
  1476. {
  1477. ;
  1478. }
  1479. return TRUE;
  1480. }
  1481. void
  1482. LinkExtensionDll(EXTDLL* Ext)
  1483. {
  1484. // Put user-loaded DLLs before default DLLs.
  1485. if (Ext->UserLoaded)
  1486. {
  1487. Ext->Next = g_ExtDlls;
  1488. g_ExtDlls = Ext;
  1489. }
  1490. else
  1491. {
  1492. EXTDLL* Prev;
  1493. EXTDLL* Cur;
  1494. Prev = NULL;
  1495. for (Cur = g_ExtDlls; Cur != NULL; Cur = Cur->Next)
  1496. {
  1497. if (!Cur->UserLoaded)
  1498. {
  1499. break;
  1500. }
  1501. Prev = Cur;
  1502. }
  1503. Ext->Next = Cur;
  1504. if (Prev == NULL)
  1505. {
  1506. g_ExtDlls = Ext;
  1507. }
  1508. else
  1509. {
  1510. Prev->Next = Ext;
  1511. }
  1512. }
  1513. }
  1514. EXTDLL *
  1515. AddExtensionDll(char *Name, BOOL UserLoaded, TargetInfo* Target,
  1516. char **End)
  1517. {
  1518. EXTDLL *Ext;
  1519. ULONG Len;
  1520. char *Last;
  1521. while (*Name == ' ' || *Name == '\t')
  1522. {
  1523. Name++;
  1524. }
  1525. if (*Name == 0)
  1526. {
  1527. ErrOut("No extension DLL name provided\n");
  1528. return NULL;
  1529. }
  1530. Len = strlen(Name);
  1531. if (End != NULL)
  1532. {
  1533. *End = Name + Len;
  1534. }
  1535. Last = Name + (Len - 1);
  1536. while (Last >= Name && (*Last == ' ' || *Last == '\t'))
  1537. {
  1538. Last--;
  1539. }
  1540. Len = (ULONG)((Last + 1) - Name);
  1541. // See if it's already in the list.
  1542. for (Ext = g_ExtDlls; Ext != NULL; Ext = Ext->Next)
  1543. {
  1544. if ((!Target || Target == Ext->Target) &&
  1545. strlen(Ext->Name) == Len &&
  1546. !_memicmp(Name, Ext->Name, Len))
  1547. {
  1548. return Ext;
  1549. }
  1550. }
  1551. Ext = (EXTDLL *)malloc(sizeof(EXTDLL) + Len);
  1552. if (Ext == NULL)
  1553. {
  1554. ErrOut("Unable to allocate memory for extension DLL\n");
  1555. return NULL;
  1556. }
  1557. ZeroMemory(Ext, sizeof(EXTDLL) + Len);
  1558. memcpy(Ext->Name, Name, Len + 1);
  1559. Ext->UserLoaded = UserLoaded;
  1560. Ext->Target = Target;
  1561. LinkExtensionDll(Ext);
  1562. NotifyChangeEngineState(DEBUG_CES_EXTENSIONS, 0, TRUE);
  1563. return Ext;
  1564. }
  1565. PCTSTR
  1566. BuildExtensionSearchPath(TargetInfo* Target)
  1567. {
  1568. DWORD Size;
  1569. DWORD TotalSize;
  1570. CHAR ExeDir[MAX_PATH];
  1571. int ExeRootLen;
  1572. PSTR OsDirPath;
  1573. CHAR OsDirTail[32];
  1574. BOOL PriPaths = FALSE;
  1575. BOOL WinPaths = FALSE;
  1576. PSTR NewPath;
  1577. //
  1578. // If we are not connected, don't build a path, since we have to pick
  1579. // up extensions based on the OS version.
  1580. //
  1581. if (Target && Target->m_ActualSystemVersion == SVER_INVALID)
  1582. {
  1583. return NULL;
  1584. }
  1585. //
  1586. // If we already have a search path, do not rebuild it.
  1587. //
  1588. if (Target)
  1589. {
  1590. if (Target->m_ExtensionSearchPath)
  1591. {
  1592. return Target->m_ExtensionSearchPath;
  1593. }
  1594. }
  1595. else
  1596. {
  1597. if (g_BaseExtensionSearchPath)
  1598. {
  1599. return g_BaseExtensionSearchPath;
  1600. }
  1601. }
  1602. // Get the directory the debugger executable is in.
  1603. // -8 because we assume we're adding \w2kfre to the path.
  1604. if (!GetEngineDirectory(ExeDir, MAX_PATH - 8))
  1605. {
  1606. // Error. Using the current directory.
  1607. ExeRootLen = 1;
  1608. }
  1609. else
  1610. {
  1611. if (ExeDir[0] == '\\' && ExeDir[1] == '\\')
  1612. {
  1613. PSTR ExeRootEnd;
  1614. // UNC path root.
  1615. ExeRootEnd = strchr(ExeDir + 2, '\\');
  1616. if (ExeRootEnd != NULL)
  1617. {
  1618. ExeRootEnd = strchr(ExeRootEnd + 1, '\\');
  1619. }
  1620. if (ExeRootEnd == NULL)
  1621. {
  1622. ExeRootLen = strlen(ExeDir);
  1623. }
  1624. else
  1625. {
  1626. ExeRootLen = (int)(ExeRootEnd - ExeDir);
  1627. }
  1628. }
  1629. else
  1630. {
  1631. // Drive letter and colon root.
  1632. ExeRootLen = 2;
  1633. }
  1634. }
  1635. //
  1636. // Calc how much space we will need to use.
  1637. //
  1638. // Leave extra room for the current directory, path, and directory of
  1639. // where debugger extensions are located.
  1640. //
  1641. TotalSize = GetEnvironmentVariable("PATH", NULL, 0) +
  1642. GetEnvironmentVariable("_NT_DEBUGGER_EXTENSION_PATH",
  1643. NULL, 0) + MAX_PATH * 4;
  1644. NewPath = (LPTSTR)calloc(TotalSize, sizeof(TCHAR));
  1645. if (!NewPath)
  1646. {
  1647. return NULL;
  1648. }
  1649. *NewPath = 0;
  1650. //
  1651. // 1 - User specified search path
  1652. //
  1653. if (GetEnvironmentVariable("_NT_DEBUGGER_EXTENSION_PATH",
  1654. NewPath, TotalSize - 2))
  1655. {
  1656. CatString(NewPath, ";", TotalSize);
  1657. }
  1658. // Generate default path for the exe dir
  1659. // Skip root as it is already taken from ExeDir.
  1660. OsDirPath = ExeDir + ExeRootLen;
  1661. if (*OsDirPath == '\\')
  1662. {
  1663. OsDirPath++;
  1664. }
  1665. //
  1666. // Figure out whether we need NT6, or NT5/NT4 free or checked extensions
  1667. //
  1668. if (!Target)
  1669. {
  1670. OsDirPath = "";
  1671. OsDirTail[0] = 0;
  1672. }
  1673. else if (Target->m_ActualSystemVersion > BIG_SVER_START &&
  1674. Target->m_ActualSystemVersion < BIG_SVER_END)
  1675. {
  1676. OsDirPath = "DbgExt";
  1677. strcpy(OsDirTail, "BIG");
  1678. }
  1679. else if (Target->m_ActualSystemVersion > XBOX_SVER_START &&
  1680. Target->m_ActualSystemVersion < XBOX_SVER_END)
  1681. {
  1682. OsDirPath = "DbgExt";
  1683. strcpy(OsDirTail, "XBox");
  1684. }
  1685. else if (Target->m_ActualSystemVersion > NTBD_SVER_START &&
  1686. Target->m_ActualSystemVersion < NTBD_SVER_END)
  1687. {
  1688. OsDirPath = "DbgExt";
  1689. strcpy(OsDirTail, "NtBd");
  1690. }
  1691. else if (Target->m_ActualSystemVersion > EFI_SVER_START &&
  1692. Target->m_ActualSystemVersion < EFI_SVER_END)
  1693. {
  1694. OsDirPath = "DbgExt";
  1695. strcpy(OsDirTail, "EFI");
  1696. }
  1697. else if (Target->m_ActualSystemVersion > W9X_SVER_START &&
  1698. Target->m_ActualSystemVersion < W9X_SVER_END)
  1699. {
  1700. strcpy(OsDirTail, "Win9X");
  1701. WinPaths = TRUE;
  1702. }
  1703. else if (Target->m_ActualSystemVersion > WCE_SVER_START &&
  1704. Target->m_ActualSystemVersion < WCE_SVER_END)
  1705. {
  1706. strcpy(OsDirTail, "WinCE");
  1707. WinPaths = TRUE;
  1708. }
  1709. else
  1710. {
  1711. // Treat everything else as an NT system. Use
  1712. // the translated system version now rather than
  1713. // the actual system version.
  1714. PriPaths = TRUE;
  1715. WinPaths = TRUE;
  1716. if (Target->m_SystemVersion > NT_SVER_W2K)
  1717. {
  1718. strcpy(OsDirTail, "WINXP");
  1719. }
  1720. else
  1721. {
  1722. if (Target->m_SystemVersion <= NT_SVER_NT4)
  1723. {
  1724. strcpy(OsDirTail, "NT4");
  1725. }
  1726. else
  1727. {
  1728. strcpy(OsDirTail, "W2K");
  1729. }
  1730. if (0xC == Target->m_CheckedBuild)
  1731. {
  1732. strcat(OsDirTail, "Chk");
  1733. }
  1734. else
  1735. {
  1736. strcat(OsDirTail, "Fre");
  1737. }
  1738. }
  1739. }
  1740. //
  1741. // 2 - OS specific subdirectories from where we launched the debugger.
  1742. // 3 - pri subdirectory from where we launched the debugger.
  1743. // 4 - Directory from where we launched the debugger.
  1744. //
  1745. PSTR End;
  1746. Size = strlen(NewPath);
  1747. End = NewPath + Size;
  1748. memcpy(End, ExeDir, ExeRootLen);
  1749. End += ExeRootLen;
  1750. TotalSize -= Size + ExeRootLen;
  1751. if (*OsDirPath)
  1752. {
  1753. if (TotalSize)
  1754. {
  1755. *End++ = '\\';
  1756. TotalSize--;
  1757. }
  1758. CopyString(End, OsDirPath, TotalSize);
  1759. Size = strlen(End);
  1760. End += Size;
  1761. TotalSize -= Size;
  1762. }
  1763. if (WinPaths)
  1764. {
  1765. PrintString(End, TotalSize, "\\winext;%s", ExeDir);
  1766. Size = strlen(End);
  1767. End += Size;
  1768. TotalSize -= Size;
  1769. }
  1770. if (*OsDirTail)
  1771. {
  1772. PrintString(End, TotalSize, "\\%s;%s", OsDirTail, ExeDir);
  1773. Size = strlen(End);
  1774. End += Size;
  1775. TotalSize -= Size;
  1776. }
  1777. if (PriPaths)
  1778. {
  1779. PrintString(End, TotalSize, "\\pri;%s", ExeDir);
  1780. Size = strlen(End);
  1781. End += Size;
  1782. TotalSize -= Size;
  1783. }
  1784. if (*--End == ':')
  1785. {
  1786. *++End = '\\';
  1787. }
  1788. else
  1789. {
  1790. TotalSize--;
  1791. }
  1792. if (TotalSize > 1)
  1793. {
  1794. *++End = ';';
  1795. *++End = 0;
  1796. TotalSize -= 2;
  1797. }
  1798. //
  1799. // 4 - Copy environment path
  1800. //
  1801. GetEnvironmentVariable("PATH", End, TotalSize);
  1802. if (Target)
  1803. {
  1804. Target->m_ExtensionSearchPath = NewPath;
  1805. }
  1806. else
  1807. {
  1808. g_BaseExtensionSearchPath = NewPath;
  1809. }
  1810. return NewPath;
  1811. }
  1812. BOOL
  1813. IsAbsolutePath(PCTSTR Path)
  1814. /*++
  1815. Routine Description:
  1816. Is this path an absolute path? Does not guarentee that the path exists. The
  1817. method is:
  1818. "\\<anything>" is an absolute path
  1819. "{char}:\<anything>" is an absolute path
  1820. anything else is not
  1821. --*/
  1822. {
  1823. BOOL Ret;
  1824. if ( (Path [0] == '\\' && Path [1] == '\\') ||
  1825. (isalpha ( Path [0] ) && Path [1] == ':' && Path [ 2 ] == '\\') )
  1826. {
  1827. Ret = TRUE;
  1828. }
  1829. else
  1830. {
  1831. Ret = FALSE;
  1832. }
  1833. return Ret;
  1834. }
  1835. void
  1836. FreeExtensionLibrary(EXTDLL* Ext)
  1837. {
  1838. FreeLibrary(Ext->Dll);
  1839. Ext->Dll = NULL;
  1840. if (Ext == g_Wow64ExtDll)
  1841. {
  1842. g_Wow64exts = NULL;
  1843. g_Wow64ExtDll = NULL;
  1844. }
  1845. if (Ext == g_WmiExtDll)
  1846. {
  1847. g_WmiFormatTraceData = NULL;
  1848. g_WmiExtDll = NULL;
  1849. }
  1850. }
  1851. BOOL
  1852. LoadExtensionDll(TargetInfo* Target, EXTDLL *Ext)
  1853. {
  1854. BOOL Found;
  1855. CHAR ExtPath[_MAX_PATH];
  1856. if (Ext->Dll != NULL)
  1857. {
  1858. // Extension is already loaded.
  1859. return TRUE;
  1860. }
  1861. //
  1862. // Do not allow extensions to be loaded via arbitrary UNC
  1863. // paths when in secure mode.
  1864. //
  1865. if ((g_SymOptions & SYMOPT_SECURE) &&
  1866. ((IS_SLASH(Ext->Name[0]) && IS_SLASH(Ext->Name[1])) ||
  1867. IsUrlPathComponent(Ext->Name)))
  1868. {
  1869. ErrOut("SECURE: UNC paths not allowed for extension DLLs - %s\n",
  1870. Ext->Name);
  1871. return FALSE;
  1872. }
  1873. //
  1874. // If we are not allowing network paths, verify that the extension will
  1875. // not be loaded from a network path.
  1876. //
  1877. if (g_EngOptions & DEBUG_ENGOPT_DISALLOW_NETWORK_PATHS)
  1878. {
  1879. DWORD NetCheck;
  1880. NetCheck = NetworkPathCheck(BuildExtensionSearchPath(Target));
  1881. //
  1882. // Check full path of the extension.
  1883. //
  1884. if (NetCheck != ERROR_FILE_OFFLINE)
  1885. {
  1886. CHAR Drive [ _MAX_DRIVE + 1];
  1887. CHAR Dir [ _MAX_DIR + 1];
  1888. CHAR Path [ _MAX_PATH + 1];
  1889. *Drive = '\000';
  1890. *Dir = '\000';
  1891. _splitpath (Ext->Name, Drive, Dir, NULL, NULL);
  1892. _makepath (Path, Drive, Dir, NULL, NULL);
  1893. NetCheck = NetworkPathCheck (Path);
  1894. }
  1895. if (NetCheck == ERROR_FILE_OFFLINE)
  1896. {
  1897. ErrOut("ERROR: extension search path contains "
  1898. "network references.\n");
  1899. return FALSE;
  1900. }
  1901. }
  1902. Found = SearchPath(BuildExtensionSearchPath(Target),
  1903. Ext->Name,
  1904. ".dll",
  1905. DIMA(ExtPath),
  1906. ExtPath,
  1907. NULL);
  1908. UINT OldMode = SetErrorMode(SEM_FAILCRITICALERRORS);
  1909. if ( Found )
  1910. {
  1911. Ext->Dll = LoadLibrary(ExtPath);
  1912. }
  1913. else if (IsAbsolutePath(Ext->Name))
  1914. {
  1915. Ext->Dll = LoadLibrary(Ext->Name);
  1916. }
  1917. SetErrorMode(OldMode);
  1918. if (Ext->Dll == NULL)
  1919. {
  1920. HRESULT Status = WIN32_LAST_STATUS();
  1921. ErrOut("The call to LoadLibrary(%s) failed, %s\n \"%s\"\n"
  1922. "Please check your debugger configuration "
  1923. "and/or network access.\n",
  1924. Ext->Name, FormatStatusCode(Status), FormatStatus(Status));
  1925. return FALSE;
  1926. }
  1927. PCSTR ExtPathTail = PathTail(Ext->Name);
  1928. if (!_stricmp(ExtPathTail, "wow64exts.dll") ||
  1929. !_stricmp(ExtPathTail, "wow64exts"))
  1930. {
  1931. g_Wow64exts = (WOW64EXTSPROC)GetProcAddress(Ext->Dll,"Wow64extsfn");
  1932. DBG_ASSERT(g_Wow64exts);
  1933. g_Wow64ExtDll = Ext;
  1934. }
  1935. if (!_stricmp(ExtPathTail, "wmitrace.dll") ||
  1936. !_stricmp(ExtPathTail, "wmitrace"))
  1937. {
  1938. g_WmiFormatTraceData = (WMI_FORMAT_TRACE_DATA)
  1939. GetProcAddress(Ext->Dll, "WmiFormatTraceData");
  1940. g_WmiExtDll = Ext;
  1941. }
  1942. if (!g_QuietMode)
  1943. {
  1944. VerbOut("Loaded %s extension DLL\n", Ext->Name);
  1945. }
  1946. //
  1947. // Now that the extension is loaded, refresh it.
  1948. //
  1949. Ext->Uninit = NULL;
  1950. PDEBUG_EXTENSION_INITIALIZE EngExt;
  1951. EngExt = (PDEBUG_EXTENSION_INITIALIZE)
  1952. GetProcAddress(Ext->Dll, "DebugExtensionInitialize");
  1953. if (EngExt != NULL)
  1954. {
  1955. ULONG Version, Flags;
  1956. HRESULT Status;
  1957. // This is an engine extension. Initialize it.
  1958. Status = EngExt(&Version, &Flags);
  1959. if (Status != S_OK)
  1960. {
  1961. ErrOut("%s!DebugExtensionInitialize failed with 0x%08lX\n",
  1962. Ext->Name, Status);
  1963. goto EH_Free;
  1964. }
  1965. Ext->ApiVersion.MajorVersion = HIWORD(Version);
  1966. Ext->ApiVersion.MinorVersion = LOWORD(Version);
  1967. Ext->ApiVersion.Revision = 0;
  1968. Ext->Notify = (PDEBUG_EXTENSION_NOTIFY)
  1969. GetProcAddress(Ext->Dll, "DebugExtensionNotify");
  1970. Ext->Uninit = (PDEBUG_EXTENSION_UNINITIALIZE)
  1971. GetProcAddress(Ext->Dll, "DebugExtensionUninitialize");
  1972. Ext->ExtensionType = DEBUG_EXTENSION_TYPE;
  1973. Ext->Init = NULL;
  1974. Ext->ApiVersionRoutine = NULL;
  1975. Ext->CheckVersionRoutine = NULL;
  1976. goto VersionCheck;
  1977. }
  1978. Ext->Init = (PWINDBG_EXTENSION_DLL_INIT64)
  1979. GetProcAddress(Ext->Dll, "WinDbgExtensionDllInit");
  1980. // Windbg Api
  1981. if (Ext->Init != NULL)
  1982. {
  1983. Ext->ExtensionType = WINDBG_EXTENSION_TYPE;
  1984. Ext->ApiVersionRoutine = (PWINDBG_EXTENSION_API_VERSION)
  1985. GetProcAddress(Ext->Dll, "ExtensionApiVersion");
  1986. if (Ext->ApiVersionRoutine == NULL)
  1987. {
  1988. ErrOut("%s is not a valid windbg extension DLL\n",
  1989. Ext->Name);
  1990. goto EH_Free;
  1991. }
  1992. Ext->CheckVersionRoutine = (PWINDBG_CHECK_VERSION)
  1993. GetProcAddress(Ext->Dll, "CheckVersion");
  1994. Ext->ApiVersion = *(Ext->ApiVersionRoutine());
  1995. if (Ext->ApiVersion.Revision >= 6)
  1996. {
  1997. (Ext->Init)(&g_WindbgExtensions64,
  1998. Target ? (USHORT)Target->m_CheckedBuild : 0,
  1999. Target ? (USHORT)Target->m_BuildNumber : 0);
  2000. }
  2001. else
  2002. {
  2003. (Ext->Init)((PWINDBG_EXTENSION_APIS64)&g_WindbgExtensions32,
  2004. Target ? (USHORT)Target->m_CheckedBuild : 0,
  2005. Target ? (USHORT)Target->m_BuildNumber : 0);
  2006. }
  2007. }
  2008. else if (g_SymOptions & SYMOPT_SECURE)
  2009. {
  2010. ErrOut("SECURE: Cannot determine extension DLL type - %s\n",
  2011. Ext->Name);
  2012. goto EH_Free;
  2013. }
  2014. else
  2015. {
  2016. Ext->ApiVersion.Revision = EXT_API_VERSION_NUMBER;
  2017. Ext->ApiVersionRoutine = NULL;
  2018. Ext->CheckVersionRoutine = NULL;
  2019. if (GetProcAddress(Ext->Dll, "NtsdExtensionDllInit"))
  2020. {
  2021. Ext->ExtensionType = NTSD_EXTENSION_TYPE;
  2022. }
  2023. else
  2024. {
  2025. Ext->ExtensionType = IS_KERNEL_TARGET(g_Target) ?
  2026. WINDBG_OLDKD_EXTENSION_TYPE : NTSD_EXTENSION_TYPE;
  2027. }
  2028. }
  2029. VersionCheck:
  2030. #if 0
  2031. // Temporarily remove this print statements.
  2032. if (!(g_EnvDbgOptions & OPTION_NOVERSIONCHECK))
  2033. {
  2034. if (Ext->ApiVersion.Revision < 6)
  2035. {
  2036. dprintf("%s uses the old 32 bit extension API and may not be fully\n", Ext->Name);
  2037. dprintf("compatible with current systems.\n");
  2038. }
  2039. else if (Ext->ApiVersion.Revision < EXT_API_VERSION_NUMBER)
  2040. {
  2041. dprintf("%s uses an earlier version of the extension API than that\n", Ext->Name);
  2042. dprintf("supported by this debugger, and should work properly, but there\n");
  2043. dprintf("may be unexpected incompatibilities.\n");
  2044. }
  2045. else if (Ext->ApiVersion.Revision > EXT_API_VERSION_NUMBER)
  2046. {
  2047. dprintf("%s uses a later version of the extension API than that\n", Ext->Name);
  2048. dprintf("supported by this debugger, and might not function correctly.\n");
  2049. dprintf("You should use the debugger from the SDK or DDK which was used\n");
  2050. dprintf("to build the extension library.\n");
  2051. }
  2052. }
  2053. #endif
  2054. // If the extension has a notification routine send
  2055. // notifications appropriate to the current state.
  2056. if (Ext->Notify != NULL)
  2057. {
  2058. __try
  2059. {
  2060. if (IS_MACHINE_SET(g_Target))
  2061. {
  2062. Ext->Notify(DEBUG_NOTIFY_SESSION_ACTIVE, 0);
  2063. }
  2064. if (IS_CUR_MACHINE_ACCESSIBLE())
  2065. {
  2066. Ext->Notify(DEBUG_NOTIFY_SESSION_ACCESSIBLE, 0);
  2067. }
  2068. }
  2069. __except(ExtensionExceptionFilter(GetExceptionInformation(),
  2070. Ext->Name,
  2071. "DebugExtensionNotify"))
  2072. {
  2073. // Empty.
  2074. }
  2075. }
  2076. return TRUE;
  2077. EH_Free:
  2078. FreeExtensionLibrary(Ext);
  2079. return FALSE;
  2080. }
  2081. void
  2082. UnlinkExtensionDll(EXTDLL* Match)
  2083. {
  2084. EXTDLL *Ext;
  2085. EXTDLL *Prev;
  2086. Prev = NULL;
  2087. for (Ext = g_ExtDlls; Ext != NULL; Ext = Ext->Next)
  2088. {
  2089. if (Match == Ext)
  2090. {
  2091. break;
  2092. }
  2093. Prev = Ext;
  2094. }
  2095. if (Ext == NULL)
  2096. {
  2097. ErrOut("! Extension DLL list inconsistency !\n");
  2098. }
  2099. else if (Prev == NULL)
  2100. {
  2101. g_ExtDlls = Ext->Next;
  2102. }
  2103. else
  2104. {
  2105. Prev->Next = Ext->Next;
  2106. }
  2107. }
  2108. void
  2109. DeferExtensionDll(EXTDLL *Ext, BOOL Verbose)
  2110. {
  2111. if (Ext->Dll == NULL)
  2112. {
  2113. // Already deferred.
  2114. return;
  2115. }
  2116. Ext->Init = NULL;
  2117. Ext->Notify = NULL;
  2118. Ext->ApiVersionRoutine = NULL;
  2119. Ext->CheckVersionRoutine = NULL;
  2120. if (Ext->Uninit != NULL)
  2121. {
  2122. Ext->Uninit();
  2123. Ext->Uninit = NULL;
  2124. }
  2125. if (Ext->Dll != NULL)
  2126. {
  2127. if (Verbose)
  2128. {
  2129. dprintf("Unloading %s extension DLL\n", Ext->Name);
  2130. }
  2131. else if (!g_QuietMode)
  2132. {
  2133. VerbOut("Unloading %s extension DLL\n", Ext->Name);
  2134. }
  2135. FreeExtensionLibrary(Ext);
  2136. }
  2137. }
  2138. void
  2139. UnloadExtensionDll(EXTDLL *Ext, BOOL Verbose)
  2140. {
  2141. UnlinkExtensionDll(Ext);
  2142. DeferExtensionDll(Ext, Verbose);
  2143. free(Ext);
  2144. NotifyChangeEngineState(DEBUG_CES_EXTENSIONS, 0, TRUE);
  2145. }
  2146. void
  2147. MoveExtensionToHead(EXTDLL* Ext)
  2148. {
  2149. UnlinkExtensionDll(Ext);
  2150. LinkExtensionDll(Ext);
  2151. }
  2152. void
  2153. UnloadTargetExtensionDlls(TargetInfo* Target)
  2154. {
  2155. EXTDLL* Ext;
  2156. for (;;)
  2157. {
  2158. for (Ext = g_ExtDlls; Ext != NULL; Ext = Ext->Next)
  2159. {
  2160. if (Ext->Target == Target)
  2161. {
  2162. UnloadExtensionDll(Ext, FALSE);
  2163. // Force a loop around as the list has
  2164. // changed.
  2165. break;
  2166. }
  2167. }
  2168. if (!Ext)
  2169. {
  2170. return;
  2171. }
  2172. }
  2173. }
  2174. void
  2175. DeferAllExtensionDlls(void)
  2176. {
  2177. EXTDLL* Ext;
  2178. for (Ext = g_ExtDlls; Ext != NULL; Ext = Ext->Next)
  2179. {
  2180. DeferExtensionDll(Ext, FALSE);
  2181. }
  2182. }
  2183. BOOL
  2184. CallAnyExtension(DebugClient* Client,
  2185. EXTDLL* Ext, PSTR Function, PCSTR Arguments,
  2186. BOOL ModuleSpecified, BOOL ShowWarnings,
  2187. HRESULT* ExtStatus)
  2188. {
  2189. if (Ext == NULL)
  2190. {
  2191. Ext = g_ExtDlls;
  2192. }
  2193. // Walk through the list of extension DLLs and attempt to
  2194. // call the given extension function on them.
  2195. while (Ext != NULL)
  2196. {
  2197. //
  2198. // hack : only dbghelp extensions or analyzebugcheck
  2199. // will work on minidump files right now.
  2200. //
  2201. // Let all the extensions run on minidumps since there is more data
  2202. // in the dumps now.
  2203. //
  2204. // char Name[_MAX_FNAME + 1];
  2205. //
  2206. // _splitpath(Ext->Name, NULL, NULL, Name, NULL);
  2207. //
  2208. // if (!IS_KERNEL_TRIAGE_DUMP(g_Target) ||
  2209. // !_stricmp(Name, "dbghelp") ||
  2210. // !_stricmp(Name, "dbgtstext") || // used by the test team
  2211. // !_stricmp(Name, "dt_exts") || // used by the test team
  2212. // !_stricmp(Name, "ext"))
  2213. {
  2214. if ((!Ext->Target || Ext->Target == g_Target) &&
  2215. LoadExtensionDll(g_Target, Ext))
  2216. {
  2217. BOOL DidCall;
  2218. DidCall = CallExtension(Client, Ext, Function, Arguments,
  2219. ExtStatus);
  2220. if (DidCall &&
  2221. *ExtStatus != DEBUG_EXTENSION_CONTINUE_SEARCH)
  2222. {
  2223. return TRUE;
  2224. }
  2225. if (!DidCall && ModuleSpecified)
  2226. {
  2227. // If a DLL was explicitly specified then the
  2228. // missing function is an error.
  2229. if (ShowWarnings &&
  2230. !(g_EnvDbgOptions & OPTION_NOEXTWARNING))
  2231. {
  2232. MaskOut(DEBUG_OUTPUT_EXTENSION_WARNING,
  2233. "%s has no %s export\n", Ext->Name, Function);
  2234. }
  2235. return FALSE;
  2236. }
  2237. }
  2238. }
  2239. Ext = Ext->Next;
  2240. }
  2241. if (ShowWarnings && !(g_EnvDbgOptions & OPTION_NOEXTWARNING))
  2242. {
  2243. MaskOut(DEBUG_OUTPUT_EXTENSION_WARNING,
  2244. "No export %s found\n", Function);
  2245. }
  2246. return FALSE;
  2247. }
  2248. void
  2249. OutputModuleIdInfo(HMODULE Mod, PSTR ModFile, LPEXT_API_VERSION ApiVer)
  2250. {
  2251. WCHAR FileBuf[MAX_IMAGE_PATH];
  2252. char *File;
  2253. time_t TimeStamp;
  2254. char *TimeStr;
  2255. char VerStr[64];
  2256. if (Mod == NULL)
  2257. {
  2258. Mod = GetModuleHandle(ModFile);
  2259. }
  2260. if (MultiByteToWideChar(CP_ACP, 0, ModFile, -1,
  2261. FileBuf, DIMA(FileBuf)) &&
  2262. GetFileStringFileInfo(FileBuf, "ProductVersion",
  2263. VerStr, sizeof(VerStr)))
  2264. {
  2265. dprintf("image %s, ", VerStr);
  2266. }
  2267. if (ApiVer != NULL)
  2268. {
  2269. dprintf("API %d.%d.%d, ",
  2270. ApiVer->MajorVersion,
  2271. ApiVer->MinorVersion,
  2272. ApiVer->Revision);
  2273. }
  2274. TimeStamp = GetTimestampForLoadedLibrary(Mod);
  2275. TimeStr = ctime(&TimeStamp);
  2276. // Delete newline.
  2277. TimeStr[strlen(TimeStr) - 1] = 0;
  2278. if (GetModuleFileName(Mod, (PSTR)FileBuf, DIMA(FileBuf) - 1) == 0)
  2279. {
  2280. File = "Unable to get filename";
  2281. }
  2282. else
  2283. {
  2284. File = (PSTR)FileBuf;
  2285. }
  2286. dprintf("built %s\n [path: %s]\n", TimeStr, File);
  2287. }
  2288. void
  2289. OutputExtensions(DebugClient* Client, BOOL Versions)
  2290. {
  2291. if ((g_Target && g_Target->m_ExtensionSearchPath) ||
  2292. (!g_Target && g_BaseExtensionSearchPath))
  2293. {
  2294. dprintf("Extension DLL search Path:\n %s\n",
  2295. g_Target ?
  2296. g_Target->m_ExtensionSearchPath : g_BaseExtensionSearchPath);
  2297. }
  2298. else
  2299. {
  2300. dprintf("Default extension DLLs are not loaded until "
  2301. "after initial connection\n");
  2302. if (g_ExtDlls == NULL)
  2303. {
  2304. return;
  2305. }
  2306. }
  2307. dprintf("Extension DLL chain:\n");
  2308. if (g_ExtDlls == NULL)
  2309. {
  2310. dprintf(" <Empty>\n");
  2311. return;
  2312. }
  2313. EXTDLL *Ext;
  2314. for (Ext = g_ExtDlls; Ext != NULL; Ext = Ext->Next)
  2315. {
  2316. if (Ext->Target && Ext->Target != g_Target)
  2317. {
  2318. continue;
  2319. }
  2320. if (Versions & (Ext->Dll == NULL))
  2321. {
  2322. LoadExtensionDll(g_Target, Ext);
  2323. }
  2324. dprintf(" %s: ", Ext->Name);
  2325. if (Ext->Dll != NULL)
  2326. {
  2327. LPEXT_API_VERSION ApiVer;
  2328. if ((Ext->ExtensionType == DEBUG_EXTENSION_TYPE) ||
  2329. (Ext->ApiVersionRoutine != NULL))
  2330. {
  2331. ApiVer = &Ext->ApiVersion;
  2332. }
  2333. else
  2334. {
  2335. ApiVer = NULL;
  2336. }
  2337. OutputModuleIdInfo(Ext->Dll, Ext->Name, ApiVer);
  2338. if (Versions)
  2339. {
  2340. HRESULT ExtStatus;
  2341. CallExtension(Client, Ext, "version", "", &ExtStatus);
  2342. }
  2343. }
  2344. else
  2345. {
  2346. dprintf("(Not loaded)\n");
  2347. }
  2348. }
  2349. }
  2350. void
  2351. NotifyExtensions(ULONG Notify, ULONG64 Argument)
  2352. {
  2353. EXTDLL *Ext;
  2354. // This routine deliberately does not provoke
  2355. // a DLL load.
  2356. for (Ext = g_ExtDlls; Ext != NULL; Ext = Ext->Next)
  2357. {
  2358. if ((!Ext->Target || Ext->Target == g_Target) &&
  2359. Ext->Notify != NULL)
  2360. {
  2361. __try
  2362. {
  2363. Ext->Notify(Notify, Argument);
  2364. }
  2365. __except(ExtensionExceptionFilter(GetExceptionInformation(),
  2366. Ext->Name,
  2367. "DebugExtensionNotify"))
  2368. {
  2369. // Empty.
  2370. }
  2371. }
  2372. }
  2373. }
  2374. //----------------------------------------------------------------------------
  2375. //
  2376. // Built-in extension commands.
  2377. //
  2378. //----------------------------------------------------------------------------
  2379. VOID
  2380. ParseBangCmd(DebugClient* Client,
  2381. BOOL BuiltInOnly)
  2382. {
  2383. PSTR Cmd, Scan;
  2384. PSTR ModName;
  2385. PSTR FnName;
  2386. EXTDLL* Ext;
  2387. char CmdCopy[MAX_COMMAND];
  2388. char Save;
  2389. PSTR FnArgs;
  2390. //
  2391. // Shell escape always consumes the entire string.
  2392. //
  2393. if (*g_CurCmd == '!')
  2394. {
  2395. g_CurCmd++;
  2396. DotShell(NULL, Client);
  2397. *g_CurCmd = 0;
  2398. return;
  2399. }
  2400. PeekChar();
  2401. // Make a copy of the command string so that modifications
  2402. // do not change the actual command string the debugger is processing.
  2403. CopyString(CmdCopy, g_CurCmd, DIMA(CmdCopy));
  2404. //
  2405. // Syntax is [path-without-spaces]module.function argument-string.
  2406. //
  2407. ModName = CmdCopy;
  2408. FnName = NULL;
  2409. Cmd = CmdCopy;
  2410. while (*Cmd != ' ' && *Cmd != '\t' && *Cmd &&
  2411. *Cmd != ';' && *Cmd != '"')
  2412. {
  2413. Cmd++;
  2414. }
  2415. Scan = Cmd;
  2416. if (*Cmd && *Cmd != ';' && *Cmd != '"')
  2417. {
  2418. *Cmd = 0;
  2419. Cmd++;
  2420. }
  2421. while (*Scan != '.' && Scan != ModName)
  2422. {
  2423. Scan--;
  2424. }
  2425. if (*Scan == '.' && !BuiltInOnly)
  2426. {
  2427. *Scan = 0;
  2428. Scan++;
  2429. FnName = Scan;
  2430. }
  2431. else
  2432. {
  2433. FnName = ModName;
  2434. ModName = NULL;
  2435. }
  2436. if ((FnArgs = BufferStringValue(&Cmd,
  2437. STRV_ESCAPED_CHARACTERS |
  2438. STRV_ALLOW_EMPTY_STRING,
  2439. NULL, &Save)) == NULL)
  2440. {
  2441. ErrOut("Syntax error in extension string\n");
  2442. return;
  2443. }
  2444. // Update the real command string pointer to account for
  2445. // the characters parsed in the copy.
  2446. g_CurCmd += Cmd - CmdCopy;
  2447. //
  2448. // ModName -> Name of module
  2449. // FnName -> Name of command to process
  2450. // FnArgs -> argument to command
  2451. //
  2452. if (ModName != NULL)
  2453. {
  2454. Ext = AddExtensionDll(ModName, TRUE, NULL, NULL);
  2455. if (Ext == NULL)
  2456. {
  2457. return;
  2458. }
  2459. }
  2460. else
  2461. {
  2462. Ext = g_ExtDlls;
  2463. }
  2464. if (!_stricmp(FnName, "load"))
  2465. {
  2466. if (ModName == NULL)
  2467. {
  2468. Ext = AddExtensionDll(FnArgs, TRUE, NULL, NULL);
  2469. if (Ext == NULL)
  2470. {
  2471. return;
  2472. }
  2473. }
  2474. LoadExtensionDll(g_Target, Ext);
  2475. return;
  2476. }
  2477. else if (!_stricmp(FnName, "setdll"))
  2478. {
  2479. if (ModName == NULL)
  2480. {
  2481. Ext = AddExtensionDll(FnArgs, TRUE, NULL, NULL);
  2482. if (Ext == NULL)
  2483. {
  2484. return;
  2485. }
  2486. }
  2487. MoveExtensionToHead(Ext);
  2488. if (ModName != NULL && Ext->Dll == NULL)
  2489. {
  2490. dprintf("Added %s to extension DLL chain\n", Ext->Name);
  2491. }
  2492. return;
  2493. }
  2494. else if (!_stricmp(FnName, "unload"))
  2495. {
  2496. if (ModName == NULL)
  2497. {
  2498. if (*FnArgs == '\0')
  2499. {
  2500. Ext = g_ExtDlls;
  2501. }
  2502. else
  2503. {
  2504. Ext = AddExtensionDll(FnArgs, TRUE, NULL, NULL);
  2505. }
  2506. if (Ext == NULL)
  2507. {
  2508. return;
  2509. }
  2510. }
  2511. if (Ext != NULL)
  2512. {
  2513. UnloadExtensionDll(Ext, TRUE);
  2514. }
  2515. return;
  2516. }
  2517. else if (!_stricmp(FnName, "unloadall"))
  2518. {
  2519. g_EngNotify++;
  2520. while (g_ExtDlls != NULL)
  2521. {
  2522. UnloadExtensionDll(g_ExtDlls, TRUE);
  2523. }
  2524. g_EngNotify--;
  2525. NotifyChangeEngineState(DEBUG_CES_EXTENSIONS, 0, TRUE);
  2526. return;
  2527. }
  2528. if (BuiltInOnly)
  2529. {
  2530. error(SYNTAX);
  2531. }
  2532. HRESULT ExtStatus;
  2533. CallAnyExtension(Client, Ext, FnName, FnArgs, ModName != NULL, TRUE,
  2534. &ExtStatus);
  2535. }
  2536. void
  2537. ReadDebugOptions (BOOL fQuiet, char * pszOptionsStr)
  2538. /*++
  2539. Routine Description:
  2540. Parses an options string (see g_EnvDbgOptionNames) and maps
  2541. it to OPTION_ flags (in g_EnvDbgOptions).
  2542. Arguments:
  2543. fQuiet - If TRUE, do not print option settings.
  2544. pszOptionsStr - Options string; if NULL, get it from _NT_DEBUG_OPTIONS
  2545. Return Value:
  2546. None
  2547. --*/
  2548. {
  2549. BOOL fInit;
  2550. char ** ppszOption;
  2551. char * psz;
  2552. DWORD dwMask;
  2553. int iOptionCount;
  2554. fInit = (pszOptionsStr == NULL);
  2555. if (fInit)
  2556. {
  2557. g_EnvDbgOptions = 0;
  2558. pszOptionsStr = getenv("_NT_DEBUG_OPTIONS");
  2559. }
  2560. if (pszOptionsStr == NULL)
  2561. {
  2562. if (!fQuiet)
  2563. {
  2564. dprintf("_NT_DEBUG_OPTIONS is not defined\n");
  2565. }
  2566. return;
  2567. }
  2568. psz = pszOptionsStr;
  2569. while (*psz != '\0')
  2570. {
  2571. *psz = (char)toupper(*psz);
  2572. psz++;
  2573. }
  2574. ppszOption = g_EnvDbgOptionNames;
  2575. for (iOptionCount = 0;
  2576. iOptionCount < OPTION_COUNT;
  2577. iOptionCount++, ppszOption++)
  2578. {
  2579. if ((strstr(pszOptionsStr, *ppszOption) == NULL))
  2580. {
  2581. continue;
  2582. }
  2583. dwMask = (1 << iOptionCount);
  2584. if (fInit)
  2585. {
  2586. g_EnvDbgOptions |= dwMask;
  2587. }
  2588. else
  2589. {
  2590. g_EnvDbgOptions ^= dwMask;
  2591. }
  2592. }
  2593. if (!fQuiet)
  2594. {
  2595. dprintf("Debug Options:");
  2596. if (g_EnvDbgOptions == 0)
  2597. {
  2598. dprintf(" <none>\n");
  2599. }
  2600. else
  2601. {
  2602. dwMask = g_EnvDbgOptions;
  2603. ppszOption = g_EnvDbgOptionNames;
  2604. while (dwMask != 0)
  2605. {
  2606. if (dwMask & 0x1)
  2607. {
  2608. dprintf(" %s", *ppszOption);
  2609. }
  2610. dwMask >>= 1;
  2611. ppszOption++;
  2612. }
  2613. dprintf("\n");
  2614. }
  2615. }
  2616. }
  2617. //----------------------------------------------------------------------------
  2618. //
  2619. // LoadWow64ExtsIfNeeded
  2620. //
  2621. //----------------------------------------------------------------------------
  2622. VOID
  2623. LoadWow64ExtsIfNeeded(ULONG64 Process)
  2624. {
  2625. LONG_PTR Wow64Info;
  2626. NTSTATUS Status;
  2627. EXTDLL * Extension;
  2628. // wx86 only runs on NT.
  2629. if (g_DebuggerPlatformId != VER_PLATFORM_WIN32_NT)
  2630. {
  2631. return;
  2632. }
  2633. //
  2634. // if New process is a Wx86 process, load in the wx86 extensions
  2635. // dll. This will stay loaded until ntsd exits.
  2636. //
  2637. Status = g_NtDllCalls.NtQueryInformationProcess(OS_HANDLE(Process),
  2638. ProcessWow64Information,
  2639. &Wow64Info,
  2640. sizeof(Wow64Info),
  2641. NULL
  2642. );
  2643. if (NT_SUCCESS(Status) && Wow64Info)
  2644. {
  2645. Extension = AddExtensionDll("wow64exts", FALSE, g_Target, NULL);
  2646. //
  2647. // Force load it so we get the entry point the debugger needs
  2648. //
  2649. LoadExtensionDll(g_Target, Extension);
  2650. }
  2651. }