0727b0b886270b1f5cba9e0b48439f822d1f9027
[reactos.git] / reactos / dll / win32 / shell32 / CExtractIcon.cpp
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Registry namespace extension
4 * FILE: dll/win32/shell32/extracticon.c
5 * PURPOSE: Icon extraction
6 *
7 * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
8 */
9
10 #include "precomp.h"
11
12 WINE_DEFAULT_DEBUG_CHANNEL(shell);
13
14 struct IconLocation
15 {
16 LPWSTR file;
17 UINT index;
18 };
19
20 class CExtractIcon :
21 public CComObjectRootEx<CComMultiThreadModelNoCS>,
22 public IDefaultExtractIconInit,
23 public IExtractIconW,
24 public IExtractIconA,
25 public IPersistFile
26 {
27 private:
28 UINT flags;
29 struct IconLocation defaultIcon;
30 struct IconLocation normalIcon;
31 struct IconLocation openIcon;
32 struct IconLocation shortcutIcon;
33 public:
34 CExtractIcon();
35 ~CExtractIcon();
36
37 // IDefaultExtractIconInit
38 virtual HRESULT STDMETHODCALLTYPE SetDefaultIcon(LPCWSTR pszFile, int iIcon);
39 virtual HRESULT STDMETHODCALLTYPE SetFlags(UINT uFlags);
40 virtual HRESULT STDMETHODCALLTYPE SetKey(HKEY hkey);
41 virtual HRESULT STDMETHODCALLTYPE SetNormalIcon(LPCWSTR pszFile, int iIcon);
42 virtual HRESULT STDMETHODCALLTYPE SetOpenIcon(LPCWSTR pszFile, int iIcon);
43 virtual HRESULT STDMETHODCALLTYPE SetShortcutIcon(LPCWSTR pszFile, int iIcon);
44
45 // IExtractIconW
46 virtual HRESULT STDMETHODCALLTYPE GetIconLocation(UINT uFlags, LPWSTR szIconFile, UINT cchMax, int *piIndex, UINT *pwFlags);
47 virtual HRESULT STDMETHODCALLTYPE Extract(LPCWSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize);
48
49 // IExtractIconA
50 virtual HRESULT STDMETHODCALLTYPE GetIconLocation(UINT uFlags, LPSTR szIconFile, UINT cchMax, int *piIndex, UINT *pwFlags);
51 virtual HRESULT STDMETHODCALLTYPE Extract(LPCSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize);
52
53 // IPersist
54 virtual HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pClassID);
55 virtual HRESULT STDMETHODCALLTYPE IsDirty();
56
57 // IPersistFile
58 virtual HRESULT STDMETHODCALLTYPE Load(LPCOLESTR pszFileName, DWORD dwMode);
59 virtual HRESULT STDMETHODCALLTYPE Save(LPCOLESTR pszFileName, BOOL fRemember);
60 virtual HRESULT STDMETHODCALLTYPE SaveCompleted(LPCOLESTR pszFileName);
61 virtual HRESULT STDMETHODCALLTYPE GetCurFile(LPOLESTR *ppszFileName);
62
63 BEGIN_COM_MAP(CExtractIcon)
64 COM_INTERFACE_ENTRY_IID(IID_IDefaultExtractIconInit, IDefaultExtractIconInit)
65 COM_INTERFACE_ENTRY_IID(IID_IExtractIconW, IExtractIconW)
66 COM_INTERFACE_ENTRY_IID(IID_IExtractIconA, IExtractIconA)
67 COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist)
68 COM_INTERFACE_ENTRY_IID(IID_IPersistFile, IPersistFile)
69 END_COM_MAP()
70 };
71
72 VOID DuplicateString(
73 LPCWSTR Source,
74 LPWSTR *Destination)
75 {
76 SIZE_T cb;
77
78 if (*Destination)
79 CoTaskMemFree(*Destination);
80
81 cb = (wcslen(Source) + 1) * sizeof(WCHAR);
82 *Destination = (LPWSTR)CoTaskMemAlloc(cb);
83 if (!*Destination)
84 return;
85 CopyMemory(*Destination, Source, cb);
86 }
87
88 CExtractIcon::CExtractIcon()
89 {
90 flags = 0;
91 memset(&defaultIcon, 0, sizeof(defaultIcon));
92 memset(&normalIcon, 0, sizeof(normalIcon));
93 memset(&openIcon, 0, sizeof(openIcon));
94 memset(&shortcutIcon, 0, sizeof(shortcutIcon));
95 }
96
97 CExtractIcon::~CExtractIcon()
98 {
99 if (defaultIcon.file) CoTaskMemFree(defaultIcon.file);
100 if (normalIcon.file) CoTaskMemFree(normalIcon.file);
101 if (openIcon.file) CoTaskMemFree(openIcon.file);
102 if (shortcutIcon.file) CoTaskMemFree(shortcutIcon.file);
103 }
104
105 HRESULT STDMETHODCALLTYPE CExtractIcon::SetDefaultIcon(
106 LPCWSTR pszFile,
107 int iIcon)
108 {
109 TRACE("(%p, %s, %d)\n", this, debugstr_w(pszFile), iIcon);
110
111 DuplicateString(pszFile, &defaultIcon.file);
112 if (!defaultIcon.file)
113 return E_OUTOFMEMORY;
114 defaultIcon.index = iIcon;
115 return S_OK;
116 }
117
118 HRESULT STDMETHODCALLTYPE CExtractIcon::SetFlags(
119 UINT uFlags)
120 {
121 TRACE("(%p, 0x%x)\n", this, uFlags);
122
123 flags = uFlags;
124 return S_OK;
125 }
126
127 HRESULT STDMETHODCALLTYPE CExtractIcon::SetKey(
128 HKEY hkey)
129 {
130 FIXME("(%p, %p)\n", this, hkey);
131 UNIMPLEMENTED;
132 return E_NOTIMPL;
133 }
134
135 HRESULT STDMETHODCALLTYPE CExtractIcon::SetNormalIcon(
136 LPCWSTR pszFile,
137 int iIcon)
138 {
139 TRACE("(%p, %s, %d)\n", this, debugstr_w(pszFile), iIcon);
140
141 DuplicateString(pszFile, &normalIcon.file);
142 if (!normalIcon.file)
143 return E_OUTOFMEMORY;
144 normalIcon.index = iIcon;
145 return S_OK;
146 }
147
148 HRESULT STDMETHODCALLTYPE CExtractIcon::SetOpenIcon(
149 LPCWSTR pszFile,
150 int iIcon)
151 {
152 TRACE("(%p, %s, %d)\n", this, debugstr_w(pszFile), iIcon);
153
154 DuplicateString(pszFile, &openIcon.file);
155 if (!openIcon.file)
156 return E_OUTOFMEMORY;
157 openIcon.index = iIcon;
158 return S_OK;
159 }
160
161 HRESULT STDMETHODCALLTYPE CExtractIcon::SetShortcutIcon(
162 LPCWSTR pszFile,
163 int iIcon)
164 {
165 TRACE("(%p, %s, %d)\n", this, debugstr_w(pszFile), iIcon);
166
167 DuplicateString(pszFile, &shortcutIcon.file);
168 if (!shortcutIcon.file)
169 return E_OUTOFMEMORY;
170 shortcutIcon.index = iIcon;
171 return S_OK;
172 }
173
174 HRESULT STDMETHODCALLTYPE CExtractIcon::GetIconLocation(
175 UINT uFlags,
176 LPWSTR szIconFile,
177 UINT cchMax,
178 int *piIndex,
179 UINT *pwFlags)
180 {
181 const struct IconLocation *icon = NULL;
182 SIZE_T cb;
183
184 TRACE("(%p, 0x%x, %s, 0x%x, %p, %p)\n", this, uFlags, debugstr_w(szIconFile), cchMax, piIndex, pwFlags);
185
186 if (!piIndex || !pwFlags)
187 return E_POINTER;
188
189 if (uFlags & GIL_DEFAULTICON)
190 icon = defaultIcon.file ? &defaultIcon : &normalIcon;
191 else if (uFlags & GIL_FORSHORTCUT)
192 icon = shortcutIcon.file ? &shortcutIcon : &normalIcon;
193 else if (uFlags & GIL_OPENICON)
194 icon = openIcon.file ? &openIcon : &normalIcon;
195 else
196 icon = &normalIcon;
197
198 if (!icon->file)
199 return E_FAIL;
200
201 cb = wcslen(icon->file) + 1;
202 if (cchMax < (UINT)cb)
203 return E_FAIL;
204 CopyMemory(szIconFile, icon->file, cb * sizeof(WCHAR));
205 *piIndex = icon->index;
206 *pwFlags = flags;
207 return S_OK;
208 }
209
210 HRESULT STDMETHODCALLTYPE CExtractIcon::Extract(
211 LPCWSTR pszFile,
212 UINT nIconIndex,
213 HICON *phiconLarge,
214 HICON *phiconSmall,
215 UINT nIconSize)
216 {
217 TRACE("(%p, %s, %u, %p, %p, %u)\n", this, debugstr_w(pszFile), nIconIndex, phiconLarge, phiconSmall, nIconSize);
218
219 /* Nothing to do, ExtractIconW::GetIconLocation should be enough */
220 return S_FALSE;
221 }
222
223 HRESULT STDMETHODCALLTYPE CExtractIcon::GetIconLocation(
224 UINT uFlags,
225 LPSTR szIconFile,
226 UINT cchMax,
227 int *piIndex,
228 UINT *pwFlags)
229 {
230 LPWSTR szIconFileW = NULL;
231 HRESULT hr;
232
233 if (cchMax > 0)
234 {
235 szIconFileW = (LPWSTR)CoTaskMemAlloc(cchMax * sizeof(WCHAR));
236 if (!szIconFileW)
237 return E_OUTOFMEMORY;
238 }
239
240 hr = GetIconLocation(
241 uFlags, szIconFileW, cchMax, piIndex, pwFlags);
242 if (SUCCEEDED(hr) && cchMax > 0)
243 if (0 == WideCharToMultiByte(CP_ACP, 0, szIconFileW, cchMax, szIconFile, cchMax, NULL, NULL))
244 hr = E_FAIL;
245
246 if (szIconFileW)
247 CoTaskMemFree(szIconFileW);
248 return hr;
249 }
250
251 HRESULT STDMETHODCALLTYPE CExtractIcon::Extract(
252 LPCSTR pszFile,
253 UINT nIconIndex,
254 HICON *phiconLarge,
255 HICON *phiconSmall,
256 UINT nIconSize)
257 {
258 LPWSTR pszFileW = NULL;
259 HRESULT hr;
260
261 if (pszFile)
262 {
263 int nLength;
264
265 nLength = MultiByteToWideChar(CP_ACP, 0, pszFile, -1, NULL, 0);
266 if (nLength == 0)
267 return E_FAIL;
268 pszFileW = (LPWSTR)CoTaskMemAlloc(nLength * sizeof(WCHAR));
269 if (!pszFileW)
270 return E_OUTOFMEMORY;
271 if (!MultiByteToWideChar(CP_ACP, 0, pszFile, nLength, pszFileW, nLength))
272 {
273 CoTaskMemFree(pszFileW);
274 return E_FAIL;
275 }
276 }
277
278 hr = Extract(pszFileW, nIconIndex, phiconLarge, phiconSmall, nIconSize);
279
280 if (pszFileW)
281 CoTaskMemFree(pszFileW);
282 return hr;
283 }
284
285 HRESULT STDMETHODCALLTYPE CExtractIcon::GetClassID(
286 CLSID *pClassID)
287 {
288 TRACE("(%p, %p)\n", this, pClassID);
289
290 if (!pClassID)
291 return E_POINTER;
292
293 *pClassID = GUID_NULL;
294 return S_OK;
295 }
296
297 HRESULT STDMETHODCALLTYPE CExtractIcon::IsDirty()
298 {
299 FIXME("(%p)\n", this);
300 UNIMPLEMENTED;
301 return E_NOTIMPL;
302 }
303
304 HRESULT STDMETHODCALLTYPE CExtractIcon::Load(
305 LPCOLESTR pszFileName,
306 DWORD dwMode)
307 {
308 FIXME("(%p, %s, %u)\n", this, debugstr_w(pszFileName), dwMode);
309 UNIMPLEMENTED;
310 return E_NOTIMPL;
311 }
312
313 HRESULT STDMETHODCALLTYPE CExtractIcon::Save(
314 LPCOLESTR pszFileName,
315 BOOL fRemember)
316 {
317 FIXME("(%p, %s, %d)\n", this, debugstr_w(pszFileName), fRemember);
318 UNIMPLEMENTED;
319 return E_NOTIMPL;
320 }
321
322 HRESULT STDMETHODCALLTYPE CExtractIcon::SaveCompleted(
323 LPCOLESTR pszFileName)
324 {
325 FIXME("(%p, %s)\n", this, debugstr_w(pszFileName));
326 UNIMPLEMENTED;
327 return E_NOTIMPL;
328 }
329
330 HRESULT STDMETHODCALLTYPE CExtractIcon::GetCurFile(
331 LPOLESTR *ppszFileName)
332 {
333 FIXME("(%p, %p)\n", this, ppszFileName);
334 UNIMPLEMENTED;
335 return E_NOTIMPL;
336 }
337
338 HRESULT WINAPI SHCreateDefaultExtractIcon(REFIID riid, void **ppv)
339 {
340 return ShellObjectCreator<CExtractIcon>(riid, ppv);
341 }