display.c
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 17k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // DISPLAY.C
  4. //
  5. // Creates a Property Sheet for the user's display
  6. //
  7. ///////////////////////////////////////////////////////////////////////////////
  8. #include "desk.h"
  9. #include "rc.h"
  10. #include "applet.h"
  11. #include <regstr.h>
  12. #include <cplext.h>
  13. extern HINSTANCE g_hInst;       // in desk.c
  14. #define MAX_PAGES 24
  15. ///////////////////////////////////////////////////////////////////////////////
  16. // location of prop sheet hookers in the registry
  17. ///////////////////////////////////////////////////////////////////////////////
  18. #pragma data_seg(".text")
  19. static const char sc_szRegDisplay[] = REGSTR_PATH_CONTROLSFOLDER "\Display";
  20. static const char sc_szRegDisplayHandlers[] = REGSTR_PATH_CONTROLSFOLDER "\Display" "\shellex\PropertySheetHandlers";
  21. const char szRestrictionKey[] = REGSTR_PATH_POLICIES "\" REGSTR_KEY_SYSTEM;
  22. const char szNoBackgroundPage[] = REGSTR_VAL_DISPCPL_NOBACKGROUNDPAGE;
  23. const char szNoSaverPage[] = REGSTR_VAL_DISPCPL_NOSCRSAVPAGE;
  24. const char szNoAppearancePage[] = REGSTR_VAL_DISPCPL_NOAPPEARANCEPAGE;
  25. const char szNoSettingsPage[] = REGSTR_VAL_DISPCPL_NOSETTINGSPAGE;
  26. const char szNoDispCPL[] = REGSTR_VAL_DISPCPL_NODISPCPL;
  27. #pragma data_seg()
  28. static int
  29. GetClInt( const char *p )
  30. {
  31.     BOOL neg = FALSE;
  32.     int v = 0;
  33.     while( *p == ' ' )
  34.         p++;                        // skip spaces
  35.     if( *p == '-' )                 // is it negative?
  36.     {
  37.         neg = TRUE;                     // yes, remember that
  38.         p++;                            // skip '-' char
  39.     }
  40.     // parse the absolute portion
  41.     while( ( *p >= '0' ) && ( *p <= '9' ) )     // digits only
  42.         v = v * 10 + *p++ - '0';    // accumulate the value
  43.     return ( neg? -v : v );         // return the result
  44. }
  45. ///////////////////////////////////////////////////////////////////////////////
  46. // CreateReplaceableHPSXA creates a new hpsxa that contains only the
  47. // interfaces with valid ReplacePage methods.
  48. // APPCOMPAT - EzDesk only implemented AddPages.  ReplacePage is NULL for them.
  49. ///////////////////////////////////////////////////////////////////////////////
  50. typedef struct {
  51.     UINT count, alloc;
  52.     IShellPropSheetExt *interfaces[0];
  53. } PSXA;
  54. HPSXA
  55. CreateReplaceableHPSXA(HPSXA hpsxa)
  56. {
  57.     PSXA *psxa = (PSXA *)hpsxa;
  58.     DWORD cb = SIZEOF(PSXA) + SIZEOF(IShellPropSheetExt *) * psxa->alloc;
  59.     PSXA *psxaRet = (PSXA *)LocalAlloc(LPTR, cb);
  60.     if (psxaRet)
  61.     {
  62.         UINT i;
  63.         psxaRet->count = 0;
  64.         psxaRet->alloc = psxa->alloc;
  65.         for (i=0; i<psxa->count; i++)
  66.         {
  67.             if (psxa->interfaces[i]->lpVtbl->ReplacePage)
  68.             {
  69.                 psxaRet->interfaces[psxaRet->count++] = psxa->interfaces[i];
  70.             }
  71.         }
  72.     }
  73.     return (HPSXA)psxaRet;
  74. }
  75. #define DestroyReplaceableHPSXA(hpsxa) LocalFree((HLOCAL)hpsxa)
  76. ///////////////////////////////////////////////////////////////////////////////
  77. // SetStartPage checks the command line for start page by name.
  78. ///////////////////////////////////////////////////////////////////////////////
  79. void SetStartPage(PROPSHEETHEADER *ppsh, LPCTSTR pszCmdLine)
  80. {
  81.     if (pszCmdLine)
  82.     {
  83.         //
  84.         // Strip spaces
  85.         //
  86.         while (*pszCmdLine == TEXT(' '))
  87.         {
  88.             pszCmdLine++;
  89.         }
  90.         //
  91.         // Check for @ sign.
  92.         //
  93.         if (*pszCmdLine == TEXT('@'))
  94.         {
  95.             UINT i;
  96.             LPTSTR pszStartPage;
  97.             LPCTSTR pszBegin;
  98.             BOOL fInQuote = FALSE;
  99.             int cchLen;
  100.             pszCmdLine++;
  101.             //
  102.             // Skip past a quote
  103.             //
  104.             if (*pszCmdLine == TEXT('"'))
  105.             {
  106.                 pszCmdLine++;
  107.                 fInQuote = TRUE;
  108.             }
  109.             //
  110.             // Save the beginning of the name.
  111.             //
  112.             pszBegin = pszCmdLine;
  113.             //
  114.             // Find the end of the name.
  115.             //
  116.             while (*pszCmdLine &&
  117.                    (fInQuote || *pszCmdLine != TEXT(' ')) &&
  118.                    (!fInQuote || *pszCmdLine != TEXT('"')))
  119.             {
  120.                 pszCmdLine++;
  121.             }
  122.             cchLen = pszCmdLine - pszBegin;
  123.             //
  124.             // Store the name in the pStartPage field.
  125.             //
  126.             pszStartPage = (LPTSTR)LocalAlloc(LPTR, (cchLen+1) * SIZEOF(TCHAR));
  127.             if (pszStartPage)
  128.             {
  129.                 lstrcpyn(pszStartPage, pszBegin, cchLen+1);
  130.                 ppsh->dwFlags |= PSH_USEPSTARTPAGE;
  131.                 ppsh->pStartPage = pszStartPage;
  132.             }
  133.         }
  134.     }
  135. }
  136. ///////////////////////////////////////////////////////////////////////////////
  137. // _AddDisplayPropSheetPage  adds pages for outside callers...
  138. ///////////////////////////////////////////////////////////////////////////////
  139. BOOL CALLBACK
  140. _AddDisplayPropSheetPage(HPROPSHEETPAGE hpage, LPARAM lParam)
  141. {
  142.     PROPSHEETHEADER FAR * ppsh = (PROPSHEETHEADER FAR *)lParam;
  143.     if( hpage && ( ppsh->nPages < MAX_PAGES ) )
  144.     {
  145.         ppsh->phpage[ppsh->nPages++] = hpage;
  146.         return TRUE;
  147.     }
  148.     return FALSE;
  149. }
  150. ///////////////////////////////////////////////////////////////////////////////
  151. // DisplayApplet
  152. ///////////////////////////////////////////////////////////////////////////////
  153. typedef HRESULT (*LPFNCOINIT)(LPVOID);
  154. typedef HRESULT (*LPFNCOUNINIT)(void);
  155. int
  156. DisplayApplet( HINSTANCE instance, HWND parent, LPCSTR cmdline )
  157. {
  158.     HINSTANCE hDesk16 = LoadLibrary16( "DeskCp16.Dll" );
  159.     FARPROC16 pDesk16 = (FARPROC16)( hDesk16?
  160.         GetProcAddress16( hDesk16, "CplApplet" ) : NULL );
  161. HKEY hKey;
  162.     BOOL fHideBackgroundPage=FALSE,fHideSaverPage=FALSE;
  163.     BOOL fHideAppearancePage=FALSE,fHideSettingsPage=FALSE;
  164.     HINSTANCE hinstOLE32 = NULL;
  165.     LPFNCOINIT lpfnCoInitialize = NULL;
  166.     LPFNCOUNINIT lpfnCoUninitialize = NULL;
  167.     int result = 0;
  168.     // look in the registry to see if particular pages have been
  169.     // restricted by admin
  170.     if (RegOpenKey(HKEY_CURRENT_USER,szRestrictionKey,&hKey) == ERROR_SUCCESS) {
  171.         fHideBackgroundPage = CheckRestriction(hKey,szNoBackgroundPage);
  172.         fHideSaverPage = CheckRestriction(hKey,szNoSaverPage);
  173.         fHideAppearancePage = CheckRestriction(hKey,szNoAppearancePage);
  174.         fHideSettingsPage = CheckRestriction(hKey,szNoSettingsPage);
  175.         RegCloseKey(hKey);
  176.     }
  177.     if( pDesk16 && CallCPLEntry16( hDesk16, pDesk16, NULL, CPL_INIT, 0, 0 ) )
  178.     {
  179.         PROPSHEETHEADER psh;
  180.         HPROPSHEETPAGE rPages[MAX_PAGES];
  181.         HPSXA hpsxa = NULL;
  182.     
  183.         psh.dwSize = sizeof(psh);
  184.         psh.dwFlags = PSH_PROPTITLE;
  185.         psh.hwndParent = parent;
  186.         psh.hInstance = instance;
  187.         psh.pszCaption = MAKEINTRESOURCE( IDS_DISPLAY_TITLE );
  188.         psh.nPages = 0;
  189.         psh.nStartPage = ( ( cmdline && *cmdline )? GetClInt( cmdline ) : 0 );
  190.         psh.phpage = rPages;
  191.         // check for special command line casess
  192.         if( psh.nStartPage == -1 )
  193.         {
  194.             // USER couldn't start the display and needs our help
  195.             // kick up the fallback settings page...
  196.             psh.nStartPage = 0;
  197.             // Have our 16-bit dll add the fallback page
  198.             SHAddPages16( NULL, "DESKCP16.DLL,GetDisplayFallbackPage",
  199.                 _AddDisplayPropSheetPage, (LPARAM)&psh );
  200.         }
  201.         else
  202.         {
  203.             UINT nPagesOld;
  204.             UINT nAdded;
  205.             //
  206.             // Load the OLE library and grab the two interesting entry points.
  207.             //
  208.             hinstOLE32 = LoadLibrary(TEXT("OLE32.DLL"));
  209.             if (hinstOLE32)
  210.             {
  211.                 lpfnCoInitialize = (LPFNCOINIT)GetProcAddress(hinstOLE32, "CoInitialize");
  212.                 lpfnCoUninitialize = (LPFNCOUNINIT)GetProcAddress(hinstOLE32, "CoUninitialize");
  213.                 if (!lpfnCoInitialize || !lpfnCoUninitialize)
  214.                 {
  215.                     lpfnCoInitialize = NULL;
  216.                     lpfnCoUninitialize = NULL;
  217.                     FreeLibrary(hinstOLE32);
  218.                     hinstOLE32 = NULL;
  219.                 }
  220.             }
  221.             //
  222.             // Call CoInitialize before calling propsheetextarray code.
  223.             //
  224.             if (lpfnCoInitialize)
  225.             {
  226.                 lpfnCoInitialize(NULL);
  227.             }
  228.             // go find any extensions
  229.             hpsxa = SHCreatePropSheetExtArray( HKEY_LOCAL_MACHINE,
  230.                     sc_szRegDisplay, 8 );
  231.             // Background page
  232.             if (!fHideBackgroundPage)
  233.             {
  234.                 nPagesOld = psh.nPages;
  235.                 nAdded = 0;
  236.                 // check for replacement pages
  237.                 if( hpsxa != NULL )
  238.                 {
  239.                     HPSXA hpsxaReplace = CreateReplaceableHPSXA(hpsxa);
  240.                     if (hpsxaReplace)
  241.                     {
  242.                         nAdded = SHReplaceFromPropSheetExtArray( hpsxaReplace, CPLPAGE_DISPLAY_BACKGROUND,
  243.                             _AddDisplayPropSheetPage, (LPARAM)&psh );
  244.                         DestroyReplaceableHPSXA(hpsxaReplace);
  245.                     }
  246.                 }
  247.                 // or just add the default page
  248.                 if (!nAdded)
  249.                 {
  250.                     SHAddPages16( NULL, "DESKCP16.DLL,GetDisplayBackgroundPage",
  251.                         _AddDisplayPropSheetPage, (LPARAM)&psh );
  252.                     nAdded = 1;
  253.                 }
  254.                 if ((nAdded > 1) && (psh.nStartPage > nPagesOld))
  255.                 {
  256.                     psh.nStartPage += nAdded - 1;
  257.                 }
  258.             }
  259.             else if (psh.nStartPage >= psh.nPages)
  260.             {
  261.                 if (psh.nStartPage == psh.nPages)
  262.                     psh.nStartPage = 0;
  263.                 else
  264.                     psh.nStartPage--;
  265.             }
  266.             // Have our 16-bit dll add the screen saver page
  267.             if (!fHideSaverPage)
  268.             {        
  269.                 SHAddPages16( NULL, "DESKCP16.DLL,GetDisplaySaverPage",
  270.                     _AddDisplayPropSheetPage, (LPARAM)&psh );
  271.             }
  272.             else if (psh.nStartPage >= psh.nPages)
  273.             {
  274.                 if (psh.nStartPage == psh.nPages)
  275.                     psh.nStartPage = 0;
  276.                 else
  277.                     psh.nStartPage--;
  278.             }
  279.             // Have our 16-bit dll add the appearance page
  280.             if (!fHideAppearancePage)
  281.             {
  282.                 SHAddPages16( NULL, "DESKCP16.DLL,GetDisplayAppearancePage",
  283.                     _AddDisplayPropSheetPage, (LPARAM)&psh );
  284.             }
  285.             else if (psh.nStartPage >= psh.nPages)
  286.             {
  287.                 if (psh.nStartPage == psh.nPages)
  288.                     psh.nStartPage = 0;
  289.                 else
  290.                     psh.nStartPage--;
  291.             }
  292.             // Load any extensions that are installed
  293.             if( hpsxa != NULL )
  294.             {
  295.                 nPagesOld = psh.nPages;
  296.                 nAdded = SHAddFromPropSheetExtArray( hpsxa,
  297.                     _AddDisplayPropSheetPage, (LPARAM)&psh );
  298.                 if (psh.nStartPage >= nPagesOld)
  299.                     psh.nStartPage += nAdded;
  300.             }
  301.             // Have our 16-bit dll add the settings page, etc
  302.          if (!fHideSettingsPage)
  303.             {
  304.                 // and add the real settings page
  305.                 SHAddPages16( NULL, "DESKCP16.DLL,GetDisplaySettingsPage",
  306.                     _AddDisplayPropSheetPage, (LPARAM)&psh );
  307.             }
  308.         }
  309.         // fallback will sometimes do other work and return no pages
  310.         if( psh.nPages )
  311.         {
  312.             SetStartPage(&psh, cmdline);
  313.             // Bring the sucker up...
  314.             switch( PropertySheet( &psh ) )
  315.             {
  316.                 case ID_PSRESTARTWINDOWS:
  317.                     result = APPLET_RESTART;
  318.                     break;
  319.                 case ID_PSREBOOTSYSTEM:
  320.                     result = APPLET_REBOOT;
  321.                     break;
  322.             }
  323.             if (psh.dwFlags & PSH_USEPSTARTPAGE)
  324.             {
  325.                 LocalFree((HANDLE)psh.pStartPage);
  326.             }
  327.         }
  328.         // free any loaded extensions
  329.         if( hpsxa )
  330.             SHDestroyPropSheetExtArray( hpsxa );
  331.         //
  332.         // We are done with propsheetextarray code, uninitialize com
  333.         // and unload OLE32 dll.
  334.         //
  335.         if (lpfnCoUninitialize)
  336.         {
  337.             lpfnCoUninitialize();
  338.         }
  339.         if (hinstOLE32)
  340.         {
  341.             lpfnCoInitialize = NULL;
  342.             lpfnCoUninitialize = NULL;
  343.             FreeLibrary(hinstOLE32);
  344.             hinstOLE32 = NULL;
  345.         }
  346.         CallCPLEntry16( hDesk16, pDesk16, NULL, CPL_EXIT, 0, 0 );
  347.     }
  348.     if( hDesk16 )
  349.         FreeLibrary16( hDesk16 );
  350.     return result;
  351. }
  352. //  Checks the given restriction.  Returns TRUE (restricted) if the
  353. //  specified key/value exists and is non-zero, false otherwise
  354. BOOL CheckRestriction(HKEY hKey,LPCSTR lpszValueName)
  355. {
  356.     DWORD dwData,dwSize=sizeof(dwData);
  357.     if ( (RegQueryValueEx(hKey,lpszValueName,NULL,NULL,
  358.         (BYTE *) &dwData,&dwSize) == ERROR_SUCCESS) &&
  359.         dwData)
  360.         return TRUE;
  361.     return FALSE;
  362. }
  363. ///////////////////////////////////////////////////////////////////////////////
  364. // UnhookPropSheet
  365. //
  366. // the ATI display pages patch the snot out off the Settings page
  367. // the problem is that we have changed the setting page, and
  368. // even if the ATI code could deal with our changes, the
  369. // settings page is not even on the same property sheet
  370. // as the extensions.
  371. //
  372. // they hook the setting page by hooking the TabContol and
  373. // watching for a mouse click to activate the Settings page
  374. // then they modify the page.  NOTE they dont patch the page
  375. // if it is activated via the keyboard only the mouse!
  376. //
  377. // what this callback does is look for someone subclassing the
  378. // tab control, if we detect this we put the correct WndProc
  379. // back.
  380. //
  381. ///////////////////////////////////////////////////////////////////////////////
  382. int CALLBACK UnhookPropSheet(HWND hDlg, UINT code, LPARAM lParam)
  383. {
  384.     HWND hwnd;
  385.     switch (code)
  386.     {
  387.         case PSCB_INITIALIZED:
  388.             if (hwnd = PropSheet_GetTabControl(hDlg))
  389.             {
  390. #ifdef DEBUG
  391.                 if ((LONG)GetClassLong(hwnd, GCL_WNDPROC) !=
  392.                     (LONG)GetWindowLong(hwnd, GWL_WNDPROC))
  393.                 {
  394.                     OutputDebugString("**** DESK.CPL: TabControl is sublassed!rn");
  395.                 }
  396. #endif
  397.                 SetWindowLong(hwnd, GWL_WNDPROC, GetClassLong(hwnd, GCL_WNDPROC));
  398.             }
  399.             break;
  400.         case PSCB_PRECREATE:
  401.             break;
  402.     }
  403.     return 0;
  404. }
  405. ///////////////////////////////////////////////////////////////////////////////
  406. // DoAdvancedProperties
  407. //
  408. // called by DESKCP16.DLL to display the Advanced settings page
  409. //
  410. //      hDlg            - parent of the propsheet
  411. //      szCaption       - caption for the prop sheet
  412. //      DevNode         - devnode of the display device
  413. //      szDeviceRegPath - registry path for device specific pages
  414. //
  415. ///////////////////////////////////////////////////////////////////////////////
  416. int _stdcall DoAdvancedProperties(
  417.     HWND  hDlg,
  418.     LPSTR szCaption,
  419.     DWORD DevNode,
  420.     LPSTR szDeviceRegPath)
  421. {
  422.     PROPSHEETHEADER psh;
  423.     HPROPSHEETPAGE rPages[MAX_PAGES];
  424.     int iResult = 0;
  425.     HPSXA hpsxa = NULL;
  426.     HPSXA hpsxaDevice = NULL;
  427.     psh.dwSize = sizeof(psh);
  428.     psh.dwFlags = PSH_USECALLBACK;
  429.     psh.hwndParent = hDlg;
  430.     psh.hInstance = g_hInst;
  431.     psh.pszCaption = szCaption;
  432.     psh.nPages = 0;
  433.     psh.nStartPage = 0;
  434.     psh.phpage = rPages;
  435.     psh.pfnCallback = UnhookPropSheet;
  436.     SHAddPages16(NULL, "DESKCP16.DLL,GetAdapterPage",
  437.         _AddDisplayPropSheetPage, (LPARAM)&psh);
  438.     SHAddPages16(NULL, "DESKCP16.DLL,GetMonitorPage",
  439.         _AddDisplayPropSheetPage, (LPARAM)&psh);
  440.     // Load any device extensions
  441.     if( szDeviceRegPath && (hpsxaDevice = SHCreatePropSheetExtArray(
  442.         HKEY_LOCAL_MACHINE, szDeviceRegPath, 8)) != NULL)
  443.     {
  444.         SHAddFromPropSheetExtArray(hpsxaDevice, _AddDisplayPropSheetPage, (LPARAM)&psh);
  445.     }
  446.     SHAddPages16(NULL, "DESKCP16.DLL,GetPerformancePage",
  447.         _AddDisplayPropSheetPage, (LPARAM)&psh);
  448.     if (psh.nPages)
  449.         iResult = PropertySheet(&psh);
  450.     // free any loaded extensions
  451.     if (hpsxa)
  452.         SHDestroyPropSheetExtArray(hpsxa);
  453.     if (hpsxaDevice)
  454.         SHDestroyPropSheetExtArray(hpsxaDevice);
  455.     return iResult;
  456. }