Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

profman.c

Go to the documentation of this file.
00001 /****************************Module*Header******************************\ 00002 * Module Name: PROFMAN.C 00003 * 00004 * Module Descripton: Profile management functions. 00005 * 00006 * Warnings: 00007 * 00008 * Issues: 00009 * 00010 * Public Routines: 00011 * 00012 * Created: 5 Nov 1996 00013 * 00014 * Author: Srinivasan Chandrasekar [srinivac] 00015 * 00016 * Copyright (c) 1996, 1997 Microsoft Corporation 00017 \***********************************************************************/ 00018 00019 #include "mscms.h" 00020 #include "objbase.h" 00021 #include "initguid.h" 00022 #include "devguid.h" 00023 #include "sti.h" 00024 00025 #define TAG_DEVICESETTINGS 'devs' 00026 #define TAG_MS01 'MS01' 00027 #define TAG_MS02 'MS02' 00028 #define TAG_MS03 'MS03' 00029 00030 #define ID_MSFT_REVERSED 'tfsm' 00031 #define ID_MEDIATYPE_REVERSED 'aidm' 00032 #define ID_DITHER_REVERSED 'ntfh' 00033 #define ID_RESLN_REVERSED 'nlsr' 00034 00035 #define DEVICE_PROFILE_DATA 1 00036 #define DEVICE_PROFILE_ENUMMODE 2 00037 00038 // 00039 // Local types 00040 // 00041 00042 typedef enum { 00043 NOMATCH = 0, 00044 MATCH = 1, 00045 EXACT_MATCH = 2, 00046 } MATCHTYPE; 00047 00048 typedef struct tagREGDATA { 00049 DWORD dwRefCount; 00050 DWORD dwManuID; 00051 DWORD dwModelID; 00052 } REGDATA, *PREGDATA; 00053 00054 typedef struct tagSCANNERDATA { 00055 PWSTR pDeviceName; 00056 HINSTANCE hModule; 00057 PSTI pSti; 00058 } SCANNERDATA, *PSCANNERDATA; 00059 00060 typedef BOOL (WINAPI *PFNOPENDEVICE)(PTSTR, LPHANDLE, PTSTR); 00061 typedef BOOL (WINAPI *PFNCLOSEDEVICE)(HANDLE); 00062 typedef DWORD (WINAPI *PFNGETDEVICEDATA)(HANDLE, PTSTR, PTSTR, PDWORD, PBYTE, DWORD, PDWORD); 00063 typedef DWORD (WINAPI *PFNSETDEVICEDATA)(HANDLE, PTSTR, PTSTR, DWORD, PBYTE, DWORD); 00064 typedef HRESULT (__stdcall *PFNSTICREATEINSTANCE)(HINSTANCE, DWORD, PSTI*, LPDWORD); 00065 00066 // 00067 // Local functions 00068 // 00069 00070 BOOL InternalGetColorDirectory(LPCTSTR, PTSTR, DWORD*); 00071 BOOL InternalInstallColorProfile(LPCTSTR, LPCTSTR); 00072 BOOL InternalUninstallColorProfile(LPCTSTR, LPCTSTR, BOOL); 00073 BOOL InternalAssociateColorProfileWithDevice(LPCTSTR, LPCTSTR, LPCTSTR); 00074 BOOL InternalDisassociateColorProfileFromDevice(LPCTSTR, LPCTSTR, LPCTSTR); 00075 BOOL InternalEnumColorProfiles(LPCTSTR, PENUMTYPE, PBYTE, PDWORD, PDWORD); 00076 BOOL InternalSetSCSProfile(LPCTSTR, DWORD, LPCTSTR); 00077 BOOL InternalGetSCSProfile(LPCTSTR, DWORD, PTSTR, PDWORD); 00078 VOID ConvertDwordToString(DWORD, PTSTR); 00079 PTSTR ConvertClassIdToClassString(DWORD); 00080 BOOL GetProfileClassString(LPCTSTR, PTSTR, PPROFILEHEADER); 00081 BOOL GetDeviceData(LPCTSTR, DWORD, DWORD, PVOID*, PDWORD, BOOL); 00082 BOOL SetDeviceData(LPCTSTR, DWORD, DWORD, PVOID, DWORD); 00083 BOOL IGetDeviceData(LPCTSTR, DWORD, DWORD, PVOID*, PDWORD, BOOL); 00084 BOOL ISetDeviceData(LPCTSTR, DWORD, DWORD, PVOID, DWORD); 00085 BOOL IsStringInMultiSz(PTSTR, PTSTR); 00086 DWORD RemoveStringFromMultiSz(PTSTR, PTSTR, DWORD); 00087 VOID InsertInBuffer(PBYTE, PBYTE, PTSTR); 00088 MATCHTYPE DoesProfileMatchEnumRecord(PTSTR, PENUMTYPE); 00089 MATCHTYPE CheckResMedHftnMatch(HPROFILE, PENUMTYPE); 00090 BOOL DwordMatches(PSETTINGS, DWORD); 00091 BOOL QwordMatches(PSETTINGS, PDWORD); 00092 BOOL WINAPI OpenPrtr(PTSTR, LPHANDLE, PTSTR); 00093 BOOL WINAPI ClosePrtr(HANDLE); 00094 DWORD WINAPI GetPrtrData(HANDLE, PTSTR, PTSTR, PDWORD, PBYTE, DWORD, PDWORD); 00095 DWORD WINAPI SetPrtrData(HANDLE, PTSTR, PTSTR, DWORD, PBYTE, DWORD); 00096 BOOL WINAPI OpenMonitor(PTSTR, LPHANDLE, PTSTR); 00097 BOOL WINAPI CloseMonitor(HANDLE); 00098 DWORD WINAPI GetMonitorData(HANDLE, PTSTR, PTSTR, PDWORD, PBYTE, DWORD, PDWORD); 00099 DWORD WINAPI SetMonitorData(HANDLE, PTSTR, PTSTR, DWORD, PBYTE, DWORD); 00100 BOOL WINAPI OpenScanner(PTSTR, LPHANDLE, PTSTR); 00101 BOOL WINAPI CloseScanner(HANDLE); 00102 DWORD WINAPI GetScannerData(HANDLE, PTSTR, PTSTR, PDWORD, PBYTE, DWORD, PDWORD); 00103 DWORD WINAPI SetScannerData(HANDLE, PTSTR, PTSTR, DWORD, PBYTE, DWORD); 00104 #ifdef _WIN95_ 00105 BOOL LoadSetupAPIDll(VOID); 00106 #else 00107 VOID ChangeICMSetting(LPCTSTR, LPCTSTR, DWORD); 00108 #endif // _WIN95_ 00109 00110 // 00111 // SetupAPI function pointers 00112 // 00113 typedef WINSETUPAPI HKEY 00114 (WINAPI *FP_SetupDiOpenDevRegKey)( 00115 IN HDEVINFO DeviceInfoSet, 00116 IN PSP_DEVINFO_DATA DeviceInfoData, 00117 IN DWORD Scope, 00118 IN DWORD HwProfile, 00119 IN DWORD KeyType, 00120 IN REGSAM samDesired 00121 ); 00122 00123 typedef WINSETUPAPI BOOL 00124 (WINAPI *FP_SetupDiDestroyDeviceInfoList)( 00125 IN HDEVINFO DeviceInfoSet 00126 ); 00127 00128 typedef WINSETUPAPI BOOL 00129 (WINAPI *FP_SetupDiEnumDeviceInfo)( 00130 IN HDEVINFO DeviceInfoSet, 00131 IN DWORD MemberIndex, 00132 OUT PSP_DEVINFO_DATA DeviceInfoData 00133 ); 00134 00135 #if !defined(_WIN95_) 00136 typedef WINSETUPAPI BOOL 00137 (WINAPI *FP_SetupDiGetDeviceInstanceId)( 00138 IN HDEVINFO DeviceInfoSet, 00139 IN PSP_DEVINFO_DATA DeviceInfoData, 00140 OUT PWSTR DeviceInstanceId, 00141 IN DWORD DeviceInstanceIdSize, 00142 OUT PDWORD RequiredSize OPTIONAL 00143 ); 00144 00145 typedef WINSETUPAPI HDEVINFO 00146 (WINAPI *FP_SetupDiGetClassDevs)( 00147 IN LPGUID ClassGuid, OPTIONAL 00148 IN PCWSTR Enumerator, OPTIONAL 00149 IN HWND hwndParent, OPTIONAL 00150 IN DWORD Flags 00151 ); 00152 #else 00153 typedef WINSETUPAPI BOOL 00154 (WINAPI *FP_SetupDiGetDeviceInstanceId)( 00155 IN HDEVINFO DeviceInfoSet, 00156 IN PSP_DEVINFO_DATA DeviceInfoData, 00157 OUT PSTR DeviceInstanceId, 00158 IN DWORD DeviceInstanceIdSize, 00159 OUT PDWORD RequiredSize OPTIONAL 00160 ); 00161 00162 typedef WINSETUPAPI HDEVINFO 00163 (WINAPI *FP_SetupDiGetClassDevs)( 00164 IN LPGUID ClassGuid, OPTIONAL 00165 IN PCSTR Enumerator, OPTIONAL 00166 IN HWND hwndParent, OPTIONAL 00167 IN DWORD Flags 00168 ); 00169 #endif 00170 00171 HMODULE ghModSetupAPIDll = NULL; 00172 00173 FP_SetupDiOpenDevRegKey fpSetupDiOpenDevRegKey = NULL; 00174 FP_SetupDiDestroyDeviceInfoList fpSetupDiDestroyDeviceInfoList = NULL; 00175 FP_SetupDiEnumDeviceInfo fpSetupDiEnumDeviceInfo = NULL; 00176 FP_SetupDiGetDeviceInstanceId fpSetupDiGetDeviceInstanceId = NULL; 00177 FP_SetupDiGetClassDevs fpSetupDiGetClassDevs = NULL; 00178 00179 // 00180 // Predefined profiles in order - INF file has 1-based index into this list 00181 // 00182 00183 TCHAR *gszDispProfiles[] = { 00184 __TEXT("mnB22G15.icm"), // 1 00185 __TEXT("mnB22G18.icm"), // 2 00186 __TEXT("mnB22G21.icm"), // 3 00187 __TEXT("mnEBUG15.icm"), // 4 00188 __TEXT("mnEBUG18.icm"), // 5 00189 __TEXT("mnEBUG21.icm"), // 6 00190 __TEXT("mnP22G15.icm"), // 7 00191 __TEXT("mnP22G18.icm"), // 8 00192 __TEXT("mnP22G21.icm"), // 9 00193 __TEXT("Diamond Compatible 9300K G2.2.icm"), // 10 00194 __TEXT("Hitachi Compatible 9300K G2.2.icm"), // 11 00195 __TEXT("NEC Compatible 9300K G2.2.icm"), // 12 00196 __TEXT("Trinitron Compatible 9300K G2.2.icm"), // 13 00197 }; 00198 00199 TCHAR *gpszClasses[] = { // different profile classes 00200 __TEXT("mntr"), // 0 00201 __TEXT("prtr"), // 1 00202 __TEXT("scnr"), // 2 00203 __TEXT("link"), // 3 00204 __TEXT("abst"), // 4 00205 __TEXT("spac"), // 5 00206 __TEXT("nmcl") // 6 00207 }; 00208 00209 #define INDEX_CLASS_MONITOR 0 00210 #define INDEX_CLASS_PRINTER 1 00211 #define INDEX_CLASS_SCANNER 2 00212 #define INDEX_CLASS_LINK 3 00213 #define INDEX_CLASS_ABSTRACT 4 00214 #define INDEX_CLASS_COLORSPACE 5 00215 #define INDEX_CLASS_NAMED 6 00216 00217 /****************************************************************************** 00218 * 00219 * GetColorDirectory 00220 * 00221 * Function: 00222 * These are the ANSI & Unicode wrappers for InternalGetColorDirectory. 00223 * Please see InternalGetColorDirectory for more details on this 00224 * function. 00225 * 00226 * Arguments: 00227 * pMachineName - name identifying machine on which the path 00228 * to the color directory is requested 00229 * pBuffer - pointer to buffer to receive pathname 00230 * pdwSize - pointer to size of buffer. On return it has size of 00231 * buffer needed if failure, and used on success 00232 * 00233 * Returns: 00234 * TRUE if successful, NULL otherwise 00235 * 00236 ******************************************************************************/ 00237 00238 #ifdef UNICODE // Windows NT versions 00239 00240 BOOL WINAPI 00241 GetColorDirectoryA( 00242 PCSTR pMachineName, 00243 PSTR pBuffer, 00244 PDWORD pdwSize 00245 ) 00246 { 00247 PWSTR pwszMachineName = NULL; // Unicode machine name 00248 PWSTR pwBuffer = NULL; // Unicode color directory path 00249 DWORD dwSize; // size of Unicode buffer 00250 DWORD dwErr = 0; // error code 00251 BOOL rc = TRUE; // return code 00252 00253 TRACEAPI((__TEXT("GetColorDirectoryA\n"))); 00254 00255 // 00256 // Validate parameters before we touch them 00257 // 00258 00259 if (!pdwSize || 00260 IsBadWritePtr(pdwSize, sizeof(DWORD)) || 00261 (pBuffer && IsBadWritePtr(pBuffer, *pdwSize))) 00262 { 00263 WARNING((__TEXT("Invalid parameter to GetColorDirectory\n"))); 00264 SetLastError(ERROR_INVALID_PARAMETER); 00265 return FALSE; 00266 } 00267 00268 // 00269 // Convert machine name to Unicode 00270 // 00271 00272 if (pMachineName) 00273 { 00274 rc = ConvertToUnicode(pMachineName, &pwszMachineName, TRUE); 00275 } 00276 else 00277 pwszMachineName = NULL; 00278 00279 dwSize = *pdwSize * sizeof(WCHAR); 00280 00281 // 00282 // Create a buffer to get Unicode directory from system 00283 // 00284 00285 if (pBuffer && dwSize) 00286 { 00287 pwBuffer = (PWSTR)MemAlloc(dwSize); 00288 if (! pwBuffer) 00289 { 00290 WARNING((__TEXT("Error allocating memory for Unicode string\n"))); 00291 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00292 rc = FALSE; 00293 goto EndGetColorDirectoryA; 00294 } 00295 } 00296 00297 rc = rc && InternalGetColorDirectory(pwszMachineName, pwBuffer, &dwSize); 00298 00299 *pdwSize = dwSize / sizeof(WCHAR); 00300 00301 // 00302 // Convert Unicode path to Ansi 00303 // 00304 00305 if (pwBuffer) 00306 { 00307 rc = rc && ConvertToAnsi(pwBuffer, &pBuffer, FALSE); 00308 } 00309 00310 EndGetColorDirectoryA: 00311 if (pwszMachineName) 00312 { 00313 MemFree(pwszMachineName); 00314 } 00315 00316 if (pwBuffer) 00317 { 00318 MemFree(pwBuffer); 00319 } 00320 00321 return rc; 00322 } 00323 00324 BOOL WINAPI 00325 GetColorDirectoryW( 00326 PCWSTR pMachineName, 00327 PWSTR pBuffer, 00328 PDWORD pdwSize 00329 ) 00330 { 00331 TRACEAPI((__TEXT("GetColorDirectoryW\n"))); 00332 00333 // 00334 // Internal function is ANSI in Windows 95, call it directly. 00335 // 00336 00337 return InternalGetColorDirectory(pMachineName, pBuffer, pdwSize); 00338 } 00339 00340 #else // Windows 95 versions 00341 00342 BOOL WINAPI 00343 GetColorDirectoryA( 00344 PCSTR pMachineName, 00345 PSTR pBuffer, 00346 PDWORD pdwSize 00347 ) 00348 { 00349 TRACEAPI((__TEXT("GetColorDirectoryA\n"))); 00350 00351 // 00352 // Internal function is ANSI in Windows 95, call it directly. 00353 // 00354 00355 return InternalGetColorDirectory(pMachineName, pBuffer, pdwSize); 00356 } 00357 00358 BOOL WINAPI 00359 GetColorDirectoryW( 00360 PCWSTR pMachineName, 00361 PWSTR pBuffer, 00362 PDWORD pdwSize 00363 ) 00364 { 00365 PSTR pszMachineName = NULL; // Ansi machine name 00366 PSTR pszBuffer = NULL; // Ansi color directory path 00367 DWORD dwSize; // size of Ansi buffer 00368 BOOL rc = TRUE; // return code 00369 00370 TRACEAPI((__TEXT("GetColorDirectoryW\n"))); 00371 00372 // 00373 // Validate parameters before we touch them 00374 // 00375 00376 if (!pdwSize || 00377 IsBadWritePtr(pdwSize, sizeof(DWORD)) || 00378 (pBuffer && IsBadWritePtr(pBuffer, *pdwSize))) 00379 { 00380 WARNING((__TEXT("Invalid parameter to GetColorDirectory\n"))); 00381 SetLastError(ERROR_INVALID_PARAMETER); 00382 return FALSE; 00383 } 00384 00385 // 00386 // Convert machine name to Ansi 00387 // 00388 00389 if (pMachineName) 00390 { 00391 rc = ConvertToAnsi(pMachineName, &pszMachineName, TRUE); 00392 } 00393 else 00394 pszMachineName = NULL; 00395 00396 // 00397 // Create a buffer to get Ansi directory from system 00398 // 00399 00400 dwSize = *pdwSize / sizeof(WCHAR); 00401 00402 if (pBuffer && dwSize) 00403 { 00404 pszBuffer = (PSTR)MemAlloc(dwSize); 00405 if (! pszBuffer) 00406 { 00407 WARNING((__TEXT("Error allocating memory for Ansi string\n"))); 00408 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00409 rc = FALSE; 00410 goto EndGetColorDirectoryW; 00411 } 00412 } 00413 00414 rc = rc && InternalGetColorDirectory(pszMachineName, pszBuffer, &dwSize); 00415 00416 *pdwSize = dwSize * sizeof(WCHAR); 00417 00418 // 00419 // Convert Ansi path to Unicode 00420 // 00421 00422 if (pszBuffer) 00423 { 00424 rc = rc && ConvertToUnicode(pszBuffer, &pBuffer, FALSE); 00425 } 00426 00427 EndGetColorDirectoryW: 00428 if (pszMachineName) 00429 { 00430 MemFree(pszMachineName); 00431 } 00432 00433 if (pszBuffer) 00434 { 00435 MemFree(pszBuffer); 00436 } 00437 00438 return rc; 00439 } 00440 00441 #endif // ! UNICODE 00442 00443 00444 /****************************************************************************** 00445 * 00446 * InstallColorProfile 00447 * 00448 * Function: 00449 * These are the ANSI & Unicode wrappers for InternalInstallColorProfile. 00450 * Please see InternalInstallColorProfile for more details on this 00451 * function. 00452 * 00453 * Arguments: 00454 * pMachineName - name identifying machine on which the profile 00455 * should be installed. NULL implies local 00456 * pProfileName - pointer to filename of profile to install 00457 * 00458 * Returns: 00459 * TRUE if successful, NULL otherwise 00460 * 00461 ******************************************************************************/ 00462 00463 #ifdef UNICODE // Windows NT versions 00464 00465 BOOL WINAPI 00466 InstallColorProfileA( 00467 PCSTR pMachineName, 00468 PCSTR pProfileName 00469 ) 00470 00471 { 00472 PWSTR pwszMachineName = NULL; // Unicode machine name 00473 PWSTR pwszProfileName = NULL; // Unicode profile name 00474 BOOL rc = TRUE; // return code 00475 00476 TRACEAPI((__TEXT("InstallColorProfileA\n"))); 00477 00478 // 00479 // Validate parameters before we touch them 00480 // 00481 00482 if (!pProfileName) 00483 { 00484 WARNING((__TEXT("Invalid parameter to InstallColorProfile\n"))); 00485 SetLastError(ERROR_INVALID_PARAMETER); 00486 return FALSE; 00487 } 00488 00489 // 00490 // Convert machine name to Unicode 00491 // 00492 00493 if (pMachineName) 00494 { 00495 rc = ConvertToUnicode(pMachineName, &pwszMachineName, TRUE); 00496 } 00497 else 00498 pwszMachineName = NULL; 00499 00500 // 00501 // Convert profile name to Unicode 00502 // 00503 00504 rc = rc && ConvertToUnicode(pProfileName, &pwszProfileName, TRUE); 00505 00506 // 00507 // Call the internal Unicode function 00508 // 00509 00510 rc = rc && InternalInstallColorProfile(pwszMachineName, pwszProfileName); 00511 00512 // 00513 // Free memory before leaving 00514 // 00515 00516 if (pwszProfileName) 00517 { 00518 MemFree(pwszProfileName); 00519 } 00520 00521 if (pwszMachineName) 00522 { 00523 MemFree(pwszMachineName); 00524 } 00525 00526 return rc; 00527 } 00528 00529 00530 BOOL WINAPI 00531 InstallColorProfileW( 00532 PCWSTR pMachineName, 00533 PCWSTR pProfileName 00534 ) 00535 { 00536 TRACEAPI((__TEXT("InstallColorProfileW\n"))); 00537 00538 // 00539 // Internal function is Unicode in Windows NT, call it directly. 00540 // 00541 00542 return InternalInstallColorProfile(pMachineName, pProfileName); 00543 } 00544 00545 00546 #else // Windows 95 versions 00547 00548 BOOL WINAPI 00549 InstallColorProfileA( 00550 PCSTR pMachineName, 00551 PCSTR pProfileName 00552 ) 00553 { 00554 TRACEAPI((__TEXT("InstallColorProfileA\n"))); 00555 00556 // 00557 // Internal function is ANSI in Windows 95, call it directly. 00558 // 00559 00560 return InternalInstallColorProfile(pMachineName, pProfileName); 00561 } 00562 00563 00564 BOOL WINAPI 00565 InstallColorProfileW( 00566 PCWSTR pMachineName, 00567 PCWSTR pProfileName 00568 ) 00569 { 00570 PSTR pszMachineName = NULL; // Ansi machine name 00571 PSTR pszProfileName = NULL; // Ansi profile name 00572 BOOL rc = TRUE; // return code 00573 00574 TRACEAPI((__TEXT("InstallColorProfileW\n"))); 00575 00576 // 00577 // Validate parameters before we touch them 00578 // 00579 00580 if (!pProfileName) 00581 { 00582 WARNING((__TEXT("Invalid parameter to InstallColorProfile\n"))); 00583 SetLastError(ERROR_INVALID_PARAMETER); 00584 return FALSE; 00585 } 00586 00587 // 00588 // Convert machine name to Ansi 00589 // 00590 00591 if (pMachineName) 00592 { 00593 rc = ConvertToAnsi(pMachineName, &pszMachineName, TRUE); 00594 } 00595 else 00596 pszMachineName = NULL; 00597 00598 // 00599 // Convert profile name to Ansi 00600 // 00601 00602 rc = rc && ConvertToAnsi(pProfileName, &pszProfileName, TRUE); 00603 00604 // 00605 // Call the internal Ansi function 00606 // 00607 00608 rc = rc && InternalInstallColorProfile(pszMachineName, pszProfileName); 00609 00610 // 00611 // Free memory before leaving 00612 // 00613 00614 if (pszProfileName) 00615 { 00616 MemFree(pszProfileName); 00617 } 00618 00619 if (pszMachineName) 00620 { 00621 MemFree(pszMachineName); 00622 } 00623 00624 return rc; 00625 } 00626 00627 00628 #endif // ! UNICODE 00629 00630 /****************************************************************************** 00631 * 00632 * UninstallColorProfile 00633 * 00634 * Function: 00635 * These are the ANSI & Unicode wrappers for InternalUninstallColorProfile. 00636 * Please see InternalUninstallColorProfile for more details on this 00637 * function. 00638 * 00639 * Arguments: 00640 * pMachineName - name identifying machine on which the profile 00641 * should be uninstalled. NULL implies local 00642 * pProfileName - pointer to filename of profile to uninstall 00643 * bDelete - TRUE if profile should be deleted in disk 00644 * 00645 * Returns: 00646 * TRUE if successful, NULL otherwise 00647 * 00648 ******************************************************************************/ 00649 00650 #ifdef UNICODE // Windows NT versions 00651 00652 BOOL WINAPI 00653 UninstallColorProfileA( 00654 PCSTR pMachineName, 00655 PCSTR pProfileName, 00656 BOOL bDelete 00657 ) 00658 { 00659 PWSTR pwszMachineName = NULL; // Unicode machine name 00660 PWSTR pwszProfileName = NULL; // Unicode profile name 00661 BOOL rc = TRUE; // return code 00662 00663 TRACEAPI((__TEXT("UninstallColorProfileA\n"))); 00664 00665 // 00666 // Validate parameters before we touch them 00667 // 00668 00669 if (!pProfileName) 00670 { 00671 WARNING((__TEXT("Invalid parameter to UninstallColorProfile\n"))); 00672 SetLastError(ERROR_INVALID_PARAMETER); 00673 return FALSE; 00674 } 00675 00676 // 00677 // Convert machine name to Unicode 00678 // 00679 00680 if (pMachineName) 00681 { 00682 rc = ConvertToUnicode(pMachineName, &pwszMachineName, TRUE); 00683 } 00684 else 00685 pwszMachineName = NULL; 00686 00687 // 00688 // Convert profile name to Unicode 00689 // 00690 00691 rc = rc && ConvertToUnicode(pProfileName, &pwszProfileName, TRUE); 00692 00693 // 00694 // Call the internal Unicode function 00695 // 00696 00697 rc = rc && InternalUninstallColorProfile(pwszMachineName, pwszProfileName, 00698 bDelete); 00699 00700 // 00701 // Free memory before leaving 00702 // 00703 00704 if (pwszProfileName) 00705 { 00706 MemFree(pwszProfileName); 00707 } 00708 00709 if (pwszMachineName) 00710 { 00711 MemFree(pwszMachineName); 00712 } 00713 00714 return rc; 00715 } 00716 00717 BOOL WINAPI 00718 UninstallColorProfileW( 00719 PCWSTR pMachineName, 00720 PCWSTR pProfileName, 00721 BOOL bDelete 00722 ) 00723 { 00724 TRACEAPI((__TEXT("UninstallColorProfileW\n"))); 00725 00726 // 00727 // Internal function is Unicode in Windows NT, call it directly. 00728 // 00729 00730 return InternalUninstallColorProfile(pMachineName, pProfileName, bDelete); 00731 } 00732 00733 00734 #else // Windows 95 versions 00735 00736 BOOL WINAPI 00737 UninstallColorProfileA( 00738 PCSTR pMachineName, 00739 PCSTR pProfileName, 00740 BOOL bDelete 00741 ) 00742 { 00743 TRACEAPI((__TEXT("UninstallColorProfileA\n"))); 00744 00745 // 00746 // Internal function is ANSI in Windows 95, call it directly. 00747 // 00748 00749 return InternalUninstallColorProfile(pMachineName, pProfileName, bDelete); 00750 } 00751 00752 00753 BOOL WINAPI 00754 UninstallColorProfileW( 00755 PCWSTR pMachineName, 00756 PCWSTR pProfileName, 00757 BOOL bDelete 00758 ) 00759 { 00760 PSTR pszMachineName = NULL; // Ansi machine name 00761 PSTR pszProfileName = NULL; // Ansi profile name 00762 BOOL rc = TRUE; // return code 00763 00764 TRACEAPI((__TEXT("UninstallColorProfileW\n"))); 00765 00766 // 00767 // Validate parameters before we touch them 00768 // 00769 00770 if (!pProfileName) 00771 { 00772 WARNING((__TEXT("Invalid parameter to UninstallColorProfile\n"))); 00773 SetLastError(ERROR_INVALID_PARAMETER); 00774 return FALSE; 00775 } 00776 00777 // 00778 // Convert machine name to Ansi 00779 // 00780 00781 if (pMachineName) 00782 { 00783 rc = ConvertToAnsi(pMachineName, &pszMachineName, TRUE); 00784 } 00785 else 00786 pszMachineName = NULL; 00787 00788 // 00789 // Convert profile name to Ansi 00790 // 00791 00792 rc = rc && ConvertToAnsi(pProfileName, &pszProfileName, TRUE); 00793 00794 // 00795 // Call the internal Ansi function 00796 // 00797 00798 rc = rc && InternalUninstallColorProfile(pszMachineName, pszProfileName, 00799 bDelete); 00800 00801 // 00802 // Free memory before leaving 00803 // 00804 00805 if (pszProfileName) 00806 { 00807 MemFree(pszProfileName); 00808 } 00809 00810 if (pszMachineName) 00811 { 00812 MemFree(pszMachineName); 00813 } 00814 00815 return rc; 00816 } 00817 00818 00819 #endif // ! UNICODE 00820 00821 00822 /****************************************************************************** 00823 * 00824 * AssociateColorProfileWithDevice 00825 * 00826 * Function: 00827 * These are the ANSI & Unicode wrappers for 00828 * InternalAssociateColorProfileWithDevice. Please see 00829 * InternalAssociateColorProfileWithDevice for more details 00830 * on this function. 00831 * 00832 * Arguments: 00833 * pMachineName - name identifying machine. NULL implies local 00834 * pProfileName - pointer to profile to associate 00835 * pDeviceName - pointer to device name 00836 * 00837 * Returns: 00838 * TRUE if successful, NULL otherwise 00839 * 00840 ******************************************************************************/ 00841 00842 #ifdef UNICODE // Windows NT versions 00843 00844 BOOL WINAPI 00845 AssociateColorProfileWithDeviceA( 00846 PCSTR pMachineName, 00847 PCSTR pProfileName, 00848 PCSTR pDeviceName 00849 ) 00850 { 00851 PWSTR pwszMachineName = NULL; // Unicode machine name 00852 PWSTR pwszProfileName = NULL; // Unicode profile name 00853 PWSTR pwszDeviceName = NULL; // Unicode device name 00854 BOOL rc = TRUE; // return code 00855 00856 TRACEAPI((__TEXT("AssociateColorProfileWithDeviceA\n"))); 00857 00858 // 00859 // Validate parameters before we touch them 00860 // 00861 00862 if (! pProfileName || 00863 ! pDeviceName) 00864 { 00865 WARNING((__TEXT("Invalid parameter to AssociateColorProfileWithDevice\n"))); 00866 SetLastError(ERROR_INVALID_PARAMETER); 00867 return FALSE; 00868 } 00869 00870 // 00871 // Convert machine name to Unicode 00872 // 00873 00874 if (pMachineName) 00875 { 00876 rc = ConvertToUnicode(pMachineName, &pwszMachineName, TRUE); 00877 } 00878 else 00879 pwszMachineName = NULL; 00880 00881 // 00882 // Convert profile name to Unicode 00883 // 00884 00885 rc = rc && ConvertToUnicode(pProfileName, &pwszProfileName, TRUE); 00886 00887 // 00888 // Convert device name to Unicode 00889 // 00890 00891 rc = rc && ConvertToUnicode(pDeviceName, &pwszDeviceName, TRUE); 00892 00893 // 00894 // Call the internal Unicode function 00895 // 00896 00897 rc = rc && InternalAssociateColorProfileWithDevice(pwszMachineName, 00898 pwszProfileName, pwszDeviceName); 00899 00900 // 00901 // Free memory before leaving 00902 // 00903 00904 if (pwszProfileName) 00905 { 00906 MemFree(pwszProfileName); 00907 } 00908 00909 if (pwszMachineName) 00910 { 00911 MemFree(pwszMachineName); 00912 } 00913 00914 if (pwszDeviceName) 00915 { 00916 MemFree(pwszDeviceName); 00917 } 00918 00919 return rc; 00920 } 00921 00922 00923 BOOL WINAPI 00924 AssociateColorProfileWithDeviceW( 00925 PCWSTR pMachineName, 00926 PCWSTR pProfileName, 00927 PCWSTR pDeviceName 00928 ) 00929 { 00930 TRACEAPI((__TEXT("AssociateColorProfileWithDeviceW\n"))); 00931 00932 // 00933 // Internal function is Unicode in Windows NT, call it directly. 00934 // 00935 00936 return InternalAssociateColorProfileWithDevice(pMachineName, 00937 pProfileName, pDeviceName); 00938 } 00939 00940 00941 #else // Windows 95 versions 00942 00943 BOOL WINAPI 00944 AssociateColorProfileWithDeviceA( 00945 PCSTR pMachineName, 00946 PCSTR pProfileName, 00947 PCSTR pDeviceName 00948 ) 00949 { 00950 TRACEAPI((__TEXT("AssociateColorProfileWithDeviceA\n"))); 00951 00952 // 00953 // Internal function is ANSI in Windows 95, call it directly. 00954 // 00955 00956 return InternalAssociateColorProfileWithDevice(pMachineName, 00957 pProfileName, pDeviceName); 00958 } 00959 00960 00961 BOOL WINAPI 00962 AssociateColorProfileWithDeviceW( 00963 PCWSTR pMachineName, 00964 PCWSTR pProfileName, 00965 PCWSTR pDeviceName 00966 ) 00967 { 00968 PSTR pszMachineName = NULL; // Ansi machine name 00969 PSTR pszProfileName = NULL; // Ansi profile name 00970 PSTR pszDeviceName = NULL; // Ansi device name 00971 BOOL rc = TRUE; // return code 00972 00973 TRACEAPI((__TEXT("AssociateColorProfileWithDeviceW\n"))); 00974 00975 // 00976 // Validate parameters before we touch them 00977 // 00978 00979 if (! pProfileName || 00980 ! pDeviceName) 00981 { 00982 WARNING((__TEXT("Invalid parameter to AssociateColorProfileWithDevice\n"))); 00983 SetLastError(ERROR_INVALID_PARAMETER); 00984 return FALSE; 00985 } 00986 00987 // 00988 // Convert machine name to Ansi 00989 // 00990 00991 if (pMachineName) 00992 { 00993 rc = ConvertToAnsi(pMachineName, &pszMachineName, TRUE); 00994 } 00995 else 00996 pszMachineName = NULL; 00997 00998 // 00999 // Convert profile name to Ansi 01000 // 01001 01002 rc = rc && ConvertToAnsi(pProfileName, &pszProfileName, TRUE); 01003 01004 // 01005 // Convert device name to Ansi 01006 // 01007 01008 rc = rc && ConvertToAnsi(pDeviceName, &pszDeviceName, TRUE); 01009 01010 // 01011 // Call the internal Ansi function 01012 // 01013 01014 rc = rc && InternalAssociateColorProfileWithDevice(pszMachineName, 01015 pszProfileName, pszDeviceName); 01016 01017 // 01018 // Free memory before leaving 01019 // 01020 01021 if (pszProfileName) 01022 { 01023 MemFree(pszProfileName); 01024 } 01025 01026 if (pszMachineName) 01027 { 01028 MemFree(pszMachineName); 01029 } 01030 01031 if (pszDeviceName) 01032 { 01033 MemFree(pszDeviceName); 01034 } 01035 01036 return rc; 01037 } 01038 01039 #endif // ! UNICODE 01040 01041 01042 /****************************************************************************** 01043 * 01044 * DisassociateColorProfileFromDevice 01045 * 01046 * Function: 01047 * These are the ANSI & Unicode wrappers for 01048 * InternalDisassociateColorProfileFromDevice. Please see 01049 * InternalDisassociateColorProfileFromDevice for more details 01050 * on this function. 01051 * 01052 * Arguments: 01053 * pMachineName - name identifying machine. NULL implies local 01054 * pProfileName - pointer to profile to disassiciate 01055 * pDeviceName - pointer to device name 01056 * 01057 * Returns: 01058 * TRUE if successful, NULL otherwise 01059 * 01060 ******************************************************************************/ 01061 01062 #ifdef UNICODE // Windows NT versions 01063 01064 BOOL WINAPI 01065 DisassociateColorProfileFromDeviceA( 01066 PCSTR pMachineName, 01067 PCSTR pProfileName, 01068 PCSTR pDeviceName 01069 ) 01070 { 01071 PWSTR pwszMachineName = NULL; // Unicode machine name 01072 PWSTR pwszProfileName = NULL; // Unicode profile name 01073 PWSTR pwszDeviceName = NULL; // Unicode device name 01074 BOOL rc = TRUE; // return code 01075 01076 TRACEAPI((__TEXT("DisassociateColorProfileWithDeviceA\n"))); 01077 01078 // 01079 // Validate parameters before we touch them 01080 // 01081 01082 if (! pProfileName || 01083 ! pDeviceName) 01084 { 01085 WARNING((__TEXT("Invalid parameter to DisassociateColorProfileFromDevice\n"))); 01086 SetLastError(ERROR_INVALID_PARAMETER); 01087 return FALSE; 01088 } 01089 01090 // 01091 // Convert machine name to Unicode 01092 // 01093 01094 if (pMachineName) 01095 { 01096 rc = ConvertToUnicode(pMachineName, &pwszMachineName, TRUE); 01097 } 01098 else 01099 pwszMachineName = NULL; 01100 01101 // 01102 // Convert profile name to Unicode 01103 // 01104 01105 rc = rc && ConvertToUnicode(pProfileName, &pwszProfileName, TRUE); 01106 01107 // 01108 // Convert device name to Unicode 01109 // 01110 01111 rc = rc && ConvertToUnicode(pDeviceName, &pwszDeviceName, TRUE); 01112 01113 // 01114 // Call the internal Unicode function 01115 // 01116 01117 rc = rc && InternalDisassociateColorProfileFromDevice(pwszMachineName, 01118 pwszProfileName, pwszDeviceName); 01119 01120 // 01121 // Free memory before leaving 01122 // 01123 01124 if (pwszProfileName) 01125 { 01126 MemFree(pwszProfileName); 01127 } 01128 01129 if (pwszMachineName) 01130 { 01131 MemFree(pwszMachineName); 01132 } 01133 01134 if (pwszDeviceName) 01135 { 01136 MemFree(pwszDeviceName); 01137 } 01138 01139 return rc; 01140 } 01141 01142 01143 BOOL WINAPI 01144 DisassociateColorProfileFromDeviceW( 01145 PCWSTR pMachineName, 01146 PCWSTR pProfileName, 01147 PCWSTR pDeviceName 01148 ) 01149 { 01150 TRACEAPI((__TEXT("DisassociateColorProfileWithDeviceW\n"))); 01151 01152 // 01153 // Internal function is Unicode in Windows NT, call it directly. 01154 // 01155 01156 return InternalDisassociateColorProfileFromDevice(pMachineName, 01157 pProfileName, pDeviceName); 01158 } 01159 01160 01161 #else // Windows 95 versions 01162 01163 BOOL WINAPI 01164 DisassociateColorProfileFromDeviceA( 01165 PCSTR pMachineName, 01166 PCSTR pProfileName, 01167 PCSTR pDeviceName 01168 ) 01169 { 01170 TRACEAPI((__TEXT("DisassociateColorProfileWithDeviceA\n"))); 01171 01172 // 01173 // Internal function is ANSI in Windows 95, call it directly. 01174 // 01175 01176 return InternalDisassociateColorProfileFromDevice(pMachineName, 01177 pProfileName, pDeviceName); 01178 } 01179 01180 01181 BOOL WINAPI 01182 DisassociateColorProfileFromDeviceW( 01183 PCWSTR pMachineName, 01184 PCWSTR pProfileName, 01185 PCWSTR pDeviceName 01186 ) 01187 { 01188 PSTR pszMachineName = NULL; // Ansi machine name 01189 PSTR pszProfileName = NULL; // Ansi profile name 01190 PSTR pszDeviceName = NULL; // Ansi device name 01191 BOOL rc = TRUE; // return code 01192 01193 TRACEAPI((__TEXT("DisassociateColorProfileWithDeviceW\n"))); 01194 01195 // 01196 // Validate parameters before we touch them 01197 // 01198 01199 if (! pProfileName || 01200 ! pDeviceName) 01201 { 01202 WARNING((__TEXT("Invalid parameter to AssociateColorProfileWithDevice\n"))); 01203 SetLastError(ERROR_INVALID_PARAMETER); 01204 return FALSE; 01205 } 01206 01207 // 01208 // Convert machine name to Ansi 01209 // 01210 01211 if (pMachineName) 01212 { 01213 rc = ConvertToAnsi(pMachineName, &pszMachineName, TRUE); 01214 } 01215 else 01216 pszMachineName = NULL; 01217 01218 // 01219 // Convert profile name to Ansi 01220 // 01221 01222 rc = rc && ConvertToAnsi(pProfileName, &pszProfileName, TRUE); 01223 01224 // 01225 // Convert device name to Ansi 01226 // 01227 01228 rc = rc && ConvertToAnsi(pDeviceName, &pszDeviceName, TRUE); 01229 01230 // 01231 // Call the internal Ansi function 01232 // 01233 01234 rc = rc && InternalDisassociateColorProfileFromDevice(pszMachineName, 01235 pszProfileName, pszDeviceName); 01236 01237 // 01238 // Free memory before leaving 01239 // 01240 01241 if (pszProfileName) 01242 { 01243 MemFree(pszProfileName); 01244 } 01245 01246 if (pszMachineName) 01247 { 01248 MemFree(pszMachineName); 01249 } 01250 01251 if (pszDeviceName) 01252 { 01253 MemFree(pszDeviceName); 01254 } 01255 01256 return rc; 01257 } 01258 01259 #endif // ! UNICODE 01260 01261 01262 01263 /****************************************************************************** 01264 * 01265 * EnumColorProfiles 01266 * 01267 * Function: 01268 * These are the ANSI & Unicode wrappers for InternalEnumColorProfile. 01269 * Please see InternalEnumColorProfile for more details on this 01270 * function. 01271 * 01272 * Arguments: 01273 * pMachineName - name identifying machine on which the enumeration 01274 * needs to be done 01275 * pEnumRecord - pointer to enumeration criteria 01276 * pBuffer - pointer to buffer to receive result, can be NULL 01277 * pdwSize - pointer to buffer size. On return it is actual number 01278 * of bytes copied/needed. 01279 * pnProfiles - pointer to DWORD. On return, it is number of profiles 01280 * copied to pBuffer. 01281 * 01282 * Returns: 01283 * TRUE if successful, NULL otherwise 01284 * 01285 ******************************************************************************/ 01286 01287 #ifdef UNICODE // Windows NT versions 01288 01289 BOOL WINAPI 01290 EnumColorProfilesA( 01291 PCSTR pMachineName, 01292 PENUMTYPEA pEnumRecord, 01293 PBYTE pBuffer, 01294 PDWORD pdwSize, 01295 PDWORD pnProfiles 01296 ) 01297 { 01298 PWSTR pwszMachineName = NULL; // Unicode machine name 01299 PWSTR pwszDeviceName = NULL; // Unicode device name 01300 PSTR pAnsiDeviceName = NULL; // incoming Ansi device name 01301 PWSTR pwBuffer = NULL; // buffer to receive data 01302 PWSTR pwTempBuffer = NULL; // temporary pointer to buffer 01303 DWORD dwSize; // size of buffer 01304 DWORD dwSizeOfStruct; // size of ENUMTYPE structure 01305 DWORD dwVersion; // ENUMTYPE structure version 01306 BOOL rc = TRUE; // return code 01307 01308 TRACEAPI((__TEXT("EnumColorProfilesA\n"))); 01309 01310 // 01311 // Validate parameters before we touch them 01312 // 01313 01314 if (! pdwSize || 01315 IsBadWritePtr(pdwSize, sizeof(DWORD)) || 01316 (pBuffer && IsBadWritePtr(pBuffer, *pdwSize)) || 01317 ! pEnumRecord || 01318 IsBadReadPtr(pEnumRecord, sizeof(DWORD)*3)) // probe until ENUMTYPE.dwFields 01319 { 01320 ParameterError_EnumColorProfilesA: 01321 WARNING((__TEXT("Invalid parameter to EnumColorProfiles\n"))); 01322 SetLastError(ERROR_INVALID_PARAMETER); 01323 return FALSE; 01324 } 01325 01326 // 01327 // Check structure size based on its version. 01328 // 01329 01330 dwSizeOfStruct = pEnumRecord->dwSize; 01331 dwVersion = pEnumRecord->dwVersion; 01332 01333 if (dwVersion >= ENUM_TYPE_VERSION) 01334 { 01335 if (dwSizeOfStruct < sizeof(ENUMTYPE)) 01336 goto ParameterError_EnumColorProfilesA; 01337 } 01338 else if (dwVersion == 0x0200) 01339 { 01340 if (dwSizeOfStruct < sizeof(ENUMTYPE)-sizeof(DWORD)) 01341 goto ParameterError_EnumColorProfilesA; 01342 01343 // 01344 // Version 2 should not have ET_DEVICECLASS bit 01345 // 01346 01347 if (pEnumRecord->dwFields & ET_DEVICECLASS) 01348 goto ParameterError_EnumColorProfilesA; 01349 01350 WARNING((__TEXT("Old version ENUMTYPE to EnumColorProfiles\n"))); 01351 } 01352 else 01353 { 01354 goto ParameterError_EnumColorProfilesA; 01355 } 01356 01357 if (IsBadReadPtr(pEnumRecord, dwSizeOfStruct)) 01358 { 01359 goto ParameterError_EnumColorProfilesA; 01360 } 01361 01362 // 01363 // Convert machine name to Unicode 01364 // 01365 01366 if (pMachineName) 01367 { 01368 rc = ConvertToUnicode(pMachineName, &pwszMachineName, TRUE); 01369 } 01370 else 01371 pwszMachineName = NULL; 01372 01373 // 01374 // If device name is specified, convert it to Unicode 01375 // 01376 01377 if (pEnumRecord->dwFields & ET_DEVICENAME) 01378 { 01379 if (! pEnumRecord->pDeviceName) 01380 { 01381 WARNING((__TEXT("Invalid parameter to EnumColorProfiles\n"))); 01382 SetLastError(ERROR_INVALID_PARAMETER); 01383 rc = FALSE; 01384 goto EndEnumColorProfilesA; 01385 } 01386 01387 // 01388 // Convert device name to Unicode 01389 // 01390 01391 pAnsiDeviceName = (PSTR)pEnumRecord->pDeviceName; 01392 rc = rc && ConvertToUnicode(pAnsiDeviceName, &pwszDeviceName, TRUE); 01393 pEnumRecord->pDeviceName = (PSTR) pwszDeviceName; 01394 } 01395 01396 dwSize = *pdwSize * sizeof(WCHAR); 01397 01398 // 01399 // Allocate buffer of suitable size 01400 // 01401 01402 if (pBuffer && dwSize) 01403 { 01404 pwBuffer = MemAlloc(dwSize); 01405 if (! pwBuffer) 01406 { 01407 WARNING((__TEXT("Error allocating memory for Unicode buffer\n"))); 01408 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 01409 rc = FALSE; 01410 goto EndEnumColorProfilesA; 01411 } 01412 } 01413 01414 // 01415 // Call the internal Unicode function 01416 // 01417 01418 rc = rc && InternalEnumColorProfiles(pwszMachineName, 01419 (PENUMTYPEW)pEnumRecord, (PBYTE)pwBuffer, &dwSize, pnProfiles); 01420 01421 if (pwBuffer && rc) 01422 { 01423 pwTempBuffer = pwBuffer; 01424 while (*pwTempBuffer) 01425 { 01426 rc = rc && ConvertToAnsi(pwTempBuffer, (PSTR *)&pBuffer, FALSE); 01427 pwTempBuffer += lstrlenW(pwTempBuffer) + 1; 01428 pBuffer += (lstrlenA((PSTR)pBuffer) + 1) * sizeof(char); 01429 } 01430 01431 *((PSTR)pBuffer) = '\0'; 01432 } 01433 01434 *pdwSize = dwSize / sizeof(WCHAR); 01435 01436 EndEnumColorProfilesA: 01437 if (pwszMachineName) 01438 { 01439 MemFree(pwszMachineName); 01440 } 01441 if (pAnsiDeviceName) 01442 { 01443 ASSERT(pEnumRecord->pDeviceName != NULL); 01444 01445 MemFree((PBYTE)pEnumRecord->pDeviceName); 01446 pEnumRecord->pDeviceName = (PCSTR)pAnsiDeviceName; 01447 } 01448 if (pwBuffer) 01449 { 01450 MemFree(pwBuffer); 01451 } 01452 01453 return rc; 01454 } 01455 01456 01457 BOOL WINAPI 01458 EnumColorProfilesW( 01459 PCWSTR pMachineName, 01460 PENUMTYPEW pEnumRecord, 01461 PBYTE pBuffer, 01462 PDWORD pdwSize, 01463 PDWORD pnProfiles 01464 ) 01465 { 01466 TRACEAPI((__TEXT("EnumColorProfilesW\n"))); 01467 01468 // 01469 // Internal function is Unicode in Windows NT, call it directly. 01470 // 01471 01472 return InternalEnumColorProfiles(pMachineName, pEnumRecord, 01473 pBuffer, pdwSize, pnProfiles); 01474 } 01475 01476 #else // Windows 95 versions 01477 01478 BOOL WINAPI 01479 EnumColorProfilesA( 01480 PCSTR pMachineName, 01481 PENUMTYPEA pEnumRecord, 01482 PBYTE pBuffer, 01483 PDWORD pdwSize, 01484 PDWORD pnProfiles 01485 ) 01486 { 01487 TRACEAPI((__TEXT("EnumColorProfilesA\n"))); 01488 01489 // 01490 // Internal function is ANSI in Windows 95, call it directly. 01491 // 01492 01493 return InternalEnumColorProfiles(pMachineName, pEnumRecord, 01494 pBuffer, pdwSize, pnProfiles); 01495 } 01496 01497 01498 BOOL WINAPI 01499 EnumColorProfilesW( 01500 PCWSTR pMachineName, 01501 PENUMTYPEW pEnumRecord, 01502 PBYTE pBuffer, 01503 PDWORD pdwSize, 01504 PDWORD pnProfiles 01505 ) 01506 { 01507 PSTR pszMachineName = NULL; // Ansi machine name 01508 PSTR pszDeviceName = NULL; // Ansi device name 01509 PWSTR pUnicodeDeviceName = NULL;// incoming Unicode device name 01510 PSTR pszBuffer = NULL; // buffer to receive data 01511 PSTR pszTempBuffer = NULL; // temporary pointer to buffer 01512 DWORD dwSize; // size of buffer 01513 DWORD dwSizeOfStruct; // size of ENUMTYPE structure 01514 DWORD dwVersion; // ENUMTYPE structure version 01515 BOOL rc = TRUE; // return code 01516 01517 TRACEAPI((__TEXT("EnumColorProfilesW\n"))); 01518 01519 // 01520 // Validate parameters before we touch them 01521 // 01522 01523 if (! pdwSize || 01524 IsBadWritePtr(pdwSize, sizeof(DWORD)) || 01525 (pBuffer && IsBadWritePtr(pBuffer, *pdwSize)) || 01526 ! pEnumRecord || 01527 IsBadReadPtr(pEnumRecord, sizeof(DWORD)*3)) // probe until ENUMTYPE.dwFields 01528 { 01529 ParameterError_EnumColorProfilesW: 01530 WARNING((__TEXT("Invalid parameter to EnumColorProfiles\n"))); 01531 SetLastError(ERROR_INVALID_PARAMETER); 01532 return FALSE; 01533 } 01534 01535 // 01536 // Check structure size based on its version. 01537 // 01538 01539 dwSizeOfStruct = pEnumRecord->dwSize; 01540 dwVersion = pEnumRecord->dwVersion; 01541 01542 if (dwVersion >= ENUM_TYPE_VERSION) 01543 { 01544 if (dwSizeOfStruct < sizeof(ENUMTYPE)) 01545 goto ParameterError_EnumColorProfilesW; 01546 } 01547 else if (dwVersion == 0x0200) 01548 { 01549 if (dwSizeOfStruct < sizeof(ENUMTYPE)-sizeof(DWORD)) 01550 goto ParameterError_EnumColorProfilesW; 01551 01552 // 01553 // Version 2 should not have ET_DEVICECLASS bit 01554 // 01555 01556 if (pEnumRecord->dwFields & ET_DEVICECLASS) 01557 goto ParameterError_EnumColorProfilesW; 01558 01559 WARNING((__TEXT("Old version ENUMTYPE to EnumColorProfiles\n"))); 01560 } 01561 else 01562 { 01563 goto ParameterError_EnumColorProfilesW; 01564 } 01565 01566 if (IsBadReadPtr(pEnumRecord, dwSizeOfStruct)) 01567 { 01568 goto ParameterError_EnumColorProfilesW; 01569 } 01570 01571 // 01572 // Convert machine name to Ansi 01573 // 01574 01575 if (pMachineName) 01576 { 01577 rc = ConvertToAnsi(pMachineName, &pszMachineName, TRUE); 01578 } 01579 01580 // 01581 // If device name is specified, convert it to Unicode 01582 // 01583 01584 if (pEnumRecord->dwFields & ET_DEVICENAME) 01585 { 01586 if (! pEnumRecord->pDeviceName) 01587 { 01588 WARNING((__TEXT("Invalid parameter to EnumColorProfiles\n"))); 01589 SetLastError(ERROR_INVALID_PARAMETER); 01590 goto EndEnumColorProfilesW; 01591 } 01592 01593 // 01594 // Convert device name to Ansi 01595 // 01596 01597 pUnicodeDeviceName = (PWSTR)pEnumRecord->pDeviceName; 01598 rc = rc && ConvertToAnsi(pUnicodeDeviceName, &pszDeviceName, TRUE); 01599 pEnumRecord->pDeviceName = (PCWSTR) pszDeviceName; 01600 } 01601 01602 dwSize = *pdwSize / sizeof(WCHAR); 01603 01604 // 01605 // Allocate buffer of suitable size 01606 // 01607 01608 if (pBuffer && dwSize) 01609 { 01610 pszBuffer = MemAlloc(dwSize); 01611 if (! pszBuffer) 01612 { 01613 WARNING((__TEXT("Error allocating memory for Ansi buffer\n"))); 01614 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 01615 rc = FALSE; 01616 goto EndEnumColorProfilesW; 01617 } 01618 } 01619 01620 // 01621 // Call the internal Ansi function 01622 // 01623 01624 rc = rc && InternalEnumColorProfiles(pszMachineName, 01625 (PENUMTYPEA)pEnumRecord, (PBYTE)pszBuffer, &dwSize, pnProfiles); 01626 01627 if (pszBuffer && rc) 01628 { 01629 pszTempBuffer = pszBuffer; 01630 while (*pszTempBuffer) 01631 { 01632 rc = rc && ConvertToUnicode(pszTempBuffer, (PWSTR *)&pBuffer, FALSE); 01633 pszTempBuffer += lstrlenA(pszTempBuffer) + 1; 01634 pBuffer += (lstrlenW((PWSTR)pBuffer) + 1) * sizeof(WCHAR); 01635 } 01636 01637 *((PWSTR)pBuffer) = '\0'; 01638 } 01639 *pdwSize = dwSize * sizeof(WCHAR); 01640 01641 EndEnumColorProfilesW: 01642 if (pszMachineName) 01643 { 01644 MemFree(pszMachineName); 01645 } 01646 if (pUnicodeDeviceName) 01647 { 01648 ASSERT(pEnumRecord->pDeviceName != NULL); 01649 01650 MemFree((PSTR)pEnumRecord->pDeviceName); 01651 pEnumRecord->pDeviceName = (PCWSTR)pUnicodeDeviceName; 01652 } 01653 if (pszBuffer) 01654 { 01655 MemFree(pszBuffer); 01656 } 01657 01658 return rc; 01659 } 01660 01661 #endif // ! UNICODE 01662 01663 01664 /****************************************************************************** 01665 * 01666 * SetStandardColorSpaceProfile 01667 * 01668 * Function: 01669 * These are the ANSI & Unicode wrappers for InternalSetSCSProfile. 01670 * Please see InternalSetSCSProfile for more details on this 01671 * function. 01672 * 01673 * Arguments: 01674 * pMachineName - name identifying machine on which the standard color 01675 * space profile should be registered 01676 * dwSCS - ID for the standard color space 01677 * pProfileName - pointer to profile filename 01678 * 01679 * Returns: 01680 * TRUE if successful, NULL otherwise 01681 * 01682 ******************************************************************************/ 01683 01684 #ifdef UNICODE // Windows NT versions 01685 01686 BOOL WINAPI 01687 SetStandardColorSpaceProfileA( 01688 PCSTR pMachineName, 01689 DWORD dwSCS, 01690 PCSTR pProfileName 01691 ) 01692 { 01693 PWSTR pwszMachineName = NULL; // Unicode machine name 01694 PWSTR pwszProfileName = NULL; // Unicode profile name 01695 BOOL rc = TRUE; // return code 01696 01697 TRACEAPI((__TEXT("SetStandardColorSpaceProfileA\n"))); 01698 01699 // 01700 // Validate parameters before we touch them 01701 // 01702 01703 if (! pProfileName) 01704 { 01705 WARNING((__TEXT("Invalid parameter to SetStandardColorSpaceProfile\n"))); 01706 SetLastError(ERROR_INVALID_PARAMETER); 01707 return FALSE; 01708 } 01709 01710 // 01711 // Convert machine name to Unicode 01712 // 01713 01714 if (pMachineName) 01715 { 01716 rc = ConvertToUnicode(pMachineName, &pwszMachineName, TRUE); 01717 } 01718 else 01719 pwszMachineName = NULL; 01720 01721 // 01722 // Convert profile name to Unicode 01723 // 01724 01725 rc = rc && ConvertToUnicode(pProfileName, &pwszProfileName, TRUE); 01726 01727 // 01728 // Call the internal Unicode function 01729 // 01730 01731 rc = rc && InternalSetSCSProfile(pwszMachineName, dwSCS, pwszProfileName); 01732 01733 // 01734 // Free memory before leaving 01735 // 01736 01737 if (pwszProfileName) 01738 { 01739 MemFree(pwszProfileName); 01740 } 01741 01742 if (pwszMachineName) 01743 { 01744 MemFree(pwszMachineName); 01745 } 01746 01747 return rc; 01748 } 01749 01750 BOOL WINAPI 01751 SetStandardColorSpaceProfileW( 01752 PCWSTR pMachineName, 01753 DWORD dwSCS, 01754 PCWSTR pProfileName 01755 ) 01756 { 01757 TRACEAPI((__TEXT("SetStandardColorSpaceProfileW\n"))); 01758 01759 // 01760 // Internal function is Unicode in Windows NT, call it directly. 01761 // 01762 01763 return InternalSetSCSProfile(pMachineName, dwSCS, pProfileName); 01764 } 01765 01766 #else // Windows 95 versions 01767 01768 BOOL WINAPI 01769 SetStandardColorSpaceProfileA( 01770 PCSTR pMachineName, 01771 DWORD dwSCS, 01772 PCSTR pProfileName 01773 ) 01774 { 01775 TRACEAPI((__TEXT("SetStandardColorSpaceProfileA\n"))); 01776 01777 // 01778 // Internal function is ANSI in Windows 95, call it directly. 01779 // 01780 01781 return InternalSetSCSProfile(pMachineName, dwSCS, pProfileName); 01782 } 01783 01784 BOOL WINAPI 01785 SetStandardColorSpaceProfileW( 01786 PCWSTR pMachineName, 01787 DWORD dwSCS, 01788 PCWSTR pProfileName 01789 ) 01790 { 01791 PSTR pszMachineName = NULL; // Ansi machine name 01792 PSTR pszProfileName = NULL; // Ansi profile name 01793 BOOL rc = TRUE; // return code 01794 01795 TRACEAPI((__TEXT("SetStandardColorSpaceProfileW\n"))); 01796 01797 // 01798 // Validate parameters before we touch them 01799 // 01800 01801 if (! pProfileName) 01802 { 01803 WARNING((__TEXT("Invalid parameter to SetStandardColorSpaceProfile\n"))); 01804 SetLastError(ERROR_INVALID_PARAMETER); 01805 return FALSE; 01806 } 01807 01808 // 01809 // Convert machine name to Ansi 01810 // 01811 01812 if (pMachineName) 01813 { 01814 rc = ConvertToAnsi(pMachineName, &pszMachineName, TRUE); 01815 } 01816 else 01817 pszMachineName = NULL; 01818 01819 // 01820 // Convert profile name to Ansi 01821 // 01822 01823 rc = rc && ConvertToAnsi(pProfileName, &pszProfileName, TRUE); 01824 01825 // 01826 // Call the internal Ansi function 01827 // 01828 01829 rc = rc && InternalSetSCSProfile(pszMachineName, dwSCS, pszProfileName); 01830 01831 // 01832 // Free memory before leaving 01833 // 01834 01835 if (pszProfileName) 01836 { 01837 MemFree(pszProfileName); 01838 } 01839 01840 if (pszMachineName) 01841 { 01842 MemFree(pszMachineName); 01843 } 01844 01845 return rc; 01846 } 01847 01848 #endif // ! UNICODE 01849 01850 01851 /****************************************************************************** 01852 * 01853 * GetStandardColorSpaceProfile 01854 * 01855 * Function: 01856 * These are the ANSI & Unicode wrappers for InternalGetSCSProfile. 01857 * Please see InternalGetSCSProfile for more details on this 01858 * function. 01859 * 01860 * Arguments: 01861 * pMachineName - name identifying machine on which the standard color 01862 * space profile should be queried 01863 * dwSCS - ID for the standard color space 01864 * pBuffer - pointer to buffer to receive profile filename 01865 * pdwSize - pointer to DWORD specifying size of buffer. On return 01866 * it has size needed/used 01867 * 01868 * Returns: 01869 * TRUE if successful, NULL otherwise 01870 * 01871 ******************************************************************************/ 01872 01873 #ifdef UNICODE // Windows NT versions 01874 01875 BOOL WINAPI 01876 GetStandardColorSpaceProfileA( 01877 PCSTR pMachineName, 01878 DWORD dwSCS, 01879 PSTR pBuffer, 01880 PDWORD pdwSize 01881 ) 01882 { 01883 PWSTR pwszMachineName = NULL; // Unicode machine name 01884 PWSTR pwBuffer = NULL; // Unicode color directory path 01885 DWORD dwSize; // size of Unicode buffer 01886 BOOL rc = TRUE; // return code 01887 01888 TRACEAPI((__TEXT("GetStandardColorSpaceProfileA\n"))); 01889 01890 // 01891 // Validate parameters before we touch them 01892 // 01893 01894 if (! pdwSize || 01895 IsBadWritePtr(pdwSize, sizeof(DWORD)) || 01896 (pBuffer && IsBadWritePtr(pBuffer, *pdwSize))) 01897 { 01898 WARNING((__TEXT("Invalid parameter to GetStandardColorSpaceProfile\n"))); 01899 SetLastError(ERROR_INVALID_PARAMETER); 01900 return FALSE; 01901 } 01902 01903 // 01904 // Convert machine name to Unicode 01905 // 01906 01907 if (pMachineName) 01908 { 01909 rc = ConvertToUnicode(pMachineName, &pwszMachineName, TRUE); 01910 } 01911 else 01912 pwszMachineName = NULL; 01913 01914 dwSize = *pdwSize * sizeof(WCHAR); 01915 01916 // 01917 // Create a buffer to get Unicode filename from system 01918 // 01919 01920 if (pBuffer && dwSize) 01921 { 01922 pwBuffer = (PWSTR)MemAlloc(dwSize); 01923 if (! pwBuffer) 01924 { 01925 WARNING((__TEXT("Error allocating memory for Unicode string\n"))); 01926 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 01927 rc = FALSE; 01928 goto EndGetSCSProfileA; 01929 } 01930 } 01931 01932 rc = rc && InternalGetSCSProfile(pwszMachineName, dwSCS, pwBuffer, &dwSize); 01933 01934 *pdwSize = dwSize / sizeof(WCHAR); 01935 01936 // 01937 // Convert Unicode path to Ansi 01938 // 01939 01940 if (pwBuffer) 01941 { 01942 rc = rc && ConvertToAnsi(pwBuffer, &pBuffer, FALSE); 01943 } 01944 01945 EndGetSCSProfileA: 01946 if (pwszMachineName) 01947 { 01948 MemFree(pwszMachineName); 01949 } 01950 01951 if (pwBuffer) 01952 { 01953 MemFree(pwBuffer); 01954 } 01955 01956 return rc; 01957 } 01958 01959 BOOL WINAPI 01960 GetStandardColorSpaceProfileW( 01961 PCWSTR pMachineName, 01962 DWORD dwSCS, 01963 PWSTR pBuffer, 01964 PDWORD pdwSize 01965 ) 01966 { 01967 TRACEAPI((__TEXT("GetStandardColorSpaceProfileW\n"))); 01968 01969 // 01970 // Internal function is Unicode in Windows NT, call it directly. 01971 // 01972 01973 return InternalGetSCSProfile(pMachineName, dwSCS, pBuffer, pdwSize); 01974 } 01975 01976 #else // Windows 95 versions 01977 01978 BOOL WINAPI 01979 GetStandardColorSpaceProfileA( 01980 PCSTR pMachineName, 01981 DWORD dwSCS, 01982 PSTR pBuffer, 01983 PDWORD pdwSize 01984 ) 01985 { 01986 TRACEAPI((__TEXT("GetStandardColorSpaceProfileA\n"))); 01987 01988 // 01989 // Internal function is ANSI in Windows 95, call it directly. 01990 // 01991 01992 return InternalGetSCSProfile(pMachineName, dwSCS, pBuffer, pdwSize); 01993 } 01994 01995 BOOL WINAPI 01996 GetStandardColorSpaceProfileW( 01997 PCWSTR pMachineName, 01998 DWORD dwSCS, 01999 PWSTR pBuffer, 02000 PDWORD pdwSize 02001 ) 02002 { 02003 PSTR pszMachineName = NULL; // Ansi machine name 02004 PSTR pszBuffer = NULL; // Ansi color directory path 02005 DWORD dwSize; // size of Ansi buffer 02006 BOOL rc = TRUE; // return code 02007 02008 TRACEAPI((__TEXT("GetStandardColorSpaceProfileW\n"))); 02009 02010 // 02011 // Validate parameters before we touch them 02012 // 02013 02014 if (! pdwSize || 02015 IsBadWritePtr(pdwSize, sizeof(DWORD)) || 02016 (pBuffer && IsBadWritePtr(pBuffer, *pdwSize))) 02017 { 02018 WARNING((__TEXT("Invalid parameter to GetStandardColorSpaceProfile\n"))); 02019 SetLastError(ERROR_INVALID_PARAMETER); 02020 return FALSE; 02021 } 02022 02023 // 02024 // Convert machine name to Ansi 02025 // 02026 02027 if (pMachineName) 02028 { 02029 rc = ConvertToAnsi(pMachineName, &pszMachineName, TRUE); 02030 } 02031 else 02032 pszMachineName = NULL; 02033 02034 dwSize = *pdwSize / sizeof(WCHAR); 02035 02036 // 02037 // Create a buffer to get Ansi profilename from system 02038 // 02039 02040 if (pBuffer && dwSize) 02041 { 02042 pszBuffer = (PSTR)MemAlloc(dwSize); 02043 if (! pBuffer) 02044 { 02045 WARNING((__TEXT("Error allocating memory for Ansi string\n"))); 02046 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 02047 rc = FALSE; 02048 goto EndGetSCSProfileW; 02049 } 02050 } 02051 02052 rc = rc && InternalGetSCSProfile(pszMachineName, dwSCS, pszBuffer, &dwSize); 02053 02054 *pdwSize = dwSize * sizeof(WCHAR); 02055 02056 // 02057 // Convert Ansi path to Unicode 02058 // 02059 02060 if (pszBuffer) 02061 { 02062 rc = rc && ConvertToUnicode(pszBuffer, &pBuffer, FALSE); 02063 } 02064 02065 EndGetSCSProfileW: 02066 if (pszMachineName) 02067 { 02068 MemFree(pszMachineName); 02069 } 02070 02071 if (pszBuffer) 02072 { 02073 MemFree(pszBuffer); 02074 } 02075 02076 return rc; 02077 } 02078 02079 #endif // ! UNICODE 02080 02081 02082 /****************************************************************************** 02083 * 02084 * GenerateCopyFilePaths 02085 * 02086 * Function: 02087 * This function is called by the Windows NT spooler to find the 02088 * directories from which color profiles should be picked up and copied 02089 * to. This is useful if the locations are version or processor 02090 * architecture dependent. As color profiles depend on neither, we don't 02091 * have to do anything, but have to export this function. 02092 * 02093 * Arguments: 02094 * don't care 02095 * 02096 * Returns: 02097 * ERROR_SUCCESS if successful, error code otherwise 02098 * 02099 ******************************************************************************/ 02100 02101 DWORD WINAPI 02102 GenerateCopyFilePaths( 02103 LPCWSTR pszPrinterName, 02104 LPCWSTR pszDirectory, 02105 LPBYTE pSplClientInfo, 02106 DWORD dwLevel, 02107 LPWSTR pszSourceDir, 02108 LPDWORD pcchSourceDirSize, 02109 LPWSTR pszTargetDir, 02110 LPDWORD pcchTargetDirSize, 02111 DWORD dwFlags 02112 ) 02113 { 02114 TRACEAPI((__TEXT("GenerateCopyFilePaths\n"))); 02115 return ERROR_SUCCESS; 02116 } 02117 02118 02119 /****************************************************************************** 02120 * 02121 * SpoolerCopyFileEvent 02122 * 02123 * Function: 02124 * This function is called by the Windows NT spooler when one of the 02125 * following events happens: 02126 * 1. When someone does a SetPrinterDataEx of the CopyFiles section 02127 * 2. When a printer connection is made 02128 * 3. When files for a printer connection get updated 02129 * 4. When a printer is deleted 02130 * 02131 * Arguments: 02132 * pszPrinterName - friendly name of printer 02133 * pszKey - "CopyFiles\ICM" for us 02134 * dwCopyFileEvent - reason for calling 02135 * 02136 * Returns: 02137 * TRUE if successful, NULL otherwise 02138 * 02139 ******************************************************************************/ 02140 02141 BOOL WINAPI 02142 SpoolerCopyFileEvent( 02143 LPWSTR pszPrinterName, 02144 LPWSTR pszKey, 02145 DWORD dwCopyFileEvent 02146 ) 02147 { 02148 PTSTR pProfileList, pTemp, pBuffer; 02149 DWORD dwSize; 02150 BOOL bRc = FALSE; 02151 TCHAR szPath[MAX_PATH]; 02152 02153 TRACEAPI((__TEXT("SpoolerCopyFileEvent\n"))); 02154 02155 switch (dwCopyFileEvent) 02156 { 02157 case COPYFILE_EVENT_SET_PRINTER_DATAEX: 02158 02159 // 02160 // When associating profiles with printer connections, we copy 02161 // the files to the remote machine, and then do a SePrinterDataEx. 02162 // This causes this event to be generated on the remote machine. We 02163 // use this to install the profile. This is not needed after we make 02164 // our APIs remotable 02165 // 02166 // Fall thru' 02167 // 02168 02169 TERSE((__TEXT("SetPrinterDataEx event\n"))); 02170 02171 case COPYFILE_EVENT_ADD_PRINTER_CONNECTION: 02172 case COPYFILE_EVENT_FILES_CHANGED: 02173 02174 // 02175 // This event is generated when a printer connection is added or 02176 // associated profiles have changed. Install all the profiles in 02177 // the client machine now. 02178 // 02179 02180 #ifdef DBG 02181 if (dwCopyFileEvent == COPYFILE_EVENT_ADD_PRINTER_CONNECTION) 02182 { 02183 WARNING((__TEXT("AddPrinterConnection Event\n"))); 02184 } 02185 else if (dwCopyFileEvent == COPYFILE_EVENT_FILES_CHANGED) 02186 { 02187 WARNING((__TEXT("FilesChanged Event\n"))); 02188 } 02189 #endif 02190 02191 dwSize = 0; 02192 if (GetDeviceData((PTSTR)pszPrinterName, CLASS_PRINTER, DEVICE_PROFILE_DATA, 02193 (PVOID *)&pProfileList, &dwSize, TRUE)) 02194 { 02195 dwSize = sizeof(szPath); 02196 if (InternalGetColorDirectory(NULL, szPath, &dwSize)) 02197 { 02198 lstrcat(szPath, gszBackslash); 02199 pBuffer = szPath + lstrlen(szPath); 02200 pTemp = pProfileList; 02201 while (*pTemp) 02202 { 02203 lstrcpy(pBuffer, pTemp); 02204 InstallColorProfile(NULL, szPath); 02205 pTemp += lstrlen(pTemp) + 1; 02206 } 02207 } 02208 02209 MemFree(pProfileList); 02210 } 02211 break; 02212 02213 case COPYFILE_EVENT_DELETE_PRINTER: 02214 02215 // 02216 // This event is generated when a printer is about to be deleted. 02217 // Get all profiles associated with the printer and disassociate 02218 // them now. 02219 // 02220 02221 TERSE((__TEXT("DeletePrinterDataEx Event\n"))); 02222 02223 dwSize = 0; 02224 if (GetDeviceData((PTSTR)pszPrinterName, CLASS_PRINTER, DEVICE_PROFILE_DATA, 02225 (PVOID *)&pProfileList, &dwSize, TRUE)) 02226 { 02227 pTemp = pProfileList; 02228 while (*pTemp) 02229 { 02230 DisassociateColorProfileFromDevice(NULL, pTemp, (PTSTR)pszPrinterName); 02231 pTemp += lstrlen(pTemp) + 1; 02232 } 02233 02234 MemFree(pProfileList); 02235 } 02236 break; 02237 } 02238 02239 bRc = TRUE; 02240 02241 return bRc; 02242 } 02243 02244 02245 /*****************************************************************************/ 02246 /***************************** Internal Functions ****************************/ 02247 /*****************************************************************************/ 02248 02249 /****************************************************************************** 02250 * 02251 * InternalGetColorDirectory 02252 * 02253 * Function: 02254 * This function returns the path to the color directory on the machine 02255 * specified. 02256 * associations should be removed before calling this function. It also 02257 * optionally deletes the file if the profile was successfully 02258 * uninstalled. 02259 * 02260 * Arguments: 02261 * pMachineName - name identifying machine on which the path 02262 * to the color directory is requested 02263 * pBuffer - pointer to buffer to receive pathname 02264 * pdwSize - pointer to size of buffer. On return it has size of 02265 * buffer needed if failure, and used on success 02266 * 02267 * Returns: 02268 * TRUE if successful, FALSE otherwise 02269 * 02270 ******************************************************************************/ 02271 02272 BOOL 02273 InternalGetColorDirectory( 02274 LPCTSTR pMachineName, 02275 PTSTR pBuffer, 02276 DWORD *pdwSize 02277 ) 02278 { 02279 DWORD dwBufLen = *pdwSize; // size supplied 02280 BOOL rc = FALSE; // return value 02281 02282 // 02283 // Get the printer driver directory 02284 // 02285 02286 #if !defined(_WIN95_) 02287 02288 DWORD dwNeeded; // size needed 02289 02290 if (!pBuffer && pdwSize && !IsBadWritePtr(pdwSize, sizeof(DWORD))) 02291 { 02292 *pdwSize = 0; 02293 } 02294 02295 if (GetPrinterDriverDirectory((PTSTR)pMachineName, NULL, 1, (PBYTE)pBuffer, 02296 *pdwSize, pdwSize)) 02297 { 02298 // 02299 // This API returns the print$ path appended with the environment 02300 // directory. e.g. c:\winnt\system32\spool\drivers\w32x86. So we need 02301 // to go back one step and then append the color directory. 02302 // 02303 02304 PWSTR pDriverDir; 02305 02306 pDriverDir = GetFilenameFromPath(pBuffer); 02307 02308 ASSERT (pDriverDir != NULL); 02309 02310 *pdwSize -= lstrlen(pDriverDir) * sizeof(WCHAR); 02311 02312 *pDriverDir = '\0'; 02313 02314 // 02315 // Calculate size of buffer needed to append color directory 02316 // 02317 02318 dwNeeded = *pdwSize + lstrlen(gszColorDir) * sizeof(WCHAR); 02319 if (pBuffer[lstrlen(pBuffer) - 1] != '\\') 02320 { 02321 dwNeeded += sizeof(WCHAR); 02322 } 02323 02324 // 02325 // Update size needed 02326 // 02327 02328 *pdwSize = dwNeeded; 02329 02330 // 02331 // If supplied buffer is big enough, append our stuff 02332 // 02333 02334 if (dwNeeded <= dwBufLen) 02335 { 02336 if (pBuffer[lstrlen(pBuffer) - 1] != '\\') 02337 { 02338 lstrcat(pBuffer, gszBackslash); 02339 } 02340 02341 lstrcat(pBuffer, gszColorDir); 02342 02343 rc = TRUE; 02344 } 02345 else 02346 { 02347 WARNING((__TEXT("Input buffer to GetColorDirectory not big enough\n"))); 02348 SetLastError(ERROR_INSUFFICIENT_BUFFER); 02349 } 02350 } 02351 else if (GetLastError() == ERROR_INVALID_USER_BUFFER) 02352 { 02353 // 02354 // Spooler sets this error if buffer is NULL. Map it to our error 02355 // 02356 02357 SetLastError(ERROR_INSUFFICIENT_BUFFER); 02358 } 02359 else if (GetLastError() == RPC_S_SERVER_UNAVAILABLE) 02360 { 02361 TCHAR achTempPath[MAX_PATH * 2]; // Make sure enough path space. 02362 02363 // 02364 // Spooler service is not running. Use hardcoded path 02365 // 02366 02367 if (GetSystemDirectory(achTempPath,MAX_PATH) != 0) 02368 { 02369 _tcscat(achTempPath,TEXT("\\spool\\drivers\\color")); 02370 02371 *pdwSize = wcslen(achTempPath) + 1; 02372 02373 if (pBuffer && (*pdwSize <= dwBufLen)) 02374 { 02375 _tcscpy(pBuffer,achTempPath); 02376 02377 rc = TRUE; 02378 } 02379 else 02380 { 02381 WARNING((__TEXT("Input buffer to GetColorDirectory not big enough\n"))); 02382 SetLastError(ERROR_INSUFFICIENT_BUFFER); 02383 } 02384 } 02385 } 02386 02387 #else 02388 02389 HKEY hkSetup; // registry key 02390 DWORD dwErr; // error code 02391 02392 // 02393 // Only local color directory query is allowed in Memphis 02394 // 02395 02396 if (pMachineName) 02397 { 02398 WARNING((__TEXT("Remote color directory query, failing...\n"))); 02399 SetLastError(ERROR_INVALID_PARAMETER); 02400 return FALSE; 02401 } 02402 02403 // 02404 // On Memphis, get this information from the setup section in the registry. 02405 // The reason we don't call GetPrinterDriverDirectory is that when we call 02406 // this function from GDI 16, it tries to go back into 16-bit mode and 02407 // deadlocks on the Win16 lock. 02408 // 02409 02410 if ((dwErr = RegOpenKey(HKEY_LOCAL_MACHINE, gszSetupPath, &hkSetup)) == ERROR_SUCCESS) 02411 { 02412 if ((dwErr = RegQueryValueEx(hkSetup, gszICMDir, 0, NULL, (PBYTE)pBuffer, 02413 pdwSize)) == ERROR_SUCCESS) 02414 { 02415 rc = TRUE; 02416 } 02417 RegCloseKey(hkSetup); 02418 } 02419 02420 if (!rc) 02421 { 02422 // 02423 // Make error codes consistent 02424 // 02425 02426 if (dwErr == ERROR_MORE_DATA) 02427 { 02428 dwErr = ERROR_INSUFFICIENT_BUFFER; 02429 } 02430 02431 WARNING((__TEXT("Error getting color directory: %d\n"), dwErr)); 02432 SetLastError(dwErr); 02433 } 02434 02435 // 02436 // RegQueryValueEx returns TRUE even if the calling buffer is NULL. Our API 02437 // is supposed to return FALSE. Check for this case. 02438 // 02439 02440 if (pBuffer == NULL && rc) 02441 { 02442 SetLastError(ERROR_INSUFFICIENT_BUFFER); 02443 rc = FALSE; 02444 } 02445 02446 #endif // !defined(_WIN95_) 02447 02448 return rc; 02449 } 02450 02451 02452 /****************************************************************************** 02453 * 02454 * InternalInstallColorProfile 02455 * 02456 * Function: 02457 * This function installs a given color profile on a a given machine. 02458 * 02459 * Arguments: 02460 * pMachineName - name identifying machine on which the profile 02461 * should be uninstalled. NULL implies local 02462 * pProfileName - Fully qualified pathname of profile to uninstall 02463 * bDelete - TRUE if profile should be deleted in disk 02464 * 02465 * Returns: 02466 * TRUE if successful, NULL otherwise 02467 * 02468 * Warning: 02469 * Currently only local install is supported, so pMachineName should 02470 * be NULL. 02471 * 02472 ******************************************************************************/ 02473 02474 BOOL 02475 InternalInstallColorProfile( 02476 LPCTSTR pMachineName, 02477 LPCTSTR pProfileName 02478 ) 02479 { 02480 PROFILEHEADER header; // profile header 02481 REGDATA regData; // for storing registry data about profile 02482 HKEY hkICM = NULL; // key to ICM branch in registry 02483 HKEY hkDevice = NULL; // key to ICM device branch in registry 02484 DWORD dwSize; // size of registry data for profile 02485 DWORD dwErr; // error code 02486 BOOL rc = FALSE; // return code 02487 PTSTR pFilename; // profile name without path 02488 TCHAR szDest[MAX_PATH]; // destination path for profile 02489 TCHAR szClass[5]; // profile class 02490 BOOL FileExist; // profile already in directory? 02491 BOOL RegExist; // profile in registry? 02492 02493 // 02494 // Validate parameters 02495 // 02496 02497 if (!pProfileName) 02498 { 02499 WARNING((__TEXT("Invalid parameter to InstallColorProfile\n"))); 02500 SetLastError(ERROR_INVALID_PARAMETER); 02501 return FALSE; 02502 } 02503 02504 // 02505 // Only local installs are allowed now 02506 // 02507 02508 if (pMachineName) 02509 { 02510 WARNING((__TEXT("Remote install attempted, failing...\n"))); 02511 SetLastError(ERROR_INVALID_PARAMETER); 02512 return FALSE; 02513 } 02514 02515 // 02516 // Get rid of the directory path and get a pointer to the filename 02517 // 02518 02519 pFilename = GetFilenameFromPath((PTSTR)pProfileName); 02520 if (! pFilename) 02521 { 02522 WARNING((__TEXT("Could not parse file name from profile path %s\n"), pProfileName)); 02523 SetLastError(ERROR_INVALID_PARAMETER); 02524 goto EndInstallColorProfile; 02525 } 02526 02527 // 02528 // Get the profile class in the form of a string 02529 // 02530 02531 if (! GetProfileClassString(pProfileName, szClass, &header)) 02532 { 02533 WARNING((__TEXT("Installing invalid profile %s\n"), pProfileName)); 02534 SetLastError(ERROR_INVALID_PROFILE); 02535 goto EndInstallColorProfile; 02536 } 02537 02538 // 02539 // Open the registry path where profiles are kept 02540 // 02541 02542 if (((dwErr = RegCreateKey(HKEY_LOCAL_MACHINE, gszICMRegPath, &hkICM)) != ERROR_SUCCESS) || 02543 ((dwErr = RegCreateKey(hkICM, szClass, &hkDevice)) != ERROR_SUCCESS)) 02544 { 02545 WARNING((__TEXT("Cannot open ICM\\device branch of registry: %d\n"), dwErr)); 02546 SetLastError(dwErr); 02547 goto EndInstallColorProfile; 02548 } 02549 02550 02551 // 02552 // If registry data exists && the profile is in the directory, then the profile is already installed, 02553 // in which case, return success. Otherwise, copy profile to color 02554 // directory (if it's not already there) and add it to the registry (if it's not already there). 02555 // 02556 02557 dwSize = sizeof(szDest); 02558 02559 // 02560 // Copy the file to the color directory 02561 // 02562 02563 if (! InternalGetColorDirectory(NULL, szDest, &dwSize)) 02564 { 02565 WARNING((__TEXT("Could not get color directory\n"))); 02566 goto EndInstallColorProfile; 02567 } 02568 02569 // 02570 // This creates the directory if it doesn't exist, doesn't do anything 02571 // if it already exists 02572 // 02573 02574 CreateDirectory(szDest, NULL); 02575 02576 if (szDest[lstrlen(szDest) - 1] != '\\') 02577 { 02578 lstrcat(szDest, gszBackslash); 02579 } 02580 lstrcat(szDest, pFilename); 02581 02582 // 02583 // If the profile is already in the color directory, do not attempt 02584 // to copy it again; it will fail. 02585 // 02586 02587 dwSize = sizeof(REGDATA); 02588 02589 FileExist = GetFileAttributes(szDest) != (DWORD)-1; 02590 RegExist = RegQueryValueEx(hkDevice, pFilename, 0, NULL, (PBYTE)&regData, &dwSize) == ERROR_SUCCESS; 02591 02592 // 02593 // If the file does exist, short circuit the CopyFile 02594 // and go on to add it into the registry. 02595 // 02596 02597 if (!FileExist && !CopyFile(pProfileName, szDest, FALSE)) 02598 { 02599 WARNING((__TEXT("Could not copy profile %s to color directory\n"), pProfileName)); 02600 goto EndInstallColorProfile; 02601 } 02602 02603 // 02604 // Add profile to the registry 02605 // 02606 02607 if(!RegExist) 02608 { 02609 regData.dwRefCount = 0; 02610 regData.dwManuID = FIX_ENDIAN(header.phManufacturer); 02611 regData.dwModelID = FIX_ENDIAN(header.phModel); 02612 if ((dwErr = RegSetValueEx(hkDevice, pFilename, 0, REG_BINARY, 02613 (PBYTE)&regData, sizeof(REGDATA))) != ERROR_SUCCESS) 02614 { 02615 WARNING((__TEXT("Could not set registry data to install profile %s: %d\n"), pFilename, dwErr)); 02616 SetLastError(dwErr); 02617 goto EndInstallColorProfile; 02618 } 02619 } 02620 02621 rc = TRUE; // Everything went well! 02622 02623 EndInstallColorProfile: 02624 if (hkICM) 02625 { 02626 RegCloseKey(hkICM); 02627 } 02628 if (hkDevice) 02629 { 02630 RegCloseKey(hkDevice); 02631 } 02632 02633 return rc; 02634 } 02635 02636 02637 /****************************************************************************** 02638 * 02639 * InternalUninstallColorProfile 02640 * 02641 * Function: 02642 * This function uninstalls a given color profile on a a given machine. 02643 * It fails if the color profile is associated with any device, so all 02644 * associations should be removed before calling this function. It also 02645 * optionally deletes the file if the profile was successfully 02646 * uninstalled. 02647 * 02648 * Arguments: 02649 * pMachineName - name identifying machine on which the profile 02650 * should be uninstalled. NULL implies local 02651 * pProfileName - pointer to profile to uninstall 02652 * bDelete - TRUE if profile should be deleted in disk 02653 * 02654 * Returns: 02655 * TRUE if successful, NULL otherwise 02656 * 02657 * Warning: 02658 * Currently only local uninstall is supported, so pMachineName should 02659 * be NULL. 02660 * 02661 ******************************************************************************/ 02662 02663 BOOL 02664 InternalUninstallColorProfile( 02665 LPCTSTR pMachineName, 02666 LPCTSTR pProfileName, 02667 BOOL bDelete 02668 ) 02669 { 02670 REGDATA regData; // for storing registry data about profile 02671 HKEY hkICM = NULL; // key to ICM branch in registry 02672 HKEY hkDevice = NULL; // key to ICM device branch in registry 02673 DWORD dwSize; // size of registry data for profile 02674 DWORD dwErr; // error code 02675 BOOL rc = FALSE; // return code 02676 PTSTR pFilename; // profile name without path 02677 TCHAR szColorPath[MAX_PATH]; // full path name of profile 02678 TCHAR szClass[5]; // profile class 02679 02680 // 02681 // Validate parameters 02682 // 02683 02684 if (!pProfileName) 02685 { 02686 WARNING((__TEXT("Invalid parameter to UninstallColorProfile\n"))); 02687 SetLastError(ERROR_INVALID_PARAMETER); 02688 return FALSE; 02689 } 02690 02691 // 02692 // Only local installs are allowed now 02693 // 02694 02695 if (pMachineName != NULL) 02696 { 02697 WARNING((__TEXT("Remote uninstall attempted, failing...\n"))); 02698 SetLastError(ERROR_NOT_SUPPORTED); 02699 return FALSE; 02700 } 02701 02702 // 02703 // Get rid of the directory path and get a pointer to the filename 02704 // 02705 02706 pFilename = GetFilenameFromPath((PTSTR)pProfileName); 02707 if (! pFilename) 02708 { 02709 WARNING((__TEXT("Could not parse file name from profile path\n"), pProfileName)); 02710 SetLastError(ERROR_INVALID_PARAMETER); 02711 goto EndUninstallColorProfile; 02712 } 02713 02714 // 02715 // Create a fully qualified path name 02716 // 02717 02718 dwSize = sizeof(szColorPath); 02719 if (! InternalGetColorDirectory(NULL, szColorPath, &dwSize)) 02720 { 02721 WARNING((__TEXT("Could not get color directory\n"))); 02722 goto EndUninstallColorProfile; 02723 } 02724 02725 if (szColorPath[lstrlen(szColorPath) - 1] != '\\') 02726 { 02727 lstrcat(szColorPath, gszBackslash); 02728 } 02729 lstrcat(szColorPath, pFilename); 02730 02731 // 02732 // Get the profile class in the form of a string 02733 // 02734 02735 if (! GetProfileClassString(szColorPath, szClass, NULL)) 02736 { 02737 WARNING((__TEXT("Installing invalid profile\n"))); 02738 SetLastError(ERROR_INVALID_PROFILE); 02739 goto EndUninstallColorProfile; 02740 } 02741 02742 // 02743 // Open the registry path where profiles are kept 02744 // 02745 02746 if (((dwErr = RegOpenKey(HKEY_LOCAL_MACHINE, gszICMRegPath, &hkICM)) != ERROR_SUCCESS) || 02747 ((dwErr = RegOpenKey(hkICM, szClass, &hkDevice)) != ERROR_SUCCESS)) 02748 { 02749 WARNING((__TEXT("Cannot open ICM\\device branch of registry: %d\n"), dwErr)); 02750 SetLastError(dwErr); 02751 goto EndUninstallColorProfile; 02752 } 02753 02754 // 02755 // Check if reference count is zero and remove value from registry 02756 // 02757 02758 dwSize = sizeof(REGDATA); 02759 if ((dwErr = RegQueryValueEx(hkDevice, pFilename, 0, NULL, (PBYTE)&regData, 02760 &dwSize)) != ERROR_SUCCESS) 02761 { 02762 WARNING((__TEXT("Trying to uninstall a profile that is not installed %s: %d\n"), pFilename, dwErr)); 02763 SetLastError(dwErr); 02764 goto EndUninstallColorProfile; 02765 } 02766 02767 if (regData.dwRefCount != 0) 02768 { 02769 WARNING((__TEXT("Trying to uninstall profile %s whose refcount is %d\n"), 02770 pFilename, regData.dwRefCount)); 02771 goto EndUninstallColorProfile; 02772 } 02773 02774 if ((dwErr = RegDeleteValue(hkDevice, pFilename)) != ERROR_SUCCESS) 02775 { 02776 WARNING((__TEXT("Error deleting profile %s from registry: %d\n"), pFilename, dwErr)); 02777 SetLastError(dwErr); 02778 goto EndUninstallColorProfile; 02779 } 02780 02781 // 02782 // Remove profile from the registry 02783 // 02784 02785 if (bDelete) 02786 { 02787 // 02788 // Delete profile from the color directory 02789 // 02790 02791 if (! DeleteFile(szColorPath)) 02792 { 02793 WARNING((__TEXT("Error deleting profile %s: %d\n"), szColorPath, GetLastError())); 02794 goto EndUninstallColorProfile; 02795 } 02796 } 02797 02798 rc = TRUE; // Everything went well! 02799 02800 EndUninstallColorProfile: 02801 if (hkICM) 02802 { 02803 RegCloseKey(hkICM); 02804 } 02805 if (hkDevice) 02806 { 02807 RegCloseKey(hkDevice); 02808 } 02809 02810 return rc; 02811 } 02812 02813 02814 /****************************************************************************** 02815 * 02816 * InternalAssociateColorProfileWithDevice 02817 * 02818 * Function: 02819 * This function associates a color profile on a a given machine with a 02820 * particular device. It fails if the color profile is not installed on 02821 * the machine. It increases the usage reference count of the profile. 02822 * 02823 * Arguments: 02824 * pMachineName - name identifying machine. NULL implies local 02825 * pProfileName - pointer to profile to associate 02826 * pDeviceName - pointer to device name 02827 * 02828 * Returns: 02829 * TRUE if successful, NULL otherwise 02830 * 02831 * Warning: 02832 * Currently only local association is supported, so pMachineName should 02833 * be NULL. 02834 * 02835 ******************************************************************************/ 02836 02837 BOOL 02838 InternalAssociateColorProfileWithDevice( 02839 LPCTSTR pMachineName, 02840 LPCTSTR pProfileName, 02841 LPCTSTR pDeviceName 02842 ) 02843 { 02844 PROFILEHEADER header; // profile header 02845 REGDATA regData; // for storing registry data about profile 02846 HKEY hkICM = NULL; // key to ICM branch in registry 02847 HKEY hkDevice = NULL; // key to ICM device branch in registry 02848 DWORD dwSize; // size of registry data 02849 DWORD dwNewSize; // new size of device registry data 02850 DWORD dwErr; // error code 02851 BOOL rc = FALSE; // return code 02852 PTSTR pFilename; // profile name without path 02853 PTSTR pProfileList = NULL; // list of associated profiles 02854 TCHAR szColorPath[MAX_PATH]; // full path name of profile 02855 TCHAR szClass[5]; // profile class 02856 BOOL bFirstProfile = FALSE; // First profile to be associated for device 02857 DWORD dwDeviceClass; // device class 02858 02859 // 02860 // Validate parameters 02861 // 02862 02863 if (! pProfileName || 02864 ! pDeviceName) 02865 { 02866 WARNING((__TEXT("Invalid parameter to AssociateColorProfileWithDevice\n"))); 02867 SetLastError(ERROR_INVALID_PARAMETER); 02868 return FALSE; 02869 } 02870 02871 // 02872 // Only local associations are allowed now 02873 // 02874 02875 if (pMachineName != NULL) 02876 { 02877 WARNING((__TEXT("Remote profile association attempted, failing...\n"))); 02878 SetLastError(ERROR_NOT_SUPPORTED); 02879 return FALSE; 02880 } 02881 02882 // 02883 // Get rid of the directory path and get a pointer to the filename 02884 // 02885 02886 pFilename = GetFilenameFromPath((PTSTR)pProfileName); 02887 if (! pFilename) 02888 { 02889 WARNING((__TEXT("Could not parse file name from profile path %s\n"), pProfileName)); 02890 SetLastError(ERROR_INVALID_PARAMETER); 02891 goto EndAssociateProfileWithDevice; 02892 } 02893 02894 // 02895 // Create a fully qualified path name 02896 // 02897 02898 dwSize = sizeof(szColorPath); 02899 if (! InternalGetColorDirectory(NULL, szColorPath, &dwSize)) 02900 { 02901 WARNING((__TEXT("Could not get color directory\n"))); 02902 goto EndAssociateProfileWithDevice; 02903 } 02904 02905 if (szColorPath[lstrlen(szColorPath) - 1] != '\\') 02906 { 02907 lstrcat(szColorPath, gszBackslash); 02908 } 02909 lstrcat(szColorPath, pFilename); 02910 02911 // 02912 // Get the profile class in the form of a string 02913 // 02914 02915 if (! GetProfileClassString(szColorPath, szClass, &header)) 02916 { 02917 WARNING((__TEXT("Installing invalid profile %s\n"), szColorPath)); 02918 SetLastError(ERROR_INVALID_PROFILE); 02919 goto EndAssociateProfileWithDevice; 02920 } 02921 02922 // 02923 // Open the registry path where profiles are kept 02924 // 02925 02926 if (((dwErr = RegOpenKey(HKEY_LOCAL_MACHINE, gszICMRegPath, &hkICM)) != ERROR_SUCCESS) || 02927 ((dwErr = RegOpenKey(hkICM, szClass, &hkDevice)) != ERROR_SUCCESS)) 02928 { 02929 WARNING((__TEXT("Cannot open ICM\\device branch of registry: %d\n"), dwErr)); 02930 SetLastError(dwErr); 02931 goto EndAssociateProfileWithDevice; 02932 } 02933 02934 // 02935 // Check if profile is installed 02936 // 02937 02938 dwSize = sizeof(REGDATA); 02939 if ((dwErr = RegQueryValueEx(hkDevice, pFilename, 0, NULL, (PBYTE)&regData, 02940 &dwSize)) != ERROR_SUCCESS) 02941 { 02942 WARNING((__TEXT("Trying to associate a profile that is not installed %s: %d\n"), pFilename, dwErr)); 02943 SetLastError(dwErr); 02944 goto EndAssociateProfileWithDevice; 02945 } 02946 02947 // 02948 // Treat CLASS_MONITOR as CLASS_COLORSPACE. 02949 // 02950 if ((dwDeviceClass = header.phClass) == CLASS_MONITOR) 02951 { 02952 // 02953 // since CLASS_MONTOR profile can be associated any device class. 02954 // 02955 dwDeviceClass = CLASS_COLORSPACE; 02956 } 02957 02958 // 02959 // Read in the list of profiles associated with the device 02960 // 02961 02962 dwSize = 0; 02963 if (! GetDeviceData(pDeviceName, dwDeviceClass, DEVICE_PROFILE_DATA, 02964 (PVOID *)&pProfileList, &dwSize, TRUE)) 02965 { 02966 pProfileList = NULL; // no data found 02967 } 02968 02969 // 02970 // If the profile is already associated with the device, return success. 02971 // Do not check if we didn't get a profile list 02972 // 02973 02974 if (pProfileList && 02975 IsStringInMultiSz(pProfileList, pFilename) == TRUE) 02976 { 02977 rc = TRUE; 02978 goto EndAssociateProfileWithDevice; 02979 } 02980 02981 if (dwSize <= sizeof(TCHAR)) 02982 { 02983 bFirstProfile = TRUE; 02984 } 02985 02986 // 02987 // Add new profile to the list of profiles, and double NULL 02988 // terminate the MULTI_SZ string. 02989 // 02990 02991 if (dwSize > 0) 02992 { 02993 // 02994 // Use a temporary pointer, so that if MemReAlloc fails, we do 02995 // not have a memory leak - the original pointer needs to be freed 02996 // 02997 02998 PTSTR pTemp; 02999 03000 dwNewSize = dwSize + (lstrlen(pFilename) + 1) * sizeof(TCHAR); 03001 03002 pTemp = MemReAlloc(pProfileList, dwNewSize); 03003 if (! pTemp) 03004 { 03005 WARNING((__TEXT("Error reallocating pProfileList\n"))); 03006 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 03007 goto EndAssociateProfileWithDevice; 03008 } 03009 else 03010 pProfileList = pTemp; 03011 } 03012 else 03013 { 03014 // 03015 // Allocate extra character for double NULL termination. Setting 03016 // dwSize to 1 accomplishes this and lets the lstrcpy below 03017 // to work correctly. 03018 // 03019 03020 dwSize = sizeof(TCHAR); // extra char for double NULL termination 03021 03022 dwNewSize = dwSize + (lstrlen(pFilename) + 1) * sizeof(TCHAR); 03023 pProfileList = MemAlloc(dwNewSize); 03024 if (! pProfileList) 03025 { 03026 WARNING((__TEXT("Error allocating pProfileList\n"))); 03027 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 03028 goto EndAssociateProfileWithDevice; 03029 } 03030 } 03031 { 03032 PTSTR pPtr; // temporary pointer 03033 03034 pPtr = (PTSTR)((PBYTE)pProfileList + dwSize - sizeof(TCHAR)); 03035 lstrcpy(pPtr, pFilename); 03036 pPtr = (PTSTR)((PBYTE)pProfileList + dwNewSize - sizeof(TCHAR)); 03037 *pPtr = '\0'; // double NULL terminate 03038 } 03039 03040 // 03041 // Set the device data 03042 // 03043 03044 if (! SetDeviceData(pDeviceName, dwDeviceClass, DEVICE_PROFILE_DATA, 03045 pProfileList, dwNewSize)) 03046 { 03047 WARNING((__TEXT("Error setting device profile data for %s\n"), pDeviceName)); 03048 goto EndAssociateProfileWithDevice; 03049 } 03050 03051 // 03052 // Increment usage count and set it 03053 // 03054 03055 regData.dwRefCount++; 03056 if ((dwErr = RegSetValueEx(hkDevice, pFilename, 0, REG_BINARY, 03057 (PBYTE)&regData, sizeof(REGDATA))) != ERROR_SUCCESS) 03058 { 03059 ERR((__TEXT("Could not set registry data for profile %s: %d\n"), pFilename, dwErr)); 03060 SetLastError(dwErr); 03061 goto EndAssociateProfileWithDevice; 03062 } 03063 03064 #if !defined(_WIN95_) 03065 03066 if (bFirstProfile) 03067 { 03068 ChangeICMSetting(pMachineName, pDeviceName, ICM_ON); 03069 } 03070 03071 #endif 03072 03073 rc = TRUE; // Everything went well! 03074 03075 EndAssociateProfileWithDevice: 03076 if (hkICM) 03077 { 03078 RegCloseKey(hkICM); 03079 } 03080 if (hkDevice) 03081 { 03082 RegCloseKey(hkDevice); 03083 } 03084 if (pProfileList) 03085 { 03086 MemFree(pProfileList); 03087 } 03088 03089 return rc; 03090 } 03091 03092 03093 /****************************************************************************** 03094 * 03095 * InternalDisassociateColorProfileFromDevice 03096 * 03097 * Function: 03098 * This function disassociates a color profile on a a given machine from 03099 * a particular device. It fails if the color profile is not installed 03100 * on the machine and associated with the device. It decreases the usage 03101 * reference count of the profile. 03102 * 03103 * Arguments: 03104 * pMachineName - name identifying machine. NULL implies local 03105 * pProfileName - pointer to profile to disassociate 03106 * pDeviceName - pointer to device name 03107 * 03108 * Returns: 03109 * TRUE if successful, NULL otherwise 03110 * 03111 * Warning: 03112 * Currently only local disassociation is supported, so pMachineName 03113 * should be NULL. 03114 * 03115 ******************************************************************************/ 03116 03117 BOOL 03118 InternalDisassociateColorProfileFromDevice( 03119 LPCTSTR pMachineName, 03120 LPCTSTR pProfileName, 03121 LPCTSTR pDeviceName 03122 ) 03123 { 03124 PROFILEHEADER header; // profile header 03125 REGDATA regData; // for storing registry data about profile 03126 HKEY hkICM = NULL; // key to ICM branch in registry 03127 HKEY hkDevice = NULL; // key to ICM device branch in registry 03128 DWORD dwSize; // size of registry data 03129 DWORD dwNewSize; // new size of device registry data 03130 DWORD dwErr; // error code 03131 BOOL rc = FALSE; // return code 03132 PTSTR pFilename; // profile name without path 03133 PTSTR pProfileList = NULL; // list of associated profiles 03134 TCHAR szColorPath[MAX_PATH]; // full path name of profile 03135 TCHAR szClass[5]; // profile class 03136 BOOL bLastProfile = FALSE; // whether last profile is being removed 03137 DWORD dwDeviceClass; // device class 03138 03139 // 03140 // Validate parameters 03141 // 03142 03143 if (! pProfileName || 03144 ! pDeviceName) 03145 { 03146 WARNING((__TEXT("Invalid parameter to DisassociateColorProfileFromDevice\n"))); 03147 SetLastError(ERROR_INVALID_PARAMETER); 03148 return FALSE; 03149 } 03150 03151 // 03152 // Only local associations are allowed now 03153 // 03154 03155 if (pMachineName != NULL) 03156 { 03157 WARNING((__TEXT("Remote profile disassociation attempted, failing...\n"))); 03158 SetLastError(ERROR_NOT_SUPPORTED); 03159 return FALSE; 03160 } 03161 03162 // 03163 // Get rid of the directory path and get a pointer to the filename 03164 // 03165 03166 pFilename = GetFilenameFromPath((PTSTR)pProfileName); 03167 if (! pFilename) 03168 { 03169 WARNING((__TEXT("Could not parse file name from profile path %s\n"), pProfileName)); 03170 SetLastError(ERROR_INVALID_PARAMETER); 03171 goto EndDisassociateProfileWithDevice; 03172 } 03173 03174 // 03175 // Create a fully qualified path name 03176 // 03177 03178 dwSize = sizeof(szColorPath); 03179 if (! InternalGetColorDirectory(NULL, szColorPath, &dwSize)) 03180 { 03181 WARNING((__TEXT("Could not get color directory\n"))); 03182 goto EndDisassociateProfileWithDevice; 03183 } 03184 03185 if (szColorPath[lstrlen(szColorPath) - 1] != '\\') 03186 { 03187 lstrcat(szColorPath, gszBackslash); 03188 } 03189 lstrcat(szColorPath, pFilename); 03190 03191 // 03192 // Get the profile class in the form of a string 03193 // 03194 03195 if (! GetProfileClassString(szColorPath, szClass, &header)) 03196 { 03197 WARNING((__TEXT("Installing invalid profile %s\n"), szColorPath)); 03198 SetLastError(ERROR_INVALID_PROFILE); 03199 goto EndDisassociateProfileWithDevice; 03200 } 03201 03202 // 03203 // Open the registry path where profiles are kept 03204 // 03205 03206 if (((dwErr = RegOpenKey(HKEY_LOCAL_MACHINE, gszICMRegPath, &hkICM)) != ERROR_SUCCESS) || 03207 ((dwErr = RegOpenKey(hkICM, szClass, &hkDevice)) != ERROR_SUCCESS)) 03208 { 03209 WARNING((__TEXT("Cannot open ICM\\device branch of registry: %d\n"), dwErr)); 03210 SetLastError(dwErr); 03211 goto EndDisassociateProfileWithDevice; 03212 } 03213 03214 // 03215 // Check if profile is installed 03216 // 03217 03218 dwSize = sizeof(REGDATA); 03219 if ((dwErr = RegQueryValueEx(hkDevice, pFilename, 0, NULL, (PBYTE)&regData, 03220 &dwSize)) != ERROR_SUCCESS) 03221 { 03222 WARNING((__TEXT("Trying to disassociate a profile that is not installed %s: %d\n"), pFilename, dwErr)); 03223 SetLastError(dwErr); 03224 goto EndDisassociateProfileWithDevice; 03225 } 03226 03227 // 03228 // Treat CLASS_MONITOR as CLASS_COLORSPACE. 03229 // 03230 if ((dwDeviceClass = header.phClass) == CLASS_MONITOR) 03231 { 03232 // 03233 // since CLASS_MONTOR profile can be associated any device class. 03234 // 03235 dwDeviceClass = CLASS_COLORSPACE; 03236 } 03237 03238 // 03239 // Read in the list of profiles associated with the device 03240 // 03241 03242 dwSize = 0; 03243 if (! GetDeviceData(pDeviceName, dwDeviceClass, DEVICE_PROFILE_DATA, 03244 (PVOID *)&pProfileList, &dwSize, TRUE)) 03245 { 03246 pProfileList = NULL; // no data found 03247 } 03248 03249 // 03250 // If the profile is not associated with the device, return failure 03251 // 03252 03253 if (! pProfileList || 03254 ! IsStringInMultiSz(pProfileList, pFilename)) 03255 { 03256 WARNING((__TEXT("Trying to disassociate a profile that is not associated %s\n"), pFilename)); 03257 SetLastError(ERROR_PROFILE_NOT_ASSOCIATED_WITH_DEVICE); 03258 goto EndDisassociateProfileWithDevice; 03259 } 03260 03261 // 03262 // Remove profile from the list of profiles, and double NULL 03263 // terminate the MULTI_SZ string. 03264 // 03265 03266 dwNewSize = RemoveStringFromMultiSz(pProfileList, pFilename, dwSize); 03267 03268 // 03269 // Set the device data 03270 // 03271 03272 if (! SetDeviceData(pDeviceName, dwDeviceClass, DEVICE_PROFILE_DATA, 03273 pProfileList, dwNewSize)) 03274 { 03275 WARNING((__TEXT("Error setting device profile data for %s\n"), pDeviceName)); 03276 goto EndDisassociateProfileWithDevice; 03277 } 03278 03279 if (dwNewSize <= sizeof(TCHAR)) 03280 { 03281 bLastProfile = TRUE; 03282 } 03283 03284 // 03285 // Decrement usage count and set it 03286 // 03287 03288 regData.dwRefCount--; 03289 if ((dwErr = RegSetValueEx(hkDevice, pFilename, 0, REG_BINARY, 03290 (PBYTE)&regData, sizeof(REGDATA))) != ERROR_SUCCESS) 03291 { 03292 ERR((__TEXT("Could not set registry data for profile %s: %d\n"), pFilename, dwErr)); 03293 SetLastError(dwErr); 03294 goto EndDisassociateProfileWithDevice; 03295 } 03296 03297 #if !defined(_WIN95_) 03298 03299 if (bLastProfile) 03300 { 03301 ChangeICMSetting(pMachineName, pDeviceName, ICM_OFF); 03302 } 03303 03304 #endif 03305 03306 rc = TRUE; // Everything went well! 03307 03308 EndDisassociateProfileWithDevice: 03309 if (hkICM) 03310 { 03311 RegCloseKey(hkICM); 03312 } 03313 if (hkDevice) 03314 { 03315 RegCloseKey(hkDevice); 03316 } 03317 if (pProfileList) 03318 { 03319 MemFree(pProfileList); 03320 } 03321 03322 return rc; 03323 } 03324 03325 03326 /****************************************************************************** 03327 * 03328 * InternalEnumColorProfiles 03329 * 03330 * Function: 03331 * These functions enumerates color profiles satisfying the given 03332 * enumeration criteria. It searches among all installed profiles, and 03333 * on return fills out a buffer with a series of NULL terminated profile 03334 * filenames double NULL terminated at the end. 03335 * 03336 * Arguments: 03337 * pMachineName - name identifying machine on which the enumeration 03338 * needs to be done 03339 * pEnumRecord - pointer to enumeration criteria 03340 * pBuffer - pointer to buffer to receive result, can be NULL 03341 * pdwSize - pointer to buffer size. On return it is actual number 03342 * of bytes copied/needed. 03343 * pnProfiles - pointer to DWORD. On return, it is number of profiles 03344 * copied to pBuffer. 03345 * 03346 * Returns: 03347 * TRUE if successful, NULL otherwise 03348 * 03349 * Warning: 03350 * Currently only local enumeration is supported, so pMachineName should 03351 * be NULL. 03352 * 03353 ******************************************************************************/ 03354 03355 BOOL 03356 InternalEnumColorProfiles( 03357 LPCTSTR pMachineName, 03358 PENUMTYPE pEnumRecord, 03359 PBYTE pBuffer, 03360 PDWORD pdwSize, 03361 PDWORD pnProfiles 03362 ) 03363 { 03364 REGDATA regData; // for storing registry data about profile 03365 HKEY hkICM = NULL; // key to ICM branch in registry 03366 HKEY hkDevice = NULL; // key to ICM device branch in registry 03367 PTSTR pProfileList = NULL; // list of associated profiles 03368 PTSTR pTempProfileList; // temporary copy of profile list 03369 DWORD dwSize; // size of profile value 03370 DWORD dwDataSize; // size of profile data 03371 DWORD dwInputSize; // incoming size of buffer 03372 DWORD i, j; // counter variables 03373 DWORD dwErr; // error code 03374 BOOL rc = FALSE; // return code 03375 TCHAR szFullPath[MAX_PATH]; // full path of profile to open 03376 PTSTR pProfile; // pointer to profile name in full path 03377 DWORD dwLen; // length of color directory string 03378 DWORD bSkipMatch; // true for skipping exact profile matching 03379 MATCHTYPE match; // Type of profile match 03380 PBYTE pBufferStart; // Start of user given buffer 03381 DWORD dwSizeOfStruct; // size of ENUMTYPE structure 03382 DWORD dwVersion; // ENUMTYPE structure version 03383 03384 // 03385 // Validate parameters 03386 // 03387 03388 if (! pdwSize || 03389 IsBadWritePtr(pdwSize, sizeof(DWORD)) || 03390 (pBuffer && IsBadWritePtr(pBuffer, *pdwSize)) || 03391 (pnProfiles && IsBadWritePtr(pnProfiles, sizeof(DWORD))) || 03392 ! pEnumRecord || 03393 IsBadReadPtr(pEnumRecord, sizeof(DWORD)*3)) // probe until ENUMTYPE.dwFields 03394 { 03395 ParameterError_InternalEnumColorProfiles: 03396 WARNING((__TEXT("Invalid parameter to EnumColorProfiles\n"))); 03397 SetLastError(ERROR_INVALID_PARAMETER); 03398 return FALSE; 03399 } 03400 03401 // 03402 // Check structure size based on its version. 03403 // 03404 03405 dwSizeOfStruct = pEnumRecord->dwSize; 03406 dwVersion = pEnumRecord->dwVersion; 03407 03408 if (dwVersion >= ENUM_TYPE_VERSION) 03409 { 03410 if (dwSizeOfStruct < sizeof(ENUMTYPE)) 03411 goto ParameterError_InternalEnumColorProfiles; 03412 } 03413 else if (dwVersion == 0x0200) 03414 { 03415 if (dwSizeOfStruct < sizeof(ENUMTYPE)-sizeof(DWORD)) 03416 goto ParameterError_InternalEnumColorProfiles; 03417 03418 // 03419 // Version 2 should not have ET_DEVICECLASS bit 03420 // 03421 03422 if (pEnumRecord->dwFields & ET_DEVICECLASS) 03423 goto ParameterError_InternalEnumColorProfiles; 03424 03425 WARNING((__TEXT("Old version ENUMTYPE to InternalEnumColorProfiles\n"))); 03426 } 03427 else 03428 { 03429 goto ParameterError_InternalEnumColorProfiles; 03430 } 03431 03432 if (IsBadReadPtr(pEnumRecord, dwSizeOfStruct)) 03433 { 03434 goto ParameterError_InternalEnumColorProfiles; 03435 } 03436 03437 // 03438 // Only local enumerations are allowed now 03439 // 03440 03441 if (pMachineName != NULL) 03442 { 03443 WARNING((__TEXT("Remote profile enumeration attempted, failing...\n"))); 03444 SetLastError(ERROR_NOT_SUPPORTED); 03445 return FALSE; 03446 } 03447 03448 dwInputSize = *pdwSize; 03449 03450 // 03451 // Get color directory 03452 // 03453 03454 dwLen = sizeof(szFullPath); 03455 if (! InternalGetColorDirectory(NULL, szFullPath, &dwLen)) 03456 { 03457 WARNING((__TEXT("Error getting color directory\n"))); 03458 return FALSE; 03459 } 03460 03461 if (szFullPath[lstrlen(szFullPath) - 1] != '\\') 03462 { 03463 lstrcat(szFullPath, gszBackslash); 03464 } 03465 pProfile = &szFullPath[lstrlen(szFullPath)]; 03466 dwLen = lstrlen(szFullPath) * sizeof(TCHAR); 03467 03468 // 03469 // Initialize return parameters 03470 // 03471 03472 *pdwSize = 0; 03473 if (pnProfiles) 03474 *pnProfiles = 0; 03475 03476 if (pBuffer && dwInputSize >= sizeof(TCHAR)) 03477 { 03478 *((PTSTR)pBuffer) = '\0'; 03479 } 03480 03481 // 03482 // Check if we are looking for the profiles of a particular device or 03483 // not because we enumerate them from different places. 03484 // 03485 03486 if (pEnumRecord->dwFields & ET_DEVICENAME) 03487 { 03488 DWORD *pbSkipMatch = &bSkipMatch; 03489 DWORD dwDeviceClass; 03490 03491 if (! pEnumRecord->pDeviceName) 03492 { 03493 WARNING((__TEXT("Invalid parameter to EnumColorProfiles\n"))); 03494 SetLastError(ERROR_INVALID_PARAMETER); 03495 goto EndEnumerateColorProfiles; 03496 } 03497 03498 // 03499 // Get list of profiles associated with the device. If we don't 03500 // know what device it is, specify ColorSpace, which tries all three 03501 // 03502 03503 if (pEnumRecord->dwFields & ET_DEVICECLASS) 03504 { 03505 dwDeviceClass = pEnumRecord->dwDeviceClass; 03506 } 03507 else 03508 { 03509 dwDeviceClass = CLASS_COLORSPACE; 03510 } 03511 03512 // 03513 // Get the device configuration whether we do exact matching or not. 03514 // 03515 03516 dwSize = sizeof(DWORD); 03517 if (! GetDeviceData(pEnumRecord->pDeviceName, dwDeviceClass, DEVICE_PROFILE_ENUMMODE, 03518 (PVOID *)&pbSkipMatch, &dwSize, FALSE)) 03519 { 03520 bSkipMatch = FALSE; 03521 } 03522 03523 // 03524 // Get the profile data. 03525 // 03526 03527 dwSize = 0; 03528 if (! GetDeviceData(pEnumRecord->pDeviceName, dwDeviceClass, DEVICE_PROFILE_DATA, 03529 (PVOID *)&pProfileList, &dwSize, TRUE)) 03530 { 03531 pProfileList = NULL; // no data found 03532 } 03533 03534 if(! pProfileList) 03535 { 03536 // 03537 // No profiles associated with this device 03538 // 03539 03540 rc = TRUE; 03541 if (pBuffer && dwInputSize >= sizeof(TCHAR)*2) 03542 { 03543 *((PTSTR)pBuffer + 1) = '\0'; 03544 } 03545 goto EndEnumerateColorProfiles; 03546 } 03547 03548 // 03549 // Run through the list of profiles and check each one to see if it 03550 // matches the enumeration criteria. If it does, and the buffer is 03551 // large enough, copy it to the buffer, and increment the byte count 03552 // and number of profiles enumerated. 03553 // 03554 03555 pBufferStart = pBuffer; 03556 pTempProfileList = pProfileList; 03557 03558 while (*pTempProfileList) 03559 { 03560 lstrcpy(pProfile, pTempProfileList); 03561 03562 if (bSkipMatch) 03563 { 03564 match = EXACT_MATCH; 03565 } 03566 else 03567 { 03568 match = DoesProfileMatchEnumRecord(szFullPath, pEnumRecord); 03569 } 03570 03571 if (match != NOMATCH) 03572 { 03573 *pdwSize += (lstrlen(pTempProfileList) + 1) * sizeof(TCHAR); 03574 03575 // 03576 // Check strictly less than because you need one more for 03577 // the final NULL termination 03578 // 03579 03580 if (pBuffer && (*pdwSize < dwInputSize)) 03581 { 03582 if (match == MATCH) 03583 { 03584 lstrcpy((PTSTR)pBuffer, pTempProfileList); 03585 } 03586 else 03587 { 03588 // 03589 // Exact match, add to beginning of buffer 03590 // 03591 03592 InsertInBuffer(pBufferStart, pBuffer, pTempProfileList); 03593 } 03594 03595 pBuffer += (lstrlen(pTempProfileList) + 1) * sizeof(TCHAR); 03596 } 03597 03598 if (pnProfiles) 03599 (*pnProfiles)++; 03600 } 03601 03602 pTempProfileList += lstrlen(pTempProfileList) + 1; 03603 } 03604 } 03605 else 03606 { 03607 DWORD dwNumClasses; 03608 PTSTR *ppszEnumClasses; 03609 PTSTR pszEnumClassArray[2]; 03610 03611 // 03612 // We are not looking at a particular device, so enumerate 03613 // profiles from the registry 03614 // 03615 03616 if (pEnumRecord->dwFields & ET_DEVICECLASS) 03617 { 03618 // 03619 // If device class is specified, enumrate the specified device class and color 03620 // space class which can be associated to any device. 03621 // 03622 03623 pszEnumClassArray[0] = ConvertClassIdToClassString(pEnumRecord->dwDeviceClass); 03624 pszEnumClassArray[1] = ConvertClassIdToClassString(CLASS_COLORSPACE); 03625 03626 if (!pszEnumClassArray[0] || !pszEnumClassArray[1]) 03627 { 03628 WARNING((__TEXT("Invalid DeviceClass to EnumColorProfiles\n"))); 03629 SetLastError(ERROR_INVALID_PARAMETER); 03630 goto EndEnumerateColorProfiles; 03631 } 03632 03633 ppszEnumClasses = pszEnumClassArray; 03634 dwNumClasses = 2; 03635 } 03636 else 03637 { 03638 ppszEnumClasses = gpszClasses; 03639 dwNumClasses = sizeof(gpszClasses)/sizeof(PTSTR); 03640 } 03641 03642 // 03643 // Open the registry path where profiles are kept (and create it if not exist) 03644 // 03645 03646 if ((dwErr = RegCreateKey(HKEY_LOCAL_MACHINE, gszICMRegPath, &hkICM)) != ERROR_SUCCESS) 03647 { 03648 WARNING((__TEXT("Cannot open ICM branch of registry: %d\n"), dwErr)); 03649 SetLastError(dwErr); 03650 goto EndEnumerateColorProfiles; 03651 } 03652 03653 pBufferStart = pBuffer; 03654 03655 for (i=0; i<dwNumClasses; i++,ppszEnumClasses++) 03656 { 03657 DWORD nValues; // number of name-values in key 03658 03659 if (RegOpenKey(hkICM, *ppszEnumClasses, &hkDevice) != ERROR_SUCCESS) 03660 { 03661 continue; // go to next key 03662 } 03663 03664 if ((dwErr = RegQueryInfoKey(hkDevice, NULL, NULL, 0, NULL, NULL, NULL, 03665 &nValues, NULL, NULL, NULL, NULL)) != ERROR_SUCCESS) 03666 { 03667 WARNING((__TEXT("Cannot count values in device branch of registry: %d\n"), dwErr)); 03668 RegCloseKey(hkDevice); 03669 SetLastError(dwErr); 03670 goto EndEnumerateColorProfiles; 03671 } 03672 03673 // 03674 // Go through the list of profiles and return everything that 03675 // satisfies the enumeration criteria 03676 // 03677 03678 for (j=0; j<nValues; j++) 03679 { 03680 dwSize = sizeof(szFullPath) - dwLen; 03681 dwDataSize = sizeof(REGDATA); 03682 if (RegEnumValue(hkDevice, j, pProfile, &dwSize, 0, 03683 NULL, (PBYTE)&regData, &dwDataSize) == ERROR_SUCCESS) 03684 { 03685 match = DoesProfileMatchEnumRecord(szFullPath, pEnumRecord); 03686 03687 if (match != NOMATCH) 03688 { 03689 *pdwSize += (lstrlen(pProfile) + 1) * sizeof(TCHAR); 03690 if (pBuffer && (*pdwSize < dwInputSize)) 03691 { 03692 if (match == MATCH) 03693 { 03694 lstrcpy((PTSTR)pBuffer, pProfile); 03695 } 03696 else 03697 { 03698 // 03699 // Exact match, add to beginning of buffer 03700 // 03701 03702 InsertInBuffer(pBufferStart, pBuffer, pProfile); 03703 } 03704 03705 pBuffer += (lstrlen(pProfile) + 1) * sizeof(TCHAR); 03706 } 03707 03708 if (pnProfiles) 03709 (*pnProfiles)++; 03710 } 03711 } 03712 } 03713 03714 RegCloseKey(hkDevice); 03715 } 03716 } 03717 03718 *pdwSize += sizeof(TCHAR); // extra NULL termination 03719 03720 if (pBuffer && *pdwSize <= dwInputSize) 03721 { 03722 *((PTSTR)pBuffer) = '\0'; 03723 rc = TRUE; 03724 } 03725 else 03726 { 03727 SetLastError(ERROR_INSUFFICIENT_BUFFER); 03728 } 03729 03730 EndEnumerateColorProfiles: 03731 03732 if (hkICM) 03733 { 03734 RegCloseKey(hkICM); 03735 } 03736 if (pProfileList) 03737 { 03738 MemFree(pProfileList); 03739 } 03740 03741 return rc; 03742 } 03743 03744 VOID 03745 InsertInBuffer( 03746 PBYTE pStart, 03747 PBYTE pEnd, 03748 PTSTR pString 03749 ) 03750 { 03751 DWORD cnt = (lstrlen(pString) + 1) * sizeof(TCHAR); 03752 03753 MyCopyMemory(pStart+cnt, pStart, (DWORD)(pEnd - pStart)); 03754 03755 lstrcpy((PTSTR)pStart, pString); 03756 03757 return; 03758 } 03759 03760 /****************************************************************************** 03761 * 03762 * InternalSetSCSProfile 03763 * 03764 * Function: 03765 * These functions regsiters the given profile for the standard color 03766 * space specified. This will register it in the OS and can be queried 03767 * using GetStandardColorSpaceProfile. 03768 * 03769 * Arguments: 03770 * pMachineName - name identifying machine on which the standard color 03771 * space profile should be registered 03772 * dwSCS - ID for the standard color space 03773 * pProfileName - pointer to profile filename 03774 * 03775 * Returns: 03776 * TRUE if successful, NULL otherwise 03777 * 03778 * Warning: 03779 * Currently only local registration is supported, so pMachineName should 03780 * be NULL. 03781 * 03782 ******************************************************************************/ 03783 03784 BOOL 03785 InternalSetSCSProfile( 03786 LPCTSTR pMachineName, 03787 DWORD dwSCS, 03788 LPCTSTR pProfileName 03789 ) 03790 { 03791 HKEY hkICM = NULL; // key to ICM branch in registry 03792 HKEY hkRegProf = NULL; // key to registered color spaces branch 03793 DWORD dwSize; // size of registry data 03794 DWORD dwErr; // error code 03795 BOOL rc = FALSE; // return code 03796 TCHAR szProfileID[5]; // profile class 03797 03798 // 03799 // Validate parameters 03800 // 03801 03802 if (!pProfileName) 03803 { 03804 WARNING((__TEXT("Invalid parameter to SetStandardColorSpaceProfile\n"))); 03805 SetLastError(ERROR_INVALID_PARAMETER); 03806 return FALSE; 03807 } 03808 03809 // 03810 // Only local registration is allowed now 03811 // 03812 03813 if (pMachineName != NULL) 03814 { 03815 WARNING((__TEXT("Remote SCS profile registration attempted, failing...\n"))); 03816 SetLastError(ERROR_NOT_SUPPORTED); 03817 return FALSE; 03818 } 03819 03820 dwSize = (lstrlen(pProfileName) + 1) * sizeof(TCHAR); 03821 03822 // 03823 // Open the registry location where this is kept 03824 // 03825 03826 if (((dwErr = RegCreateKey(HKEY_LOCAL_MACHINE, gszICMRegPath, &hkICM)) == ERROR_SUCCESS) && 03827 ((dwErr = RegCreateKey(hkICM, gszRegisteredProfiles, &hkRegProf))== ERROR_SUCCESS)) 03828 { 03829 ConvertDwordToString(dwSCS, szProfileID); 03830 03831 if ((dwErr = RegSetValueEx(hkRegProf, szProfileID, 0, REG_SZ, 03832 (PBYTE)pProfileName, dwSize)) == ERROR_SUCCESS) 03833 { 03834 rc = TRUE; 03835 } 03836 } 03837 03838 if (hkICM) 03839 { 03840 RegCloseKey(hkICM); 03841 } 03842 03843 if (hkRegProf) 03844 { 03845 RegCloseKey(hkRegProf); 03846 } 03847 03848 if (!rc) 03849 { 03850 WARNING((__TEXT("InternalSetSCSProfile failed: %d\n"), dwErr)); 03851 SetLastError(dwErr); 03852 } 03853 03854 return rc; 03855 } 03856 03857 03858 /****************************************************************************** 03859 * 03860 * InternalGetSCSProfile 03861 * 03862 * Function: 03863 * These functions retrieves the profile regsitered for the standard color 03864 * space specified. 03865 * 03866 * Arguments: 03867 * pMachineName - name identifying machine on which the standard color 03868 * space profile should be queried 03869 * dwSCS - ID for the standard color space 03870 * pBuffer - pointer to buffer to receive profile filename 03871 * pdwSize - pointer to DWORD specifying size of buffer. On return 03872 * it has size needed/used 03873 * 03874 * Returns: 03875 * TRUE if successful, NULL otherwise 03876 * 03877 * Warning: 03878 * Currently only local query is supported, so pMachineName should 03879 * be NULL. 03880 * 03881 ******************************************************************************/ 03882 03883 BOOL 03884 InternalGetSCSProfile( 03885 LPCTSTR pMachineName, 03886 DWORD dwSCS, 03887 PTSTR pBuffer, 03888 PDWORD pdwSize 03889 ) 03890 { 03891 HKEY hkICM = NULL; // key to ICM branch in registry 03892 HKEY hkRegProf = NULL; // key to registered color spaces branch 03893 DWORD dwErr; // error code 03894 DWORD dwSize; 03895 BOOL rc = FALSE; // return code 03896 TCHAR szProfileID[5]; // profile class 03897 03898 // 03899 // Validate parameters 03900 // 03901 03902 if (! pdwSize || 03903 IsBadWritePtr(pdwSize, sizeof(DWORD)) || 03904 (pBuffer && IsBadWritePtr(pBuffer, *pdwSize))) 03905 { 03906 WARNING((__TEXT("Invalid parameter to GetStandardColorSpaceProfile\n"))); 03907 SetLastError(ERROR_INVALID_PARAMETER); 03908 return FALSE; 03909 } 03910 03911 // 03912 // Only local query is allowed now 03913 // 03914 03915 if (pMachineName != NULL) 03916 { 03917 WARNING((__TEXT("Remote SCS profile query attempted, failing...\n"))); 03918 SetLastError(ERROR_NOT_SUPPORTED); 03919 return FALSE; 03920 } 03921 03922 dwSize = *pdwSize; 03923 03924 // 03925 // Look in the registry for a profile registered for this color space ID 03926 // 03927 03928 if (((dwErr = RegOpenKey(HKEY_LOCAL_MACHINE, gszICMRegPath, &hkICM)) == ERROR_SUCCESS) && 03929 ((dwErr = RegOpenKey(hkICM, gszRegisteredProfiles, &hkRegProf)) == ERROR_SUCCESS)) 03930 { 03931 ConvertDwordToString(dwSCS, szProfileID); 03932 if ((dwErr = RegQueryValueEx(hkRegProf, szProfileID, NULL, NULL, 03933 (PBYTE)pBuffer, pdwSize)) == ERROR_SUCCESS) 03934 { 03935 rc = TRUE; 03936 } 03937 } 03938 03939 if (hkICM) 03940 { 03941 RegCloseKey(hkICM); 03942 } 03943 03944 if (hkRegProf) 03945 { 03946 RegCloseKey(hkRegProf); 03947 } 03948 03949 if (!rc && (dwSCS == LCS_sRGB || dwSCS == LCS_WINDOWS_COLOR_SPACE)) 03950 { 03951 *pdwSize = dwSize; 03952 rc = GetColorDirectory(NULL, pBuffer, pdwSize); 03953 if (!rc && GetLastError() != ERROR_INSUFFICIENT_BUFFER) 03954 { 03955 return FALSE; 03956 } 03957 03958 *pdwSize += (lstrlen(gszBackslash) + lstrlen(gszsRGBProfile)) * sizeof(TCHAR); 03959 03960 if (*pdwSize <= dwSize && pBuffer) 03961 { 03962 lstrcat(pBuffer, gszBackslash); 03963 lstrcat(pBuffer, gszsRGBProfile); 03964 rc = TRUE; 03965 } 03966 else 03967 { 03968 dwErr = ERROR_INSUFFICIENT_BUFFER; 03969 } 03970 } 03971 03972 if (!rc) 03973 { 03974 WARNING((__TEXT("InternalGetSCSProfile failed: %d\n"), dwErr)); 03975 SetLastError(dwErr); 03976 } 03977 03978 // 03979 // If pBuffer is NULL, RegQueryValueEx return TRUE. Our API should return FALSE 03980 // in this case. Handle this. 03981 // 03982 03983 if (pBuffer == NULL && rc) 03984 { 03985 SetLastError(ERROR_INSUFFICIENT_BUFFER); 03986 rc = FALSE; 03987 } 03988 03989 return rc; 03990 } 03991 03992 03993 /****************************************************************************** 03994 * 03995 * ConvertDwordToString 03996 * 03997 * Function: 03998 * This function converts a DWORD into a string. The string passed in 03999 * is large enough. It converts to Unicode or Ansi depending on how 04000 * this is compiled. 04001 * 04002 * Arguments: 04003 * dword - DWORD to convert 04004 * pString - pointer to buffer to hold the result 04005 * 04006 * Returns: 04007 * Nothing 04008 * 04009 ******************************************************************************/ 04010 04011 VOID 04012 ConvertDwordToString( 04013 DWORD dword, 04014 PTSTR pString 04015 ) 04016 { 04017 int i; // counter 04018 04019 for (i=0; i<4; i++) 04020 { 04021 pString[i] = (TCHAR)(((char*)&dword)[3-i]); 04022 } 04023 04024 pString[4] = '\0'; 04025 04026 return; 04027 } 04028 04029 /****************************************************************************** 04030 * 04031 * ConvertClassIdToClassString 04032 * 04033 * Function: 04034 * This function converts a DWORD Device Class Id into a its device string 04035 * 04036 * Arguments: 04037 * dwClassId - Device class id. 04038 * 04039 * Returns: 04040 * pointer to a string 04041 * 04042 ******************************************************************************/ 04043 04044 PTSTR 04045 ConvertClassIdToClassString( 04046 DWORD dwClassId 04047 ) 04048 { 04049 switch (dwClassId) 04050 { 04051 case CLASS_MONITOR: 04052 return (gpszClasses[INDEX_CLASS_MONITOR]); 04053 case CLASS_PRINTER: 04054 return (gpszClasses[INDEX_CLASS_PRINTER]); 04055 case CLASS_SCANNER: 04056 return (gpszClasses[INDEX_CLASS_SCANNER]); 04057 case CLASS_COLORSPACE: 04058 return (gpszClasses[INDEX_CLASS_COLORSPACE]); 04059 default: 04060 return NULL; 04061 } 04062 } 04063 04064 /****************************************************************************** 04065 * 04066 * GetProfileClassString 04067 * 04068 * Function: 04069 * This function returns the profile class from the header as a string. 04070 * It also validates the profile. 04071 * 04072 * Arguments: 04073 * pProfileName - name of profile 04074 * pClass - pointer to buffer to hold the profile class string 04075 * pHeader - if this is non NULL, it returns the header here 04076 * 04077 * Returns: 04078 * TRUE on success, FALSE otherwise 04079 * 04080 ******************************************************************************/ 04081 04082 BOOL 04083 GetProfileClassString( 04084 LPCTSTR pProfileName, 04085 PTSTR pClass, 04086 PPROFILEHEADER pHeader 04087 ) 04088 { 04089 PROFILEHEADER header; // color profile header 04090 PROFILE prof; // profile object for opening profile 04091 HPROFILE hProfile = NULL; // handle to opened profile 04092 BOOL bValidProfile = FALSE; // validation of the profile 04093 BOOL rc = FALSE; // return code 04094 04095 // 04096 // Open a handle to the profile 04097 // 04098 04099 prof.dwType = PROFILE_FILENAME; 04100 prof.pProfileData = (PVOID)pProfileName; 04101 prof.cbDataSize = (lstrlen(pProfileName) + 1) * sizeof(TCHAR); 04102 04103 hProfile = OpenColorProfile(&prof, PROFILE_READ, FILE_SHARE_READ, 04104 OPEN_EXISTING); 04105 if (! hProfile) 04106 { 04107 WARNING((__TEXT("Error opening profile %s\n"), pProfileName)); 04108 goto EndGetProfileClassString; 04109 } 04110 04111 // 04112 // Check the validation of the profile. 04113 // 04114 if (! IsColorProfileValid(hProfile,&bValidProfile) || ! bValidProfile) 04115 { 04116 WARNING((__TEXT("Error invalid profile %s\n"), pProfileName)); 04117 goto EndGetProfileClassString; 04118 } 04119 04120 // 04121 // Get the profile class 04122 // 04123 04124 if (! pHeader) 04125 { 04126 pHeader = &header; 04127 } 04128 04129 if (! GetColorProfileHeader(hProfile, pHeader)) 04130 { 04131 ERR((__TEXT("Error getting color profile header for %s\n"), pProfileName)); 04132 goto EndGetProfileClassString; 04133 } 04134 ConvertDwordToString(pHeader->phClass, pClass); 04135 04136 rc= TRUE; 04137 04138 EndGetProfileClassString: 04139 if (hProfile) 04140 { 04141 CloseColorProfile(hProfile); 04142 } 04143 04144 return rc; 04145 } 04146 04147 04148 /****************************************************************************** 04149 * 04150 * GetFilenameFromPath 04151 * 04152 * Function: 04153 * This function takes a fully qualified pathname and returns a pointer 04154 * to the filename part alone 04155 * 04156 * Arguments: 04157 * pPathName - pointer to pathname 04158 * 04159 * Returns: 04160 * Pointer to filename on success, NULL otherwise 04161 * 04162 ******************************************************************************/ 04163 04164 PTSTR 04165 GetFilenameFromPath( 04166 PTSTR pPathName 04167 ) 04168 { 04169 DWORD dwLen; // length of pathname 04170 PTSTR pPathNameStart = pPathName; 04171 04172 dwLen = lstrlen(pPathName); 04173 04174 if (dwLen == 0) 04175 { 04176 return NULL; 04177 } 04178 04179 // 04180 // Go to the end of the pathname, and start going backwards till 04181 // you reach the beginning or a backslash 04182 // 04183 04184 pPathName += dwLen; 04185 04186 // 04187 // Currently 'pPathName' points null-terminate character, so move 04188 // the pointer to last character. 04189 // 04190 04191 do 04192 { 04193 pPathName = CharPrev(pPathNameStart,pPathName); 04194 04195 if (*pPathName == TEXT('\\')) 04196 { 04197 pPathName = CharNext(pPathName); 04198 break; 04199 } 04200 04201 // 04202 // Loop until fist 04203 // 04204 04205 } while (pPathNameStart < pPathName); 04206 04207 // 04208 // if *pPathName is zero, then we had a string that ends in a backslash 04209 // 04210 04211 return *pPathName ? pPathName : NULL; 04212 } 04213 04214 04215 /****************************************************************************** 04216 * 04217 * GetDeviceData 04218 * 04219 * Function: 04220 * This function is a wrapper for IGetDeviceData. For devices like monitor, 04221 * printer & scanner it calls the internal function. If we are asked 04222 * to get the device data for a "colorspace device", we try monitor, printer 04223 * and scanner till one succeeds or they all fail. This is done so that we 04224 * we can associate sRGB like profiles with any device. 04225 * 04226 * Arguments: 04227 * pDeviceName - pointer to name of the device 04228 * dwClass - device type like monitor, printer etc. 04229 * ppDeviceData - pointer to pointer to buffer to receive data 04230 * pdwSize - pointer to size of buffer. On return it is size of 04231 * data returned/size needed. 04232 * bAllocate - If TRUE, allocate memory for data 04233 * 04234 * Returns: 04235 * TRUE if successful, FALSE otherwise 04236 * 04237 ******************************************************************************/ 04238 04239 BOOL 04240 GetDeviceData( 04241 LPCTSTR pDeviceName, 04242 DWORD dwClass, 04243 DWORD dwDataType, 04244 PVOID *ppDeviceData, 04245 PDWORD pdwSize, 04246 BOOL bAllocate 04247 ) 04248 { 04249 BOOL rc = FALSE; 04250 04251 if (dwClass == CLASS_MONITOR || 04252 dwClass == CLASS_PRINTER || 04253 dwClass == CLASS_SCANNER) 04254 { 04255 rc = IGetDeviceData(pDeviceName, dwClass, dwDataType, ppDeviceData, pdwSize, bAllocate); 04256 } 04257 else if (dwClass == CLASS_COLORSPACE) 04258 { 04259 rc = IGetDeviceData(pDeviceName, CLASS_MONITOR, dwDataType, ppDeviceData, pdwSize, bAllocate) || 04260 IGetDeviceData(pDeviceName, CLASS_PRINTER, dwDataType, ppDeviceData, pdwSize, bAllocate) || 04261 IGetDeviceData(pDeviceName, CLASS_SCANNER, dwDataType, ppDeviceData, pdwSize, bAllocate); 04262 } 04263 04264 return rc; 04265 } 04266 04267 04268 /****************************************************************************** 04269 * 04270 * IGetDeviceData 04271 * 04272 * Function: 04273 * This function retrieves ICM data stored with the different devices. 04274 * 04275 * Arguments: 04276 * pDeviceName - pointer to name of the device 04277 * dwClass - device type like monitor, printer etc. 04278 * ppDeviceData - pointer to pointer to buffer to receive data 04279 * pdwSize - pointer to size of buffer. On return it is size of 04280 * data returned/size needed. 04281 * bAllocate - If TRUE, allocate memory for data 04282 * 04283 * Returns: 04284 * TRUE if successful, FALSE otherwise 04285 * 04286 ******************************************************************************/ 04287 04288 BOOL 04289 IGetDeviceData( 04290 LPCTSTR pDeviceName, 04291 DWORD dwClass, 04292 DWORD dwDataType, 04293 PVOID *ppDeviceData, 04294 PDWORD pdwSize, 04295 BOOL bAllocate 04296 ) 04297 { 04298 PFNOPENDEVICE fnOpenDevice; 04299 PFNCLOSEDEVICE fnCloseDevice; 04300 PFNGETDEVICEDATA fnGetData; 04301 HANDLE hDevice; 04302 DWORD dwSize; 04303 LPTSTR pDataKey; 04304 LPTSTR pDataValue; 04305 BOOL rc = FALSE; 04306 04307 // 04308 // Set up function pointers so we can write common code 04309 // 04310 04311 switch (dwClass) 04312 { 04313 case CLASS_PRINTER: 04314 fnOpenDevice = (PFNOPENDEVICE)OpenPrtr; 04315 fnCloseDevice = (PFNCLOSEDEVICE)ClosePrtr; 04316 fnGetData = (PFNGETDEVICEDATA)GetPrtrData; 04317 break; 04318 04319 case CLASS_MONITOR: 04320 fnOpenDevice = (PFNOPENDEVICE)OpenMonitor; 04321 fnCloseDevice = (PFNCLOSEDEVICE)CloseMonitor; 04322 fnGetData = (PFNGETDEVICEDATA)GetMonitorData; 04323 break; 04324 04325 case CLASS_SCANNER: 04326 fnOpenDevice = (PFNOPENDEVICE)OpenScanner; 04327 fnCloseDevice = (PFNCLOSEDEVICE)CloseScanner; 04328 fnGetData = (PFNGETDEVICEDATA)GetScannerData; 04329 break; 04330 04331 default: 04332 return FALSE; 04333 } 04334 04335 // 04336 // Set up registry keywords. 04337 // 04338 04339 switch (dwDataType) 04340 { 04341 case DEVICE_PROFILE_DATA: 04342 04343 pDataKey = gszICMProfileListKey; 04344 04345 // 04346 // The way to store printer profile is different than others... trim it. 04347 // 04348 04349 if (dwClass == CLASS_PRINTER) 04350 { 04351 pDataValue = gszFiles; 04352 } 04353 else 04354 { 04355 pDataValue = gszICMProfileListValue; 04356 } 04357 04358 break; 04359 04360 case DEVICE_PROFILE_ENUMMODE: 04361 04362 pDataKey = gszICMDeviceDataKey; 04363 pDataValue = gszICMProfileEnumMode; 04364 break; 04365 04366 default: 04367 return FALSE; 04368 } 04369 04370 // 04371 // Open the device and get a handle to it 04372 // 04373 04374 if (! (*fnOpenDevice)((PTSTR)pDeviceName, &hDevice, NULL)) 04375 { 04376 return FALSE; 04377 } 04378 04379 if (bAllocate || (ppDeviceData == NULL)) 04380 { 04381 DWORD retcode; 04382 04383 // 04384 // We need to allocate memory. Find out how much we need, and 04385 // allocate it. 04386 // 04387 04388 dwSize = 0; 04389 retcode = (*fnGetData)(hDevice, pDataKey, pDataValue, NULL, NULL, 0, &dwSize); 04390 04391 if ((retcode != ERROR_SUCCESS) && // Win 95 returns this 04392 (retcode != ERROR_MORE_DATA)) // NT returns this 04393 { 04394 VERBOSE((__TEXT("GetDeviceData failed for %s\n"), pDeviceName)); 04395 goto EndGetDeviceData; 04396 } 04397 04398 *pdwSize = dwSize; 04399 04400 if (ppDeviceData == NULL) 04401 { 04402 // 04403 // Caller wants to know the data size. 04404 // 04405 04406 rc = TRUE; 04407 goto EndGetDeviceData; 04408 } 04409 else 04410 { 04411 // 04412 // Allocate buffer. 04413 // 04414 04415 *ppDeviceData = MemAlloc(dwSize); 04416 if (! *ppDeviceData) 04417 { 04418 WARNING((__TEXT("Error allocating memory\n"))); 04419 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 04420 goto EndGetDeviceData; 04421 } 04422 } 04423 } 04424 04425 // 04426 // Get the data 04427 // 04428 04429 if ((*fnGetData)(hDevice, pDataKey, pDataValue, NULL, (PBYTE)*ppDeviceData, 04430 *pdwSize, pdwSize) == ERROR_SUCCESS) 04431 { 04432 rc = TRUE; 04433 } 04434 04435 EndGetDeviceData: 04436 (*fnCloseDevice)(hDevice); 04437 04438 return rc; 04439 } 04440 04441 04442 /****************************************************************************** 04443 * 04444 * SetDeviceData 04445 * 04446 * Function: 04447 * This function is a wrapper for ISetDeviceData. For devices like monitor, 04448 * printer & scanner it calls the internal function. If we are asked 04449 * to set the device data for a "colorspace device", we try monitor, printer 04450 * and scanner till one succeeds or they all fail. This is done so that we 04451 * we can associate sRGB like profiles with any device. 04452 * 04453 * Arguments: 04454 * pDeviceName - pointer to name of the device 04455 * dwClass - device type like monitor, printer etc. 04456 * pDeviceData - pointer buffer containing data 04457 * dwSize - size of data 04458 * 04459 * Returns: 04460 * TRUE if successful, FALSE otherwise 04461 * 04462 ******************************************************************************/ 04463 04464 BOOL 04465 SetDeviceData( 04466 LPCTSTR pDeviceName, 04467 DWORD dwClass, 04468 DWORD dwDataType, 04469 PVOID pDeviceData, 04470 DWORD dwSize 04471 ) 04472 { 04473 BOOL rc = FALSE; 04474 04475 if (dwClass == CLASS_MONITOR || 04476 dwClass == CLASS_PRINTER || 04477 dwClass == CLASS_SCANNER) 04478 { 04479 rc = ISetDeviceData(pDeviceName, dwClass, dwDataType, pDeviceData, dwSize); 04480 } 04481 else if (dwClass == CLASS_COLORSPACE) 04482 { 04483 rc = ISetDeviceData(pDeviceName, CLASS_MONITOR, dwDataType, pDeviceData, dwSize) || 04484 ISetDeviceData(pDeviceName, CLASS_PRINTER, dwDataType, pDeviceData, dwSize) || 04485 ISetDeviceData(pDeviceName, CLASS_SCANNER, dwDataType, pDeviceData, dwSize); 04486 } 04487 04488 return rc; 04489 } 04490 04491 04492 /****************************************************************************** 04493 * 04494 * ISetDeviceData 04495 * 04496 * Function: 04497 * This function sets ICM data stored with the different devices. 04498 * 04499 * Arguments: 04500 * pDeviceName - pointer to name of the device 04501 * dwClass - device type like monitor, printer etc. 04502 * pDeviceData - pointer buffer containing data 04503 * dwSize - size of data 04504 * 04505 * Returns: 04506 * TRUE if successful, FALSE otherwise 04507 * 04508 ******************************************************************************/ 04509 04510 BOOL 04511 ISetDeviceData( 04512 LPCTSTR pDeviceName, 04513 DWORD dwClass, 04514 DWORD dwDataType, 04515 PVOID pDeviceData, 04516 DWORD dwSize 04517 ) 04518 { 04519 PRINTER_DEFAULTS pd; 04520 PFNOPENDEVICE fnOpenDevice; 04521 PFNCLOSEDEVICE fnCloseDevice; 04522 PFNSETDEVICEDATA fnSetData; 04523 HANDLE hDevice; 04524 LPTSTR pDataKey; 04525 LPTSTR pDataValue; 04526 DWORD dwRegType = REG_BINARY; 04527 BOOL rc = FALSE; 04528 04529 // 04530 // Set up function pointers so we can write common code 04531 // 04532 04533 switch (dwClass) 04534 { 04535 case CLASS_PRINTER: 04536 fnOpenDevice = (PFNOPENDEVICE)OpenPrtr; 04537 fnCloseDevice = (PFNCLOSEDEVICE)ClosePrtr; 04538 fnSetData = (PFNSETDEVICEDATA)SetPrtrData; 04539 pd.pDatatype = __TEXT("RAW"); 04540 pd.pDevMode = NULL; 04541 pd.DesiredAccess = PRINTER_ACCESS_ADMINISTER; 04542 break; 04543 04544 case CLASS_MONITOR: 04545 fnOpenDevice = (PFNOPENDEVICE)OpenMonitor; 04546 fnCloseDevice = (PFNCLOSEDEVICE)CloseMonitor; 04547 fnSetData = (PFNSETDEVICEDATA)SetMonitorData; 04548 break; 04549 04550 case CLASS_SCANNER: 04551 fnOpenDevice = (PFNOPENDEVICE)OpenScanner; 04552 fnCloseDevice = (PFNCLOSEDEVICE)CloseScanner; 04553 fnSetData = (PFNSETDEVICEDATA)SetScannerData; 04554 break; 04555 04556 default: 04557 return FALSE; 04558 } 04559 04560 // 04561 // Set up registry keywords. 04562 // 04563 04564 switch (dwDataType) 04565 { 04566 case DEVICE_PROFILE_DATA: 04567 04568 pDataKey = gszICMProfileListKey; 04569 04570 // 04571 // The way to store printer profile is different than others... trim it. 04572 // 04573 04574 if (dwClass == CLASS_PRINTER) 04575 { 04576 pDataValue = gszFiles; 04577 dwRegType = REG_MULTI_SZ; 04578 } 04579 else 04580 { 04581 pDataValue = gszICMProfileListValue; 04582 } 04583 04584 break; 04585 04586 case DEVICE_PROFILE_ENUMMODE: 04587 04588 pDataKey = gszICMDeviceDataKey; 04589 pDataValue = gszICMProfileEnumMode; 04590 break; 04591 04592 default: 04593 return FALSE; 04594 } 04595 04596 // 04597 // Open the device and get a handle to it 04598 // 04599 04600 if (! (*fnOpenDevice)((PTSTR)pDeviceName, &hDevice, (PTSTR)&pd)) 04601 { 04602 WARNING((__TEXT("Error opening device %s\n"), pDeviceName)); 04603 return FALSE; 04604 } 04605 04606 // 04607 // Set the data 04608 // 04609 04610 if ((*fnSetData)(hDevice, pDataKey, pDataValue, dwRegType, (PBYTE)pDeviceData, 04611 dwSize) == ERROR_SUCCESS) 04612 { 04613 rc = TRUE; 04614 } 04615 04616 #if !defined(_WIN95_) 04617 04618 // 04619 // If this is printer class, need some more data for profile list. 04620 // 04621 04622 if ((rc == TRUE) && (dwClass == CLASS_PRINTER) && (dwDataType == DEVICE_PROFILE_DATA)) 04623 { 04624 if (((*fnSetData)(hDevice, pDataKey, gszDirectory, REG_SZ, (PBYTE)gszColorDir, 04625 (lstrlen(gszColorDir) + 1)*sizeof(TCHAR)) != ERROR_SUCCESS) || 04626 ((*fnSetData)(hDevice, pDataKey, gszModule, REG_SZ, (PBYTE)gszMSCMS, 04627 (lstrlen(gszMSCMS) + 1)*sizeof(TCHAR)) != ERROR_SUCCESS)) 04628 { 04629 rc = FALSE; 04630 } 04631 } 04632 04633 #endif 04634 04635 (*fnCloseDevice)(hDevice); 04636 04637 return rc; 04638 } 04639 04640 04641 /****************************************************************************** 04642 * 04643 * IsStringInMultiSz 04644 * 04645 * Function: 04646 * This functions checks if a given multi-sz string has the given string 04647 * as one of the strings, and returns TRUE if it does. 04648 * 04649 * Arguments: 04650 * pMultiSzString - multi sz string to look in 04651 * pString - string to find 04652 * 04653 * Returns: 04654 * TRUE 04655 * 04656 ******************************************************************************/ 04657 04658 BOOL 04659 IsStringInMultiSz( 04660 PTSTR pMultiSzString, 04661 PTSTR pString 04662 ) 04663 { 04664 BOOL rc = FALSE; // return code 04665 04666 while (*pMultiSzString) 04667 { 04668 if (! lstrcmpi(pMultiSzString, pString)) 04669 { 04670 rc = TRUE; 04671 break; 04672 } 04673 04674 pMultiSzString += lstrlen(pMultiSzString) + 1; 04675 } 04676 04677 return rc; 04678 } 04679 04680 04681 /****************************************************************************** 04682 * 04683 * RemoveStringFromMultiSz 04684 * 04685 * Function: 04686 * This functions removes a given string from a multi-sz string. 04687 * 04688 * Arguments: 04689 * pMultiSzString - multi sz string to look in 04690 * pString - string to remove 04691 * dwSize - size in bytes of multi-sz string 04692 * 04693 * Returns: 04694 * TRUE 04695 * 04696 ******************************************************************************/ 04697 04698 DWORD 04699 RemoveStringFromMultiSz( 04700 PTSTR pMultiSzString, 04701 PTSTR pString, 04702 DWORD dwSize 04703 ) 04704 { 04705 DWORD dwCount = dwSize; // count of bytes remaining 04706 04707 while (*pMultiSzString) 04708 { 04709 dwCount -= (lstrlen(pMultiSzString) + 1) * sizeof(TCHAR); 04710 04711 if (! lstrcmpi(pMultiSzString, pString)) 04712 { 04713 break; 04714 } 04715 04716 pMultiSzString += lstrlen(pMultiSzString) + 1; 04717 } 04718 04719 MyCopyMemory((PBYTE)pMultiSzString, (PBYTE)(pMultiSzString + lstrlen(pString) + 1), dwCount); 04720 04721 return dwSize - sizeof(TCHAR) * (lstrlen(pString) + 1); 04722 } 04723 04724 04725 /****************************************************************************** 04726 * 04727 * DoesProfileMatchEnumRecord 04728 * 04729 * Function: 04730 * This functions checks if a profile matches the criteria given in 04731 * the enumeration record. Note that it does not check if the profile 04732 * belongs to the device specified by pDeviceName. So that check must 04733 * have happened before itself. 04734 * 04735 * Arguments: 04736 * pProfileName - profile to look at 04737 * pEnumRecord - pointer to criteria to check against 04738 * 04739 * Returns: 04740 * MATCH or EXACT_MATCH if the profile matches the criteria, NOMATCH otherwise 04741 * 04742 ******************************************************************************/ 04743 04744 #define SET(pEnumRecord, bit) ((pEnumRecord)->dwFields & (bit)) 04745 04746 MATCHTYPE 04747 DoesProfileMatchEnumRecord( 04748 PTSTR pProfileName, 04749 PENUMTYPE pEnumRecord 04750 ) 04751 { 04752 PROFILEHEADER header; // color profile header 04753 PROFILE prof; // profile object for opening profile 04754 HPROFILE hProfile = NULL; // handle to opened profile 04755 MATCHTYPE rc = NOMATCH; // return code 04756 04757 // 04758 // Open a handle to the profile 04759 // 04760 04761 prof.dwType = PROFILE_FILENAME; 04762 prof.pProfileData = (PVOID)pProfileName; 04763 prof.cbDataSize = (lstrlen(pProfileName) + 1) * sizeof(TCHAR); 04764 04765 hProfile = OpenColorProfile(&prof, PROFILE_READ, FILE_SHARE_READ, 04766 OPEN_EXISTING); 04767 if (! hProfile) 04768 { 04769 WARNING((__TEXT("Error opening profile %s\n"), pProfileName)); 04770 goto EndDoesProfileMatchEnumRecord; 04771 } 04772 04773 // 04774 // Get the profile header 04775 // 04776 04777 if (! GetColorProfileHeader(hProfile, &header)) 04778 { 04779 ERR((__TEXT("Error getting color profile header for %s\n"), pProfileName)); 04780 goto EndDoesProfileMatchEnumRecord; 04781 } 04782 04783 if ((!SET(pEnumRecord, ET_CMMTYPE) || (pEnumRecord->dwCMMType == header.phCMMType)) && 04784 (!SET(pEnumRecord, ET_CLASS) || (pEnumRecord->dwClass == header.phClass)) && 04785 (!SET(pEnumRecord, ET_DATACOLORSPACE) || (pEnumRecord->dwDataColorSpace == header.phDataColorSpace)) && 04786 (!SET(pEnumRecord, ET_CONNECTIONSPACE) || (pEnumRecord->dwConnectionSpace == header.phConnectionSpace)) && 04787 (!SET(pEnumRecord, ET_SIGNATURE) || (pEnumRecord->dwSignature == header.phSignature)) && 04788 (!SET(pEnumRecord, ET_PLATFORM) || (pEnumRecord->dwPlatform == header.phPlatform)) && 04789 (!SET(pEnumRecord, ET_PROFILEFLAGS) || (pEnumRecord->dwProfileFlags == header.phProfileFlags)) && 04790 (!SET(pEnumRecord, ET_MANUFACTURER) || (pEnumRecord->dwManufacturer == header.phManufacturer)) && 04791 (!SET(pEnumRecord, ET_MODEL) || (pEnumRecord->dwModel == header.phModel)) && 04792 (!SET(pEnumRecord, ET_ATTRIBUTES) || (pEnumRecord->dwAttributes[0] == header.phAttributes[0] && 04793 pEnumRecord->dwAttributes[1] == header.phAttributes[1])) && 04794 (!SET(pEnumRecord, ET_RENDERINGINTENT) || (pEnumRecord->dwRenderingIntent == header.phRenderingIntent)) && 04795 (!SET(pEnumRecord, ET_CREATOR) || (pEnumRecord->dwCreator == header.phCreator))) 04796 { 04797 rc = EXACT_MATCH; 04798 } 04799 04800 // 04801 // Check for resolution, media type and halftoning match 04802 // 04803 04804 if (rc != NOMATCH && SET(pEnumRecord, ET_RESOLUTION|ET_MEDIATYPE|ET_DITHERMODE)) 04805 { 04806 rc = CheckResMedHftnMatch(hProfile, pEnumRecord); 04807 } 04808 04809 EndDoesProfileMatchEnumRecord: 04810 if (hProfile) 04811 { 04812 CloseColorProfile(hProfile); 04813 } 04814 04815 return rc; 04816 } 04817 04818 04819 /****************************************************************************** 04820 * 04821 * CheckResMedHftnMatch 04822 * 04823 * Function: 04824 * This functions checks if a profile matches the resolution, 04825 * media type and halftoning criteria specified by the enumeration record. 04826 * It allows an exact match, as well as an ambiguous match. If the 04827 * profile doesn't specify the criteria, it is considered to ambiguously 04828 * match the specification. 04829 * is desired. 04830 * 04831 * Arguments: 04832 * hProfile - handle identifying profile 04833 * pEnumRecord - pointer to criteria to check against 04834 * 04835 * Returns: 04836 * MATCH or EXACT_MATCH if the profile matches the criteria, NOMATCH otherwise 04837 * 04838 ******************************************************************************/ 04839 04840 MATCHTYPE 04841 CheckResMedHftnMatch( 04842 HPROFILE hProfile, 04843 PENUMTYPE pEnumRecord 04844 ) 04845 { 04846 PDEVICESETTINGS pDevSettings = NULL; 04847 PPLATFORMENTRY pPlatform; 04848 PSETTINGCOMBOS pCombo; 04849 PSETTINGS pSetting; 04850 DWORD dwMSData[4]; 04851 DWORD dwSize, i, iMax, j, jMax; 04852 MATCHTYPE rc = MATCH; // Assume ambiguous match 04853 BOOL bReference; 04854 04855 // 04856 // Check if the profile has the new device settings tag 04857 // 04858 04859 dwSize = 0; 04860 GetColorProfileElement(hProfile, TAG_DEVICESETTINGS, 0, &dwSize, NULL, &bReference); 04861 04862 if (dwSize > 0) 04863 { 04864 if (!(pDevSettings = (PDEVICESETTINGS)GlobalAllocPtr(GHND, dwSize))) 04865 { 04866 WARNING((__TEXT("Error allocating memory\n"))); 04867 return NOMATCH; 04868 } 04869 04870 if (GetColorProfileElement(hProfile, TAG_DEVICESETTINGS, 0, &dwSize, (PBYTE)pDevSettings, &bReference)) 04871 { 04872 pPlatform = &pDevSettings->PlatformEntry[0]; 04873 04874 // 04875 // Navigate to the place where Microsoft specific settings are kept 04876 // 04877 04878 i = 0; 04879 iMax = FIX_ENDIAN(pDevSettings->nPlatforms); 04880 while ((i < iMax) && (pPlatform->PlatformID != ID_MSFT_REVERSED)) 04881 04882 { 04883 i++; 04884 pPlatform = (PPLATFORMENTRY)((PBYTE)pPlatform + FIX_ENDIAN(pPlatform->dwSize)); 04885 } 04886 04887 if (i >= iMax) 04888 { 04889 // 04890 // There are no MS specific settings, assume this profile is valid 04891 // for all settings (ambigous match) 04892 // 04893 04894 goto EndCheckResMedHftnMatch; 04895 } 04896 04897 // 04898 // Found MS specific data. Now go through each combination of settings 04899 // 04900 04901 pCombo = &pPlatform->SettingCombos[0]; 04902 iMax = FIX_ENDIAN(pPlatform->nSettingCombos); 04903 for (i=0; i<iMax; i++) 04904 { 04905 // 04906 // Go through each setting in the combination 04907 // 04908 04909 pSetting = &pCombo->Settings[0]; 04910 jMax = FIX_ENDIAN(pCombo->nSettings); 04911 for (j=0; j<jMax; j++) 04912 { 04913 if (pSetting->dwSettingType == ID_MEDIATYPE_REVERSED) 04914 { 04915 if (SET(pEnumRecord, ET_MEDIATYPE) && 04916 !DwordMatches(pSetting, pEnumRecord->dwMediaType)) 04917 { 04918 goto NextCombo; 04919 } 04920 } 04921 else if (pSetting->dwSettingType == ID_DITHER_REVERSED) 04922 { 04923 if (SET(pEnumRecord, ET_DITHERMODE) && 04924 !DwordMatches(pSetting, pEnumRecord->dwDitheringMode)) 04925 { 04926 goto NextCombo; 04927 } 04928 } 04929 else if (pSetting->dwSettingType == ID_RESLN_REVERSED) 04930 { 04931 if (SET(pEnumRecord, ET_RESOLUTION) && 04932 !QwordMatches(pSetting, &pEnumRecord->dwResolution[0])) 04933 { 04934 goto NextCombo; 04935 } 04936 } 04937 04938 pSetting = (PSETTINGS)((PBYTE)pSetting + sizeof(SETTINGS) - sizeof(DWORD) + 04939 FIX_ENDIAN(pSetting->dwSizePerValue) * FIX_ENDIAN(pSetting->nValues)); 04940 } 04941 04942 // 04943 // This combination worked! 04944 // 04945 04946 rc = EXACT_MATCH; 04947 goto EndCheckResMedHftnMatch; 04948 04949 NextCombo: 04950 pCombo = (PSETTINGCOMBOS)((PBYTE)pCombo + FIX_ENDIAN(pCombo->dwSize)); 04951 } 04952 04953 rc = NOMATCH; 04954 goto EndCheckResMedHftnMatch; 04955 04956 } 04957 else 04958 { 04959 rc = NOMATCH; 04960 goto EndCheckResMedHftnMatch; 04961 } 04962 } 04963 else 04964 { 04965 // 04966 // Check if the old MSxx tags are present 04967 // 04968 04969 dwSize = sizeof(dwMSData); 04970 if (SET(pEnumRecord, ET_MEDIATYPE)) 04971 { 04972 if (GetColorProfileElement(hProfile, TAG_MS01, 0, &dwSize, dwMSData, &bReference)) 04973 { 04974 rc = EXACT_MATCH; // Assume exact match 04975 04976 if (pEnumRecord->dwMediaType != FIX_ENDIAN(dwMSData[2])) 04977 { 04978 return NOMATCH; 04979 } 04980 } 04981 } 04982 04983 dwSize = sizeof(dwMSData); 04984 if (SET(pEnumRecord, ET_DITHERMODE)) 04985 { 04986 if (GetColorProfileElement(hProfile, TAG_MS02, 0, &dwSize, dwMSData, &bReference)) 04987 { 04988 rc = EXACT_MATCH; // Assume exact match 04989 04990 if (pEnumRecord->dwDitheringMode != FIX_ENDIAN(dwMSData[2])) 04991 { 04992 return NOMATCH; 04993 } 04994 } 04995 } 04996 04997 dwSize = sizeof(dwMSData); 04998 if (SET(pEnumRecord, ET_RESOLUTION)) 04999 { 05000 if (GetColorProfileElement(hProfile, TAG_MS03, 0, &dwSize, dwMSData, &bReference)) 05001 { 05002 rc = EXACT_MATCH; // Assume exact match 05003 05004 if (pEnumRecord->dwResolution[0] != FIX_ENDIAN(dwMSData[2]) || 05005 pEnumRecord->dwResolution[1] != FIX_ENDIAN(dwMSData[3])) 05006 { 05007 return NOMATCH; 05008 } 05009 } 05010 } 05011 } 05012 05013 EndCheckResMedHftnMatch: 05014 05015 if (pDevSettings) 05016 { 05017 GlobalFreePtr(pDevSettings); 05018 } 05019 05020 return rc; 05021 } 05022 05023 05024 BOOL 05025 DwordMatches( 05026 PSETTINGS pSetting, 05027 DWORD dwValue 05028 ) 05029 { 05030 DWORD i, iMax; 05031 PDWORD pValue; 05032 05033 dwValue = FIX_ENDIAN(dwValue); // so we don't have to do this in the loop 05034 05035 // 05036 // Go through all the values. If any of them match, return TRUE. 05037 // 05038 05039 pValue = &pSetting->Value[0]; 05040 iMax = FIX_ENDIAN(pSetting->nValues); 05041 for (i=0; i<iMax; i++) 05042 { 05043 if (dwValue == *pValue) 05044 { 05045 return TRUE; 05046 } 05047 05048 pValue++; // We know that it is a DWORD 05049 } 05050 05051 return FALSE; 05052 } 05053 05054 05055 BOOL 05056 QwordMatches( 05057 PSETTINGS pSetting, 05058 PDWORD pdwValue 05059 ) 05060 { 05061 DWORD i, iMax, dwValue1, dwValue2; 05062 PDWORD pValue; 05063 05064 dwValue1 = FIX_ENDIAN(*pdwValue); // so we don't have to do this in the loop 05065 dwValue2 = FIX_ENDIAN(*(pdwValue+1)); 05066 05067 // 05068 // Go through all the values. If any of them match, return TRUE. 05069 // 05070 05071 pValue = &pSetting->Value[0]; 05072 iMax = FIX_ENDIAN(pSetting->nValues); 05073 for (i=0; i<iMax; i++) 05074 { 05075 if ((dwValue1 == *pValue) && (dwValue2 == *(pValue + 1))) 05076 { 05077 return TRUE; 05078 } 05079 05080 pValue += 2; // We know that it is a QWORD 05081 } 05082 05083 return FALSE; 05084 } 05085 05086 05087 /****************************************************************************** 05088 * 05089 * OpenPrtr 05090 * 05091 * Function: 05092 * On Memphis, we cannot call OpenPrinter() because it calls into 16-bit 05093 * code, so if we call this function from GDI-16, we deadlock. So we 05094 * look into the registry directly. 05095 * 05096 * Arguments: 05097 * pDeviceName - pointer to name of the device 05098 * phDevice - pointer that receives the handle. 05099 * pDummy - dummy parameter 05100 * 05101 * Returns: 05102 * TRUE if successful, FALSE otherwise 05103 * 05104 ******************************************************************************/ 05105 05106 BOOL WINAPI 05107 OpenPrtr( 05108 PTSTR pDeviceName, 05109 LPHANDLE phDevice, 05110 PTSTR pDummy 05111 ) 05112 { 05113 #if !defined(_WIN95_) 05114 return OpenPrinter(pDeviceName, phDevice, (LPPRINTER_DEFAULTS)pDummy); 05115 #else 05116 HKEY hkDevice = NULL; // printers branch of registry 05117 HKEY hkPrtr = NULL; // Friendly name branch of registry 05118 DWORD dwErr; // error code 05119 BOOL rc = FALSE; // return code 05120 05121 *phDevice = NULL; 05122 05123 if (((dwErr = RegOpenKey(HKEY_LOCAL_MACHINE, gszRegPrinter, &hkDevice)) != ERROR_SUCCESS) || 05124 ((dwErr = RegOpenKey(hkDevice, pDeviceName, &hkPrtr)) != ERROR_SUCCESS) || 05125 ((dwErr = RegOpenKey(hkPrtr, gszPrinterData, (HKEY *)phDevice)) != ERROR_SUCCESS)) 05126 { 05127 WARNING((__TEXT("Cannot open printer data branch of registry for %s: %d\n"), pDeviceName, dwErr)); 05128 SetLastError(dwErr); 05129 goto EndOpenPrtr; 05130 } 05131 05132 rc = TRUE; 05133 05134 EndOpenPrtr: 05135 if (hkDevice) 05136 { 05137 RegCloseKey(hkDevice); 05138 } 05139 if (hkPrtr) 05140 { 05141 RegCloseKey(hkPrtr); 05142 } 05143 05144 return rc; 05145 #endif 05146 } 05147 05148 05149 /****************************************************************************** 05150 * 05151 * ClosePrtr 05152 * 05153 * Function: 05154 * This function closes the printer handle opened by OpenPrtr. 05155 * 05156 * Arguments: 05157 * hDevice - open handle 05158 * 05159 * Returns: 05160 * TRUE if successful, FALSE otherwise 05161 * 05162 ******************************************************************************/ 05163 05164 05165 BOOL WINAPI 05166 ClosePrtr( 05167 HANDLE hDevice 05168 ) 05169 { 05170 #if !defined(_WIN95_) 05171 return ClosePrinter(hDevice); 05172 #else 05173 DWORD dwErr; 05174 05175 dwErr = RegCloseKey((HKEY)hDevice); 05176 SetLastError(dwErr); 05177 return dwErr == ERROR_SUCCESS; 05178 #endif 05179 } 05180 05181 05182 /****************************************************************************** 05183 * 05184 * GetPrtrData 05185 * 05186 * Function: 05187 * This functions returns ICM data stored with the printer instance 05188 * 05189 * Arguments: 05190 * hDevice - open printer handle 05191 * pKey - registry key for compatibility with GetPrinterDataEx 05192 * pName - name of registry value 05193 * pdwType - pointer to dword that receives type of value 05194 * pData - pointer to buffer to receive data 05195 * dwSize - size of buffer 05196 * pdwNeeded - on return, this has size of buffer filled/needed 05197 * 05198 * Returns: 05199 * ERROR_SUCCESS if successful, error code otherwise 05200 * 05201 ******************************************************************************/ 05202 05203 DWORD WINAPI 05204 GetPrtrData( 05205 HANDLE hDevice, 05206 PTSTR pKey, 05207 PTSTR pName, 05208 PDWORD pdwType, 05209 PBYTE pData, 05210 DWORD dwSize, 05211 PDWORD pdwNeeded 05212 ) 05213 { 05214 #if !defined(_WIN95_) 05215 return GetPrinterDataEx(hDevice, pKey, pName, pdwType, pData, dwSize, pdwNeeded); 05216 #else 05217 *pdwNeeded = dwSize; 05218 05219 return RegQueryValueEx((HKEY)hDevice, pName, 0, NULL, pData, pdwNeeded); 05220 #endif 05221 } 05222 05223 05224 /****************************************************************************** 05225 * 05226 * SetPrtrData 05227 * 05228 * Function: 05229 * This functions stores ICM data with the printer instance 05230 * 05231 * Arguments: 05232 * hDevice - open printer handle 05233 * pKey - registry key for compatibility with SetPrinterDataEx 05234 * pName - name of registry value 05235 * dwType - type of value 05236 * pData - pointer to data buffer 05237 * dwSize - size of buffer 05238 * 05239 * Returns: 05240 * ERROR_SUCCESS if successful, error code otherwise 05241 * 05242 ******************************************************************************/ 05243 05244 DWORD WINAPI 05245 SetPrtrData( 05246 HANDLE hDevice, 05247 PTSTR pKey, 05248 PTSTR pName, 05249 DWORD dwType, 05250 PBYTE pData, 05251 DWORD dwSize 05252 ) 05253 { 05254 #if !defined(_WIN95_) 05255 return SetPrinterDataEx(hDevice, pKey, pName, dwType, pData, dwSize); 05256 #else 05257 return RegSetValueEx((HKEY)hDevice, pName, 0, dwType, pData, dwSize); 05258 #endif 05259 } 05260 05261 05262 /****************************************************************************** 05263 * 05264 * OpenMonitor 05265 * 05266 * Function: 05267 * This function returns a handle to the monitor 05268 * 05269 * Arguments: 05270 * pDeviceName - pointer to name of the device 05271 * phDevice - pointer that receives the handle. 05272 * pDummy - dummy parameter 05273 * 05274 * Returns: 05275 * TRUE if successful, FALSE otherwise 05276 * 05277 ******************************************************************************/ 05278 05279 BOOL WINAPI 05280 OpenMonitor( 05281 PTSTR pDeviceName, 05282 LPHANDLE phDevice, 05283 PTSTR pDummy 05284 ) 05285 { 05286 #ifdef _WIN95_ 05287 05288 // 05289 // For Windows 9x platform. 05290 // 05291 05292 HDEVINFO hDevInfo = INVALID_HANDLE_VALUE; 05293 HKEY hkICM = NULL; 05294 HKEY hkDriver = NULL; // software branch of registry 05295 DWORD dwSize; // size of buffer 05296 TCHAR szName[MAX_PATH]; // buffer 05297 BOOL rc = FALSE; // return value 05298 SP_DEVINFO_DATA spdid; 05299 int i; // instance counter 05300 05301 if (!LoadSetupAPIDll()) 05302 { 05303 WARNING((__TEXT("Error loading setupapi.dll: %d\n"), GetLastError())); 05304 return FALSE; 05305 } 05306 05307 hDevInfo = (*fpSetupDiGetClassDevs)((LPGUID)&GUID_DEVCLASS_MONITOR, NULL, NULL, DIGCF_PRESENT); 05308 05309 if (hDevInfo == INVALID_HANDLE_VALUE) 05310 { 05311 WARNING((__TEXT("Error getting hDevInfo: %d\n"), GetLastError())); 05312 goto EndOpenMonitor; 05313 } 05314 05315 i = 0; 05316 while (! rc) 05317 { 05318 ZeroMemory(&spdid, sizeof(SP_DEVINFO_DATA)); 05319 spdid.cbSize = sizeof(SP_DEVINFO_DATA); 05320 if (! (*fpSetupDiEnumDeviceInfo)(hDevInfo, i, &spdid)) 05321 { 05322 if (i == 0 && !lstrcmpi(pDeviceName, gszDisplay)) 05323 { 05324 // 05325 // PnP support not in - open ICM key in registry 05326 // 05327 05328 TCHAR szICMMonitorData[] = __TEXT("ICMMonitorData"); 05329 05330 WARNING((__TEXT("PnP support absent - Using DISPLAY\n"))); 05331 05332 // 05333 // Open the registry path where monitor data is kept 05334 // 05335 05336 if ((RegOpenKey(HKEY_LOCAL_MACHINE, gszICMRegPath, &hkICM) != ERROR_SUCCESS) || 05337 (RegCreateKey(hkICM, szICMMonitorData, &hkDriver) != ERROR_SUCCESS)) 05338 { 05339 WARNING((__TEXT("Cannot open ICMMonitorData branch of registry\n"))); 05340 goto EndOpenMonitor; 05341 } 05342 rc = TRUE; 05343 } 05344 break; 05345 } 05346 05347 // 05348 // Get PnP ID. Check and see if the monitor name matches it. 05349 // 05350 05351 dwSize = sizeof(szName); 05352 if ((*fpSetupDiGetDeviceInstanceId)(hDevInfo, &spdid, szName, dwSize, NULL) && 05353 ! lstrcmp(szName, pDeviceName)) 05354 { 05355 hkDriver = (*fpSetupDiOpenDevRegKey)(hDevInfo, &spdid, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS); 05356 if (hkDriver == INVALID_HANDLE_VALUE) 05357 { 05358 WARNING((__TEXT("Could not open monitor s/w key for all access\n"))); 05359 hkDriver = (*fpSetupDiOpenDevRegKey)(hDevInfo, &spdid, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ); 05360 if (hkDriver == INVALID_HANDLE_VALUE) 05361 { 05362 WARNING((__TEXT("Error opening s/w registry key for read access: %x\n"), GetLastError())); 05363 goto EndOpenMonitor; 05364 } 05365 } 05366 05367 rc = TRUE; 05368 } 05369 05370 i++; 05371 } 05372 05373 EndOpenMonitor: 05374 05375 if (hkICM) 05376 { 05377 RegCloseKey(hkICM); 05378 } 05379 05380 if (hDevInfo != INVALID_HANDLE_VALUE) 05381 { 05382 (*fpSetupDiDestroyDeviceInfoList)(hDevInfo); 05383 } 05384 05385 *phDevice = (HANDLE)hkDriver; 05386 05387 return rc; 05388 05389 #else 05390 05391 // 05392 // For Windows NT (later than 5.0) platform 05393 // 05394 05395 TCHAR szRegPath[MAX_PATH]; 05396 HKEY hkDriver = NULL; 05397 05398 // 05399 // Copy device class root key. 05400 // 05401 05402 lstrcpy(szRegPath,gszDeviceClass); 05403 lstrcat(szRegPath,gszMonitorGUID); 05404 05405 if (!lstrcmpi(pDeviceName, gszDisplay)) 05406 { 05407 WARNING((__TEXT("PnP support absent - Using DISPLAY\n"))); 05408 05409 // 05410 // PnP support not in - just open "0000" device. 05411 // 05412 05413 lstrcat(szRegPath,TEXT("\\0000")); 05414 } 05415 else if (_tcsstr(pDeviceName,gszMonitorGUID)) 05416 { 05417 // 05418 // Extract monitor number from DeviceName 05419 // 05420 05421 TCHAR *pDeviceNumber = _tcsrchr(pDeviceName,TEXT('\\')); 05422 05423 if (pDeviceNumber) 05424 { 05425 lstrcat(szRegPath,pDeviceNumber); 05426 } 05427 else 05428 { 05429 lstrcat(szRegPath,TEXT("\\0000")); 05430 } 05431 } 05432 else 05433 { 05434 // 05435 // This is not valid monitor name. 05436 // 05437 goto EndOpenMonitor; 05438 } 05439 05440 // 05441 // Open the registry path where monitor data is kept 05442 // 05443 05444 if (RegOpenKey(HKEY_LOCAL_MACHINE, szRegPath, &hkDriver) != ERROR_SUCCESS) 05445 { 05446 WARNING((__TEXT("Cannot open %s key\n"),szRegPath)); 05447 hkDriver = NULL; 05448 } 05449 05450 EndOpenMonitor: 05451 05452 *phDevice = (HANDLE) hkDriver; 05453 05454 return (hkDriver != NULL); 05455 05456 #endif // _WIN95_ 05457 } 05458 05459 05460 /****************************************************************************** 05461 * 05462 * CloseMonitor 05463 * 05464 * Function: 05465 * This function closes the monitor handle opened by OpenMonitor 05466 * 05467 * Arguments: 05468 * hDevice - open handle 05469 * 05470 * Returns: 05471 * TRUE if successful, FALSE otherwise 05472 * 05473 ******************************************************************************/ 05474 05475 BOOL WINAPI 05476 CloseMonitor( 05477 HANDLE hDevice 05478 ) 05479 { 05480 DWORD dwErr; 05481 05482 dwErr = RegCloseKey((HKEY)hDevice); 05483 SetLastError(dwErr); 05484 return (dwErr == ERROR_SUCCESS); 05485 } 05486 05487 05488 /****************************************************************************** 05489 * 05490 * GetMonitorData 05491 * 05492 * Function: 05493 * This functions returns ICM data stored with the monitor instance 05494 * 05495 * Arguments: 05496 * hDevice - open monitor handle 05497 * pKey - registry key for compatibility with GetPrinterDataEx 05498 * pName - name of registry value 05499 * pdwType - pointer to dword that receives type of value 05500 * pData - pointer to buffer to receive data 05501 * dwSize - size of buffer 05502 * pdwNeeded - on return, this has size of buffer filled/needed 05503 * 05504 * Returns: 05505 * ERROR_SUCCESS if successful, error code otherwise 05506 * 05507 ******************************************************************************/ 05508 05509 DWORD WINAPI 05510 GetMonitorData( 05511 HANDLE hDevice, 05512 PTSTR pKey, 05513 PTSTR pName, 05514 PDWORD pdwType, 05515 PBYTE pData, 05516 DWORD dwSize, 05517 PDWORD pdwNeeded 05518 ) 05519 { 05520 DWORD dwType, dwTemp; 05521 DWORD rc; 05522 05523 *pdwNeeded = dwSize; 05524 05525 rc = RegQueryValueEx((HKEY)hDevice, pName, 0, &dwType, pData, pdwNeeded); 05526 if (rc == ERROR_SUCCESS || rc == ERROR_MORE_DATA) 05527 { 05528 if (dwType == REG_SZ) 05529 { 05530 PTSTR pFilename; 05531 05532 // 05533 // Old style value, convert to double null terminated binary 05534 // 05535 05536 if (pData) 05537 { 05538 pFilename = GetFilenameFromPath((PTSTR)pData); 05539 if (pFilename != (PTSTR)pData) 05540 { 05541 lstrcpy((PTSTR)pData, pFilename); 05542 } 05543 *pdwNeeded = lstrlen((PTSTR)pData) * sizeof(TCHAR); 05544 } 05545 05546 *pdwNeeded += sizeof(TCHAR); // for double NULL termination 05547 05548 if ((dwSize >= *pdwNeeded) && pData) 05549 { 05550 *((PTSTR)pData + lstrlen((PTSTR)pData) + 1) = '\0'; 05551 05552 // 05553 // Set the profile name in new format 05554 // 05555 05556 RegSetValueEx((HKEY)hDevice, pName, 0, REG_BINARY, pData, (lstrlen((PTSTR)pData)+2)*sizeof(TCHAR)); 05557 } 05558 } 05559 else if (*pdwNeeded == 1) 05560 { 05561 // 05562 // If we have picked up the data and it is a 1 byte non-zero 05563 // value, it is an 1 based index in a list of 05564 // predefined profiles. Deal with this case. 05565 // 05566 // If pData is NULL, then we don't know if it is non-zero or 05567 // not, so we assume it is and ask for a large enough buffer. 05568 // 05569 05570 if (!pData || *pData != 0) 05571 { 05572 // 05573 // Old style 1-based index value 05574 // 05575 05576 if ((dwSize >= MAX_PATH) && pData) 05577 { 05578 HKEY hkICM = NULL; 05579 HKEY hkDevice = NULL; 05580 REGDATA regData; 05581 05582 // 05583 // Make sure buggy inf doesn't crash us 05584 // 05585 05586 if (pData[0] > sizeof(gszDispProfiles)/sizeof(gszDispProfiles[0])) 05587 { 05588 WARNING((__TEXT("Predefined profile index too large: %d\n"), pData[0])); 05589 goto EndCompatMode; 05590 } 05591 05592 lstrcpy((PTSTR)pData, gszDispProfiles[pData[0] - 1]); 05593 *((PTSTR)pData + lstrlen((PTSTR)pData) + 1) = '\0'; 05594 05595 // 05596 // We need to update reference count as it wasn't set up 05597 // using the new API 05598 // 05599 // Open the registry path where profiles are kept 05600 // 05601 05602 if ((RegCreateKey(HKEY_LOCAL_MACHINE, gszICMRegPath, &hkICM) != ERROR_SUCCESS) || 05603 (RegCreateKey(hkICM, __TEXT("mntr"), &hkDevice) != ERROR_SUCCESS)) 05604 { 05605 WARNING((__TEXT("Cannot open ICM\\device branch of registry\n"))); 05606 goto EndCompatMode; 05607 } 05608 05609 // 05610 // If registry data exists, then the profile is already installed, 05611 // in which case, increment use count, otherwise add entry 05612 // 05613 05614 dwTemp = sizeof(REGDATA); 05615 if (RegQueryValueEx(hkDevice, (PTSTR)pData, 0, NULL, (PBYTE)&regData, 05616 &dwTemp) == ERROR_SUCCESS) 05617 { 05618 regData.dwRefCount++; 05619 } 05620 else 05621 { 05622 regData.dwRefCount = 1; 05623 regData.dwManuID = 'enon'; // it is our profile 05624 regData.dwModelID = 'enon'; 05625 } 05626 05627 if (RegSetValueEx(hkDevice, (PTSTR)pData, 0, REG_BINARY, 05628 (PBYTE)&regData, sizeof(REGDATA)) != ERROR_SUCCESS) 05629 { 05630 WARNING((__TEXT("Error setting registry value\n"))); 05631 goto EndCompatMode; 05632 } 05633 05634 // 05635 // Set the profile name in new format 05636 // 05637 05638 RegSetValueEx((HKEY)hDevice, pName, 0, REG_BINARY, pData, 05639 (lstrlen((PTSTR)pData) + 2)*sizeof(TCHAR)); 05640 05641 EndCompatMode: 05642 if (hkICM) 05643 { 05644 RegCloseKey(hkICM); 05645 } 05646 if (hkDevice) 05647 { 05648 RegCloseKey(hkDevice); 05649 } 05650 } 05651 *pdwNeeded = MAX_PATH; 05652 } 05653 } 05654 } 05655 05656 if ((rc == ERROR_SUCCESS) && (*pdwNeeded > dwSize)) 05657 { 05658 rc = ERROR_MORE_DATA; 05659 } 05660 05661 return rc; 05662 } 05663 05664 05665 /****************************************************************************** 05666 * 05667 * SetMonitorData 05668 * 05669 * Function: 05670 * This functions stores ICM data with the monitor instance 05671 * 05672 * Arguments: 05673 * hDevice - open monitor handle 05674 * pKey - registry key for compatibility with SetPrinterDataEx 05675 * pName - name of registry value 05676 * dwType - type of value 05677 * pData - pointer to data buffer 05678 * dwSize - size of buffer 05679 * 05680 * Returns: 05681 * ERROR_SUCCESS if successful, error code otherwise 05682 * 05683 ******************************************************************************/ 05684 05685 DWORD WINAPI 05686 SetMonitorData( 05687 HANDLE hDevice, 05688 PTSTR pKey, 05689 PTSTR pName, 05690 DWORD dwType, 05691 PBYTE pData, 05692 DWORD dwSize 05693 ) 05694 { 05695 return RegSetValueEx((HKEY)hDevice, pName, 0, dwType, pData, dwSize); 05696 } 05697 05698 05699 /****************************************************************************** 05700 * 05701 * OpenScanner 05702 * 05703 * Function: 05704 * This function returns a handle to the scanner 05705 * 05706 * Arguments: 05707 * pDeviceName - pointer to name of the device 05708 * phDevice - pointer that receives the handle. 05709 * pDummy - dummy parameter 05710 * 05711 * Returns: 05712 * TRUE 05713 * 05714 ******************************************************************************/ 05715 05716 BOOL WINAPI 05717 OpenScanner( 05718 PTSTR pDeviceName, 05719 LPHANDLE phDevice, 05720 PTSTR pDummy 05721 ) 05722 { 05723 PFNSTICREATEINSTANCE pStiCreateInstance; 05724 PSCANNERDATA psd = NULL; 05725 HRESULT hres; 05726 BOOL bRc = FALSE; 05727 05728 if (!(psd = (PSCANNERDATA)MemAlloc(sizeof(SCANNERDATA)))) 05729 { 05730 WARNING((__TEXT("Error allocating memory for scanner data\n"))); 05731 return FALSE; 05732 } 05733 05734 if (!(psd->pDeviceName = MemAlloc((lstrlen(pDeviceName) + 1) * sizeof(WCHAR)))) 05735 { 05736 WARNING((__TEXT("Error allocating memory for scanner name\n"))); 05737 goto EndOpenScanner; 05738 } 05739 05740 #ifdef UNICODE 05741 lstrcpy(psd->pDeviceName, pDeviceName); 05742 #else 05743 if (! ConvertToUnicode(pDeviceName, &psd->pDeviceName, FALSE)) 05744 { 05745 WARNING((__TEXT("Error converting scanner name to Unicode\n"))); 05746 goto EndOpenScanner; 05747 } 05748 #endif 05749 05750 if (!(psd->hModule = LoadLibrary(gszStiDll))) 05751 { 05752 WARNING((__TEXT("Error loading sti.dll: %d\n"), GetLastError())); 05753 goto EndOpenScanner; 05754 } 05755 05756 if (!(pStiCreateInstance = (PFNSTICREATEINSTANCE)GetProcAddress(psd->hModule, gszStiCreateInstance))) 05757 { 05758 WARNING((__TEXT("Error getting proc StiCreateInstance\n"))); 05759 goto EndOpenScanner; 05760 } 05761 05762 hres = (*pStiCreateInstance)(GetModuleHandle(NULL), STI_VERSION, &psd->pSti, NULL); 05763 05764 if (FAILED(hres)) 05765 { 05766 WARNING((__TEXT("Error creating sti instance: %d\n"), hres)); 05767 goto EndOpenScanner; 05768 } 05769 05770 *phDevice = (HANDLE)psd; 05771 05772 bRc = TRUE; 05773 05774 EndOpenScanner: 05775 05776 if (!bRc && psd) 05777 { 05778 CloseScanner((HANDLE)psd); 05779 } 05780 05781 return bRc; 05782 } 05783 05784 05785 /****************************************************************************** 05786 * 05787 * CloseScanner 05788 * 05789 * Function: 05790 * This function closes the monitor handle opened by OpenMonitor 05791 * 05792 * Arguments: 05793 * hDevice - handle of device 05794 * 05795 * Returns: 05796 * TRUE 05797 * 05798 ******************************************************************************/ 05799 05800 BOOL WINAPI 05801 CloseScanner( 05802 HANDLE hDevice 05803 ) 05804 { 05805 PSCANNERDATA psd = (PSCANNERDATA)hDevice; 05806 05807 if (psd) 05808 { 05809 if (psd->pSti) 05810 { 05811 psd->pSti->lpVtbl->Release(psd->pSti); 05812 } 05813 05814 if (psd->pDeviceName) 05815 { 05816 MemFree(psd->pDeviceName); 05817 } 05818 05819 if (psd->hModule) 05820 { 05821 FreeLibrary(psd->hModule); 05822 } 05823 05824 MemFree(psd); 05825 } 05826 05827 return TRUE; 05828 } 05829 05830 05831 /****************************************************************************** 05832 * 05833 * GetScannerData 05834 * 05835 * Function: 05836 * This functions returns ICM data stored with the scannerr instance 05837 * 05838 * Arguments: 05839 * hDevice - open scanner handle 05840 * pKey - registry key for compatibility with GetPrinterDataEx 05841 * pName - name of registry value 05842 * pdwType - pointer to dword that receives type of value 05843 * pData - pointer to buffer to receive data 05844 * dwSize - size of buffer 05845 * pdwNeeded - on return, this has size of buffer filled/needed 05846 * 05847 * Returns: 05848 * ERROR_SUCCESS if successful, error code otherwise 05849 * 05850 ******************************************************************************/ 05851 05852 DWORD WINAPI 05853 GetScannerData( 05854 HANDLE hDevice, 05855 PTSTR pKey, 05856 PTSTR pName, 05857 PDWORD pdwType, 05858 PBYTE pData, 05859 DWORD dwSize, 05860 PDWORD pdwNeeded 05861 ) 05862 { 05863 PSCANNERDATA psd = (PSCANNERDATA)hDevice; 05864 HRESULT hres; 05865 #ifndef UNICODE 05866 PWSTR pwszName; 05867 05868 // 05869 // STI interface "ALWAYS" expects Unicode. 05870 // 05871 hres = ConvertToUnicode(pName, &pwszName, TRUE); 05872 05873 if (!hres) 05874 { 05875 return (ERROR_INVALID_PARAMETER); 05876 } 05877 05878 pName = (PSTR)pwszName; 05879 05880 #endif 05881 05882 *pdwNeeded = dwSize; 05883 05884 hres = psd->pSti->lpVtbl->GetDeviceValue(psd->pSti, psd->pDeviceName, (PWSTR)pName, pdwType, pData, pdwNeeded); 05885 05886 #ifndef UNICODE 05887 05888 MemFree(pwszName); 05889 05890 #endif 05891 05892 return hres; 05893 } 05894 05895 05896 /****************************************************************************** 05897 * 05898 * SetScannerData 05899 * 05900 * Function: 05901 * This functions stores ICM data with the scanner instance 05902 * 05903 * Arguments: 05904 * hDevice - open scanner handle 05905 * pKey - registry key for compatibility with SetPrinterDataEx 05906 * pName - name of registry value 05907 * dwType - type of value 05908 * pData - pointer to data buffer 05909 * dwSize - size of buffer 05910 * 05911 * Returns: 05912 * ERROR_SUCCESS if successful, error code otherwise 05913 * 05914 ******************************************************************************/ 05915 05916 DWORD WINAPI 05917 SetScannerData( 05918 HANDLE hDevice, 05919 PTSTR pKey, 05920 PTSTR pName, 05921 DWORD dwType, 05922 PBYTE pData, 05923 DWORD dwSize 05924 ) 05925 { 05926 PSCANNERDATA psd = (PSCANNERDATA)hDevice; 05927 HRESULT hres; 05928 #ifndef UNICODE 05929 PWSTR pwszName; 05930 05931 // 05932 // STI interface "ALWAYS" expects Unicode. 05933 // 05934 hres = ConvertToUnicode(pName, &pwszName, TRUE); 05935 05936 if (!hres) 05937 { 05938 return (ERROR_INVALID_PARAMETER); 05939 } 05940 05941 pName = (PSTR)pwszName; 05942 05943 #endif 05944 05945 hres = psd->pSti->lpVtbl->SetDeviceValue(psd->pSti, psd->pDeviceName, (PWSTR)pName, dwType, pData, dwSize); 05946 05947 #ifndef UNICODE 05948 05949 MemFree(pwszName); 05950 05951 #endif 05952 05953 return hres; 05954 } 05955 05956 // 05957 // Internal functions 05958 // 05959 05960 BOOL WINAPI 05961 InternalGetDeviceConfig( 05962 LPCTSTR pDeviceName, 05963 DWORD dwDeviceClass, 05964 DWORD dwConfigType, 05965 PVOID pConfigData, 05966 PDWORD pdwSize 05967 ) 05968 { 05969 DWORD dwDataType; 05970 DWORD dwSizeRequired = 0; 05971 BOOL rc = FALSE; 05972 05973 switch (dwConfigType) 05974 { 05975 case MSCMS_PROFILE_ENUM_MODE: 05976 05977 dwDataType = DEVICE_PROFILE_ENUMMODE; 05978 break; 05979 05980 default: 05981 05982 WARNING((__TEXT("Invalid parameter to InternalGetDeviceConfig\n"))); 05983 SetLastError(ERROR_INVALID_PARAMETER); 05984 return FALSE; 05985 } 05986 05987 // 05988 // Query the size of the data. 05989 // 05990 05991 if (GetDeviceData(pDeviceName,dwDeviceClass,dwDataType,NULL,&dwSizeRequired,FALSE)) 05992 { 05993 if ((dwSizeRequired <= *pdwSize) && (pConfigData != NULL)) 05994 { 05995 // 05996 // If buffer is enough, get the data. 05997 // 05998 05999 if (GetDeviceData(pDeviceName,dwDeviceClass,dwDataType, 06000 (PVOID *)&pConfigData,pdwSize,FALSE)) 06001 { 06002 rc = TRUE; 06003 } 06004 else 06005 { 06006 WARNING((__TEXT("Failed on GetDeviceData to query data\n"))); 06007 SetLastError(ERROR_INVALID_PARAMETER); 06008 } 06009 } 06010 else 06011 { 06012 // 06013 // Return nessesary buffer size to caller. 06014 // 06015 06016 *pdwSize = dwSizeRequired; 06017 SetLastError(ERROR_INSUFFICIENT_BUFFER); 06018 } 06019 } 06020 else 06021 { 06022 WARNING((__TEXT("Failed on GetDeviceData to query data size\n"))); 06023 SetLastError(ERROR_INVALID_PARAMETER); 06024 } 06025 06026 return rc; 06027 } 06028 06029 BOOL WINAPI 06030 InternalSetDeviceConfig( 06031 LPCTSTR pDeviceName, 06032 DWORD dwDeviceClass, 06033 DWORD dwConfigType, 06034 PVOID pConfigData, 06035 DWORD dwSize 06036 ) 06037 { 06038 DWORD dwDataType; 06039 06040 switch (dwConfigType) 06041 { 06042 case MSCMS_PROFILE_ENUM_MODE: 06043 06044 dwDataType = DEVICE_PROFILE_ENUMMODE; 06045 break; 06046 06047 default: 06048 06049 WARNING((__TEXT("Invalid parameter to InternalGetDeviceConfig\n"))); 06050 SetLastError(ERROR_INVALID_PARAMETER); 06051 return FALSE; 06052 } 06053 06054 // 06055 // Save the data. 06056 // 06057 06058 return (SetDeviceData(pDeviceName,dwDeviceClass,dwDataType,pConfigData,dwSize)); 06059 } 06060 06061 #ifdef _WIN95_ 06062 06063 // 06064 // Win9x specific functions are here. 06065 // 06066 06067 BOOL 06068 LoadSetupAPIDll( 06069 VOID 06070 ) 06071 { 06072 EnterCriticalSection(&critsec); 06073 06074 if (ghModSetupAPIDll == NULL) 06075 { 06076 ghModSetupAPIDll = LoadLibrary(TEXT("setupapi.dll")); 06077 06078 if (ghModSetupAPIDll) 06079 { 06080 fpSetupDiOpenDevRegKey = (FP_SetupDiOpenDevRegKey) 06081 GetProcAddress(ghModSetupAPIDll,"SetupDiOpenDevRegKey"); 06082 fpSetupDiDestroyDeviceInfoList = (FP_SetupDiDestroyDeviceInfoList) 06083 GetProcAddress(ghModSetupAPIDll,"SetupDiDestroyDeviceInfoList"); 06084 fpSetupDiEnumDeviceInfo = (FP_SetupDiEnumDeviceInfo) 06085 GetProcAddress(ghModSetupAPIDll,"SetupDiEnumDeviceInfo"); 06086 fpSetupDiGetDeviceInstanceId = (FP_SetupDiGetDeviceInstanceId) 06087 GetProcAddress(ghModSetupAPIDll,"SetupDiGetDeviceInstanceIdA"); 06088 fpSetupDiGetClassDevs = (FP_SetupDiGetClassDevs) 06089 GetProcAddress(ghModSetupAPIDll,"SetupDiGetClassDevsA"); 06090 06091 if ((fpSetupDiOpenDevRegKey == NULL) || 06092 (fpSetupDiDestroyDeviceInfoList == NULL) || 06093 (fpSetupDiEnumDeviceInfo == NULL) || 06094 (fpSetupDiGetDeviceInstanceId == NULL) || 06095 (fpSetupDiGetClassDevs == NULL)) 06096 { 06097 WARNING((__TEXT("Could not find Export function in setupapi.dll\n"))); 06098 06099 FreeLibrary(ghModSetupAPIDll); 06100 ghModSetupAPIDll = NULL; 06101 } 06102 } 06103 } 06104 06105 LeaveCriticalSection(&critsec); 06106 06107 return (!!ghModSetupAPIDll); 06108 } 06109 06110 #else 06111 06112 // 06113 // Win NT specific functions are here. 06114 // 06115 06116 VOID 06117 ChangeICMSetting( 06118 LPCTSTR pMachineName, 06119 LPCTSTR pDeviceName, 06120 DWORD dwICMMode 06121 ) 06122 { 06123 PRINTER_INFO_8 *ppi8; 06124 PRINTER_INFO_9 *ppi9; 06125 PRINTER_DEFAULTS pd; 06126 HANDLE hPrinter; 06127 DWORD dwSize; 06128 BYTE temp[2*1024]; // sufficient for devmode 06129 06130 pd.pDatatype = NULL; 06131 pd.pDevMode = NULL; 06132 pd.DesiredAccess = PRINTER_ALL_ACCESS; 06133 06134 if (!OpenPrinter((PTSTR)pDeviceName, &hPrinter, &pd)) 06135 return; 06136 06137 // 06138 // Get and update system devmode 06139 // 06140 06141 ppi8 = (PRINTER_INFO_8 *)&temp; 06142 if (GetPrinter(hPrinter, 8, (PBYTE)ppi8, sizeof(temp), &dwSize) && 06143 ppi8->pDevMode) 06144 { 06145 switch (dwICMMode) 06146 { 06147 case ICM_ON: 06148 case ICM_OFF: 06149 ppi8->pDevMode->dmFields |= DM_ICMMETHOD; 06150 if (dwICMMode == ICM_ON) 06151 ppi8->pDevMode->dmICMMethod = DMICMMETHOD_SYSTEM; 06152 else 06153 ppi8->pDevMode->dmICMMethod = DMICMMETHOD_NONE; 06154 SetPrinter(hPrinter, 8, (PBYTE)ppi8, 0); 06155 break; 06156 } 06157 } 06158 06159 // 06160 // If the user has a per-user devmode, update this as well 06161 // 06162 06163 ppi9 = (PRINTER_INFO_9 *)&temp; 06164 if (GetPrinter(hPrinter, 9, (PBYTE)ppi9, sizeof(temp), &dwSize) && 06165 ppi9->pDevMode) 06166 { 06167 switch (dwICMMode) 06168 { 06169 case ICM_ON: 06170 case ICM_OFF: 06171 ppi9->pDevMode->dmFields |= DM_ICMMETHOD; 06172 if (dwICMMode == ICM_ON) 06173 ppi9->pDevMode->dmICMMethod = DMICMMETHOD_SYSTEM; 06174 else 06175 ppi9->pDevMode->dmICMMethod = DMICMMETHOD_NONE; 06176 SetPrinter(hPrinter, 9, (PBYTE)ppi9, 0); 06177 break; 06178 } 06179 } 06180 06181 ClosePrinter(hPrinter); 06182 06183 return; 06184 } 06185 06186 #endif // _WIN95_ 06187 06188

Generated on Sat May 15 19:41:30 2004 for test by doxygen 1.3.7