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.

361 lines
9.6 KiB

  1. #include "shellprv.h"
  2. //#include "mkhelp.h"
  3. #include "urlmon.h"
  4. #include "ids.h"
  5. class CBSCLocalCopyHelper : public IBindStatusCallback,
  6. public IAuthenticate
  7. {
  8. public:
  9. CBSCLocalCopyHelper(IBindCtx *pbc, BOOL fWebfolders);
  10. // IUnknown methods
  11. STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
  12. STDMETHODIMP_(ULONG) AddRef () ;
  13. STDMETHODIMP_(ULONG) Release ();
  14. // *** IAuthenticate ***
  15. virtual STDMETHODIMP Authenticate(
  16. HWND *phwnd,
  17. LPWSTR *pszUsername,
  18. LPWSTR *pszPassword);
  19. // *** IBindStatusCallback ***
  20. virtual STDMETHODIMP OnStartBinding(
  21. /* [in] */ DWORD grfBSCOption,
  22. /* [in] */ IBinding *pib);
  23. virtual STDMETHODIMP GetPriority(
  24. /* [out] */ LONG *pnPriority);
  25. virtual STDMETHODIMP OnLowResource(
  26. /* [in] */ DWORD reserved);
  27. virtual STDMETHODIMP OnProgress(
  28. /* [in] */ ULONG ulProgress,
  29. /* [in] */ ULONG ulProgressMax,
  30. /* [in] */ ULONG ulStatusCode,
  31. /* [in] */ LPCWSTR szStatusText);
  32. virtual STDMETHODIMP OnStopBinding(
  33. /* [in] */ HRESULT hresult,
  34. /* [in] */ LPCWSTR szError);
  35. virtual STDMETHODIMP GetBindInfo(
  36. /* [out] */ DWORD *grfBINDINFOF,
  37. /* [unique][out][in] */ BINDINFO *pbindinfo);
  38. virtual STDMETHODIMP OnDataAvailable(
  39. /* [in] */ DWORD grfBSCF,
  40. /* [in] */ DWORD dwSize,
  41. /* [in] */ FORMATETC *pformatetc,
  42. /* [in] */ STGMEDIUM *pstgmed);
  43. virtual STDMETHODIMP OnObjectAvailable(
  44. /* [in] */ REFIID riid,
  45. /* [iid_is][in] */ IUnknown *punk);
  46. protected:
  47. ~CBSCLocalCopyHelper();
  48. long _cRef;
  49. IBinding *_pib;
  50. IProgressDialog *_pdlg;
  51. HWND _hwnd;
  52. BOOL _fRosebudMagic;
  53. };
  54. CBSCLocalCopyHelper::CBSCLocalCopyHelper(IBindCtx *pbc, BOOL fWebfolders)
  55. : _cRef(1) , _fRosebudMagic(fWebfolders)
  56. {
  57. // we should use the pbc to
  58. // get our simpler uiprogress
  59. // interface. but for now
  60. // we will do nothing
  61. }
  62. CBSCLocalCopyHelper::~CBSCLocalCopyHelper()
  63. {
  64. ATOMICRELEASE(_pib);
  65. ATOMICRELEASE(_pdlg);
  66. // NOTE dont need to release _ppstm because we dont own it
  67. }
  68. STDMETHODIMP CBSCLocalCopyHelper::QueryInterface(REFIID riid, void **ppv)
  69. {
  70. static const QITAB qit[] =
  71. {
  72. QITABENT(CBSCLocalCopyHelper, IBindStatusCallback),
  73. QITABENT(CBSCLocalCopyHelper, IAuthenticate),
  74. { 0 },
  75. };
  76. return QISearch(this, qit, riid, ppv);
  77. }
  78. STDMETHODIMP_(ULONG) CBSCLocalCopyHelper::AddRef()
  79. {
  80. return InterlockedIncrement(&_cRef);
  81. }
  82. STDMETHODIMP_(ULONG) CBSCLocalCopyHelper::Release()
  83. {
  84. ASSERT( 0 != _cRef );
  85. ULONG cRef = InterlockedDecrement(&_cRef);
  86. if ( 0 == cRef )
  87. {
  88. delete this;
  89. }
  90. return cRef;
  91. }
  92. STDMETHODIMP CBSCLocalCopyHelper::Authenticate(HWND *phwnd, LPWSTR *ppszUsername, LPWSTR *ppszPassword)
  93. {
  94. if (ppszUsername)
  95. *ppszUsername = NULL;
  96. if (ppszPassword)
  97. *ppszPassword = NULL;
  98. *phwnd = GetLastActivePopup(_hwnd);
  99. return *phwnd ? S_OK : E_FAIL;
  100. }
  101. STDMETHODIMP CBSCLocalCopyHelper::OnStartBinding(DWORD dwReserved,IBinding *pib)
  102. {
  103. ATOMICRELEASE(_pib);
  104. if (pib)
  105. {
  106. pib->AddRef();
  107. _pib = pib;
  108. }
  109. if (_pdlg)
  110. {
  111. WCHAR sz[MAX_PATH];
  112. // we are starting out here
  113. _pdlg->Timer(PDTIMER_RESET, NULL);
  114. _pdlg->SetProgress(0, 0);
  115. LoadStringW(HINST_THISDLL, IDS_ACCESSINGMONIKER, sz, ARRAYSIZE(sz));
  116. _pdlg->SetLine(1, sz, FALSE, NULL);
  117. }
  118. return S_OK;
  119. }
  120. STDMETHODIMP CBSCLocalCopyHelper::GetPriority(LONG *pnPriority)
  121. {
  122. if (pnPriority)
  123. {
  124. // we are a blocking UI thread
  125. *pnPriority = THREAD_PRIORITY_ABOVE_NORMAL;
  126. }
  127. return S_OK;
  128. }
  129. STDMETHODIMP CBSCLocalCopyHelper::OnLowResource(DWORD reserved)
  130. {
  131. return S_OK;
  132. }
  133. STDMETHODIMP CBSCLocalCopyHelper::OnProgress(ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR pszStatusText)
  134. {
  135. HRESULT hr = S_OK;
  136. // handle UI udpates
  137. if (_pdlg)
  138. {
  139. if (_pdlg->HasUserCancelled())
  140. {
  141. hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
  142. }
  143. if (ulProgressMax)
  144. {
  145. _pdlg->SetProgress(ulProgress, ulProgressMax);
  146. }
  147. if (pszStatusText)
  148. _pdlg->SetLine(1, pszStatusText, FALSE, NULL);
  149. }
  150. return hr;
  151. }
  152. STDMETHODIMP CBSCLocalCopyHelper::OnStopBinding(HRESULT hresult, LPCWSTR szError)
  153. {
  154. // handle something
  155. ATOMICRELEASE(_pib);
  156. return S_OK;
  157. }
  158. STDMETHODIMP CBSCLocalCopyHelper::GetBindInfo(DWORD *grfBINDINFOF, BINDINFO *pbindinfo)
  159. {
  160. if (_fRosebudMagic && pbindinfo)
  161. {
  162. // this is the magic number that says its ok for URLMON to use DAV/rosebud/webfolders.
  163. // we dont need this during download and in fact if we
  164. // set it, we may not be able to retrieve the resource.
  165. // we coudl do some kind of check on the moniker to verify the clsid
  166. // comes from URLMON. right now this is how office handles
  167. // all of its requests so we do too.
  168. pbindinfo->dwOptions = 1;
  169. }
  170. if (grfBINDINFOF)
  171. {
  172. *grfBINDINFOF = BINDF_GETFROMCACHE_IF_NET_FAIL | BINDF_GETNEWESTVERSION;
  173. }
  174. return S_OK;
  175. }
  176. STDMETHODIMP CBSCLocalCopyHelper::OnDataAvailable(DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed)
  177. {
  178. return S_OK;
  179. }
  180. STDMETHODIMP CBSCLocalCopyHelper::OnObjectAvailable(REFIID riid, IUnknown *punk)
  181. {
  182. return E_UNEXPECTED;
  183. }
  184. HRESULT _CreateUrlmonBindCtx(IBindCtx *pbcIn, BOOL fWebfolders, IBindCtx **ppbc, IBindStatusCallback **ppbsc)
  185. {
  186. IBindCtx *pbc;
  187. HRESULT hr = CreateBindCtx(0, &pbc);
  188. *ppbc = NULL;
  189. *ppbsc = NULL;
  190. if (SUCCEEDED(hr))
  191. {
  192. IBindStatusCallback *pbsc = (IBindStatusCallback *) new CBSCLocalCopyHelper(pbcIn, fWebfolders);
  193. if (pbsc)
  194. {
  195. // maybe we should attach it to the existing
  196. // pbc, but for now we will create a new one.
  197. hr = RegisterBindStatusCallback(pbc, pbsc, NULL, 0);
  198. if (SUCCEEDED(hr))
  199. {
  200. BIND_OPTS bo = {0};
  201. bo.cbStruct = SIZEOF(bo);
  202. bo.grfMode = BindCtx_GetMode(pbcIn, STGM_READ);
  203. //
  204. // on webfolders, (and possibly other URLMON
  205. // monikers), if you are attempting to create a
  206. // writable stream you also need to pass STGM_CREATE
  207. // even if the file you are writing to already exists.
  208. //
  209. if (bo.grfMode & (STGM_WRITE | STGM_READWRITE))
  210. bo.grfMode |= STGM_CREATE;
  211. hr = pbc->SetBindOptions(&bo);
  212. }
  213. }
  214. else
  215. hr = E_OUTOFMEMORY;
  216. if (SUCCEEDED(hr))
  217. {
  218. *ppbc = pbc;
  219. *ppbsc = pbsc;
  220. }
  221. else
  222. {
  223. pbc->Release();
  224. if (pbsc)
  225. pbsc->Release();
  226. }
  227. }
  228. return hr;
  229. }
  230. static const GUID CLSID_WEBFOLDERS = // {BDEADF00-C265-11D0-BCED-00A0C90AB50F}
  231. { 0xBDEADF00, 0xC265, 0x11D0, { 0xBC, 0xED, 0x00, 0xA0, 0xC9, 0x0A, 0xB5, 0x0F} };
  232. BOOL _IsWebfolders(IShellItem *psi)
  233. {
  234. BOOL fRet = FALSE;
  235. IShellItem *psiParent;
  236. HRESULT hr = psi->GetParent(&psiParent);
  237. if (SUCCEEDED(hr))
  238. {
  239. IShellFolder *psf;
  240. SFGAOF flags = SFGAO_LINK;
  241. if (SUCCEEDED(psiParent->GetAttributes(flags, &flags))
  242. && (flags & SFGAO_LINK))
  243. {
  244. // this is a folder shortcut that needs derefing
  245. IShellItem *psiTarget;
  246. hr = psiParent->BindToHandler(NULL, BHID_LinkTargetItem, IID_PPV_ARG(IShellItem, &psiTarget));
  247. if (SUCCEEDED(hr))
  248. {
  249. // switcheroo
  250. psiParent->Release();
  251. psiParent = psiTarget;
  252. }
  253. }
  254. if (SUCCEEDED(hr))
  255. {
  256. hr = psiParent->BindToHandler(NULL, BHID_SFObject, IID_PPV_ARG(IShellFolder, &psf));
  257. if (SUCCEEDED(hr))
  258. {
  259. CLSID clsid;
  260. if (SUCCEEDED(IUnknown_GetClassID(psf, &clsid)))
  261. fRet = IsEqualGUID(clsid, CLSID_WEBFOLDERS);
  262. psf->Release();
  263. }
  264. }
  265. psiParent->Release();
  266. }
  267. return fRet;
  268. }
  269. HRESULT _CreateStorageHelper(IShellItem *psi, IBindCtx *pbc, REFGUID rbhid, REFIID riid, void **ppv)
  270. {
  271. IMoniker *pmk;
  272. HRESULT hr = psi->BindToHandler(pbc, BHID_SFObject, IID_PPV_ARG(IMoniker, &pmk));
  273. if (SUCCEEDED(hr))
  274. {
  275. IBindCtx *pbcMk;
  276. IBindStatusCallback *pbsc;
  277. hr = _CreateUrlmonBindCtx(pbc, _IsWebfolders(psi), &pbcMk, &pbsc);
  278. if (SUCCEEDED(hr))
  279. {
  280. hr = pmk->BindToStorage(pbcMk, NULL, riid, ppv);
  281. // urlmon + ftp url can cause this. remove when 3140245 is fixed
  282. if (SUCCEEDED(hr) && NULL == *ppv)
  283. hr = E_FAIL;
  284. RevokeBindStatusCallback(pbcMk, pbsc);
  285. pbcMk->Release();
  286. pbsc->Release();
  287. }
  288. }
  289. return hr;
  290. }
  291. EXTERN_C WINSHELLAPI HRESULT STDAPICALLTYPE SHCopyMonikerToTemp(IMoniker *pmk, LPCWSTR pszIn, LPWSTR pszOut, int cchOut)
  292. {
  293. // REMOVE this as soon as ComDlg32 is updated
  294. return E_NOTIMPL;
  295. }