Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

902 lines
24 KiB

  1. /******************************************************************************
  2. Source File: ICC Profile.CPP
  3. This implements the class we use to encapsulate everything we will ever care
  4. to know about a profile, including the classes we need to support
  5. associations and the like.
  6. Copyright (c) 1996, 1997 by Microsoft Corporation. All Rights Reserved.
  7. A Pretty Penny Enterprises Production
  8. Change History:
  9. 10-31-96 A-RobKj (Pretty Penny Enterprises) began encapsulating it
  10. 12-04-96 A-RobKj Added the CProfileArray and CAllDeviceList classes
  11. 12-13-96 A-RobKj Modified for faster operation (more lazy evaluation,
  12. and common DLL-wide database for installation checks)
  13. Also moved CDeviceList derived classes to the header, so
  14. I can use them other places, as well...
  15. 01-07-97 KjelgaardR@acm.org Fixed CProfileArray::Empty- wasn't setting Next
  16. object pointer to NULL after deleting said object (Fixed GP fault).
  17. 01-08-97 KjelgaardR@acm.org Modified printer enumeration routine to only
  18. enumerate color models (uses Global utility function).
  19. ******************************************************************************/
  20. #include "ICMUI.H"
  21. #include <shlobj.h>
  22. #include "shellext.h"
  23. #include "..\mscms\sti.h"
  24. typedef HRESULT (__stdcall *PFNSTICREATEINSTANCE)(HINSTANCE, DWORD, PSTI*, LPDWORD);
  25. TCHAR gszStiDll[] = __TEXT("sti.dll");
  26. char gszStiCreateInstance[] = "StiCreateInstance";
  27. // Printer DeviceEnumeration method
  28. void CPrinterList::Enumerate() {
  29. #if !defined(_WIN95_) // CPrinterList::Enumetate()
  30. // Enumerate all local printers
  31. DWORD dwcNeeded, dwcReturned;
  32. EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 4, NULL, 0, &dwcNeeded,
  33. &dwcReturned);
  34. union {
  35. PBYTE pBuff;
  36. PPRINTER_INFO_4 ppi4;
  37. };
  38. pBuff = new BYTE[dwcNeeded];
  39. while (pBuff && !EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 4, pBuff,
  40. dwcNeeded, &dwcNeeded, &dwcReturned) &&
  41. GetLastError() == ERROR_MORE_DATA) {
  42. delete [] pBuff;
  43. pBuff = new BYTE[dwcNeeded];
  44. }
  45. if (pBuff) {
  46. for (unsigned u = 0; u < dwcReturned; u++)
  47. if (CGlobals::ThisIsAColorPrinter(ppi4[u].pPrinterName)) {
  48. m_csaDeviceNames.Add(ppi4[u].pPrinterName);
  49. m_csaDisplayNames.Add(ppi4[u].pPrinterName);
  50. }
  51. delete [] pBuff;
  52. }
  53. // Now, enumerate all the connected printers
  54. EnumPrinters(PRINTER_ENUM_CONNECTIONS, NULL, 4, NULL, 0, &dwcNeeded,
  55. &dwcReturned);
  56. pBuff = new BYTE[dwcNeeded];
  57. while (pBuff && !EnumPrinters(PRINTER_ENUM_CONNECTIONS, NULL, 4, pBuff,
  58. dwcNeeded, &dwcNeeded, &dwcReturned) &&
  59. GetLastError() == ERROR_MORE_DATA) {
  60. delete [] pBuff;
  61. pBuff = new BYTE[dwcNeeded];
  62. }
  63. if (!pBuff)
  64. return;
  65. for (unsigned u = 0; u < dwcReturned; u++)
  66. if (CGlobals::ThisIsAColorPrinter(ppi4[u].pPrinterName)) {
  67. m_csaDeviceNames.Add(ppi4[u].pPrinterName);
  68. m_csaDisplayNames.Add(ppi4[u].pPrinterName);
  69. }
  70. delete [] pBuff;
  71. #else
  72. // Enumerate all local printers
  73. DWORD dwcNeeded, dwcReturned;
  74. EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 5, NULL, 0, &dwcNeeded,
  75. &dwcReturned);
  76. union {
  77. PBYTE pBuff;
  78. PPRINTER_INFO_5 ppi5;
  79. };
  80. pBuff = new BYTE[dwcNeeded];
  81. while (pBuff && !EnumPrinters(PRINTER_ENUM_LOCAL, NULL, 5, pBuff,
  82. dwcNeeded, &dwcNeeded, &dwcReturned) &&
  83. GetLastError() == ERROR_MORE_DATA) {
  84. delete [] pBuff;
  85. pBuff = new BYTE[dwcNeeded];
  86. }
  87. if (pBuff) {
  88. for (unsigned u = 0; u < dwcReturned; u++) {
  89. if (CGlobals::ThisIsAColorPrinter(ppi5[u].pPrinterName)) {
  90. m_csaDeviceNames.Add(ppi5[u].pPrinterName);
  91. m_csaDisplayNames.Add(ppi5[u].pPrinterName);
  92. }
  93. }
  94. delete [] pBuff;
  95. }
  96. #endif
  97. }
  98. // Printer Name Validity Check
  99. BOOL CPrinterList::IsValidDeviceName(LPCTSTR lpstrRef) {
  100. if (!lpstrRef) return FALSE;
  101. if (!Count())
  102. Enumerate();
  103. for (unsigned u = 0; u < Count(); u++)
  104. if (!lstrcmpi(m_csaDeviceNames[u], lpstrRef))
  105. break;
  106. return u < Count();
  107. }
  108. // Private monitor enumeration function- note this is ANSI only...
  109. extern "C" BOOL WINAPI EnumerateMonitors(LPBYTE pBuffer, PDWORD pdwcbNeeded,
  110. PDWORD pdwcReturned);
  111. // CMonitor class enumerator
  112. void CMonitorList::Enumerate() {
  113. ULONG ulSerialNumber = 1;
  114. ULONG ulDeviceIndex = 0;
  115. DISPLAY_DEVICE ddPriv;
  116. ddPriv.cb = sizeof(ddPriv);
  117. // Enumurate display adaptor on the system.
  118. while (EnumDisplayDevices(NULL, ulDeviceIndex, &ddPriv, 0))
  119. {
  120. ULONG ulMonitorIndex = 0;
  121. DISPLAY_DEVICE ddPrivMonitor;
  122. ddPrivMonitor.cb = sizeof(ddPrivMonitor);
  123. // then, enumurate monitor device, attached the display adaptor.
  124. while (EnumDisplayDevices(ddPriv.DeviceName, ulMonitorIndex, &ddPrivMonitor, 0))
  125. {
  126. TCHAR DisplayNameBuf[256]; // number: devicename - 256 is good enough.
  127. // Insert PnP id as device name.
  128. m_csaDeviceNames.Add(ddPrivMonitor.DeviceID);
  129. // If this is primary display device, remember it.
  130. if (ddPriv.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
  131. {
  132. m_csPrimaryDeviceName = ddPrivMonitor.DeviceID;
  133. }
  134. // Build display name.
  135. wsprintf(DisplayNameBuf,TEXT("%d. %s"),ulSerialNumber,ddPrivMonitor.DeviceString);
  136. m_csaDisplayNames.Add(DisplayNameBuf);
  137. ulMonitorIndex++;
  138. ulSerialNumber++;
  139. ddPrivMonitor.cb = sizeof(ddPrivMonitor);
  140. }
  141. ulDeviceIndex++;
  142. ddPriv.cb = sizeof(ddPriv);
  143. }
  144. }
  145. // Monitor Name Validity Check
  146. BOOL CMonitorList::IsValidDeviceName(LPCTSTR lpstrRef) {
  147. if (!lpstrRef) return FALSE;
  148. if (!Count())
  149. Enumerate();
  150. for (unsigned u = 0; u < Count(); u++)
  151. if (!lstrcmpi(m_csaDeviceNames[u], lpstrRef))
  152. break;
  153. return u < Count();
  154. }
  155. LPCSTR CMonitorList::DeviceNameToDisplayName(LPCTSTR lpstrRef) {
  156. if (!lpstrRef) return NULL;
  157. if (!Count())
  158. Enumerate();
  159. for (unsigned u = 0; u < Count(); u++)
  160. if (!lstrcmpi(m_csaDeviceNames[u], lpstrRef))
  161. return (LPCSTR)(m_csaDisplayNames[u]);
  162. return NULL;
  163. }
  164. // Scanner DeviceEnumeration method
  165. void CScannerList::Enumerate() {
  166. PFNSTICREATEINSTANCE pStiCreateInstance;
  167. PSTI pSti = NULL;
  168. PSTI_DEVICE_INFORMATION pDevInfo;
  169. PVOID pBuffer = NULL;
  170. HINSTANCE hModule;
  171. HRESULT hres;
  172. DWORD i, dwItemsReturned;
  173. #ifndef UNICODE
  174. char szName[256];
  175. #endif
  176. if (!(hModule = LoadLibrary(gszStiDll)))
  177. {
  178. _RPTF1(_CRT_WARN, "Error loading sti.dll: %d\n",
  179. GetLastError());
  180. return;
  181. }
  182. if (!(pStiCreateInstance = (PFNSTICREATEINSTANCE)GetProcAddress(hModule, gszStiCreateInstance)))
  183. {
  184. _RPTF0(_CRT_WARN, "Error getting proc StiCreateInstance\n");
  185. goto EndEnumerate;
  186. }
  187. hres = (*pStiCreateInstance)(GetModuleHandle(NULL), STI_VERSION, &pSti, NULL);
  188. if (FAILED(hres))
  189. {
  190. _RPTF1(_CRT_WARN, "Error creating sti instance: %d\n", hres);
  191. goto EndEnumerate;
  192. }
  193. hres = pSti->GetDeviceList(0, 0, &dwItemsReturned, &pBuffer);
  194. if (FAILED(hres) || !pBuffer)
  195. {
  196. _RPTF0(_CRT_WARN, "Error getting scanner devices\n");
  197. goto EndEnumerate;
  198. }
  199. pDevInfo = (PSTI_DEVICE_INFORMATION) pBuffer;
  200. for (i=0; i<dwItemsReturned; i++, pDevInfo++)
  201. {
  202. #ifndef UNICODE
  203. DWORD dwLen; // length of Ansi string
  204. BOOL bUsedDefaultChar;
  205. dwLen = (lstrlenW(pDevInfo->pszLocalName) + 1) * sizeof(char);
  206. //
  207. // Convert Unicode name to Ansi
  208. //
  209. if (WideCharToMultiByte(CP_ACP, 0, pDevInfo->szDeviceInternalName, -1, szName,
  210. dwLen, NULL, &bUsedDefaultChar) && ! bUsedDefaultChar)
  211. {
  212. m_csaDeviceNames.Add(szName);
  213. }
  214. else
  215. {
  216. _RPTF0(_CRT_WARN, "Error converting internalName to Unicode name\n");
  217. }
  218. if (WideCharToMultiByte(CP_ACP, 0, pDevInfo->pszLocalName, -1, szName,
  219. dwLen, NULL, &bUsedDefaultChar) && ! bUsedDefaultChar)
  220. {
  221. m_csaDisplayNames.Add(szName);
  222. }
  223. else
  224. {
  225. _RPTF0(_CRT_WARN, "Error converting deviceName to Unicode name\n");
  226. }
  227. #else
  228. m_csaDeviceNames.Add(pDevInfo->szDeviceInternalName);
  229. m_csaDisplayNames.Add(pDevInfo->pszLocalName);
  230. #endif
  231. }
  232. EndEnumerate:
  233. if (pBuffer)
  234. {
  235. LocalFree(pBuffer);
  236. }
  237. if (pSti)
  238. {
  239. pSti->Release();
  240. }
  241. if (hModule)
  242. {
  243. FreeLibrary(hModule);
  244. }
  245. return;
  246. }
  247. // Scanner Name Validity Check
  248. BOOL CScannerList::IsValidDeviceName(LPCTSTR lpstrRef) {
  249. if (!lpstrRef) return FALSE;
  250. if (!Count())
  251. Enumerate();
  252. for (unsigned u = 0; u < Count(); u++)
  253. if (!lstrcmpi(m_csaDeviceNames[u], lpstrRef))
  254. break;
  255. return u < Count();
  256. }
  257. // CAllDeviceList class enumerator
  258. void CAllDeviceList::Enumerate() {
  259. CMonitorList cml;
  260. CPrinterList cpl;
  261. CScannerList csl;
  262. cml.Enumerate();
  263. cpl.Enumerate();
  264. csl.Enumerate();
  265. for (unsigned u = 0; u < cpl.Count(); u++) {
  266. m_csaDeviceNames.Add(cpl.DeviceName(u));
  267. m_csaDisplayNames.Add(cpl.DisplayName(u));
  268. }
  269. for (u = 0; u < cml.Count(); u++) {
  270. m_csaDeviceNames.Add(cml.DeviceName(u));
  271. m_csaDisplayNames.Add(cml.DisplayName(u));
  272. }
  273. for (u = 0; u < csl.Count(); u++) {
  274. m_csaDeviceNames.Add(csl.DeviceName(u));
  275. m_csaDisplayNames.Add(csl.DisplayName(u));
  276. }
  277. }
  278. // Device Name Validity Check
  279. BOOL CAllDeviceList::IsValidDeviceName(LPCTSTR lpstrRef) {
  280. if (!lpstrRef) return FALSE;
  281. if (!Count())
  282. Enumerate();
  283. for (unsigned u = 0; u < Count(); u++)
  284. if (!lstrcmpi(m_csaDeviceNames[u], lpstrRef))
  285. break;
  286. return u < Count();
  287. }
  288. // CProfile member functions
  289. // The following static functions fills the appropriate array using the
  290. // profiles that match the search criteria goven.
  291. void CProfile::Enumerate(ENUMTYPE& et, CStringArray& csaList) {
  292. // Enumerate the existing profiles
  293. DWORD dwBuffer =0, dwcProfiles;
  294. csaList.Empty();
  295. EnumColorProfiles(NULL, &et, NULL, &dwBuffer, &dwcProfiles);
  296. if (!dwBuffer) {
  297. _RPTF2(_CRT_WARN,
  298. "CProfile::Enumerate(String)- empty list- dwBuffer %d Error %d\n",
  299. dwBuffer, GetLastError());
  300. return;
  301. }
  302. union {
  303. PBYTE pbBuffer;
  304. PTSTR pstrBuffer;
  305. };
  306. pbBuffer = new BYTE[dwBuffer];
  307. if (pbBuffer) {
  308. if (EnumColorProfiles(NULL, &et, pbBuffer, &dwBuffer, &dwcProfiles)) {
  309. for (PTSTR pstrMe = pstrBuffer;
  310. dwcProfiles--;
  311. pstrMe += 1 + lstrlen(pstrMe)) {
  312. _RPTF1(_CRT_WARN, "CProfile::Enumerate(String) %s found\n",
  313. pstrMe);
  314. csaList.Add(pstrMe);
  315. }
  316. }
  317. delete [] pbBuffer;
  318. }
  319. }
  320. void CProfile::Enumerate(ENUMTYPE& et, CStringArray& csaList, CStringArray& csaDesc) {
  321. // Enumerate the existing profiles
  322. DWORD dwBuffer =0, dwcProfiles;
  323. csaList.Empty();
  324. EnumColorProfiles(NULL, &et, NULL, &dwBuffer, &dwcProfiles);
  325. if (!dwBuffer) {
  326. _RPTF2(_CRT_WARN,
  327. "CProfile::Enumerate(String)- empty list- dwBuffer %d Error %d\n",
  328. dwBuffer, GetLastError());
  329. return;
  330. }
  331. union {
  332. PBYTE pbBuffer;
  333. PTSTR pstrBuffer;
  334. };
  335. pbBuffer = new BYTE[dwBuffer];
  336. if (pbBuffer) {
  337. if (EnumColorProfiles(NULL, &et, pbBuffer, &dwBuffer, &dwcProfiles)) {
  338. for (PTSTR pstrMe = pstrBuffer;
  339. dwcProfiles--;
  340. pstrMe += 1 + lstrlen(pstrMe)) {
  341. _RPTF1(_CRT_WARN, "CProfile::Enumerate(String) %s found\n",
  342. pstrMe);
  343. CProfile cp(pstrMe);
  344. if (cp.IsValid()) {
  345. CString csDescription = cp.TagContents('desc', 4);
  346. if (csDescription.IsEmpty()) {
  347. csaDesc.Add(pstrMe);
  348. } else {
  349. csaDesc.Add((LPTSTR)csDescription);
  350. }
  351. csaList.Add(pstrMe);
  352. }
  353. }
  354. }
  355. delete [] pbBuffer;
  356. }
  357. }
  358. void CProfile::Enumerate(ENUMTYPE& et, CProfileArray& cpaList) {
  359. // Enumerate the existing profiles
  360. DWORD dwBuffer = 0, dwcProfiles;
  361. cpaList.Empty();
  362. EnumColorProfiles(NULL, &et, NULL, &dwBuffer, &dwcProfiles);
  363. if (!dwBuffer) {
  364. _RPTF2(_CRT_WARN,
  365. "CProfile::Enumerate(Profile)- empty list- dwBuffer %d Error %d\n",
  366. dwBuffer, GetLastError());
  367. return;
  368. }
  369. union {
  370. PBYTE pbBuffer;
  371. PTSTR pstrBuffer;
  372. };
  373. pbBuffer = new BYTE[dwBuffer];
  374. if (pbBuffer) {
  375. if (EnumColorProfiles(NULL, &et, pbBuffer, &dwBuffer, &dwcProfiles)) {
  376. for (PTSTR pstrMe = pstrBuffer;
  377. dwcProfiles--;
  378. pstrMe += 1 + lstrlen(pstrMe)) {
  379. _RPTF1(_CRT_WARN, "CProfile::Enumerate(Profile) %s added\n",
  380. pstrMe);
  381. cpaList.Add(pstrMe);
  382. }
  383. }
  384. delete [] pbBuffer;
  385. }
  386. }
  387. // This retrieves the color directory name. Since it is a const, we whouldn't
  388. // be calling it too often...
  389. const CString CProfile::ColorDirectory() {
  390. TCHAR acDirectory[MAX_PATH];
  391. DWORD dwccDir = MAX_PATH;
  392. GetColorDirectory(NULL, acDirectory, &dwccDir);
  393. return acDirectory;
  394. }
  395. // This checks for profile installation
  396. void CProfile::InstallCheck() {
  397. // Enumerate the existing profiles, so we can see if this one's been
  398. // installed, already.
  399. ENUMTYPE et = {sizeof (ENUMTYPE), ENUM_TYPE_VERSION, 0, NULL};
  400. CStringArray csaWork;
  401. Enumerate(et, csaWork);
  402. for (unsigned u = 0; u < csaWork.Count(); u++)
  403. if (!lstrcmpi(csaWork[u].NameOnly(), m_csName.NameOnly()))
  404. break;
  405. m_bIsInstalled = u < csaWork.Count();
  406. m_bInstallChecked = TRUE;
  407. }
  408. // This Checks for Associated Devices
  409. void CProfile::AssociationCheck() {
  410. m_bAssociationsChecked = TRUE;
  411. // If the profile isn't installed, associations are moot...
  412. if (!IsInstalled())
  413. return;
  414. // The final step is to build a list of associations
  415. ENUMTYPE et = {sizeof (ENUMTYPE), ENUM_TYPE_VERSION, ET_DEVICENAME};
  416. CStringArray csaWork;
  417. for (unsigned u = 0; u < DeviceCount(); u++) {
  418. et.pDeviceName = m_pcdlClass -> DeviceName(u);
  419. Enumerate(et, csaWork);
  420. // We track associations by index into the total device list...
  421. for (unsigned uProfile = 0; uProfile < csaWork.Count(); uProfile++)
  422. if (!lstrcmpi(csaWork[uProfile].NameOnly(), m_csName.NameOnly())){
  423. m_cuaAssociation.Add(u); // Found one!
  424. break;
  425. }
  426. }
  427. }
  428. // This determines the device list of related class...
  429. void CProfile::DeviceCheck() {
  430. // Enumerate the available devices of this type in the csaDevice Array
  431. m_pcdlClass -> Enumerate();
  432. m_bDevicesChecked = TRUE;
  433. }
  434. // Class constructor
  435. CProfile::CProfile(LPCTSTR lpstrTarget) {
  436. _ASSERTE(lpstrTarget && *lpstrTarget);
  437. m_pcdlClass = NULL;
  438. m_bIsInstalled = FALSE;
  439. m_bInstallChecked = FALSE;
  440. m_bDevicesChecked = FALSE;
  441. m_bAssociationsChecked = FALSE;
  442. // First, let's make sure it's the real McCoy
  443. PROFILE prof = { PROFILE_FILENAME,
  444. (LPVOID) lpstrTarget,
  445. (1 + lstrlen(lpstrTarget)) * sizeof(TCHAR)};
  446. m_hprof = OpenColorProfile(&prof, PROFILE_READ,
  447. FILE_SHARE_READ|FILE_SHARE_WRITE,
  448. OPEN_EXISTING);
  449. if (!m_hprof)
  450. return;
  451. if (!GetColorProfileHeader(m_hprof, &m_phThis)) {
  452. CloseColorProfile(m_hprof);
  453. m_hprof = NULL;
  454. return;
  455. }
  456. m_csName = lpstrTarget;
  457. // Init the DeviceList pointer, because it doesn't cost much...
  458. switch (m_phThis.phClass) {
  459. case CLASS_PRINTER:
  460. // Our device list is a printer list
  461. m_pcdlClass = new CPrinterList;
  462. break;
  463. case CLASS_SCANNER:
  464. // Our device list is a scanner list
  465. m_pcdlClass = new CScannerList;
  466. break;
  467. case CLASS_MONITOR:
  468. // Our device list is a monitor list
  469. #if 1 // ALLOW_MONITOR_PROFILE_TO_ANY_DEVICE
  470. m_pcdlClass = new CAllDeviceList;
  471. #else
  472. m_pcdlClass = new CMonitorList;
  473. #endif
  474. break;
  475. case CLASS_COLORSPACE:
  476. // List everything we can count
  477. m_pcdlClass = new CAllDeviceList;
  478. break;
  479. default:
  480. // Use the base device class (i.e., no devices of this type).
  481. m_pcdlClass = new CDeviceList;
  482. }
  483. }
  484. // Destructor
  485. CProfile::~CProfile() {
  486. if (m_hprof)
  487. CloseColorProfile(m_hprof);
  488. if (m_pcdlClass)
  489. delete m_pcdlClass;
  490. }
  491. // Tag retrieval function
  492. LPCSTR CProfile::TagContents(TAGTYPE tt, unsigned uOffset) {
  493. DWORD dwcNeeded = sizeof m_acTag;
  494. BOOL bIgnore;
  495. if (!GetColorProfileElement(m_hprof, tt, 8 + uOffset, &dwcNeeded, m_acTag,
  496. &bIgnore))
  497. return NULL; // Nothing to copy!
  498. else
  499. return m_acTag;
  500. }
  501. // Profile Installation function
  502. BOOL CProfile::Install() {
  503. if (!InstallColorProfile(NULL, m_csName)) {
  504. CGlobals::ReportEx(InstFailedWithName,NULL,FALSE,
  505. MB_OK|MB_ICONEXCLAMATION,1,m_csName.NameAndExtension());
  506. return (FALSE);
  507. } else {
  508. m_bIsInstalled = TRUE;
  509. CGlobals::InvalidateList();
  510. SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_PATH, (LPCTSTR) m_csName, NULL);
  511. _RPTF1(_CRT_WARN, "CProfile::Install %s succeeded\n",
  512. (LPCSTR) m_csName);
  513. return (TRUE);
  514. }
  515. }
  516. // Profile Uninstallation function
  517. void CProfile::Uninstall(BOOL bDelete) {
  518. while (AssociationCount()) { // Dissociate all uses
  519. Dissociate(DeviceName(m_cuaAssociation[0]));
  520. m_cuaAssociation.Remove(0);
  521. }
  522. if (m_hprof)
  523. {
  524. CloseColorProfile(m_hprof);
  525. m_hprof = NULL;
  526. }
  527. if (!UninstallColorProfile(NULL, m_csName.NameAndExtension(), bDelete)) {
  528. CGlobals::ReportEx(UninstFailedWithName,NULL,FALSE,
  529. MB_OK|MB_ICONEXCLAMATION,1,m_csName.NameAndExtension());
  530. } else {
  531. m_bIsInstalled = FALSE;
  532. CGlobals::InvalidateList();
  533. SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_PATH, (LPCTSTR) m_csName, NULL);
  534. _RPTF1(_CRT_WARN, "CProfile::Uninstall %s succeeded\n",
  535. (LPCSTR) m_csName);
  536. }
  537. }
  538. // Association
  539. void CProfile::Associate(LPCTSTR lpstrDevice) {
  540. // if the profile is not installed, install it first.
  541. BOOL bInstalled = FALSE;
  542. // Install profile, if not installed, yet.
  543. if (!IsInstalled()) {
  544. bInstalled = Install();
  545. } else
  546. bInstalled = TRUE;
  547. if (bInstalled) {
  548. if (!AssociateColorProfileWithDevice(NULL, m_csName.NameAndExtension(),
  549. lpstrDevice)) {
  550. CGlobals::ReportEx(AssocFailedWithName,NULL,FALSE,1,
  551. MB_OK|MB_ICONEXCLAMATION,m_csName.NameAndExtension());
  552. } else
  553. _RPTF2(_CRT_WARN, "CProfile::Associate %s with %s succeeded\n",
  554. lpstrDevice, (LPCTSTR) m_csName.NameAndExtension());
  555. }
  556. }
  557. // Dissociation
  558. void CProfile::Dissociate(LPCTSTR lpstrDevice) {
  559. if (!DisassociateColorProfileFromDevice(NULL, m_csName.NameAndExtension(),
  560. lpstrDevice)) {
  561. CGlobals::ReportEx(DisassocFailedWithName,NULL,FALSE,1,
  562. MB_OK|MB_ICONEXCLAMATION,m_csName.NameAndExtension());
  563. } else
  564. _RPTF2(_CRT_WARN, "CProfile::Dissociate %s from %s succeeded\n",
  565. lpstrDevice, (LPCTSTR) m_csName.NameAndExtension());
  566. }
  567. // CProfileArray class- Same basic implementation, different base type.
  568. CProfile *CProfileArray::Borrow() {
  569. CProfile *pcpReturn = m_aStore[0];
  570. memcpy((LPSTR) m_aStore, (LPSTR) (m_aStore + 1),
  571. (ChunkSize() - 1) * sizeof m_aStore[0]);
  572. if (m_ucUsed > ChunkSize())
  573. m_aStore[ChunkSize() - 1] = m_pcpaNext -> Borrow();
  574. else
  575. m_aStore[ChunkSize() - 1] = (CProfile *) NULL;
  576. m_ucUsed--;
  577. if (m_ucUsed <= ChunkSize() && m_pcpaNext) {
  578. delete m_pcpaNext;
  579. m_pcpaNext = NULL;
  580. }
  581. return pcpReturn;
  582. }
  583. CProfileArray::CProfileArray() {
  584. m_ucUsed = 0;
  585. m_pcpaNext = NULL;
  586. memset(m_aStore, 0, sizeof m_aStore);
  587. }
  588. CProfileArray::~CProfileArray() {
  589. Empty();
  590. }
  591. void CProfileArray::Empty() {
  592. if (!m_ucUsed) return;
  593. if (m_pcpaNext) {
  594. delete m_pcpaNext;
  595. m_pcpaNext = NULL;
  596. m_ucUsed = ChunkSize();
  597. }
  598. while (m_ucUsed--)
  599. delete m_aStore[m_ucUsed];
  600. m_ucUsed = 0;
  601. memset(m_aStore, 0, sizeof m_aStore);
  602. }
  603. // Add an item
  604. void CProfileArray::Add(LPCTSTR lpstrNew) {
  605. _ASSERTE(lpstrNew && *lpstrNew);
  606. if (m_ucUsed < ChunkSize()) {
  607. m_aStore[m_ucUsed++] = new CProfile(lpstrNew);
  608. return;
  609. }
  610. // Not enough space! Add another record, if there isn't one
  611. if (!m_pcpaNext)
  612. m_pcpaNext = new CProfileArray;
  613. // Add the profile to the next array (recursive call!)
  614. // Note: if we failed to get memory above, we simply fail to add the
  615. // object.
  616. if (m_pcpaNext) {
  617. m_pcpaNext -> Add(lpstrNew);
  618. m_ucUsed++;
  619. }
  620. }
  621. CProfile *CProfileArray::operator [](unsigned u) const {
  622. return u < ChunkSize() ?
  623. m_aStore[u] : m_pcpaNext -> operator[](u - ChunkSize());
  624. }
  625. void CProfileArray::Remove(unsigned u) {
  626. if (u > m_ucUsed)
  627. return;
  628. if (u >= ChunkSize()) {
  629. m_pcpaNext -> Remove(u - ChunkSize());
  630. return;
  631. }
  632. delete m_aStore[u];
  633. memmove((LPSTR) (m_aStore + u), (LPSTR) (m_aStore + u + 1),
  634. (ChunkSize() - (u + 1)) * sizeof m_aStore[0]);
  635. if (m_ucUsed > ChunkSize())
  636. m_aStore[ChunkSize() - 1] = m_pcpaNext -> Borrow();
  637. else
  638. m_aStore[ChunkSize() - 1] = (CProfile *) NULL;
  639. m_ucUsed--;
  640. if (m_ucUsed <= ChunkSize() && m_pcpaNext) {
  641. delete m_pcpaNext;
  642. m_pcpaNext = NULL;
  643. }
  644. }