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

vdminit.c File Reference

#include <ntos.h>
#include <zwapi.h>
#include <ntconfig.h>
#include "vdmp.h"

Go to the source code of this file.

Defines

#define KEY_VALUE_BUFFER_SIZE   1024

Functions

NTSTATUS VdmpInitialize (PVDMICAUSERDATA pIcaUserData)


Define Documentation

#define KEY_VALUE_BUFFER_SIZE   1024
 

Definition at line 11 of file vdminit.c.

Referenced by VdmpInitialize().


Function Documentation

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()


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