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
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
#include "ki.h"
00038
#include "ia32def.h"
00039
#include "vdmntos.h"
00040
00041
00042
00043 ULONG
KeIA32EFlagsAndMaskV86 = EFLAGS_USER_SANITIZE;
00044 ULONG
KeIA32EFlagsOrMaskV86 = EFLAGS_INTERRUPT_MASK;
00045 BOOLEAN
KeIA32VdmIoplAllowed =
FALSE;
00046 ULONG
KeIA32VirtualIntExtensions = 0;
00047
00048 KMUTEX VdmStringIoMutex;
00049 PULONG
VdmFixedStateLinear;
00050
00051
00052
#if !defined(WX86)
00053
00054
NTSTATUS
00055 NtInitializeVDM(
00056 VOID
00057 )
00058 {
00059
return STATUS_SUCCESS;
00060 }
00061
00062
NTSTATUS
00063 NtVdmStartExecution (
00064 )
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 {
00079
00080
return STATUS_NOT_IMPLEMENTED;
00081
00082 }
00083
00084
#else // WX86
00085
00086
#pragma hdrstop
00087
00088
#define VDM_IO_TEST 0
00089
00090
#if VDM_IO_TEST
00091
VOID
00092 TestIoHandlerStuff(
00093 VOID
00094 );
00095
#endif
00096
00097
#if DBG
00098
VOID
00099 PspPrintDescriptor(
00100 IN PLDT_ENTRY Descriptor
00101 );
00102
00103
extern ULONG fShowLdt;
00104
#endif
00105
00106
00107 BOOLEAN
00108 KiIA32VdmDispatchIo(
00109 IN ULONG PortNumber,
00110 IN ULONG Size,
00111 IN BOOLEAN Read,
00112 IN UCHAR InstructionSize,
00113 IN PKIA32_FRAME TrapFrame
00114 );
00115
00116 BOOLEAN
00117 KiIA32VdmDispatchStringIo(
00118 IN ULONG PortNumber,
00119 IN ULONG Size,
00120 IN BOOLEAN Rep,
00121 IN BOOLEAN Read,
00122 IN ULONG Count,
00123 IN ULONG Address,
00124 IN UCHAR InstructionSize,
00125 IN PKIA32_FRAME TrapFrame
00126 );
00127
00128
00129 BOOLEAN
00130
VdmDispatchIoToHandler(
00131 IN PVDM_IO_HANDLER VdmIoHandler,
00132 IN ULONG Context,
00133 IN ULONG PortNumber,
00134 IN ULONG Size,
00135 IN BOOLEAN Read,
00136 IN OUT PULONG Data
00137 );
00138
00139 BOOLEAN
00140
VdmDispatchUnalignedIoToHandler(
00141 IN PVDM_IO_HANDLER VdmIoHandler,
00142 IN ULONG Context,
00143 IN ULONG PortNumber,
00144 IN ULONG Size,
00145 IN BOOLEAN Read,
00146 IN OUT PULONG Data
00147 );
00148
00149 BOOLEAN
00150
VdmDispatchStringIoToHandler(
00151 IN PVDM_IO_HANDLER VdmIoHandler,
00152 IN ULONG Context,
00153 IN ULONG PortNumber,
00154 IN ULONG Size,
00155 IN ULONG Count,
00156 IN BOOLEAN Read,
00157 IN ULONG Data
00158 );
00159
00160 BOOLEAN
00161
VdmCallStringIoHandler(
00162 IN PVDM_IO_HANDLER VdmIoHandler,
00163 IN PVOID StringIoRoutine,
00164 IN ULONG Context,
00165 IN ULONG PortNumber,
00166 IN ULONG Size,
00167 IN ULONG Count,
00168 IN BOOLEAN Read,
00169 IN ULONG Data
00170 );
00171
00172 BOOLEAN
00173
VdmConvertToLinearAddress(
00174 IN ULONG SegmentedAddress,
00175 IN PVOID *LinearAddress
00176 );
00177
00178
VOID
00179 KeIA32VdmInitialize(
00180 VOID
00181 );
00182
00183 ULONG
00184 KiIA32VdmEnablePentiumExtentions(
00185 ULONG
00186 );
00187
00188
#ifdef ALLOC_PRAGMA
00189
#pragma alloc_text(PAGE, KiIA32VdmDispatchIo)
00190
#pragma alloc_text(PAGE, KiIA32VdmDispatchStringIo)
00191
#pragma alloc_text(PAGE, VdmDispatchIoToHandler)
00192
#pragma alloc_text(PAGE, VdmDispatchUnalignedIoToHandler)
00193
#pragma alloc_text(PAGE, VdmDispatchStringIoToHandler)
00194
#pragma alloc_text(PAGE, VdmCallStringIoHandler)
00195
#pragma alloc_text(PAGE, VdmConvertToLinearAddress)
00196
#pragma alloc_text(INIT, KeIA32VdmInitialize)
00197
#endif
00198
00199
00200 BOOLEAN
00201 KiIA32VdmDispatchIo(
00202 IN ULONG PortNumber,
00203 IN ULONG Size,
00204 IN BOOLEAN Read,
00205 IN UCHAR InstructionSize,
00206 IN PKIA32_FRAME TrapFrame
00207 )
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230 {
00231
PVDM_TIB VdmTib;
00232 EXCEPTION_RECORD ExceptionRecord;
00233 VDM_IO_HANDLER VdmIoHandler;
00234 ULONG Result;
00235 BOOLEAN Success =
FALSE;
00236 ULONG Context;
00237
00238 Success = PsIA32GetVdmIoHandler(
00239
PsGetCurrentProcess(),
00240 PortNumber & ~0x3,
00241 &VdmIoHandler,
00242 &Context
00243 );
00244
00245
if (Success) {
00246 Result = TrapFrame->Eax;
00247
00248
00249
if (PortNumber %
Size) {
00250 Success =
VdmDispatchUnalignedIoToHandler(
00251 &VdmIoHandler,
00252 Context,
00253 PortNumber,
00254 Size,
00255 Read,
00256 &Result
00257 );
00258 }
else {
00259 Success =
VdmDispatchIoToHandler(
00260 &VdmIoHandler,
00261 Context,
00262 PortNumber,
00263 Size,
00264 Read,
00265 &Result
00266 );
00267 }
00268 }
00269
00270
if (Success) {
00271
if (Read) {
00272
switch (
Size) {
00273
case 4:
00274 TrapFrame->Eax = Result;
00275
break;
00276
case 2:
00277 *(
PUSHORT)(&TrapFrame->Eax) = (
USHORT)Result;
00278
break;
00279
case 1:
00280 *(PUCHAR)(&TrapFrame->Eax) = (UCHAR)Result;
00281
break;
00282 }
00283 }
00284 TrapFrame->Eip += (ULONG) InstructionSize;
00285
return TRUE;
00286 }
else {
00287
try {
00288 VdmTib = NtCurrentTeb()->Vdm;
00289 VdmTib->
EventInfo.
InstructionSize = (ULONG) InstructionSize;
00290 VdmTib->
EventInfo.
Event =
VdmIO;
00291 VdmTib->
EventInfo.
IoInfo.
PortNumber = (
USHORT)PortNumber;
00292 VdmTib->
EventInfo.
IoInfo.
Size = (
USHORT)
Size;
00293 VdmTib->
EventInfo.
IoInfo.
Read = Read;
00294 } except(EXCEPTION_EXECUTE_HANDLER) {
00295 ExceptionRecord.ExceptionCode = STATUS_ACCESS_VIOLATION;
00296 ExceptionRecord.ExceptionFlags = 0;
00297 ExceptionRecord.NumberParameters = 0;
00298
ExRaiseException(&ExceptionRecord);
00299
return FALSE;
00300 }
00301 }
00302
00303
VdmEndExecution(TrapFrame, VdmTib);
00304
00305
return TRUE;
00306 }
00307
00308
00309 BOOLEAN
00310 KiIA32VdmDispatchStringIo(
00311 IN ULONG PortNumber,
00312 IN ULONG Size,
00313 IN BOOLEAN Rep,
00314 IN BOOLEAN Read,
00315 IN ULONG Count,
00316 IN ULONG Address,
00317 IN UCHAR InstructionSize,
00318 IN PKIA32_FRAME TrapFrame
00319 )
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344 {
00345
PVDM_TIB VdmTib;
00346 EXCEPTION_RECORD ExceptionRecord;
00347 BOOLEAN Success =
FALSE;
00348 VDM_IO_HANDLER VdmIoHandler;
00349 ULONG Context;
00350
00351 Success = PsIA32GetVdmIoHandler(
00352
PsGetCurrentProcess(),
00353 PortNumber & ~0x3,
00354 &VdmIoHandler,
00355 &Context
00356 );
00357
00358
00359
if (Success) {
00360 Success =
VdmDispatchStringIoToHandler(
00361 &VdmIoHandler,
00362 Context,
00363 PortNumber,
00364 Size,
00365 Count,
00366 Read,
00367 Address
00368 );
00369 }
00370
00371
if (Success) {
00372
PUSHORT pIndexRegister;
00373
USHORT Index;
00374
00375
00376
00377 pIndexRegister = Read ? (
PUSHORT)&TrapFrame->Edi
00378 : (
PUSHORT)&TrapFrame->Esi;
00379
00380
if (TrapFrame->EFlags & EFLAGS_DF_MASK) {
00381
Index = *pIndexRegister - (
USHORT)(
Count *
Size);
00382 }
00383
else {
00384
Index = *pIndexRegister + (
USHORT)(
Count *
Size);
00385 }
00386
00387 *pIndexRegister =
Index;
00388
00389
if (Rep) {
00390 (
USHORT)TrapFrame->Ecx = 0;
00391 }
00392
00393 TrapFrame->Eip += (ULONG) InstructionSize;
00394
return TRUE;
00395 }
00396
00397
try {
00398 VdmTib = NtCurrentTeb()->Vdm;
00399 VdmTib->
EventInfo.
InstructionSize = (ULONG) InstructionSize;
00400 VdmTib->
EventInfo.
Event =
VdmStringIO;
00401 VdmTib->
EventInfo.
StringIoInfo.
PortNumber = (
USHORT)PortNumber;
00402 VdmTib->
EventInfo.
StringIoInfo.
Size = (
USHORT)
Size;
00403 VdmTib->
EventInfo.
StringIoInfo.Rep = Rep;
00404 VdmTib->
EventInfo.
StringIoInfo.
Read = Read;
00405 VdmTib->
EventInfo.
StringIoInfo.
Count =
Count;
00406 VdmTib->
EventInfo.
StringIoInfo.
Address = Address;
00407 } except(EXCEPTION_EXECUTE_HANDLER) {
00408 ExceptionRecord.ExceptionCode = STATUS_ACCESS_VIOLATION;
00409 ExceptionRecord.ExceptionFlags = 0;
00410 ExceptionRecord.NumberParameters = 0;
00411
ExRaiseException(&ExceptionRecord);
00412
return FALSE;
00413 }
00414
00415
00416
VdmEndExecution(TrapFrame, VdmTib);
00417
00418
return TRUE;
00419 }
00420
00421
00422 BOOLEAN
00423
VdmDispatchIoToHandler(
00424 IN PVDM_IO_HANDLER VdmIoHandler,
00425 IN ULONG Context,
00426 IN ULONG PortNumber,
00427 IN ULONG Size,
00428 IN BOOLEAN Read,
00429 IN OUT PULONG Data
00430 )
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455 {
00456
NTSTATUS Status;
00457 BOOLEAN Success1, Success2;
00458
USHORT FnIndex;
00459 UCHAR AccessType;
00460
00461
00462
ASSERT((!(PortNumber % Size)));
00463
00464
if (Read) {
00465 FnIndex = 0;
00466 AccessType =
EMULATOR_READ_ACCESS;
00467 }
else {
00468 FnIndex = 1;
00469 AccessType =
EMULATOR_WRITE_ACCESS;
00470 }
00471
00472
switch (
Size) {
00473
case 1:
00474
if (VdmIoHandler->IoFunctions[FnIndex].UcharIo[PortNumber % 4]) {
00475
Status = (*(VdmIoHandler->IoFunctions[FnIndex].UcharIo[PortNumber % 4]))(
00476 Context,
00477 PortNumber,
00478 AccessType,
00479 (PUCHAR)Data
00480 );
00481
if (
NT_SUCCESS(Status)) {
00482
return TRUE;
00483 }
00484 }
00485
00486
return FALSE;
00487
00488
case 2:
00489
if (VdmIoHandler->IoFunctions[FnIndex].UshortIo[PortNumber % 2]) {
00490
Status = (*(VdmIoHandler->IoFunctions[FnIndex].UshortIo[PortNumber % 2]))(
00491 Context,
00492 PortNumber,
00493 AccessType,
00494 (
PUSHORT)Data
00495 );
00496
if (
NT_SUCCESS(Status)) {
00497
return TRUE;
00498 }
00499 }
else {
00500
00501 Success1 =
VdmDispatchIoToHandler(
00502 VdmIoHandler,
00503 Context,
00504 PortNumber,
00505 Size /2,
00506 Read,
00507 Data
00508 );
00509
00510 Success2 =
VdmDispatchIoToHandler(
00511 VdmIoHandler,
00512 Context,
00513 PortNumber + 1,
00514 Size / 2,
00515 Read,
00516 (PULONG)((PUCHAR)Data + 1)
00517 );
00518
00519
return (Success1 || Success2);
00520
00521 }
00522
return FALSE;
00523
00524
case 4:
00525
if (VdmIoHandler->IoFunctions[FnIndex].UlongIo) {
00526
Status = (*(VdmIoHandler->IoFunctions[FnIndex].UlongIo))(
00527 Context,
00528 PortNumber,
00529 AccessType,
00530 Data
00531 );
00532
if (
NT_SUCCESS(Status)) {
00533
return TRUE;
00534 }
00535 }
else {
00536
00537 Success1 =
VdmDispatchIoToHandler(
00538 VdmIoHandler,
00539 Context,
00540 PortNumber,
00541 Size /2,
00542 Read,
00543 Data);
00544 Success2 =
VdmDispatchIoToHandler(
00545 VdmIoHandler,
00546 Context,
00547 PortNumber + 2,
00548 Size / 2,
00549 Read,
00550 (PULONG)((PUSHORT)Data + 1)
00551 );
00552
00553
return (Success1 || Success2);
00554 }
00555
return FALSE;
00556 }
00557 }
00558
00559 BOOLEAN
00560
VdmDispatchUnalignedIoToHandler(
00561 IN PVDM_IO_HANDLER VdmIoHandler,
00562 IN ULONG Context,
00563 IN ULONG PortNumber,
00564 IN ULONG Size,
00565 IN BOOLEAN Read,
00566 IN OUT PULONG Data
00567 )
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590 {
00591 ULONG
Offset;
00592 BOOLEAN Success;
00593
00594
ASSERT((Size > 1));
00595
ASSERT((PortNumber % Size));
00596
00597
Offset = 0;
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
if ((PortNumber %
Size) & 1) {
00614 Success =
VdmDispatchIoToHandler(
00615 VdmIoHandler,
00616 Context,
00617 PortNumber,
00618 1,
00619 Read,
00620 Data
00621 );
00622
Offset += 1;
00623
00624 }
else {
00625 Success =
VdmDispatchIoToHandler(
00626 VdmIoHandler,
00627 Context,
00628 PortNumber,
00629 2,
00630 Read,
00631 Data
00632 );
00633
Offset += 2;
00634 }
00635
00636
00637
if (
Size == 4) {
00638 Success |=
VdmDispatchIoToHandler(
00639 VdmIoHandler,
00640 Context,
00641 PortNumber + Offset,
00642 2,
00643 Read,
00644 (PULONG)((PUCHAR)Data + Offset)
00645 );
00646
Offset += 2;
00647 }
00648
00649
00650
if (
Offset != 4) {
00651 Success |=
VdmDispatchIoToHandler(
00652 VdmIoHandler,
00653 Context,
00654 PortNumber + Offset,
00655 1,
00656 Read,
00657 (PULONG)((PUCHAR)Data + Offset)
00658 );
00659 }
00660
00661
return Success;
00662 }
00663
00664
00665 BOOLEAN
00666
VdmDispatchStringIoToHandler(
00667 IN PVDM_IO_HANDLER VdmIoHandler,
00668 IN ULONG Context,
00669 IN ULONG PortNumber,
00670 IN ULONG Size,
00671 IN ULONG Count,
00672 IN BOOLEAN Read,
00673 IN ULONG Data
00674 )
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699 {
00700 BOOLEAN Success =
FALSE;
00701
USHORT FnIndex;
00702
NTSTATUS Status;
00703
00704
if (Read) {
00705 FnIndex = 0;
00706 }
else {
00707 FnIndex = 1;
00708 }
00709
00710
Status =
KeWaitForSingleObject(
00711 &VdmStringIoMutex,
00712 Executive,
00713 KernelMode,
00714 FALSE,
00715 NULL
00716 );
00717
00718
if (!
NT_SUCCESS(Status)) {
00719
return FALSE;
00720 }
00721
00722
switch (
Size) {
00723
case 1:
00724 Success =
VdmCallStringIoHandler(
00725 VdmIoHandler,
00726 (PVOID)VdmIoHandler->IoFunctions[FnIndex].UcharStringIo[PortNumber % 4],
00727 Context,
00728 PortNumber,
00729 Size,
00730 Count,
00731 Read,
00732 Data
00733 );
00734
case 2:
00735 Success =
VdmCallStringIoHandler(
00736 VdmIoHandler,
00737 (PVOID)VdmIoHandler->IoFunctions[FnIndex].UshortStringIo[PortNumber % 2],
00738 Context,
00739 PortNumber,
00740 Size,
00741 Count,
00742 Read,
00743 Data
00744 );
00745
case 4:
00746 Success =
VdmCallStringIoHandler(
00747 VdmIoHandler,
00748 (PVOID)VdmIoHandler->IoFunctions[FnIndex].UlongStringIo,
00749 Context,
00750 PortNumber,
00751 Size,
00752 Count,
00753 Read,
00754 Data
00755 );
00756 }
00757
KeReleaseMutex(&VdmStringIoMutex, FALSE);
00758
return Success;
00759 }
00760
00761
#define STRINGIO_BUFFER_SIZE 1024
00762
UCHAR
VdmStringIoBuffer[
STRINGIO_BUFFER_SIZE];
00763
00764 BOOLEAN
00765
VdmCallStringIoHandler(
00766 IN PVDM_IO_HANDLER VdmIoHandler,
00767 IN PVOID StringIoRoutine,
00768 IN ULONG Context,
00769 IN ULONG PortNumber,
00770 IN ULONG Size,
00771 IN ULONG Count,
00772 IN BOOLEAN Read,
00773 IN ULONG Data
00774 )
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800 {
00801 ULONG TotalBytes,BytesDone,BytesToDo,LoopCount,NumberIo;
00802 PUCHAR CurrentDataPtr;
00803 UCHAR AccessType;
00804 EXCEPTION_RECORD ExceptionRecord;
00805
NTSTATUS Status;
00806 BOOLEAN Success;
00807
00808 Success =
VdmConvertToLinearAddress(
00809 Data,
00810 &CurrentDataPtr
00811 );
00812
00813
if (!Success) {
00814 ExceptionRecord.ExceptionCode = STATUS_ACCESS_VIOLATION;
00815 ExceptionRecord.ExceptionFlags = 0;
00816 ExceptionRecord.NumberParameters = 0;
00817
ExRaiseException(&ExceptionRecord);
00818
00819
return TRUE;
00820 }
00821
00822
00823 TotalBytes =
Count *
Size;
00824 BytesDone = 0;
00825
00826
if (PortNumber %
Size) {
00827 StringIoRoutine =
NULL;
00828 }
00829
00830
if (Read) {
00831 AccessType =
EMULATOR_READ_ACCESS;
00832 }
else {
00833 AccessType =
EMULATOR_WRITE_ACCESS;
00834 }
00835
00836
00837
00838
try {
00839
while (BytesDone < TotalBytes) {
00840
if ((BytesDone +
STRINGIO_BUFFER_SIZE) > TotalBytes) {
00841 BytesToDo = TotalBytes - BytesDone;
00842 }
else {
00843 BytesToDo =
STRINGIO_BUFFER_SIZE;
00844 }
00845
00846
ASSERT((!(BytesToDo % Size)));
00847
00848
if (!Read) {
00849 RtlMoveMemory(VdmStringIoBuffer, CurrentDataPtr, BytesToDo);
00850 }
00851
00852 NumberIo = BytesToDo /
Size;
00853
00854
if (StringIoRoutine) {
00855
00856
00857
00858
00859
Status = (*((
PDRIVER_IO_PORT_UCHAR_STRING)StringIoRoutine))(
00860 Context,
00861 PortNumber,
00862 AccessType,
00863
VdmStringIoBuffer,
00864 NumberIo
00865 );
00866
00867
if (
NT_SUCCESS(Status)) {
00868 Success |=
TRUE;
00869 }
00870 }
else {
00871
if (PortNumber %
Size) {
00872
for (LoopCount = 0; LoopCount < NumberIo; LoopCount++ ) {
00873 Success |=
VdmDispatchUnalignedIoToHandler(
00874 VdmIoHandler,
00875 Context,
00876 PortNumber,
00877 Size,
00878 Read,
00879 (PULONG)(VdmStringIoBuffer + LoopCount * Size)
00880 );
00881 }
00882 }
else {
00883
for (LoopCount = 0; LoopCount < NumberIo; LoopCount++ ) {
00884 Success |=
VdmDispatchIoToHandler(
00885 VdmIoHandler,
00886 Context,
00887 PortNumber,
00888 Size,
00889 Read,
00890 (PULONG)(VdmStringIoBuffer + LoopCount * Size)
00891 );
00892 }
00893
00894 }
00895 }
00896
00897
if (Read) {
00898 RtlMoveMemory(CurrentDataPtr, VdmStringIoBuffer, BytesToDo);
00899 }
00900
00901 BytesDone += BytesToDo;
00902 CurrentDataPtr += BytesToDo;
00903 }
00904 } except(EXCEPTION_EXECUTE_HANDLER) {
00905 ExceptionRecord.ExceptionCode = GetExceptionCode();
00906 ExceptionRecord.ExceptionFlags = 0;
00907 ExceptionRecord.NumberParameters = 0;
00908
ExRaiseException(&ExceptionRecord);
00909
00910 Success =
TRUE;
00911 }
00912
return Success;
00913
00914 }
00915
00916
00917 BOOLEAN
00918
VdmConvertToLinearAddress(
00919 IN ULONG SegmentedAddress,
00920 OUT PVOID *LinearAddress
00921 )
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944 {
00945
PKTHREAD Thread;
00946 PKIA32_FRAME TrapFrame;
00947 BOOLEAN Success;
00948 KXDESCRIPTOR XDescriptor;
00949 ULONG Base, Limit, Flags;
00950
00951 Thread =
KeGetCurrentThread();
00952 TrapFrame = (PKIA32_FRAME) VdmGetTrapFrame(Thread);
00953
00954
if (TrapFrame->EFlags & EFLAGS_V86_MASK) {
00955 *LinearAddress = (PVOID)(((SegmentedAddress & 0xFFFF0000) >> 12) +
00956 (SegmentedAddress & 0xFFFF));
00957 Success =
TRUE;
00958 }
else {
00959 Success = KeIA32UnscrambleLdtEntry(
00960 (USHORT)((SegmentedAddress & 0xFFFF0000) >> 12),
00961 &XDescriptor
00962 );
00963
if (Success) {
00964 *LinearAddress = (PVOID)(XDescriptor.Words.Bits.Base +
00965 (SegmentedAddress & 0xFFFF));
00966 }
00967 }
00968
return Success;
00969 }
00970
00971
VOID
00972 KeIA32VdmInitialize(
00973 VOID
00974 )
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989 {
00990
NTSTATUS Status;
00991 OBJECT_ATTRIBUTES
ObjectAttributes;
00992 HANDLE RegistryHandle =
NULL;
00993 UNICODE_STRING WorkString;
00994 UCHAR KeyInformation[
sizeof(KEY_VALUE_BASIC_INFORMATION) + 30];
00995 ULONG ResultLength;
00996
00997
KeInitializeMutex( &VdmStringIoMutex, MUTEX_LEVEL_VDM_IO );
00998
00999
01000
01001
01002
01003
RtlInitUnicodeString(
01004 &WorkString,
01005 L
"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Wow"
01006 );
01007
01008 InitializeObjectAttributes(
01009 &ObjectAttributes,
01010 &WorkString,
01011 OBJ_CASE_INSENSITIVE,
01012 (HANDLE)NULL,
01013 NULL
01014 );
01015
01016
Status = ZwOpenKey(
01017 &RegistryHandle,
01018 KEY_READ,
01019 &ObjectAttributes
01020 );
01021
01022
01023
01024
01025
if (!
NT_SUCCESS(Status)) {
01026
return;
01027 }
01028
01029
01030
01031
01032
01033
#ifdef USE_VME
01034
01035
01036
01037
01038
01039
RtlInitUnicodeString(
01040 &WorkString,
01041 L
"DisableVme"
01042 );
01043
01044
Status = ZwQueryValueKey(
01045 RegistryHandle,
01046 &WorkString,
01047 KeyValueBasicInformation,
01048 &KeyInformation,
01049
sizeof(KEY_VALUE_BASIC_INFORMATION) + 30,
01050 &ResultLength
01051 );
01052
01053
if (!
NT_SUCCESS(Status)) {
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
if (
KeFeatureBits &
KF_V86_VIS) {
01065
KiIpiGenericCall(
01066 KiIA32VdmEnablePentiumExtentions,
01067 TRUE
01068 );
01069
KeIA32VirtualIntExtensions = V86_VIRTUAL_INT_EXTENSIONS;
01070 }
01071 }
01072
01073
01074
01075
01076
01077
if (!
KeIA32VirtualIntExtensions & V86_VIRTUAL_INT_EXTENSIONS) {
01078
01079
01080
01081
01082
01083
01084
01085
RtlInitUnicodeString(
01086 &WorkString,
01087 L
"VdmIOPL"
01088 );
01089
01090
Status = ZwQueryValueKey(
01091 RegistryHandle,
01092 &WorkString,
01093 KeyValueBasicInformation,
01094 &KeyInformation,
01095
sizeof(KEY_VALUE_BASIC_INFORMATION) + 30,
01096 &ResultLength
01097 );
01098
01099
01100
01101
01102
if (
NT_SUCCESS(Status)) {
01103
01104
01105
01106
01107
01108
KeIA32EFlagsAndMaskV86 = EFLAGS_USER_SANITIZE | EFLAGS_INTERRUPT_MASK;
01109
KeIA32EFlagsOrMaskV86 = EFLAGS_IOPL_MASK;
01110
01111
01112
01113
01114
01115
KeIA32VdmIoplAllowed =
TRUE;
01116
01117 }
01118 }
01119
#endif
01120
ZwClose(RegistryHandle);
01121 }
01122
01123
01124 BOOLEAN
01125 KeIA32VdmInsertQueueApc (
01126 IN
PKAPC Apc,
01127 IN
PKTHREAD Thread,
01128 IN KPROCESSOR_MODE ApcMode,
01129 IN PKKERNEL_ROUTINE KernelRoutine,
01130 IN PKRUNDOWN_ROUTINE RundownRoutine OPTIONAL,
01131 IN PKNORMAL_ROUTINE NormalRoutine OPTIONAL,
01132 IN PVOID NormalContext OPTIONAL,
01133 IN PVOID SystemArgument1 OPTIONAL,
01134 IN PVOID SystemArgument2 OPTIONAL,
01135 IN KPRIORITY Increment
01136 )
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188 {
01189
01190
PKAPC_STATE ApcState;
01191
PKTHREAD ApcThread;
01192 KIRQL OldIrql;
01193 BOOLEAN Inserted;
01194
01195
01196
01197
01198
01199
KiLockDispatcherDatabase(&OldIrql);
01200
01201
01202
01203
01204
01205
01206
if (Apc->Type !=
ApcObject) {
01207 Apc->Type =
ApcObject;
01208 Apc->Size =
sizeof(
KAPC);
01209 Apc->ApcStateIndex =
OriginalApcEnvironment;
01210 }
else {
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228 ApcThread = Apc->Thread;
01229
if (ApcThread) {
01230 KiAcquireSpinLock(&ApcThread->
ApcQueueLock);
01231
if (Apc->Inserted) {
01232
if (ApcThread == Apc->Thread && Apc->Thread != Thread) {
01233 Apc->Inserted =
FALSE;
01234 RemoveEntryList(&Apc->ApcListEntry);
01235 ApcState = Apc->Thread->ApcStatePointer[Apc->ApcStateIndex];
01236
if (IsListEmpty(&ApcState->
ApcListHead[Apc->ApcMode]) !=
FALSE) {
01237
if (Apc->ApcMode ==
KernelMode) {
01238 ApcState->
KernelApcPending =
FALSE;
01239
01240 }
else {
01241 ApcState->
UserApcPending =
FALSE;
01242 }
01243 }
01244
01245 }
else {
01246 KiReleaseSpinLock(&ApcThread->
ApcQueueLock);
01247
KiUnlockDispatcherDatabase(OldIrql);
01248
return TRUE;
01249 }
01250 }
01251
01252 KiReleaseSpinLock(&ApcThread->
ApcQueueLock);
01253 }
01254 }
01255
01256
01257 KiAcquireSpinLock(&Thread->ApcQueueLock);
01258
01259 Apc->ApcMode = ApcMode;
01260 Apc->Thread = Thread;
01261 Apc->KernelRoutine = KernelRoutine;
01262 Apc->RundownRoutine = RundownRoutine;
01263 Apc->NormalRoutine = NormalRoutine;
01264 Apc->SystemArgument1 = SystemArgument1;
01265 Apc->SystemArgument2 = SystemArgument2;
01266 Apc->NormalContext = NormalContext;
01267
01268
01269
01270
01271
01272 KiReleaseSpinLock(&Thread->ApcQueueLock);
01273
01274
01275
01276
01277
01278
if (Thread->ApcQueueable &&
KiInsertQueueApc(Apc, Increment)) {
01279 Inserted =
TRUE;
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
if (ApcMode ==
UserMode) {
01290
KiBoostPriorityThread(Thread, Increment);
01291 Thread->ApcState.UserApcPending =
TRUE;
01292 }
01293
01294 }
else {
01295 Inserted =
FALSE;
01296 }
01297
01298
01299
01300
01301
01302
01303
KiUnlockDispatcherDatabase(OldIrql);
01304
return Inserted;
01305 }
01306
01307
01308
VOID
01309 KeIA32VdmClearApcObject(
01310 IN
PKAPC Apc
01311 )
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331 {
01332
01333 KIRQL OldIrql;
01334
01335
01336
01337
01338
01339
KiLockDispatcherDatabase(&OldIrql);
01340 Apc->Thread =
NULL;
01341
KiUnlockDispatcherDatabase(OldIrql);
01342
01343 }
01344
01345
01346
01347
01348
01349
#if VDM_IO_TEST
01350
NTSTATUS
01351 TestIoByteRoutine(
01352 IN ULONG Port,
01353 IN UCHAR AccessMode,
01354 IN OUT PUCHAR Data
01355 )
01356 {
01357
if (AccessMode &
EMULATOR_READ_ACCESS) {
01358 *Data = Port - 400;
01359 }
01360
01361
return STATUS_SUCCESS;
01362 }
01363
01364
NTSTATUS
01365 TestIoWordReadRoutine(
01366 IN ULONG Port,
01367 IN UCHAR AccessMode,
01368 IN OUT PUSHORT Data
01369 )
01370 {
01371
if (AccessMode &
EMULATOR_READ_ACCESS) {
01372 *Data = Port - 200;
01373 }
01374
01375
return STATUS_SUCCESS;
01376 }
01377
01378
NTSTATUS
01379 TestIoWordWriteRoutine(
01380 IN ULONG Port,
01381 IN UCHAR AccessMode,
01382 IN OUT PUSHORT Data
01383 )
01384 {
01385
DbgPrint(
"Word Write routine port # %lx, %x\n",Port,*Data);
01386
01387
return STATUS_SUCCESS;
01388 }
01389
01390
NTSTATUS
01391 TestIoDwordRoutine(
01392 IN ULONG Port,
01393 IN USHORT AccessMode,
01394 IN OUT PULONG Data
01395 )
01396 {
01397
if (AccessMode &
EMULATOR_READ_ACCESS) {
01398 *Data = Port;
01399 }
01400
01401
return STATUS_SUCCESS;
01402 }
01403
01404
NTSTATUS
01405 TestIoStringRoutine(
01406 IN ULONG Port,
01407 IN USHORT AccessMode,
01408 IN OUT PSHORT Data,
01409 IN ULONG Count
01410 )
01411 {
01412 ULONG i;
01413
01414
if (AccessMode &
EMULATOR_READ_ACCESS) {
01415
for (i = 0;i <
Count ;i++ ) {
01416 Data[i] = i;
01417 }
01418 }
else {
01419
DbgPrint(
"String Port Called for write port #%lx,",Port);
01420
for (i = 0;i <
Count ;i++ ) {
01421
DbgPrint(
"%x\n",Data[i]);
01422 }
01423 }
01424
01425
return STATUS_SUCCESS;
01426 }
01427
01428 PROCESS_IO_PORT_HANDLER_INFORMATION IoPortHandler;
01429
EMULATOR_ACCESS_ENTRY Entry[4];
01430 BOOLEAN Connect =
TRUE, Disconnect =
FALSE;
01431
01432
VOID
01433 TestIoHandlerStuff(
01434 VOID
01435 )
01436 {
01437
NTSTATUS Status;
01438
01439 IoPortHandler.Install =
TRUE;
01440 IoPortHandler.NumEntries = 5
L;
01441 IoPortHandler.EmulatorAccessEntries = Entry;
01442
01443 Entry[0].
BasePort = 0x400;
01444 Entry[0].
NumConsecutivePorts = 0x30;
01445 Entry[0].
AccessType =
Uchar;
01446 Entry[0].
AccessMode =
EMULATOR_READ_ACCESS |
EMULATOR_WRITE_ACCESS;
01447 Entry[0].
StringSupport =
FALSE;
01448 Entry[0].
Routine = TestIoByteRoutine;
01449
01450 Entry[1].
BasePort = 0x400;
01451 Entry[1].
NumConsecutivePorts = 0x18;
01452 Entry[1].
AccessType =
Ushort;
01453 Entry[1].
AccessMode =
EMULATOR_READ_ACCESS |
EMULATOR_WRITE_ACCESS;
01454 Entry[1].
StringSupport =
FALSE;
01455 Entry[1].
Routine = TestIoWordReadRoutine;
01456
01457 Entry[2].
BasePort = 0x400;
01458 Entry[2].
NumConsecutivePorts = 0xc;
01459 Entry[2].
AccessType =
Ulong;
01460 Entry[2].
AccessMode =
EMULATOR_READ_ACCESS |
EMULATOR_WRITE_ACCESS;
01461 Entry[2].
StringSupport =
FALSE;
01462 Entry[2].
Routine = TestIoDwordRoutine;
01463
01464 Entry[3].
BasePort = 0x400;
01465 Entry[3].
NumConsecutivePorts = 0x18;
01466 Entry[3].
AccessType =
Ushort;
01467 Entry[3].
AccessMode =
EMULATOR_READ_ACCESS |
EMULATOR_WRITE_ACCESS;
01468 Entry[3].
StringSupport =
TRUE;
01469 Entry[3].
Routine = TestIoStringRoutine;
01470
01471
if (Connect) {
01472
Status = ZwSetInformationProcess(
01473 NtCurrentProcess(),
01474 ProcessIoPortHandlers,
01475 &IoPortHandler,
01476
sizeof(PROCESS_IO_PORT_HANDLER_INFORMATION)
01477 ) ;
01478
if (!
NT_SUCCESS(Status)) {
01479 DbgBreakPoint();
01480 }
01481 Connect =
FALSE;
01482 }
01483
01484 IoPortHandler.Install =
FALSE;
01485
if (Disconnect) {
01486
Status = ZwSetInformationProcess(
01487 NtCurrentProcess(),
01488 ProcessIoPortHandlers,
01489 &IoPortHandler,
01490
sizeof(PROCESS_IO_PORT_HANDLER_INFORMATION)
01491 );
01492
if (!
NT_SUCCESS(Status)) {
01493 DbgBreakPoint();
01494 }
01495 Disconnect =
FALSE;
01496 }
01497 }
01498
#endif
01499
01500
01501
#endif