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.

727 lines
18 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: ole2lcl.cxx (16 bit target)
  7. //
  8. // Contents: OLE2 APIs implemented locally
  9. //
  10. // Functions:
  11. //
  12. // History: 17-Dec-93 Johann Posch (johannp) Created
  13. //
  14. //--------------------------------------------------------------------------
  15. #include <headers.cxx>
  16. #pragma hdrstop
  17. #include <limits.h>
  18. #include <ole2sp.h>
  19. #include <ole2ver.h>
  20. #include <valid.h>
  21. #include <ole2int.h>
  22. #include <call32.hxx>
  23. #include <apilist.hxx>
  24. DWORD gdwOleVersion = MAKELONG(OLE_STREAM_VERSION, OLE_PRODUCT_VERSION);
  25. //+---------------------------------------------------------------------------
  26. //
  27. // Function: OleGetMalloc, Local
  28. //
  29. //----------------------------------------------------------------------------
  30. STDAPI OleGetMalloc(DWORD dwContext, IMalloc FAR* FAR* ppMalloc)
  31. {
  32. return CoGetMalloc(dwContext, ppMalloc);
  33. }
  34. //+---------------------------------------------------------------------------
  35. //
  36. // Function: OleBuildVersion, Local
  37. //
  38. //----------------------------------------------------------------------------
  39. STDAPI_(DWORD) OleBuildVersion( VOID )
  40. {
  41. return CoBuildVersion();
  42. }
  43. //+---------------------------------------------------------------------------
  44. //
  45. // Function: OleDuplicateData, Local
  46. //
  47. // Synopsis: Duplicates the given data
  48. //
  49. // History: 11-Apr-94 DrewB Copied from various places in OLE2
  50. //
  51. //----------------------------------------------------------------------------
  52. FARINTERNAL_(HBITMAP) BmDuplicate
  53. (HBITMAP hold, DWORD FAR* lpdwSize, LPBITMAP lpBm)
  54. {
  55. HBITMAP hnew = NULL;
  56. HANDLE hMem;
  57. LPSTR lpMem;
  58. DWORD dwSize;
  59. BITMAP bm;
  60. SIZE extents;
  61. extents.cx = extents.cy = 0;
  62. GetObject (hold, sizeof(BITMAP), (LPSTR) &bm);
  63. dwSize = ((DWORD) bm.bmHeight) * ((DWORD) bm.bmWidthBytes) *
  64. ((DWORD) bm.bmPlanes);
  65. if (!(hMem = GlobalAlloc (GMEM_MOVEABLE, dwSize)))
  66. return NULL;
  67. if (!(lpMem = (LPSTR) GlobalLock (hMem)))
  68. goto errRtn;
  69. GlobalUnlock (hMem);
  70. GetBitmapBits (hold, dwSize, lpMem);
  71. if (hnew = CreateBitmap (bm.bmWidth, bm.bmHeight,
  72. bm.bmPlanes, bm.bmBitsPixel, NULL)) {
  73. if (!SetBitmapBits (hnew, dwSize, lpMem)) {
  74. DeleteObject (hnew);
  75. hnew = NULL;
  76. goto errRtn;
  77. }
  78. }
  79. if (lpdwSize)
  80. *lpdwSize = dwSize;
  81. if (lpBm)
  82. *lpBm = bm;
  83. if (GetBitmapDimensionEx(hold, &extents) && extents.cx && extents.cy)
  84. SetBitmapDimensionEx(hnew, extents.cx, extents.cy, NULL);
  85. errRtn:
  86. if (hMem)
  87. GlobalFree (hMem);
  88. return hnew;
  89. }
  90. FARINTERNAL_(HPALETTE) UtDupPalette
  91. (HPALETTE hpalette)
  92. {
  93. WORD cEntries = 0;
  94. HANDLE hLogPal = NULL;
  95. LPLOGPALETTE pLogPal = NULL;
  96. HPALETTE hpaletteNew = NULL;
  97. if (0==GetObject (hpalette, sizeof(cEntries), &cEntries))
  98. return NULL;
  99. if (NULL==(hLogPal = GlobalAlloc (GMEM_MOVEABLE, sizeof (LOGPALETTE) +
  100. cEntries * sizeof (PALETTEENTRY))))
  101. return NULL;
  102. if (NULL==(pLogPal = (LPLOGPALETTE) GlobalLock (hLogPal)))
  103. goto errRtn;
  104. if (0==GetPaletteEntries (hpalette, 0, cEntries, pLogPal->palPalEntry))
  105. goto errRtn;
  106. pLogPal->palVersion = 0x300;
  107. pLogPal->palNumEntries = cEntries;
  108. if (NULL==(hpaletteNew = CreatePalette (pLogPal)))
  109. goto errRtn;
  110. errRtn:
  111. if (pLogPal)
  112. GlobalUnlock (hLogPal);
  113. if (hLogPal)
  114. GlobalFree (hLogPal);
  115. AssertSz (hpaletteNew, "Warning: UtDupPalette Failed");
  116. return hpaletteNew;
  117. }
  118. FARINTERNAL_(HANDLE) UtDupGlobal (HANDLE hsrc, UINT uiFlags)
  119. {
  120. HANDLE hdst;
  121. DWORD dwSize;
  122. #ifndef _MAC
  123. LPSTR lpdst = NULL;
  124. LPSTR lpsrc = NULL;
  125. #endif
  126. if (!hsrc)
  127. return NULL;
  128. #ifdef _MAC
  129. if (!(hdst = NewHandle(dwSize = GetHandleSize(hsrc))))
  130. return NULL;
  131. BlockMove(*hsrc, *hdst, dwSize);
  132. return hdst;
  133. #else
  134. if (!(lpsrc = GlobalLock (hsrc)))
  135. return NULL;
  136. hdst = GlobalAlloc (uiFlags, (dwSize = GlobalSize(hsrc)));
  137. if (hdst == NULL || (lpdst = GlobalLock (hdst)) == NULL)
  138. goto errRtn;
  139. UtMemCpy (lpdst, lpsrc, dwSize);
  140. GlobalUnlock (hsrc);
  141. GlobalUnlock (hdst);
  142. return hdst;
  143. errRtn:
  144. if (hdst)
  145. GlobalFree (hdst);
  146. return NULL;
  147. #endif
  148. }
  149. OLEAPI_(HANDLE) OleDuplicateData
  150. (HANDLE hSrc, CLIPFORMAT cfFormat, UINT uiFlags)
  151. {
  152. #ifndef _MAC
  153. if (!hSrc)
  154. return NULL;
  155. if (cfFormat == CF_BITMAP)
  156. return (HANDLE) BmDuplicate ((HBITMAP)hSrc, NULL, NULL);
  157. if (cfFormat == CF_PALETTE)
  158. return (HANDLE) UtDupPalette ((HPALETTE)hSrc);
  159. if (uiFlags == NULL)
  160. uiFlags = GMEM_MOVEABLE;
  161. if (cfFormat == CF_METAFILEPICT) {
  162. HANDLE hDst;
  163. LPMETAFILEPICT lpmfpSrc;
  164. LPMETAFILEPICT lpmfpDst;
  165. if (!(lpmfpSrc = (LPMETAFILEPICT) GlobalLock (hSrc)))
  166. return NULL;
  167. if (!(hDst = UtDupGlobal (hSrc, uiFlags)))
  168. return NULL;
  169. if (!(lpmfpDst = (LPMETAFILEPICT) GlobalLock (hDst))) {
  170. GlobalFree (hDst);
  171. return NULL;
  172. }
  173. *lpmfpDst = *lpmfpSrc;
  174. lpmfpDst->hMF = CopyMetaFile (lpmfpSrc->hMF, NULL);
  175. GlobalUnlock (hSrc);
  176. GlobalUnlock (hDst);
  177. return hDst;
  178. } else {
  179. return UtDupGlobal (hSrc, uiFlags);
  180. }
  181. #else
  182. AssertSz(0,"OleDuplicateData NYI");
  183. return NULL;
  184. #endif
  185. }
  186. //+---------------------------------------------------------------------------
  187. //
  188. // Function: SetBitOleStg, private
  189. //
  190. // Synopsis: Sets bit in ole stream; doc bit preserved even when stream
  191. // rewritten above; the value written is (old & mask) | value.
  192. //
  193. // Arguments: [pstg] - Storage
  194. // [mask] - Mask
  195. // [value] - Value
  196. //
  197. // Returns: Appropriate status code
  198. //
  199. // History: 11-Mar-94 DrewB Created
  200. //
  201. // Notes: Taken straight from OLE2 source
  202. //
  203. //----------------------------------------------------------------------------
  204. static INTERNAL SetBitOleStg(LPSTORAGE pstg, DWORD mask, DWORD value)
  205. {
  206. IStream FAR * pstm = NULL;
  207. HRESULT error;
  208. DWORD objflags = 0;
  209. LARGE_INTEGER large_integer;
  210. ULONG cbRead;
  211. VDATEIFACE( pstg );
  212. if (error = pstg->OpenStream(OLE_STREAM, NULL, STGM_SALL, 0, &pstm))
  213. {
  214. if (STG_E_FILENOTFOUND != GetScode(error))
  215. {
  216. goto errRtn;
  217. }
  218. if (error = pstg->CreateStream(OLE_STREAM, STGM_SALL, 0, 0, &pstm))
  219. {
  220. goto errRtn;
  221. }
  222. DWORD dwBuf[5];
  223. dwBuf[0] = gdwOleVersion;
  224. dwBuf[1] = objflags;
  225. dwBuf[2] = 0L;
  226. dwBuf[3] = 0L;
  227. dwBuf[4] = 0L;
  228. if ((error = pstm->Write(dwBuf, 5*sizeof(DWORD), NULL)) != NOERROR)
  229. {
  230. goto errRtn;
  231. }
  232. }
  233. // seek directly to word, read, modify, seek back and write.
  234. LISet32( large_integer, sizeof(DWORD) );
  235. if ((error = pstm->Seek(large_integer, STREAM_SEEK_SET, NULL)) != NOERROR)
  236. {
  237. goto errRtn;
  238. }
  239. if ((error = pstm->Read(&objflags, sizeof(objflags), &cbRead)) != NOERROR)
  240. {
  241. goto errRtn;
  242. }
  243. if (cbRead != sizeof(objflags))
  244. {
  245. goto errRtn;
  246. }
  247. objflags = (objflags & mask) | value;
  248. LISet32( large_integer, sizeof(DWORD) );
  249. if ((error = pstm->Seek(large_integer, STREAM_SEEK_SET, NULL)) != NOERROR)
  250. {
  251. goto errRtn;
  252. }
  253. error = pstm->Write(&objflags, sizeof(DWORD), NULL);
  254. errRtn:
  255. // close and return error code.
  256. if (pstm)
  257. {
  258. pstm->Release();
  259. }
  260. return error;
  261. }
  262. //+---------------------------------------------------------------------------
  263. //
  264. // Function: GetFlagsOleStg, private
  265. //
  266. // Synopsis: Return long word of flags from the ole stream
  267. //
  268. // Arguments: [pstg] - Storage
  269. // [lpobjflags] - Flags return
  270. //
  271. // Returns: Appropriate status code
  272. //
  273. // Modifies: [lpobjflags]
  274. //
  275. // History: 11-Mar-94 DrewB Created
  276. //
  277. // Notes: Taken straight from OLE2 source
  278. //
  279. //----------------------------------------------------------------------------
  280. static INTERNAL GetFlagsOleStg(LPSTORAGE pstg, LPDWORD lpobjflags)
  281. {
  282. IStream FAR * pstm = NULL;
  283. HRESULT error;
  284. LARGE_INTEGER large_integer;
  285. ULONG cbRead;
  286. VDATEIFACE( pstg );
  287. if ((error = pstg->OpenStream(OLE_STREAM, NULL,
  288. (STGM_READ | STGM_SHARE_EXCLUSIVE),
  289. 0, &pstm)) != NOERROR)
  290. {
  291. goto errRtn;
  292. }
  293. // seek directly to word, read, modify, seek back and write.
  294. LISet32( large_integer, sizeof(DWORD) );
  295. if ((error = pstm->Seek(large_integer, STREAM_SEEK_SET, NULL)) != NOERROR)
  296. {
  297. goto errRtn;
  298. }
  299. error = pstm->Read(lpobjflags, sizeof(*lpobjflags), &cbRead);
  300. if (SUCCEEDED(GetScode(error)) && cbRead != sizeof(*lpobjflags))
  301. {
  302. error = ResultFromScode(STG_E_READFAULT);
  303. }
  304. errRtn:
  305. // close and return error NOERROR (document)/S_FALSE (embedding);
  306. if (pstm)
  307. {
  308. pstm->Release();
  309. }
  310. return error == NOERROR ? NOERROR : ReportResult(0, S_FALSE, 0, 0);
  311. }
  312. //+---------------------------------------------------------------------------
  313. //
  314. // Function: GetDocumentBitStg, semi-private
  315. //
  316. // Synopsis: Get doc bit; return NOERROR if on; S_FALSE if off
  317. //
  318. // Arguments: [pStg] - Storage
  319. //
  320. // Returns: Appropriate status code
  321. //
  322. // History: 11-Mar-94 DrewB Created
  323. //
  324. // Notes: Taken straight from OLE2 source
  325. //
  326. //----------------------------------------------------------------------------
  327. STDAPI GetDocumentBitStg(LPSTORAGE pStg)
  328. {
  329. DWORD objflags;
  330. HRESULT error;
  331. if ((error = GetFlagsOleStg(pStg, &objflags)) != NOERROR)
  332. {
  333. return error;
  334. }
  335. return (objflags&OBJFLAGS_DOCUMENT) ? NOERROR : ResultFromScode(S_FALSE);
  336. }
  337. //+---------------------------------------------------------------------------
  338. //
  339. // Function: SetDocumentBitStg, semi-private
  340. //
  341. // Synopsis: Set doc bit according to fDocument
  342. //
  343. // Arguments: [pStg] - Storage
  344. // [fDocument] - Document flag
  345. //
  346. // Returns: Appropriate status code
  347. //
  348. // History: 11-Mar-94 DrewB Created
  349. //
  350. // Notes: Taken straight from OLE2 source
  351. //
  352. //----------------------------------------------------------------------------
  353. STDAPI SetDocumentBitStg(LPSTORAGE pStg, BOOL fDocument)
  354. {
  355. return SetBitOleStg(pStg, fDocument ? -1L : ~OBJFLAGS_DOCUMENT,
  356. fDocument ? OBJFLAGS_DOCUMENT : 0);
  357. }
  358. //+---------------------------------------------------------------------------
  359. //
  360. // Function: ReleaseStgMedium, public
  361. //
  362. // History: 18-Mar-94 Taken straight from OLE2 source
  363. //
  364. //----------------------------------------------------------------------------
  365. STDAPI_(void) ReleaseStgMedium(LPSTGMEDIUM pMedium)
  366. {
  367. if (pMedium)
  368. {
  369. //VDATEPTRIN rejects NULL
  370. VOID_VDATEPTRIN( pMedium, STGMEDIUM );
  371. BOOL fPunkRel = pMedium->pUnkForRelease != NULL;
  372. switch (pMedium->tymed)
  373. {
  374. case TYMED_HGLOBAL:
  375. if (pMedium->hGlobal != NULL && !fPunkRel)
  376. Verify(GlobalFree(pMedium->hGlobal) == 0);
  377. break;
  378. case TYMED_GDI:
  379. if (pMedium->hGlobal != NULL && !fPunkRel)
  380. DeleteObject(pMedium->hGlobal);
  381. break;
  382. case TYMED_MFPICT:
  383. if (pMedium->hGlobal != NULL && !fPunkRel)
  384. {
  385. LPMETAFILEPICT pmfp;
  386. if ((pmfp = (LPMETAFILEPICT)GlobalLock(pMedium->hGlobal)) ==
  387. NULL)
  388. break;
  389. DeleteMetaFile(pmfp->hMF);
  390. GlobalUnlock(pMedium->hGlobal);
  391. Verify(GlobalFree(pMedium->hGlobal) == 0);
  392. }
  393. break;
  394. case TYMED_FILE:
  395. if (pMedium->lpszFileName != NULL)
  396. {
  397. if (!IsValidPtrIn(pMedium->lpszFileName, 1))
  398. break;
  399. if (!fPunkRel)
  400. {
  401. #ifdef WIN32
  402. DeleteFile(pMedium->lpszFileName);
  403. #else
  404. #ifdef _MAC
  405. /* the libraries are essentially small model on the MAC */
  406. Verify(0==remove(pMedium->lpszFileName));
  407. #else
  408. #ifdef OLD_AND_NICE_ASSEMBLER_VERSION
  409. /* Win 3.1 specific code to call DOS to delete the file
  410. given a far pointer to the file name */
  411. extern void WINAPI DOS3Call(void);
  412. _asm
  413. {
  414. mov ah,41H
  415. push ds
  416. lds bx,pMedium
  417. lds dx,[bx].lpszFileName
  418. call DOS3Call
  419. pop ds
  420. }
  421. #else
  422. {
  423. OFSTRUCT of;
  424. OpenFile(pMedium->lpszFileName, &of, OF_DELETE);
  425. }
  426. #endif
  427. #endif
  428. #endif
  429. delete pMedium->lpszFileName;
  430. }
  431. }
  432. break;
  433. case TYMED_ISTREAM:
  434. if (pMedium->pstm != NULL &&
  435. IsValidInterface(pMedium->pstm))
  436. pMedium->pstm->Release();
  437. break;
  438. case TYMED_ISTORAGE:
  439. if (pMedium->pstg != NULL &&
  440. IsValidInterface(pMedium->pstg))
  441. pMedium->pstg->Release();
  442. break;
  443. case TYMED_NULL:
  444. break;
  445. default:
  446. thkAssert(!"Invalid medium in ReleaseStgMedium");
  447. }
  448. // NULL out to prevent unwanted use of just freed data
  449. pMedium->tymed = TYMED_NULL;
  450. if (pMedium->pUnkForRelease)
  451. {
  452. if (IsValidInterface(pMedium->pUnkForRelease))
  453. pMedium->pUnkForRelease->Release();
  454. pMedium->pUnkForRelease = NULL;
  455. }
  456. }
  457. }
  458. //+---------------------------------------------------------------------------
  459. //
  460. // Function: OleDoAutoConvert, local
  461. //
  462. // Synopsis: Taken from ole32 code
  463. //
  464. // History: 06-Oct-94 DrewB Created
  465. //
  466. // Notes: This routine must be local because it can return
  467. // information through pClsidNew even when it is
  468. // returning an error
  469. //
  470. //----------------------------------------------------------------------------
  471. STDAPI OleDoAutoConvert(LPSTORAGE pStg, LPCLSID pClsidNew)
  472. {
  473. HRESULT error;
  474. CLSID clsidOld;
  475. CLIPFORMAT cfOld;
  476. LPSTR lpszOld = NULL;
  477. LPSTR lpszNew = NULL;
  478. LPMALLOC pma;
  479. if ((error = ReadClassStg(pStg, &clsidOld)) != NOERROR)
  480. {
  481. clsidOld = CLSID_NULL;
  482. goto errRtn;
  483. }
  484. if ((error = OleGetAutoConvert(clsidOld, pClsidNew)) != NOERROR)
  485. {
  486. goto errRtn;
  487. }
  488. // read old fmt/old user type; sets out params to NULL on error
  489. error = ReadFmtUserTypeStg(pStg, &cfOld, &lpszOld);
  490. Assert(error == NOERROR || (cfOld == NULL && lpszOld == NULL));
  491. // get new user type name; if error, set to NULL string
  492. if ((error = OleRegGetUserType(*pClsidNew, USERCLASSTYPE_FULL,
  493. &lpszNew)) != NOERROR)
  494. {
  495. lpszNew = NULL;
  496. }
  497. // write class stg
  498. if ((error = WriteClassStg(pStg, *pClsidNew)) != NOERROR)
  499. {
  500. goto errRtn;
  501. }
  502. // write old fmt/new user type;
  503. if ((error = WriteFmtUserTypeStg(pStg, cfOld, lpszNew)) != NOERROR)
  504. {
  505. goto errRewriteInfo;
  506. }
  507. // set convert bit
  508. if ((error = SetConvertStg(pStg, TRUE)) != NOERROR)
  509. {
  510. goto errRewriteInfo;
  511. }
  512. goto okRtn;
  513. errRewriteInfo:
  514. (void)WriteClassStg(pStg, clsidOld);
  515. (void)WriteFmtUserTypeStg(pStg, cfOld, lpszOld);
  516. errRtn:
  517. *pClsidNew = clsidOld;
  518. okRtn:
  519. if (CoGetMalloc(MEMCTX_TASK, &pma) == NOERROR)
  520. {
  521. pma->Free(lpszOld);
  522. pma->Free(lpszNew);
  523. pma->Release();
  524. }
  525. return error;
  526. }
  527. /****** Other API defintions **********************************************/
  528. //+---------------------------------------------------------------------------
  529. //
  530. // Function: Utility functions not in the spec; in ole2.dll.
  531. //
  532. // History: 20-Apr-94 DrewB Taken from OLE2 sources
  533. //
  534. //----------------------------------------------------------------------------
  535. #define AVERAGE_STR_SIZE 64
  536. FARINTERNAL_(HRESULT) StRead (IStream FAR * lpstream, LPVOID lpBuf, ULONG ulLen)
  537. {
  538. HRESULT error;
  539. ULONG cbRead;
  540. if ((error = lpstream->Read( lpBuf, ulLen, &cbRead)) != NOERROR)
  541. return error;
  542. return ((cbRead != ulLen) ? ResultFromScode(STG_E_READFAULT) : NOERROR);
  543. }
  544. // returns S_OK when string read and allocated (even if zero length)
  545. OLEAPI ReadStringStream( LPSTREAM pstm, LPSTR FAR * ppsz )
  546. {
  547. ULONG cb;
  548. HRESULT hresult;
  549. *ppsz = NULL;
  550. if ((hresult = StRead(pstm, (void FAR *)&cb, sizeof(ULONG))) != NOERROR)
  551. return hresult;
  552. if (cb == NULL)
  553. // NULL string case
  554. return NOERROR;
  555. if ((LONG)cb < 0 || cb > INT_MAX)
  556. // out of range
  557. return ReportResult(0, E_UNSPEC, 0, 0);
  558. if (!(*ppsz = new FAR char[(int)cb]))
  559. return ReportResult(0, E_OUTOFMEMORY, 0, 0);
  560. if ((hresult = StRead(pstm, (void FAR *)(*ppsz), cb)) != NOERROR)
  561. goto errRtn;
  562. return NOERROR;
  563. errRtn:
  564. delete *ppsz;
  565. *ppsz = NULL;
  566. return hresult;
  567. }
  568. OLEAPI WriteStringStream(LPSTREAM pstm, LPCSTR psz)
  569. {
  570. HRESULT error;
  571. ULONG cb = NULL;
  572. if (psz) {
  573. cb = 1 + _fstrlen(psz);
  574. // if possible, do a single write instead of two
  575. if (cb <= AVERAGE_STR_SIZE-4) {
  576. char szBuf[AVERAGE_STR_SIZE];
  577. *((ULONG FAR*) szBuf) = cb;
  578. lstrcpy(szBuf+sizeof(ULONG), psz);
  579. return pstm->Write((VOID FAR *)szBuf, cb+sizeof(ULONG), NULL);
  580. }
  581. }
  582. if (error = pstm->Write((VOID FAR *)&cb, sizeof(ULONG), NULL))
  583. return error;
  584. if (psz == NULL)
  585. // we are done writing the string
  586. return NOERROR;
  587. return pstm->Write((VOID FAR *)psz, cb, NULL);
  588. }
  589. OLEAPI OpenOrCreateStream( IStorage FAR * pstg, char const FAR * pwcsName,
  590. IStream FAR* FAR* ppstm)
  591. {
  592. HRESULT error;
  593. error = pstg->CreateStream(pwcsName,
  594. STGM_SALL | STGM_FAILIFTHERE, 0, 0, ppstm);
  595. if (GetScode(error) == STG_E_FILEALREADYEXISTS)
  596. error = pstg->OpenStream(pwcsName, NULL, STGM_SALL, 0, ppstm);
  597. return error;
  598. }