* 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
/* GLOBALS *******************************************************************/
-/* Currently active window station */
+/*
+ * The currently active window station. This is the
+ * only one interactive window station on the system.
+ */
PWINSTATION_OBJECT InputWindowStation = NULL;
/* Winlogon SAS window */
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;
- WCHAR wstrWindowStationsDir[MAX_PATH];
+ PPEB Peb;
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE hWinstaDir;
+ WCHAR wstrWindowStationsDir[MAX_PATH];
/* Create the WindowStations directory and cache its path for later use */
Peb = NtCurrentPeb();
}
else
{
- swprintf(wstrWindowStationsDir,
- L"%ws\\%lu%ws",
- SESSION_DIR,
- Peb->SessionId,
- WINSTA_OBJ_DIR);
+ Status = RtlStringCbPrintfW(wstrWindowStationsDir,
+ sizeof(wstrWindowStationsDir),
+ L"%ws\\%lu%ws",
+ SESSION_DIR,
+ Peb->SessionId,
+ WINSTA_OBJ_DIR);
+ if (!NT_SUCCESS(Status))
+ return Status;
if (!RtlCreateUnicodeString(&gustrWindowStationsDir, wstrWindowStationsDir))
{
}
}
- 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,
+ OBJ_KERNEL_HANDLE,
+ NULL,
+ NULL);
+ Status = ZwCreateDirectoryObject(&hWinstaDir, DIRECTORY_CREATE_OBJECT, &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 **********************************************************/
+/* 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);
- UserEmptyClipboardData(WinSta);
+ if (WinSta == InputWindowStation)
+ {
+ ERR("WARNING: Deleting the interactive window station '%wZ'!\n",
+ &(OBJECT_HEADER_TO_NAME_INFO(OBJECT_TO_OBJECT_HEADER(InputWindowStation))->Name));
+
+ /* Only Winlogon can close and delete the interactive window station */
+ ASSERT(gpidLogon == PsGetCurrentProcessId());
+
+ InputWindowStation = NULL;
+ }
- RtlDestroyAtomTable(WinSta->AtomTable);
+ WinSta->Flags |= WSS_DYING;
- RtlFreeUnicodeString(&WinSta->Name);
+ UserEmptyClipboardData(WinSta);
- return STATUS_SUCCESS;
+ RtlDestroyAtomTable(WinSta->AtomTable);
+
+ return STATUS_SUCCESS;
}
NTSTATUS
-APIENTRY
+NTAPI
IntWinStaObjectParse(
_In_ PVOID Parameters)
{
NTSTATUS
NTAPI
-IntWinstaOkToClose(
+IntWinStaOkToClose(
_In_ PVOID Parameters)
{
PWIN32_OKAYTOCLOSEMETHOD_PARAMETERS OkToCloseParameters = Parameters;
ppi = PsGetCurrentProcessWin32Process();
- if(ppi && (OkToCloseParameters->Handle == ppi->hwinsta))
+ if (ppi && (OkToCloseParameters->Handle == ppi->hwinsta))
{
return STATUS_ACCESS_DENIED;
}
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 system metrics */
+ InitMetrics();
+
+ /* Set new size of the monitor */
+ UserUpdateMonitorSize((HDEV)gppdevPrimary);
+
+ /* 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
+NTSTATUS
+FASTCALL
+IntCreateWindowStation(
+ OUT HWINSTA* phWinSta,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN KPROCESSOR_MODE AccessMode,
+ IN KPROCESSOR_MODE OwnerMode,
+ IN ACCESS_MASK dwDesiredAccess,
+ DWORD Unknown2,
+ DWORD Unknown3,
+ DWORD Unknown4,
+ DWORD Unknown5,
+ DWORD Unknown6)
+{
+ NTSTATUS Status;
+ HWINSTA hWinSta;
+ PWINSTATION_OBJECT WindowStation;
+
+ TRACE("IntCreateWindowStation called\n");
+
+ ASSERT(phWinSta);
+ *phWinSta = NULL;
+
+ Status = ObOpenObjectByName(ObjectAttributes,
+ ExWindowStationObjectType,
+ AccessMode,
+ NULL,
+ dwDesiredAccess,
+ NULL,
+ (PVOID*)&hWinSta);
+ if (NT_SUCCESS(Status))
+ {
+ TRACE("IntCreateWindowStation opened window station '%wZ'\n",
+ ObjectAttributes->ObjectName);
+ *phWinSta = hWinSta;
+ return Status;
+ }
+
+ /*
+ * No existing window station found, try to create a new one.
+ */
+
+ /* Create the window station object */
+ Status = ObCreateObject(AccessMode,
+ ExWindowStationObjectType,
+ ObjectAttributes,
+ OwnerMode,
+ NULL,
+ sizeof(WINSTATION_OBJECT),
+ 0,
+ 0,
+ (PVOID*)&WindowStation);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("ObCreateObject failed for window station '%wZ', Status 0x%08lx\n",
+ ObjectAttributes->ObjectName, Status);
+ SetLastNtError(Status);
+ return Status;
+ }
+
+ /* Initialize the window station */
+ RtlZeroMemory(WindowStation, sizeof(WINSTATION_OBJECT));
+
+ InitializeListHead(&WindowStation->DesktopListHead);
+ WindowStation->dwSessionId = NtCurrentPeb()->SessionId;
+ Status = RtlCreateAtomTable(37, &WindowStation->AtomTable);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("RtlCreateAtomTable failed for window station '%wZ', Status 0x%08lx\n",
+ ObjectAttributes->ObjectName, Status);
+ ObDereferenceObject(WindowStation);
+ SetLastNtError(Status);
+ return Status;
+ }
+
+ Status = ObInsertObject(WindowStation,
+ NULL,
+ dwDesiredAccess,
+ 0,
+ NULL,
+ (PVOID*)&hWinSta);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("ObInsertObject failed for window station, Status 0x%08lx\n", Status);
+ SetLastNtError(Status);
+ return Status;
+ }
+
+ // FIXME! TODO: Add this new window station to a linked list
+
+ if (InputWindowStation == NULL)
+ {
+ ERR("Initializing input window station\n");
+
+ /* Only Winlogon can create the interactive window station */
+ ASSERT(gpidLogon == PsGetCurrentProcessId());
+
+ InputWindowStation = WindowStation;
+ WindowStation->Flags &= ~WSS_NOIO;
+
+ InitCursorImpl();
+
+ UserCreateSystemThread(ST_DESKTOP_THREAD);
+ UserCreateSystemThread(ST_RIT);
+
+ /* Desktop functions require the desktop thread running so wait for it to initialize */
+ UserLeaveCo();
+ KeWaitForSingleObject(gpDesktopThreadStartedEvent,
+ UserRequest,
+ UserMode,
+ FALSE,
+ NULL);
+ UserEnterCo();
+ }
+ else
+ {
+ WindowStation->Flags |= WSS_NOIO;
+ }
+
+ TRACE("IntCreateWindowStation created window station '%wZ' object 0x%p handle 0x%p\n",
+ ObjectAttributes->ObjectName, WindowStation, hWinSta);
+
+ *phWinSta = hWinSta;
+ EngSetLastError(ERROR_SUCCESS);
+
+ return STATUS_SUCCESS;
+}
+
+static VOID
+FreeUserModeWindowStationName(
+ IN OUT PUNICODE_STRING WindowStationName,
+ IN PUNICODE_STRING TebStaticUnicodeString,
+ IN OUT POBJECT_ATTRIBUTES UserModeObjectAttributes OPTIONAL,
+ IN POBJECT_ATTRIBUTES LocalObjectAttributes OPTIONAL)
+{
+ SIZE_T MemSize = 0;
+
+ /* Try to restore the user's UserModeObjectAttributes */
+ if (UserModeObjectAttributes && LocalObjectAttributes)
+ {
+ _SEH2_TRY
+ {
+ ProbeForWrite(UserModeObjectAttributes, sizeof(OBJECT_ATTRIBUTES), sizeof(ULONG));
+ *UserModeObjectAttributes = *LocalObjectAttributes;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ NOTHING;
+ }
+ _SEH2_END;
+ }
+
+ /* Free the user-mode memory */
+ if (WindowStationName && (WindowStationName != TebStaticUnicodeString))
+ {
+ ZwFreeVirtualMemory(ZwCurrentProcess(),
+ (PVOID*)&WindowStationName,
+ &MemSize,
+ MEM_RELEASE);
+ }
+}
+
+static NTSTATUS
+BuildUserModeWindowStationName(
+ IN OUT POBJECT_ATTRIBUTES UserModeObjectAttributes,
+ IN OUT POBJECT_ATTRIBUTES LocalObjectAttributes,
+ OUT PUNICODE_STRING* WindowStationName,
+ OUT PUNICODE_STRING* TebStaticUnicodeString)
+{
+ NTSTATUS Status;
+ SIZE_T MemSize;
+
+ LUID CallerLuid;
+ PTEB Teb;
+ USHORT StrSize;
+
+ *WindowStationName = NULL;
+ *TebStaticUnicodeString = NULL;
+
+ /* Retrieve the current process LUID */
+ Status = GetProcessLuid(NULL, NULL, &CallerLuid);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("Failed to retrieve the caller LUID, Status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ /* Compute the needed string size */
+ MemSize = _scwprintf(L"%wZ\\Service-0x%x-%x$",
+ &gustrWindowStationsDir,
+ CallerLuid.HighPart,
+ CallerLuid.LowPart);
+ MemSize = MemSize * sizeof(WCHAR) + sizeof(UNICODE_NULL);
+ if (MemSize > MAXUSHORT)
+ {
+ ERR("Window station name length is too long.\n");
+ return STATUS_NAME_TOO_LONG;
+ }
+ StrSize = (USHORT)MemSize;
+
+ /*
+ * Check whether it's short enough so that we can use the static buffer
+ * in the TEB. Otherwise continue with virtual memory allocation.
+ */
+ Teb = NtCurrentTeb();
+ if (Teb && (StrSize <= sizeof(Teb->StaticUnicodeBuffer)))
+ {
+ /* We can use the TEB's static unicode string */
+ ASSERT(Teb->StaticUnicodeString.Buffer == Teb->StaticUnicodeBuffer);
+ ASSERT(Teb->StaticUnicodeString.MaximumLength == sizeof(Teb->StaticUnicodeBuffer));
+
+ /* Remember the TEB's static unicode string address for later */
+ *TebStaticUnicodeString = &Teb->StaticUnicodeString;
+
+ *WindowStationName = *TebStaticUnicodeString;
+ (*WindowStationName)->Length = 0;
+ }
+ else
+ {
+ /* The TEB's static unicode string is too small, allocate some user-mode virtual memory */
+ MemSize += ALIGN_UP(sizeof(UNICODE_STRING), sizeof(PVOID));
+
+ /* Allocate the memory in user-mode */
+ Status = ZwAllocateVirtualMemory(ZwCurrentProcess(),
+ (PVOID*)WindowStationName,
+ 0,
+ &MemSize,
+ MEM_COMMIT,
+ PAGE_READWRITE);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("ZwAllocateVirtualMemory() failed, Status 0x%08lx\n", Status);
+ return Status;
+ }
+
+ RtlInitEmptyUnicodeString(*WindowStationName,
+ (PWCHAR)((ULONG_PTR)*WindowStationName +
+ ALIGN_UP(sizeof(UNICODE_STRING), sizeof(PVOID))),
+ StrSize);
+ }
+
+ /* Build a valid window station name from the LUID */
+ Status = RtlStringCbPrintfW((*WindowStationName)->Buffer,
+ (*WindowStationName)->MaximumLength,
+ L"%wZ\\Service-0x%x-%x$",
+ &gustrWindowStationsDir,
+ CallerLuid.HighPart,
+ CallerLuid.LowPart);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("Impossible to build a valid window station name, Status 0x%08lx\n", Status);
+ goto Quit;
+ }
+ (*WindowStationName)->Length = (USHORT)(wcslen((*WindowStationName)->Buffer) * sizeof(WCHAR));
+
+ /* Try to update the user's UserModeObjectAttributes */
+ _SEH2_TRY
+ {
+ ProbeForWrite(UserModeObjectAttributes, sizeof(OBJECT_ATTRIBUTES), sizeof(ULONG));
+ *LocalObjectAttributes = *UserModeObjectAttributes;
+
+ UserModeObjectAttributes->ObjectName = *WindowStationName;
+ UserModeObjectAttributes->RootDirectory = NULL;
+
+ Status = STATUS_SUCCESS;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+Quit:
+ if (!NT_SUCCESS(Status))
+ {
+ /* Release the window station name */
+ FreeUserModeWindowStationName(*WindowStationName,
+ *TebStaticUnicodeString,
+ NULL, NULL);
+ }
+
+ return Status;
+}
+
+HWINSTA
+APIENTRY
NtUserCreateWindowStation(
- POBJECT_ATTRIBUTES ObjectAttributes,
- ACCESS_MASK dwDesiredAccess,
- DWORD Unknown2,
- DWORD Unknown3,
- DWORD Unknown4,
- DWORD Unknown5,
- DWORD Unknown6)
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN 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));
-
- InitializeListHead(&WindowStationObject->DesktopListHead);
- Status = RtlCreateAtomTable(37, &WindowStationObject->AtomTable);
- 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",
- WindowStation, &WindowStationObject->Name, WindowStation);
- return WindowStation;
+ NTSTATUS Status = STATUS_SUCCESS;
+ HWINSTA hWinSta = NULL;
+ OBJECT_ATTRIBUTES LocalObjectAttributes;
+ PUNICODE_STRING WindowStationName = NULL;
+ PUNICODE_STRING TebStaticUnicodeString = NULL;
+ KPROCESSOR_MODE OwnerMode = UserMode;
+
+ TRACE("NtUserCreateWindowStation called\n");
+
+ /* Capture the object attributes and the window station name */
+ _SEH2_TRY
+ {
+ ProbeForRead(ObjectAttributes, sizeof(OBJECT_ATTRIBUTES), sizeof(ULONG));
+ LocalObjectAttributes = *ObjectAttributes;
+ if (LocalObjectAttributes.Length != sizeof(OBJECT_ATTRIBUTES))
+ {
+ ERR("Invalid ObjectAttributes length!\n");
+ Status = STATUS_INVALID_PARAMETER;
+ _SEH2_LEAVE;
+ }
+
+ /*
+ * Check whether the caller provided a window station name together
+ * with a RootDirectory handle.
+ *
+ * If the caller did not provide a window station name, build a new one
+ * based on the logon session identifier for the calling process.
+ * The new name is allocated in user-mode, as the rest of ObjectAttributes
+ * already is, so that the validation performed by the Object Manager
+ * can be done adequately.
+ */
+ if ((LocalObjectAttributes.ObjectName == NULL ||
+ LocalObjectAttributes.ObjectName->Buffer == NULL ||
+ LocalObjectAttributes.ObjectName->Length == 0 ||
+ LocalObjectAttributes.ObjectName->Buffer[0] == UNICODE_NULL)
+ /* &&
+ LocalObjectAttributes.RootDirectory == NULL */)
+ {
+ /* No, build the new window station name */
+ Status = BuildUserModeWindowStationName(ObjectAttributes,
+ &LocalObjectAttributes,
+ &WindowStationName,
+ &TebStaticUnicodeString);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("BuildUserModeWindowStationName() failed, Status 0x%08lx\n", Status);
+ _SEH2_LEAVE;
+ }
+ OwnerMode = KernelMode;
+ }
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status =_SEH2_GetExceptionCode();
+ ERR("ObjectAttributes capture failed, Status 0x%08lx\n", Status);
+ }
+ _SEH2_END;
+
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ return NULL;
+ }
+
+ UserEnterExclusive();
+
+ /* Create the window station */
+ Status = IntCreateWindowStation(&hWinSta,
+ ObjectAttributes,
+ UserMode,
+ OwnerMode,
+ dwDesiredAccess,
+ Unknown2,
+ Unknown3,
+ Unknown4,
+ Unknown5,
+ Unknown6);
+ UserLeave();
+
+ if (NT_SUCCESS(Status))
+ {
+ TRACE("NtUserCreateWindowStation created window station '%wZ' with handle 0x%p\n",
+ ObjectAttributes->ObjectName, hWinSta);
+ }
+ else
+ {
+ ASSERT(hWinSta == NULL);
+ ERR("NtUserCreateWindowStation failed to create window station '%wZ', Status 0x%08lx\n",
+ ObjectAttributes->ObjectName, Status);
+ }
+
+ /* Try to restore the user's ObjectAttributes and release the window station name */
+ FreeUserModeWindowStationName(WindowStationName,
+ TebStaticUnicodeString,
+ (OwnerMode == KernelMode ? ObjectAttributes : NULL),
+ &LocalObjectAttributes);
+
+ if (!NT_SUCCESS(Status))
+ {
+ ASSERT(hWinSta == NULL);
+ SetLastNtError(Status);
+ }
+
+ return hWinSta;
}
/*
* @implemented
*/
-HWINSTA APIENTRY
+HWINSTA
+APIENTRY
NtUserOpenWindowStation(
- POBJECT_ATTRIBUTES ObjectAttributes,
- ACCESS_MASK dwDesiredAccess)
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ IN 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;
+ NTSTATUS Status = STATUS_SUCCESS;
+ HWINSTA hWinSta = NULL;
+ OBJECT_ATTRIBUTES LocalObjectAttributes;
+ PUNICODE_STRING WindowStationName = NULL;
+ PUNICODE_STRING TebStaticUnicodeString = NULL;
+ KPROCESSOR_MODE OwnerMode = UserMode;
+
+ TRACE("NtUserOpenWindowStation called\n");
+
+ /* Capture the object attributes and the window station name */
+ _SEH2_TRY
+ {
+ ProbeForRead(ObjectAttributes, sizeof(OBJECT_ATTRIBUTES), sizeof(ULONG));
+ LocalObjectAttributes = *ObjectAttributes;
+ if (LocalObjectAttributes.Length != sizeof(OBJECT_ATTRIBUTES))
+ {
+ ERR("Invalid ObjectAttributes length!\n");
+ Status = STATUS_INVALID_PARAMETER;
+ _SEH2_LEAVE;
+ }
+
+ /*
+ * Check whether the caller did not provide a window station name,
+ * or provided the special "Service-0x00000000-00000000$" name.
+ *
+ * NOTE: On Windows, the special "Service-0x00000000-00000000$" string
+ * is used instead of an empty name (observed when API-monitoring
+ * OpenWindowStation() called with an empty window station name).
+ */
+ if ((LocalObjectAttributes.ObjectName == NULL ||
+ LocalObjectAttributes.ObjectName->Buffer == NULL ||
+ LocalObjectAttributes.ObjectName->Length == 0 ||
+ LocalObjectAttributes.ObjectName->Buffer[0] == UNICODE_NULL)
+ /* &&
+ LocalObjectAttributes.RootDirectory == NULL */)
+ {
+ /* No, remember that for later */
+ LocalObjectAttributes.ObjectName = NULL;
+ }
+ if (LocalObjectAttributes.ObjectName &&
+ LocalObjectAttributes.ObjectName->Length ==
+ sizeof(L"Service-0x00000000-00000000$") - sizeof(UNICODE_NULL) &&
+ _wcsnicmp(LocalObjectAttributes.ObjectName->Buffer,
+ L"Service-0x00000000-00000000$",
+ LocalObjectAttributes.ObjectName->Length / sizeof(WCHAR)) == 0)
+ {
+ /* No, remember that for later */
+ LocalObjectAttributes.ObjectName = NULL;
+ }
+
+ /*
+ * If the caller did not provide a window station name, build a new one
+ * based on the logon session identifier for the calling process.
+ * The new name is allocated in user-mode, as the rest of ObjectAttributes
+ * already is, so that the validation performed by the Object Manager
+ * can be done adequately.
+ */
+ if (!LocalObjectAttributes.ObjectName)
+ {
+ /* No, build the new window station name */
+ Status = BuildUserModeWindowStationName(ObjectAttributes,
+ &LocalObjectAttributes,
+ &WindowStationName,
+ &TebStaticUnicodeString);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("BuildUserModeWindowStationName() failed, Status 0x%08lx\n", Status);
+ _SEH2_LEAVE;
+ }
+ OwnerMode = KernelMode;
+ }
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status =_SEH2_GetExceptionCode();
+ ERR("ObjectAttributes capture failed, Status 0x%08lx\n", Status);
+ }
+ _SEH2_END;
+
+ if (!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ return NULL;
+ }
+
+ /* Open the window station */
+ Status = ObOpenObjectByName(ObjectAttributes,
+ ExWindowStationObjectType,
+ UserMode,
+ NULL,
+ dwDesiredAccess,
+ NULL,
+ (PVOID*)&hWinSta);
+ if (NT_SUCCESS(Status))
+ {
+ TRACE("NtUserOpenWindowStation opened window station '%wZ' with handle 0x%p\n",
+ ObjectAttributes->ObjectName, hWinSta);
+ }
+ else
+ {
+ ASSERT(hWinSta == NULL);
+ ERR("NtUserOpenWindowStation failed to open window station '%wZ', Status 0x%08lx\n",
+ ObjectAttributes->ObjectName, Status);
+ }
+
+ /* Try to restore the user's ObjectAttributes and release the window station name */
+ FreeUserModeWindowStationName(WindowStationName,
+ TebStaticUnicodeString,
+ (OwnerMode == KernelMode ? ObjectAttributes : NULL),
+ &LocalObjectAttributes);
+
+ if (!NT_SUCCESS(Status))
+ {
+ ASSERT(hWinSta == NULL);
+ SetLastNtError(Status);
+ }
+
+ return hWinSta;
}
/*
*
* Remarks
* The window station handle can be created with NtUserCreateWindowStation
- * or NtUserOpenWindowStation. Attemps to close a handle to the window
+ * or NtUserOpenWindowStation. Attempts to close a handle to the window
* station assigned to the calling process will fail.
*
* Status
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;
- }
-
- Status = IntValidateWindowStationHandle(
- hWinSta,
- KernelMode,
- 0,
- &Object);
+ return FALSE;
+ }
- if (!NT_SUCCESS(Status))
- {
- ERR("Validation of window station handle (%p) failed\n", hWinSta);
- return FALSE;
- }
+ Status = IntValidateWindowStationHandle(hWinSta,
+ UserMode,
+ 0,
+ &Object,
+ NULL);
+ 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;
+ POBJECT_HEADER ObjectHeader;
+ POBJECT_HEADER_NAME_INFO NameInfo;
+ OBJECT_HANDLE_INFORMATION HandleInfo;
+ USEROBJECTFLAGS ObjectFlags;
+ PUNICODE_STRING pStrNameU = NULL;
+ PVOID pvData = NULL;
+ SIZE_T 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 window station */
+ TRACE("Trying to open window station 0x%p\n", hObject);
+ Status = ObReferenceObjectByHandle(hObject,
+ 0,
+ ExWindowStationObjectType,
+ UserMode,
+ (PVOID*)&WinStaObject,
+ &HandleInfo);
+
+ if (Status == STATUS_OBJECT_TYPE_MISMATCH)
+ {
+ /* Try desktop */
+ TRACE("Trying to open desktop %p\n", hObject);
+ WinStaObject = NULL;
+ Status = IntValidateDesktopHandle(hObject,
+ UserMode,
+ 0,
+ &DesktopObject);
+ }
- 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");
+ 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:
+ {
+ ObjectFlags.fReserved = FALSE;
+ ObjectFlags.fInherit = !!(HandleInfo.HandleAttributes & OBJ_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)
+ {
+ ObjectHeader = OBJECT_TO_OBJECT_HEADER(WinStaObject);
+ NameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
+
+ if (NameInfo && (NameInfo->Name.Length > 0))
+ {
+ /* Named window station */
+ pStrNameU = &NameInfo->Name;
+ nDataSize = pStrNameU->Length + sizeof(UNICODE_NULL);
+ }
+ else
+ {
+ /* Unnamed window station (should never happen!) */
+ ASSERT(FALSE);
+ pStrNameU = NULL;
+ nDataSize = sizeof(UNICODE_NULL);
+ }
+ 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)
+ {
+ ObjectHeader = OBJECT_TO_OBJECT_HEADER(WinStaObject);
+ pStrNameU = &ObjectHeader->Type->Name;
+ nDataSize = pStrNameU->Length + sizeof(UNICODE_NULL);
+ Status = STATUS_SUCCESS;
+ }
+ else if (DesktopObject != NULL)
+ {
+ ObjectHeader = OBJECT_TO_OBJECT_HEADER(DesktopObject);
+ pStrNameU = &ObjectHeader->Type->Name;
+ nDataSize = pStrNameU->Length + sizeof(UNICODE_NULL);
+ 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 && (nDataSize > 0))
+ {
+ TRACE("Trying to copy data to caller (len = %lu, len needed = %lu)\n", nLength, nDataSize);
+ if (pvData)
+ {
+ /* Copy the data */
+ RtlCopyMemory(pvInformation, pvData, nDataSize);
+ }
+ else if (pStrNameU)
+ {
+ /* Copy and NULL-terminate the string */
+ RtlCopyMemory(pvInformation, pStrNameU->Buffer, pStrNameU->Length);
+ ((PWCHAR)pvInformation)[pStrNameU->Length / sizeof(WCHAR)] = UNICODE_NULL;
+ }
+ else
+ {
+ /* Zero the memory */
+ RtlZeroMemory(pvInformation, 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 FASTCALL
UserGetProcessWindowStation(VOID)
{
HWINSTA APIENTRY
NtUserGetProcessWindowStation(VOID)
{
- return UserGetProcessWindowStation();
+ return UserGetProcessWindowStation();
}
BOOL FASTCALL
UserSetProcessWindowStation(HWINSTA hWindowStation)
{
- PPROCESSINFO ppi;
NTSTATUS Status;
- HWINSTA hwinstaOld;
+ PPROCESSINFO ppi;
+ OBJECT_HANDLE_INFORMATION ObjectHandleInfo;
PWINSTATION_OBJECT NewWinSta = NULL, OldWinSta;
+ HWINSTA hCacheWinSta;
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 0x%p failed\n", hWindowStation);
+ SetLastNtError(Status);
+ return FALSE;
+ }
+ }
+
+ OldWinSta = ppi->prpwinsta;
+ hCacheWinSta = PsGetProcessWin32WindowStation(ppi->peProcess);
+
+ /* Dereference the previous window station */
+ if (OldWinSta != NULL)
+ {
+ ObDereferenceObject(OldWinSta);
+ }
+
+ /*
+ * FIXME: Don't allow changing the window station if there are threads that are attached to desktops and own GUI objects?
+ */
+
+ /* Close the cached EPROCESS window station handle if needed */
+ if (hCacheWinSta != NULL)
+ {
+ /* Reference the window station */
+ Status = ObReferenceObjectByHandle(hCacheWinSta,
+ 0,
+ ExWindowStationObjectType,
+ UserMode,
+ (PVOID*)&OldWinSta,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("Failed to reference the inherited window station, Status 0x%08lx\n", Status);
+ /* We failed, reset the cache */
+ hCacheWinSta = NULL;
+ PsSetProcessWindowStation(ppi->peProcess, hCacheWinSta);
+ }
+ else
+ {
+ /*
+ * Close the old handle and reset the cache only
+ * if we are setting a different window station.
+ */
+ if (NewWinSta != OldWinSta)
+ {
+ ObCloseHandle(hCacheWinSta, UserMode);
+ hCacheWinSta = NULL;
+ PsSetProcessWindowStation(ppi->peProcess, hCacheWinSta);
+ }
+
+ /* Dereference the window station */
+ ObDereferenceObject(OldWinSta);
+ }
+ }
+
+ /* Duplicate and save a new cached EPROCESS window station handle */
+ if ((hCacheWinSta == NULL) && (hWindowStation != NULL))
+ {
+ Status = ZwDuplicateObject(ZwCurrentProcess(),
+ hWindowStation,
+ ZwCurrentProcess(),
+ (PHANDLE)&hCacheWinSta,
+ 0,
+ 0,
+ DUPLICATE_SAME_ACCESS);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("UserSetProcessWindowStation: Failed to duplicate the window station handle, Status 0x%08lx\n", Status);
+ }
+ else
+ {
+ PsSetProcessWindowStation(ppi->peProcess, hCacheWinSta);
+ }
+ }
+
+ 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 (gpidLogon != PsGetCurrentProcessId())
- {
- 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,
+ NULL);
+ 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 (gpidLogon != PsGetCurrentProcessId())
- {
- 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,
+ NULL);
+ 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;
+
+ //
+ // 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.
+ */
+ 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;
- PLIST_ENTRY DesktopEntry;
- PDESKTOP DesktopObject;
- DWORD EntryCount;
- ULONG ReturnLength;
- WCHAR NullWchar;
- UNICODE_STRING DesktopName;
-
- Status = IntValidateWindowStationHandle(hWindowStation,
- KernelMode,
- 0,
- &WindowStation);
- if (! NT_SUCCESS(Status))
- {
- return Status;
- }
-
- /*
- * 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,
+ NULL);
+ 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;
+ {
+ 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;
+ {
+ 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);
}
/*
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 */