Skip to content

Commit ec80ed4

Browse files
committed
welcome back Download Manager, fucking std::async doesn't send messages to dll mains, i hate bill, this shit might prevent deadlocking download threads when exiting during download
1 parent 38aa679 commit ec80ed4

File tree

9 files changed

+231
-19
lines changed

9 files changed

+231
-19
lines changed
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
#include "pch.h"
2+
3+
#include "Download Manager.h"
4+
5+
DownloadManager::DownloadManager()
6+
{
7+
m_hInterruptEvent = nullptr;
8+
}
9+
10+
DownloadManager::~DownloadManager()
11+
{
12+
if (m_hInterruptEvent)
13+
{
14+
CloseHandle(m_hInterruptEvent);
15+
}
16+
}
17+
18+
HRESULT __stdcall DownloadManager::QueryInterface(const IID & riid, void ** ppvObject)
19+
{
20+
UNREFERENCED_PARAMETER(riid);
21+
UNREFERENCED_PARAMETER(ppvObject);
22+
23+
return E_NOINTERFACE;
24+
}
25+
26+
ULONG __stdcall DownloadManager::AddRef(void)
27+
{
28+
return 1;
29+
}
30+
31+
ULONG __stdcall DownloadManager::Release(void)
32+
{
33+
return 1;
34+
}
35+
36+
HRESULT __stdcall DownloadManager::OnStartBinding(DWORD dwReserved, IBinding * pib)
37+
{
38+
UNREFERENCED_PARAMETER(dwReserved);
39+
UNREFERENCED_PARAMETER(pib);
40+
41+
return S_OK;
42+
}
43+
44+
HRESULT __stdcall DownloadManager::GetPriority(LONG * pnPriority)
45+
{
46+
UNREFERENCED_PARAMETER(pnPriority);
47+
48+
return S_OK;
49+
}
50+
51+
HRESULT __stdcall DownloadManager::OnLowResource(DWORD reserved)
52+
{
53+
UNREFERENCED_PARAMETER(reserved);
54+
55+
return S_OK;
56+
}
57+
58+
HRESULT __stdcall DownloadManager::OnStopBinding(HRESULT hresult, LPCWSTR szError)
59+
{
60+
UNREFERENCED_PARAMETER(hresult);
61+
UNREFERENCED_PARAMETER(szError);
62+
63+
return S_OK;
64+
}
65+
66+
HRESULT __stdcall DownloadManager::GetBindInfo(DWORD * grfBINDF, BINDINFO *pbindinfo)
67+
{
68+
UNREFERENCED_PARAMETER(grfBINDF);
69+
UNREFERENCED_PARAMETER(pbindinfo);
70+
71+
return S_OK;
72+
}
73+
74+
HRESULT __stdcall DownloadManager::OnDataAvailable(DWORD grfBSCF, DWORD dwSize, FORMATETC * pformatetc, STGMEDIUM * pstgmed)
75+
{
76+
UNREFERENCED_PARAMETER(grfBSCF);
77+
UNREFERENCED_PARAMETER(dwSize);
78+
UNREFERENCED_PARAMETER(pformatetc);
79+
UNREFERENCED_PARAMETER(pstgmed);
80+
81+
return S_OK;
82+
}
83+
84+
HRESULT __stdcall DownloadManager::OnObjectAvailable(const IID & riid, IUnknown * punk)
85+
{
86+
UNREFERENCED_PARAMETER(riid);
87+
UNREFERENCED_PARAMETER(punk);
88+
89+
return S_OK;
90+
}
91+
92+
HRESULT __stdcall DownloadManager::OnProgress(ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
93+
{
94+
UNREFERENCED_PARAMETER(ulProgress);
95+
UNREFERENCED_PARAMETER(ulProgressMax);
96+
UNREFERENCED_PARAMETER(ulStatusCode);
97+
UNREFERENCED_PARAMETER(szStatusText);
98+
99+
if (m_hInterruptEvent && WaitForSingleObject(m_hInterruptEvent, 0) == WAIT_OBJECT_0)
100+
{
101+
return E_ABORT;
102+
}
103+
104+
return S_OK;
105+
}
106+
107+
BOOL DownloadManager::SetInterruptEvent(HANDLE hInterrupt)
108+
{
109+
if (m_hInterruptEvent)
110+
{
111+
CloseHandle(m_hInterruptEvent);
112+
}
113+
114+
return DuplicateHandle(GetCurrentProcess(), hInterrupt, GetCurrentProcess(), &m_hInterruptEvent, NULL, FALSE, DUPLICATE_SAME_ACCESS);
115+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//Stolen from here:
2+
//https://stackoverflow.com/a/5292277
3+
//by User Hans Passant
4+
5+
#pragma once
6+
7+
#include <windows.h>
8+
9+
class DownloadManager : public IBindStatusCallback
10+
{
11+
HANDLE m_hInterruptEvent;
12+
13+
public:
14+
15+
DownloadManager();
16+
17+
~DownloadManager();
18+
19+
HRESULT __stdcall QueryInterface(const IID & riid, void ** ppvObject);
20+
21+
ULONG STDMETHODCALLTYPE AddRef(void);
22+
23+
ULONG STDMETHODCALLTYPE Release(void);
24+
25+
virtual HRESULT STDMETHODCALLTYPE OnStartBinding(DWORD dwReserved, IBinding * pib);
26+
27+
virtual HRESULT STDMETHODCALLTYPE GetPriority(LONG * pnPriority);
28+
29+
virtual HRESULT STDMETHODCALLTYPE OnLowResource(DWORD reserved);
30+
31+
virtual HRESULT STDMETHODCALLTYPE OnStopBinding(HRESULT hresult, LPCWSTR szError);
32+
33+
virtual HRESULT STDMETHODCALLTYPE GetBindInfo(DWORD * grfBINDF, BINDINFO *pbindinfo);
34+
35+
virtual HRESULT STDMETHODCALLTYPE OnDataAvailable(DWORD grfBSCF, DWORD dwSize, FORMATETC * pformatetc, STGMEDIUM * pstgmed);
36+
37+
virtual HRESULT STDMETHODCALLTYPE OnObjectAvailable(const IID & riid, IUnknown * punk);
38+
39+
HRESULT __stdcall OnProgress(ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText);
40+
41+
BOOL SetInterruptEvent(HANDLE hInterrupt);
42+
};

GH Injector Library/Error.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@
249249
#define SYMBOL_ERR_SYMBOL_SEARCH_FAILED 0x40000013 //SymFromName : couldn't find szSymbolName in the specified pdb
250250
#define SYMBOL_CANT_OPEN_PROCESS 0x40000014 //OpenProcess : can't get PROCESS_QUERY_LIMITED_INFORMATION handle to current process
251251
#define SYMBOL_ERR_COPYFILE_FAILED 0x40000015 //CopyFileA : copying the file from the cache directory failed
252+
#define SYMBOL_ERR_INTERRUPT 0x40000016 //internal error : download has been interrupted
252253

253254

254255

GH Injector Library/GH Injector Library.vcxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@
164164
</Link>
165165
</ItemDefinitionGroup>
166166
<ItemGroup>
167+
<ClInclude Include="Download Manager.h" />
167168
<ClInclude Include="Eject.h" />
168169
<ClInclude Include="Error.h" />
169170
<ClInclude Include="Handle Hijacking.h" />
@@ -181,6 +182,7 @@
181182
<ClInclude Include="WOW64 Shells.h" />
182183
</ItemGroup>
183184
<ItemGroup>
185+
<ClCompile Include="Download Manager.cpp" />
184186
<ClCompile Include="Eject.cpp" />
185187
<ClCompile Include="Handle Hijacking.cpp" />
186188
<ClCompile Include="Hook Scanner WOW64.cpp" />

GH Injector Library/GH Injector Library.vcxproj.filters

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@
8181
<ClInclude Include="WOW64 Shells.h">
8282
<Filter>Quelldateien\wow64\Injection Methods</Filter>
8383
</ClInclude>
84+
<ClInclude Include="Download Manager.h">
85+
<Filter>Headerdateien</Filter>
86+
</ClInclude>
8487
</ItemGroup>
8588
<ItemGroup>
8689
<ClCompile Include="Handle Hijacking.cpp">
@@ -161,5 +164,8 @@
161164
<ClCompile Include="Injection Generic WOW64.cpp">
162165
<Filter>Quelldateien\wow64\Injection Methods</Filter>
163166
</ClCompile>
167+
<ClCompile Include="Download Manager.cpp">
168+
<Filter>Quelldateien</Filter>
169+
</ClCompile>
164170
</ItemGroup>
165171
</Project>

GH Injector Library/Import Handler WOW64.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ DWORD LoadNtSymbolWOW64(T & Function, const char * szFunction)
9494
DWORD sym_ret = sym_ntdll_wow64.GetSymbolAddress(szFunction, RVA);
9595
if (sym_ret != SYMBOL_ERR_SUCCESS)
9696
{
97-
printf("Failed to load WOW64 function: %s\n", szFunction);
97+
LOG("Failed to load WOW64 function: %s\n", szFunction);
9898
return 0;
9999
}
100100

GH Injector Library/Symbol Parser.cpp

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,20 @@ SYMBOL_PARSER::SYMBOL_PARSER()
77
m_Initialized = false;
88
m_Ready = false;
99
m_SymbolTable = 0;
10-
m_Filesize = 0;
1110
m_hPdbFile = nullptr;
1211
m_hProcess = nullptr;
12+
13+
m_bInterruptEvent = false;
14+
m_hInterruptEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
1315
}
1416

1517
SYMBOL_PARSER::~SYMBOL_PARSER()
1618
{
19+
if (m_hInterruptEvent)
20+
{
21+
CloseHandle(m_hInterruptEvent);
22+
}
23+
1724
if (m_Initialized)
1825
{
1926
if (m_SymbolTable)
@@ -336,13 +343,24 @@ DWORD SYMBOL_PARSER::Initialize(const std::string szModulePath, const std::strin
336343
{
337344
while (InternetCheckConnectionA("https://msdl.microsoft.com", FLAG_ICC_FORCE_CONNECTION, NULL) == FALSE)
338345
{
339-
Sleep(10);
346+
Sleep(50);
347+
348+
if (m_bInterruptEvent)
349+
{
350+
VirtualFree(pLocalImageBase, 0, MEM_RELEASE);
351+
352+
delete[] pRawData;
353+
354+
return SYMBOL_ERR_INTERRUPT;
355+
}
340356
}
341357
}
342358

343359
char szCacheFile[MAX_PATH]{ 0 };
360+
DownloadManager dlmgr;
361+
dlmgr.SetInterruptEvent(m_hInterruptEvent);
344362

345-
if (FAILED(URLDownloadToCacheFileA(nullptr, url.c_str(), szCacheFile, MAX_PATH , NULL, nullptr)))
363+
if (FAILED(URLDownloadToCacheFileA(nullptr, url.c_str(), szCacheFile, MAX_PATH , NULL, &dlmgr)))
346364
{
347365
VirtualFree(pLocalImageBase, 0, MEM_RELEASE);
348366

@@ -444,8 +462,14 @@ DWORD SYMBOL_PARSER::GetSymbolAddress(const char * szSymbolName, DWORD & RvaOut)
444462
return SYMBOL_ERR_SUCCESS;
445463
}
446464

447-
void SYMBOL_PARSER::InterruptCleanup()
465+
void SYMBOL_PARSER::Interrupt()
448466
{
467+
if (m_hInterruptEvent)
468+
{
469+
SetEvent(m_hInterruptEvent);
470+
CloseHandle(m_hInterruptEvent);
471+
}
472+
449473
if (m_Initialized)
450474
{
451475
if (m_SymbolTable)
@@ -469,7 +493,9 @@ void SYMBOL_PARSER::InterruptCleanup()
469493
m_Initialized = false;
470494
m_Ready = false;
471495
m_SymbolTable = 0;
472-
m_Filesize = 0;
473496
m_hPdbFile = nullptr;
474497
m_hProcess = nullptr;
498+
499+
m_bInterruptEvent = false;
500+
m_hInterruptEvent = nullptr;
475501
}

GH Injector Library/Symbol Parser.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,24 @@
33
#include "pch.h"
44

55
#include "Error.h"
6+
#include "Download Manager.h"
7+
68
class SYMBOL_PARSER
79
{
810
HANDLE m_hProcess;
911

1012
HANDLE m_hPdbFile;
1113
std::string m_szPdbPath;
12-
DWORD m_Filesize;
1314
DWORD64 m_SymbolTable;
1415

1516
std::string m_szModulePath;
1617

1718
bool m_Initialized;
1819
bool m_Ready;
1920

21+
HANDLE m_hInterruptEvent;
22+
bool m_bInterruptEvent;
23+
2024
bool VerifyExistingPdb(const GUID & guid);
2125

2226
public:
@@ -27,7 +31,7 @@ class SYMBOL_PARSER
2731
DWORD Initialize(const std::string szModulePath, const std::string path, std::string * pdb_path_out, bool Redownload, bool WaitForConnection = false);
2832
DWORD GetSymbolAddress(const char * szSymbolName, DWORD & RvaOut);
2933

30-
void InterruptCleanup();
34+
void Interrupt();
3135
};
3236

3337
struct PdbInfo
@@ -68,7 +72,9 @@ struct GUID_StreamData
6872
#ifdef _WIN64
6973
inline SYMBOL_PARSER sym_ntdll_wow64;
7074
inline std::shared_future<DWORD> sym_ntdll_wow64_ret;
75+
inline DWORD sym_ntdll_wow64_thread_id;
7176
#endif
7277

7378
inline SYMBOL_PARSER sym_ntdll_native;
74-
inline std::shared_future<DWORD> sym_ntdll_native_ret;
79+
inline std::shared_future<DWORD> sym_ntdll_native_ret;
80+
inline DWORD sym_ntdll_native_thread_id;

GH Injector Library/main.cpp

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@ BOOL WINAPI DllMain(HINSTANCE hDll, DWORD dwReason, void * pReserved)
3030

3131
LOG("GH Injector V%ls attached at %p\n", GH_INJ_VERSION, hDll);
3232

33-
DisableThreadLibraryCalls(hDll);
34-
3533
g_hInjMod = hDll;
3634

3735
char szRootPathA[MAX_PATH]{ 0 };
@@ -68,26 +66,42 @@ BOOL WINAPI DllMain(HINSTANCE hDll, DWORD dwReason, void * pReserved)
6866

6967
LOG("Rootpath is %s\n", szRootPathA);
7068

69+
std::string szNtDllNative = szWindowsDir;
70+
szNtDllNative += "\\System32\\ntdll.dll";
71+
72+
sym_ntdll_native_ret = std::async(std::launch::async, &SYMBOL_PARSER::Initialize, &sym_ntdll_native, szNtDllNative, g_RootPathA, nullptr, false, true);
73+
7174
#ifdef _WIN64
7275
std::string szNtDllWOW64 = szWindowsDir;
7376
szNtDllWOW64 += "\\SysWOW64\\ntdll.dll";
7477

75-
sym_ntdll_wow64_ret = std::async(std::launch::async, &SYMBOL_PARSER::Initialize, &sym_ntdll_wow64, szNtDllWOW64, g_RootPathA, nullptr, false, true);
78+
sym_ntdll_wow64_ret = std::async(std::launch::async, &SYMBOL_PARSER::Initialize, &sym_ntdll_wow64, szNtDllWOW64, g_RootPathA, nullptr, false, true);
7679
#endif
7780

78-
std::string szNtDllNative = szWindowsDir;
79-
szNtDllNative += "\\System32\\ntdll.dll";
80-
81-
sym_ntdll_native_ret = std::async(std::launch::async, &SYMBOL_PARSER::Initialize, &sym_ntdll_native, szNtDllNative, g_RootPathA, nullptr, false, true);
82-
8381
delete[] szWindowsDir;
8482
}
8583
else if (dwReason == DLL_PROCESS_DETACH)
8684
{
87-
sym_ntdll_native.InterruptCleanup();
85+
LOG("GH Injector V%ls detaching\n", GH_INJ_VERSION);
86+
87+
if (sym_ntdll_native_ret.wait_for(std::chrono::microseconds(0)) != std::future_status::ready)
88+
{
89+
sym_ntdll_native.Interrupt();
90+
if (sym_ntdll_native_ret.wait_for(std::chrono::microseconds(25)) != std::future_status::timeout)
91+
{
92+
LOG("Native ntdll pdb download thread didn't exit properly.\n");
93+
}
94+
}
8895

8996
#ifdef _WIN64
90-
sym_ntdll_wow64.InterruptCleanup();
97+
if (sym_ntdll_wow64_ret.wait_for(std::chrono::microseconds(0)) != std::future_status::ready)
98+
{
99+
sym_ntdll_wow64.Interrupt();
100+
if (sym_ntdll_wow64_ret.wait_for(std::chrono::microseconds(25)) != std::future_status::timeout)
101+
{
102+
LOG("Wow64 ntdll pdb download thread didn't exit properly.\n");
103+
}
104+
}
91105
#endif
92106

93107
LOG("GH Injector V%ls detached\n", GH_INJ_VERSION);

0 commit comments

Comments
 (0)