reactos/win32ss/gdi/gdi32/objects/dc.c

1552 lines
29 KiB
C

#include <precomp.h>
#define NDEBUG
#include <debug.h>
HDC
FASTCALL
IntCreateDICW(
LPCWSTR lpwszDriver,
LPCWSTR lpwszDevice,
LPCWSTR lpwszOutput,
PDEVMODEW lpInitData,
ULONG iType)
{
UNICODE_STRING Device, Output;
HDC hdc = NULL;
BOOL Display = FALSE, Default = FALSE;
ULONG UMdhpdev = 0;
HANDLE hspool = NULL;
if ( !ghSpooler && !LoadTheSpoolerDrv())
{
DPRINT1("WinSpooler.Drv Did not load!\n");
}
else
{
DPRINT("WinSpooler.Drv Loaded! hMod -> 0x%p\n", ghSpooler);
}
if ((!lpwszDevice) && (!lpwszDriver))
{
Default = TRUE; // Ask Win32k to set Default device.
Display = TRUE; // Most likely to be DISPLAY.
}
else
{
if ((lpwszDevice) && (wcslen(lpwszDevice) != 0)) // First
{
if (!_wcsnicmp(lpwszDevice, L"\\\\.\\DISPLAY",11)) Display = TRUE;
RtlInitUnicodeString(&Device, lpwszDevice);
}
else
{
if (lpwszDriver) // Second
{
if ((!_wcsnicmp(lpwszDriver, L"DISPLAY",7)) ||
(!_wcsnicmp(lpwszDriver, L"\\\\.\\DISPLAY",11))) Display = TRUE;
RtlInitUnicodeString(&Device, lpwszDriver);
}
}
}
if (lpwszOutput) RtlInitUnicodeString(&Output, lpwszOutput);
if (!Display)
{
//Handle Print device or something else.
DPRINT1("Not a DISPLAY device! %wZ\n", &Device);
}
hdc = NtGdiOpenDCW((Default ? NULL : &Device),
(PDEVMODEW) lpInitData,
(lpwszOutput ? &Output : NULL),
iType, // DCW 0 and ICW 1.
Display,
hspool,
(PVOID) &UMdhpdev );
#if 0
// Handle something other than a normal dc object.
if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
{
PDC_ATTR Dc_Attr;
PLDC pLDC;
GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID*)&Dc_Attr);
pLDC = LocalAlloc(LMEM_ZEROINIT, sizeof(LDC));
Dc_Attr->pvLDC = pLDC;
pLDC->hDC = hdc;
pLDC->iType = LDC_LDC; // 1 (init) local DC, 2 EMF LDC
DbgPrint("DC_ATTR Allocated -> 0x%x\n",Dc_Attr);
}
#endif
return hdc;
}
/*
* @implemented
*/
HDC
WINAPI
CreateCompatibleDC(
_In_ HDC hdc)
{
HDC hdcNew;
// PDC_ATTR pdcattr;
hdcNew = NtGdiCreateCompatibleDC(hdc);
#if 0
if ( hdc && hdcNew)
{
if (GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID*)&pdcattr))
{
if (pdcattr->pvLIcm) IcmCompatibleDC(hdcNew, hdc, pdcattr);
}
}
#endif
return hdcNew;
}
/*
* @implemented
*/
HDC
WINAPI
CreateDCA (
LPCSTR lpszDriver,
LPCSTR lpszDevice,
LPCSTR lpszOutput,
CONST DEVMODEA * lpdvmInit)
{
ANSI_STRING DriverA, DeviceA, OutputA;
UNICODE_STRING DriverU, DeviceU, OutputU;
LPDEVMODEW dvmInitW = NULL;
HDC hdc;
/*
* If needed, convert to Unicode
* any string parameter.
*/
if (lpszDriver != NULL)
{
RtlInitAnsiString(&DriverA, (LPSTR)lpszDriver);
RtlAnsiStringToUnicodeString(&DriverU, &DriverA, TRUE);
}
else
{
DriverU.Buffer = NULL;
}
if (lpszDevice != NULL)
{
RtlInitAnsiString(&DeviceA, (LPSTR)lpszDevice);
RtlAnsiStringToUnicodeString(&DeviceU, &DeviceA, TRUE);
}
else
{
DeviceU.Buffer = NULL;
}
if (lpszOutput != NULL)
{
RtlInitAnsiString(&OutputA, (LPSTR)lpszOutput);
RtlAnsiStringToUnicodeString(&OutputU, &OutputA, TRUE);
}
else
{
OutputU.Buffer = NULL;
}
if (lpdvmInit != NULL)
dvmInitW = GdiConvertToDevmodeW((LPDEVMODEA)lpdvmInit);
hdc = IntCreateDICW(DriverU.Buffer,
DeviceU.Buffer,
OutputU.Buffer,
lpdvmInit ? dvmInitW : NULL,
0);
HEAP_free(dvmInitW);
/* Free Unicode parameters. */
RtlFreeUnicodeString(&DriverU);
RtlFreeUnicodeString(&DeviceU);
RtlFreeUnicodeString(&OutputU);
/* Return the DC handle. */
return hdc;
}
/*
* @implemented
*/
HDC
WINAPI
CreateDCW (
LPCWSTR lpwszDriver,
LPCWSTR lpwszDevice,
LPCWSTR lpwszOutput,
CONST DEVMODEW *lpInitData)
{
return IntCreateDICW(lpwszDriver,
lpwszDevice,
lpwszOutput,
(PDEVMODEW)lpInitData,
0);
}
/*
* @implemented
*/
HDC
WINAPI
CreateICW(
LPCWSTR lpszDriver,
LPCWSTR lpszDevice,
LPCWSTR lpszOutput,
CONST DEVMODEW *lpdvmInit)
{
return IntCreateDICW(lpszDriver,
lpszDevice,
lpszOutput,
(PDEVMODEW)lpdvmInit,
1);
}
/*
* @implemented
*/
HDC
WINAPI
CreateICA(
LPCSTR lpszDriver,
LPCSTR lpszDevice,
LPCSTR lpszOutput,
CONST DEVMODEA *lpdvmInit)
{
NTSTATUS Status;
LPWSTR lpszDriverW, lpszDeviceW, lpszOutputW;
LPDEVMODEW dvmInitW = NULL;
HDC hdc = 0;
Status = HEAP_strdupA2W(&lpszDriverW, lpszDriver);
if (!NT_SUCCESS(Status))
SetLastError(RtlNtStatusToDosError(Status));
else
{
Status = HEAP_strdupA2W(&lpszDeviceW, lpszDevice);
if (!NT_SUCCESS(Status))
SetLastError(RtlNtStatusToDosError(Status));
else
{
Status = HEAP_strdupA2W(&lpszOutputW, lpszOutput);
if (!NT_SUCCESS(Status))
SetLastError(RtlNtStatusToDosError(Status));
else
{
if (lpdvmInit)
dvmInitW = GdiConvertToDevmodeW((LPDEVMODEA)lpdvmInit);
hdc = IntCreateDICW(lpszDriverW,
lpszDeviceW,
lpszOutputW,
lpdvmInit ? dvmInitW : NULL,
1 );
HEAP_free(dvmInitW);
HEAP_free(lpszOutputW);
}
HEAP_free(lpszDeviceW);
}
HEAP_free(lpszDriverW);
}
return hdc;
}
/*
* @implemented
*/
BOOL
WINAPI
DeleteDC(HDC hdc)
{
BOOL bResult = TRUE;
PLDC pLDC = NULL;
HANDLE hPrinter = NULL;
ULONG hType = GDI_HANDLE_GET_TYPE(hdc);
pLDC = GdiGetLDC(hdc);
if (hType != GDILoObjType_LO_DC_TYPE)
{
return METADC_DeleteDC(hdc);
}
bResult = NtGdiDeleteObjectApp(hdc);
if (bResult && pLDC)
{
DPRINT1("Delete the Local DC structure\n");
LocalFree( pLDC );
}
if (hPrinter)
fpClosePrinter(hPrinter);
return bResult;
}
/*
* @unimplemented
*/
INT
WINAPI
SaveDC(IN HDC hdc)
{
HANDLE_METADC0P(INT, SaveDC, 0, hdc);
return NtGdiSaveDC(hdc);
}
/*
* @unimplemented
*/
BOOL
WINAPI
RestoreDC(IN HDC hdc,
IN INT iLevel)
{
HANDLE_METADC(BOOL, RestoreDC, FALSE, hdc, iLevel);
return NtGdiRestoreDC(hdc, iLevel);
}
/*
* @implemented
*/
BOOL
WINAPI
CancelDC(HDC hDC)
{
PDC_ATTR pDc_Attr;
if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC &&
GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_METADC )
{
PLDC pLDC = GdiGetLDC(hDC);
if ( !pLDC )
{
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
/* If a document has started set it to die. */
if (pLDC->Flags & LDC_INIT_DOCUMENT) pLDC->Flags |= LDC_KILL_DOCUMENT;
return NtGdiCancelDC(hDC);
}
if (GdiGetHandleUserData((HGDIOBJ) hDC, GDI_OBJECT_TYPE_DC, (PVOID) &pDc_Attr))
{
pDc_Attr->ulDirty_ &= ~DC_PLAYMETAFILE;
return TRUE;
}
return FALSE;
}
INT
WINAPI
GetArcDirection(
_In_ HDC hdc)
{
return GetDCDWord( hdc, GdiGetArcDirection, 0);
}
INT
WINAPI
SetArcDirection(
_In_ HDC hdc,
_In_ INT nDirection)
{
return GetAndSetDCDWord(hdc, GdiGetSetArcDirection, nDirection, 0, 0, 0);
}
/*
* @unimplemented
*/
BOOL
WINAPI
GdiReleaseDC(HDC hdc)
{
return 0;
}
/*
* @implemented
*/
BOOL
WINAPI
GdiCleanCacheDC(HDC hdc)
{
if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_DC_TYPE)
return TRUE;
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
/*
* @implemented
*/
HDC
WINAPI
GdiConvertAndCheckDC(HDC hdc)
{
PLDC pldc;
ULONG hType = GDI_HANDLE_GET_TYPE(hdc);
if (hType == GDILoObjType_LO_DC_TYPE || hType == GDILoObjType_LO_METADC16_TYPE)
return hdc;
pldc = GdiGetLDC(hdc);
if (pldc)
{
if (pldc->Flags & LDC_SAPCALLBACK) GdiSAPCallback(pldc);
if (pldc->Flags & LDC_KILL_DOCUMENT) return NULL;
if (pldc->Flags & LDC_STARTPAGE) StartPage(hdc);
return hdc;
}
SetLastError(ERROR_INVALID_HANDLE);
return NULL;
}
/*
* @implemented
*
*/
HGDIOBJ
WINAPI
GetCurrentObject(
_In_ HDC hdc,
_In_ UINT uObjectType)
{
PDC_ATTR pdcattr = NULL;
/* Check if this is a user mode object */
if ((uObjectType == OBJ_PEN) ||
(uObjectType == OBJ_EXTPEN) ||
(uObjectType == OBJ_BRUSH) ||
(uObjectType == OBJ_COLORSPACE))
{
/* Get the DC attribute */
pdcattr = GdiGetDcAttr(hdc);
if (pdcattr == NULL)
{
return NULL;
}
}
/* Check what object was requested */
switch (uObjectType)
{
case OBJ_EXTPEN:
case OBJ_PEN:
return pdcattr->hpen;
case OBJ_BRUSH:
return pdcattr->hbrush;
case OBJ_COLORSPACE:
return pdcattr->hColorSpace;
case OBJ_PAL:
uObjectType = GDI_OBJECT_TYPE_PALETTE;
break;
case OBJ_FONT:
uObjectType = GDI_OBJECT_TYPE_FONT;
break;
case OBJ_BITMAP:
uObjectType = GDI_OBJECT_TYPE_BITMAP;
break;
/* All others are invalid */
default:
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
/* Pass the request to win32k */
return NtGdiGetDCObject(hdc, uObjectType);
}
/*
* @implemented
*/
int
WINAPI
EnumObjects(HDC hdc,
int nObjectType,
GOBJENUMPROC lpObjectFunc,
LPARAM lParam)
{
ULONG ObjectsCount;
ULONG Size;
PVOID Buffer = NULL;
DWORD_PTR EndOfBuffer;
int Result = 0;
switch (nObjectType)
{
case OBJ_BRUSH:
Size = sizeof(LOGBRUSH);
break;
case OBJ_PEN:
Size = sizeof(LOGPEN);
break;
default:
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
ObjectsCount = NtGdiEnumObjects(hdc, nObjectType, 0, NULL);
if (!ObjectsCount) return 0;
Buffer = HeapAlloc(GetProcessHeap(), 0, ObjectsCount * Size);
if (!Buffer)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return 0;
}
if (!NtGdiEnumObjects(hdc, nObjectType, ObjectsCount * Size, Buffer))
{
HeapFree(GetProcessHeap(), 0, Buffer);
return 0;
}
EndOfBuffer = (DWORD_PTR)Buffer + (ObjectsCount * Size);
while ((DWORD_PTR)Buffer < EndOfBuffer)
{
Result = lpObjectFunc(Buffer, lParam);
if (!Result) break;
Buffer = (PVOID)((DWORD_PTR)Buffer + Size);
}
HeapFree(GetProcessHeap(), 0, Buffer);
return Result;
}
/*
* @implemented
*
*/
int
WINAPI
GetDeviceCaps(
_In_ HDC hdc,
_In_ int nIndex)
{
PDC_ATTR pdcattr;
PDEVCAPS pDevCaps = GdiDevCaps; // Primary display device capabilities.
DPRINT("Device CAPS1\n");
HANDLE_METADC(INT, GetDeviceCaps, 0, hdc, nIndex);
/* Get the DC attribute */
pdcattr = GdiGetDcAttr(hdc);
if (pdcattr == NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
if (!(pdcattr->ulDirty_ & DC_PRIMARY_DISPLAY))
return NtGdiGetDeviceCaps(hdc, nIndex);
switch (nIndex)
{
case DRIVERVERSION:
return pDevCaps->ulVersion;
case TECHNOLOGY:
return pDevCaps->ulTechnology;
case HORZSIZE:
return pDevCaps->ulHorzSize;
case VERTSIZE:
return pDevCaps->ulVertSize;
case HORZRES:
return pDevCaps->ulHorzRes;
case VERTRES:
return pDevCaps->ulVertRes;
case LOGPIXELSX:
return pDevCaps->ulLogPixelsX;
case LOGPIXELSY:
return pDevCaps->ulLogPixelsY;
case BITSPIXEL:
return pDevCaps->ulBitsPixel;
case PLANES:
return pDevCaps->ulPlanes;
case NUMBRUSHES:
return -1;
case NUMPENS:
return pDevCaps->ulNumPens;
case NUMFONTS:
return pDevCaps->ulNumFonts;
case NUMCOLORS:
return pDevCaps->ulNumColors;
case ASPECTX:
return pDevCaps->ulAspectX;
case ASPECTY:
return pDevCaps->ulAspectY;
case ASPECTXY:
return pDevCaps->ulAspectXY;
case CLIPCAPS:
return CP_RECTANGLE;
case SIZEPALETTE:
return pDevCaps->ulSizePalette;
case NUMRESERVED:
return 20;
case COLORRES:
return pDevCaps->ulColorRes;
case DESKTOPVERTRES:
return pDevCaps->ulVertRes;
case DESKTOPHORZRES:
return pDevCaps->ulHorzRes;
case BLTALIGNMENT:
return pDevCaps->ulBltAlignment;
case SHADEBLENDCAPS:
return pDevCaps->ulShadeBlend;
case COLORMGMTCAPS:
return pDevCaps->ulColorMgmtCaps;
case PHYSICALWIDTH:
return pDevCaps->ulPhysicalWidth;
case PHYSICALHEIGHT:
return pDevCaps->ulPhysicalHeight;
case PHYSICALOFFSETX:
return pDevCaps->ulPhysicalOffsetX;
case PHYSICALOFFSETY:
return pDevCaps->ulPhysicalOffsetY;
case VREFRESH:
return pDevCaps->ulVRefresh;
case RASTERCAPS:
return pDevCaps->ulRasterCaps;
case CURVECAPS:
return (CC_CIRCLES | CC_PIE | CC_CHORD | CC_ELLIPSES | CC_WIDE |
CC_STYLED | CC_WIDESTYLED | CC_INTERIORS | CC_ROUNDRECT);
case LINECAPS:
return (LC_POLYLINE | LC_MARKER | LC_POLYMARKER | LC_WIDE |
LC_STYLED | LC_WIDESTYLED | LC_INTERIORS);
case POLYGONALCAPS:
return (PC_POLYGON | PC_RECTANGLE | PC_WINDPOLYGON | PC_SCANLINE |
PC_WIDE | PC_STYLED | PC_WIDESTYLED | PC_INTERIORS);
case TEXTCAPS:
return pDevCaps->ulTextCaps;
case PDEVICESIZE:
case SCALINGFACTORX:
case SCALINGFACTORY:
default:
return 0;
}
return 0;
}
/*
* @implemented
*/
DWORD
WINAPI
GetRelAbs(
_In_ HDC hdc,
_In_ DWORD dwIgnore)
{
return GetDCDWord(hdc, GdiGetRelAbs, 0);
}
/*
* @implemented
*/
INT
WINAPI
SetRelAbs(
HDC hdc,
INT Mode)
{
return GetAndSetDCDWord(hdc, GdiGetSetRelAbs, Mode, 0, 0, 0);
}
/*
* @implemented
*/
DWORD
WINAPI
GetAndSetDCDWord(
_In_ HDC hdc,
_In_ UINT u,
_In_ DWORD dwIn,
_In_ ULONG ulMFId,
_In_ USHORT usMF16Id,
_In_ DWORD dwError)
{
DWORD dwResult;
/* This is a special API, handle it appropriately */
HANDLE_METADC2(DWORD, GetAndSetDCDWord, hdc, u, dwIn, ulMFId, usMF16Id, dwError);
/* Call win32k to do the real work */
if (!NtGdiGetAndSetDCDword(hdc, u, dwIn, &dwResult))
{
return dwError;
}
return dwResult;
}
/*
* @implemented
*/
DWORD
WINAPI
GetDCDWord(
_In_ HDC hdc,
_In_ UINT u,
_In_ DWORD dwError)
{
DWORD dwResult;
if (!NtGdiGetDCDword(hdc, u, &dwResult))
{
return dwError;
}
return dwResult;
}
/*
* @implemented
*/
BOOL
WINAPI
GetAspectRatioFilterEx(
HDC hdc,
LPSIZE lpAspectRatio)
{
return NtGdiGetDCPoint(hdc, GdiGetAspectRatioFilter, (PPOINTL)lpAspectRatio );
}
/*
* @implemented
*/
UINT
WINAPI
GetBoundsRect(
HDC hdc,
LPRECT lprcBounds,
UINT flags
)
{
return NtGdiGetBoundsRect(hdc,lprcBounds,flags & ~DCB_WINDOWMGR);
}
/*
* @implemented
*/
UINT
WINAPI
SetBoundsRect(HDC hdc,
CONST RECT *prc,
UINT flags)
{
/* FIXME add check for validate the flags */
return NtGdiSetBoundsRect(hdc, (LPRECT)prc, flags & ~DCB_WINDOWMGR);
}
/*
* @implemented
*
*/
int
WINAPI
GetClipBox(HDC hdc,
LPRECT lprc)
{
return NtGdiGetAppClipBox(hdc, lprc);
}
/*
* @implemented
*/
COLORREF
WINAPI
GetDCBrushColor(
_In_ HDC hdc)
{
PDC_ATTR pdcattr;
/* Get the DC attribute */
pdcattr = GdiGetDcAttr(hdc);
if (pdcattr == NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
return CLR_INVALID;
}
return pdcattr->ulBrushClr;
}
/*
* @implemented
*/
COLORREF
WINAPI
GetDCPenColor(
_In_ HDC hdc)
{
PDC_ATTR pdcattr;
/* Get the DC attribute */
pdcattr = GdiGetDcAttr(hdc);
if (pdcattr == NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
return CLR_INVALID;
}
return pdcattr->ulPenClr;
}
/*
* @implemented
*/
COLORREF
WINAPI
SetDCBrushColor(
_In_ HDC hdc,
_In_ COLORREF crColor)
{
PDC_ATTR pdcattr;
COLORREF crOldColor;
/* Get the DC attribute */
pdcattr = GdiGetDcAttr(hdc);
if (pdcattr == NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
return CLR_INVALID;
}
/* We handle only enhanced meta DCs here */
HANDLE_METADC(COLORREF, SetDCBrushColor, CLR_INVALID, hdc, crColor);
/* Get old color and store the new */
crOldColor = pdcattr->ulBrushClr;
pdcattr->ulBrushClr = crColor;
if (pdcattr->crBrushClr != crColor)
{
pdcattr->ulDirty_ |= DIRTY_FILL;
pdcattr->crBrushClr = crColor;
}
return crOldColor;
}
/*
* @implemented
*/
COLORREF
WINAPI
SetDCPenColor(
_In_ HDC hdc,
_In_ COLORREF crColor)
{
PDC_ATTR pdcattr;
COLORREF crOldColor;
/* Get the DC attribute */
pdcattr = GdiGetDcAttr(hdc);
if (pdcattr == NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
return CLR_INVALID;
}
/* We handle only enhanced meta DCs here */
HANDLE_METADC(COLORREF, SetDCPenColor, CLR_INVALID, hdc, crColor);
/* Get old color and store the new */
crOldColor = pdcattr->ulPenClr;
pdcattr->ulPenClr = (ULONG)crColor;
if (pdcattr->crPenClr != crColor)
{
pdcattr->ulDirty_ |= DIRTY_LINE;
pdcattr->crPenClr = crColor;
}
return crOldColor;
}
/*
* @implemented
*
*/
COLORREF
WINAPI
GetBkColor(
_In_ HDC hdc)
{
PDC_ATTR pdcattr;
/* Get the DC attribute */
pdcattr = GdiGetDcAttr(hdc);
if (pdcattr == NULL)
{
/* Don't set LastError here! */
return CLR_INVALID;
}
return pdcattr->ulBackgroundClr;
}
/*
* @implemented
*/
COLORREF
WINAPI
SetBkColor(
_In_ HDC hdc,
_In_ COLORREF crColor)
{
PDC_ATTR pdcattr;
COLORREF crOldColor;
HANDLE_METADC(COLORREF, SetBkColor, CLR_INVALID, hdc, crColor);
/* Get the DC attribute */
pdcattr = GdiGetDcAttr(hdc);
if (pdcattr == NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
return CLR_INVALID;
}
/* Get old color and store the new */
crOldColor = pdcattr->ulBackgroundClr;
pdcattr->ulBackgroundClr = crColor;
if (pdcattr->crBackgroundClr != crColor)
{
pdcattr->ulDirty_ |= (DIRTY_BACKGROUND|DIRTY_LINE|DIRTY_FILL);
pdcattr->crBackgroundClr = crColor;
}
return crOldColor;
}
/*
* @implemented
*
*/
int
WINAPI
GetBkMode(HDC hdc)
{
PDC_ATTR pdcattr;
/* Get the DC attribute */
pdcattr = GdiGetDcAttr(hdc);
if (pdcattr == NULL)
{
/* Don't set LastError here! */
return 0;
}
return pdcattr->lBkMode;
}
/*
* @implemented
*
*/
int
WINAPI
SetBkMode(
_In_ HDC hdc,
_In_ int iBkMode)
{
PDC_ATTR pdcattr;
INT iOldMode;
HANDLE_METADC(INT, SetBkMode, 0, hdc, iBkMode);
/* Get the DC attribute */
pdcattr = GdiGetDcAttr(hdc);
if (pdcattr == NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
iOldMode = pdcattr->lBkMode;
pdcattr->jBkMode = iBkMode; // Processed
pdcattr->lBkMode = iBkMode; // Raw
return iOldMode;
}
/*
* @implemented
*
*/
int
WINAPI
GetROP2(
_In_ HDC hdc)
{
PDC_ATTR pdcattr;
/* Get the DC attribute */
pdcattr = GdiGetDcAttr(hdc);
if (pdcattr == NULL)
{
/* Do not set LastError here! */
return 0;
}
return pdcattr->jROP2;
}
/*
* @implemented
*/
int
WINAPI
SetROP2(
_In_ HDC hdc,
_In_ int rop2)
{
PDC_ATTR pdcattr;
INT rop2Old;
HANDLE_METADC(INT, SetROP2, 0, hdc, rop2);
/* Get the DC attribute */
pdcattr = GdiGetDcAttr(hdc);
if (pdcattr == NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
if (NtCurrentTeb()->GdiTebBatch.HDC == hdc)
{
if (pdcattr->ulDirty_ & DC_MODE_DIRTY)
{
NtGdiFlush();
pdcattr->ulDirty_ &= ~DC_MODE_DIRTY;
}
}
rop2Old = pdcattr->jROP2;
pdcattr->jROP2 = (BYTE)rop2;
return rop2Old;
}
/*
* @implemented
*
*/
int
WINAPI
GetPolyFillMode(HDC hdc)
{
PDC_ATTR pdcattr;
/* Get DC attribute */
pdcattr = GdiGetDcAttr(hdc);
if (pdcattr == NULL)
{
/* Don't set LastError here! */
return 0;
}
/* Return current fill mode */
return pdcattr->lFillMode;
}
/*
* @unimplemented
*/
int
WINAPI
SetPolyFillMode(
_In_ HDC hdc,
_In_ int iPolyFillMode)
{
INT iOldPolyFillMode;
PDC_ATTR pdcattr;
HANDLE_METADC(INT, SetPolyFillMode, 0, hdc, iPolyFillMode);
/* Get the DC attribute */
pdcattr = GdiGetDcAttr(hdc);
if (pdcattr == NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
if (NtCurrentTeb()->GdiTebBatch.HDC == hdc)
{
if (pdcattr->ulDirty_ & DC_MODE_DIRTY)
{
NtGdiFlush(); // Sync up pdcattr from Kernel space.
pdcattr->ulDirty_ &= ~(DC_MODE_DIRTY|DC_FONTTEXT_DIRTY);
}
}
iOldPolyFillMode = pdcattr->lFillMode;
pdcattr->lFillMode = iPolyFillMode;
return iOldPolyFillMode;
}
/*
* @implemented
*
*/
int
WINAPI
GetGraphicsMode(HDC hdc)
{
PDC_ATTR pdcattr;
/* Get the DC attribute */
pdcattr = GdiGetDcAttr(hdc);
if (pdcattr == NULL)
{
/* Don't set LastError here! */
return 0;
}
/* Return current graphics mode */
return pdcattr->iGraphicsMode;
}
/*
* @unimplemented
*/
int
WINAPI
SetGraphicsMode(
_In_ HDC hdc,
_In_ int iMode)
{
INT iOldMode;
PDC_ATTR pdcattr;
/* Check parameters */
if ((iMode < GM_COMPATIBLE) || (iMode > GM_ADVANCED))
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
/* Get the DC attribute */
pdcattr = GdiGetDcAttr(hdc);
if (pdcattr == NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
/* Check for trivial case */
if (iMode == pdcattr->iGraphicsMode)
return iMode;
if (NtCurrentTeb()->GdiTebBatch.HDC == hdc)
{
if (pdcattr->ulDirty_ & DC_MODE_DIRTY)
{
NtGdiFlush(); // Sync up pdcattr from Kernel space.
pdcattr->ulDirty_ &= ~(DC_MODE_DIRTY|DC_FONTTEXT_DIRTY);
}
}
/* One would think that setting the graphics mode to GM_COMPATIBLE
* would also reset the world transformation matrix to the unity
* matrix. However, in Windows, this is not the case. This doesn't
* make a lot of sense to me, but that's the way it is.
*/
iOldMode = pdcattr->iGraphicsMode;
pdcattr->iGraphicsMode = iMode;
return iOldMode;
}
/*
* @implemented
*/
HDC
WINAPI
ResetDCW(
_In_ HDC hdc,
_In_ CONST DEVMODEW *lpInitData)
{
NtGdiResetDC ( hdc, (PDEVMODEW)lpInitData, NULL, NULL, NULL);
return hdc;
}
/*
* @implemented
*/
HDC
WINAPI
ResetDCA(
_In_ HDC hdc,
_In_ CONST DEVMODEA *lpInitData)
{
LPDEVMODEW InitDataW;
InitDataW = GdiConvertToDevmodeW((LPDEVMODEA)lpInitData);
NtGdiResetDC ( hdc, InitDataW, NULL, NULL, NULL);
HEAP_free(InitDataW);
return hdc;
}
/* FIXME: include correct header */
HPALETTE WINAPI NtUserSelectPalette(HDC hDC,
HPALETTE hpal,
BOOL ForceBackground);
HPALETTE
WINAPI
SelectPalette(
HDC hdc,
HPALETTE hpal,
BOOL bForceBackground)
{
HANDLE_METADC(HPALETTE, SelectPalette, NULL, hdc, hpal, bForceBackground);
return NtUserSelectPalette(hdc, hpal, bForceBackground);
}
/*
* @implemented
*
*/
int
WINAPI
GetStretchBltMode(HDC hdc)
{
PDC_ATTR pdcattr;
/* Get the DC attribute */
pdcattr = GdiGetDcAttr(hdc);
if (pdcattr == NULL)
{
/* Don't set LastError here! */
return 0;
}
return pdcattr->lStretchBltMode;
}
/*
* @implemented
*/
int
WINAPI
SetStretchBltMode(
_In_ HDC hdc,
_In_ int iStretchMode)
{
INT iOldMode;
PDC_ATTR pdcattr;
HANDLE_METADC(INT, SetStretchBltMode, 0, hdc, iStretchMode);
/* Get the DC attribute */
pdcattr = GdiGetDcAttr(hdc);
if (pdcattr == NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
iOldMode = pdcattr->lStretchBltMode;
pdcattr->lStretchBltMode = iStretchMode;
// Wine returns an error here. We set the default.
if ((iStretchMode <= 0) || (iStretchMode > MAXSTRETCHBLTMODE)) iStretchMode = WHITEONBLACK;
pdcattr->jStretchBltMode = iStretchMode;
return iOldMode;
}
/*
* @implemented
*/
HFONT
WINAPI
GetHFONT(HDC hdc)
{
PDC_ATTR pdcattr;
/* Get the DC attribute */
pdcattr = GdiGetDcAttr(hdc);
if (pdcattr == NULL)
{
/* Don't set LastError here! */
return NULL;
}
/* Return the current font */
return pdcattr->hlfntNew;
}
HBITMAP
WINAPI
GdiSelectBitmap(
_In_ HDC hdc,
_In_ HBITMAP hbmp)
{
return NtGdiSelectBitmap(hdc, hbmp);
}
HBRUSH
WINAPI
GdiSelectBrush(
_In_ HDC hdc,
_In_ HBRUSH hbr)
{
PDC_ATTR pdcattr;
HBRUSH hbrOld;
HANDLE_METADC(HBRUSH, SelectBrush, NULL, hdc, hbr);
/* Get the DC attribute */
pdcattr = GdiGetDcAttr(hdc);
if (pdcattr == NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
/* Get the current brush. If it matches the new brush, we're done */
hbrOld = pdcattr->hbrush;
if (hbrOld == hbr)
return hbrOld;
/* Set the new brush and update dirty flags */
pdcattr->hbrush = hbr;
pdcattr->ulDirty_ |= DC_BRUSH_DIRTY;
return hbrOld;
}
HPEN
WINAPI
GdiSelectPen(
_In_ HDC hdc,
_In_ HPEN hpen)
{
PDC_ATTR pdcattr;
HPEN hpenOld;
HANDLE_METADC(HPEN, SelectPen, NULL, hdc, hpen);
/* Get the DC attribute */
pdcattr = GdiGetDcAttr(hdc);
if (pdcattr == NULL)
{
SetLastError(ERROR_INVALID_HANDLE);
return NULL;
}
/* Get the current pen. If it matches the new pen, we're done */
hpenOld = pdcattr->hpen;
if (hpenOld == hpen)
return hpenOld;
/* Set the new pen and update dirty flags */
pdcattr->ulDirty_ |= DC_PEN_DIRTY;
pdcattr->hpen = hpen;
return hpenOld;
}
HFONT
WINAPI
GdiSelectFont(
_In_ HDC hdc,
_In_ HFONT hfont)
{
PDC_ATTR pdcattr;
HFONT hfontOld;
HANDLE_METADC(HFONT, SelectFont, NULL, hdc, hfont);
/* Get the DC attribute */
pdcattr = GdiGetDcAttr(hdc);
if (pdcattr == NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
/* Get the current font. If it matches the new font, we're done */
hfontOld = pdcattr->hlfntNew;
if (hfontOld == hfont)
return hfontOld;
/* Set the new font and update dirty flags */
pdcattr->hlfntNew = hfont;
pdcattr->ulDirty_ &= ~SLOW_WIDTHS;
pdcattr->ulDirty_ |= DIRTY_CHARSET;
/* If the DC does not have a DIB section selected, try a batch command */
if (!(pdcattr->ulDirty_ & DC_DIBSECTION))
{
PGDIBSOBJECT pgO;
pgO = GdiAllocBatchCommand(hdc, GdiBCSelObj);
if (pgO)
{
pgO->hgdiobj = hfont;
return hfontOld;
}
}
/* We could not use the batch command, call win32k */
return NtGdiSelectFont(hdc, hfont);
}
/*
* @implemented
*
*/
HGDIOBJ
WINAPI
SelectObject(
_In_ HDC hdc,
_In_ HGDIOBJ hobj)
{
/* Fix up 16 bit handles */
hobj = GdiFixUpHandle(hobj);
if (!GdiValidateHandle(hobj))
{
return NULL;
}
/* Call the appropriate select function */
switch (GDI_HANDLE_GET_TYPE(hobj))
{
case GDILoObjType_LO_REGION_TYPE:
return (HGDIOBJ)ExtSelectClipRgn(hdc, hobj, RGN_COPY);
case GDILoObjType_LO_BITMAP_TYPE:
case GDILoObjType_LO_DIBSECTION_TYPE:
return GdiSelectBitmap(hdc, hobj);
case GDILoObjType_LO_BRUSH_TYPE:
return GdiSelectBrush(hdc, hobj);
case GDILoObjType_LO_PEN_TYPE:
case GDILoObjType_LO_EXTPEN_TYPE:
return GdiSelectPen(hdc, hobj);
case GDILoObjType_LO_FONT_TYPE:
return GdiSelectFont(hdc, hobj);
case GDILoObjType_LO_ICMLCS_TYPE:
return SetColorSpace(hdc, hobj);
case GDILoObjType_LO_PALETTE_TYPE:
SetLastError(ERROR_INVALID_FUNCTION);
default:
return NULL;
}
return NULL;
}
/***********************************************************************
* D3DKMTCreateDCFromMemory (GDI32.@)
*/
DWORD WINAPI D3DKMTCreateDCFromMemory( D3DKMT_CREATEDCFROMMEMORY *desc )
{
return NtGdiDdDDICreateDCFromMemory( desc );
}
DWORD WINAPI D3DKMTDestroyDCFromMemory( const D3DKMT_DESTROYDCFROMMEMORY *desc )
{
return NtGdiDdDDIDestroyDCFromMemory( desc );
}