Shortcut.cpp
上传用户:dengkfang
上传日期:2008-12-30
资源大小:5233k
文件大小:14k
源码类别:

CA认证

开发平台:

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