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

vdmp.h File Reference

#include <ntos.h>
#include <nturtl.h>
#include <vdmntos.h>

Go to the source code of this file.

Defines

#define VDMTIB_KMODE   0x0001
#define VDMTIB_PROBE   0x0002
#define VDMTIB_KPROBE   (VDMTIB_KMODE|VDMTIB_PROBE)

Functions

NTSTATUS VdmpInitialize (PVDMICAUSERDATA pIcaUserData)
NTSTATUS VdmpStartExecution (VOID)
VOID VdmSwapContexts (IN PKTRAP_FRAME TrapFrame, IN PCONTEXT InContext, IN PCONTEXT OutContext)
NTSTATUS VdmpQueueInterrupt (IN HANDLE ThreadHandle)
NTSTATUS VdmpDelayInterrupt (PVDMDELAYINTSDATA pdsd)
NTSTATUS VdmpEnterIcaLock (IN PRTL_CRITICAL_SECTION pIcaLock)
NTSTATUS VdmpLeaveIcaLock (IN PRTL_CRITICAL_SECTION pIcaLock)
BOOLEAN VdmpDispatchableIntPending (IN ULONG EFlags)
NTSTATUS VdmpIsThreadTerminating (HANDLE ThreadId)
BOOLEAN VdmPrinterStatus (ULONG iPort, ULONG cbInstructionSize, PKTRAP_FRAME TrapFrame)
BOOLEAN VdmPrinterWriteData (ULONG iPort, ULONG cbInstructionSize, PKTRAP_FRAME TrapFrame)
NTSTATUS VdmpPrinterDirectIoOpen (PVOID ServiceData)
NTSTATUS VdmpPrinterDirectIoClose (PVOID ServiceData)
VOID VdmTraceEvent (USHORT Type, USHORT wData, USHORT lData, PKTRAP_FRAME TrapFrame)
NTSTATUS VdmpPrinterInitialize (PVOID ServiceData)
NTSTATUS VdmpGetVdmTib (PVDM_TIB *ppVdmTib, ULONG dwFlags)


Define Documentation

#define VDMTIB_KMODE   0x0001
 

Definition at line 198 of file vdm/i386/vdmp.h.

Referenced by NTFastDOSIO(), VdmFlushPrinterWriteData(), VdmpPrinterInitialize(), VdmPrinterStatus(), VdmPrinterWriteData(), and VdmpStartExecution().

#define VDMTIB_KPROBE   (VDMTIB_KMODE|VDMTIB_PROBE)
 

Definition at line 200 of file vdm/i386/vdmp.h.

Referenced by VdmDispatchIRQ13(), VdmDispatchPageFault(), and VdmpQueueIntApcRoutine().

#define VDMTIB_PROBE   0x0002
 

Definition at line 199 of file vdm/i386/vdmp.h.

Referenced by VdmpInitialize().


Function Documentation

NTSTATUS VdmpDelayInterrupt PVDMDELAYINTSDATA  pdsd  ) 
 

Definition at line 1235 of file vdmints.c.

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

Referenced by NtVdmControl().

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

BOOLEAN VdmpDispatchableIntPending IN ULONG  EFlags  ) 
 

Referenced by VdmpQueueIntApcRoutine().

NTSTATUS VdmpEnterIcaLock IN PRTL_CRITICAL_SECTION  pIcaLock  ) 
 

Referenced by VdmDispatchInterrupts().

NTSTATUS VdmpGetVdmTib PVDM_TIB ppVdmTib,
ULONG  dwFlags
 

Referenced by NTFastDOSIO(), VdmDispatchIRQ13(), VdmDispatchPageFault(), VdmFlushPrinterWriteData(), VdmpInitialize(), VdmpPrinterInitialize(), VdmpQueueIntApcRoutine(), VdmPrinterStatus(), VdmPrinterWriteData(), and VdmpStartExecution().

NTSTATUS VdmpInitialize PVDMICAUSERDATA  pIcaUserData  ) 
 

Definition at line 19 of file vdminit.c.

References CmRegistryMachineHardwareDescriptionSystemName, DbgPrint, ExAllocatePoolWithTag, ExFreePool(), ExInitializeFastMutex, ExSystemExceptionFilter(), Index, KeI386MachineType, KeInitializeSpinLock(), KEY_VALUE_BUFFER_SIZE, L, NonPagedPool, NT_SUCCESS, NTSTATUS(), NULL, ObjectAttributes, PAGED_CODE, PagedPool, _EPROCESS::Pcb, ProbeForRead, ProbeForWrite(), ProbeForWriteHandle, ProbeForWriteUlong, PsChargePoolQuota(), PsGetCurrentProcess, PsGetCurrentThread, PsReturnPoolQuota(), RtlInitUnicodeString(), Status, TRUE, USHORT, _EPROCESS::VdmObjects, VdmpGetVdmTib(), and VDMTIB_PROBE.

Referenced by NtVdmControl().

