// 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(""),nType,strAddInName); CString strFile; for ( pos = m_lsFiles.GetHeadPosition(); pos; ) { strFile = m_lsFiles.GetNext( pos ); strBuf.Format( _T("%s"),strFile ); if(strXmlBuf.GetLength() + strBuf.GetLength()> 2550) { break; } strXmlBuf += strBuf; } strXmlBuf += _T(""); _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; }