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

📄 cryptoshellext.cpp

📁 使用Windows加密API的例子
💻 CPP
字号:
////////////////////////////////////////////////////////////////////////////////
//
//	Title:		Crypto Shell Extension Object
//	File:		CryptoShellExt.cpp
//	Author:		Chad Slater
//	Date:		March 2001
//
//	Abstract:	This shell extension object provides a context menu item
//				for encrypting and decrypting files in windows explorer
//				using the Win32 Crypto API.
//
//
//
//
//	Revision History:
//	---------------------------------------------------------------------
//	cslater		03/15/2001	Initial revision
//	cslater		03/16/2001	Fixed context menu item defect 
//	cslater		03/17/2001	Added two additional menu items for selecting
//							the destination folder for encrypting/decrypting
//	cslater		03/18/2001	Added a hook procedure to enable/disable the OK
//							button in the browse for folder dialog based on
//							whether the destination is writable
//
//
//
////////////////////////////////////////////////////////////////////////////////


#include "stdafx.h"
#include "Common.h"
#include "CryptoAPI.h"
#include "CryptoShellExt.h"

#include <io.h>


#define	CSP_KEYCONTAINER_NAME	L"CRYPTO_CONTEXTMENU_SHELLEXT_1_0_0"
#define	MENU_ITEMS_ADDED		5
#define	DOUBLE_ENCRYPT_FILENAME	_T("~TMP_ICRYPTO.CRP")


static BOOL 
BrowseFolder( LPTSTR	lptstrSelectedFolder );
	//	Displays the browse for folder dialog for the user to select the 
	//	destination folder for the encrypted/decrypted files


static int CALLBACK
BrowseFolderProc( HWND		hWnd,
				  UINT		nMsg,
				  LPARAM	lParam,
				  LPARAM	dwData		);
	//	Hook procedure for the browse for folder dialog
	//
	//	Used for enabling/disabling the OK button based on whether the 
	//	destination is writable


static BOOL
BuildDestinationPathFromSrc( IN		const CComBSTR	bstrSource, 
							 INOUT		  CComBSTR& bstrDestination );
	//	Constructs a destination path by combining the source filename
	//	with the destination path
	//
	//	Returns whether the operation was successful


static _variant_t
GetDblCryptTempFilename();
	//	Returns the temporary filename for decrypting to guard against double encryption


