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.

618 lines
25 KiB

  1. #include "stdafx.h"
  2. #pragma hdrstop
  3. // 98/10/02 vtan: Multiple monitor bug fixes.
  4. // Given an old monitor layout, a new monitor layout and a component
  5. // this function makes sure that it is in the new layout using a
  6. // monitor relative scheme. It tries to preserve the position
  7. // relatively within a given monitor. If the resolution of the monitor
  8. // changes then this needs to be accounted for also.
  9. // Preserve the component within a given monitor if the monitor is the
  10. // same HMONITOR but the GDI co-ordinates change.
  11. // If the same monitor cannot be located then move the component to the
  12. // nearest monitor and position it as best on that monitor.
  13. // If all else fails then use the default component positioning
  14. // algorithm. This should never happen.
  15. // Preserve the component within a given monitor if the resolution
  16. // changes. Preserve the size of the component by MOVING the component
  17. // in the X and Y axis until the left or the top of the monitor is
  18. // reached. When either axis reaches 0 then reduce the size of the
  19. // component until it fits within the given new resolution.
  20. static const int kNameSize = 16;
  21. typedef struct
  22. {
  23. HMONITOR miHMONITOR;
  24. RECT miDisplayAreaRect,
  25. miWorkAreaRect;
  26. } tMonitorInfoRec, *tMonitorInfoPtr;
  27. typedef struct
  28. {
  29. int miaCount, miaIndex;
  30. RECT miaVirtualScreen;
  31. tMonitorInfoRec miaMonitors[1];
  32. } tMonitorInfoArrayRec, *tMonitorInfoArrayPtr;
  33. typedef struct
  34. {
  35. BOOL ciValidData, ciVisible, ciRepositioned;
  36. TCHAR ciName[kNameSize]; // this is not excessive but limited
  37. DWORD ciItemState;
  38. int ciType;
  39. COMPPOS ciPosition;
  40. COMPSTATEINFO ciStateInfo;
  41. } tComponentInfoRec, *tComponentInfoPtr;
  42. static tMonitorInfoArrayPtr gOldMonitorArray = NULL;
  43. static tMonitorInfoArrayPtr gNewMonitorArray = NULL;
  44. // Functions located in Dutil.cpp used for co-ordinate mapping.
  45. void SetPt (POINT& pt, LONG x, LONG y);
  46. void OffsetPt (POINT& pt, LONG dh, LONG dv);
  47. void CalculateVirtualScreen (RECT& virtualScreen);
  48. // Local function prototypes.
  49. BOOL CALLBACK MonitorCountEnumProc (HMONITOR hMonitor, HDC dc, RECT *rc, LPARAM data);
  50. BOOL CALLBACK MonitorCalculateEnumProc (HMONITOR hMonitor, HDC dc, RECT *rc, LPARAM data);
  51. HRESULT CalculateCurrentMonitorArray(void);
  52. void ApplyCurrentMonitorArray (void);
  53. int IndexOfMonitor (tMonitorInfoArrayPtr pMIA, HMONITOR hMonitor);
  54. int IndexOfMonitor (tMonitorInfoArrayPtr pMIA, POINT& pt);
  55. int IndexOfMonitor (tMonitorInfoArrayPtr pMIA, RECT& rc);
  56. BOOL RepositionDesktopRect (RECT& rcComponent, tMonitorInfoArrayPtr oldMonitorArray, tMonitorInfoArrayPtr newMonitorArray);
  57. BOOL RepositionDesktopComponent (COMPPOS& componentPosition, COMPSTATEINFO& componentStateInfo, DWORD dwItemState);
  58. BOOL ReadAllComponents (HKEY hKeyDesktop, tComponentInfoPtr& pComponentInfo, DWORD& dwComponentCount);
  59. void WriteAllComponents (HKEY hKeyDesktop, tComponentInfoPtr pComponentInfo, DWORD dwComponentCount);
  60. BOOL CALLBACK MonitorCountEnumProc (HMONITOR hMonitor, HDC dc, RECT *rc, LPARAM data)
  61. // Count the number of monitors attached to the system.
  62. {
  63. int *iCounter;
  64. iCounter = reinterpret_cast<int*>(data);
  65. ++(*iCounter);
  66. return(TRUE);
  67. }
  68. BOOL CALLBACK MonitorCalculateEnumProc (HMONITOR hMonitor, HDC dc, RECT *rc, LPARAM data)
  69. // Store each monitor HMONITOR and dimensions in the array.
  70. {
  71. tMonitorInfoArrayPtr monitorArray;
  72. MONITORINFO monitorInfo;
  73. monitorArray = reinterpret_cast<tMonitorInfoArrayPtr>(data);
  74. monitorInfo.cbSize = sizeof(monitorInfo);
  75. // adding monitors in the space of a few nanoseconds isnt a real attack vector, but double-check
  76. // against the size of the array we allocated
  77. if ((GetMonitorInfo(hMonitor, &monitorInfo) != 0) && (monitorArray->miaIndex < monitorArray->miaCount))
  78. {
  79. tMonitorInfoPtr pMI;
  80. pMI = &monitorArray->miaMonitors[monitorArray->miaIndex++];
  81. pMI->miHMONITOR = hMonitor;
  82. TBOOL(CopyRect(&pMI->miDisplayAreaRect, &monitorInfo.rcMonitor));
  83. TBOOL(CopyRect(&pMI->miWorkAreaRect, &monitorInfo.rcWork));
  84. }
  85. return(TRUE);
  86. }
  87. HRESULT CalculateCurrentMonitorArray(void)
  88. // Allocate and fill the monitor rectangle array.
  89. {
  90. HRESULT hr = E_OUTOFMEMORY;
  91. int iCount;
  92. iCount = 0;
  93. TBOOL(EnumDisplayMonitors(NULL, NULL, MonitorCountEnumProc, reinterpret_cast<LPARAM>(&iCount)));
  94. gNewMonitorArray = reinterpret_cast<tMonitorInfoArrayPtr>(LocalAlloc(LMEM_FIXED, sizeof(tMonitorInfoArrayRec) + ((iCount - 1) * sizeof(tMonitorInfoRec))));
  95. if (gNewMonitorArray)
  96. {
  97. gNewMonitorArray->miaCount = iCount;
  98. gNewMonitorArray->miaIndex = 0;
  99. CalculateVirtualScreen(gNewMonitorArray->miaVirtualScreen);
  100. TBOOL(EnumDisplayMonitors(NULL, NULL, MonitorCalculateEnumProc, reinterpret_cast<LPARAM>(gNewMonitorArray)));
  101. hr = S_OK;
  102. }
  103. return hr;
  104. }
  105. void ApplyCurrentMonitorArray (void)
  106. // Discard the old and save the new as current monitor
  107. // rectangle array for the next time the function is called.
  108. {
  109. if (gOldMonitorArray != NULL)
  110. (HLOCAL)LocalFree(gOldMonitorArray);
  111. gOldMonitorArray = gNewMonitorArray;
  112. gNewMonitorArray = NULL;
  113. }
  114. // These functions determine the index into the monitor
  115. // rectangle array of a given HMONITOR, POINT or RECT.
  116. int IndexOfMonitor (tMonitorInfoArrayPtr pMIA, HMONITOR hMonitor)
  117. {
  118. int i, iLimit, iResult;
  119. tMonitorInfoPtr pMI;
  120. iResult = -1;
  121. for (i = 0, iLimit = pMIA->miaCount, pMI = pMIA->miaMonitors; i < iLimit; ++i, ++pMI)
  122. {
  123. if (pMI->miHMONITOR == hMonitor)
  124. {
  125. iResult = i;
  126. break;
  127. }
  128. }
  129. return(iResult);
  130. }
  131. // Note that the functions that take a POINT or RECT
  132. // require the co-ordinates to be in TRIDENT co-ordinates.
  133. int IndexOfMonitor (tMonitorInfoArrayPtr pMIA, POINT& pt)
  134. {
  135. int i, iLimit, iResult;
  136. tMonitorInfoPtr pMI;
  137. POINT ptLocal;
  138. ptLocal = pt;
  139. OffsetPt(ptLocal, +pMIA->miaVirtualScreen.left, +pMIA->miaVirtualScreen.top);
  140. iResult = -1;
  141. for (i = 0, iLimit = pMIA->miaCount, pMI = pMIA->miaMonitors; i < iLimit; ++i, ++pMI)
  142. {
  143. if (PtInRect(&pMI->miDisplayAreaRect, ptLocal) != 0)
  144. {
  145. iResult = i;
  146. break;
  147. }
  148. }
  149. return(iResult);
  150. }
  151. int IndexOfMonitor (tMonitorInfoArrayPtr pMIA, RECT& rc)
  152. {
  153. int iResult;
  154. POINT pt;
  155. // 99/05/12 #338446 vtan: Try all four corners of the rectangle
  156. // to find a match.
  157. pt.x = rc.left;
  158. pt.y = rc.top;
  159. iResult = IndexOfMonitor(pMIA, pt);
  160. if (iResult < 0)
  161. {
  162. pt.x = rc.left;
  163. pt.y = rc.bottom;
  164. iResult = IndexOfMonitor(pMIA, pt);
  165. if (iResult < 0)
  166. {
  167. pt.x = rc.right;
  168. pt.y = rc.top;
  169. iResult = IndexOfMonitor(pMIA, pt);
  170. if (iResult < 0)
  171. {
  172. pt.x = rc.right;
  173. pt.y = rc.bottom;
  174. iResult = IndexOfMonitor(pMIA, pt);
  175. }
  176. }
  177. }
  178. return(iResult);
  179. }
  180. int IndexOfMonitor (tMonitorInfoArrayPtr pMIA, COMPPOS& componentPosition)
  181. {
  182. RECT rcComponent;
  183. TBOOL(SetRect(&rcComponent, componentPosition.iLeft, componentPosition.iTop, componentPosition.iLeft + componentPosition.dwWidth, componentPosition.iTop + componentPosition.dwHeight));
  184. return(IndexOfMonitor(pMIA, rcComponent));
  185. }
  186. BOOL RepositionDesktopRect (RECT& rcComponent, tMonitorInfoArrayPtr oldMonitorArray, tMonitorInfoArrayPtr newMonitorArray)
  187. // Reposition the component's RECT based on the logic at the
  188. // top of the source file. Used for both the component's
  189. // current position and the restored position.
  190. {
  191. BOOL bRepositionedComponent;
  192. int iOldMonitorIndex, iNewMonitorIndex;
  193. // This is for future expansion. The components are always
  194. // deemed to be repositioned if this function is called.
  195. bRepositionedComponent = TRUE;
  196. // Find out if the monitor which the component was on is still
  197. // present. To do this find the index of the component in the
  198. // old monitor array, get the HMONITOR and find that in the new
  199. // monitor array.
  200. iOldMonitorIndex = IndexOfMonitor(oldMonitorArray, rcComponent);
  201. if (iOldMonitorIndex >= 0)
  202. {
  203. RECT *prcOldMonitor, *prcNewMonitor;
  204. iNewMonitorIndex = IndexOfMonitor(newMonitorArray, oldMonitorArray->miaMonitors[iOldMonitorIndex].miHMONITOR);
  205. if (iNewMonitorIndex < 0)
  206. {
  207. HMONITOR hMonitor;
  208. // The component is on a monitor that no longer exists. The only
  209. // thing to do in this case is to find the nearest monitor based
  210. // on the GDI co-ordinates and position it on that monitor.
  211. hMonitor = MonitorFromRect(&rcComponent, MONITOR_DEFAULTTONEAREST);
  212. iNewMonitorIndex = IndexOfMonitor(newMonitorArray, hMonitor);
  213. ASSERT(iNewMonitorIndex >= 0);
  214. }
  215. // If iNewMonitorIndex was already positive then the monitor which
  216. // the component was on still exists and simply mapping GDI
  217. // co-ordinates will work. Otherwise we found the nearest monitor
  218. // and mapping GDI co-ordinates also works!
  219. // This maps from the component's OLD co-ordinates in trident
  220. // co-ordinates to GDI co-ordinates. Then it maps from the GDI
  221. // co-ordinates to an OLD monitor relative co-ordinate. Then it
  222. // maps from the OLD monitor relative co-ordinates to the NEW
  223. // monitor GDI co-ordinates.
  224. prcOldMonitor = &oldMonitorArray->miaMonitors[iOldMonitorIndex].miDisplayAreaRect;
  225. prcNewMonitor = &newMonitorArray->miaMonitors[iNewMonitorIndex].miDisplayAreaRect;
  226. TBOOL(OffsetRect(&rcComponent, +oldMonitorArray->miaVirtualScreen.left, +oldMonitorArray->miaVirtualScreen.top));
  227. TBOOL(OffsetRect(&rcComponent, -prcOldMonitor->left, -prcOldMonitor->top));
  228. TBOOL(OffsetRect(&rcComponent, +prcNewMonitor->left, +prcNewMonitor->top));
  229. }
  230. else
  231. {
  232. // Component exists at an invalid location in the old monitor
  233. // layout. It may be valid in the new layout. Try this. If that
  234. // doesn't work then it doesn't exist in the old nor the new
  235. // layout. It was in no-man's land. Position it using the default
  236. // positioning system.
  237. iNewMonitorIndex = IndexOfMonitor(newMonitorArray, rcComponent);
  238. if (iNewMonitorIndex < 0)
  239. {
  240. POINT ptOrigin;
  241. COMPPOS componentPosition;
  242. GetNextComponentPosition(&componentPosition);
  243. IncrementComponentsPositioned();
  244. TBOOL(SetRect(&rcComponent, componentPosition.iLeft, componentPosition.iTop, componentPosition.iLeft + componentPosition.dwWidth, componentPosition.iTop + componentPosition.dwHeight));
  245. // Get the primary monitor index in our monitor rectangle array.
  246. SetPt(ptOrigin, 0, 0);
  247. iNewMonitorIndex = IndexOfMonitor(newMonitorArray, MonitorFromPoint(ptOrigin, MONITOR_DEFAULTTOPRIMARY));
  248. ASSERT(iNewMonitorIndex >= 0);
  249. }
  250. }
  251. // At this stage the component position is in GDI co-ordinates.
  252. // Convert from GDI co-ordinates back to trident co-ordinates.
  253. TBOOL(OffsetRect(&rcComponent, -newMonitorArray->miaVirtualScreen.left, -newMonitorArray->miaVirtualScreen.top));
  254. return(bRepositionedComponent);
  255. }
  256. BOOL RepositionDesktopComponent (COMPPOS& componentPosition, COMPSTATEINFO& componentStateInfo, DWORD dwItemState, int iComponentType)
  257. {
  258. BOOL bRepositionedComponent;
  259. tMonitorInfoArrayPtr oldMonitorArray, newMonitorArray;
  260. RECT rcComponent;
  261. // Check if the monitor layout has changed. If unchanged then
  262. // there is no need to move the components.
  263. oldMonitorArray = gOldMonitorArray;
  264. newMonitorArray = gNewMonitorArray;
  265. if (oldMonitorArray == NULL)
  266. {
  267. oldMonitorArray = newMonitorArray;
  268. }
  269. TBOOL(SetRect(&rcComponent, componentPosition.iLeft, componentPosition.iTop, componentPosition.iLeft + componentPosition.dwWidth, componentPosition.iTop + componentPosition.dwHeight));
  270. bRepositionedComponent = RepositionDesktopRect(rcComponent, oldMonitorArray, newMonitorArray);
  271. componentPosition.iLeft = rcComponent.left;
  272. componentPosition.iTop = rcComponent.top;
  273. componentPosition.dwWidth = rcComponent.right - rcComponent.left;
  274. componentPosition.dwHeight = rcComponent.bottom - rcComponent.top;
  275. ValidateComponentPosition(&componentPosition, dwItemState, iComponentType, NULL, NULL);
  276. // If the component is zoomed also reposition the restored
  277. // COMPSTATEINFO.
  278. if (IsZoomedState(dwItemState))
  279. {
  280. COMPPOS restoredCompPos;
  281. TBOOL(SetRect(&rcComponent, componentStateInfo.iLeft, componentStateInfo.iTop, componentStateInfo.iLeft + componentStateInfo.dwWidth, componentStateInfo.iTop + componentStateInfo.dwHeight));
  282. bRepositionedComponent = RepositionDesktopRect(rcComponent, oldMonitorArray, newMonitorArray) || bRepositionedComponent;
  283. restoredCompPos.iLeft = componentStateInfo.iLeft = rcComponent.left;
  284. restoredCompPos.iTop = componentStateInfo.iTop = rcComponent.top;
  285. restoredCompPos.dwWidth = componentStateInfo.dwWidth = rcComponent.right - rcComponent.left;
  286. restoredCompPos.dwHeight = componentStateInfo.dwHeight = rcComponent.bottom - rcComponent.top;
  287. ZoomComponent(&componentPosition, dwItemState, FALSE);
  288. restoredCompPos.dwSize = sizeof(restoredCompPos);
  289. ValidateComponentPosition(&restoredCompPos, IS_NORMAL, iComponentType, NULL, NULL);
  290. }
  291. return(bRepositionedComponent);
  292. }
  293. BOOL ReadAllComponents (HKEY hKeyDesktop, tComponentInfoPtr& pComponentInfo, DWORD& dwComponentCount)
  294. {
  295. tComponentInfoPtr pCI;
  296. if (RegQueryInfoKey(hKeyDesktop, NULL, NULL, NULL, &dwComponentCount, NULL, NULL, NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
  297. dwComponentCount = 0;
  298. if (dwComponentCount > 0)
  299. {
  300. // 99/08/09 #383184: STRESS fix. Allocate the whole block of
  301. // memory required for the components but allocate one extra
  302. // entry. advapi32!RegEnumKeyEx will try to access the memory
  303. // before determining that there is a failure condition. With
  304. // pageheap on (and the block allocated at the end of the page)
  305. // this causes an access violation. The simplest fix is to add
  306. // an extra entry.
  307. pComponentInfo = pCI = reinterpret_cast<tComponentInfoPtr>(LocalAlloc(LPTR, (dwComponentCount + 1) * sizeof(*pCI))); // LMEM_FIXED | LMEM_ZEROINIT
  308. if (pCI != NULL)
  309. {
  310. DWORD dwIndex, dwSize;
  311. // Enumerate all the desktop components.
  312. dwIndex = 0;
  313. dwSize = sizeof(pCI->ciName);
  314. while (RegEnumKeyEx(hKeyDesktop, dwIndex, pCI->ciName, &dwSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
  315. {
  316. CRegKey regKeyComponent;
  317. if (regKeyComponent.Open(hKeyDesktop, pCI->ciName, KEY_READ | KEY_WRITE) == ERROR_SUCCESS)
  318. {
  319. DWORD dwType, cbData;
  320. // Read the Position value.
  321. cbData = sizeof(pCI->ciPosition);
  322. if (SHQueryValueEx(regKeyComponent, REG_VAL_COMP_POSITION, NULL, &dwType, &pCI->ciPosition, &cbData) == ERROR_SUCCESS)
  323. {
  324. DWORD dwFlags;
  325. pCI->ciValidData = TRUE;
  326. if (SHQueryValueEx(regKeyComponent, REG_VAL_COMP_FLAGS, NULL, &dwType, &dwFlags, &cbData) == ERROR_SUCCESS)
  327. {
  328. pCI->ciVisible = ((dwFlags & COMP_SELECTED) != 0);
  329. pCI->ciType = (dwFlags & COMP_TYPE_MASK);
  330. }
  331. else
  332. {
  333. pCI->ciVisible = FALSE;
  334. pCI->ciType = COMP_TYPE_WEBSITE;
  335. }
  336. pCI->ciItemState = IS_NORMAL; // if missing (IE4 machine) or error the assume normal
  337. cbData = sizeof(pCI->ciItemState);
  338. if ((SHQueryValueEx(regKeyComponent, REG_VAL_COMP_CURSTATE, NULL, &dwType, &pCI->ciItemState, &cbData) == ERROR_SUCCESS))
  339. {
  340. // If the component is zoomed also read in the COMPSTATEINFO.
  341. if (IsZoomedState(pCI->ciItemState))
  342. {
  343. cbData = sizeof(pCI->ciStateInfo);
  344. TW32(SHQueryValueEx(regKeyComponent, REG_VAL_COMP_RESTOREDSTATEINFO, NULL, &dwType, &pCI->ciStateInfo, &cbData));
  345. }
  346. }
  347. }
  348. }
  349. ++pCI;
  350. ++dwIndex;
  351. dwSize = sizeof(pCI->ciName);
  352. }
  353. }
  354. }
  355. return((dwComponentCount != 0) && (pComponentInfo != NULL));
  356. }
  357. int IndexOfComponent (tComponentInfoPtr pComponentInfo, DWORD dwComponentCount, LPCTSTR pcszName)
  358. {
  359. int iResult, i;
  360. for (iResult = -1, i = 0; (iResult < 0) && (i < static_cast<int>(dwComponentCount)); ++i)
  361. {
  362. if (lstrcmp(pComponentInfo[i].ciName, pcszName) == 0)
  363. iResult = i;
  364. }
  365. return(iResult);
  366. }
  367. void WriteAllComponents (HKEY hKeyDesktop, tComponentInfoPtr pComponentInfo, DWORD dwComponentCount)
  368. {
  369. TCHAR szSubKeyName[kNameSize];
  370. DWORD dwSubKeyIndex, dwSubKeySize;
  371. // Enumerate all the desktop components.
  372. dwSubKeyIndex = 0;
  373. dwSubKeySize = ARRAYSIZE(szSubKeyName);
  374. while (RegEnumKeyEx(hKeyDesktop, dwSubKeyIndex, szSubKeyName, &dwSubKeySize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
  375. {
  376. CRegKey regKeyComponent;
  377. if (regKeyComponent.Open(hKeyDesktop, szSubKeyName, KEY_READ | KEY_WRITE) == ERROR_SUCCESS)
  378. {
  379. int i;
  380. i = IndexOfComponent(pComponentInfo, dwComponentCount, szSubKeyName);
  381. if ((i >= 0) && pComponentInfo[i].ciRepositioned)
  382. {
  383. TW32(RegSetValueEx(regKeyComponent, REG_VAL_COMP_POSITION, 0, REG_BINARY, reinterpret_cast<const unsigned char*>(&pComponentInfo[i].ciPosition), sizeof(pComponentInfo[i].ciPosition)));
  384. TW32(RegSetValueEx(regKeyComponent, REG_VAL_COMP_CURSTATE, NULL, REG_BINARY, reinterpret_cast<const unsigned char*>(&pComponentInfo[i].ciItemState), sizeof(pComponentInfo[i].ciItemState)));
  385. // If the component is zoomed also write out the COMPSTATEINFO.
  386. if (IsZoomedState(pComponentInfo[i].ciItemState))
  387. {
  388. TW32(RegSetValueEx(regKeyComponent, REG_VAL_COMP_RESTOREDSTATEINFO, 0, REG_BINARY, reinterpret_cast<const unsigned char*>(&pComponentInfo[i].ciStateInfo), sizeof(pComponentInfo[i].ciStateInfo)));
  389. }
  390. }
  391. }
  392. ++dwSubKeyIndex;
  393. dwSubKeySize = ARRAYSIZE(szSubKeyName);
  394. }
  395. }
  396. BOOL AdjustDesktopComponents (LPCRECT arectNew,
  397. int crectNew,
  398. LPCRECT arectOldMonitors,
  399. LPCRECT arectOld,
  400. int crectOld)
  401. {
  402. static const int kMaximumMonitorCount = 16;
  403. HRESULT hr;
  404. BOOL bRepositionedComponent;
  405. int zoomedComponentIndices[kMaximumMonitorCount]; // 16 monitors limitation here - make dynamic if required
  406. int i;
  407. tMonitorInfoArrayPtr oldMonitorArray;
  408. CRegKey regKeyDesktop;
  409. TCHAR szDeskcomp[MAX_PATH];
  410. for (i = 0; i < kMaximumMonitorCount; ++i)
  411. zoomedComponentIndices[i] = -1;
  412. bRepositionedComponent = FALSE;
  413. hr = CalculateCurrentMonitorArray();
  414. if (SUCCEEDED(hr))
  415. {
  416. oldMonitorArray = gOldMonitorArray;
  417. if (oldMonitorArray == NULL)
  418. oldMonitorArray = gNewMonitorArray;
  419. GetRegLocation(szDeskcomp, ARRAYSIZE(szDeskcomp), REG_DESKCOMP_COMPONENTS, NULL);
  420. if (ERROR_SUCCESS == regKeyDesktop.Open(HKEY_CURRENT_USER, szDeskcomp, KEY_READ))
  421. {
  422. DWORD dwComponentCount;
  423. tComponentInfoPtr pComponentInfo;
  424. // Enumerate all the desktop components.
  425. if (ReadAllComponents(regKeyDesktop, pComponentInfo, dwComponentCount))
  426. {
  427. tComponentInfoPtr pCI;
  428. for (pCI = pComponentInfo, i = 0; i < static_cast<int>(dwComponentCount); ++pCI, ++i)
  429. {
  430. int iPreviousMonitorIndexOfComponent;
  431. // Calculate the previous monitor position BEFORE the component
  432. // gets repositioned.
  433. iPreviousMonitorIndexOfComponent = IndexOfMonitor(oldMonitorArray, pCI->ciPosition);
  434. if (RepositionDesktopComponent(pCI->ciPosition, pCI->ciStateInfo, pCI->ciItemState, pCI->ciType))
  435. {
  436. int iCurrentMonitorIndexOfComponent;
  437. pCI->ciRepositioned = bRepositionedComponent = TRUE;
  438. iCurrentMonitorIndexOfComponent = IndexOfMonitor(gNewMonitorArray, pCI->ciPosition);
  439. if (iCurrentMonitorIndexOfComponent >= 0)
  440. {
  441. // 99/05/12 #338446 vtan: Only use a zero or positive index into the
  442. // monitor array. -1 is invalid and will cause an AV. This should NEVER
  443. // happen but rather than assert this condition is handled.
  444. if (IsZoomedState(pCI->ciItemState) && (zoomedComponentIndices[iCurrentMonitorIndexOfComponent] >= 0))
  445. {
  446. tComponentInfoPtr pCIToRestore;
  447. // This component is zoomed on a monitor that already has a zoomed
  448. // component. Compare this component and the component already on the
  449. // monitor. The one that was there before is the one that stays. The one
  450. // that shouldn't be there is the one that gets restored.
  451. if ((iPreviousMonitorIndexOfComponent == iCurrentMonitorIndexOfComponent) && pCI->ciVisible)
  452. pCIToRestore = pComponentInfo + zoomedComponentIndices[iCurrentMonitorIndexOfComponent];
  453. else
  454. pCIToRestore = pCI;
  455. pCIToRestore->ciPosition.iLeft = pCIToRestore->ciStateInfo.iLeft;
  456. pCIToRestore->ciPosition.iTop = pCIToRestore->ciStateInfo.iTop;
  457. pCIToRestore->ciPosition.dwWidth = pCIToRestore->ciStateInfo.dwWidth;
  458. pCIToRestore->ciPosition.dwHeight = pCIToRestore->ciStateInfo.dwHeight;
  459. pCIToRestore->ciPosition.izIndex = COMPONENT_TOP;
  460. pCIToRestore->ciItemState = IS_NORMAL;
  461. }
  462. // If the component is zoomed also write out the COMPSTATEINFO.
  463. if (IsZoomedState(pCI->ciItemState))
  464. {
  465. zoomedComponentIndices[iCurrentMonitorIndexOfComponent] = i;
  466. }
  467. }
  468. }
  469. }
  470. WriteAllComponents(regKeyDesktop, pComponentInfo, dwComponentCount);
  471. LocalFree(pComponentInfo);
  472. }
  473. if (bRepositionedComponent)
  474. {
  475. SHELLSTATE ss;
  476. SetDesktopFlags(COMPONENTS_DIRTY, COMPONENTS_DIRTY);
  477. SHGetSetSettings(&ss, SSF_DESKTOPHTML, FALSE);
  478. // Refresh only if AD is turned on.
  479. if(ss.fDesktopHTML)
  480. {
  481. // 98/09/22 #182982 vtan: Use dynamic HTML by default to refresh.
  482. // Only disallow usage when specifically told to by a flag.
  483. PokeWebViewDesktop(AD_APPLY_FORCE | AD_APPLY_HTMLGEN | AD_APPLY_REFRESH);
  484. }
  485. }
  486. }
  487. ApplyCurrentMonitorArray();
  488. }
  489. return bRepositionedComponent;
  490. }