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.

678 lines
17 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1999
  6. //
  7. // File: idldata.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. #include "pch.h"
  11. #pragma hdrstop
  12. #include "fmtetc.h"
  13. #include "idldata.h"
  14. #include "shsemip.h"
  15. CLIPFORMAT CIDLData::m_rgcfGlobal[ICF_MAX] = { CF_HDROP, 0 };
  16. const LARGE_INTEGER CIDLData::m_LargeIntZero;
  17. //
  18. // For those who prefer a function (rather than a ctor) to create an object,
  19. // this static function will return a pointer to the IDataObject interface.
  20. // If the function fails, no object is created.
  21. //
  22. HRESULT
  23. CIDLData::CreateInstance(
  24. IDataObject **ppOut,
  25. LPCITEMIDLIST pidlFolder,
  26. UINT cidl,
  27. LPCITEMIDLIST *apidl,
  28. IShellFolder *psfOwner,
  29. IDataObject *pdtInner
  30. )
  31. {
  32. CIDLData *pidlData;
  33. HRESULT hr = CreateInstance(&pidlData, pidlFolder, cidl, apidl, psfOwner, pdtInner);
  34. if (SUCCEEDED(hr))
  35. {
  36. pidlData->AddRef();
  37. hr = pidlData->QueryInterface(IID_IDataObject, (void **)ppOut);
  38. pidlData->Release();
  39. }
  40. else
  41. {
  42. *ppOut = NULL;
  43. }
  44. return hr;
  45. }
  46. //
  47. // For those who prefer a function (rather than a ctor) to create an object,
  48. // this static function will return a pointer to the CIDLData object.
  49. // If the function fails, no object is created. Note that the returned object
  50. // has a ref count of 0. Therefore, it acts as a normal C++ object. If you
  51. // want it to participate as a COM object, QI for IDataObject or use the
  52. // IDataObject version of CreateInstance() above.
  53. //
  54. HRESULT
  55. CIDLData::CreateInstance(
  56. CIDLData **ppOut,
  57. LPCITEMIDLIST pidlFolder,
  58. UINT cidl,
  59. LPCITEMIDLIST *apidl,
  60. IShellFolder *psfOwner,
  61. IDataObject *pdtInner
  62. )
  63. {
  64. HRESULT hr = E_OUTOFMEMORY;
  65. CIDLData *pidlData = new CIDLData(pidlFolder, cidl, apidl, psfOwner, pdtInner);
  66. if (NULL != pidlData)
  67. {
  68. hr = pidlData->CtorResult();
  69. if (SUCCEEDED(hr))
  70. {
  71. *ppOut = pidlData;
  72. }
  73. else
  74. {
  75. delete pidlData;
  76. }
  77. }
  78. return hr;
  79. }
  80. CIDLData::CIDLData(
  81. LPCITEMIDLIST pidlFolder,
  82. UINT cidl,
  83. LPCITEMIDLIST *apidl,
  84. IShellFolder *psfOwner, // Optional. Default is NULL.
  85. IDataObject *pdtobjInner // Optional. Default is NULL.
  86. ) : m_cRef(0),
  87. m_hrCtor(NOERROR),
  88. m_psfOwner(NULL),
  89. m_dwOwnerData(0),
  90. m_pdtobjInner(pdtobjInner),
  91. m_bEnumFormatCalled(false)
  92. {
  93. //
  94. // Initialize the global clipboard formats.
  95. //
  96. InitializeClipboardFormats();
  97. ZeroMemory(m_rgMedium, sizeof(m_rgMedium));
  98. ZeroMemory(m_rgFmtEtc, sizeof(m_rgFmtEtc));
  99. if (NULL != m_pdtobjInner)
  100. m_pdtobjInner->AddRef();
  101. //
  102. // Empty array is valid input.
  103. //
  104. if (NULL != apidl)
  105. {
  106. HIDA hida = HIDA_Create(pidlFolder, cidl, apidl);
  107. if (NULL != hida)
  108. {
  109. m_hrCtor = DataObject_SetGlobal(static_cast<IDataObject *>(this), g_cfHIDA, hida);
  110. if (SUCCEEDED(m_hrCtor))
  111. {
  112. if (NULL != psfOwner)
  113. {
  114. m_psfOwner = psfOwner;
  115. m_psfOwner->AddRef();
  116. }
  117. }
  118. }
  119. else
  120. {
  121. m_hrCtor = E_OUTOFMEMORY;
  122. }
  123. }
  124. }
  125. CIDLData::~CIDLData(
  126. void
  127. )
  128. {
  129. for (int i = 0; i < ARRAYSIZE(m_rgMedium); i++)
  130. {
  131. if (m_rgMedium[i].hGlobal)
  132. ReleaseStgMedium(&(m_rgMedium[i]));
  133. }
  134. if (NULL != m_psfOwner)
  135. m_psfOwner->Release();
  136. if (NULL != m_pdtobjInner)
  137. m_pdtobjInner->Release();
  138. }
  139. STDMETHODIMP
  140. CIDLData::QueryInterface(
  141. REFIID riid,
  142. void **ppv
  143. )
  144. {
  145. static const QITAB qit[] = {
  146. QITABENT(CIDLData, IDataObject),
  147. { 0 },
  148. };
  149. return QISearch(this, qit, riid, ppv);
  150. }
  151. STDMETHODIMP_(ULONG)
  152. CIDLData::AddRef(
  153. void
  154. )
  155. {
  156. return InterlockedIncrement(&m_cRef);
  157. }
  158. STDMETHODIMP_(ULONG)
  159. CIDLData::Release(
  160. void
  161. )
  162. {
  163. ASSERT( 0 != m_cRef );
  164. ULONG cRef = InterlockedDecrement(&m_cRef);
  165. if ( 0 == cRef )
  166. {
  167. delete this;
  168. }
  169. return cRef;
  170. }
  171. HRESULT
  172. CIDLData::GetData(
  173. FORMATETC *pFmtEtc,
  174. STGMEDIUM *pMedium
  175. )
  176. {
  177. HRESULT hr = E_INVALIDARG;
  178. pMedium->hGlobal = NULL;
  179. pMedium->pUnkForRelease = NULL;
  180. for (int i = 0; i < ARRAYSIZE(m_rgFmtEtc); i++)
  181. {
  182. if ((m_rgFmtEtc[i].cfFormat == pFmtEtc->cfFormat) &&
  183. (m_rgFmtEtc[i].tymed & pFmtEtc->tymed) &&
  184. (m_rgFmtEtc[i].dwAspect == pFmtEtc->dwAspect))
  185. {
  186. *pMedium = m_rgMedium[i];
  187. if (NULL != pMedium->hGlobal)
  188. {
  189. //
  190. // Indicate that the caller should not release hmem.
  191. //
  192. if (TYMED_HGLOBAL == pMedium->tymed)
  193. {
  194. InterlockedIncrement(&m_cRef);
  195. pMedium->pUnkForRelease = static_cast<IUnknown *>(this);
  196. return S_OK;
  197. }
  198. //
  199. // If the type is stream then clone the stream.
  200. //
  201. if (TYMED_ISTREAM == pMedium->tymed)
  202. {
  203. hr = CreateStreamOnHGlobal(NULL, TRUE, &(pMedium->pstm));
  204. if (SUCCEEDED(hr))
  205. {
  206. STGMEDIUM& medium = m_rgMedium[i];
  207. STATSTG stat;
  208. //
  209. // Get the Current Stream size
  210. //
  211. hr = medium.pstm->Stat(&stat, STATFLAG_NONAME);
  212. if (SUCCEEDED(hr))
  213. {
  214. //
  215. // Seek the source stream to the beginning.
  216. //
  217. medium.pstm->Seek(m_LargeIntZero, STREAM_SEEK_SET, NULL);
  218. //
  219. // Copy the entire source into the destination.
  220. // Since the destination stream is created using CreateStreamOnHGlobal,
  221. // it seek pointer is at the beginning.
  222. //
  223. hr = medium.pstm->CopyTo(pMedium->pstm, stat.cbSize, NULL, NULL);
  224. //
  225. // Before returning Set the destination seek pointer back at the beginning.
  226. //
  227. pMedium->pstm->Seek(m_LargeIntZero, STREAM_SEEK_SET, NULL);
  228. return hr;
  229. }
  230. else
  231. {
  232. hr = E_OUTOFMEMORY;
  233. }
  234. }
  235. }
  236. }
  237. }
  238. }
  239. if (E_INVALIDARG == hr && NULL != m_pdtobjInner)
  240. {
  241. hr = m_pdtobjInner->GetData(pFmtEtc, pMedium);
  242. }
  243. return hr;
  244. }
  245. STDMETHODIMP
  246. CIDLData::GetDataHere(
  247. FORMATETC *pFmtEtc,
  248. STGMEDIUM *pMedium
  249. )
  250. {
  251. HRESULT hr = E_NOTIMPL;
  252. if (NULL != m_pdtobjInner)
  253. {
  254. hr = m_pdtobjInner->GetDataHere(pFmtEtc, pMedium);
  255. }
  256. return hr;
  257. }
  258. HRESULT
  259. CIDLData::QueryGetData(
  260. FORMATETC *pFmtEtc
  261. )
  262. {
  263. HRESULT hr = S_FALSE;
  264. for (int i = 0; i < ARRAYSIZE(m_rgFmtEtc); i++)
  265. {
  266. if ((m_rgFmtEtc[i].cfFormat == pFmtEtc->cfFormat) &&
  267. (m_rgFmtEtc[i].tymed & pFmtEtc->tymed) &&
  268. (m_rgFmtEtc[i].dwAspect == pFmtEtc->dwAspect))
  269. {
  270. return S_OK;
  271. }
  272. }
  273. if (NULL != m_pdtobjInner)
  274. {
  275. hr = m_pdtobjInner->QueryGetData(pFmtEtc);
  276. }
  277. return hr;
  278. }
  279. STDMETHODIMP
  280. CIDLData::GetCanonicalFormatEtc(
  281. FORMATETC *pFmtEtcIn,
  282. FORMATETC *pFmtEtcOut
  283. )
  284. {
  285. //
  286. // This is the simplest implemtation. It means we always return
  287. // the data in the format requested.
  288. //
  289. return DATA_S_SAMEFORMATETC;
  290. }
  291. STDMETHODIMP
  292. CIDLData::SetData(
  293. FORMATETC *pFmtEtc,
  294. STGMEDIUM *pMedium,
  295. BOOL fRelease
  296. )
  297. {
  298. HRESULT hr;
  299. TraceAssert(pFmtEtc->tymed == pMedium->tymed);
  300. if (fRelease)
  301. {
  302. int i;
  303. //
  304. // First add it if that format is already present
  305. // on a NULL medium (render on demand)
  306. //
  307. for (i = 0; i < ARRAYSIZE(m_rgFmtEtc); i++)
  308. {
  309. if ((m_rgFmtEtc[i].cfFormat == pFmtEtc->cfFormat) &&
  310. (m_rgFmtEtc[i].tymed == pFmtEtc->tymed) &&
  311. (m_rgFmtEtc[i].dwAspect == pFmtEtc->dwAspect))
  312. {
  313. //
  314. // We are simply adding a format, ignore.
  315. //
  316. if (NULL == pMedium->hGlobal)
  317. {
  318. return S_OK;
  319. }
  320. //
  321. // If we are set twice on the same object
  322. //
  323. if (NULL != m_rgMedium[i].hGlobal)
  324. ReleaseStgMedium(&m_rgMedium[i]);
  325. m_rgMedium[i] = *pMedium;
  326. return S_OK;
  327. }
  328. }
  329. //
  330. // now look for a free slot
  331. //
  332. for (i = 0; i < ARRAYSIZE(m_rgFmtEtc); i++)
  333. {
  334. if (0 == m_rgFmtEtc[i].cfFormat)
  335. {
  336. //
  337. // found a free slot
  338. //
  339. m_rgMedium[i] = *pMedium;
  340. m_rgFmtEtc[i] = *pFmtEtc;
  341. return S_OK;
  342. }
  343. }
  344. //
  345. // fixed size table
  346. //
  347. hr = E_OUTOFMEMORY;
  348. }
  349. else
  350. hr = E_INVALIDARG;
  351. return hr;
  352. }
  353. STDMETHODIMP
  354. CIDLData::EnumFormatEtc(
  355. DWORD dwDirection,
  356. LPENUMFORMATETC *ppenumFormatEtc
  357. )
  358. {
  359. HRESULT hr = NOERROR;
  360. //
  361. // If this is the first time, build the format list by calling
  362. // QueryGetData with each clipboard format.
  363. //
  364. if (!m_bEnumFormatCalled)
  365. {
  366. FORMATETC fmte = { 0, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
  367. STGMEDIUM medium = { TYMED_HGLOBAL, NULL, NULL };
  368. for (int i = 0; i < ARRAYSIZE(m_rgcfGlobal); i++)
  369. {
  370. fmte.cfFormat = m_rgcfGlobal[i];
  371. if (S_OK == QueryGetData(&fmte))
  372. {
  373. SetData(&fmte, &medium, TRUE);
  374. }
  375. }
  376. m_bEnumFormatCalled = true;
  377. }
  378. //
  379. // Get the number of formatetc
  380. //
  381. UINT cfmt;
  382. for (cfmt = 0; cfmt < ARRAYSIZE(m_rgFmtEtc); cfmt++)
  383. {
  384. if (0 == m_rgFmtEtc[cfmt].cfFormat)
  385. break;
  386. }
  387. /*
  388. return SHCreateStdEnumFmtEtcEx(cfmt, m_rgFmtEtc, m_pdtobjInner, ppenumFormatEtc);
  389. */
  390. CEnumFormatEtc *pEnumFmtEtc = new CEnumFormatEtc(cfmt, m_rgFmtEtc);
  391. if (NULL != pEnumFmtEtc)
  392. {
  393. pEnumFmtEtc->AddRef();
  394. //
  395. // Ask derived classes to add their formats.
  396. //
  397. hr = ProvideFormats(pEnumFmtEtc);
  398. if (SUCCEEDED(hr))
  399. {
  400. hr = pEnumFmtEtc->QueryInterface(IID_IEnumFORMATETC, (void **)ppenumFormatEtc);
  401. }
  402. pEnumFmtEtc->Release();
  403. }
  404. else
  405. hr = E_OUTOFMEMORY;
  406. return hr;
  407. }
  408. HRESULT
  409. CIDLData::ProvideFormats(
  410. CEnumFormatEtc *pEnumFmtEtc
  411. )
  412. {
  413. //
  414. // Base class default does nothing. Our formats are added to the enumerator
  415. // in EnumFormatEtc().
  416. //
  417. return NOERROR;
  418. }
  419. STDMETHODIMP
  420. CIDLData::DAdvise(
  421. FORMATETC *pFmtEtc,
  422. DWORD advf,
  423. LPADVISESINK pAdvSink,
  424. DWORD *pdwConnection
  425. )
  426. {
  427. return OLE_E_ADVISENOTSUPPORTED;
  428. }
  429. STDMETHODIMP
  430. CIDLData::DUnadvise(
  431. DWORD dwConnection
  432. )
  433. {
  434. return OLE_E_ADVISENOTSUPPORTED;
  435. }
  436. STDMETHODIMP
  437. CIDLData::EnumDAdvise(
  438. LPENUMSTATDATA *ppenumAdvise
  439. )
  440. {
  441. return OLE_E_ADVISENOTSUPPORTED;
  442. }
  443. IShellFolder *
  444. CIDLData::GetFolder(
  445. void
  446. ) const
  447. {
  448. return m_psfOwner;
  449. }
  450. //
  451. // Clone DataObject only for MOVE/COPY operation
  452. //
  453. HRESULT
  454. CIDLData::Clone(
  455. UINT *acf,
  456. UINT ccf,
  457. IDataObject **ppdtobjOut
  458. )
  459. {
  460. HRESULT hr = NOERROR;
  461. CIDLData *pidlData = new CIDLData(NULL, 0, NULL);
  462. if (NULL == pidlData)
  463. {
  464. hr = E_OUTOFMEMORY;
  465. }
  466. else
  467. {
  468. FORMATETC fmte = { 0, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
  469. for (UINT i = 0; i < ccf; i++)
  470. {
  471. HRESULT hrT;
  472. STGMEDIUM medium;
  473. fmte.cfFormat = (CLIPFORMAT) acf[i];
  474. hrT = GetData(&fmte, &medium);
  475. if (SUCCEEDED(hrT))
  476. {
  477. HGLOBAL hmem;
  478. if (NULL != medium.pUnkForRelease)
  479. {
  480. //
  481. // We need to clone the hGlobal.
  482. //
  483. SIZE_T cbMem = GlobalSize(medium.hGlobal);
  484. hmem = GlobalAlloc(GPTR, cbMem);
  485. if (NULL != hmem)
  486. {
  487. hmemcpy((LPVOID)hmem, GlobalLock(medium.hGlobal), cbMem);
  488. GlobalUnlock(medium.hGlobal);
  489. }
  490. ReleaseStgMedium(&medium);
  491. }
  492. else
  493. {
  494. //
  495. // We don't need to clone the hGlobal.
  496. //
  497. hmem = medium.hGlobal;
  498. }
  499. if (hmem)
  500. DataObject_SetGlobal(*ppdtobjOut, (CLIPFORMAT)acf[i], hmem);
  501. }
  502. }
  503. }
  504. return hr;
  505. }
  506. HRESULT
  507. CIDLData::CloneForMoveCopy(
  508. IDataObject **ppdtobjOut
  509. )
  510. {
  511. return E_NOTIMPL;
  512. /*
  513. UINT acf[] = { g_cfHIDA, g_cfOFFSETS, CF_HDROP, g_cfFileNameMapW, g_cfFileNameMap };
  514. return Clone(acf, ARRAYSIZE(acf), ppdtobjOut);
  515. */
  516. }
  517. #define RCF(x) (CLIPFORMAT) RegisterClipboardFormat(x)
  518. void
  519. CIDLData::InitializeClipboardFormats(
  520. void
  521. )
  522. {
  523. if (g_cfHIDA == 0)
  524. {
  525. g_cfHIDA = RCF(CFSTR_SHELLIDLIST);
  526. g_cfOFFSETS = RCF(CFSTR_SHELLIDLISTOFFSET);
  527. g_cfNetResource = RCF(CFSTR_NETRESOURCES);
  528. g_cfFileContents = RCF(CFSTR_FILECONTENTS); // "FileContents"
  529. g_cfFileGroupDescriptorA = RCF(CFSTR_FILEDESCRIPTORA); // "FileGroupDescriptor"
  530. g_cfFileGroupDescriptorW = RCF(CFSTR_FILEDESCRIPTORW); // "FileGroupDescriptor"
  531. g_cfPrivateShellData = RCF(CFSTR_SHELLIDLISTP);
  532. g_cfFileName = RCF(CFSTR_FILENAMEA); // "FileName"
  533. g_cfFileNameW = RCF(CFSTR_FILENAMEW); // "FileNameW"
  534. g_cfFileNameMap = RCF(CFSTR_FILENAMEMAP); // "FileNameMap"
  535. g_cfFileNameMapW = RCF(CFSTR_FILENAMEMAPW); // "FileNameMapW"
  536. g_cfPrinterFriendlyName = RCF(CFSTR_PRINTERGROUP);
  537. g_cfHTML = RCF(TEXT("HTML Format"));
  538. g_cfPreferredDropEffect = RCF(CFSTR_PREFERREDDROPEFFECT); // "Preferred DropEffect"
  539. g_cfPerformedDropEffect = RCF(CFSTR_PERFORMEDDROPEFFECT); // "Performed DropEffect"
  540. g_cfLogicalPerformedDropEffect = RCF(CFSTR_LOGICALPERFORMEDDROPEFFECT);
  541. g_cfShellURL = RCF(CFSTR_SHELLURL); // "Uniform Resource Locator"
  542. g_cfInDragLoop = RCF(CFSTR_INDRAGLOOP); // "InShellDragLoop"
  543. g_cfDragContext = RCF(CFSTR_DRAGCONTEXT); // "DragContext"
  544. g_cfTargetCLSID = RCF(TEXT("TargetCLSID")); // who the drag drop went to
  545. }
  546. }
  547. //
  548. // This is normally a private shell function.
  549. //
  550. #define HIDA_GetPIDLItem(pida, i) (LPCITEMIDLIST)(((LPBYTE)pida)+(pida)->aoffset[i+1])
  551. CIDLData::HIDA
  552. CIDLData::HIDA_Create(
  553. LPCITEMIDLIST pidlFolder,
  554. UINT cidl,
  555. LPCITEMIDLIST *apidl
  556. )
  557. {
  558. HIDA hida;
  559. #if _MSC_VER == 1100
  560. // Workaround code generate bug in VC5 X86 compiler (12/30 version).
  561. volatile
  562. #endif
  563. UINT i;
  564. UINT offset = sizeof(CIDA) + sizeof(UINT)*cidl;
  565. UINT cbTotal = offset + ILGetSize(pidlFolder);
  566. for (i=0; i<cidl ; i++) {
  567. cbTotal += ILGetSize(apidl[i]);
  568. }
  569. hida = GlobalAlloc(GPTR, cbTotal); // This MUST be GlobalAlloc!!!
  570. if (hida)
  571. {
  572. LPIDA pida = (LPIDA)hida; // no need to lock
  573. LPCITEMIDLIST pidlNext;
  574. pida->cidl = cidl;
  575. for (i=0, pidlNext=pidlFolder; ; pidlNext=apidl[i++])
  576. {
  577. UINT cbSize = ILGetSize(pidlNext);
  578. pida->aoffset[i] = offset;
  579. MoveMemory(((LPBYTE)pida)+offset, pidlNext, cbSize);
  580. offset += cbSize;
  581. TraceAssert(ILGetSize(HIDA_GetPIDLItem(pida,i-1)) == cbSize);
  582. if (i==cidl)
  583. break;
  584. }
  585. TraceAssert(offset == cbTotal);
  586. }
  587. return hida;
  588. }