2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 * COPYRIGHT: See COPYING in the top level directory
20 * PROJECT: ReactOS kernel
21 * PURPOSE: Window stations
22 * FILE: subsys/win32k/ntuser/winsta.c
23 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
25 * 06-06-2001 CSH Created
26 * NOTES: Exported functions set the Win32 last error value
27 * on errors. The value can be retrieved with the Win32
28 * function GetLastError().
29 * TODO: The process window station is created on
30 * the first USER32/GDI32 call not related
31 * to window station/desktop handling
34 /* INCLUDES ******************************************************************/
41 /* GLOBALS *******************************************************************/
43 /* Currently active window station */
44 PWINSTATION_OBJECT InputWindowStation
= NULL
;
46 /* INITALIZATION FUNCTIONS ****************************************************/
48 static GENERIC_MAPPING IntWindowStationMapping
=
50 STANDARD_RIGHTS_READ
| WINSTA_ENUMDESKTOPS
| WINSTA_ENUMERATE
| WINSTA_READATTRIBUTES
| WINSTA_READSCREEN
,
51 STANDARD_RIGHTS_WRITE
| WINSTA_ACCESSCLIPBOARD
| WINSTA_CREATEDESKTOP
| WINSTA_WRITEATTRIBUTES
,
52 STANDARD_RIGHTS_EXECUTE
| WINSTA_ACCESSGLOBALATOMS
| WINSTA_EXITWINDOWS
,
53 STANDARD_RIGHTS_REQUIRED
| WINSTA_ACCESSCLIPBOARD
| WINSTA_ACCESSGLOBALATOMS
| WINSTA_CREATEDESKTOP
|
54 WINSTA_ENUMDESKTOPS
| WINSTA_ENUMERATE
| WINSTA_EXITWINDOWS
|
55 WINSTA_READATTRIBUTES
| WINSTA_READSCREEN
| WINSTA_WRITEATTRIBUTES
59 InitWindowStationImpl(VOID
)
61 OBJECT_ATTRIBUTES ObjectAttributes
;
62 HANDLE WindowStationsDirectory
;
63 UNICODE_STRING UnicodeString
;
67 * Create the '\Windows\WindowStations' directory
70 RtlInitUnicodeString(&UnicodeString
, WINSTA_ROOT_NAME
);
71 InitializeObjectAttributes(&ObjectAttributes
, &UnicodeString
,
73 Status
= ZwCreateDirectoryObject(&WindowStationsDirectory
, 0,
75 if (!NT_SUCCESS(Status
))
77 DPRINT("Could not create \\Windows\\WindowStations directory "
78 "(Status 0x%X)\n", Status
);
82 /* Set Winsta Object Attributes */
83 ExWindowStationObjectType
->TypeInfo
.DefaultNonPagedPoolCharge
= sizeof(WINSTATION_OBJECT
);
84 ExWindowStationObjectType
->TypeInfo
.GenericMapping
= IntWindowStationMapping
;
86 return STATUS_SUCCESS
;
90 CleanupWindowStationImpl(VOID
)
92 return STATUS_SUCCESS
;
95 /* OBJECT CALLBACKS **********************************************************/
98 IntWinStaObjectDelete(PWIN32_DELETEMETHOD_PARAMETERS Parameters
)
100 PWINSTATION_OBJECT WinSta
= (PWINSTATION_OBJECT
)Parameters
->Object
;
102 DPRINT("Deleting window station (0x%X)\n", WinSta
);
104 RtlDestroyAtomTable(WinSta
->AtomTable
);
106 RtlFreeUnicodeString(&WinSta
->Name
);
111 IntWinStaObjectParse(PWIN32_PARSEMETHOD_PARAMETERS Parameters
)
113 PUNICODE_STRING RemainingName
= Parameters
->RemainingName
;
115 /* Assume we don't find anything */
116 *Parameters
->Object
= NULL
;
118 /* Check for an empty name */
119 if (!RemainingName
->Length
)
121 /* Make sure this is a window station, can't parse a desktop now */
122 if (Parameters
->ObjectType
!= ExWindowStationObjectType
)
125 return STATUS_OBJECT_TYPE_MISMATCH
;
128 /* Reference the window station and return */
129 ObReferenceObject(Parameters
->ParseObject
);
130 *Parameters
->Object
= Parameters
->ParseObject
;
131 return STATUS_SUCCESS
;
134 /* Check for leading slash */
135 if (RemainingName
->Buffer
[0] == OBJ_NAME_PATH_SEPARATOR
)
138 RemainingName
->Buffer
++;
139 RemainingName
->Length
-= sizeof(WCHAR
);
140 RemainingName
->MaximumLength
-= sizeof(WCHAR
);
143 /* Check if there is still a slash */
144 if (wcschr(RemainingName
->Buffer
, OBJ_NAME_PATH_SEPARATOR
))
146 /* In this case, fail */
147 return STATUS_OBJECT_PATH_INVALID
;
151 * Check if we are parsing a desktop.
153 if (Parameters
->ObjectType
== ExDesktopObjectType
)
155 /* Then call the desktop parse routine */
156 return IntDesktopObjectParse(Parameters
->ParseObject
,
157 Parameters
->ObjectType
,
158 Parameters
->AccessState
,
159 Parameters
->AccessMode
,
160 Parameters
->Attributes
,
161 Parameters
->CompleteName
,
164 Parameters
->SecurityQos
,
168 /* Should hopefully never get here */
169 return STATUS_OBJECT_TYPE_MISMATCH
;
172 /* PRIVATE FUNCTIONS **********************************************************/
175 * IntGetFullWindowStationName
177 * Get a full window station object name from a name specified in
178 * NtUserCreateWindowStation, NtUserOpenWindowStation, NtUserCreateDesktop
179 * or NtUserOpenDesktop.
182 * TRUE on success, FALSE on failure.
186 IntGetFullWindowStationName(
187 OUT PUNICODE_STRING FullName
,
188 IN PUNICODE_STRING WinStaName
,
189 IN OPTIONAL PUNICODE_STRING DesktopName
)
193 FullName
->Length
= WINSTA_ROOT_NAME_LENGTH
* sizeof(WCHAR
);
194 if (WinStaName
!= NULL
)
195 FullName
->Length
+= WinStaName
->Length
+ sizeof(WCHAR
);
196 if (DesktopName
!= NULL
)
197 FullName
->Length
+= DesktopName
->Length
+ sizeof(WCHAR
);
198 FullName
->MaximumLength
= FullName
->Length
;
199 FullName
->Buffer
= ExAllocatePoolWithTag(PagedPool
, FullName
->Length
, TAG_STRING
);
200 if (FullName
->Buffer
== NULL
)
205 Buffer
= FullName
->Buffer
;
206 memcpy(Buffer
, WINSTA_ROOT_NAME
, WINSTA_ROOT_NAME_LENGTH
* sizeof(WCHAR
));
207 Buffer
+= WINSTA_ROOT_NAME_LENGTH
;
208 if (WinStaName
!= NULL
)
210 memcpy(Buffer
, L
"\\", sizeof(WCHAR
));
212 memcpy(Buffer
, WinStaName
->Buffer
, WinStaName
->Length
);
214 if (DesktopName
!= NULL
)
216 Buffer
+= WinStaName
->Length
/ sizeof(WCHAR
);
217 memcpy(Buffer
, L
"\\", sizeof(WCHAR
));
219 memcpy(Buffer
, DesktopName
->Buffer
, DesktopName
->Length
);
227 * IntValidateWindowStationHandle
229 * Validates the window station handle.
232 * If the function succeeds, the handle remains referenced. If the
233 * fucntion fails, last error is set.
237 IntValidateWindowStationHandle(
238 HWINSTA WindowStation
,
239 KPROCESSOR_MODE AccessMode
,
240 ACCESS_MASK DesiredAccess
,
241 PWINSTATION_OBJECT
*Object
)
245 if (WindowStation
== NULL
)
247 // DPRINT1("Invalid window station handle\n");
248 SetLastWin32Error(ERROR_INVALID_HANDLE
);
249 return STATUS_INVALID_HANDLE
;
252 Status
= ObReferenceObjectByHandle(
255 ExWindowStationObjectType
,
260 if (!NT_SUCCESS(Status
))
261 SetLastNtError(Status
);
267 IntGetWindowStationObject(PWINSTATION_OBJECT Object
)
271 Status
= ObReferenceObjectByPointer(
274 ExWindowStationObjectType
,
277 return NT_SUCCESS(Status
);
281 co_IntInitializeDesktopGraphics(VOID
)
283 UNICODE_STRING DriverName
;
284 if (! IntCreatePrimarySurface())
288 RtlInitUnicodeString(&DriverName
, L
"DISPLAY");
289 ScreenDeviceContext
= IntGdiCreateDC(&DriverName
, NULL
, NULL
, NULL
, FALSE
);
290 if (NULL
== ScreenDeviceContext
)
292 IntDestroyPrimarySurface();
295 DC_SetOwnership(ScreenDeviceContext
, NULL
);
297 UserAcquireOrReleaseInputOwnership(FALSE
);
299 /* Setup the cursor */
300 co_IntLoadDefaultCursors();
306 IntEndDesktopGraphics(VOID
)
308 UserAcquireOrReleaseInputOwnership(TRUE
);
309 if (NULL
!= ScreenDeviceContext
)
311 DC_SetOwnership(ScreenDeviceContext
, PsGetCurrentProcess());
312 NtGdiDeleteObjectApp(ScreenDeviceContext
);
313 ScreenDeviceContext
= NULL
;
315 IntHideDesktop(IntGetActiveDesktop());
316 IntDestroyPrimarySurface();
322 return ScreenDeviceContext
;
325 /* PUBLIC FUNCTIONS ***********************************************************/
328 * NtUserCreateWindowStation
330 * Creates a new window station.
333 * lpszWindowStationName
334 * Pointer to a null-terminated string specifying the name of the
335 * window station to be created. Window station names are
336 * case-insensitive and cannot contain backslash characters (\).
337 * Only members of the Administrators group are allowed to specify a
341 * Requested type of access
344 * Security descriptor
346 * Unknown3, Unknown4, Unknown5
350 * If the function succeeds, the return value is a handle to the newly
351 * created window station. If the specified window station already
352 * exists, the function succeeds and returns a handle to the existing
353 * window station. If the function fails, the return value is NULL.
356 * Correct the prototype to match the Windows one (with 7 parameters
364 NtUserCreateWindowStation(
365 PUNICODE_STRING lpszWindowStationName
,
366 ACCESS_MASK dwDesiredAccess
,
367 LPSECURITY_ATTRIBUTES lpSecurity
,
372 PSYSTEM_CURSORINFO CurInfo
;
373 UNICODE_STRING WindowStationName
;
374 UNICODE_STRING FullWindowStationName
;
375 PWINSTATION_OBJECT WindowStationObject
;
376 HWINSTA WindowStation
;
377 OBJECT_ATTRIBUTES ObjectAttributes
;
381 * Generate full window station name
383 Status
= ProbeAndCaptureUnicodeString(&WindowStationName
,
385 lpszWindowStationName
);
386 if (!NT_SUCCESS(Status
))
388 DPRINT1("Failed to capture window station name (status 0x%08x)\n",
390 SetLastNtError(Status
);
393 if (!IntGetFullWindowStationName(&FullWindowStationName
,
397 ReleaseCapturedUnicodeString(&WindowStationName
, UserMode
);
398 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
403 * Try to open already existing window station
406 DPRINT("Trying to open window station (%wZ)\n", &FullWindowStationName
);
408 /* Initialize ObjectAttributes for the window station object */
409 InitializeObjectAttributes(
411 &FullWindowStationName
,
416 Status
= ObOpenObjectByName(
418 ExWindowStationObjectType
,
423 (PVOID
*)&WindowStation
);
425 if (NT_SUCCESS(Status
))
427 DPRINT("Successfully opened window station (%wZ)\n",
428 FullWindowStationName
);
429 ExFreePool(FullWindowStationName
.Buffer
);
430 ReleaseCapturedUnicodeString(&WindowStationName
, UserMode
);
431 return (HWINSTA
)WindowStation
;
435 * No existing window station found, try to create new one
438 DPRINT("Creating window station (%wZ)\n", &FullWindowStationName
);
440 Status
= ObCreateObject(
442 ExWindowStationObjectType
,
446 sizeof(WINSTATION_OBJECT
),
449 (PVOID
*)&WindowStationObject
);
451 if (!NT_SUCCESS(Status
))
453 DPRINT1("Failed creating window station (%wZ)\n", &FullWindowStationName
);
454 ExFreePool(FullWindowStationName
.Buffer
);
455 ReleaseCapturedUnicodeString(&WindowStationName
, UserMode
);
456 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
460 KeInitializeSpinLock(&WindowStationObject
->Lock
);
462 InitializeListHead(&WindowStationObject
->DesktopListHead
);
464 WindowStationObject
->AtomTable
= NULL
;
465 Status
= RtlCreateAtomTable(37, &WindowStationObject
->AtomTable
);
466 WindowStationObject
->SystemMenuTemplate
= (HANDLE
)0;
468 WindowStationObject
->Name
= WindowStationName
;
470 Status
= ObInsertObject(
471 (PVOID
)WindowStationObject
,
473 STANDARD_RIGHTS_REQUIRED
,
476 (PVOID
*)&WindowStation
);
478 if (!NT_SUCCESS(Status
))
480 DPRINT1("Failed creating window station (%wZ)\n", &FullWindowStationName
);
481 ExFreePool(FullWindowStationName
.Buffer
);
482 ExFreePool(WindowStationName
.Buffer
);
483 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
484 ObDereferenceObject(WindowStationObject
);
489 * Initialize the new window station object
491 WindowStationObject
->ScreenSaverRunning
= FALSE
;
492 WindowStationObject
->ScreenSaverTimeOut
= 30;
493 WindowStationObject
->FlatMenu
= FALSE
;
495 if(!(CurInfo
= ExAllocatePool(PagedPool
, sizeof(SYSTEM_CURSORINFO
))))
497 ExFreePool(FullWindowStationName
.Buffer
);
498 /* FIXME - Delete window station object */
499 ObDereferenceObject(WindowStationObject
);
500 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
504 CurInfo
->Enabled
= FALSE
;
505 CurInfo
->ButtonsDown
= 0;
506 CurInfo
->CursorClipInfo
.IsClipped
= FALSE
;
507 CurInfo
->LastBtnDown
= 0;
508 CurInfo
->CurrentCursorObject
= NULL
;
509 CurInfo
->ShowingCursor
= 0;
511 CurInfo
->WheelScroLines
= 3;
512 CurInfo
->WheelScroChars
= 3;
516 /* FIXME: Obtain the following information from the registry */
517 CurInfo
->SwapButtons
= FALSE
;
518 CurInfo
->DblClickSpeed
= 500;
519 CurInfo
->DblClickWidth
= 4;
520 CurInfo
->DblClickHeight
= 4;
522 WindowStationObject
->SystemCursor
= CurInfo
;
524 if (!IntSetupCurIconHandles(WindowStationObject
))
526 DPRINT1("Setting up the Cursor/Icon Handle table failed!\n");
527 /* FIXME: Complain more loudly? */
528 ExFreePool(FullWindowStationName
.Buffer
);
531 DPRINT("Window station successfully created (%wZ)\n", FullWindowStationName
);
532 ExFreePool(FullWindowStationName
.Buffer
);
533 return WindowStation
;
537 * NtUserOpenWindowStation
539 * Opens an existing window station.
542 * lpszWindowStationName
543 * Name of the existing window station.
546 * Requested type of access.
549 * If the function succeeds, the return value is the handle to the
550 * specified window station. If the function fails, the return value
554 * The returned handle can be closed with NtUserCloseWindowStation.
561 NtUserOpenWindowStation(
562 PUNICODE_STRING lpszWindowStationName
,
563 ACCESS_MASK dwDesiredAccess
)
565 UNICODE_STRING WindowStationName
;
566 HWINSTA WindowStation
;
567 OBJECT_ATTRIBUTES ObjectAttributes
;
571 * Generate full window station name
574 if (!IntGetFullWindowStationName(&WindowStationName
, lpszWindowStationName
,
577 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
581 DPRINT("Trying to open window station (%wZ)\n", &WindowStationName
);
583 /* Initialize ObjectAttributes for the window station object */
584 InitializeObjectAttributes(
591 Status
= ObOpenObjectByName(
593 ExWindowStationObjectType
,
598 (PVOID
*)&WindowStation
);
600 if (!NT_SUCCESS(Status
))
602 SetLastNtError(Status
);
603 ExFreePool(WindowStationName
.Buffer
);
607 DPRINT("Successfully opened window station (%wZ)\n", &WindowStationName
);
608 ExFreePool(WindowStationName
.Buffer
);
610 return WindowStation
;
614 * NtUserCloseWindowStation
616 * Closes a window station handle.
620 * Handle to the window station.
626 * The window station handle can be created with NtUserCreateWindowStation
627 * or NtUserOpenWindowStation. Attemps to close a handle to the window
628 * station assigned to the calling process will fail.
636 NtUserCloseWindowStation(
639 PWINSTATION_OBJECT Object
;
642 DPRINT("About to close window station handle (0x%X)\n", hWinSta
);
644 Status
= IntValidateWindowStationHandle(
650 if (!NT_SUCCESS(Status
))
652 DPRINT("Validation of window station handle (0x%X) failed\n", hWinSta
);
657 /* FIXME - free the cursor information when actually deleting the object!! */
658 ASSERT(Object
->SystemCursor
);
659 ExFreePool(Object
->SystemCursor
);
662 ObDereferenceObject(Object
);
664 DPRINT("Closing window station handle (0x%X)\n", hWinSta
);
666 Status
= ZwClose(hWinSta
);
667 if (!NT_SUCCESS(Status
))
669 SetLastNtError(Status
);
677 * NtUserGetObjectInformation
679 * The NtUserGetObjectInformation function retrieves information about a
680 * window station or desktop object.
684 * Handle to the window station or desktop object for which to
685 * return information. This can be a handle of type HDESK or HWINSTA
686 * (for example, a handle returned by NtUserCreateWindowStation,
687 * NtUserOpenWindowStation, NtUserCreateDesktop, or NtUserOpenDesktop).
690 * Specifies the object information to be retrieved.
693 * Pointer to a buffer to receive the object information.
696 * Specifies the size, in bytes, of the buffer pointed to by the
700 * Pointer to a variable receiving the number of bytes required to
701 * store the requested information. If this variable's value is
702 * greater than the value of the nLength parameter when the function
703 * returns, the function returns FALSE, and none of the information
704 * is copied to the pvInfo buffer. If the value of the variable pointed
705 * to by lpnLengthNeeded is less than or equal to the value of nLength,
706 * the entire information block is copied.
709 * If the function succeeds, the return value is nonzero. If the function
710 * fails, the return value is zero.
717 NtUserGetObjectInformation(
722 PDWORD nLengthNeeded
)
724 PWINSTATION_OBJECT WinStaObject
= NULL
;
725 PDESKTOP_OBJECT DesktopObject
= NULL
;
730 /* try windowstation */
731 DPRINT("Trying to open window station 0x%x\n", hObject
);
732 Status
= IntValidateWindowStationHandle(
734 UserMode
,/*ExGetPreviousMode(),*/
735 GENERIC_READ
, /* FIXME: is this ok? */
739 if (!NT_SUCCESS(Status
) && Status
!= STATUS_OBJECT_TYPE_MISMATCH
)
741 DPRINT("Failed: 0x%x\n", Status
);
742 SetLastNtError(Status
);
746 if (Status
== STATUS_OBJECT_TYPE_MISMATCH
)
749 DPRINT("Trying to open desktop 0x%x\n", hObject
);
750 Status
= IntValidateDesktopHandle(
752 UserMode
,/*ExGetPreviousMode(),*/
753 GENERIC_READ
, /* FIXME: is this ok? */
755 if (!NT_SUCCESS(Status
))
757 DPRINT("Failed: 0x%x\n", Status
);
758 SetLastNtError(Status
);
762 DPRINT("WinSta or Desktop opened!!\n");
768 Status
= STATUS_NOT_IMPLEMENTED
;
769 DPRINT1("UOI_FLAGS unimplemented!\n");
773 if (WinStaObject
!= NULL
)
775 pvData
= ((PUNICODE_STRING
)GET_DESKTOP_NAME(WinStaObject
))->Buffer
;
776 nDataSize
= ((PUNICODE_STRING
)GET_DESKTOP_NAME(WinStaObject
))->Length
+ 2;
777 Status
= STATUS_SUCCESS
;
779 else if (DesktopObject
!= NULL
)
781 pvData
= ((PUNICODE_STRING
)GET_DESKTOP_NAME(DesktopObject
))->Buffer
;
782 nDataSize
= ((PUNICODE_STRING
)GET_DESKTOP_NAME(DesktopObject
))->Length
+ 2;
783 Status
= STATUS_SUCCESS
;
786 Status
= STATUS_INVALID_PARAMETER
;
790 if (WinStaObject
!= NULL
)
792 pvData
= L
"WindowStation";
793 nDataSize
= (wcslen(pvData
) + 1) * sizeof(WCHAR
);
794 Status
= STATUS_SUCCESS
;
796 else if (DesktopObject
!= NULL
)
799 nDataSize
= (wcslen(pvData
) + 1) * sizeof(WCHAR
);
800 Status
= STATUS_SUCCESS
;
803 Status
= STATUS_INVALID_PARAMETER
;
807 Status
= STATUS_NOT_IMPLEMENTED
;
808 DPRINT1("UOI_USER_SID unimplemented!\n");
812 Status
= STATUS_INVALID_PARAMETER
;
816 /* try to copy data to caller */
817 if (Status
== STATUS_SUCCESS
)
819 DPRINT("Trying to copy data to caller (len = %d, len needed = %d)\n", nLength
, nDataSize
);
820 *nLengthNeeded
= nDataSize
;
821 if (nLength
>= nDataSize
)
822 Status
= MmCopyToCaller(pvInformation
, pvData
, nDataSize
);
824 Status
= STATUS_BUFFER_TOO_SMALL
;
827 /* release objects */
828 if (WinStaObject
!= NULL
)
829 ObDereferenceObject(WinStaObject
);
830 if (DesktopObject
!= NULL
)
831 ObDereferenceObject(DesktopObject
);
833 SetLastNtError(Status
);
834 return NT_SUCCESS(Status
);
838 * NtUserSetObjectInformation
840 * The NtUserSetObjectInformation function sets information about a
841 * window station or desktop object.
845 * Handle to the window station or desktop object for which to set
846 * object information. This value can be a handle of type HDESK or
850 * Specifies the object information to be set.
853 * Pointer to a buffer containing the object information.
856 * Specifies the size, in bytes, of the information contained in the
857 * buffer pointed to by pvInfo.
860 * If the function succeeds, the return value is nonzero. If the function
861 * fails the return value is zero.
869 NtUserSetObjectInformation(
875 /* FIXME: ZwQueryObject */
876 /* FIXME: ZwSetInformationObject */
877 SetLastNtError(STATUS_UNSUCCESSFUL
);
885 UserGetProcessWindowStation(VOID
)
890 if(PsGetCurrentProcess() != CsrProcess
)
892 return PsGetCurrentProcess()->Win32WindowStation
;
896 DPRINT1("Should use ObFindHandleForObject\n");
897 Status
= ObOpenObjectByPointer(PsGetWin32Thread()->Desktop
->WindowStation
,
901 ExWindowStationObjectType
,
904 if (! NT_SUCCESS(Status
))
906 SetLastNtError(Status
);
907 DPRINT1("Unable to open handle for CSRSSs winsta, status 0x%08x\n",
917 * NtUserGetProcessWindowStation
919 * Returns a handle to the current process window station.
922 * If the function succeeds, the return value is handle to the window
923 * station assigned to the current process. If the function fails, the
924 * return value is NULL.
931 NtUserGetProcessWindowStation(VOID
)
933 return UserGetProcessWindowStation();
936 PWINSTATION_OBJECT FASTCALL
937 IntGetWinStaObj(VOID
)
939 PWINSTATION_OBJECT WinStaObj
;
942 * just a temporary hack, this will be gone soon
945 if(PsGetWin32Thread() != NULL
&& PsGetWin32Thread()->Desktop
!= NULL
)
947 WinStaObj
= PsGetWin32Thread()->Desktop
->WindowStation
;
948 ObReferenceObjectByPointer(WinStaObj
, KernelMode
, ExWindowStationObjectType
, 0);
950 else if(PsGetCurrentProcess() != CsrProcess
)
952 NTSTATUS Status
= IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation
,
956 if(!NT_SUCCESS(Status
))
958 SetLastNtError(Status
);
971 * NtUserSetProcessWindowStation
973 * Assigns a window station to the current process.
977 * Handle to the window station.
987 NtUserSetProcessWindowStation(HWINSTA hWindowStation
)
990 PWINSTATION_OBJECT NewWinSta
;
993 DPRINT("About to set process window station with handle (0x%X)\n",
996 if(PsGetCurrentProcess() == CsrProcess
)
998 DPRINT1("CSRSS is not allowed to change it's window station!!!\n");
999 SetLastWin32Error(ERROR_ACCESS_DENIED
);
1003 Status
= IntValidateWindowStationHandle(
1009 if (!NT_SUCCESS(Status
))
1011 DPRINT("Validation of window station handle (0x%X) failed\n",
1013 SetLastNtError(Status
);
1018 * FIXME - don't allow changing the window station if there are threads that are attached to desktops and own gui objects
1021 /* FIXME - dereference the old window station, etc... */
1022 hOld
= InterlockedExchangePointer(&PsGetCurrentProcess()->Win32WindowStation
, hWindowStation
);
1024 DPRINT("PsGetCurrentProcess()->Win32WindowStation 0x%X\n",
1025 PsGetCurrentProcess()->Win32WindowStation
);
1031 * NtUserLockWindowStation
1033 * Locks switching desktops. Only the logon application is allowed to call this function.
1040 NtUserLockWindowStation(HWINSTA hWindowStation
)
1042 PWINSTATION_OBJECT Object
;
1045 DPRINT("About to set process window station with handle (0x%X)\n",
1048 if(PsGetWin32Process() != LogonProcess
)
1050 DPRINT1("Unauthorized process attempted to lock the window station!\n");
1051 SetLastWin32Error(ERROR_ACCESS_DENIED
);
1055 Status
= IntValidateWindowStationHandle(
1060 if (!NT_SUCCESS(Status
))
1062 DPRINT("Validation of window station handle (0x%X) failed\n",
1064 SetLastNtError(Status
);
1068 Object
->Flags
|= WSS_LOCKED
;
1070 ObDereferenceObject(Object
);
1075 * NtUserUnlockWindowStation
1077 * Unlocks switching desktops. Only the logon application is allowed to call this function.
1084 NtUserUnlockWindowStation(HWINSTA hWindowStation
)
1086 PWINSTATION_OBJECT Object
;
1090 DPRINT("About to set process window station with handle (0x%X)\n",
1093 if(PsGetWin32Process() != LogonProcess
)
1095 DPRINT1("Unauthorized process attempted to unlock the window station!\n");
1096 SetLastWin32Error(ERROR_ACCESS_DENIED
);
1100 Status
= IntValidateWindowStationHandle(
1105 if (!NT_SUCCESS(Status
))
1107 DPRINT("Validation of window station handle (0x%X) failed\n",
1109 SetLastNtError(Status
);
1113 Ret
= (Object
->Flags
& WSS_LOCKED
) == WSS_LOCKED
;
1114 Object
->Flags
&= ~WSS_LOCKED
;
1116 ObDereferenceObject(Object
);
1121 * NtUserSetWindowStationUser
1128 NtUserSetWindowStationUser(
1139 static NTSTATUS FASTCALL
1140 BuildWindowStationNameList(
1143 PULONG pRequiredSize
)
1145 OBJECT_ATTRIBUTES ObjectAttributes
;
1147 HANDLE DirectoryHandle
;
1148 UNICODE_STRING DirectoryName
;
1149 char InitialBuffer
[256], *Buffer
;
1150 ULONG Context
, ReturnLength
, BufferSize
;
1152 POBJECT_DIRECTORY_INFORMATION DirEntry
;
1156 * Generate name of window station directory
1158 if (!IntGetFullWindowStationName(&DirectoryName
, NULL
, NULL
))
1160 return STATUS_INSUFFICIENT_RESOURCES
;
1164 * Try to open the directory.
1166 InitializeObjectAttributes(
1169 OBJ_CASE_INSENSITIVE
,
1173 Status
= ZwOpenDirectoryObject(
1178 ExFreePool(DirectoryName
.Buffer
);
1180 if (!NT_SUCCESS(Status
))
1185 /* First try to query the directory using a fixed-size buffer */
1188 Status
= ZwQueryDirectoryObject(DirectoryHandle
, InitialBuffer
, sizeof(InitialBuffer
),
1189 FALSE
, TRUE
, &Context
, &ReturnLength
);
1190 if (NT_SUCCESS(Status
))
1192 if (STATUS_NO_MORE_ENTRIES
== ZwQueryDirectoryObject(DirectoryHandle
, NULL
, 0, FALSE
,
1193 FALSE
, &Context
, NULL
))
1195 /* Our fixed-size buffer is large enough */
1196 Buffer
= InitialBuffer
;
1202 /* Need a larger buffer, check how large exactly */
1203 Status
= ZwQueryDirectoryObject(DirectoryHandle
, NULL
, 0, FALSE
, TRUE
, &Context
,
1205 if (STATUS_BUFFER_TOO_SMALL
== Status
)
1207 BufferSize
= ReturnLength
;
1208 Buffer
= ExAllocatePoolWithTag(PagedPool
, BufferSize
, TAG_WINSTA
);
1211 ObDereferenceObject(DirectoryHandle
);
1212 return STATUS_NO_MEMORY
;
1215 /* We should have a sufficiently large buffer now */
1217 Status
= ZwQueryDirectoryObject(DirectoryHandle
, Buffer
, BufferSize
,
1218 FALSE
, TRUE
, &Context
, &ReturnLength
);
1219 if (! NT_SUCCESS(Status
) ||
1220 STATUS_NO_MORE_ENTRIES
!= ZwQueryDirectoryObject(DirectoryHandle
, NULL
, 0, FALSE
,
1221 FALSE
, &Context
, NULL
))
1223 /* Something went wrong, maybe someone added a directory entry? Just give up. */
1225 ObDereferenceObject(DirectoryHandle
);
1226 return NT_SUCCESS(Status
) ? STATUS_INTERNAL_ERROR
: Status
;
1231 ZwClose(DirectoryHandle
);
1234 * Count the required size of buffer.
1236 ReturnLength
= sizeof(DWORD
);
1238 for (DirEntry
= (POBJECT_DIRECTORY_INFORMATION
) Buffer
; 0 != DirEntry
->ObjectName
.Length
;
1241 ReturnLength
+= DirEntry
->ObjectName
.Length
+ sizeof(WCHAR
);
1244 DPRINT("Required size: %d Entry count: %d\n", ReturnLength
, EntryCount
);
1245 if (NULL
!= pRequiredSize
)
1247 Status
= MmCopyToCaller(pRequiredSize
, &ReturnLength
, sizeof(ULONG
));
1248 if (! NT_SUCCESS(Status
))
1250 if (Buffer
!= InitialBuffer
)
1254 return STATUS_BUFFER_TOO_SMALL
;
1259 * Check if the supplied buffer is large enough.
1261 if (dwSize
< ReturnLength
)
1263 if (Buffer
!= InitialBuffer
)
1267 return STATUS_BUFFER_TOO_SMALL
;
1271 * Generate the resulting buffer contents.
1273 Status
= MmCopyToCaller(lpBuffer
, &EntryCount
, sizeof(DWORD
));
1274 if (! NT_SUCCESS(Status
))
1276 if (Buffer
!= InitialBuffer
)
1282 lpBuffer
= (PVOID
) ((PCHAR
) lpBuffer
+ sizeof(DWORD
));
1285 for (DirEntry
= (POBJECT_DIRECTORY_INFORMATION
) Buffer
; 0 != DirEntry
->ObjectName
.Length
;
1288 Status
= MmCopyToCaller(lpBuffer
, DirEntry
->ObjectName
.Buffer
, DirEntry
->ObjectName
.Length
);
1289 if (! NT_SUCCESS(Status
))
1291 if (Buffer
!= InitialBuffer
)
1297 lpBuffer
= (PVOID
) ((PCHAR
) lpBuffer
+ DirEntry
->ObjectName
.Length
);
1298 Status
= MmCopyToCaller(lpBuffer
, &NullWchar
, sizeof(WCHAR
));
1299 if (! NT_SUCCESS(Status
))
1301 if (Buffer
!= InitialBuffer
)
1307 lpBuffer
= (PVOID
) ((PCHAR
) lpBuffer
+ sizeof(WCHAR
));
1313 if (NULL
!= Buffer
&& Buffer
!= InitialBuffer
)
1318 return STATUS_SUCCESS
;
1321 static NTSTATUS FASTCALL
1322 BuildDesktopNameList(
1323 HWINSTA hWindowStation
,
1326 PULONG pRequiredSize
)
1329 PWINSTATION_OBJECT WindowStation
;
1331 PLIST_ENTRY DesktopEntry
;
1332 PDESKTOP_OBJECT DesktopObject
;
1337 Status
= IntValidateWindowStationHandle(hWindowStation
,
1341 if (! NT_SUCCESS(Status
))
1346 KeAcquireSpinLock(&WindowStation
->Lock
, &OldLevel
);
1349 * Count the required size of buffer.
1351 ReturnLength
= sizeof(DWORD
);
1353 for (DesktopEntry
= WindowStation
->DesktopListHead
.Flink
;
1354 DesktopEntry
!= &WindowStation
->DesktopListHead
;
1355 DesktopEntry
= DesktopEntry
->Flink
)
1357 DesktopObject
= CONTAINING_RECORD(DesktopEntry
, DESKTOP_OBJECT
, ListEntry
);
1358 ReturnLength
+= ((PUNICODE_STRING
)GET_DESKTOP_NAME(DesktopObject
))->Length
+ sizeof(WCHAR
);
1361 DPRINT("Required size: %d Entry count: %d\n", ReturnLength
, EntryCount
);
1362 if (NULL
!= pRequiredSize
)
1364 Status
= MmCopyToCaller(pRequiredSize
, &ReturnLength
, sizeof(ULONG
));
1365 if (! NT_SUCCESS(Status
))
1367 KeReleaseSpinLock(&WindowStation
->Lock
, OldLevel
);
1368 ObDereferenceObject(WindowStation
);
1369 return STATUS_BUFFER_TOO_SMALL
;
1374 * Check if the supplied buffer is large enough.
1376 if (dwSize
< ReturnLength
)
1378 KeReleaseSpinLock(&WindowStation
->Lock
, OldLevel
);
1379 ObDereferenceObject(WindowStation
);
1380 return STATUS_BUFFER_TOO_SMALL
;
1384 * Generate the resulting buffer contents.
1386 Status
= MmCopyToCaller(lpBuffer
, &EntryCount
, sizeof(DWORD
));
1387 if (! NT_SUCCESS(Status
))
1389 KeReleaseSpinLock(&WindowStation
->Lock
, OldLevel
);
1390 ObDereferenceObject(WindowStation
);
1393 lpBuffer
= (PVOID
) ((PCHAR
) lpBuffer
+ sizeof(DWORD
));
1396 for (DesktopEntry
= WindowStation
->DesktopListHead
.Flink
;
1397 DesktopEntry
!= &WindowStation
->DesktopListHead
;
1398 DesktopEntry
= DesktopEntry
->Flink
)
1400 DesktopObject
= CONTAINING_RECORD(DesktopEntry
, DESKTOP_OBJECT
, ListEntry
);
1401 Status
= MmCopyToCaller(lpBuffer
, ((PUNICODE_STRING
)GET_DESKTOP_NAME(DesktopObject
))->Buffer
, ((PUNICODE_STRING
)GET_DESKTOP_NAME(DesktopObject
))->Length
);
1402 if (! NT_SUCCESS(Status
))
1404 KeReleaseSpinLock(&WindowStation
->Lock
, OldLevel
);
1405 ObDereferenceObject(WindowStation
);
1408 lpBuffer
= (PVOID
) ((PCHAR
) lpBuffer
+ ((PUNICODE_STRING
)GET_DESKTOP_NAME(DesktopObject
))->Length
);
1409 Status
= MmCopyToCaller(lpBuffer
, &NullWchar
, sizeof(WCHAR
));
1410 if (! NT_SUCCESS(Status
))
1412 KeReleaseSpinLock(&WindowStation
->Lock
, OldLevel
);
1413 ObDereferenceObject(WindowStation
);
1416 lpBuffer
= (PVOID
) ((PCHAR
) lpBuffer
+ sizeof(WCHAR
));
1422 KeReleaseSpinLock(&WindowStation
->Lock
, OldLevel
);
1423 ObDereferenceObject(WindowStation
);
1425 return STATUS_SUCCESS
;
1429 * NtUserBuildNameList
1431 * Function used for enumeration of desktops or window stations.
1435 * For enumeration of window stations this parameter must be set to
1436 * zero. Otherwise it's handle for window station.
1439 * Size of buffer passed by caller.
1442 * Buffer passed by caller. If the function succedes, the buffer is
1443 * filled with window station/desktop count (in first DWORD) and
1444 * NULL-terminated window station/desktop names.
1447 * If the function suceedes, this is the number of bytes copied.
1448 * Otherwise it's size of buffer needed for function to succeed.
1455 NtUserBuildNameList(
1456 HWINSTA hWindowStation
,
1459 PULONG pRequiredSize
)
1461 /* The WindowStation name list and desktop name list are build in completely
1462 different ways. Call the appropriate function */
1463 return NULL
== hWindowStation
? BuildWindowStationNameList(dwSize
, lpBuffer
, pRequiredSize
) :
1464 BuildDesktopNameList(hWindowStation
, dwSize
, lpBuffer
, pRequiredSize
);