2 * PROJECT: ReactOS shell extensions
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/shellext/ntobjshex/ntobjfolder.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 // {845B0FB2-66E0-416B-8F91-314E23F7C12D}
28 const GUID CLSID_NtObjectFolder
= { 0x845b0fb2, 0x66e0, 0x416b, { 0x8f, 0x91, 0x31, 0x4e, 0x23, 0xf7, 0xc1, 0x2d } };
30 // {F4C430C3-3A8D-4B56-A018-E598DA60C2E0}
31 static const GUID GUID_NtObjectColumns
= { 0xf4c430c3, 0x3a8d, 0x4b56, { 0xa0, 0x18, 0xe5, 0x98, 0xda, 0x60, 0xc2, 0xe0 } };
35 NTOBJECT_COLUMN_NAME
= 0,
37 NTOBJECT_COLUMN_LINKTARGET
,
41 class CNtObjectFolderExtractIcon
:
42 public CComObjectRootEx
<CComMultiThreadModelNoCS
>,
45 PCITEMID_CHILD m_pcidlChild
;
49 CNtObjectFolderExtractIcon() :
50 m_pcidlChild(NULL
), m_NtPath(NULL
)
55 virtual ~CNtObjectFolderExtractIcon()
58 ILFree((LPITEMIDLIST
) m_pcidlChild
);
61 HRESULT
Initialize(LPCWSTR ntPath
, UINT cidl
, PCUITEMID_CHILD_ARRAY apidl
)
66 m_pcidlChild
= ILClone(apidl
[0]);
70 virtual HRESULT STDMETHODCALLTYPE
GetIconLocation(
77 const NtPidlEntry
* entry
= (NtPidlEntry
*) m_pcidlChild
;
79 if ((entry
->cb
< sizeof(NtPidlEntry
)) || (entry
->magic
!= NT_OBJECT_PIDL_MAGIC
))
84 switch (entry
->objectType
)
86 case DIRECTORY_OBJECT
:
87 case SYMBOLICLINK_OBJECT
:
88 GetModuleFileNameW(g_hInstance
, szIconFile
, cchMax
);
89 *piIndex
= -((uFlags
& GIL_OPENICON
) ? IDI_NTOBJECTDIROPEN
: IDI_NTOBJECTDIR
);
93 GetModuleFileNameW(g_hInstance
, szIconFile
, cchMax
);
94 *piIndex
= -IDI_NTOBJECTDEVICE
;
98 GetModuleFileNameW(g_hInstance
, szIconFile
, cchMax
);
99 *piIndex
= -IDI_NTOBJECTPORT
;
103 GetModuleFileNameW(g_hInstance
, szIconFile
, cchMax
);
104 *piIndex
= -IDI_REGISTRYKEY
;
108 GetModuleFileNameW(g_hInstance
, szIconFile
, cchMax
);
109 *piIndex
= -IDI_NTOBJECTITEM
;
115 virtual HRESULT STDMETHODCALLTYPE
Extract(
122 return SHDefExtractIconW(pszFile
, nIconIndex
, 0, phiconLarge
, phiconSmall
, nIconSize
);
125 DECLARE_NOT_AGGREGATABLE(CNtObjectFolderExtractIcon
)
126 DECLARE_PROTECT_FINAL_CONSTRUCT()
128 BEGIN_COM_MAP(CNtObjectFolderExtractIcon
)
129 COM_INTERFACE_ENTRY_IID(IID_IExtractIconW
, IExtractIconW
)
134 class CNtObjectPidlHelper
137 static HRESULT
CompareIDs(LPARAM lParam
, const NtPidlEntry
* first
, const NtPidlEntry
* second
)
139 if ((lParam
& 0xFFFF0000) == SHCIDS_ALLFIELDS
)
144 int minsize
= min(first
->cb
, second
->cb
);
145 int ord
= memcmp(second
, first
, minsize
);
148 return MAKE_HRESULT(0, 0, (USHORT
) ord
);
150 if (second
->cb
> first
->cb
)
151 return MAKE_HRESULT(0, 0, (USHORT
) 1);
152 if (second
->cb
< first
->cb
)
153 return MAKE_HRESULT(0, 0, (USHORT
) -1);
157 bool canonical
= ((lParam
& 0xFFFF0000) == SHCIDS_CANONICALONLY
);
159 switch (lParam
& 0xFFFF)
161 case NTOBJECT_COLUMN_NAME
:
163 bool f1
= (first
->objectType
== KEY_OBJECT
) || (first
->objectType
== DIRECTORY_OBJECT
);
164 bool f2
= (second
->objectType
== KEY_OBJECT
) || (second
->objectType
== DIRECTORY_OBJECT
);
167 return MAKE_HRESULT(0, 0, (USHORT
) -1);
169 return MAKE_HRESULT(0, 0, (USHORT
) 1);
173 // Shortcut: avoid comparing contents if not necessary when the results are not for display.
174 if (second
->entryNameLength
> first
->entryNameLength
)
175 return MAKE_HRESULT(0, 0, (USHORT
) 1);
176 if (second
->entryNameLength
< first
->entryNameLength
)
177 return MAKE_HRESULT(0, 0, (USHORT
) -1);
179 int minlength
= min(first
->entryNameLength
, second
->entryNameLength
);
182 int ord
= memcmp(first
->entryName
, second
->entryName
, minlength
);
184 return MAKE_HRESULT(0, 0, (USHORT
) ord
);
190 int minlength
= min(first
->entryNameLength
, second
->entryNameLength
);
193 int ord
= StrCmpNW(first
->entryName
, second
->entryName
, minlength
/ sizeof(WCHAR
));
195 return MAKE_HRESULT(0, 0, (USHORT
) ord
);
198 if (second
->entryNameLength
> first
->entryNameLength
)
199 return MAKE_HRESULT(0, 0, (USHORT
) 1);
200 if (second
->entryNameLength
< first
->entryNameLength
)
201 return MAKE_HRESULT(0, 0, (USHORT
) -1);
206 case NTOBJECT_COLUMN_TYPE
:
208 int ord
= second
->objectType
- first
->objectType
;
210 return MAKE_HRESULT(0, 0, (USHORT
) 1);
212 return MAKE_HRESULT(0, 0, (USHORT
) -1);
216 case NTOBJECT_COLUMN_LINKTARGET
:
218 // Can't sort by value
223 DbgPrint("Unsupported sorting mode.\n");
232 static HRESULT
CompareIDs(LPARAM lParam
, const NtPidlEntry
* first
, LPCITEMIDLIST pcidl
)
234 LPCITEMIDLIST p
= pcidl
;
235 NtPidlEntry
* second
= (NtPidlEntry
*) &(p
->mkid
);
236 if ((second
->cb
< sizeof(NtPidlEntry
)) || (second
->magic
!= NT_OBJECT_PIDL_MAGIC
))
239 return CompareIDs(lParam
, first
, second
);
242 static HRESULT
CompareIDs(LPARAM lParam
, LPCITEMIDLIST pcidl1
, LPCITEMIDLIST pcidl2
)
244 LPCITEMIDLIST p
= pcidl1
;
245 NtPidlEntry
* first
= (NtPidlEntry
*) &(p
->mkid
);
246 if ((first
->cb
< sizeof(NtPidlEntry
)) || (first
->magic
!= NT_OBJECT_PIDL_MAGIC
))
249 return CompareIDs(lParam
, first
, pcidl2
);
252 static ULONG
ConvertAttributes(const NtPidlEntry
* entry
, PULONG inMask
)
254 ULONG mask
= inMask
? *inMask
: 0xFFFFFFFF;
255 ULONG flags
= SFGAO_HASPROPSHEET
| SFGAO_CANLINK
;
257 if (entry
->objectType
== DIRECTORY_OBJECT
)
258 flags
|= SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
| SFGAO_BROWSABLE
;
260 if (entry
->objectType
== SYMBOLICLINK_OBJECT
)
261 flags
|= SFGAO_LINK
| SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
| SFGAO_BROWSABLE
;
263 if (entry
->objectType
== KEY_OBJECT
)
264 flags
|= SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
| SFGAO_BROWSABLE
;
269 static BOOL
IsFolder(LPCITEMIDLIST pcidl
)
271 NtPidlEntry
* entry
= (NtPidlEntry
*) &(pcidl
->mkid
);
272 if ((entry
->cb
< sizeof(NtPidlEntry
)) || (entry
->magic
!= NT_OBJECT_PIDL_MAGIC
))
275 return (entry
->objectType
== DIRECTORY_OBJECT
) ||
276 (entry
->objectType
== SYMBOLICLINK_OBJECT
) ||
277 (entry
->objectType
== KEY_OBJECT
);
280 static HRESULT
GetInfoFromPidl(LPCITEMIDLIST pcidl
, const NtPidlEntry
** pentry
)
282 NtPidlEntry
* entry
= (NtPidlEntry
*) &(pcidl
->mkid
);
284 if (entry
->cb
< sizeof(NtPidlEntry
))
286 DbgPrint("PCIDL too small %l (required %l)\n", entry
->cb
, sizeof(NtPidlEntry
));
290 if (entry
->magic
!= NT_OBJECT_PIDL_MAGIC
)
292 DbgPrint("PCIDL magic mismatch %04x (expected %04x)\n", entry
->magic
, NT_OBJECT_PIDL_MAGIC
);
301 //-----------------------------------------------------------------------------
304 CNtObjectFolder::CNtObjectFolder() :
309 CNtObjectFolder::~CNtObjectFolder()
316 HRESULT STDMETHODCALLTYPE
CNtObjectFolder::ParseDisplayName(
319 LPOLESTR lpszDisplayName
,
322 ULONG
*pdwAttributes
)
333 TRACE("CNtObjectFolder::ParseDisplayName name=%S (ntPath=%S)\n", lpszDisplayName
, m_NtPath
);
335 const NtPidlEntry
* info
;
337 HRESULT hr
= GetEnumNTDirectory(m_NtPath
, &it
);
343 hr
= it
->Next(1, ppidl
, NULL
);
351 hr
= CNtObjectPidlHelper::GetInfoFromPidl(*ppidl
, &info
);
352 if (FAILED_UNEXPECTEDLY(hr
))
355 if (StrCmpW(info
->entryName
, lpszDisplayName
) == 0)
361 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
364 if (pchEaten
|| pdwAttributes
)
367 *pchEaten
= wcslen(info
->entryName
);
370 *pdwAttributes
= CNtObjectPidlHelper::ConvertAttributes(info
, pdwAttributes
);
376 HRESULT STDMETHODCALLTYPE
CNtObjectFolder::EnumObjects(
379 IEnumIDList
**ppenumIDList
)
381 return GetEnumNTDirectory(m_NtPath
, ppenumIDList
);
384 HRESULT STDMETHODCALLTYPE
CNtObjectFolder::BindToObject(
390 const NtPidlEntry
* info
;
392 if (IsEqualIID(riid
, IID_IShellFolder
))
394 HRESULT hr
= CNtObjectPidlHelper::GetInfoFromPidl(pidl
, &info
);
395 if (FAILED_UNEXPECTEDLY(hr
))
398 WCHAR path
[MAX_PATH
];
400 StringCbCopyW(path
, _countof(path
), m_NtPath
);
402 PathAppendW(path
, info
->entryName
);
404 LPITEMIDLIST first
= ILCloneFirst(pidl
);
405 LPCITEMIDLIST rest
= ILGetNext(pidl
);
407 LPITEMIDLIST fullPidl
= ILCombine(m_shellPidl
, first
);
409 if (info
->objectType
== SYMBOLICLINK_OBJECT
)
411 WCHAR wbLink
[MAX_PATH
] = { 0 };
413 RtlInitEmptyUnicodeString(&link
, wbLink
, sizeof(wbLink
));
415 hr
= GetNTObjectSymbolicLinkTarget(m_NtPath
, info
->entryName
, &link
);
416 if (FAILED_UNEXPECTEDLY(hr
))
421 if (link
.Buffer
[1] == L
':' && isalphaW(link
.Buffer
[0]))
423 CComPtr
<IShellFolder
> psfDesktop
;
424 hr
= SHGetDesktopFolder(&psfDesktop
);
425 if (FAILED_UNEXPECTEDLY(hr
))
428 hr
= psfDesktop
->ParseDisplayName(NULL
, NULL
, path
, NULL
, &first
, NULL
);
429 if (FAILED_UNEXPECTEDLY(hr
))
432 return psfDesktop
->BindToObject(rest
, pbcReserved
, riid
, ppvOut
);
435 StringCbCopyW(path
, _countof(path
), L
"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{845B0FB2-66E0-416B-8F91-314E23F7C12D}");
436 PathAppend(path
, link
.Buffer
);
438 CComPtr
<IShellFolder
> psfDesktop
;
439 hr
= SHGetDesktopFolder(&psfDesktop
);
440 if (FAILED_UNEXPECTEDLY(hr
))
443 hr
= psfDesktop
->ParseDisplayName(NULL
, NULL
, path
, NULL
, &first
, NULL
);
444 if (FAILED_UNEXPECTEDLY(hr
))
453 CComPtr
<IShellFolder
> psfChild
;
455 if (info
->objectType
== KEY_OBJECT
)
457 hr
= ShellObjectCreatorInit
<CRegistryFolder
>(fullPidl
, path
, (HKEY
) NULL
, IID_PPV_ARG(IShellFolder
, &psfChild
));
461 hr
= ShellObjectCreatorInit
<CNtObjectFolder
>(fullPidl
, path
, IID_PPV_ARG(IShellFolder
, &psfChild
));
467 if (rest
->mkid
.cb
> 0)
469 return psfChild
->BindToObject(rest
, pbcReserved
, riid
, ppvOut
);
472 return psfChild
->QueryInterface(riid
, ppvOut
);
478 HRESULT STDMETHODCALLTYPE
CNtObjectFolder::BindToStorage(
488 HRESULT STDMETHODCALLTYPE
CNtObjectFolder::CompareIDs(
493 TRACE("CompareIDs\n");
495 HRESULT hr
= CNtObjectPidlHelper::CompareIDs(lParam
, pidl1
, pidl2
);
499 LPCITEMIDLIST rest1
= ILGetNext(pidl1
);
500 LPCITEMIDLIST rest2
= ILGetNext(pidl2
);
502 bool hasNext1
= (rest1
->mkid
.cb
> 0);
503 bool hasNext2
= (rest2
->mkid
.cb
> 0);
505 if (hasNext1
|| hasNext2
)
507 if (hasNext1
&& !hasNext2
)
508 return MAKE_HRESULT(0, 0, (USHORT
) -1);
510 if (hasNext2
&& !hasNext1
)
511 return MAKE_HRESULT(0, 0, (USHORT
) 1);
513 LPCITEMIDLIST first1
= ILCloneFirst(pidl1
);
515 CComPtr
<IShellFolder
> psfNext
;
516 hr
= BindToObject(first1
, NULL
, IID_PPV_ARG(IShellFolder
, &psfNext
));
517 if (FAILED_UNEXPECTEDLY(hr
))
520 return psfNext
->CompareIDs(lParam
, rest1
, rest2
);
526 HRESULT STDMETHODCALLTYPE
CNtObjectFolder::CreateViewObject(
531 if (!IsEqualIID(riid
, IID_IShellView
))
532 return E_NOINTERFACE
;
535 sfv
.cbSize
= sizeof(sfv
);
540 return SHCreateShellFolderView(&sfv
, (IShellView
**) ppvOut
);
543 HRESULT STDMETHODCALLTYPE
CNtObjectFolder::GetAttributesOf(
545 PCUITEMID_CHILD_ARRAY apidl
,
548 const NtPidlEntry
* info
;
550 TRACE("GetAttributesOf %d\n", cidl
);
554 *rgfInOut
&= SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
| SFGAO_BROWSABLE
;
558 for (int i
= 0; i
< (int) cidl
; i
++)
560 PCUITEMID_CHILD pidl
= apidl
[i
];
562 HRESULT hr
= CNtObjectPidlHelper::GetInfoFromPidl(pidl
, &info
);
563 if (FAILED_UNEXPECTEDLY(hr
))
566 // Update attributes.
567 *rgfInOut
= CNtObjectPidlHelper::ConvertAttributes(info
, rgfInOut
);
573 HRESULT STDMETHODCALLTYPE
CNtObjectFolder::GetUIObjectOf(
576 PCUITEMID_CHILD_ARRAY apidl
,
582 TRACE("GetUIObjectOf\n");
584 if (IsEqualIID(riid
, IID_IContextMenu
) ||
585 IsEqualIID(riid
, IID_IContextMenu2
) ||
586 IsEqualIID(riid
, IID_IContextMenu3
))
588 CComPtr
<IContextMenu
> pcm
;
592 int nkeys
= _countof(keys
);
593 if (cidl
== 1 && CNtObjectPidlHelper::IsFolder(apidl
[0]))
595 res
= RegOpenKey(HKEY_CLASSES_ROOT
, L
"Folder", keys
+ 0);
596 if (!NT_SUCCESS(res
))
597 return HRESULT_FROM_NT(res
);
604 HRESULT hr
= CDefFolderMenu_Create2(m_shellPidl
, hwndOwner
, cidl
, apidl
, this, DefCtxMenuCallback
, nkeys
, keys
, &pcm
);
605 if (FAILED_UNEXPECTEDLY(hr
))
608 return pcm
->QueryInterface(riid
, ppvOut
);
611 if (IsEqualIID(riid
, IID_IExtractIconW
))
613 return ShellObjectCreatorInit
<CNtObjectFolderExtractIcon
>(m_NtPath
, cidl
, apidl
, riid
, ppvOut
);
616 if (IsEqualIID(riid
, IID_IDataObject
))
618 return CIDLData_CreateFromIDArray(m_shellPidl
, cidl
, apidl
, (IDataObject
**) ppvOut
);
621 if (IsEqualIID(riid
, IID_IQueryAssociations
))
623 if (cidl
== 1 && CNtObjectPidlHelper::IsFolder(apidl
[0]))
625 CComPtr
<IQueryAssociations
> pqa
;
626 HRESULT hr
= AssocCreate(CLSID_QueryAssociations
, IID_PPV_ARG(IQueryAssociations
, &pqa
));
627 if (FAILED_UNEXPECTEDLY(hr
))
630 hr
= pqa
->Init(ASSOCF_INIT_DEFAULTTOFOLDER
, L
"NTObjShEx.NTDirectory", NULL
, hwndOwner
);
631 if (FAILED_UNEXPECTEDLY(hr
))
634 return pqa
->QueryInterface(riid
, ppvOut
);
641 HRESULT STDMETHODCALLTYPE
CNtObjectFolder::GetDisplayNameOf(
646 const NtPidlEntry
* info
;
648 TRACE("GetDisplayNameOf %p\n", pidl
);
650 HRESULT hr
= CNtObjectPidlHelper::GetInfoFromPidl(pidl
, &info
);
651 if (FAILED_UNEXPECTEDLY(hr
))
654 if ((GET_SHGDN_RELATION(uFlags
) == SHGDN_NORMAL
) &&
655 (GET_SHGDN_FOR(uFlags
) & SHGDN_FORPARSING
))
657 WCHAR path
[MAX_PATH
] = { 0 };
659 hr
= GetFullName(m_shellPidl
, uFlags
, path
, _countof(path
));
660 if (FAILED_UNEXPECTEDLY(hr
))
663 PathAppendW(path
, info
->entryName
);
665 hr
= MakeStrRetFromString(path
, lpName
);
666 if (FAILED_UNEXPECTEDLY(hr
))
669 LPCITEMIDLIST pidlFirst
= ILCloneFirst(pidl
);
670 LPCITEMIDLIST pidlNext
= ILGetNext(pidl
);
672 if (pidlNext
&& pidlNext
->mkid
.cb
> 0)
674 CComPtr
<IShellFolder
> psfChild
;
675 hr
= BindToObject(pidlFirst
, NULL
, IID_PPV_ARG(IShellFolder
, &psfChild
));
676 if (FAILED_UNEXPECTEDLY(hr
))
679 WCHAR temp
[MAX_PATH
];
682 hr
= psfChild
->GetDisplayNameOf(pidlNext
, uFlags
| SHGDN_INFOLDER
, &childName
);
683 if (FAILED_UNEXPECTEDLY(hr
))
686 hr
= StrRetToBufW(&childName
, pidlNext
, temp
, _countof(temp
));
687 if (FAILED_UNEXPECTEDLY(hr
))
690 PathAppendW(path
, temp
);
693 ILFree((LPITEMIDLIST
) pidlFirst
);
697 MakeStrRetFromString(info
->entryName
, info
->entryNameLength
, lpName
);
703 HRESULT STDMETHODCALLTYPE
CNtObjectFolder::SetNameOf(
708 LPITEMIDLIST
*ppidlOut
)
715 HRESULT STDMETHODCALLTYPE
CNtObjectFolder::GetClassID(CLSID
*lpClassId
)
720 *lpClassId
= CLSID_NtObjectFolder
;
725 HRESULT STDMETHODCALLTYPE
CNtObjectFolder::Initialize(LPCITEMIDLIST pidl
)
727 m_shellPidl
= ILClone(pidl
);
729 StringCbCopy(m_NtPath
, _countof(m_NtPath
), L
"\\");
735 HRESULT STDMETHODCALLTYPE
CNtObjectFolder::Initialize(LPCITEMIDLIST pidl
, PCWSTR ntPath
)
737 m_shellPidl
= ILClone(pidl
);
739 StringCbCopy(m_NtPath
, _countof(m_NtPath
), ntPath
);
745 HRESULT STDMETHODCALLTYPE
CNtObjectFolder::GetCurFolder(LPITEMIDLIST
* pidl
)
748 *pidl
= ILClone(m_shellPidl
);
755 HRESULT STDMETHODCALLTYPE
CNtObjectFolder::GetDefaultSearchGUID(
762 HRESULT STDMETHODCALLTYPE
CNtObjectFolder::EnumSearches(
763 IEnumExtraSearch
**ppenum
)
769 HRESULT STDMETHODCALLTYPE
CNtObjectFolder::GetDefaultColumn(
781 HRESULT STDMETHODCALLTYPE
CNtObjectFolder::GetDefaultColumnState(
783 SHCOLSTATEF
*pcsFlags
)
787 case NTOBJECT_COLUMN_NAME
:
788 *pcsFlags
= SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
;
790 case NTOBJECT_COLUMN_TYPE
:
791 *pcsFlags
= SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
;
793 case NTOBJECT_COLUMN_LINKTARGET
:
794 *pcsFlags
= SHCOLSTATE_TYPE_STR
| SHCOLSTATE_SLOW
;
801 HRESULT STDMETHODCALLTYPE
CNtObjectFolder::GetDetailsEx(
803 const SHCOLUMNID
*pscid
,
806 const NtPidlEntry
* info
;
808 TRACE("GetDetailsEx\n");
812 HRESULT hr
= CNtObjectPidlHelper::GetInfoFromPidl(pidl
, &info
);
813 if (FAILED_UNEXPECTEDLY(hr
))
816 static const GUID storage
= PSGUID_STORAGE
;
817 if (IsEqualGUID(pscid
->fmtid
, storage
))
819 if (pscid
->pid
== PID_STG_NAME
)
821 return MakeVariantString(pv
, info
->entryName
);
823 else if (pscid
->pid
== PID_STG_STORAGETYPE
)
825 if (info
->objectType
< 0)
827 NtPidlTypeData
* td
= (NtPidlTypeData
*) (((PBYTE
) info
) + FIELD_OFFSET(NtPidlEntry
, entryName
) + info
->entryNameLength
+ sizeof(WCHAR
));
829 if (td
->typeNameLength
> 0)
831 return MakeVariantString(pv
, td
->typeName
);
835 return MakeVariantString(pv
, L
"Unknown");
840 return MakeVariantString(pv
, ObjectTypeNames
[info
->objectType
]);
844 else if (IsEqualGUID(pscid
->fmtid
, GUID_NtObjectColumns
))
846 if (pscid
->pid
== NTOBJECT_COLUMN_LINKTARGET
&& info
->objectType
== SYMBOLICLINK_OBJECT
)
848 WCHAR wbLink
[MAX_PATH
] = { 0 };
850 RtlInitEmptyUnicodeString(&link
, wbLink
, sizeof(wbLink
));
852 HRESULT hr
= GetNTObjectSymbolicLinkTarget(m_NtPath
, info
->entryName
, &link
);
854 if (!FAILED_UNEXPECTEDLY(hr
) && link
.Length
> 0)
856 return MakeVariantString(pv
, link
.Buffer
);
868 HRESULT STDMETHODCALLTYPE
CNtObjectFolder::GetDetailsOf(
873 const NtPidlEntry
* info
;
875 TRACE("GetDetailsOf\n");
879 HRESULT hr
= CNtObjectPidlHelper::GetInfoFromPidl(pidl
, &info
);
880 if (FAILED_UNEXPECTEDLY(hr
))
885 case NTOBJECT_COLUMN_NAME
:
886 psd
->fmt
= LVCFMT_LEFT
;
888 MakeStrRetFromString(info
->entryName
, info
->entryNameLength
, &(psd
->str
));
890 case NTOBJECT_COLUMN_TYPE
:
891 psd
->fmt
= LVCFMT_LEFT
;
893 if (info
->objectType
< 0)
895 NtPidlTypeData
* td
= (NtPidlTypeData
*) (((PBYTE
) info
) + FIELD_OFFSET(NtPidlEntry
, entryName
) + info
->entryNameLength
+ sizeof(WCHAR
));
897 if (td
->typeNameLength
> 0)
898 MakeStrRetFromString(td
->typeName
, td
->typeNameLength
, &(psd
->str
));
900 MakeStrRetFromString(L
"Unknown", &(psd
->str
));
903 MakeStrRetFromString(ObjectTypeNames
[info
->objectType
], &(psd
->str
));
905 case NTOBJECT_COLUMN_LINKTARGET
:
907 psd
->fmt
= LVCFMT_LEFT
;
909 if (info
->objectType
== SYMBOLICLINK_OBJECT
)
911 WCHAR wbLink
[MAX_PATH
] = { 0 };
913 RtlInitEmptyUnicodeString(&link
, wbLink
, sizeof(wbLink
));
915 HRESULT hr
= GetNTObjectSymbolicLinkTarget(m_NtPath
, info
->entryName
, &link
);
917 if (!FAILED_UNEXPECTEDLY(hr
) && link
.Length
> 0)
919 MakeStrRetFromString(link
.Buffer
, link
.Length
, &(psd
->str
));
924 MakeStrRetFromString(L
"", &(psd
->str
));
933 case NTOBJECT_COLUMN_NAME
:
934 psd
->fmt
= LVCFMT_LEFT
;
937 // TODO: Make localizable
938 MakeStrRetFromString(L
"Object Name", &(psd
->str
));
940 case NTOBJECT_COLUMN_TYPE
:
941 psd
->fmt
= LVCFMT_LEFT
;
944 // TODO: Make localizable
945 MakeStrRetFromString(L
"Object Type", &(psd
->str
));
947 case NTOBJECT_COLUMN_LINKTARGET
:
948 psd
->fmt
= LVCFMT_LEFT
;
951 // TODO: Make localizable
952 MakeStrRetFromString(L
"Symlink Target", &(psd
->str
));
960 HRESULT STDMETHODCALLTYPE
CNtObjectFolder::MapColumnToSCID(
964 static const GUID storage
= PSGUID_STORAGE
;
967 case NTOBJECT_COLUMN_NAME
:
968 pscid
->fmtid
= storage
;
969 pscid
->pid
= PID_STG_NAME
;
971 case NTOBJECT_COLUMN_TYPE
:
972 pscid
->fmtid
= storage
;
973 pscid
->pid
= PID_STG_STORAGETYPE
;
975 case NTOBJECT_COLUMN_LINKTARGET
:
976 pscid
->fmtid
= GUID_NtObjectColumns
;
977 pscid
->pid
= NTOBJECT_COLUMN_LINKTARGET
;
983 HRESULT STDMETHODCALLTYPE
CNtObjectFolder::MessageSFVCB(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
987 case SFVM_DEFVIEWMODE
:
989 FOLDERVIEWMODE
* pViewMode
= (FOLDERVIEWMODE
*) lParam
;
990 *pViewMode
= FVM_DETAILS
;
993 case SFVM_COLUMNCLICK
:
995 case SFVM_BACKGROUNDENUM
:
1001 HRESULT
CNtObjectFolder::DefCtxMenuCallback(IShellFolder
* /*psf*/, HWND
/*hwnd*/, IDataObject
* /*pdtobj*/, UINT uMsg
, WPARAM
/*wParam*/, LPARAM
/*lParam*/)
1005 case DFM_MERGECONTEXTMENU
:
1007 case DFM_INVOKECOMMAND
:
1008 case DFM_INVOKECOMMANDEX
:
1009 case DFM_GETDEFSTATICID
: // Required for Windows 7 to pick a default