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