⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 shortcut.cpp

📁 MiniCA V2.0版本源码。《小型CA系统V2.1含源码》发表以来
💻 CPP
字号:
//*******************************************************************
//              
//  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 "stdafx.h"
#include "Shortcut.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// 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 store\n
  any text information and can retrieve\n
  it with "IShellLink::GetDescription"\n
  \param IconLocation   - path to the file where the icon is located\n
  that should be used. Can be an empty string\n
  \param IconIndex	  - the # of the icon in the file\n
  
	\return BOOL - ShortCut created or not\n
	
	  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('\0')!=sSpecialFolder.GetLength())
	{
		FIO.fFlags|=FOF_MULTIDESTFILES;
	}
	if(sSpecialFolder.Right(1))
	{
		sSpecialFolder+='\0';
	}
	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 ShortCut\n
  \param SpecialFolder  - where to put the shortcut (See #defines above (MSDN))\n
  \param hwnd			  - handle of the parent window for MessageBoxes\n
  the shell may need to display\n
  \param LnkPath		  - Reference to a CString that receives the linkpath if\n
  routine is successful else the string will be empty\n
  \param LnkDescription - Reference to a CString that receives the Description\n
  of the link else the string will be empty\n
  
	\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 finds\n
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 the\n
  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 long\n
path of a short (8+3) path:\n

  \param sShortPath	- short path to convert\n
  \param sLongPath	- string that receives the long path\n
  
	\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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -