1 /* $Id: winsta.c,v 1.7 2002/08/20 20:37:19 hyperion Exp $
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 /* FUNCTIONS *****************************************************************/
49 W32kGetActiveDesktop(VOID
)
55 InitWindowStationImpl(VOID
)
57 OBJECT_ATTRIBUTES ObjectAttributes
;
58 HANDLE WindowStationsDirectory
;
59 UNICODE_STRING UnicodeString
;
64 * Create the '\Windows\WindowStations' directory
66 RtlInitUnicodeStringFromLiteral(&UnicodeString
,
69 InitializeObjectAttributes(&ObjectAttributes
,
75 Status
= ZwCreateDirectoryObject(&WindowStationsDirectory
,
78 if (!NT_SUCCESS(Status
))
80 DPRINT("Could not create \\Windows\\WindowStations directory "
81 "(Status 0x%X)\n", Status
);
86 * Create the desktop window class
89 wcx
.lpfnWndProc
= W32kDesktopWindowProc
;
90 wcx
.cbClsExtra
= wcx
.cbWndExtra
= 0;
91 wcx
.hInstance
= wcx
.hIcon
= wcx
.hCursor
= NULL
;
92 wcx
.hbrBackground
= NULL
;
93 wcx
.lpszMenuName
= NULL
;
94 wcx
.lpszClassName
= L
"DesktopWindowClass";
95 DesktopWindowClass
= W32kCreateClass(&wcx
, TRUE
);
97 return(STATUS_SUCCESS
);
101 CleanupWindowStationImpl(VOID
)
103 return STATUS_SUCCESS
;
108 ValidateWindowStationHandle(HWINSTA WindowStation
,
109 KPROCESSOR_MODE AccessMode
,
110 ACCESS_MASK DesiredAccess
,
111 PWINSTATION_OBJECT
*Object
)
115 Status
= ObReferenceObjectByHandle(WindowStation
,
117 ExWindowStationObjectType
,
121 if (!NT_SUCCESS(Status
))
123 SetLastNtError(Status
);
130 ValidateDesktopHandle(HDESK Desktop
,
131 KPROCESSOR_MODE AccessMode
,
132 ACCESS_MASK DesiredAccess
,
133 PDESKTOP_OBJECT
*Object
)
137 Status
= ObReferenceObjectByHandle(Desktop
,
143 if (!NT_SUCCESS(Status
))
145 SetLastNtError(Status
);
153 * Closes a window station handle
155 * hWinSta = Handle to the window station
159 * The window station handle can be created with
160 * NtUserCreateWindowStation() or NtUserOpenWindowStation().
161 * Attemps to close a handle to the window station assigned
162 * to the calling process will fail
166 NtUserCloseWindowStation(
169 PWINSTATION_OBJECT Object
;
172 DPRINT("About to close window station handle (0x%X)\n", hWinSta
);
174 Status
= ValidateWindowStationHandle(
179 if (!NT_SUCCESS(Status
)) {
180 DPRINT("Validation of window station handle (0x%X) failed\n", hWinSta
);
184 ObDereferenceObject(Object
);
186 DPRINT("Closing window station handle (0x%X)\n", hWinSta
);
188 Status
= ZwClose(hWinSta
);
189 if (!NT_SUCCESS(Status
)) {
190 SetLastNtError(Status
);
199 * Creates a new window station
201 * lpszWindowStationName = Name of the new window station
202 * dwDesiredAccess = Requested type of access
203 * lpSecurity = Security descriptor
208 * Handle to the new window station that can be closed with
209 * NtUserCloseWindowStation()
213 NtUserCreateWindowStation(PUNICODE_STRING lpszWindowStationName
,
214 ACCESS_MASK dwDesiredAccess
,
215 LPSECURITY_ATTRIBUTES lpSecurity
,
220 OBJECT_ATTRIBUTES ObjectAttributes
;
221 UNICODE_STRING WindowStationName
;
222 PWINSTATION_OBJECT WinStaObject
;
223 WCHAR NameBuffer
[MAX_PATH
];
227 wcscpy(NameBuffer
, WINSTA_ROOT_NAME
);
228 wcscat(NameBuffer
, L
"\\");
229 wcscat(NameBuffer
, lpszWindowStationName
->Buffer
);
230 RtlInitUnicodeString(&WindowStationName
, NameBuffer
);
232 DPRINT("Trying to open window station (%wZ)\n", &WindowStationName
);
234 /* Initialize ObjectAttributes for the window station object */
235 InitializeObjectAttributes(&ObjectAttributes
,
241 Status
= ObOpenObjectByName(&ObjectAttributes
,
242 ExWindowStationObjectType
,
248 if (NT_SUCCESS(Status
))
250 DPRINT("Successfully opened window station (%wZ)\n", WindowStationName
);
251 return((HWINSTA
)WinSta
);
254 DPRINT("Creating window station (%wZ)\n", &WindowStationName
);
256 Status
= ObCreateObject(&WinSta
,
257 STANDARD_RIGHTS_REQUIRED
,
259 ExWindowStationObjectType
,
260 (PVOID
*)&WinStaObject
);
261 if (!NT_SUCCESS(Status
))
263 DPRINT("Failed creating window station (%wZ)\n", &WindowStationName
);
264 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
268 WinStaObject
->HandleTable
= ObmCreateHandleTable();
269 if (!WinStaObject
->HandleTable
)
271 DPRINT("Failed creating handle table\n");
272 ObDereferenceObject(WinStaObject
);
273 SetLastNtError(STATUS_INSUFFICIENT_RESOURCES
);
277 DPRINT("Window station successfully created (%wZ)\n", &WindowStationName
);
279 return((HWINSTA
)WinSta
);
284 NtUserGetObjectInformation(
289 PDWORD nLengthNeeded
)
296 * Returns a handle to the current process window station
300 * Handle to the window station assigned to the current process
303 * The handle need not be closed by the caller
307 NtUserGetProcessWindowStation(VOID
)
309 return PROCESS_WINDOW_STATION();
314 NtUserLockWindowStation(
315 HWINSTA hWindowStation
)
324 * Opens an existing window station
326 * lpszWindowStationName = Name of the existing window station
327 * dwDesiredAccess = Requested type of access
329 * Handle to the window station
332 * The returned handle can be closed with NtUserCloseWindowStation()
336 NtUserOpenWindowStation(
337 PUNICODE_STRING lpszWindowStationName
,
338 ACCESS_MASK dwDesiredAccess
)
340 OBJECT_ATTRIBUTES ObjectAttributes
;
341 UNICODE_STRING WindowStationName
;
342 PWINSTATION_OBJECT WinStaObject
;
343 WCHAR NameBuffer
[MAX_PATH
];
347 wcscpy(NameBuffer
, WINSTA_ROOT_NAME
);
348 wcscat(NameBuffer
, L
"\\");
349 wcscat(NameBuffer
, lpszWindowStationName
->Buffer
);
350 RtlInitUnicodeString(&WindowStationName
, NameBuffer
);
352 DPRINT("Trying to open window station (%wZ)\n", &WindowStationName
);
354 /* Initialize ObjectAttributes for the window station object */
355 InitializeObjectAttributes(
362 Status
= ObOpenObjectByName(
370 if (NT_SUCCESS(Status
))
372 DPRINT("Successfully opened window station (%wZ)\n", &WindowStationName
);
373 return (HWINSTA
)WinSta
;
376 SetLastNtError(Status
);
382 NtUserSetObjectInformation(
388 /* FIXME: ZwQueryObject */
389 /* FIXME: ZwSetInformationObject */
390 SetLastNtError(STATUS_UNSUCCESSFUL
);
396 * Assigns a window station to the current process
398 * hWinSta = Handle to the window station
403 NtUserSetProcessWindowStation(HWINSTA hWindowStation
)
405 PWINSTATION_OBJECT Object
;
408 DPRINT("About to set process window station with handle (0x%X)\n",
411 Status
= ValidateWindowStationHandle(hWindowStation
,
415 if (!NT_SUCCESS(Status
))
417 DPRINT("Validation of window station handle (0x%X) failed\n",
422 ObDereferenceObject(Object
);
424 SET_PROCESS_WINDOW_STATION(hWindowStation
);
425 DPRINT("IoGetCurrentProcess()->Win32WindowStation 0x%X\n",
426 IoGetCurrentProcess()->Win32WindowStation
);
433 NtUserSetWindowStationUser(
446 NtUserUnlockWindowStation(
447 HWINSTA hWindowStation
)
457 * Closes a desktop handle
459 * hDesktop = Handle to the desktop
463 * The desktop handle can be created with NtUserCreateDesktop() or
464 * NtUserOpenDesktop().
465 * The function will fail if any thread in the calling process is using the
466 * specified desktop handle or if the handle refers to the initial desktop
467 * of the calling process
474 PDESKTOP_OBJECT Object
;
477 DPRINT("About to close desktop handle (0x%X)\n", hDesktop
);
479 Status
= ValidateDesktopHandle(
484 if (!NT_SUCCESS(Status
)) {
485 DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop
);
489 ObDereferenceObject(Object
);
491 DPRINT("Closing desktop handle (0x%X)\n", hDesktop
);
493 Status
= ZwClose(hDesktop
);
494 if (!NT_SUCCESS(Status
)) {
495 SetLastNtError(Status
);
504 * Creates a new desktop
506 * lpszDesktopName = Name of the new desktop
507 * dwFlags = Interaction flags
508 * dwDesiredAccess = Requested type of access
509 * lpSecurity = Security descriptor
510 * hWindowStation = Handle to window station on which to create the desktop
512 * Handle to the new desktop that can be closed with NtUserCloseDesktop()
516 NtUserCreateDesktop(PUNICODE_STRING lpszDesktopName
,
518 ACCESS_MASK dwDesiredAccess
,
519 LPSECURITY_ATTRIBUTES lpSecurity
,
520 HWINSTA hWindowStation
)
522 OBJECT_ATTRIBUTES ObjectAttributes
;
523 PWINSTATION_OBJECT WinStaObject
;
524 PDESKTOP_OBJECT DesktopObject
;
525 UNICODE_STRING DesktopName
;
526 WCHAR NameBuffer
[MAX_PATH
];
530 Status
= ValidateWindowStationHandle(hWindowStation
,
534 if (!NT_SUCCESS(Status
))
536 DPRINT("Failed validation of window station handle (0x%X)\n",
541 wcscpy(NameBuffer
, WINSTA_ROOT_NAME
);
542 wcscat(NameBuffer
, L
"\\");
543 wcscat(NameBuffer
, WinStaObject
->Name
.Buffer
);
544 wcscat(NameBuffer
, L
"\\");
545 wcscat(NameBuffer
, lpszDesktopName
->Buffer
);
546 RtlInitUnicodeString(&DesktopName
, NameBuffer
);
548 ObDereferenceObject(WinStaObject
);
550 DPRINT("Trying to open desktop (%wZ)\n", &DesktopName
);
552 /* Initialize ObjectAttributes for the desktop object */
553 InitializeObjectAttributes(&ObjectAttributes
,
558 Status
= ObOpenObjectByName(&ObjectAttributes
,
565 if (NT_SUCCESS(Status
))
567 DPRINT("Successfully opened desktop (%wZ)\n", &DesktopName
);
568 return((HDESK
)Desktop
);
571 DPRINT("Status for open operation (0x%X)\n", Status
);
573 Status
= ObCreateObject(&Desktop
,
574 STANDARD_RIGHTS_REQUIRED
,
577 (PVOID
*)&DesktopObject
);
578 if (!NT_SUCCESS(Status
))
580 DPRINT("Failed creating desktop (%wZ)\n", &DesktopName
);
581 SetLastNtError(STATUS_UNSUCCESSFUL
);
585 /* Initialize some local (to win32k) desktop state. */
586 DesktopObject
->ActiveMessageQueue
= NULL
;
587 InitializeListHead(&DesktopObject
->WindowListHead
);
588 DesktopObject
->DesktopWindow
=
589 W32kCreateDesktopWindow(DesktopObject
->WindowStation
,
593 return((HDESK
)Desktop
);
597 NtUserGetThreadDesktop(DWORD dwThreadId
,
606 * Opens an existing desktop
608 * lpszDesktopName = Name of the existing desktop
609 * dwFlags = Interaction flags
610 * dwDesiredAccess = Requested type of access
612 * Handle to the desktop
615 * The returned handle can be closed with NtUserCloseDesktop()
620 PUNICODE_STRING lpszDesktopName
,
622 ACCESS_MASK dwDesiredAccess
)
624 OBJECT_ATTRIBUTES ObjectAttributes
;
625 PWINSTATION_OBJECT WinStaObject
;
626 UNICODE_STRING DesktopName
;
627 WCHAR NameBuffer
[MAX_PATH
];
631 /* Validate the window station handle and
632 compose the fully qualified desktop name */
634 Status
= ValidateWindowStationHandle(
635 PROCESS_WINDOW_STATION(),
639 if (!NT_SUCCESS(Status
))
641 DPRINT("Failed validation of window station handle (0x%X)\n",
642 PROCESS_WINDOW_STATION());
646 wcscpy(NameBuffer
, WINSTA_ROOT_NAME
);
647 wcscat(NameBuffer
, L
"\\");
648 wcscat(NameBuffer
, WinStaObject
->Name
.Buffer
);
649 wcscat(NameBuffer
, L
"\\");
650 wcscat(NameBuffer
, lpszDesktopName
->Buffer
);
651 RtlInitUnicodeString(&DesktopName
, NameBuffer
);
653 ObDereferenceObject(WinStaObject
);
656 DPRINT("Trying to open desktop station (%wZ)\n", &DesktopName
);
658 /* Initialize ObjectAttributes for the desktop object */
659 InitializeObjectAttributes(
666 Status
= ObOpenObjectByName(
674 if (NT_SUCCESS(Status
))
676 DPRINT("Successfully opened desktop (%wZ)\n", &DesktopName
);
677 return (HDESK
)Desktop
;
680 SetLastNtError(Status
);
686 * Opens the input (interactive) desktop
688 * dwFlags = Interaction flags
689 * fInherit = Inheritance option
690 * dwDesiredAccess = Requested type of access
692 * Handle to the input desktop
695 * The returned handle can be closed with NtUserCloseDesktop()
699 NtUserOpenInputDesktop(
702 ACCESS_MASK dwDesiredAccess
)
704 PDESKTOP_OBJECT Object
;
708 DPRINT("About to open input desktop\n");
710 /* Get a pointer to the desktop object */
712 Status
= ValidateDesktopHandle(
717 if (!NT_SUCCESS(Status
)) {
718 DPRINT("Validation of input desktop handle (0x%X) failed\n", InputDesktop
);
722 /* Create a new handle to the object */
724 Status
= ObOpenObjectByPointer(
733 ObDereferenceObject(Object
);
735 if (NT_SUCCESS(Status
))
737 DPRINT("Successfully opened input desktop\n");
738 return (HDESK
)Desktop
;
741 SetLastNtError(Status
);
746 NtUserPaintDesktop(HDC hDC
)
754 NtUserResolveDesktopForWOW(DWORD Unknown0
)
761 NtUserSetThreadDesktop(HDESK hDesktop
)
763 PDESKTOP_OBJECT DesktopObject
;
766 /* Initialize the Win32 state if necessary. */
769 /* Validate the new desktop. */
770 Status
= ValidateDesktopHandle(hDesktop
,
774 if (!NT_SUCCESS(Status
))
776 DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop
);
780 /* Check for setting the same desktop as before. */
781 if (DesktopObject
== PsGetWin32Thread()->Desktop
)
783 ObDereferenceObject(DesktopObject
);
787 /* FIXME: Should check here to see if the thread has any windows. */
789 ObDereferenceObject(PsGetWin32Thread()->Desktop
);
790 PsGetWin32Thread()->Desktop
= DesktopObject
;
797 * Sets the current input (interactive) desktop
799 * hDesktop = Handle to desktop
804 NtUserSwitchDesktop(HDESK hDesktop
)
806 PDESKTOP_OBJECT DesktopObject
;
809 DPRINT("About to switch desktop (0x%X)\n", hDesktop
);
811 Status
= ValidateDesktopHandle(hDesktop
,
815 if (!NT_SUCCESS(Status
))
817 DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop
);
821 /* FIXME: Fail if the desktop belong to an invisible window station */
822 /* FIXME: Fail if the process is associated with a secured
823 desktop such as Winlogon or Screen-Saver */
824 /* FIXME: Connect to input device */
826 /* Set the active desktop in the desktop's window station. */
827 DesktopObject
->WindowStation
->ActiveDesktop
= DesktopObject
;
829 /* Set the global state. */
830 InputDesktopHandle
= hDesktop
;
831 InputDesktop
= DesktopObject
;
832 InputWindowStation
= DesktopObject
->WindowStation
;
834 ObDereferenceObject(DesktopObject
);
840 W32kDesktopWindowProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)