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

vdm.c File Reference

#include "ki.h"
#include "vdmntos.h"

Go to the source code of this file.

Defines

#define VDM_IO_TEST   0
#define STRINGIO_BUFFER_SIZE   1024

Functions

BOOLEAN Ki386GetSelectorParameters (IN USHORT Selector, OUT PULONG Flags, OUT PULONG Base, OUT PULONG Limit)
BOOLEAN Ki386VdmDispatchIo (IN ULONG PortNumber, IN ULONG Size, IN BOOLEAN Read, IN UCHAR InstructionSize, IN PKTRAP_FRAME TrapFrame)
BOOLEAN Ki386VdmDispatchStringIo (IN ULONG PortNumber, IN ULONG Size, IN BOOLEAN Rep, IN BOOLEAN Read, IN ULONG Count, IN ULONG Address, IN UCHAR InstructionSize, IN PKTRAP_FRAME TrapFrame)
BOOLEAN VdmDispatchIoToHandler (IN PVDM_IO_HANDLER VdmIoHandler, IN ULONG Context, IN ULONG PortNumber, IN ULONG Size, IN BOOLEAN Read, IN OUT PULONG Data)
BOOLEAN VdmDispatchUnalignedIoToHandler (IN PVDM_IO_HANDLER VdmIoHandler, IN ULONG Context, IN ULONG PortNumber, IN ULONG Size, IN BOOLEAN Read, IN OUT PULONG Data)
BOOLEAN VdmDispatchStringIoToHandler (IN PVDM_IO_HANDLER VdmIoHandler, IN ULONG Context, IN ULONG PortNumber, IN ULONG Size, IN ULONG Count, IN BOOLEAN Read, IN ULONG Data)
BOOLEAN VdmCallStringIoHandler (IN PVDM_IO_HANDLER VdmIoHandler, IN PVOID StringIoRoutine, IN ULONG Context, IN ULONG PortNumber, IN ULONG Size, IN ULONG Count, IN BOOLEAN Read, IN ULONG Data)
BOOLEAN VdmConvertToLinearAddress (IN ULONG SegmentedAddress, IN PVOID *LinearAddress)
VOID KeI386VdmInitialize (VOID)
ULONG Ki386VdmEnablePentiumExtentions (ULONG)
BOOLEAN VdmConvertToLinearAddress (IN ULONG SegmentedAddress, OUT PVOID *LinearAddress)
BOOLEAN Ke386VdmInsertQueueApc (IN PKAPC Apc, IN PKTHREAD Thread, IN KPROCESSOR_MODE ApcMode, IN PKKERNEL_ROUTINE KernelRoutine, IN PKRUNDOWN_ROUTINE RundownRoutine OPTIONAL, IN PKNORMAL_ROUTINE NormalRoutine OPTIONAL, IN PVOID NormalContext OPTIONAL, IN KPRIORITY Increment)
VOID Ke386VdmClearApcObject (IN PKAPC Apc)

Variables

KMUTEX VdmStringIoMutex
ULONG VdmFixedStateLinear
ULONG KeI386EFlagsAndMaskV86 = EFLAGS_USER_SANITIZE
ULONG KeI386EFlagsOrMaskV86 = EFLAGS_INTERRUPT_MASK
BOOLEAN KeI386VdmIoplAllowed = FALSE
ULONG KeI386VirtualIntExtensions = 0
UCHAR VdmStringIoBuffer [STRINGIO_BUFFER_SIZE]


Define Documentation

#define STRINGIO_BUFFER_SIZE   1024
 

Definition at line 878 of file ke/i386/vdm.c.

Referenced by VdmCallStringIoHandler().

#define VDM_IO_TEST   0
 

Definition at line 39 of file ke/i386/vdm.c.


Function Documentation

VOID Ke386VdmClearApcObject IN PKAPC  Apc  ) 
 

Definition at line 1437 of file ke/i386/vdm.c.

References KiLockDispatcherDatabase, KiUnlockDispatcherDatabase(), and NULL.

Referenced by VdmpDelayIntApcRoutine(), and VdmpQueueIntApcRoutine().

