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.

247 lines
6.3 KiB

  1. #include "shellprv.h"
  2. #pragma hdrstop
  3. #include "xiconwrap.h"
  4. class CExtractIcon : public CExtractIconBase
  5. {
  6. public:
  7. HRESULT _GetIconLocationW(UINT uFlags, LPWSTR pszIconFile, UINT cchMax, int *piIndex, UINT *pwFlags);
  8. HRESULT _ExtractW(LPCWSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize);
  9. HRESULT _Init(LPCWSTR pszModule, LPCWSTR pszModuleOpen);
  10. CExtractIcon(int iIcon, int iIconOpen, int iDefIcon, int iShortcutIcon, UINT uFlags);
  11. private:
  12. ~CExtractIcon();
  13. private:
  14. int _iIcon;
  15. int _iIconOpen;
  16. int _iDefIcon;
  17. int _iShortcutIcon;
  18. UINT _uFlags; // GIL_SIMULATEDOC/PERINSTANCE/PERCLASS
  19. LPWSTR _pszModule;
  20. LPWSTR _pszModuleOpen;
  21. };
  22. CExtractIcon::CExtractIcon(int iIcon, int iIconOpen, int iDefIcon, int iShortcutIcon, UINT uFlags) :
  23. CExtractIconBase(),
  24. _iIcon(iIcon), _iIconOpen(iIconOpen),_iDefIcon(iDefIcon), _iShortcutIcon(iShortcutIcon),
  25. _uFlags(uFlags), _pszModule(NULL), _pszModuleOpen(NULL)
  26. {
  27. }
  28. CExtractIcon::~CExtractIcon()
  29. {
  30. LocalFree((HLOCAL)_pszModule); // accpets NULL
  31. if (_pszModuleOpen != _pszModule)
  32. LocalFree((HLOCAL)_pszModuleOpen); // accpets NULL
  33. }
  34. HRESULT CExtractIcon::_Init(LPCWSTR pszModule, LPCWSTR pszModuleOpen)
  35. {
  36. HRESULT hr = S_OK;
  37. _pszModule = StrDup(pszModule);
  38. if (_pszModule)
  39. {
  40. if (pszModuleOpen)
  41. {
  42. _pszModuleOpen = StrDup(pszModuleOpen);
  43. if (!_pszModuleOpen)
  44. {
  45. LocalFree((HLOCAL)_pszModule);
  46. _pszModule = NULL;
  47. hr = E_OUTOFMEMORY;
  48. }
  49. }
  50. else
  51. {
  52. _pszModuleOpen = _pszModule;
  53. }
  54. }
  55. else
  56. {
  57. hr = E_OUTOFMEMORY;
  58. }
  59. return hr;
  60. }
  61. STDAPI SHCreateDefExtIcon(LPCWSTR pszModule, int iIcon, int iIconOpen, UINT uFlags, int iDefIcon, REFIID riid, void** ppv)
  62. {
  63. return SHCreateDefExtIconKey(NULL, pszModule, iIcon, iIconOpen, iDefIcon, iIcon, uFlags, riid, ppv);
  64. }
  65. // returns S_FALSE to mean "The hkey didn't have an icon so I created a default one"
  66. STDAPI SHCreateDefExtIconKey(HKEY hkey, LPCWSTR pszModule, int iIcon, int iIconOpen, int iDefIcon, int iShortcutIcon, UINT uFlags, REFIID riid, void **ppv)
  67. {
  68. WCHAR szModule[MAX_PATH];
  69. WCHAR szModuleOpen[MAX_PATH];
  70. HRESULT hr;
  71. HRESULT hrSuccess = S_OK;
  72. LPWSTR pszModuleOpen = NULL;
  73. if (hkey)
  74. {
  75. HKEY hkChild;
  76. if (RegOpenKeyEx(hkey, c_szDefaultIcon, 0, KEY_QUERY_VALUE,
  77. &hkChild) == ERROR_SUCCESS)
  78. {
  79. DWORD cb = sizeof(szModule);
  80. if (SHQueryValueEx(hkChild, NULL, NULL, NULL, szModule, &cb) ==
  81. ERROR_SUCCESS && szModule[0])
  82. {
  83. iIcon = PathParseIconLocation(szModule);
  84. iIconOpen = iIcon;
  85. pszModule = szModule;
  86. cb = sizeof(szModuleOpen);
  87. if (SHQueryValueEx(hkChild, TEXT("OpenIcon"), NULL, NULL,
  88. szModuleOpen, &cb) == ERROR_SUCCESS && szModuleOpen[0])
  89. {
  90. iIconOpen = PathParseIconLocation(szModuleOpen);
  91. pszModuleOpen = szModuleOpen;
  92. }
  93. }
  94. else
  95. {
  96. hrSuccess = S_FALSE;
  97. }
  98. RegCloseKey(hkChild);
  99. }
  100. else
  101. {
  102. hrSuccess = S_FALSE;
  103. }
  104. }
  105. if ((NULL == pszModule) || (0 == *pszModule))
  106. {
  107. // REVIEW: We should be able to make it faster!
  108. GetModuleFileName(HINST_THISDLL, szModule, ARRAYSIZE(szModule));
  109. pszModule = szModule;
  110. }
  111. CExtractIcon* pdeib = new CExtractIcon(iIcon, iIconOpen, iDefIcon, iShortcutIcon, uFlags);
  112. if (pdeib)
  113. {
  114. hr = pdeib->_Init(pszModule, pszModuleOpen);
  115. if (SUCCEEDED(hr))
  116. {
  117. hr = pdeib->QueryInterface(riid, ppv);
  118. }
  119. pdeib->Release();
  120. }
  121. else
  122. {
  123. hr = E_OUTOFMEMORY;
  124. }
  125. if (SUCCEEDED(hr))
  126. {
  127. hr = hrSuccess;
  128. }
  129. return hr;
  130. }
  131. HRESULT CExtractIcon::_GetIconLocationW(UINT uFlags, LPWSTR pszIconFile, UINT cchMax, int *piIndex, UINT *pwFlags)
  132. {
  133. HRESULT hr = S_FALSE;
  134. pszIconFile[0] = 0;
  135. if (uFlags & GIL_DEFAULTICON)
  136. {
  137. if (-1 != _iDefIcon)
  138. {
  139. lstrcpyn(pszIconFile, c_szShell32Dll, cchMax);
  140. *piIndex = _iDefIcon;
  141. *pwFlags = _uFlags;
  142. // Make sure our default icon makes it to the cache
  143. Shell_GetCachedImageIndex(pszIconFile, *piIndex, *pwFlags);
  144. hr = S_OK;
  145. }
  146. }
  147. else
  148. {
  149. int iIcon;
  150. if ((uFlags & GIL_FORSHORTCUT) && (-1 != _iShortcutIcon))
  151. {
  152. iIcon = _iShortcutIcon;
  153. }
  154. else if (uFlags & GIL_OPENICON)
  155. {
  156. iIcon = _iIconOpen;
  157. }
  158. else
  159. {
  160. iIcon = _iIcon;
  161. }
  162. if ((UINT)-1 != iIcon)
  163. {
  164. lstrcpyn(pszIconFile, (uFlags & GIL_OPENICON) ? _pszModuleOpen : _pszModule, cchMax);
  165. *piIndex = iIcon;
  166. *pwFlags = _uFlags;
  167. hr = S_OK;
  168. }
  169. }
  170. return hr;
  171. }
  172. HRESULT CExtractIcon::_ExtractW(LPCWSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize)
  173. {
  174. HRESULT hr = S_FALSE;
  175. if (_uFlags & GIL_NOTFILENAME)
  176. {
  177. // "*" as the file name means iIndex is already a system
  178. // icon index, we are done.
  179. //
  180. // defview never calls us in this case, but external people will.
  181. if ((L'*' == pszFile[0]) && (0 == pszFile[1]))
  182. {
  183. DebugMsg(DM_TRACE, TEXT("DefExtIcon::_Extract handling '*' for backup"));
  184. HIMAGELIST himlLarge, himlSmall;
  185. Shell_GetImageLists(&himlLarge, &himlSmall);
  186. if (phiconLarge)
  187. *phiconLarge = ImageList_GetIcon(himlLarge, nIconIndex, 0);
  188. if (phiconSmall)
  189. *phiconSmall = ImageList_GetIcon(himlSmall, nIconIndex,
  190. 0);
  191. hr = S_OK;
  192. }
  193. // this is the case where nIconIndex is a unique id for the
  194. // file. always get the first icon.
  195. nIconIndex = 0;
  196. }
  197. if (S_FALSE == hr)
  198. {
  199. hr = SHDefExtractIcon(pszFile, nIconIndex, _uFlags, phiconLarge, phiconSmall, nIconSize);
  200. }
  201. return hr;
  202. }