Sync with trunk revision 64099.
[reactos.git] / dll / win32 / shell32 / folders / fonts.cpp
1 /*
2 * Fonts folder
3 *
4 * Copyright 2008 Johannes Anderwald <johannes.anderwald@reactos.org>
5 * Copyright 2009 Andrew Hill
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #include <precomp.h>
23
24 WINE_DEFAULT_DEBUG_CHANNEL (shell);
25
26 /*
27 This folder should not exist. It is just a file system folder... The \windows\fonts
28 directory contains a hidden desktop.ini with a UIHandler entry that specifies a class
29 that lives in fontext.dll. The UI handler creates a custom view for the folder, which
30 is what we normally see. However, the folder is a perfectly normal CFSFolder.
31 */
32
33 /***********************************************************************
34 * IShellFolder implementation
35 */
36
37 class CDesktopFolderEnumZ: public IEnumIDListImpl
38 {
39 public:
40 CDesktopFolderEnumZ();
41 ~CDesktopFolderEnumZ();
42 HRESULT WINAPI Initialize(DWORD dwFlags);
43 BOOL CreateFontsEnumList(DWORD dwFlags);
44
45 BEGIN_COM_MAP(CDesktopFolderEnumZ)
46 COM_INTERFACE_ENTRY_IID(IID_IEnumIDList, IEnumIDList)
47 END_COM_MAP()
48 };
49
50 static shvheader FontsSFHeader[] = {
51 {IDS_SHV_COLUMN8, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
52 {IDS_SHV_COLUMN_FONTTYPE , SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
53 {IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
54 {IDS_SHV_COLUMN12, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15}
55 };
56
57 #define COLUMN_NAME 0
58 #define COLUMN_TYPE 1
59 #define COLUMN_SIZE 2
60 #define COLUMN_FILENAME 3
61
62 #define FontsSHELLVIEWCOLUMNS (4)
63
64 CDesktopFolderEnumZ::CDesktopFolderEnumZ()
65 {
66 }
67
68 CDesktopFolderEnumZ::~CDesktopFolderEnumZ()
69 {
70 }
71
72 HRESULT WINAPI CDesktopFolderEnumZ::Initialize(DWORD dwFlags)
73 {
74 if (CreateFontsEnumList(dwFlags) == FALSE)
75 return E_FAIL;
76 return S_OK;
77 }
78
79 static LPITEMIDLIST _ILCreateFontItem(LPWSTR pszFont, LPWSTR pszFile)
80 {
81 LPITEMIDLIST pidl;
82 LPPIDLDATA data;
83 int length = wcslen(pszFont) + 1;
84 int size = sizeof(PIDLDATA) + sizeof(ITEMIDLIST);
85
86 size += length * sizeof(WCHAR);
87 size += (wcslen(pszFile) + 1) * sizeof(WCHAR);
88
89 pidl = (LPITEMIDLIST)SHAlloc(size + 5);
90 if (!pidl)
91 return pidl;
92
93 ZeroMemory(pidl, size + 5);
94 pidl->mkid.cb = size + 3;
95
96 data = _ILGetDataPointer(pidl);
97 data->type = 0x00;
98 data->u.cfont.dummy = 0xFF;
99 data->u.cfont.offsFile = length;
100 wcscpy(data->u.cfont.szName, pszFont);
101 wcscpy(&data->u.cfont.szName[length], pszFile);
102
103 return pidl;
104 }
105
106 static PIDLFontStruct * _ILGetFontStruct(LPCITEMIDLIST pidl)
107 {
108 LPPIDLDATA pdata = _ILGetDataPointer(pidl);
109
110 if (pdata && pdata->type == 0x00)
111 return (PIDLFontStruct*) & (pdata->u.cfont);
112
113 return NULL;
114 }
115
116 /**************************************************************************
117 * CDesktopFolderEnumZ::CreateFontsEnumList()
118 */
119 BOOL CDesktopFolderEnumZ::CreateFontsEnumList(DWORD dwFlags)
120 {
121 WCHAR szPath[MAX_PATH];
122 WCHAR szName[LF_FACESIZE+20];
123 WCHAR szFile[MAX_PATH];
124 LPWSTR pszPath;
125 UINT Length;
126 LONG ret;
127 DWORD dwType, dwName, dwFile, dwIndex;
128 LPITEMIDLIST pidl;
129 HKEY hKey;
130
131 if (dwFlags & SHCONTF_NONFOLDERS)
132 {
133 if (!SHGetSpecialFolderPathW(NULL, szPath, CSIDL_FONTS, FALSE))
134 return FALSE;
135
136 pszPath = PathAddBackslashW(szPath);
137 if (!pszPath)
138 return FALSE;
139 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts", 0, KEY_READ, &hKey) != ERROR_SUCCESS)
140 return FALSE;
141
142 Length = pszPath - szPath;
143 dwIndex = 0;
144 do
145 {
146 dwName = sizeof(szName) / sizeof(WCHAR);
147 dwFile = sizeof(szFile) / sizeof(WCHAR);
148 ret = RegEnumValueW(hKey, dwIndex++, szName, &dwName, NULL, &dwType, (LPBYTE)szFile, &dwFile);
149 if (ret == ERROR_SUCCESS)
150 {
151 szFile[(sizeof(szFile)/sizeof(WCHAR))-1] = L'\0';
152 if (dwType == REG_SZ && wcslen(szFile) + Length + 1 < (sizeof(szPath) / sizeof(WCHAR)))
153 {
154 wcscpy(&szPath[Length], szFile);
155 pidl = _ILCreateFontItem(szName, szPath);
156 TRACE("pidl %p name %s path %s\n", pidl, debugstr_w(szName), debugstr_w(szPath));
157 if (pidl)
158 {
159 if (!AddToEnumList(pidl))
160 SHFree(pidl);
161 }
162 }
163 }
164 } while(ret != ERROR_NO_MORE_ITEMS);
165 RegCloseKey(hKey);
166
167 }
168 return TRUE;
169 }
170
171 CFontsFolder::CFontsFolder()
172 {
173 pidlRoot = NULL;
174 apidl = NULL;
175 }
176
177 CFontsFolder::~CFontsFolder()
178 {
179 TRACE("-- destroying IShellFolder(%p)\n", this);
180 SHFree(pidlRoot);
181 }
182
183 HRESULT WINAPI CFontsFolder::FinalConstruct()
184 {
185 pidlRoot = _ILCreateFont(); /* my qualified pidl */
186 if (pidlRoot == NULL)
187 return E_OUTOFMEMORY;
188 return S_OK;
189 }
190
191 /**************************************************************************
192 * CFontsFolder::ParseDisplayName
193 */
194 HRESULT WINAPI CFontsFolder::ParseDisplayName(
195 HWND hwndOwner,
196 LPBC pbcReserved,
197 LPOLESTR lpszDisplayName,
198 DWORD *pchEaten,
199 PIDLIST_RELATIVE *ppidl,
200 DWORD * pdwAttributes)
201 {
202 HRESULT hr = E_UNEXPECTED;
203
204 TRACE ("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n", this,
205 hwndOwner, pbcReserved, lpszDisplayName, debugstr_w (lpszDisplayName),
206 pchEaten, ppidl, pdwAttributes);
207
208 *ppidl = 0;
209 if (pchEaten)
210 *pchEaten = 0; /* strange but like the original */
211
212 TRACE ("(%p)->(-- ret=0x%08x)\n", this, hr);
213
214 return hr;
215 }
216
217 /**************************************************************************
218 * CFontsFolder::EnumObjects
219 */
220 HRESULT WINAPI CFontsFolder::EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList)
221 {
222 CComObject<CDesktopFolderEnumZ> *theEnumerator;
223 CComPtr<IEnumIDList> result;
224 HRESULT hResult;
225
226 TRACE ("(%p)->(HWND=%p flags=0x%08x pplist=%p)\n", this, hwndOwner, dwFlags, ppEnumIDList);
227
228 if (ppEnumIDList == NULL)
229 return E_POINTER;
230 *ppEnumIDList = NULL;
231 ATLTRY (theEnumerator = new CComObject<CDesktopFolderEnumZ>);
232 if (theEnumerator == NULL)
233 return E_OUTOFMEMORY;
234 hResult = theEnumerator->QueryInterface(IID_PPV_ARG(IEnumIDList, &result));
235 if (FAILED (hResult))
236 {
237 delete theEnumerator;
238 return hResult;
239 }
240 hResult = theEnumerator->Initialize (dwFlags);
241 if (FAILED (hResult))
242 return hResult;
243 *ppEnumIDList = result.Detach ();
244
245 TRACE ("-- (%p)->(new ID List: %p)\n", this, *ppEnumIDList);
246
247 return S_OK;
248 }
249
250 /**************************************************************************
251 * CFontsFolder::BindToObject
252 */
253 HRESULT WINAPI CFontsFolder::BindToObject(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
254 {
255 TRACE ("(%p)->(pidl=%p,%p,%s,%p)\n", this,
256 pidl, pbcReserved, shdebugstr_guid (&riid), ppvOut);
257
258 return SHELL32_BindToChild (pidlRoot, NULL, pidl, riid, ppvOut);
259 }
260
261 /**************************************************************************
262 * CFontsFolder::BindToStorage
263 */
264 HRESULT WINAPI CFontsFolder::BindToStorage(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
265 {
266 FIXME ("(%p)->(pidl=%p,%p,%s,%p) stub\n", this,
267 pidl, pbcReserved, shdebugstr_guid (&riid), ppvOut);
268
269 *ppvOut = NULL;
270 return E_NOTIMPL;
271 }
272
273 /**************************************************************************
274 * CFontsFolder::CompareIDs
275 */
276
277 HRESULT WINAPI CFontsFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2)
278 {
279 int nReturn;
280
281 TRACE ("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", this, lParam, pidl1, pidl2);
282 nReturn = SHELL32_CompareIDs (this, lParam, pidl1, pidl2);
283 TRACE ("-- %i\n", nReturn);
284 return nReturn;
285 }
286
287 /**************************************************************************
288 * CFontsFolder::CreateViewObject
289 */
290 HRESULT WINAPI CFontsFolder::CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
291 {
292 CComPtr<IShellView> pShellView;
293 HRESULT hr = E_INVALIDARG;
294
295 TRACE ("(%p)->(hwnd=%p,%s,%p)\n", this,
296 hwndOwner, shdebugstr_guid (&riid), ppvOut);
297
298 if (!ppvOut)
299 return hr;
300
301 *ppvOut = NULL;
302
303 if (IsEqualIID (riid, IID_IDropTarget))
304 {
305 WARN ("IDropTarget not implemented\n");
306 hr = E_NOTIMPL;
307 }
308 else if (IsEqualIID (riid, IID_IContextMenu))
309 {
310 WARN ("IContextMenu not implemented\n");
311 hr = E_NOTIMPL;
312 }
313 else if (IsEqualIID (riid, IID_IShellView))
314 {
315 hr = IShellView_Constructor (this, &pShellView);
316 if (pShellView)
317 hr = pShellView->QueryInterface(riid, ppvOut);
318 }
319 TRACE ("-- (%p)->(interface=%p)\n", this, ppvOut);
320 return hr;
321 }
322
323 /**************************************************************************
324 * CFontsFolder::GetAttributesOf
325 */
326 HRESULT WINAPI CFontsFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD *rgfInOut)
327 {
328 HRESULT hr = S_OK;
329
330 TRACE ("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n", this,
331 cidl, apidl, rgfInOut, rgfInOut ? *rgfInOut : 0);
332
333 if (!rgfInOut)
334 return E_INVALIDARG;
335 if (cidl && !apidl)
336 return E_INVALIDARG;
337
338 if (*rgfInOut == 0)
339 *rgfInOut = ~0;
340
341 if (cidl == 0)
342 {
343 CComPtr<IShellFolder> psfParent;
344 LPCITEMIDLIST rpidl = NULL;
345
346 hr = SHBindToParent(pidlRoot, IID_PPV_ARG(IShellFolder, &psfParent), (LPCITEMIDLIST *)&rpidl);
347 if (SUCCEEDED(hr))
348 SHELL32_GetItemAttributes (psfParent, rpidl, rgfInOut);
349 }
350 else
351 {
352 while (cidl > 0 && *apidl)
353 {
354 pdump (*apidl);
355 SHELL32_GetItemAttributes (this, *apidl, rgfInOut);
356 apidl++;
357 cidl--;
358 }
359 }
360
361 /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
362 *rgfInOut &= ~SFGAO_VALIDATE;
363
364 TRACE ("-- result=0x%08x\n", *rgfInOut);
365 return hr;
366 }
367
368 /**************************************************************************
369 * CFontsFolder::GetUIObjectOf
370 *
371 * PARAMETERS
372 * hwndOwner [in] Parent window for any output
373 * cidl [in] array size
374 * apidl [in] simple pidl array
375 * riid [in] Requested Interface
376 * prgfInOut [ ] reserved
377 * ppvObject [out] Resulting Interface
378 *
379 */
380 HRESULT WINAPI CFontsFolder::GetUIObjectOf(
381 HWND hwndOwner,
382 UINT cidl, PCUITEMID_CHILD_ARRAY apidl,
383 REFIID riid, UINT *prgfInOut, LPVOID *ppvOut)
384 {
385 LPITEMIDLIST pidl;
386 CComPtr<IUnknown> pObj;
387 HRESULT hr = E_INVALIDARG;
388
389 TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n", this,
390 hwndOwner, cidl, apidl, shdebugstr_guid (&riid), prgfInOut, ppvOut);
391
392 if (!ppvOut)
393 return hr;
394
395 *ppvOut = NULL;
396
397 if (IsEqualIID (riid, IID_IContextMenu) && (cidl >= 1))
398 {
399 pObj = (IContextMenu *)this;
400 this->apidl = apidl[0];
401 hr = S_OK;
402 }
403 else if (IsEqualIID (riid, IID_IDataObject) && (cidl >= 1))
404 {
405 hr = IDataObject_Constructor (hwndOwner, pidlRoot, apidl, cidl, (IDataObject **)&pObj);
406 }
407 else if (IsEqualIID (riid, IID_IExtractIconA) && (cidl == 1))
408 {
409 pidl = ILCombine (pidlRoot, apidl[0]);
410 pObj = (LPUNKNOWN) IExtractIconA_Constructor (pidl);
411 SHFree (pidl);
412 hr = S_OK;
413 }
414 else if (IsEqualIID (riid, IID_IExtractIconW) && (cidl == 1))
415 {
416 pidl = ILCombine (pidlRoot, apidl[0]);
417 pObj = (LPUNKNOWN) IExtractIconW_Constructor (pidl);
418 SHFree (pidl);
419 hr = S_OK;
420 }
421 else if (IsEqualIID (riid, IID_IDropTarget) && (cidl >= 1))
422 {
423 hr = this->QueryInterface(IID_IDropTarget, (LPVOID *) & pObj);
424 }
425 else
426 hr = E_NOINTERFACE;
427
428 if (SUCCEEDED(hr) && !pObj)
429 hr = E_OUTOFMEMORY;
430
431 *ppvOut = pObj.Detach();
432 TRACE ("(%p)->hr=0x%08x\n", this, hr);
433 return hr;
434 }
435
436 /**************************************************************************
437 * CFontsFolder::GetDisplayNameOf
438 *
439 */
440 HRESULT WINAPI CFontsFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet)
441 {
442 PIDLFontStruct *pFont;
443
444 TRACE("(%p)->(pidl=%p,0x%08x,%p)\n", this, pidl, dwFlags, strRet);
445 pdump (pidl);
446
447 if (!strRet)
448 return E_INVALIDARG;
449
450 pFont = _ILGetFontStruct(pidl);
451 if (pFont)
452 {
453 strRet->pOleStr = (LPWSTR)CoTaskMemAlloc((wcslen(pFont->szName) + 1) * sizeof(WCHAR));
454 if (!strRet->pOleStr)
455 return E_OUTOFMEMORY;
456
457 wcscpy(strRet->pOleStr, pFont->szName);
458 strRet->uType = STRRET_WSTR;
459 }
460 else if (!pidl->mkid.cb)
461 {
462 WCHAR wszPath[MAX_PATH];
463
464 if ((GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL) &&
465 (GET_SHGDN_FOR (dwFlags) & SHGDN_FORPARSING))
466 {
467 if (!SHGetSpecialFolderPathW(NULL, wszPath, CSIDL_FONTS, FALSE))
468 return E_FAIL;
469 }
470 else if (!HCR_GetClassNameW(CLSID_FontsFolderShortcut, wszPath, MAX_PATH))
471 return E_FAIL;
472
473 strRet->pOleStr = (LPWSTR)CoTaskMemAlloc((wcslen(wszPath) + 1) * sizeof(WCHAR));
474 if (!strRet->pOleStr)
475 return E_OUTOFMEMORY;
476
477 wcscpy(strRet->pOleStr, wszPath);
478 strRet->uType = STRRET_WSTR;
479 }
480 else
481 return E_INVALIDARG;
482
483 return S_OK;
484 }
485
486 /**************************************************************************
487 * CFontsFolder::SetNameOf
488 * Changes the name of a file object or subfolder, possibly changing its item
489 * identifier in the process.
490 *
491 * PARAMETERS
492 * hwndOwner [in] Owner window for output
493 * pidl [in] simple pidl of item to change
494 * lpszName [in] the items new display name
495 * dwFlags [in] SHGNO formatting flags
496 * ppidlOut [out] simple pidl returned
497 */
498 HRESULT WINAPI CFontsFolder::SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl, /*simple pidl */
499 LPCOLESTR lpName, DWORD dwFlags, PITEMID_CHILD *pPidlOut)
500 {
501 FIXME ("(%p)->(%p,pidl=%p,%s,%u,%p)\n", this,
502 hwndOwner, pidl, debugstr_w (lpName), dwFlags, pPidlOut);
503 return E_FAIL;
504 }
505
506 HRESULT WINAPI CFontsFolder::GetDefaultSearchGUID(GUID *pguid)
507 {
508 FIXME ("(%p)\n", this);
509 return E_NOTIMPL;
510 }
511
512 HRESULT WINAPI CFontsFolder::EnumSearches(IEnumExtraSearch **ppenum)
513 {
514 FIXME ("(%p)\n", this);
515 return E_NOTIMPL;
516 }
517
518 HRESULT WINAPI CFontsFolder::GetDefaultColumn(DWORD dwRes, ULONG *pSort, ULONG *pDisplay)
519 {
520 TRACE ("(%p)\n", this);
521
522 if (pSort)
523 *pSort = 0;
524 if (pDisplay)
525 *pDisplay = 0;
526
527 return S_OK;
528 }
529
530 HRESULT WINAPI CFontsFolder::GetDefaultColumnState(UINT iColumn, DWORD *pcsFlags)
531 {
532 TRACE ("(%p)\n", this);
533
534 if (!pcsFlags || iColumn >= FontsSHELLVIEWCOLUMNS)
535 return E_INVALIDARG;
536 *pcsFlags = FontsSFHeader[iColumn].pcsFlags;
537 return S_OK;
538 }
539
540 HRESULT WINAPI CFontsFolder::GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID *pscid, VARIANT *pv)
541 {
542 FIXME ("(%p)\n", this);
543 return E_NOTIMPL;
544 }
545
546 HRESULT WINAPI CFontsFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *psd)
547 {
548 WCHAR buffer[MAX_PATH] = {0};
549 HRESULT hr = E_FAIL;
550 PIDLFontStruct * pfont;
551 HANDLE hFile;
552 LARGE_INTEGER FileSize;
553 SHFILEINFOW fi;
554
555 TRACE("(%p, %p, %d, %p)\n", this, pidl, iColumn, psd);
556
557 if (iColumn >= FontsSHELLVIEWCOLUMNS)
558 return E_FAIL;
559
560 psd->fmt = FontsSFHeader[iColumn].fmt;
561 psd->cxChar = FontsSFHeader[iColumn].cxChar;
562 if (pidl == NULL)
563 {
564 psd->str.uType = STRRET_WSTR;
565 if (LoadStringW(shell32_hInstance, FontsSFHeader[iColumn].colnameid, buffer, MAX_PATH))
566 hr = SHStrDupW(buffer, &psd->str.pOleStr);
567
568 return hr;
569 }
570
571 if (iColumn == COLUMN_NAME)
572 {
573 psd->str.uType = STRRET_WSTR;
574 return GetDisplayNameOf(pidl, SHGDN_NORMAL, &psd->str);
575 }
576
577 psd->str.uType = STRRET_CSTR;
578 psd->str.cStr[0] = '\0';
579
580 switch(iColumn)
581 {
582 case COLUMN_TYPE:
583 pfont = _ILGetFontStruct(pidl);
584 if (pfont)
585 {
586 if (SHGetFileInfoW(pfont->szName + pfont->offsFile, 0, &fi, sizeof(fi), SHGFI_TYPENAME))
587 {
588 psd->str.pOleStr = (LPWSTR)CoTaskMemAlloc((wcslen(fi.szTypeName) + 1) * sizeof(WCHAR));
589 if (!psd->str.pOleStr)
590 return E_OUTOFMEMORY;
591 wcscpy(psd->str.pOleStr, fi.szTypeName);
592 psd->str.uType = STRRET_WSTR;
593 return S_OK;
594 }
595 }
596 break;
597 case COLUMN_SIZE:
598 pfont = _ILGetFontStruct(pidl);
599 if (pfont)
600 {
601 hFile = CreateFileW(pfont->szName + pfont->offsFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
602 if (hFile != INVALID_HANDLE_VALUE)
603 {
604 if (GetFileSizeEx(hFile, &FileSize))
605 {
606 if (StrFormatByteSizeW(FileSize.QuadPart, buffer, sizeof(buffer) / sizeof(WCHAR)))
607 {
608 psd->str.pOleStr = (LPWSTR)CoTaskMemAlloc((wcslen(buffer) + 1) * sizeof(WCHAR));
609 if (!psd->str.pOleStr)
610 {
611 CloseHandle(hFile);
612 return E_OUTOFMEMORY;
613 }
614 wcscpy(psd->str.pOleStr, buffer);
615 psd->str.uType = STRRET_WSTR;
616 CloseHandle(hFile);
617 return S_OK;
618 }
619 }
620 CloseHandle(hFile);
621 }
622 }
623 break;
624 case COLUMN_FILENAME:
625 pfont = _ILGetFontStruct(pidl);
626 if (pfont)
627 {
628 psd->str.pOleStr = (LPWSTR)CoTaskMemAlloc((wcslen(pfont->szName + pfont->offsFile) + 1) * sizeof(WCHAR));
629 if (psd->str.pOleStr)
630 {
631 psd->str.uType = STRRET_WSTR;
632 wcscpy(psd->str.pOleStr, pfont->szName + pfont->offsFile);
633 return S_OK;
634 }
635 else
636 return E_OUTOFMEMORY;
637 }
638 break;
639 }
640
641 return E_FAIL;
642 }
643
644 HRESULT WINAPI CFontsFolder::MapColumnToSCID(UINT column, SHCOLUMNID *pscid)
645 {
646 FIXME ("(%p)\n", this);
647
648 return E_NOTIMPL;
649 }
650
651 /************************************************************************
652 * CFontsFolder::GetClassID
653 */
654 HRESULT WINAPI CFontsFolder::GetClassID(CLSID *lpClassId)
655 {
656 TRACE ("(%p)\n", this);
657
658 if (!lpClassId)
659 return E_POINTER;
660
661 *lpClassId = CLSID_FontsFolderShortcut;
662
663 return S_OK;
664 }
665
666 /************************************************************************
667 * CFontsFolder::Initialize
668 *
669 * NOTES: it makes no sense to change the pidl
670 */
671 HRESULT WINAPI CFontsFolder::Initialize(LPCITEMIDLIST pidl)
672 {
673 TRACE ("(%p)->(%p)\n", this, pidl);
674
675 return E_NOTIMPL;
676 }
677
678 /**************************************************************************
679 * CFontsFolder::GetCurFolder
680 */
681 HRESULT WINAPI CFontsFolder::GetCurFolder(LPITEMIDLIST *pidl)
682 {
683 TRACE ("(%p)->(%p)\n", this, pidl);
684
685 if (!pidl)
686 return E_POINTER;
687
688 *pidl = ILClone(pidlRoot);
689
690 return S_OK;
691 }
692
693 /**************************************************************************
694 * IContextMenu2 Implementation
695 */
696
697 /**************************************************************************
698 * CFontsFolder::QueryContextMenu()
699 */
700 HRESULT WINAPI CFontsFolder::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
701 {
702 WCHAR szBuffer[30] = {0};
703 ULONG Count = 1;
704
705 TRACE("(%p)->(hmenu=%p indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n",
706 this, hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
707
708 if (LoadStringW(shell32_hInstance, IDS_OPEN, szBuffer, sizeof(szBuffer) / sizeof(WCHAR)))
709 {
710 szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0';
711 _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count, MFT_STRING, szBuffer, MFS_DEFAULT);
712 Count++;
713 }
714
715 if (LoadStringW(shell32_hInstance, IDS_PRINT_VERB, szBuffer, sizeof(szBuffer) / sizeof(WCHAR)))
716 {
717 szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0';
718 _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_STRING, szBuffer, MFS_ENABLED);
719 }
720
721 if (LoadStringW(shell32_hInstance, IDS_COPY, szBuffer, sizeof(szBuffer) / sizeof(WCHAR)))
722 {
723 szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0';
724 _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_SEPARATOR, NULL, MFS_ENABLED);
725 _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_STRING, szBuffer, MFS_ENABLED);
726 }
727
728 if (LoadStringW(shell32_hInstance, IDS_DELETE, szBuffer, sizeof(szBuffer) / sizeof(WCHAR)))
729 {
730 szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0';
731 _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_SEPARATOR, NULL, MFS_ENABLED);
732 _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count, MFT_STRING, szBuffer, MFS_ENABLED);
733 }
734
735 if (LoadStringW(shell32_hInstance, IDS_PROPERTIES, szBuffer, sizeof(szBuffer) / sizeof(WCHAR)))
736 {
737 szBuffer[(sizeof(szBuffer)/sizeof(WCHAR))-1] = L'\0';
738 _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count++, MFT_SEPARATOR, NULL, MFS_ENABLED);
739 _InsertMenuItemW(hMenu, indexMenu++, TRUE, idCmdFirst + Count, MFT_STRING, szBuffer, MFS_ENABLED);
740 }
741
742 return MAKE_HRESULT(SEVERITY_SUCCESS, 0, Count);
743 }
744
745 /**************************************************************************
746 * CFontsFolder::InvokeCommand()
747 */
748 HRESULT WINAPI CFontsFolder::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi)
749 {
750 SHELLEXECUTEINFOW sei;
751 PIDLFontStruct * pfont;
752 SHFILEOPSTRUCTW op;
753
754 TRACE("(%p)->(invcom=%p verb=%p wnd=%p)\n", this, lpcmi, lpcmi->lpVerb, lpcmi->hwnd);
755
756 if (lpcmi->lpVerb == MAKEINTRESOURCEA(1) || lpcmi->lpVerb == MAKEINTRESOURCEA(2) || lpcmi->lpVerb == MAKEINTRESOURCEA(7))
757 {
758 ZeroMemory(&sei, sizeof(sei));
759 sei.cbSize = sizeof(sei);
760 sei.hwnd = lpcmi->hwnd;
761 sei.nShow = SW_SHOWNORMAL;
762 if (lpcmi->lpVerb == MAKEINTRESOURCEA(1))
763 sei.lpVerb = L"open";
764 else if (lpcmi->lpVerb == MAKEINTRESOURCEA(2))
765 sei.lpVerb = L"print";
766 else if (lpcmi->lpVerb == MAKEINTRESOURCEA(7))
767 sei.lpVerb = L"properties";
768
769 pfont = _ILGetFontStruct(apidl);
770 sei.lpFile = pfont->szName + pfont->offsFile;
771
772 if (ShellExecuteExW(&sei) == FALSE)
773 return E_FAIL;
774 }
775 else if (lpcmi->lpVerb == MAKEINTRESOURCEA(4))
776 {
777 FIXME("implement font copying\n");
778 return E_NOTIMPL;
779 }
780 else if (lpcmi->lpVerb == MAKEINTRESOURCEA(6))
781 {
782 ZeroMemory(&op, sizeof(op));
783 op.hwnd = lpcmi->hwnd;
784 op.wFunc = FO_DELETE;
785 op.fFlags = FOF_ALLOWUNDO;
786 pfont = _ILGetFontStruct(apidl);
787 op.pFrom = pfont->szName + pfont->offsFile;
788 SHFileOperationW(&op);
789 }
790
791 return S_OK;
792 }
793
794 /**************************************************************************
795 * CFontsFolder::GetCommandString()
796 *
797 */
798 HRESULT WINAPI CFontsFolder::GetCommandString(UINT_PTR idCommand, UINT uFlags, UINT *lpReserved, LPSTR lpszName, UINT uMaxNameLen)
799 {
800 TRACE("(%p)->(idcom=%lx flags=%x %p name=%p len=%x)\n", this, idCommand, uFlags, lpReserved, lpszName, uMaxNameLen);
801
802 return E_FAIL;
803 }
804
805 /**************************************************************************
806 * CFontsFolder::HandleMenuMsg()
807 */
808 HRESULT WINAPI CFontsFolder::HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam)
809 {
810 TRACE("(%p)->(msg=%x wp=%lx lp=%lx)\n", this, uMsg, wParam, lParam);
811
812 return E_NOTIMPL;
813 }