⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 profile.cpp

📁 WDK 自带的xpsdrv filter之 color
💻 CPP
字号:
/*++

Copyright (c) 2005 Microsoft Corporation

All rights reserved.

THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

File Name:

   profile.cpp

Abstract:

   Profile class implementation. The profile class is responsible for loading and maintaining
   colo profile resources. The class provides methods for loading profiles from filename or
   URI and is responsible for limited caching based off the file name and the (WCS)OpenProfile
   options.

--*/

#include "precomp.h"
#include "debug.h"
#include "globals.h"
#include "xdstring.h"
#include "profile.h"
#include "wcsapiconv.h"

DWORD g_tagWCSProfile = 'MS00';

/*++

Routine Name:

    CProfile::CProfile

Routine Description:

    CProfile constructor

Arguments:

    None

Return Value:

    None

--*/
CProfile::CProfile() :
    m_hProfile(NULL),
    m_dwDesiredAccess(PROFILE_READ),
    m_dwShareMode(FILE_SHARE_READ),
    m_dwCreationMode(OPEN_EXISTING),
    m_dwWCSFlags(0)
{
}

/*++

Routine Name:

    CProfile::~CProfile

Routine Description:

    CProfile destructor

Arguments:

    None

Return Value:

    None

--*/
CProfile::~CProfile()
{
    FreeProfile();
}

/*++

Routine Name:

    CProfile::SetProfile

Routine Description:

    Sets the current profile from the fixed page using the specified resoure URI

Arguments:

    pFP   - Pointer to the fixed page interface
    szURI - URI to the ICC profile to load

Return Value:

    HRESULT
    S_OK - On success
    E_*  - On error

--*/
HRESULT
CProfile::SetProfile(
    __in IFixedPage* pFP,
    __in LPCWSTR     szURI
    )
{
    HRESULT hr = S_OK;

    if (SUCCEEDED(hr = CHECK_POINTER(pFP, E_POINTER)) &&
        SUCCEEDED(hr = CHECK_POINTER(szURI, E_POINTER)))
    {
        try
        {
            CStringXDW cstrKey;

            if (SUCCEEDED(hr = CreateProfileKey(szURI, NULL, NULL, &cstrKey)) &&
                (m_hProfile == NULL ||
                 m_cstrProfileKey != cstrKey))
            {
                FreeProfile();

                //
                // Get the read stream for the URI
                //
                CComPtr<IUnknown>          pPart(NULL);
                CComPtr<IPartColorProfile> pProfilePart(NULL);
                CComPtr<IPrintReadStream>  pRead(NULL);
                CComBSTR                   bstrProfileURI(szURI);

                ULONGLONG cbEnd = 0;

                //
                // Get the profile part and a read stream. Seek to the end to find the
                // size of the profile data
                //
                if (SUCCEEDED(hr = pFP->GetPagePart(bstrProfileURI, &pPart)) &&
                    SUCCEEDED(hr = pPart.QueryInterface(&pProfilePart)) &&
                    SUCCEEDED(hr = pProfilePart->GetStream(&pRead)) &&
                    SUCCEEDED(hr = pRead->Seek(0, STREAM_SEEK_END, &cbEnd)))
                {
                    //
                    // Allocate the buffer and copy
                    //
                    UINT  cbProfileData = static_cast<UINT>(cbEnd);
                    PBYTE pProfileData  = new BYTE[cbProfileData];

                    ULONG cbRead;
                    BOOL  bEOF = FALSE;
                    if (SUCCEEDED(hr = CHECK_POINTER(pProfileData, E_OUTOFMEMORY)) &&
                        SUCCEEDED(hr = pRead->Seek(0, STREAM_SEEK_SET, &cbEnd)) &&
                        SUCCEEDED(hr = pRead->ReadBytes(pProfileData, cbProfileData, &cbRead, &bEOF)))
                    {
                        if (cbProfileData != cbRead)
                        {
                            RIP("Failed to read all profile data\n");

                            hr = E_FAIL;
                        }
                    }

                    //
                    // Create the transform from the buffer
                    //
                    if (SUCCEEDED(hr))
                    {
                        PROFILE profile = {
                            PROFILE_MEMBUFFER,
                            pProfileData,
                            cbProfileData
                            };

                        if (SUCCEEDED(hr = OpenProfile(&profile, &m_hProfile)))
                        {
                            m_cstrProfileKey = cstrKey;
                        }
                    }

                    if (pProfileData != NULL)
                    {
                        delete[] pProfileData;
                        pProfileData = NULL;
                    }
                }
            }
        }
        catch (CXDException& e)
        {
            hr = e;
        }
    }

    ERR_ON_HR(hr);
    return hr;
}

