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.

2454 lines
63 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: api.cpp
  7. //
  8. // Contents: OLE2 api definitions.
  9. //
  10. // Classes: none
  11. //
  12. // Functions: OleRun
  13. // OleIsRunning
  14. // OleLockRunning
  15. // OleSetContainedObject
  16. // OleNoteObjectVisible
  17. // OleGetData
  18. // OleSetData
  19. // OleSave
  20. // ReadClassStg
  21. // WriteClassStg
  22. // WriteFmtUserTypeStg
  23. // ReadFmtUserTypeStg
  24. // ReadM1ClassStm (internal)
  25. // WriteM1ClassStm (internal)
  26. // ReadClassStm
  27. // WriteClassStm
  28. // ReleaseStgMedium
  29. // OleDuplicateData
  30. // ReadOleStg (internal)
  31. // WriteOleStg (internal)
  32. // GetDocumentBitStg (internal and unused)
  33. // GetConvertStg
  34. // SetConvertStg
  35. // ReadClipformatStm
  36. // WriteClipformatStm
  37. // WriteMonikerStm
  38. // ReadMonikerStm
  39. // OleDraw
  40. // CreateObjectDescriptor (internal (for now))
  41. //
  42. // History: dd-mmm-yy Author Comment
  43. // 20-Feb-95 KentCe Buffer version of Read/WriteM1ClassStm.
  44. // 04-Jun-94 alexgo added CreateObjectDescriptor and
  45. // enhanced metafile support
  46. // 25-Jan-94 alexgo first pass at Cairo-style memory allocation
  47. // 11-Jan-94 chriswe fixed broken asserts
  48. // 11-Jan-94 alexgo added VDATEHEAP macros to every function
  49. // and fixed compile warnings
  50. // 08-Dec-93 ChrisWe added necessary casts to GlobalLock() calls
  51. // resulting from removing bogus GlobalLock() macros in
  52. // le2int.h
  53. // 21-Oct-93 Alex Gounares (alexgo) 32-bit port, commented
  54. // and substantial cleanup
  55. // (curts) 11/01/92 Added OleDuplicateMedium
  56. // (srinik) 06/22/92 Moved ReadStringStream, WriteStringStream
  57. // to "utstream.cpp"
  58. // (barrym) 06/02/92 Moved OleSave, ReadClassStg,
  59. // WriteClassStg, added
  60. // OleSaveCompleted, OleIsDirty
  61. // 28-May-92 Srini Koppolu (srinik) Original Author
  62. //
  63. //--------------------------------------------------------------------------
  64. // REVIEW FINAL: probably want to change all pstm->Read into StRead(pstm...)
  65. // except if spec issue 313 is accepted in which case we change StRead into
  66. // pstm->Read.
  67. #include <le2int.h>
  68. #pragma SEG(api)
  69. #define COMPOBJSTM_HEADER_SIZE 7
  70. #ifndef _MAC
  71. FARINTERNAL_(HBITMAP) BmDuplicate(HBITMAP hold, DWORD FAR* lpdwSize,
  72. LPBITMAP lpBm);
  73. #endif
  74. NAME_SEG(Api)
  75. ASSERTDATA
  76. #define MAX_STR 512
  77. #ifndef WIN32
  78. // WIN16 uses remove()
  79. #include <stdio.h>
  80. #endif
  81. DWORD gdwFirstDword = (DWORD)MAKELONG(COMPOBJ_STREAM_VERSION,
  82. BYTE_ORDER_INDICATOR);
  83. DWORD gdwOleVersion = MAKELONG(OLE_STREAM_VERSION, OLE_PRODUCT_VERSION);
  84. //+-------------------------------------------------------------------------
  85. //
  86. // Function: OleRun
  87. //
  88. // Synopsis: Calls IRunnableObject->Run on a given object
  89. //
  90. // Effects: Usually puts on object in the RunningObjectTable
  91. //
  92. // Arguments: [lpUnkown] -- Pointer to the object
  93. //
  94. // Requires:
  95. //
  96. // Returns: The HRESULT from the Run method.
  97. //
  98. // Signals:
  99. //
  100. // Modifies:
  101. //
  102. // Algorithm:
  103. //
  104. // History: dd-mmm-yy Author Comment
  105. // 21-Oct-93 alexgo ported to 32bit
  106. //
  107. // Notes:
  108. //
  109. //--------------------------------------------------------------------------
  110. #pragma SEG(OleRun)
  111. STDAPI OleRun(IUnknown FAR* lpUnknown)
  112. {
  113. OLETRACEIN((API_OleRun, PARAMFMT("lpUnknown= %p"), lpUnknown));
  114. VDATEHEAP();
  115. HRESULT hresult;
  116. IRunnableObject FAR* pRO;
  117. VDATEIFACE_LABEL(lpUnknown, errRtn, hresult);
  118. if (lpUnknown->QueryInterface(IID_IRunnableObject, (LPLPVOID)&pRO)
  119. != NOERROR)
  120. {
  121. // if no IRunnableObject, assume already running
  122. hresult = NOERROR;
  123. goto errRtn;
  124. }
  125. hresult = pRO->Run(NULL);
  126. pRO->Release();
  127. errRtn:
  128. OLETRACEOUT((API_OleRun, hresult));
  129. return hresult;
  130. }
  131. //+-------------------------------------------------------------------------
  132. //
  133. // Function: OleIsRunning
  134. //
  135. // Synopsis: calls IRunnableObject->IsRunning on the given object
  136. //
  137. // Effects: Usually returns whether or not an object is in the
  138. // Running Object Table.
  139. //
  140. // Arguments: [lpOleObj] -- pointer to the object
  141. //
  142. // Requires:
  143. //
  144. // Returns: TRUE or FALSE (from IRO->IsRunning)
  145. //
  146. // Signals:
  147. //
  148. // Modifies:
  149. //
  150. // Algorithm:
  151. //
  152. // History: dd-mmm-yy Author Comment
  153. // 21-Oct-93 alexgo ported to 32bit
  154. //
  155. // Notes:
  156. //
  157. //--------------------------------------------------------------------------
  158. #pragma SEG(OleIsRunning)
  159. STDAPI_(BOOL) OleIsRunning(IOleObject FAR* lpOleObj)
  160. {
  161. OLETRACEIN((API_OleIsRunning, PARAMFMT("lpOleObj= %p"), lpOleObj));
  162. VDATEHEAP();
  163. IRunnableObject FAR* pRO;
  164. BOOL bRetval;
  165. GEN_VDATEIFACE_LABEL(lpOleObj, FALSE, errRtn, bRetval);
  166. if (lpOleObj->QueryInterface(IID_IRunnableObject, (LPLPVOID)&pRO)
  167. != NOERROR)
  168. {
  169. // if no IRunnableObject, assume already running
  170. bRetval = TRUE;
  171. goto errRtn;
  172. }
  173. bRetval = pRO->IsRunning();
  174. pRO->Release();
  175. errRtn:
  176. OLETRACEOUTEX((API_OleIsRunning, RETURNFMT("%B"), bRetval));
  177. return bRetval;
  178. }
  179. //+-------------------------------------------------------------------------
  180. //
  181. // Function: OleLockRunning
  182. //
  183. // Synopsis: calls IRunnableObject->LockRunning on the given object
  184. //
  185. // Effects: The object usually ends up calling CoLockObjectExternal
  186. // on itself
  187. //
  188. // Arguments: [lpUnknown] -- pointer to the object
  189. // [fLock] -- TRUE == lock running
  190. // FALSE == unlock running
  191. // [fLastUnlockCloses] -- if TRUE, IRO->LockRunning
  192. // is supposed to call IOO->Close
  193. // if this was the last unlock
  194. //
  195. // Requires:
  196. //
  197. // Returns: HRESULT from IRunnableObject->LockRunning()
  198. //
  199. // Signals:
  200. //
  201. // Modifies:
  202. //
  203. // Algorithm:
  204. //
  205. // History: dd-mmm-yy Author Comment
  206. // 21-Oct-93 alexgo 32bit port, changed GEN_VDATEIFACE
  207. // to VDATEIFACE to fix a bug
  208. // Notes:
  209. //
  210. //--------------------------------------------------------------------------
  211. #pragma SEG(OleLockRunning)
  212. STDAPI OleLockRunning(LPUNKNOWN lpUnknown, BOOL fLock, BOOL fLastUnlockCloses)
  213. {
  214. OLETRACEIN((API_OleLockRunning, PARAMFMT("lpUnknown= %p, fLock= %B, fLastUnlockCloses= %B"),
  215. lpUnknown, fLock, fLastUnlockCloses));
  216. VDATEHEAP();
  217. IRunnableObject FAR* pRO;
  218. HRESULT hresult;
  219. VDATEIFACE_LABEL(lpUnknown, errRtn, hresult);
  220. if (lpUnknown->QueryInterface(IID_IRunnableObject, (LPLPVOID)&pRO)
  221. != NOERROR)
  222. {
  223. // if no IRunnableObject, no locks
  224. hresult = NOERROR;
  225. goto errRtn;
  226. }
  227. hresult = pRO->LockRunning(fLock, fLastUnlockCloses);
  228. pRO->Release();
  229. errRtn:
  230. OLETRACEOUT((API_OleLockRunning, hresult));
  231. return hresult;
  232. }
  233. //+-------------------------------------------------------------------------
  234. //
  235. // Function: OleSetContainedObject
  236. //
  237. // Synopsis: calls IRunnableObject->SetContainedObject on the given object
  238. //
  239. // Effects: Usually has the effect of calling CoLockObjectExternal
  240. // (lpUnkown, !fContained, FALSE).
  241. //
  242. // Arguments: [lpUnknown] -- pointer to the object
  243. // [fContained] -- if TRUE, the object is an embedding
  244. //
  245. // Requires:
  246. //
  247. // Returns: HRESULT from the IRO->SetContainedObject call
  248. //
  249. // Signals:
  250. //
  251. // Modifies:
  252. //
  253. // Algorithm:
  254. //
  255. // History: dd-mmm-yy Author Comment
  256. // 21-Oct-92 alexgo 32bit port, changed GEN_VDATEIFACE to
  257. // VDATEIFACE to fix a bug
  258. //
  259. // Notes: Containers usually call OleSetContainedObject(..,TRUE) after
  260. // OleLoad or OleCreate. The basic idea is to tell OLE that
  261. // the object is an embedding. The real effect is to unlock
  262. // the object (since all objects start out locked) so that
  263. // other connections may determine it's fate while invisible.
  264. // OleNoteObjectVisible, for instance, would be called to lock
  265. // the object when it become visible.
  266. //
  267. //
  268. //--------------------------------------------------------------------------
  269. #pragma SEG(OleSetContainedObject)
  270. STDAPI OleSetContainedObject(LPUNKNOWN lpUnknown, BOOL fContained)
  271. {
  272. OLETRACEIN((API_OleSetContainedObject, PARAMFMT("lpUnknown= %p, fContained= %B"),
  273. lpUnknown, fContained));
  274. VDATEHEAP();
  275. IRunnableObject FAR* pRO;
  276. HRESULT hresult;
  277. VDATEIFACE_LABEL(lpUnknown, errRtn, hresult);
  278. if (lpUnknown->QueryInterface(IID_IRunnableObject, (LPLPVOID)&pRO)
  279. != NOERROR)
  280. {
  281. // if no IRunnableObject, assume container-ness doesn't matter
  282. hresult = NOERROR;
  283. goto errRtn;
  284. }
  285. hresult = pRO->SetContainedObject(fContained);
  286. pRO->Release();
  287. errRtn:
  288. OLETRACEOUT((API_OleSetContainedObject, hresult));
  289. return hresult;
  290. }
  291. //+-------------------------------------------------------------------------
  292. //
  293. // Function: OleNoteObjectVisible
  294. //
  295. // Synopsis: Simple calls CoLockObjectExternal
  296. //
  297. // Effects:
  298. //
  299. // Arguments: [lpUnknown] -- pointer to the object
  300. // [fVisible] -- if TRUE, then lock the object,
  301. // if false, then unlock
  302. //
  303. // Requires:
  304. //
  305. // Returns: HRESULT from CoLockObjectExternal
  306. //
  307. // Signals:
  308. //
  309. // Modifies:
  310. //
  311. // Algorithm:
  312. //
  313. // History: dd-mmm-yy Author Comment
  314. // 21-Oct-93 alexgo 32bit port
  315. //
  316. // Notes:
  317. //
  318. //--------------------------------------------------------------------------
  319. #pragma SEG(OleNoteObjectVisible)
  320. STDAPI OleNoteObjectVisible(LPUNKNOWN pUnknown, BOOL fVisible)
  321. {
  322. OLETRACEIN((API_OleNoteObjectVisible, PARAMFMT("pUnknown= %p, fVisible= %B"),
  323. pUnknown, fVisible));
  324. VDATEHEAP();
  325. // NOTE: we as fLastUnlockReleases=TRUE here because there would
  326. // otherwise be no other way to fully release the stubmgr. This
  327. // means that objects can't use this mechanism to hold invisible
  328. // objects alive.
  329. HRESULT hr;
  330. hr = CoLockObjectExternal(pUnknown, fVisible, TRUE);
  331. OLETRACEOUT((API_OleNoteObjectVisible, hr));
  332. return hr;
  333. }
  334. //+-------------------------------------------------------------------------
  335. //
  336. // Function: OleSave
  337. //
  338. // Synopsis: Writes the CLSID to the storage and calls IPersistStorage->
  339. // Save()
  340. //
  341. // Effects:
  342. //
  343. // Arguments: [pPS] -- pointer to the IPersistStorage interface
  344. // on the object to be saved
  345. // [pstgSave] -- pointer to the storage to which the object
  346. // should be saved
  347. // [fSameAsLoad] -- FALSE indicates a SaveAs operation
  348. //
  349. // Requires:
  350. //
  351. // Returns: HRESULT
  352. //
  353. // Signals:
  354. //
  355. // Modifies:
  356. //
  357. // Algorithm:
  358. //
  359. // History: dd-mmm-yy Author Comment
  360. // 22-Oct-93 alexgo 32bit port
  361. //
  362. // Notes:
  363. //
  364. //--------------------------------------------------------------------------
  365. #pragma SEG(OleSave)
  366. STDAPI OleSave(
  367. IPersistStorage FAR* pPS,
  368. IStorage FAR* pstgSave,
  369. BOOL fSameAsLoad
  370. )
  371. {
  372. OLETRACEIN((API_OleSave, PARAMFMT("pPS= %p, pstgSave= %p, fSameAsLoad= %B"),
  373. pPS, pstgSave, fSameAsLoad));
  374. VDATEHEAP();
  375. HRESULT hresult;
  376. CLSID clsid;
  377. VDATEIFACE_LABEL(pPS, errRtn, hresult);
  378. VDATEIFACE_LABEL(pstgSave, errRtn, hresult);
  379. if (hresult = pPS->GetClassID(&clsid))
  380. {
  381. goto errRtn;
  382. }
  383. if (hresult = WriteClassStg(pstgSave, clsid))
  384. {
  385. goto errRtn;
  386. }
  387. if ((hresult = pPS->Save(pstgSave, fSameAsLoad)) == NOERROR)
  388. {
  389. hresult = pstgSave->Commit(0);
  390. }
  391. errRtn:
  392. OLETRACEOUT((API_OleSave, hresult));
  393. return hresult;
  394. }
  395. //+-------------------------------------------------------------------------
  396. //
  397. // Function: ReadClassStg
  398. //
  399. // Synopsis: Calls IStorage->Stat to get the CLSID from the given storage
  400. //
  401. // Effects:
  402. //
  403. // Arguments: [pstg] -- pointer to the storage
  404. // [pclsid] -- place to return the CLSID
  405. //
  406. // Requires:
  407. //
  408. // Returns: HRESULT from the IS->Stat call
  409. //
  410. // Signals:
  411. //
  412. // Modifies:
  413. //
  414. // Algorithm:
  415. //
  416. // History: dd-mmm-yy Author Comment
  417. // 22-Oct-93 alexgo 32bit port, fixed bug with invalid
  418. // [pclsid] and error on IS->Stat
  419. //
  420. // Notes:
  421. //
  422. //--------------------------------------------------------------------------
  423. #pragma SEG(ReadClassStg)
  424. STDAPI ReadClassStg( IStorage FAR * pstg, LPCLSID pclsid)
  425. {
  426. OLETRACEIN((API_ReadClassStg, PARAMFMT("pstg= %p, pclsid= %p"),
  427. pstg, pclsid));
  428. VDATEHEAP();
  429. HRESULT hresult;
  430. STATSTG statstg;
  431. VDATEIFACE_LABEL(pstg, errRtn, hresult);
  432. VDATEPTROUT_LABEL(pclsid, CLSID, errRtn, hresult);
  433. if ((hresult = pstg->Stat(&statstg, STATFLAG_NONAME)) != NOERROR)
  434. {
  435. *pclsid = CLSID_NULL;
  436. goto errRtn;
  437. }
  438. *pclsid = statstg.clsid;
  439. errRtn:
  440. OLETRACEOUT((API_ReadClassStg, hresult));
  441. return hresult;
  442. }
  443. //+-------------------------------------------------------------------------
  444. //
  445. // Function: WriteClassStg
  446. //
  447. // Synopsis: Calls IStorage->SetClass to store the CLSID in the given
  448. // storage
  449. //
  450. // Effects:
  451. //
  452. // Arguments: [pstg] -- pointer to the storage
  453. // [clsid] -- the CLSID to write into the storage
  454. //
  455. // Requires:
  456. //
  457. // Returns: HRESULT from the IS->SetClass call
  458. //
  459. // Signals:
  460. //
  461. // Modifies:
  462. //
  463. // Algorithm:
  464. //
  465. // History: dd-mmm-yy Author Comment
  466. // 22-Oct-93 alexgo 32bit port
  467. //
  468. // Notes:
  469. //
  470. //--------------------------------------------------------------------------
  471. #pragma SEG(WriteClassStg)
  472. STDAPI WriteClassStg( IStorage FAR * pstg, REFCLSID clsid)
  473. {
  474. OLETRACEIN((API_WriteClassStg, PARAMFMT("pstg= %p, clsid= %I"),
  475. pstg, &clsid));
  476. VDATEHEAP();
  477. HRESULT hr;
  478. VDATEIFACE_LABEL(pstg, errRtn, hr);
  479. // write clsid in storage (what is read above)
  480. hr = pstg->SetClass(clsid);
  481. errRtn:
  482. OLETRACEOUT((API_WriteClassStg, hr));
  483. return hr;
  484. }
  485. //+-------------------------------------------------------------------------
  486. //
  487. // Function: ReadM1ClassStm
  488. //
  489. // Synopsis: Reads -1L, CLSID from the given stream
  490. //
  491. // Effects:
  492. //
  493. // Arguments: [pStm] -- pointer to the stream
  494. // [pclsid] -- where to put the clsid
  495. //
  496. // Requires:
  497. //
  498. // Returns: HRESULT from the ReadM1ClassStm.
  499. //
  500. // Signals:
  501. //
  502. // Modifies:
  503. //
  504. // Algorithm:
  505. //
  506. // History: dd-mmm-yy Author Comment
  507. // 24-Oct-93 alexgo 32bit port
  508. // 20-Feb-95 KentCe Convert to buffered stream reads.
  509. //
  510. // Notes: Internal API.
  511. //
  512. // Reads -1L and CLSID from stream swapping bytes on
  513. // big-endian machines
  514. //
  515. //--------------------------------------------------------------------------
  516. STDAPI ReadM1ClassStm(LPSTREAM pStm, LPCLSID pclsid)
  517. {
  518. VDATEHEAP();
  519. CStmBufRead StmRead;
  520. HRESULT error;
  521. StmRead.Init(pStm);
  522. error = ReadM1ClassStmBuf(StmRead, pclsid);
  523. if (error != NOERROR)
  524. *pclsid = CLSID_NULL;
  525. StmRead.Release();
  526. return error;
  527. }
  528. //+-------------------------------------------------------------------------
  529. //
  530. // Function: WriteM1ClassStm
  531. //
  532. // Synopsis: Writes -1L, CLSID to the given stream
  533. //
  534. // Effects:
  535. //
  536. // Arguments: [pStm] -- pointer to the stream
  537. // [clsid] -- CLSID to be written
  538. //
  539. // Requires:
  540. //
  541. // Returns: HRESULT from the WriteM1ClassStm
  542. //
  543. // Signals:
  544. //
  545. // Modifies:
  546. //
  547. // Algorithm:
  548. //
  549. // History: dd-mmm-yy Author Comment
  550. // 11-Jan-84 alexgo changed dw from a DWORD to a LONG
  551. // 24-Oct-93 alexgo 32bit port
  552. // 20-Feb-95 KentCe Convert to buffered stream writes.
  553. //
  554. // Notes: Internal API.
  555. //
  556. // Writess -1L and CLSID from stream swapping bytes on
  557. // big-endian machines
  558. //
  559. //--------------------------------------------------------------------------
  560. STDAPI WriteM1ClassStm(LPSTREAM pStm, REFCLSID clsid)
  561. {
  562. VDATEHEAP();
  563. CStmBufWrite StmWrite;
  564. HRESULT error;
  565. VDATEIFACE( pStm );
  566. StmWrite.Init(pStm);
  567. error = WriteM1ClassStmBuf(StmWrite, clsid);
  568. if (FAILED(error))
  569. {
  570. goto errRtn;
  571. }
  572. error = StmWrite.Flush();
  573. errRtn:
  574. StmWrite.Release();
  575. return error;
  576. }
  577. //+-------------------------------------------------------------------------
  578. //
  579. // Function: ReadM1ClassStmBuf
  580. //
  581. // Synopsis: Reads -1L and CLSID from the given buffered stream.
  582. //
  583. // Arguments: [StmRead] -- Stream Read Object.
  584. // [pclsid] -- Where to put the clsid
  585. //
  586. // Returns: HRESULT from the StmRead.Read's
  587. //
  588. //
  589. // History: dd-mmm-yy Author Comment
  590. // 20-Feb-95 KentCe Convert to buffered stream reads.
  591. // 24-Oct-93 alexgo 32bit port
  592. //
  593. // Notes: Internal API.
  594. //
  595. // Reads -1L and CLSID from stream swapping bytes on
  596. // big-endian machines
  597. //
  598. //--------------------------------------------------------------------------
  599. STDAPI ReadM1ClassStmBuf(CStmBufRead & StmRead, LPCLSID pclsid)
  600. {
  601. VDATEHEAP();
  602. HRESULT error;
  603. LONG lValue;
  604. if ((error = StmRead.ReadLong(&lValue)) != NOERROR)
  605. {
  606. goto errRtn;
  607. }
  608. if (lValue == -1)
  609. {
  610. // have a GUID
  611. error = StmRead.Read((void FAR *)pclsid, sizeof(CLSID));
  612. }
  613. else
  614. {
  615. // this is now an error; we don't allow string form
  616. // of clsid anymore
  617. error = ResultFromScode(E_UNSPEC);
  618. }
  619. errRtn:
  620. if (error != NOERROR)
  621. {
  622. *pclsid = CLSID_NULL;
  623. }
  624. return error;
  625. }
  626. //+-------------------------------------------------------------------------
  627. //
  628. // Function: WriteM1ClassStmBuf
  629. //
  630. // Synopsis: Writes -1L and CLSID to the given buffered stream.
  631. //
  632. // Arguments: [StmRead] -- Stream Write Object.
  633. // [pclsid] -- Where to read the clsid
  634. //
  635. // Returns: HRESULT from the StmWrite.Write's
  636. //
  637. //
  638. // History: dd-mmm-yy Author Comment
  639. // 20-Feb-95 KentCe Convert to buffered stream reads.
  640. // 24-Oct-93 alexgo 32bit port
  641. //
  642. // Notes: Internal API.
  643. //
  644. // Writess -1L and CLSID from stream swapping bytes on
  645. // big-endian machines
  646. //
  647. //--------------------------------------------------------------------------
  648. STDAPI WriteM1ClassStmBuf(CStmBufWrite & StmWrite, REFCLSID clsid)
  649. {
  650. VDATEHEAP();
  651. HRESULT error;
  652. // format is -1L followed by GUID
  653. if ((error = StmWrite.WriteLong(-1)) != NOERROR)
  654. return error;
  655. return StmWrite.Write((LPVOID)&clsid, sizeof(clsid));
  656. }
  657. //+-------------------------------------------------------------------------
  658. //
  659. // Function: ReadClassStm
  660. //
  661. // Synopsis: Reads the CLSID from the given stream
  662. //
  663. // Effects:
  664. //
  665. // Arguments: [pStm] -- pointer to the stream
  666. // [pclsid] -- where to put the clsid
  667. //
  668. // Requires:
  669. //
  670. // Returns: HRESULT from the IStream->Read
  671. //
  672. // Signals:
  673. //
  674. // Modifies:
  675. //
  676. // Algorithm:
  677. //
  678. // History: dd-mmm-yy Author Comment
  679. // 24-Oct-93 alexgo 32bit port
  680. //
  681. // Notes:
  682. //
  683. //--------------------------------------------------------------------------
  684. #pragma SEG(ReadClassStm)
  685. // reads CLSID from stream swapping bytes on big-endian machines
  686. STDAPI ReadClassStm(LPSTREAM pStm, LPCLSID pclsid)
  687. {
  688. OLETRACEIN((API_ReadClassStm, PARAMFMT("pStm= %p, pclsid= %p"), pStm, pclsid));
  689. VDATEHEAP();
  690. HRESULT error;
  691. VDATEIFACE_LABEL( pStm, errRtn, error );
  692. VDATEPTROUT_LABEL(pclsid, CLSID, errRtn, error);
  693. if ((error = StRead(pStm, (void FAR *)pclsid, sizeof(CLSID)))
  694. != NOERROR)
  695. *pclsid = CLSID_NULL;
  696. errRtn:
  697. OLETRACEOUT((API_ReadClassStm, error));
  698. return error;
  699. }
  700. //+-------------------------------------------------------------------------
  701. //
  702. // Function: WriteClassStm
  703. //
  704. // Synopsis: Writes the class ID to the given stream
  705. //
  706. // Effects:
  707. //
  708. // Arguments: [pStm] -- pointer to the stream
  709. // [clsid] -- CLSID to write to the stream
  710. //
  711. // Requires:
  712. //
  713. // Returns: HRESULT from the IStream->Write call
  714. //
  715. // Signals:
  716. //
  717. // Modifies:
  718. //
  719. // Algorithm:
  720. //
  721. // History: dd-mmm-yy Author Comment
  722. // 24-Oct-93 alexgo 32bit port
  723. //
  724. // Notes:
  725. //
  726. //--------------------------------------------------------------------------
  727. #pragma SEG(WriteClassStm)
  728. // writes CLSID to stream swapping bytes on big-endian machines
  729. STDAPI WriteClassStm(LPSTREAM pStm, REFCLSID clsid)
  730. {
  731. OLETRACEIN((API_WriteClassStm, PARAMFMT("pStm= %p, clsid= %I"), pStm, &clsid));
  732. VDATEHEAP();
  733. HRESULT hr;
  734. VDATEIFACE_LABEL( pStm, errRtn, hr);
  735. hr = pStm->Write(&clsid, sizeof(clsid), NULL);
  736. errRtn:
  737. OLETRACEOUT((API_WriteClassStm, hr));
  738. return hr;
  739. }
  740. //+-------------------------------------------------------------------------
  741. //
  742. // Function: ReleaseStgMedium
  743. //
  744. // Synopsis: Releases any resources held by a storage medium
  745. //
  746. // Arguments: [pMedium] -- pointer to the storage medium
  747. //
  748. // Returns: nothing
  749. //
  750. // History: dd-mmm-yy Author Comment
  751. // 24-Oct-93 alexgo 32-bit port
  752. // 15-May-94 DavePl Added EMF support
  753. //
  754. //--------------------------------------------------------------------------
  755. #pragma SEG(ReleaseStgMedium)
  756. STDAPI_(void) ReleaseStgMedium( LPSTGMEDIUM pMedium )
  757. {
  758. OLETRACEIN((API_ReleaseStgMedium, PARAMFMT("pMedium= %p"), pMedium));
  759. VDATEHEAP();
  760. if (pMedium) {
  761. BOOL fPunkRel;
  762. //VDATEPTRIN rejects NULL
  763. VOID_VDATEPTRIN_LABEL( pMedium, STGMEDIUM, errRtn);
  764. fPunkRel = pMedium->pUnkForRelease != NULL;
  765. switch (pMedium->tymed) {
  766. case TYMED_HGLOBAL:
  767. if (pMedium->hGlobal != NULL && !fPunkRel)
  768. Verify(GlobalFree(pMedium->hGlobal) == 0);
  769. break;
  770. case TYMED_GDI:
  771. if (pMedium->hGlobal != NULL && !fPunkRel)
  772. DeleteObject(pMedium->hGlobal);
  773. break;
  774. case TYMED_ENHMF:
  775. if (pMedium->hEnhMetaFile != NULL && !fPunkRel)
  776. {
  777. Verify(DeleteEnhMetaFile(pMedium->hEnhMetaFile));
  778. };
  779. break;
  780. case TYMED_MFPICT:
  781. if (pMedium->hGlobal != NULL && !fPunkRel) {
  782. LPMETAFILEPICT pmfp;
  783. if ((pmfp = (LPMETAFILEPICT)GlobalLock(pMedium->hGlobal)) == NULL)
  784. break;
  785. DeleteMetaFile(pmfp->hMF);
  786. GlobalUnlock(pMedium->hGlobal);
  787. Verify(GlobalFree(pMedium->hGlobal) == 0);
  788. }
  789. break;
  790. case TYMED_FILE:
  791. if (pMedium->lpszFileName != NULL) {
  792. if (!IsValidPtrIn(pMedium->lpszFileName, 1))
  793. break;
  794. if (!fPunkRel) {
  795. #ifdef WIN32
  796. DeleteFile(pMedium->lpszFileName);
  797. #else
  798. #ifdef _MAC
  799. // the libraries are essentially small model on the MAC
  800. Verify(0==remove(pMedium->lpszFileName));
  801. #else
  802. #ifdef OLD_AND_NICE_ASSEMBLER_VERSION
  803. // Win 3.1 specific code to call DOS to delete the file
  804. // given a far pointer to the file name
  805. extern void WINAPI DOS3Call(void);
  806. _asm {
  807. mov ah,41H
  808. push ds
  809. lds bx,pMedium
  810. lds dx,[bx].lpszFileName
  811. call DOS3Call
  812. pop ds
  813. }
  814. #else
  815. {
  816. OFSTRUCT of;
  817. OpenFile(pMedium->lpszFileName, &of, OF_DELETE);
  818. }
  819. #endif
  820. #endif
  821. #endif
  822. }
  823. // WARNING: there was a bug in the 16bit code that the filename
  824. // string was not being freed if pUnkForRelease was NULL. the
  825. // spec says it should delete the string, so we follow the spec
  826. // here.
  827. PubMemFree(pMedium->lpszFileName);
  828. pMedium->lpszFileName = NULL;
  829. }
  830. break;
  831. case TYMED_ISTREAM:
  832. if (pMedium->pstm != NULL &&
  833. IsValidInterface(pMedium->pstm))
  834. pMedium->pstm->Release();
  835. break;
  836. case TYMED_ISTORAGE:
  837. if (pMedium->pstg != NULL &&
  838. IsValidInterface(pMedium->pstg))
  839. pMedium->pstg->Release();
  840. break;
  841. case TYMED_NULL:
  842. break;
  843. default:
  844. AssertSz(FALSE, "Invalid medium in ReleaseStgMedium");
  845. }
  846. if (pMedium->pUnkForRelease) {
  847. if (IsValidInterface(pMedium->pUnkForRelease))
  848. pMedium->pUnkForRelease->Release();
  849. pMedium->pUnkForRelease = NULL;
  850. }
  851. // NULL out to prevent unwanted use of just freed data.
  852. // Note: this must be done AFTER punkForRelease is called
  853. // because our special punkForRelease used in remoting
  854. // needs the tymed value.
  855. pMedium->tymed = TYMED_NULL;
  856. }
  857. errRtn:
  858. OLETRACEOUTEX((API_ReleaseStgMedium, NORETURN));
  859. return;
  860. }
  861. #ifdef MAC_REVIEW
  862. This API must be written for MAC and PICT format.
  863. #endif
  864. //+-------------------------------------------------------------------------
  865. //
  866. // Function: OleDuplicateData
  867. //
  868. // Synopsis: Duplicates data from the given handle and clipboard format
  869. //
  870. // Effects:
  871. //
  872. // Arguments: [hSrc] -- handle to the data to be duplicated
  873. // [cfFormat] -- format of [hSrc]
  874. // [uiFlags] -- any flags (such a GMEM_MOVEABLE) for
  875. // memory allocation
  876. //
  877. // Requires:
  878. //
  879. // Returns: a HANDLE to the duplicated resource
  880. //
  881. // Signals:
  882. //
  883. // Modifies:
  884. //
  885. // Algorithm:
  886. //
  887. // History: dd-mmm-yy Author Comment
  888. // 30-May-94 alexgo added support for enhanced metafiles
  889. // 24-Oct-93 alexgo 32bit port
  890. //
  891. // Notes:
  892. //
  893. //--------------------------------------------------------------------------
  894. #pragma SEG(OleDuplicateData)
  895. STDAPI_(HANDLE) OleDuplicateData
  896. (HANDLE hSrc, CLIPFORMAT cfFormat, UINT uiFlags)
  897. {
  898. HANDLE hDup;
  899. OLETRACEIN((API_OleDuplicateData, PARAMFMT("hSrc= %h, cfFormat= %d, uiFlags= %x"),
  900. hSrc, cfFormat, uiFlags));
  901. VDATEHEAP();
  902. if (!hSrc)
  903. {
  904. hDup = NULL;
  905. goto errRtn;
  906. }
  907. switch( cfFormat )
  908. {
  909. case CF_BITMAP:
  910. hDup = (HANDLE) BmDuplicate ((HBITMAP)hSrc, NULL, NULL);
  911. break;
  912. case CF_PALETTE:
  913. hDup = (HANDLE) UtDupPalette ((HPALETTE)hSrc);
  914. break;
  915. case CF_ENHMETAFILE:
  916. hDup = (HANDLE) CopyEnhMetaFile((HENHMETAFILE)hSrc, NULL);
  917. break;
  918. case CF_METAFILEPICT:
  919. if (uiFlags == NULL)
  920. {
  921. uiFlags = GMEM_MOVEABLE;
  922. }
  923. LPMETAFILEPICT lpmfpSrc;
  924. LPMETAFILEPICT lpmfpDst;
  925. if (!(lpmfpSrc = (LPMETAFILEPICT) GlobalLock (hSrc)))
  926. {
  927. hDup = NULL;
  928. goto errRtn;
  929. }
  930. if (!(hDup = UtDupGlobal (hSrc, uiFlags)))
  931. {
  932. GlobalUnlock(hSrc);
  933. hDup = NULL;
  934. goto errRtn;
  935. }
  936. if (!(lpmfpDst = (LPMETAFILEPICT) GlobalLock (hDup)))
  937. {
  938. GlobalUnlock(hSrc);
  939. GlobalFree (hDup);
  940. hDup = NULL;
  941. goto errRtn;
  942. }
  943. *lpmfpDst = *lpmfpSrc;
  944. lpmfpDst->hMF = CopyMetaFile (lpmfpSrc->hMF, NULL);
  945. GlobalUnlock (hSrc);
  946. GlobalUnlock (hDup);
  947. break;
  948. default:
  949. if (uiFlags == NULL)
  950. {
  951. uiFlags = GMEM_MOVEABLE;
  952. }
  953. hDup = UtDupGlobal (hSrc, uiFlags);
  954. }
  955. errRtn:
  956. OLETRACEOUTEX((API_OleDuplicateData, RETURNFMT("%h"), hDup));
  957. return hDup;
  958. }
  959. //+-------------------------------------------------------------------------
  960. //
  961. // Function: BmDuplicate
  962. //
  963. // Synopsis: Duplicates a bitmap
  964. //
  965. // Effects:
  966. //
  967. // Arguments: [hold] -- the source bitmap
  968. // [lpdwSize] -- where to put the bitmap size
  969. // [lpBm] -- where to put the new bitmap
  970. //
  971. // Requires:
  972. //
  973. // Returns: A handle to the new bitmap
  974. //
  975. // Signals:
  976. //
  977. // Modifies:
  978. //
  979. // Algorithm:
  980. //
  981. // History: dd-mmm-yy Author Comment
  982. // 25-Oct-93 alexgo 32bit port
  983. //
  984. // Notes:
  985. //
  986. //--------------------------------------------------------------------------
  987. #pragma SEG(BmDuplicate)
  988. FARINTERNAL_(HBITMAP) BmDuplicate
  989. (HBITMAP hold, DWORD FAR* lpdwSize, LPBITMAP lpBm)
  990. {
  991. VDATEHEAP();
  992. HBITMAP hnew = NULL;
  993. HANDLE hMem;
  994. LPVOID lpMem;
  995. DWORD dwSize;
  996. BITMAP bm;
  997. SIZE extents;
  998. extents.cx = extents.cy = 0;
  999. // REVIEW (davepl): The bitmap pointer here was being cast to LPOLESTR
  1000. // for some reason. It's takes a void pointer!
  1001. GetObject (hold, sizeof(BITMAP), &bm);
  1002. dwSize = ((DWORD) bm.bmHeight) * ((DWORD) bm.bmWidthBytes) *
  1003. ((DWORD) bm.bmPlanes);
  1004. if (!(hMem = GlobalAlloc (GMEM_MOVEABLE, dwSize)))
  1005. return NULL;
  1006. if (!(lpMem = GlobalLock (hMem)))
  1007. goto errRtn;
  1008. GlobalUnlock (hMem);
  1009. // REVIEW(davepl): This should probably use GetDIBits() instead
  1010. GetBitmapBits (hold, dwSize, lpMem);
  1011. if (hnew = CreateBitmap (bm.bmWidth, bm.bmHeight,
  1012. bm.bmPlanes, bm.bmBitsPixel, NULL)) {
  1013. if (!SetBitmapBits (hnew, dwSize, lpMem)) {
  1014. DeleteObject (hnew);
  1015. hnew = NULL;
  1016. goto errRtn;
  1017. }
  1018. }
  1019. if (lpdwSize)
  1020. *lpdwSize = dwSize;
  1021. if (lpBm)
  1022. *lpBm = bm;
  1023. if (hnew && GetBitmapDimensionEx(hold, &extents) && extents.cx && extents.cy)
  1024. SetBitmapDimensionEx(hnew, extents.cx, extents.cy, NULL);
  1025. errRtn:
  1026. if (hMem)
  1027. GlobalFree (hMem);
  1028. return hnew;
  1029. }
  1030. //+-------------------------------------------------------------------------
  1031. //
  1032. // Function: ReadOleStg
  1033. //
  1034. // Synopsis: Internal API to read private OLE information from
  1035. // the OLE_STREAM in the given storage
  1036. //
  1037. // Effects:
  1038. //
  1039. // Arguments: [pstg] -- pointer to the storage
  1040. // [pdwFlags] -- where to put flags stored in the
  1041. // the stream (may be NULL)
  1042. // [pdwOptUpdate] -- where to put the update flags
  1043. // (may be NULL)
  1044. // [pdwReserved] -- where to put the reserved value
  1045. // (may be NULL)
  1046. // [ppmk] -- where to put the moniker
  1047. // (may be NULL)
  1048. // [ppstmOut] -- where to put the OLE_STREAM pointer
  1049. // (may be NULL)
  1050. //
  1051. // Requires:
  1052. //
  1053. // Returns: HRESULT
  1054. //
  1055. // Signals:
  1056. //
  1057. // Modifies:
  1058. //
  1059. // Algorithm:
  1060. //
  1061. // History: dd-mmm-yy Author Comment
  1062. // 27-Oct-93 alexgo 32bit port
  1063. //
  1064. // Notes:
  1065. //
  1066. //--------------------------------------------------------------------------
  1067. #pragma SEG(ReadOleStg)
  1068. STDAPI ReadOleStg
  1069. (LPSTORAGE pstg, DWORD FAR* pdwFlags, DWORD FAR* pdwOptUpdate,
  1070. DWORD FAR* pdwReserved, LPMONIKER FAR* ppmk, LPSTREAM FAR* ppstmOut)
  1071. {
  1072. OLETRACEIN((API_ReadOleStg,
  1073. PARAMFMT("pdwFlags= %p, pdwOptUpdate= %p, pdwReserved= %p, ppmk= %p, ppstmOut= %p"),
  1074. pdwFlags, pdwOptUpdate, pdwReserved, ppmk, ppstmOut));
  1075. VDATEHEAP();
  1076. HRESULT error;
  1077. IStream FAR * pstm;
  1078. DWORD dwBuf[4];
  1079. LPMONIKER pmk;
  1080. LPOLESTR szClassName = OLE_STREAM;
  1081. if (ppmk)
  1082. {
  1083. VDATEPTROUT_LABEL( ppmk, LPMONIKER, errNoFreeRtn, error);
  1084. *ppmk = NULL;
  1085. }
  1086. if (ppstmOut){
  1087. VDATEPTROUT_LABEL( ppstmOut, LPSTREAM, errNoFreeRtn, error);
  1088. *ppstmOut = NULL;
  1089. }
  1090. VDATEIFACE_LABEL( pstg, errNoFreeRtn, error);
  1091. if ((error = pstg->OpenStream(szClassName, NULL,
  1092. (STGM_READ | STGM_SHARE_EXCLUSIVE), 0, &pstm)) != NOERROR) {
  1093. // This error is OK for some callers (ex: default handler)
  1094. // of this function. They depend on NOERROR or this error
  1095. // code. So, don't change the error code.
  1096. error = ReportResult(0, STG_E_FILENOTFOUND, 0, 0);
  1097. goto errNoFreeRtn;
  1098. }
  1099. // read Ole version number, flags, Update options, reserved field
  1100. if ((error = StRead (pstm, dwBuf, 4*sizeof(DWORD))) != NOERROR)
  1101. goto errRtn;
  1102. if (dwBuf[0] != gdwOleVersion) {
  1103. error = ResultFromScode(DV_E_CLIPFORMAT);
  1104. goto errRtn;
  1105. }
  1106. if (pdwFlags)
  1107. *pdwFlags = dwBuf[1];
  1108. if (pdwOptUpdate)
  1109. *pdwOptUpdate = dwBuf[2];
  1110. AssertSz(dwBuf[3] == NULL,"Reserved field in OLE STREAM is not NULL");
  1111. if (dwBuf[3] != NULL) {
  1112. error = ResultFromScode(DV_E_CLIPFORMAT);
  1113. goto errRtn;
  1114. }
  1115. if (pdwReserved)
  1116. *pdwReserved = dwBuf[3];
  1117. if ((error = ReadMonikerStm (pstm, &pmk)) != NOERROR)
  1118. goto errRtn;
  1119. if (ppmk)
  1120. *ppmk = pmk;
  1121. else if (pmk)
  1122. pmk->Release();
  1123. errRtn:
  1124. if (pstm) {
  1125. if ((error == NOERROR) && (ppstmOut != NULL))
  1126. *ppstmOut = pstm;
  1127. else
  1128. pstm->Release();
  1129. }
  1130. errNoFreeRtn:
  1131. OLETRACEOUT((API_ReadOleStg, error));
  1132. return error;
  1133. }
  1134. //+-------------------------------------------------------------------------
  1135. //
  1136. // Function: WriteOleStg
  1137. //
  1138. // Synopsis: Writes private OLE info into an OLE_STREAM in the given storage.
  1139. //
  1140. // Arguments: [pstg] [in] -- pointer to the storage
  1141. // [pOleObj] [in] -- object from which to get info to write
  1142. // (may be NULL)
  1143. // [dwReserved] [in] -- reserved
  1144. // [ppstmOut] [out] -- pointer to return the private stream
  1145. // (may be NULL)
  1146. // Returns: HRESULT
  1147. //
  1148. // History: dd-mmm-yy Author Comment
  1149. // Oct 27, 93 alexgo 32bit port
  1150. // Oct 23, 96 gopalk Changed to call WriteOleStgEx
  1151. //
  1152. //--------------------------------------------------------------------------
  1153. #pragma SEG(WriteOleStg)
  1154. STDAPI WriteOleStg(LPSTORAGE pstg, IOleObject* pOleObj, DWORD dwReserved,
  1155. LPSTREAM* ppstmOut)
  1156. {
  1157. OLETRACEIN((API_WriteOleStg,
  1158. PARAMFMT("pstg=%p, pOleObj=%p, dwReserved=%x, ppstmOut=%p, "),
  1159. pstg, pOleObj, dwReserved, ppstmOut));
  1160. // Local variable
  1161. HRESULT error;
  1162. do {
  1163. // Validation Checks
  1164. VDATEHEAP();
  1165. if(ppstmOut && !IsValidPtrOut(ppstmOut, sizeof(LPSTREAM))) {
  1166. error = ResultFromScode(E_INVALIDARG);
  1167. break;
  1168. }
  1169. if(!IsValidInterface(pstg)) {
  1170. error = ResultFromScode(E_INVALIDARG);
  1171. break;
  1172. }
  1173. if(pOleObj && !IsValidInterface(pOleObj)) {
  1174. error = ResultFromScode(E_INVALIDARG);
  1175. break;
  1176. }
  1177. // Call WriteOleStgEx
  1178. error = WriteOleStgEx(pstg, pOleObj, dwReserved, 0, ppstmOut);
  1179. } while(FALSE);
  1180. OLETRACEOUT((API_WriteOleStg, error));
  1181. return error;
  1182. }
  1183. //+-------------------------------------------------------------------------
  1184. //
  1185. // Function: WriteOleStgEx (Internal)
  1186. //
  1187. // Synopsis: Writes private OLE info into an OLE_STREAM in the given storage.
  1188. //
  1189. // Arguments: [pstg] [in] -- pointer to the storage
  1190. // [pOleObj] [in] -- object from which to get info to write
  1191. // (may be NULL)
  1192. // [dwReserved] [in] -- reserved
  1193. // [ppstmOut] [out] -- pointer to return the private stream
  1194. // (may be NULL)
  1195. // [dwGivenFlags] [in] -- Additional object flags to be set
  1196. //
  1197. // Returns: HRESULT
  1198. //
  1199. // History: dd-mmm-yy Author Comment
  1200. // Oct 23, 96 gopalk Creation
  1201. //
  1202. //--------------------------------------------------------------------------
  1203. STDAPI WriteOleStgEx(LPSTORAGE pstg, IOleObject* pOleObj, DWORD dwReserved,
  1204. DWORD dwGivenFlags, LPSTREAM* ppstmOut)
  1205. {
  1206. // Local Variables
  1207. HRESULT error = NOERROR;
  1208. IStream* pstm = NULL;
  1209. IOleLink* pLink;
  1210. LPMONIKER pmk;
  1211. DWORD dwUpdOpt;
  1212. ULONG cbRead;
  1213. DWORD objflags;
  1214. ULARGE_INTEGER ularge_integer;
  1215. LARGE_INTEGER large_integer;
  1216. // Initialize out parameter
  1217. if(ppstmOut)
  1218. *ppstmOut = NULL;
  1219. // Open or Create OLE_STREAM
  1220. error = OpenOrCreateStream(pstg, OLE_STREAM, &pstm);
  1221. if(error == NOERROR) {
  1222. // Write Ole version
  1223. error = pstm->Write(&gdwOleVersion, sizeof(DWORD), NULL);
  1224. if(error == NOERROR) {
  1225. // Read existing Objflags to preserve doc bit
  1226. if(pstm->Read(&objflags, sizeof(DWORD), &cbRead) != NOERROR ||
  1227. cbRead != sizeof(DWORD))
  1228. objflags = 0;
  1229. // Only preserve docbit
  1230. objflags &= OBJFLAGS_DOCUMENT;
  1231. // Set the given flags
  1232. objflags |= dwGivenFlags;
  1233. // Obtain link update options
  1234. dwUpdOpt = 0L;
  1235. if(pOleObj != NULL &&
  1236. pOleObj->QueryInterface(IID_IOleLink, (void **)&pLink) == NOERROR) {
  1237. objflags |= OBJFLAGS_LINK;
  1238. pLink->GetUpdateOptions(&dwUpdOpt);
  1239. pLink->Release();
  1240. }
  1241. // Seek to the Objflags field. We could be off due to the above read
  1242. LISet32(large_integer, sizeof(DWORD));
  1243. error = pstm->Seek(large_integer, STREAM_SEEK_SET, NULL);
  1244. if(error == NOERROR) {
  1245. // Write Objflags and link update options
  1246. DWORD dwBuf[3];
  1247. dwBuf[0] = objflags;
  1248. dwBuf[1] = dwUpdOpt;
  1249. Win4Assert(dwReserved == NULL);
  1250. dwBuf[2] = 0L;
  1251. error = pstm->Write(dwBuf, 3*sizeof(DWORD), NULL);
  1252. if(error == NOERROR) {
  1253. // Obtain object moniker
  1254. pmk = NULL;
  1255. if(pOleObj != NULL) {
  1256. error = pOleObj->GetMoniker(OLEGETMONIKER_ONLYIFTHERE,
  1257. OLEWHICHMK_OBJREL, &pmk);
  1258. if(SUCCEEDED(error) && !IsValidInterface(pmk)) {
  1259. Win4Assert(FALSE);
  1260. pmk = NULL;
  1261. }
  1262. else if(FAILED(error) && pmk) {
  1263. Win4Assert(FALSE);
  1264. if(!IsValidInterface(pmk))
  1265. pmk = NULL;
  1266. }
  1267. // Write Object moniker
  1268. error = WriteMonikerStm(pstm, pmk);
  1269. if(pmk)
  1270. pmk->Release();
  1271. // Truncate the stream to remove any existing data
  1272. if(error == NOERROR) {
  1273. LISet32(large_integer, 0);
  1274. error = pstm->Seek(large_integer, STREAM_SEEK_CUR,
  1275. &ularge_integer);
  1276. if(error == NOERROR)
  1277. pstm->SetSize(ularge_integer);
  1278. }
  1279. }
  1280. }
  1281. }
  1282. }
  1283. if(error==NOERROR && ppstmOut)
  1284. *ppstmOut = pstm;
  1285. else
  1286. pstm->Release();
  1287. }
  1288. return error;
  1289. }
  1290. //+-------------------------------------------------------------------------
  1291. //
  1292. // Function: SetBitOleStg
  1293. //
  1294. // Synopsis: internal function to write private OLE info into
  1295. // OLE_STREAM on the given storage
  1296. //
  1297. // Effects:
  1298. //
  1299. // Arguments: [pstg] -- pointer to the storage
  1300. // [mask] -- mask for old values
  1301. // [value] -- values to write
  1302. //
  1303. // Requires:
  1304. //
  1305. // Returns: HRESULT
  1306. //
  1307. // Signals:
  1308. //
  1309. // Modifies:
  1310. //
  1311. // Algorithm: writes (old_values & mask ) | value into the stream
  1312. //
  1313. // History: dd-mmm-yy Author Comment
  1314. // 27-Oct-93 alexgo 32-bit port, fixed bugs
  1315. //
  1316. // Notes:
  1317. //
  1318. //--------------------------------------------------------------------------
  1319. #pragma SEG(SetBitOleStg)
  1320. static INTERNAL SetBitOleStg(LPSTORAGE pstg, DWORD mask, DWORD value)
  1321. {
  1322. VDATEHEAP();
  1323. IStream FAR * pstm = NULL;
  1324. HRESULT error;
  1325. DWORD objflags = 0;
  1326. LARGE_INTEGER large_integer;
  1327. VDATEIFACE( pstg );
  1328. if (error = pstg->OpenStream(OLE_STREAM, NULL, STGM_SALL, 0, &pstm))
  1329. {
  1330. if (STG_E_FILENOTFOUND != GetScode(error))
  1331. goto errRtn;
  1332. if ((error = pstg->CreateStream(OLE_STREAM, STGM_SALL,
  1333. 0, 0, &pstm)) != NOERROR)
  1334. goto errRtn;
  1335. DWORD dwBuf[5];
  1336. dwBuf[0] = gdwOleVersion;
  1337. dwBuf[1] = objflags;
  1338. dwBuf[2] = 0L;
  1339. dwBuf[3] = 0L;
  1340. dwBuf[4] = 0L;
  1341. if ((error = pstm->Write(dwBuf, 5*sizeof(DWORD), NULL))
  1342. != NOERROR)
  1343. goto errRtn;
  1344. }
  1345. // seek directly to word, read, modify, seek back and write.
  1346. LISet32( large_integer, sizeof(DWORD) );
  1347. if ((error = pstm->Seek(large_integer, STREAM_SEEK_SET, NULL))
  1348. != NOERROR)
  1349. goto errRtn;
  1350. if ((error = StRead(pstm, &objflags, sizeof(objflags))) != NOERROR)
  1351. goto errRtn;
  1352. objflags = (objflags & mask) | value;
  1353. LISet32( large_integer, sizeof(DWORD) );
  1354. if ((error = pstm->Seek(large_integer, STREAM_SEEK_SET, NULL))
  1355. != NOERROR)
  1356. goto errRtn;
  1357. error = pstm->Write(&objflags, sizeof(DWORD), NULL);
  1358. errRtn:// close and return error code.
  1359. if (pstm)
  1360. pstm->Release();
  1361. return error;
  1362. }
  1363. //+-------------------------------------------------------------------------
  1364. //
  1365. // Function: GetFlagsOleStg
  1366. //
  1367. // Synopsis: Internal function to get the private ole flags from a
  1368. // given storage
  1369. //
  1370. // Effects:
  1371. //
  1372. // Arguments: [pstg] -- pointer to the storage
  1373. // [lpobjflags] -- where to put the flags
  1374. //
  1375. // Requires:
  1376. //
  1377. // Returns: HRESULT
  1378. //
  1379. // Signals:
  1380. //
  1381. // Modifies:
  1382. //
  1383. // Algorithm:
  1384. //
  1385. // History: dd-mmm-yy Author Comment
  1386. // 27-Oct-93 alexgo 32bit port, fixed bugs (error return)
  1387. //
  1388. // Notes:
  1389. //
  1390. //--------------------------------------------------------------------------
  1391. #pragma SEG(GetFlagsOleStg)
  1392. static INTERNAL GetFlagsOleStg(LPSTORAGE pstg, LPDWORD lpobjflags)
  1393. {
  1394. VDATEHEAP();
  1395. IStream FAR * pstm = NULL;
  1396. HRESULT error;
  1397. LARGE_INTEGER large_integer;
  1398. VDATEIFACE( pstg );
  1399. if ((error = pstg->OpenStream(OLE_STREAM, NULL,
  1400. (STGM_READ | STGM_SHARE_EXCLUSIVE),
  1401. 0, &pstm)) != NOERROR)
  1402. goto errRtn;
  1403. // seek directly to word, read, modify, seek back and write.
  1404. LISet32( large_integer, sizeof(DWORD) );
  1405. if ((error = pstm->Seek(large_integer, STREAM_SEEK_SET, NULL))
  1406. != NOERROR)
  1407. goto errRtn;
  1408. error = StRead(pstm, lpobjflags, sizeof(*lpobjflags));
  1409. errRtn:
  1410. if (pstm)
  1411. pstm->Release();
  1412. return error;
  1413. }
  1414. //+-------------------------------------------------------------------------
  1415. //
  1416. // Function: GetDocumentBitStg
  1417. //
  1418. // Synopsis: returns the doc bit from the given storage
  1419. //
  1420. // Effects:
  1421. //
  1422. // Arguments: [pStg] -- pointer to the storage
  1423. //
  1424. // Requires:
  1425. //
  1426. // Returns: NOERROR if the doc bit is set, S_FALSE if not
  1427. //
  1428. // Signals:
  1429. //
  1430. // Modifies:
  1431. //
  1432. // Algorithm:
  1433. //
  1434. // History: dd-mmm-yy Author Comment
  1435. // 27-Oct-93 alexgo 32bit port
  1436. //
  1437. // Notes:
  1438. // REVIEW32:: Nobody seems to use this function. Nuke it.
  1439. //
  1440. //--------------------------------------------------------------------------
  1441. #pragma SEG(GetDocumentBitStg)
  1442. // get doc bit; return NOERROR if on; S_FALSE if off
  1443. STDAPI GetDocumentBitStg(LPSTORAGE pStg)
  1444. {
  1445. OLETRACEIN((API_GetDocumentBitStg, PARAMFMT("pStg= %p"), pStg));
  1446. VDATEHEAP();
  1447. DWORD objflags;
  1448. HRESULT error;
  1449. if ((error = GetFlagsOleStg(pStg, &objflags)) == NOERROR)
  1450. {
  1451. if(!(objflags&OBJFLAGS_DOCUMENT))
  1452. {
  1453. error = ResultFromScode(S_FALSE);
  1454. }
  1455. }
  1456. OLETRACEOUT((API_GetDocumentBitStg, error));
  1457. return error;
  1458. }
  1459. //+-------------------------------------------------------------------------
  1460. //
  1461. // Function: SetDocumentBitStg
  1462. //
  1463. // Synopsis: Writes the document bit to the given storage
  1464. //
  1465. // Effects:
  1466. //
  1467. // Arguments: [pStg] -- pointer to the storage
  1468. // [fDocument] -- TRUE, storage is a document, false
  1469. // otherwise
  1470. //
  1471. // Requires:
  1472. //
  1473. // Returns: HRESULT
  1474. //
  1475. // Signals:
  1476. //
  1477. // Modifies:
  1478. //
  1479. // Algorithm:
  1480. //
  1481. // History: dd-mmm-yy Author Comment
  1482. // 27-Oct-93 alexgo 32-bit port
  1483. //
  1484. // Notes:
  1485. // REVIEW32: nobody seems to use this function, nuke it
  1486. //
  1487. //--------------------------------------------------------------------------
  1488. #pragma SEG(SetDocumentBitStg)
  1489. // set doc bit according to fDocument
  1490. STDAPI SetDocumentBitStg(LPSTORAGE pStg, BOOL fDocument)
  1491. {
  1492. OLETRACEIN((API_SetDocumentBitStg, PARAMFMT("pStg= %p, fDocument= %B"),
  1493. pStg, fDocument));
  1494. VDATEHEAP();
  1495. HRESULT hr;
  1496. hr = SetBitOleStg(pStg, fDocument ? -1L : ~OBJFLAGS_DOCUMENT,
  1497. fDocument ? OBJFLAGS_DOCUMENT : 0);
  1498. OLETRACEOUT((API_SetDocumentBitStg, hr));
  1499. return hr;
  1500. }
  1501. //+-------------------------------------------------------------------------
  1502. //
  1503. // Function: GetConvertStg
  1504. //
  1505. // Synopsis: Gets the convert bit from the given storage
  1506. //
  1507. // Effects:
  1508. //
  1509. // Arguments: [pStg] -- pointer to the storage
  1510. //
  1511. // Requires:
  1512. //
  1513. // Returns: NOERROR if set, S_FALSE if not
  1514. //
  1515. // Signals:
  1516. //
  1517. // Modifies:
  1518. //
  1519. // Algorithm:
  1520. //
  1521. // History: dd-mmm-yy Author Comment
  1522. // 27-Oct-93 alexgo 32bit port
  1523. //
  1524. // Notes:
  1525. //
  1526. //--------------------------------------------------------------------------
  1527. #pragma SEG(GetConvertStg)
  1528. STDAPI GetConvertStg(LPSTORAGE pStg)
  1529. {
  1530. OLETRACEIN((API_GetConvertStg, PARAMFMT("pStg= %p"), pStg));
  1531. VDATEHEAP();
  1532. DWORD objflags;
  1533. HRESULT error;
  1534. if ((error = GetFlagsOleStg(pStg, &objflags)) != NOERROR)
  1535. {
  1536. goto errRtn;
  1537. }
  1538. if (objflags&OBJFLAGS_CONVERT)
  1539. {
  1540. error = NOERROR;
  1541. }
  1542. else
  1543. {
  1544. error = ResultFromScode(S_FALSE);
  1545. }
  1546. errRtn:
  1547. OLETRACEOUT((API_GetConvertStg, error));
  1548. return error;
  1549. }
  1550. //+-------------------------------------------------------------------------
  1551. //
  1552. // Function: SetConvertStg
  1553. //
  1554. // Synopsis: Sets the convert bit in a storage
  1555. //
  1556. // Effects:
  1557. //
  1558. // Arguments: [pStg] -- pointer to the storage
  1559. // [fConvert] -- convert bit
  1560. //
  1561. // Requires:
  1562. //
  1563. // Returns: HRESULT
  1564. //
  1565. // Signals:
  1566. //
  1567. // Modifies:
  1568. //
  1569. // Algorithm:
  1570. //
  1571. // History: dd-mmm-yy Author Comment
  1572. // 27-Oct-93 alexgo 32bit port
  1573. //
  1574. // Notes:
  1575. //
  1576. //--------------------------------------------------------------------------
  1577. #pragma SEG(SetConvertStg)
  1578. STDAPI SetConvertStg(LPSTORAGE pStg, BOOL fConvert)
  1579. {
  1580. OLETRACEIN((API_SetConvertStg, PARAMFMT("pStg= %p, fConvert= %B"),
  1581. pStg, fConvert));
  1582. VDATEHEAP();
  1583. HRESULT hr;
  1584. hr = SetBitOleStg(pStg, fConvert ? -1L : ~OBJFLAGS_CONVERT,
  1585. fConvert ? OBJFLAGS_CONVERT : 0);
  1586. OLETRACEOUT((API_SetConvertStg, hr));
  1587. return hr;
  1588. }
  1589. //+-------------------------------------------------------------------------
  1590. //
  1591. // Function: ReadClipformatStm
  1592. //
  1593. // Synopsis: Reads the clipboard format from the given stream
  1594. //
  1595. // Effects: If the clipboard format is a length followed by a
  1596. // string, then the string is read and registered as a
  1597. // clipboard format (and the new format number is returned).
  1598. //
  1599. // Arguments: [lpstream] -- pointer to the stream
  1600. // [lpdwCf] -- where to put the clipboard format
  1601. //
  1602. // Requires:
  1603. //
  1604. // Returns: HRESULT
  1605. //
  1606. // Signals:
  1607. //
  1608. // Modifies:
  1609. //
  1610. // Algorithm: the format of the stream must be one of the following:
  1611. // 0 No clipboard format
  1612. // -1 DWORD predefined windows clipboard format in
  1613. // the second dword.
  1614. // -2 DWORD predefined mac clipboard format in the
  1615. // second dword. This may be obsolete or
  1616. // irrelevant for us. REVIEW32
  1617. // num STRING clipboard format name string (prefaced
  1618. // by length of string).
  1619. //
  1620. // History: dd-mmm-yy Author Comment
  1621. // 27-Oct-93 alexgo 32bit port, fixed ifdef and NULL
  1622. // pointer bugs
  1623. //
  1624. // 17-Mar-94 davepl Revereted to ANSI string reads
  1625. // Notes:
  1626. //
  1627. //--------------------------------------------------------------------------
  1628. STDAPI ReadClipformatStm(LPSTREAM lpstream, DWORD FAR* lpdwCf)
  1629. {
  1630. VDATEHEAP();
  1631. HRESULT error;
  1632. DWORD dwValue;
  1633. VDATEIFACE(lpstream);
  1634. VDATEPTROUT(lpdwCf, DWORD);
  1635. if (error = StRead(lpstream, &dwValue, sizeof(DWORD)))
  1636. {
  1637. return error;
  1638. }
  1639. if (dwValue == NULL)
  1640. {
  1641. // NULL cf value
  1642. *lpdwCf = NULL;
  1643. }
  1644. else if (dwValue == -1L)
  1645. {
  1646. // Then this is a NON-NULL predefined windows clipformat.
  1647. // The clipformat values follows
  1648. if (error = StRead(lpstream, &dwValue, sizeof(DWORD)))
  1649. return error;
  1650. *lpdwCf = dwValue;
  1651. }
  1652. else if (dwValue == -2L)
  1653. {
  1654. // Then this is a NON-NULL MAC clipboard format.
  1655. // The clipformat value follows. For MAC the CLIPFORMAT
  1656. // is 4 bytes
  1657. if (error = StRead(lpstream, &dwValue, sizeof(DWORD)))
  1658. {
  1659. return error;
  1660. }
  1661. *lpdwCf = dwValue;
  1662. return ResultFromScode(OLE_S_MAC_CLIPFORMAT);
  1663. }
  1664. else
  1665. {
  1666. char szACF[MAX_STR];
  1667. if (error = StRead(lpstream, szACF, dwValue))
  1668. {
  1669. return error;
  1670. }
  1671. if (((*lpdwCf = (DWORD) SSRegisterClipboardFormatA(szACF))) == 0)
  1672. {
  1673. return ResultFromScode(DV_E_CLIPFORMAT);
  1674. }
  1675. }
  1676. return NOERROR;
  1677. }
  1678. //+-------------------------------------------------------------------------
  1679. //
  1680. // Function: WriteClipformatStm
  1681. //
  1682. // Synopsis: Writes the clipboard format the given stream
  1683. //
  1684. // Arguments: [lpstream] -- pointer to the stream
  1685. // [cf] -- the clipboard format
  1686. //
  1687. // Returns: HRESULT
  1688. //
  1689. // History: dd-mmm-yy Author Comment
  1690. // 11-Jan-94 alexgo cast -1 to a DWORD to remove compile
  1691. // warning
  1692. // 27-Oct-93 alexgo 32bit port
  1693. // 16-Mar-94 davepl Revereted to ANSI string writes
  1694. //
  1695. // Notes: see ReadClipformatStm for a description of the
  1696. // data layout in the stream
  1697. //
  1698. //--------------------------------------------------------------------------
  1699. #pragma SEG(WriteClipformatStm)
  1700. STDAPI WriteClipformatStm(LPSTREAM lpstream, CLIPFORMAT cf)
  1701. {
  1702. VDATEHEAP();
  1703. #ifdef _MAC
  1704. AssertSz(0,"WriteClipformatStm NYI");
  1705. return ReportResult(0, E_NOTIMPL, 0, 0);
  1706. #else
  1707. HRESULT error;
  1708. VDATEIFACE( lpstream );
  1709. //REVIEW32 where did 0xC000 come from??? Is this
  1710. //portable to NT && Chicago??? Try to replace with a constant.
  1711. //(although there don't seem to be any :( )
  1712. if (cf < 0xC000)
  1713. {
  1714. DWORD dwBuf[2];
  1715. DWORD dwSize = sizeof(DWORD);
  1716. if (cf == NULL)
  1717. {
  1718. dwBuf[0] = NULL;
  1719. }
  1720. else
  1721. {
  1722. // write -1L, to indicate NON NULL predefined
  1723. // clipboard format
  1724. dwBuf[0] = (DWORD)-1L;
  1725. dwBuf[1] = (DWORD)cf;
  1726. dwSize += sizeof(DWORD);
  1727. }
  1728. if (error = StWrite(lpstream, dwBuf, dwSize))
  1729. {
  1730. return error;
  1731. }
  1732. }
  1733. else
  1734. {
  1735. // it is a registerd clipboard format
  1736. char szACF[MAX_STR];
  1737. ULONG len;
  1738. // Get the name of the clipboard format
  1739. len = SSGetClipboardFormatNameA(cf, szACF, sizeof(szACF));
  1740. if (0 == len)
  1741. {
  1742. return ResultFromScode(E_UNSPEC);
  1743. }
  1744. ++len; // Account for NULL terminator
  1745. if (error = StWrite(lpstream, &len, sizeof(len)))
  1746. {
  1747. return error;
  1748. }
  1749. // Write it (plus terminator) to the stream
  1750. if (error = StWrite(lpstream, szACF, len))
  1751. {
  1752. return error;
  1753. }
  1754. }
  1755. return NOERROR;
  1756. #endif // _MAC
  1757. }
  1758. //+-------------------------------------------------------------------------
  1759. //
  1760. // Function: WriteMonikerStm
  1761. //
  1762. // Synopsis: Writes the persistent state of the given moniker to the
  1763. // given stream. Internal
  1764. //
  1765. // Effects:
  1766. //
  1767. // Arguments: [pstm] -- pointer to the stream
  1768. // [pmk] -- pointer to the moniker
  1769. //
  1770. // Requires:
  1771. //
  1772. // Returns: HRESULT
  1773. //
  1774. // Signals:
  1775. //
  1776. // Modifies:
  1777. //
  1778. // Algorithm:
  1779. //
  1780. // History: dd-mmm-yy Author Comment
  1781. // 27-Oct-93 alexgo 32bit port
  1782. //
  1783. // Notes:
  1784. //
  1785. //--------------------------------------------------------------------------
  1786. #pragma SEG(WriteMonikerStm)
  1787. // write size long followed by persistent moniker
  1788. STDAPI WriteMonikerStm (LPSTREAM pstm, LPMONIKER pmk)
  1789. {
  1790. VDATEHEAP();
  1791. DWORD cb = NULL;
  1792. ULARGE_INTEGER dwBegin;
  1793. ULARGE_INTEGER dwEnd;
  1794. HRESULT error;
  1795. LARGE_INTEGER large_integer;
  1796. VDATEIFACE( pstm );
  1797. if (pmk == NULL)
  1798. return pstm->Write(&cb, sizeof(DWORD), NULL);
  1799. else {
  1800. VDATEIFACE( pmk );
  1801. // get the begining position
  1802. LISet32( large_integer, 0 );
  1803. if ((error = pstm->Seek (large_integer,
  1804. STREAM_SEEK_CUR, &dwBegin)) != NOERROR)
  1805. return error;
  1806. // skip the moniker size DWORD
  1807. LISet32( large_integer, 4);
  1808. if ((error = pstm->Seek (large_integer,
  1809. STREAM_SEEK_CUR, NULL)) != NOERROR)
  1810. return error;
  1811. if ((error = OleSaveToStream (pmk, pstm)) != NOERROR)
  1812. return error;
  1813. // get the end position
  1814. LISet32( large_integer, 0);
  1815. if ((error = pstm->Seek (large_integer,
  1816. STREAM_SEEK_CUR, &dwEnd)) != NOERROR)
  1817. return error;
  1818. // moniker data size
  1819. cb = dwEnd.LowPart - dwBegin.LowPart;
  1820. // seek to the begining position
  1821. LISet32( large_integer, dwBegin.LowPart);
  1822. if ((error = pstm->Seek (large_integer,
  1823. STREAM_SEEK_SET,NULL)) != NOERROR)
  1824. return error;
  1825. // write moniker info size
  1826. if ((error = pstm->Write(&cb, sizeof(DWORD),
  1827. NULL)) != NOERROR)
  1828. return error;
  1829. // seek to the end position
  1830. LISet32( large_integer, dwEnd.LowPart);
  1831. return pstm->Seek (large_integer, STREAM_SEEK_SET, NULL);
  1832. }
  1833. }
  1834. //+-------------------------------------------------------------------------
  1835. //
  1836. // Function: ReadMonikerStm
  1837. //
  1838. // Synopsis: Reads a moniker from the given stream (inverse of
  1839. // WriteMonikerStm)
  1840. //
  1841. // Effects:
  1842. //
  1843. // Arguments: [pstm] -- pointer to the stream
  1844. // [ppmk] -- where to put the moniker
  1845. //
  1846. // Requires:
  1847. //
  1848. // Returns: HRESULT
  1849. //
  1850. // Signals:
  1851. //
  1852. // Modifies:
  1853. //
  1854. // Algorithm:
  1855. //
  1856. // History: dd-mmm-yy Author Comment
  1857. // 27-Oct-93 alexgo 32bit port
  1858. //
  1859. // Notes:
  1860. //
  1861. //--------------------------------------------------------------------------
  1862. #pragma SEG(ReadMonikerStm)
  1863. // read size long followed by persistent moniker
  1864. STDAPI ReadMonikerStm (LPSTREAM pstm, LPMONIKER FAR* ppmk)
  1865. {
  1866. VDATEHEAP();
  1867. HRESULT error;
  1868. DWORD cb;
  1869. VDATEPTROUT( ppmk, LPMONIKER );
  1870. *ppmk = NULL;
  1871. VDATEIFACE( pstm );
  1872. if ((error = StRead (pstm, &cb, sizeof(DWORD))) != NOERROR)
  1873. return error;
  1874. if (cb == NULL)
  1875. return NOERROR;
  1876. return OleLoadFromStream (pstm, IID_IMoniker, (LPLPVOID) ppmk);
  1877. }
  1878. //+-------------------------------------------------------------------------
  1879. //
  1880. // Function: OleDraw
  1881. //
  1882. // Synopsis: Calls IViewObject->Draw on the given object
  1883. //
  1884. // Effects: Draws something on the screen :)
  1885. //
  1886. // Arguments: [lpUnk] -- pointer to the object
  1887. // [dwAspect] -- aspect to draw (NORMAL, ICON, etc)
  1888. // [hdcDraw] -- the device context to use
  1889. // [lprcBounds] -- the rectangle in which to draw
  1890. //
  1891. // Requires:
  1892. //
  1893. // Returns: HRESULT
  1894. //
  1895. // Signals:
  1896. //
  1897. // Modifies:
  1898. //
  1899. // Algorithm:
  1900. //
  1901. // History: dd-mmm-yy Author Comment
  1902. // 01-Apr-94 alexgo fixed usage of MAKELONG (only
  1903. // for 16bit)
  1904. // 27-Oct-93 alexgo 32bit port
  1905. //
  1906. // Notes:
  1907. // On Win32, RECT and RECTL are identical structures, thus there
  1908. // is no need to convert from RECT to RECTL with MAKELONG.
  1909. //
  1910. //--------------------------------------------------------------------------
  1911. #pragma SEG(OleDraw)
  1912. STDAPI OleDraw (LPUNKNOWN lpUnk, DWORD dwAspect, HDC hdcDraw,
  1913. LPCRECT lprcBounds)
  1914. {
  1915. HRESULT error;
  1916. IViewObject FAR* lpView;
  1917. #ifndef WIN32
  1918. RECTL rclBounds;
  1919. #endif //!WIN32
  1920. OLETRACEIN((API_OleDraw, PARAMFMT("lpUnk= %p, dwAspect= %x, hdcDraw= %h, lprcBounds= %tr"),
  1921. lpUnk, dwAspect, hdcDraw, lprcBounds));
  1922. VDATEHEAP();
  1923. VDATEIFACE_LABEL( lpUnk, errRtn, error );
  1924. VDATEPTRIN_LABEL( lprcBounds, RECT, errRtn, error);
  1925. #ifndef WIN32
  1926. rclBounds.left = MAKELONG(lprcBounds->left, 0);
  1927. rclBounds.right = MAKELONG(lprcBounds->right, 0);
  1928. rclBounds.top = MAKELONG(lprcBounds->top, 0);
  1929. rclBounds.bottom = MAKELONG(lprcBounds->bottom, 0);
  1930. lprcBounds = &rclBounds;
  1931. #endif //!WIN32
  1932. if ((error = lpUnk->QueryInterface (IID_IViewObject,
  1933. (LPLPVOID)&lpView)) != NOERROR)
  1934. {
  1935. error = ResultFromScode(DV_E_NOIVIEWOBJECT);
  1936. goto errRtn;
  1937. }
  1938. error = lpView->Draw (dwAspect, DEF_LINDEX, 0, 0, 0,
  1939. hdcDraw, (LPCRECTL)lprcBounds, 0, 0,0);
  1940. lpView->Release();
  1941. errRtn:
  1942. OLETRACEOUT((API_OleDraw, error));
  1943. return error;
  1944. }
  1945. //+----------------------------------------------------------------------------
  1946. //
  1947. // Function:
  1948. // CreateObjectDescriptor, static
  1949. //
  1950. // Synopsis:
  1951. // Creates and initializes an OBJECTDESCRIPTOR from the given
  1952. // parameters
  1953. //
  1954. // Arguments:
  1955. // [clsid] -- the class ID of the object being transferred
  1956. // [dwAspect] -- the display aspect drawn by the source of the
  1957. // transfer
  1958. // [psizel] -- pointer to the size of the object
  1959. // [ppointl] -- pointer to the mouse offset in the object that
  1960. // initiated a drag-drop transfer
  1961. // [dwStatus] -- the OLEMISC status flags for the object
  1962. // being transferred
  1963. // [lpszFullUserTypeName] -- the full user type name of the
  1964. // object being transferred
  1965. // [lpszSrcOfCopy] -- a human readable name for the object
  1966. // being transferred
  1967. //
  1968. // Returns:
  1969. // If successful, A handle to the new OBJECTDESCRIPTOR; otherwise
  1970. // NULL.
  1971. //
  1972. // Notes:
  1973. // REVIEW, this seems generally useful for anyone using the
  1974. // clipboard, or drag-drop; perhaps it should be exported.
  1975. //
  1976. // History:
  1977. // 12/07/93 - ChrisWe - file inspection and cleanup
  1978. //
  1979. //-----------------------------------------------------------------------------
  1980. #pragma SEG(CreateObjectDescriptor)
  1981. INTERNAL_(HGLOBAL) CreateObjectDescriptor(CLSID clsid, DWORD dwAspect,
  1982. const SIZEL FAR *psizel, const POINTL FAR *ppointl,
  1983. DWORD dwStatus, LPOLESTR lpszFullUserTypeName,
  1984. LPOLESTR lpszSrcOfCopy)
  1985. {
  1986. VDATEHEAP();
  1987. DWORD dwFullUserTypeNameBLen; // length of lpszFullUserTypeName in BYTES
  1988. DWORD dwSrcOfCopyBLen; // length of lpszSrcOfCopy in BYTES
  1989. HGLOBAL hMem; // handle to the object descriptor
  1990. LPOBJECTDESCRIPTOR lpOD; // the new object descriptor
  1991. // Get the length of Full User Type Name; Add 1 for the null terminator
  1992. if (!lpszFullUserTypeName)
  1993. dwFullUserTypeNameBLen = 0;
  1994. else
  1995. dwFullUserTypeNameBLen = (_xstrlen(lpszFullUserTypeName) +
  1996. 1) * sizeof(OLECHAR);
  1997. // Get the Source of Copy string and it's length; Add 1 for the null
  1998. // terminator
  1999. if (lpszSrcOfCopy)
  2000. dwSrcOfCopyBLen = (_xstrlen(lpszSrcOfCopy) + 1) *
  2001. sizeof(OLECHAR);
  2002. else
  2003. {
  2004. // No src moniker so use user type name as source string.
  2005. lpszSrcOfCopy = lpszFullUserTypeName;
  2006. dwSrcOfCopyBLen = dwFullUserTypeNameBLen;
  2007. }
  2008. // allocate the memory where we'll put the object descriptor
  2009. hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE,
  2010. sizeof(OBJECTDESCRIPTOR) + dwFullUserTypeNameBLen +
  2011. dwSrcOfCopyBLen);
  2012. if (hMem == NULL)
  2013. goto error;
  2014. lpOD = (LPOBJECTDESCRIPTOR)GlobalLock(hMem);
  2015. if (lpOD == NULL)
  2016. goto error;
  2017. // Set the FullUserTypeName offset and copy the string
  2018. if (!lpszFullUserTypeName)
  2019. {
  2020. // zero offset indicates that string is not present
  2021. lpOD->dwFullUserTypeName = 0;
  2022. }
  2023. else
  2024. {
  2025. lpOD->dwFullUserTypeName = sizeof(OBJECTDESCRIPTOR);
  2026. _xmemcpy(((BYTE FAR *)lpOD)+lpOD->dwFullUserTypeName,
  2027. (const void FAR *)lpszFullUserTypeName,
  2028. dwFullUserTypeNameBLen);
  2029. }
  2030. // Set the SrcOfCopy offset and copy the string
  2031. if (!lpszSrcOfCopy)
  2032. {
  2033. // zero offset indicates that string is not present
  2034. lpOD->dwSrcOfCopy = 0;
  2035. }
  2036. else
  2037. {
  2038. lpOD->dwSrcOfCopy = sizeof(OBJECTDESCRIPTOR) +
  2039. dwFullUserTypeNameBLen;
  2040. _xmemcpy(((BYTE FAR *)lpOD)+lpOD->dwSrcOfCopy,
  2041. (const void FAR *)lpszSrcOfCopy,
  2042. dwSrcOfCopyBLen);
  2043. }
  2044. // Initialize the rest of the OBJECTDESCRIPTOR
  2045. lpOD->cbSize = sizeof(OBJECTDESCRIPTOR) + dwFullUserTypeNameBLen +
  2046. dwSrcOfCopyBLen;
  2047. lpOD->clsid = clsid;
  2048. lpOD->dwDrawAspect = dwAspect;
  2049. lpOD->sizel = *psizel;
  2050. lpOD->pointl = *ppointl;
  2051. lpOD->dwStatus = dwStatus;
  2052. GlobalUnlock(hMem);
  2053. return(hMem);
  2054. error:
  2055. if (hMem)
  2056. {
  2057. GlobalUnlock(hMem);
  2058. GlobalFree(hMem);
  2059. }
  2060. return(NULL);
  2061. }