mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-08-26 19:33:31 +00:00
[SHELL32] Implement CFolder[Item] getters/setters (#9173)
This commit is contained in:
@@ -81,7 +81,7 @@ HRESULT WINAPI CDropTargetHelper::Show(BOOL fShow)
|
||||
/*************************************************************************
|
||||
* SH32_SimulateDropWithSite [SHELL32.INTERNAL]
|
||||
*/
|
||||
static HRESULT SH32_SimulateDropWithSite(IDropTarget *pDT, IDataObject *pDO, DWORD grfKeyState, PPOINTL pPtl, LPDWORD pdwEffect, IUnknown *pSite)
|
||||
HRESULT SH32_SimulateDropWithSite(IDropTarget *pDT, IDataObject *pDO, DWORD grfKeyState, PPOINTL pPtl, LPDWORD pdwEffect, IUnknown *pSite)
|
||||
{
|
||||
CScopedSetObjectWithSite site(pDT, pSite);
|
||||
return SHSimulateDrop(pDT, pDO, grfKeyState, pPtl, pdwEffect);
|
||||
|
||||
@@ -54,4 +54,7 @@ BEGIN_COM_MAP(CDropTargetHelper)
|
||||
END_COM_MAP()
|
||||
};
|
||||
|
||||
HRESULT
|
||||
SH32_SimulateDropWithSite(IDropTarget *pDT, IDataObject *pDO, DWORD grfKeyState, PPOINTL pPtl, LPDWORD pdwEffect, IUnknown *pSite);
|
||||
|
||||
#endif /* _DRAGDROPHELPER_H_ */
|
||||
|
||||
+131
-24
@@ -6,10 +6,13 @@
|
||||
*/
|
||||
|
||||
#include "precomp.h"
|
||||
#include "prop.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
||||
|
||||
|
||||
EXTERN_C BOOL WINAPI Win32CreateDirectoryW(LPCWSTR path, LPSECURITY_ATTRIBUTES sec);
|
||||
|
||||
CFolder::CFolder()
|
||||
{
|
||||
}
|
||||
@@ -18,21 +21,19 @@ CFolder::~CFolder()
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT CFolder::Initialize(LPITEMIDLIST idlist)
|
||||
HRESULT CFolder::Initialize(LPCITEMIDLIST idlist)
|
||||
{
|
||||
m_idlist.Attach(ILClone(idlist));
|
||||
if (!m_idlist)
|
||||
return E_OUTOFMEMORY;
|
||||
return CShellDispatch_Constructor(IID_PPV_ARG(IShellDispatch, &m_Application));
|
||||
}
|
||||
|
||||
HRESULT CFolder::GetShellFolder(CComPtr<IShellFolder>& psfCurrent)
|
||||
{
|
||||
CComPtr<IShellFolder> psfDesktop;
|
||||
|
||||
HRESULT hr = SHGetDesktopFolder(&psfDesktop);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
return psfDesktop->BindToObject(m_idlist, NULL, IID_PPV_ARG(IShellFolder, &psfCurrent));
|
||||
HRESULT hr = SHBindToObject(NULL, GetAbsoluteIDList(), NULL, IID_PPV_ARG(IShellFolder, &psfCurrent));
|
||||
FAILED_UNEXPECTEDLY(hr);
|
||||
return hr;
|
||||
}
|
||||
|
||||
// *** Folder methods ***
|
||||
@@ -41,12 +42,9 @@ HRESULT STDMETHODCALLTYPE CFolder::get_Title(BSTR *pbs)
|
||||
if (!pbs)
|
||||
return E_POINTER;
|
||||
|
||||
WCHAR path[MAX_PATH+2] = {0};
|
||||
WCHAR path[MAX_PATH];
|
||||
HRESULT hr = ILGetDisplayNameExW(NULL, m_idlist, path, ILGDN_INFOLDER) ? S_OK : E_FAIL;
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
*pbs = SysAllocString(path);
|
||||
*pbs = SysAllocString(SUCCEEDED(hr) ? path : L"");
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -75,17 +73,23 @@ HRESULT STDMETHODCALLTYPE CFolder::get_Parent(IDispatch **ppid)
|
||||
|
||||
HRESULT STDMETHODCALLTYPE CFolder::get_ParentFolder(Folder **ppsf)
|
||||
{
|
||||
TRACE("(%p, %p)\n", this);
|
||||
TRACE("(%p, %p)\n", this, ppsf);
|
||||
|
||||
*ppsf = NULL;
|
||||
LPCITEMIDLIST pidlAbsSelf = GetAbsoluteIDList();
|
||||
if (ILIsEmpty(pidlAbsSelf))
|
||||
return S_FALSE;
|
||||
|
||||
return E_NOTIMPL;
|
||||
CComHeapPtr<ITEMIDLIST> pidlParent;
|
||||
if (FAILED(SHILCloneParent(pidlAbsSelf, &pidlParent)))
|
||||
return E_OUTOFMEMORY;
|
||||
return ShellObjectCreatorInit<CFolder>(static_cast<LPITEMIDLIST>(pidlParent), IID_PPV_ARG(Folder, ppsf));
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE CFolder::Items(FolderItems **ppid)
|
||||
{
|
||||
/* FolderItems_Constructor */
|
||||
return ShellObjectCreatorInit<CFolderItems>(static_cast<LPITEMIDLIST>(m_idlist), this, IID_PPV_ARG(FolderItems, ppid));
|
||||
return ShellObjectCreatorInit<CFolderItems>(GetAbsoluteIDList(), this, IID_PPV_ARG(FolderItems, ppid));
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE CFolder::ParseName(BSTR bName, FolderItem **ppid)
|
||||
@@ -97,42 +101,145 @@ HRESULT STDMETHODCALLTYPE CFolder::ParseName(BSTR bName, FolderItem **ppid)
|
||||
|
||||
CComPtr<IShellFolder> psfCurrent;
|
||||
HRESULT hr = GetShellFolder(psfCurrent);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
CComHeapPtr<ITEMIDLIST_RELATIVE> relativePidl;
|
||||
hr = psfCurrent->ParseDisplayName(NULL, NULL, bName, NULL, &relativePidl, NULL);
|
||||
if (!SUCCEEDED(hr))
|
||||
return S_FALSE;
|
||||
|
||||
CComHeapPtr<ITEMIDLIST> combined;
|
||||
combined.Attach(ILCombine(m_idlist, relativePidl));
|
||||
combined.Attach(ILCombine(GetAbsoluteIDList(), relativePidl));
|
||||
if (!combined)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
return ShellObjectCreatorInit<CFolderItem>(this, static_cast<LPITEMIDLIST>(combined), IID_PPV_ARG(FolderItem, ppid));
|
||||
CComHeapPtr<ITEMIDLIST> parentPidl;
|
||||
if (FAILED(hr = SHILCloneParent((LPCITEMIDLIST)combined, &parentPidl)))
|
||||
return hr;
|
||||
CComPtr<Folder> pParent; // The parent Folder of the thing we just parsed
|
||||
hr = ShellObjectCreatorInit<CFolder>(parentPidl, IID_PPV_ARG(Folder, &pParent));
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
return ShellObjectCreatorInit<CFolderItem>(pParent, static_cast<LPITEMIDLIST>(combined), IID_PPV_ARG(FolderItem, ppid));
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE CFolder::NewFolder(BSTR bName, VARIANT vOptions)
|
||||
{
|
||||
TRACE("(%p, %s, %s)\n", this, wine_dbgstr_w(bName), wine_dbgstr_variant(&vOptions));
|
||||
|
||||
// Note: MSDN says vOptions "is not currently used"
|
||||
CComPtr<IStorage> pStg, pStgNew;
|
||||
HRESULT hr = SHBindToObject(NULL, GetAbsoluteIDList(), NULL, IID_PPV_ARG(IStorage, &pStg));
|
||||
if (FAILED(hr))
|
||||
goto tryfs;//return hr;
|
||||
hr = pStg->CreateStorage(bName, STGM_FAILIFTHERE, 0, 0, &pStgNew);
|
||||
return (hr == STG_E_FILEALREADYEXISTS) ? S_OK : hr;
|
||||
|
||||
tryfs: // HACKFIX: Our CFSFolder does not yet support IStorage, try it directly
|
||||
LPCITEMIDLIST pidlAbsSelf = GetAbsoluteIDList();
|
||||
if (SHGetAttributes(NULL, pidlAbsSelf, SFGAO_FILESYSTEM) == SFGAO_FILESYSTEM)
|
||||
{
|
||||
CComHeapPtr<WCHAR> pszDirPath;
|
||||
if (SUCCEEDED(SHELL_DisplayNameOf(NULL, pidlAbsSelf, SHGDN_FORPARSING, &pszDirPath)))
|
||||
{
|
||||
DWORD cch = wcslen(pszDirPath) + 1 + wcslen(bName) + 1, attr;
|
||||
if (PWSTR pszPath = (PWSTR)SHAlloc(cch * sizeof(WCHAR)))
|
||||
{
|
||||
StringCchPrintfW(pszPath, cch, L"%s\\%s", &pszDirPath[0], bName);
|
||||
if (PathFileExistsAndAttributesW(pszPath, &attr))
|
||||
hr = (attr & FILE_ATTRIBUTE_DIRECTORY) ? S_OK : S_FALSE;
|
||||
else
|
||||
hr = Win32CreateDirectoryW(pszPath, NULL) ? S_OK : E_FAIL;
|
||||
SHFree(pszPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT GetUIObjectFromVariant(VARIANT &vItem, REFIID riid, void **ppv)
|
||||
{
|
||||
CComHeapPtr<ITEMIDLIST> pidlOneItem;
|
||||
if (SUCCEEDED(VariantToIdlist(&vItem, &pidlOneItem)))
|
||||
return SHELL_GetUIObjectOfAbsoluteItem(NULL, pidlOneItem, riid, ppv);
|
||||
|
||||
// TODO: CFolderItems array
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT CFolder::CopyMoveOperation(VARIANT &vItem, VARIANT vOptions, BOOL bCopy)
|
||||
{
|
||||
CComPtr<IShellFolder> psfCurrent;
|
||||
HRESULT hr = GetShellFolder(psfCurrent);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
CComPtr<IDropTarget> pDT;
|
||||
if (FAILED_UNEXPECTEDLY(hr = psfCurrent->CreateViewObject(GetHwnd(), IID_PPV_ARG(IDropTarget, &pDT))))
|
||||
return hr;
|
||||
|
||||
CComPtr<IDataObject> pDO;
|
||||
if (FAILED_UNEXPECTEDLY(hr = GetUIObjectFromVariant(vItem, IID_PPV_ARG(IDataObject, &pDO))))
|
||||
return hr;
|
||||
|
||||
if (SUCCEEDED(VariantChangeType(&vOptions, &vOptions, 0, VT_I4)))
|
||||
{
|
||||
UINT flags = V_I4(&vOptions) & ~(FOF_MULTIDESTFILES | FOF_WANTMAPPINGHANDLE);
|
||||
if (flags)
|
||||
{
|
||||
extern UINT g_cf_FileOpFlags;
|
||||
if (!g_cf_FileOpFlags)
|
||||
g_cf_FileOpFlags = RegisterClipboardFormatW(L"FileOpFlags");
|
||||
DataObj_SetDWORD(pDO, g_cf_FileOpFlags, flags);
|
||||
}
|
||||
}
|
||||
hr = SH32_SimulateDropWithSite(pDT, pDO, MK_LBUTTON | (bCopy ? MK_CONTROL : MK_SHIFT), NULL, NULL, GetSite());
|
||||
return SUCCEEDED(hr) ? S_OK : S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE CFolder::MoveHere(VARIANT vItem, VARIANT vOptions)
|
||||
{
|
||||
TRACE("(%p, %s, %s)\n", this, wine_dbgstr_variant(&vItem), wine_dbgstr_variant(&vOptions));
|
||||
return E_NOTIMPL;
|
||||
return CopyMoveOperation(vItem, vOptions, FALSE);
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE CFolder::CopyHere(VARIANT vItem, VARIANT vOptions)
|
||||
{
|
||||
TRACE("(%p, %s, %s)\n", this, wine_dbgstr_variant(&vItem), wine_dbgstr_variant(&vOptions));
|
||||
return E_NOTIMPL;
|
||||
return CopyMoveOperation(vItem, vOptions, TRUE);
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE CFolder::GetDetailsOf(VARIANT vItem, int iColumn, BSTR *pbs)
|
||||
{
|
||||
TRACE("(%p, %s, %i, %p)\n", this, wine_dbgstr_variant(&vItem), iColumn, pbs);
|
||||
return E_NOTIMPL;
|
||||
|
||||
CComPtr<IShellFolder> psf;
|
||||
HRESULT hr = GetShellFolder(psf);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
PCUITEMID_CHILD pidlItem = CFolderItem::GetLeafPidlRef(&vItem);
|
||||
if (pidlItem && iColumn == -1)
|
||||
{
|
||||
PWSTR pszTip = NULL;
|
||||
if (SUCCEEDED(hr = SHELL_QueryInfoTipAlloc(psf, QITIPF_DEFAULT, pidlItem, &pszTip)))
|
||||
{
|
||||
hr = SHELL_SysAllocString(pszTip, pbs);
|
||||
SHFree(pszTip);
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
VARIANT v;
|
||||
if (pbs && SUCCEEDED(SHELL_GetDetailsOfAsStringVariant(psf, pidlItem, iColumn, &v)))
|
||||
{
|
||||
*pbs = V_BSTR(&v);
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
return SHELL_SysAllocString(L"", pbs);
|
||||
}
|
||||
|
||||
|
||||
@@ -143,7 +250,7 @@ HRESULT STDMETHODCALLTYPE CFolder::get_Self(FolderItem **ppfi)
|
||||
if (!ppfi)
|
||||
return E_POINTER;
|
||||
|
||||
return ShellObjectCreatorInit<CFolderItem>(this, static_cast<LPITEMIDLIST>(m_idlist), IID_PPV_ARG(FolderItem, ppfi));
|
||||
return ShellObjectCreatorInit<CFolderItem>(this, GetAbsoluteIDList(), IID_PPV_ARG(FolderItem, ppfi));
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE CFolder::get_OfflineStatus(LONG *pul)
|
||||
|
||||
@@ -16,6 +16,7 @@ class CFolder:
|
||||
{
|
||||
private:
|
||||
HRESULT GetShellFolder(CComPtr<IShellFolder>& psfCurrent);
|
||||
HRESULT CopyMoveOperation(VARIANT &vItem, VARIANT vOptions, BOOL bCopy);
|
||||
|
||||
CComHeapPtr<ITEMIDLIST> m_idlist;
|
||||
CComPtr<IShellDispatch> m_Application;
|
||||
@@ -24,7 +25,10 @@ public:
|
||||
CFolder();
|
||||
~CFolder();
|
||||
|
||||
HRESULT Initialize(LPITEMIDLIST idlist);
|
||||
HRESULT Initialize(LPCITEMIDLIST idlist);
|
||||
LPCITEMIDLIST GetAbsoluteIDList() { return m_idlist; }
|
||||
HWND GetHwnd() { return NULL; }
|
||||
IUnknown* GetSite() { return NULL; }
|
||||
|
||||
// *** Folder methods ***
|
||||
STDMETHOD(get_Title)(BSTR *pbs) override;
|
||||
|
||||
@@ -89,7 +89,7 @@ CFolderItemVerbs::~CFolderItemVerbs()
|
||||
DestroyMenu(m_menu);
|
||||
}
|
||||
|
||||
HRESULT CFolderItemVerbs::Init(LPITEMIDLIST idlist)
|
||||
HRESULT CFolderItemVerbs::Init(LPCITEMIDLIST idlist)
|
||||
{
|
||||
HRESULT hr = SHELL_GetUIObjectOfAbsoluteItem(NULL, idlist, IID_PPV_ARG(IContextMenu, &m_contextmenu));
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
|
||||
@@ -67,7 +67,7 @@ public:
|
||||
CFolderItemVerbs();
|
||||
virtual ~CFolderItemVerbs();
|
||||
|
||||
HRESULT Init(LPITEMIDLIST idlist);
|
||||
HRESULT Init(LPCITEMIDLIST idlist);
|
||||
|
||||
// *** FolderItemVerbs methods ***
|
||||
STDMETHOD(get_Count)(LONG *plCount) override;
|
||||
@@ -83,6 +83,8 @@ BEGIN_COM_MAP(CFolderItemVerbs)
|
||||
COM_INTERFACE_ENTRY_IID(IID_FolderItemVerbs, FolderItemVerbs)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IDispatch, IDispatch)
|
||||
END_COM_MAP()
|
||||
|
||||
static HRESULT CreateInstance(CComPtr<CFolderItemVerbs> &objref) { return ShellObjectCreator(objref); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include "precomp.h"
|
||||
#include "prop.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
||||
|
||||
@@ -18,13 +19,67 @@ CFolderItem::~CFolderItem()
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT CFolderItem::Initialize(Folder* folder, LPITEMIDLIST idlist)
|
||||
HRESULT CFolderItem::Initialize(Folder* folder, LPCITEMIDLIST idlist)
|
||||
{
|
||||
m_idlist.Attach(ILClone(idlist));
|
||||
if (!m_idlist)
|
||||
return E_OUTOFMEMORY;
|
||||
m_Folder = folder;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
inline HRESULT CFolderItem::GetParentShellFolderAndItem(REFIID riid, void**ppv, PCUITEMID_CHILD &pidlLast)
|
||||
{
|
||||
return SHBindToParent(GetAbsoluteIDList(), riid, ppv, &pidlLast);
|
||||
}
|
||||
|
||||
LPCITEMIDLIST CFolderItem::GetInternalPidlRef(IUnknown *pUnk)
|
||||
{
|
||||
LPCITEMIDLIST pidl = NULL;
|
||||
FolderItem2 *pFI2;
|
||||
if (pUnk && SUCCEEDED(pUnk->QueryInterface(IID_PPV_ARG(FolderItem2, &pFI2))))
|
||||
{
|
||||
// This assumes we are the only implementer of CFolderItem (probably true)
|
||||
// but when we get IParentAndItem we can do this in a safer way
|
||||
pidl = static_cast<CFolderItem*>(pFI2)->m_idlist;
|
||||
pFI2->Release();
|
||||
}
|
||||
return pidl;
|
||||
}
|
||||
|
||||
LPCITEMIDLIST CFolderItem::GetInternalPidlRef(const VARIANT *pV)
|
||||
{
|
||||
if (!pV)
|
||||
return NULL;
|
||||
|
||||
if (V_VT(pV) == (VT_VARIANT | VT_BYREF) && V_VARIANTREF(pV))
|
||||
pV = V_VARIANTREF(pV);
|
||||
|
||||
switch (V_VT(pV))
|
||||
{
|
||||
case VT_DISPATCH | VT_BYREF:
|
||||
return V_DISPATCHREF(pV) ? GetInternalPidlRef(*V_DISPATCHREF(pV)) : NULL;
|
||||
case VT_DISPATCH:
|
||||
return GetInternalPidlRef(V_DISPATCH(pV));
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PCUITEMID_CHILD CFolderItem::GetLeafPidlRef(const VARIANT *pV)
|
||||
{
|
||||
return (PCUITEMID_CHILD)ILFindLastID(GetInternalPidlRef(pV));
|
||||
}
|
||||
|
||||
HRESULT CFolderItem::GetFindDataFromIDList(WIN32_FIND_DATA &wfd)
|
||||
{
|
||||
CComPtr<IShellFolder2> psf;
|
||||
PCUITEMID_CHILD pidlLeaf;
|
||||
HRESULT hr = GetParentShellFolderAndItem(IID_PPV_ARG(IShellFolder2, &psf), pidlLeaf);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
return SHGetDataFromIDListW(psf, pidlLeaf, SHGDFIL_FINDDATA, &wfd, sizeof(wfd));
|
||||
}
|
||||
|
||||
// *** FolderItem methods ***
|
||||
HRESULT STDMETHODCALLTYPE CFolderItem::get_Application(IDispatch **ppid)
|
||||
{
|
||||
@@ -35,12 +90,10 @@ HRESULT STDMETHODCALLTYPE CFolderItem::get_Application(IDispatch **ppid)
|
||||
HRESULT STDMETHODCALLTYPE CFolderItem::get_Parent(IDispatch **ppid)
|
||||
{
|
||||
TRACE("(%p, %p)\n", this, ppid);
|
||||
if (ppid)
|
||||
{
|
||||
*ppid = m_Folder;
|
||||
(*ppid)->AddRef();
|
||||
}
|
||||
return E_NOTIMPL;
|
||||
|
||||
if (!ppid)
|
||||
return E_INVALIDARG;
|
||||
return m_Folder->QueryInterface(IID_PPV_ARG(IDispatch, ppid));
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE CFolderItem::get_Name(BSTR *pbs)
|
||||
@@ -49,9 +102,9 @@ HRESULT STDMETHODCALLTYPE CFolderItem::get_Name(BSTR *pbs)
|
||||
|
||||
*pbs = NULL;
|
||||
|
||||
CComPtr<IShellFolder2> Parent;
|
||||
LPCITEMIDLIST last_part;
|
||||
HRESULT hr = SHBindToParent(m_idlist, IID_PPV_ARG(IShellFolder2, &Parent), &last_part);
|
||||
CComPtr<IShellFolder> Parent;
|
||||
PCUITEMID_CHILD last_part;
|
||||
HRESULT hr = GetParentShellFolderAndItem(IID_PPV_ARG(IShellFolder, &Parent), last_part);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
@@ -66,7 +119,25 @@ HRESULT STDMETHODCALLTYPE CFolderItem::get_Name(BSTR *pbs)
|
||||
HRESULT STDMETHODCALLTYPE CFolderItem::put_Name(BSTR bs)
|
||||
{
|
||||
TRACE("(%p, %s)\n", this, wine_dbgstr_w(bs));
|
||||
return E_NOTIMPL;
|
||||
|
||||
CComPtr<IShellFolder> psf;
|
||||
PCUITEMID_CHILD pidlLeaf;
|
||||
HRESULT hr = GetParentShellFolderAndItem(IID_PPV_ARG(IShellFolder, &psf), pidlLeaf);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
LPITEMIDLIST pidlNew;
|
||||
if (SUCCEEDED(hr = psf->SetNameOf(GetHwnd(), pidlLeaf, bs, SHGDN_INFOLDER, &pidlNew)) && pidlNew)
|
||||
{
|
||||
LPITEMIDLIST pidlClone = ILClone(m_idlist);
|
||||
ILRemoveLastID(pidlClone);
|
||||
if (pidlClone && SUCCEEDED(SHILAppend(pidlNew, &pidlClone)))
|
||||
{
|
||||
m_idlist.Free();
|
||||
m_idlist.Attach(pidlClone);
|
||||
}
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE CFolderItem::get_Path(BSTR *pbs)
|
||||
@@ -93,38 +164,54 @@ HRESULT STDMETHODCALLTYPE CFolderItem::get_GetLink(IDispatch **ppid)
|
||||
|
||||
HRESULT STDMETHODCALLTYPE CFolderItem::get_GetFolder(IDispatch **ppid)
|
||||
{
|
||||
TRACE("(%p, %p)\n", this, ppid);
|
||||
return E_NOTIMPL;
|
||||
return ShellObjectCreatorInit<CFolder>(const_cast<LPITEMIDLIST>(GetAbsoluteIDList()), IID_PPV_ARG(IDispatch, ppid));
|
||||
}
|
||||
|
||||
HRESULT CFolderItem::HasAttribute(DWORD sfgaof, VARIANT_BOOL *pB)
|
||||
{
|
||||
*pB = SHGetAttributes(NULL, GetAbsoluteIDList(), sfgaof) ? VARIANT_TRUE : VARIANT_FALSE;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE CFolderItem::get_IsLink(VARIANT_BOOL *pb)
|
||||
{
|
||||
TRACE("(%p, %p)\n", this, pb);
|
||||
return E_NOTIMPL;
|
||||
return HasAttribute(SFGAO_LINK, pb);
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE CFolderItem::get_IsFolder(VARIANT_BOOL *pb)
|
||||
{
|
||||
TRACE("(%p, %p)\n", this, pb);
|
||||
return E_NOTIMPL;
|
||||
return HasAttribute(SFGAO_FOLDER, pb);
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE CFolderItem::get_IsFileSystem(VARIANT_BOOL *pb)
|
||||
{
|
||||
TRACE("(%p, %p)\n", this, pb);
|
||||
return E_NOTIMPL;
|
||||
return HasAttribute(SFGAO_FILESYSTEM, pb);
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE CFolderItem::get_IsBrowsable(VARIANT_BOOL *pb)
|
||||
{
|
||||
TRACE("(%p, %p)\n", this, pb);
|
||||
return E_NOTIMPL;
|
||||
return HasAttribute(SFGAO_BROWSABLE, pb);
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE CFolderItem::get_ModifyDate(DATE *pdt)
|
||||
{
|
||||
TRACE("(%p, %p)\n", this, pdt);
|
||||
return E_NOTIMPL;
|
||||
|
||||
WIN32_FIND_DATA wfd;
|
||||
if (SUCCEEDED(GetFindDataFromIDList(wfd)))
|
||||
{
|
||||
FILETIME ft;
|
||||
FileTimeToLocalFileTime(&wfd.ftLastWriteTime, &ft);
|
||||
WORD dd, dt;
|
||||
if (FileTimeToDosDateTime(&ft, &dd, &dt) && DosDateTimeToVariantTime(dd, dt, pdt))
|
||||
return S_OK;
|
||||
}
|
||||
*pdt = 0;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE CFolderItem::put_ModifyDate(DATE dt)
|
||||
@@ -136,37 +223,98 @@ HRESULT STDMETHODCALLTYPE CFolderItem::put_ModifyDate(DATE dt)
|
||||
HRESULT STDMETHODCALLTYPE CFolderItem::get_Size(LONG *pul)
|
||||
{
|
||||
TRACE("(%p, %p)\n", this, pul);
|
||||
return E_NOTIMPL;
|
||||
|
||||
WIN32_FIND_DATA wfd;
|
||||
if (SUCCEEDED(GetFindDataFromIDList(wfd)))
|
||||
{
|
||||
*pul = wfd.nFileSizeLow;
|
||||
return S_OK;
|
||||
}
|
||||
*pul = 0;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE CFolderItem::get_Type(BSTR *pbs)
|
||||
{
|
||||
TRACE("(%p, %p)\n", this, pbs);
|
||||
return E_NOTIMPL;
|
||||
|
||||
VARIANT v;
|
||||
V_VT(&v) = VT_EMPTY;
|
||||
if (SUCCEEDED(GetExtendedProperty(PKEY_ItemTypeText, &v)))
|
||||
{
|
||||
if (SUCCEEDED(VariantChangeType(&v, &v, 0, VT_BSTR)))
|
||||
{
|
||||
*pbs = V_BSTR(&v);
|
||||
return S_OK;
|
||||
}
|
||||
VariantClear(&v);
|
||||
}
|
||||
HRESULT hr = SHELL_SysAllocString(L"", pbs);
|
||||
return hr == S_OK ? S_FALSE : hr;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE CFolderItem::Verbs(FolderItemVerbs **ppfic)
|
||||
{
|
||||
if (!ppfic)
|
||||
return E_POINTER;
|
||||
CFolderItemVerbs* verbs = new CComObject<CFolderItemVerbs>();
|
||||
HRESULT hr = verbs->Init(m_idlist);
|
||||
|
||||
CComPtr<CFolderItemVerbs> pVerbs;
|
||||
HRESULT hr = CFolderItemVerbs::CreateInstance(pVerbs);
|
||||
if (SUCCEEDED(hr))
|
||||
hr = pVerbs->Init(GetAbsoluteIDList());
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
{
|
||||
delete verbs;
|
||||
return hr;
|
||||
}
|
||||
verbs->AddRef();
|
||||
*ppfic = verbs;
|
||||
|
||||
*ppfic = pVerbs.Detach();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE CFolderItem::InvokeVerb(VARIANT vVerb)
|
||||
{
|
||||
TRACE("(%p, %s)\n", this, wine_dbgstr_variant(&vVerb));
|
||||
return E_NOTIMPL;
|
||||
VARIANT empty;
|
||||
V_VT(&empty) = VT_EMPTY;
|
||||
return InvokeVerbEx(vVerb, empty);
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE CFolderItem::InvokeVerbEx(VARIANT vVerb, VARIANT vArgs)
|
||||
{
|
||||
TRACE("(%p, %s)\n", this, wine_dbgstr_variant(&vVerb));
|
||||
|
||||
SHELLEXECUTEINFOW sei;
|
||||
sei.cbSize = sizeof(sei);
|
||||
sei.fMask = SEE_MASK_INVOKEIDLIST | SEE_MASK_FLAG_NO_UI;
|
||||
sei.hwnd = GetHwnd();
|
||||
sei.lpVerb = V_VT(&vVerb) == VT_BSTR ? V_BSTR(&vVerb) : NULL;
|
||||
sei.lpFile = NULL;
|
||||
sei.lpParameters = V_VT(&vArgs) == VT_BSTR ? V_BSTR(&vArgs) : NULL;
|
||||
sei.lpDirectory = NULL;
|
||||
sei.nShow = SW_SHOW;
|
||||
sei.lpIDList = const_cast<LPITEMIDLIST>(GetAbsoluteIDList());
|
||||
ShellExecuteExW(&sei);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CFolderItem::GetExtendedProperty(REFPROPERTYKEY pkey, VARIANT *pv)
|
||||
{
|
||||
CComPtr<IShellFolder2> psf;
|
||||
PCUITEMID_CHILD pidlLeaf;
|
||||
HRESULT hr = GetParentShellFolderAndItem(IID_PPV_ARG(IShellFolder2, &psf), pidlLeaf);
|
||||
return FAILED(hr) ? hr : psf->GetDetailsEx(pidlLeaf, reinterpret_cast<const SHCOLUMNID*>(&pkey), pv);
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE CFolderItem::ExtendedProperty(BSTR bsPropName, VARIANT *pv)
|
||||
{
|
||||
if (!pv)
|
||||
return E_INVALIDARG;
|
||||
|
||||
PROPERTYKEY pkeybuf;
|
||||
const PROPERTYKEY *pPK = SHELL_GetPropertyKeyFromString(bsPropName, &pkeybuf);
|
||||
if (pPK && GetExtendedProperty(*pPK, pv) == S_OK)
|
||||
return S_OK;
|
||||
|
||||
V_VT(pv) = VT_EMPTY;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
|
||||
CFolderItems::CFolderItems()
|
||||
@@ -178,11 +326,13 @@ CFolderItems::~CFolderItems()
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT CFolderItems::Initialize(LPITEMIDLIST idlist, Folder* parent)
|
||||
HRESULT CFolderItems::Initialize(LPCITEMIDLIST idlist, Folder* parent)
|
||||
{
|
||||
CComPtr<IShellFolder> psfDesktop, psfTarget;
|
||||
|
||||
m_idlist.Attach(ILClone(idlist));
|
||||
if (!m_idlist)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
HRESULT hr = SHGetDesktopFolder(&psfDesktop);
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
|
||||
@@ -12,17 +12,29 @@
|
||||
class CFolderItem:
|
||||
public CComCoClass<CFolderItem>,
|
||||
public CComObjectRootEx<CComMultiThreadModelNoCS>,
|
||||
public IDispatchImpl<FolderItem, &IID_FolderItem>
|
||||
public IDispatchImpl<FolderItem2, &IID_FolderItem2>
|
||||
{
|
||||
private:
|
||||
CComHeapPtr<ITEMIDLIST> m_idlist;
|
||||
CComPtr<Folder> m_Folder;
|
||||
|
||||
inline HRESULT GetParentShellFolderAndItem(REFIID riid, void**ppv, PCUITEMID_CHILD &pidlLast);
|
||||
|
||||
static LPCITEMIDLIST GetInternalPidlRef(IUnknown *pUnk);
|
||||
static LPCITEMIDLIST GetInternalPidlRef(const VARIANT *pV);
|
||||
|
||||
public:
|
||||
CFolderItem();
|
||||
~CFolderItem();
|
||||
|
||||
HRESULT Initialize(Folder* folder, LPITEMIDLIST idlist);
|
||||
HRESULT Initialize(Folder* folder, LPCITEMIDLIST idlist);
|
||||
LPCITEMIDLIST GetAbsoluteIDList() { return m_idlist; }
|
||||
HWND GetHwnd() { return NULL; }
|
||||
HRESULT GetFindDataFromIDList(WIN32_FIND_DATA &wfd);
|
||||
HRESULT HasAttribute(DWORD sfgaof, VARIANT_BOOL *pB);
|
||||
HRESULT GetExtendedProperty(REFPROPERTYKEY pkey, VARIANT *pv);
|
||||
|
||||
static PCUITEMID_CHILD GetLeafPidlRef(const VARIANT *pV);
|
||||
|
||||
// *** FolderItem methods ***
|
||||
STDMETHOD(get_Application)(IDispatch **ppid) override;
|
||||
@@ -43,12 +55,16 @@ public:
|
||||
STDMETHOD(Verbs)(FolderItemVerbs **ppfic) override;
|
||||
STDMETHOD(InvokeVerb)(VARIANT vVerb) override;
|
||||
|
||||
// *** FolderItem2 methods ***
|
||||
STDMETHOD(InvokeVerbEx)(VARIANT vVerb, VARIANT vArgs) override;
|
||||
STDMETHOD(ExtendedProperty)(BSTR bsPropName, VARIANT *pv) override;
|
||||
|
||||
DECLARE_NOT_AGGREGATABLE(CFolderItem)
|
||||
DECLARE_PROTECT_FINAL_CONSTRUCT()
|
||||
|
||||
BEGIN_COM_MAP(CFolderItem)
|
||||
COM_INTERFACE_ENTRY_IID(IID_FolderItem, FolderItem)
|
||||
COM_INTERFACE_ENTRY_IID(IID_FolderItem2, FolderItem2)
|
||||
COM_INTERFACE_ENTRY_IID(IID_IDispatch, IDispatch)
|
||||
END_COM_MAP()
|
||||
};
|
||||
@@ -69,7 +85,7 @@ public:
|
||||
~CFolderItems();
|
||||
|
||||
// Please note: CFolderItems takes ownership of idlist.
|
||||
HRESULT Initialize(LPITEMIDLIST idlist, Folder* parent);
|
||||
HRESULT Initialize(LPCITEMIDLIST idlist, Folder* parent);
|
||||
|
||||
// *** FolderItems methods ***
|
||||
STDMETHOD(get_Count)(long *plCount) override;
|
||||
|
||||
@@ -63,6 +63,7 @@ list(APPEND SOURCE
|
||||
droptargets/CexeDropHandler.cpp
|
||||
droptargets/CFSDropTarget.cpp
|
||||
droptargets/CRecyclerDropTarget.cpp
|
||||
prop.cpp
|
||||
shldataobject.cpp
|
||||
shlexec.cpp
|
||||
shlfileop.cpp
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
*/
|
||||
|
||||
#include "precomp.h"
|
||||
#include "prop.h"
|
||||
#include "winsvc.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
||||
@@ -61,20 +62,6 @@ HRESULT STDMETHODCALLTYPE CShellDispatch::get_Parent(IDispatch **ppid)
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT VariantToIdlist(VARIANT* var, LPITEMIDLIST* idlist)
|
||||
{
|
||||
HRESULT hr = E_FAIL;
|
||||
if(V_VT(var) == VT_I4)
|
||||
{
|
||||
hr = SHGetSpecialFolderLocation(NULL, V_I4(var), idlist);
|
||||
}
|
||||
else if(V_VT(var) == VT_BSTR)
|
||||
{
|
||||
hr = SHILCreateFromPathW(V_BSTR(var), idlist, NULL);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE CShellDispatch::NameSpace(VARIANT vDir, Folder **ppsdf)
|
||||
{
|
||||
TRACE("(%p, %s, %p)\n", this, debugstr_variant(&vDir), ppsdf);
|
||||
@@ -336,6 +323,27 @@ HRESULT STDMETHODCALLTYPE CShellDispatch::GetSystemInformation(BSTR name, VARIAN
|
||||
V_UI4(ret) = si.wProcessorArchitecture;
|
||||
return S_OK;
|
||||
}
|
||||
else if (!lstrcmpiW(name, L"ProcessorSpeed"))
|
||||
{
|
||||
DWORD cb = sizeof(DWORD);
|
||||
V_VT(ret) = VT_EMPTY;
|
||||
if (RegGetValueW(HKEY_LOCAL_MACHINE, L"Hardware\\Description\\System\\CentralProcessor\\0",
|
||||
L"~Mhz", RRF_RT_REG_DWORD, NULL, &V_UI4(ret), &cb))
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
V_VT(ret) = VT_I4;
|
||||
return S_OK;
|
||||
}
|
||||
else if (!lstrcmpiW(name, L"PhysicalMemoryInstalled"))
|
||||
{
|
||||
MEMORYSTATUSEX mems;
|
||||
mems.dwLength = sizeof(mems);
|
||||
GlobalMemoryStatusEx(&mems);
|
||||
V_VT(ret) = VT_UI8;
|
||||
V_UI8(ret) = mems.ullTotalPhys;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
UINT os = 0;
|
||||
if (!lstrcmpiW(name, L"IsOS_Professional"))
|
||||
@@ -538,7 +546,7 @@ HRESULT STDMETHODCALLTYPE CShellDispatch::GetSetting(LONG setting, VARIANT_BOOL
|
||||
{
|
||||
TRACE("(%p, %lu, %p)\n", this, setting, result);
|
||||
|
||||
int flag = -1;
|
||||
int flag = 0;
|
||||
SHELLSTATE ss = { };
|
||||
SHGetSetSettings(&ss, setting, FALSE);
|
||||
switch (setting)
|
||||
@@ -552,14 +560,10 @@ HRESULT STDMETHODCALLTYPE CShellDispatch::GetSetting(LONG setting, VARIANT_BOOL
|
||||
case SSF_SEPPROCESS: flag = ss.fSepProcess; break;
|
||||
case SSF_STARTPANELON: flag = ss.fStartPanelOn; break;
|
||||
case SSF_SERVERADMINUI: flag = IsOS(OS_SERVERADMINUI); break;
|
||||
default: *result = VARIANT_FALSE; return S_FALSE;
|
||||
}
|
||||
if (flag >= 0)
|
||||
{
|
||||
*result = flag ? VARIANT_TRUE : VARIANT_FALSE;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return S_FALSE;
|
||||
*result = flag ? VARIANT_TRUE : VARIANT_FALSE;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -70,13 +70,22 @@ static void GetDefaultCopyMoveEffect()
|
||||
// FIXME: When the source is on a different volume than the target, change default from move to copy
|
||||
}
|
||||
|
||||
UINT g_cf_FileOpFlags = 0;
|
||||
|
||||
static inline DWORD GetDefaultFileOpFlags(IDataObject *pDO, DWORD fDefault = FOF_ALLOWUNDO | FOF_NOCONFIRMMKDIR)
|
||||
{
|
||||
if (!g_cf_FileOpFlags)
|
||||
g_cf_FileOpFlags = RegisterClipboardFormatW(L"FileOpFlags"); // github.com/dotnet/winforms/issues/5884?timeline_page=1
|
||||
return DataObj_GetDWORD(pDO, g_cf_FileOpFlags, fDefault);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* CFSDropTarget::_CopyItems
|
||||
*
|
||||
* copies or moves items to this folder
|
||||
*/
|
||||
HRESULT CFSDropTarget::_CopyItems(IShellFolder * pSFFrom, UINT cidl,
|
||||
LPCITEMIDLIST * apidl, BOOL bCopy)
|
||||
HRESULT CFSDropTarget::_CopyItems(IDataObject *pDO, IShellFolder * pSFFrom,
|
||||
UINT cidl, LPCITEMIDLIST * apidl, BOOL bCopy)
|
||||
{
|
||||
HRESULT ret;
|
||||
WCHAR wszDstPath[MAX_PATH + 1] = {0};
|
||||
@@ -128,7 +137,7 @@ HRESULT CFSDropTarget::_CopyItems(IShellFolder * pSFFrom, UINT cidl,
|
||||
fop.wFunc = bCopy ? FO_COPY : FO_MOVE;
|
||||
fop.pFrom = pwszSrcPathsList;
|
||||
fop.pTo = wszDstPath;
|
||||
fop.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMMKDIR;
|
||||
fop.fFlags = GetDefaultFileOpFlags(pDO);
|
||||
if (bRenameOnCollision)
|
||||
fop.fFlags |= FOF_RENAMEONCOLLISION;
|
||||
|
||||
@@ -725,7 +734,7 @@ HRESULT CFSDropTarget::_DoDrop(IDataObject *pDataObject,
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = _CopyItems(psfFrom, lpcida->cidl, (LPCITEMIDLIST*)apidl, bCopy);
|
||||
hr = _CopyItems(pDataObject, psfFrom, lpcida->cidl, (LPCITEMIDLIST*)apidl, bCopy);
|
||||
}
|
||||
|
||||
SHFree(pidl);
|
||||
@@ -760,7 +769,7 @@ HRESULT CFSDropTarget::_DoDrop(IDataObject *pDataObject,
|
||||
op.pTo = wszTargetPath;
|
||||
op.hwnd = m_hwndSite;
|
||||
op.wFunc = bCopy ? FO_COPY : FO_MOVE;
|
||||
op.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMMKDIR;
|
||||
op.fFlags = GetDefaultFileOpFlags(pDataObject);
|
||||
int res = SHFileOperationW(&op);
|
||||
if (res)
|
||||
{
|
||||
|
||||
@@ -43,7 +43,7 @@ class CFSDropTarget :
|
||||
|
||||
BOOL _QueryDrop (DWORD dwKeyState, LPDWORD pdwEffect);
|
||||
HRESULT _DoDrop(IDataObject *pDataObject, DWORD dwKeyState, POINTL pt, DWORD *pdwEffect);
|
||||
HRESULT _CopyItems(IShellFolder *pSFFrom, UINT cidl, LPCITEMIDLIST *apidl, BOOL bCopy);
|
||||
HRESULT _CopyItems(IDataObject *pDO, IShellFolder *pSFFrom, UINT cidl, LPCITEMIDLIST *apidl, BOOL bCopy);
|
||||
BOOL _GetUniqueFileName(LPCWSTR pwszBasePath, LPCWSTR pwszExt, LPWSTR pwszTarget, BOOL bShortcut);
|
||||
static DWORD WINAPI _DoDropThreadProc(LPVOID lpParameter);
|
||||
HRESULT _GetEffectFromMenu(IDataObject *pDataObject, POINTL pt, DWORD *pdwEffect, DWORD dwAvailableEffects);
|
||||
|
||||
@@ -1683,7 +1683,7 @@ HRESULT WINAPI CFSFolder::GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID *p
|
||||
switch (pscid->pid)
|
||||
{
|
||||
case PID_STG_NAME: // Handled directly here for faster performance
|
||||
return SHELL_GetDetailsOfAsStringVariant(this, pidl, SHFSF_COL_NAME, pv);
|
||||
return SHELL_GetDetailsOfAsStringVariant(static_cast<IShellFolder2*>(this), pidl, SHFSF_COL_NAME, pv);
|
||||
case PID_STG_SIZE:
|
||||
V_VT(pv) = VT_UI4;
|
||||
V_UI4(pv) = _ILGetFileSize(pidl, NULL, 0);
|
||||
|
||||
@@ -311,6 +311,8 @@ HRESULT DataObject_GetHIDACount(IDataObject *pdo);
|
||||
PIDLIST_ABSOLUTE SHELL_CIDA_ILCloneFull(_In_ const CIDA *pCIDA, _In_ UINT Index);
|
||||
PIDLIST_ABSOLUTE SHELL_DataObject_ILCloneFullItem(_In_ IDataObject *pDO, _In_ UINT Index);
|
||||
HRESULT SHELL_CloneDataObject(_In_ IDataObject *pDO, _Out_ IDataObject **ppDO);
|
||||
DWORD DataObj_GetDWORD(IDataObject *pdtobj, UINT cf, DWORD dwDefault);
|
||||
HRESULT DataObj_SetDWORD(IDataObject *pdtobj, UINT cf, DWORD dwValue);
|
||||
|
||||
EXTERN_C HRESULT
|
||||
IUnknown_InitializeCommand(
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* PROJECT: shell32
|
||||
* LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+)
|
||||
* PURPOSE: [PROP]VARIANT functions
|
||||
* COPYRIGHT: Copyright 2026 Whindmar Saksit <[email protected]>
|
||||
*/
|
||||
|
||||
#define SHELL32_PROP_IMPL
|
||||
#include "precomp.h"
|
||||
#include "prop.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(shell_prop);
|
||||
|
||||
static const struct SHELL32PKEYMAP
|
||||
{
|
||||
PCWSTR pszLegacyName;
|
||||
const PROPERTYKEY *pkey;
|
||||
} g_PkMap[] =
|
||||
{
|
||||
// learn.microsoft.com/en-us/windows/win32/api/propsys/nf-propsys-psgetpropertydescriptionbyname
|
||||
#define MKSH32PKEYMAP(sysname, legacyname, pkey) { (L##legacyname), &(pkey) },
|
||||
MKSH32PKEYMAP(?, "Name", PKEYSHELL32_Name)
|
||||
MKSH32PKEYMAP("System.ItemTypeText", "Type", PKEY_ItemTypeText)
|
||||
MKSH32PKEYMAP("System.Size", "Size", PKEY_Size)
|
||||
MKSH32PKEYMAP("System.FileAttributes", "Attributes", PKEY_FileAttributes)
|
||||
MKSH32PKEYMAP("System.DateModified", "Write", PKEY_DateModified)
|
||||
MKSH32PKEYMAP("System.Comment", "DocComments", PKEYSHELL32_Comments)
|
||||
};
|
||||
|
||||
static const PROPERTYKEY*
|
||||
SHELL_GetPropertyKeyFromLegacyName(_In_ PCWSTR pszString)
|
||||
{
|
||||
for (SIZE_T i = 0; i < _countof(g_PkMap); ++i)
|
||||
{
|
||||
if (!_wcsicmp(g_PkMap[i].pszLegacyName, pszString))
|
||||
return g_PkMap[i].pkey;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if /*TODO*/0 && (NTDDI_VERSION >= NTDDI_VISTA)
|
||||
#define SHELL_PropertyKeyFromPropertyKeyString PSPropertyKeyFromString
|
||||
#else
|
||||
static HRESULT
|
||||
SHELL_PropertyKeyFromPropertyKeyString(_In_ PCWSTR pszString, _Out_ PROPERTYKEY *pkey)
|
||||
{
|
||||
if (GUIDFromStringW(pszString, &pkey->fmtid))
|
||||
{
|
||||
for (pszString += 38; *pszString == ',' || *pszString == ' ';)
|
||||
++pszString;
|
||||
pkey->pid = StrToInt(pszString);
|
||||
if (pkey->pid)
|
||||
return S_OK;
|
||||
}
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
#endif
|
||||
|
||||
const PROPERTYKEY*
|
||||
SHELL_GetPropertyKeyFromString(_In_ PCWSTR pszString, _Out_ PROPERTYKEY *pkey)
|
||||
{
|
||||
if (SUCCEEDED(SHELL_PropertyKeyFromPropertyKeyString(pszString, pkey)))
|
||||
return pkey;
|
||||
return SHELL_GetPropertyKeyFromLegacyName(pszString);
|
||||
}
|
||||
|
||||
HRESULT
|
||||
VariantToIdlist(_In_ VARIANT *pV, _Out_ LPITEMIDLIST *ppidl)
|
||||
{
|
||||
HRESULT hr = E_FAIL;
|
||||
if (V_VT(pV) == VT_I4)
|
||||
{
|
||||
hr = SHGetSpecialFolderLocation(NULL, V_I4(pV), ppidl);
|
||||
}
|
||||
else if (V_VT(pV) == VT_BSTR)
|
||||
{
|
||||
hr = SHILCreateFromPathW(V_BSTR(pV), ppidl, NULL);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* PROJECT: shell32
|
||||
* LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+)
|
||||
* PURPOSE: [PROP]VARIANT header
|
||||
* COPYRIGHT: Copyright 2026 Whindmar Saksit <[email protected]>
|
||||
*/
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
#define SHELL32_NOPROPSYSLIB // PropSys does not yet have all the PKEY_'s we need
|
||||
|
||||
#ifdef SHELL32_NOPROPSYSLIB
|
||||
#ifdef SHELL32_PROP_IMPL
|
||||
#ifndef PSGUID_SUMMARYINFORMATION
|
||||
#define PSGUID_SUMMARYINFORMATION { 0xf29f85e0L, 0x4ff9, 0x1068, 0xab, 0x91, 0x08, 0x00, 0x2b, 0x27, 0xb3, 0xd9 }
|
||||
#endif
|
||||
#define DEFINE_SHELL32PROPERTYKEY(name, psguid, pid) \
|
||||
EXTERN_C const PROPERTYKEY DECLSPEC_SELECTANY name = { psguid, pid }
|
||||
#else
|
||||
#define DEFINE_SHELL32PROPERTYKEY(name, psguid, pid) EXTERN_C const PROPERTYKEY name
|
||||
#endif // SHELL32_PROP_IMPL
|
||||
|
||||
DEFINE_SHELL32PROPERTYKEY(PKEY_Size, PSGUID_STORAGE, PID_STG_SIZE);
|
||||
DEFINE_SHELL32PROPERTYKEY(PKEY_FileAttributes, PSGUID_STORAGE, PID_STG_ATTRIBUTES);
|
||||
DEFINE_SHELL32PROPERTYKEY(PKEY_DateModified, PSGUID_STORAGE, PID_STG_WRITETIME);
|
||||
DEFINE_SHELL32PROPERTYKEY(PKEY_ItemTypeText, PSGUID_STORAGE, PID_STG_STORAGETYPE);
|
||||
DEFINE_SHELL32PROPERTYKEY(PKEYSHELL32_Name, PSGUID_STORAGE, PID_STG_NAME);
|
||||
DEFINE_SHELL32PROPERTYKEY(PKEYSHELL32_Comments, PSGUID_SUMMARYINFORMATION, PIDSI_COMMENTS);
|
||||
|
||||
#endif // SHELL32_NOPROPSYSLIB
|
||||
|
||||
const PROPERTYKEY*
|
||||
SHELL_GetPropertyKeyFromString(_In_ PCWSTR pszString, _Out_ PROPERTYKEY *pkey);
|
||||
|
||||
HRESULT
|
||||
VariantToIdlist(_In_ VARIANT *pV, _Out_ LPITEMIDLIST *ppidl);
|
||||
@@ -106,12 +106,17 @@ MakeSCID(SHCOLUMNID &scid, REFCLSID fmtid, UINT pid)
|
||||
HRESULT
|
||||
SHELL_MapSCIDToColumn(IShellFolder2 *pSF, const SHCOLUMNID *pscid);
|
||||
HRESULT
|
||||
SHELL_GetDetailsOfAsStringVariant(IShellFolder *pSF, PCUITEMID_CHILD pidl, UINT Column, VARIANT *pVar);
|
||||
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_QueryInfoTipAlloc(_In_ IShellFolder* pSF, _In_ DWORD dwFlags, _In_ LPCITEMIDLIST pidl, _Out_ PWSTR *ppTip);
|
||||
|
||||
HRESULT
|
||||
SHELL_CreateAbsolutePidl(IShellFolder *pSF, PCUIDLIST_RELATIVE pidlChild, PIDLIST_ABSOLUTE *ppPidl);
|
||||
|
||||
|
||||
@@ -142,3 +142,20 @@ HRESULT SHELL_CloneDataObject(_In_ IDataObject *pDO, _Out_ IDataObject **ppDO)
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
static inline HRESULT DataObj_GetDWORD(IDataObject *pdtobj, UINT cf, DWORD *pdwOut)
|
||||
{
|
||||
// learn.microsoft.com/en-us/windows/win32/shell/dataobject
|
||||
return DataObject_GetData(pdtobj, (CLIPFORMAT)cf, pdwOut, sizeof(*pdwOut));
|
||||
}
|
||||
|
||||
DWORD DataObj_GetDWORD(IDataObject *pdtobj, UINT cf, DWORD dwDefault)
|
||||
{
|
||||
DWORD dwValue;
|
||||
return DataObj_GetDWORD(pdtobj, cf, &dwValue) == S_OK ? dwValue : dwDefault;
|
||||
}
|
||||
|
||||
HRESULT DataObj_SetDWORD(IDataObject *pdtobj, UINT cf, DWORD dwValue)
|
||||
{
|
||||
return DataObject_SetData(pdtobj, cf, &dwValue, sizeof(dwValue));
|
||||
}
|
||||
|
||||
@@ -91,8 +91,8 @@ SHELL_MapSCIDToColumn(IShellFolder2 *pSF, const SHCOLUMNID *pscid)
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
SHELL_GetDetailsOfAsStringVariant(IShellFolder2 *pSF, PCUITEMID_CHILD pidl, UINT Column, VARIANT *pVar)
|
||||
template<class T> static inline HRESULT
|
||||
GetDetailsOfAsStringVariant(T &pSF, PCUITEMID_CHILD pidl, UINT Column, VARIANT *pVar)
|
||||
{
|
||||
V_VT(pVar) = VT_EMPTY;
|
||||
SHELLDETAILS sd;
|
||||
@@ -106,6 +106,25 @@ SHELL_GetDetailsOfAsStringVariant(IShellFolder2 *pSF, PCUITEMID_CHILD pidl, UINT
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
SHELL_GetDetailsOfAsStringVariant(IShellFolder2 *pSF, PCUITEMID_CHILD pidl, UINT Column, VARIANT *pVar)
|
||||
{
|
||||
return GetDetailsOfAsStringVariant(pSF, pidl, Column, pVar);
|
||||
}
|
||||
|
||||
HRESULT
|
||||
SHELL_GetDetailsOfAsStringVariant(IShellFolder *pSF, PCUITEMID_CHILD pidl, UINT Column, VARIANT *pVar)
|
||||
{
|
||||
HRESULT hr;
|
||||
CComPtr<IShellFolder2> pSF2;
|
||||
if (SUCCEEDED(hr = pSF->QueryInterface(IID_PPV_ARG(IShellFolder2, &pSF2))))
|
||||
return SHELL_GetDetailsOfAsStringVariant(pSF2, pidl, Column, pVar);
|
||||
CComPtr<IShellDetails> pSD;
|
||||
if (SUCCEEDED(hr = pSF->CreateViewObject(NULL, IID_PPV_ARG(IShellDetails, &pSD))))
|
||||
return GetDetailsOfAsStringVariant(pSD, pidl, Column, pVar);
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
SHELL_GetDetailsOfColumnAsVariant(IShellFolder2 *pSF, PCUITEMID_CHILD pidl, UINT Column, VARTYPE vt, VARIANT *pVar)
|
||||
{
|
||||
@@ -139,6 +158,19 @@ SH32_GetDetailsOfPKeyAsVariant(IShellFolder2 *pSF, PCUITEMID_CHILD pidl, const S
|
||||
return SUCCEEDED(hr) ? SHELL_GetDetailsOfColumnAsVariant(pSF, pidl, hr, vt, pVar) : hr;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
SHELL_QueryInfoTipAlloc(_In_ IShellFolder* pSF, _In_ DWORD dwFlags, _In_ LPCITEMIDLIST pidl, _Out_ PWSTR *ppTip)
|
||||
{
|
||||
if (!pidl)
|
||||
return E_INVALIDARG;
|
||||
CComPtr<IQueryInfo> pQI;
|
||||
HRESULT hr = pSF->GetUIObjectOf(NULL, 1, &pidl, IID_NULL_PPV_ARG(IQueryInfo, &pQI));
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
hr = pQI->GetInfoTip(dwFlags, ppTip); // Note: *ppTip can be NULL if there is no tip
|
||||
return SUCCEEDED(hr) && !*ppTip ? S_FALSE : hr;
|
||||
}
|
||||
|
||||
HRESULT SHELL_CreateAbsolutePidl(IShellFolder *pSF, PCUIDLIST_RELATIVE pidlChild, PIDLIST_ABSOLUTE *ppPidl)
|
||||
{
|
||||
PIDLIST_ABSOLUTE pidlFolder;
|
||||
|
||||
@@ -255,6 +255,14 @@ HRESULT WINAPI DoRegisterServer(void);
|
||||
HRESULT WINAPI DoUnregisterServer(void);
|
||||
|
||||
/* Property system */
|
||||
static inline HRESULT
|
||||
SHELL_SysAllocString(PCWSTR in, BSTR *out)
|
||||
{
|
||||
if (!out)
|
||||
return E_INVALIDARG;
|
||||
return (*out = SysAllocString(in ? in : L"")) ? S_OK : E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
static inline HRESULT
|
||||
SHELL_CreateVariantBufferEx(VARIANT *pVar, UINT cb, VARTYPE vt)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user