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.

1997 lines
57 KiB

  1. //+---------------------------------------------------------------------
  2. //
  3. // File: sdv.cxx
  4. //
  5. //------------------------------------------------------------------------
  6. //[ srvrdv_overview
  7. /*
  8. SrvrDV Overview
  9. The SrvrDV base class implements the persistent data and view aspects common
  10. to most OLE Compound Document objects. It implements the IDataObject,
  11. IViewObject, and IPersist family of interfaces.
  12. The set of formats supported in IDataObject::GetData and SetData methods is
  13. very object dependent. SrvrDV uses a table approach to allow each derived
  14. class to specify precisely exactly the set of formats supported. For each
  15. of GetData and SetData there is a pair of tables. One is a table of FORMATETC
  16. structures that specify information about the format supported. A parallel
  17. table contains a pointer to a function that implements each format supported.
  18. SrvrDV has a set of static methods that implement the standard OLE clipboard
  19. formats. The derived class can include these methods in its Get/Set tables.
  20. */
  21. //]
  22. #include "headers.hxx"
  23. #pragma hdrstop
  24. OLECHAR szContents[] = OLETEXT("contents");
  25. //+---------------------------------------------------------------
  26. //
  27. // Member: SrvrDV::SrvrDV, protected
  28. //
  29. // Synopsis: Constructor for SrvrCtrl object
  30. //
  31. // Notes: To create a properly initialized object you must
  32. // call the Init method immediately after construction.
  33. //
  34. //---------------------------------------------------------------
  35. SrvrDV::SrvrDV(void)
  36. {
  37. DOUT(TEXT("SrvrDV: Constructing\r\n"));
  38. _pmk = NULL;
  39. _lpstrDisplayName = NULL;
  40. _sizel.cx = 0; _sizel.cy = 0;
  41. _pDataAdviseHolder = NULL;
  42. _fFrozen = FALSE;
  43. _pViewAdviseHolder = NULL;
  44. _fDirty = FALSE;
  45. _fNoScribble = FALSE;
  46. _pStg = NULL;
  47. }
  48. //+---------------------------------------------------------------
  49. //
  50. // Member: SrvrDV::Init, protected
  51. //
  52. // Synopsis: Fully initializes a SrvrCtrl object as part of a compound
  53. // document server aggregate
  54. //
  55. // Arguments: [pClass] -- The initialized class descriptor for the server
  56. // [pCtrl] -- The control subobject of the server we are a part of.
  57. //
  58. // Returns: NOERROR if successful
  59. //
  60. // Notes: The Init method of the control subobject creates the data/view and
  61. // inplace subobjects of the object and calls the respective Init methods
  62. // on each, including this one.
  63. // The class descriptor pointer is saved in the protected _pClass
  64. // member variable where it is accessible during the lifetime
  65. // of the object.
  66. //
  67. //---------------------------------------------------------------
  68. HRESULT
  69. SrvrDV::Init(LPCLASSDESCRIPTOR pClass, LPSRVRCTRL pCtrl)
  70. {
  71. _pClass = pClass;
  72. _pCtrl = pCtrl;
  73. return NOERROR;
  74. }
  75. //+---------------------------------------------------------------
  76. //
  77. // Member: SrvrDV::Init, protected
  78. //
  79. // Synopsis: Fully initializes a SrvrCtrl object from an existing object
  80. // to be used as a data transfer object
  81. //
  82. // Arguments: [pClass] -- The initialized class descriptor for the server
  83. // [pDV] -- The data/view subobject of the object that is the source
  84. // of this transfer data object
  85. //
  86. // Returns: NOERROR if successful
  87. //
  88. // Notes: This method is used in the process of the GetClipboardCopy method
  89. // for obtaining a transfer data object from an existing object.
  90. // The class descriptor pointer is saved in the protected _pClass
  91. // member variable where it is accessible during the lifetime
  92. // of the object.
  93. //
  94. //---------------------------------------------------------------
  95. HRESULT
  96. SrvrDV::Init(LPCLASSDESCRIPTOR pClass, LPSRVRDV pDV)
  97. {
  98. _pClass = pClass; // stash the class descriptor pointer
  99. _pCtrl = NULL; // we are a free-floating transfer data object
  100. // copy over member variables as appropriate
  101. _pmk = pDV->_pmk;
  102. if (_pmk != NULL)
  103. _pmk->AddRef();
  104. TaskAllocString(pDV->_lpstrDisplayName, &_lpstrDisplayName);
  105. _sizel = pDV->_sizel;
  106. // we create a temporary IStorage and take a snapshot of the storage.
  107. // The temporary IStorage will be automatically deleted when this
  108. // data object is released
  109. // What happens when we run out of memory?
  110. // Should re-try with disk-based docfile?
  111. //
  112. HRESULT hr;
  113. LPSTORAGE pStg;
  114. if (OK(hr = CreateStorageOnHGlobal(NULL, &pStg)))
  115. {
  116. // do a "Save Copy As" into our storage instance.
  117. if (OK(hr = OleSave((LPPERSISTSTORAGE)pDV, pStg, FALSE)))
  118. {
  119. if (OK(hr = pStg->Commit(STGC_DEFAULT)))
  120. {
  121. if (OK(hr = ((LPPERSISTSTORAGE)pDV)->SaveCompleted(NULL)))
  122. (_pStg = pStg)->AddRef();
  123. }
  124. }
  125. pStg->Release();
  126. }
  127. return hr;
  128. }
  129. //+---------------------------------------------------------------
  130. //
  131. // Member: SrvrDV::~SrvrDV, protected
  132. //
  133. // Synopsis: Destructor for the SrvrDV object
  134. //
  135. // Notes: The destructor is called as a result of the servers
  136. // reference count going to 0. It releases any held resources
  137. // including advise holders and storages.
  138. //
  139. //---------------------------------------------------------------
  140. SrvrDV::~SrvrDV(void)
  141. {
  142. if (_pmk != NULL)
  143. _pmk->Release();
  144. if (_lpstrDisplayName != NULL)
  145. TaskFreeString(_lpstrDisplayName);
  146. if (_pDataAdviseHolder != NULL)
  147. _pDataAdviseHolder->Release();
  148. if (_pViewAdviseHolder != NULL)
  149. _pViewAdviseHolder->Release();
  150. if (_pStg != NULL)
  151. _pStg->Release();
  152. DOUT(TEXT("SrvrDV: Destructed\r\n"));
  153. }
  154. #ifdef DOCGEN // documentation for pure virtual function
  155. //+---------------------------------------------------------------
  156. //
  157. // Member: SrvrDV::GetClipboardCopy, public
  158. //
  159. // Synopsis: Produces a data-transfer object representing a snapshot
  160. // of this data/view object
  161. //
  162. // Arguments: [ppDV] -- The place where the data-transfer object is returned
  163. //
  164. // Returns: Success if the data-transfer object was created.
  165. //
  166. // Notes: This method is called
  167. // as a result of an IOleObject::GetClipboardData call on the
  168. // control subobject. The overridden method should create a new
  169. // instance of itself and call the appropriate Init method on
  170. // the new instance passing the `this' pointer. This way the
  171. // new instance can initialize itself as a snapshot of this object.
  172. // All servers must override this pure virtual method.
  173. //
  174. //---------------------------------------------------------------
  175. HRESULT
  176. SrvrDV::GetClipboardCopy(LPSRVRDV FAR* ppDV)
  177. {}
  178. #endif // DOCGEN
  179. //+---------------------------------------------------------------
  180. //
  181. // Member: SrvrDV::SetExtent, public
  182. //
  183. // Synopsis: Informs the object that it has a new expected size
  184. //
  185. // Notes: IOleObject::SetExtent and GetExtent methods are passed
  186. // directly from the control subobject to the data/view subobject
  187. // via these methods. See OLE documentation for the
  188. // arguments and return values.
  189. //
  190. //---------------------------------------------------------------
  191. HRESULT
  192. SrvrDV::SetExtent(DWORD dwAspect, SIZEL& sizel)
  193. {
  194. HRESULT hr = NOERROR;
  195. switch(dwAspect)
  196. {
  197. case DVASPECT_CONTENT:
  198. case DVASPECT_DOCPRINT:
  199. #if 1
  200. // NTBug #20692: Fail Metafile setextent, because
  201. // Powerpoint tries to resize things in weird ways.
  202. hr = E_FAIL; // icon aspect is fixed size
  203. #else
  204. _sizel = sizel;
  205. #endif
  206. break;
  207. case DVASPECT_THUMBNAIL: //REVIEW: what size is a thumbnail?
  208. case DVASPECT_ICON:
  209. DOUT(TEXT("SrvrDV::SetExtent E_FAIL\r\n"));
  210. hr = E_FAIL; // icon aspect is fixed size
  211. break;
  212. default:
  213. DOUT(TEXT("SrvrDV::SetExtent E_INVALIDARG\r\n"));
  214. hr = E_INVALIDARG;
  215. break;
  216. }
  217. return hr;
  218. }
  219. //+---------------------------------------------------------------
  220. //
  221. // Member: SrvrDV::GetExtent, public
  222. //
  223. // Synopsis: Requests the current size for some draw aspect of the object
  224. //
  225. // Notes: IOleObject::SetExtent and GetExtent methods are passed
  226. // directly from the control subobject to the data/view subobject
  227. // via these methods. See OLE documentation for the
  228. // arguments and return values.
  229. //
  230. //---------------------------------------------------------------
  231. HRESULT
  232. SrvrDV::GetExtent(DWORD dwAspect, LPSIZEL lpsizel)
  233. {
  234. #if DBG
  235. TCHAR achTemp[256];
  236. wsprintf(achTemp,TEXT("SrvrDV::GetExtent (dwApsect = %ld, cx = %ld, cy = %ld)\r\n"),
  237. dwAspect, _sizel.cx, _sizel.cy);
  238. DOUT(achTemp);
  239. #endif
  240. HRESULT hr = NOERROR;
  241. switch(dwAspect) {
  242. default:
  243. DOUT(TEXT("SrvrDV::GetExtent INVALIDARG\r\n"));
  244. case DVASPECT_CONTENT:
  245. case DVASPECT_DOCPRINT:
  246. *lpsizel = _sizel;
  247. break;
  248. case DVASPECT_THUMBNAIL:
  249. case DVASPECT_ICON:
  250. // The iconic view is actually a metafile of the
  251. // icon with a text-string underneath.
  252. // This isn't the right calculation...
  253. lpsizel->cx = HimetricFromHPix(32);
  254. lpsizel->cy = HimetricFromVPix(32);
  255. break;
  256. }
  257. return hr;
  258. }
  259. //+---------------------------------------------------------------
  260. //
  261. // Member: SrvrDV::OnDataChange, public
  262. //
  263. // Synopsis: Sets the dirty flag and raises data and view changed
  264. // to all registered advises
  265. //
  266. // Arguments: [dwAdvf] -- from the ADVF Data Advise flags.
  267. // Usually this is 0. ADVF_DATAONSTOP is used
  268. // when the object is closing down.
  269. // Notes: This function should be called whenever the native
  270. // data of the object is modified.
  271. //
  272. //---------------------------------------------------------------
  273. void
  274. SrvrDV::OnDataChange(DWORD dwAdvf)
  275. {
  276. _fDirty = TRUE;
  277. if (_pViewAdviseHolder != NULL)
  278. _pViewAdviseHolder->SendOnViewChange(DVASPECT_CONTENT);
  279. if (_pDataAdviseHolder != NULL)
  280. _pDataAdviseHolder->SendOnDataChange((LPDATAOBJECT)this, 0, dwAdvf);
  281. }
  282. //+---------------------------------------------------------------
  283. //
  284. // Member: SrvrDV::SetMoniker, public
  285. //
  286. // Synopsis: Informs the object of its new, full moniker
  287. //
  288. // Arguments: [pmk] -- full moniker to the object
  289. //
  290. // Notes: The data/view subobject records the full moniker to the
  291. // object so it can properly dispense the standard OLE
  292. // Object Descriptor and Link Source clipboard formats.
  293. // This method is called whenever the IOleObject::SetMoniker
  294. // method is called on the control subobject.
  295. //
  296. //---------------------------------------------------------------
  297. void
  298. SrvrDV::SetMoniker(LPMONIKER pmk)
  299. {
  300. if (_pmk != NULL)
  301. {
  302. _pmk->Release();
  303. if (_lpstrDisplayName != NULL) // flush our cached display name
  304. {
  305. TaskFreeString(_lpstrDisplayName);
  306. _lpstrDisplayName = NULL;
  307. }
  308. }
  309. _pmk = pmk;
  310. if (_pmk != NULL)
  311. {
  312. _pmk->AddRef();
  313. }
  314. }
  315. //+---------------------------------------------------------------
  316. //
  317. // Member: SrvrDV::GetMoniker, public
  318. //
  319. // Synopsis: Returns the full moniker to the object
  320. //
  321. // Arguments: [dwAssign] -- See IOleObject::GetMoniker
  322. // [ppmk] -- The place where the moniker is returned
  323. //
  324. // Returns: Success if the moniker is available.
  325. //
  326. // Notes: This returns the moniker that this data/view subobject has
  327. // previously recorded. If no moniker is yet assigned
  328. // then the moniker is requested from the client site
  329. // via the IOleObject::GetMoniker method on the control subobject.
  330. // This method is used by the GetOBJECTDESCRIPTOR and GetLINKSOURCE
  331. // methods.
  332. //
  333. //---------------------------------------------------------------
  334. HRESULT
  335. SrvrDV::GetMoniker(DWORD dwAssign, LPMONIKER FAR* ppmk)
  336. {
  337. *ppmk = NULL; // set out params to NULL
  338. HRESULT hr = NOERROR;
  339. if (_pmk == NULL)
  340. {
  341. if (_pCtrl == NULL)
  342. {
  343. DOUT(TEXT("SrvrDV::GetMoniker E_INVALIDARG\r\n"));
  344. hr = MK_E_UNAVAILABLE;
  345. }
  346. else
  347. {
  348. hr = _pCtrl->GetMoniker(dwAssign, OLEWHICHMK_OBJFULL, &_pmk);
  349. }
  350. }
  351. if (OK(hr))
  352. (*ppmk = _pmk)->AddRef();
  353. return hr;
  354. }
  355. //+---------------------------------------------------------------
  356. //
  357. // Member: SrvrDV::GetMonikerDisplayName, public
  358. //
  359. // Synopsis: Returns the display name from the object's moniker
  360. //
  361. // Notes: The display name of the object is used in for
  362. // dispensing the Object Descriptor clipboard format.
  363. // The caller must not free the string returned.
  364. //
  365. //---------------------------------------------------------------
  366. LPOLESTR
  367. SrvrDV::GetMonikerDisplayName(DWORD dwAssign)
  368. {
  369. //
  370. // NOTE: default dwAssign is OLEGETMONIKER_ONLYIFTHERE
  371. //
  372. // we maintain a moniker display name cache in the form of member
  373. // variable _lpstrDisplayName.
  374. //
  375. // If we don't have a display name cached then take our moniker and
  376. // squeeze a display name out of it
  377. //
  378. if (!_lpstrDisplayName)
  379. {
  380. LPMONIKER pmk;
  381. if (OK(GetMoniker(dwAssign, &pmk)))
  382. {
  383. ::GetMonikerDisplayName(pmk, &_lpstrDisplayName);
  384. pmk->Release();
  385. }
  386. }
  387. return _lpstrDisplayName;
  388. }
  389. //+---------------------------------------------------------------
  390. //
  391. // Member: SrvrDV::GetEMBEDDEDOBJECT, public
  392. //
  393. // Synopsis: Implementation of IDataObject::GetData and GetDataHere
  394. // for the standard Embedded Object clipboard format
  395. //
  396. // Arguments: [pv] -- pointer to a SrvrDV object
  397. // [pformatetc] -- as in IDataObject::GetData, GetDataHere
  398. // [pmedium] -- as in IDataObject::GetData, GetDataHere
  399. // [fHere] -- TRUE for GetDataHere, FALSE for GetData
  400. //
  401. // Returns: Success if the clipboard format could be dispensed
  402. //
  403. // Notes: This and the other static GetXXX methods are for use
  404. // in the server's Get format tables.
  405. //
  406. //---------------------------------------------------------------
  407. HRESULT
  408. SrvrDV::GetEMBEDDEDOBJECT( LPSRVRDV pDV,
  409. LPFORMATETC pformatetc,
  410. LPSTGMEDIUM pmedium,
  411. BOOL fHere)
  412. {
  413. LPPERSISTSTORAGE pPStg = (LPPERSISTSTORAGE)(LPSRVRDV)pDV;
  414. HRESULT hr = NOERROR;
  415. if (!fHere && pmedium)
  416. {
  417. // fill in the pmedium structure
  418. pmedium->tymed = TYMED_ISTORAGE;
  419. hr = StgCreateDocfile(NULL,
  420. STGM_DFRALL | STGM_CREATE | STGM_DELETEONRELEASE,
  421. 0L,
  422. &pmedium->pstg);
  423. pmedium->pUnkForRelease = NULL;
  424. }
  425. if (OK(hr) && pmedium && pPStg)
  426. {
  427. if (OK(hr = OleSave(pPStg, pmedium->pstg, FALSE)))
  428. hr = pPStg->SaveCompleted(NULL);
  429. // if we failed somehow and yet created a docfile, then we will
  430. // release the docfile to delete it
  431. //
  432. if (!OK(hr) && !fHere)
  433. pmedium->pstg->Release();
  434. }
  435. return hr;
  436. }
  437. //+---------------------------------------------------------------
  438. //
  439. // Member: SrvrDV::GetMETAFILEPICT, public
  440. //
  441. // Synopsis: Implementation of IDataObject::GetData and GetDataHere
  442. // for the standard Metafilepict clipboard format
  443. //
  444. // Arguments: [pv] -- pointer to a SrvrDV object
  445. // [pformatetc] -- as in IDataObject::GetData, GetDataHere
  446. // [pmedium] -- as in IDataObject::GetData, GetDataHere
  447. // [fHere] -- TRUE for GetDataHere, FALSE for GetData
  448. //
  449. // Returns: Success if the clipboard format could be dispensed
  450. //
  451. // Notes: This member function uses IViewObject::Draw to construct
  452. // the metafile pict.
  453. // This and the other static GetXXX methods are for use
  454. // in the server's Get format tables.
  455. //
  456. //---------------------------------------------------------------
  457. HRESULT
  458. SrvrDV::GetMETAFILEPICT( LPSRVRDV pDV,
  459. LPFORMATETC pformatetc,
  460. LPSTGMEDIUM pmedium,
  461. BOOL fHere)
  462. {
  463. DOUT(TEXT("o2base/SrvrDV::GetMETAFILEPICT\r\n"));
  464. LPVIEWOBJECT pView = (LPVIEWOBJECT)pDV;
  465. SIZEL sizel;
  466. pDV->GetExtent(pformatetc->dwAspect, &sizel);
  467. RECT rc = { 0, 0, sizel.cx, sizel.cy };
  468. HRESULT hr = NOERROR;
  469. if (!fHere)
  470. {
  471. // fill in the pmedium structure
  472. pmedium->tymed = TYMED_MFPICT;
  473. pmedium->hGlobal = GlobalAlloc(GMEM_SHARE, sizeof(METAFILEPICT));
  474. if (pmedium->hGlobal == NULL)
  475. {
  476. DOUT(TEXT("o2base/SrvrDV::GetMETAFILEPICT failed\r\n"));
  477. hr = E_OUTOFMEMORY;
  478. }
  479. pmedium->pUnkForRelease = NULL;
  480. }
  481. if (OK(hr))
  482. {
  483. HMETAFILE hmf;
  484. if (OK(hr = DrawMetafile(pView, rc, pformatetc->dwAspect, &hmf)))
  485. {
  486. LPMETAFILEPICT pPict = (LPMETAFILEPICT)GlobalLock(pmedium->hGlobal);
  487. if (pPict == NULL)
  488. {
  489. DOUT(TEXT("SrvrDV::GetMETAFILEPICT E_INVALIDARG\r\n"));
  490. DeleteMetaFile(hmf);
  491. hr = E_INVALIDARG;
  492. }
  493. else
  494. {
  495. // fill in the object descriptor
  496. pPict->mm = MM_ANISOTROPIC;
  497. pPict->hMF = hmf;
  498. pPict->xExt = rc.right;
  499. pPict->yExt = rc.bottom;
  500. GlobalUnlock(pmedium->hGlobal);
  501. }
  502. }
  503. // if we failed somehow and yet allocated memory,
  504. // then we will release it here...
  505. //
  506. if (!OK(hr) && !fHere)
  507. {
  508. GlobalFree(pmedium->hGlobal);
  509. pmedium->hGlobal = NULL;
  510. }
  511. }
  512. return hr;
  513. }
  514. //+---------------------------------------------------------------
  515. //
  516. // Member: SrvrDV::GetOBJECTDESCRIPTOR, public
  517. //
  518. // Synopsis: Implementation of IDataObject::GetData and GetDataHere
  519. // for the standard Object Descriptor clipboard format
  520. //
  521. // Arguments: [pv] -- pointer to a SrvrDV object
  522. // [pformatetc] -- as in IDataObject::GetData, GetDataHere
  523. // [pmedium] -- as in IDataObject::GetData, GetDataHere
  524. // [fHere] -- TRUE for GetDataHere, FALSE for GetData
  525. //
  526. // Returns: Success if the clipboard format could be dispensed
  527. //
  528. // Notes: This and the other static GetXXX methods are for use
  529. // in the server's Get format tables.
  530. //
  531. //---------------------------------------------------------------
  532. HRESULT
  533. SrvrDV::GetOBJECTDESCRIPTOR( LPSRVRDV pDV,
  534. LPFORMATETC pformatetc,
  535. LPSTGMEDIUM pmedium,
  536. BOOL fHere)
  537. {
  538. HRESULT hr = NOERROR;
  539. LPCLASSDESCRIPTOR pClass = pDV->_pClass;
  540. //
  541. //REVIEW: what's the best display name for the OBJECTDESCRIPTOR?
  542. //
  543. OLECHAR achDisplay[256];
  544. ostrcpy(achDisplay, OLETEXT("Microsoft "));
  545. ostrcat(achDisplay, pClass->_szUserClassType[USERCLASSTYPE_FULL]);
  546. LPOLESTR lpstrDisplay = achDisplay;
  547. DWORD dwDisplay = lpstrDisplay ?
  548. (ostrlen(lpstrDisplay) + 1) * sizeof(OLECHAR) : 0;
  549. LPOLESTR lpstrUserTypeFull = pClass->_szUserClassType[USERCLASSTYPE_FULL];
  550. DWORD dwUserTypeFull = lpstrUserTypeFull ?
  551. (ostrlen(lpstrUserTypeFull) + 1) * sizeof(OLECHAR) : 0;
  552. DWORD dwSize = sizeof(OBJECTDESCRIPTOR) + dwUserTypeFull + dwDisplay;
  553. if (!fHere)
  554. {
  555. // compute the amount of memory required
  556. // fill in the pmedium structure
  557. pmedium->tymed = TYMED_HGLOBAL;
  558. pmedium->hGlobal = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, dwSize);
  559. if (pmedium->hGlobal == NULL)
  560. {
  561. DOUT(TEXT("o2base/SrvrDV::GetOBJECTDESCRIPTOR failed (pmedium)\r\n"));
  562. hr = E_OUTOFMEMORY;
  563. }
  564. pmedium->pUnkForRelease = NULL;
  565. }
  566. if (OK(hr) && (GlobalSize(pmedium->hGlobal) >= dwSize))
  567. {
  568. LPOBJECTDESCRIPTOR pObjDesc =
  569. (LPOBJECTDESCRIPTOR)GlobalLock(pmedium->hGlobal);
  570. if (pObjDesc == NULL)
  571. {
  572. DOUT(TEXT("o2base/SrvrDV::GetOBJECTDESCRIPTOR failed\r\n"));
  573. hr = E_OUTOFMEMORY;
  574. }
  575. else
  576. {
  577. //
  578. // fill in the object descriptor
  579. //
  580. pObjDesc->cbSize = dwSize;
  581. pObjDesc->clsid = pClass->_clsid;
  582. pObjDesc->dwDrawAspect = DVASPECT_CONTENT;
  583. pObjDesc->sizel = pDV->_sizel;
  584. pObjDesc->pointl.y = pObjDesc->pointl.x = 0;
  585. pObjDesc->dwStatus = pClass->_dwMiscStatus;
  586. LPOLESTR lpstrDest = (LPOLESTR)(pObjDesc + 1);
  587. if(lpstrUserTypeFull)
  588. {
  589. ostrcpy(lpstrDest, lpstrUserTypeFull);
  590. #if DBG
  591. #if !defined(UNICODE) && !defined(OLE2ANSI)
  592. LPSTR lp = ConvertOLESTRToMB(lpstrDest, -1);
  593. OutputDebugStringA(lp);
  594. OutputDebugStringA("\r\n");
  595. TaskFreeMem(lp);
  596. #endif
  597. #endif
  598. pObjDesc->dwFullUserTypeName = sizeof(OBJECTDESCRIPTOR);
  599. lpstrDest += ostrlen(lpstrUserTypeFull) + 1;
  600. }
  601. else
  602. pObjDesc->dwFullUserTypeName = 0;
  603. if (lpstrDisplay)
  604. {
  605. pObjDesc->dwSrcOfCopy = pObjDesc->dwFullUserTypeName + dwUserTypeFull;
  606. ostrcpy(lpstrDest, lpstrDisplay);
  607. #if DBG
  608. #if !defined(UNICODE) && !defined(OLE2ANSI)
  609. LPSTR lp = ConvertOLESTRToMB(lpstrDest, -1);
  610. OutputDebugStringA(lp);
  611. OutputDebugStringA("\r\n");
  612. TaskFreeMem(lp);
  613. #endif
  614. #endif
  615. }
  616. else
  617. pObjDesc->dwSrcOfCopy = 0;
  618. GlobalUnlock(pmedium->hGlobal);
  619. hr = NOERROR;
  620. }
  621. // if we failed somehow and yet allocated memory,
  622. // then we will release it here...
  623. if (!OK(hr) && !fHere)
  624. {
  625. GlobalFree(pmedium->hGlobal);
  626. pmedium->hGlobal = NULL;
  627. }
  628. }
  629. else
  630. hr = E_OUTOFMEMORY;
  631. return hr;
  632. }
  633. //+---------------------------------------------------------------
  634. //
  635. // Member: SrvrDV::GetLINKSOURCE, public
  636. //
  637. // Synopsis: Implementation of IDataObject::GetData and GetDataHere
  638. // for the standard Link Source clipboard format
  639. //
  640. // Arguments: [pv] -- pointer to a SrvrDV object
  641. // [pformatetc] -- as in IDataObject::GetData, GetDataHere
  642. // [pmedium] -- as in IDataObject::GetData, GetDataHere
  643. // [fHere] -- TRUE for GetDataHere, FALSE for GetData
  644. //
  645. // Returns: Success if the clipboard format could be dispensed
  646. //
  647. // Notes: This method uses the moniker cached by the data/view
  648. // object.
  649. // This and the other static GetXXX methods are for use
  650. // in the server's Get format tables.
  651. //
  652. //---------------------------------------------------------------
  653. HRESULT
  654. SrvrDV::GetLINKSOURCE( LPSRVRDV pDV,
  655. LPFORMATETC pformatetc,
  656. LPSTGMEDIUM pmedium,
  657. BOOL fHere)
  658. {
  659. LPMONIKER pmk;
  660. HRESULT hr;
  661. if (OK(hr = pDV->GetMoniker(OLEGETMONIKER_FORCEASSIGN, &pmk)))
  662. {
  663. if (!fHere)
  664. {
  665. pmedium->tymed = TYMED_ISTREAM;
  666. HRESULT hr = CreateStreamOnHGlobal(NULL, TRUE, &pmedium->pstm);
  667. pmedium->pUnkForRelease = NULL;
  668. }
  669. if (OK(hr))
  670. {
  671. CLSID clsid;
  672. if (OK(hr = pmk->GetClassID(&clsid)))
  673. {
  674. if (OK(hr = WriteClassStm(pmedium->pstm, clsid)))
  675. hr = pmk->Save(pmedium->pstm, FALSE);
  676. pDV->GetClassID(&clsid);
  677. WriteClassStm(pmedium->pstm, clsid);
  678. }
  679. }
  680. pmk->Release();
  681. }
  682. return hr;
  683. }
  684. //+--------------------------------------------------------------
  685. //
  686. // Member: SrvrDV::GetData, public
  687. //
  688. // Synopsis: Method of IDataObject interface
  689. //
  690. // Notes: This method searches the server's Get format table
  691. // for a compatible format. If one is found it calls
  692. // the corresponding Get function.
  693. //
  694. //---------------------------------------------------------------
  695. STDMETHODIMP
  696. SrvrDV::GetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium)
  697. {
  698. DOUT(TEXT("SrvrDV:GetData\r\n"));
  699. if (pformatetc == NULL || pmedium == NULL)
  700. {
  701. DOUT(TEXT("SrvrDV::GetData E_INVALIDARG\r\n"));
  702. return E_INVALIDARG;
  703. }
  704. HRESULT hr;
  705. int i = FindCompatibleFormat(_pClass->_pGetFmtTable,
  706. _pClass->_cGetFmtTable,
  707. *pformatetc);
  708. if (i < 0)
  709. {
  710. DOUT(TEXT("SrvrDV::GetData DV_E_FORMATETC\r\n"));
  711. hr = DV_E_FORMATETC;
  712. }
  713. else
  714. {
  715. hr = (*_pGetFuncs[i]) (this, pformatetc, pmedium, FALSE);
  716. }
  717. return hr;
  718. }
  719. //+---------------------------------------------------------------
  720. //
  721. // Member: SrvrDV::GetDataHere, public
  722. //
  723. // Synopsis: Method of IDataObject interface
  724. //
  725. // Notes: This method searches the server's Get format table
  726. // for a compatible format. If one is found it calls
  727. // the corresponding Get function.
  728. //
  729. //---------------------------------------------------------------
  730. STDMETHODIMP
  731. SrvrDV::GetDataHere(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium)
  732. {
  733. DOUT(TEXT("SrvrDV:GetDataHere\r\n"));
  734. HRESULT hr;
  735. int i = FindCompatibleFormat(_pClass->_pGetFmtTable,
  736. _pClass->_cGetFmtTable,
  737. *pformatetc);
  738. if (i < 0)
  739. {
  740. DOUT(TEXT("SrvrDV::GetDataHere DV_E_FORMATETC\r\n"));
  741. hr = DV_E_FORMATETC;
  742. }
  743. else
  744. {
  745. hr = (*_pGetFuncs[i]) (this, pformatetc, pmedium, TRUE);
  746. }
  747. return hr;
  748. }
  749. //+---------------------------------------------------------------
  750. //
  751. // Member: SrvrDV::QueryGetData, public
  752. //
  753. // Synopsis: Method of IDataObject interface
  754. //
  755. // Notes: This method searches the server's Get format table
  756. // for a compatible format. The return value indicates
  757. // whether or not a compatible format was found.
  758. //
  759. //---------------------------------------------------------------
  760. STDMETHODIMP
  761. SrvrDV::QueryGetData(LPFORMATETC pformatetc)
  762. {
  763. return FindCompatibleFormat(_pClass->_pGetFmtTable,
  764. _pClass->_cGetFmtTable,
  765. *pformatetc) >=0 ? NOERROR : DV_E_FORMATETC;
  766. }
  767. //+---------------------------------------------------------------
  768. //
  769. // Member: SrvrDV::GetCanonicalFormatEtc, public
  770. //
  771. // Synopsis: Method of IDataObject interface
  772. //
  773. // Notes: This method returns DATA_S_SAMEFORMATETC assuming
  774. // that each format the server dispenses is its own
  775. // canonical format. If this is not the case then this
  776. // method should be overridden.
  777. //
  778. //---------------------------------------------------------------
  779. STDMETHODIMP
  780. SrvrDV::GetCanonicalFormatEtc(LPFORMATETC pformatetc,
  781. LPFORMATETC pformatetcOut)
  782. {
  783. return DATA_S_SAMEFORMATETC;
  784. }
  785. //+---------------------------------------------------------------
  786. //
  787. // Member: SrvrDV::SetData, public
  788. //
  789. // Synopsis: Method of IDataObject interface
  790. //
  791. // Notes: This method searches the server's Set format table
  792. // for a compatible format. If one is found it calls
  793. // the corresponding Set function.
  794. //
  795. //---------------------------------------------------------------
  796. STDMETHODIMP
  797. SrvrDV::SetData(LPFORMATETC pformatetc, STGMEDIUM FAR *pmedium, BOOL fRelease)
  798. {
  799. DOUT(TEXT("SrvrDV:SetData\r\n"));
  800. HRESULT hr;
  801. int i = FindCompatibleFormat(_pClass->_pSetFmtTable,
  802. _pClass->_cSetFmtTable,
  803. *pformatetc);
  804. if (i < 0)
  805. {
  806. DOUT(TEXT("SrvrDV::SetData DV_E_FORMATETC\r\n"));
  807. hr = DV_E_FORMATETC;
  808. }
  809. else
  810. {
  811. hr = (*_pSetFuncs[i]) (this, pformatetc, pmedium);
  812. }
  813. if (fRelease)
  814. {
  815. ReleaseStgMedium(pmedium);
  816. }
  817. return hr;
  818. }
  819. //+---------------------------------------------------------------
  820. //
  821. // Member: SrvrDV::EnumFormatEtc, public
  822. //
  823. // Synopsis: Method of IDataObject interface
  824. //
  825. // Notes: This method creates an enumerator over the Get or
  826. // Set format tables depending on the value of the
  827. // dwDirection argument.
  828. //
  829. //---------------------------------------------------------------
  830. STDMETHODIMP
  831. SrvrDV::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC FAR* ppenumFormatEtc)
  832. {
  833. if (ppenumFormatEtc == NULL)
  834. {
  835. DOUT(TEXT("SrvrDV::EnumFormatEtc E_INVALIDARG\r\n"));
  836. return E_INVALIDARG;
  837. }
  838. *ppenumFormatEtc = NULL; // set out params to NULL
  839. // create an enumerator over our static format table.
  840. HRESULT hr = E_INVALIDARG;
  841. switch (dwDirection)
  842. {
  843. case DATADIR_GET:
  844. hr = CreateFORMATETCEnum(_pClass->_pGetFmtTable,
  845. _pClass->_cGetFmtTable,
  846. ppenumFormatEtc);
  847. break;
  848. case DATADIR_SET:
  849. hr = CreateFORMATETCEnum(_pClass->_pSetFmtTable,
  850. _pClass->_cSetFmtTable,
  851. ppenumFormatEtc);
  852. break;
  853. default:
  854. DOUT(TEXT("SrvrDV::EnumFormatEtc E_INVALIDARG (2)\r\n"));
  855. break;
  856. }
  857. return hr;
  858. }
  859. //+---------------------------------------------------------------
  860. //
  861. // Member: SrvrDV::DAdvise, public
  862. //
  863. // Synopsis: Method of IDataObject interface
  864. //
  865. // Notes: This method uses the standard OLE data advise holder.
  866. //
  867. //---------------------------------------------------------------
  868. STDMETHODIMP
  869. SrvrDV::DAdvise(FORMATETC FAR* pFormatetc,
  870. DWORD advf,
  871. LPADVISESINK pAdvSink,
  872. DWORD FAR* pdwConnection)
  873. {
  874. if (pdwConnection == NULL)
  875. {
  876. DOUT(TEXT("SrvrDV::DAdvise E_INVALIDARG\r\n"));
  877. return E_INVALIDARG;
  878. }
  879. *pdwConnection = NULL; // set out params to NULL
  880. HRESULT hr = NOERROR;
  881. if (_pDataAdviseHolder == NULL)
  882. hr = CreateDataAdviseHolder(&_pDataAdviseHolder);
  883. if (OK(hr))
  884. {
  885. hr = _pDataAdviseHolder->Advise((LPDATAOBJECT)this,
  886. pFormatetc,
  887. advf,
  888. pAdvSink,
  889. pdwConnection);
  890. }
  891. return hr;
  892. }
  893. //+---------------------------------------------------------------
  894. //
  895. // Member: SrvrDV::DUnadvise, public
  896. //
  897. // Synopsis: Method of IDataObject interface
  898. //
  899. // Notes: This method uses the standard OLE data advise holder.
  900. //
  901. //---------------------------------------------------------------
  902. STDMETHODIMP
  903. SrvrDV::DUnadvise(DWORD dwConnection)
  904. {
  905. if (_pDataAdviseHolder == NULL)
  906. return NOERROR;
  907. return _pDataAdviseHolder->Unadvise(dwConnection);
  908. }
  909. //+---------------------------------------------------------------
  910. //
  911. // Member: SrvrDV::EnumDAdvise, public
  912. //
  913. // Synopsis: Method of IDataObject interface
  914. //
  915. // Notes: This method uses the standard OLE data advise holder.
  916. //
  917. //---------------------------------------------------------------
  918. STDMETHODIMP
  919. SrvrDV::EnumDAdvise(LPENUMSTATDATA FAR* ppenumAdvise)
  920. {
  921. if (ppenumAdvise == NULL)
  922. {
  923. DOUT(TEXT("SrvrDV::EnumDAdvise E_INVALIDARG\r\n"));
  924. return E_INVALIDARG;
  925. }
  926. *ppenumAdvise = NULL; // set out params to NULL
  927. HRESULT hr;
  928. if (_pDataAdviseHolder == NULL)
  929. hr = NOERROR;
  930. else
  931. hr = _pDataAdviseHolder->EnumAdvise(ppenumAdvise);
  932. return hr;
  933. }
  934. //+---------------------------------------------------------------
  935. //
  936. // Member: SrvrDV::RenderContent, public
  937. //
  938. // Synopsis: Used to draw the content aspect of the object
  939. //
  940. // Notes: This method is used by the implementation of IViewObject::Draw
  941. // when the content aspect is requested. The parameters are
  942. // identical to those of IViewObject::Draw.
  943. // All objects should override this method.
  944. //
  945. //---------------------------------------------------------------
  946. HRESULT
  947. SrvrDV::RenderContent(DWORD dwDrawAspect,
  948. LONG lindex,
  949. void FAR* pvAspect,
  950. DVTARGETDEVICE FAR * ptd,
  951. HDC hicTargetDev,
  952. HDC hdcDraw,
  953. LPCRECTL lprectl,
  954. LPCRECTL lprcWBounds,
  955. BOOL (CALLBACK * pfnContinue) (ULONG_PTR),
  956. ULONG_PTR dwContinue)
  957. {
  958. return NOERROR;
  959. }
  960. //+---------------------------------------------------------------
  961. //
  962. // Member: SrvrDV::RenderPrint, public
  963. //
  964. // Synopsis: Used to draw the print aspect of the object
  965. //
  966. // Notes: This method is used by the implementation of IViewObject::Draw
  967. // when the docprint aspect is requested. The parameters are
  968. // identical to those of IViewObject::Draw.
  969. // By default this method calls RenderContent. If the
  970. // server has special processing for the print case then
  971. // this method should be overridden.
  972. //
  973. //---------------------------------------------------------------
  974. HRESULT
  975. SrvrDV::RenderPrint(DWORD dwDrawAspect,
  976. LONG lindex,
  977. void FAR* pvAspect,
  978. DVTARGETDEVICE FAR * ptd,
  979. HDC hicTargetDev,
  980. HDC hdcDraw,
  981. LPCRECTL lprectl,
  982. LPCRECTL lprcWBounds,
  983. BOOL (CALLBACK * pfnContinue) (ULONG_PTR),
  984. ULONG_PTR dwContinue)
  985. {
  986. return RenderContent(dwDrawAspect,
  987. lindex,
  988. pvAspect,
  989. ptd,
  990. hicTargetDev,
  991. hdcDraw,
  992. lprectl,
  993. lprcWBounds,
  994. pfnContinue,
  995. dwContinue);
  996. }
  997. //+---------------------------------------------------------------
  998. //
  999. // Member: SrvrDV::RenderThumbnail, public
  1000. //
  1001. // Synopsis: Used to draw the thumbnail aspect of the object
  1002. //
  1003. // Notes: This method is used by the implementation of IViewObject::Draw
  1004. // when the thumbnail aspect is requested. The parameters are
  1005. // identical to those of IViewObject::Draw.
  1006. // All objects should override this method.
  1007. //
  1008. //---------------------------------------------------------------
  1009. HRESULT
  1010. SrvrDV::RenderThumbnail(DWORD dwDrawAspect,
  1011. LONG lindex,
  1012. void FAR* pvAspect,
  1013. DVTARGETDEVICE FAR * ptd,
  1014. HDC hicTargetDev,
  1015. HDC hdcDraw,
  1016. LPCRECTL lprectl,
  1017. LPCRECTL lprcWBounds,
  1018. BOOL (CALLBACK * pfnContinue) (ULONG_PTR),
  1019. ULONG_PTR dwContinue)
  1020. {
  1021. return NOERROR;
  1022. }
  1023. //+---------------------------------------------------------------
  1024. //
  1025. // Member: SrvrDV::Draw, public
  1026. //
  1027. // Synopsis: Method of IViewObject interface
  1028. //
  1029. // Notes: This method calls RenderContent/Print/Thumbnail for
  1030. // those respective aspects. It handles the icon aspect
  1031. // automatically using the icon found in the class descriptor
  1032. // indicated by the _pClass member.
  1033. //
  1034. //---------------------------------------------------------------
  1035. STDMETHODIMP
  1036. SrvrDV::Draw(DWORD dwDrawAspect,
  1037. LONG lindex,
  1038. void FAR* pvAspect,
  1039. DVTARGETDEVICE FAR * ptd,
  1040. HDC hicTargetDev,
  1041. HDC hdcDraw,
  1042. LPCRECTL lprectl,
  1043. LPCRECTL lprcWBounds,
  1044. BOOL (CALLBACK * pfnContinue) (ULONG_PTR),
  1045. ULONG_PTR dwContinue)
  1046. {
  1047. HRESULT hr;
  1048. switch(dwDrawAspect) {
  1049. case DVASPECT_CONTENT:
  1050. hr = RenderContent(dwDrawAspect,
  1051. lindex,
  1052. pvAspect,
  1053. ptd,
  1054. hicTargetDev,
  1055. hdcDraw,
  1056. lprectl,
  1057. lprcWBounds,
  1058. pfnContinue,
  1059. dwContinue);
  1060. break;
  1061. case DVASPECT_DOCPRINT:
  1062. hr = RenderPrint(dwDrawAspect,
  1063. lindex,
  1064. pvAspect,
  1065. ptd,
  1066. hicTargetDev,
  1067. hdcDraw,
  1068. lprectl,
  1069. lprcWBounds,
  1070. pfnContinue,
  1071. dwContinue);
  1072. break;
  1073. case DVASPECT_THUMBNAIL:
  1074. hr = RenderThumbnail(dwDrawAspect,
  1075. lindex,
  1076. pvAspect,
  1077. ptd,
  1078. hicTargetDev,
  1079. hdcDraw,
  1080. lprectl,
  1081. lprcWBounds,
  1082. pfnContinue,
  1083. dwContinue);
  1084. break;
  1085. case DVASPECT_ICON:
  1086. {
  1087. // This is not the right way to do iconic aspect rendering!
  1088. RECT rc;
  1089. RECTL rcTemp = *lprectl;
  1090. RECTLtoRECT(rcTemp, &rc);
  1091. DrawIcon(hdcDraw, rc.left, rc.top, _pClass->_hicon);
  1092. hr = NOERROR;
  1093. }
  1094. break;
  1095. default:
  1096. DOUT(TEXT("SrvrDV::Draw E_INVALIDARG\r\n"));
  1097. hr = E_INVALIDARG;
  1098. break;
  1099. }
  1100. return hr;
  1101. }
  1102. //+---------------------------------------------------------------
  1103. //
  1104. // Member: SrvrDV::GetColorSet, public
  1105. //
  1106. // Synopsis: Method of IViewObject interface
  1107. //
  1108. // Notes: This method returns S_FALSE indicating the server
  1109. // does not support this functionality. Server's that
  1110. // wish to support it should override this method.
  1111. //
  1112. //---------------------------------------------------------------
  1113. STDMETHODIMP
  1114. SrvrDV::GetColorSet(DWORD dwDrawAspect,
  1115. LONG lindex,
  1116. void FAR* pvAspect,
  1117. DVTARGETDEVICE FAR * ptd,
  1118. HDC hicTargetDev,
  1119. LPLOGPALETTE FAR* ppColorSet)
  1120. {
  1121. if (ppColorSet == NULL)
  1122. {
  1123. DOUT(TEXT("SrvrDV::GetColorSet E_INVALIDARG\r\n"));
  1124. return E_INVALIDARG;
  1125. }
  1126. *ppColorSet = NULL; //set out params to NULL
  1127. return S_FALSE;
  1128. }
  1129. //+---------------------------------------------------------------
  1130. //
  1131. // Member: SrvrDV::Freeze, public
  1132. //
  1133. // Synopsis: Method of IViewObject interface
  1134. //
  1135. // Notes: This method sets the frozen flag, _fFrozen.
  1136. // The derived class must pay attention to this flag
  1137. // and not allow any modifications that would change
  1138. // the current rendering.
  1139. //
  1140. //---------------------------------------------------------------
  1141. STDMETHODIMP
  1142. SrvrDV::Freeze(DWORD dwDrawAspect,
  1143. LONG lindex,
  1144. void FAR* pvAspect,
  1145. DWORD FAR* pdwFreeze)
  1146. {
  1147. if (pdwFreeze == NULL)
  1148. {
  1149. DOUT(TEXT("SrvrDV::Freeze E_INVALIDARG\r\n"));
  1150. return E_INVALIDARG;
  1151. }
  1152. *pdwFreeze = 0; //set out params to NULL
  1153. _fFrozen = TRUE;
  1154. return NOERROR;
  1155. }
  1156. //+---------------------------------------------------------------
  1157. //
  1158. // Member: SrvrDV::Unfreeze, public
  1159. //
  1160. // Synopsis: Method of IViewObject interface
  1161. //
  1162. // Notes: This method clears the frozen flag, _fFrozen.
  1163. //
  1164. //---------------------------------------------------------------
  1165. STDMETHODIMP
  1166. SrvrDV::Unfreeze(DWORD dwFreeze)
  1167. {
  1168. _fFrozen = FALSE;
  1169. return NOERROR;
  1170. }
  1171. //+---------------------------------------------------------------
  1172. //
  1173. // Member: SrvrDV::SetAdvise, public
  1174. //
  1175. // Synopsis: Method of IViewObject interface
  1176. //
  1177. // Notes: This method implements an advise holder for the view
  1178. // advise.
  1179. //
  1180. //---------------------------------------------------------------
  1181. STDMETHODIMP
  1182. SrvrDV::SetAdvise(DWORD aspects, DWORD advf, LPADVISESINK pAdvSink)
  1183. {
  1184. HRESULT hr = NOERROR;
  1185. if (_pViewAdviseHolder == NULL)
  1186. hr = CreateViewAdviseHolder(&_pViewAdviseHolder);
  1187. if (OK(hr))
  1188. hr = _pViewAdviseHolder->SetAdvise(aspects, advf, pAdvSink);
  1189. return hr;
  1190. }
  1191. //+---------------------------------------------------------------
  1192. //
  1193. // Member: SrvrDV::GetAdvise, public
  1194. //
  1195. // Synopsis: Method of IViewObject interface
  1196. //
  1197. //---------------------------------------------------------------
  1198. STDMETHODIMP
  1199. SrvrDV::GetAdvise(DWORD FAR* pAspects,
  1200. DWORD FAR* pAdvf,
  1201. LPADVISESINK FAR* ppAdvSink)
  1202. {
  1203. if (ppAdvSink == NULL)
  1204. {
  1205. DOUT(TEXT("SrvrDV::GetAdvise E_INVALIDARG\r\n"));
  1206. return E_INVALIDARG;
  1207. }
  1208. *ppAdvSink = NULL; // set out params to NULL
  1209. HRESULT hr;
  1210. if (_pViewAdviseHolder==NULL)
  1211. hr = NOERROR;
  1212. else
  1213. hr = _pViewAdviseHolder->GetAdvise(pAspects, pAdvf, ppAdvSink);
  1214. return hr;
  1215. }
  1216. //+---------------------------------------------------------------
  1217. //
  1218. // Member: SrvrDV::LoadFromStream, protected
  1219. //
  1220. // Synopsis: Loads the object's persistent state from a stream
  1221. //
  1222. // Arguments: [pStrm] -- stream to load from
  1223. //
  1224. // Returns: Success iff persistent state was read
  1225. //
  1226. // Notes: This function is used in the implementation of
  1227. // IPersistStream::Load and IPersistFile::Load when
  1228. // the file is not a docfile.
  1229. // All objects should override this method.
  1230. //
  1231. //---------------------------------------------------------------
  1232. HRESULT
  1233. SrvrDV::LoadFromStream(LPSTREAM pStrm)
  1234. {
  1235. return NOERROR;
  1236. }
  1237. //+---------------------------------------------------------------
  1238. //
  1239. // Member: SrvrDV::SaveToStream, protected
  1240. //
  1241. // Synopsis: Saves the object's persistent state to a stream
  1242. //
  1243. // Arguments: [pStrm] -- stream to save to
  1244. //
  1245. // Returns: Success iff persistent state was written
  1246. //
  1247. // Notes: This function is used in the implementation of
  1248. // IPersistStream::Save and IPersistFile::Save when
  1249. // the file is not a docfile.
  1250. // All objects should override this method.
  1251. //
  1252. //---------------------------------------------------------------
  1253. HRESULT
  1254. SrvrDV::SaveToStream(LPSTREAM pStrm)
  1255. {
  1256. return NOERROR;
  1257. }
  1258. //+---------------------------------------------------------------
  1259. //
  1260. // Member: SrvrDV::GetStreamSizeMax, protected
  1261. //
  1262. // Synopsis: Returns the number of bytes required to serialize object
  1263. //
  1264. // Notes: This function is used in the implementation of
  1265. // IPersistStream::GetSizeMax.
  1266. // All objects should override this method.
  1267. //
  1268. //---------------------------------------------------------------
  1269. DWORD
  1270. SrvrDV::GetStreamSizeMax(void)
  1271. {
  1272. return 0;
  1273. }
  1274. //+---------------------------------------------------------------
  1275. //
  1276. // Member: SrvrDV::GetClassID, public
  1277. //
  1278. // Synopsis: Method of IPersist interface
  1279. //
  1280. // Notes: This method uses the class id in the class descriptor.
  1281. //
  1282. //---------------------------------------------------------------
  1283. STDMETHODIMP
  1284. SrvrDV::GetClassID(LPCLSID lpClassID)
  1285. {
  1286. if (lpClassID == NULL)
  1287. {
  1288. DOUT(TEXT("SrvrDV::GetClassID E_INVALIDARG\r\n"));
  1289. return E_INVALIDARG;
  1290. }
  1291. *lpClassID = _pClass->_clsid;
  1292. return NOERROR;
  1293. }
  1294. //+---------------------------------------------------------------
  1295. //
  1296. // Member: SrvrDV::IsDirty, public
  1297. //
  1298. // Synopsis: Method of IPersistStream/Storage/File interface
  1299. //
  1300. // Notes: This method uses the dirty flag, _fDirty.
  1301. // Objects should not set the _fDirty flag directly
  1302. // but instead call the OnDataChange method to set the
  1303. // flag.
  1304. //
  1305. //---------------------------------------------------------------
  1306. STDMETHODIMP
  1307. SrvrDV::IsDirty(void)
  1308. {
  1309. return (_fDirty ? NOERROR : S_FALSE);
  1310. }
  1311. //+---------------------------------------------------------------
  1312. //
  1313. // Member: SrvrDV::Load, public
  1314. //
  1315. // Synopsis: Method of IPersistStream interface
  1316. //
  1317. // Notes: This function uses the LoadFromStream method and
  1318. // transitions the object to the loaded state if the
  1319. // load was successful.
  1320. //
  1321. //---------------------------------------------------------------
  1322. STDMETHODIMP
  1323. SrvrDV::Load(LPSTREAM pStrm)
  1324. {
  1325. // object can be loaded only once!
  1326. if (_pCtrl->State() != OS_PASSIVE)
  1327. {
  1328. DOUT(TEXT("SrvrDV::Load E_FAIL\r\n"));
  1329. return E_FAIL;
  1330. }
  1331. HRESULT hr;
  1332. if (OK(hr = LoadFromStream(pStrm)))
  1333. hr = _pCtrl->TransitionTo(OS_LOADED);
  1334. return hr;
  1335. }
  1336. //+---------------------------------------------------------------
  1337. //
  1338. // Member: SrvrDV::Save, public
  1339. //
  1340. // Synopsis: Method of IPersistStream interface
  1341. //
  1342. // Notes: This method uses the SaveToStream method and
  1343. // clears the _fDirty flag as appropriate.
  1344. // Containers that have nonserializeable embeddings can
  1345. // override this method and return STG_E_CANTSAVE
  1346. //
  1347. //---------------------------------------------------------------
  1348. STDMETHODIMP
  1349. SrvrDV::Save(LPSTREAM pStrm, BOOL fClearDirty)
  1350. {
  1351. HRESULT hr;
  1352. if (OK(hr = SaveToStream(pStrm)))
  1353. {
  1354. if (fClearDirty)
  1355. {
  1356. _fDirty = FALSE;
  1357. }
  1358. }
  1359. return hr;
  1360. }
  1361. //+---------------------------------------------------------------
  1362. //
  1363. // Member: SrvrDV::GetSizeMax
  1364. //
  1365. // Synopsis: Method of IPersistStream interface
  1366. //
  1367. // Notes:
  1368. //
  1369. //---------------------------------------------------------------
  1370. STDMETHODIMP
  1371. SrvrDV::GetSizeMax(ULARGE_INTEGER FAR * pcbSize)
  1372. {
  1373. if (pcbSize == NULL)
  1374. {
  1375. DOUT(TEXT("SrvrDV::GetSizeMax E_INVALIDARG\r\n"));
  1376. return E_INVALIDARG;
  1377. }
  1378. ULISet32(*pcbSize, GetStreamSizeMax());
  1379. return NOERROR;
  1380. }
  1381. //+---------------------------------------------------------------
  1382. //
  1383. // Member: SrvrDV::LoadFromStorage, protected
  1384. //
  1385. // Synopsis: Loads the object's persistent state from a storage
  1386. //
  1387. // Arguments: [pSg] -- storage to load from
  1388. //
  1389. // Returns: Success iff persistent state was read
  1390. //
  1391. // Notes: This function is used in the implementation of
  1392. // IPersistStorage::Load and IPersistFile::Load when
  1393. // the file is a docfile.
  1394. // This method opens a stream, "CONTENTS", and uses
  1395. // method LoadFromStream to complete the load.
  1396. // Servers that do more sophisticated loading will want
  1397. // to override this method.
  1398. //
  1399. //---------------------------------------------------------------
  1400. HRESULT
  1401. SrvrDV::LoadFromStorage(LPSTORAGE pStg)
  1402. {
  1403. LPSTREAM pStrm;
  1404. HRESULT hr;
  1405. if (OK(hr = pStg->OpenStream(szContents, NULL, STGM_SRO, 0, &pStrm)))
  1406. {
  1407. hr = LoadFromStream(pStrm);
  1408. pStrm->Release();
  1409. }
  1410. return hr;
  1411. }
  1412. //+---------------------------------------------------------------
  1413. //
  1414. // Member: SrvrDV::SaveToStorage
  1415. //
  1416. // Synopsis: Saves the object's persistent state to a storage
  1417. //
  1418. // Arguments: [pSg] -- storage to save to
  1419. //
  1420. // Returns: Success iff persistent state was written
  1421. //
  1422. // Notes: This function is used in the implementation of
  1423. // IPersistStorage::Save and IPersistFile::Save when
  1424. // the file is a docfile.
  1425. // This method opens a stream, "CONTENTS", and uses
  1426. // method SaveToStream to complete the save.
  1427. // Servers that do more sophisticated saving will want
  1428. // to override this method.
  1429. //
  1430. //---------------------------------------------------------------
  1431. HRESULT
  1432. SrvrDV::SaveToStorage(LPSTORAGE pStg, BOOL fSameAsLoad)
  1433. {
  1434. // write our native data stream
  1435. HRESULT hr;
  1436. LPSTREAM pStrm;
  1437. hr = pStg->CreateStream(szContents, STGM_SALL|STGM_CREATE, 0L, 0L, &pStrm);
  1438. if (OK(hr))
  1439. {
  1440. hr = SaveToStream(pStrm);
  1441. pStrm->Release();
  1442. }
  1443. return hr;
  1444. }
  1445. //+---------------------------------------------------------------
  1446. //
  1447. // Member: SrvrDV::InitNew
  1448. //
  1449. // Synopsis: IPersistStorage Method
  1450. //
  1451. // Notes: This method transitions the object to loaded.
  1452. //
  1453. //---------------------------------------------------------------
  1454. STDMETHODIMP
  1455. SrvrDV::InitNew(LPSTORAGE pStg)
  1456. {
  1457. //
  1458. //REVIEW: what happens if we attempt to load the same ctrl more than once?
  1459. //
  1460. if (pStg == NULL)
  1461. {
  1462. DOUT(TEXT("SrvrDV::InitNew E_INVALIDARG\r\n"));
  1463. return E_INVALIDARG;
  1464. }
  1465. HRESULT hr;
  1466. if (OK(hr = _pCtrl->TransitionTo(OS_LOADED)))
  1467. (_pStg = pStg)->AddRef(); // hold on to the storage
  1468. return hr;
  1469. }
  1470. //+---------------------------------------------------------------
  1471. //
  1472. // Member: SrvrDV::Load
  1473. //
  1474. // Synopsis: IPersistStorage Method
  1475. //
  1476. // Notes: This method loads the object using LoadFromStorage and
  1477. // then transitions the object to loaded.
  1478. // A pointer to our storage is maintained in member variable
  1479. // _pStg.
  1480. //
  1481. //---------------------------------------------------------------
  1482. STDMETHODIMP
  1483. SrvrDV::Load(LPSTORAGE pStg)
  1484. {
  1485. // object can be loaded only once!
  1486. if (_pCtrl->State() != OS_PASSIVE)
  1487. {
  1488. DOUT(TEXT("SrvrDV::Load E_FAIL\r\n"));
  1489. return E_FAIL;
  1490. }
  1491. if (pStg == NULL)
  1492. {
  1493. DOUT(TEXT("SrvrDV::Load E_INVALIDARG\r\n"));
  1494. return E_INVALIDARG;
  1495. }
  1496. // do the load and move to the loaded state
  1497. HRESULT hr;
  1498. if (OK(hr = LoadFromStorage(pStg)))
  1499. {
  1500. if (OK(hr = _pCtrl->TransitionTo(OS_LOADED)))
  1501. {
  1502. (_pStg = pStg)->AddRef();
  1503. }
  1504. }
  1505. return hr;
  1506. }
  1507. //+---------------------------------------------------------------
  1508. //
  1509. // Member: SrvrDV::Save
  1510. //
  1511. // Synopsis: Method of IPersistStorage interface
  1512. //
  1513. // Notes: This method uses SaveToStorage to write the persistent
  1514. // state. It also writes the full user type string to the
  1515. // storage as is required.
  1516. //
  1517. //---------------------------------------------------------------
  1518. STDMETHODIMP
  1519. SrvrDV::Save(LPSTORAGE pStg, BOOL fSameAsLoad)
  1520. {
  1521. if (pStg == NULL)
  1522. {
  1523. DOUT(TEXT("SrvrDV::Save E_INVALIDARG\r\n"));
  1524. return E_INVALIDARG;
  1525. }
  1526. // write our native data stream
  1527. HRESULT hr;
  1528. if (OK(hr = SaveToStorage(pStg, fSameAsLoad)))
  1529. {
  1530. // Write the UserType string. We don't let this fail the operation.
  1531. WriteFmtUserTypeStg(pStg,
  1532. 0,
  1533. _pClass->_szUserClassType[USERCLASSTYPE_FULL]);
  1534. _fNoScribble = TRUE;
  1535. }
  1536. return hr;
  1537. }
  1538. //+---------------------------------------------------------------
  1539. //
  1540. // Member: SrvrDV::SaveCompleted
  1541. //
  1542. // Synopsis: Method of IPersistStorage interface
  1543. //
  1544. // Notes: This method clears the dirty flag and updates our
  1545. // storage pointer, _pStg, if required.
  1546. // Servers that are also containers will want to override
  1547. // this method to pass the call recursively to all loaded
  1548. // embeddings.
  1549. //
  1550. //---------------------------------------------------------------
  1551. STDMETHODIMP
  1552. SrvrDV::SaveCompleted(LPSTORAGE pStg)
  1553. {
  1554. // if pStg is non-null then we are coming out of HANDS-OFF mode,
  1555. // otherwise we are coming out of NO-SCRIBBLE mode.
  1556. if (pStg != NULL)
  1557. {
  1558. // We should be in HANDS-OFF mode and hence able to Assert that
  1559. // _pStg is NULL here by virtue of the HandsOffStorage call.
  1560. // However, the official OLE sample container app "Outline"
  1561. // fail to make the HandsOffStorage call.
  1562. // In order to be robust we release our _pStg handle if it is
  1563. // "illegally" NON-NULL
  1564. //
  1565. if (_pStg != NULL)
  1566. {
  1567. DOUT(TEXT("SrvrDV: WARNING! SaveCompleted: "));
  1568. DOUT(TEXT("SrvrDV: Container failed to make required HandsOffStorage call.\n"));
  1569. _pStg->Release();
  1570. }
  1571. (_pStg = pStg)->AddRef(); // hold on to the new storage
  1572. }
  1573. _fDirty = FALSE; // clear our dirty flag
  1574. _fNoScribble = FALSE; // we are out of NO-SCRIBBLE mode
  1575. //REVIEW: should we advise in the case we are not fRemembering?
  1576. if (_pCtrl != NULL)
  1577. _pCtrl->OnSave(); // and notify any advises that we have saved
  1578. return NOERROR;
  1579. }
  1580. //+---------------------------------------------------------------
  1581. //
  1582. // Member: SrvrDV::HandsOffStorage
  1583. //
  1584. // Synopsis: Method of IPersistStorage interface
  1585. //
  1586. // Notes: This method releases the storage we are holding on to.
  1587. // Servers that are also containers will want to override
  1588. // this method to pass the call recursively to all loaded
  1589. // embeddings.
  1590. //
  1591. //---------------------------------------------------------------
  1592. STDMETHODIMP
  1593. SrvrDV::HandsOffStorage(void)
  1594. {
  1595. if (_pStg != NULL)
  1596. _pStg->Release();
  1597. _pStg = NULL;
  1598. return NOERROR;
  1599. }
  1600. //+---------------------------------------------------------------
  1601. //
  1602. // Member: SrvrDV::Load, public
  1603. //
  1604. // Synopsis: Method of IPersistFile interface
  1605. //
  1606. // Notes: This opens the file as a docfile and uses IPersistStorage::Load
  1607. // to complete the operation.
  1608. //
  1609. //---------------------------------------------------------------
  1610. STDMETHODIMP
  1611. SrvrDV::Load(LPCOLESTR lpstrFile, DWORD grfMode)
  1612. {
  1613. // use the default storage modes if no flags were specified
  1614. if (grfMode == 0)
  1615. grfMode = STGM_DFRALL;
  1616. // if they didn't specify a share mode then use deny-write
  1617. if ( (grfMode & STGM_SHARE) == 0)
  1618. grfMode |= STGM_SHARE_DENY_WRITE;
  1619. // of course, we use transacted mode
  1620. grfMode |= STGM_TRANSACTED;
  1621. HRESULT hr;
  1622. if (lpstrFile == NULL)
  1623. {
  1624. // lpstrFile NULL is a special-case indicating that we should
  1625. // create a temporary docfile for the new file case
  1626. //
  1627. grfMode |= STGM_CREATE | STGM_DELETEONRELEASE;
  1628. LPSTORAGE pStg;
  1629. if (OK(hr = StgCreateDocfile(NULL, grfMode, 0L, &pStg)))
  1630. {
  1631. hr = InitNew(pStg);
  1632. // IPersistStorage::InitNew will hold on to the pStg
  1633. pStg->Release();
  1634. }
  1635. return hr;
  1636. }
  1637. LPSTORAGE pStg;
  1638. if (OK(hr = StgOpenStorage(lpstrFile, NULL, grfMode, NULL, 0L, &pStg)))
  1639. {
  1640. hr = Load(pStg);
  1641. // IPersistStorage::Load will hold on to the pStg
  1642. pStg->Release();
  1643. }
  1644. //REVIEW: Is the first SetMoniker happening correctly?
  1645. return hr;
  1646. }
  1647. //+---------------------------------------------------------------
  1648. //
  1649. // Member: SrvrDV::Save, public
  1650. //
  1651. // Synopsis: Method of IPersistFile interface
  1652. //
  1653. // Notes: If a file is specified then this creates a docfile and
  1654. // uses IPersistStorage::Save to complete the operation.
  1655. //
  1656. //---------------------------------------------------------------
  1657. STDMETHODIMP
  1658. SrvrDV::Save(LPCOLESTR lpstrFile, BOOL fRemember)
  1659. {
  1660. // if lpstrFile is NULL that means that we should save from where we
  1661. // loaded. Otherwise create a docfile with the specified name
  1662. HRESULT hr = NOERROR;
  1663. LPSTORAGE pStg;
  1664. if (lpstrFile == NULL)
  1665. (pStg = _pStg)->AddRef();
  1666. else
  1667. hr = StgCreateDocfile(lpstrFile, STGM_DFRALL|STGM_CREATE, 0L, &pStg);
  1668. if (OK(hr))
  1669. {
  1670. hr = OleSave((LPPERSISTSTORAGE)this, pStg, pStg == _pStg);
  1671. if (OK(hr))
  1672. {
  1673. // if we are to remember this storage then release our old
  1674. // storage and hold on to the new.
  1675. // Otherwise, wrap up a storage save by the usual SaveCompleted.
  1676. if (lpstrFile != NULL && fRemember)
  1677. {
  1678. // release our previous storage or stream
  1679. // and hold on to our new
  1680. HandsOffStorage();
  1681. ((LPPERSISTSTORAGE)this)->SaveCompleted(pStg);
  1682. }
  1683. else
  1684. {
  1685. // If we did a storage save and we are not switching to a new
  1686. // storage then we complete the transaction with a SaveCompleted.
  1687. ((LPPERSISTSTORAGE)this)->SaveCompleted(NULL);
  1688. }
  1689. }
  1690. // Release the storage. If we are supposed to hold on
  1691. // to it then we have already add-ref'd it.
  1692. pStg->Release();
  1693. }
  1694. // if we have renamed then
  1695. if (lpstrFile != NULL)
  1696. {
  1697. // TBD: Send On_Renamed advise?
  1698. //
  1699. // inform our object of its new moniker
  1700. //
  1701. LPMONIKER pmk;
  1702. if (OK(CreateFileMoniker(lpstrFile, &pmk)))
  1703. {
  1704. _pCtrl->SetMoniker(OLEWHICHMK_OBJFULL, pmk);
  1705. pmk->Release();
  1706. }
  1707. }
  1708. return hr;
  1709. }
  1710. //+---------------------------------------------------------------
  1711. //
  1712. // Member: SrvrDV::SaveCompleted, public
  1713. //
  1714. // Synopsis: Method of IPersistFile interface
  1715. //
  1716. //---------------------------------------------------------------
  1717. STDMETHODIMP
  1718. SrvrDV::SaveCompleted(LPCOLESTR lpstrFile)
  1719. {
  1720. //REVIEW: should we launch advise in the case we are not fRemembering?
  1721. if (_pCtrl != NULL)
  1722. _pCtrl->OnSave(); // and notify any advises that we have saved
  1723. return NOERROR;
  1724. }
  1725. //+---------------------------------------------------------------
  1726. //
  1727. // Member: SrvrDV::GetCurFile, public
  1728. //
  1729. // Synopsis: Method of IPersistFile interface
  1730. //
  1731. //---------------------------------------------------------------
  1732. STDMETHODIMP
  1733. SrvrDV::GetCurFile(LPOLESTR FAR * ppstrFile)
  1734. {
  1735. if (ppstrFile == NULL)
  1736. {
  1737. DOUT(TEXT("SrvrDV::GetCurFile E_INVALIDARG\r\n"));
  1738. return E_INVALIDARG;
  1739. }
  1740. *ppstrFile = 0; //set out params to NULL
  1741. HRESULT hr;
  1742. // if we don't currently have a file then return the default filename
  1743. if (_pStg == NULL)
  1744. {
  1745. // the default filename is *.ext where ext is our docfile extension
  1746. OLECHAR szDefault[6];
  1747. #if defined(OLE2ANSI)
  1748. wsprintf(szDefault, TEXT("*%s"), _pClass->_szDocfileExt);
  1749. #else
  1750. wsprintfW(szDefault, OLETEXT("*%ws"), _pClass->_szDocfileExt);
  1751. #endif
  1752. hr = TaskAllocString(szDefault, ppstrFile);
  1753. }
  1754. else
  1755. {
  1756. // the caller will free the task-allocated file name
  1757. STATSTG statstg;
  1758. if (OK(hr = _pStg->Stat(&statstg, STATFLAG_DEFAULT)))
  1759. *ppstrFile = statstg.pwcsName;
  1760. }
  1761. return hr;
  1762. }
  1763.