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