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.

654 lines
16 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1999
  6. //
  7. // File: items.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. #include "pch.h"
  11. #pragma hdrstop
  12. #include <shlwapip.h> // QITAB, QISearch
  13. #include <shsemip.h> // ILFree(), etc
  14. #include "folder.h"
  15. #include "items.h"
  16. #include "strings.h"
  17. CLIPFORMAT COfflineItemsData::m_cfHDROP;
  18. CLIPFORMAT COfflineItemsData::m_cfFileContents;
  19. CLIPFORMAT COfflineItemsData::m_cfFileDesc;
  20. CLIPFORMAT COfflineItemsData::m_cfPreferedEffect;
  21. CLIPFORMAT COfflineItemsData::m_cfPerformedEffect;
  22. CLIPFORMAT COfflineItemsData::m_cfLogicalPerformedEffect;
  23. CLIPFORMAT COfflineItemsData::m_cfDataSrcClsid;
  24. COfflineItemsData::COfflineItemsData(
  25. LPCITEMIDLIST pidlFolder,
  26. UINT cidl,
  27. LPCITEMIDLIST *apidl,
  28. HWND hwndParent,
  29. IShellFolder *psfOwner, // Optional. Default is NULL.
  30. IDataObject *pdtInner // Optional. Default is NULL.
  31. ) : CIDLData(pidlFolder,
  32. cidl,
  33. apidl,
  34. psfOwner,
  35. pdtInner),
  36. m_hwndParent(hwndParent),
  37. m_rgpolid(NULL),
  38. m_hrCtor(NOERROR),
  39. m_dwPreferredEffect(DROPEFFECT_COPY),
  40. m_dwPerformedEffect(DROPEFFECT_NONE),
  41. m_dwLogicalPerformedEffect(DROPEFFECT_NONE),
  42. m_cItems(0)
  43. {
  44. if (0 == m_cfHDROP)
  45. {
  46. m_cfHDROP = CF_HDROP;
  47. m_cfFileContents = (CLIPFORMAT)RegisterClipboardFormat(CFSTR_FILECONTENTS);
  48. m_cfFileDesc = (CLIPFORMAT)RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR);
  49. m_cfPreferedEffect = (CLIPFORMAT)RegisterClipboardFormat(CFSTR_PREFERREDDROPEFFECT);
  50. m_cfPerformedEffect = (CLIPFORMAT)RegisterClipboardFormat(CFSTR_PERFORMEDDROPEFFECT);
  51. m_cfLogicalPerformedEffect = (CLIPFORMAT)RegisterClipboardFormat(CFSTR_LOGICALPERFORMEDDROPEFFECT);
  52. m_cfDataSrcClsid = (CLIPFORMAT)RegisterClipboardFormat(c_szCFDataSrcClsid);
  53. }
  54. m_hrCtor = CIDLData::CtorResult();
  55. if (SUCCEEDED(m_hrCtor))
  56. {
  57. m_rgpolid = new LPCOLID[cidl];
  58. if (m_rgpolid)
  59. {
  60. ZeroMemory(m_rgpolid, sizeof(LPCOLID) * cidl);
  61. m_cItems = cidl;
  62. for (UINT i = 0; i < cidl; i++)
  63. {
  64. m_rgpolid[i] = (LPCOLID)ILClone(apidl[i]);
  65. if (!m_rgpolid[i])
  66. {
  67. m_hrCtor = E_OUTOFMEMORY;
  68. break;
  69. }
  70. }
  71. }
  72. else
  73. m_hrCtor = E_OUTOFMEMORY;
  74. }
  75. }
  76. COfflineItemsData::~COfflineItemsData(
  77. void
  78. )
  79. {
  80. delete[] m_rgpolid;
  81. }
  82. HRESULT
  83. COfflineItemsData::CreateInstance(
  84. COfflineItemsData **ppOut,
  85. LPCITEMIDLIST pidlFolder,
  86. UINT cidl,
  87. LPCITEMIDLIST *apidl,
  88. HWND hwndParent,
  89. IShellFolder *psfOwner,
  90. IDataObject *pdtInner
  91. )
  92. {
  93. HRESULT hr = E_OUTOFMEMORY;
  94. COfflineItemsData *pNew = new COfflineItemsData(pidlFolder,
  95. cidl,
  96. apidl,
  97. hwndParent,
  98. psfOwner,
  99. pdtInner);
  100. if (NULL != pNew)
  101. {
  102. hr = pNew->CtorResult();
  103. if (SUCCEEDED(hr))
  104. *ppOut = pNew;
  105. else
  106. delete pNew;
  107. }
  108. return hr;
  109. }
  110. HRESULT
  111. COfflineItemsData::CreateInstance(
  112. IDataObject **ppOut,
  113. LPCITEMIDLIST pidlFolder,
  114. UINT cidl,
  115. LPCITEMIDLIST *apidl,
  116. HWND hwndParent,
  117. IShellFolder *psfOwner,
  118. IDataObject *pdtInner
  119. )
  120. {
  121. COfflineItemsData *poid;
  122. HRESULT hr = CreateInstance(&poid,
  123. pidlFolder,
  124. cidl,
  125. apidl,
  126. hwndParent,
  127. psfOwner,
  128. pdtInner);
  129. if (SUCCEEDED(hr))
  130. {
  131. poid->AddRef();
  132. hr = poid->QueryInterface(IID_IDataObject, (void **)ppOut);
  133. poid->Release();
  134. }
  135. return hr;
  136. }
  137. HRESULT
  138. COfflineItemsData::GetData(
  139. FORMATETC *pFEIn,
  140. STGMEDIUM *pstm
  141. )
  142. {
  143. HRESULT hr;
  144. pstm->hGlobal = NULL;
  145. pstm->pUnkForRelease = NULL;
  146. if ((pFEIn->cfFormat == m_cfHDROP) && (pFEIn->tymed & TYMED_HGLOBAL))
  147. hr = CreateHDROP(pstm);
  148. else if ((pFEIn->cfFormat == m_cfFileDesc) && (pFEIn->tymed & TYMED_HGLOBAL))
  149. hr = CreateFileDescriptor(pstm);
  150. else if ((pFEIn->cfFormat == m_cfFileContents) && (pFEIn->tymed & TYMED_ISTREAM))
  151. hr = CreateFileContents(pstm, pFEIn->lindex);
  152. else if ((pFEIn->cfFormat == m_cfPreferedEffect) && (pFEIn->tymed & TYMED_HGLOBAL))
  153. hr = CreatePrefDropEffect(pstm);
  154. else if ((pFEIn->cfFormat == m_cfPerformedEffect) && (pFEIn->tymed & TYMED_HGLOBAL))
  155. hr = CreatePerformedDropEffect(pstm);
  156. else if ((pFEIn->cfFormat == m_cfLogicalPerformedEffect) && (pFEIn->tymed & TYMED_HGLOBAL))
  157. hr = CreateLogicalPerformedDropEffect(pstm);
  158. else if ((pFEIn->cfFormat == m_cfDataSrcClsid) && (pFEIn->tymed & TYMED_HGLOBAL))
  159. hr = CreateDataSrcClsid(pstm);
  160. else
  161. hr = CIDLData::GetData(pFEIn, pstm);
  162. return hr;
  163. }
  164. DWORD COfflineItemsData::GetDataDWORD(
  165. FORMATETC *pfe,
  166. STGMEDIUM *pstm,
  167. DWORD *pdwOut
  168. )
  169. {
  170. if (pfe->tymed == TYMED_HGLOBAL)
  171. {
  172. DWORD *pdw = (DWORD *)GlobalLock(pstm->hGlobal);
  173. if (pdw)
  174. {
  175. *pdwOut = *pdw;
  176. GlobalUnlock(pstm->hGlobal);
  177. }
  178. }
  179. return *pdwOut;
  180. }
  181. HRESULT
  182. COfflineItemsData::SetData(
  183. FORMATETC *pFEIn,
  184. STGMEDIUM *pstm,
  185. BOOL fRelease
  186. )
  187. {
  188. if (pFEIn->cfFormat == g_cfPerformedDropEffect)
  189. {
  190. GetDataDWORD(pFEIn, pstm, &m_dwPerformedEffect);
  191. }
  192. else if (pFEIn->cfFormat == g_cfLogicalPerformedDropEffect)
  193. {
  194. GetDataDWORD(pFEIn, pstm, &m_dwLogicalPerformedEffect);
  195. }
  196. else if (pFEIn->cfFormat == g_cfPreferredDropEffect)
  197. {
  198. GetDataDWORD(pFEIn, pstm, &m_dwPreferredEffect);
  199. }
  200. return CIDLData::SetData(pFEIn, pstm, fRelease);
  201. }
  202. HRESULT
  203. COfflineItemsData::QueryGetData(
  204. FORMATETC *pFEIn
  205. )
  206. {
  207. if (pFEIn->cfFormat == m_cfHDROP ||
  208. pFEIn->cfFormat == m_cfFileDesc ||
  209. pFEIn->cfFormat == m_cfFileContents ||
  210. pFEIn->cfFormat == m_cfPreferedEffect ||
  211. pFEIn->cfFormat == m_cfPerformedEffect ||
  212. pFEIn->cfFormat == m_cfLogicalPerformedEffect ||
  213. pFEIn->cfFormat == m_cfDataSrcClsid)
  214. {
  215. return S_OK;
  216. }
  217. return CIDLData::QueryGetData(pFEIn);
  218. }
  219. HRESULT
  220. COfflineItemsData::ProvideFormats(
  221. CEnumFormatEtc *pEnumFmtEtc
  222. )
  223. {
  224. FORMATETC rgFmtEtc[] = {
  225. { m_cfHDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
  226. { m_cfFileContents, NULL, DVASPECT_CONTENT, -1, TYMED_ISTREAM },
  227. { m_cfFileDesc, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
  228. { m_cfPreferedEffect, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
  229. { m_cfPerformedEffect, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
  230. { m_cfLogicalPerformedEffect, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },
  231. { m_cfDataSrcClsid, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }
  232. };
  233. //
  234. // Add our formats to the CIDLData format enumerator.
  235. //
  236. return pEnumFmtEtc->AddFormats(ARRAYSIZE(rgFmtEtc), rgFmtEtc);
  237. }
  238. HRESULT
  239. COfflineItemsData::CreateFileDescriptor(
  240. STGMEDIUM *pstm
  241. )
  242. {
  243. HRESULT hr;
  244. pstm->tymed = TYMED_HGLOBAL;
  245. pstm->pUnkForRelease = NULL;
  246. // render the file descriptor
  247. // we only allocate for m_cItems-1 file descriptors because the filegroup
  248. // descriptor has already allocated space for 1.
  249. FILEGROUPDESCRIPTOR *pfgd = (FILEGROUPDESCRIPTOR *)GlobalAlloc(GPTR, sizeof(FILEGROUPDESCRIPTOR) + (m_cItems - 1) * sizeof(FILEDESCRIPTOR));
  250. if (pfgd)
  251. {
  252. pfgd->cItems = m_cItems; // set the number of items
  253. pfgd->fgd[0].dwFlags = FD_PROGRESSUI; // turn on progress UI
  254. for (int i = 0; i < m_cItems; i++)
  255. {
  256. FILEDESCRIPTOR *pfd = &(pfgd->fgd[i]);
  257. COfflineFilesFolder::OLID_GetFileName(m_rgpolid[i], pfd->cFileName, ARRAYSIZE(pfd->cFileName));
  258. }
  259. pstm->hGlobal = pfgd;
  260. hr = S_OK;
  261. }
  262. else
  263. hr = E_OUTOFMEMORY;
  264. return hr;
  265. }
  266. HRESULT
  267. COfflineItemsData::CreatePrefDropEffect(
  268. STGMEDIUM *pstm
  269. )
  270. {
  271. return CreateDWORD(pstm, m_dwPreferredEffect);
  272. }
  273. HRESULT
  274. COfflineItemsData::CreatePerformedDropEffect(
  275. STGMEDIUM *pstm
  276. )
  277. {
  278. return CreateDWORD(pstm, m_dwPerformedEffect);
  279. }
  280. HRESULT
  281. COfflineItemsData::CreateLogicalPerformedDropEffect(
  282. STGMEDIUM *pstm
  283. )
  284. {
  285. return CreateDWORD(pstm, m_dwLogicalPerformedEffect);
  286. }
  287. HRESULT
  288. COfflineItemsData::CreateDWORD(
  289. STGMEDIUM *pstm,
  290. DWORD dwEffect
  291. )
  292. {
  293. pstm->tymed = TYMED_HGLOBAL;
  294. pstm->pUnkForRelease = NULL;
  295. pstm->hGlobal = GlobalAlloc(GPTR, sizeof(DWORD));
  296. if (pstm->hGlobal)
  297. {
  298. *((DWORD *)pstm->hGlobal) = dwEffect;
  299. return S_OK;
  300. }
  301. return E_OUTOFMEMORY;
  302. }
  303. HRESULT
  304. COfflineItemsData::CreateFileContents(
  305. STGMEDIUM *pstm,
  306. LONG lindex
  307. )
  308. {
  309. // here's a partial fix for when ole sometimes passes in -1 for lindex
  310. if (lindex == -1)
  311. {
  312. if (m_cItems == 1)
  313. lindex = 0;
  314. else
  315. return E_FAIL;
  316. }
  317. pstm->tymed = TYMED_ISTREAM;
  318. pstm->pUnkForRelease = NULL;
  319. TCHAR szPath[MAX_PATH];
  320. HRESULT hr = COfflineFilesFolder::OLID_GetFullPath(m_rgpolid[lindex], szPath, ARRAYSIZE(szPath));
  321. if (SUCCEEDED(hr))
  322. {
  323. hr = SHCreateStreamOnFile(szPath, STGM_READ, &pstm->pstm);
  324. }
  325. return hr;
  326. }
  327. HRESULT
  328. COfflineItemsData::CreateHDROP(
  329. STGMEDIUM *pstm
  330. )
  331. {
  332. HRESULT hr;
  333. int i;
  334. //
  335. // The extra MAX_PATH is so that the damned SHLWAPI functions (i.e.
  336. // PathAppend) won't complain about a too-small buffer. They require
  337. // that the destination buffer be AT LEAST MAX_PATH. So much for letting
  338. // code being smart about buffer sizes.
  339. //
  340. int cbHdrop = sizeof(DROPFILES) + (MAX_PATH * sizeof(TCHAR)) + sizeof(TEXT('\0'));
  341. TCHAR szPath[MAX_PATH];
  342. pstm->tymed = TYMED_HGLOBAL;
  343. pstm->pUnkForRelease = NULL;
  344. //
  345. // Calculate required buffer size.
  346. //
  347. for (i = 0; i < m_cItems; i++)
  348. {
  349. szPath[0] = TEXT('\0');
  350. hr = COfflineFilesFolder::OLID_GetFullPath(m_rgpolid[i], szPath, ARRAYSIZE(szPath));
  351. if (FAILED(hr))
  352. {
  353. return hr;
  354. }
  355. cbHdrop += (lstrlen(szPath) + 1) * sizeof(TCHAR);
  356. }
  357. pstm->hGlobal = GlobalAlloc(GPTR, cbHdrop);
  358. if (NULL != pstm->hGlobal)
  359. {
  360. //
  361. // Fill out the header and append the file paths in a
  362. // double-nul term list.
  363. //
  364. LPDROPFILES pdfHdr = (LPDROPFILES)pstm->hGlobal;
  365. pdfHdr->pFiles = sizeof(DROPFILES);
  366. pdfHdr->fWide = TRUE;
  367. LPTSTR pszWrite = (LPTSTR)((LPBYTE)pdfHdr + sizeof(DROPFILES));
  368. LPTSTR pszEnd = (LPTSTR)((LPBYTE)pstm->hGlobal + cbHdrop - sizeof(TCHAR));
  369. for (i = 0; i < m_cItems; i++)
  370. {
  371. // We allocated enough, so this should never fail
  372. if (SUCCEEDED(COfflineFilesFolder::OLID_GetFullPath(m_rgpolid[i], pszWrite, (UINT)(pszEnd - pszWrite))))
  373. {
  374. pszWrite += lstrlen(pszWrite) + 1;
  375. }
  376. }
  377. hr = S_OK;
  378. }
  379. else
  380. {
  381. hr = E_OUTOFMEMORY;
  382. }
  383. return hr;
  384. }
  385. HRESULT
  386. COfflineItemsData::CreateDataSrcClsid(
  387. STGMEDIUM *pstm
  388. )
  389. {
  390. HRESULT hr = E_OUTOFMEMORY;
  391. pstm->tymed = TYMED_HGLOBAL;
  392. pstm->pUnkForRelease = NULL;
  393. pstm->hGlobal = GlobalAlloc(GPTR, sizeof(CLSID));
  394. if (pstm->hGlobal)
  395. {
  396. *((CLSID *)pstm->hGlobal) = CLSID_OfflineFilesFolder;
  397. return S_OK;
  398. }
  399. return E_OUTOFMEMORY;
  400. }
  401. COfflineItems::COfflineItems(
  402. COfflineFilesFolder *pFolder,
  403. HWND hwnd
  404. ) : m_cRef(1),
  405. m_hwndBrowser(hwnd),
  406. m_pFolder(pFolder),
  407. m_ppolid(NULL),
  408. m_cItems(0)
  409. {
  410. DllAddRef();
  411. if (m_pFolder)
  412. m_pFolder->AddRef();
  413. }
  414. COfflineItems::~COfflineItems()
  415. {
  416. if (m_pFolder)
  417. m_pFolder->Release();
  418. if (m_ppolid)
  419. {
  420. for (UINT i = 0; i < m_cItems; i++)
  421. {
  422. if (m_ppolid[i])
  423. ILFree((LPITEMIDLIST)m_ppolid[i]);
  424. }
  425. LocalFree((HLOCAL)m_ppolid);
  426. }
  427. DllRelease();
  428. }
  429. HRESULT
  430. COfflineItems::Initialize(
  431. UINT cidl,
  432. LPCITEMIDLIST *ppidl
  433. )
  434. {
  435. HRESULT hr;
  436. m_ppolid = (LPCOLID *)LocalAlloc(LPTR, cidl * sizeof(LPCOLID));
  437. if (m_ppolid)
  438. {
  439. m_cItems = cidl;
  440. hr = S_OK;
  441. for (UINT i = 0; i < cidl; i++)
  442. {
  443. m_ppolid[i] = (LPCOLID)ILClone(ppidl[i]);
  444. if (!m_ppolid[i])
  445. {
  446. hr = E_OUTOFMEMORY;
  447. break;
  448. }
  449. }
  450. }
  451. else
  452. hr = E_OUTOFMEMORY;
  453. return hr;
  454. }
  455. HRESULT
  456. COfflineItems::CreateInstance(
  457. COfflineFilesFolder *pfolder,
  458. HWND hwnd,
  459. UINT cidl,
  460. LPCITEMIDLIST *ppidl,
  461. REFIID riid,
  462. void **ppv)
  463. {
  464. HRESULT hr;
  465. *ppv = NULL; // null the out param
  466. COfflineItems *pitems = new COfflineItems(pfolder, hwnd);
  467. if (pitems)
  468. {
  469. hr = pitems->Initialize(cidl, ppidl);
  470. if (SUCCEEDED(hr))
  471. {
  472. hr = pitems->QueryInterface(riid, ppv);
  473. }
  474. pitems->Release();
  475. }
  476. else
  477. hr = E_OUTOFMEMORY;
  478. return hr;
  479. }
  480. HRESULT
  481. COfflineItems::QueryInterface(
  482. REFIID iid,
  483. void **ppv
  484. )
  485. {
  486. static const QITAB qit[] = {
  487. QITABENT(COfflineItems, IContextMenu),
  488. QITABENT(COfflineItems, IQueryInfo),
  489. { 0 },
  490. };
  491. return QISearch(this, qit, iid, ppv);
  492. }
  493. ULONG
  494. COfflineItems::AddRef(
  495. void
  496. )
  497. {
  498. return InterlockedIncrement(&m_cRef);
  499. }
  500. ULONG
  501. COfflineItems::Release(
  502. void
  503. )
  504. {
  505. ASSERT( 0 != m_cRef );
  506. ULONG cRef = InterlockedDecrement(&m_cRef);
  507. if ( 0 == cRef )
  508. {
  509. delete this;
  510. }
  511. return cRef;
  512. }
  513. //
  514. // IQueryInfo Methods -------------------------------------------------------
  515. //
  516. HRESULT
  517. COfflineItems::GetInfoTip(
  518. DWORD dwFlags,
  519. WCHAR **ppwszTip
  520. )
  521. {
  522. TCHAR szPath[MAX_PATH];
  523. HRESULT hr = COfflineFilesFolder::OLID_GetFullPath(m_ppolid[0], szPath, ARRAYSIZE(szPath));
  524. if (SUCCEEDED(hr))
  525. {
  526. hr = SHStrDup(szPath, ppwszTip);
  527. }
  528. return hr;
  529. }
  530. HRESULT
  531. COfflineItems::GetInfoFlags(
  532. DWORD *pdwFlags
  533. )
  534. {
  535. *pdwFlags = 0;
  536. return S_OK;
  537. }
  538. //
  539. // IContextMenu Methods -------------------------------------------------------
  540. //
  541. HRESULT
  542. COfflineItems::QueryContextMenu(
  543. HMENU hmenu,
  544. UINT indexMenu,
  545. UINT idCmdFirst,
  546. UINT idCmdLast,
  547. UINT uFlags
  548. )
  549. {
  550. USHORT cItems = 0;
  551. return ResultFromShort(cItems); // number of menu items
  552. }
  553. HRESULT
  554. COfflineItems::InvokeCommand(
  555. LPCMINVOKECOMMANDINFO pici
  556. )
  557. {
  558. HRESULT hr = S_OK;
  559. return hr;
  560. }
  561. HRESULT
  562. COfflineItems::GetCommandString(
  563. UINT_PTR idCmd,
  564. UINT uFlags,
  565. UINT *pwReserved,
  566. LPSTR pszName,
  567. UINT cchMax
  568. )
  569. {
  570. HRESULT hr = E_FAIL;
  571. return hr;
  572. }