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 /* Full path to WindowStations directory */
24 UNICODE_STRING gustrWindowStationsDir
;
26 /* INITALIZATION FUNCTIONS ****************************************************/
31 InitWindowStationImpl(VOID
)
33 GENERIC_MAPPING IntWindowStationMapping
= { WINSTA_READ
,
38 /* Set Winsta Object Attributes */
39 ExWindowStationObjectType
->TypeInfo
.DefaultNonPagedPoolCharge
= sizeof(WINSTATION_OBJECT
);
40 ExWindowStationObjectType
->TypeInfo
.GenericMapping
= IntWindowStationMapping
;
41 ExWindowStationObjectType
->TypeInfo
.ValidAccessMask
= WINSTA_ACCESS_ALL
;
43 return STATUS_SUCCESS
;
48 UserCreateWinstaDirectoy()
52 WCHAR wstrWindowStationsDir
[MAX_PATH
];
53 OBJECT_ATTRIBUTES ObjectAttributes
;
56 /* Create the WindowStations directory and cache its path for later use */
58 if(Peb
->SessionId
== 0)
60 RtlCreateUnicodeString(&gustrWindowStationsDir
, WINSTA_OBJ_DIR
);
64 swprintf(wstrWindowStationsDir
,
70 RtlCreateUnicodeString( &gustrWindowStationsDir
, wstrWindowStationsDir
);
73 InitializeObjectAttributes(&ObjectAttributes
,
74 &gustrWindowStationsDir
,
78 Status
= ZwCreateDirectoryObject(&hWinstaDir
, 0, &ObjectAttributes
);
79 if (!NT_SUCCESS(Status
))
81 ERR("Could not create %wZ directory (Status 0x%X)\n", &gustrWindowStationsDir
, Status
);
85 TRACE("Created directory %wZ for session %d\n", &gustrWindowStationsDir
, Peb
->SessionId
);
90 /* OBJECT CALLBACKS **********************************************************/
93 IntWinStaObjectDelete(PWIN32_DELETEMETHOD_PARAMETERS Parameters
)
95 PWINSTATION_OBJECT WinSta
= (PWINSTATION_OBJECT
)Parameters
->Object
;
97 TRACE("Deleting window station (0x%X)\n", WinSta
);
99 UserEmptyClipboardData(WinSta
);
101 RtlDestroyAtomTable(WinSta
->AtomTable
);
103 RtlFreeUnicodeString(&WinSta
->Name
);
108 IntWinStaObjectParse(PWIN32_PARSEMETHOD_PARAMETERS Parameters
)
110 PUNICODE_STRING RemainingName
= Parameters
->RemainingName
;
112 /* Assume we don't find anything */
113 *Parameters
->Object
= NULL
;
115 /* Check for an empty name */
116 if (!RemainingName
->Length
)
118 /* Make sure this is a window station, can't parse a desktop now */
119 if (Parameters
->ObjectType
!= ExWindowStationObjectType
)
122 return STATUS_OBJECT_TYPE_MISMATCH
;
125 /* Reference the window station and return */
126 ObReferenceObject(Parameters
->ParseObject
);
127 *Parameters
->Object
= Parameters
->ParseObject
;
128 return STATUS_SUCCESS
;
131 /* Check for leading slash */
132 if (RemainingName
->Buffer
[0] == OBJ_NAME_PATH_SEPARATOR
)
135 RemainingName
->Buffer
++;
136 RemainingName
->Length
-= sizeof(WCHAR
);
137 RemainingName
->MaximumLength
-= sizeof(WCHAR
);
140 /* Check if there is still a slash */
141 if (wcschr(RemainingName
->Buffer
, OBJ_NAME_PATH_SEPARATOR
))
143 /* In this case, fail */
144 return STATUS_OBJECT_PATH_INVALID
;
148 * Check if we are parsing a desktop.
150 if (Parameters
->ObjectType
== ExDesktopObjectType
)
152 /* Then call the desktop parse routine */
153 return IntDesktopObjectParse(Parameters
->ParseObject
,
154 Parameters
->ObjectType
,
155 Parameters
->AccessState
,
156 Parameters
->AccessMode
,
157 Parameters
->Attributes
,
158 Parameters
->CompleteName
,
161 Parameters
->SecurityQos
,
165 /* Should hopefully never get here */
166 return STATUS_OBJECT_TYPE_MISMATCH
;
171 IntWinstaOkToClose(PWIN32_OKAYTOCLOSEMETHOD_PARAMETERS Parameters
)
175 ppi
= PsGetCurrentProcessWin32Process();
177 if(ppi
&& (Parameters
->Handle
== ppi
->hwinsta
))
179 return STATUS_ACCESS_DENIED
;
182 return STATUS_SUCCESS
;
185 /* PRIVATE FUNCTIONS **********************************************************/
188 * IntValidateWindowStationHandle
190 * Validates the window station handle.
193 * If the function succeeds, the handle remains referenced. If the
194 * fucntion fails, last error is set.
198 IntValidateWindowStationHandle(
199 HWINSTA WindowStation
,
200 KPROCESSOR_MODE AccessMode
,
201 ACCESS_MASK DesiredAccess
,
202 PWINSTATION_OBJECT
*Object
)
206 if (WindowStation
== NULL
)
208 ERR("Invalid window station handle\n");
209 EngSetLastError(ERROR_INVALID_HANDLE
);
210 return STATUS_INVALID_HANDLE
;
213 Status
= ObReferenceObjectByHandle(
216 ExWindowStationObjectType
,
221 if (!NT_SUCCESS(Status
))
222 SetLastNtError(Status
);
228 co_IntInitializeDesktopGraphics(VOID
)
231 UNICODE_STRING DriverName
= RTL_CONSTANT_STRING(L
"DISPLAY");
232 if (! IntCreatePrimarySurface())
236 ScreenDeviceContext
= IntGdiCreateDC(&DriverName
, NULL
, NULL
, NULL
, FALSE
);
237 if (NULL
== ScreenDeviceContext
)
239 IntDestroyPrimarySurface();
242 GreSetDCOwner(ScreenDeviceContext
, GDI_OBJ_HMGR_PUBLIC
);
244 /* Setup the cursor */
245 co_IntLoadDefaultCursors();
247 hSystemBM
= NtGdiCreateCompatibleDC(ScreenDeviceContext
);
249 NtGdiSelectFont(hSystemBM
, NtGdiGetStockObject(SYSTEM_FONT
));
250 GreSetDCOwner(hSystemBM
, GDI_OBJ_HMGR_PUBLIC
);
252 // FIXME: Move these to a update routine.
253 gpsi
->Planes
= NtGdiGetDeviceCaps(ScreenDeviceContext
, PLANES
);
254 gpsi
->BitsPixel
= NtGdiGetDeviceCaps(ScreenDeviceContext
, BITSPIXEL
);
255 gpsi
->BitCount
= gpsi
->Planes
* gpsi
->BitsPixel
;
256 gpsi
->dmLogPixels
= NtGdiGetDeviceCaps(ScreenDeviceContext
, LOGPIXELSY
);
257 if (NtGdiGetDeviceCaps(ScreenDeviceContext
, RASTERCAPS
) & RC_PALETTE
)
259 gpsi
->PUSIFlags
|= PUSIF_PALETTEDISPLAY
;
262 gpsi
->PUSIFlags
&= ~PUSIF_PALETTEDISPLAY
;
263 // Font is realized and this dc was previously set to internal DC_ATTR.
264 gpsi
->cxSysFontChar
= IntGetCharDimensions(hSystemBM
, &tmw
, (DWORD
*)&gpsi
->cySysFontChar
);
265 gpsi
->tmSysFont
= tmw
;
271 IntEndDesktopGraphics(VOID
)
273 if (NULL
!= ScreenDeviceContext
)
274 { // No need to allocate a new dcattr.
275 GreSetDCOwner(ScreenDeviceContext
, GDI_OBJ_HMGR_POWNED
);
276 GreDeleteObject(ScreenDeviceContext
);
277 ScreenDeviceContext
= NULL
;
279 IntHideDesktop(IntGetActiveDesktop());
280 IntDestroyPrimarySurface();
286 return ScreenDeviceContext
;
289 /* PUBLIC FUNCTIONS ***********************************************************/
292 * NtUserCreateWindowStation
294 * Creates a new window station.
297 * lpszWindowStationName
298 * Pointer to a null-terminated string specifying the name of the
299 * window station to be created. Window station names are
300 * case-insensitive and cannot contain backslash characters (\).
301 * Only members of the Administrators group are allowed to specify a
305 * Requested type of access
308 * Security descriptor
310 * Unknown3, Unknown4, Unknown5
314 * If the function succeeds, the return value is a handle to the newly
315 * created window station. If the specified window station already
316 * exists, the function succeeds and returns a handle to the existing
317 * window station. If the function fails, the return value is NULL.
320 * Correct the prototype to match the Windows one (with 7 parameters
328 NtUserCreateWindowStation(
329 POBJECT_ATTRIBUTES ObjectAttributes
,
330 ACCESS_MASK dwDesiredAccess
,
337 UNICODE_STRING WindowStationName
;
338 PWINSTATION_OBJECT WindowStationObject
;
339 HWINSTA WindowStation
;
342 TRACE("NtUserCreateWindowStation called\n");
344 Status
= ObOpenObjectByName(
346 ExWindowStationObjectType
,
351 (PVOID
*)&WindowStation
);
353 if (NT_SUCCESS(Status
))
355 TRACE("NtUserCreateWindowStation opened window station %wZ\n", ObjectAttributes
->ObjectName
);
356 return (HWINSTA
)WindowStation
;
360 * No existing window station found, try to create new one
363 /* Capture window station name */
366 ProbeForRead( ObjectAttributes
, sizeof(OBJECT_ATTRIBUTES
), 1);
367 Status
= IntSafeCopyUnicodeStringTerminateNULL(&WindowStationName
, ObjectAttributes
->ObjectName
);
369 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
371 Status
=_SEH2_GetExceptionCode();
375 if (! NT_SUCCESS(Status
))
377 ERR("Failed reading capturing window station name\n");
378 SetLastNtError(Status
);
382 /* Create the window station object */
383 Status
= ObCreateObject(
385 ExWindowStationObjectType
,
389 sizeof(WINSTATION_OBJECT
),
392 (PVOID
*)&WindowStationObject
);
394 if (!NT_SUCCESS(Status
))
396 ERR("ObCreateObject failed for window station %wZ\n", &WindowStationName
);
397 ExFreePoolWithTag(WindowStationName
.Buffer
, TAG_STRING
);
398 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
402 Status
= ObInsertObject(
403 (PVOID
)WindowStationObject
,
408 (PVOID
*)&WindowStation
);
410 if (!NT_SUCCESS(Status
))
412 ERR("ObInsertObject failed for window station %wZ\n", &WindowStationName
);
413 ExFreePoolWithTag(WindowStationName
.Buffer
, TAG_STRING
);
414 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
415 ObDereferenceObject(WindowStationObject
);
419 /* Initialize the window station */
420 RtlZeroMemory(WindowStationObject
, sizeof(WINSTATION_OBJECT
));
422 KeInitializeSpinLock(&WindowStationObject
->Lock
);
423 InitializeListHead(&WindowStationObject
->DesktopListHead
);
424 Status
= RtlCreateAtomTable(37, &WindowStationObject
->AtomTable
);
425 WindowStationObject
->SystemMenuTemplate
= (HANDLE
)0;
426 WindowStationObject
->Name
= WindowStationName
;
428 if (InputWindowStation
== NULL
)
430 TRACE("Initializeing input window station\n");
431 InputWindowStation
= WindowStationObject
;
436 TRACE("NtUserCreateWindowStation created object 0x%x with name %wZ handle 0x%x\n",
437 WindowStation
, &WindowStationObject
->Name
, WindowStation
);
438 return WindowStation
;
442 * NtUserOpenWindowStation
444 * Opens an existing window station.
447 * lpszWindowStationName
448 * Name of the existing window station.
451 * Requested type of access.
454 * If the function succeeds, the return value is the handle to the
455 * specified window station. If the function fails, the return value
459 * The returned handle can be closed with NtUserCloseWindowStation.
466 NtUserOpenWindowStation(
467 POBJECT_ATTRIBUTES ObjectAttributes
,
468 ACCESS_MASK dwDesiredAccess
)
473 Status
= ObOpenObjectByName(
475 ExWindowStationObjectType
,
482 if (!NT_SUCCESS(Status
))
484 ERR("NtUserOpenWindowStation failed\n");
485 SetLastNtError(Status
);
489 TRACE("Opened window station %wZ with handle 0x%x\n", ObjectAttributes
->ObjectName
, hwinsta
);
495 * NtUserCloseWindowStation
497 * Closes a window station handle.
501 * Handle to the window station.
507 * The window station handle can be created with NtUserCreateWindowStation
508 * or NtUserOpenWindowStation. Attemps to close a handle to the window
509 * station assigned to the calling process will fail.
517 NtUserCloseWindowStation(
520 PWINSTATION_OBJECT Object
;
523 TRACE("NtUserCloseWindowStation called (0x%x)\n", hWinSta
);
525 if (hWinSta
== UserGetProcessWindowStation())
527 ERR("Attempted to close process window station");
531 Status
= IntValidateWindowStationHandle(
537 if (!NT_SUCCESS(Status
))
539 ERR("Validation of window station handle (0x%x) failed\n", hWinSta
);
543 ObDereferenceObject(Object
);
545 TRACE("Closing window station handle (0x%x)\n", hWinSta
);
547 Status
= ObCloseHandle(hWinSta
, UserMode
);
548 if (!NT_SUCCESS(Status
))
550 SetLastNtError(Status
);
558 * NtUserGetObjectInformation
560 * The NtUserGetObjectInformation function retrieves information about a
561 * window station or desktop object.
565 * Handle to the window station or desktop object for which to
566 * return information. This can be a handle of type HDESK or HWINSTA
567 * (for example, a handle returned by NtUserCreateWindowStation,
568 * NtUserOpenWindowStation, NtUserCreateDesktop, or NtUserOpenDesktop).
571 * Specifies the object information to be retrieved.
574 * Pointer to a buffer to receive the object information.
577 * Specifies the size, in bytes, of the buffer pointed to by the
581 * Pointer to a variable receiving the number of bytes required to
582 * store the requested information. If this variable's value is
583 * greater than the value of the nLength parameter when the function
584 * returns, the function returns FALSE, and none of the information
585 * is copied to the pvInfo buffer. If the value of the variable pointed
586 * to by lpnLengthNeeded is less than or equal to the value of nLength,
587 * the entire information block is copied.
590 * If the function succeeds, the return value is nonzero. If the function
591 * fails, the return value is zero.
598 NtUserGetObjectInformation(
603 PDWORD nLengthNeeded
)
605 PWINSTATION_OBJECT WinStaObject
= NULL
;
606 PDESKTOP DesktopObject
= NULL
;
611 /* try windowstation */
612 TRACE("Trying to open window station 0x%x\n", hObject
);
613 Status
= IntValidateWindowStationHandle(
620 if (!NT_SUCCESS(Status
) && Status
!= STATUS_OBJECT_TYPE_MISMATCH
)
622 TRACE("Failed: 0x%x\n", Status
);
623 SetLastNtError(Status
);
627 if (Status
== STATUS_OBJECT_TYPE_MISMATCH
)
630 TRACE("Trying to open desktop 0x%x\n", hObject
);
631 Status
= IntValidateDesktopHandle(
636 if (!NT_SUCCESS(Status
))
638 TRACE("Failed: 0x%x\n", Status
);
639 SetLastNtError(Status
);
643 TRACE("WinSta or Desktop opened!!\n");
649 Status
= STATUS_NOT_IMPLEMENTED
;
650 ERR("UOI_FLAGS unimplemented!\n");
654 if (WinStaObject
!= NULL
)
656 pvData
= WinStaObject
->Name
.Buffer
;
657 nDataSize
= WinStaObject
->Name
.Length
+ sizeof(WCHAR
);
658 Status
= STATUS_SUCCESS
;
660 else if (DesktopObject
!= NULL
)
662 pvData
= DesktopObject
->pDeskInfo
->szDesktopName
;
663 nDataSize
= (wcslen(DesktopObject
->pDeskInfo
->szDesktopName
) + 1) * sizeof(WCHAR
);
664 Status
= STATUS_SUCCESS
;
667 Status
= STATUS_INVALID_PARAMETER
;
671 if (WinStaObject
!= NULL
)
673 pvData
= L
"WindowStation";
674 nDataSize
= sizeof(L
"WindowStation");
675 Status
= STATUS_SUCCESS
;
677 else if (DesktopObject
!= NULL
)
680 nDataSize
= sizeof(L
"Desktop");
681 Status
= STATUS_SUCCESS
;
684 Status
= STATUS_INVALID_PARAMETER
;
688 Status
= STATUS_NOT_IMPLEMENTED
;
689 ERR("UOI_USER_SID unimplemented!\n");
693 Status
= STATUS_INVALID_PARAMETER
;
697 /* try to copy data to caller */
698 if (Status
== STATUS_SUCCESS
)
700 TRACE("Trying to copy data to caller (len = %d, len needed = %d)\n", nLength
, nDataSize
);
701 *nLengthNeeded
= nDataSize
;
702 if (nLength
>= nDataSize
)
703 Status
= MmCopyToCaller(pvInformation
, pvData
, nDataSize
);
705 Status
= STATUS_BUFFER_TOO_SMALL
;
708 /* release objects */
709 if (WinStaObject
!= NULL
)
710 ObDereferenceObject(WinStaObject
);
711 if (DesktopObject
!= NULL
)
712 ObDereferenceObject(DesktopObject
);
714 SetLastNtError(Status
);
715 return NT_SUCCESS(Status
);
719 * NtUserSetObjectInformation
721 * The NtUserSetObjectInformation function sets information about a
722 * window station or desktop object.
726 * Handle to the window station or desktop object for which to set
727 * object information. This value can be a handle of type HDESK or
731 * Specifies the object information to be set.
734 * Pointer to a buffer containing the object information.
737 * Specifies the size, in bytes, of the information contained in the
738 * buffer pointed to by pvInfo.
741 * If the function succeeds, the return value is nonzero. If the function
742 * fails the return value is zero.
750 NtUserSetObjectInformation(
756 /* FIXME: ZwQueryObject */
757 /* FIXME: ZwSetInformationObject */
758 SetLastNtError(STATUS_UNSUCCESSFUL
);
766 UserGetProcessWindowStation(VOID
)
768 PPROCESSINFO ppi
= PsGetCurrentProcessWin32Process();
775 * NtUserGetProcessWindowStation
777 * Returns a handle to the current process window station.
780 * If the function succeeds, the return value is handle to the window
781 * station assigned to the current process. If the function fails, the
782 * return value is NULL.
789 NtUserGetProcessWindowStation(VOID
)
791 return UserGetProcessWindowStation();
795 UserSetProcessWindowStation(HWINSTA hWindowStation
)
800 PWINSTATION_OBJECT NewWinSta
= NULL
, OldWinSta
;
802 ppi
= PsGetCurrentProcessWin32Process();
804 /* Reference the new window station */
805 if(hWindowStation
!=NULL
)
807 Status
= IntValidateWindowStationHandle( hWindowStation
,
811 if (!NT_SUCCESS(Status
))
813 TRACE("Validation of window station handle (0x%X) failed\n",
815 SetLastNtError(Status
);
820 OldWinSta
= ppi
->prpwinsta
;
821 hwinstaOld
= PsGetProcessWin32WindowStation(ppi
->peProcess
);
823 /* Dereference the previous window station */
824 if(OldWinSta
!= NULL
)
826 ObDereferenceObject(OldWinSta
);
829 /* Check if we have a stale handle (it should happen for console apps) */
830 if(hwinstaOld
!= ppi
->hwinsta
)
832 ObCloseHandle(hwinstaOld
, UserMode
);
836 * FIXME: Don't allow changing the window station if there are threads that are attached to desktops and own GUI objects.
839 PsSetProcessWindowStation(ppi
->peProcess
, hWindowStation
);
841 ppi
->prpwinsta
= NewWinSta
;
842 ppi
->hwinsta
= hWindowStation
;
848 * NtUserSetProcessWindowStation
850 * Assigns a window station to the current process.
854 * Handle to the window station.
864 NtUserSetProcessWindowStation(HWINSTA hWindowStation
)
868 UserEnterExclusive();
870 ret
= UserSetProcessWindowStation(hWindowStation
);
878 * NtUserLockWindowStation
880 * Locks switching desktops. Only the logon application is allowed to call this function.
887 NtUserLockWindowStation(HWINSTA hWindowStation
)
889 PWINSTATION_OBJECT Object
;
892 TRACE("About to set process window station with handle (0x%X)\n",
895 if(PsGetCurrentProcessWin32Process() != LogonProcess
)
897 ERR("Unauthorized process attempted to lock the window station!\n");
898 EngSetLastError(ERROR_ACCESS_DENIED
);
902 Status
= IntValidateWindowStationHandle(
907 if (!NT_SUCCESS(Status
))
909 TRACE("Validation of window station handle (0x%X) failed\n",
911 SetLastNtError(Status
);
915 Object
->Flags
|= WSS_LOCKED
;
917 ObDereferenceObject(Object
);
922 * NtUserUnlockWindowStation
924 * Unlocks switching desktops. Only the logon application is allowed to call this function.
931 NtUserUnlockWindowStation(HWINSTA hWindowStation
)
933 PWINSTATION_OBJECT Object
;
937 TRACE("About to set process window station with handle (0x%X)\n",
940 if(PsGetCurrentProcessWin32Process() != LogonProcess
)
942 ERR("Unauthorized process attempted to unlock the window station!\n");
943 EngSetLastError(ERROR_ACCESS_DENIED
);
947 Status
= IntValidateWindowStationHandle(
952 if (!NT_SUCCESS(Status
))
954 TRACE("Validation of window station handle (0x%X) failed\n",
956 SetLastNtError(Status
);
960 Ret
= (Object
->Flags
& WSS_LOCKED
) == WSS_LOCKED
;
961 Object
->Flags
&= ~WSS_LOCKED
;
963 ObDereferenceObject(Object
);
967 static NTSTATUS FASTCALL
968 BuildWindowStationNameList(
971 PULONG pRequiredSize
)
973 OBJECT_ATTRIBUTES ObjectAttributes
;
975 HANDLE DirectoryHandle
;
976 char InitialBuffer
[256], *Buffer
;
977 ULONG Context
, ReturnLength
, BufferSize
;
979 POBJECT_DIRECTORY_INFORMATION DirEntry
;
983 * Try to open the directory.
985 InitializeObjectAttributes(
987 &gustrWindowStationsDir
,
988 OBJ_CASE_INSENSITIVE
,
992 Status
= ZwOpenDirectoryObject(
997 if (!NT_SUCCESS(Status
))
1002 /* First try to query the directory using a fixed-size buffer */
1005 Status
= ZwQueryDirectoryObject(DirectoryHandle
, InitialBuffer
, sizeof(InitialBuffer
),
1006 FALSE
, TRUE
, &Context
, &ReturnLength
);
1007 if (NT_SUCCESS(Status
))
1009 if (STATUS_NO_MORE_ENTRIES
== ZwQueryDirectoryObject(DirectoryHandle
, NULL
, 0, FALSE
,
1010 FALSE
, &Context
, NULL
))
1012 /* Our fixed-size buffer is large enough */
1013 Buffer
= InitialBuffer
;
1019 /* Need a larger buffer, check how large exactly */
1020 Status
= ZwQueryDirectoryObject(DirectoryHandle
, NULL
, 0, FALSE
, TRUE
, &Context
,
1022 if (STATUS_BUFFER_TOO_SMALL
== Status
)
1024 BufferSize
= ReturnLength
;
1025 Buffer
= ExAllocatePoolWithTag(PagedPool
, BufferSize
, TAG_WINSTA
);
1028 ObDereferenceObject(DirectoryHandle
);
1029 return STATUS_NO_MEMORY
;
1032 /* We should have a sufficiently large buffer now */
1034 Status
= ZwQueryDirectoryObject(DirectoryHandle
, Buffer
, BufferSize
,
1035 FALSE
, TRUE
, &Context
, &ReturnLength
);
1036 if (! NT_SUCCESS(Status
) ||
1037 STATUS_NO_MORE_ENTRIES
!= ZwQueryDirectoryObject(DirectoryHandle
, NULL
, 0, FALSE
,
1038 FALSE
, &Context
, NULL
))
1040 /* Something went wrong, maybe someone added a directory entry? Just give up. */
1041 ExFreePoolWithTag(Buffer
, TAG_WINSTA
);
1042 ObDereferenceObject(DirectoryHandle
);
1043 return NT_SUCCESS(Status
) ? STATUS_INTERNAL_ERROR
: Status
;
1048 ZwClose(DirectoryHandle
);
1051 * Count the required size of buffer.
1053 ReturnLength
= sizeof(DWORD
);
1055 for (DirEntry
= (POBJECT_DIRECTORY_INFORMATION
) Buffer
; 0 != DirEntry
->Name
.Length
;
1058 ReturnLength
+= DirEntry
->Name
.Length
+ sizeof(WCHAR
);
1061 TRACE("Required size: %d Entry count: %d\n", ReturnLength
, EntryCount
);
1062 if (NULL
!= pRequiredSize
)
1064 Status
= MmCopyToCaller(pRequiredSize
, &ReturnLength
, sizeof(ULONG
));
1065 if (! NT_SUCCESS(Status
))
1067 if (Buffer
!= InitialBuffer
)
1069 ExFreePoolWithTag(Buffer
, TAG_WINSTA
);
1071 return STATUS_BUFFER_TOO_SMALL
;
1076 * Check if the supplied buffer is large enough.
1078 if (dwSize
< ReturnLength
)
1080 if (Buffer
!= InitialBuffer
)
1082 ExFreePoolWithTag(Buffer
, TAG_WINSTA
);
1084 return STATUS_BUFFER_TOO_SMALL
;
1088 * Generate the resulting buffer contents.
1090 Status
= MmCopyToCaller(lpBuffer
, &EntryCount
, sizeof(DWORD
));
1091 if (! NT_SUCCESS(Status
))
1093 if (Buffer
!= InitialBuffer
)
1099 lpBuffer
= (PVOID
) ((PCHAR
) lpBuffer
+ sizeof(DWORD
));
1102 for (DirEntry
= (POBJECT_DIRECTORY_INFORMATION
) Buffer
; 0 != DirEntry
->Name
.Length
;
1105 Status
= MmCopyToCaller(lpBuffer
, DirEntry
->Name
.Buffer
, DirEntry
->Name
.Length
);
1106 if (! NT_SUCCESS(Status
))
1108 if (Buffer
!= InitialBuffer
)
1114 lpBuffer
= (PVOID
) ((PCHAR
) lpBuffer
+ DirEntry
->Name
.Length
);
1115 Status
= MmCopyToCaller(lpBuffer
, &NullWchar
, sizeof(WCHAR
));
1116 if (! NT_SUCCESS(Status
))
1118 if (Buffer
!= InitialBuffer
)
1124 lpBuffer
= (PVOID
) ((PCHAR
) lpBuffer
+ sizeof(WCHAR
));
1130 if (NULL
!= Buffer
&& Buffer
!= InitialBuffer
)
1135 return STATUS_SUCCESS
;
1138 static NTSTATUS FASTCALL
1139 BuildDesktopNameList(
1140 HWINSTA hWindowStation
,
1143 PULONG pRequiredSize
)
1146 PWINSTATION_OBJECT WindowStation
;
1148 PLIST_ENTRY DesktopEntry
;
1149 PDESKTOP DesktopObject
;
1154 Status
= IntValidateWindowStationHandle(hWindowStation
,
1158 if (! NT_SUCCESS(Status
))
1163 KeAcquireSpinLock(&WindowStation
->Lock
, &OldLevel
);
1166 * Count the required size of buffer.
1168 ReturnLength
= sizeof(DWORD
);
1170 for (DesktopEntry
= WindowStation
->DesktopListHead
.Flink
;
1171 DesktopEntry
!= &WindowStation
->DesktopListHead
;
1172 DesktopEntry
= DesktopEntry
->Flink
)
1174 DesktopObject
= CONTAINING_RECORD(DesktopEntry
, DESKTOP
, ListEntry
);
1175 ReturnLength
+= ((PUNICODE_STRING
)GET_DESKTOP_NAME(DesktopObject
))->Length
+ sizeof(WCHAR
);
1178 TRACE("Required size: %d Entry count: %d\n", ReturnLength
, EntryCount
);
1179 if (NULL
!= pRequiredSize
)
1181 Status
= MmCopyToCaller(pRequiredSize
, &ReturnLength
, sizeof(ULONG
));
1182 if (! NT_SUCCESS(Status
))
1184 KeReleaseSpinLock(&WindowStation
->Lock
, OldLevel
);
1185 ObDereferenceObject(WindowStation
);
1186 return STATUS_BUFFER_TOO_SMALL
;
1191 * Check if the supplied buffer is large enough.
1193 if (dwSize
< ReturnLength
)
1195 KeReleaseSpinLock(&WindowStation
->Lock
, OldLevel
);
1196 ObDereferenceObject(WindowStation
);
1197 return STATUS_BUFFER_TOO_SMALL
;
1201 * Generate the resulting buffer contents.
1203 Status
= MmCopyToCaller(lpBuffer
, &EntryCount
, sizeof(DWORD
));
1204 if (! NT_SUCCESS(Status
))
1206 KeReleaseSpinLock(&WindowStation
->Lock
, OldLevel
);
1207 ObDereferenceObject(WindowStation
);
1210 lpBuffer
= (PVOID
) ((PCHAR
) lpBuffer
+ sizeof(DWORD
));
1213 for (DesktopEntry
= WindowStation
->DesktopListHead
.Flink
;
1214 DesktopEntry
!= &WindowStation
->DesktopListHead
;
1215 DesktopEntry
= DesktopEntry
->Flink
)
1217 DesktopObject
= CONTAINING_RECORD(DesktopEntry
, DESKTOP
, ListEntry
);
1218 Status
= MmCopyToCaller(lpBuffer
, ((PUNICODE_STRING
)GET_DESKTOP_NAME(DesktopObject
))->Buffer
, ((PUNICODE_STRING
)GET_DESKTOP_NAME(DesktopObject
))->Length
);
1219 if (! NT_SUCCESS(Status
))
1221 KeReleaseSpinLock(&WindowStation
->Lock
, OldLevel
);
1222 ObDereferenceObject(WindowStation
);
1225 lpBuffer
= (PVOID
) ((PCHAR
) lpBuffer
+ ((PUNICODE_STRING
)GET_DESKTOP_NAME(DesktopObject
))->Length
);
1226 Status
= MmCopyToCaller(lpBuffer
, &NullWchar
, sizeof(WCHAR
));
1227 if (! NT_SUCCESS(Status
))
1229 KeReleaseSpinLock(&WindowStation
->Lock
, OldLevel
);
1230 ObDereferenceObject(WindowStation
);
1233 lpBuffer
= (PVOID
) ((PCHAR
) lpBuffer
+ sizeof(WCHAR
));
1239 KeReleaseSpinLock(&WindowStation
->Lock
, OldLevel
);
1240 ObDereferenceObject(WindowStation
);
1242 return STATUS_SUCCESS
;
1246 * NtUserBuildNameList
1248 * Function used for enumeration of desktops or window stations.
1252 * For enumeration of window stations this parameter must be set to
1253 * zero. Otherwise it's handle for window station.
1256 * Size of buffer passed by caller.
1259 * Buffer passed by caller. If the function succedes, the buffer is
1260 * filled with window station/desktop count (in first DWORD) and
1261 * NULL-terminated window station/desktop names.
1264 * If the function suceedes, this is the number of bytes copied.
1265 * Otherwise it's size of buffer needed for function to succeed.
1272 NtUserBuildNameList(
1273 HWINSTA hWindowStation
,
1276 PULONG pRequiredSize
)
1278 /* The WindowStation name list and desktop name list are build in completely
1279 different ways. Call the appropriate function */
1280 return NULL
== hWindowStation
? BuildWindowStationNameList(dwSize
, lpBuffer
, pRequiredSize
) :
1281 BuildDesktopNameList(hWindowStation
, dwSize
, lpBuffer
, pRequiredSize
);
1288 NtUserSetLogonNotifyWindow(HWND hWnd
)
1290 if(LogonProcess
!= PsGetCurrentProcessWin32Process())
1295 if(!IntIsWindow(hWnd
))