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.

468 lines
14 KiB

  1. #include "priv.h"
  2. #include "fldset.h"
  3. #define IShellView_CreateViewWindow(_pi, _piPrev, _pfs, _psb, _prc, _phw) \
  4. (_pi)->CreateViewWindow(_piPrev, _pfs, _psb, _prc, _phw)
  5. #define IShellView2_GetView(_pi, _pv, _flg) \
  6. (_pi)->GetView(_pv, _flg)
  7. #define IShellView2_CreateViewWindow2(_pi, _cParams) \
  8. (_pi)->CreateViewWindow2(_cParams)
  9. #define IUnknown_QueryInterface(_pu, _riid, _pi) \
  10. (_pu)->QueryInterface(_riid, (LPVOID*)_pi)
  11. #define IUnknown_AddRef(_pu) (_pu)->AddRef()
  12. #define IUnknown_Release(_pu) (_pu)->Release()
  13. typedef struct CViewSet
  14. {
  15. HDSA _dsaViews;
  16. } CViewSet;
  17. CViewSet* CViewSet_New()
  18. {
  19. CViewSet* pThis = (CViewSet*)LocalAlloc(LPTR, SIZEOF(CViewSet));
  20. if (!pThis)
  21. {
  22. return(NULL);
  23. }
  24. pThis->_dsaViews = DSA_Create(SIZEOF(SHELLVIEWID), 8);
  25. if (!pThis->_dsaViews)
  26. {
  27. LocalFree(pThis);
  28. pThis = NULL;
  29. }
  30. return(pThis);
  31. }
  32. int CViewSet_Add(CViewSet* that, SHELLVIEWID const* pvid)
  33. {
  34. return(DSA_AppendItem(that->_dsaViews, (LPVOID)pvid));
  35. }
  36. void CViewSet_Delete(CViewSet* that)
  37. {
  38. DSA_Destroy(that->_dsaViews);
  39. that->_dsaViews = NULL;
  40. LocalFree((HLOCAL)that);
  41. that = NULL;
  42. }
  43. void CViewSet_GetDefaultView(CViewSet* that, SHELLVIEWID* pvid)
  44. {
  45. DSA_GetItem(that->_dsaViews, 0, (LPVOID)pvid);
  46. }
  47. void CViewSet_SetDefaultView(CViewSet* that, SHELLVIEWID const* pvid)
  48. {
  49. DSA_SetItem(that->_dsaViews, 0, (LPVOID)pvid);
  50. }
  51. // PERF: A linear search for the view
  52. BOOL CViewSet_IsViewSupported(CViewSet* that, SHELLVIEWID const* pvid)
  53. {
  54. int i;
  55. // Only go down to 1 since item 0 is the default view
  56. for (i=DSA_GetItemCount(that->_dsaViews)-1; i>=1; --i)
  57. {
  58. if (0 == memcmp(pvid, DSA_GetItemPtr(that->_dsaViews, i),
  59. SIZEOF(SHELLVIEWID)))
  60. {
  61. return(TRUE);
  62. }
  63. }
  64. return(FALSE);
  65. }
  66. // PERF: a linear check
  67. BOOL CViewSet_IsSame(CViewSet* that, CViewSet* pThatView)
  68. {
  69. int iView = DSA_GetItemCount(pThatView->_dsaViews);
  70. if (DSA_GetItemCount(that->_dsaViews) != iView)
  71. {
  72. return(FALSE);
  73. }
  74. for (--iView; iView>=1; --iView)
  75. {
  76. if (!CViewSet_IsViewSupported(that,
  77. (SHELLVIEWID const*)DSA_GetItemPtr(pThatView->_dsaViews, iView)))
  78. {
  79. return(FALSE);
  80. }
  81. }
  82. return(TRUE);
  83. }
  84. BOOL CShellViews_Init(CShellViews* that)
  85. {
  86. if (that->_dpaViews)
  87. {
  88. return(TRUE);
  89. }
  90. {
  91. HDPA dpaViews = DPA_Create(4);
  92. if (!dpaViews)
  93. {
  94. return(FALSE);
  95. }
  96. {
  97. CViewSet* pCommViews = CViewSet_New();
  98. if (!pCommViews)
  99. {
  100. DPA_Destroy(dpaViews);
  101. dpaViews = NULL;
  102. return(FALSE);
  103. }
  104. // The first one is the last known view for that set
  105. CViewSet_Add(pCommViews, &VID_LargeIcons);
  106. CViewSet_Add(pCommViews, &VID_LargeIcons);
  107. CViewSet_Add(pCommViews, &VID_SmallIcons);
  108. CViewSet_Add(pCommViews, &VID_Thumbnails);
  109. CViewSet_Add(pCommViews, &VID_List );
  110. CViewSet_Add(pCommViews, &VID_Details );
  111. CViewSet_Add(pCommViews, &VID_Tile );
  112. if (0 != DPA_InsertPtr(dpaViews, 0, pCommViews))
  113. {
  114. CViewSet_Delete(pCommViews);
  115. DPA_Destroy(dpaViews);
  116. dpaViews = NULL;
  117. return(FALSE);
  118. }
  119. that->_dpaViews = dpaViews;
  120. return(TRUE);
  121. }
  122. }
  123. }
  124. void CShellViews_GetDefaultView(CShellViews* that, UINT uViewSet,
  125. SHELLVIEWID* pvid)
  126. {
  127. CViewSet* pViewSet = (CViewSet*)DPA_GetPtr(that->_dpaViews, uViewSet);
  128. if (!pViewSet)
  129. {
  130. pViewSet = (CViewSet*)DPA_GetPtr(that->_dpaViews, 0);
  131. if (!pViewSet)
  132. {
  133. *pvid = VID_LargeIcons;
  134. return;
  135. }
  136. }
  137. CViewSet_GetDefaultView(pViewSet, pvid);
  138. }
  139. void CShellViews_SetDefaultView(CShellViews* that, UINT uViewSet,
  140. SHELLVIEWID const* pvid)
  141. {
  142. CViewSet* pViewSet = (CViewSet*)DPA_GetPtr(that->_dpaViews, uViewSet);
  143. if (!pViewSet)
  144. {
  145. return;
  146. }
  147. CViewSet_SetDefaultView(pViewSet, pvid);
  148. }
  149. // PERF: a linear search for the view set
  150. int CShellViews_Add(CShellViews* that, CViewSet* pThisView, BOOL *pbNew)
  151. {
  152. int iViewSet;
  153. *pbNew = FALSE;
  154. for (iViewSet=0; ; ++iViewSet)
  155. {
  156. CViewSet* pThatView = (CViewSet*)DPA_GetPtr(that->_dpaViews, iViewSet);
  157. if (!pThatView)
  158. {
  159. break;
  160. }
  161. if (CViewSet_IsSame(pThatView, pThisView))
  162. {
  163. // Found the same set; delete the one passed in and hand back the
  164. // existing one
  165. CViewSet_Delete(pThisView);
  166. return(iViewSet);
  167. }
  168. }
  169. // I guess we didn't find it
  170. iViewSet = DPA_AppendPtr(that->_dpaViews, (LPVOID)pThisView);
  171. if (iViewSet < 0)
  172. {
  173. CViewSet_Delete(pThisView);
  174. return(0);
  175. }
  176. *pbNew = TRUE;
  177. return(iViewSet);
  178. }
  179. BOOL CShellViews_IsViewSupported(CShellViews* that, UINT uViewSet,
  180. SHELLVIEWID const*pvid)
  181. {
  182. CViewSet* pViewSet = (CViewSet*)DPA_GetPtr(that->_dpaViews, uViewSet);
  183. if (!pViewSet)
  184. {
  185. return(FALSE);
  186. }
  187. return(CViewSet_IsViewSupported(pViewSet, pvid));
  188. }
  189. int DPA_CViewSet_DeleteCallback(LPVOID p, LPVOID d)
  190. {
  191. if (p)
  192. CViewSet_Delete((CViewSet*)p);
  193. return 1;
  194. }
  195. void CShellViews_Delete(CShellViews* that)
  196. {
  197. if (that && that->_dpaViews)
  198. {
  199. DPA_DestroyCallback(that->_dpaViews, DPA_CViewSet_DeleteCallback, 0);
  200. that->_dpaViews = NULL;
  201. }
  202. }
  203. BOOL FileCabinet_GetDefaultViewID2(FOLDERSETDATABASE* that, SHELLVIEWID* pvid)
  204. {
  205. if (CShellViews_Init(&that->_cViews))
  206. {
  207. CShellViews_GetDefaultView(&that->_cViews, that->_iViewSet, pvid);
  208. return(TRUE);
  209. }
  210. return(FALSE);
  211. }
  212. HRESULT FileCabinet_CreateViewWindow2(IShellBrowser* psb, FOLDERSETDATABASE* that, IShellView *psvNew,
  213. IShellView *psvOld, RECT *prcView, HWND *phWnd)
  214. {
  215. SHELLVIEWID vid, vidOld, vidRestore;
  216. IShellView2 *psv2New;
  217. CViewSet *pThisView;
  218. DWORD dwViewPriority;
  219. BOOL bCalledSV2 = FALSE;
  220. HRESULT hres = S_OK; // init to avoid a bogus C4701 warning
  221. if (!CShellViews_Init(&that->_cViews))
  222. {
  223. // Can't do anything with view sets; just do the old thing
  224. goto OldStyle;
  225. }
  226. // Default to whatever the last "old-style" view is
  227. CShellViews_GetDefaultView(&that->_cViews, 0, &vidOld);
  228. if (psvOld)
  229. {
  230. IShellView2 *psv2Old;
  231. if (SUCCEEDED(IUnknown_QueryInterface(psvOld, IID_IShellView2, &psv2Old)))
  232. {
  233. // Try to get the current view
  234. if (NOERROR == IShellView2_GetView(psv2Old, &vidOld, SV2GV_CURRENTVIEW))
  235. {
  236. CShellViews_SetDefaultView(&that->_cViews, that->_iViewSet, &vidOld);
  237. }
  238. IUnknown_Release(psv2Old);
  239. }
  240. else
  241. {
  242. // Get the view ID from the folder settings
  243. ViewIDFromViewMode(that->_fld._fs.ViewMode, &vidOld);
  244. CShellViews_SetDefaultView(&that->_cViews, 0, &vidOld);
  245. }
  246. }
  247. pThisView = CViewSet_New();
  248. if (!pThisView)
  249. {
  250. goto OldStyle;
  251. }
  252. if (SUCCEEDED(IUnknown_QueryInterface(psvNew, IID_IShellView2, &psv2New)))
  253. {
  254. SHELLVIEWID vidFolderDefault;
  255. if (NOERROR == IShellView2_GetView(psv2New, &vidFolderDefault, SV2GV_DEFAULTVIEW))
  256. {
  257. // we can now make up a view set for that folder
  258. if (CViewSet_Add(pThisView, &vidFolderDefault) >= 0)
  259. {
  260. int iViewSet;
  261. UINT uView;
  262. BOOL bNew;
  263. // NOTE: This usage of IShellView2::GetView is not documented in MSDN...
  264. for (uView=0; NOERROR==IShellView2_GetView(psv2New, &vid, uView);
  265. ++uView)
  266. {
  267. CViewSet_Add(pThisView, &vid);
  268. }
  269. // Add that view set. we will get an existing view set if it is
  270. // a duplicate
  271. iViewSet = CShellViews_Add(&that->_cViews, pThisView, &bNew);
  272. // This is now owned by CShellViews
  273. pThisView = NULL;
  274. //
  275. // Here is where we decide which view we want to use.
  276. //
  277. // Start with what came from the FOLDERSETDATABASE, then see if
  278. // anyone else has a higher VIEW_PRIORITY_XXX that would override this one.
  279. vidRestore = that->_fld._vidRestore;
  280. dwViewPriority = that->_fld._dwViewPriority;
  281. // ToddB, 8-18-99:
  282. // When we set the _fld._dwViewPriority in WebBrowserOc::Load(IPropertyBag *...) we want that ViewID to stick
  283. // around. Only failing the CShellViews_IsViewSupported call below should set a different view. Even then
  284. // we want to go back to this view on the next navigate. To accomplish this we need to keep the priority of
  285. // that view at what it was originally set to. This can be done by removing the following line of code:
  286. //
  287. // that->_fld._dwViewPriority = VIEW_PRIORITY_NONE;
  288. //
  289. // However, its possible that the line of code above was there for a good reason. I suspect that line was
  290. // originally added simply as a precaution or because the meaning of _vidRestore was not clearly defined in
  291. // relation to navigation inside a WebBrowserOC. I'm leaving the line here and commented out just in case.
  292. // If any new bugs arise about changing the view window and getting the wrong view I would look here first.
  293. // Make sure that what we got is a supported view
  294. if (!CShellViews_IsViewSupported(&that->_cViews, iViewSet, &vidRestore))
  295. {
  296. // Oops, that view isn't supported by this shell ext.
  297. // Set the priority to NONE so that one of the others will override it.
  298. dwViewPriority = VIEW_PRIORITY_NONE;
  299. }
  300. DWORD cbSize;
  301. DWORD dwValue;
  302. DWORD dwShellExtPriority;
  303. cbSize = SIZEOF(dwValue);
  304. if (ERROR_SUCCESS == SHGetValue(HKEY_CURRENT_USER,
  305. TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced"),
  306. TEXT("ClassicViewState"), NULL, &dwValue, &cbSize)
  307. && dwValue)
  308. {
  309. // We want to inherit from the previous folder if at all possible
  310. // Otherwise, we will use the new shell extended view.
  311. // To do this, we set the shell ext view priority lower than inherit
  312. dwShellExtPriority = VIEW_PRIORITY_SHELLEXT_ASBACKUP;
  313. }
  314. else
  315. {
  316. dwShellExtPriority = VIEW_PRIORITY_SHELLEXT;
  317. }
  318. // Let the shell ext select the view if it has higher priority than
  319. // what we already have, and it is supported as well.
  320. if (dwViewPriority <= dwShellExtPriority &&
  321. CShellViews_IsViewSupported(&that->_cViews, iViewSet, &vidFolderDefault))
  322. {
  323. // shell extension is more important
  324. vidRestore = vidFolderDefault;
  325. dwViewPriority = dwShellExtPriority;
  326. }
  327. // Maybe we can inherit it from the previous view...
  328. if (dwViewPriority <= VIEW_PRIORITY_INHERIT &&
  329. psvOld &&
  330. bNew &&
  331. CShellViews_IsViewSupported(&that->_cViews, iViewSet, &vidOld))
  332. {
  333. // We just navigated from another shell view. Use the same view as the last
  334. // folder.
  335. vidRestore = vidOld;
  336. dwViewPriority = VIEW_PRIORITY_INHERIT;
  337. }
  338. // We're getting really desperate now...
  339. if (dwViewPriority <= VIEW_PRIORITY_DESPERATE)
  340. {
  341. // Try the last view for the folders current viewset.
  342. CShellViews_GetDefaultView(&that->_cViews, iViewSet, &vidRestore);
  343. dwViewPriority = VIEW_PRIORITY_DESPERATE;
  344. }
  345. // All finished trying to figure out what view to use
  346. ASSERT(dwViewPriority > VIEW_PRIORITY_NONE);
  347. // assure webview no in vid, it is persisted in shellstate now.
  348. {
  349. SV2CVW2_PARAMS cParams =
  350. {
  351. SIZEOF(SV2CVW2_PARAMS),
  352. psvOld,
  353. &that->_fld._fs,
  354. psb,
  355. prcView,
  356. &vidRestore,
  357. NULL,
  358. } ;
  359. hres = IShellView2_CreateViewWindow2(psv2New, &cParams);
  360. bCalledSV2 = TRUE;
  361. *phWnd = cParams.hwndView;
  362. }
  363. if (SUCCEEDED(hres))
  364. {
  365. that->_iViewSet = iViewSet;
  366. }
  367. }
  368. }
  369. IUnknown_Release(psv2New);
  370. }
  371. if (pThisView)
  372. {
  373. CViewSet_Delete(pThisView);
  374. }
  375. if (bCalledSV2)
  376. {
  377. return(hres);
  378. }
  379. OldStyle:
  380. that->_iViewSet = 0;
  381. return IShellView_CreateViewWindow(psvNew, psvOld, &that->_fld._fs, (IShellBrowser*)psb, prcView, phWnd);
  382. }