15,471
社区成员
发帖
与我相关
我的任务
分享
// SourceExe.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <conio.h>
using namespace std;
int main(int argc, char* argv[])
{
cout << "Hello world!" << endl;
getch();
return 0;
}
// ExeHelper.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <conio.h>
#include <windows.h>
using namespace std;
BYTE g_byCompare[16] = {'1', '2', '0', '6', '8', '0', '4', '5', '1', 0, 0, 0, 0, 0, 0, 0};
DWORD dwDefaultTimes = 30;
int main(int argc, char* argv[])
{
if (NULL == argv[0] || 0 == strlen(argv[0])
|| NULL == argv[1] || 0 == strlen(argv[1])
|| NULL == argv[2] || 0 == strlen(argv[2])
|| NULL == argv[3] || 0 == strlen(argv[3]))
{
cout << "argv error!" << endl;
getch();
return 0;
}
cout << "argv[0]=" << argv[0] << endl;
cout << "argv[1]=" << argv[1] << endl;
cout << "argv[2]=" << argv[2] << endl;
cout << "argv[3]=" << argv[3] << endl;
// 保证父进程已退出,才能操作父进程的EXE文件
HANDLE handle=(HANDLE)(atoi(argv[1]));
if (WAIT_FAILED == WaitForSingleObject(handle, INFINITE))
{
cout << "WaitForSingleObject Error (" << GetLastError() << ")" << endl;
getch();
return 0;
}
HANDLE hFile = CreateFile(
argv[2],
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL);
BYTE pBuffer[16] = {0};
DWORD dwFileSizeLow = 0;
DWORD dwFileSizeHigh = 0;
dwFileSizeLow = GetFileSize(hFile, &dwFileSizeHigh);
if (dwFileSizeLow < 16)
{
cout << "The size of " << argv[2] << " is " << dwFileSizeLow
<< ", less than 16 bytes." << endl;
getch();
return 0;
}
SetFilePointer(hFile, -16, NULL, FILE_END);
DWORD dwBytesRead = 0;
ReadFile(hFile, pBuffer, 16, &dwBytesRead, NULL);
DWORD dwTimes = 0;
memcpy(&dwTimes, pBuffer + 12, sizeof(DWORD));
// pBuffer的前12个字节应该与g_byCompare的前12个字节相同,后4个字节为使用次数
if (0 != memcmp(pBuffer, g_byCompare, 12))
{
// pBuffer前12个字节不是g_byCompare的前12个字节,则认为是第一次启动
// 在EXE文件末尾添加上默认的30次使用次数
dwTimes = dwDefaultTimes;
memcpy(pBuffer, g_byCompare, 16);
memcpy(pBuffer + 12, &dwTimes, sizeof(DWORD));
SetFilePointer(hFile, 0, NULL, FILE_END);
DWORD dwBytesWrite = 0;
WriteFile(hFile, pBuffer, 16, &dwBytesWrite, NULL);
}
cout << "Can use " << dwTimes << " times" << endl;
if (0 == dwTimes)
{
getch();
return 0;
}
cout << "Press any key to run" << endl;
getch();
// 减少使用次数,并将使用次数再更新到EXE文件
dwTimes--;
memcpy(pBuffer + 12, &dwTimes, sizeof(DWORD));
SetFilePointer(hFile, -16, NULL, FILE_END);
DWORD dwBytesWrite = 0;
WriteFile(hFile, pBuffer, 16, &dwBytesWrite, NULL);
CloseHandle(hFile);
STARTUPINFO si;
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
PROCESS_INFORMATION pi;
memset(&pi, 0, sizeof(pi));
// 然后启动第三方EXE
CreateProcess(
argv[3],
NULL,
NULL,
NULL,
FALSE,
NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE,
NULL,
NULL,
&si,
&pi);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return 0;
}
CExePackageApp theApp;
/////////////////////////////////////////////////////////////////////////////
// CExePackageApp initialization
/*
函数功能:释放资源文件
参数说明:DWORD dwResID :指定要释放的资源ID号,如IDR_EXE
LPCTSTR lpszResType :指定释放的资源的资源类型
LPCTSTR lpszFilePathName :指定释放后的目标文件名
返回值:成功则返回TRUE,失败返回FALSE
使用方法:BOOL bRet = FreeResFile(IDR_SOURCE_EXE, _T("EXE"), _T("D:\\123.txt"));
其中,IDR_SOURCE_EXE为EXE类型的资源ID
*/
BOOL FreeResFile(DWORD dwResID, LPCTSTR lpszResType, LPCTSTR lpszFilePathName)
{
HMODULE hInstance = ::GetModuleHandle(NULL);//得到自身实例句柄
HRSRC hResID = ::FindResource(hInstance, MAKEINTRESOURCE(dwResID), lpszResType); //查找资源
HGLOBAL hRes = ::LoadResource(hInstance, hResID); //加载资源
LPVOID pRes = ::LockResource(hRes); //锁定资源
if (NULL == pRes) //锁定失败
{
return FALSE;
}
DWORD dwResSize = ::SizeofResource(hInstance, hResID); //得到待释放资源文件大小
HANDLE hResFile = CreateFile(
lpszFilePathName,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (INVALID_HANDLE_VALUE == hResFile)
{
return FALSE;
}
DWORD dwWritten = 0; //写入文件的大小
WriteFile(hResFile, pRes, dwResSize, &dwWritten, NULL); //写入文件
CloseHandle(hResFile); //关闭文件句柄
FreeResource(hRes);
return (dwResSize == dwWritten); //若写入大小等于文件大小,返回成功,否则失败
}
BOOL CExePackageApp::InitInstance()
{
AfxEnableControlContainer();
// Standard initialization
// If you are not using these features and wish to reduce the size
// of your final executable, you should remove from the following
// the specific initialization routines you do not need.
#ifdef _AFXDLL
Enable3dControls(); // Call this when using MFC in a shared DLL
#else
Enable3dControlsStatic(); // Call this when linking to MFC statically
#endif
TCHAR szTmpDir[MAX_PATH] = {0};
GetTempPath(MAX_PATH, szTmpDir);
TCHAR szSourceExeFilePathName[MAX_PATH] = {0};
_stprintf(szSourceExeFilePathName, _T("%sSourceExe.exe"), szTmpDir);
TCHAR szExeHelperFilePathName[MAX_PATH] = {0};
_stprintf(szExeHelperFilePathName, _T("%sExeHelper.exe"), szTmpDir);
DeleteFile(szSourceExeFilePathName);
DeleteFile(szExeHelperFilePathName);
FreeResFile(IDR_SOURCE_EXE, "EXE", szSourceExeFilePathName);
FreeResFile(IDR_EXE_HELPER, "EXE", szExeHelperFilePathName);
TCHAR szModuleName[MAX_PATH] = {0};
GetModuleFileName(NULL, szModuleName, MAX_PATH);
STARTUPINFO si;
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
PROCESS_INFORMATION pi;
memset(&pi, 0, sizeof(pi));
SECURITY_ATTRIBUTES sa;
memset(&sa, 0, sizeof(sa));
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
// 得到此进程的句柄,传递给ExeHelper.exe,因此这儿不能关闭hParentProcess
// 需要在子进程中关闭
HANDLE hParentProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, GetCurrentProcessId());
TCHAR szCommandLine[MAX_PATH * 3] = {0};
// 注意此处的参数,调用CreateProcess时,并不会将EXE的文件名也当作参数
// 因此,需要在参数列表中加上EXE的文件名(ExeHelper.exe并不使用)
_stprintf(szCommandLine, _T("\"%s\" %d \"%s\" \"%s\""),
szExeHelperFilePathName, (DWORD)hParentProcess, szModuleName, szSourceExeFilePathName);
CreateProcess(
szExeHelperFilePathName,
szCommandLine,
&sa,
NULL,
TRUE,
NULL,
NULL,
NULL,
&si,
&pi);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
// CExePackageDlg dlg;
// m_pMainWnd = &dlg;
// int nResponse = dlg.DoModal();
// if (nResponse == IDOK)
// {
// // TODO: Place code here to handle when the dialog is
// // dismissed with OK
// }
// else if (nResponse == IDCANCEL)
// {
// // TODO: Place code here to handle when the dialog is
// // dismissed with Cancel
// }
// Since the dialog has been closed, return FALSE so that we exit the
// application, rather than start the application's message pump.
return FALSE;
}