eATM

在win10中双击运行linux程序的实现,VC++9代码

#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安装路径下的文件

下载:LXLoader

仅支持win10,且已安装linux子系统

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注