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.

219 lines
7.0 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: S h o r t C u t . C P P
  7. //
  8. // Contents: Creates shortcuts.
  9. //
  10. // Notes:
  11. //
  12. // Author: scottbri 19 June 1998
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "pch.h"
  16. #pragma hdrstop
  17. #include "foldinc.h" // Standard shell\folder includes
  18. extern const WCHAR c_szBackslash[];
  19. const WCHAR c_szLinkExt[] = L".lnk";
  20. const WCHAR c_szVersionFormat[] = L" %d";
  21. //
  22. // Function: HrGenerateLinkName
  23. //
  24. // Purpose: Combine the link path, name, and extension and verify the file
  25. // doesn't already exist.
  26. //
  27. // Parameters: pstrNew [OUT] - The name and path of the .lnk shortcut
  28. // pszPath [IN] - The directory path for the link
  29. // pszConnName [IN] - The connection name itself
  30. //
  31. // Returns: HRESULT, S_OK on success, an error if the file will not be created
  32. //
  33. HRESULT HrGenerateLinkName(OUT tstring * pstrNew, IN PCWSTR pszPath, IN PCWSTR pszConnName)
  34. {
  35. HRESULT hr = S_OK;
  36. tstring str;
  37. DWORD dwCnt = 0;
  38. do
  39. {
  40. // prepend the string with \\?\ so CreateFile will use a name buffer
  41. // larger than MAX_PATH
  42. str = L"\\\\?\\";
  43. str += pszPath;
  44. str += c_szBackslash;
  45. str += pszConnName;
  46. if (++dwCnt>1)
  47. {
  48. WCHAR szBuf[10];
  49. wsprintfW(szBuf, c_szVersionFormat, dwCnt);
  50. str += szBuf;
  51. }
  52. str += c_szLinkExt;
  53. HANDLE hFile = CreateFile(str.c_str(), GENERIC_READ, FILE_SHARE_READ,
  54. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  55. if (INVALID_HANDLE_VALUE == hFile)
  56. {
  57. hr = HRESULT_FROM_WIN32(GetLastError());
  58. if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
  59. {
  60. hr = S_OK; // Filename is unique
  61. }
  62. }
  63. else
  64. {
  65. CloseHandle(hFile);
  66. hr = HRESULT_FROM_WIN32(ERROR_DUP_NAME);
  67. }
  68. } while (HRESULT_FROM_WIN32(ERROR_DUP_NAME) == hr);
  69. if (SUCCEEDED(hr))
  70. {
  71. *pstrNew = str.c_str();
  72. }
  73. return hr;
  74. }
  75. //
  76. // Function: HrCreateStartMenuShortCut
  77. //
  78. // Purpose: Create a shortcut to a connection in the start menu
  79. //
  80. // Parameters: hwndParent [IN] - Handle to a parent window
  81. // fAllUser [IN] - Create the connection for all users
  82. // pwszName [IN] - The connection name
  83. // pConn [IN] - Connection for which the shortcut is created
  84. //
  85. // Returns: BOOL, TRUE
  86. //
  87. HRESULT HrCreateStartMenuShortCut(IN HWND hwndParent,
  88. IN BOOL fAllUsers,
  89. IN PCWSTR pszName,
  90. IN INetConnection * pConn)
  91. {
  92. HRESULT hr = S_OK;
  93. PCONFOLDPIDL pidl;
  94. PCONFOLDPIDLFOLDER pidlFolder;
  95. LPSHELLFOLDER psfConnections = NULL;
  96. if ((NULL == pConn) || (NULL == pszName))
  97. {
  98. hr = E_INVALIDARG;
  99. goto Error;
  100. }
  101. // Create a pidl for the connection
  102. //
  103. hr = HrCreateConFoldPidl(WIZARD_NOT_WIZARD, pConn, pidl);
  104. if (SUCCEEDED(hr))
  105. {
  106. // Get the pidl for the Connections Folder
  107. //
  108. hr = HrGetConnectionsFolderPidl(pidlFolder);
  109. if (SUCCEEDED(hr))
  110. {
  111. // Get the Connections Folder object
  112. //
  113. hr = HrGetConnectionsIShellFolder(pidlFolder, &psfConnections);
  114. if (SUCCEEDED(hr))
  115. {
  116. tstring str;
  117. WCHAR szPath[MAX_PATH + 1] = {0};
  118. // Find the location to stash the shortcut
  119. //
  120. if (!SHGetSpecialFolderPath(hwndParent, szPath,
  121. (fAllUsers ? CSIDL_COMMON_DESKTOPDIRECTORY :
  122. CSIDL_DESKTOPDIRECTORY), FALSE))
  123. {
  124. hr = HrFromLastWin32Error();
  125. }
  126. else if (SUCCEEDED(hr) && wcslen(szPath))
  127. {
  128. LPITEMIDLIST pidlFull;
  129. // Combine the folder and connections pidl into a
  130. // fully qualified pidl.
  131. //
  132. pidlFull = ILCombine(pidlFolder.GetItemIdList(), pidl.GetItemIdList());
  133. if (pidlFull)
  134. {
  135. IShellLink *psl = NULL;
  136. hr = CoCreateInstance(
  137. CLSID_ShellLink,
  138. NULL,
  139. CLSCTX_INPROC_SERVER | CLSCTX_NO_CODE_DOWNLOAD,
  140. IID_IShellLink,
  141. (LPVOID*)&psl);
  142. if (SUCCEEDED(hr))
  143. {
  144. IPersistFile *ppf = NULL;
  145. // Set the combined IDL
  146. //
  147. hr = psl->SetIDList(pidlFull);
  148. if (SUCCEEDED(hr))
  149. {
  150. hr = psl->QueryInterface(IID_IPersistFile,
  151. (LPVOID *)&ppf);
  152. if (SUCCEEDED(hr))
  153. {
  154. tstring strPath;
  155. // Generate the lnk filename
  156. //
  157. hr = HrGenerateLinkName(&strPath,
  158. szPath,
  159. pszName);
  160. if (SUCCEEDED(hr))
  161. {
  162. // Create the link file.
  163. //
  164. hr = ppf->Save(strPath.c_str(), TRUE);
  165. }
  166. ReleaseObj(ppf);
  167. }
  168. }
  169. ReleaseObj(psl);
  170. }
  171. if (pidlFull)
  172. {
  173. FreeIDL(pidlFull);
  174. }
  175. }
  176. else
  177. {
  178. hr = E_OUTOFMEMORY;
  179. }
  180. }
  181. else
  182. {
  183. TraceError("HrCreateStartMenuShortCut - Unable to find Start Menu save location", hr);
  184. }
  185. ReleaseObj(psfConnections);
  186. }
  187. }
  188. }
  189. Error:
  190. TraceError("HrCreateStartMenuShortCut", hr);
  191. return hr;
  192. }