windows-nt/Source/XPSP1/NT/shell/shell32/sdspatch/sdlink.cpp
2020-09-26 16:20:57 +08:00

360 lines
8.7 KiB
C++

#include "precomp.h"
#pragma hdrstop
class CShortcut :
public IShellLinkDual2,
public CObjectSafety,
protected CImpIDispatch
{
public:
CShortcut();
HRESULT Init(HWND hwnd, IShellFolder *psf, LPCITEMIDLIST pidl);
// IUnknown
STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
STDMETHODIMP_(ULONG) AddRef(void);
STDMETHODIMP_(ULONG) Release(void);
// IDispatch
virtual STDMETHODIMP GetTypeInfoCount(UINT *pctinfo)
{ return CImpIDispatch::GetTypeInfoCount(pctinfo); }
virtual STDMETHODIMP GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo **pptinfo)
{ return CImpIDispatch::GetTypeInfo(itinfo, lcid, pptinfo); }
virtual STDMETHODIMP GetIDsOfNames(REFIID riid, OLECHAR **rgszNames, UINT cNames, LCID lcid, DISPID *rgdispid)
{ return CImpIDispatch::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid); }
virtual STDMETHODIMP Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pdispparams, VARIANT *pvarResult, EXCEPINFO *pexcepinfo, UINT *puArgErr)
{ return CImpIDispatch::Invoke(dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr); }
// IShellLinkDual
STDMETHODIMP get_Path(BSTR *pbs);
STDMETHODIMP put_Path(BSTR bs);
STDMETHODIMP get_Description(BSTR *pbs);
STDMETHODIMP put_Description(BSTR bs);
STDMETHODIMP get_WorkingDirectory(BSTR *pbs);
STDMETHODIMP put_WorkingDirectory(BSTR bs);
STDMETHODIMP get_Arguments(BSTR *pbs);
STDMETHODIMP put_Arguments(BSTR bs);
STDMETHODIMP get_Hotkey(int *piHK);
STDMETHODIMP put_Hotkey(int iHK);
STDMETHODIMP get_ShowCommand(int *piShowCommand);
STDMETHODIMP put_ShowCommand(int iShowCommand);
STDMETHODIMP Resolve(int fFlags);
STDMETHODIMP GetIconLocation(BSTR *pbs, int *piIcon);
STDMETHODIMP SetIconLocation(BSTR bs, int iIcon);
STDMETHODIMP Save(VARIANT vWhere);
// IShellLinkDual2
STDMETHODIMP get_Target(FolderItem **ppfi);
private:
~CShortcut();
HRESULT _SecurityCheck();
LONG _cRef;
HWND _hwnd; // Hwnd of the main folder window
IShellLink *_psl;
};
HRESULT CShortcut_CreateIDispatch(HWND hwnd, IShellFolder *psf, LPCITEMIDLIST pidl, IDispatch ** ppid)
{
HRESULT hr = E_OUTOFMEMORY;
*ppid = NULL;
CShortcut* psdf = new CShortcut();
if (psdf)
{
hr = psdf->Init(hwnd, psf, pidl);
if (SUCCEEDED(hr))
hr = psdf->QueryInterface(IID_IDispatch, (void **)ppid);
psdf->Release();
}
return hr;
}
CShortcut::CShortcut() :
CImpIDispatch(SDSPATCH_TYPELIB, IID_IShellLinkDual2)
{
DllAddRef();
_cRef = 1;
_hwnd = NULL;
_psl = NULL;
}
CShortcut::~CShortcut(void)
{
if (_psl)
_psl->Release();
DllRelease();
}
HRESULT CShortcut::Init(HWND hwnd, IShellFolder *psf, LPCITEMIDLIST pidl)
{
_hwnd = hwnd;
return psf->GetUIObjectOf(hwnd, 1, &pidl, IID_IShellLink, NULL, (void **)&_psl);
}
STDMETHODIMP CShortcut::QueryInterface(REFIID riid, void **ppv)
{
static const QITAB qit[] = {
QITABENT(CShortcut, IShellLinkDual2),
QITABENTMULTI(CShortcut, IShellLinkDual, IShellLinkDual2),
QITABENTMULTI(CShortcut, IDispatch, IShellLinkDual2),
QITABENT(CShortcut, IObjectSafety),
{ 0 },
};
return QISearch(this, qit, riid, ppv);
}
STDMETHODIMP_(ULONG) CShortcut::AddRef(void)
{
return InterlockedIncrement(&_cRef);
}
STDMETHODIMP_(ULONG) CShortcut::Release(void)
{
if (InterlockedDecrement(&_cRef))
return _cRef;
delete this;
return 0;
}
// returns:
// TRUE - every thing OK
// FALSE - don't do it
HRESULT CShortcut::_SecurityCheck()
{
return (_dwSafetyOptions == 0) ? S_OK : E_ACCESSDENIED; // || (IsSafePage(_punkSite) == S_OK);
}
HRESULT _TCharToBSTR(LPCTSTR psz, BSTR *pbs)
{
*pbs = SysAllocStringT(psz);
return *pbs ? S_OK : E_OUTOFMEMORY;
}
LPCTSTR _BSTRToTChar(BSTR bs, TCHAR *psz, UINT cch)
{
if (bs)
SHUnicodeToTChar(bs, psz, cch);
else
psz = NULL;
return psz;
}
STDMETHODIMP CShortcut::get_Path(BSTR *pbs)
{
*pbs = NULL;
HRESULT hr = _SecurityCheck();
if (SUCCEEDED(hr))
{
TCHAR szPath[MAX_PATH];
hr = _psl->GetPath(szPath, ARRAYSIZE(szPath), NULL, 0);
if (SUCCEEDED(hr))
hr = _TCharToBSTR(szPath, pbs);
}
return hr;
}
STDMETHODIMP CShortcut::put_Path(BSTR bs)
{
HRESULT hr = _SecurityCheck();
if (SUCCEEDED(hr))
{
TCHAR szPath[MAX_PATH];
hr = _psl->SetPath(_BSTRToTChar(bs, szPath, ARRAYSIZE(szPath)));
}
return hr;
}
STDMETHODIMP CShortcut::get_Description(BSTR *pbs)
{
*pbs = NULL;
HRESULT hr = _SecurityCheck();
if (SUCCEEDED(hr))
{
TCHAR szDescription[MAX_PATH];
hr = _psl->GetDescription(szDescription, ARRAYSIZE(szDescription));
if (SUCCEEDED(hr))
hr = _TCharToBSTR(szDescription, pbs);
}
return hr;
}
STDMETHODIMP CShortcut::put_Description(BSTR bs)
{
HRESULT hr = _SecurityCheck();
if (SUCCEEDED(hr))
{
TCHAR szDesc[MAX_PATH];
hr = _psl->SetDescription(_BSTRToTChar(bs, szDesc, ARRAYSIZE(szDesc)));
}
return hr;
}
STDMETHODIMP CShortcut::get_WorkingDirectory(BSTR *pbs)
{
*pbs = NULL;
HRESULT hr = _SecurityCheck();
if (SUCCEEDED(hr))
{
TCHAR szWorkingDir[MAX_PATH];
hr = _psl->GetWorkingDirectory(szWorkingDir, ARRAYSIZE(szWorkingDir));
if (SUCCEEDED(hr))
hr = _TCharToBSTR(szWorkingDir, pbs);
}
return hr;
}
STDMETHODIMP CShortcut::put_WorkingDirectory(BSTR bs)
{
HRESULT hr = _SecurityCheck();
if (SUCCEEDED(hr))
{
TCHAR szWorkingDir[MAX_PATH];
hr = _psl->SetWorkingDirectory(_BSTRToTChar(bs, szWorkingDir, ARRAYSIZE(szWorkingDir)));
}
return hr;
}
STDMETHODIMP CShortcut::get_Arguments(BSTR *pbs)
{
*pbs = NULL;
HRESULT hr = _SecurityCheck();
if (SUCCEEDED(hr))
{
TCHAR szArgs[MAX_PATH];
hr = _psl->GetArguments(szArgs, ARRAYSIZE(szArgs));
if (SUCCEEDED(hr))
hr = _TCharToBSTR(szArgs, pbs);
}
return hr;
}
STDMETHODIMP CShortcut::put_Arguments(BSTR bs)
{
HRESULT hr = _SecurityCheck();
if (SUCCEEDED(hr))
{
TCHAR szArgs[MAX_PATH];
hr = _psl->SetArguments(_BSTRToTChar(bs, szArgs, ARRAYSIZE(szArgs)));
}
return hr;
}
STDMETHODIMP CShortcut::get_Hotkey(int *piHK)
{
HRESULT hr = _SecurityCheck();
if (SUCCEEDED(hr))
{
hr = _psl->GetHotkey((WORD*)piHK);
}
return hr;
}
STDMETHODIMP CShortcut::put_Hotkey(int iHK)
{
HRESULT hr = _SecurityCheck();
if (SUCCEEDED(hr))
{
hr = _psl->SetHotkey((WORD)iHK);
}
return hr;
}
STDMETHODIMP CShortcut::get_ShowCommand(int *piShowCommand)
{
HRESULT hr = _SecurityCheck();
if (SUCCEEDED(hr))
{
hr = _psl->GetShowCmd(piShowCommand);
}
return hr;
}
STDMETHODIMP CShortcut::put_ShowCommand(int iShowCommand)
{
HRESULT hr = _SecurityCheck();
if (SUCCEEDED(hr))
{
hr = _psl->SetShowCmd(iShowCommand);
}
return hr;
}
STDMETHODIMP CShortcut::get_Target(FolderItem **ppfi)
{
HRESULT hr = _SecurityCheck();
if (SUCCEEDED(hr))
{
LPITEMIDLIST pidl;
if (S_OK == _psl->GetIDList(&pidl))
{
hr = CFolderItem_CreateFromIDList(NULL, pidl, ppfi);
if (SUCCEEDED(hr) && _dwSafetyOptions)
hr = MakeSafeForScripting((IUnknown**)ppfi);
}
else
hr = E_FAIL;
}
return hr;
}
STDMETHODIMP CShortcut::Resolve(int fFlags)
{
HRESULT hr = _SecurityCheck();
if (SUCCEEDED(hr))
{
hr = _psl->Resolve(_hwnd, (DWORD)fFlags);
}
return hr;
}
STDMETHODIMP CShortcut::GetIconLocation(BSTR *pbs, int *piIcon)
{
*pbs = NULL;
HRESULT hr = _SecurityCheck();
if (SUCCEEDED(hr))
{
TCHAR szIconPath[MAX_PATH];
hr = _psl->GetIconLocation(szIconPath, ARRAYSIZE(szIconPath), piIcon);
if (SUCCEEDED(hr))
hr = _TCharToBSTR(szIconPath, pbs);
}
return hr;
}
STDMETHODIMP CShortcut::SetIconLocation(BSTR bs, int iIcon)
{
HRESULT hr = _SecurityCheck();
if (SUCCEEDED(hr))
{
TCHAR szArgs[MAX_PATH];
hr = _psl->SetIconLocation(_BSTRToTChar(bs, szArgs, ARRAYSIZE(szArgs)), iIcon);
}
return hr;
}
STDMETHODIMP CShortcut::Save(VARIANT vWhere)
{
HRESULT hr = _SecurityCheck();
if (SUCCEEDED(hr))
{
IPersistFile *ppf;
hr = _psl->QueryInterface(IID_IPersistFile, (void **)&ppf);
if (SUCCEEDED(hr))
{
hr = ppf->Save(VariantToStrCast(&vWhere), TRUE);
ppf->Release();
}
}
return hr;
}