[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:
David Quintana
2015-08-21 14:26:25 +00:00
parent 08229bbb07
commit 89da5820cd
4 changed files with 679 additions and 988 deletions
+109 -402
View File
@@ -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;
}
+489 -266
View File
@@ -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));
}
+6 -13
View File
@@ -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);
+75 -307
View File
@@ -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;
}