/*++

Routine Name:

    CProfile::SetProfile

Routine Description:

    Sets a profile from the specified file name

Arguments:

    szFileName - File name of the profile to open

Return Value:

    HRESULT
    S_OK - On success
    E_*  - On error

--*/
HRESULT
CProfile::SetProfile(
    __in LPCWSTR szFileName
    )
{
    HRESULT hr = S_OK;

    if (SUCCEEDED(hr = CHECK_POINTER(szFileName, E_POINTER)))
    {
        try
        {
            CStringXDW cstrKey;

            if (SUCCEEDED(hr = CreateProfileKey(szFileName, NULL, NULL, &cstrKey)) &&
                (m_hProfile == NULL ||
                 m_cstrProfileKey != cstrKey))
            {
                FreeProfile();

                CStringXDW profileFileName(szFileName);
                PROFILE profile = {
                    PROFILE_FILENAME,
                    profileFileName.GetBuffer(),
                    profileFileName.GetLength() * sizeof(WCHAR)
                    };

                if (SUCCEEDED(hr = OpenProfile(&profile, &m_hProfile)))
                {
                    m_cstrProfileKey = cstrKey;
                }
            }
        }
        catch (CXDException& e)
        {
            hr = e;
        }
    }

    ERR_ON_HR(hr);
    return hr;
}

/*++

Routine Name:

    CProfile::SetProfile

Routine Description:

    Sets a color profile from memory

Arguments:

    szProfile - Name of the profile. This is used for caching puproses
    pBuffer   - Buffer containing the profile data
    cbBuffer  - Size of the buffer

Return Value:

    HRESULT
    S_OK - On success
    E_*  - On error

--*/
HRESULT
CProfile::SetProfile(
    __in                  LPWSTR szProfile,
    __in_bcount(cbBuffer) PBYTE  pBuffer,
    __in                  UINT   cbBuffer
    )
{
    HRESULT hr = S_OK;

    if (SUCCEEDED(hr = CHECK_POINTER(szProfile, E_POINTER)) &&
        SUCCEEDED(hr = CHECK_POINTER(pBuffer, E_POINTER)))
    {
        try
        {
            CStringXDW cstrKey;

            if (SUCCEEDED(hr = CreateProfileKey(szProfile, NULL, NULL, &cstrKey)) &&
                (m_hProfile == NULL ||
                 m_cstrProfileKey != cstrKey))
            {
                FreeProfile();

                PROFILE profile = {
                    PROFILE_MEMBUFFER,
                    pBuffer,
                    cbBuffer
                    };

                if (SUCCEEDED(hr = OpenProfile(&profile, &m_hProfile)))
                {
                    m_cstrProfileKey = cstrKey;
                }
            }
        }
        catch (CXDException& e)
        {
            hr = e;
        }
    }

    ERR_ON_HR(hr);
    return hr;
}

/*++

Routine Name:

    CProfile::GetProfileHandle

Routine Description:

    Retrieves the current profile handle

Arguments:

    phProfile - Pointer to a HPROFILE that accepts the current profile handle

Return Value:

    HRESULT
    S_OK - On success
    E_*  - On error

--*/
HRESULT
CProfile::GetProfileHandle(
    __out HPROFILE* phProfile
    )
{
    HRESULT hr = S_OK;

    if (SUCCEEDED(hr = CHECK_POINTER(phProfile, E_POINTER)))
    {
        *phProfile = NULL;
        if (SUCCEEDED(hr = CHECK_HANDLE(m_hProfile, E_PENDING)))
        {
            *phProfile = m_hProfile;
        }
    }

    ERR_ON_HR_EXC(hr, E_PENDING);
    return hr;
}

/*++

Routine Name:

    CProfile::IsWCSCompatible

Routine Description:

    Checks if the current profile is suitable for use with WCS

Arguments:

    pbWCSCompat - Pointer to BOOL the accepts the result

Return Value:

    HRESULT
    S_OK - On success
    E_*  - On error

--*/
HRESULT
CProfile::IsWCSCompatible(
    __out BOOL* pbWCSCompat
    )
{
    HRESULT hr = S_OK;

    if (SUCCEEDED(hr = CHECK_POINTER(pbWCSCompat, E_POINTER)) &&
        SUCCEEDED(hr = CHECK_HANDLE(m_hProfile, E_PENDING)))
    {
        //
        // Assume true as the GetColorProfileHeader documentation states: "This function
        // does not support Windows Color System (WCS) profiles CAMP, DMP, and GMMP.", therefore
        // if the profile is loaded and it is not ICC (i.e. no header) it should be WCS compatible
        //
        *pbWCSCompat = TRUE;

        PROFILEHEADER profileHeader = {0};
        if (GetColorProfileHeader(m_hProfile, &profileHeader))
        {
            if (profileHeader.phClass == CLASS_LINK ||
                profileHeader.phClass == CLASS_NAMED)
            {
                *pbWCSCompat = FALSE;
            }
        }
    }

    ERR_ON_HR(hr);
    return hr;
}


/*++

Routine Name:

    CProfile::GetProfileKey

Routine Description:

    Retrieves a key identifying the current profile. This is composed of the profile name
    and the options used to create the profile

Arguments:

    pcstrProfileKey - Pointer to a CStringXDW object that recieves the key

Return Value:

    HRESULT
    S_OK - On success
    E_*  - On error

--*/
HRESULT
CProfile::GetProfileKey(
    __out CStringXDW* pcstrProfileKey
    )
{
    HRESULT hr = S_OK;

    if (SUCCEEDED(hr = CHECK_POINTER(pcstrProfileKey, E_POINTER)))
    {
        try
        {
            *pcstrProfileKey = m_cstrProfileKey;
        }
        catch (CXDException& e)
        {
            hr = e;
        }
    }

    ERR_ON_HR(hr);
    return hr;
}

