154 lines
3.8 KiB
C
154 lines
3.8 KiB
C
#include <windows.h>
|
|
#include "Exec.h"
|
|
#include "HResult.h"
|
|
#include "LegacyUpdate.h"
|
|
#include "MsgBox.h"
|
|
#include "Registry.h"
|
|
#include "SelfElevate.h"
|
|
#include "User.h"
|
|
#include "VersionInfo.h"
|
|
#include "Wow64.h"
|
|
|
|
static HRESULT RegisterDllInternal(LPWSTR path, BOOL state) {
|
|
HMODULE module = LoadLibrary(path);
|
|
if (!module) {
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
HRESULT hr = S_OK;
|
|
FARPROC proc = GetProcAddress(module, state ? "DllRegisterServer" : "DllUnregisterServer");
|
|
if (!proc) {
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto end;
|
|
}
|
|
|
|
hr = ((HRESULT (WINAPI *)())proc)();
|
|
|
|
end:
|
|
if (module) {
|
|
FreeLibrary(module);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
static HRESULT RegisterDllExternal(LPWSTR path, BOOL state) {
|
|
WCHAR regsvr32[MAX_PATH];
|
|
ExpandEnvironmentStrings(L"%SystemRoot%\\System32\\regsvr32.exe", regsvr32, ARRAYSIZE(regsvr32));
|
|
|
|
LPWSTR args = (LPWSTR)LocalAlloc(LPTR, (lstrlen(path) + 6) * sizeof(WCHAR));
|
|
wsprintf(args, L"/s %ls\"%ls\"", state ? L"" : L"/u ", path);
|
|
|
|
DWORD status;
|
|
HRESULT hr = Exec(NULL, regsvr32, args, NULL, SW_HIDE, TRUE, &status);
|
|
if (!SUCCEEDED(hr)) {
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
return hr;
|
|
}
|
|
|
|
if (status != 0) {
|
|
// Run again without /s, so the user can see the error
|
|
wsprintf(args, L"%ls\"%ls\"", state ? L"" : L"/u ", path);
|
|
hr = Exec(NULL, regsvr32, args, NULL, SW_SHOWDEFAULT, TRUE, &status);
|
|
}
|
|
|
|
return status == 0 ? S_OK : E_FAIL;
|
|
}
|
|
|
|
HRESULT RegisterServer(HWND hwnd, BOOL state, BOOL forLaunch) {
|
|
// Ensure elevation
|
|
HRESULT hr = S_OK;
|
|
LPWSTR installPath;
|
|
LPWSTR dllPath;
|
|
|
|
if (!IsUserAdmin()) {
|
|
LPWSTR args = (LPWSTR)LocalAlloc(LPTR, 512 * sizeof(WCHAR));
|
|
wsprintf(args, L"%ls %i", state ? L"/regserver" : L"/unregserver", hwnd);
|
|
DWORD code;
|
|
hr = SelfElevate(args, &code);
|
|
if (!SUCCEEDED(hr)) {
|
|
// Ignore error on cancelling UAC dialog
|
|
if (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED)) {
|
|
hr = S_OK;
|
|
}
|
|
goto end;
|
|
}
|
|
|
|
hr = HRESULT_FROM_WIN32(code);
|
|
goto end;
|
|
}
|
|
|
|
hr = GetInstallPath(&installPath);
|
|
if (!SUCCEEDED(hr)) {
|
|
goto end;
|
|
}
|
|
|
|
dllPath = (LPWSTR)LocalAlloc(LPTR, MAX_PATH * sizeof(WCHAR));
|
|
wsprintf(dllPath, L"%ls\\LegacyUpdate.dll", installPath);
|
|
|
|
#ifdef _DEBUG
|
|
// Warn if registration path differs, to help with debugging
|
|
LPWSTR currentPath;
|
|
hr = GetRegistryString(HKEY_CLASSES_ROOT, L"CLSID\\{AD28E0DF-5F5A-40B5-9432-85EFD97D1F9F}\\InprocServer32", NULL, KEY_WOW64_64KEY, ¤tPath, NULL);
|
|
if (SUCCEEDED(hr) && wcscmp(currentPath, dllPath) != 0) {
|
|
if (MsgBox(hwnd, L"DEBUG: Native dll currently registered at a different path. Override?", currentPath, MB_YESNO) != IDYES) {
|
|
hr = S_OK;
|
|
goto end;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
hr = RegisterDllInternal(dllPath, state);
|
|
if (!SUCCEEDED(hr)) {
|
|
// Try external registration
|
|
if (SUCCEEDED(RegisterDllExternal(dllPath, state))) {
|
|
hr = S_OK;
|
|
} else {
|
|
goto end;
|
|
}
|
|
}
|
|
|
|
#if _WIN64
|
|
if (!SUCCEEDED(hr)) {
|
|
goto end;
|
|
}
|
|
|
|
wsprintf(dllPath, L"%ls\\LegacyUpdate32.dll", installPath);
|
|
|
|
#ifdef _DEBUG
|
|
// Warn if registration path differs, to help with debugging
|
|
hr = GetRegistryString(HKEY_CLASSES_ROOT, L"CLSID\\{AD28E0DF-5F5A-40B5-9432-85EFD97D1F9F}\\InprocServer32", NULL, KEY_WOW64_32KEY, ¤tPath, NULL);
|
|
if (SUCCEEDED(hr) && wcscmp(currentPath, dllPath) != 0) {
|
|
if (MsgBox(hwnd, L"DEBUG: 32-bit dll currently registered at a different path. Override?", currentPath, MB_YESNO) != IDYES) {
|
|
hr = S_OK;
|
|
goto end;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
hr = RegisterDllExternal(dllPath, state);
|
|
#endif
|
|
|
|
end:
|
|
if (installPath) {
|
|
LocalFree(installPath);
|
|
}
|
|
|
|
if (dllPath) {
|
|
LocalFree(dllPath);
|
|
}
|
|
|
|
if (!SUCCEEDED(hr)) {
|
|
LPWSTR title = state
|
|
? L"Failed to register Legacy Update ActiveX control"
|
|
: L"Failed to unregister Legacy Update ActiveX control";
|
|
MsgBox(hwnd, title, GetMessageForHresult(hr), MB_ICONERROR);
|
|
}
|
|
|
|
if (!forLaunch) {
|
|
PostQuitMessage(hr);
|
|
}
|
|
|
|
return hr;
|
|
}
|