2 * Virtual Admin Tools Folder
4 * Copyright 2008 Johannes Anderwald
5 * Copyright 2009 Andrew Hill
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.
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.
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 Street, Fifth Floor, Boston, MA 02110-1301 USA
24 WINE_DEFAULT_DEBUG_CHANNEL (shell
);
27 This folder should not exist. It is just a file system folder...
31 * CSIDL_COMMON_ADMINTOOLS
32 * Note: CSIDL_ADMINTOOLS is ignored, tested with Window XP SP3+
35 /***********************************************************************
36 * AdminTools folder implementation
39 class CDesktopFolderEnumY
:
40 public IEnumIDListImpl
44 CDesktopFolderEnumY();
45 ~CDesktopFolderEnumY();
46 HRESULT WINAPI
Initialize(LPWSTR szTarget
, DWORD dwFlags
);
48 BEGIN_COM_MAP(CDesktopFolderEnumY
)
49 COM_INTERFACE_ENTRY_IID(IID_IEnumIDList
, IEnumIDList
)
53 static const shvheader AdminToolsSFHeader
[] = {
54 {IDS_SHV_COLUMN8
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 15},
55 {IDS_SHV_COLUMN2
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 10},
56 {IDS_SHV_COLUMN3
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 10},
57 {IDS_SHV_COLUMN4
, SHCOLSTATE_TYPE_DATE
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 12}
65 #define AdminToolsHELLVIEWCOLUMNS (4)
67 CDesktopFolderEnumY::CDesktopFolderEnumY()
71 CDesktopFolderEnumY::~CDesktopFolderEnumY()
75 HRESULT WINAPI
CDesktopFolderEnumY::Initialize(LPWSTR szTarget
, DWORD dwFlags
)
77 TRACE("(%p)->(flags=0x%08x)\n", this, dwFlags
);
78 /* enumerate the elements in %windir%\desktop */
79 return CreateFolderEnumList(szTarget
, dwFlags
);
82 CAdminToolsFolder::CAdminToolsFolder()
86 pidlRoot
= NULL
; /* absolute pidl */
89 dwAttributes
= 0; /* attributes returned by GetAttributesOf FIXME: use it */
92 CAdminToolsFolder::~CAdminToolsFolder()
94 TRACE ("-- destroying IShellFolder(%p)\n", this);
97 HeapFree(GetProcessHeap(), 0, szTarget
);
100 HRESULT WINAPI
CAdminToolsFolder::FinalConstruct()
102 szTarget
= (LPWSTR
)HeapAlloc(GetProcessHeap(), 0, MAX_PATH
* sizeof(WCHAR
));
103 if (szTarget
== NULL
)
104 return E_OUTOFMEMORY
;
105 if (!SHGetSpecialFolderPathW(NULL
, szTarget
, CSIDL_COMMON_ADMINTOOLS
, FALSE
))
108 pidlRoot
= _ILCreateAdminTools(); /* my qualified pidl */
109 if (pidlRoot
== NULL
)
110 return E_OUTOFMEMORY
;
114 /**************************************************************************
115 * CAdminToolsFolder::ParseDisplayName
118 HRESULT WINAPI
CAdminToolsFolder::ParseDisplayName(HWND hwndOwner
, LPBC pbc
, LPOLESTR lpszDisplayName
,
119 DWORD
* pchEaten
, LPITEMIDLIST
* ppidl
, DWORD
* pdwAttributes
)
121 TRACE("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n",
122 this, hwndOwner
, pbc
, lpszDisplayName
, debugstr_w(lpszDisplayName
),
123 pchEaten
, ppidl
, pdwAttributes
);
129 MessageBoxW(NULL
, lpszDisplayName
, L
"ParseDisplayName", MB_OK
);
134 /**************************************************************************
135 * CAdminToolsFolder::EnumObjects
137 HRESULT WINAPI
CAdminToolsFolder::EnumObjects(HWND hwndOwner
, DWORD dwFlags
, LPENUMIDLIST
*ppEnumIDList
)
139 CComObject
<CDesktopFolderEnumY
> *theEnumerator
;
140 CComPtr
<IEnumIDList
> result
;
143 TRACE ("(%p)->(HWND=%p flags=0x%08x pplist=%p)\n", this, hwndOwner
, dwFlags
, ppEnumIDList
);
145 if (ppEnumIDList
== NULL
)
147 *ppEnumIDList
= NULL
;
148 ATLTRY (theEnumerator
= new CComObject
<CDesktopFolderEnumY
>);
149 if (theEnumerator
== NULL
)
150 return E_OUTOFMEMORY
;
151 hResult
= theEnumerator
->QueryInterface(IID_PPV_ARG(IEnumIDList
, &result
));
152 if (FAILED (hResult
))
154 delete theEnumerator
;
157 hResult
= theEnumerator
->Initialize (szTarget
, dwFlags
);
158 if (FAILED (hResult
))
160 *ppEnumIDList
= result
.Detach ();
162 TRACE ("-- (%p)->(new ID List: %p)\n", this, *ppEnumIDList
);
167 /**************************************************************************
168 * CAdminToolsFolder::BindToObject
170 HRESULT WINAPI
CAdminToolsFolder::BindToObject(LPCITEMIDLIST pidl
, LPBC pbcReserved
, REFIID riid
, LPVOID
*ppvOut
)
172 TRACE ("(%p)->(pidl=%p,%p,%s,%p)\n", this,
173 pidl
, pbcReserved
, shdebugstr_guid (&riid
), ppvOut
);
175 return SHELL32_BindToChild(pidlRoot
, NULL
, pidl
, riid
, ppvOut
);
178 /**************************************************************************
179 * CAdminToolsFolder::BindToStorage
181 HRESULT WINAPI
CAdminToolsFolder::BindToStorage(LPCITEMIDLIST pidl
, LPBC pbcReserved
, REFIID riid
, LPVOID
*ppvOut
)
183 FIXME ("(%p)->(pidl=%p,%p,%s,%p) stub\n",
184 this, pidl
, pbcReserved
, shdebugstr_guid (&riid
), ppvOut
);
190 /**************************************************************************
191 * CAdminToolsFolder::CompareIDs
193 HRESULT WINAPI
CAdminToolsFolder::CompareIDs(LPARAM lParam
, LPCITEMIDLIST pidl1
, LPCITEMIDLIST pidl2
)
197 TRACE ("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", this, lParam
, pidl1
, pidl2
);
198 nReturn
= SHELL32_CompareIDs (this, lParam
, pidl1
, pidl2
);
199 TRACE ("-- %i\n", nReturn
);
203 /**************************************************************************
204 * CAdminToolsFolder::CreateViewObject
206 HRESULT WINAPI
CAdminToolsFolder::CreateViewObject(HWND hwndOwner
, REFIID riid
, LPVOID
*ppvOut
)
208 CComPtr
<IShellView
> pShellView
;
209 HRESULT hr
= E_INVALIDARG
;
211 TRACE ("(%p)->(hwnd=%p,%s,%p)\n", this,
212 hwndOwner
, shdebugstr_guid (&riid
), ppvOut
);
219 if (IsEqualIID (riid
, IID_IDropTarget
))
221 WARN ("IDropTarget not implemented\n");
224 else if (IsEqualIID (riid
, IID_IShellView
))
226 hr
= IShellView_Constructor ((IShellFolder
*)this, &pShellView
);
228 hr
= pShellView
->QueryInterface(riid
, ppvOut
);
230 TRACE ("-- (%p)->(interface=%p)\n", this, ppvOut
);
234 /**************************************************************************
235 * ISF_AdminTools_fnGetAttributesOf
237 HRESULT WINAPI
CAdminToolsFolder::GetAttributesOf(UINT cidl
, LPCITEMIDLIST
*apidl
, DWORD
*rgfInOut
)
240 static const DWORD dwAdminToolsAttributes
=
241 SFGAO_STORAGE
| SFGAO_HASPROPSHEET
| SFGAO_STORAGEANCESTOR
|
242 SFGAO_FILESYSANCESTOR
| SFGAO_FOLDER
| SFGAO_FILESYSTEM
;
244 TRACE ("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n",
245 this, cidl
, apidl
, rgfInOut
, rgfInOut
? *rgfInOut
: 0);
256 *rgfInOut
&= dwAdminToolsAttributes
;
258 while (cidl
> 0 && *apidl
) {
260 if (_ILIsAdminTools(*apidl
)) {
261 *rgfInOut
&= dwAdminToolsAttributes
;
263 SHELL32_GetItemAttributes (this, *apidl
, rgfInOut
);
269 /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
270 *rgfInOut
&= ~SFGAO_VALIDATE
;
272 TRACE ("-- result=0x%08x\n", *rgfInOut
);
277 /**************************************************************************
278 * CAdminToolsFolder::GetUIObjectOf
281 * HWND hwndOwner, //[in ] Parent window for any output
282 * UINT cidl, //[in ] array size
283 * LPCITEMIDLIST* apidl, //[in ] simple pidl array
284 * REFIID riid, //[in ] Requested Interface
285 * UINT* prgfInOut, //[ ] reserved
286 * LPVOID* ppvObject) //[out] Resulting Interface
289 HRESULT WINAPI
CAdminToolsFolder::GetUIObjectOf(HWND hwndOwner
, UINT cidl
, LPCITEMIDLIST
*apidl
,
290 REFIID riid
, UINT
* prgfInOut
, LPVOID
* ppvOut
)
293 CComPtr
<IUnknown
> pObj
;
294 HRESULT hr
= E_INVALIDARG
;
296 TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n",
297 this, hwndOwner
, cidl
, apidl
, shdebugstr_guid (&riid
), prgfInOut
, ppvOut
);
304 if (IsEqualIID (riid
, IID_IContextMenu
))
306 IContextMenu
* pCm
= NULL
;
307 hr
= CDefFolderMenu_Create2(pidlRoot
, hwndOwner
, cidl
, apidl
, static_cast<IShellFolder
*>(this), NULL
, 0, NULL
, &pCm
);
310 else if (IsEqualIID (riid
, IID_IDataObject
) && (cidl
>= 1))
312 IDataObject
* pDo
= NULL
;
313 hr
= IDataObject_Constructor(hwndOwner
, pidlRoot
, apidl
, cidl
, &pDo
);
316 else if (IsEqualIID (riid
, IID_IExtractIconA
) && (cidl
== 1))
318 pidl
= ILCombine (pidlRoot
, apidl
[0]);
319 pObj
= (LPUNKNOWN
) IExtractIconA_Constructor (pidl
);
323 else if (IsEqualIID (riid
, IID_IExtractIconW
) && (cidl
== 1))
325 pidl
= ILCombine (pidlRoot
, apidl
[0]);
326 pObj
= (LPUNKNOWN
) IExtractIconW_Constructor (pidl
);
330 else if (IsEqualIID (riid
, IID_IDropTarget
) && (cidl
>= 1))
332 IDropTarget
* pDt
= NULL
;
333 hr
= this->QueryInterface(IID_PPV_ARG(IDropTarget
, &pDt
));
336 else if ((IsEqualIID(riid
, IID_IShellLinkW
) ||
337 IsEqualIID(riid
, IID_IShellLinkA
)) && (cidl
== 1))
339 pidl
= ILCombine (pidlRoot
, apidl
[0]);
340 hr
= IShellLink_ConstructFromFile(NULL
, riid
, pidl
, reinterpret_cast<LPVOID
*>(&pObj
));
346 if (SUCCEEDED(hr
) && !pObj
)
349 *ppvOut
= pObj
.Detach();
350 TRACE ("(%p)->hr=0x%08x\n", this, hr
);
354 /**************************************************************************
355 * CAdminToolsFolder::GetDisplayNameOf
358 HRESULT WINAPI
CAdminToolsFolder::GetDisplayNameOf(LPCITEMIDLIST pidl
, DWORD dwFlags
, LPSTRRET strRet
)
361 LPWSTR pszPath
, pOffset
;
363 TRACE ("(%p)->(pidl=%p,0x%08x,%p)\n", this, pidl
, dwFlags
, strRet
);
369 pszPath
= (LPWSTR
)CoTaskMemAlloc((MAX_PATH
+ 1) * sizeof(WCHAR
));
371 return E_OUTOFMEMORY
;
373 ZeroMemory(pszPath
, (MAX_PATH
+ 1) * sizeof(WCHAR
));
377 if ((GET_SHGDN_RELATION (dwFlags
) == SHGDN_NORMAL
) &&
378 (GET_SHGDN_FOR (dwFlags
) & SHGDN_FORPARSING
))
379 wcscpy(pszPath
, szTarget
);
380 else if (!HCR_GetClassNameW(CLSID_AdminFolderShortcut
, pszPath
, MAX_PATH
))
383 else if (_ILIsPidlSimple(pidl
))
385 if ((GET_SHGDN_FOR(dwFlags
) & SHGDN_FORPARSING
) &&
386 (GET_SHGDN_RELATION(dwFlags
) != SHGDN_INFOLDER
) &&
389 wcscpy(pszPath
, szTarget
);
390 pOffset
= PathAddBackslashW(pszPath
);
393 if (!_ILSimpleGetTextW(pidl
, pOffset
, MAX_PATH
+ 1 - (pOffset
- pszPath
)))
401 if (_ILSimpleGetTextW(pidl
, pszPath
, MAX_PATH
+ 1))
403 if (SHELL_FS_HideExtension(pszPath
))
404 PathRemoveExtensionW(pszPath
);
410 else if (_ILIsSpecialFolder(pidl
))
412 BOOL bSimplePidl
= _ILIsPidlSimple(pidl
);
416 if (!_ILSimpleGetTextW(pidl
, pszPath
, MAX_PATH
))
419 else if ((dwFlags
& SHGDN_FORPARSING
) && !bSimplePidl
)
423 wcscpy(pszPath
, szTarget
);
424 PathAddBackslashW(pszPath
);
425 len
= wcslen(pszPath
);
427 if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild(this, pidl
, dwFlags
| SHGDN_INFOLDER
, pszPath
+ len
, MAX_PATH
+ 1 - len
)))
429 CoTaskMemFree(pszPath
);
430 return E_OUTOFMEMORY
;
438 strRet
->uType
= STRRET_WSTR
;
439 strRet
->pOleStr
= pszPath
;
440 TRACE ("-- (%p)->(%s,0x%08x)\n", this, debugstr_w(strRet
->pOleStr
), hr
);
443 CoTaskMemFree(pszPath
);
448 /**************************************************************************
449 * CAdminToolsFolder::SetNameOf
450 * Changes the name of a file object or subfolder, possibly changing its item
451 * identifier in the process.
454 * HWND hwndOwner, //[in ] Owner window for output
455 * LPCITEMIDLIST pidl, //[in ] simple pidl of item to change
456 * LPCOLESTR lpszName, //[in ] the items new display name
457 * DWORD dwFlags, //[in ] SHGNO formatting flags
458 * LPITEMIDLIST* ppidlOut) //[out] simple pidl returned
460 HRESULT WINAPI
CAdminToolsFolder::SetNameOf(HWND hwndOwner
, LPCITEMIDLIST pidl
, /* simple pidl */
461 LPCOLESTR lpName
, DWORD dwFlags
, LPITEMIDLIST
* pPidlOut
)
463 FIXME ("(%p)->(%p,pidl=%p,%s,%lu,%p)\n", this, hwndOwner
, pidl
,
464 debugstr_w (lpName
), dwFlags
, pPidlOut
);
469 HRESULT WINAPI
CAdminToolsFolder::GetDefaultSearchGUID(GUID
*pguid
)
471 FIXME ("(%p)\n", this);
475 HRESULT WINAPI
CAdminToolsFolder::EnumSearches(IEnumExtraSearch
** ppenum
)
477 FIXME ("(%p)\n", this);
481 HRESULT WINAPI
CAdminToolsFolder::GetDefaultColumn(DWORD dwRes
, ULONG
*pSort
, ULONG
*pDisplay
)
490 HRESULT WINAPI
CAdminToolsFolder::GetDefaultColumnState(UINT iColumn
, DWORD
*pcsFlags
)
492 if (!pcsFlags
|| iColumn
>= AdminToolsHELLVIEWCOLUMNS
)
494 *pcsFlags
= AdminToolsSFHeader
[iColumn
].pcsFlags
;
499 HRESULT WINAPI
CAdminToolsFolder::GetDetailsEx (LPCITEMIDLIST pidl
, const SHCOLUMNID
*pscid
, VARIANT
*pv
)
501 FIXME ("(%p): stub\n", this);
506 HRESULT WINAPI
CAdminToolsFolder::GetDetailsOf(LPCITEMIDLIST pidl
, UINT iColumn
, SHELLDETAILS
*psd
)
508 WCHAR buffer
[MAX_PATH
] = {0};
511 TRACE("(%p)->(%p %i %p): stub\n", this, pidl
, iColumn
, psd
);
513 if (iColumn
>= AdminToolsHELLVIEWCOLUMNS
)
516 psd
->fmt
= AdminToolsSFHeader
[iColumn
].fmt
;
517 psd
->cxChar
= AdminToolsSFHeader
[iColumn
].cxChar
;
520 psd
->str
.uType
= STRRET_WSTR
;
521 if (LoadStringW(shell32_hInstance
, AdminToolsSFHeader
[iColumn
].colnameid
, buffer
, MAX_PATH
))
522 hr
= SHStrDupW(buffer
, &psd
->str
.pOleStr
);
527 psd
->str
.uType
= STRRET_CSTR
;
531 psd
->str
.uType
= STRRET_WSTR
;
532 hr
= GetDisplayNameOf(pidl
,
533 SHGDN_NORMAL
| SHGDN_INFOLDER
, &psd
->str
);
536 _ILGetFileSize (pidl
, psd
->str
.cStr
, MAX_PATH
);
539 _ILGetFileType (pidl
, psd
->str
.cStr
, MAX_PATH
);
542 _ILGetFileDate (pidl
, psd
->str
.cStr
, MAX_PATH
);
549 HRESULT WINAPI
CAdminToolsFolder::MapColumnToSCID(UINT column
, SHCOLUMNID
*pscid
)
551 FIXME ("(%p): stub\n", this);
555 /************************************************************************
556 * CAdminToolsFolder::GetClassID
558 HRESULT WINAPI
CAdminToolsFolder::GetClassID(CLSID
*lpClassId
)
560 TRACE ("(%p)\n", this);
562 memcpy(lpClassId
, &CLSID_AdminFolderShortcut
, sizeof(CLSID
));
567 /************************************************************************
568 * CAdminToolsFolder::Initialize
571 HRESULT WINAPI
CAdminToolsFolder::Initialize(LPCITEMIDLIST pidl
)
574 SHFree((LPVOID
)pidlRoot
);
576 pidlRoot
= ILClone(pidl
);
580 /**************************************************************************
581 * CAdminToolsFolder::GetCurFolder
583 HRESULT WINAPI
CAdminToolsFolder::GetCurFolder(LPITEMIDLIST
*pidl
)
585 TRACE ("(%p)->(%p)\n", this, pidl
);
587 *pidl
= ILClone (pidlRoot
);