2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
4 * PURPOSE: Window stations
5 * FILE: win32ss/user/ntuser/winsta.c
6 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * TODO: The process window station is created on
8 * the first USER32/GDI32 call not related
9 * to window station/desktop handling
13 DBG_DEFAULT_CHANNEL(UserWinsta
);
15 /* GLOBALS *******************************************************************/
18 * The currently active window station. This is the
19 * only one interactive window station on the system.
21 PWINSTATION_OBJECT InputWindowStation
= NULL
;
23 /* Winlogon SAS window */
26 /* Full path to WindowStations directory */
27 UNICODE_STRING gustrWindowStationsDir
;
29 /* INITIALIZATION FUNCTIONS ****************************************************/
34 InitWindowStationImpl(VOID
)
36 GENERIC_MAPPING IntWindowStationMapping
= { WINSTA_READ
,
41 /* Set Winsta Object Attributes */
42 ExWindowStationObjectType
->TypeInfo
.DefaultNonPagedPoolCharge
= sizeof(WINSTATION_OBJECT
);
43 ExWindowStationObjectType
->TypeInfo
.GenericMapping
= IntWindowStationMapping
;
44 ExWindowStationObjectType
->TypeInfo
.ValidAccessMask
= WINSTA_ACCESS_ALL
;
46 return STATUS_SUCCESS
;
51 UserCreateWinstaDirectory(VOID
)
55 OBJECT_ATTRIBUTES ObjectAttributes
;
57 WCHAR wstrWindowStationsDir
[MAX_PATH
];
59 /* Create the WindowStations directory and cache its path for later use */
61 if(Peb
->SessionId
== 0)
63 if (!RtlCreateUnicodeString(&gustrWindowStationsDir
, WINSTA_OBJ_DIR
))
65 return STATUS_INSUFFICIENT_RESOURCES
;
70 Status
= RtlStringCbPrintfW(wstrWindowStationsDir
,
71 sizeof(wstrWindowStationsDir
),
76 if (!NT_SUCCESS(Status
))
79 if (!RtlCreateUnicodeString(&gustrWindowStationsDir
, wstrWindowStationsDir
))
81 return STATUS_INSUFFICIENT_RESOURCES
;
85 InitializeObjectAttributes(&ObjectAttributes
,
86 &gustrWindowStationsDir
,
90 Status
= ZwCreateDirectoryObject(&hWinstaDir
, DIRECTORY_CREATE_OBJECT
, &ObjectAttributes
);
91 if (!NT_SUCCESS(Status
))
93 ERR("Could not create %wZ directory (Status 0x%X)\n", &gustrWindowStationsDir
, Status
);
97 TRACE("Created directory %wZ for session %lu\n", &gustrWindowStationsDir
, Peb
->SessionId
);
102 /* OBJECT CALLBACKS ***********************************************************/
106 IntWinStaObjectDelete(
107 _In_ PVOID Parameters
)
109 PWIN32_DELETEMETHOD_PARAMETERS DeleteParameters
= Parameters
;
110 PWINSTATION_OBJECT WinSta
= (PWINSTATION_OBJECT
)DeleteParameters
->Object
;
112 TRACE("Deleting window station 0x%p\n", WinSta
);
114 if (WinSta
== InputWindowStation
)
116 ERR("WARNING: Deleting the interactive window station '%wZ'!\n",
117 &(OBJECT_HEADER_TO_NAME_INFO(OBJECT_TO_OBJECT_HEADER(InputWindowStation
))->Name
));
119 /* Only Winlogon can close and delete the interactive window station */
120 ASSERT(gpidLogon
== PsGetCurrentProcessId());
122 InputWindowStation
= NULL
;
125 WinSta
->Flags
|= WSS_DYING
;
127 UserEmptyClipboardData(WinSta
);
129 RtlDestroyAtomTable(WinSta
->AtomTable
);
131 return STATUS_SUCCESS
;
136 IntWinStaObjectParse(
137 _In_ PVOID Parameters
)
139 PWIN32_PARSEMETHOD_PARAMETERS ParseParameters
= Parameters
;
140 PUNICODE_STRING RemainingName
= ParseParameters
->RemainingName
;
142 /* Assume we don't find anything */
143 *ParseParameters
->Object
= NULL
;
145 /* Check for an empty name */
146 if (!RemainingName
->Length
)
148 /* Make sure this is a window station, can't parse a desktop now */
149 if (ParseParameters
->ObjectType
!= ExWindowStationObjectType
)
152 return STATUS_OBJECT_TYPE_MISMATCH
;
155 /* Reference the window station and return */
156 ObReferenceObject(ParseParameters
->ParseObject
);
157 *ParseParameters
->Object
= ParseParameters
->ParseObject
;
158 return STATUS_SUCCESS
;
161 /* Check for leading slash */
162 if (RemainingName
->Buffer
[0] == OBJ_NAME_PATH_SEPARATOR
)
165 RemainingName
->Buffer
++;
166 RemainingName
->Length
-= sizeof(WCHAR
);
167 RemainingName
->MaximumLength
-= sizeof(WCHAR
);
170 /* Check if there is still a slash */
171 if (wcschr(RemainingName
->Buffer
, OBJ_NAME_PATH_SEPARATOR
))
173 /* In this case, fail */
174 return STATUS_OBJECT_PATH_INVALID
;
178 * Check if we are parsing a desktop.
180 if (ParseParameters
->ObjectType
== ExDesktopObjectType
)
182 /* Then call the desktop parse routine */
183 return IntDesktopObjectParse(ParseParameters
->ParseObject
,
184 ParseParameters
->ObjectType
,
185 ParseParameters
->AccessState
,
186 ParseParameters
->AccessMode
,
187 ParseParameters
->Attributes
,
188 ParseParameters
->CompleteName
,
190 ParseParameters
->Context
,
191 ParseParameters
->SecurityQos
,
192 ParseParameters
->Object
);
195 /* Should hopefully never get here */
196 return STATUS_OBJECT_TYPE_MISMATCH
;
202 _In_ PVOID Parameters
)
204 PWIN32_OKAYTOCLOSEMETHOD_PARAMETERS OkToCloseParameters
= Parameters
;
207 ppi
= PsGetCurrentProcessWin32Process();
209 if (ppi
&& (OkToCloseParameters
->Handle
== ppi
->hwinsta
))
211 return STATUS_ACCESS_DENIED
;
214 return STATUS_SUCCESS
;
217 /* PRIVATE FUNCTIONS **********************************************************/
220 * IntValidateWindowStationHandle
222 * Validates the window station handle.
225 * If the function succeeds, the handle remains referenced. If the
226 * fucntion fails, last error is set.
230 IntValidateWindowStationHandle(
231 HWINSTA WindowStation
,
232 KPROCESSOR_MODE AccessMode
,
233 ACCESS_MASK DesiredAccess
,
234 PWINSTATION_OBJECT
*Object
,
235 POBJECT_HANDLE_INFORMATION pObjectHandleInfo
)
239 if (WindowStation
== NULL
)
241 ERR("Invalid window station handle\n");
242 EngSetLastError(ERROR_INVALID_HANDLE
);
243 return STATUS_INVALID_HANDLE
;
246 Status
= ObReferenceObjectByHandle(WindowStation
,
248 ExWindowStationObjectType
,
253 if (!NT_SUCCESS(Status
))
254 SetLastNtError(Status
);
260 co_IntInitializeDesktopGraphics(VOID
)
263 UNICODE_STRING DriverName
= RTL_CONSTANT_STRING(L
"DISPLAY");
266 ScreenDeviceContext
= IntGdiCreateDC(&DriverName
, NULL
, NULL
, NULL
, FALSE
);
267 if (NULL
== ScreenDeviceContext
)
269 IntDestroyPrimarySurface();
272 GreSetDCOwner(ScreenDeviceContext
, GDI_OBJ_HMGR_PUBLIC
);
274 if (! IntCreatePrimarySurface())
279 hSystemBM
= NtGdiCreateCompatibleDC(ScreenDeviceContext
);
281 NtGdiSelectFont(hSystemBM
, NtGdiGetStockObject(SYSTEM_FONT
));
282 GreSetDCOwner(hSystemBM
, GDI_OBJ_HMGR_PUBLIC
);
284 /* Update the SERVERINFO */
285 gpsi
->aiSysMet
[SM_CXSCREEN
] = gppdevPrimary
->gdiinfo
.ulHorzRes
;
286 gpsi
->aiSysMet
[SM_CYSCREEN
] = gppdevPrimary
->gdiinfo
.ulVertRes
;
287 gpsi
->Planes
= NtGdiGetDeviceCaps(ScreenDeviceContext
, PLANES
);
288 gpsi
->BitsPixel
= NtGdiGetDeviceCaps(ScreenDeviceContext
, BITSPIXEL
);
289 gpsi
->BitCount
= gpsi
->Planes
* gpsi
->BitsPixel
;
290 gpsi
->dmLogPixels
= NtGdiGetDeviceCaps(ScreenDeviceContext
, LOGPIXELSY
);
291 if (NtGdiGetDeviceCaps(ScreenDeviceContext
, RASTERCAPS
) & RC_PALETTE
)
293 gpsi
->PUSIFlags
|= PUSIF_PALETTEDISPLAY
;
296 gpsi
->PUSIFlags
&= ~PUSIF_PALETTEDISPLAY
;
297 // Font is realized and this dc was previously set to internal DC_ATTR.
298 gpsi
->cxSysFontChar
= IntGetCharDimensions(hSystemBM
, &tmw
, (DWORD
*)&gpsi
->cySysFontChar
);
299 gpsi
->tmSysFont
= tmw
;
301 /* Put the pointer in the center of the screen */
302 gpsi
->ptCursor
.x
= gpsi
->aiSysMet
[SM_CXSCREEN
] / 2;
303 gpsi
->ptCursor
.y
= gpsi
->aiSysMet
[SM_CYSCREEN
] / 2;
306 UserAttachMonitor((HDEV
)gppdevPrimary
);
308 /* Setup the cursor */
309 co_IntLoadDefaultCursors();
311 /* Setup the icons */
317 /* Show the desktop */
318 pdesk
= IntGetActiveDesktop();
320 co_IntShowDesktop(pdesk
, gpsi
->aiSysMet
[SM_CXSCREEN
], gpsi
->aiSysMet
[SM_CYSCREEN
], TRUE
);
326 IntEndDesktopGraphics(VOID
)
328 if (NULL
!= ScreenDeviceContext
)
329 { // No need to allocate a new dcattr.
330 GreSetDCOwner(ScreenDeviceContext
, GDI_OBJ_HMGR_POWNED
);
331 GreDeleteObject(ScreenDeviceContext
);
332 ScreenDeviceContext
= NULL
;
334 IntHideDesktop(IntGetActiveDesktop());
335 IntDestroyPrimarySurface();
341 return ScreenDeviceContext
;
345 CheckWinstaAttributeAccess(ACCESS_MASK DesiredAccess
)
347 PPROCESSINFO ppi
= PsGetCurrentProcessWin32Process();
348 if ( gpidLogon
!= PsGetCurrentProcessId() )
350 if (!(ppi
->W32PF_flags
& W32PF_IOWINSTA
))
352 ERR("Requires Interactive Window Station\n");
353 EngSetLastError(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION
);
356 if (!RtlAreAllAccessesGranted(ppi
->amwinsta
, DesiredAccess
))
358 ERR("Access Denied\n");
359 EngSetLastError(ERROR_ACCESS_DENIED
);
367 /* PUBLIC FUNCTIONS ***********************************************************/
370 * NtUserCreateWindowStation
372 * Creates a new window station.
375 * lpszWindowStationName
376 * Pointer to a null-terminated string specifying the name of the
377 * window station to be created. Window station names are
378 * case-insensitive and cannot contain backslash characters (\).
379 * Only members of the Administrators group are allowed to specify a
383 * Requested type of access
386 * Security descriptor
388 * Unknown3, Unknown4, Unknown5, Unknown6
392 * If the function succeeds, the return value is a handle to the newly
393 * created window station. If the specified window station already
394 * exists, the function succeeds and returns a handle to the existing
395 * window station. If the function fails, the return value is NULL.
403 IntCreateWindowStation(
404 OUT HWINSTA
* phWinSta
,
405 IN POBJECT_ATTRIBUTES ObjectAttributes
,
406 IN KPROCESSOR_MODE AccessMode
,
407 IN KPROCESSOR_MODE OwnerMode
,
408 IN ACCESS_MASK dwDesiredAccess
,
417 PWINSTATION_OBJECT WindowStation
;
419 TRACE("IntCreateWindowStation called\n");
424 Status
= ObOpenObjectByName(ObjectAttributes
,
425 ExWindowStationObjectType
,
431 if (NT_SUCCESS(Status
))
433 TRACE("IntCreateWindowStation opened window station '%wZ'\n",
434 ObjectAttributes
->ObjectName
);
440 * No existing window station found, try to create a new one.
443 /* Create the window station object */
444 Status
= ObCreateObject(AccessMode
,
445 ExWindowStationObjectType
,
449 sizeof(WINSTATION_OBJECT
),
452 (PVOID
*)&WindowStation
);
453 if (!NT_SUCCESS(Status
))
455 ERR("ObCreateObject failed for window station '%wZ', Status 0x%08lx\n",
456 ObjectAttributes
->ObjectName
, Status
);
457 SetLastNtError(Status
);
461 /* Initialize the window station */
462 RtlZeroMemory(WindowStation
, sizeof(WINSTATION_OBJECT
));
464 InitializeListHead(&WindowStation
->DesktopListHead
);
465 WindowStation
->dwSessionId
= NtCurrentPeb()->SessionId
;
466 Status
= RtlCreateAtomTable(37, &WindowStation
->AtomTable
);
467 if (!NT_SUCCESS(Status
))
469 ERR("RtlCreateAtomTable failed for window station '%wZ', Status 0x%08lx\n",
470 ObjectAttributes
->ObjectName
, Status
);
471 ObDereferenceObject(WindowStation
);
472 SetLastNtError(Status
);
476 Status
= ObInsertObject(WindowStation
,
482 if (!NT_SUCCESS(Status
))
484 ERR("ObInsertObject failed for window station, Status 0x%08lx\n", Status
);
485 SetLastNtError(Status
);
489 // FIXME! TODO: Add this new window station to a linked list
491 if (InputWindowStation
== NULL
)
493 ERR("Initializing input window station\n");
495 /* Only Winlogon can create the interactive window station */
496 ASSERT(gpidLogon
== PsGetCurrentProcessId());
498 InputWindowStation
= WindowStation
;
499 WindowStation
->Flags
&= ~WSS_NOIO
;
504 WindowStation
->Flags
|= WSS_NOIO
;
507 TRACE("IntCreateWindowStation created window station '%wZ' object 0x%p handle 0x%p\n",
508 ObjectAttributes
->ObjectName
, WindowStation
, hWinSta
);
511 return STATUS_SUCCESS
;
515 FreeUserModeWindowStationName(
516 IN OUT PUNICODE_STRING WindowStationName
,
517 IN PUNICODE_STRING TebStaticUnicodeString
,
518 IN OUT POBJECT_ATTRIBUTES UserModeObjectAttributes OPTIONAL
,
519 IN POBJECT_ATTRIBUTES LocalObjectAttributes OPTIONAL
)
523 /* Try to restore the user's UserModeObjectAttributes */
524 if (UserModeObjectAttributes
&& LocalObjectAttributes
)
528 ProbeForWrite(UserModeObjectAttributes
, sizeof(OBJECT_ATTRIBUTES
), sizeof(ULONG
));
529 *UserModeObjectAttributes
= *LocalObjectAttributes
;
531 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
538 /* Free the user-mode memory */
539 if (WindowStationName
&& (WindowStationName
!= TebStaticUnicodeString
))
541 ZwFreeVirtualMemory(ZwCurrentProcess(),
542 (PVOID
*)&WindowStationName
,
549 BuildUserModeWindowStationName(
550 IN OUT POBJECT_ATTRIBUTES UserModeObjectAttributes
,
551 IN OUT POBJECT_ATTRIBUTES LocalObjectAttributes
,
552 OUT PUNICODE_STRING
* WindowStationName
,
553 OUT PUNICODE_STRING
* TebStaticUnicodeString
)
562 *WindowStationName
= NULL
;
563 *TebStaticUnicodeString
= NULL
;
565 /* Retrieve the current process LUID */
566 Status
= GetProcessLuid(NULL
, NULL
, &CallerLuid
);
567 if (!NT_SUCCESS(Status
))
569 ERR("Failed to retrieve the caller LUID, Status 0x%08lx\n", Status
);
573 /* Compute the needed string size */
574 MemSize
= _scwprintf(L
"%wZ\\Service-0x%x-%x$",
575 &gustrWindowStationsDir
,
578 MemSize
= MemSize
* sizeof(WCHAR
) + sizeof(UNICODE_NULL
);
579 if (MemSize
> MAXUSHORT
)
581 ERR("Window station name length is too long.\n");
582 return STATUS_NAME_TOO_LONG
;
584 StrSize
= (USHORT
)MemSize
;
587 * Check whether it's short enough so that we can use the static buffer
588 * in the TEB. Otherwise continue with virtual memory allocation.
590 Teb
= NtCurrentTeb();
591 if (Teb
&& (StrSize
<= sizeof(Teb
->StaticUnicodeBuffer
)))
593 /* We can use the TEB's static unicode string */
594 ASSERT(Teb
->StaticUnicodeString
.Buffer
== Teb
->StaticUnicodeBuffer
);
595 ASSERT(Teb
->StaticUnicodeString
.MaximumLength
== sizeof(Teb
->StaticUnicodeBuffer
));
597 /* Remember the TEB's static unicode string address for later */
598 *TebStaticUnicodeString
= &Teb
->StaticUnicodeString
;
600 *WindowStationName
= *TebStaticUnicodeString
;
601 (*WindowStationName
)->Length
= 0;
605 /* The TEB's static unicode string is too small, allocate some user-mode virtual memory */
606 MemSize
+= ALIGN_UP(sizeof(UNICODE_STRING
), sizeof(PVOID
));
608 /* Allocate the memory in user-mode */
609 Status
= ZwAllocateVirtualMemory(ZwCurrentProcess(),
610 (PVOID
*)WindowStationName
,
615 if (!NT_SUCCESS(Status
))
617 ERR("ZwAllocateVirtualMemory() failed, Status 0x%08lx\n", Status
);
621 RtlInitEmptyUnicodeString(*WindowStationName
,
622 (PWCHAR
)((ULONG_PTR
)*WindowStationName
+
623 ALIGN_UP(sizeof(UNICODE_STRING
), sizeof(PVOID
))),
627 /* Build a valid window station name from the LUID */
628 Status
= RtlStringCbPrintfW((*WindowStationName
)->Buffer
,
629 (*WindowStationName
)->MaximumLength
,
630 L
"%wZ\\Service-0x%x-%x$",
631 &gustrWindowStationsDir
,
634 if (!NT_SUCCESS(Status
))
636 ERR("Impossible to build a valid window station name, Status 0x%08lx\n", Status
);
639 (*WindowStationName
)->Length
= (USHORT
)(wcslen((*WindowStationName
)->Buffer
) * sizeof(WCHAR
));
641 /* Try to update the user's UserModeObjectAttributes */
644 ProbeForWrite(UserModeObjectAttributes
, sizeof(OBJECT_ATTRIBUTES
), sizeof(ULONG
));
645 *LocalObjectAttributes
= *UserModeObjectAttributes
;
647 UserModeObjectAttributes
->ObjectName
= *WindowStationName
;
648 UserModeObjectAttributes
->RootDirectory
= NULL
;
650 Status
= STATUS_SUCCESS
;
652 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
654 Status
= _SEH2_GetExceptionCode();
659 if (!NT_SUCCESS(Status
))
661 /* Release the window station name */
662 FreeUserModeWindowStationName(*WindowStationName
,
663 *TebStaticUnicodeString
,
672 NtUserCreateWindowStation(
673 IN POBJECT_ATTRIBUTES ObjectAttributes
,
674 IN ACCESS_MASK dwDesiredAccess
,
681 NTSTATUS Status
= STATUS_SUCCESS
;
682 HWINSTA hWinSta
= NULL
;
683 OBJECT_ATTRIBUTES LocalObjectAttributes
;
684 PUNICODE_STRING WindowStationName
= NULL
;
685 PUNICODE_STRING TebStaticUnicodeString
= NULL
;
686 KPROCESSOR_MODE OwnerMode
= UserMode
;
688 TRACE("NtUserCreateWindowStation called\n");
690 /* Capture the object attributes and the window station name */
693 ProbeForRead(ObjectAttributes
, sizeof(OBJECT_ATTRIBUTES
), sizeof(ULONG
));
694 LocalObjectAttributes
= *ObjectAttributes
;
695 if (LocalObjectAttributes
.Length
!= sizeof(OBJECT_ATTRIBUTES
))
697 ERR("Invalid ObjectAttributes length!\n");
698 Status
= STATUS_INVALID_PARAMETER
;
703 * Check whether the caller provided a window station name together
704 * with a RootDirectory handle.
706 * If the caller did not provide a window station name, build a new one
707 * based on the logon session identifier for the calling process.
708 * The new name is allocated in user-mode, as the rest of ObjectAttributes
709 * already is, so that the validation performed by the Object Manager
710 * can be done adequately.
712 if ((LocalObjectAttributes
.ObjectName
== NULL
||
713 LocalObjectAttributes
.ObjectName
->Buffer
== NULL
||
714 LocalObjectAttributes
.ObjectName
->Length
== 0 ||
715 LocalObjectAttributes
.ObjectName
->Buffer
[0] == UNICODE_NULL
)
717 LocalObjectAttributes.RootDirectory == NULL */)
719 /* No, build the new window station name */
720 Status
= BuildUserModeWindowStationName(ObjectAttributes
,
721 &LocalObjectAttributes
,
723 &TebStaticUnicodeString
);
724 if (!NT_SUCCESS(Status
))
726 ERR("BuildUserModeWindowStationName() failed, Status 0x%08lx\n", Status
);
729 OwnerMode
= KernelMode
;
732 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
734 Status
=_SEH2_GetExceptionCode();
735 ERR("ObjectAttributes capture failed, Status 0x%08lx\n", Status
);
739 if (!NT_SUCCESS(Status
))
741 SetLastNtError(Status
);
745 /* Create the window station */
746 Status
= IntCreateWindowStation(&hWinSta
,
756 if (NT_SUCCESS(Status
))
758 TRACE("NtUserCreateWindowStation created window station '%wZ' with handle 0x%p\n",
759 ObjectAttributes
->ObjectName
, hWinSta
);
763 ASSERT(hWinSta
== NULL
);
764 ERR("NtUserCreateWindowStation failed to create window station '%wZ', Status 0x%08lx\n",
765 ObjectAttributes
->ObjectName
, Status
);
768 /* Try to restore the user's ObjectAttributes and release the window station name */
769 FreeUserModeWindowStationName(WindowStationName
,
770 TebStaticUnicodeString
,
771 (OwnerMode
== KernelMode
? ObjectAttributes
: NULL
),
772 &LocalObjectAttributes
);
774 if (!NT_SUCCESS(Status
))
776 ASSERT(hWinSta
== NULL
);
777 SetLastNtError(Status
);
784 * NtUserOpenWindowStation
786 * Opens an existing window station.
789 * lpszWindowStationName
790 * Name of the existing window station.
793 * Requested type of access.
796 * If the function succeeds, the return value is the handle to the
797 * specified window station. If the function fails, the return value
801 * The returned handle can be closed with NtUserCloseWindowStation.
809 NtUserOpenWindowStation(
810 IN POBJECT_ATTRIBUTES ObjectAttributes
,
811 IN ACCESS_MASK dwDesiredAccess
)
813 NTSTATUS Status
= STATUS_SUCCESS
;
814 HWINSTA hWinSta
= NULL
;
815 OBJECT_ATTRIBUTES LocalObjectAttributes
;
816 PUNICODE_STRING WindowStationName
= NULL
;
817 PUNICODE_STRING TebStaticUnicodeString
= NULL
;
818 KPROCESSOR_MODE OwnerMode
= UserMode
;
820 TRACE("NtUserOpenWindowStation called\n");
822 /* Capture the object attributes and the window station name */
825 ProbeForRead(ObjectAttributes
, sizeof(OBJECT_ATTRIBUTES
), sizeof(ULONG
));
826 LocalObjectAttributes
= *ObjectAttributes
;
827 if (LocalObjectAttributes
.Length
!= sizeof(OBJECT_ATTRIBUTES
))
829 ERR("Invalid ObjectAttributes length!\n");
830 Status
= STATUS_INVALID_PARAMETER
;
835 * Check whether the caller did not provide a window station name,
836 * or provided the special "Service-0x00000000-00000000$" name.
838 * NOTE: On Windows, the special "Service-0x00000000-00000000$" string
839 * is used instead of an empty name (observed when API-monitoring
840 * OpenWindowStation() called with an empty window station name).
842 if ((LocalObjectAttributes
.ObjectName
== NULL
||
843 LocalObjectAttributes
.ObjectName
->Buffer
== NULL
||
844 LocalObjectAttributes
.ObjectName
->Length
== 0 ||
845 LocalObjectAttributes
.ObjectName
->Buffer
[0] == UNICODE_NULL
)
847 LocalObjectAttributes.RootDirectory == NULL */)
849 /* No, remember that for later */
850 LocalObjectAttributes
.ObjectName
= NULL
;
852 if (LocalObjectAttributes
.ObjectName
&&
853 LocalObjectAttributes
.ObjectName
->Length
==
854 sizeof(L
"Service-0x00000000-00000000$") - sizeof(UNICODE_NULL
) &&
855 _wcsnicmp(LocalObjectAttributes
.ObjectName
->Buffer
,
856 L
"Service-0x00000000-00000000$",
857 LocalObjectAttributes
.ObjectName
->Length
/ sizeof(WCHAR
)) == 0)
859 /* No, remember that for later */
860 LocalObjectAttributes
.ObjectName
= NULL
;
864 * If the caller did not provide a window station name, build a new one
865 * based on the logon session identifier for the calling process.
866 * The new name is allocated in user-mode, as the rest of ObjectAttributes
867 * already is, so that the validation performed by the Object Manager
868 * can be done adequately.
870 if (!LocalObjectAttributes
.ObjectName
)
872 /* No, build the new window station name */
873 Status
= BuildUserModeWindowStationName(ObjectAttributes
,
874 &LocalObjectAttributes
,
876 &TebStaticUnicodeString
);
877 if (!NT_SUCCESS(Status
))
879 ERR("BuildUserModeWindowStationName() failed, Status 0x%08lx\n", Status
);
882 OwnerMode
= KernelMode
;
885 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
887 Status
=_SEH2_GetExceptionCode();
888 ERR("ObjectAttributes capture failed, Status 0x%08lx\n", Status
);
892 if (!NT_SUCCESS(Status
))
894 SetLastNtError(Status
);
898 /* Open the window station */
899 Status
= ObOpenObjectByName(ObjectAttributes
,
900 ExWindowStationObjectType
,
906 if (NT_SUCCESS(Status
))
908 TRACE("NtUserOpenWindowStation opened window station '%wZ' with handle 0x%p\n",
909 ObjectAttributes
->ObjectName
, hWinSta
);
913 ASSERT(hWinSta
== NULL
);
914 ERR("NtUserOpenWindowStation failed to open window station '%wZ', Status 0x%08lx\n",
915 ObjectAttributes
->ObjectName
, Status
);
918 /* Try to restore the user's ObjectAttributes and release the window station name */
919 FreeUserModeWindowStationName(WindowStationName
,
920 TebStaticUnicodeString
,
921 (OwnerMode
== KernelMode
? ObjectAttributes
: NULL
),
922 &LocalObjectAttributes
);
924 if (!NT_SUCCESS(Status
))
926 ASSERT(hWinSta
== NULL
);
927 SetLastNtError(Status
);
934 * NtUserCloseWindowStation
936 * Closes a window station handle.
940 * Handle to the window station.
946 * The window station handle can be created with NtUserCreateWindowStation
947 * or NtUserOpenWindowStation. Attempts to close a handle to the window
948 * station assigned to the calling process will fail.
956 NtUserCloseWindowStation(
959 PWINSTATION_OBJECT Object
;
962 TRACE("NtUserCloseWindowStation called (%p)\n", hWinSta
);
964 if (hWinSta
== UserGetProcessWindowStation())
966 ERR("Attempted to close process window station\n");
970 Status
= IntValidateWindowStationHandle(hWinSta
,
976 if (!NT_SUCCESS(Status
))
978 ERR("Validation of window station handle (%p) failed\n", hWinSta
);
982 ObDereferenceObject(Object
);
984 TRACE("Closing window station handle (%p)\n", hWinSta
);
986 Status
= ObCloseHandle(hWinSta
, UserMode
);
987 if (!NT_SUCCESS(Status
))
989 SetLastNtError(Status
);
997 * NtUserGetObjectInformation
999 * The NtUserGetObjectInformation function retrieves information about a
1000 * window station or desktop object.
1004 * Handle to the window station or desktop object for which to
1005 * return information. This can be a handle of type HDESK or HWINSTA
1006 * (for example, a handle returned by NtUserCreateWindowStation,
1007 * NtUserOpenWindowStation, NtUserCreateDesktop, or NtUserOpenDesktop).
1010 * Specifies the object information to be retrieved.
1013 * Pointer to a buffer to receive the object information.
1016 * Specifies the size, in bytes, of the buffer pointed to by the
1020 * Pointer to a variable receiving the number of bytes required to
1021 * store the requested information. If this variable's value is
1022 * greater than the value of the nLength parameter when the function
1023 * returns, the function returns FALSE, and none of the information
1024 * is copied to the pvInfo buffer. If the value of the variable pointed
1025 * to by lpnLengthNeeded is less than or equal to the value of nLength,
1026 * the entire information block is copied.
1029 * If the function succeeds, the return value is nonzero. If the function
1030 * fails, the return value is zero.
1037 NtUserGetObjectInformation(
1040 PVOID pvInformation
,
1042 PDWORD nLengthNeeded
)
1045 PWINSTATION_OBJECT WinStaObject
= NULL
;
1046 PDESKTOP DesktopObject
= NULL
;
1047 POBJECT_HEADER ObjectHeader
;
1048 POBJECT_HEADER_NAME_INFO NameInfo
;
1049 OBJECT_HANDLE_INFORMATION HandleInfo
;
1050 USEROBJECTFLAGS ObjectFlags
;
1051 PUNICODE_STRING pStrNameU
= NULL
;
1052 PVOID pvData
= NULL
;
1053 SIZE_T nDataSize
= 0;
1058 ProbeForWrite(nLengthNeeded
, sizeof(*nLengthNeeded
), 1);
1059 ProbeForWrite(pvInformation
, nLength
, 1);
1061 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1063 SetLastNtError(_SEH2_GetExceptionCode());
1068 /* Try window station */
1069 TRACE("Trying to open window station 0x%p\n", hObject
);
1070 Status
= ObReferenceObjectByHandle(hObject
,
1072 ExWindowStationObjectType
,
1074 (PVOID
*)&WinStaObject
,
1077 if (Status
== STATUS_OBJECT_TYPE_MISMATCH
)
1080 TRACE("Trying to open desktop %p\n", hObject
);
1081 WinStaObject
= NULL
;
1082 Status
= IntValidateDesktopHandle(hObject
,
1088 if (!NT_SUCCESS(Status
))
1090 ERR("Failed: 0x%x\n", Status
);
1094 TRACE("WinSta or Desktop opened!\n");
1101 ObjectFlags
.fReserved
= FALSE
;
1102 ObjectFlags
.fInherit
= !!(HandleInfo
.HandleAttributes
& OBJ_INHERIT
);
1104 ObjectFlags
.dwFlags
= 0;
1105 if (WinStaObject
!= NULL
)
1107 if (!(WinStaObject
->Flags
& WSS_NOIO
))
1108 ObjectFlags
.dwFlags
|= WSF_VISIBLE
;
1110 else if (DesktopObject
!= NULL
)
1112 FIXME("Setting DF_ALLOWOTHERACCOUNTHOOK is unimplemented.\n");
1116 ERR("No associated WinStaObject nor DesktopObject!\n");
1119 pvData
= &ObjectFlags
;
1120 nDataSize
= sizeof(ObjectFlags
);
1121 Status
= STATUS_SUCCESS
;
1127 if (WinStaObject
!= NULL
)
1129 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(WinStaObject
);
1130 NameInfo
= OBJECT_HEADER_TO_NAME_INFO(ObjectHeader
);
1132 if (NameInfo
&& (NameInfo
->Name
.Length
> 0))
1134 /* Named window station */
1135 pStrNameU
= &NameInfo
->Name
;
1136 nDataSize
= pStrNameU
->Length
+ sizeof(UNICODE_NULL
);
1140 /* Unnamed window station (should never happen!) */
1143 nDataSize
= sizeof(UNICODE_NULL
);
1145 Status
= STATUS_SUCCESS
;
1147 else if (DesktopObject
!= NULL
)
1149 pvData
= DesktopObject
->pDeskInfo
->szDesktopName
;
1150 nDataSize
= (wcslen(DesktopObject
->pDeskInfo
->szDesktopName
) + 1) * sizeof(WCHAR
);
1151 Status
= STATUS_SUCCESS
;
1155 Status
= STATUS_INVALID_PARAMETER
;
1162 if (WinStaObject
!= NULL
)
1164 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(WinStaObject
);
1165 pStrNameU
= &ObjectHeader
->Type
->Name
;
1166 nDataSize
= pStrNameU
->Length
+ sizeof(UNICODE_NULL
);
1167 Status
= STATUS_SUCCESS
;
1169 else if (DesktopObject
!= NULL
)
1171 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(DesktopObject
);
1172 pStrNameU
= &ObjectHeader
->Type
->Name
;
1173 nDataSize
= pStrNameU
->Length
+ sizeof(UNICODE_NULL
);
1174 Status
= STATUS_SUCCESS
;
1178 Status
= STATUS_INVALID_PARAMETER
;
1184 Status
= STATUS_NOT_IMPLEMENTED
;
1185 ERR("UOI_USER_SID unimplemented!\n");
1189 Status
= STATUS_INVALID_PARAMETER
;
1194 if ((Status
== STATUS_SUCCESS
) && (nLength
< nDataSize
))
1195 Status
= STATUS_BUFFER_TOO_SMALL
;
1200 *nLengthNeeded
= nDataSize
;
1202 /* Try to copy data to caller */
1203 if (Status
== STATUS_SUCCESS
&& (nDataSize
> 0))
1205 TRACE("Trying to copy data to caller (len = %lu, len needed = %lu)\n", nLength
, nDataSize
);
1209 RtlCopyMemory(pvInformation
, pvData
, nDataSize
);
1213 /* Copy and NULL-terminate the string */
1214 RtlCopyMemory(pvInformation
, pStrNameU
->Buffer
, pStrNameU
->Length
);
1215 ((PWCHAR
)pvInformation
)[pStrNameU
->Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
1219 /* Zero the memory */
1220 RtlZeroMemory(pvInformation
, nDataSize
);
1224 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1226 Status
= _SEH2_GetExceptionCode();
1230 /* Release objects */
1231 if (DesktopObject
!= NULL
)
1232 ObDereferenceObject(DesktopObject
);
1233 if (WinStaObject
!= NULL
)
1234 ObDereferenceObject(WinStaObject
);
1236 if (!NT_SUCCESS(Status
))
1238 SetLastNtError(Status
);
1246 * NtUserSetObjectInformation
1248 * The NtUserSetObjectInformation function sets information about a
1249 * window station or desktop object.
1253 * Handle to the window station or desktop object for which to set
1254 * object information. This value can be a handle of type HDESK or
1258 * Specifies the object information to be set.
1261 * Pointer to a buffer containing the object information.
1264 * Specifies the size, in bytes, of the information contained in the
1265 * buffer pointed to by pvInfo.
1268 * If the function succeeds, the return value is nonzero. If the function
1269 * fails the return value is zero.
1277 NtUserSetObjectInformation(
1280 PVOID pvInformation
,
1283 /* FIXME: ZwQueryObject */
1284 /* FIXME: ZwSetInformationObject */
1285 SetLastNtError(STATUS_UNSUCCESSFUL
);
1291 UserGetProcessWindowStation(VOID
)
1293 PPROCESSINFO ppi
= PsGetCurrentProcessWin32Process();
1295 return ppi
->hwinsta
;
1300 * NtUserGetProcessWindowStation
1302 * Returns a handle to the current process window station.
1305 * If the function succeeds, the return value is handle to the window
1306 * station assigned to the current process. If the function fails, the
1307 * return value is NULL.
1314 NtUserGetProcessWindowStation(VOID
)
1316 return UserGetProcessWindowStation();
1320 UserSetProcessWindowStation(HWINSTA hWindowStation
)
1325 OBJECT_HANDLE_INFORMATION ObjectHandleInfo
;
1326 PWINSTATION_OBJECT NewWinSta
= NULL
, OldWinSta
;
1328 ppi
= PsGetCurrentProcessWin32Process();
1330 /* Reference the new window station */
1331 if (hWindowStation
!= NULL
)
1333 Status
= IntValidateWindowStationHandle(hWindowStation
,
1338 if (!NT_SUCCESS(Status
))
1340 TRACE("Validation of window station handle (%p) failed\n",
1342 SetLastNtError(Status
);
1347 OldWinSta
= ppi
->prpwinsta
;
1348 hwinstaOld
= PsGetProcessWin32WindowStation(ppi
->peProcess
);
1350 /* Dereference the previous window station */
1351 if (OldWinSta
!= NULL
)
1353 ObDereferenceObject(OldWinSta
);
1356 /* Check if we have a stale handle (it should happen for console apps) */
1357 if (hwinstaOld
!= ppi
->hwinsta
)
1359 ObCloseHandle(hwinstaOld
, UserMode
);
1363 * FIXME: Don't allow changing the window station if there are threads that are attached to desktops and own GUI objects.
1366 PsSetProcessWindowStation(ppi
->peProcess
, hWindowStation
);
1368 ppi
->prpwinsta
= NewWinSta
;
1369 ppi
->hwinsta
= hWindowStation
;
1370 ppi
->amwinsta
= hWindowStation
!= NULL
? ObjectHandleInfo
.GrantedAccess
: 0;
1371 TRACE("WS : Granted Access 0x%08lx\n",ppi
->amwinsta
);
1373 if (RtlAreAllAccessesGranted(ppi
->amwinsta
, WINSTA_READSCREEN
))
1375 ppi
->W32PF_flags
|= W32PF_READSCREENACCESSGRANTED
;
1379 ppi
->W32PF_flags
&= ~W32PF_READSCREENACCESSGRANTED
;
1382 if (NewWinSta
&& !(NewWinSta
->Flags
& WSS_NOIO
))
1384 ppi
->W32PF_flags
|= W32PF_IOWINSTA
;
1386 else // Might be closed if the handle is null.
1388 ppi
->W32PF_flags
&= ~W32PF_IOWINSTA
;
1394 * NtUserSetProcessWindowStation
1396 * Assigns a window station to the current process.
1400 * Handle to the window station.
1410 NtUserSetProcessWindowStation(HWINSTA hWindowStation
)
1414 UserEnterExclusive();
1416 ret
= UserSetProcessWindowStation(hWindowStation
);
1424 * NtUserLockWindowStation
1426 * Locks switching desktops. Only the logon application is allowed to call this function.
1433 NtUserLockWindowStation(HWINSTA hWindowStation
)
1435 PWINSTATION_OBJECT Object
;
1438 TRACE("About to set process window station with handle (%p)\n",
1441 if (gpidLogon
!= PsGetCurrentProcessId())
1443 ERR("Unauthorized process attempted to lock the window station!\n");
1444 EngSetLastError(ERROR_ACCESS_DENIED
);
1448 Status
= IntValidateWindowStationHandle(hWindowStation
,
1453 if (!NT_SUCCESS(Status
))
1455 TRACE("Validation of window station handle (%p) failed\n",
1457 SetLastNtError(Status
);
1461 Object
->Flags
|= WSS_LOCKED
;
1463 ObDereferenceObject(Object
);
1468 * NtUserUnlockWindowStation
1470 * Unlocks switching desktops. Only the logon application is allowed to call this function.
1477 NtUserUnlockWindowStation(HWINSTA hWindowStation
)
1479 PWINSTATION_OBJECT Object
;
1483 TRACE("About to set process window station with handle (%p)\n",
1486 if (gpidLogon
!= PsGetCurrentProcessId())
1488 ERR("Unauthorized process attempted to unlock the window station!\n");
1489 EngSetLastError(ERROR_ACCESS_DENIED
);
1493 Status
= IntValidateWindowStationHandle(hWindowStation
,
1498 if (!NT_SUCCESS(Status
))
1500 TRACE("Validation of window station handle (%p) failed\n",
1502 SetLastNtError(Status
);
1506 Ret
= (Object
->Flags
& WSS_LOCKED
) == WSS_LOCKED
;
1507 Object
->Flags
&= ~WSS_LOCKED
;
1509 ObDereferenceObject(Object
);
1513 static NTSTATUS FASTCALL
1514 BuildWindowStationNameList(
1517 PULONG pRequiredSize
)
1519 OBJECT_ATTRIBUTES ObjectAttributes
;
1521 HANDLE DirectoryHandle
;
1522 char InitialBuffer
[256], *Buffer
;
1523 ULONG Context
, ReturnLength
, BufferSize
;
1525 POBJECT_DIRECTORY_INFORMATION DirEntry
;
1529 // FIXME: Fully wrong! Since, by calling NtUserCreateWindowStation
1530 // with judicious parameters one can create window stations elsewhere
1531 // than in Windows\WindowStations directory, Win32k definitely MUST
1532 // maintain a list of window stations it has created, and not rely
1533 // on the enumeration of Windows\WindowStations !!!
1537 * Try to open the directory.
1539 InitializeObjectAttributes(&ObjectAttributes
,
1540 &gustrWindowStationsDir
,
1541 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
1545 Status
= ZwOpenDirectoryObject(&DirectoryHandle
,
1549 if (!NT_SUCCESS(Status
))
1554 /* First try to query the directory using a fixed-size buffer */
1557 Status
= ZwQueryDirectoryObject(DirectoryHandle
,
1559 sizeof(InitialBuffer
),
1564 if (NT_SUCCESS(Status
))
1566 if (STATUS_NO_MORE_ENTRIES
== ZwQueryDirectoryObject(DirectoryHandle
, NULL
, 0, FALSE
,
1567 FALSE
, &Context
, NULL
))
1569 /* Our fixed-size buffer is large enough */
1570 Buffer
= InitialBuffer
;
1576 /* Need a larger buffer, check how large exactly */
1577 Status
= ZwQueryDirectoryObject(DirectoryHandle
, NULL
, 0, FALSE
, TRUE
, &Context
,
1579 if (!NT_SUCCESS(Status
))
1581 ERR("ZwQueryDirectoryObject failed\n");
1582 ZwClose(DirectoryHandle
);
1586 BufferSize
= ReturnLength
;
1587 Buffer
= ExAllocatePoolWithTag(PagedPool
, BufferSize
, TAG_WINSTA
);
1590 ZwClose(DirectoryHandle
);
1591 return STATUS_NO_MEMORY
;
1594 /* We should have a sufficiently large buffer now */
1596 Status
= ZwQueryDirectoryObject(DirectoryHandle
, Buffer
, BufferSize
,
1597 FALSE
, TRUE
, &Context
, &ReturnLength
);
1598 if (! NT_SUCCESS(Status
) ||
1599 STATUS_NO_MORE_ENTRIES
!= ZwQueryDirectoryObject(DirectoryHandle
, NULL
, 0, FALSE
,
1600 FALSE
, &Context
, NULL
))
1602 /* Something went wrong, maybe someone added a directory entry? Just give up. */
1603 ExFreePoolWithTag(Buffer
, TAG_WINSTA
);
1604 ZwClose(DirectoryHandle
);
1605 return NT_SUCCESS(Status
) ? STATUS_INTERNAL_ERROR
: Status
;
1609 ZwClose(DirectoryHandle
);
1612 * Count the required size of buffer.
1614 ReturnLength
= sizeof(DWORD
);
1616 for (DirEntry
= (POBJECT_DIRECTORY_INFORMATION
) Buffer
;
1617 0 != DirEntry
->Name
.Length
;
1620 ReturnLength
+= DirEntry
->Name
.Length
+ sizeof(WCHAR
);
1623 TRACE("Required size: %lu Entry count: %lu\n", ReturnLength
, EntryCount
);
1624 if (NULL
!= pRequiredSize
)
1626 Status
= MmCopyToCaller(pRequiredSize
, &ReturnLength
, sizeof(ULONG
));
1627 if (! NT_SUCCESS(Status
))
1629 if (Buffer
!= InitialBuffer
)
1631 ExFreePoolWithTag(Buffer
, TAG_WINSTA
);
1633 return STATUS_BUFFER_TOO_SMALL
;
1638 * Check if the supplied buffer is large enough.
1640 if (dwSize
< ReturnLength
)
1642 if (Buffer
!= InitialBuffer
)
1644 ExFreePoolWithTag(Buffer
, TAG_WINSTA
);
1646 return STATUS_BUFFER_TOO_SMALL
;
1650 * Generate the resulting buffer contents.
1652 Status
= MmCopyToCaller(lpBuffer
, &EntryCount
, sizeof(DWORD
));
1653 if (! NT_SUCCESS(Status
))
1655 if (Buffer
!= InitialBuffer
)
1657 ExFreePoolWithTag(Buffer
, TAG_WINSTA
);
1661 lpBuffer
= (PVOID
) ((PCHAR
) lpBuffer
+ sizeof(DWORD
));
1664 for (DirEntry
= (POBJECT_DIRECTORY_INFORMATION
) Buffer
;
1665 0 != DirEntry
->Name
.Length
;
1668 Status
= MmCopyToCaller(lpBuffer
, DirEntry
->Name
.Buffer
, DirEntry
->Name
.Length
);
1669 if (! NT_SUCCESS(Status
))
1671 if (Buffer
!= InitialBuffer
)
1673 ExFreePoolWithTag(Buffer
, TAG_WINSTA
);
1677 lpBuffer
= (PVOID
) ((PCHAR
) lpBuffer
+ DirEntry
->Name
.Length
);
1678 Status
= MmCopyToCaller(lpBuffer
, &NullWchar
, sizeof(WCHAR
));
1679 if (! NT_SUCCESS(Status
))
1681 if (Buffer
!= InitialBuffer
)
1683 ExFreePoolWithTag(Buffer
, TAG_WINSTA
);
1687 lpBuffer
= (PVOID
) ((PCHAR
) lpBuffer
+ sizeof(WCHAR
));
1693 if (Buffer
!= InitialBuffer
)
1695 ExFreePoolWithTag(Buffer
, TAG_WINSTA
);
1698 return STATUS_SUCCESS
;
1701 static NTSTATUS FASTCALL
1702 BuildDesktopNameList(
1703 HWINSTA hWindowStation
,
1706 PULONG pRequiredSize
)
1709 PWINSTATION_OBJECT WindowStation
;
1710 PLIST_ENTRY DesktopEntry
;
1711 PDESKTOP DesktopObject
;
1715 UNICODE_STRING DesktopName
;
1717 Status
= IntValidateWindowStationHandle(hWindowStation
,
1722 if (! NT_SUCCESS(Status
))
1728 * Count the required size of buffer.
1730 ReturnLength
= sizeof(DWORD
);
1732 for (DesktopEntry
= WindowStation
->DesktopListHead
.Flink
;
1733 DesktopEntry
!= &WindowStation
->DesktopListHead
;
1734 DesktopEntry
= DesktopEntry
->Flink
)
1736 DesktopObject
= CONTAINING_RECORD(DesktopEntry
, DESKTOP
, ListEntry
);
1737 RtlInitUnicodeString(&DesktopName
, DesktopObject
->pDeskInfo
->szDesktopName
);
1738 ReturnLength
+= DesktopName
.Length
+ sizeof(WCHAR
);
1741 TRACE("Required size: %lu Entry count: %lu\n", ReturnLength
, EntryCount
);
1742 if (NULL
!= pRequiredSize
)
1744 Status
= MmCopyToCaller(pRequiredSize
, &ReturnLength
, sizeof(ULONG
));
1745 if (! NT_SUCCESS(Status
))
1747 ObDereferenceObject(WindowStation
);
1748 return STATUS_BUFFER_TOO_SMALL
;
1753 * Check if the supplied buffer is large enough.
1755 if (dwSize
< ReturnLength
)
1757 ObDereferenceObject(WindowStation
);
1758 return STATUS_BUFFER_TOO_SMALL
;
1762 * Generate the resulting buffer contents.
1764 Status
= MmCopyToCaller(lpBuffer
, &EntryCount
, sizeof(DWORD
));
1765 if (! NT_SUCCESS(Status
))
1767 ObDereferenceObject(WindowStation
);
1770 lpBuffer
= (PVOID
) ((PCHAR
) lpBuffer
+ sizeof(DWORD
));
1773 for (DesktopEntry
= WindowStation
->DesktopListHead
.Flink
;
1774 DesktopEntry
!= &WindowStation
->DesktopListHead
;
1775 DesktopEntry
= DesktopEntry
->Flink
)
1777 DesktopObject
= CONTAINING_RECORD(DesktopEntry
, DESKTOP
, ListEntry
);
1778 RtlInitUnicodeString(&DesktopName
, DesktopObject
->pDeskInfo
->szDesktopName
);
1779 Status
= MmCopyToCaller(lpBuffer
, DesktopName
.Buffer
, DesktopName
.Length
);
1780 if (! NT_SUCCESS(Status
))
1782 ObDereferenceObject(WindowStation
);
1785 lpBuffer
= (PVOID
) ((PCHAR
)lpBuffer
+ DesktopName
.Length
);
1786 Status
= MmCopyToCaller(lpBuffer
, &NullWchar
, sizeof(WCHAR
));
1787 if (! NT_SUCCESS(Status
))
1789 ObDereferenceObject(WindowStation
);
1792 lpBuffer
= (PVOID
) ((PCHAR
) lpBuffer
+ sizeof(WCHAR
));
1796 * Clean up and return
1798 ObDereferenceObject(WindowStation
);
1799 return STATUS_SUCCESS
;
1803 * NtUserBuildNameList
1805 * Function used for enumeration of desktops or window stations.
1809 * For enumeration of window stations this parameter must be set to
1810 * zero. Otherwise it's handle for window station.
1813 * Size of buffer passed by caller.
1816 * Buffer passed by caller. If the function succeeds, the buffer is
1817 * filled with window station/desktop count (in first DWORD) and
1818 * NULL-terminated window station/desktop names.
1821 * If the function succeeds, this is the number of bytes copied.
1822 * Otherwise it's size of buffer needed for function to succeed.
1829 NtUserBuildNameList(
1830 HWINSTA hWindowStation
,
1833 PULONG pRequiredSize
)
1835 /* The WindowStation name list and desktop name list are build in completely
1836 different ways. Call the appropriate function */
1837 return NULL
== hWindowStation
? BuildWindowStationNameList(dwSize
, lpBuffer
, pRequiredSize
) :
1838 BuildDesktopNameList(hWindowStation
, dwSize
, lpBuffer
, pRequiredSize
);
1845 NtUserSetLogonNotifyWindow(HWND hWnd
)
1847 if (gpidLogon
!= PsGetCurrentProcessId())
1852 if (!IntIsWindow(hWnd
))
1864 NtUserLockWorkStation(VOID
)
1867 PTHREADINFO pti
= PsGetCurrentThreadWin32Thread();
1869 UserEnterExclusive();
1871 if (pti
->rpdesk
== IntGetActiveDesktop())
1873 ret
= UserPostMessage(hwndSAS
, WM_LOGONNOTIFY
, LN_LOCK_WORKSTATION
, 0);
1887 NtUserSetWindowStationUser(
1888 IN HWINSTA hWindowStation
,
1890 IN PSID psid OPTIONAL
,
1895 PWINSTATION_OBJECT WindowStation
= NULL
;
1898 UserEnterExclusive();
1900 if (gpidLogon
!= PsGetCurrentProcessId())
1902 EngSetLastError(ERROR_ACCESS_DENIED
);
1906 /* Validate the window station */
1907 Status
= IntValidateWindowStationHandle(hWindowStation
,
1912 if (!NT_SUCCESS(Status
))
1917 /* Capture the user LUID */
1920 ProbeForRead(pluid
, sizeof(LUID
), 1);
1923 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1925 Status
= _SEH2_GetExceptionCode();
1926 _SEH2_YIELD(goto Leave
);
1930 /* Reset the window station user LUID */
1931 RtlZeroMemory(&WindowStation
->luidUser
, sizeof(LUID
));
1933 /* Reset the window station user SID */
1934 if (WindowStation
->psidUser
)
1936 ExFreePoolWithTag(WindowStation
->psidUser
, USERTAG_SECURITY
);
1937 WindowStation
->psidUser
= NULL
;
1940 /* Copy the new user SID if one has been provided */
1943 WindowStation
->psidUser
= ExAllocatePoolWithTag(PagedPool
, size
, USERTAG_SECURITY
);
1944 if (WindowStation
->psidUser
== NULL
)
1946 EngSetLastError(ERROR_OUTOFMEMORY
);
1950 Status
= STATUS_SUCCESS
;
1953 ProbeForRead(psid
, size
, 1);
1954 RtlCopyMemory(WindowStation
->psidUser
, psid
, size
);
1956 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1958 Status
= _SEH2_GetExceptionCode();
1962 if (!NT_SUCCESS(Status
))
1964 ExFreePoolWithTag(WindowStation
->psidUser
, USERTAG_SECURITY
);
1965 WindowStation
->psidUser
= NULL
;
1970 /* Copy the new user LUID */
1971 WindowStation
->luidUser
= luidUser
;
1977 ObDereferenceObject(WindowStation
);