mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Removed hooks on DLL_PROCESS_DETACH
Fixes a crash when opening Blood 2's display settings from the launcher.
This commit is contained in:
parent
44cc4c2ad5
commit
9ddeab4149
@ -196,6 +196,20 @@ namespace CompatGdi
|
|||||||
return RealPrimarySurface::isFullScreen();
|
return RealPrimarySurface::isFullScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void unhookWndProc(LPCSTR className, WNDPROC oldWndProc)
|
||||||
|
{
|
||||||
|
HWND hwnd = CreateWindow(className, nullptr, 0, 0, 0, 0, 0, nullptr, nullptr, nullptr, 0);
|
||||||
|
SetClassLongPtr(hwnd, GCLP_WNDPROC, reinterpret_cast<LONG>(oldWndProc));
|
||||||
|
DestroyWindow(hwnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uninstallHooks()
|
||||||
|
{
|
||||||
|
CompatGdiCaret::uninstallHooks();
|
||||||
|
CompatGdiWinProc::uninstallHooks();
|
||||||
|
CompatGdiPaintHandlers::uninstallHooks();
|
||||||
|
}
|
||||||
|
|
||||||
void updatePalette(DWORD startingEntry, DWORD count)
|
void updatePalette(DWORD startingEntry, DWORD count)
|
||||||
{
|
{
|
||||||
if (isEmulationEnabled() && CompatPrimarySurface::palette)
|
if (isEmulationEnabled() && CompatPrimarySurface::palette)
|
||||||
|
@ -13,6 +13,8 @@ namespace CompatGdi
|
|||||||
void installHooks();
|
void installHooks();
|
||||||
void invalidate(const RECT* rect);
|
void invalidate(const RECT* rect);
|
||||||
bool isEmulationEnabled();
|
bool isEmulationEnabled();
|
||||||
|
void unhookWndProc(LPCSTR className, WNDPROC oldWndProc);
|
||||||
|
void uninstallHooks();
|
||||||
void updatePalette(DWORD startingEntry, DWORD count);
|
void updatePalette(DWORD startingEntry, DWORD count);
|
||||||
|
|
||||||
extern CRITICAL_SECTION g_gdiCriticalSection;
|
extern CRITICAL_SECTION g_gdiCriticalSection;
|
||||||
|
@ -10,6 +10,9 @@
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
HWINEVENTHOOK g_compatGdiCaretGeneralEventHook = nullptr;
|
||||||
|
HWINEVENTHOOK g_compatGdiCaretLocationChangeEventHook = nullptr;
|
||||||
|
|
||||||
template <typename Result, typename... Params>
|
template <typename Result, typename... Params>
|
||||||
using FuncPtr = Result(WINAPI *)(Params...);
|
using FuncPtr = Result(WINAPI *)(Params...);
|
||||||
|
|
||||||
@ -121,18 +124,23 @@ namespace CompatGdiCaret
|
|||||||
{
|
{
|
||||||
InitializeCriticalSection(&g_caretCriticalSection);
|
InitializeCriticalSection(&g_caretCriticalSection);
|
||||||
|
|
||||||
Compat::beginHookTransaction();
|
|
||||||
HOOK_GDI_CARET_FUNCTION(user32, CreateCaret);
|
HOOK_GDI_CARET_FUNCTION(user32, CreateCaret);
|
||||||
HOOK_GDI_CARET_FUNCTION(user32, DestroyCaret);
|
HOOK_GDI_CARET_FUNCTION(user32, DestroyCaret);
|
||||||
HOOK_GDI_CARET_FUNCTION(user32, HideCaret);
|
HOOK_GDI_CARET_FUNCTION(user32, HideCaret);
|
||||||
HOOK_GDI_CARET_FUNCTION(user32, SetCaretPos);
|
HOOK_GDI_CARET_FUNCTION(user32, SetCaretPos);
|
||||||
HOOK_GDI_CARET_FUNCTION(user32, ShowCaret);
|
HOOK_GDI_CARET_FUNCTION(user32, ShowCaret);
|
||||||
Compat::endHookTransaction();
|
|
||||||
|
|
||||||
const DWORD threadId = GetCurrentThreadId();
|
const DWORD threadId = GetCurrentThreadId();
|
||||||
SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_HIDE,
|
g_compatGdiCaretGeneralEventHook = SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_HIDE,
|
||||||
nullptr, &compatGdiCaretEvent, 0, threadId, WINEVENT_OUTOFCONTEXT);
|
|
||||||
SetWinEventHook(EVENT_OBJECT_LOCATIONCHANGE, EVENT_OBJECT_LOCATIONCHANGE,
|
|
||||||
nullptr, &compatGdiCaretEvent, 0, threadId, WINEVENT_OUTOFCONTEXT);
|
nullptr, &compatGdiCaretEvent, 0, threadId, WINEVENT_OUTOFCONTEXT);
|
||||||
|
g_compatGdiCaretLocationChangeEventHook = SetWinEventHook(
|
||||||
|
EVENT_OBJECT_LOCATIONCHANGE, EVENT_OBJECT_LOCATIONCHANGE, nullptr, &compatGdiCaretEvent,
|
||||||
|
0, threadId, WINEVENT_OUTOFCONTEXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void uninstallHooks()
|
||||||
|
{
|
||||||
|
UnhookWinEvent(g_compatGdiCaretLocationChangeEventHook);
|
||||||
|
UnhookWinEvent(g_compatGdiCaretGeneralEventHook);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,4 +3,5 @@
|
|||||||
namespace CompatGdiCaret
|
namespace CompatGdiCaret
|
||||||
{
|
{
|
||||||
void installHooks();
|
void installHooks();
|
||||||
|
void uninstallHooks();
|
||||||
}
|
}
|
||||||
|
@ -135,8 +135,6 @@ namespace CompatGdiDcFunctions
|
|||||||
{
|
{
|
||||||
void installHooks()
|
void installHooks()
|
||||||
{
|
{
|
||||||
Compat::beginHookTransaction();
|
|
||||||
|
|
||||||
// Bitmap functions
|
// Bitmap functions
|
||||||
HOOK_GDI_DC_FUNCTION(msimg32, AlphaBlend);
|
HOOK_GDI_DC_FUNCTION(msimg32, AlphaBlend);
|
||||||
HOOK_GDI_DC_FUNCTION(gdi32, BitBlt);
|
HOOK_GDI_DC_FUNCTION(gdi32, BitBlt);
|
||||||
@ -226,7 +224,5 @@ namespace CompatGdiDcFunctions
|
|||||||
// Undocumented functions
|
// Undocumented functions
|
||||||
HOOK_GDI_DC_FUNCTION(gdi32, GdiDrawStream);
|
HOOK_GDI_DC_FUNCTION(gdi32, GdiDrawStream);
|
||||||
HOOK_GDI_DC_FUNCTION(gdi32, PolyPatBlt);
|
HOOK_GDI_DC_FUNCTION(gdi32, PolyPatBlt);
|
||||||
|
|
||||||
Compat::endHookTransaction();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -316,11 +316,18 @@ namespace CompatGdiPaintHandlers
|
|||||||
CompatGdi::hookWndProc("#32768", g_origMenuWndProc, &menuWndProc);
|
CompatGdi::hookWndProc("#32768", g_origMenuWndProc, &menuWndProc);
|
||||||
CompatGdi::hookWndProc("ScrollBar", g_origScrollBarWndProc, &scrollBarWndProc);
|
CompatGdi::hookWndProc("ScrollBar", g_origScrollBarWndProc, &scrollBarWndProc);
|
||||||
|
|
||||||
Compat::beginHookTransaction();
|
|
||||||
HOOK_FUNCTION(user32, DefWindowProcA, defWindowProcA);
|
HOOK_FUNCTION(user32, DefWindowProcA, defWindowProcA);
|
||||||
HOOK_FUNCTION(user32, DefWindowProcW, defWindowProcW);
|
HOOK_FUNCTION(user32, DefWindowProcW, defWindowProcW);
|
||||||
HOOK_FUNCTION(user32, DefDlgProcA, defDlgProcA);
|
HOOK_FUNCTION(user32, DefDlgProcA, defDlgProcA);
|
||||||
HOOK_FUNCTION(user32, DefDlgProcW, defDlgProcW);
|
HOOK_FUNCTION(user32, DefDlgProcW, defDlgProcW);
|
||||||
Compat::endHookTransaction();
|
}
|
||||||
|
|
||||||
|
void uninstallHooks()
|
||||||
|
{
|
||||||
|
CompatGdi::unhookWndProc("ComboLBox", g_origComboListBoxWndProc);
|
||||||
|
CompatGdi::unhookWndProc("Edit", g_origEditWndProc);
|
||||||
|
CompatGdi::unhookWndProc("ListBox", g_origListBoxWndProc);
|
||||||
|
CompatGdi::unhookWndProc("#32768", g_origMenuWndProc);
|
||||||
|
CompatGdi::unhookWndProc("ScrollBar", g_origScrollBarWndProc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,4 +3,5 @@
|
|||||||
namespace CompatGdiPaintHandlers
|
namespace CompatGdiPaintHandlers
|
||||||
{
|
{
|
||||||
void installHooks();
|
void installHooks();
|
||||||
|
void uninstallHooks();
|
||||||
}
|
}
|
||||||
|
@ -47,10 +47,8 @@ namespace CompatGdiScrollFunctions
|
|||||||
{
|
{
|
||||||
void installHooks()
|
void installHooks()
|
||||||
{
|
{
|
||||||
Compat::beginHookTransaction();
|
|
||||||
HOOK_FUNCTION(user32, ScrollWindow, scrollWindow);
|
HOOK_FUNCTION(user32, ScrollWindow, scrollWindow);
|
||||||
HOOK_FUNCTION(user32, ScrollWindowEx, scrollWindowEx);
|
HOOK_FUNCTION(user32, ScrollWindowEx, scrollWindowEx);
|
||||||
Compat::endHookTransaction();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateScrolledWindow(HWND hwnd)
|
void updateScrolledWindow(HWND hwnd)
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
HHOOK g_callWndRetProcHook = nullptr;
|
||||||
|
HWINEVENTHOOK g_objectStateChangeEventHook = nullptr;
|
||||||
std::unordered_map<HWND, RECT> g_prevWindowRect;
|
std::unordered_map<HWND, RECT> g_prevWindowRect;
|
||||||
|
|
||||||
void disableDwmAttributes(HWND hwnd);
|
void disableDwmAttributes(HWND hwnd);
|
||||||
@ -196,8 +198,14 @@ namespace CompatGdiWinProc
|
|||||||
void installHooks()
|
void installHooks()
|
||||||
{
|
{
|
||||||
const DWORD threadId = GetCurrentThreadId();
|
const DWORD threadId = GetCurrentThreadId();
|
||||||
SetWindowsHookEx(WH_CALLWNDPROCRET, callWndRetProc, nullptr, threadId);
|
g_callWndRetProcHook = SetWindowsHookEx(WH_CALLWNDPROCRET, callWndRetProc, nullptr, threadId);
|
||||||
SetWinEventHook(EVENT_OBJECT_STATECHANGE, EVENT_OBJECT_STATECHANGE,
|
g_objectStateChangeEventHook = SetWinEventHook(EVENT_OBJECT_STATECHANGE, EVENT_OBJECT_STATECHANGE,
|
||||||
nullptr, &objectStateChangeEvent, 0, threadId, WINEVENT_OUTOFCONTEXT);
|
nullptr, &objectStateChangeEvent, 0, threadId, WINEVENT_OUTOFCONTEXT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void uninstallHooks()
|
||||||
|
{
|
||||||
|
UnhookWinEvent(g_objectStateChangeEventHook);
|
||||||
|
UnhookWindowsHookEx(g_callWndRetProcHook);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,4 +3,5 @@
|
|||||||
namespace CompatGdiWinProc
|
namespace CompatGdiWinProc
|
||||||
{
|
{
|
||||||
void installHooks();
|
void installHooks();
|
||||||
|
void uninstallHooks();
|
||||||
}
|
}
|
||||||
|
@ -90,9 +90,7 @@ namespace CompatRegistry
|
|||||||
{
|
{
|
||||||
void installHooks()
|
void installHooks()
|
||||||
{
|
{
|
||||||
Compat::beginHookTransaction();
|
|
||||||
HOOK_FUNCTION(KernelBase, RegGetValueW, regGetValueW);
|
HOOK_FUNCTION(KernelBase, RegGetValueW, regGetValueW);
|
||||||
Compat::endHookTransaction();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setValue(HKEY key, const char* subKey, const char* valueName, DWORD value)
|
void setValue(HKEY key, const char* subKey, const char* valueName, DWORD value)
|
||||||
|
@ -114,9 +114,7 @@ private:
|
|||||||
s_vtablePtrToCompatVtable[s_vtablePtr] = &s_compatVtable;
|
s_vtablePtrToCompatVtable[s_vtablePtr] = &s_compatVtable;
|
||||||
Compat::g_hookedMethods.emplace(origMethodPtr,
|
Compat::g_hookedMethods.emplace(origMethodPtr,
|
||||||
Compat::HookedMethodInfo(origMethodPtr, s_vtablePtrToCompatVtable));
|
Compat::HookedMethodInfo(origMethodPtr, s_vtablePtrToCompatVtable));
|
||||||
Compat::beginHookTransaction();
|
|
||||||
Compat::hookFunction(origMethodPtr, newMethodPtr);
|
Compat::hookFunction(origMethodPtr, newMethodPtr);
|
||||||
Compat::endHookTransaction();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "CompatVtable.h"
|
#include "CompatVtable.h"
|
||||||
#include "DDrawProcs.h"
|
#include "DDrawProcs.h"
|
||||||
#include "DDrawRepository.h"
|
#include "DDrawRepository.h"
|
||||||
|
#include "RealPrimarySurface.h"
|
||||||
#include "Time.h"
|
#include "Time.h"
|
||||||
|
|
||||||
struct IDirectInput;
|
struct IDirectInput;
|
||||||
@ -142,6 +143,10 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID /*lpvReserved*/)
|
|||||||
{
|
{
|
||||||
if (fdwReason == DLL_PROCESS_ATTACH)
|
if (fdwReason == DLL_PROCESS_ATTACH)
|
||||||
{
|
{
|
||||||
|
char currentProcessPath[MAX_PATH] = {};
|
||||||
|
GetModuleFileName(nullptr, currentProcessPath, MAX_PATH);
|
||||||
|
Compat::Log() << "Process path: " << currentProcessPath;
|
||||||
|
|
||||||
char currentDllPath[MAX_PATH] = {};
|
char currentDllPath[MAX_PATH] = {};
|
||||||
GetModuleFileName(hinstDLL, currentDllPath, MAX_PATH);
|
GetModuleFileName(hinstDLL, currentDllPath, MAX_PATH);
|
||||||
Compat::Log() << "Loading DDrawCompat from " << currentDllPath;
|
Compat::Log() << "Loading DDrawCompat from " << currentDllPath;
|
||||||
@ -181,8 +186,13 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID /*lpvReserved*/)
|
|||||||
}
|
}
|
||||||
else if (fdwReason == DLL_PROCESS_DETACH)
|
else if (fdwReason == DLL_PROCESS_DETACH)
|
||||||
{
|
{
|
||||||
|
Compat::Log() << "Detaching DDrawCompat";
|
||||||
|
RealPrimarySurface::removeUpdateThread();
|
||||||
|
CompatGdi::uninstallHooks();
|
||||||
|
Compat::unhookAllFunctions();
|
||||||
FreeLibrary(g_origDInputModule);
|
FreeLibrary(g_origDInputModule);
|
||||||
FreeLibrary(g_origDDrawModule);
|
FreeLibrary(g_origDDrawModule);
|
||||||
|
Compat::Log() << "DDrawCompat detached successfully";
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <detours.h>
|
#include <detours.h>
|
||||||
|
|
||||||
@ -8,6 +11,8 @@
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
std::vector<std::pair<void*, void*>> g_hookedFunctions;
|
||||||
|
|
||||||
FARPROC getProcAddress(HMODULE module, const char* procName)
|
FARPROC getProcAddress(HMODULE module, const char* procName)
|
||||||
{
|
{
|
||||||
if (!module || !procName)
|
if (!module || !procName)
|
||||||
@ -45,25 +50,36 @@ namespace
|
|||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void hookFunction(const char* funcName, void*& origFuncPtr, void* newFuncPtr)
|
||||||
|
{
|
||||||
|
DetourTransactionBegin();
|
||||||
|
const bool attachSuccessful = NO_ERROR == DetourAttach(&origFuncPtr, newFuncPtr);
|
||||||
|
const bool commitSuccessful = NO_ERROR == DetourTransactionCommit();
|
||||||
|
if (!attachSuccessful || !commitSuccessful)
|
||||||
|
{
|
||||||
|
if (funcName)
|
||||||
|
{
|
||||||
|
Compat::Log() << "Failed to hook a function: " << funcName;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Compat::Log() << "Failed to hook a function: " << origFuncPtr;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_hookedFunctions.push_back(std::make_pair(origFuncPtr, newFuncPtr));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Compat
|
namespace Compat
|
||||||
{
|
{
|
||||||
void beginHookTransaction()
|
|
||||||
{
|
|
||||||
DetourTransactionBegin();
|
|
||||||
}
|
|
||||||
|
|
||||||
void endHookTransaction()
|
|
||||||
{
|
|
||||||
DetourTransactionCommit();
|
|
||||||
}
|
|
||||||
|
|
||||||
void hookFunction(void*& origFuncPtr, void* newFuncPtr)
|
void hookFunction(void*& origFuncPtr, void* newFuncPtr)
|
||||||
{
|
{
|
||||||
DetourAttach(&origFuncPtr, newFuncPtr);
|
::hookFunction(nullptr, origFuncPtr, newFuncPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void hookFunction(const char* moduleName, const char* funcName, void*& origFuncPtr, void* newFuncPtr)
|
void hookFunction(const char* moduleName, const char* funcName, void*& origFuncPtr, void* newFuncPtr)
|
||||||
{
|
{
|
||||||
FARPROC procAddr = getProcAddress(GetModuleHandle(moduleName), funcName);
|
FARPROC procAddr = getProcAddress(GetModuleHandle(moduleName), funcName);
|
||||||
@ -74,10 +90,16 @@ namespace Compat
|
|||||||
}
|
}
|
||||||
|
|
||||||
origFuncPtr = procAddr;
|
origFuncPtr = procAddr;
|
||||||
if (NO_ERROR != DetourAttach(&origFuncPtr, newFuncPtr))
|
::hookFunction(funcName, origFuncPtr, newFuncPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void unhookAllFunctions()
|
||||||
|
{
|
||||||
|
for (auto& hookedFunc : g_hookedFunctions)
|
||||||
{
|
{
|
||||||
Compat::Log() << "Failed to hook a function: " << funcName;
|
DetourTransactionBegin();
|
||||||
return;
|
DetourDetach(&hookedFunc.first, hookedFunc.second);
|
||||||
|
DetourTransactionCommit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -7,9 +7,6 @@
|
|||||||
|
|
||||||
namespace Compat
|
namespace Compat
|
||||||
{
|
{
|
||||||
void beginHookTransaction();
|
|
||||||
void endHookTransaction();
|
|
||||||
|
|
||||||
template <typename OrigFuncPtr, OrigFuncPtr origFunc>
|
template <typename OrigFuncPtr, OrigFuncPtr origFunc>
|
||||||
OrigFuncPtr& getOrigFuncPtr()
|
OrigFuncPtr& getOrigFuncPtr()
|
||||||
{
|
{
|
||||||
@ -26,4 +23,6 @@ namespace Compat
|
|||||||
hookFunction(moduleName, funcName,
|
hookFunction(moduleName, funcName,
|
||||||
reinterpret_cast<void*&>(getOrigFuncPtr<OrigFuncPtr, origFunc>()), newFuncPtr);
|
reinterpret_cast<void*&>(getOrigFuncPtr<OrigFuncPtr, origFunc>()), newFuncPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void unhookAllFunctions();
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ namespace
|
|||||||
IDirectDrawSurface7* g_backBuffer = nullptr;
|
IDirectDrawSurface7* g_backBuffer = nullptr;
|
||||||
IReleaseNotifier g_releaseNotifier(onRelease);
|
IReleaseNotifier g_releaseNotifier(onRelease);
|
||||||
|
|
||||||
|
bool g_stopUpdateThread = false;
|
||||||
HANDLE g_updateThread = nullptr;
|
HANDLE g_updateThread = nullptr;
|
||||||
HANDLE g_updateEvent = nullptr;
|
HANDLE g_updateEvent = nullptr;
|
||||||
RECT g_updateRect = {};
|
RECT g_updateRect = {};
|
||||||
@ -140,6 +141,11 @@ namespace
|
|||||||
{
|
{
|
||||||
WaitForSingleObject(g_updateEvent, INFINITE);
|
WaitForSingleObject(g_updateEvent, INFINITE);
|
||||||
|
|
||||||
|
if (g_stopUpdateThread)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
const long long qpcTargetNextUpdate = g_qpcNextUpdate;
|
const long long qpcTargetNextUpdate = g_qpcNextUpdate;
|
||||||
const int msUntilNextUpdate =
|
const int msUntilNextUpdate =
|
||||||
Time::qpcToMs(qpcTargetNextUpdate - Time::queryPerformanceCounter());
|
Time::qpcToMs(qpcTargetNextUpdate - Time::queryPerformanceCounter());
|
||||||
@ -317,6 +323,25 @@ void RealPrimarySurface::release()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RealPrimarySurface::removeUpdateThread()
|
||||||
|
{
|
||||||
|
if (!g_updateThread)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_stopUpdateThread = true;
|
||||||
|
SetEvent(g_updateEvent);
|
||||||
|
if (WAIT_OBJECT_0 != WaitForSingleObject(g_updateThread, 1000))
|
||||||
|
{
|
||||||
|
TerminateThread(g_updateThread, 0);
|
||||||
|
Compat::Log() << "The update thread was terminated forcefully";
|
||||||
|
}
|
||||||
|
ResetEvent(g_updateEvent);
|
||||||
|
g_stopUpdateThread = false;
|
||||||
|
g_updateThread = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
HRESULT RealPrimarySurface::restore()
|
HRESULT RealPrimarySurface::restore()
|
||||||
{
|
{
|
||||||
return g_frontBuffer->lpVtbl->Restore(g_frontBuffer);
|
return g_frontBuffer->lpVtbl->Restore(g_frontBuffer);
|
||||||
|
@ -18,6 +18,7 @@ public:
|
|||||||
static bool isFullScreen();
|
static bool isFullScreen();
|
||||||
static bool isLost();
|
static bool isLost();
|
||||||
static void release();
|
static void release();
|
||||||
|
static void removeUpdateThread();
|
||||||
static HRESULT restore();
|
static HRESULT restore();
|
||||||
static void setClipper(LPDIRECTDRAWCLIPPER clipper);
|
static void setClipper(LPDIRECTDRAWCLIPPER clipper);
|
||||||
static void setPalette();
|
static void setPalette();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user