[SHELL32]
[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(uFlags, szIconFileW, cchMax, piIndex, pwFlags);
241 if (SUCCEEDED(hr) && cchMax > 0)
242 if (0 == WideCharToMultiByte(CP_ACP, 0, szIconFileW, cchMax, szIconFile, cchMax, NULL, NULL))
243 hr = E_FAIL;
244
245 if (szIconFileW)
246 CoTaskMemFree(szIconFileW);
247 return hr;
248 }
249
250 HRESULT STDMETHODCALLTYPE CExtractIcon::Extract(
251 LPCSTR pszFile,
252 UINT nIconIndex,
253 HICON *phiconLarge,
254 HICON *phiconSmall,
255 UINT nIconSize)
256 {
257 LPWSTR pszFileW = NULL;
258 HRESULT hr;
259
260 if (pszFile)
261 {
262 int nLength;
263
264 nLength = MultiByteToWideChar(CP_ACP, 0, pszFile, -1, NULL, 0);
265 if (nLength == 0)
266 return E_FAIL;
267 pszFileW = (LPWSTR)CoTaskMemAlloc(nLength * sizeof(WCHAR));
268 if (!pszFileW)
269 return E_OUTOFMEMORY;
270 if (!MultiByteToWideChar(CP_ACP, 0, pszFile, nLength, pszFileW, nLength))
271 {
272 CoTaskMemFree(pszFileW);
273 return E_FAIL;
274 }
275 }
276
277 hr = Extract(pszFileW, nIconIndex, phiconLarge, phiconSmall, nIconSize);
278
279 if (pszFileW)
280 CoTaskMemFree(pszFileW);
281 return hr;
282 }
283
284 HRESULT STDMETHODCALLTYPE CExtractIcon::GetClassID(
285 CLSID *pClassID)
286 {
287 TRACE("(%p, %p)\n", this, pClassID);
288
289 if (!pClassID)
290 return E_POINTER;
291
292 *pClassID = GUID_NULL;
293 return S_OK;
294 }
295
296 HRESULT STDMETHODCALLTYPE CExtractIcon::IsDirty()
297 {
298 FIXME("(%p)\n", this);
299 UNIMPLEMENTED;
300 return E_NOTIMPL;
301 }
302
303 HRESULT STDMETHODCALLTYPE CExtractIcon::Load(
304 LPCOLESTR pszFileName,
305 DWORD dwMode)
306 {
307 FIXME("(%p, %s, %u)\n", this, debugstr_w(pszFileName), dwMode);
308 UNIMPLEMENTED;
309 return E_NOTIMPL;
310 }
311
312 HRESULT STDMETHODCALLTYPE CExtractIcon::Save(
313 LPCOLESTR pszFileName,
314 BOOL fRemember)
315 {
316 FIXME("(%p, %s, %d)\n", this, debugstr_w(pszFileName), fRemember);
317 UNIMPLEMENTED;
318 return E_NOTIMPL;
319 }
320
321 HRESULT STDMETHODCALLTYPE CExtractIcon::SaveCompleted(
322 LPCOLESTR pszFileName)
323 {
324 FIXME("(%p, %s)\n", this, debugstr_w(pszFileName));
325 UNIMPLEMENTED;
326 return E_NOTIMPL;
327 }
328
329 HRESULT STDMETHODCALLTYPE CExtractIcon::GetCurFile(
330 LPOLESTR *ppszFileName)
331 {
332 FIXME("(%p, %p)\n", this, ppszFileName);
333 UNIMPLEMENTED;
334 return E_NOTIMPL;
335 }
336
337 HRESULT WINAPI SHCreateDefaultExtractIcon(REFIID riid, void **ppv)
338 {
339 return ShellObjectCreator<CExtractIcon>(riid, ppv);
340 }