01442 : 01443 01444 Clears a VDM APC object, synchronously with Ke386VdmInsertQueueApc, and 01445 is expected to be called by one of the vdm kernel apc routine or the 01446 rundown routine. 01447 01448 01449 Arguments: 01450 01451 Apc - Supplies a pointer to a control object of type APC. 01452 01453 01454 Return Value: 01455 01456 void 01457 01458 --*/ 01459 { 01460 01461 KIRQL OldIrql; 01462 01463 // 01464 // Take Dispatcher database lock, to sync with Ke386VDMInsertQueueApc 01465 // 01466 01467 KiLockDispatcherDatabase(&OldIrql); 01468 Apc->Thread = NULL; 01469 KiUnlockDispatcherDatabase(OldIrql); 01470 01471 }

BOOLEAN Ke386VdmInsertQueueApc IN PKAPC  Apc,
IN PKTHREAD  Thread,
IN KPROCESSOR_MODE  ApcMode,
IN PKKERNEL_ROUTINE  KernelRoutine,
IN PKRUNDOWN_ROUTINE RundownRoutine  OPTIONAL,
IN PKNORMAL_ROUTINE NormalRoutine  OPTIONAL,
IN PVOID NormalContext  OPTIONAL,
IN KPRIORITY  Increment
 

Definition at line 1257 of file ke/i386/vdm.c.

References _KAPC_STATE::ApcListHead, ApcObject, _KTHREAD::ApcQueueLock, FALSE, Increment, _KAPC_STATE::KernelApcPending, KernelMode, KiBoostPriorityThread, KiInsertQueueApc(), KiLockDispatcherDatabase, KiUnlockDispatcherDatabase(), NULL, OriginalApcEnvironment, TRUE, _KAPC_STATE::UserApcPending, and UserMode.

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

01270 : 01271 01272 This function initializes, and queues a vdm type of APC to the 01273 specified thread. 01274 01275 01276 A Vdm type of APC: 01277 - OriginalApcEnvironment 01278 - will only be queued to one thread at a time 01279 - if UserMode Fires on the next system exit. A UserMode apc should 01280 not be queued if the current vdm context is not application mode. 01281 01282 Arguments: 01283 01284 Apc - Supplies a pointer to a control object of type APC. 01285 01286 Thread - Supplies a pointer to a dispatcher object of type thread. 01287 01288 ApcMode - Supplies the processor mode user\kernel of the Apc 01289 01290 KernelRoutine - Supplies a pointer to a function that is to be 01291 executed at IRQL APC_LEVEL in kernel mode. 01292 01293 RundownRoutine - Supplies an optional pointer to a function that is to be 01294 called if the APC is in a thread's APC queue when the thread terminates. 01295 01296 NormalRoutine - Supplies an optional pointer to a function that is 01297 to be executed at IRQL 0 in the specified processor mode. If this 01298 parameter is not specified, then the ProcessorMode and NormalContext 01299 parameters are ignored. 01300 01301 NormalContext - Supplies a pointer to an arbitrary data structure which is 01302 to be passed to the function specified by the NormalRoutine parameter. 01303 01304 Increment - Supplies the priority increment that is to be applied if 01305 queuing the APC causes a thread wait to be satisfied. 01306 01307 01308 Return Value: 01309 01310 If APC queuing is disabled, then a value of FALSE is returned. 01311 Otherwise a value of TRUE is returned. 01312 01313 01314 --*/ 01315 01316 { 01317 01318 PKAPC_STATE ApcState; 01319 PKTHREAD ApcThread; 01320 KIRQL OldIrql; 01321 BOOLEAN Inserted; 01322 01323 // 01324 // Raise IRQL to dispatcher level and lock dispatcher database. 01325 // 01326 01327 KiLockDispatcherDatabase(&OldIrql); 01328 01329 // 01330 // If the apc object not initialized, then initialize it and acquire 01331 // the target thread APC queue lock. 01332 // 01333 01334 if (Apc->Type != ApcObject) { 01335 Apc->Type = ApcObject; 01336 Apc->Size = sizeof(KAPC); 01337 Apc->ApcStateIndex = OriginalApcEnvironment; 01338 } else { 01339 01340 // 01341 // Acquire the APC thread APC queue lock. 01342 // 01343 // If the APC is inserted in the corresponding APC queue, and the 01344 // APC thread is not the same thread as the target thread, then 01345 // the APC is removed from its current queue, the APC pending state 01346 // is updated, the APC thread APC queue lock is released, and the 01347 // target thread APC queue lock is acquired. Otherwise, the APC 01348 // thread and the target thread are same thread and the APC is already 01349 // queued to the correct thread. 01350 // 01351 // If the APC is not inserted in an APC queue, then release the 01352 // APC thread APC queue lock and acquire the target thread APC queue 01353 // lock. 01354 // 01355 01356 ApcThread = Apc->Thread; 01357 if (ApcThread) { 01358 KiAcquireSpinLock(&ApcThread->ApcQueueLock); 01359 if (Apc->Inserted) { 01360 if (ApcThread == Apc->Thread && Apc->Thread != Thread) { 01361 Apc->Inserted = FALSE; 01362 RemoveEntryList(&Apc->ApcListEntry); 01363 ApcState = Apc->Thread->ApcStatePointer[Apc->ApcStateIndex]; 01364 if (IsListEmpty(&ApcState->ApcListHead[Apc->ApcMode]) != FALSE) { 01365 if (Apc->ApcMode == KernelMode) { 01366 ApcState->KernelApcPending = FALSE; 01367 01368 } else { 01369 ApcState->UserApcPending = FALSE; 01370 } 01371 } 01372 01373 } else { 01374 KiReleaseSpinLock(&ApcThread->ApcQueueLock); 01375 KiUnlockDispatcherDatabase(OldIrql); 01376 return TRUE; 01377 } 01378 } 01379 01380 KiReleaseSpinLock(&ApcThread->ApcQueueLock); 01381 } 01382 } 01383 01384 01385 KiAcquireSpinLock(&Thread->ApcQueueLock); 01386 01387 Apc->ApcMode = ApcMode; 01388 Apc->Thread = Thread; 01389 Apc->KernelRoutine = KernelRoutine; 01390 Apc->RundownRoutine = RundownRoutine; 01391 Apc->NormalRoutine = NormalRoutine; 01392 Apc->SystemArgument1 = NULL; 01393 Apc->SystemArgument2 = NULL; 01394 Apc->NormalContext = NormalContext; 01395 01396 // 01397 // Unlock the target thread APC queue. 01398 // 01399 01400 KiReleaseSpinLock(&Thread->ApcQueueLock); 01401 01402 // 01403 // If APC queuing is enable, then attempt to queue the APC object. 01404 // 01405 01406 if (Thread->ApcQueueable && KiInsertQueueApc(Apc, Increment)) { 01407 Inserted = TRUE; 01408 01409 // 01410 // If UserMode: 01411 // For vdm a UserMode Apc is only queued by a kernel mode 01412 // apc which is on the current thread for the target thread. 01413 // Force UserApcPending for User mode apcstate, so that 01414 // the apc will fire when this thread exits the kernel. 01415 // 01416 01417 if (ApcMode == UserMode) { 01418 KiBoostPriorityThread(Thread, Increment); 01419 Thread->ApcState.UserApcPending = TRUE; 01420 } 01421 01422 } else { 01423 Inserted = FALSE; 01424 } 01425 01426 // 01427 // Unlock the dispatcher database, lower IRQL to its previous value, and 01428 // return whether the APC object was inserted. 01429 // 01430 01431 KiUnlockDispatcherDatabase(OldIrql); 01432 return Inserted; 01433 }

VOID KeI386VdmInitialize VOID   ) 
 

