From a5f9430988b4e72aac2e2f151284f5882bd9e33b Mon Sep 17 00:00:00 2001 From: David Quintana Date: Sat, 14 Mar 2015 04:04:27 +0000 Subject: [PATCH] [NTOBJSHEX] * Fix content type column to represent the correct type, or "Key". This column would contain the custom class name if it was ever assigned (I have not seen such a case). * Implement reading registry values when enumerating details. Now the registry browsing is semi-useful, albeit read-only. svn path=/trunk/; revision=66676 --- reactos/dll/shellext/ntobjshex/ntobjutil.cpp | 48 ++++++ reactos/dll/shellext/ntobjshex/ntobjutil.h | 4 +- reactos/dll/shellext/ntobjshex/regfolder.cpp | 155 +++++++++++++------ 3 files changed, 156 insertions(+), 51 deletions(-) diff --git a/reactos/dll/shellext/ntobjshex/ntobjutil.cpp b/reactos/dll/shellext/ntobjshex/ntobjutil.cpp index d0c3b97aeaa..933c87ceb69 100644 --- a/reactos/dll/shellext/ntobjshex/ntobjutil.cpp +++ b/reactos/dll/shellext/ntobjshex/ntobjutil.cpp @@ -372,6 +372,7 @@ HRESULT EnumerateRegistryKey(HDPA hdpa, PCWSTR path, HKEY root, UINT * hdpaCount entry->cb = FIELD_OFFSET(RegPidlEntry, entryName); entry->magic = REGISTRY_PIDL_MAGIC; entry->entryType = otype; + entry->contentType = type; if (cchName > 0) { @@ -415,3 +416,50 @@ HRESULT EnumerateRegistryKey(HDPA hdpa, PCWSTR path, HKEY root, UINT * hdpaCount return S_OK; } + +HRESULT ReadRegistryValue(HKEY root, PCWSTR path, PCWSTR valueName, PVOID * valueData, PDWORD valueLength) +{ + HKEY hkey; + + DWORD res; + if (root) + { + res = RegOpenKeyExW(root, *path == '\\' ? path + 1 : path, 0, STANDARD_RIGHTS_READ | KEY_QUERY_VALUE, &hkey); + } + else + { + res = NtOpenObject(KEY_OBJECT, (PHANDLE) &hkey, STANDARD_RIGHTS_READ | KEY_QUERY_VALUE, path); + } + if (!NT_SUCCESS(res)) + { + ERR("RegOpenKeyExW failed for path %S with status=%x\n", path, res); + return HRESULT_FROM_NT(res); + } + + res = RegQueryValueExW(hkey, valueName, NULL, NULL, NULL, valueLength); + + if (*valueLength > 0) + { + *valueData = (PBYTE) CoTaskMemAlloc(*valueLength); + + res = RegQueryValueExW(hkey, valueName, NULL, NULL, (PBYTE) *valueData, valueLength); + if (!NT_SUCCESS(res)) + { + CoTaskMemFree(*valueData); + *valueData = NULL; + + RegCloseKey(hkey); + + ERR("RegOpenKeyExW failed for path %S with status=%x\n", path, res); + return HRESULT_FROM_NT(res); + } + } + else + { + *valueData = NULL; + } + + RegCloseKey(hkey); + + return S_OK; +} \ No newline at end of file diff --git a/reactos/dll/shellext/ntobjshex/ntobjutil.h b/reactos/dll/shellext/ntobjshex/ntobjutil.h index 66f4dd25678..51988cad370 100644 --- a/reactos/dll/shellext/ntobjshex/ntobjutil.h +++ b/reactos/dll/shellext/ntobjshex/ntobjutil.h @@ -101,4 +101,6 @@ struct RegPidlEntry #include HRESULT EnumerateNtDirectory(HDPA hdpa, PCWSTR path, UINT * hdpaCount); -HRESULT EnumerateRegistryKey(HDPA hdpa, PCWSTR path, HKEY root, UINT * hdpaCount); \ No newline at end of file +HRESULT EnumerateRegistryKey(HDPA hdpa, PCWSTR path, HKEY root, UINT * hdpaCount); + +HRESULT ReadRegistryValue(HKEY root, PCWSTR path, PCWSTR valueName, PVOID * valueData, PDWORD valueLength); \ No newline at end of file diff --git a/reactos/dll/shellext/ntobjshex/regfolder.cpp b/reactos/dll/shellext/ntobjshex/regfolder.cpp index 298b6b41188..e130845d704 100644 --- a/reactos/dll/shellext/ntobjshex/regfolder.cpp +++ b/reactos/dll/shellext/ntobjshex/regfolder.cpp @@ -362,66 +362,88 @@ public: return (entry->entryType == REG_ENTRY_KEY); } + HRESULT FormatValueData(DWORD contentType, PVOID td, DWORD contentsLength, PCWSTR * strContents) + { + switch (contentType) + { + 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_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 (%d)", + *(LARGE_INTEGER*) td, ((LARGE_INTEGER*) td)->QuadPart); + *strContents = strValue; + return S_OK; + } + default: + { + PCWSTR strTodo = L""; + DWORD bufferLength = (wcslen(strTodo) + 1) * sizeof(WCHAR); + PWSTR strValue = (PWSTR) CoTaskMemAlloc(bufferLength); + StringCbCopyW(strValue, bufferLength, strTodo); + *strContents = strValue; + return S_OK; + } + } + } + HRESULT FormatContentsForDisplay(RegPidlEntry * info, PCWSTR * strContents) { PVOID td = (((PBYTE) info) + FIELD_OFFSET(RegPidlEntry, entryName) + info->entryNameLength + sizeof(WCHAR)); - if (info->contentsLength > 0) + if (info->entryType == REG_ENTRY_VALUE_WITH_CONTENT) { - if (info->entryType == REG_ENTRY_VALUE_WITH_CONTENT) + if (info->contentsLength > 0) { - switch (info->contentType) - { - case REG_SZ: - case REG_EXPAND_SZ: - { - PWSTR strValue = (PWSTR) CoTaskMemAlloc(info->contentsLength + sizeof(WCHAR)); - StringCbCopyNW(strValue, info->contentsLength + sizeof(WCHAR), (LPCWSTR) td, info->contentsLength); - *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 (%d)", - *(LARGE_INTEGER*) td, ((LARGE_INTEGER*) td)->QuadPart); - *strContents = strValue; - return S_OK; - } - default: - { - PCWSTR strTodo = L""; - DWORD bufferLength = (wcslen(strTodo) + 1) * sizeof(WCHAR); - PWSTR strValue = (PWSTR) CoTaskMemAlloc(bufferLength); - StringCbCopyW(strValue, bufferLength, strTodo); - *strContents = strValue; - return S_OK; - } - } + return FormatValueData(info->contentType, td, info->contentsLength, strContents); } - else + } + else if (info->entryType == REG_ENTRY_VALUE) + { + PVOID valueData; + DWORD valueLength; + HRESULT hr = ReadRegistryValue(NULL, m_ntPath, info->entryName, &valueData, &valueLength); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + if (valueLength > 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; + hr = FormatValueData(info->contentType, valueData, valueLength, strContents); + + CoTaskMemFree(valueData); + + return hr; } } else { - PCWSTR strEmpty = L"(Empty)"; + PCWSTR strEmpty = L""; DWORD bufferLength = (wcslen(strEmpty) + 1) * sizeof(WCHAR); PWSTR strValue = (PWSTR) CoTaskMemAlloc(bufferLength); StringCbCopyW(strValue, bufferLength, strEmpty); @@ -429,6 +451,12 @@ public: return S_OK; } + PCWSTR strEmpty = L"(Empty)"; + DWORD bufferLength = (wcslen(strEmpty) + 1) * sizeof(WCHAR); + PWSTR strValue = (PWSTR) CoTaskMemAlloc(bufferLength); + StringCbCopyW(strValue, bufferLength, strEmpty); + *strContents = strValue; + return S_OK; } }; @@ -1003,11 +1031,26 @@ HRESULT STDMETHODCALLTYPE CRegistryFolder::GetDetailsEx( { if (pscid->pid == PID_STG_NAME) { - return MakeVariantString(pv, info->entryName); + if (info->entryNameLength > 0) + { + return MakeVariantString(pv, info->entryName); + } + return MakeVariantString(pv, L"(Default)"); } else if (pscid->pid == PID_STG_STORAGETYPE) { - return MakeVariantString(pv, RegistryTypeNames[info->entryType]); + if (info->entryType == REG_ENTRY_KEY) + { + if (info->contentsLength > 0) + { + PWSTR td = (PWSTR)(((PBYTE) info) + FIELD_OFFSET(RegPidlEntry, entryName) + info->entryNameLength + sizeof(WCHAR)); + + return MakeVariantString(pv, td); + } + return MakeVariantString(pv, L"Key"); + } + + return MakeVariantString(pv, RegistryTypeNames[info->contentType]); } else if (pscid->pid == PID_STG_CONTENTS) { @@ -1066,6 +1109,18 @@ HRESULT STDMETHODCALLTYPE CRegistryFolder::GetDetailsOf( case REGISTRY_COLUMN_TYPE: psd->fmt = LVCFMT_LEFT; + 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)); case REGISTRY_COLUMN_VALUE: