1 /* 2 * PROJECT: ReactOS 'General' Shim library 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: Ignore FreeLibrary calls 5 * COPYRIGHT: Copyright 2018 Mark Jansen (mark.jansen@reactos.org) 6 */ 7 8 #define WIN32_NO_STATUS 9 #include <windef.h> 10 #include <winbase.h> 11 #include <shimlib.h> 12 #include <strsafe.h> 13 14 15 #define SHIM_NS IgnoreFreeLibrary 16 #include <setup_shim.inl> 17 18 typedef BOOL(WINAPI* FREELIBRARYPROC)(HMODULE); 19 20 const char** g_Names; 21 static int g_NameCount; 22 23 BOOL WINAPI SHIM_OBJ_NAME(FreeLibrary)(HMODULE hModule) 24 { 25 char Buffer[MAX_PATH], *Ptr = Buffer; 26 DWORD len, wanted = ARRAYSIZE(Buffer); 27 for (;;) 28 { 29 len = GetModuleFileNameA(hModule, Ptr, wanted); 30 if (len < wanted) 31 break; 32 33 wanted *= 2; 34 if (Ptr != Buffer) 35 ShimLib_ShimFree(Ptr); 36 37 Ptr = ShimLib_ShimMalloc(wanted); 38 if (!Ptr) 39 break; 40 } 41 42 if (Ptr && len) 43 { 44 char* ModuleName = NULL; 45 int n; 46 for (; len; len--) 47 { 48 ModuleName = Ptr + len; 49 if (ModuleName[-1] == '/' || ModuleName[-1] == '\\') 50 break; 51 } 52 for (n = 0; n < g_NameCount; ++n) 53 { 54 if (!stricmp(g_Names[n], ModuleName)) 55 { 56 SHIM_INFO("Prevented unload of %s\n", ModuleName); 57 if (Ptr && Ptr != Buffer) 58 ShimLib_ShimFree(Ptr); 59 return TRUE; 60 } 61 } 62 } 63 64 if (Ptr && Ptr != Buffer) 65 ShimLib_ShimFree(Ptr); 66 67 return CALL_SHIM(0, FREELIBRARYPROC)(hModule); 68 } 69 70 static VOID InitIgnoreFreeLibrary(PCSTR CommandLine) 71 { 72 PCSTR prev, cur; 73 int count = 1, n = 0; 74 const char** names; 75 76 if (!CommandLine || !*CommandLine) 77 return; 78 79 prev = CommandLine; 80 while ((cur = strchr(prev, ';'))) 81 { 82 count++; 83 prev = cur + 1; 84 } 85 86 names = ShimLib_ShimMalloc(sizeof(char*) * count); 87 if (!names) 88 { 89 SHIM_WARN("Unable to allocate %u bytes\n", sizeof(char*) * count); 90 return; 91 } 92 93 prev = CommandLine; 94 while ((cur = strchr(prev, ';'))) 95 { 96 names[n] = ShimLib_StringNDuplicateA(prev, cur - prev + 1); 97 if (!names[n]) 98 { 99 SHIM_WARN("Unable to allocate %u bytes\n", cur - prev + 2); 100 goto fail; 101 } 102 n++; 103 prev = cur + 1; 104 } 105 names[n] = ShimLib_StringDuplicateA(prev); 106 if (!names[n]) 107 { 108 SHIM_WARN("Unable to allocate last string\n"); 109 goto fail; 110 } 111 112 g_Names = names; 113 g_NameCount = count; 114 return; 115 116 fail: 117 --n; 118 while (n >= 0) 119 { 120 if (names[n]) 121 ShimLib_ShimFree((PVOID)names[n]); 122 123 --n; 124 } 125 ShimLib_ShimFree(names); 126 } 127 128 BOOL WINAPI SHIM_OBJ_NAME(Notify)(DWORD fdwReason, PVOID ptr) 129 { 130 if (fdwReason == SHIM_NOTIFY_ATTACH) 131 { 132 SHIM_MSG("IgnoreFreeLibrary(%s)\n", SHIM_OBJ_NAME(g_szCommandLine)); 133 InitIgnoreFreeLibrary(SHIM_OBJ_NAME(g_szCommandLine)); 134 } 135 return TRUE; 136 } 137 138 139 #define SHIM_NOTIFY_FN SHIM_OBJ_NAME(Notify) 140 #define SHIM_NUM_HOOKS 1 141 #define SHIM_SETUP_HOOKS \ 142 SHIM_HOOK(0, "KERNEL32.DLL", "FreeLibrary", SHIM_OBJ_NAME(FreeLibrary)) 143 144 #include <implement_shim.inl> 145