ReactOS 0.4.17-dev-769-g1500a35
desktop.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
4 * PURPOSE: Desktops
5 * FILE: subsystems/win32/win32k/ntuser/desktop.c
6 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 */
8
9/* INCLUDES ******************************************************************/
10
11#include <win32k.h>
13
14#include <reactos/buildno.h>
15
16static NTSTATUS
18
19static NTSTATUS
21
22static NTSTATUS
24
25static VOID
27
28/* GLOBALS *******************************************************************/
29
30/* These can be changed via registry settings.
31 * Default values (interactive desktop / non-interactive desktop):
32 * Windows 2003 x86: 3 MB / 512 KB (Disconnect: 64 KB, Winlogon: 128 KB)
33 * Windows 7 x86: 12 MB / 512 KB
34 * Windows 7 x64: 20 MB / 768 KB
35 * Windows 10 x64: 20 MB / 4 MB
36 * See:
37 * - https://dbmentors.blogspot.com/2011/09/desktop-heap-overview.html
38 * - https://www.ibm.com/support/pages/using-microsoft-desktop-heap-monitor-dheapmon-determine-desktop-heap-space-and-troubleshoot-filenet-p8-and-image-services-issues
39 * - https://www.betaarchive.com/wiki/index.php?title=Microsoft_KB_Archive/184802
40 * - https://kb.firedaemon.com/support/solutions/articles/4000086192-windows-service-quota-limits-and-desktop-heap-exhaustion
41 * - https://learn.microsoft.com/en-us/troubleshoot/windows-server/performance/desktop-heap-limitation-out-of-memory
42 */
43#ifdef _WIN64
44DWORD gdwDesktopSectionSize = 20 * 1024; // 20 MB (Windows 7 style)
45#else
46DWORD gdwDesktopSectionSize = 3 * 1024; // 3 MB (Windows 2003 style)
47#endif
50
58
59/* OBJECT CALLBACKS **********************************************************/
60
68 IN OUT PUNICODE_STRING CompleteName,
73{
77 PLIST_ENTRY NextEntry, ListHead;
78 PWINSTATION_OBJECT WinStaObject = (PWINSTATION_OBJECT)ParseObject;
79 UNICODE_STRING DesktopName;
80 PBOOLEAN pContext = (PBOOLEAN) Context;
81
82 if (pContext)
83 *pContext = FALSE;
84
85 /* Set the list pointers and loop the window station */
86 ListHead = &WinStaObject->DesktopListHead;
87 NextEntry = ListHead->Flink;
88 while (NextEntry != ListHead)
89 {
90 /* Get the current desktop */
91 Desktop = CONTAINING_RECORD(NextEntry, DESKTOP, ListEntry);
92
93 /* Get the desktop name */
94 ASSERT(Desktop->pDeskInfo != NULL);
95 RtlInitUnicodeString(&DesktopName, Desktop->pDeskInfo->szDesktopName);
96
97 /* Compare the name */
99 &DesktopName,
101 {
102 /* We found a match. Did this come from a create? */
103 if (Context)
104 {
105 /* Unless OPEN_IF was given, fail with an error */
106 if (!(Attributes & OBJ_OPENIF))
107 {
108 /* Name collision */
110 }
111 else
112 {
113 /* Otherwise, return with a warning only */
115 }
116 }
117 else
118 {
119 /* This was a real open, so this is OK */
121 }
122
123 /* Reference the desktop and return it */
125 *Object = Desktop;
126 return Status;
127 }
128
129 /* Go to the next desktop */
130 NextEntry = NextEntry->Flink;
131 }
132
133 /* If we got here but this isn't a create, just fail */
135
136 /* Create the desktop object */
142 NULL,
143 sizeof(DESKTOP),
144 0,
145 0,
146 (PVOID*)&Desktop);
147 if (!NT_SUCCESS(Status))
148 return Status;
149 RtlZeroMemory(Desktop, sizeof(DESKTOP));
150
151 /* Assign the session ID to the desktop */
152 Desktop->dwSessionId = PsGetCurrentProcessSessionId(); // gSessionId
153 ASSERT(Desktop->dwSessionId == WinStaObject->dwSessionId);
154
155 /* Assign security to the desktop we have created */
157 if (!NT_SUCCESS(Status))
158 {
160 return Status;
161 }
162
163 /* Initialize the desktop */
165 if (!NT_SUCCESS(Status))
166 {
168 return Status;
169 }
170
171 /* Set the desktop object and return success */
172 *Object = Desktop;
173 *pContext = TRUE;
174 return STATUS_SUCCESS;
175}
176
178NTAPI
181{
183 PDESKTOP pdesk = (PDESKTOP)DeleteParameters->Object;
184
185 TRACE("Deleting desktop object 0x%p\n", pdesk);
186
187 if (pdesk->pDeskInfo &&
188 pdesk->pDeskInfo->spwnd)
189 {
190 ASSERT(pdesk->pDeskInfo->spwnd->spwndChild == NULL);
192 }
193
194 if (pdesk->spwndMessage)
196
197 /* Remove the desktop from the window station's list of associated desktops */
198 RemoveEntryList(&pdesk->ListEntry);
199
200 /* Free the heap */
201 IntFreeDesktopHeap(pdesk);
202
204
205 return STATUS_SUCCESS;
206}
207
209NTAPI
212{
215
216 if (pti == NULL)
217 {
218 /* This happens when we leak desktop handles */
219 return STATUS_SUCCESS;
220 }
221
222 /* Do not allow the current desktop or the initial desktop to be closed */
223 if (OkToCloseParameters->Handle == pti->ppi->hdeskStartup ||
224 OkToCloseParameters->Handle == pti->hdesk)
225 {
227 }
228
229 return STATUS_SUCCESS;
230}
231
233NTAPI
236{
237 NTSTATUS Ret;
239 PPROCESSINFO ppi = PsGetProcessWin32Process(OpenParameters->Process);
240 if (ppi == NULL)
241 return STATUS_SUCCESS;
242
244 Ret = IntMapDesktopView((PDESKTOP)OpenParameters->Object);
245 UserLeave();
246 return Ret;
247}
248
250NTAPI
253{
254 NTSTATUS Ret;
256 PPROCESSINFO ppi = PsGetProcessWin32Process(CloseParameters->Process);
257 if (ppi == NULL)
258 {
259 /* This happens when the process leaks desktop handles.
260 * At this point the PPROCESSINFO is already destroyed */
261 return STATUS_SUCCESS;
262 }
263
265 Ret = IntUnmapDesktopView((PDESKTOP)CloseParameters->Object);
266 UserLeave();
267 return Ret;
268}
269
270
271/* PRIVATE FUNCTIONS **********************************************************/
272
273CODE_SEG("INIT")
275NTAPI
277{
278 GENERIC_MAPPING IntDesktopMapping = { DESKTOP_READ,
282
283 /* Set Desktop Object Attributes */
285 ExDesktopObjectType->TypeInfo.GenericMapping = IntDesktopMapping;
287
288 /* Allocate memory for the event structure */
290 sizeof(KEVENT),
293 {
294 ERR("Failed to allocate event!\n");
295 return STATUS_NO_MEMORY;
296 }
297
298 /* Initialize the kernel event */
301 FALSE);
302
303 return STATUS_SUCCESS;
304}
305
306static NTSTATUS
309 IN BOOLEAN InSafeMode,
310 IN BOOLEAN AppendNtSystemRoot)
311{
313
314 RTL_OSVERSIONINFOEXW VerInfo;
315 UNICODE_STRING BuildLabString;
316 UNICODE_STRING CSDVersionString;
317 RTL_QUERY_REGISTRY_TABLE VersionConfigurationTable[] =
318 {
319 {
320 NULL,
322 L"BuildLab",
323 &BuildLabString,
324 REG_NONE, NULL, 0
325 },
326 {
327 NULL,
329 L"CSDVersion",
330 &CSDVersionString,
331 REG_NONE, NULL, 0
332 },
333
334 {0}
335 };
336
337 WCHAR BuildLabBuffer[256];
338 WCHAR VersionBuffer[256];
339 PWCHAR EndBuffer;
340
341 VerInfo.dwOSVersionInfoSize = sizeof(VerInfo);
342
343 /*
344 * This call is uniquely used to retrieve the current CSD numbers.
345 * All the rest (major, minor, ...) is either retrieved from the
346 * SharedUserData structure, or from the registry.
347 */
349
350 /*
351 * - Retrieve the BuildLab string from the registry (set by the kernel).
352 * - In kernel-mode, szCSDVersion is not initialized. Initialize it
353 * and query its value from the registry.
354 */
355 RtlZeroMemory(BuildLabBuffer, sizeof(BuildLabBuffer));
356 RtlInitEmptyUnicodeString(&BuildLabString,
357 BuildLabBuffer,
358 sizeof(BuildLabBuffer));
359 RtlZeroMemory(VerInfo.szCSDVersion, sizeof(VerInfo.szCSDVersion));
360 RtlInitEmptyUnicodeString(&CSDVersionString,
361 VerInfo.szCSDVersion,
362 sizeof(VerInfo.szCSDVersion));
364 L"",
365 VersionConfigurationTable,
366 NULL,
367 NULL);
368 if (!NT_SUCCESS(Status))
369 {
370 /* Indicate nothing is there */
371 BuildLabString.Length = 0;
372 CSDVersionString.Length = 0;
373 }
374 /* NULL-terminate the strings */
375 BuildLabString.Buffer[BuildLabString.Length / sizeof(WCHAR)] = UNICODE_NULL;
376 CSDVersionString.Buffer[CSDVersionString.Length / sizeof(WCHAR)] = UNICODE_NULL;
377
378 EndBuffer = VersionBuffer;
379 if ( /* VerInfo.wServicePackMajor != 0 && */ CSDVersionString.Length)
380 {
381 /* Print the version string */
382 Status = RtlStringCbPrintfExW(VersionBuffer,
383 sizeof(VersionBuffer),
384 &EndBuffer,
385 NULL,
386 0,
387 L": %wZ",
388 &CSDVersionString);
389 if (!NT_SUCCESS(Status))
390 {
391 /* No version, NULL-terminate the string */
392 *EndBuffer = UNICODE_NULL;
393 }
394 }
395 else
396 {
397 /* No version, NULL-terminate the string */
398 *EndBuffer = UNICODE_NULL;
399 }
400
401 if (InSafeMode)
402 {
403 /* String for Safe Mode */
404 Status = RtlStringCchPrintfW(pwszzVersion,
405 cchDest,
406 L"ReactOS Version %S %wZ (NT %u.%u Build %u%s)\n",
407 KERNEL_VERSION_STR,
408 &BuildLabString,
409 SharedUserData->NtMajorVersion,
410 SharedUserData->NtMinorVersion,
411 (VerInfo.dwBuildNumber & 0xFFFF),
412 VersionBuffer);
413
414 if (AppendNtSystemRoot && NT_SUCCESS(Status))
415 {
416 Status = RtlStringCbPrintfW(VersionBuffer,
417 sizeof(VersionBuffer),
418 L" - %s\n",
419 SharedUserData->NtSystemRoot);
420 if (NT_SUCCESS(Status))
421 {
422 /* Replace the last newline by a NULL, before concatenating */
423 EndBuffer = wcsrchr(pwszzVersion, L'\n');
424 if (EndBuffer) *EndBuffer = UNICODE_NULL;
425
426 /* The concatenated string has a terminating newline */
427 Status = RtlStringCchCatW(pwszzVersion,
428 cchDest,
429 VersionBuffer);
430 if (!NT_SUCCESS(Status))
431 {
432 /* Concatenation failed, put back the newline */
433 if (EndBuffer) *EndBuffer = L'\n';
434 }
435 }
436
437 /* Override any failures as the NtSystemRoot string is optional */
439 }
440 }
441 else
442 {
443 /* Multi-string for Normal Mode */
444 Status = RtlStringCchPrintfW(pwszzVersion,
445 cchDest,
446 L"ReactOS Version %S\n"
447 L"Build %wZ\n"
448 L"Reporting NT %u.%u (Build %u%s)\n",
449 KERNEL_VERSION_STR,
450 &BuildLabString,
451 SharedUserData->NtMajorVersion,
452 SharedUserData->NtMinorVersion,
453 (VerInfo.dwBuildNumber & 0xFFFF),
454 VersionBuffer);
455
456 if (AppendNtSystemRoot && NT_SUCCESS(Status))
457 {
458 Status = RtlStringCbPrintfW(VersionBuffer,
459 sizeof(VersionBuffer),
460 L"%s\n",
461 SharedUserData->NtSystemRoot);
462 if (NT_SUCCESS(Status))
463 {
464 Status = RtlStringCchCatW(pwszzVersion,
465 cchDest,
466 VersionBuffer);
467 }
468
469 /* Override any failures as the NtSystemRoot string is optional */
471 }
472 }
473
474 if (!NT_SUCCESS(Status))
475 {
476 /* Fall-back string */
477 Status = RtlStringCchPrintfW(pwszzVersion,
478 cchDest,
479 L"ReactOS Version %S %wZ\n",
480 KERNEL_VERSION_STR,
481 &BuildLabString);
482 if (!NT_SUCCESS(Status))
483 {
484 /* General failure, NULL-terminate the string */
485 pwszzVersion[0] = UNICODE_NULL;
486 }
487 }
488
489 /*
490 * Convert the string separators (newlines) into NULLs
491 * and NULL-terminate the multi-string.
492 */
493 while (*pwszzVersion)
494 {
495 EndBuffer = wcschr(pwszzVersion, L'\n');
496 if (!EndBuffer) break;
497 pwszzVersion = EndBuffer;
498
499 *pwszzVersion++ = UNICODE_NULL;
500 }
501 *pwszzVersion = UNICODE_NULL;
502
503 return Status;
504}
505
506
507/*
508 * IntResolveDesktop
509 *
510 * The IntResolveDesktop function attempts to retrieve valid handles to
511 * a desktop and a window station suitable for the specified process.
512 * The specified desktop path string is used only as a hint for the resolution.
513 *
514 * - If the process is already assigned to a window station and a desktop,
515 * handles to these objects are returned directly regardless of the specified
516 * desktop path string. This is what happens when this function is called for
517 * a process that has been already started and connected to the Win32 USER.
518 *
519 * - If the process is being connected to the Win32 USER, or is in a state
520 * where a window station is assigned to it but no desktop yet, the desktop
521 * path string is used as a hint for the resolution.
522 * A specified window station (if any, otherwise "WinSta0" is used as default)
523 * is tested for existence and accessibility. If the checks are OK a handle
524 * to it is returned. Otherwise we either fail (the window station does not
525 * exist) or, in case a default window station was used, we attempt to open
526 * or create a non-interactive Service-0xXXXX-YYYY$ window station. This is
527 * typically what happens when a non-interactive process is started while
528 * the WinSta0 window station was used as the default one.
529 * A specified desktop (if any, otherwise "Default" is used as default)
530 * is then tested for existence on the opened window station.
531 *
532 * - Rules for the choice of the default window station, when none is specified
533 * in the desktop path:
534 *
535 * 1. By default, a SYSTEM process connects to a non-interactive window
536 * station, either the Service-0x0-3e7$ (from the SYSTEM LUID) station,
537 * or one that has been inherited and that is non-interactive.
538 * Only when the interactive window station WinSta0 is specified that
539 * the process can connect to it (e.g. the case of interactive services).
540 *
541 * 2. An interactive process, i.e. a process whose LUID is the same as the
542 * one assigned to WinSta0 by Winlogon on user logon, connects by default
543 * to the WinSta0 window station, unless it has inherited from another
544 * interactive window station (which must be... none other than WinSta0).
545 *
546 * 3. A non-interactive (but not SYSTEM) process connects by default to
547 * a non-interactive Service-0xXXXX-YYYY$ window station (whose name
548 * is derived from the process' LUID), or to another non-interactive
549 * window station that has been inherited.
550 * Otherwise it may be able connect to the interactive WinSta0 only if
551 * it has explicit access rights to it.
552 *
553 * Parameters
554 * Process
555 * The user process object.
556 *
557 * DesktopPath
558 * The desktop path string used as a hint for desktop resolution.
559 *
560 * bInherit
561 * Whether or not the returned handles are inheritable.
562 *
563 * phWinSta
564 * Pointer to a window station handle.
565 *
566 * phDesktop
567 * Pointer to a desktop handle.
568 *
569 * Return Value
570 * Status code.
571 */
572
577 IN PUNICODE_STRING DesktopPath,
578 IN BOOL bInherit,
579 OUT HWINSTA* phWinSta,
580 OUT HDESK* phDesktop)
581{
583 HWINSTA hWinSta = NULL, hWinStaDup = NULL;
584 HDESK hDesktop = NULL, hDesktopDup = NULL;
585 PPROCESSINFO ppi;
587 LUID ProcessLuid;
588 USHORT StrSize;
589 SIZE_T MemSize;
590 PSECURITY_DESCRIPTOR ServiceSD;
593 UNICODE_STRING WinStaName, DesktopName;
594 const UNICODE_STRING WinSta0Name = RTL_CONSTANT_STRING(L"WinSta0");
595 PWINSTATION_OBJECT WinStaObject;
596 HWINSTA hTempWinSta = NULL;
597 BOOLEAN bUseDefaultWinSta = FALSE;
598 BOOLEAN bInteractive = FALSE;
599 BOOLEAN bAccessAllowed = FALSE;
600
602
603 ASSERT(phWinSta);
604 ASSERT(phDesktop);
605 ASSERT(DesktopPath);
606
607 *phWinSta = NULL;
608 *phDesktop = NULL;
609
611 /* ppi is typically NULL for console applications that connect to Win32 USER */
612 if (!ppi) TRACE("IntResolveDesktop: ppi is NULL!\n");
613
614 if (ppi && ppi->hwinsta != NULL && ppi->hdeskStartup != NULL)
615 {
616 /*
617 * If this process is the current one, just return the cached handles.
618 * Otherwise, open the window station and desktop objects.
619 */
621 {
622 hWinSta = ppi->hwinsta;
623 hDesktop = ppi->hdeskStartup;
624 }
625 else
626 {
628 0,
629 NULL,
632 UserMode,
633 (PHANDLE)&hWinSta);
634 if (!NT_SUCCESS(Status))
635 {
636 ERR("IntResolveDesktop: Could not reference window station 0x%p\n", ppi->prpwinsta);
638 return Status;
639 }
640
642 0,
643 NULL,
646 UserMode,
647 (PHANDLE)&hDesktop);
648 if (!NT_SUCCESS(Status))
649 {
650 ERR("IntResolveDesktop: Could not reference desktop 0x%p\n", ppi->rpdeskStartup);
651 ObCloseHandle(hWinSta, UserMode);
653 return Status;
654 }
655 }
656
657 *phWinSta = hWinSta;
658 *phDesktop = hDesktop;
659 return STATUS_SUCCESS;
660 }
661
662 /* We will by default use the default window station and desktop */
663 RtlInitEmptyUnicodeString(&WinStaName, NULL, 0);
664 RtlInitEmptyUnicodeString(&DesktopName, NULL, 0);
665
666 /*
667 * Parse the desktop path string which can be of the form "WinSta\Desktop"
668 * or just "Desktop". In the latter case we use the default window station
669 * on which the process is attached to (or if none, "WinSta0").
670 */
671 if (DesktopPath->Buffer != NULL && DesktopPath->Length > sizeof(WCHAR))
672 {
673 DesktopName = *DesktopPath;
674
675 /* Find the separator */
676 while (DesktopName.Length > 0 && *DesktopName.Buffer &&
677 *DesktopName.Buffer != OBJ_NAME_PATH_SEPARATOR)
678 {
679 DesktopName.Buffer++;
680 DesktopName.Length -= sizeof(WCHAR);
681 DesktopName.MaximumLength -= sizeof(WCHAR);
682 }
683 if (DesktopName.Length > 0)
684 {
685 RtlInitEmptyUnicodeString(&WinStaName, DesktopPath->Buffer,
686 DesktopPath->Length - DesktopName.Length);
687 // (USHORT)((ULONG_PTR)DesktopName.Buffer - (ULONG_PTR)DesktopPath->Buffer);
688 WinStaName.Length = WinStaName.MaximumLength;
689
690 /* Skip the separator */
691 DesktopName.Buffer++;
692 DesktopName.Length -= sizeof(WCHAR);
693 DesktopName.MaximumLength -= sizeof(WCHAR);
694 }
695 else
696 {
697 RtlInitEmptyUnicodeString(&WinStaName, NULL, 0);
698 DesktopName = *DesktopPath;
699 }
700 }
701
702 TRACE("IntResolveDesktop: WinStaName:'%wZ' ; DesktopName:'%wZ'\n", &WinStaName, &DesktopName);
703
704 /* Retrieve the process LUID */
705 Status = GetProcessLuid(NULL, Process, &ProcessLuid);
706 if (!NT_SUCCESS(Status))
707 {
708 ERR("IntResolveDesktop: Failed to retrieve the process LUID, Status 0x%08lx\n", Status);
710 return Status;
711 }
712
713 /*
714 * If this process is not the current one, obtain a temporary handle
715 * to it so that we can perform handles duplication later.
716 */
718 {
721 NULL,
722 0,
725 &hProcess);
726 if (!NT_SUCCESS(Status))
727 {
728 ERR("IntResolveDesktop: Failed to obtain a handle to process 0x%p, Status 0x%08lx\n", Process, Status);
730 return Status;
731 }
733 }
734
735 /*
736 * If no window station has been specified, search the process handle table
737 * for inherited window station handles, otherwise use a default one.
738 */
739 if (WinStaName.Buffer == NULL)
740 {
741 /*
742 * We want to find a suitable default window station.
743 * For applications that can be interactive, i.e. that have allowed
744 * access to the single interactive window station on the system,
745 * the default window station is 'WinSta0'.
746 * For applications that cannot be interactive, i.e. that do not have
747 * access to 'WinSta0' (e.g. non-interactive services), the default
748 * window station is 'Service-0xXXXX-YYYY$' (created if needed).
749 * Precedence will however be taken by any inherited window station
750 * that possesses the required interactivity property.
751 */
752 bUseDefaultWinSta = TRUE;
753
754 /*
755 * Use the default 'WinSta0' window station. Whether we should
756 * use 'Service-0xXXXX-YYYY$' instead will be determined later.
757 */
758 // RtlInitUnicodeString(&WinStaName, L"WinSta0");
759 WinStaName = WinSta0Name;
760
762 NULL,
764 NULL,
765 (PHANDLE)&hWinSta))
766 {
767 TRACE("IntResolveDesktop: Inherited window station is: 0x%p\n", hWinSta);
768 }
769 }
770
771 /*
772 * If no desktop has been specified, search the process handle table
773 * for inherited desktop handles, otherwise use the Default desktop.
774 * Note that the inherited desktop that we may use, may not belong
775 * to the window station we will connect to.
776 */
777 if (DesktopName.Buffer == NULL)
778 {
779 /* Use a default desktop name */
780 RtlInitUnicodeString(&DesktopName, L"Default");
781
783 NULL,
785 NULL,
786 (PHANDLE)&hDesktop))
787 {
788 TRACE("IntResolveDesktop: Inherited desktop is: 0x%p\n", hDesktop);
789 }
790 }
791
792
793 /*
794 * We are going to open either a window station or a desktop.
795 * Even if this operation is done from kernel-mode, we should
796 * "emulate" an opening from user-mode (i.e. using an ObjectAttributes
797 * allocated in user-mode, with AccessMode == UserMode) for the
798 * Object Manager to perform proper access validation to the
799 * window station or desktop.
800 */
801
802 /*
803 * Estimate the maximum size needed for the window station name
804 * and desktop name to be given to ObjectAttributes->ObjectName.
805 */
806 StrSize = 0;
807
808 /* Window station name */
809 MemSize = _scwprintf(L"Service-0x%x-%x$", MAXULONG, MAXULONG) * sizeof(WCHAR);
811 + max(WinStaName.Length, MemSize) + sizeof(UNICODE_NULL);
812 if (MemSize > MAXUSHORT)
813 {
814 ERR("IntResolveDesktop: Window station name length is too long.\n");
816 goto Quit;
817 }
818 StrSize = max(StrSize, (USHORT)MemSize);
819
820 /* Desktop name */
821 MemSize = max(DesktopName.Length + sizeof(UNICODE_NULL), sizeof(L"Default"));
822 StrSize = max(StrSize, (USHORT)MemSize);
823
824 /* Size for the OBJECT_ATTRIBUTES */
825 MemSize = ALIGN_UP(sizeof(OBJECT_ATTRIBUTES), sizeof(PVOID));
826
827 /* Add the string size */
828 MemSize += ALIGN_UP(sizeof(UNICODE_STRING), sizeof(PVOID));
829 MemSize += StrSize;
830
831 /* Allocate the memory in user-mode */
832 Status = ZwAllocateVirtualMemory(ZwCurrentProcess(),
834 0,
835 &MemSize,
838 if (!NT_SUCCESS(Status))
839 {
840 ERR("ZwAllocateVirtualMemory() failed, Status 0x%08lx\n", Status);
841 goto Quit;
842 }
843
845 ALIGN_UP(sizeof(OBJECT_ATTRIBUTES), sizeof(PVOID)));
846
847 RtlInitEmptyUnicodeString(ObjectName,
849 ALIGN_UP(sizeof(UNICODE_STRING), sizeof(PVOID))),
850 StrSize);
851
852
853 /* If we got an inherited window station handle, duplicate and use it */
854 if (hWinSta)
855 {
856 ASSERT(bUseDefaultWinSta);
857
858 /* Duplicate the handle if it belongs to another process than the current one */
860 {
862 Status = ZwDuplicateObject(hProcess,
863 hWinSta,
865 (PHANDLE)&hWinStaDup,
866 0,
867 0,
869 if (!NT_SUCCESS(Status))
870 {
871 ERR("IntResolveDesktop: Failed to duplicate the window station handle, Status 0x%08lx\n", Status);
872 /* We will use a default window station */
873 hWinSta = NULL;
874 }
875 else
876 {
877 hWinSta = hWinStaDup;
878 }
879 }
880 }
881
882 /*
883 * If we have an inherited window station, check whether
884 * it is interactive and remember that for later.
885 */
886 if (hWinSta)
887 {
888 ASSERT(bUseDefaultWinSta);
889
890 /* Reference the inherited window station */
892 0,
895 (PVOID*)&WinStaObject,
896 NULL);
897 if (!NT_SUCCESS(Status))
898 {
899 ERR("Failed to reference the inherited window station, Status 0x%08lx\n", Status);
900 /* We will use a default window station */
901 if (hWinStaDup)
902 {
903 ASSERT(hWinSta == hWinStaDup);
904 ObCloseHandle(hWinStaDup, UserMode);
905 hWinStaDup = NULL;
906 }
907 hWinSta = NULL;
908 }
909 else
910 {
911 ERR("Process LUID is: 0x%x-%x, inherited window station LUID is: 0x%x-%x\n",
912 ProcessLuid.HighPart, ProcessLuid.LowPart,
913 WinStaObject->luidUser.HighPart, WinStaObject->luidUser.LowPart);
914
915 /* Check whether this window station is interactive, and remember it for later */
916 bInteractive = !(WinStaObject->Flags & WSS_NOIO);
917
918 /* Dereference the window station */
919 ObDereferenceObject(WinStaObject);
920 }
921 }
922
923 /* Build a valid window station name */
925 ObjectName->MaximumLength,
926 L"%wZ\\%wZ",
928 &WinStaName);
929 if (!NT_SUCCESS(Status))
930 {
931 ERR("Impossible to build a valid window station name, Status 0x%08lx\n", Status);
932 goto Quit;
933 }
934 ObjectName->Length = (USHORT)(wcslen(ObjectName->Buffer) * sizeof(WCHAR));
935
936 TRACE("Parsed initial window station: '%wZ'\n", ObjectName);
937
938 /* Try to open the window station */
942 NULL,
943 NULL);
944 if (bInherit)
945 ObjectAttributes->Attributes |= OBJ_INHERIT;
946
949 UserMode,
950 NULL,
952 NULL,
953 (PHANDLE)&hTempWinSta);
954 if (!NT_SUCCESS(Status))
955 {
956 ERR("Failed to open the window station '%wZ', Status 0x%08lx\n", ObjectName, Status);
957 }
958 else
959 {
960 //
961 // FIXME TODO: Perform a window station access check!!
962 // If we fail AND bUseDefaultWinSta == FALSE we just quit.
963 //
964
965 /*
966 * Check whether we are opening the (single) interactive
967 * window station, and if so, perform an access check.
968 */
969 /* Check whether we are allowed to perform interactions */
970 if (RtlEqualUnicodeString(&WinStaName, &WinSta0Name, TRUE))
971 {
972 LUID SystemLuid = SYSTEM_LUID;
973
974 /* Interactive window station: check for user LUID */
975 WinStaObject = InputWindowStation;
976
978
979 // TODO: Check also that we compare wrt. window station WinSta0
980 // which is the only one that can be interactive on the system.
981 if (((!bUseDefaultWinSta || bInherit) && RtlEqualLuid(&ProcessLuid, &SystemLuid)) ||
982 RtlEqualLuid(&ProcessLuid, &WinStaObject->luidUser))
983 {
984 /* We are interactive on this window station */
985 bAccessAllowed = TRUE;
987 }
988 }
989 else
990 {
991 /* Non-interactive window station: we have access since we were able to open it */
992 bAccessAllowed = TRUE;
994 }
995 }
996
997 /* If we failed, bail out if we were not trying to open the default window station */
998 if (!NT_SUCCESS(Status) && !bUseDefaultWinSta) // if (!bAccessAllowed)
999 goto Quit;
1000
1001 if (/* bAccessAllowed && */ bInteractive || !bAccessAllowed)
1002 {
1003 /*
1004 * Close WinSta0 if the inherited window station is interactive so that
1005 * we can use it, or we do not have access to the interactive WinSta0.
1006 */
1007 ObCloseHandle(hTempWinSta, UserMode);
1008 hTempWinSta = NULL;
1009 }
1010 if (bInteractive == bAccessAllowed)
1011 {
1012 /* Keep using the inherited window station */
1013 NOTHING;
1014 }
1015 else // if (bInteractive != bAccessAllowed)
1016 {
1017 /*
1018 * Close the inherited window station, we will either keep using
1019 * the interactive WinSta0, or use Service-0xXXXX-YYYY$.
1020 */
1021 if (hWinStaDup)
1022 {
1023 ASSERT(hWinSta == hWinStaDup);
1024 ObCloseHandle(hWinStaDup, UserMode);
1025 hWinStaDup = NULL;
1026 }
1027 hWinSta = hTempWinSta; // hTempWinSta is NULL in case bAccessAllowed == FALSE
1028 }
1029
1030 if (bUseDefaultWinSta)
1031 {
1032 if (hWinSta == NULL && !bInteractive)
1033 {
1034 /* Build a valid window station name from the LUID */
1036 ObjectName->MaximumLength,
1037 L"%wZ\\Service-0x%x-%x$",
1039 ProcessLuid.HighPart,
1040 ProcessLuid.LowPart);
1041 if (!NT_SUCCESS(Status))
1042 {
1043 ERR("Impossible to build a valid window station name, Status 0x%08lx\n", Status);
1044 goto Quit;
1045 }
1046 ObjectName->Length = (USHORT)(wcslen(ObjectName->Buffer) * sizeof(WCHAR));
1047
1048 /*
1049 * Set up a security descriptor for the new service's window station.
1050 * A service has an associated window station and desktop. The newly
1051 * created window station and desktop will get this security descriptor
1052 * if such objects weren't created before.
1053 */
1054 Status = IntCreateServiceSecurity(&ServiceSD);
1055 if (!NT_SUCCESS(Status))
1056 {
1057 ERR("Failed to create a security descriptor for service window station, Status 0x%08lx\n", Status);
1058 goto Quit;
1059 }
1060
1061 /*
1062 * Create or open the non-interactive window station.
1063 * NOTE: The non-interactive window station handle is never inheritable.
1064 */
1066 ObjectName,
1068 NULL,
1069 ServiceSD);
1070
1071 Status = IntCreateWindowStation(&hWinSta,
1073 UserMode,
1074 KernelMode,
1076 0, 0, 0, 0, 0);
1077
1078 IntFreeSecurityBuffer(ServiceSD);
1079
1080 if (!NT_SUCCESS(Status))
1081 {
1082 ASSERT(hWinSta == NULL);
1083 ERR("Failed to create or open the non-interactive window station '%wZ', Status 0x%08lx\n",
1085 goto Quit;
1086 }
1087
1088 //
1089 // FIXME: We might not need to always create or open the "Default"
1090 // desktop on the Service-0xXXXX-YYYY$ window station; we may need
1091 // to use another one....
1092 //
1093
1094 /* Create or open the Default desktop on the window station */
1096 ObjectName->MaximumLength,
1097 L"Default");
1098 if (!NT_SUCCESS(Status))
1099 {
1100 ERR("Impossible to build a valid desktop name, Status 0x%08lx\n", Status);
1101 goto Quit;
1102 }
1103 ObjectName->Length = (USHORT)(wcslen(ObjectName->Buffer) * sizeof(WCHAR));
1104
1105 /*
1106 * NOTE: The non-interactive desktop handle is never inheritable.
1107 * The security descriptor is inherited from the newly created
1108 * window station for the desktop.
1109 */
1111 ObjectName,
1113 hWinSta,
1114 NULL);
1115
1116 Status = IntCreateDesktop(&hDesktop,
1118 UserMode,
1119 NULL,
1120 NULL,
1121 0,
1123 if (!NT_SUCCESS(Status))
1124 {
1125 ASSERT(hDesktop == NULL);
1126 ERR("Failed to create or open the desktop '%wZ' on window station 0x%p, Status 0x%08lx\n",
1127 ObjectName, hWinSta, Status);
1128 }
1129
1130 goto Quit;
1131 }
1132/*
1133 if (hWinSta == NULL)
1134 {
1135 Status = STATUS_UNSUCCESSFUL;
1136 goto Quit;
1137 }
1138*/
1139 }
1140
1141 /*
1142 * If we got an inherited desktop handle, duplicate and use it,
1143 * otherwise open a new desktop.
1144 */
1145 if (hDesktop != NULL)
1146 {
1147 /* Duplicate the handle if it belongs to another process than the current one */
1149 {
1151 Status = ZwDuplicateObject(hProcess,
1152 hDesktop,
1154 (PHANDLE)&hDesktopDup,
1155 0,
1156 0,
1158 if (!NT_SUCCESS(Status))
1159 {
1160 ERR("IntResolveDesktop: Failed to duplicate the desktop handle, Status 0x%08lx\n", Status);
1161 /* We will use a default desktop */
1162 hDesktop = NULL;
1163 }
1164 else
1165 {
1166 hDesktop = hDesktopDup;
1167 }
1168 }
1169 }
1170
1171 if ((hWinSta != NULL) && (hDesktop == NULL))
1172 {
1174 ObjectName->MaximumLength,
1175 DesktopName.Buffer,
1176 DesktopName.Length);
1177 if (!NT_SUCCESS(Status))
1178 {
1179 ERR("Impossible to build a valid desktop name, Status 0x%08lx\n", Status);
1180 goto Quit;
1181 }
1182 ObjectName->Length = (USHORT)(wcslen(ObjectName->Buffer) * sizeof(WCHAR));
1183
1184 TRACE("Parsed initial desktop: '%wZ'\n", ObjectName);
1185
1186 /* Open the desktop object */
1188 ObjectName,
1190 hWinSta,
1191 NULL);
1192 if (bInherit)
1193 ObjectAttributes->Attributes |= OBJ_INHERIT;
1194
1195 /*
1196 * A sandboxed process can be denied a piece of DESKTOP_ALL_ACCESS
1197 * on its startup desktop and must still be able to connect to it.
1198 */
1201 UserMode,
1202 NULL,
1204 NULL,
1205 (PHANDLE)&hDesktop);
1206 if (!NT_SUCCESS(Status))
1207 {
1208 ERR("Failed to open the desktop '%wZ' on window station 0x%p, Status 0x%08lx\n",
1209 ObjectName, hWinSta, Status);
1210 goto Quit;
1211 }
1212 }
1213
1214Quit:
1215 /* Release the object attributes */
1216 if (ObjectAttributes)
1217 {
1218 MemSize = 0;
1219 ZwFreeVirtualMemory(ZwCurrentProcess(),
1221 &MemSize,
1222 MEM_RELEASE);
1223 }
1224
1225 /* Close the temporary process handle */
1226 if (hProcess) // if (Process != PsGetCurrentProcess())
1228
1229 if (NT_SUCCESS(Status))
1230 {
1231 *phWinSta = hWinSta;
1232 *phDesktop = hDesktop;
1233 return STATUS_SUCCESS;
1234 }
1235 else
1236 {
1237 ERR("IntResolveDesktop(%wZ) failed, Status 0x%08lx\n", DesktopPath, Status);
1238
1239 if (hDesktopDup)
1240 ObCloseHandle(hDesktopDup, UserMode);
1241 if (hWinStaDup)
1242 ObCloseHandle(hWinStaDup, UserMode);
1243
1244 if (hDesktop)
1245 ObCloseHandle(hDesktop, UserMode);
1246 if (hWinSta)
1247 ObCloseHandle(hWinSta, UserMode);
1248
1250 return Status;
1251 }
1252}
1253
1254/*
1255 * IntValidateDesktopHandle
1256 *
1257 * Validates the desktop handle.
1258 *
1259 * Remarks
1260 * If the function succeeds, the handle remains referenced.
1261 * If the function fails, last error is set.
1262 */
1263
1266 HDESK Desktop,
1270{
1272
1276 AccessMode,
1277 (PVOID*)Object,
1278 NULL);
1279
1280 TRACE("IntValidateDesktopHandle: handle:0x%p obj:0x%p access:0x%x Status:0x%lx\n",
1282
1283 if (!NT_SUCCESS(Status))
1285
1286 return Status;
1287}
1288
1291{
1292 return gpdeskInputDesktop;
1293}
1294
1295/*
1296 * Returns or creates a handle to the desktop object
1297 */
1298HDESK FASTCALL
1300{
1302 HDESK hDesk;
1303
1304 ASSERT(DesktopObject);
1305
1307 DesktopObject,
1309 NULL,
1310 (PHANDLE)&hDesk))
1311 {
1312 Status = ObOpenObjectByPointer(DesktopObject,
1313 0,
1314 NULL,
1315 0,
1317 UserMode,
1318 (PHANDLE)&hDesk);
1319 if (!NT_SUCCESS(Status))
1320 {
1321 /* Unable to create a handle */
1322 ERR("Unable to create a desktop handle\n");
1323 return NULL;
1324 }
1325 }
1326 else
1327 {
1328 TRACE("Got handle: 0x%p\n", hDesk);
1329 }
1330
1331 return hDesk;
1332}
1333
1336{
1338 if (!pdo)
1339 {
1340 TRACE("No active desktop\n");
1341 return(NULL);
1342 }
1344}
1345
1348{
1351 if (!pdo)
1352 {
1353 TRACE("No active desktop\n");
1354 return;
1355 }
1356 if (NewQueue != NULL)
1357 {
1358 if (NewQueue->Desktop != NULL)
1359 {
1360 TRACE("Message Queue already attached to another desktop!\n");
1361 return;
1362 }
1363 IntReferenceMessageQueue(NewQueue);
1364 (void)InterlockedExchangePointer((PVOID*)&NewQueue->Desktop, pdo);
1365 }
1367 if (Old != NULL)
1368 {
1370 gpqForegroundPrev = Old;
1372 }
1373 // Only one Q can have active foreground even when there are more than one desktop.
1374 if (NewQueue)
1375 {
1377 }
1378 else
1379 {
1381 ERR("ptiLastInput is CLEARED!!\n");
1382 ptiLastInput = NULL; // ReactOS hacks... should check for process death.
1383 }
1384}
1385
1388{
1389 if (!pti) pti = PsGetCurrentThreadWin32Thread();
1390 if (pti->pDeskInfo) return pti->pDeskInfo->spwnd;
1391 return NULL;
1392}
1393
1395{
1396 if (pWnd->head.rpdesk &&
1397 pWnd->head.rpdesk->pDeskInfo)
1398 return pWnd->head.rpdesk->pDeskInfo->spwnd;
1399 return NULL;
1400}
1401
1403{
1405 if (!pdo)
1406 {
1407 TRACE("No active desktop\n");
1408 return NULL;
1409 }
1410 return pdo->DesktopWindow;
1411}
1412
1414{
1416 if (!pdo)
1417 {
1418 TRACE("No active desktop\n");
1419 return NULL;
1420 }
1421 // return pdo->pDeskInfo->spwnd;
1423}
1424
1426{
1428 if (!pdo)
1429 {
1430 TRACE("No active desktop\n");
1431 return NULL;
1432 }
1433 return UserHMGetHandle(pdo->spwndMessage);
1434}
1435
1437{
1439 if (!pdo)
1440 {
1441 TRACE("No active desktop\n");
1442 return NULL;
1443 }
1444 return pdo->spwndMessage;
1445}
1446
1448{
1450 PDESKTOP pdo = pti->rpdesk;
1451 if (!pdo)
1452 {
1453 ERR("Thread doesn't have a desktop\n");
1454 return NULL;
1455 }
1456 return pdo->DesktopWindow;
1457}
1458
1459/* PUBLIC FUNCTIONS ***********************************************************/
1460
1463{
1464 *lResult = 0;
1465
1466 switch (Msg)
1467 {
1468 case WM_NCCREATE:
1469 if (!Wnd->fnid)
1470 Wnd->fnid = FNID_DESKTOP;
1471 *lResult = (LRESULT)TRUE;
1472 return TRUE;
1473
1474 case WM_CREATE:
1475 {
1476 /* Save process and thread IDs */
1477 ULONG Value;
1483 }
1484 case WM_CLOSE:
1485 return TRUE;
1486
1487 case WM_DISPLAYCHANGE:
1489 return TRUE;
1490
1491 case WM_ERASEBKGND:
1493 *lResult = (LRESULT)TRUE;
1494 return TRUE;
1495
1496 case WM_PAINT:
1497 {
1498 PAINTSTRUCT Ps;
1499 if (IntBeginPaint(Wnd, &Ps))
1500 IntEndPaint(Wnd, &Ps);
1501 return TRUE;
1502 }
1503
1504 case WM_SYSCOLORCHANGE:
1506 return TRUE;
1507
1508 case WM_SETCURSOR:
1509 {
1510 PCURICON_OBJECT pcurOld, pcurNew;
1512 if (!pcurNew)
1513 return TRUE;
1514
1515 pcurNew->CURSORF_flags |= CURSORF_CURRENT;
1516 pcurOld = UserSetCursor(pcurNew, FALSE);
1517 if (pcurOld)
1518 {
1519 pcurOld->CURSORF_flags &= ~CURSORF_CURRENT;
1520 UserDereferenceObject(pcurOld);
1521 }
1522 return TRUE;
1523 }
1524
1526 {
1527 PWINDOWPOS pWindowPos = (PWINDOWPOS)lParam;
1528 if ((pWindowPos->flags & SWP_SHOWWINDOW) != 0)
1529 {
1531 IntSetThreadDesktop(hdesk, FALSE);
1532 }
1533 break;
1534 }
1535
1536 default:
1537 TRACE("DWP calling IDWP Msg %d\n",Msg);
1538 *lResult = IntDefWindowProc(Wnd, Msg, wParam, lParam, FALSE);
1539 }
1540
1541 return TRUE; /* We are done. Do not do any callbacks to user mode */
1542}
1543
1546{
1547 *lResult = 0;
1548
1549 switch(Msg)
1550 {
1551 case WM_NCCREATE:
1552 pwnd->fnid |= FNID_MESSAGEWND;
1553 *lResult = (LRESULT)TRUE;
1554 break;
1555 case WM_DESTROY:
1556 pwnd->fnid |= FNID_DESTROY;
1557 break;
1558 default:
1559 ERR("UMWP calling IDWP\n");
1560 *lResult = IntDefWindowProc(pwnd, Msg, wParam, lParam, FALSE);
1561 }
1562
1563 return TRUE; /* We are done. Do not do any callbacks to user mode */
1564}
1565
1567{
1568 BOOL Ret;
1569 MSG Msg;
1570
1572
1574
1575 /* Register system classes. This thread does not belong to any desktop so the
1576 classes will be allocated from the shared heap */
1578
1580
1581 while (TRUE)
1582 {
1583 Ret = co_IntGetPeekMessage(&Msg, 0, 0, 0, PM_REMOVE, TRUE);
1584 if (Ret)
1585 {
1587 }
1588 }
1589
1590 UserLeave();
1591}
1592
1594UserGetDesktopDC(ULONG DcType, BOOL bAltDc, BOOL ValidatehWnd)
1595{
1596 PWND DesktopObject = 0;
1597 HDC DesktopHDC = 0;
1598
1599 /* This can be called from GDI/DX, so acquire the USER lock */
1601
1602 if (DcType == DCTYPE_DIRECT)
1603 {
1604 DesktopObject = UserGetDesktopWindow();
1605 DesktopHDC = (HDC)UserGetWindowDC(DesktopObject);
1606 }
1607 else
1608 {
1609 PMONITOR pMonitor = UserGetPrimaryMonitor();
1610 DesktopHDC = IntGdiCreateDisplayDC(pMonitor->hDev, DcType, bAltDc);
1611 }
1612
1613 UserLeave();
1614
1615 return DesktopHDC;
1616}
1617
1620{
1621 PWND Window = NULL;
1622 PREGION Rgn;
1623
1625 Rgn = IntSysCreateRectpRgnIndirect(&Window->rcWindow);
1626
1628 Rgn,
1631
1632 REGION_Delete(Rgn);
1633}
1634
1635
1638{
1639 PWND pwnd = Desktop->pDeskInfo->spwnd;
1641 ASSERT(pwnd);
1642
1643 if (!bRedraw)
1645
1647
1648 if (bRedraw)
1650
1651 return STATUS_SUCCESS;
1652}
1653
1656{
1657 PWND DesktopWnd;
1658
1659 DesktopWnd = IntGetWindowObject(Desktop->DesktopWindow);
1660 if (! DesktopWnd)
1661 {
1663 }
1664 DesktopWnd->style &= ~WS_VISIBLE;
1665
1666 return STATUS_SUCCESS;
1667}
1668
1669static
1672{
1673 ULONG entries=0;
1674 PLIST_ENTRY ListEntry;
1675 PSHELL_HOOK_WINDOW Current;
1676 HWND* list;
1677
1678 /* FIXME: If we save nb elements in desktop, we don't have to loop to find nb entries */
1679 ListEntry = Desktop->ShellHookWindows.Flink;
1680 while (ListEntry != &Desktop->ShellHookWindows)
1681 {
1682 ListEntry = ListEntry->Flink;
1683 entries++;
1684 }
1685
1686 if (!entries) return NULL;
1687
1688 list = ExAllocatePoolWithTag(PagedPool, sizeof(HWND) * (entries + 1), USERTAG_WINDOWLIST); /* alloc one extra for nullterm */
1689 if (list)
1690 {
1691 HWND* cursor = list;
1692
1693 ListEntry = Desktop->ShellHookWindows.Flink;
1694 while (ListEntry != &Desktop->ShellHookWindows)
1695 {
1696 Current = CONTAINING_RECORD(ListEntry, SHELL_HOOK_WINDOW, ListEntry);
1697 ListEntry = ListEntry->Flink;
1698 *cursor++ = Current->hWnd;
1699 }
1700
1701 *cursor = NULL; /* Nullterm list */
1702 }
1703
1704 return list;
1705}
1706
1707/*
1708 * Send the Message to the windows registered for ShellHook
1709 * notifications. The lParam contents depend on the Message. See
1710 * MSDN for more details (RegisterShellHookWindow)
1711 */
1713{
1715 HWND* HwndList;
1716
1717 if (!gpsi->uiShellMsg)
1718 {
1719 gpsi->uiShellMsg = IntAddAtom(L"SHELLHOOK");
1720
1721 TRACE("MsgType = %x\n", gpsi->uiShellMsg);
1722 if (!gpsi->uiShellMsg)
1723 ERR("LastError: %x\n", EngGetLastError());
1724 }
1725
1726 if (!Desktop)
1727 {
1728 TRACE("IntShellHookNotify: No desktop!\n");
1729 return;
1730 }
1731
1732 // Allow other devices have a shot at foreground.
1733 if (Message == HSHELL_APPCOMMAND) ptiLastInput = NULL;
1734
1735 // FIXME: System Tray Support.
1736
1738 if (HwndList)
1739 {
1740 HWND* cursor = HwndList;
1741 LPARAM shellhookparam = (Message == HSHELL_LANGUAGE || Message == HSHELL_APPCOMMAND)
1742 ? lParam : (LPARAM)wParam;
1743
1744 for (; *cursor; cursor++)
1745 {
1746 TRACE("Sending notify\n");
1749 Message,
1750 shellhookparam);
1751/* co_IntPostOrSendMessage(*cursor,
1752 gpsi->uiShellMsg,
1753 Message,
1754 shellhookparam);*/
1755 }
1756
1758 }
1759
1760 if (ISITHOOKED(WH_SHELL))
1761 {
1763 }
1764}
1765
1766/*
1767 * Add the window to the ShellHookWindows list. The windows
1768 * on that list get notifications that are important to shell
1769 * type applications.
1770 *
1771 * TODO: Validate the window? I'm not sure if sending these messages to
1772 * an unsuspecting application that is not your own is a nice thing to do.
1773 */
1775{
1777 PDESKTOP Desktop = pti->rpdesk;
1779
1780 TRACE("IntRegisterShellHookWindow\n");
1781
1782 /* First deregister the window, so we can be sure it's never twice in the
1783 * list.
1784 */
1786
1788 sizeof(SHELL_HOOK_WINDOW),
1789 TAG_WINSTA);
1790
1791 if (!Entry)
1792 return FALSE;
1793
1794 Entry->hWnd = hWnd;
1795
1796 InsertTailList(&Desktop->ShellHookWindows, &Entry->ListEntry);
1797
1798 return TRUE;
1799}
1800
1801/*
1802 * Remove the window from the ShellHookWindows list. The windows
1803 * on that list get notifications that are important to shell
1804 * type applications.
1805 */
1807{
1809 PDESKTOP Desktop = pti->rpdesk;
1810 PLIST_ENTRY ListEntry;
1811 PSHELL_HOOK_WINDOW Current;
1812
1813 // FIXME: This probably shouldn't happen, but it does
1814 if (Desktop == NULL)
1815 {
1817 if (Desktop == NULL)
1818 return FALSE;
1819 }
1820
1821 ListEntry = Desktop->ShellHookWindows.Flink;
1822 while (ListEntry != &Desktop->ShellHookWindows)
1823 {
1824 Current = CONTAINING_RECORD(ListEntry, SHELL_HOOK_WINDOW, ListEntry);
1825 ListEntry = ListEntry->Flink;
1826 if (Current->hWnd == hWnd)
1827 {
1828 RemoveEntryList(&Current->ListEntry);
1829 ExFreePoolWithTag(Current, TAG_WINSTA);
1830 return TRUE;
1831 }
1832 }
1833
1834 return FALSE;
1835}
1836
1837static VOID
1839{
1840 /* FIXME: Disable until unmapping works in mm */
1841#if 0
1842 if (Desktop->pheapDesktop != NULL)
1843 {
1844 MmUnmapViewInSessionSpace(Desktop->pheapDesktop);
1845 Desktop->pheapDesktop = NULL;
1846 }
1847
1848 if (Desktop->hsectionDesktop != NULL)
1849 {
1850 ObDereferenceObject(Desktop->hsectionDesktop);
1851 Desktop->hsectionDesktop = NULL;
1852 }
1853#endif
1854}
1855
1858{
1859 static WCHAR s_wszSafeMode[] = L"Safe Mode"; // FIXME: Localize!
1860
1861 RECTL Rect;
1862 HBRUSH DesktopBrush, PreviousBrush;
1863 HWND hWndDesktop;
1864 BOOL doPatBlt = TRUE;
1865 PWND WndDesktop;
1866 BOOLEAN InSafeMode;
1867
1868 if (GdiGetClipBox(hDC, &Rect) == ERROR)
1869 return FALSE;
1870
1871 hWndDesktop = IntGetDesktopWindow(); // rpdesk->DesktopWindow;
1872
1873 WndDesktop = UserGetWindowObject(hWndDesktop); // rpdesk->pDeskInfo->spwnd;
1874 if (!WndDesktop)
1875 return FALSE;
1876
1877 /* Retrieve the current SafeMode state */
1878 InSafeMode = (UserGetSystemMetrics(SM_CLEANBOOT) != 0); // gpsi->aiSysMet[SM_CLEANBOOT];
1879
1880 if (!InSafeMode)
1881 {
1882 DesktopBrush = (HBRUSH)WndDesktop->pcls->hbrBackground;
1883
1884 /*
1885 * Paint desktop background
1886 */
1888 {
1889 SIZE sz;
1890 int x, y;
1891 int scaledWidth, scaledHeight;
1892 int wallpaperX, wallpaperY, wallpaperWidth, wallpaperHeight;
1893 HDC hWallpaperDC;
1894
1895 sz.cx = WndDesktop->rcWindow.right - WndDesktop->rcWindow.left;
1896 sz.cy = WndDesktop->rcWindow.bottom - WndDesktop->rcWindow.top;
1897
1898 if (gspv.WallpaperMode == wmFit ||
1900 {
1901 int scaleNum, scaleDen;
1902
1903 // Precision improvement over ((sz.cx / gspv.cxWallpaper) > (sz.cy / gspv.cyWallpaper))
1904 if ((sz.cx * gspv.cyWallpaper) > (sz.cy * gspv.cxWallpaper))
1905 {
1906 if (gspv.WallpaperMode == wmFit)
1907 {
1908 scaleNum = sz.cy;
1909 scaleDen = gspv.cyWallpaper;
1910 }
1911 else
1912 {
1913 scaleNum = sz.cx;
1914 scaleDen = gspv.cxWallpaper;
1915 }
1916 }
1917 else
1918 {
1919 if (gspv.WallpaperMode == wmFit)
1920 {
1921 scaleNum = sz.cx;
1922 scaleDen = gspv.cxWallpaper;
1923 }
1924 else
1925 {
1926 scaleNum = sz.cy;
1927 scaleDen = gspv.cyWallpaper;
1928 }
1929 }
1930
1931 scaledWidth = EngMulDiv(gspv.cxWallpaper, scaleNum, scaleDen);
1932 scaledHeight = EngMulDiv(gspv.cyWallpaper, scaleNum, scaleDen);
1933
1934 if (gspv.WallpaperMode == wmFill)
1935 {
1936 wallpaperX = (((scaledWidth - sz.cx) * gspv.cxWallpaper) / (2 * scaledWidth));
1937 wallpaperY = (((scaledHeight - sz.cy) * gspv.cyWallpaper) / (2 * scaledHeight));
1938
1939 wallpaperWidth = (sz.cx * gspv.cxWallpaper) / scaledWidth;
1940 wallpaperHeight = (sz.cy * gspv.cyWallpaper) / scaledHeight;
1941 }
1942 }
1943
1944 if (gspv.WallpaperMode == wmStretch ||
1947 {
1948 x = 0;
1949 y = 0;
1950 }
1951 else if (gspv.WallpaperMode == wmFit)
1952 {
1953 x = (sz.cx - scaledWidth) / 2;
1954 y = (sz.cy - scaledHeight) / 2;
1955 }
1956 else
1957 {
1958 /* Find the upper left corner, can be negative if the bitmap is bigger than the screen */
1959 x = (sz.cx / 2) - (gspv.cxWallpaper / 2);
1960 y = (sz.cy / 2) - (gspv.cyWallpaper / 2);
1961 }
1962
1963 hWallpaperDC = NtGdiCreateCompatibleDC(hDC);
1964 if (hWallpaperDC != NULL)
1965 {
1966 HBITMAP hOldBitmap;
1967
1968 /* Fill in the area that the bitmap is not going to cover */
1969 if (x > 0 || y > 0)
1970 {
1971 /* FIXME: Clip out the bitmap
1972 can be replaced with "NtGdiPatBlt(hDC, x, y, gspv.cxWallpaper, gspv.cyWallpaper, PATCOPY | DSTINVERT);"
1973 once we support DSTINVERT */
1974 PreviousBrush = NtGdiSelectBrush(hDC, DesktopBrush);
1975 NtGdiPatBlt(hDC, Rect.left, Rect.top, Rect.right, Rect.bottom, PATCOPY);
1976 NtGdiSelectBrush(hDC, PreviousBrush);
1977 }
1978
1979 /* Do not fill the background after it is painted no matter the size of the picture */
1980 doPatBlt = FALSE;
1981
1982 hOldBitmap = NtGdiSelectBitmap(hWallpaperDC, gspv.hbmWallpaper);
1983
1985 {
1986 if (Rect.right && Rect.bottom)
1988 x,
1989 y,
1990 sz.cx,
1991 sz.cy,
1992 hWallpaperDC,
1993 0,
1994 0,
1997 SRCCOPY,
1998 CLR_INVALID);
1999 }
2000 else if (gspv.WallpaperMode == wmTile)
2001 {
2002 /* Paint the bitmap across the screen then down */
2003 for (y = 0; y < Rect.bottom; y += gspv.cyWallpaper)
2004 {
2005 for (x = 0; x < Rect.right; x += gspv.cxWallpaper)
2006 {
2008 x,
2009 y,
2012 hWallpaperDC,
2013 0,
2014 0,
2015 SRCCOPY,
2017 0);
2018 }
2019 }
2020 }
2021 else if (gspv.WallpaperMode == wmFit)
2022 {
2023 if (Rect.right && Rect.bottom)
2024 {
2026 x,
2027 y,
2028 scaledWidth,
2029 scaledHeight,
2030 hWallpaperDC,
2031 0,
2032 0,
2035 SRCCOPY,
2036 CLR_INVALID);
2037 }
2038 }
2039 else if (gspv.WallpaperMode == wmFill)
2040 {
2041 if (Rect.right && Rect.bottom)
2042 {
2044 x,
2045 y,
2046 sz.cx,
2047 sz.cy,
2048 hWallpaperDC,
2049 wallpaperX,
2050 wallpaperY,
2051 wallpaperWidth,
2052 wallpaperHeight,
2053 SRCCOPY,
2054 CLR_INVALID);
2055 }
2056 }
2057 else
2058 {
2060 x,
2061 y,
2064 hWallpaperDC,
2065 0,
2066 0,
2067 SRCCOPY,
2069 0);
2070 }
2071 NtGdiSelectBitmap(hWallpaperDC, hOldBitmap);
2072 NtGdiDeleteObjectApp(hWallpaperDC);
2073 }
2074 }
2075 }
2076 else
2077 {
2078 /* Black desktop background in Safe Mode */
2079 DesktopBrush = StockObjects[BLACK_BRUSH];
2080 }
2081
2082 /* Background is set to none, clear the screen */
2083 if (doPatBlt)
2084 {
2085 PreviousBrush = NtGdiSelectBrush(hDC, DesktopBrush);
2086 NtGdiPatBlt(hDC, Rect.left, Rect.top, Rect.right, Rect.bottom, PATCOPY);
2087 NtGdiSelectBrush(hDC, PreviousBrush);
2088 }
2089
2090 /*
2091 * Display the system version on the desktop background
2092 */
2093 if (InSafeMode || g_AlwaysDisplayVersion || g_PaintDesktopVersion)
2094 {
2096 static WCHAR wszzVersion[1024] = L"\0";
2097
2098 /* Only used in normal mode */
2099 // We expect at most 4 strings (3 for version, 1 for optional NtSystemRoot)
2100 static POLYTEXTW VerStrs[4] = {{0},{0},{0},{0}};
2101 INT i = 0;
2102 SIZE_T len;
2103
2104 HFONT hFont1 = NULL, hFont2 = NULL, hOldFont = NULL;
2105 COLORREF crText, color_old;
2106 UINT align_old;
2107 INT mode_old;
2108 PDC pdc;
2109
2110 if (!UserSystemParametersInfo(SPI_GETWORKAREA, 0, &Rect, 0))
2111 {
2112 Rect.left = Rect.top = 0;
2115 }
2116 else
2117 {
2118 RECTL_vOffsetRect(&Rect, -Rect.left, -Rect.top);
2119 }
2120
2121 /*
2122 * Set up the fonts (otherwise use default ones)
2123 */
2124
2125 /* Font for the principal version string */
2126 hFont1 = GreCreateFontIndirectW(&gspv.ncm.lfCaptionFont);
2127 /* Font for the secondary version strings */
2128 hFont2 = GreCreateFontIndirectW(&gspv.ncm.lfMenuFont);
2129
2130 if (hFont1)
2131 hOldFont = NtGdiSelectFont(hDC, hFont1);
2132
2133 if (gspv.hbmWallpaper == NULL)
2134 {
2135 /* Retrieve the brush fill colour */
2136 // TODO: The following code constitutes "GreGetBrushColor".
2137 PreviousBrush = NtGdiSelectBrush(hDC, DesktopBrush);
2138 pdc = DC_LockDc(hDC);
2139 if (pdc)
2140 {
2141 crText = pdc->eboFill.ulRGBColor;
2142 DC_UnlockDc(pdc);
2143 }
2144 else
2145 {
2146 crText = RGB(0, 0, 0);
2147 }
2148 NtGdiSelectBrush(hDC, PreviousBrush);
2149
2150 /* Adjust text colour according to the brush */
2151 if (GetRValue(crText) + GetGValue(crText) + GetBValue(crText) > 128 * 3)
2152 crText = RGB(0, 0, 0);
2153 else
2154 crText = RGB(255, 255, 255);
2155 }
2156 else
2157 {
2158 /* Always use white when the text is displayed on top of a wallpaper */
2159 crText = RGB(255, 255, 255);
2160 }
2161
2162 color_old = IntGdiSetTextColor(hDC, crText);
2163 align_old = IntGdiSetTextAlign(hDC, TA_RIGHT);
2164 mode_old = IntGdiSetBkMode(hDC, TRANSPARENT);
2165
2166 /* Display the system version information */
2167 if (!*wszzVersion)
2168 {
2169 Status = GetSystemVersionString(wszzVersion,
2170 ARRAYSIZE(wszzVersion),
2171 InSafeMode,
2173 if (!InSafeMode && NT_SUCCESS(Status) && *wszzVersion)
2174 {
2175 PWCHAR pstr = wszzVersion;
2176 for (i = 0; (i < ARRAYSIZE(VerStrs)) && *pstr; ++i)
2177 {
2178 VerStrs[i].n = lstrlenW(pstr);
2179 VerStrs[i].lpstr = pstr;
2180 pstr += (VerStrs[i].n + 1);
2181 }
2182 }
2183 }
2184 else
2185 {
2187 }
2188 if (NT_SUCCESS(Status) && *wszzVersion)
2189 {
2190 if (!InSafeMode)
2191 {
2192 SIZE Size = {0, 0};
2193 LONG TotalHeight = 0;
2194
2195 /* Normal Mode: multiple version information text separated by newlines */
2197
2198 /* Compute the heights of the strings */
2199 if (hFont1) NtGdiSelectFont(hDC, hFont1);
2200 for (i = 0; i < ARRAYSIZE(VerStrs); ++i)
2201 {
2202 if (!VerStrs[i].lpstr || !*VerStrs[i].lpstr || (VerStrs[i].n == 0))
2203 break;
2204
2205 GreGetTextExtentW(hDC, VerStrs[i].lpstr, VerStrs[i].n, &Size, 1);
2206 VerStrs[i].y = Size.cy; // Store the string height
2207 TotalHeight += Size.cy;
2208
2209 /* While the first string was using hFont1, all the others use hFont2 */
2210 if (hFont2) NtGdiSelectFont(hDC, hFont2);
2211 }
2212 /* The total height must not exceed the screen height */
2213 TotalHeight = min(TotalHeight, Rect.bottom);
2214
2215 /* Display the strings */
2216 if (hFont1) NtGdiSelectFont(hDC, hFont1);
2217 for (i = 0; i < ARRAYSIZE(VerStrs); ++i)
2218 {
2219 if (!VerStrs[i].lpstr || !*VerStrs[i].lpstr || (VerStrs[i].n == 0))
2220 break;
2221
2222 TotalHeight -= VerStrs[i].y;
2224 Rect.right - 5,
2225 Rect.bottom - TotalHeight - 5,
2226 0, NULL,
2227 VerStrs[i].lpstr,
2228 VerStrs[i].n,
2229 NULL, 0);
2230
2231 /* While the first string was using hFont1, all the others use hFont2 */
2232 if (hFont2) NtGdiSelectFont(hDC, hFont2);
2233 }
2234 }
2235 else
2236 {
2237 if (hFont1) NtGdiSelectFont(hDC, hFont1);
2238
2239 /* Safe Mode: single version information text in top center */
2240 len = wcslen(wszzVersion);
2241
2243 GreExtTextOutW(hDC, (Rect.right + Rect.left)/2, Rect.top + 3, 0, NULL, wszzVersion, len, NULL, 0);
2244 }
2245 }
2246
2247 if (InSafeMode)
2248 {
2249 if (hFont1) NtGdiSelectFont(hDC, hFont1);
2250
2251 /* Print Safe Mode text in corners */
2252 len = wcslen(s_wszSafeMode);
2253
2255 GreExtTextOutW(hDC, Rect.left, Rect.top + 3, 0, NULL, s_wszSafeMode, len, NULL, 0);
2257 GreExtTextOutW(hDC, Rect.right, Rect.top + 3, 0, NULL, s_wszSafeMode, len, NULL, 0);
2259 GreExtTextOutW(hDC, Rect.left, Rect.bottom - 5, 0, NULL, s_wszSafeMode, len, NULL, 0);
2261 GreExtTextOutW(hDC, Rect.right, Rect.bottom - 5, 0, NULL, s_wszSafeMode, len, NULL, 0);
2262 }
2263
2264 IntGdiSetBkMode(hDC, mode_old);
2265 IntGdiSetTextAlign(hDC, align_old);
2266 IntGdiSetTextColor(hDC, color_old);
2267
2268 if (hFont2)
2269 GreDeleteObject(hFont2);
2270
2271 if (hFont1)
2272 {
2273 NtGdiSelectFont(hDC, hOldFont);
2274 GreDeleteObject(hFont1);
2275 }
2276 }
2277
2278 return TRUE;
2279}
2280
2281static NTSTATUS
2283{
2284 static const UNICODE_STRING WinlogonDesktop = RTL_CONSTANT_STRING(L"Winlogon");
2285 PVOID DesktopHeapSystemBase = NULL;
2287 SIZE_T DesktopInfoSize;
2288 ULONG i;
2289
2290 TRACE("UserInitializeDesktop desktop 0x%p with name %wZ\n", pdesk, DesktopName);
2291
2292 /* Set desktop size, based on whether the WinSta is interactive or not */
2293 if (pwinsta == InputWindowStation)
2294 {
2295 /* Check if the Desktop is named "Winlogon" */
2296 if (RtlEqualUnicodeString(DesktopName, &WinlogonDesktop, TRUE))
2297 {
2299 }
2300 else
2301 {
2303 }
2304 }
2305 else
2306 {
2308 }
2309
2310 /* Link the desktop with the parent window station */
2311 ObReferenceObject(pwinsta);
2312 pdesk->rpwinstaParent = pwinsta;
2313 InsertTailList(&pwinsta->DesktopListHead, &pdesk->ListEntry);
2314
2315 /* Create the desktop heap */
2316 pdesk->hsectionDesktop = NULL;
2318 &DesktopHeapSystemBase,
2319 HeapSize);
2320 if (pdesk->pheapDesktop == NULL)
2321 {
2322 ERR("Failed to create desktop heap!\n");
2323 return STATUS_NO_MEMORY;
2324 }
2325
2326 /* Create DESKTOPINFO */
2327 DesktopInfoSize = sizeof(DESKTOPINFO) + DesktopName->Length + sizeof(WCHAR);
2328 pdesk->pDeskInfo = RtlAllocateHeap(pdesk->pheapDesktop,
2330 DesktopInfoSize);
2331 if (pdesk->pDeskInfo == NULL)
2332 {
2333 ERR("Failed to create the DESKTOP structure!\n");
2334 return STATUS_NO_MEMORY;
2335 }
2336
2337 /* Initialize the DESKTOPINFO */
2338 pdesk->pDeskInfo->pvDesktopBase = DesktopHeapSystemBase;
2339 pdesk->pDeskInfo->pvDesktopLimit = (PVOID)((ULONG_PTR)DesktopHeapSystemBase + HeapSize);
2341 DesktopName->Buffer,
2342 DesktopName->Length + sizeof(WCHAR));
2343 for (i = 0; i < NB_HOOKS; i++)
2344 {
2346 }
2347
2349 InitializeListHead(&pdesk->PtiList);
2350
2351 return STATUS_SUCCESS;
2352}
2353
2354/* SYSCALLS *******************************************************************/
2355
2356/*
2357 * NtUserCreateDesktop
2358 *
2359 * Creates a new desktop.
2360 *
2361 * Parameters
2362 * poaAttribs
2363 * Object Attributes.
2364 *
2365 * lpszDesktopDevice
2366 * Name of the device.
2367 *
2368 * pDeviceMode
2369 * Device Mode.
2370 *
2371 * dwFlags
2372 * Interaction flags.
2373 *
2374 * dwDesiredAccess
2375 * Requested type of access.
2376 *
2377 *
2378 * Return Value
2379 * If the function succeeds, the return value is a handle to the newly
2380 * created desktop. If the specified desktop already exists, the function
2381 * succeeds and returns a handle to the existing desktop. When you are
2382 * finished using the handle, call the CloseDesktop function to close it.
2383 * If the function fails, the return value is NULL.
2384 *
2385 * Status
2386 * @implemented
2387 */
2388
2392 OUT HDESK* phDesktop,
2395 IN PUNICODE_STRING lpszDesktopDevice OPTIONAL,
2396 IN LPDEVMODEW lpdmw OPTIONAL,
2398 IN ACCESS_MASK dwDesiredAccess)
2399{
2401 PDESKTOP pdesk = NULL;
2402 HDESK hDesk;
2404 UNICODE_STRING ClassName;
2405 LARGE_STRING WindowName;
2406 BOOL NoHooks = FALSE;
2407 PWND pWnd = NULL;
2408 CREATESTRUCTW Cs;
2409 PTHREADINFO ptiCurrent;
2410 PCLS pcls;
2411
2412 TRACE("Enter IntCreateDesktop\n");
2413
2415
2416 ASSERT(phDesktop);
2417 *phDesktop = NULL;
2418
2419 ptiCurrent = PsGetCurrentThreadWin32Thread();
2420 ASSERT(ptiCurrent);
2422
2423 /* Turn off hooks when calling any CreateWindowEx from inside win32k */
2424 NoHooks = (ptiCurrent->TIF_flags & TIF_DISABLEHOOKS);
2425 ptiCurrent->TIF_flags |= TIF_DISABLEHOOKS;
2426 ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags;
2427
2428 /*
2429 * Try to open already existing desktop
2430 */
2433 AccessMode,
2434 NULL,
2435 dwDesiredAccess,
2436 (PVOID)&Context,
2437 (PHANDLE)&hDesk);
2438 if (!NT_SUCCESS(Status))
2439 {
2440 ERR("ObOpenObjectByName failed to open/create desktop\n");
2441 goto Quit;
2442 }
2443
2444 /* In case the object was not created (eg if it existed), return now */
2445 if (Context == FALSE)
2446 {
2447 TRACE("IntCreateDesktop opened desktop '%wZ'\n", ObjectAttributes->ObjectName);
2449 goto Quit;
2450 }
2451
2452 /* Reference the desktop */
2454 0,
2456 KernelMode,
2457 (PVOID*)&pdesk,
2458 NULL);
2459 if (!NT_SUCCESS(Status))
2460 {
2461 ERR("Failed to reference desktop object\n");
2462 goto Quit;
2463 }
2464
2465 /* Get the desktop window class. The thread desktop does not belong to any desktop
2466 * so the classes created there (including the desktop class) are allocated in the shared heap
2467 * It would cause problems if we used a class that belongs to the caller
2468 */
2469 ClassName.Buffer = WC_DESKTOP;
2470 ClassName.Length = 0;
2471 pcls = IntGetAndReferenceClass(&ClassName, 0, TRUE);
2472 if (pcls == NULL)
2473 {
2474 ASSERT(FALSE);
2476 goto Quit;
2477 }
2478
2479 RtlZeroMemory(&WindowName, sizeof(WindowName));
2480 RtlZeroMemory(&Cs, sizeof(Cs));
2486 Cs.hInstance = hModClient; // hModuleWin; // Server side winproc!
2487 Cs.lpszName = (LPCWSTR) &WindowName;
2488 Cs.lpszClass = (LPCWSTR) &ClassName;
2489
2490 /* Use IntCreateWindow instead of co_UserCreateWindowEx because the later expects a thread with a desktop */
2491 pWnd = IntCreateWindow(&Cs, &WindowName, pcls, NULL, NULL, NULL, pdesk, WINVER);
2492 if (pWnd == NULL)
2493 {
2494 ERR("Failed to create desktop window for the new desktop\n");
2496 goto Quit;
2497 }
2498 pWnd->fnid = FNID_DESKTOP;
2499
2500 /* Assign the desktop window to the desktop */
2501 pdesk->DesktopWindow = UserHMGetHandle(pWnd);
2502 pdesk->pDeskInfo->spwnd = pWnd;
2503
2504 ClassName.Buffer = MAKEINTATOM(gpsi->atomSysClass[ICLS_HWNDMESSAGE]);
2505 ClassName.Length = 0;
2506 pcls = IntGetAndReferenceClass(&ClassName, 0, TRUE);
2507 if (pcls == NULL)
2508 {
2509 ASSERT(FALSE);
2511 goto Quit;
2512 }
2513
2514 RtlZeroMemory(&WindowName, sizeof(WindowName));
2515 RtlZeroMemory(&Cs, sizeof(Cs));
2516 Cs.cx = Cs.cy = 100;
2518 Cs.hInstance = hModClient; // hModuleWin; // Server side winproc!
2519 Cs.lpszName = (LPCWSTR)&WindowName;
2520 Cs.lpszClass = (LPCWSTR)&ClassName;
2521 pWnd = IntCreateWindow(&Cs, &WindowName, pcls, NULL, NULL, NULL, pdesk, WINVER);
2522 if (pWnd == NULL)
2523 {
2524 ERR("Failed to create message window for the new desktop\n");
2526 goto Quit;
2527 }
2528 pWnd->fnid = FNID_MESSAGEWND;
2529
2530 /* Assign the message window to the desktop */
2531 pdesk->spwndMessage = pWnd;
2532
2533 /* Now...
2534 if !(WinStaObject->Flags & WSF_NOIO) is (not set) for desktop input output mode (see wiki)
2535 Create Tooltip. Saved in DesktopObject->spwndTooltip.
2536 Tooltip dwExStyle: WS_EX_TOOLWINDOW|WS_EX_TOPMOST
2537 hWndParent are spwndMessage. Use hModuleWin for server side winproc!
2538 The rest is same as message window.
2539 https://learn.microsoft.com/en-us/windows/win32/controls/tooltip-controls
2540 */
2542
2543Quit:
2544 if (pdesk != NULL)
2545 {
2546 ObDereferenceObject(pdesk);
2547 }
2548 if (!NT_SUCCESS(Status) && hDesk != NULL)
2549 {
2550 ObCloseHandle(hDesk, AccessMode);
2551 hDesk = NULL;
2552 }
2553 if (!NoHooks)
2554 {
2555 ptiCurrent->TIF_flags &= ~TIF_DISABLEHOOKS;
2556 ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags;
2557 }
2558
2559 TRACE("Leave IntCreateDesktop, Status 0x%08lx\n", Status);
2560
2561 if (NT_SUCCESS(Status))
2562 *phDesktop = hDesk;
2563 else
2565 return Status;
2566}
2567
2568HDESK APIENTRY
2571 PUNICODE_STRING lpszDesktopDevice,
2572 LPDEVMODEW lpdmw,
2573 DWORD dwFlags,
2574 ACCESS_MASK dwDesiredAccess)
2575{
2577 HDESK hDesk;
2578 HDESK Ret = NULL;
2579
2580 TRACE("Enter NtUserCreateDesktop\n");
2582
2583 Status = IntCreateDesktop(&hDesk,
2585 UserMode,
2586 lpszDesktopDevice,
2587 lpdmw,
2588 dwFlags,
2589 dwDesiredAccess);
2590 if (!NT_SUCCESS(Status))
2591 {
2592 ERR("IntCreateDesktop failed, Status 0x%08lx\n", Status);
2593 // SetLastNtError(Status);
2594 goto Exit; // Return NULL
2595 }
2596
2597 Ret = hDesk;
2598
2599Exit:
2600 TRACE("Leave NtUserCreateDesktop, ret=0x%p\n", Ret);
2601 UserLeave();
2602 return Ret;
2603}
2604
2605/*
2606 * NtUserOpenDesktop
2607 *
2608 * Opens an existing desktop.
2609 *
2610 * Parameters
2611 * lpszDesktopName
2612 * Name of the existing desktop.
2613 *
2614 * dwFlags
2615 * Interaction flags.
2616 *
2617 * dwDesiredAccess
2618 * Requested type of access.
2619 *
2620 * Return Value
2621 * Handle to the desktop or zero on failure.
2622 *
2623 * Status
2624 * @implemented
2625 */
2626
2627HDESK APIENTRY
2630 DWORD dwFlags,
2631 ACCESS_MASK dwDesiredAccess)
2632{
2634 HDESK Desktop;
2635
2639 UserMode,
2640 NULL,
2641 dwDesiredAccess,
2642 NULL,
2643 (HANDLE*)&Desktop);
2644
2645 if (!NT_SUCCESS(Status))
2646 {
2647 ERR("Failed to open desktop\n");
2649 return NULL;
2650 }
2651
2652 TRACE("Opened desktop %S with handle 0x%p\n", ObjectAttributes->ObjectName->Buffer, Desktop);
2653
2654 return Desktop;
2655}
2656
2658 BOOL fInherit,
2659 ACCESS_MASK dwDesiredAccess)
2660{
2664 HDESK hdesk = NULL;
2665
2666 if (!gpdeskInputDesktop)
2667 {
2668 return NULL;
2669 }
2670
2671 if (pti->ppi->prpwinsta != InputWindowStation)
2672 {
2673 ERR("Tried to open input desktop from non interactive winsta!\n");
2675 return NULL;
2676 }
2677
2678 if (fInherit) HandleAttributes = OBJ_INHERIT;
2679
2680 /* Create a new handle to the object */
2684 NULL,
2685 dwDesiredAccess,
2687 UserMode,
2688 (PHANDLE)&hdesk);
2689
2690 if (!NT_SUCCESS(Status))
2691 {
2692 ERR("Failed to open input desktop object\n");
2694 }
2695
2696 return hdesk;
2697}
2698
2699/*
2700 * NtUserOpenInputDesktop
2701 *
2702 * Opens the input (interactive) desktop.
2703 *
2704 * Parameters
2705 * dwFlags
2706 * Interaction flags.
2707 *
2708 * fInherit
2709 * Inheritance option.
2710 *
2711 * dwDesiredAccess
2712 * Requested type of access.
2713 *
2714 * Return Value
2715 * Handle to the input desktop or zero on failure.
2716 *
2717 * Status
2718 * @implemented
2719 */
2720
2721HDESK APIENTRY
2723 DWORD dwFlags,
2724 BOOL fInherit,
2725 ACCESS_MASK dwDesiredAccess)
2726{
2727 HDESK hdesk;
2728
2730 TRACE("Enter NtUserOpenInputDesktop gpdeskInputDesktop 0x%p\n", gpdeskInputDesktop);
2731
2732 hdesk = UserOpenInputDesktop(dwFlags, fInherit, dwDesiredAccess);
2733
2734 TRACE("NtUserOpenInputDesktop returning 0x%p\n", hdesk);
2735 UserLeave();
2736 return hdesk;
2737}
2738
2739/*
2740 * NtUserCloseDesktop
2741 *
2742 * Closes a desktop handle.
2743 *
2744 * Parameters
2745 * hDesktop
2746 * Handle to the desktop.
2747 *
2748 * Return Value
2749 * Status
2750 *
2751 * Remarks
2752 * The desktop handle can be created with NtUserCreateDesktop or
2753 * NtUserOpenDesktop. This function will fail if any thread in the calling
2754 * process is using the specified desktop handle or if the handle refers
2755 * to the initial desktop of the calling process.
2756 *
2757 * Status
2758 * @implemented
2759 */
2760
2762NtUserCloseDesktop(HDESK hDesktop)
2763{
2764 PDESKTOP pdesk;
2766 BOOL Ret = FALSE;
2767
2768 TRACE("NtUserCloseDesktop(0x%p) called\n", hDesktop);
2770
2771 if (hDesktop == gptiCurrent->hdesk || hDesktop == gptiCurrent->ppi->hdeskStartup)
2772 {
2773 ERR("Attempted to close thread desktop\n");
2775 goto Exit; // Return FALSE
2776 }
2777
2778 Status = IntValidateDesktopHandle(hDesktop, UserMode, 0, &pdesk);
2779 if (!NT_SUCCESS(Status))
2780 {
2781 ERR("Validation of desktop handle 0x%p failed\n", hDesktop);
2782 goto Exit; // Return FALSE
2783 }
2784
2785 ObDereferenceObject(pdesk);
2786
2787 Status = ObCloseHandle(hDesktop, UserMode);
2788 if (!NT_SUCCESS(Status))
2789 {
2790 ERR("Failed to close desktop handle 0x%p\n", hDesktop);
2792 goto Exit; // Return FALSE
2793 }
2794
2795 Ret = TRUE;
2796
2797Exit:
2798 TRACE("Leave NtUserCloseDesktop, ret=%i\n", Ret);
2799 UserLeave();
2800 return Ret;
2801}
2802
2803/*
2804 * NtUserPaintDesktop
2805 *
2806 * The NtUserPaintDesktop function fills the clipping region in the
2807 * specified device context with the desktop pattern or wallpaper. The
2808 * function is provided primarily for shell desktops.
2809 *
2810 * Parameters
2811 * hDC
2812 * Handle to the device context.
2813 *
2814 * Status
2815 * @implemented
2816 */
2817
2820{
2821 BOOL Ret;
2822
2824 TRACE("Enter NtUserPaintDesktop\n");
2825
2826 Ret = IntPaintDesktop(hDC);
2827
2828 TRACE("Leave NtUserPaintDesktop, ret=%i\n", Ret);
2829 UserLeave();
2830 return Ret;
2831}
2832
2833/*
2834 * NtUserResolveDesktop
2835 *
2836 * The NtUserResolveDesktop function attempts to retrieve valid handles to
2837 * a desktop and a window station suitable for the specified process.
2838 * The specified desktop path string is used only as a hint for the resolution.
2839 *
2840 * See the description of IntResolveDesktop for more details.
2841 *
2842 * Parameters
2843 * ProcessHandle
2844 * Handle to a user process.
2845 *
2846 * DesktopPath
2847 * The desktop path string used as a hint for desktop resolution.
2848 *
2849 * bInherit
2850 * Whether or not the returned handles are inheritable.
2851 *
2852 * phWinSta
2853 * Pointer to a window station handle.
2854 *
2855 * Return Value
2856 * Handle to the desktop (direct return value) and
2857 * handle to the associated window station (by pointer).
2858 * NULL in case of failure.
2859 *
2860 * Remarks
2861 * Callable by CSRSS only.
2862 *
2863 * Status
2864 * @implemented
2865 */
2866
2867HDESK
2868NTAPI
2871 IN PUNICODE_STRING DesktopPath,
2872 IN BOOL bInherit,
2873 OUT HWINSTA* phWinSta)
2874{
2877 HWINSTA hWinSta = NULL;
2878 HDESK hDesktop = NULL;
2879 UNICODE_STRING CapturedDesktopPath;
2880
2881 /* Allow only the Console Server to perform this operation (via CSRSS) */
2883 return NULL;
2884
2885 /* Get the process object the user handle was referencing */
2889 UserMode,
2890 (PVOID*)&Process,
2891 NULL);
2892 if (!NT_SUCCESS(Status))
2893 return NULL;
2894
2896
2897 _SEH2_TRY
2898 {
2899 /* Probe the handle pointer */
2900 // ProbeForWriteHandle
2901 ProbeForWrite(phWinSta, sizeof(HWINSTA), sizeof(HWINSTA));
2902 }
2904 {
2906 _SEH2_YIELD(goto Quit);
2907 }
2908 _SEH2_END;
2909
2910 /* Capture the user desktop path string */
2911 Status = ProbeAndCaptureUnicodeString(&CapturedDesktopPath,
2912 UserMode,
2913 DesktopPath);
2914 if (!NT_SUCCESS(Status))
2915 goto Quit;
2916
2917 /* Call the internal function */
2919 &CapturedDesktopPath,
2920 bInherit,
2921 &hWinSta,
2922 &hDesktop);
2923 if (!NT_SUCCESS(Status))
2924 {
2925 ERR("IntResolveDesktop failed, Status 0x%08lx\n", Status);
2926 hWinSta = NULL;
2927 hDesktop = NULL;
2928 }
2929
2930 _SEH2_TRY
2931 {
2932 /* Return the window station handle */
2933 *phWinSta = hWinSta;
2934 }
2936 {
2938
2939 /* We failed, close the opened desktop and window station */
2940 if (hDesktop) ObCloseHandle(hDesktop, UserMode);
2941 hDesktop = NULL;
2942 if (hWinSta) ObCloseHandle(hWinSta, UserMode);
2943 }
2944 _SEH2_END;
2945
2946 /* Free the captured string */
2947 ReleaseCapturedUnicodeString(&CapturedDesktopPath, UserMode);
2948
2949Quit:
2950 UserLeave();
2951
2952 /* Dereference the process object */
2954
2955 /* Return the desktop handle */
2956 return hDesktop;
2957}
2958
2959/*
2960 * NtUserSwitchDesktop
2961 *
2962 * Sets the current input (interactive) desktop.
2963 *
2964 * Parameters
2965 * hDesktop
2966 * Handle to desktop.
2967 *
2968 * Return Value
2969 * Status
2970 *
2971 * Status
2972 * @unimplemented
2973 */
2974
2977{
2978 PDESKTOP pdesk;
2980 BOOL bRedrawDesktop;
2981 BOOL Ret = FALSE;
2982
2984 TRACE("Enter NtUserSwitchDesktop(0x%p)\n", hdesk);
2985
2986 Status = IntValidateDesktopHandle(hdesk, UserMode, 0, &pdesk);
2987 if (!NT_SUCCESS(Status))
2988 {
2989 ERR("Validation of desktop handle 0x%p failed\n", hdesk);
2990 goto Exit;
2991 }
2992
2994 {
2995 ObDereferenceObject(pdesk);
2996 ERR("NtUserSwitchDesktop called for a desktop of a different session\n");
2997 goto Exit;
2998 }
2999
3000 if (pdesk == gpdeskInputDesktop)
3001 {
3002 ObDereferenceObject(pdesk);
3003 WARN("NtUserSwitchDesktop called for active desktop\n");
3004 Ret = TRUE;
3005 goto Exit;
3006 }
3007
3008 /*
3009 * Don't allow applications switch the desktop if it's locked,
3010 * unless the caller is the logon application itself.
3011 */
3012 if ((pdesk->rpwinstaParent->Flags & WSS_LOCKED) &&
3014 {
3015 ObDereferenceObject(pdesk);
3016 ERR("Switching desktop 0x%p denied because the window station is locked!\n", hdesk);
3017 goto Exit;
3018 }
3019
3020 if (pdesk->rpwinstaParent != InputWindowStation)
3021 {
3022 ObDereferenceObject(pdesk);
3023 ERR("Switching desktop 0x%p denied because desktop doesn't belong to the interactive winsta!\n", hdesk);
3024 goto Exit;
3025 }
3026
3027 /* FIXME: Fail if the process is associated with a secured
3028 desktop such as Winlogon or Screen-Saver */
3029 /* FIXME: Connect to input device */
3030
3031 TRACE("Switching from desktop 0x%p to 0x%p\n", gpdeskInputDesktop, pdesk);
3032
3033 bRedrawDesktop = FALSE;
3034
3035 /* The first time SwitchDesktop is called, gpdeskInputDesktop is NULL */
3036 if (gpdeskInputDesktop != NULL)
3037 {
3039 bRedrawDesktop = TRUE;
3040
3041 /* Hide the previous desktop window */
3043 }
3044
3045 /* Set the active desktop in the desktop's window station */
3047
3048 /* Set the global state */
3049 gpdeskInputDesktop = pdesk;
3050
3051 /* Show the new desktop window */
3053
3054 // TODO: Request hard-error popups to be respawned to the new desktop.
3055
3056 /* Notify waiters that a desktop has been switched on the
3057 * interactive window station: pulse the legacy (NT 3.5+)
3058 * event and send the desktop-switch notification (Vista+) */
3060#if (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
3061 IntNotifyWinEvent(EVENT_SYSTEM_DESKTOPSWITCH, NULL, OBJID_WINDOW, CHILDID_SELF, 0);
3062#endif
3063
3064 TRACE("SwitchDesktop gpdeskInputDesktop 0x%p\n", gpdeskInputDesktop);
3065 ObDereferenceObject(pdesk);
3066
3067 Ret = TRUE;
3068
3069Exit:
3070 TRACE("Leave NtUserSwitchDesktop, ret=%i\n", Ret);
3071 UserLeave();
3072 return Ret;
3073}
3074
3075/*
3076 * NtUserGetThreadDesktop
3077 *
3078 * Status
3079 * @implemented
3080 */
3081
3082HDESK APIENTRY
3084{
3085 HDESK hDesk;
3087 PTHREADINFO pti;
3089 PDESKTOP DesktopObject;
3091
3093 TRACE("Enter NtUserGetThreadDesktop\n");
3094
3095 if (!dwThreadId)
3096 {
3098 hDesk = NULL;
3099 goto Quit;
3100 }
3101
3102 /* Validate the Win32 thread and retrieve its information */
3104 if (pti)
3105 {
3106 /* Get the desktop handle of the thread */
3107 hDesk = pti->hdesk;
3108 Process = pti->ppi->peProcess;
3109 }
3110 else if (hConsoleDesktop)
3111 {
3112 /*
3113 * The thread may belong to a console, so attempt to use the provided
3114 * console desktop handle as a fallback. Otherwise this means that the
3115 * thread is either not Win32 or invalid.
3116 */
3117 hDesk = hConsoleDesktop;
3119 }
3120 else
3121 {
3123 hDesk = NULL;
3124 goto Quit;
3125 }
3126
3127 if (!hDesk)
3128 {
3129 ERR("Desktop information of thread 0x%x broken!?\n", dwThreadId);
3130 goto Quit;
3131 }
3132
3134 {
3135 /*
3136 * Just return the handle, since we queried the desktop handle
3137 * of a thread running in the same context.
3138 */
3139 goto Quit;
3140 }
3141
3142 /*
3143 * We could just use the cached rpdesk instead of looking up the handle,
3144 * but it may actually be safer to validate the desktop and get a temporary
3145 * reference to it so that it does not disappear under us (e.g. when the
3146 * desktop is being destroyed) during the operation.
3147 */
3148 /*
3149 * Switch into the context of the thread we are trying to get
3150 * the desktop from, so we can use the handle.
3151 */
3152 KeAttachProcess(&Process->Pcb);
3154 0,
3156 UserMode,
3157 (PVOID*)&DesktopObject,
3160
3161 if (NT_SUCCESS(Status))
3162 {
3163 /*
3164 * Lookup our handle table if we can find a handle to the desktop object.
3165 * If not, create one.
3166 * QUESTION: Do we really need to create a handle in case it doesn't exist??
3167 */
3168 hDesk = IntGetDesktopObjectHandle(DesktopObject);
3169
3170 /* All done, we got a valid handle to the desktop */
3171 ObDereferenceObject(DesktopObject);
3172 }
3173 else
3174 {
3175 /* The handle could not be found, there is nothing to get... */
3176 hDesk = NULL;
3177 }
3178
3179 if (!hDesk)
3180 {
3181 ERR("Could not retrieve or access desktop for thread 0x%x\n", dwThreadId);
3183 }
3184
3185Quit:
3186 TRACE("Leave NtUserGetThreadDesktop, hDesk = 0x%p\n", hDesk);
3187 UserLeave();
3188 return hDesk;
3189}
3190
3191static NTSTATUS
3193{
3194 PPROCESSINFO ppi;
3195 PW32HEAP_USER_MAPPING HeapMapping, *PrevLink;
3197
3198 TRACE("IntUnmapDesktopView called for desktop object %p\n", pdesk);
3199
3201
3202 /*
3203 * Unmap if we're the last thread using the desktop.
3204 * Start the search at the next mapping: skip the first entry
3205 * as it must be the global user heap mapping.
3206 */
3207 PrevLink = &ppi->HeapMappings.Next;
3208 HeapMapping = *PrevLink;
3209 while (HeapMapping != NULL)
3210 {
3211 if (HeapMapping->KernelMapping == (PVOID)pdesk->pheapDesktop)
3212 {
3213 if (--HeapMapping->Count == 0)
3214 {
3215 *PrevLink = HeapMapping->Next;
3216
3217 TRACE("ppi 0x%p unmapped heap of desktop 0x%p\n", ppi, pdesk);
3219 HeapMapping->UserMapping);
3220
3221 ObDereferenceObject(pdesk);
3222
3223 UserHeapFree(HeapMapping);
3224 break;
3225 }
3226 }
3227
3228 PrevLink = &HeapMapping->Next;
3229 HeapMapping = HeapMapping->Next;
3230 }
3231
3232 return Status;
3233}
3234
3235static NTSTATUS
3237{
3238 PPROCESSINFO ppi;
3239 PW32HEAP_USER_MAPPING HeapMapping, *PrevLink;
3240 PVOID UserBase = NULL;
3241 SIZE_T ViewSize = 0;
3244
3245 TRACE("IntMapDesktopView called for desktop object 0x%p\n", pdesk);
3246
3248
3249 /*
3250 * Find out if another thread already mapped the desktop heap.
3251 * Start the search at the next mapping: skip the first entry
3252 * as it must be the global user heap mapping.
3253 */
3254 PrevLink = &ppi->HeapMappings.Next;
3255 HeapMapping = *PrevLink;
3256 while (HeapMapping != NULL)
3257 {
3258 if (HeapMapping->KernelMapping == (PVOID)pdesk->pheapDesktop)
3259 {
3260 HeapMapping->Count++;
3261 return STATUS_SUCCESS;
3262 }
3263
3264 PrevLink = &HeapMapping->Next;
3265 HeapMapping = HeapMapping->Next;
3266 }
3267
3268 /* We're the first, map the heap */
3269 Offset.QuadPart = 0;
3270 Status = MmMapViewOfSection(pdesk->hsectionDesktop,
3272 &UserBase,
3273 0,
3274 0,
3275 &Offset,
3276 &ViewSize,
3277 ViewUnmap,
3280 if (!NT_SUCCESS(Status))
3281 {
3282 ERR("Failed to map desktop\n");
3283 return Status;
3284 }
3285
3286 TRACE("ppi 0x%p mapped heap of desktop 0x%p\n", ppi, pdesk);
3287
3288 /* Add the mapping */
3289 HeapMapping = UserHeapAlloc(sizeof(*HeapMapping));
3290 if (HeapMapping == NULL)
3291 {
3293 ERR("UserHeapAlloc() failed!\n");
3294 return STATUS_NO_MEMORY;
3295 }
3296
3297 HeapMapping->Next = NULL;
3298 HeapMapping->KernelMapping = (PVOID)pdesk->pheapDesktop;
3299 HeapMapping->UserMapping = UserBase;
3300 HeapMapping->Limit = ViewSize;
3301 HeapMapping->Count = 1;
3302 *PrevLink = HeapMapping;
3303
3304 ObReferenceObject(pdesk);
3305
3306 return STATUS_SUCCESS;
3307}
3308
3309BOOL
3311 IN BOOL FreeOnFailure)
3312{
3313 PDESKTOP pdesk = NULL, pdeskOld;
3314 PTHREADINFO pti;
3316 PCLIENTTHREADINFO pctiOld, pctiNew = NULL;
3317 PCLIENTINFO pci;
3318
3320
3321 TRACE("IntSetThreadDesktop hDesktop:0x%p, FOF:%i\n",hDesktop, FreeOnFailure);
3322
3324 pci = pti->pClientInfo;
3325
3326 /* If the caller gave us a desktop, ensure it is valid */
3327 if (hDesktop != NULL)
3328 {
3329 /* Validate the new desktop. */
3330 Status = IntValidateDesktopHandle(hDesktop, UserMode, 0, &pdesk);
3331 if (!NT_SUCCESS(Status))
3332 {
3333 ERR("Validation of desktop handle 0x%p failed\n", hDesktop);
3334 return FALSE;
3335 }
3336
3337 if (pti->rpdesk == pdesk)
3338 {
3339 /* Nothing to do */
3340 ObDereferenceObject(pdesk);
3341 return TRUE;
3342 }
3343 }
3344
3345 /* Make sure that we don't own any window in the current desktop */
3346 if (!IsListEmpty(&pti->WindowListHead))
3347 {
3348 if (pdesk)
3349 ObDereferenceObject(pdesk);
3350 ERR("Attempted to change thread desktop although the thread has windows!\n");
3352 return FALSE;
3353 }
3354
3355 /* Desktop is being re-set so clear out foreground. */
3356 if (pti->rpdesk != pdesk && pti->MessageQueue == gpqForeground)
3357 {
3358 // Like above, there shouldn't be any windows, hooks or anything active on this threads desktop!
3360 }
3361
3362 /* Before doing the switch, map the new desktop heap and allocate the new pcti */
3363 if (pdesk != NULL)
3364 {
3365 Status = IntMapDesktopView(pdesk);
3366 if (!NT_SUCCESS(Status))
3367 {
3368 ERR("Failed to map desktop heap!\n");
3369 ObDereferenceObject(pdesk);
3371 return FALSE;
3372 }
3373
3374 pctiNew = DesktopHeapAlloc(pdesk, sizeof(CLIENTTHREADINFO));
3375 if (pctiNew == NULL)
3376 {
3377 ERR("Failed to allocate new pcti\n");
3378 IntUnmapDesktopView(pdesk);
3379 ObDereferenceObject(pdesk);
3381 return FALSE;
3382 }
3383 }
3384
3385 /*
3386 * Processes, in particular Winlogon.exe, that manage window stations
3387 * (especially the interactive WinSta0 window station) and desktops,
3388 * may not be able to connect at startup to a window station and have
3389 * an associated desktop as well, if none exists on the system already.
3390 * Because creating a new window station does not affect the window station
3391 * associated to the process, and because neither by associating a window
3392 * station to the process nor creating a new desktop on it does associate
3393 * a startup desktop to that process, the process has to actually assigns
3394 * one of its threads to a desktop so that it gets automatically an assigned
3395 * startup desktop.
3396 *
3397 * This is what actually happens for Winlogon.exe, which is started without
3398 * any window station and desktop. By creating the first (and therefore
3399 * interactive) WinSta0 window station, then assigning WinSta0 to itself
3400 * and creating the Default desktop on it, and then assigning this desktop
3401 * to its main thread, Winlogon.exe basically does the similar steps that
3402 * would have been done automatically at its startup if there were already
3403 * an existing WinSta0 window station and Default desktop.
3404 *
3405 * Of course all this must not be done if we are a SYSTEM or CSRSS thread.
3406 */
3407 // if (pti->ppi->peProcess != gpepCSRSS)
3408 if (!(pti->TIF_flags & (TIF_SYSTEMTHREAD | TIF_CSRSSTHREAD)) &&
3409 pti->ppi->rpdeskStartup == NULL && hDesktop != NULL)
3410 {
3411 ERR("The process 0x%p '%s' didn't have an assigned startup desktop before, assigning it now!\n",
3412 pti->ppi->peProcess, pti->ppi->peProcess->ImageFileName);
3413
3414 pti->ppi->hdeskStartup = hDesktop;
3415 pti->ppi->rpdeskStartup = pdesk;
3416 }
3417
3418 /* free all classes or move them to the shared heap */
3419 if (pti->rpdesk != NULL)
3420 {
3421 if (!IntCheckProcessDesktopClasses(pti->rpdesk, FreeOnFailure))
3422 {
3423 ERR("Failed to move process classes to shared heap!\n");
3424 if (pdesk)
3425 {
3426 DesktopHeapFree(pdesk, pctiNew);
3427 IntUnmapDesktopView(pdesk);
3428 ObDereferenceObject(pdesk);
3429 }
3430 return FALSE;
3431 }
3432 }
3433
3434 pdeskOld = pti->rpdesk;
3435 if (pti->pcti != &pti->cti)
3436 pctiOld = pti->pcti;
3437 else
3438 pctiOld = NULL;
3439
3440 /* do the switch */
3441 if (pdesk != NULL)
3442 {
3443 pti->rpdesk = pdesk;
3444 pti->hdesk = hDesktop;
3445 pti->pDeskInfo = pti->rpdesk->pDeskInfo;
3446 pti->pcti = pctiNew;
3447
3449 pci->pDeskInfo = (PVOID)((ULONG_PTR)pti->pDeskInfo - pci->ulClientDelta);
3450 pci->pClientThreadInfo = (PVOID)((ULONG_PTR)pti->pcti - pci->ulClientDelta);
3451
3452 /* initialize the new pcti */
3453 if (pctiOld != NULL)
3454 {
3455 RtlCopyMemory(pctiNew, pctiOld, sizeof(CLIENTTHREADINFO));
3456 }
3457 else
3458 {
3459 RtlZeroMemory(pctiNew, sizeof(CLIENTTHREADINFO));
3460 pci->fsHooks = pti->fsHooks;
3461 pci->dwTIFlags = pti->TIF_flags;
3462 }
3463 }
3464 else
3465 {
3466 pti->rpdesk = NULL;
3467 pti->hdesk = NULL;
3468 pti->pDeskInfo = NULL;
3469 pti->pcti = &pti->cti; // Always point inside so there will be no crash when posting or sending msg's!
3470 pci->ulClientDelta = 0;
3471 pci->pDeskInfo = NULL;
3472 pci->pClientThreadInfo = NULL;
3473 }
3474
3475 /* clean up the old desktop */
3476 if (pdeskOld != NULL)
3477 {
3478 RemoveEntryList(&pti->PtiLink);
3479 if (pctiOld) DesktopHeapFree(pdeskOld, pctiOld);
3480 IntUnmapDesktopView(pdeskOld);
3481 ObDereferenceObject(pdeskOld);
3482 }
3483
3484 if (pdesk)
3485 {
3486 InsertTailList(&pdesk->PtiList, &pti->PtiLink);
3487 }
3488
3489 TRACE("IntSetThreadDesktop: pti 0x%p ppi 0x%p switched from object 0x%p to 0x%p\n", pti, pti->ppi, pdeskOld, pdesk);
3490
3491 return TRUE;
3492}
3493
3494/*
3495 * NtUserSetThreadDesktop
3496 *
3497 * Status
3498 * @implemented
3499 */
3500
3503{
3504 BOOL ret = FALSE;
3505
3507
3508 // FIXME: IntSetThreadDesktop validates the desktop handle, it should happen
3509 // here too and set the NT error level. Q. Is it necessary to have the validation
3510 // in IntSetThreadDesktop? Is it needed there too?
3511 if (hDesktop || (!hDesktop && PsGetCurrentProcess() == gpepCSRSS))
3512 ret = IntSetThreadDesktop(hDesktop, FALSE);
3513
3514 UserLeave();
3515
3516 return ret;
3517}
3518
3519/* EOF */
static HDC hDC
Definition: 3dtext.c:33
NTSTATUS NTAPI MmUnmapViewInSessionSpace(IN PVOID MappedBase)
Definition: section.c:2738
NTSTATUS NTAPI MmUnmapViewOfSection(IN PEPROCESS Process, IN PVOID BaseAddress)
Definition: section.c:2766
#define CODE_SEG(...)
unsigned char BOOLEAN
Definition: actypes.h:127
#define OBJ_NAME_PATH_SEPARATOR
Definition: arcname_tests.c:25
HWND hWnd
Definition: settings.c:17
LONG NTSTATUS
Definition: precomp.h:26
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
#define UlongToHandle(ul)
Definition: basetsd.h:91
#define HandleToULong(h)
Definition: basetsd.h:89
#define DBG_DEFAULT_CHANNEL(ch)
Definition: debug.h:106
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:616
_Inout_ PFCB _Inout_ PUNICODE_STRING RemainingName
Definition: cdprocs.h:802
Definition: list.h:37
WPARAM wParam
Definition: combotst.c:138
struct @1802 Msg[]
LPARAM lParam
Definition: combotst.c:139
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
PEPROCESS gpepCSRSS
Definition: csr.c:15
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
FORCEINLINE VOID DC_UnlockDc(PDC pdc)
Definition: dc.h:238
COLORREF FASTCALL IntGdiSetTextColor(HDC hDC, COLORREF color)
Definition: dcutil.c:172
@ DCTYPE_DIRECT
Definition: dc.h:41
UINT FASTCALL IntGdiSetTextAlign(HDC hDC, UINT Mode)
Definition: dcutil.c:145
INT FASTCALL IntGdiSetBkMode(HDC hDC, INT backgroundMode)
Definition: dcutil.c:124
HDC FASTCALL IntGdiCreateDisplayDC(HDEV hDev, ULONG DcType, BOOL EmptyDC)
Definition: dclife.c:1063
FORCEINLINE PDC DC_LockDc(HDC hdc)
Definition: dc.h:220
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define ERROR_BUSY
Definition: dderror.h:12
#define ERROR_INVALID_FUNCTION
Definition: dderror.h:6
static CHAR Desktop[MAX_PATH]
Definition: dem.c:256
struct _DESKTOP * PDESKTOP
struct _DESKTOP DESKTOP
static __inline ULONG_PTR DesktopHeapGetUserDelta(VOID)
Definition: desktop.h:274
#define DT_GWL_THREADID
Definition: desktop.h:56
static __inline PVOID DesktopHeapAlloc(IN PDESKTOP Desktop, IN SIZE_T Bytes)
Definition: desktop.h:206
static __inline BOOL DesktopHeapFree(IN PDESKTOP Desktop, IN PVOID lpMem)
Definition: desktop.h:217
#define DT_GWL_PROCESSID
Definition: desktop.h:55
_In_ ULONG Attributes
Definition: dispmprt.h:1077
_In_ HANDLE _In_ CONST PDXGKMDT_OPM_GET_INFO_PARAMETERS Parameters
Definition: dispmprt.h:321
_Check_return_ _In_ D3DDDI_VIDEO_PRESENT_TARGET_ID _In_ PDXGKARG_SYSTEM_DISPLAY_ENABLE_FLAGS _Out_ UINT _Out_ UINT * Height
Definition: dispmprt.h:1445
_Check_return_ _In_ D3DDDI_VIDEO_PRESENT_TARGET_ID _In_ PDXGKARG_SYSTEM_DISPLAY_ENABLE_FLAGS _Out_ UINT * Width
Definition: dispmprt.h:1444
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
NTSTATUS NTAPI RtlGetVersion(IN OUT PRTL_OSVERSIONINFOW lpVersionInformation)
Definition: version.c:182
#define APIENTRY
Definition: api.h:79
#define RTL_CONSTANT_STRING(s)
Definition: combase.c:35
#define wcschr
Definition: compat.h:17
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define PAGE_READONLY
Definition: compat.h:138
#define wcsrchr
Definition: compat.h:16
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
#define lstrlenW
Definition: compat.h:750
_ACRTIMP int __cdecl _scwprintf(const wchar_t *,...)
Definition: wcs.c:1678
_ACRTIMP size_t __cdecl wcslen(const wchar_t *)
Definition: wcs.c:2988
static const WCHAR Message[]
Definition: register.c:74
#define RGB(r, g, b)
Definition: precomp.h:67
#define GetBValue(quad)
Definition: precomp.h:71
#define GetGValue(quad)
Definition: precomp.h:70
#define GetRValue(quad)
Definition: precomp.h:69
return ret
Definition: mutex.c:147
#define L(x)
Definition: resources.c:13
#define InterlockedExchangePointer(Target, Value)
Definition: dshow.h:45
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
UNICODE_STRING * PUNICODE_STRING
Definition: env_spec_w32.h:373
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define NonPagedPool
Definition: env_spec_w32.h:307
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define PagedPool
Definition: env_spec_w32.h:308
#define ERROR(name)
Definition: error_private.h:53
LONG NTAPI KePulseEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:69
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
DWORD dwThreadId
Definition: fdebug.c:31
PsGetCurrentThreadId
Definition: CrNtStubs.h:8
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
PUSER_MESSAGE_QUEUE gpqForeground
Definition: focus.c:13
PTHREADINFO ptiLastInput
Definition: focus.c:18
PUSER_MESSAGE_QUEUE gpqForegroundPrev
Definition: focus.c:14
BOOL APIENTRY GreExtTextOutW(_In_ HDC hDC, _In_ INT XStart, _In_ INT YStart, _In_ UINT fuOptions, _In_opt_ PRECTL lprc, _In_reads_opt_(Count) PCWCH String, _In_ INT Count, _In_opt_ const INT *Dx, _In_ DWORD dwCodePage)
Definition: freetype.c:7215
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
Status
Definition: gdiplustypes.h:24
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLdouble n
Definition: glext.h:7729
GLbitfield flags
Definition: glext.h:7161
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
unsigned int UINT
Definition: sysinfo.c:13
#define ISITHOOKED(HookId)
Definition: hook.h:6
const char cursor[]
Definition: icontest.c:13
PSERVERINFO gpsi
Definition: imm.c:18
#define PROCESS_QUERY_INFORMATION
Definition: pstypes.h:162
#define TIF_CSRSSTHREAD
Definition: ntuser.h:269
#define FNID_DESTROY
Definition: ntuser.h:902
#define FNID_DESKTOP
Definition: ntuser.h:866
#define UserHMGetHandle(obj)
Definition: ntuser.h:233
#define CURSORF_CURRENT
Definition: ntuser.h:1211
struct _DESKTOPINFO DESKTOPINFO
#define FNID_MESSAGEWND
Definition: ntuser.h:868
#define TIF_SYSTEMTHREAD
Definition: ntuser.h:268
#define NB_HOOKS
Definition: ntuser.h:130
#define TIF_DISABLEHOOKS
Definition: ntuser.h:294
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
#define NOTHING
Definition: input_list.c:10
#define NtCurrentTeb
if(dx< 0)
Definition: linetemp.h:194
_In_ BOOL _In_ HANDLE hProcess
Definition: mapping.h:71
LONG_PTR LPARAM
Definition: minwindef.h:175
LONG_PTR LRESULT
Definition: minwindef.h:176
UINT_PTR WPARAM
Definition: minwindef.h:174
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define DESKTOP_ALL_ACCESS
Definition: precomp.h:22
static HBITMAP
Definition: button.c:44
static HDC
Definition: imagelist.c:88
ObjectType
Definition: metafile.c:88
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:115
#define min(a, b)
Definition: monoChain.cc:55
PCURICON_OBJECT FASTCALL UserSetCursor(PCURICON_OBJECT NewCursor, BOOL ForceChange)
Definition: msgqueue.c:93
#define IntReferenceMessageQueue(MsgQueue)
Definition: msgqueue.h:217
#define IntDereferenceMessageQueue(MsgQueue)
Definition: msgqueue.h:220
struct _USER_MESSAGE_QUEUE * PUSER_MESSAGE_QUEUE
#define KernelMode
Definition: asm.h:38
#define UserMode
Definition: asm.h:39
_In_ HANDLE ProcessHandle
Definition: mmfuncs.h:407
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize _Pre_valid_ PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T ViewSize
Definition: mmfuncs.h:412
#define SEC_NO_CHANGE
Definition: mmtypes.h:95
_In_ HANDLE _In_opt_ HANDLE _Out_opt_ PHANDLE _In_ ACCESS_MASK _In_ ULONG HandleAttributes
Definition: obfuncs.h:442
_In_ LPWSTR _In_ DWORD _In_ DWORD _In_ DWORD dwFlags
Definition: netsh.h:141
#define _In_
Definition: no_sal2.h:158
#define PAGE_READWRITE
Definition: nt_native.h:1307
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
ULONG ACCESS_MASK
Definition: nt_native.h:40
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
#define FASTCALL
Definition: nt_native.h:50
#define RTL_REGISTRY_WINDOWS_NT
Definition: nt_native.h:164
#define RTL_QUERY_REGISTRY_DIRECT
Definition: nt_native.h:144
@ ViewUnmap
Definition: nt_native.h:1282
#define MEM_RELEASE
Definition: nt_native.h:1319
#define REG_NONE
Definition: nt_native.h:1495
#define MEM_COMMIT
Definition: nt_native.h:1316
#define HEAP_NO_SERIALIZE
Definition: nt_native.h:1695
#define MAXIMUM_ALLOWED
Definition: nt_native.h:83
#define UNICODE_NULL
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
@ SynchronizationEvent
PVOID NTAPI PsGetProcessWin32Process(PEPROCESS Process)
Definition: process.c:1223
POBJECT_TYPE PsProcessType
Definition: process.c:20
PVOID NTAPI PsGetCurrentProcessWin32Process(VOID)
Definition: process.c:1213
HANDLE NTAPI PsGetCurrentProcessId(VOID)
Definition: process.c:1153
ULONG NTAPI PsGetCurrentProcessSessionId(VOID)
Definition: process.c:1163
PVOID NTAPI PsGetCurrentThreadWin32Thread(VOID)
Definition: thread.c:805
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
#define STATUS_OBJECT_NAME_EXISTS
Definition: ntstatus.h:189
#define STATUS_NAME_TOO_LONG
Definition: ntstatus.h:592
NTSTRSAFEAPI RtlStringCbCopyW(_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cbDest, _In_ NTSTRSAFE_PCWSTR pszSrc)
Definition: ntstrsafe.h:174
NTSTRSAFEAPI RtlStringCchCatW(_Inout_updates_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cchDest, _In_ NTSTRSAFE_PCWSTR pszSrc)
Definition: ntstrsafe.h:601
NTSTRSAFEVAPI RtlStringCbPrintfExW(_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cbDest, _Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PWSTR *ppszDestEnd, _Out_opt_ size_t *pcbRemaining, _In_ STRSAFE_DWORD dwFlags, _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,...)
Definition: ntstrsafe.h:1335
NTSTRSAFEVAPI RtlStringCbPrintfW(_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cbDest, _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,...)
Definition: ntstrsafe.h:1173
NTSTRSAFEVAPI RtlStringCchPrintfW(_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cchDest, _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,...)
Definition: ntstrsafe.h:1110
NTSTRSAFEAPI RtlStringCbCopyNW(_Out_writes_bytes_(cbDest) NTSTRSAFE_PWSTR pszDest, _In_ size_t cbDest, _In_reads_bytes_(cbToCopy) STRSAFE_LPCWSTR pszSrc, _In_ size_t cbToCopy)
Definition: ntstrsafe.h:416
LRESULT FASTCALL IntDefWindowProc(PWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam, BOOL Ansi)
Definition: defwnd.c:633
LRESULT APIENTRY co_HOOK_CallHooks(INT HookId, INT Code, WPARAM wParam, LPARAM lParam)
Definition: hook.c:1102
BOOLEAN FASTCALL co_WinPosSetWindowPos(PWND Window, HWND WndInsertAfter, INT x, INT y, INT cx, INT cy, UINT flags)
Definition: winpos.c:1792
PWINSTATION_OBJECT InputWindowStation
Definition: winsta.c:21
UNICODE_STRING gustrWindowStationsDir
Definition: winsta.c:27
NTSTATUS FASTCALL IntCreateWindowStation(OUT HWINSTA *phWinSta, IN POBJECT_ATTRIBUTES ObjectAttributes, IN KPROCESSOR_MODE AccessMode, IN KPROCESSOR_MODE OwnerMode, IN ACCESS_MASK dwDesiredAccess, DWORD Unknown2, DWORD Unknown3, DWORD Unknown4, DWORD Unknown5, DWORD Unknown6)
Definition: winsta.c:665
HINSTANCE hModClient
Definition: ntuser.c:25
BOOL g_AlwaysDisplayVersion
Definition: ntuser.c:17
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:255
PTHREADINFO gptiCurrent
Definition: ntuser.c:15
VOID FASTCALL UserEnterExclusive(VOID)
Definition: ntuser.c:247
BOOL FASTCALL UserIsEnteredExclusive(VOID)
Definition: ntuser.c:231
NTSTATUS NTAPI ObCloseHandle(IN HANDLE Handle, IN KPROCESSOR_MODE AccessMode)
Definition: obhandle.c:3406
BOOLEAN NTAPI ObFindHandleForObject(IN PEPROCESS Process, IN PVOID Object, IN POBJECT_TYPE ObjectType, IN POBJECT_HANDLE_INFORMATION HandleInformation, OUT PHANDLE Handle)
Definition: obhandle.c:2878
NTSTATUS NTAPI ObOpenObjectByPointer(IN PVOID Object, IN ULONG HandleAttributes, IN PACCESS_STATE PassedAccessState, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PHANDLE Handle)
Definition: obhandle.c:2764
NTSTATUS NTAPI ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, IN PACCESS_STATE PassedAccessState, IN ACCESS_MASK DesiredAccess, IN OUT PVOID ParseContext, OUT PHANDLE Handle)
Definition: obhandle.c:2554
NTSTATUS NTAPI ObCreateObject(IN KPROCESSOR_MODE ProbeMode OPTIONAL, IN POBJECT_TYPE Type, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN KPROCESSOR_MODE AccessMode, IN OUT PVOID ParseContext OPTIONAL, IN ULONG ObjectSize, IN ULONG PagedPoolCharge OPTIONAL, IN ULONG NonPagedPoolCharge OPTIONAL, OUT PVOID *Object)
Definition: oblife.c:1040
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:493
#define LRESULT
Definition: ole.h:14
#define LOWORD(l)
Definition: pedump.c:82
short WCHAR
Definition: pedump.c:58
#define WS_POPUP
Definition: pedump.c:616
#define WS_VISIBLE
Definition: pedump.c:620
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
#define WS_CLIPCHILDREN
Definition: pedump.c:619
VOID NTAPI KeDetachProcess(VOID)
Definition: procobj.c:621
VOID NTAPI KeAttachProcess(IN PKPROCESS Process)
Definition: procobj.c:582
__kernel_entry W32KAPI HDC APIENTRY NtGdiCreateCompatibleDC(_In_opt_ HDC hdc)
__kernel_entry W32KAPI BOOL APIENTRY NtGdiBitBlt(_In_ HDC hdcDst, _In_ INT x, _In_ INT y, _In_ INT cx, _In_ INT cy, _In_opt_ HDC hdcSrc, _In_ INT xSrc, _In_ INT ySrc, _In_ DWORD rop4, _In_ DWORD crBackColor, _In_ FLONG fl)
__kernel_entry W32KAPI HBRUSH APIENTRY NtGdiSelectBrush(_In_ HDC hdc, _In_ HBRUSH hbrush)
__kernel_entry W32KAPI BOOL APIENTRY NtGdiStretchBlt(_In_ HDC hdcDst, _In_ INT xDst, _In_ INT yDst, _In_ INT cxDst, _In_ INT cyDst, _In_opt_ HDC hdcSrc, _In_ INT xSrc, _In_ INT ySrc, _In_ INT cxSrc, _In_ INT cySrc, _In_ DWORD dwRop, _In_ DWORD dwBackColor)
__kernel_entry W32KAPI HBITMAP APIENTRY NtGdiSelectBitmap(_In_ HDC hdc, _In_ HBITMAP hbm)
__kernel_entry W32KAPI BOOL APIENTRY NtGdiPatBlt(_In_ HDC hdcDest, _In_ INT x, _In_ INT y, _In_ INT cx, _In_ INT cy, _In_ DWORD dwRop)
Definition: bitblt.c:988
__kernel_entry W32KAPI BOOL APIENTRY NtGdiDeleteObjectApp(_In_ HANDLE hobj)
__kernel_entry W32KAPI HFONT APIENTRY NtGdiSelectFont(_In_ HDC hdc, _In_ HFONT hf)
Definition: dcobjs.c:597
_In_ INT cchDest
Definition: shlwapi.h:1161
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define OBJ_OPENIF
Definition: winternl.h:229
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define OBJ_INHERIT
Definition: winternl.h:225
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:204
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:104
#define _SEH2_END
Definition: pseh2_64.h:194
#define _SEH2_TRY
Definition: pseh2_64.h:93
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:207
#define IntSysCreateRectpRgnIndirect(prc)
Definition: region.h:93
#define list
Definition: rosglue.h:35
#define __fallthrough
Definition: sal_old.h:314
static __inline NTSTATUS ProbeAndCaptureUnicodeString(OUT PUNICODE_STRING Dest, IN KPROCESSOR_MODE CurrentMode, IN const UNICODE_STRING *UnsafeSrc)
Definition: probe.h:142
static __inline VOID ReleaseCapturedUnicodeString(IN PUNICODE_STRING CapturedString, IN KPROCESSOR_MODE CurrentMode)
Definition: probe.h:239
#define SharedUserData
NTSTATUS NTAPI MmMapViewOfSection(_In_ PVOID SectionObject, _In_ PEPROCESS Process, _Outptr_result_bytebuffer_(*ViewSize) _Pre_opt_valid_ PVOID *BaseAddress, _In_ ULONG_PTR ZeroBits, _In_ SIZE_T CommitSize, _Inout_opt_ PLARGE_INTEGER SectionOffset, _Inout_ PSIZE_T ViewSize, _In_range_(ViewShare, ViewUnmap) SECTION_INHERIT InheritDisposition, _In_ ULONG AllocationType, _In_ ULONG Protect)
Definition: section.c:4031
Entry
Definition: section.c:5216
#define STATUS_SUCCESS
Definition: shellext.h:65
HANDLE gpidLogon
Definition: simplecall.c:15
static void Exit(void)
Definition: sock.c:1330
#define TRACE(s)
Definition: solgame.cpp:4
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
_In_ PVOID Context
Definition: storport.h:2269
Definition: polytest.cpp:41
Definition: window.c:29
ULONG_PTR ulClientDelta
Definition: ntuser.h:330
ULONG fsHooks
Definition: ntuser.h:332
PCLIENTTHREADINFO pClientThreadInfo
Definition: ntuser.h:336
DWORD dwTIFlags
Definition: ntuser.h:328
PDESKTOPINFO pDeskInfo
Definition: ntuser.h:329
Definition: ntuser.h:570
HBRUSH hbrBackground
Definition: ntuser.h:591
ULONG CURSORF_flags
Definition: cursoricon.h:16
WCHAR szDesktopName[1]
Definition: ntuser.h:161
LIST_ENTRY aphkStart[NB_HOOKS]
Definition: ntuser.h:142
struct _WND * spwnd
Definition: ntuser.h:140
PVOID pvDesktopLimit
Definition: ntuser.h:139
PVOID pvDesktopBase
Definition: ntuser.h:138
PVOID hsectionDesktop
Definition: desktop.h:22
struct _USER_MESSAGE_QUEUE * ActiveMessageQueue
Definition: desktop.h:38
LIST_ENTRY PtiList
Definition: desktop.h:25
LIST_ENTRY ListEntry
Definition: desktop.h:9
struct _WINSTATION_OBJECT * rpwinstaParent
Definition: desktop.h:11
LIST_ENTRY ShellHookWindows
Definition: desktop.h:43
PWIN32HEAP pheapDesktop
Definition: desktop.h:23
PWND spwndMessage
Definition: desktop.h:20
HWND DesktopWindow
Definition: desktop.h:40
PDESKTOPINFO pDeskInfo
Definition: desktop.h:8
DWORD dwSessionId
Definition: desktop.h:6
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
LONG HighPart
DWORD LowPart
HDEV hDev
Definition: monitor.h:23
GENERIC_MAPPING GenericMapping
Definition: obtypes.h:379
ULONG DefaultNonPagedPoolCharge
Definition: obtypes.h:386
OBJECT_TYPE_INITIALIZER TypeInfo
Definition: obtypes.h:411
WCHAR szCSDVersion[128]
Definition: rtltypes.h:274
ULONG dwOSVersionInfoSize
Definition: rtltypes.h:269
ULONG dwBuildNumber
Definition: rtltypes.h:272
LPCWSTR lpstr
Definition: wingdi.h:3010
UINT n
Definition: wingdi.h:3009
HWINSTA hwinsta
Definition: win32.h:269
HDESK hdeskStartup
Definition: win32.h:265
W32HEAP_USER_MAPPING HeapMappings
Definition: win32.h:292
struct _DESKTOP * rpdeskStartup
Definition: win32.h:260
struct _WINSTATION_OBJECT * prpwinsta
Definition: win32.h:268
Definition: region.h:8
LIST_ENTRY ListEntry
Definition: desktop.h:69
LONG cx
Definition: kdterminal.h:27
LONG cy
Definition: kdterminal.h:28
WALLPAPER_MODE WallpaperMode
Definition: sysparams.h:144
NONCLIENTMETRICSW ncm
Definition: sysparams.h:51
ULONG cxWallpaper
Definition: sysparams.h:143
ULONG cyWallpaper
Definition: sysparams.h:143
HANDLE hbmWallpaper
Definition: sysparams.h:142
struct _DESKTOP * rpdesk
Definition: ntuser.h:197
PPROCESSINFO ppi
Definition: win32.h:89
struct _DESKTOPINFO * pDeskInfo
Definition: win32.h:94
ULONG fsHooks
Definition: win32.h:118
CLIENTTHREADINFO cti
Definition: win32.h:145
struct _CLIENTINFO * pClientInfo
Definition: win32.h:95
HDESK hdesk
Definition: win32.h:109
struct _CLIENTTHREADINFO * pcti
Definition: win32.h:92
FLONG TIF_flags
Definition: win32.h:96
struct _DESKTOP * rpdesk
Definition: win32.h:93
LIST_ENTRY WindowListHead
Definition: win32.h:156
struct _USER_MESSAGE_QUEUE * MessageQueue
Definition: win32.h:90
LIST_ENTRY PtiLink
Definition: win32.h:127
USHORT MaximumLength
Definition: env_spec_w32.h:370
struct _DESKTOP * Desktop
Definition: msgqueue.h:50
struct _W32HEAP_USER_MAPPING * Next
Definition: win32.h:200
ULONG_PTR Limit
Definition: win32.h:203
UINT flags
Definition: winuser.h:3702
struct _DESKTOP * ActiveDesktop
Definition: winsta.h:42
DWORD dwSessionId
Definition: winsta.h:17
LIST_ENTRY DesktopListHead
Definition: winsta.h:19
Definition: ntuser.h:698
PCLS pcls
Definition: ntuser.h:724
THRDESKHEAD head
Definition: ntuser.h:699
DWORD style
Definition: ntuser.h:710
DWORD fnid
Definition: ntuser.h:713
RECT rcWindow
Definition: ntuser.h:720
LPCWSTR lpszClass
Definition: winuser.h:3073
LPCWSTR lpszName
Definition: winuser.h:3072
HINSTANCE hInstance
Definition: winuser.h:3064
LONG right
Definition: windef.h:108
LONG bottom
Definition: windef.h:109
LONG top
Definition: windef.h:107
LONG left
Definition: windef.h:106
ATOM atomSysClass[ICLS_NOTUSED+1]
Definition: ntuser.h:1064
UINT uiShellMsg
Definition: ntuser.h:1067
#define max(a, b)
Definition: svc.c:63
@ wmFill
Definition: sysparams.h:45
@ wmTile
Definition: sysparams.h:42
@ wmStretch
Definition: sysparams.h:43
@ wmFit
Definition: sysparams.h:44
#define WINVER
Definition: targetver.h:11
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1829
uint16_t * PWSTR
Definition: typedefs.h:56
#define MAXULONG
Definition: typedefs.h:251
const uint16_t * LPCWSTR
Definition: typedefs.h:57
unsigned char * PBOOLEAN
Definition: typedefs.h:53
#define NTAPI
Definition: typedefs.h:36
void * PVOID
Definition: typedefs.h:50
ULONG_PTR SIZE_T
Definition: typedefs.h:80
int32_t INT
Definition: typedefs.h:58
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define MAXUSHORT
Definition: typedefs.h:83
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
uint16_t * PWCHAR
Definition: typedefs.h:56
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define HIWORD(l)
Definition: typedefs.h:247
#define OUT
Definition: typedefs.h:40
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
#define ALIGN_UP(size, type)
Definition: umtypes.h:91
#define WC_DESKTOP
Definition: undocuser.h:12
HDC FASTCALL IntBeginPaint(PWND Window, PPAINTSTRUCT Ps)
Definition: painting.c:1443
BOOL FASTCALL co_UserRedrawWindow(PWND Window, const RECTL *UpdateRect, PREGION UpdateRgn, ULONG Flags)
Definition: painting.c:897
BOOL FASTCALL IntEndPaint(PWND Wnd, PPAINTSTRUCT Ps)
Definition: painting.c:1539
VOID FASTCALL IntInvalidateWindows(PWND Wnd, PREGION Rgn, ULONG Flags)
Definition: painting.c:645
RTL_ATOM FASTCALL IntAddAtom(LPWSTR AtomName)
Definition: useratom.c:13
PWND FASTCALL UserGetWindowObject(HWND hWnd)
Definition: window.c:123
PWND FASTCALL IntGetWindowObject(HWND hWnd)
Definition: window.c:75
HDC FASTCALL UserGetWindowDC(PWND Wnd)
Definition: windc.c:947
BOOLEAN co_UserDestroyWindow(PVOID Object)
Definition: window.c:2857
PWIN32HEAP UserCreateHeap(OUT PVOID *SectionObject, IN OUT PVOID *SystemBase, IN SIZE_T HeapSize)
Definition: usrheap.c:181
static __inline PVOID UserHeapAlloc(SIZE_T Bytes)
Definition: usrheap.h:34
static __inline BOOL UserHeapFree(PVOID lpMem)
Definition: usrheap.h:44
_Must_inspect_result_ _In_ WDFCOLLECTION _In_ WDFOBJECT Object
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2664
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4539
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
POBJECT_TYPE ExDesktopObjectType
Definition: win32k.c:22
POBJECT_TYPE ExWindowStationObjectType
Definition: win32k.c:21
VOID FASTCALL SetLastNtError(_In_ NTSTATUS Status)
Definition: error.c:30
HFONT FASTCALL GreCreateFontIndirectW(_In_ const LOGFONTW *lplf)
Definition: font.c:30
BOOL NTAPI GreDeleteObject(HGDIOBJ hobj)
Definition: gdiobj.c:1158
HGDIOBJ StockObjects[]
Definition: stockobj.c:100
FORCEINLINE VOID RECTL_vOffsetRect(_Inout_ RECTL *prcl, _In_ INT cx, _In_ INT cy)
Definition: rect.h:31
VOID FASTCALL REGION_Delete(PREGION pRgn)
Definition: region.c:2449
BOOL FASTCALL GreGetTextExtentW(_In_ HDC hDC, _In_reads_(cwc) PCWCH lpwsz, _In_ INT cwc, _Out_ PSIZE psize, _In_ UINT flOpts)
Definition: text.c:77
BOOL IntCheckProcessDesktopClasses(IN PDESKTOP Desktop, IN BOOL FreeOnFailure)
Definition: class.c:1017
PCLS IntGetAndReferenceClass(PUNICODE_STRING ClassName, HINSTANCE hInstance, BOOL bDesktopThread)
Definition: class.c:1450
BOOL FASTCALL UserRegisterSystemClasses(VOID)
Definition: class.c:2337
PCURICON_OBJECT FASTCALL UserGetCurIconObject(HCURSOR hCurIcon)
Definition: cursoricon.c:200
static NTSTATUS IntMapDesktopView(IN PDESKTOP pdesk)
Definition: desktop.c:3236
HDESK APIENTRY NtUserOpenInputDesktop(DWORD dwFlags, BOOL fInherit, ACCESS_MASK dwDesiredAccess)
Definition: desktop.c:2722
BOOL APIENTRY NtUserCloseDesktop(HDESK hDesktop)
Definition: desktop.c:2762
PDESKTOP FASTCALL IntGetActiveDesktop(VOID)
Definition: desktop.c:1290
DWORD gdwDesktopSectionSize
Definition: desktop.c:46
PTHREADINFO gptiDesktopThread
Definition: desktop.c:53
BOOL APIENTRY NtUserSetThreadDesktop(HDESK hDesktop)
Definition: desktop.c:3502
HCURSOR gDesktopCursor
Definition: desktop.c:54
PKEVENT gpDesktopSwitchEvent
WinSta0_DesktopSwitch legacy (NT 3.5+) event.
Definition: desktop.c:56
HDESK APIENTRY NtUserOpenDesktop(POBJECT_ATTRIBUTES ObjectAttributes, DWORD dwFlags, ACCESS_MASK dwDesiredAccess)
Definition: desktop.c:2628
NTSTATUS FASTCALL IntCreateDesktop(OUT HDESK *phDesktop, IN POBJECT_ATTRIBUTES ObjectAttributes, IN KPROCESSOR_MODE AccessMode, IN PUNICODE_STRING lpszDesktopDevice OPTIONAL, IN LPDEVMODEW lpdmw OPTIONAL, IN DWORD dwFlags, IN ACCESS_MASK dwDesiredAccess)
Definition: desktop.c:2391
HWND FASTCALL IntGetCurrentThreadDesktopWindow(VOID)
Definition: desktop.c:1447
NTSTATUS NTAPI IntDesktopOkToClose(_In_ PVOID Parameters)
Definition: desktop.c:210
NTSTATUS NTAPI InitDesktopImpl(VOID)
Definition: desktop.c:276
VOID APIENTRY UserRedrawDesktop(VOID)
Definition: desktop.c:1619
PKEVENT gpDesktopThreadStartedEvent
Definition: desktop.c:55
HDC ScreenDeviceContext
Definition: desktop.c:52
PWND FASTCALL UserGetDesktopWindow(VOID)
Definition: desktop.c:1413
BOOL IntDeRegisterShellHookWindow(HWND hWnd)
Definition: desktop.c:1806
HWND FASTCALL IntGetMessageWindow(VOID)
Definition: desktop.c:1425
NTSTATUS FASTCALL IntHideDesktop(PDESKTOP Desktop)
Definition: desktop.c:1655
VOID NTAPI DesktopThreadMain(VOID)
Definition: desktop.c:1566
HDESK UserOpenInputDesktop(DWORD dwFlags, BOOL fInherit, ACCESS_MASK dwDesiredAccess)
Definition: desktop.c:2657
HDESK FASTCALL IntGetDesktopObjectHandle(PDESKTOP DesktopObject)
Definition: desktop.c:1299
HDESK APIENTRY NtUserGetThreadDesktop(DWORD dwThreadId, HDESK hConsoleDesktop)
Definition: desktop.c:3083
VOID FASTCALL IntSetFocusMessageQueue(PUSER_MESSAGE_QUEUE NewQueue)
Definition: desktop.c:1347
NTSTATUS FASTCALL co_IntShowDesktop(PDESKTOP Desktop, ULONG Width, ULONG Height, BOOL bRedraw)
Definition: desktop.c:1637
HWND FASTCALL IntGetDesktopWindow(VOID)
Definition: desktop.c:1402
NTSTATUS NTAPI IntDesktopObjectClose(_In_ PVOID Parameters)
Definition: desktop.c:251
BOOL IntRegisterShellHookWindow(HWND hWnd)
Definition: desktop.c:1774
NTSTATUS FASTCALL IntValidateDesktopHandle(HDESK Desktop, KPROCESSOR_MODE AccessMode, ACCESS_MASK DesiredAccess, PDESKTOP *Object)
Definition: desktop.c:1265
DWORD gdwNOIOSectionSize
Definition: desktop.c:48
static VOID IntFreeDesktopHeap(IN PDESKTOP pdesk)
PUSER_MESSAGE_QUEUE FASTCALL IntGetFocusMessageQueue(VOID)
Definition: desktop.c:1335
HDESK NTAPI NtUserResolveDesktop(IN HANDLE ProcessHandle, IN PUNICODE_STRING DesktopPath, IN BOOL bInherit, OUT HWINSTA *phWinSta)
Definition: desktop.c:2869
NTSTATUS APIENTRY IntDesktopObjectParse(IN PVOID ParseObject, IN PVOID ObjectType, IN OUT PACCESS_STATE AccessState, IN KPROCESSOR_MODE AccessMode, IN ULONG Attributes, IN OUT PUNICODE_STRING CompleteName, IN OUT PUNICODE_STRING RemainingName, IN OUT PVOID Context OPTIONAL, IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL, OUT PVOID *Object)
Definition: desktop.c:63
BOOL APIENTRY NtUserPaintDesktop(HDC hDC)
Definition: desktop.c:2819
BOOL FASTCALL DesktopWindowProc(PWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT *lResult)
Definition: desktop.c:1462
VOID co_IntShellHookNotify(WPARAM Message, WPARAM wParam, LPARAM lParam)
Definition: desktop.c:1712
BOOL APIENTRY NtUserSwitchDesktop(HDESK hdesk)
Definition: desktop.c:2976
NTSTATUS FASTCALL IntResolveDesktop(IN PEPROCESS Process, IN PUNICODE_STRING DesktopPath, IN BOOL bInherit, OUT HWINSTA *phWinSta, OUT HDESK *phDesktop)
Definition: desktop.c:575
BOOL FASTCALL IntPaintDesktop(HDC hDC)
Definition: desktop.c:1857
PWND FASTCALL IntGetThreadDesktopWindow(PTHREADINFO pti)
Definition: desktop.c:1387
static NTSTATUS GetSystemVersionString(OUT PWSTR pwszzVersion, IN SIZE_T cchDest, IN BOOLEAN InSafeMode, IN BOOLEAN AppendNtSystemRoot)
Definition: desktop.c:307
BOOL FASTCALL UserMessageWindowProc(PWND pwnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT *lResult)
Definition: desktop.c:1545
HANDLE ghDesktopSwitchEvent
WinSta0_DesktopSwitch handle in the CSRSS process.
Definition: desktop.c:57
NTSTATUS NTAPI IntDesktopObjectOpen(_In_ PVOID Parameters)
Definition: desktop.c:234
DWORD gdwWinlogonSectionSize
Definition: desktop.c:49
HDC FASTCALL UserGetDesktopDC(ULONG DcType, BOOL bAltDc, BOOL ValidatehWnd)
Definition: desktop.c:1594
NTSTATUS NTAPI IntDesktopObjectDelete(_In_ PVOID Parameters)
Definition: desktop.c:179
HDESK APIENTRY NtUserCreateDesktop(POBJECT_ATTRIBUTES ObjectAttributes, PUNICODE_STRING lpszDesktopDevice, LPDEVMODEW lpdmw, DWORD dwFlags, ACCESS_MASK dwDesiredAccess)
Definition: desktop.c:2569
PDESKTOP gpdeskInputDesktop
Currently active desktop.
Definition: desktop.c:51
BOOL IntSetThreadDesktop(IN HDESK hDesktop, IN BOOL FreeOnFailure)
Definition: desktop.c:3310
static HWND *FASTCALL UserBuildShellHookHwndList(PDESKTOP Desktop)
Definition: desktop.c:1671
PWND FASTCALL UserGetMessageWindow(VOID)
Definition: desktop.c:1436
static NTSTATUS IntUnmapDesktopView(IN PDESKTOP pdesk)
Definition: desktop.c:3192
static NTSTATUS UserInitializeDesktop(PDESKTOP pdesk, PUNICODE_STRING DesktopName, PWINSTATION_OBJECT pwinsta)
Definition: desktop.c:2282
PWND FASTCALL co_GetDesktopWindow(PWND pWnd)
Definition: desktop.c:1394
VOID FASTCALL IntNotifyWinEvent(DWORD Event, PWND pWnd, LONG idObject, LONG idChild, DWORD flags)
Definition: event.c:178
LRESULT FASTCALL IntDispatchMessage(PMSG pMsg)
Definition: message.c:890
BOOL FASTCALL UserPostMessage(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam)
Definition: message.c:1395
BOOL APIENTRY co_IntGetPeekMessage(PMSG pMsg, HWND hWnd, UINT MsgFilterMin, UINT MsgFilterMax, UINT RemoveMsg, BOOL bGMSG)
Definition: message.c:1226
LONG NTAPI UserGetSystemMetrics(ULONG Index)
Definition: metric.c:209
NTSTATUS GetProcessLuid(IN PETHREAD Thread OPTIONAL, IN PEPROCESS Process OPTIONAL, OUT PLUID Luid)
Definition: misc.c:814
PTHREADINFO FASTCALL IntTID2PTI(HANDLE id)
Definition: misc.c:41
PMONITOR NTAPI UserGetPrimaryMonitor(VOID)
Definition: monitor.c:102
BOOL FASTCALL UserDereferenceObject(PVOID Object)
Definition: object.c:647
NTSTATUS NTAPI IntAssignDesktopSecurityOnParse(_In_ PWINSTATION_OBJECT WinSta, _In_ PDESKTOP Desktop, _In_ PACCESS_STATE AccessState)
Assigns a security descriptor to the desktop object during a desktop object parse procedure.
Definition: security.c:270
NTSTATUS NTAPI IntCreateServiceSecurity(_Out_ PSECURITY_DESCRIPTOR *ServiceSd)
Creates a security descriptor for the service.
Definition: security.c:327
VOID IntFreeSecurityBuffer(_In_ PVOID Buffer)
Frees an allocated security buffer from UM memory that is been previously allocated by IntAllocateSec...
Definition: security.c:133
#define DESKTOP_WRITE
Definition: security.h:19
#define DESKTOP_EXECUTE
Definition: security.h:27
#define DESKTOP_READ
Definition: security.h:15
BOOL g_PaintDesktopVersion
Definition: sysparams.c:19
SPIVALUES gspv
Definition: sysparams.c:17
BOOL FASTCALL UserSystemParametersInfo(UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni)
Definition: sysparams.c:2123
#define TAG_WINSTA
Definition: tags.h:11
#define USERTAG_EVENT
Definition: tags.h:230
#define USERTAG_WINDOWLIST
Definition: tags.h:298
LONG FASTCALL co_UserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi)
Definition: window.c:4025
PWND FASTCALL IntCreateWindow(CREATESTRUCTW *Cs, PLARGE_STRING WindowName, PCLS Class, PWND ParentWindow, PWND OwnerWindow, PVOID acbiBuffer, PDESKTOP pdeskCreated, DWORD dwVer)
Definition: window.c:1805
#define WSS_LOCKED
Definition: winsta.h:7
struct _WINSTATION_OBJECT * PWINSTATION_OBJECT
#define WSS_NOIO
Definition: winsta.h:9
#define OBJID_WINDOW
Definition: winable.h:15
#define CHILDID_SELF
Definition: winable.h:14
SIZE_T WINAPI HeapSize(HANDLE, DWORD, LPCVOID)
#define MAKEINTATOM(i)
Definition: winbase.h:1198
ENGAPI ULONG APIENTRY EngGetLastError(VOID)
Definition: error.c:9
ENGAPI INT APIENTRY EngMulDiv(_In_ INT a, _In_ INT b, _In_ INT c)
Definition: math.c:26
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:21
DWORD COLORREF
Definition: windef.h:100
HICON HCURSOR
Definition: windef.h:99
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
#define ERROR_INVALID_WINDOW_HANDLE
Definition: winerror.h:1226
#define TA_RIGHT
Definition: wingdi.h:933
#define TA_LEFT
Definition: wingdi.h:932
#define TRANSPARENT
Definition: wingdi.h:950
#define CLR_INVALID
Definition: wingdi.h:883
#define SRCCOPY
Definition: wingdi.h:333
#define PATCOPY
Definition: wingdi.h:335
#define BLACK_BRUSH
Definition: wingdi.h:896
#define TA_TOP
Definition: wingdi.h:930
#define TA_BOTTOM
Definition: wingdi.h:929
#define TA_CENTER
Definition: wingdi.h:931
#define WM_PAINT
Definition: winuser.h:1648
#define WM_ERASEBKGND
Definition: winuser.h:1653
#define WM_CLOSE
Definition: winuser.h:1649
#define SWP_NOACTIVATE
Definition: winuser.h:1253
#define SWP_NOREDRAW
Definition: winuser.h:1257
#define SM_CYVIRTUALSCREEN
Definition: winuser.h:1050
#define SM_CYSCREEN
Definition: winuser.h:971
#define WM_WINDOWPOSCHANGING
Definition: winuser.h:1689
#define WM_CREATE
Definition: winuser.h:1636
#define WH_SHELL
Definition: winuser.h:40
#define RDW_UPDATENOW
Definition: winuser.h:1231
#define RDW_ERASE
Definition: winuser.h:1222
#define WM_SYSCOLORCHANGE
Definition: winuser.h:1654
#define WM_NCCREATE
Definition: winuser.h:1711
#define SM_CXVIRTUALSCREEN
Definition: winuser.h:1049
#define RDW_ALLCHILDREN
Definition: winuser.h:1232
#define PM_REMOVE
Definition: winuser.h:1207
#define RDW_FRAME
Definition: winuser.h:1223
#define SWP_SHOWWINDOW
Definition: winuser.h:1259
#define WM_SETCURSOR
Definition: winuser.h:1664
#define SM_CLEANBOOT
Definition: winuser.h:1038
#define WM_DESTROY
Definition: winuser.h:1637
#define SM_CXSCREEN
Definition: winuser.h:970
struct _WINDOWPOS * PWINDOWPOS
#define SM_XVIRTUALSCREEN
Definition: winuser.h:1047
#define SWP_NOZORDER
Definition: winuser.h:1258
#define RDW_INVALIDATE
Definition: winuser.h:1225
#define SM_YVIRTUALSCREEN
Definition: winuser.h:1048
_In_ PVOID _Out_opt_ PULONG_PTR _Outptr_opt_ PCUNICODE_STRING * ObjectName
Definition: cmfuncs.h:64
#define EVENT_INCREMENT
Definition: iotypes.h:597
#define IO_NO_INCREMENT
Definition: iotypes.h:598
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
_In_ PEPROCESS _In_ KPROCESSOR_MODE AccessMode
Definition: mmfuncs.h:396
_In_ ACCESS_MASK _In_opt_ POBJECT_TYPE _In_ KPROCESSOR_MODE _Out_ PVOID _Out_opt_ POBJECT_HANDLE_INFORMATION HandleInformation
Definition: obfuncs.h:44
#define ObDereferenceObject
Definition: obfuncs.h:203
#define ObReferenceObject
Definition: obfuncs.h:204
#define DUPLICATE_SAME_ACCESS
#define PsGetCurrentProcess
Definition: psfuncs.h:17
#define RtlEqualLuid(Luid1, Luid2)
Definition: rtlfuncs.h:304
_In_opt_ PVOID _In_opt_ PUNICODE_STRING _In_ PSECURITY_DESCRIPTOR _In_ PACCESS_STATE AccessState
Definition: sefuncs.h:417
#define SYSTEM_LUID
Definition: setypes.h:700
#define ZwCurrentProcess()