mirror of https://github.com/lianthony/NT4.0
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.
1798 lines
48 KiB
1798 lines
48 KiB
/****************************Module*Header******************************\
|
|
* Module Name: PROFMAN.C
|
|
*
|
|
* Module Descripton: Profile management functions.
|
|
*
|
|
* Warnings:
|
|
*
|
|
* Issues:
|
|
*
|
|
* Public Routines:
|
|
*
|
|
* Created: 2 May 1996
|
|
* Author: Srinivasan Chandrasekar [srinivac]
|
|
*
|
|
* Copyright (c) 1996, 1997 Microsoft Corporation
|
|
\***********************************************************************/
|
|
|
|
#include "mscms.h"
|
|
|
|
/*
|
|
* Local functions
|
|
*/
|
|
ULONG InternalHandleColorProfiles(PTSTR, DEVTYPE, PTSTR*,
|
|
DWORD, PPROFILECALLBACK, PVOID, PROFILEOP);
|
|
BOOL InternalCreateNewColorProfileSet(PTSTR, DEVTYPE);
|
|
BOOL GetPrinterModelName(PTSTR, PTSTR);
|
|
BOOL AddOrRemovePrinterProfile(HKEY, PTSTR, PTSTR, BOOL);
|
|
ULONG EnumerateProfiles(HKEY, PPROFILECALLBACK, PVOID);
|
|
void GetManuAndModelIDs(PTSTR, PTSTR, PTSTR);
|
|
BOOL AddOrRemoveProfileEntry(HKEY, PTSTR, BOOL);
|
|
BOOL IsMatch(PSEARCHTYPE, PPROFILEHEADER);
|
|
ULONG InternalSearchColorProfiles(PSEARCHTYPE, PPROFILECALLBACK, PVOID);
|
|
BOOL InternalGetSystemColorProfile(DWORD, PTSTR, PDWORD);
|
|
ULONG WINAPI fnCallback(PWSTR, PVOID);
|
|
|
|
/******************************************************************************
|
|
*
|
|
* AddColorProfiles
|
|
*
|
|
* Function:
|
|
* These are the ANSI & Unicode wrappers for InternalAddColorProfiles.
|
|
* Please see InternalAddColorProfiles for more details on this function.
|
|
*
|
|
* Arguments:
|
|
* pDevicename - name identifying device
|
|
* devType - type of device
|
|
* papProfilenames - pointer to array of profiles to add
|
|
* nCount - number of profiles in array
|
|
*
|
|
* Returns:
|
|
* TRUE if successful, NULL otherwise
|
|
*
|
|
******************************************************************************/
|
|
|
|
#ifdef UNICODE // Windows NT versions
|
|
|
|
BOOL WINAPI AddColorProfilesA(
|
|
PSTR pDevicename,
|
|
DEVTYPE devType,
|
|
PSTR *papProfilenames,
|
|
DWORD nCount
|
|
)
|
|
{
|
|
PWSTR *pwszProfiles;
|
|
DWORD i;
|
|
BOOL rc;
|
|
WCHAR wszDevicename[CCHDEVICENAME];
|
|
|
|
/*
|
|
* Validate parameters before we touch them
|
|
*/
|
|
if (!papProfilenames ||
|
|
nCount <= 0 ||
|
|
IsBadReadPtr(papProfilenames, sizeof(PTSTR)*nCount))
|
|
{
|
|
WARNING(("ICM: Invalid parameter to AddColorProfiles\n"));
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Convert device name to Unicode
|
|
*/
|
|
if (!MultiByteToWideChar(CP_ACP, 0, pDevicename, -1, wszDevicename, CCHDEVICENAME))
|
|
{
|
|
WARNING(("Error converting to Unicode device name\n"));
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Allocate memory for an array of pointers to Unicode strings and convert
|
|
* incoming profile names to Unicode
|
|
*/
|
|
pwszProfiles = (PWSTR *)GlobalAllocPtr(GHND, nCount*sizeof(PWSTR));
|
|
if (!pwszProfiles)
|
|
{
|
|
WARNING(("Error allocating memory for Unicode profile names\n"));
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return FALSE;
|
|
}
|
|
|
|
rc = TRUE;
|
|
for (i=0; i<nCount; i++)
|
|
{
|
|
pwszProfiles[i] = (PWSTR)GlobalAllocPtr(GHND, (lstrlenA(papProfilenames[i]) + 1)*sizeof(WCHAR));
|
|
if (!pwszProfiles[i])
|
|
{
|
|
WARNING(("Error allocating memory for Unicode profile names\n"));
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
rc = FALSE;
|
|
break;
|
|
}
|
|
if (!MultiByteToWideChar(CP_ACP, 0, (PSTR)papProfilenames[i], -1,
|
|
pwszProfiles[i], lstrlenA(papProfilenames[i]) + 1))
|
|
{
|
|
WARNING(("Error converting to Unicode profile name\n"));
|
|
rc = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* If everything is fine, call the internal Unicode function
|
|
*/
|
|
if (rc)
|
|
{
|
|
rc = (BOOL)InternalHandleColorProfiles(wszDevicename, devType,
|
|
pwszProfiles, nCount, NULL, NULL, ADDPROFILES);
|
|
}
|
|
|
|
/*
|
|
* Free all memory before leaving
|
|
*/
|
|
for (i=0; i<nCount; i++)
|
|
{
|
|
if (pwszProfiles[i])
|
|
{
|
|
GlobalFreePtr(pwszProfiles[i]);
|
|
}
|
|
}
|
|
if (pwszProfiles)
|
|
{
|
|
GlobalFreePtr(pwszProfiles);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
BOOL WINAPI AddColorProfilesW(
|
|
PWSTR pDevicename,
|
|
DEVTYPE devType,
|
|
PWSTR *papProfilenames,
|
|
DWORD nCount
|
|
)
|
|
{
|
|
/*
|
|
* Internal function is Unicode in Windows NT, call it directly.
|
|
*/
|
|
return (BOOL)InternalHandleColorProfiles(pDevicename, devType,
|
|
papProfilenames, nCount, NULL, NULL, ADDPROFILES);
|
|
}
|
|
|
|
#else // Windows 95 versions
|
|
|
|
BOOL WINAPI AddColorProfilesA(
|
|
PSTR pDevicename,
|
|
DEVTYPE devType,
|
|
PSTR *papProfilenames,
|
|
DWORD nCount
|
|
)
|
|
{
|
|
/*
|
|
* Internal function is ANSI in Windows 95, call it directly.
|
|
*/
|
|
return (BOOL)InternalHandleColorProfiles(pDevicename, devType,
|
|
papProfilenames, nCount, NULL, NULL, ADDPROFILES);
|
|
}
|
|
|
|
|
|
BOOL WINAPI AddColorProfilesW(
|
|
PWSTR pDevicename,
|
|
DEVTYPE devType,
|
|
PWSTR *papProfilenames,
|
|
DWORD nCount
|
|
)
|
|
{
|
|
/*
|
|
* Unicode version not supported under Windows 95
|
|
*/
|
|
SetLastError(ERROR_NOT_SUPPORTED);
|
|
return FALSE;
|
|
}
|
|
|
|
#endif // ! UNICODE
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* RemoveColorProfiles
|
|
*
|
|
* Function:
|
|
* These are the ANSI & Unicode wrappers for InternalRemoveColorProfiles.
|
|
* Please see InternalRemoveColorProfiles for more details on this function.
|
|
*
|
|
* Arguments:
|
|
* pDevicename - name identifying device
|
|
* devType - type of device
|
|
* papProfilenames - pointer to array of profiles to remove
|
|
* nCount - number of profiles in array
|
|
*
|
|
* Returns:
|
|
* TRUE if successful, NULL otherwise
|
|
*
|
|
******************************************************************************/
|
|
|
|
#ifdef UNICODE // Windows NT versions
|
|
|
|
BOOL WINAPI RemoveColorProfilesA(
|
|
PSTR pDevicename,
|
|
DEVTYPE devType,
|
|
PSTR *papProfilenames,
|
|
DWORD nCount
|
|
)
|
|
{
|
|
PWSTR *pwszProfiles;
|
|
DWORD i;
|
|
BOOL rc;
|
|
WCHAR wszDevicename[CCHDEVICENAME];
|
|
|
|
/*
|
|
* Validate parameters before we touch them
|
|
*/
|
|
if (!papProfilenames ||
|
|
nCount <= 0 ||
|
|
IsBadReadPtr(papProfilenames, sizeof(PTSTR)*nCount))
|
|
{
|
|
WARNING(("ICM: Invalid parameter to RemoveColorProfiles\n"));
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Convert device name to Unicode
|
|
*/
|
|
if (!MultiByteToWideChar(CP_ACP, 0, pDevicename, -1, wszDevicename, CCHDEVICENAME))
|
|
{
|
|
WARNING(("Error converting to Unicode device name\n"));
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Allocate memory for an array of pointers to Unicode strings and convert
|
|
* incoming profile names to Unicode
|
|
*/
|
|
pwszProfiles = (PWSTR *)GlobalAllocPtr(GHND, nCount*sizeof(PWSTR));
|
|
if (!pwszProfiles)
|
|
{
|
|
WARNING(("Error allocating memory for Unicode profile names\n"));
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return FALSE;
|
|
}
|
|
|
|
rc = TRUE;
|
|
for (i=0; i<nCount; i++)
|
|
{
|
|
pwszProfiles[i] = (PWSTR)GlobalAllocPtr(GHND, (lstrlenA(papProfilenames[i]) + 1)*sizeof(WCHAR));
|
|
if (!pwszProfiles[i])
|
|
{
|
|
WARNING(("Error allocating memory for Unicode profile names\n"));
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
rc = FALSE;
|
|
break;
|
|
}
|
|
if (!MultiByteToWideChar(CP_ACP, 0, (PSTR)papProfilenames[i], -1,
|
|
pwszProfiles[i], lstrlenA(papProfilenames[i]) + 1))
|
|
{
|
|
WARNING(("Error converting to Unicode profile name\n"));
|
|
rc = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* If everything is fine, call the internal Unicode function
|
|
*/
|
|
if (rc)
|
|
{
|
|
rc = (BOOL)InternalHandleColorProfiles(wszDevicename, devType,
|
|
pwszProfiles, nCount, NULL, NULL, REMOVEPROFILES);
|
|
}
|
|
|
|
/*
|
|
* Free all memory before leaving
|
|
*/
|
|
for (i=0; i<nCount; i++)
|
|
{
|
|
if (pwszProfiles[i])
|
|
{
|
|
GlobalFreePtr(pwszProfiles[i]);
|
|
}
|
|
}
|
|
if (pwszProfiles)
|
|
{
|
|
GlobalFreePtr(pwszProfiles);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
BOOL WINAPI RemoveColorProfilesW(
|
|
PWSTR pDevicename,
|
|
DEVTYPE devType,
|
|
PWSTR *papProfilenames,
|
|
DWORD nCount
|
|
)
|
|
{
|
|
/*
|
|
* Internal function is Unicode in Windows NT, call it directly.
|
|
*/
|
|
return (BOOL)InternalHandleColorProfiles(pDevicename, devType,
|
|
papProfilenames, nCount, NULL, NULL, REMOVEPROFILES);
|
|
}
|
|
|
|
#else // Windows 95 versions
|
|
|
|
BOOL WINAPI RemoveColorProfilesA(
|
|
PSTR pDevicename,
|
|
DEVTYPE devType,
|
|
PSTR *papProfilenames,
|
|
DWORD nCount
|
|
)
|
|
{
|
|
/*
|
|
* Internal function is ANSI in Windows 95, call it directly.
|
|
*/
|
|
return (BOOL)InternalHandleColorProfiles(pDevicename, devType,
|
|
papProfilenames, nCount, NULL, NULL, REMOVEPROFILES);
|
|
}
|
|
|
|
|
|
BOOL WINAPI RemoveColorProfilesW(
|
|
PWSTR pDevicename,
|
|
DEVTYPE devType,
|
|
PWSTR *papProfilenames,
|
|
DWORD nCount
|
|
)
|
|
{
|
|
/*
|
|
* Unicode version not supported under Windows 95
|
|
*/
|
|
SetLastError(ERROR_NOT_SUPPORTED);
|
|
return FALSE;
|
|
}
|
|
|
|
#endif // ! UNICODE
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* CreateNewColorProfileSet
|
|
*
|
|
* Function:
|
|
* These are the ANSI & Unicode wrappers for
|
|
* InternalCreateNewColorProfileSet. Please see
|
|
* InternalCreateNewColorProfileSet for more details on this function.
|
|
*
|
|
* Arguments:
|
|
* pDevicename - name identifying device
|
|
* devType - type of device
|
|
*
|
|
* Returns:
|
|
* TRUE if successful, FALSE otherwise
|
|
*
|
|
******************************************************************************/
|
|
|
|
#ifdef UNICODE // Windows NT versions
|
|
|
|
BOOL WINAPI CreateNewColorProfileSetA(
|
|
PSTR pDevicename,
|
|
DEVTYPE devType
|
|
)
|
|
{
|
|
WCHAR wszDevicename[CCHDEVICENAME];
|
|
|
|
/*
|
|
* Validate parameters before we touch them
|
|
*/
|
|
if (!pDevicename)
|
|
{
|
|
WARNING(("ICM: Invalid parameter to CreateNewColorProfileSet\n"));
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Convert device name to Unicode
|
|
*/
|
|
if (!MultiByteToWideChar(CP_ACP, 0, pDevicename, -1, wszDevicename, CCHDEVICENAME))
|
|
{
|
|
WARNING(("Error converting to Unicode device name\n"));
|
|
return FALSE;
|
|
}
|
|
|
|
return InternalCreateNewColorProfileSet(wszDevicename, devType);
|
|
}
|
|
|
|
BOOL WINAPI CreateNewColorProfileSetW(
|
|
PWSTR pDevicename,
|
|
DEVTYPE devType
|
|
)
|
|
{
|
|
/*
|
|
* Internal function is Unicode in Windows NT, call it directly.
|
|
*/
|
|
return InternalCreateNewColorProfileSet(pDevicename, devType);
|
|
}
|
|
|
|
#else // Windows 95 versions
|
|
|
|
BOOL WINAPI CreateNewColorProfileSetA(
|
|
PSTR pDevicename,
|
|
DEVTYPE devType
|
|
)
|
|
{
|
|
/*
|
|
* Internal function is ANSI in Windows 95, call it directly.
|
|
*/
|
|
return InternalCreateNewColorProfileSet(pDevicename, devType);
|
|
}
|
|
|
|
BOOL WINAPI CreateNewColorProfileSetW(
|
|
PWSTR pDevicename,
|
|
DEVTYPE devType
|
|
)
|
|
{
|
|
/*
|
|
* Unicode version not supported under Windows 95
|
|
*/
|
|
SetLastError(ERROR_NOT_SUPPORTED);
|
|
return FALSE;
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* EnumColorProfiles
|
|
*
|
|
* Function:
|
|
* These are the ANSI & Unicode wrappers for InternalEnumColorProfiles.
|
|
* Please see InternalEnumColorProfiles for more details on this function.
|
|
*
|
|
* Arguments:
|
|
* pDevicename - name identifying device
|
|
* devType - type of device
|
|
* pCallbackFunc - function that is called for each profile
|
|
* pClientData - app suplied data for callback function
|
|
*
|
|
* Returns:
|
|
* Last value returned by callback funtion.
|
|
*
|
|
******************************************************************************/
|
|
|
|
#ifdef UNICODE // Windows NT versions
|
|
|
|
ULONG WINAPI EnumColorProfilesA(
|
|
PSTR pDevicename,
|
|
DEVTYPE devType,
|
|
PPROFILECALLBACK pCallbackFunc,
|
|
PVOID pClientData
|
|
)
|
|
{
|
|
WCHAR wszDevicename[CCHDEVICENAME];
|
|
CALLBACKDATA data;
|
|
|
|
/*
|
|
* Validate parameters before we touch them
|
|
*/
|
|
if (!pDevicename)
|
|
{
|
|
WARNING(("ICM: Invalid parameter to CreateNewColorProfileSet\n"));
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Convert device name to Unicode
|
|
*/
|
|
if (!MultiByteToWideChar(CP_ACP, 0, pDevicename, -1, wszDevicename, CCHDEVICENAME))
|
|
{
|
|
WARNING(("Error converting to Unicode device name\n"));
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* The internal function will return Unicode strings, so we pass in our callback
|
|
* function which converts it to ANSI before calling the app supplied ANSI function
|
|
*/
|
|
data.pCallbackFunc = pCallbackFunc;
|
|
data.pClientData = pClientData;
|
|
return InternalHandleColorProfiles(wszDevicename, devType,
|
|
NULL, 0, (PPROFILECALLBACK)fnCallback, (PVOID)&data, ENUMPROFILES);
|
|
}
|
|
|
|
ULONG WINAPI EnumColorProfilesW(
|
|
PWSTR pDevicename,
|
|
DEVTYPE devType,
|
|
PPROFILECALLBACK pCallbackFunc,
|
|
PVOID pClientData
|
|
)
|
|
{
|
|
/*
|
|
* Internal function is Unicode in Windows NT, call it directly.
|
|
*/
|
|
return InternalHandleColorProfiles(pDevicename, devType,
|
|
NULL, 0, pCallbackFunc, pClientData, ENUMPROFILES);
|
|
}
|
|
|
|
#else // Windows 95 versions
|
|
|
|
ULONG WINAPI EnumColorProfilesA(
|
|
PSTR pDevicename,
|
|
DEVTYPE devType,
|
|
PPROFILECALLBACK pCallbackFunc,
|
|
PVOID pClientData
|
|
)
|
|
{
|
|
/*
|
|
* Internal function is ANSI in Windows 95, call it directly.
|
|
*/
|
|
return InternalHandleColorProfiles(pDevicename, devType,
|
|
NULL, 0, pCallbackFunc, pClientData, ENUMPROFILES);
|
|
}
|
|
|
|
ULONG WINAPI EnumColorProfilesW(
|
|
PWSTR pDevicename,
|
|
DEVTYPE devType,
|
|
PPROFILECALLBACK pCallbackFunc,
|
|
PVOID pClientData
|
|
)
|
|
{
|
|
/*
|
|
* Unicode version not supported under Windows 95
|
|
*/
|
|
SetLastError(ERROR_NOT_SUPPORTED);
|
|
return FALSE;
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* SearchColorProfiles
|
|
*
|
|
* Function:
|
|
* These are the ANSI & Unicode wrappers for InternalSearchColorProfiles.
|
|
* Please see InternalSearchColorProfiles for more details.
|
|
*
|
|
* Arguments:
|
|
* pSearchType - pointer to structure specifying the search criteria
|
|
* pCallbackFunc - function that is called for each profile
|
|
* pClientData - app suplied data for callback function
|
|
*
|
|
* Returns:
|
|
* Last value returned by callback funtion.
|
|
*
|
|
******************************************************************************/
|
|
|
|
#ifdef UNICODE // Windows NT versions
|
|
|
|
ULONG WINAPI SearchColorProfilesA(
|
|
PSEARCHTYPE pSearchType,
|
|
PPROFILECALLBACK pCallbackFunc,
|
|
PVOID pClientData
|
|
)
|
|
{
|
|
CALLBACKDATA data;
|
|
|
|
/*
|
|
* Validate parameters before we touch them
|
|
*/
|
|
if (!pCallbackFunc)
|
|
{
|
|
WARNING(("ICM: Invalid parameter to SearchColorProfiles\n"));
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Provide our Unicode callback function to translate data to ANSI
|
|
*/
|
|
data.pCallbackFunc = pCallbackFunc;
|
|
data.pClientData = pClientData;
|
|
return InternalSearchColorProfiles(pSearchType, (PPROFILECALLBACK)fnCallback, (PVOID)&data);
|
|
}
|
|
|
|
|
|
ULONG WINAPI SearchColorProfilesW(
|
|
PSEARCHTYPE pSearchType,
|
|
PPROFILECALLBACK pCallbackFunc,
|
|
PVOID pClientData
|
|
)
|
|
{
|
|
/*
|
|
* Internal function is Unicode in Windows NT, call it directly.
|
|
*/
|
|
return InternalSearchColorProfiles(pSearchType, pCallbackFunc, pClientData);
|
|
}
|
|
|
|
#else // Windows 95 versions
|
|
|
|
ULONG WINAPI SearchColorProfilesA(
|
|
PSEARCHTYPE pSearchType,
|
|
PPROFILECALLBACK pCallbackFunc,
|
|
PVOID pClientData
|
|
)
|
|
{
|
|
/*
|
|
* Internal function is ANSI in Windows 95, call it directly.
|
|
*/
|
|
return InternalSearchColorProfiles(pSearchType, pCallbackFunc, pClientData);
|
|
}
|
|
|
|
ULONG WINAPI SearchColorProfilesW(
|
|
PSEARCHTYPE pSearchType,
|
|
PPROFILECALLBACK pCallbackFunc,
|
|
PVOID pClientData
|
|
)
|
|
{
|
|
/*
|
|
* Unicode version not supported under Windows 95
|
|
*/
|
|
SetLastError(ERROR_NOT_SUPPORTED);
|
|
return FALSE;
|
|
}
|
|
|
|
#endif // ! UNICODE
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* GetSystemColorProfile
|
|
*
|
|
* Function:
|
|
* These are ANSI and Unicode wrappers for InternalGetSystemColorProfile.
|
|
* Please see InternalGetSystemColorProfile for more details.
|
|
*
|
|
* Arguments:
|
|
* dwProfileID - specifies the profile identifier eg. 'sRGB'
|
|
* pBuffer - buffer to recieve the profile filename
|
|
* pcbSize - pointer to dword that has size of buffer. On return
|
|
* it has size of filename,
|
|
*
|
|
* Returns:
|
|
* TRUE if successful, FALSE otherwise.
|
|
*
|
|
******************************************************************************/
|
|
|
|
#ifdef UNICODE // Windows NT versions
|
|
|
|
BOOL WINAPI GetSystemColorProfileA(
|
|
DWORD dwProfileID,
|
|
PSTR pBuffer,
|
|
PDWORD pcbSize
|
|
)
|
|
{
|
|
PWSTR pwBuffer = NULL;
|
|
DWORD cbSize;
|
|
BOOL rc;
|
|
|
|
/*
|
|
* Validate parameters before we touch them
|
|
*/
|
|
if (!pcbSize ||
|
|
IsBadReadPtr(pcbSize, sizeof(DWORD)) ||
|
|
((*pcbSize > 0) &&
|
|
(!pBuffer ||
|
|
IsBadWritePtr(pBuffer, *pcbSize)
|
|
)
|
|
)
|
|
)
|
|
{
|
|
WARNING(("ICM: Invalid parameter to GetSystemColorProfile\n"));
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Allocate memory for receiving Unicode filename
|
|
*/
|
|
cbSize = *pcbSize * sizeof(WCHAR);
|
|
if (*pcbSize > 0)
|
|
{
|
|
pwBuffer = (PWSTR)GlobalAllocPtr(GHND, cbSize);
|
|
if (!pwBuffer)
|
|
{
|
|
WARNING(("ICM: Error allocating memory for Unicode string in GetSystemColorProfileA\n"));
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
rc = InternalGetSystemColorProfile(dwProfileID, pwBuffer, &cbSize);
|
|
|
|
/*
|
|
* Convert Unicode back to ANSI. It might not work, but this is the best
|
|
* we can do.
|
|
*/
|
|
if (rc && pBuffer)
|
|
{
|
|
if (!WideCharToMultiByte(CP_ACP, 0, pwBuffer, -1, pBuffer, *pcbSize, NULL, NULL))
|
|
{
|
|
WARNING(("Error converting from Unicode to ANSI in GetSystemColorProfile\n"));
|
|
rc = FALSE;
|
|
}
|
|
}
|
|
|
|
if (pwBuffer)
|
|
{
|
|
GlobalFreePtr(pwBuffer);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
BOOL WINAPI GetSystemColorProfileW(
|
|
DWORD dwProfileID,
|
|
PWSTR pBuffer,
|
|
PDWORD pcbSize
|
|
)
|
|
{
|
|
/*
|
|
* Internal function is Unicode in Windows NT, call it directly.
|
|
*/
|
|
return InternalGetSystemColorProfile(dwProfileID, pBuffer, pcbSize);
|
|
}
|
|
|
|
|
|
#else // Windows 95 versions
|
|
|
|
BOOL WINAPI GetSystemColorProfileA(
|
|
DWORD dwProfileID,
|
|
PSTR pBuffer,
|
|
PDWORD pcbSize
|
|
)
|
|
{
|
|
/*
|
|
* Internal function is ANSI in Windows 95, call it directly.
|
|
*/
|
|
return InternalGetSystemColorProfile(dwProfileID, pBuffer, pcbSize);
|
|
}
|
|
|
|
BOOL WINAPI GetSystemColorProfileW(
|
|
DWORD dwProfileID,
|
|
PWSTR pBuffer,
|
|
PDWORD pcbSize
|
|
)
|
|
{
|
|
/*
|
|
* Unicode version not supported under Windows 95
|
|
*/
|
|
SetLastError(ERROR_NOT_SUPPORTED);
|
|
return FALSE;
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
/*========================================================================*/
|
|
|
|
/******************************************************************************
|
|
*
|
|
* InternalHandleColorProfiles
|
|
*
|
|
* Function:
|
|
* This functions adds, removes or enumerates color profiles in the system
|
|
* registry for the specified device.
|
|
*
|
|
* Arguments:
|
|
* pDevicename - name identifying device
|
|
* devType - type of device
|
|
* papProfilenames - pointer to array of profiles to add/remove
|
|
* nCount - number of profiles in array
|
|
* pCallbackFunc - callback function for profile enumeration
|
|
* pClientData - app supplied data for callback function
|
|
* mode - specifies if add, remove or enumeration is needed
|
|
*
|
|
* Returns:
|
|
* Non zero value if successful, zero otherwise
|
|
*
|
|
******************************************************************************/
|
|
|
|
ULONG InternalHandleColorProfiles(
|
|
PTSTR pDevicename,
|
|
DEVTYPE devType,
|
|
PTSTR *papProfilenames,
|
|
DWORD nCount,
|
|
PPROFILECALLBACK pCallbackFunc,
|
|
PVOID pClientData,
|
|
PROFILEOP mode
|
|
)
|
|
{
|
|
HKEY hkICM, hkdev, hkManu, hkModel, hkBranch;
|
|
HANDLE hPrinter;
|
|
DWORD i, dwType, cbSize;
|
|
BOOL rc = FALSE;
|
|
TCHAR szModelname[CCHDEVICENAME], manu[5], model[5], szValue[32];
|
|
|
|
#ifdef DBG
|
|
if (mode == ADDPROFILES)
|
|
{
|
|
TRACEAPI(("AddColorProfiles\n"));
|
|
}
|
|
else if (mode == REMOVEPROFILES)
|
|
{
|
|
TRACEAPI(("RemoveColorProfiles\n"));
|
|
}
|
|
else
|
|
{
|
|
TRACEAPI(("EnumColorProfiles\n"));
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* Validate parameters
|
|
*/
|
|
if (((mode == ENUMPROFILES) &&
|
|
(!pDevicename ||
|
|
!pCallbackFunc
|
|
)
|
|
) ||
|
|
((mode != ENUMPROFILES) &&
|
|
(!pDevicename ||
|
|
!papProfilenames ||
|
|
nCount == 0 ||
|
|
IsBadReadPtr(papProfilenames, sizeof(PTSTR)*nCount)
|
|
)
|
|
)
|
|
)
|
|
{
|
|
WARNING(("ICM: Invalid parameter to HandleColorProfiles\n"));
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Open the registry
|
|
*/
|
|
if (RegCreateKey(HKEY_LOCAL_MACHINE, gszICMRegPath, &hkICM)
|
|
!= ERROR_SUCCESS)
|
|
{
|
|
ERR(("ICM: Cannot open ICM branch of registry in HandleColorProfiles\n"));
|
|
return FALSE;
|
|
}
|
|
hkdev = hkManu = hkModel = hkBranch = NULL;
|
|
|
|
switch (devType)
|
|
{
|
|
case DEV_SCANNER:
|
|
break;
|
|
|
|
case DEV_DISPLAY:
|
|
break;
|
|
|
|
case DEV_PRINTER:
|
|
/*
|
|
* Get the printer's model name
|
|
*/
|
|
if (!GetPrinterModelName(pDevicename, szModelname))
|
|
{
|
|
WARNING(("ICM: Invalid printer name to HandleColorProfiles\n"));
|
|
SetLastError(ERROR_INVALID_NAME);
|
|
goto EndHandleColorProfiles;
|
|
}
|
|
|
|
/*
|
|
* Open the registry key for printer
|
|
*/
|
|
RegCreateKey(hkICM, gszPrinter, &hkdev);
|
|
|
|
/*
|
|
* Generate manufacturer & model IDs from the printer device name
|
|
*/
|
|
GetManuAndModelIDs(szModelname, manu, model);
|
|
|
|
/*
|
|
* Create keys for manufacturer and model
|
|
*/
|
|
RegCreateKey(hkdev, manu, &hkManu);
|
|
RegCreateKey(hkManu, model, &hkModel);
|
|
|
|
/*
|
|
* Check if printer shares profiles or has a unique bucket
|
|
*/
|
|
OpenPrinter(pDevicename, &hPrinter, NULL);
|
|
if (hPrinter)
|
|
{
|
|
if (GetPrinterData(hPrinter, gszICMKey, &dwType, (PBYTE)szValue,
|
|
32, &cbSize) != ERROR_SUCCESS)
|
|
{
|
|
lstrcpy(szValue, gszDefault); // shares profiles
|
|
}
|
|
ClosePrinter(hPrinter);
|
|
}
|
|
if (RegCreateKey(hkModel, szValue, &hkBranch) != ERROR_SUCCESS)
|
|
goto EndHandleColorProfiles;
|
|
|
|
if (mode == ENUMPROFILES)
|
|
{
|
|
rc = EnumerateProfiles(hkBranch, pCallbackFunc, pClientData);
|
|
}
|
|
else
|
|
{
|
|
rc = TRUE;
|
|
for (i=0; i<nCount; i++)
|
|
{
|
|
rc = AddOrRemovePrinterProfile(hkBranch, papProfilenames[i],
|
|
szModelname, mode == ADDPROFILES) && rc;
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
EndHandleColorProfiles:
|
|
if (hkICM)
|
|
RegCloseKey(hkICM);
|
|
if (hkdev)
|
|
RegCloseKey(hkdev);
|
|
if (hkManu)
|
|
RegCloseKey(hkManu);
|
|
if (hkModel)
|
|
RegCloseKey(hkModel);
|
|
if (hkBranch)
|
|
RegCloseKey(hkBranch);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* AddOrRemovePrinterProfile
|
|
*
|
|
* Function:
|
|
* This functions adds or removes a printer profile into/from the registry
|
|
*
|
|
* Arguments:
|
|
* hkPrtr - registry location where printer profiles are kept
|
|
* pProfile - profile to add/remove
|
|
* pDevicename - model name of printer
|
|
* bAdd - TRUE if profile should be added, FALSE to remove
|
|
*
|
|
* Returns:
|
|
* TRUE if successful, FALSE otherwise
|
|
*
|
|
******************************************************************************/
|
|
|
|
BOOL AddOrRemovePrinterProfile(
|
|
HKEY hkPrtr,
|
|
PTSTR pProfile,
|
|
PTSTR pDevicename,
|
|
BOOL bAdd
|
|
)
|
|
{
|
|
PROFILEHEADER header;
|
|
PROFILE profile;
|
|
HPROFILE hProfile;
|
|
HKEY hkMedia, hkDither, hkRes, hkLast;
|
|
DWORD cbSize, val, i;
|
|
BOOL rc = FALSE, bRef;
|
|
TCHAR szValue[32], *pStr;
|
|
|
|
hkMedia = hkDither = hkRes = hkLast = NULL;
|
|
|
|
/*
|
|
* Open the profile and check if it is a printer profile
|
|
*/
|
|
profile.dwType = PROFILE_FILENAME;
|
|
profile.pProfileData = pProfile;
|
|
profile.cbDataSize = lstrlen(profile.pProfileData) * sizeof(TCHAR);
|
|
hProfile = OpenColorProfile(&profile, 0, OPEN_EXISTING);
|
|
if (!hProfile)
|
|
{
|
|
goto EndAddOrRemovePrinterProfile;
|
|
}
|
|
|
|
GetColorProfileHeader(hProfile, &header);
|
|
if (header.phClass != CLASS_PRINTER)
|
|
{
|
|
WARNING(("ICM: Wrong profile class passed to AddOrRemovePrinterProfile\n"));
|
|
SetLastError(ERROR_INVALID_PROFILE);
|
|
goto EndAddOrRemovePrinterProfile;
|
|
}
|
|
|
|
/*
|
|
* Get the media tag from the profile
|
|
*/
|
|
cbSize = 4;
|
|
if (GetColorProfileElement(hProfile, 'MS01', 0, &cbSize, szValue, &bRef))
|
|
{
|
|
val = *((DWORD *)szValue);
|
|
if (val < DMMEDIA_USER)
|
|
{
|
|
if (val > DMMEDIA_TRANSPARENCY)
|
|
val = 0;
|
|
pStr = gMediaType[val];
|
|
}
|
|
else
|
|
{
|
|
pStr = szValue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pStr = gMediaType[0];
|
|
}
|
|
RegCreateKey(hkPrtr, pStr, &hkMedia);
|
|
|
|
/*
|
|
* Get the dither type tag from the profile
|
|
*/
|
|
cbSize = 4;
|
|
if (GetColorProfileElement(hProfile, 'MS02', 0, &cbSize, szValue, &bRef))
|
|
{
|
|
// BUGBUG - debug this
|
|
val = *((DWORD *)szValue);
|
|
if (val < DMDITHER_USER)
|
|
{
|
|
if (val > DMDITHER_GRAYSCALE)
|
|
val = 0;
|
|
pStr = gDitherType[val];
|
|
}
|
|
else
|
|
{
|
|
pStr = szValue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pStr = gDitherType[0];
|
|
}
|
|
RegCreateKey(hkMedia, pStr, &hkDither);
|
|
|
|
/*
|
|
* Get the resolution tag from the profile
|
|
*/
|
|
cbSize = 8;
|
|
if (GetColorProfileElement(hProfile, 'MS03', 0, &cbSize, szValue, &bRef))
|
|
{
|
|
#if 0
|
|
itoa(SwapBytes(pTag[2]), (DWORD *)&NameOfManu[0]);
|
|
NameOfManu[5] = 'x';
|
|
itoa(SwapBytes(pTag[3]), (DWORD *)&NameOfManu[6]);
|
|
NameOfManu[11] = 0;
|
|
|
|
val = *((DWORD *)szValue;
|
|
val2 = *((DWORD *)szValue + 1);
|
|
itoa(val, szValue, 10);
|
|
szValue[5] = 'x';
|
|
itoa(val2, &szValue[6], 10);
|
|
#endif
|
|
pStr = szValue;
|
|
}
|
|
else
|
|
pStr = gResolution[0];
|
|
|
|
RegCreateKey(hkDither, pStr, &hkRes);
|
|
|
|
/*
|
|
* Get the device color space from profile
|
|
*/
|
|
for (i=0; i<4; i++)
|
|
{
|
|
// BUGBUG: Fix this for BIG_ENDIAN machines
|
|
szValue[i] = ((char*)&header.phDataColorSpace)[3-i];
|
|
}
|
|
szValue[4] = 0;
|
|
RegCreateKey(hkRes, szValue, &hkLast);
|
|
|
|
/*
|
|
* Add or remove profile
|
|
*/
|
|
rc = AddOrRemoveProfileEntry(hkLast, pProfile, bAdd);
|
|
|
|
EndAddOrRemovePrinterProfile:
|
|
if (hProfile)
|
|
CloseColorProfile(hProfile);
|
|
if (hkMedia)
|
|
RegCloseKey(hkMedia);
|
|
if (hkDither)
|
|
RegCloseKey(hkDither);
|
|
if (hkRes)
|
|
RegCloseKey(hkRes);
|
|
if (hkLast)
|
|
RegCloseKey(hkLast);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* GetManuAndModelIDs
|
|
*
|
|
* Function:
|
|
* This functions creates manu and model ID from the model name of
|
|
* the printer. This algorithm maintains backward compatibility with
|
|
* Windows 95.
|
|
*
|
|
* Arguments:
|
|
* pDevicename - model name of printer
|
|
* pManu - buffer to get the manu ID
|
|
* pModel - buffer to get the model ID
|
|
*
|
|
* Returns:
|
|
* Nothing
|
|
*
|
|
******************************************************************************/
|
|
|
|
void GetManuAndModelIDs(
|
|
PTSTR pDevicename,
|
|
PTSTR pManu,
|
|
PTSTR pModel
|
|
)
|
|
{
|
|
DWORD dwCheckSum, dwSize;
|
|
int i;
|
|
WORD wCRC16a[16]={
|
|
0000000, 0140301, 0140601, 0000500,
|
|
0141401, 0001700, 0001200, 0141101,
|
|
0143001, 0003300, 0003600, 0143501,
|
|
0002400, 0142701, 0142201, 0002100,
|
|
};
|
|
WORD wCRC16b[16]={
|
|
0000000, 0146001, 0154001, 0012000,
|
|
0170001, 0036000, 0024000, 0162001,
|
|
0120001, 0066000, 0074000, 0132001,
|
|
0050000, 0116001, 0104001, 0043000,
|
|
};
|
|
TCHAR *pByte;
|
|
TCHAR temp;
|
|
BYTE bTmp;
|
|
|
|
/*
|
|
* Define the manufacturer to be the first 4 characters of the
|
|
* device name. A space or a hypen end the string, and the
|
|
* remaining part of the string is filled with spaces. We need
|
|
* this computed ID to be 4 chars so that there is no chance of
|
|
* collisions with real EISA IDs.
|
|
*/
|
|
pByte = pDevicename;
|
|
for (i=0; i<4; i++, pByte++)
|
|
{
|
|
if (*pByte == ' ' || *pByte == '-')
|
|
{
|
|
for (; i<4; i++)
|
|
{
|
|
pManu[i] = ' ';
|
|
}
|
|
}
|
|
else
|
|
{
|
|
temp = *pByte;
|
|
if (temp >= 'a' && temp <= 'z')
|
|
temp = temp + 'A' - 'a';
|
|
pManu[i] = temp;
|
|
}
|
|
}
|
|
pManu[4] = '\0';
|
|
|
|
/*
|
|
* Define the model to be a CRC of the complete DriverDesc
|
|
* string. We use the same method that the PnP LPT
|
|
* enumerator uses to create unique ID's. It turns out
|
|
* that this is really not unique, but it gets us close
|
|
* enough.
|
|
*/
|
|
dwCheckSum = 0;
|
|
dwSize = lstrlen(pDevicename);
|
|
|
|
for (pByte=pDevicename; dwSize; dwSize--, pByte++)
|
|
{
|
|
bTmp = (BYTE)(((WORD)*pByte)^((WORD)dwCheckSum)); // Xor CRC with new char
|
|
dwCheckSum = (dwCheckSum >> 8) ^ wCRC16a[bTmp & 0x0F] ^ wCRC16b[bTmp >> 4];
|
|
}
|
|
wsprintf(pModel, __TEXT("%X"), dwCheckSum);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* AddOrRemoveProfileEntry
|
|
*
|
|
* Function:
|
|
* This functions adds or removes the given profile into under the
|
|
* registry key that is given. It searches from profile00 to
|
|
* profile99.
|
|
*
|
|
* Arguments:
|
|
* hKey - open registry key under which to add the profile
|
|
* pProfilename - file name of the profile
|
|
*
|
|
* Returns:
|
|
* TRUE if successful, FALSE otherwise
|
|
*
|
|
******************************************************************************/
|
|
|
|
BOOL AddOrRemoveProfileEntry(
|
|
HKEY hKey,
|
|
PTSTR pProfilename,
|
|
BOOL bAdd
|
|
)
|
|
{
|
|
DWORD dwType, dwSize;
|
|
int i, j;
|
|
TCHAR szName[10], szValue[MAX_PATH];
|
|
BOOL rc = TRUE;
|
|
|
|
/*
|
|
* Go through list of profiles and enter this profile in the
|
|
* first available spot if adding, else if found remove it
|
|
*/
|
|
lstrcpy(szName, __TEXT("profile"));
|
|
szName[9] = 0;
|
|
for (i=0 ;i<10 ; i++)
|
|
{
|
|
szName[7] = '0' + i;
|
|
for (j=0 ;j<10 ; j++)
|
|
{
|
|
dwSize = MAX_PATH;
|
|
szName[8] = '0' + j;
|
|
if (RegQueryValueEx(hKey, szName, 0, &dwType,
|
|
(BYTE *)szValue, &dwSize) == ERROR_SUCCESS)
|
|
{
|
|
if (!lstrcmpi(szValue, pProfilename))
|
|
{
|
|
if (!bAdd)
|
|
RegDeleteValue(hKey, szName);
|
|
|
|
return TRUE; // profile already exists or we just removed it
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (bAdd)
|
|
{
|
|
if (RegSetValueEx(hKey, szName, 0, REG_SZ,
|
|
(BYTE *)pProfilename,
|
|
(lstrlen(pProfilename)+1)*sizeof(TCHAR)) != ERROR_SUCCESS)
|
|
{
|
|
rc = FALSE;
|
|
}
|
|
return rc;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return FALSE; // no more empty slots
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* GetPrinterModelName
|
|
*
|
|
* Function:
|
|
* This functions takes a printer friendly name and returns the model
|
|
* name.
|
|
*
|
|
* Arguments:
|
|
* pFriendlyName - friendly name of the printer
|
|
* pModelName - buffer that gets the model name
|
|
*
|
|
* Returns:
|
|
* TRUE if successful, FALSE otherwise
|
|
*
|
|
******************************************************************************/
|
|
|
|
BOOL GetPrinterModelName(
|
|
PTSTR pFriendlyName,
|
|
PTSTR pModelName
|
|
)
|
|
{
|
|
TCHAR szBuf[MAX_PATH];
|
|
HKEY hKey;
|
|
DWORD dwNeeded, dwType;
|
|
|
|
lstrcpy(szBuf, gszRegPrinter);
|
|
lstrcat(szBuf, pFriendlyName);
|
|
|
|
if (RegOpenKey(HKEY_LOCAL_MACHINE, szBuf, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
dwNeeded = CCHDEVICENAME * sizeof(TCHAR);
|
|
RegQueryValueEx(hKey, gszPrinterDriver, NULL, &dwType,
|
|
(BYTE *)pModelName, &dwNeeded);
|
|
|
|
RegCloseKey(hKey);
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* InternalCreateNewColorProfileSet
|
|
*
|
|
* Function:
|
|
* This function creates a new name for the profile bucket for the
|
|
* given device. Future AddColorProfiles() to this device will be added
|
|
* under this bucket.
|
|
*
|
|
* Arguments:
|
|
* pDevicename - name identifying device
|
|
* devType - type of device
|
|
*
|
|
* Returns:
|
|
* TRUE if successful, FALSE otherwise
|
|
*
|
|
******************************************************************************/
|
|
|
|
BOOL InternalCreateNewColorProfileSet(
|
|
PTSTR pDevicename,
|
|
DEVTYPE devType
|
|
)
|
|
{
|
|
HANDLE hPrinter;
|
|
HKEY hkICM, hkdev, hkmanu, hkmodel, hktemp;
|
|
BOOL rc = FALSE;
|
|
TCHAR szModelname[CCHDEVICENAME], szValue[5];
|
|
TCHAR manu[5], model[5];
|
|
|
|
TRACEAPI(("CreateNewColorProfileSet\n"));
|
|
|
|
/*
|
|
* Validate parameters
|
|
*/
|
|
if (!pDevicename)
|
|
{
|
|
WARNING(("ICM: Invalid parameter to CreateNewColorProfileSet\n"));
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Open the registry
|
|
*/
|
|
if (RegCreateKey(HKEY_LOCAL_MACHINE, gszICMRegPath, &hkICM)
|
|
!= ERROR_SUCCESS)
|
|
{
|
|
ERR(("ICM: Cannot open ICM branch of registry in CreateNewColorProfileSet\n"));
|
|
return FALSE;
|
|
}
|
|
|
|
switch (devType)
|
|
{
|
|
case DEV_SCANNER:
|
|
break;
|
|
|
|
case DEV_DISPLAY:
|
|
break;
|
|
|
|
case DEV_PRINTER:
|
|
/*
|
|
* Get the printer's model name
|
|
*/
|
|
if (!GetPrinterModelName(pDevicename, szModelname))
|
|
{
|
|
WARNING(("ICM: Invalid printer name to AddColorProfiles\n"));
|
|
SetLastError(ERROR_INVALID_NAME);
|
|
goto EndCreateNewColorProfileSet;
|
|
}
|
|
|
|
/*
|
|
* Open the registry key for printer
|
|
*/
|
|
RegCreateKey(hkICM, gszPrinter, &hkdev);
|
|
|
|
/*
|
|
* Create unique bucket for printer
|
|
*/
|
|
OpenPrinter(pDevicename, &hPrinter, NULL);
|
|
if (hPrinter)
|
|
{
|
|
HANDLE hMutex;
|
|
|
|
hkmanu = hkmodel = 0;
|
|
|
|
GetManuAndModelIDs(szModelname, manu, model);
|
|
RegOpenKey(hkdev, manu, &hkmanu);
|
|
RegOpenKey(hkmanu, model, &hkmodel);
|
|
|
|
hktemp = 0;
|
|
|
|
/*
|
|
* Use a named mutex object to prevent multiple threads/processes
|
|
* from creating the same bucket name
|
|
*/
|
|
hMutex = CreateMutex(NULL, TRUE, gszMutexName); // Create and own mutex
|
|
if (GetLastError() == ERROR_ALREADY_EXISTS)
|
|
{
|
|
/*
|
|
* Mutex already exists, so we have to explicitely ask for ownership
|
|
*/
|
|
WaitForSingleObject(hMutex, INFINITE);
|
|
}
|
|
|
|
do {
|
|
if (hktemp)
|
|
RegCloseKey(hktemp);
|
|
wsprintf(szValue, __TEXT("%X"), GetTickCount());
|
|
} while (RegOpenKey(hkmodel, szValue, &hktemp) == ERROR_SUCCESS);
|
|
|
|
/*
|
|
* Release and close the mutex handle
|
|
*/
|
|
ReleaseMutex(hMutex);
|
|
CloseHandle(hMutex);
|
|
|
|
RegCloseKey(hkmanu);
|
|
RegCloseKey(hkmodel);
|
|
|
|
if (SetPrinterData(hPrinter, gszICMKey, REG_SZ,
|
|
(PBYTE)szValue, (lstrlen(szValue) + 1)*sizeof(TCHAR)) == ERROR_SUCCESS)
|
|
{
|
|
rc = TRUE;
|
|
}
|
|
|
|
ClosePrinter(hPrinter);
|
|
}
|
|
RegCloseKey(hkdev);
|
|
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
EndCreateNewColorProfileSet:
|
|
if (hkICM)
|
|
{
|
|
RegCloseKey(hkICM);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
#define SET(ps, bit) (ps->stFields & (bit))
|
|
|
|
BOOL IsMatch(
|
|
PSEARCHTYPE pSearch,
|
|
PPROFILEHEADER pHeader
|
|
)
|
|
{
|
|
return ((!SET(pSearch, ST_CMMTYPE) || (pSearch->stCMMType == pHeader->phCMMType)) &&
|
|
(!SET(pSearch, ST_CLASS) || (pSearch->stClass == pHeader->phClass)) &&
|
|
(!SET(pSearch, ST_DATACOLORSPACE) || (pSearch->stDataColorSpace == pHeader->phDataColorSpace)) &&
|
|
(!SET(pSearch, ST_CONNECTIONSPACE) || (pSearch->stConnectionSpace == pHeader->phConnectionSpace)) &&
|
|
(!SET(pSearch, ST_SIGNATURE) || (pSearch->stSignature == pHeader->phSignature)) &&
|
|
(!SET(pSearch, ST_PLATFORM) || (pSearch->stPlatform == pHeader->phPlatform)) &&
|
|
(!SET(pSearch, ST_PROFILEFLAGS) || (pSearch->stProfileFlags == pHeader->phProfileFlags)) &&
|
|
(!SET(pSearch, ST_MANUFACTURER) || (pSearch->stManufacturer == pHeader->phManufacturer)) &&
|
|
(!SET(pSearch, ST_MODEL) || (pSearch->stModel == pHeader->phModel)) &&
|
|
(!SET(pSearch, ST_ATTRIBUTES) || (pSearch->stAttributes[0] == pHeader->phAttributes[0] &&
|
|
pSearch->stAttributes[1] == pHeader->phAttributes[1])) &&
|
|
(!SET(pSearch, ST_RENDERINGINTENT) || (pSearch->stRenderingIntent == pHeader->phRenderingIntent)) &&
|
|
(!SET(pSearch, ST_CREATOR) || (pSearch->stCreator == pHeader->phCreator))
|
|
);
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* InternalSearchColorProfiles
|
|
*
|
|
* Function:
|
|
* This function searches through all the profiles in the COLOR
|
|
* directory, and calls the callback function once for each profile
|
|
* that satisfies the search criteria
|
|
*
|
|
* Arguments:
|
|
* pSearchType - pointer to structure specifying the search criteria
|
|
* pCallbackFunc - function that is called for each profile
|
|
* pClientData - app suplied data for callback function
|
|
*
|
|
* Returns:
|
|
* Last value returned by callback funtion.
|
|
*
|
|
******************************************************************************/
|
|
|
|
ULONG InternalSearchColorProfiles(
|
|
PSEARCHTYPE pSearchType,
|
|
PPROFILECALLBACK pCallbackFunc,
|
|
PVOID pClientData
|
|
)
|
|
{
|
|
WIN32_FIND_DATA wfd;
|
|
PROFILEHEADER header;
|
|
PROFILE profile;
|
|
HANDLE hFindFile;
|
|
HPROFILE hProfile;
|
|
ULONG rc = 0;
|
|
DWORD index;
|
|
TCHAR szPath[MAX_PATH];
|
|
|
|
TRACEAPI(("SearchColorProfiles\n"));
|
|
|
|
/*
|
|
* Validate parameters
|
|
*/
|
|
if (!pSearchType ||
|
|
IsBadReadPtr(pSearchType, sizeof(SEARCHTYPE)) ||
|
|
!pCallbackFunc)
|
|
{
|
|
WARNING(("ICM: Invalid parameter to SearchColorProfiles\n"));
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Create a buffer with "%SYSTEMDIR%\COLOR\*.*" to search for profiles
|
|
*/
|
|
GetSystemDirectory(szPath, MAX_PATH);
|
|
if (szPath[lstrlen(szPath)-1] != '\\')
|
|
lstrcat(szPath, gszBackslash);
|
|
lstrcat(szPath, gszColorDir);
|
|
lstrcat(szPath, gszBackslash);
|
|
index = lstrlen(szPath);
|
|
lstrcat(szPath, gszStarDotStar);
|
|
|
|
hFindFile = FindFirstFile(szPath, &wfd);
|
|
if (hFindFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
do {
|
|
szPath[index] = 0;
|
|
lstrcat(szPath, wfd.cFileName); // append filename to COLOR directory
|
|
profile.dwType = PROFILE_FILENAME;
|
|
profile.pProfileData = szPath;
|
|
profile.cbDataSize = lstrlen(profile.pProfileData) * sizeof(TCHAR);
|
|
hProfile = OpenColorProfile(&profile, 0, OPEN_EXISTING);
|
|
if (hProfile)
|
|
{
|
|
GetColorProfileHeader(hProfile, &header);
|
|
CloseColorProfile(hProfile);
|
|
|
|
if (IsMatch(pSearchType, &header))
|
|
{
|
|
rc = (*pCallbackFunc)(profile.pProfileData, pClientData);
|
|
if (rc == 0)
|
|
break;
|
|
}
|
|
}
|
|
} while (FindNextFile(hFindFile, &wfd));
|
|
|
|
FindClose(hFindFile);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* InternalGetSystemColorProfile
|
|
*
|
|
* Function:
|
|
* This function returns the system color profile of the type requested.
|
|
* Currently only sRGB is registered (it is also hardcoded for efficiency).
|
|
* Other types can be registered in the registry. We are not giving an
|
|
* API to do that yet because having multiple color spaces is not
|
|
* preferred, but the potential exists and a mechanism is provided.
|
|
*
|
|
* Arguments:
|
|
* dwProfileID - specifies the profile identifier eg. 'sRGB'
|
|
* pBuffer - buffer to recieve the profile filename
|
|
* pcbSize - pointer to dword that has size of buffer. On return
|
|
* it has size of filename,
|
|
*
|
|
* Returns:
|
|
* TRUE if successful, FALSE otherwise.
|
|
*
|
|
* Comments:
|
|
* If pBuffer is NULL, or it is not big enough, pcbSize is filled with
|
|
* size needed, and function returns FALSE. GetLastError() returns
|
|
* ERROR_MORE_DATA
|
|
*
|
|
******************************************************************************/
|
|
|
|
BOOL InternalGetSystemColorProfile(
|
|
DWORD dwProfileID,
|
|
PTSTR pBuffer,
|
|
PDWORD pcbSize
|
|
)
|
|
{
|
|
DWORD cbSize;
|
|
HKEY hkICM, hkRegProf;
|
|
BOOL rc = FALSE;
|
|
TCHAR szPath[MAX_PATH];
|
|
|
|
TRACEAPI(("GetSystemColorProfile\n"));
|
|
|
|
/*
|
|
* Validate parameters
|
|
*/
|
|
if (!pcbSize ||
|
|
IsBadReadPtr(pcbSize, sizeof(DWORD)) ||
|
|
((*pcbSize > 0) &&
|
|
(!pBuffer ||
|
|
IsBadWritePtr(pBuffer, *pcbSize)
|
|
)
|
|
)
|
|
)
|
|
{
|
|
WARNING(("ICM: Invalid parameter to GetSystemColorProfile\n"));
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Check if sRGB is being requested
|
|
*/
|
|
if (dwProfileID == LCS_sRGB)
|
|
{
|
|
GetSystemDirectory(szPath, MAX_PATH);
|
|
if (szPath[lstrlen(szPath)-1] != '\\')
|
|
lstrcat(szPath, gszBackslash);
|
|
lstrcat(szPath, gszColorDir);
|
|
lstrcat(szPath, gszBackslash);
|
|
lstrcat(szPath, gszsRGBProfile);
|
|
|
|
cbSize = (lstrlen(szPath) + 1)*sizeof(TCHAR);
|
|
rc = TRUE;
|
|
if (*pcbSize < cbSize && pBuffer)
|
|
{
|
|
WARNING(("ICM: Buffer too small in GetSystemColorProfile\n"));
|
|
SetLastError(ERROR_MORE_DATA);
|
|
rc = FALSE;
|
|
}
|
|
|
|
if (*pcbSize >= cbSize)
|
|
{
|
|
lstrcpy(pBuffer, szPath);
|
|
}
|
|
*pcbSize = cbSize;
|
|
}
|
|
else
|
|
{
|
|
DWORD i;
|
|
TCHAR szProfileID[5];
|
|
|
|
/*
|
|
* Look in the registry to check if this type is registered
|
|
*/
|
|
RegCreateKey(HKEY_LOCAL_MACHINE, gszICMRegPath, &hkICM);
|
|
if (RegOpenKey(hkICM, gszRegisteredProfiles, &hkRegProf) == ERROR_SUCCESS)
|
|
{
|
|
for (i=0; i<4; i++)
|
|
{
|
|
szProfileID[i] = ((char*)&dwProfileID)[3-i];
|
|
}
|
|
|
|
if (RegQueryValueEx(hkRegProf, szProfileID, NULL, NULL, (PBYTE)pBuffer, pcbSize)
|
|
== ERROR_SUCCESS)
|
|
{
|
|
rc = TRUE;
|
|
}
|
|
RegCloseKey(hkRegProf);
|
|
}
|
|
RegCloseKey(hkICM);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* fnCallback
|
|
*
|
|
* Function:
|
|
* This function is used to by the Unicode DLL to call an app supplied
|
|
* ANSI callback function. It converts Unicode strings to ANSI.
|
|
*
|
|
* Arguments:
|
|
* pwProfile - Unicode profile string that needs to be converted
|
|
* pData - private data that has app callback and data
|
|
*
|
|
* Returns:
|
|
* Value returned by app callback funtion.
|
|
*
|
|
******************************************************************************/
|
|
|
|
ULONG WINAPI fnCallback(
|
|
PWSTR pwProfile,
|
|
PVOID pData
|
|
)
|
|
{
|
|
PPROFILECALLBACK pTemp;
|
|
char szProfile[MAX_PATH];
|
|
|
|
/*
|
|
* Convert Unicode back to ANSI. It might not work, but this is the best
|
|
* we can do.
|
|
*/
|
|
if (!WideCharToMultiByte(CP_ACP, 0, pwProfile, -1, szProfile, MAX_PATH, NULL, NULL))
|
|
{
|
|
WARNING(("Error converting from Unicode to ANSI in fnCallback\n"));
|
|
return 1; // To continue enumeration
|
|
}
|
|
|
|
pTemp = (PPROFILECALLBACK)((PCALLBACKDATA)pData)->pCallbackFunc;
|
|
return (*pTemp)((PTSTR)szProfile, ((PCALLBACKDATA)pData)->pClientData);
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* EnumerateProfiles
|
|
*
|
|
* Function:
|
|
* This functions all profiles registered under the given key
|
|
*
|
|
* Arguments:
|
|
* hKey - key under which to enumerate profile
|
|
* pCallbackFunc - app supplied funtion to call back for each profile
|
|
* pClientData - data for callback function
|
|
*
|
|
* Returns:
|
|
* Last value returned by the callback function
|
|
*
|
|
******************************************************************************/
|
|
TCHAR szValue[MAX_PATH];
|
|
|
|
ULONG EnumerateProfiles(
|
|
HKEY hKey,
|
|
PPROFILECALLBACK pCallbackFunc,
|
|
PVOID pClientData
|
|
)
|
|
{
|
|
HKEY hSubkey;
|
|
DWORD nSubkeys, nValues, i, cbName, cbValue;
|
|
ULONG rc;
|
|
TCHAR szName[32];
|
|
|
|
if (RegQueryInfoKey(hKey, NULL, NULL, 0, &nSubkeys, NULL, NULL,
|
|
&nValues, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (nSubkeys > 0)
|
|
{
|
|
/*
|
|
* This is not the leaf node, recurse
|
|
*/
|
|
for (i=0; i<nSubkeys; i++)
|
|
{
|
|
RegEnumKey(hKey, i, szName, 32);
|
|
if (RegOpenKey(hKey, szName, &hSubkey) == ERROR_SUCCESS)
|
|
{
|
|
rc = EnumerateProfiles(hSubkey, pCallbackFunc, pClientData);
|
|
RegCloseKey(hSubkey);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* This is the leaf node - enumerate all the profiles registered
|
|
*/
|
|
for (i=0; i<nValues; i++)
|
|
{
|
|
cbName = 32;
|
|
cbValue = MAX_PATH;
|
|
if (RegEnumValue(hKey, i, szName, &cbName, 0, NULL, (LPBYTE)szValue,
|
|
&cbValue) == ERROR_SUCCESS)
|
|
{
|
|
rc = (*pCallbackFunc)(szValue, pClientData);
|
|
if (rc == 0)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return rc;
|
|
}
|