Skip to content

Commit 53885cd

Browse files
committed
fix release errors
1 parent ad7986e commit 53885cd

6 files changed

Lines changed: 92 additions & 64 deletions

File tree

MemoryModule/MmpDotNet.cpp

Lines changed: 37 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,13 @@
11
#include "stdafx.h"
22
#include <3rdparty/Detours/detours.h>
33

4-
typedef HRESULT (WINAPI* GetFileVersion_T)(
5-
LPCWSTR szFilename,
6-
LPWSTR szBuffer,
7-
DWORD cchBuffer,
8-
DWORD* dwLength
9-
);
10-
114
typedef struct _MMP_FAKE_HANDLE_LIST_ENTRY {
125
LIST_ENTRY InMmpFakeHandleList;
136
HANDLE hObject;
147
PVOID value;
158
BOOL bImageMapping;
169
}MMP_FAKE_HANDLE_LIST_ENTRY, * PMMP_FAKE_HANDLE_LIST_ENTRY;
1710

18-
static decltype(&CreateFileW) OriginCreateFileW = CreateFileW;
19-
static decltype(&GetFileInformationByHandle) OriginGetFileInformationByHandle = GetFileInformationByHandle;
20-
static decltype(&GetFileAttributesExW) OriginGetFileAttributesExW = GetFileAttributesExW;
21-
static decltype(&GetFileSize) OriginGetFileSize = GetFileSize;
22-
static decltype(&GetFileSizeEx) OriginGetFileSizeEx = GetFileSizeEx;
23-
static decltype(&CreateFileMappingW) OriginCreateFileMappingW = CreateFileMappingW;
24-
static decltype(&MapViewOfFileEx) OriginMapViewOfFileEx = MapViewOfFileEx;
25-
static decltype(&MapViewOfFile) OriginMapViewOfFile = MapViewOfFile;
26-
static decltype(&UnmapViewOfFile)OriginUnmapViewOfFile = UnmapViewOfFile;
27-
static decltype(&CloseHandle)OriginCloseHandle = CloseHandle;
28-
static GetFileVersion_T OriginGetFileVersion1 = nullptr;
29-
static GetFileVersion_T OriginGetFileVersion2 = nullptr;
30-
3111
BOOL MmpIsMemoryModuleFileName(
3212
_In_ LPCWSTR lpFileName,
3313
_Out_opt_ PLDR_DATA_TABLE_ENTRY *LdrEntry) {
@@ -127,7 +107,7 @@ HANDLE WINAPI HookCreateFileW(
127107
return hEvent;
128108
}
129109

130-
return OriginCreateFileW(
110+
return MmpGlobalDataPtr->MmpDotNet.Hooks.OriginCreateFileW(
131111
lpFileName,
132112
dwDesiredAccess,
133113
dwShareMode,
@@ -154,7 +134,7 @@ BOOL WINAPI HookGetFileInformationByHandle(
154134
return TRUE;
155135
}
156136
else {
157-
return OriginGetFileInformationByHandle(
137+
return MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileInformationByHandle(
158138
hFile,
159139
lpFileInformation
160140
);
@@ -186,7 +166,7 @@ BOOL WINAPI HookGetFileAttributesExW(
186166
}
187167
}
188168

189-
return OriginGetFileAttributesExW(
169+
return MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileAttributesExW(
190170
lpFileName,
191171
fInfoLevelId,
192172
lpFileInformation
@@ -207,7 +187,7 @@ DWORD WINAPI HookGetFileSize(
207187
return module->dwImageFileSize;
208188
}
209189
else {
210-
return OriginGetFileSize(
190+
return MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileSize(
211191
hFile,
212192
lpFileSizeHigh
213193
);
@@ -228,7 +208,7 @@ BOOL WINAPI HookGetFileSizeEx(
228208
return TRUE;
229209
}
230210
else {
231-
return OriginGetFileSizeEx(
211+
return MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileSizeEx(
232212
hFile,
233213
lpFileSize
234214
);
@@ -252,7 +232,7 @@ HANDLE WINAPI HookCreateFileMappingW(
252232
return hEvent;
253233
}
254234

255-
return OriginCreateFileMappingW(
235+
return MmpGlobalDataPtr->MmpDotNet.Hooks.OriginCreateFileMappingW(
256236
hFile,
257237
lpFileMappingAttributes,
258238
flProtect,
@@ -288,7 +268,7 @@ LPVOID WINAPI HookMapViewOfFileEx(
288268
return hModule;
289269
}
290270

291-
return OriginMapViewOfFileEx(
271+
return MmpGlobalDataPtr->MmpDotNet.Hooks.OriginMapViewOfFileEx(
292272
hFileMappingObject,
293273
dwDesiredAccess,
294274
dwFileOffsetHigh,
@@ -324,14 +304,14 @@ BOOL WINAPI HookUnmapViewOfFile(_In_ LPCVOID lpBaseAddress) {
324304
return TRUE;
325305
}
326306

327-
return OriginUnmapViewOfFile(lpBaseAddress);
307+
return MmpGlobalDataPtr->MmpDotNet.Hooks.OriginUnmapViewOfFile(lpBaseAddress);
328308
}
329309

330310
BOOL WINAPI HookCloseHandle(_In_ _Post_ptr_invalid_ HANDLE hObject) {
331311
auto iter = MmpFindHandleEntry(hObject);
332312
if (iter)MmpFreeHandleEntry(iter);
333313

334-
return OriginCloseHandle(hObject);
314+
return MmpGlobalDataPtr->MmpDotNet.Hooks.OriginCloseHandle(hObject);
335315
}
336316

337317
HRESULT WINAPI HookGetFileVersion(
@@ -374,7 +354,7 @@ HRESULT WINAPI HookGetFileVersion(
374354

375355
}
376356

377-
return OriginGetFileVersion1(
357+
return MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileVersion1(
378358
szFilename,
379359
szBuffer,
380360
cchBuffer,
@@ -389,28 +369,39 @@ BOOL WINAPI MmpPreInitializeHooksForDotNet() {
389369
if (!MmpGlobalDataPtr->MmpDotNet.PreHooked) {
390370
HMODULE hModule = LoadLibraryW(L"mscoree.dll");
391371
if (hModule) {
392-
OriginGetFileVersion2 = (GetFileVersion_T)GetProcAddress(hModule, "GetFileVersion");
393-
if (OriginGetFileVersion2) {
372+
MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileVersion2 = (GetFileVersion_T)GetProcAddress(hModule, "GetFileVersion");
373+
if (MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileVersion2) {
394374

395375
GetSystemTimeAsFileTime(&MmpGlobalDataPtr->MmpDotNet.AssemblyTimes);
396376

397377
InitializeCriticalSection(&MmpGlobalDataPtr->MmpDotNet.MmpFakeHandleListLock);
398378
InitializeListHead(&MmpGlobalDataPtr->MmpDotNet.MmpFakeHandleListHead);
399379

380+
MmpGlobalDataPtr->MmpDotNet.Hooks.OriginCreateFileW = CreateFileW;
381+
MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileInformationByHandle = GetFileInformationByHandle;
382+
MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileAttributesExW = GetFileAttributesExW;
383+
MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileSize = GetFileSize;
384+
MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileSizeEx = GetFileSizeEx;
385+
MmpGlobalDataPtr->MmpDotNet.Hooks.OriginCreateFileMappingW = CreateFileMappingW;
386+
MmpGlobalDataPtr->MmpDotNet.Hooks.OriginMapViewOfFileEx = MapViewOfFileEx;
387+
MmpGlobalDataPtr->MmpDotNet.Hooks.OriginMapViewOfFile = MapViewOfFile;
388+
MmpGlobalDataPtr->MmpDotNet.Hooks.OriginUnmapViewOfFile = UnmapViewOfFile;
389+
MmpGlobalDataPtr->MmpDotNet.Hooks.OriginCloseHandle = CloseHandle;
390+
400391
DetourTransactionBegin();
401392
DetourUpdateThread(NtCurrentThread());
402393

403-
DetourAttach((PVOID*)&OriginCreateFileW, HookCreateFileW);
404-
DetourAttach((PVOID*)&OriginGetFileInformationByHandle, HookGetFileInformationByHandle);
405-
DetourAttach((PVOID*)&OriginGetFileAttributesExW, HookGetFileAttributesExW);
406-
DetourAttach((PVOID*)&OriginGetFileSize, HookGetFileSize);
407-
DetourAttach((PVOID*)&OriginGetFileSizeEx, HookGetFileSizeEx);
408-
DetourAttach((PVOID*)&OriginCreateFileMappingW, HookCreateFileMappingW);
409-
DetourAttach((PVOID*)&OriginMapViewOfFileEx, HookMapViewOfFileEx);
410-
DetourAttach((PVOID*)&OriginMapViewOfFile, HookMapViewOfFile);
411-
DetourAttach((PVOID*)&OriginUnmapViewOfFile, HookUnmapViewOfFile);
412-
DetourAttach((PVOID*)&OriginCloseHandle, HookCloseHandle);
413-
DetourAttach((PVOID*)&OriginGetFileVersion2, HookGetFileVersion);
394+
DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpDotNet.Hooks.OriginCreateFileW, HookCreateFileW);
395+
DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileInformationByHandle, HookGetFileInformationByHandle);
396+
DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileAttributesExW, HookGetFileAttributesExW);
397+
DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileSize, HookGetFileSize);
398+
DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileSizeEx, HookGetFileSizeEx);
399+
DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpDotNet.Hooks.OriginCreateFileMappingW, HookCreateFileMappingW);
400+
DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpDotNet.Hooks.OriginMapViewOfFileEx, HookMapViewOfFileEx);
401+
DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpDotNet.Hooks.OriginMapViewOfFile, HookMapViewOfFile);
402+
DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpDotNet.Hooks.OriginUnmapViewOfFile, HookUnmapViewOfFile);
403+
DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpDotNet.Hooks.OriginCloseHandle, HookCloseHandle);
404+
DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileVersion2, HookGetFileVersion);
414405

415406
DetourTransactionCommit();
416407

@@ -427,8 +418,8 @@ BOOL WINAPI MmpPreInitializeHooksForDotNet() {
427418
BOOL WINAPI MmpInitializeHooksForDotNet() {
428419
HMODULE hModule = GetModuleHandleW(L"mscoreei.dll");
429420
if (hModule) {
430-
OriginGetFileVersion1 = (GetFileVersion_T)GetProcAddress(hModule, "GetFileVersion");
431-
if (OriginGetFileVersion1) {
421+
MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileVersion1 = (GetFileVersion_T)GetProcAddress(hModule, "GetFileVersion");
422+
if (MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileVersion1) {
432423

433424
EnterCriticalSection(NtCurrentPeb()->FastPebLock);
434425

@@ -440,7 +431,7 @@ BOOL WINAPI MmpInitializeHooksForDotNet() {
440431
if (!MmpGlobalDataPtr->MmpDotNet.Initialized) {
441432
DetourTransactionBegin();
442433
DetourUpdateThread(NtCurrentThread());
443-
DetourAttach((PVOID*)&OriginGetFileVersion1, HookGetFileVersion);
434+
DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpDotNet.Hooks.OriginGetFileVersion1, HookGetFileVersion);
444435
DetourTransactionCommit();
445436
MmpGlobalDataPtr->MmpDotNet.Initialized = TRUE;
446437
}

MemoryModule/MmpDotNet.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
11
#pragma once
2+
3+
typedef HRESULT(WINAPI* GetFileVersion_T)(
4+
LPCWSTR szFilename,
5+
LPWSTR szBuffer,
6+
DWORD cchBuffer,
7+
DWORD* dwLength
8+
);
9+
210
BOOL WINAPI MmpPreInitializeHooksForDotNet();
311
BOOL WINAPI MmpInitializeHooksForDotNet();

MemoryModule/MmpGlobalData.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ typedef struct _MMP_TLS_DATA {
2424
CRITICAL_SECTION MmpTlspLock;
2525
LIST_ENTRY MmpThreadLocalStoragePointer;
2626
DWORD MmpActiveThreadCount;
27+
28+
struct {
29+
decltype(&NtCreateThread) OriginNtCreateThread;
30+
decltype(&NtCreateThreadEx) OriginNtCreateThreadEx;
31+
decltype(&NtSetInformationProcess) OriginNtSetInformationProcess;
32+
decltype(&LdrShutdownThread) OriginLdrShutdownThread;
33+
}Hooks;
2734
}MMP_TLS_DATA, * PMMP_TLS_DATA;
2835

2936
//MmpDotNet.cpp
@@ -35,6 +42,21 @@ typedef struct _MMP_DOT_NET_DATA {
3542

3643
BOOLEAN PreHooked;
3744
BOOLEAN Initialized;
45+
46+
struct {
47+
decltype(&CreateFileW) OriginCreateFileW;
48+
decltype(&GetFileInformationByHandle) OriginGetFileInformationByHandle;
49+
decltype(&GetFileAttributesExW) OriginGetFileAttributesExW;
50+
decltype(&GetFileSize) OriginGetFileSize;
51+
decltype(&GetFileSizeEx) OriginGetFileSizeEx;
52+
decltype(&CreateFileMappingW) OriginCreateFileMappingW;
53+
decltype(&MapViewOfFileEx) OriginMapViewOfFileEx;
54+
decltype(&MapViewOfFile) OriginMapViewOfFile;
55+
decltype(&UnmapViewOfFile)OriginUnmapViewOfFile;
56+
decltype(&CloseHandle)OriginCloseHandle;
57+
GetFileVersion_T OriginGetFileVersion1;
58+
GetFileVersion_T OriginGetFileVersion2;
59+
}Hooks;
3860
}MMP_DOT_NET_DATA, * PMMP_DOT_NET_DATA;
3961

4062
typedef struct _MMP_GLOBAL_DATA {

MemoryModule/MmpTls.cpp

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,6 @@ typedef struct _MMP_TLSP_RECORD {
5555
PVOID* TlspMmpBlock;
5656
}MMP_TLSP_RECORD, * PMMP_TLSP_RECORD;
5757

58-
decltype(&NtCreateThread) OriginNtCreateThread = NtCreateThread;
59-
decltype(&NtCreateThreadEx) OriginNtCreateThreadEx = NtCreateThreadEx;
60-
decltype(&NtSetInformationProcess) OriginNtSetInformationProcess = NtSetInformationProcess;
61-
decltype(&LdrShutdownThread) OriginLdrShutdownThread = LdrShutdownThread;
62-
6358
typedef struct _THREAD_CONTEXT {
6459
PTHREAD_START_ROUTINE ThreadStartRoutine;
6560
LPVOID ThreadParameter;
@@ -262,7 +257,7 @@ NTSTATUS NTAPI HookNtCreateThread(
262257
Context.Rdx = ULONG64(_Context);
263258
#endif
264259

265-
status = OriginNtCreateThread(
260+
status = MmpGlobalDataPtr->MmpTls.Hooks.OriginNtCreateThread(
266261
ThreadHandle,
267262
DesiredAccess,
268263
ObjectAttributes,
@@ -299,7 +294,7 @@ NTSTATUS NTAPI HookNtCreateThreadEx(
299294
Context->ThreadStartRoutine = PTHREAD_START_ROUTINE(StartRoutine);
300295
Context->ThreadParameter = Argument;
301296

302-
NTSTATUS status = OriginNtCreateThreadEx(
297+
NTSTATUS status = MmpGlobalDataPtr->MmpTls.Hooks.OriginNtCreateThreadEx(
303298
ThreadHandle,
304299
DesiredAccess,
305300
ObjectAttributes,
@@ -382,7 +377,7 @@ VOID NTAPI HookLdrShutdownThread(VOID) {
382377
//
383378
// Call the original function
384379
//
385-
OriginLdrShutdownThread();
380+
MmpGlobalDataPtr->MmpTls.Hooks.OriginLdrShutdownThread();
386381
}
387382

388383
BOOL NTAPI PreHookNtSetInformationProcess() {
@@ -463,7 +458,7 @@ NTSTATUS NTAPI HookNtSetInformationProcess(
463458
_In_ ULONG ProcessInformationLength) {
464459

465460
if (ProcessInformationClass != ProcessTlsInformation) {
466-
return OriginNtSetInformationProcess(
461+
return MmpGlobalDataPtr->MmpTls.Hooks.OriginNtSetInformationProcess(
467462
ProcessHandle,
468463
ProcessInformationClass,
469464
ProcessInformation,
@@ -537,7 +532,7 @@ NTSTATUS NTAPI HookNtSetInformationProcess(
537532
}
538533
}
539534

540-
status = OriginNtSetInformationProcess(
535+
status = MmpGlobalDataPtr->MmpTls.Hooks.OriginNtSetInformationProcess(
541536
hProcess,
542537
ProcessInformationClass,
543538
Tls,
@@ -826,12 +821,18 @@ BOOL NTAPI MmpTlsInitialize() {
826821
//
827822
// Hook functions
828823
//
824+
825+
MmpGlobalDataPtr->MmpTls.Hooks.OriginNtCreateThread = NtCreateThread;
826+
MmpGlobalDataPtr->MmpTls.Hooks.OriginNtCreateThreadEx = NtCreateThreadEx;
827+
MmpGlobalDataPtr->MmpTls.Hooks.OriginLdrShutdownThread = LdrShutdownThread;
828+
MmpGlobalDataPtr->MmpTls.Hooks.OriginNtSetInformationProcess = NtSetInformationProcess;
829+
829830
DetourTransactionBegin();
830831
DetourUpdateThread(NtCurrentThread());
831-
DetourAttach((PVOID*)&OriginNtCreateThread, HookNtCreateThread);
832-
DetourAttach((PVOID*)&OriginNtCreateThreadEx, HookNtCreateThreadEx);
833-
DetourAttach((PVOID*)&OriginLdrShutdownThread, HookLdrShutdownThread);
834-
DetourAttach((PVOID*)&OriginNtSetInformationProcess, HookNtSetInformationProcess);
832+
DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpTls.Hooks.OriginNtCreateThread, HookNtCreateThread);
833+
DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpTls.Hooks.OriginNtCreateThreadEx, HookNtCreateThreadEx);
834+
DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpTls.Hooks.OriginLdrShutdownThread, HookLdrShutdownThread);
835+
DetourAttach((PVOID*)&MmpGlobalDataPtr->MmpTls.Hooks.OriginNtSetInformationProcess, HookNtSetInformationProcess);
835836
DetourTransactionCommit();
836837

837838
return TRUE;

MemoryModulePP.sln

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ Global
2121
{5B1F46DB-036E-4A50-AF5F-F5D6584D42C6}.Debug|x64.Build.0 = Debug|x64
2222
{5B1F46DB-036E-4A50-AF5F-F5D6584D42C6}.Debug|x86.ActiveCfg = DebugDll|Win32
2323
{5B1F46DB-036E-4A50-AF5F-F5D6584D42C6}.Debug|x86.Build.0 = DebugDll|Win32
24-
{5B1F46DB-036E-4A50-AF5F-F5D6584D42C6}.Release|x64.ActiveCfg = ReleaseDll|x64
25-
{5B1F46DB-036E-4A50-AF5F-F5D6584D42C6}.Release|x64.Build.0 = ReleaseDll|x64
24+
{5B1F46DB-036E-4A50-AF5F-F5D6584D42C6}.Release|x64.ActiveCfg = Release|x64
25+
{5B1F46DB-036E-4A50-AF5F-F5D6584D42C6}.Release|x64.Build.0 = Release|x64
2626
{5B1F46DB-036E-4A50-AF5F-F5D6584D42C6}.Release|x86.ActiveCfg = ReleaseDll|Win32
2727
{5B1F46DB-036E-4A50-AF5F-F5D6584D42C6}.Release|x86.Build.0 = ReleaseDll|Win32
2828
{5B3131BA-178A-4A28-BD54-315A45C97ED1}.Debug|x64.ActiveCfg = Debug|x64

test/test.vcxproj

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@
122122
<SDLCheck>true</SDLCheck>
123123
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
124124
<ConformanceMode>true</ConformanceMode>
125+
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
125126
</ClCompile>
126127
<Link>
127128
<SubSystem>Console</SubSystem>
@@ -140,22 +141,27 @@
140141
<SDLCheck>true</SDLCheck>
141142
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
142143
<ConformanceMode>true</ConformanceMode>
144+
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
143145
</ClCompile>
144146
<Link>
145147
<SubSystem>Console</SubSystem>
146148
<EnableCOMDATFolding>true</EnableCOMDATFolding>
147149
<OptimizeReferences>true</OptimizeReferences>
148150
<GenerateDebugInformation>true</GenerateDebugInformation>
151+
<EntryPointSymbol>
152+
</EntryPointSymbol>
149153
</Link>
150154
</ItemDefinitionGroup>
151155
<ItemGroup>
152156
<ClCompile Include="test.cpp">
153157
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
154158
</ExcludedFromBuild>
155-
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
159+
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
160+
</ExcludedFromBuild>
156161
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
157162
</ExcludedFromBuild>
158-
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
163+
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
164+
</ExcludedFromBuild>
159165
</ClCompile>
160166
</ItemGroup>
161167
<ItemGroup>

0 commit comments

Comments
 (0)