[NTOSKRNL]

Fix SystemUnloadGdiDriverInformation case of NtSetSystemInformation.

svn path=/trunk/; revision=60949
This commit is contained in:
Timo Kreuzer 2013-11-11 19:09:53 +00:00
parent 76568b06b5
commit 7833279fa4
3 changed files with 66 additions and 86 deletions

View file

@ -1397,7 +1397,7 @@ SSI_DEF(SystemLoadGdiDriverInformation)
/* Class 27 - Unload Image */ /* Class 27 - Unload Image */
SSI_DEF(SystemUnloadGdiDriverInformation) SSI_DEF(SystemUnloadGdiDriverInformation)
{ {
PVOID SectionPointer = Buffer; PVOID *SectionPointer = Buffer;
/* Validate size */ /* Validate size */
if (Size != sizeof(PVOID)) if (Size != sizeof(PVOID))
@ -1410,7 +1410,7 @@ SSI_DEF(SystemUnloadGdiDriverInformation)
if (ExGetPreviousMode() != KernelMode) return STATUS_PRIVILEGE_NOT_HELD; if (ExGetPreviousMode() != KernelMode) return STATUS_PRIVILEGE_NOT_HELD;
/* Unload the image */ /* Unload the image */
MmUnloadSystemImage(SectionPointer); MmUnloadSystemImage(*SectionPointer);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }

View file

@ -9,6 +9,7 @@
#include <win32k.h> #include <win32k.h>
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
DBG_DEFAULT_CHANNEL(EngLDev);
#ifndef RVA_TO_ADDR #ifndef RVA_TO_ADDR
#define RVA_TO_ADDR(Base,Rva) ((PVOID)(((ULONG_PTR)(Base)) + (Rva))) #define RVA_TO_ADDR(Base,Rva) ((PVOID)(((ULONG_PTR)(Base)) + (Rva)))
@ -16,9 +17,9 @@
/** Globals *******************************************************************/ /** Globals *******************************************************************/
HSEMAPHORE ghsemLDEVList; static HSEMAPHORE ghsemLDEVList;
LDEVOBJ *gpldevHead = NULL; static LDEVOBJ *gpldevHead = NULL;
LDEVOBJ *gpldevWin32k = NULL; static LDEVOBJ *gpldevWin32k = NULL;
/** Private functions *********************************************************/ /** Private functions *********************************************************/
@ -26,7 +27,7 @@ LDEVOBJ *gpldevWin32k = NULL;
INIT_FUNCTION INIT_FUNCTION
NTSTATUS NTSTATUS
NTAPI NTAPI
InitLDEVImpl() InitLDEVImpl(VOID)
{ {
ULONG cbSize; ULONG cbSize;
@ -34,6 +35,7 @@ InitLDEVImpl()
ghsemLDEVList = EngCreateSemaphore(); ghsemLDEVList = EngCreateSemaphore();
if (!ghsemLDEVList) if (!ghsemLDEVList)
{ {
ERR("Failed to create ghsemLDEVList\n");
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
} }
@ -69,9 +71,10 @@ InitLDEVImpl()
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
static
PLDEVOBJ PLDEVOBJ
NTAPI LDEVOBJ_AllocLDEV(
LDEVOBJ_AllocLDEV(LDEVTYPE ldevtype) _In_ LDEVTYPE ldevtype)
{ {
PLDEVOBJ pldev; PLDEVOBJ pldev;
@ -79,7 +82,7 @@ LDEVOBJ_AllocLDEV(LDEVTYPE ldevtype)
pldev = ExAllocatePoolWithTag(PagedPool, sizeof(LDEVOBJ), GDITAG_LDEV); pldev = ExAllocatePoolWithTag(PagedPool, sizeof(LDEVOBJ), GDITAG_LDEV);
if (!pldev) if (!pldev)
{ {
DPRINT1("Failed to allocate LDEVOBJ.\n"); ERR("Failed to allocate LDEVOBJ.\n");
return NULL; return NULL;
} }
@ -92,9 +95,10 @@ LDEVOBJ_AllocLDEV(LDEVTYPE ldevtype)
return pldev; return pldev;
} }
static
VOID VOID
NTAPI LDEVOBJ_vFreeLDEV(
LDEVOBJ_vFreeLDEV(PLDEVOBJ pldev) _In_ _Post_ptr_invalid_ PLDEVOBJ pldev)
{ {
/* Make sure we don't have a driver loaded */ /* Make sure we don't have a driver loaded */
ASSERT(pldev && pldev->pGdiDriverInfo == NULL); ASSERT(pldev && pldev->pGdiDriverInfo == NULL);
@ -107,19 +111,19 @@ LDEVOBJ_vFreeLDEV(PLDEVOBJ pldev)
PDEVMODEINFO PDEVMODEINFO
NTAPI NTAPI
LDEVOBJ_pdmiGetModes( LDEVOBJ_pdmiGetModes(
PLDEVOBJ pldev, _In_ PLDEVOBJ pldev,
HANDLE hDriver) _In_ HANDLE hDriver)
{ {
ULONG cbSize, cbFull; ULONG cbSize, cbFull;
PDEVMODEINFO pdminfo; PDEVMODEINFO pdminfo;
DPRINT("LDEVOBJ_pdmiGetModes(%p, %p)\n", pldev, hDriver); TRACE("LDEVOBJ_pdmiGetModes(%p, %p)\n", pldev, hDriver);
/* Call the driver to get the required size */ /* Call the driver to get the required size */
cbSize = pldev->pfn.GetModes(hDriver, 0, NULL); cbSize = pldev->pfn.GetModes(hDriver, 0, NULL);
if (!cbSize) if (!cbSize)
{ {
DPRINT1("DrvGetModes returned 0\n"); ERR("DrvGetModes returned 0\n");
return NULL; return NULL;
} }
@ -130,7 +134,7 @@ LDEVOBJ_pdmiGetModes(
pdminfo = ExAllocatePoolWithTag(PagedPool, cbFull, GDITAG_DEVMODE); pdminfo = ExAllocatePoolWithTag(PagedPool, cbFull, GDITAG_DEVMODE);
if (!pdminfo) if (!pdminfo)
{ {
DPRINT1("Could not allocate devmodeinfo\n"); ERR("Could not allocate devmodeinfo\n");
return NULL; return NULL;
} }
@ -142,7 +146,7 @@ LDEVOBJ_pdmiGetModes(
if (!cbSize) if (!cbSize)
{ {
/* Could not get modes */ /* Could not get modes */
DPRINT1("returned size %lu(%lu)\n", cbSize, pdminfo->cbdevmode); ERR("returned size %lu(%lu)\n", cbSize, pdminfo->cbdevmode);
ExFreePoolWithTag(pdminfo, GDITAG_DEVMODE); ExFreePoolWithTag(pdminfo, GDITAG_DEVMODE);
pdminfo = NULL; pdminfo = NULL;
} }
@ -150,12 +154,11 @@ LDEVOBJ_pdmiGetModes(
return pdminfo; return pdminfo;
} }
static
BOOL BOOL
NTAPI
LDEVOBJ_bLoadImage( LDEVOBJ_bLoadImage(
IN PLDEVOBJ pldev, _Inout_ PLDEVOBJ pldev,
PUNICODE_STRING pstrPathName) _In_ PUNICODE_STRING pustrPathName)
{ {
PSYSTEM_GDI_DRIVER_INFORMATION pDriverInfo; PSYSTEM_GDI_DRIVER_INFORMATION pDriverInfo;
NTSTATUS Status; NTSTATUS Status;
@ -165,19 +168,19 @@ LDEVOBJ_bLoadImage(
ASSERT(pldev && pldev->pGdiDriverInfo == NULL); ASSERT(pldev && pldev->pGdiDriverInfo == NULL);
/* Allocate a SYSTEM_GDI_DRIVER_INFORMATION structure */ /* Allocate a SYSTEM_GDI_DRIVER_INFORMATION structure */
cbSize = sizeof(SYSTEM_GDI_DRIVER_INFORMATION) + pstrPathName->Length; cbSize = sizeof(SYSTEM_GDI_DRIVER_INFORMATION) + pustrPathName->Length;
pDriverInfo = ExAllocatePoolWithTag(PagedPool, cbSize, GDITAG_LDEV); pDriverInfo = ExAllocatePoolWithTag(PagedPool, cbSize, GDITAG_LDEV);
if (!pDriverInfo) if (!pDriverInfo)
{ {
DPRINT1("Failed to allocate SYSTEM_GDI_DRIVER_INFORMATION\n"); ERR("Failed to allocate SYSTEM_GDI_DRIVER_INFORMATION\n");
return FALSE; return FALSE;
} }
/* Initialize the UNICODE_STRING and copy the driver name */ /* Initialize the UNICODE_STRING and copy the driver name */
RtlInitEmptyUnicodeString(&pDriverInfo->DriverName, RtlInitEmptyUnicodeString(&pDriverInfo->DriverName,
(PWSTR)(pDriverInfo + 1), (PWSTR)(pDriverInfo + 1),
pstrPathName->Length); pustrPathName->Length);
RtlCopyUnicodeString(&pDriverInfo->DriverName, pstrPathName); RtlCopyUnicodeString(&pDriverInfo->DriverName, pustrPathName);
/* Try to load the driver */ /* Try to load the driver */
Status = ZwSetSystemInformation(SystemLoadGdiDriverInformation, Status = ZwSetSystemInformation(SystemLoadGdiDriverInformation,
@ -186,8 +189,8 @@ LDEVOBJ_bLoadImage(
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("Failed to load a GDI driver: '%S', Status = 0x%lx\n", ERR("Failed to load a GDI driver: '%wZ', Status = 0x%lx\n",
pstrPathName->Buffer, Status); pustrPathName, Status);
/* Free the allocated memory */ /* Free the allocated memory */
ExFreePoolWithTag(pDriverInfo, GDITAG_LDEV); ExFreePoolWithTag(pDriverInfo, GDITAG_LDEV);
@ -201,10 +204,10 @@ LDEVOBJ_bLoadImage(
return TRUE; return TRUE;
} }
static
VOID VOID
NTAPI
LDEVOBJ_vUnloadImage( LDEVOBJ_vUnloadImage(
IN PLDEVOBJ pldev) _Inout_ PLDEVOBJ pldev)
{ {
NTSTATUS Status; NTSTATUS Status;
@ -220,11 +223,11 @@ LDEVOBJ_vUnloadImage(
/* Unload the driver */ /* Unload the driver */
Status = ZwSetSystemInformation(SystemUnloadGdiDriverInformation, Status = ZwSetSystemInformation(SystemUnloadGdiDriverInformation,
&pldev->pGdiDriverInfo->ImageAddress, &pldev->pGdiDriverInfo->SectionPointer,
sizeof(HANDLE)); sizeof(HANDLE));
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("Failed to unload the driver, this is bad.\n"); ERR("Failed to unload the driver, this is bad.\n");
} }
/* Free the driver info structure */ /* Free the driver info structure */
@ -232,10 +235,10 @@ LDEVOBJ_vUnloadImage(
pldev->pGdiDriverInfo = NULL; pldev->pGdiDriverInfo = NULL;
} }
static
BOOL BOOL
NTAPI LDEVOBJ_bEnableDriver(
LDEVOBJ_bLoadDriver( _Inout_ PLDEVOBJ pldev)
IN PLDEVOBJ pldev)
{ {
PFN_DrvEnableDriver pfnEnableDriver; PFN_DrvEnableDriver pfnEnableDriver;
DRVENABLEDATA ded; DRVENABLEDATA ded;
@ -249,10 +252,7 @@ LDEVOBJ_bLoadDriver(
pfnEnableDriver = pldev->pGdiDriverInfo->EntryPoint; pfnEnableDriver = pldev->pGdiDriverInfo->EntryPoint;
if (!pfnEnableDriver(GDI_ENGINE_VERSION, sizeof(ded), &ded)) if (!pfnEnableDriver(GDI_ENGINE_VERSION, sizeof(ded), &ded))
{ {
DPRINT1("DrvEnableDriver failed\n"); ERR("DrvEnableDriver failed\n");
/* Unload the image. */
LDEVOBJ_vUnloadImage(pldev);
return FALSE; return FALSE;
} }
@ -269,12 +269,11 @@ LDEVOBJ_bLoadDriver(
return TRUE; return TRUE;
} }
static
PVOID PVOID
NTAPI
LDEVOBJ_pvFindImageProcAddress( LDEVOBJ_pvFindImageProcAddress(
IN PLDEVOBJ pldev, _In_ PLDEVOBJ pldev,
IN LPSTR pszProcName) _In_z_ LPSTR pszProcName)
{ {
PVOID pvImageBase; PVOID pvImageBase;
PIMAGE_EXPORT_DIRECTORY pExportDir; PIMAGE_EXPORT_DIRECTORY pExportDir;
@ -318,8 +317,8 @@ LDEVOBJ_pvFindImageProcAddress(
PLDEVOBJ PLDEVOBJ
NTAPI NTAPI
EngLoadImageEx( EngLoadImageEx(
LPWSTR pwszDriverName, _In_z_ LPWSTR pwszDriverName,
ULONG ldevtype) _In_ ULONG ldevtype)
{ {
WCHAR acwBuffer[MAX_PATH]; WCHAR acwBuffer[MAX_PATH];
PLDEVOBJ pldev; PLDEVOBJ pldev;
@ -327,7 +326,7 @@ EngLoadImageEx(
SIZE_T cwcLength; SIZE_T cwcLength;
LPWSTR pwsz; LPWSTR pwsz;
DPRINT("EngLoadImageEx(%ls, %lu)\n", pwszDriverName, ldevtype); TRACE("EngLoadImageEx(%ls, %lu)\n", pwszDriverName, ldevtype);
ASSERT(pwszDriverName); ASSERT(pwszDriverName);
/* Initialize buffer for the the driver name */ /* Initialize buffer for the the driver name */
@ -343,7 +342,7 @@ EngLoadImageEx(
pwsz = pwszDriverName + cwcLength; pwsz = pwszDriverName + cwcLength;
while (pwsz > pwszDriverName) while (pwsz > pwszDriverName)
{ {
if (_wcsnicmp(pwsz, L"\\system32\\", 10) == 0) if ((*pwsz == L'\\') && (_wcsnicmp(pwsz, L"\\system32\\", 10) == 0))
{ {
/* Driver name starts after system32 */ /* Driver name starts after system32 */
pwsz += 10; pwsz += 10;
@ -356,12 +355,11 @@ EngLoadImageEx(
RtlAppendUnicodeToString(&strDriverName, pwsz); RtlAppendUnicodeToString(&strDriverName, pwsz);
/* MSDN says "The driver must include this suffix in the pwszDriver string." /* MSDN says "The driver must include this suffix in the pwszDriver string."
But in fact it's optional. But in fact it's optional. The function can also load .sys files without
appending the .dll extension. */
ms win32k EngLoadImageEx loading .sys file without append .dll if ((cwcLength < 4) ||
*/ ((_wcsnicmp(pwszDriverName + cwcLength - 4, L".dll", 4) != 0) &&
if ( (_wcsnicmp(pwszDriverName + cwcLength - 4, L".dll", 4) != 0) && (_wcsnicmp(pwszDriverName + cwcLength - 4, L".sys", 4) != 0)) )
(_wcsnicmp(pwszDriverName + cwcLength - 4, L".sys", 4) != 0) )
{ {
/* Append the .dll suffix */ /* Append the .dll suffix */
RtlAppendUnicodeToString(&strDriverName, L".dll"); RtlAppendUnicodeToString(&strDriverName, L".dll");
@ -392,7 +390,7 @@ EngLoadImageEx(
pldev = LDEVOBJ_AllocLDEV(ldevtype); pldev = LDEVOBJ_AllocLDEV(ldevtype);
if (!pldev) if (!pldev)
{ {
DPRINT1("Could not allocate LDEV\n"); ERR("Could not allocate LDEV\n");
goto leave; goto leave;
} }
@ -401,7 +399,7 @@ EngLoadImageEx(
{ {
LDEVOBJ_vFreeLDEV(pldev); LDEVOBJ_vFreeLDEV(pldev);
pldev = NULL; pldev = NULL;
DPRINT1("LDEVOBJ_bLoadImage failed\n"); ERR("LDEVOBJ_bLoadImage failed\n");
goto leave; goto leave;
} }
@ -409,9 +407,12 @@ EngLoadImageEx(
if (ldevtype != LDEV_IMAGE) if (ldevtype != LDEV_IMAGE)
{ {
/* Load the driver */ /* Load the driver */
if (!LDEVOBJ_bLoadDriver(pldev)) if (!LDEVOBJ_bEnableDriver(pldev))
{ {
DPRINT1("LDEVOBJ_bLoadDriver failed\n"); ERR("LDEVOBJ_bEnableDriver failed\n");
/* Unload the image. */
LDEVOBJ_vUnloadImage(pldev);
LDEVOBJ_vFreeLDEV(pldev); LDEVOBJ_vFreeLDEV(pldev);
pldev = NULL; pldev = NULL;
goto leave; goto leave;
@ -431,8 +432,7 @@ leave:
/* Unlock loader */ /* Unlock loader */
EngReleaseSemaphore(ghsemLDEVList); EngReleaseSemaphore(ghsemLDEVList);
DPRINT("EngLoadImageEx returning %p\n", pldev); TRACE("EngLoadImageEx returning %p\n", pldev);
return pldev; return pldev;
} }

View file

@ -30,37 +30,17 @@ typedef struct _LDEVOBJ
} LDEVOBJ, *PLDEVOBJ; } LDEVOBJ, *PLDEVOBJ;
extern PLDEVOBJ gpldevHead;
extern HSEMAPHORE ghsemDriverMgmt;
PLDEVOBJ
NTAPI
LDEVOBJ_pldevLoadImage(
PUNICODE_STRING pusPathName,
LDEVTYPE ldevtype);
BOOL
NTAPI
LDEVOBJ_bLoadDriver(
IN PLDEVOBJ pldev);
PVOID
NTAPI
LDEVOBJ_pvFindImageProcAddress(
IN PLDEVOBJ pldev,
IN LPSTR lpProcName);
PDEVMODEINFO
NTAPI
LDEVOBJ_pdmiGetModes(
PLDEVOBJ pldev,
HANDLE hDriver);
INIT_FUNCTION INIT_FUNCTION
NTSTATUS NTSTATUS
NTAPI NTAPI
InitLDEVImpl(VOID); InitLDEVImpl(VOID);
PDEVMODEINFO
NTAPI
LDEVOBJ_pdmiGetModes(
_In_ PLDEVOBJ pldev,
_In_ HANDLE hDriver);
PLDEVOBJ PLDEVOBJ
APIENTRY APIENTRY
EngLoadImageEx( EngLoadImageEx(
@ -75,6 +55,6 @@ EngGetLDEV(
NTSTATUS NTSTATUS
APIENTRY APIENTRY
DriverEntry ( DriverEntry (
IN PDRIVER_OBJECT DriverObject, _In_ PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath); _In_ PUNICODE_STRING RegistryPath);