mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-09-02 04:13:34 +00:00
[NTOBJSHEX]
* Use lazy enumeration of the nt objects and registry keys, as intended for the IEnumIDList interface. * Display of the NT Object creation date has been lost in the process, but it was only really used by symlinks. * Symlink target display doesn't appear to work at the moment, will fix later. svn path=/trunk/; revision=68783
This commit is contained in:
@@ -34,7 +34,6 @@ enum NtObjectColumns
|
||||
{
|
||||
NTOBJECT_COLUMN_NAME = 0,
|
||||
NTOBJECT_COLUMN_TYPE,
|
||||
NTOBJECT_COLUMN_CREATEDATE,
|
||||
NTOBJECT_COLUMN_LINKTARGET,
|
||||
NTOBJECT_COLUMN_END
|
||||
};
|
||||
@@ -43,28 +42,25 @@ class CNtObjectFolderExtractIcon :
|
||||
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
||||
public IExtractIconW
|
||||
{
|
||||
PCIDLIST_ABSOLUTE m_pcidlFolder;
|
||||
PCITEMID_CHILD m_pcidlChild;
|
||||
PCITEMID_CHILD m_pcidlChild;
|
||||
LPCWSTR m_NtPath;
|
||||
|
||||
public:
|
||||
CNtObjectFolderExtractIcon() :
|
||||
m_pcidlFolder(NULL),
|
||||
m_pcidlChild(NULL)
|
||||
m_pcidlChild(NULL), m_NtPath(NULL)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
virtual ~CNtObjectFolderExtractIcon()
|
||||
{
|
||||
if (m_pcidlFolder)
|
||||
ILFree((LPITEMIDLIST) m_pcidlFolder);
|
||||
if (m_pcidlChild)
|
||||
ILFree((LPITEMIDLIST) m_pcidlChild);
|
||||
}
|
||||
|
||||
HRESULT Initialize(PCIDLIST_ABSOLUTE parent, UINT cidl, PCUITEMID_CHILD_ARRAY apidl)
|
||||
HRESULT Initialize(LPCWSTR ntPath, UINT cidl, PCUITEMID_CHILD_ARRAY apidl)
|
||||
{
|
||||
m_pcidlFolder = ILClone(parent);
|
||||
m_NtPath = ntPath;
|
||||
if (cidl != 1)
|
||||
return E_INVALIDARG;
|
||||
m_pcidlChild = ILClone(apidl[0]);
|
||||
@@ -85,11 +81,6 @@ public:
|
||||
|
||||
UINT flags = 0;
|
||||
|
||||
#define GIL_CHECKSHIELD 0x0200
|
||||
#define GIL_SHIELD 0x0200
|
||||
if (uFlags & GIL_CHECKSHIELD && !(entry->objectInformation.GrantedAccess & STANDARD_RIGHTS_READ))
|
||||
flags |= GIL_SHIELD;
|
||||
|
||||
switch (entry->objectType)
|
||||
{
|
||||
case DIRECTORY_OBJECT:
|
||||
@@ -145,195 +136,23 @@ class CNtObjectPidlManager
|
||||
private:
|
||||
PWSTR m_ntPath;
|
||||
|
||||
HDPA m_hDpa;
|
||||
UINT m_hDpaCount;
|
||||
|
||||
int DpaDeleteCallback(NtPidlEntry * info)
|
||||
{
|
||||
CoTaskMemFree(info);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int CALLBACK s_DpaDeleteCallback(void *pItem, void *pData)
|
||||
{
|
||||
CNtObjectPidlManager * mf = (CNtObjectPidlManager*) pData;
|
||||
NtPidlEntry * item = (NtPidlEntry*) pItem;
|
||||
return mf->DpaDeleteCallback(item);
|
||||
}
|
||||
|
||||
public:
|
||||
CNtObjectPidlManager() :
|
||||
m_ntPath(NULL),
|
||||
m_hDpa(NULL),
|
||||
m_hDpaCount(0)
|
||||
m_ntPath(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
~CNtObjectPidlManager()
|
||||
{
|
||||
DPA_DestroyCallback(m_hDpa, s_DpaDeleteCallback, this);
|
||||
}
|
||||
|
||||
HRESULT Initialize(PWSTR ntPath)
|
||||
{
|
||||
m_ntPath = ntPath;
|
||||
m_hDpa = NULL;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT Enumerate()
|
||||
{
|
||||
if (m_hDpa)
|
||||
return S_OK;
|
||||
|
||||
m_hDpa = DPA_Create(10);
|
||||
|
||||
if (!m_hDpa)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
HRESULT hr = EnumerateNtDirectory(m_hDpa, m_ntPath, &m_hDpaCount);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT FindPidlInList(PCUITEMID_CHILD pcidl, const NtPidlEntry ** pinfo)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
if (!m_hDpa)
|
||||
{
|
||||
hr = Enumerate();
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
if (!m_hDpa)
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
const NtPidlEntry * info = (const 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 { name='%S' } in a list of %d items\n", info->entryName, m_hDpaCount);
|
||||
|
||||
for (UINT i = 0; i < m_hDpaCount; i++)
|
||||
{
|
||||
const NtPidlEntry * pInfo = (const NtPidlEntry *) DPA_GetPtr(m_hDpa, i);
|
||||
ASSERT(pInfo);
|
||||
|
||||
hr = CompareIDs(SHCIDS_CANONICALONLY, pInfo, info);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
if (hr == S_OK)
|
||||
{
|
||||
*pinfo = pInfo;
|
||||
return S_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE("Comparison returned %d for '%S'\n", (int) (short) (hr & 0xFFFF), pInfo->entryName);
|
||||
}
|
||||
}
|
||||
|
||||
ERR("PIDL NOT FOUND: Requested filename: %S\n", info->entryName);
|
||||
*pinfo = NULL;
|
||||
|
||||
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
HRESULT FindByName(LPCWSTR strParsingName, NtPidlEntry ** pinfo)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
if (!m_hDpa)
|
||||
{
|
||||
hr = Enumerate();
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
if (!m_hDpa)
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
TRACE("Searching for '%S' in a list of %d items\n", strParsingName, m_hDpaCount);
|
||||
|
||||
for (int i = 0; i < (int) m_hDpaCount; i++)
|
||||
{
|
||||
NtPidlEntry * pInfo = (NtPidlEntry *) DPA_GetPtr(m_hDpa, i);
|
||||
ASSERT(pInfo);
|
||||
|
||||
int order = CompareStringW(GetThreadLocale(), NORM_IGNORECASE,
|
||||
pInfo->entryName, wcslen(pInfo->entryName),
|
||||
strParsingName, wcslen(strParsingName));
|
||||
|
||||
if (order == CSTR_EQUAL)
|
||||
{
|
||||
*pinfo = pInfo;
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
TRACE("Pidl not found\n");
|
||||
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
HRESULT GetPidl(UINT index, NtPidlEntry ** pEntry)
|
||||
{
|
||||
if (!m_hDpa)
|
||||
{
|
||||
HRESULT hr = Enumerate();
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
if (!m_hDpa)
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
*pEntry = NULL;
|
||||
|
||||
NtPidlEntry * entry = (NtPidlEntry *) DPA_GetPtr(m_hDpa, index);
|
||||
if (!entry)
|
||||
{
|
||||
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
*pEntry = entry;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT GetCount(UINT * count)
|
||||
{
|
||||
if (!m_hDpa)
|
||||
{
|
||||
HRESULT hr = Enumerate();
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
if (!m_hDpa)
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
*count = m_hDpaCount;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static LPITEMIDLIST CreatePidlFromItem(const NtPidlEntry * entry)
|
||||
{
|
||||
LPITEMIDLIST idl = (LPITEMIDLIST) CoTaskMemAlloc(entry->cb + 2);
|
||||
if (!idl)
|
||||
return NULL;
|
||||
memset(idl, 0, entry->cb + 2);
|
||||
memcpy(idl, entry, entry->cb);
|
||||
return idl;
|
||||
}
|
||||
|
||||
static HRESULT CompareIDs(LPARAM lParam, const NtPidlEntry * first, const NtPidlEntry * second)
|
||||
{
|
||||
if ((lParam & 0xFFFF0000) == SHCIDS_ALLFIELDS)
|
||||
@@ -413,16 +232,6 @@ public:
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
case NTOBJECT_COLUMN_CREATEDATE:
|
||||
{
|
||||
LONGLONG ord = second->objectInformation.CreateTime.QuadPart - first->objectInformation.CreateTime.QuadPart;
|
||||
if (ord > 0)
|
||||
return MAKE_HRESULT(0, 0, (USHORT) 1);
|
||||
if (ord < 0)
|
||||
return MAKE_HRESULT(0, 0, (USHORT) -1);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
case NTOBJECT_COLUMN_LINKTARGET:
|
||||
{
|
||||
// Can't sort by value
|
||||
@@ -478,131 +287,34 @@ public:
|
||||
|
||||
BOOL IsFolder(LPCITEMIDLIST pcidl)
|
||||
{
|
||||
const NtPidlEntry * entry;
|
||||
HRESULT hr = FindPidlInList(pcidl, &entry);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
NtPidlEntry * entry = (NtPidlEntry*) &(pcidl->mkid);
|
||||
if ((entry->cb < sizeof(NtPidlEntry)) || (entry->magic != NT_OBJECT_PIDL_MAGIC))
|
||||
return FALSE;
|
||||
|
||||
return (entry->objectType == DIRECTORY_OBJECT) ||
|
||||
(entry->objectType == SYMBOLICLINK_OBJECT) ||
|
||||
(entry->objectType == KEY_OBJECT);
|
||||
}
|
||||
};
|
||||
|
||||
class CNtObjectFolderEnum :
|
||||
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
||||
public IEnumIDList
|
||||
{
|
||||
private:
|
||||
CComPtr<CNtObjectFolder> m_Folder;
|
||||
|
||||
HWND m_HwndOwner;
|
||||
SHCONTF m_Flags;
|
||||
|
||||
UINT m_Index;
|
||||
UINT m_Count;
|
||||
|
||||
public:
|
||||
CNtObjectFolderEnum() :
|
||||
m_HwndOwner(NULL),
|
||||
m_Flags(0),
|
||||
m_Index(0),
|
||||
m_Count(0)
|
||||
virtual HRESULT GetInfoFromPidl(LPCITEMIDLIST pcidl, const NtPidlEntry ** pentry)
|
||||
{
|
||||
}
|
||||
NtPidlEntry * entry = (NtPidlEntry*) &(pcidl->mkid);
|
||||
|
||||
virtual ~CNtObjectFolderEnum()
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT Initialize(CNtObjectFolder * folder, HWND hwndOwner, SHCONTF flags)
|
||||
{
|
||||
m_Folder = folder;
|
||||
|
||||
m_Folder->GetManager().GetCount(&m_Count);
|
||||
|
||||
m_HwndOwner = hwndOwner;
|
||||
m_Flags = flags;
|
||||
|
||||
return Reset();
|
||||
}
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE Next(
|
||||
ULONG celt,
|
||||
LPITEMIDLIST *rgelt,
|
||||
ULONG *pceltFetched)
|
||||
{
|
||||
if (pceltFetched)
|
||||
*pceltFetched = 0;
|
||||
|
||||
if (m_Index >= m_Count)
|
||||
return S_FALSE;
|
||||
|
||||
for (int i = 0; i < (int) celt;)
|
||||
if (entry->cb < sizeof(NtPidlEntry))
|
||||
{
|
||||
NtPidlEntry * tinfo;
|
||||
BOOL flagsOk = FALSE;
|
||||
|
||||
do {
|
||||
HRESULT hr = m_Folder->GetManager().GetPidl(m_Index++, &tinfo);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
switch (tinfo->objectType)
|
||||
{
|
||||
case SYMBOLICLINK_OBJECT:
|
||||
case DIRECTORY_OBJECT:
|
||||
case KEY_OBJECT:
|
||||
flagsOk = (m_Flags & SHCONTF_FOLDERS) != 0;
|
||||
break;
|
||||
default:
|
||||
flagsOk = (m_Flags & SHCONTF_NONFOLDERS) != 0;
|
||||
break;
|
||||
}
|
||||
} while (m_Index < m_Count && !flagsOk);
|
||||
|
||||
if (flagsOk)
|
||||
{
|
||||
if (rgelt)
|
||||
rgelt[i] = m_Folder->GetManager().CreatePidlFromItem(tinfo);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (m_Index == m_Count)
|
||||
{
|
||||
if (pceltFetched)
|
||||
*pceltFetched = i;
|
||||
return (i == (int) celt) ? S_OK : S_FALSE;
|
||||
}
|
||||
DbgPrint("PCIDL too small %l (required %l)\n", entry->cb, sizeof(NtPidlEntry));
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
if (pceltFetched) *pceltFetched = celt;
|
||||
if (entry->magic != NT_OBJECT_PIDL_MAGIC)
|
||||
{
|
||||
DbgPrint("PCIDL magic mismatch %04x (expected %04x)\n", entry->magic, NT_OBJECT_PIDL_MAGIC);
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*pentry = entry;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE Skip(ULONG celt)
|
||||
{
|
||||
return Next(celt, NULL, NULL);
|
||||
}
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE Reset()
|
||||
{
|
||||
m_Index = 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE Clone(IEnumIDList **ppenum)
|
||||
{
|
||||
return ShellObjectCreatorInit<CNtObjectFolderEnum>(m_Folder, m_HwndOwner, m_Flags, IID_PPV_ARG(IEnumIDList, ppenum));
|
||||
}
|
||||
|
||||
DECLARE_NOT_AGGREGATABLE(CNtObjectFolderEnum)
|
||||
DECLARE_PROTECT_FINAL_CONSTRUCT()
|
||||
|
||||
BEGIN_COM_MAP(CNtObjectFolderEnum)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IEnumIDList, IEnumIDList)
|
||||
END_COM_MAP()
|
||||
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -631,8 +343,6 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::ParseDisplayName(
|
||||
LPITEMIDLIST *ppidl,
|
||||
ULONG *pdwAttributes)
|
||||
{
|
||||
NtPidlEntry * info;
|
||||
|
||||
if (!ppidl)
|
||||
return E_POINTER;
|
||||
|
||||
@@ -644,19 +354,43 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::ParseDisplayName(
|
||||
|
||||
TRACE("CNtObjectFolder::ParseDisplayName name=%S (ntPath=%S)\n", lpszDisplayName, m_NtPath);
|
||||
|
||||
HRESULT hr = m_PidlManager->FindByName(lpszDisplayName, &info);
|
||||
const NtPidlEntry * info;
|
||||
IEnumIDList * it;
|
||||
HRESULT hr = GetEnumNTDirectory(m_NtPath, &it);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
hr = it->Next(1, ppidl, NULL);
|
||||
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
if (hr != S_OK)
|
||||
break;
|
||||
|
||||
hr = m_PidlManager->GetInfoFromPidl(*ppidl, &info);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
if (StrCmpW(info->entryName, lpszDisplayName) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (hr != S_OK)
|
||||
{
|
||||
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
*ppidl = m_PidlManager->CreatePidlFromItem(info);
|
||||
if (pchEaten || pdwAttributes)
|
||||
{
|
||||
if (pchEaten)
|
||||
*pchEaten = wcslen(info->entryName);
|
||||
|
||||
if (pchEaten)
|
||||
*pchEaten = wcslen(info->entryName);
|
||||
|
||||
if (pdwAttributes)
|
||||
*pdwAttributes = m_PidlManager->ConvertAttributes(info, pdwAttributes);
|
||||
if (pdwAttributes)
|
||||
*pdwAttributes = m_PidlManager->ConvertAttributes(info, pdwAttributes);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
@@ -666,7 +400,7 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::EnumObjects(
|
||||
SHCONTF grfFlags,
|
||||
IEnumIDList **ppenumIDList)
|
||||
{
|
||||
return ShellObjectCreatorInit<CNtObjectFolderEnum>(this, hwndOwner, grfFlags, IID_PPV_ARG(IEnumIDList, ppenumIDList));
|
||||
return GetEnumNTDirectory(m_NtPath, ppenumIDList);
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE CNtObjectFolder::BindToObject(
|
||||
@@ -679,13 +413,10 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::BindToObject(
|
||||
|
||||
if (IsEqualIID(riid, IID_IShellFolder))
|
||||
{
|
||||
HRESULT hr = m_PidlManager->FindPidlInList(pidl, &info);
|
||||
HRESULT hr = m_PidlManager->GetInfoFromPidl(pidl, &info);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
if (!(info->objectInformation.GrantedAccess & (STANDARD_RIGHTS_READ | FILE_LIST_DIRECTORY)))
|
||||
return E_ACCESSDENIED;
|
||||
|
||||
WCHAR path[MAX_PATH];
|
||||
|
||||
StringCbCopyW(path, _countof(path), m_NtPath);
|
||||
@@ -699,18 +430,32 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::BindToObject(
|
||||
|
||||
if (info->objectType == SYMBOLICLINK_OBJECT)
|
||||
{
|
||||
NtPidlSymlinkData * symlink = (NtPidlSymlinkData*) (((PBYTE) info) + FIELD_OFFSET(NtPidlEntry, entryName) + info->entryNameLength + sizeof(WCHAR));
|
||||
WCHAR wbLink[MAX_PATH] = { 0 };
|
||||
UNICODE_STRING link;
|
||||
RtlInitEmptyUnicodeString(&link, wbLink, sizeof(wbLink));
|
||||
|
||||
if (symlink->targetNameLength > 0)
|
||||
hr = GetNTObjectSymbolicLinkTarget(m_NtPath, info->entryName, &link);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
if (link.Length > 0)
|
||||
{
|
||||
if (symlink->targetName[1] == L':' && isalphaW(symlink->targetName[0]))
|
||||
if (link.Buffer[1] == L':' && isalphaW(link.Buffer[0]))
|
||||
{
|
||||
ERR("TODO: Navigating to WIN32 PATH from NT PATH.\n");
|
||||
return E_NOTIMPL;
|
||||
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;
|
||||
|
||||
return psfDesktop->BindToObject(rest, pbcReserved, riid, ppvOut);
|
||||
}
|
||||
|
||||
StringCbCopyW(path, _countof(path), L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{845B0FB2-66E0-416B-8F91-314E23F7C12D}");
|
||||
PathAppend(path, symlink->targetName);
|
||||
PathAppend(path, link.Buffer);
|
||||
|
||||
CComPtr<IShellFolder> psfDesktop;
|
||||
hr = SHGetDesktopFolder(&psfDesktop);
|
||||
@@ -731,7 +476,7 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::BindToObject(
|
||||
|
||||
if (info->objectType == KEY_OBJECT)
|
||||
{
|
||||
hr = ShellObjectCreatorInit<CRegistryFolder>(fullPidl, path, (HKEY)NULL, IID_PPV_ARG(IShellFolder, &psfChild));
|
||||
hr = ShellObjectCreatorInit<CRegistryFolder>(fullPidl, path, (HKEY) NULL, IID_PPV_ARG(IShellFolder, &psfChild));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -824,7 +569,7 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::GetAttributesOf(
|
||||
{
|
||||
const NtPidlEntry * info;
|
||||
|
||||
TRACE("GetAttributesOf\n");
|
||||
TRACE("GetAttributesOf %d\n", cidl);
|
||||
|
||||
if (cidl == 0)
|
||||
{
|
||||
@@ -836,7 +581,7 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::GetAttributesOf(
|
||||
{
|
||||
PCUITEMID_CHILD pidl = apidl[i];
|
||||
|
||||
HRESULT hr = m_PidlManager->FindPidlInList(pidl, &info);
|
||||
HRESULT hr = m_PidlManager->GetInfoFromPidl(pidl, &info);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
@@ -855,6 +600,7 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::GetUIObjectOf(
|
||||
UINT *prgfInOut,
|
||||
void **ppvOut)
|
||||
{
|
||||
DWORD res;
|
||||
TRACE("GetUIObjectOf\n");
|
||||
|
||||
if (IsEqualIID(riid, IID_IContextMenu) ||
|
||||
@@ -863,12 +609,14 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::GetUIObjectOf(
|
||||
{
|
||||
CComPtr<IContextMenu> pcm;
|
||||
|
||||
HKEY keys [1];
|
||||
HKEY keys[1];
|
||||
|
||||
int nkeys = _countof(keys);
|
||||
if (cidl == 1 && m_PidlManager->IsFolder(apidl[0]))
|
||||
{
|
||||
RegOpenKey(HKEY_CLASSES_ROOT, L"Folder", keys + 0);
|
||||
res = RegOpenKey(HKEY_CLASSES_ROOT, L"Folder", keys + 0);
|
||||
if (!NT_SUCCESS(res))
|
||||
return HRESULT_FROM_NT(res);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -884,12 +632,12 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::GetUIObjectOf(
|
||||
|
||||
if (IsEqualIID(riid, IID_IExtractIconW))
|
||||
{
|
||||
return ShellObjectCreatorInit<CNtObjectFolderExtractIcon>(m_shellPidl, cidl, apidl, riid, ppvOut);
|
||||
return ShellObjectCreatorInit<CNtObjectFolderExtractIcon>(m_NtPath, cidl, apidl, riid, ppvOut);
|
||||
}
|
||||
|
||||
if (IsEqualIID(riid, IID_IDataObject))
|
||||
{
|
||||
return CIDLData_CreateFromIDArray(m_shellPidl, cidl, apidl, (IDataObject**)ppvOut);
|
||||
return CIDLData_CreateFromIDArray(m_shellPidl, cidl, apidl, (IDataObject**) ppvOut);
|
||||
}
|
||||
|
||||
if (IsEqualIID(riid, IID_IQueryAssociations))
|
||||
@@ -921,7 +669,7 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::GetDisplayNameOf(
|
||||
|
||||
TRACE("GetDisplayNameOf %p\n", pidl);
|
||||
|
||||
HRESULT hr = m_PidlManager->FindPidlInList(pidl, &info);
|
||||
HRESULT hr = m_PidlManager->GetInfoFromPidl(pidl, &info);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
@@ -964,7 +712,7 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::GetDisplayNameOf(
|
||||
PathAppendW(path, temp);
|
||||
}
|
||||
|
||||
ILFree((LPITEMIDLIST)pidlFirst);
|
||||
ILFree((LPITEMIDLIST) pidlFirst);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1073,11 +821,8 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::GetDefaultColumnState(
|
||||
case NTOBJECT_COLUMN_TYPE:
|
||||
*pcsFlags = SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT;
|
||||
return S_OK;
|
||||
case NTOBJECT_COLUMN_CREATEDATE:
|
||||
*pcsFlags = SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT;
|
||||
return S_OK;
|
||||
case NTOBJECT_COLUMN_LINKTARGET:
|
||||
*pcsFlags = SHCOLSTATE_TYPE_STR;
|
||||
*pcsFlags = SHCOLSTATE_TYPE_STR | SHCOLSTATE_SLOW;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -1095,7 +840,7 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::GetDetailsEx(
|
||||
|
||||
if (pidl)
|
||||
{
|
||||
HRESULT hr = m_PidlManager->FindPidlInList(pidl, &info);
|
||||
HRESULT hr = m_PidlManager->GetInfoFromPidl(pidl, &info);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
@@ -1126,35 +871,25 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::GetDetailsEx(
|
||||
return MakeVariantString(pv, ObjectTypeNames[info->objectType]);
|
||||
}
|
||||
}
|
||||
else if (pscid->pid == PID_STG_WRITETIME)
|
||||
{
|
||||
DOUBLE varTime;
|
||||
SYSTEMTIME stime;
|
||||
FileTimeToSystemTime((FILETIME*) &(info->objectInformation.CreateTime), &stime);
|
||||
SystemTimeToVariantTime(&stime, &varTime);
|
||||
|
||||
V_VT(pv) = VT_DATE;
|
||||
V_DATE(pv) = varTime;
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
else if (IsEqualGUID(pscid->fmtid, GUID_NtObjectColumns))
|
||||
{
|
||||
if (pscid->pid == NTOBJECT_COLUMN_LINKTARGET)
|
||||
if (pscid->pid == NTOBJECT_COLUMN_LINKTARGET && info->objectType == SYMBOLICLINK_OBJECT)
|
||||
{
|
||||
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)
|
||||
{
|
||||
NtPidlSymlinkData * symlink = (NtPidlSymlinkData*) (((PBYTE) info) + FIELD_OFFSET(NtPidlEntry, entryName) + info->entryNameLength + sizeof(WCHAR));
|
||||
|
||||
if (symlink->targetNameLength > 0)
|
||||
{
|
||||
return MakeVariantString(pv, symlink->targetName);
|
||||
}
|
||||
return MakeVariantString(pv, link.Buffer);
|
||||
}
|
||||
|
||||
V_VT(pv) = VT_EMPTY;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
V_VT(pv) = VT_EMPTY;
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1172,7 +907,7 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::GetDetailsOf(
|
||||
|
||||
if (pidl)
|
||||
{
|
||||
HRESULT hr = m_PidlManager->FindPidlInList(pidl, &info);
|
||||
HRESULT hr = m_PidlManager->GetInfoFromPidl(pidl, &info);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
@@ -1198,37 +933,21 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::GetDetailsOf(
|
||||
else
|
||||
MakeStrRetFromString(ObjectTypeNames[info->objectType], &(psd->str));
|
||||
return S_OK;
|
||||
case NTOBJECT_COLUMN_CREATEDATE:
|
||||
psd->fmt = LVCFMT_LEFT;
|
||||
|
||||
if (info->objectInformation.CreateTime.QuadPart != 0)
|
||||
{
|
||||
WCHAR dbuff[128];
|
||||
PWSTR tbuff;
|
||||
SYSTEMTIME stime;
|
||||
FileTimeToSystemTime((LPFILETIME) &(info->objectInformation.CreateTime), &stime);
|
||||
GetDateFormat(LOCALE_USER_DEFAULT, 0, &stime, NULL, dbuff, _countof(dbuff));
|
||||
tbuff = dbuff + wcslen(dbuff);
|
||||
*tbuff++ = L' ';
|
||||
GetTimeFormat(LOCALE_USER_DEFAULT, 0, &stime, NULL, tbuff, _countof(dbuff) - (tbuff - dbuff));
|
||||
|
||||
MakeStrRetFromString(dbuff, &(psd->str));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
MakeStrRetFromString(L"", &(psd->str));
|
||||
return S_OK;
|
||||
|
||||
case NTOBJECT_COLUMN_LINKTARGET:
|
||||
{
|
||||
psd->fmt = LVCFMT_LEFT;
|
||||
|
||||
if (info->objectType == SYMBOLICLINK_OBJECT)
|
||||
{
|
||||
NtPidlSymlinkData * symlink = (NtPidlSymlinkData*) (((PBYTE) info) + FIELD_OFFSET(NtPidlEntry, entryName) + info->entryNameLength + sizeof(WCHAR));
|
||||
WCHAR wbLink[MAX_PATH] = { 0 };
|
||||
UNICODE_STRING link;
|
||||
RtlInitEmptyUnicodeString(&link, wbLink, sizeof(wbLink));
|
||||
|
||||
if (symlink->targetNameLength > 0)
|
||||
HRESULT hr = GetNTObjectSymbolicLinkTarget(m_NtPath, info->entryName, &link);
|
||||
|
||||
if (!FAILED_UNEXPECTEDLY(hr) && link.Length > 0)
|
||||
{
|
||||
MakeStrRetFromString(symlink->targetName, symlink->targetNameLength, &(psd->str));
|
||||
MakeStrRetFromString(link.Buffer, link.Length, &(psd->str));
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
@@ -1236,6 +955,7 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::GetDetailsOf(
|
||||
MakeStrRetFromString(L"", &(psd->str));
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1255,13 +975,6 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::GetDetailsOf(
|
||||
// TODO: Make localizable
|
||||
MakeStrRetFromString(L"Object Type", &(psd->str));
|
||||
return S_OK;
|
||||
case NTOBJECT_COLUMN_CREATEDATE:
|
||||
psd->fmt = LVCFMT_LEFT;
|
||||
psd->cxChar = 20;
|
||||
|
||||
// TODO: Make localizable
|
||||
MakeStrRetFromString(L"Creation Time", &(psd->str));
|
||||
return S_OK;
|
||||
case NTOBJECT_COLUMN_LINKTARGET:
|
||||
psd->fmt = LVCFMT_LEFT;
|
||||
psd->cxChar = 30;
|
||||
@@ -1290,10 +1003,6 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::MapColumnToSCID(
|
||||
pscid->fmtid = storage;
|
||||
pscid->pid = PID_STG_STORAGETYPE;
|
||||
return S_OK;
|
||||
case NTOBJECT_COLUMN_CREATEDATE:
|
||||
pscid->fmtid = storage;
|
||||
pscid->pid = PID_STG_WRITETIME;
|
||||
return S_OK;
|
||||
case NTOBJECT_COLUMN_LINKTARGET:
|
||||
pscid->fmtid = GUID_NtObjectColumns;
|
||||
pscid->pid = NTOBJECT_COLUMN_LINKTARGET;
|
||||
@@ -1316,8 +1025,6 @@ HRESULT STDMETHODCALLTYPE CNtObjectFolder::MessageSFVCB(UINT uMsg, WPARAM wParam
|
||||
return S_FALSE;
|
||||
case SFVM_BACKGROUNDENUM:
|
||||
return S_OK;
|
||||
case SFVM_DEFITEMCOUNT:
|
||||
return m_PidlManager->GetCount((UINT*) lParam);
|
||||
}
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,17 @@
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(ntobjshex);
|
||||
|
||||
static struct RootKeyEntry {
|
||||
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" }
|
||||
};
|
||||
|
||||
typedef NTSTATUS(__stdcall* pfnNtGenericOpen)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
|
||||
typedef NTSTATUS(__stdcall* pfnNtOpenFile)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PIO_STATUS_BLOCK, ULONG, ULONG);
|
||||
|
||||
@@ -36,7 +47,7 @@ const LPCWSTR ObjectTypeNames [] = {
|
||||
0
|
||||
};
|
||||
|
||||
const LPCWSTR RegistryTypeNames[] = {
|
||||
const LPCWSTR RegistryTypeNames [] = {
|
||||
L"REG_NONE",
|
||||
L"REG_SZ",
|
||||
L"REG_EXPAND_SZ",
|
||||
@@ -99,179 +110,18 @@ OBJECT_TYPE MapTypeNameToType(LPCWSTR TypeName, DWORD cbTypeName)
|
||||
return UNKNOWN_OBJECT_TYPE;
|
||||
}
|
||||
|
||||
HRESULT EnumerateNtDirectory(HDPA hdpa, PCWSTR path, UINT * hdpaCount)
|
||||
HRESULT ReadRegistryValue(HKEY root, PCWSTR path, PCWSTR valueName, PVOID * valueData, PDWORD valueLength)
|
||||
{
|
||||
WCHAR buffer[MAX_PATH];
|
||||
PWSTR pend;
|
||||
|
||||
*hdpaCount = 0;
|
||||
|
||||
StringCbCopyExW(buffer, sizeof(buffer), path, &pend, NULL, 0);
|
||||
|
||||
ULONG enumContext = 0;
|
||||
HANDLE directory = NULL;
|
||||
|
||||
DWORD err = NtOpenObject(DIRECTORY_OBJECT, &directory, FILE_LIST_DIRECTORY, buffer);
|
||||
if (!NT_SUCCESS(err))
|
||||
{
|
||||
ERR("NtOpenDirectoryObject failed for path %S with status=%x\n", buffer, err);
|
||||
return HRESULT_FROM_NT(err);
|
||||
}
|
||||
|
||||
if (pend[-1] != '\\')
|
||||
*pend++ = '\\';
|
||||
|
||||
|
||||
BYTE dirbuffer[2048];
|
||||
|
||||
BOOL first = TRUE;
|
||||
while (NtQueryDirectoryObject(directory, dirbuffer, 2048, TRUE, first, &enumContext, NULL) == STATUS_SUCCESS)
|
||||
{
|
||||
first = FALSE;
|
||||
POBJECT_DIRECTORY_INFORMATION info = (POBJECT_DIRECTORY_INFORMATION) dirbuffer;
|
||||
//for (; info->Name.Buffer != NULL; info++)
|
||||
{
|
||||
if (info->Name.Buffer)
|
||||
{
|
||||
StringCbCopyNW(pend, sizeof(buffer), info->Name.Buffer, info->Name.Length);
|
||||
}
|
||||
|
||||
OBJECT_TYPE otype = MapTypeNameToType(info->TypeName.Buffer, info->TypeName.Length);
|
||||
OBJECT_BASIC_INFORMATION object = { 0 };
|
||||
|
||||
WCHAR wbLink[_MAX_PATH] = { 0 };
|
||||
UNICODE_STRING link;
|
||||
RtlInitEmptyUnicodeString(&link, wbLink, sizeof(wbLink));
|
||||
|
||||
DWORD entryBufferLength = FIELD_OFFSET(NtPidlEntry,entryName) + sizeof(WCHAR);
|
||||
if (info->Name.Buffer)
|
||||
entryBufferLength += info->Name.Length;
|
||||
|
||||
if (otype < 0)
|
||||
{
|
||||
entryBufferLength += FIELD_OFFSET(NtPidlTypeData,typeName) + sizeof(WCHAR);
|
||||
|
||||
if (info->TypeName.Buffer)
|
||||
{
|
||||
entryBufferLength += info->TypeName.Length;
|
||||
}
|
||||
}
|
||||
|
||||
if (otype == SYMBOLICLINK_OBJECT)
|
||||
{
|
||||
entryBufferLength += FIELD_OFFSET(NtPidlSymlinkData,targetName) + sizeof(WCHAR);
|
||||
}
|
||||
|
||||
DWORD access = STANDARD_RIGHTS_READ;
|
||||
if ((otype == DIRECTORY_OBJECT) ||
|
||||
(otype == SYMBOLICLINK_OBJECT))
|
||||
access |= FILE_LIST_DIRECTORY;
|
||||
|
||||
HANDLE handle;
|
||||
if (!NtOpenObject(otype, &handle, access, buffer))
|
||||
{
|
||||
DWORD read;
|
||||
|
||||
if (!NT_SUCCESS(NtQueryObject(handle, ObjectBasicInformation, &object, sizeof(OBJECT_BASIC_INFORMATION), &read)))
|
||||
{
|
||||
ZeroMemory(&object, sizeof(OBJECT_BASIC_INFORMATION));
|
||||
}
|
||||
|
||||
if (otype == SYMBOLICLINK_OBJECT)
|
||||
{
|
||||
if (NtQuerySymbolicLinkObject(handle, &link, NULL) == STATUS_SUCCESS)
|
||||
{
|
||||
entryBufferLength += link.Length;
|
||||
}
|
||||
else
|
||||
{
|
||||
link.Length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
NtClose(handle);
|
||||
}
|
||||
|
||||
NtPidlEntry* entry = (NtPidlEntry*) CoTaskMemAlloc(entryBufferLength);
|
||||
if (!entry)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
memset(entry, 0, entryBufferLength);
|
||||
|
||||
entry->cb = FIELD_OFFSET(NtPidlEntry,entryName);
|
||||
entry->magic = NT_OBJECT_PIDL_MAGIC;
|
||||
entry->objectType = otype;
|
||||
entry->objectInformation = object;
|
||||
memset(entry->objectInformation.Reserved, 0, sizeof(entry->objectInformation.Reserved));
|
||||
|
||||
if (info->Name.Buffer)
|
||||
{
|
||||
entry->entryNameLength = info->Name.Length;
|
||||
StringCbCopyNW(entry->entryName, entryBufferLength, info->Name.Buffer, info->Name.Length);
|
||||
entry->cb += entry->entryNameLength + sizeof(WCHAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
entry->entryNameLength = 0;
|
||||
entry->entryName[0] = 0;
|
||||
entry->cb += sizeof(WCHAR);
|
||||
}
|
||||
|
||||
if (otype < 0)
|
||||
{
|
||||
NtPidlTypeData * typedata = (NtPidlTypeData*) ((PBYTE) entry + entry->cb);
|
||||
DWORD remainingSpace = entryBufferLength - ((PBYTE) (typedata->typeName) - (PBYTE) entry);
|
||||
|
||||
if (info->TypeName.Buffer)
|
||||
{
|
||||
typedata->typeNameLength = info->TypeName.Length;
|
||||
StringCbCopyNW(typedata->typeName, remainingSpace, info->TypeName.Buffer, info->TypeName.Length);
|
||||
|
||||
entry->cb += typedata->typeNameLength + sizeof(WCHAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
typedata->typeNameLength = 0;
|
||||
typedata->typeName[0] = 0;
|
||||
entry->cb += typedata->typeNameLength + sizeof(WCHAR);
|
||||
}
|
||||
}
|
||||
|
||||
if (otype == SYMBOLICLINK_OBJECT)
|
||||
{
|
||||
NtPidlSymlinkData * symlink = (NtPidlSymlinkData*) ((PBYTE) entry + entry->cb);
|
||||
DWORD remainingSpace = entryBufferLength - ((PBYTE) (symlink->targetName) - (PBYTE) entry);
|
||||
|
||||
symlink->targetNameLength = link.Length;
|
||||
StringCbCopyNW(symlink->targetName, remainingSpace, link.Buffer, link.Length);
|
||||
|
||||
entry->cb += symlink->targetNameLength + sizeof(WCHAR);
|
||||
}
|
||||
|
||||
DPA_AppendPtr(hdpa, entry);
|
||||
(*hdpaCount)++;
|
||||
}
|
||||
}
|
||||
|
||||
NtClose(directory);
|
||||
|
||||
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);
|
||||
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 | KEY_ENUMERATE_SUB_KEYS, path);
|
||||
res = NtOpenObject(KEY_OBJECT, (PHANDLE) &hkey, STANDARD_RIGHTS_READ | KEY_QUERY_VALUE, path);
|
||||
}
|
||||
if (!NT_SUCCESS(res))
|
||||
{
|
||||
@@ -279,7 +129,227 @@ HRESULT EnumerateRegistryKey(HDPA hdpa, PCWSTR path, HKEY root, UINT * hdpaCount
|
||||
return HRESULT_FROM_NT(res);
|
||||
}
|
||||
|
||||
for (int idx = 0;; ++idx)
|
||||
res = RegQueryValueExW(hkey, valueName, NULL, NULL, NULL, valueLength);
|
||||
if (!NT_SUCCESS(res))
|
||||
{
|
||||
ERR("RegQueryValueExW failed for path %S with status=%x\n", path, res);
|
||||
return HRESULT_FROM_NT(res);
|
||||
}
|
||||
|
||||
if (*valueLength > 0)
|
||||
{
|
||||
PBYTE data = (PBYTE) CoTaskMemAlloc(*valueLength);;
|
||||
*valueData = data;
|
||||
|
||||
res = RegQueryValueExW(hkey, valueName, NULL, NULL, data, valueLength);
|
||||
if (!NT_SUCCESS(res))
|
||||
{
|
||||
CoTaskMemFree(data);
|
||||
*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;
|
||||
}
|
||||
|
||||
HRESULT GetNTObjectSymbolicLinkTarget(LPCWSTR path, LPCWSTR entryName, PUNICODE_STRING LinkTarget)
|
||||
{
|
||||
HANDLE handle;
|
||||
WCHAR buffer[MAX_PATH];
|
||||
LPWSTR pend = buffer;
|
||||
|
||||
StringCbCopyExW(buffer, sizeof(buffer), path, &pend, NULL, 0);
|
||||
|
||||
if (pend[-1] != '\\')
|
||||
*pend++ = '\\';
|
||||
|
||||
StringCbCatW(buffer, sizeof(buffer), entryName);
|
||||
|
||||
DbgPrint("GetNTObjectSymbolicLinkTarget %d\n", buffer);
|
||||
|
||||
LinkTarget->Length = 0;
|
||||
|
||||
DWORD err = NtOpenObject(SYMBOLICLINK_OBJECT, &handle, 0, buffer);
|
||||
if (!NT_SUCCESS(err))
|
||||
return HRESULT_FROM_NT(err);
|
||||
|
||||
err = NT_SUCCESS(NtQuerySymbolicLinkObject(handle, LinkTarget, NULL));
|
||||
if (!NT_SUCCESS(err))
|
||||
return HRESULT_FROM_NT(err);
|
||||
|
||||
NtClose(handle);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
class CEnumRegRoot :
|
||||
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
||||
public IEnumIDList
|
||||
{
|
||||
UINT m_idx;
|
||||
|
||||
public:
|
||||
CEnumRegRoot()
|
||||
: m_idx(0)
|
||||
{
|
||||
}
|
||||
|
||||
~CEnumRegRoot()
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT EnumerateNext(LPITEMIDLIST* ppidl)
|
||||
{
|
||||
if (m_idx >= _countof(RootKeys))
|
||||
return S_FALSE;
|
||||
|
||||
RootKeyEntry& key = RootKeys[m_idx++];
|
||||
|
||||
PCWSTR name = key.keyName;
|
||||
DWORD cchName = wcslen(name);
|
||||
|
||||
REG_ENTRY_TYPE otype = REG_ENTRY_ROOT;
|
||||
|
||||
DWORD entryBufferLength = FIELD_OFFSET(RegPidlEntry, entryName) + sizeof(WCHAR) + cchName * sizeof(WCHAR);
|
||||
|
||||
// allocate space for the terminator
|
||||
entryBufferLength += 2;
|
||||
|
||||
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;
|
||||
entry->rootKey = key.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);
|
||||
}
|
||||
|
||||
*ppidl = (LPITEMIDLIST) entry;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE Next(ULONG celt, LPITEMIDLIST *rgelt, ULONG *pceltFetched)
|
||||
{
|
||||
if (pceltFetched)
|
||||
*pceltFetched = 0;
|
||||
|
||||
while (celt-- > 0)
|
||||
{
|
||||
HRESULT hr = EnumerateNext(rgelt);
|
||||
if (hr != S_OK)
|
||||
return hr;
|
||||
|
||||
if (pceltFetched)
|
||||
(*pceltFetched)++;
|
||||
if (rgelt)
|
||||
rgelt++;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE Skip(ULONG celt)
|
||||
{
|
||||
while (celt > 0)
|
||||
{
|
||||
HRESULT hr = EnumerateNext(NULL);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
if (hr != S_OK)
|
||||
break;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE Reset()
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE Clone(IEnumIDList **ppenum)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
DECLARE_NOT_AGGREGATABLE(CEnumRegRoot)
|
||||
DECLARE_PROTECT_FINAL_CONSTRUCT()
|
||||
|
||||
BEGIN_COM_MAP(CEnumRegRoot)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IEnumIDList, IEnumIDList)
|
||||
END_COM_MAP()
|
||||
|
||||
};
|
||||
|
||||
class CEnumRegKey :
|
||||
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
||||
public IEnumIDList
|
||||
{
|
||||
PCWSTR m_path;
|
||||
HKEY m_hkey;
|
||||
BOOL m_values;
|
||||
int m_idx;
|
||||
|
||||
public:
|
||||
CEnumRegKey()
|
||||
: m_path(NULL), m_hkey(NULL), m_values(FALSE), m_idx(0)
|
||||
{
|
||||
}
|
||||
|
||||
~CEnumRegKey()
|
||||
{
|
||||
RegCloseKey(m_hkey);
|
||||
}
|
||||
|
||||
HRESULT Initialize(PCWSTR path, HKEY root)
|
||||
{
|
||||
m_path = path;
|
||||
|
||||
DWORD res;
|
||||
if (root)
|
||||
{
|
||||
res = RegOpenKeyExW(root, *path == '\\' ? path + 1 : path, 0, STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &m_hkey);
|
||||
}
|
||||
else
|
||||
{
|
||||
res = NtOpenObject(KEY_OBJECT, (PHANDLE) &m_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);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT NextKey(LPITEMIDLIST* ppidl)
|
||||
{
|
||||
WCHAR name[MAX_PATH];
|
||||
DWORD cchName = _countof(name);
|
||||
@@ -287,28 +357,31 @@ HRESULT EnumerateRegistryKey(HDPA hdpa, PCWSTR path, HKEY root, UINT * hdpaCount
|
||||
WCHAR className[MAX_PATH];
|
||||
DWORD cchClass = _countof(className);
|
||||
|
||||
if (RegEnumKeyExW(hkey, idx, name, &cchName, 0, className, &cchClass, NULL))
|
||||
break;
|
||||
if (RegEnumKeyExW(m_hkey, m_idx++, name, &cchName, 0, className, &cchClass, NULL))
|
||||
return S_FALSE;
|
||||
|
||||
name[cchName] = 0;
|
||||
className[cchClass] = 0;
|
||||
|
||||
REG_ENTRY_TYPE otype = REG_ENTRY_KEY;
|
||||
|
||||
DWORD entryBufferLength = FIELD_OFFSET(RegPidlEntry,entryName) + sizeof(WCHAR) + cchName * sizeof(WCHAR);
|
||||
DWORD entryBufferLength = FIELD_OFFSET(RegPidlEntry, entryName) + sizeof(WCHAR) + cchName * sizeof(WCHAR);
|
||||
|
||||
if (cchClass > 0)
|
||||
{
|
||||
entryBufferLength += sizeof(WCHAR) + cchClass * sizeof(WCHAR);
|
||||
}
|
||||
|
||||
|
||||
// allocate space for the terminator
|
||||
entryBufferLength += 2;
|
||||
|
||||
RegPidlEntry* entry = (RegPidlEntry*) CoTaskMemAlloc(entryBufferLength);
|
||||
if (!entry)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
memset(entry, 0, entryBufferLength);
|
||||
|
||||
entry->cb = FIELD_OFFSET(NtPidlEntry,entryName);
|
||||
entry->cb = FIELD_OFFSET(RegPidlEntry, entryName);
|
||||
entry->magic = REGISTRY_PIDL_MAGIC;
|
||||
entry->entryType = otype;
|
||||
|
||||
@@ -336,24 +409,23 @@ HRESULT EnumerateRegistryKey(HDPA hdpa, PCWSTR path, HKEY root, UINT * hdpaCount
|
||||
entry->cb += entry->contentsLength + sizeof(WCHAR);
|
||||
}
|
||||
|
||||
DPA_AppendPtr(hdpa, entry);
|
||||
(*hdpaCount)++;
|
||||
|
||||
*ppidl = (LPITEMIDLIST) entry;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
for (int idx = 0;; ++idx)
|
||||
|
||||
HRESULT NextValue(LPITEMIDLIST* ppidl)
|
||||
{
|
||||
WCHAR name[MAX_PATH];
|
||||
DWORD cchName = _countof(name);
|
||||
DWORD type;
|
||||
DWORD dataSize;
|
||||
DWORD type = 0;
|
||||
DWORD dataSize = 0;
|
||||
|
||||
if (RegEnumValueW(hkey, idx, name, &cchName, 0, &type, NULL, &dataSize))
|
||||
break;
|
||||
if (RegEnumValueW(m_hkey, m_idx++, name, &cchName, 0, &type, NULL, &dataSize))
|
||||
return S_FALSE;
|
||||
|
||||
REG_ENTRY_TYPE otype = REG_ENTRY_VALUE;
|
||||
|
||||
DWORD entryBufferLength = FIELD_OFFSET(RegPidlEntry,entryName) + sizeof(WCHAR) + cchName * sizeof(WCHAR);
|
||||
DWORD entryBufferLength = FIELD_OFFSET(RegPidlEntry, entryName) + sizeof(WCHAR) + cchName * sizeof(WCHAR);
|
||||
|
||||
BOOL copyData = dataSize < 32;
|
||||
if (copyData)
|
||||
@@ -362,8 +434,8 @@ HRESULT EnumerateRegistryKey(HDPA hdpa, PCWSTR path, HKEY root, UINT * hdpaCount
|
||||
|
||||
otype = REG_ENTRY_VALUE_WITH_CONTENT;
|
||||
}
|
||||
|
||||
RegPidlEntry* entry = (RegPidlEntry*) CoTaskMemAlloc(entryBufferLength);
|
||||
|
||||
RegPidlEntry* entry = (RegPidlEntry*) CoTaskMemAlloc(entryBufferLength + 2);
|
||||
if (!entry)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
@@ -396,7 +468,7 @@ HRESULT EnumerateRegistryKey(HDPA hdpa, PCWSTR path, HKEY root, UINT * hdpaCount
|
||||
// In case it's an unterminated string, RegGetValue will add the NULL termination
|
||||
dataSize += sizeof(WCHAR);
|
||||
|
||||
if (!RegQueryValueExW(hkey, name, NULL, NULL, contentData, &dataSize))
|
||||
if (!RegQueryValueExW(m_hkey, name, NULL, NULL, contentData, &dataSize))
|
||||
{
|
||||
entry->cb += entry->contentsLength + sizeof(WCHAR);
|
||||
}
|
||||
@@ -408,54 +480,168 @@ HRESULT EnumerateRegistryKey(HDPA hdpa, PCWSTR path, HKEY root, UINT * hdpaCount
|
||||
|
||||
}
|
||||
|
||||
DPA_AppendPtr(hdpa, entry);
|
||||
(*hdpaCount)++;
|
||||
*ppidl = (LPITEMIDLIST) entry;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
RegCloseKey(hkey);
|
||||
|
||||
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++)
|
||||
HRESULT EnumerateNext(LPITEMIDLIST* ppidl)
|
||||
{
|
||||
PCWSTR name = rootKeys[i].keyName;
|
||||
DWORD cchName = wcslen(rootKeys[i].keyName);
|
||||
|
||||
REG_ENTRY_TYPE otype = REG_ENTRY_ROOT;
|
||||
if (!m_values)
|
||||
{
|
||||
HRESULT hr = NextKey(ppidl);
|
||||
if (hr != S_FALSE)
|
||||
return hr;
|
||||
|
||||
DWORD entryBufferLength = FIELD_OFFSET(RegPidlEntry, entryName) + sizeof(WCHAR) + cchName * sizeof(WCHAR);
|
||||
// switch to values.
|
||||
m_values = TRUE;
|
||||
m_idx = 0;
|
||||
}
|
||||
|
||||
RegPidlEntry* entry = (RegPidlEntry*) CoTaskMemAlloc(entryBufferLength);
|
||||
return NextValue(ppidl);
|
||||
}
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE Next(ULONG celt, LPITEMIDLIST *rgelt, ULONG *pceltFetched)
|
||||
{
|
||||
if (pceltFetched)
|
||||
*pceltFetched = 0;
|
||||
|
||||
while (celt-- > 0)
|
||||
{
|
||||
HRESULT hr = EnumerateNext(rgelt);
|
||||
if (hr != S_OK)
|
||||
return hr;
|
||||
|
||||
if (pceltFetched)
|
||||
(*pceltFetched)++;
|
||||
if (rgelt)
|
||||
rgelt++;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE Skip(ULONG celt)
|
||||
{
|
||||
while (celt > 0)
|
||||
{
|
||||
HRESULT hr = EnumerateNext(NULL);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
if (hr != S_OK)
|
||||
break;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE Reset()
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE Clone(IEnumIDList **ppenum)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
DECLARE_NOT_AGGREGATABLE(CEnumRegKey)
|
||||
DECLARE_PROTECT_FINAL_CONSTRUCT()
|
||||
|
||||
BEGIN_COM_MAP(CEnumRegKey)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IEnumIDList, IEnumIDList)
|
||||
END_COM_MAP()
|
||||
};
|
||||
|
||||
class CEnumNTDirectory :
|
||||
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
||||
public IEnumIDList
|
||||
{
|
||||
WCHAR buffer[MAX_PATH];
|
||||
HANDLE m_directory;
|
||||
BOOL m_first;
|
||||
ULONG m_enumContext;
|
||||
PWSTR m_pend;
|
||||
|
||||
public:
|
||||
CEnumNTDirectory()
|
||||
: m_directory(NULL), m_first(TRUE), m_enumContext(0), m_pend(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
~CEnumNTDirectory()
|
||||
{
|
||||
NtClose(m_directory);
|
||||
}
|
||||
|
||||
HRESULT Initialize(PCWSTR path)
|
||||
{
|
||||
StringCbCopyExW(buffer, sizeof(buffer), path, &m_pend, NULL, 0);
|
||||
|
||||
DWORD err = NtOpenObject(DIRECTORY_OBJECT, &m_directory, FILE_LIST_DIRECTORY, buffer);
|
||||
if (!NT_SUCCESS(err))
|
||||
{
|
||||
ERR("NtOpenDirectoryObject failed for path %S with status=%x\n", buffer, err);
|
||||
return HRESULT_FROM_NT(err);
|
||||
}
|
||||
|
||||
if (m_pend[-1] != '\\')
|
||||
*m_pend++ = '\\';
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT EnumerateNext(LPITEMIDLIST* ppidl)
|
||||
{
|
||||
BYTE dirbuffer[2048];
|
||||
if (!NT_SUCCESS(NtQueryDirectoryObject(m_directory, dirbuffer, 2048, TRUE, m_first, &m_enumContext, NULL)))
|
||||
return S_FALSE;
|
||||
|
||||
// if ppidl is NULL, assume the caller was Skip(),
|
||||
// so we don't care about the info
|
||||
if (!ppidl)
|
||||
return S_OK;
|
||||
|
||||
m_first = FALSE;
|
||||
POBJECT_DIRECTORY_INFORMATION info = (POBJECT_DIRECTORY_INFORMATION) dirbuffer;
|
||||
|
||||
if (info->Name.Buffer)
|
||||
{
|
||||
StringCbCopyNW(m_pend, sizeof(buffer), info->Name.Buffer, info->Name.Length);
|
||||
}
|
||||
|
||||
OBJECT_TYPE otype = MapTypeNameToType(info->TypeName.Buffer, info->TypeName.Length);
|
||||
|
||||
DWORD entryBufferLength = FIELD_OFFSET(NtPidlEntry, entryName) + sizeof(WCHAR);
|
||||
if (info->Name.Buffer)
|
||||
entryBufferLength += info->Name.Length;
|
||||
|
||||
if (otype < 0)
|
||||
{
|
||||
entryBufferLength += FIELD_OFFSET(NtPidlTypeData, typeName) + sizeof(WCHAR);
|
||||
|
||||
if (info->TypeName.Buffer)
|
||||
{
|
||||
entryBufferLength += info->TypeName.Length;
|
||||
}
|
||||
}
|
||||
|
||||
// allocate space for the terminator
|
||||
entryBufferLength += 2;
|
||||
|
||||
NtPidlEntry* entry = (NtPidlEntry*) 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;
|
||||
entry->magic = NT_OBJECT_PIDL_MAGIC;
|
||||
entry->objectType = otype;
|
||||
|
||||
if (cchName > 0)
|
||||
if (info->Name.Buffer)
|
||||
{
|
||||
entry->entryNameLength = cchName * sizeof(WCHAR);
|
||||
StringCbCopyNW(entry->entryName, entryBufferLength, name, entry->entryNameLength);
|
||||
entry->entryNameLength = info->Name.Length;
|
||||
StringCbCopyNW(entry->entryName, entryBufferLength, info->Name.Buffer, info->Name.Length);
|
||||
entry->cb += entry->entryNameLength + sizeof(WCHAR);
|
||||
}
|
||||
else
|
||||
@@ -464,58 +650,95 @@ HRESULT EnumerateRootKeys(HDPA hdpa, UINT * hdpaCount)
|
||||
entry->entryName[0] = 0;
|
||||
entry->cb += sizeof(WCHAR);
|
||||
}
|
||||
|
||||
DPA_AppendPtr(hdpa, entry);
|
||||
(*hdpaCount)++;
|
||||
|
||||
if (otype < 0)
|
||||
{
|
||||
NtPidlTypeData * typedata = (NtPidlTypeData*) ((PBYTE) entry + entry->cb);
|
||||
DWORD remainingSpace = entryBufferLength - ((PBYTE) (typedata->typeName) - (PBYTE) entry);
|
||||
|
||||
if (info->TypeName.Buffer)
|
||||
{
|
||||
typedata->typeNameLength = info->TypeName.Length;
|
||||
StringCbCopyNW(typedata->typeName, remainingSpace, info->TypeName.Buffer, info->TypeName.Length);
|
||||
|
||||
entry->cb += typedata->typeNameLength + sizeof(WCHAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
typedata->typeNameLength = 0;
|
||||
typedata->typeName[0] = 0;
|
||||
entry->cb += typedata->typeNameLength + sizeof(WCHAR);
|
||||
}
|
||||
}
|
||||
|
||||
*ppidl = (LPITEMIDLIST) entry;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
virtual HRESULT STDMETHODCALLTYPE Next(ULONG celt, LPITEMIDLIST *rgelt, ULONG *pceltFetched)
|
||||
{
|
||||
if (pceltFetched)
|
||||
*pceltFetched = 0;
|
||||
|
||||
while (celt-- > 0)
|
||||
{
|
||||
HRESULT hr = EnumerateNext(rgelt);
|
||||
if (hr != S_OK)
|
||||
return hr;
|
||||
|
||||
if (pceltFetched)
|
||||
(*pceltFetched)++;
|
||||
if (rgelt)
|
||||
rgelt++;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE Skip(ULONG celt)
|
||||
{
|
||||
while (celt > 0)
|
||||
{
|
||||
HRESULT hr = EnumerateNext(NULL);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
if (hr != S_OK)
|
||||
break;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE Reset()
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE Clone(IEnumIDList **ppenum)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
DECLARE_NOT_AGGREGATABLE(CEnumNTDirectory)
|
||||
DECLARE_PROTECT_FINAL_CONSTRUCT()
|
||||
|
||||
BEGIN_COM_MAP(CEnumNTDirectory)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IEnumIDList, IEnumIDList)
|
||||
END_COM_MAP()
|
||||
};
|
||||
|
||||
HRESULT GetEnumRegistryRoot(IEnumIDList ** ppil)
|
||||
{
|
||||
return ShellObjectCreator<CEnumRegRoot>(IID_PPV_ARG(IEnumIDList, ppil));
|
||||
}
|
||||
|
||||
HRESULT ReadRegistryValue(HKEY root, PCWSTR path, PCWSTR valueName, PVOID * valueData, PDWORD valueLength)
|
||||
HRESULT GetEnumRegistryKey(LPCWSTR path, HKEY root, IEnumIDList ** ppil)
|
||||
{
|
||||
HKEY hkey;
|
||||
return ShellObjectCreatorInit<CEnumRegKey>(path, root, IID_PPV_ARG(IEnumIDList, ppil));
|
||||
}
|
||||
|
||||
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;
|
||||
HRESULT GetEnumNTDirectory(LPCWSTR path, IEnumIDList ** ppil)
|
||||
{
|
||||
return ShellObjectCreatorInit<CEnumNTDirectory>(path, IID_PPV_ARG(IEnumIDList, ppil));
|
||||
}
|
||||
@@ -50,11 +50,8 @@ struct NtPidlEntry
|
||||
// If this is -1, there will be a NtPidlTypeData following this, and before any other extensions
|
||||
OBJECT_TYPE objectType;
|
||||
|
||||
OBJECT_BASIC_INFORMATION objectInformation;
|
||||
|
||||
USHORT entryNameLength;
|
||||
WCHAR entryName[ANYSIZE_ARRAY];
|
||||
|
||||
};
|
||||
|
||||
struct NtPidlTypeData
|
||||
@@ -63,12 +60,6 @@ struct NtPidlTypeData
|
||||
WCHAR typeName[ANYSIZE_ARRAY];
|
||||
};
|
||||
|
||||
struct NtPidlSymlinkData
|
||||
{
|
||||
USHORT targetNameLength;
|
||||
WCHAR targetName[ANYSIZE_ARRAY];
|
||||
};
|
||||
|
||||
// REGISTRY browser
|
||||
enum REG_ENTRY_TYPE
|
||||
{
|
||||
@@ -107,8 +98,10 @@ struct RegPidlEntry
|
||||
|
||||
#include <poppack.h>
|
||||
|
||||
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);
|
||||
|
||||
HRESULT ReadRegistryValue(HKEY root, PCWSTR path, PCWSTR valueName, PVOID * valueData, PDWORD valueLength);
|
||||
HRESULT GetEnumRegistryRoot(IEnumIDList ** ppil);
|
||||
HRESULT GetEnumRegistryKey(LPCWSTR path, HKEY root, IEnumIDList ** ppil);
|
||||
HRESULT GetEnumNTDirectory(LPCWSTR path, IEnumIDList ** ppil);
|
||||
|
||||
HRESULT GetNTObjectSymbolicLinkTarget(LPCWSTR path, LPCWSTR entryName, PUNICODE_STRING LinkTarget);
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(ntobjshex);
|
||||
|
||||
|
||||
// {1C6D6E08-2332-4A7B-A94D-6432DB2B5AE6}
|
||||
const GUID CLSID_RegistryFolder = { 0x1c6d6e08, 0x2332, 0x4a7b, { 0xa9, 0x4d, 0x64, 0x32, 0xdb, 0x2b, 0x5a, 0xe6 } };
|
||||
|
||||
@@ -130,9 +131,6 @@ private:
|
||||
PWSTR m_ntPath;
|
||||
HKEY m_hRoot;
|
||||
|
||||
HDPA m_hDpa;
|
||||
UINT m_hDpaCount;
|
||||
|
||||
int DpaDeleteCallback(RegPidlEntry * info)
|
||||
{
|
||||
CoTaskMemFree(info);
|
||||
@@ -149,188 +147,22 @@ private:
|
||||
public:
|
||||
CRegistryPidlManager() :
|
||||
m_ntPath(NULL),
|
||||
m_hRoot(NULL),
|
||||
m_hDpa(NULL),
|
||||
m_hDpaCount(0)
|
||||
m_hRoot(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
~CRegistryPidlManager()
|
||||
{
|
||||
DPA_DestroyCallback(m_hDpa, s_DpaDeleteCallback, this);
|
||||
}
|
||||
|
||||
HRESULT Initialize(PWSTR ntPath, HKEY hRoot)
|
||||
{
|
||||
m_ntPath = ntPath;
|
||||
m_hRoot = hRoot;
|
||||
m_hDpa = NULL;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT Enumerate()
|
||||
{
|
||||
if (m_hDpa)
|
||||
return S_OK;
|
||||
|
||||
m_hDpa = DPA_Create(10);
|
||||
|
||||
if (!m_hDpa)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
HRESULT FindPidlInList(PCUITEMID_CHILD pcidl, const RegPidlEntry ** pinfo)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
if (!m_hDpa)
|
||||
{
|
||||
hr = Enumerate();
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
if (!m_hDpa)
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
const RegPidlEntry * info = (const RegPidlEntry *) pcidl;
|
||||
if ((info->cb < sizeof(RegPidlEntry)) || (info->magic != REGISTRY_PIDL_MAGIC))
|
||||
{
|
||||
ERR("FindPidlInList: Requested pidl is not of the correct type.\n");
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
TRACE("Searching for pidl { name='%S' } in a list of %d items\n", info->entryName, m_hDpaCount);
|
||||
|
||||
for (UINT i = 0; i < m_hDpaCount; i++)
|
||||
{
|
||||
const RegPidlEntry * pInfo = (const RegPidlEntry *) DPA_GetPtr(m_hDpa, i);
|
||||
ASSERT(pInfo);
|
||||
|
||||
hr = CompareIDs(SHCIDS_CANONICALONLY, pInfo, info);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
if (hr == S_OK)
|
||||
{
|
||||
*pinfo = pInfo;
|
||||
return S_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE("Comparison returned %d for '%S'\n", (int) (short) (hr & 0xFFFF), pInfo->entryName);
|
||||
}
|
||||
}
|
||||
|
||||
ERR("PIDL NOT FOUND: Requested filename: %S\n", info->entryName);
|
||||
*pinfo = NULL;
|
||||
|
||||
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
HRESULT FindByName(LPCWSTR strParsingName, RegPidlEntry ** pinfo)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
if (!m_hDpa)
|
||||
{
|
||||
hr = Enumerate();
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
if (!m_hDpa)
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
|
||||
TRACE("Searching for '%S' in a list of %d items\n", strParsingName, m_hDpaCount);
|
||||
|
||||
for (int i = 0; i < (int) m_hDpaCount; i++)
|
||||
{
|
||||
RegPidlEntry * pInfo = (RegPidlEntry *) DPA_GetPtr(m_hDpa, i);
|
||||
ASSERT(pInfo);
|
||||
|
||||
int order = CompareStringW(GetThreadLocale(), NORM_IGNORECASE,
|
||||
pInfo->entryName, wcslen(pInfo->entryName),
|
||||
strParsingName, wcslen(strParsingName));
|
||||
|
||||
if (order == CSTR_EQUAL)
|
||||
{
|
||||
*pinfo = pInfo;
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
TRACE("Pidl not found\n");
|
||||
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
HRESULT GetPidl(UINT index, RegPidlEntry ** pEntry)
|
||||
{
|
||||
if (!m_hDpa)
|
||||
{
|
||||
HRESULT hr = Enumerate();
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
if (!m_hDpa)
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
*pEntry = NULL;
|
||||
|
||||
RegPidlEntry * entry = (RegPidlEntry *) DPA_GetPtr(m_hDpa, index);
|
||||
if (!entry)
|
||||
{
|
||||
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
*pEntry = entry;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT GetCount(UINT * count)
|
||||
{
|
||||
if (!m_hDpa)
|
||||
{
|
||||
HRESULT hr = Enumerate();
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
if (!m_hDpa)
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
*count = m_hDpaCount;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
static LPITEMIDLIST CreatePidlFromItem(const RegPidlEntry * entry)
|
||||
{
|
||||
LPITEMIDLIST idl = (LPITEMIDLIST) CoTaskMemAlloc(entry->cb + 2);
|
||||
if (!idl)
|
||||
return NULL;
|
||||
memset(idl, 0, entry->cb + 2);
|
||||
memcpy(idl, entry, entry->cb);
|
||||
return idl;
|
||||
}
|
||||
|
||||
static HRESULT CompareIDs(LPARAM lParam, const RegPidlEntry * first, const RegPidlEntry * second)
|
||||
{
|
||||
if ((lParam & 0xFFFF0000) == SHCIDS_ALLFIELDS)
|
||||
@@ -460,15 +292,34 @@ public:
|
||||
|
||||
BOOL IsFolder(LPCITEMIDLIST pcidl)
|
||||
{
|
||||
const RegPidlEntry * entry;
|
||||
HRESULT hr = FindPidlInList(pcidl, &entry);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
RegPidlEntry * entry = (RegPidlEntry*) &(pcidl->mkid);
|
||||
if ((entry->cb < sizeof(RegPidlEntry)) || (entry->magic != REGISTRY_PIDL_MAGIC))
|
||||
return FALSE;
|
||||
|
||||
return (entry->entryType == REG_ENTRY_KEY) ||
|
||||
(entry->entryType == REG_ENTRY_ROOT);
|
||||
}
|
||||
|
||||
HRESULT GetInfoFromPidl(LPCITEMIDLIST pcidl, const RegPidlEntry ** pentry)
|
||||
{
|
||||
RegPidlEntry * entry = (RegPidlEntry*) &(pcidl->mkid);
|
||||
|
||||
if (entry->cb < sizeof(RegPidlEntry))
|
||||
{
|
||||
DbgPrint("PCIDL too small %l (required %l)\n", entry->cb, sizeof(RegPidlEntry));
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
if (entry->magic != REGISTRY_PIDL_MAGIC)
|
||||
{
|
||||
DbgPrint("PCIDL magic mismatch %04x (expected %04x)\n", entry->magic, REGISTRY_PIDL_MAGIC);
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*pentry = entry;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT FormatValueData(DWORD contentType, PVOID td, DWORD contentsLength, PCWSTR * strContents)
|
||||
{
|
||||
switch (contentType)
|
||||
@@ -574,121 +425,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class CRegistryFolderEnum :
|
||||
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
||||
public IEnumIDList
|
||||
{
|
||||
private:
|
||||
CComPtr<CRegistryFolder> m_Folder;
|
||||
|
||||
HWND m_HwndOwner;
|
||||
SHCONTF m_Flags;
|
||||
|
||||
UINT m_Index;
|
||||
UINT m_Count;
|
||||
|
||||
public:
|
||||
CRegistryFolderEnum() :
|
||||
m_HwndOwner(NULL),
|
||||
m_Flags(0),
|
||||
m_Index(0),
|
||||
m_Count(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~CRegistryFolderEnum()
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT Initialize(CRegistryFolder * folder, HWND hwndOwner, SHCONTF flags)
|
||||
{
|
||||
m_Folder = folder;
|
||||
|
||||
m_Folder->GetManager().GetCount(&m_Count);
|
||||
|
||||
m_HwndOwner = hwndOwner;
|
||||
m_Flags = flags;
|
||||
|
||||
return Reset();
|
||||
}
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE Next(
|
||||
ULONG celt,
|
||||
LPITEMIDLIST *rgelt,
|
||||
ULONG *pceltFetched)
|
||||
{
|
||||
if (pceltFetched)
|
||||
*pceltFetched = 0;
|
||||
|
||||
if (m_Index >= m_Count)
|
||||
return S_FALSE;
|
||||
|
||||
for (int i = 0; i < (int) celt;)
|
||||
{
|
||||
RegPidlEntry * tinfo;
|
||||
BOOL flagsOk = FALSE;
|
||||
|
||||
do {
|
||||
HRESULT hr = m_Folder->GetManager().GetPidl(m_Index++, &tinfo);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
switch (tinfo->entryType)
|
||||
{
|
||||
case REG_ENTRY_KEY:
|
||||
case REG_ENTRY_ROOT:
|
||||
flagsOk = (m_Flags & SHCONTF_FOLDERS) != 0;
|
||||
break;
|
||||
default:
|
||||
flagsOk = (m_Flags & SHCONTF_NONFOLDERS) != 0;
|
||||
break;
|
||||
}
|
||||
} while (m_Index < m_Count && !flagsOk);
|
||||
|
||||
if (flagsOk)
|
||||
{
|
||||
if (rgelt)
|
||||
rgelt[i] = m_Folder->GetManager().CreatePidlFromItem(tinfo);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (m_Index == m_Count)
|
||||
{
|
||||
if (pceltFetched)
|
||||
*pceltFetched = i;
|
||||
return (i == (int) celt) ? S_OK : S_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (pceltFetched) *pceltFetched = celt;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE Skip(ULONG celt)
|
||||
{
|
||||
return Next(celt, NULL, NULL);
|
||||
}
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE Reset()
|
||||
{
|
||||
m_Index = 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE Clone(IEnumIDList **ppenum)
|
||||
{
|
||||
return ShellObjectCreatorInit<CRegistryFolderEnum>(m_Folder, m_HwndOwner, m_Flags, IID_PPV_ARG(IEnumIDList, ppenum));
|
||||
}
|
||||
|
||||
DECLARE_NOT_AGGREGATABLE(CRegistryFolderEnum)
|
||||
DECLARE_PROTECT_FINAL_CONSTRUCT()
|
||||
|
||||
BEGIN_COM_MAP(CRegistryFolderEnum)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IEnumIDList, IEnumIDList)
|
||||
END_COM_MAP()
|
||||
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CRegistryFolder
|
||||
|
||||
@@ -715,8 +451,6 @@ HRESULT STDMETHODCALLTYPE CRegistryFolder::ParseDisplayName(
|
||||
LPITEMIDLIST *ppidl,
|
||||
ULONG *pdwAttributes)
|
||||
{
|
||||
RegPidlEntry * info;
|
||||
|
||||
if (!ppidl)
|
||||
return E_POINTER;
|
||||
|
||||
@@ -728,19 +462,45 @@ HRESULT STDMETHODCALLTYPE CRegistryFolder::ParseDisplayName(
|
||||
|
||||
TRACE("CRegistryFolder::ParseDisplayName name=%S (ntPath=%S)\n", lpszDisplayName, m_NtPath);
|
||||
|
||||
HRESULT hr = m_PidlManager->FindByName(lpszDisplayName, &info);
|
||||
const RegPidlEntry * info;
|
||||
IEnumIDList * it;
|
||||
HRESULT hr = GetEnumNTDirectory(m_NtPath, &it);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
*ppidl = m_PidlManager->CreatePidlFromItem(info);
|
||||
while (TRUE)
|
||||
{
|
||||
hr = it->Next(1, ppidl, NULL);
|
||||
|
||||
if (pchEaten)
|
||||
*pchEaten = wcslen(info->entryName);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
if (pdwAttributes)
|
||||
*pdwAttributes = m_PidlManager->ConvertAttributes(info, pdwAttributes);
|
||||
if (hr != S_OK)
|
||||
break;
|
||||
|
||||
hr = m_PidlManager->GetInfoFromPidl(*ppidl, &info);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
if (StrCmpW(info->entryName, lpszDisplayName) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (hr != S_OK)
|
||||
{
|
||||
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
if (pchEaten || pdwAttributes)
|
||||
{
|
||||
if (pchEaten)
|
||||
*pchEaten = wcslen(info->entryName);
|
||||
|
||||
if (pdwAttributes)
|
||||
*pdwAttributes = m_PidlManager->ConvertAttributes(info, pdwAttributes);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
@@ -750,7 +510,14 @@ HRESULT STDMETHODCALLTYPE CRegistryFolder::EnumObjects(
|
||||
SHCONTF grfFlags,
|
||||
IEnumIDList **ppenumIDList)
|
||||
{
|
||||
return ShellObjectCreatorInit<CRegistryFolderEnum>(this, hwndOwner, grfFlags, IID_PPV_ARG(IEnumIDList, ppenumIDList));
|
||||
if (wcslen(m_NtPath) == 0 && m_hRoot == NULL)
|
||||
{
|
||||
return GetEnumRegistryRoot(ppenumIDList);
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetEnumRegistryKey(m_NtPath, m_hRoot, ppenumIDList);
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE CRegistryFolder::BindToObject(
|
||||
@@ -763,7 +530,7 @@ HRESULT STDMETHODCALLTYPE CRegistryFolder::BindToObject(
|
||||
|
||||
if (IsEqualIID(riid, IID_IShellFolder))
|
||||
{
|
||||
HRESULT hr = m_PidlManager->FindPidlInList(pidl, &info);
|
||||
HRESULT hr = m_PidlManager->GetInfoFromPidl(pidl, &info);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
@@ -886,7 +653,7 @@ HRESULT STDMETHODCALLTYPE CRegistryFolder::GetAttributesOf(
|
||||
{
|
||||
PCUITEMID_CHILD pidl = apidl[i];
|
||||
|
||||
HRESULT hr = m_PidlManager->FindPidlInList(pidl, &info);
|
||||
HRESULT hr = m_PidlManager->GetInfoFromPidl(pidl, &info);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
@@ -913,12 +680,15 @@ HRESULT STDMETHODCALLTYPE CRegistryFolder::GetUIObjectOf(
|
||||
{
|
||||
CComPtr<IContextMenu> pcm;
|
||||
|
||||
HKEY keys [1];
|
||||
DWORD res;
|
||||
HKEY keys[1];
|
||||
|
||||
int nkeys = _countof(keys);
|
||||
if (cidl == 1 && m_PidlManager->IsFolder(apidl[0]))
|
||||
{
|
||||
RegOpenKey(HKEY_CLASSES_ROOT, L"Folder", keys + 0);
|
||||
res = RegOpenKey(HKEY_CLASSES_ROOT, L"Folder", keys + 0);
|
||||
if (!NT_SUCCESS(res))
|
||||
return HRESULT_FROM_NT(res);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -971,7 +741,7 @@ HRESULT STDMETHODCALLTYPE CRegistryFolder::GetDisplayNameOf(
|
||||
|
||||
TRACE("GetDisplayNameOf %p\n", pidl);
|
||||
|
||||
HRESULT hr = m_PidlManager->FindPidlInList(pidl, &info);
|
||||
HRESULT hr = m_PidlManager->GetInfoFromPidl(pidl, &info);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
@@ -1144,7 +914,7 @@ HRESULT STDMETHODCALLTYPE CRegistryFolder::GetDetailsEx(
|
||||
|
||||
if (pidl)
|
||||
{
|
||||
HRESULT hr = m_PidlManager->FindPidlInList(pidl, &info);
|
||||
HRESULT hr = m_PidlManager->GetInfoFromPidl(pidl, &info);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
@@ -1170,7 +940,7 @@ HRESULT STDMETHODCALLTYPE CRegistryFolder::GetDetailsEx(
|
||||
{
|
||||
if (info->contentsLength > 0)
|
||||
{
|
||||
PWSTR td = (PWSTR)(((PBYTE) info) + FIELD_OFFSET(RegPidlEntry, entryName) + info->entryNameLength + sizeof(WCHAR));
|
||||
PWSTR td = (PWSTR) (((PBYTE) info) + FIELD_OFFSET(RegPidlEntry, entryName) + info->entryNameLength + sizeof(WCHAR));
|
||||
|
||||
return MakeVariantString(pv, td);
|
||||
}
|
||||
@@ -1217,7 +987,7 @@ HRESULT STDMETHODCALLTYPE CRegistryFolder::GetDetailsOf(
|
||||
|
||||
if (pidl)
|
||||
{
|
||||
HRESULT hr = m_PidlManager->FindPidlInList(pidl, &info);
|
||||
HRESULT hr = m_PidlManager->GetInfoFromPidl(pidl, &info);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
@@ -1343,8 +1113,6 @@ HRESULT STDMETHODCALLTYPE CRegistryFolder::MessageSFVCB(UINT uMsg, WPARAM wParam
|
||||
return S_FALSE;
|
||||
case SFVM_BACKGROUNDENUM:
|
||||
return S_OK;
|
||||
case SFVM_DEFITEMCOUNT:
|
||||
return m_PidlManager->GetCount((UINT*) lParam);
|
||||
}
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user