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.
3296 lines
79 KiB
3296 lines
79 KiB
|
|
/******************************Module*Header*******************************\
|
|
* Module Name:
|
|
*
|
|
* icmutils.cxx
|
|
*
|
|
* Abstract
|
|
*
|
|
* This module implements Integrated Color Matching utilities
|
|
*
|
|
* Author:
|
|
*
|
|
* Mark Enstrom (marke) 02-13-95
|
|
* (Directly ported from Chicago)
|
|
*
|
|
* Copyright (c) 1993 Microsoft Corporation
|
|
\**************************************************************************/
|
|
|
|
#include "precomp.hxx"
|
|
|
|
|
|
typedef struct _FILEVIEW_ICM
|
|
{
|
|
HANDLE hFile; // File handle
|
|
HANDLE hMapFile; // File mapping handle
|
|
PBYTE pView; // Pointer to memory mapped file
|
|
} FILEVIEW_ICM, *PFILEVIEW_ICM;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef ICM_ENABLED
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
void myprintf( char *pszFormat, ... );
|
|
#define eprintf(psz,v) myprintf(psz,v)
|
|
#define tprintf(psz,v)
|
|
#else
|
|
#define myprintf(psz,v)
|
|
#define eprintf(psz,v)
|
|
#define tprintf(psz,v)
|
|
#endif
|
|
|
|
extern DWORD dwSystemID;
|
|
|
|
WCHAR num[] = L"0123456789";
|
|
|
|
WCHAR szICMRegPath[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\ICM";
|
|
WCHAR szICMatchers[] = L"ICMatchers";
|
|
WCHAR szICMInited[] = L"ICMInited";
|
|
|
|
WCHAR szManuTag[] = L"ManufacturerTag";
|
|
WCHAR szModelTag[] = L"ModelTag";
|
|
|
|
WCHAR szP[] = L"profile";
|
|
WCHAR szICP[] = L"ICMProfile";
|
|
WCHAR szICPd[] = L"ICMProfiled";
|
|
WCHAR szDefault[] = L"default";
|
|
|
|
WCHAR *DispProfs[] = {L"mnB22G15.icm",
|
|
L"mnB22G18.icm",
|
|
L"mnB22G21.icm",
|
|
L"mnEBUG15.icm",
|
|
L"mnEBUG18.icm",
|
|
L"mnEBUG21.icm",
|
|
L"mnP22G15.icm",
|
|
L"mnP22G18.icm",
|
|
L"mnP22G21.icm"
|
|
};
|
|
|
|
WCHAR *MediaType[] = {L"MediaUnknown",
|
|
L"Standard",
|
|
L"Glossy",
|
|
L"Transparency"
|
|
};
|
|
|
|
WCHAR *DitherType[] = {L"DitherUnknown",
|
|
L"NoDither",
|
|
L"Coarse",
|
|
L"Fine",
|
|
L"LineArt",
|
|
L"Grayscale"
|
|
};
|
|
|
|
WCHAR szDriver[80] = L"System\\CurrentControlSet\\Services\\Class\\";
|
|
WCHAR szregPrint[] = L"Enum\\Root\\Printer";
|
|
|
|
#define NUM_PRTR_SUBSTS 23
|
|
WCHAR szPrtrSubsts[] = L"HP EE82HP EF90"
|
|
L"HP EE70HP EF90"
|
|
L"HP 31D5HP EF90"
|
|
L"HP E8B0HP EE70"
|
|
L"CANOE06BCANO1D62"
|
|
L"CANOC8C8CANODE03"
|
|
L"EPSO468AEPSOA999"
|
|
L"TEKTEADBTEKT72F7"
|
|
L"TEKTC2A0TEKT72F7"
|
|
L"TEKTE470TEKT72F7"
|
|
L"TEKT2453TEKT72F7"
|
|
L"TEKT8624TEKT72F7"
|
|
L"TEKT8EC3TEKT72F7"
|
|
L"TEKT2A43TEKT72F7"
|
|
L"TEKTF5EATEKT72F7"
|
|
L"TEKT354BTEKT72F7"
|
|
L"TEKTF4FATEKT72F7"
|
|
L"TEKTF908TEKTCF25"
|
|
L"TEKT39A9TEKTCF25"
|
|
L"TEKTF818TEKTCF25"
|
|
L"TEKTD40FTEKTCF25"
|
|
L"TEKT14AETEKTCF25"
|
|
L"TEKTD51FTEKTCF25";
|
|
|
|
extern WCHAR szColorDir[];
|
|
|
|
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,
|
|
};
|
|
|
|
BOOL AddICToRegistry(PFILEVIEW_ICM, PWSTR, BOOL);
|
|
BOOL MapICFile(PWSTR, PFILEVIEW_ICM);
|
|
void UnmapICFile(PFILEVIEW_ICM);
|
|
BOOL RecurseReg(HKEY, PWSTR, int, int);
|
|
void word_to_ascii(DWORD, PDWORD);
|
|
void Derive_Manu_and_Model(PWSTR, DWORD []);
|
|
BOOL Get_Profile_From_MMI(HKEY, PWSTR, DWORD []);
|
|
void Get_CRC_CheckSum(PVOID, ULONG, PULONG);
|
|
VOID record_manufacturer(HKEY, PFILEVIEW_ICM, PWSTR);
|
|
VOID record_model(HKEY, PFILEVIEW_ICM, PWSTR);
|
|
BOOL GetRealDriverInfo(PWSTR, PWSTR);
|
|
int EnumProfileNames(HKEY, ICMENUMPROC, LPARAM);
|
|
BOOL check_file_existence(PWSTR);
|
|
WORD Swap2Bytes(WORD);
|
|
DWORD SwapBytes(DWORD);
|
|
DWORD *GetTagPtr(PBYTE, DWORD);
|
|
|
|
LONG
|
|
IcmOpenKey(
|
|
HANDLE hKeyIn,
|
|
PWSTR pwStr,
|
|
HANDLE *hKey
|
|
);
|
|
LONG
|
|
IcmQueryValueEx(
|
|
HKEY hKey,
|
|
LPWSTR lpwValueName,
|
|
LPDWORD res,
|
|
LPDWORD lpdwType,
|
|
LPBYTE lpbData,
|
|
LPDWORD lpcbData
|
|
);
|
|
LONG
|
|
IcmSetValueEx(
|
|
HKEY hKey,
|
|
LPWSTR lpwValueName,
|
|
DWORD dwReserved,
|
|
DWORD fdwType,
|
|
CONST BYTE * lpbData,
|
|
DWORD cbData
|
|
);
|
|
LONG
|
|
IcmCloseKey(
|
|
HKEY hKey
|
|
);
|
|
|
|
LONG
|
|
IcmEnumKey(
|
|
HANDLE hKeyIn,
|
|
DWORD iSubKey,
|
|
PWSTR pwName,
|
|
DWORD NameLength
|
|
);
|
|
|
|
LONG
|
|
IcmCreateKey(
|
|
HANDLE hKeyIn,
|
|
PWSTR pwStr,
|
|
HANDLE *hKey
|
|
);
|
|
|
|
LONG
|
|
IcmDeleteKey(
|
|
HANDLE hKeyIn,
|
|
PWSTR pwStr
|
|
);
|
|
|
|
LONG
|
|
IcmDeleteValue(
|
|
HKEY hKey,
|
|
PWSTR lpwValueName
|
|
);
|
|
|
|
//
|
|
// BUGBUG no PFILETIME
|
|
//
|
|
//LONG
|
|
//IcmQueryInfoKey(
|
|
// HKEY hKey,
|
|
// LPWSTR lpszClass,
|
|
// LPDWORD lpcchClass,
|
|
// LPDWORD lpdwReserved,
|
|
// LPDWORD lpcSubKeys,
|
|
// LPDWORD lpcchMaxSubkey,
|
|
// LPDWORD lpcchMaxClass,
|
|
// LPDWORD lpcValues,
|
|
// LPDWORD lpcchMaxValueName,
|
|
// LPDWORD lpcbMaxValueData,
|
|
// LPDWORD lpcbSecurityDescriptor,
|
|
// PFILETIME lpftLastWriteTime
|
|
// );
|
|
|
|
LONG
|
|
IcmEnumValue(
|
|
HKEY hKey,
|
|
DWORD iValue,
|
|
LPWSTR lpszValue,
|
|
LPDWORD lpcchValue,
|
|
LPDWORD lpdwReserved,
|
|
LPDWORD lpdwType,
|
|
LPBYTE lpbData,
|
|
LPDWORD lpcbData
|
|
);
|
|
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* Routine Name
|
|
*
|
|
* icm_FindMonitorProfile
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* Find the monitor profile
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pBuffer - points to a buffer to fill in with the filename of the
|
|
* profile to use; if null then no filename is wanted, rather
|
|
* enumeration of all profiles is going to be done, what is
|
|
* wanted is the regkey of the terminal branch
|
|
*
|
|
* Return Value:
|
|
*
|
|
* int - FALSE if no profile or regkey to be found
|
|
* TRUE if filename found
|
|
* hRegKey if terminal branch found for enum case
|
|
*
|
|
\**************************************************************************/
|
|
|
|
int
|
|
icm_FindMonitorProfile(
|
|
PWSTR pBuffer,
|
|
DWORD hack
|
|
)
|
|
{
|
|
int bResult = FALSE;
|
|
HKEY hkLocalMachine;
|
|
HKEY hkMonitor = 0;
|
|
HKEY hkICM = 0;
|
|
HKEY hkICMmntr = 0;
|
|
int i;
|
|
int defaultProfile = 0;
|
|
WORD Modl;
|
|
DWORD Transfer = 0;
|
|
DWORD Model[4] = {0, 0, 0, 0};
|
|
PWSTR ptempBuf;
|
|
WCHAR tempBuf[3];
|
|
DWORD ValueType;
|
|
DWORD ValueSize;
|
|
WCHAR ValueOfValue[MAX_PATH];
|
|
|
|
//
|
|
// open registry base
|
|
//
|
|
|
|
if (IcmOpenKey(NULL,
|
|
L"\\Registry\\Machine",
|
|
&hkLocalMachine) != ERROR_SUCCESS)
|
|
{
|
|
goto FMPReturn;
|
|
}
|
|
|
|
//
|
|
// First we need to look in the registry for the monitor that the user
|
|
// is using, due to the fun way the registry is structured there is
|
|
// one level of indirection.
|
|
//
|
|
// Open the key that tells us the monitor.
|
|
//
|
|
|
|
if (IcmOpenKey(hkLocalMachine,
|
|
L"Software\\ENUM\\Monitor\\Default_Monitor\\0001",
|
|
&hkMonitor) != ERROR_SUCCESS)
|
|
{
|
|
goto FMPReturn;
|
|
}
|
|
|
|
//
|
|
// Query for the driver section to look in.
|
|
//
|
|
|
|
ValueSize = MAX_PATH;
|
|
|
|
if (
|
|
IcmQueryValueEx(hkMonitor,
|
|
L"Driver",
|
|
0,
|
|
&ValueType,
|
|
(LPBYTE)ValueOfValue,
|
|
&ValueSize) != ERROR_SUCCESS)
|
|
{
|
|
goto FMPCloseKeys;
|
|
}
|
|
|
|
//
|
|
// Done with this key.
|
|
//
|
|
|
|
IcmCloseKey(hkMonitor);
|
|
|
|
//
|
|
// Copy the driver string description onto the class string.
|
|
// And then see if that exists in the registry.
|
|
//
|
|
|
|
szDriver[sizeof(L"System\\CurrentControlSet\\Services\\Class\\") - sizeof(WCHAR)] = 0;
|
|
|
|
wcscat(szDriver,ValueOfValue);
|
|
|
|
if (IcmOpenKey(hkLocalMachine,szDriver,&hkMonitor) != ERROR_SUCCESS)
|
|
{
|
|
goto FMPReturn;
|
|
}
|
|
|
|
//
|
|
// Okay, we're to the driver section. Let's see if we've already
|
|
// determined a profile for this sucker, the string ICMProfile is
|
|
// what we're looking for. This can have either one of two meanings.
|
|
// 1) It gives us the name of a profile to use. In this case if
|
|
// the profile still exists or/and is accessible (think of the
|
|
// net case) then we are done. 2) This is an index into the set of
|
|
// generic monitor profiles shipped in the box. Monitors.inf has some
|
|
// default values for some monitors which get set at setup time. Or
|
|
// third party utilities can pick a different default. This index
|
|
// is used as a fallback, we still check to see if there are more
|
|
// robust methods of determining which profile to use.
|
|
// Note that GDI does not set a value for ICMProfile, basically
|
|
// due to paranoia. GDI does not want to deal with the different
|
|
// scenarios of profiles coming and going. In the future perhaps.
|
|
// For now it is up to third party utilities which construct or
|
|
// provide great profiles to set this to the name of the great profile.
|
|
//
|
|
|
|
if (pBuffer)
|
|
{
|
|
ptempBuf = pBuffer;
|
|
ValueSize = MAX_PATH;
|
|
}
|
|
else
|
|
{
|
|
ptempBuf = (PWSTR) &tempBuf;
|
|
ValueSize = 3 * sizeof(WCHAR);
|
|
}
|
|
|
|
if (IcmQueryValueEx(hkMonitor,
|
|
szICP,
|
|
0,
|
|
&ValueType,
|
|
(LPBYTE)ptempBuf,
|
|
&ValueSize) == ERROR_SUCCESS)
|
|
{
|
|
if (ValueType == REG_BINARY)
|
|
{
|
|
i = (int) (BYTE) *ptempBuf;
|
|
if ((i >= 1) && (i <= 9))
|
|
{
|
|
defaultProfile = i;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// If setting up for an enum we don't want to stop
|
|
// here, but there is no way to enforce this
|
|
// profile being in its appropriate section.
|
|
//
|
|
|
|
if (pBuffer)
|
|
{
|
|
if (check_file_existence(pBuffer))
|
|
{
|
|
bResult = TRUE;
|
|
goto FMPCloseKeys;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// No defined profile, let's open the mini-database of profiles.
|
|
//
|
|
|
|
if (IcmOpenKey(hkLocalMachine,
|
|
L"Software\\Microsoft\\Windows\\CurrentVersion\\ICM\\mntr",
|
|
&hkICMmntr) != ERROR_SUCCESS)
|
|
{
|
|
goto FMPCloseKeys;
|
|
}
|
|
|
|
//
|
|
// Let's do the EDID thing. The EDID is the information passed back
|
|
// to Windows from Plug and Play monitors, all 80h bytes of it. It has
|
|
// lots of good stuff in it, like refresh rates, resolutions, and
|
|
// color info. What we are interested in here are the manu and modl
|
|
// ID's. These are packed tightly into a few bytes, if I had the
|
|
// spec in front of me I'd tell you exactly how, but I don't so
|
|
// you'll have to read the code.
|
|
//
|
|
|
|
ValueSize = sizeof(EDID);
|
|
if (IcmQueryValueEx(hkMonitor,
|
|
L"EDID",
|
|
0,
|
|
&ValueType,
|
|
(LPBYTE)ValueOfValue,
|
|
&ValueSize) == ERROR_SUCCESS)
|
|
{
|
|
Transfer = (DWORD)Swap2Bytes((WORD)((EDID *)ValueOfValue)->ids.manu);
|
|
Model[0] = ' ';
|
|
for (i = 0; i < 3; i++)
|
|
{
|
|
Model[0] <<= 8;
|
|
Model[0] |= (Transfer & 0x1F) + ('A' - 1);
|
|
Transfer >>= 5;
|
|
}
|
|
|
|
Modl = (WORD)Swap2Bytes((WORD)((EDID *)ValueOfValue)->ids.modl);
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
Model[2] <<= 8;
|
|
Transfer = (Modl & 0xF);
|
|
|
|
if (Transfer > 9)
|
|
{
|
|
Transfer += ('A'- 0xA);
|
|
}
|
|
else
|
|
{
|
|
Transfer += '0';
|
|
}
|
|
|
|
Model[2] |= Transfer;
|
|
Modl >>= 4;
|
|
}
|
|
|
|
if (bResult = Get_Profile_From_MMI(hkICMmntr, pBuffer, Model))
|
|
{
|
|
goto FMPRecordICProfile;
|
|
}
|
|
|
|
|
|
//
|
|
// If here we should create a profile based on the colorimetric info
|
|
// from the EDID. This can wait for Nashville.
|
|
//
|
|
|
|
}
|
|
|
|
//
|
|
// No EDID thing, did the user tell us the monitor being used?
|
|
//
|
|
|
|
ValueSize = MAX_PATH;
|
|
|
|
if (IcmQueryValueEx(hkMonitor,
|
|
L"DriverDesc",
|
|
0,
|
|
&ValueType,
|
|
(PBYTE)ValueOfValue,
|
|
&ValueSize) == ERROR_SUCCESS)
|
|
{
|
|
Derive_Manu_and_Model(ValueOfValue, Model);
|
|
}
|
|
|
|
if (wcscmp(ValueOfValue, L"(Unknown Monitor)") && (Model[0]))
|
|
{
|
|
if (bResult = Get_Profile_From_MMI(hkICMmntr, pBuffer, Model))
|
|
{
|
|
goto FMPRecordICProfile;
|
|
}
|
|
|
|
//
|
|
// At this point there is not an icm branch for the manu and model
|
|
// of the display. We use the default derived above. Failing that
|
|
// we look in the substitution list.
|
|
//
|
|
|
|
if (pBuffer)
|
|
{
|
|
//
|
|
// Are the manu and model in the substitution list?
|
|
//
|
|
|
|
if (IcmOpenKey(hkLocalMachine,szICMRegPath, &hkICM) == ERROR_SUCCESS)
|
|
{
|
|
ValueSize = MAX_PATH;
|
|
|
|
if (IcmQueryValueEx(hkICM,
|
|
L"SubstList",
|
|
0,
|
|
&ValueType,
|
|
(PBYTE)ValueOfValue,
|
|
&ValueSize) == ERROR_SUCCESS)
|
|
{
|
|
for (i = 0; i < (int)(ValueSize - (int)(4 * sizeof(DWORD)));i += 4 * (int)(sizeof(DWORD)))
|
|
{
|
|
if (Model[0] == *((DWORD *)&ValueOfValue[i]))
|
|
{
|
|
if (Model[2] == *((DWORD *)&ValueOfValue[i+4]))
|
|
{
|
|
|
|
Model[0] = *((DWORD *)&ValueOfValue[i+8]);
|
|
Model[2] = *((DWORD *)&ValueOfValue[i+12]);
|
|
|
|
if (SwapBytes(Model[0]) < '0001' || SwapBytes(Model[0]) > '0009')
|
|
{
|
|
if (bResult = Get_Profile_From_MMI(hkICMmntr, pBuffer, Model))
|
|
{
|
|
goto FMPRecordICProfile;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!defaultProfile)
|
|
{
|
|
defaultProfile = (SwapBytes(Model[0]) - '0000');
|
|
}
|
|
goto FMPRecordICProfile;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// "ICMProfiled" is for informational, debugging purposes only.
|
|
//
|
|
|
|
FMPRecordICProfile:
|
|
if (bResult && pBuffer)
|
|
{
|
|
IcmSetValueEx(hkMonitor,
|
|
szICPd,
|
|
0,
|
|
REG_SZ,
|
|
(PBYTE)pBuffer,
|
|
wcslen(pBuffer));
|
|
}
|
|
|
|
FMPCloseKeys:
|
|
|
|
if (hkICM)
|
|
{
|
|
IcmCloseKey(hkICM);
|
|
}
|
|
|
|
if (hkICMmntr)
|
|
{
|
|
IcmCloseKey(hkICMmntr);
|
|
}
|
|
|
|
if (hkMonitor)
|
|
{
|
|
IcmCloseKey(hkMonitor);
|
|
}
|
|
|
|
|
|
FMPReturn:
|
|
|
|
if (hkLocalMachine)
|
|
{
|
|
IcmCloseKey(hkLocalMachine);
|
|
}
|
|
|
|
if (!bResult)
|
|
{
|
|
if (!defaultProfile)
|
|
{
|
|
//
|
|
// this is the default profile for the NEC4FG
|
|
//
|
|
|
|
defaultProfile = 2;
|
|
}
|
|
|
|
if (pBuffer)
|
|
{
|
|
wcscpy(pBuffer, szColorDir);
|
|
wcscat(pBuffer, L"\\");
|
|
wcscat(pBuffer, DispProfs[defaultProfile - 1]);
|
|
|
|
if (check_file_existence(pBuffer))
|
|
{
|
|
return (TRUE);
|
|
}
|
|
else
|
|
{
|
|
return (FALSE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return (defaultProfile);
|
|
}
|
|
}
|
|
return (bResult);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* Routine Name
|
|
*
|
|
* icm_FindPrinterProfile
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* Find theprinter ICM profile
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pBuffer - points to a buffer to fill in with the filename of the
|
|
* profile to use; if null then no filename is wanted, rather
|
|
* enumeration of all profiles is going to be done, what is
|
|
* wanted is the regkey of the terminal branch
|
|
*
|
|
* devmode - ??? we don;t have one of these!
|
|
*
|
|
* unfriendly_name - ??? no idea
|
|
*
|
|
* Return Value:
|
|
*
|
|
* int - FALSE if no profile or regkey to be found
|
|
* TRUE if filename found
|
|
* hRegKey if terminal branch found for enum case
|
|
*
|
|
\**************************************************************************/
|
|
|
|
int
|
|
icm_FindPrinterProfile(
|
|
PWSTR pBuffer,
|
|
PDEVMODEW devmode,
|
|
PWSTR unfriendly_name
|
|
)
|
|
{
|
|
int bResult = FALSE;
|
|
HKEY hkPrint = 0;
|
|
HKEY hkPrinter = 0;
|
|
HKEY hkLocalMachine;
|
|
WCHAR number[5] = L"0000";
|
|
HKEY hkICM = 0;
|
|
HKEY hkICMprtr = 0;
|
|
HKEY hkManu = 0;
|
|
HKEY hkModl = 0;
|
|
HKEY hkMedia = 0;
|
|
HKEY hkDither = 0;
|
|
DWORD CheckSum = 0;
|
|
DWORD Model[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
|
PWSTR pStr = (PWSTR)NULL;
|
|
int i, j;
|
|
WCHAR NameOfValue[16];
|
|
DWORD ValueType;
|
|
DWORD ValueSize;
|
|
char ValueOfValue[MAX_PATH];
|
|
WCHAR SubstString[MAX_PATH + (0x10 * NUM_PRTR_SUBSTS)];
|
|
|
|
//
|
|
// open registry base
|
|
//
|
|
|
|
if (IcmOpenKey(NULL,
|
|
L"\\Registry\\Machine",
|
|
&hkLocalMachine) != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// If the printer branch of the ICM branch doesn't exist, there is
|
|
// no reason to continue.
|
|
//
|
|
|
|
if (IcmOpenKey(hkLocalMachine,
|
|
L"Software\\Microsoft\\Windows\\CurrentVersion\\ICM\\prtr",
|
|
&hkICMprtr) != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
|
|
//
|
|
// BUGBUG Devmode wrong
|
|
//
|
|
//if (!devmode->dmICCManufacturer) // does the devmode have the knowledge?
|
|
if (FALSE)
|
|
{
|
|
//
|
|
// For complete correctness the devmode really must tell us the
|
|
// manufacturer and model. But if here then it doesn't so we
|
|
// just use the unfriendly name to derive these quantities.
|
|
// (Also it would have made sense to use the BIDI printer stuff
|
|
// to determine ID's, but that simply did not come together in
|
|
// time.)
|
|
//
|
|
|
|
Derive_Manu_and_Model(unfriendly_name, Model);
|
|
|
|
if (!Model[0])
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
if (IcmOpenKey(hkICMprtr,(WCHAR *)&Model[0], &hkManu) == ERROR_SUCCESS)
|
|
{
|
|
if (IcmOpenKey(hkManu,(WCHAR *)&Model[2], &hkModl) != ERROR_SUCCESS)
|
|
{
|
|
IcmCloseKey(hkManu);
|
|
|
|
//
|
|
// We can't seem to find nothing. Are the manu & model in the subst list?
|
|
//
|
|
|
|
if (IcmOpenKey(hkLocalMachine,szICMRegPath, &hkICM) == ERROR_SUCCESS)
|
|
{
|
|
ValueSize = MAX_PATH;
|
|
if (IcmQueryValueEx(hkICM,
|
|
L"SubstList",
|
|
0,
|
|
&ValueType,
|
|
(PBYTE)ValueOfValue,
|
|
&ValueSize) == ERROR_SUCCESS)
|
|
{
|
|
wcscpy(SubstString, szPrtrSubsts);
|
|
wcscat(SubstString, (WCHAR *)ValueOfValue);
|
|
|
|
for (i = 0; i < (int)(ValueSize - (int)(4 * sizeof(DWORD)));i += 4 * (int)(sizeof(DWORD)))
|
|
{
|
|
if (Model[0] == *((DWORD *)&SubstString[i]))
|
|
{
|
|
if (Model[2] == *((DWORD *)&SubstString[i+4]))
|
|
{
|
|
Model[4] = *((DWORD *)&SubstString[i+8]);
|
|
Model[6] = *((DWORD *)&SubstString[i+12]);
|
|
if (IcmOpenKey(hkICMprtr, (WCHAR *)&Model[4], &hkManu) == ERROR_SUCCESS)
|
|
{
|
|
if (IcmOpenKey(hkManu, (WCHAR *)&Model[6], &hkModl) == ERROR_SUCCESS)
|
|
{
|
|
break;
|
|
}
|
|
IcmCloseKey(hkManu);
|
|
hkManu = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// BUGBUG Devmode
|
|
//
|
|
//Model[0] = devmode->dmICCManufacturer;
|
|
Model[0] = 0;
|
|
|
|
if (IcmOpenKey(hkICMprtr,
|
|
(WCHAR *)&Model[0],
|
|
&hkManu) != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// BUGBUG Devmode
|
|
//
|
|
//Model[0] = devmode->dmICCModel;
|
|
|
|
if (IcmOpenKey(hkManu,
|
|
(WCHAR *)&Model[0],
|
|
&hkModl) != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// A small question arises as to the applicability of a profile that
|
|
// does not match in all of the fields. Should we fail and say that
|
|
// we don't have a profile if the manu and modl match but, say, the
|
|
// media is wrong? My purist attitude says that the match is incom-
|
|
// plete and that the match should fail. For the nonce though we
|
|
// will let it succeed. If we get to a node that doesn't have the
|
|
// specified attribute wanted then we will pick a neighbor of that
|
|
// specified and continue as if nothing was wrong. If there is no
|
|
// neighbor then we fail out.
|
|
//
|
|
|
|
//
|
|
// BUGBUG devmode wrong
|
|
//
|
|
//if (devmode->dmMediaType > DMMEDIA_USER)
|
|
//{
|
|
// word_to_ascii(devmode->dmMediaType, (PDWORD)&number);
|
|
// pStr = (PWSTR)&number;
|
|
//}
|
|
//else
|
|
//{
|
|
// pStr = MediaType[devmode->dmMediaType];
|
|
//}
|
|
|
|
if (IcmOpenKey(hkModl, pStr, &hkMedia) != ERROR_SUCCESS)
|
|
{
|
|
if (IcmEnumKey(hkModl, 0, (WCHAR *)ValueOfValue, MAX_PATH) != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
if (IcmOpenKey(hkModl, (WCHAR *)ValueOfValue, &hkMedia) != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
//
|
|
//
|
|
// BUGBUG Devmode
|
|
//
|
|
//if (devmode->dmDitherType > DMDITHER_USER)
|
|
//{
|
|
// word_to_ascii(devmode->dmDitherType, (PDWORD)&number);
|
|
// pStr = (PWSTR)&number;
|
|
//}
|
|
//else
|
|
//{
|
|
// pStr = DitherType[devmode->dmDitherType];
|
|
//}
|
|
|
|
if (IcmOpenKey(hkMedia, pStr, &hkDither) != ERROR_SUCCESS)
|
|
{
|
|
if (IcmEnumKey(hkMedia, 0, (WCHAR *)ValueOfValue, MAX_PATH) != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
if (IcmOpenKey(hkMedia, (WCHAR *)ValueOfValue, &hkDither) != ERROR_SUCCESS)
|
|
{
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
if (!pBuffer)
|
|
{
|
|
//
|
|
// enum starter wanted
|
|
//
|
|
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// !!! This code could be shared with get_profi... below.
|
|
// Check to see if a default has been set.
|
|
//
|
|
|
|
ValueSize = MAX_PATH;
|
|
|
|
if (IcmQueryValueEx(hkDither,
|
|
szDefault,
|
|
0,
|
|
&ValueType,
|
|
(PBYTE)pBuffer,
|
|
&ValueSize) == ERROR_SUCCESS)
|
|
{
|
|
ValueSize = MAX_PATH;
|
|
|
|
if (IcmQueryValueEx(hkDither,
|
|
pBuffer,
|
|
0,
|
|
&ValueType,
|
|
(PBYTE)pBuffer,
|
|
&ValueSize) == ERROR_SUCCESS)
|
|
{
|
|
bResult = check_file_existence(pBuffer);
|
|
}
|
|
}
|
|
|
|
if (!bResult)
|
|
{
|
|
//
|
|
// No default, go for the first "profileXX" that is accessable.
|
|
//
|
|
|
|
wcscpy((WCHAR *)NameOfValue, szP);
|
|
NameOfValue[9] = 0;
|
|
|
|
for (i=0 ;i<10 ; i++)
|
|
{
|
|
NameOfValue[7] = num[i];
|
|
|
|
for (j=0 ;j<10 ; j++)
|
|
{
|
|
ValueSize = MAX_PATH;
|
|
NameOfValue[8] = num[j];
|
|
if (IcmQueryValueEx(hkDither,
|
|
NameOfValue,
|
|
0,
|
|
&ValueType,
|
|
(PBYTE)pBuffer,
|
|
&ValueSize) == ERROR_SUCCESS)
|
|
{
|
|
if (bResult = check_file_existence(pBuffer))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (bResult)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
exit:
|
|
|
|
if (hkLocalMachine)
|
|
{
|
|
IcmCloseKey(hkLocalMachine);
|
|
}
|
|
|
|
if (hkPrint)
|
|
{
|
|
IcmCloseKey(hkPrint);
|
|
}
|
|
|
|
if (hkPrinter)
|
|
{
|
|
IcmCloseKey(hkPrinter);
|
|
}
|
|
|
|
if (hkICM)
|
|
{
|
|
IcmCloseKey(hkICM);
|
|
}
|
|
|
|
if (hkICMprtr)
|
|
{
|
|
IcmCloseKey(hkICMprtr);
|
|
}
|
|
|
|
if (hkManu)
|
|
{
|
|
IcmCloseKey(hkManu);
|
|
}
|
|
|
|
if (hkModl)
|
|
{
|
|
IcmCloseKey(hkModl);
|
|
}
|
|
|
|
if (hkMedia)
|
|
{
|
|
IcmCloseKey(hkMedia);
|
|
}
|
|
|
|
|
|
if (pBuffer)
|
|
{
|
|
if (hkDither)
|
|
{
|
|
IcmCloseKey(hkDither);
|
|
}
|
|
return (bResult);
|
|
}
|
|
else
|
|
{
|
|
return ((int)hkDither);
|
|
}
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* Routine Name
|
|
*
|
|
* Derive_Manu_and_Model
|
|
*
|
|
* Routine Description:
|
|
*
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
* devicedesc -
|
|
* pulModel[] -
|
|
*
|
|
* Return Value:
|
|
*
|
|
* None
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
Derive_Manu_and_Model(
|
|
PWSTR devicedesc,
|
|
DWORD pulModel[]
|
|
)
|
|
{
|
|
int i;
|
|
WCHAR *pbyte;
|
|
DWORD Transfer;
|
|
DWORD CheckSum;
|
|
|
|
//
|
|
// Define the manufacturer to be the first 4 characters of the
|
|
// DriverDesc string. 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 = devicedesc;
|
|
|
|
for (i = 0; i < 4; i++, pbyte++)
|
|
{
|
|
if (*pbyte == L' ' || *pbyte == L'-')
|
|
{
|
|
for (; i < 4; i++)
|
|
{
|
|
// pulModel[0] >>= 8; !!! broken for sure
|
|
// pulModel[0] |= L' ' << 24;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pulModel[0] >>= 8;
|
|
Transfer = (DWORD) *pbyte;
|
|
|
|
if (Transfer >= L'a' && Transfer <= L'z')
|
|
{
|
|
Transfer -= 0x20;
|
|
}
|
|
pulModel[0] |= (Transfer << 24);
|
|
}
|
|
}
|
|
|
|
//
|
|
// 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.
|
|
//
|
|
|
|
CheckSum = 0;
|
|
Get_CRC_CheckSum(devicedesc, wcslen(devicedesc), &CheckSum);
|
|
word_to_ascii(CheckSum, &pulModel[2]);
|
|
}
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* Routine Name
|
|
*
|
|
* Get_Profile_From_MMI
|
|
*
|
|
* Routine Description:
|
|
*
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
* hkICM -
|
|
* pBuffer -
|
|
* Model[] -
|
|
*
|
|
* Return Value:
|
|
*
|
|
*
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BOOL
|
|
Get_Profile_From_MMI(
|
|
HKEY hkICM,
|
|
PWSTR pBuffer,
|
|
DWORD Model[]
|
|
)
|
|
{
|
|
HKEY hkManu;
|
|
HKEY hkModl;
|
|
int i,j;
|
|
WCHAR NameOfValue[16];
|
|
DWORD ValueType;
|
|
DWORD ValueSize;
|
|
int bResult = FALSE;
|
|
|
|
if (IcmOpenKey(hkICM, (WCHAR *)&Model[0], &hkManu) == ERROR_SUCCESS)
|
|
{
|
|
if (IcmOpenKey(hkManu, (WCHAR *)&Model[2], &hkModl) == ERROR_SUCCESS)
|
|
{
|
|
if (pBuffer)
|
|
{
|
|
//
|
|
// Check to see if a default has been set.
|
|
//
|
|
|
|
ValueSize = MAX_PATH;
|
|
|
|
if (IcmQueryValueEx(hkModl,
|
|
szDefault,
|
|
0,
|
|
&ValueType,
|
|
(PBYTE)pBuffer,
|
|
&ValueSize) == ERROR_SUCCESS)
|
|
{
|
|
ValueSize = MAX_PATH;
|
|
|
|
if (IcmQueryValueEx(hkModl,
|
|
pBuffer,
|
|
0,
|
|
&ValueType,
|
|
(PBYTE)pBuffer,
|
|
&ValueSize) == ERROR_SUCCESS)
|
|
{
|
|
bResult = check_file_existence(pBuffer);
|
|
}
|
|
}
|
|
|
|
if (!bResult)
|
|
{
|
|
|
|
//
|
|
// No default, go for the first "profileXX" that is accessable.
|
|
//
|
|
|
|
wcscpy(NameOfValue, szP);
|
|
NameOfValue[9] = 0;
|
|
|
|
for (i=0 ;i<10 ; i++)
|
|
{
|
|
NameOfValue[7] = num[i];
|
|
|
|
for (j=0 ;j<10 ; j++)
|
|
{
|
|
ValueSize = MAX_PATH;
|
|
NameOfValue[8] = num[j];
|
|
|
|
if (IcmQueryValueEx(hkModl,
|
|
NameOfValue,
|
|
0,
|
|
&ValueType,
|
|
(PBYTE)pBuffer,
|
|
&ValueSize) == ERROR_SUCCESS)
|
|
{
|
|
if (bResult = check_file_existence(pBuffer))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bResult)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
IcmCloseKey(hkModl);
|
|
|
|
}
|
|
else
|
|
{
|
|
bResult = (int)hkModl;
|
|
}
|
|
}
|
|
|
|
IcmCloseKey(hkManu);
|
|
|
|
}
|
|
return (bResult);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* Routine Name
|
|
*
|
|
* Get_CRC_CheckSum
|
|
*
|
|
* Routine Description:
|
|
*
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pBuffer -
|
|
* ulSize -
|
|
* pulSeed -
|
|
*
|
|
* Return Value:
|
|
*
|
|
* None
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
Get_CRC_CheckSum(
|
|
PVOID pBuffer,
|
|
ULONG ulSize,
|
|
PULONG pulSeed
|
|
)
|
|
{
|
|
PBYTE pb;
|
|
BYTE bTmp;
|
|
|
|
//
|
|
// Use CRC16 as the CRC function.
|
|
// Algorithm from Stu Wecker (Digital memo 130-959-002-00).
|
|
//
|
|
|
|
for (pb=(BYTE *)pBuffer; ulSize; ulSize--, pb++)
|
|
{
|
|
//
|
|
// Xor CRC with new char
|
|
//
|
|
|
|
bTmp=(BYTE)(((WORD)*pb)^((WORD)*pulSeed));
|
|
*pulSeed=((*pulSeed)>>8) ^ wCRC16a[bTmp&0x0F] ^ wCRC16b[bTmp>>4];
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* Routine Name
|
|
*
|
|
* UpdateICMRegKey
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* This is a little catch-all routine. Since Daytona has shipped we really
|
|
* can't add any new API's. So we overload this one, but we do so politely
|
|
* only with functions that have to do with manipulating the ICM branch
|
|
* in the registry.
|
|
*
|
|
* ICM_UPDATEREG does a complete updating of the color directory
|
|
* ICM_ADDPROFILE adds a profile to the ICM branch
|
|
* ICM_DELETEPROFILE deletes a profile from the ICM branch
|
|
* ICM_QUERYPROFILE determines if a file is in the ICM branch
|
|
* ICM_SETDEFAULTPROFILE makes the given profile first among equals
|
|
* ICM_REGISTERICMATCHER tells gdi how to make an ICC icm id to dll
|
|
* ICM_UNREGISTERICMATCHER gets rid of the above
|
|
*
|
|
* Arguments:
|
|
*
|
|
* hwnd -
|
|
* hInst -
|
|
* szFileName -
|
|
* ncmdShow -
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BOOL
|
|
UpdateICMRegKey(
|
|
DWORD hwnd,
|
|
DWORD hInst,
|
|
PWSTR szFileName,
|
|
UINT ncmdShow
|
|
)
|
|
|
|
{
|
|
//
|
|
// BUGBUG win32_find_dataW and FindFile not defined
|
|
//
|
|
//
|
|
//
|
|
// HKEY hkColor;
|
|
// HKEY hkMatchers;
|
|
// HKEY hkLocalMachine;
|
|
// DWORD iDirNameLen;
|
|
// HANDLE hFindFile;
|
|
// BOOL bResult = FALSE;
|
|
// DWORD VType;
|
|
// WCHAR unfriendly_name[32];
|
|
// WCHAR DirName[MAX_PATH];
|
|
//
|
|
// FILEVIEW_ICM myfv;
|
|
// WIN32_FIND_DATAW ffd;
|
|
//
|
|
// //
|
|
// // try to open registry base
|
|
// //
|
|
//
|
|
// if (IcmOpenKey(NULL,
|
|
// L"Registry\\Machine",
|
|
// &hkLocalMachine) == ERROR_SUCCESS)
|
|
// {
|
|
//
|
|
// switch (ncmdShow)
|
|
// {
|
|
// case ICM_UPDATEREG:
|
|
//
|
|
// //
|
|
// // This little routine goes through all files in the color directory,
|
|
// // updating the registry as it encounters every icm file. We
|
|
// // only need to do this at first boot, so we use a little marker
|
|
// // to say we've done this.
|
|
// //
|
|
//
|
|
// iDirNameLen = MAX_PATH;
|
|
//
|
|
// if (IcmCreateKey(hkLocalMachine,
|
|
// szICMRegPath,
|
|
// &hkColor) == ERROR_SUCCESS)
|
|
//
|
|
// {
|
|
// if (IcmQueryValueEx(hkColor,
|
|
// szICMInited,
|
|
// 0,
|
|
// &VType,
|
|
// (PBYTE)DirName,
|
|
// &iDirNameLen) != ERROR_SUCCESS)
|
|
// {
|
|
// IcmSetValueEx(hkColor,
|
|
// szICMInited,
|
|
// 0,
|
|
// REG_SZ,
|
|
// (PBYTE)szICMInited,
|
|
// wcslen(szICMInited)
|
|
// );
|
|
//
|
|
// wcscpy(DirName, szColorDir);
|
|
//
|
|
// //
|
|
// // account for slash to come
|
|
// //
|
|
//
|
|
// iDirNameLen = wcslen(DirName) + 1;
|
|
// wcscat(DirName, L"\\*.*");
|
|
//
|
|
// if ((hFindFile = FindFirstFileW(DirName, &ffd)) != INVALID_HANDLE_VALUE)
|
|
// {
|
|
// do
|
|
// {
|
|
// if (!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
|
// {
|
|
// DirName[iDirNameLen]=0;
|
|
// wcscat(DirName, (PWSTR) &(ffd.cFileName));
|
|
// if (MapICFile(DirName, &myfv))
|
|
// {
|
|
// AddICToRegistry(&myfv, DirName, FALSE);
|
|
// UnmapICFile(&myfv);
|
|
// }
|
|
// }
|
|
// } while (FindNextFileW(hFindFile,&ffd));
|
|
//
|
|
// FindClose(hFindFile);
|
|
// bResult = TRUE;
|
|
// }
|
|
// }
|
|
// else
|
|
// {
|
|
// bResult = TRUE;
|
|
// }
|
|
// IcmCloseKey(hkColor);
|
|
// }
|
|
// break;
|
|
//
|
|
// case ICM_ADDPROFILE:
|
|
// if (MapICFile(szFileName, &myfv))
|
|
// {
|
|
// bResult = AddICToRegistry(&myfv, szFileName, FALSE);
|
|
// UnmapICFile(&myfv);
|
|
// }
|
|
// break;
|
|
//
|
|
// case ICM_DELETEPROFILE:
|
|
// case ICM_QUERYPROFILE:
|
|
// case ICM_SETDEFAULTPROFILE:
|
|
// if (IcmOpenKey(hkLocalMachine, szICMRegPath, &hkColor) == ERROR_SUCCESS)
|
|
// {
|
|
// bResult = RecurseReg(hkColor, szFileName, ncmdShow, 0);
|
|
// IcmCloseKey(hkColor);
|
|
// }
|
|
// break;
|
|
//
|
|
// case ICM_REGISTERICMATCHER:
|
|
// case ICM_UNREGISTERICMATCHER:
|
|
// if (IcmOpenKey(hkLocalMachine, szICMRegPath, &hkColor) == ERROR_SUCCESS)
|
|
// {
|
|
// if (IcmCreateKey(hkColor, szICMatchers, &hkMatchers) == ERROR_SUCCESS)
|
|
// {
|
|
// if (ncmdShow == ICM_REGISTERICMATCHER)
|
|
// {
|
|
// bResult = IcmSetValueEx(hkMatchers,
|
|
// (PWSTR)hInst,
|
|
// 0,
|
|
// REG_SZ,
|
|
// (PBYTE)szFileName,
|
|
// wcslen(szFileName));
|
|
// }
|
|
// else
|
|
// {
|
|
// bResult = IcmDeleteValue(hkMatchers, (PWSTR)hInst);
|
|
// }
|
|
// IcmCloseKey(hkMatchers);
|
|
// }
|
|
// IcmCloseKey(hkColor);
|
|
// }
|
|
// break;
|
|
//
|
|
// case ICM_QUERYMATCH:
|
|
//
|
|
// GetRealDriverInfo(szFileName, unfriendly_name);
|
|
//
|
|
// bResult = icm_FindPrinterProfile(DirName,
|
|
// (PDEVMODEW)szFileName,
|
|
// unfriendly_name);
|
|
// break;
|
|
//
|
|
// default:
|
|
// bResult = FALSE;
|
|
// break;
|
|
// }
|
|
// return bResult;
|
|
// }
|
|
//
|
|
// if (hkLocalMachine)
|
|
// {
|
|
// IcmCloseKey(hkLocalMachine);
|
|
// }
|
|
//
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* Routine Name
|
|
*
|
|
* MapICFile
|
|
*
|
|
* Routine Description:
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pszFile -
|
|
* pfv -
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BOOL
|
|
MapICFile(
|
|
PWSTR pszFile,
|
|
PFILEVIEW_ICM pfv
|
|
)
|
|
{
|
|
//
|
|
// BUGBUG Whole thing is mess
|
|
//
|
|
// HANDLE hFile, hMapFile;
|
|
// BOOL brc, bResult;
|
|
// PBYTE pView;
|
|
// DWORD dwRead, dwSize;
|
|
// CM_HEADER cmheader;
|
|
//
|
|
// //
|
|
// // Open existing file
|
|
// //
|
|
//
|
|
// bResult = FALSE;
|
|
// pView = NULL;
|
|
// hFile = 0; // BUGBUG INVALID_HANDLE_VALUE;
|
|
// hMapFile = 0; // BUGBUG INVALID_HANDLE_VALUE;
|
|
//
|
|
// //
|
|
// // BUGBUG
|
|
// //
|
|
// //hFile = CreateFileW(pszFile, // lpFileName
|
|
// // GENERIC_READ, // dwDesiredAccess
|
|
// // FILE_SHARE_READ, // dwShareMode
|
|
// // NULL, // lpSecurityAttributes
|
|
// // OPEN_EXISTING, // dwCreationDisposition
|
|
// // FILE_ATTRIBUTE_NORMAL, // dwFlagsAndAttributes
|
|
// // NULL ); // hTemplate
|
|
//
|
|
// if (hFile == 0) //BUGBUG INVALID_HANDLE_VALUE)
|
|
// {
|
|
// eprintf(" CreateFile failed, error #%d!\n", GetLastError());
|
|
// goto MCFReturn;
|
|
// }
|
|
//
|
|
// //
|
|
// // Get file size
|
|
// //
|
|
//
|
|
// // BUGBUG dwSize = GetFileSize( hFile, NULL );
|
|
//
|
|
// if (dwSize == 0xFFFFFFFF)
|
|
// {
|
|
// eprintf(" GetFileSize failed, error #%d\n", GetLastError());
|
|
// goto MCFCloseFile;
|
|
// }
|
|
//
|
|
// //
|
|
// // Quick check for proper InterColor header
|
|
// //
|
|
// // BUGBUG
|
|
// //brc = ReadFile(hFile, // File handle
|
|
// // &cmheader, // lpBuffer
|
|
// // sizeof(CM_HEADER), // nNumberOfBytesToRead
|
|
// // &dwRead, // lpNumberOfBytesRead
|
|
// // NULL); // lpOverlapped (???)
|
|
//
|
|
// if (!brc)
|
|
// {
|
|
// eprintf(" ReadFile failed, error #%d!\n", GetLastError());
|
|
// goto MCFCloseFile;
|
|
// }
|
|
//
|
|
// if (
|
|
// (dwRead != sizeof(CM_HEADER)) ||
|
|
// (SwapBytes(cmheader.CMPSize) != dwSize) ||
|
|
// (SwapBytes(cmheader.ProfileVersion) != 0x02000000)
|
|
// )
|
|
// {
|
|
// eprintf(" Invalid InterColor header, ignore #%d!\n", GetLastError());
|
|
// goto MCFCloseFile;
|
|
// }
|
|
//
|
|
// //
|
|
// // Create mapping handle
|
|
// //
|
|
// // BUGBUG
|
|
// //hMapFile = CreateFileMapping(hFile, // hFile
|
|
// // NULL, // lpFileMappingAttributes
|
|
// // PAGE_READONLY, // flProtect
|
|
// // 0, // dwMaximumSizeHigh
|
|
// // 0, // dwMaximumSizeLow
|
|
// // NULL ); // lpName
|
|
//
|
|
// if (hMapFile == 0) //BUGBUG INVALID_HANDLE_VALUE)
|
|
// {
|
|
// eprintf(" CreateFileMapping failed, error #%d!\n", GetLastError());
|
|
// goto MCFCloseFile;
|
|
// }
|
|
//
|
|
// //
|
|
// // Map view of file
|
|
// //
|
|
//
|
|
// pView = (PBYTE)MapViewOfFile(hMapFile, // hFileMappingObject
|
|
// FILE_MAP_READ, // dwDesiredAccess
|
|
// 0, // dwFileOffsetHigh
|
|
// 0, // dwFileOffsetLow
|
|
// 0 ); // dwNumberOfBytesToMap
|
|
//
|
|
// if (!pView)
|
|
// {
|
|
// eprintf(" MapViewOfFile failed, error #%d!\n", GetLastError());
|
|
// goto MCFCloseFile;
|
|
// }
|
|
//
|
|
// bResult = TRUE;
|
|
//
|
|
// MCFCloseFile:
|
|
// if (!bResult)
|
|
// {
|
|
// if (pView)
|
|
// {
|
|
// if (!UnmapViewOfFile(pView))
|
|
// {
|
|
// eprintf(" UnmapViewOfFile failed, error = #%d\n", GetLastError() );
|
|
// }
|
|
// }
|
|
//
|
|
// if (hMapFile != INVALID_HANDLE_VALUE)
|
|
// {
|
|
// if (!CloseHandle(hMapFile));
|
|
// {
|
|
// eprintf(" CloseHandle(hMapFile) failed, error = #%d\n", GetLastError() );
|
|
// }
|
|
// }
|
|
//
|
|
// if (hFile != INVALID_HANDLE_VALUE)
|
|
// {
|
|
// if (!CloseHandle(hFile))
|
|
// {
|
|
// eprintf(" CloseHandle(hFile) failed, error = #%d\n", GetLastError() );
|
|
// }
|
|
// }
|
|
// }
|
|
//
|
|
//MCFReturn:
|
|
//
|
|
// pfv->hFile = hFile;
|
|
// pfv->hMapFile = hMapFile;
|
|
// pfv->pView = pView;
|
|
//
|
|
// return bResult;
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* Routine Name
|
|
*
|
|
* UnmapICFile
|
|
*
|
|
* Routine Description:
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pfv -
|
|
*
|
|
* Return Value:
|
|
*
|
|
* None
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
UnmapICFile(
|
|
PFILEVIEW_ICM pfv
|
|
)
|
|
{
|
|
// BUGBUG
|
|
// UnmapViewOfFile(pfv->pView);
|
|
// CloseHandle(pfv->hMapFile);
|
|
// CloseHandle(pfv->hFile);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* Routine Name
|
|
*
|
|
* AddICToRegistry
|
|
*
|
|
* Routine Description:
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pfv -
|
|
* filename -
|
|
* fdefault -
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BOOL
|
|
AddICToRegistry(
|
|
PFILEVIEW_ICM pfv,
|
|
PWSTR filename,
|
|
BOOL fdefault
|
|
)
|
|
{
|
|
BOOL bResult = FALSE;
|
|
HKEY hkLocalMachine;
|
|
HKEY hkICM = 0;
|
|
HKEY hkptyp = 0;
|
|
CM_HEADER *pICProfile;
|
|
HKEY hkManu = 0;
|
|
HKEY hkModel = 0;
|
|
HKEY hkGamma = 0;
|
|
HKEY hkPhos = 0;
|
|
HKEY hkMedia = 0;
|
|
HKEY hkDither = 0;
|
|
HKEY hkLast = 0;
|
|
int i,j;
|
|
WCHAR NameOfManu[11];
|
|
DWORD ValueType;
|
|
WCHAR NameOfValue[16];
|
|
DWORD ValueSize;
|
|
WCHAR ValueOfValue[MAX_PATH];
|
|
|
|
//
|
|
// try to open registry base
|
|
//
|
|
|
|
if (IcmOpenKey(NULL,
|
|
L"Registry\\Machine",
|
|
&hkLocalMachine) == ERROR_SUCCESS)
|
|
{
|
|
|
|
IcmCreateKey(hkLocalMachine, szICMRegPath, &hkICM);
|
|
|
|
pICProfile = (CM_HEADER *)(pfv->pView);
|
|
|
|
NameOfManu[4] = 0;
|
|
*((DWORD *)NameOfManu) = (pICProfile->deviceManufacturer);
|
|
|
|
if (pICProfile->Class == 'rtnm')
|
|
{
|
|
IcmCreateKey(hkICM,L"mntr",&hkptyp);
|
|
IcmCreateKey(hkptyp, NameOfManu, &hkManu);
|
|
|
|
if (*((DWORD *)NameOfManu) != 'enon')
|
|
{
|
|
record_manufacturer(hkManu, pfv, ValueOfValue);
|
|
*((DWORD *)NameOfManu) = pICProfile->deviceModel;
|
|
IcmCreateKey(hkManu, NameOfManu, &hkLast);
|
|
record_model(hkLast, pfv, ValueOfValue);
|
|
}
|
|
else
|
|
{
|
|
hkLast = hkManu;
|
|
}
|
|
}
|
|
else if (pICProfile->Class == 'rncs')
|
|
{
|
|
IcmCreateKey(hkICM,L"scnr",&hkptyp);
|
|
IcmCreateKey(hkptyp, NameOfManu, &hkManu);
|
|
record_manufacturer(hkManu, pfv, ValueOfValue);
|
|
|
|
*((DWORD *)NameOfManu) = pICProfile->deviceModel;
|
|
|
|
IcmCreateKey(hkManu, NameOfManu, &hkLast);
|
|
record_model(hkLast, pfv, ValueOfValue);
|
|
}
|
|
else if (pICProfile->Class == 'rtrp')
|
|
{
|
|
|
|
IcmCreateKey(hkICM,L"prtr",&hkptyp);
|
|
IcmCreateKey(hkptyp, NameOfManu, &hkManu);
|
|
|
|
record_manufacturer(hkManu, pfv, ValueOfValue);
|
|
|
|
*((DWORD *)NameOfManu) = pICProfile->deviceModel;
|
|
|
|
IcmCreateKey(hkManu, NameOfManu, &hkModel);
|
|
record_model(hkModel, pfv, ValueOfValue);
|
|
|
|
if (pICProfile->deviceAttributes[0] >= DMMEDIA_USER)
|
|
{
|
|
word_to_ascii(pICProfile->deviceAttributes[0], (DWORD *)&NameOfManu);
|
|
}
|
|
else
|
|
{
|
|
if (pICProfile->deviceAttributes[0] > DMMEDIA_TRANSPARENCY)
|
|
{
|
|
pICProfile->deviceAttributes[0] = 0;
|
|
}
|
|
|
|
wcscpy(NameOfManu, MediaType[pICProfile->deviceAttributes[0]]);
|
|
}
|
|
|
|
IcmCreateKey(hkModel, NameOfManu, &hkMedia);
|
|
|
|
if (pICProfile->deviceAttributes[1] >= DMDITHER_USER)
|
|
{
|
|
word_to_ascii(pICProfile->deviceAttributes[1], (DWORD *)&NameOfManu);
|
|
}
|
|
else
|
|
{
|
|
if (pICProfile->deviceAttributes[1] > DMDITHER_GRAYSCALE)
|
|
{
|
|
pICProfile->deviceAttributes[1] = 0;
|
|
}
|
|
wcscpy(NameOfManu, DitherType[pICProfile->deviceAttributes[1]]);
|
|
}
|
|
|
|
IcmCreateKey(hkMedia, NameOfManu, &hkLast);
|
|
}
|
|
|
|
//
|
|
// !!! ICM wide character constants broken
|
|
//
|
|
//else if (pICProfile->Class == L'knil')
|
|
//{
|
|
// IcmCreateKey(hkICM,L"link",&hkLast);
|
|
//}
|
|
//else if (pICProfile->Class == L'caps')
|
|
//{
|
|
// IcmCreateKey(hkICM,L"spac",&hkLast);
|
|
//}
|
|
//else if (pICProfile->Class == L'tsba')
|
|
//{
|
|
// IcmCreateKey(hkICM,L"abst",&hkLast);
|
|
//}
|
|
//
|
|
|
|
else
|
|
{
|
|
goto GFFCloseKeys;
|
|
}
|
|
|
|
if (!hkLast)
|
|
{
|
|
goto GFFCloseKeys;
|
|
}
|
|
|
|
bResult = TRUE;
|
|
|
|
//
|
|
// is the profile already in the registry?
|
|
//
|
|
|
|
wcscpy(NameOfValue, szP);
|
|
|
|
NameOfValue[9] = 0;
|
|
|
|
|
|
for (i=0 ;i<10 ; i++)
|
|
{
|
|
NameOfValue[7] = num[i];
|
|
for (j=0 ;j<10 ; j++)
|
|
{
|
|
ValueSize = MAX_PATH;
|
|
NameOfValue[8] = num[j];
|
|
|
|
if (IcmQueryValueEx(hkLast,
|
|
NameOfValue,
|
|
0,
|
|
&ValueType,
|
|
(PBYTE)ValueOfValue,
|
|
&ValueSize) == ERROR_SUCCESS)
|
|
{
|
|
if (!_wcsicmp(ValueOfValue, filename)) //!!! what is this ???
|
|
{
|
|
goto GFFCloseKeys;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (IcmSetValueEx(hkLast,
|
|
NameOfValue,
|
|
0,
|
|
REG_SZ,
|
|
(PBYTE)filename,
|
|
wcslen(filename)+1) != ERROR_SUCCESS)
|
|
{
|
|
bResult = FALSE;
|
|
}
|
|
|
|
goto GFFCloseKeys;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
GFFCloseKeys:
|
|
if (hkLocalMachine) { IcmCloseKey(hkLocalMachine); }
|
|
if (hkLast) { IcmCloseKey(hkLast); }
|
|
if (hkDither) { IcmCloseKey(hkDither); }
|
|
if (hkMedia) { IcmCloseKey(hkMedia); }
|
|
if (hkPhos) { IcmCloseKey(hkPhos); }
|
|
if (hkGamma) { IcmCloseKey(hkGamma); }
|
|
if (hkManu) { IcmCloseKey(hkManu); }
|
|
if (hkptyp) { IcmCloseKey(hkptyp); }
|
|
if (hkICM) { IcmCloseKey(hkICM); }
|
|
|
|
return bResult;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* Routine Name
|
|
*
|
|
* RecurseReg
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* This routine recurses down the ICM branch to the terminal leafs looking
|
|
* for a given profile filename. When it finds it it either just returns
|
|
* that fact, or it nukes it unmercilessly. It also tidies as it goes,
|
|
* deleting branches below that have no profiles or subkeys in them. This
|
|
* way the set of branches that lead to profileless terminal branch will
|
|
* get removed when the last profile in that terminal branch is removed.
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
* hkRecurse - the node to check
|
|
* filename - profile we are looking for
|
|
* command - looking or deleting
|
|
* level - debugging info, recurse level
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BOOL
|
|
RecurseReg(
|
|
HKEY hkRecurse,
|
|
PWSTR filename,
|
|
int command,
|
|
int level
|
|
)
|
|
{
|
|
//
|
|
// BUGBUG Whole thing a mess!
|
|
// int i, j;
|
|
// HKEY hknext;
|
|
// WCHAR sznext[15];
|
|
// WCHAR szdummy[15];
|
|
// DWORD idummy = 0;
|
|
// DWORD idumb = 0;
|
|
// DWORD icSubKeys;
|
|
// DWORD icValues;
|
|
// FILETIME pft;
|
|
// WCHAR VProfile[MAX_PATH];
|
|
// WCHAR ProfileName[MAX_PATH];
|
|
// DWORD VType;
|
|
// DWORD VSize = MAX_PATH;
|
|
// DWORD PSize = MAX_PATH;
|
|
//
|
|
// //
|
|
// // assume file not in registry
|
|
// //
|
|
//
|
|
// BOOL bResult = FALSE;
|
|
// int bResult1 = FALSE;
|
|
//
|
|
//
|
|
//#ifdef myDEBUG
|
|
//
|
|
// int k;
|
|
//
|
|
//#endif
|
|
//
|
|
//
|
|
// //
|
|
// // Dive down the branches to the terminal leafs.
|
|
// // Go through all subkeys by enuming them, opening them, and recursing
|
|
// // down them.
|
|
// //
|
|
//
|
|
// for (i=0; !IcmEnumKey(hkRecurse, i, sznext, 16); i++)
|
|
// {
|
|
//
|
|
//
|
|
//#ifdef myDEBUG
|
|
//
|
|
// for (k=0; k <= level; k++)
|
|
// {
|
|
// eprintf(" ", 0);
|
|
// }
|
|
//
|
|
// eprintf(sznext, 0);
|
|
// eprintf("\n", 0);
|
|
//
|
|
//#endif
|
|
//
|
|
//
|
|
// if (IcmOpenKey(hkRecurse, sznext, &hknext) == ERROR_SUCCESS)
|
|
// {
|
|
//
|
|
// //
|
|
// // The finding of a profile needs to be percolated back up
|
|
// // the calls, so the result needs to be OR'ed in.
|
|
// //
|
|
//
|
|
// bResult |= RecurseReg(hknext, filename, command, level+1);
|
|
//
|
|
// //
|
|
// // Recursion may have deleted the profile in hknext. Do housecleaning.
|
|
// // Check to see if this key has any subkeys or profiles.
|
|
// //
|
|
//
|
|
// IcmQueryInfoKey(hknext,
|
|
// szdummy,
|
|
// &idummy,
|
|
// 0,
|
|
// &icSubKeys,
|
|
// &idumb,
|
|
// &idumb,
|
|
// &icValues,
|
|
// &idumb,
|
|
// &idumb,
|
|
// &idumb,
|
|
// &pft);
|
|
//
|
|
//
|
|
// //
|
|
// // No subkeys make it a candidate for deleting.
|
|
// //
|
|
//
|
|
// if (!icSubKeys)
|
|
// {
|
|
// //
|
|
// // No values elects the candidate for deleting.
|
|
// //
|
|
//
|
|
// if (!icValues)
|
|
// {
|
|
//
|
|
//
|
|
// #ifdef myDEBUG
|
|
// for (k=0; k <= level; k++) eprintf(" ", 0);
|
|
// {
|
|
// eprintf("DELETED", 1);
|
|
// }
|
|
//
|
|
// eprintf("\n", 0);
|
|
// #endif
|
|
//
|
|
//
|
|
// IcmCloseKey(hknext);
|
|
// IcmDeleteKey(hkRecurse, sznext);
|
|
//
|
|
// //
|
|
// // Restart loop, list is out of whack.
|
|
// //
|
|
//
|
|
// i = -1;
|
|
// }
|
|
//
|
|
// //
|
|
// // Is the one value a profile or desc?
|
|
// //
|
|
//
|
|
// else if (icValues == 1)
|
|
// {
|
|
// IcmEnumValue(hknext,
|
|
// 0,
|
|
// VProfile,
|
|
// &VSize,
|
|
// 0,
|
|
// &VType,
|
|
// (PBYTE)ProfileName,
|
|
// &PSize);
|
|
//
|
|
// if (
|
|
// !wcscmp(VProfile, szManuTag) || // !!! what is this
|
|
// !wcscmp(VProfile, szModelTag)
|
|
// )
|
|
// {
|
|
//
|
|
// IcmCloseKey(hknext);
|
|
//
|
|
//
|
|
// #ifdef myDEBUG
|
|
// for (k=0; k <= level; k++)
|
|
// {
|
|
// eprintf(" ", 0);
|
|
// }
|
|
//
|
|
// eprintf("DELETED", 1);
|
|
// eprintf("\n", 0);
|
|
// #endif
|
|
//
|
|
//
|
|
// IcmDeleteKey(hkRecurse, sznext);
|
|
//
|
|
// //
|
|
// // restart loop, list is out of whack
|
|
// //
|
|
//
|
|
// i = -1;
|
|
// }
|
|
//
|
|
// }
|
|
// else
|
|
// {
|
|
// IcmCloseKey(hknext);
|
|
// }
|
|
// }
|
|
// else
|
|
// {
|
|
// IcmCloseKey(hknext);
|
|
// }
|
|
// }
|
|
// }
|
|
//
|
|
// //
|
|
// // We've looked below. We now have to look at the current level.
|
|
// //
|
|
// // use as a count of neighbors
|
|
// //
|
|
//
|
|
// idummy = 0;
|
|
//
|
|
// for (i = 0;
|
|
// !IcmEnumValue(hkRecurse,
|
|
// i,
|
|
// VProfile,
|
|
// &VSize,
|
|
// 0,
|
|
// &VType,
|
|
// (PBYTE)ProfileName,
|
|
// &PSize);
|
|
// VSize = MAX_PATH, PSize = MAX_PATH, i++)
|
|
// {
|
|
// for (j = 0; j < 8 ; j++) // count the number of neighbors
|
|
// {
|
|
// if (VProfile[j] != szP[j])
|
|
// {
|
|
// break;
|
|
// }
|
|
// }
|
|
//
|
|
// if (j == 7)
|
|
// {
|
|
// idummy++;
|
|
// }
|
|
//
|
|
//
|
|
//#ifdef myDEBUG
|
|
//
|
|
// for (k=0; k <= level; k++) eprintf(" ", 0);
|
|
// {
|
|
// eprintf(VProfile, 1);
|
|
// }
|
|
//
|
|
// eprintf("\n", 0);
|
|
//#endif
|
|
//
|
|
// //
|
|
// // did we find it?
|
|
// //
|
|
//
|
|
// if (!wcsicmp(filename, ProfileName))
|
|
// {
|
|
//
|
|
//
|
|
//#ifdef myDEBUG
|
|
//
|
|
// for (k=0; k <= level; k++)
|
|
// {
|
|
// eprintf(" ", 0);
|
|
// }
|
|
//
|
|
// if (command == ICM_DELETEPROFILE)
|
|
// {
|
|
// eprintf("DELETED", 1);
|
|
// }
|
|
// else if (command == ICM_QUERYPROFILE)
|
|
// {
|
|
// eprintf("FOUND", 1);
|
|
// }
|
|
// else
|
|
// {
|
|
// eprintf("SETDEFAULT", 1);
|
|
// eprintf("\n", 0);
|
|
// }
|
|
//
|
|
//#endif
|
|
//
|
|
//
|
|
// if (command == ICM_QUERYPROFILE)
|
|
// {
|
|
// bResult1 = 1;
|
|
//
|
|
// //
|
|
// // If this is already the default profile we need to know
|
|
// // to let the user know.
|
|
// //
|
|
//
|
|
// PSize = MAX_PATH;
|
|
//
|
|
// if (IcmQueryValueEx(hkRecurse,
|
|
// szDefault,
|
|
// 0,
|
|
// &VType,
|
|
// (PBYTE)ProfileName,
|
|
// &PSize) == ERROR_SUCCESS)
|
|
// {
|
|
// if (!wcsicmp(VProfile, ProfileName)) //!!!
|
|
// {
|
|
// bResult1 |= 0x80000000;
|
|
// }
|
|
// }
|
|
// }
|
|
// else if (command == ICM_SETDEFAULTPROFILE)
|
|
// {
|
|
// bResult = !IcmSetValueEx(hkRecurse,
|
|
// szDefault,
|
|
// 0,
|
|
// REG_SZ,
|
|
// (PBYTE)VProfile,
|
|
// wcslen(VProfile));
|
|
// }
|
|
// else if (command == ICM_DELETEPROFILE)
|
|
// {
|
|
// bResult = !IcmDeleteValue(hkRecurse, VProfile);
|
|
//
|
|
// //
|
|
// // If this was the default profile we need to delete that as well.
|
|
// // Default string structure is: default = "profileXX".
|
|
// //
|
|
//
|
|
// PSize = MAX_PATH;
|
|
//
|
|
// if (IcmQueryValueEx(hkRecurse,
|
|
// szDefault,
|
|
// 0,
|
|
// &VType,
|
|
// (PBYTE)ProfileName,
|
|
// &PSize) == ERROR_SUCCESS)
|
|
// {
|
|
// if (!wcsicmp(VProfile, ProfileName))
|
|
// {
|
|
// IcmDeleteValue(hkRecurse, szDefault);
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
//
|
|
// //
|
|
// // probably a better way of doing this, but the
|
|
// // problem this solves should be obvious
|
|
// //
|
|
//
|
|
// if (command == ICM_QUERYPROFILE)
|
|
// {
|
|
// if (bResult1 != FALSE)
|
|
// {
|
|
// bResult = bResult1 | idummy;
|
|
// }
|
|
// }
|
|
//
|
|
// return (bResult);
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* Routine Name
|
|
*
|
|
* record_manufacturer
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* This gets the manufacturer string out of the icc profile and stores it in
|
|
* as a value under the given key, which should be the manufacturer key.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* hkKey -
|
|
* pfv -
|
|
* pBuffer -
|
|
*
|
|
* Return Value:
|
|
*
|
|
* None
|
|
*
|
|
\**************************************************************************/
|
|
|
|
//
|
|
// !!! This whole routine is messed up
|
|
//
|
|
|
|
VOID
|
|
record_manufacturer(
|
|
HKEY hkKey,
|
|
PFILEVIEW_ICM pfv,
|
|
PWSTR pBuffer
|
|
)
|
|
{
|
|
DWORD *pTag;
|
|
int ValueSize;
|
|
int i;
|
|
|
|
//
|
|
// get the manufacturer description
|
|
//
|
|
|
|
if (pTag = GetTagPtr(pfv->pView, 'dnmd'))
|
|
{
|
|
i = ValueSize = SwapBytes(pTag[2]);
|
|
pTag = (DWORD *)((PBYTE)pTag + 12);
|
|
|
|
for (i = 0; i < ValueSize; i++)
|
|
{
|
|
pBuffer[i] = (WCHAR)((PBYTE)pTag)[i];
|
|
}
|
|
|
|
pBuffer[i] = 0;
|
|
IcmSetValueEx(hkKey, szManuTag, 0, REG_SZ, (PBYTE)pBuffer, ValueSize+1);
|
|
}
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* Routine Name
|
|
*
|
|
* record_model
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* This gets the model string out of the icc profile and stores it in as a
|
|
* value under the given key, which should be the model key.
|
|
*
|
|
* Arguments:
|
|
*
|
|
*
|
|
* Return Value:
|
|
*
|
|
* None
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
record_model(
|
|
HKEY hkKey,
|
|
PFILEVIEW_ICM pfv,
|
|
PWSTR pBuffer
|
|
)
|
|
{
|
|
DWORD *pTag;
|
|
DWORD ValueSize;
|
|
int i;
|
|
|
|
//
|
|
// get the model description
|
|
//
|
|
|
|
if (pTag = GetTagPtr(pfv->pView, 'ddmd'))
|
|
{
|
|
i = ValueSize = SwapBytes(pTag[2]);
|
|
|
|
pTag = (DWORD *)((PBYTE)pTag + 12);
|
|
|
|
for (i = 0; i < (int)ValueSize; i++)
|
|
{
|
|
pBuffer[i] = (WCHAR)((PBYTE)pTag)[i];
|
|
}
|
|
|
|
pBuffer[i] = 0;
|
|
|
|
IcmSetValueEx(hkKey, szModelTag, 0, REG_SZ, (PBYTE)pBuffer, ValueSize+1);
|
|
}
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* Routine Name
|
|
*
|
|
* CEnumICMProfiles
|
|
*
|
|
* Routine Description:
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
*
|
|
* Return Value:
|
|
*
|
|
* None
|
|
*
|
|
\**************************************************************************/
|
|
|
|
int
|
|
CEnumICMProfiles(
|
|
DWORD pdc,
|
|
ICMENUMPROC lpfnCallBack,
|
|
LPARAM lpClientData,
|
|
PDEVMODEW devmode
|
|
)
|
|
{
|
|
HKEY hkStart;
|
|
WCHAR non_friendly[32];
|
|
WCHAR szBuffer[MAX_PATH];
|
|
int retval = 0;
|
|
|
|
if (!devmode)
|
|
{
|
|
if (hkStart = (HKEY)icm_FindMonitorProfile((PWSTR)NULL,0))
|
|
{
|
|
if (((int)hkStart >= 1) && ((int)hkStart <= 9))
|
|
{
|
|
wcscpy(szBuffer, szColorDir);
|
|
wcscat(szBuffer, L"\\");
|
|
wcscat(szBuffer, DispProfs[(int)hkStart]);
|
|
|
|
if (check_file_existence(szBuffer))
|
|
{
|
|
// return ((*lpfnCallBack)(szBuffer, lpClientData)); !!! call back to user !!!
|
|
}
|
|
else
|
|
{
|
|
return (FALSE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
retval = EnumProfileNames(hkStart, lpfnCallBack, lpClientData);
|
|
IcmCloseKey(hkStart);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
GetRealDriverInfo((PWSTR)devmode, (PWSTR)&non_friendly);
|
|
|
|
if (hkStart = (HKEY)icm_FindPrinterProfile(0, devmode, (PWSTR)&non_friendly))
|
|
{
|
|
retval = EnumProfileNames(hkStart, lpfnCallBack, lpClientData);
|
|
IcmCloseKey(hkStart);
|
|
}
|
|
}
|
|
return(retval);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* Routine Name
|
|
*
|
|
* EnumProfileNames
|
|
*
|
|
* Routine Description:
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
*
|
|
* Return Value:
|
|
*
|
|
* None
|
|
*
|
|
\**************************************************************************/
|
|
|
|
int
|
|
EnumProfileNames(
|
|
HKEY hkStart,
|
|
ICMENUMPROC lpfnCallBack,
|
|
LPARAM lpClientData
|
|
)
|
|
{
|
|
int i, j;
|
|
WCHAR VProfile[MAX_PATH];
|
|
WCHAR ProfileName[MAX_PATH];
|
|
DWORD VType;
|
|
DWORD VSize = MAX_PATH;
|
|
DWORD PSize = MAX_PATH;
|
|
int retval = 0;
|
|
|
|
for (i = 0;
|
|
!IcmEnumValue(hkStart,
|
|
i,
|
|
VProfile,
|
|
&VSize,
|
|
0,
|
|
&VType,
|
|
(PBYTE)ProfileName,
|
|
&PSize);
|
|
VSize = MAX_PATH, PSize = MAX_PATH, i++)
|
|
{
|
|
|
|
//
|
|
// Make sure to report back only "profileXX = ..." strings!
|
|
//
|
|
|
|
for (j = 0; j < 8 ; j++)
|
|
{
|
|
if (VProfile[j] != szP[j])
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (j == 7)
|
|
{
|
|
// !!! call back !!! if (!(retval = (*lpfnCallBack)(ProfileName, lpClientData)))
|
|
// {
|
|
// break;
|
|
// }
|
|
}
|
|
}
|
|
|
|
return (retval);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* Routine Name
|
|
*
|
|
* GetRealDriverInfo
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* This was stolen from 16 bit GDI and then stripped down, since there's
|
|
* not a thunk for it.
|
|
*
|
|
* Arguments:
|
|
*
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
\**************************************************************************/
|
|
|
|
WCHAR szRegPrinter[]=L"System\\CurrentControlSet\\Control\\Print\\Printers\\";
|
|
WCHAR szPrinterDriver[]=L"Printer Driver";
|
|
|
|
BOOL GetRealDriverInfo(PWSTR pPrinterName, PWSTR pDeviceName)
|
|
{
|
|
WCHAR szBuf[MAX_PATH];
|
|
HKEY hKey;
|
|
HKEY hkLocalMachine;
|
|
DWORD dwNeeded, dwType;
|
|
BOOL bRet = FALSE;
|
|
|
|
//
|
|
// open registry base
|
|
//
|
|
|
|
if (IcmOpenKey(NULL,
|
|
L"\\Registry\\Machine",
|
|
&hkLocalMachine) == ERROR_SUCCESS)
|
|
{
|
|
|
|
|
|
wcscpy(szBuf, szRegPrinter);
|
|
wcscat(szBuf, pPrinterName);
|
|
|
|
if (IcmOpenKey(hkLocalMachine, szBuf, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
dwNeeded = CCHDEVICENAME;
|
|
|
|
IcmQueryValueEx(hKey,
|
|
szPrinterDriver,
|
|
NULL,
|
|
&dwType,
|
|
(PBYTE)pDeviceName,
|
|
&dwNeeded);
|
|
|
|
IcmCloseKey(hKey);
|
|
|
|
bRet = TRUE;
|
|
}
|
|
|
|
IcmCloseKey(hkLocalMachine);
|
|
|
|
}
|
|
|
|
return(bRet);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* Routine Name
|
|
*
|
|
* check_file_existence
|
|
*
|
|
* Routine Description:
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pBuffer -
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BOOL
|
|
check_file_existence(
|
|
PWSTR pBuffer
|
|
)
|
|
{
|
|
//
|
|
// BUGBUG Whole thing a mess
|
|
//
|
|
// HANDLE hFile;
|
|
//
|
|
// hFile = CreateFileW(pBuffer, // lpFileName
|
|
// GENERIC_READ, // dwDesiredAccess
|
|
// FILE_SHARE_READ, // dwShareMode
|
|
// NULL, // lpSecurityAttributes
|
|
// OPEN_EXISTING, // dwCreationDisposition
|
|
// FILE_ATTRIBUTE_NORMAL, // dwFlagsAndAttributes
|
|
// NULL ); // hTemplate
|
|
//
|
|
// if (hFile != INVALID_HANDLE_VALUE)
|
|
// {
|
|
// CloseHandle(hFile);
|
|
// return (TRUE);
|
|
// }
|
|
// else
|
|
// {
|
|
// return (FALSE);
|
|
// }
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* Routine Name
|
|
*
|
|
* GetTagPtr
|
|
*
|
|
* Routine Description:
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pBuffer -
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
\**************************************************************************/
|
|
|
|
DWORD *
|
|
GetTagPtr(
|
|
PBYTE pView,
|
|
DWORD sig
|
|
)
|
|
{
|
|
int i;
|
|
CM_TAG_HEADER *pTagHeader;
|
|
CM_TAG_RECORD *pTagRecord;
|
|
DWORD *ptag = 0;
|
|
|
|
pTagHeader = (CM_TAG_HEADER *)pView;
|
|
pTagHeader = (CM_TAG_HEADER *)((DWORD)pTagHeader + sizeof(CM_HEADER));
|
|
i = SwapBytes(pTagHeader->count);
|
|
pTagRecord = (CM_TAG_RECORD *)&(pTagHeader->taglist);
|
|
|
|
|
|
for (; i != 0 ; i--)
|
|
{
|
|
if (pTagRecord->tag == sig)
|
|
{
|
|
ptag = (DWORD *)((DWORD)pView + SwapBytes(pTagRecord->begin));
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
pTagRecord++;
|
|
}
|
|
}
|
|
|
|
if (!i)
|
|
{
|
|
ptag = 0;
|
|
}
|
|
|
|
return(ptag);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* Routine Name
|
|
*
|
|
* SwapBytes
|
|
* Swap2Bytes
|
|
* word_to_ascii
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* Byte swap and wide character conversions
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pBuffer -
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
\**************************************************************************/
|
|
|
|
DWORD
|
|
SwapBytes (
|
|
DWORD input
|
|
)
|
|
{
|
|
|
|
//
|
|
// DWORD BSWAP
|
|
//
|
|
// input = |3|2|1|0
|
|
//
|
|
|
|
DWORD t1 = input >> 24; // | | | |3
|
|
DWORD t2 = (input >> 8) & 0xFF00; // | | |2|
|
|
DWORD t3 = input << 24; // |0| | |
|
|
DWORD t4 = (input & 0xff00) << 8; // | |1| |
|
|
|
|
return(t1 | t2 | t3 | t4);
|
|
|
|
}
|
|
|
|
WORD
|
|
Swap2Bytes(
|
|
WORD input
|
|
)
|
|
{
|
|
return((input << 16) | (input >> 16));
|
|
}
|
|
|
|
VOID
|
|
word_to_ascii(
|
|
DWORD input,
|
|
PDWORD output
|
|
)
|
|
{
|
|
|
|
//
|
|
// bazzare 4 bit to char expansion
|
|
//
|
|
|
|
UCHAR ch;
|
|
DWORD tmp = 0;
|
|
ULONG Index;
|
|
|
|
for (Index=0;Index<4;Index++)
|
|
{
|
|
tmp <<= 8;
|
|
ch = (UCHAR)(input & 0x0f);
|
|
ch += '0';
|
|
if (ch > '9')
|
|
{
|
|
ch += ('A' - '9' - 1);
|
|
}
|
|
tmp |= ch;
|
|
input >>= 4;
|
|
}
|
|
|
|
*output = tmp;
|
|
|
|
//
|
|
// _asm
|
|
// {
|
|
// mov ecx,4
|
|
// mov eax,input
|
|
// wta_loop:
|
|
// shl edx,8
|
|
// mov dl,al
|
|
// and dl,0Fh
|
|
// add dl,'0'
|
|
// cmp dl,'9'
|
|
// jbe wta_ehh
|
|
// add dl,'A' - '9' - 1
|
|
// wta_ehh:
|
|
// shr eax,4
|
|
// loop wta_loop
|
|
// mov eax,output
|
|
// mov [eax],edx
|
|
// }
|
|
//
|
|
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* Routine Name
|
|
*
|
|
* IcmOpenKey
|
|
* IcmQueryValueEx
|
|
* IcmSetValueEx
|
|
* IcmCreateKey
|
|
* IcmDeleteKey
|
|
* IcmEnumKey
|
|
* IcmCloseKey
|
|
* IcmDeleteValue
|
|
* IcmQueryInfoKey
|
|
* IcmEnumValue
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* Nt thunks for win32 reg calls
|
|
*
|
|
* Arguments:
|
|
*
|
|
*
|
|
*
|
|
* Return Value:
|
|
*
|
|
*
|
|
*
|
|
\**************************************************************************/
|
|
|
|
|
|
LONG
|
|
IcmOpenKey(
|
|
HANDLE hKeyIn,
|
|
PWSTR pwStr,
|
|
HANDLE *hKey
|
|
)
|
|
{
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
UNICODE_STRING UnicodeString;
|
|
NTSTATUS NtStatus;
|
|
LONG lStatus = ERROR_BADKEY;
|
|
|
|
|
|
RtlInitUnicodeString(&UnicodeString,pwStr);
|
|
|
|
//
|
|
// Open a registry key relative to hKeyIn
|
|
//
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&UnicodeString,
|
|
OBJ_CASE_INSENSITIVE,
|
|
hKeyIn,
|
|
NULL);
|
|
|
|
NtStatus = ZwOpenKey(hKey,
|
|
KEY_ALL_ACCESS,
|
|
&ObjectAttributes);
|
|
|
|
if (NT_SUCCESS(NtStatus))
|
|
{
|
|
lStatus = ERROR_SUCCESS;
|
|
}
|
|
|
|
return(lStatus);
|
|
}
|
|
|
|
|
|
LONG
|
|
IcmCreateKey(
|
|
HANDLE hKeyIn,
|
|
PWSTR pwStr,
|
|
HANDLE *hKey
|
|
)
|
|
{
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
UNICODE_STRING UnicodeString;
|
|
NTSTATUS NtStatus;
|
|
LONG lStatus = ERROR_BADKEY;
|
|
|
|
|
|
RtlInitUnicodeString(&UnicodeString,pwStr);
|
|
|
|
//
|
|
// Open a registry key relative to hKeyIn
|
|
//
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&UnicodeString,
|
|
OBJ_CASE_INSENSITIVE,
|
|
hKeyIn,
|
|
NULL);
|
|
|
|
NtStatus = ZwCreateKey(hKey,
|
|
KEY_ALL_ACCESS,
|
|
&ObjectAttributes,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
|
|
if (NT_SUCCESS(NtStatus))
|
|
{
|
|
lStatus = ERROR_SUCCESS;
|
|
}
|
|
|
|
return(lStatus);
|
|
}
|
|
|
|
LONG
|
|
IcmDeleteKey(
|
|
HANDLE hKeyIn,
|
|
PWSTR pwStr
|
|
)
|
|
{
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
UNICODE_STRING UnicodeString;
|
|
NTSTATUS NtStatus;
|
|
LONG lStatus = ERROR_BADKEY;
|
|
HKEY hkDel;
|
|
|
|
|
|
RtlInitUnicodeString(&UnicodeString,pwStr);
|
|
|
|
//
|
|
// Open a registry key relative to hKeyIn
|
|
//
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&UnicodeString,
|
|
OBJ_CASE_INSENSITIVE,
|
|
hKeyIn,
|
|
NULL);
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
NtStatus = ZwOpenKey(&hkDel,
|
|
KEY_ALL_ACCESS,
|
|
&ObjectAttributes);
|
|
|
|
if (NT_SUCCESS(NtStatus))
|
|
{
|
|
|
|
|
|
NtStatus = ZwDeleteKey(hkDel);
|
|
|
|
if (NT_SUCCESS(NtStatus))
|
|
{
|
|
lStatus = ERROR_SUCCESS;
|
|
ZwClose(hkDel);
|
|
}
|
|
}
|
|
return(lStatus);
|
|
}
|
|
|
|
|
|
LONG
|
|
IcmQueryValueEx(
|
|
HKEY hKey,
|
|
LPWSTR lpwValueName,
|
|
LPDWORD res,
|
|
LPDWORD lpdwType,
|
|
LPBYTE lpbData,
|
|
LPDWORD lpcbData
|
|
)
|
|
{
|
|
UNICODE_STRING UnicodeString;
|
|
NTSTATUS NtStatus;
|
|
LONG lStatus = ERROR_CANTOPEN;
|
|
ULONG DataSize = sizeof(KEY_VALUE_FULL_INFORMATION) + *lpcbData;
|
|
ULONG DataReturnSize;
|
|
|
|
PKEY_VALUE_FULL_INFORMATION pKeyFullInfo;
|
|
|
|
pKeyFullInfo = (PKEY_VALUE_FULL_INFORMATION)PALLOCNOZ(DataSize, 'mciG');
|
|
|
|
if (pKeyFullInfo != (PKEY_VALUE_FULL_INFORMATION)NULL)
|
|
{
|
|
|
|
//
|
|
// make NT call
|
|
//
|
|
|
|
RtlInitUnicodeString(&UnicodeString,lpwValueName);
|
|
|
|
NtStatus = ZwQueryValueKey(hKey,
|
|
&UnicodeString,
|
|
KeyValueFullInformation,
|
|
pKeyFullInfo,
|
|
DataSize,
|
|
&DataReturnSize);
|
|
|
|
if (NT_SUCCESS(NtStatus))
|
|
{
|
|
|
|
ULONG DataCopySize;
|
|
|
|
lStatus = ERROR_SUCCESS;
|
|
|
|
//
|
|
// copy data to users buffer
|
|
//
|
|
|
|
DataCopySize = min(pKeyFullInfo->DataLength,*lpcbData);
|
|
|
|
memcpy((VOID *)lpbData,(VOID *)((BYTE *)pKeyFullInfo + pKeyFullInfo->DataOffset),DataCopySize);
|
|
|
|
}
|
|
|
|
VFREEMEM(pKeyFullInfo);
|
|
}
|
|
|
|
return(lStatus);
|
|
}
|
|
|
|
LONG
|
|
IcmSetValueEx(
|
|
HKEY hKey,
|
|
LPWSTR lpwValueName,
|
|
DWORD dwReserved,
|
|
DWORD fdwType,
|
|
CONST BYTE * lpbData,
|
|
DWORD cbData
|
|
)
|
|
{
|
|
|
|
UNICODE_STRING UnicodeString;
|
|
NTSTATUS NtStatus;
|
|
LONG lStatus = ERROR_CANTOPEN;
|
|
|
|
//
|
|
// make NT call
|
|
//
|
|
|
|
RtlInitUnicodeString(&UnicodeString,lpwValueName);
|
|
|
|
NtStatus = ZwSetValueKey(hKey,
|
|
&UnicodeString,
|
|
0,
|
|
fdwType,
|
|
(PVOID)lpbData,
|
|
cbData
|
|
);
|
|
|
|
if (NT_SUCCESS(NtStatus))
|
|
{
|
|
lStatus = ERROR_SUCCESS;
|
|
}
|
|
|
|
return(lStatus);
|
|
}
|
|
|
|
LONG
|
|
IcmEnumKey(
|
|
HANDLE hKeyIn,
|
|
DWORD iSubKey,
|
|
PWSTR pwName,
|
|
DWORD NameLength
|
|
)
|
|
{
|
|
NTSTATUS NtStatus;
|
|
LONG lStatus = ERROR_BADKEY;
|
|
PKEY_BASIC_INFORMATION pKeyBasicInfo;
|
|
UCHAR TmpData[MAX_PATH];
|
|
ULONG DataSize;
|
|
ULONG RetDataSize;
|
|
|
|
pKeyBasicInfo = (PKEY_BASIC_INFORMATION)TmpData;
|
|
|
|
NtStatus = ZwEnumerateKey(hKeyIn,
|
|
iSubKey,
|
|
KeyBasicInformation,
|
|
pKeyBasicInfo,
|
|
MAX_PATH,
|
|
&RetDataSize);
|
|
|
|
if (NT_SUCCESS(NtStatus))
|
|
{
|
|
lStatus = ERROR_SUCCESS;
|
|
|
|
//
|
|
// copy to user buffer
|
|
//
|
|
|
|
memcpy(pwName,
|
|
pKeyBasicInfo->Name,
|
|
min(pKeyBasicInfo->NameLength,NameLength));
|
|
|
|
}
|
|
|
|
return(lStatus);
|
|
|
|
}
|
|
|
|
LONG
|
|
IcmCloseKey(
|
|
HKEY hKey
|
|
)
|
|
{
|
|
LONG lStatus = ERROR_BADKEY;
|
|
NTSTATUS NtStatus;
|
|
|
|
NtStatus = ZwClose(hKey);
|
|
|
|
if (NT_SUCCESS(NtStatus))
|
|
{
|
|
lStatus = ERROR_SUCCESS;
|
|
}
|
|
|
|
return(lStatus);
|
|
}
|
|
|
|
LONG
|
|
IcmDeleteValue(
|
|
HKEY hKey,
|
|
PWSTR lpwValueName
|
|
)
|
|
{
|
|
UNICODE_STRING UnicodeString;
|
|
NTSTATUS NtStatus;
|
|
LONG lStatus = ERROR_CANTOPEN;
|
|
|
|
//
|
|
// make NT call
|
|
//
|
|
|
|
RtlInitUnicodeString(&UnicodeString,lpwValueName);
|
|
|
|
NtStatus = ZwDeleteValueKey(hKey,
|
|
&UnicodeString
|
|
);
|
|
|
|
if (NT_SUCCESS(NtStatus))
|
|
{
|
|
lStatus = ERROR_SUCCESS;
|
|
}
|
|
|
|
return(lStatus);
|
|
|
|
}
|
|
|
|
//
|
|
// BUGBUG no FILETIME
|
|
//
|
|
//LONG
|
|
//IcmQueryInfoKey(
|
|
// HKEY hKey,
|
|
// LPWSTR lpszClass,
|
|
// LPDWORD lpcchClass,
|
|
// LPDWORD lpdwReserved,
|
|
// LPDWORD lpcSubKeys,
|
|
// LPDWORD lpcchMaxSubkey,
|
|
// LPDWORD lpcchMaxClass,
|
|
// LPDWORD lpcValues,
|
|
// LPDWORD lpcchMaxValueName,
|
|
// LPDWORD lpcbMaxValueData,
|
|
// LPDWORD lpcbSecurityDescriptor,
|
|
// PFILETIME lpftLastWriteTime
|
|
// )
|
|
//{
|
|
// NTSTATUS NtStatus;
|
|
// LONG lStatus = ERROR_BADKEY;
|
|
// PKEY_FULL_INFORMATION pKeyFullInfo;
|
|
// UCHAR TmpData[MAX_PATH];
|
|
// ULONG DataSize;
|
|
// ULONG RetDataSize;
|
|
//
|
|
// pKeyFullInfo = (PKEY_FULL_INFORMATION)TmpData;
|
|
//
|
|
// NtStatus = ZwQueryKey(
|
|
// hKey,
|
|
// KeyFullInformation,
|
|
// pKeyFullInfo,
|
|
// MAX_PATH,
|
|
// &RetDataSize
|
|
// );
|
|
//
|
|
//
|
|
// if (NT_SUCCESS(NtStatus))
|
|
// {
|
|
// lStatus = ERROR_SUCCESS;
|
|
//
|
|
// //
|
|
// // copy class string to caller buffer
|
|
// //
|
|
//
|
|
// wcsncpy(lpszClass,pKeyFullInfo->Class,min(*lpcchClass,pKeyFullInfo->ClassLength));
|
|
//
|
|
// //
|
|
// // copy other buffer entries
|
|
// //
|
|
//
|
|
// *lpcSubKeys = pKeyFullInfo->SubKeys;
|
|
// *lpcchMaxSubkey = pKeyFullInfo->MaxNameLen;
|
|
// *lpcchMaxClass = pKeyFullInfo->MaxClassLen;
|
|
// *lpcValues = pKeyFullInfo->Values;
|
|
// *lpcchMaxValueName = pKeyFullInfo->MaxValueNameLen;
|
|
// *lpcbMaxValueData = pKeyFullInfo->MaxValueDataLen;
|
|
// *lpcbSecurityDescriptor = 0;
|
|
//
|
|
// lpftLastWriteTime->dwLowDateTime = pKeyFullInfo->LastWriteTime.LowPart;
|
|
// lpftLastWriteTime->dwHighDateTime = pKeyFullInfo->LastWriteTime.HighPart;
|
|
// }
|
|
//
|
|
// return(lStatus);
|
|
//
|
|
//}
|
|
//
|
|
|
|
LONG
|
|
IcmEnumValue(
|
|
HKEY hKey,
|
|
DWORD iValue,
|
|
LPTSTR lpszValue,
|
|
LPDWORD lpcchValue,
|
|
LPDWORD lpdwReserved,
|
|
LPDWORD lpdwType,
|
|
LPBYTE lpbData,
|
|
LPDWORD lpcbData
|
|
)
|
|
{
|
|
NTSTATUS NtStatus;
|
|
LONG lStatus = ERROR_BADKEY;
|
|
PKEY_VALUE_FULL_INFORMATION pKeyInfo;
|
|
UCHAR Buffer[2 * MAX_PATH];
|
|
ULONG Length = 2 * MAX_PATH;
|
|
ULONG RetLength;
|
|
|
|
pKeyInfo = (PKEY_VALUE_FULL_INFORMATION)&Buffer[0];
|
|
|
|
NtStatus = ZwEnumerateValueKey(
|
|
hKey,
|
|
iValue,
|
|
KeyValueFullInformation,
|
|
pKeyInfo,
|
|
Length,
|
|
&RetLength
|
|
);
|
|
|
|
if (NT_SUCCESS(NtStatus))
|
|
{
|
|
lStatus = ERROR_SUCCESS;
|
|
|
|
//
|
|
// copy to callers parameters
|
|
//
|
|
|
|
*lpdwType = pKeyInfo->Type;
|
|
|
|
memcpy(lpszValue,pKeyInfo->Name,min(*lpcchValue,pKeyInfo->NameLength));
|
|
|
|
memcpy(
|
|
lpbData,
|
|
(WCHAR *)((PBYTE)pKeyInfo + pKeyInfo->DataOffset),
|
|
min(*lpcbData,pKeyInfo->DataLength)
|
|
);
|
|
}
|
|
|
|
return(lStatus);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
|
|
int
|
|
icm_FindMonitorProfile(
|
|
PWSTR pBuffer,
|
|
DWORD hack
|
|
)
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
int
|
|
icm_FindPrinterProfile(
|
|
PWSTR pBuffer,
|
|
PDEVMODEW devmode,
|
|
PWSTR unfriendly_name
|
|
)
|
|
{
|
|
return(0);
|
|
}
|
|
|
|
#endif
|