00025 : 00026 00027 Initialize the address space of a VDM. 00028 00029 Arguments: 00030 00031 None, 00032 00033 Return Value: 00034 00035 NTSTATUS. 00036 00037 --*/ 00038 00039 { 00040 NTSTATUS Status, StatusCopy; 00041 OBJECT_ATTRIBUTES ObjectAttributes; 00042 UNICODE_STRING SectionName; 00043 UNICODE_STRING WorkString; 00044 ULONG ViewSize; 00045 LARGE_INTEGER ViewBase; 00046 PVOID BaseAddress; 00047 PVOID destination; 00048 HANDLE SectionHandle, RegistryHandle; 00049 PEPROCESS Process; 00050 ULONG ResultLength; 00051 ULONG Index; 00052 PCM_FULL_RESOURCE_DESCRIPTOR ResourceDescriptor; 00053 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResourceDescriptor; 00054 PKEY_VALUE_FULL_INFORMATION KeyValueBuffer; 00055 PCM_ROM_BLOCK BiosBlock; 00056 ULONG LastMappedAddress; 00057 PVDM_PROCESS_OBJECTS pVdmObjects = NULL; 00058 USHORT PagedQuotaCharged = 0; 00059 USHORT NonPagedQuotaCharged = 0; 00060 HANDLE hThread; 00061 PVDM_TIB VdmTib; 00062 00063 00064 PAGED_CODE(); 00065 00066 Status = VdmpGetVdmTib(&VdmTib, VDMTIB_PROBE); // take from user mode and probe 00067 00068 if (!NT_SUCCESS(Status)) { 00069 return Status; 00070 } 00071 00072 if ((KeI386MachineType & MACHINE_TYPE_PC_9800_COMPATIBLE) == 0) { 00073 00074 // 00075 // This is PC/AT (and FMR in Japan) VDM. 00076 // 00077 00078 RtlInitUnicodeString( 00079 &SectionName, 00080 L"\\Device\\PhysicalMemory" 00081 ); 00082 00083 InitializeObjectAttributes( 00084 &ObjectAttributes, 00085 &SectionName, 00086 OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE, 00087 (HANDLE) NULL, 00088 (PSECURITY_DESCRIPTOR) NULL 00089 ); 00090 00091 Status = ZwOpenSection( 00092 &SectionHandle, 00093 SECTION_ALL_ACCESS, 00094 &ObjectAttributes 00095 ); 00096 00097 if (!NT_SUCCESS(Status)) { 00098 00099 return Status; 00100 00101 } 00102 00103 // 00104 // Copy the first page of memory into the VDM's address space 00105 // 00106 00107 BaseAddress = 0; 00108 destination = 0; 00109 ViewSize = 0x1000; 00110 ViewBase.LowPart = 0; 00111 ViewBase.HighPart = 0; 00112 00113 Status = ZwMapViewOfSection( 00114 SectionHandle, 00115 NtCurrentProcess(), 00116 &BaseAddress, 00117 0, 00118 ViewSize, 00119 &ViewBase, 00120 &ViewSize, 00121 ViewUnmap, 00122 0, 00123 PAGE_READWRITE 00124 ); 00125 00126 if (!NT_SUCCESS(Status)) { 00127 ZwClose(SectionHandle); 00128 return Status; 00129 } 00130 00131 // problem with this statement below -- 00132 // it could be a non-vdm process and copying memory to address 0 00133 // should be guarded against 00134 00135 StatusCopy = STATUS_SUCCESS; 00136 try { 00137 RtlMoveMemory( 00138 destination, 00139 BaseAddress, 00140 ViewSize 00141 ); 00142 } 00143 except(ExSystemExceptionFilter()) { 00144 StatusCopy = GetExceptionCode(); 00145 } 00146 00147 00148 Status = ZwUnmapViewOfSection( 00149 NtCurrentProcess(), 00150 BaseAddress 00151 ); 00152 00153 if (!NT_SUCCESS(Status) || !NT_SUCCESS(StatusCopy)) { 00154 ZwClose(SectionHandle); 00155 return (NT_SUCCESS(Status) ? StatusCopy : Status); 00156 } 00157 00158 // 00159 // Map Rom into address space 00160 // 00161 00162 BaseAddress = (PVOID) 0x000C0000; 00163 ViewSize = 0x40000; 00164 ViewBase.LowPart = 0x000C0000; 00165 ViewBase.HighPart = 0; 00166 00167 00168 // 00169 // First unmap the reserved memory. This must be done here to prevent 00170 // the virtual memory in question from being consumed by some other 00171 // alloc vm call. 00172 // 00173 00174 Status = ZwFreeVirtualMemory( 00175 NtCurrentProcess(), 00176 &BaseAddress, 00177 &ViewSize, 00178 MEM_RELEASE 00179 ); 00180 00181 // N.B. This should probably take into account the fact that there are 00182 // a handfull of error conditions that are ok. (such as no memory to 00183 // release.) 00184 00185 if (!NT_SUCCESS(Status)) { 00186 ZwClose(SectionHandle); 00187 return Status; 00188 00189 } 00190 00191 // 00192 // Set up and open KeyPath 00193 // 00194 00195 InitializeObjectAttributes( 00196 &ObjectAttributes, 00197 &CmRegistryMachineHardwareDescriptionSystemName, 00198 OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE, 00199 (HANDLE)NULL, 00200 NULL 00201 ); 00202 00203 Status = ZwOpenKey( 00204 &RegistryHandle, 00205 KEY_READ, 00206 &ObjectAttributes 00207 ); 00208 00209 if (!NT_SUCCESS(Status)) { 00210 ZwClose(SectionHandle); 00211 return Status; 00212 } 00213 00214 // 00215 // Allocate space for the data 00216 // 00217 00218 KeyValueBuffer = ExAllocatePoolWithTag( 00219 PagedPool, 00220 KEY_VALUE_BUFFER_SIZE, 00221 ' MDV' 00222 ); 00223 00224 if (KeyValueBuffer == NULL) { 00225 ZwClose(RegistryHandle); 00226 ZwClose(SectionHandle); 00227 return STATUS_NO_MEMORY; 00228 } 00229 00230 // 00231 // Get the data for the rom information 00232 // 00233 00234 RtlInitUnicodeString( 00235 &WorkString, 00236 L"Configuration Data" 00237 ); 00238 00239 Status = ZwQueryValueKey( 00240 RegistryHandle, 00241 &WorkString, 00242 KeyValueFullInformation, 00243 KeyValueBuffer, 00244 KEY_VALUE_BUFFER_SIZE, 00245 &ResultLength 00246 ); 00247 00248 if (!NT_SUCCESS(Status)) { 00249 ZwClose(RegistryHandle); 00250 ExFreePool(KeyValueBuffer); 00251 ZwClose(SectionHandle); 00252 return Status; 00253 } 00254 00255 ResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR) 00256 ((PUCHAR) KeyValueBuffer + KeyValueBuffer->DataOffset); 00257 00258 if ((KeyValueBuffer->DataLength < sizeof(CM_FULL_RESOURCE_DESCRIPTOR)) || 00259 (ResourceDescriptor->PartialResourceList.Count < 2) 00260 ) { 00261 ZwClose(RegistryHandle); 00262 ExFreePool(KeyValueBuffer); 00263 ZwClose(SectionHandle); 00264 // No rom blocks. 00265 return STATUS_SUCCESS; 00266 } 00267 00268 PartialResourceDescriptor = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) 00269 ((PUCHAR)ResourceDescriptor + 00270 sizeof(CM_FULL_RESOURCE_DESCRIPTOR) + 00271 ResourceDescriptor->PartialResourceList.PartialDescriptors[0] 00272 .u.DeviceSpecificData.DataSize); 00273 00274 00275 if (KeyValueBuffer->DataLength < ((PUCHAR)PartialResourceDescriptor - 00276 (PUCHAR)ResourceDescriptor + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) 00277 + sizeof(CM_ROM_BLOCK)) 00278 ) { 00279 ZwClose(RegistryHandle); 00280 ExFreePool(KeyValueBuffer); 00281 ZwClose(SectionHandle); 00282 return STATUS_ILL_FORMED_SERVICE_ENTRY; 00283 } 00284 00285 00286 BiosBlock = (PCM_ROM_BLOCK)((PUCHAR)PartialResourceDescriptor + 00287 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)); 00288 00289 Index = PartialResourceDescriptor->u.DeviceSpecificData.DataSize / 00290 sizeof(CM_ROM_BLOCK); 00291 00292 // 00293 // N.B. Rom blocks begin on 2K (not necessarily page) boundaries 00294 // They end on 512 byte boundaries. This means that we have 00295 // to keep track of the last page mapped, and round the next 00296 // Rom block up to the next page boundary if necessary. 00297 // 00298 00299 LastMappedAddress = 0xC0000; 00300 00301 while (Index) { 00302 #if 0 00303 DbgPrint( 00304 "Bios Block, PhysAddr = %lx, size = %lx\n", 00305 BiosBlock->Address, 00306 BiosBlock->Size 00307 ); 00308 #endif 00309 if ((Index > 1) && 00310 ((BiosBlock->Address + BiosBlock->Size) == BiosBlock[1].Address) 00311 ) { 00312 // 00313 // Coalesce adjacent blocks 00314 // 00315 BiosBlock[1].Address = BiosBlock[0].Address; 00316 BiosBlock[1].Size += BiosBlock[0].Size; 00317 Index--; 00318 BiosBlock++; 00319 continue; 00320 } 00321 00322 BaseAddress = (PVOID)(BiosBlock->Address); 00323 ViewSize = BiosBlock->Size; 00324 00325 if ((ULONG)BaseAddress < LastMappedAddress) { 00326 if (ViewSize > (LastMappedAddress - (ULONG)BaseAddress)) { 00327 ViewSize = ViewSize - (LastMappedAddress - (ULONG)BaseAddress); 00328 BaseAddress = (PVOID)LastMappedAddress; 00329 } else { 00330 ViewSize = 0; 00331 } 00332 } 00333 00334 ViewBase.LowPart = (ULONG)BaseAddress; 00335 00336 if (ViewSize > 0) { 00337 00338 Status = ZwMapViewOfSection( 00339 SectionHandle, 00340 NtCurrentProcess(), 00341 &BaseAddress, 00342 0, 00343 ViewSize, 00344 &ViewBase, 00345 &ViewSize, 00346 ViewUnmap, 00347 MEM_DOS_LIM, 00348 PAGE_READWRITE 00349 ); 00350 00351 if (!NT_SUCCESS(Status)) { 00352 break; 00353 } 00354 00355 LastMappedAddress = (ULONG)BaseAddress + ViewSize; 00356 } 00357 00358 Index--; 00359 BiosBlock++; 00360 } 00361 00362 // 00363 // Free up the handles 00364 // 00365 00366 ZwClose(SectionHandle); 00367 ZwClose(RegistryHandle); 00368 ExFreePool(KeyValueBuffer); 00369 00370 } else { 00371 00372 // 00373 // This is PC-9800 Series VDM. 00374 // 00375 00376 Status = STATUS_SUCCESS; 00377 } 00378 00379 // 00380 // Mark the process as a vdm 00381 // 00382 00383 Process = PsGetCurrentProcess(); 00384 Process->Pcb.VdmFlag = TRUE; 00385 00386 00387 // 00388 // Create VdmObjects structure 00389 // 00390 // N.B. We don't use ExAllocatePoolWithQuota because it 00391 // takes a reference to the process (which ExFreePool 00392 // dereferences). Since we expect to clean up on 00393 // process deletion, we don't need or want the reference 00394 // (which will prevent the process from being deleted) 00395 // 00396 00397 try { 00398 00399 Process->VdmObjects = ExAllocatePoolWithTag( 00400 NonPagedPool, 00401 sizeof(VDM_PROCESS_OBJECTS), 00402 ' MDV' 00403 ); 00404 00405 if (Process->VdmObjects == NULL) { 00406 return STATUS_NO_MEMORY; 00407 } 00408 00409 00410 // 00411 // We use NonPagedQuotaCharged to keep track of the quota to return 00412 // if this function fails 00413 // 00414 PsChargePoolQuota(Process, NonPagedPool, sizeof(VDM_PROCESS_OBJECTS)); 00415 NonPagedQuotaCharged = sizeof(VDM_PROCESS_OBJECTS); 00416 00417 RtlZeroMemory( Process->VdmObjects, sizeof(VDM_PROCESS_OBJECTS)); 00418 pVdmObjects = Process->VdmObjects; 00419 ExInitializeFastMutex(&pVdmObjects->DelayIntFastMutex); 00420 KeInitializeSpinLock(&pVdmObjects->DelayIntSpinLock); 00421 InitializeListHead(&pVdmObjects->DelayIntListHead); 00422 00423 pVdmObjects->pIcaUserData = ExAllocatePoolWithTag( 00424 PagedPool, 00425 sizeof(VDMICAUSERDATA), 00426 ' MDV' 00427 ); 00428 00429 if (pVdmObjects->pIcaUserData == NULL) { 00430 Status = STATUS_NO_MEMORY; 00431 } else { 00432 00433 // 00434 // We use NonPagedQuotaCharged to keep track of the quota to return 00435 // if this function fails 00436 // 00437 PsChargePoolQuota( 00438 Process, 00439 PagedPool, 00440 sizeof(VDMICAUSERDATA) 00441 ); 00442 PagedQuotaCharged = sizeof(VDMICAUSERDATA); 00443 00444 RtlZeroMemory( pVdmObjects->pIcaUserData, sizeof(VDMICAUSERDATA)); 00445 00446 00447 // 00448 // Copy Ica addresses from service data (in user space) into 00449 // pVdmObjects->pIcaUserData 00450 // 00451 00452 ProbeForRead(pIcaUserData, sizeof(VDMICAUSERDATA), sizeof(UCHAR)); 00453 *pVdmObjects->pIcaUserData = *pIcaUserData; 00454 00455 00456 // 00457 // Probe static addresses in IcaUserData. 00458 // 00459 pIcaUserData = pVdmObjects->pIcaUserData; 00460 00461 ProbeForWriteHandle(pIcaUserData->phWowIdleEvent); 00462 00463 ProbeForWrite( 00464 pIcaUserData->pIcaLock, 00465 sizeof(RTL_CRITICAL_SECTION), 00466 sizeof(UCHAR) 00467 ); 00468 00469 ProbeForWrite( 00470 pIcaUserData->pIcaMaster, 00471 sizeof(VDMVIRTUALICA), 00472 sizeof(UCHAR) 00473 ); 00474 00475 ProbeForWrite( 00476 pIcaUserData->pIcaSlave, 00477 sizeof(VDMVIRTUALICA), 00478 sizeof(UCHAR) 00479 ); 00480 00481 ProbeForWriteUlong(pIcaUserData->pIretHooked); 00482 ProbeForWriteUlong(pIcaUserData->pDelayIrq); 00483 ProbeForWriteUlong(pIcaUserData->pUndelayIrq); 00484 ProbeForWriteUlong(pIcaUserData->pDelayIret); 00485 00486 00487 // 00488 // Save pointer to main thread, for delayed interrupts DPC routine. 00489 // To keep the pointer to the main thread valid, open a thread handle 00490 // and keep it open until process cleanup. 00491 // 00492 00493 InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); 00494 Status = ZwOpenThread(&hThread, 00495 THREAD_QUERY_INFORMATION, 00496 &ObjectAttributes, 00497 &NtCurrentTeb()->ClientId 00498 ); 00499 00500 if (NT_SUCCESS(Status)) { 00501 pVdmObjects->MainThread = PsGetCurrentThread(); 00502 } 00503 00504 00505 pVdmObjects->VdmTib = VdmTib; 00506 } 00507 00508 } except(ExSystemExceptionFilter()) { 00509 Status = GetExceptionCode(); 00510 } 00511 00512 00513 if (!NT_SUCCESS(Status)) { 00514 if (pVdmObjects) { 00515 if (pVdmObjects->pIcaUserData) { 00516 ExFreePool(pVdmObjects->pIcaUserData); 00517 } 00518 ExFreePool(pVdmObjects); 00519 } 00520 Process->VdmObjects = NULL; 00521 00522 // 00523 // Return Quota charged 00524 // 00525 PsReturnPoolQuota(Process, NonPagedPool, NonPagedQuotaCharged); 00526 PsReturnPoolQuota(Process, PagedPool, PagedQuotaCharged); 00527 } 00528 00529 // 00530 // following codepath only for PC/AT (and FMR in Japan) vdm 00531 // 00532 00533 if ((KeI386MachineType & MACHINE_TYPE_PC_9800_COMPATIBLE) == 0) { 00534 00535 #ifdef WHEN_IO_DISPATCHING_IMPROVED 00536 // Sudeepb - Once we improve the IO dispatching we should use this 00537 // routine. Currently we are dispatching the printer ports directly 00538 // from emv86.asm and instemul.asm 00539 00540 VdmInitializePrinter (); 00541 #endif 00542 } 00543 00544 return Status; 00545 00546 } // end InitializeVDM() } // end InitializeVDM()

NTSTATUS VdmpIsThreadTerminating HANDLE  ThreadId  ) 
 

