BOOL APIENTRY NtUserLockWindowStation(HWINSTA hWindowStation) { 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 FASTCALL UserSetProcessWindowStation(HWINSTA hWindowStation) { PPROCESSINFO ppi; NTSTATUS Status; HWINSTA hwinstaOld; 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 (0x%X) 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; }
static PWINSTATION_OBJECT FASTCALL IntGetWinStaForCbAccess(VOID) { HWINSTA hWinSta; PWINSTATION_OBJECT pWinStaObj; NTSTATUS Status; hWinSta = UserGetProcessWindowStation(); Status = IntValidateWindowStationHandle(hWinSta, KernelMode, WINSTA_ACCESSCLIPBOARD, &pWinStaObj, 0); if (!NT_SUCCESS(Status)) { ERR("Cannot open winsta\n"); SetLastNtError(Status); return NULL; } return pWinStaObj; }
BOOL APIENTRY NtUserCloseWindowStation( HWINSTA hWinSta) { PWINSTATION_OBJECT Object; NTSTATUS Status; TRACE("NtUserCloseWindowStation called (%p)\n", hWinSta); if (hWinSta == UserGetProcessWindowStation()) { ERR("Attempted to close process window station\n"); return FALSE; } Status = IntValidateWindowStationHandle(hWinSta, UserMode, 0, &Object, 0); if (!NT_SUCCESS(Status)) { ERR("Validation of window station handle (%p) failed\n", hWinSta); return FALSE; } ObDereferenceObject(Object); TRACE("Closing window station handle (%p)\n", hWinSta); Status = ObCloseHandle(hWinSta, UserMode); if (!NT_SUCCESS(Status)) { SetLastNtError(Status); return FALSE; } return TRUE; }
BOOL APIENTRY NtUserUnlockWindowStation(HWINSTA hWindowStation) { PWINSTATION_OBJECT Object; NTSTATUS Status; BOOL Ret; TRACE("About to set process window station with handle (0x%X)\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 (0x%X) failed\n", hWindowStation); SetLastNtError(Status); return FALSE; } Ret = (Object->Flags & WSS_LOCKED) == WSS_LOCKED; Object->Flags &= ~WSS_LOCKED; ObDereferenceObject(Object); return Ret; }
BOOL FASTCALL UserSetProcessWindowStation(HWINSTA hWindowStation) { 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, 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 NtUserSetWindowStationUser( HWINSTA hWindowStation, PLUID pluid, PSID psid, DWORD size) { NTSTATUS Status; PWINSTATION_OBJECT WindowStation = NULL; BOOL Ret = FALSE; UserEnterExclusive(); if (gpidLogon != PsGetCurrentProcessId()) { EngSetLastError(ERROR_ACCESS_DENIED); goto Leave; } Status = IntValidateWindowStationHandle(hWindowStation, UserMode, 0, &WindowStation, 0); if (!NT_SUCCESS(Status)) { goto Leave; } if (WindowStation->psidUser) { ExFreePoolWithTag(WindowStation->psidUser, USERTAG_SECURITY); } WindowStation->psidUser = ExAllocatePoolWithTag(PagedPool, size, USERTAG_SECURITY); if (WindowStation->psidUser == NULL) { EngSetLastError(ERROR_OUTOFMEMORY); goto Leave; } _SEH2_TRY { ProbeForRead( psid, size, 1); ProbeForRead( pluid, sizeof(LUID), 1); RtlCopyMemory(WindowStation->psidUser, psid, size); WindowStation->luidUser = *pluid; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END; if (!NT_SUCCESS(Status)) { ExFreePoolWithTag(WindowStation->psidUser, USERTAG_SECURITY); WindowStation->psidUser = 0; goto Leave; } Ret = TRUE; Leave: if (WindowStation) ObDereferenceObject(WindowStation); UserLeave(); return Ret; }
static NTSTATUS FASTCALL BuildDesktopNameList( HWINSTA hWindowStation, ULONG dwSize, PVOID lpBuffer, PULONG pRequiredSize) { 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); 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); 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; }
static NTSTATUS FASTCALL BuildDesktopNameList( 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; 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: %d Entry count: %d\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; 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; }