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.

124 lines
3.8 KiB

  1. #include "shellprv.h"
  2. #include "brutil.h"
  3. #include "icotask.h"
  4. // {EB30900C-1AC4-11d2-8383-00C04FD918D0}
  5. static const GUID TASKID_IconExtraction =
  6. { 0xeb30900c, 0x1ac4, 0x11d2, { 0x83, 0x83, 0x0, 0xc0, 0x4f, 0xd9, 0x18, 0xd0 } };
  7. CIconTask::CIconTask(LPITEMIDLIST pidl, PFNICONTASKBALLBACK pfn, LPVOID pvData, UINT uId):
  8. _pidl(pidl), _pfn(pfn), _pvData(pvData), _uId(uId), CRunnableTask(RTF_DEFAULT)
  9. {
  10. }
  11. CIconTask::~CIconTask()
  12. {
  13. if (_pidl)
  14. ILFree(_pidl);
  15. }
  16. // IRunnableTask methods (override)
  17. STDMETHODIMP CIconTask::RunInitRT(void)
  18. {
  19. int iIndex = -1;
  20. IShellFolder* psf;
  21. LPCITEMIDLIST pidlItem;
  22. // We need to rebind because shell folders may not be thread safe.
  23. HRESULT hr = IEBindToParentFolder(_pidl, &psf, &pidlItem);
  24. if (SUCCEEDED(hr))
  25. {
  26. iIndex = SHMapPIDLToSystemImageListIndex(psf, pidlItem, NULL);
  27. psf->Release();
  28. }
  29. _pfn(_pvData, _uId, iIndex);
  30. return S_OK; // return S_OK even if we don't get an icon.
  31. }
  32. // NOTE: If you pass NULL for psf and pidlFolder, you must pass a full pidl which
  33. // the API takes ownership of. (This is an optimization) lamadio - 7.28.98
  34. HRESULT AddIconTask(IShellTaskScheduler* pts, IShellFolder* psf, LPCITEMIDLIST pidlFolder,
  35. LPCITEMIDLIST pidl, PFNICONTASKBALLBACK pfn, LPVOID pvData,
  36. UINT uId, int* piTempIcon)
  37. {
  38. if (!pts)
  39. return E_INVALIDARG;
  40. HRESULT hr = E_PENDING;
  41. TCHAR szIconFile[MAX_PATH];
  42. // The shell has a concept of GIL_ASYNC which means that an extension called with this flag
  43. // should not really load the target file, it should "Fake" it, returning an icon for the type.
  44. // Later, on a background thread, we're going to call it again without the GIL_ASYNC, and at
  45. // that time, it should really extract the icon.
  46. // This is an optimiation for slow icon extraction, such as network shares
  47. // NOTE: There is significant overhead to actually loading the shell extension. If you know the
  48. // type of the item, pass NULL to piTempIcopn
  49. if (piTempIcon)
  50. {
  51. *piTempIcon = -1;
  52. UINT uFlags;
  53. IExtractIconA* pixa;
  54. IExtractIconW* pix;
  55. if (SUCCEEDED(psf->GetUIObjectOf(NULL, 1, (LPCITEMIDLIST*)&pidl, IID_X_PPV_ARG(IExtractIconW, NULL, &pix))))
  56. {
  57. hr = pix->GetIconLocation(GIL_FORSHELL | GIL_ASYNC,
  58. szIconFile, ARRAYSIZE(szIconFile), piTempIcon, &uFlags);
  59. pix->Release();
  60. }
  61. else if (SUCCEEDED(psf->GetUIObjectOf(NULL, 1,(LPCITEMIDLIST*)&pidl, IID_X_PPV_ARG(IExtractIconA, NULL, &pixa))))
  62. {
  63. char szIconFileA[MAX_PATH];
  64. hr = pixa->GetIconLocation(GIL_FORSHELL | GIL_ASYNC,
  65. szIconFileA, ARRAYSIZE(szIconFileA), piTempIcon, &uFlags);
  66. SHAnsiToUnicode(szIconFileA, szIconFile, ARRAYSIZE(szIconFile));
  67. pixa->Release();
  68. }
  69. }
  70. if (hr == E_PENDING)
  71. {
  72. if (piTempIcon)
  73. *piTempIcon = Shell_GetCachedImageIndex(szIconFile, *piTempIcon, 0);
  74. LPITEMIDLIST pidlFull;
  75. if (psf)
  76. pidlFull = ILCombine(pidlFolder, pidl);
  77. else
  78. pidlFull = (LPITEMIDLIST)pidl;
  79. hr = E_OUTOFMEMORY;
  80. CIconTask* pit = new CIconTask(pidlFull, pfn, pvData, uId);
  81. // Don't ILFree(pidlFull) because CIconTask takes ownership.
  82. // FEATURE (lamadio) Remove this from the memory list. Ask Saml how to do this
  83. // for the IMallocSpy stuff.
  84. if (pit)
  85. {
  86. hr = pts->AddTask(SAFECAST(pit, IRunnableTask*), TASKID_IconExtraction,
  87. ITSAT_DEFAULT_LPARAM, ITSAT_DEFAULT_PRIORITY);
  88. pit->Release();
  89. }
  90. }
  91. else
  92. {
  93. *piTempIcon = SHMapPIDLToSystemImageListIndex(psf, pidl, NULL);
  94. hr = S_OK;
  95. }
  96. return hr;
  97. }