Definition at line 1922 of file vdmints.c.

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

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

NTSTATUS VdmpLeaveIcaLock IN PRTL_CRITICAL_SECTION  pIcaLock  ) 
 

Referenced by VdmDispatchInterrupts().

NTSTATUS VdmpPrinterDirectIoClose PVOID  ServiceData  ) 
 

Definition at line 388 of file vdmprint.c.

References EXCEPTION_EXECUTE_HANDLER, ExSystemExceptionFilter(), NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, ProbeForRead, ProbeForWrite(), Status, USHORT, and VdmFlushPrinterWriteData().

Referenced by NtVdmControl().

00389 { 00390 NTSTATUS Status; 00391 PVDM_PRINTER_INFO PrtInfo; 00392 USHORT Adapter; 00393 PVDM_TIB VdmTib; 00394 00395 PAGED_CODE(); 00396 00397 Status = STATUS_SUCCESS; 00398 00399 // first we fetch vdm tib and do some damage control in case 00400 // this is bad user-mode memory 00401 // PrtInfo points to a stricture 00402 00403 try { 00404 VdmTib = NtCurrentTeb()->Vdm; 00405 ProbeForWrite(VdmTib, sizeof(VDM_TIB), sizeof(UCHAR)); 00406 00407 // now verify that servicedata ptr is valid 00408 ProbeForRead(ServiceData, sizeof(USHORT), sizeof(UCHAR)); 00409 Adapter = *(USHORT *)ServiceData; 00410 00411 } except (ExSystemExceptionFilter()) { 00412 Status = GetExceptionCode(); 00413 } 00414 00415 if (NULL == VdmTib || NULL == ServiceData) { 00416 Status = STATUS_ACCESS_VIOLATION; 00417 } 00418 00419 if (!NT_SUCCESS(Status)) { 00420 return(Status); 00421 } 00422 00423 PrtInfo =&VdmTib->PrinterInfo; 00424 00425 try { 00426 if (Adapter < VDM_NUMBER_OF_LPT) { 00427 if (PRT_MODE_DIRECT_IO == PrtInfo->prt_Mode[Adapter] && 00428 PrtInfo->prt_BytesInBuffer[Adapter]) { 00429 Status = VdmFlushPrinterWriteData(Adapter); 00430 } 00431 } 00432 else { 00433 Status = STATUS_INVALID_PARAMETER; 00434 } 00435 } except (EXCEPTION_EXECUTE_HANDLER) { 00436 Status = GetExceptionCode(); 00437 } 00438 return Status; 00439 }

NTSTATUS VdmpPrinterDirectIoOpen PVOID  ServiceData  ) 
 

