// MBShellExt.cpp : Implementation of CMBShellExt
|
|
#include "stdafx.h"
|
#include "MBShellExt.h"
|
|
#pragma comment(lib,"shlwapi.lib")
|
#pragma message("Automatically linking with Shlwapi.dll")
|
|
// CMBShellExt
|
|
#define REG_SUBKEY _T( "Software\\Activesoft\\MBClient" )
|
|
#define PSW_EMKEY ( _T("P512D790") ) // ÊÇAPM\EMÉϵÄÃÜÔ¿
|
|
// CMBShellExt
|
#define AMCADDIN_FLAG_SHELLEX_MENU ( 16384 ) // ÔÊÐí¼ÓÈë×ÊÔ´¹ÜÀíÆ÷ÓÒ¼ü²Ëµ¥ÖÐ
|
|
HRESULT CMBShellExt::Initialize( LPCITEMIDLIST pidlFolder, LPDATAOBJECT pDataObj, HKEY hProgID )
|
{
|
FORMATETC fmt = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
|
STGMEDIUM stg = { TYMED_HGLOBAL };
|
HDROP hDrop;
|
|
// Look for CF_HDROP data in the data object.
|
if ( FAILED( pDataObj->GetData( &fmt, &stg ) ) )
|
{
|
// Nope! Return an "invalid argument" error back to Explorer.
|
return E_INVALIDARG;
|
}
|
|
// Get a pointer to the actual data.
|
hDrop = (HDROP)GlobalLock( stg.hGlobal );
|
if ( NULL == hDrop )
|
return E_INVALIDARG;
|
|
// Note that it's vitally important to error-check everything, especially pointers. Since our extension runs in Explorer's process space, if we crash we take down Explorer too. On 9x, such a crash might necessitate rebooting the computer.
|
|
// So, now that we have an HDROP handle, we can get the filename we need.
|
|
// Sanity check ¨C make sure there is at least one filename.
|
UINT uNumFiles = DragQueryFile( hDrop, 0xFFFFFFFF, NULL, 0 );
|
if ( 0 == uNumFiles )
|
{
|
GlobalUnlock( stg.hGlobal );
|
ReleaseStgMedium( &stg );
|
return E_INVALIDARG;
|
}
|
|
HRESULT hr = S_OK;
|
TCHAR szFile[MAX_PATH];
|
UINT nLen;
|
|
// get multi files
|
for ( UINT uFile = 0; uFile < uNumFiles; uFile++ )
|
{
|
// Get the next filename.
|
nLen = DragQueryFile( hDrop, uFile, szFile, MAX_PATH );
|
if ( nLen == 0 )
|
continue;
|
|
if ( PathIsDirectory ( szFile ) )
|
{
|
szFile[nLen] = '\\';
|
szFile[nLen+1] = '\0';
|
}
|
|
m_lsFiles.AddTail( szFile );
|
} // end for
|
|
GlobalUnlock( stg.hGlobal );
|
ReleaseStgMedium( &stg );
|
return hr;
|
}
|
|
HRESULT CMBShellExt::QueryContextMenu( HMENU hmenu, UINT uMenuIndex, UINT uidFirstCmd, UINT uidLastCmd, UINT uFlags )
|
{
|
// If the flags include CMF_DEFAULTONLY then we shouldn't do anything.
|
if ( uFlags & CMF_DEFAULTONLY )
|
return MAKE_HRESULT( SEVERITY_SUCCESS, FACILITY_NULL, 0 );
|
|
int nNum = 0;
|
POSITION pos;
|
CString strDispName;
|
CString strMenuName;
|
|
|
strMenuName = _T("MBCÉÏ´«");//µ½Îĵµ¹ñ
|
InsertMenu( hmenu, uMenuIndex, MF_BYPOSITION, uidFirstCmd + nNum, strMenuName );
|
++nNum;
|
HBITMAP hBitmap= GetSTKBitmap(1);
|
if(hBitmap)
|
{
|
SetMenuItemBitmaps(hmenu,
|
uMenuIndex,
|
MF_BYPOSITION,
|
hBitmap,
|
hBitmap);
|
}
|
/*strMenuName = _T("MBCÉÏ´«µ½¸öÈËÍøÅÌ");
|
InsertMenu( hmenu, uMenuIndex, MF_BYPOSITION, uidFirstCmd + nNum, strMenuName );
|
++nNum;
|
hBitmap= GetSTKBitmap(1);
|
if(hBitmap)
|
{
|
SetMenuItemBitmaps(hmenu,
|
uMenuIndex,
|
MF_BYPOSITION,
|
hBitmap,
|
hBitmap);
|
}*/
|
for ( pos = m_lsAddInDispName.GetHeadPosition(); pos; )
|
{
|
strDispName = m_lsAddInDispName.GetNext( pos );
|
InsertMenu( hmenu, uMenuIndex, MF_BYPOSITION, uidFirstCmd + nNum, strDispName );
|
++nNum;
|
}
|
|
strMenuName = _T("MBCÒ×·¢");
|
InsertMenu( hmenu, uMenuIndex, MF_BYPOSITION, uidFirstCmd + nNum, strMenuName );
|
hBitmap= GetSTKBitmap();
|
if(hBitmap)
|
{
|
SetMenuItemBitmaps(hmenu,
|
uMenuIndex,
|
MF_BYPOSITION,
|
hBitmap,
|
hBitmap);
|
}
|
return MAKE_HRESULT( SEVERITY_SUCCESS, FACILITY_NULL, nNum + 1 );
|
}
|
|
#ifdef _WIN64
|
HRESULT CMBShellExt::GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT* pwReserved, LPSTR pszName, UINT cchMax)
|
{
|
USES_CONVERSION;
|
|
// Check idCmd, it must be 0 since we have only one menu item.
|
if ( idCmd < 0 && idCmd > (UINT)m_lsAddInDispName.GetCount() )
|
return E_INVALIDARG;
|
|
// If Explorer is asking for a help string, copy our string into the
|
// supplied buffer.
|
if ( uFlags & GCS_HELPTEXT )
|
{
|
CString strText;
|
LPCTSTR szText = _T("");
|
if(idCmd == 0)
|
{
|
szText = _T("MBCÒ×·¢");
|
}
|
else
|
{
|
strText.Format( _T("This is the MBC shell extension's help %d"), idCmd);
|
szText = strText;
|
}
|
if ( uFlags & GCS_UNICODE )
|
{
|
// We need to cast pszName to a Unicode string, and then use the
|
// Unicode string copy API.
|
lstrcpynW( (LPWSTR) pszName, T2CW(szText), cchMax );
|
}
|
else
|
{
|
// Use the ANSI string copy API to return the help string.
|
lstrcpynA( pszName, T2CA(szText), cchMax );
|
}
|
|
return S_OK;
|
}
|
|
return E_INVALIDARG;
|
}
|
|
#else
|
HRESULT CMBShellExt::GetCommandString( UINT idCmd, UINT uFlags, UINT* pwReserved, LPSTR pszName, UINT cchMax )
|
{
|
USES_CONVERSION;
|
|
// Check idCmd, it must be 0 since we have only one menu item.
|
if ( idCmd < 0 && idCmd > (UINT)m_lsAddInDispName.GetCount() )
|
return E_INVALIDARG;
|
|
// If Explorer is asking for a help string, copy our string into the
|
// supplied buffer.
|
if ( uFlags & GCS_HELPTEXT )
|
{
|
LPCTSTR szText = _T("This is the MBC shell extension's help");
|
|
if ( uFlags & GCS_UNICODE )
|
{
|
// We need to cast pszName to a Unicode string, and then use the
|
// Unicode string copy API.
|
lstrcpynW( (LPWSTR) pszName, T2CW(szText), cchMax );
|
}
|
else
|
{
|
// Use the ANSI string copy API to return the help string.
|
lstrcpynA( pszName, T2CA(szText), cchMax );
|
}
|
|
return S_OK;
|
}
|
|
return E_INVALIDARG;
|
}
|
#endif
|
|
HRESULT CMBShellExt::InvokeCommand( LPCMINVOKECOMMANDINFO pCmdInfo )
|
{
|
// If lpVerb really points to a string, ignore this function call and bail out.
|
int nMenuID = 0;
|
|
// Get the command index - the only valid one is 0.
|
nMenuID = LOWORD( pCmdInfo->lpVerb );
|
|
|
if ( 0 != HIWORD( pCmdInfo->lpVerb ) )
|
{
|
return E_INVALIDARG;
|
}
|
|
if ( nMenuID >= 0 && nMenuID <= m_lsAddInDispName.GetCount( ) + 2 )
|
{
|
#ifdef _WIN64
|
CString strAMViewPath;
|
|
if ( DoSTKCom( nMenuID, pCmdInfo->hwnd ) )
|
return S_OK;
|
else
|
return S_FALSE;
|
#else
|
if ( DoSTKCom( nMenuID, pCmdInfo->hwnd ) )
|
return S_OK;
|
else
|
return S_FALSE;
|
#endif
|
|
return S_OK;
|
}
|
|
return E_INVALIDARG;
|
}
|
|
bool CMBShellExt::DoSTKCom( long nMenuID, HWND hWnd )
|
{
|
HRESULT hr;
|
CString strMBExe;
|
strMBExe.Format( _T("%s\\mbcU.exe"), GetSTKWorkDir());
|
HANDLE hEventShareMemory = OpenEvent(EVENT_ALL_ACCESS , FALSE, _T("mbcSharedMemoryEvent"));
|
if (NULL == hEventShareMemory)
|
{
|
long nErrorId = GetLastError();
|
CString strMessage;
|
strMessage.Format(_T("OpenEvent mbcSharedMemoryEvent ErrorID:%d"),nErrorId);
|
WriteLog(strMessage);
|
ShellExecute( NULL, _T("open"), strMBExe, _T(""), _T(""), SW_SHOW );
|
//MessageBox(hWnd, strMessage, _T("mbEasySend"), MB_OK | MB_ICONINFORMATION );
|
return false;
|
}
|
HANDLE hShareMemory = OpenFileMapping( PAGE_READONLY,false,_T("mbcSharedMemory") );
|
if (NULL == hShareMemory)
|
{
|
/*m_hShareMemory = CreateFileMapping(HANDLE(0xFFFFFFFF), NULL, PAGE_READWRITE,0, 2560, _T("mbcSharedMemory"));
|
if (NULL == m_hShareMemory)
|
{*/
|
long nErrorId = GetLastError();
|
CString strMessage;
|
strMessage.Format(_T("OpenFileMapping mbcSharedMemory ErrorID:%d"),nErrorId);
|
//MessageBox(hWnd, strMessage, _T("mbEasySend"), MB_OK | MB_ICONINFORMATION );
|
ShellExecute( NULL, _T("open"), strMBExe, _T(""), _T(""), SW_SHOW );
|
WriteLog(strMessage);
|
return false;
|
//}
|
}
|
TCHAR* lpBuffer = (TCHAR*)MapViewOfFile(hShareMemory, FILE_MAP_WRITE, 0, 0, 2560);
|
if (NULL == lpBuffer)
|
{
|
//MessageBox(hWnd, _T("MapViewOfFile mbcSharedMemoryʧ°Ü"), _T("mbEasySend"), MB_OK | MB_ICONINFORMATION );
|
long nErrorId = GetLastError();
|
CString strMessage;
|
strMessage.Format(_T("MapViewOfFile mbcSharedMemory ErrorID:%d"),nErrorId);
|
WriteLog(strMessage);
|
return false;
|
}
|
POSITION pos;
|
CString strBuf;
|
CString strXmlBuf;
|
CString strAddInName = _T("");
|
int nType = 0;
|
if(nMenuID == 0 )//|| nMenuID == 1
|
nType = 1;
|
if ( nMenuID -1 > m_lsAddInName.GetCount() )
|
{
|
pos = m_lsAddInName.FindIndex( nMenuID - 1 );
|
if ( pos )
|
{
|
strAddInName = m_lsAddInName.GetAt( pos );
|
}
|
}
|
strXmlBuf.Format(_T("<body type='%d' addin='%s'>"),nType,strAddInName);
|
CString strFile;
|
for ( pos = m_lsFiles.GetHeadPosition(); pos; )
|
{
|
strFile = m_lsFiles.GetNext( pos );
|
strBuf.Format( _T("<file>%s</file>"),strFile );
|
if(strXmlBuf.GetLength() + strBuf.GetLength()> 2550)
|
{
|
break;
|
}
|
strXmlBuf += strBuf;
|
}
|
strXmlBuf += _T("</body>");
|
_stprintf(lpBuffer,_T("%s"), strXmlBuf );
|
UnmapViewOfFile(lpBuffer);
|
SetEvent(hEventShareMemory);
|
CloseHandle(hEventShareMemory);
|
CloseHandle(hShareMemory);
|
return true;
|
}
|
|
void CMBShellExt::GetAddInMenu( )
|
{
|
HKEY hKey;
|
DWORD dwBuf = MAX_PATH;
|
DWORD dwIndex = 0;
|
CRegKey myKey;
|
CString strSubPath, strDispName;
|
CString strName, strValue;
|
TCHAR szValue[256]= { 0 };
|
TCHAR szName[80] = { 0 };
|
DWORD dwReaded = 0;
|
DWORD dwValue = 0;
|
int nFlag = 0;
|
|
RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\ActiveSoft\\MBClient\\AMCAddIn"), 0, KEY_ENUMERATE_SUB_KEYS, &hKey);
|
|
m_lsAddInName.RemoveAll();
|
m_lsAddInDispName.RemoveAll();
|
while (RegEnumKey(hKey, dwIndex, szName, dwBuf) == 0)
|
{
|
dwIndex++;
|
|
szName[dwBuf] = '\0';
|
strName = szName;
|
strDispName = _T("");
|
strSubPath.Format( _T("SOFTWARE\\ActiveSoft\\MBClient\\AMCAddIn\\%s"), strName );
|
myKey.Close( );
|
if ( myKey.Open( HKEY_LOCAL_MACHINE, strSubPath, KEY_READ ) == ERROR_SUCCESS )
|
{
|
dwReaded = 255;
|
nFlag = 0;
|
|
if ( ERROR_SUCCESS == myKey.QueryValue( dwValue, _T( "Flag" ) ) )
|
nFlag = dwValue;
|
|
if ( nFlag & AMCADDIN_FLAG_SHELLEX_MENU )
|
{
|
#ifdef AFX_TARG_CHS
|
if ( ERROR_SUCCESS == myKey.QueryValue( szValue, _T( "DisplayName" ), &dwReaded ) && dwReaded > 0 )
|
{
|
szValue[dwReaded] = '\0';
|
strDispName = szValue;
|
}
|
#else
|
if ( ERROR_SUCCESS == myKey.QueryValue( szValue, _T( "DisplayName_ENU" ), &dwReaded ) && dwReaded > 0 )
|
{
|
szValue[dwReaded] = '\0';
|
strDispName = szValue;
|
}
|
#endif
|
if ( strDispName.IsEmpty() )
|
strDispName = strName;
|
m_lsAddInDispName.AddTail( strDispName );
|
m_lsAddInName.AddTail( strName );
|
}
|
|
myKey.Close( );
|
}
|
else
|
{
|
continue;
|
}
|
}
|
|
RegCloseKey(hKey);
|
}
|
|
bool CMBShellExt::CStringToAnsi( LPCTSTR pszT, LPSTR *ppszA )
|
{
|
ULONG cbAnsi, cCharacters;
|
|
if ( pszT == NULL )
|
{
|
*ppszA= NULL;
|
return false;
|
}
|
#ifdef _UNICODE
|
cCharacters = wcslen(pszT);
|
cbAnsi = ::WideCharToMultiByte( CP_ACP, 0, pszT, -1, NULL, 0, NULL, NULL );
|
*ppszA = (LPSTR) CoTaskMemAlloc(cbAnsi+1);
|
if ( NULL == *ppszA )
|
return false;
|
ZeroMemory(*ppszA,cbAnsi+1);
|
// Convert to ANSI.
|
if (0 == WideCharToMultiByte(CP_ACP, 0, pszT, cCharacters, *ppszA,
|
cbAnsi, NULL, NULL))
|
{
|
CoTaskMemFree(*ppszA);
|
*ppszA = NULL;
|
return false;
|
}
|
#else
|
cCharacters = strlen(pszT);
|
*ppszA = (LPSTR) CoTaskMemAlloc(cCharacters+1);
|
if ( NULL == *ppszA )
|
return false;
|
ZeroMemory(*ppszA,cCharacters+1);
|
memcpy(*ppszA,pszT,cCharacters);
|
#endif
|
return true;
|
}
|
|
CString CMBShellExt::GetSTKWorkDir()
|
{
|
CString strWorkDir;
|
CRegKey reg;
|
CString strSubKey;
|
TCHAR szValue[256] = { 0 };
|
DWORD dwReaded;
|
|
strSubKey.Format( _T("%s"), REG_SUBKEY );
|
if ( ERROR_SUCCESS == reg.Open( HKEY_LOCAL_MACHINE, strSubKey, KEY_READ ) )
|
{
|
dwReaded = 255;
|
if ( ERROR_SUCCESS == reg.QueryStringValue( _T( "WorkDir" ), szValue, &dwReaded ) && dwReaded > 0 )
|
{
|
strWorkDir = szValue;
|
strWorkDir.TrimRight();
|
strWorkDir.TrimRight( '\\' );
|
}
|
|
reg.Close();
|
}
|
if ( strWorkDir.IsEmpty() )
|
strWorkDir =GetModulePath();
|
return strWorkDir;
|
}
|
|
|
|
// дÈÕÖ¾
|
void CMBShellExt::WriteLog( CString strLog )
|
{
|
CTime tmCurrent = CTime::GetCurrentTime();
|
CString strTime = tmCurrent.Format( _T(" %Y-%m-%d %H:%M:%S = ") );
|
CString strEnter = _T(" \r\n ");
|
CString strLogPath = _T(" ");
|
CString strBuff;
|
LPSTR pDest ;
|
CFile file;
|
|
strLogPath.Format( _T("%s\\mbEasySend.log"),GetModulePath());
|
if ( !file.Open(strLogPath, CFile::modeCreate | CFile::modeWrite | CFile::modeNoTruncate) )
|
{
|
return ;
|
}
|
file.Seek( 0, CFile::end );
|
|
strBuff.Format( _T("%s%s%s"),strTime, strLog,strEnter );
|
if ( CStringToAnsi(strBuff, &pDest))
|
{
|
file.Write( (void*)pDest, strlen(pDest));
|
CoTaskMemFree(pDest);
|
}
|
file.Close();
|
}
|
HBITMAP CMBShellExt::GetSTKBitmap(int nMenuType)
|
{
|
HINSTANCE hInstance = NULL;
|
HBITMAP hBitmap = NULL;
|
#ifdef _WIN64
|
hInstance = ::GetModuleHandle( _T("mbEasySendW.dll") );
|
#else
|
hInstance = ::GetModuleHandle( _T("mbEasySend.dll") );
|
#endif
|
if(nMenuType == 0)
|
hBitmap = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_AM) );//IDB_USERSTAT
|
else
|
hBitmap = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_MBC) );//IDB_USERSTAT
|
HIMAGELIST hImageList1= ImageList_Create(16,16,ILC_COLORDDB|ILC_MASK ,1,2); //
|
ImageList_SetBkColor(hImageList1, GetSysColor( COLOR_MENU ) );
|
ImageList_AddMasked(hImageList1, hBitmap, RGB(255,0,255));//ÉèÖð×ɫΪ͸Ã÷É«
|
//ImageList_Add( hImageList1, hBitmap,NULL); //AfxGetInstanceHandle()
|
CWnd *pWnd = AfxGetMainWnd(); // Get main window
|
if (pWnd == NULL)
|
pWnd = CWnd::GetDesktopWindow();
|
if(!pWnd)
|
return NULL;
|
CDC *pDC = pWnd->GetDC(); // Get device context
|
if(!pDC)
|
return NULL;
|
HBITMAP hBmp;
|
HICON hIcon = ImageList_GetIcon(hImageList1,0,0);
|
HDC hTmpDc;
|
hTmpDc = CreateCompatibleDC(pDC->GetSafeHdc());
|
hBmp = CreateCompatibleBitmap(pDC->GetSafeHdc(),16,16);
|
HBITMAP hOldBmp = (HBITMAP)::SelectObject(hTmpDc,hBmp);
|
HBRUSH hBrush ;
|
COLORREF newclrBack;
|
newclrBack=GetSysColor(COLOR_3DFACE);
|
hBrush =CreateSolidBrush(newclrBack);
|
::DrawIconEx(
|
hTmpDc,
|
0,
|
0,
|
hIcon,
|
16,
|
16,
|
0,
|
hBrush,
|
DI_NORMAL
|
);
|
(HBITMAP)::SelectObject(hTmpDc, hOldBmp );
|
DeleteDC(hTmpDc);
|
::DestroyIcon(hIcon);
|
pWnd->ReleaseDC(pDC);
|
return hBmp;
|
}
|
// »ñȡִÐгÌÐòËùÔÚµÄĿ¼
|
CString CMBShellExt::GetModulePath()
|
{
|
CString strFileName;
|
HINSTANCE hInstance = NULL;
|
#ifdef _WIN64
|
hInstance = ::GetModuleHandle( _T("mbEasySendW.dll") );
|
#else
|
hInstance = ::GetModuleHandle( _T("mbEasySend.dll") );
|
#endif
|
if (m_strBinPath.IsEmpty( ))
|
{
|
int nPos;
|
|
GetModuleFileName( hInstance, strFileName.GetBuffer( MAX_PATH ), MAX_PATH );
|
strFileName.ReleaseBuffer();
|
strFileName = GetPathName( strFileName );
|
return strFileName;
|
}
|
else
|
return m_strBinPath;
|
}
|
// ȡȫ·¾¶ÎļþÃûÖеÄ·¾¶
|
CString CMBShellExt::GetPathName( CString strFileName )
|
{
|
int nPos;
|
CString strPathName;
|
|
if ( strFileName.IsEmpty() )
|
return _T( "" );
|
|
nPos = strFileName.ReverseFind( '\\' );
|
if ( nPos < 0 )
|
return _T( "" );
|
|
strPathName = strFileName.Left( nPos );
|
return strPathName;
|
}
|