3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * PURPOSE: Window stations and desktops
6 * FILE: subsys/win32k/ntuser/winsta.c
7 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
9 * 06-06-2001 CSH Created
10 * NOTES: Exported functions set the Win32 last error value
11 * on errors. The value can be retrieved with the Win32
12 * function GetLastError().
13 * TODO: The process window station is created on
14 * the first USER32/GDI32 call not related
15 * to window station/desktop handling
18 /* INCLUDES ******************************************************************/
20 #include <ddk/ntddk.h>
21 #include <win32k/win32k.h>
22 #include <include/winsta.h>
23 #include <include/object.h>
24 #include <include/guicheck.h>
25 #include <napi/win32.h>
26 #include <include/class.h>
27 #include <include/window.h>
32 /* GLOBALS *******************************************************************/
34 #define WINSTA_ROOT_NAME L"\\Windows\\WindowStations"
37 W32kDesktopWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
39 STATIC PWNDCLASS_OBJECT DesktopWindowClass;
41 /* Currently active desktop */
42 STATIC HDESK InputDesktopHandle = NULL;
43 STATIC PDESKTOP_OBJECT InputDesktop = NULL;
44 STATIC PWINSTATION_OBJECT InputWindowStation = NULL;
46 static HDC ScreenDeviceContext = NULL;
48 /* FUNCTIONS *****************************************************************/
51 W32kGetActiveDesktop(VOID)
57 InitWindowStationImpl(VOID)
59 OBJECT_ATTRIBUTES ObjectAttributes;
60 HANDLE WindowStationsDirectory;
61 UNICODE_STRING UnicodeString;
66 * Create the '\Windows\WindowStations' directory
68 RtlInitUnicodeStringFromLiteral(&UnicodeString,
71 InitializeObjectAttributes(&ObjectAttributes,
77 Status = ZwCreateDirectoryObject(&WindowStationsDirectory,
80 if (!NT_SUCCESS(Status))
82 DPRINT("Could not create \\Windows\\WindowStations directory "
83 "(Status 0x%X)\n", Status);
88 * Create the desktop window class
91 wcx.lpfnWndProc = W32kDesktopWindowProc;
92 wcx.cbClsExtra = wcx.cbWndExtra = 0;
93 wcx.hInstance = wcx.hIcon = wcx.hCursor = NULL;
94 wcx.hbrBackground = NULL;
95 wcx.lpszMenuName = NULL;
96 wcx.lpszClassName = L"DesktopWindowClass";
97 DesktopWindowClass = W32kCreateClass(&wcx, TRUE);
99 return(STATUS_SUCCESS);
103 CleanupWindowStationImpl(VOID)
105 return STATUS_SUCCESS;
110 ValidateWindowStationHandle(HWINSTA WindowStation,
111 KPROCESSOR_MODE AccessMode,
112 ACCESS_MASK DesiredAccess,
113 PWINSTATION_OBJECT *Object)
117 Status = ObReferenceObjectByHandle(WindowStation,
119 ExWindowStationObjectType,
123 if (!NT_SUCCESS(Status))
125 SetLastNtError(Status);
132 ValidateDesktopHandle(HDESK Desktop,
133 KPROCESSOR_MODE AccessMode,
134 ACCESS_MASK DesiredAccess,
135 PDESKTOP_OBJECT *Object)
139 Status = ObReferenceObjectByHandle(Desktop,
145 if (!NT_SUCCESS(Status))
147 SetLastNtError(Status);
155 * Closes a window station handle
157 * hWinSta = Handle to the window station
161 * The window station handle can be created with
162 * NtUserCreateWindowStation() or NtUserOpenWindowStation().
163 * Attemps to close a handle to the window station assigned
164 * to the calling process will fail
168 NtUserCloseWindowStation(
171 PWINSTATION_OBJECT Object;
174 DPRINT("About to close window station handle (0x%X)\n", hWinSta);
176 Status = ValidateWindowStationHandle(
181 if (!NT_SUCCESS(Status)) {
182 DPRINT("Validation of window station handle (0x%X) failed\n", hWinSta);
186 ObDereferenceObject(Object);
188 DPRINT("Closing window station handle (0x%X)\n", hWinSta);
190 Status = ZwClose(hWinSta);
191 if (!NT_SUCCESS(Status)) {
192 SetLastNtError(Status);
201 * Creates a new window station
203 * lpszWindowStationName = Name of the new window station
204 * dwDesiredAccess = Requested type of access
205 * lpSecurity = Security descriptor
210 * Handle to the new window station that can be closed with
211 * NtUserCloseWindowStation()
215 NtUserCreateWindowStation(PUNICODE_STRING lpszWindowStationName,
216 ACCESS_MASK dwDesiredAccess,
217 LPSECURITY_ATTRIBUTES lpSecurity,
222 OBJECT_ATTRIBUTES ObjectAttributes;
223 UNICODE_STRING WindowStationName;
224 PWINSTATION_OBJECT WinStaObject;
225 WCHAR NameBuffer[MAX_PATH];
229 wcscpy(NameBuffer, WINSTA_ROOT_NAME);
230 wcscat(NameBuffer, L"\\");
231 wcscat(NameBuffer, lpszWindowStationName->Buffer);
232 RtlInitUnicodeString(&WindowStationName, NameBuffer);
234 DPRINT("Trying to open window station (%wZ)\n", &WindowStationName);
236 /* Initialize ObjectAttributes for the window station object */
237 InitializeObjectAttributes(&ObjectAttributes,
243 Status = ObOpenObjectByName(&ObjectAttributes,
244 ExWindowStationObjectType,
250 if (NT_SUCCESS(Status))
252 DPRINT("Successfully opened window station (%wZ)\n", WindowStationName);
253 return((HWINSTA)WinSta);
256 DPRINT("Creating window station (%wZ)\n", &WindowStationName);
258 Status = ObCreateObject(&WinSta,
259 STANDARD_RIGHTS_REQUIRED,
261 ExWindowStationObjectType,
262 (PVOID*)&WinStaObject);
263 if (!NT_SUCCESS(Status))
265 DPRINT("Failed creating window station (%wZ)\n", &WindowStationName);
266 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
270 WinStaObject->HandleTable = ObmCreateHandleTable();
271 if (!WinStaObject->HandleTable)
273 DPRINT("Failed creating handle table\n");
274 ObDereferenceObject(WinStaObject);
275 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
279 DPRINT("Window station successfully created (%wZ)\n", &WindowStationName);
281 return((HWINSTA)WinSta);
286 NtUserGetObjectInformation(
291 PDWORD nLengthNeeded)
298 * Returns a handle to the current process window station
302 * Handle to the window station assigned to the current process
305 * The handle need not be closed by the caller
309 NtUserGetProcessWindowStation(VOID)
311 return PROCESS_WINDOW_STATION();
316 NtUserLockWindowStation(
317 HWINSTA hWindowStation)
326 * Opens an existing window station
328 * lpszWindowStationName = Name of the existing window station
329 * dwDesiredAccess = Requested type of access
331 * Handle to the window station
334 * The returned handle can be closed with NtUserCloseWindowStation()
338 NtUserOpenWindowStation(
339 PUNICODE_STRING lpszWindowStationName,
340 ACCESS_MASK dwDesiredAccess)
342 OBJECT_ATTRIBUTES ObjectAttributes;
343 UNICODE_STRING WindowStationName;
344 PWINSTATION_OBJECT WinStaObject;
345 WCHAR NameBuffer[MAX_PATH];
349 wcscpy(NameBuffer, WINSTA_ROOT_NAME);
350 wcscat(NameBuffer, L"\\");
351 wcscat(NameBuffer, lpszWindowStationName->Buffer);
352 RtlInitUnicodeString(&WindowStationName, NameBuffer);
354 DPRINT("Trying to open window station (%wZ)\n", &WindowStationName);
356 /* Initialize ObjectAttributes for the window station object */
357 InitializeObjectAttributes(
364 Status = ObOpenObjectByName(
372 if (NT_SUCCESS(Status))
374 DPRINT("Successfully opened window station (%wZ)\n", &WindowStationName);
375 return (HWINSTA)WinSta;
378 SetLastNtError(Status);
384 NtUserSetObjectInformation(
390 /* FIXME: ZwQueryObject */
391 /* FIXME: ZwSetInformationObject */
392 SetLastNtError(STATUS_UNSUCCESSFUL);
398 * Assigns a window station to the current process
400 * hWinSta = Handle to the window station
405 NtUserSetProcessWindowStation(HWINSTA hWindowStation)
407 PWINSTATION_OBJECT Object;
410 DPRINT("About to set process window station with handle (0x%X)\n",
413 Status = ValidateWindowStationHandle(hWindowStation,
417 if (!NT_SUCCESS(Status))
419 DPRINT("Validation of window station handle (0x%X) failed\n",
424 ObDereferenceObject(Object);
426 SET_PROCESS_WINDOW_STATION(hWindowStation);
427 DPRINT("IoGetCurrentProcess()->Win32WindowStation 0x%X\n",
428 IoGetCurrentProcess()->Win32WindowStation);
435 NtUserSetWindowStationUser(
448 NtUserUnlockWindowStation(
449 HWINSTA hWindowStation)
459 * Closes a desktop handle
461 * hDesktop = Handle to the desktop
465 * The desktop handle can be created with NtUserCreateDesktop() or
466 * NtUserOpenDesktop().
467 * The function will fail if any thread in the calling process is using the
468 * specified desktop handle or if the handle refers to the initial desktop
469 * of the calling process
476 PDESKTOP_OBJECT Object;
479 DPRINT("About to close desktop handle (0x%X)\n", hDesktop);
481 Status = ValidateDesktopHandle(
486 if (!NT_SUCCESS(Status)) {
487 DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop);
491 ObDereferenceObject(Object);
493 DPRINT("Closing desktop handle (0x%X)\n", hDesktop);
495 Status = ZwClose(hDesktop);
496 if (!NT_SUCCESS(Status)) {
497 SetLastNtError(Status);
506 * Creates a new desktop
508 * lpszDesktopName = Name of the new desktop
509 * dwFlags = Interaction flags
510 * dwDesiredAccess = Requested type of access
511 * lpSecurity = Security descriptor
512 * hWindowStation = Handle to window station on which to create the desktop
514 * Handle to the new desktop that can be closed with NtUserCloseDesktop()
518 NtUserCreateDesktop(PUNICODE_STRING lpszDesktopName,
520 ACCESS_MASK dwDesiredAccess,
521 LPSECURITY_ATTRIBUTES lpSecurity,
522 HWINSTA hWindowStation)
524 OBJECT_ATTRIBUTES ObjectAttributes;
525 PWINSTATION_OBJECT WinStaObject;
526 PDESKTOP_OBJECT DesktopObject;
527 UNICODE_STRING DesktopName;
528 WCHAR NameBuffer[MAX_PATH];
532 Status = ValidateWindowStationHandle(hWindowStation,
536 if (!NT_SUCCESS(Status))
538 DPRINT("Failed validation of window station handle (0x%X)\n",
543 wcscpy(NameBuffer, WINSTA_ROOT_NAME);
544 wcscat(NameBuffer, L"\\");
545 wcscat(NameBuffer, WinStaObject->Name.Buffer);
546 wcscat(NameBuffer, L"\\");
547 wcscat(NameBuffer, lpszDesktopName->Buffer);
548 RtlInitUnicodeString(&DesktopName, NameBuffer);
550 ObDereferenceObject(WinStaObject);
552 DPRINT("Trying to open desktop (%wZ)\n", &DesktopName);
554 /* Initialize ObjectAttributes for the desktop object */
555 InitializeObjectAttributes(&ObjectAttributes,
560 Status = ObOpenObjectByName(&ObjectAttributes,
567 if (NT_SUCCESS(Status))
569 DPRINT("Successfully opened desktop (%wZ)\n", &DesktopName);
570 return((HDESK)Desktop);
573 DPRINT("Status for open operation (0x%X)\n", Status);
575 Status = ObCreateObject(&Desktop,
576 STANDARD_RIGHTS_REQUIRED,
579 (PVOID*)&DesktopObject);
580 if (!NT_SUCCESS(Status))
582 DPRINT("Failed creating desktop (%wZ)\n", &DesktopName);
583 SetLastNtError(STATUS_UNSUCCESSFUL);
587 /* Initialize some local (to win32k) desktop state. */
588 DesktopObject->ActiveMessageQueue = NULL;
589 InitializeListHead(&DesktopObject->WindowListHead);
590 DesktopObject->DesktopWindow =
591 W32kCreateDesktopWindow(DesktopObject->WindowStation,
595 return((HDESK)Desktop);
599 NtUserGetThreadDesktop(DWORD dwThreadId,
608 * Opens an existing desktop
610 * lpszDesktopName = Name of the existing desktop
611 * dwFlags = Interaction flags
612 * dwDesiredAccess = Requested type of access
614 * Handle to the desktop
617 * The returned handle can be closed with NtUserCloseDesktop()
622 PUNICODE_STRING lpszDesktopName,
624 ACCESS_MASK dwDesiredAccess)
626 OBJECT_ATTRIBUTES ObjectAttributes;
627 PWINSTATION_OBJECT WinStaObject;
628 UNICODE_STRING DesktopName;
629 WCHAR NameBuffer[MAX_PATH];
633 /* Validate the window station handle and
634 compose the fully qualified desktop name */
636 Status = ValidateWindowStationHandle(
637 PROCESS_WINDOW_STATION(),
641 if (!NT_SUCCESS(Status))
643 DPRINT("Failed validation of window station handle (0x%X)\n",
644 PROCESS_WINDOW_STATION());
648 wcscpy(NameBuffer, WINSTA_ROOT_NAME);
649 wcscat(NameBuffer, L"\\");
650 wcscat(NameBuffer, WinStaObject->Name.Buffer);
651 wcscat(NameBuffer, L"\\");
652 wcscat(NameBuffer, lpszDesktopName->Buffer);
653 RtlInitUnicodeString(&DesktopName, NameBuffer);
655 ObDereferenceObject(WinStaObject);
658 DPRINT("Trying to open desktop station (%wZ)\n", &DesktopName);
660 /* Initialize ObjectAttributes for the desktop object */
661 InitializeObjectAttributes(
668 Status = ObOpenObjectByName(
676 if (NT_SUCCESS(Status))
678 DPRINT("Successfully opened desktop (%wZ)\n", &DesktopName);
679 return (HDESK)Desktop;
682 SetLastNtError(Status);
688 * Opens the input (interactive) desktop
690 * dwFlags = Interaction flags
691 * fInherit = Inheritance option
692 * dwDesiredAccess = Requested type of access
694 * Handle to the input desktop
697 * The returned handle can be closed with NtUserCloseDesktop()
701 NtUserOpenInputDesktop(
704 ACCESS_MASK dwDesiredAccess)
706 PDESKTOP_OBJECT Object;
710 DPRINT("About to open input desktop\n");
712 /* Get a pointer to the desktop object */
714 Status = ValidateDesktopHandle(
719 if (!NT_SUCCESS(Status)) {
720 DPRINT("Validation of input desktop handle (0x%X) failed\n", InputDesktop);
724 /* Create a new handle to the object */
726 Status = ObOpenObjectByPointer(
735 ObDereferenceObject(Object);
737 if (NT_SUCCESS(Status))
739 DPRINT("Successfully opened input desktop\n");
740 return (HDESK)Desktop;
743 SetLastNtError(Status);
748 NtUserPaintDesktop(HDC hDC)
756 NtUserResolveDesktopForWOW(DWORD Unknown0)
763 NtUserSetThreadDesktop(HDESK hDesktop)
765 PDESKTOP_OBJECT DesktopObject;
768 /* Initialize the Win32 state if necessary. */
771 /* Validate the new desktop. */
772 Status = ValidateDesktopHandle(hDesktop,
776 if (!NT_SUCCESS(Status))
778 DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop);
782 /* Check for setting the same desktop as before. */
783 if (DesktopObject == PsGetWin32Thread()->Desktop)
785 ObDereferenceObject(DesktopObject);
789 /* FIXME: Should check here to see if the thread has any windows. */
791 ObDereferenceObject(PsGetWin32Thread()->Desktop);
792 PsGetWin32Thread()->Desktop = DesktopObject;
799 * Sets the current input (interactive) desktop
801 * hDesktop = Handle to desktop
806 NtUserSwitchDesktop(HDESK hDesktop)
808 PDESKTOP_OBJECT DesktopObject;
811 DPRINT("About to switch desktop (0x%X)\n", hDesktop);
813 Status = ValidateDesktopHandle(hDesktop,
817 if (!NT_SUCCESS(Status))
819 DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop);
823 /* FIXME: Fail if the desktop belong to an invisible window station */
824 /* FIXME: Fail if the process is associated with a secured
825 desktop such as Winlogon or Screen-Saver */
826 /* FIXME: Connect to input device */
828 /* Set the active desktop in the desktop's window station. */
829 DesktopObject->WindowStation->ActiveDesktop = DesktopObject;
831 /* Set the global state. */
832 InputDesktopHandle = hDesktop;
833 InputDesktop = DesktopObject;
834 InputWindowStation = DesktopObject->WindowStation;
836 ObDereferenceObject(DesktopObject);
842 W32kInitializeDesktopGraphics(VOID)
844 ScreenDeviceContext = W32kCreateDC(L"DISPLAY", NULL, NULL, NULL);
845 GDIOBJ_MarkObjectGlobal(ScreenDeviceContext);
846 EnableMouse(ScreenDeviceContext);
847 NtUserAcquireOrReleaseInputOwnership(FALSE);
851 W32kEndDesktopGraphics(VOID)
853 NtUserAcquireOrReleaseInputOwnership(TRUE);
855 if (NULL != ScreenDeviceContext)
857 W32kDeleteDC(ScreenDeviceContext);
858 ScreenDeviceContext = NULL;
863 W32kGetScreenDC(VOID)
865 return(ScreenDeviceContext);
869 W32kDesktopWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)