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.

653 lines
16 KiB

  1. //____________________________________________________________________________
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1995 - 1996.
  5. //
  6. // File: dataobj.cxx
  7. //
  8. // Contents:
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 1/17/1996 RaviR Created
  15. //
  16. //____________________________________________________________________________
  17. #include "..\pch\headers.hxx"
  18. #pragma hdrstop
  19. #include "dbg.h"
  20. #include "macros.h"
  21. #include "jobidl.hxx"
  22. extern "C" UINT g_cfJobIDList;
  23. extern "C" UINT g_cfShellIDList;
  24. extern "C" UINT g_cfPreferredDropEffect;
  25. //____________________________________________________________________________
  26. //
  27. // Class: CObjFormats
  28. //
  29. // Purpose: Impements IEnumFORMATETC for job objects.
  30. //____________________________________________________________________________
  31. class CObjFormats : public IEnumFORMATETC
  32. {
  33. friend HRESULT JFGetObjFormats(UINT cfmt, FORMATETC *afmt, LPVOID *ppvObj);
  34. public:
  35. ~CObjFormats() { if (m_aFmt) delete [] m_aFmt; }
  36. // IUnknown methods
  37. DECLARE_STANDARD_IUNKNOWN;
  38. // IEnumFORMATETC methods
  39. STDMETHODIMP Next(ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed);
  40. STDMETHODIMP Skip(ULONG celt);
  41. STDMETHODIMP Reset();
  42. STDMETHODIMP Clone(IEnumFORMATETC ** ppenum);
  43. private:
  44. CObjFormats(UINT cfmt, FORMATETC * afmt)
  45. : m_iFmt(0), m_cFmt(cfmt), m_aFmt(afmt), m_ulRefs(1) {}
  46. UINT m_iFmt;
  47. UINT m_cFmt;
  48. FORMATETC * m_aFmt;
  49. };
  50. //____________________________________________________________________________
  51. //
  52. // Members: IUnknown methods
  53. //____________________________________________________________________________
  54. IMPLEMENT_STANDARD_IUNKNOWN(CObjFormats);
  55. STDMETHODIMP
  56. CObjFormats::QueryInterface(
  57. REFIID riid,
  58. LPVOID FAR* ppvObj)
  59. {
  60. if (IsEqualIID(IID_IUnknown, riid) ||
  61. IsEqualIID(IID_IEnumFORMATETC, riid))
  62. {
  63. *ppvObj = (IUnknown*)(IEnumFORMATETC*) this;
  64. this->AddRef();
  65. return S_OK;
  66. }
  67. *ppvObj = NULL;
  68. return E_NOINTERFACE;
  69. }
  70. //____________________________________________________________________________
  71. //
  72. // Members: IEnumFORMATETC methods
  73. //____________________________________________________________________________
  74. STDMETHODIMP
  75. CObjFormats::Next(
  76. ULONG celt,
  77. FORMATETC *rgelt,
  78. ULONG *pceltFethed)
  79. {
  80. UINT cfetch = 0;
  81. HRESULT hr = S_FALSE;
  82. if (m_iFmt < m_cFmt)
  83. {
  84. cfetch = m_cFmt - m_iFmt;
  85. if (cfetch >= celt)
  86. {
  87. cfetch = celt;
  88. hr = S_OK;
  89. }
  90. CopyMemory(rgelt, &m_aFmt[m_iFmt], cfetch * sizeof(FORMATETC));
  91. m_iFmt += cfetch;
  92. }
  93. if (pceltFethed)
  94. {
  95. *pceltFethed = cfetch;
  96. }
  97. return hr;
  98. }
  99. STDMETHODIMP
  100. CObjFormats::Skip(
  101. ULONG celt)
  102. {
  103. m_iFmt += celt;
  104. if (m_iFmt > m_cFmt)
  105. {
  106. m_iFmt = m_cFmt;
  107. return S_FALSE;
  108. }
  109. return S_OK;
  110. }
  111. STDMETHODIMP
  112. CObjFormats::Reset()
  113. {
  114. m_iFmt = 0;
  115. return S_OK;
  116. }
  117. STDMETHODIMP
  118. CObjFormats::Clone(
  119. IEnumFORMATETC ** ppenum)
  120. {
  121. return E_NOTIMPL;
  122. }
  123. //____________________________________________________________________________
  124. //
  125. // Function: Function to obtain the IEnumFORMATETC interface for jobs.
  126. //____________________________________________________________________________
  127. HRESULT
  128. JFGetObjFormats(
  129. UINT cfmt,
  130. FORMATETC * afmt,
  131. LPVOID * ppvObj)
  132. {
  133. TRACE_FUNCTION(JFGetObjFormats);
  134. FORMATETC * pFmt = new FORMATETC[cfmt];
  135. if (pFmt == NULL)
  136. {
  137. CHECK_HRESULT(E_OUTOFMEMORY);
  138. return E_OUTOFMEMORY;
  139. }
  140. CopyMemory(pFmt, afmt, cfmt * sizeof(FORMATETC));
  141. CObjFormats * pObjFormats = new CObjFormats(cfmt, pFmt);
  142. if (pObjFormats == NULL)
  143. {
  144. delete [] pFmt;
  145. CHECK_HRESULT(E_OUTOFMEMORY);
  146. return E_OUTOFMEMORY;
  147. }
  148. HRESULT hr = pObjFormats->QueryInterface(IID_IEnumFORMATETC, ppvObj);
  149. pObjFormats->Release();
  150. DEBUG_OUT((DEB_TRACE, "RETURNING CObjFormats<%x, %d>\n",
  151. pObjFormats, pObjFormats->m_ulRefs));
  152. return hr;
  153. }
  154. //____________________________________________________________________________
  155. //____________________________________________________________________________
  156. //________________ _______________________________________
  157. //________________ class CJobObject _______________________________________
  158. //________________ _______________________________________
  159. //____________________________________________________________________________
  160. //____________________________________________________________________________
  161. class CJobObject : public IDataObject
  162. {
  163. public:
  164. CJobObject(
  165. LPCTSTR pszFolderPath,
  166. LPITEMIDLIST pidlFolder,
  167. UINT cidl,
  168. LPITEMIDLIST *apidl,
  169. BOOL fCut);
  170. ~CJobObject()
  171. {
  172. ILA_Free(m_cidl, m_apidl);
  173. ILFree(m_pidlFolder);
  174. DEBUG_ASSERT(m_ulRefs == 0);
  175. }
  176. // Iunknown methods
  177. DECLARE_STANDARD_IUNKNOWN;
  178. // IDataObject
  179. STDMETHODIMP GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium);
  180. STDMETHODIMP GetDataHere(FORMATETC *pformatetc, STGMEDIUM *pmedium);
  181. STDMETHODIMP QueryGetData(FORMATETC *pformatetc);
  182. STDMETHODIMP GetCanonicalFormatEtc(FORMATETC *pformatectIn,
  183. FORMATETC *pformatetcOut);
  184. STDMETHODIMP SetData(FORMATETC *pformatetc, STGMEDIUM *pmedium,
  185. BOOL fRelease);
  186. STDMETHODIMP EnumFormatEtc(DWORD dwDirection,
  187. IEnumFORMATETC **ppenumFormatEtc);
  188. STDMETHODIMP DAdvise(FORMATETC *pformatetc, DWORD advf,
  189. IAdviseSink *pAdvSink, DWORD *pdwConnection);
  190. STDMETHODIMP DUnadvise(DWORD dwConnection);
  191. STDMETHODIMP EnumDAdvise(IEnumSTATDATA **ppenumAdvise);
  192. private:
  193. LPCTSTR m_pszFolderPath;
  194. LPITEMIDLIST m_pidlFolder;
  195. UINT m_cidl;
  196. LPITEMIDLIST * m_apidl;
  197. BOOL m_fCut; // this is for a cut operation
  198. };
  199. inline
  200. CJobObject::CJobObject(
  201. LPCTSTR pszFolderPath,
  202. LPITEMIDLIST pidlFolder,
  203. UINT cidl,
  204. LPITEMIDLIST *apidl,
  205. BOOL fCut):
  206. m_cidl(cidl),
  207. m_pszFolderPath(pszFolderPath),
  208. m_pidlFolder(pidlFolder),
  209. m_apidl(apidl),
  210. m_ulRefs(1),
  211. m_fCut(fCut)
  212. {
  213. }
  214. //____________________________________________________________________________
  215. //
  216. // Members: IUnknown methods
  217. //____________________________________________________________________________
  218. IMPLEMENT_STANDARD_IUNKNOWN(CJobObject);
  219. STDMETHODIMP
  220. CJobObject::QueryInterface(
  221. REFIID riid,
  222. LPVOID FAR* ppvObj)
  223. {
  224. if (IsEqualIID(IID_IUnknown, riid) ||
  225. IsEqualIID(IID_IDataObject, riid))
  226. {
  227. *ppvObj = (IUnknown*)((IDataObject*)this);
  228. this->AddRef();
  229. return S_OK;
  230. }
  231. *ppvObj = NULL;
  232. return E_NOINTERFACE;
  233. }
  234. //____________________________________________________________________________
  235. //
  236. // Function: DbgPrintFmt
  237. //
  238. // Synopsis: Function to print out the format name.
  239. //____________________________________________________________________________
  240. #if DBG==1
  241. void
  242. DbgPrintFmt(
  243. UINT format)
  244. {
  245. #undef DEB_USEREX
  246. #define DEB_USEREX DEB_USER15
  247. TCHAR szFmtName[550];
  248. int cchFmtName = 550;
  249. if (format == g_cfJobIDList)
  250. {
  251. DEBUG_OUT((DEB_USEREX, "\t\t<Format=Job IDList Array>\n"));
  252. return;
  253. }
  254. else if (format == g_cfPreferredDropEffect)
  255. {
  256. DEBUG_OUT((DEB_USEREX, "\t\t<Format=Preferred DropEffect>\n"));
  257. return;
  258. }
  259. int iRet = GetClipboardFormatName(format, szFmtName, cchFmtName);
  260. if (iRet == 0)
  261. if (GetLastError() == 0)
  262. DEBUG_OUT((DEB_USEREX, "\t\t<Predefined format=%d>\n", format));
  263. else
  264. DEBUG_OUT((DEB_USEREX, "\t\t<Unknown Format=%d>\n", format));
  265. else
  266. DEBUG_OUT((DEB_USEREX, "\t\t<Format=%ws>\n", szFmtName));
  267. }
  268. #define DBG_PRINT_FMT(fmt) DbgPrintFmt(fmt)
  269. #else
  270. #define DBG_PRINT_FMT(fmt)
  271. #endif
  272. //____________________________________________________________________________
  273. //
  274. // Member: CJobObject::IDataObject::GetData
  275. //
  276. // History: 1/31/1996 RaviR Created
  277. //____________________________________________________________________________
  278. STDMETHODIMP
  279. CJobObject::GetData(
  280. FORMATETC *pfmt,
  281. STGMEDIUM *pmedium)
  282. {
  283. TRACE(CJobObject, GetData);
  284. DBG_PRINT_FMT(pfmt->cfFormat);
  285. Win4Assert(g_cfJobIDList != 0);
  286. if (pfmt->tymed & TYMED_HGLOBAL)
  287. {
  288. if (pfmt->cfFormat == CF_HDROP)
  289. {
  290. pmedium->hGlobal = HDROPFromJobIDList(m_pszFolderPath,
  291. m_cidl, (PJOBID *)m_apidl);
  292. }
  293. else if (pfmt->cfFormat == g_cfShellIDList)
  294. {
  295. pmedium->hGlobal = CreateIDListArray(m_pidlFolder,
  296. m_cidl,
  297. (PJOBID *)m_apidl);
  298. }
  299. else if (pfmt->cfFormat == g_cfJobIDList)
  300. {
  301. // Note Ole32's GetHGlobalFromILockBytes uses this
  302. pmedium->hGlobal = HJOBIDA_Create(m_cidl, (PJOBID *)m_apidl);
  303. }
  304. else if (pfmt->cfFormat == g_cfPreferredDropEffect)
  305. {
  306. DWORD *pdw = (DWORD *)GlobalAlloc(GPTR, sizeof(DWORD));
  307. if (pdw)
  308. {
  309. *pdw = m_fCut ? DROPEFFECT_MOVE : DROPEFFECT_COPY;
  310. pmedium->hGlobal = (HGLOBAL)pdw;
  311. }
  312. }
  313. else
  314. {
  315. pmedium->tymed = TYMED_NULL;
  316. pmedium->hGlobal = NULL;
  317. pmedium->pUnkForRelease = NULL;
  318. return DATA_E_FORMATETC;
  319. }
  320. if (pmedium->hGlobal != NULL)
  321. {
  322. pmedium->tymed = TYMED_HGLOBAL;
  323. pmedium->pUnkForRelease = NULL;
  324. return S_OK;
  325. }
  326. else
  327. {
  328. return E_OUTOFMEMORY;
  329. }
  330. }
  331. return DV_E_TYMED;
  332. }
  333. //____________________________________________________________________________
  334. //
  335. // Member: CJobObject::IDataObject::GetDataHere
  336. //____________________________________________________________________________
  337. STDMETHODIMP
  338. CJobObject::GetDataHere(
  339. FORMATETC *pfmt,
  340. STGMEDIUM *pmedium)
  341. {
  342. TRACE(CJobObject, GetDataHere);
  343. DBG_PRINT_FMT(pfmt->cfFormat);
  344. return E_NOTIMPL;
  345. }
  346. //____________________________________________________________________________
  347. //
  348. // Member: CJobObject::IDataObject::QueryGetData
  349. //
  350. // History: 1/31/1996 RaviR Created
  351. //____________________________________________________________________________
  352. STDMETHODIMP
  353. CJobObject::QueryGetData(
  354. FORMATETC *pfmt)
  355. {
  356. TRACE(CJobObject, QueryGetData);
  357. DBG_PRINT_FMT(pfmt->cfFormat);
  358. //
  359. // Check the aspects we support.
  360. //
  361. if (!(DVASPECT_CONTENT & pfmt->dwAspect))
  362. {
  363. return DATA_E_FORMATETC;
  364. }
  365. Win4Assert(g_cfJobIDList != 0);
  366. if (pfmt->cfFormat == CF_HDROP ||
  367. pfmt->cfFormat == g_cfJobIDList ||
  368. pfmt->cfFormat == g_cfShellIDList ||
  369. pfmt->cfFormat == g_cfPreferredDropEffect)
  370. {
  371. return S_OK;
  372. }
  373. return S_FALSE;
  374. }
  375. //____________________________________________________________________________
  376. //
  377. // Member: CJobObject::IDataObject::GetCanonicalFormatEtc
  378. //____________________________________________________________________________
  379. STDMETHODIMP
  380. CJobObject::GetCanonicalFormatEtc(
  381. FORMATETC *pfmtIn,
  382. FORMATETC *pfmtOut)
  383. {
  384. TRACE(CJobObject, GetCanonicalFormatEtc);
  385. *pfmtOut = *pfmtIn;
  386. pfmtOut->ptd = NULL;
  387. return DATA_S_SAMEFORMATETC;
  388. }
  389. //____________________________________________________________________________
  390. //
  391. // Member: CJobObject::IDataObject::SetData
  392. //____________________________________________________________________________
  393. STDMETHODIMP
  394. CJobObject::SetData(
  395. FORMATETC *pfmt,
  396. STGMEDIUM *pmedium,
  397. BOOL fRelease)
  398. {
  399. TRACE(CJobObject, SetData);
  400. DBG_PRINT_FMT(pfmt->cfFormat);
  401. return E_NOTIMPL;
  402. }
  403. //____________________________________________________________________________
  404. //
  405. // Member: CJobObject::IDataObject::EnumFormatEtc
  406. //
  407. // History: 1/31/1996 RaviR Created
  408. //____________________________________________________________________________
  409. STDMETHODIMP
  410. CJobObject::EnumFormatEtc(
  411. DWORD dwDirection,
  412. IEnumFORMATETC **ppenumFormatEtc)
  413. {
  414. TRACE(CJobObject, EnumFormatEtc);
  415. if (dwDirection == DATADIR_SET)
  416. {
  417. return E_FAIL;
  418. }
  419. FORMATETC fmte[] = {
  420. {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL},
  421. {(CLIPFORMAT)g_cfJobIDList, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL},
  422. {(CLIPFORMAT)g_cfShellIDList, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL},
  423. {(CLIPFORMAT)g_cfPreferredDropEffect, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL},
  424. };
  425. HRESULT hr = JFGetObjFormats(ARRAYLEN(fmte), fmte, (void**)ppenumFormatEtc);
  426. return hr;
  427. }
  428. //____________________________________________________________________________
  429. //
  430. // Member: CJobObject::IDataObject::DAdvise
  431. //____________________________________________________________________________
  432. STDMETHODIMP
  433. CJobObject::DAdvise(
  434. FORMATETC *pformatetc,
  435. DWORD advf,
  436. IAdviseSink *pAdvSink,
  437. DWORD *pdwConnection)
  438. {
  439. TRACE(CJobObject, DAdvise);
  440. return E_NOTIMPL;
  441. }
  442. //____________________________________________________________________________
  443. //
  444. // Member: CJobObject::IDataObject::DUnadvise
  445. //____________________________________________________________________________
  446. STDMETHODIMP
  447. CJobObject::DUnadvise(
  448. DWORD dwConnection)
  449. {
  450. TRACE(CJobObject, DUnadvise);
  451. return E_NOTIMPL;
  452. }
  453. //____________________________________________________________________________
  454. //
  455. // Member: CJobObject::IDataObject::EnumDAdvise
  456. //____________________________________________________________________________
  457. STDMETHODIMP
  458. CJobObject::EnumDAdvise(
  459. IEnumSTATDATA **ppenumAdvise)
  460. {
  461. TRACE(CJobObject, EnumDAdvise);
  462. return E_NOTIMPL;
  463. }
  464. //+--------------------------------------------------------------------------
  465. //
  466. // Function: JFGetDataObject
  467. //
  468. // Synopsis: Function to create a data object for jobs in the job folder.
  469. //
  470. // Arguments: [pszFolderPath] - full path to tasks folder
  471. // [pidlFolder] - pidl to that folder, supplied by shell's
  472. // call to IPersistFolder::Initialize.
  473. // [cidl] - number elements in array
  474. // [apidl] - array of idls, each naming a .job object
  475. // [fCut] - TRUE if this is created for cut operation
  476. // [ppvObj] - filled with pointer to new data object
  477. //
  478. // Returns: HRESULT
  479. //
  480. // Modifies: *[ppvObj]
  481. //
  482. // History: 01/31/1996 RaviR Created
  483. // 05-30-1997 DavidMun Pass copy of [pidlFolder]
  484. //
  485. //---------------------------------------------------------------------------
  486. HRESULT
  487. JFGetDataObject(
  488. LPCTSTR pszFolderPath,
  489. LPCITEMIDLIST pidlFolder,
  490. UINT cidl,
  491. LPCITEMIDLIST * apidl,
  492. BOOL fCut,
  493. LPVOID * ppvObj)
  494. {
  495. TRACE_FUNCTION(JFGetDataObject);
  496. LPITEMIDLIST * apidlTemp = ILA_Clone(cidl, apidl);
  497. if (NULL == apidlTemp)
  498. {
  499. CHECK_HRESULT(E_OUTOFMEMORY);
  500. return E_OUTOFMEMORY;
  501. }
  502. LPITEMIDLIST pidlFolderCopy = ILClone(pidlFolder);
  503. if (!pidlFolderCopy)
  504. {
  505. ILA_Free(cidl, apidlTemp);
  506. CHECK_HRESULT(E_OUTOFMEMORY);
  507. return E_OUTOFMEMORY;
  508. }
  509. CJobObject * pJobObjects = new CJobObject(pszFolderPath,
  510. pidlFolderCopy,
  511. cidl,
  512. apidlTemp,
  513. fCut);
  514. if (pJobObjects == NULL)
  515. {
  516. ILA_Free(cidl, apidlTemp);
  517. CHECK_HRESULT(E_OUTOFMEMORY);
  518. return E_OUTOFMEMORY;
  519. }
  520. HRESULT hr = pJobObjects->QueryInterface(IID_IDataObject, ppvObj);
  521. pJobObjects->Release();
  522. return hr;
  523. }