test: vdmints.c File Reference

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# vdmints.c File Reference

`#include <ntos.h>`
`#include <zwapi.h>`
`#include "vdmp.h"`

Go to the source code of this file.

## Defines

#define | VDM_HWINT_INCREMENT EVENT_INCREMENT

## Functions

VOID | VdmpQueueIntApcRoutine (IN PKAPC Apc, IN PKNORMAL_ROUTINE *NormalRoutine, IN PVOID *NormalContext, IN PVOID *SystemArgument1, IN PVOID *SystemArgument2)
VOID | VdmpQueueIntNormalRoutine (IN PVOID NormalContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
VOID | VdmpDelayIntDpcRoutine (IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
VOID | VdmpDelayIntApcRoutine (IN PKAPC Apc, IN PKNORMAL_ROUTINE *NormalRoutine, IN PVOID *NormalContext, IN PVOID *SystemArgument1, IN PVOID *SystemArgument2)
int | RestartDelayedInterrupts (PVDMICAUSERDATA pIcaUserData)
int | IcaScan (PVDMICAUSERDATA pIcaUserData, PVDMVIRTUALICA pIcaAdapter)
int | IcaAccept (PVDMICAUSERDATA pIcaUserData, PVDMVIRTUALICA pIcaAdapter)
ULONG | GetIretHookAddress (PKTRAP_FRAME TrapFrame, PVDMICAUSERDATA pIcaUserData, int IrqNum)
VOID | PushRmInterrupt (PKTRAP_FRAME TrapFrame, ULONG IretHookAddress, PVDM_TIB VdmTib, ULONG InterruptNumber)
NTSTATUS | PushPmInterrupt (PKTRAP_FRAME TrapFrame, ULONG IretHookAddress, PVDM_TIB VdmTib, ULONG InterruptNumber)
VOID | VdmpNullRundownRoutine (IN PKAPC Apc)
int | VdmpExceptionHandler (IN PEXCEPTION_POINTERS ExceptionInfo)
NTSTATUS | VdmpQueueInterrupt (IN HANDLE ThreadHandle)
NTSTATUS | VdmDispatchInterrupts (PKTRAP_FRAME TrapFrame, PVDM_TIB VdmTib)
NTSTATUS | VdmpDelayInterrupt (PVDMDELAYINTSDATA pdsd)
BOOLEAN | VdmpDispatchableIntPending (ULONG EFlags)
NTSTATUS | VdmpIsThreadTerminating (HANDLE ThreadId)

## Variables

POBJECT_TYPE | ExSemaphoreObjectType
POBJECT_TYPE | ExEventObjectType

## Define Documentation

#define VDM_HWINT_INCREMENT EVENT_INCREMENT

| Definition at line 31 of file vdmints.c. Referenced by VdmDispatchInterrupts(), VdmpDelayIntDpcRoutine(), and VdmpQueueIntApcRoutine().

## Function Documentation

ULONG GetIretHookAddress | ( | PKTRAP_FRAME | TrapFrame,
|  | PVDMICAUSERDATA | pIcaUserData,
|  | int | IrqNum
| ) |

Definition at line 897 of file vdmints.c.

References PAGED_CODE.

Referenced by VdmDispatchInterrupts().

    00904                    :
    00905
    00906     Retrieves the IretHookAddress from the real mode\protect mode
    00907     iret hook bop table. This function is equivalent to
    00908     softpc\base\system\ica.c - ica_iret_hook_needed()
    00909
    00910 Arguments:
    00911
    00912     TrapFrame       - address of current trapframe
    00913     pIcaUserData    - addr of ica data
    00914     IrqNum          - IrqLineNum
    00915
    00916 Return Value:
    00917
    00918     ULONG IretHookAddress. seg:offset or sel:offset Iret Hook,
    00919                            0 if none
    00920 --*/
    00921 {
    00922     ULONG  IrqMask;
    00923     ULONG  AddrBopTable;
    00924     int    IretBopSize;
    00925
    00926     PAGED_CODE();
    00927
    00928     IrqMask = 1 << IrqNum;
    00929     if (!(IrqMask & *pIcaUserData->pIretHooked) ||
    00930         !*pIcaUserData->pAddrIretBopTable )
    00931       {
    00932         return 0;
    00933         }
    00934
    00935     if (TrapFrame->EFlags & EFLAGS_V86_MASK) {
    00936         AddrBopTable = *pIcaUserData->pAddrIretBopTable;
    00937         IretBopSize  = VDM_RM_IRETBOPSIZE;
    00938         }
    00939     else {
    00940         AddrBopTable = (VDM_PM_IRETBOPSEG << 16) | VDM_PM_IRETBOPOFF;
    00941         IretBopSize  = VDM_PM_IRETBOPSIZE;
    00942         }
    00943
    00944     *pIcaUserData->pDelayIret |= IrqMask;
    00945
    00946     return AddrBopTable + IretBopSize * IrqNum;
    00947 }

int IcaAccept | ( | PVDMICAUSERDATA | pIcaUserData,
|  | PVDMVIRTUALICA | pIcaAdapter
| ) |

Definition at line 831 of file vdmints.c.

References FALSE, IcaScan(), and PAGED_CODE.

Referenced by VdmDispatchInterrupts().

    00837                    :
    00838
    00839    Does the equivalent of a cpu IntAck cycle retrieving the Irql Line Num
    00840    for interrupt dispatch, and setting the ica state to reflect that
    00841    the interrupt is in service.
    00842
    00843    Similar to softpc\base\system\ica.c - ica_accept() scan_irr(),
    00844    except that this code rejects interrupt dispatching if the ica
    00845    is in Auto-EOI as this may involve a new interrupt cycle, and
    00846    eoi hooks to be activated.
    00847
    00848 Arguments:
    00849     PVDMICAUSERDATA  pIcaUserData   - addr of ica userdata
    00850     PVDMVIRTUALICA   pIcaAdapter    - addr of ica adapter
    00851
    00852
    00853 Return Value:
    00854
    00855     ULONG IrqLineNum for the specific adapter (0 to 7)
    00856     returns -1 if there are no interrupts to generate (spurious ints
    00857                are normally done on line 7
    00858
    00859 --*/
    00860 {
    00861     int line;
    00862     UCHAR bit;
    00863
    00864     PAGED_CODE();
    00865
    00866
    00867     //
    00868     // Drop the INT line, and scan the ica
    00869     //
    00870     pIcaAdapter->ica_cpu_int = FALSE;
    00871
    00872     line = IcaScan(pIcaUserData, pIcaAdapter);
    00873
    00874     if (line < 0) {
    00875         return -1;
    00876         }
    00877
    00878     bit = (1 << line);
    00879     pIcaAdapter->ica_isr |= bit;
    00880
    00881         //
    00882         // decrement the count and clear the IRR bit
    00883         // ensure the count doesn't wrap past zero.
    00884         //
    00885     if (--(pIcaAdapter->ica_count[line]) <= 0)  {
    00886         pIcaAdapter->ica_irr &= ~bit;
    00887         pIcaAdapter->ica_count[line] = 0;
    00888         }
    00889
    00890
    00891     return(line);
    00892 }

int IcaScan | ( | PVDMICAUSERDATA | pIcaUserData,
|  | PVDMVIRTUALICA | pIcaAdapter
| ) |

Definition at line 750 of file vdmints.c.

References PAGED_CODE.

Referenced by IcaAccept(), and RestartDelayedInterrupts().

    00756                    :
    00757
    00758    Similar to softpc\base\system\ica.c - scan_irr(),
    00759
    00760    Check the IRR, the IMR and the ISR to determine which interrupt
    00761    should be delivered.
    00762
    00763    A bit set in the IRR will generate an interrupt if:
    00764      IMR bit, DelayIret bit, DelayIrq bit AND ISR higher priority bits
    00765      are clear (unless Special Mask Mode, in which case ISR is ignored)
    00766
    00767    If there is no bit set, then return -1
    00768
    00769
    00770 Arguments:
    00771     PVDMICAUSERDATA  pIcaUserData   - addr of ica userdata
    00772     PVDMVIRTUALICA   pIcaAdapter    - addr of ica adapter
    00773
    00774
    00775 Return Value:
    00776
    00777     int IrqLineNum for the specific adapter (0 to 7)
    00778     -1 for none
    00779
    00780 --*/
    00781 {
    00782    int   i,line;
    00783    UCHAR bit;
    00784    ULONG IrrImrDelay;
    00785    ULONG ActiveIsr;
    00786
    00787    PAGED_CODE();
    00788
    00789    IrrImrDelay = *pIcaUserData->pDelayIrq | *pIcaUserData->pDelayIret;
    00790    if (pIcaAdapter == pIcaUserData->pIcaSlave) {
    00791        IrrImrDelay >>= 8;
    00792        }
    00793
    00794    IrrImrDelay = pIcaAdapter->ica_irr & ~(pIcaAdapter->ica_imr | (UCHAR)IrrImrDelay);
    00795
    00796    if (IrrImrDelay)  {
    00797
    00798         /*
    00799          * Does the current mode require the ica to prevent
    00800          * interrupts if that line is still active (ie in the isr)?
    00801          *
    00802          * Normal Case: Used by DOS and Win3.1/S the isr prevents interrupts.
    00803          * Special Mask Mode, Special Fully Nested Mode do not block
    00804          * interrupts using bits in the isr. SMM is the mode used
    00805          * by Windows95 and Win3.1/E.
    00806          *
    00807          */
    00808        ActiveIsr = (pIcaAdapter->ica_mode & (ICA_SMM|ICA_SFNM))
    00809                       ? 0 : pIcaAdapter->ica_isr;
    00810
    00811        for(i = 0; i < 8; i++)  {
    00812            line = (pIcaAdapter->ica_hipri + i) & 7;
    00813            bit = 1 << line;
    00814            if (ActiveIsr & bit) {
    00815                break;            /* No nested interrupt possible */
    00816                }
    00817
    00818            if (IrrImrDelay & bit) {
    00819                return line;
    00820                }
    00821            }
    00822        }
    00823
    00824   return -1;
    00825 }

NTSTATUS PushPmInterrupt | ( | PKTRAP_FRAME | TrapFrame,
|  | ULONG | IretHookAddress,
|  | PVDM_TIB | VdmTib,
|  | ULONG | InterruptNumber
| ) |

Definition at line 1045 of file vdmints.c.

References _Vdm_InterruptHandler::CsSelector, _Vdm_InterruptHandler::Eip, _Vdm_Tib::Flags, Ki386GetSelectorParameters(), PAGED_CODE, PUSHORT, SEL_TYPE_2GIG, SEL_TYPE_BIG, SEL_TYPE_ED, USHORT, and _Vdm_Tib::VdmInterruptHandlers.

Referenced by VdmDispatchInterrupts().

    01053                    :
    01054
    01055     Pushes ProtectMode interrupt frame onto the UserMode stack in the TrapFrame
    01056     Raises an exception if an invalid stack is found
    01057
    01058 Arguments:
    01059
    01060     TrapFrame       - address of current trapframe
    01061     IretHookAddress - address of Iret Hook, 0 if none
    01062     VdmTib          - address of current vdm tib
    01063     InterruptNumber - interrupt number to reflect
    01064
    01065 Return Value:
    01066
    01067     None.
    01068
    01069 --*/
    01070 {
    01071     ULONG   Flags,Base,Limit;
    01072     ULONG   VdmSp, VdmSpOrg;
    01073     PUSHORT VdmStackPointer;
    01074     ULONG   StackOffset;
    01075     BOOLEAN Frame32 = (BOOLEAN) VdmTib->DpmiInfo.Flags;
    01076
    01077     PAGED_CODE();
    01078
    01079     //
    01080     // Switch to "locked" dpmi stack if lock count is zero
    01081     // This emulates the win3.1 Begin_Use_Locked_PM_Stack function.
    01082     //
    01083
    01084     if (!VdmTib->DpmiInfo.LockCount++) {
    01085         VdmTib->DpmiInfo.SaveEsp        = TrapFrame->HardwareEsp;
    01086         VdmTib->DpmiInfo.SaveEip        = TrapFrame->Eip;
    01087         VdmTib->DpmiInfo.SaveSsSelector = (USHORT) TrapFrame->HardwareSegSs;
    01088         TrapFrame->HardwareEsp       = 0x1000;
    01089         TrapFrame->HardwareSegSs     = (ULONG) VdmTib->DpmiInfo.SsSelector | 0x7;
    01090     }
    01091
    01092     //
    01093     // Use Sp or Esp ?
    01094     //
    01095     if (!Ki386GetSelectorParameters((USHORT)TrapFrame->HardwareSegSs,
    01096                                    &Flags, &Base, &Limit))
    01097        {
    01098         return STATUS_ACCESS_VIOLATION;
    01099         }
    01100
    01101     //
    01102     // Adjust the limit for page granularity
    01103     //
    01104     Limit++;
    01105     if (Flags & SEL_TYPE_2GIG) {
    01106         Limit = (Limit << 12) | 0xfff;
    01107         }
    01108
    01109     VdmSp = (Flags & SEL_TYPE_BIG) ? TrapFrame->HardwareEsp
    01110                                    : (USHORT)TrapFrame->HardwareEsp;
    01111
    01112     //
    01113     // Get pointer to current stack
    01114     //
    01115     VdmStackPointer = (PUSHORT)(Base + VdmSp);
    01116
    01117
    01118     //
    01119     // Create enough room for iret hook frame
    01120     //
    01121     VdmSpOrg = VdmSp;
    01122     if (IretHookAddress) {
    01123         if (Frame32) {
    01124             VdmSp -= 3*sizeof(ULONG);
    01125         } else {
    01126             VdmSp -= 3*sizeof(USHORT);
    01127         }
    01128     }
    01129
    01130     //
    01131     // Create enough room for 2 iret frames
    01132     //
    01133
    01134     if (Frame32) {
    01135         VdmSp -= 6*sizeof(ULONG);
    01136     } else {
    01137         VdmSp -= 6*sizeof(USHORT);
    01138     }
    01139
    01140     //
    01141     // Set Final Value of Sp\Esp, do this before checking stack
    01142     // limits so that invalid esp is visible to debuggers
    01143     //
    01144     if (Flags & SEL_TYPE_BIG) {
    01145         TrapFrame->HardwareEsp = VdmSp;
    01146         }
    01147     else {
    01148         (USHORT)TrapFrame->HardwareEsp = (USHORT)VdmSp;
    01149         }
    01150
    01151
    01152     //
    01153     // Check stack limits
    01154     // If any of the following conditions are TRUE
    01155     //    - New stack pointer wraps (not enuf space)
    01156     //    - If normal stack and Sp not below limit
    01157     //    - If Expand Down stack and Sp not above limit
    01158     //
    01159     // Then raise a Stack Fault
    01160     //
    01161     if ( VdmSp >= VdmSpOrg ||
    01162          !(Flags & SEL_TYPE_ED) && VdmSpOrg > Limit ||
    01163          (Flags & SEL_TYPE_ED) && VdmSp < Limit )
    01164        {
    01165         return STATUS_ACCESS_VIOLATION;
    01166         }
    01167
    01168     //
    01169     // Build the Hw Int iret frame
    01170     //
    01171
    01172     if (Frame32) {
    01173
    01174        *(--(PULONG)VdmStackPointer)          = TrapFrame->EFlags;
    01175        *(PUSHORT)(--(PULONG)VdmStackPointer) = (USHORT)TrapFrame->SegCs;
    01176        *(--(PULONG)VdmStackPointer)          = TrapFrame->Eip;
    01177        *(--(PULONG)VdmStackPointer)          = TrapFrame->EFlags & ~EFLAGS_TF_MASK;
    01178        *(--(PULONG)VdmStackPointer)          = VdmTib->DpmiInfo.DosxIntIretD >> 16;
    01179        *(--(PULONG)VdmStackPointer)          = VdmTib->DpmiInfo.DosxIntIretD & 0xffff;
    01180
    01181     } else {
    01182
    01183        *(--(PUSHORT)VdmStackPointer) = (USHORT)TrapFrame->EFlags;
    01184        *(--(PUSHORT)VdmStackPointer) = (USHORT)TrapFrame->SegCs;
    01185        *(--(PUSHORT)VdmStackPointer) = (USHORT)TrapFrame->Eip;
    01186        *(--(PUSHORT)VdmStackPointer) = (USHORT)(TrapFrame->EFlags & ~EFLAGS_TF_MASK);
    01187        *(--(PULONG)VdmStackPointer)          = VdmTib->DpmiInfo.DosxIntIret;
    01188
    01189     }
    01190
    01191     //
    01192     // Point cs and ip at interrupt handler
    01193     //
    01194     TrapFrame->SegCs = VdmTib->VdmInterruptHandlers[InterruptNumber].CsSelector | 0x7;
    01195     TrapFrame->Eip   = VdmTib->VdmInterruptHandlers[InterruptNumber].Eip;
    01196
    01197     //
    01198     // Turn off trace bit so we don't trace the iret hook
    01199     //
    01200     TrapFrame->EFlags &= ~EFLAGS_TF_MASK;
    01201
    01202     //
    01203     // Build the Irethook Iret frame, if one exists
    01204     //
    01205     if (IretHookAddress) {
    01206         ULONG SegCs, Eip;
    01207
    01208         //
    01209         // Point cs and eip at the iret hook, so when we build
    01210         // the frame below, the correct contents are set
    01211         //
    01212         SegCs = IretHookAddress >> 16;
    01213         Eip   = IretHookAddress & 0xFFFF;
    01214
    01215         if (Frame32) {
    01216
    01217            *(--(PULONG)VdmStackPointer)          = TrapFrame->EFlags;
    01218            *(PUSHORT)(--(PULONG)VdmStackPointer) = (USHORT)SegCs;
    01219            *(--(PULONG)VdmStackPointer)          = Eip;
    01220
    01221         } else {
    01222
    01223            *(--(PUSHORT)VdmStackPointer) = (USHORT)TrapFrame->EFlags;
    01224            *(--(PUSHORT)VdmStackPointer) = (USHORT)SegCs;
    01225            *(--(PUSHORT)VdmStackPointer) = (USHORT)Eip;
    01226
    01227         }
    01228     }
    01229     return STATUS_SUCCESS;
    01230 }

VOID PushRmInterrupt | ( | PKTRAP_FRAME | TrapFrame,
|  | ULONG | IretHookAddress,
|  | PVDM_TIB | VdmTib,
|  | ULONG | InterruptNumber
| ) |

Definition at line 953 of file vdmints.c.

References PAGED_CODE, PUSHORT, USHORT, and _Vdm_Tib::VdmInterruptHandlers.

Referenced by VdmDispatchInterrupts().

    00961                    :
    00962
    00963     Pushes RealMode interrupt frame onto the UserMode stack in the TrapFrame
    00964
    00965 Arguments:
    00966
    00967     TrapFrame          - address of current trapframe
    00968     IretHookAddress    - address of Iret Hook, 0 if none
    00969     VdmTib             - address of current vdm tib
    00970     InterruptNumber    - interrupt number to reflect
    00971
    00972
    00973 Return Value:
    00974
    00975     None.
    00976
    00977 --*/
    00978 {
    00979     ULONG      UserSS;
    00980     USHORT     UserSP;
    00981     USHORT     NewCS;
    00982     USHORT     NewIP;
    00983
    00984     PAGED_CODE();
    00985
    00986
    00987     //
    00988     // Get pointers to current stack
    00989     //
    00990     UserSS  = TrapFrame->HardwareSegSs << 4;
    00991     UserSP  = (USHORT) TrapFrame->HardwareEsp;
    00992
    00993     //
    00994     //  load interrupt stack frame, pushing flags, Cs and ip
    00995     //
    00996     UserSP -= 2;
    00997     *(PUSHORT)(UserSS + UserSP) = (USHORT)TrapFrame->EFlags;
    00998     UserSP -= 2;
    00999     *(PUSHORT)(UserSS + UserSP) = (USHORT)TrapFrame->SegCs;
    01000     UserSP -= 2;
    01001     *(PUSHORT)(UserSS + UserSP) = (USHORT)TrapFrame->Eip;
    01002
    01003
    01004     //
    01005     // load IretHook stack frame if one exists
    01006     //
    01007     if (IretHookAddress) {
    01008        UserSP -= 2;
    01009        *(PUSHORT)(UserSS + UserSP) = (USHORT)(TrapFrame->EFlags & ~EFLAGS_TF_MASK);
    01010        UserSP -= 2;
    01011        *(PUSHORT)(UserSS + UserSP) = (USHORT)(IretHookAddress >> 16);
    01012        UserSP -= 2;
    01013        *(PUSHORT)(UserSS + UserSP) = (USHORT)IretHookAddress;
    01014        }
    01015
    01016     //
    01017     //  Set new sp, ip, and cs.
    01018     //
    01019
    01020     if (VdmTib->VdmInterruptHandlers[InterruptNumber].Flags & VDM_INT_HOOKED) {
    01021         NewCS = (USHORT) (VdmTib->DpmiInfo.DosxRmReflector >> 16);
    01022         NewIP = (USHORT) VdmTib->DpmiInfo.DosxRmReflector;
    01023         //
    01024         // now encode the interrupt number into CS
    01025         //
    01026         NewCS -= (USHORT) InterruptNumber;
    01027         NewIP += (USHORT) (InterruptNumber*16);
    01028
    01029     } else {
    01030         PUSHORT pIvtEntry = (PUSHORT) (InterruptNumber * 4);
    01031
    01032         NewIP = *pIvtEntry++;
    01033         NewCS = *pIvtEntry;
    01034     }
    01035
    01036     TrapFrame->HardwareEsp =  UserSP;
    01037     TrapFrame->Eip         =  NewIP;
    01038     TrapFrame->SegCs       =  NewCS;
    01039 }

int RestartDelayedInterrupts | ( | PVDMICAUSERDATA | pIcaUserData | ) |

Definition at line 715 of file vdmints.c.

References IcaScan(), PAGED_CODE, and TRUE.

Referenced by VdmDispatchInterrupts().

    00718 {
    00719    int line;
    00720
    00721
    00722    PAGED_CODE();
    00723
    00724    *pIcaUserData->pUndelayIrq = 0;
    00725
    00726    line = IcaScan(pIcaUserData, pIcaUserData->pIcaSlave);
    00727    if (line != -1) {
    00728        // set the slave
    00729        pIcaUserData->pIcaSlave->ica_int_line = line;
    00730        pIcaUserData->pIcaSlave->ica_cpu_int = TRUE;
    00731
    00732        // set the master cascade
    00733        line = pIcaUserData->pIcaSlave->ica_ssr;
    00734        pIcaUserData->pIcaMaster->ica_irr |= 1 << line;
    00735        pIcaUserData->pIcaMaster->ica_count[line]++;
    00736        }
    00737
    00738    line = IcaScan(pIcaUserData, pIcaUserData->pIcaMaster);
    00739    if (line != -1) {
    00740        pIcaUserData->pIcaMaster->ica_cpu_int = TRUE;
    00741        pIcaUserData->pIcaMaster->ica_int_line = TRUE;
    00742        }
    00743
    00744    return line;
    00745 }

NTSTATUS VdmDispatchInterrupts | ( | PKTRAP_FRAME | TrapFrame,
|  | PVDM_TIB | VdmTib
| ) |

Definition at line 477 of file vdmints.c.

References _VdmEventInfo::Event, _Vdm_Tib::EventInfo, ExRaiseStatus(), GetIretHookAddress(), IcaAccept(), _VdmEventInfo::InstructionSize, KeBoostPriorityThread(), KeGetCurrentThread, KeI386VdmIoplAllowed, KeI386VirtualIntExtensions, NT_SUCCESS, NTSTATUS(), PAGED_CODE, ProbeForWrite(), PsGetCurrentProcess, PushPmInterrupt(), PushRmInterrupt(), RestartDelayedInterrupts(), Status, USHORT, VDM_HWINT_INCREMENT, VDM_VIRTUAL_INTERRUPTS, VdmEndExecution(), VDMEVENTCLASS, VdmIntAck, VdmpEnterIcaLock(), VdmpExceptionHandler(), VdmpLeaveIcaLock(), and VdmTraceEvent().

Referenced by VdmpQueueIntApcRoutine(), and VdmpStartExecution().

    00483                    :
    00484
    00485     This routine dispatches interrupts to the vdm.
    00486     Assumes that we are in application mode and NOT MONITOR context.
    00487     This routine may switch from application context back to monitor
    00488     context, if it cannot handle the interrupt (Ica in AEOI, or timer
    00489     int pending).
    00490
    00491 Arguments:
    00492
    00493     TrapFrame address of current trapframe
    00494     VdmTib    address of current vdm tib
    00495
    00496 Return Value:
    00497
    00498     None.
    00499
    00500 --*/
    00501 {
    00502     NTSTATUS   Status;
    00503     ULONG      IretHookAddress;
    00504     ULONG      InterruptNumber;
    00505     int        IrqLineNum;
    00506     USHORT     IcaRotate = 0;
    00507     PVDMICAUSERDATA  pIcaUserData;
    00508     PVDMVIRTUALICA   pIcaAdapter;
    00509     VDMEVENTCLASS  VdmEvent = VdmMaxEvent;
    00510
    00511     PAGED_CODE();
    00512
    00513     try {
    00514
    00515        //
    00516        // Probe pointers in IcaUserData which will be touched
    00517        //
    00518        pIcaUserData = ((PVDM_PROCESS_OBJECTS)PsGetCurrentProcess()->VdmObjects)
    00519                       ->pIcaUserData;
    00520
    00521
    00522        ProbeForWrite(pIcaUserData->pAddrIretBopTable,
    00523                      (TrapFrame->EFlags & EFLAGS_V86_MASK)
    00524                          ? VDM_RM_IRETBOPSIZE*16 : VDM_PM_IRETBOPSIZE*16,
    00525                      sizeof(ULONG)
    00526                      );
    00527
    00528        //
    00529        // Take the Ica Lock, if this fails raise status as we can't
    00530        // safely recover the critical section state
    00531        //
    00532        Status = VdmpEnterIcaLock(pIcaUserData->pIcaLock);
    00533        if (!NT_SUCCESS(Status)) {
    00534            ExRaiseStatus(Status);
    00535            }
    00536
    00537
    00538        if (*pIcaUserData->pUndelayIrq)
    00539            RestartDelayedInterrupts(pIcaUserData);
    00540 VDIretry:
    00541
    00542
    00543        //
    00544        // Clear the VIP bit
    00545        //
    00546        if (((KeI386VirtualIntExtensions & V86_VIRTUAL_INT_EXTENSIONS) &&
    00547             (TrapFrame->EFlags & EFLAGS_V86_MASK)) ||
    00548            ((KeI386VirtualIntExtensions & PM_VIRTUAL_INT_EXTENSIONS) &&
    00549             !(TrapFrame->EFlags & EFLAGS_V86_MASK)) )
    00550           {
    00551             TrapFrame->EFlags &= ~EFLAGS_VIP;
    00552            }
    00553
    00554
    00555         //
    00556         // Mark the vdm state as hw int dispatched. Must use the lock as
    00557         // kernel mode DelayedIntApcRoutine changes the bit as well
    00558         //
    00559         _asm {
    00560             mov  eax,FIXED_NTVDMSTATE_LINEAR
    00561             lock and dword ptr [eax], ~VDM_INT_HARDWARE
    00562             }
    00563
    00564        pIcaAdapter = pIcaUserData->pIcaMaster;
    00565        IrqLineNum = IcaAccept(pIcaUserData, pIcaAdapter);
    00566        if (IrqLineNum >= 0) {
    00567            UCHAR bit = 1 << IrqLineNum;
    00568
    00569            if (pIcaUserData->pIcaMaster->ica_ssr & bit) {
    00570                pIcaAdapter = pIcaUserData->pIcaSlave;
    00571                IrqLineNum = IcaAccept(pIcaUserData, pIcaAdapter);
    00572                if (IrqLineNum < 0) {
    00573                    pIcaUserData->pIcaMaster->ica_isr &= ~bit;
    00574                    }
    00575                }
    00576            }
    00577
    00578        //
    00579        // Skip spurious ints
    00580        //
    00581        if (IrqLineNum < 0)  {
    00582           //
    00583           // Check for delayed interrupts which need to be restarted
    00584           //
    00585           if (*pIcaUserData->pUndelayIrq &&
    00586               RestartDelayedInterrupts(pIcaUserData) != -1)
    00587              {
    00588               goto VDIretry;
    00589               }
    00590
    00591           Status = VdmpLeaveIcaLock(pIcaUserData->pIcaLock);
    00592           if (!NT_SUCCESS(Status)) {
    00593               ExRaiseStatus(Status);
    00594               }
    00595
    00596           return Status;
    00597           }
    00598
    00599
    00600        //
    00601        // Capture the AutoEoi mode case for special handling
    00602        //
    00603        if (pIcaAdapter->ica_mode & ICA_AEOI) {
    00604            VdmEvent = VdmIntAck;
    00605            VdmTib->EventInfo.IntAckInfo = (ULONG)IcaRotate | VDMINTACK_AEOI;
    00606            if (pIcaAdapter == pIcaUserData->pIcaSlave) {
    00607                VdmTib->EventInfo.IntAckInfo |= VDMINTACK_SLAVE;
    00608                }
    00609            }
    00610
    00611
    00612        InterruptNumber = IrqLineNum + pIcaAdapter->ica_base;
    00613
    00614        //
    00615        // Get the IretHookAddress ... if any
    00616        //
    00617        if (pIcaAdapter == pIcaUserData->pIcaSlave) {
    00618            IrqLineNum += 8;
    00619            }
    00620
    00621
    00622        IretHookAddress = GetIretHookAddress( TrapFrame,
    00623                                              pIcaUserData,
    00624                                              IrqLineNum
    00625                                              );
    00626
    00627        if (*pNtVDMState & VDM_TRACE_HISTORY) {
    00628             VdmTraceEvent(VDMTR_KERNEL_HW_INT,
    00629                           (USHORT)InterruptNumber,
    00630                           0,
    00631                           TrapFrame);
    00632        }
    00633
    00634        //
    00635        // Push the interrupt frames
    00636        //
    00637        if (TrapFrame->EFlags & EFLAGS_V86_MASK) {
    00638           PushRmInterrupt(TrapFrame,
    00639                           IretHookAddress,
    00640                           VdmTib,
    00641                           InterruptNumber
    00642                           );
    00643           }
    00644        else  {
    00645           Status = PushPmInterrupt(
    00646                           TrapFrame,
    00647                           IretHookAddress,
    00648                           VdmTib,
    00649                           InterruptNumber
    00650                           );
    00651
    00652           if (!NT_SUCCESS(Status)) {
    00653               VdmpLeaveIcaLock(pIcaUserData->pIcaLock);
    00654               ExRaiseStatus(Status);
    00655               }
    00656           }
    00657
    00658         //
    00659         // Disable interrupts and the trap flag
    00660         //
    00661
    00662
    00663         if (((KeI386VirtualIntExtensions & V86_VIRTUAL_INT_EXTENSIONS) &&
    00664              (TrapFrame->EFlags & EFLAGS_V86_MASK)) ||
    00665             ((KeI386VirtualIntExtensions & PM_VIRTUAL_INT_EXTENSIONS) &&
    00666              !(TrapFrame->EFlags & EFLAGS_V86_MASK)) )
    00667            {
    00668             TrapFrame->EFlags &= ~EFLAGS_VIF;
    00669             }
    00670         else if (!KeI386VdmIoplAllowed ||
    00671                  !(TrapFrame->EFlags & EFLAGS_V86_MASK))
    00672            {
    00673             *pNtVDMState &= ~VDM_VIRTUAL_INTERRUPTS;
    00674             }
    00675         else {
    00676             TrapFrame->EFlags &= ~EFLAGS_INTERRUPT_MASK;
    00677             }
    00678
    00679         TrapFrame->EFlags &= ~(EFLAGS_NT_MASK | EFLAGS_TF_MASK);
    00680
    00681         KeBoostPriorityThread(KeGetCurrentThread(), VDM_HWINT_INCREMENT);
    00682
    00683
    00684         //
    00685         // Release the ica lock
    00686         //
    00687         Status = VdmpLeaveIcaLock(pIcaUserData->pIcaLock);
    00688         if (!NT_SUCCESS(Status)) {
    00689             ExRaiseStatus(Status);
    00690             }
    00691
    00692         //
    00693         // check to see if we are supposed to switch back to monitor context
    00694         //
    00695         if (VdmEvent != VdmMaxEvent) {
    00696             VdmTib->EventInfo.Event = VdmIntAck;
    00697             VdmTib->EventInfo.InstructionSize = 0;
    00698             VdmEndExecution(TrapFrame, VdmTib);
    00699             }
    00700         }
    00701     except(VdmpExceptionHandler(GetExceptionInformation())) {
    00702         Status = GetExceptionCode();
    00703         VdmDispatchException(TrapFrame,
    00704                              Status,
    00705                              (PVOID)TrapFrame->Eip,
    00706                              0,0,0,0   // no parameters
    00707                              );
    00708         }
    00709
    00710     return Status;
    00711 }

VOID VdmpDelayIntApcRoutine | ( | IN PKAPC | Apc,
|  | IN PKNORMAL_ROUTINE * | NormalRoutine,
|  | IN PVOID * | NormalContext,
|  | IN PVOID * | SystemArgument1,
|  | IN PVOID * | SystemArgument2
| ) |

Definition at line 1709 of file vdmints.c.

References FALSE, Ke386VdmClearApcObject(), KeAcquireSpinLock, KeReleaseSpinLock(), KernelMode, KPROCESSOR_MODE, NULL, PsGetCurrentProcess, TRUE, VdmpExceptionHandler(), and VdmpQueueIntApcRoutine().

Referenced by VdmpDelayIntDpcRoutine(), and VdmpNullRundownRoutine().

    01719                    :
    01720
    01721     This function is the special APC routine that is called to
    01722     dispatch a delayed interupt. This routines clears the IrqLine
    01723     bit. VdmpQueueIntApcRoutine will restart interrupts.
    01724
    01725 Arguments:
    01726
    01727     Apc - Supplies a pointer to the APC object used to invoke this routine.
    01728
    01729     NormalRoutine - Supplies a pointer to a pointer to an optional
    01730         normal routine, which is executed when wow is blocked.
    01731
    01732     NormalContext - Supplies a pointer to a pointer to an arbitrary data
    01733         structure that was specified when the APC was initialized and is
    01734         NOT USED.
    01735
    01736     SystemArgument1, SystemArgument2 - Supplies a set of two pointers to
    01737         two arguments that contain untyped data that are
    01738         NOT USED.
    01739
    01740 Return Value:
    01741
    01742     None.
    01743
    01744 --*/
    01745
    01746 {
    01747     KIRQL    OldIrql;
    01748     PLIST_ENTRY  Next;
    01749     PDELAYINTIRQ pDelayIntIrq;
    01750     PVDM_PROCESS_OBJECTS pVdmObjects;
    01751     KPROCESSOR_MODE  ProcessorMode;
    01752     PULONG           pDelayIrq;
    01753     PULONG           pUndelayIrq;
    01754     PULONG           pDelayIret;
    01755     ULONG            IrqLine;
    01756     BOOLEAN          FreeIrqLine;
    01757
    01758
    01759     //
    01760     // Get a pointer to pVdmObjects
    01761     //
    01762     pVdmObjects = PsGetCurrentProcess()->VdmObjects;
    01763     ExAcquireFastMutex(&pVdmObjects->DelayIntFastMutex);
    01764     KeAcquireSpinLock(&pVdmObjects->DelayIntSpinLock, &OldIrql);
    01765
    01766     Ke386VdmClearApcObject(Apc);
    01767
    01768     FreeIrqLine = FALSE;
    01769
    01770     try {
    01771
    01772        //
    01773        // Search the DelayedIntList for the pDelayIntIrq.
    01774        //
    01775        Next = pVdmObjects->DelayIntListHead.Flink;
    01776        while (Next != &pVdmObjects->DelayIntListHead) {
    01777            pDelayIntIrq = CONTAINING_RECORD(Next,DELAYINTIRQ,DelayIntListEntry);
    01778            if (&pDelayIntIrq->Apc == Apc) {
    01779                break;
    01780                }
    01781            Next = Next->Flink;
    01782            }
    01783
    01784        if (Next == &pVdmObjects->DelayIntListHead) {
    01785            pDelayIntIrq = NULL;
    01786            }
    01787
    01788        //
    01789        // If we found the IrqLine in the DelayedIntList,
    01790        // restart interrupts.
    01791        //
    01792        if (pDelayIntIrq && pDelayIntIrq->InUse) {
    01793            pDelayIntIrq->InUse  = VDMDELAY_NOTINUSE;
    01794            IrqLine = pDelayIntIrq->IrqLine;
    01795            FreeIrqLine = TRUE;
    01796            }
    01797
    01798        }
    01799     except(VdmpExceptionHandler(GetExceptionInformation())) {
    01800        ; // fall thru
    01801        }
    01802
    01803
    01804     KeReleaseSpinLock(&pVdmObjects->DelayIntSpinLock, OldIrql);
    01805
    01806
    01807     try {
    01808
    01809         if (!FreeIrqLine) {
    01810             leave;
    01811             }
    01812
    01813         pDelayIrq = pVdmObjects->pIcaUserData->pDelayIrq;
    01814         pUndelayIrq = pVdmObjects->pIcaUserData->pUndelayIrq;
    01815         pDelayIret = pVdmObjects->pIcaUserData->pDelayIret;
    01816
    01817         //
    01818         // These variables are being modified without holding the
    01819         // ICA lock. This should be OK because none of the ntvdm
    01820         // devices (timer, mouse etc. should ever do a delayed int
    01821         // while a previous delayed interrupt is still pending.
    01822         //
    01823
    01824         *pDelayIrq &= ~IrqLine;
    01825         _asm {
    01826            mov eax, pUndelayIrq
    01827            mov ebx, IrqLine
    01828            lock or [eax], ebx
    01829            }
    01830
    01831         //
    01832         // If we are waiting for an iret hook we have nothing left to do
    01833         // since the iret hook will restart interrupts.
    01834         //
    01835         if (!(IrqLine & *pDelayIret)) {
    01836
    01837            //
    01838            // set hardware int pending
    01839            //
    01840            _asm {
    01841                mov  eax,FIXED_NTVDMSTATE_LINEAR
    01842                lock or dword ptr [eax], VDM_INT_HARDWARE
    01843                }
    01844
    01845            //
    01846            // Queue a UserModeApc to dispatch interrupts
    01847            //
    01848            if (NormalRoutine) {
    01849                ProcessorMode = KernelMode;
    01850                VdmpQueueIntApcRoutine(Apc,
    01851                                       NormalRoutine,
    01852                                       (PVOID *)&ProcessorMode,
    01853                                       SystemArgument1,
    01854                                       SystemArgument2
    01855                                       );
    01856                }
    01857            }
    01858         }
    01859     except(VdmpExceptionHandler(GetExceptionInformation())) {
    01860        ; // fall thru
    01861        }
    01862
    01863     ExReleaseFastMutex(&pVdmObjects->DelayIntFastMutex);
    01864
    01865     return;
    01866 }

VOID VdmpDelayIntDpcRoutine | ( | IN PKDPC | Dpc,
|  | IN PVOID | DeferredContext,
|  | IN PVOID | SystemArgument1,
|  | IN PVOID | SystemArgument2
| ) |

Definition at line 1583 of file vdmints.c.

References Ke386VdmInsertQueueApc(), KeAcquireSpinLock, KeReleaseSpinLock(), KernelMode, NULL, ObDereferenceObject, _ETHREAD::Tcb, VDM_HWINT_INCREMENT, _EPROCESS::VdmObjects, VdmpDelayIntApcRoutine(), VdmpNullRundownRoutine(), and VdmpQueueIntNormalRoutine().

Referenced by VdmpDelayInterrupt().

    01592                    :
    01593
    01594     This function is the DPC routine that is called when a DelayedInterrupt
    01595     timer expires. Its function is to insert the associated APC into the
    01596     target thread's APC queue.
    01597
    01598 Arguments:
    01599
    01600     Dpc - Supplies a pointer to a control object of type DPC.
    01601
    01602     DeferredContext - Supplies a pointer to the Target EProcess
    01603
    01604     SystemArgument1, SystemArgument2 - Supplies a set of two pointers to
    01605         two arguments that contain untyped data that are
    01606         NOT USED.
    01607
    01608
    01609 Return Value:
    01610
    01611     None.
    01612
    01613 --*/
    01614
    01615 {
    01616
    01617     PVDM_PROCESS_OBJECTS pVdmObjects;
    01618     PEPROCESS    Process;
    01619     PETHREAD     Thread, MainThread;
    01620     PLIST_ENTRY  Next;
    01621     PDELAYINTIRQ pDelayIntIrq;
    01622     KIRQL        OldIrql;
    01623
    01624     //
    01625     // Get address of Process VdmObjects
    01626     //
    01627     Process = (PEPROCESS)DeferredContext;
    01628     pVdmObjects = (PVDM_PROCESS_OBJECTS)Process->VdmObjects;
    01629
    01630
    01631     KeAcquireSpinLock(&pVdmObjects->DelayIntSpinLock, &OldIrql);
    01632
    01633
    01634     //
    01635     // Search the DelayedIntList for the matching Dpc.
    01636     //
    01637     Next = pVdmObjects->DelayIntListHead.Flink;
    01638     while (Next != &pVdmObjects->DelayIntListHead) {
    01639         pDelayIntIrq = CONTAINING_RECORD(Next,DELAYINTIRQ,DelayIntListEntry);
    01640         if (&pDelayIntIrq->Dpc == Dpc) {
    01641             break;
    01642             }
    01643         Next = Next->Flink;
    01644         }
    01645
    01646     if (Next == &pVdmObjects->DelayIntListHead) {
    01647         pDelayIntIrq = NULL;
    01648         MainThread = Thread = NULL;
    01649         }
    01650     else {
    01651         Thread = pDelayIntIrq->Thread;
    01652         pDelayIntIrq->Thread = NULL;
    01653         MainThread = pDelayIntIrq->MainThread;
    01654         pDelayIntIrq->MainThread = NULL;
    01655         }
    01656
    01657
    01658     if (pDelayIntIrq && pDelayIntIrq->InUse) {
    01659         if ((Thread &&
    01660              Ke386VdmInsertQueueApc(&pDelayIntIrq->Apc,
    01661                                     &Thread->Tcb,
    01662                                     KernelMode,
    01663                                     VdmpDelayIntApcRoutine,
    01664                                     VdmpNullRundownRoutine,    // rundown
    01665                                     VdmpQueueIntNormalRoutine, // normal routine
    01666                                     NULL,                      // NormalContext
    01667                                     VDM_HWINT_INCREMENT
    01668                                     ))
    01669             ||
    01670             (MainThread &&
    01671              Ke386VdmInsertQueueApc(&pDelayIntIrq->Apc,
    01672                                     &MainThread->Tcb,
    01673                                     KernelMode,
    01674                                     VdmpDelayIntApcRoutine,
    01675                                     VdmpNullRundownRoutine,    // rundown
    01676                                     VdmpQueueIntNormalRoutine, // normal routine
    01677                                     NULL,                      // NormalContext
    01678                                     VDM_HWINT_INCREMENT
    01679                                     )))
    01680            {
    01681             pDelayIntIrq->InUse  = VDMDELAY_KAPC;
    01682             }
    01683         else {
    01684             // This hwinterrupt line is blocked forever.
    01685             pDelayIntIrq->InUse  = VDMDELAY_NOTINUSE;
    01686             }
    01687         }
    01688
    01689
    01690     KeReleaseSpinLock(&pVdmObjects->DelayIntSpinLock, OldIrql);
    01691
    01692     if (Thread) {
    01693         ObDereferenceObject(Thread);
    01694         }
    01695
    01696     if (MainThread) {
    01697         ObDereferenceObject(MainThread);
    01698         }
    01699
    01700     ObDereferenceObject(Process);
    01701
    01702
    01703     return;
    01704 }

NTSTATUS VdmpDelayInterrupt | ( | PVDMDELAYINTSDATA | pdsd | ) |

Definition at line 1235 of file vdmints.c.

References Delay, ExAllocatePoolWithTag, EXCEPTION_EXECUTE_HANDLER, ExFreePool(), FALSE, KeAcquireSpinLock, KeInitializeDpc(), KeInitializeTimer(), KeMaximumIncrement, KeMinimumIncrement, KeReleaseSpinLock(), KernelMode, KeSetTimer(), KeTimeIncrement, NonPagedPool, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObject, ObReferenceObjectByHandle(), ObReferenceObjectByPointer(), _EPROCESS::Pcb, ProbeForRead, ProbeForWriteUlong, PsChargePoolQuota(), PsGetCurrentProcess, PsThreadType, Status, TRUE, _EPROCESS::VdmObjects, and VdmpDelayIntDpcRoutine().

Referenced by NtVdmControl().

    01241                    :
    01242
    01243     Sets a timer to dispatch the delayed interrupt through KeSetTimer.
    01244     When the timer fires a user mode APC is queued to queue the interrupt.
    01245
    01246     This function uses lazy allocation routines to allocate internal
    01247     data structures (nonpaged pool) on a per Irq basis, and needs to
    01248     be notified when specific Irq Lines no longer need Delayed
    01249     Interrupt services.
    01250
    01251     The caller must own the IcaLock to synchronize access to the
    01252     Irq lists.
    01253
    01254     WARNING: - Until the Delayed interrupt fires or is cancelled,
    01255                the specific Irq line will not generate any interrupts.
    01256
    01257              - The APC routine, does not take the HostIca lock, when
    01258                unblocking the IrqLine. Devices which use delayed Interrupts
    01259                should not queue ANY additional interrupts for the same IRQ
    01260                line until the delayed interrupt has fired or been cancelled.
    01261
    01262 Arguments:
    01263
    01264     pdsd.Delay         Delay Interval in usecs
    01265                        if Delay is 0xFFFFFFFF then per Irq Line nonpaged
    01266                            data structures are freed. No Timers are set.
    01267                        else the Delay is used as the timer delay.
    01268
    01269     pdsd.DelayIrqLine  IrqLine Number
    01270
    01271     pdsd.hThread       Thread Handle of CurrentMonitorTeb
    01272
    01273
    01274 Return Value:
    01275
    01276     NTSTATUS.
    01277
    01278 --*/
    01279
    01280 {
    01281     PVDM_PROCESS_OBJECTS pVdmObjects;
    01282     PLIST_ENTRY   Next;
    01283     PEPROCESS     Process;
    01284     PDELAYINTIRQ  pDelayIntIrq;
    01285     PETHREAD      Thread, MainThread;
    01286     NTSTATUS      Status;
    01287     KIRQL         OldIrql;
    01288     ULONG         IrqLine;
    01289     ULONG         Delay;
    01290     PULONG        pDelayIrq;
    01291     PULONG        pUndelayIrq;
    01292     LARGE_INTEGER liDelay;
    01293     BOOLEAN       FreeIrqLine, AlreadyInUse;
    01294
    01295
    01296
    01297     //
    01298     // Get a pointer to pVdmObjects
    01299     //
    01300     Process = PsGetCurrentProcess();
    01301     pVdmObjects = Process->VdmObjects;
    01302     if (Process->Pcb.VdmFlag != TRUE || !pVdmObjects) {
    01303         return STATUS_INVALID_PARAMETER_1;
    01304         }
    01305
    01306     ExAcquireFastMutex(&pVdmObjects->DelayIntFastMutex);
    01307
    01308     Status = STATUS_SUCCESS;
    01309     Thread = MainThread = NULL;
    01310     FreeIrqLine = TRUE;
    01311     AlreadyInUse = FALSE;
    01312
    01313     try {
    01314
    01315         //
    01316         // Probe the parameters
    01317         //
    01318         ProbeForRead(pdsd, sizeof(VDMDELAYINTSDATA), sizeof(ULONG));
    01319
    01320         //
    01321         // Form a BitMask for the IrqLine Number
    01322         //
    01323         IrqLine = 1 << pdsd->DelayIrqLine;
    01324         if (!IrqLine) {
    01325             Status = STATUS_INVALID_PARAMETER_2;
    01326             goto VidEarlyExit;
    01327             }
    01328
    01329         pDelayIrq = pVdmObjects->pIcaUserData->pDelayIrq;
    01330         ProbeForWriteUlong(pDelayIrq);
    01331         pUndelayIrq = pVdmObjects->pIcaUserData->pUndelayIrq;
    01332         ProbeForWriteUlong(pUndelayIrq);
    01333
    01334
    01335         //
    01336         // Copy out the Delay parameter, and convert hundreths nanosecs
    01337         //
    01338         Delay = pdsd->Delay;
    01339
    01340         //
    01341         // Check to see if we need to reset the timer resolution
    01342         //
    01343         if (Delay == 0xFFFFFFFF) {
    01344             ZwSetTimerResolution(KeMaximumIncrement, FALSE, &Delay);
    01345             goto VidEarlyExit;
    01346             }
    01347
    01348
    01349          FreeIrqLine = FALSE;
    01350
    01351             // convert delay to hundreths of nanosecs
    01352             // and ensure min delay of 1 msec
    01353             //
    01354          Delay = Delay < 1000 ? 10000 : Delay * 10;
    01355
    01356             //
    01357             // If the delay time is close to the system's clock rate
    01358             // then adjust the system's clock rate and if needed
    01359             // the delay time so that the timer will fire before the
    01360             // the due time.
    01361             //
    01362          if (Delay < 150000) {
    01363              ULONG ul = Delay >> 1;
    01364
    01365              if (ul < KeTimeIncrement && KeTimeIncrement > KeMinimumIncrement) {
    01366                  ZwSetTimerResolution(ul, TRUE, (PULONG)&liDelay.LowPart);
    01367                  }
    01368
    01369              if (Delay < KeTimeIncrement) {
    01370                  // can't set system clock rate low enuf, so use half delay
    01371                  Delay >>= 1;
    01372                  }
    01373              else if (Delay < (KeTimeIncrement << 1)) {
    01374                  // Real close to the system clock rate, lower delay
    01375                  // proportionally, to avoid missing clock cycles.
    01376                  Delay -= KeTimeIncrement >> 1;
    01377                  }
    01378              }
    01379
    01380          //
    01381          // Reference the Target Thread
    01382          //
    01383          Status = ObReferenceObjectByHandle(
    01384                           pdsd->hThread,
    01385                           THREAD_QUERY_INFORMATION,
    01386                           PsThreadType,
    01387                           KeGetPreviousMode(),
    01388                           &Thread,
    01389                           NULL
    01390                           );
    01391          if (!NT_SUCCESS(Status)) {
    01392              Thread = NULL;
    01393              goto VidEarlyExit;
    01394              }
    01395
    01396
    01397          Status = ObReferenceObjectByPointer(
    01398                           pVdmObjects->MainThread,
    01399                           THREAD_QUERY_INFORMATION,
    01400                           PsThreadType,
    01401                           KernelMode
    01402                           );
    01403          if (NT_SUCCESS(Status)) {
    01404              MainThread = pVdmObjects->MainThread;
    01405              }
    01406          else {
    01407              goto VidEarlyExit;
    01408              }
    01409
    01410 VidEarlyExit:;
    01411         }
    01412    except(EXCEPTION_EXECUTE_HANDLER) {
    01413         Status = GetExceptionCode();
    01414         }
    01415
    01416    if (!NT_SUCCESS(Status)) {
    01417        ExReleaseFastMutex(&pVdmObjects->DelayIntFastMutex);
    01418        if (Thread) {
    01419            ObDereferenceObject(Thread);
    01420            }
    01421
    01422        if (MainThread) {
    01423            ObDereferenceObject(MainThread);
    01424            }
    01425
    01426        return Status;
    01427        }
    01428
    01429
    01430
    01431    KeAcquireSpinLock(&pVdmObjects->DelayIntSpinLock, &OldIrql);
    01432
    01433    try {
    01434
    01435         //
    01436         // Search the DelayedIntList for a matching Irq Line.
    01437         //
    01438         Next = pVdmObjects->DelayIntListHead.Flink;
    01439         while (Next != &pVdmObjects->DelayIntListHead) {
    01440             pDelayIntIrq = CONTAINING_RECORD(Next, DELAYINTIRQ, DelayIntListEntry);
    01441             if (pDelayIntIrq->IrqLine == IrqLine) {
    01442                 break;
    01443                 }
    01444             Next = Next->Flink;
    01445             }
    01446
    01447         if (Next == &pVdmObjects->DelayIntListHead) {
    01448             pDelayIntIrq = NULL;
    01449             }
    01450
    01451
    01452         if (!pDelayIntIrq) {
    01453             if (FreeIrqLine) {
    01454                 goto VidExit;
    01455                 }
    01456
    01457             //
    01458             // If a DelayIntIrq does not exist for this irql, allocate from nonpaged
    01459             // pool and initialize it
    01460             //
    01461
    01462             pDelayIntIrq = ExAllocatePoolWithTag(NonPagedPool,
    01463                                                  sizeof(DELAYINTIRQ),
    01464                                                  ' MDV');
    01465
    01466             if (!pDelayIntIrq) {
    01467                 Status = STATUS_NO_MEMORY;
    01468                 goto VidExit;
    01469                 }
    01470
    01471
    01472             try {
    01473                 PsChargePoolQuota(Process, NonPagedPool, sizeof(DELAYINTIRQ));
    01474                 }
    01475             except(EXCEPTION_EXECUTE_HANDLER) {
    01476                 Status = GetExceptionCode();
    01477                 ExFreePool(pDelayIntIrq);
    01478                 goto VidExit;
    01479                 }
    01480             RtlZeroMemory(pDelayIntIrq, sizeof(DELAYINTIRQ));
    01481             pDelayIntIrq->IrqLine = IrqLine;
    01482
    01483             KeInitializeTimer(&pDelayIntIrq->Timer);
    01484
    01485             KeInitializeDpc(&pDelayIntIrq->Dpc,
    01486                             VdmpDelayIntDpcRoutine,
    01487                             Process
    01488                             );
    01489
    01490             InsertTailList(&pVdmObjects->DelayIntListHead,
    01491                            &pDelayIntIrq->DelayIntListEntry
    01492                            );
    01493             }
    01494
    01495
    01496          if (Delay == 0xFFFFFFFF) {
    01497              if (pDelayIntIrq->InUse == VDMDELAY_KTIMER) {
    01498                  pDelayIntIrq->InUse = VDMDELAY_NOTINUSE;
    01499                  pDelayIntIrq = NULL;
    01500                  }
    01501              }
    01502          else if (pDelayIntIrq->InUse == VDMDELAY_NOTINUSE) {
    01503              liDelay = RtlEnlargedIntegerMultiply(Delay, -1);
    01504              KeSetTimer(&pDelayIntIrq->Timer, liDelay, &pDelayIntIrq->Dpc);
    01505              ObReferenceObject(Process);
    01506              }
    01507
    01508 VidExit:;
    01509         }
    01510     except(EXCEPTION_EXECUTE_HANDLER)  {
    01511         Status = GetExceptionCode();
    01512         }
    01513
    01514     if (pDelayIntIrq && !pDelayIntIrq->InUse) {
    01515
    01516         if (NT_SUCCESS(Status)) {
    01517             //
    01518             // Save PETHREAD of Target thread for the dpc routine
    01519             // the DPC routine will deref the threads.
    01520             //
    01521             pDelayIntIrq->InUse = VDMDELAY_KTIMER;
    01522             pDelayIntIrq->Thread = Thread;
    01523             Thread = NULL;
    01524             pDelayIntIrq->MainThread = MainThread;
    01525             MainThread = NULL;
    01526             }
    01527         else {
    01528             pDelayIntIrq->InUse = VDMDELAY_NOTINUSE;
    01529             pDelayIntIrq->Thread = NULL;
    01530             FreeIrqLine = TRUE;
    01531             }
    01532         }
    01533     else {
    01534         AlreadyInUse = TRUE;
    01535         }
    01536
    01537
    01538
    01539     KeReleaseSpinLock(&pVdmObjects->DelayIntSpinLock, OldIrql);
    01540
    01541     try {
    01542         if (FreeIrqLine) {
    01543             *pDelayIrq &= ~IrqLine;
    01544             _asm {
    01545                mov eax, pUndelayIrq
    01546                mov ebx, IrqLine
    01547                lock or [eax], ebx
    01548                }
    01549             }
    01550         else  if (!AlreadyInUse) {  // TakeIrqLine
    01551             *pDelayIrq |= IrqLine;
    01552             _asm {
    01553                mov eax, pUndelayIrq
    01554                mov ebx, IrqLine
    01555                not ebx
    01556                lock and [eax], ebx
    01557                }
    01558             }
    01559         }
    01560     except(EXCEPTION_EXECUTE_HANDLER)  {
    01561         Status = GetExceptionCode();
    01562         }
    01563
    01564     ExReleaseFastMutex(&pVdmObjects->DelayIntFastMutex);
    01565
    01566     if (Thread) {
    01567         ObDereferenceObject(Thread);
    01568         }
    01569
    01570     if (MainThread) {
    01571         ObDereferenceObject(MainThread);
    01572         }
    01573
    01574     return Status;
    01575
    01576 }

BOOLEAN VdmpDispatchableIntPending | ( | ULONG | EFlags | ) |

Definition at line 1870 of file vdmints.c.

References ASSERT, KeI386VdmIoplAllowed, KeI386VirtualIntExtensions, PAGED_CODE, and VDM_VIRTUAL_INTERRUPTS.

    01875                    :
    01876
    01877     This routine determines whether or not there is a dispatchable
    01878     virtual interrupt to dispatch.
    01879
    01880 Arguments:
    01881
    01882     EFlags -- supplies a pointer to the EFlags to be checked
    01883
    01884 Return Value:
    01885
    01886     True -- a virtual interrupt should be dispatched
    01887     False -- no virtual interrupt should be dispatched
    01888
    01889 --*/
    01890 {
    01891     PAGED_CODE();
    01892     //
    01893     // Insure that we are not trying to run with IOPL and pentium extensions
    01894     //
    01895     ASSERT((!(KeI386VdmIoplAllowed &&
    01896         (KeI386VirtualIntExtensions & (V86_VIRTUAL_INT_EXTENSIONS |
    01897         PM_VIRTUAL_INT_EXTENSIONS)))));
    01898
    01899     if (EFlags & EFLAGS_V86_MASK) {
    01900         if (KeI386VirtualIntExtensions & V86_VIRTUAL_INT_EXTENSIONS) {
    01901             return(0 != (EFlags & EFLAGS_VIF));
    01902         } else if (KeI386VdmIoplAllowed) {
    01903             return (0 != (EFlags & EFLAGS_INTERRUPT_MASK));
    01904         } else {
    01905             return (0 != (*pNtVDMState & VDM_VIRTUAL_INTERRUPTS));
    01906         }
    01907     } else {
    01908         if (KeI386VirtualIntExtensions & PM_VIRTUAL_INT_EXTENSIONS) {
    01909             return(0 != (EFlags & EFLAGS_VIF));
    01910         } else {
    01911             return (0 != (*pNtVDMState & VDM_VIRTUAL_INTERRUPTS));
    01912         }
    01913     }
    01914 }

int VdmpExceptionHandler | ( | IN PEXCEPTION_POINTERS | ExceptionInfo | ) |

Definition at line 1996 of file vdmints.c.

References DbgPrint, EXCEPTION_EXECUTE_HANDLER, and PAGED_CODE.

Referenced by VdmDispatchInterrupts(), VdmpDelayIntApcRoutine(), VdmpQueueIntApcRoutine(), and VdmpQueueIntNormalRoutine().

    01999 {
    02000 #if DBG
    02001     PEXCEPTION_RECORD ExceptionRecord;
    02002     PCONTEXT ContextRecord;
    02003     ULONG NumberParameters;
    02004     PULONG ExceptionInformation;
    02005 #endif
    02006
    02007     PAGED_CODE();
    02008
    02009 #if DBG
    02010
    02011     ExceptionRecord = ExceptionInfo->ExceptionRecord;
    02012     DbgPrint("VdmExRecord ExCode %x Flags %x Address %x\n",
    02013              ExceptionRecord->ExceptionCode,
    02014              ExceptionRecord->ExceptionFlags,
    02015              ExceptionRecord->ExceptionAddress
    02016              );
    02017
    02018     NumberParameters = ExceptionRecord->NumberParameters;
    02019     if (NumberParameters) {
    02020         DbgPrint("VdmExRecord Parameters:\n");
    02021
    02022         ExceptionInformation = ExceptionRecord->ExceptionInformation;
    02023         while (NumberParameters--) {
    02024            DbgPrint("\t%x\n", *ExceptionInformation);
    02025            }
    02026         }
    02027
    02028 #endif
    02029
    02030     return EXCEPTION_EXECUTE_HANDLER;
    02031 }

NTSTATUS VdmpIsThreadTerminating | ( | HANDLE | ThreadId | ) |

Definition at line 1922 of file vdmints.c.

References NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, PAGED_CODE, PsIsThreadTerminating, PsLookupProcessThreadByCid(), and Status.

    01927                    :
    01928
    01929     This routine determines if the specified thread is terminating or not.
    01930
    01931 Arguments:
    01932
    01933 Return Value:
    01934
    01935     True --
    01936     False -
    01937
    01938 --*/
    01939 {
    01940     CLIENT_ID     Cid;
    01941     PETHREAD      Thread;
    01942     NTSTATUS      Status;
    01943
    01944     PAGED_CODE();
    01945
    01946         //
    01947         // If the owning thread juest exited the IcaLock the
    01948         // OwningThread Tid may be NULL, return success, since
    01949         // we don't know what the owning threads state was.
    01950         //
    01951     if (!ThreadId) {
    01952         return STATUS_SUCCESS;
    01953         }
    01954
    01955     Cid.UniqueProcess = NtCurrentTeb()->ClientId.UniqueProcess;
    01956     Cid.UniqueThread  = ThreadId;
    01957
    01958     Status = PsLookupProcessThreadByCid(&Cid, NULL, &Thread);
    01959     if (NT_SUCCESS(Status)) {
    01960         Status = PsIsThreadTerminating(Thread) ? STATUS_THREAD_IS_TERMINATING
    01961                                                : STATUS_SUCCESS;
    01962         ObDereferenceObject(Thread);
    01963         }
    01964
    01965     return Status;
    01966 }

VOID VdmpNullRundownRoutine | ( | IN PKAPC | Apc | ) |

Definition at line 1969 of file vdmints.c.

References NULL, and VdmpDelayIntApcRoutine().

Referenced by VdmpDelayIntDpcRoutine(), VdmpQueueIntApcRoutine(), and VdmpQueueInterrupt().

    01974                    :
    01975
    01976     This routine is used as a rundown routine for our APC.
    01977     Attempts to clear the delayed int state
    01978
    01979 Arguments:
    01980
    01981     Apc - Supplies a pointer to the Apc to run down.
    01982
    01983 Return Value:
    01984
    01985     None.
    01986
    01987 --*/
    01988 {
    01989    VdmpDelayIntApcRoutine( Apc, NULL, NULL, NULL, NULL);
    01990 }

VOID VdmpQueueIntApcRoutine | ( | IN PKAPC | Apc,
|  | IN PKNORMAL_ROUTINE * | NormalRoutine,
|  | IN PVOID * | NormalContext,
|  | IN PVOID * | SystemArgument1,
|  | IN PVOID * | SystemArgument2
| ) |

Definition at line 232 of file vdmints.c.

References ASSERT, _VdmEventInfo::Event, _Vdm_Tib::EventInfo, _VdmEventInfo::InstructionSize, Ke386VdmClearApcObject(), Ke386VdmInsertQueueApc(), KeI386VirtualIntExtensions, KernelMode, KPROCESSOR_MODE, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, PsGetCurrentProcess, PsGetCurrentThread, PsIsThreadTerminating, Status, _ETHREAD::Tcb, UserMode, VDM_HWINT_INCREMENT, VDM_INTERRUPT_PENDING, VdmDispatchInterrupts(), VdmEndExecution(), VdmIntAck, VdmpDispatchableIntPending(), VdmpExceptionHandler(), VdmpGetVdmTib(), VdmpNullRundownRoutine(), VdmpQueueIntApcRoutine(), and VDMTIB_KPROBE.

Referenced by VdmpDelayIntApcRoutine(), VdmpQueueIntApcRoutine(), and VdmpQueueInterrupt().

    00242                    :
    00243
    00244     Kernel and User mode Special Apc routine to dispatchvirtual
    00245     interrupts to the vdm.
    00246
    00247     For KernelMode routine:
    00248         if vdm is running in application mode
    00249            queue a UserModeApc to the same thread
    00250         else do nothing
    00251
    00252     For UserMode routine
    00253         if vdm is running in application mode dispatch virtual interrupts
    00254         else do nothing
    00255
    00256 Arguments:
    00257
    00258     Apc -
    00259         Supplies a pointer to the APC object used to invoke this routine.
    00260
    00261     NormalRoutine -
    00262         Supplies a pointer to a pointer to the normal routine
    00263         function that was specified when the APC was initialized.
    00264
    00265     NormalContext - Supplies a pointer to the processor mode
    00266         specifying that this is a Kernel Mode or UserMode apc
    00267
    00268     SystemArgument1 -
    00269
    00270     SystemArgument2 - NOT USED
    00271         Supplies a set of two pointers to two arguments that contain
    00272         untyped data.
    00273
    00274 Return Value:
    00275
    00276     None.
    00277
    00278 --*/
    00279
    00280 {
    00281     PVDM_PROCESS_OBJECTS pVdmObjects;
    00282     NTSTATUS     Status;
    00283     PETHREAD     Thread;
    00284     PKTRAP_FRAME TrapFrame;
    00285     PVDM_TIB     VdmTib;
    00286
    00287     PAGED_CODE();
    00288
    00289     Ke386VdmClearApcObject(Apc);
    00290
    00291
    00292     try {
    00293
    00294         //
    00295         // Get the trap frame for the current thread
    00296         //
    00297         Thread    = PsGetCurrentThread();
    00298
    00299         //
    00300         // If the thread is dying, bail out
    00301         //
    00302         if (PsIsThreadTerminating(Thread))
    00303             return;
    00304
    00305         //
    00306         // if no pending interrupts, ignore this APC.
    00307         //
    00308         if (!(*pNtVDMState & VDM_INTERRUPT_PENDING)) {
    00309             return;
    00310             }
    00311
    00312         TrapFrame = VdmGetTrapFrame(&Thread->Tcb);
    00313
    00314         if (VdmpDispatchableIntPending(TrapFrame->EFlags))
    00315           {
    00316             pVdmObjects = PsGetCurrentProcess()->VdmObjects;
    00317                 //
    00318                 // if we are in v86 mode or segmented protected mode
    00319                 // then queue the UserMode Apc, which will dispatch
    00320                 // the hardware interrupt
    00321                 //
    00322             if ((TrapFrame->EFlags & EFLAGS_V86_MASK) ||
    00323                  TrapFrame->SegCs != (KGDT_R3_CODE | RPL_MASK))
    00324               {
    00325                 if ((KPROCESSOR_MODE)*NormalContext == KernelMode) {
    00326
    00327                      Ke386VdmInsertQueueApc(
    00328                              &pVdmObjects->QueuedIntUserApc,
    00329                              &Thread->Tcb,
    00330                              UserMode,
    00331                              VdmpQueueIntApcRoutine,
    00332                              VdmpNullRundownRoutine,// rundown
    00333                              NULL,                  // normal routine
    00334                              (PVOID)UserMode,       // NormalContext
    00335                              (*pNtVDMState & VDM_INT_HARDWARE) // PrBoost
    00336                               ? VDM_HWINT_INCREMENT : 0
    00337                              );
    00338
    00339                     }
    00340                 else  {
    00341                      ASSERT(*NormalContext == (PVOID)UserMode);
    00342
    00343                      Status = VdmpGetVdmTib(&VdmTib, VDMTIB_KPROBE);
    00344                      if (!NT_SUCCESS(Status)) {
    00345                         return;
    00346                      }
    00347
    00348
    00349                      //VdmTib = (PsGetCurrentProcess()->VdmObjects)->VdmTib;
    00350                      // VdmTib =
    00351                      //    ((PVDM_PROCESS_OBJECTS)(PsGetCurrentProcess()->VdmObjects))->VdmTib;
    00352
    00353                         //
    00354                         // If there are no hardware ints, dispatch timer ints
    00355                         // else dispatch hw interrupts
    00356                         //
    00357                      if (*pNtVDMState & VDM_INT_TIMER &&
    00358                          !(*pNtVDMState & VDM_INT_HARDWARE))
    00359                        {
    00360                          VdmTib->EventInfo.Event = VdmIntAck;
    00361                          VdmTib->EventInfo.InstructionSize = 0;
    00362                          VdmTib->EventInfo.IntAckInfo = 0;
    00363                          VdmEndExecution(TrapFrame, VdmTib);
    00364                          }
    00365                      else {
    00366                          VdmDispatchInterrupts(TrapFrame, VdmTib);
    00367                          }
    00368                      }
    00369                 }
    00370
    00371                 //
    00372                 // If we are not in application mode and wow is all blocked
    00373                 // then Wake up WowExec by setting the wow idle event
    00374                 //
    00375             else if (*NormalRoutine &&
    00376                      !(*pNtVDMState & VDM_WOWBLOCKED))
    00377                {
    00378                 *NormalRoutine = NULL;
    00379                 }
    00380
    00381             }
    00382         // WARNING this may set VIP for flat if VPI is ever set in CR4
    00383         else if (((KeI386VirtualIntExtensions & V86_VIRTUAL_INT_EXTENSIONS) &&
    00384                   (TrapFrame->EFlags & EFLAGS_V86_MASK)) ||
    00385                  ((KeI386VirtualIntExtensions & PM_VIRTUAL_INT_EXTENSIONS) &&
    00386                   !(TrapFrame->EFlags & EFLAGS_V86_MASK)) )
    00387            {
    00388             // The CPU traps EVERY instruction if VIF and VIP are both ON.
    00389             // Make sure that you set VIP ON only when  there are pending
    00390             // interrupts, i.e. (*pNtVDMState & VDM_INTERRUPT_PENDING) != 0.
    00391             ASSERT(*pNtVDMState & VDM_INTERRUPT_PENDING);
    00392
    00393             TrapFrame->EFlags |= EFLAGS_VIP;
    00394             }
    00395         }
    00396     except(VdmpExceptionHandler(GetExceptionInformation()))  {
    00397         VdmDispatchException(TrapFrame,
    00398                              GetExceptionCode(),
    00399                              (PVOID)TrapFrame->Eip,
    00400                              0,0,0,0   // no parameters
    00401                              );
    00402         return;
    00403         }
    00404 }

NTSTATUS VdmpQueueInterrupt | ( | IN HANDLE | ThreadHandle | ) |

Definition at line 146 of file vdmints.c.

References Ke386VdmInsertQueueApc(), KernelMode, KPROCESSOR_MODE, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), PAGED_CODE, _EPROCESS::Pcb, PsGetCurrentProcess, PsThreadType, Status, _ETHREAD::Tcb, ThreadHandle, _ETHREAD::ThreadsProcess, TRUE, _EPROCESS::VdmObjects, VdmpNullRundownRoutine(), VdmpQueueIntApcRoutine(), and VdmpQueueIntNormalRoutine().

Referenced by NtVdmControl().

    00152                    :
    00153
    00154     Queues a user mode APC to the specifed application thread
    00155     which will dispatch an interrupt.
    00156
    00157     if APC is already queued to specified thread
    00158        does nothing
    00159
    00160     if APC is queued to the wrong thread
    00161        dequeue it
    00162
    00163     Reset the user APC for the specifed thread
    00164
    00165     Insert the APC in the queue for the specifed thread
    00166
    00167 Arguments:
    00168
    00169     ThreadHandle - handle of thread to insert QueueIntApcRoutine
    00170
    00171 Return Value:
    00172
    00173     NTSTATUS.
    00174
    00175 --*/
    00176
    00177 {
    00178
    00179     PEPROCESS    Process;
    00180     PETHREAD     Thread;
    00181     NTSTATUS     Status;
    00182     KPROCESSOR_MODE      PrevMode;
    00183     PVDM_PROCESS_OBJECTS pVdmObjects;
    00184
    00185     PAGED_CODE();
    00186
    00187
    00188     PrevMode = KeGetPreviousMode();
    00189
    00190     Status = ObReferenceObjectByHandle(ThreadHandle,
    00191                                        THREAD_QUERY_INFORMATION,
    00192                                        PsThreadType,
    00193                                        PrevMode,
    00194                                        &Thread,
    00195                                        NULL
    00196                                        );
    00197     if (!NT_SUCCESS(Status)) {
    00198         return Status;
    00199         }
    00200
    00201     Process = PsGetCurrentProcess();
    00202     if (Process != Thread->ThreadsProcess || Process->Pcb.VdmFlag != TRUE)
    00203       {
    00204         Status = STATUS_INVALID_PARAMETER_1;
    00205         }
    00206     else {
    00207         pVdmObjects = Process->VdmObjects;
    00208
    00209         if (!Ke386VdmInsertQueueApc(&pVdmObjects->QueuedIntApc,
    00210                                     &Thread->Tcb,
    00211                                     KernelMode,
    00212                                     VdmpQueueIntApcRoutine,
    00213                                     VdmpNullRundownRoutine, // rundown
    00214                                     VdmpQueueIntNormalRoutine, // normal routine
    00215                                     (PVOID)KernelMode,      // NormalContext
    00216                                     0
    00217                                     ))
    00218            {
    00219             Status = STATUS_UNSUCCESSFUL;
    00220             }
    00221         else {
    00222             Status = STATUS_SUCCESS;
    00223             }
    00224         }
    00225
    00226     ObDereferenceObject(Thread);
    00227     return Status;
    00228 }

VOID VdmpQueueIntNormalRoutine | ( | IN PVOID | NormalContext,
|  | IN PVOID | SystemArgument1,
|  | IN PVOID | SystemArgument2
| ) |

Definition at line 408 of file vdmints.c.

References Event(), EVENT_INCREMENT, ExEventObjectType, FALSE, KeSetEvent(), NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), PsGetCurrentProcess, PsGetCurrentThread, Status, _ETHREAD::Tcb, UserMode, and VdmpExceptionHandler().

Referenced by VdmpDelayIntDpcRoutine(), and VdmpQueueInterrupt().

    00415                    :
    00416
    00417
    00418
    00419 Arguments:
    00420
    00421
    00422 Return Value:
    00423
    00424     None.
    00425
    00426 --*/
    00427 {
    00428     PETHREAD Thread;
    00429     PKEVENT  Event;
    00430     NTSTATUS Status;
    00431     PKTRAP_FRAME TrapFrame;
    00432     PVDM_PROCESS_OBJECTS pVdmObjects;
    00433
    00434
    00435     try {
    00436
    00437         //
    00438         // Wake up WowExec by setting the wow idle event
    00439         //
    00440
    00441         pVdmObjects = PsGetCurrentProcess()->VdmObjects;
    00442
    00443         Status = ObReferenceObjectByHandle(
    00444                          *pVdmObjects->pIcaUserData->phWowIdleEvent,
    00445                          EVENT_MODIFY_STATE,
    00446                          ExEventObjectType,
    00447                          UserMode,
    00448                          &Event,
    00449                          NULL
    00450                          );
    00451
    00452         if (NT_SUCCESS(Status)) {
    00453             KeSetEvent(Event, EVENT_INCREMENT, FALSE);
    00454             ObDereferenceObject(Event);
    00455             }
    00456
    00457         }
    00458     except(VdmpExceptionHandler(GetExceptionInformation()))  {
    00459         Thread    = PsGetCurrentThread();
    00460         TrapFrame = VdmGetTrapFrame(&Thread->Tcb);
    00461         VdmDispatchException(TrapFrame,
    00462                              GetExceptionCode(),
    00463                              (PVOID)TrapFrame->Eip,
    00464                              0,0,0,0   // no parameters
    00465                              );
    00466         return;
    00467         }
    00468 }

## Variable Documentation

POBJECT_TYPE ExEventObjectType

| Definition at line 143 of file vdmints.c.

POBJECT_TYPE ExSemaphoreObjectType

| Definition at line 142 of file vdmints.c. Referenced by ExpSemaphoreInitialization(), NtCreateSemaphore(), NtOpenSemaphore(), NtQuerySemaphore(), NtReleaseSemaphore(), and NtSignalAndWaitForSingleObject().