2 * PROJECT: ReactOS shell extensions
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll\shellext\ntobjshex\regfolder.cpp
5 * PURPOSE: NT Object Namespace shell extension
6 * PROGRAMMERS: David Quintana <gigaherz@gmail.com>
10 #include "ntobjenum.h"
14 #define DFM_MERGECONTEXTMENU 1 // uFlags LPQCMINFO
15 #define DFM_INVOKECOMMAND 2 // idCmd pszArgs
16 #define DFM_INVOKECOMMANDEX 12 // idCmd PDFMICS
17 #define DFM_GETDEFSTATICID 14 // idCmd * 0
19 #define SHCIDS_ALLFIELDS 0x80000000L
20 #define SHCIDS_CANONICALONLY 0x10000000L
22 #define GET_SHGDN_FOR(dwFlags) ((DWORD)dwFlags & (DWORD)0x0000FF00)
23 #define GET_SHGDN_RELATION(dwFlags) ((DWORD)dwFlags & (DWORD)0x000000FF)
25 WINE_DEFAULT_DEBUG_CHANNEL(ntobjshex
);
27 // {1C6D6E08-2332-4A7B-A94D-6432DB2B5AE6}
28 const GUID CLSID_RegistryFolder
= { 0x1c6d6e08, 0x2332, 0x4a7b, { 0xa9, 0x4d, 0x64, 0x32, 0xdb, 0x2b, 0x5a, 0xe6 } };
30 // {18A4B504-F6D8-4D8A-8661-6296514C2CF0}
31 static const GUID GUID_RegistryColumns
= { 0x18a4b504, 0xf6d8, 0x4d8a, { 0x86, 0x61, 0x62, 0x96, 0x51, 0x4c, 0x2c, 0xf0 } };
35 REGISTRY_COLUMN_NAME
= 0,
37 REGISTRY_COLUMN_VALUE
,
41 class CRegistryFolderExtractIcon
:
42 public CComObjectRootEx
<CComMultiThreadModelNoCS
>,
45 PCIDLIST_ABSOLUTE m_pcidlFolder
;
46 PCITEMID_CHILD m_pcidlChild
;
49 CRegistryFolderExtractIcon() :
56 virtual ~CRegistryFolderExtractIcon()
59 ILFree((LPITEMIDLIST
) m_pcidlFolder
);
61 ILFree((LPITEMIDLIST
) m_pcidlChild
);
64 HRESULT
Initialize(PCIDLIST_ABSOLUTE parent
, UINT cidl
, PCUITEMID_CHILD_ARRAY apidl
)
66 m_pcidlFolder
= ILClone(parent
);
69 m_pcidlChild
= ILClone(apidl
[0]);
73 virtual HRESULT STDMETHODCALLTYPE
GetIconLocation(
80 const RegPidlEntry
* entry
= (RegPidlEntry
*) m_pcidlChild
;
82 if ((entry
->cb
< sizeof(RegPidlEntry
)) || (entry
->magic
!= REGISTRY_PIDL_MAGIC
))
87 switch (entry
->entryType
)
91 GetModuleFileNameW(g_hInstance
, szIconFile
, cchMax
);
92 *piIndex
= -IDI_REGISTRYKEY
;
96 GetModuleFileNameW(g_hInstance
, szIconFile
, cchMax
);
97 *piIndex
= -IDI_REGISTRYVALUE
;
101 GetModuleFileNameW(g_hInstance
, szIconFile
, cchMax
);
102 *piIndex
= -IDI_NTOBJECTITEM
;
108 virtual HRESULT STDMETHODCALLTYPE
Extract(
115 return SHDefExtractIconW(pszFile
, nIconIndex
, 0, phiconLarge
, phiconSmall
, nIconSize
);
118 DECLARE_NOT_AGGREGATABLE(CRegistryFolderExtractIcon
)
119 DECLARE_PROTECT_FINAL_CONSTRUCT()
121 BEGIN_COM_MAP(CRegistryFolderExtractIcon
)
122 COM_INTERFACE_ENTRY_IID(IID_IExtractIconW
, IExtractIconW
)
127 class CRegistryPidlHelper
130 static HRESULT
CompareIDs(LPARAM lParam
, const RegPidlEntry
* first
, const RegPidlEntry
* second
)
132 if ((lParam
& 0xFFFF0000) == SHCIDS_ALLFIELDS
)
137 int minsize
= min(first
->cb
, second
->cb
);
138 int ord
= memcmp(second
, first
, minsize
);
141 return MAKE_HRESULT(0, 0, (USHORT
) ord
);
143 if (second
->cb
> first
->cb
)
144 return MAKE_HRESULT(0, 0, (USHORT
) 1);
145 if (second
->cb
< first
->cb
)
146 return MAKE_HRESULT(0, 0, (USHORT
) -1);
150 bool canonical
= ((lParam
& 0xFFFF0000) == SHCIDS_CANONICALONLY
);
152 switch (lParam
& 0xFFFF)
154 case REGISTRY_COLUMN_NAME
:
156 bool f1
= (first
->entryType
== REG_ENTRY_KEY
) || (first
->entryType
== REG_ENTRY_ROOT
);
157 bool f2
= (second
->entryType
== REG_ENTRY_KEY
) || (second
->entryType
== REG_ENTRY_ROOT
);
160 return MAKE_HRESULT(0, 0, (USHORT
) -1);
162 return MAKE_HRESULT(0, 0, (USHORT
) 1);
166 // Shortcut: avoid comparing contents if not necessary when the results are not for display.
167 if (second
->entryNameLength
> first
->entryNameLength
)
168 return MAKE_HRESULT(0, 0, (USHORT
) 1);
169 if (second
->entryNameLength
< first
->entryNameLength
)
170 return MAKE_HRESULT(0, 0, (USHORT
) -1);
172 int minlength
= min(first
->entryNameLength
, second
->entryNameLength
);
175 int ord
= memcmp(first
->entryName
, second
->entryName
, minlength
);
177 return MAKE_HRESULT(0, 0, (USHORT
) ord
);
183 int minlength
= min(first
->entryNameLength
, second
->entryNameLength
);
186 int ord
= StrCmpNW(first
->entryName
, second
->entryName
, minlength
/ sizeof(WCHAR
));
188 return MAKE_HRESULT(0, 0, (USHORT
) ord
);
191 if (second
->entryNameLength
> first
->entryNameLength
)
192 return MAKE_HRESULT(0, 0, (USHORT
) 1);
193 if (second
->entryNameLength
< first
->entryNameLength
)
194 return MAKE_HRESULT(0, 0, (USHORT
) -1);
199 case REGISTRY_COLUMN_TYPE
:
201 int ord
= second
->contentType
- first
->contentType
;
203 return MAKE_HRESULT(0, 0, (USHORT
) 1);
205 return MAKE_HRESULT(0, 0, (USHORT
) -1);
209 case REGISTRY_COLUMN_VALUE
:
211 // Can't sort by value
216 DbgPrint("Unsupported sorting mode.\n");
225 static HRESULT
CompareIDs(LPARAM lParam
, const RegPidlEntry
* first
, LPCITEMIDLIST pcidl
)
227 LPCITEMIDLIST p
= pcidl
;
228 RegPidlEntry
* second
= (RegPidlEntry
*) &(p
->mkid
);
229 if ((second
->cb
< sizeof(RegPidlEntry
)) || (second
->magic
!= REGISTRY_PIDL_MAGIC
))
232 return CompareIDs(lParam
, first
, second
);
235 static HRESULT
CompareIDs(LPARAM lParam
, LPCITEMIDLIST pcidl1
, LPCITEMIDLIST pcidl2
)
237 LPCITEMIDLIST p
= pcidl1
;
238 RegPidlEntry
* first
= (RegPidlEntry
*) &(p
->mkid
);
239 if ((first
->cb
< sizeof(RegPidlEntry
)) || (first
->magic
!= REGISTRY_PIDL_MAGIC
))
242 return CompareIDs(lParam
, first
, pcidl2
);
245 static ULONG
ConvertAttributes(const RegPidlEntry
* entry
, PULONG inMask
)
247 ULONG mask
= inMask
? *inMask
: 0xFFFFFFFF;
250 if ((entry
->entryType
== REG_ENTRY_KEY
) ||
251 (entry
->entryType
== REG_ENTRY_ROOT
))
252 flags
|= SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
| SFGAO_BROWSABLE
;
257 static BOOL
IsFolder(LPCITEMIDLIST pcidl
)
259 RegPidlEntry
* entry
= (RegPidlEntry
*) &(pcidl
->mkid
);
260 if ((entry
->cb
< sizeof(RegPidlEntry
)) || (entry
->magic
!= REGISTRY_PIDL_MAGIC
))
263 return (entry
->entryType
== REG_ENTRY_KEY
) ||
264 (entry
->entryType
== REG_ENTRY_ROOT
);
267 static HRESULT
GetInfoFromPidl(LPCITEMIDLIST pcidl
, const RegPidlEntry
** pentry
)
269 RegPidlEntry
* entry
= (RegPidlEntry
*) &(pcidl
->mkid
);
271 if (entry
->cb
< sizeof(RegPidlEntry
))
273 DbgPrint("PCIDL too small %l (required %l)\n", entry
->cb
, sizeof(RegPidlEntry
));
277 if (entry
->magic
!= REGISTRY_PIDL_MAGIC
)
279 DbgPrint("PCIDL magic mismatch %04x (expected %04x)\n", entry
->magic
, REGISTRY_PIDL_MAGIC
);
287 static HRESULT
FormatValueData(DWORD contentType
, PVOID td
, DWORD contentsLength
, PCWSTR
* strContents
)
293 PCWSTR strTodo
= L
"";
294 DWORD bufferLength
= (wcslen(strTodo
) + 1) * sizeof(WCHAR
);
295 PWSTR strValue
= (PWSTR
) CoTaskMemAlloc(bufferLength
);
296 StringCbCopyW(strValue
, bufferLength
, strTodo
);
297 *strContents
= strValue
;
303 PWSTR strValue
= (PWSTR
) CoTaskMemAlloc(contentsLength
+ sizeof(WCHAR
));
304 StringCbCopyNW(strValue
, contentsLength
+ sizeof(WCHAR
), (LPCWSTR
) td
, contentsLength
);
305 *strContents
= strValue
;
310 DWORD bufferLength
= 64 * sizeof(WCHAR
);
311 PWSTR strValue
= (PWSTR
) CoTaskMemAlloc(bufferLength
);
312 StringCbPrintfW(strValue
, bufferLength
, L
"0x%08x (%d)",
313 *(DWORD
*) td
, *(DWORD
*) td
);
314 *strContents
= strValue
;
319 DWORD bufferLength
= 64 * sizeof(WCHAR
);
320 PWSTR strValue
= (PWSTR
) CoTaskMemAlloc(bufferLength
);
321 StringCbPrintfW(strValue
, bufferLength
, L
"0x%016llx (%d)",
322 *(LARGE_INTEGER
*) td
, ((LARGE_INTEGER
*) td
)->QuadPart
);
323 *strContents
= strValue
;
328 PCWSTR strTodo
= L
"<TODO: Convert value for display>";
329 DWORD bufferLength
= (wcslen(strTodo
) + 1) * sizeof(WCHAR
);
330 PWSTR strValue
= (PWSTR
) CoTaskMemAlloc(bufferLength
);
331 StringCbCopyW(strValue
, bufferLength
, strTodo
);
332 *strContents
= strValue
;
338 static HRESULT
FormatContentsForDisplay(const RegPidlEntry
* info
, LPCWSTR ntPath
, PCWSTR
* strContents
)
340 PVOID td
= (((PBYTE
) info
) + FIELD_OFFSET(RegPidlEntry
, entryName
) + info
->entryNameLength
+ sizeof(WCHAR
));
342 if (info
->entryType
== REG_ENTRY_VALUE_WITH_CONTENT
)
344 if (info
->contentsLength
> 0)
346 return FormatValueData(info
->contentType
, td
, info
->contentsLength
, strContents
);
349 else if (info
->entryType
== REG_ENTRY_VALUE
)
353 HRESULT hr
= ReadRegistryValue(NULL
, ntPath
, info
->entryName
, &valueData
, &valueLength
);
354 if (FAILED_UNEXPECTEDLY(hr
))
356 PCWSTR strEmpty
= L
"(Error reading value)";
357 DWORD bufferLength
= (wcslen(strEmpty
) + 1) * sizeof(WCHAR
);
358 PWSTR strValue
= (PWSTR
) CoTaskMemAlloc(bufferLength
);
359 StringCbCopyW(strValue
, bufferLength
, strEmpty
);
360 *strContents
= strValue
;
366 hr
= FormatValueData(info
->contentType
, valueData
, valueLength
, strContents
);
368 CoTaskMemFree(valueData
);
375 PCWSTR strEmpty
= L
"";
376 DWORD bufferLength
= (wcslen(strEmpty
) + 1) * sizeof(WCHAR
);
377 PWSTR strValue
= (PWSTR
) CoTaskMemAlloc(bufferLength
);
378 StringCbCopyW(strValue
, bufferLength
, strEmpty
);
379 *strContents
= strValue
;
383 PCWSTR strEmpty
= L
"(Empty)";
384 DWORD bufferLength
= (wcslen(strEmpty
) + 1) * sizeof(WCHAR
);
385 PWSTR strValue
= (PWSTR
) CoTaskMemAlloc(bufferLength
);
386 StringCbCopyW(strValue
, bufferLength
, strEmpty
);
387 *strContents
= strValue
;
392 //-----------------------------------------------------------------------------
395 CRegistryFolder::CRegistryFolder() :
400 CRegistryFolder::~CRegistryFolder()
407 HRESULT STDMETHODCALLTYPE
CRegistryFolder::ParseDisplayName(
410 LPOLESTR lpszDisplayName
,
413 ULONG
*pdwAttributes
)
424 TRACE("CRegistryFolder::ParseDisplayName name=%S (ntPath=%S)\n", lpszDisplayName
, m_NtPath
);
426 const RegPidlEntry
* info
;
428 HRESULT hr
= GetEnumNTDirectory(m_NtPath
, &it
);
431 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
436 hr
= it
->Next(1, ppidl
, NULL
);
444 hr
= CRegistryPidlHelper::GetInfoFromPidl(*ppidl
, &info
);
445 if (FAILED_UNEXPECTEDLY(hr
))
448 if (StrCmpW(info
->entryName
, lpszDisplayName
) == 0)
454 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
457 if (pchEaten
|| pdwAttributes
)
460 *pchEaten
= wcslen(info
->entryName
);
463 *pdwAttributes
= CRegistryPidlHelper::ConvertAttributes(info
, pdwAttributes
);
469 HRESULT STDMETHODCALLTYPE
CRegistryFolder::EnumObjects(
472 IEnumIDList
**ppenumIDList
)
474 if (wcslen(m_NtPath
) == 0 && m_hRoot
== NULL
)
476 return GetEnumRegistryRoot(ppenumIDList
);
480 return GetEnumRegistryKey(m_NtPath
, m_hRoot
, ppenumIDList
);
484 HRESULT STDMETHODCALLTYPE
CRegistryFolder::BindToObject(
490 const RegPidlEntry
* info
;
492 if (IsEqualIID(riid
, IID_IShellFolder
))
494 HRESULT hr
= CRegistryPidlHelper::GetInfoFromPidl(pidl
, &info
);
495 if (FAILED_UNEXPECTEDLY(hr
))
498 LPITEMIDLIST first
= ILCloneFirst(pidl
);
499 LPCITEMIDLIST rest
= ILGetNext(pidl
);
501 LPITEMIDLIST fullPidl
= ILCombine(m_shellPidl
, first
);
503 CComPtr
<IShellFolder
> psfChild
;
504 if (wcslen(m_NtPath
) == 0 && m_hRoot
== NULL
)
506 hr
= ShellObjectCreatorInit
<CRegistryFolder
>(fullPidl
, L
"", info
->rootKey
, IID_PPV_ARG(IShellFolder
, &psfChild
));
510 WCHAR path
[MAX_PATH
];
512 StringCbCopyW(path
, _countof(path
), m_NtPath
);
514 PathAppendW(path
, info
->entryName
);
516 hr
= ShellObjectCreatorInit
<CRegistryFolder
>(fullPidl
, path
, m_hRoot
, IID_PPV_ARG(IShellFolder
, &psfChild
));
522 if (rest
->mkid
.cb
> 0)
524 return psfChild
->BindToObject(rest
, pbcReserved
, riid
, ppvOut
);
527 return psfChild
->QueryInterface(riid
, ppvOut
);
533 HRESULT STDMETHODCALLTYPE
CRegistryFolder::BindToStorage(
543 HRESULT STDMETHODCALLTYPE
CRegistryFolder::CompareIDs(
548 TRACE("CompareIDs\n");
550 HRESULT hr
= CRegistryPidlHelper::CompareIDs(lParam
, pidl1
, pidl2
);
554 LPCITEMIDLIST rest1
= ILGetNext(pidl1
);
555 LPCITEMIDLIST rest2
= ILGetNext(pidl2
);
557 bool hasNext1
= (rest1
->mkid
.cb
> 0);
558 bool hasNext2
= (rest2
->mkid
.cb
> 0);
560 if (hasNext1
|| hasNext2
)
562 if (hasNext1
&& !hasNext2
)
563 return MAKE_HRESULT(0, 0, (USHORT
) -1);
565 if (hasNext2
&& !hasNext1
)
566 return MAKE_HRESULT(0, 0, (USHORT
) 1);
568 LPCITEMIDLIST first1
= ILCloneFirst(pidl1
);
570 CComPtr
<IShellFolder
> psfNext
;
571 hr
= BindToObject(first1
, NULL
, IID_PPV_ARG(IShellFolder
, &psfNext
));
572 if (FAILED_UNEXPECTEDLY(hr
))
575 return psfNext
->CompareIDs(lParam
, rest1
, rest2
);
581 HRESULT STDMETHODCALLTYPE
CRegistryFolder::CreateViewObject(
586 if (!IsEqualIID(riid
, IID_IShellView
))
587 return E_NOINTERFACE
;
590 sfv
.cbSize
= sizeof(sfv
);
595 return SHCreateShellFolderView(&sfv
, (IShellView
**) ppvOut
);
598 HRESULT STDMETHODCALLTYPE
CRegistryFolder::GetAttributesOf(
600 PCUITEMID_CHILD_ARRAY apidl
,
603 const RegPidlEntry
* info
;
605 TRACE("GetAttributesOf\n");
609 *rgfInOut
&= SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
| SFGAO_BROWSABLE
;
613 for (int i
= 0; i
< (int) cidl
; i
++)
615 PCUITEMID_CHILD pidl
= apidl
[i
];
617 HRESULT hr
= CRegistryPidlHelper::GetInfoFromPidl(pidl
, &info
);
618 if (FAILED_UNEXPECTEDLY(hr
))
621 // Update attributes.
622 *rgfInOut
= CRegistryPidlHelper::ConvertAttributes(info
, rgfInOut
);
628 HRESULT STDMETHODCALLTYPE
CRegistryFolder::GetUIObjectOf(
631 PCUITEMID_CHILD_ARRAY apidl
,
636 TRACE("GetUIObjectOf\n");
638 if (IsEqualIID(riid
, IID_IContextMenu
) ||
639 IsEqualIID(riid
, IID_IContextMenu2
) ||
640 IsEqualIID(riid
, IID_IContextMenu3
))
642 CComPtr
<IContextMenu
> pcm
;
647 int nkeys
= _countof(keys
);
648 if (cidl
== 1 && CRegistryPidlHelper::IsFolder(apidl
[0]))
650 res
= RegOpenKey(HKEY_CLASSES_ROOT
, L
"Folder", keys
+ 0);
651 if (!NT_SUCCESS(res
))
652 return HRESULT_FROM_NT(res
);
659 HRESULT hr
= CDefFolderMenu_Create2(m_shellPidl
, hwndOwner
, cidl
, apidl
, this, DefCtxMenuCallback
, nkeys
, keys
, &pcm
);
660 if (FAILED_UNEXPECTEDLY(hr
))
663 return pcm
->QueryInterface(riid
, ppvOut
);
666 if (IsEqualIID(riid
, IID_IExtractIconW
))
668 return ShellObjectCreatorInit
<CRegistryFolderExtractIcon
>(m_shellPidl
, cidl
, apidl
, riid
, ppvOut
);
671 if (IsEqualIID(riid
, IID_IDataObject
))
673 return CIDLData_CreateFromIDArray(m_shellPidl
, cidl
, apidl
, (IDataObject
**) ppvOut
);
676 if (IsEqualIID(riid
, IID_IQueryAssociations
))
678 if (cidl
== 1 && CRegistryPidlHelper::IsFolder(apidl
[0]))
680 CComPtr
<IQueryAssociations
> pqa
;
681 HRESULT hr
= AssocCreate(CLSID_QueryAssociations
, IID_PPV_ARG(IQueryAssociations
, &pqa
));
682 if (FAILED_UNEXPECTEDLY(hr
))
685 hr
= pqa
->Init(ASSOCF_INIT_DEFAULTTOFOLDER
, L
"NTObjShEx.RegFolder", NULL
, hwndOwner
);
686 if (FAILED_UNEXPECTEDLY(hr
))
689 return pqa
->QueryInterface(riid
, ppvOut
);
696 HRESULT STDMETHODCALLTYPE
CRegistryFolder::GetDisplayNameOf(
701 const RegPidlEntry
* info
;
703 TRACE("GetDisplayNameOf %p\n", pidl
);
705 HRESULT hr
= CRegistryPidlHelper::GetInfoFromPidl(pidl
, &info
);
706 if (FAILED_UNEXPECTEDLY(hr
))
709 if ((GET_SHGDN_RELATION(uFlags
) == SHGDN_NORMAL
) &&
710 (GET_SHGDN_FOR(uFlags
) & SHGDN_FORPARSING
))
712 WCHAR path
[MAX_PATH
] = { 0 };
714 hr
= GetFullName(m_shellPidl
, uFlags
, path
, _countof(path
));
715 if (FAILED_UNEXPECTEDLY(hr
))
718 PathAppendW(path
, info
->entryName
);
720 hr
= MakeStrRetFromString(path
, lpName
);
721 if (FAILED_UNEXPECTEDLY(hr
))
724 LPCITEMIDLIST pidlFirst
= ILCloneFirst(pidl
);
725 LPCITEMIDLIST pidlNext
= ILGetNext(pidl
);
727 if (pidlNext
&& pidlNext
->mkid
.cb
> 0)
729 CComPtr
<IShellFolder
> psfChild
;
730 hr
= BindToObject(pidlFirst
, NULL
, IID_PPV_ARG(IShellFolder
, &psfChild
));
731 if (FAILED_UNEXPECTEDLY(hr
))
734 WCHAR temp
[MAX_PATH
];
737 hr
= psfChild
->GetDisplayNameOf(pidlNext
, uFlags
| SHGDN_INFOLDER
, &childName
);
738 if (FAILED_UNEXPECTEDLY(hr
))
741 hr
= StrRetToBufW(&childName
, pidlNext
, temp
, _countof(temp
));
742 if (FAILED_UNEXPECTEDLY(hr
))
745 PathAppendW(path
, temp
);
748 ILFree((LPITEMIDLIST
) pidlFirst
);
752 MakeStrRetFromString(info
->entryName
, info
->entryNameLength
, lpName
);
758 HRESULT STDMETHODCALLTYPE
CRegistryFolder::SetNameOf(
763 LPITEMIDLIST
*ppidlOut
)
770 HRESULT STDMETHODCALLTYPE
CRegistryFolder::GetClassID(CLSID
*lpClassId
)
775 *lpClassId
= CLSID_RegistryFolder
;
780 HRESULT STDMETHODCALLTYPE
CRegistryFolder::Initialize(LPCITEMIDLIST pidl
)
782 m_shellPidl
= ILClone(pidl
);
785 StringCbCopy(m_NtPath
, _countof(m_NtPath
), L
"");
790 HRESULT STDMETHODCALLTYPE
CRegistryFolder::Initialize(LPCITEMIDLIST pidl
, PCWSTR ntPath
, HKEY hRoot
)
792 m_shellPidl
= ILClone(pidl
);
795 StringCbCopy(m_NtPath
, _countof(m_NtPath
), ntPath
);
800 HRESULT STDMETHODCALLTYPE
CRegistryFolder::GetCurFolder(LPITEMIDLIST
* pidl
)
803 *pidl
= ILClone(m_shellPidl
);
810 HRESULT STDMETHODCALLTYPE
CRegistryFolder::GetDefaultSearchGUID(
817 HRESULT STDMETHODCALLTYPE
CRegistryFolder::EnumSearches(
818 IEnumExtraSearch
**ppenum
)
824 HRESULT STDMETHODCALLTYPE
CRegistryFolder::GetDefaultColumn(
836 HRESULT STDMETHODCALLTYPE
CRegistryFolder::GetDefaultColumnState(
838 SHCOLSTATEF
*pcsFlags
)
842 case REGISTRY_COLUMN_NAME
:
843 *pcsFlags
= SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
;
845 case REGISTRY_COLUMN_TYPE
:
846 *pcsFlags
= SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
;
848 case REGISTRY_COLUMN_VALUE
:
849 *pcsFlags
= SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
| SHCOLSTATE_SLOW
;
856 HRESULT STDMETHODCALLTYPE
CRegistryFolder::GetDetailsEx(
858 const SHCOLUMNID
*pscid
,
861 const RegPidlEntry
* info
;
863 TRACE("GetDetailsEx\n");
867 HRESULT hr
= CRegistryPidlHelper::GetInfoFromPidl(pidl
, &info
);
868 if (FAILED_UNEXPECTEDLY(hr
))
871 static const GUID storage
= PSGUID_STORAGE
;
872 if (IsEqualGUID(pscid
->fmtid
, storage
))
874 if (pscid
->pid
== PID_STG_NAME
)
876 if (info
->entryNameLength
> 0)
878 return MakeVariantString(pv
, info
->entryName
);
880 return MakeVariantString(pv
, L
"(Default)");
882 else if (pscid
->pid
== PID_STG_STORAGETYPE
)
884 if (info
->entryType
== REG_ENTRY_ROOT
)
886 return MakeVariantString(pv
, L
"Key");
889 if (info
->entryType
== REG_ENTRY_KEY
)
891 if (info
->contentsLength
> 0)
893 PWSTR td
= (PWSTR
) (((PBYTE
) info
) + FIELD_OFFSET(RegPidlEntry
, entryName
) + info
->entryNameLength
+ sizeof(WCHAR
));
895 return MakeVariantString(pv
, td
);
897 return MakeVariantString(pv
, L
"Key");
900 return MakeVariantString(pv
, RegistryTypeNames
[info
->contentType
]);
902 else if (pscid
->pid
== PID_STG_CONTENTS
)
904 PCWSTR strValueContents
;
906 hr
= CRegistryPidlHelper::FormatContentsForDisplay(info
, m_NtPath
, &strValueContents
);
907 if (FAILED_UNEXPECTEDLY(hr
))
916 hr
= MakeVariantString(pv
, strValueContents
);
918 CoTaskMemFree((PVOID
) strValueContents
);
929 HRESULT STDMETHODCALLTYPE
CRegistryFolder::GetDetailsOf(
934 const RegPidlEntry
* info
;
936 TRACE("GetDetailsOf\n");
940 HRESULT hr
= CRegistryPidlHelper::GetInfoFromPidl(pidl
, &info
);
941 if (FAILED_UNEXPECTEDLY(hr
))
946 case REGISTRY_COLUMN_NAME
:
947 psd
->fmt
= LVCFMT_LEFT
;
949 if (info
->entryNameLength
> 0)
951 return MakeStrRetFromString(info
->entryName
, info
->entryNameLength
, &(psd
->str
));
953 return MakeStrRetFromString(L
"(Default)", &(psd
->str
));
955 case REGISTRY_COLUMN_TYPE
:
956 psd
->fmt
= LVCFMT_LEFT
;
958 if (info
->entryType
== REG_ENTRY_ROOT
)
960 return MakeStrRetFromString(L
"Key", &(psd
->str
));
963 if (info
->entryType
== REG_ENTRY_KEY
)
965 if (info
->contentsLength
> 0)
967 PWSTR td
= (PWSTR
) (((PBYTE
) info
) + FIELD_OFFSET(RegPidlEntry
, entryName
) + info
->entryNameLength
+ sizeof(WCHAR
));
969 return MakeStrRetFromString(td
, info
->contentsLength
, &(psd
->str
));
972 return MakeStrRetFromString(L
"Key", &(psd
->str
));
975 return MakeStrRetFromString(RegistryTypeNames
[info
->entryType
], &(psd
->str
));
977 case REGISTRY_COLUMN_VALUE
:
978 psd
->fmt
= LVCFMT_LEFT
;
980 PCWSTR strValueContents
;
982 hr
= CRegistryPidlHelper::FormatContentsForDisplay(info
, m_NtPath
, &strValueContents
);
983 if (FAILED_UNEXPECTEDLY(hr
))
988 return MakeStrRetFromString(L
"(Empty)", &(psd
->str
));
991 hr
= MakeStrRetFromString(strValueContents
, &(psd
->str
));
993 CoTaskMemFree((PVOID
) strValueContents
);
1002 case REGISTRY_COLUMN_NAME
:
1003 psd
->fmt
= LVCFMT_LEFT
;
1006 // TODO: Make localizable
1007 MakeStrRetFromString(L
"Object Name", &(psd
->str
));
1009 case REGISTRY_COLUMN_TYPE
:
1010 psd
->fmt
= LVCFMT_LEFT
;
1013 // TODO: Make localizable
1014 MakeStrRetFromString(L
"Content Type", &(psd
->str
));
1016 case REGISTRY_COLUMN_VALUE
:
1017 psd
->fmt
= LVCFMT_LEFT
;
1020 // TODO: Make localizable
1021 MakeStrRetFromString(L
"Value", &(psd
->str
));
1026 return E_INVALIDARG
;
1029 HRESULT STDMETHODCALLTYPE
CRegistryFolder::MapColumnToSCID(
1033 static const GUID storage
= PSGUID_STORAGE
;
1036 case REGISTRY_COLUMN_NAME
:
1037 pscid
->fmtid
= storage
;
1038 pscid
->pid
= PID_STG_NAME
;
1040 case REGISTRY_COLUMN_TYPE
:
1041 pscid
->fmtid
= storage
;
1042 pscid
->pid
= PID_STG_STORAGETYPE
;
1044 case REGISTRY_COLUMN_VALUE
:
1045 pscid
->fmtid
= storage
;
1046 pscid
->pid
= PID_STG_CONTENTS
;
1049 return E_INVALIDARG
;
1052 HRESULT STDMETHODCALLTYPE
CRegistryFolder::MessageSFVCB(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1056 case SFVM_DEFVIEWMODE
:
1058 FOLDERVIEWMODE
* pViewMode
= (FOLDERVIEWMODE
*) lParam
;
1059 *pViewMode
= FVM_DETAILS
;
1062 case SFVM_COLUMNCLICK
:
1064 case SFVM_BACKGROUNDENUM
:
1070 HRESULT
CRegistryFolder::DefCtxMenuCallback(IShellFolder
* /*psf*/, HWND
/*hwnd*/, IDataObject
* /*pdtobj*/, UINT uMsg
, WPARAM
/*wParam*/, LPARAM
/*lParam*/)
1074 case DFM_MERGECONTEXTMENU
:
1076 case DFM_INVOKECOMMAND
:
1077 case DFM_INVOKECOMMANDEX
:
1078 case DFM_GETDEFSTATICID
: // Required for Windows 7 to pick a default