branch update for HEAD-2003050101
[reactos.git] / subsys / win32k / ntuser / winsta.c
1 /* $Id$
2  *
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)
8  * REVISION HISTORY:
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
16  */
17
18 /* INCLUDES ******************************************************************/
19
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>
28
29 #define NDEBUG
30 #include <debug.h>
31
32 /* GLOBALS *******************************************************************/
33
34 #define WINSTA_ROOT_NAME L"\\Windows\\WindowStations"
35
36 LRESULT CALLBACK
37 W32kDesktopWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
38
39 STATIC PWNDCLASS_OBJECT DesktopWindowClass;
40
41 /* Currently active desktop */
42 STATIC HDESK InputDesktopHandle = NULL; 
43 STATIC PDESKTOP_OBJECT InputDesktop = NULL;
44 STATIC PWINSTATION_OBJECT InputWindowStation = NULL;
45
46 static HDC ScreenDeviceContext = NULL;
47
48 /* FUNCTIONS *****************************************************************/
49
50 PDESKTOP_OBJECT
51 W32kGetActiveDesktop(VOID)
52 {
53   return(InputDesktop);
54 }
55
56 NTSTATUS
57 InitWindowStationImpl(VOID)
58 {
59   OBJECT_ATTRIBUTES ObjectAttributes;
60   HANDLE WindowStationsDirectory;
61   UNICODE_STRING UnicodeString;
62   NTSTATUS Status;
63   WNDCLASSEX wcx;
64
65   /*
66    * Create the '\Windows\WindowStations' directory
67    */
68   RtlInitUnicodeStringFromLiteral(&UnicodeString,
69                        WINSTA_ROOT_NAME);
70
71   InitializeObjectAttributes(&ObjectAttributes,
72                              &UnicodeString,
73                              0,
74                              NULL,
75                              NULL);
76   
77   Status = ZwCreateDirectoryObject(&WindowStationsDirectory,
78                                    0,
79                                    &ObjectAttributes);
80   if (!NT_SUCCESS(Status))
81     {
82       DPRINT("Could not create \\Windows\\WindowStations directory "
83              "(Status 0x%X)\n", Status);
84       return Status;
85     }
86
87   /* 
88    * Create the desktop window class
89    */
90   wcx.style = 0;
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);
98
99   return(STATUS_SUCCESS);
100 }
101
102 NTSTATUS
103 CleanupWindowStationImpl(VOID)
104 {
105   return STATUS_SUCCESS;
106 }
107
108
109 NTSTATUS
110 ValidateWindowStationHandle(HWINSTA WindowStation,
111                             KPROCESSOR_MODE AccessMode,
112                             ACCESS_MASK DesiredAccess,
113                             PWINSTATION_OBJECT *Object)
114 {
115   NTSTATUS Status;
116   
117   Status = ObReferenceObjectByHandle(WindowStation,
118                                      DesiredAccess,
119                                      ExWindowStationObjectType,
120                                      AccessMode,
121                                      (PVOID*)Object,
122                                      NULL);
123   if (!NT_SUCCESS(Status)) 
124     {
125       SetLastNtError(Status);
126     }
127   
128   return Status;
129 }
130
131 NTSTATUS
132 ValidateDesktopHandle(HDESK Desktop,
133                       KPROCESSOR_MODE AccessMode,
134                       ACCESS_MASK DesiredAccess,
135                       PDESKTOP_OBJECT *Object)
136 {
137   NTSTATUS Status;
138
139   Status = ObReferenceObjectByHandle(Desktop,
140                                      DesiredAccess,
141                                      ExDesktopObjectType,
142                                      AccessMode,
143                                      (PVOID*)Object,
144                                      NULL);
145   if (!NT_SUCCESS(Status)) 
146     {
147       SetLastNtError(Status);
148     }
149   
150   return Status;
151 }
152
153 /*
154  * FUNCTION:
155  *   Closes a window station handle
156  * ARGUMENTS:
157  *   hWinSta = Handle to the window station 
158  * RETURNS:
159  *   Status
160  * NOTES:
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
165  */
166 BOOL
167 STDCALL
168 NtUserCloseWindowStation(
169   HWINSTA hWinSta)
170 {
171   PWINSTATION_OBJECT Object;
172   NTSTATUS Status;
173
174   DPRINT("About to close window station handle (0x%X)\n", hWinSta);
175
176   Status = ValidateWindowStationHandle(
177     hWinSta,
178     KernelMode,
179     0,
180     &Object);
181   if (!NT_SUCCESS(Status)) {
182     DPRINT("Validation of window station handle (0x%X) failed\n", hWinSta);
183     return FALSE;
184   }
185
186   ObDereferenceObject(Object);
187
188   DPRINT("Closing window station handle (0x%X)\n", hWinSta);
189
190   Status = ZwClose(hWinSta);
191   if (!NT_SUCCESS(Status)) {
192     SetLastNtError(Status);
193     return FALSE;
194   } else {
195     return TRUE;
196   }
197 }
198
199 /*
200  * FUNCTION:
201  *   Creates a new window station
202  * ARGUMENTS:
203  *   lpszWindowStationName = Name of the new window station
204  *   dwDesiredAccess       = Requested type of access
205  *   lpSecurity            = Security descriptor
206  *   Unknown3              = Unused
207  *   Unknown4              = Unused
208  *   Unknown5              = Unused
209  * RETURNS:
210  *   Handle to the new window station that can be closed with
211  *   NtUserCloseWindowStation()
212  *   Zero on failure
213  */
214 HWINSTA STDCALL
215 NtUserCreateWindowStation(PUNICODE_STRING lpszWindowStationName,
216                           ACCESS_MASK dwDesiredAccess,
217                           LPSECURITY_ATTRIBUTES lpSecurity,
218                           DWORD Unknown3,
219                           DWORD Unknown4,
220                           DWORD Unknown5)
221 {
222   OBJECT_ATTRIBUTES ObjectAttributes;
223   UNICODE_STRING WindowStationName;
224   PWINSTATION_OBJECT WinStaObject;
225   WCHAR NameBuffer[MAX_PATH];
226   NTSTATUS Status;
227   HWINSTA WinSta;
228
229   wcscpy(NameBuffer, WINSTA_ROOT_NAME);
230   wcscat(NameBuffer, L"\\");
231   wcscat(NameBuffer, lpszWindowStationName->Buffer);
232   RtlInitUnicodeString(&WindowStationName, NameBuffer);
233
234   DPRINT("Trying to open window station (%wZ)\n", &WindowStationName);
235
236   /* Initialize ObjectAttributes for the window station object */
237   InitializeObjectAttributes(&ObjectAttributes,
238                              &WindowStationName,
239                              0,
240                              NULL,
241                              NULL);
242   
243   Status = ObOpenObjectByName(&ObjectAttributes,
244                               ExWindowStationObjectType,
245                               NULL,
246                               UserMode,
247                               dwDesiredAccess,
248                               NULL,
249                               &WinSta);
250   if (NT_SUCCESS(Status))
251     {
252       DPRINT("Successfully opened window station (%wZ)\n", WindowStationName);
253       return((HWINSTA)WinSta);
254     }
255   
256   DPRINT("Creating window station (%wZ)\n", &WindowStationName);
257
258   Status = ObCreateObject(&WinSta,
259                           STANDARD_RIGHTS_REQUIRED,
260                           &ObjectAttributes,
261                           ExWindowStationObjectType,
262                           (PVOID*)&WinStaObject);
263   if (!NT_SUCCESS(Status))
264     {
265       DPRINT("Failed creating window station (%wZ)\n", &WindowStationName);
266       SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
267       return (HWINSTA)0;
268     }
269
270   WinStaObject->HandleTable = ObmCreateHandleTable();
271   if (!WinStaObject->HandleTable)
272     {
273       DPRINT("Failed creating handle table\n");
274       ObDereferenceObject(WinStaObject);
275       SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
276       return((HWINSTA)0);
277     }
278   
279   DPRINT("Window station successfully created (%wZ)\n", &WindowStationName);
280   
281   return((HWINSTA)WinSta);
282 }
283
284 BOOL
285 STDCALL
286 NtUserGetObjectInformation(
287   HANDLE hObject,
288   DWORD nIndex,
289   PVOID pvInformation,
290   DWORD nLength,
291   PDWORD nLengthNeeded)
292 {
293   return FALSE;
294 }
295
296 /*
297  * FUNCTION:
298  *   Returns a handle to the current process window station
299  * ARGUMENTS:
300  *   None
301  * RETURNS:
302  *   Handle to the window station assigned to the current process
303  *   Zero on failure
304  * NOTES:
305  *   The handle need not be closed by the caller
306  */
307 HWINSTA
308 STDCALL
309 NtUserGetProcessWindowStation(VOID)
310 {
311   return PROCESS_WINDOW_STATION();
312 }
313
314 BOOL
315 STDCALL
316 NtUserLockWindowStation(
317   HWINSTA hWindowStation)
318 {
319   UNIMPLEMENTED
320
321   return 0;
322 }
323
324 /*
325  * FUNCTION:
326  *   Opens an existing window station
327  * ARGUMENTS:
328  *   lpszWindowStationName = Name of the existing window station
329  *   dwDesiredAccess       = Requested type of access
330  * RETURNS:
331  *   Handle to the window station
332  *   Zero on failure
333  * NOTES:
334  *   The returned handle can be closed with NtUserCloseWindowStation()
335  */
336 HWINSTA
337 STDCALL
338 NtUserOpenWindowStation(
339   PUNICODE_STRING lpszWindowStationName,
340   ACCESS_MASK dwDesiredAccess)
341 {
342   OBJECT_ATTRIBUTES ObjectAttributes;
343   UNICODE_STRING WindowStationName;
344   PWINSTATION_OBJECT WinStaObject;
345   WCHAR NameBuffer[MAX_PATH];
346   NTSTATUS Status;
347   HWINSTA WinSta;
348
349   wcscpy(NameBuffer, WINSTA_ROOT_NAME);
350   wcscat(NameBuffer, L"\\");
351   wcscat(NameBuffer, lpszWindowStationName->Buffer);
352   RtlInitUnicodeString(&WindowStationName, NameBuffer);
353
354   DPRINT("Trying to open window station (%wZ)\n", &WindowStationName);
355
356   /* Initialize ObjectAttributes for the window station object */
357   InitializeObjectAttributes(
358     &ObjectAttributes,
359     &WindowStationName,
360     0,
361     NULL,
362     NULL);
363
364   Status = ObOpenObjectByName(
365     &ObjectAttributes,
366     ExDesktopObjectType,
367     NULL,
368     UserMode,
369     dwDesiredAccess,
370     NULL,
371     &WinSta);
372   if (NT_SUCCESS(Status))
373   {
374     DPRINT("Successfully opened window station (%wZ)\n", &WindowStationName);
375     return (HWINSTA)WinSta;
376   }
377
378   SetLastNtError(Status);
379   return (HWINSTA)0;
380 }
381
382 BOOL
383 STDCALL
384 NtUserSetObjectInformation(
385   HANDLE hObject,
386   DWORD nIndex,
387   PVOID pvInformation,
388   DWORD nLength)
389 {
390   /* FIXME: ZwQueryObject */
391   /* FIXME: ZwSetInformationObject */
392   SetLastNtError(STATUS_UNSUCCESSFUL);
393   return FALSE;
394 }
395
396 /*
397  * FUNCTION:
398  *   Assigns a window station to the current process
399  * ARGUMENTS:
400  *   hWinSta = Handle to the window station
401  * RETURNS:
402  *   Status
403  */
404 BOOL STDCALL
405 NtUserSetProcessWindowStation(HWINSTA hWindowStation)
406 {
407   PWINSTATION_OBJECT Object;
408   NTSTATUS Status;
409
410   DPRINT("About to set process window station with handle (0x%X)\n", 
411          hWindowStation);
412
413   Status = ValidateWindowStationHandle(hWindowStation,
414                                        KernelMode,
415                                        0,
416                                        &Object);
417   if (!NT_SUCCESS(Status)) 
418     {
419       DPRINT("Validation of window station handle (0x%X) failed\n", 
420              hWindowStation);
421       return FALSE;
422     }
423   
424   ObDereferenceObject(Object);
425
426   SET_PROCESS_WINDOW_STATION(hWindowStation);
427   DPRINT("IoGetCurrentProcess()->Win32WindowStation 0x%X\n",
428          IoGetCurrentProcess()->Win32WindowStation);
429
430   return TRUE;
431 }
432
433 DWORD
434 STDCALL
435 NtUserSetWindowStationUser(
436   DWORD Unknown0,
437   DWORD Unknown1,
438   DWORD Unknown2,
439   DWORD Unknown3)
440 {
441   UNIMPLEMENTED
442
443   return 0;
444 }
445
446 BOOL
447 STDCALL
448 NtUserUnlockWindowStation(
449   HWINSTA hWindowStation)
450 {
451   UNIMPLEMENTED
452
453   return FALSE;
454 }
455
456
457 /*
458  * FUNCTION:
459  *   Closes a desktop handle
460  * ARGUMENTS:
461  *   hDesktop = Handle to the desktop
462  * RETURNS:
463  *   Status
464  * NOTES:
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
470  */
471 BOOL
472 STDCALL
473 NtUserCloseDesktop(
474   HDESK hDesktop)
475 {
476   PDESKTOP_OBJECT Object;
477   NTSTATUS Status;
478
479   DPRINT("About to close desktop handle (0x%X)\n", hDesktop);
480
481   Status = ValidateDesktopHandle(
482     hDesktop,
483     KernelMode,
484     0,
485     &Object);
486   if (!NT_SUCCESS(Status)) {
487     DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop);
488     return FALSE;
489   }
490
491   ObDereferenceObject(Object);
492
493   DPRINT("Closing desktop handle (0x%X)\n", hDesktop);
494
495   Status = ZwClose(hDesktop);
496   if (!NT_SUCCESS(Status)) {
497     SetLastNtError(Status);
498     return FALSE;
499   } else {
500     return TRUE;
501   }
502 }
503
504 /*
505  * FUNCTION:
506  *   Creates a new desktop
507  * ARGUMENTS:
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
513  * RETURNS:
514  *   Handle to the new desktop that can be closed with NtUserCloseDesktop()
515  *   Zero on failure
516  */
517 HDESK STDCALL
518 NtUserCreateDesktop(PUNICODE_STRING lpszDesktopName,
519                     DWORD dwFlags,
520                     ACCESS_MASK dwDesiredAccess,
521                     LPSECURITY_ATTRIBUTES lpSecurity,
522                     HWINSTA hWindowStation)
523 {
524   OBJECT_ATTRIBUTES ObjectAttributes;
525   PWINSTATION_OBJECT WinStaObject;
526   PDESKTOP_OBJECT DesktopObject;
527   UNICODE_STRING DesktopName;
528   WCHAR NameBuffer[MAX_PATH];
529   NTSTATUS Status;
530   HDESK Desktop;
531
532   Status = ValidateWindowStationHandle(hWindowStation,
533                                        KernelMode,
534                                        0,
535                                        &WinStaObject);
536   if (!NT_SUCCESS(Status))
537     {
538       DPRINT("Failed validation of window station handle (0x%X)\n", 
539              hWindowStation);
540       return((HDESK)0);
541     }
542   
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);
549
550   ObDereferenceObject(WinStaObject);
551
552   DPRINT("Trying to open desktop (%wZ)\n", &DesktopName);
553
554   /* Initialize ObjectAttributes for the desktop object */
555   InitializeObjectAttributes(&ObjectAttributes,
556                              &DesktopName,
557                              0,
558                              NULL,
559                              NULL);
560   Status = ObOpenObjectByName(&ObjectAttributes,
561                               ExDesktopObjectType,
562                               NULL,
563                               UserMode,
564                               dwDesiredAccess,
565                               NULL,
566                               &Desktop);
567   if (NT_SUCCESS(Status))
568     {
569       DPRINT("Successfully opened desktop (%wZ)\n", &DesktopName);
570       return((HDESK)Desktop);
571     }
572
573   DPRINT("Status for open operation (0x%X)\n", Status);
574
575   Status = ObCreateObject(&Desktop,
576                           STANDARD_RIGHTS_REQUIRED,
577                           &ObjectAttributes,
578                           ExDesktopObjectType,
579                           (PVOID*)&DesktopObject);
580   if (!NT_SUCCESS(Status))
581     {
582       DPRINT("Failed creating desktop (%wZ)\n", &DesktopName);
583       SetLastNtError(STATUS_UNSUCCESSFUL);
584       return((HDESK)0);
585     }
586   
587   /* Initialize some local (to win32k) desktop state. */
588   DesktopObject->ActiveMessageQueue = NULL;  
589   InitializeListHead(&DesktopObject->WindowListHead);
590   DesktopObject->DesktopWindow = 
591     W32kCreateDesktopWindow(DesktopObject->WindowStation,
592                             DesktopWindowClass,
593                             640, 480);
594
595   return((HDESK)Desktop);
596 }
597
598 HDESK STDCALL
599 NtUserGetThreadDesktop(DWORD dwThreadId,
600                        DWORD Unknown1)
601 {
602   UNIMPLEMENTED;
603   return((HDESK)0);
604 }
605
606 /*
607  * FUNCTION:
608  *   Opens an existing desktop
609  * ARGUMENTS:
610  *   lpszDesktopName = Name of the existing desktop
611  *   dwFlags         = Interaction flags
612  *   dwDesiredAccess = Requested type of access
613  * RETURNS:
614  *   Handle to the desktop
615  *   Zero on failure
616  * NOTES:
617  *   The returned handle can be closed with NtUserCloseDesktop()
618  */
619 HDESK
620 STDCALL
621 NtUserOpenDesktop(
622   PUNICODE_STRING lpszDesktopName,
623   DWORD dwFlags,
624   ACCESS_MASK dwDesiredAccess)
625 {
626   OBJECT_ATTRIBUTES ObjectAttributes;
627   PWINSTATION_OBJECT WinStaObject;
628   UNICODE_STRING DesktopName;
629   WCHAR NameBuffer[MAX_PATH];
630   NTSTATUS Status;
631   HDESK Desktop;
632
633   /* Validate the window station handle and
634      compose the fully qualified desktop name */
635
636   Status = ValidateWindowStationHandle(
637     PROCESS_WINDOW_STATION(),
638     KernelMode,
639     0,
640     &WinStaObject);
641   if (!NT_SUCCESS(Status))
642   {
643     DPRINT("Failed validation of window station handle (0x%X)\n",
644       PROCESS_WINDOW_STATION());
645     return (HDESK)0;
646   }
647
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);
654
655   ObDereferenceObject(WinStaObject);
656
657
658   DPRINT("Trying to open desktop station (%wZ)\n", &DesktopName);
659
660   /* Initialize ObjectAttributes for the desktop object */
661   InitializeObjectAttributes(
662     &ObjectAttributes,
663     &DesktopName,
664     0,
665     NULL,
666     NULL);
667
668   Status = ObOpenObjectByName(
669     &ObjectAttributes,
670     ExDesktopObjectType,
671     NULL,
672     UserMode,
673     dwDesiredAccess,
674     NULL,
675     &Desktop);
676   if (NT_SUCCESS(Status))
677   {
678     DPRINT("Successfully opened desktop (%wZ)\n", &DesktopName);
679     return (HDESK)Desktop;
680   }
681
682   SetLastNtError(Status);
683   return (HDESK)0;
684 }
685
686 /*
687  * FUNCTION:
688  *   Opens the input (interactive) desktop
689  * ARGUMENTS:
690  *   dwFlags         = Interaction flags
691  *   fInherit        = Inheritance option
692  *   dwDesiredAccess = Requested type of access
693  * RETURNS:
694  *   Handle to the input desktop
695  *   Zero on failure
696  * NOTES:
697  *   The returned handle can be closed with NtUserCloseDesktop()
698  */
699 HDESK
700 STDCALL
701 NtUserOpenInputDesktop(
702   DWORD dwFlags,
703   BOOL fInherit,
704   ACCESS_MASK dwDesiredAccess)
705 {
706   PDESKTOP_OBJECT Object;
707   NTSTATUS Status;
708   HDESK Desktop;
709
710   DPRINT("About to open input desktop\n");
711
712   /* Get a pointer to the desktop object */
713
714   Status = ValidateDesktopHandle(
715     InputDesktop,
716     KernelMode,
717     0,
718     &Object);
719   if (!NT_SUCCESS(Status)) {
720     DPRINT("Validation of input desktop handle (0x%X) failed\n", InputDesktop);
721     return (HDESK)0;
722   }
723
724   /* Create a new handle to the object */
725
726   Status = ObOpenObjectByPointer(
727     Object,
728     0,
729     NULL,
730     dwDesiredAccess,
731     ExDesktopObjectType,
732     UserMode,
733     &Desktop);
734
735   ObDereferenceObject(Object);
736
737   if (NT_SUCCESS(Status))
738   {
739     DPRINT("Successfully opened input desktop\n");
740     return (HDESK)Desktop;
741   }
742
743   SetLastNtError(Status);
744   return (HDESK)0;
745 }
746
747 BOOL STDCALL
748 NtUserPaintDesktop(HDC hDC)
749 {
750   UNIMPLEMENTED
751
752   return FALSE;
753 }
754
755 DWORD STDCALL
756 NtUserResolveDesktopForWOW(DWORD Unknown0)
757 {
758   UNIMPLEMENTED
759   return 0;
760 }
761
762 BOOL STDCALL
763 NtUserSetThreadDesktop(HDESK hDesktop)
764 {  
765   PDESKTOP_OBJECT DesktopObject;
766   NTSTATUS Status;
767
768   /* Initialize the Win32 state if necessary. */
769   W32kGuiCheck();
770
771   /* Validate the new desktop. */
772   Status = ValidateDesktopHandle(hDesktop,
773                                  KernelMode,
774                                  0,
775                                  &DesktopObject);
776   if (!NT_SUCCESS(Status)) 
777     {
778       DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop);
779       return(FALSE);
780     }
781
782   /* Check for setting the same desktop as before. */
783   if (DesktopObject == PsGetWin32Thread()->Desktop)
784     {
785       ObDereferenceObject(DesktopObject);
786       return(TRUE);
787     }
788
789   /* FIXME: Should check here to see if the thread has any windows. */
790
791   ObDereferenceObject(PsGetWin32Thread()->Desktop);
792   PsGetWin32Thread()->Desktop = DesktopObject;
793
794   return(TRUE);
795 }
796
797 /*
798  * FUNCTION:
799  *   Sets the current input (interactive) desktop
800  * ARGUMENTS:
801  *   hDesktop = Handle to desktop
802  * RETURNS:
803  *   Status
804  */
805 BOOL STDCALL
806 NtUserSwitchDesktop(HDESK hDesktop)
807 {
808   PDESKTOP_OBJECT DesktopObject;
809   NTSTATUS Status;
810
811   DPRINT("About to switch desktop (0x%X)\n", hDesktop);
812
813   Status = ValidateDesktopHandle(hDesktop,
814                                  KernelMode,
815                                  0,
816                                  &DesktopObject);
817   if (!NT_SUCCESS(Status)) 
818     {
819       DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop);
820       return(FALSE);
821     }
822
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 */
827
828   /* Set the active desktop in the desktop's window station. */
829   DesktopObject->WindowStation->ActiveDesktop = DesktopObject;
830
831   /* Set the global state. */
832   InputDesktopHandle = hDesktop;
833   InputDesktop = DesktopObject;
834   InputWindowStation = DesktopObject->WindowStation;
835
836   ObDereferenceObject(DesktopObject);
837
838   return(TRUE);
839 }
840
841 VOID
842 W32kInitializeDesktopGraphics(VOID)
843 {
844   ScreenDeviceContext = W32kCreateDC(L"DISPLAY", NULL, NULL, NULL);
845   GDIOBJ_MarkObjectGlobal(ScreenDeviceContext);
846   EnableMouse(ScreenDeviceContext);
847   NtUserAcquireOrReleaseInputOwnership(FALSE);
848 }
849
850 VOID
851 W32kEndDesktopGraphics(VOID)
852 {
853   NtUserAcquireOrReleaseInputOwnership(TRUE);
854   EnableMouse(FALSE);
855   if (NULL != ScreenDeviceContext)
856     {
857       W32kDeleteDC(ScreenDeviceContext);
858       ScreenDeviceContext = NULL;
859     }
860 }
861
862 HDC
863 W32kGetScreenDC(VOID)
864 {
865   return(ScreenDeviceContext);
866 }
867
868 LRESULT CALLBACK
869 W32kDesktopWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
870 {
871   switch (msg)
872     {
873     case WM_CREATE:
874       return(0);
875
876     case WM_NCCREATE:
877       return(1);
878
879     default:
880       return(0);
881     }
882 }
883
884 /* EOF */