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