Test
This commit is contained in:
43
shared/Exec.c
Normal file
43
shared/Exec.c
Normal file
@@ -0,0 +1,43 @@
|
||||
#include "stdafx.h"
|
||||
#include "Exec.h"
|
||||
|
||||
HRESULT Exec(LPWSTR verb, LPWSTR file, LPWSTR params, LPWSTR workingDir, WORD show, BOOL wait, LPDWORD exitCode) {
|
||||
SHELLEXECUTEINFO execInfo = {0};
|
||||
execInfo.cbSize = sizeof(execInfo);
|
||||
execInfo.lpVerb = verb;
|
||||
execInfo.lpFile = file;
|
||||
execInfo.lpParameters = params;
|
||||
execInfo.lpDirectory = workingDir;
|
||||
execInfo.nShow = show;
|
||||
return ExecEx(&execInfo, wait, exitCode);
|
||||
}
|
||||
|
||||
HRESULT ExecEx(LPSHELLEXECUTEINFO execInfo, BOOL wait, LPDWORD exitCode) {
|
||||
if (wait) {
|
||||
execInfo->fMask |= SEE_MASK_NOCLOSEPROCESS;
|
||||
}
|
||||
|
||||
if (!ShellExecuteEx(execInfo)) {
|
||||
return HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (wait) {
|
||||
if (execInfo->hProcess == NULL) {
|
||||
TRACE(L"ShellExecuteEx() didn't return a handle: %u", GetLastError());
|
||||
hr = E_FAIL;
|
||||
}
|
||||
|
||||
WaitForSingleObject(execInfo->hProcess, INFINITE);
|
||||
|
||||
if (exitCode != NULL && GetExitCodeProcess(execInfo->hProcess, exitCode) == 0) {
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
TRACE(L"GetExitCodeProcess() failed: %p\n", hr);
|
||||
}
|
||||
|
||||
CloseHandle(execInfo->hProcess);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
7
shared/Exec.h
Normal file
7
shared/Exec.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include <shellapi.h>
|
||||
|
||||
EXTERN_C HRESULT Exec(LPWSTR verb, LPWSTR file, LPWSTR params, LPWSTR workingDir, WORD show, BOOL wait, LPDWORD exitCode);
|
||||
EXTERN_C HRESULT ExecEx(LPSHELLEXECUTEINFO execInfo, BOOL wait, LPDWORD exitCode);
|
36
shared/GetPidForName.c
Normal file
36
shared/GetPidForName.c
Normal file
@@ -0,0 +1,36 @@
|
||||
#include "stdafx.h"
|
||||
#include <psapi.h>
|
||||
#include "GetPidForName.h"
|
||||
|
||||
#pragma comment(lib, "psapi.lib")
|
||||
|
||||
DWORD GetPidForName(const LPTSTR process) {
|
||||
// Yes, eat all of our SHRTs!
|
||||
DWORD pids[SHRT_MAX];
|
||||
DWORD bytesReturned;
|
||||
if (!EnumProcesses(pids, sizeof(pids), &bytesReturned)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD count = bytesReturned / sizeof(DWORD);
|
||||
for (DWORD i = 0; i < count; ++i) {
|
||||
HANDLE handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_READ, FALSE, pids[i]);
|
||||
if (handle) {
|
||||
WCHAR path[MAX_PATH];
|
||||
if (GetModuleBaseName(handle, NULL, path, ARRAYSIZE(path))) {
|
||||
LPWSTR basename = wcsrchr(path, L'\\');
|
||||
if (basename) {
|
||||
basename += 1;
|
||||
CharLowerBuffW(basename, (DWORD)wcslen(basename));
|
||||
if (_wcsicmp(process, basename) == 0) {
|
||||
CloseHandle(handle);
|
||||
return pids[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
CloseHandle(handle);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
5
shared/GetPidForName.h
Normal file
5
shared/GetPidForName.h
Normal file
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
EXTERN_C DWORD GetPidForName(LPTSTR process);
|
31
shared/LegacyUpdate.c
Normal file
31
shared/LegacyUpdate.c
Normal file
@@ -0,0 +1,31 @@
|
||||
#include "stdafx.h"
|
||||
#include <windows.h>
|
||||
#include "Registry.h"
|
||||
|
||||
static LPWSTR _installPath;
|
||||
|
||||
EXTERN_C HRESULT GetInstallPath(LPWSTR *path) {
|
||||
*path = (LPWSTR)LocalAlloc(LPTR, MAX_PATH * sizeof(WCHAR));
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (!_installPath) {
|
||||
DWORD size = 0;
|
||||
hr = GetRegistryString(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\LegacyUpdate", L"InstallLocation", KEY_WOW64_64KEY, &_installPath, &size);
|
||||
if (SUCCEEDED(hr)) {
|
||||
lstrcpy(*path, _installPath);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// Do our best to guess where it should be
|
||||
LPWSTR programFiles;
|
||||
hr = GetRegistryString(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion", L"ProgramFilesDir", KEY_WOW64_64KEY, &programFiles, &size);
|
||||
if (SUCCEEDED(hr)) {
|
||||
_installPath = (LPWSTR)LocalAlloc(LPTR, MAX_PATH * sizeof(WCHAR));
|
||||
wsprintf(_installPath, L"%ls\\Legacy Update", programFiles);
|
||||
LocalFree(programFiles);
|
||||
}
|
||||
}
|
||||
|
||||
lstrcpy(*path, _installPath);
|
||||
return hr;
|
||||
}
|
5
shared/LegacyUpdate.h
Normal file
5
shared/LegacyUpdate.h
Normal file
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
EXTERN_C HRESULT GetInstallPath(LPWSTR *path);
|
256
shared/LoadImage.c
Normal file
256
shared/LoadImage.c
Normal file
@@ -0,0 +1,256 @@
|
||||
#include <windows.h>
|
||||
#include <wincodec.h>
|
||||
#include <gdiplus.h>
|
||||
|
||||
// Adapted from https://faithlife.codes/blog/2008/09/displaying_a_splash_screen_with_c_part_i/
|
||||
// 1. Get resource as an IStream
|
||||
// 2. Use Windows Imaging Component to load the PNG
|
||||
// 3. Convert the WIC bitmap to an HBITMAP
|
||||
// Why does loading a PNG need to be so difficult?
|
||||
|
||||
typedef HRESULT (WINAPI *_WICConvertBitmapSource)(REFWICPixelFormatGUID dstFormat, IWICBitmapSource *pISrc, IWICBitmapSource **ppIDst);
|
||||
|
||||
static _WICConvertBitmapSource $WICConvertBitmapSource;
|
||||
|
||||
static HGLOBAL GetRawResource(HINSTANCE hInstance, LPWSTR name, LPWSTR type) {
|
||||
HRSRC resource = FindResource(hInstance, name, type);
|
||||
if (!resource) {
|
||||
TRACE(L"FindResource failed: %d", GetLastError());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DWORD resourceSize = SizeofResource(hInstance, resource);
|
||||
HGLOBAL imageHandle = LoadResource(hInstance, resource);
|
||||
if (!imageHandle) {
|
||||
TRACE(L"LoadResource failed: %d", GetLastError());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LPVOID sourceResourceData = LockResource(imageHandle);
|
||||
if (!sourceResourceData) {
|
||||
TRACE(L"LockResource failed: %d", GetLastError());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HGLOBAL resourceDataHandle = GlobalAlloc(GMEM_MOVEABLE, resourceSize);
|
||||
if (!resourceDataHandle) {
|
||||
TRACE(L"GlobalAlloc failed: %d", GetLastError());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LPVOID resourceData = GlobalLock(resourceDataHandle);
|
||||
if (!resourceData) {
|
||||
TRACE(L"GlobalLock failed: %d", GetLastError());
|
||||
GlobalFree(resourceDataHandle);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CopyMemory(resourceData, sourceResourceData, resourceSize);
|
||||
GlobalUnlock(resourceDataHandle);
|
||||
return resourceDataHandle;
|
||||
}
|
||||
|
||||
static IStream *GetResourceStream(HINSTANCE hInstance, LPWSTR name, LPWSTR type) {
|
||||
IStream *stream;
|
||||
HGLOBAL resource = GetRawResource(hInstance, name, type);
|
||||
if (!resource) {
|
||||
TRACE(L"GetResource failed: %d", GetLastError());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(CreateStreamOnHGlobal(resource, TRUE, &stream))) {
|
||||
return stream;
|
||||
}
|
||||
|
||||
GlobalFree(resource);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static IWICBitmapSource *GetWICBitmap(IStream *imageStream) {
|
||||
IWICBitmapSource *bitmap;
|
||||
IWICBitmapDecoder *decoder;
|
||||
UINT frameCount;
|
||||
IWICBitmapFrameDecode *frame;
|
||||
|
||||
if (!SUCCEEDED(CoCreateInstance(&CLSID_WICPngDecoder, NULL, CLSCTX_INPROC_SERVER, &IID_IWICBitmapDecoder, (LPVOID *)&decoder))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!SUCCEEDED(IWICBitmapDecoder_Initialize(decoder, imageStream, WICDecodeMetadataCacheOnLoad))) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!SUCCEEDED(IWICBitmapDecoder_GetFrameCount(decoder, &frameCount)) || frameCount != 1) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!SUCCEEDED(IWICBitmapDecoder_GetFrame(decoder, 0, &frame))) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
$WICConvertBitmapSource(&GUID_WICPixelFormat32bppPBGRA, (IWICBitmapSource *)frame, &bitmap);
|
||||
IWICBitmapFrameDecode_Release(frame);
|
||||
|
||||
end:
|
||||
IWICBitmapDecoder_Release(decoder);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
static HBITMAP GetHBitmapForWICBitmap(IWICBitmapSource *bitmap) {
|
||||
HBITMAP hBitmap;
|
||||
UINT width, height;
|
||||
if (!SUCCEEDED(IWICBitmapSource_GetSize(bitmap, &width, &height)) || width == 0 || height == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BITMAPINFO bminfo;
|
||||
ZeroMemory(&bminfo, sizeof(bminfo));
|
||||
bminfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bminfo.bmiHeader.biWidth = width;
|
||||
bminfo.bmiHeader.biHeight = -(LONG)height;
|
||||
bminfo.bmiHeader.biPlanes = 1;
|
||||
bminfo.bmiHeader.biBitCount = 32;
|
||||
bminfo.bmiHeader.biCompression = BI_RGB;
|
||||
|
||||
void *imageBits;
|
||||
HDC screenDC = GetDC(NULL);
|
||||
hBitmap = CreateDIBSection(screenDC, &bminfo, DIB_RGB_COLORS, &imageBits, NULL, 0);
|
||||
ReleaseDC(NULL, screenDC);
|
||||
if (!hBitmap) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UINT stride = width * 4;
|
||||
UINT imageSize = stride * height;
|
||||
if (!SUCCEEDED(IWICBitmapSource_CopyPixels(bitmap, NULL, stride, imageSize, (BYTE*)imageBits))) {
|
||||
DeleteObject(hBitmap);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return hBitmap;
|
||||
}
|
||||
|
||||
HBITMAP LoadPNGResource(HINSTANCE hInstance, LPWSTR resourceName, LPWSTR resourceType) {
|
||||
if (!$WICConvertBitmapSource) {
|
||||
$WICConvertBitmapSource = (_WICConvertBitmapSource)GetProcAddress(LoadLibrary(L"windowscodecs.dll"), "WICConvertBitmapSource");
|
||||
if (!$WICConvertBitmapSource) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
IStream *imageStream = GetResourceStream(hInstance, resourceName, resourceType);
|
||||
if (!imageStream) {
|
||||
TRACE(L"GetResourceStream failed: %d", GetLastError());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IWICBitmapSource *bitmap = GetWICBitmap(imageStream);
|
||||
if (!bitmap) {
|
||||
TRACE(L"GetWICBitmap failed: %d", GetLastError());
|
||||
IStream_Release(imageStream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HBITMAP result = GetHBitmapForWICBitmap(bitmap);
|
||||
IWICBitmapSource_Release(bitmap);
|
||||
IStream_Release(imageStream);
|
||||
return result;
|
||||
}
|
||||
|
||||
BOOL ScaleAndWriteToBMP(HBITMAP hBitmap, DWORD width, DWORD height, LPWSTR outputPath) {
|
||||
BOOL result = FALSE;
|
||||
if (!hBitmap) {
|
||||
TRACE(L"Null bitmap");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
HDC hdc = GetDC(NULL);
|
||||
HDC hdcMem = CreateCompatibleDC(hdc);
|
||||
HBITMAP scaledBitmap = CreateCompatibleBitmap(hdc, width, height);
|
||||
if (!scaledBitmap) {
|
||||
TRACE(L"CreateCompatibleBitmap failed: %d", GetLastError());
|
||||
goto end;
|
||||
}
|
||||
|
||||
BITMAP bmp;
|
||||
if (!GetObject(hBitmap, sizeof(BITMAP), &bmp)) {
|
||||
TRACE(L"GetObject failed: %d", GetLastError());
|
||||
goto end;
|
||||
}
|
||||
|
||||
HBITMAP hOld = (HBITMAP)SelectObject(hdcMem, hBitmap);
|
||||
HDC hdcMemScaled = CreateCompatibleDC(hdc);
|
||||
HBITMAP hOldScaled = (HBITMAP)SelectObject(hdcMemScaled, scaledBitmap);
|
||||
SetStretchBltMode(hdcMemScaled, HALFTONE);
|
||||
|
||||
if (!StretchBlt(hdcMemScaled,
|
||||
0, 0, width, height, hdcMem,
|
||||
0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY)) {
|
||||
TRACE(L"StretchBlt failed: %d", GetLastError());
|
||||
goto end;
|
||||
}
|
||||
|
||||
BITMAPINFOHEADER bmih = {0};
|
||||
bmih.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bmih.biWidth = width;
|
||||
bmih.biHeight = height;
|
||||
bmih.biPlanes = 1;
|
||||
bmih.biBitCount = bmp.bmBitsPixel;
|
||||
bmih.biCompression = BI_RGB;
|
||||
bmih.biSizeImage = ((width * bmp.bmBitsPixel + 31) / 32) * 4 * height;
|
||||
|
||||
BITMAPFILEHEADER bmfh = {0};
|
||||
bmfh.bfType = 0x4D42;
|
||||
bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
|
||||
bmfh.bfSize = bmfh.bfOffBits + bmih.biSizeImage;
|
||||
|
||||
HGLOBAL handle = GlobalAlloc(GMEM_MOVEABLE, bmih.biSizeImage);
|
||||
if (!handle) {
|
||||
TRACE(L"GlobalAlloc failed: %d", GetLastError());
|
||||
goto end;
|
||||
}
|
||||
|
||||
BYTE *bitmapData = (BYTE *)GlobalLock(handle);
|
||||
if (!bitmapData) {
|
||||
TRACE(L"GlobalLock failed: %d", GetLastError());
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!GetDIBits(hdcMemScaled, scaledBitmap, 0, height, bitmapData, (BITMAPINFO *)&bmih, DIB_RGB_COLORS)) {
|
||||
TRACE(L"GetDIBits failed: %d", GetLastError());
|
||||
goto end;
|
||||
}
|
||||
|
||||
HANDLE file = CreateFile(outputPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (file == INVALID_HANDLE_VALUE) {
|
||||
TRACE(L"CreateFile failed: %d", GetLastError());
|
||||
goto end;
|
||||
}
|
||||
|
||||
DWORD written;
|
||||
if (!WriteFile(file, &bmfh, sizeof(BITMAPFILEHEADER), &written, NULL) ||
|
||||
!WriteFile(file, &bmih, sizeof(BITMAPINFOHEADER), &written, NULL) ||
|
||||
!WriteFile(file, bitmapData, bmih.biSizeImage, &written, NULL)) {
|
||||
TRACE(L"WriteFile failed: %d", GetLastError());
|
||||
goto end;
|
||||
}
|
||||
|
||||
result = TRUE;
|
||||
|
||||
end:
|
||||
if (file && file != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(file);
|
||||
}
|
||||
if (scaledBitmap) {
|
||||
DeleteObject(scaledBitmap);
|
||||
}
|
||||
if (handle) {
|
||||
GlobalUnlock(handle);
|
||||
GlobalFree(handle);
|
||||
}
|
||||
ReleaseDC(NULL, hdc);
|
||||
DeleteDC(hdcMem);
|
||||
DeleteDC(hdcMemScaled);
|
||||
|
||||
return result;
|
||||
}
|
4
shared/LoadImage.h
Normal file
4
shared/LoadImage.h
Normal file
@@ -0,0 +1,4 @@
|
||||
#include <windows.h>
|
||||
|
||||
HBITMAP LoadPNGResource(HINSTANCE hInstance, LPWSTR resourceName, LPWSTR resourceType);
|
||||
BOOL ScaleAndWriteToBMP(HBITMAP hBitmap, DWORD width, DWORD height, LPWSTR outputPath);
|
93
shared/Registry.c
Normal file
93
shared/Registry.c
Normal file
@@ -0,0 +1,93 @@
|
||||
#include "stdafx.h"
|
||||
#include "Registry.h"
|
||||
#include "VersionInfo.h"
|
||||
#include <malloc.h>
|
||||
|
||||
static ALWAYS_INLINE REGSAM GetWow64Flag(REGSAM options) {
|
||||
#ifdef _WIN64
|
||||
return options;
|
||||
#else
|
||||
if (AtLeastWinXP2002()) {
|
||||
return options;
|
||||
}
|
||||
|
||||
// Filter out WOW64 keys, which are not supported on Windows 2000
|
||||
return options & ~(KEY_WOW64_64KEY | KEY_WOW64_32KEY);
|
||||
#endif
|
||||
}
|
||||
|
||||
HRESULT GetRegistryString(HKEY key, LPCWSTR subkeyPath, LPCWSTR valueName, REGSAM options, LPWSTR *data, LPDWORD size) {
|
||||
HKEY subkey;
|
||||
HRESULT hr = HRESULT_FROM_WIN32(RegOpenKeyEx(key, subkeyPath, 0, GetWow64Flag(KEY_READ | options), &subkey));
|
||||
if (!SUCCEEDED(hr)) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (data) {
|
||||
DWORD length = 512 * sizeof(WCHAR);
|
||||
LPWSTR buffer = (LPWSTR)LocalAlloc(LPTR, length);
|
||||
if (!buffer) {
|
||||
hr = E_OUTOFMEMORY;
|
||||
goto end;
|
||||
}
|
||||
|
||||
LSTATUS status;
|
||||
do {
|
||||
status = RegQueryValueEx(subkey, valueName, NULL, NULL, (BYTE *)buffer, &length);
|
||||
if (status == ERROR_MORE_DATA) {
|
||||
length += 256 * sizeof(WCHAR);
|
||||
LPWSTR newBuffer = (LPWSTR)LocalReAlloc(buffer, length, LMEM_MOVEABLE);
|
||||
if (!newBuffer) {
|
||||
LocalFree(buffer);
|
||||
hr = E_OUTOFMEMORY;
|
||||
goto end;
|
||||
}
|
||||
|
||||
buffer = newBuffer;
|
||||
} else if (status != ERROR_SUCCESS) {
|
||||
hr = HRESULT_FROM_WIN32(status);
|
||||
LocalFree(buffer);
|
||||
goto end;
|
||||
}
|
||||
} while (status == ERROR_MORE_DATA);
|
||||
|
||||
*data = buffer;
|
||||
|
||||
if (size) {
|
||||
*size = length / sizeof(WCHAR);
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
if (subkey) {
|
||||
RegCloseKey(subkey);
|
||||
}
|
||||
if (!SUCCEEDED(hr)) {
|
||||
if (data) {
|
||||
*data = NULL;
|
||||
}
|
||||
if (size) {
|
||||
*size = 0;
|
||||
}
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT GetRegistryDword(HKEY key, LPCWSTR subkeyPath, LPCWSTR valueName, REGSAM options, LPDWORD data) {
|
||||
HKEY subkey;
|
||||
HRESULT hr = HRESULT_FROM_WIN32(RegOpenKeyEx(key, subkeyPath, 0, GetWow64Flag(KEY_READ | options), &subkey));
|
||||
if (!SUCCEEDED(hr)) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (data) {
|
||||
DWORD length = sizeof(DWORD);
|
||||
hr = HRESULT_FROM_WIN32(RegQueryValueEx(subkey, valueName, NULL, NULL, (LPBYTE)data, &length));
|
||||
}
|
||||
|
||||
end:
|
||||
if (subkey) {
|
||||
RegCloseKey(subkey);
|
||||
}
|
||||
return hr;
|
||||
}
|
6
shared/Registry.h
Normal file
6
shared/Registry.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
EXTERN_C HRESULT GetRegistryString(HKEY key, LPCWSTR subkeyPath, LPCWSTR valueName, REGSAM options, LPWSTR *data, LPDWORD size);
|
||||
EXTERN_C HRESULT GetRegistryDword(HKEY key, LPCWSTR subkeyPath, LPCWSTR valueName, REGSAM options, LPDWORD data);
|
45
shared/Startup.h
Normal file
45
shared/Startup.h
Normal file
@@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
typedef void (WINAPI *_SetDefaultDllDirectories)(DWORD DirectoryFlags);
|
||||
typedef BOOL (WINAPI *_SetDllDirectoryW)(LPWSTR);
|
||||
|
||||
static inline void HardenDllSearchPaths() {
|
||||
// Try our best to secure DLL search paths to just system32
|
||||
WCHAR path[MAX_PATH];
|
||||
|
||||
// Reset %windir% and %SystemRoot%
|
||||
GetWindowsDirectory(path, ARRAYSIZE(path));
|
||||
SetEnvironmentVariable(L"WINDIR", path);
|
||||
SetEnvironmentVariable(L"SystemRoot", path);
|
||||
|
||||
// Reset %PATH% to just system32
|
||||
ZeroMemory(path, sizeof(path));
|
||||
GetSystemDirectory(path, ARRAYSIZE(path));
|
||||
SetEnvironmentVariable(L"PATH", path);
|
||||
|
||||
wcscat(path, L"\\kernel32.dll");
|
||||
HMODULE kernel32 = GetModuleHandle(path);
|
||||
if (!kernel32) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Windows Vista SP2+/7 SP1+ with KB2533623
|
||||
_SetDefaultDllDirectories $SetDefaultDllDirectories = (_SetDefaultDllDirectories)GetProcAddress(kernel32, "SetDefaultDllDirectories");
|
||||
if ($SetDefaultDllDirectories) {
|
||||
$SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM32);
|
||||
return;
|
||||
}
|
||||
|
||||
// Windows XP SP1+
|
||||
_SetDllDirectoryW $SetDllDirectoryW = (_SetDllDirectoryW)GetProcAddress(kernel32, "SetDllDirectoryW");
|
||||
if ($SetDllDirectoryW) {
|
||||
$SetDllDirectoryW(L"");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void Startup() {
|
||||
HardenDllSearchPaths();
|
||||
}
|
16
shared/Trace.h
Normal file
16
shared/Trace.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(ATLTRACE)
|
||||
#define TRACE ATLTRACE
|
||||
#elif defined(_DEBUG)
|
||||
// Yeah, sue me lol
|
||||
#define TRACE(...) { \
|
||||
LPWSTR __traceMsg = (LPWSTR)LocalAlloc(LPTR, 4096 * sizeof(WCHAR)); \
|
||||
wsprintf(__traceMsg, L"%hs(%d): %hs: ", __FILE__, __LINE__, __FUNCTION__); \
|
||||
wsprintf(__traceMsg + wcslen(__traceMsg), __VA_ARGS__); \
|
||||
MessageBox(NULL, __traceMsg, L"Debug", MB_OK); \
|
||||
LocalFree(__traceMsg); \
|
||||
}
|
||||
#else
|
||||
#define TRACE(...)
|
||||
#endif
|
20
shared/User.h
Normal file
20
shared/User.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
static inline BOOL IsUserAdmin() {
|
||||
SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_AUTHORITY;
|
||||
PSID adminsSid;
|
||||
BOOL result = FALSE;
|
||||
|
||||
if (!AllocateAndInitializeSid(&authority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &adminsSid)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!CheckTokenMembership(NULL, adminsSid, &result)) {
|
||||
result = FALSE;
|
||||
}
|
||||
|
||||
FreeSid(adminsSid);
|
||||
return result;
|
||||
}
|
6
shared/Version.h
Normal file
6
shared/Version.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#define VERSION_MAJOR 1
|
||||
#define VERSION_MINOR 11
|
||||
#define VERSION_PATCH 0
|
||||
#define VERSION_BUILD 0
|
||||
|
||||
#define VERSION_STRING "1.11"
|
44
shared/VersionInfo.c
Normal file
44
shared/VersionInfo.c
Normal file
@@ -0,0 +1,44 @@
|
||||
#include "stdafx.h"
|
||||
#include "VersionInfo.h"
|
||||
|
||||
static BOOL _loadedOwnVersion = FALSE;
|
||||
static LPWSTR _version;
|
||||
|
||||
HRESULT GetOwnVersion(LPWSTR *version) {
|
||||
if (!_loadedOwnVersion) {
|
||||
_loadedOwnVersion = TRUE;
|
||||
|
||||
LPWSTR filename;
|
||||
GetOwnFileName(&filename);
|
||||
|
||||
DWORD verHandle;
|
||||
DWORD verInfoSize = GetFileVersionInfoSize(filename, &verHandle);
|
||||
if (verInfoSize == 0) {
|
||||
LocalFree(filename);
|
||||
return HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
|
||||
LPVOID verInfo = LocalAlloc(LPTR, verInfoSize);
|
||||
if (!GetFileVersionInfo(filename, verHandle, verInfoSize, verInfo)) {
|
||||
LocalFree(filename);
|
||||
LocalFree(verInfo);
|
||||
return HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
|
||||
LocalFree(filename);
|
||||
|
||||
LPWSTR value;
|
||||
UINT size;
|
||||
if (!VerQueryValue(verInfo, L"\\StringFileInfo\\040904B0\\ProductVersion", (LPVOID *)&value, &size)) {
|
||||
LocalFree(verInfo);
|
||||
return HRESULT_FROM_WIN32(GetLastError());
|
||||
}
|
||||
|
||||
_version = (LPWSTR)LocalAlloc(LPTR, (wcslen(value) + 1) * sizeof(WCHAR));
|
||||
wcscpy(_version, value);
|
||||
LocalFree(verInfo);
|
||||
}
|
||||
|
||||
*version = _version;
|
||||
return _version == NULL ? E_FAIL : S_OK;
|
||||
}
|
79
shared/WMI.c
Normal file
79
shared/WMI.c
Normal file
@@ -0,0 +1,79 @@
|
||||
#include "stdafx.h"
|
||||
#include "WMI.h"
|
||||
#include <wbemcli.h>
|
||||
|
||||
#pragma comment(lib, "wbemuuid.lib")
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define our_CLSID_WbemLocator CLSID_WbemLocator
|
||||
#define our_IID_IWbemLocator IID_IWbemLocator
|
||||
#define IWbemLocator_ConnectServer(obj, ...) obj->ConnectServer(__VA_ARGS__)
|
||||
#define IWbemServices_ExecQuery(obj, ...) obj->ExecQuery(__VA_ARGS__)
|
||||
#define IEnumWbemClassObject_Next(obj, ...) obj->Next(__VA_ARGS__)
|
||||
#define IWbemClassObject_Get(obj, ...) obj->Get(__VA_ARGS__)
|
||||
#define IWbemClassObject_Release(obj) obj->Release()
|
||||
#define IEnumWbemClassObject_Release(obj) obj->Release()
|
||||
#define IWbemServices_Release(obj) obj->Release()
|
||||
#define IWbemLocator_Release(obj) obj->Release()
|
||||
#else
|
||||
#define our_CLSID_WbemLocator &CLSID_WbemLocator
|
||||
#define our_IID_IWbemLocator &IID_IWbemLocator
|
||||
#endif
|
||||
|
||||
HRESULT QueryWMIProperty(LPWSTR query, LPWSTR property, LPVARIANT value) {
|
||||
IWbemLocator *locator = NULL;
|
||||
IWbemServices *services = NULL;
|
||||
IEnumWbemClassObject *enumerator = NULL;
|
||||
IWbemClassObject *object = NULL;
|
||||
HRESULT hr = CoCreateInstance(our_CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, our_IID_IWbemLocator, (void **)&locator);
|
||||
if (!SUCCEEDED(hr)) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
BSTR server = SysAllocString(L"ROOT\\CIMV2");
|
||||
hr = IWbemLocator_ConnectServer(locator, server, NULL, NULL, NULL, 0, NULL, NULL, &services);
|
||||
SysFreeString(server);
|
||||
if (!SUCCEEDED(hr)) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
hr = CoSetProxyBlanket((IUnknown *)services, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
|
||||
if (!SUCCEEDED(hr)) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
BSTR wql = SysAllocString(L"WQL");
|
||||
BSTR queryBstr = SysAllocString(query);
|
||||
hr = IWbemServices_ExecQuery(services, wql, queryBstr, WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &enumerator);
|
||||
SysFreeString(wql);
|
||||
SysFreeString(queryBstr);
|
||||
if (!SUCCEEDED(hr)) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
ULONG uReturn = 0;
|
||||
hr = IEnumWbemClassObject_Next(enumerator, WBEM_INFINITE, 1, &object, &uReturn);
|
||||
if (!SUCCEEDED(hr)) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
BSTR propBstr = SysAllocString(property);
|
||||
hr = IWbemClassObject_Get(object, propBstr, 0, value, NULL, NULL);
|
||||
SysFreeString(propBstr);
|
||||
|
||||
end:
|
||||
if (object) {
|
||||
IWbemClassObject_Release(object);
|
||||
}
|
||||
if (enumerator) {
|
||||
IEnumWbemClassObject_Release(enumerator);
|
||||
}
|
||||
if (services) {
|
||||
IWbemServices_Release(services);
|
||||
}
|
||||
if (locator) {
|
||||
IWbemLocator_Release(locator);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
44
shared/WULog.h
Normal file
44
shared/WULog.h
Normal file
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include "stdafx.h"
|
||||
#include <windows.h>
|
||||
#include <shlobj.h>
|
||||
#include "Exec.h"
|
||||
#include "HResult.h"
|
||||
#include "VersionInfo.h"
|
||||
|
||||
static inline HRESULT ViewWindowsUpdateLog(int nCmdShow) {
|
||||
WCHAR windir[MAX_PATH];
|
||||
HRESULT hr = SHGetFolderPath(0, CSIDL_WINDOWS, NULL, 0, windir);
|
||||
if (!SUCCEEDED(hr)) {
|
||||
TRACE(L"SHGetFolderPath() failed: %ls\n", GetMessageForHresult(hr));
|
||||
return hr;
|
||||
}
|
||||
|
||||
LPWSTR workDir = windir;
|
||||
|
||||
if (AtLeastWin10()) {
|
||||
// Windows 10 moves WU/USO logs to ETW. The ETW logs can be converted back to a plain-text .log
|
||||
// using a cmdlet.
|
||||
WCHAR powershell[MAX_PATH];
|
||||
ExpandEnvironmentStrings(L"%SystemRoot%\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", powershell, ARRAYSIZE(powershell));
|
||||
|
||||
DWORD code;
|
||||
HRESULT hr = Exec(NULL, powershell, L"-Command Get-WindowsUpdateLog", windir, nCmdShow, TRUE, &code);
|
||||
if (!SUCCEEDED(hr) || code != 0) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
// On success, the log is written to Desktop\WindowsUpdate.log.
|
||||
WCHAR desktop[MAX_PATH];
|
||||
hr = SHGetFolderPath(0, CSIDL_DESKTOP, NULL, 0, desktop);
|
||||
if (!SUCCEEDED(hr)) {
|
||||
TRACE(L"SHGetFolderPath() failed: %ls\n", GetMessageForHresult(hr));
|
||||
return hr;
|
||||
}
|
||||
|
||||
workDir = desktop;
|
||||
}
|
||||
|
||||
return Exec(L"open", L"WindowsUpdate.log", NULL, workDir, nCmdShow, FALSE, NULL);
|
||||
}
|
45
shared/Wow64.c
Normal file
45
shared/Wow64.c
Normal file
@@ -0,0 +1,45 @@
|
||||
#include "stdafx.h"
|
||||
#include "Wow64.h"
|
||||
|
||||
typedef BOOL (WINAPI *_Wow64DisableWow64FsRedirection)(PVOID *OldValue);
|
||||
typedef BOOL (WINAPI *_Wow64RevertWow64FsRedirection)(PVOID OldValue);
|
||||
|
||||
static BOOL _loadedWow64;
|
||||
static _Wow64DisableWow64FsRedirection $Wow64DisableWow64FsRedirection;
|
||||
static _Wow64RevertWow64FsRedirection $Wow64RevertWow64FsRedirection;
|
||||
|
||||
#if _WIN64
|
||||
// Not needed
|
||||
#define DisableWow64FsRedirection(OldValue) TRUE
|
||||
#define RevertWow64FsRedirection(OldValue) TRUE
|
||||
#else
|
||||
static void LoadWow64Symbols() {
|
||||
if (!_loadedWow64) {
|
||||
_loadedWow64 = TRUE;
|
||||
|
||||
HMODULE kernel32 = GetModuleHandle(L"kernel32.dll");
|
||||
$Wow64DisableWow64FsRedirection = (_Wow64DisableWow64FsRedirection)GetProcAddress(kernel32, "Wow64DisableWow64FsRedirection");
|
||||
$Wow64RevertWow64FsRedirection = (_Wow64RevertWow64FsRedirection)GetProcAddress(kernel32, "Wow64RevertWow64FsRedirection");
|
||||
}
|
||||
}
|
||||
|
||||
BOOL DisableWow64FsRedirection(PVOID *OldValue) {
|
||||
LoadWow64Symbols();
|
||||
|
||||
if ($Wow64DisableWow64FsRedirection) {
|
||||
return $Wow64DisableWow64FsRedirection(OldValue);
|
||||
} else {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL RevertWow64FsRedirection(PVOID OldValue) {
|
||||
LoadWow64Symbols();
|
||||
|
||||
if ($Wow64RevertWow64FsRedirection) {
|
||||
return $Wow64RevertWow64FsRedirection(OldValue);
|
||||
} else {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
#endif
|
6
shared/Wow64.h
Normal file
6
shared/Wow64.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
BOOL DisableWow64FsRedirection(PVOID *OldValue);
|
||||
BOOL RevertWow64FsRedirection(PVOID OldValue);
|
Reference in New Issue
Block a user