[NTOBJSHEX] Formatting only

This commit is contained in:
Stanislav Motylkov 2022-12-20 20:08:08 +03:00
parent 4c25af5bd4
commit ba03ffd645
No known key found for this signature in database
GPG key ID: AFE513258CBA9E92
9 changed files with 404 additions and 390 deletions

View file

@ -1,9 +1,8 @@
/* /*
* PROJECT: ReactOS shell extensions * PROJECT: NT Object Namespace shell extension
* LICENSE: GPL - See COPYING in the top level directory * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* FILE: dll/shellext/ntobjshex/ntobjfolder.cpp * PURPOSE: Folder view class placeholder file
* PURPOSE: NT Object Namespace shell extension * COPYRIGHT: Copyright 2015-2017 David Quintana <gigaherz@gmail.com>
* PROGRAMMERS: David Quintana <gigaherz@gmail.com>
*/ */
#include "precomp.h" #include "precomp.h"

View file

@ -1,10 +1,10 @@
/* /*
* PROJECT: ReactOS shell extensions * PROJECT: NT Object Namespace shell extension
* LICENSE: GPL - See COPYING in the top level directory * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* FILE: dll/shellext/ntobjshex/ntobjfolder.h * PURPOSE: Folder view class header and implementation
* PURPOSE: NT Object Namespace shell extension * COPYRIGHT: Copyright 2015-2017 David Quintana <gigaherz@gmail.com>
* PROGRAMMERS: David Quintana <gigaherz@gmail.com>
*/ */
#pragma once #pragma once
extern const GUID CLSID_NtObjectFolder; extern const GUID CLSID_NtObjectFolder;
@ -24,16 +24,18 @@ public:
{ {
switch (uMsg) switch (uMsg)
{ {
case SFVM_DEFVIEWMODE: case SFVM_DEFVIEWMODE:
{ {
FOLDERVIEWMODE* pViewMode = (FOLDERVIEWMODE*)lParam; FOLDERVIEWMODE* pViewMode = (FOLDERVIEWMODE*)lParam;
*pViewMode = FVM_DETAILS; *pViewMode = FVM_DETAILS;
return S_OK; return S_OK;
} }
case SFVM_COLUMNCLICK:
return S_FALSE; case SFVM_COLUMNCLICK:
case SFVM_BACKGROUNDENUM: return S_FALSE;
return S_OK;
case SFVM_BACKGROUNDENUM:
return S_OK;
} }
DbgPrint("MessageSFVCB unimplemented %d %08x %08x\n", uMsg, wParam, lParam); DbgPrint("MessageSFVCB unimplemented %d %08x %08x\n", uMsg, wParam, lParam);
@ -697,12 +699,13 @@ public:
{ {
switch (uMsg) switch (uMsg)
{ {
case DFM_MERGECONTEXTMENU: case DFM_MERGECONTEXTMENU:
return S_OK; return S_OK;
case DFM_INVOKECOMMAND:
case DFM_INVOKECOMMANDEX: case DFM_INVOKECOMMAND:
case DFM_GETDEFSTATICID: // Required for Windows 7 to pick a default case DFM_INVOKECOMMANDEX:
return S_FALSE; case DFM_GETDEFSTATICID: // Required for Windows 7 to pick a default
return S_FALSE;
} }
return E_NOTIMPL; return E_NOTIMPL;
} }
@ -718,4 +721,4 @@ public:
COM_INTERFACE_ENTRY_IID(IID_IPersistFolder2, IPersistFolder2) COM_INTERFACE_ENTRY_IID(IID_IPersistFolder2, IPersistFolder2)
END_COM_MAP() END_COM_MAP()
}; };

View file

@ -1,19 +1,8 @@
/* /*
* Copyright 2004, 2005 Martin Fuchs * PROJECT: NT Object Namespace shell extension
* * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
* This library is free software; you can redistribute it and/or * PURPOSE: NT Object Namespace enumeration functions
* modify it under the terms of the GNU Lesser General Public * COPYRIGHT: Copyright 2004-2005 Martin Fuchs <martin-fuchs@gmx.net>
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include "precomp.h" #include "precomp.h"
@ -73,19 +62,19 @@ static DWORD NtOpenObject(OBJECT_TYPE type, PHANDLE phandle, DWORD access, LPCWS
switch (type) switch (type)
{ {
case DIRECTORY_OBJECT: return NtOpenDirectoryObject(phandle, access, &open_struct); case DIRECTORY_OBJECT: return NtOpenDirectoryObject(phandle, access, &open_struct);
case SYMBOLICLINK_OBJECT: return NtOpenSymbolicLinkObject(phandle, access, &open_struct); case SYMBOLICLINK_OBJECT: return NtOpenSymbolicLinkObject(phandle, access, &open_struct);
case MUTANT_OBJECT: return NtOpenMutant(phandle, access, &open_struct); case MUTANT_OBJECT: return NtOpenMutant(phandle, access, &open_struct);
case SECTION_OBJECT: return NtOpenSection(phandle, access, &open_struct); case SECTION_OBJECT: return NtOpenSection(phandle, access, &open_struct);
case EVENT_OBJECT: return NtOpenEvent(phandle, access, &open_struct); case EVENT_OBJECT: return NtOpenEvent(phandle, access, &open_struct);
case SEMAPHORE_OBJECT: return NtOpenSemaphore(phandle, access, &open_struct); case SEMAPHORE_OBJECT: return NtOpenSemaphore(phandle, access, &open_struct);
case TIMER_OBJECT: return NtOpenTimer(phandle, access, &open_struct); case TIMER_OBJECT: return NtOpenTimer(phandle, access, &open_struct);
case KEY_OBJECT: return NtOpenKey(phandle, access, &open_struct); case KEY_OBJECT: return NtOpenKey(phandle, access, &open_struct);
case EVENTPAIR_OBJECT: return NtOpenEventPair(phandle, access, &open_struct); case EVENTPAIR_OBJECT: return NtOpenEventPair(phandle, access, &open_struct);
case IOCOMPLETION_OBJECT: return NtOpenIoCompletion(phandle, access, &open_struct); case IOCOMPLETION_OBJECT: return NtOpenIoCompletion(phandle, access, &open_struct);
case FILE_OBJECT: return NtOpenFile(phandle, access, &open_struct, &ioStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0); case FILE_OBJECT: return NtOpenFile(phandle, access, &open_struct, &ioStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0);
default: default:
return ERROR_INVALID_FUNCTION; return ERROR_INVALID_FUNCTION;
} }
} }
@ -748,4 +737,4 @@ HRESULT GetEnumRegistryKey(LPCWSTR path, HKEY root, IEnumIDList ** ppil)
HRESULT GetEnumNTDirectory(LPCWSTR path, IEnumIDList ** ppil) HRESULT GetEnumNTDirectory(LPCWSTR path, IEnumIDList ** ppil)
{ {
return ShellObjectCreatorInit<CEnumNTDirectory>(path, IID_PPV_ARG(IEnumIDList, ppil)); return ShellObjectCreatorInit<CEnumNTDirectory>(path, IID_PPV_ARG(IEnumIDList, ppil));
} }

View file

@ -1,20 +1,10 @@
/* /*
* Copyright 2004 Martin Fuchs * PROJECT: NT Object Namespace shell extension
* * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
* This library is free software; you can redistribute it and/or * PURPOSE: NT Object Namespace enumeration header
* modify it under the terms of the GNU Lesser General Public * COPYRIGHT: Copyright 2004 Martin Fuchs <martin-fuchs@gmx.net>
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#pragma once #pragma once
@ -100,4 +90,4 @@ HRESULT GetEnumRegistryRoot(IEnumIDList ** ppil);
HRESULT GetEnumRegistryKey(LPCWSTR path, HKEY root, IEnumIDList ** ppil); HRESULT GetEnumRegistryKey(LPCWSTR path, HKEY root, IEnumIDList ** ppil);
HRESULT GetEnumNTDirectory(LPCWSTR path, IEnumIDList ** ppil); HRESULT GetEnumNTDirectory(LPCWSTR path, IEnumIDList ** ppil);
HRESULT GetNTObjectSymbolicLinkTarget(LPCWSTR path, LPCWSTR entryName, PUNICODE_STRING LinkTarget); HRESULT GetNTObjectSymbolicLinkTarget(LPCWSTR path, LPCWSTR entryName, PUNICODE_STRING LinkTarget);

View file

@ -1,9 +1,8 @@
/* /*
* PROJECT: ReactOS shell extensions * PROJECT: NT Object Namespace shell extension
* LICENSE: GPL - See COPYING in the top level directory * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* FILE: dll/shellext/ntobjshex/ntobjfolder.cpp * PURPOSE: NT Object Namespace folder class implementation
* PURPOSE: NT Object Namespace shell extension * COPYRIGHT: Copyright 2015-2017 David Quintana <gigaherz@gmail.com>
* PROGRAMMERS: David Quintana <gigaherz@gmail.com>
*/ */
#include "precomp.h" #include "precomp.h"
@ -62,32 +61,36 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolderExtractIcon::GetIconLocation(
switch (entry->objectType) switch (entry->objectType)
{ {
case DIRECTORY_OBJECT: case DIRECTORY_OBJECT:
case SYMBOLICLINK_OBJECT: case SYMBOLICLINK_OBJECT:
GetModuleFileNameW(g_hInstance, szIconFile, cchMax); GetModuleFileNameW(g_hInstance, szIconFile, cchMax);
*piIndex = -((uFlags & GIL_OPENICON) ? IDI_NTOBJECTDIROPEN : IDI_NTOBJECTDIR); *piIndex = -((uFlags & GIL_OPENICON) ? IDI_NTOBJECTDIROPEN : IDI_NTOBJECTDIR);
*pwFlags = flags; *pwFlags = flags;
return S_OK; return S_OK;
case DEVICE_OBJECT:
GetModuleFileNameW(g_hInstance, szIconFile, cchMax); case DEVICE_OBJECT:
*piIndex = -IDI_NTOBJECTDEVICE; GetModuleFileNameW(g_hInstance, szIconFile, cchMax);
*pwFlags = flags; *piIndex = -IDI_NTOBJECTDEVICE;
return S_OK; *pwFlags = flags;
case PORT_OBJECT: return S_OK;
GetModuleFileNameW(g_hInstance, szIconFile, cchMax);
*piIndex = -IDI_NTOBJECTPORT; case PORT_OBJECT:
*pwFlags = flags; GetModuleFileNameW(g_hInstance, szIconFile, cchMax);
return S_OK; *piIndex = -IDI_NTOBJECTPORT;
case KEY_OBJECT: *pwFlags = flags;
GetModuleFileNameW(g_hInstance, szIconFile, cchMax); return S_OK;
*piIndex = -IDI_REGISTRYKEY;
*pwFlags = flags; case KEY_OBJECT:
return S_OK; GetModuleFileNameW(g_hInstance, szIconFile, cchMax);
default: *piIndex = -IDI_REGISTRYKEY;
GetModuleFileNameW(g_hInstance, szIconFile, cchMax); *pwFlags = flags;
*piIndex = -IDI_NTOBJECTITEM; return S_OK;
*pwFlags = flags;
return S_OK; default:
GetModuleFileNameW(g_hInstance, szIconFile, cchMax);
*piIndex = -IDI_NTOBJECTITEM;
*pwFlags = flags;
return S_OK;
} }
} }
@ -223,15 +226,17 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::GetDefaultColumnState(
{ {
switch (iColumn) switch (iColumn)
{ {
case NTOBJECT_COLUMN_NAME: case NTOBJECT_COLUMN_NAME:
*pcsFlags = SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT; *pcsFlags = SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT;
return S_OK; return S_OK;
case NTOBJECT_COLUMN_TYPE:
*pcsFlags = SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT; case NTOBJECT_COLUMN_TYPE:
return S_OK; *pcsFlags = SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT;
case NTOBJECT_COLUMN_LINKTARGET: return S_OK;
*pcsFlags = SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT | SHCOLSTATE_SLOW;
return S_OK; case NTOBJECT_COLUMN_LINKTARGET:
*pcsFlags = SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT | SHCOLSTATE_SLOW;
return S_OK;
} }
return E_INVALIDARG; return E_INVALIDARG;
@ -321,75 +326,83 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::GetDetailsOf(
switch (iColumn) switch (iColumn)
{ {
case NTOBJECT_COLUMN_NAME: case NTOBJECT_COLUMN_NAME:
psd->fmt = LVCFMT_LEFT;
MakeStrRetFromString(info->entryName, info->entryNameLength, &(psd->str));
return S_OK;
case NTOBJECT_COLUMN_TYPE:
psd->fmt = LVCFMT_LEFT;
if (info->objectType < 0)
{ {
NtPidlTypeData * td = (NtPidlTypeData*) (((PBYTE) info) + FIELD_OFFSET(NtPidlEntry, entryName) + info->entryNameLength + sizeof(WCHAR)); psd->fmt = LVCFMT_LEFT;
if (td->typeNameLength > 0) MakeStrRetFromString(info->entryName, info->entryNameLength, &(psd->str));
MakeStrRetFromString(td->typeName, td->typeNameLength, &(psd->str)); return S_OK;
else
MakeStrRetFromString(L"Unknown", &(psd->str));
} }
else
MakeStrRetFromString(ObjectTypeNames[info->objectType], &(psd->str));
return S_OK;
case NTOBJECT_COLUMN_LINKTARGET:
{
psd->fmt = LVCFMT_LEFT;
if (info->objectType == SYMBOLICLINK_OBJECT) case NTOBJECT_COLUMN_TYPE:
{ {
WCHAR wbLink[MAX_PATH] = { 0 }; psd->fmt = LVCFMT_LEFT;
UNICODE_STRING link;
RtlInitEmptyUnicodeString(&link, wbLink, sizeof(wbLink));
HRESULT hr = GetNTObjectSymbolicLinkTarget(m_NtPath, info->entryName, &link); if (info->objectType < 0)
if (!FAILED_UNEXPECTEDLY(hr) && link.Length > 0)
{ {
MakeStrRetFromString(link.Buffer, link.Length, &(psd->str)); NtPidlTypeData * td = (NtPidlTypeData*) (((PBYTE) info) + FIELD_OFFSET(NtPidlEntry, entryName) + info->entryNameLength + sizeof(WCHAR));
return S_OK;
if (td->typeNameLength > 0)
MakeStrRetFromString(td->typeName, td->typeNameLength, &(psd->str));
else
MakeStrRetFromString(L"Unknown", &(psd->str));
} }
else
MakeStrRetFromString(ObjectTypeNames[info->objectType], &(psd->str));
return S_OK;
} }
MakeStrRetFromString(L"", &(psd->str)); case NTOBJECT_COLUMN_LINKTARGET:
return S_OK; {
} psd->fmt = LVCFMT_LEFT;
if (info->objectType == SYMBOLICLINK_OBJECT)
{
WCHAR wbLink[MAX_PATH] = { 0 };
UNICODE_STRING link;
RtlInitEmptyUnicodeString(&link, wbLink, sizeof(wbLink));
HRESULT hr = GetNTObjectSymbolicLinkTarget(m_NtPath, info->entryName, &link);
if (!FAILED_UNEXPECTEDLY(hr) && link.Length > 0)
{
MakeStrRetFromString(link.Buffer, link.Length, &(psd->str));
return S_OK;
}
}
MakeStrRetFromString(L"", &(psd->str));
return S_OK;
}
} }
} }
else else
{ {
switch (iColumn) switch (iColumn)
{ {
case NTOBJECT_COLUMN_NAME: case NTOBJECT_COLUMN_NAME:
psd->fmt = LVCFMT_LEFT; psd->fmt = LVCFMT_LEFT;
psd->cxChar = 30; psd->cxChar = 30;
// TODO: Make localizable // TODO: Make localizable
MakeStrRetFromString(L"Object Name", &(psd->str)); MakeStrRetFromString(L"Object Name", &(psd->str));
return S_OK; return S_OK;
case NTOBJECT_COLUMN_TYPE:
psd->fmt = LVCFMT_LEFT;
psd->cxChar = 20;
// TODO: Make localizable case NTOBJECT_COLUMN_TYPE:
MakeStrRetFromString(L"Object Type", &(psd->str)); psd->fmt = LVCFMT_LEFT;
return S_OK; psd->cxChar = 20;
case NTOBJECT_COLUMN_LINKTARGET:
psd->fmt = LVCFMT_LEFT;
psd->cxChar = 30;
// TODO: Make localizable // TODO: Make localizable
MakeStrRetFromString(L"Symlink Target", &(psd->str)); MakeStrRetFromString(L"Object Type", &(psd->str));
return S_OK; return S_OK;
case NTOBJECT_COLUMN_LINKTARGET:
psd->fmt = LVCFMT_LEFT;
psd->cxChar = 30;
// TODO: Make localizable
MakeStrRetFromString(L"Symlink Target", &(psd->str));
return S_OK;
} }
} }
@ -403,18 +416,20 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::MapColumnToSCID(
static const GUID storage = PSGUID_STORAGE; static const GUID storage = PSGUID_STORAGE;
switch (iColumn) switch (iColumn)
{ {
case NTOBJECT_COLUMN_NAME: case NTOBJECT_COLUMN_NAME:
pscid->fmtid = storage; pscid->fmtid = storage;
pscid->pid = PID_STG_NAME; pscid->pid = PID_STG_NAME;
return S_OK; return S_OK;
case NTOBJECT_COLUMN_TYPE:
pscid->fmtid = storage; case NTOBJECT_COLUMN_TYPE:
pscid->pid = PID_STG_STORAGETYPE; pscid->fmtid = storage;
return S_OK; pscid->pid = PID_STG_STORAGETYPE;
case NTOBJECT_COLUMN_LINKTARGET: return S_OK;
pscid->fmtid = GUID_NtObjectColumns;
pscid->pid = NTOBJECT_COLUMN_LINKTARGET; case NTOBJECT_COLUMN_LINKTARGET:
return S_OK; pscid->fmtid = GUID_NtObjectColumns;
pscid->pid = NTOBJECT_COLUMN_LINKTARGET;
return S_OK;
} }
return E_INVALIDARG; return E_INVALIDARG;
} }
@ -441,15 +456,15 @@ HRESULT CNtObjectFolder::CompareIDs(LPARAM lParam, const NtPidlEntry * first, co
switch (column) switch (column)
{ {
case NTOBJECT_COLUMN_NAME: case NTOBJECT_COLUMN_NAME:
return CompareName(lParam, first, second); return CompareName(lParam, first, second);
case NTOBJECT_COLUMN_TYPE: case NTOBJECT_COLUMN_TYPE:
return MAKE_COMPARE_HRESULT(second->objectType - first->objectType); return MAKE_COMPARE_HRESULT(second->objectType - first->objectType);
case NTOBJECT_COLUMN_LINKTARGET: case NTOBJECT_COLUMN_LINKTARGET:
// Can't sort by link target yet // Can't sort by link target yet
return E_INVALIDARG; return E_INVALIDARG;
} }
DbgPrint("Unsupported sorting mode.\n"); DbgPrint("Unsupported sorting mode.\n");
@ -498,4 +513,4 @@ HRESULT CNtObjectFolder::GetInfoFromPidl(LPCITEMIDLIST pcidl, const NtPidlEntry
*pentry = entry; *pentry = entry;
return S_OK; return S_OK;
} }

View file

@ -1,10 +1,10 @@
/* /*
* PROJECT: ReactOS shell extensions * PROJECT: NT Object Namespace shell extension
* LICENSE: GPL - See COPYING in the top level directory * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* FILE: dll/shellext/ntobjshex/ntobjfolder.h * PURPOSE: NT Object Namespace folder class header
* PURPOSE: NT Object Namespace shell extension * COPYRIGHT: Copyright 2015-2017 David Quintana <gigaherz@gmail.com>
* PROGRAMMERS: David Quintana <gigaherz@gmail.com>
*/ */
#pragma once #pragma once
extern const GUID CLSID_NtObjectFolder; extern const GUID CLSID_NtObjectFolder;
@ -113,4 +113,4 @@ protected:
HRESULT FormatValueData(DWORD contentType, PVOID td, DWORD contentsLength, PCWSTR * strContents); HRESULT FormatValueData(DWORD contentType, PVOID td, DWORD contentsLength, PCWSTR * strContents);
HRESULT FormatContentsForDisplay(const NtPidlEntry * info, HKEY rootKey, LPCWSTR ntPath, PCWSTR * strContents); HRESULT FormatContentsForDisplay(const NtPidlEntry * info, HKEY rootKey, LPCWSTR ntPath, PCWSTR * strContents);
}; };

