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.

1643 lines
53 KiB

  1. /******************************************************************************
  2. Source File: Device Profile Management .CPP
  3. Change History:
  4. Implements the class which provides the various device profile management UI
  5. Copyright (c) 1996 by Microsoft Corporation
  6. A Pretty Penny Enterprises, Inc. Production
  7. 11-27-96 a-RobKj@microsoft.com coded it
  8. ******************************************************************************/
  9. #include "ICMUI.H"
  10. //
  11. // This function is obtained from the April 1998 Knowledge Base
  12. // Its purpose is to determine if the current user is an
  13. // Administrator and therefore priveledged to change profile
  14. // settings.
  15. //
  16. // BOOL IsAdmin(void)
  17. //
  18. // returns TRUE if user is an admin
  19. // FALSE if user is not an admin
  20. //
  21. #if defined(_WIN95_)
  22. //
  23. // Always administrator on Windows 9x platform.
  24. //
  25. BOOL IsAdmin(void) {
  26. return (TRUE);
  27. }
  28. #else
  29. BOOL IsAdmin(void)
  30. {
  31. BOOL fReturn = FALSE;
  32. PSID psidAdmin;
  33. SID_IDENTIFIER_AUTHORITY SystemSidAuthority= SECURITY_NT_AUTHORITY;
  34. if ( AllocateAndInitializeSid ( &SystemSidAuthority, 2,
  35. SECURITY_BUILTIN_DOMAIN_RID,
  36. DOMAIN_ALIAS_RID_ADMINS,
  37. 0, 0, 0, 0, 0, 0, &psidAdmin) )
  38. {
  39. if(!CheckTokenMembership( NULL, psidAdmin, &fReturn )) {
  40. //
  41. // explicitly disallow Admin Access if CheckTokenMembership fails.
  42. //
  43. fReturn = FALSE;
  44. }
  45. FreeSid ( psidAdmin);
  46. }
  47. return ( fReturn );
  48. }
  49. #endif // _WIN95_
  50. /******************************************************************************
  51. List Managment functions
  52. The method used here is simlar to that used in the profile Managment sheets
  53. for managing device associations.
  54. We (not royal, I mean the OS and I) manage two "to-do" lists and use these
  55. to show the user the anticipated result of these lists being applied. The
  56. first list is a list of existing associations that are to be broken. The
  57. second is one of new associations to be made. This is coupled with a list
  58. of the current associations.
  59. The "Removals" list is the indices of existing associations which will be
  60. borken. The "Adds" list is a list of new profiles to be associated. The
  61. "Profiles" list is the list of existing associations.
  62. Adding and removing profiles could mean removing an item from one of the work
  63. lists (undoing a previous selection), or adding one. Each time such a change
  64. is made, the profile list box is emptied and refilled. This lets us avoid
  65. mapping removals and additions more directly.
  66. When changes are commited, either with Apply or OK, we make or break
  67. associations as specified, then empty all of the lists, and rebuild the list
  68. of current associations.
  69. We use the ITEMDATA of the UI list box to handle the associations. This lets
  70. the list remain sorted.
  71. All of the list management functions can be overriden, if needed.
  72. ******************************************************************************/
  73. void CDeviceProfileManagement::InitList() {
  74. // Make sure the lists are empty.
  75. m_cuaRemovals.Empty();
  76. m_cpaAdds.Empty();
  77. // Determine the associations for the target device.
  78. ENUMTYPE et = {sizeof et, ENUM_TYPE_VERSION, ET_DEVICENAME, m_csDevice};
  79. CProfile::Enumerate(et, m_cpaProfile);
  80. }
  81. // Fill the UI list of profiles
  82. void CDeviceProfileManagement::FillList(DWORD dwFlags) {
  83. // Before reset list box, get current selection to restore later.
  84. CString csSelect;
  85. csSelect.Empty();
  86. LRESULT idSelect = LB_ERR;
  87. if ( !(dwFlags & DEVLIST_NOSELECT)) {
  88. // Get current selected position.
  89. idSelect = SendMessage(m_hwndList, LB_GETCURSEL, 0, 0);
  90. // Get text length where currently selected, than allocate buffer for that.
  91. DWORD dwLen = (DWORD) SendMessage(m_hwndList, LB_GETTEXTLEN, idSelect, 0);
  92. TCHAR *pszSelect = new TCHAR[dwLen + 1];
  93. // Get text itself.
  94. if (pszSelect != NULL) {
  95. if (SendMessage(m_hwndList, LB_GETTEXT, idSelect, (LPARAM) pszSelect) != LB_ERR) {
  96. csSelect = pszSelect;
  97. }
  98. delete [] pszSelect;
  99. }
  100. }
  101. // reset list box
  102. SendMessage(m_hwndList, LB_RESETCONTENT, 0, 0);
  103. // Fill the profile list box from the list of profiles
  104. for (unsigned u = 0; u < m_cpaProfile.Count(); u++) {
  105. // Don't list profiles tentatively disassociated...
  106. for (unsigned uOut = 0; uOut < m_cuaRemovals.Count(); uOut++)
  107. if (m_cuaRemovals[uOut] == u)
  108. break;
  109. if (uOut < m_cuaRemovals.Count())
  110. continue; // Don't add this to list, it's been zapped!
  111. LRESULT id = SendMessage(m_hwndList, LB_ADDSTRING, 0,
  112. (LPARAM) (LPCTSTR) m_cpaProfile[u] -> GetName());
  113. SendMessage(m_hwndList, LB_SETITEMDATA, id, u);
  114. }
  115. // Add the profiles that have been tentatively added...
  116. for (u = 0; u < m_cpaAdds.Count(); u ++) {
  117. LRESULT id = SendMessage(m_hwndList, LB_ADDSTRING, 0,
  118. (LPARAM) (LPCTSTR) m_cpaAdds[u] -> GetName());
  119. SendMessage(m_hwndList, LB_SETITEMDATA, id, u + m_cpaProfile.Count());
  120. }
  121. // If we have any profiles, select the first one
  122. // Otherwise, disable the "Remove" button, as there's nothing to remove
  123. unsigned itemCount = (m_cpaProfile.Count() + m_cpaAdds.Count() - m_cuaRemovals.Count());
  124. if (itemCount) {
  125. // The Remove button must remain disabled
  126. // unless the user is Administrator.
  127. // This code is specific to the Monitor Profile
  128. // Property sheet.
  129. if (!m_bReadOnly) {
  130. EnableWindow(GetDlgItem(m_hwnd, RemoveButton), TRUE);
  131. }
  132. if ( !(dwFlags & DEVLIST_NOSELECT)) {
  133. // Find out the string selected previously.
  134. idSelect = LB_ERR;
  135. if (!csSelect.IsEmpty()) {
  136. idSelect = SendMessage(m_hwndList, LB_FINDSTRINGEXACT,
  137. (WPARAM) -1, (LPARAM) (LPCTSTR) csSelect);
  138. }
  139. // if could not find, just select first item.
  140. if (idSelect == LB_ERR) {
  141. idSelect = 0;
  142. }
  143. // Select it.
  144. SendMessage(m_hwndList, LB_SETCURSEL, idSelect, 0);
  145. }
  146. } else {
  147. HWND hwndRemove = GetDlgItem(m_hwnd, RemoveButton);
  148. // If focus is on Remove, move it to Add button.
  149. if (GetFocus() == hwndRemove) {
  150. HWND hwndAdd = GetDlgItem(m_hwnd, AddButton);
  151. SetFocus(hwndAdd);
  152. SendMessage(hwndRemove, BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE, 0));
  153. SendMessage(hwndAdd, BM_SETSTYLE, BS_DEFPUSHBUTTON, MAKELPARAM(TRUE, 0));
  154. }
  155. EnableWindow(hwndRemove, FALSE);
  156. }
  157. // Apply button needs to remain disabled unless the
  158. // user has permision to make changes - ie. user
  159. // is Administrator.
  160. if ((dwFlags & DEVLIST_CHANGED) && !(m_bReadOnly)) {
  161. EnableApplyButton();
  162. SettingChanged(TRUE);
  163. }
  164. }
  165. void CDeviceProfileManagement::GetDeviceTypeString(DWORD dwType,CString& csDeviceName) {
  166. DWORD id;
  167. switch (dwType) {
  168. case CLASS_MONITOR :
  169. id = ClassMonitorString;
  170. break;
  171. case CLASS_PRINTER :
  172. id = ClassPrinterString;
  173. break;
  174. case CLASS_SCANNER :
  175. id = ClassScannerString;
  176. break;
  177. case CLASS_LINK :
  178. id = ClassLinkString;
  179. break;
  180. case CLASS_ABSTRACT :
  181. id = ClassAbstractString;
  182. break;
  183. case CLASS_NAMED :
  184. id = ClassNamedString;
  185. break;
  186. case CLASS_COLORSPACE :
  187. default :
  188. id = ClassColorSpaceString;
  189. break;
  190. }
  191. // Load string.
  192. csDeviceName.Load(id);
  193. }
  194. // Constructor
  195. CDeviceProfileManagement::CDeviceProfileManagement(LPCTSTR lpstrDevice,
  196. HINSTANCE hiWhere,
  197. int idPage, DWORD dwType) {
  198. m_csDevice = lpstrDevice;
  199. m_dwType = dwType;
  200. m_psp.hInstance = hiWhere;
  201. m_psp.pszTemplate = MAKEINTRESOURCE(idPage);
  202. // Setting m_bReadOnly to false enables functionality
  203. m_bReadOnly = FALSE; // default setting is false
  204. #if defined(_WIN95_)
  205. //
  206. // There is no way to detect printer supports CMYK or not on Win 9x.
  207. m_bCMYK = TRUE;
  208. #else
  209. // we need to check the device capabilities
  210. // and determine if we're trying to associate
  211. // a cmyk printer profile to a printer that
  212. // doesn't support it.
  213. m_bCMYK = FALSE; // default setting - don't support cmyk
  214. // if the device is a printer
  215. if (m_dwType == CLASS_PRINTER) {
  216. HDC hdcThis = CGlobals::GetPrinterHDC(m_csDevice);
  217. // if the printer supports CMYK
  218. if (hdcThis) {
  219. if (GetDeviceCaps(hdcThis, COLORMGMTCAPS) & CM_CMYK_COLOR) {
  220. m_bCMYK = TRUE;
  221. }
  222. DeleteDC(hdcThis);
  223. }
  224. }
  225. #endif // defined(_WIN95_)
  226. }
  227. // UI initialization
  228. BOOL CDeviceProfileManagement::OnInit() {
  229. InitList();
  230. m_hwndList = GetDlgItem(m_hwnd, ProfileListControl);
  231. // Fill the profile list box
  232. FillList(DEVLIST_ONINIT);
  233. // Disable apply button as default.
  234. DisableApplyButton();
  235. // Nothing changed, yet.
  236. SettingChanged(FALSE);
  237. return TRUE;
  238. }
  239. // Command processing
  240. BOOL CDeviceProfileManagement::OnCommand(WORD wNotifyCode, WORD wid,
  241. HWND hwndCtl) {
  242. switch (wNotifyCode) {
  243. case BN_CLICKED:
  244. switch (wid) {
  245. case AddButton: {
  246. unsigned i = 0, u = 0;
  247. // Time to do the old OpenFile dialog stuff...
  248. CAddProfileDialog capd(m_hwnd, m_psp.hInstance);
  249. // See if a profile was selected
  250. while(i < capd.ProfileCount()) {
  251. // Check profile validity and device type
  252. CProfile cpTemp(capd.ProfileName(i));
  253. // CLASS_COLORSPACE and CLASS_MONITOR can be associated to
  254. // any device. Other (CLASS_SCANNER, CLASS_PRINTER) only
  255. // can be associated to much device.
  256. if ( !cpTemp.IsValid() // Wrong profile type or invalid?
  257. || ( cpTemp.GetType() != m_dwType
  258. && cpTemp.GetType() != CLASS_COLORSPACE
  259. #if 1 // ALLOW_MONITOR_PROFILE_TO_ANY_DEVICE
  260. && cpTemp.GetType() != CLASS_MONITOR
  261. #endif
  262. )
  263. ) {
  264. // Throw up a message box to inform the user of this
  265. if (cpTemp.IsValid())
  266. {
  267. CString csDeviceType; GetDeviceTypeString(m_dwType,csDeviceType);
  268. CString csProfileType; GetDeviceTypeString(cpTemp.GetType(),csProfileType);
  269. CGlobals::ReportEx(MismatchDeviceType, m_hwnd, FALSE,
  270. MB_OK|MB_ICONEXCLAMATION, 3,
  271. (LPTSTR)capd.ProfileNameAndExtension(i),
  272. (LPTSTR)csProfileType,
  273. (LPTSTR)csDeviceType);
  274. }
  275. else
  276. {
  277. CGlobals::ReportEx(InstFailedWithName, m_hwnd, FALSE,
  278. MB_OK|MB_ICONEXCLAMATION, 1,
  279. (LPTSTR)capd.ProfileNameAndExtension(i));
  280. }
  281. goto SkipToNext;
  282. }
  283. // See if the profile has already been listed for addition
  284. for (u = 0; u < m_cpaAdds.Count(); u++) {
  285. if (!lstrcmpi(m_cpaAdds[u] -> GetName(), cpTemp.GetName())) {
  286. goto SkipToNext; // This profile is already added
  287. }
  288. }
  289. // If this profile is on the existing list, either ignore
  290. // or zap it from the removal list, as the case may be
  291. for (u = 0; u < m_cpaProfile.Count(); u++) {
  292. if (!lstrcmpi(m_cpaProfile[u] -> GetName(),
  293. cpTemp.GetName())) {
  294. // Is this one on the removal list?
  295. for (unsigned uOut = 0;
  296. uOut < m_cuaRemovals.Count();
  297. uOut++) {
  298. if (m_cuaRemovals[uOut] == u) {
  299. // Was to be removed- undo that...
  300. m_cuaRemovals.Remove(uOut);
  301. FillList(DEVLIST_CHANGED);
  302. break;
  303. }
  304. }
  305. goto SkipToNext;
  306. } // End of name in existing list
  307. }
  308. // We need to check the device capabilities
  309. // and determine if we're trying to associate
  310. // a cmyk printer profile to a printer that
  311. // doesn't support it.
  312. if ((!m_bCMYK) && (cpTemp.GetColorSpace() == SPACE_CMYK)) {
  313. CGlobals::ReportEx(UnsupportedProfile, m_hwnd, FALSE,
  314. MB_OK|MB_ICONEXCLAMATION, 2,
  315. (LPTSTR)m_csDevice,
  316. (LPTSTR)capd.ProfileNameAndExtension(i));
  317. goto SkipToNext;
  318. }
  319. // Add this profile to the list, item (max orig + index)
  320. m_cpaAdds.Add(capd.ProfileName(i));
  321. // Change has been made, update the list
  322. FillList(DEVLIST_CHANGED);
  323. SkipToNext:
  324. i++;
  325. }
  326. return TRUE;
  327. }
  328. case RemoveButton: {
  329. // Remove the selected profile
  330. LRESULT id = SendMessage(m_hwndList, LB_GETCURSEL, 0, 0);
  331. unsigned u = (unsigned) SendMessage(m_hwndList,
  332. LB_GETITEMDATA, id, 0);
  333. // If this is a tentative add, just drop it, otherwise
  334. // note that it's been removed...
  335. if (u >= m_cpaProfile.Count())
  336. m_cpaAdds.Remove(u - m_cpaProfile.Count());
  337. else
  338. m_cuaRemovals.Add(u);
  339. // That's it- just update the display, now...
  340. FillList(DEVLIST_CHANGED);
  341. // explicitly set the position of the current selection
  342. // after the list has been recomputed.
  343. int listsize = m_cpaProfile.Count()+m_cpaAdds.Count()-m_cuaRemovals.Count();
  344. if (id >= listsize) id = listsize-1;
  345. if (id < 0) id = 0;
  346. SendMessage(m_hwndList, LB_SETCURSEL, id, 0);
  347. return TRUE;
  348. }
  349. }
  350. break;
  351. case LBN_SELCHANGE: {
  352. LRESULT id = SendMessage(m_hwndList, LB_GETCURSEL, 0, 0);
  353. if (id == -1) {
  354. EnableWindow(GetDlgItem(m_hwnd, RemoveButton), FALSE);
  355. } else {
  356. // The Remove button must remain disabled on a monitor
  357. // profile property page if the user isn't the
  358. // Administrator, otherwise enable remove button.
  359. EnableWindow(GetDlgItem(m_hwnd, RemoveButton), !m_bReadOnly);
  360. }
  361. return TRUE;
  362. }
  363. }
  364. return FALSE;
  365. }
  366. // Property Sheet notification processing
  367. BOOL CDeviceProfileManagement::OnNotify(int idCtrl, LPNMHDR pnmh) {
  368. switch (pnmh -> code) {
  369. case PSN_APPLY:
  370. DisableApplyButton();
  371. if (SettingChanged()) {
  372. // Apply the changes the user has made...
  373. SettingChanged(FALSE);
  374. while (m_cpaAdds.Count()) {
  375. if (!m_cpaAdds[0] -> IsInstalled()) {
  376. m_cpaAdds[0] -> Install();
  377. }
  378. m_cpaAdds[0] -> Associate(m_csDevice);
  379. m_cpaAdds.Remove(0);
  380. }
  381. // Now do the removals (actually just dissociations)
  382. while (m_cuaRemovals.Count()) {
  383. m_cpaProfile[m_cuaRemovals[0]] -> Dissociate(m_csDevice);
  384. m_cuaRemovals.Remove(0);
  385. }
  386. InitList();
  387. FillList();
  388. SetWindowLongPtr(m_hwnd, DWLP_MSGRESULT, PSNRET_NOERROR);
  389. }
  390. return TRUE;
  391. }
  392. return FALSE;
  393. }
  394. // This hook procedure both forces the use of the old-style common dialog
  395. // and changes the OK button to an Add button. The actual button text is
  396. // a string resource, and hence localizable.
  397. UINT_PTR APIENTRY CAddProfileDialog::OpenFileHookProc(HWND hDlg, UINT uMessage,
  398. WPARAM wp, LPARAM lp) {
  399. switch (uMessage) {
  400. case WM_INITDIALOG: {
  401. CString csAddButton;
  402. OPENFILENAME *pofn = (OPENFILENAME *) lp;
  403. csAddButton.Load(AddButtonText);
  404. SetDlgItemText(GetParent(hDlg), IDOK, csAddButton);
  405. return TRUE;
  406. }
  407. }
  408. return FALSE;
  409. }
  410. // Once again, a constructor that actually does most of the work!
  411. TCHAR gacColorDir[MAX_PATH] = _TEXT("\0");
  412. TCHAR gacFilter[MAX_PATH] = _TEXT("\0");
  413. CAddProfileDialog::CAddProfileDialog(HWND hwndOwner, HINSTANCE hi) {
  414. TCHAR tempBuffer[MAX_PATH*10];
  415. // Empty the profile list.
  416. csa_Files.Empty();
  417. // Prepare file filter (if not yet).
  418. if (gacFilter[0] == NULL) {
  419. ULONG offset; /* 32bits is enough even for sundown */
  420. CString csIccFilter; CString csAllFilter;
  421. // If the filter is not built yet, build it here.
  422. csIccFilter.Load(IccProfileFilterString);
  423. csAllFilter.Load(AllProfileFilterString);
  424. offset = 0;
  425. lstrcpy(gacFilter+offset, csIccFilter);
  426. offset += lstrlen(csIccFilter)+1;
  427. lstrcpy(gacFilter+offset, TEXT("*.icm;*.icc"));
  428. offset += lstrlen(TEXT("*.icm;*.icc"))+1;
  429. lstrcpy(gacFilter+offset, csAllFilter);
  430. offset += lstrlen(csAllFilter)+1;
  431. lstrcpy(gacFilter+offset, TEXT("*.*"));
  432. offset += lstrlen(TEXT("*.*"))+1;
  433. *(gacFilter+offset) = TEXT('\0');
  434. }
  435. if (gacColorDir[0] == _TEXT('\0')) {
  436. DWORD dwcbDir = MAX_PATH;
  437. GetColorDirectory(NULL, gacColorDir, &dwcbDir);
  438. }
  439. // Time to do the old OpenFile dialog stuff...
  440. CString csTitle; csTitle.Load(AddProfileAssociation);
  441. // Set initial filename as null.
  442. memset(tempBuffer, 0, sizeof tempBuffer);
  443. OPENFILENAME ofn = {
  444. sizeof ofn, hwndOwner, hi,
  445. gacFilter,
  446. NULL, 0, 1,
  447. tempBuffer, sizeof tempBuffer / sizeof tempBuffer[0],
  448. NULL, 0,
  449. gacColorDir,
  450. csTitle,
  451. OFN_ALLOWMULTISELECT | OFN_EXPLORER | OFN_HIDEREADONLY |
  452. OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_ENABLEHOOK,
  453. 0, 0,
  454. _TEXT("icm"),
  455. (LPARAM) this, OpenFileHookProc, NULL};
  456. if (!GetOpenFileName(&ofn)) {
  457. if (CommDlgExtendedError() == FNERR_BUFFERTOOSMALL) {
  458. CGlobals::Report(TooManyFileSelected);
  459. }
  460. } else {
  461. if (tempBuffer[0] != TEXT('\0')) {
  462. TCHAR *pPath = tempBuffer;
  463. TCHAR *pFile = tempBuffer + lstrlen(tempBuffer) + 1;
  464. // remember the last access-ed directory.
  465. memset(gacColorDir, 0, sizeof pPath);
  466. memcpy(gacColorDir, pPath, ofn.nFileOffset*sizeof(TCHAR));
  467. if (*pFile) {
  468. TCHAR workBuffer[MAX_PATH];
  469. // This is multiple-selection
  470. // Work through the buufer to build profile file list.
  471. while (*pFile) {
  472. lstrcpy(workBuffer,pPath);
  473. lstrcat(workBuffer,TEXT("\\"));
  474. lstrcat(workBuffer,pFile);
  475. // Insert built profile pathname
  476. AddProfile(workBuffer);
  477. // Move on to next.
  478. pFile = pFile + lstrlen(pFile) + 1;
  479. }
  480. }
  481. else {
  482. // Single selection case.
  483. AddProfile(pPath);
  484. #if HIDEYUKN_DBG
  485. MessageBox(NULL,pPath,TEXT(""),MB_OK);
  486. #endif
  487. }
  488. }
  489. }
  490. return;
  491. }
  492. // Printer Profile Management
  493. CONST DWORD PrinterUIHelpIds[] = {
  494. AddButton, IDH_PRINTERUI_ADD,
  495. RemoveButton, IDH_PRINTERUI_REMOVE,
  496. ProfileListControl, IDH_PRINTERUI_LIST,
  497. #if !defined(_WIN95_)
  498. ProfileListControlText, IDH_PRINTERUI_LIST,
  499. PrinterUIIcon, IDH_DISABLED,
  500. DescriptionText, IDH_DISABLED,
  501. DefaultButton, IDH_PRINTERUI_DEFAULTBTN,
  502. AutoSelButton, IDH_PRINTERUI_AUTOMATIC,
  503. AutoSelText, IDH_PRINTERUI_AUTOMATIC,
  504. ManualSelButton, IDH_PRINTERUI_MANUAL,
  505. ManualSelText, IDH_PRINTERUI_MANUAL,
  506. DefaultProfileText, IDH_PRINTERUI_DEFAULTTEXT,
  507. DefaultProfile, IDH_PRINTERUI_DEFAULTTEXT,
  508. #endif
  509. 0, 0
  510. };
  511. // Initialize lists override- call the base class, then set the default
  512. void CPrinterProfileManagement::InitList() {
  513. CDeviceProfileManagement::InitList();
  514. m_uDefault = m_cpaProfile.Count() ? 0 : (unsigned) -1;
  515. }
  516. // Fill list override- write the correct default and call the base function
  517. void CPrinterProfileManagement::FillList(DWORD dwFlags) {
  518. // If we are initializing list box, we want to put focus on
  519. // "default" profile. here we won't below FillList set focus
  520. // to first one.
  521. if (dwFlags & DEVLIST_ONINIT) {
  522. dwFlags |= DEVLIST_NOSELECT;
  523. }
  524. CDeviceProfileManagement::FillList(dwFlags);
  525. // There is either no default profile, an existing profile is the
  526. // default, or a newly selected one is. Some people just like the
  527. // selection operator.
  528. // if there is only 1 profile in list box, we treat it as default profile.
  529. if (SendMessage(m_hwndList,LB_GETCOUNT,0,0) == 1) {
  530. m_uDefault = (unsigned)SendMessage(m_hwndList, LB_GETITEMDATA, 0, 0);
  531. }
  532. if (m_uDefault == -1) {
  533. // There is no profile associated for this device.
  534. CString csNoProfile;
  535. csNoProfile.Load(NoProfileString);
  536. SetDlgItemText(m_hwnd, DefaultProfile, csNoProfile);
  537. } else {
  538. // If the default has been deleted, set default as last in list.
  539. if (m_uDefault >= (m_cpaProfile.Count() + m_cpaAdds.Count())) {
  540. m_uDefault = (m_cpaProfile.Count() + m_cpaAdds.Count()) - 1;
  541. }
  542. // Put default profile name in UI.
  543. CProfile *pcpDefault = (m_uDefault < m_cpaProfile.Count()) ? \
  544. m_cpaProfile[m_uDefault] : \
  545. m_cpaAdds[m_uDefault - m_cpaProfile.Count()];
  546. SetDlgItemText(m_hwnd, DefaultProfile, pcpDefault -> GetName());
  547. LRESULT idSelect = SendMessage(m_hwndList, LB_FINDSTRINGEXACT,
  548. (WPARAM) -1, (LPARAM) (LPCTSTR) pcpDefault -> GetName());
  549. // if could not find, just select first item.
  550. if (idSelect == LB_ERR) {
  551. idSelect = 0;
  552. }
  553. // Select it.
  554. SendMessage(m_hwndList, LB_SETCURSEL, idSelect, 0);
  555. }
  556. // 03-08-1997 [email protected] Memphis RAID 18420
  557. // Disable the Default button if there aren't any profiles
  558. if (m_bManualMode && m_bAdminAccess) {
  559. EnableWindow(GetDlgItem(m_hwnd, DefaultButton),
  560. m_cpaAdds.Count() + m_cpaProfile.Count() - m_cuaRemovals.Count());
  561. }
  562. }
  563. // Printer Profile Management class constructor- doesn't need any individual
  564. // code at the moment.
  565. CPrinterProfileManagement::CPrinterProfileManagement(LPCTSTR lpstrName,
  566. HINSTANCE hiWhere) :
  567. CDeviceProfileManagement(lpstrName, hiWhere, PrinterUI, CLASS_PRINTER) {
  568. }
  569. // This class overrides OnInit so it can disable the UI if the user lacks
  570. // authority to make changes.
  571. BOOL CPrinterProfileManagement::OnInit() {
  572. // Call the base class routine first, as it does most of the work...
  573. CDeviceProfileManagement::OnInit();
  574. DWORD dwSize = sizeof(DWORD);
  575. // Query current mode.
  576. if (!InternalGetDeviceConfig((LPCTSTR)m_csDevice, CLASS_PRINTER,
  577. MSCMS_PROFILE_ENUM_MODE, &m_bManualMode, &dwSize)) {
  578. // Auto selection mode as default.
  579. m_bManualMode = FALSE;
  580. }
  581. // Now, see if we have sufficient authority to administer the printer
  582. HANDLE hPrinter;
  583. PRINTER_DEFAULTS pd = {NULL, NULL, PRINTER_ACCESS_ADMINISTER};
  584. m_bAdminAccess = TRUE;
  585. m_bLocalPrinter = TRUE;
  586. if (OpenPrinter(const_cast<LPTSTR> ((LPCTSTR) m_csDevice), &hPrinter, &pd)) {
  587. // We can administer the printer- proceed in the normal way.
  588. #if !defined(_WIN95_)
  589. // If the printer is "Network Printer", we don't allow user to install
  590. // or uninstall color profile.
  591. BYTE StackPrinterData[sizeof(PRINTER_INFO_4)+MAX_PATH*2];
  592. PBYTE pPrinterData = StackPrinterData;
  593. BOOL bSuccess = TRUE;
  594. DWORD dwReturned;
  595. if (!GetPrinter(hPrinter, 4, pPrinterData, sizeof(StackPrinterData), &dwReturned)) {
  596. if ((GetLastError() == ERROR_INSUFFICIENT_BUFFER) &&
  597. (pPrinterData = (PBYTE) LocalAlloc(LPTR, dwReturned))) {
  598. if (GetPrinter(hPrinter, 4, pPrinterData, dwReturned, &dwReturned)) {
  599. bSuccess = TRUE;
  600. }
  601. }
  602. } else {
  603. bSuccess = TRUE;
  604. }
  605. if (bSuccess)
  606. {
  607. m_bLocalPrinter = ((PRINTER_INFO_4 *)pPrinterData)->pServerName ? FALSE : TRUE;
  608. }
  609. else
  610. {
  611. m_bAdminAccess = FALSE;
  612. }
  613. if (pPrinterData && (pPrinterData != StackPrinterData))
  614. {
  615. LocalFree(pPrinterData);
  616. }
  617. #endif // !defined(_WIN95_)
  618. ClosePrinter(hPrinter);
  619. } else {
  620. m_bAdminAccess = FALSE;
  621. }
  622. // How many profile in listbox ?
  623. LRESULT itemCount = SendMessage(m_hwndList, LB_GETCOUNT, 0, 0);
  624. if (itemCount == LB_ERR) itemCount = 0;
  625. // make sure the ancestor list code behaves correctly.
  626. // You need Admin Access and a Local Printer to be able to add/remove profiles
  627. m_bReadOnly = !(m_bAdminAccess && m_bLocalPrinter);
  628. // Enable/Disable the controls (if needed)
  629. CheckDlgButton(m_hwnd, AutoSelButton, m_bManualMode ? BST_UNCHECKED : BST_CHECKED);
  630. CheckDlgButton(m_hwnd, ManualSelButton, m_bManualMode ? BST_CHECKED : BST_UNCHECKED);
  631. // Only administrator can change 'auto','manual' configuration.
  632. EnableWindow(GetDlgItem(m_hwnd, AutoSelButton), m_bAdminAccess && m_bLocalPrinter);
  633. EnableWindow(GetDlgItem(m_hwnd, ManualSelButton), m_bAdminAccess && m_bLocalPrinter);
  634. // Only administrator and printer is at local, can install/uninstall color profile.
  635. EnableWindow(GetDlgItem(m_hwnd, AddButton), m_bAdminAccess && m_bLocalPrinter);
  636. EnableWindow(GetDlgItem(m_hwnd, RemoveButton), m_bAdminAccess && m_bLocalPrinter && itemCount);
  637. EnableWindow(m_hwndList, m_bAdminAccess);
  638. EnableWindow(GetDlgItem(m_hwnd, DefaultProfileText), m_bAdminAccess);
  639. EnableWindow(GetDlgItem(m_hwnd, DefaultProfile), m_bAdminAccess);
  640. // Only with manual mode, these controls are enabled.
  641. EnableWindow(GetDlgItem(m_hwnd, DefaultButton), m_bAdminAccess && m_bManualMode
  642. && m_bLocalPrinter && itemCount);
  643. if (!m_bAdminAccess) {
  644. // Set the focus to the OK button
  645. SetFocus(GetDlgItem(m_hwndSheet, IDOK));
  646. return FALSE; // Because we moved the focus!
  647. }
  648. return TRUE;
  649. }
  650. // Command processing- we never let them click into the edit control, to
  651. // prevent them from editing it.
  652. BOOL CPrinterProfileManagement::OnCommand(WORD wNotifyCode, WORD wid,
  653. HWND hwndCtl) {
  654. switch (wNotifyCode) {
  655. case LBN_DBLCLK: {
  656. // Retrieve the ID of the new default profile
  657. // only accept dblclk changes if the dialog
  658. // is not read only - i.e. user is admin
  659. if (m_bManualMode) {
  660. int id = (int)SendMessage(m_hwndList, LB_GETCURSEL, 0, 0);
  661. m_uDefault = (unsigned)SendMessage(m_hwndList, LB_GETITEMDATA, id, 0);
  662. // Change has been made, update the list
  663. FillList(DEVLIST_CHANGED);
  664. }
  665. return TRUE;
  666. }
  667. case BN_CLICKED:
  668. switch (wid) {
  669. case AutoSelButton:
  670. case ManualSelButton: {
  671. // How many profile in listbox ?
  672. LRESULT itemCount = SendMessage(m_hwndList, LB_GETCOUNT, 0, 0);
  673. if (itemCount == LB_ERR) itemCount = 0;
  674. m_bManualMode = (wid == ManualSelButton) ? TRUE : FALSE;
  675. // Only with manual mode, these controls are enabled.
  676. EnableWindow(GetDlgItem(m_hwnd, DefaultButton), m_bManualMode && itemCount);
  677. // Configuarion has been changed, enable apply button.
  678. EnableApplyButton();
  679. SettingChanged(TRUE);
  680. return TRUE;
  681. }
  682. case RemoveButton: {
  683. // Make sure we've tracked the default profile correctly
  684. // when a profile is removed.
  685. // All cases break, because we then want the base class to
  686. // process this message.
  687. LRESULT id = SendMessage(m_hwndList, LB_GETCURSEL, 0, 0);
  688. unsigned uTarget = (unsigned)SendMessage(m_hwndList, LB_GETITEMDATA,
  689. id, 0);
  690. if (uTarget > m_uDefault || m_uDefault == (unsigned) -1)
  691. break; // Nothing here to worry about
  692. if (m_uDefault == uTarget) {
  693. if (CGlobals::ReportEx(AskRemoveDefault, m_hwnd, FALSE,
  694. MB_YESNO|MB_ICONEXCLAMATION,0) == IDYES) {
  695. // The default has been deleted- the profile
  696. // at the top of monitor profile list will be
  697. // made the default profile, if we have
  698. LRESULT itemCount = SendMessage(m_hwndList, LB_GETCOUNT, 0, 0);
  699. if ((itemCount != LB_ERR) && (itemCount > 1)) {
  700. m_uDefault = (unsigned)SendMessage(m_hwndList, LB_GETITEMDATA, 0, 0);
  701. if (m_uDefault == uTarget) {
  702. m_uDefault = (unsigned)SendMessage(m_hwndList, LB_GETITEMDATA, 1, 0);
  703. }
  704. } else {
  705. m_uDefault = -1;
  706. }
  707. break;
  708. } else {
  709. return TRUE; // opration cancelled.
  710. }
  711. }
  712. if (uTarget < m_cpaProfile.Count())
  713. break; // We're fine
  714. // Must be an added profile below us in the list was
  715. // zapped- we need to decrement ourselves.
  716. m_uDefault--;
  717. break;
  718. }
  719. case DefaultButton: {
  720. LRESULT id = SendMessage(m_hwndList, LB_GETCURSEL, 0, 0);
  721. m_uDefault = (unsigned)SendMessage(m_hwndList, LB_GETITEMDATA, id, 0);
  722. // Change has been made, update the list
  723. FillList(DEVLIST_CHANGED);
  724. return TRUE;
  725. }
  726. }
  727. // Deliberate fall-through (use a break if you add a case here)
  728. }
  729. // Use common command handling if not handled above
  730. return CDeviceProfileManagement::OnCommand(wNotifyCode, wid, hwndCtl);
  731. }
  732. // Property Sheet notification processing
  733. BOOL CPrinterProfileManagement::OnNotify(int idCtrl, LPNMHDR pnmh) {
  734. switch (pnmh -> code) {
  735. case PSN_APPLY: {
  736. DisableApplyButton();
  737. // If nothing changed, nothing need to do.
  738. if (!SettingChanged())
  739. return TRUE;
  740. if (m_bManualMode) {
  741. // If the user hasn't selected a default, and we have
  742. // associated profiles, then we can't allow this.
  743. // 03-08-1997 A-RobKj Fix for Memphis RAID 18416- if there's
  744. // only one profile left, then it must be the default.
  745. if (m_uDefault == (unsigned) -1 && (m_cpaAdds.Count() +
  746. m_cpaProfile.Count() - m_cuaRemovals.Count()) > 1) {
  747. CGlobals::Report(NoDefaultProfile, m_hwndSheet);
  748. SetWindowLongPtr(m_hwnd, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE);
  749. break;
  750. }
  751. // ATTENTION: This behavior is hardly depend on EnumColorProfiles() API
  752. // OK, if the default profile has changed, we have to delete default
  753. // profile associations, and do the association for default profile
  754. // in "last".
  755. // Let the base class handle the cases where the default hasn't
  756. // changed, or we started with no profiles and still have none.
  757. //
  758. // 03-08-1997 Sleazy code note. The case where no default is
  759. // selected but only one is assigned will now fall here. Since the
  760. // default happens to be the "last", and there only is one, letting
  761. // the base class handle it is not a problem. The list filling
  762. // code will take care of the rest for us.
  763. if (m_uDefault == (unsigned) -1) break;
  764. // Remove default first (if default is associated), then associate later.
  765. if (m_uDefault < m_cpaProfile.Count())
  766. m_cpaProfile[m_uDefault] -> Dissociate(m_csDevice);
  767. // Now do the other removals (actually just dissociations)
  768. for (unsigned u = 0; u < m_cuaRemovals.Count(); u++) {
  769. m_cpaProfile[m_cuaRemovals[u]] -> Dissociate(m_csDevice);
  770. }
  771. // Add in the new ones
  772. for (u = 0; u < m_cpaAdds.Count(); u++) {
  773. if (m_uDefault >= m_cpaProfile.Count())
  774. if (u == (m_uDefault - m_cpaProfile.Count()))
  775. continue; // this is default, will be done later
  776. // OK, add it back in...
  777. m_cpaAdds[u] -> Associate(m_csDevice);
  778. }
  779. // Finally, associate back default profile.
  780. if (m_uDefault < m_cpaProfile.Count())
  781. m_cpaProfile[m_uDefault] -> Associate(m_csDevice);
  782. else
  783. m_cpaAdds[m_uDefault - m_cpaProfile.Count()] -> Associate(m_csDevice);
  784. // Update the various working structures...
  785. InitList();
  786. FillList();
  787. SetWindowLongPtr(m_hwnd, DWLP_MSGRESULT, PSNRET_NOERROR);
  788. // Now, we have updated settings.
  789. SettingChanged(FALSE);
  790. }
  791. // Update "auto/manual" status.
  792. InternalSetDeviceConfig((LPCTSTR)m_csDevice, CLASS_PRINTER,
  793. MSCMS_PROFILE_ENUM_MODE, &m_bManualMode, sizeof(DWORD));
  794. }
  795. }
  796. // Let the base class handle everything else
  797. return CDeviceProfileManagement::OnNotify(idCtrl, pnmh);
  798. }
  799. // Context-sensitive help handler
  800. BOOL CPrinterProfileManagement::OnHelp(LPHELPINFO pHelp) {
  801. if (pHelp->iContextType == HELPINFO_WINDOW) {
  802. WinHelp((HWND) pHelp->hItemHandle, WINDOWS_HELP_FILE,
  803. HELP_WM_HELP, (ULONG_PTR) (LPSTR) PrinterUIHelpIds);
  804. }
  805. return (TRUE);
  806. }
  807. BOOL CPrinterProfileManagement::OnContextMenu(HWND hwnd) {
  808. WinHelp(hwnd, WINDOWS_HELP_FILE,
  809. HELP_CONTEXTMENU, (ULONG_PTR) (LPSTR) PrinterUIHelpIds);
  810. return (TRUE);
  811. }
  812. // Scanner Profile Management
  813. // Scanner Profile Management class constructor- doesn't need any individual
  814. // code at the moment.
  815. // Scanner Profile Management
  816. CONST DWORD ScannerUIHelpIds[] = {
  817. #if !defined(_WIN95_)
  818. AddButton, IDH_SCANNERUI_ADD,
  819. RemoveButton, IDH_SCANNERUI_REMOVE,
  820. ProfileListControl, IDH_SCANNERUI_LIST,
  821. ProfileListControlText, IDH_SCANNERUI_LIST,
  822. #endif
  823. 0, 0
  824. };
  825. CScannerProfileManagement::CScannerProfileManagement(LPCTSTR lpstrName,
  826. HINSTANCE hiWhere) :
  827. CDeviceProfileManagement(lpstrName, hiWhere, ScannerUI, CLASS_SCANNER) {
  828. m_bReadOnly = !IsAdmin();
  829. }
  830. // This class overrides OnInit so it can disable the UI if the user lacks
  831. // authority to make changes.
  832. BOOL CScannerProfileManagement::OnInit() {
  833. // Call the base class routine first, as it does most of the work...
  834. CDeviceProfileManagement::OnInit();
  835. // Now, see if we have sufficient authority to administer the scanner
  836. //
  837. if (m_bReadOnly) {
  838. // User is not Admin, Disable all of the controls
  839. EnableWindow(GetDlgItem(m_hwnd, AddButton), FALSE);
  840. EnableWindow(GetDlgItem(m_hwnd, RemoveButton), FALSE);
  841. // Set the focus to the OK button
  842. SetFocus(GetDlgItem(m_hwndSheet, IDOK));
  843. return FALSE; // Because we moved the focus!
  844. }
  845. return TRUE;
  846. }
  847. // Context-sensitive help handler
  848. BOOL CScannerProfileManagement::OnHelp(LPHELPINFO pHelp) {
  849. if (pHelp->iContextType == HELPINFO_WINDOW) {
  850. WinHelp((HWND) pHelp->hItemHandle, WINDOWS_HELP_FILE,
  851. HELP_WM_HELP, (ULONG_PTR) (LPSTR) ScannerUIHelpIds);
  852. }
  853. return (TRUE);
  854. }
  855. BOOL CScannerProfileManagement::OnContextMenu(HWND hwnd) {
  856. WinHelp(hwnd, WINDOWS_HELP_FILE,
  857. HELP_CONTEXTMENU, (ULONG_PTR) (LPSTR) ScannerUIHelpIds);
  858. return (TRUE);
  859. }
  860. // Monitor Profile Management class- since the mechanism for default
  861. // profile manipulation is a bit sleazy, so is some of this code.
  862. CONST DWORD MonitorUIHelpIds[] = {
  863. AddButton, IDH_MONITORUI_ADD,
  864. RemoveButton, IDH_MONITORUI_REMOVE,
  865. DefaultButton, IDH_MONITORUI_DEFAULT,
  866. ProfileListControl, IDH_MONITORUI_LIST,
  867. #if !defined(_WIN95_)
  868. ProfileListControlText, IDH_MONITORUI_LIST,
  869. MonitorName, IDH_MONITORUI_DISPLAY,
  870. MonitorNameText, IDH_MONITORUI_DISPLAY,
  871. DefaultProfile, IDH_MONITORUI_PROFILE,
  872. DefaultProfileText, IDH_MONITORUI_PROFILE,
  873. #endif
  874. 0, 0
  875. };
  876. // Initialize lists override- call the base class, then set the default
  877. void CMonitorProfileManagement::InitList() {
  878. CDeviceProfileManagement::InitList();
  879. m_uDefault = m_cpaProfile.Count() ? 0 : (unsigned) -1;
  880. }
  881. // Fill list override- write the correct default and call the base function
  882. void CMonitorProfileManagement::FillList(DWORD dwFlags) {
  883. // If we are initializing list box, we want to put focus on
  884. // "default" profile. here we won't below FillList set focus
  885. // to first one.
  886. if (dwFlags & DEVLIST_ONINIT) {
  887. dwFlags |= DEVLIST_NOSELECT;
  888. }
  889. CDeviceProfileManagement::FillList(dwFlags);
  890. // There is either no default profile, an existing profile is the
  891. // default, or a newly selected one is. Some people just like the
  892. // selection operator.
  893. // if there is only 1 profile in list box, we treat it as default profile.
  894. if (SendMessage(m_hwndList,LB_GETCOUNT,0,0) == 1) {
  895. m_uDefault = (unsigned)SendMessage(m_hwndList, LB_GETITEMDATA, 0, 0);
  896. }
  897. if (m_uDefault == -1) {
  898. // There is no profile associated for this device.
  899. CString csNoProfile;
  900. csNoProfile.Load(NoProfileString);
  901. SetDlgItemText(m_hwnd, DefaultProfile, csNoProfile);
  902. } else {
  903. // If the default has been deleted, set default as last in list.
  904. if (m_uDefault >= (m_cpaProfile.Count() + m_cpaAdds.Count())) {
  905. m_uDefault = (m_cpaProfile.Count() + m_cpaAdds.Count()) - 1;
  906. }
  907. // Put default profile name in UI.
  908. CProfile *pcpDefault = (m_uDefault < m_cpaProfile.Count()) ? \
  909. m_cpaProfile[m_uDefault] : \
  910. m_cpaAdds[m_uDefault - m_cpaProfile.Count()];
  911. SetDlgItemText(m_hwnd, DefaultProfile, pcpDefault -> GetName());
  912. // If we are initialing list box, put focus on default profile.
  913. if (dwFlags & DEVLIST_ONINIT) {
  914. LRESULT idSelect = SendMessage(m_hwndList, LB_FINDSTRINGEXACT,
  915. (WPARAM) -1, (LPARAM) (LPCTSTR) pcpDefault -> GetName());
  916. // if could not find, just select first item.
  917. if (idSelect == LB_ERR) {
  918. idSelect = 0;
  919. }
  920. // Select it.
  921. SendMessage(m_hwndList, LB_SETCURSEL, idSelect, 0);
  922. }
  923. }
  924. // 03-08-1997 [email protected] Memphis RAID 18420
  925. // Disable the Default button if there aren't any profiles
  926. // We do it here, because this gets called any time the list changes.
  927. // only allow Default button to be enabled if
  928. // the dialog isn't read only.
  929. // the remove button should remain dissabled
  930. // under all conditions while the user is not
  931. // administrator.
  932. if (m_bReadOnly) {
  933. EnableWindow(GetDlgItem(m_hwnd, RemoveButton), FALSE);
  934. } else {
  935. EnableWindow(GetDlgItem(m_hwnd, DefaultButton),
  936. m_cpaAdds.Count() + m_cpaProfile.Count() - m_cuaRemovals.Count());
  937. }
  938. }
  939. // Constructor
  940. CMonitorProfileManagement::CMonitorProfileManagement(LPCTSTR lpstrName,
  941. LPCTSTR lpstrFriendlyName,
  942. HINSTANCE hiWhere) :
  943. CDeviceProfileManagement(lpstrName, hiWhere, MonitorUI, CLASS_MONITOR) {
  944. // if the user is not the administrator,
  945. // make this property sheet read only.
  946. m_bReadOnly = !IsAdmin();
  947. // Keep friendly name in MonitorProfileManagement class.
  948. m_csDeviceFriendlyName = lpstrFriendlyName;
  949. }
  950. // UI Initialization
  951. BOOL CMonitorProfileManagement::OnInit() {
  952. // Do common initializations
  953. CDeviceProfileManagement::OnInit();
  954. // Mark the device name in the space provided
  955. SetDlgItemText(m_hwnd, MonitorName, m_csDeviceFriendlyName);
  956. // Now, see if we have sufficient authority to administer the monitor
  957. if(m_bReadOnly) {
  958. // User is not Admin, Disable all of the controls
  959. EnableWindow(GetDlgItem(m_hwnd, AddButton), FALSE);
  960. EnableWindow(GetDlgItem(m_hwnd, RemoveButton), FALSE);
  961. EnableWindow(GetDlgItem(m_hwnd, DefaultButton), FALSE);
  962. // EnableWindow(m_hwndList, FALSE);
  963. // Set the focus to the OK button
  964. SetFocus(GetDlgItem(m_hwndSheet, IDOK));
  965. return FALSE; // Because we moved the focus!
  966. }
  967. return TRUE;
  968. }
  969. // Command processing- we never let them click into the edit control, to
  970. // prevent them from editing it.
  971. BOOL CMonitorProfileManagement::OnCommand(WORD wNotifyCode, WORD wid,
  972. HWND hwndCtl) {
  973. switch (wNotifyCode) {
  974. case LBN_DBLCLK: {
  975. // Retrieve the ID of the new default profile
  976. // only accept dblclk changes if the dialog
  977. // is not read only - i.e. user is admin
  978. if (!m_bReadOnly) {
  979. int id = (int)SendMessage(m_hwndList, LB_GETCURSEL, 0, 0);
  980. m_uDefault = (unsigned)SendMessage(m_hwndList, LB_GETITEMDATA, id, 0);
  981. // Change has been made, update the list
  982. FillList(DEVLIST_CHANGED);
  983. }
  984. return TRUE;
  985. }
  986. case BN_CLICKED:
  987. switch (wid) {
  988. case RemoveButton: {
  989. // Make sure we've tracked the default profile correctly
  990. // when a profile is removed.
  991. // All cases break, because we then want the base class to
  992. // process this message.
  993. LRESULT id = SendMessage(m_hwndList, LB_GETCURSEL, 0, 0);
  994. unsigned uTarget = (unsigned)SendMessage(m_hwndList, LB_GETITEMDATA,
  995. id, 0);
  996. if (uTarget > m_uDefault || m_uDefault == (unsigned) -1)
  997. break; // Nothing here to worry about
  998. if (m_uDefault == uTarget) {
  999. if (CGlobals::ReportEx(AskRemoveDefault, m_hwnd, FALSE,
  1000. MB_YESNO|MB_ICONEXCLAMATION,0) == IDYES) {
  1001. // The default has been deleted- the profile
  1002. // at the top of monitor profile list will be
  1003. // made the default profile, if we have
  1004. LRESULT itemCount = SendMessage(m_hwndList, LB_GETCOUNT, 0, 0);
  1005. if ((itemCount != LB_ERR) && (itemCount > 1)) {
  1006. m_uDefault = (unsigned)SendMessage(m_hwndList, LB_GETITEMDATA, 0, 0);
  1007. if (m_uDefault == uTarget) {
  1008. m_uDefault = (unsigned)SendMessage(m_hwndList, LB_GETITEMDATA, 1, 0);
  1009. }
  1010. } else {
  1011. m_uDefault = -1;
  1012. }
  1013. break;
  1014. } else {
  1015. return TRUE; // operation cancelled.
  1016. }
  1017. }
  1018. if (uTarget < m_cpaProfile.Count())
  1019. break; // We're fine
  1020. // Must be an added profile below us in the list was
  1021. // zapped- we need to decrement ourselves.
  1022. m_uDefault--;
  1023. break;
  1024. }
  1025. case DefaultButton: {
  1026. LRESULT id = SendMessage(m_hwndList, LB_GETCURSEL, 0, 0);
  1027. m_uDefault = (unsigned)SendMessage(m_hwndList, LB_GETITEMDATA, id, 0);
  1028. // Change has been made, update the list
  1029. FillList(DEVLIST_CHANGED);
  1030. return TRUE;
  1031. }
  1032. }
  1033. // Deliberate fall-through (use a break if you add a case here)
  1034. }
  1035. // Use common command handling if not handled above
  1036. return CDeviceProfileManagement::OnCommand(wNotifyCode, wid, hwndCtl);
  1037. }
  1038. // Property Sheet notification processing
  1039. BOOL CMonitorProfileManagement::OnNotify(int idCtrl, LPNMHDR pnmh) {
  1040. switch (pnmh -> code) {
  1041. case PSN_APPLY: {
  1042. DisableApplyButton();
  1043. // If nothing changed, nothing need to do.
  1044. if (!SettingChanged())
  1045. return TRUE;
  1046. // If the user hasn't selected a default, and we have
  1047. // associated profiles, then we can't allow this.
  1048. // 03-08-1997 A-RobKj Fix for Memphis RAID 18416- if there's
  1049. // only one profile left, then it must be the default.
  1050. if (m_uDefault == (unsigned) -1 && (m_cpaAdds.Count() +
  1051. m_cpaProfile.Count() - m_cuaRemovals.Count()) > 1) {
  1052. CGlobals::Report(NoDefaultProfile, m_hwndSheet);
  1053. SetWindowLongPtr(m_hwnd, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE);
  1054. break;
  1055. }
  1056. // ATTENTION: This behavior is hardly depend on EnumColorProfiles() API
  1057. // OK, if the default profile has changed, we have to delete default
  1058. // profile associations, and do the association for default profile
  1059. // in "last".
  1060. // Let the base class handle the cases where the default hasn't
  1061. // changed, or we started with no profiles and still have none.
  1062. //
  1063. // 03-08-1997 Sleazy code note. The case where no default is
  1064. // selected but only one is assigned will now fall here. Since the
  1065. // default happens to be the "last", and there only is one, letting
  1066. // the base class handle it is not a problem. The list filling
  1067. // code will take care of the rest for us.
  1068. if (m_uDefault == (unsigned) -1) break;
  1069. // Remove default first (if default is associated), then associate later.
  1070. if (m_uDefault < m_cpaProfile.Count())
  1071. m_cpaProfile[m_uDefault] -> Dissociate(m_csDevice);
  1072. // Now do the other removals (actually just dissociations)
  1073. for (unsigned u = 0; u < m_cuaRemovals.Count(); u++) {
  1074. m_cpaProfile[m_cuaRemovals[u]] -> Dissociate(m_csDevice);
  1075. }
  1076. // Add in the new ones
  1077. for (u = 0; u < m_cpaAdds.Count(); u++) {
  1078. if (m_uDefault >= m_cpaProfile.Count())
  1079. if (u == (m_uDefault - m_cpaProfile.Count()))
  1080. continue; // this is default, will be done later
  1081. // OK, add it back in...
  1082. m_cpaAdds[u] -> Associate(m_csDevice);
  1083. }
  1084. // Finally, associate default profile.
  1085. if (m_uDefault < m_cpaProfile.Count())
  1086. m_cpaProfile[m_uDefault] -> Associate(m_csDevice);
  1087. else
  1088. m_cpaAdds[m_uDefault - m_cpaProfile.Count()] -> Associate(m_csDevice);
  1089. // Update the various working structures...
  1090. InitList();
  1091. FillList();
  1092. SetWindowLongPtr(m_hwnd, DWLP_MSGRESULT, PSNRET_NOERROR);
  1093. // Now, we have updated settings.
  1094. SettingChanged(FALSE);
  1095. }
  1096. }
  1097. // Let the base class handle everything else
  1098. return CDeviceProfileManagement::OnNotify(idCtrl, pnmh);
  1099. }
  1100. // Context-sensitive help handler
  1101. BOOL CMonitorProfileManagement::OnHelp(LPHELPINFO pHelp) {
  1102. if (pHelp->iContextType == HELPINFO_WINDOW) {
  1103. WinHelp((HWND) pHelp->hItemHandle, WINDOWS_HELP_FILE,
  1104. HELP_WM_HELP, (ULONG_PTR) (LPSTR) MonitorUIHelpIds);
  1105. }
  1106. return (TRUE);
  1107. }
  1108. BOOL CMonitorProfileManagement::OnContextMenu(HWND hwnd) {
  1109. WinHelp(hwnd, WINDOWS_HELP_FILE,
  1110. HELP_CONTEXTMENU, (ULONG_PTR) (LPSTR) MonitorUIHelpIds);
  1111. return (TRUE);
  1112. }