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

Windows Kernel

Development Platform:

Visual C++

  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.         return(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.     LocalFree((HLOCAL)that);
  40. }
  41. void CViewSet_GetDefaultView(CViewSet* that, SHELLVIEWID* pvid)
  42. {
  43.     DSA_GetItem(that->_dsaViews, 0, (LPVOID)pvid);
  44. }
  45. void CViewSet_SetDefaultView(CViewSet* that, SHELLVIEWID const* pvid)
  46. {
  47.     DSA_SetItem(that->_dsaViews, 0, (LPVOID)pvid);
  48. }
  49. // BUGBUG: A linear search for the view
  50. BOOL CViewSet_IsViewSupported(CViewSet* that, SHELLVIEWID const* pvid)
  51. {
  52.     int i;
  53.     // Only go down to 1 since item 0 is the default view
  54.     for (i=DSA_GetItemCount(that->_dsaViews)-1; i>=1; --i)
  55.     {
  56.         if (0 == memcmp(pvid, DSA_GetItemPtr(that->_dsaViews, i),
  57.             SIZEOF(SHELLVIEWID)))
  58.         {
  59.             return(TRUE);
  60.         }
  61.     }
  62.     return(FALSE);
  63. }
  64. // BUGBUG: a linear check
  65. BOOL CViewSet_IsSame(CViewSet* that, CViewSet* pThatView)
  66. {
  67.     int iView = DSA_GetItemCount(pThatView->_dsaViews);
  68.     if (DSA_GetItemCount(that->_dsaViews) != iView)
  69.     {
  70.         return(FALSE);
  71.     }
  72.     for (--iView; iView>=1; --iView)
  73.     {
  74.         if (!CViewSet_IsViewSupported(that,
  75.             (SHELLVIEWID const*)DSA_GetItemPtr(pThatView->_dsaViews, iView)))
  76.         {
  77.             return(FALSE);
  78.         }
  79.     }
  80.     return(TRUE);
  81. }
  82. BOOL CShellViews_Init(CShellViews* that)
  83. {
  84.     if (that->_dpaViews)
  85.     {
  86.         return(TRUE);
  87.     }
  88.     {
  89.         HDPA dpaViews = DPA_Create(4);
  90.         if (!dpaViews)
  91.         {
  92.             return(FALSE);
  93.         }
  94.         {
  95.             CViewSet* pCommViews = CViewSet_New();
  96.             if (!pCommViews)
  97.             {
  98.                 DPA_Destroy(dpaViews);
  99.                 return(FALSE);
  100.             }
  101.             // The first one is the last known view for that set
  102.             CViewSet_Add(pCommViews, &VID_LargeIcons);
  103.             CViewSet_Add(pCommViews, &VID_LargeIcons);
  104.             CViewSet_Add(pCommViews, &VID_SmallIcons);
  105.             CViewSet_Add(pCommViews, &VID_List      );
  106.             CViewSet_Add(pCommViews, &VID_Details   );
  107.             if (0 != DPA_InsertPtr(dpaViews, 0, pCommViews))
  108.             {
  109.                 CViewSet_Delete(pCommViews);
  110.                 DPA_Destroy(dpaViews);
  111.                 return(FALSE);
  112.             }
  113.             that->_dpaViews = dpaViews;
  114.             return(TRUE);
  115.         }
  116.     }
  117. }
  118. void CShellViews_GetDefaultView(CShellViews* that, UINT uViewSet,
  119.     SHELLVIEWID* pvid)
  120. {
  121.     CViewSet* pViewSet = (CViewSet*)DPA_GetPtr(that->_dpaViews, uViewSet);
  122.     if (!pViewSet)
  123.     {
  124.         pViewSet = (CViewSet*)DPA_GetPtr(that->_dpaViews, 0);
  125.         if (!pViewSet)
  126.         {
  127.             *pvid = VID_LargeIcons;
  128.             return;
  129.         }
  130.     }
  131.     CViewSet_GetDefaultView(pViewSet, pvid);
  132. }
  133. void CShellViews_SetDefaultView(CShellViews* that, UINT uViewSet,
  134.     SHELLVIEWID const* pvid)
  135. {
  136.     CViewSet* pViewSet = (CViewSet*)DPA_GetPtr(that->_dpaViews, uViewSet);
  137.     if (!pViewSet)
  138.     {
  139.         return;
  140.     }
  141.     CViewSet_SetDefaultView(pViewSet, pvid);
  142. }
  143. // BUGBUG: a linear search for the view set
  144. int CShellViews_Add(CShellViews* that, CViewSet* pThisView, BOOL *pbNew)
  145. {
  146.     int iViewSet;
  147.     *pbNew = FALSE;
  148.     for (iViewSet=0; ; ++iViewSet)
  149.     {
  150.         CViewSet* pThatView = (CViewSet*)DPA_GetPtr(that->_dpaViews, iViewSet);
  151.         if (!pThatView)
  152.         {
  153.             break;
  154.         }
  155.         if (CViewSet_IsSame(pThatView, pThisView))
  156.         {
  157.             // Found the same set; delete the one passed in and hand back the
  158.             // existing one
  159.             CViewSet_Delete(pThisView);
  160.             return(iViewSet);
  161.         }
  162.     }
  163.     // I guess we didn't find it
  164.     iViewSet = DPA_AppendPtr(that->_dpaViews, (LPVOID)pThisView);
  165.     if (iViewSet < 0)
  166.     {
  167.         CViewSet_Delete(pThisView);
  168.         return(0);
  169.     }
  170.     *pbNew = TRUE;
  171.     return(iViewSet);
  172. }
  173. BOOL CShellViews_IsViewSupported(CShellViews* that, UINT uViewSet,
  174.     SHELLVIEWID  const*pvid)
  175. {
  176.     CViewSet* pViewSet = (CViewSet*)DPA_GetPtr(that->_dpaViews, uViewSet);
  177.     if (!pViewSet)
  178.     {
  179.         return(FALSE);
  180.     }
  181.     return(CViewSet_IsViewSupported(pViewSet, pvid));
  182. }
  183. int DPA_CViewSet_DeleteCallback(LPVOID p, LPVOID d)
  184. {
  185.     if (p)
  186.         CViewSet_Delete((CViewSet*)p);
  187.     return 1;
  188. }
  189. void CShellViews_Delete(CShellViews* that)
  190. {
  191.     if (that->_dpaViews)
  192.     {
  193.         DPA_DestroyCallback(that->_dpaViews, DPA_CViewSet_DeleteCallback, 0);
  194.         that->_dpaViews = NULL;
  195.     }
  196. }
  197. BOOL FileCabinet_GetDefaultViewID2(FOLDERSETDATABASE* that, SHELLVIEWID* pvid)
  198. {
  199.     if (CShellViews_Init(&that->_cViews))
  200.     {
  201.         CShellViews_GetDefaultView(&that->_cViews, that->_iViewSet, pvid);
  202.         return(TRUE);
  203.     }
  204.     return(FALSE);
  205. }
  206. HRESULT FileCabinet_CreateViewWindow2(IShellBrowser* psb, FOLDERSETDATABASE* that, IShellView *psvNew,
  207.     IShellView *psvOld, RECT *prcView, HWND *phWnd)
  208. {
  209.     SHELLVIEWID vid, vidOld, vidRestore;
  210.     IShellView2 *psv2New;
  211.     CViewSet *pThisView;
  212.     DWORD dwViewPriority;
  213.     BOOL bCalledSV2 = FALSE;
  214.     HRESULT hres = S_OK;  // init to avoid a bogus C4701 warning
  215.     if (!CShellViews_Init(&that->_cViews))
  216.     {
  217.         // Can't do anything with view sets; just do the old thing
  218.         goto OldStyle;
  219.     }
  220.     // Default to whatever the last "old-style" view is
  221.     CShellViews_GetDefaultView(&that->_cViews, 0, &vidOld);
  222.     if (psvOld)
  223.     {
  224.         IShellView2 *psv2Old;
  225.         if (SUCCEEDED(IUnknown_QueryInterface(psvOld, IID_IShellView2,
  226.                                               &psv2Old)))
  227.         {
  228.             // Try to get the current view
  229.             if (NOERROR == IShellView2_GetView(psv2Old, &vidOld, SV2GV_CURRENTVIEW))
  230.             {
  231.                 CShellViews_SetDefaultView(&that->_cViews, that->_iViewSet, &vidOld);
  232.             }
  233.             IUnknown_Release(psv2Old);
  234.         }
  235.         else
  236.         {
  237.             // Get the view ID from the folder settings
  238.             ViewIDFromViewMode(that->_fld._fs.ViewMode, &vidOld);
  239.             CShellViews_SetDefaultView(&that->_cViews, 0, &vidOld);
  240.         }
  241.     }
  242.     pThisView = CViewSet_New();
  243.     if (!pThisView)
  244.     {
  245.         goto OldStyle;
  246.     }
  247.     if (SUCCEEDED(IUnknown_QueryInterface(psvNew, IID_IShellView2, &psv2New)))
  248.     {
  249.         SHELLVIEWID vidFolderDefault;
  250.         if (NOERROR == IShellView2_GetView(psv2New, &vidFolderDefault, SV2GV_DEFAULTVIEW))
  251.         {
  252.             // we can now make up a view set for that folder
  253.             if (CViewSet_Add(pThisView, &vidFolderDefault) >= 0)
  254.             {
  255.                 int iViewSet;
  256.                 UINT uView;
  257.                 BOOL bNew;
  258.                 for (uView=0; NOERROR==IShellView2_GetView(psv2New, &vid, uView);
  259.                     ++uView)
  260.                 {
  261.                     CViewSet_Add(pThisView, &vid);
  262.                 }
  263.                 // Add that view set.  we will get an existing view set if it is
  264.                 // a duplicate
  265.                 iViewSet = CShellViews_Add(&that->_cViews, pThisView, &bNew);
  266.                 // This is now owned by CShellViews
  267.                 pThisView = NULL;
  268.                 
  269.                 //
  270.                 // Here is where we decide which view we want to use.
  271.                 //
  272.                 // Start with what came from the FOLDERSETDATABASE, then see if
  273.                 // anyone else has a higher VIEW_PRIORITY_XXX that would override this one.
  274.                 vidRestore = that->_fld._vidRestore;
  275.                 dwViewPriority = that->_fld._dwViewPriority;
  276.                 that->_fld._dwViewPriority = VIEW_PRIORITY_NONE;
  277.                 // Make sure that what we got is a supported view
  278.                 if (!CShellViews_IsViewSupported(&that->_cViews, iViewSet, &vidRestore))
  279.                 {
  280.                     // Oops, that view isn't supported by this shell ext.
  281.                     // Set the priority to NONE so that one of the others will override it.
  282.                     dwViewPriority = VIEW_PRIORITY_NONE;
  283.                 }
  284.                 // Let the shell ext select the view if it has higher priority than
  285.                 // what we already have, and it is supported as well.
  286.                 if (dwViewPriority <= VIEW_PRIORITY_SHELLEXT &&
  287.                     vidFolderDefault != VID_LargeIcons &&
  288.                     CShellViews_IsViewSupported(&that->_cViews, iViewSet, &vidFolderDefault))
  289.                 {
  290.                     // shell extension is more important
  291.                     vidRestore = vidFolderDefault;
  292.                     dwViewPriority = VIEW_PRIORITY_SHELLEXT;
  293.                 }
  294.                 // Maybe we can inherit it from the previous view...
  295.                 if (dwViewPriority <= VIEW_PRIORITY_INHERIT &&
  296.                     psvOld &&
  297.                     bNew &&
  298.                     CShellViews_IsViewSupported(&that->_cViews, iViewSet, &vidOld))
  299.                 {
  300.                     // We just navigated from another shell view. Use the same view as the last
  301.                     // folder.
  302.                     vidRestore = vidOld;
  303.                     dwViewPriority = VIEW_PRIORITY_INHERIT;
  304.                 }
  305.                 // We're getting really desperate now...
  306.                 if (dwViewPriority <= VIEW_PRIORITY_DESPERATE)
  307.                 {
  308.                     // Try the last view for the folders current viewset.
  309.                     CShellViews_GetDefaultView(&that->_cViews, iViewSet, &vidRestore);
  310.                     dwViewPriority = VIEW_PRIORITY_DESPERATE;
  311.                 }
  312.                   
  313.                 // All finished trying to figure out what view to use
  314.                 ASSERT(dwViewPriority > VIEW_PRIORITY_NONE);
  315.                 // assure webview no in vid, it is persisted in shellstate now.
  316.                 {
  317.                     SV2CVW2_PARAMS cParams =
  318.                     {
  319.                         SIZEOF(SV2CVW2_PARAMS),
  320.                         psvOld,
  321.                         &that->_fld._fs,
  322.                         psb,
  323.                         prcView,
  324.                         &vidRestore,
  325.                         NULL,
  326.                     } ;
  327.                     hres = IShellView2_CreateViewWindow2(psv2New, &cParams);
  328.                     bCalledSV2 = TRUE;
  329.                     *phWnd = cParams.hwndView;
  330.                 }
  331.                 if (SUCCEEDED(hres))
  332.                 {
  333.                     that->_iViewSet = iViewSet;
  334.                 }
  335.             }
  336.         }
  337.         IUnknown_Release(psv2New);
  338.     }
  339.     if (pThisView)
  340.     {
  341.         CViewSet_Delete(pThisView);
  342.     }
  343.     if (bCalledSV2)
  344.     {
  345.         return(hres);
  346.     }
  347. OldStyle:
  348.     that->_iViewSet = 0;
  349.     return IShellView_CreateViewWindow(psvNew, psvOld, &that->_fld._fs, (IShellBrowser*)psb, prcView, phWnd);
  350. }