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.

513 lines
11 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. Shortcut.cpp
  5. Abstract:
  6. Implementation of the IShellLink wrapper class.
  7. Notes:
  8. ANSI & Unicode via TCHAR - runs on Win9x/NT/2K/XP etc.
  9. History:
  10. 01/29/2001 rparsons Created
  11. 01/10/2002 rparsons Revised
  12. 01/27/2002 rparsons Converted to TCHAR
  13. --*/
  14. #include "shortcut.h"
  15. /*++
  16. Routine Description:
  17. Creates a shortcut given a CSIDL.
  18. Arguments:
  19. pszFileNamePath - Name and path of the file that the shortcut points to.
  20. pszDisplayName - Shortcut display text.
  21. pszArguments - Arguments to be passed to the program.
  22. pszStartIn - The start-in directory for the program.
  23. nCmdShow - Dictates how the program will be displayed.
  24. nFolder - CSIDL that dictates where to place the shortcut.
  25. Return Value:
  26. S_OK on success, a failure code otherwise.
  27. --*/
  28. HRESULT
  29. CShortcut::CreateShortcut(
  30. IN LPCTSTR pszFileNamePath,
  31. IN LPTSTR pszDisplayName,
  32. IN LPCTSTR pszArguments OPTIONAL,
  33. IN LPCTSTR pszStartIn OPTIONAL,
  34. IN int nCmdShow,
  35. IN int nFolder
  36. )
  37. {
  38. HRESULT hr;
  39. TCHAR szDestFolder[MAX_PATH];
  40. TCHAR szLocation[MAX_PATH];
  41. if (!pszFileNamePath || !pszDisplayName) {
  42. return E_INVALIDARG;
  43. }
  44. hr = SHGetFolderPath(NULL, nFolder, NULL, SHGFP_TYPE_CURRENT, szDestFolder);
  45. if (FAILED(hr)) {
  46. return hr;
  47. }
  48. hr = StringCchPrintf(szLocation,
  49. ARRAYSIZE(szLocation),
  50. "%s\\%s.lnk",
  51. szDestFolder,
  52. pszDisplayName);
  53. if (FAILED(hr)) {
  54. return hr;
  55. }
  56. //
  57. // Call the function to do the work of creating the shortcut.
  58. //
  59. hr = BuildShortcut(pszFileNamePath,
  60. pszArguments,
  61. szLocation,
  62. pszStartIn,
  63. nCmdShow);
  64. return hr;
  65. }
  66. /*++
  67. Routine Description:
  68. Creates a shortcut given a path.
  69. Arguments:
  70. lpLnkDirectory - Path that will contain the shortcut
  71. lpFileNamePath - Name and path of the file that the shortcut points to
  72. lpDisplayName - Shortcut display text
  73. lpArguments - Arguments to be passed to the program
  74. lpStartIn - The start-in directory for the program
  75. nCmdShow - Dictates how the program will be displayed
  76. Return Value:
  77. Calls BuildShortcut which returns an HRESULT.
  78. --*/
  79. HRESULT
  80. CShortcut::CreateShortcut(
  81. IN LPCTSTR pszLnkDirectory,
  82. IN LPCTSTR pszFileNamePath,
  83. IN LPTSTR pszDisplayName,
  84. IN LPCTSTR pszArguments OPTIONAL,
  85. IN LPCTSTR pszStartIn OPTIONAL,
  86. IN int nCmdShow
  87. )
  88. {
  89. HRESULT hr;
  90. TCHAR szLocation[MAX_PATH];
  91. if (!pszLnkDirectory || !pszFileNamePath || !pszDisplayName) {
  92. return E_INVALIDARG;
  93. }
  94. hr = StringCchPrintf(szLocation,
  95. ARRAYSIZE(szLocation),
  96. "%s\\%s.lnk",
  97. pszLnkDirectory,
  98. pszDisplayName);
  99. if (FAILED(hr)) {
  100. return hr;
  101. }
  102. //
  103. // Call the function to do the work of creating the shortcut.
  104. //
  105. return BuildShortcut(pszFileNamePath,
  106. pszArguments,
  107. szLocation,
  108. pszStartIn,
  109. nCmdShow);
  110. }
  111. /*++
  112. Routine Description:
  113. Does the work of actually creating the shortcut.
  114. Arguments:
  115. pszPath - Path that the shortcut points to.
  116. pszArguments - Arguments to be passed to the program.
  117. pszLocation - Location of the shortcut and it's name.
  118. pszWorkingDir - The start-in directory for the program.
  119. nCmdShow - Dictates how the program will be displayed.
  120. Return Value:
  121. S_OK on success, an HRESULT code on failure.
  122. --*/
  123. HRESULT
  124. CShortcut::BuildShortcut(
  125. IN LPCTSTR pszPath,
  126. IN LPCTSTR pszArguments OPTIONAL,
  127. IN LPCTSTR pszLocation,
  128. IN LPCTSTR pszWorkingDir OPTIONAL,
  129. IN int nCmdShow
  130. )
  131. {
  132. IShellLink* pisl = NULL;
  133. IPersistFile* pipf = NULL;
  134. HRESULT hr = E_FAIL;
  135. WCHAR wszLocation[MAX_PATH];
  136. if (!pszPath || !pszLocation) {
  137. return E_INVALIDARG;
  138. }
  139. //
  140. // Load the COM libraries.
  141. //
  142. hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
  143. if (FAILED(hr)) {
  144. return hr;
  145. }
  146. //
  147. // Get an IShellLink interface pointer.
  148. //
  149. hr = CoCreateInstance(CLSID_ShellLink,
  150. NULL,
  151. CLSCTX_INPROC_SERVER,
  152. IID_IShellLink,
  153. (LPVOID*)&pisl);
  154. if (FAILED(hr)) {
  155. goto exit;
  156. }
  157. //
  158. // Get an IPersistFile interface pointer.
  159. //
  160. hr = pisl->QueryInterface(IID_IPersistFile, (LPVOID*)&pipf);
  161. if (FAILED(hr)) {
  162. goto exit;
  163. }
  164. //
  165. // Set the path to the shortcut.
  166. //
  167. hr = pisl->SetPath(pszPath);
  168. if (FAILED(hr)) {
  169. goto exit;
  170. }
  171. //
  172. // Set the arguments for the shortcut.
  173. //
  174. if (pszArguments) {
  175. hr = pisl->SetArguments(pszArguments);
  176. if (FAILED(hr)) {
  177. goto exit;
  178. }
  179. }
  180. //
  181. // Set the working directory.
  182. //
  183. if (pszWorkingDir) {
  184. hr = pisl->SetWorkingDirectory(pszWorkingDir);
  185. if (FAILED(hr)) {
  186. goto exit;
  187. }
  188. }
  189. //
  190. // Set the show flag.
  191. //
  192. hr = pisl->SetShowCmd(nCmdShow);
  193. if (FAILED(hr)) {
  194. goto exit;
  195. }
  196. //
  197. // Convert from ANSI to UNICODE prior to the save.
  198. //
  199. #ifndef UNICODE
  200. if (!MultiByteToWideChar(CP_ACP,
  201. 0,
  202. pszLocation,
  203. -1,
  204. wszLocation,
  205. MAX_PATH)) {
  206. hr = E_FAIL;
  207. goto exit;
  208. }
  209. #else
  210. wcsncpy(wszLocation, pszLocation, MAX_PATH);
  211. #endif // UNICODE
  212. //
  213. // Write the shortcut to disk.
  214. //
  215. hr = pipf->Save(wszLocation, TRUE);
  216. if (FAILED(hr)) {
  217. goto exit;
  218. }
  219. exit:
  220. if (pisl) {
  221. pisl->Release();
  222. }
  223. if (pipf) {
  224. pipf->Release();
  225. }
  226. CoUninitialize();
  227. return hr;
  228. }
  229. /*++
  230. Routine Description:
  231. Creates a group on the start menu.
  232. Arguments:
  233. pszGroupName - Name of the group.
  234. fAllUsers - A flag to indicate if the group should
  235. appear in the All Users folder. If false,
  236. the group is created in the private user's folder.
  237. Return Value:
  238. S_OK on success, an HRESULT code on failure.
  239. --*/
  240. HRESULT
  241. CShortcut::CreateGroup(
  242. IN LPCTSTR pszGroupName,
  243. IN BOOL fAllUsers
  244. )
  245. {
  246. LPITEMIDLIST pidl;
  247. TCHAR szProgramPath[MAX_PATH];
  248. TCHAR szGroupPath[MAX_PATH];
  249. BOOL bReturn = FALSE;
  250. HRESULT hr;
  251. if (!pszGroupName) {
  252. return E_INVALIDARG;
  253. }
  254. //
  255. // Get the PIDL for the Programs folder in the shell namespace
  256. //
  257. hr = SHGetSpecialFolderLocation(NULL,
  258. fAllUsers ? CSIDL_COMMON_PROGRAMS : CSIDL_PROGRAMS,
  259. &pidl);
  260. if (FAILED(hr)) {
  261. return hr;
  262. }
  263. //
  264. // Get the path associated with the PIDL.
  265. //
  266. bReturn = SHGetPathFromIDList(pidl, szProgramPath);
  267. if (!bReturn) {
  268. goto exit;
  269. }
  270. //
  271. // Build the path for the new group.
  272. //
  273. hr = StringCchPrintf(szGroupPath,
  274. ARRAYSIZE(szGroupPath),
  275. "%s\\%s",
  276. szProgramPath,
  277. pszGroupName);
  278. if (FAILED(hr)) {
  279. goto exit;
  280. }
  281. //
  282. // Create the directory (group) where shortcuts will reside.
  283. //
  284. if (!CreateDirectory(szGroupPath, NULL)) {
  285. goto exit;
  286. }
  287. //
  288. // Tell the shell that we changed something.
  289. //
  290. SHChangeNotify(SHCNE_MKDIR,
  291. SHCNF_PATH,
  292. (LPVOID)szGroupPath,
  293. 0);
  294. hr = S_OK;
  295. exit:
  296. if (pidl) {
  297. CoTaskMemFree((LPVOID)pidl);
  298. }
  299. return hr;
  300. }
  301. /*++
  302. Routine Description:
  303. Sets arguments for a given shortcut.
  304. Arguments:
  305. pszFileName - Name of the file to set the arguments for.
  306. pszArguments - Arguments to apply to file.
  307. Return Value:
  308. S_OK on success, an HRESULT code on failure.
  309. --*/
  310. HRESULT
  311. CShortcut::SetArguments(
  312. IN LPTSTR pszFileName,
  313. IN LPTSTR pszArguments
  314. )
  315. {
  316. IShellLink* pisl = NULL;
  317. IPersistFile* pipf = NULL;
  318. HRESULT hr = E_FAIL;
  319. WCHAR wszFileName[MAX_PATH];
  320. if (!pszFileName || !pszArguments) {
  321. return E_INVALIDARG;
  322. }
  323. //
  324. // Load the COM libraries.
  325. //
  326. hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
  327. if (FAILED(hr)) {
  328. return hr;
  329. }
  330. //
  331. // Get an IShellLink interface pointer.
  332. //
  333. hr = CoCreateInstance(CLSID_ShellLink,
  334. NULL,
  335. CLSCTX_INPROC_SERVER,
  336. IID_IShellLink,
  337. (LPVOID*)&pisl);
  338. if (FAILED(hr)) {
  339. goto exit;
  340. }
  341. //
  342. // Get an IPersistFile interface pointer.
  343. //
  344. hr = pisl->QueryInterface(IID_IPersistFile, (LPVOID*)&pipf);
  345. if (FAILED(hr)) {
  346. goto exit;
  347. }
  348. //
  349. // Convert from ANSI to UNICODE.
  350. //
  351. #ifndef UNICODE
  352. if (!MultiByteToWideChar(CP_ACP,
  353. 0,
  354. pszFileName,
  355. -1,
  356. wszFileName,
  357. MAX_PATH)) {
  358. hr = E_FAIL;
  359. goto exit;
  360. }
  361. #else
  362. wcsncpy(wszFileName, pszFileName, MAX_PATH);
  363. #endif
  364. //
  365. // Load the shortcut so we can change it.
  366. //
  367. hr = pipf->Load(wszFileName, STGM_READWRITE);
  368. if (FAILED(hr)) {
  369. goto exit;
  370. }
  371. //
  372. // Set the arguments.
  373. //
  374. hr = pisl->SetArguments(pszArguments);
  375. if (FAILED(hr)) {
  376. goto exit;
  377. }
  378. //
  379. // Save the shortcut back to disk.
  380. //
  381. hr = pipf->Save(wszFileName, TRUE);
  382. if (FAILED(hr)) {
  383. goto exit;
  384. }
  385. exit:
  386. if (pisl) {
  387. pisl->Release();
  388. }
  389. if (pipf) {
  390. pipf->Release();
  391. }
  392. CoUninitialize();
  393. return hr;
  394. }