mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-09-03 04:13:31 +00:00
[NTOBJSHEX]
* Fix all the size calculations broken by r66425. * Fix subfolder navigation (in windows). * Fix enumeration skipping the last item. * Add the beginning of a registry folder implementation. It doesn't display all data types yet, and it doesn't support editing or searching. CORE-9244 svn path=/trunk/; revision=66426
This commit is contained in:
@@ -19,6 +19,7 @@ add_library(ntobjshex SHARED
|
||||
ntobjshex.cpp
|
||||
ntobjutil.cpp
|
||||
ntobjshex.rc
|
||||
regfolder.cpp
|
||||
${CMAKE_CURRENT_BINARY_DIR}/ntobjshex.def)
|
||||
|
||||
list(APPEND atl_rc_deps
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "precomp.h"
|
||||
#include "ntobjutil.h"
|
||||
#include <ntquery.h>
|
||||
#include "util.h"
|
||||
|
||||
#define SHCIDS_ALLFIELDS 0x80000000L
|
||||
#define SHCIDS_CANONICALONLY 0x10000000L
|
||||
@@ -32,45 +33,6 @@ enum NtObjectColumns
|
||||
NTOBJECT_COLUMN_LINKTARGET = 3,
|
||||
};
|
||||
|
||||
static HRESULT MakeStrRetFromString(LPCWSTR string, DWORD cbLength, STRRET * str)
|
||||
{
|
||||
str->uType = STRRET_WSTR;
|
||||
|
||||
DWORD blen = cbLength + sizeof(WCHAR);
|
||||
str->pOleStr = (LPWSTR) CoTaskMemAlloc(blen);
|
||||
return StringCbCopyNW(str->pOleStr, blen, string, cbLength);
|
||||
}
|
||||
|
||||
static HRESULT MakeStrRetFromString(LPCWSTR string, STRRET * str)
|
||||
{
|
||||
DWORD stringLength = wcslen(string) * sizeof(WCHAR);
|
||||
return MakeStrRetFromString(string, stringLength, str);
|
||||
}
|
||||
|
||||
static HRESULT MakeVariantString(VARIANT * pv, PCWSTR string)
|
||||
{
|
||||
V_VT(pv) = VT_BSTR;
|
||||
V_BSTR(pv) = SysAllocString(string);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT GetFullName(PCIDLIST_ABSOLUTE pidl, DWORD uFlags, PWSTR strName, DWORD cchName)
|
||||
{
|
||||
CComPtr<IShellFolder> psfDesktop;
|
||||
STRRET str;
|
||||
HRESULT hr;
|
||||
|
||||
hr = SHGetDesktopFolder(&psfDesktop);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
hr = psfDesktop->GetDisplayNameOf(pidl, uFlags, &str);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
return StrRetToBufW(&str, pidl, strName, cchName);
|
||||
}
|
||||
|
||||
class CNtObjectFolderContextMenu :
|
||||
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
||||
public IContextMenu
|
||||
@@ -113,7 +75,8 @@ public:
|
||||
const NtPidlEntry * entry = (NtPidlEntry *) m_pcidlChild;
|
||||
|
||||
if ((entry->objectType == DIRECTORY_OBJECT) ||
|
||||
(entry->objectType == SYMBOLICLINK_OBJECT))
|
||||
(entry->objectType == SYMBOLICLINK_OBJECT) ||
|
||||
(entry->objectType == KEY_OBJECT))
|
||||
{
|
||||
MENUITEMINFOW mii;
|
||||
|
||||
@@ -373,6 +336,13 @@ public:
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
NtPidlEntry * info = (NtPidlEntry *) pcidl;
|
||||
if ((info->cb < sizeof(NtPidlEntry)) || (info->magic != NT_OBJECT_PIDL_MAGIC))
|
||||
{
|
||||
ERR("FindPidlInList: Requested pidl is not of the correct type.\n");
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
TRACE("Searching for pidl { cb=%d } in a list of %d items\n", pcidl->mkid.cb, m_hDpaCount);
|
||||
|
||||
for (UINT i = 0; i < m_hDpaCount; i++)
|
||||
@@ -395,7 +365,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
TRACE("Pidl not found\n");
|
||||
ERR("PIDL NOT FOUND: Requested filename: %S\n", info->entryName);
|
||||
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
@@ -537,6 +507,9 @@ public:
|
||||
if (entry->objectType == SYMBOLICLINK_OBJECT)
|
||||
flags |= SFGAO_LINK | SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_BROWSABLE;
|
||||
|
||||
if (entry->objectType == KEY_OBJECT)
|
||||
flags |= SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_BROWSABLE;
|
||||
|
||||
return flags & mask;
|
||||
}
|
||||
|
||||
@@ -605,6 +578,7 @@ public:
|
||||
{
|
||||
case SYMBOLICLINK_OBJECT:
|
||||
case DIRECTORY_OBJECT:
|
||||
case KEY_OBJECT:
|
||||
flagsOk = (m_Flags & SHCONTF_FOLDERS) != 0;
|
||||
break;
|
||||
default:
|
||||
@@ -613,7 +587,7 @@ public:
|
||||
}
|
||||
} while (m_Index < m_Count && !flagsOk);
|
||||
|
||||
if (m_Index < m_Count)
|
||||
if (flagsOk)
|
||||
{
|
||||
if (rgelt)
|
||||
rgelt[i] = m_Folder->GetManager().CreatePidlFromItem(tinfo);
|
||||
@@ -660,12 +634,6 @@ public:
|
||||
//-----------------------------------------------------------------------------
|
||||
// CNtObjectFolder
|
||||
|
||||
extern "C"
|
||||
HRESULT WINAPI CMergedFolder_Constructor(REFIID riid, LPVOID *ppv)
|
||||
{
|
||||
return ShellObjectCreator<CNtObjectFolder>(riid, ppv);
|
||||
}
|
||||
|
||||
CNtObjectFolder::CNtObjectFolder() :
|
||||
m_PidlManager(NULL),
|
||||
m_shellPidl(NULL)
|
||||
@@ -674,6 +642,7 @@ CNtObjectFolder::CNtObjectFolder() :
|
||||
|
||||
CNtObjectFolder::~CNtObjectFolder()
|
||||
{
|
||||
TRACE("Destroying CNtObjectFolder %p\n", this);
|
||||
}
|
||||
|
||||
// IShellFolder
|
||||
@@ -697,7 +666,7 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::ParseDisplayName(
|
||||
if (pdwAttributes)
|
||||
*pdwAttributes = 0;
|
||||
|
||||
TRACE("ParseDisplayName name=%S\n", lpszDisplayName);
|
||||
TRACE("CNtObjectFolder::ParseDisplayName name=%S (ntPath=%S)\n", lpszDisplayName, m_NtPath);
|
||||
|
||||
hr = m_PidlManager->FindByName(lpszDisplayName, &info);
|
||||
if (FAILED(hr))
|
||||
@@ -743,36 +712,64 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::BindToObject(
|
||||
return E_ACCESSDENIED;
|
||||
|
||||
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);
|
||||
|
||||
if (info->objectType == SYMBOLICLINK_OBJECT)
|
||||
{
|
||||
NtPidlSymlinkData * symlink = (NtPidlSymlinkData*) (((PBYTE) info) + sizeof(NtPidlEntry) + info->entryNameLength + sizeof(WCHAR));
|
||||
NtPidlSymlinkData * symlink = (NtPidlSymlinkData*) (((PBYTE) info) + FIELD_OFFSET(NtPidlEntry,entryName) + info->entryNameLength + sizeof(WCHAR));
|
||||
|
||||
if (symlink->targetNameLength > 0)
|
||||
{
|
||||
StringCbCopyW(path, _countof(path), symlink->targetName);
|
||||
if (symlink->targetName[1] == L':' && isalphaW(symlink->targetName[0]))
|
||||
{
|
||||
ERR("TODO: Navigating to WIN32 PATH from NT PATH.\n");
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
StringCbCopyW(path, _countof(path), L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{845B0FB2-66E0-416B-8F91-314E23F7C12D}");
|
||||
PathAppend(path, symlink->targetName);
|
||||
|
||||
CComPtr<IShellFolder> psfDesktop;
|
||||
hr = SHGetDesktopFolder(&psfDesktop);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
hr = psfDesktop->ParseDisplayName(NULL, NULL, path, NULL, &first, NULL);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
}
|
||||
else
|
||||
{
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
}
|
||||
|
||||
CComPtr<IShellFolder> psfChild;
|
||||
|
||||
if (info->objectType == KEY_OBJECT)
|
||||
{
|
||||
hr = ShellObjectCreatorInit<CRegistryFolder>(fullPidl, path, IID_PPV_ARG(IShellFolder, &psfChild));
|
||||
}
|
||||
else
|
||||
{
|
||||
StringCbCopyW(path, _countof(path), m_NtPath);
|
||||
|
||||
PathAppendW(path, info->entryName);
|
||||
|
||||
DbgPrint("BindToObject for Directory %S\n", path);
|
||||
hr = ShellObjectCreatorInit<CNtObjectFolder>(fullPidl, path, IID_PPV_ARG(IShellFolder, &psfChild));
|
||||
}
|
||||
|
||||
LPITEMIDLIST fullPidl = ILCombine(m_shellPidl, pidl);
|
||||
|
||||
hr = ShellObjectCreatorInit<CNtObjectFolder>(fullPidl, path, riid, ppvOut);
|
||||
|
||||
ILFree(fullPidl);
|
||||
ILFree(first);
|
||||
|
||||
return hr;
|
||||
if (rest->mkid.cb > 0)
|
||||
{
|
||||
return psfChild->BindToObject(rest, pbcReserved, riid, ppvOut);
|
||||
}
|
||||
|
||||
return psfChild->QueryInterface(riid, ppvOut);
|
||||
}
|
||||
|
||||
return E_NOTIMPL;
|
||||
@@ -953,18 +950,70 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::GetClassID(CLSID *lpClassId)
|
||||
// IPersistFolder
|
||||
HRESULT STDMETHODCALLTYPE CNtObjectFolder::Initialize(LPCITEMIDLIST pidl)
|
||||
{
|
||||
return Initialize(pidl, L"\\");
|
||||
m_shellPidl = ILClone(pidl);
|
||||
|
||||
PCWSTR ntPath = L"\\";
|
||||
|
||||
#if 0
|
||||
WCHAR debugTemp[MAX_PATH];
|
||||
GetFullName(m_shellPidl, SHGDN_FORPARSING, debugTemp, _countof(debugTemp));
|
||||
DbgPrint("INITIALIZE CRegistryFolder PIDL PATH: %S (ntPath: %S)\n", debugTemp, ntPath);
|
||||
|
||||
if (ntPath[wcslen(ntPath)-1] == L'\\' && debugTemp[wcslen(debugTemp) - 1] != L'\\')
|
||||
wcscat(debugTemp, L"\\");
|
||||
|
||||
PCWSTR guidTemp = L"::{845B0FB2-66E0-416B-8F91-314E23F7C12D}";
|
||||
|
||||
PCWSTR findTemp = StrStrW(debugTemp, guidTemp);
|
||||
PCWSTR nextTemp = findTemp + wcslen(guidTemp);
|
||||
|
||||
if (wcscmp(nextTemp, ntPath))
|
||||
{
|
||||
DbgPrint("WHAT THE F, the NT PATH DOES NOT MATCH\n");
|
||||
return E_FAIL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!m_PidlManager)
|
||||
{
|
||||
m_PidlManager = new CNtObjectPidlManager();
|
||||
|
||||
StringCbCopy(m_NtPath, _countof(m_NtPath), ntPath);
|
||||
}
|
||||
|
||||
return m_PidlManager->Initialize(m_NtPath);
|
||||
}
|
||||
|
||||
// Internal
|
||||
HRESULT STDMETHODCALLTYPE CNtObjectFolder::Initialize(LPCITEMIDLIST pidl, PCWSTR ntPath)
|
||||
{
|
||||
m_shellPidl = ILClone(pidl);
|
||||
StringCbCopy(m_NtPath, _countof(m_NtPath), ntPath);
|
||||
TRACE("INITIALIZE %p CNtObjectFolder with ntPath %S\n", this, ntPath);
|
||||
|
||||
#if 0
|
||||
m_shellPidl = ILClone(pidl);
|
||||
WCHAR debugTemp[MAX_PATH];
|
||||
GetFullName(m_shellPidl, SHGDN_FORPARSING, debugTemp, _countof(debugTemp));
|
||||
DbgPrint("INITIALIZE CNtObjectFolder PIDL PATH: %S (ntPath: %S)\n", debugTemp, ntPath);
|
||||
|
||||
if (ntPath[wcslen(ntPath) - 1] == L'\\' && debugTemp[wcslen(debugTemp) - 1] != L'\\')
|
||||
wcscat(debugTemp, L"\\");
|
||||
|
||||
PCWSTR guidTemp = L"::{845B0FB2-66E0-416B-8F91-314E23F7C12D}";
|
||||
|
||||
PCWSTR findTemp = StrStrW(debugTemp, guidTemp);
|
||||
PCWSTR nextTemp = findTemp + wcslen(guidTemp);
|
||||
|
||||
if (wcscmp(nextTemp, ntPath))
|
||||
{
|
||||
DbgPrint("WHAT THE F, the NT PATH DOES NOT MATCH\n");
|
||||
return E_FAIL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!m_PidlManager)
|
||||
m_PidlManager = new CNtObjectPidlManager();
|
||||
|
||||
StringCbCopy(m_NtPath, _countof(m_NtPath), ntPath);
|
||||
return m_PidlManager->Initialize(m_NtPath);
|
||||
}
|
||||
|
||||
@@ -1055,7 +1104,7 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::GetDetailsEx(
|
||||
{
|
||||
if (info->objectType < 0)
|
||||
{
|
||||
NtPidlTypeData * td = (NtPidlTypeData*) (((PBYTE) info) + sizeof(NtPidlEntry) + info->entryNameLength + sizeof(WCHAR));
|
||||
NtPidlTypeData * td = (NtPidlTypeData*) (((PBYTE) info) + FIELD_OFFSET(NtPidlEntry,entryName) + info->entryNameLength + sizeof(WCHAR));
|
||||
|
||||
if (td->typeNameLength > 0)
|
||||
{
|
||||
@@ -1089,7 +1138,7 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::GetDetailsEx(
|
||||
{
|
||||
if (info->objectType == SYMBOLICLINK_OBJECT)
|
||||
{
|
||||
NtPidlSymlinkData * symlink = (NtPidlSymlinkData*) (((PBYTE) info) + sizeof(NtPidlEntry) + info->entryNameLength + sizeof(WCHAR));
|
||||
NtPidlSymlinkData * symlink = (NtPidlSymlinkData*) (((PBYTE) info) + FIELD_OFFSET(NtPidlEntry,entryName) + info->entryNameLength + sizeof(WCHAR));
|
||||
|
||||
if (symlink->targetNameLength > 0)
|
||||
{
|
||||
@@ -1134,7 +1183,7 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::GetDetailsOf(
|
||||
|
||||
if (info->objectType < 0)
|
||||
{
|
||||
NtPidlTypeData * td = (NtPidlTypeData*) (((PBYTE) info) + sizeof(NtPidlEntry) + info->entryNameLength + sizeof(WCHAR));
|
||||
NtPidlTypeData * td = (NtPidlTypeData*) (((PBYTE) info) + FIELD_OFFSET(NtPidlEntry,entryName) + info->entryNameLength + sizeof(WCHAR));
|
||||
|
||||
if (td->typeNameLength > 0)
|
||||
MakeStrRetFromString(td->typeName, td->typeNameLength, &(psd->str));
|
||||
@@ -1170,7 +1219,7 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::GetDetailsOf(
|
||||
|
||||
if (info->objectType == SYMBOLICLINK_OBJECT)
|
||||
{
|
||||
NtPidlSymlinkData * symlink = (NtPidlSymlinkData*) (((PBYTE) info) + sizeof(NtPidlEntry) + info->entryNameLength + sizeof(WCHAR));
|
||||
NtPidlSymlinkData * symlink = (NtPidlSymlinkData*) (((PBYTE) info) + FIELD_OFFSET(NtPidlEntry,entryName) + info->entryNameLength + sizeof(WCHAR));
|
||||
|
||||
if (symlink->targetNameLength > 0)
|
||||
{
|
||||
|
||||
@@ -36,7 +36,22 @@ const LPCWSTR ObjectTypeNames [] = {
|
||||
0
|
||||
};
|
||||
|
||||
static DWORD NtOpenObject(OBJECT_TYPE type, HANDLE* phandle, DWORD access, LPCWSTR path)
|
||||
const LPCWSTR RegistryTypeNames[] = {
|
||||
L"REG_NONE",
|
||||
L"REG_SZ",
|
||||
L"REG_EXPAND_SZ",
|
||||
L"REG_BINARY",
|
||||
L"REG_DWORD",
|
||||
L"REG_DWORD_BIG_ENDIAN",
|
||||
L"REG_LINK",
|
||||
L"REG_MULTI_SZ",
|
||||
L"REG_RESOURCE_LIST",
|
||||
L"REG_FULL_RESOURCE_DESCRIPTOR",
|
||||
L"REG_RESOURCE_REQUIREMENTS_LIST ",
|
||||
L"REG_QWORD"
|
||||
};
|
||||
|
||||
static DWORD NtOpenObject(OBJECT_TYPE type, PHANDLE phandle, DWORD access, LPCWSTR path)
|
||||
{
|
||||
UNICODE_STRING ustr;
|
||||
|
||||
@@ -128,7 +143,7 @@ HRESULT EnumerateNtDirectory(HDPA hdpa, PCWSTR path, UINT * hdpaCount)
|
||||
UNICODE_STRING link;
|
||||
RtlInitEmptyUnicodeString(&link, wbLink, sizeof(wbLink));
|
||||
|
||||
DWORD entryBufferLength = sizeof(NtPidlEntry) + sizeof(WCHAR);
|
||||
DWORD entryBufferLength = FIELD_OFFSET(NtPidlEntry,entryName) + sizeof(WCHAR);
|
||||
if (info->Name.Buffer)
|
||||
entryBufferLength += info->Name.Length;
|
||||
|
||||
@@ -183,7 +198,7 @@ HRESULT EnumerateNtDirectory(HDPA hdpa, PCWSTR path, UINT * hdpaCount)
|
||||
|
||||
memset(entry, 0, entryBufferLength);
|
||||
|
||||
entry->cb = sizeof(NtPidlEntry);
|
||||
entry->cb = FIELD_OFFSET(NtPidlEntry,entryName);
|
||||
entry->magic = NT_OBJECT_PIDL_MAGIC;
|
||||
entry->objectType = otype;
|
||||
entry->objectInformation = object;
|
||||
@@ -242,3 +257,161 @@ HRESULT EnumerateNtDirectory(HDPA hdpa, PCWSTR path, UINT * hdpaCount)
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT EnumerateRegistryKey(HDPA hdpa, PCWSTR path, HKEY root, UINT * hdpaCount)
|
||||
{
|
||||
*hdpaCount = 0;
|
||||
|
||||
HKEY hkey;
|
||||
|
||||
DWORD res;
|
||||
if (root)
|
||||
{
|
||||
res = RegOpenKeyExW(root, *path == '\\' ? path + 1 : path, 0, STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &hkey);
|
||||
}
|
||||
else
|
||||
{
|
||||
res = NtOpenObject(KEY_OBJECT, (PHANDLE)&hkey, STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, path);
|
||||
}
|
||||
if (!NT_SUCCESS(res))
|
||||
{
|
||||
ERR("RegOpenKeyExW failed for path %S with status=%x\n", path, res);
|
||||
return HRESULT_FROM_NT(res);
|
||||
}
|
||||
|
||||
for (int idx = 0;; ++idx)
|
||||
{
|
||||
WCHAR name[MAX_PATH];
|
||||
DWORD cchName = _countof(name);
|
||||
|
||||
WCHAR className[MAX_PATH];
|
||||
DWORD cchClass = _countof(className);
|
||||
|
||||
if (RegEnumKeyExW(hkey, idx, name, &cchName, 0, className, &cchClass, NULL))
|
||||
break;
|
||||
|
||||
name[cchName] = 0;
|
||||
className[cchClass] = 0;
|
||||
|
||||
REG_ENTRY_TYPE otype = REG_ENTRY_KEY;
|
||||
|
||||
DWORD entryBufferLength = FIELD_OFFSET(RegPidlEntry,entryName) + sizeof(WCHAR) + cchName * sizeof(WCHAR);
|
||||
|
||||
if (cchClass > 0)
|
||||
{
|
||||
entryBufferLength += sizeof(WCHAR) + cchClass * 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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (cchClass)
|
||||
{
|
||||
PWSTR contentData = (PWSTR) ((PBYTE) entry + entry->cb);
|
||||
DWORD remainingSpace = entryBufferLength - entry->cb;
|
||||
|
||||
entry->contentsLength = cchClass * sizeof(WCHAR);
|
||||
StringCbCopyNW(contentData, remainingSpace, className, entry->contentsLength);
|
||||
|
||||
entry->cb += entry->contentsLength + sizeof(WCHAR);
|
||||
}
|
||||
|
||||
DPA_AppendPtr(hdpa, entry);
|
||||
(*hdpaCount)++;
|
||||
|
||||
}
|
||||
|
||||
for (int idx = 0;; ++idx)
|
||||
{
|
||||
WCHAR name[MAX_PATH];
|
||||
DWORD cchName = _countof(name);
|
||||
DWORD type;
|
||||
DWORD dataSize;
|
||||
|
||||
if (RegEnumValueW(hkey, idx, name, &cchName, 0, &type, NULL, &dataSize))
|
||||
break;
|
||||
|
||||
REG_ENTRY_TYPE otype = REG_ENTRY_VALUE;
|
||||
|
||||
DWORD entryBufferLength = FIELD_OFFSET(RegPidlEntry,entryName) + sizeof(WCHAR) + cchName * sizeof(WCHAR);
|
||||
|
||||
BOOL copyData = dataSize < 32;
|
||||
if (copyData)
|
||||
{
|
||||
entryBufferLength += dataSize + sizeof(WCHAR);
|
||||
|
||||
otype = REG_ENTRY_VALUE_WITH_CONTENT;
|
||||
}
|
||||
|
||||
RegPidlEntry* entry = (RegPidlEntry*) CoTaskMemAlloc(entryBufferLength);
|
||||
if (!entry)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
memset(entry, 0, entryBufferLength);
|
||||
|
||||
entry->cb = FIELD_OFFSET(RegPidlEntry, entryName);
|
||||
entry->magic = REGISTRY_PIDL_MAGIC;
|
||||
entry->entryType = otype;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (copyData)
|
||||
{
|
||||
PBYTE contentData = (PBYTE) ((PBYTE) entry + entry->cb);
|
||||
|
||||
entry->contentsLength = dataSize;
|
||||
|
||||
// In case it's an unterminated string, RegGetValue will add the NULL termination
|
||||
dataSize += sizeof(WCHAR);
|
||||
|
||||
if (!RegQueryValueExW(hkey, name, NULL, NULL, contentData, &dataSize))
|
||||
{
|
||||
entry->cb += entry->contentsLength + sizeof(WCHAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
entry->contentsLength = 0;
|
||||
entry->cb += sizeof(WCHAR);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DPA_AppendPtr(hdpa, entry);
|
||||
(*hdpaCount)++;
|
||||
}
|
||||
|
||||
RegCloseKey(hkey);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -37,8 +37,11 @@ enum OBJECT_TYPE {
|
||||
extern const LPCWSTR ObjectTypeNames[];
|
||||
|
||||
#define NT_OBJECT_PIDL_MAGIC (USHORT)0x9A03
|
||||
#define REGISTRY_PIDL_MAGIC (USHORT)0x5364
|
||||
|
||||
#include <pshpack1.h>
|
||||
|
||||
// NT OBJECT browsere
|
||||
struct NtPidlEntry
|
||||
{
|
||||
USHORT cb;
|
||||
@@ -65,6 +68,37 @@ struct NtPidlSymlinkData
|
||||
USHORT targetNameLength;
|
||||
WCHAR targetName[ANYSIZE_ARRAY];
|
||||
};
|
||||
|
||||
// REGISTRY browsere
|
||||
enum REG_ENTRY_TYPE
|
||||
{
|
||||
REG_ENTRY_KEY,
|
||||
REG_ENTRY_VALUE,
|
||||
REG_ENTRY_VALUE_WITH_CONTENT
|
||||
// any more?
|
||||
};
|
||||
extern const LPCWSTR RegistryTypeNames [];
|
||||
|
||||
struct RegPidlEntry
|
||||
{
|
||||
USHORT cb;
|
||||
USHORT magic; // 0x5364 ~~~ "REGK"
|
||||
|
||||
REG_ENTRY_TYPE entryType;
|
||||
|
||||
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;
|
||||
|
||||
WCHAR entryName[0];
|
||||
|
||||
};
|
||||
|
||||
|
||||
#include <poppack.h>
|
||||
|
||||
HRESULT EnumerateNtDirectory(HDPA hdpa, PCWSTR path, UINT * hdpaCount);
|
||||
HRESULT EnumerateNtDirectory(HDPA hdpa, PCWSTR path, UINT * hdpaCount);
|
||||
HRESULT EnumerateRegistryKey(HDPA hdpa, PCWSTR path, HKEY root, UINT * hdpaCount);
|
||||
@@ -47,3 +47,4 @@ DEFINE_GUID(CLSID_NtObjectFolder,
|
||||
0x845b0fb2, 0x66e0, 0x416b, 0x8f, 0x91, 0x31, 0x4e, 0x23, 0xf7, 0xc1, 0x2d);
|
||||
|
||||
#include "ntobjns.h"
|
||||
#include "regfolder.h"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* PROJECT: ReactOS system libraries
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: dll\win32\stobject\stobject.cpp
|
||||
* PURPOSE: Systray shell service object
|
||||
* PROGRAMMERS: Robert Naumann
|
||||
David Quintana <[email protected]>
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
extern const GUID CLSID_RegistryFolder;
|
||||
|
||||
class CRegistryPidlManager;
|
||||
|
||||
class CRegistryFolder :
|
||||
public CComCoClass<CRegistryFolder, &CLSID_RegistryFolder>,
|
||||
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
||||
public IShellFolder2,
|
||||
public IPersistFolder2
|
||||
{
|
||||
CRegistryPidlManager * m_PidlManager;
|
||||
|
||||
WCHAR m_NtPath[MAX_PATH];
|
||||
|
||||
LPITEMIDLIST m_shellPidl;
|
||||
|
||||
public:
|
||||
|
||||
CRegistryFolder();
|
||||
virtual ~CRegistryFolder();
|
||||
|
||||
CRegistryPidlManager& GetManager() { return *m_PidlManager; }
|
||||
|
||||
// IShellFolder
|
||||
virtual HRESULT STDMETHODCALLTYPE ParseDisplayName(
|
||||
HWND hwndOwner,
|
||||
LPBC pbcReserved,
|
||||
LPOLESTR lpszDisplayName,
|
||||
ULONG *pchEaten,
|
||||
LPITEMIDLIST *ppidl,
|
||||
ULONG *pdwAttributes);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE EnumObjects(
|
||||
HWND hwndOwner,
|
||||
SHCONTF grfFlags,
|
||||
IEnumIDList **ppenumIDList);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE BindToObject(
|
||||
LPCITEMIDLIST pidl,
|
||||
LPBC pbcReserved,
|
||||
REFIID riid,
|
||||
void **ppvOut);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE BindToStorage(
|
||||
LPCITEMIDLIST pidl,
|
||||
LPBC pbcReserved,
|
||||
REFIID riid,
|
||||
void **ppvObj);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE CompareIDs(
|
||||
LPARAM lParam,
|
||||
LPCITEMIDLIST pidl1,
|
||||
LPCITEMIDLIST pidl2);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE CreateViewObject(
|
||||
HWND hwndOwner,
|
||||
REFIID riid,
|
||||
void **ppvOut);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetAttributesOf(
|
||||
UINT cidl,
|
||||
PCUITEMID_CHILD_ARRAY apidl,
|
||||
SFGAOF *rgfInOut);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetUIObjectOf(
|
||||
HWND hwndOwner,
|
||||
UINT cidl,
|
||||
PCUITEMID_CHILD_ARRAY apidl,
|
||||
REFIID riid,
|
||||
UINT *prgfInOut,
|
||||
void **ppvOut);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetDisplayNameOf(
|
||||
LPCITEMIDLIST pidl,
|
||||
SHGDNF uFlags,
|
||||
STRRET *lpName);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE SetNameOf(
|
||||
HWND hwnd,
|
||||
LPCITEMIDLIST pidl,
|
||||
LPCOLESTR lpszName,
|
||||
SHGDNF uFlags,
|
||||
LPITEMIDLIST *ppidlOut);
|
||||
|
||||
// IShellFolder2
|
||||
virtual HRESULT STDMETHODCALLTYPE GetDefaultSearchGUID(
|
||||
GUID *lpguid);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE EnumSearches(
|
||||
IEnumExtraSearch **ppenum);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetDefaultColumn(
|
||||
DWORD dwReserved,
|
||||
ULONG *pSort,
|
||||
ULONG *pDisplay);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetDefaultColumnState(
|
||||
UINT iColumn,
|
||||
SHCOLSTATEF *pcsFlags);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetDetailsEx(
|
||||
LPCITEMIDLIST pidl,
|
||||
const SHCOLUMNID *pscid,
|
||||
VARIANT *pv);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetDetailsOf(
|
||||
LPCITEMIDLIST pidl,
|
||||
UINT iColumn,
|
||||
SHELLDETAILS *psd);
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE MapColumnToSCID(
|
||||
UINT iColumn,
|
||||
SHCOLUMNID *pscid);
|
||||
|
||||
// IPersist
|
||||
virtual HRESULT STDMETHODCALLTYPE GetClassID(CLSID *lpClassId);
|
||||
|
||||
// IPersistFolder
|
||||
virtual HRESULT STDMETHODCALLTYPE Initialize(LPCITEMIDLIST pidl);
|
||||
|
||||
// IPersistFolder2
|
||||
virtual HRESULT STDMETHODCALLTYPE GetCurFolder(LPITEMIDLIST * pidl);
|
||||
|
||||
// Internal
|
||||
HRESULT STDMETHODCALLTYPE Initialize(LPCITEMIDLIST pidl, PCWSTR ntPath);
|
||||
|
||||
DECLARE_REGISTRY_RESOURCEID(IDR_NTOBJECTFOLDER)
|
||||
DECLARE_NOT_AGGREGATABLE(CRegistryFolder)
|
||||
DECLARE_PROTECT_FINAL_CONSTRUCT()
|
||||
|
||||
BEGIN_COM_MAP(CRegistryFolder)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IShellFolder, IShellFolder)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IShellFolder2, IShellFolder2)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IPersistFolder, IPersistFolder)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IPersistFolder2, IPersistFolder2)
|
||||
END_COM_MAP()
|
||||
|
||||
};
|
||||
@@ -7,6 +7,9 @@
|
||||
#define IDI_NTOBJECTDEVICE 5
|
||||
#define IDI_NTOBJECTPORT 6
|
||||
|
||||
#define IDI_REGISTRYKEY 32
|
||||
#define IDI_REGISTRYVALUE 33
|
||||
|
||||
#define IDS_NAME 101
|
||||
|
||||
#define IDR_NTOBJECTFOLDER 1001
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef INLINE
|
||||
#define INLINE inline
|
||||
#endif
|
||||
|
||||
HRESULT INLINE MakeStrRetFromString(LPCWSTR string, DWORD cbLength, STRRET * str)
|
||||
{
|
||||
str->uType = STRRET_WSTR;
|
||||
|
||||
DWORD blen = cbLength + sizeof(WCHAR);
|
||||
str->pOleStr = (LPWSTR) CoTaskMemAlloc(blen);
|
||||
return StringCbCopyNW(str->pOleStr, blen, string, cbLength);
|
||||
}
|
||||
|
||||
HRESULT INLINE MakeStrRetFromString(LPCWSTR string, STRRET * str)
|
||||
{
|
||||
DWORD stringLength = wcslen(string) * sizeof(WCHAR);
|
||||
return MakeStrRetFromString(string, stringLength, str);
|
||||
}
|
||||
|
||||
HRESULT INLINE MakeVariantString(VARIANT * pv, PCWSTR string)
|
||||
{
|
||||
V_VT(pv) = VT_BSTR;
|
||||
V_BSTR(pv) = SysAllocString(string);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT INLINE GetFullName(PCIDLIST_ABSOLUTE pidl, DWORD uFlags, PWSTR strName, DWORD cchName)
|
||||
{
|
||||
CComPtr<IShellFolder> psfDesktop;
|
||||
STRRET str;
|
||||
HRESULT hr;
|
||||
|
||||
hr = SHGetDesktopFolder(&psfDesktop);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
hr = psfDesktop->GetDisplayNameOf(pidl, uFlags, &str);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
return StrRetToBufW(&str, pidl, strName, cchName);
|
||||
}
|
||||
Reference in New Issue
Block a user