📄 desktop.c
字号:
}
/* Back ground is set to none, clear the screen */
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);
}
color_old = NtGdiSetTextColor(hDC, RGB(255,255,255));
align_old = NtGdiSetTextAlign(hDC, TA_RIGHT);
mode_old = NtGdiSetBkMode(hDC, TRANSPARENT);
NtGdiExtTextOut(hDC, rect.right-16, rect.bottom-48, 0, NULL, s_wszVersion, len, NULL);
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
*
* Sets the current input (interactive) desktop.
*
* Parameters
* hDesktop
* Handle to desktop.
*
* Return Value
* Status
*
* Status
* @unimplemented
*/
BOOL STDCALL
NtUserSwitchDesktop(HDESK hDesktop)
{
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);
if (!NT_SUCCESS(Status))
{
DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop);
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 != PsGetCurrentProcessWin32Process())
{
ObDereferenceObject(DesktopObject);
DPRINT1("Switching desktop 0x%x denied because the work station is locked!\n", hDesktop);
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 */
/* FIXME: Connect to input device */
/* Set the active desktop in the desktop's window station. */
DesktopObject->WindowStation->ActiveDesktop = DesktopObject;
/* Set the global state. */
InputDesktop = DesktopObject;
InputDesktopHandle = hDesktop;
InputWindowStation = DesktopObject->WindowStation;
ObDereferenceObject(DesktopObject);
RETURN(TRUE);
CLEANUP:
DPRINT("Leave NtUserSwitchDesktop, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
/*
* NtUserResolveDesktopForWOW
*
* Status
* @unimplemented
*/
DWORD STDCALL
NtUserResolveDesktopForWOW(DWORD Unknown0)
{
UNIMPLEMENTED
return 0;
}
/*
* NtUserGetThreadDesktop
*
* Status
* @implemented
*/
HDESK STDCALL
NtUserGetThreadDesktop(DWORD dwThreadId, DWORD Unknown1)
{
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;
}
static NTSTATUS
IntUnmapDesktopView(IN PDESKTOP_OBJECT DesktopObject)
{
PW32THREADINFO ti;
PW32HEAP_USER_MAPPING HeapMapping, *PrevLink = &PsGetCurrentProcessWin32Process()->HeapMappings.Next;
NTSTATUS Status = STATUS_SUCCESS;
TRACE("DO %p\n");
/* unmap if we're the last thread using the desktop */
HeapMapping = *PrevLink;
while (HeapMapping != NULL)
{
if (HeapMapping->KernelMapping == (PVOID)DesktopObject->hDesktopHeap)
{
if (--HeapMapping->Count == 0)
{
*PrevLink = HeapMapping->Next;
Status = MmUnmapViewOfSection(PsGetCurrentProcess(),
HeapMapping->UserMapping);
ObDereferenceObject(DesktopObject);
UserHeapFree(HeapMapping);
break;
}
}
PrevLink = &HeapMapping->Next;
HeapMapping = HeapMapping->Next;
}
ti = GetW32ThreadInfo();
if (ti != NULL)
{
if (ti->Desktop == DesktopObject->DesktopInfo)
{
ti->Desktop = NULL;
ti->DesktopHeapDelta = 0;
}
}
return Status;
}
static NTSTATUS
IntMapDesktopView(IN PDESKTOP_OBJECT DesktopObject)
{
PW32THREADINFO ti;
PW32HEAP_USER_MAPPING HeapMapping, *PrevLink = &PsGetCurrentProcessWin32Process()->HeapMappings.Next;
PVOID UserBase = NULL;
ULONG ViewSize = 0;
LARGE_INTEGER Offset;
NTSTATUS Status;
/* find out if another thread already mapped the desktop heap */
HeapMapping = *PrevLink;
while (HeapMapping != NULL)
{
if (HeapMapping->KernelMapping == (PVOID)DesktopObject->hDesktopHeap)
{
HeapMapping->Count++;
return STATUS_SUCCESS;
}
PrevLink = &HeapMapping->Next;
HeapMapping = HeapMapping->Next;
}
/* we're the first, map the heap */
DPRINT("Noone mapped the desktop heap %p yet, so - map it!\n", DesktopObject->hDesktopHeap);
Offset.QuadPart = 0;
Status = MmMapViewOfSection(DesktopObject->DesktopHeapSection,
PsGetCurrentProcess(),
&UserBase,
0,
0,
&Offset,
&ViewSize,
ViewUnmap,
SEC_NO_CHANGE,
PAGE_EXECUTE_READ); /* would prefer PAGE_READONLY, but thanks to RTL heaps... */
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to map desktop\n");
return Status;
}
/* add the mapping */
HeapMapping = UserHeapAlloc(sizeof(W32HEAP_USER_MAPPING));
if (HeapMapping == NULL)
{
MmUnmapViewOfSection(PsGetCurrentProcess(),
UserBase);
DPRINT1("UserHeapAlloc() failed!\n");
return STATUS_NO_MEMORY;
}
HeapMapping->Next = NULL;
HeapMapping->KernelMapping = (PVOID)DesktopObject->hDesktopHeap;
HeapMapping->UserMapping = UserBase;
HeapMapping->Count = 1;
*PrevLink = HeapMapping;
ObReferenceObject(DesktopObject);
/* create a W32THREADINFO structure if not already done, or update it */
ti = GetW32ThreadInfo();
if (ti != NULL)
{
if (ti->Desktop == NULL)
{
ti->Desktop = DesktopObject->DesktopInfo;
ti->DesktopHeapDelta = DesktopHeapGetUserDelta();
}
}
return STATUS_SUCCESS;
}
BOOL
IntSetThreadDesktop(IN PDESKTOP_OBJECT DesktopObject,
IN BOOL FreeOnFailure)
{
PDESKTOP_OBJECT OldDesktop;
PW32THREAD W32Thread;
NTSTATUS Status;
BOOL MapHeap;
DPRINT("IntSetThreadDesktop() DO=%p, FOF=%d\n", DesktopObject, FreeOnFailure);
MapHeap = (PsGetCurrentProcess() != PsInitialSystemProcess);
W32Thread = PsGetCurrentThreadWin32Thread();
if (W32Thread->Desktop != DesktopObject)
{
OldDesktop = W32Thread->Desktop;
if (!IsListEmpty(&W32Thread->WindowListHead))
{
DPRINT1("Attempted to change thread desktop although the thread has windows!\n");
SetLastWin32Error(ERROR_BUSY);
return FALSE;
}
W32Thread->Desktop = DesktopObject;
if (MapHeap && DesktopObject != NULL)
{
Status = IntMapDesktopView(DesktopObject);
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
return FALSE;
}
}
if (OldDesktop != NULL &&
!IntCheckProcessDesktopClasses(OldDesktop->DesktopInfo,
FreeOnFailure))
{
DPRINT1("Failed to move process classes to shared heap!\n");
/* failed to move desktop classes to the shared heap,
unmap the view and return the error */
if (MapHeap && DesktopObject != NULL)
IntUnmapDesktopView(DesktopObject);
return FALSE;
}
if (DesktopObject != NULL)
{
ObReferenceObject(DesktopObject);
}
if (OldDesktop != NULL)
{
if (MapHeap)
{
IntUnmapDesktopView(OldDesktop);
}
ObDereferenceObject(OldDesktop);
/* update the thread info */
if (W32Thread != NULL && W32Thread->ThreadInfo != NULL &&
W32Thread->ThreadInfo->Desktop != (DesktopObject != NULL ? DesktopObject->DesktopInfo : NULL))
{
if (DesktopObject != NULL)
{
W32Thread->ThreadInfo->Desktop = DesktopObject->DesktopInfo;
W32Thread->ThreadInfo->DesktopHeapDelta = DesktopHeapGetUserDelta();
}
else
{
W32Thread->ThreadInfo->Desktop = NULL;
W32Thread->ThreadInfo->DesktopHeapDelta = 0;
}
}
}
}
return TRUE;
}
/*
* NtUserSetThreadDesktop
*
* Status
* @implemented
*/
BOOL STDCALL
NtUserSetThreadDesktop(HDESK hDesktop)
{
PDESKTOP_OBJECT DesktopObject;
NTSTATUS Status;
DECLARE_RETURN(BOOL);
UserEnterExclusive();
DPRINT("Enter NtUserSetThreadDesktop\n");
/* Validate the new desktop. */
Status = IntValidateDesktopHandle(
hDesktop,
UserMode,
0,
&DesktopObject);
if (!NT_SUCCESS(Status))
{
DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop);
RETURN(FALSE);
}
/* FIXME: Should check here to see if the thread has any windows. */
if (!IntSetThreadDesktop(DesktopObject,
FALSE))
{
RETURN(FALSE);
}
RETURN(TRUE);
CLEANUP:
DPRINT("Leave NtUserSetThreadDesktop, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
/* EOF */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -