Leaked source code of windows server 2003
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.

551 lines
11 KiB

  1. /*
  2. * shlink.cpp - IShellLink implementation for CFusionShortcut class.
  3. */
  4. // note: BUGBUG?
  5. // from MSDN, it's unclear that for the GetX methods the len arguments
  6. // are counting the terminating NULL or not.
  7. // "size of the buffer pointed by szX"
  8. // so here, and other methods, assume they do -ie. wcslen(s) + L'\0'
  9. /* Headers
  10. **********/
  11. #include "project.hpp"
  12. /* Types
  13. ********/
  14. /*typedef enum isl_getpath_flags
  15. {
  16. // flag combinations
  17. ALL_ISL_GETPATH_FLAGS = (SLGP_SHORTPATH |
  18. SLGP_UNCPRIORITY)
  19. }
  20. ISL_GETPATH_FLAGS;*/
  21. /********************************** Methods **********************************/
  22. HRESULT STDMETHODCALLTYPE CFusionShortcut::SetPath(LPCWSTR pcwzPath)
  23. {
  24. HRESULT hr = S_OK;
  25. WCHAR rgchNewPath[MAX_PATH];
  26. BOOL bChanged = FALSE;
  27. LPWSTR pwzOriPath = (LPWSTR) pcwzPath; // still, pwzOriPath shouldn't be modified
  28. LPWSTR pwzFixedPath = NULL;
  29. ASSERT(! pwzOriPath)
  30. // ... this checks if all space in string...
  31. if (! AnyNonWhiteSpace(pwzOriPath))
  32. pwzOriPath = NULL;
  33. if (pwzOriPath)
  34. {
  35. LPWSTR pwzFileName;
  36. // this ignores "If the lpBuffer buffer is too small, the return value is the size
  37. // of the buffer, in WCHARs, required to hold the path"
  38. if (GetFullPathName(pwzOriPath, sizeof(rgchNewPath)/sizeof(WCHAR),
  39. rgchNewPath, &pwzFileName) > 0)
  40. pwzOriPath = rgchNewPath;
  41. else
  42. hr = GetLastWin32Error();
  43. }
  44. if (hr == S_OK)
  45. {
  46. bChanged = ! ((! pwzOriPath && ! m_pwzPath) ||
  47. (pwzOriPath && m_pwzPath &&
  48. ! wcscmp(pwzOriPath, m_pwzPath)));
  49. if (bChanged && pwzOriPath)
  50. {
  51. // (+ 1) for null terminator.
  52. pwzFixedPath = new(WCHAR[wcslen(pwzOriPath) + 1]);
  53. if (pwzFixedPath)
  54. wcscpy(pwzFixedPath, pwzOriPath);
  55. else
  56. hr = E_OUTOFMEMORY;
  57. }
  58. }
  59. if (hr == S_OK && bChanged)
  60. {
  61. if (m_pwzPath)
  62. delete [] m_pwzPath;
  63. m_pwzPath = pwzFixedPath;
  64. Dirty(TRUE);
  65. }
  66. ASSERT(hr == S_OK || FAILED(hr));
  67. return(hr);
  68. }
  69. HRESULT STDMETHODCALLTYPE CFusionShortcut::GetPath(LPWSTR pwzFile,
  70. int ncFileBufLen,
  71. PWIN32_FIND_DATA pwfd,
  72. DWORD dwFlags)
  73. {
  74. HRESULT hr = S_OK;
  75. ASSERT(NULL == pwfd);
  76. // Ignore dwFlags.
  77. if (pwfd)
  78. ZeroMemory(pwfd, sizeof(*pwfd));
  79. if (m_pwzPath)
  80. {
  81. if (pwzFile == NULL || ncFileBufLen <= 0)
  82. hr = E_INVALIDARG;
  83. else
  84. {
  85. wcsncpy(pwzFile, m_pwzPath, ncFileBufLen-1);
  86. pwzFile[ncFileBufLen-1] = L'\0';
  87. }
  88. }
  89. else
  90. {
  91. if (ncFileBufLen > 0 && pwzFile != NULL)
  92. *pwzFile = L'\0';
  93. hr = S_FALSE;
  94. }
  95. ASSERT((hr == S_OK && ncFileBufLen < 1) ||
  96. (hr == S_FALSE &&
  97. (ncFileBufLen < 1 || ! *pwzFile)));
  98. return(hr);
  99. }
  100. HRESULT STDMETHODCALLTYPE CFusionShortcut::SetRelativePath(LPCWSTR pcwzRelativePath,
  101. DWORD dwReserved)
  102. {
  103. HRESULT hr;
  104. // dwReserved may be any value.
  105. hr = E_NOTIMPL;
  106. return(hr);
  107. }
  108. HRESULT STDMETHODCALLTYPE CFusionShortcut::SetIDList(LPCITEMIDLIST pcidl)
  109. {
  110. HRESULT hr;
  111. hr = E_NOTIMPL;
  112. return(hr);
  113. }
  114. HRESULT STDMETHODCALLTYPE CFusionShortcut::GetIDList(LPITEMIDLIST *ppidl)
  115. {
  116. HRESULT hr;
  117. if (ppidl != NULL)
  118. *ppidl = NULL;
  119. hr = E_NOTIMPL;
  120. return(hr);
  121. }
  122. HRESULT STDMETHODCALLTYPE CFusionShortcut::SetDescription(LPCWSTR pcwzDescription)
  123. {
  124. HRESULT hr = S_OK;
  125. BOOL bDifferent;
  126. LPWSTR pwzNewDesc = NULL;
  127. // Set m_pwzDesc to description.
  128. bDifferent = ! ((! pcwzDescription && ! m_pwzDesc) ||
  129. (pcwzDescription && m_pwzDesc &&
  130. ! wcscmp(pcwzDescription, m_pwzDesc)));
  131. if (bDifferent && pcwzDescription)
  132. {
  133. // (+ 1) for null terminator.
  134. pwzNewDesc = new(WCHAR[wcslen(pcwzDescription) + 1]);
  135. if (pwzNewDesc)
  136. wcscpy(pwzNewDesc, pcwzDescription);
  137. else
  138. hr = E_OUTOFMEMORY;
  139. }
  140. if (hr == S_OK && bDifferent)
  141. {
  142. if (m_pwzDesc)
  143. delete [] m_pwzDesc;
  144. m_pwzDesc = pwzNewDesc;
  145. Dirty(TRUE);
  146. }
  147. return(hr);
  148. }
  149. HRESULT STDMETHODCALLTYPE CFusionShortcut::GetDescription(LPWSTR pwzDescription,
  150. int ncDesciptionBufLen)
  151. {
  152. HRESULT hr = S_OK;
  153. // Get description from m_pwzDesc.
  154. if (m_pwzDesc)
  155. {
  156. if (pwzDescription == NULL || ncDesciptionBufLen <= 0)
  157. hr = E_INVALIDARG;
  158. else
  159. {
  160. wcsncpy(pwzDescription, m_pwzDesc, ncDesciptionBufLen-1);
  161. pwzDescription[ncDesciptionBufLen-1] = L'\0';
  162. }
  163. }
  164. else
  165. {
  166. if (ncDesciptionBufLen > 0 && pwzDescription != NULL)
  167. pwzDescription = L'\0';
  168. }
  169. ASSERT(hr == S_OK &&
  170. (ncDesciptionBufLen <= 0 ||
  171. EVAL(wcslen(pwzDescription) < ncDesciptionBufLen)));
  172. return(hr);
  173. }
  174. HRESULT STDMETHODCALLTYPE CFusionShortcut::SetArguments(LPCWSTR pcwzArgs)
  175. {
  176. HRESULT hr;
  177. hr = E_NOTIMPL;
  178. return(hr);
  179. }
  180. HRESULT STDMETHODCALLTYPE CFusionShortcut::GetArguments(LPWSTR pwzArgs,
  181. int ncArgsBufLen)
  182. {
  183. HRESULT hr;
  184. if (ncArgsBufLen > 0 && pwzArgs != NULL)
  185. *pwzArgs = L'\0';
  186. hr = E_NOTIMPL;
  187. return(hr);
  188. }
  189. HRESULT STDMETHODCALLTYPE CFusionShortcut::SetWorkingDirectory(LPCWSTR pcwzWorkingDirectory)
  190. {
  191. HRESULT hr = S_OK;
  192. WCHAR rgchNewPath[MAX_PATH];
  193. BOOL bChanged = FALSE;
  194. LPWSTR pwzOriWorkingDirectory = (LPWSTR) pcwzWorkingDirectory; // still, pwzOriWorkingDirectory shouldn't be modified
  195. LPWSTR pwzFixedWorkingDirectory = NULL;
  196. ASSERT(! pwzOriWorkingDirectory)
  197. // ... this checks if all space in string...
  198. if (! AnyNonWhiteSpace(pwzOriWorkingDirectory))
  199. pwzOriWorkingDirectory = NULL;
  200. if (pwzOriWorkingDirectory)
  201. {
  202. LPWSTR pwzFileName;
  203. // this ignores "If the lpBuffer buffer is too small, the return value is the size
  204. // of the buffer, in WCHARs, required to hold the path"
  205. if (GetFullPathName(pwzOriWorkingDirectory, sizeof(rgchNewPath)/sizeof(WCHAR),
  206. rgchNewPath, &pwzFileName) > 0)
  207. pwzOriWorkingDirectory = rgchNewPath;
  208. else
  209. hr = GetLastWin32Error();
  210. }
  211. if (hr == S_OK)
  212. {
  213. bChanged = ! ((! pwzOriWorkingDirectory && ! m_pwzWorkingDirectory) ||
  214. (pwzOriWorkingDirectory && m_pwzWorkingDirectory &&
  215. ! wcscmp(pwzOriWorkingDirectory, m_pwzWorkingDirectory)));
  216. if (bChanged && pwzOriWorkingDirectory)
  217. {
  218. // (+ 1) for null terminator.
  219. pwzFixedWorkingDirectory = new(WCHAR[wcslen(pwzOriWorkingDirectory) + 1]);
  220. if (pwzFixedWorkingDirectory)
  221. wcscpy(pwzFixedWorkingDirectory, pwzOriWorkingDirectory);
  222. else
  223. hr = E_OUTOFMEMORY;
  224. }
  225. }
  226. if (hr == S_OK && bChanged)
  227. {
  228. if (m_pwzWorkingDirectory)
  229. delete [] m_pwzWorkingDirectory;
  230. m_pwzWorkingDirectory = pwzFixedWorkingDirectory;
  231. Dirty(TRUE);
  232. }
  233. ASSERT(hr == S_OK || FAILED(hr));
  234. return(hr);
  235. }
  236. HRESULT STDMETHODCALLTYPE CFusionShortcut::GetWorkingDirectory(LPWSTR pwzWorkingDirectory,
  237. int ncbWorkingDirectoryBufLen)
  238. {
  239. HRESULT hr = S_OK;
  240. if (m_pwzWorkingDirectory)
  241. {
  242. if (pwzWorkingDirectory == NULL || ncbWorkingDirectoryBufLen <= 0)
  243. hr = E_INVALIDARG;
  244. else
  245. {
  246. wcsncpy(pwzWorkingDirectory, m_pwzWorkingDirectory,
  247. ncbWorkingDirectoryBufLen-1);
  248. pwzWorkingDirectory[ncbWorkingDirectoryBufLen-1] = L'\0';
  249. }
  250. }
  251. else
  252. {
  253. if (ncbWorkingDirectoryBufLen > 0 && pwzWorkingDirectory != NULL)
  254. *pwzWorkingDirectory = L'\0';
  255. hr = S_FALSE;
  256. }
  257. ASSERT(IsValidPathResult(hr, pwzWorkingDirectory, ncbWorkingDirectoryBufLen));
  258. ASSERT(hr == S_OK ||
  259. hr == S_FALSE);
  260. return(hr);
  261. }
  262. HRESULT STDMETHODCALLTYPE CFusionShortcut::SetHotkey(WORD wHotkey)
  263. {
  264. HRESULT hr=S_OK;
  265. ASSERT(! wHotkey)
  266. if (wHotkey != m_wHotkey)
  267. {
  268. m_wHotkey = wHotkey;
  269. Dirty(TRUE);
  270. }
  271. return(hr);
  272. }
  273. HRESULT STDMETHODCALLTYPE CFusionShortcut::GetHotkey(PWORD pwHotkey)
  274. {
  275. HRESULT hr=S_OK;
  276. if (pwHotkey == NULL)
  277. hr = E_INVALIDARG;
  278. else
  279. *pwHotkey = m_wHotkey;
  280. ASSERT(! *pwHotkey)
  281. return(hr);
  282. }
  283. HRESULT STDMETHODCALLTYPE CFusionShortcut::SetShowCmd(int nShowCmd)
  284. {
  285. HRESULT hr=S_OK;
  286. ASSERT(IsValidShowCmd(nShowCmd));
  287. if (nShowCmd != m_nShowCmd)
  288. {
  289. m_nShowCmd = nShowCmd;
  290. Dirty(TRUE);
  291. }
  292. return(hr);
  293. }
  294. HRESULT STDMETHODCALLTYPE CFusionShortcut::GetShowCmd(PINT pnShowCmd)
  295. {
  296. HRESULT hr=S_OK;
  297. if (pnShowCmd == NULL)
  298. hr = E_INVALIDARG;
  299. else
  300. *pnShowCmd = m_nShowCmd;
  301. ASSERT(IsValidShowCmd(m_nShowCmd));
  302. return(hr);
  303. }
  304. HRESULT STDMETHODCALLTYPE CFusionShortcut::SetIconLocation(LPCWSTR pcwzIconFile,
  305. int niIcon)
  306. {
  307. HRESULT hr = S_OK;
  308. BOOL bNewNonWhiteSpace;
  309. ASSERT(IsValidIconIndex(pcwzIconFile ? S_OK : S_FALSE, pcwzIconFile, MAX_PATH, niIcon));
  310. bNewNonWhiteSpace = AnyNonWhiteSpace(pcwzIconFile);
  311. if (hr == S_OK)
  312. {
  313. WCHAR rgchOldPath[MAX_PATH];
  314. int niOldIcon;
  315. UINT uFlags;
  316. hr = GetIconLocation(0, rgchOldPath, sizeof(rgchOldPath)/sizeof(WCHAR), &niOldIcon,
  317. &uFlags);
  318. // should this continue even if there's error getting icon location??
  319. if (SUCCEEDED(hr))
  320. {
  321. BOOL bOldNonWhiteSpace;
  322. BOOL bChanged = FALSE;
  323. LPWSTR pwzNewIconFile = NULL;
  324. int niNewIcon = 0;
  325. bOldNonWhiteSpace = AnyNonWhiteSpace(rgchOldPath);
  326. ASSERT(! *rgchOldPath || bOldNonWhiteSpace);
  327. // check
  328. bChanged = ((! bOldNonWhiteSpace && bNewNonWhiteSpace) ||
  329. (bOldNonWhiteSpace && ! bNewNonWhiteSpace) ||
  330. (bOldNonWhiteSpace && bNewNonWhiteSpace &&
  331. (wcscmp(rgchOldPath, pcwzIconFile) != 0 ||
  332. niIcon != niOldIcon)));
  333. // clear hr
  334. hr = S_OK;
  335. if (bChanged && bNewNonWhiteSpace)
  336. {
  337. // (+ 1) for null terminator.
  338. // BUGBUG: slightly not optimize as it makes a copy even if only the index changes
  339. pwzNewIconFile = new(WCHAR[wcslen(pcwzIconFile) + 1]);
  340. if (pwzNewIconFile)
  341. {
  342. wcscpy(pwzNewIconFile, pcwzIconFile);
  343. niNewIcon = niIcon;
  344. }
  345. else
  346. hr = E_OUTOFMEMORY;
  347. }
  348. if (hr == S_OK && bChanged)
  349. {
  350. if (m_pwzIconFile)
  351. delete [] m_pwzIconFile;
  352. m_pwzIconFile = pwzNewIconFile;
  353. m_niIcon = niNewIcon;
  354. Dirty(TRUE);
  355. }
  356. }
  357. }
  358. ASSERT(hr == S_OK ||
  359. hr == E_OUTOFMEMORY ||
  360. hr == E_FILE_NOT_FOUND);
  361. return(hr);
  362. }
  363. HRESULT STDMETHODCALLTYPE CFusionShortcut::GetIconLocation(LPWSTR pwzIconFile,
  364. int ncbIconFileBufLen,
  365. PINT pniIcon)
  366. {
  367. HRESULT hr=S_OK;
  368. // this ignores icon index (even if set) if icon file path is not
  369. if (m_pwzIconFile)
  370. {
  371. if (pwzIconFile == NULL || ncbIconFileBufLen <= 0)
  372. hr = E_INVALIDARG;
  373. else
  374. {
  375. wcsncpy(pwzIconFile, m_pwzIconFile, ncbIconFileBufLen-1);
  376. pwzIconFile[ncbIconFileBufLen-1] = L'\0';
  377. if (pniIcon == NULL)
  378. hr = E_INVALIDARG;
  379. else
  380. *pniIcon = m_niIcon;
  381. }
  382. }
  383. else
  384. {
  385. if (ncbIconFileBufLen > 0 && pwzIconFile != NULL)
  386. *pwzIconFile = L'\0';
  387. if (pniIcon != NULL)
  388. *pniIcon = 0;
  389. hr = S_FALSE;
  390. }
  391. ASSERT(IsValidIconIndex(hr, pwzIconFile, ncbIconFileBufLen, *pniIcon));
  392. return(hr);
  393. }
  394. HRESULT STDMETHODCALLTYPE CFusionShortcut::Resolve(HWND hwnd, DWORD dwFlags)
  395. {
  396. HRESULT hr;
  397. ASSERT(IS_VALID_HANDLE(hwnd, WND));
  398. // BUGBUG?: check dwFlags
  399. hr = S_OK;
  400. // BUGBUG?: should this check the shortcut and do the UI/update/save?
  401. return(hr);
  402. }