📄 dc.c
字号:
/*
* 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: dc.c 28434 2007-08-20 19:50:07Z cfinck $
*
* DC.C - Device context functions
*
*/
#include <w32k.h>
#define NDEBUG
#include <debug.h>
/* ROS Internal. Please deprecate */
NTHALAPI
BOOLEAN
NTAPI
HalQueryDisplayOwnership(
VOID
);
#ifndef OBJ_COLORSPACE
#define OBJ_COLORSPACE (14)
#endif
static GDIDEVICE PrimarySurface;
static KEVENT VideoDriverNeedsPreparation;
static KEVENT VideoDriverPrepared;
NTSTATUS FASTCALL
InitDcImpl(VOID)
{
KeInitializeEvent(&VideoDriverNeedsPreparation, SynchronizationEvent, TRUE);
KeInitializeEvent(&VideoDriverPrepared, NotificationEvent, FALSE);
return STATUS_SUCCESS;
}
/* FIXME: DCs should probably be thread safe */
/*
* DC device-independent Get/SetXXX functions
* (RJJ) swiped from WINE
*/
#define DC_GET_VAL( func_type, func_name, dc_field ) \
func_type STDCALL func_name( HDC hdc ) \
{ \
func_type ft; \
PDC dc = DC_LockDc( hdc ); \
if (!dc) \
{ \
SetLastWin32Error(ERROR_INVALID_HANDLE); \
return 0; \
} \
ft = dc->dc_field; \
DC_UnlockDc(dc); \
return ft; \
}
/* DC_GET_VAL_EX is used to define functions returning a POINT or a SIZE. It is
* important that the function has the right signature, for the implementation
* we can do whatever we want.
*/
#define DC_GET_VAL_EX( FuncName, ret_x, ret_y, type, ax, ay ) \
VOID FASTCALL Int##FuncName ( PDC dc, LP##type pt) \
{ \
ASSERT(dc); \
ASSERT(pt); \
pt->ax = dc->ret_x; \
pt->ay = dc->ret_y; \
} \
BOOL STDCALL NtGdi##FuncName ( HDC hdc, LP##type pt ) \
{ \
NTSTATUS Status = STATUS_SUCCESS; \
type Safept; \
PDC dc; \
if(!pt) \
{ \
SetLastWin32Error(ERROR_INVALID_PARAMETER); \
return FALSE; \
} \
if(!(dc = DC_LockDc(hdc))) \
{ \
SetLastWin32Error(ERROR_INVALID_HANDLE); \
return FALSE; \
} \
Int##FuncName( dc, &Safept); \
DC_UnlockDc(dc); \
_SEH_TRY \
{ \
ProbeForWrite(pt, \
sizeof( type ), \
1); \
*pt = Safept; \
} \
_SEH_HANDLE \
{ \
Status = _SEH_GetExceptionCode(); \
} \
_SEH_END; \
if(!NT_SUCCESS(Status)) \
{ \
SetLastNtError(Status); \
return FALSE; \
} \
return TRUE; \
}
#define DC_SET_MODE( func_name, dc_field, min_val, max_val ) \
INT STDCALL func_name( HDC hdc, INT mode ) \
{ \
INT prevMode; \
PDC dc; \
if ((mode < min_val) || (mode > max_val)) \
{ \
SetLastWin32Error(ERROR_INVALID_PARAMETER); \
return 0; \
} \
dc = DC_LockDc ( hdc ); \
if ( !dc ) \
{ \
SetLastWin32Error(ERROR_INVALID_HANDLE); \
return 0; \
} \
prevMode = dc->dc_field; \
dc->dc_field = mode; \
DC_UnlockDc ( dc ); \
return prevMode; \
}
// --------------------------------------------------------- File Statics
// ----------------------------------------------------- Public Functions
BOOL STDCALL
NtGdiCancelDC(HDC hDC)
{
UNIMPLEMENTED;
return FALSE;
}
HDC STDCALL
NtGdiCreateCompatibleDC(HDC hDC)
{
PDC NewDC, OrigDC;
HBITMAP hBitmap;
HDC hNewDC, DisplayDC;
HRGN hVisRgn;
UNICODE_STRING DriverName;
INT DC_Type = DC_TYPE_DIRECT;
DisplayDC = NULL;
if (hDC == NULL)
{
RtlInitUnicodeString(&DriverName, L"DISPLAY");
DisplayDC = IntGdiCreateDC(&DriverName, NULL, NULL, NULL, TRUE);
if (NULL == DisplayDC)
{
return NULL;
}
hDC = DisplayDC;
DC_Type = DC_TYPE_MEMORY; // Null hDC == Memory DC.
}
/* Allocate a new DC based on the original DC's device */
OrigDC = DC_LockDc(hDC);
if (NULL == OrigDC)
{
if (NULL != DisplayDC)
{
NtGdiDeleteObjectApp(DisplayDC);
}
return NULL;
}
hNewDC = DC_AllocDC(&OrigDC->DriverName);
if (NULL == hNewDC)
{
DC_UnlockDc(OrigDC);
if (NULL != DisplayDC)
{
NtGdiDeleteObjectApp(DisplayDC);
}
return NULL;
}
NewDC = DC_LockDc( hNewDC );
/* Copy information from original DC to new DC */
NewDC->hSelf = hNewDC;
NewDC->IsIC = FALSE;
NewDC->DC_Type = DC_Type;
NewDC->PDev = OrigDC->PDev;
memcpy(NewDC->FillPatternSurfaces,
OrigDC->FillPatternSurfaces,
sizeof OrigDC->FillPatternSurfaces);
NewDC->GDIInfo = OrigDC->GDIInfo;
NewDC->DevInfo = OrigDC->DevInfo;
NewDC->w.bitsPerPixel = OrigDC->w.bitsPerPixel;
/* DriverName is copied in the AllocDC routine */
NewDC->DeviceDriver = OrigDC->DeviceDriver;
NewDC->Dc_Attr.ptlWindowOrg.x = OrigDC->Dc_Attr.ptlWindowOrg.x;
NewDC->Dc_Attr.ptlWindowOrg.y = OrigDC->Dc_Attr.ptlWindowOrg.y;
NewDC->Dc_Attr.szlWindowExt.cx = OrigDC->Dc_Attr.szlWindowExt.cx;
NewDC->Dc_Attr.szlWindowExt.cy = OrigDC->Dc_Attr.szlWindowExt.cy;
NewDC->Dc_Attr.ptlViewportOrg.x = OrigDC->Dc_Attr.ptlViewportOrg.x;
NewDC->Dc_Attr.ptlViewportOrg.y = OrigDC->Dc_Attr.ptlViewportOrg.y;
NewDC->Dc_Attr.szlViewportExt.cx = OrigDC->Dc_Attr.szlViewportExt.cx;
NewDC->Dc_Attr.szlViewportExt.cy = OrigDC->Dc_Attr.szlViewportExt.cy;
/* Create default bitmap */
if (!(hBitmap = IntGdiCreateBitmap( 1, 1, 1, NewDC->w.bitsPerPixel, NULL )))
{
DC_UnlockDc( OrigDC );
DC_UnlockDc( NewDC );
DC_FreeDC( hNewDC );
if (NULL != DisplayDC)
{
NtGdiDeleteObjectApp(DisplayDC);
}
return NULL;
}
NewDC->w.flags = DC_MEMORY;
NewDC->w.hBitmap = hBitmap;
NewDC->w.hFirstBitmap = hBitmap;
NewDC->GDIDevice = OrigDC->GDIDevice;
NewDC->PalIndexed = OrigDC->PalIndexed;
NewDC->w.hPalette = OrigDC->w.hPalette;
NewDC->Dc_Attr.crForegroundClr = OrigDC->Dc_Attr.crForegroundClr;
NewDC->Dc_Attr.lTextAlign = OrigDC->Dc_Attr.lTextAlign;
NewDC->Dc_Attr.crBackgroundClr = OrigDC->Dc_Attr.crBackgroundClr;
NewDC->Dc_Attr.jBkMode = OrigDC->Dc_Attr.jBkMode;
NewDC->Dc_Attr.jROP2 = OrigDC->Dc_Attr.jROP2;
DC_UnlockDc(NewDC);
DC_UnlockDc(OrigDC);
if (NULL != DisplayDC)
{
NtGdiDeleteObjectApp(DisplayDC);
}
hVisRgn = NtGdiCreateRectRgn(0, 0, 1, 1);
IntGdiSelectVisRgn(hNewDC, hVisRgn);
NtGdiDeleteObject(hVisRgn);
DC_InitDC(hNewDC);
return hNewDC;
}
static BOOLEAN FASTCALL
GetRegistryPath(PUNICODE_STRING RegistryPath, ULONG DisplayNumber)
{
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
WCHAR DeviceNameBuffer[20];
NTSTATUS Status;
swprintf(DeviceNameBuffer, L"\\Device\\Video%lu", DisplayNumber);
RtlInitUnicodeString(RegistryPath, NULL);
RtlZeroMemory(QueryTable, sizeof(QueryTable));
QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
QueryTable[0].Name = DeviceNameBuffer;
QueryTable[0].EntryContext = RegistryPath;
Status = RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP,
L"VIDEO",
QueryTable,
NULL,
NULL);
if (! NT_SUCCESS(Status))
{
DPRINT1("No \\Device\\Video%lu value in DEVICEMAP\\VIDEO found\n", DisplayNumber);
return FALSE;
}
DPRINT("RegistryPath %wZ\n", RegistryPath);
return TRUE;
}
static BOOL FASTCALL
FindDriverFileNames(PUNICODE_STRING DriverFileNames, ULONG DisplayNumber)
{
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
UNICODE_STRING RegistryPath;
NTSTATUS Status;
if (! GetRegistryPath(&RegistryPath, DisplayNumber))
{
DPRINT("GetRegistryPath failed\n");
return FALSE;
}
RtlZeroMemory(QueryTable, sizeof(QueryTable));
QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
QueryTable[0].Name = L"InstalledDisplayDrivers";
QueryTable[0].EntryContext = DriverFileNames;
Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
RegistryPath.Buffer,
QueryTable,
NULL,
NULL);
RtlFreeUnicodeString(&RegistryPath);
if (! NT_SUCCESS(Status))
{
DPRINT1("No InstalledDisplayDrivers value in service entry found\n");
return FALSE;
}
DPRINT("DriverFileNames %S\n", DriverFileNames->Buffer);
return TRUE;
}
static NTSTATUS STDCALL
DevModeCallback(IN PWSTR ValueName,
IN ULONG ValueType,
IN PVOID ValueData,
IN ULONG ValueLength,
IN PVOID Context,
IN PVOID EntryContext)
{
PDEVMODEW DevMode = (PDEVMODEW) Context;
DPRINT("Found registry value for name %S: type %d, length %d\n",
ValueName, ValueType, ValueLength);
if (REG_DWORD == ValueType && sizeof(DWORD) == ValueLength)
{
if (0 == _wcsicmp(ValueName, L"DefaultSettings.BitsPerPel"))
{
DevMode->dmBitsPerPel = *((DWORD *) ValueData);
}
else if (0 == _wcsicmp(ValueName, L"DefaultSettings.Flags"))
{
DevMode->dmDisplayFlags = *((DWORD *) ValueData);
}
else if (0 == _wcsicmp(ValueName, L"DefaultSettings.VRefresh"))
{
DevMode->dmDisplayFrequency = *((DWORD *) ValueData);
}
else if (0 == _wcsicmp(ValueName, L"DefaultSettings.XPanning"))
{
DevMode->dmPanningWidth = *((DWORD *) ValueData);
}
else if (0 == _wcsicmp(ValueName, L"DefaultSettings.XResolution"))
{
DevMode->dmPelsWidth = *((DWORD *) ValueData);
}
else if (0 == _wcsicmp(ValueName, L"DefaultSettings.YPanning"))
{
DevMode->dmPanningHeight = *((DWORD *) ValueData);
}
else if (0 == _wcsicmp(ValueName, L"DefaultSettings.YResolution"))
{
DevMode->dmPelsHeight = *((DWORD *) ValueData);
}
}
return STATUS_SUCCESS;
}
static BOOL FASTCALL
SetupDevMode(PDEVMODEW DevMode, ULONG DisplayNumber)
{
UNICODE_STRING RegistryPath;
RTL_QUERY_REGISTRY_TABLE QueryTable[2];
NTSTATUS Status;
BOOLEAN Valid = TRUE;
if (!GetRegistryPath(&RegistryPath, DisplayNumber))
{
DPRINT("GetRegistryPath failed\n");
return FALSE;
}
RtlZeroMemory(QueryTable, sizeof(QueryTable));
QueryTable[0].QueryRoutine = DevModeCallback;
QueryTable[0].Flags = 0;
QueryTable[0].Name = NULL;
QueryTable[0].EntryContext = NULL;
QueryTable[0].DefaultType = REG_NONE;
QueryTable[0].DefaultData = NULL;
QueryTable[0].DefaultLength = 0;
Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
RegistryPath.Buffer,
QueryTable,
DevMode,
NULL);
if (! NT_SUCCESS(Status))
{
DPRINT("RtlQueryRegistryValues for %wZ failed with status 0x%08x\n",
&RegistryPath, Status);
Valid = FALSE;
}
else
{
DPRINT("dmBitsPerPel %d dmDisplayFrequency %d dmPelsWidth %d dmPelsHeight %d\n",
DevMode->dmBitsPerPel, DevMode->dmDisplayFrequency,
DevMode->dmPelsWidth, DevMode->dmPelsHeight);
if (0 == DevMode->dmBitsPerPel || 0 == DevMode->dmDisplayFrequency
|| 0 == DevMode->dmPelsWidth || 0 == DevMode->dmPelsHeight)
{
DPRINT("Not all required devmode members are set\n");
Valid = FALSE;
}
}
RtlFreeUnicodeString(&RegistryPath);
if (! Valid)
{
RtlZeroMemory(DevMode, sizeof(DEVMODEW));
}
return Valid;
}
static BOOL FASTCALL
IntPrepareDriver()
{
PGD_ENABLEDRIVER GDEnableDriver;
DRVENABLEDATA DED;
UNICODE_STRING DriverFileNames;
PWSTR CurrentName;
BOOL GotDriver;
BOOL DoDefault;
ULONG DisplayNumber;
LARGE_INTEGER Zero;
BOOLEAN ret = FALSE;
Zero.QuadPart = 0;
if (STATUS_SUCCESS != KeWaitForSingleObject(&VideoDriverNeedsPreparation, Executive, KernelMode, TRUE, &Zero))
{
/* Concurrent access. Wait for VideoDriverPrepared event */
if (STATUS_SUCCESS == KeWaitForSingleObject(&VideoDriverPrepared, Executive, KernelMode, TRUE, NULL))
ret = PrimarySurface.PreparedDriver;
goto cleanup;
}
for (DisplayNumber = 0; ; DisplayNumber++)
{
DPRINT("Trying to load display driver no. %d\n", DisplayNumber);
RtlZeroMemory(&PrimarySurface, sizeof(PrimarySurface));
PrimarySurface.VideoFileObject = DRIVER_FindMPDriver(DisplayNumber);
/* Open the miniport driver */
if (PrimarySurface.VideoFileObject == NULL)
{
DPRINT1("FindMPDriver failed\n");
goto cleanup;
}
/* Retrieve DDI driver names from registry */
RtlInitUnicodeString(&DriverFileNames, NULL);
if (!FindDriverFileNames(&DriverFileNames, DisplayNumber))
{
DPRINT1("FindDriverFileNames failed\n");
continue;
}
/*
* DriverFileNames may be a list of drivers in REG_SZ_MULTI format,
* scan all of them until a good one found.
*/
CurrentName = DriverFileNames.Buffer;
GotDriver = FALSE;
while (!GotDriver &&
CurrentName < DriverFileNames.Buffer + (DriverFileNames.Length / sizeof (WCHAR)))
{
/* Get the DDI driver's entry point */
GDEnableDriver = DRIVER_FindDDIDriver(CurrentName);
if (NULL == GDEnableDriver)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -