ReactOS  0.4.13-dev-100-gc8611ae
ntobjfolder.cpp
Go to the documentation of this file.
1 /*
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>
7  */
8 
9 #include "precomp.h"
10 
11 #include <wine/unicode.h>
12 
13 // {845B0FB2-66E0-416B-8F91-314E23F7C12D}
14 const GUID CLSID_NtObjectFolder = { 0x845b0fb2, 0x66e0, 0x416b, { 0x8f, 0x91, 0x31, 0x4e, 0x23, 0xf7, 0xc1, 0x2d } };
15 
16 // {F4C430C3-3A8D-4B56-A018-E598DA60C2E0}
17 static const GUID GUID_NtObjectColumns = { 0xf4c430c3, 0x3a8d, 0x4b56, { 0xa0, 0x18, 0xe5, 0x98, 0xda, 0x60, 0xc2, 0xe0 } };
18 
20 {
25 };
26 
28  m_NtPath(NULL),
29  m_pcidlChild(NULL)
30 {
31 
32 }
33 
35 {
36  if (m_pcidlChild)
38 }
39 
41 {
42  m_NtPath = ntPath;
43  if (cidl != 1)
44  return E_INVALIDARG;
45  m_pcidlChild = ILClone(apidl[0]);
46  return S_OK;
47 }
48 
50  UINT uFlags,
51  LPWSTR szIconFile,
52  UINT cchMax,
53  INT *piIndex,
54  UINT *pwFlags)
55 {
57 
58  if ((entry->cb < sizeof(NtPidlEntry)) || (entry->magic != NT_OBJECT_PIDL_MAGIC))
59  return E_INVALIDARG;
60 
61  UINT flags = 0;
62 
63  switch (entry->objectType)
64  {
65  case DIRECTORY_OBJECT:
68  *piIndex = -((uFlags & GIL_OPENICON) ? IDI_NTOBJECTDIROPEN : IDI_NTOBJECTDIR);
69  *pwFlags = flags;
70  return S_OK;
71  case DEVICE_OBJECT:
73  *piIndex = -IDI_NTOBJECTDEVICE;
74  *pwFlags = flags;
75  return S_OK;
76  case PORT_OBJECT:
78  *piIndex = -IDI_NTOBJECTPORT;
79  *pwFlags = flags;
80  return S_OK;
81  case KEY_OBJECT:
83  *piIndex = -IDI_REGISTRYKEY;
84  *pwFlags = flags;
85  return S_OK;
86  default:
88  *piIndex = -IDI_NTOBJECTITEM;
89  *pwFlags = flags;
90  return S_OK;
91  }
92 }
93 
95  LPCWSTR pszFile,
96  UINT nIconIndex,
97  HICON *phiconLarge,
98  HICON *phiconSmall,
99  UINT nIconSize)
100 {
101  return SHDefExtractIconW(pszFile, nIconIndex, 0, phiconLarge, phiconSmall, nIconSize);
102 }
103 
104 //-----------------------------------------------------------------------------
105 // CNtObjectFolder
106 
108 {
109 }
110 
112 {
113 }
114 
115 // IShellFolder
116 
118  HWND hwndOwner,
119  SHCONTF grfFlags,
120  IEnumIDList **ppenumIDList)
121 {
122  return GetEnumNTDirectory(m_NtPath, ppenumIDList);
123 }
124 
126 {
127  return info->objectType == SYMBOLICLINK_OBJECT;
128 }
129 
131  const NtPidlEntry * info,
132  LPITEMIDLIST * fullPidl)
133 {
134  WCHAR wbLink[MAX_PATH] = { 0 };
136  RtlInitEmptyUnicodeString(&link, wbLink, sizeof(wbLink));
137 
138  *fullPidl = NULL;
139 
141  if (FAILED_UNEXPECTEDLY(hr))
142  return hr;
143 
145 
146  if (link.Length == 0)
147  return E_UNEXPECTED;
148 
149  if (link.Buffer[1] == L':' && isalphaW(link.Buffer[0]))
150  {
151  StringCbCopyNW(path, _countof(path), link.Buffer, link.Length);
152 
153  CComPtr<IShellFolder> psfDesktop;
154  hr = SHGetDesktopFolder(&psfDesktop);
155  if (FAILED_UNEXPECTEDLY(hr))
156  return hr;
157 
158  return psfDesktop->ParseDisplayName(NULL, NULL, path, NULL, fullPidl, NULL);
159  }
160 
161  StringCbCopyW(path, _countof(path), L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{845B0FB2-66E0-416B-8F91-314E23F7C12D}");
162  PathAppend(path, link.Buffer);
163 
164  CComPtr<IShellFolder> psfDesktop;
165  hr = SHGetDesktopFolder(&psfDesktop);
166  if (FAILED_UNEXPECTEDLY(hr))
167  return hr;
168 
169  LPITEMIDLIST pidl;
170 
171  hr = psfDesktop->ParseDisplayName(NULL, NULL, path, NULL, &pidl, NULL);
172  if (FAILED(hr))
173  return hr;
174 
175  *fullPidl = pidl;
176 
177  DumpIdList(pidl);
178 
179  return S_OK;
180 }
181 
183  PWSTR path,
184  const NtPidlEntry * info,
186  LPCITEMIDLIST rest,
187  LPITEMIDLIST fullPidl,
188  LPBC pbcReserved,
189  IShellFolder** ppsfChild)
190 {
191 
192  if (info->objectType == KEY_OBJECT)
193  {
194  return ShellObjectCreatorInit<CRegistryFolder>(fullPidl, path, (HKEY) NULL, IID_PPV_ARG(IShellFolder, ppsfChild));
195  }
196 
197  return ShellObjectCreatorInit<CNtObjectFolder>(fullPidl, path, IID_PPV_ARG(IShellFolder, ppsfChild));
198 }
199 
200 // IPersistFolder
202 {
203  m_shellPidl = ILClone(pidl);
204 
206 
207  return S_OK;
208 }
209 
210 // Internal
212 {
213  m_shellPidl = ILClone(pidl);
214 
216 
217  return S_OK;
218 }
219 
221  UINT iColumn,
222  SHCOLSTATEF *pcsFlags)
223 {
224  switch (iColumn)
225  {
228  return S_OK;
231  return S_OK;
234  return S_OK;
235  }
236 
237  return E_INVALIDARG;
238 }
239 
241  LPCITEMIDLIST pidl,
242  const SHCOLUMNID *pscid,
243  VARIANT *pv)
244 {
245  const NtPidlEntry * info;
246 
247  TRACE("GetDetailsEx\n");
248 
249  if (pidl)
250  {
251  HRESULT hr = GetInfoFromPidl(pidl, &info);
252  if (FAILED_UNEXPECTEDLY(hr))
253  return hr;
254 
255  static const GUID storage = PSGUID_STORAGE;
256  if (IsEqualGUID(pscid->fmtid, storage))
257  {
258  if (pscid->pid == PID_STG_NAME)
259  {
260  return MakeVariantString(pv, info->entryName);
261  }
262  else if (pscid->pid == PID_STG_STORAGETYPE)
263  {
264  if (info->objectType < 0)
265  {
266  NtPidlTypeData * td = (NtPidlTypeData*) (((PBYTE) info) + FIELD_OFFSET(NtPidlEntry, entryName) + info->entryNameLength + sizeof(WCHAR));
267 
268  if (td->typeNameLength > 0)
269  {
270  return MakeVariantString(pv, td->typeName);
271  }
272  else
273  {
274  return MakeVariantString(pv, L"Unknown");
275  }
276  }
277  else
278  {
279  return MakeVariantString(pv, ObjectTypeNames[info->objectType]);
280  }
281  }
282  }
283  else if (IsEqualGUID(pscid->fmtid, GUID_NtObjectColumns))
284  {
285  if (pscid->pid == NTOBJECT_COLUMN_LINKTARGET && info->objectType == SYMBOLICLINK_OBJECT)
286  {
287  WCHAR wbLink[MAX_PATH] = { 0 };
289  RtlInitEmptyUnicodeString(&link, wbLink, sizeof(wbLink));
290 
292 
293  if (!FAILED_UNEXPECTEDLY(hr) && link.Length > 0)
294  {
295  return MakeVariantString(pv, link.Buffer);
296  }
297  }
298 
299  V_VT(pv) = VT_EMPTY;
300  return S_OK;
301  }
302  }
303 
304  return E_INVALIDARG;
305 }
306 
308  LPCITEMIDLIST pidl,
309  UINT iColumn,
310  SHELLDETAILS *psd)
311 {
312  const NtPidlEntry * info;
313 
314  TRACE("GetDetailsOf\n");
315 
316  if (pidl)
317  {
318  HRESULT hr = GetInfoFromPidl(pidl, &info);
319  if (FAILED_UNEXPECTEDLY(hr))
320  return hr;
321 
322  switch (iColumn)
323  {
325  psd->fmt = LVCFMT_LEFT;
326 
327  MakeStrRetFromString(info->entryName, info->entryNameLength, &(psd->str));
328  return S_OK;
330  psd->fmt = LVCFMT_LEFT;
331 
332  if (info->objectType < 0)
333  {
334  NtPidlTypeData * td = (NtPidlTypeData*) (((PBYTE) info) + FIELD_OFFSET(NtPidlEntry, entryName) + info->entryNameLength + sizeof(WCHAR));
335 
336  if (td->typeNameLength > 0)
337  MakeStrRetFromString(td->typeName, td->typeNameLength, &(psd->str));
338  else
339  MakeStrRetFromString(L"Unknown", &(psd->str));
340  }
341  else
342  MakeStrRetFromString(ObjectTypeNames[info->objectType], &(psd->str));
343  return S_OK;
345  {
346  psd->fmt = LVCFMT_LEFT;
347 
348  if (info->objectType == SYMBOLICLINK_OBJECT)
349  {
350  WCHAR wbLink[MAX_PATH] = { 0 };
352  RtlInitEmptyUnicodeString(&link, wbLink, sizeof(wbLink));
353 
355 
356  if (!FAILED_UNEXPECTEDLY(hr) && link.Length > 0)
357  {
358  MakeStrRetFromString(link.Buffer, link.Length, &(psd->str));
359  return S_OK;
360  }
361  }
362 
363  MakeStrRetFromString(L"", &(psd->str));
364  return S_OK;
365  }
366  }
367  }
368  else
369  {
370  switch (iColumn)
371  {
373  psd->fmt = LVCFMT_LEFT;
374  psd->cxChar = 30;
375 
376  // TODO: Make localizable
377  MakeStrRetFromString(L"Object Name", &(psd->str));
378  return S_OK;
380  psd->fmt = LVCFMT_LEFT;
381  psd->cxChar = 20;
382 
383  // TODO: Make localizable
384  MakeStrRetFromString(L"Object Type", &(psd->str));
385  return S_OK;
387  psd->fmt = LVCFMT_LEFT;
388  psd->cxChar = 30;
389 
390  // TODO: Make localizable
391  MakeStrRetFromString(L"Symlink Target", &(psd->str));
392  return S_OK;
393  }
394  }
395 
396  return E_INVALIDARG;
397 }
398 
400  UINT iColumn,
401  SHCOLUMNID *pscid)
402 {
403  static const GUID storage = PSGUID_STORAGE;
404  switch (iColumn)
405  {
407  pscid->fmtid = storage;
408  pscid->pid = PID_STG_NAME;
409  return S_OK;
411  pscid->fmtid = storage;
412  pscid->pid = PID_STG_STORAGETYPE;
413  return S_OK;
415  pscid->fmtid = GUID_NtObjectColumns;
417  return S_OK;
418  }
419  return E_INVALIDARG;
420 }
421 
423 {
424  HRESULT hr;
425 
426  DWORD sortMode = lParam & 0xFFFF0000;
427  DWORD column = lParam & 0x0000FFFF;
428 
429  if (sortMode == SHCIDS_ALLFIELDS)
430  {
431  if (column != 0)
432  return E_INVALIDARG;
433 
434  int minsize = min(first->cb, second->cb);
435  hr = MAKE_COMPARE_HRESULT(memcmp(second, first, minsize));
436  if (hr != S_EQUAL)
437  return hr;
438 
439  return MAKE_COMPARE_HRESULT(second->cb - first->cb);
440  }
441 
442  switch (column)
443  {
445  return CompareName(lParam, first, second);
446 
448  return MAKE_COMPARE_HRESULT(second->objectType - first->objectType);
449 
451  // Can't sort by link target yet
452  return E_INVALIDARG;
453  }
454 
455  DbgPrint("Unsupported sorting mode.\n");
456  return E_INVALIDARG;
457 }
458 
460 {
461  ULONG mask = inMask ? *inMask : 0xFFFFFFFF;
462  ULONG flags = SFGAO_HASPROPSHEET | SFGAO_CANLINK;
463 
464  if (entry->objectType == DIRECTORY_OBJECT)
465  flags |= SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_BROWSABLE;
466 
467  if (entry->objectType == SYMBOLICLINK_OBJECT)
468  flags |= SFGAO_LINK | SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_BROWSABLE;
469 
470  if (entry->objectType == KEY_OBJECT)
471  flags |= SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_BROWSABLE;
472 
473  return flags & mask;
474 }
475 
477 {
478  return (info->objectType == DIRECTORY_OBJECT) ||
479  (info->objectType == SYMBOLICLINK_OBJECT) ||
480  (info->objectType == KEY_OBJECT);
481 }
482 
484 {
485  NtPidlEntry * entry = (NtPidlEntry*) &(pcidl->mkid);
486 
487  if (entry->cb < sizeof(NtPidlEntry))
488  {
489  DbgPrint("PCIDL too small %l (required %l)\n", entry->cb, sizeof(NtPidlEntry));
490  return E_INVALIDARG;
491  }
492 
493  if (entry->magic != NT_OBJECT_PIDL_MAGIC)
494  {
495  DbgPrint("PCIDL magic mismatch %04x (expected %04x)\n", entry->magic, NT_OBJECT_PIDL_MAGIC);
496  return E_INVALIDARG;
497  }
498 
499  *pentry = entry;
500  return S_OK;
501 }
virtual HRESULT STDMETHODCALLTYPE MapColumnToSCID(UINT iColumn, SHCOLUMNID *pscid)
DWORD WINAPI GetModuleFileNameW(HINSTANCE hModule, LPWSTR lpFilename, DWORD nSize)
Definition: loader.c:607
const uint16_t * PCWSTR
Definition: typedefs.h:55
USHORT cb
Definition: ntobjenum.h:43
static HICON
Definition: imagelist.c:84
virtual ~CNtObjectFolder()
void WINAPI ILFree(LPITEMIDLIST pidl)
Definition: pidl.c:925
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
HRESULT hr
Definition: shlfolder.c:183
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
#define DbgPrint
Definition: loader.c:25
interface IBindCtx * LPBC
Definition: objfwd.h:18
STRSAFEAPI StringCbCopyNW(STRSAFE_LPWSTR pszDest, size_t cbDest, STRSAFE_LPCWSTR pszSrc, size_t cbToCopy)
Definition: strsafe.h:255
virtual ~CNtObjectFolderExtractIcon()
Definition: ntobjfolder.cpp:34
HRESULT GetEnumNTDirectory(LPCWSTR path, IEnumIDList **ppil)
Definition: ntobjenum.cpp:748
uint16_t * PWSTR
Definition: typedefs.h:54
#define _countof(array)
Definition: fontsub.cpp:30
const LPCWSTR ObjectTypeNames[]
Definition: ntobjenum.cpp:36
const GLint * first
Definition: glext.h:5794
uint8_t entry
Definition: isohybrid.c:63
const ITEMIDLIST UNALIGNED * LPCITEMIDLIST
Definition: shtypes.idl:42
PCITEMID_CHILD m_pcidlChild
Definition: ntobjfolder.h:17
#define LVCFMT_LEFT
Definition: commctrl.h:2570
#define PID_STG_NAME
Definition: ntquery.h:56
HRESULT INLINE MakeVariantString(VARIANT *pv, PCWSTR string)
Definition: util.h:22
#define MAKE_COMPARE_HRESULT(x)
Definition: shellutils.h:380
UINT uFlags
Definition: api.c:60
#define PathAppend
Definition: shlwapi.h:801
#define IID_PPV_ARG(Itype, ppType)
virtual BOOL STDMETHODCALLTYPE IsFolder(const NtPidlEntry *info)
WCHAR typeName[ANYSIZE_ARRAY]
Definition: ntobjenum.h:56
STRRET str
Definition: shtypes.idl:108
int32_t INT
Definition: typedefs.h:56
DWORD SHCONTF
Definition: shobjidl.idl:182
struct _test_info info[]
Definition: SetCursorPos.c:19
virtual HRESULT STDMETHODCALLTYPE GetDetailsEx(LPCITEMIDLIST pidl, const SHCOLUMNID *pscid, VARIANT *pv)
virtual HRESULT STDMETHODCALLTYPE EnumObjects(HWND hwndOwner, SHCONTF grfFlags, IEnumIDList **ppenumIDList)
#define PSGUID_STORAGE
Definition: ntquery.h:47
#define NT_OBJECT_PIDL_MAGIC
Definition: ntobjenum.h:35
OBJECT_TYPE objectType
Definition: ntobjenum.h:47
#define SHCIDS_ALLFIELDS
Definition: precomp.h:49
GLenum GLint GLuint mask
Definition: glext.h:6028
#define IDI_NTOBJECTDIROPEN
Definition: resource.h:5
static void DumpIdList(LPCITEMIDLIST pcidl)
Definition: undocshell.h:701
const PCUITEMID_CHILD * PCUITEMID_CHILD_ARRAY
Definition: shtypes.idl:71
NtObjectColumns
Definition: ntobjfolder.cpp:19
unsigned int BOOL
Definition: ntddk_ex.h:94
#define IDI_REGISTRYKEY
Definition: resource.h:9
#define E_INVALIDARG
Definition: ddrawi.h:101
smooth NULL
Definition: ftsmooth.c:416
virtual HRESULT STDMETHODCALLTYPE ResolveSymLink(const NtPidlEntry *info, LPITEMIDLIST *fullPidl)
LONG_PTR LPARAM
Definition: windef.h:208
HRESULT Initialize(LPCWSTR ntPath, PCIDLIST_ABSOLUTE parent, UINT cidl, PCUITEMID_CHILD_ARRAY apidl)
Definition: ntobjfolder.cpp:40
virtual ULONG STDMETHODCALLTYPE ConvertAttributes(const NtPidlEntry *entry, PULONG inMask)
HRESULT GetNTObjectSymbolicLinkTarget(LPCWSTR path, LPCWSTR entryName, PUNICODE_STRING LinkTarget)
Definition: ntobjenum.cpp:162
USHORT typeNameLength
Definition: ntobjenum.h:55
#define PID_STG_STORAGETYPE
Definition: ntquery.h:50
#define IDI_NTOBJECTDEVICE
Definition: resource.h:7
const GUID CLSID_NtObjectFolder
Definition: ntobjfolder.cpp:14
#define TRACE(s)
Definition: solgame.cpp:4
HRESULT WINAPI SHGetDesktopFolder(IShellFolder **psf)
virtual HRESULT GetInfoFromPidl(LPCITEMIDLIST pcidl, const NtPidlEntry **pentry)
r parent
Definition: btrfs.c:2659
__wchar_t WCHAR
Definition: xmlstorage.h:180
LONG HRESULT
Definition: typedefs.h:77
virtual HRESULT STDMETHODCALLTYPE CompareName(LPARAM lParam, const NtPidlEntry *first, const NtPidlEntry *second)
Definition: foldercommon.h:289
#define FAILED_UNEXPECTEDLY(hr)
Definition: shellutils.h:35
#define MAX_PATH
Definition: compat.h:26
#define STDMETHODCALLTYPE
Definition: bdasup.h:9
unsigned long DWORD
Definition: ntddk_ex.h:95
#define S_EQUAL
Definition: shellutils.h:378
virtual HRESULT STDMETHODCALLTYPE InternalBindToObject(PWSTR path, const NtPidlEntry *info, LPITEMIDLIST first, LPCITEMIDLIST rest, LPITEMIDLIST fullPidl, LPBC pbcReserved, IShellFolder **ppsfChild)
virtual HRESULT STDMETHODCALLTYPE GetDetailsOf(LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS *psd)
GLbitfield flags
Definition: glext.h:7161
UINT cchMax
#define StringCbCopy
Definition: strsafe.h:155
#define IDI_NTOBJECTITEM
Definition: resource.h:6
struct _DEVICE_OBJECT DEVICE_OBJECT
DWORD SHCOLSTATEF
Definition: shtypes.idl:142
static const WCHAR L[]
Definition: oid.c:1250
#define V_VT(A)
Definition: oleauto.h:211
virtual HRESULT STDMETHODCALLTYPE CompareIDs(LPARAM lParam, const NtPidlEntry *first, const NtPidlEntry *second)
virtual BOOL STDMETHODCALLTYPE IsSymLink(const NtPidlEntry *info)
virtual HRESULT STDMETHODCALLTYPE Extract(LPCWSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize)
Definition: ntobjfolder.cpp:94
virtual HRESULT STDMETHODCALLTYPE Initialize(LPCITEMIDLIST pidl)
#define S_OK
Definition: intsafe.h:59
LPITEMIDLIST WINAPI ILClone(LPCITEMIDLIST pidl)
Definition: pidl.c:228
Definition: services.c:325
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
unsigned int * PULONG
Definition: retypes.h:1
#define min(a, b)
Definition: monoChain.cc:55
unsigned int UINT
Definition: ndis.h:50
BOOL WINAPI IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
Definition: compobj.c:4021
#define E_UNEXPECTED
Definition: winerror.h:2456
HRESULT WINAPI SHDefExtractIconW(LPCWSTR pszIconFile, int iIndex, UINT uFlags, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize)
Definition: iconcache.cpp:1020
#define IDI_NTOBJECTPORT
Definition: resource.h:8
unsigned int ULONG
Definition: retypes.h:1
const WCHAR * link
Definition: db.cpp:985
HINSTANCE g_hInstance
Definition: MainWindow.cpp:18
WINE_UNICODE_INLINE int isalphaW(WCHAR wc)
Definition: unicode.h:195
WCHAR * LPWSTR
Definition: xmlstorage.h:184
STRSAFEAPI StringCbCopyW(STRSAFE_LPWSTR pszDest, size_t cbDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:166
ITEMIDLIST UNALIGNED * LPITEMIDLIST
Definition: shtypes.idl:41
BYTE * PBYTE
Definition: pedump.c:66
LPARAM lParam
Definition: combotst.c:139
#define IDI_NTOBJECTDIR
Definition: resource.h:4
virtual HRESULT STDMETHODCALLTYPE GetDefaultColumnState(UINT iColumn, SHCOLSTATEF *pcsFlags)
static const GUID GUID_NtObjectColumns
Definition: ntobjfolder.cpp:17
HRESULT INLINE MakeStrRetFromString(LPCWSTR string, DWORD cbLength, STRRET *str)
Definition: util.h:7
virtual HRESULT STDMETHODCALLTYPE GetIconLocation(UINT uFlags, LPWSTR szIconFile, UINT cchMax, INT *piIndex, UINT *pwFlags)
Definition: ntobjfolder.cpp:49