xref: /reactos/ntoskrnl/vdm/vdmexec.c (revision c2c66aff)
1*c2c66affSColin Finck /*
2*c2c66affSColin Finck  * PROJECT:         ReactOS Kernel
3*c2c66affSColin Finck  * LICENSE:         GPL - See COPYING in the top level directory
4*c2c66affSColin Finck  * FILE:            ntoskrnl/vdm/vdmexec.c
5*c2c66affSColin Finck  * PURPOSE:         Support for executing VDM code and context swapping.
6*c2c66affSColin Finck  * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
7*c2c66affSColin Finck  */
8*c2c66affSColin Finck 
9*c2c66affSColin Finck /* INCLUDES *****************************************************************/
10*c2c66affSColin Finck 
11*c2c66affSColin Finck #include <ntoskrnl.h>
12*c2c66affSColin Finck #define NDEBUG
13*c2c66affSColin Finck #include <debug.h>
14*c2c66affSColin Finck 
15*c2c66affSColin Finck /* GLOBALS *******************************************************************/
16*c2c66affSColin Finck 
17*c2c66affSColin Finck ULONG VdmBopCount;
18*c2c66affSColin Finck 
19*c2c66affSColin Finck /* FUNCTIONS *****************************************************************/
20*c2c66affSColin Finck 
21*c2c66affSColin Finck NTSTATUS
22*c2c66affSColin Finck NTAPI
VdmpGetVdmTib(OUT PVDM_TIB * VdmTib)23*c2c66affSColin Finck VdmpGetVdmTib(OUT PVDM_TIB *VdmTib)
24*c2c66affSColin Finck {
25*c2c66affSColin Finck     PVDM_TIB Tib;
26*c2c66affSColin Finck     PAGED_CODE();
27*c2c66affSColin Finck 
28*c2c66affSColin Finck     /* Assume vailure */
29*c2c66affSColin Finck     *VdmTib = NULL;
30*c2c66affSColin Finck 
31*c2c66affSColin Finck     /* Get the current TIB */
32*c2c66affSColin Finck     Tib = NtCurrentTeb()->Vdm;
33*c2c66affSColin Finck     if (!Tib) return STATUS_INVALID_SYSTEM_SERVICE;
34*c2c66affSColin Finck 
35*c2c66affSColin Finck     /* Validate the size */
36*c2c66affSColin Finck     if (Tib->Size != sizeof(VDM_TIB)) return STATUS_INVALID_SYSTEM_SERVICE;
37*c2c66affSColin Finck 
38*c2c66affSColin Finck     /* Return it */
39*c2c66affSColin Finck     *VdmTib = Tib;
40*c2c66affSColin Finck     return STATUS_SUCCESS;
41*c2c66affSColin Finck }
42*c2c66affSColin Finck 
43*c2c66affSColin Finck VOID
44*c2c66affSColin Finck NTAPI
VdmSwapContext(IN PKTRAP_FRAME TrapFrame,IN PCONTEXT OutContext,IN PCONTEXT InContext)45*c2c66affSColin Finck VdmSwapContext(IN PKTRAP_FRAME TrapFrame,
46*c2c66affSColin Finck                IN PCONTEXT OutContext,
47*c2c66affSColin Finck                IN PCONTEXT InContext)
48*c2c66affSColin Finck {
49*c2c66affSColin Finck     ULONG EFlags, OldEFlags;
50*c2c66affSColin Finck 
51*c2c66affSColin Finck     /* Make sure that we're at APC_LEVEL and that this is a valid frame */
52*c2c66affSColin Finck     ASSERT(KeGetCurrentIrql() == APC_LEVEL);
53*c2c66affSColin Finck     ASSERT(TrapFrame->DbgArgMark == 0xBADB0D00);
54*c2c66affSColin Finck 
55*c2c66affSColin Finck     /* Check if this is a V86 frame */
56*c2c66affSColin Finck     if (TrapFrame->EFlags & EFLAGS_V86_MASK)
57*c2c66affSColin Finck     {
58*c2c66affSColin Finck         /* Copy segment registers */
59*c2c66affSColin Finck         OutContext->SegGs = TrapFrame->V86Gs;
60*c2c66affSColin Finck         OutContext->SegFs = TrapFrame->V86Fs;
61*c2c66affSColin Finck         OutContext->SegEs = TrapFrame->V86Es;
62*c2c66affSColin Finck         OutContext->SegDs = TrapFrame->V86Ds;
63*c2c66affSColin Finck     }
64*c2c66affSColin Finck     else if (TrapFrame->SegCs != (KGDT_R3_CODE | RPL_MASK))
65*c2c66affSColin Finck     {
66*c2c66affSColin Finck         /* This was kernel mode, copy segment registers */
67*c2c66affSColin Finck         OutContext->SegGs = TrapFrame->SegGs;
68*c2c66affSColin Finck         OutContext->SegFs = TrapFrame->SegFs;
69*c2c66affSColin Finck         OutContext->SegEs = TrapFrame->SegEs;
70*c2c66affSColin Finck         OutContext->SegDs = TrapFrame->SegDs;
71*c2c66affSColin Finck     }
72*c2c66affSColin Finck 
73*c2c66affSColin Finck     /* Copy CS and SS */
74*c2c66affSColin Finck     OutContext->SegCs = TrapFrame->SegCs;
75*c2c66affSColin Finck     OutContext->SegSs = TrapFrame->HardwareSegSs;
76*c2c66affSColin Finck 
77*c2c66affSColin Finck     /* Copy general purpose registers */
78*c2c66affSColin Finck     OutContext->Eax = TrapFrame->Eax;
79*c2c66affSColin Finck     OutContext->Ebx = TrapFrame->Ebx;
80*c2c66affSColin Finck     OutContext->Ecx = TrapFrame->Ecx;
81*c2c66affSColin Finck     OutContext->Edx = TrapFrame->Edx;
82*c2c66affSColin Finck     OutContext->Esi = TrapFrame->Esi;
83*c2c66affSColin Finck     OutContext->Edi = TrapFrame->Edi;
84*c2c66affSColin Finck 
85*c2c66affSColin Finck     /* Copy stack and counter */
86*c2c66affSColin Finck     OutContext->Ebp = TrapFrame->Ebp;
87*c2c66affSColin Finck     OutContext->Esp = TrapFrame->HardwareEsp;
88*c2c66affSColin Finck     OutContext->Eip = TrapFrame->Eip;
89*c2c66affSColin Finck 
90*c2c66affSColin Finck     /* Finally the flags */
91*c2c66affSColin Finck     OutContext->EFlags = TrapFrame->EFlags;
92*c2c66affSColin Finck 
93*c2c66affSColin Finck     /* Now copy from the in frame to the trap frame */
94*c2c66affSColin Finck     TrapFrame->SegCs = InContext->SegCs;
95*c2c66affSColin Finck     TrapFrame->HardwareSegSs = InContext->SegSs;
96*c2c66affSColin Finck 
97*c2c66affSColin Finck     /* Copy the general purpose registers */
98*c2c66affSColin Finck     TrapFrame->Eax = InContext->Eax;
99*c2c66affSColin Finck     TrapFrame->Ebx = InContext->Ebx;
100*c2c66affSColin Finck     TrapFrame->Ecx = InContext->Ecx;
101*c2c66affSColin Finck     TrapFrame->Edx = InContext->Edx;
102*c2c66affSColin Finck     TrapFrame->Esi = InContext->Esi;
103*c2c66affSColin Finck     TrapFrame->Edi = InContext->Edi;
104*c2c66affSColin Finck 
105*c2c66affSColin Finck     /* Copy the stack and counter */
106*c2c66affSColin Finck     TrapFrame->Ebp = InContext->Ebp;
107*c2c66affSColin Finck     TrapFrame->HardwareEsp = InContext->Esp;
108*c2c66affSColin Finck     TrapFrame->Eip = InContext->Eip;
109*c2c66affSColin Finck 
110*c2c66affSColin Finck     /* Check if the context is from V86 */
111*c2c66affSColin Finck     EFlags = InContext->EFlags;
112*c2c66affSColin Finck     if (EFlags & EFLAGS_V86_MASK)
113*c2c66affSColin Finck     {
114*c2c66affSColin Finck         /* Sanitize the flags for V86 */
115*c2c66affSColin Finck         EFlags &= KeI386EFlagsAndMaskV86;
116*c2c66affSColin Finck         EFlags |= KeI386EFlagsOrMaskV86;
117*c2c66affSColin Finck     }
118*c2c66affSColin Finck     else
119*c2c66affSColin Finck     {
120*c2c66affSColin Finck         /* Add RPL_MASK to segments */
121*c2c66affSColin Finck         TrapFrame->SegCs |= RPL_MASK;
122*c2c66affSColin Finck         TrapFrame->HardwareSegSs |= RPL_MASK;
123*c2c66affSColin Finck 
124*c2c66affSColin Finck         /* Check for bogus CS */
125*c2c66affSColin Finck         if (TrapFrame->SegCs < KGDT_R0_CODE)
126*c2c66affSColin Finck         {
127*c2c66affSColin Finck             /* Set user-mode */
128*c2c66affSColin Finck             TrapFrame->SegCs = KGDT_R3_CODE | RPL_MASK;
129*c2c66affSColin Finck         }
130*c2c66affSColin Finck 
131*c2c66affSColin Finck         /* Sanitize flags and add interrupt mask */
132*c2c66affSColin Finck         EFlags &= EFLAGS_USER_SANITIZE;
133*c2c66affSColin Finck         EFlags |=EFLAGS_INTERRUPT_MASK;
134*c2c66affSColin Finck     }
135*c2c66affSColin Finck 
136*c2c66affSColin Finck     /* Save the new eflags */
137*c2c66affSColin Finck     OldEFlags = TrapFrame->EFlags;
138*c2c66affSColin Finck     TrapFrame->EFlags = EFlags;
139*c2c66affSColin Finck 
140*c2c66affSColin Finck     /* Check if we need to fixup ESP0 */
141*c2c66affSColin Finck     if ((OldEFlags ^ EFlags) & EFLAGS_V86_MASK)
142*c2c66affSColin Finck     {
143*c2c66affSColin Finck         /* Fix it up */
144*c2c66affSColin Finck         Ki386AdjustEsp0(TrapFrame);
145*c2c66affSColin Finck     }
146*c2c66affSColin Finck 
147*c2c66affSColin Finck     /* Check if this is a V86 context */
148*c2c66affSColin Finck     if (InContext->EFlags & EFLAGS_V86_MASK)
149*c2c66affSColin Finck     {
150*c2c66affSColin Finck         /* Copy VDM segments */
151*c2c66affSColin Finck         TrapFrame->V86Gs = InContext->SegGs;
152*c2c66affSColin Finck         TrapFrame->V86Fs = InContext->SegFs;
153*c2c66affSColin Finck         TrapFrame->V86Es = InContext->SegEs;
154*c2c66affSColin Finck         TrapFrame->V86Ds = InContext->SegDs;
155*c2c66affSColin Finck     }
156*c2c66affSColin Finck     else
157*c2c66affSColin Finck     {
158*c2c66affSColin Finck         /* Copy monitor segments */
159*c2c66affSColin Finck         TrapFrame->SegGs = InContext->SegGs;
160*c2c66affSColin Finck         TrapFrame->SegFs = InContext->SegFs;
161*c2c66affSColin Finck         TrapFrame->SegEs = InContext->SegEs;
162*c2c66affSColin Finck         TrapFrame->SegDs = InContext->SegDs;
163*c2c66affSColin Finck     }
164*c2c66affSColin Finck 
165*c2c66affSColin Finck     /* Clear the exception list and return */
166*c2c66affSColin Finck     TrapFrame->ExceptionList = EXCEPTION_CHAIN_END;
167*c2c66affSColin Finck }
168*c2c66affSColin Finck 
169*c2c66affSColin Finck NTSTATUS
170*c2c66affSColin Finck NTAPI
VdmpStartExecution(VOID)171*c2c66affSColin Finck VdmpStartExecution(VOID)
172*c2c66affSColin Finck {
173*c2c66affSColin Finck     PETHREAD Thread = PsGetCurrentThread();
174*c2c66affSColin Finck     PKTRAP_FRAME VdmFrame;
175*c2c66affSColin Finck     NTSTATUS Status;
176*c2c66affSColin Finck     PVDM_TIB VdmTib;
177*c2c66affSColin Finck     BOOLEAN Interrupts;
178*c2c66affSColin Finck     KIRQL OldIrql;
179*c2c66affSColin Finck     CONTEXT VdmContext;
180*c2c66affSColin Finck     PAGED_CODE();
181*c2c66affSColin Finck 
182*c2c66affSColin Finck     /* Get the thread's VDM frame and TIB */
183*c2c66affSColin Finck     VdmFrame = (PVOID)((ULONG_PTR)Thread->Tcb.InitialStack -
184*c2c66affSColin Finck                                   sizeof(FX_SAVE_AREA) -
185*c2c66affSColin Finck                                   sizeof(KTRAP_FRAME));
186*c2c66affSColin Finck     Status = VdmpGetVdmTib(&VdmTib);
187*c2c66affSColin Finck     if (!NT_SUCCESS(Status)) return STATUS_INVALID_SYSTEM_SERVICE;
188*c2c66affSColin Finck 
189*c2c66affSColin Finck     /* Go to APC level */
190*c2c66affSColin Finck     KeRaiseIrql(APC_LEVEL, &OldIrql);
191*c2c66affSColin Finck 
192*c2c66affSColin Finck     /* Check if interrupts are enabled */
193*c2c66affSColin Finck     Interrupts = (BOOLEAN)(VdmTib->VdmContext.EFlags & EFLAGS_INTERRUPT_MASK);
194*c2c66affSColin Finck 
195*c2c66affSColin Finck     /* We don't support full VDM yet, this shouldn't happen */
196*c2c66affSColin Finck     ASSERT(*VdmState == 0);
197*c2c66affSColin Finck     ASSERT(VdmTib->VdmContext.EFlags & EFLAGS_V86_MASK);
198*c2c66affSColin Finck 
199*c2c66affSColin Finck     /* Check if VME is supported and V86 mode was enabled */
200*c2c66affSColin Finck     if ((KeI386VirtualIntExtensions) &&
201*c2c66affSColin Finck         (VdmTib->VdmContext.EFlags & EFLAGS_V86_MASK))
202*c2c66affSColin Finck     {
203*c2c66affSColin Finck         /* Check if interrupts are enabled */
204*c2c66affSColin Finck         if (Interrupts)
205*c2c66affSColin Finck         {
206*c2c66affSColin Finck             /* Set fake IF flag */
207*c2c66affSColin Finck             VdmTib->VdmContext.EFlags |= EFLAGS_VIF;
208*c2c66affSColin Finck         }
209*c2c66affSColin Finck         else
210*c2c66affSColin Finck         {
211*c2c66affSColin Finck             /* Remove fake IF flag, turn on real IF flag */
212*c2c66affSColin Finck             VdmTib->VdmContext.EFlags &= ~EFLAGS_VIF;
213*c2c66affSColin Finck             VdmTib->VdmContext.EFlags |= EFLAGS_INTERRUPT_MASK;
214*c2c66affSColin Finck         }
215*c2c66affSColin Finck     }
216*c2c66affSColin Finck     else
217*c2c66affSColin Finck     {
218*c2c66affSColin Finck         /* Set interrupt state in the VDM State */
219*c2c66affSColin Finck         if (VdmTib->VdmContext.EFlags & EFLAGS_INTERRUPT_MASK)
220*c2c66affSColin Finck         {
221*c2c66affSColin Finck             /* Enable them as well */
222*c2c66affSColin Finck             InterlockedOr((PLONG)VdmState, EFLAGS_INTERRUPT_MASK);
223*c2c66affSColin Finck         }
224*c2c66affSColin Finck         else
225*c2c66affSColin Finck         {
226*c2c66affSColin Finck             /* Disable them */
227*c2c66affSColin Finck             InterlockedAnd((PLONG)VdmState, ~EFLAGS_INTERRUPT_MASK);
228*c2c66affSColin Finck         }
229*c2c66affSColin Finck 
230*c2c66affSColin Finck         /* Enable the interrupt flag */
231*c2c66affSColin Finck         VdmTib->VdmContext.EFlags |= EFLAGS_INTERRUPT_MASK;
232*c2c66affSColin Finck     }
233*c2c66affSColin Finck 
234*c2c66affSColin Finck     /*  Get the VDM context and make sure it's not an edited frame */
235*c2c66affSColin Finck     VdmContext = VdmTib->VdmContext;
236*c2c66affSColin Finck     if (!(VdmContext.SegCs & FRAME_EDITED))
237*c2c66affSColin Finck     {
238*c2c66affSColin Finck         /* Fail */
239*c2c66affSColin Finck         KeLowerIrql(OldIrql);
240*c2c66affSColin Finck         return STATUS_INVALID_SYSTEM_SERVICE;
241*c2c66affSColin Finck     }
242*c2c66affSColin Finck 
243*c2c66affSColin Finck     /* Now do the VDM Swap */
244*c2c66affSColin Finck     VdmSwapContext(VdmFrame, &VdmTib->MonitorContext, &VdmContext);
245*c2c66affSColin Finck 
246*c2c66affSColin Finck     /* Lower the IRQL and return EAX */
247*c2c66affSColin Finck     KeLowerIrql(OldIrql);
248*c2c66affSColin Finck     return VdmFrame->Eax;
249*c2c66affSColin Finck }
250*c2c66affSColin Finck 
251*c2c66affSColin Finck VOID
252*c2c66affSColin Finck NTAPI
VdmEndExecution(IN PKTRAP_FRAME TrapFrame,IN PVDM_TIB VdmTib)253*c2c66affSColin Finck VdmEndExecution(IN PKTRAP_FRAME TrapFrame,
254*c2c66affSColin Finck                 IN PVDM_TIB VdmTib)
255*c2c66affSColin Finck {
256*c2c66affSColin Finck     KIRQL OldIrql;
257*c2c66affSColin Finck     CONTEXT Context;
258*c2c66affSColin Finck     PAGED_CODE();
259*c2c66affSColin Finck 
260*c2c66affSColin Finck     /* Sanity check */
261*c2c66affSColin Finck     ASSERT((TrapFrame->EFlags & EFLAGS_V86_MASK) ||
262*c2c66affSColin Finck            (TrapFrame->SegCs != (KGDT_R3_CODE | RPL_MASK)));
263*c2c66affSColin Finck 
264*c2c66affSColin Finck     /* Raise to APC_LEVEL */
265*c2c66affSColin Finck     KeRaiseIrql(APC_LEVEL, &OldIrql);
266*c2c66affSColin Finck 
267*c2c66affSColin Finck     /* Set success */
268*c2c66affSColin Finck     VdmTib->MonitorContext.Eax = STATUS_SUCCESS;
269*c2c66affSColin Finck 
270*c2c66affSColin Finck     /* Make a copy of the monitor context */
271*c2c66affSColin Finck     Context = VdmTib->MonitorContext;
272*c2c66affSColin Finck 
273*c2c66affSColin Finck     /* Check if V86 mode was enabled or the trap was edited */
274*c2c66affSColin Finck     if ((Context.EFlags & EFLAGS_V86_MASK) || (Context.SegCs & FRAME_EDITED))
275*c2c66affSColin Finck     {
276*c2c66affSColin Finck         /* Switch contexts */
277*c2c66affSColin Finck         VdmSwapContext(TrapFrame, &VdmTib->VdmContext, &Context);
278*c2c66affSColin Finck 
279*c2c66affSColin Finck         /* Check if VME is supported and V86 mode was enabled */
280*c2c66affSColin Finck         if ((KeI386VirtualIntExtensions) &&
281*c2c66affSColin Finck             (VdmTib->VdmContext.EFlags & EFLAGS_V86_MASK))
282*c2c66affSColin Finck         {
283*c2c66affSColin Finck             /* Check for VIF (virtual interrupt) flag state */
284*c2c66affSColin Finck             if (VdmTib->VdmContext.EFlags & EFLAGS_VIF)
285*c2c66affSColin Finck             {
286*c2c66affSColin Finck                 /* Set real IF flag */
287*c2c66affSColin Finck                 VdmTib->VdmContext.EFlags |= EFLAGS_INTERRUPT_MASK;
288*c2c66affSColin Finck             }
289*c2c66affSColin Finck             else
290*c2c66affSColin Finck             {
291*c2c66affSColin Finck                 /* Remove real IF flag */
292*c2c66affSColin Finck                 VdmTib->VdmContext.EFlags &= ~EFLAGS_INTERRUPT_MASK;
293*c2c66affSColin Finck             }
294*c2c66affSColin Finck 
295*c2c66affSColin Finck             /* Turn off VIP and VIF */
296*c2c66affSColin Finck             TrapFrame->EFlags &= ~(EFLAGS_VIP | EFLAGS_VIF);
297*c2c66affSColin Finck             VdmTib->VdmContext.EFlags &= ~(EFLAGS_VIP | EFLAGS_VIF);
298*c2c66affSColin Finck         }
299*c2c66affSColin Finck         else
300*c2c66affSColin Finck         {
301*c2c66affSColin Finck             /* Set the EFLAGS based on our software copy of EFLAGS */
302*c2c66affSColin Finck             VdmTib->VdmContext.EFlags = (VdmTib->VdmContext.EFlags & ~EFLAGS_INTERRUPT_MASK) |
303*c2c66affSColin Finck                                         (*VdmState & EFLAGS_INTERRUPT_MASK);
304*c2c66affSColin Finck         }
305*c2c66affSColin Finck     }
306*c2c66affSColin Finck 
307*c2c66affSColin Finck     /* Lower IRQL and reutrn */
308*c2c66affSColin Finck     KeLowerIrql(OldIrql);
309*c2c66affSColin Finck }
310*c2c66affSColin Finck 
311*c2c66affSColin Finck BOOLEAN
312*c2c66affSColin Finck NTAPI
VdmDispatchBop(IN PKTRAP_FRAME TrapFrame)313*c2c66affSColin Finck VdmDispatchBop(IN PKTRAP_FRAME TrapFrame)
314*c2c66affSColin Finck {
315*c2c66affSColin Finck     PUCHAR Eip;
316*c2c66affSColin Finck     PVDM_TIB VdmTib;
317*c2c66affSColin Finck 
318*c2c66affSColin Finck     /* Check if this is from V86 mode */
319*c2c66affSColin Finck     if (TrapFrame->EFlags & EFLAGS_V86_MASK)
320*c2c66affSColin Finck     {
321*c2c66affSColin Finck         /* Calculate flat EIP */
322*c2c66affSColin Finck         Eip = (PUCHAR)((TrapFrame->Eip & 0xFFFF) +
323*c2c66affSColin Finck                       ((TrapFrame->SegCs & 0xFFFF) << 4));
324*c2c66affSColin Finck 
325*c2c66affSColin Finck         /* Check if this is a BOP */
326*c2c66affSColin Finck         if (*(PUSHORT)Eip == 0xC4C4)
327*c2c66affSColin Finck         {
328*c2c66affSColin Finck             /* Check sure its the DOS Bop */
329*c2c66affSColin Finck             if (Eip[2] == 0x50)
330*c2c66affSColin Finck             {
331*c2c66affSColin Finck                 /* FIXME: No VDM Support */
332*c2c66affSColin Finck                 ASSERT(FALSE);
333*c2c66affSColin Finck             }
334*c2c66affSColin Finck 
335*c2c66affSColin Finck             /* Increase the number of BOP operations */
336*c2c66affSColin Finck             VdmBopCount++;
337*c2c66affSColin Finck 
338*c2c66affSColin Finck             /* Get the TIB */
339*c2c66affSColin Finck             VdmTib = NtCurrentTeb()->Vdm;
340*c2c66affSColin Finck 
341*c2c66affSColin Finck             /* Fill out a VDM Event */
342*c2c66affSColin Finck             VdmTib->EventInfo.InstructionSize = 3;
343*c2c66affSColin Finck             VdmTib->EventInfo.BopNumber = Eip[2];
344*c2c66affSColin Finck             VdmTib->EventInfo.Event = VdmBop;
345*c2c66affSColin Finck 
346*c2c66affSColin Finck             /* End VDM Execution */
347*c2c66affSColin Finck             VdmEndExecution(TrapFrame, VdmTib);
348*c2c66affSColin Finck         }
349*c2c66affSColin Finck         else
350*c2c66affSColin Finck         {
351*c2c66affSColin Finck             /* Not a BOP */
352*c2c66affSColin Finck             return FALSE;
353*c2c66affSColin Finck         }
354*c2c66affSColin Finck     }
355*c2c66affSColin Finck     else
356*c2c66affSColin Finck     {
357*c2c66affSColin Finck         /* FIXME: Shouldn't happen on ROS */
358*c2c66affSColin Finck         ASSERT(FALSE);
359*c2c66affSColin Finck     }
360*c2c66affSColin Finck 
361*c2c66affSColin Finck     /* Return success */
362*c2c66affSColin Finck     return TRUE;
363*c2c66affSColin Finck }
364*c2c66affSColin Finck 
365*c2c66affSColin Finck BOOLEAN
366*c2c66affSColin Finck NTAPI
VdmDispatchPageFault(_In_ PKTRAP_FRAME TrapFrame)367*c2c66affSColin Finck VdmDispatchPageFault(
368*c2c66affSColin Finck     _In_ PKTRAP_FRAME TrapFrame)
369*c2c66affSColin Finck {
370*c2c66affSColin Finck     NTSTATUS Status;
371*c2c66affSColin Finck     PVDM_TIB VdmTib;
372*c2c66affSColin Finck 
373*c2c66affSColin Finck     PAGED_CODE();
374*c2c66affSColin Finck 
375*c2c66affSColin Finck     /* Get the VDM TIB so we can terminate V86 execution */
376*c2c66affSColin Finck     Status = VdmpGetVdmTib(&VdmTib);
377*c2c66affSColin Finck     if (!NT_SUCCESS(Status))
378*c2c66affSColin Finck     {
379*c2c66affSColin Finck         /* Not a proper VDM fault, keep looking */
380*c2c66affSColin Finck         DPRINT1("VdmDispatchPageFault: no VDM TIB, Vdm=%p\n", NtCurrentTeb()->Vdm);
381*c2c66affSColin Finck         return FALSE;
382*c2c66affSColin Finck     }
383*c2c66affSColin Finck 
384*c2c66affSColin Finck     /* Must be coming from V86 code */
385*c2c66affSColin Finck     ASSERT(TrapFrame->EFlags & EFLAGS_V86_MASK);
386*c2c66affSColin Finck 
387*c2c66affSColin Finck     _SEH2_TRY
388*c2c66affSColin Finck     {
389*c2c66affSColin Finck         /* Fill out a VDM Event */
390*c2c66affSColin Finck         VdmTib->EventInfo.Event = VdmMemAccess;
391*c2c66affSColin Finck         VdmTib->EventInfo.InstructionSize = 0;
392*c2c66affSColin Finck 
393*c2c66affSColin Finck         /* End VDM Execution */
394*c2c66affSColin Finck         VdmEndExecution(TrapFrame, VdmTib);
395*c2c66affSColin Finck     }
396*c2c66affSColin Finck     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
397*c2c66affSColin Finck     {
398*c2c66affSColin Finck         Status = _SEH2_GetExceptionCode();
399*c2c66affSColin Finck     }
400*c2c66affSColin Finck     _SEH2_END;
401*c2c66affSColin Finck 
402*c2c66affSColin Finck     /* Consider the exception handled if we succeeded */
403*c2c66affSColin Finck     DPRINT1("VdmDispatchPageFault EFlags %lx exit with 0x%lx\n", TrapFrame->EFlags, Status);
404*c2c66affSColin Finck     return NT_SUCCESS(Status);
405*c2c66affSColin Finck }
406*c2c66affSColin Finck 
407