Source code of Windows XP (NT5)
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.

318 lines
8.6 KiB

  1. /*****************************************************************************\
  2. FILE: isfvcb.cpp
  3. DESCRIPTION:
  4. This is a base class that implements the default behavior of
  5. IShellFolderViewCallBack. This allows default DefView implementation with this
  6. callback to override specific behavior.
  7. \*****************************************************************************/
  8. #include "priv.h"
  9. #include "isfvcb.h"
  10. //===========================
  11. // *** IShellFolderViewCB Interface ***
  12. //===========================
  13. /*****************************************************************************\
  14. FUNCTION: _OnSetISFV
  15. DESCRIPTION:
  16. Same as ::SetSite();
  17. \*****************************************************************************/
  18. HRESULT CBaseFolderViewCB::_OnSetISFV(IShellFolderView * psfv)
  19. {
  20. IUnknown_Set((IUnknown **) &m_psfv, (IUnknown *) psfv);
  21. return S_OK;
  22. }
  23. /*****************************************************************************\
  24. FUNCTION: IShellFolderViewCB::MessageSFVCB
  25. DESCRIPTION:
  26. \*****************************************************************************/
  27. #define NOTHANDLED(m) case m: hr = E_NOTIMPL; break
  28. HRESULT CBaseFolderViewCB::MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam)
  29. {
  30. HRESULT hr = E_FAIL;
  31. switch (uMsg)
  32. {
  33. case DVM_GETDETAILSOF:
  34. hr = _OnGetDetailsOf((UINT)wParam, (PDETAILSINFO)lParam);
  35. break;
  36. case DVM_COLUMNCLICK:
  37. hr = _OnColumnClick((UINT)wParam);
  38. break;
  39. case DVM_MERGEMENU:
  40. hr = _OnMergeMenu((LPQCMINFO)lParam);
  41. break;
  42. case DVM_UNMERGEMENU:
  43. hr = _OnUnMergeMenu((HMENU)lParam);
  44. break;
  45. case DVM_INVOKECOMMAND:
  46. hr = _OnInvokeCommand((UINT)wParam);
  47. break;
  48. case DVM_GETHELPTEXT:
  49. hr = _OnGetHelpText(lParam, wParam);
  50. break;
  51. case SFVM_GETHELPTOPIC:
  52. hr = _OnGetHelpTopic((SFVM_HELPTOPIC_DATA *) lParam);
  53. break;
  54. case DVM_GETTOOLTIPTEXT:
  55. // TODO: Implement
  56. hr = E_NOTIMPL;
  57. break;
  58. case DVM_UPDATESTATUSBAR:
  59. // TODO: Implement
  60. hr = _OnUpdateStatusBar();
  61. break;
  62. case DVM_WINDOWCREATED:
  63. hr = _OnWindowCreated();
  64. break;
  65. case SFVM_BACKGROUNDENUMDONE:
  66. hr = _OnBackGroundEnumDone();
  67. break;
  68. case DVM_INITMENUPOPUP:
  69. hr = _OnInitMenuPopup((HMENU) lParam, (UINT) HIWORD(wParam), (UINT) LOWORD(wParam));
  70. break;
  71. case DVM_RELEASE:
  72. {
  73. CBaseFolderViewCB * pfv = (CBaseFolderViewCB *) lParam;
  74. if (pfv)
  75. hr = pfv->Release();
  76. }
  77. break;
  78. case DVM_DEFITEMCOUNT:
  79. hr = _OnDefItemCount((LPINT)lParam);
  80. break;
  81. case DVM_DIDDRAGDROP:
  82. hr = _OnDidDragDrop((DROPEFFECT)wParam, (IDataObject *)lParam);
  83. break;
  84. case DVM_REFRESH:
  85. hr = _OnRefresh((BOOL) wParam);
  86. break;
  87. case SFVM_ADDPROPERTYPAGES:
  88. hr = _OnAddPropertyPages((SFVM_PROPPAGE_DATA *)lParam);
  89. break;
  90. case DVM_BACKGROUNDENUM:
  91. // WARNING! If we return S_OK from DVM_BACKGROUNDENUM, we also
  92. // are promising that we support free threading on our IEnumIDList
  93. // interface! This allows the shell to do enumeration on our
  94. // IEnumIDList on a separate background thread.
  95. hr = S_OK; // Always enum in background
  96. break;
  97. case SFVM_DONTCUSTOMIZE:
  98. if (lParam)
  99. *((BOOL *) lParam) = FALSE; // Yes, we are customizable.
  100. hr = S_OK;
  101. break;
  102. case SFVM_GETZONE:
  103. hr = _OnGetZone((DWORD *) lParam, wParam);
  104. break;
  105. case SFVM_GETPANE:
  106. hr = _OnGetPane((DWORD) wParam, (DWORD *)lParam);
  107. break;
  108. case SFVM_SETISFV:
  109. hr = _OnSetISFV((IShellFolderView *)lParam);
  110. break;
  111. case SFVM_GETNOTIFY:
  112. hr = _OnGetNotify((LPITEMIDLIST *) wParam, (LONG *) lParam);
  113. break;
  114. case SFVM_FSNOTIFY:
  115. hr = _OnFSNotify((LPITEMIDLIST *) wParam, (LONG *) lParam);
  116. break;
  117. case SFVM_QUERYFSNOTIFY:
  118. hr = _OnQueryFSNotify((SHChangeNotifyEntry *) lParam);
  119. break;
  120. case SFVM_SIZE:
  121. hr = _OnSize((LONG) wParam, (LONG) lParam);
  122. break;
  123. case SFVM_THISIDLIST:
  124. hr = _OnThisIDList((LPITEMIDLIST *) lParam);
  125. break;
  126. // The following are some we could do.
  127. // SFVM_HWNDMAIN
  128. // Others that aren't currently handled.
  129. NOTHANDLED(DVM_GETBUTTONINFO);
  130. NOTHANDLED(DVM_GETBUTTONS);
  131. NOTHANDLED(DVM_SELCHANGE);
  132. NOTHANDLED(DVM_DRAWITEM);
  133. NOTHANDLED(DVM_MEASUREITEM);
  134. NOTHANDLED(DVM_EXITMENULOOP);
  135. NOTHANDLED(DVM_GETCCHMAX);
  136. NOTHANDLED(DVM_WINDOWDESTROY);
  137. NOTHANDLED(DVM_SETFOCUS);
  138. NOTHANDLED(DVM_KILLFOCUS);
  139. NOTHANDLED(DVM_QUERYCOPYHOOK);
  140. NOTHANDLED(DVM_NOTIFYCOPYHOOK);
  141. NOTHANDLED(DVM_DEFVIEWMODE);
  142. #if 0
  143. NOTHANDLED(DVM_INSERTITEM); // Too verbose
  144. NOTHANDLED(DVM_DELETEITEM);
  145. #endif
  146. NOTHANDLED(DVM_GETWORKINGDIR);
  147. NOTHANDLED(DVM_GETCOLSAVESTREAM);
  148. NOTHANDLED(DVM_SELECTALL);
  149. NOTHANDLED(DVM_SUPPORTSIDENTIFY);
  150. NOTHANDLED(DVM_FOLDERISPARENT);
  151. default:
  152. hr = E_NOTIMPL;
  153. break;
  154. }
  155. return hr;
  156. }
  157. /****************************************************\
  158. Constructor
  159. \****************************************************/
  160. CBaseFolderViewCB::CBaseFolderViewCB() : m_cRef(1), m_dwSignature(c_dwSignature)
  161. {
  162. DllAddRef();
  163. // This needs to be allocated in Zero Inited Memory.
  164. // Assert that all Member Variables are inited to Zero.
  165. ASSERT(!m_psfv);
  166. }
  167. /****************************************************\
  168. Destructor
  169. \****************************************************/
  170. CBaseFolderViewCB::~CBaseFolderViewCB()
  171. {
  172. m_dwSignature = 0; // Turn off _IShellFolderViewCallBack
  173. IUnknown_Set((IUnknown **)&m_psfv, NULL);
  174. DllRelease();
  175. }
  176. //===========================
  177. // *** IUnknown Interface ***
  178. //===========================
  179. ULONG CBaseFolderViewCB::AddRef()
  180. {
  181. m_cRef++;
  182. return m_cRef;
  183. }
  184. ULONG CBaseFolderViewCB::Release()
  185. {
  186. ASSERT(m_cRef > 0);
  187. m_cRef--;
  188. if (m_cRef > 0)
  189. return m_cRef;
  190. delete this;
  191. return 0;
  192. }
  193. // {7982F251-C37A-11d1-9823-006097DF5BD4}
  194. static const GUID CIID_PrivateThis = { 0x7982f251, 0xc37a, 0x11d1, { 0x98, 0x23, 0x0, 0x60, 0x97, 0xdf, 0x5b, 0xd4 } };
  195. HRESULT CBaseFolderViewCB::QueryInterface(REFIID riid, void **ppvObj)
  196. {
  197. if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IShellFolderViewCB))
  198. {
  199. *ppvObj = SAFECAST(this, IShellFolderViewCB*);
  200. }
  201. else
  202. if (IsEqualIID(riid, IID_IObjectWithSite))
  203. {
  204. *ppvObj = SAFECAST(this, IObjectWithSite*);
  205. }
  206. else
  207. {
  208. *ppvObj = NULL;
  209. return E_NOINTERFACE;
  210. }
  211. AddRef();
  212. return S_OK;
  213. }
  214. HRESULT CBaseFolderViewCB::_IShellFolderViewCallBack(IShellView * psvOuter, IShellFolder * psf, HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  215. {
  216. IShellFolderViewCB * psfvcb = NULL;
  217. HRESULT hr = E_FAIL;
  218. // Now this is a total hack. I am bastardizing the pszOuter param to really be the this pointer that
  219. // is the IShellFolderViewCB interface of the CBaseFolderViewCB object. I use the SFVM_WINDOWDESTROY event to
  220. // release the object but DefView calls us back with one more message before we completely go away
  221. // and that message is SFVM_SETISFV. Everytime the SFVM_SETISFV is called with a NULL lParam, it's
  222. // equivalent to calling ::SetSite(NULL). We can ignore this because we release the back pointer in our
  223. // destructor.
  224. if (((SFVM_SETISFV == uMsg) && !lParam) ||
  225. (SFVM_PRERELEASE == uMsg))
  226. {
  227. return S_OK;
  228. }
  229. // psvOuter is really our CBaseFolderViewCB. Sniff around to make sure.
  230. // Note that this casting must exactly invert the casts that we do in
  231. // CBaseFolder::_CreateShellView.
  232. CBaseFolderViewCB *pbfvcb = (CBaseFolderViewCB *)(IShellFolderViewCB *)psvOuter;
  233. if (EVAL(!IsBadReadPtr(pbfvcb, sizeof(CBaseFolderViewCB))) &&
  234. EVAL(pbfvcb->m_dwSignature == c_dwSignature))
  235. {
  236. // psvOuter is really our CBaseFolderViewCB and let's make sure with this QI.
  237. hr = psvOuter->QueryInterface(IID_IShellFolderViewCB, (void **) &psfvcb);
  238. if (EVAL(psfvcb))
  239. {
  240. hr = psfvcb->MessageSFVCB(uMsg, wParam, lParam);
  241. if ((SFVM_WINDOWDESTROY == uMsg)) // (DVM_WINDOWDESTROY == SFVM_WINDOWDESTROY)
  242. {
  243. ASSERT(!lParam); // Sometimes callers want this to be freed.
  244. psvOuter->Release(); // We are releasing the psvOuter that DefView is holding. We shouldn't be called again.
  245. }
  246. psfvcb->Release();
  247. }
  248. }
  249. return hr;
  250. }