00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
#include <ntos.h>
00027
#include <zwapi.h>
00028
#include "vdmp.h"
00029
00030
00031 #define VDM_HWINT_INCREMENT EVENT_INCREMENT
00032
00033
00034
00035
00036
00037
00038
VOID
00039
VdmpQueueIntApcRoutine (
00040 IN
PKAPC Apc,
00041 IN PKNORMAL_ROUTINE *NormalRoutine,
00042 IN PVOID *NormalContext,
00043 IN PVOID *SystemArgument1,
00044 IN PVOID *SystemArgument2
00045 );
00046
00047
VOID
00048
VdmpQueueIntNormalRoutine (
00049 IN PVOID NormalContext,
00050 IN PVOID SystemArgument1,
00051 IN PVOID SystemArgument2
00052 );
00053
00054
00055
VOID
00056
VdmpDelayIntDpcRoutine (
00057 IN
PKDPC Dpc,
00058 IN PVOID DeferredContext,
00059 IN PVOID SystemArgument1,
00060 IN PVOID SystemArgument2
00061 );
00062
00063
00064
VOID
00065
VdmpDelayIntApcRoutine (
00066 IN
PKAPC Apc,
00067 IN PKNORMAL_ROUTINE *NormalRoutine,
00068 IN PVOID *NormalContext,
00069 IN PVOID *SystemArgument1,
00070 IN PVOID *SystemArgument2
00071 );
00072
00073
int
00074
RestartDelayedInterrupts(
00075 PVDMICAUSERDATA pIcaUserData
00076 );
00077
00078
int
00079
IcaScan(
00080 PVDMICAUSERDATA pIcaUserData,
00081 PVDMVIRTUALICA pIcaAdapter
00082 );
00083
00084
int
00085
IcaAccept(
00086 PVDMICAUSERDATA pIcaUserData,
00087 PVDMVIRTUALICA pIcaAdapter
00088 );
00089
00090 ULONG
00091
GetIretHookAddress(
00092 PKTRAP_FRAME TrapFrame,
00093 PVDMICAUSERDATA pIcaUserData,
00094
int IrqNum
00095 );
00096
00097
VOID
00098
PushRmInterrupt(
00099 PKTRAP_FRAME TrapFrame,
00100 ULONG IretHookAddress,
00101
PVDM_TIB VdmTib,
00102 ULONG InterruptNumber
00103 );
00104
00105
NTSTATUS
00106
PushPmInterrupt(
00107 PKTRAP_FRAME TrapFrame,
00108 ULONG IretHookAddress,
00109
PVDM_TIB VdmTib,
00110 ULONG InterruptNumber
00111 );
00112
00113
VOID
00114
VdmpNullRundownRoutine(
00115 IN
PKAPC Apc
00116 );
00117
00118
00119
int
00120
VdmpExceptionHandler(
00121 IN PEXCEPTION_POINTERS ExceptionInfo
00122 );
00123
00124
00125
#ifdef ALLOC_PRAGMA
00126
#pragma alloc_text(PAGE, VdmpQueueInterrupt)
00127
#pragma alloc_text(PAGE, VdmpQueueIntApcRoutine)
00128
#pragma alloc_text(PAGE, VdmpQueueIntNormalRoutine)
00129
#pragma alloc_text(PAGE, VdmDispatchInterrupts)
00130
#pragma alloc_text(PAGE, RestartDelayedInterrupts)
00131
#pragma alloc_text(PAGE, IcaScan)
00132
#pragma alloc_text(PAGE, IcaAccept)
00133
#pragma alloc_text(PAGE, GetIretHookAddress)
00134
#pragma alloc_text(PAGE, PushRmInterrupt)
00135
#pragma alloc_text(PAGE, PushPmInterrupt)
00136
#pragma alloc_text(PAGE, VdmpDispatchableIntPending)
00137
#pragma alloc_text(PAGE, VdmpIsThreadTerminating)
00138
#pragma alloc_text(PAGE, VdmpNullRundownRoutine)
00139
#pragma alloc_text(PAGE, VdmpExceptionHandler)
00140
#endif
00141
00142 extern POBJECT_TYPE ExSemaphoreObjectType;
00143 extern POBJECT_TYPE ExEventObjectType;
00144
00145
NTSTATUS
00146 VdmpQueueInterrupt(
00147 IN HANDLE ThreadHandle
00148 )
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
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,
00214
VdmpQueueIntNormalRoutine,
00215 (PVOID)
KernelMode,
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 }
00229
00230
00231
VOID
00232 VdmpQueueIntApcRoutine (
00233 IN
PKAPC Apc,
00234 IN PKNORMAL_ROUTINE *NormalRoutine,
00235 IN PVOID *NormalContext,
00236 IN PVOID *SystemArgument1,
00237 IN PVOID *SystemArgument2
00238 )
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
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
00296
00297 Thread =
PsGetCurrentThread();
00298
00299
00300
00301
00302
if (
PsIsThreadTerminating(Thread))
00303
return;
00304
00305
00306
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
00319
00320
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,
00333
NULL,
00334 (PVOID)
UserMode,
00335 (*pNtVDMState & VDM_INT_HARDWARE)
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
00350
00351
00352
00353
00354
00355
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
00373
00374
00375
else if (*NormalRoutine &&
00376 !(*pNtVDMState & VDM_WOWBLOCKED))
00377 {
00378 *NormalRoutine =
NULL;
00379 }
00380
00381 }
00382
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
00389
00390
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
00401 );
00402
return;
00403 }
00404 }
00405
00406
00407
VOID
00408 VdmpQueueIntNormalRoutine (
00409 IN PVOID NormalContext,
00410 IN PVOID SystemArgument1,
00411 IN PVOID SystemArgument2
00412 )
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
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
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
00465 );
00466
return;
00467 }
00468 }
00469
00470
00471
00472
00473
00474
00475
00476
NTSTATUS
00477 VdmDispatchInterrupts(
00478 PKTRAP_FRAME TrapFrame,
00479
PVDM_TIB VdmTib
00480 )
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
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
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
00530
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
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
00557
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
00580
00581
if (IrqLineNum < 0) {
00582
00583
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
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
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
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
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
00686
00687
Status =
VdmpLeaveIcaLock(pIcaUserData->pIcaLock);
00688
if (!
NT_SUCCESS(
Status)) {
00689
ExRaiseStatus(
Status);
00690 }
00691
00692
00693
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
00707 );
00708 }
00709
00710
return Status;
00711 }
00712
00713
00714
int
00715 RestartDelayedInterrupts(
00716 PVDMICAUSERDATA pIcaUserData
00717 )
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
00729 pIcaUserData->pIcaSlave->ica_int_line = line;
00730 pIcaUserData->pIcaSlave->ica_cpu_int =
TRUE;
00731
00732
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 }
00746
00747
00748
00749
int
00750 IcaScan(
00751 PVDMICAUSERDATA pIcaUserData,
00752 PVDMVIRTUALICA pIcaAdapter
00753 )
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
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
00800
00801
00802
00803
00804
00805
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;
00816 }
00817
00818
if (IrrImrDelay & bit) {
00819
return line;
00820 }
00821 }
00822 }
00823
00824
return -1;
00825 }
00826
00827
00828
00829
00830
int
00831 IcaAccept(
00832 PVDMICAUSERDATA pIcaUserData,
00833 PVDMVIRTUALICA pIcaAdapter
00834 )
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860 {
00861
int line;
00862 UCHAR bit;
00863
00864
PAGED_CODE();
00865
00866
00867
00868
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
00883
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 }
00893
00894
00895
00896 ULONG
00897 GetIretHookAddress(
00898 PKTRAP_FRAME TrapFrame,
00899 PVDMICAUSERDATA pIcaUserData,
00900
int IrqNum
00901 )
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
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 }
00948
00949
00950
00951
00952
VOID
00953 PushRmInterrupt(
00954 PKTRAP_FRAME TrapFrame,
00955 ULONG IretHookAddress,
00956
PVDM_TIB VdmTib,
00957 ULONG InterruptNumber
00958 )
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978 {
00979 ULONG UserSS;
00980
USHORT UserSP;
00981
USHORT NewCS;
00982
USHORT NewIP;
00983
00984
PAGED_CODE();
00985
00986
00987
00988
00989
00990 UserSS = TrapFrame->HardwareSegSs << 4;
00991 UserSP = (
USHORT) TrapFrame->HardwareEsp;
00992
00993
00994
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
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
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
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 }
01040
01041
01042
01043
01044
NTSTATUS
01045 PushPmInterrupt(
01046 PKTRAP_FRAME TrapFrame,
01047 ULONG IretHookAddress,
01048
PVDM_TIB VdmTib,
01049 ULONG InterruptNumber
01050 )
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
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
01081
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
01094
01095
if (!
Ki386GetSelectorParameters((
USHORT)TrapFrame->HardwareSegSs,
01096 &Flags, &Base, &Limit))
01097 {
01098
return STATUS_ACCESS_VIOLATION;
01099 }
01100
01101
01102
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
01114
01115 VdmStackPointer = (
PUSHORT)(Base + VdmSp);
01116
01117
01118
01119
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
01132
01133
01134
if (Frame32) {
01135 VdmSp -= 6*
sizeof(ULONG);
01136 }
else {
01137 VdmSp -= 6*
sizeof(
USHORT);
01138 }
01139
01140
01141
01142
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
01154
01155
01156
01157
01158
01159
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
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
01193
01194 TrapFrame->SegCs = VdmTib->
VdmInterruptHandlers[InterruptNumber].
CsSelector | 0x7;
01195 TrapFrame->Eip = VdmTib->
VdmInterruptHandlers[InterruptNumber].
Eip;
01196
01197
01198
01199
01200 TrapFrame->EFlags &= ~EFLAGS_TF_MASK;
01201
01202
01203
01204
01205
if (IretHookAddress) {
01206 ULONG SegCs, Eip;
01207
01208
01209
01210
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 }
01231
01232
01233
01234
NTSTATUS
01235 VdmpDelayInterrupt(
01236 PVDMDELAYINTSDATA pdsd
01237 )
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
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
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
01317
01318
ProbeForRead(pdsd,
sizeof(VDMDELAYINTSDATA),
sizeof(ULONG));
01319
01320
01321
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
01337
01338
Delay = pdsd->Delay;
01339
01340
01341
01342
01343
if (
Delay == 0xFFFFFFFF) {
01344 ZwSetTimerResolution(
KeMaximumIncrement,
FALSE, &
Delay);
01345
goto VidEarlyExit;
01346 }
01347
01348
01349 FreeIrqLine =
FALSE;
01350
01351
01352
01353
01354
Delay =
Delay < 1000 ? 10000 :
Delay * 10;
01355
01356
01357
01358
01359
01360
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
01371
Delay >>= 1;
01372 }
01373
else if (
Delay < (
KeTimeIncrement << 1)) {
01374
01375
01376
Delay -=
KeTimeIncrement >> 1;
01377 }
01378 }
01379
01380
01381
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
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
01459
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
01519
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) {
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 }
01577
01578
01579
01580
01581
01582
VOID
01583 VdmpDelayIntDpcRoutine (
01584 IN
PKDPC Dpc,
01585 IN PVOID DeferredContext,
01586 IN PVOID SystemArgument1,
01587 IN PVOID SystemArgument2
01588 )
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
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
01626
01627 Process = (
PEPROCESS)DeferredContext;
01628 pVdmObjects = (PVDM_PROCESS_OBJECTS)Process->
VdmObjects;
01629
01630
01631
KeAcquireSpinLock(&pVdmObjects->DelayIntSpinLock, &OldIrql);
01632
01633
01634
01635
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,
01665
VdmpQueueIntNormalRoutine,
01666
NULL,
01667
VDM_HWINT_INCREMENT
01668 ))
01669 ||
01670 (MainThread &&
01671
Ke386VdmInsertQueueApc(&pDelayIntIrq->Apc,
01672 &MainThread->
Tcb,
01673
KernelMode,
01674
VdmpDelayIntApcRoutine,
01675
VdmpNullRundownRoutine,
01676
VdmpQueueIntNormalRoutine,
01677
NULL,
01678
VDM_HWINT_INCREMENT
01679 )))
01680 {
01681 pDelayIntIrq->InUse = VDMDELAY_KAPC;
01682 }
01683
else {
01684
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 }
01705
01706
01707
01708
VOID
01709 VdmpDelayIntApcRoutine (
01710 IN
PKAPC Apc,
01711 IN PKNORMAL_ROUTINE *NormalRoutine,
01712 IN PVOID *NormalContext,
01713 IN PVOID *SystemArgument1,
01714 IN PVOID *SystemArgument2
01715 )
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742
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
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
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
01790
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 ;
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
01819
01820
01821
01822
01823
01824 *pDelayIrq &= ~IrqLine;
01825 _asm {
01826 mov eax, pUndelayIrq
01827 mov ebx, IrqLine
01828 lock or [eax], ebx
01829 }
01830
01831
01832
01833
01834
01835
if (!(IrqLine & *pDelayIret)) {
01836
01837
01838
01839
01840 _asm {
01841 mov eax,FIXED_NTVDMSTATE_LINEAR
01842 lock or dword ptr [eax], VDM_INT_HARDWARE
01843 }
01844
01845
01846
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 ;
01861 }
01862
01863 ExReleaseFastMutex(&pVdmObjects->DelayIntFastMutex);
01864
01865
return;
01866 }
01867
01868
01869 BOOLEAN
01870 VdmpDispatchableIntPending(
01871 ULONG EFlags
01872 )
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890 {
01891
PAGED_CODE();
01892
01893
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 }
01915
01916
01917
01918
01919
01920
01921
NTSTATUS
01922 VdmpIsThreadTerminating(
01923 HANDLE ThreadId
01924 )
01925
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
01939 {
01940 CLIENT_ID Cid;
01941
PETHREAD Thread;
01942
NTSTATUS Status;
01943
01944
PAGED_CODE();
01945
01946
01947
01948
01949
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 }
01967
01968
VOID
01969 VdmpNullRundownRoutine(
01970 IN
PKAPC Apc
01971 )
01972
01973
01974
01975
01976
01977
01978
01979
01980
01981
01982
01983
01984
01985
01986
01987
01988 {
01989
VdmpDelayIntApcRoutine( Apc,
NULL,
NULL,
NULL,
NULL);
01990 }
01991
01992
01993
01994
01995
int
01996 VdmpExceptionHandler(
01997 IN PEXCEPTION_POINTERS ExceptionInfo
01998 )
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 }