360 lines
8.7 KiB
C++
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;
|
||
|
}
|