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.

1525 lines
44 KiB

  1. //+---------------------------------------------------------------------
  2. //
  3. // File: sctrl.cxx
  4. //
  5. //------------------------------------------------------------------------
  6. //[ srvr_overview
  7. /*
  8. Srvr Library Overview
  9. The Srvr library is a set of C++ base classes intended to greatly simplify
  10. the process of implementing an OLE Compound Document object DLL in C++.
  11. This library requires the O2UTIL library and and understanding of elements
  12. in that library is prerequisite to a complete understanding of these base
  13. classes. Consult documentation for the O2UTIL library.
  14. The library consists of three C++ base classes: SrvrCtrl, SrvrDV, and
  15. SrvrInPlace. An OLE Compound Document object implemented using the Srvr
  16. library is an aggregate of three subobjects -- the control, data/view
  17. and in-place subobjects. The implementations of these subobjects are C++
  18. classes that inherit from SrvrCtrl, SrvrDV, and SrvrInPlace respectively.
  19. Behaviour specific to the C.D. object type is implemented
  20. by overriding virtual methods on the base classes. The base classes are
  21. designed so that a simple but functional server can be implemented by overriding
  22. only a small number of virtual methods. Progressively more advanced servers
  23. can be implemented by deriving more virtual methods and adding support for
  24. new interfaces in the derived classes.
  25. In the following discussion, the unqualified term "object" refers to an OLE
  26. Compound Document (C.D.) object. The term "subobject" refers to a C++ object
  27. whose class inherits from one of the Srvr base classes.
  28. The data/view subobject encapsulates the persistent data of an object and the
  29. rendering of that data. This subobject supports the IDataObject, IViewObject,
  30. and the IPersist family of interfaces. These subobjects can also function
  31. independently as a data transfer object for clipboard and drag-drop operations.
  32. The control subobject manages the dynamic control of the object. This subobject
  33. supports the IOleObject interface and directs all state transitions of the object.
  34. The in-place subobject is responsible for the child window and user interface
  35. of an object while it is in-place active. The subobject supports the
  36. IOleInPlaceObject and IOleInPlaceActiveObject interfaces. This subobject is
  37. not required for objects that don't support in-place editing.
  38. The control subobject controls the aggregate and holds pointers to the data/view
  39. and inplace subobjects. It maintains the reference count for the object as a
  40. whole and delegates QueryInterfaces to the other subobjects for interfaces
  41. that it does not handle. The data/view and in-place subobjects each hold a
  42. pointer to the control subobject. They each forward their IUnknown methods
  43. to the control. When a data/view subobject is being used independently as
  44. a data-transfer object then its control pointer is NULL.
  45. For more information consult the overview sections for each of the base
  46. classes and the documentation for the base class methods.
  47. */
  48. //]
  49. //[ srvrctrl_overview
  50. /*
  51. SrvrCtrl Overview
  52. The SrvrCtrl base class implements the control aspects common to most
  53. OLE Compound Document objects. It records the state of the object and
  54. directs the state transitions. It implements the IOleObject interface.
  55. An object is in one of five possible states: passive, loaded, in-place,
  56. U.I. active, or opened. An object is passive when it is holding no
  57. resources. This is true for objects that are newly created or have
  58. been released. An object becomes loaded when it gets
  59. an IPersistXXX::Load or IPersistStorage::InitNew call and has loaded
  60. or initialized the necessary part of its persistent state. An object in
  61. the in-place state has a child window in its containers window and
  62. can receive window messages. The object (nor any of its embeddings)
  63. does not have its U.I. visible (e.g. shared menu or toolbars).
  64. A U.I. active object does have its (or one of its embeddings) U.I. visible.
  65. An open object is one that is being open-edited in a separate, top-level
  66. window.
  67. Part of implementing the control subobject of an OLE Compound Document object
  68. is implementing verbs. There are a number of standard, OLE-defined verbs
  69. and an object can add its own. Since the set of verbs is very object
  70. dependent SrvrCtrl requires a derived class to supply tables indicating
  71. the verbs that are supported. One is table of OLEVERB structures giving
  72. standard information about the verb including the verb number and name.
  73. A parallel table contains a pointer for each verb pointing to a function
  74. that implements that verb. SrvrCtrl has a set of static methods that
  75. implement the standard OLE verbs. The derived class can include these methods
  76. in its verb table. SrvrCtrl implements all the IOleObject verb-related
  77. methods using these two verb tables. The verb tables must be in order
  78. of verb number and must be contiguous (i.e. no missing verb numbers).
  79. */
  80. //]
  81. #include "headers.hxx"
  82. #pragma hdrstop
  83. //+---------------------------------------------------------------
  84. //
  85. // Member: SrvrCtrl::SrvrCtrl, protected
  86. //
  87. // Synopsis: Constructor for SrvrCtrl object
  88. //
  89. // Notes: To create a properly initialized object you must
  90. // call the Init method immediately after construction.
  91. //
  92. //---------------------------------------------------------------
  93. SrvrCtrl::SrvrCtrl(void)
  94. {
  95. DOUT(TEXT("SrvrCtrl: Constructing\r\n"));
  96. _pDV = NULL;
  97. _pInPlace = NULL;
  98. _pPrivUnkDV = NULL;
  99. _pPrivUnkIP = NULL;
  100. // site-related information
  101. _pClientSite = NULL;
  102. _pOleAdviseHolder = NULL;
  103. _pClass = NULL;
  104. _dwRegROT = 0;
  105. _lpstrCntrApp = NULL;
  106. _lpstrCntrObj = NULL;
  107. #if !defined(UNICODE) && !defined(OLE2ANSI)
  108. _lpstrCntrAppA = NULL;
  109. _lpstrCntrObjA = NULL;
  110. #endif
  111. _state = OS_PASSIVE;
  112. EnableIPB(TRUE);
  113. }
  114. //+---------------------------------------------------------------
  115. //
  116. // Member: SrvrCtrl::Init, protected
  117. //
  118. // Synopsis: Fully initializes a SrvrCtrl object
  119. //
  120. // Arguments: [pClass] -- The initialized class descriptor for the server
  121. // [pUnkOuter] -- The controlling unknown if this server is being
  122. // created as part of an aggregate; NULL otherwise
  123. //
  124. // Returns: NOERROR if successful
  125. //
  126. // Notes: The class descriptor pointer is saved in the protected _pClass
  127. // member variable where it is accessible during the lifetime
  128. // of the object.
  129. //
  130. //---------------------------------------------------------------
  131. HRESULT
  132. SrvrCtrl::Init(LPCLASSDESCRIPTOR pClass)
  133. {
  134. _pClass = pClass;
  135. return NOERROR;
  136. }
  137. //+---------------------------------------------------------------
  138. //
  139. // Member: SrvrCtrl::~SrvrCtrl, protected
  140. //
  141. // Synopsis: Destructor for the SrvrCtrl object
  142. //
  143. // Notes: The destructor is called as a result of the servers
  144. // reference count going to 0. It ensure the object
  145. // is in a passive state and releases the data/view and inplace
  146. // subobjects objects.
  147. //
  148. //---------------------------------------------------------------
  149. SrvrCtrl::~SrvrCtrl(void)
  150. {
  151. DOUT(TEXT("~~~~~SrvrCtrl::~OPCtrl\r\n"));
  152. // note: we don't have to release _pDV and _pInPlace because
  153. // we should have released them right away (standard aggregation policy)
  154. // We must release the private unknowns of those two subobjects, though.
  155. if (_pPrivUnkIP)
  156. _pPrivUnkIP->Release();
  157. if (_pPrivUnkDV)
  158. _pPrivUnkDV->Release();
  159. // free our advise holder
  160. if(_pOleAdviseHolder != NULL)
  161. _pOleAdviseHolder->Release();
  162. // release our client site
  163. TaskFreeString(_lpstrCntrApp);
  164. TaskFreeString(_lpstrCntrObj);
  165. #if !defined(UNICODE) && !defined(OLE2ANSI)
  166. TaskFreeMem(_lpstrCntrAppA);
  167. TaskFreeMem(_lpstrCntrObjA);
  168. #endif
  169. if (_pClientSite != NULL)
  170. _pClientSite->Release();
  171. DOUT(TEXT("SrvrCtrl: Destructed\r\n"));
  172. }
  173. //+---------------------------------------------------------------
  174. //
  175. // Member: SrvrCtrl::TransitionTo, public
  176. //
  177. // Synopsis: Drives the transition of the object from one state to another
  178. //
  179. // Arguments: [state] -- the desired resulting state of the object
  180. //
  181. // Returns: Success iff the transition completed successfully. On failure
  182. // the object will be in the original or some intermediate,
  183. // but consistent, state.
  184. //
  185. // Notes: There are eight direct state transitions. These are:
  186. // between the passive and loaded states, between the
  187. // loaded and inplace states, between the inplace and U.I. active
  188. // states, and between the loaded and opened states.
  189. // Each of these direct transitions has an overridable method
  190. // that effects it. The TransitionTo function implements
  191. // transitions between any two arbitrary states by calling
  192. // these direct transition methods in the proper order.
  193. //
  194. //---------------------------------------------------------------
  195. HRESULT
  196. SrvrCtrl::TransitionTo(OLE_SERVER_STATE state)
  197. {
  198. #if DBG
  199. TCHAR achTemp[256];
  200. wsprintf(achTemp,TEXT("[%d] --> [%d] SrvrCtrl::TransitionTo\n\r"),(int)_state,(int)state);
  201. DOUT(achTemp);
  202. #endif //DBG
  203. Assert(state >= OS_PASSIVE && state <= OS_OPEN);
  204. Assert(_state >= OS_PASSIVE && _state <= OS_OPEN);
  205. //
  206. // at each iteration we transition one state closer to
  207. // our destination state...
  208. //
  209. HRESULT hr = NOERROR;
  210. while (state != _state && OK(hr))
  211. {
  212. switch(_state)
  213. {
  214. case OS_PASSIVE:
  215. // from passive we can only go to loaded!
  216. if (OK(hr = PassiveToLoaded()))
  217. _state = OS_LOADED;
  218. break;
  219. case OS_LOADED:
  220. switch(state)
  221. {
  222. default:
  223. if (OK(hr = LoadedToRunning()))
  224. _state = OS_RUNNING;
  225. break;
  226. case OS_PASSIVE:
  227. if (OK(hr = LoadedToPassive()))
  228. _state = OS_PASSIVE;
  229. break;
  230. }
  231. break;
  232. case OS_RUNNING:
  233. switch(state)
  234. {
  235. default:
  236. case OS_LOADED:
  237. if (OK(hr = RunningToLoaded()))
  238. _state = OS_LOADED;
  239. break;
  240. case OS_INPLACE:
  241. case OS_UIACTIVE:
  242. if (OK(hr = RunningToInPlace()))
  243. _state = OS_INPLACE;
  244. break;
  245. case OS_OPEN:
  246. if (OK(hr = RunningToOpened()))
  247. _state = OS_OPEN;
  248. break;
  249. }
  250. break;
  251. case OS_INPLACE:
  252. switch(state)
  253. {
  254. default:
  255. if (OK(hr = InPlaceToRunning()))
  256. {
  257. //
  258. // The following handles re-entrancy cases in which
  259. // processing of this state transition caused us to
  260. // reach a state below our current target state...
  261. if(_state < OS_RUNNING)
  262. goto LExit;
  263. _state = OS_RUNNING;
  264. }
  265. break;
  266. case OS_UIACTIVE:
  267. if (OK(hr = InPlaceToUIActive()))
  268. _state = OS_UIACTIVE;
  269. break;
  270. }
  271. break;
  272. case OS_UIACTIVE:
  273. // from UIActive we can only go to inplace
  274. if (OK(hr = UIActiveToInPlace()))
  275. {
  276. //
  277. // In the course of notifying the container that we
  278. // are no longer UIActive, it is possible that we
  279. // got InPlace deactivated (or worse, Closed).
  280. // If this happened we abort our currently targeted
  281. // transition...
  282. if(_state < OS_INPLACE)
  283. goto LExit;
  284. _state = OS_INPLACE;
  285. }
  286. break;
  287. case OS_OPEN:
  288. // from Open we can only go to running
  289. if (OK(hr = OpenedToRunning()))
  290. _state = OS_RUNNING;
  291. break;
  292. }
  293. }
  294. LExit:
  295. #if DBG
  296. wsprintf(achTemp,TEXT("SrvrCtrl::TransitionTo [%d] hr = %lx\n\r"),(int)_state, hr);
  297. DOUT(achTemp);
  298. #endif //DBG
  299. return hr;
  300. }
  301. //+---------------------------------------------------------------
  302. //
  303. // Member: SrvrCtrl::PassiveToLoaded, protected
  304. //
  305. // Synopsis: Effects the direct passive to loaded state transition
  306. //
  307. // Returns: Success iff the object is in the loaded state. On failure
  308. // the object will be in a consistent passive state.
  309. //
  310. // Notes: The base class does not do any processing on this transition.
  311. //
  312. //---------------------------------------------------------------
  313. HRESULT
  314. SrvrCtrl::PassiveToLoaded(void)
  315. {
  316. return NOERROR;
  317. }
  318. //+---------------------------------------------------------------
  319. //
  320. // Member: SrvrCtrl::LoadedToRunning, protected
  321. //
  322. // Synopsis: Effects the direct loaded to running state transition
  323. //
  324. // Returns: Success if the object is running.
  325. //
  326. // Notes: This transition occurs as a result of an
  327. // IRunnableObject::Run call (TBD) and is implicit in any
  328. // DoVerb call.
  329. //
  330. //---------------------------------------------------------------
  331. HRESULT
  332. SrvrCtrl::LoadedToRunning(void)
  333. {
  334. DOUT(TEXT("SrvrCtrl::LoadedToRunning\r\n"));
  335. //
  336. // enter ourself in the Running Object Table
  337. //
  338. LPMONIKER pmk;
  339. if (OK(_pDV->GetMoniker(OLEGETMONIKER_ONLYIFTHERE, &pmk)))
  340. {
  341. RegisterAsRunning((LPUNKNOWN)this, pmk, &_dwRegROT);
  342. pmk->Release();
  343. }
  344. return NOERROR;
  345. }
  346. //+---------------------------------------------------------------
  347. //
  348. // Member: SrvrCtrl::LoadedToPassive, protected
  349. //
  350. // Synopsis: Effects the direct loaded to passive state transition
  351. //
  352. // Returns: Success if the object is loaded.
  353. //
  354. // Notes: This transition occurs as a result of an IOleObject::Close()
  355. // call.
  356. // This method sends an OnClose notification to all of our
  357. // advises.
  358. //
  359. //---------------------------------------------------------------
  360. HRESULT
  361. SrvrCtrl::LoadedToPassive(void)
  362. {
  363. DOUT(TEXT("SrvrCtrl::LoadedToPassive\r\n"));
  364. // notify our data advise holders of 'stop'
  365. _pDV->OnDataChange(ADVF_DATAONSTOP);
  366. // notify our advise holders that we have closed
  367. if (_pOleAdviseHolder != NULL)
  368. {
  369. DOUT(TEXT("SrvrCtrl::LoadedToPassive calling _pOleAdviseHolder->SendOnClose()\r\n"));
  370. _pOleAdviseHolder->SendOnClose();
  371. }
  372. // forcibly cut off remoting clients???
  373. //CoDisconnectObject((LPUNKNOWN)this, 0);
  374. //
  375. // revoke our entry in the running object table
  376. //
  377. if (_dwRegROT != 0)
  378. {
  379. DOUT(TEXT(".-.-.SrvrCtrl::RunningToLoaded calling RevokeAsRunning\r\n"));
  380. RevokeAsRunning(&_dwRegROT);
  381. _dwRegROT = 0;
  382. }
  383. DOUT(TEXT("SrvrCtrl::LoadedToPassive (returning)\r\n"));
  384. return NOERROR;
  385. }
  386. //+---------------------------------------------------------------
  387. //
  388. // Member: SrvrCtrl::RunningToLoaded, protected
  389. //
  390. // Synopsis: Effects the direct running to loaded state transition
  391. //
  392. // Returns: Success if the object is loaded.
  393. //
  394. //---------------------------------------------------------------
  395. HRESULT
  396. SrvrCtrl::RunningToLoaded(void)
  397. {
  398. DOUT(TEXT("SrvrCtrl::RunningToLoaded\r\n"));
  399. return NOERROR;
  400. }
  401. //+---------------------------------------------------------------
  402. //
  403. // Member: SrvrCtrl::RunningToOpened, protected
  404. //
  405. // Synopsis: Effects the direct running to opened state transition
  406. //
  407. // Returns: Success if the object is open-edited.
  408. //
  409. // Notes: Open-editing is not yet supported. This returns E_FAIL.
  410. //
  411. // The derived class MUST completely override this
  412. // transition to implement an open-ediing server!
  413. //
  414. //---------------------------------------------------------------
  415. HRESULT
  416. SrvrCtrl::RunningToOpened(void)
  417. {
  418. DOUT(TEXT("SrvrCtrl::RunningToOpened E_FAIL\r\n"));
  419. return E_FAIL;
  420. }
  421. //+---------------------------------------------------------------
  422. //
  423. // Member: SrvrCtrl::OpenedToRunning, protected
  424. //
  425. // Synopsis: Effects the direct opened to running state transition
  426. //
  427. // Returns: Success if the open-editing session was shut down
  428. //
  429. // Notes: This occurs as the result of a DoVerb(HIDE...)
  430. //
  431. //---------------------------------------------------------------
  432. HRESULT
  433. SrvrCtrl::OpenedToRunning(void)
  434. {
  435. // notify our container so it can un-hatch
  436. if (_pClientSite != NULL)
  437. _pClientSite->OnShowWindow(FALSE);
  438. return NOERROR;
  439. }
  440. //+---------------------------------------------------------------
  441. //
  442. // Member: SrvrCtrl::RunningToInPlace, protected
  443. //
  444. // Synopsis: Effects the direct Running to inplace state transition
  445. //
  446. // Returns: Success iff the object is in the inplace state. On failure
  447. // the object will be in a consistent Running state.
  448. //
  449. // Notes: This transition invokes the ActivateInPlace method on the
  450. // inplace subobject of the server, if there is one. Containers
  451. // will typically override this method in order to additionally
  452. // inplace activate any inside-out embeddings that are visible.
  453. // If the server does not support in-place
  454. // activation then this method will return E_UNEXPECTED.
  455. //
  456. //---------------------------------------------------------------
  457. HRESULT
  458. SrvrCtrl::RunningToInPlace(void)
  459. {
  460. if (_pInPlace == NULL)
  461. {
  462. DOUT(TEXT("SrvrCtrl::RunningToInPlace E_FAIL\r\n"));
  463. return E_FAIL;
  464. }
  465. return _pInPlace->ActivateInPlace(_pClientSite);
  466. }
  467. //+---------------------------------------------------------------
  468. //
  469. // Member: SrvrCtrl::InPlaceToRunning, protected
  470. //
  471. // Synopsis: Effects the direct inplace to Running state transition
  472. //
  473. // Returns: Success under all but catastrophic circumstances.
  474. //
  475. // Notes: This transition invokes the DeactivateInPlace method on the
  476. // inplace subobject of the server, if there is one. Containers
  477. // will typically override this method in order to additionally
  478. // inplace deactivate any inplace-active embeddings.
  479. // If the server does not support in-place activation then
  480. // this method will never be called.
  481. // This method is called as the result of a DoVerb(HIDE...)
  482. //
  483. //---------------------------------------------------------------
  484. HRESULT
  485. SrvrCtrl::InPlaceToRunning(void)
  486. {
  487. Assert(_pInPlace != NULL);
  488. return _pInPlace->DeactivateInPlace();
  489. }
  490. //+---------------------------------------------------------------
  491. //
  492. // Member: SrvrCtrl::InPlaceToUIActive, protected
  493. //
  494. // Synopsis: Effects the direct inplace to U.I. active state transition
  495. //
  496. // Returns: Success iff the object is in the U.I. active state. On failure
  497. // the object will be in a consistent inplace state.
  498. //
  499. // Notes: This transition invokes the ActivateUI methods on the inplace
  500. // subobject of the server.
  501. // If the server does not support in-place activation then
  502. // this method will never be called.
  503. //
  504. //---------------------------------------------------------------
  505. HRESULT
  506. SrvrCtrl::InPlaceToUIActive(void)
  507. {
  508. Assert(_pInPlace != NULL);
  509. return _pInPlace->ActivateUI();
  510. }
  511. //+---------------------------------------------------------------
  512. //
  513. // Member: SrvrCtrl::UIActiveToInPlace, protected
  514. //
  515. // Synopsis: Effects the direct U.I. Active to inplace state transition
  516. //
  517. // Returns: Success under all but catastrophic circumstances.
  518. //
  519. // Notes: This transition invokes the DeactivateUI methods
  520. // on the inplace subobject of the server. Containers
  521. // will typically override this method in order to possibly
  522. // U.I. deactivate a U.I. active embedding.
  523. // If the server does not support in-place activation then
  524. // this method will never be called.
  525. //
  526. //---------------------------------------------------------------
  527. HRESULT
  528. SrvrCtrl::UIActiveToInPlace(void)
  529. {
  530. Assert(_pInPlace != NULL);
  531. return _pInPlace->DeactivateUI();
  532. }
  533. //+---------------------------------------------------------------
  534. //
  535. // Member: SrvrCtrl::OnSave, public
  536. //
  537. // Synopsis: Raises the OnSave advise to any registered advises
  538. //
  539. // Notes: This method is called by the data/view subobject upon
  540. // successful completion of a save operation.
  541. //
  542. //---------------------------------------------------------------
  543. void
  544. SrvrCtrl::OnSave(void)
  545. {
  546. if (_pOleAdviseHolder != NULL)
  547. _pOleAdviseHolder->SendOnSave();
  548. }
  549. //+---------------------------------------------------------------
  550. //
  551. // Member: SrvrCtrl::DoShow, public
  552. //
  553. // Synopsis: Implementation of the standard verb OLEIVERB_SHOW
  554. //
  555. // Arguments: [pv] -- pointer to a SrvrCntrl object.
  556. // All other parameters are the same as the IOleObject::DoVerb
  557. // method.
  558. //
  559. // Returns: Success if the verb was successfully executed
  560. //
  561. // Notes: This and the other static Do functions are provided for
  562. // use in the server's verb table. This verb results in
  563. // a ShowObject call on our container and a transition
  564. // to the U.I. active state
  565. //
  566. //---------------------------------------------------------------
  567. HRESULT
  568. SrvrCtrl::DoShow(LPVOID pv,
  569. LONG iVerb,
  570. LPMSG lpmsg,
  571. LPOLECLIENTSITE pActiveSite,
  572. LONG lindex,
  573. HWND hwndParent,
  574. LPCRECT lprcPosRect)
  575. {
  576. LPSRVRCTRL pCtrl = (LPSRVRCTRL)pv;
  577. HRESULT hr = NOERROR;
  578. #if DBG
  579. TCHAR achTemp[256];
  580. wsprintf(achTemp,TEXT("SrvrCtrl::DoShow [%d]\n\r"),(int)pCtrl->State());
  581. DOUT(achTemp);
  582. #endif
  583. if (pCtrl->_pClientSite != NULL)
  584. {
  585. pCtrl->_pClientSite->ShowObject();
  586. if(pCtrl->State() == OS_OPEN)
  587. {
  588. HWND hwnd = NULL;
  589. if(pCtrl->_pInPlace)
  590. pCtrl->_pInPlace->GetWindow(&hwnd);
  591. if(hwnd != NULL)
  592. SetForegroundWindow(hwnd);
  593. }
  594. else
  595. {
  596. hr = pCtrl->TransitionTo(OS_UIACTIVE);
  597. }
  598. }
  599. if (!OK(hr))
  600. {
  601. // the default action is OPEN...
  602. hr = pCtrl->TransitionTo(OS_OPEN);
  603. }
  604. // if the verb was unknown then return Unknown Verb error.
  605. if (OK(hr) && iVerb != OLEIVERB_PRIMARY && iVerb != OLEIVERB_SHOW)
  606. {
  607. DOUT(TEXT("SrvrCtrl::DoShow returning OLEOBJ_S_INVALIDVERB\r\n"));
  608. hr = OLEOBJ_S_INVALIDVERB;
  609. }
  610. return hr;
  611. }
  612. //+---------------------------------------------------------------
  613. //
  614. // Member: SrvrCtrl::DoOpen, public
  615. //
  616. // Synopsis: Implementation of the standard verb OLEIVERB_OPEN.
  617. // This verb results in a transition to the open state.
  618. //
  619. //---------------------------------------------------------------
  620. HRESULT
  621. SrvrCtrl::DoOpen(LPVOID pv,
  622. LONG iVerb,
  623. LPMSG lpmsg,
  624. LPOLECLIENTSITE pActiveSite,
  625. LONG lindex,
  626. HWND hwndParent,
  627. LPCRECT lprcPosRect)
  628. {
  629. DOUT(TEXT("SrvrCtrl::DoOpen\r\n"));
  630. LPSRVRCTRL pCtrl = (LPSRVRCTRL)pv;
  631. if(pCtrl->State() == OS_OPEN)
  632. {
  633. HWND hwnd = NULL;
  634. if(pCtrl->_pInPlace)
  635. pCtrl->_pInPlace->GetWindow(&hwnd);
  636. if(hwnd != NULL)
  637. SetForegroundWindow(hwnd);
  638. }
  639. return pCtrl->TransitionTo(OS_OPEN);
  640. }
  641. //+---------------------------------------------------------------
  642. //
  643. // Member: SrvrCtrl::DoHide, public
  644. //
  645. // Synopsis: Implementation of the standard verb OLEIVERB_HIDE
  646. // This verb results in a transition to the Running state.
  647. //
  648. //---------------------------------------------------------------
  649. HRESULT
  650. SrvrCtrl::DoHide(LPVOID pv,
  651. LONG iVerb,
  652. LPMSG lpmsg,
  653. LPOLECLIENTSITE pActiveSite,
  654. LONG lindex,
  655. HWND hwndParent,
  656. LPCRECT lprcPosRect)
  657. {
  658. DOUT(TEXT("SrvrCtrl::DoHide\r\n"));
  659. LPSRVRCTRL pCtrl = (LPSRVRCTRL)pv;
  660. if(pCtrl != NULL)
  661. {
  662. //jyg: ntbug 17327
  663. // if(pCtrl->_state == OS_LOADED || pCtrl->_state == OS_PASSIVE)
  664. // return pCtrl->TransitionTo(OS_PASSIVE);
  665. // else
  666. return pCtrl->TransitionTo(OS_RUNNING);
  667. }
  668. else
  669. {
  670. DOUT(TEXT("SrvrCtrl::DoHide E_INVALIDARG\r\n"));
  671. return E_INVALIDARG;
  672. }
  673. }
  674. //+---------------------------------------------------------------
  675. //
  676. // Member: SrvrCtrl::DoUIActivate, public
  677. //
  678. // Synopsis: Implementation of the standard verb OLEIVERB_UIACTIVATE
  679. // This verb results in a transition to the U.I. active state.
  680. //
  681. //---------------------------------------------------------------
  682. HRESULT
  683. SrvrCtrl::DoUIActivate(LPVOID pv,
  684. LONG iVerb,
  685. LPMSG lpmsg,
  686. LPOLECLIENTSITE pActiveSite,
  687. LONG lindex,
  688. HWND hwndParent,
  689. LPCRECT lprcPosRect)
  690. {
  691. LPSRVRCTRL pCtrl = (LPSRVRCTRL)pv;
  692. HRESULT hr = pCtrl->TransitionTo(OS_UIACTIVE);
  693. if(OK(hr) && (lpmsg != NULL))
  694. {
  695. PostMessage(pCtrl->_pInPlace->WindowHandle(),
  696. lpmsg->message,
  697. lpmsg->wParam,
  698. lpmsg->lParam);
  699. }
  700. return hr;
  701. }
  702. //+---------------------------------------------------------------
  703. //
  704. // Member: SrvrCtrl::DoInPlaceActivate, public
  705. //
  706. // Synopsis: Implementation of the standard verb OLEIVERB_INPLACEACTIVATE
  707. // This verb results in a transition to the inplace state.
  708. //
  709. //---------------------------------------------------------------
  710. HRESULT
  711. SrvrCtrl::DoInPlaceActivate(LPVOID pv,
  712. LONG iVerb,
  713. LPMSG lpmsg,
  714. LPOLECLIENTSITE pActiveSite,
  715. LONG lindex,
  716. HWND hwndParent,
  717. LPCRECT lprcPosRect)
  718. {
  719. LPSRVRCTRL pCtrl = (LPSRVRCTRL)pv;
  720. HRESULT hr = pCtrl->TransitionTo(OS_INPLACE);
  721. if(OK(hr) && (lpmsg != NULL))
  722. {
  723. PostMessage(pCtrl->_pInPlace->WindowHandle(),
  724. lpmsg->message,
  725. lpmsg->wParam,
  726. lpmsg->lParam);
  727. }
  728. return hr;
  729. }
  730. //+---------------------------------------------------------------
  731. //
  732. // Member: SrvrCtrl::SetClientSite, public
  733. //
  734. // Synopsis: Method of IOleObject interface
  735. //
  736. // Notes: This method saves the client site pointer in the
  737. // _pClientSite member variable.
  738. //
  739. // We never fail!
  740. //
  741. //---------------------------------------------------------------
  742. STDMETHODIMP
  743. SrvrCtrl::SetClientSite(LPOLECLIENTSITE pClientSite)
  744. {
  745. //
  746. // if we already have a client site then release it
  747. //
  748. if (_pClientSite != NULL)
  749. _pClientSite->Release();
  750. //
  751. // if there is a new client site then hold on to it
  752. //
  753. _pClientSite = pClientSite;
  754. if (_pClientSite != NULL)
  755. _pClientSite->AddRef();
  756. return NOERROR;
  757. }
  758. //+---------------------------------------------------------------
  759. //
  760. // Member: SrvrCtrl::GetClientSite
  761. //
  762. // Synopsis: Method of IOleObject interface
  763. //
  764. //---------------------------------------------------------------
  765. STDMETHODIMP
  766. SrvrCtrl::GetClientSite(LPOLECLIENTSITE FAR* ppClientSite)
  767. {
  768. if (ppClientSite == NULL)
  769. {
  770. DOUT(TEXT("SrvrCtrl::GetClientSite E_INVALIDARG\r\n"));
  771. return E_INVALIDARG;
  772. }
  773. *ppClientSite = NULL; // set out params to NULL
  774. //
  775. // if we have a client site then return it, but addref it first.
  776. //
  777. if (_pClientSite != NULL)
  778. (*ppClientSite = _pClientSite)->AddRef();
  779. return NOERROR;
  780. }
  781. //+---------------------------------------------------------------
  782. //
  783. // Member: SrvrCtrl::SetHostNames
  784. //
  785. // Synopsis: Method of IOleObject interface
  786. //
  787. // Notes: This method saves copies of the container-related strings
  788. // in the _lpstrCntrApp and _lpstrCntrObj member variables.
  789. //
  790. // We never fail!
  791. //
  792. //---------------------------------------------------------------
  793. STDMETHODIMP
  794. SrvrCtrl::SetHostNames(LPCOLESTR lpstrCntrApp, LPCOLESTR lpstrCntrObj)
  795. {
  796. // free any strings we are holding on to
  797. if (_lpstrCntrApp != NULL)
  798. {
  799. TaskFreeString(_lpstrCntrApp);
  800. _lpstrCntrApp = NULL;
  801. #if !defined(UNICODE) && !defined(OLE2ANSI)
  802. TaskFreeMem(_lpstrCntrAppA);
  803. _lpstrCntrAppA = NULL;
  804. #endif
  805. }
  806. if (_lpstrCntrObj != NULL)
  807. {
  808. TaskFreeString(_lpstrCntrObj);
  809. _lpstrCntrObj = NULL;
  810. #if !defined(UNICODE) && !defined(OLE2ANSI)
  811. TaskFreeMem(_lpstrCntrObjA);
  812. _lpstrCntrObjA = NULL;
  813. #endif
  814. }
  815. // make copies of the new strings and hold on
  816. TaskAllocString(lpstrCntrApp, &_lpstrCntrApp);
  817. TaskAllocString(lpstrCntrObj, &_lpstrCntrObj);
  818. #if !defined(UNICODE) && !defined(OLE2ANSI)
  819. _lpstrCntrAppA = ConvertOLESTRToMB(_lpstrCntrApp, -1);
  820. _lpstrCntrObjA = ConvertOLESTRToMB(_lpstrCntrObj, -1);
  821. #endif
  822. return NOERROR;
  823. }
  824. //+---------------------------------------------------------------
  825. //
  826. // Member: SrvrCtrl::Close
  827. //
  828. // Synopsis: Method of IOleObject interface
  829. //
  830. // Notes: This method ensures the object is in the loaded
  831. // (not passive!) state.
  832. //
  833. //---------------------------------------------------------------
  834. STDMETHODIMP
  835. SrvrCtrl::Close(DWORD dwSaveOption)
  836. {
  837. HRESULT hr = NOERROR;
  838. // if our object is dirty then we should save it, depending on the
  839. // save options
  840. if (_pClientSite != NULL && NOERROR == _pDV->IsDirty())
  841. {
  842. BOOL fSave;
  843. switch(dwSaveOption)
  844. {
  845. case OLECLOSE_SAVEIFDIRTY:
  846. fSave = TRUE;
  847. break;
  848. case OLECLOSE_NOSAVE:
  849. fSave = FALSE;
  850. break;
  851. case OLECLOSE_PROMPTSAVE:
  852. {
  853. // put up a message box asking the user if they want to update
  854. // the container
  855. LPOLESTR lpstrObj =
  856. _pDV->GetMonikerDisplayName(OLEGETMONIKER_ONLYIFTHERE);
  857. if (lpstrObj == NULL)
  858. {
  859. lpstrObj = _pClass->_szUserClassType[USERCLASSTYPE_FULL];
  860. }
  861. int i = IDYES;
  862. #if 0
  863. #pragma message("Localizable string here!")
  864. int i = MessageBox(NULL,
  865. TEXT("Object has changed. Update?"),
  866. lpstrObj,
  867. MB_YESNOCANCEL | MB_ICONQUESTION);
  868. #endif
  869. if (IDCANCEL == i)
  870. {
  871. return OLE_E_PROMPTSAVECANCELLED;
  872. }
  873. fSave = (IDYES == i);
  874. }
  875. break;
  876. default:
  877. DOUT(TEXT("SrvrCtrl::Close E_INVALIDARG\r\n"));
  878. return E_INVALIDARG;
  879. }
  880. if (fSave)
  881. hr = _pClientSite->SaveObject();
  882. }
  883. // Ensure that we do not loose any SaveObject() failure.
  884. if (SUCCEEDED (hr))
  885. hr = TransitionTo(OS_PASSIVE);
  886. else
  887. (void) TransitionTo(OS_PASSIVE);
  888. return hr;
  889. }
  890. //+---------------------------------------------------------------
  891. //
  892. // Member: SrvrCtrl::SetMoniker
  893. //
  894. // Synopsis: Method of IOleObject interface
  895. //
  896. // Notes: This method notifies our data/view subobject of our new
  897. // moniker. It also registers us in the running object
  898. // table and sends an OnRename notification to all registered
  899. // advises.
  900. //
  901. //---------------------------------------------------------------
  902. STDMETHODIMP
  903. SrvrCtrl::SetMoniker(DWORD dwWhichMoniker, LPMONIKER pmk)
  904. {
  905. // our moniker has changed so revoke our entry in the running object table
  906. if (_dwRegROT != 0)
  907. {
  908. RevokeAsRunning(&_dwRegROT);
  909. }
  910. //
  911. // insure that we have a full moniker to register in the ROT
  912. // if we have a full moniker, then go with it
  913. // otherwise ask our client site for a full moniker
  914. //
  915. HRESULT hr = NOERROR;
  916. LPMONIKER pmkFull = NULL;
  917. if (dwWhichMoniker == OLEWHICHMK_OBJFULL)
  918. {
  919. if((pmkFull = pmk) != NULL)
  920. pmkFull->AddRef();
  921. }
  922. else
  923. {
  924. if (_pClientSite == NULL)
  925. {
  926. DOUT(TEXT("SrvrCtrl::SetMoniker E_FAIL\r\n"));
  927. hr = E_FAIL;
  928. }
  929. else
  930. {
  931. hr = _pClientSite->GetMoniker(OLEGETMONIKER_ONLYIFTHERE,
  932. OLEWHICHMK_OBJFULL,
  933. &pmkFull);
  934. }
  935. }
  936. if (OK(hr))
  937. {
  938. // stow the moniker away in our data object
  939. _pDV->SetMoniker(pmkFull);
  940. if(pmkFull != NULL)
  941. {
  942. // register ourself in the running object table
  943. // NOTE: if we had native data items that weren't embeddings
  944. // but could be pseudo-objects then we would also register a
  945. // wildcard moniker
  946. //
  947. RegisterAsRunning((LPUNKNOWN)this, pmkFull, &_dwRegROT);
  948. // notify our advise holders that we have been renamed!
  949. if (_pOleAdviseHolder != NULL)
  950. {
  951. _pOleAdviseHolder->SendOnRename(pmkFull);
  952. }
  953. pmkFull->Release();
  954. }
  955. else
  956. {
  957. RevokeAsRunning(&_dwRegROT);
  958. }
  959. }
  960. return hr;
  961. }
  962. //+---------------------------------------------------------------
  963. //
  964. // Member: SrvrCtrl::GetMoniker
  965. //
  966. // Synopsis: Method of IOleObject interface
  967. //
  968. // Notes: This method forwards the request to our client site
  969. //
  970. //---------------------------------------------------------------
  971. STDMETHODIMP
  972. SrvrCtrl::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, LPMONIKER FAR* ppmk)
  973. {
  974. if (ppmk == NULL)
  975. {
  976. DOUT(TEXT("SrvrCtrl::GetMoniker E_INVALIDARG\r\n"));
  977. return E_INVALIDARG;
  978. }
  979. *ppmk = NULL; // set out parameters to NULL
  980. // get the requested moniker from our client site
  981. HRESULT hr;
  982. if (_pClientSite == NULL)
  983. {
  984. DOUT(TEXT("SrvrCtrl::GetMoniker MK_E_UNAVAILABLE\r\n"));
  985. hr = MK_E_UNAVAILABLE;
  986. }
  987. else
  988. hr = _pClientSite->GetMoniker(dwAssign, dwWhichMoniker, ppmk);
  989. return hr;
  990. }
  991. //+---------------------------------------------------------------
  992. //
  993. // Member: SrvrCtrl::InitFromData
  994. //
  995. // Synopsis: Method of IOleObject interface
  996. //
  997. // Notes: This method returns S_FALSE indicating InitFromData
  998. // is not supported. Servers that wish to support initialization
  999. // from a selection should override this function.
  1000. //
  1001. //---------------------------------------------------------------
  1002. STDMETHODIMP
  1003. SrvrCtrl::InitFromData(LPDATAOBJECT pDataObject,
  1004. BOOL fCreation,
  1005. DWORD dwReserved)
  1006. {
  1007. return S_FALSE;
  1008. }
  1009. //+---------------------------------------------------------------
  1010. //
  1011. // Member: SrvrCtrl::GetClipboardData
  1012. //
  1013. // Synopsis: Method of IOleObject interface
  1014. //
  1015. // Notes: This method uses the GetClipboardCopy method on our
  1016. // data/view subobject to obtain a data transfer object
  1017. // representing a snapshot of our compound document object.
  1018. //
  1019. // This is considered an exotic, and OPTIONAL method to
  1020. // implement. It was intended for programatic access
  1021. // (bypassing the clipboard), and will probably never
  1022. // be used...
  1023. //
  1024. //---------------------------------------------------------------
  1025. STDMETHODIMP
  1026. SrvrCtrl::GetClipboardData(DWORD dwReserved, LPDATAOBJECT FAR* ppDataObject)
  1027. {
  1028. if (ppDataObject == NULL)
  1029. {
  1030. DOUT(TEXT("SrvrCtrl::GetClipboardData E_INVALIDARG\r\n"));
  1031. return E_INVALIDARG;
  1032. }
  1033. *ppDataObject = NULL; // set out params to NULL
  1034. // create a new data object initialized from our own data object
  1035. LPSRVRDV pDV = NULL;
  1036. HRESULT hr;
  1037. if (OK(hr = _pDV->GetClipboardCopy(&pDV)))
  1038. {
  1039. *ppDataObject = (LPDATAOBJECT)pDV;
  1040. }
  1041. return hr;
  1042. }
  1043. //+---------------------------------------------------------------
  1044. //
  1045. // Member: SrvrCtrl::DoVerb
  1046. //
  1047. // Synopsis: Method of IOleObject interface
  1048. //
  1049. // Notes: This method locates the requested verb in the servers
  1050. // verb table and calls the associated verb function.
  1051. // If the verb is not found then the first (at index 0) verb in
  1052. // the verb table is called. This should be the primary verb
  1053. // with verb number 0.
  1054. //
  1055. //---------------------------------------------------------------
  1056. STDMETHODIMP
  1057. SrvrCtrl::DoVerb(LONG iVerb,
  1058. LPMSG lpmsg,
  1059. LPOLECLIENTSITE pActiveSite,
  1060. LONG lindex,
  1061. HWND hwndParent,
  1062. LPCRECT lprcPosRect)
  1063. {
  1064. //
  1065. // All DoVerbs make an implicit transition to the running state if
  1066. // the object is not already running...
  1067. //
  1068. HRESULT hr = NOERROR;
  1069. if (_state < OS_RUNNING)
  1070. hr = TransitionTo(OS_RUNNING);
  1071. if (OK(hr))
  1072. {
  1073. //
  1074. // find the verb in the verb table. if it is not there then default
  1075. // to the 0th entry in the table (should be primary verb)
  1076. //
  1077. for (int i = 0; i < _pClass->_cVerbTable; i++)
  1078. {
  1079. if (iVerb == _pClass->_pVerbTable[i].lVerb)
  1080. {
  1081. break;
  1082. }
  1083. }
  1084. if (i >= _pClass->_cVerbTable)
  1085. {
  1086. i = 0;
  1087. }
  1088. // dispatch the verb
  1089. hr = (*_pVerbFuncs[i])(this,
  1090. iVerb,
  1091. lpmsg,
  1092. pActiveSite,
  1093. lindex,
  1094. hwndParent,
  1095. lprcPosRect);
  1096. }
  1097. return hr;
  1098. }
  1099. //+---------------------------------------------------------------
  1100. //
  1101. // Member: SrvrCtrl::EnumVerbs
  1102. //
  1103. // Synopsis: Method of IOleObject interface
  1104. //
  1105. // Notes: This method produces an enumerator over the server's
  1106. // verb table.
  1107. //
  1108. //---------------------------------------------------------------
  1109. STDMETHODIMP
  1110. SrvrCtrl::EnumVerbs(LPENUMOLEVERB FAR* ppenum)
  1111. {
  1112. if (ppenum == NULL)
  1113. {
  1114. DOUT(TEXT("SrvrCtrl::EnumVerbs E_INVALIDARG\r\n"));
  1115. return E_INVALIDARG;
  1116. }
  1117. *ppenum = NULL;
  1118. //return OLE_S_USEREG;
  1119. return CreateOLEVERBEnum(_pClass->_pVerbTable, _pClass->_cVerbTable, ppenum);
  1120. }
  1121. //+---------------------------------------------------------------
  1122. //
  1123. // Member: SrvrCtrl::Update
  1124. //
  1125. // Synopsis: Method of IOleObject interface
  1126. //
  1127. // Notes: This method returns NOERROR indicating that the update was
  1128. // successful. Containers will wish to override this function
  1129. // in order to recursively pass the function on to all embeddings.
  1130. //
  1131. //---------------------------------------------------------------
  1132. STDMETHODIMP
  1133. SrvrCtrl::Update(void)
  1134. {
  1135. return NOERROR;
  1136. }
  1137. //+---------------------------------------------------------------
  1138. //
  1139. // Member: SrvrCtrl::IsUpToDate
  1140. //
  1141. // Synopsis: Method of IOleObject interface
  1142. //
  1143. // Notes: This method returns NOERROR indicating that the object is
  1144. // up to date. Containers will wish to override this function
  1145. // in order to recursively pass the function on to all embeddings.
  1146. //
  1147. //---------------------------------------------------------------
  1148. STDMETHODIMP
  1149. SrvrCtrl::IsUpToDate(void)
  1150. {
  1151. return NOERROR;
  1152. }
  1153. //+---------------------------------------------------------------
  1154. //
  1155. // Member: SrvrCtrl::GetUserClassID
  1156. //
  1157. // Synopsis: Method of IOleObject interface
  1158. //
  1159. // Notes: This method supplies the class id from the server's
  1160. // CLASSDESCRIPTOR structure
  1161. //
  1162. //---------------------------------------------------------------
  1163. STDMETHODIMP
  1164. SrvrCtrl::GetUserClassID(CLSID FAR* pClsid)
  1165. {
  1166. if (pClsid == NULL)
  1167. {
  1168. DOUT(TEXT("SrvrCtrl::GetUserClassID E_INVALIDARG\r\n"));
  1169. return E_INVALIDARG;
  1170. }
  1171. *pClsid = _pClass->_clsid;
  1172. return NOERROR;
  1173. }
  1174. //+---------------------------------------------------------------
  1175. //
  1176. // Member: SrvrCtrl::GetUserType
  1177. //
  1178. // Synopsis: Method of IOleObject interface
  1179. //
  1180. // Notes: This method supplies the user type string from the server's
  1181. // CLASSDESCRIPTOR structure
  1182. //
  1183. //---------------------------------------------------------------
  1184. STDMETHODIMP
  1185. SrvrCtrl::GetUserType(DWORD dwFormOfType, LPOLESTR FAR* plpstr)
  1186. {
  1187. if (plpstr == NULL || dwFormOfType < 1 || dwFormOfType > 3)
  1188. {
  1189. DOUT(TEXT("SrvrCtrl::GetUserType E_INVALIDARG\r\n"));
  1190. return E_INVALIDARG;
  1191. }
  1192. return TaskAllocString(_pClass->_szUserClassType[dwFormOfType], plpstr);
  1193. }
  1194. //+---------------------------------------------------------------
  1195. //
  1196. // Member: SrvrCtrl::SetExtent
  1197. //
  1198. // Synopsis: Method of IOleObject interface
  1199. //
  1200. // Notes: This method is forwarded to the SetExtent method on
  1201. // the data/view subobject.
  1202. //
  1203. //---------------------------------------------------------------
  1204. STDMETHODIMP
  1205. SrvrCtrl::SetExtent(DWORD dwDrawAspect, LPSIZEL lpsizel)
  1206. {
  1207. if (lpsizel == NULL)
  1208. {
  1209. DOUT(TEXT("SrvrCtrl::SetExtent E_INVALIDARG\r\n"));
  1210. return E_INVALIDARG;
  1211. }
  1212. return _pDV->SetExtent(dwDrawAspect, *lpsizel);
  1213. }
  1214. //+---------------------------------------------------------------
  1215. //
  1216. // Member: SrvrCtrl::GetExtent
  1217. //
  1218. // Synopsis: Method of IOleObject interface
  1219. //
  1220. // Notes: This method is forwarded to the SetExtent method on
  1221. // the data/view subobject.
  1222. //
  1223. //---------------------------------------------------------------
  1224. STDMETHODIMP
  1225. SrvrCtrl::GetExtent(DWORD dwDrawAspect, LPSIZEL lpsizel)
  1226. {
  1227. if (lpsizel == NULL)
  1228. {
  1229. DOUT(TEXT("SrvrCtrl::GetExtent E_INVALIDARG\r\n"));
  1230. return E_INVALIDARG;
  1231. }
  1232. return _pDV->GetExtent(dwDrawAspect, lpsizel);
  1233. }
  1234. //+---------------------------------------------------------------
  1235. //
  1236. // Member: SrvrCtrl::Advise
  1237. //
  1238. // Synopsis: Method of IOleObject interface
  1239. //
  1240. // Notes: This method is implemented using the standard
  1241. // OLE advise holder.
  1242. //
  1243. //---------------------------------------------------------------
  1244. STDMETHODIMP
  1245. SrvrCtrl::Advise(IAdviseSink FAR* pAdvSink, DWORD FAR* pdwConnection)
  1246. {
  1247. if (pdwConnection == NULL)
  1248. {
  1249. DOUT(TEXT("SrvrCtrl::Advise E_INVALIDARG\r\n"));
  1250. return E_INVALIDARG;
  1251. }
  1252. *pdwConnection = NULL; // set out params to NULL
  1253. HRESULT hr = NOERROR;
  1254. if (_pOleAdviseHolder == NULL)
  1255. hr = CreateOleAdviseHolder(&_pOleAdviseHolder);
  1256. if (OK(hr))
  1257. hr = _pOleAdviseHolder->Advise(pAdvSink, pdwConnection);
  1258. return hr;
  1259. }
  1260. //+---------------------------------------------------------------
  1261. //
  1262. // Member: SrvrCtrl::Unadvise
  1263. //
  1264. // Synopsis: Method of IOleObject interface
  1265. //
  1266. // Notes: This method is implemented using the standard
  1267. // OLE advise holder.
  1268. //
  1269. //---------------------------------------------------------------
  1270. STDMETHODIMP
  1271. SrvrCtrl::Unadvise(DWORD dwConnection)
  1272. {
  1273. if (_pOleAdviseHolder == NULL)
  1274. return NOERROR;
  1275. return _pOleAdviseHolder->Unadvise(dwConnection);
  1276. }
  1277. //+---------------------------------------------------------------
  1278. //
  1279. // Member: SrvrCtrl::EnumAdvise
  1280. //
  1281. // Synopsis: Method of IOleObject interface
  1282. //
  1283. // Notes: This method is implemented using the standard
  1284. // OLE advise holder.
  1285. //
  1286. //---------------------------------------------------------------
  1287. STDMETHODIMP
  1288. SrvrCtrl::EnumAdvise(LPENUMSTATDATA FAR* ppenumAdvise)
  1289. {
  1290. if (ppenumAdvise == NULL)
  1291. {
  1292. DOUT(TEXT("SrvrCtrl::EnumAdvise E_INVALIDARG\r\n"));
  1293. return E_INVALIDARG;
  1294. }
  1295. HRESULT hr;
  1296. if (_pOleAdviseHolder == NULL)
  1297. {
  1298. *ppenumAdvise = NULL;
  1299. hr = NOERROR;
  1300. }
  1301. else
  1302. {
  1303. hr = _pOleAdviseHolder->EnumAdvise(ppenumAdvise);
  1304. }
  1305. return hr;
  1306. }
  1307. //+---------------------------------------------------------------
  1308. //
  1309. // Member: SrvrCtrl::GetMiscStatus
  1310. //
  1311. // Synopsis: Method of IOleObject interface
  1312. //
  1313. // Notes: This method supplies the misc status flags from the server's
  1314. // CLASSDESCRIPTOR structure
  1315. //
  1316. //---------------------------------------------------------------
  1317. STDMETHODIMP
  1318. SrvrCtrl::GetMiscStatus(DWORD dwAspect, DWORD FAR* pdwStatus)
  1319. {
  1320. if (pdwStatus == NULL)
  1321. {
  1322. DOUT(TEXT("SrvrCtrl::GetMiscStatus E_INVALIDARG\r\n"));
  1323. return E_INVALIDARG;
  1324. }
  1325. *pdwStatus = _pClass->_dwMiscStatus;
  1326. return NOERROR;
  1327. }
  1328. //+---------------------------------------------------------------
  1329. //
  1330. // Member: SrvrCtrl::SetColorScheme
  1331. //
  1332. // Synopsis: Method of IOleObject interface
  1333. //
  1334. // Notes: Servers should override this method if they are
  1335. // interested in the palette.
  1336. //
  1337. //---------------------------------------------------------------
  1338. STDMETHODIMP
  1339. SrvrCtrl::SetColorScheme(LPLOGPALETTE lpLogpal)
  1340. {
  1341. DOUT(TEXT("SrvrCtrl::SetColorScheme E_NOTIMPL\r\n"));
  1342. return E_NOTIMPL; //will we ever?
  1343. }