[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 */
SSI_DEF(SystemUnloadGdiDriverInformation)
{
PVOID SectionPointer = Buffer;
PVOID *SectionPointer = Buffer;
/* Validate size */
if (Size != sizeof(PVOID))
@ -1410,7 +1410,7 @@ SSI_DEF(SystemUnloadGdiDriverInformation)
if (ExGetPreviousMode() != KernelMode) return STATUS_PRIVILEGE_NOT_HELD;
/* Unload the image */
MmUnloadSystemImage(SectionPointer);
MmUnloadSystemImage(*SectionPointer);
return STATUS_SUCCESS;
}

View file

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

View file

@ -30,37 +30,17 @@ typedef struct _LDEVOBJ
} 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
NTSTATUS
NTAPI
InitLDEVImpl(VOID);
PDEVMODEINFO
NTAPI
LDEVOBJ_pdmiGetModes(
_In_ PLDEVOBJ pldev,
_In_ HANDLE hDriver);
PLDEVOBJ
APIENTRY
EngLoadImageEx(
@ -75,6 +55,6 @@ EngGetLDEV(
NTSTATUS
APIENTRY
DriverEntry (
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath);
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath);