* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * $Id: desktop.c,v 1.12 2004/05/05 22:47:06 weiden Exp $
+ * $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
/* INCLUDES ******************************************************************/
-#define __WIN32K__
-#include <ddk/ntddmou.h>
-#include <win32k/win32k.h>
-#include <csrss/csrss.h>
-#include <include/winsta.h>
-#include <include/desktop.h>
-#include <include/object.h>
-#include <include/window.h>
-#include <include/error.h>
-#include <include/cursoricon.h>
-#include <include/hotkey.h>
-#include <include/color.h>
-#include <include/mouse.h>
-#include <include/callback.h>
-#include <include/guicheck.h>
-#include <include/intgdi.h>
+#include <w32k.h>
#define NDEBUG
#include <debug.h>
-#if 0
-/* not yet defined in w32api... */
-NTSTATUS STDCALL
-ObFindHandleForObject(IN PEPROCESS Process,
- IN PVOID Object,
- IN POBJECT_TYPE ObjectType,
- IN POBJECT_HANDLE_INFORMATION HandleInformation,
- OUT PHANDLE Handle);
-#else
-#define ObFindHandleForObject(Process, Object, ObjectType, HandleInformation, Handle) \
- (STATUS_UNSUCCESSFUL)
-#endif
-
/* GLOBALS *******************************************************************/
/* Currently active desktop */
PDESKTOP_OBJECT InputDesktop = NULL;
-HDESK InputDesktopHandle = NULL;
+HDESK InputDesktopHandle = NULL;
HDC ScreenDeviceContext = NULL;
+BOOL g_PaintDesktopVersion = FALSE;
+
/* INITALIZATION FUNCTIONS ****************************************************/
+static GENERIC_MAPPING IntDesktopMapping =
+ {
+ STANDARD_RIGHTS_READ | DESKTOP_ENUMERATE | DESKTOP_READOBJECTS,
+ STANDARD_RIGHTS_WRITE | DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | DESKTOP_HOOKCONTROL |
+ DESKTOP_JOURNALPLAYBACK | DESKTOP_JOURNALRECORD | DESKTOP_WRITEOBJECTS,
+ STANDARD_RIGHTS_EXECUTE | DESKTOP_SWITCHDESKTOP,
+ STANDARD_RIGHTS_REQUIRED | DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | DESKTOP_ENUMERATE |
+ DESKTOP_HOOKCONTROL | DESKTOP_JOURNALPLAYBACK | DESKTOP_JOURNALRECORD |
+ DESKTOP_READOBJECTS | DESKTOP_SWITCHDESKTOP | DESKTOP_WRITEOBJECTS
+ };
+
NTSTATUS FASTCALL
InitDesktopImpl(VOID)
{
- return STATUS_SUCCESS;
+ /* Set Desktop Object Attributes */
+ ExDesktopObjectType->TypeInfo.DefaultNonPagedPoolCharge = sizeof(DESKTOP_OBJECT);
+ ExDesktopObjectType->TypeInfo.GenericMapping = IntDesktopMapping;
+
+ return STATUS_SUCCESS;
}
NTSTATUS FASTCALL
CleanupDesktopImpl(VOID)
{
- return STATUS_SUCCESS;
+ return STATUS_SUCCESS;
+}
+
+/* OBJECT CALLBACKS **********************************************************/
+
+NTSTATUS STDCALL
+IntDesktopObjectCreate(PVOID ObjectBody,
+ PVOID Parent,
+ PWSTR RemainingPath,
+ struct _OBJECT_ATTRIBUTES* ObjectAttributes)
+{
+ PDESKTOP_OBJECT Desktop = (PDESKTOP_OBJECT)ObjectBody;
+ UNICODE_STRING UnicodeString;
+
+ DPRINT("Creating desktop (0x%X) Name (%S)\n", Desktop, RemainingPath);
+ if (RemainingPath == NULL)
+ {
+ return STATUS_SUCCESS;
+ }
+
+ if (wcschr((RemainingPath + 1), '\\') != NULL)
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ RtlInitUnicodeString(&UnicodeString, (RemainingPath + 1));
+
+ InitializeListHead(&Desktop->ShellHookWindows);
+
+ Desktop->WindowStation = (PWINSTATION_OBJECT)Parent;
+
+ /* Put the desktop on the window station's list of associcated desktops */
+// ExInterlocked
+ InsertTailList(
+ &Desktop->WindowStation->DesktopListHead,
+ &Desktop->ListEntry);//,
+// &Desktop->WindowStation->Lock);
+
+ return RtlCreateUnicodeString(&Desktop->Name, UnicodeString.Buffer);
+}
+
+VOID STDCALL
+IntDesktopObjectDelete(PVOID DeletedObject)
+{
+ PDESKTOP_OBJECT Desktop = (PDESKTOP_OBJECT)DeletedObject;
+
+ DPRINT("Deleting desktop (0x%X)\n", Desktop);
+
+ /* Remove the desktop from the window station's list of associcated desktops */
+ RemoveEntryList(&Desktop->ListEntry);
+
+ RtlFreeUnicodeString(&Desktop->Name);
}
/* PRIVATE FUNCTIONS **********************************************************/
+static int GetSystemVersionString(LPWSTR buffer)
+{
+ RTL_OSVERSIONINFOEXW versionInfo;
+ int len;
+
+ versionInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW);
+
+ if (!NT_SUCCESS(RtlGetVersion((PRTL_OSVERSIONINFOW)&versionInfo)))
+ return 0;
+
+ if (versionInfo.dwMajorVersion <= 4)
+ len = swprintf(buffer,
+ L"ReactOS Version %d.%d %s Build %d",
+ versionInfo.dwMajorVersion, versionInfo.dwMinorVersion,
+ versionInfo.szCSDVersion, versionInfo.dwBuildNumber&0xFFFF);
+ else
+ len = swprintf(buffer,
+ L"ReactOS %s (Build %d)",
+ versionInfo.szCSDVersion, versionInfo.dwBuildNumber&0xFFFF);
+
+ return len;
+}
+
+
+NTSTATUS FASTCALL
+IntParseDesktopPath(PEPROCESS Process,
+ PUNICODE_STRING DesktopPath,
+ HWINSTA *hWinSta,
+ HDESK *hDesktop)
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING WinSta, Desktop, FullName;
+ BOOL DesktopPresent = FALSE;
+ BOOL WinStaPresent = FALSE;
+ NTSTATUS Status;
+
+ ASSERT(hWinSta);
+
+ *hWinSta = NULL;
+
+ if(hDesktop != NULL)
+ {
+ *hDesktop = NULL;
+ }
+
+ RtlInitUnicodeString(&WinSta, NULL);
+ RtlInitUnicodeString(&Desktop, NULL);
+
+ if(DesktopPath != NULL && DesktopPath->Buffer != NULL && DesktopPath->Length > sizeof(WCHAR))
+ {
+ PWCHAR c = DesktopPath->Buffer;
+ USHORT wl = 0;
+ USHORT l = DesktopPath->Length;
+
+ /*
+ * Parse the desktop path string which can be in the form "WinSta\Desktop"
+ * or just "Desktop". In latter case WinSta0 will be used.
+ */
+
+ while(l > 0)
+ {
+ if(*c == L'\\')
+ {
+ wl = (ULONG_PTR)c - (ULONG_PTR)DesktopPath->Buffer;
+ break;
+ }
+ l -= sizeof(WCHAR);
+ c++;
+ }
+
+ if(wl > 0)
+ {
+ WinSta.Length = wl;
+ WinSta.MaximumLength = wl + sizeof(WCHAR);
+ WinSta.Buffer = DesktopPath->Buffer;
+
+ WinStaPresent = TRUE;
+ c++;
+ }
+
+ Desktop.Length = DesktopPath->Length - wl;
+ if(wl > 0)
+ {
+ Desktop.Length -= sizeof(WCHAR);
+ }
+ if(Desktop.Length > 0)
+ {
+ Desktop.MaximumLength = Desktop.Length + sizeof(WCHAR);
+ Desktop.Buffer = ((wl > 0) ? c : DesktopPath->Buffer);
+ DesktopPresent = TRUE;
+ }
+ }
+
+ if(!WinStaPresent)
+ {
+ /* search the process handle table for (inherited) window station
+ handles, use a more appropriate one than WinSta0 if possible. */
+ Status = ObFindHandleForObject(Process,
+ NULL,
+ ExWindowStationObjectType,
+ NULL,
+ (PHANDLE)hWinSta);
+ if(!NT_SUCCESS(Status))
+ {
+ /* we had no luck searching for opened handles, use WinSta0 now */
+ RtlInitUnicodeString(&WinSta, L"WinSta0");
+ }
+ }
+
+ if(!DesktopPresent && hDesktop != NULL)
+ {
+ /* search the process handle table for (inherited) desktop
+ handles, use a more appropriate one than Default if possible. */
+ Status = ObFindHandleForObject(Process,
+ NULL,
+ ExDesktopObjectType,
+ NULL,
+ (PHANDLE)hDesktop);
+ if(!NT_SUCCESS(Status))
+ {
+ /* we had no luck searching for opened handles, use Desktop now */
+ RtlInitUnicodeString(&Desktop, L"Default");
+ }
+ }
+
+ if(*hWinSta == NULL)
+ {
+ if(!IntGetFullWindowStationName(&FullName, &WinSta, NULL))
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* open the window station */
+ InitializeObjectAttributes(&ObjectAttributes,
+ &FullName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = ObOpenObjectByName(&ObjectAttributes,
+ ExWindowStationObjectType,
+ NULL,
+ KernelMode,
+ 0,
+ NULL,
+ (HANDLE*)hWinSta);
+
+ RtlFreeUnicodeString(&FullName);
+
+ if(!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ DPRINT("Failed to reference window station %wZ PID: %d!\n", &WinSta, PsGetCurrentProcessId());
+ return Status;
+ }
+ }
+
+ if(hDesktop != NULL && *hDesktop == NULL)
+ {
+ if(!IntGetFullWindowStationName(&FullName, &WinSta, &Desktop))
+ {
+ NtClose(*hWinSta);
+ *hWinSta = NULL;
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* open the desktop object */
+ InitializeObjectAttributes(&ObjectAttributes,
+ &FullName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = ObOpenObjectByName(&ObjectAttributes,
+ ExDesktopObjectType,
+ NULL,
+ KernelMode,
+ 0,
+ NULL,
+ (HANDLE*)hDesktop);
+
+ RtlFreeUnicodeString(&FullName);
+
+ if(!NT_SUCCESS(Status))
+ {
+ *hDesktop = NULL;
+ NtClose(*hWinSta);
+ *hWinSta = NULL;
+ SetLastNtError(Status);
+ DPRINT("Failed to reference desktop %wZ PID: %d!\n", &Desktop, PsGetCurrentProcessId());
+ return Status;
+ }
+ }
+
+ return STATUS_SUCCESS;
+}
+
/*
* IntValidateDesktopHandle
*
NTSTATUS Status;
Status = ObReferenceObjectByHandle(
- Desktop,
- DesiredAccess,
- ExDesktopObjectType,
- AccessMode,
- (PVOID*)Object,
- NULL);
+ Desktop,
+ DesiredAccess,
+ ExDesktopObjectType,
+ AccessMode,
+ (PVOID*)Object,
+ NULL);
if (!NT_SUCCESS(Status))
SetLastNtError(Status);
return Status;
}
-PRECT FASTCALL
-IntGetDesktopWorkArea(PDESKTOP_OBJECT Desktop)
+VOID FASTCALL
+IntGetDesktopWorkArea(PDESKTOP_OBJECT Desktop, PRECT Rect)
{
- PRECT Ret;
-
- Ret = &Desktop->WorkArea;
- if((Ret->right == -1) && ScreenDeviceContext)
- {
- PDC dc;
- SURFOBJ *SurfObj;
- dc = DC_LockDc(ScreenDeviceContext);
- SurfObj = (SURFOBJ*)AccessUserObject((ULONG) dc->Surface);
- if(SurfObj)
- {
- Ret->right = SurfObj->sizlBitmap.cx;
- Ret->bottom = SurfObj->sizlBitmap.cy;
- }
- DC_UnlockDc(ScreenDeviceContext);
- }
-
- return Ret;
+ PRECT Ret;
+
+ ASSERT(Desktop);
+
+ Ret = &Desktop->WorkArea;
+ if((Ret->right == -1) && ScreenDeviceContext)
+ {
+ PDC dc;
+ BITMAPOBJ *BitmapObj;
+ dc = DC_LockDc(ScreenDeviceContext);
+ /* FIXME - Handle dc == NULL!!!! */
+ BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
+ if(BitmapObj)
+ {
+ Ret->right = BitmapObj->SurfObj.sizlBitmap.cx;
+ Ret->bottom = BitmapObj->SurfObj.sizlBitmap.cy;
+ BITMAPOBJ_UnlockBitmap(BitmapObj);
+ }
+ DC_UnlockDc(dc);
+ }
+
+ if(Rect)
+ {
+ *Rect = *Ret;
+ }
}
PDESKTOP_OBJECT FASTCALL
IntGetActiveDesktop(VOID)
{
- return InputDesktop;
+ return InputDesktop;
}
/*
HDESK FASTCALL
IntGetDesktopObjectHandle(PDESKTOP_OBJECT DesktopObject)
{
- NTSTATUS Status;
- HDESK Ret;
-
- ASSERT(DesktopObject);
-
- Status = ObFindHandleForObject(PsGetCurrentProcess(),
- DesktopObject,
- ExDesktopObjectType,
- NULL,
- (PHANDLE)&Ret);
-
- if(!NT_SUCCESS(Status))
- {
- Status = ObOpenObjectByPointer(DesktopObject,
- 0,
- NULL,
- 0,
- ExDesktopObjectType,
- UserMode,
- (PHANDLE)&Ret);
- if(!NT_SUCCESS(Status))
- {
- /* unable to create a handle */
- DPRINT1("Unable to create a desktop handle\n");
- return NULL;
- }
- }
-
- return Ret;
+ NTSTATUS Status;
+ HDESK Ret;
+
+ ASSERT(DesktopObject);
+
+ Status = ObFindHandleForObject(PsGetCurrentProcess(),
+ DesktopObject,
+ ExDesktopObjectType,
+ NULL,
+ (PHANDLE)&Ret);
+
+ if(!NT_SUCCESS(Status))
+ {
+ Status = ObOpenObjectByPointer(DesktopObject,
+ 0,
+ NULL,
+ 0,
+ ExDesktopObjectType,
+ UserMode,
+ (PHANDLE)&Ret);
+ if(!NT_SUCCESS(Status))
+ {
+ /* unable to create a handle */
+ DPRINT1("Unable to create a desktop handle\n");
+ return NULL;
+ }
+ }
+
+ return Ret;
}
PUSER_MESSAGE_QUEUE FASTCALL
VOID FASTCALL
IntSetFocusMessageQueue(PUSER_MESSAGE_QUEUE NewQueue)
{
+ PUSER_MESSAGE_QUEUE Old;
PDESKTOP_OBJECT pdo = IntGetActiveDesktop();
if (!pdo)
{
DPRINT("No active desktop\n");
return;
}
- pdo->ActiveMessageQueue = NewQueue;
+ if(NewQueue != NULL)
+ {
+ if(NewQueue->Desktop != NULL)
+ {
+ DPRINT("Message Queue already attached to another desktop!\n");
+ return;
+ }
+ IntReferenceMessageQueue(NewQueue);
+ InterlockedExchange((LONG*)&NewQueue->Desktop, (LONG)pdo);
+ }
+ Old = (PUSER_MESSAGE_QUEUE)InterlockedExchange((LONG*)&pdo->ActiveMessageQueue, (LONG)NewQueue);
+ if(Old != NULL)
+ {
+ InterlockedExchange((LONG*)&Old->Desktop, 0);
+ IntDereferenceMessageQueue(Old);
+ }
}
HWND FASTCALL IntGetDesktopWindow(VOID)
DPRINT("No active desktop\n");
return NULL;
}
- return pdo->DesktopWindow;
+ return pdo->DesktopWindow;
}
-/* PUBLIC FUNCTIONS ***********************************************************/
+PWINDOW_OBJECT FASTCALL UserGetDesktopWindow(VOID)
+{
+ PDESKTOP_OBJECT pdo = IntGetActiveDesktop();
+
+ if (!pdo)
+ {
+ DPRINT("No active desktop\n");
+ return NULL;
+ }
+
+ return UserGetWindowObject(pdo->DesktopWindow);
+}
-static NTSTATUS FASTCALL
-NotifyCsrss(PCSRSS_API_REQUEST Request, PCSRSS_API_REPLY Reply)
+HWND FASTCALL IntGetCurrentThreadDesktopWindow(VOID)
{
- NTSTATUS Status;
- UNICODE_STRING PortName;
- ULONG ConnectInfoLength;
- static HANDLE WindowsApiPort = NULL;
-
- RtlInitUnicodeString(&PortName, L"\\Windows\\ApiPort");
- ConnectInfoLength = 0;
- Status = ZwConnectPort(&WindowsApiPort,
- &PortName,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- &ConnectInfoLength);
- if (! NT_SUCCESS(Status))
- {
- return Status;
- }
-
- Request->Header.DataSize = sizeof(CSRSS_API_REQUEST) - LPC_MESSAGE_BASE_SIZE;
- Request->Header.MessageSize = sizeof(CSRSS_API_REQUEST);
-
- Status = ZwRequestWaitReplyPort(WindowsApiPort,
- &Request->Header,
- &Reply->Header);
- if (! NT_SUCCESS(Status) || ! NT_SUCCESS(Status = Reply->Status))
- {
- ZwClose(WindowsApiPort);
- return Status;
- }
-
-// ZwClose(WindowsApiPort);
-
- return STATUS_SUCCESS;
+ PDESKTOP_OBJECT pdo = PsGetWin32Thread()->Desktop;
+ if (NULL == pdo)
+ {
+ DPRINT1("Thread doesn't have a desktop\n");
+ return NULL;
+ }
+ return pdo->DesktopWindow;
}
+BOOL FASTCALL IntDesktopUpdatePerUserSettings(BOOL bEnable)
+{
+ if (bEnable)
+ {
+ RTL_QUERY_REGISTRY_TABLE QueryTable[2];
+ NTSTATUS Status;
+
+ RtlZeroMemory(QueryTable, sizeof(QueryTable));
+
+ QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
+ QueryTable[0].Name = L"PaintDesktopVersion";
+ QueryTable[0].EntryContext = &g_PaintDesktopVersion;
+
+ /* Query the "PaintDesktopVersion" flag in the "Control Panel\Desktop" key */
+ Status = RtlQueryRegistryValues(RTL_REGISTRY_USER,
+ L"Control Panel\\Desktop",
+ QueryTable, NULL, NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("RtlQueryRegistryValues failed for PaintDesktopVersion (%x)\n",
+ Status);
+ g_PaintDesktopVersion = FALSE;
+ return FALSE;
+ }
+
+ DPRINT("PaintDesktopVersion = %d\n", g_PaintDesktopVersion);
+
+ return TRUE;
+ }
+ else
+ {
+ g_PaintDesktopVersion = FALSE;
+ return TRUE;
+ }
+}
+
+/* PUBLIC FUNCTIONS ***********************************************************/
+
NTSTATUS FASTCALL
-IntShowDesktop(PDESKTOP_OBJECT Desktop, ULONG Width, ULONG Height)
+co_IntShowDesktop(PDESKTOP_OBJECT Desktop, ULONG Width, ULONG Height)
{
- CSRSS_API_REQUEST Request;
- CSRSS_API_REPLY Reply;
+ CSR_API_MESSAGE Request;
- Request.Type = CSRSS_SHOW_DESKTOP;
- Request.Data.ShowDesktopRequest.DesktopWindow = Desktop->DesktopWindow;
- Request.Data.ShowDesktopRequest.Width = Width;
- Request.Data.ShowDesktopRequest.Height = Height;
+ Request.Type = MAKE_CSR_API(SHOW_DESKTOP, CSR_GUI);
+ Request.Data.ShowDesktopRequest.DesktopWindow = Desktop->DesktopWindow;
+ Request.Data.ShowDesktopRequest.Width = Width;
+ Request.Data.ShowDesktopRequest.Height = Height;
- return NotifyCsrss(&Request, &Reply);
+ return co_CsrNotify(&Request);
}
NTSTATUS FASTCALL
IntHideDesktop(PDESKTOP_OBJECT Desktop)
{
#if 0
- CSRSS_API_REQUEST Request;
- CSRSS_API_REPLY Reply;
+ CSRSS_API_REQUEST Request;
+ CSRSS_API_REPLY Reply;
- Request.Type = CSRSS_HIDE_DESKTOP;
- Request.Data.HideDesktopRequest.DesktopWindow = Desktop->DesktopWindow;
+ Request.Type = CSRSS_HIDE_DESKTOP;
+ Request.Data.HideDesktopRequest.DesktopWindow = Desktop->DesktopWindow;
- return NotifyCsrss(&Request, &Reply);
+ return NotifyCsrss(&Request, &Reply);
#else
- PWINDOW_OBJECT DesktopWindow;
- DesktopWindow = IntGetWindowObject(Desktop->DesktopWindow);
- if (! DesktopWindow)
- {
+ PWINDOW_OBJECT DesktopWindow;
+
+ DesktopWindow = IntGetWindowObject(Desktop->DesktopWindow);
+ if (! DesktopWindow)
+ {
return ERROR_INVALID_WINDOW_HANDLE;
- }
- DesktopWindow->Style &= ~WS_VISIBLE;
+ }
+ DesktopWindow->Style &= ~WS_VISIBLE;
+
+ return STATUS_SUCCESS;
+#endif
+}
+
- return STATUS_SUCCESS;
+
+
+static
+HWND* FASTCALL
+UserBuildShellHookHwndList(PDESKTOP_OBJECT Desktop)
+{
+ ULONG entries=0;
+ PSHELL_HOOK_WINDOW Current;
+ HWND* list;
+
+ /* fixme: if we save nb elements in desktop, we dont have to loop to find nb entries */
+ LIST_FOR_EACH(Current, &Desktop->ShellHookWindows, SHELL_HOOK_WINDOW, ListEntry)
+ entries++;
+
+ if (!entries) return NULL;
+
+ list = ExAllocatePool(PagedPool, sizeof(HWND) * (entries + 1)); /* alloc one extra for nullterm */
+ if (list)
+ {
+ HWND* cursor = list;
+
+ LIST_FOR_EACH(Current, &Desktop->ShellHookWindows, SHELL_HOOK_WINDOW, ListEntry)
+ *cursor++ = Current->hWnd;
+
+ *cursor = NULL; /* nullterm list */
+ }
+
+ return list;
+}
+
+/*
+ * Send the Message to the windows registered for ShellHook
+ * notifications. The lParam contents depend on the Message. See
+ * MSDN for more details (RegisterShellHookWindow)
+ */
+VOID co_IntShellHookNotify(WPARAM Message, LPARAM lParam)
+{
+ PDESKTOP_OBJECT Desktop = IntGetActiveDesktop();
+ HWND* HwndList;
+
+ static UINT MsgType = 0;
+
+ if (!MsgType)
+ {
+
+ /* Too bad, this doesn't work.*/
+#if 0
+ UNICODE_STRING Str;
+ RtlInitUnicodeString(&Str, L"SHELLHOOK");
+ MsgType = UserRegisterWindowMessage(&Str);
#endif
+
+ MsgType = IntAddAtom(L"SHELLHOOK");
+
+ DPRINT("MsgType = %x\n", MsgType);
+ if (!MsgType)
+ DPRINT1("LastError: %x\n", GetLastNtError());
+ }
+
+ if (!Desktop)
+ {
+ DPRINT1("IntShellHookNotify: No desktop!\n");
+ return;
+ }
+
+ HwndList = UserBuildShellHookHwndList(Desktop);
+ if (HwndList)
+ {
+ HWND* cursor = HwndList;
+
+ for (; *cursor; cursor++)
+ {
+ DPRINT("Sending notify\n");
+ co_IntPostOrSendMessage(*cursor,
+ MsgType,
+ Message,
+ lParam);
+ }
+
+ ExFreePool(HwndList);
+ }
+
}
+/*
+ * Add the window to the ShellHookWindows list. The windows
+ * on that list get notifications that are important to shell
+ * type applications.
+ *
+ * TODO: Validate the window? I'm not sure if sending these messages to
+ * an unsuspecting application that is not your own is a nice thing to do.
+ */
+BOOL IntRegisterShellHookWindow(HWND hWnd)
+{
+ PDESKTOP_OBJECT Desktop = PsGetWin32Thread()->Desktop;
+ PSHELL_HOOK_WINDOW Entry;
+
+ DPRINT("IntRegisterShellHookWindow\n");
+
+ /* First deregister the window, so we can be sure it's never twice in the
+ * list.
+ */
+ IntDeRegisterShellHookWindow(hWnd);
+
+ Entry = ExAllocatePoolWithTag(PagedPool,
+ sizeof(SHELL_HOOK_WINDOW),
+ TAG_WINSTA);
+
+ if (!Entry)
+ return FALSE;
+
+ Entry->hWnd = hWnd;
+
+ InsertTailList(&Desktop->ShellHookWindows, &Entry->ListEntry);
+
+ return TRUE;
+}
+
+/*
+ * Remove the window from the ShellHookWindows list. The windows
+ * on that list get notifications that are important to shell
+ * type applications.
+ */
+BOOL IntDeRegisterShellHookWindow(HWND hWnd)
+{
+ PDESKTOP_OBJECT Desktop = PsGetWin32Thread()->Desktop;
+ PSHELL_HOOK_WINDOW Current;
+
+ LIST_FOR_EACH(Current, &Desktop->ShellHookWindows, SHELL_HOOK_WINDOW, ListEntry)
+ {
+ if (Current->hWnd == hWnd)
+ {
+ RemoveEntryList(&Current->ListEntry);
+ ExFreePool(Current);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+
+
+/* SYSCALLS *******************************************************************/
+
+
/*
* NtUserCreateDesktop
*
LPSECURITY_ATTRIBUTES lpSecurity,
HWINSTA hWindowStation)
{
- OBJECT_ATTRIBUTES ObjectAttributes;
- PWINSTATION_OBJECT WinStaObject;
- PDESKTOP_OBJECT DesktopObject;
- UNICODE_STRING DesktopName;
- NTSTATUS Status;
- HDESK Desktop;
- CSRSS_API_REQUEST Request;
- CSRSS_API_REPLY Reply;
-
- Status = IntValidateWindowStationHandle(
- hWindowStation,
- KernelMode,
- 0,
- &WinStaObject);
-
- if (! NT_SUCCESS(Status))
- {
- DPRINT1("Failed validation of window station handle (0x%X)\n",
- hWindowStation);
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ PWINSTATION_OBJECT WinStaObject;
+ PDESKTOP_OBJECT DesktopObject;
+ UNICODE_STRING DesktopName;
+ NTSTATUS Status;
+ HDESK Desktop;
+ CSR_API_MESSAGE Request;
+ DECLARE_RETURN(HDESK);
+
+ DPRINT("Enter NtUserCreateDesktop: %wZ\n", lpszDesktopName);
+ UserEnterExclusive();
+
+ Status = IntValidateWindowStationHandle(
+ hWindowStation,
+ KernelMode,
+ 0, /* FIXME - WINSTA_CREATEDESKTOP */
+ &WinStaObject);
+
+ if (! NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed validation of window station handle (0x%X), cannot create desktop %wZ\n",
+ hWindowStation, lpszDesktopName);
SetLastNtError(Status);
- return NULL;
- }
-
- if (! IntGetFullWindowStationName(&DesktopName, &WinStaObject->Name,
- lpszDesktopName))
- {
+ RETURN( NULL);
+ }
+
+ if (! IntGetFullWindowStationName(&DesktopName, &WinStaObject->Name,
+ lpszDesktopName))
+ {
SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
ObDereferenceObject(WinStaObject);
- return NULL;
- }
-
- ObDereferenceObject(WinStaObject);
-
- /*
- * Try to open already existing desktop
- */
-
- DPRINT("Trying to open desktop (%wZ)\n", &DesktopName);
-
- /* Initialize ObjectAttributes for the desktop object */
- InitializeObjectAttributes(
- &ObjectAttributes,
- &DesktopName,
- 0,
- NULL,
- NULL);
-
- Status = ObOpenObjectByName(
- &ObjectAttributes,
- ExDesktopObjectType,
- NULL,
- UserMode,
- dwDesiredAccess,
- NULL,
- (HANDLE*)&Desktop);
-
- if (NT_SUCCESS(Status))
- {
+ RETURN( NULL);
+ }
+
+ ObDereferenceObject(WinStaObject);
+
+ /*
+ * Try to open already existing desktop
+ */
+
+ DPRINT1("Trying to open desktop (%wZ)\n", &DesktopName);
+
+ /* Initialize ObjectAttributes for the desktop object */
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &DesktopName,
+ 0,
+ NULL,
+ NULL);
+
+ Status = ObOpenObjectByName(
+ &ObjectAttributes,
+ ExDesktopObjectType,
+ NULL,
+ KernelMode,
+ dwDesiredAccess,
+ NULL,
+ (HANDLE*)&Desktop);
+
+ if (NT_SUCCESS(Status))
+ {
DPRINT("Successfully opened desktop (%wZ)\n", &DesktopName);
ExFreePool(DesktopName.Buffer);
- return Desktop;
- }
-
- /*
- * No existing desktop found, try to create new one
- */
-
- Status = ObCreateObject(
- ExGetPreviousMode(),
- ExDesktopObjectType,
- &ObjectAttributes,
- ExGetPreviousMode(),
- NULL,
- sizeof(DESKTOP_OBJECT),
- 0,
- 0,
- (PVOID*)&DesktopObject);
-
- if (! NT_SUCCESS(Status))
- {
+ RETURN( Desktop);
+ }
+
+ /*
+ * No existing desktop found, try to create new one
+ */
+
+ Status = ObCreateObject(
+ KernelMode,
+ ExDesktopObjectType,
+ &ObjectAttributes,
+ ExGetPreviousMode(),
+ NULL,
+ sizeof(DESKTOP_OBJECT),
+ 0,
+ 0,
+ (PVOID*)&DesktopObject);
+
+ if (! NT_SUCCESS(Status))
+ {
DPRINT1("Failed creating desktop (%wZ)\n", &DesktopName);
ExFreePool(DesktopName.Buffer);
SetLastNtError(STATUS_UNSUCCESSFUL);
- return NULL;
- }
-
- // init desktop area
- DesktopObject->WorkArea.left = 0;
- DesktopObject->WorkArea.top = 0;
- DesktopObject->WorkArea.right = -1;
- DesktopObject->WorkArea.bottom = -1;
- IntGetDesktopWorkArea(DesktopObject);
-
- /* Initialize some local (to win32k) desktop state. */
- DesktopObject->ActiveMessageQueue = NULL;
-
- Status = ObInsertObject(
- (PVOID)DesktopObject,
- NULL,
- STANDARD_RIGHTS_REQUIRED,
- 0,
- NULL,
- (HANDLE*)&Desktop);
-
- ObDereferenceObject(DesktopObject);
- ExFreePool(DesktopName.Buffer);
-
- if (! NT_SUCCESS(Status))
- {
+ RETURN( NULL);
+ }
+
+ // init desktop area
+ DesktopObject->WorkArea.left = 0;
+ DesktopObject->WorkArea.top = 0;
+ DesktopObject->WorkArea.right = -1;
+ DesktopObject->WorkArea.bottom = -1;
+ IntGetDesktopWorkArea(DesktopObject, NULL);
+
+ /* Initialize some local (to win32k) desktop state. */
+ DesktopObject->ActiveMessageQueue = NULL;
+
+ Status = ObInsertObject(
+ (PVOID)DesktopObject,
+ NULL,
+ STANDARD_RIGHTS_REQUIRED,
+ 0,
+ NULL,
+ (HANDLE*)&Desktop);
+
+ ObDereferenceObject(DesktopObject);
+ ExFreePool(DesktopName.Buffer);
+
+ if (! NT_SUCCESS(Status))
+ {
DPRINT1("Failed to create desktop handle\n");
SetLastNtError(Status);
- return NULL;
- }
+ RETURN( NULL);
+ }
- Request.Type = CSRSS_CREATE_DESKTOP;
- memcpy(Request.Data.CreateDesktopRequest.DesktopName, lpszDesktopName->Buffer,
- lpszDesktopName->Length);
- Request.Data.CreateDesktopRequest.DesktopName[lpszDesktopName->Length / sizeof(WCHAR)] = L'\0';
+ /*
+ * Create a handle for CSRSS and notify CSRSS
+ */
+ Request.Type = MAKE_CSR_API(CREATE_DESKTOP, CSR_GUI);
+ Status = CsrInsertObject(Desktop,
+ GENERIC_ALL,
+ (HANDLE*)&Request.Data.CreateDesktopRequest.DesktopHandle);
+ if (! NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to create desktop handle for CSRSS\n");
+ ZwClose(Desktop);
+ SetLastNtError(Status);
+ RETURN( NULL);
+ }
- Status = NotifyCsrss(&Request, &Reply);
- if (! NT_SUCCESS(Status))
- {
+ Status = co_CsrNotify(&Request);
+ if (! NT_SUCCESS(Status))
+ {
+ CsrCloseHandle(Request.Data.CreateDesktopRequest.DesktopHandle);
DPRINT1("Failed to notify CSRSS about new desktop\n");
ZwClose(Desktop);
SetLastNtError(Status);
- return NULL;
- }
+ RETURN( NULL);
+ }
- return Desktop;
+ RETURN( Desktop);
+
+CLEANUP:
+ DPRINT("Leave NtUserCreateDesktop, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
}
/*
UNICODE_STRING DesktopName;
NTSTATUS Status;
HDESK Desktop;
+ DECLARE_RETURN(HDESK);
+
+ DPRINT("Enter NtUserOpenDesktop: %wZ\n", lpszDesktopName);
+ UserEnterExclusive();
/*
* Validate the window station handle and compose the fully
*/
Status = IntValidateWindowStationHandle(
- PROCESS_WINDOW_STATION(),
- KernelMode,
- 0,
- &WinStaObject);
+ PsGetCurrentProcess()->Win32WindowStation,
+ KernelMode,
+ 0,
+ &WinStaObject);
if (!NT_SUCCESS(Status))
{
- DPRINT("Failed validation of window station handle (0x%X)\n",
- PROCESS_WINDOW_STATION());
+ DPRINT1("Failed validation of window station handle (0x%X)\n",
+ PsGetCurrentProcess()->Win32WindowStation);
SetLastNtError(Status);
- return 0;
+ RETURN( 0);
}
if (!IntGetFullWindowStationName(&DesktopName, &WinStaObject->Name,
- lpszDesktopName))
+ lpszDesktopName))
{
SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
ObDereferenceObject(WinStaObject);
- return 0;
+ RETURN( 0);
}
-
+
ObDereferenceObject(WinStaObject);
- DPRINT("Trying to open desktop station (%wZ)\n", &DesktopName);
+ DPRINT1("Trying to open desktop (%wZ)\n", &DesktopName);
/* Initialize ObjectAttributes for the desktop object */
InitializeObjectAttributes(
NULL);
Status = ObOpenObjectByName(
- &ObjectAttributes,
- ExDesktopObjectType,
- NULL,
- UserMode,
- dwDesiredAccess,
- NULL,
- (HANDLE*)&Desktop);
+ &ObjectAttributes,
+ ExDesktopObjectType,
+ NULL,
+ UserMode,
+ dwDesiredAccess,
+ NULL,
+ (HANDLE*)&Desktop);
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
ExFreePool(DesktopName.Buffer);
- return 0;
+ RETURN( 0);
}
DPRINT("Successfully opened desktop (%wZ)\n", &DesktopName);
ExFreePool(DesktopName.Buffer);
- return Desktop;
+ RETURN( Desktop);
+
+CLEANUP:
+ DPRINT("Leave NtUserOpenDesktop, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
}
/*
*
* dwDesiredAccess
* Requested type of access.
- *
+ *
* Return Value
* Handle to the input desktop or zero on failure.
*
PDESKTOP_OBJECT Object;
NTSTATUS Status;
HDESK Desktop;
+ DECLARE_RETURN(HDESK);
+
+ DPRINT("Enter NtUserOpenInputDesktop\n");
+ UserEnterExclusive();
DPRINT("About to open input desktop\n");
/* Get a pointer to the desktop object */
Status = IntValidateDesktopHandle(
- InputDesktopHandle,
- UserMode,
- 0,
- &Object);
+ InputDesktopHandle,
+ UserMode,
+ 0,
+ &Object);
if (!NT_SUCCESS(Status))
{
DPRINT("Validation of input desktop handle (0x%X) failed\n", InputDesktop);
- return (HDESK)0;
+ RETURN((HDESK)0);
}
/* Create a new handle to the object */
Status = ObOpenObjectByPointer(
- Object,
- 0,
- NULL,
- dwDesiredAccess,
- ExDesktopObjectType,
- UserMode,
- (HANDLE*)&Desktop);
+ Object,
+ 0,
+ NULL,
+ dwDesiredAccess,
+ ExDesktopObjectType,
+ UserMode,
+ (HANDLE*)&Desktop);
ObDereferenceObject(Object);
if (NT_SUCCESS(Status))
{
DPRINT("Successfully opened input desktop\n");
- return (HDESK)Desktop;
+ RETURN((HDESK)Desktop);
}
SetLastNtError(Status);
- return (HDESK)0;
+ RETURN((HDESK)0);
+
+CLEANUP:
+ DPRINT("Leave NtUserOpenInputDesktop, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
}
/*
{
PDESKTOP_OBJECT Object;
NTSTATUS Status;
+ DECLARE_RETURN(BOOL);
+
+ DPRINT("Enter NtUserCloseDesktop\n");
+ UserEnterExclusive();
DPRINT("About to close desktop handle (0x%X)\n", hDesktop);
Status = IntValidateDesktopHandle(
- hDesktop,
- UserMode,
- 0,
- &Object);
+ hDesktop,
+ UserMode,
+ 0,
+ &Object);
if (!NT_SUCCESS(Status))
{
DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop);
- return FALSE;
+ RETURN(FALSE);
}
ObDereferenceObject(Object);
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
- return FALSE;
+ RETURN(FALSE);
}
- return TRUE;
+ RETURN(TRUE);
+
+CLEANUP:
+ DPRINT("Leave NtUserCloseDesktop, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
}
+
+
+
/*
* NtUserPaintDesktop
*
* function is provided primarily for shell desktops.
*
* Parameters
- * hdc
- * Handle to the device context.
+ * hDC
+ * Handle to the device context.
*
* Status
* @implemented
BOOL STDCALL
NtUserPaintDesktop(HDC hDC)
{
- RECT Rect;
- HBRUSH DesktopBrush, PreviousBrush;
- HWND hWndDesktop;
+ RECT Rect;
+ HBRUSH DesktopBrush, PreviousBrush;
+ HWND hWndDesktop;
+ BOOL doPatBlt = TRUE;
+ PWINDOW_OBJECT WndDesktop;
+ int len;
+ DECLARE_RETURN(BOOL);
+
+ UserEnterExclusive();
+ DPRINT("Enter NtUserPaintDesktop\n");
- IntGdiGetClipBox(hDC, &Rect);
+ PWINSTATION_OBJECT WinSta = PsGetWin32Thread()->Desktop->WindowStation;
- hWndDesktop = IntGetDesktopWindow();
- DesktopBrush = (HBRUSH)NtUserGetClassLong(hWndDesktop, GCL_HBRBACKGROUND, FALSE);
+ IntGdiGetClipBox(hDC, &Rect);
- /*
- * Paint desktop background
- */
+ hWndDesktop = IntGetDesktopWindow();
+ if (!(WndDesktop = UserGetWindowObject(hWndDesktop)))
+ RETURN(FALSE);
- PreviousBrush = NtGdiSelectObject(hDC, DesktopBrush);
- NtGdiPatBlt(hDC, Rect.left, Rect.top, Rect.right, Rect.bottom, PATCOPY);
- NtGdiSelectObject(hDC, PreviousBrush);
+ DesktopBrush = (HBRUSH)IntGetClassLong(WndDesktop, GCL_HBRBACKGROUND, FALSE); //fixme: verify retval
- return TRUE;
+
+ /*
+ * Paint desktop background
+ */
+
+ if(WinSta->hbmWallpaper != NULL)
+ {
+ PWINDOW_OBJECT DeskWin;
+
+ if((DeskWin = UserGetWindowObject(hWndDesktop)))
+ {
+ SIZE sz;
+ int x, y;
+ HDC hWallpaperDC;
+
+ sz.cx = DeskWin->WindowRect.right - DeskWin->WindowRect.left;
+ sz.cy = DeskWin->WindowRect.bottom - DeskWin->WindowRect.top;
+
+
+ x = (sz.cx / 2) - (WinSta->cxWallpaper / 2);
+ y = (sz.cy / 2) - (WinSta->cyWallpaper / 2);
+
+ hWallpaperDC = NtGdiCreateCompatibleDC(hDC);
+ if(hWallpaperDC != NULL)
+ {
+ HBITMAP hOldBitmap;
+
+ if(x > 0 || y > 0)
+ {
+ /* FIXME - clip out the bitmap */
+ PreviousBrush = NtGdiSelectObject(hDC, DesktopBrush);
+ NtGdiPatBlt(hDC, Rect.left, Rect.top, Rect.right, Rect.bottom, PATCOPY);
+ NtGdiSelectObject(hDC, PreviousBrush);
+ }
+ else
+ doPatBlt = FALSE;
+
+ hOldBitmap = NtGdiSelectObject(hWallpaperDC, WinSta->hbmWallpaper);
+ NtGdiBitBlt(hDC, x, y, WinSta->cxWallpaper, WinSta->cyWallpaper, hWallpaperDC, 0, 0, SRCCOPY);
+ NtGdiSelectObject(hWallpaperDC, hOldBitmap);
+
+ NtGdiDeleteDC(hWallpaperDC);
+ }
+ }
+ }
+
+ if (doPatBlt)
+ {
+ PreviousBrush = NtGdiSelectObject(hDC, DesktopBrush);
+ NtGdiPatBlt(hDC, Rect.left, Rect.top, Rect.right, Rect.bottom, PATCOPY);
+ NtGdiSelectObject(hDC, PreviousBrush);
+ }
+
+ /*
+ * Display system version on the desktop background
+ */
+
+ if (g_PaintDesktopVersion)
+ {
+ static WCHAR s_wszVersion[256] = {0};
+ RECT rect;
+
+ if (*s_wszVersion)
+ len = wcslen(s_wszVersion);
+ else
+ len = GetSystemVersionString(s_wszVersion);
+
+ if (len)
+ {
+ if (!UserSystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0))
+ {
+ rect.right = UserGetSystemMetrics(SM_CXSCREEN);
+ rect.bottom = UserGetSystemMetrics(SM_CYSCREEN);
+ }
+
+ COLORREF color_old = NtGdiSetTextColor(hDC, RGB(255,255,255));
+ UINT align_old = NtGdiSetTextAlign(hDC, TA_RIGHT);
+ int mode_old = NtGdiSetBkMode(hDC, TRANSPARENT);
+
+ NtGdiTextOut(hDC, rect.right-16, rect.bottom-48, s_wszVersion, len);
+
+ NtGdiSetBkMode(hDC, mode_old);
+ NtGdiSetTextAlign(hDC, align_old);
+ NtGdiSetTextColor(hDC, color_old);
+ }
+ }
+
+ RETURN(TRUE);
+
+CLEANUP:
+ DPRINT("Leave NtUserPaintDesktop, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
}
+
/*
* NtUserSwitchDesktop
*
{
PDESKTOP_OBJECT DesktopObject;
NTSTATUS Status;
+ DECLARE_RETURN(BOOL);
+
+ UserEnterExclusive();
+ DPRINT("Enter NtUserSwitchDesktop\n");
DPRINT("About to switch desktop (0x%X)\n", hDesktop);
Status = IntValidateDesktopHandle(
- hDesktop,
- UserMode,
- 0,
- &DesktopObject);
+ hDesktop,
+ UserMode,
+ 0,
+ &DesktopObject);
- if (!NT_SUCCESS(Status))
+ if (!NT_SUCCESS(Status))
{
DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop);
- return FALSE;
+ RETURN(FALSE);
}
-
+
/*
* Don't allow applications switch the desktop if it's locked, unless the caller
* is the logon application itself
*/
if((DesktopObject->WindowStation->Flags & WSS_LOCKED) &&
- LogonProcess != NULL && LogonProcess != PsGetWin32Process())
+ LogonProcess != NULL && LogonProcess != PsGetWin32Process())
{
ObDereferenceObject(DesktopObject);
DPRINT1("Switching desktop 0x%x denied because the work station is locked!\n", hDesktop);
- return FALSE;
+ RETURN(FALSE);
}
-
+
/* FIXME: Fail if the desktop belong to an invisible window station */
/* FIXME: Fail if the process is associated with a secured
desktop such as Winlogon or Screen-Saver */
ObDereferenceObject(DesktopObject);
- return TRUE;
+ RETURN(TRUE);
+
+CLEANUP:
+ DPRINT("Leave NtUserSwitchDesktop, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
}
/*
HDESK STDCALL
NtUserGetThreadDesktop(DWORD dwThreadId, DWORD Unknown1)
{
- NTSTATUS Status;
- PETHREAD Thread;
- PDESKTOP_OBJECT DesktopObject;
- HDESK Ret, hThreadDesktop;
- OBJECT_HANDLE_INFORMATION HandleInformation;
-
- if(!dwThreadId)
- {
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
- return 0;
- }
-
- Status = PsLookupThreadByThreadId((PVOID)dwThreadId, &Thread);
- if(!NT_SUCCESS(Status))
- {
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
- return 0;
- }
-
- if(Thread->ThreadsProcess == PsGetCurrentProcess())
- {
- /* just return the handle, we queried the desktop handle of a thread running
- in the same context */
- Ret = Thread->Win32Thread->hDesktop;
- ObDereferenceObject(Thread);
- return Ret;
- }
-
- /* get the desktop handle and the desktop of the thread */
- if(!(hThreadDesktop = Thread->Win32Thread->hDesktop) ||
- !(DesktopObject = Thread->Win32Thread->Desktop))
- {
- ObDereferenceObject(Thread);
- DPRINT1("Desktop information of thread 0x%x broken!?\n", dwThreadId);
- return NULL;
- }
-
- /* we could just use DesktopObject instead of looking up the handle, but latter
- may be a bit safer (e.g. when the desktop is being destroyed */
- /* switch into the context of the thread we're trying to get the desktop from,
- so we can use the handle */
- KeAttachProcess(Thread->ThreadsProcess);
- Status = ObReferenceObjectByHandle(hThreadDesktop,
- GENERIC_ALL,
- ExDesktopObjectType,
- UserMode,
- (PVOID*)&DesktopObject,
- &HandleInformation);
- KeDetachProcess();
-
- /* the handle couldn't be found, there's nothing to get... */
- if(!NT_SUCCESS(Status))
- {
- ObDereferenceObject(Thread);
- return NULL;
- }
-
- /* lookup our handle table if we can find a handle to the desktop object,
- if not, create one */
- Ret = IntGetDesktopObjectHandle(DesktopObject);
-
- /* all done, we got a valid handle to the desktop */
- ObDereferenceObject(DesktopObject);
- ObDereferenceObject(Thread);
- return Ret;
+ NTSTATUS Status;
+ PETHREAD Thread;
+ PDESKTOP_OBJECT DesktopObject;
+ HDESK Ret, hThreadDesktop;
+ OBJECT_HANDLE_INFORMATION HandleInformation;
+ DECLARE_RETURN(HDESK);
+
+ UserEnterExclusive();
+ DPRINT("Enter NtUserGetThreadDesktop\n");
+
+ if(!dwThreadId)
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ RETURN(0);
+ }
+
+ Status = PsLookupThreadByThreadId((HANDLE)dwThreadId, &Thread);
+ if(!NT_SUCCESS(Status))
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ RETURN(0);
+ }
+
+ if(Thread->ThreadsProcess == PsGetCurrentProcess())
+ {
+ /* just return the handle, we queried the desktop handle of a thread running
+ in the same context */
+ Ret = ((PW32THREAD)Thread->Tcb.Win32Thread)->hDesktop;
+ ObDereferenceObject(Thread);
+ RETURN(Ret);
+ }
+
+ /* get the desktop handle and the desktop of the thread */
+ if(!(hThreadDesktop = ((PW32THREAD)Thread->Tcb.Win32Thread)->hDesktop) ||
+ !(DesktopObject = ((PW32THREAD)Thread->Tcb.Win32Thread)->Desktop))
+ {
+ ObDereferenceObject(Thread);
+ DPRINT1("Desktop information of thread 0x%x broken!?\n", dwThreadId);
+ RETURN(NULL);
+ }
+
+ /* we could just use DesktopObject instead of looking up the handle, but latter
+ may be a bit safer (e.g. when the desktop is being destroyed */
+ /* switch into the context of the thread we're trying to get the desktop from,
+ so we can use the handle */
+ KeAttachProcess(&Thread->ThreadsProcess->Pcb);
+ Status = ObReferenceObjectByHandle(hThreadDesktop,
+ GENERIC_ALL,
+ ExDesktopObjectType,
+ UserMode,
+ (PVOID*)&DesktopObject,
+ &HandleInformation);
+ KeDetachProcess();
+
+ /* the handle couldn't be found, there's nothing to get... */
+ if(!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(Thread);
+ RETURN(NULL);
+ }
+
+ /* lookup our handle table if we can find a handle to the desktop object,
+ if not, create one */
+ Ret = IntGetDesktopObjectHandle(DesktopObject);
+
+ /* all done, we got a valid handle to the desktop */
+ ObDereferenceObject(DesktopObject);
+ ObDereferenceObject(Thread);
+ RETURN(Ret);
+
+CLEANUP:
+ DPRINT("Leave NtUserGetThreadDesktop, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
}
/*
PW32THREAD W32Thread;
PDESKTOP_OBJECT DesktopObject;
NTSTATUS Status;
-
+ DECLARE_RETURN(BOOL);
+
+ UserEnterExclusive();
+ DPRINT("Enter NtUserSetThreadDesktop\n");
+
/* Validate the new desktop. */
Status = IntValidateDesktopHandle(
- hDesktop,
- UserMode,
- 0,
- &DesktopObject);
+ hDesktop,
+ UserMode,
+ 0,
+ &DesktopObject);
- if (!NT_SUCCESS(Status))
+ if (!NT_SUCCESS(Status))
{
DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop);
- return FALSE;
+ RETURN(FALSE);
}
W32Thread = PsGetWin32Thread();
- /* Check for setting the same desktop as before. */
- if (DesktopObject == W32Thread->Desktop)
- {
- W32Thread->hDesktop = hDesktop;
- ObDereferenceObject(DesktopObject);
- return TRUE;
- }
/* FIXME: Should check here to see if the thread has any windows. */
W32Thread->Desktop = DesktopObject;
W32Thread->hDesktop = hDesktop;
- return TRUE;
+ RETURN(TRUE);
+
+CLEANUP:
+ DPRINT("Leave NtUserSetThreadDesktop, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
}
/* EOF */