[NTOBJSHEX]

* Implement loading the hardcoded list of root keys.
* Add support for root keys to the registry PIDL structure.
* Add support for root-key PIDLs in the registry folder.
* Implement loading root keys when no path is specified.
* Expose the registry folder as a namespace extension to My Computer.
* Make the namespace extension folder names load from resources.
* Add icons for registry keys and values.
CORE-9244 #resolve #comment Basic registry browsing should now be functional. Any other issues (including editing capability), would go in followup issues.

svn path=/trunk/; revision=66719
This commit is contained in:
David Quintana 2015-03-15 00:00:13 +00:00
parent 42d0a9c883
commit 477fb78355
14 changed files with 219 additions and 40 deletions

View file

@ -2,5 +2,6 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
STRINGTABLE
BEGIN
IDS_NAME "NT Object Namespace"
IDS_NTOBJFLD_NAME "NT Object Namespace"
IDS_REGISTRY_NAME "System Registry"
END

View file

@ -3,5 +3,6 @@ LANGUAGE LANG_ROMANIAN, SUBLANG_NEUTRAL
STRINGTABLE
BEGIN
IDS_NAME "Spațiu de nume Obiect NT"
IDS_NTOBJFLD_NAME "Spațiu de nume Obiect NT"
IDS_REGISTRY_NAME "System Registry"
END

View file

@ -107,6 +107,11 @@ public:
*piIndex = -IDI_NTOBJECTPORT;
*pwFlags = flags;
return S_OK;
case KEY_OBJECT:
GetModuleFileNameW(g_hInstance, szIconFile, cchMax);
*piIndex = -IDI_REGISTRYKEY;
*pwFlags = flags;
return S_OK;
default:
GetModuleFileNameW(g_hInstance, szIconFile, cchMax);
*piIndex = -IDI_NTOBJECTITEM;
@ -624,7 +629,7 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::BindToObject(
if (info->objectType == KEY_OBJECT)
{
hr = ShellObjectCreatorInit<CRegistryFolder>(fullPidl, path, IID_PPV_ARG(IShellFolder, &psfChild));
hr = ShellObjectCreatorInit<CRegistryFolder>(fullPidl, path, (HKEY)NULL, IID_PPV_ARG(IShellFolder, &psfChild));
}
else
{

View file

@ -14,6 +14,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(ntobjshex);
BEGIN_OBJECT_MAP(ObjectMap)
OBJECT_ENTRY(CLSID_NtObjectFolder, CNtObjectFolder)
OBJECT_ENTRY(CLSID_RegistryFolder, CRegistryFolder)
END_OBJECT_MAP()
HINSTANCE g_hInstance;

View file

@ -12,8 +12,11 @@ IDI_NTOBJECTDIROPEN ICON "resources/3.ico"
IDI_NTOBJECTITEM ICON "resources/4.ico"
IDI_NTOBJECTDEVICE ICON "resources/5.ico"
IDI_NTOBJECTPORT ICON "resources/6.ico"
IDI_REGISTRYKEY ICON "resources/7.ico"
IDI_REGISTRYVALUE ICON "resources/8.ico"
IDR_NTOBJECTFOLDER REGISTRY "resources/rgs/ntobjectfolder.rgs"
IDR_REGISTRYFOLDER REGISTRY "resources/rgs/regfolder.rgs"
/* UTF-8 */
#pragma code_page(65001)

View file

@ -417,6 +417,62 @@ HRESULT EnumerateRegistryKey(HDPA hdpa, PCWSTR path, HKEY root, UINT * hdpaCount
return S_OK;
}
HRESULT EnumerateRootKeys(HDPA hdpa, UINT * hdpaCount)
{
*hdpaCount = 0;
static struct {
HKEY key;
PCWSTR keyName;
} rootKeys [] = {
{ HKEY_CLASSES_ROOT, L"HKEY_CLASSES_ROOT" },
{ HKEY_CURRENT_USER, L"HKEY_CURRENT_USER" },
{ HKEY_LOCAL_MACHINE, L"HKEY_LOCAL_MACHINE" },
{ HKEY_USERS, L"HKEY_USERS" },
{ HKEY_CURRENT_CONFIG, L"HKEY_CURRENT_CONFIG" }
};
for (UINT i = 0; i < _countof(rootKeys); i++)
{
PCWSTR name = rootKeys[i].keyName;
DWORD cchName = wcslen(rootKeys[i].keyName);
REG_ENTRY_TYPE otype = REG_ENTRY_ROOT;
DWORD entryBufferLength = FIELD_OFFSET(RegPidlEntry, entryName) + sizeof(WCHAR) + cchName * sizeof(WCHAR);
RegPidlEntry* entry = (RegPidlEntry*) CoTaskMemAlloc(entryBufferLength);
if (!entry)
return E_OUTOFMEMORY;
memset(entry, 0, entryBufferLength);
entry->cb = FIELD_OFFSET(NtPidlEntry, entryName);
entry->magic = REGISTRY_PIDL_MAGIC;
entry->entryType = otype;
entry->rootKey = rootKeys[i].key;
if (cchName > 0)
{
entry->entryNameLength = cchName * sizeof(WCHAR);
StringCbCopyNW(entry->entryName, entryBufferLength, name, entry->entryNameLength);
entry->cb += entry->entryNameLength + sizeof(WCHAR);
}
else
{
entry->entryNameLength = 0;
entry->entryName[0] = 0;
entry->cb += sizeof(WCHAR);
}
DPA_AppendPtr(hdpa, entry);
(*hdpaCount)++;
}
return S_OK;
}
HRESULT ReadRegistryValue(HKEY root, PCWSTR path, PCWSTR valueName, PVOID * valueData, PDWORD valueLength)
{
HKEY hkey;

View file

@ -72,6 +72,7 @@ struct NtPidlSymlinkData
// REGISTRY browser
enum REG_ENTRY_TYPE
{
REG_ENTRY_ROOT,
REG_ENTRY_KEY,
REG_ENTRY_VALUE,
REG_ENTRY_VALUE_WITH_CONTENT
@ -88,10 +89,16 @@ struct RegPidlEntry
USHORT entryNameLength;
// For Value entries, this contains the value contents, if it's resonably small.
// For Key entries, this contains the custom class name
DWORD contentType;
USHORT contentsLength;
union {
struct {
// For Value entries, this contains the value contents, if it's resonably small.
// For Key entries, this contains the custom class name
DWORD contentType;
USHORT contentsLength;
};
HKEY rootKey;
};
WCHAR entryName[ANYSIZE_ARRAY];
@ -102,5 +109,6 @@ struct RegPidlEntry
HRESULT EnumerateNtDirectory(HDPA hdpa, PCWSTR path, UINT * hdpaCount);
HRESULT EnumerateRegistryKey(HDPA hdpa, PCWSTR path, HKEY root, UINT * hdpaCount);
HRESULT EnumerateRootKeys(HDPA hdpa, UINT * hdpaCount);
HRESULT ReadRegistryValue(HKEY root, PCWSTR path, PCWSTR valueName, PVOID * valueData, PDWORD valueLength);

View file

@ -86,6 +86,7 @@ public:
switch (entry->entryType)
{
case REG_ENTRY_KEY:
case REG_ENTRY_ROOT:
GetModuleFileNameW(g_hInstance, szIconFile, cchMax);
*piIndex = -IDI_REGISTRYKEY;
*pwFlags = flags;
@ -126,6 +127,7 @@ class CRegistryPidlManager
{
private:
PWSTR m_ntPath;
HKEY m_hRoot;
HDPA m_hDpa;
UINT m_hDpaCount;
@ -146,6 +148,7 @@ private:
public:
CRegistryPidlManager() :
m_ntPath(NULL),
m_hRoot(NULL),
m_hDpa(NULL),
m_hDpaCount(0)
{
@ -156,18 +159,28 @@ public:
DPA_DestroyCallback(m_hDpa, s_DpaDeleteCallback, this);
}
HRESULT Initialize(PWSTR ntPath)
HRESULT Initialize(PWSTR ntPath, HKEY hRoot)
{
m_ntPath = ntPath;
m_hRoot = hRoot;
m_hDpa = DPA_Create(10);
if (!m_hDpa)
return E_OUTOFMEMORY;
HRESULT hr = EnumerateRegistryKey(m_hDpa, m_ntPath, NULL, &m_hDpaCount);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
if (wcslen(m_ntPath) == 0 && m_hRoot == NULL)
{
HRESULT hr = EnumerateRootKeys(m_hDpa, &m_hDpaCount);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
}
else
{
HRESULT hr = EnumerateRegistryKey(m_hDpa, m_ntPath, m_hRoot, &m_hDpaCount);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
}
return S_OK;
}
@ -346,7 +359,8 @@ public:
ULONG mask = inMask ? *inMask : 0xFFFFFFFF;
ULONG flags = 0;
if (entry->entryType == REG_ENTRY_KEY)
if ((entry->entryType == REG_ENTRY_KEY) ||
(entry->entryType == REG_ENTRY_ROOT))
flags |= SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_BROWSABLE;
return flags & mask;
@ -359,7 +373,8 @@ public:
if (FAILED_UNEXPECTEDLY(hr))
return FALSE;
return (entry->entryType == REG_ENTRY_KEY);
return (entry->entryType == REG_ENTRY_KEY) ||
(entry->entryType == REG_ENTRY_ROOT);
}
HRESULT FormatValueData(DWORD contentType, PVOID td, DWORD contentsLength, PCWSTR * strContents)
@ -430,7 +445,14 @@ public:
DWORD valueLength;
HRESULT hr = ReadRegistryValue(NULL, m_ntPath, info->entryName, &valueData, &valueLength);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
{
PCWSTR strEmpty = L"(Error reading value)";
DWORD bufferLength = (wcslen(strEmpty) + 1) * sizeof(WCHAR);
PWSTR strValue = (PWSTR) CoTaskMemAlloc(bufferLength);
StringCbCopyW(strValue, bufferLength, strEmpty);
*strContents = strValue;
return S_OK;
}
if (valueLength > 0)
{
@ -522,6 +544,7 @@ public:
switch (tinfo->entryType)
{
case REG_ENTRY_KEY:
case REG_ENTRY_ROOT:
flagsOk = (m_Flags & SHCONTF_FOLDERS) != 0;
break;
default:
@ -651,19 +674,26 @@ HRESULT STDMETHODCALLTYPE CRegistryFolder::BindToObject(
if (FAILED_UNEXPECTEDLY(hr))
return hr;
WCHAR path[MAX_PATH];
StringCbCopyW(path, _countof(path), m_NtPath);
PathAppendW(path, info->entryName);
LPITEMIDLIST first = ILCloneFirst(pidl);
LPCITEMIDLIST rest = ILGetNext(pidl);
LPITEMIDLIST fullPidl = ILCombine(m_shellPidl, first);
CComPtr<IShellFolder> psfChild;
hr = ShellObjectCreatorInit<CRegistryFolder>(fullPidl, path, IID_PPV_ARG(IShellFolder, &psfChild));
if (wcslen(m_NtPath) == 0 && m_hRoot == NULL)
{
hr = ShellObjectCreatorInit<CRegistryFolder>(fullPidl, L"", info->rootKey, IID_PPV_ARG(IShellFolder, &psfChild));
}
else
{
WCHAR path[MAX_PATH];
StringCbCopyW(path, _countof(path), m_NtPath);
PathAppendW(path, info->entryName);
hr = ShellObjectCreatorInit<CRegistryFolder>(fullPidl, path, m_hRoot, IID_PPV_ARG(IShellFolder, &psfChild));
}
ILFree(fullPidl);
ILFree(first);
@ -928,8 +958,9 @@ HRESULT STDMETHODCALLTYPE CRegistryFolder::GetClassID(CLSID *lpClassId)
HRESULT STDMETHODCALLTYPE CRegistryFolder::Initialize(LPCITEMIDLIST pidl)
{
m_shellPidl = ILClone(pidl);
m_hRoot = NULL;
PCWSTR ntPath = L"\\REGISTRY";
PCWSTR ntPath = L"";
if (!m_PidlManager)
{
@ -938,19 +969,20 @@ HRESULT STDMETHODCALLTYPE CRegistryFolder::Initialize(LPCITEMIDLIST pidl)
StringCbCopy(m_NtPath, _countof(m_NtPath), ntPath);
}
return m_PidlManager->Initialize(m_NtPath);
return m_PidlManager->Initialize(m_NtPath, m_hRoot);
}
// Internal
HRESULT STDMETHODCALLTYPE CRegistryFolder::Initialize(LPCITEMIDLIST pidl, PCWSTR ntPath)
HRESULT STDMETHODCALLTYPE CRegistryFolder::Initialize(LPCITEMIDLIST pidl, PCWSTR ntPath, HKEY hRoot)
{
m_shellPidl = ILClone(pidl);
m_hRoot = hRoot;
if (!m_PidlManager)
m_PidlManager = new CRegistryPidlManager();
StringCbCopy(m_NtPath, _countof(m_NtPath), ntPath);
return m_PidlManager->Initialize(m_NtPath);
return m_PidlManager->Initialize(m_NtPath, m_hRoot);
}
// IPersistFolder2
@ -1039,6 +1071,11 @@ HRESULT STDMETHODCALLTYPE CRegistryFolder::GetDetailsEx(
}
else if (pscid->pid == PID_STG_STORAGETYPE)
{
if (info->entryType == REG_ENTRY_ROOT)
{
return MakeVariantString(pv, L"Key");
}
if (info->entryType == REG_ENTRY_KEY)
{
if (info->contentsLength > 0)
@ -1109,6 +1146,11 @@ HRESULT STDMETHODCALLTYPE CRegistryFolder::GetDetailsOf(
case REGISTRY_COLUMN_TYPE:
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)

View file

@ -21,6 +21,7 @@ class CRegistryFolder :
{
CRegistryPidlManager * m_PidlManager;
HKEY m_hRoot;
WCHAR m_NtPath[MAX_PATH];
LPITEMIDLIST m_shellPidl;
@ -136,11 +137,11 @@ public:
virtual HRESULT STDMETHODCALLTYPE MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam);
// Internal
HRESULT STDMETHODCALLTYPE Initialize(LPCITEMIDLIST pidl, PCWSTR ntPath);
HRESULT STDMETHODCALLTYPE Initialize(LPCITEMIDLIST pidl, PCWSTR ntPath, HKEY hRoot);
static HRESULT CALLBACK DefCtxMenuCallback(IShellFolder *, HWND, IDataObject *, UINT, WPARAM, LPARAM);
DECLARE_REGISTRY_RESOURCEID(IDR_NTOBJECTFOLDER)
DECLARE_REGISTRY_RESOURCEID(IDR_REGISTRYFOLDER)
DECLARE_NOT_AGGREGATABLE(CRegistryFolder)
DECLARE_PROTECT_FINAL_CONSTRUCT()

View file

@ -1,15 +1,16 @@
#pragma once
#define IDI_NTOBJECTFOLDER 1
#define IDI_NTOBJECTDIR 2
#define IDI_NTOBJECTDIROPEN 3
#define IDI_NTOBJECTITEM 4
#define IDI_NTOBJECTDEVICE 5
#define IDI_NTOBJECTPORT 6
#define IDI_NTOBJECTFOLDER 1
#define IDI_NTOBJECTDIR 2
#define IDI_NTOBJECTDIROPEN 3
#define IDI_NTOBJECTITEM 4
#define IDI_NTOBJECTDEVICE 5
#define IDI_NTOBJECTPORT 6
#define IDI_REGISTRYKEY 7
#define IDI_REGISTRYVALUE 8
#define IDI_REGISTRYKEY 32
#define IDI_REGISTRYVALUE 33
#define IDS_NTOBJFLD_NAME 101
#define IDS_REGISTRY_NAME 102
#define IDS_NAME 101
#define IDR_NTOBJECTFOLDER 1001
#define IDR_NTOBJECTFOLDER 1001
#define IDR_REGISTRYFOLDER 1002

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

View file

@ -7,7 +7,7 @@ HKCR
NTObjShEx.NTDirectory = s 'NT Namespace Directory Class'
{
CLSID = s '{845B0FB2-66E0-416B-8F91-314E23F7C12D}'
CurVer = s 'WMIFldr.CWMIFldr.1'
CurVer = s 'NTObjShEx.NTDirectory.1'
}
NoRemove CLSID
{
@ -20,6 +20,7 @@ HKCR
val ThreadingModel = s 'Both'
}
val InfoTip = s 'Allows browsing of the NT Object Namespace'
val LocalizedString = s '@%MODULE%,-101'
DefaultIcon = s '%MODULE%,0'
ShellFolder
{
@ -45,7 +46,7 @@ HKLM
{
NoRemove NameSpace
{
ForceRemove {845B0FB2-66E0-416B-8F91-314E23F7C12D} = s 'NT Object Namespace Extension'
ForceRemove {845B0FB2-66E0-416B-8F91-314E23F7C12D} = s 'NT Object Namespace'
{
}
}

View file

@ -0,0 +1,59 @@
HKCR
{
NTObjShEx.RegFolder.1 = s 'Registry Folder Class'
{
CLSID = s '{1C6D6E08-2332-4A7B-A94D-6432DB2B5AE6}'
}
NTObjShEx.RegFolder = s 'Registry Folder Class'
{
CLSID = s '{1C6D6E08-2332-4A7B-A94D-6432DB2B5AE6}'
CurVer = s 'NTObjShEx.RegFolder.1'
}
NoRemove CLSID
{
ForceRemove {1C6D6E08-2332-4A7B-A94D-6432DB2B5AE6} = s 'System Registry Namespace Extension'
{
ProgID = s 'NTObjShEx.RegFolder.1'
VersionIndependentProgID = s 'NTObjShEx.RegFolder'
InprocServer32 = s '%MODULE%'
{
val ThreadingModel = s 'Both'
}
val InfoTip = s 'Allows browsing of the System Registry'
val LocalizedString = s '@%MODULE%,-102'
DefaultIcon = s '%MODULE%,-7'
ShellFolder
{
val Attributes = d '0xA8000000'
val BrowserFlags = d '0x22'
}
}
}
}
HKLM
{
NoRemove Software
{
NoRemove Microsoft
{
NoRemove Windows
{
NoRemove CurrentVersion
{
NoRemove Explorer
{
NoRemove MyComputer
{
NoRemove NameSpace
{
ForceRemove {1C6D6E08-2332-4A7B-A94D-6432DB2B5AE6} = s 'System Registry'
{
}
}
}
}
}
}
}
}
}