📄 desktop.c
字号:
NULL,
(PHANDLE)&Ret))
{
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;
}
}
else
{
DPRINT1("Got handle: %lx\n", Ret);
}
return Ret;
}
PUSER_MESSAGE_QUEUE FASTCALL
IntGetFocusMessageQueue(VOID)
{
PDESKTOP_OBJECT pdo = IntGetActiveDesktop();
if (!pdo)
{
DPRINT("No active desktop\n");
return(NULL);
}
return (PUSER_MESSAGE_QUEUE)pdo->ActiveMessageQueue;
}
VOID FASTCALL
IntSetFocusMessageQueue(PUSER_MESSAGE_QUEUE NewQueue)
{
PUSER_MESSAGE_QUEUE Old;
PDESKTOP_OBJECT pdo = IntGetActiveDesktop();
if (!pdo)
{
DPRINT("No active desktop\n");
return;
}
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)
{
PDESKTOP_OBJECT pdo = IntGetActiveDesktop();
if (!pdo)
{
DPRINT("No active desktop\n");
return NULL;
}
return pdo->DesktopWindow;
}
PWINDOW_OBJECT FASTCALL UserGetDesktopWindow(VOID)
{
PDESKTOP_OBJECT pdo = IntGetActiveDesktop();
if (!pdo)
{
DPRINT("No active desktop\n");
return NULL;
}
return UserGetWindowObject(pdo->DesktopWindow);
}
HWND FASTCALL IntGetCurrentThreadDesktopWindow(VOID)
{
PDESKTOP_OBJECT pdo = PsGetCurrentThreadWin32Thread()->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
co_IntShowDesktop(PDESKTOP_OBJECT Desktop, ULONG Width, ULONG Height)
{
CSR_API_MESSAGE Request;
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 co_CsrNotify(&Request);
}
NTSTATUS FASTCALL
IntHideDesktop(PDESKTOP_OBJECT Desktop)
{
#if 0
CSRSS_API_REQUEST Request;
CSRSS_API_REPLY Reply;
Request.Type = CSRSS_HIDE_DESKTOP;
Request.Data.HideDesktopRequest.DesktopWindow = Desktop->DesktopWindow;
return NotifyCsrss(&Request, &Reply);
#else
PWINDOW_OBJECT DesktopWindow;
DesktopWindow = IntGetWindowObject(Desktop->DesktopWindow);
if (! DesktopWindow)
{
return ERROR_INVALID_WINDOW_HANDLE;
}
DesktopWindow->Style &= ~WS_VISIBLE;
return STATUS_SUCCESS;
#endif
}
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)
{
DPRINT("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 = PsGetCurrentThreadWin32Thread()->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 = PsGetCurrentThreadWin32Thread()->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;
}
static VOID
IntFreeDesktopHeap(IN OUT PDESKTOP_OBJECT Desktop)
{
if (Desktop->DesktopHeapSection != NULL)
{
ObDereferenceObject(Desktop->DesktopHeapSection);
Desktop->DesktopHeapSection = NULL;
}
}
/* SYSCALLS *******************************************************************/
/*
* NtUserCreateDesktop
*
* Creates a new desktop.
*
* Parameters
* lpszDesktopName
* Name of the new desktop.
*
* dwFlags
* Interaction flags.
*
* dwDesiredAccess
* Requested type of access.
*
* lpSecurity
* Security descriptor.
*
* hWindowStation
* Handle to window station on which to create the desktop.
*
* Return Value
* If the function succeeds, the return value is a handle to the newly
* created desktop. If the specified desktop already exists, the function
* succeeds and returns a handle to the existing desktop. When you are
* finished using the handle, call the CloseDesktop function to close it.
* If the function fails, the return value is NULL.
*
* Status
* @implemented
*/
HDESK STDCALL
NtUserCreateDesktop(
PUNICODE_STRING lpszDesktopName,
DWORD dwFlags,
ACCESS_MASK dwDesiredAccess,
LPSECURITY_ATTRIBUTES lpSecurity,
HWINSTA hWindowStation)
{
OBJECT_ATTRIBUTES ObjectAttributes;
PWINSTATION_OBJECT WinStaObject;
PDESKTOP_OBJECT DesktopObject;
UNICODE_STRING DesktopName;
NTSTATUS Status;
HDESK Desktop;
CSR_API_MESSAGE Request;
PVOID DesktopHeapSystemBase = NULL;
SIZE_T DesktopInfoSize;
UNICODE_STRING SafeDesktopName;
ULONG DummyContext;
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(lpszDesktopName != NULL)
{
Status = IntSafeCopyUnicodeString(&SafeDesktopName, lpszDesktopName);
if(!NT_SUCCESS(Status))
{
SetLastNtError(Status);
RETURN( NULL);
}
}
else
{
RtlInitUnicodeString(&SafeDesktopName, NULL);
}
if (! IntGetFullWindowStationName(&DesktopName, &WinStaObject->Name,
&SafeDesktopName))
{
SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
ObDereferenceObject(WinStaObject);
RtlFreeUnicodeString(&SafeDesktopName);
RETURN( NULL);
}
RtlFreeUnicodeString(&SafeDesktopName);
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,
KernelMode,
NULL,
dwDesiredAccess,
(PVOID)&DummyContext,
(HANDLE*)&Desktop);
if (!NT_SUCCESS(Status)) RETURN(NULL);
if (Status == STATUS_OBJECT_NAME_EXISTS)
{
ExFreePool(DesktopName.Buffer);
RETURN( Desktop);
}
/* Reference the desktop */
Status = ObReferenceObjectByHandle(Desktop,
0,
ExDesktopObjectType,
KernelMode,
(PVOID)&DesktopObject,
NULL);
if (!NT_SUCCESS(Status)) RETURN(NULL);
DesktopObject->DesktopHeapSection = NULL;
DesktopObject->hDesktopHeap = UserCreateHeap(&DesktopObject->DesktopHeapSection,
&DesktopHeapSystemBase,
4 * 1024 * 1024); /* FIXME */
if (DesktopObject->hDesktopHeap == NULL)
{
ObDereferenceObject(DesktopObject);
DPRINT1("Failed to create desktop heap!\n");
RETURN(NULL);
}
DesktopInfoSize = FIELD_OFFSET(DESKTOP,
szDesktopName[(lpszDesktopName->Length / sizeof(WCHAR)) + 1]);
DesktopObject->DesktopInfo = RtlAllocateHeap(DesktopObject->hDesktopHeap,
HEAP_NO_SERIALIZE,
DesktopInfoSize);
if (DesktopObject->DesktopInfo == NULL)
{
ObDereferenceObject(DesktopObject);
DPRINT1("Failed to create the DESKTOP structure!\n");
RETURN(NULL);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -