[shell32]
[reactos.git] / reactos / dll / win32 / shell32 / shfldr_admintools.c
1 /*
2 * Virtual Admin Tools Folder
3 *
4 * Copyright 2008 Johannes Anderwald
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include <precomp.h>
22
23 WINE_DEFAULT_DEBUG_CHANNEL (shell);
24
25
26 /* List shortcuts of
27 * CSIDL_COMMON_ADMINTOOLS
28 * Note: CSIDL_ADMINTOOLS is ignored, tested with Window XP SP3+
29 */
30
31 /***********************************************************************
32 * AdminTools folder implementation
33 */
34
35 typedef struct {
36 IShellFolder2Vtbl *lpVtbl;
37 IPersistFolder2Vtbl *lpVtblPersistFolder2;
38
39 LONG ref;
40
41 CLSID *pclsid;
42
43 LPITEMIDLIST pidlRoot; /* absolute pidl */
44 LPWSTR szTarget;
45
46 int dwAttributes; /* attributes returned by GetAttributesOf FIXME: use it */
47 } IGenericSFImpl;
48
49 static const shvheader AdminToolsSFHeader[] = {
50 {IDS_SHV_COLUMN8, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
51 {IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
52 {IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
53 {IDS_SHV_COLUMN4, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 12}
54 };
55
56 #define COLUMN_NAME 0
57 #define COLUMN_SIZE 1
58 #define COLUMN_TYPE 2
59 #define COLUMN_DATE 3
60
61 #define AdminToolsHELLVIEWCOLUMNS (4)
62
63
64 #define _IPersistFolder2_Offset ((INT_PTR)(&(((IGenericSFImpl*)0)->lpVtblPersistFolder2)))
65 #define _ICOM_THIS_From_IPersistFolder2(class, name) class* This = (class*)(((char*)name)-_IPersistFolder2_Offset);
66
67 #define _IUnknown_(This) (IShellFolder*)&(This->lpVtbl)
68 #define _IShellFolder_(This) (IShellFolder*)&(This->lpVtbl)
69
70 #define _IPersist_(This) (IPersist*)&(This->lpVtblPersistFolder2)
71 #define _IPersistFolder_(This) (IPersistFolder*)&(This->lpVtblPersistFolder2)
72 #define _IPersistFolder2_(This) (IPersistFolder2*)&(This->lpVtblPersistFolder2)
73
74 /**************************************************************************
75 * ISF_AdminTools_fnQueryInterface
76 *
77 * NOTE does not support IPersist/IPersistFolder
78 */
79 static HRESULT WINAPI ISF_AdminTools_fnQueryInterface(
80 IShellFolder2 * iface, REFIID riid, LPVOID * ppvObj)
81 {
82 IGenericSFImpl *This = (IGenericSFImpl *)iface;
83
84 TRACE ("(%p)->(%s,%p)\n", This, shdebugstr_guid (riid), ppvObj);
85
86 *ppvObj = NULL;
87
88 if (IsEqualIID (riid, &IID_IUnknown) ||
89 IsEqualIID (riid, &IID_IShellFolder) ||
90 IsEqualIID (riid, &IID_IShellFolder2))
91 {
92 *ppvObj = This;
93 }
94
95 else if (IsEqualIID (riid, &IID_IPersist) ||
96 IsEqualIID (riid, &IID_IPersistFolder) ||
97 IsEqualIID (riid, &IID_IPersistFolder2))
98 {
99 *ppvObj = _IPersistFolder2_ (This);
100 }
101
102 if (*ppvObj)
103 {
104 IUnknown_AddRef ((IUnknown *) (*ppvObj));
105 TRACE ("-- Interface: (%p)->(%p)\n", ppvObj, *ppvObj);
106 return S_OK;
107 }
108 TRACE ("-- Interface: E_NOINTERFACE\n");
109 return E_NOINTERFACE;
110 }
111
112 static ULONG WINAPI ISF_AdminTools_fnAddRef (IShellFolder2 * iface)
113 {
114 IGenericSFImpl *This = (IGenericSFImpl *)iface;
115 ULONG refCount = InterlockedIncrement(&This->ref);
116
117 TRACE ("(%p)->(count=%lu)\n", This, refCount - 1);
118
119 return refCount;
120 }
121
122 static ULONG WINAPI ISF_AdminTools_fnRelease (IShellFolder2 * iface)
123 {
124 IGenericSFImpl *This = (IGenericSFImpl *)iface;
125 ULONG refCount = InterlockedDecrement(&This->ref);
126
127 TRACE ("(%p)->(count=%lu)\n", This, refCount + 1);
128
129 if (!refCount)
130 {
131 TRACE ("-- destroying IShellFolder(%p)\n", This);
132 if (This->pidlRoot)
133 SHFree (This->pidlRoot);
134 HeapFree(GetProcessHeap(), 0, This->szTarget);
135 HeapFree(GetProcessHeap(), 0, This);
136 return 0;
137 }
138 return refCount;
139 }
140
141 /**************************************************************************
142 * ISF_AdminTools_fnParseDisplayName
143 *
144 */
145 static HRESULT WINAPI ISF_AdminTools_fnParseDisplayName (IShellFolder2 * iface,
146 HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName,
147 DWORD * pchEaten, LPITEMIDLIST * ppidl, DWORD * pdwAttributes)
148 {
149 IGenericSFImpl *This = (IGenericSFImpl *)iface;
150
151 TRACE("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n",
152 This, hwndOwner, pbc, lpszDisplayName, debugstr_w(lpszDisplayName),
153 pchEaten, ppidl, pdwAttributes);
154
155 *ppidl = 0;
156 if (pchEaten)
157 *pchEaten = 0;
158
159 MessageBoxW(NULL, lpszDisplayName, L"ParseDisplayName", MB_OK);
160
161 return E_NOTIMPL;
162 }
163
164 /**************************************************************************
165 * CreateAdminToolsEnumList()
166 */
167 static BOOL CreateAdminToolsEnumList(IEnumIDList *list, IGenericSFImpl *This, DWORD dwFlags)
168 {
169 TRACE("(%p)->(flags=0x%08x)\n", list, dwFlags);
170 /* enumerate the elements in %windir%\desktop */
171 return CreateFolderEnumList(list, This->szTarget, dwFlags);
172 }
173
174 /**************************************************************************
175 * ISF_AdminTools_fnEnumObjects
176 */
177 static HRESULT WINAPI ISF_AdminTools_fnEnumObjects (IShellFolder2 * iface,
178 HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST * ppEnumIDList)
179 {
180 IGenericSFImpl *This = (IGenericSFImpl *)iface;
181
182 TRACE ("(%p)->(HWND=%p flags=0x%08lx pplist=%p)\n",
183 This, hwndOwner, dwFlags, ppEnumIDList);
184
185 if(!ppEnumIDList) return E_OUTOFMEMORY;
186 *ppEnumIDList = IEnumIDList_Constructor();
187 if (*ppEnumIDList)
188 CreateAdminToolsEnumList(*ppEnumIDList, This, dwFlags);
189
190 TRACE ("-- (%p)->(new ID List: %p)\n", This, *ppEnumIDList);
191
192 return (*ppEnumIDList) ? S_OK : E_OUTOFMEMORY;
193 }
194
195 /**************************************************************************
196 * ISF_AdminTools_fnBindToObject
197 */
198 static HRESULT WINAPI ISF_AdminTools_fnBindToObject (IShellFolder2 * iface,
199 LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
200 {
201 IGenericSFImpl *This = (IGenericSFImpl *)iface;
202
203 TRACE ("(%p)->(pidl=%p,%p,%s,%p)\n", This,
204 pidl, pbcReserved, shdebugstr_guid (riid), ppvOut);
205
206 return SHELL32_BindToChild (This->pidlRoot, NULL, pidl, riid, ppvOut);
207 }
208
209 /**************************************************************************
210 * ISF_AdminTools_fnBindToStorage
211 */
212 static HRESULT WINAPI ISF_AdminTools_fnBindToStorage (IShellFolder2 * iface,
213 LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
214 {
215 IGenericSFImpl *This = (IGenericSFImpl *)iface;
216
217 FIXME ("(%p)->(pidl=%p,%p,%s,%p) stub\n",
218 This, pidl, pbcReserved, shdebugstr_guid (riid), ppvOut);
219
220 *ppvOut = NULL;
221 return E_NOTIMPL;
222 }
223
224 /**************************************************************************
225 * ISF_AdminTools_fnCompareIDs
226 */
227 static HRESULT WINAPI ISF_AdminTools_fnCompareIDs (IShellFolder2 * iface,
228 LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
229 {
230 IGenericSFImpl *This = (IGenericSFImpl *)iface;
231 int nReturn;
232
233 TRACE ("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", This, lParam, pidl1, pidl2);
234 nReturn = SHELL32_CompareIDs (_IShellFolder_ (This), lParam, pidl1, pidl2);
235 TRACE ("-- %i\n", nReturn);
236 return nReturn;
237 }
238
239 /**************************************************************************
240 * ISF_AdminTools_fnCreateViewObject
241 */
242 static HRESULT WINAPI ISF_AdminTools_fnCreateViewObject (IShellFolder2 * iface,
243 HWND hwndOwner, REFIID riid, LPVOID * ppvOut)
244 {
245
246 LPSHELLVIEW pShellView;
247 HRESULT hr = E_INVALIDARG;
248 IGenericSFImpl *This = (IGenericSFImpl *)iface;
249
250 TRACE ("(%p)->(hwnd=%p,%s,%p)\n", This,
251 hwndOwner, shdebugstr_guid (riid), ppvOut);
252
253 if (!ppvOut)
254 return hr;
255
256 *ppvOut = NULL;
257
258 if (IsEqualIID (riid, &IID_IDropTarget))
259 {
260 WARN ("IDropTarget not implemented\n");
261 hr = E_NOTIMPL;
262 }
263 else if (IsEqualIID (riid, &IID_IShellView))
264 {
265 pShellView = IShellView_Constructor ((IShellFolder *) iface);
266 if (pShellView)
267 {
268 hr = IShellView_QueryInterface (pShellView, riid, ppvOut);
269 IShellView_Release (pShellView);
270 }
271 }
272 TRACE ("-- (%p)->(interface=%p)\n", This, ppvOut);
273 return hr;
274 }
275
276 /**************************************************************************
277 * ISF_AdminTools_fnGetAttributesOf
278 */
279 static HRESULT WINAPI ISF_AdminTools_fnGetAttributesOf (IShellFolder2 * iface,
280 UINT cidl, LPCITEMIDLIST * apidl, DWORD * rgfInOut)
281 {
282 IGenericSFImpl *This = (IGenericSFImpl *)iface;
283 HRESULT hr = S_OK;
284 static const DWORD dwAdminToolsAttributes =
285 SFGAO_STORAGE | SFGAO_HASPROPSHEET | SFGAO_STORAGEANCESTOR |
286 SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_FILESYSTEM;
287
288 TRACE ("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n",
289 This, cidl, apidl, rgfInOut, rgfInOut ? *rgfInOut : 0);
290
291 if (!rgfInOut)
292 return E_INVALIDARG;
293 if (cidl && !apidl)
294 return E_INVALIDARG;
295
296 if (*rgfInOut == 0)
297 *rgfInOut = ~0;
298
299 if(cidl == 0) {
300 *rgfInOut &= dwAdminToolsAttributes;
301 } else {
302 while (cidl > 0 && *apidl) {
303 pdump (*apidl);
304 if (_ILIsAdminTools(*apidl)) {
305 *rgfInOut &= dwAdminToolsAttributes;
306 } else {
307 SHELL32_GetItemAttributes (_IShellFolder_ (This), *apidl, rgfInOut);
308 }
309 apidl++;
310 cidl--;
311 }
312 }
313 /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
314 *rgfInOut &= ~SFGAO_VALIDATE;
315
316 TRACE ("-- result=0x%08x\n", *rgfInOut);
317
318 return hr;
319 }
320
321 /**************************************************************************
322 * ISF_AdminTools_fnGetUIObjectOf
323 *
324 * PARAMETERS
325 * HWND hwndOwner, //[in ] Parent window for any output
326 * UINT cidl, //[in ] array size
327 * LPCITEMIDLIST* apidl, //[in ] simple pidl array
328 * REFIID riid, //[in ] Requested Interface
329 * UINT* prgfInOut, //[ ] reserved
330 * LPVOID* ppvObject) //[out] Resulting Interface
331 *
332 */
333 static HRESULT WINAPI ISF_AdminTools_fnGetUIObjectOf (IShellFolder2 * iface,
334 HWND hwndOwner, UINT cidl, LPCITEMIDLIST * apidl,
335 REFIID riid, UINT * prgfInOut, LPVOID * ppvOut)
336 {
337 IGenericSFImpl *This = (IGenericSFImpl *)iface;
338
339 LPITEMIDLIST pidl;
340 IUnknown *pObj = NULL;
341 HRESULT hr = E_INVALIDARG;
342
343 TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n",
344 This, hwndOwner, cidl, apidl, shdebugstr_guid (riid), prgfInOut, ppvOut);
345
346 if (!ppvOut)
347 return hr;
348
349 *ppvOut = NULL;
350
351 if (IsEqualIID (riid, &IID_IContextMenu))
352 {
353 hr = CDefFolderMenu_Create2(This->pidlRoot, hwndOwner, cidl, apidl, (IShellFolder*)iface, NULL, 0, NULL, (IContextMenu**)&pObj);
354 }
355 else if (IsEqualIID (riid, &IID_IDataObject) && (cidl >= 1))
356 {
357 pObj = (LPUNKNOWN) IDataObject_Constructor( hwndOwner,
358 This->pidlRoot, apidl, cidl);
359 hr = S_OK;
360 }
361 else if (IsEqualIID (riid, &IID_IExtractIconA) && (cidl == 1))
362 {
363 pidl = ILCombine (This->pidlRoot, apidl[0]);
364 pObj = (LPUNKNOWN) IExtractIconA_Constructor (pidl);
365 SHFree (pidl);
366 hr = S_OK;
367 }
368 else if (IsEqualIID (riid, &IID_IExtractIconW) && (cidl == 1))
369 {
370 pidl = ILCombine (This->pidlRoot, apidl[0]);
371 pObj = (LPUNKNOWN) IExtractIconW_Constructor (pidl);
372 SHFree (pidl);
373 hr = S_OK;
374 }
375 else if (IsEqualIID (riid, &IID_IDropTarget) && (cidl >= 1))
376 {
377 hr = IShellFolder_QueryInterface (iface,
378 &IID_IDropTarget, (LPVOID *) & pObj);
379 }
380 else if ((IsEqualIID(riid,&IID_IShellLinkW) ||
381 IsEqualIID(riid,&IID_IShellLinkA)) && (cidl == 1))
382 {
383 pidl = ILCombine (This->pidlRoot, apidl[0]);
384 hr = IShellLink_ConstructFromFile(NULL, riid, pidl, (LPVOID*)&pObj);
385 SHFree (pidl);
386 }
387 else
388 hr = E_NOINTERFACE;
389
390 if (SUCCEEDED(hr) && !pObj)
391 hr = E_OUTOFMEMORY;
392
393 *ppvOut = pObj;
394 TRACE ("(%p)->hr=0x%08x\n", This, hr);
395 return hr;
396 }
397
398 /**************************************************************************
399 * ISF_AdminTools_fnGetDisplayNameOf
400 *
401 */
402 static HRESULT WINAPI ISF_AdminTools_fnGetDisplayNameOf (IShellFolder2 * iface,
403 LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet)
404 {
405 IGenericSFImpl *This = (IGenericSFImpl *)iface;
406 HRESULT hr = S_OK;
407 LPWSTR pszPath, pOffset;
408
409
410 TRACE ("(%p)->(pidl=%p,0x%08x,%p)\n", This, pidl, dwFlags, strRet);
411 pdump (pidl);
412
413 if (!strRet)
414 return E_INVALIDARG;
415
416 pszPath = CoTaskMemAlloc((MAX_PATH +1) * sizeof(WCHAR));
417 if (!pszPath)
418 return E_OUTOFMEMORY;
419
420 ZeroMemory(pszPath, (MAX_PATH +1) * sizeof(WCHAR));
421
422 if (_ILIsAdminTools (pidl))
423 {
424 if ((GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL) &&
425 (GET_SHGDN_FOR (dwFlags) & SHGDN_FORPARSING))
426 wcscpy(pszPath, This->szTarget);
427 else if (!HCR_GetClassNameW(&CLSID_AdminFolderShortcut, pszPath, MAX_PATH))
428 hr = E_FAIL;
429 }
430 else if (_ILIsPidlSimple(pidl))
431 {
432 if ((GET_SHGDN_FOR(dwFlags) & SHGDN_FORPARSING) &&
433 (GET_SHGDN_RELATION(dwFlags) != SHGDN_INFOLDER) &&
434 This->szTarget)
435 {
436 wcscpy(pszPath, This->szTarget);
437 pOffset = PathAddBackslashW(pszPath);
438 if (pOffset)
439 {
440 if (!_ILSimpleGetTextW(pidl, pOffset, MAX_PATH + 1 - (pOffset - pszPath)))
441 hr = E_FAIL;
442 }
443 else
444 hr = E_FAIL;
445 }
446 else
447 {
448 if (_ILSimpleGetTextW(pidl, pszPath, MAX_PATH + 1))
449 {
450 if (SHELL_FS_HideExtension(pszPath))
451 PathRemoveExtensionW(pszPath);
452 }
453 else
454 hr = E_FAIL;
455 }
456 }
457 else if (_ILIsSpecialFolder(pidl))
458 {
459 BOOL bSimplePidl = _ILIsPidlSimple(pidl);
460
461 if (bSimplePidl)
462 {
463 if (!_ILSimpleGetTextW(pidl, pszPath, MAX_PATH))
464 hr = E_FAIL;
465 }
466 else if ((dwFlags & SHGDN_FORPARSING) && !bSimplePidl)
467 {
468 int len = 0;
469
470 wcscpy(pszPath, This->szTarget);
471 PathAddBackslashW(pszPath);
472 len = wcslen(pszPath);
473
474 if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags | SHGDN_INFOLDER, pszPath + len, MAX_PATH + 1 - len)))
475 {
476 CoTaskMemFree(pszPath);
477 return E_OUTOFMEMORY;
478 }
479
480 }
481 }
482
483 if (SUCCEEDED(hr))
484 {
485 strRet->uType = STRRET_WSTR;
486 strRet->u.pOleStr = pszPath;
487 TRACE ("-- (%p)->(%s,0x%08x)\n", This, debugstr_w(strRet->u.pOleStr), hr);
488 }
489 else
490 CoTaskMemFree(pszPath);
491
492 return hr;
493 }
494
495 /**************************************************************************
496 * ISF_AdminTools_fnSetNameOf
497 * Changes the name of a file object or subfolder, possibly changing its item
498 * identifier in the process.
499 *
500 * PARAMETERS
501 * HWND hwndOwner, //[in ] Owner window for output
502 * LPCITEMIDLIST pidl, //[in ] simple pidl of item to change
503 * LPCOLESTR lpszName, //[in ] the items new display name
504 * DWORD dwFlags, //[in ] SHGNO formatting flags
505 * LPITEMIDLIST* ppidlOut) //[out] simple pidl returned
506 */
507 static HRESULT WINAPI ISF_AdminTools_fnSetNameOf (IShellFolder2 * iface,
508 HWND hwndOwner, LPCITEMIDLIST pidl, /* simple pidl */
509 LPCOLESTR lpName, DWORD dwFlags, LPITEMIDLIST * pPidlOut)
510 {
511 IGenericSFImpl *This = (IGenericSFImpl *)iface;
512
513 FIXME ("(%p)->(%p,pidl=%p,%s,%lu,%p)\n", This, hwndOwner, pidl,
514 debugstr_w (lpName), dwFlags, pPidlOut);
515
516 return E_FAIL;
517 }
518
519 static HRESULT WINAPI ISF_AdminTools_fnGetDefaultSearchGUID(IShellFolder2 *iface,
520 GUID * pguid)
521 {
522 IGenericSFImpl *This = (IGenericSFImpl *)iface;
523
524 FIXME ("(%p)\n", This);
525 return E_NOTIMPL;
526 }
527
528 static HRESULT WINAPI ISF_AdminTools_fnEnumSearches (IShellFolder2 *iface,
529 IEnumExtraSearch ** ppenum)
530 {
531 IGenericSFImpl *This = (IGenericSFImpl *)iface;
532 FIXME ("(%p)\n", This);
533 return E_NOTIMPL;
534 }
535
536 static HRESULT WINAPI ISF_AdminTools_fnGetDefaultColumn (IShellFolder2 * iface,
537 DWORD dwRes, ULONG * pSort, ULONG * pDisplay)
538 {
539 if (pSort)
540 *pSort = 0;
541 if (pDisplay)
542 *pDisplay = 0;
543
544 return S_OK;
545 }
546 static HRESULT WINAPI ISF_AdminTools_fnGetDefaultColumnState (
547 IShellFolder2 * iface, UINT iColumn, DWORD * pcsFlags)
548 {
549 if (!pcsFlags || iColumn >= AdminToolsHELLVIEWCOLUMNS)
550 return E_INVALIDARG;
551 *pcsFlags = AdminToolsSFHeader[iColumn].pcsFlags;
552 return S_OK;
553
554 }
555
556 static HRESULT WINAPI ISF_AdminTools_fnGetDetailsEx (IShellFolder2 * iface,
557 LPCITEMIDLIST pidl, const SHCOLUMNID * pscid, VARIANT * pv)
558 {
559 IGenericSFImpl *This = (IGenericSFImpl *)iface;
560 FIXME ("(%p): stub\n", This);
561
562 return E_NOTIMPL;
563 }
564
565 static HRESULT WINAPI ISF_AdminTools_fnGetDetailsOf (IShellFolder2 * iface,
566 LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS * psd)
567 {
568 IGenericSFImpl *This = (IGenericSFImpl *)iface;
569 WCHAR buffer[MAX_PATH] = {0};
570 HRESULT hr = E_FAIL;
571
572 TRACE("(%p)->(%p %i %p): stub\n", This, pidl, iColumn, psd);
573
574 if (iColumn >= AdminToolsHELLVIEWCOLUMNS)
575 return E_FAIL;
576
577 psd->fmt = AdminToolsSFHeader[iColumn].fmt;
578 psd->cxChar = AdminToolsSFHeader[iColumn].cxChar;
579 if (pidl == NULL)
580 {
581 psd->str.uType = STRRET_WSTR;
582 if (LoadStringW(shell32_hInstance, AdminToolsSFHeader[iColumn].colnameid, buffer, MAX_PATH))
583 hr = SHStrDupW(buffer, &psd->str.u.pOleStr);
584
585 return hr;
586 }
587
588 psd->str.uType = STRRET_CSTR;
589 switch (iColumn)
590 {
591 case COLUMN_NAME:
592 psd->str.uType = STRRET_WSTR;
593 hr = IShellFolder_GetDisplayNameOf(iface, pidl,
594 SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
595 break;
596 case COLUMN_SIZE:
597 _ILGetFileSize (pidl, psd->str.u.cStr, MAX_PATH);
598 break;
599 case COLUMN_TYPE:
600 _ILGetFileType (pidl, psd->str.u.cStr, MAX_PATH);
601 break;
602 case COLUMN_DATE:
603 _ILGetFileDate (pidl, psd->str.u.cStr, MAX_PATH);
604 break;
605 }
606
607 return hr;
608 }
609
610 static HRESULT WINAPI ISF_AdminTools_fnMapColumnToSCID (
611 IShellFolder2 * iface, UINT column, SHCOLUMNID * pscid)
612 {
613 IGenericSFImpl *This = (IGenericSFImpl *)iface;
614 FIXME ("(%p): stub\n", This);
615 return E_NOTIMPL;
616 }
617
618 static IShellFolder2Vtbl vt_ShellFolder2 =
619 {
620 ISF_AdminTools_fnQueryInterface,
621 ISF_AdminTools_fnAddRef,
622 ISF_AdminTools_fnRelease,
623 ISF_AdminTools_fnParseDisplayName,
624 ISF_AdminTools_fnEnumObjects,
625 ISF_AdminTools_fnBindToObject,
626 ISF_AdminTools_fnBindToStorage,
627 ISF_AdminTools_fnCompareIDs,
628 ISF_AdminTools_fnCreateViewObject,
629 ISF_AdminTools_fnGetAttributesOf,
630 ISF_AdminTools_fnGetUIObjectOf,
631 ISF_AdminTools_fnGetDisplayNameOf,
632 ISF_AdminTools_fnSetNameOf,
633 /* ShellFolder2 */
634 ISF_AdminTools_fnGetDefaultSearchGUID,
635 ISF_AdminTools_fnEnumSearches,
636 ISF_AdminTools_fnGetDefaultColumn,
637 ISF_AdminTools_fnGetDefaultColumnState,
638 ISF_AdminTools_fnGetDetailsEx,
639 ISF_AdminTools_fnGetDetailsOf,
640 ISF_AdminTools_fnMapColumnToSCID
641 };
642
643 /************************************************************************
644 * IPF_AdminTools_QueryInterface
645 */
646 static HRESULT WINAPI IPF_AdminTools_QueryInterface (
647 IPersistFolder2 * iface, REFIID iid, LPVOID * ppvObj)
648 {
649 _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
650
651 TRACE ("(%p)\n", This);
652
653 return IUnknown_QueryInterface (_IUnknown_ (This), iid, ppvObj);
654 }
655
656 /************************************************************************
657 * IPF_AdminTools_AddRef
658 */
659 static ULONG WINAPI IPF_AdminTools_AddRef (IPersistFolder2 * iface)
660 {
661 _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
662
663 TRACE ("(%p)->(count=%lu)\n", This, This->ref);
664
665 return IUnknown_AddRef (_IUnknown_ (This));
666 }
667
668 /************************************************************************
669 * IPF_AdminTools_Release
670 */
671 static ULONG WINAPI IPF_AdminTools_Release (IPersistFolder2 * iface)
672 {
673 _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
674
675 TRACE ("(%p)->(count=%lu)\n", This, This->ref);
676
677 return IUnknown_Release (_IUnknown_ (This));
678 }
679
680 /************************************************************************
681 * IPF_AdminTools_GetClassID
682 */
683 static HRESULT WINAPI IPF_AdminTools_GetClassID (
684 IPersistFolder2 * iface, CLSID * lpClassId)
685 {
686 _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
687
688 TRACE ("(%p)\n", This);
689
690 memcpy(lpClassId, &CLSID_AdminFolderShortcut, sizeof(CLSID));
691
692 return S_OK;
693 }
694
695 /************************************************************************
696 * IPF_AdminTools_Initialize
697 *
698 */
699 static HRESULT WINAPI IPF_AdminTools_Initialize (
700 IPersistFolder2 * iface, LPCITEMIDLIST pidl)
701 {
702 _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
703 if (This->pidlRoot)
704 SHFree((LPVOID)This->pidlRoot);
705
706 This->pidlRoot = ILClone(pidl);
707 return S_OK;
708 }
709
710 /**************************************************************************
711 * IPF_AdminTools_fnGetCurFolder
712 */
713 static HRESULT WINAPI IPF_AdminTools_GetCurFolder (
714 IPersistFolder2 * iface, LPITEMIDLIST * pidl)
715 {
716 _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
717
718 TRACE ("(%p)->(%p)\n", This, pidl);
719
720 *pidl = ILClone (This->pidlRoot);
721 return S_OK;
722 }
723
724 static IPersistFolder2Vtbl vt_PersistFolder2 =
725 {
726 IPF_AdminTools_QueryInterface,
727 IPF_AdminTools_AddRef,
728 IPF_AdminTools_Release,
729 IPF_AdminTools_GetClassID,
730 IPF_AdminTools_Initialize,
731 IPF_AdminTools_GetCurFolder
732 };
733
734 /**************************************************************************
735 * ISF_AdminTools_Constructor
736 */
737 HRESULT WINAPI ISF_AdminTools_Constructor (
738 IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv)
739 {
740 IGenericSFImpl *sf;
741 HRESULT hr;
742
743 TRACE ("unkOut=%p %s\n", pUnkOuter, shdebugstr_guid (riid));
744
745 if (pUnkOuter)
746 return CLASS_E_NOAGGREGATION;
747
748 sf = HeapAlloc( GetProcessHeap(), 0, sizeof(*sf) );
749 if (!sf)
750 return E_OUTOFMEMORY;
751
752 sf->szTarget = HeapAlloc( GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR) );
753 if (!sf->szTarget)
754 {
755 HeapFree(GetProcessHeap(), 0, sf);
756 return E_OUTOFMEMORY;
757 }
758 if (!SHGetSpecialFolderPathW(NULL, sf->szTarget, CSIDL_COMMON_ADMINTOOLS, FALSE))
759 {
760 HeapFree(GetProcessHeap(), 0, sf->szTarget);
761 HeapFree(GetProcessHeap(), 0, sf);
762 return E_FAIL;
763 }
764
765 sf->ref = 1;
766 sf->lpVtbl = &vt_ShellFolder2;
767 sf->lpVtblPersistFolder2 = &vt_PersistFolder2;
768 sf->pidlRoot = _ILCreateAdminTools(); /* my qualified pidl */
769
770 hr = IUnknown_QueryInterface( _IUnknown_(sf), riid, ppv );
771 IUnknown_Release( _IUnknown_(sf) );
772
773 TRACE ("--(%p)\n", *ppv);
774 return hr;
775 }