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.

362 lines
8.7 KiB

  1. #include <basedef.h>
  2. #include <vmm.h>
  3. #include <vwin32.h>
  4. #include "ntddpack.h"
  5. #include "except.h"
  6. #include "exvector.h"
  7. #pragma VxD_LOCKED_CODE_SEG
  8. #pragma VxD_LOCKED_DATA_SEG
  9. extern PVOID C_Handle_Trap_1;
  10. extern PVOID C_Handle_Trap_3;
  11. extern DWORD pfnHandler;
  12. extern PVOID pProcessHandle;
  13. BOOL
  14. DriverControl(DWORD dwMessage)
  15. {
  16. switch (dwMessage)
  17. {
  18. case 0:
  19. _asm mov eax, 1
  20. _asm mov esi, offset C_Handle_Trap_1
  21. VMMCall( Hook_PM_Fault );
  22. _asm mov eax, 3
  23. _asm mov esi, offset C_Handle_Trap_3
  24. VMMCall( Hook_PM_Fault );
  25. break;
  26. case 1:
  27. _asm mov eax, 1
  28. _asm mov esi, offset C_Handle_Trap_1
  29. VMMCall( Unhook_PM_Fault );
  30. _asm mov eax, 3
  31. _asm mov esi, offset C_Handle_Trap_3
  32. VMMCall( Unhook_PM_Fault );
  33. break;
  34. default:
  35. 0;
  36. }
  37. return STATUS_SUCCESS;
  38. }
  39. DWORD
  40. _stdcall
  41. DriverIOControl(DWORD dwService,
  42. DWORD dwDDB,
  43. DWORD hDevice,
  44. PDIOCPARAMETERS pDiocParms)
  45. /*++
  46. Routine Description:
  47. This is the dispatch routine for create/open and close requests.
  48. These requests complete successfully.
  49. Arguments:
  50. DeviceObject - Pointer to the device object.
  51. Irp - Pointer to the request packet.
  52. Return Value:
  53. Status is returned.
  54. --*/
  55. {
  56. PVOID pInputParams;
  57. switch ( dwService )
  58. {
  59. case DIOC_OPEN:
  60. //
  61. // Nothing to do
  62. //
  63. break;
  64. case DIOC_CLOSEHANDLE:
  65. //
  66. // If our client for the except handler is going away, initialize the exception handler data
  67. //
  68. if (pProcessHandle == VWIN32_GetCurrentProcessHandle()) {
  69. pfnHandler = 0;
  70. pProcessHandle = 0;
  71. }
  72. break;
  73. case INSTALL_RING_3_HANDLER:
  74. //
  75. // See if we already have a client
  76. //
  77. if (pProcessHandle) {
  78. return STATUS_UNSUCCESSFUL;
  79. }
  80. pProcessHandle = VWIN32_GetCurrentProcessHandle();
  81. //
  82. // Copy the handler into our global
  83. //
  84. pInputParams = (PVOID)(pDiocParms->lpvInBuffer);
  85. _asm mov eax, pInputParams
  86. _asm mov eax, [eax]
  87. _asm mov pfnHandler, eax
  88. break;
  89. default:
  90. //
  91. // Error, Unrecognized IOCTL
  92. //
  93. *(DWORD *)(pDiocParms->lpcbBytesReturned) = 0;
  94. break;
  95. }
  96. return STATUS_SUCCESS;
  97. }
  98. //
  99. // Helper function for maintaining context information between ring levels
  100. //
  101. VOID
  102. FillContextRecord(PCRS pcrs,
  103. PCONTEXT pContext)
  104. {
  105. DWORD dwDebugRegister;
  106. //
  107. // Clear trace and direction flags for the exception dispatcher
  108. //
  109. pcrs->Client_EFlags &= ~(TF_MASK | DF_MASK);
  110. //
  111. // Fill context record
  112. //
  113. pContext->Eax = pcrs->Client_EAX;
  114. pContext->Ebx = pcrs->Client_EBX;
  115. pContext->Ecx = pcrs->Client_ECX;
  116. pContext->Edx = pcrs->Client_EDX;
  117. pContext->Esi = pcrs->Client_ESI;
  118. pContext->Edi = pcrs->Client_EDI;
  119. pContext->Eip = pcrs->Client_EIP;
  120. pContext->Ebp = pcrs->Client_EBP;
  121. pContext->Esp = pcrs->Client_ESP;
  122. pContext->SegGs = pcrs->Client_GS;
  123. pContext->SegFs = pcrs->Client_FS;
  124. pContext->SegEs = pcrs->Client_ES;
  125. pContext->SegDs = pcrs->Client_DS;
  126. pContext->SegCs = pcrs->Client_CS;
  127. pContext->EFlags = pcrs->Client_EFlags;
  128. //
  129. // Store the debug registers
  130. //
  131. _asm mov eax, dr0
  132. _asm mov dwDebugRegister, eax
  133. pContext->Dr0 = dwDebugRegister;
  134. _asm mov eax, dr1
  135. _asm mov dwDebugRegister, eax
  136. pContext->Dr1 = dwDebugRegister;
  137. _asm mov eax, dr2
  138. _asm mov dwDebugRegister, eax
  139. pContext->Dr2 = dwDebugRegister;
  140. _asm mov eax, dr3
  141. _asm mov dwDebugRegister, eax
  142. pContext->Dr3 = dwDebugRegister;
  143. _asm mov eax, dr6
  144. _asm mov dwDebugRegister, eax
  145. pContext->Dr6 = dwDebugRegister;
  146. _asm mov eax, dr7
  147. _asm mov dwDebugRegister, eax
  148. pContext->Dr7 = dwDebugRegister;
  149. //
  150. // This is a full context
  151. //
  152. pContext->ContextFlags = (DWORD)-1;
  153. }
  154. VOID
  155. RestorePCRS(PCRS pcrs,
  156. PCONTEXT pContext)
  157. {
  158. DWORD dwDebugRegister;
  159. //
  160. // Restore pcrs
  161. //
  162. pcrs->Client_EAX = pContext->Eax;
  163. pcrs->Client_EBX = pContext->Ebx;
  164. pcrs->Client_ECX = pContext->Ecx;
  165. pcrs->Client_EDX = pContext->Edx;
  166. pcrs->Client_ESI = pContext->Esi;
  167. pcrs->Client_EDI = pContext->Edi;
  168. pcrs->Client_EIP = pContext->Eip;
  169. pcrs->Client_EBP = pContext->Ebp;
  170. pcrs->Client_ESP = pContext->Esp;
  171. pcrs->Client_GS = pContext->SegGs;
  172. pcrs->Client_FS = pContext->SegFs;
  173. pcrs->Client_ES = pContext->SegEs;
  174. pcrs->Client_DS = pContext->SegDs;
  175. pcrs->Client_CS = pContext->SegCs;
  176. pcrs->Client_EFlags = pContext->EFlags;
  177. //
  178. // Restore the debug registers
  179. //
  180. dwDebugRegister = pContext->Dr0;
  181. _asm mov eax, dwDebugRegister
  182. _asm mov dr0, eax
  183. dwDebugRegister = pContext->Dr1;
  184. _asm mov eax, dwDebugRegister
  185. _asm mov dr1, eax
  186. dwDebugRegister = pContext->Dr2;
  187. _asm mov eax, dwDebugRegister
  188. _asm mov dr2, eax
  189. dwDebugRegister = pContext->Dr3;
  190. _asm mov eax, dwDebugRegister
  191. _asm mov dr3, eax
  192. dwDebugRegister = pContext->Dr6;
  193. _asm mov eax, dwDebugRegister
  194. _asm mov dr6, eax
  195. dwDebugRegister = pContext->Dr7;
  196. _asm mov eax, dwDebugRegister
  197. _asm mov dr7, eax
  198. }
  199. //
  200. // Exception dispatching routine
  201. //
  202. BOOL
  203. __cdecl
  204. C_Trap_Exception_Handler(ULONG ExceptionNumber,
  205. PCRS pcrs)
  206. {
  207. DWORD dwException = ExceptionNumber >> 2;
  208. PEXCEPTION_RECORD pExceptionRecord;
  209. PCONTEXT pContextRecord;
  210. PSTACKFRAME pStackFrame;
  211. ULONG Result;
  212. ULONG StackTop;
  213. ULONG Length;
  214. //
  215. // Make sure our current thread is Win32
  216. //
  217. if (FALSE == VWIN32_IsClientWin32()) {
  218. return FALSE;
  219. }
  220. //
  221. // Make sure we only handle exceptions for our controlling "process"
  222. //
  223. if (pProcessHandle != VWIN32_GetCurrentProcessHandle()) {
  224. return FALSE;
  225. }
  226. //
  227. // If selector isn't flat, we can't handle this exception
  228. //
  229. if ((pcrs->Client_SS != pcrs->Client_DS) ||
  230. (pcrs->Client_SS != pcrs->Client_ES)){
  231. return FALSE;
  232. }
  233. //
  234. // See if this is a context set
  235. //
  236. if (SET_CONTEXT == *(DWORD *)(pcrs->Client_EIP)) {
  237. //
  238. // Set the context data
  239. //
  240. pContextRecord = *(DWORD *)(pcrs->Client_ESP + 0x10);
  241. RestorePCRS(pcrs,
  242. pContextRecord);
  243. return TRUE;
  244. }
  245. //
  246. // Move stack pointer down one context record length
  247. //
  248. StackTop = (pcrs->Client_ESP & ~3) - ((sizeof(CONTEXT) + 3) & ~3);
  249. pContextRecord = (PCONTEXT) StackTop;
  250. FillContextRecord(pcrs,
  251. pContextRecord);
  252. //
  253. // Adjust eip for breakpoint exceptions
  254. //
  255. if (3 == dwException) {
  256. pContextRecord->Eip -= 1;
  257. }
  258. Length = (sizeof(EXCEPTION_RECORD) - (EXCEPTION_MAXIMUM_PARAMETERS - 2) *
  259. sizeof(*pExceptionRecord->ExceptionInformation) + 3) & ~3;
  260. //
  261. // We are now at the Exception Record
  262. //
  263. StackTop = StackTop - Length;
  264. pExceptionRecord = (PEXCEPTION_RECORD)StackTop;
  265. pExceptionRecord->ExceptionFlags = 0;
  266. pExceptionRecord->ExceptionRecord = 0;
  267. pExceptionRecord->ExceptionAddress = (PVOID)pcrs->Client_EIP;
  268. pExceptionRecord->NumberParameters = 0;
  269. switch (dwException) {
  270. case 1:
  271. pExceptionRecord->ExceptionCode = STATUS_SINGLE_STEP;
  272. break;
  273. case 3:
  274. pExceptionRecord->ExceptionCode = STATUS_BREAKPOINT;
  275. pExceptionRecord->NumberParameters = 1;
  276. pExceptionRecord->ExceptionInformation[0] = BREAKPOINT_BREAK;
  277. pExceptionRecord->ExceptionAddress = (PVOID)pContextRecord->Eip;
  278. break;
  279. default:
  280. 0;
  281. }
  282. //
  283. // Setup the exception call frame
  284. //
  285. StackTop = StackTop - sizeof(STACKFRAME);
  286. pStackFrame = (PSTACKFRAME) StackTop;
  287. pStackFrame->ExceptPointers.ExceptionRecord = pExceptionRecord;
  288. pStackFrame->ExceptPointers.ContextRecord = pContextRecord;
  289. pStackFrame->pExceptPointers = (PVOID)(StackTop + 0x08);
  290. pStackFrame->RetAddress = (PVOID)0xffecbad7; // App will page fault out if unexpected exception occurs
  291. //
  292. // Transfer control to Ring 3 handler
  293. //
  294. pcrs->Client_ESP = (ULONG)pStackFrame;
  295. pcrs->Client_EIP = (ULONG)pfnHandler;
  296. return TRUE;
  297. SkipHandler:
  298. //
  299. // We didn't process the exception give it to the next handler
  300. //
  301. return FALSE;
  302. }