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.

353 lines
7.2 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. vdmuserrefs.c
  5. Abstract:
  6. This module contains routines that probe and fetch from the
  7. instruction stream to make the vdm bop support solid.
  8. Author:
  9. Neill Clift (NeillC) 27-Jun-2001
  10. Revision History:
  11. --*/
  12. #include "vdmp.h"
  13. #pragma alloc_text (PAGE, VdmFetchBop1)
  14. #pragma alloc_text (PAGE, VdmFetchBop4)
  15. #pragma alloc_text (PAGE, VdmDispatchOpcodeV86_try)
  16. #pragma alloc_text (PAGE, VdmTibPass1)
  17. #pragma alloc_text (PAGE, VdmDispatchBop)
  18. #pragma alloc_text (PAGE, VdmFetchULONG)
  19. VOID
  20. NTFastDOSIO (
  21. PKTRAP_FRAME TrapFrame,
  22. ULONG IoType
  23. );
  24. ULONG
  25. VdmFetchBop4 (
  26. IN PVOID Pc
  27. )
  28. /*++
  29. Routine Description:
  30. This routine reads up to 4 bytes of bop instruction data
  31. Arguments:
  32. Pc - Program counter fetched from the faulting instruction's trap frame.
  33. Return Value:
  34. ULONG - Up to 4 bytes of instruction stream. Unfetchable bytes are zeroed.
  35. --*/
  36. {
  37. ULONG Value;
  38. ULONG i;
  39. BOOLEAN DidProbe;
  40. DidProbe = FALSE;
  41. try {
  42. ProbeForReadSmallStructure (Pc, sizeof (UCHAR), sizeof (UCHAR));
  43. DidProbe = TRUE;
  44. return *(PULONG)Pc;
  45. } except (EXCEPTION_EXECUTE_HANDLER) {
  46. if (DidProbe == FALSE) {
  47. return 0;
  48. }
  49. }
  50. Value = 0;
  51. try {
  52. for (i = 0; i < sizeof (ULONG); i++) {
  53. Value += (((PUCHAR)Pc)[i])<<(i*8);
  54. }
  55. } except (EXCEPTION_EXECUTE_HANDLER) {
  56. }
  57. return Value;
  58. }
  59. ULONG
  60. VdmFetchULONG (
  61. IN PVOID Pc
  62. )
  63. /*++
  64. Routine Description:
  65. This routine reads 4 bytes from the user address space
  66. Arguments:
  67. Pc - Program counter fetched from the faulting instruction's trap frame.
  68. Return Value:
  69. ULONG - 4 bytes of user mode data
  70. --*/
  71. {
  72. try {
  73. ProbeForReadSmallStructure (Pc, sizeof (ULONG), sizeof (UCHAR));
  74. return *(PULONG)Pc;
  75. } except (EXCEPTION_EXECUTE_HANDLER) {
  76. return 0;
  77. }
  78. }
  79. ULONG
  80. VdmFetchBop1 (
  81. IN PVOID Pc
  82. )
  83. /*++
  84. Routine Description:
  85. This routine reads a single byte of bop instruction data.
  86. Arguments:
  87. Pc - Program counter fetched from the faulting instruction's trap frame
  88. Return Value:
  89. ULONG - 1 byte of instruction stream or zero if unreadable
  90. --*/
  91. {
  92. try {
  93. ProbeForReadSmallStructure (Pc, sizeof (UCHAR), sizeof (UCHAR));
  94. return *(PUCHAR)Pc;
  95. } except (EXCEPTION_EXECUTE_HANDLER) {
  96. return 0;
  97. }
  98. }
  99. ULONG
  100. VdmDispatchOpcodeV86_try (
  101. IN PKTRAP_FRAME TrapFrame
  102. )
  103. /*++
  104. Routine Description:
  105. This routine is just a shell around trap.asm code to handle faulting
  106. instruction stream references. This routines is called at APC_LEVEL
  107. to prevent NtSetContextThread from changing the EIP after its been probed
  108. earlier.
  109. Arguments:
  110. Pc - Program counter fetched from the faulting instructions trap frame
  111. Return Value:
  112. ULONG - 1 byte of instruction stream or zero if unreadable
  113. --*/
  114. {
  115. try {
  116. return Ki386DispatchOpcodeV86 (TrapFrame);
  117. } except (EXCEPTION_EXECUTE_HANDLER) {
  118. return 0;
  119. }
  120. }
  121. ULONG
  122. VdmDispatchOpcode_try (
  123. IN PKTRAP_FRAME TrapFrame
  124. )
  125. /*++
  126. Routine Description:
  127. This routine is just a shell around trap.asm code to handle faulting
  128. instruction stream references. This routines is called at APC_LEVEL
  129. to prevent NtSetContextThread from changing the EIP after its been probed
  130. earlier.
  131. Arguments:
  132. Pc - Program counter fetched from the faulting instructions trap frame
  133. Return Value:
  134. ULONG - 1 byte of instruction stream or zero if unreadable
  135. --*/
  136. {
  137. try {
  138. return Ki386DispatchOpcode (TrapFrame);
  139. } except (EXCEPTION_EXECUTE_HANDLER) {
  140. return 0;
  141. }
  142. }
  143. PVOID
  144. VdmTibPass1 (
  145. IN ULONG Cs,
  146. IN ULONG Eip,
  147. IN ULONG Ebx
  148. )
  149. {
  150. PVDM_TIB VdmTib;
  151. //
  152. // Copy the specified registers to the VDM Tib communication area,
  153. // using proper probing and exception handling.
  154. //
  155. try {
  156. VdmTib = NtCurrentTeb()->Vdm;
  157. ProbeForWrite (VdmTib, sizeof(VDM_TIB), sizeof(UCHAR));
  158. VdmTib->VdmContext.Ebx = Ebx;
  159. VdmTib->VdmContext.Eip = Eip;
  160. VdmTib->VdmContext.SegCs = Cs;
  161. } except (EXCEPTION_EXECUTE_HANDLER) {
  162. return NULL;
  163. }
  164. return VdmTib;
  165. }
  166. #define BOP_INSTRUCTION 0xC4C4
  167. #define SVC_DEMFASTREAD 0x42
  168. #define SVC_DEMFASTWRITE 0x43
  169. #define DOS_BOP 0x50
  170. extern ULONG VdmBopCount;
  171. LOGICAL
  172. VdmDispatchBop (
  173. IN PKTRAP_FRAME TrapFrame
  174. )
  175. /*++
  176. Routine Description:
  177. This routine attempts to decode and execute the user instruction. If
  178. this cannot be done, FALSE is returned and the ntvdm monitor must handle
  179. it.
  180. Arguments:
  181. TrapFrame - Supplies a pointer to register trapframe.
  182. Return Value:
  183. TRUE if the opcode was handled here.
  184. FALSE if not (ie: the caller must reflect this instruction to ntvdm
  185. to handle on behalf of the 16-bit app).
  186. Environment:
  187. Kernel mode, APC_LEVEL.
  188. --*/
  189. {
  190. LOGICAL RetVal;
  191. BOOLEAN GotSelector;
  192. PVDM_TIB VdmTib;
  193. ULONG SegCs;
  194. ULONG LinearEIP;
  195. ULONG Flags;
  196. ULONG Base;
  197. ULONG Limit;
  198. ULONG IoType = 0;
  199. LOGICAL DoFastIo;
  200. if (TrapFrame->EFlags & EFLAGS_V86_MASK) {
  201. SegCs = TrapFrame->SegCs & 0xFFFF;
  202. LinearEIP = (SegCs << 4) + (TrapFrame->Eip & 0xffff);
  203. }
  204. else {
  205. GotSelector = Ki386GetSelectorParameters ((USHORT) TrapFrame->SegCs,
  206. &Flags,
  207. &Base,
  208. &Limit);
  209. if (GotSelector == FALSE) {
  210. return TRUE;
  211. }
  212. LinearEIP = Base + TrapFrame->Eip;
  213. }
  214. DoFastIo = FALSE;
  215. RetVal = TRUE;
  216. try {
  217. ProbeForReadSmallStructure (LinearEIP, sizeof (UCHAR), sizeof (UCHAR));
  218. if (*(PUSHORT)LinearEIP != BOP_INSTRUCTION) {
  219. RetVal = FALSE;
  220. leave;
  221. }
  222. //
  223. // Check the BOP number.
  224. //
  225. if (*(PUCHAR)(LinearEIP + 2) == DOS_BOP) {
  226. if ((*(PUCHAR)(LinearEIP + 3) == SVC_DEMFASTREAD) ||
  227. (*(PUCHAR)(LinearEIP + 3) == SVC_DEMFASTWRITE)) {
  228. //
  229. // Take the fast I/O path.
  230. //
  231. IoType = (ULONG)(*(PUCHAR)(LinearEIP + 3));
  232. DoFastIo = TRUE;
  233. leave;
  234. }
  235. }
  236. VdmBopCount += 1;
  237. VdmTib = NtCurrentTeb()->Vdm;
  238. ProbeForWrite (VdmTib, sizeof(VDM_TIB), sizeof(UCHAR));
  239. VdmTib->EventInfo.Event = VdmBop;
  240. VdmTib->EventInfo.BopNumber = *(PUCHAR)(LinearEIP + 2);
  241. VdmTib->EventInfo.InstructionSize = 3;
  242. VdmEndExecution (TrapFrame, VdmTib);
  243. } except (EXCEPTION_EXECUTE_HANDLER) {
  244. RetVal = FALSE;
  245. NOTHING; // Fall through
  246. }
  247. if (DoFastIo) {
  248. NTFastDOSIO (TrapFrame, IoType);
  249. }
  250. return RetVal;
  251. }