Definition at line 380 of file vdmprint.c.

References PAGED_CODE.

Referenced by NtVdmControl().

00381 { 00382 PAGED_CODE(); 00383 00384 return STATUS_SUCCESS; 00385 00386 }

NTSTATUS VdmpPrinterInitialize PVOID  ServiceData  ) 
 

Definition at line 295 of file vdmprint.c.

References EXCEPTION_EXECUTE_HANDLER, FALSE, NT_SUCCESS, NTSTATUS(), ProbeForWrite(), PsGetCurrentProcess, Status, VdmpGetVdmTib(), and VDMTIB_KMODE.

Referenced by NtVdmControl().

00300 : 00301 00302 This routine probes and caches the data associated with kernel 00303 mode printer emulation. 00304 00305 Arguments: 00306 00307 ServiceData - Not used. 00308 00309 Return Value: 00310 00311 00312 --*/ 00313 { 00314 PUCHAR State, PrtStatus, Control, HostState; 00315 PVDM_TIB VdmTib; 00316 PVDM_PROCESS_OBJECTS VdmObjects; 00317 NTSTATUS Status; 00318 00319 Status = STATUS_SUCCESS; 00320 00321 // 00322 // Note: We only support two printers in the kernel. 00323 // 00324 00325 Status = VdmpGetVdmTib(&VdmTib, VDMTIB_KMODE); 00326 if (!NT_SUCCESS(Status)) { 00327 return(FALSE); 00328 } 00329 00330 00331 try { 00332 State = VdmTib->PrinterInfo.prt_State; 00333 PrtStatus = VdmTib->PrinterInfo.prt_Status; 00334 Control = VdmTib->PrinterInfo.prt_Control; 00335 HostState = VdmTib->PrinterInfo.prt_HostState; 00336 00337 // 00338 // Probe the locations for two printers 00339 // 00340 ProbeForWrite( 00341 State, 00342 2 * sizeof(UCHAR), 00343 sizeof(UCHAR) 00344 ); 00345 00346 ProbeForWrite( 00347 PrtStatus, 00348 2 * sizeof(UCHAR), 00349 sizeof(UCHAR) 00350 ); 00351 00352 ProbeForWrite( 00353 Control, 00354 2 * sizeof(UCHAR), 00355 sizeof(UCHAR) 00356 ); 00357 00358 ProbeForWrite( 00359 HostState, 00360 2 * sizeof(UCHAR), 00361 sizeof(UCHAR) 00362 ); 00363 00364 } except (EXCEPTION_EXECUTE_HANDLER) { 00365 Status = GetExceptionCode(); 00366 } 00367 00368 if (NT_SUCCESS(Status)) { 00369 VdmObjects = PsGetCurrentProcess()->VdmObjects; 00370 VdmObjects->PrinterState = State; 00371 VdmObjects->PrinterStatus = PrtStatus; 00372 VdmObjects->PrinterControl = Control; 00373 VdmObjects->PrinterHostState = HostState; 00374 } 00375 00376 return Status; 00377 }

NTSTATUS VdmpQueueInterrupt IN HANDLE  ThreadHandle  ) 
 

