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.

475 lines
17 KiB

  1. #ifndef __SHLINK_H__
  2. #define __SHLINK_H__
  3. #include <trkwks.h>
  4. #include <rpcasync.h>
  5. #include <filter.h>
  6. #include "cowsite.h"
  7. class CDarwinContextMenuCB;
  8. class CTracker;
  9. class CShellLink : public IShellLinkA,
  10. public IShellLinkW,
  11. public IPersistStream,
  12. public IPersistFile,
  13. public IShellExtInit,
  14. public IContextMenu3,
  15. public IDropTarget,
  16. public IQueryInfo,
  17. public IShellLinkDataList,
  18. public IExtractIconA,
  19. public IExtractIconW,
  20. public IExtractImage2,
  21. public IPersistPropertyBag,
  22. public IServiceProvider,
  23. public IFilter,
  24. public CObjectWithSite,
  25. public ICustomizeInfoTip
  26. {
  27. friend CTracker;
  28. friend CDarwinContextMenuCB;
  29. public:
  30. CShellLink();
  31. // IUnknown
  32. STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
  33. STDMETHODIMP_(ULONG) AddRef();
  34. STDMETHODIMP_(ULONG) Release();
  35. // IShellLinkA methods
  36. STDMETHOD(GetPath)(LPSTR pszFile, int cchMaxPath, WIN32_FIND_DATAA *pfd, DWORD flags);
  37. STDMETHOD(SetPath)(LPCSTR pszFile);
  38. //STDMETHOD(GetIDList)(LPITEMIDLIST *ppidl);
  39. //STDMETHOD(SetIDList)(LPCITEMIDLIST pidl);
  40. STDMETHOD(GetDescription)(LPSTR pszName, int cchMaxName);
  41. STDMETHOD(SetDescription)(LPCSTR pszName);
  42. STDMETHOD(GetWorkingDirectory)(LPSTR pszDir, int cchMaxPath);
  43. STDMETHOD(SetWorkingDirectory)(LPCSTR pszDir);
  44. STDMETHOD(GetArguments)(LPSTR pszArgs, int cchMaxPath);
  45. STDMETHOD(SetArguments)(LPCSTR pszArgs);
  46. //STDMETHOD(GetHotkey)(WORD *pwHotkey);
  47. //STDMETHOD(SetHotkey)(WORD wHotkey);
  48. //STDMETHOD(GetShowCmd)(int *piShowCmd);
  49. //STDMETHOD(SetShowCmd)(int iShowCmd);
  50. STDMETHOD(GetIconLocation)(LPSTR pszIconPath, int cchIconPath, int *piIcon);
  51. STDMETHOD(SetIconLocation)(LPCSTR pszIconPath, int iIcon);
  52. //STDMETHOD(Resolve)(HWND hwnd, DWORD dwResolveFlags);
  53. STDMETHOD(SetRelativePath)(LPCSTR pszPathRel, DWORD dwReserved);
  54. // IShellLinkW
  55. STDMETHOD(GetPath)(LPWSTR pszFile, int cchMaxPath, WIN32_FIND_DATAW *pfd, DWORD fFlags);
  56. STDMETHOD(GetIDList)(LPITEMIDLIST *ppidl);
  57. STDMETHOD(SetIDList)(LPCITEMIDLIST pidl);
  58. STDMETHOD(GetDescription)(LPWSTR pszName, int cchMaxName);
  59. STDMETHOD(SetDescription)(LPCWSTR pszName);
  60. STDMETHOD(GetWorkingDirectory)(LPWSTR pszDir, int cchMaxPath);
  61. STDMETHOD(SetWorkingDirectory)(LPCWSTR pszDir);
  62. STDMETHOD(GetArguments)(LPWSTR pszArgs, int cchMaxPath);
  63. STDMETHOD(SetArguments)(LPCWSTR pszArgs);
  64. STDMETHOD(GetHotkey)(WORD *pwHotKey);
  65. STDMETHOD(SetHotkey)(WORD wHotkey);
  66. STDMETHOD(GetShowCmd)(int *piShowCmd);
  67. STDMETHOD(SetShowCmd)(int iShowCmd);
  68. STDMETHOD(GetIconLocation)(LPWSTR pszIconPath, int cchIconPath, int *piIcon);
  69. STDMETHOD(SetIconLocation)(LPCWSTR pszIconPath, int iIcon);
  70. STDMETHOD(SetRelativePath)(LPCWSTR pszPathRel, DWORD dwReserved);
  71. STDMETHOD(Resolve)(HWND hwnd, DWORD dwResolveFlags);
  72. STDMETHOD(SetPath)(LPCWSTR pszFile);
  73. // IPersist
  74. STDMETHOD(GetClassID)(CLSID *pClassID);
  75. STDMETHOD(IsDirty)();
  76. // IPersistStream
  77. STDMETHOD(Load)(IStream *pstm);
  78. STDMETHOD(Save)(IStream *pstm, BOOL fClearDirty);
  79. STDMETHOD(GetSizeMax)(ULARGE_INTEGER *pcbSize);
  80. // IPersistFile
  81. STDMETHOD(Load)(LPCOLESTR pwszFile, DWORD grfMode);
  82. STDMETHOD(Save)(LPCOLESTR pwszFile, BOOL fRemember);
  83. STDMETHOD(SaveCompleted)(LPCOLESTR pwszFile);
  84. STDMETHOD(GetCurFile)(LPOLESTR *lplpszFileName);
  85. // IPersistPropertyBag
  86. STDMETHOD(Save)(IPropertyBag* pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties);
  87. STDMETHOD(Load)(IPropertyBag* pPropBag, IErrorLog* pErrorLog);
  88. STDMETHOD(InitNew)(void);
  89. // IShellExtInit
  90. STDMETHOD(Initialize)(LPCITEMIDLIST pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID);
  91. // IContextMenu3
  92. STDMETHOD(QueryContextMenu)(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
  93. STDMETHOD(InvokeCommand)(LPCMINVOKECOMMANDINFO piciIn);
  94. STDMETHOD(GetCommandString)(UINT_PTR idCmd, UINT wFlags, UINT *pmf, LPSTR pszName, UINT cchMax);
  95. STDMETHOD(HandleMenuMsg)(UINT uMsg, WPARAM wParam, LPARAM lParam);
  96. STDMETHOD(HandleMenuMsg2)(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *lResult);
  97. // IDropTarget
  98. STDMETHOD(DragEnter)(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
  99. STDMETHOD(DragOver)(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
  100. STDMETHOD(DragLeave)();
  101. STDMETHOD(Drop)(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
  102. // IQueryInfo
  103. STDMETHOD(GetInfoTip)(DWORD dwFlags, WCHAR **ppwszTip);
  104. STDMETHOD(GetInfoFlags)(LPDWORD pdwFlags);
  105. // IShellLinkDataList
  106. STDMETHOD(AddDataBlock)(void *pdb);
  107. STDMETHOD(CopyDataBlock)(DWORD dwSig, void **ppdb);
  108. STDMETHOD(RemoveDataBlock)(DWORD dwSig);
  109. STDMETHOD(GetFlags)(LPDWORD pdwFlags);
  110. STDMETHOD(SetFlags)(DWORD dwFlags);
  111. // IExtractIconA
  112. STDMETHOD(GetIconLocation)(UINT uFlags,LPSTR szIconFile,UINT cchMax,int *piIndex,UINT * pwFlags);
  113. STDMETHOD(Extract)(LPCSTR pszFile,UINT nIconIndex,HICON *phiconLarge,HICON *phiconSmall,UINT nIcons);
  114. // IExtractIconW
  115. STDMETHOD(GetIconLocation)(UINT uFlags, LPWSTR pszIconFile, UINT cchMax, int *piIndex, UINT *pwFlags);
  116. STDMETHOD(Extract)(LPCWSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize);
  117. // IExtractImage
  118. STDMETHOD (GetLocation)(LPWSTR pszPathBuffer, DWORD cch, DWORD * pdwPriority, const SIZE * prgSize,
  119. DWORD dwRecClrDepth, DWORD *pdwFlags);
  120. STDMETHOD (Extract)(HBITMAP *phBmpThumbnail);
  121. // IExtractImage2
  122. STDMETHOD (GetDateStamp)(FILETIME *pftDateStamp);
  123. // IServiceProvider
  124. STDMETHOD(QueryService)(REFGUID guidService, REFIID riid, void **ppv);
  125. // IFilter
  126. STDMETHOD(Init)(ULONG grfFlags, ULONG cAttributes, const FULLPROPSPEC *aAttributes, ULONG *pFlags);
  127. STDMETHOD(GetChunk)(STAT_CHUNK *pStat);
  128. STDMETHOD(GetText)(ULONG *pcwcBuffer, WCHAR *awcBuffer);
  129. STDMETHOD(GetValue)(PROPVARIANT **ppPropValue);
  130. STDMETHOD(BindRegion)(FILTERREGION origPos, REFIID riid, void **ppunk);
  131. //*** IObjectWithSite ***
  132. //STDMETHOD(SetSite)(IUnknown *punkSite);
  133. //STDMETHOD(GetSite)(REFIID riid, void **ppvSite);
  134. // ICustomizeInfoTip
  135. STDMETHODIMP SetPrefixText(LPCWSTR pszPrefix);
  136. STDMETHODIMP SetExtraProperties(const SHCOLUMNID *pscid, UINT cscid);
  137. // public non interface members
  138. void _AddExtraDataSection(DATABLOCK_HEADER *pdbh);
  139. void _RemoveExtraDataSection(DWORD dwSig);
  140. void * _ReadExtraDataSection(DWORD dwSig);
  141. protected:
  142. HRESULT _Resolve(HWND hwnd, DWORD dwResolveFlags, DWORD dwTracker);
  143. private:
  144. ~CShellLink();
  145. static DWORD CALLBACK _InvokeThreadProc(void *pv);
  146. static DWORD CALLBACK _VerifyPathThreadProc(void *pv);
  147. void _ResetPersistData();
  148. BOOL _GetRelativePath(LPTSTR pszPath);
  149. BOOL _GetUNCPath(LPTSTR pszName);
  150. HRESULT _SetPIDLPath(LPCITEMIDLIST pidl, LPCTSTR pszPath, BOOL bUpdateTrackingData);
  151. HRESULT _SetSimplePIDL(LPCTSTR pszPath);
  152. void _UpdateWorkingDir(LPCTSTR pszPath);
  153. PLINKINFO _GetLinkInfo(LPCTSTR pszPath);
  154. void _FreeLinkInfo();
  155. HRESULT _GetFindDataAndTracker(LPCTSTR pszPath);
  156. void _ClearTrackerData();
  157. BOOL _SetFindData(const WIN32_FIND_DATA *pfd);
  158. void _GetFindData(WIN32_FIND_DATA *pfd);
  159. BOOL _IsEqualFindData(const WIN32_FIND_DATA *pfd);
  160. HRESULT _ResolveIDList(HWND hwnd, DWORD dwResolveFlags);
  161. HRESULT _ResolveLinkInfo(HWND hwnd, DWORD dwResolveFlags, LPTSTR pszPath, DWORD *pfifFlags);
  162. HRESULT _ResolveRemovable(HWND hwnd, LPCTSTR pszPath);
  163. BOOL _ShouldTryRemovable(HRESULT hr, LPCTSTR pszPath);
  164. void _SetIDListFromEnvVars();
  165. BOOL _ResolveDarwin(HWND hwnd, DWORD dwResolveFlags, HRESULT *phr);
  166. HRESULT _ResolveLogo3Link(HWND hwnd, DWORD dwResolveFlags);
  167. HRESULT _CheckForLinkBlessing(LPCTSTR *ppszPathIn);
  168. HRESULT BlessLink(LPCTSTR *ppszPath, DWORD dwSignature);
  169. BOOL _EncodeSpecialFolder();
  170. void _DecodeSpecialFolder();
  171. HRESULT _SetRelativePath(LPCTSTR pszRelSource);
  172. HRESULT _UpdateTracker();
  173. HRESULT _LoadFromFile(LPCTSTR pszPath);
  174. HRESULT _LoadFromPIF(LPCTSTR szPath);
  175. HRESULT _SaveToFile(LPTSTR pszPathSave, BOOL fRemember);
  176. HRESULT _SaveAsLink(LPCTSTR szPath);
  177. HRESULT _SaveAsPIF(LPCTSTR pszPath, BOOL fPath);
  178. BOOL _GetWorkingDir(LPTSTR pszDir);
  179. HRESULT _GetUIObject(HWND hwnd, REFIID riid, void **ppvOut);
  180. HRESULT _ShortNetTimeout();
  181. HRESULT _CreateDarwinContextMenu(HWND hwnd,IContextMenu **pcmOut);
  182. HRESULT _CreateDarwinContextMenuForPidl(HWND hwnd, LPCITEMIDLIST pidlTarget, IContextMenu **pcmOut);
  183. HRESULT _InvokeCommandAsync(LPCMINVOKECOMMANDINFO pici);
  184. HRESULT _InitDropTarget();
  185. HRESULT _GetExtractIcon(REFIID riid, void **ppvOut);
  186. HRESULT _InitExtractIcon();
  187. HRESULT _InitExtractImage();
  188. BOOL _GetExpandedPath(LPTSTR psz, DWORD cch);
  189. HRESULT _SetField(LPTSTR *ppszField, LPCWSTR pszValueW);
  190. HRESULT _SetField(LPTSTR *ppszField, LPCSTR pszValueA);
  191. HRESULT _GetField(LPCTSTR pszField, LPWSTR pszValueW, int cchValue);
  192. HRESULT _GetField(LPCTSTR pszField, LPSTR pszValueA, int cchValue);
  193. int _IsOldDarwin(LPCTSTR pszPath);
  194. HRESULT _SetPathOldDarwin(LPCTSTR pszPath);
  195. BOOL _LinkInfo(LINKINFODATATYPE info, LPTSTR psz, UINT cch);
  196. HRESULT _CreateProcessWithShimLayer(HANDLE hData, BOOL fAllowAsync);
  197. HRESULT _MaybeAddShim(IBindCtx **ppbcRelease);
  198. HRESULT _UpdateIconFromExpIconSz();
  199. //
  200. // Inner class to manage the context menu of the shortcut target.
  201. // We do this to ensure that the target's context menu gets a proper
  202. // SetSite call so it can contact the containing shortcut.
  203. //
  204. class TargetContextMenu {
  205. public:
  206. operator IUnknown*() { return _pcmTarget; }
  207. // WARNING! Use only as an output pointer
  208. IContextMenu **GetOutputPtr() { return &_pcmTarget; }
  209. HRESULT QueryContextMenu(IShellLink *outer, HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
  210. {
  211. IUnknown_SetSite(_pcmTarget, outer);
  212. HRESULT hr = _pcmTarget->QueryContextMenu(hmenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
  213. IUnknown_SetSite(_pcmTarget, NULL);
  214. return hr;
  215. }
  216. HRESULT InvokeCommand(IShellLink *outer, LPCMINVOKECOMMANDINFO pici)
  217. {
  218. IUnknown_SetSite(_pcmTarget, outer);
  219. HRESULT hr = _pcmTarget->InvokeCommand(pici);
  220. IUnknown_SetSite(_pcmTarget, NULL);
  221. return hr;
  222. }
  223. HRESULT HandleMenuMsg2(IShellLink *outer, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plResult);
  224. // This doesn't need to be wrapped in a SetSite (yet)
  225. UINT GetCommandString(IShellLink *outer, UINT_PTR idCmd, UINT wFlags, UINT *pmf, LPSTR pszName, UINT cchMax)
  226. {
  227. HRESULT hr = _pcmTarget->GetCommandString(idCmd, wFlags, pmf, pszName, cchMax);
  228. return hr;
  229. }
  230. // This doesn't need to be wrapped in a SetSite (yet)
  231. UINT GetMenuIndexForCanonicalVerb(IShellLink *outer, HMENU hMenu, UINT idCmdFirst, LPCWSTR pwszVerb)
  232. {
  233. UINT ui = ::GetMenuIndexForCanonicalVerb(hMenu, _pcmTarget, idCmdFirst, pwszVerb);
  234. return ui;
  235. }
  236. void AtomicRelease()
  237. {
  238. ATOMICRELEASE(_pcmTarget);
  239. }
  240. ~TargetContextMenu()
  241. {
  242. IUnknown_SetSite(_pcmTarget, NULL);
  243. AtomicRelease();
  244. }
  245. private:
  246. IContextMenu *_pcmTarget; // stuff for IContextMenu
  247. };
  248. // Data Members
  249. LONG _cRef; // Ref Count
  250. BOOL _bDirty; // something has changed
  251. LPTSTR _pszCurFile; // current file from IPersistFile
  252. LPTSTR _pszRelSource; // overrides pszCurFile in relative tracking
  253. TargetContextMenu _cmTarget; // stuff for IContextMenu
  254. CDarwinContextMenuCB *_pcbDarwin;
  255. UINT _indexMenuSave;
  256. UINT _idCmdFirstSave;
  257. UINT _idCmdLastSave;
  258. UINT _uFlagsSave;
  259. // IDropTarget specific
  260. IDropTarget* _pdtSrc; // IDropTarget of link source (unresolved)
  261. DWORD _grfKeyStateLast;
  262. IExtractIconW *_pxi; // for IExtractIcon support
  263. IExtractIconA *_pxiA;
  264. IExtractImage *_pxthumb;
  265. UINT _gilFlags; // ::GetIconLocation() flags
  266. // persistant data
  267. LPITEMIDLIST _pidl; // may be NULL
  268. PLINKINFO _pli; // may be NULL
  269. LPTSTR _pszName; // title on short volumes
  270. LPTSTR _pszRelPath;
  271. LPTSTR _pszWorkingDir;
  272. LPTSTR _pszArgs;
  273. LPTSTR _pszIconLocation;
  274. LPDBLIST _pExtraData; // extra data to preserve for future compatibility
  275. CTracker *_ptracker;
  276. WORD _wOldHotkey; // to broadcast hotkey changes
  277. WORD _wAllign;
  278. SHELL_LINK_DATA _sld;
  279. BOOL _bExpandedIcon; // have we already tried to update the icon from the env variable for this instance?
  280. // IFilter stuff
  281. UINT _iChunkIndex;
  282. UINT _iValueIndex;
  283. LPWSTR _pszPrefix;
  284. };
  285. DECLARE_INTERFACE_(ISLTracker, IUnknown)
  286. {
  287. STDMETHOD(QueryInterface)(REFIID riid, void **ppv);
  288. STDMETHOD_(ULONG, AddRef)();
  289. STDMETHOD_(ULONG, Release)();
  290. STDMETHOD(Resolve)(HWND hwnd, DWORD fFlags, DWORD TrackerRestrictions) PURE;
  291. STDMETHOD(GetIDs)(CDomainRelativeObjId *pdroidBirth, CDomainRelativeObjId *pdroidLast, CMachineId *pmcid) PURE;
  292. STDMETHOD(CancelSearch)() PURE;
  293. };
  294. // This class implements the object ID-based link tracking (new to NT5).
  295. class CTracker : public ISLTracker
  296. {
  297. public:
  298. // IUnknown
  299. STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
  300. STDMETHODIMP_(ULONG) AddRef();
  301. STDMETHODIMP_(ULONG) Release();
  302. // ISLTracker
  303. STDMETHODIMP Resolve(HWND hwnd, DWORD fFlags, DWORD TrackerRestrictions);
  304. STDMETHODIMP GetIDs(CDomainRelativeObjId *pdroidBirth, CDomainRelativeObjId *pdroidLast, CMachineId *pmcid);
  305. CTracker(CShellLink *psl) : _psl(psl)
  306. {
  307. _fLoadedAtLeastOnce = _fLoaded = _fDirty = FALSE;
  308. _fCritsecInitialized = _fMendInProgress = _fUserCancelled = FALSE;
  309. _hEvent = NULL;
  310. _pRpcAsyncState = NULL;
  311. };
  312. ~CTracker()
  313. {
  314. if (_fCritsecInitialized)
  315. {
  316. DeleteCriticalSection(&_cs);
  317. _fCritsecInitialized = FALSE;
  318. }
  319. if (NULL != _pRpcAsyncState)
  320. {
  321. delete[] _pRpcAsyncState;
  322. _pRpcAsyncState = NULL;
  323. }
  324. if (NULL != _hEvent)
  325. {
  326. CloseHandle(_hEvent);
  327. _hEvent = NULL;
  328. }
  329. }
  330. // Initialization.
  331. HRESULT InitFromHandle(const HANDLE hFile, const TCHAR* ptszFile);
  332. HRESULT InitNew();
  333. void UnInit();
  334. // Load and Save
  335. HRESULT Load(BYTE *pb, ULONG cb);
  336. ULONG GetSize()
  337. {
  338. return sizeof(DWORD) // To save the length
  339. + sizeof(DWORD) // To save flags
  340. + sizeof(_mcidLast) + sizeof(_droidLast) + sizeof(_droidBirth);
  341. }
  342. void Save(BYTE *pb, ULONG cb);
  343. // Search for a file
  344. HRESULT Search(const DWORD dwTickCountDeadline,
  345. const WIN32_FIND_DATA *pfdIn,
  346. WIN32_FIND_DATA *pfdOut,
  347. UINT uShlinkFlags,
  348. DWORD TrackerRestrictions);
  349. STDMETHODIMP CancelSearch(); // Also in ISLTracker
  350. BOOL IsDirty()
  351. {
  352. return _fDirty;
  353. }
  354. BOOL IsLoaded()
  355. {
  356. return _fLoaded;
  357. }
  358. BOOL WasLoadedAtLeastOnce()
  359. {
  360. return _fLoadedAtLeastOnce;
  361. }
  362. private:
  363. // Call this from either InitNew or Load
  364. HRESULT InitRPC();
  365. BOOL _fDirty:1;
  366. // TRUE => InitNew has be called, but neither InitFromHandle nor Load
  367. // has been called since.
  368. BOOL _fLoaded:1;
  369. // TRUE => _cs has been intialized and must be deleted on destruction.
  370. BOOL _fCritsecInitialized:1;
  371. // TRUE => An async call to LnkMendLink is active
  372. BOOL _fMendInProgress:1;
  373. BOOL _fUserCancelled:1;
  374. // Event used for the async RPC call LnkMendLink, and a critsec to
  375. // coordinate the search thread and UI thread.
  376. HANDLE _hEvent;
  377. CRITICAL_SECTION _cs;
  378. // Either InitFromHandle or Load has been called at least once, though
  379. // InitNew may have been called since.
  380. BOOL _fLoadedAtLeastOnce:1;
  381. CShellLink *_psl;
  382. PRPC_ASYNC_STATE _pRpcAsyncState;
  383. CMachineId _mcidLast;
  384. CDomainRelativeObjId _droidLast;
  385. CDomainRelativeObjId _droidBirth;
  386. };
  387. #endif //__SHLINK_H__