[WIN32K:NTUSER] Split NtUserCreateWindowStation() into the part that captures the user-mode data and the internal worker IntCreateWindowStation() function, which will also be used later.

Add a FIXME note about how we currently handle the window station name.
This commit is contained in:
Hermès Bélusca-Maïto 2018-06-16 19:45:07 +02:00
parent f47afc3b61
commit ba018294d3
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0
2 changed files with 135 additions and 50 deletions

View file

@ -386,108 +386,96 @@ CheckWinstaAttributeAccess(ACCESS_MASK DesiredAccess)
* @implemented * @implemented
*/ */
HWINSTA APIENTRY NTSTATUS
NtUserCreateWindowStation( FASTCALL
POBJECT_ATTRIBUTES ObjectAttributes, IntCreateWindowStation(
ACCESS_MASK dwDesiredAccess, OUT HWINSTA* phWinSta,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN KPROCESSOR_MODE AccessMode,
IN ACCESS_MASK dwDesiredAccess,
DWORD Unknown2, DWORD Unknown2,
DWORD Unknown3, DWORD Unknown3,
DWORD Unknown4, DWORD Unknown4,
DWORD Unknown5, DWORD Unknown5,
DWORD Unknown6) DWORD Unknown6)
{ {
UNICODE_STRING WindowStationName;
PWINSTATION_OBJECT WindowStationObject;
HWINSTA WindowStation;
NTSTATUS Status; NTSTATUS Status;
HWINSTA WindowStation;
PWINSTATION_OBJECT WindowStationObject;
TRACE("NtUserCreateWindowStation called\n"); TRACE("IntCreateWindowStation called\n");
ASSERT(phWinSta);
*phWinSta = NULL;
Status = ObOpenObjectByName(ObjectAttributes, Status = ObOpenObjectByName(ObjectAttributes,
ExWindowStationObjectType, ExWindowStationObjectType,
UserMode, AccessMode,
NULL, NULL,
dwDesiredAccess, dwDesiredAccess,
NULL, NULL,
(PVOID*)&WindowStation); (PVOID*)&WindowStation);
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
TRACE("NtUserCreateWindowStation opened window station %wZ\n", ObjectAttributes->ObjectName); TRACE("IntCreateWindowStation opened window station %wZ\n",
return (HWINSTA)WindowStation; ObjectAttributes->ObjectName);
*phWinSta = WindowStation;
return Status;
} }
/* /*
* No existing window station found, try to create new one * No existing window station found, try to create new one.
*/ */
/* Capture window station name */
_SEH2_TRY
{
ProbeForRead( ObjectAttributes, sizeof(OBJECT_ATTRIBUTES), 1);
Status = IntSafeCopyUnicodeStringTerminateNULL(&WindowStationName, ObjectAttributes->ObjectName);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status =_SEH2_GetExceptionCode();
}
_SEH2_END
if (! NT_SUCCESS(Status))
{
ERR("Failed reading capturing window station name\n");
SetLastNtError(Status);
return NULL;
}
/* Create the window station object */ /* Create the window station object */
Status = ObCreateObject(UserMode, Status = ObCreateObject(KernelMode,
ExWindowStationObjectType, ExWindowStationObjectType,
ObjectAttributes, ObjectAttributes,
UserMode, AccessMode,
NULL, NULL,
sizeof(WINSTATION_OBJECT), sizeof(WINSTATION_OBJECT),
0, 0,
0, 0,
(PVOID*)&WindowStationObject); (PVOID*)&WindowStationObject);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
ERR("ObCreateObject failed with %lx for window station %wZ\n", Status, &WindowStationName); ERR("ObCreateObject failed with %lx for window station %wZ\n",
ExFreePoolWithTag(WindowStationName.Buffer, TAG_STRING); Status, ObjectAttributes->ObjectName);
SetLastNtError(STATUS_INSUFFICIENT_RESOURCES); SetLastNtError(Status);
return 0; return Status;
} }
/* Initialize the window station */ /* Initialize the window station */
RtlZeroMemory(WindowStationObject, sizeof(WINSTATION_OBJECT)); RtlZeroMemory(WindowStationObject, sizeof(WINSTATION_OBJECT));
InitializeListHead(&WindowStationObject->DesktopListHead); InitializeListHead(&WindowStationObject->DesktopListHead);
WindowStationObject->Name = WindowStationName; WindowStationObject->Name = *ObjectAttributes->ObjectName;
ObjectAttributes->ObjectName = NULL; // FIXME! (see NtUserCreateWindowStation())
WindowStationObject->dwSessionId = NtCurrentPeb()->SessionId; WindowStationObject->dwSessionId = NtCurrentPeb()->SessionId;
Status = RtlCreateAtomTable(37, &WindowStationObject->AtomTable); Status = RtlCreateAtomTable(37, &WindowStationObject->AtomTable);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
ERR("RtlCreateAtomTable failed with %lx for window station %wZ\n", Status, &WindowStationName); ERR("RtlCreateAtomTable failed with %lx for window station %wZ\n", Status, ObjectAttributes->ObjectName);
ObDereferenceObject(WindowStationObject); ObDereferenceObject(WindowStationObject);
SetLastNtError(STATUS_INSUFFICIENT_RESOURCES); SetLastNtError(Status);
return 0; return Status;
} }
Status = ObInsertObject((PVOID)WindowStationObject, Status = ObInsertObject(WindowStationObject,
NULL, NULL,
dwDesiredAccess, dwDesiredAccess,
0, 0,
NULL, NULL,
(PVOID*)&WindowStation); (PVOID*)&WindowStation);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
ERR("ObInsertObject failed with %lx for window station\n", Status); ERR("ObInsertObject failed with %lx for window station\n", Status);
SetLastNtError(STATUS_INSUFFICIENT_RESOURCES); SetLastNtError(Status);
return 0; return Status;
} }
// FIXME! TODO: Add this new window station to a linked list
if (InputWindowStation == NULL) if (InputWindowStation == NULL)
{ {
ERR("Initializing input window station\n"); ERR("Initializing input window station\n");
@ -502,9 +490,84 @@ NtUserCreateWindowStation(
WindowStationObject->Flags |= WSS_NOIO; WindowStationObject->Flags |= WSS_NOIO;
} }
TRACE("NtUserCreateWindowStation created object %p with name %wZ handle %p\n", TRACE("IntCreateWindowStation created object 0x%p with name %wZ handle 0x%p\n",
WindowStation, &WindowStationObject->Name, WindowStation); WindowStationObject, &WindowStationObject->Name, WindowStation);
return WindowStation;
*phWinSta = WindowStation;
return STATUS_SUCCESS;
}
HWINSTA
APIENTRY
NtUserCreateWindowStation(
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN ACCESS_MASK dwDesiredAccess,
DWORD Unknown2,
DWORD Unknown3,
DWORD Unknown4,
DWORD Unknown5,
DWORD Unknown6)
{
NTSTATUS Status;
HWINSTA hWinSta;
OBJECT_ATTRIBUTES LocalObjectAttributes;
UNICODE_STRING WindowStationName;
TRACE("NtUserCreateWindowStation called\n");
/* Capture window station name */
_SEH2_TRY
{
ProbeForRead(ObjectAttributes, sizeof(OBJECT_ATTRIBUTES), sizeof(ULONG));
LocalObjectAttributes = *ObjectAttributes;
Status = IntSafeCopyUnicodeStringTerminateNULL(&WindowStationName,
LocalObjectAttributes.ObjectName);
LocalObjectAttributes.ObjectName = &WindowStationName;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status =_SEH2_GetExceptionCode();
}
_SEH2_END
if (!NT_SUCCESS(Status))
{
ERR("Failed reading or capturing window station name, Status 0x%08lx\n", Status);
SetLastNtError(Status);
return NULL;
}
// TODO: Capture and use the SecurityQualityOfService!
Status = IntCreateWindowStation(&hWinSta,
&LocalObjectAttributes,
UserMode,
dwDesiredAccess,
Unknown2,
Unknown3,
Unknown4,
Unknown5,
Unknown6);
// FIXME! Because in some situations we store the allocated window station name
// inside the window station, we must not free it now! We know this fact when
// IntCreateWindowStation() sets LocalObjectAttributes.ObjectName to NULL.
// This hack must be removed once we just use the stored Ob name instead
// (in which case we will always free the allocated name here).
if (LocalObjectAttributes.ObjectName)
ExFreePoolWithTag(LocalObjectAttributes.ObjectName->Buffer, TAG_STRING);
if (NT_SUCCESS(Status))
{
TRACE("NtUserCreateWindowStation created a window station with handle 0x%p\n", hWinSta);
}
else
{
ASSERT(hWinSta == NULL);
TRACE("NtUserCreateWindowStation failed to create a window station!\n");
}
return hWinSta;
} }
/* /*
@ -764,6 +827,7 @@ NtUserGetObjectInformation(
case UOI_NAME: case UOI_NAME:
{ {
// FIXME: Use either ObQueryNameString() or read directly that name inside the Object section!
if (WinStaObject != NULL) if (WinStaObject != NULL)
{ {
pvData = WinStaObject->Name.Buffer; pvData = WinStaObject->Name.Buffer;
@ -1136,6 +1200,14 @@ BuildWindowStationNameList(
POBJECT_DIRECTORY_INFORMATION DirEntry; POBJECT_DIRECTORY_INFORMATION DirEntry;
WCHAR NullWchar; WCHAR NullWchar;
//
// FIXME: Fully wrong! Since, by calling NtUserCreateWindowStation
// with judicious parameters one can create window stations elsewhere
// than in Windows\WindowStations directory, Win32k definitely MUST
// maintain a list of window stations it has created, and not rely
// on the enumeration of Windows\WindowStations !!!
//
/* /*
* Try to open the directory. * Try to open the directory.
*/ */

View file

@ -107,6 +107,19 @@ IntValidateWindowStationHandle(
PWINSTATION_OBJECT *Object, PWINSTATION_OBJECT *Object,
POBJECT_HANDLE_INFORMATION pObjectHandleInfo); POBJECT_HANDLE_INFORMATION pObjectHandleInfo);
NTSTATUS
FASTCALL
IntCreateWindowStation(
OUT HWINSTA* phWinSta,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN KPROCESSOR_MODE AccessMode,
IN ACCESS_MASK dwDesiredAccess,
DWORD Unknown2,
DWORD Unknown3,
DWORD Unknown4,
DWORD Unknown5,
DWORD Unknown6);
BOOL FASTCALL UserSetProcessWindowStation(HWINSTA hWindowStation); BOOL FASTCALL UserSetProcessWindowStation(HWINSTA hWindowStation);
BOOL FASTCALL co_IntInitializeDesktopGraphics(VOID); BOOL FASTCALL co_IntInitializeDesktopGraphics(VOID);