HRESULT CCryptoShellExt::
Initialize ( LPCITEMIDLIST	pidlFolder,
		     LPDATAOBJECT	pDataObj,
			 HKEY			hProgID			)
	{
	FORMATETC fmt		= { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
	STGMEDIUM stg		= { TYMED_HGLOBAL };
	HDROP     hDrop		=	NULL;
	HRESULT	  hr		=	S_OK;
	UINT	  uNumFiles	=	0;
	HMODULE	  hLib		=	NULL;

	try
		{
			// Look for CF_HDROP data in the data object
		CHECK_HR( pDataObj->GetData( &fmt, &stg ) );
		hDrop = (HDROP) GlobalLock ( stg.hGlobal );
		if( NULL == hDrop )
			THROW_HRESULT( E_INVALIDARG );

			// How many files are selected?
		CleanUp();
		m_nFiles = DragQueryFile ( hDrop, 0xFFFFFFFF, NULL, 0 );
		if( m_nFiles <= 0 )
			THROW_HRESULT( E_INVALIDARG );

			//	Allocate the buffer to hold the paths to the selected files
		m_pbstrFiles = new CComBSTR[ m_nFiles ];
		if( m_pbstrFiles == NULL )
			THROW_HRESULT( E_OUTOFMEMORY );

			//	For each file selected in Explorer, save them in case the user
			//	selects our context menu item
		for( UINT nIndex = 0;
				nIndex < m_nFiles;
					nIndex++ )
			{
			TCHAR	lptstrFile[ MAX_PATH ] = {0};
			if( DragQueryFile ( hDrop, nIndex, lptstrFile, MAX_PATH ) == 0 )
				THROW_HRESULT( E_INVALIDARG );
			m_pbstrFiles[ nIndex ] = lptstrFile;
			}
		}

	catch( HRESULT _hr )
		{
		hr = _hr;
		}

	GlobalUnlock ( stg.hGlobal );
	ReleaseStgMedium ( &stg );	
	return hr;
	}


HRESULT CCryptoShellExt::
QueryContextMenu (	HMENU hMenu,
					UINT  uMenuIndex, 
					UINT  uidFirstCmd,
					UINT  uidLastCmd,
					UINT  uFlags )
	{
	HRESULT hr = S_OK;

	try
		{
			// If the flag is CMF_DEFAULTONLY then don't do anything
		if( uFlags & CMF_DEFAULTONLY )
			throw MAKE_HRESULT ( SEVERITY_SUCCESS, FACILITY_NULL, 0 );

			//	Get the menu item out of the string table and insert it
		CHECK_HR( InsertContextMenuItem( hMenu, uMenuIndex, uidFirstCmd, IDC_ENCRYPT_FILE_TO, IDS_ENCRYPT_FILE_TO_MENU_ITEM ) );
		CHECK_HR( InsertContextMenuItem( hMenu, uMenuIndex, uidFirstCmd, IDC_ENCRYPT_FILE,	  IDS_ENCRYPT_MENU_ITEM			) );
		CHECK_HR( InsertContextMenuItem( hMenu, uMenuIndex, uidFirstCmd, IDC_DECRYPT_FILE_TO, IDS_DECRYPT_FILE_TO_MENU_ITEM ) );		
		CHECK_HR( InsertContextMenuItem( hMenu, uMenuIndex, uidFirstCmd, IDC_DECRYPT_FILE,	  IDS_DECRYPT_MENU_ITEM			) );
		
			//	Insert a separator 
		InsertMenu( hMenu, uMenuIndex, MF_BYPOSITION | MF_SEPARATOR, 0, 0 );
		hr = MAKE_HRESULT ( SEVERITY_SUCCESS, FACILITY_NULL, MENU_ITEMS_ADDED );
		}
	catch( HRESULT _hr )
		{
		hr = _hr;
		}

	return hr;
	}


HRESULT CCryptoShellExt::
GetCommandString (	UINT   idCmd,
					UINT   uFlags,
					LPUINT pwReserved,
					LPSTR  pszName,
					UINT   cchMax	)
	{
	USES_CONVERSION;
	int		nStringID	=	0;
	HRESULT	hr			=	S_OK;

		// If Explorer is asking for a help string, copy our string into the
		// supplied buffer
    if( uFlags & GCS_HELPTEXT )
        {
        TCHAR	lptstrBuffer[ MAX_STRINGTBL + 1 ] = {0};

			//	Which menu item is selected?
		switch( idCmd )
			{
			case IDC_ENCRYPT_FILE:
				nStringID = IDS_ENCRYPT_OBJECT_FLYBY_HELP;
				break;

			case IDC_DECRYPT_FILE:
				nStringID = IDS_DECRYPT_OBJECT_FLYBY_HELP;
				break;

			case IDC_ENCRYPT_FILE_TO:
				nStringID = IDS_ENCRYPT_FILE_TO_FLYBY;
				break;

			case IDC_DECRYPT_FILE_TO:
				nStringID = IDS_DECRYPT_FILE_TO_FLYBY;
				break;

			default:
				ATLASSERT( 0 );
				hr =  E_INVALIDARG;
				break;
			}

			//	Load the help string that will appear in the status bar
			//	as a fly-by help string
		if( SUCCEEDED( hr ) &&
			::LoadString( _Module.m_hInst,
						  nStringID,
						  lptstrBuffer,
						  MAX_STRINGTBL ) != 0 )
			{
			if ( uFlags & GCS_UNICODE )
				lstrcpynW ( (LPWSTR) pszName, T2CW(lptstrBuffer), cchMax );
			else
				lstrcpynA ( pszName, T2CA(lptstrBuffer), cchMax );
			}
		}

    return hr;
	}	


HRESULT CCryptoShellExt::
InvokeCommand ( LPCMINVOKECOMMANDINFO pCmdInfo )
	{
	HRESULT	hr = S_OK;

		// If lpVerb points to a string, then ignore this call
    if( HIWORD( pCmdInfo->lpVerb ) != 0 )
        hr = E_INVALIDARG;

	else
		{
		TCHAR	lptstrDestination[ MAX_PATH ] = {0};

			// Carry out the menu selection
		switch( LOWORD( pCmdInfo->lpVerb ) )
			{
			case IDC_ENCRYPT_FILE:
				DoCrypto();			
				break;
			
			case IDC_DECRYPT_FILE:
				DoCrypto( CCryptoShellExt::cryptDecrypt );
				break;

			case IDC_ENCRYPT_FILE_TO:
				if( BrowseFolder( lptstrDestination ) )
					DoCrypto( CCryptoShellExt::cryptEncrypt, lptstrDestination );
				break;

			case IDC_DECRYPT_FILE_TO:
				if( BrowseFolder( lptstrDestination ) )
					DoCrypto( CCryptoShellExt::cryptDecrypt, lptstrDestination );
					break;
			
			default:
				ATLASSERT( 0 );
				hr = E_INVALIDARG;
				break;
			}

			//	The context menu is gone at this point
		CleanUp();
		}
	return hr;
	}


void CCryptoShellExt::
CleanUp()
	{
	if( m_pbstrFiles != NULL )
		{
		delete [] m_pbstrFiles;
		m_pbstrFiles = NULL;
		}
	m_nFiles = 0;
	}


void CCryptoShellExt::
DoCrypto(	CCryptoShellExt::CryptAction Action,
			LPCTSTR						 lpctstrDestination	) const
	{
	_variant_t	vtDestination;

	try
		{
		ATLASSERT( m_nFiles > 0 );
		if( m_nFiles > 0 )
			{
			CComPtr< ICrypto >	pCrypto;

			if( SUCCEEDED( pCrypto.CoCreateInstance( CLSID_Crypto ) ) )
				{
				ATLASSERT( pCrypto != NULL );
				if( !pCrypto )
					THROW_HRESULT( E_FAIL );

					//	Set the key container name
				CHECK_HR( pCrypto->put_ContainerName( CSP_KEYCONTAINER_NAME ) );

					//	For each file selected in Explorer, encrypt/decrypt
				for( UINT nIndex = 0;
						nIndex < m_nFiles;
							nIndex++ )
					{
					CComBSTR	bstrDestination;

						//	If the user specified a destination, set that now
					if( lpctstrDestination )
						{
						bstrDestination = lpctstrDestination;
						BuildDestinationPathFromSrc( m_pbstrFiles[ nIndex ].m_str, bstrDestination );
						}

					ATLASSERT( m_pbstrFiles != NULL );
					ATLASSERT( !::IsBadReadPtr( m_pbstrFiles, sizeof( CComBSTR* ) ) );
					ATLASSERT( !::IsBadReadPtr( m_pbstrFiles[ nIndex ], sizeof( CComBSTR ) ) );
					if( m_pbstrFiles != NULL &&
						!::IsBadReadPtr( m_pbstrFiles,			 sizeof( CComBSTR* ) ) &&
						!::IsBadReadPtr( m_pbstrFiles[ nIndex ], sizeof( CComBSTR  ) ) )
						{
							//	Change to hour glass icon
						HCURSOR	hCursor = SetCursor( LoadCursor( NULL, IDC_WAIT ) );
						switch( Action )
							{
							case CCryptoShellExt::cryptEncrypt:
								{
								USES_CONVERSION;
								_variant_t	varDblEncryptFilename = GetDblCryptTempFilename();

									//	Try to decrypt first to guard against multiple encryptions
								if( FAILED( pCrypto->DecryptDoc( m_pbstrFiles[ nIndex ].m_str, varDblEncryptFilename ) ) )
									{
									( lpctstrDestination != NULL ) ?
										CHECK_HR( pCrypto->EncryptDoc( m_pbstrFiles[ nIndex ].m_str, _variant_t(bstrDestination) ) ) :
										CHECK_HR( pCrypto->EncryptDoc( m_pbstrFiles[ nIndex ].m_str, vtMissing ) );
									}

									//	Cleanup the intermediate file
								_unlink( W2A(varDblEncryptFilename.bstrVal) );								
								break;
								}

							case CCryptoShellExt::cryptDecrypt:
								( lpctstrDestination != NULL ) ?
									CHECK_HR( pCrypto->DecryptDoc( m_pbstrFiles[ nIndex ].m_str, _variant_t(vtDestination)  ) ) :
									CHECK_HR( pCrypto->DecryptDoc( m_pbstrFiles[ nIndex ].m_str, vtMissing  ) );
								break;

							default:
								ATLASSERT( 0 );
								break;
							}
						SetCursor( hCursor );
						}
					}
				}
			}
		}
	catch( HRESULT _hr )
		{
		UNREFERENCED_PARAMETER( _hr );
		IErrorInfo* pErrorInfo = NULL;
		if( ::GetErrorInfo( 0, &pErrorInfo ) == S_OK &&
			pErrorInfo                       != NULL    )
			{
			CComBSTR	bstrErrorMsg;
			
			pErrorInfo->GetDescription( &bstrErrorMsg );
			::MessageBox( NULL, _bstr_t(bstrErrorMsg.m_str), NULL, MB_OK | MB_ICONEXCLAMATION );
			pErrorInfo->Release();
			}	   
		}
	}


HRESULT CCryptoShellExt::
InsertContextMenuItem(	HMENU	hMenu,
						int		nMenuIndex,
						int		uidFirstCmd,
						int		uidCmdItem,
						int		nStringID	) const
	{
	HRESULT	hr								  = E_FAIL;
	TCHAR	lptstrBuffer[ MAX_STRINGTBL + 1 ] = {0};

		//	Insert the decrypt menu item
	if( ( ::LoadString( _Module.m_hInst,  nStringID,  lptstrBuffer,  MAX_STRINGTBL ) != 0    ) &&
		InsertMenu( hMenu, nMenuIndex, MF_BYPOSITION, uidFirstCmd + uidCmdItem, lptstrBuffer ) )
			hr = S_OK;

	return hr;
	}


BOOL 
BrowseFolder( LPTSTR	lptstrSelectedFolder )
	{
	BOOL			bResult	=	FALSE;

	ATLASSERT( !::IsBadWritePtr( lptstrSelectedFolder, sizeof( TCHAR ) * MAX_PATH ) );
	if( !::IsBadWritePtr( lptstrSelectedFolder, sizeof( TCHAR ) * MAX_PATH ) )
		{
		LPITEMIDLIST	pItemList	=	NULL;
		BROWSEINFO		BrowseInfo	=	{0};

		BrowseInfo.ulFlags	=	BIF_RETURNONLYFSDIRS | BIF_DONTGOBELOWDOMAIN ;
		BrowseInfo.lpfn     =	BrowseFolderProc;

			//	Show the browse dialog
		pItemList	=	SHBrowseForFolder( &BrowseInfo );
		if( pItemList )
			bResult = SHGetPathFromIDList( pItemList, lptstrSelectedFolder );
		}
	return bResult;	
	}



int CALLBACK
BrowseFolderProc( HWND		hWnd,
				  UINT		nMsg,
				  LPARAM	lParam,
				  LPARAM	dwData		)
	{
	switch( nMsg )
		{
		case	BFFM_SELCHANGED:
			{
			USES_CONVERSION;
			TCHAR	lptstrPath[ MAX_PATH ] = {0};
			
				//	Enable/disable the OK button based on whether the 
				//	selection is writable
			ATLASSERT( lParam );
			if( SHGetPathFromIDList( (LPITEMIDLIST)lParam, lptstrPath ) )
				::SendMessage( hWnd, BFFM_ENABLEOK, 0, _access( T2A(lptstrPath), 02 ) == 0 );			
			break;
			}
		}

	return 0;
	}


BOOL
BuildDestinationPathFromSrc( IN		const CComBSTR	bstrSource, 
							 INOUT		  CComBSTR& bstrDestination )
	{
	USES_CONVERSION;
	BOOL	bSuccess = FALSE;
	CHAR	lpstrSource[ MAX_PATH ]			= {0};
	CHAR*	lpstrSourceFilename				= NULL;
	CHAR	lpstrDestination[ MAX_PATH ]	= {0};

	if( bstrSource.Length()		 > 0 &&
		bstrDestination.Length() > 0 )
		{
			//	Perform string manipulations on CHAR first, then convert back
		strcpy( lpstrSource,	  W2A(bstrSource.m_str) );
		strcpy( lpstrDestination, W2A(bstrDestination)  );

			//	Point to the source filename
		lpstrSourceFilename = strrchr( lpstrSource, '\\' );
		if( lpstrSourceFilename )
			{
			lpstrSourceFilename++;
			ATLASSERT( lpstrSourceFilename != NULL );
			if( lpstrSourceFilename )
				{
					//	Tack on the trailing backslash if one doesn't already exist
				if( lpstrDestination[ strlen( lpstrDestination ) - 1 ] != '\\' )
					strcat( lpstrDestination, "\\" );

					//	Tack on the source filename
				strcat( lpstrDestination, lpstrSourceFilename );
				bstrDestination = lpstrDestination;
				bSuccess = TRUE;
				}
			}
		}

	return bSuccess;
	}


_variant_t
GetDblCryptTempFilename()
	{
	_variant_t  varFilename;
	TCHAR		lptstrTempDir[ MAX_PATH ] = {0};

	GetTempPath( MAX_PATH, lptstrTempDir );
	lstrcat( lptstrTempDir, DOUBLE_ENCRYPT_FILENAME );

	varFilename = lptstrTempDir;

	return varFilename;
	}

⌨️ 快捷键说明

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