Sample Code

Windows Driver Samples/ XPSDrv Driver and Filter Sample/ C++/ src/ filters/ color/ profile.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(std::nothrow) 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_reads_bytes_(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;
}

Our Services

  • What our customers say about us?

© 2011-2024 All Rights Reserved. Joya Systems. 4425 South Mopac Building II Suite 101 Austin, TX 78735 Tel: 800-DEV-KERNEL

Privacy Policy. Terms of use. Valid XHTML & CSS