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