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.

777 lines
17 KiB

  1. /*
  2. * d o c h o s t . c p p
  3. *
  4. * Purpose:
  5. * basic implementation of a docobject host. Used by the body class to
  6. * host Trident and/or MSHTML
  7. *
  8. * History
  9. * August '96: brettm - created
  10. *
  11. * Copyright (C) Microsoft Corp. 1995, 1996.
  12. */
  13. #include "pch.hxx"
  14. #include <resource.h>
  15. #include "globals.h"
  16. #include "dochost.h"
  17. /*
  18. * m a c r o s
  19. */
  20. /*
  21. * c o n s t a n t s
  22. */
  23. static CHAR c_szDocHostWndClass[] = "MEPAD_DocHost";
  24. /*
  25. * t y p e d e f s
  26. */
  27. /*
  28. * g l o b a l s
  29. */
  30. /*
  31. * f u n c t i o n p r o t y p e s
  32. */
  33. /*
  34. * f u n c t i o n s
  35. */
  36. HRESULT HrInitNew(LPUNKNOWN pUnk)
  37. {
  38. LPPERSISTSTREAMINIT ppsi=0;
  39. HRESULT hr;
  40. if (!pUnk)
  41. return E_INVALIDARG;
  42. hr=pUnk->QueryInterface(IID_IPersistStreamInit, (LPVOID *)&ppsi);
  43. if (FAILED(hr))
  44. goto error;
  45. hr = ppsi->InitNew();
  46. error:
  47. ReleaseObj(ppsi);
  48. return hr;
  49. }
  50. CDocHost::CDocHost()
  51. {
  52. /*
  53. Not initialised
  54. Member: Initialised In:
  55. --------------------+---------------------------
  56. */
  57. m_cRef=1;
  58. m_hwnd=0;
  59. m_pDocView=0;
  60. m_lpOleObj=0;
  61. m_pCmdTarget=0;
  62. m_ulAdviseConnection=0;
  63. m_hwndDocObj=NULL;
  64. m_fUIActive=FALSE;
  65. m_fFocus=FALSE;
  66. m_fDownloading=FALSE;
  67. m_dhbBorder=dhbNone;
  68. m_fCycleFocus=FALSE;
  69. m_pInPlaceActiveObj = NULL;
  70. m_dwFrameWidth = 0;
  71. m_dwFrameHeight = 0;
  72. m_pInPlaceFrame =0;
  73. }
  74. CDocHost::~CDocHost()
  75. {
  76. SafeRelease(m_pInPlaceFrame);
  77. SafeRelease(m_pCmdTarget);
  78. SafeRelease(m_lpOleObj);
  79. SafeRelease(m_pDocView);
  80. SafeRelease(m_pInPlaceActiveObj);
  81. HrCloseDocObj();
  82. }
  83. ULONG CDocHost::AddRef()
  84. {
  85. return ++m_cRef;
  86. }
  87. ULONG CDocHost::Release()
  88. {
  89. if (--m_cRef==0)
  90. {
  91. delete this;
  92. return 0;
  93. }
  94. return m_cRef;
  95. }
  96. HRESULT CDocHost::QueryInterface(REFIID riid, LPVOID *lplpObj)
  97. {
  98. if(!lplpObj)
  99. return E_INVALIDARG;
  100. *lplpObj = NULL; // set to NULL, in case we fail.
  101. if (IsEqualIID(riid, IID_IUnknown))
  102. *lplpObj = (LPVOID)(LPUNKNOWN)(LPOLEINPLACEFRAME)this;
  103. else if (IsEqualIID(riid, IID_IOleInPlaceSite))
  104. *lplpObj = (LPVOID)(LPOLEINPLACESITE)this;
  105. else if (IsEqualIID(riid, IID_IOleClientSite))
  106. *lplpObj = (LPVOID)(LPOLECLIENTSITE)this;
  107. else if (IsEqualIID(riid, IID_IOleControlSite))
  108. *lplpObj = (LPVOID)(IOleControlSite *)this;
  109. else if (IsEqualIID(riid, IID_IAdviseSink))
  110. *lplpObj = (LPVOID)(LPADVISESINK)this;
  111. else if (IsEqualIID(riid, IID_IOleDocumentSite))
  112. *lplpObj = (LPVOID)(LPOLEDOCUMENTSITE)this;
  113. // BUG BUGB
  114. // I don't think we need to provide this, here for debugging for now
  115. // brettm
  116. else if (IsEqualIID(riid, IID_IOleCommandTarget))
  117. *lplpObj = (LPVOID)(LPOLECOMMANDTARGET)this;
  118. else if (IsEqualIID(riid, IID_IServiceProvider))
  119. *lplpObj = (LPVOID)(LPSERVICEPROVIDER)this;
  120. else
  121. return E_NOINTERFACE;
  122. AddRef();
  123. return NOERROR;
  124. }
  125. LRESULT CALLBACK CDocHost::ExtWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  126. {
  127. LPDOCHOST pDocHost;
  128. if(msg==WM_CREATE)
  129. {
  130. pDocHost=(CDocHost *)((LPMDICREATESTRUCT)((LPCREATESTRUCT)lParam)->lpCreateParams)->lParam;
  131. if(!pDocHost)
  132. return -1;
  133. if(!pDocHost->WMCreate(hwnd))
  134. return -1;
  135. }
  136. pDocHost = (LPDOCHOST)GetWndThisPtr(hwnd);
  137. if(pDocHost)
  138. return pDocHost->WndProc(hwnd, msg, wParam, lParam);
  139. else
  140. return DefMDIChildProc(hwnd, msg, wParam, lParam);
  141. }
  142. LRESULT CDocHost::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  143. {
  144. switch(msg)
  145. {
  146. case WM_MDIACTIVATE:
  147. // if lParam is our HWND we're being activated, else deactivated
  148. if (m_pInPlaceActiveObj)
  149. m_pInPlaceActiveObj->OnDocWindowActivate((HWND)lParam == m_hwnd);
  150. break;
  151. case WM_DESTROY:
  152. HrCloseDocObj();
  153. break;
  154. case WM_SETFOCUS:
  155. if(m_pDocView)
  156. m_pDocView->UIActivate(TRUE);
  157. break;
  158. case WM_SIZE:
  159. WMSize(LOWORD(lParam), HIWORD(lParam));
  160. return 0;
  161. case WM_NCDESTROY:
  162. WMNCDestroy();
  163. break;
  164. }
  165. return DefMDIChildProc(hwnd, msg, wParam, lParam);
  166. }
  167. void CDocHost::WMNCDestroy()
  168. {
  169. SetWindowLong(m_hwnd, GWL_USERDATA, NULL);
  170. m_hwnd = NULL;
  171. Release();
  172. }
  173. BOOL CDocHost::WMCreate(HWND hwnd)
  174. {
  175. m_hwnd = hwnd;
  176. SetWindowLong(hwnd, GWL_USERDATA, (LPARAM)this);
  177. AddRef();
  178. return SUCCEEDED(HrSubWMCreate())?TRUE:FALSE;
  179. }
  180. HRESULT CDocHost::HrCreateDocObj(LPCLSID pCLSID)
  181. {
  182. HRESULT hr=NOERROR;
  183. if(!pCLSID)
  184. return E_INVALIDARG;
  185. hr = CoCreateInstance(*pCLSID, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
  186. IID_IOleObject, (LPVOID *)&m_lpOleObj);
  187. if (FAILED(hr))
  188. {
  189. MessageBox(m_hwnd, "MEPAD", "Failed to create DocObj", MB_OK);
  190. goto error;
  191. }
  192. hr = m_lpOleObj->SetClientSite((LPOLECLIENTSITE)this);
  193. if (FAILED(hr))
  194. goto error;
  195. hr = m_lpOleObj->Advise((LPADVISESINK)this, &m_ulAdviseConnection);
  196. if (FAILED(hr))
  197. goto error;
  198. hr = m_lpOleObj->QueryInterface(IID_IOleCommandTarget, (LPVOID *)&m_pCmdTarget);
  199. if (FAILED(hr))
  200. goto error;
  201. hr = HrInitNew(m_lpOleObj);
  202. if (FAILED(hr))
  203. goto error;
  204. error:
  205. return hr;
  206. }
  207. HRESULT CDocHost::HrShow()
  208. {
  209. RECT rc;
  210. HRESULT hr;
  211. GetClientRect(m_hwnd, &rc);
  212. HrGetDocObjSize(&rc);
  213. hr=m_lpOleObj->DoVerb(OLEIVERB_SHOW, NULL, (LPOLECLIENTSITE)this, 0, m_hwnd, &rc);
  214. if(FAILED(hr))
  215. goto error;
  216. ShowWindow(m_hwnd, SW_SHOW);
  217. error:
  218. return hr;
  219. }
  220. HRESULT CDocHost::HrCloseDocObj()
  221. {
  222. LPOLEINPLACEOBJECT pInPlaceObj=0;
  223. SafeRelease(m_pInPlaceFrame);
  224. SafeRelease(m_pCmdTarget);
  225. SafeRelease(m_pInPlaceActiveObj);
  226. if(m_pDocView)
  227. {
  228. m_pDocView->UIActivate(FALSE);
  229. m_pDocView->CloseView(0);
  230. m_pDocView->SetInPlaceSite(NULL);
  231. SafeRelease(m_pDocView);
  232. }
  233. if (m_lpOleObj)
  234. {
  235. if (m_ulAdviseConnection)
  236. {
  237. m_lpOleObj->Unadvise(m_ulAdviseConnection);
  238. m_ulAdviseConnection=NULL;
  239. }
  240. // deactivate the docobj. mshtml seems more sensitive to this than Trident.
  241. if (!FAILED(m_lpOleObj->QueryInterface(IID_IOleInPlaceObject, (LPVOID*)&pInPlaceObj)))
  242. {
  243. pInPlaceObj->InPlaceDeactivate();
  244. pInPlaceObj->Release();
  245. }
  246. // close the ole object, but blow off changes as we have either extracted
  247. // them ourselves or don't care.
  248. m_lpOleObj->Close(OLECLOSE_NOSAVE);
  249. #ifdef DEBUG
  250. ULONG uRef;
  251. uRef=
  252. #endif
  253. m_lpOleObj->Release();
  254. m_lpOleObj=NULL;
  255. }
  256. m_fDownloading=FALSE;
  257. m_fFocus=FALSE;
  258. m_fUIActive=FALSE;
  259. return NOERROR;
  260. }
  261. HRESULT CDocHost::HrInit(HWND hwndParent, int idDlgItem, DWORD dhbBorder)
  262. {
  263. HRESULT hr=S_OK;
  264. HWND hwnd;
  265. WNDCLASS wc={0};
  266. if(!IsWindow(hwndParent))
  267. return E_INVALIDARG;
  268. m_dhbBorder=dhbBorder;
  269. if (!GetClassInfo(g_hInst, c_szDocHostWndClass, &wc))
  270. {
  271. wc.lpfnWndProc = CDocHost::ExtWndProc;
  272. wc.hInstance = g_hInst;
  273. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  274. wc.lpszClassName = c_szDocHostWndClass;
  275. wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  276. wc.hIcon = LoadIcon(g_hInst, MAKEINTRESOURCE(idiApp));
  277. wc.style = CS_DBLCLKS;
  278. if(!RegisterClass(&wc))
  279. return E_OUTOFMEMORY;
  280. }
  281. hwnd = CreateMDIWindow(
  282. c_szDocHostWndClass,
  283. "MimeEdit Host",
  284. MDIS_ALLCHILDSTYLES|
  285. WS_CHILD|WS_CLIPCHILDREN|WS_CLIPSIBLINGS|WS_MAXIMIZEBOX|WS_CAPTION|WS_SYSMENU|WS_THICKFRAME,
  286. CW_USEDEFAULT, CW_USEDEFAULT,
  287. CW_USEDEFAULT, CW_USEDEFAULT,
  288. hwndParent,
  289. g_hInst,
  290. (LONG)this);
  291. if(!hwnd)
  292. {
  293. hr=E_OUTOFMEMORY;
  294. goto error;
  295. }
  296. error:
  297. return hr;
  298. }
  299. // *** IOleWindow methods ***
  300. HRESULT CDocHost::GetWindow(HWND *phwnd)
  301. {
  302. *phwnd=m_hwnd;
  303. return NOERROR;
  304. }
  305. HRESULT CDocHost::ContextSensitiveHelp(BOOL fEnterMode)
  306. {
  307. return E_NOTIMPL;
  308. }
  309. // *** IOleInPlaceUIWindow methods ***
  310. HRESULT CDocHost::GetBorder(LPRECT lprectBorder)
  311. {
  312. return E_NOTIMPL;
  313. }
  314. HRESULT CDocHost::RequestBorderSpace(LPCBORDERWIDTHS pborderwidths)
  315. {
  316. return NOERROR;
  317. }
  318. HRESULT CDocHost::SetBorderSpace(LPCBORDERWIDTHS lpborderwidths)
  319. {
  320. return NOERROR;
  321. }
  322. HRESULT CDocHost::SetActiveObject(IOleInPlaceActiveObject * pActiveObject, LPCOLESTR lpszObjName)
  323. {
  324. SafeRelease(m_pInPlaceActiveObj);
  325. m_pInPlaceActiveObj=pActiveObject;
  326. if(m_pInPlaceActiveObj)
  327. m_pInPlaceActiveObj->AddRef();
  328. return NOERROR;
  329. }
  330. // **** IOleInPlaceSite methods ****
  331. HRESULT CDocHost::CanInPlaceActivate()
  332. {
  333. return NOERROR;
  334. }
  335. HRESULT CDocHost::OnInPlaceActivate()
  336. {
  337. LPOLEINPLACEACTIVEOBJECT pInPlaceActive=0;
  338. m_lpOleObj->QueryInterface(IID_IOleInPlaceActiveObject, (LPVOID *)&pInPlaceActive);
  339. if(pInPlaceActive)
  340. {
  341. pInPlaceActive->GetWindow(&m_hwndDocObj);
  342. ReleaseObj(pInPlaceActive);
  343. }
  344. return NOERROR;
  345. }
  346. HRESULT CDocHost::OnUIActivate()
  347. {
  348. m_fUIActive=TRUE;
  349. return NOERROR;
  350. }
  351. HRESULT CDocHost::GetWindowContext(IOleInPlaceFrame **ppFrame,
  352. IOleInPlaceUIWindow **ppDoc,
  353. LPRECT lprcPosRect,
  354. LPRECT lprcClipRect,
  355. LPOLEINPLACEFRAMEINFO lpFrameInfo)
  356. {
  357. *ppFrame = (LPOLEINPLACEFRAME)m_pInPlaceFrame;
  358. m_pInPlaceFrame->AddRef();
  359. *ppDoc = (IOleInPlaceUIWindow *)this;
  360. AddRef();
  361. GetClientRect(m_hwnd, lprcClipRect);
  362. GetClientRect(m_hwnd, lprcPosRect);
  363. HrGetDocObjSize(lprcClipRect);
  364. HrGetDocObjSize(lprcPosRect);
  365. lpFrameInfo->fMDIApp = FALSE;
  366. lpFrameInfo->hwndFrame=m_hwnd;
  367. lpFrameInfo->haccel = NULL;
  368. lpFrameInfo->cAccelEntries = 0;
  369. return NOERROR;
  370. }
  371. HRESULT CDocHost::Scroll(SIZE scrollExtent)
  372. {
  373. // the docobject consumes the entireview, so scroll requests
  374. // are meaningless. Return NOERROR to indicate that they're scolled
  375. // into view.
  376. return NOERROR;
  377. }
  378. HRESULT CDocHost::OnUIDeactivate(BOOL fUndoable)
  379. {
  380. m_fUIActive=FALSE;
  381. return S_OK;
  382. }
  383. HRESULT CDocHost::OnInPlaceDeactivate()
  384. {
  385. return S_OK;
  386. }
  387. HRESULT CDocHost::DiscardUndoState()
  388. {
  389. return E_NOTIMPL;
  390. }
  391. HRESULT CDocHost::DeactivateAndUndo()
  392. {
  393. return E_NOTIMPL;
  394. }
  395. HRESULT CDocHost::OnPosRectChange(LPCRECT lprcPosRect)
  396. {
  397. return E_NOTIMPL;
  398. }
  399. // IOleClientSite methods.
  400. HRESULT CDocHost::SaveObject()
  401. {
  402. return E_NOTIMPL;
  403. }
  404. HRESULT CDocHost::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, LPMONIKER *ppmnk)
  405. {
  406. return E_NOTIMPL;
  407. }
  408. HRESULT CDocHost::GetContainer(LPOLECONTAINER *ppCont)
  409. {
  410. if(ppCont)
  411. *ppCont=NULL;
  412. return E_NOINTERFACE;
  413. }
  414. HRESULT CDocHost::ShowObject()
  415. {
  416. // always shown.
  417. // $TODO: do we need to restore the browser here if it is
  418. // minimised?
  419. return NOERROR;
  420. }
  421. HRESULT CDocHost::OnShowWindow(BOOL fShow)
  422. {
  423. return E_NOTIMPL;
  424. }
  425. HRESULT CDocHost::RequestNewObjectLayout()
  426. {
  427. return E_NOTIMPL;
  428. }
  429. // IAdviseSink methods
  430. void CDocHost::OnDataChange(FORMATETC *pfetc, STGMEDIUM *pstgmed)
  431. {
  432. }
  433. void CDocHost::OnViewChange(DWORD dwAspect, LONG lIndex)
  434. {
  435. }
  436. void CDocHost::OnRename(LPMONIKER pmk)
  437. {
  438. }
  439. void CDocHost::OnSave()
  440. {
  441. }
  442. void CDocHost::OnClose()
  443. {
  444. }
  445. // IOleDocumentSite
  446. HRESULT CDocHost::ActivateMe(LPOLEDOCUMENTVIEW pViewToActivate)
  447. {
  448. return HrCreateDocView();
  449. }
  450. HRESULT CDocHost::HrCreateDocView()
  451. {
  452. HRESULT hr;
  453. LPOLEDOCUMENT pOleDoc=NULL;
  454. hr=OleRun(m_lpOleObj);
  455. if(FAILED(hr))
  456. goto error;
  457. hr=m_lpOleObj->QueryInterface(IID_IOleDocument, (LPVOID*)&pOleDoc);
  458. if(FAILED(hr))
  459. goto error;
  460. hr=pOleDoc->CreateView(this, NULL,0,&m_pDocView);
  461. if(FAILED(hr))
  462. goto error;
  463. hr=m_pDocView->SetInPlaceSite(this);
  464. if(FAILED(hr))
  465. goto error;
  466. hr=m_pDocView->Show(TRUE);
  467. if(FAILED(hr))
  468. goto error;
  469. error:
  470. ReleaseObj(pOleDoc);
  471. return hr;
  472. }
  473. HRESULT CDocHost::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD rgCmds[], OLECMDTEXT *pCmdText)
  474. {
  475. ULONG ul;
  476. // BUGBUG: Check IsEqualGUID(*pguidCmdGroup, CGID_ShellDocView) as well
  477. if (!rgCmds)
  478. return E_INVALIDARG;
  479. if (pguidCmdGroup == NULL)
  480. {
  481. for (ul=0;ul<cCmds; ul++)
  482. {
  483. switch (rgCmds[ul].cmdID)
  484. {
  485. case OLECMDID_OPEN:
  486. case OLECMDID_SAVE:
  487. case OLECMDID_PRINT:
  488. rgCmds[ul].cmdf = MSOCMDF_ENABLED;
  489. break;
  490. default:
  491. rgCmds[ul].cmdf = 0;
  492. break;
  493. }
  494. }
  495. /* for now we deal only with status text*/
  496. if (pCmdText)
  497. {
  498. if (!(pCmdText->cmdtextf & OLECMDTEXTF_STATUS))
  499. {
  500. pCmdText->cmdtextf = OLECMDTEXTF_NONE;// is this needed?
  501. pCmdText->cwActual = 0;
  502. return NOERROR;
  503. }
  504. }
  505. return NOERROR;
  506. }
  507. return OLECMDERR_E_UNKNOWNGROUP;
  508. }
  509. HRESULT CDocHost::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdExecOpt, VARIANTARG *pvaIn, VARIANTARG *pvaOut)
  510. {
  511. if (pguidCmdGroup == NULL)
  512. {
  513. switch(nCmdID)
  514. {
  515. case OLECMDID_SETDOWNLOADSTATE:
  516. if(pvaIn->vt==VT_I4)
  517. {
  518. m_fDownloading=pvaIn->lVal;
  519. return S_OK;
  520. }
  521. break;
  522. case OLECMDID_UPDATECOMMANDS:
  523. OnUpdateCommands();
  524. break;
  525. case OLECMDID_SETPROGRESSPOS:
  526. // when done downloading trident now hits us with a
  527. // setprogresspos == -1 to indicate we should remove the "Done"
  528. if (pvaIn->lVal == -1)
  529. m_pInPlaceFrame->SetStatusText(NULL);
  530. return S_OK;
  531. case OLECMDID_SETPROGRESSTEXT:
  532. if(pvaIn->vt == (VT_BSTR))
  533. m_pInPlaceFrame->SetStatusText((LPCOLESTR)pvaIn->bstrVal);
  534. return S_OK;
  535. }
  536. }
  537. return OLECMDERR_E_UNKNOWNGROUP;
  538. }
  539. void CDocHost::WMSize(int cxBody, int cyBody)
  540. {
  541. RECT rc={0};
  542. if(m_pDocView)
  543. {
  544. rc.bottom=cyBody;
  545. rc.right=cxBody;
  546. // give the subclass a chance to override the size of the
  547. // docobj
  548. HrGetDocObjSize(&rc);
  549. m_pDocView->SetRect(&rc);
  550. }
  551. // notify the subclass of a wmsize
  552. OnWMSize(&rc);
  553. }
  554. HRESULT CDocHost::QueryService(REFGUID guidService, REFIID riid, LPVOID *ppvObject)
  555. {
  556. return E_UNEXPECTED;
  557. }
  558. HRESULT CDocHost::HrSubWMCreate()
  559. {
  560. return NOERROR;
  561. }
  562. HRESULT CDocHost::OnControlInfoChanged()
  563. {
  564. return E_NOTIMPL;
  565. }
  566. HRESULT CDocHost::LockInPlaceActive(BOOL fLock)
  567. {
  568. return E_NOTIMPL;
  569. }
  570. HRESULT CDocHost::GetExtendedControl(LPDISPATCH *ppDisp)
  571. {
  572. if (ppDisp)
  573. *ppDisp=NULL;
  574. return E_NOTIMPL;
  575. }
  576. HRESULT CDocHost::TransformCoords(POINTL *pPtlHimetric, POINTF *pPtfContainer,DWORD dwFlags)
  577. {
  578. return E_NOTIMPL;
  579. }
  580. /*
  581. * this is a little trippy, so bear with me. When we get a tab, and trident is UIActive we always pass it off to them
  582. * if it tabs off the end of its internal tab order (a list of urls for instance) then we get hit with a VK_TAB in our
  583. * IOleControlSite::TranslateAccel. If so then we set m_fCycleFocus to TRUE and return S_OK to indicate we took the tab
  584. * tridents IOIPAO::TranslateAccel returns S_OK to indicate it snagged the TAB, we then detect if we set cyclefocus to true
  585. * there and if so, we return S_FALSE from CBody::HrTranslateAccel to indicate to the browser that we didn't take it and it
  586. * move the focus on
  587. *
  588. */
  589. HRESULT CDocHost::TranslateAccelerator(LPMSG lpMsg, DWORD grfModifiers)
  590. {
  591. if (lpMsg->message == WM_KEYDOWN && lpMsg->wParam == VK_TAB)
  592. {
  593. m_fCycleFocus=TRUE;
  594. return S_OK;
  595. }
  596. return E_NOTIMPL;
  597. }
  598. HRESULT CDocHost::OnFocus(BOOL fGotFocus)
  599. {
  600. m_fFocus = fGotFocus;
  601. return S_OK;
  602. }
  603. HRESULT CDocHost::ShowPropertyFrame(void)
  604. {
  605. return E_NOTIMPL;
  606. }