ReactOS  0.4.15-dev-5137-g826bd41
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;
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 new service's window station.
1026  * A service has an associated window station and desktop. The newly
1027  * created window station and desktop will get this security descriptor
1028  * if such objects weren't created before.
1029  */
1030  Status = IntCreateServiceSecurity(&ServiceSD);
1031  if (!NT_SUCCESS(Status))
1032  {
1033  ERR("Failed to create a security descriptor for service window station, Status 0x%08lx\n", Status);
1034  goto Quit;
1035  }
1036 
1037  /*
1038  * Create or open the non-interactive window station.
1039  * NOTE: The non-interactive window station handle is never inheritable.
1040  */
1042  ObjectName,
1044  NULL,
1045  ServiceSD);
1046 
1047  Status = IntCreateWindowStation(&hWinSta,
1049  UserMode,
1050  KernelMode,
1052  0, 0, 0, 0, 0);
1053 
1054  IntFreeSecurityBuffer(ServiceSD);
1055 
1056  if (!NT_SUCCESS(Status))
1057  {
1058  ASSERT(hWinSta == NULL);
1059  ERR("Failed to create or open the non-interactive window station '%wZ', Status 0x%08lx\n",
1060  ObjectName, Status);
1061  goto Quit;
1062  }
1063 
1064  //
1065  // FIXME: We might not need to always create or open the "Default"
1066  // desktop on the Service-0xXXXX-YYYY$ window station; we may need
1067  // to use another one....
1068  //
1069 
1070  /* Create or open the Default desktop on the window station */
1072  ObjectName->MaximumLength,
1073  L"Default");
1074  if (!NT_SUCCESS(Status))
1075  {
1076  ERR("Impossible to build a valid desktop name, Status 0x%08lx\n", Status);
1077  goto Quit;
1078  }
1079  ObjectName->Length = (USHORT)(wcslen(ObjectName->Buffer) * sizeof(WCHAR));
1080 
1081  /*
1082  * NOTE: The non-interactive desktop handle is never inheritable.
1083  * The security descriptor is inherited from the newly created
1084  * window station for the desktop.
1085  */
1087  ObjectName,
1089  hWinSta,
1090  NULL);
1091 
1092  Status = IntCreateDesktop(&hDesktop,
1094  UserMode,
1095  NULL,
1096  NULL,
1097  0,
1098  MAXIMUM_ALLOWED);
1099  if (!NT_SUCCESS(Status))
1100  {
1101  ASSERT(hDesktop == NULL);
1102  ERR("Failed to create or open the desktop '%wZ' on window station 0x%p, Status 0x%08lx\n",
1103  ObjectName, hWinSta, Status);
1104  }
1105 
1106  goto Quit;
1107  }
1108 /*
1109  if (hWinSta == NULL)
1110  {
1111  Status = STATUS_UNSUCCESSFUL;
1112  goto Quit;
1113  }
1114 */
1115  }
1116 
1117  /*
1118  * If we got an inherited desktop handle, duplicate and use it,
1119  * otherwise open a new desktop.
1120  */
1121  if (hDesktop != NULL)
1122  {
1123  /* Duplicate the handle if it belongs to another process than the current one */
1124  if (Process != PsGetCurrentProcess())
1125  {
1126  ASSERT(hProcess);
1127  Status = ZwDuplicateObject(hProcess,
1128  hDesktop,
1129  ZwCurrentProcess(),
1130  (PHANDLE)&hDesktopDup,
1131  0,
1132  0,
1134  if (!NT_SUCCESS(Status))
1135  {
1136  ERR("IntResolveDesktop: Failed to duplicate the desktop handle, Status 0x%08lx\n", Status);
1137  /* We will use a default desktop */
1138  hDesktop = NULL;
1139  }
1140  else
1141  {
1142  hDesktop = hDesktopDup;
1143  }
1144  }
1145  }
1146 
1147  if ((hWinSta != NULL) && (hDesktop == NULL))
1148  {
1150  ObjectName->MaximumLength,
1151  DesktopName.Buffer,
1152  DesktopName.Length);
1153  if (!NT_SUCCESS(Status))
1154  {
1155  ERR("Impossible to build a valid desktop name, Status 0x%08lx\n", Status);
1156  goto Quit;
1157  }
1158  ObjectName->Length = (USHORT)(wcslen(ObjectName->Buffer) * sizeof(WCHAR));
1159 
1160  TRACE("Parsed initial desktop: '%wZ'\n", ObjectName);
1161 
1162  /* Open the desktop object */
1164  ObjectName,
1166  hWinSta,
1167  NULL);
1168  if (bInherit)
1169  ObjectAttributes->Attributes |= OBJ_INHERIT;
1170 
1173  UserMode,
1174  NULL,
1176  NULL,
1177  (PHANDLE)&hDesktop);
1178  if (!NT_SUCCESS(Status))
1179  {
1180  ERR("Failed to open the desktop '%wZ' on window station 0x%p, Status 0x%08lx\n",
1181  ObjectName, hWinSta, Status);
1182  goto Quit;
1183  }
1184  }
1185 
1186 Quit:
1187  /* Release the object attributes */
1188  if (ObjectAttributes)
1189  {
1190  MemSize = 0;
1191  ZwFreeVirtualMemory(ZwCurrentProcess(),
1193  &MemSize,
1194  MEM_RELEASE);
1195  }
1196 
1197  /* Close the temporary process handle */
1198  if (hProcess) // if (Process != PsGetCurrentProcess())
1200 
1201  if (NT_SUCCESS(Status))
1202  {
1203  *phWinSta = hWinSta;
1204  *phDesktop = hDesktop;
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 
1222  return Status;
1223  }
1224 }
1225 
1226 /*
1227  * IntValidateDesktopHandle
1228  *
1229  * Validates the desktop handle.
1230  *
1231  * Remarks
1232  * If the function succeeds, the handle remains referenced. If the
1233  * fucntion fails, last error is set.
1234  */
1235 
1238  HDESK Desktop,
1241  PDESKTOP *Object)
1242 {
1243  NTSTATUS Status;
1244 
1246  DesiredAccess,
1248  AccessMode,
1249  (PVOID*)Object,
1250  NULL);
1251 
1252  TRACE("IntValidateDesktopHandle: handle:0x%p obj:0x%p access:0x%x Status:0x%lx\n",
1254 
1255  if (!NT_SUCCESS(Status))
1257 
1258  return Status;
1259 }
1260 
1263 {
1264  return gpdeskInputDesktop;
1265 }
1266 
1267 /*
1268  * Returns or creates a handle to the desktop object
1269  */
1270 HDESK FASTCALL
1272 {
1273  NTSTATUS Status;
1274  HDESK hDesk;
1275 
1276  ASSERT(DesktopObject);
1277 
1279  DesktopObject,
1281  NULL,
1282  (PHANDLE)&hDesk))
1283  {
1284  Status = ObOpenObjectByPointer(DesktopObject,
1285  0,
1286  NULL,
1287  0,
1289  UserMode,
1290  (PHANDLE)&hDesk);
1291  if (!NT_SUCCESS(Status))
1292  {
1293  /* Unable to create a handle */
1294  ERR("Unable to create a desktop handle\n");
1295  return NULL;
1296  }
1297  }
1298  else
1299  {
1300  TRACE("Got handle: 0x%p\n", hDesk);
1301  }
1302 
1303  return hDesk;
1304 }
1305 
1308 {
1309  PDESKTOP pdo = IntGetActiveDesktop();
1310  if (!pdo)
1311  {
1312  TRACE("No active desktop\n");
1313  return(NULL);
1314  }
1316 }
1317 
1318 VOID FASTCALL
1320 {
1321  PUSER_MESSAGE_QUEUE Old;
1322  PDESKTOP pdo = IntGetActiveDesktop();
1323  if (!pdo)
1324  {
1325  TRACE("No active desktop\n");
1326  return;
1327  }
1328  if (NewQueue != NULL)
1329  {
1330  if (NewQueue->Desktop != NULL)
1331  {
1332  TRACE("Message Queue already attached to another desktop!\n");
1333  return;
1334  }
1335  IntReferenceMessageQueue(NewQueue);
1336  (void)InterlockedExchangePointer((PVOID*)&NewQueue->Desktop, pdo);
1337  }
1339  if (Old != NULL)
1340  {
1342  gpqForegroundPrev = Old;
1344  }
1345  // Only one Q can have active foreground even when there are more than one desktop.
1346  if (NewQueue)
1347  {
1349  }
1350  else
1351  {
1352  gpqForeground = NULL;
1353  ERR("ptiLastInput is CLEARED!!\n");
1354  ptiLastInput = NULL; // ReactOS hacks... should check for process death.
1355  }
1356 }
1357 
1358 PWND FASTCALL
1360 {
1361  if (!pti) pti = PsGetCurrentThreadWin32Thread();
1362  if (pti->pDeskInfo) return pti->pDeskInfo->spwnd;
1363  return NULL;
1364 }
1365 
1367 {
1368  if (pWnd->head.rpdesk &&
1369  pWnd->head.rpdesk->pDeskInfo)
1370  return pWnd->head.rpdesk->pDeskInfo->spwnd;
1371  return NULL;
1372 }
1373 
1375 {
1376  PDESKTOP pdo = IntGetActiveDesktop();
1377  if (!pdo)
1378  {
1379  TRACE("No active desktop\n");
1380  return NULL;
1381  }
1382  return pdo->DesktopWindow;
1383 }
1384 
1385 // Win: _GetDesktopWindow
1387 {
1388  PDESKTOP pdo = IntGetActiveDesktop();
1389 
1390  if (!pdo)
1391  {
1392  TRACE("No active desktop\n");
1393  return NULL;
1394  }
1395  // return pdo->pDeskInfo->spwnd;
1396  return UserGetWindowObject(pdo->DesktopWindow);
1397 }
1398 
1400 {
1401  PDESKTOP pdo = IntGetActiveDesktop();
1402 
1403  if (!pdo)
1404  {
1405  TRACE("No active desktop\n");
1406  return NULL;
1407  }
1408  return pdo->spwndMessage->head.h;
1409 }
1410 
1411 // Win: _GetMessageWindow
1413 {
1414  PDESKTOP pdo = IntGetActiveDesktop();
1415 
1416  if (!pdo)
1417  {
1418  TRACE("No active desktop\n");
1419  return NULL;
1420  }
1421  return pdo->spwndMessage;
1422 }
1423 
1425 {
1427  PDESKTOP pdo = pti->rpdesk;
1428  if (NULL == pdo)
1429  {
1430  ERR("Thread doesn't have a desktop\n");
1431  return NULL;
1432  }
1433  return pdo->DesktopWindow;
1434 }
1435 
1436 /* PUBLIC FUNCTIONS ***********************************************************/
1437 
1438 BOOL FASTCALL
1440 {
1441  PAINTSTRUCT Ps;
1442  ULONG Value;
1443  //ERR("DesktopWindowProc\n");
1444 
1445  *lResult = 0;
1446 
1447  switch (Msg)
1448  {
1449  case WM_NCCREATE:
1450  if (!Wnd->fnid)
1451  {
1452  Wnd->fnid = FNID_DESKTOP;
1453  }
1454  *lResult = (LRESULT)TRUE;
1455  return TRUE;
1456 
1457  case WM_CREATE:
1459  // Save Process ID
1462  // Save Thread ID
1464  case WM_CLOSE:
1465  return TRUE;
1466 
1467  case WM_DISPLAYCHANGE:
1469  return TRUE;
1470 
1471  case WM_ERASEBKGND:
1473  *lResult = 1;
1474  return TRUE;
1475 
1476  case WM_PAINT:
1477  {
1478  if (IntBeginPaint(Wnd, &Ps))
1479  {
1480  IntEndPaint(Wnd, &Ps);
1481  }
1482  return TRUE;
1483  }
1484  case WM_SYSCOLORCHANGE:
1486  return TRUE;
1487 
1488  case WM_SETCURSOR:
1489  {
1490  PCURICON_OBJECT pcurOld, pcurNew;
1492  if (!pcurNew)
1493  {
1494  return TRUE;
1495  }
1496 
1497  pcurNew->CURSORF_flags |= CURSORF_CURRENT;
1498  pcurOld = UserSetCursor(pcurNew, FALSE);
1499  if (pcurOld)
1500  {
1501  pcurOld->CURSORF_flags &= ~CURSORF_CURRENT;
1502  UserDereferenceObject(pcurOld);
1503  }
1504  return TRUE;
1505  }
1506 
1507  case WM_WINDOWPOSCHANGING:
1508  {
1509  PWINDOWPOS pWindowPos = (PWINDOWPOS)lParam;
1510  if ((pWindowPos->flags & SWP_SHOWWINDOW) != 0)
1511  {
1512  HDESK hdesk = UserOpenInputDesktop(0, FALSE, DESKTOP_ALL_ACCESS);
1513  IntSetThreadDesktop(hdesk, FALSE);
1514  }
1515  break;
1516  }
1517  default:
1518  TRACE("DWP calling IDWP Msg %d\n",Msg);
1519  //*lResult = IntDefWindowProc(Wnd, Msg, wParam, lParam, FALSE);
1520  }
1521  return TRUE; /* We are done. Do not do any callbacks to user mode */
1522 }
1523 
1524 BOOL FASTCALL
1526 {
1527  *lResult = 0;
1528 
1529  switch(Msg)
1530  {
1531  case WM_NCCREATE:
1532  pwnd->fnid |= FNID_MESSAGEWND;
1533  *lResult = (LRESULT)TRUE;
1534  break;
1535  case WM_DESTROY:
1536  pwnd->fnid |= FNID_DESTROY;
1537  break;
1538  default:
1539  ERR("UMWP calling IDWP\n");
1540  *lResult = IntDefWindowProc(pwnd, Msg, wParam, lParam, FALSE);
1541  }
1542 
1543  return TRUE; /* We are done. Do not do any callbacks to user mode */
1544 }
1545 
1547 {
1548  BOOL Ret;
1549  MSG Msg;
1550 
1552 
1554 
1555  /* Register system classes. This thread does not belong to any desktop so the
1556  classes will be allocated from the shared heap */
1558 
1560 
1561  while (TRUE)
1562  {
1563  Ret = co_IntGetPeekMessage(&Msg, 0, 0, 0, PM_REMOVE, TRUE);
1564  if (Ret)
1565  {
1567  }
1568  }
1569 
1570  UserLeave();
1571 }
1572 
1573 HDC FASTCALL
1574 UserGetDesktopDC(ULONG DcType, BOOL bAltDc, BOOL ValidatehWnd)
1575 {
1576  PWND DesktopObject = 0;
1577  HDC DesktopHDC = 0;
1578 
1579  /* This can be called from GDI/DX, so acquire the USER lock */
1581 
1582  if (DcType == DCTYPE_DIRECT)
1583  {
1584  DesktopObject = UserGetDesktopWindow();
1585  DesktopHDC = (HDC)UserGetWindowDC(DesktopObject);
1586  }
1587  else
1588  {
1589  PMONITOR pMonitor = UserGetPrimaryMonitor();
1590  DesktopHDC = IntGdiCreateDisplayDC(pMonitor->hDev, DcType, bAltDc);
1591  }
1592 
1593  UserLeave();
1594 
1595  return DesktopHDC;
1596 }
1597 
1598 VOID APIENTRY
1600 {
1601  PWND Window = NULL;
1602  PREGION Rgn;
1603 
1605  Rgn = IntSysCreateRectpRgnIndirect(&Window->rcWindow);
1606 
1608  Rgn,
1609  RDW_FRAME | RDW_ERASE |
1611 
1612  REGION_Delete(Rgn);
1613 }
1614 
1615 
1618 {
1619  PWND pwnd = Desktop->pDeskInfo->spwnd;
1621  ASSERT(pwnd);
1622 
1623  if (!bRedraw)
1624  flags |= SWP_NOREDRAW;
1625 
1626  co_WinPosSetWindowPos(pwnd, NULL, 0, 0, Width, Height, flags);
1627 
1628  if (bRedraw)
1630 
1631  return STATUS_SUCCESS;
1632 }
1633 
1636 {
1637  PWND DesktopWnd;
1638 
1639  DesktopWnd = IntGetWindowObject(Desktop->DesktopWindow);
1640  if (! DesktopWnd)
1641  {
1643  }
1644  DesktopWnd->style &= ~WS_VISIBLE;
1645 
1646  return STATUS_SUCCESS;
1647 }
1648 
1649 static
1650 HWND* FASTCALL
1652 {
1653  ULONG entries=0;
1654  PLIST_ENTRY ListEntry;
1655  PSHELL_HOOK_WINDOW Current;
1656  HWND* list;
1657 
1658  /* FIXME: If we save nb elements in desktop, we don't have to loop to find nb entries */
1659  ListEntry = Desktop->ShellHookWindows.Flink;
1660  while (ListEntry != &Desktop->ShellHookWindows)
1661  {
1662  ListEntry = ListEntry->Flink;
1663  entries++;
1664  }
1665 
1666  if (!entries) return NULL;
1667 
1668  list = ExAllocatePoolWithTag(PagedPool, sizeof(HWND) * (entries + 1), USERTAG_WINDOWLIST); /* alloc one extra for nullterm */
1669  if (list)
1670  {
1671  HWND* cursor = list;
1672 
1673  ListEntry = Desktop->ShellHookWindows.Flink;
1674  while (ListEntry != &Desktop->ShellHookWindows)
1675  {
1676  Current = CONTAINING_RECORD(ListEntry, SHELL_HOOK_WINDOW, ListEntry);
1677  ListEntry = ListEntry->Flink;
1678  *cursor++ = Current->hWnd;
1679  }
1680 
1681  *cursor = NULL; /* Nullterm list */
1682  }
1683 
1684  return list;
1685 }
1686 
1687 /*
1688  * Send the Message to the windows registered for ShellHook
1689  * notifications. The lParam contents depend on the Message. See
1690  * MSDN for more details (RegisterShellHookWindow)
1691  */
1693 {
1695  HWND* HwndList;
1696 
1697  if (!gpsi->uiShellMsg)
1698  {
1699  gpsi->uiShellMsg = IntAddAtom(L"SHELLHOOK");
1700 
1701  TRACE("MsgType = %x\n", gpsi->uiShellMsg);
1702  if (!gpsi->uiShellMsg)
1703  ERR("LastError: %x\n", EngGetLastError());
1704  }
1705 
1706  if (!Desktop)
1707  {
1708  TRACE("IntShellHookNotify: No desktop!\n");
1709  return;
1710  }
1711 
1712  // Allow other devices have a shot at foreground.
1713  if (Message == HSHELL_APPCOMMAND) ptiLastInput = NULL;
1714 
1715  // FIXME: System Tray Support.
1716 
1717  HwndList = UserBuildShellHookHwndList(Desktop);
1718  if (HwndList)
1719  {
1720  HWND* cursor = HwndList;
1721 
1722  for (; *cursor; cursor++)
1723  {
1724  TRACE("Sending notify\n");
1726  gpsi->uiShellMsg,
1727  Message,
1728  (Message == HSHELL_LANGUAGE ? lParam : (LPARAM)wParam) );
1729 /* co_IntPostOrSendMessage(*cursor,
1730  gpsi->uiShellMsg,
1731  Message,
1732  (Message == HSHELL_LANGUAGE ? lParam : (LPARAM)wParam) );*/
1733  }
1734 
1736  }
1737 
1738  if (ISITHOOKED(WH_SHELL))
1739  {
1741  }
1742 }
1743 
1744 /*
1745  * Add the window to the ShellHookWindows list. The windows
1746  * on that list get notifications that are important to shell
1747  * type applications.
1748  *
1749  * TODO: Validate the window? I'm not sure if sending these messages to
1750  * an unsuspecting application that is not your own is a nice thing to do.
1751  */
1753 {
1755  PDESKTOP Desktop = pti->rpdesk;
1757 
1758  TRACE("IntRegisterShellHookWindow\n");
1759 
1760  /* First deregister the window, so we can be sure it's never twice in the
1761  * list.
1762  */
1764 
1766  sizeof(SHELL_HOOK_WINDOW),
1767  TAG_WINSTA);
1768 
1769  if (!Entry)
1770  return FALSE;
1771 
1772  Entry->hWnd = hWnd;
1773 
1774  InsertTailList(&Desktop->ShellHookWindows, &Entry->ListEntry);
1775 
1776  return TRUE;
1777 }
1778 
1779 /*
1780  * Remove the window from the ShellHookWindows list. The windows
1781  * on that list get notifications that are important to shell
1782  * type applications.
1783  */
1785 {
1787  PDESKTOP Desktop = pti->rpdesk;
1788  PLIST_ENTRY ListEntry;
1789  PSHELL_HOOK_WINDOW Current;
1790 
1791  ListEntry = Desktop->ShellHookWindows.Flink;
1792  while (ListEntry != &Desktop->ShellHookWindows)
1793  {
1794  Current = CONTAINING_RECORD(ListEntry, SHELL_HOOK_WINDOW, ListEntry);
1795  ListEntry = ListEntry->Flink;
1796  if (Current->hWnd == hWnd)
1797  {
1798  RemoveEntryList(&Current->ListEntry);
1799  ExFreePoolWithTag(Current, TAG_WINSTA);
1800  return TRUE;
1801  }
1802  }
1803 
1804  return FALSE;
1805 }
1806 
1807 static VOID
1809 {
1810  /* FIXME: Disable until unmapping works in mm */
1811 #if 0
1812  if (Desktop->pheapDesktop != NULL)
1813  {
1814  MmUnmapViewInSessionSpace(Desktop->pheapDesktop);
1815  Desktop->pheapDesktop = NULL;
1816  }
1817 
1818  if (Desktop->hsectionDesktop != NULL)
1819  {
1820  ObDereferenceObject(Desktop->hsectionDesktop);
1821  Desktop->hsectionDesktop = NULL;
1822  }
1823 #endif
1824 }
1825 
1826 BOOL FASTCALL
1828 {
1829  static WCHAR s_wszSafeMode[] = L"Safe Mode"; // FIXME: Localize!
1830 
1831  RECTL Rect;
1832  HBRUSH DesktopBrush, PreviousBrush;
1833  HWND hWndDesktop;
1834  BOOL doPatBlt = TRUE;
1835  PWND WndDesktop;
1836  BOOLEAN InSafeMode;
1837 
1838  if (GdiGetClipBox(hDC, &Rect) == ERROR)
1839  return FALSE;
1840 
1841  hWndDesktop = IntGetDesktopWindow(); // rpdesk->DesktopWindow;
1842 
1843  WndDesktop = UserGetWindowObject(hWndDesktop); // rpdesk->pDeskInfo->spwnd;
1844  if (!WndDesktop)
1845  return FALSE;
1846 
1847  /* Retrieve the current SafeMode state */
1848  InSafeMode = (UserGetSystemMetrics(SM_CLEANBOOT) != 0); // gpsi->aiSysMet[SM_CLEANBOOT];
1849 
1850  if (!InSafeMode)
1851  {
1852  DesktopBrush = (HBRUSH)WndDesktop->pcls->hbrBackground;
1853 
1854  /*
1855  * Paint desktop background
1856  */
1857  if (gspv.hbmWallpaper != NULL)
1858  {
1859  SIZE sz;
1860  int x, y;
1861  int scaledWidth, scaledHeight;
1862  int wallpaperX, wallpaperY, wallpaperWidth, wallpaperHeight;
1863  HDC hWallpaperDC;
1864 
1865  sz.cx = WndDesktop->rcWindow.right - WndDesktop->rcWindow.left;
1866  sz.cy = WndDesktop->rcWindow.bottom - WndDesktop->rcWindow.top;
1867 
1868  if (gspv.WallpaperMode == wmFit ||
1870  {
1871  int scaleNum, scaleDen;
1872 
1873  // Precision improvement over ((sz.cx / gspv.cxWallpaper) > (sz.cy / gspv.cyWallpaper))
1874  if ((sz.cx * gspv.cyWallpaper) > (sz.cy * gspv.cxWallpaper))
1875  {
1876  if (gspv.WallpaperMode == wmFit)
1877  {
1878  scaleNum = sz.cy;
1879  scaleDen = gspv.cyWallpaper;
1880  }
1881  else
1882  {
1883  scaleNum = sz.cx;
1884  scaleDen = gspv.cxWallpaper;
1885  }
1886  }
1887  else
1888  {
1889  if (gspv.WallpaperMode == wmFit)
1890  {
1891  scaleNum = sz.cx;
1892  scaleDen = gspv.cxWallpaper;
1893  }
1894  else
1895  {
1896  scaleNum = sz.cy;
1897  scaleDen = gspv.cyWallpaper;
1898  }
1899  }
1900 
1901  scaledWidth = EngMulDiv(gspv.cxWallpaper, scaleNum, scaleDen);
1902  scaledHeight = EngMulDiv(gspv.cyWallpaper, scaleNum, scaleDen);
1903 
1904  if (gspv.WallpaperMode == wmFill)
1905  {
1906  wallpaperX = (((scaledWidth - sz.cx) * gspv.cxWallpaper) / (2 * scaledWidth));
1907  wallpaperY = (((scaledHeight - sz.cy) * gspv.cyWallpaper) / (2 * scaledHeight));
1908 
1909  wallpaperWidth = (sz.cx * gspv.cxWallpaper) / scaledWidth;
1910  wallpaperHeight = (sz.cy * gspv.cyWallpaper) / scaledHeight;
1911  }
1912  }
1913 
1914  if (gspv.WallpaperMode == wmStretch ||
1915  gspv.WallpaperMode == wmTile ||
1917  {
1918  x = 0;
1919  y = 0;
1920  }
1921  else if (gspv.WallpaperMode == wmFit)
1922  {
1923  x = (sz.cx - scaledWidth) / 2;
1924  y = (sz.cy - scaledHeight) / 2;
1925  }
1926  else
1927  {
1928  /* Find the upper left corner, can be negative if the bitmap is bigger than the screen */
1929  x = (sz.cx / 2) - (gspv.cxWallpaper / 2);
1930  y = (sz.cy / 2) - (gspv.cyWallpaper / 2);
1931  }
1932 
1933  hWallpaperDC = NtGdiCreateCompatibleDC(hDC);
1934  if (hWallpaperDC != NULL)
1935  {
1936  HBITMAP hOldBitmap;
1937 
1938  /* Fill in the area that the bitmap is not going to cover */
1939  if (x > 0 || y > 0)
1940  {
1941  /* FIXME: Clip out the bitmap
1942  can be replaced with "NtGdiPatBlt(hDC, x, y, gspv.cxWallpaper, gspv.cyWallpaper, PATCOPY | DSTINVERT);"
1943  once we support DSTINVERT */
1944  PreviousBrush = NtGdiSelectBrush(hDC, DesktopBrush);
1945  NtGdiPatBlt(hDC, Rect.left, Rect.top, Rect.right, Rect.bottom, PATCOPY);
1946  NtGdiSelectBrush(hDC, PreviousBrush);
1947  }
1948 
1949  /* Do not fill the background after it is painted no matter the size of the picture */
1950  doPatBlt = FALSE;
1951 
1952  hOldBitmap = NtGdiSelectBitmap(hWallpaperDC, gspv.hbmWallpaper);
1953 
1954  if (gspv.WallpaperMode == wmStretch)
1955  {
1956  if (Rect.right && Rect.bottom)
1958  x,
1959  y,
1960  sz.cx,
1961  sz.cy,
1962  hWallpaperDC,
1963  0,
1964  0,
1965  gspv.cxWallpaper,
1966  gspv.cyWallpaper,
1967  SRCCOPY,
1968  0);
1969  }
1970  else if (gspv.WallpaperMode == wmTile)
1971  {
1972  /* Paint the bitmap across the screen then down */
1973  for (y = 0; y < Rect.bottom; y += gspv.cyWallpaper)
1974  {
1975  for (x = 0; x < Rect.right; x += gspv.cxWallpaper)
1976  {
1977  NtGdiBitBlt(hDC,
1978  x,
1979  y,
1980  gspv.cxWallpaper,
1981  gspv.cyWallpaper,
1982  hWallpaperDC,
1983  0,
1984  0,
1985  SRCCOPY,
1986  0,
1987  0);
1988  }
1989  }
1990  }
1991  else if (gspv.WallpaperMode == wmFit)
1992  {
1993  if (Rect.right && Rect.bottom)
1994  {
1996  x,
1997  y,
1998  scaledWidth,
1999  scaledHeight,
2000  hWallpaperDC,
2001  0,
2002  0,
2003  gspv.cxWallpaper,
2004  gspv.cyWallpaper,
2005  SRCCOPY,
2006  0);
2007  }
2008  }
2009  else if (gspv.WallpaperMode == wmFill)
2010  {
2011  if (Rect.right && Rect.bottom)
2012  {
2014  x,
2015  y,
2016  sz.cx,
2017  sz.cy,
2018  hWallpaperDC,
2019  wallpaperX,
2020  wallpaperY,
2021  wallpaperWidth,
2022  wallpaperHeight,
2023  SRCCOPY,
2024  0);
2025  }
2026  }
2027  else
2028  {
2029  NtGdiBitBlt(hDC,
2030  x,
2031  y,
2032  gspv.cxWallpaper,
2033  gspv.cyWallpaper,
2034  hWallpaperDC,
2035  0,
2036  0,
2037  SRCCOPY,
2038  0,
2039  0);
2040  }
2041  NtGdiSelectBitmap(hWallpaperDC, hOldBitmap);
2042  NtGdiDeleteObjectApp(hWallpaperDC);
2043  }
2044  }
2045  }
2046  else
2047  {
2048  /* Black desktop background in Safe Mode */
2049  DesktopBrush = StockObjects[BLACK_BRUSH];
2050  }
2051 
2052  /* Background is set to none, clear the screen */
2053  if (doPatBlt)
2054  {
2055  PreviousBrush = NtGdiSelectBrush(hDC, DesktopBrush);
2056  NtGdiPatBlt(hDC, Rect.left, Rect.top, Rect.right, Rect.bottom, PATCOPY);
2057  NtGdiSelectBrush(hDC, PreviousBrush);
2058  }
2059 
2060  /*
2061  * Display the system version on the desktop background
2062  */
2063  if (InSafeMode || g_AlwaysDisplayVersion || g_PaintDesktopVersion)
2064  {
2065  NTSTATUS Status;
2066  static WCHAR wszzVersion[1024] = L"\0";
2067 
2068  /* Only used in normal mode */
2069  // We expect at most 4 strings (3 for version, 1 for optional NtSystemRoot)
2070  static POLYTEXTW VerStrs[4] = {{0},{0},{0},{0}};
2071  INT i = 0;
2072  SIZE_T len;
2073 
2074  HFONT hFont1 = NULL, hFont2 = NULL, hOldFont = NULL;
2075  COLORREF crText, color_old;
2076  UINT align_old;
2077  INT mode_old;
2078  PDC pdc;
2079 
2080  if (!UserSystemParametersInfo(SPI_GETWORKAREA, 0, &Rect, 0))
2081  {
2082  Rect.left = Rect.top = 0;
2085  }
2086  else
2087  {
2088  RECTL_vOffsetRect(&Rect, -Rect.left, -Rect.top);
2089  }
2090 
2091  /*
2092  * Set up the fonts (otherwise use default ones)
2093  */
2094 
2095  /* Font for the principal version string */
2096  hFont1 = GreCreateFontIndirectW(&gspv.ncm.lfCaptionFont);
2097  /* Font for the secondary version strings */
2098  hFont2 = GreCreateFontIndirectW(&gspv.ncm.lfMenuFont);
2099 
2100  if (hFont1)
2101  hOldFont = NtGdiSelectFont(hDC, hFont1);
2102 
2103  if (gspv.hbmWallpaper == NULL)
2104  {
2105  /* Retrieve the brush fill colour */
2106  // TODO: The following code constitutes "GreGetBrushColor".
2107  PreviousBrush = NtGdiSelectBrush(hDC, DesktopBrush);
2108  pdc = DC_LockDc(hDC);
2109  if (pdc)
2110  {
2111  crText = pdc->eboFill.ulRGBColor;
2112  DC_UnlockDc(pdc);
2113  }
2114  else
2115  {
2116  crText = RGB(0, 0, 0);
2117  }
2118  NtGdiSelectBrush(hDC, PreviousBrush);
2119 
2120  /* Adjust text colour according to the brush */
2121  if (GetRValue(crText) + GetGValue(crText) + GetBValue(crText) > 128 * 3)
2122  crText = RGB(0, 0, 0);
2123  else
2124  crText = RGB(255, 255, 255);
2125  }
2126  else
2127  {
2128  /* Always use white when the text is displayed on top of a wallpaper */
2129  crText = RGB(255, 255, 255);
2130  }
2131 
2132  color_old = IntGdiSetTextColor(hDC, crText);
2133  align_old = IntGdiSetTextAlign(hDC, TA_RIGHT);
2134  mode_old = IntGdiSetBkMode(hDC, TRANSPARENT);
2135 
2136  /* Display the system version information */
2137  if (!*wszzVersion)
2138  {
2139  Status = GetSystemVersionString(wszzVersion,
2140  ARRAYSIZE(wszzVersion),
2141  InSafeMode,
2143  if (!InSafeMode && NT_SUCCESS(Status) && *wszzVersion)
2144  {
2145  PWCHAR pstr = wszzVersion;
2146  for (i = 0; (i < ARRAYSIZE(VerStrs)) && *pstr; ++i)
2147  {
2148  VerStrs[i].n = lstrlenW(pstr);
2149  VerStrs[i].lpstr = pstr;
2150  pstr += (VerStrs[i].n + 1);
2151  }
2152  }
2153  }
2154  else
2155  {
2157  }
2158  if (NT_SUCCESS(Status) && *wszzVersion)
2159  {
2160  if (!InSafeMode)
2161  {
2162  SIZE Size = {0, 0};
2163  LONG TotalHeight = 0;
2164 
2165  /* Normal Mode: multiple version information text separated by newlines */
2167 
2168  /* Compute the heights of the strings */
2169  if (hFont1) NtGdiSelectFont(hDC, hFont1);
2170  for (i = 0; i < ARRAYSIZE(VerStrs); ++i)
2171  {
2172  if (!VerStrs[i].lpstr || !*VerStrs[i].lpstr || (VerStrs[i].n == 0))
2173  break;
2174 
2175  GreGetTextExtentW(hDC, VerStrs[i].lpstr, VerStrs[i].n, &Size, 1);
2176  VerStrs[i].y = Size.cy; // Store the string height
2177  TotalHeight += Size.cy;
2178 
2179  /* While the first string was using hFont1, all the others use hFont2 */
2180  if (hFont2) NtGdiSelectFont(hDC, hFont2);
2181  }
2182  /* The total height must not exceed the screen height */
2183  TotalHeight = min(TotalHeight, Rect.bottom);
2184 
2185  /* Display the strings */
2186  if (hFont1) NtGdiSelectFont(hDC, hFont1);
2187  for (i = 0; i < ARRAYSIZE(VerStrs); ++i)
2188  {
2189  if (!VerStrs[i].lpstr || !*VerStrs[i].lpstr || (VerStrs[i].n == 0))
2190  break;
2191 
2192  TotalHeight -= VerStrs[i].y;
2194  Rect.right - 5,
2195  Rect.bottom - TotalHeight - 5,
2196  0, NULL,
2197  VerStrs[i].lpstr,
2198  VerStrs[i].n,
2199  NULL, 0);
2200 
2201  /* While the first string was using hFont1, all the others use hFont2 */
2202  if (hFont2) NtGdiSelectFont(hDC, hFont2);
2203  }
2204  }
2205  else
2206  {
2207  if (hFont1) NtGdiSelectFont(hDC, hFont1);
2208 
2209  /* Safe Mode: single version information text in top center */
2210  len = wcslen(wszzVersion);
2211 
2213  GreExtTextOutW(hDC, (Rect.right + Rect.left)/2, Rect.top + 3, 0, NULL, wszzVersion, len, NULL, 0);
2214  }
2215  }
2216 
2217  if (InSafeMode)
2218  {
2219  if (hFont1) NtGdiSelectFont(hDC, hFont1);
2220 
2221  /* Print Safe Mode text in corners */
2222  len = wcslen(s_wszSafeMode);
2223 
2225  GreExtTextOutW(hDC, Rect.left, Rect.top + 3, 0, NULL, s_wszSafeMode, len, NULL, 0);
2227  GreExtTextOutW(hDC, Rect.right, Rect.top + 3, 0, NULL, s_wszSafeMode, len, NULL, 0);
2229  GreExtTextOutW(hDC, Rect.left, Rect.bottom - 5, 0, NULL, s_wszSafeMode, len, NULL, 0);
2231  GreExtTextOutW(hDC, Rect.right, Rect.bottom - 5, 0, NULL, s_wszSafeMode, len, NULL, 0);
2232  }
2233 
2234  IntGdiSetBkMode(hDC, mode_old);
2235  IntGdiSetTextAlign(hDC, align_old);
2236  IntGdiSetTextColor(hDC, color_old);
2237 
2238  if (hFont2)
2239  GreDeleteObject(hFont2);
2240 
2241  if (hFont1)
2242  {
2243  NtGdiSelectFont(hDC, hOldFont);
2244  GreDeleteObject(hFont1);
2245  }
2246  }
2247 
2248  return TRUE;
2249 }
2250 
2251 static NTSTATUS
2253 {
2254  PVOID DesktopHeapSystemBase = NULL;
2256  SIZE_T DesktopInfoSize;
2257  ULONG i;
2258 
2259  TRACE("UserInitializeDesktop desktop 0x%p with name %wZ\n", pdesk, DesktopName);
2260 
2261  RtlZeroMemory(pdesk, sizeof(DESKTOP));
2262 
2263  /* Link the desktop with the parent window station */
2264  ObReferenceObject(pwinsta);
2265  pdesk->rpwinstaParent = pwinsta;
2266  InsertTailList(&pwinsta->DesktopListHead, &pdesk->ListEntry);
2267 
2268  /* Create the desktop heap */
2269  pdesk->hsectionDesktop = NULL;
2270  pdesk->pheapDesktop = UserCreateHeap(&pdesk->hsectionDesktop,
2271  &DesktopHeapSystemBase,
2272  HeapSize);
2273  if (pdesk->pheapDesktop == NULL)
2274  {
2275  ERR("Failed to create desktop heap!\n");
2276  return STATUS_NO_MEMORY;
2277  }
2278 
2279  /* Create DESKTOPINFO */
2280  DesktopInfoSize = sizeof(DESKTOPINFO) + DesktopName->Length + sizeof(WCHAR);
2281  pdesk->pDeskInfo = RtlAllocateHeap(pdesk->pheapDesktop,
2283  DesktopInfoSize);
2284  if (pdesk->pDeskInfo == NULL)
2285  {
2286  ERR("Failed to create the DESKTOP structure!\n");
2287  return STATUS_NO_MEMORY;
2288  }
2289 
2290  /* Initialize the DESKTOPINFO */
2291  pdesk->pDeskInfo->pvDesktopBase = DesktopHeapSystemBase;
2292  pdesk->pDeskInfo->pvDesktopLimit = (PVOID)((ULONG_PTR)DesktopHeapSystemBase + HeapSize);
2294  DesktopName->Buffer,
2295  DesktopName->Length + sizeof(WCHAR));
2296  for (i = 0; i < NB_HOOKS; i++)
2297  {
2299  }
2300 
2302  InitializeListHead(&pdesk->PtiList);
2303 
2304  return STATUS_SUCCESS;
2305 }
2306 
2307 /* SYSCALLS *******************************************************************/
2308 
2309 /*
2310  * NtUserCreateDesktop
2311  *
2312  * Creates a new desktop.
2313  *
2314  * Parameters
2315  * poaAttribs
2316  * Object Attributes.
2317  *
2318  * lpszDesktopDevice
2319  * Name of the device.
2320  *
2321  * pDeviceMode
2322  * Device Mode.
2323  *
2324  * dwFlags
2325  * Interaction flags.
2326  *
2327  * dwDesiredAccess
2328  * Requested type of access.
2329  *
2330  *
2331  * Return Value
2332  * If the function succeeds, the return value is a handle to the newly
2333  * created desktop. If the specified desktop already exists, the function
2334  * succeeds and returns a handle to the existing desktop. When you are
2335  * finished using the handle, call the CloseDesktop function to close it.
2336  * If the function fails, the return value is NULL.
2337  *
2338  * Status
2339  * @implemented
2340  */
2341 
2342 NTSTATUS
2343 FASTCALL
2345  OUT HDESK* phDesktop,
2348  IN PUNICODE_STRING lpszDesktopDevice OPTIONAL,
2349  IN LPDEVMODEW lpdmw OPTIONAL,
2350  IN DWORD dwFlags,
2351  IN ACCESS_MASK dwDesiredAccess)
2352 {
2353  NTSTATUS Status;
2354  PDESKTOP pdesk = NULL;
2355  HDESK hDesk;
2356  BOOLEAN Context = FALSE;
2357  UNICODE_STRING ClassName;
2358  LARGE_STRING WindowName;
2359  BOOL NoHooks = FALSE;
2360  PWND pWnd = NULL;
2361  CREATESTRUCTW Cs;
2362  PTHREADINFO ptiCurrent;
2363  PCLS pcls;
2364 
2365  TRACE("Enter IntCreateDesktop\n");
2366 
2368 
2369  ASSERT(phDesktop);
2370  *phDesktop = NULL;
2371 
2372  ptiCurrent = PsGetCurrentThreadWin32Thread();
2373  ASSERT(ptiCurrent);
2375 
2376  /* Turn off hooks when calling any CreateWindowEx from inside win32k */
2377  NoHooks = (ptiCurrent->TIF_flags & TIF_DISABLEHOOKS);
2378  ptiCurrent->TIF_flags |= TIF_DISABLEHOOKS;
2379  ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags;
2380 
2381  /*
2382  * Try to open already existing desktop
2383  */
2386  AccessMode,
2387  NULL,
2388  dwDesiredAccess,
2389  (PVOID)&Context,
2390  (PHANDLE)&hDesk);
2391  if (!NT_SUCCESS(Status))
2392  {
2393  ERR("ObOpenObjectByName failed to open/create desktop\n");
2394  goto Quit;
2395  }
2396 
2397  /* In case the object was not created (eg if it existed), return now */
2398  if (Context == FALSE)
2399  {
2400  TRACE("IntCreateDesktop opened desktop '%wZ'\n", ObjectAttributes->ObjectName);
2402  goto Quit;
2403  }
2404 
2405  /* Reference the desktop */
2407  0,
2409  KernelMode,
2410  (PVOID*)&pdesk,
2411  NULL);
2412  if (!NT_SUCCESS(Status))
2413  {
2414  ERR("Failed to reference desktop object\n");
2415  goto Quit;
2416  }
2417 
2418  /* Get the desktop window class. The thread desktop does not belong to any desktop
2419  * so the classes created there (including the desktop class) are allocated in the shared heap
2420  * It would cause problems if we used a class that belongs to the caller
2421  */
2422  ClassName.Buffer = WC_DESKTOP;
2423  ClassName.Length = 0;
2424  pcls = IntGetAndReferenceClass(&ClassName, 0, TRUE);
2425  if (pcls == NULL)
2426  {
2427  ASSERT(FALSE);
2429  goto Quit;
2430  }
2431 
2432  RtlZeroMemory(&WindowName, sizeof(WindowName));
2433  RtlZeroMemory(&Cs, sizeof(Cs));
2439  Cs.hInstance = hModClient; // hModuleWin; // Server side winproc!
2440  Cs.lpszName = (LPCWSTR) &WindowName;
2441  Cs.lpszClass = (LPCWSTR) &ClassName;
2442 
2443  /* Use IntCreateWindow instead of co_UserCreateWindowEx because the later expects a thread with a desktop */
2444  pWnd = IntCreateWindow(&Cs, &WindowName, pcls, NULL, NULL, NULL, pdesk, WINVER);
2445  if (pWnd == NULL)
2446  {
2447  ERR("Failed to create desktop window for the new desktop\n");
2449  goto Quit;
2450  }
2451 
2452  pdesk->dwSessionId = PsGetCurrentProcessSessionId();
2453  pdesk->DesktopWindow = pWnd->head.h;
2454  pdesk->pDeskInfo->spwnd = pWnd;
2455  pWnd->fnid = FNID_DESKTOP;
2456 
2457  ClassName.Buffer = MAKEINTATOM(gpsi->atomSysClass[ICLS_HWNDMESSAGE]);
2458  ClassName.Length = 0;
2459  pcls = IntGetAndReferenceClass(&ClassName, 0, TRUE);
2460  if (pcls == NULL)
2461  {
2462  ASSERT(FALSE);
2464  goto Quit;
2465  }
2466 
2467  RtlZeroMemory(&WindowName, sizeof(WindowName));
2468  RtlZeroMemory(&Cs, sizeof(Cs));
2469  Cs.cx = Cs.cy = 100;
2471  Cs.hInstance = hModClient; // hModuleWin; // Server side winproc!
2472  Cs.lpszName = (LPCWSTR)&WindowName;
2473  Cs.lpszClass = (LPCWSTR)&ClassName;
2474  pWnd = IntCreateWindow(&Cs, &WindowName, pcls, NULL, NULL, NULL, pdesk, WINVER);
2475  if (pWnd == NULL)
2476  {
2477  ERR("Failed to create message window for the new desktop\n");
2479  goto Quit;
2480  }
2481 
2482  pdesk->spwndMessage = pWnd;
2483  pWnd->fnid = FNID_MESSAGEWND;
2484 
2485  /* Now...
2486  if !(WinStaObject->Flags & WSF_NOIO) is (not set) for desktop input output mode (see wiki)
2487  Create Tooltip. Saved in DesktopObject->spwndTooltip.
2488  Tooltip dwExStyle: WS_EX_TOOLWINDOW|WS_EX_TOPMOST
2489  hWndParent are spwndMessage. Use hModuleWin for server side winproc!
2490  The rest is same as message window.
2491  http://msdn.microsoft.com/en-us/library/bb760250(VS.85).aspx
2492  */
2494 
2495 Quit:
2496  if (pdesk != NULL)
2497  {
2498  ObDereferenceObject(pdesk);
2499  }
2500  if (!NT_SUCCESS(Status) && hDesk != NULL)
2501  {
2502  ObCloseHandle(hDesk, AccessMode);
2503  hDesk = NULL;
2504  }
2505  if (!NoHooks)
2506  {
2507  ptiCurrent->TIF_flags &= ~TIF_DISABLEHOOKS;
2508  ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags;
2509  }
2510 
2511  TRACE("Leave IntCreateDesktop, Status 0x%08lx\n", Status);
2512 
2513  if (NT_SUCCESS(Status))
2514  *phDesktop = hDesk;
2515  else
2517  return Status;
2518 }
2519 
2520 HDESK APIENTRY
2523  PUNICODE_STRING lpszDesktopDevice,
2524  LPDEVMODEW lpdmw,
2525  DWORD dwFlags,
2526  ACCESS_MASK dwDesiredAccess)
2527 {
2528  NTSTATUS Status;
2529  HDESK hDesk;
2530 
2531  DECLARE_RETURN(HDESK);
2532 
2533  TRACE("Enter NtUserCreateDesktop\n");
2535 
2536  Status = IntCreateDesktop(&hDesk,
2538  UserMode,
2539  lpszDesktopDevice,
2540  lpdmw,
2541  dwFlags,
2542  dwDesiredAccess);
2543  if (!NT_SUCCESS(Status))
2544  {
2545  ERR("IntCreateDesktop failed, Status 0x%08lx\n", Status);
2546  // SetLastNtError(Status);
2547  RETURN(NULL);
2548  }
2549 
2550  RETURN(hDesk);
2551 
2552 CLEANUP:
2553  TRACE("Leave NtUserCreateDesktop, ret=0x%p\n", _ret_);
2554  UserLeave();
2555  END_CLEANUP;
2556 }
2557 
2558 /*
2559  * NtUserOpenDesktop
2560  *
2561  * Opens an existing desktop.
2562  *
2563  * Parameters
2564  * lpszDesktopName
2565  * Name of the existing desktop.
2566  *
2567  * dwFlags
2568  * Interaction flags.
2569  *
2570  * dwDesiredAccess
2571  * Requested type of access.
2572  *
2573  * Return Value
2574  * Handle to the desktop or zero on failure.
2575  *
2576  * Status
2577  * @implemented
2578  */
2579 
2580 HDESK APIENTRY
2583  DWORD dwFlags,
2584  ACCESS_MASK dwDesiredAccess)
2585 {
2586  NTSTATUS Status;
2587  HDESK Desktop;
2588 
2592  UserMode,
2593  NULL,
2594  dwDesiredAccess,
2595  NULL,
2596  (HANDLE*)&Desktop);
2597 
2598  if (!NT_SUCCESS(Status))
2599  {
2600  ERR("Failed to open desktop\n");
2602  return NULL;
2603  }
2604 
2605  TRACE("Opened desktop %S with handle 0x%p\n", ObjectAttributes->ObjectName->Buffer, Desktop);
2606 
2607  return Desktop;
2608 }
2609 
2611  BOOL fInherit,
2612  ACCESS_MASK dwDesiredAccess)
2613 {
2615  NTSTATUS Status;
2616  ULONG HandleAttributes = 0;
2617  HDESK hdesk = NULL;
2618 
2619  if (!gpdeskInputDesktop)
2620  {
2621  return NULL;
2622  }
2623 
2624  if (pti->ppi->prpwinsta != InputWindowStation)
2625  {
2626  ERR("Tried to open input desktop from non interactive winsta!\n");
2628  return NULL;
2629  }
2630 
2631  if (fInherit) HandleAttributes = OBJ_INHERIT;
2632 
2633  /* Create a new handle to the object */
2637  NULL,
2638  dwDesiredAccess,
2640  UserMode,
2641  (PHANDLE)&hdesk);
2642 
2643  if (!NT_SUCCESS(Status))
2644  {
2645  ERR("Failed to open input desktop object\n");
2647  }
2648 
2649  return hdesk;
2650 }
2651 
2652 /*
2653  * NtUserOpenInputDesktop
2654  *
2655  * Opens the input (interactive) desktop.
2656  *
2657  * Parameters
2658  * dwFlags
2659  * Interaction flags.
2660  *
2661  * fInherit
2662  * Inheritance option.
2663  *
2664  * dwDesiredAccess
2665  * Requested type of access.
2666  *
2667  * Return Value
2668  * Handle to the input desktop or zero on failure.
2669  *
2670  * Status
2671  * @implemented
2672  */
2673 
2674 HDESK APIENTRY
2676  DWORD dwFlags,
2677  BOOL fInherit,
2678  ACCESS_MASK dwDesiredAccess)
2679 {
2680  HDESK hdesk;
2681 
2683  TRACE("Enter NtUserOpenInputDesktop gpdeskInputDesktop 0x%p\n", gpdeskInputDesktop);
2684 
2685  hdesk = UserOpenInputDesktop(dwFlags, fInherit, dwDesiredAccess);
2686 
2687  TRACE("NtUserOpenInputDesktop returning 0x%p\n", hdesk);
2688  UserLeave();
2689  return hdesk;
2690 }
2691 
2692 /*
2693  * NtUserCloseDesktop
2694  *
2695  * Closes a desktop handle.
2696  *
2697  * Parameters
2698  * hDesktop
2699  * Handle to the desktop.
2700  *
2701  * Return Value
2702  * Status
2703  *
2704  * Remarks
2705  * The desktop handle can be created with NtUserCreateDesktop or
2706  * NtUserOpenDesktop. This function will fail if any thread in the calling
2707  * process is using the specified desktop handle or if the handle refers
2708  * to the initial desktop of the calling process.
2709  *
2710  * Status
2711  * @implemented
2712  */
2713 
2714 BOOL APIENTRY
2715 NtUserCloseDesktop(HDESK hDesktop)
2716 {
2717  PDESKTOP pdesk;
2718  NTSTATUS Status;
2720 
2721  TRACE("NtUserCloseDesktop(0x%p) called\n", hDesktop);
2723 
2724  if (hDesktop == gptiCurrent->hdesk || hDesktop == gptiCurrent->ppi->hdeskStartup)
2725  {
2726  ERR("Attempted to close thread desktop\n");
2728  RETURN(FALSE);
2729  }
2730 
2731  Status = IntValidateDesktopHandle(hDesktop, UserMode, 0, &pdesk);
2732  if (!NT_SUCCESS(Status))
2733  {
2734  ERR("Validation of desktop handle 0x%p failed\n", hDesktop);
2735  RETURN(FALSE);
2736  }
2737 
2738  ObDereferenceObject(pdesk);
2739 
2740  Status = ObCloseHandle(hDesktop, UserMode);
2741  if (!NT_SUCCESS(Status))
2742  {
2743  ERR("Failed to close desktop handle 0x%p\n", hDesktop);
2745  RETURN(FALSE);
2746  }
2747 
2748  RETURN(TRUE);
2749 
2750 CLEANUP:
2751  TRACE("Leave NtUserCloseDesktop, ret=%i\n", _ret_);
2752  UserLeave();
2753  END_CLEANUP;
2754 }
2755 
2756 /*
2757  * NtUserPaintDesktop
2758  *
2759  * The NtUserPaintDesktop function fills the clipping region in the
2760  * specified device context with the desktop pattern or wallpaper. The
2761  * function is provided primarily for shell desktops.
2762  *
2763  * Parameters
2764  * hDC
2765  * Handle to the device context.
2766  *
2767  * Status
2768  * @implemented
2769  */
2770 
2771 BOOL APIENTRY
2773 {
2774  BOOL Ret;
2775 
2777  TRACE("Enter NtUserPaintDesktop\n");
2778 
2779  Ret = IntPaintDesktop(hDC);
2780 
2781  TRACE("Leave NtUserPaintDesktop, ret=%i\n", Ret);
2782  UserLeave();
2783  return Ret;
2784 }
2785 
2786 /*
2787  * NtUserResolveDesktop
2788  *
2789  * The NtUserResolveDesktop function attempts to retrieve valid handles to
2790  * a desktop and a window station suitable for the specified process.
2791  * The specified desktop path string is used only as a hint for the resolution.
2792  *
2793  * See the description of IntResolveDesktop for more details.
2794  *
2795  * Parameters
2796  * ProcessHandle
2797  * Handle to a user process.
2798  *
2799  * DesktopPath
2800  * The desktop path string used as a hint for desktop resolution.
2801  *
2802  * bInherit
2803  * Whether or not the returned handles are inheritable.
2804  *
2805  * phWinSta
2806  * Pointer to a window station handle.
2807  *
2808  * Return Value
2809  * Handle to the desktop (direct return value) and
2810  * handle to the associated window station (by pointer).
2811  * NULL in case of failure.
2812  *
2813  * Remarks
2814  * Callable by CSRSS only.
2815  *
2816  * Status
2817  * @implemented
2818  */
2819 
2820 HDESK
2821 NTAPI
2824  IN PUNICODE_STRING DesktopPath,
2825  IN BOOL bInherit,
2826  OUT HWINSTA* phWinSta)
2827 {
2828  NTSTATUS Status;
2830  HWINSTA hWinSta = NULL;
2831  HDESK hDesktop = NULL;
2832  UNICODE_STRING CapturedDesktopPath;
2833 
2834  /* Allow only the Console Server to perform this operation (via CSRSS) */
2835  if (PsGetCurrentProcess() != gpepCSRSS)
2836  return NULL;
2837 
2838  /* Get the process object the user handle was referencing */
2841  *PsProcessType,
2842  UserMode,
2843  (PVOID*)&Process,
2844  NULL);
2845  if (!NT_SUCCESS(Status))
2846  return NULL;
2847 
2849 
2850  _SEH2_TRY
2851  {
2852  /* Probe the handle pointer */
2853  // ProbeForWriteHandle
2854  ProbeForWrite(phWinSta, sizeof(HWINSTA), sizeof(HWINSTA));
2855  }
2857  {
2859  _SEH2_YIELD(goto Quit);
2860  }
2861  _SEH2_END;
2862 
2863  /* Capture the user desktop path string */
2864  Status = ProbeAndCaptureUnicodeString(&CapturedDesktopPath,
2865  UserMode,
2866  DesktopPath);
2867  if (!NT_SUCCESS(Status))
2868  goto Quit;
2869 
2870  /* Call the internal function */
2872  &CapturedDesktopPath,
2873  bInherit,
2874  &hWinSta,
2875  &hDesktop);
2876  if (!NT_SUCCESS(Status))
2877  {
2878  ERR("IntResolveDesktop failed, Status 0x%08lx\n", Status);
2879  hWinSta = NULL;
2880  hDesktop = NULL;
2881  }
2882 
2883  _SEH2_TRY
2884  {
2885  /* Return the window station handle */
2886  *phWinSta = hWinSta;
2887  }
2889  {
2891 
2892  /* We failed, close the opened desktop and window station */
2893  if (hDesktop) ObCloseHandle(hDesktop, UserMode);
2894  hDesktop = NULL;
2895  if (hWinSta) ObCloseHandle(hWinSta, UserMode);
2896  }
2897  _SEH2_END;
2898 
2899  /* Free the captured string */
2900  ReleaseCapturedUnicodeString(&CapturedDesktopPath, UserMode);
2901 
2902 Quit:
2903  UserLeave();
2904 
2905  /* Dereference the process object */
2907 
2908  /* Return the desktop handle */
2909  return hDesktop;
2910 }
2911 
2912 /*
2913  * NtUserSwitchDesktop
2914  *
2915  * Sets the current input (interactive) desktop.
2916  *
2917  * Parameters
2918  * hDesktop
2919  * Handle to desktop.
2920  *
2921  * Return Value
2922  * Status
2923  *
2924  * Status
2925  * @unimplemented
2926  */
2927 
2928 BOOL APIENTRY
2930 {
2931  PDESKTOP pdesk;
2932  NTSTATUS Status;
2933  BOOL bRedrawDesktop;
2935 
2937  TRACE("Enter NtUserSwitchDesktop(0x%p)\n", hdesk);
2938 
2939  Status = IntValidateDesktopHandle(hdesk, UserMode, 0, &pdesk);
2940  if (!NT_SUCCESS(Status))
2941  {
2942  ERR("Validation of desktop handle 0x%p failed\n", hdesk);
2943  RETURN(FALSE);
2944  }
2945 
2946  if (PsGetCurrentProcessSessionId() != pdesk->rpwinstaParent->dwSessionId)
2947  {
2948  ObDereferenceObject(pdesk);
2949  ERR("NtUserSwitchDesktop called for a desktop of a different session\n");
2950  RETURN(FALSE);
2951  }
2952 
2953  if (pdesk == gpdeskInputDesktop)
2954  {
2955  ObDereferenceObject(pdesk);
2956  WARN("NtUserSwitchDesktop called for active desktop\n");
2957  RETURN(TRUE);
2958  }
2959 
2960  /*
2961  * Don't allow applications switch the desktop if it's locked, unless the caller
2962  * is the logon application itself
2963  */
2964  if ((pdesk->rpwinstaParent->Flags & WSS_LOCKED) &&
2966  {
2967  ObDereferenceObject(pdesk);
2968  ERR("Switching desktop 0x%p denied because the window station is locked!\n", hdesk);
2969  RETURN(FALSE);
2970  }
2971 
2972  if (pdesk->rpwinstaParent != InputWindowStation)
2973  {
2974  ObDereferenceObject(pdesk);
2975  ERR("Switching desktop 0x%p denied because desktop doesn't belong to the interactive winsta!\n", hdesk);
2976  RETURN(FALSE);
2977  }
2978 
2979  /* FIXME: Fail if the process is associated with a secured
2980  desktop such as Winlogon or Screen-Saver */
2981  /* FIXME: Connect to input device */
2982 
2983  TRACE("Switching from desktop 0x%p to 0x%p\n", gpdeskInputDesktop, pdesk);
2984 
2985  bRedrawDesktop = FALSE;
2986 
2987  /* The first time SwitchDesktop is called, gpdeskInputDesktop is NULL */
2988  if (gpdeskInputDesktop != NULL)
2989  {
2991  bRedrawDesktop = TRUE;
2992 
2993  /* Hide the previous desktop window */
2995  }
2996 
2997  /* Set the active desktop in the desktop's window station. */
2999 
3000  /* Set the global state. */
3001  gpdeskInputDesktop = pdesk;
3002 
3003  /* Show the new desktop window */
3005 
3006  TRACE("SwitchDesktop gpdeskInputDesktop 0x%p\n", gpdeskInputDesktop);
3007  ObDereferenceObject(pdesk);
3008 
3009  RETURN(TRUE);
3010 
3011 CLEANUP:
3012  TRACE("Leave NtUserSwitchDesktop, ret=%i\n", _ret_);
3013  UserLeave();
3014  END_CLEANUP;
3015 }
3016 
3017 /*
3018  * NtUserGetThreadDesktop
3019  *
3020  * Status
3021  * @implemented
3022  */
3023 
3024 HDESK APIENTRY
3025 NtUserGetThreadDesktop(DWORD dwThreadId, HDESK hConsoleDesktop)
3026 {
3027  HDESK hDesk;
3028  NTSTATUS Status;
3029  PTHREADINFO pti;
3031  PDESKTOP DesktopObject;
3033 
3035  TRACE("Enter NtUserGetThreadDesktop\n");
3036 
3037  if (!dwThreadId)
3038  {
3040  hDesk = NULL;
3041  goto Quit;
3042  }
3043 
3044  /* Validate the Win32 thread and retrieve its information */
3046  if (pti)
3047  {
3048  /* Get the desktop handle of the thread */
3049  hDesk = pti->hdesk;
3050  Process = pti->ppi->peProcess;
3051  }
3052  else if (hConsoleDesktop)
3053  {
3054  /*
3055  * The thread may belong to a console, so attempt to use the provided
3056  * console desktop handle as a fallback. Otherwise this means that the
3057  * thread is either not Win32 or invalid.
3058  */
3059  hDesk = hConsoleDesktop;
3060  Process = gpepCSRSS;
3061  }
3062  else
3063  {
3065  hDesk = NULL;
3066  goto Quit;
3067  }
3068 
3069  if (!hDesk)
3070  {
3071  ERR("Desktop information of thread 0x%x broken!?\n", dwThreadId);
3072  goto Quit;
3073  }
3074 
3075  if (Process == PsGetCurrentProcess())
3076  {
3077  /*
3078  * Just return the handle, since we queried the desktop handle
3079  * of a thread running in the same context.
3080  */
3081  goto Quit;
3082  }
3083 
3084  /*
3085  * We could just use the cached rpdesk instead of looking up the handle,
3086  * but it may actually be safer to validate the desktop and get a temporary
3087  * reference to it so that it does not disappear under us (e.g. when the
3088  * desktop is being destroyed) during the operation.
3089  */
3090  /*
3091  * Switch into the context of the thread we are trying to get
3092  * the desktop from, so we can use the handle.
3093  */
3094  KeAttachProcess(&Process->Pcb);
3096  0,
3098  UserMode,
3099  (PVOID*)&DesktopObject,
3101  KeDetachProcess();
3102 
3103  if (NT_SUCCESS(Status))
3104  {
3105  /*
3106  * Lookup our handle table if we can find a handle to the desktop object.
3107  * If not, create one.
3108  * QUESTION: Do we really need to create a handle in case it doesn't exist??
3109  */
3110  hDesk = IntGetDesktopObjectHandle(DesktopObject);
3111 
3112  /* All done, we got a valid handle to the desktop */
3113  ObDereferenceObject(DesktopObject);
3114  }
3115  else
3116  {
3117  /* The handle could not be found, there is nothing to get... */
3118  hDesk = NULL;
3119  }
3120 
3121  if (!hDesk)
3122  {
3123  ERR("Could not retrieve or access desktop for thread 0x%x\n", dwThreadId);
3125  }
3126 
3127 Quit:
3128  TRACE("Leave NtUserGetThreadDesktop, hDesk = 0x%p\n", hDesk);
3129  UserLeave();
3130  return hDesk;
3131 }
3132 
3133 static NTSTATUS
3135 {
3136  PPROCESSINFO ppi;
3137  PW32HEAP_USER_MAPPING HeapMapping, *PrevLink;
3139 
3140  TRACE("IntUnmapDesktopView called for desktop object %p\n", pdesk);
3141 
3143 
3144  /*
3145  * Unmap if we're the last thread using the desktop.
3146  * Start the search at the next mapping: skip the first entry
3147  * as it must be the global user heap mapping.
3148  */
3149  PrevLink = &ppi->HeapMappings.Next;
3150  HeapMapping = *PrevLink;
3151  while (HeapMapping != NULL)
3152  {
3153  if (HeapMapping->KernelMapping == (PVOID)pdesk->pheapDesktop)
3154  {
3155  if (--HeapMapping->Count == 0)
3156  {
3157  *PrevLink = HeapMapping->Next;
3158 
3159  TRACE("ppi 0x%p unmapped heap of desktop 0x%p\n", ppi, pdesk);
3161  HeapMapping->UserMapping);
3162 
3163  ObDereferenceObject(pdesk);
3164 
3165  UserHeapFree(HeapMapping);
3166  break;
3167  }
3168  }
3169 
3170  PrevLink = &HeapMapping->Next;
3171  HeapMapping = HeapMapping->Next;
3172  }
3173 
3174  return Status;
3175 }
3176 
3177 static NTSTATUS
3179 {
3180  PPROCESSINFO ppi;
3181  PW32HEAP_USER_MAPPING HeapMapping, *PrevLink;
3182  PVOID UserBase = NULL;
3183  SIZE_T ViewSize = 0;
3185  NTSTATUS Status;
3186 
3187  TRACE("IntMapDesktopView called for desktop object 0x%p\n", pdesk);
3188 
3190 
3191  /*
3192  * Find out if another thread already mapped the desktop heap.
3193  * Start the search at the next mapping: skip the first entry
3194  * as it must be the global user heap mapping.
3195  */
3196  PrevLink = &ppi->HeapMappings.Next;
3197  HeapMapping = *PrevLink;
3198  while (HeapMapping != NULL)
3199  {
3200  if (HeapMapping->KernelMapping == (PVOID)pdesk->pheapDesktop)
3201  {
3202  HeapMapping->Count++;
3203  return STATUS_SUCCESS;
3204  }
3205 
3206  PrevLink = &HeapMapping->Next;
3207  HeapMapping = HeapMapping->Next;
3208  }
3209 
3210  /* We're the first, map the heap */
3211  Offset.QuadPart = 0;
3212  Status = MmMapViewOfSection(pdesk->hsectionDesktop,
3214  &UserBase,
3215  0,
3216  0,
3217  &Offset,
3218  &ViewSize,
3219  ViewUnmap,
3220  SEC_NO_CHANGE,
3221  PAGE_EXECUTE_READ); /* Would prefer PAGE_READONLY, but thanks to RTL heaps... */
3222  if (!NT_SUCCESS(Status))
3223  {
3224  ERR("Failed to map desktop\n");
3225  return Status;
3226  }
3227 
3228  TRACE("ppi 0x%p mapped heap of desktop 0x%p\n", ppi, pdesk);
3229 
3230  /* Add the mapping */
3231  HeapMapping = UserHeapAlloc(sizeof(*HeapMapping));
3232  if (HeapMapping == NULL)
3233  {
3235  ERR("UserHeapAlloc() failed!\n");
3236  return STATUS_NO_MEMORY;
3237  }
3238 
3239  HeapMapping->Next = NULL;
3240  HeapMapping->KernelMapping = (PVOID)pdesk->pheapDesktop;
3241  HeapMapping->UserMapping = UserBase;
3242  HeapMapping->Limit = ViewSize;
3243  HeapMapping->Count = 1;
3244  *PrevLink = HeapMapping;
3245 
3246  ObReferenceObject(pdesk);
3247 
3248  return STATUS_SUCCESS;
3249 }
3250 
3251 BOOL
3252 IntSetThreadDesktop(IN HDESK hDesktop,
3253  IN BOOL FreeOnFailure)
3254 {
3255  PDESKTOP pdesk = NULL, pdeskOld;
3256  PTHREADINFO pti;
3257  NTSTATUS Status;
3258  PCLIENTTHREADINFO pctiOld, pctiNew = NULL;
3259  PCLIENTINFO pci;
3260 
3261  ASSERT(NtCurrentTeb());
3262 
3263  TRACE("IntSetThreadDesktop hDesktop:0x%p, FOF:%i\n",hDesktop, FreeOnFailure);
3264 
3266  pci = pti->pClientInfo;
3267 
3268  /* If the caller gave us a desktop, ensure it is valid */
3269  if (hDesktop != NULL)
3270  {
3271  /* Validate the new desktop. */
3272  Status = IntValidateDesktopHandle(hDesktop, UserMode, 0, &pdesk);
3273  if (!NT_SUCCESS(Status))
3274  {
3275  ERR("Validation of desktop handle 0x%p failed\n", hDesktop);
3276  return FALSE;
3277  }
3278 
3279  if (pti->rpdesk == pdesk)
3280  {
3281  /* Nothing to do */
3282  ObDereferenceObject(pdesk);
3283  return TRUE;
3284  }
3285  }
3286 
3287  /* Make sure that we don't own any window in the current desktop */
3288  if (!IsListEmpty(&pti->WindowListHead))
3289  {
3290  if (pdesk)
3291  ObDereferenceObject(pdesk);
3292  ERR("Attempted to change thread desktop although the thread has windows!\n");
3294  return FALSE;
3295  }
3296 
3297  /* Desktop is being re-set so clear out foreground. */
3298  if (pti->rpdesk != pdesk && pti->MessageQueue == gpqForeground)
3299  {
3300  // Like above, there shouldn't be any windows, hooks or anything active on this threads desktop!
3302  }
3303 
3304  /* Before doing the switch, map the new desktop heap and allocate the new pcti */
3305  if (pdesk != NULL)
3306  {
3307  Status = IntMapDesktopView(pdesk);
3308  if (!NT_SUCCESS(Status))
3309  {
3310  ERR("Failed to map desktop heap!\n");
3311  ObDereferenceObject(pdesk);
3313  return FALSE;
3314  }
3315 
3316  pctiNew = DesktopHeapAlloc(pdesk, sizeof(CLIENTTHREADINFO));
3317  if (pctiNew == NULL)
3318  {
3319  ERR("Failed to allocate new pcti\n");
3320  IntUnmapDesktopView(pdesk);
3321  ObDereferenceObject(pdesk);
3323  return FALSE;
3324  }
3325  }
3326 
3327  /*
3328  * Processes, in particular Winlogon.exe, that manage window stations
3329  * (especially the interactive WinSta0 window station) and desktops,
3330  * may not be able to connect at startup to a window station and have
3331  * an associated desktop as well, if none exists on the system already.
3332  * Because creating a new window station does not affect the window station
3333  * associated to the process, and because neither by associating a window
3334  * station to the process nor creating a new desktop on it does associate
3335  * a startup desktop to that process, the process has to actually assigns
3336  * one of its threads to a desktop so that it gets automatically an assigned
3337  * startup desktop.
3338  *
3339  * This is what actually happens for Winlogon.exe, which is started without
3340  * any window station and desktop. By creating the first (and therefore
3341  * interactive) WinSta0 window station, then assigning WinSta0 to itself
3342  * and creating the Default desktop on it, and then assigning this desktop
3343  * to its main thread, Winlogon.exe basically does the similar steps that
3344  * would have been done automatically at its startup if there were already
3345  * an existing WinSta0 window station and Default desktop.
3346  *
3347  * Of course all this must not be done if we are a SYSTEM or CSRSS thread.
3348  */
3349  // if (pti->ppi->peProcess != gpepCSRSS)
3350  if (!(pti->TIF_flags & (TIF_SYSTEMTHREAD | TIF_CSRSSTHREAD)) &&
3351  pti->ppi->rpdeskStartup == NULL && hDesktop != NULL)
3352  {
3353  ERR("The process 0x%p '%s' didn't have an assigned startup desktop before, assigning it now!\n",
3354  pti->ppi->peProcess, pti->ppi->peProcess->ImageFileName);
3355 
3356  pti->ppi->hdeskStartup = hDesktop;
3357  pti->ppi->rpdeskStartup = pdesk;
3358  }
3359 
3360  /* free all classes or move them to the shared heap */
3361  if (pti->rpdesk != NULL)
3362  {
3363  if (!IntCheckProcessDesktopClasses(pti->rpdesk, FreeOnFailure))
3364  {
3365  ERR("Failed to move process classes to shared heap!\n");
3366  if (pdesk)
3367  {
3368  DesktopHeapFree(pdesk, pctiNew);
3369  IntUnmapDesktopView(pdesk);
3370  ObDereferenceObject(pdesk);
3371  }
3372  return FALSE;
3373  }
3374  }
3375 
3376  pdeskOld = pti->rpdesk;
3377  if (pti->pcti != &pti->cti)
3378  pctiOld = pti->pcti;
3379  else
3380  pctiOld = NULL;
3381 
3382  /* do the switch */
3383  if (pdesk != NULL)
3384  {
3385  pti->rpdesk = pdesk;
3386  pti->hdesk = hDesktop;
3387  pti->pDeskInfo = pti->rpdesk->pDeskInfo;
3388  pti->pcti = pctiNew;
3389 
3391  pci->pDeskInfo = (PVOID)((ULONG_PTR)pti->pDeskInfo - pci->ulClientDelta);
3392  pci->pClientThreadInfo = (PVOID)((ULONG_PTR)pti->pcti - pci->ulClientDelta);
3393 
3394  /* initialize the new pcti */
3395  if (pctiOld != NULL)
3396  {
3397  RtlCopyMemory(pctiNew, pctiOld, sizeof(CLIENTTHREADINFO));
3398  }
3399  else
3400  {
3401  RtlZeroMemory(pctiNew, sizeof(CLIENTTHREADINFO));
3402  pci->fsHooks = pti->fsHooks;
3403  pci->dwTIFlags = pti->TIF_flags;
3404  }
3405  }
3406  else
3407  {
3408  pti->rpdesk = NULL;
3409  pti->hdesk = NULL;
3410  pti->pDeskInfo = NULL;
3411  pti->pcti = &pti->cti; // Always point inside so there will be no crash when posting or sending msg's!
3412  pci->ulClientDelta = 0;
3413  pci->pDeskInfo = NULL;
3414  pci->pClientThreadInfo = NULL;
3415  }
3416 
3417  /* clean up the old desktop */
3418  if (pdeskOld != NULL)
3419  {
3420  RemoveEntryList(&pti->PtiLink);
3421  if (pctiOld) DesktopHeapFree(pdeskOld, pctiOld);
3422  IntUnmapDesktopView(pdeskOld);
3423  ObDereferenceObject(pdeskOld);
3424  }
3425 
3426  if (pdesk)
3427  {
3428  InsertTailList(&pdesk->PtiList, &pti->PtiLink);
3429  }
3430 
3431  TRACE("IntSetThreadDesktop: pti 0x%p ppi 0x%p switched from object 0x%p to 0x%p\n", pti, pti->ppi, pdeskOld, pdesk);
3432 
3433  return TRUE;
3434 }
3435 
3436 /*
3437  * NtUserSetThreadDesktop
3438  *
3439  * Status
3440  * @implemented
3441  */
3442 
3443 BOOL APIENTRY
3444 NtUserSetThreadDesktop(HDESK hDesktop)
3445 {
3446  BOOL ret = FALSE;
3447 
3449 
3450  // FIXME: IntSetThreadDesktop validates the desktop handle, it should happen
3451  // here too and set the NT error level. Q. Is it necessary to have the validation
3452  // in IntSetThreadDesktop? Is it needed there too?
3453  if (hDesktop || (!hDesktop && PsGetCurrentProcess() == gpepCSRSS))
3454  ret = IntSetThreadDesktop(hDesktop, FALSE);
3455 
3456  UserLeave();
3457 
3458  return ret;
3459 }
3460 
3461 /* 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:2532
BOOL IntCheckProcessDesktopClasses(IN PDESKTOP Desktop, IN BOOL FreeOnFailure)
Definition: class.c:1012
_SEH2_TRY
Definition: create.c:4226
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:1616
#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
#define NOTHING
Definition: input_list.c:10
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:217
#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:2856
#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:42
BOOL APIENTRY NtUserSetThreadDesktop(HDESK hDesktop)
Definition: desktop.c:3444
#define TRUE
Definition: types.h:120
BOOL FASTCALL UserRegisterSystemClasses(VOID)
Definition: class.c:2306
#define ZwCurrentProcess()
LIST_ENTRY WindowListHead
Definition: win32.h:151
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:91
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:1748
#define STATUS_OBJECT_NAME_EXISTS
Definition: ntstatus.h:114
LONG NTSTATUS
Definition: precomp.h:26
#define WINVER
Definition: targetver.h:11
HDEV hDev
Definition: monitor.h:23
struct _DESKTOP * PDESKTOP
static HDC
Definition: imagelist.c:92
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:122
LIST_ENTRY DesktopListHead
Definition: winsta.h:19
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:1439
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
_SEH2_END
Definition: create.c:4400
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:2772
NTSTATUS NTAPI ObOpenObjectByPointer(IN PVOID Object, IN ULONG HandleAttributes, IN PACCESS_STATE PassedAccessState, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PHANDLE Handle)
Definition: obhandle.c:2742
struct _WINSTATION_OBJECT * prpwinsta
Definition: win32.h:257
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:1673
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
SIZE_T WINAPI HeapSize(HANDLE, DWORD, LPCVOID)
PUSER_MESSAGE_QUEUE FASTCALL IntGetFocusMessageQueue(VOID)
Definition: desktop.c:1307
struct _DESKTOP * rpdesk
Definition: win32.h:88
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:2581
#define DT_GWL_PROCESSID
Definition: desktop.h:55
#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:2822
PPROCESSINFO ppi
Definition: win32.h:84
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:447
#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:104
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:254
#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:3134
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:2845
#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:1626
BOOL g_AlwaysDisplayVersion
Definition: ntuser.c:17
BOOL IntRegisterShellHookWindow(HWND hWnd)
Definition: desktop.c:1752
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:1412
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:1827
LONG_PTR LPARAM
Definition: windef.h:208
PWND FASTCALL co_GetDesktopWindow(PWND pWnd)
Definition: desktop.c:1366
#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:3584
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:3919
W32HEAP_USER_MAPPING HeapMappings
Definition: win32.h:281
void * PVOID
Definition: retypes.h:9
struct _CLIENTTHREADINFO * pcti
Definition: win32.h:87
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:2610
#define SM_CYVIRTUALSCREEN
Definition: winuser.h:1033
struct _WINDOWPOS * PWINDOWPOS
#define WM_DESTROY
Definition: winuser.h:1599
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:2946
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:197
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:113
#define InterlockedExchangePointer(Target, Value)
Definition: dshow.h:45
BOOL IntDeRegisterShellHookWindow(HWND hWnd)
Definition: desktop.c:1784
_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:4014
#define OBJ_INHERIT
Definition: winternl.h:225
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
static NTSTATUS IntMapDesktopView(IN PDESKTOP pdesk)
Definition: desktop.c:3178
#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:1271
struct _DESKTOP * rpdeskStartup
Definition: win32.h:249
#define WM_WINDOWPOSCHANGING
Definition: winuser.h:1651
#define WM_CLOSE
Definition: winuser.h:1611
#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:1399
struct _WINSTATION_OBJECT * PWINSTATION_OBJECT
HDC FASTCALL UserGetDesktopDC(ULONG DcType, BOOL bAltDc, BOOL ValidatehWnd)
Definition: desktop.c:1574
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
HWND FASTCALL IntGetCurrentThreadDesktopWindow(VOID)
Definition: desktop.c:1424
struct _CLIENTINFO * pClientInfo
Definition: win32.h:90
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:1525
#define WM_PAINT
Definition: winuser.h:1610
#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:1651
#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:1386
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:3379
VOID NTAPI DesktopThreadMain(VOID)
Definition: desktop.c:1546
LONG HighPart
BOOL APIENTRY NtUserCloseDesktop(HDESK hDesktop)
Definition: desktop.c:2715
#define NB_HOOKS
Definition: ntuser.h:127
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1175
LPCWSTR lpszName
Definition: winuser.h:2954
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
NTSTATUS FASTCALL co_IntShowDesktop(PDESKTOP Desktop, ULONG Width, ULONG Height, BOOL bRedraw)
Definition: desktop.c:1617
Definition: typedefs.h:119
HDESK APIENTRY NtUserCreateDesktop(POBJECT_ATTRIBUTES ObjectAttributes, PUNICODE_STRING lpszDesktopDevice, LPDEVMODEW lpdmw, DWORD dwFlags, ACCESS_MASK dwDesiredAccess)
Definition: desktop.c:2521
CLIENTTHREADINFO cti
Definition: win32.h:140
PDESKTOPINFO pDeskInfo
Definition: ntuser.h:308
#define wcsrchr
Definition: compat.h:16
VOID APIENTRY UserRedrawDesktop(VOID)
Definition: desktop.c:1599
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:2675
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:85
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:1374
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:1319
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:2344
#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:235
#define WINSTA_ACCESS_ALL
Definition: security.h:57
HWINSTA hwinsta
Definition: win32.h:258
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:3252
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:1237
#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:1692
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:2252
#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:1598
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:2955
#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
struct @1592 Msg[]
#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:1262
#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:1615
#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:89
#define WS_VISIBLE
Definition: pedump.c:620
HDESK APIENTRY NtUserGetThreadDesktop(DWORD dwThreadId, HDESK hConsoleDesktop)
Definition: desktop.c:3025
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:194
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:2929
#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:1359
ATOM atomSysClass[ICLS_NOTUSED+1]
Definition: ntuser.h:1031
LIST_ENTRY ShellHookWindows
Definition: desktop.h:43
NTSTATUS FASTCALL IntHideDesktop(PDESKTOP Desktop)
Definition: desktop.c:1635
#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