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

253 lines
8.9 KiB

  1. #include "priv.h"
  2. #include <regstr.h>
  3. #include <atlcom.h>
  4. #include <shguidp.h>
  5. #include <shlguid.h>
  6. typedef struct
  7. {
  8. DWORD dwWidth;
  9. DWORD dwHeight;
  10. DWORD dwColor;
  11. BOOL fAvailable;
  12. } SCREENMODE;
  13. class ATL_NO_VTABLE CScreenResFixer :
  14. public CComObjectRootEx<CComSingleThreadModel>,
  15. public CComCoClass<CScreenResFixer, &CLSID_ScreenResFixer>,
  16. public IContextMenu,
  17. public IScreenResFixer
  18. {
  19. public:
  20. CScreenResFixer() {}
  21. virtual ~CScreenResFixer() {}
  22. DECLARE_NOT_AGGREGATABLE(CScreenResFixer)
  23. BEGIN_COM_MAP(CScreenResFixer)
  24. COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu)
  25. COM_INTERFACE_ENTRY(IScreenResFixer)
  26. END_COM_MAP()
  27. // *** IContextMenu methods ***
  28. STDMETHODIMP QueryContextMenu(HMENU hmenu, UINT iIndexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) { return E_NOTIMPL; }
  29. STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO lpici);
  30. STDMETHODIMP GetCommandString(UINT_PTR idCmd, UINT uType, UINT *pRes, LPSTR pszName, UINT cchMax) { return E_NOTIMPL; }
  31. private:
  32. int _PickScreenResolution(SCREENMODE* modes, int cModes);
  33. HRESULT _FixScreenResolution(BOOL fShowDisplayCPL);
  34. };
  35. // *** IContextMenu methods ***
  36. STDMETHODIMP CScreenResFixer::InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
  37. {
  38. WCHAR szTitle[256];
  39. HRESULT hr;
  40. szTitle[0] = 0;
  41. LoadString(HINST_THISDLL, IDS_SCREENRESFIXER_TITLE, szTitle, ARRAYSIZE(szTitle));
  42. BOOL fOK = FALSE;
  43. if (lpici)
  44. {
  45. WCHAR szText[512];
  46. szText[0] = 0;
  47. LoadString(HINST_THISDLL, IDS_SCREENRESFIXER_TEXT, szText, ARRAYSIZE(szText));
  48. fOK = (IDYES == SHMessageBoxCheck(NULL, szText, szTitle, MB_YESNO, 0, TEXT("ScreenCheck")));
  49. }
  50. else
  51. {
  52. WCHAR szText[512];
  53. szText[0] = 0;
  54. LoadString(HINST_THISDLL, IDS_SCREENRESFIXER_ALTTEXT, szText, ARRAYSIZE(szText));
  55. fOK = (IDOK == MessageBox(NULL, szText, szTitle, MB_OK));
  56. }
  57. if (fOK)
  58. {
  59. hr = _FixScreenResolution(!(lpici == NULL));
  60. }
  61. else
  62. {
  63. // If the user checked "Don't show me again" then force this setting into HKLM, so that it doesn't
  64. // show up for any users
  65. if (!SHRegGetBoolUSValue(REGSTR_PATH_EXPLORER TEXT("\\DontShowMeThisDialogAgain"), TEXT("ScreenCheck"), FALSE, TRUE))
  66. {
  67. SHRegSetUSValueW(REGSTR_PATH_EXPLORER TEXT("\\DontShowMeThisDialogAgain"), TEXT("ScreenCheck"), REG_SZ, L"no", sizeof(L"no"), SHREGSET_HKLM);
  68. }
  69. hr = S_OK;
  70. }
  71. // Now that the user finished with their screen resolution, tell the Start Menu
  72. // it's okay to pop up.
  73. HWND hwndTray = FindWindow(TEXT(WNDCLASS_TRAYNOTIFY), NULL);
  74. if (hwndTray)
  75. PostMessage(hwndTray, RegisterWindowMessage(TEXT("Welcome Finished")), 0, 0);
  76. return hr;
  77. }
  78. int CScreenResFixer::_PickScreenResolution(SCREENMODE* modes, int cModes)
  79. {
  80. static const struct {
  81. int iMinWidth;
  82. int iMinHeight;
  83. int iMaxWidth;
  84. int iMaxHeight;
  85. int iIdealColor;
  86. }
  87. picker[] =
  88. {
  89. { 800, 600, 1024, 768, 32 },
  90. { 800, 600, 1024, 768, 24 },
  91. { 800, 600, 1024, 768, -1 },
  92. { 1024, 768, -1, -1, 32 },
  93. { 1024, 768, -1, -1, 24 },
  94. { 1024, 768, -1, -1, -1 },
  95. };
  96. for (int i = 0; i < ARRAYSIZE(picker); i++)
  97. {
  98. // Try for Ideal Color in given resolution range
  99. for (int iMode = 0; iMode < cModes; iMode++)
  100. {
  101. if ((modes[iMode].fAvailable) &&
  102. (modes[iMode].dwWidth >= (DWORD)picker[i].iMinWidth) &&
  103. (modes[iMode].dwHeight >= (DWORD)picker[i].iMinHeight))
  104. {
  105. if ((picker[i].iMaxWidth == -1) ||
  106. ((modes[iMode].dwWidth < (DWORD)picker[i].iMaxWidth) &&
  107. (modes[iMode].dwHeight < (DWORD)picker[i].iMaxHeight)))
  108. {
  109. if (((picker[i].iIdealColor == -1) && (modes[iMode].dwColor >= 15)) ||
  110. (modes[iMode].dwColor == (DWORD)picker[i].iIdealColor))
  111. {
  112. return iMode;
  113. }
  114. }
  115. }
  116. }
  117. }
  118. return -1;
  119. }
  120. void UpdateRecycleBinInfo()
  121. {
  122. static const LPTSTR lpszSubkey = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ScreenResFixer");
  123. static const LPTSTR lpszValue = TEXT("AdjustRecycleBinPosition");
  124. //Read if the we have done it once already.
  125. DWORD dwAdjustPos = 0; //Assume that Recycle-bin has been already positioned.
  126. DWORD dwSize = sizeof(dwAdjustPos);
  127. SHRegGetUSValue(lpszSubkey, lpszValue, NULL, &dwAdjustPos, &dwSize, FALSE, &dwAdjustPos, dwSize);
  128. // 0 => Recycle-bin hasn't been positioned because of resolution fixer.
  129. // 1 => Recycle-bin needs to be repositioned. It has't happened yet!
  130. // 2 => Recycle-bin has already been re-positioned. Nothing needs to be done here!
  131. if(dwAdjustPos == 0)
  132. {
  133. // 0 => Recycle-bin hasn't been positioned because of resolution fixer.
  134. // So, we need to change the settings sothat when desktop.cpp responds to res change,
  135. // it will position the recycle-bin.
  136. dwAdjustPos = 1;
  137. SHRegSetUSValue(lpszSubkey, lpszValue, REG_DWORD, &dwAdjustPos, sizeof(dwAdjustPos), SHREGSET_HKCU | SHREGSET_FORCE_HKCU);
  138. }
  139. }
  140. HRESULT CScreenResFixer::_FixScreenResolution(BOOL fShowDisplayCPL)
  141. {
  142. IDisplaySettings * pds;
  143. HRESULT hr = CoCreateInstance(CLSID_DisplaySettings, NULL, CLSCTX_INPROC_SERVER,
  144. IID_PPV_ARG(IDisplaySettings, &pds));
  145. if (SUCCEEDED(hr))
  146. {
  147. for (DWORD dwMon = 0; SUCCEEDED(pds->SetMonitor(dwMon)); dwMon++)
  148. {
  149. BOOL fAttached = FALSE;
  150. hr = pds->GetAttached(&fAttached);
  151. if (SUCCEEDED(hr) && fAttached)
  152. {
  153. DWORD dwWidth, dwHeight, dwColor;
  154. hr = pds->GetSelectedMode(&dwWidth, &dwHeight, &dwColor);
  155. if (SUCCEEDED(hr) && ((dwWidth < 800) || (dwHeight < 600) || (dwColor < 15)))
  156. {
  157. DWORD cModes = 0;
  158. hr = pds->GetModeCount(&cModes, TRUE);
  159. if (SUCCEEDED( hr ) && (cModes > 0))
  160. {
  161. SCREENMODE* modes = new SCREENMODE[cModes];
  162. if (modes)
  163. {
  164. for (DWORD i = 0; i < cModes; i++)
  165. {
  166. hr = pds->GetMode(i, TRUE, &modes[i].dwWidth, &modes[i].dwHeight, &modes[i].dwColor);
  167. modes[i].fAvailable = SUCCEEDED(hr) && ((i <= 0) ||
  168. (modes[i].dwWidth != modes[i-1].dwWidth) ||
  169. (modes[i].dwHeight != modes[i-1].dwHeight) ||
  170. (modes[i].dwColor != modes[i-1].dwColor));
  171. }
  172. int iMode = _PickScreenResolution(modes, cModes);
  173. if (iMode != -1)
  174. {
  175. static BOOL fRecycleBinInfoUpdated = FALSE; //to begin with!
  176. //We are about to change the mode. Make a note in registry
  177. if(!fRecycleBinInfoUpdated)
  178. {
  179. UpdateRecycleBinInfo();
  180. fRecycleBinInfoUpdated = TRUE;
  181. }
  182. BOOL fApplied = FALSE;
  183. pds->SetSelectedMode(NULL, modes[iMode].dwWidth, modes[iMode].dwHeight, modes[iMode].dwColor, &fApplied, fShowDisplayCPL ? DS_BACKUPDISPLAYCPL : 0);
  184. if (!fApplied)
  185. {
  186. hr = E_FAIL;
  187. }
  188. }
  189. delete [] modes;
  190. modes = NULL;
  191. }
  192. else
  193. {
  194. hr = E_OUTOFMEMORY;
  195. }
  196. }
  197. }
  198. }
  199. }
  200. }
  201. return hr;
  202. }
  203. HRESULT CScreenResFixer_CreateInstance(IN IUnknown * punkOuter, IN REFIID riid, OUT LPVOID * ppvObj)
  204. {
  205. HRESULT hr = E_INVALIDARG;
  206. if (!punkOuter && ppvObj)
  207. {
  208. CComObject<CScreenResFixer> * pThis = new CComObject<CScreenResFixer>();
  209. *ppvObj = NULL;
  210. if (pThis)
  211. {
  212. hr = pThis->QueryInterface(riid, ppvObj);
  213. }
  214. else
  215. {
  216. hr = E_OUTOFMEMORY;
  217. }
  218. }
  219. return hr;
  220. }