BOOLEAN Ki386GetSelectorParameters IN USHORT  Selector,
OUT PULONG  Flags,
OUT PULONG  Base,
OUT PULONG  Limit
 

BOOLEAN Ki386VdmDispatchIo IN ULONG  PortNumber,
IN ULONG  Size,
IN BOOLEAN  Read,
IN UCHAR  InstructionSize,
IN PKTRAP_FRAME  TrapFrame
 

Definition at line 307 of file ke/i386/vdm.c.

References _VdmEventInfo::Event, _Vdm_Tib::EventInfo, EXCEPTION_EXECUTE_HANDLER, ExRaiseException(), FALSE, _VdmEventInfo::InstructionSize, _VdmEventInfo::IoInfo, _VdmIoInfo::PortNumber, Ps386GetVdmIoHandler(), PsGetCurrentProcess, PUSHORT, _VdmIoInfo::Read, _VdmIoInfo::Size, Size, TRUE, USHORT, VdmDispatchIoToHandler(), VdmDispatchUnalignedIoToHandler(), VdmEndExecution(), and VdmIO.

00316 : 00317 00318 This routine sets up the Event info for an IO event, and causes the 00319 event to be reflected to the Monitor. 00320 00321 It is assumed that interrupts are enabled upon entry, and Irql is 00322 at APC level. 00323 00324 Arguments: 00325 00326 PortNumber -- Supplies the port number the IO was done to 00327 Size -- Supplies the size of the IO operation. 00328 Read -- Indicates whether the IO operation was a read or a write. 00329 InstructionSize -- Supplies the size of the IO instruction in bytes. 00330 00331 Return Value: 00332 00333 True if the io instruction will be reflected to User mode. 00334 00335 --*/ 00336 { 00337 PVDM_TIB VdmTib; 00338 EXCEPTION_RECORD ExceptionRecord; 00339 VDM_IO_HANDLER VdmIoHandler; 00340 ULONG Result; 00341 BOOLEAN Success = FALSE; 00342 ULONG Context; 00343 00344 Success = Ps386GetVdmIoHandler( 00345 PsGetCurrentProcess(), 00346 PortNumber & ~0x3, 00347 &VdmIoHandler, 00348 &Context 00349 ); 00350 00351 if (Success) { 00352 Result = TrapFrame->Eax; 00353 // if port is not aligned, perform unaligned IO 00354 // else do the io the easy way 00355 if (PortNumber % Size) { 00356 Success = VdmDispatchUnalignedIoToHandler( 00357 &VdmIoHandler, 00358 Context, 00359 PortNumber, 00360 Size, 00361 Read, 00362 &Result 00363 ); 00364 } else { 00365 Success = VdmDispatchIoToHandler( 00366 &VdmIoHandler, 00367 Context, 00368 PortNumber, 00369 Size, 00370 Read, 00371 &Result 00372 ); 00373 } 00374 } 00375 00376 if (Success) { 00377 if (Read) { 00378 switch (Size) { 00379 case 4: 00380 TrapFrame->Eax = Result; 00381 break; 00382 case 2: 00383 *(PUSHORT)(&TrapFrame->Eax) = (USHORT)Result; 00384 break; 00385 case 1: 00386 *(PUCHAR)(&TrapFrame->Eax) = (UCHAR)Result; 00387 break; 00388 } 00389 } 00390 TrapFrame->Eip += (ULONG) InstructionSize; 00391 return TRUE; 00392 } else { 00393 try { 00394 VdmTib = 00395 ((PVDM_PROCESS_OBJECTS)PsGetCurrentProcess()->VdmObjects)->VdmTib; 00396 VdmTib->EventInfo.InstructionSize = (ULONG) InstructionSize; 00397 VdmTib->EventInfo.Event = VdmIO; 00398 VdmTib->EventInfo.IoInfo.PortNumber = (USHORT)PortNumber; 00399 VdmTib->EventInfo.IoInfo.Size = (USHORT)Size; 00400 VdmTib->EventInfo.IoInfo.Read = Read; 00401 } except(EXCEPTION_EXECUTE_HANDLER) { 00402 ExceptionRecord.ExceptionCode = STATUS_ACCESS_VIOLATION; 00403 ExceptionRecord.ExceptionFlags = 0; 00404 ExceptionRecord.NumberParameters = 0; 00405 ExRaiseException(&ExceptionRecord); 00406 return FALSE; 00407 } 00408 } 00409 00410 VdmEndExecution(TrapFrame, VdmTib); 00411 00412 return TRUE; 00413 00414 }

BOOLEAN Ki386VdmDispatchStringIo IN ULONG  PortNumber,
IN ULONG  Size,
IN BOOLEAN  Rep,
IN BOOLEAN  Read,
IN ULONG  Count,
IN ULONG  Address,
IN UCHAR  InstructionSize,
IN PKTRAP_FRAME  TrapFrame
 

Definition at line 418 of file ke/i386/vdm.c.

References _VdmStringIoInfo::Address, _VdmStringIoInfo::Count, Count, _VdmEventInfo::Event, _Vdm_Tib::EventInfo, EXCEPTION_EXECUTE_HANDLER, ExRaiseException(), FALSE, Index, _VdmEventInfo::InstructionSize, _VdmStringIoInfo::PortNumber, Ps386GetVdmIoHandler(), PsGetCurrentProcess, PUSHORT, _VdmStringIoInfo::Read, _VdmStringIoInfo::Size, Size, _VdmEventInfo::StringIoInfo, TRUE, USHORT, VdmDispatchStringIoToHandler(), VdmEndExecution(), and VdmStringIO.

00430 : 00431 00432 This routine sets up the Event info for a string IO event, and causes the 00433 event to be reflected to the Monitor. 00434 00435 It is assumed that interrupts are enabled upon entry, and Irql is 00436 at APC level. 00437 00438 Arguments: 00439 00440 PortNumber -- Supplies the port number the IO was done to 00441 Size -- Supplies the size of the IO operation. 00442 Read -- Indicates whether the IO operation was a read or a write. 00443 Count -- indicates the number of IO operations of Size size 00444 Address -- Indicates address for string io 00445 InstructionSize -- Supplies the size of the IO instruction in bytes. 00446 00447 00448 Return Value: 00449 00450 True if the io instruction will be reflected to User mode. 00451 00452 00453 00454 --*/ 00455 { 00456 PVDM_TIB VdmTib; 00457 EXCEPTION_RECORD ExceptionRecord; 00458 BOOLEAN Success = FALSE; 00459 VDM_IO_HANDLER VdmIoHandler; 00460 ULONG Context; 00461 00462 Success = Ps386GetVdmIoHandler( 00463 PsGetCurrentProcess(), 00464 PortNumber & ~0x3, 00465 &VdmIoHandler, 00466 &Context 00467 ); 00468 00469 00470 if (Success) { 00471 Success = VdmDispatchStringIoToHandler( 00472 &VdmIoHandler, 00473 Context, 00474 PortNumber, 00475 Size, 00476 Count, 00477 Read, 00478 Address 00479 ); 00480 } 00481 00482 if (Success) { 00483 PUSHORT pIndexRegister; 00484 USHORT Index; 00485 00486 // WARNING no 32 bit address support 00487 00488 pIndexRegister = Read ? (PUSHORT)&TrapFrame->Edi 00489 : (PUSHORT)&TrapFrame->Esi; 00490 00491 if (TrapFrame->EFlags & EFLAGS_DF_MASK) { 00492 Index = *pIndexRegister - (USHORT)(Count * Size); 00493 } 00494 else { 00495 Index = *pIndexRegister + (USHORT)(Count * Size); 00496 } 00497 00498 *pIndexRegister = Index; 00499 00500 if (Rep) { 00501 (USHORT)TrapFrame->Ecx = 0; 00502 } 00503 00504 TrapFrame->Eip += (ULONG) InstructionSize; 00505 return TRUE; 00506 } 00507 00508 try { 00509 VdmTib = 00510 ((PVDM_PROCESS_OBJECTS)PsGetCurrentProcess()->VdmObjects)->VdmTib; 00511 VdmTib->EventInfo.InstructionSize = (ULONG) InstructionSize; 00512 VdmTib->EventInfo.Event = VdmStringIO; 00513 VdmTib->EventInfo.StringIoInfo.PortNumber = (USHORT)PortNumber; 00514 VdmTib->EventInfo.StringIoInfo.Size = (USHORT)Size; 00515 VdmTib->EventInfo.StringIoInfo.Rep = Rep; 00516 VdmTib->EventInfo.StringIoInfo.Read = Read; 00517 VdmTib->EventInfo.StringIoInfo.Count = Count; 00518 VdmTib->EventInfo.StringIoInfo.Address = Address; 00519 } except(EXCEPTION_EXECUTE_HANDLER) { 00520 ExceptionRecord.ExceptionCode = STATUS_ACCESS_VIOLATION; 00521 ExceptionRecord.ExceptionFlags = 0; 00522 ExceptionRecord.NumberParameters = 0; 00523 ExRaiseException(&ExceptionRecord); 00524 return FALSE; 00525 } 00526 00527 00528 VdmEndExecution(TrapFrame, VdmTib); 00529 00530 return TRUE; 00531 }

ULONG Ki386VdmEnablePentiumExtentions ULONG   ) 
 

Referenced by KeI386VdmInitialize().

BOOLEAN VdmCallStringIoHandler IN PVDM_IO_HANDLER  VdmIoHandler,
IN PVOID  StringIoRoutine,
IN ULONG  Context,
IN ULONG  PortNumber,
IN ULONG  Size,
IN ULONG  Count,
IN BOOLEAN  Read,
IN ULONG  Data
 

Definition at line 882 of file ke/i386/vdm.c.

References ASSERT, Count, EMULATOR_READ_ACCESS, EMULATOR_WRITE_ACCESS, EXCEPTION_EXECUTE_HANDLER, ExRaiseException(), NT_SUCCESS, NTSTATUS(), NULL, PDRIVER_IO_PORT_UCHAR_STRING, Size, Status, STRINGIO_BUFFER_SIZE, TRUE, VdmConvertToLinearAddress(), VdmDispatchIoToHandler(), VdmDispatchUnalignedIoToHandler(), and VdmStringIoBuffer.

Referenced by VdmDispatchStringIoToHandler().

00894 : 00895 00896 This routine actually performs the call to string io routine. It takes 00897 care of buffering the user data in kernel space so that the device driver 00898 does not have to. If there is not a string io function, or the io is 00899 misaligned, it will be simulated as a series of normal io operations 00900 00901 Arguments: 00902 00903 StringIoRoutine -- Supplies a pointer to the string Io routine 00904 Context -- Supplies 32 bits of data set when the port was trapped 00905 PortNumber -- Supplies the number of the port to perform Io to 00906 Size -- Supplies the size of the io operations 00907 Count -- Supplies the number of Io operations in the string. 00908 Read -- Indicates a read operation 00909 Data -- Supplies a pointer to the user buffer to perform the io on. 00910 00911 Returns 00912 00913 TRUE if a handler was called 00914 FALSE if not. 00915 00916 --*/ 00917 { 00918 ULONG TotalBytes,BytesDone,BytesToDo,LoopCount,NumberIo; 00919 PUCHAR CurrentDataPtr; 00920 UCHAR AccessType; 00921 EXCEPTION_RECORD ExceptionRecord; 00922 NTSTATUS Status; 00923 BOOLEAN Success; 00924 00925 Success = VdmConvertToLinearAddress( 00926 Data, 00927 &CurrentDataPtr 00928 ); 00929 00930 if (!Success) { 00931 ExceptionRecord.ExceptionCode = STATUS_ACCESS_VIOLATION; 00932 ExceptionRecord.ExceptionFlags = 0; 00933 ExceptionRecord.NumberParameters = 0; 00934 ExRaiseException(&ExceptionRecord); 00935 // Cause kernel exit, rather than Io reflection 00936 return TRUE; 00937 } 00938 00939 00940 TotalBytes = Count * Size; 00941 BytesDone = 0; 00942 00943 if (PortNumber % Size) { 00944 StringIoRoutine = NULL; 00945 } 00946 00947 if (Read) { 00948 AccessType = EMULATOR_READ_ACCESS; 00949 } else { 00950 AccessType = EMULATOR_WRITE_ACCESS; 00951 } 00952 00953 00954 // Set up try out here to avoid overhead in loop 00955 try { 00956 while (BytesDone < TotalBytes) { 00957 if ((BytesDone + STRINGIO_BUFFER_SIZE) > TotalBytes) { 00958 BytesToDo = TotalBytes - BytesDone; 00959 } else { 00960 BytesToDo = STRINGIO_BUFFER_SIZE; 00961 } 00962 00963 ASSERT((!(BytesToDo % Size))); 00964 00965 if (!Read) { 00966 RtlMoveMemory(VdmStringIoBuffer, CurrentDataPtr, BytesToDo); 00967 } 00968 00969 NumberIo = BytesToDo / Size; 00970 00971 if (StringIoRoutine) { 00972 // in order to avoid having 3 separate calls, one for each size 00973 // we simply cast the parameters appropriately for the 00974 // byte routine. 00975 00976 Status = (*((PDRIVER_IO_PORT_UCHAR_STRING)StringIoRoutine))( 00977 Context, 00978 PortNumber, 00979 AccessType, 00980 VdmStringIoBuffer, 00981 NumberIo 00982 ); 00983 00984 if (NT_SUCCESS(Status)) { 00985 Success |= TRUE; 00986 } 00987 } else { 00988 if (PortNumber % Size) { 00989 for (LoopCount = 0; LoopCount < NumberIo; LoopCount++ ) { 00990 Success |= VdmDispatchUnalignedIoToHandler( 00991 VdmIoHandler, 00992 Context, 00993 PortNumber, 00994 Size, 00995 Read, 00996 (PULONG)(VdmStringIoBuffer + LoopCount * Size) 00997 ); 00998 } 00999 } else { 01000 for (LoopCount = 0; LoopCount < NumberIo; LoopCount++ ) { 01001 Success |= VdmDispatchIoToHandler( 01002 VdmIoHandler, 01003 Context, 01004 PortNumber, 01005 Size, 01006 Read, 01007 (PULONG)(VdmStringIoBuffer + LoopCount * Size) 01008 ); 01009 } 01010 01011 } 01012 } 01013 01014 if (Read) { 01015 RtlMoveMemory(CurrentDataPtr, VdmStringIoBuffer, BytesToDo); 01016 } 01017 01018 BytesDone += BytesToDo; 01019 CurrentDataPtr += BytesToDo; 01020 } 01021 } except(EXCEPTION_EXECUTE_HANDLER) { 01022 ExceptionRecord.ExceptionCode = GetExceptionCode(); 01023 ExceptionRecord.ExceptionFlags = 0; 01024 ExceptionRecord.NumberParameters = 0; 01025 ExRaiseException(&ExceptionRecord); 01026 // Cause kernel exit, rather than Io reflection 01027 Success = TRUE; 01028 } 01029 return Success; 01030 01031 }

BOOLEAN VdmConvertToLinearAddress IN ULONG  SegmentedAddress,
OUT PVOID *  LinearAddress
 

Definition at line 1034 of file ke/i386/vdm.c.

References KeGetCurrentThread, Ki386GetSelectorParameters(), TRUE, and USHORT.

Referenced by VdmCallStringIoHandler().

01040 : 01041 01042 This routine converts the specified segmented address into a linear 01043 address, based on processor mode in user mode. 01044 01045 Arguments: 01046 01047 SegmentedAddress -- Supplies the segmented address to convert. 01048 LinearAddress -- Supplies a pointer to the destination for the 01049 coresponding linear address 01050 01051 Return Value: 01052 01053 True if the address was converted. 01054 False otherwise 01055 01056 Note: 01057 01058 A linear address of 0 is a valid return 01059 --*/ 01060 { 01061 PKTHREAD Thread; 01062 PKTRAP_FRAME TrapFrame; 01063 BOOLEAN Success; 01064 ULONG Base, Limit, Flags; 01065 01066 Thread = KeGetCurrentThread(); 01067 TrapFrame = VdmGetTrapFrame(Thread); 01068 01069 if (TrapFrame->EFlags & EFLAGS_V86_MASK) { 01070 *LinearAddress = (PVOID)(((SegmentedAddress & 0xFFFF0000) >> 12) + 01071 (SegmentedAddress & 0xFFFF)); 01072 Success = TRUE; 01073 } else { 01074 Success = Ki386GetSelectorParameters( 01075 (USHORT)((SegmentedAddress & 0xFFFF0000) >> 16), 01076 &Flags, 01077 &Base, 01078 &Limit 01079 ); 01080 if (Success) { 01081 *LinearAddress = (PVOID)(Base + (SegmentedAddress & 0xFFFF)); 01082 } 01083 } 01084 return Success; 01085 }

BOOLEAN VdmConvertToLinearAddress IN ULONG  SegmentedAddress,
IN PVOID *  LinearAddress
 

BOOLEAN VdmDispatchIoToHandler IN PVDM_IO_HANDLER  VdmIoHandler,
IN ULONG  Context,
IN ULONG  PortNumber,
IN ULONG  Size,
IN BOOLEAN  Read,
IN OUT PULONG  Data
 

Definition at line 535 of file ke/i386/vdm.c.

References ASSERT, EMULATOR_READ_ACCESS, EMULATOR_WRITE_ACCESS, FALSE, NT_SUCCESS, NTSTATUS(), PUSHORT, Size, Status, TRUE, and USHORT.

Referenced by Ki386VdmDispatchIo(), VdmCallStringIoHandler(), and VdmDispatchUnalignedIoToHandler().

00545 : 00546 00547 This routine calls the handler for the IO. If there is not a handler 00548 of the proper size, it will call this function for 2 io's to the next 00549 smaller size. If the size was a byte, and there was no handler, FALSE 00550 is returned. 00551 00552 Arguments: 00553 00554 VdmIoHandler -- Supplies a pointer to the handler table 00555 Context -- Supplies 32 bits of data set when the port was trapped 00556 PortNumber -- Supplies the port number the IO was done to 00557 Size -- Supplies the size of the IO operation. 00558 Read -- Indicates whether the IO operation was a read or a write. 00559 Result -- Supplies a pointer to the location to put the result 00560 00561 Return Value: 00562 00563 True if one or more handlers were called to take care of the IO. 00564 False if no handler was called to take care of the IO. 00565 00566 --*/ 00567 { 00568 NTSTATUS Status; 00569 BOOLEAN Success1, Success2; 00570 USHORT FnIndex; 00571 UCHAR AccessType; 00572 00573 // Insure that Io is aligned 00574 ASSERT((!(PortNumber % Size))); 00575 00576 if (Read) { 00577 FnIndex = 0; 00578 AccessType = EMULATOR_READ_ACCESS; 00579 } else { 00580 FnIndex = 1; 00581 AccessType = EMULATOR_WRITE_ACCESS; 00582 } 00583 00584 switch (Size) { 00585 case 1: 00586 if (VdmIoHandler->IoFunctions[FnIndex].UcharIo[PortNumber % 4]) { 00587 Status = (*(VdmIoHandler->IoFunctions[FnIndex].UcharIo[PortNumber % 4]))( 00588 Context, 00589 PortNumber, 00590 AccessType, 00591 (PUCHAR)Data 00592 ); 00593 if (NT_SUCCESS(Status)) { 00594 return TRUE; 00595 } 00596 } 00597 // No handler for this port 00598 return FALSE; 00599 00600 case 2: 00601 if (VdmIoHandler->IoFunctions[FnIndex].UshortIo[PortNumber % 2]) { 00602 Status = (*(VdmIoHandler->IoFunctions[FnIndex].UshortIo[PortNumber % 2]))( 00603 Context, 00604 PortNumber, 00605 AccessType, 00606 (PUSHORT)Data 00607 ); 00608 if (NT_SUCCESS(Status)) { 00609 return TRUE; 00610 } 00611 } else { 00612 // Dispatch to the two uchar handlers for this ushort port 00613 Success1 = VdmDispatchIoToHandler( 00614 VdmIoHandler, 00615 Context, 00616 PortNumber, 00617 Size /2, 00618 Read, 00619 Data 00620 ); 00621 00622 Success2 = VdmDispatchIoToHandler( 00623 VdmIoHandler, 00624 Context, 00625 PortNumber + 1, 00626 Size / 2, 00627 Read, 00628 (PULONG)((PUCHAR)Data + 1) 00629 ); 00630 00631 return (Success1 || Success2); 00632 00633 } 00634 return FALSE; 00635 00636 case 4: 00637 if (VdmIoHandler->IoFunctions[FnIndex].UlongIo) { 00638 Status = (*(VdmIoHandler->IoFunctions[FnIndex].UlongIo))( 00639 Context, 00640 PortNumber, 00641 AccessType, 00642 Data 00643 ); 00644 if (NT_SUCCESS(Status)) { 00645 return TRUE; 00646 } 00647 } else { 00648 // Dispatch to the two ushort handlers for this port 00649 Success1 = VdmDispatchIoToHandler( 00650 VdmIoHandler, 00651 Context, 00652 PortNumber, 00653 Size /2, 00654 Read, 00655 Data); 00656 Success2 = VdmDispatchIoToHandler( 00657 VdmIoHandler, 00658 Context, 00659 PortNumber + 2, 00660 Size / 2, 00661 Read, 00662 (PULONG)((PUSHORT)Data + 1) 00663 ); 00664 00665 return (Success1 || Success2); 00666 } 00667 return FALSE; 00668 } 00669 }

BOOLEAN VdmDispatchStringIoToHandler IN PVDM_IO_HANDLER  VdmIoHandler,
IN ULONG  Context,
IN ULONG  PortNumber,
IN ULONG  Size,
IN ULONG  Count,
IN BOOLEAN  Read,
IN ULONG  Data
 

Definition at line 777 of file ke/i386/vdm.c.

References Count, Executive, FALSE, KeReleaseMutex(), KernelMode, KeWaitForSingleObject(), NT_SUCCESS, NTSTATUS(), NULL, Size, Status, USHORT, VdmCallStringIoHandler(), and VdmStringIoMutex.

Referenced by Ki386VdmDispatchStringIo().

00788 : 00789 00790 This routine calls the handler for the IO. If there is not a handler 00791 of the proper size, or the io is not aligned, it will simulate the io 00792 to the normal io handlers. 00793 00794 Arguments: 00795 00796 VdmIoHandler -- Supplies a pointer to the handler table 00797 Context -- Supplies 32 bits of data set when the port was trapped 00798 PortNumber -- Supplies the port number the IO was done to 00799 Size -- Supplies the size of the IO operation. 00800 Count -- Supplies the number of IO operations. 00801 Read -- Indicates whether the IO operation was a read or a write. 00802 Data -- Supplies a segmented address at which to put the result. 00803 00804 Return Value: 00805 00806 True if one or more handlers were called to take care of the IO. 00807 False if no handler was called to take care of the IO. 00808 00809 --*/ 00810 { 00811 BOOLEAN Success = FALSE; 00812 USHORT FnIndex; 00813 NTSTATUS Status; 00814 00815 if (Read) { 00816 FnIndex = 0; 00817 } else { 00818 FnIndex = 1; 00819 } 00820 00821 Status = KeWaitForSingleObject( 00822 &VdmStringIoMutex, 00823 Executive, 00824 KernelMode, 00825 FALSE, 00826 NULL 00827 ); 00828 00829 if (!NT_SUCCESS(Status)) { 00830 return FALSE; 00831 } 00832 00833 switch (Size) { 00834 case 1: 00835 Success = VdmCallStringIoHandler( 00836 VdmIoHandler, 00837 (PVOID)VdmIoHandler->IoFunctions[FnIndex].UcharStringIo[PortNumber % 4], 00838 Context, 00839 PortNumber, 00840 Size, 00841 Count, 00842 Read, 00843 Data 00844 ); 00845 break; 00846 00847 case 2: 00848 Success = VdmCallStringIoHandler( 00849 VdmIoHandler, 00850 (PVOID)VdmIoHandler->IoFunctions[FnIndex].UshortStringIo[PortNumber % 2], 00851 Context, 00852 PortNumber, 00853 Size, 00854 Count, 00855 Read, 00856 Data 00857 ); 00858 break; 00859 00860 case 4: 00861 Success = VdmCallStringIoHandler( 00862 VdmIoHandler, 00863 (PVOID)VdmIoHandler->IoFunctions[FnIndex].UlongStringIo, 00864 Context, 00865 PortNumber, 00866 Size, 00867 Count, 00868 Read, 00869 Data 00870 ); 00871 break; 00872 00873 } 00874 KeReleaseMutex(&VdmStringIoMutex, FALSE); 00875 return Success; 00876 }

BOOLEAN VdmDispatchUnalignedIoToHandler IN PVDM_IO_HANDLER  VdmIoHandler,
IN ULONG  Context,
IN ULONG  PortNumber,
IN ULONG  Size,
IN BOOLEAN  Read,
IN OUT PULONG  Data
 

Definition at line 672 of file ke/i386/vdm.c.

References ASSERT, Offset, Size, and VdmDispatchIoToHandler().

Referenced by Ki386VdmDispatchIo(), and VdmCallStringIoHandler().

00682 : 00683 00684 This routine converts the unaligned IO to the necessary number of aligned 00685 IOs to smaller ports. 00686 00687 Arguments: 00688 00689 VdmIoHandler -- Supplies a pointer to the handler table 00690 Context -- Supplies 32 bits of data set when the port was trapped 00691 PortNumber -- Supplies the port number the IO was done to 00692 Size -- Supplies the size of the IO operation. 00693 Read -- Indicates whether the IO operation was a read or a write. 00694 Result -- Supplies a pointer to the location to put the result 00695 00696 Return Value: 00697 00698 True if one or more handlers were called to take care of the IO. 00699 False if no handler was called to take care of the IO. 00700 00701 --*/ 00702 { 00703 ULONG Offset; 00704 BOOLEAN Success; 00705 00706 ASSERT((Size > 1)); 00707 ASSERT((PortNumber % Size)); 00708 00709 Offset = 0; 00710 00711 // 00712 // The possible unaligned io situations are as follows. 00713 // 00714 // 1. Uchar aligned Ulong io 00715 // We have to dispatch a uchar io, a ushort io, and a uchar io 00716 // 00717 // 2. Ushort aligned Ulong Io 00718 // We have to dispatch a ushort io, and a ushort io 00719 // 00720 // 3. Uchar aligned Ushort Io 00721 // We have to dispatch a uchar io and a uchar io 00722 // 00723 00724 // if the port is uchar aligned 00725 if ((PortNumber % Size) & 1) { 00726 Success = VdmDispatchIoToHandler( 00727 VdmIoHandler, 00728 Context, 00729 PortNumber, 00730 1, 00731 Read, 00732 Data 00733 ); 00734 Offset += 1; 00735 // else it is ushort aligned (and therefore must be a ulong port) 00736 } else { 00737 Success = VdmDispatchIoToHandler( 00738 VdmIoHandler, 00739 Context, 00740 PortNumber, 00741 2, 00742 Read, 00743 Data 00744 ); 00745 Offset += 2; 00746 } 00747 00748 // if it is a ulong port, we know we have a ushort IO to dispatch 00749 if (Size == 4) { 00750 Success |= VdmDispatchIoToHandler( 00751 VdmIoHandler, 00752 Context, 00753 PortNumber + Offset, 00754 2, 00755 Read, 00756 (PULONG)((PUCHAR)Data + Offset) 00757 ); 00758 Offset += 2; 00759 } 00760 00761 // If we haven't dispatched the entire port, dispatch the final uchar 00762 if (Offset != 4) { 00763 Success |= VdmDispatchIoToHandler( 00764 VdmIoHandler, 00765 Context, 00766 PortNumber + Offset, 00767 1, 00768 Read, 00769 (PULONG)((PUCHAR)Data + Offset) 00770 ); 00771 } 00772 00773 return Success; 00774 }


Variable Documentation

ULONG KeI386EFlagsAndMaskV86 = EFLAGS_USER_SANITIZE
 

Definition at line 153 of file ke/i386/vdm.c.

Referenced by KeI386VdmInitialize().

ULONG KeI386EFlagsOrMaskV86 = EFLAGS_INTERRUPT_MASK
 

Definition at line 154 of file ke/i386/vdm.c.

Referenced by KeI386VdmInitialize().

BOOLEAN KeI386VdmIoplAllowed = FALSE
 

Definition at line 155 of file ke/i386/vdm.c.

Referenced by KeI386VdmInitialize(), NtVdmControl(), VdmDispatchInterrupts(), VdmEndExecution(), VdmpDispatchableIntPending(), and VdmpStartExecution().

ULONG KeI386VirtualIntExtensions = 0
 

Definition at line 156 of file ke/i386/vdm.c.

Referenced by KeI386VdmInitialize(), NtVdmControl(), VdmDispatchInterrupts(), VdmEndExecution(), VdmpDispatchableIntPending(), VdmpQueueIntApcRoutine(), and VdmpStartExecution().

ULONG VdmFixedStateLinear
 

Definition at line 151 of file ke/i386/vdm.c.

Referenced by KeI386VdmInitialize(), and VdmpStartExecution().

UCHAR VdmStringIoBuffer[STRINGIO_BUFFER_SIZE]
 

Definition at line 879 of file ke/i386/vdm.c.

Referenced by VdmCallStringIoHandler().

KMUTEX VdmStringIoMutex
 

Definition at line 150 of file ke/i386/vdm.c.

Referenced by KeI386VdmInitialize(), and VdmDispatchStringIoToHandler().


Generated on Sat May 15 19:46:07 2004 for test by doxygen 1.3.7