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.

666 lines
20 KiB

  1. #include "shellprv.h"
  2. #include <regstr.h>
  3. #include <shellp.h>
  4. #include "ole2dup.h"
  5. #include "ids.h"
  6. #include "defview.h"
  7. #include "lvutil.h"
  8. #include "idlcomm.h"
  9. #include "filetbl.h"
  10. #include "undo.h"
  11. #include "vdate.h"
  12. #include "cnctnpt.h"
  13. #include "mshtml.h"
  14. #include <sfview.h>
  15. #include "defviewp.h"
  16. #include "shellp.h"
  17. #define LISTVIEW_PROP TEXT("CombView_listview_subclass")
  18. #define ISMOUSEDOWN(msg) ((msg) == WM_LBUTTONDOWN || (msg) == WM_RBUTTONDOWN || (msg) == WM_MBUTTONDOWN)
  19. #define HWNDLISTVIEW (g_pdsvlvp->pdsv->_hwndListview)
  20. #define COMBVIEW_SUBCLASS_ID 42
  21. typedef struct
  22. {
  23. CDefView *pdsv;
  24. BOOL fInPaint;
  25. HHOOK hHookMouse;
  26. HHOOK hHookGetMsg;
  27. } DVLVPROP;
  28. //
  29. // We need this global (g_pdsvlvp) for the mouse hook we need to implement the combined
  30. // view. Since we only have one combined view at this point it is sufficient to have
  31. // a single global, but if we end up with more than one combined view then
  32. // there needs to be some additional code added so the hook(s) can figure out
  33. // which combined view(s) it is associated with.
  34. //
  35. DVLVPROP * g_pdsvlvp = NULL;
  36. const LPCTSTR c_rgElements[] = {
  37. TEXT("A"),
  38. TEXT("ANCHOR"), // ???
  39. TEXT("PLUGINS"), // ???
  40. TEXT("APPLET"),
  41. TEXT("EMBED"),
  42. TEXT("FORM"),
  43. TEXT("IFRAME"),
  44. TEXT("BUTTON"),
  45. TEXT("INPUT"),
  46. TEXT("OBJECT")
  47. };
  48. BOOL CombView_EnableAnimations(BOOL fEnable);
  49. // Returns the first sibling window of the passed in window
  50. HWND GetSpecialSibling(HWND hwnd)
  51. {
  52. HWND hwndT = GetWindow(hwnd, GW_HWNDFIRST);
  53. while (hwnd == hwndT)
  54. hwndT = GetWindow(hwndT, GW_HWNDNEXT);
  55. return hwndT;
  56. }
  57. LRESULT CALLBACK CombView_LV_SubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam,
  58. LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
  59. {
  60. DVLVPROP *pdsvlvp = (DVLVPROP *)dwRefData;
  61. // 2000-07-11 vtan: First check g_pdsvlvp for NULL. If this is NULL then the dwRefData
  62. // has already been released in EnableCombinedView. There is only one DVLVPROP stored
  63. // in the entire process in g_pdsvlvp. This seems like a problem. lamadio should fix
  64. // this properly in the future.
  65. if ((g_pdsvlvp != NULL) &&
  66. pdsvlvp &&
  67. pdsvlvp->pdsv->_fCombinedView &&
  68. !pdsvlvp->fInPaint &&
  69. uMsg == WM_PAINT)
  70. {
  71. // This code works well for general painting, like minimizing a window or
  72. // or surfacing the desktop. However, it doesn't help the drag full windows
  73. // scenario very much.
  74. HRGN hrgn, hrgn2;
  75. RECT rc;
  76. HWND hwndT = GetSpecialSibling(hwnd);
  77. // Turn on animations!
  78. CombView_EnableAnimations(TRUE);
  79. if (hwndT && (hrgn = CreateRectRgn(0, 0, 0, 0)))
  80. {
  81. if (hrgn2 = CreateRectRgn(0, 0, 0, 0))
  82. {
  83. pdsvlvp->fInPaint = TRUE;
  84. if (!GetClassLongPtr(hwndT, GCLP_HBRBACKGROUND))
  85. SetClassLongPtr(hwndT, GCLP_HBRBACKGROUND, (LPARAM)GetStockObject(HOLLOW_BRUSH));
  86. if (GetUpdateRect(hwndT, &rc, FALSE))
  87. {
  88. RECT rcLV = rc;
  89. MapWindowPoints(hwndT, hwnd, (LPPOINT)&rcLV, 2);
  90. SetRectRgn(hrgn2, rcLV.left, rcLV.top, rcLV.right, rcLV.bottom);
  91. GetWindowRgn(hwnd, hrgn);
  92. CombineRgn(hrgn2, hrgn, hrgn2, RGN_DIFF);
  93. SetWindowRgn(hwnd, hrgn2, FALSE);
  94. InvalidateRect(hwndT, &rc, FALSE);
  95. UpdateWindow(hwndT);
  96. SetWindowRgn(hwnd, hrgn, FALSE);
  97. InvalidateRect(hwnd, &rcLV, FALSE);
  98. }
  99. else
  100. {
  101. DeleteObject(hrgn);
  102. DeleteObject(hrgn2);
  103. }
  104. pdsvlvp->fInPaint = FALSE;
  105. }
  106. else
  107. {
  108. DeleteObject(hrgn);
  109. }
  110. }
  111. }
  112. return DefSubclassProc(hwnd, uMsg, wParam, lParam);
  113. }
  114. // We need to set capture while we are stealing the mouse so that the
  115. // window manager won't send WM_SETCURSOR messages to the wrong window.
  116. // This function will also, as a side effect, send the WM_SETCURSOR to the
  117. // listview so that it will set the hand cursor when it needs to.
  118. void StealMouse(DVLVPROP * pdvlvp, BOOL fSteal, UINT msg)
  119. {
  120. HWND hwndCapture = GetCapture();
  121. if (fSteal && (hwndCapture == NULL || hwndCapture == HWNDLISTVIEW))
  122. {
  123. // We need to set capture so that the window manager will not
  124. // try to send the w_setcursor message to the wrong window, and we
  125. // send it here ourself to the listview.
  126. SetCapture(HWNDLISTVIEW);
  127. SendMessage(HWNDLISTVIEW, WM_SETCURSOR, (WPARAM)HWNDLISTVIEW,
  128. MAKELPARAM(HTCLIENT, LOWORD(msg)));
  129. }
  130. else
  131. {
  132. // If the listview still has capture release it now
  133. if (HWNDLISTVIEW == hwndCapture)
  134. ReleaseCapture();
  135. }
  136. }
  137. LRESULT CALLBACK CombView_GetMsgHook(int nCode, WPARAM wParam, LPARAM lParam)
  138. {
  139. #define LPMSG ((LPMSG)lParam)
  140. HHOOK hHookNext = NULL;
  141. if (g_pdsvlvp)
  142. {
  143. if (LPMSG->message >= WM_MOUSEFIRST && LPMSG->message <= WM_MOUSELAST)
  144. {
  145. POINT pt;
  146. pt.x = GET_X_LPARAM(LPMSG->lParam);
  147. pt.y = GET_Y_LPARAM(LPMSG->lParam);
  148. MapWindowPoints(LPMSG->hwnd, HWNDLISTVIEW, &pt, 1);
  149. int iHit = g_pdsvlvp->pdsv->_HitTest(&pt);
  150. // Unhook our hook when all of the mouse buttons are up and we're not over
  151. // an item in the listview
  152. if (GetKeyState(VK_LBUTTON) >= 0 &&
  153. GetKeyState(VK_RBUTTON) >= 0 &&
  154. GetKeyState(VK_MBUTTON) >= 0 &&
  155. iHit == -1)
  156. {
  157. UnhookWindowsHookEx(g_pdsvlvp->hHookGetMsg);
  158. g_pdsvlvp->hHookGetMsg = NULL;
  159. }
  160. else
  161. {
  162. hHookNext = g_pdsvlvp->hHookGetMsg;
  163. }
  164. if (IsChildOrSelf(GetSpecialSibling(HWNDLISTVIEW), LPMSG->hwnd) == S_OK)
  165. {
  166. // If we have grabbed the mouse, give it to the listview
  167. LPMSG->hwnd = HWNDLISTVIEW;
  168. LPMSG->lParam = MAKELPARAM(LOWORD(pt.x), LOWORD(pt.y));
  169. }
  170. }
  171. else
  172. {
  173. hHookNext = g_pdsvlvp->hHookGetMsg;
  174. }
  175. // If we've just unhooked, or the hover is coming through to the listview and
  176. // no mouse button is down then clear our ownership of the mouse
  177. #define MK_BUTTON (MK_LBUTTON | MK_RBUTTON | MK_MBUTTON)
  178. if (!hHookNext ||
  179. // We need to special case the WM_MOUSEHOVER here so that the listview
  180. // is able to implement hover select. If we have capture set when the
  181. // hover select message goes through then it will ignore the message, so
  182. // clear the capture now.
  183. (LPMSG->message == WM_MOUSEHOVER && LPMSG->hwnd == HWNDLISTVIEW && !(LPMSG->wParam & MK_BUTTON)))
  184. StealMouse(g_pdsvlvp, FALSE, 0);
  185. }
  186. if (hHookNext)
  187. CallNextHookEx(hHookNext, nCode, wParam, lParam);
  188. return 0;
  189. #undef LPMSG
  190. }
  191. BOOL DoesElementNeedMouse (LPTSTR psz)
  192. {
  193. for (int i = 0; i < ARRAYSIZE(c_rgElements); i++)
  194. {
  195. if (lstrcmpi(c_rgElements[i], psz) == 0)
  196. return TRUE;
  197. }
  198. return FALSE;
  199. }
  200. BOOL ShouldStealMouseClick(POINT * ppt, DVLVPROP * pdsvlvp)
  201. {
  202. IHTMLDocument2 *pihtmldoc2;
  203. IHTMLElement *pielem;
  204. HRESULT hr = E_FAIL;
  205. if (SUCCEEDED(pdsvlvp->pdsv->GetItemObject(SVGIO_BACKGROUND, IID_IHTMLDocument2, (void **)&pihtmldoc2)))
  206. {
  207. // Work around for Trident issue -
  208. // elementFromPoint is returning success here even though pielem is
  209. // still NULL.
  210. if (SUCCEEDED(pihtmldoc2->elementFromPoint(ppt->x, ppt->y, &pielem)) && pielem)
  211. {
  212. IHTMLElement *pielemT;
  213. do {
  214. BSTR bstr = NULL;
  215. TCHAR sz[MAX_PATH];
  216. pielem->get_tagName(&bstr);
  217. SHUnicodeToTChar(bstr, sz, ARRAYSIZE(sz));
  218. SysFreeString(bstr);
  219. if (DoesElementNeedMouse(sz))
  220. {
  221. hr = E_FAIL;
  222. }
  223. else
  224. {
  225. if (SUCCEEDED(hr = pielem->get_parentElement(&pielemT)))
  226. {
  227. pielem->Release();
  228. pielem = pielemT;
  229. }
  230. else
  231. {
  232. hr = S_OK;
  233. pielem->Release();
  234. pielem = NULL;
  235. }
  236. }
  237. } while (SUCCEEDED(hr) && pielem);
  238. if (pielem)
  239. pielem->Release();
  240. }
  241. pihtmldoc2->Release();
  242. }
  243. return SUCCEEDED(hr);
  244. }
  245. LRESULT CALLBACK CombView_MouseHook(int nCode, WPARAM wParam, LPARAM lParam)
  246. {
  247. #define PMHS ((MOUSEHOOKSTRUCT *)lParam)
  248. if ((nCode == HC_ACTION) && g_pdsvlvp && (PMHS->hwnd != HWNDLISTVIEW) && IsWindowVisible(HWNDLISTVIEW))
  249. {
  250. // If it isn't over the listview and the button is going down or we're
  251. // moving over an area that would hit a listview icon then
  252. // we need to start hooking mouse events. Install the GetMessage hook
  253. // so that we can do what we need to do.
  254. HWND hwndParent = GetSpecialSibling(HWNDLISTVIEW);
  255. POINT ptLV = PMHS->pt;
  256. HWND hwndHittest = WindowFromPoint(PMHS->pt);
  257. ScreenToClient(HWNDLISTVIEW, &ptLV);
  258. int iHit = g_pdsvlvp->pdsv->_HitTest(&ptLV);
  259. ScreenToClient(hwndParent, &(PMHS->pt));
  260. BOOL fStealMouse = (ISMOUSEDOWN(wParam) && ShouldStealMouseClick(&(PMHS->pt), g_pdsvlvp)) ||
  261. (!GetCapture() && (iHit != -1) && (!hwndHittest || (hwndHittest == HWNDLISTVIEW)));
  262. if (!g_pdsvlvp->hHookGetMsg)
  263. {
  264. if (hwndHittest && (IsChildOrSelf(hwndParent, hwndHittest) == S_OK))
  265. {
  266. if (fStealMouse)
  267. {
  268. // Note: We have to steal the mouse at this point and use the
  269. // GetMessage hook to redirect the mouse messages to our listview
  270. // window. If we do something different like swallow the message here
  271. // and then PostMessage faked up events to the listview then all
  272. // of the hover select functionality will break because the system
  273. // won't detect the mouse as being over the listview.
  274. StealMouse(g_pdsvlvp, TRUE, (UINT) wParam);
  275. g_pdsvlvp->hHookGetMsg = SetWindowsHookEx(WH_GETMESSAGE, CombView_GetMsgHook,
  276. NULL, GetCurrentThreadId());
  277. }
  278. }
  279. }
  280. else
  281. {
  282. if (fStealMouse)
  283. StealMouse(g_pdsvlvp, TRUE, (UINT) wParam);
  284. else
  285. SendMessage(HWNDLISTVIEW, WM_SETCURSOR, (WPARAM)HWNDLISTVIEW, MAKELPARAM(HTCLIENT, LOWORD((UINT) wParam)));
  286. }
  287. }
  288. if (g_pdsvlvp)
  289. return CallNextHookEx(g_pdsvlvp->hHookMouse, nCode, wParam, lParam);
  290. else
  291. return 0;
  292. #undef PMHS
  293. }
  294. /*
  295. * This is the main entry point where a defview can be turned into a combined
  296. * view. The effect of a combined view is to layer an extended view under
  297. * the listview icons (via a regional listview) of a normal defview.
  298. *
  299. * Warnings:
  300. * 1) This is currently only used by the "Active Desktop", it is optimized
  301. * to only support one instance. Multiple combined views are not currently supported.
  302. * 2) Disabling the combined view doesn't completely unhook itself from the defview
  303. */
  304. void EnableCombinedView(CDefView *pdsv, BOOL fEnable)
  305. {
  306. DVLVPROP * pdsvlvp = g_pdsvlvp;
  307. if (pdsvlvp)
  308. {
  309. if (!fEnable)
  310. {
  311. // Unhook ourselves
  312. UnhookWindowsHookEx(pdsvlvp->hHookMouse);
  313. if (pdsvlvp->hHookGetMsg)
  314. {
  315. UnhookWindowsHookEx(pdsvlvp->hHookGetMsg);
  316. StealMouse(pdsvlvp, FALSE, 0);
  317. }
  318. g_pdsvlvp = NULL;
  319. RemoveWindowSubclass(pdsv->_hwndListview, CombView_LV_SubclassProc, COMBVIEW_SUBCLASS_ID);
  320. LocalFree((HLOCAL)pdsvlvp);
  321. }
  322. }
  323. else
  324. {
  325. if (fEnable)
  326. {
  327. pdsvlvp = (DVLVPROP *)LocalAlloc(LPTR, sizeof(DVLVPROP));
  328. if (pdsvlvp)
  329. {
  330. // We are only expecting one combined view
  331. ASSERT(g_pdsvlvp == NULL);
  332. // Get ourself hooked in
  333. pdsvlvp->pdsv = pdsv;
  334. SetWindowSubclass(pdsv->_hwndListview, CombView_LV_SubclassProc, COMBVIEW_SUBCLASS_ID, (DWORD_PTR)pdsvlvp);
  335. pdsvlvp->hHookMouse = SetWindowsHookEx(WH_MOUSE, CombView_MouseHook, NULL, GetCurrentThreadId());
  336. g_pdsvlvp = pdsvlvp;
  337. }
  338. }
  339. }
  340. }
  341. /*
  342. * This function is used to optimize the combined view ("Active Desktop") by turning
  343. * off any animated html elements or embeddings when it is completely obscured.
  344. *
  345. * Note that we always honor enabling animations if they aren't already enabled.
  346. * To make the client code easier though we only disable animations if we know
  347. * the desktop is obscured.
  348. *
  349. * Returns: The state of animation after the call
  350. */
  351. BOOL CombView_EnableAnimations(BOOL fEnable)
  352. {
  353. static BOOL fEnabled = TRUE;
  354. if ((fEnable != fEnabled) && g_pdsvlvp)
  355. {
  356. IOleCommandTarget* pct;
  357. BOOL fChangeAnimationState = fEnable;
  358. if (!fEnable)
  359. {
  360. HDC hdc;
  361. RECT rc;
  362. HWND hwnd;
  363. if ((hwnd = GetSpecialSibling(HWNDLISTVIEW)) && (hdc = GetDC(hwnd)))
  364. {
  365. fChangeAnimationState = (GetClipBox(hdc, &rc) == NULLREGION);
  366. ReleaseDC(hwnd, hdc);
  367. }
  368. }
  369. if (fChangeAnimationState &&
  370. SUCCEEDED(g_pdsvlvp->pdsv->_psb->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &pct))))
  371. {
  372. VARIANT var = { 0 };
  373. TraceMsg(DM_TRACE, "Active Desktop: Animation state is changing:%d", fEnable);
  374. var.vt = VT_I4;
  375. var.lVal = fEnable;
  376. pct->Exec(NULL, OLECMDID_ENABLE_INTERACTION, OLECMDEXECOPT_DONTPROMPTUSER, &var, NULL);
  377. pct->Release();
  378. fEnabled = fEnable;
  379. }
  380. }
  381. return fEnabled;
  382. }
  383. // IDocHostUIHandler
  384. // This is implemented by the combined view so that we can support various
  385. // Win95 desktop functionality in a compatible way in the extended view.
  386. // Some examples include picking off context menu invocations, configuring the
  387. // host to display the way we want it too, and modifying drag/drop behavior.
  388. HRESULT CSFVSite::ShowContextMenu(DWORD dwID, POINT *ppt, IUnknown *pcmdtReserved, IDispatch *pdispReserved)
  389. {
  390. CSFVFrame* pFrame = IToClass(CSFVFrame, _cSite, this);
  391. CDefView* pView = IToClass(CDefView, _cFrame, pFrame);
  392. // For Web View's w/o DVOC, it might be nice to let Trident's menu through...
  393. if ((dwID == CONTEXT_MENU_DEFAULT || dwID == CONTEXT_MENU_IMAGE) && pView->_hwndListview)
  394. {
  395. // we used to unselect everything first, but that's bogus because it breaks the app key trying
  396. // to get a context menu on the currently selected items
  397. // BOGUS - Trident blows up if we send the message here and the user
  398. // turns off webview. Post it for now.
  399. PostMessage(pView->_hwndListview, WM_CONTEXTMENU,
  400. (WPARAM)pView->_hwndListview, MAKELPARAM((short)LOWORD(ppt->x), (short)LOWORD(ppt->y)));
  401. return S_OK;
  402. }
  403. else
  404. {
  405. return S_FALSE;
  406. }
  407. }
  408. // IDocHostUIHandler
  409. HRESULT CSFVSite::GetHostInfo(DOCHOSTUIINFO *pInfo)
  410. {
  411. CSFVFrame* pFrame = IToClass(CSFVFrame, _cSite, this);
  412. CDefView* pView = IToClass(CDefView, _cFrame, pFrame);
  413. pInfo->cbSize = sizeof(*pInfo);
  414. if (pView->_fCombinedView)
  415. {
  416. pInfo->dwFlags = DOCHOSTUIFLAG_DISABLE_HELP_MENU | // We don't want Trident's help
  417. DOCHOSTUIFLAG_NO3DBORDER | // Desktop should be borderless
  418. DOCHOSTUIFLAG_SCROLL_NO; // | // Desktop should never scroll
  419. // DOCHOSTUIFLAG_DIALOG; // Prevent selection in Trident
  420. }
  421. else
  422. {
  423. pInfo->dwFlags = DOCHOSTUIFLAG_DISABLE_HELP_MENU |
  424. DOCHOSTUIFLAG_DIALOG |
  425. DOCHOSTUIFLAG_DISABLE_SCRIPT_INACTIVE;
  426. }
  427. if (SHIsLowMemoryMachine(ILMM_IE4))
  428. pInfo->dwFlags = pInfo->dwFlags | DOCHOSTUIFLAG_DISABLE_OFFSCREEN;
  429. pInfo->dwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT; // default
  430. return S_OK;
  431. }
  432. HRESULT CSFVSite::ShowUI(DWORD dwID, IOleInPlaceActiveObject *pActiveObject,
  433. IOleCommandTarget *pCommandTarget, IOleInPlaceFrame *pFrame, IOleInPlaceUIWindow *pDoc)
  434. {
  435. // Host did not display its own UI. Trident will proceed to display its own.
  436. return S_OK;
  437. }
  438. HRESULT CSFVSite::HideUI(void)
  439. {
  440. // This one is paired with ShowUI
  441. return S_FALSE;
  442. }
  443. HRESULT CSFVSite::UpdateUI(void)
  444. {
  445. // LATER: Isn't this equivalent to OLECMDID_UPDATECOMMANDS?
  446. return S_FALSE;
  447. }
  448. HRESULT CSFVSite::EnableModeless(BOOL fEnable)
  449. {
  450. // Called from the Trident when the equivalent member of its
  451. // IOleInPlaceActiveObject is called by the frame. We don't care
  452. // those cases.
  453. return S_OK;
  454. }
  455. HRESULT CSFVSite::OnDocWindowActivate(BOOL fActivate)
  456. {
  457. // Called from the Trident when the equivalent member of its
  458. // IOleInPlaceActiveObject is called by the frame. We don't care
  459. // those cases.
  460. return S_OK;
  461. }
  462. HRESULT CSFVSite::OnFrameWindowActivate(BOOL fActivate)
  463. {
  464. // Called from the Trident when the equivalent member of its
  465. // IOleInPlaceActiveObject is called by the frame. We don't care
  466. // those cases.
  467. return S_OK;
  468. }
  469. HRESULT CSFVSite::ResizeBorder(LPCRECT prcBorder, IOleInPlaceUIWindow *pUIWindow, BOOL fRameWindow)
  470. {
  471. // Called from the Trident when the equivalent member of its
  472. // IOleInPlaceActiveObject is called by the frame. We don't care
  473. // those cases.
  474. return S_OK;
  475. }
  476. HRESULT CSFVSite::TranslateAccelerator(LPMSG lpMsg, const GUID *pguidCmdGroup, DWORD nCmdID)
  477. {
  478. // Called from the Trident when the equivalent member of its
  479. // IOleInPlaceActiveObject is called by the frame.
  480. // Trap F5 alone and handle the refresh ourselves!
  481. // Note:This code-path will be hit for desktop only if the active desktop
  482. // is turned on.
  483. //
  484. // And probably if focus is on Trident. It's probably good to
  485. // pick this off for Web View too.
  486. //
  487. if ((lpMsg->message == WM_KEYDOWN) && (lpMsg->wParam == VK_F5))
  488. {
  489. CSFVFrame* pFrame = IToClass(CSFVFrame, _cSite, this);
  490. CDefView* pView = IToClass(CDefView, _cFrame, pFrame);
  491. pView->Refresh();
  492. return S_OK;
  493. }
  494. return S_FALSE; // The message was not translated
  495. }
  496. HRESULT CSFVSite::GetOptionKeyPath(BSTR *pbstrKey, DWORD dw)
  497. {
  498. // Trident will default to its own user options.
  499. *pbstrKey = NULL;
  500. return S_FALSE;
  501. }
  502. HRESULT CSFVSite::GetDropTarget(IDropTarget *pDropTarget, IDropTarget **ppDropTarget)
  503. {
  504. HRESULT hr;
  505. CSFVFrame* pFrame = IToClass(CSFVFrame, _cSite, this);
  506. CDefView* pView = IToClass(CDefView, _cFrame, pFrame);
  507. if (!pView->_IsDesktop())
  508. {
  509. hr = S_FALSE; // Let trident delegate in webview folders
  510. }
  511. else
  512. {
  513. if (_dt._pdtFrame == NULL)
  514. {
  515. pView->_psb->QueryInterface(IID_PPV_ARG(IDropTarget, &_dt._pdtFrame));
  516. }
  517. if (_dt._pdtFrame)
  518. {
  519. *ppDropTarget = &_dt;
  520. AddRef();
  521. hr = S_OK;
  522. }
  523. else
  524. {
  525. ASSERT(0);
  526. hr = E_UNEXPECTED;
  527. }
  528. }
  529. return hr;
  530. }
  531. HRESULT CSFVSite::GetExternal(IDispatch **ppDisp)
  532. {
  533. HRESULT hr;
  534. if (ppDisp)
  535. {
  536. *ppDisp = NULL;
  537. hr = S_OK;
  538. }
  539. else
  540. {
  541. hr = E_INVALIDARG;
  542. }
  543. return hr;
  544. }
  545. HRESULT CSFVSite::TranslateUrl(DWORD dwTranslate, OLECHAR *pchURLIn, OLECHAR **ppchURLOut)
  546. {
  547. HRESULT hr;
  548. if (ppchURLOut)
  549. {
  550. *ppchURLOut = NULL;
  551. hr = S_OK;
  552. }
  553. else
  554. {
  555. hr = E_INVALIDARG;
  556. }
  557. return hr;
  558. }
  559. HRESULT CSFVSite::FilterDataObject(IDataObject *pdtobj, IDataObject **ppdtobjRet)
  560. {
  561. HRESULT hr;
  562. if (ppdtobjRet)
  563. {
  564. *ppdtobjRet = NULL;
  565. hr = S_OK;
  566. }
  567. else
  568. {
  569. hr = E_INVALIDARG;
  570. }
  571. return hr;
  572. }