NTSTATUS CreateDllSection(IN IN PUNICODE_STRING pDllName, OUT PHANDLE pSection, OUT PPVOID pBaseAddress) { HANDLE hFile; OBJECT_ATTRIBUTES oa = {sizeof oa, 0, pDllName, OBJ_CASE_INSENSITIVE}; IO_STATUS_BLOCK iosb; SIZE_T size=0; NTSTATUS status; PAGED_CODE(); ASSERT(pSection&&pBaseAddress); *pBaseAddress = NULL; status = ZwOpenFile(&hFile, FILE_EXECUTE | SYNCHRONIZE, &oa, &iosb, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT); if (NT_SUCCESS(status)) { oa.ObjectName = 0; status = ZwCreateSection(pSection, SECTION_ALL_ACCESS, &oa, 0,PAGE_EXECUTE, SEC_IMAGE, hFile); if (NT_SUCCESS(status)) { status = ZwMapViewOfSection(*pSection, ZwCurrentProcess(), pBaseAddress, 0, 1000, 0, &size, (SECTION_INHERIT)1, MEM_TOP_DOWN, PAGE_READWRITE); if (!NT_SUCCESS(status)) { ZwClose(*pSection); } } ZwClose(hFile); } return status; }
PVOID NTAPI EngMapSectionView( _In_ HANDLE hSection, _In_ SIZE_T cjSize, _In_ ULONG cjOffset, _Out_ PHANDLE phSecure) { LARGE_INTEGER liSectionOffset; PVOID pvBaseAddress; NTSTATUS Status; /* Check if the size is ok (for 64 bit) */ if (cjSize > ULONG_MAX) { DPRINT1("chSize out of range: 0x%Id\n", cjSize); return NULL; } /* Align the offset at allocation granularity and compensate for the size */ liSectionOffset.QuadPart = cjOffset & ~(MM_ALLOCATION_GRANULARITY - 1); cjSize += cjOffset & (MM_ALLOCATION_GRANULARITY - 1); /* Map the section */ Status = ZwMapViewOfSection(hSection, NtCurrentProcess(), &pvBaseAddress, 0, cjSize, &liSectionOffset, &cjSize, ViewShare, 0, PAGE_READWRITE); if (!NT_SUCCESS(Status)) { DPRINT1("ZwMapViewOfSection failed (0x%lx)\n", Status); return NULL; } /* Secure the section memory */ *phSecure = EngSecureMem(pvBaseAddress, (ULONG)cjSize); if (!*phSecure) { ZwUnmapViewOfSection(NtCurrentProcess(), pvBaseAddress); return NULL; } /* Return the address where the requested data starts */ return (PUCHAR)pvBaseAddress + (cjOffset & (MM_ALLOCATION_GRANULARITY - 1)); }
NTSTATUS NTAPI IntInitializeVideoAddressSpace(VOID) { OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING PhysMemName = RTL_CONSTANT_STRING(L"\\Device\\PhysicalMemory"); NTSTATUS Status; HANDLE PhysMemHandle; PVOID BaseAddress; LARGE_INTEGER Offset; SIZE_T ViewSize; CHAR IVTAndBda[1024+256]; /* Free the 1MB pre-reserved region. In reality, ReactOS should simply support us mapping the view into the reserved area, but it doesn't. */ BaseAddress = 0; ViewSize = 1024 * 1024; Status = ZwFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &ViewSize, MEM_RELEASE); if (!NT_SUCCESS(Status)) { DPRINT1("Couldn't unmap reserved memory (%x)\n", Status); return 0; } /* Open the physical memory section */ InitializeObjectAttributes(&ObjectAttributes, &PhysMemName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); Status = ZwOpenSection(&PhysMemHandle, SECTION_ALL_ACCESS, &ObjectAttributes); if (!NT_SUCCESS(Status)) { DPRINT1("Couldn't open \\Device\\PhysicalMemory\n"); return Status; } /* Map the BIOS and device registers into the address space */ Offset.QuadPart = 0xa0000; ViewSize = 0x100000 - 0xa0000; BaseAddress = (PVOID)0xa0000; Status = ZwMapViewOfSection(PhysMemHandle, NtCurrentProcess(), &BaseAddress, 0, ViewSize, &Offset, &ViewSize, ViewUnmap, 0, PAGE_EXECUTE_READWRITE); if (!NT_SUCCESS(Status)) { DPRINT1("Couldn't map physical memory (%x)\n", Status); ZwClose(PhysMemHandle); return Status; } /* Close physical memory section handle */ ZwClose(PhysMemHandle); if (BaseAddress != (PVOID)0xa0000) { DPRINT1("Couldn't map physical memory at the right address (was %x)\n", BaseAddress); return STATUS_UNSUCCESSFUL; } /* Allocate some low memory to use for the non-BIOS * parts of the v86 mode address space */ BaseAddress = (PVOID)0x1; ViewSize = 0xa0000 - 0x1000; Status = ZwAllocateVirtualMemory(NtCurrentProcess(), &BaseAddress, 0, &ViewSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to allocate virtual memory (Status %x)\n", Status); return Status; } if (BaseAddress != (PVOID)0x0) { DPRINT1("Failed to allocate virtual memory at right address (was %x)\n", BaseAddress); return 0; } /* Get the real mode IVT and BDA from the kernel */ Status = NtVdmControl(VdmInitialize, IVTAndBda); if (!NT_SUCCESS(Status)) { DPRINT1("NtVdmControl failed (status %x)\n", Status); return Status; } /* Return success */ return STATUS_SUCCESS; }
NTSTATUS MapPhysicalMemoryToLinearSpace(PVOID pPhysAddress, ULONG PhysMemSizeInBytes, PVOID *ppPhysMemLin, HANDLE *pPhysicalMemoryHandle) { UNICODE_STRING PhysicalMemoryUnicodeString; PVOID PhysicalMemorySection = NULL; OBJECT_ATTRIBUTES ObjectAttributes; PHYSICAL_ADDRESS ViewBase; NTSTATUS ntStatus; PHYSICAL_ADDRESS pStartPhysAddress; PHYSICAL_ADDRESS pEndPhysAddress; PHYSICAL_ADDRESS MappingLength; BOOLEAN Result1, Result2; ULONG IsIOSpace; unsigned char *pbPhysMemLin = NULL; OutputDebugString ("Entering MapPhysicalMemoryToLinearSpace"); RtlInitUnicodeString (&PhysicalMemoryUnicodeString, L"\\Device\\PhysicalMemory"); InitializeObjectAttributes (&ObjectAttributes, &PhysicalMemoryUnicodeString, OBJ_CASE_INSENSITIVE, (HANDLE) NULL, (PSECURITY_DESCRIPTOR) NULL); *pPhysicalMemoryHandle = NULL; ntStatus = ZwOpenSection (pPhysicalMemoryHandle, SECTION_ALL_ACCESS, &ObjectAttributes); if (NT_SUCCESS(ntStatus)) { ntStatus = ObReferenceObjectByHandle (*pPhysicalMemoryHandle, SECTION_ALL_ACCESS, (POBJECT_TYPE) NULL, KernelMode, &PhysicalMemorySection, (POBJECT_HANDLE_INFORMATION) NULL); if (NT_SUCCESS(ntStatus)) { pStartPhysAddress.QuadPart = (ULONGLONG)pPhysAddress; pEndPhysAddress = RtlLargeIntegerAdd (pStartPhysAddress, RtlConvertUlongToLargeInteger(PhysMemSizeInBytes)); IsIOSpace = 0; Result1 = HalTranslateBusAddress (1, 0, pStartPhysAddress, &IsIOSpace, &pStartPhysAddress); IsIOSpace = 0; Result2 = HalTranslateBusAddress (1, 0, pEndPhysAddress, &IsIOSpace, &pEndPhysAddress); if (Result1 && Result2) { MappingLength = RtlLargeIntegerSubtract (pEndPhysAddress, pStartPhysAddress); if (MappingLength.LowPart) { // Let ZwMapViewOfSection pick a linear address PhysMemSizeInBytes = MappingLength.LowPart; ViewBase = pStartPhysAddress; ntStatus = ZwMapViewOfSection (*pPhysicalMemoryHandle, (HANDLE) -1, &pbPhysMemLin, 0L, PhysMemSizeInBytes, &ViewBase, &PhysMemSizeInBytes, ViewShare, 0, PAGE_READWRITE | PAGE_NOCACHE); if (!NT_SUCCESS(ntStatus)) OutputDebugString ("ERROR: ZwMapViewOfSection failed"); else { pbPhysMemLin += (ULONG)pStartPhysAddress.LowPart - (ULONG)ViewBase.LowPart; *ppPhysMemLin = pbPhysMemLin; } } else OutputDebugString ("ERROR: RtlLargeIntegerSubtract failed"); } else OutputDebugString ("ERROR: MappingLength = 0"); } else OutputDebugString ("ERROR: ObReferenceObjectByHandle failed"); } else OutputDebugString ("ERROR: ZwOpenSection failed"); if (!NT_SUCCESS(ntStatus)) ZwClose(*pPhysicalMemoryHandle); OutputDebugString ("Leaving MapPhysicalMemoryToLinearSpace"); return ntStatus; }
BOOL ShareMemKImp::InitializeShareMem(HANDLE hFile, LPSECURITY_ATTRIBUTES lpAttributes, DWORD flProtect, DWORD dwMaximumSize, LPCWSTR lpName, DWORD dwDesiredAccess, ShareMemClassInit* lpInitialization, void* lpUserContext) { UninitializeShareMem(); DWORD size; size = dwMaximumSize + sizeof(ShareMemHeader); if (size < dwMaximumSize) return FALSE; UNICODE_STRING us; RtlInitUnicodeString(&us, lpName); OBJECT_ATTRIBUTES attr; InitializeObjectAttributes(&attr, &us, OBJ_OPENIF, NULL, NULL); LARGE_INTEGER li; li.QuadPart = size; NTSTATUS status; status = ZwCreateSection(&m_hMapSect, READ_CONTROL|WRITE_DAC|dwDesiredAccess, &attr, &li, flProtect, SEC_COMMIT, hFile); BOOLEAN init; init = status != STATUS_SUCCESS ? FALSE : TRUE; if (m_hMapSect) { SIZE_T v_size; v_size = 0; status = ZwMapViewOfSection(m_hMapSect, ZwCurrentProcess(), &m_hMapView, 0, size, NULL, &v_size, ViewUnmap, 0, PAGE_READWRITE); if (m_hMapView) { m_hMapSize = dwMaximumSize; ShareMemHeader* smh; smh = (ShareMemHeader*)m_hMapView; if (init) { LARGE_INTEGER tick; KeQueryTickCount(&tick); RtlStringCchPrintfW(smh->m_LockName, sizeof(smh->m_LockName), L"K-%08x-%08x-%08x", PsGetCurrentProcessId(), PsGetCurrentThreadId(), tick.LowPart); if (lpInitialization) smh->m_bResult = lpInitialization(this, lpUserContext); else smh->m_bResult = TRUE; smh->m_bInitialized = TRUE; } else while(1) if (smh->m_bInitialized) break; return smh->m_bResult; } } return FALSE; }
static VOID TestPhysicalMemorySection(VOID) { NTSTATUS Status; UNICODE_STRING SectionName = RTL_CONSTANT_STRING(L"\\Device\\PhysicalMemory"); OBJECT_ATTRIBUTES ObjectAttributes; HANDLE SectionHandle; PVOID SectionObject; PUCHAR MyPage; PHYSICAL_ADDRESS MyPagePhysical; PUCHAR ZeroPageContents; PHYSICAL_ADDRESS ZeroPagePhysical; PVOID Mapping; PUCHAR MappingBytes; SIZE_T ViewSize; SIZE_T EqualBytes; MyPage = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, 'MPmK'); if (skip(MyPage != NULL, "Out of memory\n")) return; MyPagePhysical = MmGetPhysicalAddress(MyPage); RtlFillMemory(MyPage + 0 * PAGE_SIZE / 4, PAGE_SIZE / 4, 0x23); RtlFillMemory(MyPage + 1 * PAGE_SIZE / 4, PAGE_SIZE / 4, 0x67); RtlFillMemory(MyPage + 2 * PAGE_SIZE / 4, PAGE_SIZE / 4, 0xab); RtlFillMemory(MyPage + 3 * PAGE_SIZE / 4, PAGE_SIZE / 4, 0xef); ZeroPageContents = ExAllocatePoolWithTag(PagedPool, PAGE_SIZE, 'ZPmK'); if (skip(ZeroPageContents != NULL, "Out of memory\n")) { ExFreePoolWithTag(MyPage, 'MPmK'); return; } ZeroPagePhysical.QuadPart = 0; Mapping = MmMapIoSpace(ZeroPagePhysical, PAGE_SIZE, MmCached); if (skip(Mapping != NULL, "Failed to map zero page\n")) { ExFreePoolWithTag(ZeroPageContents, 'ZPmK'); ExFreePoolWithTag(MyPage, 'MPmK'); return; } RtlCopyMemory(ZeroPageContents, Mapping, PAGE_SIZE); MmUnmapIoSpace(Mapping, PAGE_SIZE); InitializeObjectAttributes(&ObjectAttributes, &SectionName, OBJ_KERNEL_HANDLE, NULL, NULL); Status = ZwOpenSection(&SectionHandle, SECTION_ALL_ACCESS, &ObjectAttributes); ok_eq_hex(Status, STATUS_SUCCESS); if (!skip(NT_SUCCESS(Status), "No section\n")) { /* Map zero page and compare */ Mapping = NULL; ViewSize = PAGE_SIZE; Status = ZwMapViewOfSection(SectionHandle, ZwCurrentProcess(), &Mapping, 0, 0, &ZeroPagePhysical, &ViewSize, ViewUnmap, 0, PAGE_READWRITE); ok_eq_hex(Status, STATUS_SUCCESS); if (!skip(NT_SUCCESS(Status), "No view\n")) { ok((LONG_PTR)Mapping > 0, "Mapping = %p\n", Mapping); EqualBytes = RtlCompareMemory(Mapping, ZeroPageContents, PAGE_SIZE); ok_eq_size(EqualBytes, PAGE_SIZE); Status = ZwUnmapViewOfSection(ZwCurrentProcess(), Mapping); ok_eq_hex(Status, STATUS_SUCCESS); } /* Map the zero page non-cached */ Mapping = NULL; ViewSize = PAGE_SIZE; Status = ZwMapViewOfSection(SectionHandle, ZwCurrentProcess(), &Mapping, 0, 0, &ZeroPagePhysical, &ViewSize, ViewUnmap, 0, PAGE_READWRITE | PAGE_NOCACHE); ok_eq_hex(Status, STATUS_SUCCESS); if (!skip(NT_SUCCESS(Status), "No view\n")) { ok((LONG_PTR)Mapping > 0, "Mapping = %p\n", Mapping); EqualBytes = RtlCompareMemory(Mapping, ZeroPageContents, PAGE_SIZE); ok_eq_size(EqualBytes, PAGE_SIZE); Status = ZwUnmapViewOfSection(ZwCurrentProcess(), Mapping); ok_eq_hex(Status, STATUS_SUCCESS); } /* Map our NP page, compare, and check that modifications are reflected */ Mapping = NULL; ViewSize = PAGE_SIZE; Status = ZwMapViewOfSection(SectionHandle, ZwCurrentProcess(), &Mapping, 0, 0, &MyPagePhysical, &ViewSize, ViewUnmap, 0, PAGE_READWRITE); ok_eq_hex(Status, STATUS_SUCCESS); if (!skip(NT_SUCCESS(Status), "No view\n")) { ok((LONG_PTR)Mapping > 0, "Mapping = %p\n", Mapping); EqualBytes = RtlCompareMemory(Mapping, MyPage, PAGE_SIZE); ok_eq_size(EqualBytes, PAGE_SIZE); MappingBytes = Mapping; ok(MappingBytes[5] == 0x23, "Mapping[5] = 0x%x\n", MappingBytes[5]); ok(MyPage[5] == 0x23, "MyPage[5] = 0x%x\n", MyPage[5]); MyPage[5] = 0x44; ok(MappingBytes[5] == 0x44, "Mapping[5] = 0x%x\n", MappingBytes[5]); ok(MyPage[5] == 0x44, "MyPage[5] = 0x%x\n", MyPage[5]); MappingBytes[5] = 0x88; ok(MappingBytes[5] == 0x88, "Mapping[5] = 0x%x\n", MappingBytes[5]); ok(MyPage[5] == 0x88, "MyPage[5] = 0x%x\n", MyPage[5]); Status = ZwUnmapViewOfSection(ZwCurrentProcess(), Mapping); ok_eq_hex(Status, STATUS_SUCCESS); } Status = ZwClose(SectionHandle); ok_eq_hex(Status, STATUS_SUCCESS); } /* Try flag 0x80000000, which ROS calls SEC_PHYSICALMEMORY */ InitializeObjectAttributes(&ObjectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL); Status = ZwCreateSection(&SectionHandle, SECTION_ALL_ACCESS, &ObjectAttributes, NULL, PAGE_READWRITE, 0x80000000, NULL); ok_eq_hex(Status, STATUS_INVALID_PARAMETER_6); if (NT_SUCCESS(Status)) ZwClose(SectionHandle); /* Assertion failure: AllocationAttributes & SEC_IMAGE | SEC_RESERVE | SEC_COMMIT */ if (!KmtIsCheckedBuild) { InitializeObjectAttributes(&ObjectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL); Status = MmCreateSection(&SectionObject, SECTION_ALL_ACCESS, &ObjectAttributes, NULL, PAGE_READWRITE, 0x80000000, NULL, NULL); ok_eq_hex(Status, STATUS_INVALID_PARAMETER_6); if (NT_SUCCESS(Status)) ObDereferenceObject(SectionObject); } InitializeObjectAttributes(&ObjectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL); Status = MmCreateSection(&SectionObject, SECTION_ALL_ACCESS, &ObjectAttributes, NULL, PAGE_READWRITE, SEC_RESERVE | 0x80000000, NULL, NULL); ok_eq_hex(Status, STATUS_INVALID_PARAMETER_6); if (NT_SUCCESS(Status)) ObDereferenceObject(SectionObject); ExFreePoolWithTag(ZeroPageContents, 'ZPmK'); ExFreePoolWithTag(MyPage, 'MPmK'); }
NTSTATUS NTAPI INIT_FUNCTION VdmpInitialize(PVOID ControlData) { OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING PhysMemName = RTL_CONSTANT_STRING(L"\\Device\\PhysicalMemory"); NTSTATUS Status; HANDLE PhysMemHandle; PVOID BaseAddress; volatile PVOID NullAddress = NULL; LARGE_INTEGER Offset; ULONG ViewSize; /* Open the physical memory section */ InitializeObjectAttributes(&ObjectAttributes, &PhysMemName, 0, NULL, NULL); Status = ZwOpenSection(&PhysMemHandle, SECTION_ALL_ACCESS, &ObjectAttributes); if (!NT_SUCCESS(Status)) { DPRINT1("Couldn't open \\Device\\PhysicalMemory\n"); return Status; } /* Map the BIOS and device registers into the address space */ Offset.QuadPart = 0; ViewSize = PAGE_SIZE; BaseAddress = 0; Status = ZwMapViewOfSection(PhysMemHandle, NtCurrentProcess(), &BaseAddress, 0, ViewSize, &Offset, &ViewSize, ViewUnmap, 0, PAGE_READWRITE); if (!NT_SUCCESS(Status)) { DPRINT1("Couldn't map physical memory (%x)\n", Status); ZwClose(PhysMemHandle); return Status; } /* Enter SEH */ _SEH2_TRY { /* Copy the first physical page into the first virtual page */ RtlMoveMemory(NullAddress, BaseAddress, ViewSize); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { /* Fail */ DPRINT1("Couldn't copy first page (%x)\n", Status); ZwClose(PhysMemHandle); ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress); _SEH2_YIELD(return _SEH2_GetExceptionCode()); } _SEH2_END; /* Close physical memory section handle */ ZwClose(PhysMemHandle); /* Unmap the section */ Status = ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress); if (!NT_SUCCESS(Status)) { DPRINT1("Couldn't unmap the section (%x)\n", Status); return Status; } return STATUS_SUCCESS; }
NTSTATUS VdmpInitialize( PVDMICAUSERDATA pIcaUserData ) /*++ Routine Description: Initialize the address space of a VDM. Arguments: None, Return Value: NTSTATUS. --*/ { NTSTATUS Status, StatusCopy; OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING SectionName; UNICODE_STRING WorkString; ULONG ViewSize; LARGE_INTEGER ViewBase; PVOID BaseAddress; PVOID destination; HANDLE SectionHandle, RegistryHandle; PEPROCESS Process; ULONG ResultLength; ULONG Index; PCM_FULL_RESOURCE_DESCRIPTOR ResourceDescriptor; PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResourceDescriptor; PKEY_VALUE_FULL_INFORMATION KeyValueBuffer; PCM_ROM_BLOCK BiosBlock; ULONG LastMappedAddress; PVDM_PROCESS_OBJECTS pVdmObjects = NULL; USHORT PagedQuotaCharged = 0; USHORT NonPagedQuotaCharged = 0; HANDLE hThread; PVDM_TIB VdmTib; PAGED_CODE(); Status = VdmpGetVdmTib(&VdmTib, VDMTIB_PROBE); // take from user mode and probe if (!NT_SUCCESS(Status)) { return Status; } if ((KeI386MachineType & MACHINE_TYPE_PC_9800_COMPATIBLE) == 0) { // // This is PC/AT (and FMR in Japan) VDM. // RtlInitUnicodeString( &SectionName, L"\\Device\\PhysicalMemory" ); InitializeObjectAttributes( &ObjectAttributes, &SectionName, OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE, (HANDLE) NULL, (PSECURITY_DESCRIPTOR) NULL ); Status = ZwOpenSection( &SectionHandle, SECTION_ALL_ACCESS, &ObjectAttributes ); if (!NT_SUCCESS(Status)) { return Status; } // // Copy the first page of memory into the VDM's address space // BaseAddress = 0; destination = 0; ViewSize = 0x1000; ViewBase.LowPart = 0; ViewBase.HighPart = 0; Status = ZwMapViewOfSection( SectionHandle, NtCurrentProcess(), &BaseAddress, 0, ViewSize, &ViewBase, &ViewSize, ViewUnmap, 0, PAGE_READWRITE ); if (!NT_SUCCESS(Status)) { ZwClose(SectionHandle); return Status; } // problem with this statement below -- // it could be a non-vdm process and copying memory to address 0 // should be guarded against StatusCopy = STATUS_SUCCESS; try { RtlMoveMemory( destination, BaseAddress, ViewSize ); } except(ExSystemExceptionFilter()) { StatusCopy = GetExceptionCode(); } Status = ZwUnmapViewOfSection( NtCurrentProcess(), BaseAddress ); if (!NT_SUCCESS(Status) || !NT_SUCCESS(StatusCopy)) { ZwClose(SectionHandle); return (NT_SUCCESS(Status) ? StatusCopy : Status); } // // Map Rom into address space // BaseAddress = (PVOID) 0x000C0000; ViewSize = 0x40000; ViewBase.LowPart = 0x000C0000; ViewBase.HighPart = 0; // // First unmap the reserved memory. This must be done here to prevent // the virtual memory in question from being consumed by some other // alloc vm call. // Status = ZwFreeVirtualMemory( NtCurrentProcess(), &BaseAddress, &ViewSize, MEM_RELEASE ); // N.B. This should probably take into account the fact that there are // a handfull of error conditions that are ok. (such as no memory to // release.) if (!NT_SUCCESS(Status)) { ZwClose(SectionHandle); return Status; } // // Set up and open KeyPath // InitializeObjectAttributes( &ObjectAttributes, &CmRegistryMachineHardwareDescriptionSystemName, OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE, (HANDLE)NULL, NULL ); Status = ZwOpenKey( &RegistryHandle, KEY_READ, &ObjectAttributes ); if (!NT_SUCCESS(Status)) { ZwClose(SectionHandle); return Status; } // // Allocate space for the data // KeyValueBuffer = ExAllocatePoolWithTag( PagedPool, KEY_VALUE_BUFFER_SIZE, ' MDV' ); if (KeyValueBuffer == NULL) { ZwClose(RegistryHandle); ZwClose(SectionHandle); return STATUS_NO_MEMORY; } // // Get the data for the rom information // RtlInitUnicodeString( &WorkString, L"Configuration Data" ); Status = ZwQueryValueKey( RegistryHandle, &WorkString, KeyValueFullInformation, KeyValueBuffer, KEY_VALUE_BUFFER_SIZE, &ResultLength ); if (!NT_SUCCESS(Status)) { ZwClose(RegistryHandle); ExFreePool(KeyValueBuffer); ZwClose(SectionHandle); return Status; } ResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR) ((PUCHAR) KeyValueBuffer + KeyValueBuffer->DataOffset); if ((KeyValueBuffer->DataLength < sizeof(CM_FULL_RESOURCE_DESCRIPTOR)) || (ResourceDescriptor->PartialResourceList.Count < 2) ) { ZwClose(RegistryHandle); ExFreePool(KeyValueBuffer); ZwClose(SectionHandle); // No rom blocks. return STATUS_SUCCESS; } PartialResourceDescriptor = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)ResourceDescriptor + sizeof(CM_FULL_RESOURCE_DESCRIPTOR) + ResourceDescriptor->PartialResourceList.PartialDescriptors[0] .u.DeviceSpecificData.DataSize); if (KeyValueBuffer->DataLength < ((PUCHAR)PartialResourceDescriptor - (PUCHAR)ResourceDescriptor + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) + sizeof(CM_ROM_BLOCK)) ) { ZwClose(RegistryHandle); ExFreePool(KeyValueBuffer); ZwClose(SectionHandle); return STATUS_ILL_FORMED_SERVICE_ENTRY; } BiosBlock = (PCM_ROM_BLOCK)((PUCHAR)PartialResourceDescriptor + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)); Index = PartialResourceDescriptor->u.DeviceSpecificData.DataSize / sizeof(CM_ROM_BLOCK); // // N.B. Rom blocks begin on 2K (not necessarily page) boundaries // They end on 512 byte boundaries. This means that we have // to keep track of the last page mapped, and round the next // Rom block up to the next page boundary if necessary. // LastMappedAddress = 0xC0000; while (Index) { #if 0 DbgPrint( "Bios Block, PhysAddr = %lx, size = %lx\n", BiosBlock->Address, BiosBlock->Size ); #endif if ((Index > 1) && ((BiosBlock->Address + BiosBlock->Size) == BiosBlock[1].Address) ) { // // Coalesce adjacent blocks // BiosBlock[1].Address = BiosBlock[0].Address; BiosBlock[1].Size += BiosBlock[0].Size; Index--; BiosBlock++; continue; } BaseAddress = (PVOID)(BiosBlock->Address); ViewSize = BiosBlock->Size; if ((ULONG)BaseAddress < LastMappedAddress) { if (ViewSize > (LastMappedAddress - (ULONG)BaseAddress)) { ViewSize = ViewSize - (LastMappedAddress - (ULONG)BaseAddress); BaseAddress = (PVOID)LastMappedAddress; } else { ViewSize = 0; } } ViewBase.LowPart = (ULONG)BaseAddress; if (ViewSize > 0) { Status = ZwMapViewOfSection( SectionHandle, NtCurrentProcess(), &BaseAddress, 0, ViewSize, &ViewBase, &ViewSize, ViewUnmap, MEM_DOS_LIM, PAGE_READWRITE ); if (!NT_SUCCESS(Status)) { break; } LastMappedAddress = (ULONG)BaseAddress + ViewSize; } Index--; BiosBlock++; } // // Free up the handles // ZwClose(SectionHandle); ZwClose(RegistryHandle); ExFreePool(KeyValueBuffer); } else {
int main() { unsigned long long segmnt; LARGE_INTEGER viewbase; size_t vaddress,maplen; WCHAR ppath[PATH_MAX]; NTSTATUS status; char tmp[64]; int fd; if (OpenPhysMem()) { fprintf(stderr,"Unable to open physical memory device\n"); return 1; } memset(&viewbase,0,sizeof(viewbase)); viewbase.QuadPart = (ULONGLONG)ROM_offset; maplen = ROM_size-1; vaddress = 0; status = ZwMapViewOfSection(mem_fd,(HANDLE)-1,(PVOID*)(&vaddress),0UL, ROM_size-1,&viewbase,(PDWORD)(&maplen),ViewShare,0,PAGE_READONLY); if (!NT_SUCCESS(status)) { fprintf(stderr,"Failed to map view of section for %08llx status=0x%08lx\n",viewbase.QuadPart,(unsigned long)status); return 1; } ROM = (unsigned char*)((size_t)vaddress); printf(HELLO); printf("Press ENTER to start\n"); waitforenter(); /* write it out */ for (segmnt=ROM_offset; segmnt < (ROM_offset+(unsigned long long)ROM_size); segmnt += (unsigned long long)ROM_blocksize) { while (freespace() < (66UL << 10UL)) { if (GetCurrentDirectoryW(sizeof(ppath),ppath) == 0) { fprintf(stderr,"Unable to get current directory\n"); return 1; } /* chdir() off the drive so that it is safe for the user to remove the * pen drive, floppy, etc. */ if (SetCurrentDirectoryW(L"C:\\"/*FIXME*/) == 0) { fprintf(stderr,"Unable to bail out to root\n"); return 1; } printf("Unmount and remove disk, move files off on another computer,\n"); printf("re-mount and re-insert and hit ENTER\n"); waitforenter(); /* assuming the user has reloaded the disk/flash drive/whatever and remounted * at the same point, jump back into the directory and try to resume our work */ if (SetCurrentDirectoryW(ppath) == 0) { fprintf(stderr,"Unable to reenter capture dir\n"); return 1; } } sprintf(tmp,CAPTURE_SPRINTF,segmnt); printf("Writing ... %s\n",tmp); fd = open(tmp,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,0644); if (fd < 0) { fprintf(stderr,"Unable to open file, %s\n",strerror(errno)); return 1; } if ((size_t)write(fd,ROM+segmnt-ROM_offset,ROM_blocksize) != ROM_blocksize) { fprintf(stderr,"Unable to write ROM block\n"); return 1; } close(fd); } ZwUnmapViewOfSection((HANDLE)-1,(PVOID)vaddress); ClosePhysMem(); return 0; }
/* * @implemented */ LPVOID NTAPI MapViewOfFileEx(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap, LPVOID lpBaseAddress) { NTSTATUS Status; LARGE_INTEGER SectionOffset; SIZE_T ViewSize; ULONG Protect; LPVOID ViewBase; /* Convert the offset */ SectionOffset.LowPart = dwFileOffsetLow; SectionOffset.HighPart = dwFileOffsetHigh; /* Save the size and base */ ViewBase = lpBaseAddress; ViewSize = dwNumberOfBytesToMap; /* Convert flags to NT Protection Attributes */ if (dwDesiredAccess & FILE_MAP_WRITE) { Protect = PAGE_READWRITE; } else if (dwDesiredAccess & FILE_MAP_READ) { Protect = PAGE_READONLY; } else if (dwDesiredAccess & FILE_MAP_COPY) { Protect = PAGE_WRITECOPY; } else { Protect = PAGE_NOACCESS; } /* Map the section */ Status = ZwMapViewOfSection(hFileMappingObject, NtCurrentProcess(), &ViewBase, 0, 0, &SectionOffset, &ViewSize, ViewShare, 0, Protect); if (!NT_SUCCESS(Status)) { /* We failed */ BaseSetLastNTError(Status); return NULL; } /* Return the base */ return ViewBase; }
VOID tgwinkEvtIoDeviceControl( _In_ WDFQUEUE Queue, _In_ WDFREQUEST Request, _In_ size_t OutputBufferLength, _In_ size_t InputBufferLength, _In_ ULONG IoControlCode ) { WDFMEMORY mem; NTSTATUS status; WDFDEVICE dev; PDEVICE_CONTEXT context; void *uBase = NULL; LARGE_INTEGER offset; size_t size; dev = WdfIoQueueGetDevice(Queue); context = DeviceGetContext(dev); switch (IoControlCode) { case IOCTL_TGWINK_SAY_HELLO: if (OutputBufferLength != 4) { WdfRequestComplete(Request, STATUS_BAD_DATA); break; } status = WdfRequestRetrieveOutputMemory(Request, &mem); if (!NT_SUCCESS(status)) { KdPrint("tgwinkEvtIoDeviceControl could not get request memory buffer, status 0x%x\n", status); WdfVerifierDbgBreakPoint(); WdfRequestComplete(Request, status); break; } *((DWORD32 *)(WdfMemoryGetBuffer(mem, NULL))) = 0x5a5aa5a5; WdfRequestComplete(Request, STATUS_SUCCESS); break; case IOCTL_TGWINK_MAP_BAR_0: if (sizeof(void *) > OutputBufferLength) { KdPrint("tgwinkEvtIoDeviceControl needs a larger buffer (%d > %d)!\n", sizeof(void *), OutputBufferLength); WdfRequestComplete(Request, STATUS_BUFFER_TOO_SMALL); break; } offset = context->bar[0].phyAddr; size = context->bar[0].length; status = ZwMapViewOfSection(context->hMemory, ZwCurrentProcess(), &uBase, 0, 0, &offset, &size, ViewUnmap, 0, PAGE_READWRITE); if (!NT_SUCCESS(status)) { KdPrint("tgwinkEvtIoDeviceControl could not map view of section, status "); switch (status) { case STATUS_CONFLICTING_ADDRESSES: KdPrint("STATUS_CONFLICTING_ADDRESSES\n"); break; case STATUS_INVALID_PAGE_PROTECTION: KdPrint("STATUS_INVALID_PAGE_PROTECTION\n"); break; case STATUS_SECTION_PROTECTION: KdPrint("STATUS_SECTION_PROTECTION\n"); break; default: KdPrint("0x % x\n", status); break; } WdfRequestComplete(Request, status); break; } status = WdfRequestRetrieveOutputMemory(Request, &mem); if (!NT_SUCCESS(status)) { KdPrint("tgwinkEvtIoDeviceControl could not get request memory buffer, status 0x%x\n", status); WdfVerifierDbgBreakPoint(); WdfRequestComplete(Request, status); break; } *((void **)(WdfMemoryGetBuffer(mem, NULL))) = uBase; WdfRequestComplete(Request, STATUS_SUCCESS); break; case IOCTL_TGWINK_READ_PHYS: { PVOID buf; ULONG_PTR page, ofs, vtgt = 0; SIZE_T vsz = 0; if (InputBufferLength != sizeof(PVOID)) { KdPrint("tgwinkEvtIoDeviceControl requires a %d-byte buffer for this ioctl (got %d)\n", sizeof(PVOID), OutputBufferLength); WdfRequestComplete(Request, STATUS_INSUFFICIENT_RESOURCES); break; } status = WdfRequestRetrieveInputBuffer(Request, sizeof(PVOID), &buf, NULL); if (!NT_SUCCESS(status)) { KdPrint("tgwinkEvtIoDeviceControl could not get request memory buffer, status 0x%x\n", status); WdfRequestComplete(Request, status); break; } ofs = *((ULONG_PTR *)buf); page = ofs & ~0xfff; vsz = OutputBufferLength + (page ^ ofs); buf = NULL; status = WdfRequestRetrieveOutputMemory(Request, &mem); if (!NT_SUCCESS(status)) { KdPrint("tgwinkEvtIoDeviceControl could not get request memory buffer, status 0x%x\n", status); WdfRequestComplete(Request, status); break; } status = ZwMapViewOfSection(context->hMemory, (HANDLE)-1, (PVOID *)&vtgt, 0, 0, (PLARGE_INTEGER)&page, &vsz, ViewUnmap, 0, PAGE_READONLY); if (!NT_SUCCESS(status)) { KdPrint("tgwinkEvtIoDeviceControl could not map view of physical memory section, status 0x%x\n", status); WdfRequestComplete(Request, status); break; } ofs -= page; status = WdfMemoryCopyFromBuffer(mem, 0, (PVOID)(vtgt + ofs), OutputBufferLength); if (!NT_SUCCESS(status)) { KdPrint("tgwinkEvtIoDeviceControl failed to copy data from memory to buffer, status 0x%x\n", status); WdfRequestComplete(Request, status); break; } status = ZwUnmapViewOfSection((HANDLE)-1, (PVOID)vtgt); if (!NT_SUCCESS(status)) { KdPrint("tgwinkEvtIoDeviceControl failed to unmap view of physical memory section, status 0x%x\n", status); WdfRequestComplete(Request, status); break; } WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, OutputBufferLength); } break; case IOCTL_TGWINK_PEND_INTR: { WdfWaitLockAcquire(context->nnLock, NULL); if (context->notifyNext) { PINTERRUPT_CONTEXT pCtx = InterruptGetContext(context->hIrq); status = WdfRequestRetrieveOutputMemory(Request, &mem); if (!NT_SUCCESS(status)) { KdPrint("tgwinkEvtIoDeviceControl failed to retrieve output memory, status 0x%x\n", status); WdfRequestComplete(Request, status); } status = WdfMemoryCopyFromBuffer(mem, 0, &pCtx->serial, 8); if (!NT_SUCCESS(status)) { KdPrint("tgwinkEvtIoDeviceControl failed to copy interrupt number to buffer, status 0x%x\n", status); WdfRequestComplete(Request, status); } WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, 8); context->notifyNext = 0; KdPrint("tgwinkEvtIoDeviceControl satisfied interrupt notification request synchronously.\n"); //WdfInterruptEnable(context->hIrq); } else { KdPrint("tgwinkEvtIoDeviceControl forwarding PEND_INTR request to notification queue\n"); WdfRequestForwardToIoQueue(Request, context->NotificationQueue); } WdfWaitLockRelease(context->nnLock); } break; default: WdfRequestComplete(Request, STATUS_UNSUCCESSFUL); } }