Created
July 25, 2016 00:06
-
-
Save NoTimeForHero/41298b742efb656e43b2013512a60617 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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