📄 winsta.c
字号:
/*
* ReactOS W32 Subsystem
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PURPOSE: Window stations
* FILE: subsys/win32k/ntuser/winsta.c
* PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISION HISTORY:
* 06-06-2001 CSH Created
* NOTES: Exported functions set the Win32 last error value
* on errors. The value can be retrieved with the Win32
* function GetLastError().
* TODO: The process window station is created on
* the first USER32/GDI32 call not related
* to window station/desktop handling
*/
/* INCLUDES ******************************************************************/
#include <w32k.h>
#define NDEBUG
#include <debug.h>
/* GLOBALS *******************************************************************/
/* Currently active window station */
PWINSTATION_OBJECT InputWindowStation = NULL;
/* INITALIZATION FUNCTIONS ****************************************************/
static GENERIC_MAPPING IntWindowStationMapping =
{
STANDARD_RIGHTS_READ | WINSTA_ENUMDESKTOPS | WINSTA_ENUMERATE | WINSTA_READATTRIBUTES | WINSTA_READSCREEN,
STANDARD_RIGHTS_WRITE | WINSTA_ACCESSCLIPBOARD | WINSTA_CREATEDESKTOP | WINSTA_WRITEATTRIBUTES,
STANDARD_RIGHTS_EXECUTE | WINSTA_ACCESSGLOBALATOMS | WINSTA_EXITWINDOWS,
STANDARD_RIGHTS_REQUIRED | WINSTA_ACCESSCLIPBOARD | WINSTA_ACCESSGLOBALATOMS | WINSTA_CREATEDESKTOP |
WINSTA_ENUMDESKTOPS | WINSTA_ENUMERATE | WINSTA_EXITWINDOWS |
WINSTA_READATTRIBUTES | WINSTA_READSCREEN | WINSTA_WRITEATTRIBUTES
};
NTSTATUS FASTCALL
InitWindowStationImpl(VOID)
{
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE WindowStationsDirectory;
UNICODE_STRING UnicodeString;
NTSTATUS Status;
/*
* Create the '\Windows\WindowStations' directory
*/
RtlInitUnicodeString(&UnicodeString, WINSTA_ROOT_NAME);
InitializeObjectAttributes(&ObjectAttributes, &UnicodeString,
0, NULL, NULL);
Status = ZwCreateDirectoryObject(&WindowStationsDirectory, 0,
&ObjectAttributes);
if (!NT_SUCCESS(Status))
{
DPRINT("Could not create \\Windows\\WindowStations directory "
"(Status 0x%X)\n", Status);
return Status;
}
/* Set Winsta Object Attributes */
ExWindowStationObjectType->TypeInfo.DefaultNonPagedPoolCharge = sizeof(WINSTATION_OBJECT);
ExWindowStationObjectType->TypeInfo.GenericMapping = IntWindowStationMapping;
return STATUS_SUCCESS;
}
NTSTATUS FASTCALL
CleanupWindowStationImpl(VOID)
{
return STATUS_SUCCESS;
}
BOOL FASTCALL
IntSetupClipboard(PWINSTATION_OBJECT WinStaObj)
{
WinStaObj->Clipboard = ExAllocatePool(PagedPool, sizeof(CLIPBOARDSYSTEM));
if (WinStaObj->Clipboard)
{
RtlZeroMemory(WinStaObj->Clipboard, sizeof(CLIPBOARDSYSTEM));
return TRUE;
}
return FALSE;
}
/* OBJECT CALLBACKS **********************************************************/
VOID STDCALL
IntWinStaObjectDelete(PWIN32_DELETEMETHOD_PARAMETERS Parameters)
{
PWINSTATION_OBJECT WinSta = (PWINSTATION_OBJECT)Parameters->Object;
DPRINT("Deleting window station (0x%X)\n", WinSta);
RtlDestroyAtomTable(WinSta->AtomTable);
RtlFreeUnicodeString(&WinSta->Name);
}
NTSTATUS
STDCALL
IntWinStaObjectParse(PWIN32_PARSEMETHOD_PARAMETERS Parameters)
{
PUNICODE_STRING RemainingName = Parameters->RemainingName;
/* Assume we don't find anything */
*Parameters->Object = NULL;
/* Check for an empty name */
if (!RemainingName->Length)
{
/* Make sure this is a window station, can't parse a desktop now */
if (Parameters->ObjectType != ExWindowStationObjectType)
{
/* Fail */
return STATUS_OBJECT_TYPE_MISMATCH;
}
/* Reference the window station and return */
ObReferenceObject(Parameters->ParseObject);
*Parameters->Object = Parameters->ParseObject;
return STATUS_SUCCESS;
}
/* Check for leading slash */
if (RemainingName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR)
{
/* Skip it */
RemainingName->Buffer++;
RemainingName->Length -= sizeof(WCHAR);
RemainingName->MaximumLength -= sizeof(WCHAR);
}
/* Check if there is still a slash */
if (wcschr(RemainingName->Buffer, OBJ_NAME_PATH_SEPARATOR))
{
/* In this case, fail */
return STATUS_OBJECT_PATH_INVALID;
}
/*
* Check if we are parsing a desktop.
*/
if (Parameters->ObjectType == ExDesktopObjectType)
{
/* Then call the desktop parse routine */
return IntDesktopObjectParse(Parameters->ParseObject,
Parameters->ObjectType,
Parameters->AccessState,
Parameters->AccessMode,
Parameters->Attributes,
Parameters->CompleteName,
RemainingName,
Parameters->Context,
Parameters->SecurityQos,
Parameters->Object);
}
/* Should hopefully never get here */
return STATUS_OBJECT_TYPE_MISMATCH;
}
/* PRIVATE FUNCTIONS **********************************************************/
/*
* IntGetFullWindowStationName
*
* Get a full window station object name from a name specified in
* NtUserCreateWindowStation, NtUserOpenWindowStation, NtUserCreateDesktop
* or NtUserOpenDesktop.
*
* Return Value
* TRUE on success, FALSE on failure.
*/
BOOL FASTCALL
IntGetFullWindowStationName(
OUT PUNICODE_STRING FullName,
IN PUNICODE_STRING WinStaName,
IN OPTIONAL PUNICODE_STRING DesktopName)
{
PWCHAR Buffer;
FullName->Length = WINSTA_ROOT_NAME_LENGTH * sizeof(WCHAR);
if (WinStaName != NULL)
FullName->Length += WinStaName->Length + sizeof(WCHAR);
if (DesktopName != NULL)
FullName->Length += DesktopName->Length + sizeof(WCHAR);
FullName->MaximumLength = FullName->Length;
FullName->Buffer = ExAllocatePoolWithTag(PagedPool, FullName->Length, TAG_STRING);
if (FullName->Buffer == NULL)
{
return FALSE;
}
Buffer = FullName->Buffer;
memcpy(Buffer, WINSTA_ROOT_NAME, WINSTA_ROOT_NAME_LENGTH * sizeof(WCHAR));
Buffer += WINSTA_ROOT_NAME_LENGTH;
if (WinStaName != NULL)
{
memcpy(Buffer, L"\\", sizeof(WCHAR));
Buffer ++;
memcpy(Buffer, WinStaName->Buffer, WinStaName->Length);
if (DesktopName != NULL)
{
Buffer += WinStaName->Length / sizeof(WCHAR);
memcpy(Buffer, L"\\", sizeof(WCHAR));
Buffer ++;
memcpy(Buffer, DesktopName->Buffer, DesktopName->Length);
}
}
return TRUE;
}
/*
* IntValidateWindowStationHandle
*
* Validates the window station handle.
*
* Remarks
* If the function succeeds, the handle remains referenced. If the
* fucntion fails, last error is set.
*/
NTSTATUS FASTCALL
IntValidateWindowStationHandle(
HWINSTA WindowStation,
KPROCESSOR_MODE AccessMode,
ACCESS_MASK DesiredAccess,
PWINSTATION_OBJECT *Object)
{
NTSTATUS Status;
if (WindowStation == NULL)
{
// DPRINT1("Invalid window station handle\n");
SetLastWin32Error(ERROR_INVALID_HANDLE);
return STATUS_INVALID_HANDLE;
}
Status = ObReferenceObjectByHandle(
WindowStation,
DesiredAccess,
ExWindowStationObjectType,
AccessMode,
(PVOID*)Object,
NULL);
if (!NT_SUCCESS(Status))
SetLastNtError(Status);
return Status;
}
BOOL FASTCALL
IntGetWindowStationObject(PWINSTATION_OBJECT Object)
{
NTSTATUS Status;
Status = ObReferenceObjectByPointer(
Object,
KernelMode,
ExWindowStationObjectType,
0);
return NT_SUCCESS(Status);
}
BOOL FASTCALL
co_IntInitializeDesktopGraphics(VOID)
{
UNICODE_STRING DriverName;
if (! IntCreatePrimarySurface())
{
return FALSE;
}
RtlInitUnicodeString(&DriverName, L"DISPLAY");
ScreenDeviceContext = IntGdiCreateDC(&DriverName, NULL, NULL, NULL, FALSE);
if (NULL == ScreenDeviceContext)
{
IntDestroyPrimarySurface();
return FALSE;
}
DC_SetOwnership(ScreenDeviceContext, NULL);
/* Setup the cursor */
co_IntLoadDefaultCursors();
return TRUE;
}
VOID FASTCALL
IntEndDesktopGraphics(VOID)
{
if (NULL != ScreenDeviceContext)
{
DC_SetOwnership(ScreenDeviceContext, PsGetCurrentProcess());
NtGdiDeleteObjectApp(ScreenDeviceContext);
ScreenDeviceContext = NULL;
}
IntHideDesktop(IntGetActiveDesktop());
IntDestroyPrimarySurface();
}
HDC FASTCALL
IntGetScreenDC(VOID)
{
return ScreenDeviceContext;
}
/* PUBLIC FUNCTIONS ***********************************************************/
/*
* NtUserCreateWindowStation
*
* Creates a new window station.
*
* Parameters
* lpszWindowStationName
* Pointer to a null-terminated string specifying the name of the
* window station to be created. Window station names are
* case-insensitive and cannot contain backslash characters (\).
* Only members of the Administrators group are allowed to specify a
* name.
*
* dwDesiredAccess
* Requested type of access
*
* lpSecurity
* Security descriptor
*
* Unknown3, Unknown4, Unknown5
* Unused
*
* Return Value
* If the function succeeds, the return value is a handle to the newly
* created window station. If the specified window station already
* exists, the function succeeds and returns a handle to the existing
* window station. If the function fails, the return value is NULL.
*
* Todo
* Correct the prototype to match the Windows one (with 7 parameters
* on Windows XP).
*
* Status
* @implemented
*/
HWINSTA STDCALL
NtUserCreateWindowStation(
PUNICODE_STRING lpszWindowStationName,
ACCESS_MASK dwDesiredAccess,
LPSECURITY_ATTRIBUTES lpSecurity,
DWORD Unknown3,
DWORD Unknown4,
DWORD Unknown5)
{
PSYSTEM_CURSORINFO CurInfo;
UNICODE_STRING WindowStationName;
UNICODE_STRING FullWindowStationName;
PWINSTATION_OBJECT WindowStationObject;
HWINSTA WindowStation;
OBJECT_ATTRIBUTES ObjectAttributes;
NTSTATUS Status;
/*
* Generate full window station name
*/
Status = ProbeAndCaptureUnicodeString(&WindowStationName,
UserMode,
lpszWindowStationName);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to capture window station name (status 0x%08x)\n",
Status);
SetLastNtError(Status);
return 0;
}
if (!IntGetFullWindowStationName(&FullWindowStationName,
&WindowStationName,
NULL))
{
ReleaseCapturedUnicodeString(&WindowStationName, UserMode);
SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
return 0;
}
/*
* Try to open already existing window station
*/
DPRINT("Trying to open window station (%wZ)\n", &FullWindowStationName);
/* Initialize ObjectAttributes for the window station object */
InitializeObjectAttributes(
&ObjectAttributes,
&FullWindowStationName,
0,
NULL,
NULL);
Status = ObOpenObjectByName(
&ObjectAttributes,
ExWindowStationObjectType,
KernelMode,
NULL,
dwDesiredAccess,
NULL,
(PVOID*)&WindowStation);
if (NT_SUCCESS(Status))
{
DPRINT("Successfully opened window station (%wZ)\n",
FullWindowStationName);
ExFreePool(FullWindowStationName.Buffer);
ReleaseCapturedUnicodeString(&WindowStationName, UserMode);
return (HWINSTA)WindowStation;
}
/*
* No existing window station found, try to create new one
*/
DPRINT("Creating window station (%wZ)\n", &FullWindowStationName);
Status = ObCreateObject(
KernelMode,
ExWindowStationObjectType,
&ObjectAttributes,
ExGetPreviousMode(),
NULL,
sizeof(WINSTATION_OBJECT),
0,
0,
(PVOID*)&WindowStationObject);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed creating window station (%wZ)\n", &FullWindowStationName);
ExFreePool(FullWindowStationName.Buffer);
ReleaseCapturedUnicodeString(&WindowStationName, UserMode);
SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
return 0;
}
KeInitializeSpinLock(&WindowStationObject->Lock);
InitializeListHead(&WindowStationObject->DesktopListHead);
WindowStationObject->AtomTable = NULL;
Status = RtlCreateAtomTable(37, &WindowStationObject->AtomTable);
WindowStationObject->SystemMenuTemplate = (HANDLE)0;
WindowStationObject->Name = WindowStationName;
Status = ObInsertObject(
(PVOID)WindowStationObject,
NULL,
STANDARD_RIGHTS_REQUIRED,
0,
NULL,
(PVOID*)&WindowStation);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed creating window station (%wZ)\n", &FullWindowStationName);
ExFreePool(FullWindowStationName.Buffer);
ExFreePool(WindowStationName.Buffer);
SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
ObDereferenceObject(WindowStationObject);
return 0;
}
/*
* Initialize the new window station object
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -