Shortcut.cpp
上传用户:maryhy001
上传日期:2007-05-02
资源大小:2317k
文件大小:15k
源码类别:

网格计算

开发平台:

Visual C++

  1. //*******************************************************************
  2. //              
  3. //  FILE:       Shortcut.cpp
  4. //              
  5. //  AUTHOR:     Thomas Latuske <CobUser@GMX.de>
  6. //              
  7. //  COMPONENT:  CShortcut
  8. //              
  9. //  DATE:       04.05.2004
  10. //              
  11. //  COMMENTS:   Update 11.05.2004:
  12. // - added ResolveLink
  13. // - added GetSpecialFolder (split off)
  14. //              
  15. //*******************************************************************
  16. // Includes
  17. //////////////////////////////////////////////////////////////////////
  18. #include "stdafx.h"
  19. #include "Shortcut.h"
  20. //////////////////////////////////////////////////////////////////////
  21. // Konstruktion/Destruktion
  22. //////////////////////////////////////////////////////////////////////
  23. CShortcut::CShortcut()
  24. {
  25. m_sCmdArg.Empty();
  26. }
  27. CShortcut::~CShortcut()
  28. {
  29. }
  30. /*!
  31. ***************************************************************
  32. param LnkTarget   - The File/Folder the link belongs to
  33. param LnkName   - The name of the ShortCut
  34. param SpecialFolder  - where to put the shortcut (See #defines below)
  35. param LnkDescription - an application can use it to storen
  36. any text information and can retrieven
  37. it with "IShellLink::GetDescription"n
  38. param IconLocation   - path to the file where the icon is locatedn
  39.     that should be used. Can be an empty stringn
  40. param IconIndex   - the # of the icon in the filen
  41. return BOOL - ShortCut created or notn
  42.   Defines for Special Folders:
  43. SendTo Menu/Folder: CSIDL_SENDTO
  44. Desktop for current User CSIDL_DESKTOP
  45. Desktop: CSIDL_COMMON_DESKTOPDIRECTORY
  46. Autostart for current User: CSIDL_STARTUP
  47. Autostart: CSIDL_COMMON_STARTUP
  48. Start-menu for current User: CSIDL_STARTMENU
  49. Start-menu: CSIDL_STARTMENU
  50. Programms-menu for current User:CSIDL_COMMON_STARTMENU
  51. and some more.....
  52. *****************************************************************/
  53. BOOL CShortcut::CreateShortCut(CString LnkTarget, CString LnkName, UINT SpecialFolder, CString LnkDescription, CString IconLocation, UINT IconIndex)
  54. {
  55. HRESULT hr;
  56. CFile cfFull;
  57. CString sExePath, sExe, sSpecialFolder;
  58. char *chTmp = sExePath.GetBuffer(MAX_PATH);
  59. GetModuleFileName(NULL, chTmp, MAX_PATH);
  60. sExePath.ReleaseBuffer();
  61. // Find the Special Folder:
  62. if(!GetSpecialFolder(SpecialFolder, sSpecialFolder))
  63. return FALSE;
  64. sSpecialFolder += LnkName + "." + "lnk";
  65. if(LnkTarget == "_this")
  66. {
  67. cfFull.SetFilePath(sExePath);
  68. sExe = cfFull.GetFileName();
  69. sExe.Delete(sExe.Find(".") + 1, 3);
  70. }
  71. else
  72. {
  73. sExePath = LnkTarget;
  74. }
  75. // Create the ShortCut:
  76. CoInitialize(NULL);
  77.     BOOL bRet = FALSE;
  78.     IShellLink* psl;
  79.     if (SUCCEEDED( CoCreateInstance(CLSID_ShellLink,
  80. NULL,
  81. CLSCTX_INPROC_SERVER,
  82. IID_IShellLink,
  83. (LPVOID*) &psl)))
  84.     {
  85.         IPersistFile* ppf;
  86. // 
  87.         psl->SetPath(sExePath);
  88.         psl->SetDescription(LnkDescription);
  89. if(!m_sCmdArg.IsEmpty())
  90. psl->SetArguments(m_sCmdArg);
  91.         if (SUCCEEDED(psl->QueryInterface(IID_IPersistFile, (LPVOID *)&ppf)))
  92. {
  93.             WORD wsz[MAX_PATH];
  94.         MultiByteToWideChar(CP_ACP,
  95.                         MB_PRECOMPOSED,
  96.                     sSpecialFolder,
  97.                 -1,
  98.             wsz,
  99.         MAX_PATH);
  100. /* Call IShellLink::SetIconLocation with the file containing
  101. the icon and the index of the icon */
  102. if(!IconLocation.IsEmpty())
  103. {
  104. hr = psl->SetIconLocation(IconLocation, IconIndex);
  105. #ifdef _DEBUG
  106. if(FAILED(hr))
  107. TRACE("IconLocation not changed!n");
  108. #endif
  109. }
  110. if(SUCCEEDED(ppf->Save(wsz, TRUE)))
  111. {
  112. bRet = TRUE;
  113. }
  114.         ppf->Release();
  115. }
  116.         psl->Release();
  117.     } 
  118. if(bRet)
  119. {
  120. TRACE("Lnk Written!n");
  121. }
  122. else
  123. {
  124. TRACE("Lnk NOT Written! CreateShortCut(...) failed!n");
  125. }
  126. return bRet;
  127. }
  128. /*!
  129. ***************************************************************
  130. param LnkName - The name of the ShortCut
  131. param SpecialFolder - Location of the shortcut (See #defines below)
  132.   return void
  133.   Defines for Special Folders:
  134. SendTo Menu/Folder: CSIDL_SENDTO
  135. Desktop for current User CSIDL_DESKTOP
  136. Desktop: CSIDL_COMMON_DESKTOPDIRECTORY
  137. Autostart for current User: CSIDL_STARTUP
  138. Autostart: CSIDL_COMMON_STARTUP
  139. Start-menu for current User: CSIDL_STARTMENU
  140. Start-menu: CSIDL_STARTMENU
  141. Programms-menu for current User:CSIDL_COMMON_STARTMENU
  142. and some more.....
  143. *****************************************************************/
  144. BOOL CShortcut::DeleteShortCut(CString LnkName, UINT SpecialFolder)
  145. {
  146. CFile cfFull;
  147. CString sExePath, sExe, sSpecialFolder;
  148. char *chTmp = sExePath.GetBuffer(MAX_PATH);
  149. GetModuleFileName(NULL, chTmp, MAX_PATH);
  150. sExePath.ReleaseBuffer();
  151. if(!GetSpecialFolder(SpecialFolder, sSpecialFolder))
  152. return FALSE;
  153. // Work with the special folder's path (contained in szPath)
  154. cfFull.SetFilePath(sExePath);
  155. sExe = cfFull.GetFileName();
  156. sExe.Delete(sExe.Find(".") + 1, 3);
  157. sSpecialFolder += LnkName + "." + "lnk";
  158. // DELETE THE LINK:
  159. SHFILEOPSTRUCT FIO;
  160. memset(&FIO, 0, sizeof SHFILEOPSTRUCT);
  161. //  FIO.pTo=NULL; // MUST be NULL
  162.     FIO.wFunc=FO_DELETE;
  163.     FIO.fFlags=FOF_NOERRORUI|FOF_NOCONFIRMATION;
  164. if(sSpecialFolder.Find('')!=sSpecialFolder.GetLength())
  165. {
  166. FIO.fFlags|=FOF_MULTIDESTFILES;
  167. }
  168. if(sSpecialFolder.Right(1))
  169. {
  170. sSpecialFolder+='';
  171. }
  172. FIO.pFrom=&*sSpecialFolder;
  173. int bD = SHFileOperation(&FIO);
  174. if(!bD)
  175. {
  176. TRACE("Lnk Deleted!n");
  177. return TRUE;
  178. }
  179. else
  180. {
  181. TRACE("Lnk NOT Deleted! DeleteShortCut(...) FAILED!n");
  182. return FALSE;
  183. }
  184. }
  185. /*********************************************
  186.  This is useful when creating a link to an
  187.  application that takes command-line arguments:
  188.  *********************************************/
  189. void CShortcut::SetCmdArguments(CString sArg)
  190. {
  191. m_sCmdArg = sArg;
  192. }
  193. /*********************************************
  194.  This routine tests if a link already existits:
  195.  *********************************************/
  196. BOOL CShortcut::isLinkAvailable(CString LnkName, UINT SpecialFolder)
  197. {
  198. CFileStatus cfStatus;
  199. CString sSpecialFolder;
  200. // Find the Special Folder:
  201. if(!GetSpecialFolder(SpecialFolder, sSpecialFolder))
  202. return FALSE;
  203. // Work with the special folder's path (contained in szPath)
  204. sSpecialFolder += "\";
  205. sSpecialFolder += LnkName + "." + "lnk";
  206. if(CFile::GetStatus(sSpecialFolder, cfStatus))
  207. {
  208. #ifdef _DEBUG
  209. afxDump << "Full file name = " << cfStatus.m_szFullName << "n";
  210. #endif
  211. return TRUE;
  212. }
  213. else
  214. {
  215. #ifdef _DEBUG
  216. afxDump << "File NOT available = " << cfStatus.m_szFullName << "n";
  217. #endif
  218. return FALSE;
  219. }
  220. }
  221. /*********************************************
  222.  This routine resolves the lnk destination:
  223. param LnkName   - The name of the ShortCutn
  224. param SpecialFolder  - where to put the shortcut (See #defines above (MSDN))n
  225. param hwnd   - handle of the parent window for MessageBoxesn
  226. the shell may need to displayn
  227. param LnkPath   - Reference to a CString that receives the linkpath ifn
  228. routine is successful else the string will be emptyn
  229. param LnkDescription - Reference to a CString that receives the Descriptionn
  230. of the link else the string will be emptyn
  231. returns a HRESULT n
  232.  *********************************************/
  233. HRESULT CShortcut::ResolveLink(CString LnkName, UINT SpecialFolder, HWND hwnd, CString &LnkPath, CString &LnkDescription)
  234. {
  235. HRESULT hres;     
  236. IShellLink* psl;
  237. char *szGotPath = LnkPath.GetBuffer(MAX_PATH); 
  238. char *szDescription = LnkDescription.GetBuffer(MAX_PATH);
  239. CString sLnkFile, sSpecialFolder;
  240. CString sLong;
  241. WIN32_FIND_DATA wfd;  
  242. // get the path to the special folder:
  243. if(!GetSpecialFolder(SpecialFolder, sSpecialFolder))
  244. return 1; // return ERROR
  245. // build a linkfile:
  246. sLnkFile = sSpecialFolder + LnkName + ".lnk";
  247.     // Get a pointer to the IShellLink interface. 
  248.     hres = CoCreateInstance(CLSID_ShellLink,
  249. NULL,
  250. CLSCTX_INPROC_SERVER,
  251. IID_IShellLink,
  252. (LPVOID*) &psl);
  253.     if(SUCCEEDED(hres)) 
  254. {
  255. IPersistFile* ppf;  
  256. // Get a pointer to the IPersistFile interface. 
  257. hres = psl->QueryInterface(IID_IPersistFile, (LPVOID *)&ppf);
  258. if (SUCCEEDED(hres)) 
  259. WORD wsz[MAX_PATH];  
  260.             // Ensure that the string is Unicode. 
  261. MultiByteToWideChar(CP_ACP,
  262. 0,
  263. sLnkFile,//lpszLinkFile,
  264. -1,
  265. wsz, 
  266. MAX_PATH);   // Load the shortcut. 
  267. hres = ppf->Load(wsz, STGM_READ); 
  268. if (SUCCEEDED(hres)) 
  269. {   // Resolve the link. 
  270. hres = psl->Resolve(hwnd, SLR_ANY_MATCH); 
  271. if (SUCCEEDED(hres)) 
  272. {  
  273. // Get the path to the link target. 
  274. hres = psl->GetPath(szGotPath, 
  275. MAX_PATH,
  276. (WIN32_FIND_DATA *)&wfd, 
  277. SLGP_SHORTPATH ); 
  278. LnkPath.ReleaseBuffer();
  279. if (!SUCCEEDED(hres))
  280. {
  281. LnkDescription.ReleaseBuffer();
  282. return hres; // application-defined function  
  283. }
  284. // Get the description of the target:
  285. hres = psl->GetDescription(szDescription, MAX_PATH); 
  286. LnkDescription.ReleaseBuffer();
  287. if (!SUCCEEDED(hres)) 
  288. return hres; 
  289. }
  290. // Release the pointer to the IPersistFile interface. 
  291. ppf->Release();         
  292.     // Release the pointer to the IShellLink interface. 
  293. psl->Release();
  294. }
  295. // whether OS is <= NT4 or not... use this helper:
  296. if(ShortToLongPathName(LnkPath, sLong) > LnkPath.GetLength())
  297. LnkPath = sLong;
  298. return hres; 
  299. }
  300. /*********************************************
  301.  This routine is a helper that findsn
  302.  the path to the special folder:n
  303. param SpecialFolder - an UINT-define (See #defines above or (MSDN))n
  304. param SpecialFolderString - Reference to a CString that receives then
  305.   path to the special folder
  306. returns a BOOL - Found or not n
  307.  *********************************************/
  308. BOOL CShortcut::GetSpecialFolder(UINT SpecialFolder, CString &SpecialFolderString)
  309. {
  310. HRESULT hr;
  311. // Find the Special Folder:
  312.    // Allocate a pointer to an Item ID list
  313.    LPITEMIDLIST pidl;
  314.    // Get a pointer to an item ID list that
  315.    // represents the path of a special folder
  316.    hr = SHGetSpecialFolderLocation(NULL, SpecialFolder, &pidl);
  317.     if(SUCCEEDED(hr))
  318. { // Convert the item ID list's binary
  319. // representation into a file system path
  320. char szPath[_MAX_PATH];
  321. if(SHGetPathFromIDList(pidl, szPath))
  322. {
  323. // Allocate a pointer to an IMalloc interface
  324. LPMALLOC pMalloc;
  325. // Get the address of our task allocator's IMalloc interface
  326. hr = SHGetMalloc(&pMalloc);
  327. // Free the item ID list allocated by SHGetSpecialFolderLocation
  328. pMalloc->Free(pidl);
  329. // Free our task allocator
  330. pMalloc->Release();
  331. // Work with the special folder's path (contained in szPath)
  332. SpecialFolderString = szPath;
  333. SpecialFolderString += "\";
  334. return TRUE;
  335. }
  336. }
  337. return FALSE;
  338. }
  339. /*********************************************
  340.  This routine is a helper that builds a longn
  341.  path of a short (8+3) path:n
  342. param sShortPath - short path to convertn
  343. param sLongPath - string that receives the long pathn
  344. returns a BOOL - Found or not n
  345.  *********************************************/
  346. // if the extension contains '~', replace it with '*'!!!!!!!!!!!!!!!
  347. int CShortcut::ShortToLongPathName(CString sShortPath, CString &sLongPath)
  348. {
  349. // Catch null pointers.
  350. if (sShortPath.IsEmpty()) return 0;
  351. // Check whether the input path is valid.
  352. if (0xffffffff == GetFileAttributes(sShortPath)) return 0;
  353. // Special characters.
  354. CString sep = "\";
  355. CString colon = ":";
  356. CString sDrive, sCutPath, sTmpShort;
  357.   int npos = sShortPath.GetLength();
  358. // Copy the short path into the work buffer and convert forward
  359. // slashes to backslashes.
  360. CString path = sShortPath;
  361. path.Replace("/", sep);
  362. // We need a couple of markers for stepping through the path.
  363. int left = 0;
  364. int right = 0;
  365. // Parse the first bit of the path.
  366. if (path.GetLength() >= 2 && isalpha(path[0]) && colon == path[1]) // Drive letter?
  367. {
  368. if (2 == path.GetLength()) // 抌are