ReactOS 0.4.16-dev-303-g11d5cb8
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
51/* Currently active desktop */
57
58/* OBJECT CALLBACKS **********************************************************/
59
67 IN OUT PUNICODE_STRING CompleteName,
72{
76 PLIST_ENTRY NextEntry, ListHead;
77 PWINSTATION_OBJECT WinStaObject = (PWINSTATION_OBJECT)ParseObject;
78 UNICODE_STRING DesktopName;
79 PBOOLEAN pContext = (PBOOLEAN) Context;
80
81 if (pContext)
82 *pContext = FALSE;
83
84 /* Set the list pointers and loop the window station */
85 ListHead = &WinStaObject->DesktopListHead;
86 NextEntry = ListHead->Flink;
87 while (NextEntry != ListHead)
88 {
89 /* Get the current desktop */
90 Desktop = CONTAINING_RECORD(NextEntry, DESKTOP, ListEntry);
91
92 /* Get the desktop name */
93 ASSERT(Desktop->pDeskInfo != NULL);
94 RtlInitUnicodeString(&DesktopName, Desktop->pDeskInfo->szDesktopName);
95
96 /* Compare the name */
98 &DesktopName,
100 {
101 /* We found a match. Did this come from a create? */
102 if (Context)
103 {
104 /* Unless OPEN_IF was given, fail with an error */
105 if (!(Attributes & OBJ_OPENIF))
106 {
107 /* Name collision */
109 }
110 else
111 {
112 /* Otherwise, return with a warning only */
114 }
115 }
116 else
117 {
118 /* This was a real open, so this is OK */
120 }
121
122 /* Reference the desktop and return it */
124 *Object = Desktop;
125 return Status;
126 }
127
128 /* Go to the next desktop */
129 NextEntry = NextEntry->Flink;
130 }
131
132 /* If we got here but this isn't a create, just fail */
134
135 /* Create the desktop object */
141 NULL,
142 sizeof(DESKTOP),
143 0,
144 0,
145 (PVOID*)&Desktop);
146 if (!NT_SUCCESS(Status)) return Status;
147
148 /* Assign security to the desktop we have created */
150 if (!NT_SUCCESS(Status))
151 {
153 return Status;
154 }
155
156 /* Initialize the desktop */
158 if (!NT_SUCCESS(Status))
159 {
161 return Status;
162 }
163
164 /* Set the desktop object and return success */
165 *Object = Desktop;
166 *pContext = TRUE;
167 return STATUS_SUCCESS;
168}
169
171NTAPI
174{
176 PDESKTOP pdesk = (PDESKTOP)DeleteParameters->Object;
177
178 TRACE("Deleting desktop object 0x%p\n", pdesk);
179
180 if (pdesk->pDeskInfo &&
181 pdesk->pDeskInfo->spwnd)
182 {
183 ASSERT(pdesk->pDeskInfo->spwnd->spwndChild == NULL);
185 }
186
187 if (pdesk->spwndMessage)
189
190 /* Remove the desktop from the window station's list of associated desktops */
191 RemoveEntryList(&pdesk->ListEntry);
192
193 /* Free the heap */
194 IntFreeDesktopHeap(pdesk);
195
197
198 return STATUS_SUCCESS;
199}
200
202NTAPI
205{
208
209 if (pti == NULL)
210 {
211 /* This happens when we leak desktop handles */
212 return STATUS_SUCCESS;
213 }
214
215 /* Do not allow the current desktop or the initial desktop to be closed */
216 if (OkToCloseParameters->Handle == pti->ppi->hdeskStartup ||
217 OkToCloseParameters->Handle == pti->hdesk)
218 {
220 }
221
222 return STATUS_SUCCESS;
223}
224
226NTAPI
229{
230 NTSTATUS Ret;
232 PPROCESSINFO ppi = PsGetProcessWin32Process(OpenParameters->Process);
233 if (ppi == NULL)
234 return STATUS_SUCCESS;
235
237 Ret = IntMapDesktopView((PDESKTOP)OpenParameters->Object);
238 UserLeave();
239 return Ret;
240}
241
243NTAPI
246{
247 NTSTATUS Ret;
249 PPROCESSINFO ppi = PsGetProcessWin32Process(CloseParameters->Process);
250 if (ppi == NULL)
251 {
252 /* This happens when the process leaks desktop handles.
253 * At this point the PPROCESSINFO is already destroyed */
254 return STATUS_SUCCESS;
255 }
256
258 Ret = IntUnmapDesktopView((PDESKTOP)CloseParameters->Object);
259 UserLeave();
260 return Ret;
261}
262
263
264/* PRIVATE FUNCTIONS **********************************************************/
265
266CODE_SEG("INIT")
268NTAPI
270{
271 GENERIC_MAPPING IntDesktopMapping = { DESKTOP_READ,
275
276 /* Set Desktop Object Attributes */
278 ExDesktopObjectType->TypeInfo.GenericMapping = IntDesktopMapping;
280
281 /* Allocate memory for the event structure */
283 sizeof(KEVENT),
286 {
287 ERR("Failed to allocate event!\n");
288 return STATUS_NO_MEMORY;
289 }
290
291 /* Initialize the kernel event */
294 FALSE);
295
296 return STATUS_SUCCESS;
297}
298
299static NTSTATUS
301 IN SIZE_T cchDest,
302 IN BOOLEAN InSafeMode,
303 IN BOOLEAN AppendNtSystemRoot)
304{
306
307 RTL_OSVERSIONINFOEXW VerInfo;
308 UNICODE_STRING BuildLabString;
309 UNICODE_STRING CSDVersionString;
310 RTL_QUERY_REGISTRY_TABLE VersionConfigurationTable[] =
311 {
312 {
313 NULL,
315 L"BuildLab",
316 &BuildLabString,
317 REG_NONE, NULL, 0
318 },
319 {
320 NULL,
322 L"CSDVersion",
323 &CSDVersionString,
324 REG_NONE, NULL, 0
325 },
326
327 {0}
328 };
329
330 WCHAR BuildLabBuffer[256];
331 WCHAR VersionBuffer[256];
332 PWCHAR EndBuffer;
333
334 VerInfo.dwOSVersionInfoSize = sizeof(VerInfo);
335
336 /*
337 * This call is uniquely used to retrieve the current CSD numbers.
338 * All the rest (major, minor, ...) is either retrieved from the
339 * SharedUserData structure, or from the registry.
340 */
342
343 /*
344 * - Retrieve the BuildLab string from the registry (set by the kernel).
345 * - In kernel-mode, szCSDVersion is not initialized. Initialize it
346 * and query its value from the registry.
347 */
348 RtlZeroMemory(BuildLabBuffer, sizeof(BuildLabBuffer));
349 RtlInitEmptyUnicodeString(&BuildLabString,
350 BuildLabBuffer,
351 sizeof(BuildLabBuffer));
352 RtlZeroMemory(VerInfo.szCSDVersion, sizeof(VerInfo.szCSDVersion));
353 RtlInitEmptyUnicodeString(&CSDVersionString,
354 VerInfo.szCSDVersion,
355 sizeof(VerInfo.szCSDVersion));
357 L"",
358 VersionConfigurationTable,
359 NULL,
360 NULL);
361 if (!NT_SUCCESS(Status))
362 {
363 /* Indicate nothing is there */
364 BuildLabString.Length = 0;
365 CSDVersionString.Length = 0;
366 }
367 /* NULL-terminate the strings */
368 BuildLabString.Buffer[BuildLabString.Length / sizeof(WCHAR)] = UNICODE_NULL;
369 CSDVersionString.Buffer[CSDVersionString.Length / sizeof(WCHAR)] = UNICODE_NULL;
370
371 EndBuffer = VersionBuffer;
372 if ( /* VerInfo.wServicePackMajor != 0 && */ CSDVersionString.Length)
373 {
374 /* Print the version string */
375 Status = RtlStringCbPrintfExW(VersionBuffer,
376 sizeof(VersionBuffer),
377 &EndBuffer,
378 NULL,
379 0,
380 L": %wZ",
381 &CSDVersionString);
382 if (!NT_SUCCESS(Status))
383 {
384 /* No version, NULL-terminate the string */
385 *EndBuffer = UNICODE_NULL;
386 }
387 }
388 else
389 {
390 /* No version, NULL-terminate the string */
391 *EndBuffer = UNICODE_NULL;
392 }
393
394 if (InSafeMode)
395 {
396 /* String for Safe Mode */
397 Status = RtlStringCchPrintfW(pwszzVersion,
398 cchDest,
399 L"ReactOS Version %S %wZ (NT %u.%u Build %u%s)\n",
400 KERNEL_VERSION_STR,
401 &BuildLabString,
402 SharedUserData->NtMajorVersion,
403 SharedUserData->NtMinorVersion,
404 (VerInfo.dwBuildNumber & 0xFFFF),
405 VersionBuffer);
406
407 if (AppendNtSystemRoot && NT_SUCCESS(Status))
408 {
409 Status = RtlStringCbPrintfW(VersionBuffer,
410 sizeof(VersionBuffer),
411 L" - %s\n",
412 SharedUserData->NtSystemRoot);
413 if (NT_SUCCESS(Status))
414 {
415 /* Replace the last newline by a NULL, before concatenating */
416 EndBuffer = wcsrchr(pwszzVersion, L'\n');
417 if (EndBuffer) *EndBuffer = UNICODE_NULL;
418
419 /* The concatenated string has a terminating newline */
420 Status = RtlStringCchCatW(pwszzVersion,
421 cchDest,
422 VersionBuffer);
423 if (!NT_SUCCESS(Status))
424 {
425 /* Concatenation failed, put back the newline */
426 if (EndBuffer) *EndBuffer = L'\n';
427 }
428 }
429
430 /* Override any failures as the NtSystemRoot string is optional */
432 }
433 }
434 else
435 {
436 /* Multi-string for Normal Mode */
437 Status = RtlStringCchPrintfW(pwszzVersion,
438 cchDest,
439 L"ReactOS Version %S\n"
440 L"Build %wZ\n"
441 L"Reporting NT %u.%u (Build %u%s)\n",
442 KERNEL_VERSION_STR,
443 &BuildLabString,
444 SharedUserData->NtMajorVersion,
445 SharedUserData->NtMinorVersion,
446 (VerInfo.dwBuildNumber & 0xFFFF),
447 VersionBuffer);
448
449 if (AppendNtSystemRoot && NT_SUCCESS(Status))
450 {
451 Status = RtlStringCbPrintfW(VersionBuffer,
452 sizeof(VersionBuffer),
453 L"%s\n",
454 SharedUserData->NtSystemRoot);
455 if (NT_SUCCESS(Status))
456 {
457 Status = RtlStringCchCatW(pwszzVersion,
458 cchDest,
459 VersionBuffer);
460 }
461
462 /* Override any failures as the NtSystemRoot string is optional */
464 }
465 }
466
467 if (!NT_SUCCESS(Status))
468 {
469 /* Fall-back string */
470 Status = RtlStringCchPrintfW(pwszzVersion,
471 cchDest,
472 L"ReactOS Version %S %wZ\n",
473 KERNEL_VERSION_STR,
474 &BuildLabString);
475 if (!NT_SUCCESS(Status))
476 {
477 /* General failure, NULL-terminate the string */
478 pwszzVersion[0] = UNICODE_NULL;
479 }
480 }
481
482 /*
483 * Convert the string separators (newlines) into NULLs
484 * and NULL-terminate the multi-string.
485 */
486 while (*pwszzVersion)
487 {
488 EndBuffer = wcschr(pwszzVersion, L'\n');
489 if (!EndBuffer) break;
490 pwszzVersion = EndBuffer;
491
492 *pwszzVersion++ = UNICODE_NULL;
493 }
494 *pwszzVersion = UNICODE_NULL;
495
496 return Status;
497}
498
499
500/*
501 * IntResolveDesktop
502 *
503 * The IntResolveDesktop function attempts to retrieve valid handles to
504 * a desktop and a window station suitable for the specified process.
505 * The specified desktop path string is used only as a hint for the resolution.
506 *
507 * - If the process is already assigned to a window station and a desktop,
508 * handles to these objects are returned directly regardless of the specified
509 * desktop path string. This is what happens when this function is called for
510 * a process that has been already started and connected to the Win32 USER.
511 *
512 * - If the process is being connected to the Win32 USER, or is in a state
513 * where a window station is assigned to it but no desktop yet, the desktop
514 * path string is used as a hint for the resolution.
515 * A specified window station (if any, otherwise "WinSta0" is used as default)
516 * is tested for existence and accessibility. If the checks are OK a handle
517 * to it is returned. Otherwise we either fail (the window station does not
518 * exist) or, in case a default window station was used, we attempt to open
519 * or create a non-interactive Service-0xXXXX-YYYY$ window station. This is
520 * typically what happens when a non-interactive process is started while
521 * the WinSta0 window station was used as the default one.
522 * A specified desktop (if any, otherwise "Default" is used as default)
523 * is then tested for existence on the opened window station.
524 *
525 * - Rules for the choice of the default window station, when none is specified
526 * in the desktop path:
527 *
528 * 1. By default, a SYSTEM process connects to a non-interactive window
529 * station, either the Service-0x0-3e7$ (from the SYSTEM LUID) station,
530 * or one that has been inherited and that is non-interactive.
531 * Only when the interactive window station WinSta0 is specified that
532 * the process can connect to it (e.g. the case of interactive services).
533 *
534 * 2. An interactive process, i.e. a process whose LUID is the same as the
535 * one assigned to WinSta0 by Winlogon on user logon, connects by default
536 * to the WinSta0 window station, unless it has inherited from another
537 * interactive window station (which must be... none other than WinSta0).
538 *
539 * 3. A non-interactive (but not SYSTEM) process connects by default to
540 * a non-interactive Service-0xXXXX-YYYY$ window station (whose name
541 * is derived from the process' LUID), or to another non-interactive
542 * window station that has been inherited.
543 * Otherwise it may be able connect to the interactive WinSta0 only if
544 * it has explicit access rights to it.
545 *
546 * Parameters
547 * Process
548 * The user process object.
549 *
550 * DesktopPath
551 * The desktop path string used as a hint for desktop resolution.
552 *
553 * bInherit
554 * Whether or not the returned handles are inheritable.
555 *
556 * phWinSta
557 * Pointer to a window station handle.
558 *
559 * phDesktop
560 * Pointer to a desktop handle.
561 *
562 * Return Value
563 * Status code.
564 */
565
570 IN PUNICODE_STRING DesktopPath,
571 IN BOOL bInherit,
572 OUT HWINSTA* phWinSta,
573 OUT HDESK* phDesktop)
574{
576 HWINSTA hWinSta = NULL, hWinStaDup = NULL;
577 HDESK hDesktop = NULL, hDesktopDup = NULL;
578 PPROCESSINFO ppi;
580 LUID ProcessLuid;
581 USHORT StrSize;
582 SIZE_T MemSize;
583 PSECURITY_DESCRIPTOR ServiceSD;
586 UNICODE_STRING WinStaName, DesktopName;
587 const UNICODE_STRING WinSta0Name = RTL_CONSTANT_STRING(L"WinSta0");
588 PWINSTATION_OBJECT WinStaObject;
589 HWINSTA hTempWinSta = NULL;
590 BOOLEAN bUseDefaultWinSta = FALSE;
591 BOOLEAN bInteractive = FALSE;
592 BOOLEAN bAccessAllowed = FALSE;
593
595
596 ASSERT(phWinSta);
597 ASSERT(phDesktop);
598 ASSERT(DesktopPath);
599
600 *phWinSta = NULL;
601 *phDesktop = NULL;
602
604 /* ppi is typically NULL for console applications that connect to Win32 USER */
605 if (!ppi) TRACE("IntResolveDesktop: ppi is NULL!\n");
606
607 if (ppi && ppi->hwinsta != NULL && ppi->hdeskStartup != NULL)
608 {
609 /*
610 * If this process is the current one, just return the cached handles.
611 * Otherwise, open the window station and desktop objects.
612 */
614 {
615 hWinSta = ppi->hwinsta;
616 hDesktop = ppi->hdeskStartup;
617 }
618 else
619 {
621 0,
622 NULL,
625 UserMode,
626 (PHANDLE)&hWinSta);
627 if (!NT_SUCCESS(Status))
628 {
629 ERR("IntResolveDesktop: Could not reference window station 0x%p\n", ppi->prpwinsta);
631 return Status;
632 }
633
635 0,
636 NULL,
639 UserMode,
640 (PHANDLE)&hDesktop);
641 if (!NT_SUCCESS(Status))
642 {
643 ERR("IntResolveDesktop: Could not reference desktop 0x%p\n", ppi->rpdeskStartup);
644 ObCloseHandle(hWinSta, UserMode);
646 return Status;
647 }
648 }
649
650 *phWinSta = hWinSta;
651 *phDesktop = hDesktop;
652 return STATUS_SUCCESS;
653 }
654
655 /* We will by default use the default window station and desktop */
656 RtlInitEmptyUnicodeString(&WinStaName, NULL, 0);
657 RtlInitEmptyUnicodeString(&DesktopName, NULL, 0);
658
659 /*
660 * Parse the desktop path string which can be of the form "WinSta\Desktop"
661 * or just "Desktop". In the latter case we use the default window station
662 * on which the process is attached to (or if none, "WinSta0").
663 */
664 if (DesktopPath->Buffer != NULL && DesktopPath->Length > sizeof(WCHAR))
665 {
666 DesktopName = *DesktopPath;
667
668 /* Find the separator */
669 while (DesktopName.Length > 0 && *DesktopName.Buffer &&
670 *DesktopName.Buffer != OBJ_NAME_PATH_SEPARATOR)
671 {
672 DesktopName.Buffer++;
673 DesktopName.Length -= sizeof(WCHAR);
674 DesktopName.MaximumLength -= sizeof(WCHAR);
675 }
676 if (DesktopName.Length > 0)
677 {
678 RtlInitEmptyUnicodeString(&WinStaName, DesktopPath->Buffer,
679 DesktopPath->Length - DesktopName.Length);
680 // (USHORT)((ULONG_PTR)DesktopName.Buffer - (ULONG_PTR)DesktopPath->Buffer);
681 WinStaName.Length = WinStaName.MaximumLength;
682
683 /* Skip the separator */
684 DesktopName.Buffer++;
685 DesktopName.Length -= sizeof(WCHAR);
686 DesktopName.MaximumLength -= sizeof(WCHAR);
687 }
688 else
689 {
690 RtlInitEmptyUnicodeString(&WinStaName, NULL, 0);
691 DesktopName = *DesktopPath;
692 }
693 }
694
695 TRACE("IntResolveDesktop: WinStaName:'%wZ' ; DesktopName:'%wZ'\n", &WinStaName, &DesktopName);
696
697 /* Retrieve the process LUID */
698 Status = GetProcessLuid(NULL, Process, &ProcessLuid);
699 if (!NT_SUCCESS(Status))
700 {
701 ERR("IntResolveDesktop: Failed to retrieve the process LUID, Status 0x%08lx\n", Status);
703 return Status;
704 }
705
706 /*
707 * If this process is not the current one, obtain a temporary handle
708 * to it so that we can perform handles duplication later.
709 */
711 {
714 NULL,
715 0,
718 &hProcess);
719 if (!NT_SUCCESS(Status))
720 {
721 ERR("IntResolveDesktop: Failed to obtain a handle to process 0x%p, Status 0x%08lx\n", Process, Status);
723 return Status;
724 }
726 }
727
728 /*
729 * If no window station has been specified, search the process handle table
730 * for inherited window station handles, otherwise use a default one.
731 */
732 if (WinStaName.Buffer == NULL)
733 {
734 /*
735 * We want to find a suitable default window station.
736 * For applications that can be interactive, i.e. that have allowed
737 * access to the single interactive window station on the system,
738 * the default window station is 'WinSta0'.
739 * For applications that cannot be interactive, i.e. that do not have
740 * access to 'WinSta0' (e.g. non-interactive services), the default
741 * window station is 'Service-0xXXXX-YYYY$' (created if needed).
742 * Precedence will however be taken by any inherited window station
743 * that possesses the required interactivity property.
744 */
745 bUseDefaultWinSta = TRUE;
746
747 /*
748 * Use the default 'WinSta0' window station. Whether we should
749 * use 'Service-0xXXXX-YYYY$' instead will be determined later.
750 */
751 // RtlInitUnicodeString(&WinStaName, L"WinSta0");
752 WinStaName = WinSta0Name;
753
755 NULL,
757 NULL,
758 (PHANDLE)&hWinSta))
759 {
760 TRACE("IntResolveDesktop: Inherited window station is: 0x%p\n", hWinSta);
761 }
762 }
763
764 /*
765 * If no desktop has been specified, search the process handle table
766 * for inherited desktop handles, otherwise use the Default desktop.
767 * Note that the inherited desktop that we may use, may not belong
768 * to the window station we will connect to.
769 */
770 if (DesktopName.Buffer == NULL)
771 {
772 /* Use a default desktop name */
773 RtlInitUnicodeString(&DesktopName, L"Default");
774
776 NULL,
778 NULL,
779 (PHANDLE)&hDesktop))
780 {
781 TRACE("IntResolveDesktop: Inherited desktop is: 0x%p\n", hDesktop);
782 }
783 }
784
785
786 /*
787 * We are going to open either a window station or a desktop.
788 * Even if this operation is done from kernel-mode, we should
789 * "emulate" an opening from user-mode (i.e. using an ObjectAttributes
790 * allocated in user-mode, with AccessMode == UserMode) for the
791 * Object Manager to perform proper access validation to the
792 * window station or desktop.
793 */
794
795 /*
796 * Estimate the maximum size needed for the window station name
797 * and desktop name to be given to ObjectAttributes->ObjectName.
798 */
799 StrSize = 0;
800
801 /* Window station name */
802 MemSize = _scwprintf(L"Service-0x%x-%x$", MAXULONG, MAXULONG) * sizeof(WCHAR);
804 + max(WinStaName.Length, MemSize) + sizeof(UNICODE_NULL);
805 if (MemSize > MAXUSHORT)
806 {
807 ERR("IntResolveDesktop: Window station name length is too long.\n");
809 goto Quit;
810 }
811 StrSize = max(StrSize, (USHORT)MemSize);
812
813 /* Desktop name */
814 MemSize = max(DesktopName.Length + sizeof(UNICODE_NULL), sizeof(L"Default"));
815 StrSize = max(StrSize, (USHORT)MemSize);
816
817 /* Size for the OBJECT_ATTRIBUTES */
818 MemSize = ALIGN_UP(sizeof(OBJECT_ATTRIBUTES), sizeof(PVOID));
819
820 /* Add the string size */
821 MemSize += ALIGN_UP(sizeof(UNICODE_STRING), sizeof(PVOID));
822 MemSize += StrSize;
823
824 /* Allocate the memory in user-mode */
825 Status = ZwAllocateVirtualMemory(ZwCurrentProcess(),
827 0,
828 &MemSize,
831 if (!NT_SUCCESS(Status))
832 {
833 ERR("ZwAllocateVirtualMemory() failed, Status 0x%08lx\n", Status);
834 goto Quit;
835 }
836
838 ALIGN_UP(sizeof(OBJECT_ATTRIBUTES), sizeof(PVOID)));
839
840 RtlInitEmptyUnicodeString(ObjectName,
842 ALIGN_UP(sizeof(UNICODE_STRING), sizeof(PVOID))),
843 StrSize);
844
845
846 /* If we got an inherited window station handle, duplicate and use it */
847 if (hWinSta)
848 {
849 ASSERT(bUseDefaultWinSta);
850
851 /* Duplicate the handle if it belongs to another process than the current one */
853 {
855 Status = ZwDuplicateObject(hProcess,
856 hWinSta,
858 (PHANDLE)&hWinStaDup,
859 0,
860 0,
862 if (!NT_SUCCESS(Status))
863 {
864 ERR("IntResolveDesktop: Failed to duplicate the window station handle, Status 0x%08lx\n", Status);
865 /* We will use a default window station */
866 hWinSta = NULL;
867 }
868 else
869 {
870 hWinSta = hWinStaDup;
871 }
872 }
873 }
874
875 /*
876 * If we have an inherited window station, check whether
877 * it is interactive and remember that for later.
878 */
879 if (hWinSta)
880 {
881 ASSERT(bUseDefaultWinSta);
882
883 /* Reference the inherited window station */
885 0,
888 (PVOID*)&WinStaObject,
889 NULL);
890 if (!NT_SUCCESS(Status))
891 {
892 ERR("Failed to reference the inherited window station, Status 0x%08lx\n", Status);
893 /* We will use a default window station */
894 if (hWinStaDup)
895 {
896 ASSERT(hWinSta == hWinStaDup);
897 ObCloseHandle(hWinStaDup, UserMode);
898 hWinStaDup = NULL;
899 }
900 hWinSta = NULL;
901 }
902 else
903 {
904 ERR("Process LUID is: 0x%x-%x, inherited window station LUID is: 0x%x-%x\n",
905 ProcessLuid.HighPart, ProcessLuid.LowPart,
906 WinStaObject->luidUser.HighPart, WinStaObject->luidUser.LowPart);
907
908 /* Check whether this window station is interactive, and remember it for later */
909 bInteractive = !(WinStaObject->Flags & WSS_NOIO);
910
911 /* Dereference the window station */
912 ObDereferenceObject(WinStaObject);
913 }
914 }
915
916 /* Build a valid window station name */
918 ObjectName->MaximumLength,
919 L"%wZ\\%wZ",
921 &WinStaName);
922 if (!NT_SUCCESS(Status))
923 {
924 ERR("Impossible to build a valid window station name, Status 0x%08lx\n", Status);
925 goto Quit;
926 }
927 ObjectName->Length = (USHORT)(wcslen(ObjectName->Buffer) * sizeof(WCHAR));
928
929 TRACE("Parsed initial window station: '%wZ'\n", ObjectName);
930
931 /* Try to open the window station */
935 NULL,
936 NULL);
937 if (bInherit)
938 ObjectAttributes->Attributes |= OBJ_INHERIT;
939
942 UserMode,
943 NULL,
945 NULL,
946 (PHANDLE)&hTempWinSta);
947 if (!NT_SUCCESS(Status))
948 {
949 ERR("Failed to open the window station '%wZ', Status 0x%08lx\n", ObjectName, Status);
950 }
951 else
952 {
953 //
954 // FIXME TODO: Perform a window station access check!!
955 // If we fail AND bUseDefaultWinSta == FALSE we just quit.
956 //
957
958 /*
959 * Check whether we are opening the (single) interactive
960 * window station, and if so, perform an access check.
961 */
962 /* Check whether we are allowed to perform interactions */
963 if (RtlEqualUnicodeString(&WinStaName, &WinSta0Name, TRUE))
964 {
965 LUID SystemLuid = SYSTEM_LUID;
966
967 /* Interactive window station: check for user LUID */
968 WinStaObject = InputWindowStation;
969
971
972 // TODO: Check also that we compare wrt. window station WinSta0
973 // which is the only one that can be interactive on the system.
974 if (((!bUseDefaultWinSta || bInherit) && RtlEqualLuid(&ProcessLuid, &SystemLuid)) ||
975 RtlEqualLuid(&ProcessLuid, &WinStaObject->luidUser))
976 {
977 /* We are interactive on this window station */
978 bAccessAllowed = TRUE;
980 }
981 }
982 else
983 {
984 /* Non-interactive window station: we have access since we were able to open it */
985 bAccessAllowed = TRUE;
987 }
988 }
989
990 /* If we failed, bail out if we were not trying to open the default window station */
991 if (!NT_SUCCESS(Status) && !bUseDefaultWinSta) // if (!bAccessAllowed)
992 goto Quit;
993
994 if (/* bAccessAllowed && */ bInteractive || !bAccessAllowed)
995 {
996 /*
997 * Close WinSta0 if the inherited window station is interactive so that
998 * we can use it, or we do not have access to the interactive WinSta0.
999 */
1000 ObCloseHandle(hTempWinSta, UserMode);
1001 hTempWinSta = NULL;
1002 }
1003 if (bInteractive == bAccessAllowed)
1004 {
1005 /* Keep using the inherited window station */
1006 NOTHING;
1007 }
1008 else // if (bInteractive != bAccessAllowed)
1009 {
1010 /*
1011 * Close the inherited window station, we will either keep using
1012 * the interactive WinSta0, or use Service-0xXXXX-YYYY$.
1013 */
1014 if (hWinStaDup)
1015 {
1016 ASSERT(hWinSta == hWinStaDup);
1017 ObCloseHandle(hWinStaDup, UserMode);
1018 hWinStaDup = NULL;
1019 }
1020 hWinSta = hTempWinSta; // hTempWinSta is NULL in case bAccessAllowed == FALSE
1021 }
1022
1023 if (bUseDefaultWinSta)
1024 {
1025 if (hWinSta == NULL && !bInteractive)
1026 {
1027 /* Build a valid window station name from the LUID */
1029 ObjectName->MaximumLength,
1030 L"%wZ\\Service-0x%x-%x$",
1032 ProcessLuid.HighPart,
1033 ProcessLuid.LowPart);
1034 if (!NT_SUCCESS(Status))
1035 {
1036 ERR("Impossible to build a valid window station name, Status 0x%08lx\n", Status);
1037 goto Quit;
1038 }
1039 ObjectName->Length = (USHORT)(wcslen(ObjectName->Buffer) * sizeof(WCHAR));
1040
1041 /*
1042 * Set up a security descriptor for the new service's window station.
1043 * A service has an associated window station and desktop. The newly
1044 * created window station and desktop will get this security descriptor
1045 * if such objects weren't created before.
1046 */
1047 Status = IntCreateServiceSecurity(&ServiceSD);
1048 if (!NT_SUCCESS(Status))
1049 {
1050 ERR("Failed to create a security descriptor for service window station, Status 0x%08lx\n", Status);
1051 goto Quit;
1052 }
1053
1054 /*
1055 * Create or open the non-interactive window station.
1056 * NOTE: The non-interactive window station handle is never inheritable.
1057 */
1059 ObjectName,
1061 NULL,
1062 ServiceSD);
1063
1064 Status = IntCreateWindowStation(&hWinSta,
1066 UserMode,
1067 KernelMode,
1069 0, 0, 0, 0, 0);
1070
1071 IntFreeSecurityBuffer(ServiceSD);
1072
1073 if (!NT_SUCCESS(Status))
1074 {
1075 ASSERT(hWinSta == NULL);
1076 ERR("Failed to create or open the non-interactive window station '%wZ', Status 0x%08lx\n",
1078 goto Quit;
1079 }
1080
1081 //
1082 // FIXME: We might not need to always create or open the "Default"
1083 // desktop on the Service-0xXXXX-YYYY$ window station; we may need
1084 // to use another one....
1085 //
1086
1087 /* Create or open the Default desktop on the window station */
1089 ObjectName->MaximumLength,
1090 L"Default");
1091 if (!NT_SUCCESS(Status))
1092 {
1093 ERR("Impossible to build a valid desktop name, Status 0x%08lx\n", Status);
1094 goto Quit;
1095 }
1096 ObjectName->Length = (USHORT)(wcslen(ObjectName->Buffer) * sizeof(WCHAR));
1097
1098 /*
1099 * NOTE: The non-interactive desktop handle is never inheritable.
1100 * The security descriptor is inherited from the newly created
1101 * window station for the desktop.
1102 */
1104 ObjectName,
1106 hWinSta,
1107 NULL);
1108
1109 Status = IntCreateDesktop(&hDesktop,
1111 UserMode,
1112 NULL,
1113 NULL,
1114 0,
1116 if (!NT_SUCCESS(Status))
1117 {
1118 ASSERT(hDesktop == NULL);
1119 ERR("Failed to create or open the desktop '%wZ' on window station 0x%p, Status 0x%08lx\n",
1120 ObjectName, hWinSta, Status);
1121 }
1122
1123 goto Quit;
1124 }
1125/*
1126 if (hWinSta == NULL)
1127 {
1128 Status = STATUS_UNSUCCESSFUL;
1129 goto Quit;
1130 }
1131*/
1132 }
1133
1134 /*
1135 * If we got an inherited desktop handle, duplicate and use it,
1136 * otherwise open a new desktop.
1137 */
1138 if (hDesktop != NULL)
1139 {
1140 /* Duplicate the handle if it belongs to another process than the current one */
1142 {
1144 Status = ZwDuplicateObject(hProcess,
1145 hDesktop,
1147 (PHANDLE)&hDesktopDup,
1148 0,
1149 0,
1151 if (!NT_SUCCESS(Status))
1152 {
1153 ERR("IntResolveDesktop: Failed to duplicate the desktop handle, Status 0x%08lx\n", Status);
1154 /* We will use a default desktop */
1155 hDesktop = NULL;
1156 }
1157 else
1158 {
1159 hDesktop = hDesktopDup;
1160 }
1161 }
1162 }
1163
1164 if ((hWinSta != NULL) && (hDesktop == NULL))
1165 {
1167 ObjectName->MaximumLength,
1168 DesktopName.Buffer,
1169 DesktopName.Length);
1170 if (!NT_SUCCESS(Status))
1171 {
1172 ERR("Impossible to build a valid desktop name, Status 0x%08lx\n", Status);
1173 goto Quit;
1174 }
1175 ObjectName->Length = (USHORT)(wcslen(ObjectName->Buffer) * sizeof(WCHAR));
1176
1177 TRACE("Parsed initial desktop: '%wZ'\n", ObjectName);
1178
1179 /* Open the desktop object */
1181 ObjectName,
1183 hWinSta,
1184 NULL);
1185 if (bInherit)
1186 ObjectAttributes->Attributes |= OBJ_INHERIT;
1187
1190 UserMode,
1191 NULL,
1193 NULL,
1194 (PHANDLE)&hDesktop);
1195 if (!NT_SUCCESS(Status))
1196 {
1197 ERR("Failed to open the desktop '%wZ' on window station 0x%p, Status 0x%08lx\n",
1198 ObjectName, hWinSta, Status);
1199 goto Quit;
1200 }
1201 }
1202
1203Quit:
1204 /* Release the object attributes */
1205 if (ObjectAttributes)
1206 {
1207 MemSize = 0;
1208 ZwFreeVirtualMemory(ZwCurrentProcess(),
1210 &MemSize,
1211 MEM_RELEASE);
1212 }
1213
1214 /* Close the temporary process handle */
1215 if (hProcess) // if (Process != PsGetCurrentProcess())
1217
1218 if (NT_SUCCESS(Status))
1219 {
1220 *phWinSta = hWinSta;
1221 *phDesktop = hDesktop;
1222 return STATUS_SUCCESS;
1223 }
1224 else
1225 {
1226 ERR("IntResolveDesktop(%wZ) failed, Status 0x%08lx\n", DesktopPath, Status);
1227
1228 if (hDesktopDup)
1229 ObCloseHandle(hDesktopDup, UserMode);
1230 if (hWinStaDup)
1231 ObCloseHandle(hWinStaDup, UserMode);
1232
1233 if (hDesktop)
1234 ObCloseHandle(hDesktop, UserMode);
1235 if (hWinSta)
1236 ObCloseHandle(hWinSta, UserMode);
1237
1239 return Status;
1240 }
1241}
1242
1243/*
1244 * IntValidateDesktopHandle
1245 *
1246 * Validates the desktop handle.
1247 *
1248 * Remarks
1249 * If the function succeeds, the handle remains referenced. If the
1250 * fucntion fails, last error is set.
1251 */
1252
1255 HDESK Desktop,
1259{
1261
1265 AccessMode,
1266 (PVOID*)Object,
1267 NULL);
1268
1269 TRACE("IntValidateDesktopHandle: handle:0x%p obj:0x%p access:0x%x Status:0x%lx\n",
1271
1272 if (!NT_SUCCESS(Status))
1274
1275 return Status;
1276}
1277
1280{
1281 return gpdeskInputDesktop;
1282}
1283
1284/*
1285 * Returns or creates a handle to the desktop object
1286 */
1287HDESK FASTCALL
1289{
1291 HDESK hDesk;
1292
1293 ASSERT(DesktopObject);
1294
1296 DesktopObject,
1298 NULL,
1299 (PHANDLE)&hDesk))
1300 {
1301 Status = ObOpenObjectByPointer(DesktopObject,
1302 0,
1303 NULL,
1304 0,
1306 UserMode,
1307 (PHANDLE)&hDesk);
1308 if (!NT_SUCCESS(Status))
1309 {
1310 /* Unable to create a handle */
1311 ERR("Unable to create a desktop handle\n");
1312 return NULL;
1313 }
1314 }
1315 else
1316 {
1317 TRACE("Got handle: 0x%p\n", hDesk);
1318 }
1319
1320 return hDesk;
1321}
1322
1325{
1327 if (!pdo)
1328 {
1329 TRACE("No active desktop\n");
1330 return(NULL);
1331 }
1333}
1334
1337{
1340 if (!pdo)
1341 {
1342 TRACE("No active desktop\n");
1343 return;
1344 }
1345 if (NewQueue != NULL)
1346 {
1347 if (NewQueue->Desktop != NULL)
1348 {
1349 TRACE("Message Queue already attached to another desktop!\n");
1350 return;
1351 }
1352 IntReferenceMessageQueue(NewQueue);
1353 (void)InterlockedExchangePointer((PVOID*)&NewQueue->Desktop, pdo);
1354 }
1356 if (Old != NULL)
1357 {
1359 gpqForegroundPrev = Old;
1361 }
1362 // Only one Q can have active foreground even when there are more than one desktop.
1363 if (NewQueue)
1364 {
1366 }
1367 else
1368 {
1370 ERR("ptiLastInput is CLEARED!!\n");
1371 ptiLastInput = NULL; // ReactOS hacks... should check for process death.
1372 }
1373}
1374
1377{
1378 if (!pti) pti = PsGetCurrentThreadWin32Thread();
1379 if (pti->pDeskInfo) return pti->pDeskInfo->spwnd;
1380 return NULL;
1381}
1382
1384{
1385 if (pWnd->head.rpdesk &&
1386 pWnd->head.rpdesk->pDeskInfo)
1387 return pWnd->head.rpdesk->pDeskInfo->spwnd;
1388 return NULL;
1389}
1390
1392{
1394 if (!pdo)
1395 {
1396 TRACE("No active desktop\n");
1397 return NULL;
1398 }
1399 return pdo->DesktopWindow;
1400}
1401
1402// Win: _GetDesktopWindow
1404{
1406
1407 if (!pdo)
1408 {
1409 TRACE("No active desktop\n");
1410 return NULL;
1411 }
1412 // return pdo->pDeskInfo->spwnd;
1414}
1415
1417{
1419
1420 if (!pdo)
1421 {
1422 TRACE("No active desktop\n");
1423 return NULL;
1424 }
1425 return UserHMGetHandle(pdo->spwndMessage);
1426}
1427
1428// Win: _GetMessageWindow
1430{
1432
1433 if (!pdo)
1434 {
1435 TRACE("No active desktop\n");
1436 return NULL;
1437 }
1438 return pdo->spwndMessage;
1439}
1440
1442{
1444 PDESKTOP pdo = pti->rpdesk;
1445 if (NULL == pdo)
1446 {
1447 ERR("Thread doesn't have a desktop\n");
1448 return NULL;
1449 }
1450 return pdo->DesktopWindow;
1451}
1452
1453/* PUBLIC FUNCTIONS ***********************************************************/
1454
1457{
1458 PAINTSTRUCT Ps;
1459 ULONG Value;
1460 //ERR("DesktopWindowProc\n");
1461
1462 *lResult = 0;
1463
1464 switch (Msg)
1465 {
1466 case WM_NCCREATE:
1467 if (!Wnd->fnid)
1468 {
1469 Wnd->fnid = FNID_DESKTOP;
1470 }
1471 *lResult = (LRESULT)TRUE;
1472 return TRUE;
1473
1474 case WM_CREATE:
1476 // Save Process ID
1479 // Save Thread ID
1481 case WM_CLOSE:
1482 return TRUE;
1483
1484 case WM_DISPLAYCHANGE:
1486 return TRUE;
1487
1488 case WM_ERASEBKGND:
1490 *lResult = 1;
1491 return TRUE;
1492
1493 case WM_PAINT:
1494 {
1495 if (IntBeginPaint(Wnd, &Ps))
1496 {
1497 IntEndPaint(Wnd, &Ps);
1498 }
1499 return TRUE;
1500 }
1501 case WM_SYSCOLORCHANGE:
1503 return TRUE;
1504
1505 case WM_SETCURSOR:
1506 {
1507 PCURICON_OBJECT pcurOld, pcurNew;
1509 if (!pcurNew)
1510 {
1511 return TRUE;
1512 }
1513
1514 pcurNew->CURSORF_flags |= CURSORF_CURRENT;
1515 pcurOld = UserSetCursor(pcurNew, FALSE);
1516 if (pcurOld)
1517 {
1518 pcurOld->CURSORF_flags &= ~CURSORF_CURRENT;
1519 UserDereferenceObject(pcurOld);
1520 }
1521 return TRUE;
1522 }
1523
1525 {
1526 PWINDOWPOS pWindowPos = (PWINDOWPOS)lParam;
1527 if ((pWindowPos->flags & SWP_SHOWWINDOW) != 0)
1528 {
1530 IntSetThreadDesktop(hdesk, FALSE);
1531 }
1532 break;
1533 }
1534 default:
1535 TRACE("DWP calling IDWP Msg %d\n",Msg);
1536 //*lResult = IntDefWindowProc(Wnd, Msg, wParam, lParam, FALSE);
1537 }
1538 return TRUE; /* We are done. Do not do any callbacks to user mode */
1539}
1540
1543{
1544 *lResult = 0;
1545
1546 switch(Msg)
1547 {
1548 case WM_NCCREATE:
1549 pwnd->fnid |= FNID_MESSAGEWND;
1550 *lResult = (LRESULT)TRUE;
1551 break;
1552 case WM_DESTROY:
1553 pwnd->fnid |= FNID_DESTROY;
1554 break;
1555 default:
1556 ERR("UMWP calling IDWP\n");
1557 *lResult = IntDefWindowProc(pwnd, Msg, wParam, lParam, FALSE);
1558 }
1559
1560 return TRUE; /* We are done. Do not do any callbacks to user mode */
1561}
1562
1564{
1565 BOOL Ret;
1566 MSG Msg;
1567
1569
1571
1572 /* Register system classes. This thread does not belong to any desktop so the
1573 classes will be allocated from the shared heap */
1575
1577
1578 while (TRUE)
1579 {
1580 Ret = co_IntGetPeekMessage(&Msg, 0, 0, 0, PM_REMOVE, TRUE);
1581 if (Ret)
1582 {
1584 }
1585 }
1586
1587 UserLeave();
1588}
1589
1591UserGetDesktopDC(ULONG DcType, BOOL bAltDc, BOOL ValidatehWnd)
1592{
1593 PWND DesktopObject = 0;
1594 HDC DesktopHDC = 0;
1595
1596 /* This can be called from GDI/DX, so acquire the USER lock */
1598
1599 if (DcType == DCTYPE_DIRECT)
1600 {
1601 DesktopObject = UserGetDesktopWindow();
1602 DesktopHDC = (HDC)UserGetWindowDC(DesktopObject);
1603 }
1604 else
1605 {
1606 PMONITOR pMonitor = UserGetPrimaryMonitor();
1607 DesktopHDC = IntGdiCreateDisplayDC(pMonitor->hDev, DcType, bAltDc);
1608 }
1609
1610 UserLeave();
1611
1612 return DesktopHDC;
1613}
1614
1617{
1618 PWND Window = NULL;
1619 PREGION Rgn;
1620
1622 Rgn = IntSysCreateRectpRgnIndirect(&Window->rcWindow);
1623
1625 Rgn,
1628
1629 REGION_Delete(Rgn);
1630}
1631
1632
1635{
1636 PWND pwnd = Desktop->pDeskInfo->spwnd;
1638 ASSERT(pwnd);
1639
1640 if (!bRedraw)
1642
1644
1645 if (bRedraw)
1647
1648 return STATUS_SUCCESS;
1649}
1650
1653{
1654 PWND DesktopWnd;
1655
1656 DesktopWnd = IntGetWindowObject(Desktop->DesktopWindow);
1657 if (! DesktopWnd)
1658 {
1660 }
1661 DesktopWnd->style &= ~WS_VISIBLE;
1662
1663 return STATUS_SUCCESS;
1664}
1665
1666static
1669{
1670 ULONG entries=0;
1671 PLIST_ENTRY ListEntry;
1672 PSHELL_HOOK_WINDOW Current;
1673 HWND* list;
1674
1675 /* FIXME: If we save nb elements in desktop, we don't have to loop to find nb entries */
1676 ListEntry = Desktop->ShellHookWindows.Flink;
1677 while (ListEntry != &Desktop->ShellHookWindows)
1678 {
1679 ListEntry = ListEntry->Flink;
1680 entries++;
1681 }
1682
1683 if (!entries) return NULL;
1684
1685 list = ExAllocatePoolWithTag(PagedPool, sizeof(HWND) * (entries + 1), USERTAG_WINDOWLIST); /* alloc one extra for nullterm */
1686 if (list)
1687 {
1688 HWND* cursor = list;
1689
1690 ListEntry = Desktop->ShellHookWindows.Flink;
1691 while (ListEntry != &Desktop->ShellHookWindows)
1692 {
1693 Current = CONTAINING_RECORD(ListEntry, SHELL_HOOK_WINDOW, ListEntry);
1694 ListEntry = ListEntry->Flink;
1695 *cursor++ = Current->hWnd;
1696 }
1697
1698 *cursor = NULL; /* Nullterm list */
1699 }
1700
1701 return list;
1702}
1703
1704/*
1705 * Send the Message to the windows registered for ShellHook
1706 * notifications. The lParam contents depend on the Message. See
1707 * MSDN for more details (RegisterShellHookWindow)
1708 */
1710{
1712 HWND* HwndList;
1713
1714 if (!gpsi->uiShellMsg)
1715 {
1716 gpsi->uiShellMsg = IntAddAtom(L"SHELLHOOK");
1717
1718 TRACE("MsgType = %x\n", gpsi->uiShellMsg);
1719 if (!gpsi->uiShellMsg)
1720 ERR("LastError: %x\n", EngGetLastError());
1721 }
1722
1723 if (!Desktop)
1724 {
1725 TRACE("IntShellHookNotify: No desktop!\n");
1726 return;
1727 }
1728
1729 // Allow other devices have a shot at foreground.
1730 if (Message == HSHELL_APPCOMMAND) ptiLastInput = NULL;
1731
1732 // FIXME: System Tray Support.
1733
1735 if (HwndList)
1736 {
1737 HWND* cursor = HwndList;
1738
1739 for (; *cursor; cursor++)
1740 {
1741 TRACE("Sending notify\n");
1744 Message,
1745 (Message == HSHELL_LANGUAGE ? lParam : (LPARAM)wParam) );
1746/* co_IntPostOrSendMessage(*cursor,
1747 gpsi->uiShellMsg,
1748 Message,
1749 (Message == HSHELL_LANGUAGE ? lParam : (LPARAM)wParam) );*/
1750 }
1751
1753 }
1754
1755 if (ISITHOOKED(WH_SHELL))
1756 {
1758 }
1759}
1760
1761/*
1762 * Add the window to the ShellHookWindows list. The windows
1763 * on that list get notifications that are important to shell
1764 * type applications.
1765 *
1766 * TODO: Validate the window? I'm not sure if sending these messages to
1767 * an unsuspecting application that is not your own is a nice thing to do.
1768 */
1770{
1772 PDESKTOP Desktop = pti->rpdesk;
1774
1775 TRACE("IntRegisterShellHookWindow\n");
1776
1777 /* First deregister the window, so we can be sure it's never twice in the
1778 * list.
1779 */
1781
1783 sizeof(SHELL_HOOK_WINDOW),
1784 TAG_WINSTA);
1785
1786 if (!Entry)
1787 return FALSE;
1788
1789 Entry->hWnd = hWnd;
1790
1791 InsertTailList(&Desktop->ShellHookWindows, &Entry->ListEntry);
1792
1793 return TRUE;
1794}
1795
1796/*
1797 * Remove the window from the ShellHookWindows list. The windows
1798 * on that list get notifications that are important to shell
1799 * type applications.
1800 */
1802{
1804 PDESKTOP Desktop = pti->rpdesk;
1805 PLIST_ENTRY ListEntry;
1806 PSHELL_HOOK_WINDOW Current;
1807
1808 // FIXME: This probably shouldn't happen, but it does
1809 if (Desktop == NULL)
1810 {
1812 if (Desktop == NULL)
1813 return FALSE;
1814 }
1815
1816 ListEntry = Desktop->ShellHookWindows.Flink;
1817 while (ListEntry != &Desktop->ShellHookWindows)
1818 {
1819 Current = CONTAINING_RECORD(ListEntry, SHELL_HOOK_WINDOW, ListEntry);
1820 ListEntry = ListEntry->Flink;
1821 if (Current->hWnd == hWnd)
1822 {
1823 RemoveEntryList(&Current->ListEntry);
1824 ExFreePoolWithTag(Current, TAG_WINSTA);
1825 return TRUE;
1826 }
1827 }
1828
1829 return FALSE;
1830}
1831
1832static VOID
1834{
1835 /* FIXME: Disable until unmapping works in mm */
1836#if 0
1837 if (Desktop->pheapDesktop != NULL)
1838 {
1839 MmUnmapViewInSessionSpace(Desktop->pheapDesktop);
1840 Desktop->pheapDesktop = NULL;
1841 }
1842
1843 if (Desktop->hsectionDesktop != NULL)
1844 {
1845 ObDereferenceObject(Desktop->hsectionDesktop);
1846 Desktop->hsectionDesktop = NULL;
1847 }
1848#endif
1849}
1850
1853{
1854 static WCHAR s_wszSafeMode[] = L"Safe Mode"; // FIXME: Localize!
1855
1856 RECTL Rect;
1857 HBRUSH DesktopBrush, PreviousBrush;
1858 HWND hWndDesktop;
1859 BOOL doPatBlt = TRUE;
1860 PWND WndDesktop;
1861 BOOLEAN InSafeMode;
1862
1863 if (GdiGetClipBox(hDC, &Rect) == ERROR)
1864 return FALSE;
1865
1866 hWndDesktop = IntGetDesktopWindow(); // rpdesk->DesktopWindow;
1867
1868 WndDesktop = UserGetWindowObject(hWndDesktop); // rpdesk->pDeskInfo->spwnd;
1869 if (!WndDesktop)
1870 return FALSE;
1871
1872 /* Retrieve the current SafeMode state */
1873 InSafeMode = (UserGetSystemMetrics(SM_CLEANBOOT) != 0); // gpsi->aiSysMet[SM_CLEANBOOT];
1874
1875 if (!InSafeMode)
1876 {
1877 DesktopBrush = (HBRUSH)WndDesktop->pcls->hbrBackground;
1878
1879 /*
1880 * Paint desktop background
1881 */
1883 {
1884 SIZE sz;
1885 int x, y;
1886 int scaledWidth, scaledHeight;
1887 int wallpaperX, wallpaperY, wallpaperWidth, wallpaperHeight;
1888 HDC hWallpaperDC;
1889
1890 sz.cx = WndDesktop->rcWindow.right - WndDesktop->rcWindow.left;
1891 sz.cy = WndDesktop->rcWindow.bottom - WndDesktop->rcWindow.top;
1892
1893 if (gspv.WallpaperMode == wmFit ||
1895 {
1896 int scaleNum, scaleDen;
1897
1898 // Precision improvement over ((sz.cx / gspv.cxWallpaper) > (sz.cy / gspv.cyWallpaper))
1899 if ((sz.cx * gspv.cyWallpaper) > (sz.cy * gspv.cxWallpaper))
1900 {
1901 if (gspv.WallpaperMode == wmFit)
1902 {
1903 scaleNum = sz.cy;
1904 scaleDen = gspv.cyWallpaper;
1905 }
1906 else
1907 {
1908 scaleNum = sz.cx;
1909 scaleDen = gspv.cxWallpaper;
1910 }
1911 }
1912 else
1913 {
1914 if (gspv.WallpaperMode == wmFit)
1915 {
1916 scaleNum = sz.cx;
1917 scaleDen = gspv.cxWallpaper;
1918 }
1919 else
1920 {
1921 scaleNum = sz.cy;
1922 scaleDen = gspv.cyWallpaper;
1923 }
1924 }
1925
1926 scaledWidth = EngMulDiv(gspv.cxWallpaper, scaleNum, scaleDen);
1927 scaledHeight = EngMulDiv(gspv.cyWallpaper, scaleNum, scaleDen);
1928
1929 if (gspv.WallpaperMode == wmFill)
1930 {
1931 wallpaperX = (((scaledWidth - sz.cx) * gspv.cxWallpaper) / (2 * scaledWidth));
1932 wallpaperY = (((scaledHeight - sz.cy) * gspv.cyWallpaper) / (2 * scaledHeight));
1933
1934 wallpaperWidth = (sz.cx * gspv.cxWallpaper) / scaledWidth;
1935 wallpaperHeight = (sz.cy * gspv.cyWallpaper) / scaledHeight;
1936 }
1937 }
1938
1939 if (gspv.WallpaperMode == wmStretch ||
1942 {
1943 x = 0;
1944 y = 0;
1945 }
1946 else if (gspv.WallpaperMode == wmFit)
1947 {
1948 x = (sz.cx - scaledWidth) / 2;
1949 y = (sz.cy - scaledHeight) / 2;
1950 }
1951 else
1952 {
1953 /* Find the upper left corner, can be negative if the bitmap is bigger than the screen */
1954 x = (sz.cx / 2) - (gspv.cxWallpaper / 2);
1955 y = (sz.cy / 2) - (gspv.cyWallpaper / 2);
1956 }
1957
1958 hWallpaperDC = NtGdiCreateCompatibleDC(hDC);
1959 if (hWallpaperDC != NULL)
1960 {
1961 HBITMAP hOldBitmap;
1962
1963 /* Fill in the area that the bitmap is not going to cover */
1964 if (x > 0 || y > 0)
1965 {
1966 /* FIXME: Clip out the bitmap
1967 can be replaced with "NtGdiPatBlt(hDC, x, y, gspv.cxWallpaper, gspv.cyWallpaper, PATCOPY | DSTINVERT);"
1968 once we support DSTINVERT */
1969 PreviousBrush = NtGdiSelectBrush(hDC, DesktopBrush);
1970 NtGdiPatBlt(hDC, Rect.left, Rect.top, Rect.right, Rect.bottom, PATCOPY);
1971 NtGdiSelectBrush(hDC, PreviousBrush);
1972 }
1973
1974 /* Do not fill the background after it is painted no matter the size of the picture */
1975 doPatBlt = FALSE;
1976
1977 hOldBitmap = NtGdiSelectBitmap(hWallpaperDC, gspv.hbmWallpaper);
1978
1980 {
1981 if (Rect.right && Rect.bottom)
1983 x,
1984 y,
1985 sz.cx,
1986 sz.cy,
1987 hWallpaperDC,
1988 0,
1989 0,
1992 SRCCOPY,
1993 0);
1994 }
1995 else if (gspv.WallpaperMode == wmTile)
1996 {
1997 /* Paint the bitmap across the screen then down */
1998 for (y = 0; y < Rect.bottom; y += gspv.cyWallpaper)
1999 {
2000 for (x = 0; x < Rect.right; x += gspv.cxWallpaper)
2001 {
2003 x,
2004 y,
2007 hWallpaperDC,
2008 0,
2009 0,
2010 SRCCOPY,
2011 0,
2012 0);
2013 }
2014 }
2015 }
2016 else if (gspv.WallpaperMode == wmFit)
2017 {
2018 if (Rect.right && Rect.bottom)
2019 {
2021 x,
2022 y,
2023 scaledWidth,
2024 scaledHeight,
2025 hWallpaperDC,
2026 0,
2027 0,
2030 SRCCOPY,
2031 0);
2032 }
2033 }
2034 else if (gspv.WallpaperMode == wmFill)
2035 {
2036 if (Rect.right && Rect.bottom)
2037 {
2039 x,
2040 y,
2041 sz.cx,
2042 sz.cy,
2043 hWallpaperDC,
2044 wallpaperX,
2045 wallpaperY,
2046 wallpaperWidth,
2047 wallpaperHeight,
2048 SRCCOPY,
2049 0);
2050 }
2051 }
2052 else
2053 {
2055 x,
2056 y,
2059 hWallpaperDC,
2060 0,
2061 0,
2062 SRCCOPY,
2063 0,
2064 0);
2065 }
2066 NtGdiSelectBitmap(hWallpaperDC, hOldBitmap);
2067 NtGdiDeleteObjectApp(hWallpaperDC);
2068 }
2069 }
2070 }
2071 else
2072 {
2073 /* Black desktop background in Safe Mode */
2074 DesktopBrush = StockObjects[BLACK_BRUSH];
2075 }
2076
2077 /* Background is set to none, clear the screen */
2078 if (doPatBlt)
2079 {
2080 PreviousBrush = NtGdiSelectBrush(hDC, DesktopBrush);
2081 NtGdiPatBlt(hDC, Rect.left, Rect.top, Rect.right, Rect.bottom, PATCOPY);
2082 NtGdiSelectBrush(hDC, PreviousBrush);
2083 }
2084
2085 /*
2086 * Display the system version on the desktop background
2087 */
2088 if (InSafeMode || g_AlwaysDisplayVersion || g_PaintDesktopVersion)
2089 {
2091 static WCHAR wszzVersion[1024] = L"\0";
2092
2093 /* Only used in normal mode */
2094 // We expect at most 4 strings (3 for version, 1 for optional NtSystemRoot)
2095 static POLYTEXTW VerStrs[4] = {{0},{0},{0},{0}};
2096 INT i = 0;
2097 SIZE_T len;
2098
2099 HFONT hFont1 = NULL, hFont2 = NULL, hOldFont = NULL;
2100 COLORREF crText, color_old;
2101 UINT align_old;
2102 INT mode_old;
2103 PDC pdc;
2104
2105 if (!UserSystemParametersInfo(SPI_GETWORKAREA, 0, &Rect, 0))
2106 {
2107 Rect.left = Rect.top = 0;
2110 }
2111 else
2112 {
2113 RECTL_vOffsetRect(&Rect, -Rect.left, -Rect.top);
2114 }
2115
2116 /*
2117 * Set up the fonts (otherwise use default ones)
2118 */
2119
2120 /* Font for the principal version string */
2121 hFont1 = GreCreateFontIndirectW(&gspv.ncm.lfCaptionFont);
2122 /* Font for the secondary version strings */
2123 hFont2 = GreCreateFontIndirectW(&gspv.ncm.lfMenuFont);
2124
2125 if (hFont1)
2126 hOldFont = NtGdiSelectFont(hDC, hFont1);
2127
2128 if (gspv.hbmWallpaper == NULL)
2129 {
2130 /* Retrieve the brush fill colour */
2131 // TODO: The following code constitutes "GreGetBrushColor".
2132 PreviousBrush = NtGdiSelectBrush(hDC, DesktopBrush);
2133 pdc = DC_LockDc(hDC);
2134 if (pdc)
2135 {
2136 crText = pdc->eboFill.ulRGBColor;
2137 DC_UnlockDc(pdc);
2138 }
2139 else
2140 {
2141 crText = RGB(0, 0, 0);
2142 }
2143 NtGdiSelectBrush(hDC, PreviousBrush);
2144
2145 /* Adjust text colour according to the brush */
2146 if (GetRValue(crText) + GetGValue(crText) + GetBValue(crText) > 128 * 3)
2147 crText = RGB(0, 0, 0);
2148 else
2149 crText = RGB(255, 255, 255);
2150 }
2151 else
2152 {
2153 /* Always use white when the text is displayed on top of a wallpaper */
2154 crText = RGB(255, 255, 255);
2155 }
2156
2157 color_old = IntGdiSetTextColor(hDC, crText);
2158 align_old = IntGdiSetTextAlign(hDC, TA_RIGHT);
2159 mode_old = IntGdiSetBkMode(hDC, TRANSPARENT);
2160
2161 /* Display the system version information */
2162 if (!*wszzVersion)
2163 {
2164 Status = GetSystemVersionString(wszzVersion,
2165 ARRAYSIZE(wszzVersion),
2166 InSafeMode,
2168 if (!InSafeMode && NT_SUCCESS(Status) && *wszzVersion)
2169 {
2170 PWCHAR pstr = wszzVersion;
2171 for (i = 0; (i < ARRAYSIZE(VerStrs)) && *pstr; ++i)
2172 {
2173 VerStrs[i].n = lstrlenW(pstr);
2174 VerStrs[i].lpstr = pstr;
2175 pstr += (VerStrs[i].n + 1);
2176 }
2177 }
2178 }
2179 else
2180 {
2182 }
2183 if (NT_SUCCESS(Status) && *wszzVersion)
2184 {
2185 if (!InSafeMode)
2186 {
2187 SIZE Size = {0, 0};
2188 LONG TotalHeight = 0;
2189
2190 /* Normal Mode: multiple version information text separated by newlines */
2192
2193 /* Compute the heights of the strings */
2194 if (hFont1) NtGdiSelectFont(hDC, hFont1);
2195 for (i = 0; i < ARRAYSIZE(VerStrs); ++i)
2196 {
2197 if (!VerStrs[i].lpstr || !*VerStrs[i].lpstr || (VerStrs[i].n == 0))
2198 break;
2199
2200 GreGetTextExtentW(hDC, VerStrs[i].lpstr, VerStrs[i].n, &Size, 1);
2201 VerStrs[i].y = Size.cy; // Store the string height
2202 TotalHeight += Size.cy;
2203
2204 /* While the first string was using hFont1, all the others use hFont2 */
2205 if (hFont2) NtGdiSelectFont(hDC, hFont2);
2206 }
2207 /* The total height must not exceed the screen height */
2208 TotalHeight = min(TotalHeight, Rect.bottom);
2209
2210 /* Display the strings */
2211 if (hFont1) NtGdiSelectFont(hDC, hFont1);
2212 for (i = 0; i < ARRAYSIZE(VerStrs); ++i)
2213 {
2214 if (!VerStrs[i].lpstr || !*VerStrs[i].lpstr || (VerStrs[i].n == 0))
2215 break;
2216
2217 TotalHeight -= VerStrs[i].y;
2219 Rect.right - 5,
2220 Rect.bottom - TotalHeight - 5,
2221 0, NULL,
2222 VerStrs[i].lpstr,
2223 VerStrs[i].n,
2224 NULL, 0);
2225
2226 /* While the first string was using hFont1, all the others use hFont2 */
2227 if (hFont2) NtGdiSelectFont(hDC, hFont2);
2228 }
2229 }
2230 else
2231 {
2232 if (hFont1) NtGdiSelectFont(hDC, hFont1);
2233
2234 /* Safe Mode: single version information text in top center */
2235 len = wcslen(wszzVersion);
2236
2238 GreExtTextOutW(hDC, (Rect.right + Rect.left)/2, Rect.top + 3, 0, NULL, wszzVersion, len, NULL, 0);
2239 }
2240 }
2241
2242 if (InSafeMode)
2243 {
2244 if (hFont1) NtGdiSelectFont(hDC, hFont1);
2245
2246 /* Print Safe Mode text in corners */
2247 len = wcslen(s_wszSafeMode);
2248
2250 GreExtTextOutW(hDC, Rect.left, Rect.top + 3, 0, NULL, s_wszSafeMode, len, NULL, 0);
2252 GreExtTextOutW(hDC, Rect.right, Rect.top + 3, 0, NULL, s_wszSafeMode, len, NULL, 0);
2254 GreExtTextOutW(hDC, Rect.left, Rect.bottom - 5, 0, NULL, s_wszSafeMode, len, NULL, 0);
2256 GreExtTextOutW(hDC, Rect.right, Rect.bottom - 5, 0, NULL, s_wszSafeMode, len, NULL, 0);
2257 }
2258
2259 IntGdiSetBkMode(hDC, mode_old);
2260 IntGdiSetTextAlign(hDC, align_old);
2261 IntGdiSetTextColor(hDC, color_old);
2262
2263 if (hFont2)
2264 GreDeleteObject(hFont2);
2265
2266 if (hFont1)
2267 {
2268 NtGdiSelectFont(hDC, hOldFont);
2269 GreDeleteObject(hFont1);
2270 }
2271 }
2272
2273 return TRUE;
2274}
2275
2276static NTSTATUS
2278{
2279 static const UNICODE_STRING WinlogonDesktop = RTL_CONSTANT_STRING(L"Winlogon");
2280 PVOID DesktopHeapSystemBase = NULL;
2282 SIZE_T DesktopInfoSize;
2283 ULONG i;
2284
2285 TRACE("UserInitializeDesktop desktop 0x%p with name %wZ\n", pdesk, DesktopName);
2286
2287 RtlZeroMemory(pdesk, sizeof(DESKTOP));
2288
2289 /* Set desktop size, based on whether the WinSta is interactive or not */
2290 if (pwinsta == InputWindowStation)
2291 {
2292 /* Check if the Desktop is named "Winlogon" */
2293 if (RtlEqualUnicodeString(DesktopName, &WinlogonDesktop, TRUE))
2294 {
2296 }
2297 else
2298 {
2300 }
2301 }
2302 else
2303 {
2305 }
2306
2307 /* Link the desktop with the parent window station */
2308 ObReferenceObject(pwinsta);
2309 pdesk->rpwinstaParent = pwinsta;
2310 InsertTailList(&pwinsta->DesktopListHead, &pdesk->ListEntry);
2311
2312 /* Create the desktop heap */
2313 pdesk->hsectionDesktop = NULL;
2315 &DesktopHeapSystemBase,
2316 HeapSize);
2317 if (pdesk->pheapDesktop == NULL)
2318 {
2319 ERR("Failed to create desktop heap!\n");
2320 return STATUS_NO_MEMORY;
2321 }
2322
2323 /* Create DESKTOPINFO */
2324 DesktopInfoSize = sizeof(DESKTOPINFO) + DesktopName->Length + sizeof(WCHAR);
2325 pdesk->pDeskInfo = RtlAllocateHeap(pdesk->pheapDesktop,
2327 DesktopInfoSize);
2328 if (pdesk->pDeskInfo == NULL)
2329 {
2330 ERR("Failed to create the DESKTOP structure!\n");
2331 return STATUS_NO_MEMORY;
2332 }
2333
2334 /* Initialize the DESKTOPINFO */
2335 pdesk->pDeskInfo->pvDesktopBase = DesktopHeapSystemBase;
2336 pdesk->pDeskInfo->pvDesktopLimit = (PVOID)((ULONG_PTR)DesktopHeapSystemBase + HeapSize);
2338 DesktopName->Buffer,
2339 DesktopName->Length + sizeof(WCHAR));
2340 for (i = 0; i < NB_HOOKS; i++)
2341 {
2343 }
2344
2346 InitializeListHead(&pdesk->PtiList);
2347
2348 return STATUS_SUCCESS;
2349}
2350
2351/* SYSCALLS *******************************************************************/
2352
2353/*
2354 * NtUserCreateDesktop
2355 *
2356 * Creates a new desktop.
2357 *
2358 * Parameters
2359 * poaAttribs
2360 * Object Attributes.
2361 *
2362 * lpszDesktopDevice
2363 * Name of the device.
2364 *
2365 * pDeviceMode
2366 * Device Mode.
2367 *
2368 * dwFlags
2369 * Interaction flags.
2370 *
2371 * dwDesiredAccess
2372 * Requested type of access.
2373 *
2374 *
2375 * Return Value
2376 * If the function succeeds, the return value is a handle to the newly
2377 * created desktop. If the specified desktop already exists, the function
2378 * succeeds and returns a handle to the existing desktop. When you are
2379 * finished using the handle, call the CloseDesktop function to close it.
2380 * If the function fails, the return value is NULL.
2381 *
2382 * Status
2383 * @implemented
2384 */
2385
2389 OUT HDESK* phDesktop,
2392 IN PUNICODE_STRING lpszDesktopDevice OPTIONAL,
2393 IN LPDEVMODEW lpdmw OPTIONAL,
2395 IN ACCESS_MASK dwDesiredAccess)
2396{
2398 PDESKTOP pdesk = NULL;
2399 HDESK hDesk;
2401 UNICODE_STRING ClassName;
2402 LARGE_STRING WindowName;
2403 BOOL NoHooks = FALSE;
2404 PWND pWnd = NULL;
2405 CREATESTRUCTW Cs;
2406 PTHREADINFO ptiCurrent;
2407 PCLS pcls;
2408
2409 TRACE("Enter IntCreateDesktop\n");
2410
2412
2413 ASSERT(phDesktop);
2414 *phDesktop = NULL;
2415
2416 ptiCurrent = PsGetCurrentThreadWin32Thread();
2417 ASSERT(ptiCurrent);
2419
2420 /* Turn off hooks when calling any CreateWindowEx from inside win32k */
2421 NoHooks = (ptiCurrent->TIF_flags & TIF_DISABLEHOOKS);
2422 ptiCurrent->TIF_flags |= TIF_DISABLEHOOKS;
2423 ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags;
2424
2425 /*
2426 * Try to open already existing desktop
2427 */
2430 AccessMode,
2431 NULL,
2432 dwDesiredAccess,
2433 (PVOID)&Context,
2434 (PHANDLE)&hDesk);
2435 if (!NT_SUCCESS(Status))
2436 {
2437 ERR("ObOpenObjectByName failed to open/create desktop\n");
2438 goto Quit;
2439 }
2440
2441 /* In case the object was not created (eg if it existed), return now */
2442 if (Context == FALSE)
2443 {
2444 TRACE("IntCreateDesktop opened desktop '%wZ'\n", ObjectAttributes->ObjectName);
2446 goto Quit;
2447 }
2448
2449 /* Reference the desktop */
2451 0,
2453 KernelMode,
2454 (PVOID*)&pdesk,
2455 NULL);
2456 if (!NT_SUCCESS(Status))
2457 {
2458 ERR("Failed to reference desktop object\n");
2459 goto Quit;
2460 }
2461
2462 /* Get the desktop window class. The thread desktop does not belong to any desktop
2463 * so the classes created there (including the desktop class) are allocated in the shared heap
2464 * It would cause problems if we used a class that belongs to the caller
2465 */
2466 ClassName.Buffer = WC_DESKTOP;
2467 ClassName.Length = 0;
2468 pcls = IntGetAndReferenceClass(&ClassName, 0, TRUE);
2469 if (pcls == NULL)
2470 {
2471 ASSERT(FALSE);
2473 goto Quit;
2474 }
2475
2476 RtlZeroMemory(&WindowName, sizeof(WindowName));
2477 RtlZeroMemory(&Cs, sizeof(Cs));
2483 Cs.hInstance = hModClient; // hModuleWin; // Server side winproc!
2484 Cs.lpszName = (LPCWSTR) &WindowName;
2485 Cs.lpszClass = (LPCWSTR) &ClassName;
2486
2487 /* Use IntCreateWindow instead of co_UserCreateWindowEx because the later expects a thread with a desktop */
2488 pWnd = IntCreateWindow(&Cs, &WindowName, pcls, NULL, NULL, NULL, pdesk, WINVER);
2489 if (pWnd == NULL)
2490 {
2491 ERR("Failed to create desktop window for the new desktop\n");
2493 goto Quit;
2494 }
2495
2497 pdesk->DesktopWindow = UserHMGetHandle(pWnd);
2498 pdesk->pDeskInfo->spwnd = pWnd;
2499 pWnd->fnid = FNID_DESKTOP;
2500
2501 ClassName.Buffer = MAKEINTATOM(gpsi->atomSysClass[ICLS_HWNDMESSAGE]);
2502 ClassName.Length = 0;
2503 pcls = IntGetAndReferenceClass(&ClassName, 0, TRUE);
2504 if (pcls == NULL)
2505 {
2506 ASSERT(FALSE);
2508 goto Quit;
2509 }
2510
2511 RtlZeroMemory(&WindowName, sizeof(WindowName));
2512 RtlZeroMemory(&Cs, sizeof(Cs));
2513 Cs.cx = Cs.cy = 100;
2515 Cs.hInstance = hModClient; // hModuleWin; // Server side winproc!
2516 Cs.lpszName = (LPCWSTR)&WindowName;
2517 Cs.lpszClass = (LPCWSTR)&ClassName;
2518 pWnd = IntCreateWindow(&Cs, &WindowName, pcls, NULL, NULL, NULL, pdesk, WINVER);
2519 if (pWnd == NULL)
2520 {
2521 ERR("Failed to create message window for the new desktop\n");
2523 goto Quit;
2524 }
2525
2526 pdesk->spwndMessage = pWnd;
2527 pWnd->fnid = FNID_MESSAGEWND;
2528
2529 /* Now...
2530 if !(WinStaObject->Flags & WSF_NOIO) is (not set) for desktop input output mode (see wiki)
2531 Create Tooltip. Saved in DesktopObject->spwndTooltip.
2532 Tooltip dwExStyle: WS_EX_TOOLWINDOW|WS_EX_TOPMOST
2533 hWndParent are spwndMessage. Use hModuleWin for server side winproc!
2534 The rest is same as message window.
2535 http://msdn.microsoft.com/en-us/library/bb760250(VS.85).aspx
2536 */
2538
2539Quit:
2540 if (pdesk != NULL)
2541 {
2542 ObDereferenceObject(pdesk);
2543 }
2544 if (!NT_SUCCESS(Status) && hDesk != NULL)
2545 {
2546 ObCloseHandle(hDesk, AccessMode);
2547 hDesk = NULL;
2548 }
2549 if (!NoHooks)
2550 {
2551 ptiCurrent->TIF_flags &= ~TIF_DISABLEHOOKS;
2552 ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags;
2553 }
2554
2555 TRACE("Leave IntCreateDesktop, Status 0x%08lx\n", Status);
2556
2557 if (NT_SUCCESS(Status))
2558 *phDesktop = hDesk;
2559 else
2561 return Status;
2562}
2563
2564HDESK APIENTRY
2567 PUNICODE_STRING lpszDesktopDevice,
2568 LPDEVMODEW lpdmw,
2569 DWORD dwFlags,
2570 ACCESS_MASK dwDesiredAccess)
2571{
2573 HDESK hDesk;
2574 HDESK Ret = NULL;
2575
2576 TRACE("Enter NtUserCreateDesktop\n");
2578
2579 Status = IntCreateDesktop(&hDesk,
2581 UserMode,
2582 lpszDesktopDevice,
2583 lpdmw,
2584 dwFlags,
2585 dwDesiredAccess);
2586 if (!NT_SUCCESS(Status))
2587 {
2588 ERR("IntCreateDesktop failed, Status 0x%08lx\n", Status);
2589 // SetLastNtError(Status);
2590 goto Exit; // Return NULL
2591 }
2592
2593 Ret = hDesk;
2594
2595Exit:
2596 TRACE("Leave NtUserCreateDesktop, ret=0x%p\n", Ret);
2597 UserLeave();
2598 return Ret;
2599}
2600
2601/*
2602 * NtUserOpenDesktop
2603 *
2604 * Opens an existing desktop.
2605 *
2606 * Parameters
2607 * lpszDesktopName
2608 * Name of the existing desktop.
2609 *
2610 * dwFlags
2611 * Interaction flags.
2612 *
2613 * dwDesiredAccess
2614 * Requested type of access.
2615 *
2616 * Return Value
2617 * Handle to the desktop or zero on failure.
2618 *
2619 * Status
2620 * @implemented
2621 */
2622
2623HDESK APIENTRY
2626 DWORD dwFlags,
2627 ACCESS_MASK dwDesiredAccess)
2628{
2630 HDESK Desktop;
2631
2635 UserMode,
2636 NULL,
2637 dwDesiredAccess,
2638 NULL,
2639 (HANDLE*)&Desktop);
2640
2641 if (!NT_SUCCESS(Status))
2642 {
2643 ERR("Failed to open desktop\n");
2645 return NULL;
2646 }
2647
2648 TRACE("Opened desktop %S with handle 0x%p\n", ObjectAttributes->ObjectName->Buffer, Desktop);
2649
2650 return Desktop;
2651}
2652
2654 BOOL fInherit,
2655 ACCESS_MASK dwDesiredAccess)
2656{
2660 HDESK hdesk = NULL;
2661
2662 if (!gpdeskInputDesktop)
2663 {
2664 return NULL;
2665 }
2666
2667 if (pti->ppi->prpwinsta != InputWindowStation)
2668 {
2669 ERR("Tried to open input desktop from non interactive winsta!\n");
2671 return NULL;
2672 }
2673
2674 if (fInherit) HandleAttributes = OBJ_INHERIT;
2675
2676 /* Create a new handle to the object */
2680 NULL,
2681 dwDesiredAccess,
2683 UserMode,
2684 (PHANDLE)&hdesk);
2685
2686 if (!NT_SUCCESS(Status))
2687 {
2688 ERR("Failed to open input desktop object\n");
2690 }
2691
2692 return hdesk;
2693}
2694
2695/*
2696 * NtUserOpenInputDesktop
2697 *
2698 * Opens the input (interactive) desktop.
2699 *
2700 * Parameters
2701 * dwFlags
2702 * Interaction flags.
2703 *
2704 * fInherit
2705 * Inheritance option.
2706 *
2707 * dwDesiredAccess
2708 * Requested type of access.
2709 *
2710 * Return Value
2711 * Handle to the input desktop or zero on failure.
2712 *
2713 * Status
2714 * @implemented
2715 */
2716
2717HDESK APIENTRY
2719 DWORD dwFlags,
2720 BOOL fInherit,
2721 ACCESS_MASK dwDesiredAccess)
2722{
2723 HDESK hdesk;
2724
2726 TRACE("Enter NtUserOpenInputDesktop gpdeskInputDesktop 0x%p\n", gpdeskInputDesktop);
2727
2728 hdesk = UserOpenInputDesktop(dwFlags, fInherit, dwDesiredAccess);
2729
2730 TRACE("NtUserOpenInputDesktop returning 0x%p\n", hdesk);
2731 UserLeave();
2732 return hdesk;
2733}
2734
2735/*
2736 * NtUserCloseDesktop
2737 *
2738 * Closes a desktop handle.
2739 *
2740 * Parameters
2741 * hDesktop
2742 * Handle to the desktop.
2743 *
2744 * Return Value
2745 * Status
2746 *
2747 * Remarks
2748 * The desktop handle can be created with NtUserCreateDesktop or
2749 * NtUserOpenDesktop. This function will fail if any thread in the calling
2750 * process is using the specified desktop handle or if the handle refers
2751 * to the initial desktop of the calling process.
2752 *
2753 * Status
2754 * @implemented
2755 */
2756
2758NtUserCloseDesktop(HDESK hDesktop)
2759{
2760 PDESKTOP pdesk;
2762 BOOL Ret = FALSE;
2763
2764 TRACE("NtUserCloseDesktop(0x%p) called\n", hDesktop);
2766
2767 if (hDesktop == gptiCurrent->hdesk || hDesktop == gptiCurrent->ppi->hdeskStartup)
2768 {
2769 ERR("Attempted to close thread desktop\n");
2771 goto Exit; // Return FALSE
2772 }
2773
2774 Status = IntValidateDesktopHandle(hDesktop, UserMode, 0, &pdesk);
2775 if (!NT_SUCCESS(Status))
2776 {
2777 ERR("Validation of desktop handle 0x%p failed\n", hDesktop);
2778 goto Exit; // Return FALSE
2779 }
2780
2781 ObDereferenceObject(pdesk);
2782
2783 Status = ObCloseHandle(hDesktop, UserMode);
2784 if (!NT_SUCCESS(Status))
2785 {
2786 ERR("Failed to close desktop handle 0x%p\n", hDesktop);
2788 goto Exit; // Return FALSE
2789 }
2790
2791 Ret = TRUE;
2792
2793Exit:
2794 TRACE("Leave NtUserCloseDesktop, ret=%i\n", Ret);
2795 UserLeave();
2796 return Ret;
2797}
2798
2799/*
2800 * NtUserPaintDesktop
2801 *
2802 * The NtUserPaintDesktop function fills the clipping region in the
2803 * specified device context with the desktop pattern or wallpaper. The
2804 * function is provided primarily for shell desktops.
2805 *
2806 * Parameters
2807 * hDC
2808 * Handle to the device context.
2809 *
2810 * Status
2811 * @implemented
2812 */
2813
2816{
2817 BOOL Ret;
2818
2820 TRACE("Enter NtUserPaintDesktop\n");
2821
2822 Ret = IntPaintDesktop(hDC);
2823
2824 TRACE("Leave NtUserPaintDesktop, ret=%i\n", Ret);
2825 UserLeave();
2826 return Ret;
2827}
2828
2829/*
2830 * NtUserResolveDesktop
2831 *
2832 * The NtUserResolveDesktop function attempts to retrieve valid handles to
2833 * a desktop and a window station suitable for the specified process.
2834 * The specified desktop path string is used only as a hint for the resolution.
2835 *
2836 * See the description of IntResolveDesktop for more details.
2837 *
2838 * Parameters
2839 * ProcessHandle
2840 * Handle to a user process.
2841 *
2842 * DesktopPath
2843 * The desktop path string used as a hint for desktop resolution.
2844 *
2845 * bInherit
2846 * Whether or not the returned handles are inheritable.
2847 *
2848 * phWinSta
2849 * Pointer to a window station handle.
2850 *
2851 * Return Value
2852 * Handle to the desktop (direct return value) and
2853 * handle to the associated window station (by pointer).
2854 * NULL in case of failure.
2855 *
2856 * Remarks
2857 * Callable by CSRSS only.
2858 *
2859 * Status
2860 * @implemented
2861 */
2862
2863HDESK
2864NTAPI
2867 IN PUNICODE_STRING DesktopPath,
2868 IN BOOL bInherit,
2869 OUT HWINSTA* phWinSta)
2870{
2873 HWINSTA hWinSta = NULL;
2874 HDESK hDesktop = NULL;
2875 UNICODE_STRING CapturedDesktopPath;
2876
2877 /* Allow only the Console Server to perform this operation (via CSRSS) */
2879 return NULL;
2880
2881 /* Get the process object the user handle was referencing */
2885 UserMode,
2886 (PVOID*)&Process,
2887 NULL);
2888 if (!NT_SUCCESS(Status))
2889 return NULL;
2890
2892
2893 _SEH2_TRY
2894 {
2895 /* Probe the handle pointer */
2896 // ProbeForWriteHandle
2897 ProbeForWrite(phWinSta, sizeof(HWINSTA), sizeof(HWINSTA));
2898 }
2900 {
2902 _SEH2_YIELD(goto Quit);
2903 }
2904 _SEH2_END;
2905
2906 /* Capture the user desktop path string */
2907 Status = ProbeAndCaptureUnicodeString(&CapturedDesktopPath,
2908 UserMode,
2909 DesktopPath);
2910 if (!NT_SUCCESS(Status))
2911 goto Quit;
2912
2913 /* Call the internal function */
2915 &CapturedDesktopPath,
2916 bInherit,
2917 &hWinSta,
2918 &hDesktop);
2919 if (!NT_SUCCESS(Status))
2920 {
2921 ERR("IntResolveDesktop failed, Status 0x%08lx\n", Status);
2922 hWinSta = NULL;
2923 hDesktop = NULL;
2924 }
2925
2926 _SEH2_TRY
2927 {
2928 /* Return the window station handle */
2929 *phWinSta = hWinSta;
2930 }
2932 {
2934
2935 /* We failed, close the opened desktop and window station */
2936 if (hDesktop) ObCloseHandle(hDesktop, UserMode);
2937 hDesktop = NULL;
2938 if (hWinSta) ObCloseHandle(hWinSta, UserMode);
2939 }
2940 _SEH2_END;
2941
2942 /* Free the captured string */
2943 ReleaseCapturedUnicodeString(&CapturedDesktopPath, UserMode);
2944
2945Quit:
2946 UserLeave();
2947
2948 /* Dereference the process object */
2950
2951 /* Return the desktop handle */
2952 return hDesktop;
2953}
2954
2955/*
2956 * NtUserSwitchDesktop
2957 *
2958 * Sets the current input (interactive) desktop.
2959 *
2960 * Parameters
2961 * hDesktop
2962 * Handle to desktop.
2963 *
2964 * Return Value
2965 * Status
2966 *
2967 * Status
2968 * @unimplemented
2969 */
2970
2973{
2974 PDESKTOP pdesk;
2976 BOOL bRedrawDesktop;
2977 BOOL Ret = FALSE;
2978
2980 TRACE("Enter NtUserSwitchDesktop(0x%p)\n", hdesk);
2981
2982 Status = IntValidateDesktopHandle(hdesk, UserMode, 0, &pdesk);
2983 if (!NT_SUCCESS(Status))
2984 {
2985 ERR("Validation of desktop handle 0x%p failed\n", hdesk);
2986 goto Exit; // Return FALSE
2987 }
2988
2989 if (PsGetCurrentProcessSessionId() != pdesk->rpwinstaParent->dwSessionId)
2990 {
2991 ObDereferenceObject(pdesk);
2992 ERR("NtUserSwitchDesktop called for a desktop of a different session\n");
2993 goto Exit; // Return FALSE
2994 }
2995
2996 if (pdesk == gpdeskInputDesktop)
2997 {
2998 ObDereferenceObject(pdesk);
2999 WARN("NtUserSwitchDesktop called for active desktop\n");
3000 Ret = TRUE;
3001 goto Exit;
3002 }
3003
3004 /*
3005 * Don't allow applications switch the desktop if it's locked, unless the caller
3006 * is the logon application itself
3007 */
3008 if ((pdesk->rpwinstaParent->Flags & WSS_LOCKED) &&
3010 {
3011 ObDereferenceObject(pdesk);
3012 ERR("Switching desktop 0x%p denied because the window station is locked!\n", hdesk);
3013 goto Exit; // Return FALSE
3014 }
3015
3016 if (pdesk->rpwinstaParent != InputWindowStation)
3017 {
3018 ObDereferenceObject(pdesk);
3019 ERR("Switching desktop 0x%p denied because desktop doesn't belong to the interactive winsta!\n", hdesk);
3020 goto Exit; // Return FALSE
3021 }
3022
3023 /* FIXME: Fail if the process is associated with a secured
3024 desktop such as Winlogon or Screen-Saver */
3025 /* FIXME: Connect to input device */
3026
3027 TRACE("Switching from desktop 0x%p to 0x%p\n", gpdeskInputDesktop, pdesk);
3028
3029 bRedrawDesktop = FALSE;
3030
3031 /* The first time SwitchDesktop is called, gpdeskInputDesktop is NULL */
3032 if (gpdeskInputDesktop != NULL)
3033 {
3035 bRedrawDesktop = TRUE;
3036
3037 /* Hide the previous desktop window */
3039 }
3040
3041 /* Set the active desktop in the desktop's window station. */
3043
3044 /* Set the global state. */
3045 gpdeskInputDesktop = pdesk;
3046
3047 /* Show the new desktop window */
3049
3050 TRACE("SwitchDesktop gpdeskInputDesktop 0x%p\n", gpdeskInputDesktop);
3051 ObDereferenceObject(pdesk);
3052
3053 Ret = TRUE;
3054
3055Exit:
3056 TRACE("Leave NtUserSwitchDesktop, ret=%i\n", Ret);
3057 UserLeave();
3058 return Ret;
3059}
3060
3061/*
3062 * NtUserGetThreadDesktop
3063 *
3064 * Status
3065 * @implemented
3066 */
3067
3068HDESK APIENTRY
3070{
3071 HDESK hDesk;
3073 PTHREADINFO pti;
3075 PDESKTOP DesktopObject;
3077
3079 TRACE("Enter NtUserGetThreadDesktop\n");
3080
3081 if (!dwThreadId)
3082 {
3084 hDesk = NULL;
3085 goto Quit;
3086 }
3087
3088 /* Validate the Win32 thread and retrieve its information */
3090 if (pti)
3091 {
3092 /* Get the desktop handle of the thread */
3093 hDesk = pti->hdesk;
3094 Process = pti->ppi->peProcess;
3095 }
3096 else if (hConsoleDesktop)
3097 {
3098 /*
3099 * The thread may belong to a console, so attempt to use the provided
3100 * console desktop handle as a fallback. Otherwise this means that the
3101 * thread is either not Win32 or invalid.
3102 */
3103 hDesk = hConsoleDesktop;
3105 }
3106 else
3107 {
3109 hDesk = NULL;
3110 goto Quit;
3111 }
3112
3113 if (!hDesk)
3114 {
3115 ERR("Desktop information of thread 0x%x broken!?\n", dwThreadId);
3116 goto Quit;
3117 }
3118
3120 {
3121 /*
3122 * Just return the handle, since we queried the desktop handle
3123 * of a thread running in the same context.
3124 */
3125 goto Quit;
3126 }
3127
3128 /*
3129 * We could just use the cached rpdesk instead of looking up the handle,
3130 * but it may actually be safer to validate the desktop and get a temporary
3131 * reference to it so that it does not disappear under us (e.g. when the
3132 * desktop is being destroyed) during the operation.
3133 */
3134 /*
3135 * Switch into the context of the thread we are trying to get
3136 * the desktop from, so we can use the handle.
3137 */
3138 KeAttachProcess(&Process->Pcb);
3140 0,
3142 UserMode,
3143 (PVOID*)&DesktopObject,
3146
3147 if (NT_SUCCESS(Status))
3148 {
3149 /*
3150 * Lookup our handle table if we can find a handle to the desktop object.
3151 * If not, create one.
3152 * QUESTION: Do we really need to create a handle in case it doesn't exist??
3153 */
3154 hDesk = IntGetDesktopObjectHandle(DesktopObject);
3155
3156 /* All done, we got a valid handle to the desktop */
3157 ObDereferenceObject(DesktopObject);
3158 }
3159 else
3160 {
3161 /* The handle could not be found, there is nothing to get... */
3162 hDesk = NULL;
3163 }
3164
3165 if (!hDesk)
3166 {
3167 ERR("Could not retrieve or access desktop for thread 0x%x\n", dwThreadId);
3169 }
3170
3171Quit:
3172 TRACE("Leave NtUserGetThreadDesktop, hDesk = 0x%p\n", hDesk);
3173 UserLeave();
3174 return hDesk;
3175}
3176
3177static NTSTATUS
3179{
3180 PPROCESSINFO ppi;
3181 PW32HEAP_USER_MAPPING HeapMapping, *PrevLink;
3183
3184 TRACE("IntUnmapDesktopView called for desktop object %p\n", pdesk);
3185
3187
3188 /*
3189 * Unmap if we're the last thread using the desktop.
3190 * Start the search at the next mapping: skip the first entry
3191 * as it must be the global user heap mapping.
3192 */
3193 PrevLink = &ppi->HeapMappings.Next;
3194 HeapMapping = *PrevLink;
3195 while (HeapMapping != NULL)
3196 {
3197 if (HeapMapping->KernelMapping == (PVOID)pdesk->pheapDesktop)
3198 {
3199 if (--HeapMapping->Count == 0)
3200 {
3201 *PrevLink = HeapMapping->Next;
3202
3203 TRACE("ppi 0x%p unmapped heap of desktop 0x%p\n", ppi, pdesk);
3205 HeapMapping->UserMapping);
3206
3207 ObDereferenceObject(pdesk);
3208
3209 UserHeapFree(HeapMapping);
3210 break;
3211 }
3212 }
3213
3214 PrevLink = &HeapMapping->Next;
3215 HeapMapping = HeapMapping->Next;
3216 }
3217
3218 return Status;
3219}
3220
3221static NTSTATUS
3223{
3224 PPROCESSINFO ppi;
3225 PW32HEAP_USER_MAPPING HeapMapping, *PrevLink;
3226 PVOID UserBase = NULL;
3227 SIZE_T ViewSize = 0;
3230
3231 TRACE("IntMapDesktopView called for desktop object 0x%p\n", pdesk);
3232
3234
3235 /*
3236 * Find out if another thread already mapped the desktop heap.
3237 * Start the search at the next mapping: skip the first entry
3238 * as it must be the global user heap mapping.
3239 */
3240 PrevLink = &ppi->HeapMappings.Next;
3241 HeapMapping = *PrevLink;
3242 while (HeapMapping != NULL)
3243 {
3244 if (HeapMapping->KernelMapping == (PVOID)pdesk->pheapDesktop)
3245 {
3246 HeapMapping->Count++;
3247 return STATUS_SUCCESS;
3248 }
3249
3250 PrevLink = &HeapMapping->Next;
3251 HeapMapping = HeapMapping->Next;
3252 }
3253
3254 /* We're the first, map the heap */
3255 Offset.QuadPart = 0;
3256 Status = MmMapViewOfSection(pdesk->hsectionDesktop,
3258 &UserBase,
3259 0,
3260 0,
3261 &Offset,
3262 &ViewSize,
3263 ViewUnmap,
3266 if (!NT_SUCCESS(Status))
3267 {
3268 ERR("Failed to map desktop\n");
3269 return Status;
3270 }
3271
3272 TRACE("ppi 0x%p mapped heap of desktop 0x%p\n", ppi, pdesk);
3273
3274 /* Add the mapping */
3275 HeapMapping = UserHeapAlloc(sizeof(*HeapMapping));
3276 if (HeapMapping == NULL)
3277 {
3279 ERR("UserHeapAlloc() failed!\n");
3280 return STATUS_NO_MEMORY;
3281 }
3282
3283 HeapMapping->Next = NULL;
3284 HeapMapping->KernelMapping = (PVOID)pdesk->pheapDesktop;
3285 HeapMapping->UserMapping = UserBase;
3286 HeapMapping->Limit = ViewSize;
3287 HeapMapping->Count = 1;
3288 *PrevLink = HeapMapping;
3289
3290 ObReferenceObject(pdesk);
3291
3292 return STATUS_SUCCESS;
3293}
3294
3295BOOL
3297 IN BOOL FreeOnFailure)
3298{
3299 PDESKTOP pdesk = NULL, pdeskOld;
3300 PTHREADINFO pti;
3302 PCLIENTTHREADINFO pctiOld, pctiNew = NULL;
3303 PCLIENTINFO pci;
3304
3306
3307 TRACE("IntSetThreadDesktop hDesktop:0x%p, FOF:%i\n",hDesktop, FreeOnFailure);
3308
3310 pci = pti->pClientInfo;
3311
3312 /* If the caller gave us a desktop, ensure it is valid */
3313 if (hDesktop != NULL)
3314 {
3315 /* Validate the new desktop. */
3316 Status = IntValidateDesktopHandle(hDesktop, UserMode, 0, &pdesk);
3317 if (!NT_SUCCESS(Status))
3318 {
3319 ERR("Validation of desktop handle 0x%p failed\n", hDesktop);
3320 return FALSE;
3321 }
3322
3323 if (pti->rpdesk == pdesk)
3324 {
3325 /* Nothing to do */
3326 ObDereferenceObject(pdesk);
3327 return TRUE;
3328 }
3329 }
3330
3331 /* Make sure that we don't own any window in the current desktop */
3332 if (!IsListEmpty(&pti->WindowListHead))
3333 {
3334 if (pdesk)
3335 ObDereferenceObject(pdesk);
3336 ERR("Attempted to change thread desktop although the thread has windows!\n");
3338 return FALSE;
3339 }
3340
3341 /* Desktop is being re-set so clear out foreground. */
3342 if (pti->rpdesk != pdesk && pti->MessageQueue == gpqForeground)
3343 {
3344 // Like above, there shouldn't be any windows, hooks or anything active on this threads desktop!
3346 }
3347
3348 /* Before doing the switch, map the new desktop heap and allocate the new pcti */
3349 if (pdesk != NULL)
3350 {
3351 Status = IntMapDesktopView(pdesk);
3352 if (!NT_SUCCESS(Status))
3353 {
3354 ERR("Failed to map desktop heap!\n");
3355 ObDereferenceObject(pdesk);
3357 return FALSE;
3358 }
3359
3360 pctiNew = DesktopHeapAlloc(pdesk, sizeof(CLIENTTHREADINFO));
3361 if (pctiNew == NULL)
3362 {
3363 ERR("Failed to allocate new pcti\n");
3364 IntUnmapDesktopView(pdesk);
3365 ObDereferenceObject(pdesk);
3367 return FALSE;
3368 }
3369 }
3370
3371 /*
3372 * Processes, in particular Winlogon.exe, that manage window stations
3373 * (especially the interactive WinSta0 window station) and desktops,
3374 * may not be able to connect at startup to a window station and have
3375 * an associated desktop as well, if none exists on the system already.
3376 * Because creating a new window station does not affect the window station
3377 * associated to the process, and because neither by associating a window
3378 * station to the process nor creating a new desktop on it does associate
3379 * a startup desktop to that process, the process has to actually assigns
3380 * one of its threads to a desktop so that it gets automatically an assigned
3381 * startup desktop.
3382 *
3383 * This is what actually happens for Winlogon.exe, which is started without
3384 * any window station and desktop. By creating the first (and therefore
3385 * interactive) WinSta0 window station, then assigning WinSta0 to itself
3386 * and creating the Default desktop on it, and then assigning this desktop
3387 * to its main thread, Winlogon.exe basically does the similar steps that
3388 * would have been done automatically at its startup if there were already
3389 * an existing WinSta0 window station and Default desktop.
3390 *
3391 * Of course all this must not be done if we are a SYSTEM or CSRSS thread.
3392 */
3393 // if (pti->ppi->peProcess != gpepCSRSS)
3394 if (!(pti->TIF_flags & (TIF_SYSTEMTHREAD | TIF_CSRSSTHREAD)) &&
3395 pti->ppi->rpdeskStartup == NULL && hDesktop != NULL)
3396 {
3397 ERR("The process 0x%p '%s' didn't have an assigned startup desktop before, assigning it now!\n",
3398 pti->ppi->peProcess, pti->ppi->peProcess->ImageFileName);
3399
3400 pti->ppi->hdeskStartup = hDesktop;
3401 pti->ppi->rpdeskStartup = pdesk;
3402 }
3403
3404 /* free all classes or move them to the shared heap */
3405 if (pti->rpdesk != NULL)
3406 {
3407 if (!IntCheckProcessDesktopClasses(pti->rpdesk, FreeOnFailure))
3408 {
3409 ERR("Failed to move process classes to shared heap!\n");
3410 if (pdesk)
3411 {
3412 DesktopHeapFree(pdesk, pctiNew);
3413 IntUnmapDesktopView(pdesk);
3414 ObDereferenceObject(pdesk);
3415 }
3416 return FALSE;
3417 }
3418 }
3419
3420 pdeskOld = pti->rpdesk;
3421 if (pti->pcti != &pti->cti)
3422 pctiOld = pti->pcti;
3423 else
3424 pctiOld = NULL;
3425
3426 /* do the switch */
3427 if (pdesk != NULL)
3428 {
3429 pti->rpdesk = pdesk;
3430 pti->hdesk = hDesktop;
3431 pti->pDeskInfo = pti->rpdesk->pDeskInfo;
3432 pti->pcti = pctiNew;
3433
3435 pci->pDeskInfo = (PVOID)((ULONG_PTR)pti->pDeskInfo - pci->ulClientDelta);
3436 pci->pClientThreadInfo = (PVOID)((ULONG_PTR)pti->pcti - pci->ulClientDelta);
3437
3438 /* initialize the new pcti */
3439 if (pctiOld != NULL)
3440 {
3441 RtlCopyMemory(pctiNew, pctiOld, sizeof(CLIENTTHREADINFO));
3442 }
3443 else
3444 {
3445 RtlZeroMemory(pctiNew, sizeof(CLIENTTHREADINFO));
3446 pci->fsHooks = pti->fsHooks;
3447 pci->dwTIFlags = pti->TIF_flags;
3448 }
3449 }
3450 else
3451 {
3452 pti->rpdesk = NULL;
3453 pti->hdesk = NULL;
3454 pti->pDeskInfo = NULL;
3455 pti->pcti = &pti->cti; // Always point inside so there will be no crash when posting or sending msg's!
3456 pci->ulClientDelta = 0;
3457 pci->pDeskInfo = NULL;
3458 pci->pClientThreadInfo = NULL;
3459 }
3460
3461 /* clean up the old desktop */
3462 if (pdeskOld != NULL)
3463 {
3464 RemoveEntryList(&pti->PtiLink);
3465 if (pctiOld) DesktopHeapFree(pdeskOld, pctiOld);
3466 IntUnmapDesktopView(pdeskOld);
3467 ObDereferenceObject(pdeskOld);
3468 }
3469
3470 if (pdesk)
3471 {
3472 InsertTailList(&pdesk->PtiList, &pti->PtiLink);
3473 }
3474
3475 TRACE("IntSetThreadDesktop: pti 0x%p ppi 0x%p switched from object 0x%p to 0x%p\n", pti, pti->ppi, pdeskOld, pdesk);
3476
3477 return TRUE;
3478}
3479
3480/*
3481 * NtUserSetThreadDesktop
3482 *
3483 * Status
3484 * @implemented
3485 */
3486
3489{
3490 BOOL ret = FALSE;
3491
3493
3494 // FIXME: IntSetThreadDesktop validates the desktop handle, it should happen
3495 // here too and set the NT error level. Q. Is it necessary to have the validation
3496 // in IntSetThreadDesktop? Is it needed there too?
3497 if (hDesktop || (!hDesktop && PsGetCurrentProcess() == gpepCSRSS))
3498 ret = IntSetThreadDesktop(hDesktop, FALSE);
3499
3500 UserLeave();
3501
3502 return ret;
3503}
3504
3505/* EOF */
static HDC hDC
Definition: 3dtext.c:33
NTSTATUS NTAPI MmUnmapViewInSessionSpace(IN PVOID MappedBase)
Definition: section.c:2722
NTSTATUS NTAPI MmUnmapViewOfSection(IN PEPROCESS Process, IN PVOID BaseAddress)
Definition: section.c:2750
#define CODE_SEG(...)
unsigned char BOOLEAN
#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:97
#define HandleToULong(h)
Definition: basetsd.h:95
#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:590
_Inout_ PFCB _Inout_ PUNICODE_STRING RemainingName
Definition: cdprocs.h:802
Definition: list.h:37
WPARAM wParam
Definition: combotst.c:138
struct @1641 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
#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:158
#define APIENTRY
Definition: api.h:79
#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
PSERVERINFO gpsi
Definition: imm.c:18
static const WCHAR Message[]
Definition: register.c:74
#define RGB(r, g, b)
Definition: precomp.h:71
#define GetBValue(quad)
Definition: precomp.h:75
#define GetGValue(quad)
Definition: precomp.h:74
#define GetRValue(quad)
Definition: precomp.h:73
#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
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 OPTIONAL PRECTL lprc, IN LPCWSTR String, IN INT Count, IN OPTIONAL LPINT Dx, IN DWORD dwCodePage)
Definition: freetype.c:7304
_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:25
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
#define ISITHOOKED(HookId)
Definition: hook.h:6
const char cursor[]
Definition: icontest.c:13
_Check_return_ _CRTIMP int __cdecl _scwprintf(_In_z_ _Printf_format_string_ const wchar_t *_Format,...)
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define PROCESS_QUERY_INFORMATION
Definition: pstypes.h:167
#define TIF_CSRSSTHREAD
Definition: ntuser.h:266
#define FNID_DESTROY
Definition: ntuser.h:898
#define FNID_DESKTOP
Definition: ntuser.h:862
#define UserHMGetHandle(obj)
Definition: ntuser.h:230
#define CURSORF_CURRENT
Definition: ntuser.h:1207
struct _DESKTOPINFO DESKTOPINFO
#define FNID_MESSAGEWND
Definition: ntuser.h:864
#define TIF_SYSTEMTHREAD
Definition: ntuser.h:265
#define NB_HOOKS
Definition: ntuser.h:127
#define TIF_DISABLEHOOKS
Definition: ntuser.h:291
#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
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
#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
#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
static LPCSTR lpstr
Definition: font.c:51
static DWORD *static HFONT(WINAPI *pCreateFontIndirectExA)(const ENUMLOGFONTEXDVA *)
ObjectType
Definition: metafile.c:81
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#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
unsigned int UINT
Definition: ndis.h:50
#define KernelMode
Definition: asm.h:34
#define UserMode
Definition: asm.h:35
_In_ HANDLE ProcessHandle
Definition: mmfuncs.h:403
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T ViewSize
Definition: mmfuncs.h:408
#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:433
#define _In_
Definition: no_sal2.h:158
ULONG ACCESS_MASK
Definition: nt_native.h:40
#define PAGE_READWRITE
Definition: nt_native.h:1304
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
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:1279
#define MEM_RELEASE
Definition: nt_native.h:1316
#define REG_NONE
Definition: nt_native.h:1492
#define MEM_COMMIT
Definition: nt_native.h:1313
#define HEAP_NO_SERIALIZE
Definition: nt_native.h:1692
#define MAXIMUM_ALLOWED
Definition: nt_native.h:83
#define UNICODE_NULL
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
@ SynchronizationEvent
__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:992
__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
PVOID NTAPI PsGetProcessWin32Process(PEPROCESS Process)
Definition: process.c:1193
POBJECT_TYPE PsProcessType
Definition: process.c:20
PVOID NTAPI PsGetCurrentProcessWin32Process(VOID)
Definition: process.c:1183
HANDLE NTAPI PsGetCurrentProcessId(VOID)
Definition: process.c:1123
ULONG NTAPI PsGetCurrentProcessSessionId(VOID)
Definition: process.c:1133
PVOID NTAPI PsGetCurrentThreadWin32Thread(VOID)
Definition: thread.c:805
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
#define STATUS_OBJECT_NAME_EXISTS
Definition: ntstatus.h:114
#define STATUS_NAME_TOO_LONG
Definition: ntstatus.h:498
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:535
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:447
HINSTANCE hModClient
Definition: ntuser.c:25
BOOL g_AlwaysDisplayVersion
Definition: ntuser.c:17
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:258
PTHREADINFO gptiCurrent
Definition: ntuser.c:15
VOID FASTCALL UserEnterExclusive(VOID)
Definition: ntuser.c:249
BOOL FASTCALL UserIsEnteredExclusive(VOID)
Definition: ntuser.c:231
#define L(x)
Definition: ntvdm.h:50
NTSTATUS NTAPI ObCloseHandle(IN HANDLE Handle, IN KPROCESSOR_MODE AccessMode)
Definition: obhandle.c:3379
BOOLEAN NTAPI ObFindHandleForObject(IN PEPROCESS Process, IN PVOID Object, IN POBJECT_TYPE ObjectType, IN POBJECT_HANDLE_INFORMATION HandleInformation, OUT PHANDLE Handle)
Definition: obhandle.c:2856
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:2742
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:2532
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:1039
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:494
#define LRESULT
Definition: ole.h:14
#define LOWORD(l)
Definition: pedump.c:82
#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
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:66
#define _SEH2_END
Definition: pseh2_64.h:155
#define _SEH2_TRY
Definition: pseh2_64.h:55
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:168
#define IntSysCreateRectpRgnIndirect(prc)
Definition: region.h:93
#define list
Definition: rosglue.h:35
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, IN OUT PVOID *BaseAddress, IN ULONG_PTR ZeroBits, IN SIZE_T CommitSize, IN OUT PLARGE_INTEGER SectionOffset OPTIONAL, IN OUT PSIZE_T ViewSize, IN SECTION_INHERIT InheritDisposition, IN ULONG AllocationType, IN ULONG Protect)
Definition: section.c:4001
#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
Definition: polytest.cpp:41
base of all file and directory entries
Definition: entries.h:83
Definition: window.c:28
ULONG_PTR ulClientDelta
Definition: ntuser.h:326
ULONG fsHooks
Definition: ntuser.h:328
PCLIENTTHREADINFO pClientThreadInfo
Definition: ntuser.h:332
DWORD dwTIFlags
Definition: ntuser.h:324
PDESKTOPINFO pDeskInfo
Definition: ntuser.h:325
Definition: ntuser.h:566
HBRUSH hbrBackground
Definition: ntuser.h:587
ULONG CURSORF_flags
Definition: cursoricon.h:16
WCHAR szDesktopName[1]
Definition: ntuser.h:158
LIST_ENTRY aphkStart[NB_HOOKS]
Definition: ntuser.h:139
struct _WND * spwnd
Definition: ntuser.h:137
PVOID pvDesktopLimit
Definition: ntuser.h:136
PVOID pvDesktopBase
Definition: ntuser.h:135
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:358
ULONG DefaultNonPagedPoolCharge
Definition: obtypes.h:365
OBJECT_TYPE_INITIALIZER TypeInfo
Definition: obtypes.h:390
WCHAR szCSDVersion[128]
Definition: rtltypes.h:274
ULONG dwOSVersionInfoSize
Definition: rtltypes.h:269
ULONG dwBuildNumber
Definition: rtltypes.h:272
LPCWSTR lpstr
Definition: wingdi.h:2564
UINT n
Definition: wingdi.h:2563
HWINSTA hwinsta
Definition: win32.h:268
HDESK hdeskStartup
Definition: win32.h:264
W32HEAP_USER_MAPPING HeapMappings
Definition: win32.h:291
struct _DESKTOP * rpdeskStartup
Definition: win32.h:259
struct _WINSTATION_OBJECT * prpwinsta
Definition: win32.h:267
Definition: region.h:8
LIST_ENTRY ListEntry
Definition: desktop.h:67
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:194
PPROCESSINFO ppi
Definition: win32.h:88
struct _DESKTOPINFO * pDeskInfo
Definition: win32.h:93
ULONG fsHooks
Definition: win32.h:117
CLIENTTHREADINFO cti
Definition: win32.h:144
struct _CLIENTINFO * pClientInfo
Definition: win32.h:94
HDESK hdesk
Definition: win32.h:108
struct _CLIENTTHREADINFO * pcti
Definition: win32.h:91
FLONG TIF_flags
Definition: win32.h:95
struct _DESKTOP * rpdesk
Definition: win32.h:92
LIST_ENTRY WindowListHead
Definition: win32.h:155
struct _USER_MESSAGE_QUEUE * MessageQueue
Definition: win32.h:89
LIST_ENTRY PtiLink
Definition: win32.h:126
USHORT MaximumLength
Definition: env_spec_w32.h:370
struct _DESKTOP * Desktop
Definition: msgqueue.h:50
struct _W32HEAP_USER_MAPPING * Next
Definition: win32.h:199
ULONG_PTR Limit
Definition: win32.h:202
UINT flags
Definition: winuser.h:3597
struct _DESKTOP * ActiveDesktop
Definition: winsta.h:42
LIST_ENTRY DesktopListHead
Definition: winsta.h:19
Definition: ntuser.h:694
PCLS pcls
Definition: ntuser.h:720
THRDESKHEAD head
Definition: ntuser.h:695
DWORD style
Definition: ntuser.h:706
DWORD fnid
Definition: ntuser.h:709
RECT rcWindow
Definition: ntuser.h:716
LPCWSTR lpszClass
Definition: winuser.h:2968
LPCWSTR lpszName
Definition: winuser.h:2967
HINSTANCE hInstance
Definition: winuser.h:2959
LONG right
Definition: windef.h:308
LONG bottom
Definition: windef.h:309
LONG top
Definition: windef.h:307
LONG left
Definition: windef.h:306
ATOM atomSysClass[ICLS_NOTUSED+1]
Definition: ntuser.h:1060
UINT uiShellMsg
Definition: ntuser.h:1063
#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
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1829
uint16_t * PWSTR
Definition: typedefs.h:56
#define MAXULONG
Definition: typedefs.h:251
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:10
HDC FASTCALL IntBeginPaint(PWND Window, PPAINTSTRUCT Ps)
Definition: painting.c:1442
BOOL FASTCALL co_UserRedrawWindow(PWND Window, const RECTL *UpdateRect, PREGION UpdateRgn, ULONG Flags)
Definition: painting.c:895
BOOL FASTCALL IntEndPaint(PWND Wnd, PPAINTSTRUCT Ps)
Definition: painting.c:1539
VOID FASTCALL IntInvalidateWindows(PWND Wnd, PREGION Rgn, ULONG Flags)
Definition: painting.c:643
_In_ HFONT _Out_ PUINT _Out_ PUINT Width
Definition: font.h:89
_In_ HFONT _Out_ PUINT Height
Definition: font.h:88
RTL_ATOM FASTCALL IntAddAtom(LPWSTR AtomName)
Definition: useratom.c:13
PWND FASTCALL UserGetWindowObject(HWND hWnd)
Definition: window.c:124
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:2856
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
int ret
_Must_inspect_result_ _In_ WDFCOLLECTION _In_ WDFOBJECT Object
_Must_inspect_result_ _In_ WDFDMAENABLER _In_ _In_opt_ PWDF_OBJECT_ATTRIBUTES Attributes
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2658
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
_Must_inspect_result_ _In_ WDFQUEUE _In_opt_ WDFREQUEST _In_opt_ WDFFILEOBJECT _Inout_opt_ PWDF_REQUEST_PARAMETERS Parameters
Definition: wdfio.h:869
_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:31
HFONT FASTCALL GreCreateFontIndirectW(LOGFONTW *lplf)
Definition: font.c:23
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(HDC hDC, LPCWSTR lpwsz, INT cwc, LPSIZE psize, UINT flOpts)
Definition: text.c:78
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:3222
HDESK APIENTRY NtUserOpenInputDesktop(DWORD dwFlags, BOOL fInherit, ACCESS_MASK dwDesiredAccess)
Definition: desktop.c:2718
BOOL APIENTRY NtUserCloseDesktop(HDESK hDesktop)
Definition: desktop.c:2758
PDESKTOP FASTCALL IntGetActiveDesktop(VOID)
Definition: desktop.c:1279
DWORD gdwDesktopSectionSize
Definition: desktop.c:46
PTHREADINFO gptiDesktopThread
Definition: desktop.c:54
BOOL APIENTRY NtUserSetThreadDesktop(HDESK hDesktop)
Definition: desktop.c:3488
HCURSOR gDesktopCursor
Definition: desktop.c:55
HDESK APIENTRY NtUserOpenDesktop(POBJECT_ATTRIBUTES ObjectAttributes, DWORD dwFlags, ACCESS_MASK dwDesiredAccess)
Definition: desktop.c:2624
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:2388
HWND FASTCALL IntGetCurrentThreadDesktopWindow(VOID)
Definition: desktop.c:1441
NTSTATUS NTAPI IntDesktopOkToClose(_In_ PVOID Parameters)
Definition: desktop.c:203
NTSTATUS NTAPI InitDesktopImpl(VOID)
Definition: desktop.c:269
VOID APIENTRY UserRedrawDesktop(VOID)
Definition: desktop.c:1616
PKEVENT gpDesktopThreadStartedEvent
Definition: desktop.c:56
HDC ScreenDeviceContext
Definition: desktop.c:53
PWND FASTCALL UserGetDesktopWindow(VOID)
Definition: desktop.c:1403
BOOL IntDeRegisterShellHookWindow(HWND hWnd)
Definition: desktop.c:1801
HWND FASTCALL IntGetMessageWindow(VOID)
Definition: desktop.c:1416
NTSTATUS FASTCALL IntHideDesktop(PDESKTOP Desktop)
Definition: desktop.c:1652
VOID NTAPI DesktopThreadMain(VOID)
Definition: desktop.c:1563
HDESK UserOpenInputDesktop(DWORD dwFlags, BOOL fInherit, ACCESS_MASK dwDesiredAccess)
Definition: desktop.c:2653
HDESK FASTCALL IntGetDesktopObjectHandle(PDESKTOP DesktopObject)
Definition: desktop.c:1288
HDESK APIENTRY NtUserGetThreadDesktop(DWORD dwThreadId, HDESK hConsoleDesktop)
Definition: desktop.c:3069
VOID FASTCALL IntSetFocusMessageQueue(PUSER_MESSAGE_QUEUE NewQueue)
Definition: desktop.c:1336
NTSTATUS FASTCALL co_IntShowDesktop(PDESKTOP Desktop, ULONG Width, ULONG Height, BOOL bRedraw)
Definition: desktop.c:1634
HWND FASTCALL IntGetDesktopWindow(VOID)
Definition: desktop.c:1391
NTSTATUS NTAPI IntDesktopObjectClose(_In_ PVOID Parameters)
Definition: desktop.c:244
BOOL IntRegisterShellHookWindow(HWND hWnd)
Definition: desktop.c:1769
NTSTATUS FASTCALL IntValidateDesktopHandle(HDESK Desktop, KPROCESSOR_MODE AccessMode, ACCESS_MASK DesiredAccess, PDESKTOP *Object)
Definition: desktop.c:1254
DWORD gdwNOIOSectionSize
Definition: desktop.c:48
static VOID IntFreeDesktopHeap(IN PDESKTOP pdesk)
PUSER_MESSAGE_QUEUE FASTCALL IntGetFocusMessageQueue(VOID)
Definition: desktop.c:1324
HDESK NTAPI NtUserResolveDesktop(IN HANDLE ProcessHandle, IN PUNICODE_STRING DesktopPath, IN BOOL bInherit, OUT HWINSTA *phWinSta)
Definition: desktop.c:2865
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:62
BOOL APIENTRY NtUserPaintDesktop(HDC hDC)
Definition: desktop.c:2815
BOOL FASTCALL DesktopWindowProc(PWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT *lResult)
Definition: desktop.c:1456
VOID co_IntShellHookNotify(WPARAM Message, WPARAM wParam, LPARAM lParam)
Definition: desktop.c:1709
BOOL APIENTRY NtUserSwitchDesktop(HDESK hdesk)
Definition: desktop.c:2972
NTSTATUS FASTCALL IntResolveDesktop(IN PEPROCESS Process, IN PUNICODE_STRING DesktopPath, IN BOOL bInherit, OUT HWINSTA *phWinSta, OUT HDESK *phDesktop)
Definition: desktop.c:568
BOOL FASTCALL IntPaintDesktop(HDC hDC)
Definition: desktop.c:1852
PWND FASTCALL IntGetThreadDesktopWindow(PTHREADINFO pti)
Definition: desktop.c:1376
static NTSTATUS GetSystemVersionString(OUT PWSTR pwszzVersion, IN SIZE_T cchDest, IN BOOLEAN InSafeMode, IN BOOLEAN AppendNtSystemRoot)
Definition: desktop.c:300
BOOL FASTCALL UserMessageWindowProc(PWND pwnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT *lResult)
Definition: desktop.c:1542
NTSTATUS NTAPI IntDesktopObjectOpen(_In_ PVOID Parameters)
Definition: desktop.c:227
DWORD gdwWinlogonSectionSize
Definition: desktop.c:49
HDC FASTCALL UserGetDesktopDC(ULONG DcType, BOOL bAltDc, BOOL ValidatehWnd)
Definition: desktop.c:1591
NTSTATUS NTAPI IntDesktopObjectDelete(_In_ PVOID Parameters)
Definition: desktop.c:172
HDESK APIENTRY NtUserCreateDesktop(POBJECT_ATTRIBUTES ObjectAttributes, PUNICODE_STRING lpszDesktopDevice, LPDEVMODEW lpdmw, DWORD dwFlags, ACCESS_MASK dwDesiredAccess)
Definition: desktop.c:2565
PDESKTOP gpdeskInputDesktop
Definition: desktop.c:52
BOOL IntSetThreadDesktop(IN HDESK hDesktop, IN BOOL FreeOnFailure)
Definition: desktop.c:3296
static HWND *FASTCALL UserBuildShellHookHwndList(PDESKTOP Desktop)
Definition: desktop.c:1668
PWND FASTCALL UserGetMessageWindow(VOID)
Definition: desktop.c:1429
static NTSTATUS IntUnmapDesktopView(IN PDESKTOP pdesk)
Definition: desktop.c:3178
static NTSTATUS UserInitializeDesktop(PDESKTOP pdesk, PUNICODE_STRING DesktopName, PWINSTATION_OBJECT pwinsta)
Definition: desktop.c:2277
PWND FASTCALL co_GetDesktopWindow(PWND pWnd)
Definition: desktop.c:1383
struct _DESKTOP * PDESKTOP
struct _DESKTOP DESKTOP
static __inline ULONG_PTR DesktopHeapGetUserDelta(VOID)
Definition: desktop.h:272
#define DT_GWL_THREADID
Definition: desktop.h:56
static __inline PVOID DesktopHeapAlloc(IN PDESKTOP Desktop, IN SIZE_T Bytes)
Definition: desktop.h:204
static __inline BOOL DesktopHeapFree(IN PDESKTOP Desktop, IN PVOID lpMem)
Definition: desktop.h:215
#define DT_GWL_PROCESSID
Definition: desktop.h:55
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:214
NTSTATUS GetProcessLuid(IN PETHREAD Thread OPTIONAL, IN PEPROCESS Process OPTIONAL, OUT PLUID Luid)
Definition: misc.c:815
PTHREADINFO FASTCALL IntTID2PTI(HANDLE id)
Definition: misc.c:42
PMONITOR NTAPI UserGetPrimaryMonitor(VOID)
Definition: monitor.c:102
BOOL FASTCALL UserDereferenceObject(PVOID Object)
Definition: object.c:644
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 WINSTA_ACCESS_ALL
Definition: security.h:57
#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:2105
#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:1804
#define WSS_LOCKED
Definition: winsta.h:7
struct _WINSTATION_OBJECT * PWINSTATION_OBJECT
#define WSS_NOIO
Definition: winsta.h:9
SIZE_T WINAPI HeapSize(HANDLE, DWORD, LPCVOID)
#define MAKEINTATOM(i)
Definition: winbase.h:1488
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1176
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:22
LONG_PTR LPARAM
Definition: windef.h:208
LONG_PTR LRESULT
Definition: windef.h:209
UINT_PTR WPARAM
Definition: windef.h:207
DWORD COLORREF
Definition: windef.h:300
HICON HCURSOR
Definition: windef.h:299
#define ERROR_INVALID_WINDOW_HANDLE
Definition: winerror.h:881
#define TA_RIGHT
Definition: wingdi.h:933
#define TA_LEFT
Definition: wingdi.h:932
#define TRANSPARENT
Definition: wingdi.h:950
#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:1623
#define WM_ERASEBKGND
Definition: winuser.h:1628
#define WM_CLOSE
Definition: winuser.h:1624
#define SWP_NOACTIVATE
Definition: winuser.h:1245
#define SWP_NOREDRAW
Definition: winuser.h:1249
#define SM_CYVIRTUALSCREEN
Definition: winuser.h:1042
#define SM_CYSCREEN
Definition: winuser.h:963
#define WM_WINDOWPOSCHANGING
Definition: winuser.h:1664
#define WM_CREATE
Definition: winuser.h:1611
#define WH_SHELL
Definition: winuser.h:40
#define RDW_UPDATENOW
Definition: winuser.h:1223
#define RDW_ERASE
Definition: winuser.h:1214
#define WM_SYSCOLORCHANGE
Definition: winuser.h:1629
#define WM_NCCREATE
Definition: winuser.h:1686
#define SM_CXVIRTUALSCREEN
Definition: winuser.h:1041
#define RDW_ALLCHILDREN
Definition: winuser.h:1224
#define PM_REMOVE
Definition: winuser.h:1199
#define RDW_FRAME
Definition: winuser.h:1215
#define SWP_SHOWWINDOW
Definition: winuser.h:1251
#define WM_SETCURSOR
Definition: winuser.h:1639
#define SM_CLEANBOOT
Definition: winuser.h:1030
#define WM_DESTROY
Definition: winuser.h:1612
#define SM_CXSCREEN
Definition: winuser.h:962
struct _WINDOWPOS * PWINDOWPOS
#define SM_XVIRTUALSCREEN
Definition: winuser.h:1039
#define SWP_NOZORDER
Definition: winuser.h:1250
#define RDW_INVALIDATE
Definition: winuser.h:1217
#define SM_YVIRTUALSCREEN
Definition: winuser.h:1040
_In_ PVOID _Out_opt_ PULONG_PTR _Outptr_opt_ PCUNICODE_STRING * ObjectName
Definition: cmfuncs.h:64
#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
__wchar_t WCHAR
Definition: xmlstorage.h:180
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
#define ZwCurrentProcess()