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.

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