/*++

Routine Name:

    CProfile::operator==

Routine Description:

    CProfile equality operator

Arguments:

    cstrProfileKey - the key to compare against

Return Value:

    HRESULT
    S_OK - On success
    E_*  - On error

--*/
BOOL
CProfile::operator==(
    __in CONST CStringXDW& cstrProfileKey
    ) CONST
{
    BOOL bEqual = TRUE;

    try
    {
        if (m_cstrProfileKey != cstrProfileKey)
        {
            bEqual = FALSE;
        }
    }
    catch (CXDException&)
    {
        bEqual = FALSE;
    }

    return bEqual;
}

/*++

Routine Name:

    CProfile::operator!=

Routine Description:

    CProfile inequality operator

Arguments:

    cstrProfileKey - profile key to compare against

Return Value:

    HRESULT
    S_OK - On success
    E_*  - On error

--*/
BOOL
CProfile::operator!=(
    __in CONST CStringXDW& cstrProfileKey
    ) CONST
{
    return !operator==(cstrProfileKey);
}

/*++

Routine Name:

    CProfile::FreeProfile

Routine Description:

    Frees the current profile

Arguments:

    None

Return Value:

    None

--*/
VOID
CProfile::FreeProfile(
    VOID
    )
{
    try
    {
        m_cstrProfileKey.Empty();
    }
    catch (CXDException&)
    {
    }

    if (m_hProfile != NULL)
    {
        CloseColorProfile(m_hProfile);
        m_hProfile = NULL;
    }
}

/*++

Routine Name:

    CProfile::OpenProfile

Routine Description:

    Opens the current profile based off the current OS. Vista uses WCSOpenProfile while
    earlier Windows use OpenProfile

Arguments:

    pProfile  - Pointer to the profile structure used to open the profile
    phProfile - Pointer to a HPROFILE to recieve the opened profile handle

Return Value:

    HRESULT
    S_OK - On success
    E_*  - On error

--*/
HRESULT
CProfile::OpenProfile(
    __in  PROFILE*  pProfile,
    __out HPROFILE* phProfile
    )
{
    HRESULT hr = S_OK;

    if (SUCCEEDED(hr = CHECK_POINTER(pProfile, E_POINTER)) &&
        SUCCEEDED(hr = CHECK_POINTER(phProfile, E_POINTER)))
    {
        //
        // Get a handle to the color profile using WCS in Vista or the XP API in earlier operating systems
        //
        if (IsVista())
        {
            *phProfile = WcsOpenColorProfileXD(pProfile, NULL, NULL, m_dwDesiredAccess, m_dwShareMode, m_dwCreationMode, m_dwWCSFlags);
        }
        else
        {
            *phProfile = OpenColorProfile(pProfile, m_dwDesiredAccess, m_dwShareMode, m_dwCreationMode);
        }

        if (FAILED(CHECK_POINTER(*phProfile, E_POINTER)))
        {
            hr = GetLastErrorAsHResult();
        }
    }

    ERR_ON_HR(hr);
    return hr;
}

/*++

Routine Name:

    CProfile::CreateProfileKey

Routine Description:

    Creates a profile key based on the possible profile names used to construct the
    profile and the settings used to open the profile

Arguments:


    pszCDMP  - Device model profile name
    pszCAMP  - Color adjustment model profile name
    pszGMMP  - Gamut model profile name
    pcstrKey - Pointer to a CStringXDW that recieves the key

Return Value:

    HRESULT
    S_OK - On success
    E_*  - On error

--*/
HRESULT
CProfile::CreateProfileKey(
    __in     LPCWSTR     pszCDMP,
    __in_opt LPCWSTR     pszCAMP,
    __in_opt LPCWSTR     pszGMMP,
    __out    CStringXDW* pcstrKey
    )
{
    HRESULT hr = S_OK;

    if (SUCCEEDED(hr = CHECK_POINTER(pszCDMP, E_POINTER)) &&
        SUCCEEDED(hr = CHECK_POINTER(pcstrKey, E_POINTER)))
    {
        try
        {
            pcstrKey->Empty();
            pcstrKey->Append(pszCDMP);

            if (pszCAMP != NULL)
            {
                pcstrKey->Append(pszCAMP);
            }

            if (pszGMMP != NULL)
            {
                pcstrKey->Append(pszGMMP);
            }

            CStringXDW cstrOpenOptions;
            cstrOpenOptions.Format(L"%x%x%x%x", m_dwDesiredAccess, m_dwShareMode, m_dwCreationMode, m_dwWCSFlags);

            pcstrKey->Append(cstrOpenOptions);
            pcstrKey->MakeLower();
        }
        catch (CXDException& e)
        {
            hr = e;
        }
    }

    ERR_ON_HR(hr);
    return hr;
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -