desktop.c
来自「一个类似windows」· C语言 代码 · 共 1,890 行 · 第 1/4 页
C
1,890 行
/*
* ReactOS W32 Subsystem
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: desktop.c 21596 2006-04-15 10:41:58Z greatlrd $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PURPOSE: Desktops
* FILE: subsys/win32k/ntuser/desktop.c
* PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISION HISTORY:
* 06-06-2001 CSH Created
*/
/* INCLUDES ******************************************************************/
#include <w32k.h>
#define NDEBUG
#include <debug.h>
/* GLOBALS *******************************************************************/
/* Currently active desktop */
PDESKTOP_OBJECT InputDesktop = NULL;
HDESK InputDesktopHandle = NULL;
HDC ScreenDeviceContext = NULL;
BOOL g_PaintDesktopVersion = FALSE;
static VOID IntFreeDesktopHeap(IN OUT PDESKTOP_OBJECT Desktop);
/* 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)
{
/* Set Desktop Object Attributes */
ExDesktopObjectType->TypeInfo.DefaultNonPagedPoolCharge = sizeof(DESKTOP_OBJECT);
ExDesktopObjectType->TypeInfo.GenericMapping = IntDesktopMapping;
return STATUS_SUCCESS;
}
NTSTATUS FASTCALL
CleanupDesktopImpl(VOID)
{
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);
IntFreeDesktopHeap(Desktop);
}
/* 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
*
* Validates the desktop handle.
*
* Remarks
* If the function succeeds, the handle remains referenced. If the
* fucntion fails, last error is set.
*/
NTSTATUS FASTCALL
IntValidateDesktopHandle(
HDESK Desktop,
KPROCESSOR_MODE AccessMode,
ACCESS_MASK DesiredAccess,
PDESKTOP_OBJECT *Object)
{
NTSTATUS Status;
Status = ObReferenceObjectByHandle(
Desktop,
DesiredAccess,
ExDesktopObjectType,
AccessMode,
(PVOID*)Object,
NULL);
if (!NT_SUCCESS(Status))
SetLastNtError(Status);
return Status;
}
VOID FASTCALL
IntGetDesktopWorkArea(PDESKTOP_OBJECT Desktop, PRECT Rect)
{
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;
}
/*
* returns or creates a handle to the desktop object
*/
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;
}
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);
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?