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