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.

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