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 along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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
62 InitWindowStationImpl(VOID
)
64 OBJECT_ATTRIBUTES ObjectAttributes
;
65 HANDLE WindowStationsDirectory
;
66 UNICODE_STRING UnicodeString
;
70 * Create the '\Windows\WindowStations' directory
73 RtlInitUnicodeString(&UnicodeString
, WINSTA_ROOT_NAME
);
74 InitializeObjectAttributes(&ObjectAttributes
, &UnicodeString
,
76 Status
= ZwCreateDirectoryObject(&WindowStationsDirectory
, 0,
78 if (!NT_SUCCESS(Status
))
80 DPRINT("Could not create \\Windows\\WindowStations directory "
81 "(Status 0x%X)\n", Status
);
85 /* Set Winsta Object Attributes */
86 ExWindowStationObjectType
->TypeInfo
.DefaultNonPagedPoolCharge
= sizeof(WINSTATION_OBJECT
);
87 ExWindowStationObjectType
->TypeInfo
.GenericMapping
= IntWindowStationMapping
;
89 return STATUS_SUCCESS
;
93 CleanupWindowStationImpl(VOID
)
95 return STATUS_SUCCESS
;
99 IntSetupClipboard(PWINSTATION_OBJECT WinStaObj
)
101 WinStaObj
->Clipboard
= ExAllocatePoolWithTag(PagedPool
, sizeof(CLIPBOARDSYSTEM
), TAG_WINSTA
);
102 if (WinStaObj
->Clipboard
)
104 RtlZeroMemory(WinStaObj
->Clipboard
, sizeof(CLIPBOARDSYSTEM
));
110 /* OBJECT CALLBACKS **********************************************************/
113 IntWinStaObjectDelete(PWIN32_DELETEMETHOD_PARAMETERS Parameters
)
115 PWINSTATION_OBJECT WinSta
= (PWINSTATION_OBJECT
)Parameters
->Object
;
117 DPRINT("Deleting window station (0x%X)\n", WinSta
);
119 RtlDestroyAtomTable(WinSta
->AtomTable
);
121 RtlFreeUnicodeString(&WinSta
->Name
);
126 IntWinStaObjectParse(PWIN32_PARSEMETHOD_PARAMETERS Parameters
)
128 PUNICODE_STRING RemainingName
= Parameters
->RemainingName
;
130 /* Assume we don't find anything */
131 *Parameters
->Object
= NULL
;
133 /* Check for an empty name */
134 if (!RemainingName
->Length
)
136 /* Make sure this is a window station, can't parse a desktop now */
137 if (Parameters
->ObjectType
!= ExWindowStationObjectType
)
140 return STATUS_OBJECT_TYPE_MISMATCH
;
143 /* Reference the window station and return */
144 ObReferenceObject(Parameters
->ParseObject
);
145 *Parameters
->Object
= Parameters
->ParseObject
;
146 return STATUS_SUCCESS
;
149 /* Check for leading slash */
150 if (RemainingName
->Buffer
[0] == OBJ_NAME_PATH_SEPARATOR
)
153 RemainingName
->Buffer
++;
154 RemainingName
->Length
-= sizeof(WCHAR
);
155 RemainingName
->MaximumLength
-= sizeof(WCHAR
);
158 /* Check if there is still a slash */
159 if (wcschr(RemainingName
->Buffer
, OBJ_NAME_PATH_SEPARATOR
))
161 /* In this case, fail */
162 return STATUS_OBJECT_PATH_INVALID
;
166 * Check if we are parsing a desktop.
168 if (Parameters
->ObjectType
== ExDesktopObjectType
)
170 /* Then call the desktop parse routine */
171 return IntDesktopObjectParse(Parameters
->ParseObject
,
172 Parameters
->ObjectType
,
173 Parameters
->AccessState
,
174 Parameters
->AccessMode
,
175 Parameters
->Attributes
,
176 Parameters
->CompleteName
,
179 Parameters
->SecurityQos
,
183 /* Should hopefully never get here */
184 return STATUS_OBJECT_TYPE_MISMATCH
;
187 /* PRIVATE FUNCTIONS **********************************************************/
190 * IntGetFullWindowStationName
192 * Get a full window station object name from a name specified in
193 * NtUserCreateWindowStation, NtUserOpenWindowStation, NtUserCreateDesktop
194 * or NtUserOpenDesktop.
197 * TRUE on success, FALSE on failure.
201 IntGetFullWindowStationName(
202 OUT PUNICODE_STRING FullName
,
203 IN PUNICODE_STRING WinStaName
,
204 IN OPTIONAL PUNICODE_STRING DesktopName
)
208 FullName
->Length
= WINSTA_ROOT_NAME_LENGTH
* sizeof(WCHAR
);
209 if (WinStaName
!= NULL
)
210 FullName
->Length
+= WinStaName
->Length
+ sizeof(WCHAR
);
211 if (DesktopName
!= NULL
)
212 FullName
->Length
+= DesktopName
->Length
+ sizeof(WCHAR
);
213 FullName
->MaximumLength
= FullName
->Length
;
214 FullName
->Buffer
= ExAllocatePoolWithTag(PagedPool
, FullName
->Length
, TAG_STRING
);
215 if (FullName
->Buffer
== NULL
)
220 Buffer
= FullName
->Buffer
;
221 memcpy(Buffer
, WINSTA_ROOT_NAME
, WINSTA_ROOT_NAME_LENGTH
* sizeof(WCHAR
));
222 Buffer
+= WINSTA_ROOT_NAME_LENGTH
;
223 if (WinStaName
!= NULL
)
225 memcpy(Buffer
, L
"\\", sizeof(WCHAR
));
227 memcpy(Buffer
, WinStaName
->Buffer
, WinStaName
->Length
);
229 if (DesktopName
!= NULL
)
231 Buffer
+= WinStaName
->Length
/ sizeof(WCHAR
);
232 memcpy(Buffer
, L
"\\", sizeof(WCHAR
));
234 memcpy(Buffer
, DesktopName
->Buffer
, DesktopName
->Length
);
242 * IntValidateWindowStationHandle
244 * Validates the window station handle.
247 * If the function succeeds, the handle remains referenced. If the
248 * fucntion fails, last error is set.
252 IntValidateWindowStationHandle(
253 HWINSTA WindowStation
,
254 KPROCESSOR_MODE AccessMode
,
255 ACCESS_MASK DesiredAccess
,
256 PWINSTATION_OBJECT
*Object
)
260 if (WindowStation
== NULL
)
262 // DPRINT1("Invalid window station handle\n");
263 SetLastWin32Error(ERROR_INVALID_HANDLE
);
264 return STATUS_INVALID_HANDLE
;
267 Status
= ObReferenceObjectByHandle(
270 ExWindowStationObjectType
,
275 if (!NT_SUCCESS(Status
))
276 SetLastNtError(Status
);
282 IntGetWindowStationObject(PWINSTATION_OBJECT Object
)
286 Status
= ObReferenceObjectByPointer(
289 ExWindowStationObjectType
,
292 return NT_SUCCESS(Status
);
297 co_IntInitializeDesktopGraphics(VOID
)
300 UNICODE_STRING DriverName
= RTL_CONSTANT_STRING(L
"DISPLAY");
301 if (! IntCreatePrimarySurface())
305 ScreenDeviceContext
= IntGdiCreateDC(&DriverName
, NULL
, NULL
, NULL
, FALSE
);
306 if (NULL
== ScreenDeviceContext
)
308 IntDestroyPrimarySurface();
311 IntGdiSetDCOwnerEx(ScreenDeviceContext
, GDI_OBJ_HMGR_PUBLIC
, FALSE
);
313 /* Setup the cursor */
314 co_IntLoadDefaultCursors();
316 hSystemBM
= NtGdiCreateCompatibleDC(ScreenDeviceContext
);
318 NtGdiSelectFont( hSystemBM
, NtGdiGetStockObject(SYSTEM_FONT
));
319 IntGdiSetDCOwnerEx( hSystemBM
, GDI_OBJ_HMGR_PUBLIC
, FALSE
);
321 // FIXME! Move these to a update routine.
322 gpsi
->Planes
= NtGdiGetDeviceCaps(ScreenDeviceContext
, PLANES
);
323 gpsi
->BitsPixel
= NtGdiGetDeviceCaps(ScreenDeviceContext
, BITSPIXEL
);
324 gpsi
->BitCount
= gpsi
->Planes
* gpsi
->BitsPixel
;
325 gpsi
->dmLogPixels
= NtGdiGetDeviceCaps(ScreenDeviceContext
, LOGPIXELSY
);
326 // Font is realized and this dc was previously set to internal DC_ATTR.
327 gpsi
->cxSysFontChar
= IntGetCharDimensions(hSystemBM
, &tmw
, (DWORD
*)&gpsi
->cySysFontChar
);
328 gpsi
->tmSysFont
= tmw
;
334 IntEndDesktopGraphics(VOID
)
336 if (NULL
!= ScreenDeviceContext
)
337 { // No need to allocate a new dcattr.
338 DC_SetOwnership(ScreenDeviceContext
, PsGetCurrentProcess());
339 NtGdiDeleteObjectApp(ScreenDeviceContext
);
340 ScreenDeviceContext
= NULL
;
342 IntHideDesktop(IntGetActiveDesktop());
343 IntDestroyPrimarySurface();
349 return ScreenDeviceContext
;
352 /* PUBLIC FUNCTIONS ***********************************************************/
355 * NtUserCreateWindowStation
357 * Creates a new window station.
360 * lpszWindowStationName
361 * Pointer to a null-terminated string specifying the name of the
362 * window station to be created. Window station names are
363 * case-insensitive and cannot contain backslash characters (\).
364 * Only members of the Administrators group are allowed to specify a
368 * Requested type of access
371 * Security descriptor
373 * Unknown3, Unknown4, Unknown5
377 * If the function succeeds, the return value is a handle to the newly
378 * created window station. If the specified window station already
379 * exists, the function succeeds and returns a handle to the existing
380 * window station. If the function fails, the return value is NULL.
383 * Correct the prototype to match the Windows one (with 7 parameters
391 NtUserCreateWindowStation(
392 PUNICODE_STRING lpszWindowStationName
,
393 ACCESS_MASK dwDesiredAccess
,
394 LPSECURITY_ATTRIBUTES lpSecurity
,
400 UNICODE_STRING WindowStationName
;
401 UNICODE_STRING FullWindowStationName
;
402 PWINSTATION_OBJECT WindowStationObject
;
403 HWINSTA WindowStation
;
404 OBJECT_ATTRIBUTES ObjectAttributes
;
408 * Generate full window station name
410 Status
= ProbeAndCaptureUnicodeString(&WindowStationName
,
412 lpszWindowStationName
);
413 if (!NT_SUCCESS(Status
))
415 DPRINT1("Failed to capture window station name (status 0x%08x)\n",
417 SetLastNtError(Status
);
420 if (!IntGetFullWindowStationName(&FullWindowStationName
,
424 ReleaseCapturedUnicodeString(&WindowStationName
, UserMode
);
425 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
430 * Try to open already existing window station
433 DPRINT("Trying to open window station (%wZ)\n", &FullWindowStationName
);
435 /* Initialize ObjectAttributes for the window station object */
436 InitializeObjectAttributes(
438 &FullWindowStationName
,
443 Status
= ObOpenObjectByName(
445 ExWindowStationObjectType
,
450 (PVOID
*)&WindowStation
);
452 if (NT_SUCCESS(Status
))
454 DPRINT("Successfully opened window station (%wZ)\n",
455 FullWindowStationName
);
456 ExFreePool(FullWindowStationName
.Buffer
);
457 ReleaseCapturedUnicodeString(&WindowStationName
, UserMode
);
458 return (HWINSTA
)WindowStation
;
462 * No existing window station found, try to create new one
465 DPRINT("Creating window station (%wZ)\n", &FullWindowStationName
);
467 Status
= ObCreateObject(
469 ExWindowStationObjectType
,
473 sizeof(WINSTATION_OBJECT
),
476 (PVOID
*)&WindowStationObject
);
478 if (!NT_SUCCESS(Status
))
480 DPRINT1("Failed creating window station (%wZ)\n", &FullWindowStationName
);
481 ExFreePool(FullWindowStationName
.Buffer
);
482 ReleaseCapturedUnicodeString(&WindowStationName
, UserMode
);
483 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
487 /* Zero out the buffer */
488 RtlZeroMemory(WindowStationObject
, sizeof(WINSTATION_OBJECT
));
490 KeInitializeSpinLock(&WindowStationObject
->Lock
);
492 InitializeListHead(&WindowStationObject
->DesktopListHead
);
494 WindowStationObject
->AtomTable
= NULL
;
495 Status
= RtlCreateAtomTable(37, &WindowStationObject
->AtomTable
);
496 WindowStationObject
->SystemMenuTemplate
= (HANDLE
)0;
498 WindowStationObject
->Name
= WindowStationName
;
500 Status
= ObInsertObject(
501 (PVOID
)WindowStationObject
,
503 STANDARD_RIGHTS_REQUIRED
,
506 (PVOID
*)&WindowStation
);
508 if (!NT_SUCCESS(Status
))
510 DPRINT1("Failed creating window station (%wZ)\n", &FullWindowStationName
);
511 ExFreePool(FullWindowStationName
.Buffer
);
512 ExFreePool(WindowStationName
.Buffer
);
513 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
514 ObDereferenceObject(WindowStationObject
);
519 * Initialize the new window station object
522 WindowStationObject
->ScreenSaverRunning
= FALSE
;
524 WindowStationObject
->FlatMenu
= FALSE
;
526 if (!IntSetupClipboard(WindowStationObject
))
528 DPRINT1("WindowStation: Error Setting up the clipboard!!!\n");
531 if (InputWindowStation
== NULL
)
533 InputWindowStation
= WindowStationObject
;
538 DPRINT("Window station successfully created (%wZ)\n", &FullWindowStationName
);
539 ExFreePool(FullWindowStationName
.Buffer
);
540 return WindowStation
;
544 * NtUserOpenWindowStation
546 * Opens an existing window station.
549 * lpszWindowStationName
550 * Name of the existing window station.
553 * Requested type of access.
556 * If the function succeeds, the return value is the handle to the
557 * specified window station. If the function fails, the return value
561 * The returned handle can be closed with NtUserCloseWindowStation.
568 NtUserOpenWindowStation(
569 PUNICODE_STRING lpszWindowStationName
,
570 ACCESS_MASK dwDesiredAccess
)
572 UNICODE_STRING WindowStationName
;
573 HWINSTA WindowStation
;
574 OBJECT_ATTRIBUTES ObjectAttributes
;
578 * Generate full window station name
581 if (!IntGetFullWindowStationName(&WindowStationName
, lpszWindowStationName
,
584 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
588 DPRINT("Trying to open window station (%wZ)\n", &WindowStationName
);
590 /* Initialize ObjectAttributes for the window station object */
591 InitializeObjectAttributes(
594 OBJ_CASE_INSENSITIVE
,
598 Status
= ObOpenObjectByName(
600 ExWindowStationObjectType
,
605 (PVOID
*)&WindowStation
);
607 if (!NT_SUCCESS(Status
))
609 SetLastNtError(Status
);
610 ExFreePool(WindowStationName
.Buffer
);
614 DPRINT("Successfully opened window station (%wZ)\n", &WindowStationName
);
615 ExFreePool(WindowStationName
.Buffer
);
617 return WindowStation
;
621 * NtUserCloseWindowStation
623 * Closes a window station handle.
627 * Handle to the window station.
633 * The window station handle can be created with NtUserCreateWindowStation
634 * or NtUserOpenWindowStation. Attemps to close a handle to the window
635 * station assigned to the calling process will fail.
643 NtUserCloseWindowStation(
646 PWINSTATION_OBJECT Object
;
649 DPRINT("About to close window station handle (0x%X)\n", hWinSta
);
651 if (hWinSta
== UserGetProcessWindowStation())
656 Status
= IntValidateWindowStationHandle(
662 if (!NT_SUCCESS(Status
))
664 DPRINT("Validation of window station handle (0x%X) failed\n", hWinSta
);
668 ObDereferenceObject(Object
);
670 DPRINT("Closing window station handle (0x%X)\n", hWinSta
);
672 Status
= ZwClose(hWinSta
);
673 if (!NT_SUCCESS(Status
))
675 SetLastNtError(Status
);
683 * NtUserGetObjectInformation
685 * The NtUserGetObjectInformation function retrieves information about a
686 * window station or desktop object.
690 * Handle to the window station or desktop object for which to
691 * return information. This can be a handle of type HDESK or HWINSTA
692 * (for example, a handle returned by NtUserCreateWindowStation,
693 * NtUserOpenWindowStation, NtUserCreateDesktop, or NtUserOpenDesktop).
696 * Specifies the object information to be retrieved.
699 * Pointer to a buffer to receive the object information.
702 * Specifies the size, in bytes, of the buffer pointed to by the
706 * Pointer to a variable receiving the number of bytes required to
707 * store the requested information. If this variable's value is
708 * greater than the value of the nLength parameter when the function
709 * returns, the function returns FALSE, and none of the information
710 * is copied to the pvInfo buffer. If the value of the variable pointed
711 * to by lpnLengthNeeded is less than or equal to the value of nLength,
712 * the entire information block is copied.
715 * If the function succeeds, the return value is nonzero. If the function
716 * fails, the return value is zero.
723 NtUserGetObjectInformation(
728 PDWORD nLengthNeeded
)
730 PWINSTATION_OBJECT WinStaObject
= NULL
;
731 PDESKTOP DesktopObject
= NULL
;
736 /* try windowstation */
737 DPRINT("Trying to open window station 0x%x\n", hObject
);
738 Status
= IntValidateWindowStationHandle(
740 UserMode
,/*ExGetPreviousMode(),*/
741 GENERIC_READ
, /* FIXME: is this ok? */
745 if (!NT_SUCCESS(Status
) && Status
!= STATUS_OBJECT_TYPE_MISMATCH
)
747 DPRINT("Failed: 0x%x\n", Status
);
748 SetLastNtError(Status
);
752 if (Status
== STATUS_OBJECT_TYPE_MISMATCH
)
755 DPRINT("Trying to open desktop 0x%x\n", hObject
);
756 Status
= IntValidateDesktopHandle(
758 UserMode
,/*ExGetPreviousMode(),*/
759 GENERIC_READ
, /* FIXME: is this ok? */
761 if (!NT_SUCCESS(Status
))
763 DPRINT("Failed: 0x%x\n", Status
);
764 SetLastNtError(Status
);
768 DPRINT("WinSta or Desktop opened!!\n");
774 Status
= STATUS_NOT_IMPLEMENTED
;
775 DPRINT1("UOI_FLAGS unimplemented!\n");
779 if (WinStaObject
!= NULL
)
781 pvData
= ((PUNICODE_STRING
)GET_DESKTOP_NAME(WinStaObject
))->Buffer
;
782 nDataSize
= ((PUNICODE_STRING
)GET_DESKTOP_NAME(WinStaObject
))->Length
+ 2;
783 Status
= STATUS_SUCCESS
;
785 else if (DesktopObject
!= NULL
)
787 pvData
= ((PUNICODE_STRING
)GET_DESKTOP_NAME(DesktopObject
))->Buffer
;
788 nDataSize
= ((PUNICODE_STRING
)GET_DESKTOP_NAME(DesktopObject
))->Length
+ 2;
789 Status
= STATUS_SUCCESS
;
792 Status
= STATUS_INVALID_PARAMETER
;
796 if (WinStaObject
!= NULL
)
798 pvData
= L
"WindowStation";
799 nDataSize
= (wcslen(pvData
) + 1) * sizeof(WCHAR
);
800 Status
= STATUS_SUCCESS
;
802 else if (DesktopObject
!= NULL
)
805 nDataSize
= (wcslen(pvData
) + 1) * sizeof(WCHAR
);
806 Status
= STATUS_SUCCESS
;
809 Status
= STATUS_INVALID_PARAMETER
;
813 Status
= STATUS_NOT_IMPLEMENTED
;
814 DPRINT1("UOI_USER_SID unimplemented!\n");
818 Status
= STATUS_INVALID_PARAMETER
;
822 /* try to copy data to caller */
823 if (Status
== STATUS_SUCCESS
)
825 DPRINT("Trying to copy data to caller (len = %d, len needed = %d)\n", nLength
, nDataSize
);
826 *nLengthNeeded
= nDataSize
;
827 if (nLength
>= nDataSize
)
828 Status
= MmCopyToCaller(pvInformation
, pvData
, nDataSize
);
830 Status
= STATUS_BUFFER_TOO_SMALL
;
833 /* release objects */
834 if (WinStaObject
!= NULL
)
835 ObDereferenceObject(WinStaObject
);
836 if (DesktopObject
!= NULL
)
837 ObDereferenceObject(DesktopObject
);
839 SetLastNtError(Status
);
840 return NT_SUCCESS(Status
);
844 * NtUserSetObjectInformation
846 * The NtUserSetObjectInformation function sets information about a
847 * window station or desktop object.
851 * Handle to the window station or desktop object for which to set
852 * object information. This value can be a handle of type HDESK or
856 * Specifies the object information to be set.
859 * Pointer to a buffer containing the object information.
862 * Specifies the size, in bytes, of the information contained in the
863 * buffer pointed to by pvInfo.
866 * If the function succeeds, the return value is nonzero. If the function
867 * fails the return value is zero.
875 NtUserSetObjectInformation(
881 /* FIXME: ZwQueryObject */
882 /* FIXME: ZwSetInformationObject */
883 SetLastNtError(STATUS_UNSUCCESSFUL
);
891 UserGetProcessWindowStation(VOID
)
897 if(PsGetCurrentProcess() != CsrProcess
)
899 return PsGetCurrentProcess()->Win32WindowStation
;
903 DPRINT1("Should use ObFindHandleForObject\n");
904 pti
= PsGetCurrentThreadWin32Thread();
905 Status
= ObOpenObjectByPointer(pti
->rpdesk
->rpwinstaParent
,
909 ExWindowStationObjectType
,
912 if (! NT_SUCCESS(Status
))
914 SetLastNtError(Status
);
915 DPRINT1("Unable to open handle for CSRSSs winsta, status 0x%08x\n",
925 * NtUserGetProcessWindowStation
927 * Returns a handle to the current process window station.
930 * If the function succeeds, the return value is handle to the window
931 * station assigned to the current process. If the function fails, the
932 * return value is NULL.
939 NtUserGetProcessWindowStation(VOID
)
941 return UserGetProcessWindowStation();
944 PWINSTATION_OBJECT FASTCALL
945 IntGetWinStaObj(VOID
)
947 PWINSTATION_OBJECT WinStaObj
;
948 PTHREADINFO Win32Thread
;
949 PEPROCESS CurrentProcess
;
952 * just a temporary hack, this will be gone soon
955 Win32Thread
= PsGetCurrentThreadWin32Thread();
956 if(Win32Thread
!= NULL
&& Win32Thread
->rpdesk
!= NULL
)
958 WinStaObj
= Win32Thread
->rpdesk
->rpwinstaParent
;
959 ObReferenceObjectByPointer(WinStaObj
, KernelMode
, ExWindowStationObjectType
, 0);
961 else if((CurrentProcess
= PsGetCurrentProcess()) != CsrProcess
)
963 NTSTATUS Status
= IntValidateWindowStationHandle(CurrentProcess
->Win32WindowStation
,
967 if(!NT_SUCCESS(Status
))
969 SetLastNtError(Status
);
982 * NtUserSetProcessWindowStation
984 * Assigns a window station to the current process.
988 * Handle to the window station.
998 NtUserSetProcessWindowStation(HWINSTA hWindowStation
)
1000 PWINSTATION_OBJECT NewWinSta
;
1003 DPRINT("About to set process window station with handle (0x%X)\n",
1006 if(PsGetCurrentProcess() == CsrProcess
)
1008 DPRINT1("CSRSS is not allowed to change it's window station!!!\n");
1009 SetLastWin32Error(ERROR_ACCESS_DENIED
);
1013 Status
= IntValidateWindowStationHandle(
1019 if (!NT_SUCCESS(Status
))
1021 DPRINT("Validation of window station handle (0x%X) failed\n",
1023 SetLastNtError(Status
);
1028 * FIXME - don't allow changing the window station if there are threads that are attached to desktops and own gui objects
1031 /* FIXME - dereference the old window station, etc... */
1032 InterlockedExchangePointer(&PsGetCurrentProcess()->Win32WindowStation
, hWindowStation
);
1034 DPRINT("PsGetCurrentProcess()->Win32WindowStation 0x%X\n",
1035 PsGetCurrentProcess()->Win32WindowStation
);
1041 * NtUserLockWindowStation
1043 * Locks switching desktops. Only the logon application is allowed to call this function.
1050 NtUserLockWindowStation(HWINSTA hWindowStation
)
1052 PWINSTATION_OBJECT Object
;
1055 DPRINT("About to set process window station with handle (0x%X)\n",
1058 if(PsGetCurrentProcessWin32Process() != LogonProcess
)
1060 DPRINT1("Unauthorized process attempted to lock the window station!\n");
1061 SetLastWin32Error(ERROR_ACCESS_DENIED
);
1065 Status
= IntValidateWindowStationHandle(
1070 if (!NT_SUCCESS(Status
))
1072 DPRINT("Validation of window station handle (0x%X) failed\n",
1074 SetLastNtError(Status
);
1078 Object
->Flags
|= WSS_LOCKED
;
1080 ObDereferenceObject(Object
);
1085 * NtUserUnlockWindowStation
1087 * Unlocks switching desktops. Only the logon application is allowed to call this function.
1094 NtUserUnlockWindowStation(HWINSTA hWindowStation
)
1096 PWINSTATION_OBJECT Object
;
1100 DPRINT("About to set process window station with handle (0x%X)\n",
1103 if(PsGetCurrentProcessWin32Process() != LogonProcess
)
1105 DPRINT1("Unauthorized process attempted to unlock the window station!\n");
1106 SetLastWin32Error(ERROR_ACCESS_DENIED
);
1110 Status
= IntValidateWindowStationHandle(
1115 if (!NT_SUCCESS(Status
))
1117 DPRINT("Validation of window station handle (0x%X) failed\n",
1119 SetLastNtError(Status
);
1123 Ret
= (Object
->Flags
& WSS_LOCKED
) == WSS_LOCKED
;
1124 Object
->Flags
&= ~WSS_LOCKED
;
1126 ObDereferenceObject(Object
);
1130 static NTSTATUS FASTCALL
1131 BuildWindowStationNameList(
1134 PULONG pRequiredSize
)
1136 OBJECT_ATTRIBUTES ObjectAttributes
;
1138 HANDLE DirectoryHandle
;
1139 UNICODE_STRING DirectoryName
;
1140 char InitialBuffer
[256], *Buffer
;
1141 ULONG Context
, ReturnLength
, BufferSize
;
1143 POBJECT_DIRECTORY_INFORMATION DirEntry
;
1147 * Generate name of window station directory
1149 if (!IntGetFullWindowStationName(&DirectoryName
, NULL
, NULL
))
1151 return STATUS_INSUFFICIENT_RESOURCES
;
1155 * Try to open the directory.
1157 InitializeObjectAttributes(
1160 OBJ_CASE_INSENSITIVE
,
1164 Status
= ZwOpenDirectoryObject(
1169 ExFreePool(DirectoryName
.Buffer
);
1171 if (!NT_SUCCESS(Status
))
1176 /* First try to query the directory using a fixed-size buffer */
1179 Status
= ZwQueryDirectoryObject(DirectoryHandle
, InitialBuffer
, sizeof(InitialBuffer
),
1180 FALSE
, TRUE
, &Context
, &ReturnLength
);
1181 if (NT_SUCCESS(Status
))
1183 if (STATUS_NO_MORE_ENTRIES
== ZwQueryDirectoryObject(DirectoryHandle
, NULL
, 0, FALSE
,
1184 FALSE
, &Context
, NULL
))
1186 /* Our fixed-size buffer is large enough */
1187 Buffer
= InitialBuffer
;
1193 /* Need a larger buffer, check how large exactly */
1194 Status
= ZwQueryDirectoryObject(DirectoryHandle
, NULL
, 0, FALSE
, TRUE
, &Context
,
1196 if (STATUS_BUFFER_TOO_SMALL
== Status
)
1198 BufferSize
= ReturnLength
;
1199 Buffer
= ExAllocatePoolWithTag(PagedPool
, BufferSize
, TAG_WINSTA
);
1202 ObDereferenceObject(DirectoryHandle
);
1203 return STATUS_NO_MEMORY
;
1206 /* We should have a sufficiently large buffer now */
1208 Status
= ZwQueryDirectoryObject(DirectoryHandle
, Buffer
, BufferSize
,
1209 FALSE
, TRUE
, &Context
, &ReturnLength
);
1210 if (! NT_SUCCESS(Status
) ||
1211 STATUS_NO_MORE_ENTRIES
!= ZwQueryDirectoryObject(DirectoryHandle
, NULL
, 0, FALSE
,
1212 FALSE
, &Context
, NULL
))
1214 /* Something went wrong, maybe someone added a directory entry? Just give up. */
1215 ExFreePoolWithTag(Buffer
, TAG_WINSTA
);
1216 ObDereferenceObject(DirectoryHandle
);
1217 return NT_SUCCESS(Status
) ? STATUS_INTERNAL_ERROR
: Status
;
1222 ZwClose(DirectoryHandle
);
1225 * Count the required size of buffer.
1227 ReturnLength
= sizeof(DWORD
);
1229 for (DirEntry
= (POBJECT_DIRECTORY_INFORMATION
) Buffer
; 0 != DirEntry
->Name
.Length
;
1232 ReturnLength
+= DirEntry
->Name
.Length
+ sizeof(WCHAR
);
1235 DPRINT("Required size: %d Entry count: %d\n", ReturnLength
, EntryCount
);
1236 if (NULL
!= pRequiredSize
)
1238 Status
= MmCopyToCaller(pRequiredSize
, &ReturnLength
, sizeof(ULONG
));
1239 if (! NT_SUCCESS(Status
))
1241 if (Buffer
!= InitialBuffer
)
1243 ExFreePoolWithTag(Buffer
, TAG_WINSTA
);
1245 return STATUS_BUFFER_TOO_SMALL
;
1250 * Check if the supplied buffer is large enough.
1252 if (dwSize
< ReturnLength
)
1254 if (Buffer
!= InitialBuffer
)
1256 ExFreePoolWithTag(Buffer
, TAG_WINSTA
);
1258 return STATUS_BUFFER_TOO_SMALL
;
1262 * Generate the resulting buffer contents.
1264 Status
= MmCopyToCaller(lpBuffer
, &EntryCount
, sizeof(DWORD
));
1265 if (! NT_SUCCESS(Status
))
1267 if (Buffer
!= InitialBuffer
)
1273 lpBuffer
= (PVOID
) ((PCHAR
) lpBuffer
+ sizeof(DWORD
));
1276 for (DirEntry
= (POBJECT_DIRECTORY_INFORMATION
) Buffer
; 0 != DirEntry
->Name
.Length
;
1279 Status
= MmCopyToCaller(lpBuffer
, DirEntry
->Name
.Buffer
, DirEntry
->Name
.Length
);
1280 if (! NT_SUCCESS(Status
))
1282 if (Buffer
!= InitialBuffer
)
1288 lpBuffer
= (PVOID
) ((PCHAR
) lpBuffer
+ DirEntry
->Name
.Length
);
1289 Status
= MmCopyToCaller(lpBuffer
, &NullWchar
, sizeof(WCHAR
));
1290 if (! NT_SUCCESS(Status
))
1292 if (Buffer
!= InitialBuffer
)
1298 lpBuffer
= (PVOID
) ((PCHAR
) lpBuffer
+ sizeof(WCHAR
));
1304 if (NULL
!= Buffer
&& Buffer
!= InitialBuffer
)
1309 return STATUS_SUCCESS
;
1312 static NTSTATUS FASTCALL
1313 BuildDesktopNameList(
1314 HWINSTA hWindowStation
,
1317 PULONG pRequiredSize
)
1320 PWINSTATION_OBJECT WindowStation
;
1322 PLIST_ENTRY DesktopEntry
;
1323 PDESKTOP DesktopObject
;
1328 Status
= IntValidateWindowStationHandle(hWindowStation
,
1332 if (! NT_SUCCESS(Status
))
1337 KeAcquireSpinLock(&WindowStation
->Lock
, &OldLevel
);
1340 * Count the required size of buffer.
1342 ReturnLength
= sizeof(DWORD
);
1344 for (DesktopEntry
= WindowStation
->DesktopListHead
.Flink
;
1345 DesktopEntry
!= &WindowStation
->DesktopListHead
;
1346 DesktopEntry
= DesktopEntry
->Flink
)
1348 DesktopObject
= CONTAINING_RECORD(DesktopEntry
, DESKTOP
, ListEntry
);
1349 ReturnLength
+= ((PUNICODE_STRING
)GET_DESKTOP_NAME(DesktopObject
))->Length
+ sizeof(WCHAR
);
1352 DPRINT("Required size: %d Entry count: %d\n", ReturnLength
, EntryCount
);
1353 if (NULL
!= pRequiredSize
)
1355 Status
= MmCopyToCaller(pRequiredSize
, &ReturnLength
, sizeof(ULONG
));
1356 if (! NT_SUCCESS(Status
))
1358 KeReleaseSpinLock(&WindowStation
->Lock
, OldLevel
);
1359 ObDereferenceObject(WindowStation
);
1360 return STATUS_BUFFER_TOO_SMALL
;
1365 * Check if the supplied buffer is large enough.
1367 if (dwSize
< ReturnLength
)
1369 KeReleaseSpinLock(&WindowStation
->Lock
, OldLevel
);
1370 ObDereferenceObject(WindowStation
);
1371 return STATUS_BUFFER_TOO_SMALL
;
1375 * Generate the resulting buffer contents.
1377 Status
= MmCopyToCaller(lpBuffer
, &EntryCount
, sizeof(DWORD
));
1378 if (! NT_SUCCESS(Status
))
1380 KeReleaseSpinLock(&WindowStation
->Lock
, OldLevel
);
1381 ObDereferenceObject(WindowStation
);
1384 lpBuffer
= (PVOID
) ((PCHAR
) lpBuffer
+ sizeof(DWORD
));
1387 for (DesktopEntry
= WindowStation
->DesktopListHead
.Flink
;
1388 DesktopEntry
!= &WindowStation
->DesktopListHead
;
1389 DesktopEntry
= DesktopEntry
->Flink
)
1391 DesktopObject
= CONTAINING_RECORD(DesktopEntry
, DESKTOP
, ListEntry
);
1392 Status
= MmCopyToCaller(lpBuffer
, ((PUNICODE_STRING
)GET_DESKTOP_NAME(DesktopObject
))->Buffer
, ((PUNICODE_STRING
)GET_DESKTOP_NAME(DesktopObject
))->Length
);
1393 if (! NT_SUCCESS(Status
))
1395 KeReleaseSpinLock(&WindowStation
->Lock
, OldLevel
);
1396 ObDereferenceObject(WindowStation
);
1399 lpBuffer
= (PVOID
) ((PCHAR
) lpBuffer
+ ((PUNICODE_STRING
)GET_DESKTOP_NAME(DesktopObject
))->Length
);
1400 Status
= MmCopyToCaller(lpBuffer
, &NullWchar
, sizeof(WCHAR
));
1401 if (! NT_SUCCESS(Status
))
1403 KeReleaseSpinLock(&WindowStation
->Lock
, OldLevel
);
1404 ObDereferenceObject(WindowStation
);
1407 lpBuffer
= (PVOID
) ((PCHAR
) lpBuffer
+ sizeof(WCHAR
));
1413 KeReleaseSpinLock(&WindowStation
->Lock
, OldLevel
);
1414 ObDereferenceObject(WindowStation
);
1416 return STATUS_SUCCESS
;
1420 * NtUserBuildNameList
1422 * Function used for enumeration of desktops or window stations.
1426 * For enumeration of window stations this parameter must be set to
1427 * zero. Otherwise it's handle for window station.
1430 * Size of buffer passed by caller.
1433 * Buffer passed by caller. If the function succedes, the buffer is
1434 * filled with window station/desktop count (in first DWORD) and
1435 * NULL-terminated window station/desktop names.
1438 * If the function suceedes, this is the number of bytes copied.
1439 * Otherwise it's size of buffer needed for function to succeed.
1446 NtUserBuildNameList(
1447 HWINSTA hWindowStation
,
1450 PULONG pRequiredSize
)
1452 /* The WindowStation name list and desktop name list are build in completely
1453 different ways. Call the appropriate function */
1454 return NULL
== hWindowStation
? BuildWindowStationNameList(dwSize
, lpBuffer
, pRequiredSize
) :
1455 BuildDesktopNameList(hWindowStation
, dwSize
, lpBuffer
, pRequiredSize
);