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.

686 lines
16 KiB

  1. /*++
  2. Copyright (C) 1993-1999 Microsoft Corporation
  3. Module Name:
  4. ioleobj.cpp
  5. Abstract:
  6. Implementation of the IOleObject interface for Polyline. Some of
  7. these just pass through to the default handler which does default
  8. implementations.
  9. --*/
  10. #include "polyline.h"
  11. #include "unkhlpr.h"
  12. #include "utils.h"
  13. #include "unihelpr.h"
  14. void RegisterAsRunning(IUnknown *pUnk, IMoniker *pmk,
  15. DWORD dwFlags, LPDWORD pdwReg);
  16. /*
  17. * CImpIOleObject interface implementation
  18. */
  19. IMPLEMENT_CONTAINED_CONSTRUCTOR(CPolyline, CImpIOleObject)
  20. IMPLEMENT_CONTAINED_DESTRUCTOR(CImpIOleObject)
  21. IMPLEMENT_CONTAINED_QUERYINTERFACE(CImpIOleObject)
  22. IMPLEMENT_CONTAINED_ADDREF(CImpIOleObject)
  23. STDMETHODIMP_(ULONG) CImpIOleObject::Release(
  24. void
  25. )
  26. {
  27. --m_cRef;
  28. #if 0
  29. // Release cached site related interfaces
  30. if (m_cRef == 0) {
  31. ReleaseInterface(m_pObj->m_pIOleClientSite);
  32. ReleaseInterface(m_pObj->m_pIOleControlSite);
  33. ReleaseInterface(m_pObj->m_pIDispatchAmbients);
  34. }
  35. #endif
  36. return m_pUnkOuter->Release();
  37. }
  38. /*
  39. * CImpIOleObject::SetClientSite
  40. * CImpIOleObject::GetClientSite
  41. *
  42. * Purpose:
  43. * Manages the IOleClientSite pointer of our container.
  44. */
  45. STDMETHODIMP CImpIOleObject::SetClientSite (LPOLECLIENTSITE pIOleClientSite)
  46. {
  47. ReleaseInterface(m_pObj->m_pIOleClientSite);
  48. ReleaseInterface(m_pObj->m_pIOleControlSite);
  49. ReleaseInterface(m_pObj->m_pIDispatchAmbients);
  50. m_pObj->m_pIOleClientSite = pIOleClientSite;
  51. if (NULL != m_pObj->m_pIOleClientSite) {
  52. HRESULT hr;
  53. LPMONIKER pmk;
  54. LPOLECONTAINER pIOleCont;
  55. m_pObj->m_pIOleClientSite->AddRef();
  56. /*
  57. * Within IRunnableObject::Run we're supposed to register
  58. * ourselves as running...however, the moniker has to come
  59. * from the container's IOleClientSite::GetMoniker. But
  60. * Run is called before SetClientSite here, so we have to
  61. * register now that we do have the client site as well
  62. * as lock the container.
  63. */
  64. hr = m_pObj->m_pIOleClientSite->GetMoniker
  65. (OLEGETMONIKER_ONLYIFTHERE, OLEWHICHMK_OBJFULL, &pmk);
  66. if (SUCCEEDED(hr)) {
  67. RegisterAsRunning(m_pUnkOuter, pmk, 0, &m_pObj->m_dwRegROT);
  68. pmk->Release();
  69. }
  70. hr = m_pObj->m_pIOleClientSite->GetContainer(&pIOleCont);
  71. if (SUCCEEDED(hr)) {
  72. m_pObj->m_fLockContainer=TRUE;
  73. pIOleCont->LockContainer(TRUE);
  74. pIOleCont->Release();
  75. }
  76. /*
  77. * Go get the container's IDispatch for ambient
  78. * properties if it has one, and initilize ourself
  79. * with those properties.
  80. */
  81. hr = m_pObj->m_pIOleClientSite->QueryInterface(IID_IDispatch
  82. , (void **)&m_pObj->m_pIDispatchAmbients);
  83. if (SUCCEEDED(hr))
  84. m_pObj->AmbientsInitialize((ULONG)INITAMBIENT_ALL);
  85. /*
  86. * Get the control site
  87. */
  88. hr = m_pObj->m_pIOleClientSite->QueryInterface(IID_IOleControlSite, (void **)&m_pObj->m_pIOleControlSite);
  89. }
  90. return NOERROR;
  91. }
  92. STDMETHODIMP CImpIOleObject::GetClientSite(LPOLECLIENTSITE *ppSite)
  93. {
  94. //Be sure to AddRef the new pointer you are giving away.
  95. *ppSite=m_pObj->m_pIOleClientSite;
  96. m_pObj->m_pIOleClientSite->AddRef();
  97. return NOERROR;
  98. }
  99. /*
  100. * CImpIOleObject::SetHostNames
  101. *
  102. * Purpose:
  103. * Provides the object with names of the container application and
  104. * the object in the container to use in object user interface.
  105. *
  106. * Parameters:
  107. * pszApp LPCOLESTR of the container application.
  108. * pszObj LPCOLESTR of some name that is useful in window
  109. * titles.
  110. *
  111. * Return Value:
  112. * HRESULT NOERROR
  113. */
  114. STDMETHODIMP CImpIOleObject::SetHostNames(LPCOLESTR /* pszApp */
  115. , LPCOLESTR /* pszObj */)
  116. {
  117. return NOERROR;
  118. }
  119. /*
  120. * CImpIOleObject::Close
  121. *
  122. * Purpose:
  123. * Forces the object to close down its user interface and unload.
  124. *
  125. * Parameters:
  126. * dwSaveOption DWORD describing the circumstances under which
  127. * the object is being saved and closed.
  128. *
  129. * Return Value:
  130. * HRESULT NOERROR or a general error value.
  131. */
  132. STDMETHODIMP CImpIOleObject::Close(DWORD dwSaveOption)
  133. {
  134. BOOL fSave=FALSE;
  135. //If object is dirty and we're asked to save, save it and close.
  136. if (OLECLOSE_SAVEIFDIRTY==dwSaveOption && m_pObj->m_fDirty)
  137. fSave=TRUE;
  138. /*
  139. * If asked to prompt, only do so if dirty, then if we get a
  140. * YES, save as usual and close. On NO, just close. On
  141. * CANCEL return OLE_E_PROMPTSAVECANCELLED.
  142. */
  143. if (OLECLOSE_PROMPTSAVE==dwSaveOption && m_pObj->m_fDirty) {
  144. UINT uRet;
  145. uRet = MessageBox(NULL, ResourceString(IDS_CLOSEPROMPT),
  146. ResourceString(IDS_CLOSECAPTION), MB_YESNOCANCEL);
  147. if (IDCANCEL==uRet)
  148. return ResultFromScode(OLE_E_PROMPTSAVECANCELLED);
  149. if (IDYES==uRet)
  150. fSave=TRUE;
  151. }
  152. if (fSave) {
  153. m_pObj->SendAdvise(OBJECTCODE_SAVEOBJECT);
  154. m_pObj->SendAdvise(OBJECTCODE_SAVED);
  155. }
  156. //We get directly here on OLECLOSE_NOSAVE.
  157. if ( m_pObj->m_fLockContainer && ( NULL != m_pObj->m_pIOleClientSite ) ) {
  158. //Match LockContainer call from SetClientSite
  159. LPOLECONTAINER pIOleCont;
  160. if (SUCCEEDED(m_pObj->m_pIOleClientSite->GetContainer(&pIOleCont))) {
  161. pIOleCont->LockContainer(FALSE);
  162. pIOleCont->Release();
  163. }
  164. }
  165. // Deactivate
  166. m_pObj->InPlaceDeactivate();
  167. // Revoke registration in ROT
  168. if (m_pObj->m_dwRegROT != 0) {
  169. IRunningObjectTable *pROT;
  170. if (!FAILED(GetRunningObjectTable(0, &pROT))) {
  171. pROT->Revoke(m_pObj->m_dwRegROT);
  172. pROT->Release();
  173. m_pObj->m_dwRegROT = 0;
  174. }
  175. }
  176. return NOERROR;
  177. }
  178. /*
  179. * CImpIOleObject::DoVerb
  180. *
  181. * Purpose:
  182. * Executes an object-defined action.
  183. *
  184. * Parameters:
  185. * iVerb LONG index of the verb to execute.
  186. * pMSG LPMSG describing the event causing the
  187. * activation.
  188. * pActiveSite LPOLECLIENTSITE to the site involved.
  189. * lIndex LONG the piece on which execution is happening.
  190. * hWndParent HWND of the window in which the object can play
  191. * in-place.
  192. * pRectPos LPRECT of the object in hWndParent where the
  193. * object can play in-place if desired.
  194. *
  195. * Return Value:
  196. * HRESULT NOERROR or a general error value.
  197. */
  198. STDMETHODIMP CImpIOleObject::DoVerb(LONG iVerb, LPMSG /* pMSG */
  199. , LPOLECLIENTSITE pActiveSite, LONG /* lIndex */, HWND /* hWndParent */
  200. , LPCRECT /* pRectPos */)
  201. {
  202. HRESULT hr;
  203. CAUUID caGUID;
  204. USES_CONVERSION
  205. switch (iVerb)
  206. {
  207. case OLEIVERB_HIDE:
  208. if (NULL != m_pObj->m_pIOleIPSite) {
  209. m_pObj->UIDeactivate();
  210. ShowWindow(m_pObj->m_pHW->Window(), SW_HIDE);
  211. }
  212. else {
  213. ShowWindow(m_pObj->m_pHW->Window(), SW_HIDE);
  214. m_pObj->SendAdvise(OBJECTCODE_HIDEWINDOW);
  215. }
  216. break;
  217. case OLEIVERB_PRIMARY:
  218. case OLEIVERB_SHOW:
  219. if (NULL != m_pObj->m_pIOleIPSite) {
  220. ShowWindow(m_pObj->m_pHW->Window(), SW_SHOW);
  221. return NOERROR; //Already active
  222. }
  223. if (m_pObj->m_fAllowInPlace) {
  224. return m_pObj->InPlaceActivate(pActiveSite ,TRUE);
  225. }
  226. return ResultFromScode(OLEOBJ_S_INVALIDVERB);
  227. break;
  228. case OLEIVERB_INPLACEACTIVATE:
  229. if (NULL != m_pObj->m_pHW) {
  230. HWND hWndHW=m_pObj->m_pHW->Window();
  231. ShowWindow(hWndHW, SW_SHOW);
  232. SetFocus(hWndHW);
  233. return NOERROR;
  234. }
  235. /*
  236. * Only inside-out supporting containers will use
  237. * this verb.
  238. */
  239. m_pObj->m_fContainerKnowsInsideOut=TRUE;
  240. m_pObj->InPlaceActivate(pActiveSite, FALSE);
  241. break;
  242. case OLEIVERB_UIACTIVATE:
  243. m_pObj->InPlaceActivate(pActiveSite, TRUE);
  244. break;
  245. case OLEIVERB_PROPERTIES:
  246. case POLYLINEVERB_PROPERTIES:
  247. /*
  248. * Let the container try first if there are
  249. * extended controls. Otherwise we'll display
  250. * our own pages.
  251. */
  252. if (NULL!=m_pObj->m_pIOleControlSite) {
  253. hr=m_pObj->m_pIOleControlSite->ShowPropertyFrame();
  254. if (NOERROR==hr)
  255. break; //All done
  256. }
  257. //Put up our property pages.
  258. hr=m_pObj->m_pImpISpecifyPP->GetPages(&caGUID);
  259. if (FAILED(hr))
  260. return FALSE;
  261. hr=OleCreatePropertyFrame(m_pObj->m_pCtrl->Window(), 10, 10
  262. , T2W(ResourceString(IDS_PROPFRM_TITLE)), 1, (IUnknown **)&m_pObj
  263. , caGUID.cElems, caGUID.pElems
  264. , LOCALE_USER_DEFAULT, 0L, NULL);
  265. //Free the GUIDs
  266. CoTaskMemFree((void *)caGUID.pElems);
  267. break;
  268. default:
  269. return ResultFromScode(OLEOBJ_S_INVALIDVERB);
  270. }
  271. return NOERROR;
  272. }
  273. /*
  274. * CImpIOleObject::GetUserClassID
  275. *
  276. * Purpose:
  277. * Used for linked objects, this returns the class ID of what end
  278. * users think they are editing.
  279. *
  280. * Parameters:
  281. * pClsID LPCLSID in which to store the CLSID.
  282. *
  283. * Return Value:
  284. * HRESULT NOERROR or a general error value.
  285. */
  286. STDMETHODIMP CImpIOleObject::GetUserClassID(LPCLSID pClsID)
  287. {
  288. /*
  289. * If you are not registered to handle data other than yourself,
  290. * then you can just return your class ID here. If you are
  291. * registered as usable from Treat-As dialogs, then you need to
  292. * return the CLSID of what you are really editing.
  293. */
  294. *pClsID=CLSID_SystemMonitor;
  295. return NOERROR;
  296. }
  297. /*
  298. * CImpIOleObject::SetExtent
  299. *
  300. * Purpose:
  301. * Sets the size of the object in HIMETRIC units.
  302. *
  303. * Parameters:
  304. * dwAspect DWORD of the aspect affected.
  305. * pszl LPSIZEL containing the new size.
  306. *
  307. * Return Value:
  308. * HRESULT NOERROR or a general error value.
  309. */
  310. STDMETHODIMP CImpIOleObject::SetExtent(
  311. DWORD dwAspect,
  312. LPSIZEL pszl )
  313. {
  314. RECT rectExt;
  315. if (dwAspect == DVASPECT_CONTENT) {
  316. // convert from HIMETRIC to device coord
  317. SetRect(&rectExt, 0, 0, pszl->cx, pszl->cy);
  318. m_pObj->RectConvertMappings(&rectExt,TRUE);
  319. // If changed and non-zero, store as new extent
  320. if ( !EqualRect ( &m_pObj->m_RectExt, &rectExt )
  321. && !IsRectEmpty( &rectExt ) ) {
  322. m_pObj->m_RectExt = rectExt;
  323. m_pObj->m_pImpIPolyline->SizeSet(&rectExt, TRUE);
  324. // Notify container of change to force metafile update
  325. //m_pObj->SendAdvise(OBJECTCODE_DATACHANGED);
  326. }
  327. }
  328. return NOERROR;
  329. }
  330. /*
  331. * CImpIOleObject::GetExtent
  332. *
  333. * Purpose:
  334. * Retrieves the size of the object in HIMETRIC units.
  335. *
  336. * Parameters:
  337. * dwAspect DWORD of the aspect requested
  338. * pszl LPSIZEL into which to store the size.
  339. *
  340. * Return Value:
  341. * HRESULT NOERROR or a general error value.
  342. */
  343. STDMETHODIMP CImpIOleObject::GetExtent(DWORD dwAspect, LPSIZEL pszl)
  344. {
  345. //Delegate directly to IViewObject2::GetExtent
  346. return m_pObj->m_pImpIViewObject->GetExtent(dwAspect, -1
  347. , NULL, pszl);
  348. }
  349. /*
  350. * CImpIOleObject::Advise
  351. * CImpIOleObject::Unadvise
  352. * CImpIOleObject::EnumAdvise
  353. *
  354. * Purpose:
  355. * Advisory connection functions.
  356. */
  357. STDMETHODIMP CImpIOleObject::Advise(
  358. LPADVISESINK pIAdviseSink,
  359. LPDWORD pdwConn
  360. )
  361. {
  362. if (NULL==m_pObj->m_pIOleAdviseHolder)
  363. {
  364. HRESULT hr;
  365. hr=CreateOleAdviseHolder(&m_pObj->m_pIOleAdviseHolder);
  366. if (FAILED(hr))
  367. return hr;
  368. }
  369. return m_pObj->m_pIOleAdviseHolder->Advise(pIAdviseSink, pdwConn);
  370. }
  371. STDMETHODIMP CImpIOleObject::Unadvise(DWORD dwConn)
  372. {
  373. if (NULL!=m_pObj->m_pIOleAdviseHolder)
  374. return m_pObj->m_pIOleAdviseHolder->Unadvise(dwConn);
  375. return ResultFromScode(E_FAIL);
  376. }
  377. STDMETHODIMP CImpIOleObject::EnumAdvise(LPENUMSTATDATA *ppEnum)
  378. {
  379. if (NULL!=m_pObj->m_pIOleAdviseHolder)
  380. return m_pObj->m_pIOleAdviseHolder->EnumAdvise(ppEnum);
  381. return ResultFromScode(E_FAIL);
  382. }
  383. /*
  384. * CImpIOleObject::SetMoniker
  385. *
  386. * Purpose:
  387. * Informs the object of its moniker or its container's moniker
  388. * depending on dwWhich.
  389. *
  390. * Parameters:
  391. * dwWhich DWORD describing whether the moniker is the
  392. * object's or the container's.
  393. * pmk LPMONIKER with the name.
  394. *
  395. * Return Value:
  396. * HRESULT NOERROR or a general error value.
  397. */
  398. STDMETHODIMP CImpIOleObject::SetMoniker(DWORD /* dwWhich */
  399. , LPMONIKER /* pmk */)
  400. {
  401. LPMONIKER pmkFull;
  402. HRESULT hr = ResultFromScode(E_FAIL);
  403. HRESULT hrTmp;
  404. LPBC pbc;
  405. if (NULL!=m_pObj->m_pIOleClientSite) {
  406. hr = m_pObj->m_pIOleClientSite->GetMoniker
  407. (OLEGETMONIKER_ONLYIFTHERE, OLEWHICHMK_OBJFULL
  408. , &pmkFull);
  409. if (SUCCEEDED(hr)) {
  410. hrTmp = CreateBindCtx(0,&pbc);
  411. if (SUCCEEDED(hrTmp)) {
  412. hrTmp = pmkFull->IsRunning(pbc, NULL, NULL);
  413. pbc->Release();
  414. if (hrTmp == NOERROR) {
  415. pmkFull->Release();
  416. return NOERROR;
  417. }
  418. }
  419. //This will revoke the old one if m_dwRegROT is nonzero.
  420. RegisterAsRunning(m_pUnkOuter, pmkFull, 0, &m_pObj->m_dwRegROT);
  421. //Inform clients of the new moniker
  422. if (NULL!=m_pObj->m_pIOleAdviseHolder)
  423. m_pObj->m_pIOleAdviseHolder->SendOnRename(pmkFull);
  424. pmkFull->Release();
  425. }
  426. }
  427. return hr;
  428. }
  429. /*
  430. * CImpIOleObject::GetMoniker
  431. *
  432. * Purpose:
  433. * Asks the object for a moniker that can later be used to
  434. * reconnect to it.
  435. *
  436. * Parameters:
  437. * dwAssign DWORD determining how to assign the moniker to
  438. * to the object.
  439. * dwWhich DWORD describing which moniker the caller wants.
  440. * ppmk LPMONIKER * into which to store the moniker.
  441. *
  442. * Return Value:
  443. * HRESULT NOERROR or a general error value.
  444. */
  445. STDMETHODIMP CImpIOleObject::GetMoniker(DWORD /* dwAssign */
  446. , DWORD /* dwWhich */, LPMONIKER *ppmk)
  447. {
  448. HRESULT hr=ResultFromScode(E_FAIL);
  449. *ppmk=NULL;
  450. /*
  451. * Since we only support embedded objects, our moniker
  452. * is always the full moniker from the contianer.
  453. */
  454. if (NULL!=m_pObj->m_pIOleClientSite)
  455. {
  456. hr=m_pObj->m_pIOleClientSite->GetMoniker
  457. (OLEGETMONIKER_ONLYIFTHERE, OLEWHICHMK_OBJFULL, ppmk);
  458. }
  459. return (NULL!=*ppmk) ? NOERROR : hr;
  460. }
  461. //Methods not implemented or trivial
  462. STDMETHODIMP CImpIOleObject::InitFromData(
  463. LPDATAOBJECT /* pIDataObject */
  464. , BOOL /* fCreation */, DWORD /* dw */)
  465. {
  466. return ResultFromScode(E_NOTIMPL);
  467. }
  468. STDMETHODIMP CImpIOleObject::GetClipboardData(DWORD /* dwReserved */
  469. , LPDATAOBJECT * /* ppIDataObj */)
  470. {
  471. return ResultFromScode(E_NOTIMPL);
  472. }
  473. STDMETHODIMP CImpIOleObject::Update(void)
  474. {
  475. return NOERROR;
  476. }
  477. STDMETHODIMP CImpIOleObject::IsUpToDate(void)
  478. {
  479. return NOERROR;
  480. }
  481. STDMETHODIMP CImpIOleObject::SetColorScheme(LPLOGPALETTE /* pLP */)
  482. {
  483. return ResultFromScode(E_NOTIMPL);
  484. }
  485. //Methods implemented using registry helper functions in OLE.
  486. STDMETHODIMP CImpIOleObject::EnumVerbs(LPENUMOLEVERB *ppEnum)
  487. {
  488. return OleRegEnumVerbs(m_pObj->m_clsID, ppEnum);
  489. }
  490. STDMETHODIMP CImpIOleObject::GetUserType(
  491. DWORD dwForm,
  492. LPOLESTR *ppszType
  493. )
  494. {
  495. return OleRegGetUserType(m_pObj->m_clsID, dwForm, ppszType);
  496. }
  497. STDMETHODIMP CImpIOleObject::GetMiscStatus(
  498. DWORD dwAspect,
  499. LPDWORD pdwStatus
  500. )
  501. {
  502. return OleRegGetMiscStatus(m_pObj->m_clsID, dwAspect, pdwStatus);
  503. }
  504. void RegisterAsRunning(
  505. IUnknown *pUnk,
  506. IMoniker *pmk,
  507. DWORD dwFlags,
  508. LPDWORD pdwReg
  509. )
  510. {
  511. IRunningObjectTable *pROT;
  512. HRESULT hr;
  513. DWORD dwReg = *pdwReg;
  514. dwReg=*pdwReg;
  515. if (FAILED(GetRunningObjectTable(0, &pROT)))
  516. return;
  517. hr = pROT->Register(dwFlags, pUnk, pmk, pdwReg);
  518. if (MK_S_MONIKERALREADYREGISTERED == GetScode(hr))
  519. {
  520. if (0 != dwReg)
  521. pROT->Revoke(dwReg);
  522. }
  523. pROT->Release();
  524. return;
  525. }