Shortcut.cpp
上传用户:maryhy001
上传日期:2007-05-02
资源大小:2317k
文件大小:15k
- //*******************************************************************
- //
- // FILE: Shortcut.cpp
- //
- // AUTHOR: Thomas Latuske <CobUser@GMX.de>
- //
- // COMPONENT: CShortcut
- //
- // DATE: 04.05.2004
- //
- // COMMENTS: Update 11.05.2004:
- // - added ResolveLink
- // - added GetSpecialFolder (split off)
- //
- //*******************************************************************
- // Includes
- //////////////////////////////////////////////////////////////////////
- #include "stdafx.h"
- #include "Shortcut.h"
- //////////////////////////////////////////////////////////////////////
- // Konstruktion/Destruktion
- //////////////////////////////////////////////////////////////////////
- CShortcut::CShortcut()
- {
- m_sCmdArg.Empty();
- }
- CShortcut::~CShortcut()
- {
- }
- /*!
- ***************************************************************
- param LnkTarget - The File/Folder the link belongs to
- param LnkName - The name of the ShortCut
- param SpecialFolder - where to put the shortcut (See #defines below)
- param LnkDescription - an application can use it to storen
- any text information and can retrieven
- it with "IShellLink::GetDescription"n
- param IconLocation - path to the file where the icon is locatedn
- that should be used. Can be an empty stringn
- param IconIndex - the # of the icon in the filen
- return BOOL - ShortCut created or notn
- Defines for Special Folders:
- SendTo Menu/Folder: CSIDL_SENDTO
- Desktop for current User CSIDL_DESKTOP
- Desktop: CSIDL_COMMON_DESKTOPDIRECTORY
- Autostart for current User: CSIDL_STARTUP
- Autostart: CSIDL_COMMON_STARTUP
- Start-menu for current User: CSIDL_STARTMENU
- Start-menu: CSIDL_STARTMENU
- Programms-menu for current User:CSIDL_COMMON_STARTMENU
- and some more.....
- *****************************************************************/
- BOOL CShortcut::CreateShortCut(CString LnkTarget, CString LnkName, UINT SpecialFolder, CString LnkDescription, CString IconLocation, UINT IconIndex)
- {
- HRESULT hr;
- CFile cfFull;
- CString sExePath, sExe, sSpecialFolder;
- char *chTmp = sExePath.GetBuffer(MAX_PATH);
- GetModuleFileName(NULL, chTmp, MAX_PATH);
- sExePath.ReleaseBuffer();
- // Find the Special Folder:
- if(!GetSpecialFolder(SpecialFolder, sSpecialFolder))
- return FALSE;
-
- sSpecialFolder += LnkName + "." + "lnk";
-
- if(LnkTarget == "_this")
- {
- cfFull.SetFilePath(sExePath);
- sExe = cfFull.GetFileName();
- sExe.Delete(sExe.Find(".") + 1, 3);
- }
- else
- {
- sExePath = LnkTarget;
- }
- // Create the ShortCut:
- CoInitialize(NULL);
- BOOL bRet = FALSE;
- IShellLink* psl;
- if (SUCCEEDED( CoCreateInstance(CLSID_ShellLink,
- NULL,
- CLSCTX_INPROC_SERVER,
- IID_IShellLink,
- (LPVOID*) &psl)))
- {
- IPersistFile* ppf;
- //
- psl->SetPath(sExePath);
- psl->SetDescription(LnkDescription);
- if(!m_sCmdArg.IsEmpty())
- psl->SetArguments(m_sCmdArg);
- if (SUCCEEDED(psl->QueryInterface(IID_IPersistFile, (LPVOID *)&ppf)))
- {
- WORD wsz[MAX_PATH];
- MultiByteToWideChar(CP_ACP,
- MB_PRECOMPOSED,
- sSpecialFolder,
- -1,
- wsz,
- MAX_PATH);
- /* Call IShellLink::SetIconLocation with the file containing
- the icon and the index of the icon */
- if(!IconLocation.IsEmpty())
- {
- hr = psl->SetIconLocation(IconLocation, IconIndex);
- #ifdef _DEBUG
- if(FAILED(hr))
- TRACE("IconLocation not changed!n");
- #endif
- }
-
- if(SUCCEEDED(ppf->Save(wsz, TRUE)))
- {
- bRet = TRUE;
- }
- ppf->Release();
- }
- psl->Release();
- }
- if(bRet)
- {
- TRACE("Lnk Written!n");
- }
- else
- {
- TRACE("Lnk NOT Written! CreateShortCut(...) failed!n");
- }
- return bRet;
- }
- /*!
- ***************************************************************
- param LnkName - The name of the ShortCut
- param SpecialFolder - Location of the shortcut (See #defines below)
- return void
- Defines for Special Folders:
- SendTo Menu/Folder: CSIDL_SENDTO
- Desktop for current User CSIDL_DESKTOP
- Desktop: CSIDL_COMMON_DESKTOPDIRECTORY
- Autostart for current User: CSIDL_STARTUP
- Autostart: CSIDL_COMMON_STARTUP
- Start-menu for current User: CSIDL_STARTMENU
- Start-menu: CSIDL_STARTMENU
- Programms-menu for current User:CSIDL_COMMON_STARTMENU
- and some more.....
- *****************************************************************/
- BOOL CShortcut::DeleteShortCut(CString LnkName, UINT SpecialFolder)
- {
- CFile cfFull;
- CString sExePath, sExe, sSpecialFolder;
- char *chTmp = sExePath.GetBuffer(MAX_PATH);
- GetModuleFileName(NULL, chTmp, MAX_PATH);
- sExePath.ReleaseBuffer();
- if(!GetSpecialFolder(SpecialFolder, sSpecialFolder))
- return FALSE;
- // Work with the special folder's path (contained in szPath)
- cfFull.SetFilePath(sExePath);
- sExe = cfFull.GetFileName();
- sExe.Delete(sExe.Find(".") + 1, 3);
- sSpecialFolder += LnkName + "." + "lnk";
- // DELETE THE LINK:
- SHFILEOPSTRUCT FIO;
- memset(&FIO, 0, sizeof SHFILEOPSTRUCT);
- // FIO.pTo=NULL; // MUST be NULL
- FIO.wFunc=FO_DELETE;
- FIO.fFlags=FOF_NOERRORUI|FOF_NOCONFIRMATION;
-
- if(sSpecialFolder.Find(' ')!=sSpecialFolder.GetLength())
- {
- FIO.fFlags|=FOF_MULTIDESTFILES;
- }
- if(sSpecialFolder.Right(1))
- {
- sSpecialFolder+=' ';
- }
- FIO.pFrom=&*sSpecialFolder;
-
- int bD = SHFileOperation(&FIO);
- if(!bD)
- {
- TRACE("Lnk Deleted!n");
- return TRUE;
- }
- else
- {
- TRACE("Lnk NOT Deleted! DeleteShortCut(...) FAILED!n");
- return FALSE;
- }
- }
- /*********************************************
- This is useful when creating a link to an
- application that takes command-line arguments:
- *********************************************/
- void CShortcut::SetCmdArguments(CString sArg)
- {
- m_sCmdArg = sArg;
- }
- /*********************************************
- This routine tests if a link already existits:
- *********************************************/
- BOOL CShortcut::isLinkAvailable(CString LnkName, UINT SpecialFolder)
- {
- CFileStatus cfStatus;
- CString sSpecialFolder;
- // Find the Special Folder:
- if(!GetSpecialFolder(SpecialFolder, sSpecialFolder))
- return FALSE;
- // Work with the special folder's path (contained in szPath)
- sSpecialFolder += "\";
- sSpecialFolder += LnkName + "." + "lnk";
- if(CFile::GetStatus(sSpecialFolder, cfStatus))
- {
- #ifdef _DEBUG
- afxDump << "Full file name = " << cfStatus.m_szFullName << "n";
- #endif
- return TRUE;
- }
- else
- {
- #ifdef _DEBUG
- afxDump << "File NOT available = " << cfStatus.m_szFullName << "n";
- #endif
- return FALSE;
- }
- }
- /*********************************************
- This routine resolves the lnk destination:
- param LnkName - The name of the ShortCutn
- param SpecialFolder - where to put the shortcut (See #defines above (MSDN))n
- param hwnd - handle of the parent window for MessageBoxesn
- the shell may need to displayn
- param LnkPath - Reference to a CString that receives the linkpath ifn
- routine is successful else the string will be emptyn
- param LnkDescription - Reference to a CString that receives the Descriptionn
- of the link else the string will be emptyn
- returns a HRESULT n
- *********************************************/
- HRESULT CShortcut::ResolveLink(CString LnkName, UINT SpecialFolder, HWND hwnd, CString &LnkPath, CString &LnkDescription)
- {
- HRESULT hres;
- IShellLink* psl;
- char *szGotPath = LnkPath.GetBuffer(MAX_PATH);
- char *szDescription = LnkDescription.GetBuffer(MAX_PATH);
- CString sLnkFile, sSpecialFolder;
- CString sLong;
- WIN32_FIND_DATA wfd;
- // get the path to the special folder:
- if(!GetSpecialFolder(SpecialFolder, sSpecialFolder))
- return 1; // return ERROR
- // build a linkfile:
- sLnkFile = sSpecialFolder + LnkName + ".lnk";
- // Get a pointer to the IShellLink interface.
- hres = CoCreateInstance(CLSID_ShellLink,
- NULL,
- CLSCTX_INPROC_SERVER,
- IID_IShellLink,
- (LPVOID*) &psl);
- if(SUCCEEDED(hres))
- {
- IPersistFile* ppf;
- // Get a pointer to the IPersistFile interface.
- hres = psl->QueryInterface(IID_IPersistFile, (LPVOID *)&ppf);
- if (SUCCEEDED(hres))
- {
- WORD wsz[MAX_PATH];
- // Ensure that the string is Unicode.
- MultiByteToWideChar(CP_ACP,
- 0,
- sLnkFile,//lpszLinkFile,
- -1,
- wsz,
- MAX_PATH); // Load the shortcut.
- hres = ppf->Load(wsz, STGM_READ);
-
- if (SUCCEEDED(hres))
- { // Resolve the link.
- hres = psl->Resolve(hwnd, SLR_ANY_MATCH);
-
- if (SUCCEEDED(hres))
- {
- // Get the path to the link target.
- hres = psl->GetPath(szGotPath,
- MAX_PATH,
- (WIN32_FIND_DATA *)&wfd,
- SLGP_SHORTPATH );
-
- LnkPath.ReleaseBuffer();
-
- if (!SUCCEEDED(hres))
- {
- LnkDescription.ReleaseBuffer();
- return hres; // application-defined function
- }
- // Get the description of the target:
- hres = psl->GetDescription(szDescription, MAX_PATH);
- LnkDescription.ReleaseBuffer();
- if (!SUCCEEDED(hres))
- return hres;
- }
- }
- // Release the pointer to the IPersistFile interface.
- ppf->Release();
- }
- // Release the pointer to the IShellLink interface.
- psl->Release();
- }
- // whether OS is <= NT4 or not... use this helper:
- if(ShortToLongPathName(LnkPath, sLong) > LnkPath.GetLength())
- LnkPath = sLong;
-
- return hres;
- }
- /*********************************************
- This routine is a helper that findsn
- the path to the special folder:n
- param SpecialFolder - an UINT-define (See #defines above or (MSDN))n
- param SpecialFolderString - Reference to a CString that receives then
- path to the special folder
- returns a BOOL - Found or not n
- *********************************************/
- BOOL CShortcut::GetSpecialFolder(UINT SpecialFolder, CString &SpecialFolderString)
- {
- HRESULT hr;
- // Find the Special Folder:
- // Allocate a pointer to an Item ID list
- LPITEMIDLIST pidl;
- // Get a pointer to an item ID list that
- // represents the path of a special folder
- hr = SHGetSpecialFolderLocation(NULL, SpecialFolder, &pidl);
- if(SUCCEEDED(hr))
- { // Convert the item ID list's binary
- // representation into a file system path
- char szPath[_MAX_PATH];
- if(SHGetPathFromIDList(pidl, szPath))
- {
- // Allocate a pointer to an IMalloc interface
- LPMALLOC pMalloc;
-
- // Get the address of our task allocator's IMalloc interface
- hr = SHGetMalloc(&pMalloc);
-
- // Free the item ID list allocated by SHGetSpecialFolderLocation
- pMalloc->Free(pidl);
- // Free our task allocator
- pMalloc->Release();
- // Work with the special folder's path (contained in szPath)
- SpecialFolderString = szPath;
- SpecialFolderString += "\";
-
- return TRUE;
- }
- }
- return FALSE;
- }
- /*********************************************
- This routine is a helper that builds a longn
- path of a short (8+3) path:n
- param sShortPath - short path to convertn
- param sLongPath - string that receives the long pathn
- returns a BOOL - Found or not n
- *********************************************/
- // if the extension contains '~', replace it with '*'!!!!!!!!!!!!!!!
- int CShortcut::ShortToLongPathName(CString sShortPath, CString &sLongPath)
- {
- // Catch null pointers.
- if (sShortPath.IsEmpty()) return 0;
- // Check whether the input path is valid.
- if (0xffffffff == GetFileAttributes(sShortPath)) return 0;
- // Special characters.
- CString sep = "\";
- CString colon = ":";
- CString sDrive, sCutPath, sTmpShort;
- int npos = sShortPath.GetLength();
- // Copy the short path into the work buffer and convert forward
- // slashes to backslashes.
- CString path = sShortPath;
- path.Replace("/", sep);
- // We need a couple of markers for stepping through the path.
- int left = 0;
- int right = 0;
- // Parse the first bit of the path.
- if (path.GetLength() >= 2 && isalpha(path[0]) && colon == path[1]) // Drive letter?
- {
- if (2 == path.GetLength()) // 抌are