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.

678 lines
16 KiB

  1. /*
  2. * shlink.cpp - IShellLink implementation for InternetShortcut class.
  3. */
  4. /* Headers
  5. **********/
  6. #include "project.hpp"
  7. #pragma hdrstop
  8. /* Types
  9. ********/
  10. typedef enum isl_getpath_flags
  11. {
  12. // flag combinations
  13. ALL_ISL_GETPATH_FLAGS = (SLGP_SHORTPATH |
  14. SLGP_UNCPRIORITY)
  15. }
  16. ISL_GETPATH_FLAGS;
  17. typedef enum isl_resolve_flags
  18. {
  19. // flag combinations
  20. ALL_ISL_RESOLVE_FLAGS = (SLR_NO_UI |
  21. SLR_ANY_MATCH |
  22. SLR_UPDATE)
  23. }
  24. ISL_RESOLVE_FLAGS;
  25. /********************************** Methods **********************************/
  26. HRESULT STDMETHODCALLTYPE InternetShortcut::SetPath(PCSTR pcszPath)
  27. {
  28. HRESULT hr;
  29. DebugEntry(InternetShortcut::SetPath);
  30. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  31. ASSERT(IS_VALID_STRING_PTR(pcszPath, CSTR));
  32. // Treat path as literal URL.
  33. hr = SetURL(pcszPath, 0);
  34. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  35. DebugExitHRESULT(InternetShortcut::SetPath, hr);
  36. return(hr);
  37. }
  38. #pragma warning(disable:4100) /* "unreferenced formal parameter" warning */
  39. HRESULT STDMETHODCALLTYPE InternetShortcut::GetPath(PSTR pszFile,
  40. int ncFileBufLen,
  41. PWIN32_FIND_DATA pwfd,
  42. DWORD dwFlags)
  43. {
  44. HRESULT hr;
  45. DebugEntry(InternetShortcut::GetPath);
  46. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  47. ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszFile, STR, ncFileBufLen));
  48. ASSERT(NULL == pwfd || IS_VALID_STRUCT_PTR(pwfd, CWIN32_FIND_DATA));
  49. ASSERT(FLAGS_ARE_VALID(dwFlags, ALL_ISL_GETPATH_FLAGS));
  50. // Ignore dwFlags.
  51. if (pwfd)
  52. ZeroMemory(pwfd, sizeof(*pwfd));
  53. if (m_pszURL)
  54. {
  55. lstrcpyn(pszFile, m_pszURL, ncFileBufLen);
  56. hr = S_OK;
  57. }
  58. else
  59. {
  60. // No URL.
  61. if (ncFileBufLen > 0)
  62. *pszFile = '\0';
  63. hr = S_FALSE;
  64. }
  65. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  66. ASSERT((hr == S_OK &&
  67. (ncFileBufLen < 1 ||
  68. IS_VALID_STRING_PTR(pszFile, STR))) ||
  69. (hr == S_FALSE &&
  70. (ncFileBufLen < 1 ||
  71. ! *pszFile)));
  72. DebugExitHRESULT(InternetShortcut::GetPath, hr);
  73. return(hr);
  74. }
  75. HRESULT STDMETHODCALLTYPE InternetShortcut::SetRelativePath(
  76. PCSTR pcszRelativePath,
  77. DWORD dwReserved)
  78. {
  79. HRESULT hr;
  80. DebugEntry(InternetShortcut::SetRelativePath);
  81. // dwReserved may be any value.
  82. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  83. ASSERT(IS_VALID_STRING_PTR(pcszRelativePath, CSTR));
  84. hr = E_NOTIMPL;
  85. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  86. DebugExitHRESULT(InternetShortcut::SetRelativePath, hr);
  87. return(hr);
  88. }
  89. HRESULT STDMETHODCALLTYPE InternetShortcut::SetIDList(LPCITEMIDLIST pcidl)
  90. {
  91. HRESULT hr;
  92. DebugEntry(InternetShortcut::SetIDList);
  93. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  94. ASSERT(IS_VALID_STRUCT_PTR(pcidl, CITEMIDLIST));
  95. hr = E_NOTIMPL;
  96. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  97. DebugExitHRESULT(InternetShortcut::SetIDList, hr);
  98. return(hr);
  99. }
  100. #pragma warning(default:4100) /* "unreferenced formal parameter" warning */
  101. HRESULT STDMETHODCALLTYPE InternetShortcut::GetIDList(LPITEMIDLIST *ppidl)
  102. {
  103. HRESULT hr;
  104. DebugEntry(InternetShortcut::GetIDList);
  105. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  106. ASSERT(IS_VALID_WRITE_PTR(ppidl, PITEMIDLIST));
  107. *ppidl = NULL;
  108. hr = E_NOTIMPL;
  109. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  110. DebugExitHRESULT(InternetShortcut::GetIDList, hr);
  111. return(hr);
  112. }
  113. HRESULT STDMETHODCALLTYPE InternetShortcut::SetDescription(
  114. PCSTR pcszDescription)
  115. {
  116. HRESULT hr;
  117. BOOL bDifferent;
  118. PSTR pszFileCopy;
  119. DebugEntry(InternetShortcut::SetDescription);
  120. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  121. ASSERT(IS_VALID_STRING_PTR(pcszDescription, CSTR));
  122. // Set m_pszFile to description.
  123. bDifferent = (! m_pszFile ||
  124. lstrcmp(pcszDescription, m_pszFile) != 0);
  125. if (StringCopy(pcszDescription, &pszFileCopy))
  126. {
  127. if (m_pszFile)
  128. {
  129. delete m_pszFile;
  130. m_pszFile = NULL;
  131. }
  132. m_pszFile = pszFileCopy;
  133. if (bDifferent)
  134. Dirty(TRUE);
  135. hr = S_OK;
  136. }
  137. else
  138. hr = E_OUTOFMEMORY;
  139. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  140. DebugExitHRESULT(InternetShortcut::SetDescription, hr);
  141. return(hr);
  142. }
  143. HRESULT STDMETHODCALLTYPE InternetShortcut::GetDescription(
  144. PSTR pszDescription,
  145. int ncDesciptionBufLen)
  146. {
  147. HRESULT hr;
  148. DebugEntry(InternetShortcut::GetDescription);
  149. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  150. ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszDescription, STR, ncDesciptionBufLen));
  151. // Get description from m_pszFile.
  152. if (m_pszFile)
  153. lstrcpyn(pszDescription, m_pszFile, ncDesciptionBufLen);
  154. else
  155. {
  156. if (ncDesciptionBufLen > 0)
  157. pszDescription = '\0';
  158. }
  159. hr = S_OK;
  160. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  161. ASSERT(hr == S_OK &&
  162. (ncDesciptionBufLen <= 0 ||
  163. (IS_VALID_STRING_PTR(pszDescription, STR) &&
  164. EVAL(lstrlen(pszDescription) < ncDesciptionBufLen))));
  165. DebugExitHRESULT(InternetShortcut::GetDescription, hr);
  166. return(hr);
  167. }
  168. #pragma warning(disable:4100) /* "unreferenced formal parameter" warning */
  169. HRESULT STDMETHODCALLTYPE InternetShortcut::SetArguments(PCSTR pcszArgs)
  170. {
  171. HRESULT hr;
  172. DebugEntry(InternetShortcut::SetArguments);
  173. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  174. ASSERT(IS_VALID_STRING_PTR(pcszArgs, CSTR));
  175. hr = E_NOTIMPL;
  176. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  177. DebugExitHRESULT(InternetShortcut::SetArguments, hr);
  178. return(hr);
  179. }
  180. #pragma warning(default:4100) /* "unreferenced formal parameter" warning */
  181. HRESULT STDMETHODCALLTYPE InternetShortcut::GetArguments(PSTR pszArgs,
  182. int ncArgsBufLen)
  183. {
  184. HRESULT hr;
  185. DebugEntry(InternetShortcut::GetArguments);
  186. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  187. ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszArgs, STR, ncArgsBufLen));
  188. if (ncArgsBufLen > 0)
  189. *pszArgs = '\0';
  190. hr = E_NOTIMPL;
  191. WARNING_OUT(("InternetShortcut::GetArguments(): Arguments not maintained for CLSID_InternetShortcut."));
  192. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  193. DebugExitHRESULT(InternetShortcut::GetArguments, hr);
  194. return(hr);
  195. }
  196. HRESULT STDMETHODCALLTYPE InternetShortcut::SetWorkingDirectory(
  197. PCSTR pcszWorkingDirectory)
  198. {
  199. HRESULT hr = S_OK;
  200. char rgchNewPath[MAX_PATH_LEN];
  201. BOOL bChanged = FALSE;
  202. PSTR pszNewWorkingDirectory = NULL;
  203. DebugEntry(InternetShortcut::SetWorkingDirectory);
  204. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  205. ASSERT(! pcszWorkingDirectory ||
  206. IS_VALID_STRING_PTR(pcszWorkingDirectory, CSTR));
  207. if (! AnyMeat(pcszWorkingDirectory))
  208. pcszWorkingDirectory = NULL;
  209. if (pcszWorkingDirectory)
  210. {
  211. PSTR pszFileName;
  212. if (GetFullPathName(pcszWorkingDirectory, sizeof(rgchNewPath),
  213. rgchNewPath, &pszFileName) > 0)
  214. pcszWorkingDirectory = rgchNewPath;
  215. else
  216. hr = E_PATH_NOT_FOUND;
  217. }
  218. if (hr == S_OK)
  219. {
  220. bChanged = ! ((! pcszWorkingDirectory && ! m_pszWorkingDirectory) ||
  221. (pcszWorkingDirectory && m_pszWorkingDirectory &&
  222. ! lstrcmp(pcszWorkingDirectory, m_pszWorkingDirectory)));
  223. if (bChanged && pcszWorkingDirectory)
  224. {
  225. // (+ 1) for null terminator.
  226. pszNewWorkingDirectory = new(char[lstrlen(pcszWorkingDirectory) + 1]);
  227. if (pszNewWorkingDirectory)
  228. lstrcpy(pszNewWorkingDirectory, pcszWorkingDirectory);
  229. else
  230. hr = E_OUTOFMEMORY;
  231. }
  232. }
  233. if (hr == S_OK)
  234. {
  235. if (bChanged)
  236. {
  237. if (m_pszWorkingDirectory)
  238. delete m_pszWorkingDirectory;
  239. m_pszWorkingDirectory = pszNewWorkingDirectory;
  240. Dirty(TRUE);
  241. TRACE_OUT(("InternetShortcut::SetWorkingDirectory(): Set working directory to %s.",
  242. CHECK_STRING(m_pszWorkingDirectory)));
  243. }
  244. else
  245. TRACE_OUT(("InternetShortcut::SetWorkingDirectory(): Working directory already %s.",
  246. CHECK_STRING(m_pszWorkingDirectory)));
  247. }
  248. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  249. ASSERT(hr == S_OK ||
  250. hr == E_OUTOFMEMORY ||
  251. hr == E_PATH_NOT_FOUND);
  252. DebugExitHRESULT(InternetShortcut::SetWorkingDirectory, hr);
  253. return(hr);
  254. }
  255. HRESULT STDMETHODCALLTYPE InternetShortcut::GetWorkingDirectory(
  256. PSTR pszWorkingDirectory,
  257. int ncbWorkingDirectoryBufLen)
  258. {
  259. HRESULT hr;
  260. DebugEntry(InternetShortcut::GetWorkingDirectory);
  261. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  262. ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszWorkingDirectory, STR, ncbWorkingDirectoryBufLen));
  263. if (m_pszWorkingDirectory)
  264. {
  265. lstrcpyn(pszWorkingDirectory, m_pszWorkingDirectory,
  266. ncbWorkingDirectoryBufLen);
  267. hr = S_OK;
  268. }
  269. else
  270. {
  271. if (ncbWorkingDirectoryBufLen > 0)
  272. *pszWorkingDirectory = '\0';
  273. hr = S_FALSE;
  274. }
  275. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  276. ASSERT(IsValidPathResult(hr, pszWorkingDirectory, ncbWorkingDirectoryBufLen));
  277. ASSERT(hr == S_OK ||
  278. hr == S_FALSE);
  279. DebugExitHRESULT(InternetShortcut::GetWorkingDirectory, hr);
  280. return(hr);
  281. }
  282. HRESULT STDMETHODCALLTYPE InternetShortcut::SetHotkey(WORD wHotkey)
  283. {
  284. HRESULT hr;
  285. DebugEntry(InternetShortcut::SetHotkey);
  286. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  287. ASSERT(! wHotkey ||
  288. EVAL(IsValidHotkey(wHotkey)));
  289. if (wHotkey != m_wHotkey)
  290. Dirty(TRUE);
  291. m_wHotkey = wHotkey;
  292. hr = S_OK;
  293. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  294. DebugExitHRESULT(InternetShortcut::SetHotkey, hr);
  295. return(hr);
  296. }
  297. HRESULT STDMETHODCALLTYPE InternetShortcut::GetHotkey(PWORD pwHotkey)
  298. {
  299. HRESULT hr;
  300. DebugEntry(InternetShortcut::GetHotkey);
  301. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  302. ASSERT(IS_VALID_WRITE_PTR(pwHotkey, WORD));
  303. *pwHotkey = m_wHotkey;
  304. hr = S_OK;
  305. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  306. ASSERT(! *pwHotkey ||
  307. EVAL(IsValidHotkey(*pwHotkey)));
  308. DebugExitHRESULT(InternetShortcut::GetHotkey, hr);
  309. return(hr);
  310. }
  311. HRESULT STDMETHODCALLTYPE InternetShortcut::SetShowCmd(int nShowCmd)
  312. {
  313. HRESULT hr;
  314. DebugEntry(InternetShortcut::SetShowCmd);
  315. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  316. ASSERT(IsValidShowCmd(nShowCmd));
  317. if (nShowCmd != m_nShowCmd)
  318. {
  319. m_nShowCmd = nShowCmd;
  320. Dirty(TRUE);
  321. TRACE_OUT(("InternetShortcut::SetShowCmd(): Set show command to %d.",
  322. m_nShowCmd));
  323. }
  324. else
  325. TRACE_OUT(("InternetShortcut::SetShowCmd(): Show command already %d.",
  326. m_nShowCmd));
  327. hr = S_OK;
  328. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  329. ASSERT(hr == S_OK);
  330. DebugExitHRESULT(InternetShortcut::SetShowCmd, hr);
  331. return(hr);
  332. }
  333. HRESULT STDMETHODCALLTYPE InternetShortcut::GetShowCmd(PINT pnShowCmd)
  334. {
  335. HRESULT hr;
  336. DebugEntry(InternetShortcut::GetShowCmd);
  337. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  338. ASSERT(IS_VALID_WRITE_PTR(pnShowCmd, INT));
  339. *pnShowCmd = m_nShowCmd;
  340. hr = S_OK;
  341. ASSERT(IsValidShowCmd(m_nShowCmd));
  342. DebugExitHRESULT(InternetShortcut::GetShowCmd, hr);
  343. return(hr);
  344. }
  345. HRESULT STDMETHODCALLTYPE InternetShortcut::SetIconLocation(PCSTR pcszIconFile,
  346. int niIcon)
  347. {
  348. HRESULT hr = S_OK;
  349. BOOL bNewMeat;
  350. char rgchNewPath[MAX_PATH_LEN];
  351. DebugEntry(InternetShortcut::SetIconLocation);
  352. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  353. ASSERT(IsValidIconIndex(pcszIconFile ? S_OK : S_FALSE, pcszIconFile, MAX_PATH_LEN, niIcon));
  354. bNewMeat = AnyMeat(pcszIconFile);
  355. if (bNewMeat)
  356. hr = FullyQualifyPath(pcszIconFile, rgchNewPath, sizeof(rgchNewPath));
  357. if (hr == S_OK)
  358. {
  359. char rgchOldPath[MAX_PATH_LEN];
  360. int niOldIcon;
  361. UINT uFlags;
  362. hr = GetIconLocation(0, rgchOldPath, sizeof(rgchOldPath), &niOldIcon,
  363. &uFlags);
  364. if (SUCCEEDED(hr))
  365. {
  366. BOOL bOldMeat;
  367. BOOL bChanged = FALSE;
  368. PSTR pszNewIconFile = NULL;
  369. int niNewIcon = 0;
  370. bOldMeat = AnyMeat(rgchOldPath);
  371. ASSERT(! *rgchOldPath ||
  372. bOldMeat);
  373. bChanged = ((! bOldMeat && bNewMeat) ||
  374. (bOldMeat && ! bNewMeat) ||
  375. (bOldMeat && bNewMeat &&
  376. (lstrcmp(rgchOldPath, rgchNewPath) != 0 ||
  377. niIcon != niOldIcon)));
  378. if (bChanged && bNewMeat)
  379. {
  380. // (+ 1) for null terminator.
  381. pszNewIconFile = new(char[lstrlen(rgchNewPath) + 1]);
  382. if (pszNewIconFile)
  383. {
  384. lstrcpy(pszNewIconFile, rgchNewPath);
  385. niNewIcon = niIcon;
  386. hr = S_OK;
  387. }
  388. else
  389. hr = E_OUTOFMEMORY;
  390. }
  391. else
  392. hr = S_OK;
  393. if (hr == S_OK)
  394. {
  395. if (bChanged)
  396. {
  397. if (m_pszIconFile)
  398. delete m_pszIconFile;
  399. m_pszIconFile = pszNewIconFile;
  400. m_niIcon = niNewIcon;
  401. Dirty(TRUE);
  402. TRACE_OUT(("InternetShortcut::SetIconLocation(): Set icon location to %d in %s.",
  403. m_niIcon,
  404. CHECK_STRING(m_pszIconFile)));
  405. }
  406. else
  407. TRACE_OUT(("InternetShortcut::SetIconLocation(): Icon location already %d in %s.",
  408. m_niIcon,
  409. CHECK_STRING(m_pszIconFile)));
  410. }
  411. }
  412. }
  413. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  414. ASSERT(hr == S_OK ||
  415. hr == E_OUTOFMEMORY ||
  416. hr == E_FILE_NOT_FOUND);
  417. DebugExitHRESULT(InternetShortcut::SetIconLocation, hr);
  418. return(hr);
  419. }
  420. HRESULT STDMETHODCALLTYPE InternetShortcut::GetIconLocation(
  421. PSTR pszIconFile,
  422. int ncbIconFileBufLen,
  423. PINT pniIcon)
  424. {
  425. HRESULT hr;
  426. DebugEntry(InternetShortcut::GetIconLocation);
  427. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  428. ASSERT(IS_VALID_WRITE_BUFFER_PTR(pszIconFile, STR, ncbIconFileBufLen));
  429. ASSERT(IS_VALID_WRITE_PTR(pniIcon, int));
  430. if (m_pszIconFile)
  431. {
  432. lstrcpyn(pszIconFile, m_pszIconFile, ncbIconFileBufLen);
  433. *pniIcon = m_niIcon;
  434. hr = S_OK;
  435. }
  436. else
  437. {
  438. if (ncbIconFileBufLen > 0)
  439. *pszIconFile = '\0';
  440. *pniIcon = 0;
  441. hr = S_FALSE;
  442. }
  443. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  444. ASSERT(IsValidIconIndex(hr, pszIconFile, ncbIconFileBufLen, *pniIcon));
  445. DebugExitHRESULT(InternetShortcut::GetIconLocation, hr);
  446. return(hr);
  447. }
  448. #pragma warning(disable:4100) /* "unreferenced formal parameter" warning */
  449. HRESULT STDMETHODCALLTYPE InternetShortcut::Resolve(HWND hwnd, DWORD dwFlags)
  450. {
  451. HRESULT hr;
  452. DebugEntry(InternetShortcut::Resolve);
  453. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  454. ASSERT(IS_VALID_HANDLE(hwnd, WND));
  455. ASSERT(FLAGS_ARE_VALID(dwFlags, ALL_ISL_RESOLVE_FLAGS));
  456. hr = S_OK;
  457. WARNING_OUT(("InternetShortcut::Resolve(): This method is a NOP for CLSID_InternetShortcut."));
  458. ASSERT(IS_VALID_STRUCT_PTR(this, CInternetShortcut));
  459. DebugExitHRESULT(InternetShortcut::Resolve, hr);
  460. return(hr);
  461. }
  462. #pragma warning(default:4100) /* "unreferenced formal parameter" warning */