many changes, see description [skip ci]

Note: currently only works via manual injection, Rundll32Entry has been removed

- Fixed conflict with UpdatePack7R2 (and WuaCpuFix) by hooking `RegQueryValueExW` and fixing the path to `wuaueng.dll`. (fixes #100)
- Eliminated lots of redundant and unnecessary code.
- Other reliability improvements and bug fixes.
- Removed the error message that displays in the installers when `wuaueng.dll` is below the minimum supported version, and added an internal check that will skip the patching procedure if the version of `wuaueng.dll` is too low. **This means you can now safely install wufuc prior to any updates, and it will automatically start working once it's needed, without any potential side effects.** (fixes #99)
- Added `/UNATTENDED` flag to the batch installer and uninstaller. You can use this to bypass the confirmation for a fully automated installation/uninstallation. To use it, you invoke the batch script from an elevated command prompt, like so: `"wufuc_installer.bat" /UNATTENDED`
- Improved logging framework to allow multiple processes to safely write to the same `.log` file.
This commit is contained in:
zeffy
2017-09-21 19:09:03 -07:00
parent 9ec707e3f5
commit ab40ad39a2
32 changed files with 600 additions and 809 deletions

View File

@@ -1,12 +1,11 @@
#include "helpers.h"
#include "logging.h"
#include "tracing.h"
#include <stdint.h>
#include <Windows.h>
#include <tchar.h>
#include <Psapi.h>
#include <TlHelp32.h>
static BOOL CompareWindowsVersion(BYTE Operator, DWORD dwMajorVersion, DWORD dwMinorVersion, WORD wServicePackMajor, WORD wServicePackMinor, DWORD dwTypeMask) {
@@ -27,25 +26,23 @@ static BOOL CompareWindowsVersion(BYTE Operator, DWORD dwMajorVersion, DWORD dwM
}
BOOL IsWindows7(void) {
static BOOL m_checkedIsWindows7 = FALSE;
static BOOL m_isWindows7 = FALSE;
static BOOL checked = FALSE, isWindows7 = FALSE;
if ( !m_checkedIsWindows7 ) {
m_isWindows7 = CompareWindowsVersion(VER_EQUAL, 6, 1, 0, 0, VER_MAJORVERSION | VER_MINORVERSION);
m_checkedIsWindows7 = TRUE;
if ( !checked ) {
isWindows7 = CompareWindowsVersion(VER_EQUAL, 6, 1, 0, 0, VER_MAJORVERSION | VER_MINORVERSION);
checked = TRUE;
}
return m_isWindows7;
return isWindows7;
}
BOOL IsWindows8Point1(void) {
static BOOL m_checkedIsWindows8Point1 = FALSE;
static BOOL m_isWindows8Point1 = FALSE;
static BOOL checked = FALSE, isWindows8Point1 = FALSE;
if ( !m_checkedIsWindows8Point1 ) {
m_isWindows8Point1 = CompareWindowsVersion(VER_EQUAL, 6, 3, 0, 0, VER_MAJORVERSION | VER_MINORVERSION);
m_checkedIsWindows8Point1 = TRUE;
if ( !checked ) {
isWindows8Point1 = CompareWindowsVersion(VER_EQUAL, 6, 3, 0, 0, VER_MAJORVERSION | VER_MINORVERSION);
checked = TRUE;
}
return m_isWindows8Point1;
return isWindows8Point1;
}
BOOL IsOperatingSystemSupported(void) {
@@ -57,64 +54,87 @@ BOOL IsOperatingSystemSupported(void) {
}
BOOL IsWow64(void) {
static BOOL m_checkedIsWow64 = FALSE;
static BOOL m_isWow64 = FALSE;
static ISWOW64PROCESS fpIsWow64Process = NULL;
static BOOL checked = FALSE, isWow64 = FALSE;
static ISWOW64PROCESS pfnIsWow64Process = NULL;
if ( !m_checkedIsWow64 ) {
if ( !fpIsWow64Process )
fpIsWow64Process = (ISWOW64PROCESS)GetProcAddress(GetModuleHandle(_T("kernel32.dll")), "IsWow64Process");
if ( !checked ) {
if ( !pfnIsWow64Process )
pfnIsWow64Process = (ISWOW64PROCESS)GetProcAddress(GetModuleHandle(_T("kernel32.dll")), "IsWow64Process");
if ( fpIsWow64Process && fpIsWow64Process(GetCurrentProcess(), &m_isWow64) )
m_checkedIsWow64 = TRUE;
if ( pfnIsWow64Process && pfnIsWow64Process(GetCurrentProcess(), &isWow64) )
checked = TRUE;
}
return m_isWow64;
return isWow64;
}
void suspend_other_threads(LPHANDLE lphThreads, size_t *lpcb) {
DWORD dwProcessId = GetCurrentProcessId();
DWORD dwThreadId = GetCurrentThreadId();
size_t suspend_other_threads(LPHANDLE lphThreads, size_t nMaxCount) {
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
THREADENTRY32 te = { 0 };
te.dwSize = sizeof(te);
Thread32First(hSnap, &te);
size_t count = 0;
do {
if ( te.th32OwnerProcessID != dwProcessId || te.th32ThreadID == dwThreadId )
continue;
if ( Thread32First(hSnap, &te) ) {
DWORD dwProcessId = GetCurrentProcessId();
DWORD dwThreadId = GetCurrentThreadId();
WaitForTracingMutex(); // make sure we don't dead lock
do {
if ( te.th32OwnerProcessID != dwProcessId || te.th32ThreadID == dwThreadId )
continue;
lphThreads[count] = OpenThread(THREAD_SUSPEND_RESUME, FALSE, te.th32ThreadID);
SuspendThread(lphThreads[count]);
count++;
} while ( count < *lpcb && Thread32Next(hSnap, &te) );
lphThreads[count] = OpenThread(THREAD_SUSPEND_RESUME, FALSE, te.th32ThreadID);
SuspendThread(lphThreads[count]);
count++;
} while ( count < nMaxCount && Thread32Next(hSnap, &te) );
ReleaseTracingMutex();
}
CloseHandle(hSnap);
*lpcb = count;
trace(_T("Suspended %d other threads"), count);
trace(_T("Suspended %zu other threads"), count);
return count;
}
void resume_and_close_threads(LPHANDLE lphThreads, size_t cb) {
for ( size_t i = 0; i < cb; i++ ) {
void resume_and_close_threads(LPHANDLE lphThreads, size_t nCount) {
for ( size_t i = 0; i < nCount; i++ ) {
ResumeThread(lphThreads[i]);
CloseHandle(lphThreads[i]);
}
trace(_T("Resumed %d threads"), cb);
trace(_T("Resumed %zu threads"), nCount);
}
void get_cpuid_brand(char *brand) {
char *get_cpuid_brand(char *brand, size_t nMaxCount) {
int info[4];
__cpuidex(info, 0x80000000, 0);
if ( info[0] < 0x80000004 ) {
brand[0] = '\0';
return;
return brand;
}
uint32_t *char_as_int = (uint32_t *)brand;
for ( int op = 0x80000002; op <= 0x80000004; op++ ) {
__cpuidex(info, op, 0);
*(char_as_int++) = info[0];
*(char_as_int++) = info[1];
*(char_as_int++) = info[2];
*(char_as_int++) = info[3];
for ( int i = 0; i < 4; i++ )
*(char_as_int++) = info[i];
}
size_t i = 0;
while ( i < nMaxCount && isspace(brand[i]) )
i++;
return brand + i;
}
wchar_t *find_fname(wchar_t *pPath) {
wchar_t *pwc = wcsrchr(pPath, L'\\');
if ( pwc && *(++pwc) )
return pwc;
return pPath;
}
int compare_versions(WORD ma1, WORD mi1, WORD b1, WORD r1, WORD ma2, WORD mi2, WORD b2, WORD r2) {
if ( ma1 < ma2 ) return -1;
if ( ma1 > ma2 ) return 1;
if ( mi1 < mi2 ) return -1;
if ( mi1 > mi2 ) return 1;
if ( b1 < b2 ) return -1;
if ( b1 > b2 ) return 1;
if ( r1 < r2 ) return -1;
if ( r1 > r2 ) return 1;
return 0;
}