Definition at line 146 of file vdmints.c.

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

Referenced by NtVdmControl().

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

BOOLEAN VdmPrinterStatus ULONG  iPort,
ULONG  cbInstructionSize,
PKTRAP_FRAME  TrapFrame
 

Definition at line 42 of file vdmprint.c.

References ASSERT, DbgPrint, EXCEPTION_EXECUTE_HANDLER, FALSE, get_control, get_status, HOST_LPT_BUSY, host_lpt_status, IRQ, KeLowerIrql(), KeRaiseIrql(), NOTBUSY, NT_SUCCESS, NtDeviceIoControlFile(), NTSTATUS(), NULL, PAGED_CODE, PASSIVE_LEVEL, set_status, Status, STATUS_PORT_OFFSET, STATUS_REG_MASK, USHORT, VdmFlushPrinterWriteData(), VdmpGetVdmTib(), and VDMTIB_KMODE.

00050 : 00051 00052 This routine handles the read operation on the printer status port 00053 00054 Arguments: 00055 iPort - port on which the io was trapped 00056 cbInstructionSize - Instruction size to update TsEip 00057 TrapFrame - Trap Frame 00058 00059 Return Value: 00060 00061 True if successfull, False otherwise 00062 00063 --*/ 00064 { 00065 UCHAR PrtMode; 00066 USHORT adapter; 00067 ULONG * printer_status; 00068 KIRQL OldIrql; 00069 PIO_STATUS_BLOCK IoStatusBlock; 00070 PVDM_PRINTER_INFO PrtInfo; 00071 PVDM_TIB VdmTib; 00072 NTSTATUS Status = STATUS_SUCCESS; 00073 00074 PAGED_CODE(); 00075 00076 // why we have printer stuff in TIB? It would be more appropriate 00077 // if we have them in the process object. The main reason(I think) 00078 // is that we can get rid of synchronization. 00079 // 00080 00081 Status = VdmpGetVdmTib(&VdmTib, VDMTIB_KMODE); 00082 if (!NT_SUCCESS(Status)) { 00083 return(FALSE); 00084 } 00085 00086 PrtInfo = &VdmTib->PrinterInfo; 00087 IoStatusBlock = (PIO_STATUS_BLOCK) &VdmTib->TempArea1; 00088 printer_status = &VdmTib->PrinterInfo.prt_Scratch; 00089 00090 *pNtVDMState |= VDM_IDLEACTIVITY; 00091 try { 00092 // first, figure out which PRT we are dealing with. The 00093 // port addresses in the PrinterInfo are base address of each 00094 // PRT sorted in the adapter order. 00095 00096 if ((USHORT)iPort == PrtInfo->prt_PortAddr[0] + STATUS_PORT_OFFSET) 00097 adapter = 0; 00098 else if ((USHORT)iPort == PrtInfo->prt_PortAddr[1] + STATUS_PORT_OFFSET) 00099 adapter = 1; 00100 else if ((USHORT)iPort == PrtInfo->prt_PortAddr[2] + STATUS_PORT_OFFSET) 00101 adapter = 2; 00102 else { 00103 // something must be wrong in our code, better check it out 00104 ASSERT(FALSE); 00105 return FALSE; 00106 } 00107 PrtMode = PrtInfo->prt_Mode[adapter]; 00108 00109 00110 if(PRT_MODE_SIMULATE_STATUS_PORT == PrtMode) { 00111 // we are simulating printer status read. 00112 // get the current status from softpc. 00113 if (!(get_status(adapter) & NOTBUSY) && 00114 !(host_lpt_status(adapter) & HOST_LPT_BUSY)) { 00115 if (get_control(adapter) & IRQ) 00116 return FALSE; 00117 set_status(adapter, get_status(adapter) | NOTBUSY); 00118 } 00119 *printer_status = (ULONG)(get_status(adapter) | STATUS_REG_MASK); 00120 } 00121 else if (PRT_MODE_DIRECT_IO == PrtMode) { 00122 // we have to read the i/o directly(of course, through file system 00123 // which in turn goes to the driver). 00124 // Before performing read, flush out all pending output data in our 00125 // buffer. This is done because the status we are about to read 00126 // may depend on those pending output data. 00127 // 00128 if (PrtInfo->prt_BytesInBuffer[adapter]) { 00129 Status = VdmFlushPrinterWriteData(adapter); 00130 #ifdef DBG 00131 if (!NT_SUCCESS(Status)) { 00132 DbgPrint("VdmPrintStatus: failed to flush buffered data, status = %ls\n", Status); 00133 } 00134 #endif 00135 } 00136 OldIrql = KeGetCurrentIrql(); 00137 // lower irql to passive before doing any IO 00138 KeLowerIrql(PASSIVE_LEVEL); 00139 Status = NtDeviceIoControlFile(PrtInfo->prt_Handle[adapter], 00140 NULL, // notification event 00141 NULL, // APC routine 00142 NULL, // Apc Context 00143 IoStatusBlock, 00144 IOCTL_VDM_PAR_READ_STATUS_PORT, 00145 NULL, 00146 0, 00147 printer_status, 00148 sizeof(ULONG) 00149 ); 00150 00151 if (!NT_SUCCESS(Status) || !NT_SUCCESS(IoStatusBlock->Status)) { 00152 // fake a status to make it looks like the port is not connected 00153 // to a printer. 00154 *printer_status = 0x7F; 00155 #ifdef DBG 00156 DbgPrint("VdmPrinterStatus: failed to get status from printer, status = %lx\n", Status); 00157 #endif 00158 // always tell the caller that we have simulated the operation. 00159 Status = STATUS_SUCCESS; 00160 } 00161 KeRaiseIrql(OldIrql, &OldIrql); 00162 } 00163 else 00164 // we don't simulate it here 00165 return FALSE; 00166 00167 TrapFrame->Eax &= 0xffffff00; 00168 TrapFrame->Eax |= (UCHAR)*printer_status; 00169 TrapFrame->Eip += cbInstructionSize; 00170 00171 } except(EXCEPTION_EXECUTE_HANDLER) { 00172 Status = GetExceptionCode(); 00173 } 00174 return (NT_SUCCESS(Status)); 00175 }

BOOLEAN VdmPrinterWriteData ULONG  iPort,
ULONG  cbInstructionSize,
PKTRAP_FRAME  TrapFrame
 

Definition at line 177 of file vdmprint.c.

References ASSERT, DATA_PORT_OFFSET, EXCEPTION_EXECUTE_HANDLER, FALSE, NT_SUCCESS, NTSTATUS(), PAGED_CODE, Status, USHORT, VdmFlushPrinterWriteData(), VdmpGetVdmTib(), and VDMTIB_KMODE.

00182 { 00183 UCHAR PrtMode; 00184 PVDM_PRINTER_INFO PrtInfo; 00185 USHORT adapter; 00186 PVDM_TIB VdmTib; 00187 NTSTATUS Status = STATUS_SUCCESS; 00188 00189 PAGED_CODE(); 00190 00191 Status = VdmpGetVdmTib(&VdmTib, VDMTIB_KMODE); 00192 if (!NT_SUCCESS(Status)) { 00193 return(FALSE); 00194 } 00195 00196 PrtInfo = &VdmTib->PrinterInfo; 00197 *pNtVDMState |= VDM_IDLEACTIVITY; 00198 00199 try { 00200 // first, figure out which PRT we are dealing with. The 00201 // port addresses in the PrinterInfo are base address of each 00202 // PRT sorted in the adapter order 00203 if ((USHORT)iPort == PrtInfo->prt_PortAddr[0] + DATA_PORT_OFFSET) 00204 adapter = 0; 00205 else if ((USHORT)iPort == PrtInfo->prt_PortAddr[1] + DATA_PORT_OFFSET) 00206 adapter = 1; 00207 else if ((USHORT)iPort == PrtInfo->prt_PortAddr[2] + DATA_PORT_OFFSET) 00208 adapter = 2; 00209 else { 00210 // something must be wrong in our code, better check it out 00211 ASSERT(FALSE); 00212 return FALSE; 00213 } 00214 if (PRT_MODE_DIRECT_IO == PrtInfo->prt_Mode[adapter]){ 00215 PrtInfo->prt_Buffer[adapter][PrtInfo->prt_BytesInBuffer[adapter]] = (UCHAR)TrapFrame->Eax; 00216 // buffer full, then flush it out 00217 if (++PrtInfo->prt_BytesInBuffer[adapter] >= PRT_DATA_BUFFER_SIZE){ 00218 00219 VdmFlushPrinterWriteData(adapter); 00220 } 00221 00222 TrapFrame->Eip += cbInstructionSize; 00223 00224 } 00225 else 00226 Status = STATUS_ILLEGAL_INSTRUCTION; 00227 } except(EXCEPTION_EXECUTE_HANDLER) { 00228 Status = GetExceptionCode(); 00229 } 00230 return(NT_SUCCESS(Status)); 00231 00232 }

NTSTATUS VdmpStartExecution VOID   ) 
 

Definition at line 40 of file strtexec.c.

References APC_LEVEL, ASSERT, _VdmEventInfo::Event, _Vdm_Tib::EventInfo, EXCEPTION_EXECUTE_HANDLER, FALSE, _VdmEventInfo::InstructionSize, KeI386VdmIoplAllowed, KeI386VirtualIntExtensions, KeLowerIrql(), KeRaiseIrql(), _Vdm_Tib::MonitorContext, NT_SUCCESS, NTSTATUS(), PAGED_CODE, PsGetCurrentThread, Status, _ETHREAD::Tcb, TRUE, VDM_VIRTUAL_INTERRUPTS, _Vdm_Tib::VdmContext, VdmDispatchInterrupts(), VdmFixedStateLinear, VdmIntAck, VdmpGetVdmTib(), VdmSwapContexts(), and VDMTIB_KMODE.

Referenced by NtVdmControl().

00045 : 00046 00047 This routine causes execution of dos application code to begin. The 00048 Dos application executes on the thread. The Vdms context is loaded 00049 from the VDM_TIB for the thread. The 32 bit context is stored into 00050 the MonitorContext. Execution in the VDM context will continue until 00051 an event occurs that the monitor needs to service. At that point, 00052 the information will be put into the VDM_TIB, and the call will 00053 return. 00054 00055 Arguments: 00056 00057 Return Value: 00058 00059 TrapFrame->Eax for application mode, required for system sevices 00060 exit. 00061 00062 00063 --*/ 00064 { 00065 PVDM_TIB VdmTib; 00066 PKTRAP_FRAME TrapFrame; 00067 PETHREAD Thread; 00068 KIRQL OldIrql; 00069 BOOLEAN IntsEnabled; 00070 PVDM_PROCESS_OBJECTS pProcessObjects; 00071 NTSTATUS Status; 00072 CONTEXT VdmContext; 00073 00074 PAGED_CODE(); 00075 00076 00077 KeRaiseIrql(APC_LEVEL, &OldIrql); 00078 00079 // 00080 // Form a pointer to the trap frame for the current thread 00081 // 00082 Thread = PsGetCurrentThread(); 00083 TrapFrame = VdmGetTrapFrame(&Thread->Tcb); 00084 00085 00086 // 00087 // Get the VdmTib 00088 // 00089 00090 Status = VdmpGetVdmTib(&VdmTib, VDMTIB_KMODE); 00091 if (!NT_SUCCESS(Status)) { 00092 KeLowerIrql(OldIrql); 00093 return(STATUS_INVALID_SYSTEM_SERVICE); 00094 } 00095 00096 try { 00097 00098 // 00099 // Determine if interrupts are on or off 00100 // 00101 IntsEnabled = VdmTib->VdmContext.EFlags & EFLAGS_INTERRUPT_MASK 00102 ? TRUE : FALSE; 00103 00104 // 00105 // check for timer ints to dispatch, However if interrupts are disabled 00106 // or there are hardware ints pending we postpone dispatching the timer 00107 // interrupt until interrupts are enabled. 00108 // 00109 if (*pNtVDMState & VDM_INT_TIMER && 00110 IntsEnabled && !(*pNtVDMState & VDM_INT_HARDWARE)) 00111 { 00112 VdmTib->EventInfo.Event = VdmIntAck; 00113 VdmTib->EventInfo.InstructionSize = 0; 00114 VdmTib->EventInfo.IntAckInfo = 0; 00115 KeLowerIrql(OldIrql); 00116 return STATUS_SUCCESS; 00117 } 00118 00119 // 00120 // Perform IF to VIF translation 00121 // 00122 00123 // 00124 // If the processor supports IF virtualization 00125 // 00126 if (((KeI386VirtualIntExtensions & V86_VIRTUAL_INT_EXTENSIONS) && 00127 (VdmTib->VdmContext.EFlags & EFLAGS_V86_MASK)) || 00128 ((KeI386VirtualIntExtensions & PM_VIRTUAL_INT_EXTENSIONS) && 00129 !(VdmTib->VdmContext.EFlags & EFLAGS_V86_MASK))) 00130 { 00131 // 00132 // Translate IF to VIF 00133 // 00134 00135 if (IntsEnabled) { 00136 VdmTib->VdmContext.EFlags |= EFLAGS_VIF; 00137 00138 } else { 00139 VdmTib->VdmContext.EFlags &= ~EFLAGS_VIF; 00140 VdmTib->VdmContext.EFlags |= EFLAGS_INTERRUPT_MASK; 00141 } 00142 00143 if (*pNtVDMState & VDM_INT_HARDWARE) 00144 VdmTib->VdmContext.EFlags |= EFLAGS_VIP; 00145 else 00146 VdmTib->VdmContext.EFlags &= ~EFLAGS_VIP; 00147 00148 00149 // 00150 // Else if we are not running in v86 mode, or not using IOPL in 00151 // v86 mode 00152 // 00153 } else if (!(KeI386VdmIoplAllowed) || 00154 !(VdmTib->VdmContext.EFlags & EFLAGS_V86_MASK)) 00155 { 00156 // 00157 // Translate the real interrupt flag in the VdmContext to the virtual 00158 // interrupt flag in the VdmTib, and force real interrupts enabled. 00159 // 00160 00161 ASSERT(VDM_VIRTUAL_INTERRUPTS == EFLAGS_INTERRUPT_MASK); 00162 00163 if (VdmTib->VdmContext.EFlags & EFLAGS_INTERRUPT_MASK) { 00164 _asm { 00165 00166 mov eax,VdmFixedStateLinear ; get pointer to VDM State 00167 lock or dword ptr [eax], dword ptr VDM_VIRTUAL_INTERRUPTS 00168 } 00169 } else { 00170 _asm { 00171 00172 mov eax,VdmFixedStateLinear ; get pointer to VDM State 00173 lock and dword ptr [eax], NOT VDM_VIRTUAL_INTERRUPTS 00174 } 00175 } 00176 00177 // 00178 // Insure that real interrupts are always enabled. 00179 // 00180 VdmTib->VdmContext.EFlags |= EFLAGS_INTERRUPT_MASK; 00181 } 00182 00183 // before working on a trap frame, make sure that it's our own structure 00184 // 00185 00186 VdmContext = VdmTib->VdmContext; 00187 if (!(VdmContext.SegCs & FRAME_EDITED)) { 00188 // we will crash in KiServiceExit 00189 KeLowerIrql(OldIrql); 00190 return(STATUS_INVALID_SYSTEM_SERVICE); 00191 } 00192 00193 // 00194 // Switch from MonitorContext to VdmContext 00195 // 00196 00197 VdmSwapContexts( 00198 TrapFrame, 00199 &(VdmTib->MonitorContext), 00200 &VdmContext 00201 ); 00202 00203 00204 // 00205 // Check for pending interrupts 00206 // 00207 if (IntsEnabled && (*pNtVDMState & VDM_INT_HARDWARE)) { 00208 VdmDispatchInterrupts(TrapFrame, VdmTib); 00209 } 00210 00211 } 00212 except(EXCEPTION_EXECUTE_HANDLER) { 00213 Status = GetExceptionCode(); 00214 KeLowerIrql(OldIrql); 00215 return(Status); 00216 } 00217 00218 KeLowerIrql(OldIrql); 00219 00220 return (NTSTATUS) TrapFrame->Eax; 00221 }

VOID VdmSwapContexts IN PKTRAP_FRAME  TrapFrame,
IN PCONTEXT  InContext,
IN PCONTEXT  OutContext
 

Referenced by VdmEndExecution(), and VdmpStartExecution().

VOID VdmTraceEvent USHORT  Type,
USHORT  wData,
USHORT  lData,
PKTRAP_FRAME  TrapFrame
 

Definition at line 37 of file vdmtrace.c.

References APC_LEVEL, EXCEPTION_EXECUTE_HANDLER, _Vdm_Tib::Flags, KeLowerIrql(), KeRaiseIrql(), NtGetTickCount(), NTSTATUS(), PAGED_CODE, Status, and USHORT.

00046 : 00047 00048 00049 00050 Arguments: 00051 00052 Return Value: 00053 00054 None 00055 00056 --*/ 00057 { 00058 PVDM_TIB VdmTib; 00059 NTSTATUS Status = STATUS_SUCCESS; 00060 KIRQL OldIrql; 00061 PVDM_TRACEENTRY pEntry; 00062 PVDM_TRACEINFO pInfo; 00063 LARGE_INTEGER CurTime, DiffTime; 00064 00065 00066 PAGED_CODE(); 00067 #if 0 00068 // This code represents a security problem. Since it is only used 00069 // on special occasions, it won't be built into the standard build. 00070 // Individuals wishing to use it can build themselves a kernel with 00071 // it in. 00072 #if 0 00073 // 00074 // Raise Irql to APC level... 00075 // 00076 KeRaiseIrql(APC_LEVEL, &OldIrql); 00077 00078 // 00079 // VdmTib is in user mode memory 00080 // 00081 try { 00082 #endif 00083 if ((*(ULONG *)(FIXED_NTVDMSTATE_LINEAR) & VDM_TRACE_HISTORY)) { 00084 00085 // 00086 // Get a pointer to the VdmTib 00087 // 00088 VdmTib = NtCurrentTeb()->Vdm; 00089 00090 if (VdmTib->TraceInfo.pTraceTable) { 00091 00092 pEntry = &VdmTib->TraceInfo.pTraceTable[VdmTib->TraceInfo.CurrentEntry]; 00093 00094 pEntry->Type = Type; 00095 pEntry->wData = wData; 00096 pEntry->lData = lData; 00097 00098 switch (VdmTib->TraceInfo.Flags & VDMTI_TIMER_MODE) { 00099 case VDMTI_TIMER_TICK: 00100 CurTime.LowPart = NtGetTickCount(); 00101 pEntry->Time = CurTime.LowPart - VdmTib->TraceInfo.TimeStamp.LowPart; 00102 VdmTib->TraceInfo.TimeStamp.LowPart = CurTime.LowPart; 00103 break; 00104 00105 case VDMTI_TIMER_PERFCTR: 00106 pEntry->Time = 0; 00107 break; 00108 00109 case VDMTI_TIMER_STAT: 00110 pEntry->Time = 0; 00111 break; 00112 00113 } 00114 00115 pEntry->eax = TrapFrame->Eax; 00116 pEntry->ebx = TrapFrame->Ebx; 00117 pEntry->ecx = TrapFrame->Ecx; 00118 pEntry->edx = TrapFrame->Edx; 00119 pEntry->esi = TrapFrame->Esi; 00120 pEntry->edi = TrapFrame->Edi; 00121 pEntry->ebp = TrapFrame->Ebp; 00122 pEntry->esp = TrapFrame->HardwareEsp; 00123 pEntry->eip = TrapFrame->Eip; 00124 pEntry->eflags = TrapFrame->EFlags; 00125 00126 pEntry->cs = (USHORT) TrapFrame->SegCs; 00127 pEntry->ds = (USHORT) TrapFrame->SegDs; 00128 pEntry->es = (USHORT) TrapFrame->SegEs; 00129 pEntry->fs = (USHORT) TrapFrame->SegFs; 00130 pEntry->gs = (USHORT) TrapFrame->SegGs; 00131 pEntry->ss = (USHORT) TrapFrame->HardwareSegSs; 00132 00133 if (++VdmTib->TraceInfo.CurrentEntry >= 00134 (VdmTib->TraceInfo.NumPages*4096/sizeof(VDM_TRACEENTRY))) { 00135 VdmTib->TraceInfo.CurrentEntry = 0; 00136 } 00137 } 00138 } 00139 00140 #if 0 00141 } except(EXCEPTION_EXECUTE_HANDLER) { 00142 Status = GetExceptionCode(); 00143 } 00144 00145 KeLowerIrql(OldIrql); 00146 #endif 00147 #endif 00148 } }


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