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.

412 lines
14 KiB

  1. #include "shellprv.h"
  2. #include "cowsite.h"
  3. #pragma hdrstop
  4. // this is the comdlg frame that we will use to host the file picker object, it mostly is
  5. // a stub that will forward accordingly
  6. //
  7. // the lifetime of this is handled by the DefView object we are attached to, which when
  8. // the parent (CFolderViewHost) is destroyed will be taken down.
  9. class CViewHostBrowser : public IShellBrowser, ICommDlgBrowser2, IServiceProvider
  10. {
  11. public:
  12. CViewHostBrowser(HWND hwndParent, IShellView *psvWeak, IUnknown *punkSiteWeak);
  13. ~CViewHostBrowser();
  14. // IServiceProvider
  15. STDMETHODIMP QueryService(REFGUID guidService, REFIID riid, void **ppv);
  16. // *** IUnknown methods ***
  17. STDMETHOD(QueryInterface)(REFIID riid, LPVOID *ppvObj);
  18. STDMETHOD_(ULONG,AddRef)(THIS);
  19. STDMETHOD_(ULONG,Release)(THIS);
  20. // *** IOleWindow methods ***
  21. STDMETHOD(GetWindow)(HWND *lphwnd)
  22. { *lphwnd = _hwndParent; return S_OK; }
  23. STDMETHOD(ContextSensitiveHelp)(BOOL fEnterMode)
  24. { return S_OK; }
  25. // *** IShellBrowser methods *** (same as IOleInPlaceFrame)
  26. STDMETHOD(InsertMenusSB)(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths)
  27. { return E_NOTIMPL; }
  28. STDMETHOD(SetMenuSB)(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject)
  29. { return S_OK; }
  30. STDMETHOD(RemoveMenusSB)(HMENU hmenuShared)
  31. { return E_NOTIMPL; }
  32. STDMETHOD(SetStatusTextSB)(LPCOLESTR lpszStatusText)
  33. { return S_OK; }
  34. STDMETHOD(EnableModelessSB)(BOOL fEnable)
  35. { return S_OK; }
  36. STDMETHOD(TranslateAcceleratorSB)(LPMSG lpmsg, WORD wID)
  37. { return S_FALSE; }
  38. // *** IShellBrowser methods ***
  39. STDMETHOD(BrowseObject)(LPCITEMIDLIST pidl, UINT wFlags)
  40. { return E_FAIL; }
  41. STDMETHOD(GetViewStateStream)(DWORD grfMode, LPSTREAM *pStrm)
  42. { return E_FAIL; }
  43. STDMETHOD(GetControlWindow)(UINT id, HWND *lphwnd)
  44. { return E_NOTIMPL; }
  45. STDMETHOD(SendControlMsg)(UINT id, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *pret);
  46. STDMETHOD(QueryActiveShellView)(IShellView **ppshv);
  47. STDMETHOD(OnViewWindowActive)(IShellView *pshv)
  48. { return S_OK; }
  49. STDMETHOD(SetToolbarItems)(LPTBBUTTON lpButtons, UINT nButtons, UINT uFlags)
  50. { return S_OK; }
  51. // *** ICommDlgBrowser methods ***
  52. STDMETHOD(OnDefaultCommand)(IShellView *ppshv)
  53. { return S_OK; }
  54. STDMETHOD(OnStateChange)(IShellView *ppshv, ULONG uChange);
  55. STDMETHOD(IncludeObject)(IShellView *ppshv, LPCITEMIDLIST lpItem);
  56. // *** ICommDlgBrowser2 methods ***
  57. STDMETHOD(Notify)(IShellView *ppshv, DWORD dwNotifyType)
  58. { return S_FALSE; }
  59. STDMETHOD(GetDefaultMenuText)(IShellView *ppshv, WCHAR *pszText, INT cchMax)
  60. { return S_FALSE; }
  61. STDMETHOD(GetViewFlags)(DWORD *pdwFlags)
  62. { *pdwFlags = 0; return S_OK; }
  63. private:
  64. long _cRef;
  65. HWND _hwndParent;
  66. IShellView *_psvWeak;
  67. IUnknown *_punkSiteWeak; // not addref'd.
  68. friend class CFolderViewHost;
  69. };
  70. CViewHostBrowser::CViewHostBrowser(HWND hwndParent, IShellView *psvWeak, IUnknown *punkSiteWeak) :
  71. _cRef(1), _hwndParent(hwndParent), _psvWeak(psvWeak), _punkSiteWeak(punkSiteWeak)
  72. {
  73. // _psvWeak->AddRef(); // we hold a weak refernece to our parent, therefore don't AddRef()
  74. // _punkSiteWeak->AddRef(); // we hold a weak reference to our parent, therefore don't AddRef()!
  75. }
  76. CViewHostBrowser::~CViewHostBrowser()
  77. {
  78. // _psvWeak->Release(); // this is scoped on the lifetime of our parent
  79. // _punkSiteWeak->Release(); // we hold a weak reference to our parent, therefore don't Release()!
  80. }
  81. HRESULT CViewHostBrowser::QueryInterface(REFIID riid, void **ppvObj)
  82. {
  83. static const QITAB qit[] = {
  84. QITABENT(CViewHostBrowser, IShellBrowser), // IID_IShellBrowser
  85. QITABENT(CViewHostBrowser, ICommDlgBrowser2), // IID_ICommDlgBrowser2
  86. QITABENTMULTI(CViewHostBrowser, ICommDlgBrowser, ICommDlgBrowser2), // IID_ICommDlgBrowser
  87. QITABENT(CViewHostBrowser, IServiceProvider), // IID_IServiceProvider
  88. { 0 },
  89. };
  90. return QISearch(this, qit, riid, ppvObj);
  91. }
  92. ULONG CViewHostBrowser::AddRef()
  93. {
  94. return InterlockedIncrement(&_cRef);
  95. }
  96. ULONG CViewHostBrowser::Release()
  97. {
  98. ASSERT( 0 != _cRef );
  99. ULONG cRef = InterlockedDecrement(&_cRef);
  100. if ( 0 == cRef )
  101. {
  102. delete this;
  103. }
  104. return cRef;
  105. }
  106. // IShellBrowser
  107. HRESULT CViewHostBrowser::SendControlMsg(UINT id, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *pret)
  108. {
  109. if (pret)
  110. *pret = 0L;
  111. return S_OK;
  112. }
  113. HRESULT CViewHostBrowser::QueryActiveShellView(IShellView **ppshv)
  114. {
  115. HRESULT hr = E_NOINTERFACE;
  116. if (_psvWeak)
  117. {
  118. hr = _psvWeak->QueryInterface(IID_PPV_ARG(IShellView, ppshv));
  119. }
  120. return hr;
  121. }
  122. // ICommDlgBrowser - these are forwarded to our site object
  123. HRESULT CViewHostBrowser::OnStateChange(IShellView *ppshv, ULONG uChange)
  124. {
  125. HRESULT hr = S_OK;
  126. ICommDlgBrowser *pcdb;
  127. if (SUCCEEDED(IUnknown_QueryService(_punkSiteWeak, SID_SCommDlgBrowser, IID_PPV_ARG(ICommDlgBrowser, &pcdb))))
  128. {
  129. hr = pcdb->OnStateChange(ppshv, uChange);
  130. pcdb->Release();
  131. }
  132. return hr;
  133. }
  134. HRESULT CViewHostBrowser::IncludeObject(IShellView *ppshv, LPCITEMIDLIST lpItem)
  135. {
  136. HRESULT hr = S_OK;
  137. ICommDlgBrowser *pcdb;
  138. if (SUCCEEDED(IUnknown_QueryService(_punkSiteWeak, SID_SCommDlgBrowser, IID_PPV_ARG(ICommDlgBrowser, &pcdb))))
  139. {
  140. hr = pcdb->IncludeObject(ppshv, lpItem);
  141. pcdb->Release();
  142. }
  143. return hr;
  144. }
  145. // IServiceProvider
  146. HRESULT CViewHostBrowser::QueryService(REFGUID guidService, REFIID riid, void **ppvObj)
  147. {
  148. HRESULT hr = E_FAIL;
  149. *ppvObj = NULL;
  150. if (IsEqualGUID(guidService, SID_SCommDlgBrowser))
  151. {
  152. hr = this->QueryInterface(riid, ppvObj);
  153. }
  154. return hr;
  155. }
  156. // this is the file picker object it creates an IShellView (which for us should result in
  157. // a defview implement). from this we can then give the window to the caller and they
  158. // can place on their dialog as needed.
  159. class CFolderViewHost : public IFolderViewHost, IServiceProvider, IOleWindow, IFolderView, CObjectWithSite
  160. {
  161. public:
  162. CFolderViewHost();
  163. ~CFolderViewHost();
  164. // *** IFolderViewHost ***
  165. STDMETHODIMP Initialize(HWND hwndParent, IDataObject *pdo, RECT *prc);
  166. // *** IUnknown methods ***
  167. STDMETHOD(QueryInterface)(REFIID riid, LPVOID *ppvObj);
  168. STDMETHOD_(ULONG,AddRef)(THIS);
  169. STDMETHOD_(ULONG,Release)(THIS);
  170. // *** IOleWindow methods ***
  171. STDMETHOD(GetWindow)(HWND *lphwnd)
  172. { *lphwnd = _hwndView; return S_OK; }
  173. STDMETHOD(ContextSensitiveHelp)(BOOL fEnterMode)
  174. { return S_OK; }
  175. // IServiceProvider
  176. STDMETHODIMP QueryService(REFGUID guidService, REFIID riid, void **ppv)
  177. { return IUnknown_QueryService(_punkSite, guidService, riid, ppv); }
  178. // IFolderView
  179. STDMETHODIMP GetCurrentViewMode(UINT *pViewMode)
  180. { return _pfv->GetCurrentViewMode(pViewMode); }
  181. STDMETHODIMP SetCurrentViewMode(UINT ViewMode)
  182. { return _pfv->SetCurrentViewMode(ViewMode); }
  183. STDMETHODIMP GetFolder(REFIID ridd, void **ppv)
  184. { return _pfv->GetFolder(ridd, ppv); }
  185. STDMETHODIMP Item(int iItemIndex, LPITEMIDLIST *ppidl)
  186. { return _pfv->Item(iItemIndex, ppidl); }
  187. STDMETHODIMP ItemCount(UINT uFlags, int *pcItems)
  188. { return _pfv->ItemCount(uFlags, pcItems); }
  189. STDMETHODIMP Items(UINT uFlags, REFIID riid, void **ppv)
  190. { return _pfv->Items(uFlags, riid, ppv); }
  191. STDMETHODIMP GetSelectionMarkedItem(int *piItem)
  192. { return _pfv->GetSelectionMarkedItem(piItem); }
  193. STDMETHODIMP GetFocusedItem(int *piItem)
  194. { return _pfv->GetFocusedItem(piItem); }
  195. STDMETHODIMP GetItemPosition(LPCITEMIDLIST pidl, POINT* ppt)
  196. { return _pfv->GetItemPosition(pidl, ppt); }
  197. STDMETHODIMP GetSpacing(POINT* ppt)
  198. { return _pfv->GetSpacing(ppt); }
  199. STDMETHODIMP GetDefaultSpacing(POINT* ppt)
  200. { return _pfv->GetDefaultSpacing(ppt); }
  201. STDMETHODIMP GetAutoArrange()
  202. { return _pfv->GetAutoArrange(); }
  203. STDMETHODIMP SelectItem(int iItem, DWORD dwFlags)
  204. { return _pfv->SelectItem(iItem, dwFlags); }
  205. STDMETHODIMP SelectAndPositionItems(UINT cidl, LPCITEMIDLIST* apidl, POINT* apt, DWORD dwFlags)
  206. { return _pfv->SelectAndPositionItems(cidl, apidl, apt, dwFlags); }
  207. private:
  208. long _cRef;
  209. IFolderView *_pfv; // IFolderView
  210. HWND _hwndView;
  211. };
  212. CFolderViewHost::CFolderViewHost() :
  213. _cRef(1)
  214. {
  215. }
  216. CFolderViewHost::~CFolderViewHost()
  217. {
  218. if (_pfv)
  219. _pfv->Release();
  220. }
  221. HRESULT CFolderViewHost::QueryInterface(REFIID riid, void **ppvObj)
  222. {
  223. static const QITAB qit[] = {
  224. QITABENT(CFolderViewHost, IFolderViewHost), // IID_IFolderViewHost
  225. QITABENT(CFolderViewHost, IOleWindow), // IID_IOleWindow
  226. QITABENT(CFolderViewHost, IFolderView), // IID_IFolderView
  227. QITABENT(CFolderViewHost, IServiceProvider), // IID_IServiceProvider
  228. QITABENT(CFolderViewHost, IObjectWithSite), // IID_IObjectWithSite
  229. { 0 },
  230. };
  231. return QISearch(this, qit, riid, ppvObj);
  232. }
  233. ULONG CFolderViewHost::AddRef()
  234. {
  235. return InterlockedIncrement(&_cRef);
  236. }
  237. ULONG CFolderViewHost::Release()
  238. {
  239. ASSERT( 0 != _cRef );
  240. ULONG cRef = InterlockedDecrement(&_cRef);
  241. if ( 0 == cRef )
  242. {
  243. delete this;
  244. }
  245. return cRef;
  246. }
  247. // the initialize method handles the creation of the view object from the.
  248. HRESULT CFolderViewHost::Initialize(HWND hwndParent, IDataObject *pdo, RECT *prc)
  249. {
  250. // first we perform a namespace walk, this will retrieve our selection from the view
  251. // using this we can then create the view object.
  252. INamespaceWalk *pnsw;
  253. HRESULT hr = CoCreateInstance(CLSID_NamespaceWalker, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(INamespaceWalk, &pnsw));
  254. if (SUCCEEDED(hr))
  255. {
  256. LPITEMIDLIST *aItems = NULL;
  257. UINT cItems = 0;
  258. hr = pnsw->Walk(pdo, NSWF_NONE_IMPLIES_ALL, 0, NULL);
  259. if (SUCCEEDED(hr))
  260. {
  261. IShellFolder *psf = NULL;
  262. hr = pnsw->GetIDArrayResult(&cItems, &aItems);
  263. if (S_OK == hr)
  264. {
  265. hr = SHBindToIDListParent(aItems[0], IID_PPV_ARG(IShellFolder, &psf), NULL);
  266. }
  267. else if (S_FALSE == hr)
  268. {
  269. hr = E_FAIL; // fail unless we perform the bind.
  270. STGMEDIUM medium;
  271. LPIDA pida = DataObj_GetHIDA(pdo, &medium);
  272. if (pida)
  273. {
  274. if (pida->cidl == 1)
  275. {
  276. LPITEMIDLIST pidl = IDA_ILClone(pida, 0);
  277. if (pidl)
  278. {
  279. hr = SHBindToObjectEx(NULL, pidl, NULL, IID_PPV_ARG(IShellFolder, &psf));
  280. ILFree(pidl);
  281. }
  282. }
  283. HIDA_ReleaseStgMedium(pida, &medium);
  284. }
  285. }
  286. else
  287. {
  288. hr = E_FAIL;
  289. }
  290. if (SUCCEEDED(hr))
  291. {
  292. IShellView *psv;
  293. hr = psf->CreateViewObject(hwndParent, IID_PPV_ARG(IShellView, &psv));
  294. if (SUCCEEDED(hr))
  295. {
  296. CViewHostBrowser *pvhb = new CViewHostBrowser(hwndParent, psv, SAFECAST(this, IServiceProvider*));
  297. if (pvhb)
  298. {
  299. hr = psv->QueryInterface(IID_PPV_ARG(IFolderView, &_pfv));
  300. if (SUCCEEDED(hr))
  301. {
  302. FOLDERSETTINGS fs = {0};
  303. fs.ViewMode = FVM_THUMBNAIL;
  304. fs.fFlags = FWF_AUTOARRANGE|FWF_NOWEBVIEW|FWF_HIDEFILENAMES|FWF_CHECKSELECT;
  305. IFolderView *pfv;
  306. if (SUCCEEDED(IUnknown_QueryService(_punkSite, SID_SFolderView, IID_PPV_ARG(IFolderView, &pfv))))
  307. {
  308. pfv->GetCurrentViewMode(&fs.ViewMode);
  309. pfv->Release();
  310. }
  311. hr = psv->CreateViewWindow(NULL, &fs, pvhb, prc, &_hwndView);
  312. if (SUCCEEDED(hr))
  313. {
  314. hr = psv->UIActivate(SVUIA_INPLACEACTIVATE);
  315. }
  316. }
  317. pvhb->Release();
  318. }
  319. else
  320. {
  321. hr = E_OUTOFMEMORY;
  322. }
  323. psv->Release();
  324. }
  325. for (int i = 0; SUCCEEDED(hr) && (i != cItems); i++)
  326. {
  327. LPCITEMIDLIST pidlChild = ILFindLastID(aItems[i]);
  328. hr = _pfv->SelectAndPositionItems(1, &pidlChild, NULL, SVSI_CHECK);
  329. }
  330. psf->Release();
  331. }
  332. FreeIDListArray(aItems, cItems);
  333. }
  334. pnsw->Release();
  335. }
  336. return hr;
  337. }
  338. STDAPI CFolderViewHost_CreateInstance(IUnknown *punkOut, REFIID riid, void **ppv)
  339. {
  340. CFolderViewHost *pfp = new CFolderViewHost();
  341. if (!pfp)
  342. return E_OUTOFMEMORY;
  343. HRESULT hr = pfp->QueryInterface(riid, ppv);
  344. pfp->Release();
  345. return hr;
  346. }