2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
4 * PURPOSE: Window stations
5 * FILE: subsystems/win32/win32k/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 *******************************************************************/
17 /* Currently active window station */
18 PWINSTATION_OBJECT InputWindowStation
= NULL
;
20 /* Winlogon SAS window */
23 /* INITALIZATION FUNCTIONS ****************************************************/
25 static GENERIC_MAPPING IntWindowStationMapping
=
27 STANDARD_RIGHTS_READ
| WINSTA_ENUMDESKTOPS
| WINSTA_ENUMERATE
| WINSTA_READATTRIBUTES
| WINSTA_READSCREEN
,
28 STANDARD_RIGHTS_WRITE
| WINSTA_ACCESSCLIPBOARD
| WINSTA_CREATEDESKTOP
| WINSTA_WRITEATTRIBUTES
,
29 STANDARD_RIGHTS_EXECUTE
| WINSTA_ACCESSGLOBALATOMS
| WINSTA_EXITWINDOWS
,
30 STANDARD_RIGHTS_REQUIRED
| WINSTA_ACCESSCLIPBOARD
| WINSTA_ACCESSGLOBALATOMS
| WINSTA_CREATEDESKTOP
|
31 WINSTA_ENUMDESKTOPS
| WINSTA_ENUMERATE
| WINSTA_EXITWINDOWS
|
32 WINSTA_READATTRIBUTES
| WINSTA_READSCREEN
| WINSTA_WRITEATTRIBUTES
39 InitWindowStationImpl(VOID
)
41 OBJECT_ATTRIBUTES ObjectAttributes
;
42 HANDLE WindowStationsDirectory
;
43 UNICODE_STRING UnicodeString
;
47 * Create the '\Windows\WindowStations' directory
50 RtlInitUnicodeString(&UnicodeString
, WINSTA_ROOT_NAME
);
51 InitializeObjectAttributes(&ObjectAttributes
, &UnicodeString
,
53 Status
= ZwCreateDirectoryObject(&WindowStationsDirectory
, 0,
55 if (!NT_SUCCESS(Status
))
57 TRACE("Could not create \\Windows\\WindowStations directory "
58 "(Status 0x%X)\n", Status
);
62 /* Set Winsta Object Attributes */
63 ExWindowStationObjectType
->TypeInfo
.DefaultNonPagedPoolCharge
= sizeof(WINSTATION_OBJECT
);
64 ExWindowStationObjectType
->TypeInfo
.GenericMapping
= IntWindowStationMapping
;
66 return STATUS_SUCCESS
;
70 CleanupWindowStationImpl(VOID
)
72 return STATUS_SUCCESS
;
75 /* OBJECT CALLBACKS **********************************************************/
78 IntWinStaObjectDelete(PWIN32_DELETEMETHOD_PARAMETERS Parameters
)
80 PWINSTATION_OBJECT WinSta
= (PWINSTATION_OBJECT
)Parameters
->Object
;
82 TRACE("Deleting window station (0x%X)\n", WinSta
);
84 UserEmptyClipboardData(WinSta
);
86 RtlDestroyAtomTable(WinSta
->AtomTable
);
88 RtlFreeUnicodeString(&WinSta
->Name
);
93 IntWinStaObjectParse(PWIN32_PARSEMETHOD_PARAMETERS Parameters
)
95 PUNICODE_STRING RemainingName
= Parameters
->RemainingName
;
97 /* Assume we don't find anything */
98 *Parameters
->Object
= NULL
;
100 /* Check for an empty name */
101 if (!RemainingName
->Length
)
103 /* Make sure this is a window station, can't parse a desktop now */
104 if (Parameters
->ObjectType
!= ExWindowStationObjectType
)
107 return STATUS_OBJECT_TYPE_MISMATCH
;
110 /* Reference the window station and return */
111 ObReferenceObject(Parameters
->ParseObject
);
112 *Parameters
->Object
= Parameters
->ParseObject
;
113 return STATUS_SUCCESS
;
116 /* Check for leading slash */
117 if (RemainingName
->Buffer
[0] == OBJ_NAME_PATH_SEPARATOR
)
120 RemainingName
->Buffer
++;
121 RemainingName
->Length
-= sizeof(WCHAR
);
122 RemainingName
->MaximumLength
-= sizeof(WCHAR
);
125 /* Check if there is still a slash */
126 if (wcschr(RemainingName
->Buffer
, OBJ_NAME_PATH_SEPARATOR
))
128 /* In this case, fail */
129 return STATUS_OBJECT_PATH_INVALID
;
133 * Check if we are parsing a desktop.
135 if (Parameters
->ObjectType
== ExDesktopObjectType
)
137 /* Then call the desktop parse routine */
138 return IntDesktopObjectParse(Parameters
->ParseObject
,
139 Parameters
->ObjectType
,
140 Parameters
->AccessState
,
141 Parameters
->AccessMode
,
142 Parameters
->Attributes
,
143 Parameters
->CompleteName
,
146 Parameters
->SecurityQos
,
150 /* Should hopefully never get here */
151 return STATUS_OBJECT_TYPE_MISMATCH
;
156 IntWinstaOkToClose(PWIN32_OKAYTOCLOSEMETHOD_PARAMETERS Parameters
)
160 ppi
= PsGetCurrentProcessWin32Process();
162 if(ppi
&& (Parameters
->Handle
== ppi
->hwinsta
))
164 return STATUS_ACCESS_DENIED
;
167 return STATUS_SUCCESS
;
170 /* PRIVATE FUNCTIONS **********************************************************/
173 * IntGetFullWindowStationName
175 * Get a full window station object name from a name specified in
176 * NtUserCreateWindowStation, NtUserOpenWindowStation, NtUserCreateDesktop
177 * or NtUserOpenDesktop.
180 * TRUE on success, FALSE on failure.
184 IntGetFullWindowStationName(
185 OUT PUNICODE_STRING FullName
,
186 IN PUNICODE_STRING WinStaName
,
187 IN OPTIONAL PUNICODE_STRING DesktopName
)
191 FullName
->Length
= WINSTA_ROOT_NAME_LENGTH
* sizeof(WCHAR
);
192 if (WinStaName
!= NULL
)
193 FullName
->Length
+= WinStaName
->Length
+ sizeof(WCHAR
);
194 if (DesktopName
!= NULL
)
195 FullName
->Length
+= DesktopName
->Length
+ sizeof(WCHAR
);
196 FullName
->MaximumLength
= FullName
->Length
;
197 FullName
->Buffer
= ExAllocatePoolWithTag(PagedPool
, FullName
->Length
, TAG_STRING
);
198 if (FullName
->Buffer
== NULL
)
203 Buffer
= FullName
->Buffer
;
204 memcpy(Buffer
, WINSTA_ROOT_NAME
, WINSTA_ROOT_NAME_LENGTH
* sizeof(WCHAR
));
205 Buffer
+= WINSTA_ROOT_NAME_LENGTH
;
206 if (WinStaName
!= NULL
)
210 memcpy(Buffer
, WinStaName
->Buffer
, WinStaName
->Length
);
212 if (DesktopName
!= NULL
)
214 Buffer
+= WinStaName
->Length
/ sizeof(WCHAR
);
217 memcpy(Buffer
, DesktopName
->Buffer
, DesktopName
->Length
);
225 * IntValidateWindowStationHandle
227 * Validates the window station handle.
230 * If the function succeeds, the handle remains referenced. If the
231 * fucntion fails, last error is set.
235 IntValidateWindowStationHandle(
236 HWINSTA WindowStation
,
237 KPROCESSOR_MODE AccessMode
,
238 ACCESS_MASK DesiredAccess
,
239 PWINSTATION_OBJECT
*Object
)
243 if (WindowStation
== NULL
)
245 WARN("Invalid window station handle\n");
246 EngSetLastError(ERROR_INVALID_HANDLE
);
247 return STATUS_INVALID_HANDLE
;
250 Status
= ObReferenceObjectByHandle(
253 ExWindowStationObjectType
,
258 if (!NT_SUCCESS(Status
))
259 SetLastNtError(Status
);
265 IntGetWindowStationObject(PWINSTATION_OBJECT Object
)
269 Status
= ObReferenceObjectByPointer(
272 ExWindowStationObjectType
,
275 return NT_SUCCESS(Status
);
280 co_IntInitializeDesktopGraphics(VOID
)
283 UNICODE_STRING DriverName
= RTL_CONSTANT_STRING(L
"DISPLAY");
284 if (! IntCreatePrimarySurface())
288 ScreenDeviceContext
= IntGdiCreateDC(&DriverName
, NULL
, NULL
, NULL
, FALSE
);
289 if (NULL
== ScreenDeviceContext
)
291 IntDestroyPrimarySurface();
294 GreSetDCOwner(ScreenDeviceContext
, GDI_OBJ_HMGR_PUBLIC
);
296 /* Setup the cursor */
297 co_IntLoadDefaultCursors();
299 hSystemBM
= NtGdiCreateCompatibleDC(ScreenDeviceContext
);
301 NtGdiSelectFont(hSystemBM
, NtGdiGetStockObject(SYSTEM_FONT
));
302 GreSetDCOwner(hSystemBM
, GDI_OBJ_HMGR_PUBLIC
);
304 // FIXME: Move these to a update routine.
305 gpsi
->Planes
= NtGdiGetDeviceCaps(ScreenDeviceContext
, PLANES
);
306 gpsi
->BitsPixel
= NtGdiGetDeviceCaps(ScreenDeviceContext
, BITSPIXEL
);
307 gpsi
->BitCount
= gpsi
->Planes
* gpsi
->BitsPixel
;
308 gpsi
->dmLogPixels
= NtGdiGetDeviceCaps(ScreenDeviceContext
, LOGPIXELSY
);
309 if (NtGdiGetDeviceCaps(ScreenDeviceContext
, RASTERCAPS
) & RC_PALETTE
)
311 gpsi
->PUSIFlags
|= PUSIF_PALETTEDISPLAY
;
314 gpsi
->PUSIFlags
&= ~PUSIF_PALETTEDISPLAY
;
315 // Font is realized and this dc was previously set to internal DC_ATTR.
316 gpsi
->cxSysFontChar
= IntGetCharDimensions(hSystemBM
, &tmw
, (DWORD
*)&gpsi
->cySysFontChar
);
317 gpsi
->tmSysFont
= tmw
;
323 IntEndDesktopGraphics(VOID
)
325 if (NULL
!= ScreenDeviceContext
)
326 { // No need to allocate a new dcattr.
327 GreSetDCOwner(ScreenDeviceContext
, GDI_OBJ_HMGR_POWNED
);
328 GreDeleteObject(ScreenDeviceContext
);
329 ScreenDeviceContext
= NULL
;
331 IntHideDesktop(IntGetActiveDesktop());
332 IntDestroyPrimarySurface();
338 return ScreenDeviceContext
;
341 /* PUBLIC FUNCTIONS ***********************************************************/
344 * NtUserCreateWindowStation
346 * Creates a new window station.
349 * lpszWindowStationName
350 * Pointer to a null-terminated string specifying the name of the
351 * window station to be created. Window station names are
352 * case-insensitive and cannot contain backslash characters (\).
353 * Only members of the Administrators group are allowed to specify a
357 * Requested type of access
360 * Security descriptor
362 * Unknown3, Unknown4, Unknown5
366 * If the function succeeds, the return value is a handle to the newly
367 * created window station. If the specified window station already
368 * exists, the function succeeds and returns a handle to the existing
369 * window station. If the function fails, the return value is NULL.
372 * Correct the prototype to match the Windows one (with 7 parameters
380 NtUserCreateWindowStation(
381 POBJECT_ATTRIBUTES ObjectAttributes
,
382 ACCESS_MASK dwDesiredAccess
,
389 UNICODE_STRING WindowStationName
;
390 PWINSTATION_OBJECT WindowStationObject
;
391 HWINSTA WindowStation
;
394 Status
= ObOpenObjectByName(
396 ExWindowStationObjectType
,
401 (PVOID
*)&WindowStation
);
403 if (NT_SUCCESS(Status
))
405 return (HWINSTA
)WindowStation
;
410 * No existing window station found, try to create new one
413 /* Capture window station name */
416 ProbeForRead( ObjectAttributes
, sizeof(OBJECT_ATTRIBUTES
), 1);
417 Status
= IntSafeCopyUnicodeString(&WindowStationName
, ObjectAttributes
->ObjectName
);
419 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
421 Status
=_SEH2_GetExceptionCode();
425 if (! NT_SUCCESS(Status
))
427 ERR("Failed reading capturing window station name\n");
428 SetLastNtError(Status
);
432 /* Create the window station object */
433 Status
= ObCreateObject(
435 ExWindowStationObjectType
,
439 sizeof(WINSTATION_OBJECT
),
442 (PVOID
*)&WindowStationObject
);
444 if (!NT_SUCCESS(Status
))
446 ExFreePoolWithTag(WindowStationName
.Buffer
, TAG_STRING
);
447 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
451 Status
= ObInsertObject(
452 (PVOID
)WindowStationObject
,
454 STANDARD_RIGHTS_REQUIRED
,
457 (PVOID
*)&WindowStation
);
459 if (!NT_SUCCESS(Status
))
461 ExFreePoolWithTag(WindowStationName
.Buffer
, TAG_STRING
);
462 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
463 ObDereferenceObject(WindowStationObject
);
467 /* Initialize the window station */
468 RtlZeroMemory(WindowStationObject
, sizeof(WINSTATION_OBJECT
));
470 KeInitializeSpinLock(&WindowStationObject
->Lock
);
471 InitializeListHead(&WindowStationObject
->DesktopListHead
);
472 Status
= RtlCreateAtomTable(37, &WindowStationObject
->AtomTable
);
473 WindowStationObject
->SystemMenuTemplate
= (HANDLE
)0;
474 WindowStationObject
->Name
= WindowStationName
;
475 WindowStationObject
->ScreenSaverRunning
= FALSE
;
476 WindowStationObject
->FlatMenu
= FALSE
;
478 if (InputWindowStation
== NULL
)
480 InputWindowStation
= WindowStationObject
;
485 return WindowStation
;
489 * NtUserOpenWindowStation
491 * Opens an existing window station.
494 * lpszWindowStationName
495 * Name of the existing window station.
498 * Requested type of access.
501 * If the function succeeds, the return value is the handle to the
502 * specified window station. If the function fails, the return value
506 * The returned handle can be closed with NtUserCloseWindowStation.
513 NtUserOpenWindowStation(
514 POBJECT_ATTRIBUTES ObjectAttributes
,
515 ACCESS_MASK dwDesiredAccess
)
517 HWINSTA WindowStation
;
520 Status
= ObOpenObjectByName(
522 ExWindowStationObjectType
,
527 (PVOID
*)&WindowStation
);
529 if (!NT_SUCCESS(Status
))
531 SetLastNtError(Status
);
535 return WindowStation
;
539 * NtUserCloseWindowStation
541 * Closes a window station handle.
545 * Handle to the window station.
551 * The window station handle can be created with NtUserCreateWindowStation
552 * or NtUserOpenWindowStation. Attemps to close a handle to the window
553 * station assigned to the calling process will fail.
561 NtUserCloseWindowStation(
564 PWINSTATION_OBJECT Object
;
567 TRACE("About to close window station handle (0x%X)\n", hWinSta
);
569 if (hWinSta
== UserGetProcessWindowStation())
574 Status
= IntValidateWindowStationHandle(
580 if (!NT_SUCCESS(Status
))
582 TRACE("Validation of window station handle (0x%X) failed\n", hWinSta
);
586 ObDereferenceObject(Object
);
588 TRACE("Closing window station handle (0x%X)\n", hWinSta
);
590 Status
= ObCloseHandle(hWinSta
, UserMode
);
591 if (!NT_SUCCESS(Status
))
593 SetLastNtError(Status
);
601 * NtUserGetObjectInformation
603 * The NtUserGetObjectInformation function retrieves information about a
604 * window station or desktop object.
608 * Handle to the window station or desktop object for which to
609 * return information. This can be a handle of type HDESK or HWINSTA
610 * (for example, a handle returned by NtUserCreateWindowStation,
611 * NtUserOpenWindowStation, NtUserCreateDesktop, or NtUserOpenDesktop).
614 * Specifies the object information to be retrieved.
617 * Pointer to a buffer to receive the object information.
620 * Specifies the size, in bytes, of the buffer pointed to by the
624 * Pointer to a variable receiving the number of bytes required to
625 * store the requested information. If this variable's value is
626 * greater than the value of the nLength parameter when the function
627 * returns, the function returns FALSE, and none of the information
628 * is copied to the pvInfo buffer. If the value of the variable pointed
629 * to by lpnLengthNeeded is less than or equal to the value of nLength,
630 * the entire information block is copied.
633 * If the function succeeds, the return value is nonzero. If the function
634 * fails, the return value is zero.
641 NtUserGetObjectInformation(
646 PDWORD nLengthNeeded
)
648 PWINSTATION_OBJECT WinStaObject
= NULL
;
649 PDESKTOP DesktopObject
= NULL
;
654 /* try windowstation */
655 TRACE("Trying to open window station 0x%x\n", hObject
);
656 Status
= IntValidateWindowStationHandle(
658 UserMode
,/*ExGetPreviousMode(),*/
659 GENERIC_READ
, /* FIXME: is this ok? */
663 if (!NT_SUCCESS(Status
) && Status
!= STATUS_OBJECT_TYPE_MISMATCH
)
665 TRACE("Failed: 0x%x\n", Status
);
666 SetLastNtError(Status
);
670 if (Status
== STATUS_OBJECT_TYPE_MISMATCH
)
673 TRACE("Trying to open desktop 0x%x\n", hObject
);
674 Status
= IntValidateDesktopHandle(
676 UserMode
,/*ExGetPreviousMode(),*/
677 GENERIC_READ
, /* FIXME: is this ok? */
679 if (!NT_SUCCESS(Status
))
681 TRACE("Failed: 0x%x\n", Status
);
682 SetLastNtError(Status
);
686 TRACE("WinSta or Desktop opened!!\n");
692 Status
= STATUS_NOT_IMPLEMENTED
;
693 ERR("UOI_FLAGS unimplemented!\n");
697 if (WinStaObject
!= NULL
)
699 pvData
= ((PUNICODE_STRING
)GET_DESKTOP_NAME(WinStaObject
))->Buffer
;
700 nDataSize
= ((PUNICODE_STRING
)GET_DESKTOP_NAME(WinStaObject
))->Length
+ 2;
701 Status
= STATUS_SUCCESS
;
703 else if (DesktopObject
!= NULL
)
705 pvData
= ((PUNICODE_STRING
)GET_DESKTOP_NAME(DesktopObject
))->Buffer
;
706 nDataSize
= ((PUNICODE_STRING
)GET_DESKTOP_NAME(DesktopObject
))->Length
+ 2;
707 Status
= STATUS_SUCCESS
;
710 Status
= STATUS_INVALID_PARAMETER
;
714 if (WinStaObject
!= NULL
)
716 pvData
= L
"WindowStation";
717 nDataSize
= (wcslen(pvData
) + 1) * sizeof(WCHAR
);
718 Status
= STATUS_SUCCESS
;
720 else if (DesktopObject
!= NULL
)
723 nDataSize
= (wcslen(pvData
) + 1) * sizeof(WCHAR
);
724 Status
= STATUS_SUCCESS
;
727 Status
= STATUS_INVALID_PARAMETER
;
731 Status
= STATUS_NOT_IMPLEMENTED
;
732 ERR("UOI_USER_SID unimplemented!\n");
736 Status
= STATUS_INVALID_PARAMETER
;
740 /* try to copy data to caller */
741 if (Status
== STATUS_SUCCESS
)
743 TRACE("Trying to copy data to caller (len = %d, len needed = %d)\n", nLength
, nDataSize
);
744 *nLengthNeeded
= nDataSize
;
745 if (nLength
>= nDataSize
)
746 Status
= MmCopyToCaller(pvInformation
, pvData
, nDataSize
);
748 Status
= STATUS_BUFFER_TOO_SMALL
;
751 /* release objects */
752 if (WinStaObject
!= NULL
)
753 ObDereferenceObject(WinStaObject
);
754 if (DesktopObject
!= NULL
)
755 ObDereferenceObject(DesktopObject
);
757 SetLastNtError(Status
);
758 return NT_SUCCESS(Status
);
762 * NtUserSetObjectInformation
764 * The NtUserSetObjectInformation function sets information about a
765 * window station or desktop object.
769 * Handle to the window station or desktop object for which to set
770 * object information. This value can be a handle of type HDESK or
774 * Specifies the object information to be set.
777 * Pointer to a buffer containing the object information.
780 * Specifies the size, in bytes, of the information contained in the
781 * buffer pointed to by pvInfo.
784 * If the function succeeds, the return value is nonzero. If the function
785 * fails the return value is zero.
793 NtUserSetObjectInformation(
799 /* FIXME: ZwQueryObject */
800 /* FIXME: ZwSetInformationObject */
801 SetLastNtError(STATUS_UNSUCCESSFUL
);
809 UserGetProcessWindowStation(VOID
)
811 PPROCESSINFO ppi
= PsGetCurrentProcessWin32Process();
813 //ASSERT(ppi->hwinsta);
820 * NtUserGetProcessWindowStation
822 * Returns a handle to the current process window station.
825 * If the function succeeds, the return value is handle to the window
826 * station assigned to the current process. If the function fails, the
827 * return value is NULL.
834 NtUserGetProcessWindowStation(VOID
)
836 return UserGetProcessWindowStation();
839 PWINSTATION_OBJECT FASTCALL
840 IntGetWinStaObj(VOID
)
842 PWINSTATION_OBJECT WinStaObj
;
845 Status
= IntValidateWindowStationHandle(
846 UserGetProcessWindowStation(),
850 if(!NT_SUCCESS(Status
))
852 SetLastNtError(Status
);
860 UserSetProcessWindowStation(HWINSTA hWindowStation
)
865 PWINSTATION_OBJECT NewWinSta
= NULL
, OldWinSta
;
867 ppi
= PsGetCurrentProcessWin32Process();
869 /* Reference the new window station */
870 if(hWindowStation
!=NULL
)
872 Status
= IntValidateWindowStationHandle( hWindowStation
,
876 if (!NT_SUCCESS(Status
))
878 TRACE("Validation of window station handle (0x%X) failed\n",
880 SetLastNtError(Status
);
885 OldWinSta
= ppi
->prpwinsta
;
886 hwinstaOld
= PsGetProcessWin32WindowStation(ppi
->peProcess
);
888 /* Dereference the previous window station */
889 if(OldWinSta
!= NULL
)
891 ObDereferenceObject(OldWinSta
);
894 /* Check if we have a stale handle (it should happen for console apps) */
895 if(hwinstaOld
!= ppi
->hwinsta
)
897 ObCloseHandle(hwinstaOld
, UserMode
);
901 * FIXME: Don't allow changing the window station if there are threads that are attached to desktops and own GUI objects.
904 PsSetProcessWindowStation(ppi
->peProcess
, hWindowStation
);
906 ppi
->prpwinsta
= NewWinSta
;
907 ppi
->hwinsta
= hWindowStation
;
913 * NtUserSetProcessWindowStation
915 * Assigns a window station to the current process.
919 * Handle to the window station.
929 NtUserSetProcessWindowStation(HWINSTA hWindowStation
)
933 UserEnterExclusive();
935 ret
= UserSetProcessWindowStation(hWindowStation
);
943 * NtUserLockWindowStation
945 * Locks switching desktops. Only the logon application is allowed to call this function.
952 NtUserLockWindowStation(HWINSTA hWindowStation
)
954 PWINSTATION_OBJECT Object
;
957 TRACE("About to set process window station with handle (0x%X)\n",
960 if(PsGetCurrentProcessWin32Process() != LogonProcess
)
962 ERR("Unauthorized process attempted to lock the window station!\n");
963 EngSetLastError(ERROR_ACCESS_DENIED
);
967 Status
= IntValidateWindowStationHandle(
972 if (!NT_SUCCESS(Status
))
974 TRACE("Validation of window station handle (0x%X) failed\n",
976 SetLastNtError(Status
);
980 Object
->Flags
|= WSS_LOCKED
;
982 ObDereferenceObject(Object
);
987 * NtUserUnlockWindowStation
989 * Unlocks switching desktops. Only the logon application is allowed to call this function.
996 NtUserUnlockWindowStation(HWINSTA hWindowStation
)
998 PWINSTATION_OBJECT Object
;
1002 TRACE("About to set process window station with handle (0x%X)\n",
1005 if(PsGetCurrentProcessWin32Process() != LogonProcess
)
1007 ERR("Unauthorized process attempted to unlock the window station!\n");
1008 EngSetLastError(ERROR_ACCESS_DENIED
);
1012 Status
= IntValidateWindowStationHandle(
1017 if (!NT_SUCCESS(Status
))
1019 TRACE("Validation of window station handle (0x%X) failed\n",
1021 SetLastNtError(Status
);
1025 Ret
= (Object
->Flags
& WSS_LOCKED
) == WSS_LOCKED
;
1026 Object
->Flags
&= ~WSS_LOCKED
;
1028 ObDereferenceObject(Object
);
1032 static NTSTATUS FASTCALL
1033 BuildWindowStationNameList(
1036 PULONG pRequiredSize
)
1038 OBJECT_ATTRIBUTES ObjectAttributes
;
1040 HANDLE DirectoryHandle
;
1041 UNICODE_STRING DirectoryName
= RTL_CONSTANT_STRING(WINSTA_ROOT_NAME
);
1042 char InitialBuffer
[256], *Buffer
;
1043 ULONG Context
, ReturnLength
, BufferSize
;
1045 POBJECT_DIRECTORY_INFORMATION DirEntry
;
1049 * Try to open the directory.
1051 InitializeObjectAttributes(
1054 OBJ_CASE_INSENSITIVE
,
1058 Status
= ZwOpenDirectoryObject(
1063 if (!NT_SUCCESS(Status
))
1068 /* First try to query the directory using a fixed-size buffer */
1071 Status
= ZwQueryDirectoryObject(DirectoryHandle
, InitialBuffer
, sizeof(InitialBuffer
),
1072 FALSE
, TRUE
, &Context
, &ReturnLength
);
1073 if (NT_SUCCESS(Status
))
1075 if (STATUS_NO_MORE_ENTRIES
== ZwQueryDirectoryObject(DirectoryHandle
, NULL
, 0, FALSE
,
1076 FALSE
, &Context
, NULL
))
1078 /* Our fixed-size buffer is large enough */
1079 Buffer
= InitialBuffer
;
1085 /* Need a larger buffer, check how large exactly */
1086 Status
= ZwQueryDirectoryObject(DirectoryHandle
, NULL
, 0, FALSE
, TRUE
, &Context
,
1088 if (STATUS_BUFFER_TOO_SMALL
== Status
)
1090 BufferSize
= ReturnLength
;
1091 Buffer
= ExAllocatePoolWithTag(PagedPool
, BufferSize
, TAG_WINSTA
);
1094 ObDereferenceObject(DirectoryHandle
);
1095 return STATUS_NO_MEMORY
;
1098 /* We should have a sufficiently large buffer now */
1100 Status
= ZwQueryDirectoryObject(DirectoryHandle
, Buffer
, BufferSize
,
1101 FALSE
, TRUE
, &Context
, &ReturnLength
);
1102 if (! NT_SUCCESS(Status
) ||
1103 STATUS_NO_MORE_ENTRIES
!= ZwQueryDirectoryObject(DirectoryHandle
, NULL
, 0, FALSE
,
1104 FALSE
, &Context
, NULL
))
1106 /* Something went wrong, maybe someone added a directory entry? Just give up. */
1107 ExFreePoolWithTag(Buffer
, TAG_WINSTA
);
1108 ObDereferenceObject(DirectoryHandle
);
1109 return NT_SUCCESS(Status
) ? STATUS_INTERNAL_ERROR
: Status
;
1114 ZwClose(DirectoryHandle
);
1117 * Count the required size of buffer.
1119 ReturnLength
= sizeof(DWORD
);
1121 for (DirEntry
= (POBJECT_DIRECTORY_INFORMATION
) Buffer
; 0 != DirEntry
->Name
.Length
;
1124 ReturnLength
+= DirEntry
->Name
.Length
+ sizeof(WCHAR
);
1127 TRACE("Required size: %d Entry count: %d\n", ReturnLength
, EntryCount
);
1128 if (NULL
!= pRequiredSize
)
1130 Status
= MmCopyToCaller(pRequiredSize
, &ReturnLength
, sizeof(ULONG
));
1131 if (! NT_SUCCESS(Status
))
1133 if (Buffer
!= InitialBuffer
)
1135 ExFreePoolWithTag(Buffer
, TAG_WINSTA
);
1137 return STATUS_BUFFER_TOO_SMALL
;
1142 * Check if the supplied buffer is large enough.
1144 if (dwSize
< ReturnLength
)
1146 if (Buffer
!= InitialBuffer
)
1148 ExFreePoolWithTag(Buffer
, TAG_WINSTA
);
1150 return STATUS_BUFFER_TOO_SMALL
;
1154 * Generate the resulting buffer contents.
1156 Status
= MmCopyToCaller(lpBuffer
, &EntryCount
, sizeof(DWORD
));
1157 if (! NT_SUCCESS(Status
))
1159 if (Buffer
!= InitialBuffer
)
1165 lpBuffer
= (PVOID
) ((PCHAR
) lpBuffer
+ sizeof(DWORD
));
1168 for (DirEntry
= (POBJECT_DIRECTORY_INFORMATION
) Buffer
; 0 != DirEntry
->Name
.Length
;
1171 Status
= MmCopyToCaller(lpBuffer
, DirEntry
->Name
.Buffer
, DirEntry
->Name
.Length
);
1172 if (! NT_SUCCESS(Status
))
1174 if (Buffer
!= InitialBuffer
)
1180 lpBuffer
= (PVOID
) ((PCHAR
) lpBuffer
+ DirEntry
->Name
.Length
);
1181 Status
= MmCopyToCaller(lpBuffer
, &NullWchar
, sizeof(WCHAR
));
1182 if (! NT_SUCCESS(Status
))
1184 if (Buffer
!= InitialBuffer
)
1190 lpBuffer
= (PVOID
) ((PCHAR
) lpBuffer
+ sizeof(WCHAR
));
1196 if (NULL
!= Buffer
&& Buffer
!= InitialBuffer
)
1201 return STATUS_SUCCESS
;
1204 static NTSTATUS FASTCALL
1205 BuildDesktopNameList(
1206 HWINSTA hWindowStation
,
1209 PULONG pRequiredSize
)
1212 PWINSTATION_OBJECT WindowStation
;
1214 PLIST_ENTRY DesktopEntry
;
1215 PDESKTOP DesktopObject
;
1220 Status
= IntValidateWindowStationHandle(hWindowStation
,
1224 if (! NT_SUCCESS(Status
))
1229 KeAcquireSpinLock(&WindowStation
->Lock
, &OldLevel
);
1232 * Count the required size of buffer.
1234 ReturnLength
= sizeof(DWORD
);
1236 for (DesktopEntry
= WindowStation
->DesktopListHead
.Flink
;
1237 DesktopEntry
!= &WindowStation
->DesktopListHead
;
1238 DesktopEntry
= DesktopEntry
->Flink
)
1240 DesktopObject
= CONTAINING_RECORD(DesktopEntry
, DESKTOP
, ListEntry
);
1241 ReturnLength
+= ((PUNICODE_STRING
)GET_DESKTOP_NAME(DesktopObject
))->Length
+ sizeof(WCHAR
);
1244 TRACE("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 KeReleaseSpinLock(&WindowStation
->Lock
, OldLevel
);
1251 ObDereferenceObject(WindowStation
);
1252 return STATUS_BUFFER_TOO_SMALL
;
1257 * Check if the supplied buffer is large enough.
1259 if (dwSize
< ReturnLength
)
1261 KeReleaseSpinLock(&WindowStation
->Lock
, OldLevel
);
1262 ObDereferenceObject(WindowStation
);
1263 return STATUS_BUFFER_TOO_SMALL
;
1267 * Generate the resulting buffer contents.
1269 Status
= MmCopyToCaller(lpBuffer
, &EntryCount
, sizeof(DWORD
));
1270 if (! NT_SUCCESS(Status
))
1272 KeReleaseSpinLock(&WindowStation
->Lock
, OldLevel
);
1273 ObDereferenceObject(WindowStation
);
1276 lpBuffer
= (PVOID
) ((PCHAR
) lpBuffer
+ sizeof(DWORD
));
1279 for (DesktopEntry
= WindowStation
->DesktopListHead
.Flink
;
1280 DesktopEntry
!= &WindowStation
->DesktopListHead
;
1281 DesktopEntry
= DesktopEntry
->Flink
)
1283 DesktopObject
= CONTAINING_RECORD(DesktopEntry
, DESKTOP
, ListEntry
);
1284 Status
= MmCopyToCaller(lpBuffer
, ((PUNICODE_STRING
)GET_DESKTOP_NAME(DesktopObject
))->Buffer
, ((PUNICODE_STRING
)GET_DESKTOP_NAME(DesktopObject
))->Length
);
1285 if (! NT_SUCCESS(Status
))
1287 KeReleaseSpinLock(&WindowStation
->Lock
, OldLevel
);
1288 ObDereferenceObject(WindowStation
);
1291 lpBuffer
= (PVOID
) ((PCHAR
) lpBuffer
+ ((PUNICODE_STRING
)GET_DESKTOP_NAME(DesktopObject
))->Length
);
1292 Status
= MmCopyToCaller(lpBuffer
, &NullWchar
, sizeof(WCHAR
));
1293 if (! NT_SUCCESS(Status
))
1295 KeReleaseSpinLock(&WindowStation
->Lock
, OldLevel
);
1296 ObDereferenceObject(WindowStation
);
1299 lpBuffer
= (PVOID
) ((PCHAR
) lpBuffer
+ sizeof(WCHAR
));
1305 KeReleaseSpinLock(&WindowStation
->Lock
, OldLevel
);
1306 ObDereferenceObject(WindowStation
);
1308 return STATUS_SUCCESS
;
1312 * NtUserBuildNameList
1314 * Function used for enumeration of desktops or window stations.
1318 * For enumeration of window stations this parameter must be set to
1319 * zero. Otherwise it's handle for window station.
1322 * Size of buffer passed by caller.
1325 * Buffer passed by caller. If the function succedes, the buffer is
1326 * filled with window station/desktop count (in first DWORD) and
1327 * NULL-terminated window station/desktop names.
1330 * If the function suceedes, this is the number of bytes copied.
1331 * Otherwise it's size of buffer needed for function to succeed.
1338 NtUserBuildNameList(
1339 HWINSTA hWindowStation
,
1342 PULONG pRequiredSize
)
1344 /* The WindowStation name list and desktop name list are build in completely
1345 different ways. Call the appropriate function */
1346 return NULL
== hWindowStation
? BuildWindowStationNameList(dwSize
, lpBuffer
, pRequiredSize
) :
1347 BuildDesktopNameList(hWindowStation
, dwSize
, lpBuffer
, pRequiredSize
);
1354 NtUserSetLogonNotifyWindow(HWND hWnd
)
1356 if(LogonProcess
!= PsGetCurrentProcessWin32Process())
1361 if(!IntIsWindow(hWnd
))