Skip to content

Instantly share code, notes, and snippets.

@NoTimeForHero
Created July 25, 2016 00:06
Show Gist options
  • Save NoTimeForHero/41298b742efb656e43b2013512a60617 to your computer and use it in GitHub Desktop.
Save NoTimeForHero/41298b742efb656e43b2013512a60617 to your computer and use it in GitHub Desktop.
// NetFrameworkChecker.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include "NetFrameworkChecker.h"
wstringstream logger;
bool need_log = true;
bool debug = true;
// Порядок вызова GetLastError в коде важен, иначе он будет возвращать 0
// То есть нельзя ставить этот метод после какой-либо функции, иначе он будет возвращать неправильный результат
// Deprecated: CreateProcess не позволяет запросить повышение прав через UAC
bool easyCreateProcess(wstring path, PROCESS_INFORMATION &pi) {
STARTUPINFO cif; ZeroMemory(&cif, sizeof(STARTUPINFO));
bool status = CreateProcess(path.c_str(), NULL, NULL, NULL, FALSE, 0, NULL, NULL, &cif, &pi);
LONG nError = GetLastError();
logger << "CreateProcess(" << nError << "): " << getErrorMessage(nError);
if (!status)
return false;
return true;
}
// Способ завершить запущенный процесс:
//TerminateProcess(PROCESS_INFORMATION pi.hProcess, NO_ERROR);
LONG startProcess(LPCTSTR file, bool wait_process) {
SHELLEXECUTEINFO ExecuteInfo;
memset(&ExecuteInfo, 0, sizeof(ExecuteInfo));
ExecuteInfo.cbSize = sizeof(ExecuteInfo);
ExecuteInfo.fMask = 0;
ExecuteInfo.hwnd = 0;
ExecuteInfo.lpVerb = L"open"; // Operation to perform
ExecuteInfo.lpFile = file; // Application name
ExecuteInfo.fMask = wait_process ? SEE_MASK_NOCLOSEPROCESS : NULL;
ExecuteInfo.lpParameters = NULL; // Additional parameters
ExecuteInfo.lpDirectory = 0; // Default directory
ExecuteInfo.nShow = SW_SHOW;
ExecuteInfo.hInstApp = 0;
logger << "ShellExecuteEx: " << file << endl;
ShellExecuteEx(&ExecuteInfo);
LONG nError = GetLastError();
if (wait_process) {
WaitForSingleObject(ExecuteInfo.hProcess, INFINITE);
}
logger << "ShellExecuteEx(" << nError << "): " << getErrorMessage(nError);
return nError;
}
bool makeSetup(HINSTANCE hInstance) {
wstring setupPath = wstring(ExePath() + L"\\setup.exe");
logger << "setupPath = " << setupPath << endl << endl;
LONG code = extractResource(hInstance, IDR_NET_INSTALLER, setupPath.c_str());
// ошибка 183 = File Already Exists, тогда он будет просто перезаписан
if (code != 0 && code != 183) return false;
logger << "Starting NET Framework installler and waiting them." << endl;
code = startProcess(setupPath.c_str(), true);
if (code != 0) return false;
DeleteFile(setupPath.c_str());
LONG nError = GetLastError();
logger << "DeleteFile(" << nError << "): " << getErrorMessage(nError);
return true;
}
int CALLBACK WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
bool setup_launched = false;
bool installed = isNetFrameworkInstalled();
logger << "Extracting mode: " << "Current directory" << endl;
logger << "Exe path: " << ExePath() << endl;
logger << endl << endl;
//wstring testPath = wstring(ExePath() + L"\\Test.exe");
//extractResource(hInstance, IDR_EXAMPLE, testPath.c_str());
if (true) { //!installed) {
setup_launched = true;
if (!makeSetup(hInstance)) {
goto internal_error;
}
}
if (setup_launched) {
logger << endl << "Now trying to check again NET Framework installation." << endl;
installed = isNetFrameworkInstalled();
}
if (installed) {
//startProcess(ExePath() + L"\\Test.exe", true);
}
finish_output();
//system("pause");
return 0;
internal_error:
logger << "[internal_error] section:" << endl;
finish_output();
return 0;
not_installed:
return 0;
}
LONG extractResource(HINSTANCE hInstance, LONG RES_ID, LPCTSTR target) {
HRSRC hrsrc = NULL;
HGLOBAL hGlbl = NULL;
BYTE *pExeResource = NULL;
HANDLE hFile = INVALID_HANDLE_VALUE;
hrsrc = FindResource(hInstance, (LPCWSTR)RES_ID, RT_RCDATA);
if (hrsrc == NULL) {
logger << "Can't find resource with ID: " << RES_ID << endl;
return -1;
}
hGlbl = LoadResource(hInstance, hrsrc);
if (hGlbl == NULL) {
logger << "Can't load resource with ID: " << RES_ID << endl;
return -2;
}
pExeResource = (BYTE*)LockResource(hGlbl);
if (pExeResource == NULL) {
logger << "Can't lock resource with ID: " << RES_ID << endl;
return -3;
}
DWORD size = SizeofResource(hInstance, hrsrc);
hFile = CreateFile(target, GENERIC_WRITE | GENERIC_READ, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
LONG nError = GetLastError();
logger << "extractResource(" << nError << "): " << getErrorMessage(nError);
logger << "Name: " << target << endl;
if (hFile == INVALID_HANDLE_VALUE)
return nError;
DWORD bytesWritten = 0;
WriteFile(hFile, pExeResource, size, &bytesWritten, NULL);
CloseHandle(hFile);
logger << "Size: " << bytesWritten << endl;
return nError;
}
wstring ExePath() {
TCHAR buffer[MAX_PATH];
GetModuleFileName(NULL, buffer, MAX_PATH);
wstring::size_type pos = wstring(buffer).find_last_of(L"\\/");
return wstring(buffer).substr(0, pos);
}
void finish_output() {
wstring target = ExePath() + L"\\unpacker.log";
HANDLE hFile = CreateFile(target.c_str(), GENERIC_WRITE | GENERIC_READ, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
LONG nError = GetLastError();
logger << __LINE__ << ":finish_output->CreateFile(" << nError << "): " << getErrorMessage(nError);
// Если файл создан успешно или он уже существовал (перезаписан)
if (hFile != INVALID_HANDLE_VALUE && (nError == 0 || nError == 183)) {
DWORD bytesWritten;
wstring fileout = logger.str();
WriteFile(hFile, fileout.c_str(), fileout.size()*sizeof(wchar_t), &bytesWritten, NULL); // size() возвращает количество букв без учёта мультибайтовости
CloseHandle(hFile);
} else {
wstring clone(logger.str());
MessageBox(NULL, clone.c_str(), L"NetFrameWorkChecker", MB_OK);
}
OutputDebugString(logger.str().c_str());
if (debug) {
wstring clone(logger.str());
MessageBox(NULL, clone.c_str(), L"NetFrameWorkChecker", MB_OK);
}
}
bool isNetFrameworkInstalled() {
logger << "Checking registry..." << endl;
// Проверка наличия секции в реестре
HKEY hKey = OpenKey(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v4\\Client");
if (!hKey) goto error;
// Проверка наличия ключа в реестре
bool no_key;
LPTSTR v1 = GetVal(hKey, L"TargetVersion", no_key);
if (no_key) goto error;
logger << "Installed?: [TRUE]" << endl;
logger << "Net Framework Version Detected: " << v1 << endl;
return true;
error:
logger << "Installed?: [FALSE]" << endl;
logger << "Net Framework Is Not Installed! " << endl;
return false;
}
HKEY OpenKey(HKEY hRootKey, wchar_t* strKey)
{
HKEY hKey;
LONG nError = RegOpenKeyEx(hRootKey, strKey, NULL, KEY_READ, &hKey);
logger << "Reading key: " << strKey << endl;
logger << "OpenKey(" << nError << "): " << getErrorMessage(nError) << endl;
return hKey;
}
LPTSTR GetVal(HKEY hKey, LPCTSTR lpValue, bool &success)
{
TCHAR data[1024];
DWORD size = sizeof(data);
DWORD type = REG_SZ;
LONG nError = RegQueryValueEx(hKey, lpValue, NULL, &type, (LPBYTE)&data, &size);
success = !!nError;
logger << "Reading: " << lpValue << endl;
logger << "GetVal(" << nError << "): " << getErrorMessage(nError) << endl;
return data;
}
wstring getErrorMessage(LONG nError) {
LPWSTR errorText = NULL;
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, nError, MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), (LPWSTR)&errorText, 0, NULL);
if (errorText == NULL) return L"Unknown error code! (Invalid Language Dictionary?)\n";
return wstring(errorText);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment