ReactOS  0.4.15-dev-1206-g731eddf
v86vdm.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Kernel
3  * LICENSE: BSD - See COPYING.ARM in the top level directory
4  * FILE: ntoskrnl/ke/i386/v86vdm.c
5  * PURPOSE: V8086 and VDM Trap Emulation
6  * PROGRAMMERS: ReactOS Portable Systems Group
7  * Alex Ionescu (alex.ionescu@reactos.org)
8  */
9 
10 /* INCLUDES *******************************************************************/
11 
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <debug.h>
15 
16 #define KiVdmGetInstructionSize(x) ((x) & 0xFF)
17 #define KiVdmGetPrefixFlags(x) ((x) & 0xFFFFFF00)
18 
19 /* GLOBALS ********************************************************************/
20 
26 
27 /* UNHANDLED OPCODES **********************************************************/
28 
35 KiVdmUnhandledOpcode(INBimm);
36 KiVdmUnhandledOpcode(INWimm);
37 KiVdmUnhandledOpcode(OUTBimm);
38 KiVdmUnhandledOpcode(OUTWimm);
46 
47 /* OPCODE HANDLERS ************************************************************/
48 
49 BOOLEAN
52  IN ULONG Flags)
53 {
54  ULONG Esp, V86EFlags, TrapEFlags;
55 
56  /* Get current V8086 flags and mask out interrupt flag */
57  V86EFlags = *KiNtVdmState;
58  V86EFlags &= ~EFLAGS_INTERRUPT_MASK;
59 
60  /* Get trap frame EFLags */
61  TrapEFlags = TrapFrame->EFlags;
62  /* Check for VME support */
64  {
65  /* Copy the virtual interrupt flag to the interrupt flag */
66  TrapEFlags &= ~EFLAGS_INTERRUPT_MASK;
67  if(TrapEFlags & EFLAGS_VIF)
68  TrapEFlags |= EFLAGS_INTERRUPT_MASK;
69  }
70  /* Leave only align, nested task and interrupt */
72 
73  /* Add in those flags if they exist, and add in the IOPL flag */
74  V86EFlags |= TrapEFlags;
75  V86EFlags |= EFLAGS_IOPL;
76 
77  /* Build flat ESP */
78  Esp = (TrapFrame->HardwareSegSs << 4) + (USHORT)TrapFrame->HardwareEsp;
79 
80  /* Check for OPER32 */
82  {
83  /* Save EFlags */
84  Esp -= 4;
85  *(PULONG)Esp = V86EFlags;
86  }
87  else
88  {
89  /* Save EFLags */
90  Esp -= 2;
91  *(PUSHORT)Esp = (USHORT)V86EFlags;
92  }
93 
94  /* Set new ESP and EIP */
95  TrapFrame->HardwareEsp = Esp - (TrapFrame->HardwareSegSs << 4);
96  TrapFrame->Eip += KiVdmGetInstructionSize(Flags);
97 
98  /* We're done */
99  return TRUE;
100 }
101 
102 BOOLEAN
103 FASTCALL
105  IN ULONG Flags)
106 {
107  ULONG Esp, V86EFlags, EFlags, TrapEFlags;
108 
109  /* Build flat ESP */
110  Esp = (TrapFrame->HardwareSegSs << 4) + (USHORT)TrapFrame->HardwareEsp;
111 
112  /* Check for OPER32 */
114  {
115  /* Read EFlags */
116  EFlags = *(PULONG)Esp;
117  Esp += 4;
118  }
119  else
120  {
121  /* Read EFlags */
122  EFlags = *(PUSHORT)Esp;
123  Esp += 2;
124  }
125 
126  /* Set new ESP */
127  TrapFrame->HardwareEsp = Esp - (TrapFrame->HardwareSegSs << 4);
128 
129  /* Mask out IOPL from the flags */
130  EFlags &= ~EFLAGS_IOPL;
131 
132  /* Save the V86 flags, but mask out the nested task flag */
133  V86EFlags = EFlags & ~EFLAGS_NESTED_TASK;
134 
135  /* Now leave only alignment, nested task and interrupt flag */
137 
138  /* Get trap EFlags */
139  TrapEFlags = TrapFrame->EFlags;
140 
141  /* Check for VME support */
143  {
144  /* Copy the IF flag into the VIF one */
145  V86EFlags &= ~EFLAGS_VIF;
146  if(V86EFlags & EFLAGS_INTERRUPT_MASK)
147  {
148  V86EFlags |= EFLAGS_VIF;
149  /* Don't set the interrupt flag */
150  V86EFlags &= ~EFLAGS_INTERRUPT_MASK;
151  }
152  }
153 
154  /* Add V86 flag */
155  V86EFlags |= EFLAGS_V86_MASK;
156 
157  /* Update EFlags in trap frame */
158  TrapFrame->EFlags |= V86EFlags;
159 
160  /* Check if ESP0 needs to be fixed up */
161  if (TrapEFlags & EFLAGS_V86_MASK) Ki386AdjustEsp0(TrapFrame);
162 
163  /* Update the V8086 EFlags state */
165  KiVdmSetVdmEFlags(EFlags);
166 
167  /* FIXME: Check for VDM interrupts */
168 
169  /* Update EIP */
170  TrapFrame->Eip += KiVdmGetInstructionSize(Flags);
171 
172  /* We're done */
173  return TRUE;
174 }
175 
176 BOOLEAN
177 FASTCALL
179  IN ULONG Flags)
180 {
181  ULONG Esp, V86EFlags, TrapEFlags, Eip, Interrupt;
182 
183  /* Read trap frame EFlags */
184  TrapEFlags = TrapFrame->EFlags;
185 
186  /* Remove interrupt flag from V8086 EFlags */
187  V86EFlags = *KiNtVdmState;
189 
190  /* Keep only alignment and interrupt flag from the V8086 state */
191  V86EFlags &= (EFLAGS_ALIGN_CHECK | EFLAGS_INTERRUPT_MASK);
192 
193  /* Check for VME support */
195 
196  /* Mask in the relevant V86 EFlags into the trap flags */
197  V86EFlags |= (TrapEFlags & ~EFLAGS_INTERRUPT_MASK);
198 
199  /* And mask out the VIF, nested task and TF flag from the trap flags */
200  TrapFrame->EFlags = TrapEFlags &~ (EFLAGS_VIF | EFLAGS_NESTED_TASK | EFLAGS_TF);
201 
202  /* Add the IOPL flag to the local trap flags */
203  V86EFlags |= EFLAGS_IOPL;
204 
205  /* Build flat ESP */
206  Esp = (TrapFrame->HardwareSegSs << 4) + TrapFrame->HardwareEsp;
207 
208  /* Push EFlags */
209  Esp -= 2;
210  *(PUSHORT)(Esp) = (USHORT)V86EFlags;
211 
212  /* Push CS */
213  Esp -= 2;
214  *(PUSHORT)(Esp) = (USHORT)TrapFrame->SegCs;
215 
216  /* Push IP */
217  Esp -= 2;
218  *(PUSHORT)(Esp) = (USHORT)TrapFrame->Eip + KiVdmGetInstructionSize(Flags) + 1;
219 
220  /* Update ESP */
221  TrapFrame->HardwareEsp = (USHORT)Esp;
222 
223  /* Get flat EIP */
224  Eip = (TrapFrame->SegCs << 4) + TrapFrame->Eip;
225 
226  /* Now get the *next* EIP address (current is original + the count - 1) */
228 
229  /* Now read the interrupt number */
230  Interrupt = *(PUCHAR)Eip;
231 
232  /* Read the EIP from its IVT entry */
233  Interrupt = *(PULONG)(Interrupt * 4);
234  TrapFrame->Eip = (USHORT)Interrupt;
235 
236  /* Now get the CS segment */
237  Interrupt = (USHORT)(Interrupt >> 16);
238 
239  /* Check if the trap was not V8086 trap */
240  if (!(TrapFrame->EFlags & EFLAGS_V86_MASK))
241  {
242  /* Was it a kernel CS? */
243  Interrupt |= RPL_MASK;
244  if (TrapFrame->SegCs == KGDT_R0_CODE)
245  {
246  /* Add the RPL mask */
247  TrapFrame->SegCs = Interrupt;
248  }
249  else
250  {
251  /* Set user CS */
252  TrapFrame->SegCs = KGDT_R3_CODE | RPL_MASK;
253  }
254  }
255  else
256  {
257  /* Set IVT CS */
258  TrapFrame->SegCs = Interrupt;
259  }
260 
261  /* We're done */
262  return TRUE;
263 }
264 
265 BOOLEAN
266 FASTCALL
268  IN ULONG Flags)
269 {
270  ULONG Esp, V86EFlags, EFlags, TrapEFlags, Eip;
271 
272  /* Build flat ESP */
273  Esp = (TrapFrame->HardwareSegSs << 4) + TrapFrame->HardwareEsp;
274 
275  /* Check for OPER32 */
277  {
278  /* Build segmented EIP */
279  TrapFrame->Eip = *(PULONG)Esp;
280  TrapFrame->SegCs = *(PUSHORT)(Esp + 4);
281 
282  /* Set new ESP */
283  TrapFrame->HardwareEsp += 12;
284 
285  /* Get EFLAGS */
286  EFlags = *(PULONG)(Esp + 8);
287  }
288  else
289  {
290  /* Build segmented EIP */
291  TrapFrame->Eip = *(PUSHORT)Esp;
292  TrapFrame->SegCs = *(PUSHORT)(Esp + 2);
293 
294  /* Set new ESP */
295  TrapFrame->HardwareEsp += 6;
296 
297  /* Get EFLAGS */
298  EFlags = *(PUSHORT)(Esp + 4);
299  }
300 
301  /* Mask out EFlags */
303  V86EFlags = EFlags;
304 
305  /* Check for VME support */
307 
308  /* Add V86 and Interrupt flag */
310 
311  /* Update EFlags in trap frame */
312  TrapEFlags = TrapFrame->EFlags;
313  TrapFrame->EFlags = (TrapFrame->EFlags & EFLAGS_VIP) | EFlags;
314 
315  /* Check if ESP0 needs to be fixed up */
316  if (!(TrapEFlags & EFLAGS_V86_MASK)) Ki386AdjustEsp0(TrapFrame);
317 
318  /* Update the V8086 EFlags state */
320  KiVdmSetVdmEFlags(V86EFlags);
321 
322  /* Build flat EIP and check if this is the BOP instruction */
323  Eip = (TrapFrame->SegCs << 4) + TrapFrame->Eip;
324  if (*(PUSHORT)Eip == 0xC4C4)
325  {
326  /* Dispatch the BOP */
327  VdmDispatchBop(TrapFrame);
328  }
329  else
330  {
331  /* FIXME: Check for VDM interrupts */
332  DPRINT("FIXME: Check for VDM interrupts\n");
333  }
334 
335  /* We're done */
336  return TRUE;
337 }
338 
339 BOOLEAN
340 FASTCALL
342  IN ULONG Flags)
343 {
344  /* Check for VME support */
346 
347  /* Disable interrupts */
349 
350  /* Skip instruction */
351  TrapFrame->Eip += KiVdmGetInstructionSize(Flags);
352 
353  /* Done */
354  return TRUE;
355 }
356 
357 BOOLEAN
358 FASTCALL
360  IN ULONG Flags)
361 {
362  /* Check for VME support */
364 
365  /* Enable interrupts */
367 
368  /* Skip instruction */
369  TrapFrame->Eip += KiVdmGetInstructionSize(Flags);
370 
371  /* Done */
372  return TRUE;
373 }
374 
375 /* MASTER OPCODE HANDLER ******************************************************/
376 
377 BOOLEAN
378 FASTCALL
380  IN ULONG Flags)
381 {
382  ULONG Eip;
383 
384  /* Get flat EIP of the *current* instruction (not the original EIP) */
385  Eip = (TrapFrame->SegCs << 4) + TrapFrame->Eip;
386  Eip += KiVdmGetInstructionSize(Flags) - 1;
387 
388  /* Read the opcode entry */
389  switch (*(PUCHAR)Eip)
390  {
391  case 0xF: return KiCallVdmHandler(F);
392  case 0x26: return KiCallVdmPrefixHandler(PFX_FLAG_ES);
393  case 0x2E: return KiCallVdmPrefixHandler(PFX_FLAG_CS);
394  case 0x36: return KiCallVdmPrefixHandler(PFX_FLAG_SS);
395  case 0x3E: return KiCallVdmPrefixHandler(PFX_FLAG_DS);
396  case 0x64: return KiCallVdmPrefixHandler(PFX_FLAG_FS);
397  case 0x65: return KiCallVdmPrefixHandler(PFX_FLAG_GS);
398  case 0x66: return KiCallVdmPrefixHandler(PFX_FLAG_OPER32);
399  case 0x67: return KiCallVdmPrefixHandler(PFX_FLAG_ADDR32);
400  case 0xF0: return KiCallVdmPrefixHandler(PFX_FLAG_LOCK);
401  case 0xF2: return KiCallVdmPrefixHandler(PFX_FLAG_REPNE);
402  case 0xF3: return KiCallVdmPrefixHandler(PFX_FLAG_REP);
403  case 0x6C: return KiCallVdmHandler(INSB);
404  case 0x6D: return KiCallVdmHandler(INSW);
405  case 0x6E: return KiCallVdmHandler(OUTSB);
406  case 0x6F: return KiCallVdmHandler(OUTSW);
407  case 0x98: return KiCallVdmHandler(NPX);
408  case 0xD8: return KiCallVdmHandler(NPX);
409  case 0xD9: return KiCallVdmHandler(NPX);
410  case 0xDA: return KiCallVdmHandler(NPX);
411  case 0xDB: return KiCallVdmHandler(NPX);
412  case 0xDC: return KiCallVdmHandler(NPX);
413  case 0xDD: return KiCallVdmHandler(NPX);
414  case 0xDE: return KiCallVdmHandler(NPX);
415  case 0xDF: return KiCallVdmHandler(NPX);
416  case 0x9C: return KiCallVdmHandler(PUSHF);
417  case 0x9D: return KiCallVdmHandler(POPF);
418  case 0xCD: return KiCallVdmHandler(INTnn);
419  case 0xCE: return KiCallVdmHandler(INTO);
420  case 0xCF: return KiCallVdmHandler(IRET);
421  case 0xE4: return KiCallVdmHandler(INBimm);
422  case 0xE5: return KiCallVdmHandler(INWimm);
423  case 0xE6: return KiCallVdmHandler(OUTBimm);
424  case 0xE7: return KiCallVdmHandler(OUTWimm);
425  case 0xEC: return KiCallVdmHandler(INB);
426  case 0xED: return KiCallVdmHandler(INW);
427  case 0xEE: return KiCallVdmHandler(OUTB);
428  case 0xEF: return KiCallVdmHandler(OUTW);
429  case 0xF4: return KiCallVdmHandler(HLT);
430  case 0xFA: return KiCallVdmHandler(CLI);
431  case 0xFB: return KiCallVdmHandler(STI);
432  default:
433  DPRINT1("Unhandled instruction: 0x%02x.\n", *(PUCHAR)Eip);
434  return KiCallVdmHandler(INV);
435  }
436 }
437 
438 /* PREFIX HANDLER *************************************************************/
439 
440 BOOLEAN
441 FASTCALL
443  IN ULONG Flags)
444 {
445  /* Increase instruction size */
446  Flags++;
447 
448  /* Handle the next opcode */
449  return KiVdmHandleOpcode(TrapFrame, Flags);
450 }
451 
452 /* TRAP HANDLER ***************************************************************/
453 
454 BOOLEAN
455 FASTCALL
457 {
458  /* Clean up */
459  TrapFrame->Eip &= 0xFFFF;
460  TrapFrame->HardwareEsp &= 0xFFFF;
461 
462  /* We start with only 1 byte per instruction */
463  return KiVdmHandleOpcode(TrapFrame, 1);
464 }
465 
466 ULONG_PTR
467 FASTCALL
469 {
470  PKPCR Pcr = KeGetPcr();
471  ULONG_PTR StackFrameUnaligned;
472  PKV8086_STACK_FRAME StackFrame;
474  PKV86_FRAME V86Frame;
475  PFX_SAVE_AREA NpxFrame;
476 
477  /* Get the stack frame back */
478  StackFrameUnaligned = TrapFrame->Esi;
479  StackFrame = (PKV8086_STACK_FRAME)(ROUND_UP(StackFrameUnaligned - 4, 16) + 4);
480  V86Frame = &StackFrame->V86Frame;
481  NpxFrame = &StackFrame->NpxArea;
482  ASSERT((ULONG_PTR)NpxFrame % 16 == 0);
483 
484  /* Copy the FPU frame back */
487 
488  /* Set initial stack back */
489  Thread->InitialStack = (PVOID)((ULONG_PTR)V86Frame->ThreadStack + sizeof(FX_SAVE_AREA));
490 
491  /* Set ESP0 back in the KTSS */
492  Pcr->TSS->Esp0 = (ULONG_PTR)Thread->InitialStack;
493  Pcr->TSS->Esp0 -= sizeof(KTRAP_FRAME) - FIELD_OFFSET(KTRAP_FRAME, V86Es);
494  Pcr->TSS->Esp0 -= NPX_FRAME_LENGTH;
495 
496  /* Restore TEB addresses */
497  Thread->Teb = V86Frame->ThreadTeb;
498  KiSetTebBase(KeGetPcr(), V86Frame->ThreadTeb);
499 
500  /* Enable interrupts and return a pointer to the trap frame */
501  _enable();
502  return StackFrameUnaligned;
503 }
504 
505 VOID
506 FASTCALL
507 KiEnterV86Mode(IN ULONG_PTR StackFrameUnaligned)
508 {
510  PKV8086_STACK_FRAME StackFrame = (PKV8086_STACK_FRAME)(ROUND_UP(StackFrameUnaligned - 4, 16) + 4);
511  PKTRAP_FRAME TrapFrame = &StackFrame->TrapFrame;
512  PKV86_FRAME V86Frame = &StackFrame->V86Frame;
513  PFX_SAVE_AREA NpxFrame = &StackFrame->NpxArea;
514 
515  ASSERT((ULONG_PTR)NpxFrame % 16 == 0);
516 
517  /* Build fake user-mode trap frame */
518  TrapFrame->SegCs = KGDT_R0_CODE | RPL_MASK;
519  TrapFrame->SegEs = TrapFrame->SegDs = TrapFrame->SegFs = TrapFrame->SegGs = 0;
520  TrapFrame->ErrCode = 0;
521 
522  /* Get the current thread's initial stack */
525 
526  /* Save TEB addresses */
527  V86Frame->ThreadTeb = Thread->Teb;
528  V86Frame->PcrTeb = KeGetPcr()->NtTib.Self;
529 
530  /* Save return EIP */
532 
533  /* Save our stack (after the frames) */
534  TrapFrame->Esi = StackFrameUnaligned;
535  TrapFrame->Edi = (ULONG_PTR)_AddressOfReturnAddress() + 4;
536 
537  /* Sanitize EFlags and enable interrupts */
538  TrapFrame->EFlags = __readeflags() & 0x60DD7;
539  TrapFrame->EFlags |= EFLAGS_INTERRUPT_MASK;
540 
541  /* Fill out the rest of the frame */
542  TrapFrame->HardwareSegSs = KGDT_R3_DATA | RPL_MASK;
543  TrapFrame->HardwareEsp = 0x11FFE;
544  TrapFrame->ExceptionList = EXCEPTION_CHAIN_END;
545  TrapFrame->Dr7 = 0;
546 
547  /* Set some debug fields if trap debugging is enabled */
548  KiFillTrapFrameDebug(TrapFrame);
549 
550  /* Disable interrupts */
551  _disable();
552 
553  /* Copy the thread's NPX frame */
554  RtlCopyMemory(NpxFrame, V86Frame->ThreadStack, sizeof(FX_SAVE_AREA));
555 
556  /* Clear exception list */
557  KeGetPcr()->NtTib.ExceptionList = EXCEPTION_CHAIN_END;
558 
559  /* Set new ESP0 */
560  KeGetPcr()->TSS->Esp0 = (ULONG_PTR)&TrapFrame->V86Es;
561 
562  /* Set new initial stack */
563  Thread->InitialStack = V86Frame;
564 
565  /* Set VDM TEB */
566  Thread->Teb = (PTEB)TRAMPOLINE_TEB;
568 
569  /* Enable interrupts */
570  _enable();
571 
572  /* Start VDM execution */
574 
575  /* Exit to V86 mode */
576  KiEoiHelper(TrapFrame);
577 }
578 
579 VOID
580 NTAPI
582 {
583 
585  PKPROCESS Process = Thread->ApcState.Process;
586  PKTRAP_FRAME TrapFrame;
588 
589  /* IOPL was enabled for this process/thread */
590  Process->Iopl = TRUE;
591  Thread->Iopl = TRUE;
592 
593  /* Get the trap frame on exit */
594  TrapFrame = KeGetTrapFrame(Thread);
595 
596  /* Convert to a context */
597  Context.ContextFlags = CONTEXT_CONTROL;
598  KeTrapFrameToContext(TrapFrame, NULL, &Context);
599 
600  /* Set the IOPL flag */
601  Context.EFlags |= EFLAGS_IOPL;
602 
603  /* Convert back to a trap frame */
605 }
606 
607 /* PUBLIC FUNCTIONS ***********************************************************/
608 
609 /*
610  * @implemented
611  */
612 NTSTATUS
613 NTAPI
616 {
617  PUCHAR Trampoline = (PUCHAR)TRAMPOLINE_BASE;
618  PTEB VdmTeb = (PTEB)TRAMPOLINE_TEB;
619  PVDM_TIB VdmTib = (PVDM_TIB)TRAMPOLINE_TIB;
620  ULONG ContextSize = FIELD_OFFSET(CONTEXT, ExtendedRegisters);
622  PKTSS Tss = KeGetPcr()->TSS;
623  PKPROCESS Process = Thread->ApcState.Process;
624  PVDM_PROCESS_OBJECTS VdmProcessObjects;
625  USHORT OldOffset, OldBase;
626 
627  /* Start with a clean TEB */
628  RtlZeroMemory(VdmTeb, sizeof(TEB));
629 
630  /* Write the interrupt and bop */
631  *Trampoline++ = 0xCD;
632  *Trampoline++ = (UCHAR)Int;
633  *(PULONG)Trampoline = TRAMPOLINE_BOP;
634 
635  /* Setup the VDM TEB and TIB */
636  VdmTeb->Vdm = (PVOID)TRAMPOLINE_TIB;
637  RtlZeroMemory(VdmTib, sizeof(VDM_TIB));
638  VdmTib->Size = sizeof(VDM_TIB);
639 
640  /* Set a blank VDM state */
641  *VdmState = 0;
642 
643  /* Copy the context */
645  VdmTib->VdmContext.SegCs = (ULONG_PTR)Trampoline >> 4;
646  VdmTib->VdmContext.SegSs = (ULONG_PTR)Trampoline >> 4;
647  VdmTib->VdmContext.Eip = 0;
648  VdmTib->VdmContext.Esp = 2 * PAGE_SIZE - sizeof(ULONG_PTR);
651 
652  /* This can't be a real VDM process */
653  ASSERT(PsGetCurrentProcess()->VdmObjects == NULL);
654 
655  /* Allocate VDM structure */
656  VdmProcessObjects = ExAllocatePoolWithTag(NonPagedPool,
657  sizeof(VDM_PROCESS_OBJECTS),
658  ' eK');
659  if (!VdmProcessObjects) return STATUS_NO_MEMORY;
660 
661  /* Set it up */
662  RtlZeroMemory(VdmProcessObjects, sizeof(VDM_PROCESS_OBJECTS));
663  VdmProcessObjects->VdmTib = VdmTib;
664  PsGetCurrentProcess()->VdmObjects = VdmProcessObjects;
665 
666  /* Set the system affinity for the current thread */
668 
669  /* Make sure there's space for two IOPMs, then copy & clear the current */
670  ASSERT(((PKIPCR)KeGetPcr())->GDT[KGDT_TSS / 8].LimitLow >=
671  (0x2000 + IOPM_OFFSET - 1));
673  RtlZeroMemory(&Tss->IoMaps[0].IoMap, IOPM_SIZE);
674 
675  /* Save the old offset and base, and set the new ones */
676  OldOffset = Process->IopmOffset;
677  OldBase = Tss->IoMapBase;
678  Process->IopmOffset = (USHORT)IOPM_OFFSET;
679  Tss->IoMapBase = (USHORT)IOPM_OFFSET;
680 
681  /* Switch stacks and work the magic */
683 
684  /* Restore IOPM */
686  Process->IopmOffset = OldOffset;
687  Tss->IoMapBase = OldBase;
688 
689  /* Restore affinity */
691 
692  /* Restore context */
694  Context->ContextFlags = CONTEXT_FULL;
695 
696  /* Free VDM objects */
697  ExFreePoolWithTag(PsGetCurrentProcess()->VdmObjects, ' eK');
698  PsGetCurrentProcess()->VdmObjects = NULL;
699 
700  /* Return status */
701  return STATUS_SUCCESS;
702 }
703 
704 /*
705  * @implemented
706  */
707 BOOLEAN
708 NTAPI
710  IN ULONG MapNumber)
711 {
712  USHORT MapOffset;
713  PKPRCB Prcb;
714  KAFFINITY TargetProcessors;
715 
716  if(MapNumber > IOPM_COUNT)
717  return FALSE;
718 
719  MapOffset = KiComputeIopmOffset(MapNumber);
720 
721  Process->IopmOffset = MapOffset;
722 
723  TargetProcessors = Process->ActiveProcessors;
724  Prcb = KeGetCurrentPrcb();
725  if (TargetProcessors & Prcb->SetMember)
726  KeGetPcr()->TSS->IoMapBase = MapOffset;
727 
728  return TRUE;
729 }
730 
731 /*
732  * @implemented
733  */
734 BOOLEAN
735 NTAPI
737  IN PKIO_ACCESS_MAP IopmBuffer)
738 {
740  PKPRCB Prcb;
741  PVOID pt;
742 
743  if ((MapNumber > IOPM_COUNT) || (MapNumber == IO_ACCESS_MAP_NONE))
744  return FALSE;
745 
746  Prcb = KeGetCurrentPrcb();
747 
748  // Copy the IOP map and load the map for the current process.
749  pt = &(KeGetPcr()->TSS->IoMaps[MapNumber-1].IoMap);
750  RtlMoveMemory(pt, (PVOID)IopmBuffer, IOPM_SIZE);
751  CurrentProcess = Prcb->CurrentThread->ApcState.Process;
752  KeGetPcr()->TSS->IoMapBase = CurrentProcess->IopmOffset;
753 
754  return TRUE;
755 }
756 
757 /*
758  * @implemented
759  */
760 BOOLEAN
761 NTAPI
763  IN PKIO_ACCESS_MAP IopmBuffer)
764 {
765  ULONG i;
766  PVOID Map;
767  PUCHAR p;
768 
769  if (MapNumber > IOPM_COUNT)
770  return FALSE;
771 
772  if (MapNumber == IO_ACCESS_MAP_NONE)
773  {
774  // no access, simply return a map of all 1s
775  p = (PUCHAR)IopmBuffer;
776  for (i = 0; i < IOPM_SIZE; i++) {
777  p[i] = (UCHAR)-1;
778  }
779  }
780  else
781  {
782  // copy the bits
783  Map = (PVOID)&(KeGetPcr()->TSS->IoMaps[MapNumber-1].IoMap);
784  RtlMoveMemory((PVOID)IopmBuffer, Map, IOPM_SIZE);
785  }
786 
787  return TRUE;
788 }
VOID NTAPI KeContextToTrapFrame(PCONTEXT Context, PKEXCEPTION_FRAME ExeptionFrame, PKTRAP_FRAME TrapFrame, ULONG ContextFlags, KPROCESSOR_MODE PreviousMode)
NTSTATUS NTAPI NtVdmControl(IN ULONG ControlCode, IN PVOID ControlData)
Definition: stubs.c:433
#define KiCallVdmPrefixHandler(x)
Definition: ke.h:132
KV86_FRAME V86Frame
Definition: ke.h:163
#define CONTEXT_CONTROL
Definition: nt_native.h:1369
#define IN
Definition: typedefs.h:39
#define EFLAGS_ALIGN_CHECK
Definition: ketypes.h:130
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
Definition: vdm.h:134
ULONG Esp
Definition: nt_native.h:1479
ULONG V86Es
Definition: ketypes.h:272
#define ROUND_UP(n, align)
Definition: eventvwr.h:31
#define NPX_FRAME_LENGTH
Definition: asm.h:246
#define IOPM_SIZE
Definition: ketypes.h:179
#define KiCallVdmHandler(x)
Definition: ke.h:131
ULONG Eip
Definition: nt_native.h:1476
#define VdmState
Definition: vdm.h:48
FX_SAVE_AREA NpxArea
Definition: ke.h:162
#define PFX_FLAG_ADDR32
Definition: ke.h:102
#define TRAMPOLINE_TIB
Definition: vdm.h:37
#define TRUE
Definition: types.h:120
#define pt(x, y)
Definition: drawing.c:79
struct _KV8086_STACK_FRAME * PKV8086_STACK_FRAME
VOID NTAPI KeRevertToUserAffinityThread(VOID)
Definition: thrdobj.c:1030
unsigned char * PUCHAR
Definition: retypes.h:3
ULONG OldOffset
Definition: shell.c:90
CONTEXT VdmContext
Definition: vdm.h:140
void __cdecl _enable(void)
Definition: intrin_arm.h:373
VOID NTAPI Ke386SetIOPL(VOID)
Definition: v86vdm.c:581
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN FASTCALL KiVdmOpcodePOPF(IN PKTRAP_FRAME TrapFrame, IN ULONG Flags)
Definition: v86vdm.c:104
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1063
USHORT SegFs
Definition: ketypes.h:366
VOID NTAPI Ki386AdjustEsp0(IN PKTRAP_FRAME TrapFrame)
Definition: exp.c:280
void * _AddressOfReturnAddress(void)
#define KGDT_R0_CODE
Definition: ketypes.h:75
PVOID PcrTeb
Definition: ke.h:153
#define TRAMPOLINE_BASE
Definition: vdm.h:36
#define PFX_FLAG_DS
Definition: ke.h:98
#define KiVdmGetInstructionSize(x)
Definition: v86vdm.c:16
#define PFX_FLAG_REP
Definition: ke.h:105
ULONG HardwareSegSs
Definition: ketypes.h:271
VOID FASTCALL KiEnterV86Mode(IN ULONG_PTR StackFrameUnaligned)
Definition: v86vdm.c:507
#define PFX_FLAG_LOCK
Definition: ke.h:103
_Must_inspect_result_ _In_ FLT_CONTEXT_TYPE _In_ SIZE_T ContextSize
Definition: fltkernel.h:1444
Definition: ke.h:289
ULONG Esi
Definition: ketypes.h:263
#define FASTCALL
Definition: nt_native.h:50
DECLSPEC_NORETURN VOID FASTCALL KiEoiHelper(IN PKTRAP_FRAME TrapFrame)
Definition: traphdlr.c:126
ULONG Size
Definition: vdm.h:136
#define KeGetPcr()
Definition: ke.h:25
ULONG Edi
Definition: ketypes.h:262
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
VOID NTAPI KeSetSystemAffinityThread(IN KAFFINITY Affinity)
Definition: thrdobj.c:1116
#define EFLAGS_V86_MASK
Definition: ketypes.h:129
PVDM_TIB VdmTib
Definition: vdm.h:165
uint32_t ULONG_PTR
Definition: typedefs.h:65
BOOLEAN FASTCALL KiVdmOpcodeCLI(IN PKTRAP_FRAME TrapFrame, IN ULONG Flags)
Definition: v86vdm.c:341
#define EFLAGS_VIP
Definition: ketypes.h:132
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define FIXED_NTVDMSTATE_LINEAR_PC_AT
Definition: asm.h:644
__INTRIN_INLINE uintptr_t __readeflags(void)
Definition: intrin_x86.h:1569
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
PVOID ThreadStack
Definition: ke.h:151
USHORT SegGs
Definition: ketypes.h:367
#define FALSE
Definition: types.h:117
#define PFX_FLAG_OPER32
Definition: ke.h:101
#define EFLAGS_NESTED_TASK
Definition: ketypes.h:128
#define EFLAGS_USER_SANITIZE
Definition: ketypes.h:133
USHORT SegEs
Definition: ketypes.h:365
#define PsGetCurrentProcess
Definition: psfuncs.h:17
struct _KTHREAD * CurrentThread
Definition: ketypes.h:566
#define RPL_MASK
Definition: ketypes.h:69
ULONG SegCs
Definition: nt_native.h:1477
unsigned char BOOLEAN
#define PFX_FLAG_ES
Definition: ke.h:95
BOOLEAN NTAPI Ke386SetIoAccessMap(IN ULONG MapNumber, IN PKIO_ACCESS_MAP IopmBuffer)
Definition: v86vdm.c:736
smooth NULL
Definition: ftsmooth.c:416
BOOLEAN FASTCALL KiVdmOpcodeSTI(IN PKTRAP_FRAME TrapFrame, IN ULONG Flags)
Definition: v86vdm.c:359
#define KiVdmGetPrefixFlags(x)
Definition: v86vdm.c:17
USHORT SegCs
Definition: ketypes.h:380
BOOLEAN FASTCALL KiVdmOpcodePrefix(IN PKTRAP_FRAME TrapFrame, IN ULONG Flags)
Definition: v86vdm.c:442
#define KiVdmClearVdmEFlags(x)
Definition: ke.h:130
Definition: ketypes.h:789
void DPRINT(...)
Definition: polytest.cpp:61
#define KGDT_R3_DATA
Definition: ketypes.h:78
ULONG EFlags
Definition: nt_native.h:1478
VOID NTAPI KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame, IN OUT PCONTEXT Context)
Definition: context.c:147
KIO_ACCESS_MAP * PKIO_ACCESS_MAP
Definition: ketypes.h:191
void * PVOID
Definition: retypes.h:9
#define PFX_FLAG_GS
Definition: ke.h:100
Definition: utils.h:160
ULONG ContextFlags
Definition: nt_native.h:1426
FORCEINLINE PFX_SAVE_AREA KiGetThreadNpxArea(IN PKTHREAD Thread)
Definition: ke.h:600
struct _Vdm_Tib * PVDM_TIB
#define IO_ACCESS_MAP_NONE
Definition: ketypes.h:263
ULONG KeI386EFlagsOrMaskV86
Definition: v86vdm.c:22
ULONG KeI386EFlagsAndMaskV86
Definition: v86vdm.c:21
#define CONTEXT_FULL
Definition: nt_native.h:1375
ULONG CurrentProcess
Definition: shell.c:125
PVOID Ki386IopmSaveArea
Definition: v86vdm.c:23
const PULONG KiNtVdmState
Definition: v86vdm.c:25
struct _FX_SAVE_AREA FX_SAVE_AREA
#define KGDT_TSS
Definition: ketypes.h:79
if(!(yy_init))
Definition: macro.lex.yy.c:714
ULONG HardwareEsp
Definition: ketypes.h:270
BOOLEAN FASTCALL KiVdmOpcodeINTnn(IN PKTRAP_FRAME TrapFrame, IN ULONG Flags)
Definition: v86vdm.c:178
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
#define TRAMPOLINE_BOP
Definition: vdm.h:43
struct _EXCEPTION_REGISTRATION_RECORD FAR * ExceptionList
Definition: ketypes.h:260
#define PFX_FLAG_CS
Definition: ke.h:96
#define KiFillTrapFrameDebug(x)
Definition: trap_x.h:184
USHORT IoMapBase
Definition: ketypes.h:823
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define EFLAGS_VIF
Definition: ketypes.h:131
BOOLEAN KeI386VirtualIntExtensions
Definition: v86vdm.c:24
PVOID ThreadTeb
Definition: ke.h:152
unsigned char UCHAR
Definition: xmlstorage.h:181
#define EFLAGS_IOPL
Definition: cpu.c:17
VOID NTAPI Ki386SetupAndExitToV86Mode(OUT PTEB VdmTeb)
BOOLEAN FASTCALL KiVdmOpcodePUSHF(IN PKTRAP_FRAME TrapFrame, IN ULONG Flags)
Definition: v86vdm.c:51
VOID FASTCALL Ki386BiosCallReturnAddress(IN PKTRAP_FRAME TrapFrame)
#define PFX_FLAG_REPNE
Definition: ke.h:104
#define PFX_FLAG_SS
Definition: ke.h:97
#define PAGE_SIZE
Definition: env_spec_w32.h:49
USHORT SegDs
Definition: ketypes.h:364
#define EFLAGS_TF
Definition: ketypes.h:125
#define IOPM_COUNT
Definition: ketypes.h:178
ULONG Eip
Definition: ketypes.h:267
UINT64 SetMember
Definition: ketypes.h:578
struct _KTSS * TSS
Definition: ke.h:54
Definition: compat.h:694
#define TRAMPOLINE_TEB
Definition: vdm.h:38
BOOLEAN NTAPI Ke386QueryIoAccessMap(IN ULONG MapNumber, IN PKIO_ACCESS_MAP IopmBuffer)
Definition: v86vdm.c:762
BOOLEAN NTAPI Ke386IoSetAccessProcess(IN PKPROCESS Process, IN ULONG MapNumber)
Definition: v86vdm.c:709
#define IOPM_OFFSET
Definition: ketypes.h:264
NTSTATUS NTAPI Ke386CallBios(IN ULONG Int, OUT PCONTEXT Context)
Definition: v86vdm.c:614
#define EXCEPTION_CHAIN_END
Definition: rtltypes.h:63
ULONG SegSs
Definition: nt_native.h:1480
unsigned short USHORT
Definition: pedump.c:61
#define PFX_FLAG_FS
Definition: ke.h:99
ULONG_PTR KAFFINITY
Definition: compat.h:85
#define KiComputeIopmOffset(MapNumber)
Definition: ketypes.h:265
BOOLEAN FASTCALL KiVdmHandleOpcode(IN PKTRAP_FRAME TrapFrame, IN ULONG Flags)
Definition: v86vdm.c:379
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
unsigned int * PULONG
Definition: retypes.h:1
struct _TEB * PTEB
BOOLEAN NTAPI VdmDispatchBop(IN PKTRAP_FRAME TrapFrame)
Definition: vdmexec.c:313
UCHAR IoMap[8196]
Definition: ketypes.h:903
BOOLEAN FASTCALL Ki386HandleOpcodeV86(IN PKTRAP_FRAME TrapFrame)
Definition: v86vdm.c:456
#define DPRINT1
Definition: precomp.h:8
BOOLEAN FASTCALL KiVdmOpcodeIRET(IN PKTRAP_FRAME TrapFrame, IN ULONG Flags)
Definition: v86vdm.c:267
#define KiVdmSetVdmEFlags(x)
Definition: ke.h:129
#define KGDT_R3_CODE
Definition: ketypes.h:77
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
#define OUT
Definition: typedefs.h:40
void __cdecl _disable(void)
Definition: intrin_arm.h:365
struct tagContext Context
Definition: acpixf.h:1034
unsigned int ULONG
Definition: retypes.h:1
FORCEINLINE VOID KiSetTebBase(PKPCR Pcr, PVOID TebAddress)
Definition: ke.h:318
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define ULONG_PTR
Definition: config.h:101
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
UINT64 Dr7
Definition: ketypes.h:347
GLfloat GLfloat p
Definition: glext.h:8902
#define KeGetCurrentThread
Definition: hal.h:44
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define KeGetTrapFrame(Thread)
Definition: ke.h:145
ULONG ErrCode
Definition: ketypes.h:266
ULONG EFlags
Definition: ketypes.h:384
unsigned short * PUSHORT
Definition: retypes.h:2
PVOID Vdm
Definition: compat.h:740
KIIO_ACCESS_MAP IoMaps[IOPM_COUNT]
Definition: ketypes.h:824
struct _Vdm_Tib VDM_TIB
#define F(x, y, z)
Definition: md5.c:51
KiVdmUnhandledOpcode(F)
int Int
Definition: definitions.h:37
KTRAP_FRAME TrapFrame
Definition: ke.h:161
#define EFLAGS_INTERRUPT_MASK
Definition: ketypes.h:126
ULONG_PTR FASTCALL KiExitV86Mode(IN PKTRAP_FRAME TrapFrame)
Definition: v86vdm.c:468