static VOID LDEVOBJ_vUnloadImage( _Inout_ PLDEVOBJ pldev) { NTSTATUS Status; /* Make sure we have a driver info */ ASSERT(pldev && pldev->pGdiDriverInfo != NULL); /* Check if we have loaded a driver */ if (pldev->pfn.DisableDriver) { /* Call the unload function */ pldev->pfn.DisableDriver(); } /* Unload the driver */ Status = ZwSetSystemInformation(SystemUnloadGdiDriverInformation, &pldev->pGdiDriverInfo->SectionPointer, sizeof(HANDLE)); if (!NT_SUCCESS(Status)) { ERR("Failed to unload the driver, this is bad.\n"); } /* Free the driver info structure */ ExFreePoolWithTag(pldev->pGdiDriverInfo, GDITAG_LDEV); pldev->pGdiDriverInfo = NULL; }
static BOOL LDEVOBJ_bLoadImage( _Inout_ PLDEVOBJ pldev, _In_ PUNICODE_STRING pustrPathName) { PSYSTEM_GDI_DRIVER_INFORMATION pDriverInfo; NTSTATUS Status; ULONG cbSize; /* Make sure no image is loaded yet */ ASSERT(pldev && pldev->pGdiDriverInfo == NULL); /* Allocate a SYSTEM_GDI_DRIVER_INFORMATION structure */ cbSize = sizeof(SYSTEM_GDI_DRIVER_INFORMATION) + pustrPathName->Length; pDriverInfo = ExAllocatePoolWithTag(PagedPool, cbSize, GDITAG_LDEV); if (!pDriverInfo) { ERR("Failed to allocate SYSTEM_GDI_DRIVER_INFORMATION\n"); return FALSE; } /* Initialize the UNICODE_STRING and copy the driver name */ RtlInitEmptyUnicodeString(&pDriverInfo->DriverName, (PWSTR)(pDriverInfo + 1), pustrPathName->Length); RtlCopyUnicodeString(&pDriverInfo->DriverName, pustrPathName); /* Try to load the driver */ Status = ZwSetSystemInformation(SystemLoadGdiDriverInformation, pDriverInfo, sizeof(SYSTEM_GDI_DRIVER_INFORMATION)); if (!NT_SUCCESS(Status)) { ERR("Failed to load a GDI driver: '%wZ', Status = 0x%lx\n", pustrPathName, Status); /* Free the allocated memory */ ExFreePoolWithTag(pDriverInfo, GDITAG_LDEV); return FALSE; } /* Set the driver info */ pldev->pGdiDriverInfo = pDriverInfo; /* Return success. */ return TRUE; }
void VBOXCALL supdrvOSLdrUnload(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage) { if (pImage->pvNtSectionObj) { if (pImage->hMemLock != NIL_RTR0MEMOBJ) { RTR0MemObjFree(pImage->hMemLock, false /*fFreeMappings*/); pImage->hMemLock = NIL_RTR0MEMOBJ; } NTSTATUS rcNt = ZwSetSystemInformation(MY_SystemUnloadGdiDriverInformation, &pImage->pvNtSectionObj, sizeof(pImage->pvNtSectionObj)); if (rcNt != STATUS_SUCCESS) SUPR0Printf("VBoxDrv: failed to unload '%s', rcNt=%#x\n", pImage->szName, rcNt); pImage->pvNtSectionObj = NULL; } NOREF(pDevExt); }
int VBOXCALL supdrvOSLdrOpen(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const char *pszFilename) { pImage->pvNtSectionObj = NULL; pImage->hMemLock = NIL_RTR0MEMOBJ; #ifdef VBOX_WITHOUT_NATIVE_R0_LOADER # ifndef RT_ARCH_X86 # error "VBOX_WITHOUT_NATIVE_R0_LOADER is only safe on x86." # endif NOREF(pDevExt); NOREF(pszFilename); NOREF(pImage); return VERR_NOT_SUPPORTED; #else /* * Convert the filename from DOS UTF-8 to NT UTF-16. */ size_t cwcFilename; int rc = RTStrCalcUtf16LenEx(pszFilename, RTSTR_MAX, &cwcFilename); if (RT_FAILURE(rc)) return rc; PRTUTF16 pwcsFilename = (PRTUTF16)RTMemTmpAlloc((4 + cwcFilename + 1) * sizeof(RTUTF16)); if (!pwcsFilename) return VERR_NO_TMP_MEMORY; pwcsFilename[0] = '\\'; pwcsFilename[1] = '?'; pwcsFilename[2] = '?'; pwcsFilename[3] = '\\'; PRTUTF16 pwcsTmp = &pwcsFilename[4]; rc = RTStrToUtf16Ex(pszFilename, RTSTR_MAX, &pwcsTmp, cwcFilename + 1, NULL); if (RT_SUCCESS(rc)) { /* * Try load it. */ MYSYSTEMGDIDRIVERINFO Info; RtlInitUnicodeString(&Info.Name, pwcsFilename); Info.ImageAddress = NULL; Info.SectionPointer = NULL; Info.EntryPointer = NULL; Info.ExportSectionPointer = NULL; Info.ImageLength = 0; NTSTATUS rcNt = ZwSetSystemInformation(MY_SystemLoadGdiDriverInSystemSpaceInformation, &Info, sizeof(Info)); if (NT_SUCCESS(rcNt)) { pImage->pvImage = Info.ImageAddress; pImage->pvNtSectionObj = Info.SectionPointer; Log(("ImageAddress=%p SectionPointer=%p ImageLength=%#x cbImageBits=%#x rcNt=%#x '%ls'\n", Info.ImageAddress, Info.SectionPointer, Info.ImageLength, pImage->cbImageBits, rcNt, Info.Name.Buffer)); # ifdef DEBUG_bird SUPR0Printf("ImageAddress=%p SectionPointer=%p ImageLength=%#x cbImageBits=%#x rcNt=%#x '%ws'\n", Info.ImageAddress, Info.SectionPointer, Info.ImageLength, pImage->cbImageBits, rcNt, Info.Name.Buffer); # endif if (pImage->cbImageBits == Info.ImageLength) { /* * Lock down the entire image, just to be on the safe side. */ rc = RTR0MemObjLockKernel(&pImage->hMemLock, pImage->pvImage, pImage->cbImageBits, RTMEM_PROT_READ); if (RT_FAILURE(rc)) { pImage->hMemLock = NIL_RTR0MEMOBJ; supdrvOSLdrUnload(pDevExt, pImage); } } else { supdrvOSLdrUnload(pDevExt, pImage); rc = VERR_LDR_MISMATCH_NATIVE; } } else { Log(("rcNt=%#x '%ls'\n", rcNt, pwcsFilename)); SUPR0Printf("VBoxDrv: rcNt=%x '%ws'\n", rcNt, pwcsFilename); switch (rcNt) { case /* 0xc0000003 */ STATUS_INVALID_INFO_CLASS: # ifdef RT_ARCH_AMD64 /* Unwind will crash and BSOD, so no fallback here! */ rc = VERR_NOT_IMPLEMENTED; # else /* * Use the old way of loading the modules. * * Note! We do *NOT* try class 26 because it will probably * not work correctly on terminal servers and such. */ rc = VERR_NOT_SUPPORTED; # endif break; case /* 0xc0000034 */ STATUS_OBJECT_NAME_NOT_FOUND: rc = VERR_MODULE_NOT_FOUND; break; case /* 0xC0000263 */ STATUS_DRIVER_ENTRYPOINT_NOT_FOUND: rc = VERR_LDR_IMPORTED_SYMBOL_NOT_FOUND; break; case 0xC0000428 /* STATUS_INVALID_IMAGE_HASH */ : rc = VERR_LDR_IMAGE_HASH; break; case 0xC000010E /* STATUS_IMAGE_ALREADY_LOADED */ : Log(("WARNING: see @bugref{4853} for cause of this failure on Windows 7 x64\n")); rc = VERR_ALREADY_LOADED; break; default: rc = VERR_LDR_GENERAL_FAILURE; break; } pImage->pvNtSectionObj = NULL; } } RTMemTmpFree(pwcsFilename); NOREF(pDevExt); return rc; #endif }