mirror of
https://github.com/reactos/reactos.git
synced 2025-04-25 16:10:29 +00:00
[SHELL32] Implement IShellFolder2::GetDetailsEx (#7880)
This commit is contained in:
parent
4cbd5d1b44
commit
d3456f5060
10 changed files with 395 additions and 44 deletions
|
@ -84,6 +84,14 @@ HRESULT WINAPI CControlPanelEnum::Initialize(DWORD dwFlags, IEnumIDList* pRegEnu
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
static const CLSID* IsRegItem(LPCITEMIDLIST pidl)
|
||||
{
|
||||
BYTE type = _ILGetType(pidl);
|
||||
if (type == PT_CONTROLS_OLDREGITEM || type == PT_CONTROLS_NEWREGITEM)
|
||||
return (CLSID*)((BYTE*)pidl + (pidl->mkid.cb - sizeof(CLSID)));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static LPITEMIDLIST _ILCreateCPanelApplet(LPCWSTR pszName, LPCWSTR pszDisplayName, LPCWSTR pszComment, int iIconIdx)
|
||||
{
|
||||
PIDLCPanelStruct *pCP;
|
||||
|
@ -565,8 +573,9 @@ HRESULT WINAPI CControlPanelFolder::GetDefaultColumnState(UINT iColumn, DWORD *p
|
|||
|
||||
HRESULT WINAPI CControlPanelFolder::GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID *pscid, VARIANT *pv)
|
||||
{
|
||||
FIXME("(%p)\n", this);
|
||||
return E_NOTIMPL;
|
||||
if (IsRegItem(pidl))
|
||||
return m_regFolder->GetDetailsEx(pidl, pscid, pv);
|
||||
return SH32_GetDetailsOfPKeyAsVariant(this, pidl, pscid, pv, FALSE);
|
||||
}
|
||||
|
||||
HRESULT WINAPI CControlPanelFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *psd)
|
||||
|
@ -605,8 +614,12 @@ HRESULT WINAPI CControlPanelFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iCol
|
|||
|
||||
HRESULT WINAPI CControlPanelFolder::MapColumnToSCID(UINT column, SHCOLUMNID *pscid)
|
||||
{
|
||||
FIXME("(%p)\n", this);
|
||||
return E_NOTIMPL;
|
||||
switch (column)
|
||||
{
|
||||
case CONTROLPANEL_COL_NAME: return MakeSCID(*pscid, FMTID_Storage, PID_STG_NAME);
|
||||
case CONTROLPANEL_COL_COMMENT: return MakeSCID(*pscid, FMTID_SummaryInformation, PIDSI_COMMENTS);
|
||||
}
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
|
|
|
@ -955,14 +955,14 @@ HRESULT WINAPI CDesktopFolder::GetDefaultColumnState(UINT iColumn, SHCOLSTATEF *
|
|||
return hr;
|
||||
}
|
||||
|
||||
HRESULT WINAPI CDesktopFolder::GetDetailsEx(
|
||||
PCUITEMID_CHILD pidl,
|
||||
const SHCOLUMNID *pscid,
|
||||
VARIANT *pv)
|
||||
HRESULT WINAPI CDesktopFolder::GetDetailsEx(PCUITEMID_CHILD pidl,
|
||||
const SHCOLUMNID *pscid, VARIANT *pv)
|
||||
{
|
||||
FIXME ("(%p)\n", this);
|
||||
|
||||
return E_NOTIMPL;
|
||||
HRESULT hr;
|
||||
CComPtr<IShellFolder2> psf;
|
||||
if (FAILED_UNEXPECTEDLY(hr = _GetSFFromPidl(pidl, &psf)))
|
||||
return hr;
|
||||
return psf->GetDetailsEx(pidl, pscid, pv);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
|
@ -1002,8 +1002,14 @@ HRESULT WINAPI CDesktopFolder::GetDetailsOf(
|
|||
|
||||
HRESULT WINAPI CDesktopFolder::MapColumnToSCID(UINT column, SHCOLUMNID *pscid)
|
||||
{
|
||||
FIXME ("(%p)\n", this);
|
||||
return E_NOTIMPL;
|
||||
// Note: All these folders use the same SHFSF_COL mapping (m_regFolder only handles a subset).
|
||||
if (m_DesktopFSFolder)
|
||||
return m_DesktopFSFolder->MapColumnToSCID(column, pscid);
|
||||
if (m_SharedDesktopFSFolder)
|
||||
return m_SharedDesktopFSFolder->MapColumnToSCID(column, pscid);
|
||||
if (m_regFolder)
|
||||
return m_regFolder->MapColumnToSCID(column, pscid);
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
HRESULT WINAPI CDesktopFolder::GetClassID(CLSID *lpClassId)
|
||||
|
|
|
@ -26,6 +26,9 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
||||
|
||||
extern BOOL IsDriveFloppyA(LPCSTR pszDriveRoot);
|
||||
extern BOOL IsDriveFloppyW(LPCWSTR pszDriveRoot);
|
||||
|
||||
/*
|
||||
CDrivesFolder should create a CRegFolder to represent the virtual items that exist only in
|
||||
the registry. The CRegFolder is aggregated by the CDrivesFolder.
|
||||
|
@ -105,6 +108,13 @@ template<class T> static T* GetDrivePath(PCUITEMID_CHILD pidl, T *Path)
|
|||
return Path;
|
||||
}
|
||||
|
||||
static inline UINT _ILGetRemovableTypeId(LPCITEMIDLIST pidl)
|
||||
{
|
||||
WCHAR buf[8];
|
||||
if (GetDrivePath(pidl, buf) && IsDriveFloppyW(buf))
|
||||
return SHDID_COMPUTER_DRIVE35; // TODO: 3.5-inch vs 5.25-inch
|
||||
return SHDID_COMPUTER_REMOVABLE;
|
||||
}
|
||||
|
||||
BOOL _ILGetDriveType(LPCITEMIDLIST pidl)
|
||||
{
|
||||
|
@ -477,8 +487,6 @@ static HRESULT GetDriveLabel(PCWSTR DrivePath, LPWSTR szLabel, UINT cchMax)
|
|||
return hr == S_OK ? S_OK : GetRawDriveLabel(DrivePath, szLabel, cchMax);
|
||||
}
|
||||
|
||||
BOOL IsDriveFloppyA(LPCSTR pszDriveRoot);
|
||||
|
||||
HRESULT CDrivesExtractIcon_CreateInstance(IShellFolder * psf, LPCITEMIDLIST pidl, REFIID riid, LPVOID * ppvOut)
|
||||
{
|
||||
CComPtr<IDefaultExtractIconInit> initIcon;
|
||||
|
@ -1149,10 +1157,33 @@ HRESULT WINAPI CDrivesFolder::GetDefaultColumnState(UINT iColumn, SHCOLSTATEF *
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT WINAPI CDrivesFolder::GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID * pscid, VARIANT * pv)
|
||||
HRESULT WINAPI CDrivesFolder::GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID *pscid, VARIANT *pv)
|
||||
{
|
||||
FIXME("(%p)\n", this);
|
||||
return E_NOTIMPL;
|
||||
const CLSID *pCLSID = IsRegItem(pidl);
|
||||
if (pscid->fmtid == FMTID_ShellDetails)
|
||||
{
|
||||
switch (pscid->pid)
|
||||
{
|
||||
case PID_DESCRIPTIONID:
|
||||
{
|
||||
if (pCLSID)
|
||||
return SHELL_CreateSHDESCRIPTIONID(pv, SHDID_ROOT_REGITEM, pCLSID);
|
||||
UINT id = SHDID_COMPUTER_OTHER;
|
||||
switch (_ILGetDriveType(pidl))
|
||||
{
|
||||
case DRIVE_REMOVABLE: id = _ILGetRemovableTypeId(pidl); break;
|
||||
case DRIVE_FIXED: id = SHDID_COMPUTER_FIXED; break;
|
||||
case DRIVE_REMOTE: id = SHDID_COMPUTER_NETDRIVE; break;
|
||||
case DRIVE_CDROM: id = SHDID_COMPUTER_CDROM; break;
|
||||
case DRIVE_RAMDISK: id = SHDID_COMPUTER_RAMDISK; break;
|
||||
}
|
||||
return SHELL_CreateSHDESCRIPTIONID(pv, id, &CLSID_NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pCLSID)
|
||||
return m_regFolder->GetDetailsEx(pidl, pscid, pv);
|
||||
return SH32_GetDetailsOfPKeyAsVariant(this, pidl, pscid, pv, FALSE);
|
||||
}
|
||||
|
||||
HRESULT WINAPI CDrivesFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *psd)
|
||||
|
@ -1175,13 +1206,14 @@ HRESULT WINAPI CDrivesFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, S
|
|||
switch (MyComputerSFHeader[iColumn].colnameid)
|
||||
{
|
||||
case IDS_SHV_COLUMN_NAME:
|
||||
return m_regFolder->GetDetailsOf(pidl, SHFSF_COL_NAME, psd);
|
||||
case IDS_SHV_COLUMN_TYPE:
|
||||
return m_regFolder->GetDetailsOf(pidl, iColumn, psd);
|
||||
return m_regFolder->GetDetailsOf(pidl, SHFSF_COL_TYPE, psd);
|
||||
case IDS_SHV_COLUMN_DISK_CAPACITY:
|
||||
case IDS_SHV_COLUMN_DISK_AVAILABLE:
|
||||
return SHSetStrRet(&psd->str, ""); /* blank col */
|
||||
return SHSetStrRetEmpty(&psd->str);
|
||||
case IDS_SHV_COLUMN_COMMENTS:
|
||||
return m_regFolder->GetDetailsOf(pidl, 2, psd); /* 2 = comments */
|
||||
return m_regFolder->GetDetailsOf(pidl, SHFSF_COL_COMMENT, psd);
|
||||
DEFAULT_UNREACHABLE;
|
||||
}
|
||||
}
|
||||
|
@ -1228,10 +1260,15 @@ HRESULT WINAPI CDrivesFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, S
|
|||
return hr;
|
||||
}
|
||||
|
||||
HRESULT WINAPI CDrivesFolder::MapColumnToSCID(UINT column, SHCOLUMNID * pscid)
|
||||
HRESULT WINAPI CDrivesFolder::MapColumnToSCID(UINT column, SHCOLUMNID *pscid)
|
||||
{
|
||||
FIXME("(%p)\n", this);
|
||||
return E_NOTIMPL;
|
||||
switch (column < _countof(MyComputerSFHeader) ? MyComputerSFHeader[column].colnameid : ~0UL)
|
||||
{
|
||||
case IDS_SHV_COLUMN_NAME: return MakeSCID(*pscid, FMTID_Storage, PID_STG_NAME);
|
||||
case IDS_SHV_COLUMN_TYPE: return MakeSCID(*pscid, FMTID_Storage, PID_STG_STORAGETYPE);
|
||||
case IDS_SHV_COLUMN_COMMENTS: return MakeSCID(*pscid, FMTID_SummaryInformation, PIDSI_COMMENTS);
|
||||
}
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
|
|
|
@ -88,9 +88,9 @@ static HKEY OpenKeyFromFileType(LPCWSTR pExtension, LPCWSTR KeyName)
|
|||
return hkey;
|
||||
}
|
||||
|
||||
static LPCWSTR ExtensionFromPidl(PCUIDLIST_RELATIVE pidl, LPWSTR Buf, UINT cchMax)
|
||||
static LPCWSTR ExtensionFromPidl(PCUIDLIST_RELATIVE pidl, LPWSTR Buf, UINT cchMax, BOOL AllowFolder = FALSE)
|
||||
{
|
||||
if (!_ILIsValue(pidl))
|
||||
if (!AllowFolder && !_ILIsValue(pidl))
|
||||
{
|
||||
ERR("Invalid pidl!\n");
|
||||
return NULL;
|
||||
|
@ -171,6 +171,21 @@ HRESULT GetCLSIDForFileType(PCUIDLIST_RELATIVE pidl, LPCWSTR KeyName, CLSID* pcl
|
|||
return GetCLSIDForFileTypeFromExtension(pExtension, KeyName, pclsid);
|
||||
}
|
||||
|
||||
HRESULT GetItemCLSID(PCUIDLIST_RELATIVE pidl, CLSID *pclsid)
|
||||
{
|
||||
WCHAR buf[256];
|
||||
LPCWSTR pExt = ExtensionFromPidl(pidl, buf, _countof(buf), TRUE);
|
||||
if (!pExt)
|
||||
return E_FAIL;
|
||||
HRESULT hr = E_FAIL;
|
||||
if (!ItemIsFolder(pidl))
|
||||
hr = GetCLSIDForFileTypeFromExtension(pExt, L"CLSID", pclsid);
|
||||
// TODO: Should we handle folders with desktop.ini here?
|
||||
if (hr != S_OK && pExt[0] == '.' && pExt[1] == '{')
|
||||
hr = CLSIDFromString(pExt + 1, pclsid);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT
|
||||
getDefaultIconLocation(LPWSTR szIconFile, UINT cchMax, int *piIndex, UINT uFlags)
|
||||
{
|
||||
|
@ -1643,12 +1658,56 @@ HRESULT WINAPI CFSFolder::GetDefaultColumnState(UINT iColumn,
|
|||
return GetDefaultFSColumnState(iColumn, *pcsFlags);
|
||||
}
|
||||
|
||||
HRESULT WINAPI CFSFolder::GetDetailsEx(PCUITEMID_CHILD pidl,
|
||||
const SHCOLUMNID * pscid, VARIANT * pv)
|
||||
HRESULT WINAPI CFSFolder::GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID *pscid, VARIANT *pv)
|
||||
{
|
||||
FIXME ("(%p)\n", this);
|
||||
|
||||
return E_NOTIMPL;
|
||||
if (!_ILGetFSType(pidl))
|
||||
return E_INVALIDARG;
|
||||
HRESULT hr;
|
||||
if (pscid->fmtid == FMTID_ShellDetails)
|
||||
{
|
||||
switch (pscid->pid)
|
||||
{
|
||||
case PID_DESCRIPTIONID:
|
||||
{
|
||||
if (FAILED(hr = SHELL_CreateVariantBuffer(pv, sizeof(SHDESCRIPTIONID))))
|
||||
return hr;
|
||||
SHDESCRIPTIONID *pDID = (SHDESCRIPTIONID*)V_ARRAY(pv)->pvData;
|
||||
if (ItemIsFolder(pidl))
|
||||
pDID->dwDescriptionId = SHDID_FS_DIRECTORY;
|
||||
else if (_ILGetFSType(pidl) & PT_FS_FILE_FLAG)
|
||||
pDID->dwDescriptionId = SHDID_FS_FILE;
|
||||
else
|
||||
pDID->dwDescriptionId = SHDID_FS_OTHER;
|
||||
if (FAILED(GetItemCLSID(pidl, &pDID->clsid)))
|
||||
pDID->clsid = CLSID_NULL;
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Handle non-string fields here when possible instead of deferring to GetDetailsOf
|
||||
const FileStruct &fsitem = ((PIDLDATA*)pidl->mkid.abID)->u.file;
|
||||
if (pscid->fmtid == FMTID_Storage)
|
||||
{
|
||||
switch (pscid->pid)
|
||||
{
|
||||
case PID_STG_NAME: // Handled directly here for faster performance
|
||||
return SHELL_GetDetailsOfAsStringVariant(this, pidl, SHFSF_COL_NAME, pv);
|
||||
case PID_STG_SIZE:
|
||||
V_VT(pv) = VT_UI4;
|
||||
V_UI4(pv) = _ILGetFileSize(pidl, NULL, 0);
|
||||
return S_OK;
|
||||
case PID_STG_ATTRIBUTES:
|
||||
V_VT(pv) = VT_UI4;
|
||||
V_UI4(pv) = fsitem.uFileAttribs;
|
||||
return S_OK;
|
||||
case PID_STG_WRITETIME:
|
||||
V_VT(pv) = VT_DATE;
|
||||
if (DosDateTimeToVariantTime(fsitem.uFileDate, fsitem.uFileTime, &V_DATE(pv)))
|
||||
return S_OK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return SH32_GetDetailsOfPKeyAsVariant(this, pidl, pscid, pv, TRUE);
|
||||
}
|
||||
|
||||
HRESULT WINAPI CFSFolder::GetDetailsOf(PCUITEMID_CHILD pidl,
|
||||
|
@ -1714,11 +1773,18 @@ HRESULT WINAPI CFSFolder::GetDetailsOf(PCUITEMID_CHILD pidl,
|
|||
return hr;
|
||||
}
|
||||
|
||||
HRESULT WINAPI CFSFolder::MapColumnToSCID (UINT column,
|
||||
SHCOLUMNID * pscid)
|
||||
HRESULT WINAPI CFSFolder::MapColumnToSCID(UINT column, SHCOLUMNID *pscid)
|
||||
{
|
||||
FIXME ("(%p)\n", this);
|
||||
return E_NOTIMPL;
|
||||
switch (column)
|
||||
{
|
||||
case SHFSF_COL_NAME: return MakeSCID(*pscid, FMTID_Storage, PID_STG_NAME);
|
||||
case SHFSF_COL_SIZE: return MakeSCID(*pscid, FMTID_Storage, PID_STG_SIZE);
|
||||
case SHFSF_COL_TYPE: return MakeSCID(*pscid, FMTID_Storage, PID_STG_STORAGETYPE);
|
||||
case SHFSF_COL_MDATE: return MakeSCID(*pscid, FMTID_Storage, PID_STG_WRITETIME);
|
||||
case SHFSF_COL_FATTS: return MakeSCID(*pscid, FMTID_Storage, PID_STG_ATTRIBUTES);
|
||||
case SHFSF_COL_COMMENT: return MakeSCID(*pscid, FMTID_SummaryInformation, PIDSI_COMMENTS);
|
||||
}
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
|
|
|
@ -818,7 +818,18 @@ HRESULT WINAPI CRegFolder::GetDefaultColumnState(UINT iColumn, DWORD *pcsFlags)
|
|||
|
||||
HRESULT WINAPI CRegFolder::GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID *pscid, VARIANT *pv)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
const CLSID *pCLSID = IsRegItem(pidl);
|
||||
if (!pCLSID)
|
||||
return E_INVALIDARG;
|
||||
if (pscid->fmtid == FMTID_ShellDetails)
|
||||
{
|
||||
switch (pscid->pid)
|
||||
{
|
||||
case PID_DESCRIPTIONID:
|
||||
return SHELL_CreateSHDESCRIPTIONID(pv, SHDID_ROOT_REGITEM, pCLSID);
|
||||
}
|
||||
}
|
||||
return SH32_GetDetailsOfPKeyAsVariant(this, pidl, pscid, pv, TRUE);
|
||||
}
|
||||
|
||||
HRESULT WINAPI CRegFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *psd)
|
||||
|
@ -849,7 +860,7 @@ HRESULT WINAPI CRegFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHEL
|
|||
case COL_INFOTIP:
|
||||
HKEY hKey;
|
||||
if (!HCR_RegOpenClassIDKey(*clsid, &hKey))
|
||||
return SHSetStrRet(&psd->str, "");
|
||||
return SHSetStrRetEmpty(&psd->str);
|
||||
|
||||
psd->str.cStr[0] = 0x00;
|
||||
psd->str.uType = STRRET_CSTR;
|
||||
|
@ -857,17 +868,23 @@ HRESULT WINAPI CRegFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHEL
|
|||
RegCloseKey(hKey);
|
||||
return S_OK;
|
||||
default:
|
||||
/* Return an empty string when we area asked for a column we don't support.
|
||||
Only the regfolder is supposed to do this as it supports less columns compared to other folder
|
||||
/* Return an empty string when we are asked for a column we don't support.
|
||||
Only the regfolder is supposed to do this as it supports fewer columns compared to other folders
|
||||
and its contents are supposed to be presented alongside items that support more columns. */
|
||||
return SHSetStrRet(&psd->str, "");
|
||||
return SHSetStrRetEmpty(&psd->str);
|
||||
}
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
HRESULT WINAPI CRegFolder::MapColumnToSCID(UINT column, SHCOLUMNID *pscid)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
switch (column)
|
||||
{
|
||||
case COL_NAME: return MakeSCID(*pscid, FMTID_Storage, PID_STG_NAME);
|
||||
case COL_TYPE: return MakeSCID(*pscid, FMTID_Storage, PID_STG_STORAGETYPE);
|
||||
case COL_INFOTIP: return MakeSCID(*pscid, FMTID_SummaryInformation, PIDSI_COMMENTS);
|
||||
}
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
static HRESULT CALLBACK RegFolderContextMenuCallback(IShellFolder *psf, HWND hwnd, IDataObject *pdtobj,
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#ifndef _SHFLDR_H_
|
||||
#define _SHFLDR_H_
|
||||
#include <ntquery.h> // For PID_STG_*
|
||||
|
||||
#define CHARS_IN_GUID 39
|
||||
|
||||
|
@ -94,6 +95,23 @@ SHELL_GetDefaultFolderEnumSHCONTF();
|
|||
BOOL
|
||||
SHELL_IncludeItemInFolderEnum(IShellFolder *pSF, PCUITEMID_CHILD pidl, SFGAOF Query, SHCONTF Flags);
|
||||
|
||||
static inline HRESULT
|
||||
MakeSCID(SHCOLUMNID &scid, REFCLSID fmtid, UINT pid)
|
||||
{
|
||||
scid.fmtid = fmtid;
|
||||
scid.pid = pid;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
SHELL_MapSCIDToColumn(IShellFolder2 *pSF, const SHCOLUMNID *pscid);
|
||||
HRESULT
|
||||
SHELL_GetDetailsOfAsStringVariant(IShellFolder2 *pSF, PCUITEMID_CHILD pidl, UINT Column, VARIANT *pVar);
|
||||
HRESULT
|
||||
SHELL_GetDetailsOfColumnAsVariant(IShellFolder2 *pSF, PCUITEMID_CHILD pidl, UINT Column, VARTYPE vt, VARIANT *pVar);
|
||||
HRESULT
|
||||
SH32_GetDetailsOfPKeyAsVariant(IShellFolder2 *pSF, PCUITEMID_CHILD pidl, const SHCOLUMNID *pscid, VARIANT *pVar, BOOL UseFsColMap);
|
||||
|
||||
HRESULT
|
||||
SHELL_CreateAbsolutePidl(IShellFolder *pSF, PCUIDLIST_RELATIVE pidlChild, PIDLIST_ABSOLUTE *ppPidl);
|
||||
|
||||
|
|
|
@ -54,6 +54,91 @@ BOOL SHELL_IncludeItemInFolderEnum(IShellFolder *pSF, PCUITEMID_CHILD pidl, SFGA
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static HRESULT
|
||||
MapSCIDToShell32FsColumn(const SHCOLUMNID *pscid, VARTYPE &vt)
|
||||
{
|
||||
if (pscid->fmtid == FMTID_Storage)
|
||||
{
|
||||
switch (pscid->pid)
|
||||
{
|
||||
case PID_STG_NAME: vt = VT_BSTR; return SHFSF_COL_NAME;
|
||||
case PID_STG_SIZE: vt = VT_UI8; return SHFSF_COL_SIZE;
|
||||
case PID_STG_STORAGETYPE: vt = VT_BSTR; return SHFSF_COL_TYPE;
|
||||
case PID_STG_ATTRIBUTES: vt = VT_BSTR; return SHFSF_COL_FATTS;
|
||||
case PID_STG_WRITETIME: vt = VT_DATE; return SHFSF_COL_MDATE;
|
||||
}
|
||||
}
|
||||
if (pscid->fmtid == FMTID_SummaryInformation && pscid->pid == PIDSI_COMMENTS)
|
||||
{
|
||||
vt = VT_BSTR;
|
||||
return SHFSF_COL_COMMENT;
|
||||
}
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
SHELL_MapSCIDToColumn(IShellFolder2 *pSF, const SHCOLUMNID *pscid)
|
||||
{
|
||||
for (UINT i = 0; i <= SHCIDS_COLUMNMASK; ++i)
|
||||
{
|
||||
SHCOLUMNID scid;
|
||||
HRESULT hr = pSF->MapColumnToSCID(i, &scid);
|
||||
if (FAILED(hr))
|
||||
break;
|
||||
if (IsEqualPropertyKey(scid, *pscid))
|
||||
return i;
|
||||
}
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
SHELL_GetDetailsOfAsStringVariant(IShellFolder2 *pSF, PCUITEMID_CHILD pidl, UINT Column, VARIANT *pVar)
|
||||
{
|
||||
V_VT(pVar) = VT_EMPTY;
|
||||
SHELLDETAILS sd;
|
||||
sd.str.uType = STRRET_CSTR;
|
||||
HRESULT hr = pSF->GetDetailsOf(pidl, Column, &sd);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
if (FAILED(hr = StrRetToBSTR(&sd.str, pidl, &V_BSTR(pVar))))
|
||||
return hr;
|
||||
V_VT(pVar) = VT_BSTR;
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
SHELL_GetDetailsOfColumnAsVariant(IShellFolder2 *pSF, PCUITEMID_CHILD pidl, UINT Column, VARTYPE vt, VARIANT *pVar)
|
||||
{
|
||||
HRESULT hr = SHELL_GetDetailsOfAsStringVariant(pSF, pidl, Column, pVar);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
if (vt == VT_EMPTY)
|
||||
{
|
||||
SHCOLSTATEF state;
|
||||
if (FAILED(pSF->GetDefaultColumnState(Column, &state)))
|
||||
state = SHCOLSTATE_TYPE_STR;
|
||||
if ((state & SHCOLSTATE_TYPEMASK) == SHCOLSTATE_TYPE_INT)
|
||||
vt = VT_I8;
|
||||
else if ((state & SHCOLSTATE_TYPEMASK) == SHCOLSTATE_TYPE_DATE)
|
||||
vt = VT_DATE;
|
||||
else
|
||||
vt = VT_BSTR;
|
||||
}
|
||||
if (vt != VT_BSTR)
|
||||
VariantChangeType(pVar, pVar, 0, vt);
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
SH32_GetDetailsOfPKeyAsVariant(IShellFolder2 *pSF, PCUITEMID_CHILD pidl, const SHCOLUMNID *pscid, VARIANT *pVar, BOOL UseFsColMap)
|
||||
{
|
||||
// CFSFolder and CRegFolder uses the SHFSF_COL columns and can use the faster and better version,
|
||||
// everyone else must ask the folder to map the SCID to a column.
|
||||
VARTYPE vt = VT_EMPTY;
|
||||
HRESULT hr = UseFsColMap ? MapSCIDToShell32FsColumn(pscid, vt) : SHELL_MapSCIDToColumn(pSF, pscid);
|
||||
return SUCCEEDED(hr) ? SHELL_GetDetailsOfColumnAsVariant(pSF, pidl, hr, vt, pVar) : hr;
|
||||
}
|
||||
|
||||
HRESULT SHELL_CreateAbsolutePidl(IShellFolder *pSF, PCUIDLIST_RELATIVE pidlChild, PIDLIST_ABSOLUTE *ppPidl)
|
||||
{
|
||||
PIDLIST_ABSOLUTE pidlFolder;
|
||||
|
|
|
@ -1254,6 +1254,33 @@ LPITEMIDLIST WINAPI SHSimpleIDListFromPathAW(LPCVOID lpszPath)
|
|||
return SHSimpleIDListFromPathA (lpszPath);
|
||||
}
|
||||
|
||||
static HRESULT GetShellFolder2ItemDetailsExToBuffer(IShellFolder2 *psf2, LPCITEMIDLIST pidl,
|
||||
const SHCOLUMNID *pscid, void*buf, UINT cb)
|
||||
{
|
||||
VARIANT var;
|
||||
V_VT(&var) = VT_EMPTY;
|
||||
HRESULT hr = IShellFolder2_GetDetailsEx(psf2, pidl, pscid, &var);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = SHELL_VariantToBuffer(&var, buf, cb);
|
||||
VariantClear(&var);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT GetShellFolder1ItemDetailsExToBuffer(LPSHELLFOLDER psf, LPCITEMIDLIST pidl,
|
||||
const SHCOLUMNID *pscid, void*buf, UINT cb)
|
||||
{
|
||||
IShellFolder2 *psf2;
|
||||
HRESULT hr = IShellFolder_QueryInterface(psf, &IID_IShellFolder2, (void**)&psf2);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = GetShellFolder2ItemDetailsExToBuffer(psf2, pidl, pscid, buf, cb);
|
||||
IShellFolder2_Release(psf2);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* SHGetDataFromIDListA [SHELL32.247]
|
||||
*
|
||||
|
@ -1303,8 +1330,10 @@ HRESULT WINAPI SHGetDataFromIDListA(LPSHELLFOLDER psf, LPCITEMIDLIST pidl,
|
|||
pfd->cAlternateFileName[0] = '\0';
|
||||
return S_OK;
|
||||
|
||||
case SHGDFIL_NETRESOURCE:
|
||||
case SHGDFIL_DESCRIPTIONID:
|
||||
return SHGetDataFromIDListW(psf, pidl, nFormat, dest, len);
|
||||
|
||||
case SHGDFIL_NETRESOURCE:
|
||||
FIXME_(shell)("SHGDFIL %i stub\n", nFormat);
|
||||
break;
|
||||
|
||||
|
@ -1334,7 +1363,7 @@ HRESULT WINAPI SHGetDataFromIDListW(LPSHELLFOLDER psf, LPCITEMIDLIST pidl,
|
|||
|
||||
switch (nFormat)
|
||||
{
|
||||
case SHGDFIL_FINDDATA:
|
||||
case SHGDFIL_FINDDATA: /* FIXME: Ask the folder for PID_FINDDATA */
|
||||
pfd = dest;
|
||||
|
||||
if (_ILIsDrive(pidl))
|
||||
|
@ -1362,8 +1391,14 @@ HRESULT WINAPI SHGetDataFromIDListW(LPSHELLFOLDER psf, LPCITEMIDLIST pidl,
|
|||
pfd->cAlternateFileName[13] = 0;
|
||||
return S_OK;
|
||||
|
||||
case SHGDFIL_NETRESOURCE:
|
||||
case SHGDFIL_DESCRIPTIONID:
|
||||
{
|
||||
/* TODO: Use PKEY_DescriptionID when the propsys headers are ready */
|
||||
SHCOLUMNID scid = { FMTID_ShellDetails, PID_DESCRIPTIONID };
|
||||
return GetShellFolder1ItemDetailsExToBuffer(psf, pidl, &scid, dest, len);
|
||||
}
|
||||
|
||||
case SHGDFIL_NETRESOURCE:
|
||||
FIXME_(shell)("SHGDFIL %i stub\n", nFormat);
|
||||
break;
|
||||
|
||||
|
|
|
@ -216,6 +216,73 @@ LPWSTR SH_FormatFileSizeWithBytes(PULARGE_INTEGER lpQwSize, LPWSTR pszBuf, UINT
|
|||
HRESULT WINAPI DoRegisterServer(void);
|
||||
HRESULT WINAPI DoUnregisterServer(void);
|
||||
|
||||
/* Property system */
|
||||
static inline HRESULT
|
||||
SHELL_CreateVariantBufferEx(VARIANT *pVar, UINT cb, VARTYPE vt)
|
||||
{
|
||||
SAFEARRAY *pSA = SafeArrayCreateVector(vt, 0, cb);
|
||||
if (pSA)
|
||||
{
|
||||
V_VT(pVar) = VT_ARRAY | vt;
|
||||
V_ARRAY(pVar) = pSA;
|
||||
return S_OK;
|
||||
}
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
static inline HRESULT
|
||||
SHELL_CreateVariantBuffer(VARIANT *pVar, UINT cb)
|
||||
{
|
||||
return SHELL_CreateVariantBufferEx(pVar, cb, VT_UI1);
|
||||
}
|
||||
|
||||
static inline HRESULT
|
||||
SHELL_InitVariantFromBuffer(VARIANT *pVar, const void *pData, UINT cb)
|
||||
{
|
||||
HRESULT hr = SHELL_CreateVariantBuffer(pVar, cb);
|
||||
if (SUCCEEDED(hr))
|
||||
CopyMemory(V_ARRAY(pVar)->pvData, pData, cb);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static inline void*
|
||||
SHELL_GetSafeArrayDataPtr(const SAFEARRAY *pSA, SIZE_T *pcb)
|
||||
{
|
||||
if (pSA->cDims != 1)
|
||||
return NULL;
|
||||
LONG lob, upb;
|
||||
SafeArrayGetLBound((SAFEARRAY*)pSA, 1, &lob);
|
||||
SafeArrayGetUBound((SAFEARRAY*)pSA, 1, &upb);
|
||||
*pcb = (SIZE_T)(upb - lob) + 1;
|
||||
return pSA->pvData;
|
||||
}
|
||||
|
||||
static inline HRESULT
|
||||
SHELL_VariantToBuffer(VARIANT *pVar, void *pData, SIZE_T cb)
|
||||
{
|
||||
if (V_VT(pVar) != (VT_ARRAY | VT_UI1))
|
||||
return E_INVALIDARG;
|
||||
SIZE_T cbArr;
|
||||
void *pArrData = SHELL_GetSafeArrayDataPtr(V_ARRAY(pVar), &cbArr);
|
||||
if (!pArrData || cbArr < cb)
|
||||
return E_FAIL;
|
||||
CopyMemory(pData, pArrData, cb);
|
||||
return (cbArr > cb) ? S_FALSE : S_OK;
|
||||
}
|
||||
|
||||
static inline HRESULT
|
||||
SHELL_CreateSHDESCRIPTIONID(VARIANT *pVar, DWORD Id, const CLSID *pCLSID)
|
||||
{
|
||||
HRESULT hr = SHELL_CreateVariantBuffer(pVar, sizeof(SHDESCRIPTIONID));
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
SHDESCRIPTIONID *pDID = (SHDESCRIPTIONID*)V_ARRAY(pVar)->pvData;
|
||||
pDID->dwDescriptionId = Id;
|
||||
pDID->clsid = *pCLSID;
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
|
|
@ -474,6 +474,13 @@ template<class B, class R> static HRESULT SHILCombine(B base, PCUIDLIST_RELATIVE
|
|||
static inline bool StrIsNullOrEmpty(LPCSTR str) { return !str || !*str; }
|
||||
static inline bool StrIsNullOrEmpty(LPCWSTR str) { return !str || !*str; }
|
||||
|
||||
HRESULT inline SHSetStrRetEmpty(LPSTRRET pStrRet)
|
||||
{
|
||||
pStrRet->uType = STRRET_CSTR;
|
||||
pStrRet->cStr[0] = '\0';
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT inline SHSetStrRet(LPSTRRET pStrRet, LPCSTR pstrValue)
|
||||
{
|
||||
pStrRet->uType = STRRET_CSTR;
|
||||
|
|
Loading…
Reference in a new issue