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.

256 lines
6.5 KiB

  1. //
  2. // Link.C
  3. //
  4. // Copyright (C) Microsoft, 1994,1995 All Rights Reserved.
  5. //
  6. // History:
  7. // ral 6/23/94 - First pass
  8. // 3/20/95 [stevecat] - NT port & real clean up, unicode, etc.
  9. //
  10. //
  11. #include "priv.h"
  12. #include "appwiz.h"
  13. const static TCHAR szExplorer[] = TEXT("Explorer");
  14. const static TCHAR szExpSelParams[] = TEXT("/Select,");
  15. //
  16. // Returns the fully-qualified path name of the link.
  17. //
  18. BOOL GetLinkName(LPTSTR lpszLinkName, LPWIZDATA lpwd)
  19. {
  20. if( PathCombine(lpszLinkName, lpwd->lpszFolder, lpwd->szProgDesc) == NULL )
  21. return( FALSE );
  22. #ifdef NO_NEW_SHORTCUT_HOOK
  23. lstrcat(lpszLinkName, (lpwd->dwFlags & WDFLAG_DOSAPP) ? c_szPIF : c_szLNK);
  24. #else
  25. if ((lstrlen(lpszLinkName) + lstrlen(lpwd->szExt)) >= MAX_PATH)
  26. return FALSE;
  27. lstrcat(lpszLinkName, lpwd->szExt);
  28. #endif
  29. return( TRUE );
  30. }
  31. //
  32. // Opens the folder of the newly created link.
  33. //
  34. BOOL OpenLinkFolder(LPWIZDATA lpwd, LPTSTR lpszLinkName)
  35. {
  36. SHELLEXECUTEINFO ei;
  37. TCHAR szParams[MAX_PATH];
  38. lstrcpy(szParams, szExpSelParams);
  39. lstrcat(szParams, lpszLinkName);
  40. ei.cbSize = sizeof(ei);
  41. ei.hwnd = lpwd->hwnd;
  42. ei.fMask = 0;
  43. ei.lpVerb = NULL;
  44. ei.lpFile = szExplorer;
  45. ei.lpParameters = szParams;
  46. ei.lpDirectory = NULL;
  47. ei.lpClass = NULL;
  48. ei.nShow = SW_SHOWDEFAULT;
  49. ei.hInstApp = g_hinst;
  50. return(ShellExecuteEx(&ei));
  51. }
  52. //
  53. // Cretates a link.
  54. //
  55. BOOL CreateLink(LPWIZDATA lpwd)
  56. {
  57. BOOL bWorked = FALSE;
  58. IShellLink *psl;
  59. HCURSOR hcurOld = SetCursor(LoadCursor(NULL, IDC_WAIT));
  60. IPersistFile *ppf;
  61. TCHAR szLinkName[MAX_PATH];
  62. WCHAR wszPath[MAX_PATH];
  63. szLinkName[0] = TEXT('\0');
  64. GetLinkName(szLinkName, lpwd);
  65. if (lpwd->lpszOriginalName)
  66. {
  67. if (PathFileExists(szLinkName))
  68. {
  69. DeleteFile(lpwd->lpszOriginalName);
  70. SHChangeNotify(SHCNE_DELETE, SHCNF_FLUSH | SHCNF_PATH,
  71. lpwd->lpszOriginalName, NULL);
  72. }
  73. else
  74. {
  75. // we use full pidls here since simple net pidls fail to compare to full net pidls,
  76. // and thus the changenotify will never make it to the client and it will not update.
  77. LPITEMIDLIST pidlOriginal = ILCreateFromPath(lpwd->lpszOriginalName); // need to do this before the move!
  78. LPITEMIDLIST pidlLink = NULL;
  79. if (MoveFile(lpwd->lpszOriginalName, szLinkName))
  80. {
  81. pidlLink = ILCreateFromPath(szLinkName); // need to do this after the move (or it won't exist)!
  82. if (pidlOriginal && pidlLink)
  83. {
  84. SHChangeNotify(SHCNE_RENAMEITEM, SHCNF_FLUSH | SHCNF_IDLIST, pidlOriginal, pidlLink);
  85. }
  86. else
  87. {
  88. TraceMsg(TF_ERROR, "%s", "Unable to generate pidls for rename notify");
  89. SHChangeNotify(SHCNE_RENAMEITEM, SHCNF_FLUSH | SHCNF_PATH, lpwd->lpszOriginalName, szLinkName);
  90. }
  91. }
  92. else
  93. {
  94. TraceMsg(TF_ERROR, "%s", "Unable to rename link -- Will end up with two");
  95. TraceMsg(TF_ERROR, "%s", szLinkName);
  96. }
  97. if (pidlOriginal)
  98. ILFree(pidlOriginal);
  99. if (pidlLink)
  100. ILFree(pidlLink);
  101. }
  102. //
  103. // Now get rid of this in case we fail later and then re-enter
  104. // this routine later.
  105. //
  106. lpwd->lpszOriginalName = NULL;
  107. }
  108. //
  109. // If we're just supposed to copy it, it's simple!
  110. //
  111. if (lpwd->dwFlags & WDFLAG_COPYLINK)
  112. {
  113. bWorked = CopyFile(lpwd->szExeName, szLinkName, FALSE);
  114. goto ExitNoFree;
  115. }
  116. #ifndef NO_NEW_SHORTCUT_HOOK
  117. if (lpwd->pnshhk)
  118. {
  119. //
  120. // The object is ready to be saved to a file.
  121. //
  122. if (FAILED(lpwd->pnshhk->lpVtbl->QueryInterface(lpwd->pnshhk, &IID_IPersistFile, &ppf)))
  123. goto ExitFreePSL;
  124. }
  125. else
  126. #ifdef UNICODE
  127. if (lpwd->pnshhkA)
  128. {
  129. //
  130. // The object is ready to be saved to a file.
  131. //
  132. if (FAILED(lpwd->pnshhkA->lpVtbl->QueryInterface(lpwd->pnshhkA, &IID_IPersistFile, &ppf)))
  133. goto ExitFreePSL;
  134. }
  135. else
  136. #endif
  137. {
  138. #endif
  139. //
  140. // We didn't do a simple copy. Now do the full-blown create.
  141. //
  142. if (FAILED(CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLink, (void **)&psl)))
  143. {
  144. TraceMsg(TF_ERROR, "%s", "Could not create instance of IShellLink");
  145. goto ExitNoFree;
  146. }
  147. if (FAILED(psl->lpVtbl->QueryInterface(psl, &IID_IPersistFile, &ppf)))
  148. {
  149. goto ExitFreePSL;
  150. }
  151. psl->lpVtbl->SetPath(psl, lpwd->szExeName);
  152. psl->lpVtbl->SetArguments(psl, lpwd->szParams);
  153. psl->lpVtbl->SetWorkingDirectory(psl, lpwd->szWorkingDir);
  154. if (lpwd->dwFlags & WDFLAG_DOSAPP)
  155. {
  156. #ifdef UNICODE
  157. MultiByteToWideChar(CP_ACP, 0, lpwd->PropPrg.achIconFile, -1, wszPath, ARRAYSIZE(wszPath));
  158. psl->lpVtbl->SetIconLocation(psl, wszPath, (int)(lpwd->PropPrg.wIconIndex));
  159. #else
  160. psl->lpVtbl->SetIconLocation(psl, lpwd->PropPrg.achIconFile, (int)(lpwd->PropPrg.wIconIndex));
  161. #endif // UNICODE
  162. }
  163. #ifndef NO_NEW_SHORTCUT_HOOK
  164. }
  165. #endif
  166. #ifdef UNICODE
  167. bWorked = SUCCEEDED(ppf->lpVtbl->Save(ppf, szLinkName, TRUE));
  168. #else
  169. if (MultiByteToWideChar(CP_ACP, 0, szLinkName, -1, wszPath, ARRAYSIZE(wszPath)))
  170. {
  171. bWorked = SUCCEEDED(ppf->lpVtbl->Save(ppf, wszPath, TRUE));
  172. }
  173. #endif // UNICODE
  174. ppf->lpVtbl->Release(ppf);
  175. ExitFreePSL:
  176. #ifndef NO_NEW_SHORTCUT_HOOK
  177. if (lpwd->pnshhk)
  178. {
  179. lpwd->pnshhk->lpVtbl->Release(lpwd->pnshhk);
  180. lpwd->pnshhk = NULL;
  181. }
  182. else
  183. #ifdef UNICODE
  184. if (lpwd->pnshhkA)
  185. {
  186. lpwd->pnshhkA->lpVtbl->Release(lpwd->pnshhkA);
  187. lpwd->pnshhkA = NULL;
  188. }
  189. else
  190. #endif
  191. #endif
  192. psl->lpVtbl->Release(psl);
  193. ExitNoFree:
  194. if (bWorked)
  195. {
  196. SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_FLUSH | SHCNF_PATH,
  197. szLinkName, NULL);
  198. }
  199. SetCursor(hcurOld);
  200. if (bWorked)
  201. {
  202. if (!(lpwd->dwFlags & WDFLAG_DONTOPENFLDR))
  203. {
  204. OpenLinkFolder(lpwd, szLinkName);
  205. }
  206. }
  207. else
  208. {
  209. ShellMessageBox(g_hinst, lpwd->hwnd, MAKEINTRESOURCE(IDS_NOSHORTCUT),
  210. 0, MB_OK | MB_ICONEXCLAMATION);
  211. }
  212. return(bWorked);
  213. }