View file

@ -1,9 +1,8 @@
/* /*
* PROJECT: ReactOS shell extensions * PROJECT: NT Object Namespace shell extension
* LICENSE: GPL - See COPYING in the top level directory * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* FILE: dll/shellext/ntobjshex/ntobjshex.cpp * PURPOSE: Shell extension entry point and exports
* PURPOSE: NT Object Namespace shell extension * COPYRIGHT: Copyright 2015-2017 David Quintana <gigaherz@gmail.com>
* PROGRAMMERS: David Quintana <gigaherz@gmail.com>
*/ */
#include "precomp.h" #include "precomp.h"

View file

@ -1,9 +1,8 @@
/* /*
* PROJECT: ReactOS shell extensions * PROJECT: NT Object Namespace shell extension
* LICENSE: GPL - See COPYING in the top level directory * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* FILE: dll/shellext/ntobjshex/regfolder.cpp * PURPOSE: System Registry folder class implementation
* PURPOSE: NT Object Namespace shell extension * COPYRIGHT: Copyright 2015-2017 David Quintana <gigaherz@gmail.com>
* PROGRAMMERS: David Quintana <gigaherz@gmail.com>
*/ */
#include "precomp.h" #include "precomp.h"
@ -64,22 +63,24 @@ HRESULT STDMETHODCALLTYPE CRegistryFolderExtractIcon::GetIconLocation(
switch (entry->entryType) switch (entry->entryType)
{ {
case REG_ENTRY_KEY: case REG_ENTRY_KEY:
case REG_ENTRY_ROOT: case REG_ENTRY_ROOT:
GetModuleFileNameW(g_hInstance, szIconFile, cchMax); GetModuleFileNameW(g_hInstance, szIconFile, cchMax);
*piIndex = -IDI_REGISTRYKEY; *piIndex = -IDI_REGISTRYKEY;
*pwFlags = flags; *pwFlags = flags;
return S_OK; return S_OK;
case REG_ENTRY_VALUE:
GetModuleFileNameW(g_hInstance, szIconFile, cchMax); case REG_ENTRY_VALUE:
*piIndex = -IDI_REGISTRYVALUE; GetModuleFileNameW(g_hInstance, szIconFile, cchMax);
*pwFlags = flags; *piIndex = -IDI_REGISTRYVALUE;
return S_OK; *pwFlags = flags;
default: return S_OK;
GetModuleFileNameW(g_hInstance, szIconFile, cchMax);
*piIndex = -IDI_NTOBJECTITEM; default:
*pwFlags = flags; GetModuleFileNameW(g_hInstance, szIconFile, cchMax);
return S_OK; *piIndex = -IDI_NTOBJECTITEM;
*pwFlags = flags;
return S_OK;
} }
} }
@ -160,15 +161,17 @@ HRESULT STDMETHODCALLTYPE CRegistryFolder::GetDefaultColumnState(
{ {
switch (iColumn) switch (iColumn)
{ {
case REGISTRY_COLUMN_NAME: case REGISTRY_COLUMN_NAME:
*pcsFlags = SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT; *pcsFlags = SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT;
return S_OK; return S_OK;
case REGISTRY_COLUMN_TYPE:
*pcsFlags = SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT; case REGISTRY_COLUMN_TYPE:
return S_OK; *pcsFlags = SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT;
case REGISTRY_COLUMN_VALUE: return S_OK;
*pcsFlags = SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT | SHCOLSTATE_SLOW;
return S_OK; case REGISTRY_COLUMN_VALUE:
*pcsFlags = SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT | SHCOLSTATE_SLOW;
return S_OK;
} }
return E_INVALIDARG; return E_INVALIDARG;
@ -264,83 +267,91 @@ HRESULT STDMETHODCALLTYPE CRegistryFolder::GetDetailsOf(
switch (iColumn) switch (iColumn)
{ {
case REGISTRY_COLUMN_NAME: case REGISTRY_COLUMN_NAME:
psd->fmt = LVCFMT_LEFT;
if (info->entryNameLength > 0)
{ {
return MakeStrRetFromString(info->entryName, info->entryNameLength, &(psd->str)); psd->fmt = LVCFMT_LEFT;
}
return MakeStrRetFromString(L"(Default)", &(psd->str));
case REGISTRY_COLUMN_TYPE: if (info->entryNameLength > 0)
psd->fmt = LVCFMT_LEFT;
if (info->entryType == REG_ENTRY_ROOT)
{
return MakeStrRetFromString(L"Key", &(psd->str));
}
if (info->entryType == REG_ENTRY_KEY)
{
if (info->contentsLength > 0)
{ {
PWSTR td = (PWSTR)(((PBYTE)info) + FIELD_OFFSET(RegPidlEntry, entryName) + info->entryNameLength + sizeof(WCHAR)); return MakeStrRetFromString(info->entryName, info->entryNameLength, &(psd->str));
}
return MakeStrRetFromString(L"(Default)", &(psd->str));
}
return MakeStrRetFromString(td, info->contentsLength, &(psd->str)); case REGISTRY_COLUMN_TYPE:
{
psd->fmt = LVCFMT_LEFT;
if (info->entryType == REG_ENTRY_ROOT)
{
return MakeStrRetFromString(L"Key", &(psd->str));
} }
return MakeStrRetFromString(L"Key", &(psd->str)); if (info->entryType == REG_ENTRY_KEY)
{
if (info->contentsLength > 0)
{
PWSTR td = (PWSTR)(((PBYTE)info) + FIELD_OFFSET(RegPidlEntry, entryName) + info->entryNameLength + sizeof(WCHAR));
return MakeStrRetFromString(td, info->contentsLength, &(psd->str));
}
return MakeStrRetFromString(L"Key", &(psd->str));
}
return MakeStrRetFromString(RegistryTypeNames[info->entryType], &(psd->str));
} }
return MakeStrRetFromString(RegistryTypeNames[info->entryType], &(psd->str)); case REGISTRY_COLUMN_VALUE:
case REGISTRY_COLUMN_VALUE:
psd->fmt = LVCFMT_LEFT;
PCWSTR strValueContents;
hr = FormatContentsForDisplay(info, m_hRoot, m_NtPath, &strValueContents);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
if (hr == S_FALSE)
{ {
return MakeStrRetFromString(L"(Empty)", &(psd->str)); psd->fmt = LVCFMT_LEFT;
PCWSTR strValueContents;
hr = FormatContentsForDisplay(info, m_hRoot, m_NtPath, &strValueContents);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
if (hr == S_FALSE)
{
return MakeStrRetFromString(L"(Empty)", &(psd->str));
}
hr = MakeStrRetFromString(strValueContents, &(psd->str));
CoTaskMemFree((PVOID)strValueContents);
return hr;
} }
hr = MakeStrRetFromString(strValueContents, &(psd->str));
CoTaskMemFree((PVOID)strValueContents);
return hr;
} }
} }
else else
{ {
switch (iColumn) switch (iColumn)
{ {
case REGISTRY_COLUMN_NAME: case REGISTRY_COLUMN_NAME:
psd->fmt = LVCFMT_LEFT; psd->fmt = LVCFMT_LEFT;
psd->cxChar = 30; psd->cxChar = 30;
// TODO: Make localizable // TODO: Make localizable
MakeStrRetFromString(L"Object Name", &(psd->str)); MakeStrRetFromString(L"Object Name", &(psd->str));
return S_OK; return S_OK;
case REGISTRY_COLUMN_TYPE:
psd->fmt = LVCFMT_LEFT;
psd->cxChar = 20;
// TODO: Make localizable case REGISTRY_COLUMN_TYPE:
MakeStrRetFromString(L"Content Type", &(psd->str)); psd->fmt = LVCFMT_LEFT;
return S_OK; psd->cxChar = 20;
case REGISTRY_COLUMN_VALUE:
psd->fmt = LVCFMT_LEFT;
psd->cxChar = 20;
// TODO: Make localizable // TODO: Make localizable
MakeStrRetFromString(L"Value", &(psd->str)); MakeStrRetFromString(L"Content Type", &(psd->str));
return S_OK; return S_OK;
case REGISTRY_COLUMN_VALUE:
psd->fmt = LVCFMT_LEFT;
psd->cxChar = 20;
// TODO: Make localizable
MakeStrRetFromString(L"Value", &(psd->str));
return S_OK;
} }
} }
@ -354,18 +365,20 @@ HRESULT STDMETHODCALLTYPE CRegistryFolder::MapColumnToSCID(
static const GUID storage = PSGUID_STORAGE; static const GUID storage = PSGUID_STORAGE;
switch (iColumn) switch (iColumn)
{ {
case REGISTRY_COLUMN_NAME: case REGISTRY_COLUMN_NAME:
pscid->fmtid = storage; pscid->fmtid = storage;
pscid->pid = PID_STG_NAME; pscid->pid = PID_STG_NAME;
return S_OK; return S_OK;
case REGISTRY_COLUMN_TYPE:
pscid->fmtid = storage; case REGISTRY_COLUMN_TYPE:
pscid->pid = PID_STG_STORAGETYPE; pscid->fmtid = storage;
return S_OK; pscid->pid = PID_STG_STORAGETYPE;
case REGISTRY_COLUMN_VALUE: return S_OK;
pscid->fmtid = storage;
pscid->pid = PID_STG_CONTENTS; case REGISTRY_COLUMN_VALUE:
return S_OK; pscid->fmtid = storage;
pscid->pid = PID_STG_CONTENTS;
return S_OK;
} }
return E_INVALIDARG; return E_INVALIDARG;
} }
@ -392,15 +405,15 @@ HRESULT CRegistryFolder::CompareIDs(LPARAM lParam, const RegPidlEntry * first, c
switch (column) switch (column)
{ {
case REGISTRY_COLUMN_NAME: case REGISTRY_COLUMN_NAME:
return CompareName(lParam, first, second); return CompareName(lParam, first, second);
case REGISTRY_COLUMN_TYPE: case REGISTRY_COLUMN_TYPE:
return MAKE_COMPARE_HRESULT(second->contentType - first->contentType); return MAKE_COMPARE_HRESULT(second->contentType - first->contentType);
case REGISTRY_COLUMN_VALUE: case REGISTRY_COLUMN_VALUE:
// Can't sort by link target yet // Can't sort by link target yet
return E_INVALIDARG; return E_INVALIDARG;
} }
DbgPrint("Unsupported sorting mode.\n"); DbgPrint("Unsupported sorting mode.\n");
@ -448,99 +461,105 @@ HRESULT CRegistryFolder::FormatValueData(DWORD contentType, PVOID td, DWORD cont
{ {
switch (contentType) switch (contentType)
{ {
case 0: case 0:
{
PCWSTR strTodo = L"";
DWORD bufferLength = (wcslen(strTodo) + 1) * sizeof(WCHAR);
PWSTR strValue = (PWSTR)CoTaskMemAlloc(bufferLength);
StringCbCopyW(strValue, bufferLength, strTodo);
*strContents = strValue;
return S_OK;
}
case REG_SZ:
case REG_EXPAND_SZ:
{
PWSTR strValue = (PWSTR)CoTaskMemAlloc(contentsLength + sizeof(WCHAR));
StringCbCopyNW(strValue, contentsLength + sizeof(WCHAR), (LPCWSTR)td, contentsLength);
*strContents = strValue;
return S_OK;
}
case REG_MULTI_SZ:
{
PCWSTR separator = L" "; // To match regedit
size_t sepChars = wcslen(separator);
int strings = 0;
int stringChars = 0;
PCWSTR strData = (PCWSTR)td;
while (*strData)
{ {
size_t len = wcslen(strData); PCWSTR strTodo = L"";
stringChars += len; DWORD bufferLength = (wcslen(strTodo) + 1) * sizeof(WCHAR);
strData += len + 1; // Skips null-terminator PWSTR strValue = (PWSTR)CoTaskMemAlloc(bufferLength);
strings++; StringCbCopyW(strValue, bufferLength, strTodo);
*strContents = strValue;
return S_OK;
} }
int cch = stringChars + (strings - 1) * sepChars + 1; case REG_SZ:
case REG_EXPAND_SZ:
PWSTR strValue = (PWSTR)CoTaskMemAlloc(cch * sizeof(WCHAR));
strValue[0] = 0;
strData = (PCWSTR)td;
while (*strData)
{ {
StrCatW(strValue, strData); PWSTR strValue = (PWSTR)CoTaskMemAlloc(contentsLength + sizeof(WCHAR));
strData += wcslen(strData) + 1; StringCbCopyNW(strValue, contentsLength + sizeof(WCHAR), (LPCWSTR)td, contentsLength);
if (*strData) *strContents = strValue;
StrCatW(strValue, separator); return S_OK;
} }
*strContents = strValue; case REG_MULTI_SZ:
return S_OK;
}
case REG_DWORD:
{
DWORD bufferLength = 64 * sizeof(WCHAR);
PWSTR strValue = (PWSTR)CoTaskMemAlloc(bufferLength);
StringCbPrintfW(strValue, bufferLength, L"0x%08x (%d)",
*(DWORD*)td, *(DWORD*)td);
*strContents = strValue;
return S_OK;
}
case REG_QWORD:
{
DWORD bufferLength = 64 * sizeof(WCHAR);
PWSTR strValue = (PWSTR)CoTaskMemAlloc(bufferLength);
StringCbPrintfW(strValue, bufferLength, L"0x%016llx (%lld)",
*(LARGE_INTEGER*)td, ((LARGE_INTEGER*)td)->QuadPart);
*strContents = strValue;
return S_OK;
}
case REG_BINARY:
{
DWORD bufferLength = (contentsLength * 3 + 1) * sizeof(WCHAR);
PWSTR strValue = (PWSTR)CoTaskMemAlloc(bufferLength);
PWSTR strTemp = strValue;
PBYTE data = (PBYTE)td;
for (DWORD i = 0; i < contentsLength; i++)
{ {
StringCbPrintfW(strTemp, bufferLength, L"%02x ", data[i]); PCWSTR separator = L" "; // To match regedit
strTemp += 3; size_t sepChars = wcslen(separator);
bufferLength -= 3; int strings = 0;
int stringChars = 0;
PCWSTR strData = (PCWSTR)td;
while (*strData)
{
size_t len = wcslen(strData);
stringChars += len;
strData += len + 1; // Skips null-terminator
strings++;
}
int cch = stringChars + (strings - 1) * sepChars + 1;
PWSTR strValue = (PWSTR)CoTaskMemAlloc(cch * sizeof(WCHAR));
strValue[0] = 0;
strData = (PCWSTR)td;
while (*strData)
{
StrCatW(strValue, strData);
strData += wcslen(strData) + 1;
if (*strData)
StrCatW(strValue, separator);
}
*strContents = strValue;
return S_OK;
}
case REG_DWORD:
{
DWORD bufferLength = 64 * sizeof(WCHAR);
PWSTR strValue = (PWSTR)CoTaskMemAlloc(bufferLength);
StringCbPrintfW(strValue, bufferLength, L"0x%08x (%d)",
*(DWORD*)td, *(DWORD*)td);
*strContents = strValue;
return S_OK;
}
case REG_QWORD:
{
DWORD bufferLength = 64 * sizeof(WCHAR);
PWSTR strValue = (PWSTR)CoTaskMemAlloc(bufferLength);
StringCbPrintfW(strValue, bufferLength, L"0x%016llx (%lld)",
*(LARGE_INTEGER*)td, ((LARGE_INTEGER*)td)->QuadPart);
*strContents = strValue;
return S_OK;
}
case REG_BINARY:
{
DWORD bufferLength = (contentsLength * 3 + 1) * sizeof(WCHAR);
PWSTR strValue = (PWSTR)CoTaskMemAlloc(bufferLength);
PWSTR strTemp = strValue;
PBYTE data = (PBYTE)td;
for (DWORD i = 0; i < contentsLength; i++)
{
StringCbPrintfW(strTemp, bufferLength, L"%02x ", data[i]);
strTemp += 3;
bufferLength -= 3;
}
*strContents = strValue;
return S_OK;
}
default:
{
PCWSTR strFormat = L"<Unimplemented value type %d>";
DWORD bufferLength = (wcslen(strFormat) + 15) * sizeof(WCHAR);
PWSTR strValue = (PWSTR)CoTaskMemAlloc(bufferLength);
StringCbPrintfW(strValue, bufferLength, strFormat, contentType);
*strContents = strValue;
return S_OK;
} }
*strContents = strValue;
return S_OK;
}
default:
{
PCWSTR strFormat = L"<Unimplemented value type %d>";
DWORD bufferLength = (wcslen(strFormat) + 15) * sizeof(WCHAR);
PWSTR strValue = (PWSTR)CoTaskMemAlloc(bufferLength);
StringCbPrintfW(strValue, bufferLength, strFormat, contentType);
*strContents = strValue;
return S_OK;
}
} }
} }

View file

@ -1,10 +1,10 @@
/* /*
* PROJECT: ReactOS shell extensions * PROJECT: NT Object Namespace shell extension
* LICENSE: GPL - See COPYING in the top level directory * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* FILE: dll/shellext/ntobjshex/regfolder.h * PURPOSE: System Registry folder class header
* PURPOSE: NT Object Namespace shell extension * COPYRIGHT: Copyright 2015-2017 David Quintana <gigaherz@gmail.com>
* PROGRAMMERS: David Quintana <gigaherz@gmail.com>
*/ */
#pragma once #pragma once
extern const GUID CLSID_RegistryFolder; extern const GUID CLSID_RegistryFolder;