test: devprop.cpp Source File

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

# devprop.cpp

Go to the documentation of this file.

    00001 /******************************************************************************
    00002
    00003   Source File:  Device Profile Management .CPP
    00004
    00005   Change History:
    00006
    00007
    00008   Implements the class which provides the various device profile management UI
    00009
    00010   Copyright (c) 1996 by Microsoft Corporation
    00011
    00012   A Pretty Penny Enterprises, Inc. Production
    00013   11-27-96  a-RobKj@microsoft.com coded it
    00014
    00015 ******************************************************************************/
    00016
    00017 #include    "ICMUI.H"
    00018
    00019 //
    00020 // This function is obtained from the April 1998 Knowledge Base
    00021 // Its purpose is to determine if the current user is an
    00022 // Administrator and therefore priveledged to change profile
    00023 // settings.
    00024 //
    00025 // BOOL IsAdmin(void)
    00026 //
    00027 //      returns TRUE if user is an admin
    00028 //              FALSE if user is not an admin
    00029 //
    00030
    00031 #if defined(_WIN95_)
    00032
    00033 //
    00034 // Always administrator on Windows 9x platform.
    00035 //
    00036
    00037 BOOL IsAdmin(void) {
    00038
    00039     return (TRUE);
    00040 }
    00041
    00042 #else
    00043
    00044 BOOL IsAdmin(void)
    00045 {
    00046     BOOL   fReturn = FALSE;
    00047     PSID   psidAdmin;
    00048
    00049     SID_IDENTIFIER_AUTHORITY SystemSidAuthority= SECURITY_NT_AUTHORITY;
    00050
    00051     if ( AllocateAndInitializeSid ( &SystemSidAuthority, 2,
    00052             SECURITY_BUILTIN_DOMAIN_RID,
    00053             DOMAIN_ALIAS_RID_ADMINS,
    00054             0, 0, 0, 0, 0, 0, &psidAdmin) )
    00055     {
    00056         if(!CheckTokenMembership( NULL, psidAdmin, &fReturn )) {
    00057
    00058           //
    00059           // explicitly disallow Admin Access if CheckTokenMembership fails.
    00060           //
    00061
    00062           fReturn = FALSE;
    00063         }
    00064         FreeSid ( psidAdmin);
    00065     }
    00066
    00067     return ( fReturn );
    00068 }
    00069
    00070 #endif // _WIN95_
    00071
    00072 /******************************************************************************
    00073
    00074   List Managment functions
    00075
    00076   The method used here is simlar to that used in the profile Managment sheets
    00077   for managing device associations.
    00078
    00079   We (not royal, I mean the OS and I) manage two "to-do" lists and use these
    00080   to show the user the anticipated result of these lists being applied.  The
    00081   first list is a list of existing associations that are to be broken.  The
    00082   second is one of new associations to be made.  This is coupled with a list
    00083   of the current associations.
    00084
    00085   The "Removals" list is the indices of existing associations which will be
    00086   borken.  The "Adds" list is a list of new profiles to be associated.  The
    00087   "Profiles" list is the list of existing associations.
    00088
    00089   Adding and removing profiles could mean removing an item from one of the work
    00090   lists (undoing a previous selection), or adding one.  Each time such a change
    00091   is made, the profile list box is emptied and refilled.  This lets us avoid
    00092   mapping removals and additions more directly.
    00093
    00094   When changes are commited, either with Apply or OK, we make or break
    00095   associations as specified, then empty all of the lists, and rebuild the list
    00096   of current associations.
    00097
    00098   We use the ITEMDATA of the UI list box to handle the associations.  This lets
    00099   the list remain sorted.
    00100
    00101   All of the list management functions can be overriden, if needed.
    00102
    00103 ******************************************************************************/
    00104
    00105 void    CDeviceProfileManagement::InitList() {
    00106
    00107     //  Make sure the lists are empty.
    00108
    00109     m_cuaRemovals.Empty();
    00110     m_cpaAdds.Empty();
    00111
    00112     //  Determine the associations for the target device.
    00113
    00114     ENUMTYPE    et = {sizeof et, ENUM_TYPE_VERSION, ET_DEVICENAME, m_csDevice};
    00115
    00116     CProfile::Enumerate(et, m_cpaProfile);
    00117 }
    00118
    00119 //  Fill the UI list of profiles
    00120
    00121 void    CDeviceProfileManagement::FillList(DWORD dwFlags) {
    00122
    00123     //  Before reset list box, get current selection to restore later.
    00124
    00125     CString csSelect;
    00126
    00127     csSelect.Empty();
    00128
    00129     LRESULT idSelect = LB_ERR;
    00130
    00131     if ( !(dwFlags & DEVLIST_NOSELECT)) {
    00132
    00133         //  Get current selected position.
    00134
    00135         idSelect = SendMessage(m_hwndList, LB_GETCURSEL, 0, 0);
    00136
    00137         //  Get text length where currently selected, than allocate buffer for that.
    00138
    00139         DWORD   dwLen = (DWORD) SendMessage(m_hwndList, LB_GETTEXTLEN, idSelect, 0);
    00140         TCHAR  *pszSelect = new TCHAR[dwLen + 1];
    00141
    00142         //  Get text itself.
    00143
    00144         if (pszSelect != NULL) {
    00145
    00146             if (SendMessage(m_hwndList, LB_GETTEXT, idSelect, (LPARAM) pszSelect) != LB_ERR) {
    00147                 csSelect = pszSelect;
    00148             }
    00149
    00150             delete pszSelect;
    00151         }
    00152     }
    00153
    00154     //  reset list box
    00155
    00156     SendMessage(m_hwndList, LB_RESETCONTENT, 0, 0);
    00157
    00158     //  Fill the profile list box from the list of profiles
    00159
    00160     for (unsigned u = 0; u < m_cpaProfile.Count(); u++) {
    00161
    00162         //  Don't list profiles tentatively disassociated...
    00163
    00164         for (unsigned uOut = 0; uOut < m_cuaRemovals.Count(); uOut++)
    00165             if  (m_cuaRemovals[uOut] == u)
    00166                 break;
    00167
    00168         if  (uOut < m_cuaRemovals.Count())
    00169             continue;   //  Don't add this to list, it's been zapped!
    00170
    00171         LRESULT id = SendMessage(m_hwndList, LB_ADDSTRING, 0,
    00172             (LPARAM) (LPCTSTR) m_cpaProfile[u] -> GetName());
    00173
    00174         SendMessage(m_hwndList, LB_SETITEMDATA, id, u);
    00175     }
    00176
    00177     //  Add the profiles that have been tentatively added...
    00178
    00179     for (u = 0; u < m_cpaAdds.Count(); u ++) {
    00180         LRESULT id = SendMessage(m_hwndList, LB_ADDSTRING, 0,
    00181             (LPARAM) (LPCTSTR) m_cpaAdds[u] -> GetName());
    00182         SendMessage(m_hwndList, LB_SETITEMDATA, id, u + m_cpaProfile.Count());
    00183     }
    00184
    00185     //  If we have any profiles, select the first one
    00186     //  Otherwise, disable the "Remove" button, as there's nothing to remove
    00187
    00188     unsigned itemCount = (m_cpaProfile.Count() + m_cpaAdds.Count() - m_cuaRemovals.Count());
    00189
    00190     if  (itemCount) {
    00191
    00192         // The Remove button must remain disabled
    00193         // unless the user is Administrator.
    00194         // This code is specific to the Monitor Profile
    00195         // Property sheet.
    00196
    00197         if (!m_bReadOnly) {
    00198             EnableWindow(GetDlgItem(m_hwnd, RemoveButton), TRUE);
    00199         }
    00200
    00201         if ( !(dwFlags & DEVLIST_NOSELECT)) {
    00202
    00203             // Find out the string selected previously.
    00204
    00205             idSelect = LB_ERR;
    00206
    00207             if (!csSelect.IsEmpty()) {
    00208                 idSelect = SendMessage(m_hwndList, LB_FINDSTRINGEXACT,
    00209                                        (WPARAM) -1, (LPARAM) (LPCTSTR) csSelect);
    00210             }
    00211
    00212             // if could not find, just select first item.
    00213
    00214             if (idSelect == LB_ERR) {
    00215                 idSelect = 0;
    00216             }
    00217
    00218             // Select it.
    00219
    00220             SendMessage(m_hwndList, LB_SETCURSEL, idSelect, 0);
    00221         }
    00222
    00223     } else {
    00224
    00225         HWND hwndRemove = GetDlgItem(m_hwnd, RemoveButton);
    00226
    00227         // If focus is on Remove, move it to Add button.
    00228
    00229         if (GetFocus() == hwndRemove) {
    00230
    00231             HWND hwndAdd = GetDlgItem(m_hwnd, AddButton);
    00232
    00233             SetFocus(hwndAdd);
    00234             SendMessage(hwndRemove, BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE, 0));
    00235             SendMessage(hwndAdd, BM_SETSTYLE, BS_DEFPUSHBUTTON, MAKELPARAM(TRUE, 0));
    00236         }
    00237
    00238         EnableWindow(hwndRemove, FALSE);
    00239     }
    00240
    00241     // Apply button needs to remain disabled unless the
    00242     // user has permision to make changes - ie. user
    00243     // is Administrator.
    00244
    00245     if  ((dwFlags & DEVLIST_CHANGED) && !(m_bReadOnly)) {
    00246         EnableApplyButton();
    00247         SettingChanged(TRUE);
    00248     }
    00249 }
    00250
    00251 void CDeviceProfileManagement::GetDeviceTypeString(DWORD dwType,CString& csDeviceName) {
    00252
    00253     DWORD id;
    00254
    00255     switch (dwType) {
    00256
    00257     case CLASS_MONITOR :
    00258         id = ClassMonitorString;
    00259         break;
    00260     case CLASS_PRINTER :
    00261         id = ClassPrinterString;
    00262         break;
    00263     case CLASS_SCANNER :
    00264         id = ClassScannerString;
    00265         break;
    00266     case CLASS_LINK :
    00267         id = ClassLinkString;
    00268         break;
    00269     case CLASS_ABSTRACT :
    00270         id = ClassAbstractString;
    00271         break;
    00272     case CLASS_NAMED :
    00273         id = ClassNamedString;
    00274         break;
    00275     case CLASS_COLORSPACE :
    00276     default :
    00277         id = ClassColorSpaceString;
    00278         break;
    00279     }
    00280
    00281     // Load string.
    00282
    00283     csDeviceName.Load(id);
    00284 }
    00285
    00286 //  Constructor
    00287
    00288 CDeviceProfileManagement::CDeviceProfileManagement(LPCTSTR lpstrDevice,
    00289                                                    HINSTANCE hiWhere,
    00290                                                    int idPage, DWORD dwType) {
    00291         m_csDevice = lpstrDevice;
    00292     m_dwType = dwType;
    00293     m_psp.hInstance = hiWhere;
    00294     m_psp.pszTemplate = MAKEINTRESOURCE(idPage);
    00295
    00296     //  Setting m_bReadOnly to false enables functionality
    00297
    00298     m_bReadOnly = FALSE;        // default setting is false
    00299
    00300 #if defined(_WIN95_)
    00301
    00302     //
    00303     // There is no way to detect printer supports CMYK or not on Win 9x.
    00304
    00305     m_bCMYK = TRUE;
    00306
    00307 #else
    00308
    00309     //  we need to check the device capabilities
    00310     //  and determine if we're trying to associate
    00311     //  a cmyk printer profile to a printer that
    00312     //  doesn't support it.
    00313
    00314     m_bCMYK = FALSE;            // default setting - don't support cmyk
    00315
    00316     //  if the device is a printer
    00317
    00318     if (m_dwType == CLASS_PRINTER) {
    00319
    00320         HDC hdcThis = CGlobals::GetPrinterHDC(m_csDevice);
    00321
    00322         //  if the printer supports CMYK
    00323
    00324         if (hdcThis) {
    00325             if (GetDeviceCaps(hdcThis, COLORMGMTCAPS) & CM_CMYK_COLOR) {
    00326                 m_bCMYK = TRUE;
    00327             }
    00328             DeleteDC(hdcThis);
    00329         }
    00330     }
    00331
    00332 #endif // defined(_WIN95_)
    00333 }
    00334
    00335 //  UI initialization
    00336
    00337 BOOL    CDeviceProfileManagement::OnInit() {
    00338
    00339     InitList();
    00340
    00341     m_hwndList = GetDlgItem(m_hwnd, ProfileListControl);
    00342
    00343     //  Fill the profile list box
    00344
    00345     FillList(DEVLIST_ONINIT);
    00346
    00347     //  Disable apply button as default.
    00348
    00349     DisableApplyButton();
    00350
    00351     //  Nothing changed, yet.
    00352
    00353     SettingChanged(FALSE);
    00354
    00355     return  TRUE;
    00356 }
    00357
    00358 //  Command processing
    00359
    00360 BOOL    CDeviceProfileManagement::OnCommand(WORD wNotifyCode, WORD wid,
    00361                                              HWND hwndCtl) {
    00362
    00363     switch  (wNotifyCode) {
    00364
    00365         case    BN_CLICKED:
    00366
    00367             switch  (wid) {
    00368
    00369                 case    AddButton: {
    00370
    00371                     unsigned i = 0, u = 0;
    00372
    00373                     //  Time to do the old OpenFile dialog stuff...
    00374
    00375                     CAddProfileDialog capd(m_hwnd, m_psp.hInstance);
    00376
    00377                     //  See if a profile was selected
    00378
    00379                     while(i < capd.ProfileCount()) {
    00380
    00381                         //  Check profile validity and device type
    00382
    00383                         CProfile cpTemp(capd.ProfileName(i));
    00384
    00385                         //  CLASS_COLORSPACE and CLASS_MONITOR can be associated to
    00386                         //  any device. Other (CLASS_SCANNER, CLASS_PRINTER) only
    00387                         //  can be associated to much device.
    00388
    00389                         if (    !cpTemp.IsValid() // Wrong profile type or invalid?
    00390                              || (   cpTemp.GetType() != m_dwType
    00391                                  && cpTemp.GetType() != CLASS_COLORSPACE
    00392                         #if 1 // ALLOW_MONITOR_PROFILE_TO_ANY_DEVICE
    00393                                  && cpTemp.GetType() != CLASS_MONITOR
    00394                         #endif
    00395                                 )
    00396                            ) {
    00397
    00398                             //  Throw up a message box to inform the user of this
    00399
    00400                             if (cpTemp.IsValid())
    00401                             {
    00402                                 CString csDeviceType;  GetDeviceTypeString(m_dwType,csDeviceType);
    00403                                 CString csProfileType; GetDeviceTypeString(cpTemp.GetType(),csProfileType);
    00404
    00405                                 CGlobals::ReportEx(MismatchDeviceType, m_hwnd, FALSE,
    00406                                                MB_OK|MB_ICONEXCLAMATION, 3,
    00407                                                (LPTSTR)capd.ProfileNameAndExtension(i),
    00408                                                (LPTSTR)csProfileType,
    00409                                                (LPTSTR)csDeviceType);
    00410                             }
    00411                             else
    00412                             {
    00413                                 CGlobals::ReportEx(InstFailedWithName, m_hwnd, FALSE,
    00414                                                MB_OK|MB_ICONEXCLAMATION, 1,
    00415                                                (LPTSTR)capd.ProfileNameAndExtension(i));
    00416                             }
    00417
    00418                             goto SkipToNext;
    00419                         }
    00420
    00421                         //  See if the profile has already been listed for addition
    00422
    00423                         for (u = 0; u < m_cpaAdds.Count(); u++) {
    00424                             if  (!lstrcmpi(m_cpaAdds[u] -> GetName(), cpTemp.GetName())) {
    00425                                 goto SkipToNext; //  This profile is already added
    00426                             }
    00427                         }
    00428
    00429                         //  If this profile is on the existing list, either ignore
    00430                         //  or zap it from the removal list, as the case may be
    00431
    00432                         for (u = 0; u < m_cpaProfile.Count(); u++) {
    00433                             if  (!lstrcmpi(m_cpaProfile[u] -> GetName(),
    00434                                     cpTemp.GetName())) {
    00435                                 //  Is this one on the removal list?
    00436                                 for (unsigned uOut = 0;
    00437                                      uOut < m_cuaRemovals.Count();
    00438                                      uOut++) {
    00439                                     if  (m_cuaRemovals[uOut] == u) {
    00440                                         //  Was to be removed- undo that...
    00441                                         m_cuaRemovals.Remove(uOut);
    00442                                         FillList(DEVLIST_CHANGED);
    00443                                         break;
    00444                                     }
    00445                                 }
    00446                                 goto SkipToNext;
    00447                             }   //  End of name in existing list
    00448                         }
    00449
    00450                         //  We need to check the device capabilities
    00451                         //  and determine if we're trying to associate
    00452                         //  a cmyk printer profile to a printer that
    00453                         //  doesn't support it.
    00454
    00455                         if  ((!m_bCMYK) && (cpTemp.GetColorSpace() == SPACE_CMYK)) {
    00456                             CGlobals::ReportEx(UnsupportedProfile, m_hwnd, FALSE,
    00457                                                 MB_OK|MB_ICONEXCLAMATION, 2,
    00458                                                 (LPTSTR)m_csDevice,
    00459                                                 (LPTSTR)capd.ProfileNameAndExtension(i));
    00460                             goto SkipToNext;
    00461                         }
    00462
    00463                         //  Add this profile to the list, item (max orig + index)
    00464
    00465                         m_cpaAdds.Add(capd.ProfileName(i));
    00466
    00467                         //  Change has been made, update the list
    00468
    00469                         FillList(DEVLIST_CHANGED);
    00470 SkipToNext:
    00471                         i++;
    00472                     }
    00473
    00474                     return  TRUE;
    00475                 }
    00476
    00477                 case    RemoveButton: {
    00478
    00479                     //  Remove the selected profile
    00480
    00481                     LRESULT id = SendMessage(m_hwndList, LB_GETCURSEL, 0, 0);
    00482                     unsigned u = (unsigned) SendMessage(m_hwndList,
    00483                         LB_GETITEMDATA, id, 0);
    00484
    00485                     //  If this is a tentative add, just drop it, otherwise
    00486                     //  note that it's been removed...
    00487
    00488                     if  (u >= m_cpaProfile.Count())
    00489                         m_cpaAdds.Remove(u - m_cpaProfile.Count());
    00490                     else
    00491                         m_cuaRemovals.Add(u);
    00492
    00493                     //  That's it- just update the display, now...
    00494
    00495                     FillList(DEVLIST_CHANGED);
    00496
    00497                     // explicitly set the position of the current selection
    00498                     // after the list has been recomputed.
    00499
    00500                     int listsize = m_cpaProfile.Count()+m_cpaAdds.Count()-m_cuaRemovals.Count();
    00501                     if (id >= listsize) id = listsize-1;
    00502                     if (id < 0)         id = 0;
    00503                     SendMessage(m_hwndList, LB_SETCURSEL, id, 0);
    00504
    00505                     return  TRUE;
    00506                 }
    00507             }
    00508             break;
    00509
    00510         case    LBN_SELCHANGE: {
    00511
    00512             LRESULT id = SendMessage(m_hwndList, LB_GETCURSEL, 0, 0);
    00513
    00514             if (id == -1) {
    00515                 EnableWindow(GetDlgItem(m_hwnd, RemoveButton), FALSE);
    00516             } else {
    00517
    00518                 // The Remove button must remain disabled on a monitor
    00519                 // profile property page if the user isn't the
    00520                 // Administrator, otherwise enable remove button.
    00521
    00522                 EnableWindow(GetDlgItem(m_hwnd, RemoveButton), !m_bReadOnly);
    00523             }
    00524
    00525             return  TRUE;
    00526         }
    00527     }
    00528
    00529     return  FALSE;
    00530 }
    00531
    00532 //  Property Sheet notification processing
    00533
    00534 BOOL    CDeviceProfileManagement::OnNotify(int idCtrl, LPNMHDR pnmh) {
    00535
    00536     switch  (pnmh -> code) {
    00537
    00538         case    PSN_APPLY:
    00539
    00540             DisableApplyButton();
    00541
    00542             if (SettingChanged()) {
    00543
    00544                 //  Apply the changes the user has made...
    00545
    00546                 SettingChanged(FALSE);
    00547
    00548                 while   (m_cpaAdds.Count()) {
    00549                     if  (!m_cpaAdds[0] -> IsInstalled()) {
    00550                         m_cpaAdds[0] -> Install();
    00551                     }
    00552                     m_cpaAdds[0] -> Associate(m_csDevice);
    00553                     m_cpaAdds.Remove(0);
    00554                 }
    00555
    00556                 //  Now do the removals (actually just dissociations)
    00557
    00558                 while   (m_cuaRemovals.Count()) {
    00559                     m_cpaProfile[m_cuaRemovals[0]] -> Dissociate(m_csDevice);
    00560                     m_cuaRemovals.Remove(0);
    00561                 }
    00562
    00563                 InitList();
    00564                 FillList();
    00565
    00566                 SetWindowLongPtr(m_hwnd, DWLP_MSGRESULT, PSNRET_NOERROR);
    00567             }
    00568
    00569             return  TRUE;
    00570     }
    00571
    00572     return  FALSE;
    00573 }
    00574
    00575 //  This hook procedure both forces the use of the old-style common dialog
    00576 //  and changes the OK button to an Add button.  The actual button text is
    00577 //  a string resource, and hence localizable.
    00578
    00579 UINT_PTR APIENTRY CAddProfileDialog::OpenFileHookProc(HWND hDlg, UINT uMessage,
    00580                                                   WPARAM wp, LPARAM lp) {
    00581     switch  (uMessage) {
    00582
    00583         case    WM_INITDIALOG: {
    00584
    00585             CString csAddButton;
    00586
    00587             OPENFILENAME    *pofn = (OPENFILENAME *) lp;
    00588
    00589             csAddButton.Load(AddButtonText);
    00590
    00591             SetDlgItemText(GetParent(hDlg), IDOK, csAddButton);
    00592             return  TRUE;
    00593         }
    00594     }
    00595
    00596     return  FALSE;
    00597 }
    00598
    00599 //  Once again, a constructor that actually does most of the work!
    00600
    00601 TCHAR gacColorDir[MAX_PATH] = _TEXT("\0");
    00602 TCHAR gacFilter[MAX_PATH]   = _TEXT("\0");
    00603
    00604 CAddProfileDialog::CAddProfileDialog(HWND hwndOwner, HINSTANCE hi) {
    00605
    00606     TCHAR tempBuffer[MAX_PATH*10];
    00607
    00608     // Empty the profile list.
    00609
    00610     csa_Files.Empty();
    00611
    00612     // Prepare file filter (if not yet).
    00613
    00614     if (gacFilter[0] == NULL) {
    00615
    00616         ULONG offset; /* 32bits is enough even for sundown */
    00617         CString csIccFilter; CString csAllFilter;
    00618
    00619         // If the filter is not built yet, build it here.
    00620
    00621         csIccFilter.Load(IccProfileFilterString);
    00622         csAllFilter.Load(AllProfileFilterString);
    00623         offset = 0;
    00624         lstrcpy(gacFilter+offset, csIccFilter);
    00625         offset += lstrlen(csIccFilter)+1;
    00626         lstrcpy(gacFilter+offset, TEXT("*.icm;*.icc"));
    00627         offset += lstrlen(TEXT("*.icm;*.icc"))+1;
    00628         lstrcpy(gacFilter+offset, csAllFilter);
    00629         offset += lstrlen(csAllFilter)+1;
    00630         lstrcpy(gacFilter+offset, TEXT("*.*"));
    00631         offset += lstrlen(TEXT("*.*"))+1;
    00632         *(gacFilter+offset) = TEXT('\0');
    00633     }
    00634
    00635     if (gacColorDir[0] == _TEXT('\0'))  {
    00636         DWORD dwcbDir = MAX_PATH;
    00637         GetColorDirectory(NULL, gacColorDir, &dwcbDir);
    00638     }
    00639
    00640     //  Time to do the old OpenFile dialog stuff...
    00641     CString csTitle; csTitle.Load(AddProfileAssociation);
    00642
    00643     //  Set initial filename as null.
    00644     memset(tempBuffer, 0, sizeof tempBuffer);
    00645
    00646     OPENFILENAME ofn = {
    00647         sizeof ofn, hwndOwner, hi,
    00648         gacFilter,
    00649         NULL, 0, 1,
    00650         tempBuffer, sizeof tempBuffer / sizeof tempBuffer[0],
    00651         NULL, 0,
    00652         gacColorDir,
    00653         csTitle,
    00654         OFN_ALLOWMULTISELECT | OFN_EXPLORER | OFN_HIDEREADONLY |
    00655         OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_ENABLEHOOK,
    00656         0, 0,
    00657         _TEXT("icm"),
    00658         (LPARAM) this, OpenFileHookProc, NULL};
    00659
    00660     if  (!GetOpenFileName(&ofn)) {
    00661         if (CommDlgExtendedError() == FNERR_BUFFERTOOSMALL) {
    00662             CGlobals::Report(TooManyFileSelected);
    00663         }
    00664     } else {
    00665         if (tempBuffer[0] != TEXT('\0')) {
    00666
    00667             TCHAR *pPath = tempBuffer;
    00668             TCHAR *pFile = tempBuffer + lstrlen(tempBuffer) + 1;
    00669
    00670             // remember the last access-ed directory.
    00671
    00672             memset(gacColorDir, 0, sizeof pPath);
    00673             memcpy(gacColorDir, pPath, ofn.nFileOffset*sizeof(TCHAR));
    00674
    00675             if (*pFile) {
    00676                 TCHAR workBuffer[MAX_PATH];
    00677
    00678                 // This is multiple-selection
    00679                 // Work through the buufer to build profile file list.
    00680
    00681                 while (*pFile) {
    00682
    00683                     lstrcpy(workBuffer,pPath);
    00684                     lstrcat(workBuffer,TEXT("\\"));
    00685                     lstrcat(workBuffer,pFile);
    00686
    00687                     // Insert built profile pathname
    00688                     AddProfile(workBuffer);
    00689
    00690                     // Move on to next.
    00691                     pFile = pFile + lstrlen(pFile) + 1;
    00692                 }
    00693             }
    00694             else {
    00695                 // Single selection case.
    00696                 AddProfile(pPath);
    00697
    00698                 #if HIDEYUKN_DBG
    00699                 MessageBox(NULL,pPath,TEXT(""),MB_OK);
    00700                 #endif
    00701             }
    00702         }
    00703     }
    00704
    00705     return;
    00706 }
    00707
    00708 //  Printer Profile Management
    00709
    00710 CONST DWORD PrinterUIHelpIds[] = {
    00711     AddButton,              IDH_PRINTERUI_ADD,
    00712     RemoveButton,           IDH_PRINTERUI_REMOVE,
    00713     ProfileListControl,     IDH_PRINTERUI_LIST,
    00714
    00715 #if !defined(_WIN95_)
    00716     ProfileListControlText, IDH_PRINTERUI_LIST,
    00717     PrinterUIIcon,          IDH_DISABLED,
    00718     DescriptionText,        IDH_DISABLED,
    00719     DefaultButton,          IDH_PRINTERUI_DEFAULTBTN,
    00720     AutoSelButton,          IDH_PRINTERUI_AUTOMATIC,
    00721     AutoSelText,            IDH_PRINTERUI_AUTOMATIC,
    00722     ManualSelButton,        IDH_PRINTERUI_MANUAL,
    00723     ManualSelText,          IDH_PRINTERUI_MANUAL,
    00724     DefaultProfileText,     IDH_PRINTERUI_DEFAULTTEXT,
    00725     DefaultProfile,         IDH_PRINTERUI_DEFAULTTEXT,
    00726 #endif
    00727     0, 0
    00728 };
    00729
    00730 //  Initialize lists override- call the base class, then set the default
    00731
    00732 void    CPrinterProfileManagement::InitList() {
    00733
    00734     CDeviceProfileManagement::InitList();
    00735
    00736     m_uDefault = m_cpaProfile.Count() ? 0 : (unsigned) -1;
    00737 }
    00738
    00739 //  Fill list override- write the correct default and call the base function
    00740
    00741 void    CPrinterProfileManagement::FillList(DWORD dwFlags) {
    00742
    00743     //  If we are initializing list box, we want to put focus on
    00744     //  "default" profile. here we won't below FillList set focus
    00745     //  to first one.
    00746
    00747     if (dwFlags & DEVLIST_ONINIT) {
    00748         dwFlags |= DEVLIST_NOSELECT;
    00749     }
    00750
    00751     CDeviceProfileManagement::FillList(dwFlags);
    00752
    00753     //  There is either no default profile, an existing profile is the
    00754     //  default, or a newly selected one is.  Some people just like the
    00755     //  selection operator.
    00756
    00757     //  if there is only 1 profile in list box, we treat it as default profile.
    00758
    00759     if (SendMessage(m_hwndList,LB_GETCOUNT,0,0) == 1) {
    00760         m_uDefault = (unsigned)SendMessage(m_hwndList, LB_GETITEMDATA, 0, 0);
    00761     }
    00762
    00763     if (m_uDefault == -1) {
    00764
    00765         // There is no profile associated for this device.
    00766
    00767         CString csNoProfile;
    00768         csNoProfile.Load(NoProfileString);
    00769         SetDlgItemText(m_hwnd, DefaultProfile, csNoProfile);
    00770
    00771     } else {
    00772
    00773         // If the default has been deleted, set default as last in list.
    00774
    00775         if (m_uDefault >= (m_cpaProfile.Count() + m_cpaAdds.Count())) {
    00776
    00777             m_uDefault = (m_cpaProfile.Count() + m_cpaAdds.Count()) - 1;
    00778         }
    00779
    00780         // Put default profile name in UI.
    00781
    00782         CProfile *pcpDefault = (m_uDefault < m_cpaProfile.Count()) ? \
    00783                                            m_cpaProfile[m_uDefault] : \
    00784                                            m_cpaAdds[m_uDefault - m_cpaProfile.Count()];
    00785
    00786         SetDlgItemText(m_hwnd, DefaultProfile, pcpDefault -> GetName());
    00787
    00788         LRESULT idSelect = SendMessage(m_hwndList, LB_FINDSTRINGEXACT,
    00789                                    (WPARAM) -1, (LPARAM) (LPCTSTR) pcpDefault -> GetName());
    00790
    00791         // if could not find, just select first item.
    00792
    00793         if (idSelect == LB_ERR) {
    00794             idSelect = 0;
    00795         }
    00796
    00797         // Select it.
    00798
    00799         SendMessage(m_hwndList, LB_SETCURSEL, idSelect, 0);
    00800     }
    00801
    00802     //  03-08-1997  Bob_Kjelgaard@Prodigy.Net   Memphis RAID 18420
    00803     //  Disable the Default button if there aren't any profiles
    00804
    00805     if (m_bManualMode && m_bAdminAccess) {
    00806         EnableWindow(GetDlgItem(m_hwnd, DefaultButton),
    00807                      m_cpaAdds.Count() + m_cpaProfile.Count() - m_cuaRemovals.Count());
    00808     }
    00809 }
    00810
    00811 //  Printer Profile Management class constructor- doesn't need any individual
    00812 //  code at the moment.
    00813
    00814 CPrinterProfileManagement::CPrinterProfileManagement(LPCTSTR lpstrName,
    00815                                                      HINSTANCE hiWhere) :
    00816     CDeviceProfileManagement(lpstrName, hiWhere, PrinterUI, CLASS_PRINTER) {
    00817 }
    00818
    00819 //  This class overrides OnInit so it can disable the UI if the user lacks
    00820 //  authority to make changes.
    00821
    00822 BOOL    CPrinterProfileManagement::OnInit() {
    00823
    00824     //  Call the base class routine first, as it does most of the work...
    00825
    00826     CDeviceProfileManagement::OnInit();
    00827
    00828     DWORD dwSize = sizeof(DWORD);
    00829
    00830     //  Query current mode.
    00831
    00832     if (!InternalGetDeviceConfig((LPCTSTR)m_csDevice, CLASS_PRINTER,
    00833                                  MSCMS_PROFILE_ENUM_MODE, &m_bManualMode, &dwSize)) {
    00834
    00835         //  Auto selection mode as default.
    00836
    00837         m_bManualMode = FALSE;
    00838     }
    00839
    00840     //  Now, see if we have sufficient authority to administer the printer
    00841
    00842     HANDLE  hPrinter;
    00843     PRINTER_DEFAULTS    pd = {NULL, NULL, PRINTER_ACCESS_ADMINISTER};
    00844
    00845     m_bAdminAccess  = TRUE;
    00846     m_bLocalPrinter = TRUE;
    00847
    00848     if  (OpenPrinter(const_cast<LPTSTR> ((LPCTSTR) m_csDevice), &hPrinter, &pd)) {
    00849
    00850         //  We can administer the printer- proceed in the normal way.
    00851
    00852 #if !defined(_WIN95_)
    00853
    00854         //  If the printer is "Network Printer", we don't allow user to install
    00855         //  or uninstall color profile.
    00856
    00857         BYTE  StackPrinterData[sizeof(PRINTER_INFO_4)+MAX_PATH*2];
    00858         PBYTE pPrinterData = StackPrinterData;
    00859         BOOL  bSuccess = TRUE;
    00860         DWORD dwReturned;
    00861
    00862         if (!GetPrinter(hPrinter, 4, pPrinterData, sizeof(StackPrinterData), &dwReturned)) {
    00863
    00864             if ((GetLastError() == ERROR_INSUFFICIENT_BUFFER) &&
    00865                 (pPrinterData = (PBYTE) LocalAlloc(LPTR, dwReturned))) {
    00866
    00867                 if (GetPrinter(hPrinter, 4, pPrinterData, dwReturned, &dwReturned)) {
    00868
    00869                     bSuccess = TRUE;
    00870
    00871                 }
    00872             }
    00873
    00874         } else {
    00875
    00876             bSuccess = TRUE;
    00877         }
    00878
    00879         if (bSuccess)
    00880         {
    00881             m_bLocalPrinter = ((PRINTER_INFO_4 *)pPrinterData)->pServerName ? FALSE : TRUE;
    00882         }
    00883         else
    00884         {
    00885             m_bAdminAccess = FALSE;
    00886         }
    00887
    00888         if (pPrinterData && (pPrinterData != StackPrinterData))
    00889         {
    00890             LocalFree(pPrinterData);
    00891         }
    00892
    00893 #endif // !defined(_WIN95_)
    00894
    00895         ClosePrinter(hPrinter);
    00896
    00897     } else {
    00898
    00899         m_bAdminAccess = FALSE;
    00900     }
    00901
    00902     // How many profile in listbox ?
    00903
    00904     LRESULT itemCount = SendMessage(m_hwndList, LB_GETCOUNT, 0, 0);
    00905     if (itemCount == LB_ERR) itemCount = 0;
    00906
    00907     //  make sure the ancestor list code behaves correctly.
    00908     //  You need Admin Access and a Local Printer to be able to add/remove profiles
    00909
    00910     m_bReadOnly = !(m_bAdminAccess && m_bLocalPrinter);
    00911
    00912     //  Enable/Disable the controls (if needed)
    00913
    00914     CheckDlgButton(m_hwnd, AutoSelButton, m_bManualMode ? BST_UNCHECKED : BST_CHECKED);
    00915     CheckDlgButton(m_hwnd, ManualSelButton, m_bManualMode ? BST_CHECKED : BST_UNCHECKED);
    00916
    00917     //  Only administrator can change 'auto','manual' configuration.
    00918
    00919     EnableWindow(GetDlgItem(m_hwnd, AutoSelButton), m_bAdminAccess && m_bLocalPrinter);
    00920     EnableWindow(GetDlgItem(m_hwnd, ManualSelButton), m_bAdminAccess && m_bLocalPrinter);
    00921
    00922     //  Only administrator and printer is at local, can install/uninstall color profile.
    00923
    00924     EnableWindow(GetDlgItem(m_hwnd, AddButton), m_bAdminAccess && m_bLocalPrinter);
    00925     EnableWindow(GetDlgItem(m_hwnd, RemoveButton), m_bAdminAccess && m_bLocalPrinter && itemCount);
    00926
    00927     EnableWindow(m_hwndList, m_bAdminAccess);
    00928     EnableWindow(GetDlgItem(m_hwnd, DefaultProfileText), m_bAdminAccess);
    00929     EnableWindow(GetDlgItem(m_hwnd, DefaultProfile), m_bAdminAccess);
    00930
    00931     //  Only with manual mode, these controls are enabled.
    00932
    00933     EnableWindow(GetDlgItem(m_hwnd, DefaultButton), m_bAdminAccess && m_bManualMode
    00934                                                          && m_bLocalPrinter && itemCount);
    00935
    00936     if (!m_bAdminAccess) {
    00937
    00938         //  Set the focus to the OK button
    00939
    00940         SetFocus(GetDlgItem(m_hwndSheet, IDOK));
    00941         return  FALSE;  //  Because we moved the focus!
    00942     }
    00943
    00944     return TRUE;
    00945 }
    00946
    00947 //  Command processing- we never let them click into the edit control, to
    00948 //  prevent them from editing it.
    00949
    00950 BOOL    CPrinterProfileManagement::OnCommand(WORD wNotifyCode, WORD wid,
    00951                                              HWND hwndCtl) {
    00952
    00953     switch  (wNotifyCode) {
    00954
    00955         case    LBN_DBLCLK: {
    00956
    00957             //  Retrieve the ID of the new default profile
    00958             //  only accept dblclk changes if the dialog
    00959             //  is not read only - i.e. user is admin
    00960
    00961             if  (m_bManualMode) {
    00962
    00963                 int id = (int)SendMessage(m_hwndList, LB_GETCURSEL, 0, 0);
    00964                 m_uDefault = (unsigned)SendMessage(m_hwndList, LB_GETITEMDATA, id, 0);
    00965
    00966                 //  Change has been made, update the list
    00967
    00968                 FillList(DEVLIST_CHANGED);
    00969             }
    00970
    00971             return  TRUE;
    00972         }
    00973
    00974         case    BN_CLICKED:
    00975
    00976             switch  (wid) {
    00977
    00978                 case    AutoSelButton:
    00979                 case    ManualSelButton: {
    00980
    00981                     // How many profile in listbox ?
    00982
    00983                     LRESULT itemCount = SendMessage(m_hwndList, LB_GETCOUNT, 0, 0);
    00984                     if (itemCount == LB_ERR) itemCount = 0;
    00985
    00986                     m_bManualMode = (wid == ManualSelButton) ? TRUE : FALSE;
    00987
    00988                     //  Only with manual mode, these controls are enabled.
    00989
    00990                     EnableWindow(GetDlgItem(m_hwnd, DefaultButton), m_bManualMode && itemCount);
    00991
    00992                     //  Configuarion has been changed, enable apply button.
    00993
    00994                     EnableApplyButton();
    00995                     SettingChanged(TRUE);
    00996
    00997                     return TRUE;
    00998                 }
    00999
    01000                 case    RemoveButton: {
    01001
    01002                     //  Make sure we've tracked the default profile correctly
    01003                     //  when a profile is removed.
    01004                     //  All cases break, because we then want the base class to
    01005                     //  process this message.
    01006
    01007                     LRESULT id = SendMessage(m_hwndList, LB_GETCURSEL, 0, 0);
    01008
    01009                     unsigned uTarget = (unsigned)SendMessage(m_hwndList, LB_GETITEMDATA,
    01010                         id, 0);
    01011
    01012                     if  (uTarget > m_uDefault || m_uDefault == (unsigned) -1)
    01013                         break;  //  Nothing here to worry about
    01014
    01015                     if  (m_uDefault == uTarget) {
    01016
    01017                         if (CGlobals::ReportEx(AskRemoveDefault, m_hwnd, FALSE,
    01018                                                MB_YESNO|MB_ICONEXCLAMATION,0) == IDYES) {
    01019
    01020                             //  The default has been deleted- the profile
    01021                             //  at the top of monitor profile list will be
    01022                             //  made the default profile, if we have
    01023
    01024                             LRESULT itemCount = SendMessage(m_hwndList, LB_GETCOUNT, 0, 0);
    01025
    01026                             if ((itemCount != LB_ERR) && (itemCount > 1)) {
    01027                                 m_uDefault = (unsigned)SendMessage(m_hwndList, LB_GETITEMDATA, 0, 0);
    01028                                 if (m_uDefault == uTarget) {
    01029                                     m_uDefault = (unsigned)SendMessage(m_hwndList, LB_GETITEMDATA, 1, 0);
    01030                                 }
    01031                             } else {
    01032                                 m_uDefault = -1;
    01033                             }
    01034
    01035                             break;
    01036                         } else {
    01037                             return TRUE; // opration cancelled.
    01038                         }
    01039                     }
    01040
    01041                     if  (uTarget < m_cpaProfile.Count())
    01042                         break;  // We're fine
    01043
    01044                     //  Must be an added profile below us in the list was
    01045                     //  zapped- we need to decrement ourselves.
    01046
    01047                     m_uDefault--;
    01048                     break;
    01049                 }
    01050
    01051                 case    DefaultButton: {
    01052
    01053                     LRESULT id = SendMessage(m_hwndList, LB_GETCURSEL, 0, 0);
    01054
    01055                     m_uDefault = (unsigned)SendMessage(m_hwndList, LB_GETITEMDATA, id, 0);
    01056
    01057                     //  Change has been made, update the list
    01058
    01059                     FillList(DEVLIST_CHANGED);
    01060
    01061                     return  TRUE;
    01062                 }
    01063             }
    01064
    01065         //  Deliberate fall-through (use a break if you add a case here)
    01066     }
    01067
    01068     //  Use common command handling if not handled above
    01069
    01070     return  CDeviceProfileManagement::OnCommand(wNotifyCode, wid, hwndCtl);
    01071 }
    01072
    01073 //  Property Sheet notification processing
    01074
    01075 BOOL    CPrinterProfileManagement::OnNotify(int idCtrl, LPNMHDR pnmh) {
    01076
    01077     switch  (pnmh -> code) {
    01078
    01079         case    PSN_APPLY: {
    01080
    01081             DisableApplyButton();
    01082
    01083             //  If nothing changed, nothing need to do.
    01084
    01085             if (!SettingChanged())
    01086                 return TRUE;
    01087
    01088             if (m_bManualMode) {
    01089
    01090                 //  If the user hasn't selected a default, and we have
    01091                 //  associated profiles, then we can't allow this.
    01092
    01093                 //  03-08-1997  A-RobKj Fix for Memphis RAID 18416- if there's
    01094                 //  only one profile left, then it must be the default.
    01095
    01096                 if  (m_uDefault == (unsigned) -1 && (m_cpaAdds.Count() +
    01097                      m_cpaProfile.Count() - m_cuaRemovals.Count()) > 1) {
    01098
    01099                     CGlobals::Report(NoDefaultProfile, m_hwndSheet);
    01100                     SetWindowLongPtr(m_hwnd, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE);
    01101                     break;
    01102                 }
    01103
    01104                 //  !!! This behavior is hardly depend on EnumColorProfiles() API !!!
    01105
    01106                 //  OK, if the default profile has changed, we have to delete default
    01107                 //  profile associations, and do the association for default profile
    01108                 //  in "last".
    01109
    01110                 //  Let the base class handle the cases where the default hasn't
    01111                 //  changed, or we started with no profiles and still have none.
    01112                 //
    01113                 //  03-08-1997  Sleazy code note.  The case where no default is
    01114                 //  selected but only one is assigned will now fall here.  Since the
    01115                 //  default happens to be the "last", and there only is one, letting
    01116                 //  the base class handle it is not a problem.  The list filling
    01117                 //  code will take care of the rest for us.
    01118
    01119                 if  (m_uDefault == (unsigned) -1) break;
    01120
    01121                 //  Remove default first (if default is associated), then associate later.
    01122
    01123                 if  (m_uDefault < m_cpaProfile.Count())
    01124                     m_cpaProfile[m_uDefault] -> Dissociate(m_csDevice);
    01125
    01126                 //  Now do the other removals (actually just dissociations)
    01127
    01128                 for (unsigned u = 0; u < m_cuaRemovals.Count(); u++) {
    01129                     m_cpaProfile[m_cuaRemovals[u]] -> Dissociate(m_csDevice);
    01130                 }
    01131
    01132                 //  Add in the new ones
    01133
    01134                 for (u = 0; u < m_cpaAdds.Count(); u++) {
    01135                     if  (m_uDefault >= m_cpaProfile.Count())
    01136                         if  (u == (m_uDefault - m_cpaProfile.Count()))
    01137                             continue;   // this is default, will be done later
    01138
    01139                     //  OK, add it back in...
    01140                     m_cpaAdds[u] -> Associate(m_csDevice);
    01141                 }
    01142
    01143                 //  Finally, associate back default profile.
    01144
    01145                 if  (m_uDefault < m_cpaProfile.Count())
    01146                     m_cpaProfile[m_uDefault] -> Associate(m_csDevice);
    01147                 else
    01148                     m_cpaAdds[m_uDefault - m_cpaProfile.Count()] -> Associate(m_csDevice);
    01149
    01150                 //  Update the various working structures...
    01151
    01152                 InitList();
    01153                 FillList();
    01154
    01155                 SetWindowLongPtr(m_hwnd, DWLP_MSGRESULT, PSNRET_NOERROR);
    01156
    01157                 //  Now, we have updated settings.
    01158
    01159                 SettingChanged(FALSE);
    01160             }
    01161
    01162             // Update "auto/manual" status.
    01163
    01164             InternalSetDeviceConfig((LPCTSTR)m_csDevice, CLASS_PRINTER,
    01165                                     MSCMS_PROFILE_ENUM_MODE, &m_bManualMode, sizeof(DWORD));
    01166         }
    01167     }
    01168
    01169     //  Let the base class handle everything else
    01170
    01171     return  CDeviceProfileManagement::OnNotify(idCtrl, pnmh);
    01172 }
    01173
    01174 //  Context-sensitive help handler
    01175
    01176 BOOL    CPrinterProfileManagement::OnHelp(LPHELPINFO pHelp) {
    01177
    01178     if (pHelp->iContextType == HELPINFO_WINDOW) {
    01179         WinHelp((HWND) pHelp->hItemHandle, WINDOWS_HELP_FILE,
    01180                 HELP_WM_HELP, (ULONG_PTR) (LPSTR) PrinterUIHelpIds);
    01181     }
    01182
    01183     return (TRUE);
    01184 }
    01185
    01186 BOOL    CPrinterProfileManagement::OnContextMenu(HWND hwnd) {
    01187
    01188     WinHelp(hwnd, WINDOWS_HELP_FILE,
    01189             HELP_CONTEXTMENU, (ULONG_PTR) (LPSTR) PrinterUIHelpIds);
    01190
    01191     return (TRUE);
    01192 }
    01193
    01194 //  Scanner Profile Management
    01195 //  Scanner Profile Management class constructor- doesn't need any individual
    01196 //  code at the moment.
    01197
    01198 //  Scanner Profile Management
    01199
    01200 CONST DWORD ScannerUIHelpIds[] = {
    01201 #if !defined(_WIN95_)
    01202     AddButton,          IDH_SCANNERUI_ADD,
    01203     RemoveButton,       IDH_SCANNERUI_REMOVE,
    01204     ProfileListControl, IDH_SCANNERUI_LIST,
    01205     ProfileListControlText, IDH_SCANNERUI_LIST,
    01206 #endif
    01207     0, 0
    01208 };
    01209
    01210 CScannerProfileManagement::CScannerProfileManagement(LPCTSTR lpstrName,
    01211                                                      HINSTANCE hiWhere) :
    01212
    01213     CDeviceProfileManagement(lpstrName, hiWhere, ScannerUI, CLASS_SCANNER) {
    01214     m_bReadOnly = !IsAdmin();
    01215 }
    01216
    01217 //  This class overrides OnInit so it can disable the UI if the user lacks
    01218 //  authority to make changes.
    01219
    01220 BOOL    CScannerProfileManagement::OnInit() {
    01221
    01222     //  Call the base class routine first, as it does most of the work...
    01223
    01224     CDeviceProfileManagement::OnInit();
    01225
    01226     //  Now, see if we have sufficient authority to administer the scanner
    01227     //
    01228     if (m_bReadOnly) {
    01229         // User is not Admin, Disable all of the controls
    01230
    01231         EnableWindow(GetDlgItem(m_hwnd, AddButton), FALSE);
    01232         EnableWindow(GetDlgItem(m_hwnd, RemoveButton), FALSE);
    01233
    01234         //  Set the focus to the OK button
    01235         SetFocus(GetDlgItem(m_hwndSheet, IDOK));
    01236         return  FALSE;  //  Because we moved the focus!
    01237     }
    01238
    01239     return TRUE;
    01240 }
    01241
    01242 //  Context-sensitive help handler
    01243
    01244 BOOL    CScannerProfileManagement::OnHelp(LPHELPINFO pHelp) {
    01245
    01246     if (pHelp->iContextType == HELPINFO_WINDOW) {
    01247         WinHelp((HWND) pHelp->hItemHandle, WINDOWS_HELP_FILE,
    01248                 HELP_WM_HELP, (ULONG_PTR) (LPSTR) ScannerUIHelpIds);
    01249     }
    01250
    01251     return (TRUE);
    01252 }
    01253
    01254 BOOL    CScannerProfileManagement::OnContextMenu(HWND hwnd) {
    01255
    01256     WinHelp(hwnd, WINDOWS_HELP_FILE,
    01257             HELP_CONTEXTMENU, (ULONG_PTR) (LPSTR) ScannerUIHelpIds);
    01258
    01259     return (TRUE);
    01260 }
    01261
    01262
    01263
    01264 //  Monitor Profile Management class- since the mechanism for default
    01265 //  profile manipulation is a bit sleazy, so is some of this code.
    01266
    01267 CONST DWORD MonitorUIHelpIds[] = {
    01268     AddButton,              IDH_MONITORUI_ADD,
    01269     RemoveButton,           IDH_MONITORUI_REMOVE,
    01270     DefaultButton,          IDH_MONITORUI_DEFAULT,
    01271     ProfileListControl,     IDH_MONITORUI_LIST,
    01272 #if !defined(_WIN95_)
    01273     ProfileListControlText, IDH_MONITORUI_LIST,
    01274     MonitorName,            IDH_MONITORUI_DISPLAY,
    01275     MonitorNameText,        IDH_MONITORUI_DISPLAY,
    01276     DefaultProfile,         IDH_MONITORUI_PROFILE,
    01277     DefaultProfileText,     IDH_MONITORUI_PROFILE,
    01278 #endif
    01279     0, 0
    01280 };
    01281
    01282 //  Initialize lists override- call the base class, then set the default
    01283
    01284 void    CMonitorProfileManagement::InitList() {
    01285
    01286     CDeviceProfileManagement::InitList();
    01287
    01288     m_uDefault = m_cpaProfile.Count() ? 0 : (unsigned) -1;
    01289 }
    01290
    01291 //  Fill list override- write the correct default and call the base function
    01292
    01293 void    CMonitorProfileManagement::FillList(DWORD dwFlags) {
    01294
    01295     //  If we are initializing list box, we want to put focus on
    01296     //  "default" profile. here we won't below FillList set focus
    01297     //  to first one.
    01298
    01299     if (dwFlags & DEVLIST_ONINIT) {
    01300         dwFlags |= DEVLIST_NOSELECT;
    01301     }
    01302
    01303     CDeviceProfileManagement::FillList(dwFlags);
    01304
    01305     //  There is either no default profile, an existing profile is the
    01306     //  default, or a newly selected one is.  Some people just like the
    01307     //  selection operator.
    01308
    01309     //  if there is only 1 profile in list box, we treat it as default profile.
    01310
    01311     if (SendMessage(m_hwndList,LB_GETCOUNT,0,0) == 1) {
    01312         m_uDefault = (unsigned)SendMessage(m_hwndList, LB_GETITEMDATA, 0, 0);
    01313     }
    01314
    01315     if (m_uDefault == -1) {
    01316
    01317         // There is no profile associated for this device.
    01318
    01319         CString csNoProfile;
    01320         csNoProfile.Load(NoProfileString);
    01321         SetDlgItemText(m_hwnd, DefaultProfile, csNoProfile);
    01322
    01323     } else {
    01324
    01325         // If the default has been deleted, set default as last in list.
    01326
    01327         if (m_uDefault >= (m_cpaProfile.Count() + m_cpaAdds.Count())) {
    01328
    01329             m_uDefault = (m_cpaProfile.Count() + m_cpaAdds.Count()) - 1;
    01330         }
    01331
    01332         // Put default profile name in UI.
    01333
    01334         CProfile *pcpDefault = (m_uDefault < m_cpaProfile.Count()) ? \
    01335                                            m_cpaProfile[m_uDefault] : \
    01336                                            m_cpaAdds[m_uDefault - m_cpaProfile.Count()];
    01337
    01338         SetDlgItemText(m_hwnd, DefaultProfile, pcpDefault -> GetName());
    01339
    01340         // If we are initialing list box, put focus on default profile.
    01341
    01342         if (dwFlags & DEVLIST_ONINIT) {
    01343
    01344             LRESULT idSelect = SendMessage(m_hwndList, LB_FINDSTRINGEXACT,
    01345                                    (WPARAM) -1, (LPARAM) (LPCTSTR) pcpDefault -> GetName());
    01346
    01347             // if could not find, just select first item.
    01348
    01349             if (idSelect == LB_ERR) {
    01350                 idSelect = 0;
    01351             }
    01352
    01353             // Select it.
    01354
    01355             SendMessage(m_hwndList, LB_SETCURSEL, idSelect, 0);
    01356         }
    01357     }
    01358
    01359     //  03-08-1997  Bob_Kjelgaard@Prodigy.Net   Memphis RAID 18420
    01360     //  Disable the Default button if there aren't any profiles
    01361
    01362     // We do it here, because this gets called any time the list changes.
    01363     // only allow Default button to be enabled if
    01364     // the dialog isn't read only.
    01365     // the remove button should remain dissabled
    01366     // under all conditions while the user is not
    01367     // administrator.
    01368
    01369     if (m_bReadOnly) {
    01370         EnableWindow(GetDlgItem(m_hwnd, RemoveButton), FALSE);
    01371     } else {
    01372         EnableWindow(GetDlgItem(m_hwnd, DefaultButton),
    01373                      m_cpaAdds.Count() + m_cpaProfile.Count() - m_cuaRemovals.Count());
    01374     }
    01375 }
    01376
    01377 //  Constructor
    01378
    01379 CMonitorProfileManagement::CMonitorProfileManagement(LPCTSTR lpstrName,
    01380                                                      LPCTSTR lpstrFriendlyName,
    01381                                                      HINSTANCE hiWhere) :
    01382   CDeviceProfileManagement(lpstrName, hiWhere, MonitorUI, CLASS_MONITOR) {
    01383
    01384
    01385    // if the user is not the administrator,
    01386    // make this property sheet read only.
    01387
    01388    m_bReadOnly = !IsAdmin();
    01389
    01390    // Keep friendly name in MonitorProfileManagement class.
    01391
    01392    m_csDeviceFriendlyName = lpstrFriendlyName;
    01393 }
    01394
    01395 //  UI Initialization
    01396
    01397 BOOL    CMonitorProfileManagement::OnInit() {
    01398
    01399     //  Do common initializations
    01400
    01401     CDeviceProfileManagement::OnInit();
    01402
    01403     //  Mark the device name in the space provided
    01404
    01405     SetDlgItemText(m_hwnd, MonitorName, m_csDeviceFriendlyName);
    01406
    01407     //  Now, see if we have sufficient authority to administer the monitor
    01408
    01409     if(m_bReadOnly) {
    01410
    01411         //  User is not Admin, Disable all of the controls
    01412
    01413         EnableWindow(GetDlgItem(m_hwnd, AddButton), FALSE);
    01414         EnableWindow(GetDlgItem(m_hwnd, RemoveButton), FALSE);
    01415         EnableWindow(GetDlgItem(m_hwnd, DefaultButton), FALSE);
    01416
    01417         //  EnableWindow(m_hwndList, FALSE);
    01418
    01419         //  Set the focus to the OK button
    01420
    01421         SetFocus(GetDlgItem(m_hwndSheet, IDOK));
    01422         return  FALSE;  //  Because we moved the focus!
    01423     }
    01424
    01425     return  TRUE;
    01426 }
    01427
    01428 //  Command processing- we never let them click into the edit control, to
    01429 //  prevent them from editing it.
    01430
    01431 BOOL    CMonitorProfileManagement::OnCommand(WORD wNotifyCode, WORD wid,
    01432                                              HWND hwndCtl) {
    01433
    01434     switch  (wNotifyCode) {
    01435
    01436         case    LBN_DBLCLK: {
    01437
    01438             //  Retrieve the ID of the new default profile
    01439             //  only accept dblclk changes if the dialog
    01440             //  is not read only - i.e. user is admin
    01441
    01442             if  (!m_bReadOnly) {
    01443
    01444                 int id = (int)SendMessage(m_hwndList, LB_GETCURSEL, 0, 0);
    01445                 m_uDefault = (unsigned)SendMessage(m_hwndList, LB_GETITEMDATA, id, 0);
    01446
    01447                 //  Change has been made, update the list
    01448
    01449                 FillList(DEVLIST_CHANGED);
    01450             }
    01451
    01452             return  TRUE;
    01453         }
    01454
    01455         case    BN_CLICKED:
    01456
    01457             switch  (wid) {
    01458
    01459                 case    RemoveButton: {
    01460
    01461                     //  Make sure we've tracked the default profile correctly
    01462                     //  when a profile is removed.
    01463                     //  All cases break, because we then want the base class to
    01464                     //  process this message.
    01465
    01466                     LRESULT id = SendMessage(m_hwndList, LB_GETCURSEL, 0, 0);
    01467
    01468                     unsigned uTarget = (unsigned)SendMessage(m_hwndList, LB_GETITEMDATA,
    01469                         id, 0);
    01470
    01471                     if  (uTarget > m_uDefault || m_uDefault == (unsigned) -1)
    01472                         break;  //  Nothing here to worry about
    01473
    01474                     if  (m_uDefault == uTarget) {
    01475
    01476                         if (CGlobals::ReportEx(AskRemoveDefault, m_hwnd, FALSE,
    01477                                                MB_YESNO|MB_ICONEXCLAMATION,0) == IDYES) {
    01478
    01479                             //  The default has been deleted- the profile
    01480                             //  at the top of monitor profile list will be
    01481                             //  made the default profile, if we have
    01482
    01483                             LRESULT itemCount = SendMessage(m_hwndList, LB_GETCOUNT, 0, 0);
    01484
    01485                             if ((itemCount != LB_ERR) && (itemCount > 1)) {
    01486                                 m_uDefault = (unsigned)SendMessage(m_hwndList, LB_GETITEMDATA, 0, 0);
    01487                                 if (m_uDefault == uTarget) {
    01488                                     m_uDefault = (unsigned)SendMessage(m_hwndList, LB_GETITEMDATA, 1, 0);
    01489                                 }
    01490                             } else {
    01491                                 m_uDefault = -1;
    01492                             }
    01493
    01494                             break;
    01495                         } else {
    01496                             return TRUE; // operation cancelled.
    01497                         }
    01498                     }
    01499
    01500                     if  (uTarget < m_cpaProfile.Count())
    01501                         break;  // We're fine
    01502
    01503                     //  Must be an added profile below us in the list was
    01504                     //  zapped- we need to decrement ourselves.
    01505
    01506                     m_uDefault--;
    01507                     break;
    01508                 }
    01509
    01510                 case    DefaultButton: {
    01511
    01512                     LRESULT id = SendMessage(m_hwndList, LB_GETCURSEL, 0, 0);
    01513
    01514                     m_uDefault = (unsigned)SendMessage(m_hwndList, LB_GETITEMDATA, id, 0);
    01515
    01516                     //  Change has been made, update the list
    01517
    01518                     FillList(DEVLIST_CHANGED);
    01519
    01520                     return  TRUE;
    01521                 }
    01522             }
    01523
    01524         //  Deliberate fall-through (use a break if you add a case here)
    01525     }
    01526
    01527     //  Use common command handling if not handled above
    01528     return  CDeviceProfileManagement::OnCommand(wNotifyCode, wid, hwndCtl);
    01529 }
    01530
    01531 //  Property Sheet notification processing
    01532
    01533 BOOL    CMonitorProfileManagement::OnNotify(int idCtrl, LPNMHDR pnmh) {
    01534
    01535     switch  (pnmh -> code) {
    01536
    01537         case    PSN_APPLY: {
    01538
    01539             DisableApplyButton();
    01540
    01541             //  If nothing changed, nothing need to do.
    01542
    01543             if (!SettingChanged())
    01544                 return TRUE;
    01545
    01546             //  If the user hasn't selected a default, and we have
    01547             //  associated profiles, then we can't allow this.
    01548
    01549             //  03-08-1997  A-RobKj Fix for Memphis RAID 18416- if there's
    01550             //  only one profile left, then it must be the default.
    01551
    01552             if  (m_uDefault == (unsigned) -1 && (m_cpaAdds.Count() +
    01553                  m_cpaProfile.Count() - m_cuaRemovals.Count()) > 1) {
    01554
    01555                 CGlobals::Report(NoDefaultProfile, m_hwndSheet);
    01556                 SetWindowLongPtr(m_hwnd, DWLP_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE);
    01557                 break;
    01558             }
    01559
    01560             //  !!! This behavior is hardly depend on EnumColorProfiles() API !!!
    01561
    01562             //  OK, if the default profile has changed, we have to delete default
    01563             //  profile associations, and do the association for default profile
    01564             //  in "last".
    01565
    01566             //  Let the base class handle the cases where the default hasn't
    01567             //  changed, or we started with no profiles and still have none.
    01568             //
    01569             //  03-08-1997  Sleazy code note.  The case where no default is
    01570             //  selected but only one is assigned will now fall here.  Since the
    01571             //  default happens to be the "last", and there only is one, letting
    01572             //  the base class handle it is not a problem.  The list filling
    01573             //  code will take care of the rest for us.
    01574
    01575             if  (m_uDefault == (unsigned) -1) break;
    01576
    01577             //  Remove default first (if default is associated), then associate later.
    01578
    01579             if  (m_uDefault < m_cpaProfile.Count())
    01580                 m_cpaProfile[m_uDefault] -> Dissociate(m_csDevice);
    01581
    01582             //  Now do the other removals (actually just dissociations)
    01583
    01584             for (unsigned u = 0; u < m_cuaRemovals.Count(); u++) {
    01585                 m_cpaProfile[m_cuaRemovals[u]] -> Dissociate(m_csDevice);
    01586             }
    01587
    01588             //  Add in the new ones
    01589
    01590             for (u = 0; u < m_cpaAdds.Count(); u++) {
    01591                 if  (m_uDefault >= m_cpaProfile.Count())
    01592                     if  (u == (m_uDefault - m_cpaProfile.Count()))
    01593                         continue;   // this is default, will be done later
    01594
    01595                 //  OK, add it back in...
    01596                 m_cpaAdds[u] -> Associate(m_csDevice);
    01597             }
    01598
    01599             //  Finally, associate default profile.
    01600
    01601             if  (m_uDefault < m_cpaProfile.Count())
    01602                 m_cpaProfile[m_uDefault] -> Associate(m_csDevice);
    01603             else
    01604                 m_cpaAdds[m_uDefault - m_cpaProfile.Count()] -> Associate(m_csDevice);
    01605
    01606             //  Update the various working structures...
    01607
    01608             InitList();
    01609             FillList();
    01610
    01611             SetWindowLongPtr(m_hwnd, DWLP_MSGRESULT, PSNRET_NOERROR);
    01612
    01613             //  Now, we have updated settings.
    01614
    01615             SettingChanged(FALSE);
    01616         }
    01617     }
    01618
    01619     //  Let the base class handle everything else
    01620
    01621     return  CDeviceProfileManagement::OnNotify(idCtrl, pnmh);
    01622 }
    01623
    01624 //  Context-sensitive help handler
    01625
    01626 BOOL    CMonitorProfileManagement::OnHelp(LPHELPINFO pHelp) {
    01627
    01628     if (pHelp->iContextType == HELPINFO_WINDOW) {
    01629         WinHelp((HWND) pHelp->hItemHandle, WINDOWS_HELP_FILE,
    01630             HELP_WM_HELP, (ULONG_PTR) (LPSTR) MonitorUIHelpIds);
    01631     }
    01632
    01633     return (TRUE);
    01634 }
    01635
    01636 BOOL    CMonitorProfileManagement::OnContextMenu(HWND hwnd) {
    01637
    01638     WinHelp(hwnd, WINDOWS_HELP_FILE,
    01639             HELP_CONTEXTMENU, (ULONG_PTR) (LPSTR) MonitorUIHelpIds);
    01640
    01641     return (TRUE);
    01642 }
    01643