Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1306 lines
25 KiB

/******************************Module*Header*******************************\
* Module Name:
*
* icmapi.cxx
*
* Abstract
*
* This module implements Integrated Color match API support
*
* Author:
*
* Mark Enstrom (marke) 9-27-93
*
* Copyright (c) 1993 Microsoft Corporation
\**************************************************************************/
#include "precomp.hxx"
//
// global ICM table for storing Color Transforms,
// These can probably be combined and protected by
// the same semaphore
//
extern PCOLORSPACE gpStockColorSpace;
extern HANDLE ghDefaultICM;
extern PICMDLL pGlobalIcmDllTable;
extern HPALETTE hForePalette;
#if DBG
extern ULONG IcmDebugLevel;
#endif
typedef ULONG (*PFN_VERPROC)(UINT);
#define INIT_NUM_OF_LCS 10
#define HEAP_OVERHEAD 100
#define INIT_NUM_XFORMS 5
#define INIT_XFORM_ARRAY_SIZE INIT_NUM_XFORMS * (sizeof(COLOR_TRANSFORM))
VOID
WCHAR_TO_UCHAR(
PUCHAR pu,
PUCHAR pw
)
{
//
// convert wide character to ascii
//
pw++;
while (*pw != '0') {
*pu++ = *pw;
pw += 2;
}
//
// terminate pu
//
*pu = '0';
}
VOID
UCHAR_TO_WCHAR(
PUCHAR pw,
PUCHAR pu
)
{
//
// convert ascii character to wide char
//
while (*pu != '0')
{
*pw = 0;
*(pw+1) = *pu;
pw += 2;
pu++;
}
//
// terminate pw
//
*((PUSHORT)pw) = 0x0000;
}
/******************************Public*Routine******************************\
*
* Routine Name
*
* InitICMObjects
*
* Routine Description:
*
* Force re-realization for DC objects due to change in ICM state
*
* Arguments:
*
* hdc
*
* Return Value:
*
* None
*
\**************************************************************************/
VOID
InitICMObjects(
HDC hdc
)
{
ASSERTGDI(FALSE,"Shouldn't be calling ICM functions");
#if DBG
if (IcmDebugLevel >= 2)
{
DbgPrint("InitICMObjects\n");
}
#endif
DCOBJ dco(hdc);
if (dco.bValid())
{
//
// ICM turned on or off, re-realize all objects/colors
//
XEPALOBJ palDstDC(dco.ppal());
palDstDC.vUpdateTime();
//
// force re-realization of palette, do not change
// foreground status
//
GreSelectPalette(hdc,(HPALETTE)dco.hpal(),TRUE);
//
// force re-realization
//
// Grab the palette semaphore which stops any palettes from being selected
// in or out.
//
//{
//
// //
// // We have the palette semaphore and all the DC's exclusively locked. Noone else
// // can be accessing the translates because you must hold one of those things to
// // access them. So we can delete the translates.
// //
//
// palDstDC.vMakeNoXlate();
//
//
// PDEVOBJ po(dco.hdev());
// XEPALOBJ palSurf(po.ppalSurf());
// palSurf.vUpdateTime();
// }
GreRealizePalette(hdc);
GreSetTextColor(hdc,GreGetTextColor(hdc));
GreSetBkColor(hdc,GreGetBkColor(hdc));
dco.ulDirty(dco.ulDirty() | DIRTY_BRUSHES);
}
}
/******************************Public*Routine******************************\
*
* Routine Name
*
* GreCreateColorSpace
*
* Routine Description:
*
* Create a color space object
*
* Arguments:
*
* lpLogColorSpace - Logical Color space
*
* Return Value:
*
* Handle to ColorSpace object or NULL on failure
*
\**************************************************************************/
HCOLORSPACE
APIENTRY
GreCreateColorSpace(
LPLOGCOLORSPACEW pLogColorSpace
)
{
ASSERTGDI(FALSE,"Shouldn't be calling ICM functions");
BOOL bStatus;
HCOLORSPACE hReturn = (HCOLORSPACE)NULL;
#if DBG
if (IcmDebugLevel >= 2)
{
DbgPrint("CreateColorSpaceInternal: pLogColorSpace = %lx\n",pLogColorSpace);
}
#endif
if (pLogColorSpace != (LPLOGCOLORSPACEW)NULL) {
if ((pLogColorSpace->lcsVersion != 0x400))
{
WARNING("GreCreateColorSpace failed, wrong version\n");
//
// set last error?
//
return((HCOLORSPACE) 0);
}
//
// Try to create new internal color space object
//
COLORSPACEMEM ColorSpaceMem;
bStatus = ColorSpaceMem.bCreateColorSpace(pLogColorSpace);
if (bStatus) {
ColorSpaceMem.vKeepIt();
//
// set owner
//
ColorSpaceMem.vSetPID(W32GetCurrentPID());
//
// !!!add color space to global list
//
hReturn = ColorSpaceMem.pColorSpace->hColorSpace();
}
}
return(hReturn);
}
/******************************Public*Routine******************************\
*
* Routine Name
*
* GreDeleteColorSpace
*
* Routine Description:
*
* Delete a color space object
*
* Arguments:
*
* hColorSpace - Handle of Logical Color Space to delete
*
* Return Value:
*
* BOOL status
*
\**************************************************************************/
BOOL
APIENTRY
GreDeleteColorSpace(
HCOLORSPACE hColorSpace
)
{
ASSERTGDI(FALSE,"Shouldn't be calling ICM functions");
BOOL bRet;
COLORSPACEREF ColorSpace;
//
// Try to remove handle from hmgr. This will fail if the color space
// is locked down on any threads or if it has been marked global or
// un-deleteable.
//
#if DBG
if (IcmDebugLevel >= 2)
{
DbgPrint("GreDeleteColorSpace %lx\n",hColorSpace);
}
#endif
bRet = ColorSpace.bRemoveColorSpace(hColorSpace);
return(bRet);
}
/******************************Public*Routine******************************\
*
* Routine Name
*
* GreSetColorSpace
*
* Routine Description:
*
* Set Color Space for DC
*
* Arguments:
*
* hdc - handle of dc
* hColorSpace - handle of color space
*
* Return Value:
*
* BOOL Status
*
\**************************************************************************/
BOOL
APIENTRY
GreSetColorSpace(
HDC hdc,
HCOLORSPACE hColorSpace
)
{
ASSERTGDI(FALSE,"Shouldn't be calling ICM functions");
BOOL bReturn = FALSE;
//
// validate the DC
//
DCOBJ dco(hdc);
PCOLORXFORM pColorTrans;
if (dco.bValid())
{
//
// its a valid DC, now validate HColorSpace
//
COLORSPACEREF ColorSpaceSel(hColorSpace);
if (ColorSpaceSel.bValid())
{
//
// dec ref count of old color space if not default
//
if (dco.pdc->GetPColorSpace() != gpStockColorSpace)
{
DEC_SHARE_REF_CNT((PCOLORSPACE)dco.pdc->GetPColorSpace());
}
//
// set color space handle in dc
//
dco.pdc->SetColorSpace(hColorSpace);
dco.pdc->SetPColorSpace(ColorSpaceSel.pColorSpace);
//
// up the ref count of the selected color space
//
INC_SHARE_REF_CNT(ColorSpaceSel.pColorSpace);
//
// If Icm is enabled then get a color transform to match this
// color space
//
if (dco.pdc->GetICMMode() & DC_DIC_ON) {
//
// create a transform for the newly selected color space
//
//
// if C1_ICM them loog in device block for hooked ICMDLL calls
// !!! <not yet implemented>
//
bReturn = CreateColorTransform((HANDLE)NULL,hdc,(HDC)NULL);
}
}
InitICMObjects(hdc);
}
return(bReturn);
}
/******************************Public*Routine******************************\
*
* Routine Name
*
* GreGetColorSpace
*
* Routine Description:
*
* Get Color Space for DC
*
* Arguments:
*
* hdc - handle of dc
*
* Return Value:
*
* HCOLORSPACE or NULL
*
\**************************************************************************/
HCOLORSPACE
APIENTRY
GreGetColorSpace(
HDC hdc
)
{
ASSERTGDI(FALSE,"Shouldn't be calling ICM functions");
HCOLORSPACE hReturn = NULL;
//
// validate the DC
//
DCOBJ dco(hdc);
#if DBG
if (IcmDebugLevel >= 2)
{
DbgPrint("GreGetColorSpaceInternal\n");
}
#endif
if (dco.bValid())
{
//
// its a valid DC, now get the HCOLORSPACE
//
hReturn = (HCOLORSPACE)dco.pdc->GetColorSpace();
}
return(hReturn);
}
/******************************Public*Routine******************************\
*
* Routine Name
*
* GreGetLogColorSpace
*
* Routine Description:
*
* Get Logical Color Space for DC
*
* Arguments:
*
* hColorSpace - handle of ColorSpace
* pBuffer - Buffer to receive information
* nSize - Maximum size of buffer
*
* Return Value:
*
* HCOLORSPACE or NULL
*
\**************************************************************************/
BOOL
APIENTRY
GreGetLogColorSpace(
HCOLORSPACE hColorSpace,
LPLOGCOLORSPACEW pBuffer,
DWORD nSize
)
{
ASSERTGDI(FALSE,"Shouldn't be calling ICM functions");
BOOL bRet = FALSE;
#if DBG
if (IcmDebugLevel >= 2)
{
DbgPrint("GreGetLogColorSpaceInternal\n");
}
#endif
COLORSPACEREF ColorSpaceSel(hColorSpace);
if (ColorSpaceSel.bValid())
{
//
// copy out info
//
if (nSize > sizeof(LOGCOLORSPACE)) {
nSize = sizeof(LOGCOLORSPACE);
}
memcpy(pBuffer,ColorSpaceSel.pColorSpace->pGetLogBase(),nSize);
bRet = TRUE;
ColorSpaceSel.vAltUnlock();
}
return(bRet);
}
/******************************Public*Routine******************************\
*
* Routine Name
*
* GreSetICMMode
*
* Routine Description:
*
* Set ICM mode for DC
*
* Arguments:
*
* hdc - HDC to change
* Mode - mode to switch to
*
* Return Value:
*
* BOOL Status
*
\**************************************************************************/
BOOL
APIENTRY
GreSetICMMode(
HDC hdc,
int Mode
)
{
ASSERTGDI(FALSE,"Shouldn't be calling ICM functions");
//
// Get the DC
//
#if DBG
if (IcmDebugLevel >= 2)
{
DbgPrint("GreSetICMMode: hDC = 0x%lx : Mode = 0x%02lx\n",hdc,Mode);\
}
#endif
DCOBJ dco(hdc);
BOOL bStatus;
BOOL bChangeState = FALSE;
LONG lRet = ICM_OFF;
if (!dco.bValid())
{
WARNING("Invalid DC in call to GreSetICMMode\n");
}
else
{
LONG PrevICMMode = dco.pdc->GetICMMode();
//
// is this just a query?
//
if (Mode == ICM_QUERY)
{
if (PrevICMMode & DC_DIC_ON)
{
lRet = ICM_ON;
}
}
else
{
//
// In the printer set-up dialog box the user can turn ICM for the print
// job. However applications may want to overide this. They can do so
// in two ways. 1) Get the devmode and turn ICM off in it before
// createdc. 2) Make a seticmmode call to turn ICM on or off, this
// tells the system to turn forcing off.
//
//
// turn DC_ICM_FORCED_ON off in the DC, if the Mode passed in
// indicates FORCE_ON, set DC_ICM_FORCED_ON back on and set
// mode to just ICM_ON
//
// This is all for exact chicago compatibility.
//
PrevICMMode &= ~DC_ICM_FORCED_ON;
if (Mode == ICM_ON_FORCED) {
PrevICMMode |= DC_ICM_FORCED_ON;
Mode = ICM_ON;
}
//
// take action based on previous state of ICM and next state
//
if (PrevICMMode & DC_DIC_ON)
{
//
// ICM was already on
//
if (Mode == ICM_OFF)
{
//
// ICM was on, now being turned off
//
PrevICMMode &= ~(DC_DIC_ON | DC_ICM_CMYK);
dco.pdc->SetICMMode(PrevICMMode);
dco.pdc->hcmXform(NULL);
InitICMObjects(hdc);
lRet = ICM_OFF;
}
else if (Mode == ICM_ON)
{
//
// ICM Was on, still on
//
lRet = ICM_ON;
}
}
else
{
//
// ICM was off
//
if (Mode == ICM_ON) {
//
// ICM is turned on
//
PrevICMMode |= DC_DIC_ON;
dco.pdc->SetICMMode(PrevICMMode);
//
// If the color transform field from the DC is not NULL,
// this DC is using a device driver that supports ICM
//
PCOLORXFORM pDcColorXform = (PCOLORXFORM)dco.pdc->GetColorTransform();
HANDLE hModule = (HANDLE)NULL;
if (pDcColorXform != (PCOLORXFORM)NULL) {
//
// If the device has C1_ICM flag set them
// get pLDevice->hModule. This is the driver's entry
// in the ICMDLL table
//
// !!! <Not yet implemented>
//
}
BOOL bStatus = CreateColorTransform(hModule,hdc,(HDC)NULL);
if (!bStatus) {
//
// couldn't create transform, turn off ICM
//
WARNING("CreateColorTransform fails\n");
PrevICMMode &= ~(DC_DIC_ON | DC_ICM_CMYK | DC_ICM_FORCED_ON);
dco.pdc->SetICMMode(PrevICMMode);
dco.pdc->hcmXform(NULL);
lRet = ICM_OFF;
}
else
{
//
// initialize all GDI objects with new ICM setting
//
InitICMObjects(hdc);
lRet = ICM_ON;
}
}
}
}
}
return(lRet);
}
/******************************Public*Routine******************************\
*
* Routine Name
*
* GreGetColorProfile
*
* Routine Description:
*
* retreive the current color profile of the specified DC
*
* Arguments:
*
* hdc - Handle of DC
*
* Return Value:
*
* Pointer to profile if successful, otherwise NULL
*
\**************************************************************************/
LPCSTR
APIENTRY
GreGetColorProfile(
HDC hdc
)
{
ASSERTGDI(FALSE,"Shouldn't be calling ICM functions");
LPCSTR lpcRet = (LPCSTR)NULL;
DCOBJ dco(hdc);
if (dco.bValid())
{
//
// lpcRet = dco.pdc->GetProfile();
//
} else {
WARNING("Passed in invalid hdc\n");
}
return(lpcRet);
}
/******************************Public*Routine******************************\
*
* Routine Name
*
* GreSetColorProfile
*
* Routine Description:
*
* Set the color profile for the given DC
*
* Arguments:
*
* hdc - Handle of DC
* lpFileName - Name of PROFILE
*
* Return Value:
*
* BOOL Status
*
\**************************************************************************/
BOOL
APIENTRY
GreSetColorProfile(
HDC hdc,
LPCSTR lpFileName
)
{
ASSERTGDI(FALSE,"Shouldn't be calling ICM functions");
BOOL bRet = FALSE;
DCOBJ dco(hdc);
if (dco.bValid())
{
//
// bRet = dco.pdc->SetProfile(lpFileName);
//
} else {
WARNING("Passed in invalid hdc\n");
}
return(bRet);
}
/******************************Public*Routine******************************\
*
* Routine Name
*
* GreCheckColorsInGamut
*
* Routine Description:
*
* Determine if the RGB(s) lie(s) in the output GAMUT of the device
*
* Arguments:
*
* hdc - Handle of DC
* lpaRGBQuad - array of RGBQUADs to check
* dlpBuffer - buffer to put results
* nCount - Count of elements in array
*
* Return Value:
*
* BOOL Status
*
\**************************************************************************/
BOOL
APIENTRY
GreCheckColorsInGamut(
HDC hdc,
LPVOID lpRGBQuad,
LPVOID dlpBuffer,
DWORD nCount
)
{
ASSERTGDI(FALSE,"Shouldn't be calling ICM functions");
BOOL bRet = FALSE;
DCOBJ dco(hdc);
if (dco.bValid())
{
//
// retrieve color transform information from DC
//
PFN_CM_CHECK_GAMUT pfnCheck;
PCOLORXFORM pColorTransform = (PCOLORXFORM)dco.pdc->GetColorTransform();
if (pColorTransform != (PCOLORXFORM)NULL)
{
//
// Get ICM DLL call information from the color transform
//
pfnCheck = (PFN_CM_CHECK_GAMUT)pColorTransform->pIcmDll->CMRGBsInGamut;
if (pfnCheck != (PFN_CM_CHECK_GAMUT)NULL) {
//
// call ICM DLL to check RGBs
//
bRet = pfnCheck(
pColorTransform->hXform,
lpRGBQuad,
dlpBuffer,
nCount
);
}
else
{
WARNING("Device has ICM Enabled but CMRGBsInGamut is NULL\n");
}
} else {
WARNING("DC has ICM enabled but NULL pColorTransform\n");
}
} else {
WARNING("GreCheckColorsInGamut passed an invalid hdc\n");
}
return(bRet);
}
/******************************Public*Routine******************************\
*
* Routine Name
*
* GreColorMatchToTarget
*
* Routine Description:
*
* Call ICM color matcher to match src to target
*
* Arguments:
*
* hdc - Handle of DC source
* hdcTarget - Handle of DC target
* DWORD - dwAction
*
* Return Value:
*
* BOOL Status
*
\**************************************************************************/
BOOL
APIENTRY
GreColorMatchToTarget(
HDC hdc,
HDC hdcTarget,
DWORD dwAction
)
{
ASSERTGDI(FALSE,"Shouldn't be calling ICM functions");
return(TRUE);
}
/******************************Public*Routine******************************\
*
* Routine Name
*
* GreGetICMProfile
*
* Routine Description:
*
* Get icm profile
*
* Arguments:
*
* hdc - Handle of DC source
* szBuffer - Size of return buffer
* pBuffer - Buffer for return profiles
*
* Return Value:
*
* BOOL Status
*
\**************************************************************************/
BOOL
APIENTRY
GreGetICMProfile(
HDC hdc,
DWORD szBuffer,
LPWSTR pBuffer
)
{
ASSERTGDI(FALSE,"Shouldn't be calling ICM functions");
BOOL bStatus = FALSE;
//
// !!! This is a real mess, must only use WCHAR, but chicago icmutils.cxx
// uses UCHAR!!!
//
// check for valid DC
//
DCOBJ dcoTrg(hdc);
if (dcoTrg.bValid())
{
PVOID pvDeviceProfile = pvGetDeviceProfile(dcoTrg);
if (pvDeviceProfile != (PVOID)NULL) {
//
// if this string fits in the user buffer, return it
//
LONG lStrLen = wcslen((PWCHAR)pvDeviceProfile);
if ((DWORD)lStrLen <= szBuffer)
{
#if DBG
if (IcmDebugLevel >= 2)
{
DbgPrint("GreGetICMProfile returns %s\n",pvDeviceProfile);
}
#endif
wcscpy(pBuffer,(WCHAR *)pvDeviceProfile);
bStatus = TRUE;
}
}
}
return(bStatus);
}
/******************************Public*Routine******************************\
*
* Routine Name
*
* GreSetICMProfile
*
* Routine Description:
*
* Set icm profile
*
* Arguments:
*
* hdc - Handle of DC source
* pszFileName - name of profile file
*
* Return Value:
*
* BOOL Status
*
\**************************************************************************/
BOOL
APIENTRY
GreSetICMProfile(
HDC hdc,
LPWSTR pszFileName
)
{
ASSERTGDI(FALSE,"Shouldn't be calling ICM functions");
BOOL bStatus = FALSE;
//
// make sure string is valid
//
if (pszFileName != (PWSTR)NULL) {
//
// make sure DC is valid
//
DCOBJ dco(hdc);
if (dco.bValid())
{
//
// make copy for keeps
//
LPWSTR pvNewProfile = (LPWSTR)PALLOCNOZ(wcslen(pszFileName) * sizeof(WCHAR), 'mciG');
if (pvNewProfile != (PWSTR)NULL) {
//
// free old profile string
//
PVOID pvOld = (PVOID)dco.pdc->GetDeviceProfile();
if (pvOld != (PVOID)NULL) {
VFREEMEM(pvOld);
}
wcscpy(pvNewProfile,pszFileName);
dco.pdc->SetDeviceProfile(pvNewProfile);
bStatus = TRUE;
}
}
}
return(bStatus);
}
/******************************Public*Routine******************************\
*
* Routine Name
*
* EnumICMProfiles
*
* Routine Description:
*
* Somehow call-back to app to enum profiles
*
* Arguments:
*
* hdc - Handle of DC source
* lpEnumGamutMatchProc - proc address to call back...
* lParam - who knows?
*
* Return Value:
*
* BOOL Status
*
\**************************************************************************/
int
WINAPI
GreEnumICMProfiles(
HDC hdc,
ICMENUMPROCW lpEnumGamutMatchProc,
LPARAM lParam
)
{
ASSERTGDI(FALSE,"Shouldn't be calling ICM functions");
return(0);
}
/******************************Public*Routine******************************\
*
* Routine Name
*
* GreGetDeviceGammaRamp
*
* Routine Description:
*
* Return gamma ramp in use by output device
*
* Arguments:
*
* hdc - Handle of DC source
* lpGammaRamp - pointer to ramp
*
* Return Value:
*
* BOOL Status
*
\**************************************************************************/
BOOL
GreGetDeviceGammaRamp(
HDC hdc,
LPVOID lpGammaRamp
)
{
return(TRUE);
}
/******************************Public*Routine******************************\
*
* Routine Name
*
* GreSetDeviceGammaRamp
*
* Routine Description:
*
* Set gamma ramp in use by output device
*
* Arguments:
*
* hdc - Handle of DC source
* lpGammaRamp - pointer to ramp
*
* Return Value:
*
* BOOL Status
*
\**************************************************************************/
BOOL
WINAPI
GreSetDeviceGammaRamp(
HDC hdc,
LPVOID lpGammaRamp
)
{
ASSERTGDI(FALSE,"Shouldn't be calling ICM functions");
return(TRUE);
}
/******************************Public*Routine******************************\
*
* Routine Name
*
* GreDeleteColorTransform
*
* Routine Description:
*
* Deletes a color transform
*
* Arguments:
*
* hxform - handle of color transform
*
* Return Value:
*
* BOOL Status
*
\**************************************************************************/
VOID
WINAPI
GreDeleteColorTransform(
HANDLE hxform
)
{
#if DBG
if (IcmDebugLevel >= 2)
{
DbgPrint("GreDeleteColorTransform %lx\n",hxform);
}
#endif
bDeleteColorTransform(hxform);
}
/******************************Public*Routine******************************\
*
* Routine Name
*
* GreDeleteIcmDll
*
* Routine Description:
*
* Deletes a ICMDLL
*
* Arguments:
*
* hIcmDll - handle of ICM DLL
*
* Return Value:
*
* BOOL Status
*
\**************************************************************************/
VOID
WINAPI
GreDeleteIcmDll(
HANDLE hIcmDll
)
{
ASSERTGDI(FALSE,"Shouldn't be calling ICM functions");
ICMDLLREF IcmRef(hIcmDll);
#if DBG
if (IcmDebugLevel >= 2)
{
DbgPrint("GreDeleteIcmDll %lx\n",hIcmDll);
}
#endif
IcmRef.pIcmDll->vRemoveFromList();
IcmRef.bRemoveIcmDll(hIcmDll);
}