Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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