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.

765 lines
26 KiB

  1. /*************************************************************************
  2. **
  3. ** OLE 2 Standard Utilities
  4. **
  5. ** olestd.c
  6. **
  7. ** This file contains utilities that are useful for most standard
  8. ** OLE 2.0 compound document type applications.
  9. **
  10. ** (c) Copyright Microsoft Corp. 1992 All Rights Reserved
  11. **
  12. *************************************************************************/
  13. #include "precomp.h"
  14. #include "common.h"
  15. #include "utility.h"
  16. #include <stdlib.h>
  17. #include <shellapi.h>
  18. #include <wchar.h>
  19. #include <reghelp.hxx>
  20. OLEDBGDATA
  21. #ifdef _DEBUG
  22. static TCHAR szAssertMemAlloc[] = TEXT("CoGetMalloc failed");
  23. #endif
  24. static int IsCloseFormatEtc(FORMATETC FAR* pFetcLeft, FORMATETC FAR* pFetcRight);
  25. /* OleStdInitialize
  26. ** ----------------
  27. ** Call to initialize this library sample code
  28. **
  29. */
  30. UINT _g_cfObjectDescriptor;
  31. UINT _g_cfLinkSrcDescriptor;
  32. UINT _g_cfEmbedSource;
  33. UINT _g_cfEmbeddedObject;
  34. UINT _g_cfLinkSource;
  35. UINT _g_cfOwnerLink;
  36. UINT _g_cfFileName;
  37. UINT _g_cfFileNameW;
  38. HINSTANCE _g_hOleStdInst;
  39. HINSTANCE _g_hOleStdResInst;
  40. #pragma code_seg(".text$initseg")
  41. STDAPI_(void) OleStdInitialize(HINSTANCE hInstance, HINSTANCE hResInstance)
  42. {
  43. _g_hOleStdInst = hInstance;
  44. _g_hOleStdResInst = hResInstance ? hResInstance : hInstance;
  45. _g_cfObjectDescriptor = RegisterClipboardFormat(CF_OBJECTDESCRIPTOR);
  46. _g_cfLinkSrcDescriptor = RegisterClipboardFormat(CF_LINKSRCDESCRIPTOR);
  47. _g_cfEmbedSource = RegisterClipboardFormat(CF_EMBEDSOURCE);
  48. _g_cfEmbeddedObject = RegisterClipboardFormat(CF_EMBEDDEDOBJECT);
  49. _g_cfLinkSource = RegisterClipboardFormat(CF_LINKSOURCE);
  50. _g_cfOwnerLink = RegisterClipboardFormat(CF_OWNERLINK);
  51. _g_cfFileName = RegisterClipboardFormat(CF_FILENAME);
  52. _g_cfFileNameW = RegisterClipboardFormat(CF_FILENAMEW);
  53. }
  54. #pragma code_seg()
  55. /* OleStdIsOleLink
  56. ** ---------------
  57. ** Returns TRUE if the OleObject is infact an OLE link object. this
  58. ** checks if IOleLink interface is supported. if so, the object is a
  59. ** link, otherwise not.
  60. */
  61. STDAPI_(BOOL) OleStdIsOleLink(LPUNKNOWN lpUnk)
  62. {
  63. LPUNKNOWN lpOleLink;
  64. lpOleLink = OleStdQueryInterface(lpUnk, IID_IOleLink);
  65. if (lpOleLink)
  66. {
  67. OleStdRelease(lpOleLink);
  68. return TRUE;
  69. }
  70. return FALSE;
  71. }
  72. /* OleStdQueryInterface
  73. ** --------------------
  74. ** Returns the desired interface pointer if exposed by the given object.
  75. ** Returns NULL if the interface is not available.
  76. ** eg.:
  77. ** lpDataObj = OleStdQueryInterface(lpOleObj, &IID_DataObject);
  78. */
  79. STDAPI_(LPUNKNOWN) OleStdQueryInterface(LPUNKNOWN lpUnk, REFIID riid)
  80. {
  81. LPUNKNOWN lpInterface;
  82. HRESULT hrErr;
  83. hrErr = lpUnk->QueryInterface(
  84. riid,
  85. (LPVOID FAR*)&lpInterface
  86. );
  87. if (hrErr == NOERROR)
  88. return lpInterface;
  89. else
  90. return NULL;
  91. }
  92. /* OleStdGetData
  93. ** -------------
  94. ** Retrieve data from an IDataObject in a specified format on a
  95. ** global memory block. This function ALWAYS returns a private copy
  96. ** of the data to the caller. if necessary a copy is made of the
  97. ** data (ie. if lpMedium->pUnkForRelease != NULL). The caller assumes
  98. ** ownership of the data block in all cases and must free the data
  99. ** when done with it. The caller may directly free the data handle
  100. ** returned (taking care whether it is a simple HGLOBAL or a HANDLE
  101. ** to a MetafilePict) or the caller may call
  102. ** ReleaseStgMedium(lpMedium). this OLE helper function will do the
  103. ** right thing.
  104. **
  105. ** PARAMETERS:
  106. ** LPDATAOBJECT lpDataObj -- object on which GetData should be
  107. ** called.
  108. ** CLIPFORMAT cfFormat -- desired clipboard format (eg. CF_TEXT)
  109. ** DVTARGETDEVICE FAR* lpTargetDevice -- target device for which
  110. ** the data should be composed. This may
  111. ** be NULL. NULL can be used whenever the
  112. ** data format is insensitive to target
  113. ** device or when the caller does not care
  114. ** what device is used.
  115. ** LPSTGMEDIUM lpMedium -- ptr to STGMEDIUM struct. the
  116. ** resultant medium from the
  117. ** IDataObject::GetData call is
  118. ** returned.
  119. **
  120. ** RETURNS:
  121. ** HGLOBAL -- global memory handle of retrieved data block.
  122. ** NULL -- if error.
  123. */
  124. STDAPI_(HGLOBAL) OleStdGetData(
  125. LPDATAOBJECT lpDataObj,
  126. CLIPFORMAT cfFormat,
  127. DVTARGETDEVICE FAR* lpTargetDevice,
  128. DWORD dwDrawAspect,
  129. LPSTGMEDIUM lpMedium)
  130. {
  131. HRESULT hrErr;
  132. FORMATETC formatetc;
  133. HGLOBAL hGlobal = NULL;
  134. HGLOBAL hCopy;
  135. LPVOID lp;
  136. formatetc.cfFormat = cfFormat;
  137. formatetc.ptd = lpTargetDevice;
  138. formatetc.dwAspect = dwDrawAspect;
  139. formatetc.lindex = -1;
  140. switch (cfFormat)
  141. {
  142. case CF_METAFILEPICT:
  143. formatetc.tymed = TYMED_MFPICT;
  144. break;
  145. case CF_BITMAP:
  146. formatetc.tymed = TYMED_GDI;
  147. break;
  148. default:
  149. formatetc.tymed = TYMED_HGLOBAL;
  150. break;
  151. }
  152. OLEDBG_BEGIN2(TEXT("IDataObject::GetData called\r\n"))
  153. hrErr = lpDataObj->GetData(
  154. (LPFORMATETC)&formatetc,
  155. lpMedium
  156. );
  157. OLEDBG_END2
  158. if (hrErr != NOERROR)
  159. return NULL;
  160. if ((hGlobal = lpMedium->hGlobal) == NULL)
  161. return NULL;
  162. // Check if hGlobal really points to valid memory
  163. if ((lp = GlobalLock(hGlobal)) != NULL)
  164. {
  165. if (IsBadReadPtr(lp, 1))
  166. {
  167. GlobalUnlock(hGlobal);
  168. return NULL; // ERROR: memory is NOT valid
  169. }
  170. GlobalUnlock(hGlobal);
  171. }
  172. if (hGlobal != NULL && lpMedium->pUnkForRelease != NULL)
  173. {
  174. /* OLE2NOTE: the callee wants to retain ownership of the data.
  175. ** this is indicated by passing a non-NULL pUnkForRelease.
  176. ** thus, we will make a copy of the data and release the
  177. ** callee's copy.
  178. */
  179. hCopy = OleDuplicateData(hGlobal, cfFormat, GHND|GMEM_SHARE);
  180. ReleaseStgMedium(lpMedium); // release callee's copy of data
  181. hGlobal = hCopy;
  182. lpMedium->hGlobal = hCopy;
  183. lpMedium->pUnkForRelease = NULL;
  184. }
  185. return hGlobal;
  186. }
  187. /* OleStdMalloc
  188. ** ------------
  189. ** allocate memory using the currently active IMalloc* allocator
  190. */
  191. STDAPI_(LPVOID) OleStdMalloc(ULONG ulSize)
  192. {
  193. LPVOID pout;
  194. LPMALLOC pmalloc;
  195. if (CoGetMalloc(MEMCTX_TASK, &pmalloc) != NOERROR)
  196. {
  197. OleDbgAssertSz(0, szAssertMemAlloc);
  198. return NULL;
  199. }
  200. pout = (LPVOID)pmalloc->Alloc(ulSize);
  201. pmalloc->Release();
  202. return pout;
  203. }
  204. /* OleStdRealloc
  205. ** -------------
  206. ** re-allocate memory using the currently active IMalloc* allocator
  207. */
  208. STDAPI_(LPVOID) OleStdRealloc(LPVOID pmem, ULONG ulSize)
  209. {
  210. LPVOID pout;
  211. LPMALLOC pmalloc;
  212. if (CoGetMalloc(MEMCTX_TASK, &pmalloc) != NOERROR)
  213. {
  214. OleDbgAssertSz(0, szAssertMemAlloc);
  215. return NULL;
  216. }
  217. pout = (LPVOID)pmalloc->Realloc(pmem, ulSize);
  218. pmalloc->Release();
  219. return pout;
  220. }
  221. /* OleStdFree
  222. ** ----------
  223. ** free memory using the currently active IMalloc* allocator
  224. */
  225. STDAPI_(void) OleStdFree(LPVOID pmem)
  226. {
  227. LPMALLOC pmalloc;
  228. if (pmem == NULL)
  229. return;
  230. if (CoGetMalloc(MEMCTX_TASK, &pmalloc) != NOERROR)
  231. {
  232. OleDbgAssertSz(0, szAssertMemAlloc);
  233. return;
  234. }
  235. if (1 == pmalloc->DidAlloc(pmem))
  236. {
  237. pmalloc->Free(pmem);
  238. }
  239. pmalloc->Release();
  240. }
  241. /* OleStdGetSize
  242. ** -------------
  243. ** Get the size of a memory block that was allocated using the
  244. ** currently active IMalloc* allocator.
  245. */
  246. STDAPI_(ULONG) OleStdGetSize(LPVOID pmem)
  247. {
  248. ULONG ulSize;
  249. LPMALLOC pmalloc;
  250. if (CoGetMalloc(MEMCTX_TASK, &pmalloc) != NOERROR)
  251. {
  252. OleDbgAssertSz(0, szAssertMemAlloc);
  253. return (ULONG)-1;
  254. }
  255. ulSize = (ULONG) pmalloc->GetSize(pmem);
  256. pmalloc->Release();
  257. return ulSize;
  258. }
  259. /* OleStdLoadString
  260. ** ----------------
  261. ** Load a string from resources. The string is allocated
  262. ** with the active IMalloc allocator.
  263. */
  264. STDAPI_(LPTSTR) OleStdLoadString(HINSTANCE hInst, UINT nID)
  265. {
  266. LPTSTR lpszResult = (LPTSTR)OleStdMalloc(256 * sizeof(TCHAR));
  267. if (lpszResult == NULL)
  268. return NULL;
  269. LoadString(hInst, nID, lpszResult, 256);
  270. return lpszResult;
  271. }
  272. /* OleStdCopyString
  273. ** ----------------
  274. ** Copy a string into memory allocated with the currently active
  275. ** IMalloc* allocator.
  276. */
  277. STDAPI_(LPTSTR) OleStdCopyString(LPTSTR lpszSrc)
  278. {
  279. UINT nSize = (lstrlen(lpszSrc)+1) * sizeof(TCHAR);
  280. LPTSTR lpszResult = (LPTSTR)OleStdMalloc(nSize);
  281. if (lpszResult == NULL)
  282. return NULL;
  283. memcpy(lpszResult, lpszSrc, nSize);
  284. return lpszResult;
  285. }
  286. /*
  287. * OleStdGetObjectDescriptorData
  288. *
  289. * Purpose:
  290. * Fills and returns a OBJECTDESCRIPTOR structure.
  291. * See OBJECTDESCRIPTOR for more information.
  292. *
  293. * Parameters:
  294. * clsid CLSID CLSID of object being transferred
  295. * dwDrawAspect DWORD Display Aspect of object
  296. * sizel SIZEL Size of object in HIMETRIC
  297. * pointl POINTL Offset from upper-left corner of object where mouse went
  298. * down for drag. Meaningful only when drag-drop is used.
  299. * dwStatus DWORD OLEMISC flags
  300. * lpszFullUserTypeName LPSTR Full User Type Name
  301. * lpszSrcOfCopy LPSTR Source of Copy
  302. *
  303. * Return Value:
  304. * HBGLOBAL Handle to OBJECTDESCRIPTOR structure.
  305. */
  306. STDAPI_(HGLOBAL) OleStdGetObjectDescriptorData(
  307. CLSID clsid,
  308. DWORD dwDrawAspect,
  309. SIZEL sizel,
  310. POINTL pointl,
  311. DWORD dwStatus,
  312. LPTSTR lpszFullUserTypeName,
  313. LPTSTR lpszSrcOfCopy)
  314. {
  315. HGLOBAL hMem = NULL;
  316. IBindCtx FAR *pbc = NULL;
  317. LPOBJECTDESCRIPTOR lpOD;
  318. DWORD dwObjectDescSize, dwFullUserTypeNameLen, dwSrcOfCopyLen;
  319. // Get the length of Full User Type Name; Add 1 for the null terminator
  320. dwFullUserTypeNameLen = lpszFullUserTypeName ? lstrlen(lpszFullUserTypeName)+1 : 0;
  321. // Get the Source of Copy string and it's length; Add 1 for the null terminator
  322. if (lpszSrcOfCopy)
  323. dwSrcOfCopyLen = lstrlen(lpszSrcOfCopy)+1;
  324. else
  325. {
  326. // No src moniker so use user type name as source string.
  327. lpszSrcOfCopy = lpszFullUserTypeName;
  328. dwSrcOfCopyLen = dwFullUserTypeNameLen;
  329. }
  330. // Allocate space for OBJECTDESCRIPTOR and the additional string data
  331. dwObjectDescSize = sizeof(OBJECTDESCRIPTOR);
  332. hMem = GlobalAlloc(GHND|GMEM_SHARE, dwObjectDescSize +
  333. (dwFullUserTypeNameLen + dwSrcOfCopyLen) * sizeof(OLECHAR));
  334. if (!hMem)
  335. return NULL;
  336. lpOD = (LPOBJECTDESCRIPTOR)GlobalLock(hMem);
  337. // Set the FullUserTypeName offset and copy the string
  338. if (lpszFullUserTypeName)
  339. {
  340. lpOD->dwFullUserTypeName = dwObjectDescSize;
  341. lstrcpy((LPTSTR)((LPBYTE)lpOD+lpOD->dwFullUserTypeName), lpszFullUserTypeName);
  342. }
  343. else
  344. lpOD->dwFullUserTypeName = 0; // zero offset indicates that string is not present
  345. // Set the SrcOfCopy offset and copy the string
  346. if (lpszSrcOfCopy)
  347. {
  348. lpOD->dwSrcOfCopy = dwObjectDescSize + dwFullUserTypeNameLen * sizeof(OLECHAR);
  349. lstrcpy((LPTSTR)((LPBYTE)lpOD+lpOD->dwSrcOfCopy), lpszSrcOfCopy);
  350. }
  351. else
  352. lpOD->dwSrcOfCopy = 0; // zero offset indicates that string is not present
  353. // Initialize the rest of the OBJECTDESCRIPTOR
  354. lpOD->cbSize = dwObjectDescSize +
  355. (dwFullUserTypeNameLen + dwSrcOfCopyLen) * sizeof(OLECHAR);
  356. lpOD->clsid = clsid;
  357. lpOD->dwDrawAspect = dwDrawAspect;
  358. lpOD->sizel = sizel;
  359. lpOD->pointl = pointl;
  360. lpOD->dwStatus = dwStatus;
  361. GlobalUnlock(hMem);
  362. return hMem;
  363. }
  364. /*
  365. * OleStdFillObjectDescriptorFromData
  366. *
  367. * Purpose:
  368. * Fills and returns a OBJECTDESCRIPTOR structure. The source object will
  369. * offer CF_OBJECTDESCRIPTOR if it is an OLE2 object, CF_OWNERLINK if it
  370. * is an OLE1 object, or CF_FILENAME if it has been copied to the clipboard
  371. * by FileManager.
  372. *
  373. * Parameters:
  374. * lpDataObject LPDATAOBJECT Source object
  375. * lpmedium LPSTGMEDIUM Storage medium
  376. * lpcfFmt CLIPFORMAT FAR * Format offered by lpDataObject
  377. * (OUT parameter)
  378. *
  379. * Return Value:
  380. * HBGLOBAL Handle to OBJECTDESCRIPTOR structure.
  381. */
  382. STDAPI_(HGLOBAL) OleStdFillObjectDescriptorFromData(
  383. LPDATAOBJECT lpDataObject,
  384. LPSTGMEDIUM lpmedium,
  385. CLIPFORMAT FAR* lpcfFmt)
  386. {
  387. CLSID clsid;
  388. SIZEL sizelHim;
  389. POINTL pointl;
  390. LPTSTR lpsz, szFullUserTypeName, szSrcOfCopy, szClassName, szDocName, szItemName;
  391. int nClassName, nDocName, nItemName, nFullUserTypeName;
  392. LPTSTR szBuf = NULL;
  393. HGLOBAL hMem = NULL;
  394. HKEY hKey = NULL;
  395. DWORD dw = OLEUI_CCHKEYMAX_SIZE;
  396. HGLOBAL hObjDesc;
  397. HRESULT hrErr;
  398. // GetData CF_OBJECTDESCRIPTOR format from the object on the clipboard.
  399. // Only OLE 2 objects on the clipboard will offer CF_OBJECTDESCRIPTOR
  400. hMem = OleStdGetData(
  401. lpDataObject,
  402. (CLIPFORMAT) _g_cfObjectDescriptor,
  403. NULL,
  404. DVASPECT_CONTENT,
  405. lpmedium);
  406. if (hMem)
  407. {
  408. *lpcfFmt = (CLIPFORMAT)_g_cfObjectDescriptor;
  409. return hMem; // Don't drop to clean up at the end of this function
  410. }
  411. // If CF_OBJECTDESCRIPTOR is not available, i.e. if this is not an OLE2 object,
  412. // check if this is an OLE 1 object. OLE 1 objects will offer CF_OWNERLINK
  413. else
  414. {
  415. hMem = OleStdGetData(
  416. lpDataObject,
  417. (CLIPFORMAT) _g_cfOwnerLink,
  418. NULL,
  419. DVASPECT_CONTENT,
  420. lpmedium);
  421. if (hMem)
  422. {
  423. *lpcfFmt = (CLIPFORMAT)_g_cfOwnerLink;
  424. // CF_OWNERLINK contains null-terminated strings for class name, document name
  425. // and item name with two null terminating characters at the end
  426. szClassName = (LPTSTR)GlobalLock(hMem);
  427. nClassName = lstrlen(szClassName);
  428. szDocName = szClassName + nClassName + 1;
  429. nDocName = lstrlen(szDocName);
  430. szItemName = szDocName + nDocName + 1;
  431. nItemName = lstrlen(szItemName);
  432. // Find FullUserTypeName from Registration database using class name
  433. if (OpenClassesRootKey(NULL, &hKey) != ERROR_SUCCESS)
  434. goto error;
  435. // Allocate space for szFullUserTypeName & szSrcOfCopy. Maximum length of FullUserTypeName
  436. // is OLEUI_CCHKEYMAX_SIZE. SrcOfCopy is constructed by concatenating FullUserTypeName, Document
  437. // Name and ItemName separated by spaces.
  438. szBuf = (LPTSTR)OleStdMalloc(
  439. (DWORD)2*OLEUI_CCHKEYMAX_SIZE+
  440. (nDocName+nItemName+4)*sizeof(TCHAR));
  441. if (NULL == szBuf)
  442. goto error;
  443. szFullUserTypeName = szBuf;
  444. szSrcOfCopy = szFullUserTypeName+OLEUI_CCHKEYMAX_SIZE+1;
  445. // Get FullUserTypeName
  446. if (RegQueryValue(hKey, NULL, szFullUserTypeName, (LONG*)&dw) != ERROR_SUCCESS)
  447. goto error;
  448. // Build up SrcOfCopy string from FullUserTypeName, DocumentName & ItemName
  449. lpsz = szSrcOfCopy;
  450. lstrcpy(lpsz, szFullUserTypeName);
  451. nFullUserTypeName = lstrlen(szFullUserTypeName);
  452. lpsz[nFullUserTypeName]= ' ';
  453. lpsz += nFullUserTypeName+1;
  454. lstrcpy(lpsz, szDocName);
  455. lpsz[nDocName] = ' ';
  456. lpsz += nDocName+1;
  457. lstrcpy(lpsz, szItemName);
  458. sizelHim.cx = sizelHim.cy = 0;
  459. pointl.x = pointl.y = 0;
  460. CLSIDFromProgID(szClassName, &clsid);
  461. hObjDesc = OleStdGetObjectDescriptorData(
  462. clsid,
  463. DVASPECT_CONTENT,
  464. sizelHim,
  465. pointl,
  466. 0,
  467. szFullUserTypeName,
  468. szSrcOfCopy
  469. );
  470. if (!hObjDesc)
  471. goto error;
  472. }
  473. else
  474. {
  475. BOOL fUnicode = TRUE;
  476. hMem = OleStdGetData(
  477. lpDataObject,
  478. (CLIPFORMAT) _g_cfFileNameW,
  479. NULL,
  480. DVASPECT_CONTENT,
  481. lpmedium);
  482. if (!hMem)
  483. {
  484. hMem = OleStdGetData(
  485. lpDataObject,
  486. (CLIPFORMAT) _g_cfFileName,
  487. NULL,
  488. DVASPECT_CONTENT,
  489. lpmedium);
  490. fUnicode = FALSE;
  491. }
  492. if (hMem)
  493. {
  494. *lpcfFmt = fUnicode ? (CLIPFORMAT)_g_cfFileNameW : (CLIPFORMAT)_g_cfFileName;
  495. lpsz = (LPTSTR)GlobalLock(hMem);
  496. if (!fUnicode)
  497. {
  498. OLECHAR wsz[OLEUI_CCHKEYMAX];
  499. ATOW(wsz, (LPSTR)lpsz, OLEUI_CCHKEYMAX);
  500. hrErr = GetClassFile(wsz, &clsid);
  501. }
  502. else
  503. hrErr = GetClassFile((LPWSTR)lpsz, &clsid);
  504. /* OLE2NOTE: if the file does not have an OLE class
  505. ** associated, then use the OLE 1 Packager as the class of
  506. ** the object to be created. this is the behavior of
  507. ** OleCreateFromData API
  508. */
  509. if (hrErr != NOERROR)
  510. CLSIDFromProgID(OLESTR("Package"), &clsid);
  511. sizelHim.cx = sizelHim.cy = 0;
  512. pointl.x = pointl.y = 0;
  513. if (OleRegGetUserType(clsid, USERCLASSTYPE_FULL, &szBuf) != NOERROR)
  514. goto error;
  515. hObjDesc = OleStdGetObjectDescriptorData(
  516. clsid,
  517. DVASPECT_CONTENT,
  518. sizelHim,
  519. pointl,
  520. 0,
  521. szBuf,
  522. lpsz
  523. );
  524. if (!hObjDesc)
  525. goto error;
  526. }
  527. else
  528. goto error;
  529. }
  530. }
  531. // Check if object is CF_FILENAME
  532. // Clean up
  533. OleStdFree(szBuf);
  534. if (hMem)
  535. {
  536. GlobalUnlock(hMem);
  537. GlobalFree(hMem);
  538. }
  539. if (hKey)
  540. RegCloseKey(hKey);
  541. return hObjDesc;
  542. error:
  543. OleStdFree(szBuf);
  544. if (hMem)
  545. {
  546. GlobalUnlock(hMem);
  547. GlobalFree(hMem);
  548. }
  549. if (hKey)
  550. RegCloseKey(hKey);
  551. return NULL;
  552. }
  553. /* Call Release on the object that is NOT necessarily expected to go away.
  554. */
  555. STDAPI_(ULONG) OleStdRelease(LPUNKNOWN lpUnk)
  556. {
  557. ULONG cRef;
  558. cRef = lpUnk->Release();
  559. #ifdef _DEBUG
  560. {
  561. TCHAR szBuf[80];
  562. wsprintf(
  563. szBuf,
  564. TEXT("refcnt = %ld after object (0x%lx) release\n"),
  565. cRef,
  566. lpUnk
  567. );
  568. OleDbgOut4(szBuf);
  569. }
  570. #endif
  571. return cRef;
  572. }
  573. /*
  574. * OleStdMarkPasteEntryList
  575. *
  576. * Purpose:
  577. * Mark each entry in the PasteEntryList if its format is available from
  578. * the source IDataObject*. the dwScratchSpace field of each PasteEntry
  579. * is set to TRUE if available, else FALSE.
  580. *
  581. * Parameters:
  582. * LPOLEUIPASTEENTRY array of PasteEntry structures
  583. * int count of elements in PasteEntry array
  584. * LPDATAOBJECT source IDataObject* pointer
  585. *
  586. * Return Value:
  587. * none
  588. */
  589. STDAPI_(void) OleStdMarkPasteEntryList(
  590. LPDATAOBJECT lpSrcDataObj,
  591. LPOLEUIPASTEENTRY lpPriorityList,
  592. int cEntries)
  593. {
  594. LPENUMFORMATETC lpEnumFmtEtc = NULL;
  595. #define FORMATETC_MAX 20
  596. FORMATETC rgfmtetc[FORMATETC_MAX];
  597. int i;
  598. HRESULT hrErr;
  599. DWORD j, cFetched;
  600. // Clear all marks
  601. for (i = 0; i < cEntries; i++)
  602. {
  603. lpPriorityList[i].dwScratchSpace = FALSE;
  604. if (! lpPriorityList[i].fmtetc.cfFormat)
  605. {
  606. // caller wants this item always considered available
  607. // (by specifying a NULL format)
  608. lpPriorityList[i].dwScratchSpace = TRUE;
  609. }
  610. else if (lpPriorityList[i].fmtetc.cfFormat == _g_cfEmbeddedObject
  611. || lpPriorityList[i].fmtetc.cfFormat == _g_cfEmbedSource
  612. || lpPriorityList[i].fmtetc.cfFormat == _g_cfFileName)
  613. {
  614. // if there is an OLE object format, then handle it
  615. // specially by calling OleQueryCreateFromData. the caller
  616. // need only specify one object type format.
  617. OLEDBG_BEGIN2(TEXT("OleQueryCreateFromData called\r\n"))
  618. hrErr = OleQueryCreateFromData(lpSrcDataObj);
  619. OLEDBG_END2
  620. if(NOERROR == hrErr)
  621. lpPriorityList[i].dwScratchSpace = TRUE;
  622. }
  623. else if (lpPriorityList[i].fmtetc.cfFormat == _g_cfLinkSource)
  624. {
  625. // if there is OLE 2.0 LinkSource format, then handle it
  626. // specially by calling OleQueryLinkFromData.
  627. OLEDBG_BEGIN2(TEXT("OleQueryLinkFromData called\r\n"))
  628. hrErr = OleQueryLinkFromData(lpSrcDataObj);
  629. OLEDBG_END2
  630. if(NOERROR == hrErr) {
  631. lpPriorityList[i].dwScratchSpace = TRUE;
  632. }
  633. }
  634. }
  635. OLEDBG_BEGIN2(TEXT("IDataObject::EnumFormatEtc called\r\n"))
  636. hrErr = lpSrcDataObj->EnumFormatEtc(
  637. DATADIR_GET,
  638. (LPENUMFORMATETC FAR*)&lpEnumFmtEtc
  639. );
  640. OLEDBG_END2
  641. if (hrErr != NOERROR)
  642. return; // unable to get format enumerator
  643. // Enumerate the formats offered by the source
  644. // Loop over all formats offered by the source
  645. cFetched = 0;
  646. memset(rgfmtetc,0,sizeof(rgfmtetc));
  647. if (lpEnumFmtEtc->Next(
  648. FORMATETC_MAX, rgfmtetc, &cFetched) == NOERROR
  649. || (cFetched > 0 && cFetched <= FORMATETC_MAX) )
  650. {
  651. for (j = 0; j < cFetched; j++)
  652. {
  653. for (i = 0; i < cEntries; i++)
  654. {
  655. if (!lpPriorityList[i].dwScratchSpace &&
  656. IsCloseFormatEtc(&lpPriorityList[i].fmtetc, &rgfmtetc[j]))
  657. {
  658. lpPriorityList[i].dwScratchSpace = TRUE;
  659. }
  660. }
  661. }
  662. } // endif
  663. OleStdRelease((LPUNKNOWN)lpEnumFmtEtc);
  664. }
  665. // returns 1 for a close match
  666. // (all fields match exactly except the tymed which simply overlaps)
  667. // 0 for no match
  668. int IsCloseFormatEtc(FORMATETC FAR* pFetcLeft, FORMATETC FAR* pFetcRight)
  669. {
  670. if (pFetcLeft->cfFormat != pFetcRight->cfFormat)
  671. return 0;
  672. else if (!OleStdCompareTargetDevice (pFetcLeft->ptd, pFetcRight->ptd))
  673. return 0;
  674. if (pFetcLeft->dwAspect != pFetcRight->dwAspect)
  675. return 0;
  676. return((pFetcLeft->tymed | pFetcRight->tymed) != 0);
  677. }