general.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 35k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. /**************************************************************************
  2.  * Module Name: general.cpp
  3.  *
  4.  * Contains all the code to manage multiple devices
  5.  *
  6.  * Copyright (c) Microsoft Corp.  1995-1996 All Rights Reserved
  7.  *
  8.  * NOTES:
  9.  *
  10.  * History: Create by dli on 7/21/97
  11.  *
  12.  **************************************************************************/
  13. #include "precomp.h"
  14. #include "settings.hxx"
  15. #ifndef WINNT
  16. // codes for SelectFontSize
  17. #define DPI_INVALID   (-1)
  18. #define DPI_FROMCOMBO (-2)
  19. #define DPI_CUSTOM    (-3)
  20. #endif
  21. extern "C" {
  22. extern INT_PTR CALLBACK CustomFontDlgProc(HWND hDlg, UINT uMessage, WPARAM wParam, LPARAM lParam);
  23. extern int  g_iNewDPI;     //defined in lookdlg.c; 
  24. }
  25. //BUGBUG: (dli) This should be put in regstr.h
  26. static const TCHAR sc_szRegFontSize[]           = REGSTR_PATH_SETUP TEXT("\") REGSTR_VAL_FONTSIZE;
  27. static const TCHAR sc_szQuickResRegName[]       = TEXT("Taskbar Display Controls");
  28. static const TCHAR sc_szQuickResCommandLine[]  = TEXT("RunDLL deskcp16.dll,QUICKRES_RUNDLLENTRY");
  29. static const TCHAR sc_szQuickResClass[]  = TEXT("SysQuickRes");
  30. static const char c_szQuickResCommandLine[]  = "RunDLL deskcp16.dll,QUICKRES_RUNDLLENTRY";
  31. #ifndef WINNT
  32. static const TCHAR sc_szFonts[] = TEXT("fonts");
  33. static const TCHAR sc_szBootDesc[] = TEXT("boot.description");
  34. static const TCHAR sc_szAspect[] = TEXT("aspect");
  35. #endif
  36. //-----------------------------------------------------------------------------
  37. static const DWORD sc_GeneralHelpIds[] =
  38. {
  39.     // font size
  40.     IDC_FONTSIZEGRP,   NO_HELP, // IDH_DISPLAY_SETTINGS_ADVANCED_GENERAL_FONTSIZE, 
  41.     IDC_FONT_SIZE_STR, IDH_DISPLAY_SETTINGS_ADVANCED_GENERAL_FONTSIZE, 
  42.     IDC_FONT_SIZE,     IDH_DISPLAY_SETTINGS_ADVANCED_GENERAL_FONTSIZE,    
  43.     IDC_CUSTFONTPER,   IDH_DISPLAY_SETTINGS_ADVANCED_GENERAL_FONTSIZE, 
  44.     // group box
  45.     IDC_DYNA,          NO_HELP, // IDH_DISPLAY_SETTINGS_ADVANCED_GENERAL_DYNA,     
  46.     // radio buttons
  47.     IDC_DYNA_TEXT,     NO_HELP,
  48.     IDC_NODYNA,        IDH_DISPLAY_SETTINGS_ADVANCED_GENERAL_RESTART, 
  49.     IDC_YESDYNA,       IDH_DISPLAY_SETTINGS_ADVANCED_GENERAL_DONT_RESTART,
  50.     IDC_SHUTUP,        IDH_DISPLAY_SETTINGS_ADVANCED_GENERAL_ASK_ME, 
  51.     0, 0
  52. };
  53. BOOL IsUserAdmin(VOID);
  54. /*--------------------------------------------------------------------------*
  55.  *--------------------------------------------------------------------------*/
  56. class CGeneralDlg {
  57.     private:
  58.         int _idCustomFonts;
  59.         int _iDynaOrg;
  60.         HWND _hwndFontList;
  61.         HWND _hDlg;
  62.         //
  63.         // current log pixels of the screen.
  64.         // does not change !
  65.         int _cLogPix;
  66.         BOOL _fForceSmallFont;
  67.         BOOL _InitFontList();
  68.         void _InitDynaCDSPreference();
  69. #ifndef WINNT
  70.         void _InstallQuickRes(BOOL fEnable);
  71.         void _InitQuickResCheckbox();
  72.         void _ApplyQuickResCheckbox();
  73. #endif
  74.     public:
  75.         CGeneralDlg(BOOL fFoceSmallFont);
  76.         void InitGeneralDlg(HWND hDlg);
  77.         void SetFontSizeText( int cdpi );
  78.         BOOL ChangeFontSize();
  79.         void HandleGeneralApply(HWND hDlg);
  80.         void HandleFontSelChange();
  81.         void ForceSmallFont();
  82.         LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  83. };
  84. CGeneralDlg::CGeneralDlg(BOOL fFoceSmallFont) : _fForceSmallFont(fFoceSmallFont), _idCustomFonts(-1)
  85. {
  86.     HKEY hkFont;
  87.     DWORD cb;
  88.     //
  89.     // For font size just always use the one of the current screen.
  90.     // Whether or not we are testing the current screen.
  91.     //
  92.     _cLogPix = 96;
  93.     //
  94.     // If the size does not match what is in the registry, then install
  95.     // the new one
  96.     //
  97. #ifdef WINNT
  98.     if ((RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  99.                       SZ_FONTDPI_PROF,
  100.                       0,
  101.                       KEY_READ,
  102.                       &hkFont) == ERROR_SUCCESS) ||
  103.         (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  104.                       SZ_FONTDPI,
  105.                       0,
  106.                       KEY_READ,
  107.                       &hkFont) == ERROR_SUCCESS))
  108.     {
  109.         cb = sizeof(DWORD);
  110.         if (RegQueryValueEx(hkFont,
  111.                             SZ_LOGPIXELS,
  112.                             NULL,
  113.                             NULL,
  114.                             (LPBYTE) &_cLogPix,
  115.                             &cb) != ERROR_SUCCESS) {
  116.             _cLogPix = 96;
  117.         }
  118. #else
  119.         TCHAR szBuf[10];
  120.    if (RegOpenKeyEx(HKEY_CURRENT_CONFIG, REGSTR_PATH_DISPLAYSETTINGS, 0, KEY_READ, &hkFont) == ERROR_SUCCESS)
  121.    {
  122.        cb = SIZEOF(szBuf);
  123.        
  124.        if (RegQueryValueEx(hkFont, REGSTR_VAL_DPILOGICALX, NULL, NULL, (LPBYTE) szBuf, &cb) == ERROR_SUCCESS)
  125.        {
  126.            _cLogPix = MyStrToLong(szBuf);
  127.        }
  128.        else
  129.        {
  130.            _cLogPix = 96;
  131.        }   
  132. #endif
  133.        RegCloseKey(hkFont);
  134.     }
  135. };
  136. #ifndef WINNT
  137. #define ABS(x) ((x) < 0 ? -(x) : (x))
  138. /*
  139. ** given an arbitrary DPI, find the fontsize set that should be used
  140. ** for the DPI.  enumerate the possible sizes and choose the closest one.
  141. */
  142. BOOL NEAR PASCAL DeskCPLFontSize_GetRealSize(HKEY hkFontSize, LPCTSTR lpFontSize, LPTSTR lpRealSize)
  143. {
  144.     HKEY hk;
  145.     TCHAR szBuf[100];
  146.     int i;
  147.     
  148.     if (RegOpenKeyEx(hkFontSize, (LPTSTR)lpFontSize, 0, KEY_READ, &hk) == ERROR_SUCCESS)
  149.     {
  150.         // the font size is in there as is.  use it.
  151.         lstrcpy(lpRealSize, lpFontSize);
  152.         RegCloseKey(hk);
  153.     }
  154.     else
  155.     {
  156.         int iWant, iBest, iCur;
  157.         DWORD cchBuf = SIZEOF(szBuf);
  158.         iBest = 0;
  159.         iWant = MyStrToLong(lpFontSize);
  160.         // find closest match
  161.         for (i=0; ; i++)
  162.         {
  163.             // enumerate the fonts
  164.             if (RegEnumKeyEx(hkFontSize,i,(LPTSTR)szBuf,&cchBuf, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
  165.                 break;  // Bail if no more keys.
  166.             iCur = MyStrToLong(szBuf);
  167.             if ((!iBest) || (ABS(iBest - iWant) > ABS(iCur - iWant)))
  168.             {
  169.                 iBest = iCur;
  170.             }
  171.         }
  172.         if (!iBest)
  173.             return FALSE;
  174.         wsprintf(lpRealSize, TEXT("%d"), iBest);
  175.     }
  176.     return TRUE;
  177. }
  178. // NOTE: (dli) We should really call the SetupX api Display_SetFontSize for this
  179. // but we don't want to go through thunking. So directly access the registry 
  180. BOOL DeskCPLSetFontSize(LPCTSTR lpszFontSize)
  181. {
  182.     TCHAR szBuf[100], szRealSize[50];
  183.     TCHAR szLHS[100], szRHS[100];
  184.     HKEY hkFontSize=NULL, hkIniStuff=NULL, hkSettings=NULL,hk=NULL;
  185.     BOOL bRet = FALSE;
  186.     DWORD dw;
  187.     int i;
  188.     HDC hdc;
  189.     DWORD cbData1, cbData2;
  190.     DWORD cbLHS;
  191.     //
  192.     //  validate the font size.
  193.     //
  194.     i = MyStrToLong(lpszFontSize);
  195.     if (i < 50 || i > 1000)
  196.         goto error;
  197.     
  198.     // open the fonts key.
  199.     //
  200.     if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, sc_szRegFontSize, 0, KEY_READ, &hkFontSize) != ERROR_SUCCESS)
  201.         goto error;
  202.     
  203.     //  open the HKEY_CURRENT_CONFIGDisplaySettings key
  204.     //
  205.     if (RegCreateKeyEx(HKEY_CURRENT_CONFIG, REGSTR_PATH_DISPLAYSETTINGS, 0, TEXT(""), 0, KEY_WRITE, NULL, &hkSettings, NULL) != ERROR_SUCCESS)
  206.         goto error;
  207.     // first, get the "real" fontsize to be installed
  208.     if (!DeskCPLFontSize_GetRealSize(hkFontSize, lpszFontSize, szRealSize))
  209.         goto error;
  210.     /*
  211.     ** set up the new fontsize
  212.     */
  213.     // first, changes to system.ini
  214.     lstrcpy(szBuf, szRealSize);
  215.     lstrcat(szBuf, TEXT("\"));
  216.     lstrcat(szBuf, REGSTR_KEY_SYSTEM);
  217.     
  218.     if (RegOpenKeyEx(hkFontSize, szBuf, 0, KEY_READ, &hkIniStuff) != ERROR_SUCCESS)
  219.         goto error;
  220.     if (RegCreateKeyEx(HKEY_CURRENT_CONFIG, REGSTR_PATH_DISPLAYSETTINGS,  0, TEXT(""), 0, KEY_WRITE, NULL, &hk, NULL) != ERROR_SUCCESS)
  221.         goto error;
  222.     for (dw=0; ; dw++)
  223.     {
  224.         cbData1 = SIZEOF(szLHS);
  225.         cbData2 = SIZEOF(szRHS);
  226.         if (RegEnumValue(hkIniStuff, dw, szLHS, &cbData1, NULL, NULL, (LPBYTE)szRHS, &cbData2) != ERROR_SUCCESS)
  227.             break;
  228.         // remember, the registry has LH and RH reversed here
  229.         cbLHS = lstrlen(szLHS) * SIZEOF(TCHAR);
  230.         RegSetValueEx(hk, szRHS, 0, REG_SZ, (LPBYTE)szLHS, cbLHS);
  231.         // erase (or write) the value in SYSTEM.INI
  232.         //
  233.         // we want to write the system fonts to SYSTEM.INI even though we
  234.         // dont read them from there.  so old stupid apps will still work.
  235.         //
  236.         WritePrivateProfileString(g_szBoot, szRHS, szLHS, g_szSystemIni);
  237.     }
  238.     RegCloseKey(hkIniStuff);
  239.     RegCloseKey(hk);
  240.     // second, changes to win.ini
  241.     lstrcpy(szBuf, szRealSize);
  242.     lstrcat(szBuf, TEXT("\"));
  243.     lstrcat(szBuf, REGSTR_KEY_USER);
  244.     if (RegOpenKeyEx(hkFontSize, szBuf, 0, KEY_READ, &hkIniStuff) != ERROR_SUCCESS)
  245.         goto error;
  246.     RegDeleteKey(HKEY_CURRENT_CONFIG, REGSTR_PATH_FONTS);
  247.     if (RegCreateKeyEx(HKEY_CURRENT_CONFIG, REGSTR_PATH_FONTS, 0, TEXT(""), 0, KEY_WRITE, NULL, &hk, NULL) != ERROR_SUCCESS)
  248.         goto error;
  249.     for (dw=0; ; dw++)
  250.     {
  251.         cbData1 = SIZEOF(szLHS);
  252.         cbData2 = SIZEOF(szRHS);
  253.         // remember, the registry has LH and RH reversed here
  254.         if (RegEnumValue(hkIniStuff, dw, szLHS, &cbData1, NULL, NULL, (LPBYTE)szRHS, &cbData2) != ERROR_SUCCESS)
  255.             break;
  256.         
  257.         // remember, the registry has LH and RH reversed here
  258.         cbLHS = lstrlen(szLHS) * SIZEOF(TCHAR);
  259.         RegSetValueEx(hk, szRHS, NULL, REG_SZ, (LPBYTE)szLHS, cbLHS);
  260.         //
  261.         // dont write the font to WIN.INI![Fonts], delete it.
  262.         //
  263.         WriteProfileString(sc_szFonts, szRHS, NULL);
  264.     }
  265.     RegCloseKey(hkIniStuff);
  266.     RegCloseKey(hk);
  267.     /*
  268.     ** mark the new current font size
  269.     */
  270.     cbLHS = lstrlen(lpszFontSize) * SIZEOF(TCHAR);
  271.     RegSetValueEx(hkSettings, REGSTR_VAL_DPILOGICALX, NULL, REG_SZ, (LPBYTE)lpszFontSize, cbLHS);
  272.     RegSetValueEx(hkSettings, REGSTR_VAL_DPILOGICALY, NULL, REG_SZ, (LPBYTE)lpszFontSize, cbLHS);
  273.     RegSetValueEx(hkSettings, REGSTR_VAL_DPIPHYSICALX, NULL, REG_SZ, (LPBYTE)lpszFontSize, cbLHS);
  274.     RegSetValueEx(hkSettings, REGSTR_VAL_DPIPHYSICALY, NULL, REG_SZ, (LPBYTE)lpszFontSize, cbLHS);
  275.     // write silly DPI settings in system.ini
  276.     wsprintf(szBuf, TEXT("100,%s,%s"), (LPTSTR)lpszFontSize, (LPTSTR)lpszFontSize);
  277.     WritePrivateProfileString(sc_szBootDesc, sc_szAspect, szBuf, g_szSystemIni);
  278.     bRet = TRUE;
  279.     hdc = GetDC(NULL);
  280.     if (MyStrToLong(lpszFontSize) != GetDeviceCaps(hdc, LOGPIXELSX))
  281.         bRet++;     // need a restart
  282.     ReleaseDC(NULL, hdc);
  283. // BUGBUG error recovery?  can it be done here?  is it needed?
  284. error:
  285.     if (hkFontSize) RegCloseKey(hkFontSize);
  286.     if (hkSettings) RegCloseKey(hkSettings);
  287.     return bRet;
  288. }
  289. #endif
  290. //
  291. //  The purpose of this function is to check if the OriginalDPI value was already saved in the 
  292. // per-machine part of the registry. If this is NOT present, then get the system DPI and save it 
  293. // there. We want to do it just once for a machine. When an end-user logsin, we need to detect if
  294. // we need to change the sizes of UI fonts based on DPI change. We use the "AppliedDPI", which is 
  295. // stored on the per-user branch of the registry to determine the dpi change. If this "AppliedDPI"
  296. // is missing, then this OriginalDPI value will be used. If this value is also missing, that 
  297. // implies that nobody has changed the system DPI value.
  298. //
  299. void SaveOriginalDPI()
  300. {
  301.     //See if the "OriginalDPI value is present under HKEY_LOCAL_MACHINE.
  302.     HKEY hk;
  303.     if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  304.                                      SZ_CONTROLPANEL,
  305.                                      0,
  306.                                      KEY_READ | KEY_WRITE,
  307.                                      &hk) == ERROR_SUCCESS)
  308.     {
  309.         int   iOriginalDPI;
  310.         DWORD dwDataSize = sizeof(iOriginalDPI);
  311.         
  312.         if (RegQueryValueEx(hk, SZ_ORIGINALDPI, NULL, NULL,
  313.                             (LPBYTE)&iOriginalDPI, &dwDataSize) != ERROR_SUCCESS)
  314.         {
  315.             //"OriginalDPI" value is not present in the registry. Now, get the DPI
  316.             // and save it as the "OriginalDPI"
  317.             HDC hdc = GetDC(NULL);
  318.             iOriginalDPI = GetDeviceCaps(hdc, LOGPIXELSY);
  319.             ReleaseDC(NULL, hdc);
  320.             
  321.             DWORD   dwSize = sizeof(iOriginalDPI);
  322.             //Save the current DPI as the "OriginalDPI" value.
  323.             RegSetValueEx(hk,
  324.                             SZ_ORIGINALDPI,
  325.                             NULL,
  326.                             REG_DWORD,
  327.                             (LPBYTE) &iOriginalDPI,
  328.                             dwSize);
  329.         }
  330.         
  331.         RegCloseKey(hk);
  332.     }
  333. }
  334. BOOL CGeneralDlg::ChangeFontSize()
  335. {
  336.     int cFontSize = 0;
  337.     int cForcedFontSize;
  338.     int cUIfontSize;
  339.     //
  340.     // Change font size if necessary
  341.     //
  342.     int i = ComboBox_GetCurSel(_hwndFontList);
  343.     if (i != CB_ERR ) {
  344.         TCHAR awcDesc[10];
  345.         cFontSize = (int)ComboBox_GetItemData(_hwndFontList, i);
  346.         if ( (cFontSize != CB_ERR) &&
  347.              (cFontSize != 0) &&
  348.              (cFontSize != _cLogPix)) {
  349.             //
  350.             // The user has changed the fonts.
  351.             // Lets make sure they want this.
  352.             //
  353.             if (FmtMessageBox(_hDlg,
  354.                               MB_YESNO | MB_DEFBUTTON2 | MB_ICONQUESTION,
  355.                               ID_DSP_TXT_CHANGE_FONT,
  356.                               ID_DSP_TXT_NEW_FONT)
  357.                 == IDNO) {
  358.                 return FALSE;
  359.             }
  360.             //Save the original DPI before the DPI ever changed.
  361.             SaveOriginalDPI();
  362.             
  363.             cUIfontSize = cForcedFontSize = cFontSize;
  364.             if (_idCustomFonts == i) {
  365.                 BOOL predefined = FALSE;
  366.                 int count = ComboBox_GetCount(_hwndFontList);
  367.                 int max = -1, min = 0xffff, dpi;
  368.                 for (i = 0; i < count; i++) {
  369.                     if (i == _idCustomFonts) 
  370.                         continue;
  371.                     dpi  = (int)ComboBox_GetItemData(_hwndFontList, i);
  372.                     if (dpi == cFontSize)  {
  373.                         predefined = TRUE;
  374.                         break;
  375.                     }
  376.                     if (dpi < min) min = dpi;
  377.                     if (dpi > max) max = dpi;
  378.                 }
  379.                 if (!predefined) {
  380.                     if ((cFontSize > max) || (cFontSize + (max-min)/2 > max))
  381.                         cForcedFontSize = max;
  382.                     else 
  383.                         cForcedFontSize = min;
  384.                     // Currently our Custom font picker allows end-users to pick upto 500% of 
  385.                     // normal font size; But, when we enlarge the UI fonts to this size, the 
  386.                     // system becomes un-usable after reboot. So, what we do here is to allow
  387.                     // ui font sizes to grow up to 200% and then all further increases are 
  388.                     // proportionally reduced such that the maximum possible ui font size is only
  389.                     // 250%. (i.e the range 200% to 500% is mapped on to a range of 200% to 250%)
  390.                     // In other words, we allow upto 192 dpi (200%) with no modification. For any
  391.                     // DPI greater than 192, we proportionately reduce it such that the highest DPI
  392.                     // is only 240!
  393.                     if(cUIfontSize > 192)
  394.                         cUIfontSize = 192 + ((cUIfontSize - 192)/6);
  395.                 }
  396.             }
  397.             //
  398.             // Call setup to change the font size.
  399.             //
  400.             wsprintf(awcDesc, TEXT("%d"), cForcedFontSize);
  401.             
  402. #ifdef WINNT // DLI: Memphis does not have syssetup.dll 
  403.             if (SetupChangeFontSize(_hDlg, awcDesc) == NO_ERROR) 
  404. #else
  405.             if (DeskCPLSetFontSize(awcDesc))
  406. #endif
  407.             {
  408.                 //
  409.                 // Font change has succeeded; Now there is a new DPI to be applied to UI fonts!
  410.                 // 
  411.                 g_iNewDPI = cUIfontSize;
  412.                 
  413.                 //
  414.                 // A font size change will require a system reboot.
  415.                 //
  416.                 PropSheet_RestartWindows(GetParent(_hDlg));
  417. #ifdef WINNT
  418.                 if (cForcedFontSize != cFontSize) {
  419.                     HKEY hkFont;
  420.                     DWORD dwSize;
  421.                     if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  422.                                      SZ_FONTDPI_PROF,
  423.                                      0,
  424.                                      KEY_WRITE,
  425.                                      &hkFont) == ERROR_SUCCESS) {
  426.                         dwSize = sizeof(DWORD);
  427.                         RegSetValueEx(hkFont,
  428.                                       SZ_LOGPIXELS,
  429.                                       NULL,
  430.                                       REG_DWORD,
  431.                                       (LPBYTE) &cFontSize,
  432.                                       dwSize);
  433.                         RegCloseKey(hkFont);
  434.                     }
  435.                     if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  436.                                      SZ_FONTDPI,
  437.                                      0,
  438.                                      KEY_WRITE,
  439.                                      &hkFont) == ERROR_SUCCESS) {
  440.                         dwSize = sizeof(DWORD);
  441.                         RegSetValueEx(hkFont,
  442.                                       SZ_LOGPIXELS,
  443.                                       NULL,
  444.                                       REG_DWORD,
  445.                                       (LPBYTE) &cFontSize,
  446.                                       dwSize);
  447.                         RegCloseKey(hkFont);
  448.                     }
  449.                 }
  450. #endif
  451.             }
  452.             else
  453.             {
  454.                 //
  455.                 // Setup failed.
  456.                 //
  457.                 FmtMessageBox(_hDlg,
  458.                               MB_ICONSTOP | MB_OK,
  459.                               ID_DSP_TXT_CHANGE_FONT,
  460.                               ID_DSP_TXT_ADMIN_INSTALL);
  461.                 return FALSE;
  462.             }
  463.         }
  464.     }
  465.     if (cFontSize == 0)
  466.     {
  467.         //
  468.         // If we could not read the inf, then ignore the font selection
  469.         // and don't force the reboot on account of that.
  470.         //
  471.         cFontSize = _cLogPix;
  472.     }
  473.     return TRUE;
  474. }
  475. void CGeneralDlg::InitGeneralDlg(HWND hDlg)
  476. {
  477.     _hDlg = hDlg;
  478.     _hwndFontList = GetDlgItem(_hDlg, IDC_FONT_SIZE);
  479.     _InitFontList();
  480. #ifndef WINNT
  481.     _InitQuickResCheckbox();
  482. #endif
  483.     _iDynaOrg = -1;
  484. }
  485. void CGeneralDlg::_InitDynaCDSPreference()
  486. {
  487.     int iDyna = GetDynaCDSPreference();
  488.     if(iDyna != _iDynaOrg)
  489.     {
  490.         _iDynaOrg = iDyna;
  491.         CheckDlgButton(_hDlg, IDC_SHUTUP, FALSE);
  492.         CheckDlgButton(_hDlg, IDC_YESDYNA, FALSE);
  493.         CheckDlgButton(_hDlg, IDC_NODYNA, FALSE);
  494.         if (_iDynaOrg & DCDSF_ASK)
  495.             CheckDlgButton(_hDlg, IDC_SHUTUP, TRUE);
  496.         else if (_iDynaOrg & DCDSF_DYNA)
  497.             CheckDlgButton(_hDlg, IDC_YESDYNA, TRUE);
  498.         else
  499.             CheckDlgButton(_hDlg, IDC_NODYNA, TRUE);
  500.     }
  501. }
  502. // Init Font sizes 
  503. //
  504. // For NT:
  505. // Read the supported fonts out of the inf file(s)
  506. // Select was the user currently has.
  507. //
  508. // For WIN95:
  509. BOOL CGeneralDlg::_InitFontList() {
  510.     int i;
  511.     ASSERT(_hwndFontList);
  512.     ULONG uCurSel = (ULONG) -1;
  513.     int cPix = 0;
  514.     TCHAR szBuf2[100];
  515. #ifdef WINNT
  516.     HINF InfFileHandle;
  517.     INFCONTEXT infoContext;
  518.     //
  519.     // Get all font entries from both inf files
  520.     //
  521.     InfFileHandle = SetupOpenInfFile(TEXT("font.inf"),
  522.                                      NULL,
  523.                                      INF_STYLE_WIN4,
  524.                                      NULL);
  525.     if (InfFileHandle != INVALID_HANDLE_VALUE)
  526.     {
  527.         if (SetupFindFirstLine(InfFileHandle,
  528.                                TEXT("Font Sizes"),
  529.                                NULL,
  530.                                &infoContext))
  531.         {
  532.             while(TRUE)
  533.             {
  534.                 TCHAR awcDesc[LINE_LEN];
  535.                 if (SetupGetStringField(&infoContext,
  536.                                         0,
  537.                                         awcDesc,
  538.                                         SIZEOF(awcDesc),
  539.                                         NULL) &&
  540.                     SetupGetIntField(&infoContext,
  541.                                      1,
  542.                                      &cPix))
  543.                 {
  544.                     //
  545.                     // Add it to the list box
  546.                     //
  547.                     i = ComboBox_AddString(_hwndFontList, awcDesc);
  548.                     if (i != CB_ERR)
  549.                     {
  550.                         ComboBox_SetItemData(_hwndFontList, i, cPix);
  551.                         if (_cLogPix == cPix)
  552.                             uCurSel = i;
  553.                     }
  554.                 }
  555.                 //
  556.                 // Try to get the next line.
  557.                 //
  558.                 if (!SetupFindNextLine(&infoContext,
  559.                                        &infoContext))
  560.                 {
  561.                     break;
  562.                 }
  563.             }
  564.         }
  565.         SetupCloseInfFile(InfFileHandle);
  566.     }
  567. #else
  568.     HKEY hkFonts, hkEnumFont;
  569.     int index;
  570.     TCHAR szBuf[100];
  571.     DWORD cbData;
  572.     if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, sc_szRegFontSize, 0, KEY_READ, &hkFonts) != ERROR_SUCCESS)
  573.     {
  574.         LoadString(hInstance, IDS_UNKNOWN, szBuf, SIZEOF(szBuf));
  575.         ComboBox_AddString(_hwndFontList, szBuf);
  576.         ComboBox_SetCurSel(_hwndFontList, 0);
  577.         return FALSE;
  578.     }
  579.     for (i=0; ; i++)
  580.     {
  581.         DWORD cchBuf = ARRAYSIZE(szBuf);
  582.         // enumerate the fonts
  583.         if (RegEnumKeyEx(hkFonts,i,szBuf,&cchBuf, NULL,NULL, NULL, NULL)
  584.             != ERROR_SUCCESS)
  585.             break;  // Bail if no more keys.
  586.         if (RegOpenKeyEx(hkFonts, szBuf, 0, KEY_READ, &hkEnumFont) != ERROR_SUCCESS)
  587.             break;
  588.         cbData = SIZEOF(szBuf2);
  589.         if (RegQueryValueEx(hkEnumFont, REGSTR_VAL_DESCRIPTION, NULL, NULL,
  590.                             (LPBYTE)szBuf2, &cbData) == ERROR_SUCCESS)
  591.         {
  592.             index = ComboBox_AddString(_hwndFontList, szBuf2);
  593.             if (index != CB_ERR)
  594.             {
  595.                 cPix = (int)MyStrToLong(szBuf);
  596.                 ComboBox_SetItemData(_hwndFontList, index, cPix);
  597.                 if (_cLogPix == cPix)
  598.                     uCurSel = i;
  599.             }
  600.         }
  601.         RegCloseKey(hkEnumFont);
  602.     }
  603.     RegCloseKey(hkFonts);
  604. #endif
  605.     //
  606.     // Put in the custom fonts string
  607.     //
  608.     LoadString(hInstance, ID_DSP_CUSTOM_FONTS, szBuf2, SIZEOF(szBuf2));
  609.     _idCustomFonts = ComboBox_AddString(_hwndFontList, szBuf2);
  610.     if (_idCustomFonts != CB_ERR)
  611.         ComboBox_SetItemData(_hwndFontList, _idCustomFonts, _cLogPix);
  612.     
  613.     if (uCurSel == (ULONG) -1) {
  614.         uCurSel = _idCustomFonts;
  615.     }
  616.     if (_fForceSmallFont && (_cLogPix == 96))
  617.         this->ForceSmallFont();
  618.     else
  619.     {
  620.         //
  621.         // Select the right entry.
  622.         //
  623.         ComboBox_SetCurSel(_hwndFontList, uCurSel);
  624.         this->SetFontSizeText( _cLogPix );
  625.     }
  626.     
  627.     //
  628.     // !!! We currently change the font size by calling SetupChangeFontSize
  629.     // !!! This function request the user to be an administrator.
  630.     //
  631.         
  632.     EnableWindow(_hwndFontList, IsUserAdmin());
  633.     
  634.     return TRUE;
  635. }
  636. void CGeneralDlg::SetFontSizeText( int cdpi )
  637. {
  638.     HWND hwndCustFontPer;
  639.     TCHAR achStr[80];
  640.     TCHAR achFnt[120];
  641.     if (cdpi == CDPI_NORMAL)
  642.     {
  643.         LoadString(hInstance, ID_DSP_NORMAL_FONTSIZE_TEXT, achStr, sizeof(achStr));
  644.         wsprintf(achFnt, achStr, cdpi);
  645.     }
  646.     else
  647.     {
  648.         LoadString(hInstance, ID_DSP_CUSTOM_FONTSIZE_TEXT, achStr, sizeof(achStr));
  649.         wsprintf(achFnt, achStr, (100 * cdpi + 50) / CDPI_NORMAL, cdpi );
  650.     }
  651.     hwndCustFontPer = GetDlgItem(_hDlg, IDC_CUSTFONTPER);
  652.     SendMessage(hwndCustFontPer, WM_SETTEXT, 0, (LPARAM)achFnt);
  653. }
  654. //
  655. // ForceSmallFont method
  656. //
  657. //
  658. void CGeneralDlg::ForceSmallFont() {
  659.     int i, iSmall, dpiSmall, dpi;
  660.     //
  661.     // Set small font size in the listbox.
  662.     //
  663.     iSmall = CB_ERR;
  664.     dpiSmall = 9999;
  665.     for (i=0; i <=1; i++)
  666.     {
  667.         dpi = (int)ComboBox_GetItemData(_hwndFontList, i);
  668.         if (dpi == CB_ERR)
  669.             continue;
  670.         if (dpi < dpiSmall || iSmall < CB_ERR)
  671.         {
  672.             iSmall = i;
  673.             dpiSmall = dpi;
  674.         }
  675.     }
  676.     if (iSmall != -1)
  677.         ComboBox_SetCurSel(_hwndFontList, iSmall);
  678.     this->SetFontSizeText(dpiSmall);
  679.     EnableWindow(_hwndFontList, FALSE);
  680. }
  681. void CGeneralDlg::HandleGeneralApply(HWND hDlg)
  682. {
  683.     int iDynaNew;
  684.     if (IsDlgButtonChecked(hDlg, IDC_YESDYNA))
  685.         iDynaNew= DCDSF_YES;
  686.     else if (IsDlgButtonChecked(hDlg, IDC_NODYNA))
  687.         iDynaNew= DCDSF_NO;
  688.     else
  689.         iDynaNew = DCDSF_PROBABLY;
  690.     if (iDynaNew != _iDynaOrg)
  691.     {
  692.         SetDisplayCPLPreference(REGSTR_VAL_DYNASETTINGSCHANGE, iDynaNew);
  693.         _iDynaOrg = iDynaNew;
  694.     }
  695. #ifndef WINNT
  696.     _ApplyQuickResCheckbox();
  697. #endif
  698.     BOOL bSuccess = ChangeFontSize();
  699.     
  700.     long lRet = (bSuccess ? PSNRET_NOERROR: PSNRET_INVALID_NOCHANGEPAGE);
  701.     SetWindowLongPtr(hDlg, DWLP_MSGRESULT, lRet);
  702. }
  703. void CGeneralDlg::HandleFontSelChange()
  704. {
  705.     //
  706.     // Warn the USER font changes will not be seen until after
  707.     // reboot
  708.     //
  709.     int iCurSel;
  710.     int cdpi;
  711.     iCurSel = ComboBox_GetCurSel(_hwndFontList);
  712.     cdpi = (int)ComboBox_GetItemData(_hwndFontList, iCurSel);
  713.     if (iCurSel == _idCustomFonts) {
  714.         InitDragSizeClass();
  715.         cdpi = (int)DialogBoxParam(hInstance, MAKEINTRESOURCE(DLG_CUSTOMFONT),
  716.                               _hDlg, CustomFontDlgProc, cdpi );
  717.         if (cdpi != 0)
  718.             ComboBox_SetItemData(_hwndFontList, _idCustomFonts, cdpi);
  719.         else
  720.             cdpi = (int)ComboBox_GetItemData(_hwndFontList, _idCustomFonts);
  721.     }
  722.     if (cdpi != _cLogPix)
  723.     {
  724.         FmtMessageBox(_hDlg,
  725.                       MB_ICONINFORMATION,
  726.                       ID_DSP_TXT_CHANGE_FONT,
  727.                       ID_DSP_TXT_FONT_LATER);
  728.         PropSheet_Changed(GetParent(_hDlg), _hDlg);
  729.     }
  730.     this->SetFontSizeText(cdpi);
  731. }
  732. void StartStopQuickRes(HWND hDlg, BOOL fEnable)
  733. {
  734.     HWND hwnd;
  735. TryAgain:
  736.     hwnd = FindWindow(sc_szQuickResClass, NULL);
  737.     if (fEnable)
  738.     {
  739.         if (!hwnd)
  740.             WinExec(c_szQuickResCommandLine, SW_SHOWNORMAL);
  741.         return;
  742.     }
  743.     if (hwnd)
  744.     {
  745.         SendMessage(hwnd, WM_CLOSE, 0, 0L);
  746.         goto TryAgain;
  747.     }
  748. }
  749. #ifndef WINNT
  750. void CGeneralDlg::_InstallQuickRes(BOOL fEnable)
  751. {
  752.     HKEY hk = NULL;
  753.     if (fEnable)
  754.     {
  755.         if (RegCreateKeyEx(HKEY_CURRENT_USER, REGSTR_PATH_RUN, 0, TEXT(""), 0, KEY_WRITE, NULL, &hk, NULL) == ERROR_SUCCESS)
  756.         {
  757.             RegSetValueEx(hk, sc_szQuickResRegName, NULL, REG_SZ,
  758.                 (LPBYTE)sc_szQuickResCommandLine,
  759.                 lstrlen(sc_szQuickResCommandLine) + 1);
  760.         }
  761.     }
  762.     else if (RegOpenKeyEx(HKEY_CURRENT_USER, REGSTR_PATH_RUN, 0, KEY_WRITE, &hk) == ERROR_SUCCESS)
  763.         RegDeleteValue(hk, sc_szQuickResRegName);
  764.     if (hk)
  765.         RegCloseKey(hk);
  766. }
  767. void CGeneralDlg::_ApplyQuickResCheckbox()
  768. {
  769.     BOOL fEnable = (IsDlgButtonChecked(_hDlg, IDC_SHOWQUICKRES) == BST_CHECKED);
  770.     _InstallQuickRes(fEnable);
  771.     StartStopQuickRes(_hDlg, fEnable);
  772. }
  773. void CGeneralDlg::_InitQuickResCheckbox()
  774. {
  775.     BOOL fResult = FALSE;
  776.     HKEY hk;
  777.     if (RegOpenKeyEx(HKEY_CURRENT_USER, REGSTR_PATH_RUN, 0, KEY_READ, &hk) == ERROR_SUCCESS)
  778.     {
  779.         TCHAR szBuf[4];
  780.         DWORD dwLen = 0;
  781.         fResult = (RegQueryValueEx(hk, sc_szQuickResRegName, NULL, NULL,
  782.             (LPBYTE)szBuf, &dwLen) == ERROR_MORE_DATA);
  783.         RegCloseKey(hk);
  784.     }
  785.     CheckDlgButton(_hDlg, IDC_SHOWQUICKRES, fResult? BST_CHECKED : BST_UNCHECKED);
  786. }
  787. #endif
  788. LRESULT CALLBACK CGeneralDlg::WndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  789. {
  790.     NMHDR *lpnm;
  791.     switch (message)
  792.     {
  793.     case WM_INITDIALOG:
  794.         InitGeneralDlg(hDlg);
  795.         break;
  796.     case WM_NOTIFY:
  797.         lpnm = (NMHDR *)lParam;
  798.         switch (lpnm->code)
  799.         {
  800.             case PSN_SETACTIVE:
  801.                 _InitDynaCDSPreference();
  802.                 return TRUE;
  803.             case PSN_APPLY:
  804.                 HandleGeneralApply(hDlg);
  805.                 return TRUE;
  806.             default:
  807.                 return FALSE;
  808.         }
  809.         break;
  810.         
  811.     case WM_COMMAND:
  812.         switch (GET_WM_COMMAND_ID(wParam, lParam))
  813.         {
  814.             case IDC_NODYNA:
  815.             case IDC_YESDYNA:
  816.             case IDC_SHUTUP:
  817.                 if (GET_WM_COMMAND_CMD(wParam, lParam) == BN_CLICKED)
  818.                     PropSheet_Changed(GetParent(hDlg), hDlg);
  819.                 break;
  820.             case IDC_FONT_SIZE:
  821.                 switch (GET_WM_COMMAND_CMD(wParam, lParam))
  822.                 {
  823.                     case CBN_SELCHANGE:
  824.                         HandleFontSelChange();
  825.                         break;
  826.                     default:
  827.                         break;
  828.                 }
  829.                 break;
  830.             case IDC_SHOWQUICKRES:
  831.                 PropSheet_Changed(GetParent(hDlg), hDlg);
  832.                 break;
  833.                 
  834.             default:
  835.                 break;
  836.         }
  837.         break;
  838.         
  839.     case WM_HELP:
  840.         WinHelp((HWND)((LPHELPINFO)lParam)->hItemHandle, TEXT("display.hlp"), HELP_WM_HELP,
  841.             (DWORD_PTR)(LPTSTR)sc_GeneralHelpIds);
  842.         break;
  843.     case WM_CONTEXTMENU:
  844.         WinHelp((HWND)wParam, TEXT("display.hlp"), HELP_CONTEXTMENU,
  845.             (DWORD_PTR)(LPTSTR)sc_GeneralHelpIds);
  846.         break;
  847.   
  848.     default:
  849.         return FALSE;
  850.     }
  851.     return TRUE;
  852. }
  853. //-----------------------------------------------------------------------------
  854. //
  855. // Callback functions PropertySheet can use
  856. //
  857. INT_PTR CALLBACK
  858. GeneralPageProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  859. {
  860.     CGeneralDlg * pcgd = (CGeneralDlg * )GetWindowLongPtr(hDlg, DWLP_USER);
  861.     switch (message)
  862.     {
  863.         case WM_INITDIALOG:
  864.             ASSERT(!pcgd);
  865.             ASSERT(lParam);
  866.             pcgd = new CGeneralDlg((BOOL)((LPPROPSHEETPAGE)lParam)->lParam);
  867.             if(pcgd)
  868.             {
  869.                 // now we need to init
  870.                 pcgd->InitGeneralDlg(hDlg);
  871.                 SetWindowLongPtr(hDlg, DWLP_USER, (LPARAM)pcgd);
  872.                 return TRUE;
  873.             }
  874.             break;
  875.             
  876.         case WM_DESTROY:
  877.             if (pcgd)
  878.             {
  879.                 SetWindowLongPtr(hDlg, DWLP_USER, NULL);
  880.                 delete pcgd;
  881.             }
  882.             break;
  883.         default:
  884.             if (pcgd)
  885.                 return pcgd->WndProc(hDlg, message, wParam, lParam);
  886.             break;
  887.     }
  888.     return FALSE;
  889. }
  890. /*--------------------------------------------------------------------------*
  891.  *--------------------------------------------------------------------------*/
  892. INT_PTR CALLBACK AskDynaCDSProc(HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
  893. {
  894.     int *pTemp;
  895.     switch (msg)
  896.     {
  897.     case WM_INITDIALOG:
  898.         if ((pTemp = (int *)lp) != NULL)
  899.         {
  900.             SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)pTemp);
  901.             CheckDlgButton(hDlg, (*pTemp & DCDSF_DYNA)?
  902.                 IDC_YESDYNA : IDC_NODYNA, BST_CHECKED);
  903.         }
  904.         else
  905.             EndDialog(hDlg, -1);
  906.         break;
  907.     case WM_COMMAND:
  908.         switch (GET_WM_COMMAND_ID(wp, lp))
  909.         {
  910.         case IDOK:
  911.             if ((pTemp = (int *)GetWindowLongPtr(hDlg, DWLP_USER)) != NULL)
  912.             {
  913.                 *pTemp = IsDlgButtonChecked(hDlg, IDC_YESDYNA)? DCDSF_DYNA : 0;
  914.                 if (!IsDlgButtonChecked(hDlg, IDC_SHUTUP))
  915.                     *pTemp |= DCDSF_ASK;
  916.                 SetDisplayCPLPreference(REGSTR_VAL_DYNASETTINGSCHANGE, *pTemp);
  917.             }
  918.             EndDialog(hDlg, TRUE);
  919.             break;
  920.         case IDCANCEL:
  921.             EndDialog(hDlg, FALSE);
  922.             break;
  923.         default:
  924.             return FALSE;
  925.         }
  926.         break;
  927.     default:
  928.         return FALSE;
  929.     }
  930.     return TRUE;
  931. }
  932. int  AskDynaCDS(HWND hOwner)
  933. {
  934.     int val = GetDynaCDSPreference();
  935.     if (val & DCDSF_ASK)
  936.     {
  937.         switch (DialogBoxParam(hInstance, MAKEINTRESOURCE(DLG_ASKDYNACDS),
  938.             hOwner, AskDynaCDSProc, (LPARAM)(int *)&val))
  939.         {
  940.         case 0:         // user cancelled
  941.             return -1;
  942.         case -1:        // dialog could not be displayed
  943.             val = DCDSF_NO;
  944.             break;
  945.         }
  946.     }
  947.     return ((val & DCDSF_DYNA) == DCDSF_DYNA);
  948. }
  949. BOOL IsUserAdmin(VOID)
  950. /*++
  951. Routine Description:
  952.     This routine returns TRUE if the caller's process is a
  953.     member of the Administrators local group.
  954.     Caller is NOT expected to be impersonating anyone and IS
  955.     expected to be able to open their own process and process
  956.     token.
  957. --*/
  958. {
  959.     HANDLE Token;
  960.     DWORD BytesRequired;
  961.     PTOKEN_GROUPS Groups;
  962.     BOOL bRet;
  963.     DWORD i;
  964.     SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  965.     PSID AdministratorsGroup;
  966.     //
  967.     // Open the process token.
  968.     //
  969.     if(!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &Token)) 
  970.     {
  971.         return(FALSE);
  972.     }
  973.     bRet = FALSE;
  974.     Groups = NULL;
  975.     //
  976.     // Get group information.
  977.     //
  978.     if(!GetTokenInformation(Token, TokenGroups, NULL, 0, &BytesRequired) && 
  979.        (GetLastError() == ERROR_INSUFFICIENT_BUFFER) && 
  980.        (Groups = (PTOKEN_GROUPS)malloc(BytesRequired)) && 
  981.        GetTokenInformation(Token, TokenGroups, Groups, BytesRequired, &BytesRequired)) 
  982.     {
  983.         bRet = AllocateAndInitializeSid(&NtAuthority,
  984.                                         2,
  985.                                         SECURITY_BUILTIN_DOMAIN_RID,
  986.                                         DOMAIN_ALIAS_RID_ADMINS,
  987.                                         0, 0, 0, 0, 0, 0,
  988.                                         &AdministratorsGroup);
  989.         if(bRet) 
  990.         {
  991.             //
  992.             // See if the user has the administrator group.
  993.             //
  994.             bRet = FALSE;
  995.             for (i = 0; i < Groups->GroupCount; i++) 
  996.             {
  997.                 if(EqualSid(Groups->Groups[i].Sid, AdministratorsGroup)) 
  998.                 {
  999.                     bRet = TRUE;
  1000.                     break;
  1001.                 }
  1002.             }
  1003.             FreeSid(AdministratorsGroup);
  1004.         }
  1005.     }
  1006.     //
  1007.     // Clean up and return.
  1008.     //
  1009.     if(Groups) 
  1010.     {
  1011.         free(Groups);
  1012.     }
  1013.     CloseHandle(Token);
  1014.     return(bRet);
  1015. }