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.

743 lines
16 KiB

  1. //
  2. // SITE.CPP
  3. // Document Object Site Object
  4. //
  5. // Copyright (c)1995-1999 Microsoft Corporation, All Rights Reserved
  6. //
  7. #include "stdafx.h"
  8. #include "DHTMLEd.h"
  9. #include "DHTMLEdit.h"
  10. #include "proxyframe.h"
  11. #include "site.h"
  12. #include <urlmon.h>
  13. #include "triedsnk.h"
  14. #include "private.h"
  15. /*
  16. * CSite::CSite
  17. * CSite::~CSite
  18. *
  19. * Constructor Parameters:
  20. * hWnd HWND of the window associated with the site
  21. * pFR PCFrame to the parent structure.
  22. */
  23. CSite::CSite(CProxyFrame* pFR )
  24. {
  25. m_cRef = 0;
  26. m_hWnd = NULL;
  27. m_pFR = pFR;
  28. m_dwPropNotifyCookie = 0;
  29. m_dwOleObjectCookie = 0;
  30. m_pObj = NULL;
  31. m_bFiltered = TRUE;//FALSE;
  32. m_pIOleObject = NULL;
  33. m_pIOleIPObject = NULL;
  34. m_pIOleDocView = NULL;
  35. m_pIOleCommandTarget = NULL;
  36. m_pImpIOleClientSite = NULL;
  37. m_pImpIAdviseSink = NULL;
  38. m_pImpIOleIPSite = NULL;
  39. m_pImpIOleDocumentSite = NULL;
  40. m_pImpIDocHostUIHandler = NULL;
  41. m_pImpIDocHostShowUI = NULL;
  42. m_pImpAmbientIDispatch = NULL;
  43. m_pImpIPropertyNotifySink = NULL;
  44. m_pImpIOleControlSite = NULL;
  45. m_pTriEdDocEvtSink = NULL;
  46. m_pTriEdWndEvtSink = NULL;
  47. m_bfSaveAsUnicode = FALSE;
  48. m_cpCodePage = CP_ACP;
  49. m_piMLang = NULL;
  50. }
  51. CSite::~CSite(void)
  52. {
  53. //Object pointers cleaned up in Close.
  54. //We delete our own interfaces since we control them
  55. DeleteInterfaceImp( m_pImpIOleDocumentSite );
  56. DeleteInterfaceImp( m_pImpIOleIPSite );
  57. DeleteInterfaceImp( m_pImpIAdviseSink );
  58. DeleteInterfaceImp( m_pImpIOleClientSite );
  59. DeleteInterfaceImp( m_pImpIDocHostUIHandler );
  60. DeleteInterfaceImp( m_pImpIDocHostShowUI );
  61. DeleteInterfaceImp( m_pImpAmbientIDispatch);
  62. DeleteInterfaceImp( m_pImpIPropertyNotifySink);
  63. DeleteInterfaceImp( m_pImpIOleControlSite );
  64. if ( NULL != m_pTriEdDocEvtSink )
  65. {
  66. delete m_pTriEdDocEvtSink;
  67. }
  68. if ( NULL != m_pTriEdWndEvtSink )
  69. {
  70. delete m_pTriEdWndEvtSink;
  71. }
  72. }
  73. /*
  74. * CSite::QueryInterface
  75. * CSite::AddRef
  76. * CSite::Release
  77. *
  78. * Purpose:
  79. * IUnknown members for CSite object.
  80. */
  81. STDMETHODIMP CSite::QueryInterface( REFIID riid, void **ppv )
  82. {
  83. *ppv = NULL;
  84. #ifdef _DEBUG
  85. OLECHAR wszGUID[39];
  86. StringFromGUID2(riid, wszGUID, 39);
  87. USES_CONVERSION;
  88. LPTSTR szGUID = OLE2T(wszGUID);
  89. OutputDebugString(_T("CSite::QI("));
  90. OutputDebugString(szGUID);
  91. OutputDebugString(_T(")\n"));
  92. #endif
  93. if ( IID_IOleClientSite == riid )
  94. {
  95. *ppv = m_pImpIOleClientSite;
  96. }
  97. if ( IID_IAdviseSink == riid )
  98. {
  99. *ppv = m_pImpIAdviseSink;
  100. }
  101. if ( IID_IOleWindow == riid || IID_IOleInPlaceSite == riid )
  102. {
  103. *ppv = m_pImpIOleIPSite;
  104. }
  105. if ( IID_IOleDocumentSite == riid )
  106. {
  107. *ppv = m_pImpIOleDocumentSite;
  108. }
  109. if ( IID_IDocHostUIHandler == riid )
  110. {
  111. *ppv = m_pImpIDocHostUIHandler;
  112. }
  113. if ( IID_IDocHostShowUI == riid )
  114. {
  115. *ppv = m_pImpIDocHostShowUI;
  116. }
  117. if ( IID_IDispatch == riid )
  118. {
  119. *ppv = m_pImpAmbientIDispatch;
  120. }
  121. if ( IID_IPropertyNotifySink== riid )
  122. {
  123. *ppv = m_pImpIPropertyNotifySink;
  124. }
  125. if ( IID_IOleControlSite== riid )
  126. {
  127. *ppv = m_pImpIOleControlSite;
  128. }
  129. if ( NULL != *ppv )
  130. {
  131. ((LPUNKNOWN)*ppv)->AddRef();
  132. return NOERROR;
  133. }
  134. // Try the frame instead
  135. return GetFrame()->QueryInterface( riid, ppv );
  136. }
  137. STDMETHODIMP_(ULONG) CSite::AddRef(void)
  138. {
  139. return ++m_cRef;
  140. }
  141. STDMETHODIMP_(ULONG) CSite::Release(void)
  142. {
  143. if ( 0 != --m_cRef )
  144. {
  145. return m_cRef;
  146. }
  147. delete this;
  148. return 0;
  149. }
  150. /*
  151. * CSite::HrCreate
  152. *
  153. * Purpose:
  154. * Asks the site to instantiate the MSHTML.DLL object.
  155. *
  156. *
  157. * Parameters:
  158. * pIStorage IStorage * of the parent storage in which we're
  159. * to create an IStorage for the new object.
  160. * pchPath Path of what to load..
  161. *
  162. * Return Value:
  163. * BOOL Result of the creation.
  164. */
  165. HRESULT CSite::HrCreate(IUnknown* pUnk, IUnknown** ppUnkTriEdit)
  166. {
  167. HRESULT hr = S_OK;
  168. _ASSERTE(NULL == m_pObj);
  169. if (m_pObj)
  170. return E_UNEXPECTED;
  171. // It is valid for pUnk and ppUnkTriEdit to be NULL
  172. // Create the site's interface implementations which MSHTML.DLL will call
  173. m_pImpIOleClientSite = new CImpIOleClientSite( this, this );
  174. m_pImpIAdviseSink = new CImpIAdviseSink( this, this );
  175. m_pImpIOleIPSite = new CImpIOleInPlaceSite( this, this );
  176. m_pImpIOleDocumentSite = new CImpIOleDocumentSite( this, this );
  177. m_pImpIDocHostUIHandler = new CImpIDocHostUIHandler( this, this );
  178. m_pImpIDocHostShowUI = new CImpIDocHostShowUI( this, this );
  179. m_pImpAmbientIDispatch = new CImpAmbientIDispatch( this, this );
  180. m_pImpIPropertyNotifySink = new CImplPropertyNotifySink( this, this );
  181. m_pImpIOleControlSite = new CImpIOleControlSite ( this, this );
  182. m_pTriEdDocEvtSink = new CTriEditEventSink ( m_pFR, DIID_HTMLDocumentEvents );
  183. m_pTriEdWndEvtSink = new CTriEditEventSink ( m_pFR, DIID_HTMLWindowEvents );
  184. if ( NULL == m_pImpIOleClientSite
  185. || NULL == m_pImpIAdviseSink
  186. || NULL == m_pImpIOleIPSite
  187. || NULL == m_pImpIOleDocumentSite
  188. || NULL == m_pImpIDocHostUIHandler
  189. || NULL == m_pImpAmbientIDispatch
  190. || NULL == m_pImpIPropertyNotifySink
  191. || NULL == m_pImpIOleControlSite
  192. || NULL == m_pTriEdDocEvtSink
  193. || NULL == m_pImpIOleControlSite
  194. )
  195. {
  196. // releasing the site will delete any of the interface
  197. // implementations that did get allocated
  198. return E_OUTOFMEMORY;
  199. }
  200. // Create TriEdit
  201. hr = CoCreateInstance( CLSID_TriEditDocument, pUnk,
  202. CLSCTX_INPROC_SERVER, IID_IUnknown, (void **)&m_pObj );
  203. if (SUCCEEDED(hr))
  204. {
  205. if (ppUnkTriEdit)
  206. {
  207. m_pObj->AddRef();
  208. *ppUnkTriEdit = m_pObj;
  209. }
  210. }
  211. else if ( REGDB_E_CLASSNOTREG == hr )
  212. {
  213. DllUnregisterServer ();
  214. }
  215. // RJ - 2/26/98
  216. // defer call ObjectInitialize() until control has been created
  217. // so that props for IDHUIHandler::GetHostInfo can be set by host. ObjectInitialize
  218. // (really SetClientSite results in IDHUIHandler::GetHostInfo being called
  219. #if 0
  220. hr = ObjectInitialize();
  221. #endif
  222. return hr;
  223. }
  224. /*
  225. * CSite::HrObjectInitialize
  226. * (Protected)
  227. *
  228. * Purpose:
  229. * Creates DocObject object and cache frequently used interfaces
  230. *
  231. * Return Value:
  232. * HRESULT indicating success or failure
  233. */
  234. HRESULT CSite::HrObjectInitialize()
  235. {
  236. HRESULT hr;
  237. _ASSERTE(m_pObj);
  238. if (NULL == m_pObj)
  239. {
  240. return E_UNEXPECTED;
  241. }
  242. // cache IOleObject
  243. if (FAILED(hr = m_pObj->QueryInterface( IID_IOleObject, (void **)&m_pIOleObject )))
  244. return hr;
  245. _ASSERTE(m_pIOleObject);
  246. // SetClientSite is critical for DocObjects
  247. m_pIOleObject->SetClientSite( m_pImpIOleClientSite );
  248. _ASSERTE(0 == m_dwOleObjectCookie);
  249. m_pIOleObject->Advise(m_pImpIAdviseSink, &m_dwOleObjectCookie);
  250. // cache IOleCommandTarget
  251. if (FAILED(hr = m_pObj->QueryInterface( IID_IOleCommandTarget, (void **) &m_pIOleCommandTarget)))
  252. return hr;
  253. _ASSERTE(m_pIOleCommandTarget);
  254. if (FAILED(hr = HrRegisterPropNotifySink(TRUE)))
  255. return hr;
  256. // Hook up the proxy frame to the Trident Document events
  257. if (FAILED(hr = m_pTriEdDocEvtSink->Advise ( m_pIOleObject )))
  258. return hr;
  259. CComQIPtr<IHTMLDocument2, &IID_IHTMLDocument2>piHtmlDoc ( m_pIOleObject );
  260. _ASSERTE ( piHtmlDoc );
  261. if ( piHtmlDoc )
  262. {
  263. CComPtr<IHTMLWindow2> piHtmlWindow = NULL;
  264. hr = piHtmlDoc->get_parentWindow ( &piHtmlWindow );
  265. if ( SUCCEEDED ( hr ) )
  266. {
  267. hr = m_pTriEdWndEvtSink->Advise ( piHtmlWindow );
  268. }
  269. }
  270. if ( FAILED ( hr ) )
  271. return hr;
  272. // Attempt to create the IMultiLanguage2 object, avaialable only with IE5.
  273. // It's OK if this fails.
  274. CoCreateInstance ( CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER, IID_IMultiLanguage2Correct, (void**)&m_piMLang );
  275. // Put the object in the running state
  276. OleRun( m_pIOleObject );
  277. return hr;
  278. }
  279. /*
  280. * CSite::Close
  281. *
  282. * Purpose:
  283. * Possibly commits the storage, then releases it, afterwards
  284. * frees alls the object pointers.
  285. *
  286. * Parameters:
  287. * fCommit BOOL indicating if we're to commit.
  288. *
  289. * Return Value:
  290. * None
  291. */
  292. void CSite::Close(BOOL fCommit)
  293. {
  294. HRESULT hr = S_OK;
  295. _ASSERTE(m_pObj);
  296. hr = HrRegisterPropNotifySink(FALSE);
  297. _ASSERTE(SUCCEEDED(hr));
  298. if ( NULL != m_pIOleIPObject )
  299. {
  300. m_pIOleIPObject->InPlaceDeactivate();
  301. }
  302. ReleaseInterface( m_pIOleDocView );
  303. ReleaseInterface( m_pIOleCommandTarget );
  304. ReleaseInterface( m_piMLang );
  305. if ( NULL != m_pIOleObject )
  306. {
  307. hr = m_pIOleObject->Unadvise(m_dwOleObjectCookie);
  308. _ASSERTE(SUCCEEDED(hr));
  309. m_pTriEdDocEvtSink->Unadvise ();
  310. m_pTriEdWndEvtSink->Unadvise ();
  311. m_pIOleObject->Close( fCommit ? OLECLOSE_SAVEIFDIRTY : OLECLOSE_NOSAVE );
  312. m_pIOleObject->SetClientSite( NULL );
  313. ReleaseInterface( m_pIOleObject );
  314. }
  315. ReleaseInterface( m_pObj );
  316. }
  317. /*
  318. * CSite::InitialActivate
  319. *
  320. * Purpose:
  321. * Activates a verb on the object living in the site.
  322. *
  323. * Parameters:
  324. * iVerb LONG of the verb to execute.
  325. * hWnd HWND of hosting window
  326. *
  327. * Return Value:
  328. * None
  329. */
  330. void
  331. CSite::InitialActivate(LONG iVerb, HWND hWnd)
  332. {
  333. _ASSERTE(hWnd);
  334. m_hWnd = hWnd;
  335. Activate(iVerb);
  336. }
  337. void CSite::Activate(LONG iVerb)
  338. {
  339. RECT rc = {0};
  340. // There is no window when we're being called to discard - (InPlaceDeactivate)
  341. if ( iVerb != OLEIVERB_DISCARDUNDOSTATE )
  342. {
  343. _ASSERTE(m_hWnd);
  344. GetClientRect(m_hWnd, &rc);
  345. }
  346. if (m_pIOleObject)
  347. {
  348. m_pIOleObject->DoVerb(iVerb, NULL, m_pImpIOleClientSite, -1, m_hWnd, &rc);
  349. }
  350. }
  351. /*
  352. * CSite::UpdateObjectRects
  353. *
  354. * Purpose:
  355. * Informs the site that the client area window was resized and
  356. * that the site needs to also tell the DocObject of the resize.
  357. *
  358. * Parameters:
  359. * None
  360. *
  361. * Return Value:
  362. * None
  363. */
  364. void CSite::UpdateObjectRects( void )
  365. {
  366. if ( NULL != m_pIOleDocView )
  367. {
  368. RECT rc;
  369. GetClientRect(m_hWnd, &rc);
  370. m_pIOleDocView->SetRect(&rc);
  371. }
  372. }
  373. void CSite::OnReadyStateChanged()
  374. {
  375. HRESULT hr = S_OK;
  376. VARIANT Var;
  377. IDispatch * pDisp = NULL;
  378. CComDispatchDriver dispDriver;
  379. _ASSERTE(m_pObj);
  380. hr = m_pObj->QueryInterface(IID_IDispatch, (void **)&pDisp);
  381. _ASSERTE(SUCCEEDED(hr));
  382. if (SUCCEEDED(hr))
  383. {
  384. VariantInit(&Var);
  385. dispDriver = pDisp;
  386. if (SUCCEEDED(hr = dispDriver.GetProperty(DISPID_READYSTATE, &Var)))
  387. {
  388. // should be either I4 or I2
  389. _ASSERTE(Var.vt == VT_I4 || Var.vt == VT_I2);
  390. // we get the ready state so we can warn about sending while downloading
  391. GetFrame()->OnReadyStateChanged((READYSTATE) Var.lVal);
  392. }
  393. _ASSERTE(SUCCEEDED(hr));
  394. pDisp->Release();
  395. }
  396. }
  397. HRESULT
  398. CSite::HrRegisterPropNotifySink(BOOL fRegister)
  399. {
  400. IConnectionPointContainer *pCPContainer=0;
  401. IConnectionPoint *pCP=0;
  402. HRESULT hr = S_OK;
  403. _ASSERTE(m_pObj);
  404. hr = m_pObj->QueryInterface(IID_IConnectionPointContainer, (LPVOID *)&pCPContainer);
  405. if (FAILED(hr))
  406. goto error;
  407. hr = pCPContainer->FindConnectionPoint(IID_IPropertyNotifySink, &pCP);
  408. if (FAILED(hr))
  409. goto error;
  410. if (fRegister)
  411. {
  412. _ASSERTE(m_dwPropNotifyCookie == 0);
  413. hr = pCP->Advise((IPropertyNotifySink *)this, &m_dwPropNotifyCookie);
  414. if (FAILED(hr))
  415. goto error;
  416. }
  417. else
  418. {
  419. if (m_dwPropNotifyCookie)
  420. {
  421. hr = pCP->Unadvise(m_dwPropNotifyCookie);
  422. if (FAILED(hr))
  423. goto error;
  424. m_dwPropNotifyCookie = 0;
  425. }
  426. }
  427. error:
  428. ReleaseInterface(pCPContainer);
  429. ReleaseInterface(pCP);
  430. return hr;
  431. }
  432. HRESULT
  433. CSite::HrSaveToStream(LPSTREAM pStream)
  434. {
  435. HRESULT hr = S_OK;
  436. CComQIPtr<IPersistStreamInit, &IID_IPersistStreamInit> piPersistStreamInit(m_pObj);
  437. _ASSERTE(pStream);
  438. _ASSERTE(m_pObj);
  439. if (!piPersistStreamInit)
  440. return E_NOINTERFACE;
  441. if (FAILED(hr = piPersistStreamInit->Save(pStream, TRUE)))
  442. {
  443. _ASSERTE(SUCCEEDED(hr));
  444. goto cleanup;
  445. }
  446. // This can return an ASCII stream, even if we loaded Unicode into the control!
  447. hr = HrConvertStreamToUnicode ( pStream );
  448. cleanup:
  449. return hr;
  450. }
  451. HRESULT
  452. CSite::HrSaveToStreamAndFilter(LPSTREAM* ppStream, DWORD dwFilterFlags)
  453. {
  454. HRESULT hr = S_OK;
  455. CComPtr<IStream> piStream;
  456. CComPtr<IStream> piFilteredStream;
  457. VARIANT_BOOL vbBrowse;
  458. _ASSERTE(ppStream);
  459. if (FAILED(hr = CreateStreamOnHGlobal(NULL, TRUE, &piStream)))
  460. {
  461. _ASSERTE(SUCCEEDED(hr));
  462. goto cleanup;
  463. }
  464. if (FAILED(hr = HrSaveToStream(piStream)))
  465. {
  466. _ASSERTE(SUCCEEDED(hr));
  467. goto cleanup;
  468. }
  469. m_pFR->GetBrowseMode ( &vbBrowse );
  470. if ( vbBrowse )
  471. {
  472. piStream.p->AddRef ();
  473. piFilteredStream = piStream;
  474. }
  475. else
  476. {
  477. hr = HrFilter(FALSE, piStream, &piFilteredStream, dwFilterFlags);
  478. }
  479. if (FAILED(hr))
  480. {
  481. _ASSERTE(SUCCEEDED(hr));
  482. goto cleanup;
  483. }
  484. *ppStream = piFilteredStream;
  485. (*ppStream)->AddRef();
  486. cleanup:
  487. return hr;
  488. }
  489. HRESULT
  490. CSite::HrSaveToFile(BSTR fileName, DWORD dwFilterFlags)
  491. {
  492. USES_CONVERSION;
  493. HRESULT hr = S_OK;
  494. LPTSTR pFileName = NULL;
  495. CComPtr<IStream> piStream;
  496. _ASSERTE(fileName);
  497. pFileName = OLE2T(fileName);
  498. _ASSERTE(pFileName);
  499. if (NULL == pFileName)
  500. return E_OUTOFMEMORY;
  501. _ASSERTE(fileName);
  502. if (FAILED(hr = HrSaveToStreamAndFilter(&piStream, dwFilterFlags)))
  503. {
  504. _ASSERTE(SUCCEEDED(hr));
  505. goto cleanup;
  506. }
  507. if (FAILED(hr = HrStreamToFile(piStream, pFileName)))
  508. {
  509. goto cleanup;
  510. }
  511. cleanup:
  512. return hr;
  513. }
  514. HRESULT
  515. CSite::HrSaveToBstr(BSTR* pBstr, DWORD dwFilterFlags)
  516. {
  517. HRESULT hr = S_OK;
  518. CComPtr<IStream> piStream;
  519. _ASSERTE(pBstr);
  520. if (FAILED(hr = HrSaveToStreamAndFilter(&piStream, dwFilterFlags)))
  521. {
  522. _ASSERTE(SUCCEEDED(hr));
  523. goto cleanup;
  524. }
  525. if (FAILED(hr = HrStreamToBstr(piStream, pBstr)))
  526. {
  527. _ASSERTE(SUCCEEDED(hr));
  528. goto cleanup;
  529. }
  530. cleanup:
  531. return hr;
  532. }
  533. HRESULT
  534. CSite::HrIsDirtyIPersistStreamInit(BOOL& bVal)
  535. {
  536. HRESULT hr = S_OK;
  537. HRESULT hrpsi = S_FALSE;
  538. CComQIPtr<IPersistStreamInit, &IID_IPersistStreamInit> piPersistStreamInit(m_pObj);
  539. _ASSERTE(m_pObj);
  540. bVal = FALSE;
  541. if (!piPersistStreamInit)
  542. return E_NOINTERFACE;
  543. if (FAILED(hrpsi = piPersistStreamInit->IsDirty()))
  544. {
  545. _ASSERTE(SUCCEEDED(hr));
  546. goto cleanup;
  547. }
  548. (S_OK == hrpsi) ? bVal = TRUE : bVal = FALSE;
  549. cleanup:
  550. return hr;
  551. }
  552. HRESULT CSite::GetContainer ( LPOLECONTAINER* ppContainer )
  553. {
  554. return m_pFR->GetContainer ( ppContainer );
  555. }
  556. /*
  557. * CImpIOleControlSite::QueryInterface
  558. * CImpIOleControlSite::AddRef
  559. * CImpIOleControlSite::Release
  560. *
  561. * Purpose:
  562. * IUnknown members for CImpIOleControlSite object.
  563. */
  564. CImpIOleControlSite::CImpIOleControlSite( PCSite pSite, LPUNKNOWN pUnkOuter )
  565. {
  566. m_cRef = 0;
  567. m_pSite = pSite;
  568. m_pUnkOuter = pUnkOuter;
  569. }
  570. CImpIOleControlSite::~CImpIOleControlSite( void )
  571. {
  572. }
  573. STDMETHODIMP CImpIOleControlSite::QueryInterface( REFIID riid, void **ppv )
  574. {
  575. return m_pUnkOuter->QueryInterface( riid, ppv );
  576. }
  577. STDMETHODIMP_(ULONG) CImpIOleControlSite::AddRef( void )
  578. {
  579. ++m_cRef;
  580. return m_pUnkOuter->AddRef();
  581. }
  582. STDMETHODIMP_(ULONG) CImpIOleControlSite::Release( void )
  583. {
  584. --m_cRef;
  585. return m_pUnkOuter->Release();
  586. }