Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

359 lines
8.7 KiB

  1. #include "precomp.h"
  2. #pragma hdrstop
  3. class CShortcut :
  4. public IShellLinkDual2,
  5. public CObjectSafety,
  6. protected CImpIDispatch
  7. {
  8. public:
  9. CShortcut();
  10. HRESULT Init(HWND hwnd, IShellFolder *psf, LPCITEMIDLIST pidl);
  11. // IUnknown
  12. STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
  13. STDMETHODIMP_(ULONG) AddRef(void);
  14. STDMETHODIMP_(ULONG) Release(void);
  15. // IDispatch
  16. virtual STDMETHODIMP GetTypeInfoCount(UINT *pctinfo)
  17. { return CImpIDispatch::GetTypeInfoCount(pctinfo); }
  18. virtual STDMETHODIMP GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo **pptinfo)
  19. { return CImpIDispatch::GetTypeInfo(itinfo, lcid, pptinfo); }
  20. virtual STDMETHODIMP GetIDsOfNames(REFIID riid, OLECHAR **rgszNames, UINT cNames, LCID lcid, DISPID *rgdispid)
  21. { return CImpIDispatch::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid); }
  22. virtual STDMETHODIMP Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pdispparams, VARIANT *pvarResult, EXCEPINFO *pexcepinfo, UINT *puArgErr)
  23. { return CImpIDispatch::Invoke(dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr); }
  24. // IShellLinkDual
  25. STDMETHODIMP get_Path(BSTR *pbs);
  26. STDMETHODIMP put_Path(BSTR bs);
  27. STDMETHODIMP get_Description(BSTR *pbs);
  28. STDMETHODIMP put_Description(BSTR bs);
  29. STDMETHODIMP get_WorkingDirectory(BSTR *pbs);
  30. STDMETHODIMP put_WorkingDirectory(BSTR bs);
  31. STDMETHODIMP get_Arguments(BSTR *pbs);
  32. STDMETHODIMP put_Arguments(BSTR bs);
  33. STDMETHODIMP get_Hotkey(int *piHK);
  34. STDMETHODIMP put_Hotkey(int iHK);
  35. STDMETHODIMP get_ShowCommand(int *piShowCommand);
  36. STDMETHODIMP put_ShowCommand(int iShowCommand);
  37. STDMETHODIMP Resolve(int fFlags);
  38. STDMETHODIMP GetIconLocation(BSTR *pbs, int *piIcon);
  39. STDMETHODIMP SetIconLocation(BSTR bs, int iIcon);
  40. STDMETHODIMP Save(VARIANT vWhere);
  41. // IShellLinkDual2
  42. STDMETHODIMP get_Target(FolderItem **ppfi);
  43. private:
  44. ~CShortcut();
  45. HRESULT _SecurityCheck();
  46. LONG _cRef;
  47. HWND _hwnd; // Hwnd of the main folder window
  48. IShellLink *_psl;
  49. };
  50. HRESULT CShortcut_CreateIDispatch(HWND hwnd, IShellFolder *psf, LPCITEMIDLIST pidl, IDispatch ** ppid)
  51. {
  52. HRESULT hr = E_OUTOFMEMORY;
  53. *ppid = NULL;
  54. CShortcut* psdf = new CShortcut();
  55. if (psdf)
  56. {
  57. hr = psdf->Init(hwnd, psf, pidl);
  58. if (SUCCEEDED(hr))
  59. hr = psdf->QueryInterface(IID_IDispatch, (void **)ppid);
  60. psdf->Release();
  61. }
  62. return hr;
  63. }
  64. CShortcut::CShortcut() :
  65. CImpIDispatch(SDSPATCH_TYPELIB, IID_IShellLinkDual2)
  66. {
  67. DllAddRef();
  68. _cRef = 1;
  69. _hwnd = NULL;
  70. _psl = NULL;
  71. }
  72. CShortcut::~CShortcut(void)
  73. {
  74. if (_psl)
  75. _psl->Release();
  76. DllRelease();
  77. }
  78. HRESULT CShortcut::Init(HWND hwnd, IShellFolder *psf, LPCITEMIDLIST pidl)
  79. {
  80. _hwnd = hwnd;
  81. return psf->GetUIObjectOf(hwnd, 1, &pidl, IID_IShellLink, NULL, (void **)&_psl);
  82. }
  83. STDMETHODIMP CShortcut::QueryInterface(REFIID riid, void **ppv)
  84. {
  85. static const QITAB qit[] = {
  86. QITABENT(CShortcut, IShellLinkDual2),
  87. QITABENTMULTI(CShortcut, IShellLinkDual, IShellLinkDual2),
  88. QITABENTMULTI(CShortcut, IDispatch, IShellLinkDual2),
  89. QITABENT(CShortcut, IObjectSafety),
  90. { 0 },
  91. };
  92. return QISearch(this, qit, riid, ppv);
  93. }
  94. STDMETHODIMP_(ULONG) CShortcut::AddRef(void)
  95. {
  96. return InterlockedIncrement(&_cRef);
  97. }
  98. STDMETHODIMP_(ULONG) CShortcut::Release(void)
  99. {
  100. if (InterlockedDecrement(&_cRef))
  101. return _cRef;
  102. delete this;
  103. return 0;
  104. }
  105. // returns:
  106. // TRUE - every thing OK
  107. // FALSE - don't do it
  108. HRESULT CShortcut::_SecurityCheck()
  109. {
  110. return (_dwSafetyOptions == 0) ? S_OK : E_ACCESSDENIED; // || (IsSafePage(_punkSite) == S_OK);
  111. }
  112. HRESULT _TCharToBSTR(LPCTSTR psz, BSTR *pbs)
  113. {
  114. *pbs = SysAllocStringT(psz);
  115. return *pbs ? S_OK : E_OUTOFMEMORY;
  116. }
  117. LPCTSTR _BSTRToTChar(BSTR bs, TCHAR *psz, UINT cch)
  118. {
  119. if (bs)
  120. SHUnicodeToTChar(bs, psz, cch);
  121. else
  122. psz = NULL;
  123. return psz;
  124. }
  125. STDMETHODIMP CShortcut::get_Path(BSTR *pbs)
  126. {
  127. *pbs = NULL;
  128. HRESULT hr = _SecurityCheck();
  129. if (SUCCEEDED(hr))
  130. {
  131. TCHAR szPath[MAX_PATH];
  132. hr = _psl->GetPath(szPath, ARRAYSIZE(szPath), NULL, 0);
  133. if (SUCCEEDED(hr))
  134. hr = _TCharToBSTR(szPath, pbs);
  135. }
  136. return hr;
  137. }
  138. STDMETHODIMP CShortcut::put_Path(BSTR bs)
  139. {
  140. HRESULT hr = _SecurityCheck();
  141. if (SUCCEEDED(hr))
  142. {
  143. TCHAR szPath[MAX_PATH];
  144. hr = _psl->SetPath(_BSTRToTChar(bs, szPath, ARRAYSIZE(szPath)));
  145. }
  146. return hr;
  147. }
  148. STDMETHODIMP CShortcut::get_Description(BSTR *pbs)
  149. {
  150. *pbs = NULL;
  151. HRESULT hr = _SecurityCheck();
  152. if (SUCCEEDED(hr))
  153. {
  154. TCHAR szDescription[MAX_PATH];
  155. hr = _psl->GetDescription(szDescription, ARRAYSIZE(szDescription));
  156. if (SUCCEEDED(hr))
  157. hr = _TCharToBSTR(szDescription, pbs);
  158. }
  159. return hr;
  160. }
  161. STDMETHODIMP CShortcut::put_Description(BSTR bs)
  162. {
  163. HRESULT hr = _SecurityCheck();
  164. if (SUCCEEDED(hr))
  165. {
  166. TCHAR szDesc[MAX_PATH];
  167. hr = _psl->SetDescription(_BSTRToTChar(bs, szDesc, ARRAYSIZE(szDesc)));
  168. }
  169. return hr;
  170. }
  171. STDMETHODIMP CShortcut::get_WorkingDirectory(BSTR *pbs)
  172. {
  173. *pbs = NULL;
  174. HRESULT hr = _SecurityCheck();
  175. if (SUCCEEDED(hr))
  176. {
  177. TCHAR szWorkingDir[MAX_PATH];
  178. hr = _psl->GetWorkingDirectory(szWorkingDir, ARRAYSIZE(szWorkingDir));
  179. if (SUCCEEDED(hr))
  180. hr = _TCharToBSTR(szWorkingDir, pbs);
  181. }
  182. return hr;
  183. }
  184. STDMETHODIMP CShortcut::put_WorkingDirectory(BSTR bs)
  185. {
  186. HRESULT hr = _SecurityCheck();
  187. if (SUCCEEDED(hr))
  188. {
  189. TCHAR szWorkingDir[MAX_PATH];
  190. hr = _psl->SetWorkingDirectory(_BSTRToTChar(bs, szWorkingDir, ARRAYSIZE(szWorkingDir)));
  191. }
  192. return hr;
  193. }
  194. STDMETHODIMP CShortcut::get_Arguments(BSTR *pbs)
  195. {
  196. *pbs = NULL;
  197. HRESULT hr = _SecurityCheck();
  198. if (SUCCEEDED(hr))
  199. {
  200. TCHAR szArgs[MAX_PATH];
  201. hr = _psl->GetArguments(szArgs, ARRAYSIZE(szArgs));
  202. if (SUCCEEDED(hr))
  203. hr = _TCharToBSTR(szArgs, pbs);
  204. }
  205. return hr;
  206. }
  207. STDMETHODIMP CShortcut::put_Arguments(BSTR bs)
  208. {
  209. HRESULT hr = _SecurityCheck();
  210. if (SUCCEEDED(hr))
  211. {
  212. TCHAR szArgs[MAX_PATH];
  213. hr = _psl->SetArguments(_BSTRToTChar(bs, szArgs, ARRAYSIZE(szArgs)));
  214. }
  215. return hr;
  216. }
  217. STDMETHODIMP CShortcut::get_Hotkey(int *piHK)
  218. {
  219. HRESULT hr = _SecurityCheck();
  220. if (SUCCEEDED(hr))
  221. {
  222. hr = _psl->GetHotkey((WORD*)piHK);
  223. }
  224. return hr;
  225. }
  226. STDMETHODIMP CShortcut::put_Hotkey(int iHK)
  227. {
  228. HRESULT hr = _SecurityCheck();
  229. if (SUCCEEDED(hr))
  230. {
  231. hr = _psl->SetHotkey((WORD)iHK);
  232. }
  233. return hr;
  234. }
  235. STDMETHODIMP CShortcut::get_ShowCommand(int *piShowCommand)
  236. {
  237. HRESULT hr = _SecurityCheck();
  238. if (SUCCEEDED(hr))
  239. {
  240. hr = _psl->GetShowCmd(piShowCommand);
  241. }
  242. return hr;
  243. }
  244. STDMETHODIMP CShortcut::put_ShowCommand(int iShowCommand)
  245. {
  246. HRESULT hr = _SecurityCheck();
  247. if (SUCCEEDED(hr))
  248. {
  249. hr = _psl->SetShowCmd(iShowCommand);
  250. }
  251. return hr;
  252. }
  253. STDMETHODIMP CShortcut::get_Target(FolderItem **ppfi)
  254. {
  255. HRESULT hr = _SecurityCheck();
  256. if (SUCCEEDED(hr))
  257. {
  258. LPITEMIDLIST pidl;
  259. if (S_OK == _psl->GetIDList(&pidl))
  260. {
  261. hr = CFolderItem_CreateFromIDList(NULL, pidl, ppfi);
  262. if (SUCCEEDED(hr) && _dwSafetyOptions)
  263. hr = MakeSafeForScripting((IUnknown**)ppfi);
  264. }
  265. else
  266. hr = E_FAIL;
  267. }
  268. return hr;
  269. }
  270. STDMETHODIMP CShortcut::Resolve(int fFlags)
  271. {
  272. HRESULT hr = _SecurityCheck();
  273. if (SUCCEEDED(hr))
  274. {
  275. hr = _psl->Resolve(_hwnd, (DWORD)fFlags);
  276. }
  277. return hr;
  278. }
  279. STDMETHODIMP CShortcut::GetIconLocation(BSTR *pbs, int *piIcon)
  280. {
  281. *pbs = NULL;
  282. HRESULT hr = _SecurityCheck();
  283. if (SUCCEEDED(hr))
  284. {
  285. TCHAR szIconPath[MAX_PATH];
  286. hr = _psl->GetIconLocation(szIconPath, ARRAYSIZE(szIconPath), piIcon);
  287. if (SUCCEEDED(hr))
  288. hr = _TCharToBSTR(szIconPath, pbs);
  289. }
  290. return hr;
  291. }
  292. STDMETHODIMP CShortcut::SetIconLocation(BSTR bs, int iIcon)
  293. {
  294. HRESULT hr = _SecurityCheck();
  295. if (SUCCEEDED(hr))
  296. {
  297. TCHAR szArgs[MAX_PATH];
  298. hr = _psl->SetIconLocation(_BSTRToTChar(bs, szArgs, ARRAYSIZE(szArgs)), iIcon);
  299. }
  300. return hr;
  301. }
  302. STDMETHODIMP CShortcut::Save(VARIANT vWhere)
  303. {
  304. HRESULT hr = _SecurityCheck();
  305. if (SUCCEEDED(hr))
  306. {
  307. IPersistFile *ppf;
  308. hr = _psl->QueryInterface(IID_IPersistFile, (void **)&ppf);
  309. if (SUCCEEDED(hr))
  310. {
  311. hr = ppf->Save(VariantToStrCast(&vWhere), TRUE);
  312. ppf->Release();
  313. }
  314. }
  315. return hr;
  316. }