test: vdminit.c File Reference

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