* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Win32k subsystem
* PURPOSE: Window stations
- * FILE: subsystems/win32/win32k/ntuser/winsta.c
+ * FILE: win32ss/user/ntuser/winsta.c
* PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
* TODO: The process window station is created on
* the first USER32/GDI32 call not related
NTAPI
InitWindowStationImpl(VOID)
{
- GENERIC_MAPPING IntWindowStationMapping = { WINSTA_READ,
- WINSTA_WRITE,
- WINSTA_EXECUTE,
- WINSTA_ACCESS_ALL};
+ GENERIC_MAPPING IntWindowStationMapping = { WINSTA_READ,
+ WINSTA_WRITE,
+ WINSTA_EXECUTE,
+ WINSTA_ACCESS_ALL};
- /* Set Winsta Object Attributes */
- ExWindowStationObjectType->TypeInfo.DefaultNonPagedPoolCharge = sizeof(WINSTATION_OBJECT);
- ExWindowStationObjectType->TypeInfo.GenericMapping = IntWindowStationMapping;
- ExWindowStationObjectType->TypeInfo.ValidAccessMask = WINSTA_ACCESS_ALL;
+ /* Set Winsta Object Attributes */
+ ExWindowStationObjectType->TypeInfo.DefaultNonPagedPoolCharge = sizeof(WINSTATION_OBJECT);
+ ExWindowStationObjectType->TypeInfo.GenericMapping = IntWindowStationMapping;
+ ExWindowStationObjectType->TypeInfo.ValidAccessMask = WINSTA_ACCESS_ALL;
- return STATUS_SUCCESS;
+ return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
-UserCreateWinstaDirectory()
+UserCreateWinstaDirectory(VOID)
{
PPEB Peb;
NTSTATUS Status;
}
}
- InitializeObjectAttributes(&ObjectAttributes,
- &gustrWindowStationsDir,
- 0,
- NULL,
- NULL);
- Status = ZwCreateDirectoryObject(&hWinstaDir, 0, &ObjectAttributes);
- if (!NT_SUCCESS(Status))
- {
- ERR("Could not create %wZ directory (Status 0x%X)\n", &gustrWindowStationsDir, Status);
- return Status;
- }
+ InitializeObjectAttributes(&ObjectAttributes,
+ &gustrWindowStationsDir,
+ 0,
+ NULL,
+ NULL);
+ Status = ZwCreateDirectoryObject(&hWinstaDir, 0, &ObjectAttributes);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("Could not create %wZ directory (Status 0x%X)\n", &gustrWindowStationsDir, Status);
+ return Status;
+ }
- TRACE("Created directory %wZ for session %lu\n", &gustrWindowStationsDir, Peb->SessionId);
+ TRACE("Created directory %wZ for session %lu\n", &gustrWindowStationsDir, Peb->SessionId);
- return Status;
+ return Status;
}
/* OBJECT CALLBACKS **********************************************************/
NTSTATUS
-APIENTRY
+NTAPI
IntWinStaObjectDelete(
_In_ PVOID Parameters)
{
PWIN32_DELETEMETHOD_PARAMETERS DeleteParameters = Parameters;
- PWINSTATION_OBJECT WinSta = (PWINSTATION_OBJECT)DeleteParameters->Object;
+ PWINSTATION_OBJECT WinSta = (PWINSTATION_OBJECT)DeleteParameters->Object;
+
+ TRACE("Deleting window station (0x%p)\n", WinSta);
- TRACE("Deleting window station (0x%p)\n", WinSta);
+ WinSta->Flags |= WSS_DYING;
- UserEmptyClipboardData(WinSta);
+ UserEmptyClipboardData(WinSta);
- RtlDestroyAtomTable(WinSta->AtomTable);
+ RtlDestroyAtomTable(WinSta->AtomTable);
- RtlFreeUnicodeString(&WinSta->Name);
+ RtlFreeUnicodeString(&WinSta->Name);
- return STATUS_SUCCESS;
+ return STATUS_SUCCESS;
}
NTSTATUS
-APIENTRY
+NTAPI
IntWinStaObjectParse(
_In_ PVOID Parameters)
{
NTSTATUS
NTAPI
-IntWinstaOkToClose(
+IntWinStaOkToClose(
_In_ PVOID Parameters)
{
PWIN32_OKAYTOCLOSEMETHOD_PARAMETERS OkToCloseParameters = Parameters;
NTSTATUS FASTCALL
IntValidateWindowStationHandle(
- HWINSTA WindowStation,
- KPROCESSOR_MODE AccessMode,
- ACCESS_MASK DesiredAccess,
- PWINSTATION_OBJECT *Object)
+ HWINSTA WindowStation,
+ KPROCESSOR_MODE AccessMode,
+ ACCESS_MASK DesiredAccess,
+ PWINSTATION_OBJECT *Object,
+ POBJECT_HANDLE_INFORMATION pObjectHandleInfo)
{
- NTSTATUS Status;
-
- if (WindowStation == NULL)
- {
- ERR("Invalid window station handle\n");
- EngSetLastError(ERROR_INVALID_HANDLE);
- return STATUS_INVALID_HANDLE;
- }
-
- Status = ObReferenceObjectByHandle(
- WindowStation,
- DesiredAccess,
- ExWindowStationObjectType,
- AccessMode,
- (PVOID*)Object,
- NULL);
-
- if (!NT_SUCCESS(Status))
- SetLastNtError(Status);
-
- return Status;
+ NTSTATUS Status;
+
+ if (WindowStation == NULL)
+ {
+ ERR("Invalid window station handle\n");
+ EngSetLastError(ERROR_INVALID_HANDLE);
+ return STATUS_INVALID_HANDLE;
+ }
+
+ Status = ObReferenceObjectByHandle(WindowStation,
+ DesiredAccess,
+ ExWindowStationObjectType,
+ AccessMode,
+ (PVOID*)Object,
+ pObjectHandleInfo);
+
+ if (!NT_SUCCESS(Status))
+ SetLastNtError(Status);
+
+ return Status;
}
BOOL FASTCALL
co_IntInitializeDesktopGraphics(VOID)
{
- TEXTMETRICW tmw;
- UNICODE_STRING DriverName = RTL_CONSTANT_STRING(L"DISPLAY");
- PDESKTOP pdesk;
-
- ScreenDeviceContext = IntGdiCreateDC(&DriverName, NULL, NULL, NULL, FALSE);
- if (NULL == ScreenDeviceContext)
- {
- IntDestroyPrimarySurface();
- return FALSE;
- }
- GreSetDCOwner(ScreenDeviceContext, GDI_OBJ_HMGR_PUBLIC);
-
- if (! IntCreatePrimarySurface())
- {
- return FALSE;
- }
-
- hSystemBM = NtGdiCreateCompatibleDC(ScreenDeviceContext);
-
- NtGdiSelectFont(hSystemBM, NtGdiGetStockObject(SYSTEM_FONT));
- GreSetDCOwner(hSystemBM, GDI_OBJ_HMGR_PUBLIC);
-
- /* Update the SERVERINFO */
- gpsi->aiSysMet[SM_CXSCREEN] = gppdevPrimary->gdiinfo.ulHorzRes;
- gpsi->aiSysMet[SM_CYSCREEN] = gppdevPrimary->gdiinfo.ulVertRes;
- gpsi->Planes = NtGdiGetDeviceCaps(ScreenDeviceContext, PLANES);
- gpsi->BitsPixel = NtGdiGetDeviceCaps(ScreenDeviceContext, BITSPIXEL);
- gpsi->BitCount = gpsi->Planes * gpsi->BitsPixel;
- gpsi->dmLogPixels = NtGdiGetDeviceCaps(ScreenDeviceContext, LOGPIXELSY);
- if (NtGdiGetDeviceCaps(ScreenDeviceContext, RASTERCAPS) & RC_PALETTE)
- {
- gpsi->PUSIFlags |= PUSIF_PALETTEDISPLAY;
- }
- else
- gpsi->PUSIFlags &= ~PUSIF_PALETTEDISPLAY;
- // Font is realized and this dc was previously set to internal DC_ATTR.
- gpsi->cxSysFontChar = IntGetCharDimensions(hSystemBM, &tmw, (DWORD*)&gpsi->cySysFontChar);
- gpsi->tmSysFont = tmw;
-
- /* Put the pointer in the center of the screen */
- gpsi->ptCursor.x = gpsi->aiSysMet[SM_CXSCREEN] / 2;
- gpsi->ptCursor.y = gpsi->aiSysMet[SM_CYSCREEN] / 2;
-
- /* Attach monitor */
- UserAttachMonitor((HDEV)gppdevPrimary);
-
- /* Setup the cursor */
- co_IntLoadDefaultCursors();
-
- /* Show the desktop */
- pdesk = IntGetActiveDesktop();
- ASSERT(pdesk);
- co_IntShowDesktop(pdesk, gpsi->aiSysMet[SM_CXSCREEN], gpsi->aiSysMet[SM_CYSCREEN], TRUE);
-
- return TRUE;
+ TEXTMETRICW tmw;
+ UNICODE_STRING DriverName = RTL_CONSTANT_STRING(L"DISPLAY");
+ PDESKTOP pdesk;
+
+ ScreenDeviceContext = IntGdiCreateDC(&DriverName, NULL, NULL, NULL, FALSE);
+ if (NULL == ScreenDeviceContext)
+ {
+ IntDestroyPrimarySurface();
+ return FALSE;
+ }
+ GreSetDCOwner(ScreenDeviceContext, GDI_OBJ_HMGR_PUBLIC);
+
+ if (! IntCreatePrimarySurface())
+ {
+ return FALSE;
+ }
+
+ hSystemBM = NtGdiCreateCompatibleDC(ScreenDeviceContext);
+
+ NtGdiSelectFont(hSystemBM, NtGdiGetStockObject(SYSTEM_FONT));
+ GreSetDCOwner(hSystemBM, GDI_OBJ_HMGR_PUBLIC);
+
+ /* Update the SERVERINFO */
+ gpsi->aiSysMet[SM_CXSCREEN] = gppdevPrimary->gdiinfo.ulHorzRes;
+ gpsi->aiSysMet[SM_CYSCREEN] = gppdevPrimary->gdiinfo.ulVertRes;
+ gpsi->Planes = NtGdiGetDeviceCaps(ScreenDeviceContext, PLANES);
+ gpsi->BitsPixel = NtGdiGetDeviceCaps(ScreenDeviceContext, BITSPIXEL);
+ gpsi->BitCount = gpsi->Planes * gpsi->BitsPixel;
+ gpsi->dmLogPixels = NtGdiGetDeviceCaps(ScreenDeviceContext, LOGPIXELSY);
+ if (NtGdiGetDeviceCaps(ScreenDeviceContext, RASTERCAPS) & RC_PALETTE)
+ {
+ gpsi->PUSIFlags |= PUSIF_PALETTEDISPLAY;
+ }
+ else
+ gpsi->PUSIFlags &= ~PUSIF_PALETTEDISPLAY;
+ // Font is realized and this dc was previously set to internal DC_ATTR.
+ gpsi->cxSysFontChar = IntGetCharDimensions(hSystemBM, &tmw, (DWORD*)&gpsi->cySysFontChar);
+ gpsi->tmSysFont = tmw;
+
+ /* Put the pointer in the center of the screen */
+ gpsi->ptCursor.x = gpsi->aiSysMet[SM_CXSCREEN] / 2;
+ gpsi->ptCursor.y = gpsi->aiSysMet[SM_CYSCREEN] / 2;
+
+ /* Attach monitor */
+ UserAttachMonitor((HDEV)gppdevPrimary);
+
+ /* Setup the cursor */
+ co_IntLoadDefaultCursors();
+
+ /* Setup the icons */
+ co_IntSetWndIcons();
+
+ /* Setup Menu */
+ MenuInit();
+
+ /* Show the desktop */
+ pdesk = IntGetActiveDesktop();
+ ASSERT(pdesk);
+ co_IntShowDesktop(pdesk, gpsi->aiSysMet[SM_CXSCREEN], gpsi->aiSysMet[SM_CYSCREEN], TRUE);
+
+ return TRUE;
}
VOID FASTCALL
IntEndDesktopGraphics(VOID)
{
- if (NULL != ScreenDeviceContext)
- { // No need to allocate a new dcattr.
- GreSetDCOwner(ScreenDeviceContext, GDI_OBJ_HMGR_POWNED);
- GreDeleteObject(ScreenDeviceContext);
- ScreenDeviceContext = NULL;
- }
- IntHideDesktop(IntGetActiveDesktop());
- IntDestroyPrimarySurface();
+ if (NULL != ScreenDeviceContext)
+ { // No need to allocate a new dcattr.
+ GreSetDCOwner(ScreenDeviceContext, GDI_OBJ_HMGR_POWNED);
+ GreDeleteObject(ScreenDeviceContext);
+ ScreenDeviceContext = NULL;
+ }
+ IntHideDesktop(IntGetActiveDesktop());
+ IntDestroyPrimarySurface();
}
HDC FASTCALL
IntGetScreenDC(VOID)
{
- return ScreenDeviceContext;
+ return ScreenDeviceContext;
}
+BOOL FASTCALL
+CheckWinstaAttributeAccess(ACCESS_MASK DesiredAccess)
+{
+ PPROCESSINFO ppi = PsGetCurrentProcessWin32Process();
+ if ( gpidLogon != PsGetCurrentProcessId() )
+ {
+ if (!(ppi->W32PF_flags & W32PF_IOWINSTA))
+ {
+ ERR("Requires Interactive Window Station\n");
+ EngSetLastError(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION);
+ return FALSE;
+ }
+ if (!RtlAreAllAccessesGranted(ppi->amwinsta, DesiredAccess))
+ {
+ ERR("Access Denied\n");
+ EngSetLastError(ERROR_ACCESS_DENIED);
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+
/* PUBLIC FUNCTIONS ***********************************************************/
/*
* lpSecurity
* Security descriptor
*
- * Unknown3, Unknown4, Unknown5
+ * Unknown3, Unknown4, Unknown5, Unknown6
* Unused
*
* Return Value
* 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 APIENTRY
NtUserCreateWindowStation(
- POBJECT_ATTRIBUTES ObjectAttributes,
- ACCESS_MASK dwDesiredAccess,
- DWORD Unknown2,
- DWORD Unknown3,
- DWORD Unknown4,
- DWORD Unknown5,
- DWORD Unknown6)
+ POBJECT_ATTRIBUTES ObjectAttributes,
+ ACCESS_MASK dwDesiredAccess,
+ DWORD Unknown2,
+ DWORD Unknown3,
+ DWORD Unknown4,
+ DWORD Unknown5,
+ DWORD Unknown6)
{
- UNICODE_STRING WindowStationName;
- PWINSTATION_OBJECT WindowStationObject;
- HWINSTA WindowStation;
- NTSTATUS Status;
-
- TRACE("NtUserCreateWindowStation called\n");
-
- Status = ObOpenObjectByName(
- ObjectAttributes,
- ExWindowStationObjectType,
- UserMode,
- NULL,
- dwDesiredAccess,
- NULL,
- (PVOID*)&WindowStation);
-
- if (NT_SUCCESS(Status))
- {
- TRACE("NtUserCreateWindowStation opened window station %wZ\n", ObjectAttributes->ObjectName);
- return (HWINSTA)WindowStation;
- }
-
- /*
- * 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 */
- Status = ObCreateObject(
- UserMode,
- ExWindowStationObjectType,
- ObjectAttributes,
- UserMode,
- NULL,
- sizeof(WINSTATION_OBJECT),
- 0,
- 0,
- (PVOID*)&WindowStationObject);
-
- if (!NT_SUCCESS(Status))
- {
- ERR("ObCreateObject failed for window station %wZ\n", &WindowStationName);
- ExFreePoolWithTag(WindowStationName.Buffer, TAG_STRING);
- SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
- return 0;
- }
-
- Status = ObInsertObject(
- (PVOID)WindowStationObject,
- NULL,
- dwDesiredAccess,
- 0,
- NULL,
- (PVOID*)&WindowStation);
-
- if (!NT_SUCCESS(Status))
- {
- ERR("ObInsertObject failed for window station %wZ\n", &WindowStationName);
- ExFreePoolWithTag(WindowStationName.Buffer, TAG_STRING);
- SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
- ObDereferenceObject(WindowStationObject);
- return 0;
- }
-
- /* Initialize the window station */
- RtlZeroMemory(WindowStationObject, sizeof(WINSTATION_OBJECT));
-
- KeInitializeSpinLock(&WindowStationObject->Lock);
- InitializeListHead(&WindowStationObject->DesktopListHead);
- Status = RtlCreateAtomTable(37, &WindowStationObject->AtomTable);
- WindowStationObject->SystemMenuTemplate = (HANDLE)0;
- WindowStationObject->Name = WindowStationName;
- WindowStationObject->dwSessionId = NtCurrentPeb()->SessionId;
-
- if (InputWindowStation == NULL)
- {
- TRACE("Initializeing input window station\n");
- InputWindowStation = WindowStationObject;
-
- InitCursorImpl();
- }
-
- TRACE("NtUserCreateWindowStation created object %p with name %wZ handle %p\n",
+ UNICODE_STRING WindowStationName;
+ PWINSTATION_OBJECT WindowStationObject;
+ HWINSTA WindowStation;
+ NTSTATUS Status;
+
+ TRACE("NtUserCreateWindowStation called\n");
+
+ Status = ObOpenObjectByName(ObjectAttributes,
+ ExWindowStationObjectType,
+ UserMode,
+ NULL,
+ dwDesiredAccess,
+ NULL,
+ (PVOID*)&WindowStation);
+
+ if (NT_SUCCESS(Status))
+ {
+ TRACE("NtUserCreateWindowStation opened window station %wZ\n", ObjectAttributes->ObjectName);
+ return (HWINSTA)WindowStation;
+ }
+
+ /*
+ * 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 */
+ Status = ObCreateObject(UserMode,
+ ExWindowStationObjectType,
+ ObjectAttributes,
+ UserMode,
+ NULL,
+ sizeof(WINSTATION_OBJECT),
+ 0,
+ 0,
+ (PVOID*)&WindowStationObject);
+
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("ObCreateObject failed with %lx for window station %wZ\n", Status, &WindowStationName);
+ ExFreePoolWithTag(WindowStationName.Buffer, TAG_STRING);
+ SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
+ return 0;
+ }
+
+ /* Initialize the window station */
+ RtlZeroMemory(WindowStationObject, sizeof(WINSTATION_OBJECT));
+
+ InitializeListHead(&WindowStationObject->DesktopListHead);
+ WindowStationObject->Name = WindowStationName;
+ WindowStationObject->dwSessionId = NtCurrentPeb()->SessionId;
+ Status = RtlCreateAtomTable(37, &WindowStationObject->AtomTable);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("RtlCreateAtomTable failed with %lx for window station %wZ\n", Status, &WindowStationName);
+ ObDereferenceObject(WindowStationObject);
+ SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
+ return 0;
+ }
+
+ Status = ObInsertObject((PVOID)WindowStationObject,
+ NULL,
+ dwDesiredAccess,
+ 0,
+ NULL,
+ (PVOID*)&WindowStation);
+
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("ObInsertObject failed with %lx for window station\n", Status);
+ SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
+ return 0;
+ }
+
+ if (InputWindowStation == NULL)
+ {
+ ERR("Initializing input window station\n");
+ InputWindowStation = WindowStationObject;
+
+ WindowStationObject->Flags &= ~WSS_NOIO;
+
+ InitCursorImpl();
+ }
+ else
+ {
+ WindowStationObject->Flags |= WSS_NOIO;
+ }
+
+ TRACE("NtUserCreateWindowStation created object %p with name %wZ handle %p\n",
WindowStation, &WindowStationObject->Name, WindowStation);
- return WindowStation;
+ return WindowStation;
}
/*
HWINSTA APIENTRY
NtUserOpenWindowStation(
- POBJECT_ATTRIBUTES ObjectAttributes,
- ACCESS_MASK dwDesiredAccess)
+ POBJECT_ATTRIBUTES ObjectAttributes,
+ ACCESS_MASK dwDesiredAccess)
{
- HWINSTA hwinsta;
- NTSTATUS Status;
-
- Status = ObOpenObjectByName(
- ObjectAttributes,
- ExWindowStationObjectType,
- UserMode,
- NULL,
- dwDesiredAccess,
- NULL,
- (PVOID*)&hwinsta);
-
- if (!NT_SUCCESS(Status))
- {
- ERR("NtUserOpenWindowStation failed\n");
- SetLastNtError(Status);
- return 0;
- }
-
- TRACE("Opened window station %wZ with handle %p\n", ObjectAttributes->ObjectName, hwinsta);
-
- return hwinsta;
+ HWINSTA hwinsta;
+ NTSTATUS Status;
+
+ Status = ObOpenObjectByName(ObjectAttributes,
+ ExWindowStationObjectType,
+ UserMode,
+ NULL,
+ dwDesiredAccess,
+ NULL,
+ (PVOID*)&hwinsta);
+
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("NtUserOpenWindowStation failed\n");
+ SetLastNtError(Status);
+ return 0;
+ }
+
+ TRACE("Opened window station %wZ with handle %p\n", ObjectAttributes->ObjectName, hwinsta);
+
+ return hwinsta;
}
/*
BOOL
APIENTRY
NtUserCloseWindowStation(
- HWINSTA hWinSta)
+ HWINSTA hWinSta)
{
- PWINSTATION_OBJECT Object;
- NTSTATUS Status;
+ PWINSTATION_OBJECT Object;
+ NTSTATUS Status;
- TRACE("NtUserCloseWindowStation called (%p)\n", hWinSta);
+ TRACE("NtUserCloseWindowStation called (%p)\n", hWinSta);
- if (hWinSta == UserGetProcessWindowStation())
- {
+ if (hWinSta == UserGetProcessWindowStation())
+ {
ERR("Attempted to close process window station\n");
- return FALSE;
- }
+ return FALSE;
+ }
- Status = IntValidateWindowStationHandle(
- hWinSta,
- KernelMode,
- 0,
- &Object);
+ Status = IntValidateWindowStationHandle(hWinSta,
+ UserMode,
+ 0,
+ &Object,
+ 0);
- if (!NT_SUCCESS(Status))
- {
- ERR("Validation of window station handle (%p) failed\n", hWinSta);
- return FALSE;
- }
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("Validation of window station handle (%p) failed\n", hWinSta);
+ return FALSE;
+ }
- ObDereferenceObject(Object);
+ ObDereferenceObject(Object);
- TRACE("Closing window station handle (%p)\n", hWinSta);
+ TRACE("Closing window station handle (%p)\n", hWinSta);
- Status = ObCloseHandle(hWinSta, UserMode);
- if (!NT_SUCCESS(Status))
- {
- SetLastNtError(Status);
- return FALSE;
- }
+ Status = ObCloseHandle(hWinSta, UserMode);
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ return FALSE;
+ }
- return TRUE;
+ return TRUE;
}
/*
BOOL APIENTRY
NtUserGetObjectInformation(
- HANDLE hObject,
- DWORD nIndex,
- PVOID pvInformation,
- DWORD nLength,
- PDWORD nLengthNeeded)
+ HANDLE hObject,
+ DWORD nIndex,
+ PVOID pvInformation,
+ DWORD nLength,
+ PDWORD nLengthNeeded)
{
- PWINSTATION_OBJECT WinStaObject = NULL;
- PDESKTOP DesktopObject = NULL;
- NTSTATUS Status;
- PVOID pvData = NULL;
- DWORD nDataSize = 0;
-
- _SEH2_TRY
- {
- if (nLengthNeeded)
- ProbeForWrite(nLengthNeeded, sizeof(*nLengthNeeded), 1);
- ProbeForWrite(pvInformation, nLength, 1);
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- SetLastNtError(_SEH2_GetExceptionCode());
- return FALSE;
- }
- _SEH2_END;
-
- /* try windowstation */
- TRACE("Trying to open window station %p\n", hObject);
- Status = ObReferenceObjectByHandle(
- hObject,
- 0,
- ExWindowStationObjectType,
- UserMode,
- (PVOID*)&WinStaObject,
- NULL);
-
- if (Status == STATUS_OBJECT_TYPE_MISMATCH)
- {
- /* try desktop */
- TRACE("Trying to open desktop %p\n", hObject);
- Status = IntValidateDesktopHandle(
- hObject,
- UserMode,
- 0,
- &DesktopObject);
- }
-
- if (!NT_SUCCESS(Status))
- {
- ERR("Failed: 0x%x\n", Status);
- goto Exit;
- }
-
- TRACE("WinSta or Desktop opened!!\n");
-
- /* get data */
- switch (nIndex)
- {
- case UOI_FLAGS:
- Status = STATUS_NOT_IMPLEMENTED;
- ERR("UOI_FLAGS unimplemented!\n");
- break;
-
- case UOI_NAME:
- if (WinStaObject != NULL)
- {
- pvData = WinStaObject->Name.Buffer;
- nDataSize = WinStaObject->Name.Length + sizeof(WCHAR);
- Status = STATUS_SUCCESS;
- }
- else if (DesktopObject != NULL)
- {
- pvData = DesktopObject->pDeskInfo->szDesktopName;
- nDataSize = (wcslen(DesktopObject->pDeskInfo->szDesktopName) + 1) * sizeof(WCHAR);
- Status = STATUS_SUCCESS;
- }
- else
- Status = STATUS_INVALID_PARAMETER;
- break;
+ NTSTATUS Status;
+ PWINSTATION_OBJECT WinStaObject = NULL;
+ PDESKTOP DesktopObject = NULL;
+ USEROBJECTFLAGS ObjectFlags;
+ PVOID pvData = NULL;
+ SIZE_T nDataSize = 0;
- case UOI_TYPE:
- if (WinStaObject != NULL)
- {
- pvData = L"WindowStation";
- nDataSize = sizeof(L"WindowStation");
- Status = STATUS_SUCCESS;
- }
- else if (DesktopObject != NULL)
- {
- pvData = L"Desktop";
- nDataSize = sizeof(L"Desktop");
+ _SEH2_TRY
+ {
+ if (nLengthNeeded)
+ ProbeForWrite(nLengthNeeded, sizeof(*nLengthNeeded), 1);
+ ProbeForWrite(pvInformation, nLength, 1);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ SetLastNtError(_SEH2_GetExceptionCode());
+ return FALSE;
+ }
+ _SEH2_END;
+
+ /* Try window station */
+ TRACE("Trying to open window station %p\n", hObject);
+ Status = ObReferenceObjectByHandle(hObject,
+ 0,
+ ExWindowStationObjectType,
+ UserMode,
+ (PVOID*)&WinStaObject,
+ NULL);
+
+ if (Status == STATUS_OBJECT_TYPE_MISMATCH)
+ {
+ /* Try desktop */
+ TRACE("Trying to open desktop %p\n", hObject);
+ WinStaObject = NULL;
+ Status = IntValidateDesktopHandle(hObject,
+ UserMode,
+ 0,
+ &DesktopObject);
+ }
+
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("Failed: 0x%x\n", Status);
+ goto Exit;
+ }
+
+ TRACE("WinSta or Desktop opened!\n");
+
+ /* Get data */
+ switch (nIndex)
+ {
+ case UOI_FLAGS:
+ {
+ OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo;
+ ULONG BytesWritten;
+
+ ObjectFlags.fReserved = FALSE;
+
+ /* Check whether this handle is inheritable */
+ Status = ZwQueryObject(hObject,
+ ObjectHandleFlagInformation,
+ &HandleInfo,
+ sizeof(OBJECT_HANDLE_ATTRIBUTE_INFORMATION),
+ &BytesWritten);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("ZwQueryObject failed, Status 0x%08lx\n", Status);
+ break;
+ }
+ ObjectFlags.fInherit = HandleInfo.Inherit;
+
+ ObjectFlags.dwFlags = 0;
+ if (WinStaObject != NULL)
+ {
+ if (!(WinStaObject->Flags & WSS_NOIO))
+ ObjectFlags.dwFlags |= WSF_VISIBLE;
+ }
+ else if (DesktopObject != NULL)
+ {
+ FIXME("Setting DF_ALLOWOTHERACCOUNTHOOK is unimplemented.\n");
+ }
+ else
+ {
+ ERR("No associated WinStaObject nor DesktopObject!\n");
+ }
+
+ pvData = &ObjectFlags;
+ nDataSize = sizeof(ObjectFlags);
Status = STATUS_SUCCESS;
- }
- else
- Status = STATUS_INVALID_PARAMETER;
- break;
+ break;
+ }
+
+ case UOI_NAME:
+ {
+ if (WinStaObject != NULL)
+ {
+ pvData = WinStaObject->Name.Buffer;
+ nDataSize = WinStaObject->Name.Length + sizeof(WCHAR);
+ Status = STATUS_SUCCESS;
+ }
+ else if (DesktopObject != NULL)
+ {
+ pvData = DesktopObject->pDeskInfo->szDesktopName;
+ nDataSize = (wcslen(DesktopObject->pDeskInfo->szDesktopName) + 1) * sizeof(WCHAR);
+ Status = STATUS_SUCCESS;
+ }
+ else
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ }
+ break;
+ }
- case UOI_USER_SID:
- Status = STATUS_NOT_IMPLEMENTED;
- ERR("UOI_USER_SID unimplemented!\n");
- break;
+ case UOI_TYPE:
+ {
+ if (WinStaObject != NULL)
+ {
+ pvData = L"WindowStation";
+ nDataSize = sizeof(L"WindowStation");
+ Status = STATUS_SUCCESS;
+ }
+ else if (DesktopObject != NULL)
+ {
+ pvData = L"Desktop";
+ nDataSize = sizeof(L"Desktop");
+ Status = STATUS_SUCCESS;
+ }
+ else
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ }
+ break;
+ }
- default:
- Status = STATUS_INVALID_PARAMETER;
- break;
- }
+ case UOI_USER_SID:
+ Status = STATUS_NOT_IMPLEMENTED;
+ ERR("UOI_USER_SID unimplemented!\n");
+ break;
+
+ default:
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
Exit:
- if (Status == STATUS_SUCCESS && nLength < nDataSize)
- Status = STATUS_BUFFER_TOO_SMALL;
-
- _SEH2_TRY
- {
- if (nLengthNeeded)
- *nLengthNeeded = nDataSize;
-
- /* try to copy data to caller */
- if (Status == STATUS_SUCCESS)
- {
- TRACE("Trying to copy data to caller (len = %lu, len needed = %lu)\n", nLength, nDataSize);
- RtlCopyMemory(pvInformation, pvData, nDataSize);
- }
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- Status = _SEH2_GetExceptionCode();
- }
- _SEH2_END;
-
- /* release objects */
- if (WinStaObject != NULL)
- ObDereferenceObject(WinStaObject);
- if (DesktopObject != NULL)
- ObDereferenceObject(DesktopObject);
-
- if (!NT_SUCCESS(Status))
- {
- SetLastNtError(Status);
- return FALSE;
- }
-
- return TRUE;
+ if ((Status == STATUS_SUCCESS) && (nLength < nDataSize))
+ Status = STATUS_BUFFER_TOO_SMALL;
+
+ _SEH2_TRY
+ {
+ if (nLengthNeeded)
+ *nLengthNeeded = nDataSize;
+
+ /* Try to copy data to caller */
+ if (Status == STATUS_SUCCESS)
+ {
+ TRACE("Trying to copy data to caller (len = %lu, len needed = %lu)\n", nLength, nDataSize);
+ RtlCopyMemory(pvInformation, pvData, nDataSize);
+ }
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+ /* Release objects */
+ if (DesktopObject != NULL)
+ ObDereferenceObject(DesktopObject);
+ if (WinStaObject != NULL)
+ ObDereferenceObject(WinStaObject);
+
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ return FALSE;
+ }
+
+ return TRUE;
}
/*
BOOL
APIENTRY
NtUserSetObjectInformation(
- HANDLE hObject,
- DWORD nIndex,
- PVOID pvInformation,
- DWORD nLength)
+ HANDLE hObject,
+ DWORD nIndex,
+ PVOID pvInformation,
+ DWORD nLength)
{
- /* FIXME: ZwQueryObject */
- /* FIXME: ZwSetInformationObject */
- SetLastNtError(STATUS_UNSUCCESSFUL);
- return FALSE;
+ /* FIXME: ZwQueryObject */
+ /* FIXME: ZwSetInformationObject */
+ SetLastNtError(STATUS_UNSUCCESSFUL);
+ return FALSE;
}
HWINSTA APIENTRY
NtUserGetProcessWindowStation(VOID)
{
- return UserGetProcessWindowStation();
+ return UserGetProcessWindowStation();
}
BOOL FASTCALL
PPROCESSINFO ppi;
NTSTATUS Status;
HWINSTA hwinstaOld;
+ OBJECT_HANDLE_INFORMATION ObjectHandleInfo;
PWINSTATION_OBJECT NewWinSta = NULL, OldWinSta;
ppi = PsGetCurrentProcessWin32Process();
/* Reference the new window station */
- if(hWindowStation !=NULL)
- {
- Status = IntValidateWindowStationHandle( hWindowStation,
- KernelMode,
- 0,
- &NewWinSta);
- if (!NT_SUCCESS(Status))
- {
- TRACE("Validation of window station handle (%p) failed\n",
- hWindowStation);
- SetLastNtError(Status);
- return FALSE;
- }
- }
-
- OldWinSta = ppi->prpwinsta;
- hwinstaOld = PsGetProcessWin32WindowStation(ppi->peProcess);
-
- /* Dereference the previous window station */
- if(OldWinSta != NULL)
- {
- ObDereferenceObject(OldWinSta);
- }
-
- /* Check if we have a stale handle (it should happen for console apps) */
- if(hwinstaOld != ppi->hwinsta)
- {
- ObCloseHandle(hwinstaOld, UserMode);
- }
-
- /*
- * FIXME: Don't allow changing the window station if there are threads that are attached to desktops and own GUI objects.
- */
-
- PsSetProcessWindowStation(ppi->peProcess, hWindowStation);
-
- ppi->prpwinsta = NewWinSta;
- ppi->hwinsta = hWindowStation;
-
- return TRUE;
+ if (hWindowStation != NULL)
+ {
+ Status = IntValidateWindowStationHandle(hWindowStation,
+ UserMode,
+ 0,
+ &NewWinSta,
+ &ObjectHandleInfo);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("Validation of window station handle (%p) failed\n",
+ hWindowStation);
+ SetLastNtError(Status);
+ return FALSE;
+ }
+ }
+
+ OldWinSta = ppi->prpwinsta;
+ hwinstaOld = PsGetProcessWin32WindowStation(ppi->peProcess);
+
+ /* Dereference the previous window station */
+ if (OldWinSta != NULL)
+ {
+ ObDereferenceObject(OldWinSta);
+ }
+
+ /* Check if we have a stale handle (it should happen for console apps) */
+ if (hwinstaOld != ppi->hwinsta)
+ {
+ ObCloseHandle(hwinstaOld, UserMode);
+ }
+
+ /*
+ * FIXME: Don't allow changing the window station if there are threads that are attached to desktops and own GUI objects.
+ */
+
+ PsSetProcessWindowStation(ppi->peProcess, hWindowStation);
+
+ ppi->prpwinsta = NewWinSta;
+ ppi->hwinsta = hWindowStation;
+ ppi->amwinsta = hWindowStation != NULL ? ObjectHandleInfo.GrantedAccess : 0;
+ TRACE("WS : Granted Access 0x%08lx\n",ppi->amwinsta);
+
+ if (RtlAreAllAccessesGranted(ppi->amwinsta, WINSTA_READSCREEN))
+ {
+ ppi->W32PF_flags |= W32PF_READSCREENACCESSGRANTED;
+ }
+ else
+ {
+ ppi->W32PF_flags &= ~W32PF_READSCREENACCESSGRANTED;
+ }
+
+ if (NewWinSta && !(NewWinSta->Flags & WSS_NOIO))
+ {
+ ppi->W32PF_flags |= W32PF_IOWINSTA;
+ }
+ else // Might be closed if the handle is null.
+ {
+ ppi->W32PF_flags &= ~W32PF_IOWINSTA;
+ }
+ return TRUE;
}
/*
BOOL APIENTRY
NtUserLockWindowStation(HWINSTA hWindowStation)
{
- PWINSTATION_OBJECT Object;
- NTSTATUS Status;
-
- TRACE("About to set process window station with handle (%p)\n",
- hWindowStation);
-
- if(PsGetCurrentProcessWin32Process() != LogonProcess)
- {
- ERR("Unauthorized process attempted to lock the window station!\n");
- EngSetLastError(ERROR_ACCESS_DENIED);
- return FALSE;
- }
-
- Status = IntValidateWindowStationHandle(
- hWindowStation,
- KernelMode,
- 0,
- &Object);
- if (!NT_SUCCESS(Status))
- {
- TRACE("Validation of window station handle (%p) failed\n",
- hWindowStation);
- SetLastNtError(Status);
- return FALSE;
- }
-
- Object->Flags |= WSS_LOCKED;
-
- ObDereferenceObject(Object);
- return TRUE;
+ PWINSTATION_OBJECT Object;
+ NTSTATUS Status;
+
+ TRACE("About to set process window station with handle (%p)\n",
+ hWindowStation);
+
+ if (gpidLogon != PsGetCurrentProcessId())
+ {
+ ERR("Unauthorized process attempted to lock the window station!\n");
+ EngSetLastError(ERROR_ACCESS_DENIED);
+ return FALSE;
+ }
+
+ Status = IntValidateWindowStationHandle(hWindowStation,
+ UserMode,
+ 0,
+ &Object,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("Validation of window station handle (%p) failed\n",
+ hWindowStation);
+ SetLastNtError(Status);
+ return FALSE;
+ }
+
+ Object->Flags |= WSS_LOCKED;
+
+ ObDereferenceObject(Object);
+ return TRUE;
}
/*
BOOL APIENTRY
NtUserUnlockWindowStation(HWINSTA hWindowStation)
{
- PWINSTATION_OBJECT Object;
- NTSTATUS Status;
- BOOL Ret;
-
- TRACE("About to set process window station with handle (%p)\n",
- hWindowStation);
-
- if(PsGetCurrentProcessWin32Process() != LogonProcess)
- {
- ERR("Unauthorized process attempted to unlock the window station!\n");
- EngSetLastError(ERROR_ACCESS_DENIED);
- return FALSE;
- }
-
- Status = IntValidateWindowStationHandle(
- hWindowStation,
- KernelMode,
- 0,
- &Object);
- if (!NT_SUCCESS(Status))
- {
- TRACE("Validation of window station handle (%p) failed\n",
- hWindowStation);
- SetLastNtError(Status);
- return FALSE;
- }
-
- Ret = (Object->Flags & WSS_LOCKED) == WSS_LOCKED;
- Object->Flags &= ~WSS_LOCKED;
-
- ObDereferenceObject(Object);
- return Ret;
+ PWINSTATION_OBJECT Object;
+ NTSTATUS Status;
+ BOOL Ret;
+
+ TRACE("About to set process window station with handle (%p)\n",
+ hWindowStation);
+
+ if (gpidLogon != PsGetCurrentProcessId())
+ {
+ ERR("Unauthorized process attempted to unlock the window station!\n");
+ EngSetLastError(ERROR_ACCESS_DENIED);
+ return FALSE;
+ }
+
+ Status = IntValidateWindowStationHandle(hWindowStation,
+ UserMode,
+ 0,
+ &Object,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ TRACE("Validation of window station handle (%p) failed\n",
+ hWindowStation);
+ SetLastNtError(Status);
+ return FALSE;
+ }
+
+ Ret = (Object->Flags & WSS_LOCKED) == WSS_LOCKED;
+ Object->Flags &= ~WSS_LOCKED;
+
+ ObDereferenceObject(Object);
+ return Ret;
}
static NTSTATUS FASTCALL
BuildWindowStationNameList(
- ULONG dwSize,
- PVOID lpBuffer,
- PULONG pRequiredSize)
+ ULONG dwSize,
+ PVOID lpBuffer,
+ PULONG pRequiredSize)
{
- OBJECT_ATTRIBUTES ObjectAttributes;
- NTSTATUS Status;
- HANDLE DirectoryHandle;
- char InitialBuffer[256], *Buffer;
- ULONG Context, ReturnLength, BufferSize;
- DWORD EntryCount;
- POBJECT_DIRECTORY_INFORMATION DirEntry;
- WCHAR NullWchar;
-
- /*
- * Try to open the directory.
- */
- InitializeObjectAttributes(
- &ObjectAttributes,
- &gustrWindowStationsDir,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
-
- Status = ZwOpenDirectoryObject(
- &DirectoryHandle,
- DIRECTORY_QUERY,
- &ObjectAttributes);
-
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
-
- /* First try to query the directory using a fixed-size buffer */
- Context = 0;
- Buffer = NULL;
- Status = ZwQueryDirectoryObject(DirectoryHandle, InitialBuffer, sizeof(InitialBuffer),
- FALSE, TRUE, &Context, &ReturnLength);
- if (NT_SUCCESS(Status))
- {
- if (STATUS_NO_MORE_ENTRIES == ZwQueryDirectoryObject(DirectoryHandle, NULL, 0, FALSE,
- FALSE, &Context, NULL))
- {
- /* Our fixed-size buffer is large enough */
- Buffer = InitialBuffer;
- }
- }
-
- if (NULL == Buffer)
- {
- /* Need a larger buffer, check how large exactly */
- Status = ZwQueryDirectoryObject(DirectoryHandle, NULL, 0, FALSE, TRUE, &Context,
- &ReturnLength);
- if (STATUS_BUFFER_TOO_SMALL == Status)
- {
- ObDereferenceObject(DirectoryHandle);
- return STATUS_NO_MEMORY;
- }
-
- BufferSize = ReturnLength;
- Buffer = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_WINSTA);
- if (NULL == Buffer)
- {
- ObDereferenceObject(DirectoryHandle);
- return STATUS_NO_MEMORY;
- }
-
- /* We should have a sufficiently large buffer now */
- Context = 0;
- Status = ZwQueryDirectoryObject(DirectoryHandle, Buffer, BufferSize,
- FALSE, TRUE, &Context, &ReturnLength);
- if (! NT_SUCCESS(Status) ||
- STATUS_NO_MORE_ENTRIES != ZwQueryDirectoryObject(DirectoryHandle, NULL, 0, FALSE,
- FALSE, &Context, NULL))
- {
- /* Something went wrong, maybe someone added a directory entry? Just give up. */
- ExFreePoolWithTag(Buffer, TAG_WINSTA);
- ObDereferenceObject(DirectoryHandle);
- return NT_SUCCESS(Status) ? STATUS_INTERNAL_ERROR : Status;
- }
- }
-
- ZwClose(DirectoryHandle);
-
- /*
- * Count the required size of buffer.
- */
- ReturnLength = sizeof(DWORD);
- EntryCount = 0;
- for (DirEntry = (POBJECT_DIRECTORY_INFORMATION) Buffer; 0 != DirEntry->Name.Length;
- DirEntry++)
- {
- ReturnLength += DirEntry->Name.Length + sizeof(WCHAR);
- EntryCount++;
- }
- TRACE("Required size: %lu Entry count: %lu\n", ReturnLength, EntryCount);
- if (NULL != pRequiredSize)
- {
- Status = MmCopyToCaller(pRequiredSize, &ReturnLength, sizeof(ULONG));
- if (! NT_SUCCESS(Status))
- {
- if (Buffer != InitialBuffer)
- {
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ NTSTATUS Status;
+ HANDLE DirectoryHandle;
+ char InitialBuffer[256], *Buffer;
+ ULONG Context, ReturnLength, BufferSize;
+ DWORD EntryCount;
+ POBJECT_DIRECTORY_INFORMATION DirEntry;
+ WCHAR NullWchar;
+
+ /*
+ * Try to open the directory.
+ */
+ InitializeObjectAttributes(&ObjectAttributes,
+ &gustrWindowStationsDir,
+ OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
+ NULL,
+ NULL);
+
+ Status = ZwOpenDirectoryObject(&DirectoryHandle,
+ DIRECTORY_QUERY,
+ &ObjectAttributes);
+
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ /* First try to query the directory using a fixed-size buffer */
+ Context = 0;
+ Buffer = NULL;
+ Status = ZwQueryDirectoryObject(DirectoryHandle,
+ InitialBuffer,
+ sizeof(InitialBuffer),
+ FALSE,
+ TRUE,
+ &Context,
+ &ReturnLength);
+ if (NT_SUCCESS(Status))
+ {
+ if (STATUS_NO_MORE_ENTRIES == ZwQueryDirectoryObject(DirectoryHandle, NULL, 0, FALSE,
+ FALSE, &Context, NULL))
+ {
+ /* Our fixed-size buffer is large enough */
+ Buffer = InitialBuffer;
+ }
+ }
+
+ if (NULL == Buffer)
+ {
+ /* Need a larger buffer, check how large exactly */
+ Status = ZwQueryDirectoryObject(DirectoryHandle, NULL, 0, FALSE, TRUE, &Context,
+ &ReturnLength);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("ZwQueryDirectoryObject failed\n");
+ ZwClose(DirectoryHandle);
+ return Status;
+ }
+
+ BufferSize = ReturnLength;
+ Buffer = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_WINSTA);
+ if (NULL == Buffer)
+ {
+ ZwClose(DirectoryHandle);
+ return STATUS_NO_MEMORY;
+ }
+
+ /* We should have a sufficiently large buffer now */
+ Context = 0;
+ Status = ZwQueryDirectoryObject(DirectoryHandle, Buffer, BufferSize,
+ FALSE, TRUE, &Context, &ReturnLength);
+ if (! NT_SUCCESS(Status) ||
+ STATUS_NO_MORE_ENTRIES != ZwQueryDirectoryObject(DirectoryHandle, NULL, 0, FALSE,
+ FALSE, &Context, NULL))
+ {
+ /* Something went wrong, maybe someone added a directory entry? Just give up. */
ExFreePoolWithTag(Buffer, TAG_WINSTA);
- }
- return STATUS_BUFFER_TOO_SMALL;
- }
- }
-
- /*
- * Check if the supplied buffer is large enough.
- */
- if (dwSize < ReturnLength)
- {
- if (Buffer != InitialBuffer)
- {
- ExFreePoolWithTag(Buffer, TAG_WINSTA);
- }
- return STATUS_BUFFER_TOO_SMALL;
- }
-
- /*
- * Generate the resulting buffer contents.
- */
- Status = MmCopyToCaller(lpBuffer, &EntryCount, sizeof(DWORD));
- if (! NT_SUCCESS(Status))
- {
- if (Buffer != InitialBuffer)
- {
- ExFreePoolWithTag(Buffer, TAG_WINSTA);
- }
- return Status;
- }
- lpBuffer = (PVOID) ((PCHAR) lpBuffer + sizeof(DWORD));
-
- NullWchar = L'\0';
- for (DirEntry = (POBJECT_DIRECTORY_INFORMATION) Buffer; 0 != DirEntry->Name.Length;
+ ZwClose(DirectoryHandle);
+ return NT_SUCCESS(Status) ? STATUS_INTERNAL_ERROR : Status;
+ }
+ }
+
+ ZwClose(DirectoryHandle);
+
+ /*
+ * Count the required size of buffer.
+ */
+ ReturnLength = sizeof(DWORD);
+ EntryCount = 0;
+ for (DirEntry = (POBJECT_DIRECTORY_INFORMATION) Buffer;
+ 0 != DirEntry->Name.Length;
DirEntry++)
- {
- Status = MmCopyToCaller(lpBuffer, DirEntry->Name.Buffer, DirEntry->Name.Length);
- if (! NT_SUCCESS(Status))
- {
- if (Buffer != InitialBuffer)
- {
+ {
+ ReturnLength += DirEntry->Name.Length + sizeof(WCHAR);
+ EntryCount++;
+ }
+ TRACE("Required size: %lu Entry count: %lu\n", ReturnLength, EntryCount);
+ if (NULL != pRequiredSize)
+ {
+ Status = MmCopyToCaller(pRequiredSize, &ReturnLength, sizeof(ULONG));
+ if (! NT_SUCCESS(Status))
+ {
+ if (Buffer != InitialBuffer)
+ {
+ ExFreePoolWithTag(Buffer, TAG_WINSTA);
+ }
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+ }
+
+ /*
+ * Check if the supplied buffer is large enough.
+ */
+ if (dwSize < ReturnLength)
+ {
+ if (Buffer != InitialBuffer)
+ {
ExFreePoolWithTag(Buffer, TAG_WINSTA);
- }
- return Status;
- }
- lpBuffer = (PVOID) ((PCHAR) lpBuffer + DirEntry->Name.Length);
- Status = MmCopyToCaller(lpBuffer, &NullWchar, sizeof(WCHAR));
- if (! NT_SUCCESS(Status))
- {
- if (Buffer != InitialBuffer)
- {
+ }
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+
+ /*
+ * Generate the resulting buffer contents.
+ */
+ Status = MmCopyToCaller(lpBuffer, &EntryCount, sizeof(DWORD));
+ if (! NT_SUCCESS(Status))
+ {
+ if (Buffer != InitialBuffer)
+ {
ExFreePoolWithTag(Buffer, TAG_WINSTA);
- }
- return Status;
- }
- lpBuffer = (PVOID) ((PCHAR) lpBuffer + sizeof(WCHAR));
- }
-
- /*
- * Clean up
- */
- if (Buffer != InitialBuffer)
- {
- ExFreePoolWithTag(Buffer, TAG_WINSTA);
- }
-
- return STATUS_SUCCESS;
+ }
+ return Status;
+ }
+ lpBuffer = (PVOID) ((PCHAR) lpBuffer + sizeof(DWORD));
+
+ NullWchar = L'\0';
+ for (DirEntry = (POBJECT_DIRECTORY_INFORMATION) Buffer;
+ 0 != DirEntry->Name.Length;
+ DirEntry++)
+ {
+ Status = MmCopyToCaller(lpBuffer, DirEntry->Name.Buffer, DirEntry->Name.Length);
+ if (! NT_SUCCESS(Status))
+ {
+ if (Buffer != InitialBuffer)
+ {
+ ExFreePoolWithTag(Buffer, TAG_WINSTA);
+ }
+ return Status;
+ }
+ lpBuffer = (PVOID) ((PCHAR) lpBuffer + DirEntry->Name.Length);
+ Status = MmCopyToCaller(lpBuffer, &NullWchar, sizeof(WCHAR));
+ if (! NT_SUCCESS(Status))
+ {
+ if (Buffer != InitialBuffer)
+ {
+ ExFreePoolWithTag(Buffer, TAG_WINSTA);
+ }
+ return Status;
+ }
+ lpBuffer = (PVOID) ((PCHAR) lpBuffer + sizeof(WCHAR));
+ }
+
+ /*
+ * Clean up
+ */
+ if (Buffer != InitialBuffer)
+ {
+ ExFreePoolWithTag(Buffer, TAG_WINSTA);
+ }
+
+ return STATUS_SUCCESS;
}
static NTSTATUS FASTCALL
BuildDesktopNameList(
- HWINSTA hWindowStation,
- ULONG dwSize,
- PVOID lpBuffer,
- PULONG pRequiredSize)
+ HWINSTA hWindowStation,
+ ULONG dwSize,
+ PVOID lpBuffer,
+ PULONG pRequiredSize)
{
- NTSTATUS Status;
- PWINSTATION_OBJECT WindowStation;
- KIRQL OldLevel;
- PLIST_ENTRY DesktopEntry;
- PDESKTOP DesktopObject;
- DWORD EntryCount;
- ULONG ReturnLength;
- WCHAR NullWchar;
- PUNICODE_STRING DesktopName;
-
- Status = IntValidateWindowStationHandle(hWindowStation,
- KernelMode,
- 0,
- &WindowStation);
- if (! NT_SUCCESS(Status))
- {
- return Status;
- }
-
- KeAcquireSpinLock(&WindowStation->Lock, &OldLevel);
-
- /*
- * Count the required size of buffer.
- */
- ReturnLength = sizeof(DWORD);
- EntryCount = 0;
- for (DesktopEntry = WindowStation->DesktopListHead.Flink;
+ NTSTATUS Status;
+ PWINSTATION_OBJECT WindowStation;
+ PLIST_ENTRY DesktopEntry;
+ PDESKTOP DesktopObject;
+ DWORD EntryCount;
+ ULONG ReturnLength;
+ WCHAR NullWchar;
+ UNICODE_STRING DesktopName;
+
+ Status = IntValidateWindowStationHandle(hWindowStation,
+ UserMode,
+ 0,
+ &WindowStation,
+ 0);
+ if (! NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ /*
+ * Count the required size of buffer.
+ */
+ ReturnLength = sizeof(DWORD);
+ EntryCount = 0;
+ for (DesktopEntry = WindowStation->DesktopListHead.Flink;
DesktopEntry != &WindowStation->DesktopListHead;
DesktopEntry = DesktopEntry->Flink)
- {
- DesktopObject = CONTAINING_RECORD(DesktopEntry, DESKTOP, ListEntry);
- DesktopName = GET_DESKTOP_NAME(DesktopObject);
- if (DesktopName) ReturnLength += DesktopName->Length + sizeof(WCHAR);
- EntryCount++;
- }
- TRACE("Required size: %lu Entry count: %lu\n", ReturnLength, EntryCount);
- if (NULL != pRequiredSize)
- {
- Status = MmCopyToCaller(pRequiredSize, &ReturnLength, sizeof(ULONG));
- if (! NT_SUCCESS(Status))
- {
- KeReleaseSpinLock(&WindowStation->Lock, OldLevel);
- ObDereferenceObject(WindowStation);
- return STATUS_BUFFER_TOO_SMALL;
- }
- }
-
- /*
- * Check if the supplied buffer is large enough.
- */
- if (dwSize < ReturnLength)
- {
- KeReleaseSpinLock(&WindowStation->Lock, OldLevel);
- ObDereferenceObject(WindowStation);
- return STATUS_BUFFER_TOO_SMALL;
- }
-
- /*
- * Generate the resulting buffer contents.
- */
- Status = MmCopyToCaller(lpBuffer, &EntryCount, sizeof(DWORD));
- if (! NT_SUCCESS(Status))
- {
- KeReleaseSpinLock(&WindowStation->Lock, OldLevel);
- ObDereferenceObject(WindowStation);
- return Status;
- }
- lpBuffer = (PVOID) ((PCHAR) lpBuffer + sizeof(DWORD));
-
- NullWchar = L'\0';
- for (DesktopEntry = WindowStation->DesktopListHead.Flink;
+ {
+ DesktopObject = CONTAINING_RECORD(DesktopEntry, DESKTOP, ListEntry);
+ RtlInitUnicodeString(&DesktopName, DesktopObject->pDeskInfo->szDesktopName);
+ ReturnLength += DesktopName.Length + sizeof(WCHAR);
+ EntryCount++;
+ }
+ TRACE("Required size: %lu Entry count: %lu\n", ReturnLength, EntryCount);
+ if (NULL != pRequiredSize)
+ {
+ Status = MmCopyToCaller(pRequiredSize, &ReturnLength, sizeof(ULONG));
+ if (! NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(WindowStation);
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+ }
+
+ /*
+ * Check if the supplied buffer is large enough.
+ */
+ if (dwSize < ReturnLength)
+ {
+ ObDereferenceObject(WindowStation);
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+
+ /*
+ * Generate the resulting buffer contents.
+ */
+ Status = MmCopyToCaller(lpBuffer, &EntryCount, sizeof(DWORD));
+ if (! NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(WindowStation);
+ return Status;
+ }
+ lpBuffer = (PVOID) ((PCHAR) lpBuffer + sizeof(DWORD));
+
+ NullWchar = L'\0';
+ for (DesktopEntry = WindowStation->DesktopListHead.Flink;
DesktopEntry != &WindowStation->DesktopListHead;
DesktopEntry = DesktopEntry->Flink)
- {
- DesktopObject = CONTAINING_RECORD(DesktopEntry, DESKTOP, ListEntry);
- _PRAGMA_WARNING_SUPPRESS(__WARNING_DEREF_NULL_PTR)
- DesktopName = GET_DESKTOP_NAME(DesktopObject);/// @todo Don't mess around with the object headers!
- if (!DesktopName) continue;
-
- Status = MmCopyToCaller(lpBuffer, DesktopName->Buffer, DesktopName->Length);
- if (! NT_SUCCESS(Status))
- {
- KeReleaseSpinLock(&WindowStation->Lock, OldLevel);
- ObDereferenceObject(WindowStation);
- return Status;
- }
- lpBuffer = (PVOID) ((PCHAR)lpBuffer + DesktopName->Length);
- Status = MmCopyToCaller(lpBuffer, &NullWchar, sizeof(WCHAR));
- if (! NT_SUCCESS(Status))
- {
- KeReleaseSpinLock(&WindowStation->Lock, OldLevel);
- ObDereferenceObject(WindowStation);
- return Status;
- }
- lpBuffer = (PVOID) ((PCHAR) lpBuffer + sizeof(WCHAR));
- }
-
- /*
- * Clean up
- */
- KeReleaseSpinLock(&WindowStation->Lock, OldLevel);
- ObDereferenceObject(WindowStation);
-
- return STATUS_SUCCESS;
+ {
+ DesktopObject = CONTAINING_RECORD(DesktopEntry, DESKTOP, ListEntry);
+ RtlInitUnicodeString(&DesktopName, DesktopObject->pDeskInfo->szDesktopName);
+ Status = MmCopyToCaller(lpBuffer, DesktopName.Buffer, DesktopName.Length);
+ if (! NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(WindowStation);
+ return Status;
+ }
+ lpBuffer = (PVOID) ((PCHAR)lpBuffer + DesktopName.Length);
+ Status = MmCopyToCaller(lpBuffer, &NullWchar, sizeof(WCHAR));
+ if (! NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(WindowStation);
+ return Status;
+ }
+ lpBuffer = (PVOID) ((PCHAR) lpBuffer + sizeof(WCHAR));
+ }
+
+ /*
+ * Clean up and return
+ */
+ ObDereferenceObject(WindowStation);
+ return STATUS_SUCCESS;
}
/*
* Size of buffer passed by caller.
*
* lpBuffer
- * Buffer passed by caller. If the function succedes, the buffer is
+ * Buffer passed by caller. If the function succeeds, the buffer is
* filled with window station/desktop count (in first DWORD) and
* NULL-terminated window station/desktop names.
*
* pRequiredSize
- * If the function suceedes, this is the number of bytes copied.
+ * If the function succeeds, this is the number of bytes copied.
* Otherwise it's size of buffer needed for function to succeed.
*
* Status
NTSTATUS APIENTRY
NtUserBuildNameList(
- HWINSTA hWindowStation,
- ULONG dwSize,
- PVOID lpBuffer,
- PULONG pRequiredSize)
+ HWINSTA hWindowStation,
+ ULONG dwSize,
+ PVOID lpBuffer,
+ PULONG pRequiredSize)
{
- /* The WindowStation name list and desktop name list are build in completely
- different ways. Call the appropriate function */
- return NULL == hWindowStation ? BuildWindowStationNameList(dwSize, lpBuffer, pRequiredSize) :
- BuildDesktopNameList(hWindowStation, dwSize, lpBuffer, pRequiredSize);
+ /* The WindowStation name list and desktop name list are build in completely
+ different ways. Call the appropriate function */
+ return NULL == hWindowStation ? BuildWindowStationNameList(dwSize, lpBuffer, pRequiredSize) :
+ BuildDesktopNameList(hWindowStation, dwSize, lpBuffer, pRequiredSize);
}
/*
BOOL APIENTRY
NtUserSetLogonNotifyWindow(HWND hWnd)
{
- if(LogonProcess != PsGetCurrentProcessWin32Process())
+ if (gpidLogon != PsGetCurrentProcessId())
{
return FALSE;
}
- if(!IntIsWindow(hWnd))
+ if (!IntIsWindow(hWnd))
{
return FALSE;
}
UserLeave();
- return ret;
+ return ret;
}
+BOOL
+NTAPI
+NtUserSetWindowStationUser(
+ IN HWINSTA hWindowStation,
+ IN PLUID pluid,
+ IN PSID psid OPTIONAL,
+ IN DWORD size)
+{
+ BOOL Ret = FALSE;
+ NTSTATUS Status;
+ PWINSTATION_OBJECT WindowStation = NULL;
+ LUID luidUser;
+
+ UserEnterExclusive();
+
+ if (gpidLogon != PsGetCurrentProcessId())
+ {
+ EngSetLastError(ERROR_ACCESS_DENIED);
+ goto Leave;
+ }
+
+ /* Validate the window station */
+ Status = IntValidateWindowStationHandle(hWindowStation,
+ UserMode,
+ 0,
+ &WindowStation,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ goto Leave;
+ }
+
+ /* Capture the user LUID */
+ _SEH2_TRY
+ {
+ ProbeForRead(pluid, sizeof(LUID), 1);
+ luidUser = *pluid;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ _SEH2_YIELD(goto Leave);
+ }
+ _SEH2_END;
+
+ /* Reset the window station user LUID */
+ RtlZeroMemory(&WindowStation->luidUser, sizeof(LUID));
+
+ /* Reset the window station user SID */
+ if (WindowStation->psidUser)
+ {
+ ExFreePoolWithTag(WindowStation->psidUser, USERTAG_SECURITY);
+ WindowStation->psidUser = NULL;
+ }
+
+ /* Copy the new user SID if one has been provided */
+ if (psid)
+ {
+ WindowStation->psidUser = ExAllocatePoolWithTag(PagedPool, size, USERTAG_SECURITY);
+ if (WindowStation->psidUser == NULL)
+ {
+ EngSetLastError(ERROR_OUTOFMEMORY);
+ goto Leave;
+ }
+
+ Status = STATUS_SUCCESS;
+ _SEH2_TRY
+ {
+ ProbeForRead(psid, size, 1);
+ RtlCopyMemory(WindowStation->psidUser, psid, size);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+ if (!NT_SUCCESS(Status))
+ {
+ ExFreePoolWithTag(WindowStation->psidUser, USERTAG_SECURITY);
+ WindowStation->psidUser = NULL;
+ goto Leave;
+ }
+ }
+
+ /* Copy the new user LUID */
+ WindowStation->luidUser = luidUser;
+
+ Ret = TRUE;
+
+Leave:
+ if (WindowStation)
+ ObDereferenceObject(WindowStation);
+
+ UserLeave();
+ return Ret;
+}
+
+
/* EOF */