#pragma once class CLXConsole { public: CLXConsole(void); virtual ~CLXConsole(void); public: //创建控制台窗口 BOOL CreateConsole(); //读输入 BOOL Read(CString &inStr); //任意键 char ReadChar(); BOOL Write(const LPCSTR szFormat,...); BOOL Loop(); BOOL ExecCmd(LPCSTR szCMD); //运行 BOOL LXLoader(int argc,char* argv[]); //运行原始程序 BOOL RunDefault(int argc,char* argv[]); //判断是否为ELF文件 BOOL IsELF(CString &filePath); //判断是否安装到系统 BOOL IsInstall(); //安装 BOOL InstallLoader(); //卸载 BOOL UninstallLoader(); //取得默认路径 CString GetDefaultExePath(); //取得当前程序路径 CString GetCurrentPath(); BOOL OpenKey(CRegKey &key); CString QueryKey(LPCSTR lpszKeyName); BOOL SetKey(LPCSTR lpszKeyName,LPCSTR lpszValue,BOOL bExString=FALSE); BOOL DeleteKey(LPCSTR lpszKeyName); static BOOL WriteFile(LPCSTR lpszFile,LPCSTR lpszString); private: static BOOL WINAPI HandlerRoutine(DWORD dwCtrlType); BOOL m_bFreeConsole; char *m_lpBuffer; #define MAX_IN_BUFFER 8192 HANDLE m_hOutput; HANDLE m_hInput; };
#include "StdAfx.h" #include "LXConsole.h" CLXConsole::CLXConsole(void) :m_bFreeConsole(FALSE) { m_lpBuffer=new char[MAX_IN_BUFFER]; RtlZeroMemory(m_lpBuffer,MAX_IN_BUFFER); } CLXConsole::~CLXConsole(void) { if (m_bFreeConsole) { SetConsoleCtrlHandler(HandlerRoutine,FALSE); FreeConsole(); } delete m_lpBuffer; } CString GetLastErrorString( DWORD dwErrCode/*=NULL*/ ) { DWORD dwSrcCode=0; CString strResult(__T(""));TCHAR* buffer; if(!dwErrCode) { dwErrCode=::GetLastError(); dwSrcCode=dwErrCode; } ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,NULL,dwErrCode,0,( LPTSTR )&buffer,0,NULL); if ((int)dwErrCode>=0) { strResult.Format(__T("(%d):%s"),dwErrCode,buffer); }else{ strResult.Format(__T("(0x%08X):%s"),dwErrCode,buffer); } strResult.Replace(__T("\r\n"),_T(" ")); LocalFree( buffer ); if (dwSrcCode) ::SetLastError(dwSrcCode); return strResult; } BOOL WINAPI CLXConsole::HandlerRoutine(DWORD dwCtrlType) { switch (dwCtrlType) { case CTRL_C_EVENT: break; case CTRL_BREAK_EVENT: break; case CTRL_CLOSE_EVENT: ::TerminateProcess(::GetCurrentProcess(),0); break; case CTRL_LOGOFF_EVENT: break; case CTRL_SHUTDOWN_EVENT: break; } return TRUE; } BOOL CLXConsole::CreateConsole() { ASSERT(m_bFreeConsole==FALSE); m_bFreeConsole=AllocConsole(); if (m_bFreeConsole) { m_hOutput=GetStdHandle(STD_OUTPUT_HANDLE); m_hInput=GetStdHandle(STD_INPUT_HANDLE); if (!m_hOutput || !m_hInput || !SetConsoleCtrlHandler(HandlerRoutine,TRUE)) { CloseHandle(m_hOutput); CloseHandle(m_hInput); FreeConsole(); m_bFreeConsole=FALSE; } } return m_bFreeConsole; } BOOL CLXConsole::Read(CString &inStr) { inStr.Empty(); TCHAR szBuffer[1024]={0}; DWORD dwReadBuffer=0; BOOL bResult=ReadConsole(m_hInput,szBuffer,sizeof(szBuffer)-1,&dwReadBuffer,NULL); if (bResult) { inStr=szBuffer; } return bResult; } char CLXConsole::ReadChar() { TCHAR szBuffer[2]={0}; DWORD dwReadBuffer=0; BOOL bResult=ReadConsole(m_hInput,szBuffer,sizeof(szBuffer)-1,&dwReadBuffer,NULL); if (bResult) { return szBuffer[0]; } return 0; } BOOL CLXConsole::Write(const LPCSTR szFormat,...) { CString strMessage; va_list arglist; va_start(arglist, szFormat); strMessage.FormatV(szFormat,arglist); va_end(arglist); DWORD dwWrite=0; BOOL bResult=WriteConsole(m_hOutput,(LPCSTR)strMessage,strMessage.GetLength(),&dwWrite,NULL); return bResult; } BOOL CLXConsole::Loop() { CString cmdStr; do { if (!Read(cmdStr)) { break; } system(cmdStr); } while (TRUE); return TRUE; } BOOL CLXConsole::ExecCmd(LPCSTR szCMD) { return system(szCMD)==0; } BOOL CLXConsole::LXLoader(int argc,char* argv[]) { CString fileFullPath; //文件路径 CString filePath; CString fileExt; //扩展名 CString fileName; //文件名 fileFullPath=argv[0]; int nEndChar=fileFullPath.ReverseFind('\\'); if(nEndChar==-1) { //路径中没有\\ 退出 return FALSE; } filePath=fileFullPath.Left(nEndChar+1); fileName=fileFullPath.Right(fileFullPath.GetLength()-nEndChar-1); nEndChar=fileName.ReverseFind('.'); if (nEndChar!=-1) { fileExt=fileName.Right(fileName.GetLength()-nEndChar-1); } //暂时只处理没有扩展名的 if (!fileExt.IsEmpty()) { return FALSE; } //判断是否为ELF执行文件 if (!IsELF(fileFullPath)) { return FALSE; } BOOL bCurrDir=TRUE; CString shScript; shScript.Format("./%s",fileName); CString shName; shName.Format("LXLoader_%d.sh",::GetTickCount()); CString shFile; shFile.Format("%s%s",filePath,shName); if(!WriteFile(shFile,shScript)) { CString errMsg; errMsg.Format("无法写入此文件:\r\n%s",shFile); AfxMessageBox(errMsg); return FALSE; } CFileStatus rStatus; CFile::GetStatus(shFile,rStatus);//获得文件的属性设置 rStatus.m_attribute=rStatus.m_attribute | 0x2 | 0x4 ; CFile::SetStatus(shFile, rStatus ); //防止程序退出造成的垃圾文件 ::MoveFileExA(shFile,NULL,MOVEFILE_DELAY_UNTIL_REBOOT); if (!CreateConsole()) { return FALSE; } CString cmdStr; cmdStr.Format("bash %s",shName); CString titleStr; titleStr.Format("Linux:%s",fileFullPath); SetConsoleTitle(titleStr); ExecCmd(cmdStr); ::DeleteFileA(shFile); //ExecCmd("pause"); ExecCmd("bash"); return TRUE; } BOOL CLXConsole::RunDefault(int argc,char* argv[]) { CString defExe(QueryKey("lx_old")); if (defExe.IsEmpty()) return FALSE; defExe.Replace("%1",argv[0]); //::ShellExecute(NULL,NULL,defExe,NULL,NULL,SW_SHOWDEFAULT); //::WinExec(defExe,SW_SHOWDEFAULT); CString curDir; DWORD dwSize=::GetCurrentDirectory(1024,curDir.GetBuffer(1025)); curDir.ReleaseBuffer(dwSize); STARTUPINFO st={0}; st.cb=sizeof(STARTUPINFO); GetStartupInfo(&st); PROCESS_INFORMATION pi={0}; DWORD dwFlags=NULL; defExe="%SystemRoot%\\SysWow64\\OpenWith.exe"; dwFlags|=CREATE_NEW_CONSOLE; dwFlags|=CREATE_DEFAULT_ERROR_MODE; TCHAR szPath[100] ={0}; GetWindowsDirectory( szPath, 100 ) ; defExe=szPath; defExe+="\\SysWOW64\\OpenWith.exe \""; defExe+=argv[0]; defExe+="\""; BOOL bResult=::CreateProcess(NULL,(LPSTR)(LPCSTR)defExe,NULL,NULL,NULL ,dwFlags,NULL, curDir,&st,&pi); //strCommandLine.ReleaseBuffer(); //c:\\Windows\\SysWOW64\\OpenWith.exe //::ShellExecuteA(NULL,"open",NULL,__argv[0],curDir,SW_SHOWDEFAULT); //AfxMessageBox(GetLastErrorString(0)); return bResult; } BOOL CLXConsole::IsELF(CString &filePath) { CFile fileObj; if (!fileObj.Open(filePath,CFile::modeRead|CFile::shareDenyNone)) { CString errMsg; errMsg.Format("无法读取此文件:\r\n%s",filePath); AfxMessageBox(errMsg); return FALSE; } char szBuffer[4]={0}; if (fileObj.GetLength()<4) { fileObj.Close(); return FALSE; } if(fileObj.Read(szBuffer,4)!=4) { CString errMsg; errMsg.Format("读取文件数据失败:\r\n%s",filePath); AfxMessageBox(errMsg); return FALSE; } fileObj.Close(); if (szBuffer[0]==0x7F && szBuffer[1]==0x45 && szBuffer[2]==0x4c && szBuffer[3]==0x46) { return TRUE; } return FALSE; } BOOL CLXConsole::IsInstall() { CString exePath=GetCurrentPath(); CString curPath=GetDefaultExePath(); if (curPath.IsEmpty()) { AfxMessageBox("操作失败,可能不支持此系统\r\n计算机\\HKEY_CLASSES_ROOT\\Unknown\\shell\\openas\\command\\默认值为空"); ::ExitProcess(1); } exePath.MakeLower(); curPath.MakeLower(); if (curPath.Find(exePath)!=-1) { return TRUE; }else{ if (curPath.Find(" -lxloader")!=-1) { AfxMessageBox("LXLoader程序路径已改变,需要重新安装!"); } return FALSE; } } BOOL CLXConsole::InstallLoader() { CString oldExe(QueryKey("lx_old")); if (oldExe.IsEmpty()) { oldExe=QueryKey(NULL); } CString DelegateExecute(QueryKey("DelegateExecute")); SetKey("lx_old",oldExe); if (!DelegateExecute.IsEmpty()) { SetKey("lx_DelegateExecute",DelegateExecute); DeleteKey("DelegateExecute"); } CString curExe(GetCurrentPath()); curExe+="\" \"%1\" -lxloader"; curExe="\""+curExe; SetKey(NULL,curExe,TRUE); return TRUE; } BOOL CLXConsole::UninstallLoader() { CString lx_DelegateExecute(QueryKey("lx_DelegateExecute")); CString lx_old(QueryKey("lx_old")); if (!lx_old.IsEmpty()) { SetKey(NULL,lx_old,TRUE); DeleteKey("lx_old"); } if (!lx_DelegateExecute.IsEmpty()) { SetKey("DelegateExecute",lx_DelegateExecute); DeleteKey("lx_DelegateExecute"); } return TRUE; } CString CLXConsole::QueryKey(LPCSTR lpszKeyName) { CString msg; CRegKey key; if (!OpenKey(key)) return FALSE; LONG lResult=0; CString valueString; DWORD dwSize=1024; lResult=key.QueryStringValue(lpszKeyName,valueString.GetBuffer(1025),&dwSize); valueString.ReleaseBuffer(dwSize); if (lResult==ERROR_INVALID_DATA) { DWORD dwType=REG_EXPAND_SZ; dwSize=1024; lResult=key.QueryValue(lpszKeyName,&dwType,(void*)valueString.GetBuffer(1025),&dwSize); valueString.ReleaseBuffer(dwSize); } if(lResult!=ERROR_SUCCESS && lResult!=2) { msg.Format("查询值失败:\r\nUnknown\\shell\\openas\\command\\%s\r\n%s" ,lpszKeyName,GetLastErrorString(lResult)); AfxMessageBox(msg); ::TerminateProcess(GetCurrentProcess(),1); } key.Close(); return valueString; } BOOL CLXConsole::SetKey(LPCSTR lpszKeyName,LPCSTR lpszValue,BOOL bExString) { CString msg; CRegKey key; if (!OpenKey(key)) return FALSE; LONG lResult=0; lResult=key.SetStringValue(lpszKeyName,lpszValue,bExString?REG_EXPAND_SZ:REG_SZ ); key.Close(); if(lResult!=ERROR_SUCCESS) { msg.Format("修改值失败:\r\nUnknown\\shell\\openas\\command\\%s\r\n%s" ,lpszKeyName,GetLastErrorString(lResult)); AfxMessageBox(msg); ::TerminateProcess(GetCurrentProcess(),1); } return TRUE; } BOOL CLXConsole::DeleteKey(LPCSTR lpszKeyName) { CString msg; CRegKey key; if (!OpenKey(key)) return FALSE; LONG lResult=0; lResult=key.DeleteValue(lpszKeyName); if (lResult!=ERROR_SUCCESS) { msg.Format("删除值失败:\r\nUnknown\\shell\\openas\\command\\%s\r\n%s" ,lpszKeyName,GetLastErrorString(lResult)); AfxMessageBox(msg); ::TerminateProcess(GetCurrentProcess(),1); } key.Close(); return TRUE; } BOOL CLXConsole::OpenKey(CRegKey &key) { CString msg; LONG lResult=0; lResult=key.Open(HKEY_CLASSES_ROOT,_T("Unknown\\shell\\openas\\command"),KEY_ALL_ACCESS); if (lResult!=ERROR_SUCCESS) { msg.Format("%s\r\nHKEY_CLASSES_ROOT\\Unknown\\shell\\openas\\command" ,GetLastErrorString(lResult)); AfxMessageBox(msg); ::TerminateProcess(GetCurrentProcess(),1); } return TRUE; } CString CLXConsole::GetDefaultExePath() { return QueryKey(NULL); } CString CLXConsole::GetCurrentPath() { CString exePath; DWORD dwSize=::GetModuleFileName(NULL,exePath.GetBuffer(1025),1024); exePath.ReleaseBuffer(dwSize); return exePath; } BOOL CLXConsole::WriteFile(LPCSTR lpszFile,LPCSTR lpszString) { CFile file; if (!file.Open(lpszFile,CFile::modeWrite|CFile::modeCreate)) { return FALSE; } file.Write(lpszString,(UINT)strlen(lpszString)); return TRUE; }
BOOL CLXLoaderApp::InitInstance() { CWinAppEx::InitInstance(); SetRegistryKey(_T("LXLoader")); if (__argc==1) { CLXLoaderDlg dlg; m_pMainWnd = &dlg; INT_PTR nResponse = dlg.DoModal(); }else{ CLXConsole console; if(!console.LXLoader(__argc-1,&__argv[1])) { console.RunDefault(__argc-1,&__argv[1]); } return TRUE; } return FALSE; }
目前只能打开路径不在linux安装路径下的文件
仅支持win10,且已安装linux子系统
1