Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1283 lines
37 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. vdmdbg.c
  5. Abstract:
  6. This module contains the debugging support needed to debug
  7. 16-bit VDM applications
  8. Author:
  9. Bob Day (bobday) 16-Sep-1992 Wrote it
  10. Revision History:
  11. Neil Sandlin (neilsa) 1-Mar-1997 Enhanced it
  12. --*/
  13. #include <precomp.h>
  14. #pragma hdrstop
  15. WORD LastEventFlags;
  16. //----------------------------------------------------------------------------
  17. // VDMGetThreadSelectorEntry()
  18. //
  19. // Public interface to the InternalGetThreadSelectorEntry, needed because
  20. // that routine requires the process handle.
  21. //
  22. //----------------------------------------------------------------------------
  23. BOOL
  24. WINAPI
  25. VDMGetThreadSelectorEntry(
  26. HANDLE hProcess,
  27. HANDLE hUnused,
  28. WORD wSelector,
  29. LPVDMLDT_ENTRY lpSelectorEntry
  30. ) {
  31. BOOL fResult;
  32. UNREFERENCED_PARAMETER(hUnused);
  33. fResult = InternalGetThreadSelectorEntry(
  34. hProcess,
  35. wSelector,
  36. lpSelectorEntry );
  37. return( fResult );
  38. }
  39. //----------------------------------------------------------------------------
  40. // VDMGetPointer()
  41. //
  42. // Public interface to the InternalGetPointer, needed because that
  43. // routine requires the process handle.
  44. //
  45. //----------------------------------------------------------------------------
  46. ULONG
  47. WINAPI
  48. VDMGetPointer(
  49. HANDLE hProcess,
  50. HANDLE hUnused,
  51. WORD wSelector,
  52. DWORD dwOffset,
  53. BOOL fProtMode
  54. ) {
  55. ULONG ulResult;
  56. UNREFERENCED_PARAMETER(hUnused);
  57. ulResult = InternalGetPointer(
  58. hProcess,
  59. wSelector,
  60. dwOffset,
  61. fProtMode );
  62. return( ulResult );
  63. }
  64. //
  65. // Obselete functions
  66. //
  67. BOOL
  68. WINAPI
  69. VDMGetThreadContext(
  70. LPDEBUG_EVENT lpDebugEvent,
  71. LPVDMCONTEXT lpVDMContext)
  72. {
  73. HANDLE hProcess;
  74. BOOL bReturn;
  75. hProcess = OpenProcess( PROCESS_VM_READ, FALSE, lpDebugEvent->dwProcessId );
  76. bReturn = VDMGetContext(hProcess, NULL, lpVDMContext);
  77. CloseHandle( hProcess );
  78. return bReturn;
  79. }
  80. BOOL WINAPI VDMSetThreadContext(
  81. LPDEBUG_EVENT lpDebugEvent,
  82. LPVDMCONTEXT lpVDMContext)
  83. {
  84. HANDLE hProcess;
  85. BOOL bReturn;
  86. hProcess = OpenProcess( PROCESS_VM_READ, FALSE, lpDebugEvent->dwProcessId );
  87. bReturn = VDMSetContext(hProcess, NULL, lpVDMContext);
  88. CloseHandle( hProcess );
  89. return bReturn;
  90. }
  91. //----------------------------------------------------------------------------
  92. // VDMGetContext()
  93. //
  94. // Interface to get the simulated context. The same functionality as
  95. // GetThreadContext except that it happens on the simulated 16-bit context,
  96. // rather than the 32-bit context.
  97. //
  98. //----------------------------------------------------------------------------
  99. BOOL
  100. WINAPI
  101. VDMGetContext(
  102. HANDLE hProcess,
  103. HANDLE hThread,
  104. LPVDMCONTEXT lpVDMContext
  105. ) {
  106. VDMCONTEXT vcContext;
  107. BOOL b;
  108. DWORD lpNumberOfBytesRead;
  109. int i;
  110. BOOL bUseVDMContext = TRUE;
  111. #ifdef _X86_
  112. if (hThread) {
  113. vcContext.ContextFlags = lpVDMContext->ContextFlags;
  114. if (!GetThreadContext(hThread, (CONTEXT*)&vcContext)) {
  115. return FALSE;
  116. }
  117. if ((vcContext.EFlags & V86FLAGS_V86) || (vcContext.SegCs != 0x1b)) {
  118. bUseVDMContext = FALSE;
  119. }
  120. }
  121. #endif
  122. if (bUseVDMContext) {
  123. b = ReadProcessMemory(hProcess,
  124. lpVdmContext,
  125. &vcContext,
  126. sizeof(vcContext),
  127. &lpNumberOfBytesRead
  128. );
  129. if ( !b || lpNumberOfBytesRead != sizeof(vcContext) ) {
  130. return( FALSE );
  131. }
  132. }
  133. #ifdef _X86_
  134. if ((lpVDMContext->ContextFlags & VDMCONTEXT_CONTROL) == VDMCONTEXT_CONTROL) {
  135. //
  136. // Set registers ebp, eip, cs, eflag, esp and ss.
  137. //
  138. lpVDMContext->Ebp = vcContext.Ebp;
  139. lpVDMContext->Eip = vcContext.Eip;
  140. lpVDMContext->SegCs = vcContext.SegCs;
  141. lpVDMContext->EFlags = vcContext.EFlags;
  142. lpVDMContext->SegSs = vcContext.SegSs;
  143. lpVDMContext->Esp = vcContext.Esp;
  144. }
  145. //
  146. // Set segment register contents if specified.
  147. //
  148. if ((lpVDMContext->ContextFlags & VDMCONTEXT_SEGMENTS) == VDMCONTEXT_SEGMENTS) {
  149. //
  150. // Set segment registers gs, fs, es, ds.
  151. //
  152. // These values are junk most of the time, but useful
  153. // for debugging under certain conditions. Therefore,
  154. // we report whatever was in the frame.
  155. //
  156. lpVDMContext->SegGs = vcContext.SegGs;
  157. lpVDMContext->SegFs = vcContext.SegFs;
  158. lpVDMContext->SegEs = vcContext.SegEs;
  159. lpVDMContext->SegDs = vcContext.SegDs;
  160. }
  161. //
  162. // Set integer register contents if specified.
  163. //
  164. if ((lpVDMContext->ContextFlags & VDMCONTEXT_INTEGER) == VDMCONTEXT_INTEGER) {
  165. //
  166. // Set integer registers edi, esi, ebx, edx, ecx, eax
  167. //
  168. lpVDMContext->Edi = vcContext.Edi;
  169. lpVDMContext->Esi = vcContext.Esi;
  170. lpVDMContext->Ebx = vcContext.Ebx;
  171. lpVDMContext->Ecx = vcContext.Ecx;
  172. lpVDMContext->Edx = vcContext.Edx;
  173. lpVDMContext->Eax = vcContext.Eax;
  174. }
  175. //
  176. // Fetch floating register contents if requested, and type of target
  177. // is user. (system frames have no fp state, so ignore request)
  178. //
  179. if ( (lpVDMContext->ContextFlags & VDMCONTEXT_FLOATING_POINT) ==
  180. VDMCONTEXT_FLOATING_POINT ) {
  181. lpVDMContext->FloatSave.ControlWord = vcContext.FloatSave.ControlWord;
  182. lpVDMContext->FloatSave.StatusWord = vcContext.FloatSave.StatusWord;
  183. lpVDMContext->FloatSave.TagWord = vcContext.FloatSave.TagWord;
  184. lpVDMContext->FloatSave.ErrorOffset = vcContext.FloatSave.ErrorOffset;
  185. lpVDMContext->FloatSave.ErrorSelector = vcContext.FloatSave.ErrorSelector;
  186. lpVDMContext->FloatSave.DataOffset = vcContext.FloatSave.DataOffset;
  187. lpVDMContext->FloatSave.DataSelector = vcContext.FloatSave.DataSelector;
  188. lpVDMContext->FloatSave.Cr0NpxState = vcContext.FloatSave.Cr0NpxState;
  189. for (i = 0; i < SIZE_OF_80387_REGISTERS; i++) {
  190. lpVDMContext->FloatSave.RegisterArea[i] = vcContext.FloatSave.RegisterArea[i];
  191. }
  192. }
  193. //
  194. // Fetch Dr register contents if requested. Values may be trash.
  195. //
  196. if ((lpVDMContext->ContextFlags & VDMCONTEXT_DEBUG_REGISTERS) ==
  197. VDMCONTEXT_DEBUG_REGISTERS) {
  198. lpVDMContext->Dr0 = vcContext.Dr0;
  199. lpVDMContext->Dr1 = vcContext.Dr1;
  200. lpVDMContext->Dr2 = vcContext.Dr2;
  201. lpVDMContext->Dr3 = vcContext.Dr3;
  202. lpVDMContext->Dr6 = vcContext.Dr6;
  203. lpVDMContext->Dr7 = vcContext.Dr7;
  204. }
  205. #else
  206. {
  207. NT_CPU_INFO nt_cpu_info;
  208. BOOL bInNano;
  209. ULONG UMask;
  210. b = ReadProcessMemory(hProcess,
  211. lpNtCpuInfo,
  212. &nt_cpu_info,
  213. sizeof(NT_CPU_INFO),
  214. &lpNumberOfBytesRead
  215. );
  216. if ( !b || lpNumberOfBytesRead != sizeof(NT_CPU_INFO) ) {
  217. return( FALSE );
  218. }
  219. bInNano = ReadDword(hProcess, nt_cpu_info.in_nano_cpu);
  220. UMask = ReadDword(hProcess, nt_cpu_info.universe);
  221. lpVDMContext->Eax = GetRegValue(hProcess, nt_cpu_info.eax, bInNano, UMask);
  222. lpVDMContext->Ecx = GetRegValue(hProcess, nt_cpu_info.ecx, bInNano, UMask);
  223. lpVDMContext->Edx = GetRegValue(hProcess, nt_cpu_info.edx, bInNano, UMask);
  224. lpVDMContext->Ebx = GetRegValue(hProcess, nt_cpu_info.ebx, bInNano, UMask);
  225. lpVDMContext->Ebp = GetRegValue(hProcess, nt_cpu_info.ebp, bInNano, UMask);
  226. lpVDMContext->Esi = GetRegValue(hProcess, nt_cpu_info.esi, bInNano, UMask);
  227. lpVDMContext->Edi = GetRegValue(hProcess, nt_cpu_info.edi, bInNano, UMask);
  228. lpVDMContext->Esp = GetEspValue(hProcess, nt_cpu_info, bInNano);
  229. //
  230. // nt_cpu_info.flags isn't very much use, because several of the
  231. // flags values are not kept in memory, but computed each time.
  232. // The emulator doesn't supply us with the right value, so we
  233. // try to get it from the code in ntvdmd.dll
  234. //
  235. lpVDMContext->EFlags = vcContext.EFlags;
  236. //
  237. // On risc platforms, we don't run in V86 mode, we run in REAL mode.
  238. // So the widespread usage of testing the V86 mode bit in EFLAGS
  239. // would not correctly determine the address mode. Since there is
  240. // no more room in the VDM context structure, the simplest thing
  241. // to do is simply pretend to be in V86 mode when we are in REAL mode.
  242. //
  243. if (ReadDword(hProcess, nt_cpu_info.cr0) & 1) {
  244. lpVDMContext->EFlags |= V86FLAGS_V86;
  245. }
  246. lpVDMContext->Eip = ReadDword(hProcess, nt_cpu_info.eip);
  247. lpVDMContext->SegEs = ReadWord(hProcess, nt_cpu_info.es);
  248. lpVDMContext->SegCs = ReadWord(hProcess, nt_cpu_info.cs);
  249. lpVDMContext->SegSs = ReadWord(hProcess, nt_cpu_info.ss);
  250. lpVDMContext->SegDs = ReadWord(hProcess, nt_cpu_info.ds);
  251. lpVDMContext->SegFs = ReadWord(hProcess, nt_cpu_info.fs);
  252. lpVDMContext->SegGs = ReadWord(hProcess, nt_cpu_info.gs);
  253. }
  254. #endif
  255. return( TRUE );
  256. }
  257. //----------------------------------------------------------------------------
  258. // VDMSetContext()
  259. //
  260. // Interface to set the simulated context. Similar in most respects to
  261. // the SetThreadContext API supported by Win NT. Only differences are
  262. // in the bits which must be "sanitized".
  263. //
  264. //----------------------------------------------------------------------------
  265. BOOL
  266. WINAPI
  267. VDMSetContext(
  268. HANDLE hProcess,
  269. HANDLE hThread,
  270. LPVDMCONTEXT lpVDMContext
  271. ) {
  272. VDMINTERNALINFO viInfo;
  273. VDMCONTEXT vcContext;
  274. BOOL b;
  275. DWORD lpNumberOfBytes;
  276. INT i;
  277. BOOL bUseVDMContext = TRUE;
  278. #ifdef _X86_
  279. if (hThread) {
  280. if (!GetThreadContext(hThread, (CONTEXT*)&vcContext)) {
  281. return FALSE;
  282. }
  283. if ((vcContext.EFlags & V86FLAGS_V86) || (vcContext.SegCs != 0x1b)) {
  284. bUseVDMContext = FALSE;
  285. }
  286. }
  287. #endif
  288. if (bUseVDMContext) {
  289. b = ReadProcessMemory(hProcess,
  290. lpVdmContext,
  291. &vcContext,
  292. sizeof(vcContext),
  293. &lpNumberOfBytes
  294. );
  295. if ( !b || lpNumberOfBytes != sizeof(vcContext) ) {
  296. return( FALSE );
  297. }
  298. }
  299. if ((lpVDMContext->ContextFlags & VDMCONTEXT_CONTROL) == VDMCONTEXT_CONTROL) {
  300. //
  301. // Set registers ebp, eip, cs, eflag, esp and ss.
  302. //
  303. vcContext.Ebp = lpVDMContext->Ebp;
  304. vcContext.Eip = lpVDMContext->Eip;
  305. //
  306. // Don't allow them to modify the mode bit.
  307. //
  308. // Only allow these bits to get set: 01100000110111110111
  309. // V86FLAGS_CARRY 0x00001
  310. // V86FLAGS_? 0x00002
  311. // V86FLAGS_PARITY 0x00004
  312. // V86FLAGS_AUXCARRY 0x00010
  313. // V86FLAGS_ZERO 0x00040
  314. // V86FLAGS_SIGN 0x00080
  315. // V86FLAGS_TRACE 0x00100
  316. // V86FLAGS_INTERRUPT 0x00200
  317. // V86FLAGS_DIRECTION 0x00400
  318. // V86FLAGS_OVERFLOW 0x00800
  319. // V86FLAGS_RESUME 0x10000
  320. // V86FLAGS_VM86 0x20000
  321. // V86FLAGS_ALIGNMENT 0x40000
  322. //
  323. // Commonly flags will be 0x10246
  324. //
  325. if ( vcContext.EFlags & V86FLAGS_V86 ) {
  326. vcContext.EFlags = V86FLAGS_V86 | (lpVDMContext->EFlags &
  327. ( V86FLAGS_CARRY
  328. | 0x0002
  329. | V86FLAGS_PARITY
  330. | V86FLAGS_AUXCARRY
  331. | V86FLAGS_ZERO
  332. | V86FLAGS_SIGN
  333. | V86FLAGS_TRACE
  334. | V86FLAGS_INTERRUPT
  335. | V86FLAGS_DIRECTION
  336. | V86FLAGS_OVERFLOW
  337. | V86FLAGS_RESUME
  338. | V86FLAGS_ALIGNMENT
  339. | V86FLAGS_IOPL
  340. ));
  341. } else {
  342. vcContext.EFlags = ~V86FLAGS_V86 & (lpVDMContext->EFlags &
  343. ( V86FLAGS_CARRY
  344. | 0x0002
  345. | V86FLAGS_PARITY
  346. | V86FLAGS_AUXCARRY
  347. | V86FLAGS_ZERO
  348. | V86FLAGS_SIGN
  349. | V86FLAGS_TRACE
  350. | V86FLAGS_INTERRUPT
  351. | V86FLAGS_DIRECTION
  352. | V86FLAGS_OVERFLOW
  353. | V86FLAGS_RESUME
  354. | V86FLAGS_ALIGNMENT
  355. | V86FLAGS_IOPL
  356. ));
  357. }
  358. //
  359. // CS might only be allowable as a ring 3 selector.
  360. //
  361. if ( vcContext.EFlags & V86FLAGS_V86 ) {
  362. vcContext.SegCs = lpVDMContext->SegCs;
  363. } else {
  364. #ifdef i386
  365. vcContext.SegCs = lpVDMContext->SegCs | 0x0003;
  366. #else
  367. vcContext.SegCs = lpVDMContext->SegCs;
  368. #endif
  369. }
  370. vcContext.SegSs = lpVDMContext->SegSs;
  371. vcContext.Esp = lpVDMContext->Esp;
  372. }
  373. //
  374. // Set segment register contents if specified.
  375. //
  376. if ((lpVDMContext->ContextFlags & VDMCONTEXT_SEGMENTS) == VDMCONTEXT_SEGMENTS) {
  377. //
  378. // Set segment registers gs, fs, es, ds.
  379. //
  380. vcContext.SegGs = lpVDMContext->SegGs;
  381. vcContext.SegFs = lpVDMContext->SegFs;
  382. vcContext.SegEs = lpVDMContext->SegEs;
  383. vcContext.SegDs = lpVDMContext->SegDs;
  384. }
  385. //
  386. // Set integer register contents if specified.
  387. //
  388. if ((lpVDMContext->ContextFlags & VDMCONTEXT_INTEGER) == VDMCONTEXT_INTEGER) {
  389. //
  390. // Set integer registers edi, esi, ebx, edx, ecx, eax
  391. //
  392. vcContext.Edi = lpVDMContext->Edi;
  393. vcContext.Esi = lpVDMContext->Esi;
  394. vcContext.Ebx = lpVDMContext->Ebx;
  395. vcContext.Ecx = lpVDMContext->Ecx;
  396. vcContext.Edx = lpVDMContext->Edx;
  397. vcContext.Eax = lpVDMContext->Eax;
  398. }
  399. //
  400. // Fetch floating register contents if requested, and type of target
  401. // is user.
  402. //
  403. if ( (lpVDMContext->ContextFlags & VDMCONTEXT_FLOATING_POINT) ==
  404. VDMCONTEXT_FLOATING_POINT ) {
  405. vcContext.FloatSave.ControlWord = lpVDMContext->FloatSave.ControlWord;
  406. vcContext.FloatSave.StatusWord = lpVDMContext->FloatSave.StatusWord;
  407. vcContext.FloatSave.TagWord = lpVDMContext->FloatSave.TagWord;
  408. vcContext.FloatSave.ErrorOffset = lpVDMContext->FloatSave.ErrorOffset;
  409. vcContext.FloatSave.ErrorSelector = lpVDMContext->FloatSave.ErrorSelector;
  410. vcContext.FloatSave.DataOffset = lpVDMContext->FloatSave.DataOffset;
  411. vcContext.FloatSave.DataSelector = lpVDMContext->FloatSave.DataSelector;
  412. vcContext.FloatSave.Cr0NpxState = lpVDMContext->FloatSave.Cr0NpxState;
  413. for (i = 0; i < SIZE_OF_80387_REGISTERS; i++) {
  414. vcContext.FloatSave.RegisterArea[i] = lpVDMContext->FloatSave.RegisterArea[i];
  415. }
  416. }
  417. //
  418. // Fetch Dr register contents if requested. Values may be trash.
  419. //
  420. if ((lpVDMContext->ContextFlags & VDMCONTEXT_DEBUG_REGISTERS) ==
  421. VDMCONTEXT_DEBUG_REGISTERS) {
  422. vcContext.Dr0 = lpVDMContext->Dr0;
  423. vcContext.Dr1 = lpVDMContext->Dr1;
  424. vcContext.Dr2 = lpVDMContext->Dr2;
  425. vcContext.Dr3 = lpVDMContext->Dr3;
  426. vcContext.Dr6 = lpVDMContext->Dr6;
  427. vcContext.Dr7 = lpVDMContext->Dr7;
  428. }
  429. #ifdef _X86_
  430. if (!bUseVDMContext) {
  431. if (!SetThreadContext(hThread, (CONTEXT*)&vcContext)) {
  432. return FALSE;
  433. }
  434. }
  435. #endif
  436. b = WriteProcessMemory(
  437. hProcess,
  438. lpVdmContext,
  439. &vcContext,
  440. sizeof(vcContext),
  441. &lpNumberOfBytes
  442. );
  443. if ( !b || lpNumberOfBytes != sizeof(vcContext) ) {
  444. return( FALSE );
  445. }
  446. return( TRUE );
  447. }
  448. //----------------------------------------------------------------------------
  449. // VDMBreakThread()
  450. //
  451. // Interface to interrupt a thread while it is running without any break-
  452. // points. An ideal debugger would have this feature. Since it is hard
  453. // to implement, we will be doing it later.
  454. //
  455. //----------------------------------------------------------------------------
  456. BOOL
  457. WINAPI
  458. VDMBreakThread(
  459. HANDLE hProcess,
  460. HANDLE hThread
  461. ) {
  462. return( FALSE );
  463. }
  464. //----------------------------------------------------------------------------
  465. // VDMProcessException()
  466. //
  467. // This function acts as a filter of debug events. Most debug events
  468. // should be ignored by the debugger (because they don't have the context
  469. // record pointer or the internal info structure setup. Those events
  470. // cause this function to return FALSE, which tells the debugger to just
  471. // blindly continue the exception. When the function does return TRUE,
  472. // the debugger should look at the exception code to determine what to
  473. // do (and all the the structures have been set up properly to deal with
  474. // calls to the other APIs).
  475. //
  476. //----------------------------------------------------------------------------
  477. BOOL
  478. WINAPI
  479. VDMProcessException(
  480. LPDEBUG_EVENT lpDebugEvent
  481. ) {
  482. LPDWORD lpdw;
  483. int mode;
  484. BOOL fResult = TRUE;
  485. lpdw = &(lpDebugEvent->u.Exception.ExceptionRecord.ExceptionInformation[0]);
  486. mode = LOWORD(lpdw[0]);
  487. LastEventFlags = HIWORD(lpdw[0]);
  488. switch( mode ) {
  489. case DBG_SEGLOAD:
  490. case DBG_SEGMOVE:
  491. case DBG_SEGFREE:
  492. case DBG_MODLOAD:
  493. case DBG_MODFREE:
  494. ProcessSegmentNotification(lpDebugEvent);
  495. fResult = FALSE;
  496. break;
  497. case DBG_BREAK:
  498. ProcessBPNotification(lpDebugEvent);
  499. break;
  500. }
  501. ProcessInitNotification(lpDebugEvent);
  502. return( fResult );
  503. }
  504. //----------------------------------------------------------------------------
  505. // VDMGetSelectorModule()
  506. //
  507. // Interface to determine the module and segment associated with a given
  508. // selector. This is useful during debugging to associate symbols with
  509. // code and data segments. The symbol lookup should be done by the
  510. // debugger, given the module and segment number.
  511. //
  512. // This code was adapted from the Win 3.1 ToolHelp DLL
  513. //
  514. //----------------------------------------------------------------------------
  515. BOOL
  516. WINAPI
  517. VDMGetSelectorModule(
  518. HANDLE hProcess,
  519. HANDLE hUnused,
  520. WORD wSelector,
  521. PUINT lpSegmentNumber,
  522. LPSTR lpModuleName,
  523. UINT nNameSize,
  524. LPSTR lpModulePath,
  525. UINT nPathSize
  526. ) {
  527. BOOL b;
  528. DWORD lpNumberOfBytes;
  529. BOOL fResult;
  530. DWORD lphMaster;
  531. DWORD lphMasterLen;
  532. DWORD lphMasterStart;
  533. DWORD lpOwner;
  534. DWORD lpThisModuleResTab;
  535. DWORD lpThisModuleName;
  536. DWORD lpPath;
  537. DWORD lpThisModulecSeg;
  538. DWORD lpThisModuleSegTab;
  539. DWORD lpThisSegHandle;
  540. WORD wMaster;
  541. WORD wMasterLen;
  542. DWORD dwMasterStart;
  543. DWORD dwArenaOffset;
  544. WORD wArenaSlot;
  545. DWORD lpArena;
  546. WORD wModHandle;
  547. WORD wResTab;
  548. UCHAR cLength;
  549. WORD wPathOffset;
  550. UCHAR cPath;
  551. WORD cSeg;
  552. WORD iSeg;
  553. WORD wSegTab;
  554. WORD wHandle;
  555. // CHAR chName[MAX_MODULE_NAME_LENGTH];
  556. // CHAR chPath[MAX_MODULE_PATH_LENGTH];
  557. UNREFERENCED_PARAMETER(hUnused);
  558. if ( lpModuleName != NULL ) *lpModuleName = '\0';
  559. if ( lpModulePath != NULL ) *lpModulePath = '\0';
  560. if ( lpSegmentNumber != NULL ) *lpSegmentNumber = 0;
  561. fResult = FALSE;
  562. #if 0
  563. if ( wKernelSeg == 0 ) {
  564. return( FALSE );
  565. }
  566. // Read out the master heap selector
  567. lphMaster = InternalGetPointer(
  568. hProcess,
  569. wKernelSeg,
  570. dwOffsetTHHOOK + TOOL_HMASTER, // To hGlobalHeap
  571. TRUE );
  572. if ( lphMaster == (DWORD)NULL ) goto punt;
  573. b = ReadProcessMemory(
  574. hProcess,
  575. (LPVOID)lphMaster,
  576. &wMaster,
  577. sizeof(wMaster),
  578. &lpNumberOfBytes
  579. );
  580. if ( !b || lpNumberOfBytes != sizeof(wMaster) ) goto punt;
  581. wMaster |= 1; // Convert to selector
  582. // Read out the master heap selector length
  583. lphMasterLen = InternalGetPointer(
  584. hProcess,
  585. wKernelSeg,
  586. dwOffsetTHHOOK + TOOL_HMASTLEN, // To SelTableLen
  587. TRUE );
  588. if ( lphMasterLen == (DWORD)NULL ) goto punt;
  589. b = ReadProcessMemory(
  590. hProcess,
  591. (LPVOID)lphMasterLen,
  592. &wMasterLen,
  593. sizeof(wMasterLen),
  594. &lpNumberOfBytes
  595. );
  596. if ( !b || lpNumberOfBytes != sizeof(wMasterLen) ) goto punt;
  597. // Read out the master heap selector start
  598. lphMasterStart = InternalGetPointer(
  599. hProcess,
  600. wKernelSeg,
  601. dwOffsetTHHOOK + TOOL_HMASTSTART, // To SelTableStart
  602. TRUE );
  603. if ( lphMasterStart == (DWORD)NULL ) goto punt;
  604. b = ReadProcessMemory(
  605. hProcess,
  606. (LPVOID)lphMasterStart,
  607. &dwMasterStart,
  608. sizeof(dwMasterStart),
  609. &lpNumberOfBytes
  610. );
  611. if ( !b || lpNumberOfBytes != sizeof(dwMasterStart) ) goto punt;
  612. // Now make sure the selector provided is in the right range
  613. if ( fKernel386 ) {
  614. // 386 kernel?
  615. wArenaSlot = (WORD)(wSelector & 0xFFF8); // Mask low 3 bits
  616. wArenaSlot = wArenaSlot >> 1; // Sel/8*4
  617. if ( (WORD)wArenaSlot > wMasterLen ) goto punt; // Out of range
  618. wArenaSlot += (WORD)dwMasterStart;
  619. // Ok, Now read out the area header offset
  620. dwArenaOffset = (DWORD)0; // Default to 0
  621. lpArena = InternalGetPointer(
  622. hProcess,
  623. wMaster,
  624. wArenaSlot,
  625. TRUE );
  626. if ( lpArena == (DWORD)NULL ) goto punt;
  627. // 386 Kernel?
  628. b = ReadProcessMemory(
  629. hProcess,
  630. (LPVOID)lpArena,
  631. &dwArenaOffset,
  632. sizeof(dwArenaOffset),
  633. &lpNumberOfBytes
  634. );
  635. if ( !b || lpNumberOfBytes != sizeof(dwArenaOffset) ) goto punt;
  636. // Read out the owner member
  637. lpOwner = InternalGetPointer(
  638. hProcess,
  639. wMaster,
  640. dwArenaOffset+GA_OWNER386,
  641. TRUE );
  642. if ( lpOwner == (DWORD)NULL ) goto punt;
  643. } else {
  644. lpOwner = InternalGetPointer(
  645. hProcess,
  646. wSelector,
  647. 0,
  648. TRUE );
  649. if ( lpOwner == (DWORD)NULL ) goto punt;
  650. lpOwner -= GA_SIZE;
  651. lpOwner += GA_OWNER;
  652. }
  653. b = ReadProcessMemory(
  654. hProcess,
  655. (LPVOID)lpOwner,
  656. &wModHandle,
  657. sizeof(wModHandle),
  658. &lpNumberOfBytes
  659. );
  660. if ( !b || lpNumberOfBytes != sizeof(wModHandle) ) goto punt;
  661. // Now read out the owners module name
  662. // Name is the first name in the resident names table
  663. lpThisModuleResTab = InternalGetPointer(
  664. hProcess,
  665. wModHandle,
  666. NE_RESTAB,
  667. TRUE );
  668. if ( lpThisModuleResTab == (DWORD)NULL ) goto punt;
  669. b = ReadProcessMemory(
  670. hProcess,
  671. (LPVOID)lpThisModuleResTab,
  672. &wResTab,
  673. sizeof(wResTab),
  674. &lpNumberOfBytes
  675. );
  676. if ( !b || lpNumberOfBytes != sizeof(wResTab) ) goto punt;
  677. // Get the 1st byte of the resident names table (1st byte of module name)
  678. lpThisModuleName = InternalGetPointer(
  679. hProcess,
  680. wModHandle,
  681. wResTab,
  682. TRUE );
  683. if ( lpThisModuleName == (DWORD)NULL ) goto punt;
  684. // PASCAL string (1st byte is length), read the byte.
  685. b = ReadProcessMemory(
  686. hProcess,
  687. (LPVOID)lpThisModuleName,
  688. &cLength,
  689. sizeof(cLength),
  690. &lpNumberOfBytes
  691. );
  692. if ( !b || lpNumberOfBytes != sizeof(cLength) ) goto punt;
  693. if ( cLength > MAX_MODULE_NAME_LENGTH ) goto punt;
  694. // Now go read the text of the name
  695. lpThisModuleName += 1;
  696. b = ReadProcessMemory(
  697. hProcess,
  698. (LPVOID)lpThisModuleName,
  699. &chName,
  700. cLength,
  701. &lpNumberOfBytes
  702. );
  703. if ( !b || lpNumberOfBytes != (DWORD)cLength ) goto punt;
  704. chName[cLength] = '\0'; // Nul terminate it
  705. // Grab out the path name too!
  706. lpPath = InternalGetPointer(
  707. hProcess,
  708. wModHandle,
  709. NE_PATHOFFSET,
  710. TRUE );
  711. if ( lpPath == (DWORD)NULL ) goto punt;
  712. b = ReadProcessMemory(
  713. hProcess,
  714. (LPVOID)lpPath,
  715. &wPathOffset,
  716. sizeof(wPathOffset),
  717. &lpNumberOfBytes
  718. );
  719. if ( !b || lpNumberOfBytes != sizeof(wPathOffset) ) goto punt;
  720. // Get the 1st byte of the path name
  721. lpThisModuleName = InternalGetPointer(
  722. hProcess,
  723. wModHandle,
  724. wPathOffset,
  725. TRUE );
  726. if ( lpThisModuleName == (DWORD)NULL ) goto punt;
  727. // PASCAL string (1st byte is length), read the byte.
  728. b = ReadProcessMemory(
  729. hProcess,
  730. (LPVOID)lpThisModuleName,
  731. &cPath,
  732. sizeof(cPath),
  733. &lpNumberOfBytes
  734. );
  735. if ( !b || lpNumberOfBytes != sizeof(cPath) ) goto punt;
  736. if ( cPath > MAX_MODULE_NAME_LENGTH ) goto punt;
  737. lpThisModuleName += 8; // 1st 8 characters are ignored
  738. cPath -= 8;
  739. // Now go read the text of the name
  740. b = ReadProcessMemory(
  741. hProcess,
  742. (LPVOID)lpThisModuleName,
  743. &chPath,
  744. cPath,
  745. &lpNumberOfBytes
  746. );
  747. if ( !b || lpNumberOfBytes != (DWORD)cPath ) goto punt;
  748. chPath[cPath] = '\0'; // Nul terminate it
  749. // Ok, we found the module we need, now grab the right selector for the
  750. // segment number passed in.
  751. lpThisModulecSeg = InternalGetPointer(
  752. hProcess,
  753. wModHandle,
  754. NE_CSEG,
  755. TRUE );
  756. if ( lpThisModulecSeg == (DWORD)NULL ) goto punt;
  757. b = ReadProcessMemory(
  758. hProcess,
  759. (LPVOID)lpThisModulecSeg,
  760. &cSeg,
  761. sizeof(cSeg),
  762. &lpNumberOfBytes
  763. );
  764. if ( !b || lpNumberOfBytes != sizeof(cSeg) ) goto punt;
  765. // Read the segment table pointer for this module
  766. lpThisModuleSegTab = InternalGetPointer(
  767. hProcess,
  768. wModHandle,
  769. NE_SEGTAB,
  770. TRUE );
  771. if ( lpThisModuleSegTab == (DWORD)NULL ) goto punt;
  772. b = ReadProcessMemory(
  773. hProcess,
  774. (LPVOID)lpThisModuleSegTab,
  775. &wSegTab,
  776. sizeof(wSegTab),
  777. &lpNumberOfBytes
  778. );
  779. if ( !b || lpNumberOfBytes != sizeof(wSegTab) ) goto punt;
  780. // Loop through all of the segments for this module trying to find
  781. // one with the right handle.
  782. iSeg = 0;
  783. wSelector &= 0xFFF8;
  784. while ( iSeg < cSeg ) {
  785. lpThisSegHandle = InternalGetPointer(
  786. hProcess,
  787. wModHandle,
  788. wSegTab+iSeg*NEW_SEG1_SIZE+NS_HANDLE,
  789. TRUE );
  790. if ( lpThisSegHandle == (DWORD)NULL ) goto punt;
  791. b = ReadProcessMemory(
  792. hProcess,
  793. (LPVOID)lpThisSegHandle,
  794. &wHandle,
  795. sizeof(wHandle),
  796. &lpNumberOfBytes
  797. );
  798. if ( !b || lpNumberOfBytes != sizeof(wHandle) ) goto punt;
  799. wHandle &= 0xFFF8;
  800. if ( wHandle == (WORD)wSelector ) {
  801. break;
  802. }
  803. iSeg++;
  804. }
  805. if ( iSeg >= cSeg ) goto punt; // Wasn't found at all!
  806. if ( lpModuleName && strlen(chName)+1 > nNameSize ) goto punt;
  807. if ( lpModulePath && strlen(chPath)+1 > nPathSize ) goto punt;
  808. if ( lpModuleName != NULL ) strcpy( lpModuleName, chName );
  809. if ( lpModulePath != NULL ) strcpy( lpModulePath, chPath );
  810. if ( lpSegmentNumber != NULL ) *lpSegmentNumber = iSeg;
  811. fResult = TRUE;
  812. punt:
  813. #endif
  814. return( fResult );
  815. }
  816. //----------------------------------------------------------------------------
  817. // VDMGetModuleSelector()
  818. //
  819. // Interface to determine the selector for a given module's segment.
  820. // This is useful during debugging to associate code and data segments
  821. // with symbols. The symbol lookup should be done by the debugger, to
  822. // determine the module and segment number, which are then passed to us
  823. // and we determine the current selector for that module's segment.
  824. //
  825. // Again, this code was adapted from the Win 3.1 ToolHelp DLL
  826. //
  827. //----------------------------------------------------------------------------
  828. BOOL
  829. WINAPI
  830. VDMGetModuleSelector(
  831. HANDLE hProcess,
  832. HANDLE hUnused,
  833. UINT uSegmentNumber,
  834. LPSTR lpModuleName,
  835. LPWORD lpSelector
  836. ) {
  837. BOOL b;
  838. DWORD lpNumberOfBytes;
  839. BOOL fResult;
  840. WORD wModHandle;
  841. DWORD lpModuleHead;
  842. DWORD lpThisModuleName;
  843. DWORD lpThisModuleNext;
  844. DWORD lpThisModuleResTab;
  845. DWORD lpThisModulecSeg;
  846. DWORD lpThisModuleSegTab;
  847. DWORD lpThisSegHandle;
  848. WORD wResTab;
  849. UCHAR cLength;
  850. WORD cSeg;
  851. WORD wSegTab;
  852. WORD wHandle;
  853. // CHAR chName[MAX_MODULE_NAME_LENGTH];
  854. UNREFERENCED_PARAMETER(hUnused);
  855. *lpSelector = 0;
  856. fResult = FALSE;
  857. #if 0
  858. if ( wKernelSeg == 0 ) {
  859. return( FALSE );
  860. }
  861. lpModuleHead = InternalGetPointer(
  862. hProcess,
  863. wKernelSeg,
  864. dwOffsetTHHOOK + TOOL_HMODFIRST,
  865. TRUE );
  866. if ( lpModuleHead == (DWORD)NULL ) goto punt;
  867. // lpModuleHead is a pointer into kernels data segment. It points to the
  868. // head of the module list (a chain of near pointers).
  869. b = ReadProcessMemory(
  870. hProcess,
  871. (LPVOID)lpModuleHead,
  872. &wModHandle,
  873. sizeof(wModHandle),
  874. &lpNumberOfBytes
  875. );
  876. if ( !b || lpNumberOfBytes != sizeof(wModHandle) ) goto punt;
  877. while( wModHandle != (WORD)0 ) {
  878. wModHandle |= 1;
  879. // Name is the first name in the resident names table
  880. lpThisModuleResTab = InternalGetPointer(
  881. hProcess,
  882. wModHandle,
  883. NE_RESTAB,
  884. TRUE );
  885. if ( lpThisModuleResTab == (DWORD)NULL ) goto punt;
  886. b = ReadProcessMemory(
  887. hProcess,
  888. (LPVOID)lpThisModuleResTab,
  889. &wResTab,
  890. sizeof(wResTab),
  891. &lpNumberOfBytes
  892. );
  893. if ( !b || lpNumberOfBytes != sizeof(wResTab) ) goto punt;
  894. // Get the 1st byte of the resident names table (1st byte of module name)
  895. lpThisModuleName = InternalGetPointer(
  896. hProcess,
  897. wModHandle,
  898. wResTab,
  899. TRUE );
  900. if ( lpThisModuleName == (DWORD)NULL ) goto punt;
  901. // PASCAL string (1st byte is length), read the byte.
  902. b = ReadProcessMemory(
  903. hProcess,
  904. (LPVOID)lpThisModuleName,
  905. &cLength,
  906. sizeof(cLength),
  907. &lpNumberOfBytes
  908. );
  909. if ( !b || lpNumberOfBytes != sizeof(cLength) ) goto punt;
  910. if ( cLength > MAX_MODULE_NAME_LENGTH ) goto punt;
  911. lpThisModuleName += 1;
  912. // Now go read the text of the name
  913. b = ReadProcessMemory(
  914. hProcess,
  915. (LPVOID)lpThisModuleName,
  916. &chName,
  917. cLength,
  918. &lpNumberOfBytes
  919. );
  920. if ( !b || lpNumberOfBytes != (DWORD)cLength ) goto punt;
  921. chName[cLength] = '\0'; // Nul terminate it
  922. if ( _stricmp(chName, lpModuleName) == 0 ) {
  923. // Found the name which matches!
  924. break;
  925. }
  926. // Move to the next module in the list.
  927. lpThisModuleNext = InternalGetPointer(
  928. hProcess,
  929. wModHandle,
  930. NE_CBENTTAB,
  931. TRUE );
  932. if ( lpThisModuleNext == (DWORD)NULL ) goto punt;
  933. b = ReadProcessMemory(
  934. hProcess,
  935. (LPVOID)lpThisModuleNext,
  936. &wModHandle,
  937. sizeof(wModHandle),
  938. &lpNumberOfBytes
  939. );
  940. if ( !b || lpNumberOfBytes != sizeof(wModHandle) ) goto punt;
  941. }
  942. if ( wModHandle == (WORD)0 ) {
  943. goto punt;
  944. }
  945. // Ok, we found the module we need, now grab the right selector for the
  946. // segment number passed in.
  947. lpThisModulecSeg = InternalGetPointer(
  948. hProcess,
  949. wModHandle,
  950. NE_CSEG,
  951. TRUE );
  952. if ( lpThisModulecSeg == (DWORD)NULL ) goto punt;
  953. b = ReadProcessMemory(
  954. hProcess,
  955. (LPVOID)lpThisModulecSeg,
  956. &cSeg,
  957. sizeof(cSeg),
  958. &lpNumberOfBytes
  959. );
  960. if ( !b || lpNumberOfBytes != sizeof(cSeg) ) goto punt;
  961. if ( uSegmentNumber > (DWORD)cSeg ) goto punt;
  962. // Read the segment table pointer for this module
  963. lpThisModuleSegTab = InternalGetPointer(
  964. hProcess,
  965. wModHandle,
  966. NE_SEGTAB,
  967. TRUE );
  968. if ( lpThisModuleSegTab == (DWORD)NULL ) goto punt;
  969. b = ReadProcessMemory(
  970. hProcess,
  971. (LPVOID)lpThisModuleSegTab,
  972. &wSegTab,
  973. sizeof(wSegTab),
  974. &lpNumberOfBytes
  975. );
  976. if ( !b || lpNumberOfBytes != sizeof(wSegTab) ) goto punt;
  977. lpThisSegHandle = InternalGetPointer(
  978. hProcess,
  979. wModHandle,
  980. wSegTab+(WORD)uSegmentNumber*NEW_SEG1_SIZE+NS_HANDLE,
  981. TRUE );
  982. if ( lpThisSegHandle == (DWORD)NULL ) goto punt;
  983. b = ReadProcessMemory(
  984. hProcess,
  985. (LPVOID)lpThisSegHandle,
  986. &wHandle,
  987. sizeof(wHandle),
  988. &lpNumberOfBytes
  989. );
  990. if ( !b || lpNumberOfBytes != sizeof(wHandle) ) goto punt;
  991. *lpSelector = (WORD)(wHandle | 1);
  992. fResult = TRUE;
  993. punt:
  994. #endif
  995. return( fResult );
  996. }
  997. DWORD
  998. WINAPI
  999. VDMGetDbgFlags(
  1000. HANDLE hProcess
  1001. )
  1002. {
  1003. ULONG NtvdmState;
  1004. ULONG VdmDbgFlags;
  1005. BOOL b;
  1006. DWORD lpNumberOfBytes;
  1007. //
  1008. // Merge in the two places where our flags are kept
  1009. //
  1010. b = ReadProcessMemory(hProcess, lpNtvdmState, &NtvdmState,
  1011. sizeof(NtvdmState), &lpNumberOfBytes);
  1012. if ( !b || lpNumberOfBytes != sizeof(NtvdmState) ) {
  1013. return 0;
  1014. }
  1015. b = ReadProcessMemory(hProcess, lpVdmDbgFlags, &VdmDbgFlags,
  1016. sizeof(VdmDbgFlags), &lpNumberOfBytes);
  1017. if ( !b || lpNumberOfBytes != sizeof(VdmDbgFlags) ) {
  1018. return 0;
  1019. }
  1020. return ((NtvdmState & (VDMDBG_BREAK_EXCEPTIONS | VDMDBG_BREAK_DEBUGGER)) |
  1021. (VdmDbgFlags & ~(VDMDBG_BREAK_EXCEPTIONS | VDMDBG_BREAK_DEBUGGER)));
  1022. }
  1023. BOOL
  1024. WINAPI
  1025. VDMSetDbgFlags(
  1026. HANDLE hProcess,
  1027. DWORD VdmDbgFlags
  1028. )
  1029. {
  1030. ULONG NtvdmState;
  1031. BOOL b;
  1032. DWORD lpNumberOfBytes;
  1033. //
  1034. // The flags are spread out in two places, so split off the appropriate
  1035. // bits and write them separately.
  1036. //
  1037. b = ReadProcessMemory(hProcess, lpNtvdmState, &NtvdmState,
  1038. sizeof(NtvdmState), &lpNumberOfBytes);
  1039. if ( !b || lpNumberOfBytes != sizeof(NtvdmState) ) {
  1040. return FALSE;
  1041. }
  1042. NtvdmState &= ~(VDMDBG_BREAK_EXCEPTIONS | VDMDBG_BREAK_DEBUGGER);
  1043. NtvdmState |= VdmDbgFlags & (VDMDBG_BREAK_EXCEPTIONS | VDMDBG_BREAK_DEBUGGER);
  1044. b = WriteProcessMemory(hProcess, lpNtvdmState, &NtvdmState,
  1045. sizeof(NtvdmState), &lpNumberOfBytes);
  1046. if ( !b || lpNumberOfBytes != sizeof(NtvdmState) ) {
  1047. return FALSE;
  1048. }
  1049. VdmDbgFlags &= ~(VDMDBG_BREAK_EXCEPTIONS | VDMDBG_BREAK_DEBUGGER);
  1050. b = WriteProcessMemory(hProcess, lpVdmDbgFlags, &VdmDbgFlags,
  1051. sizeof(VdmDbgFlags), &lpNumberOfBytes);
  1052. if ( !b || lpNumberOfBytes != sizeof(VdmDbgFlags) ) {
  1053. return FALSE;
  1054. }
  1055. return TRUE;
  1056. }