FastMM4BCB.cpp 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070
  1. /*
  2. Fast Memory Manager: BCB support 2.04
  3. Description:
  4. FastMM support unit for C++ Builder. Loads FastMM4 on startup of the Borland
  5. C++ Builder application or DLL.
  6. Usage:
  7. 1) Copy FastMM4BCB.cpp, FastMM4.pas, FastMM4Message.pas, FastMM4Options.inc,
  8. and FastMM_FullDebugMode.lib to your source folder.
  9. 2) Copy FastMM_FullDebugMode.dll to your application's .exe directory (if you
  10. intend to use FullDebugMode).
  11. 3) To your project, add FastMM4Messages.pas first, then FastMM4.pas, then
  12. FastMM4BCB.cpp. On compiling the .pas files, .hpp files are created and
  13. imported by the subsequent files.
  14. 4) Add USEOBJ("FastMM4BCB.cpp") to your project file, BEFORE any other
  15. USEFORM directives.
  16. 5) Under the Project -> Options -> Linker menu uncheck "Use Dynamic RTL"
  17. (sorry, won't work with the RTL DLL).
  18. FastMM will now install itself on startup and replace the RTL memory manager.
  19. Acknowledgements:
  20. - Jarek Karciarz, Vladimir Ulchenko (Vavan) and Bob Gonder for their help in
  21. implementing the initial BCB support.
  22. - JiYuan Xie for doing an entire rewrite of this unit to allow leak reporting,
  23. etc. under BCB.
  24. - Remy Lebeau for some bugfixes.
  25. - James Nachbar and Albert Wiersch for improved usage instructions and
  26. bugfixes.
  27. Change log:
  28. Version 1.00 (15 June 2005):
  29. - Initial release. Due to limitations of BCB it cannot be uninstalled (thus
  30. no leak checking and not useable in DLLs unless the DLL always shares the
  31. main application's MM). Thanks to Jarek Karciarz, Vladimir Ulchenko and Bob
  32. Gonder for their help.
  33. Version 1.01 (6 August 2005):
  34. - Fixed a regression bug (Thanks to Omar Zelaya).
  35. Version 2.00 (22 April 2008):
  36. - Rewritten by JiYuan Xie to implement leak reporting, etc. (Thank you!)
  37. Version 2.01 (9 December 2008):
  38. - Fixed a compiler error when 'STRICT' is defined
  39. Version 2.02 (24 January 2009):
  40. - JiYuan Xie fixed the BCB compatibility. (Thanks!)
  41. Version 2.03 (03 March 2009):
  42. - Changes for BCB2009 in "TCHAR = wchar_t" mode
  43. Version 2.04 (10 January 2010):
  44. - Fixed a compilation error in BCB6 (Thanks to Remy Lebeau)
  45. */
  46. //#ifndef _NO_VCL
  47. #pragma hdrstop
  48. #include "FastMM4Messages.hpp"
  49. #include "FastMM4.hpp"
  50. //BCB6 support
  51. #include <tchar.h>
  52. #pragma option push
  53. #pragma option -k- -d -vi- -O2 -b- -3 -a8 -pc -RT- -x -xd -r -AT -vG- -vG0- -vG1- -vG2- -vG3- -vGc- -vGt- -vGd-
  54. #ifdef __cplusplus
  55. extern "C" {
  56. #endif
  57. #ifdef PatchBCBTerminate
  58. #ifdef FullDebugMode
  59. #ifndef LoadDebugDLLDynamically
  60. #pragma link "FastMM_FullDebugMode.lib"
  61. #if defined(RawStackTraces)
  62. __declspec(dllimport) void __fastcall GetRawStackTrace(unsigned * AReturnAddresses,
  63. unsigned AMaxDepth, unsigned ASkipFrames);
  64. #else
  65. __declspec(dllimport) void __fastcall GetFrameBasedStackTrace(unsigned * AReturnAddresses,
  66. unsigned AMaxDepth, unsigned ASkipFrames);
  67. #endif
  68. __declspec(dllimport) void __fastcall LogStackTrace(unsigned * AReturnAddresses,
  69. unsigned AMaxDepth, char *ABuffer);
  70. #endif
  71. #endif
  72. #pragma pack(push,1)
  73. typedef struct {
  74. unsigned char JmpInst; //E9
  75. int Offset;
  76. } TRelativeJmp32, * PRelativeJmp32;
  77. typedef struct {
  78. unsigned short JmpInst; //FF 25
  79. void * * DestPtr;
  80. } TIndirectJmp32, * PIndirectJmp32;
  81. #pragma pack(pop)
  82. //Return true if write OK
  83. bool __fastcall WriteMem(void * Location, void * Data, unsigned int DataSize)
  84. {
  85. unsigned long OldProtect;
  86. if (VirtualProtect(Location, DataSize, PAGE_EXECUTE_READWRITE, &OldProtect))
  87. {
  88. memmove(Location, Data, DataSize);
  89. FlushInstructionCache(GetCurrentProcess(), Location, sizeof(DataSize));
  90. VirtualProtect(Location, DataSize, OldProtect, &OldProtect);
  91. return true;
  92. }
  93. else {
  94. return false;
  95. }
  96. }
  97. #define RelativeJmp32Inst (0xE9)
  98. //Return true if patch OK
  99. bool __fastcall PatchProc(void * OldProc, void * NewProc, TRelativeJmp32 * Backup)
  100. {
  101. if (OldProc && NewProc)
  102. {
  103. TRelativeJmp32 JmpData;
  104. JmpData.JmpInst = RelativeJmp32Inst;
  105. JmpData.Offset = (int)NewProc - ((int)OldProc + sizeof(JmpData));
  106. if (Backup)
  107. {
  108. *Backup = *((PRelativeJmp32)OldProc);
  109. }
  110. return WriteMem(OldProc, &JmpData, sizeof(JmpData));
  111. }
  112. else {
  113. return false;
  114. }
  115. };
  116. //Return true if unpatch OK
  117. bool __fastcall UnPatchProc(void * OldProc, void * NewProc, TRelativeJmp32 * Backup)
  118. {
  119. if (OldProc && NewProc && Backup)
  120. {
  121. int Offset = (int)NewProc - ((int)OldProc + sizeof(TRelativeJmp32));
  122. if ((((PRelativeJmp32)OldProc)->JmpInst == RelativeJmp32Inst)
  123. && (((PRelativeJmp32)OldProc)->Offset == Offset))
  124. {
  125. return WriteMem(OldProc, &Backup, sizeof(*Backup));
  126. }
  127. }
  128. return false;
  129. };
  130. typedef void * (__fastcall * GetMemFunc)(int Size);
  131. typedef int (__fastcall * FreeMemFunc)(void * P);
  132. typedef void * (__fastcall * ReallocMemFunc)(void * P, int Size);
  133. #if __BORLANDC__ >= 0x582
  134. //>= BDS2006 ?
  135. typedef void * (__fastcall * AllocMemFunc)(unsigned Size);
  136. #endif
  137. #ifndef _RTLDLL //Not using Dynamic RTL
  138. extern void _terminate(int code);
  139. #endif
  140. #ifndef FullDebugMode
  141. #define InternalGetMem FastGetMem
  142. #define InternalFreeMem FastFreeMem
  143. #define InternalReallocMem FastReallocMem
  144. #if __BORLANDC__ >= 0x582
  145. //>= BDS2006 ?
  146. #define InternalAllocMem FastAllocMem
  147. #endif
  148. #else
  149. #define InternalGetMem DebugGetMem
  150. #define InternalFreeMem DebugFreeMem
  151. #define InternalReallocMem DebugReallocMem
  152. #if __BORLANDC__ >= 0x582
  153. //>= BDS2006 ?
  154. #define InternalAllocMem DebugAllocMem
  155. #endif
  156. #endif //FullDebugMode
  157. #ifdef CheckCppObjectTypeEnabled
  158. void __fastcall FinalizeModuleCodeDataRanges(void);
  159. #endif
  160. void __fastcall FinalizeHeapRedirectorStoreList(void);
  161. extern bool IsBorlandMMDLL;
  162. #if defined(__DLL__) && defined(FullDebugMode) && defined(LoadDebugDLLDynamically)
  163. void __fastcall CallOldFullDebugModeDllEntry(void);
  164. #endif
  165. void * StockGetMemPtr = NULL;
  166. void New_terminate(int code)
  167. {
  168. //FasttMM4.pas need export a "FinalizeMemoryManager" routine which contain
  169. //codes of original "finalization" section
  170. FinalizeMemoryManager();
  171. #ifdef CheckCppObjectTypeEnabled
  172. GetCppVirtObjSizeByTypeIdPtrFunc = NULL;
  173. GetCppVirtObjTypeIdPtrFunc = NULL;
  174. GetCppVirtObjTypeNameFunc = NULL;
  175. GetCppVirtObjTypeNameByTypeIdPtrFunc = NULL;
  176. GetCppVirtObjTypeNameByVTablePtrFunc = NULL;
  177. FinalizeModuleCodeDataRanges();
  178. #endif
  179. #ifdef DetectMMOperationsAfterUninstall
  180. //Do nothing
  181. #endif
  182. if (IsBorlandMMDLL)
  183. {
  184. FinalizeHeapRedirectorStoreList();
  185. }
  186. #if defined(__DLL__) && defined(FullDebugMode) && defined(LoadDebugDLLDynamically)
  187. CallOldFullDebugModeDllEntry();
  188. #endif
  189. ExitProcess(code);
  190. }
  191. void * PatchLocation = NULL;
  192. #if defined(__DLL__) && defined(FullDebugMode) && defined(LoadDebugDLLDynamically)
  193. #pragma pack(push,1)
  194. typedef struct {
  195. unsigned char PushEbp; //0x55
  196. unsigned short MovEbpEsp; //0x8B 0xEC
  197. unsigned char SubEsp[3]; //0x83 0xC4 0xC4
  198. } DelphiDllEntryInsts, *DelphiDllEntryInstsPtr;
  199. typedef struct {
  200. DelphiDllEntryInsts OldInsts;
  201. TRelativeJmp32 JmpToRemainInsts;
  202. } FullDebugModeDllEntryThunk;
  203. #pragma pack(pop)
  204. FullDebugModeDllEntryThunk OldFullDebugModeDllEntryThunk;
  205. bool ExecuteOldFullDebugModeDllEntry = false;
  206. bool FullDebugModeDllEntryHooked = false;
  207. bool __fastcall PrepareFullDebugModeDllEntryThunk(FullDebugModeDllEntryThunk *Thunk,
  208. void *OldEntry)
  209. {
  210. DelphiDllEntryInstsPtr OldInstsPtr = (DelphiDllEntryInstsPtr)OldEntry;
  211. if ((OldInstsPtr->PushEbp == 0x55)
  212. && (OldInstsPtr->MovEbpEsp == 0xEC8B)
  213. && (OldInstsPtr->SubEsp[0] == 0x83)
  214. && (OldInstsPtr->SubEsp[1] == 0xC4))
  215. {
  216. unsigned long OldProtect;
  217. if (VirtualProtect((void *)Thunk, sizeof(*Thunk), PAGE_EXECUTE_READWRITE, &OldProtect))
  218. {
  219. Thunk->OldInsts = *OldInstsPtr;
  220. //jump to (OldEntry + sizeof(*OldInstsPtr)) from Thunk->JmpToRemainInsts
  221. Thunk->JmpToRemainInsts.JmpInst = RelativeJmp32Inst;
  222. Thunk->JmpToRemainInsts.Offset = ((int)OldInstsPtr + sizeof(*OldInstsPtr))
  223. - ((int)&Thunk->JmpToRemainInsts + sizeof(Thunk->JmpToRemainInsts));
  224. return true;
  225. }
  226. }
  227. return false;
  228. }
  229. #if defined(PURE_CPLUSPLUS) //__BORLANDC__ < 0x0560
  230. typedef BOOL WINAPI (*DllEntryFunc)(
  231. HINSTANCE hinstDLL,
  232. DWORD fdwReason,
  233. LPVOID lpvReserved);
  234. BOOL WINAPI NewFullDebugModeDllEntry(
  235. HINSTANCE hinstDLL,
  236. DWORD fdwReason,
  237. LPVOID lpvReserved)
  238. {
  239. //[ESP + 4] hinstDLL
  240. //[ESP + 8] fdwReason
  241. //[ESP + 12] lpvReserved
  242. if (fdwReason != DLL_PROCESS_DETACH)
  243. {
  244. DllEntryFunc OldDllEntry = (DllEntryFunc)(&OldFullDebugModeDllEntryThunk);
  245. return (*OldDllEntry)(hinstDLL, fdwReason, lpvReserved);
  246. }
  247. else
  248. {
  249. if (ExecuteOldFullDebugModeDllEntry)
  250. {
  251. ExecuteOldFullDebugModeDllEntry = 0;
  252. DllEntryFunc OldDllEntry = (DllEntryFunc)(&OldFullDebugModeDllEntryThunk);
  253. return (*OldDllEntry)(hinstDLL, fdwReason, lpvReserved);
  254. }
  255. else
  256. {
  257. return true;
  258. }
  259. }
  260. }
  261. #else
  262. //#pragma warn -8002 //"W8002: Restarting compile using assembly"
  263. #pragma option -w-asc
  264. //#pragma warn -8070 //"W8070 Function should return a value"
  265. #pragma option -w-rvl //the same as above
  266. __declspec(naked) BOOL WINAPI NewFullDebugModeDllEntry(
  267. HINSTANCE hinstDLL,
  268. DWORD fdwReason,
  269. LPVOID lpvReserved)
  270. {
  271. //[ESP + 4] hinstDLL
  272. //[ESP + 8] fdwReason
  273. //[ESP + 12] lpvReserved
  274. /*
  275. if (fdwReason != DLL_PROCESS_DETACH)
  276. {
  277. DllEntryFunc OldDllEntry = (DllEntryFunc)(&OldFullDebugModeDllEntryThunk);
  278. return (*OldDllEntry)(hinstDLL, fdwReason, lpvReserved);
  279. }
  280. else
  281. {
  282. if (ExecuteOldFullDebugModeDllEntry)
  283. {
  284. ExecuteOldFullDebugModeDllEntry = 0;
  285. DllEntryFunc OldDllEntry = (DllEntryFunc)(&OldFullDebugModeDllEntryThunk);
  286. return (*OldDllEntry)(hinstDLL, fdwReason, lpvReserved);
  287. }
  288. else
  289. {
  290. return true;
  291. }
  292. }
  293. */
  294. asm
  295. {
  296. mov eax, [esp + 8] //fdwReason
  297. test eax, eax //is DLL_PROCESS_DETACH ?
  298. jz ProcessDetech
  299. #if __BORLANDC__ < 0x0560
  300. lea eax, OldFullDebugModeDllEntryThunk //not DLL_PROCESS_DETACH, call original entry
  301. jmp eax
  302. #else
  303. jmp OldFullDebugModeDllEntryThunk //not DLL_PROCESS_DETACH, call original entry
  304. #endif
  305. ProcessDetech:
  306. movzx eax, ExecuteOldFullDebugModeDllEntry
  307. test eax, eax
  308. jz Exit //do nothing if ExecuteOldFullDebugModeDllEntry flag not set
  309. xor eax, eax
  310. mov ExecuteOldFullDebugModeDllEntry, al //reset ExecuteOldDebugModeDllEntry flag
  311. #if __BORLANDC__ < 0x0560
  312. lea eax, OldFullDebugModeDllEntryThunk
  313. jmp eax
  314. #else
  315. jmp OldFullDebugModeDllEntryThunk
  316. #endif
  317. Exit:
  318. setz al
  319. ret
  320. }
  321. }
  322. #endif
  323. void * __fastcall GetModuleEntryPoint(HMODULE AModule)
  324. {
  325. if (AModule)
  326. {
  327. PIMAGE_NT_HEADERS ntheader = (PIMAGE_NT_HEADERS)((unsigned)AModule
  328. + ((PIMAGE_DOS_HEADER)AModule)->e_lfanew);
  329. return (void *)(ntheader->OptionalHeader.AddressOfEntryPoint
  330. + (unsigned)AModule);
  331. }
  332. else
  333. {
  334. return NULL;
  335. }
  336. }
  337. bool __fastcall TryHookFullDebugModeDllEntry(void)
  338. {
  339. HMODULE AModule = GetModuleHandle(FullDebugModeLibraryName);
  340. if (AModule)
  341. {
  342. void *Entry = GetModuleEntryPoint(AModule);
  343. if (Entry)
  344. {
  345. if (PrepareFullDebugModeDllEntryThunk(&OldFullDebugModeDllEntryThunk, Entry))
  346. {
  347. FullDebugModeDllEntryHooked = PatchProc(Entry, &NewFullDebugModeDllEntry, NULL);
  348. return FullDebugModeDllEntryHooked;
  349. }
  350. }
  351. }
  352. return false;
  353. }
  354. void __fastcall CallOldFullDebugModeDllEntry(void)
  355. {
  356. if (FullDebugModeDllEntryHooked)
  357. {
  358. HMODULE AModule = GetModuleHandle(FullDebugModeLibraryName);
  359. if (AModule)
  360. {
  361. ExecuteOldFullDebugModeDllEntry = 1;
  362. NewFullDebugModeDllEntry((HINSTANCE)AModule, DLL_PROCESS_DETACH, NULL);
  363. }
  364. }
  365. }
  366. #endif
  367. #define DVCLALResName _TEXT("DVCLAL")
  368. #define _terminateExport "_terminate"
  369. //Return true if patched OK
  370. bool __fastcall Patch_terminate(void)
  371. {
  372. if (!PatchLocation)
  373. {
  374. #ifndef _RTLDLL //Not uses Dynamic RTL
  375. PatchLocation = &_terminate;
  376. #else
  377. //Get module handle of RTL dll
  378. PIndirectJmp32 P = (PIndirectJmp32)&exit;
  379. if ((!IsBadReadPtr(P, sizeof(TIndirectJmp32))) && (P->JmpInst == 0x25FF)
  380. && (P->DestPtr) && (!IsBadReadPtr(P->DestPtr, sizeof(void *))))
  381. {
  382. PatchLocation = *(P->DestPtr);
  383. }
  384. else {
  385. PatchLocation = P;
  386. }
  387. PatchLocation = (void *)System::FindHInstance(PatchLocation);
  388. if (PatchLocation)
  389. {
  390. //Get real patch location
  391. PatchLocation = GetProcAddress((HMODULE)PatchLocation, _terminateExport);
  392. if (!PatchLocation)
  393. {
  394. return false;
  395. }
  396. }
  397. else {
  398. return false;
  399. }
  400. #endif //_RTLDLL
  401. if ((((PRelativeJmp32)PatchLocation)->JmpInst == RelativeJmp32Inst)
  402. || (!PatchProc(PatchLocation, &New_terminate, NULL)))
  403. {
  404. PatchLocation = NULL;
  405. return false;
  406. }
  407. else {
  408. return true;
  409. }
  410. }
  411. else {
  412. return true;
  413. }
  414. }
  415. extern int __CPPdebugHook;
  416. bool IsMMInstalled = false;
  417. bool IsInDLL = false;
  418. bool IsBorlandMMDLL = false;
  419. bool terminatePatched = false;
  420. #define CPPdebugHookExport "___CPPdebugHook"
  421. //#ifndef _RTLDLL
  422. #if __BORLANDC__ < 0x0560
  423. #if defined(PURE_CPLUSPLUS)
  424. void * _RTLENTRY Cpp_malloc_Stub(size_t size)
  425. {
  426. if (size)
  427. return InternalGetMem(size);
  428. else
  429. return NULL;
  430. }
  431. void _RTLENTRY Cpp_free_Stub(void *block)
  432. {
  433. if (block)
  434. InternalFreeMem(block);
  435. }
  436. void * _RTLENTRY Cpp_realloc_Stub(void *block, size_t size)
  437. {
  438. if (!block)
  439. {
  440. if (size)
  441. return InternalGetMem(size);
  442. else
  443. return NULL;
  444. }
  445. else {
  446. if (!size)
  447. {
  448. InternalFreeMem(block);
  449. return NULL;
  450. }
  451. else
  452. return InternalReallocMem(block, size);
  453. }
  454. }
  455. void _RTLENTRY Cpp_terminate_Stub(void)
  456. {
  457. }
  458. #else
  459. GetMemFunc GetMemPtr;
  460. FreeMemFunc FreeMemPtr;
  461. ReallocMemFunc ReallocMemPtr;
  462. //#pragma warn -8002 //"W8002: Restarting compile using assembly"
  463. #pragma option -w-asc
  464. //#pragma warn -8070 //"W8070 Function should return a value"
  465. #pragma option -w-rvl //the same as above
  466. __declspec(naked) void * _RTLENTRY Cpp_malloc_Stub(size_t size)
  467. {
  468. asm
  469. {
  470. mov eax, [esp + 4] //size
  471. test eax, eax
  472. jz malloc_Exit
  473. //#if __BORLANDC__ >= 0x564
  474. // jmp GetMemPtr
  475. // nop
  476. //#else
  477. call GetMemPtr
  478. ret
  479. //#endif
  480. nop
  481. malloc_Exit:
  482. ret
  483. }
  484. }
  485. __declspec(naked) void _RTLENTRY Cpp_free_Stub(void *block)
  486. {
  487. asm
  488. {
  489. mov eax, [esp + 4] //block
  490. test eax, eax
  491. jz free_Exit
  492. //#if __BORLANDC__ >= 0x564
  493. // jmp FreeMemPtr
  494. // nop
  495. //#else
  496. call FreeMemPtr
  497. ret
  498. //#endif
  499. nop
  500. free_Exit:
  501. ret
  502. }
  503. }
  504. __declspec(naked) void * _RTLENTRY Cpp_realloc_Stub(void *block, size_t size)
  505. {
  506. asm
  507. {
  508. mov eax, [esp + 4] //block
  509. test eax, eax
  510. jnz realloc_Realloc
  511. realloc_Alloc:
  512. mov eax, [esp + 8] //size
  513. test eax, eax
  514. jz realloc_Exit2 //realloc_Exit1
  515. //#if __BORLANDC__ >= 0x564
  516. // jmp GetMemPtr
  517. // nop
  518. //#else
  519. call GetMemPtr
  520. ret
  521. //#endif
  522. nop
  523. ////realloc_Exit1:
  524. // //ret
  525. realloc_Realloc:
  526. mov edx, [esp + 8] //size
  527. test edx, edx
  528. jnz realloc_DoRealloc
  529. call FreeMemPtr
  530. realloc_ReturnNULL:
  531. xor eax, eax
  532. realloc_Exit2:
  533. ret
  534. nop
  535. nop
  536. nop
  537. realloc_DoRealloc:
  538. //#if __BORLANDC__ >= 0x564
  539. // jmp ReallocMemPtr
  540. // //ret
  541. //#else
  542. call ReallocMemPtr
  543. ret
  544. //#endif
  545. }
  546. }
  547. __declspec(naked) void _RTLENTRY Cpp_terminate_Stub(void)
  548. {
  549. //Do nothing
  550. asm ret;
  551. }
  552. #endif
  553. #else
  554. //#pragma warn -8070 //"W8070 Function should return a value"
  555. #pragma option -w-rvl //the same as above
  556. __declspec(naked) void * _RTLENTRY Cpp_malloc_Stub(size_t size)
  557. {
  558. //if (size)
  559. //return InternalGetMem(size);
  560. //else
  561. //return NULL;
  562. asm
  563. {
  564. mov eax, [esp + 4] //size
  565. test eax, eax
  566. jz malloc_Exit
  567. #if __BORLANDC__ >= 0x564
  568. jmp InternalGetMem
  569. nop
  570. #else
  571. call InternalGetMem
  572. ret
  573. #endif
  574. nop
  575. nop
  576. malloc_Exit:
  577. ret
  578. }
  579. }
  580. __declspec(naked) void _RTLENTRY Cpp_free_Stub(void *block)
  581. {
  582. //if (block)
  583. //InternalFreeMem(block);
  584. asm
  585. {
  586. mov eax, [esp + 4] //block
  587. test eax, eax
  588. jz free_Exit
  589. #if __BORLANDC__ >= 0x564
  590. jmp InternalFreeMem
  591. nop
  592. #else
  593. call InternalFreeMem
  594. ret
  595. #endif
  596. nop
  597. nop
  598. free_Exit:
  599. ret
  600. }
  601. }
  602. __declspec(naked) void * _RTLENTRY Cpp_realloc_Stub(void *block, size_t size)
  603. {
  604. /*
  605. if (!block)
  606. {
  607. if (size)
  608. return InternalGetMem(size);
  609. else
  610. return NULL;
  611. }
  612. else {
  613. if (!size)
  614. {
  615. InternalFreeMem(block);
  616. return NULL;
  617. }
  618. else
  619. return InternalReallocMem(block, size);
  620. }
  621. */
  622. asm
  623. {
  624. mov eax, [esp + 4] //block
  625. test eax, eax
  626. jnz realloc_Realloc
  627. realloc_Alloc:
  628. mov eax, [esp + 8] //size
  629. test eax, eax
  630. jz realloc_Exit2 //realloc_Exit1
  631. #if __BORLANDC__ >= 0x564
  632. jmp InternalGetMem
  633. nop
  634. #else
  635. call InternalGetMem
  636. ret
  637. #endif
  638. nop
  639. nop
  640. //realloc_Exit1:
  641. //ret
  642. realloc_Realloc:
  643. mov edx, [esp + 8] //size
  644. test edx, edx
  645. jnz realloc_DoRealloc
  646. call InternalFreeMem
  647. realloc_ReturnNULL:
  648. xor eax, eax
  649. realloc_Exit2:
  650. ret
  651. realloc_DoRealloc:
  652. #if __BORLANDC__ >= 0x564
  653. jmp InternalReallocMem
  654. //ret
  655. #else
  656. call InternalReallocMem
  657. ret
  658. #endif
  659. }
  660. }
  661. __declspec(naked) void _RTLENTRY Cpp_terminate_Stub(void)
  662. {
  663. //Do nothing
  664. asm ret;
  665. }
  666. #endif
  667. #ifdef DetectMMOperationsAfterUninstall
  668. GetMemFunc InvalidGetMemPtr;
  669. FreeMemFunc InvalidFreeMemPtr;
  670. ReallocMemFunc InvalidReallocMemPtr;
  671. #if defined(PURE_CPLUSPLUS) //__BORLANDC__ < 0x0560
  672. void * _RTLENTRY Cpp_Invalid_malloc_Stub(size_t size)
  673. {
  674. if (size)
  675. return (*InvalidGetMemPtr)(size);
  676. else
  677. return NULL;
  678. }
  679. void _RTLENTRY Cpp_Invalid_free_Stub(void *block)
  680. {
  681. if (block)
  682. (*InvalidFreeMemPtr)(block);
  683. }
  684. void * _RTLENTRY Cpp_Invalid_realloc_Stub(void *block, size_t size)
  685. {
  686. if (!block)
  687. {
  688. if (size)
  689. return (*InvalidGetMemPtr)(size);
  690. else
  691. return NULL;
  692. }
  693. else {
  694. if (!size)
  695. {
  696. (*InvalidFreeMemPtr)(block);
  697. return NULL;
  698. }
  699. else
  700. return (*InvalidReallocMemPtr)(block, size);
  701. }
  702. }
  703. #else
  704. //#pragma warn -8002 //"W8002: Restarting compile using assembly"
  705. #pragma option -w-asc
  706. //#pragma warn -8070 //"W8070 Function should return a value"
  707. #pragma option -w-rvl //the same as above
  708. __declspec(naked) void * _RTLENTRY Cpp_Invalid_malloc_Stub(size_t size)
  709. {
  710. asm
  711. {
  712. mov eax, [esp + 4] //size
  713. test eax, eax
  714. jz Invalid_malloc_Exit
  715. #if __BORLANDC__ >= 0x564
  716. jmp InvalidGetMemPtr
  717. nop
  718. #else
  719. call InvalidGetMemPtr
  720. ret
  721. #endif
  722. nop
  723. Invalid_malloc_Exit:
  724. ret
  725. }
  726. }
  727. __declspec(naked) void _RTLENTRY Cpp_Invalid_free_Stub(void *block)
  728. {
  729. asm
  730. {
  731. mov eax, [esp + 4] //block
  732. test eax, eax
  733. jz Invalid_free_Exit
  734. #if __BORLANDC__ >= 0x564
  735. jmp InvalidFreeMemPtr
  736. nop
  737. #else
  738. call InvalidFreeMemPtr
  739. ret
  740. #endif
  741. nop
  742. Invalid_free_Exit:
  743. ret
  744. }
  745. }
  746. __declspec(naked) void * _RTLENTRY Cpp_Invalid_realloc_Stub(void *block, size_t size)
  747. {
  748. asm
  749. {
  750. mov eax, [esp + 4] //block
  751. test eax, eax
  752. jnz Invalid_realloc_Realloc
  753. Invalid_realloc_Alloc:
  754. mov eax, [esp + 8] //size
  755. test eax, eax
  756. jz Invalid_realloc_Exit2 //Invalid_realloc_Exit1
  757. #if __BORLANDC__ >= 0x564
  758. jmp InvalidGetMemPtr
  759. nop
  760. #else
  761. call InvalidGetMemPtr
  762. ret
  763. #endif
  764. nop
  765. //Invalid_realloc_Exit1:
  766. //ret
  767. Invalid_realloc_Realloc:
  768. mov edx, [esp + 8] //size
  769. test edx, edx
  770. jnz Invalid_realloc_DoRealloc
  771. call InvalidFreeMemPtr
  772. Invalid_realloc_ReturnNULL:
  773. xor eax, eax
  774. Invalid_realloc_Exit2:
  775. ret
  776. nop
  777. nop
  778. nop
  779. Invalid_realloc_DoRealloc:
  780. #if __BORLANDC__ >= 0x564
  781. jmp InvalidReallocMemPtr
  782. //ret
  783. #else
  784. call InvalidReallocMemPtr
  785. ret
  786. #endif
  787. }
  788. }
  789. #endif
  790. #endif //DetectMMOperationsAfterUninstall
  791. #pragma option push -b -a8
  792. typedef void (_RTLENTRY *HeapRedirect_free) (void *);
  793. typedef void * (_RTLENTRY *HeapRedirect_malloc) (size_t);
  794. typedef void * (_RTLENTRY *HeapRedirect_realloc) (void *, size_t);
  795. typedef void (_RTLENTRY *HeapRedirect_terminate) (void);
  796. typedef enum
  797. {
  798. hrfVirgin,
  799. hrfInternal,
  800. hrfBorlndmm,
  801. hrfOldBorlndmm,
  802. hrfVCLSystem,
  803. hrfDgbAlloc,
  804. hrfOther
  805. } HeapRedirectFlag;
  806. typedef struct
  807. {
  808. size_t size;
  809. unsigned int allocated;
  810. HeapRedirectFlag flags;
  811. HeapRedirect_free free;
  812. HeapRedirect_malloc malloc;
  813. HeapRedirect_realloc realloc;
  814. HeapRedirect_terminate terminate;
  815. } HeapRedirector;
  816. typedef struct HeapRedirectorStoreStruct
  817. {
  818. HeapRedirector Data;
  819. HMODULE Module;
  820. void * PatchAddress;
  821. TRelativeJmp32 PatchBackup;
  822. struct HeapRedirectorStoreStruct *Next;
  823. } HeapRedirectorStore, *HeapRedirectorStorePtr;
  824. extern HeapRedirector * _RTLENTRY _EXPFUNC _get_heap_redirector_info(void);
  825. typedef HeapRedirector * _RTLENTRY _EXPFUNC (* rtl_get_heap_redirector_info_func)(void);
  826. #pragma option pop
  827. HeapRedirector * pHRDir = NULL;
  828. HeapRedirector Old_heap_redirector;
  829. HeapRedirectorStorePtr HeapRedirectorStoreListHeader = NULL;
  830. //#endif //!_RTLDLL
  831. #define UseHeap
  832. #ifdef UseHeap
  833. HANDLE ProcessHeapHandle = NULL;
  834. #endif
  835. void __fastcall InitFinalMemMgr(void)
  836. {
  837. #ifdef UseHeap
  838. if (!ProcessHeapHandle)
  839. {
  840. ProcessHeapHandle = GetProcessHeap();
  841. }
  842. #endif
  843. }
  844. void * __fastcall FinalGetMem(unsigned ASize)
  845. {
  846. #ifdef UseHeap
  847. return HeapAlloc(ProcessHeapHandle, HEAP_GENERATE_EXCEPTIONS, ASize);
  848. #else
  849. return malloc(ASize);
  850. #endif
  851. }
  852. void __fastcall FinalFreeMem(void * ABlock)
  853. {
  854. #ifdef UseHeap
  855. HeapFree(ProcessHeapHandle, 0, ABlock);
  856. #else
  857. free(ABlock);
  858. #endif
  859. }
  860. void * __fastcall FinalReallocMem(void * ABlock, unsigned ANewSize)
  861. {
  862. #ifdef UseHeap
  863. return HeapReAlloc(ProcessHeapHandle, HEAP_GENERATE_EXCEPTIONS, ABlock, ANewSize);
  864. #else
  865. return realloc(ABlock, ANewSize);
  866. #endif
  867. }
  868. void __fastcall FinalizeHeapRedirectorStoreList(void)
  869. {
  870. if (HeapRedirectorStoreListHeader)
  871. {
  872. HeapRedirectorStorePtr next, ptr = HeapRedirectorStoreListHeader;
  873. HeapRedirectorStoreListHeader = NULL;
  874. while (ptr)
  875. {
  876. next = ptr->Next;
  877. FinalFreeMem(ptr);
  878. ptr = next;
  879. }
  880. }
  881. }
  882. typedef bool __fastcall (* EnumModuleCallback)(HMODULE AModule, void *AParam);
  883. #define PSAPI _TEXT("psapi")
  884. bool __fastcall EnumModulesWinNT(EnumModuleCallback ACallback, void *AParam)
  885. {
  886. typedef BOOL (__stdcall * EnumProcessModulesType)(HANDLE hProcess,
  887. HMODULE* lphModule,
  888. DWORD cb,
  889. LPDWORD lpcbNeeded
  890. );
  891. if (!ACallback)
  892. {
  893. return false;
  894. }
  895. EnumProcessModulesType EnumProcessModules;
  896. bool DynamicLoaded;
  897. HMODULE PsapiLib = GetModuleHandle(PSAPI);
  898. if (!PsapiLib)
  899. {
  900. PsapiLib = LoadLibrary(PSAPI);
  901. if (!PsapiLib)
  902. {
  903. return false;
  904. }
  905. DynamicLoaded = true;
  906. }
  907. else {
  908. DynamicLoaded = false;
  909. }
  910. InitFinalMemMgr();
  911. bool ret = false;
  912. try
  913. {
  914. EnumProcessModules = (EnumProcessModulesType)GetProcAddress(PsapiLib,
  915. "EnumProcessModules");
  916. if (EnumProcessModules)
  917. {
  918. HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
  919. FALSE, GetCurrentProcessId());
  920. if (hProcess)
  921. {
  922. try
  923. {
  924. DWORD cbNeeded = 0;
  925. if (EnumProcessModules(hProcess, NULL, 0, &cbNeeded))
  926. {
  927. HMODULE * hMod = (HMODULE *)FinalGetMem(cbNeeded);
  928. try
  929. {
  930. if (EnumProcessModules(hProcess, hMod, cbNeeded, &cbNeeded))
  931. {
  932. for (unsigned int i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)
  933. {
  934. if (!ACallback(hMod[i], AParam))
  935. {
  936. break;
  937. }
  938. }
  939. ret = true;
  940. }
  941. }
  942. __finally
  943. {
  944. FinalFreeMem(hMod);
  945. }
  946. }
  947. }
  948. __finally
  949. {
  950. CloseHandle(hProcess);
  951. }
  952. }
  953. }
  954. }
  955. __finally
  956. {
  957. if (DynamicLoaded)
  958. {
  959. FreeLibrary(PsapiLib);
  960. }
  961. }
  962. return ret;
  963. }
  964. #define KERNEL32 _TEXT("kernel32")
  965. bool __fastcall EnumModulesWin9x(EnumModuleCallback ACallback, void *AParam)
  966. {
  967. #define MAX_MODULE_NAME32 255
  968. #define TH32CS_SNAPMODULE 0x00000008
  969. typedef struct tagMODULEENTRY32
  970. {
  971. DWORD dwSize;
  972. DWORD th32ModuleID;
  973. DWORD th32ProcessID;
  974. DWORD GlblcntUsage;
  975. DWORD ProccntUsage;
  976. BYTE * modBaseAddr;
  977. DWORD modBaseSize;
  978. HMODULE hModule;
  979. char szModule[MAX_MODULE_NAME32 + 1];
  980. char szExePath[MAX_PATH];
  981. } MODULEENTRY32;
  982. typedef MODULEENTRY32 * PMODULEENTRY32;
  983. typedef MODULEENTRY32 * LPMODULEENTRY32;
  984. typedef HANDLE (__stdcall * CreateToolhelp32SnapshotType)(DWORD dwFlags,
  985. DWORD th32ProcessID);
  986. typedef BOOL (__stdcall * Module32FirstType)(HANDLE hSnapshot, LPMODULEENTRY32 lpme);
  987. typedef BOOL (__stdcall * Module32NextType)(HANDLE hSnapshot, LPMODULEENTRY32 lpme);
  988. if (!ACallback)
  989. {
  990. return false;
  991. }
  992. HMODULE Kernel32Lib;
  993. HANDLE hSnapshot;
  994. CreateToolhelp32SnapshotType CreateToolhelp32Snapshot;
  995. Module32FirstType Module32First;
  996. Module32NextType Module32Next;
  997. bool ret = false;
  998. Kernel32Lib = GetModuleHandle(KERNEL32);
  999. if (Kernel32Lib)
  1000. {
  1001. CreateToolhelp32Snapshot = (CreateToolhelp32SnapshotType)GetProcAddress(Kernel32Lib,
  1002. "CreateToolhelp32Snapshot");
  1003. Module32First = (Module32FirstType)GetProcAddress(Kernel32Lib, "Module32First");
  1004. Module32Next = (Module32NextType)GetProcAddress(Kernel32Lib, "Module32Next");
  1005. if ((CreateToolhelp32Snapshot) && (Module32First) && (Module32Next))
  1006. {
  1007. hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
  1008. if (hSnapshot != INVALID_HANDLE_VALUE)
  1009. {
  1010. try
  1011. {
  1012. MODULEENTRY32 ModuleInfo = {0};
  1013. ModuleInfo.dwSize = sizeof(ModuleInfo);
  1014. while (Module32First(hSnapshot, &ModuleInfo))
  1015. {
  1016. if (!ACallback(ModuleInfo.hModule, AParam))
  1017. break;
  1018. }
  1019. ret = true;
  1020. }
  1021. __finally
  1022. {
  1023. CloseHandle(hSnapshot);
  1024. }
  1025. }
  1026. }
  1027. }
  1028. return ret;
  1029. }
  1030. bool __fastcall EnumModules(EnumModuleCallback ACallback, void *AParam)
  1031. {
  1032. if (ACallback)
  1033. {
  1034. OSVERSIONINFO OSVersionInfo;
  1035. OSVersionInfo.dwOSVersionInfoSize = sizeof(OSVersionInfo);
  1036. if (GetVersionEx(&OSVersionInfo))
  1037. {
  1038. if (OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
  1039. {
  1040. return EnumModulesWinNT(ACallback, AParam);
  1041. }
  1042. else {
  1043. return EnumModulesWin9x(ACallback, AParam);
  1044. }
  1045. }
  1046. }
  1047. return false;
  1048. }
  1049. #ifdef CheckCppObjectTypeEnabled
  1050. typedef struct {
  1051. DWORD CodeSecStart;
  1052. DWORD DataSecStart;
  1053. DWORD DataSecEnd;
  1054. } ModuleCodeDataRanges, * PModuleCodeDataRanges;
  1055. int ModuleCodeDataRangesCount = 0;
  1056. int ModuleCodeDataRangesCapacity = 0;
  1057. PModuleCodeDataRanges gpModuleCodeDataRanges = NULL;
  1058. unsigned LowestDataAddr = NULL;
  1059. unsigned HighestDataAddr = NULL;
  1060. bool __fastcall FindCodeDataRangeByDataAddr(DWORD ADataAddr, int * Index,
  1061. PModuleCodeDataRanges * ARange)
  1062. {
  1063. bool ret = false;
  1064. int L, H, I;
  1065. L = 0;
  1066. H = ModuleCodeDataRangesCount - 1;
  1067. while (L <= H)
  1068. {
  1069. I = (L + H) / 2;
  1070. DWORD AStart = gpModuleCodeDataRanges[I].DataSecStart;
  1071. DWORD AEnd = gpModuleCodeDataRanges[I].DataSecEnd;
  1072. if (ADataAddr < AStart)
  1073. {
  1074. H = I - 1;
  1075. }
  1076. else if (ADataAddr >= AEnd)
  1077. {
  1078. L = I + 1;
  1079. }
  1080. else {
  1081. if (ARange)
  1082. {
  1083. *ARange = &(gpModuleCodeDataRanges[I]);
  1084. }
  1085. L = I;
  1086. ret = true;
  1087. break;
  1088. }
  1089. }
  1090. if (Index)
  1091. {
  1092. *Index = L;
  1093. }
  1094. return ret;
  1095. }
  1096. bool __fastcall FindCodeDataRangeByCodeAddr(DWORD ACodeAddr, int * Index,
  1097. PModuleCodeDataRanges * ARange)
  1098. {
  1099. bool ret = false;
  1100. int L, H, I;
  1101. L = 0;
  1102. H = ModuleCodeDataRangesCount - 1;
  1103. while (L <= H)
  1104. {
  1105. I = (L + H) / 2;
  1106. DWORD AStart = gpModuleCodeDataRanges[I].CodeSecStart;
  1107. DWORD AEnd = gpModuleCodeDataRanges[I].DataSecStart;
  1108. if (ACodeAddr < AStart)
  1109. {
  1110. H = I - 1;
  1111. }
  1112. else if (ACodeAddr >= AEnd)
  1113. {
  1114. L = I + 1;
  1115. }
  1116. else {
  1117. if (ARange)
  1118. {
  1119. *ARange = &(gpModuleCodeDataRanges[I]);
  1120. }
  1121. L = I;
  1122. ret = true;
  1123. break;
  1124. }
  1125. }
  1126. if (Index)
  1127. {
  1128. *Index = L;
  1129. }
  1130. return ret;
  1131. }
  1132. PIMAGE_SECTION_HEADER __fastcall GetImageFirstSection(PIMAGE_NT_HEADERS ntheader)
  1133. {
  1134. return (PIMAGE_SECTION_HEADER)((unsigned)&(ntheader->OptionalHeader)
  1135. + ntheader->FileHeader.SizeOfOptionalHeader);
  1136. }
  1137. #define DefaultCodeSectionName _TEXT(".text")
  1138. #define DefaultDataSectionName _TEXT(".data")
  1139. bool __fastcall AddModuleCodeDataRange(HMODULE AModule, void *AParam)
  1140. {
  1141. if ((FindResource(AModule, DVCLALResName, RT_RCDATA))
  1142. /*&& (GetProcAddress(AModule, CPPdebugHookExport))*/)
  1143. {
  1144. PIMAGE_NT_HEADERS ntheader = (PIMAGE_NT_HEADERS)((unsigned)AModule
  1145. + ((PIMAGE_DOS_HEADER)AModule)->e_lfanew);
  1146. PIMAGE_SECTION_HEADER CodeSecHeader = GetImageFirstSection(ntheader);
  1147. //= IMAGE_FIRST_SECTION(ntheader);
  1148. PIMAGE_SECTION_HEADER DataSecHeader = CodeSecHeader + 1;
  1149. if (((memcmp(DefaultCodeSectionName, CodeSecHeader->Name, 5)) == 0)
  1150. && (CodeSecHeader->Characteristics == (IMAGE_SCN_MEM_EXECUTE
  1151. | IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_CODE))
  1152. && ((memcmp(DefaultDataSectionName, DataSecHeader->Name, 5)) == 0)
  1153. && (DataSecHeader->Characteristics == (IMAGE_SCN_MEM_WRITE
  1154. | IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA)))
  1155. {
  1156. int Index;
  1157. if (!FindCodeDataRangeByDataAddr((unsigned)AModule
  1158. + DataSecHeader->VirtualAddress, &Index, NULL))
  1159. {
  1160. int NewCount = ModuleCodeDataRangesCount + 1;
  1161. if (NewCount >= ModuleCodeDataRangesCapacity)
  1162. {
  1163. //Realloc
  1164. int NewCapacity = ModuleCodeDataRangesCapacity
  1165. + (ModuleCodeDataRangesCapacity / 4);
  1166. gpModuleCodeDataRanges =
  1167. (PModuleCodeDataRanges)FinalReallocMem(gpModuleCodeDataRanges,
  1168. sizeof(ModuleCodeDataRanges) * NewCapacity);
  1169. ModuleCodeDataRangesCapacity = NewCapacity;
  1170. }
  1171. ModuleCodeDataRangesCount = NewCount;
  1172. gpModuleCodeDataRanges[Index].CodeSecStart = (unsigned)AModule
  1173. + CodeSecHeader->VirtualAddress;
  1174. gpModuleCodeDataRanges[Index].DataSecStart = (unsigned)AModule
  1175. + DataSecHeader->VirtualAddress;
  1176. gpModuleCodeDataRanges[Index].DataSecEnd = (unsigned)AModule
  1177. + DataSecHeader->VirtualAddress + DataSecHeader->Misc.VirtualSize;
  1178. }
  1179. }
  1180. }
  1181. return true;
  1182. }
  1183. void __fastcall FinalizeModuleCodeDataRanges(void)
  1184. {
  1185. if ((unsigned)gpModuleCodeDataRanges > 1)
  1186. {
  1187. FinalFreeMem(gpModuleCodeDataRanges);
  1188. gpModuleCodeDataRanges = NULL;
  1189. ModuleCodeDataRangesCount = 0;
  1190. ModuleCodeDataRangesCapacity = NULL;
  1191. }
  1192. }
  1193. #define InitialCodeDataRangeCount 256
  1194. bool __fastcall FillModuleCodeDataRanges(void)
  1195. {
  1196. if (!gpModuleCodeDataRanges)
  1197. {
  1198. InitFinalMemMgr();
  1199. gpModuleCodeDataRanges =
  1200. (PModuleCodeDataRanges)FinalGetMem(sizeof(ModuleCodeDataRanges)
  1201. * InitialCodeDataRangeCount);
  1202. ModuleCodeDataRangesCapacity = InitialCodeDataRangeCount;
  1203. bool ret = EnumModules(AddModuleCodeDataRange, NULL);
  1204. if ((!ret) || (!ModuleCodeDataRangesCount))
  1205. {
  1206. FinalizeModuleCodeDataRanges();
  1207. gpModuleCodeDataRanges = (PModuleCodeDataRanges)1;
  1208. return false;
  1209. }
  1210. if (ret)
  1211. {
  1212. LowestDataAddr = gpModuleCodeDataRanges->DataSecStart;
  1213. HighestDataAddr =
  1214. gpModuleCodeDataRanges[ModuleCodeDataRangesCount - 1].DataSecEnd
  1215. - sizeof(void *);
  1216. }
  1217. return ret;
  1218. }
  1219. else {
  1220. return false;
  1221. }
  1222. }
  1223. #pragma option push -a1
  1224. struct TypeDescriptor;
  1225. typedef TypeDescriptor * TypeDescriptorPtr;
  1226. struct TypeDescriptor
  1227. {
  1228. unsigned Size;
  1229. unsigned short Mask;
  1230. unsigned short Name;
  1231. union
  1232. {
  1233. struct
  1234. {
  1235. unsigned VTablePtrOffset;
  1236. unsigned Flags;
  1237. }
  1238. Class;
  1239. };
  1240. };
  1241. //TypeDescriptor.Mask flags
  1242. #define TYPE_MASK_IS_STRUCT 0x0001
  1243. #define TYPE_MASK_IS_CLASS 0x0002
  1244. #define CLASS_FLAG_HAS_VTABPTR 0x00000010
  1245. #define CLASS_FLAG_HAS_RTTI 0x00000040
  1246. #pragma option pop
  1247. TypeDescriptorPtr __fastcall GetCppVirtualObjectTypeIdPtrByVTablePtr(void * AVTablePtr,
  1248. unsigned AVTablePtrOffset)
  1249. {
  1250. if (AVTablePtr)
  1251. {
  1252. if ((!((unsigned)AVTablePtr & (sizeof(void *) - 1)))
  1253. && (!((unsigned)AVTablePtrOffset & (sizeof(void *) - 1))))
  1254. {
  1255. if (!gpModuleCodeDataRanges)
  1256. {
  1257. if (!FillModuleCodeDataRanges())
  1258. {
  1259. return NULL;
  1260. }
  1261. }
  1262. if (((unsigned)AVTablePtr >= LowestDataAddr) && ((unsigned)AVTablePtr <= HighestDataAddr))
  1263. {
  1264. PModuleCodeDataRanges ADataRange, ACodeRange;
  1265. if (FindCodeDataRangeByDataAddr((unsigned)AVTablePtr
  1266. - (sizeof(unsigned) * 4), NULL, &ADataRange))
  1267. {
  1268. //maybe vtableptr
  1269. unsigned * vftPtr = (unsigned *)AVTablePtr;
  1270. unsigned VMFuncAddr = *vftPtr;
  1271. if (((VMFuncAddr >= ADataRange->CodeSecStart)
  1272. && (VMFuncAddr < ADataRange->DataSecStart))
  1273. || (FindCodeDataRangeByCodeAddr(VMFuncAddr, NULL, &ACodeRange)))
  1274. {
  1275. //address of virtual member function is valid
  1276. unsigned varOffset = vftPtr[-2];
  1277. unsigned rttiPtrOffset = vftPtr[-1];
  1278. if (varOffset <= AVTablePtrOffset)
  1279. {
  1280. unsigned rttiPtr = (unsigned)((char *)vftPtr - rttiPtrOffset);
  1281. if ((rttiPtr >= ADataRange->DataSecStart)
  1282. && (((unsigned *)rttiPtr)[-1] == 0))
  1283. { //rtti Ptr is valid
  1284. TypeDescriptorPtr mdtpidPtr = *((TypeDescriptorPtr *)((unsigned *)rttiPtr - 2) - 1);
  1285. if (((unsigned)mdtpidPtr > ADataRange->CodeSecStart)
  1286. && (((unsigned)mdtpidPtr + (sizeof(TypeDescriptor) - sizeof(GUID)))
  1287. < ADataRange->DataSecStart))
  1288. { //tpid data in code section
  1289. if ((mdtpidPtr->Size >= (AVTablePtrOffset + sizeof(void *)))
  1290. && (mdtpidPtr->Class.VTablePtrOffset == AVTablePtrOffset)
  1291. && (mdtpidPtr->Mask & (TYPE_MASK_IS_STRUCT | TYPE_MASK_IS_CLASS))
  1292. && (mdtpidPtr->Class.Flags & (CLASS_FLAG_HAS_VTABPTR | CLASS_FLAG_HAS_RTTI)))
  1293. { //tpid data valid ?
  1294. unsigned char * TypeName = (unsigned char *)mdtpidPtr
  1295. + mdtpidPtr->Name;
  1296. if ((((unsigned)TypeName + sizeof(unsigned char) * 2)
  1297. < ADataRange->DataSecStart) && (*TypeName <= 'z'))
  1298. {
  1299. return mdtpidPtr;
  1300. }
  1301. }
  1302. }
  1303. }
  1304. }
  1305. }
  1306. }
  1307. }
  1308. }
  1309. }
  1310. return NULL;
  1311. }
  1312. //#define CheckVirtualRootBaseFirst //Returned may not be the most derived type
  1313. TypeDescriptorPtr __fastcall GetCppVirtualObjectTypeIdPtr(void * APointer, unsigned ASize)
  1314. {
  1315. if ((APointer) && (ASize >= sizeof(void *)))
  1316. {
  1317. if (!((unsigned)APointer & (sizeof(void *) - 1)))
  1318. {
  1319. if (!gpModuleCodeDataRanges)
  1320. {
  1321. if (!FillModuleCodeDataRanges())
  1322. {
  1323. return NULL;
  1324. }
  1325. }
  1326. #ifdef CheckVirtualRootBaseFirst
  1327. TypeDescriptorPtr ret = GetCppVirtualObjectTypeIdPtrByVTablePtr(*((void **)APointer), 0);
  1328. if (ret)
  1329. {
  1330. return ret;
  1331. }
  1332. #endif
  1333. PModuleCodeDataRanges ADataRange, ACodeRange;
  1334. unsigned ObjectSize = ASize;
  1335. ASize = ASize - (ASize & (sizeof(void *) - 1)) - sizeof(void *);
  1336. unsigned * DataPtr = (unsigned *)((char *)APointer + ASize);
  1337. #ifdef CheckVirtualRootBaseFirst
  1338. while (DataPtr > (unsigned *)APointer)
  1339. #else
  1340. while (DataPtr >= (unsigned *)APointer)
  1341. #endif
  1342. {
  1343. unsigned Data = *DataPtr;
  1344. if ((Data >= LowestDataAddr) && (Data <= HighestDataAddr))
  1345. {
  1346. if (FindCodeDataRangeByDataAddr(Data - (sizeof(unsigned) * 4),
  1347. NULL, &ADataRange))
  1348. {
  1349. //maybe vtableptr
  1350. unsigned * vftPtr = (unsigned *)Data;
  1351. unsigned VMFuncAddr = *vftPtr;
  1352. if (((VMFuncAddr >= ADataRange->CodeSecStart)
  1353. && (VMFuncAddr < ADataRange->DataSecStart))
  1354. || (FindCodeDataRangeByCodeAddr(VMFuncAddr, NULL, &ACodeRange)))
  1355. {
  1356. //address of virtual member function is valid
  1357. unsigned varOffset = vftPtr[-2];
  1358. unsigned rttiPtrOffset = vftPtr[-1];
  1359. unsigned vftPtrOffset = (char *)DataPtr - (char *)APointer;
  1360. if (varOffset <= vftPtrOffset)
  1361. {
  1362. unsigned rttiPtr = (unsigned)((char *)vftPtr - rttiPtrOffset);
  1363. if ((rttiPtr >= ADataRange->DataSecStart)
  1364. && (((unsigned *)rttiPtr)[-1] == 0))
  1365. { //rtti Ptr is valid
  1366. TypeDescriptorPtr mdtpidPtr = *((TypeDescriptorPtr *)((unsigned *)rttiPtr - 2) - 1);
  1367. if (((unsigned)mdtpidPtr > ADataRange->CodeSecStart)
  1368. && (((unsigned)mdtpidPtr + (sizeof(TypeDescriptor) - sizeof(GUID)))
  1369. < ADataRange->DataSecStart))
  1370. { //tpid data in code section
  1371. if ((mdtpidPtr->Size <= ObjectSize)
  1372. && (mdtpidPtr->Class.VTablePtrOffset == vftPtrOffset)
  1373. && (mdtpidPtr->Mask & (TYPE_MASK_IS_STRUCT | TYPE_MASK_IS_CLASS))
  1374. && (mdtpidPtr->Class.Flags & (CLASS_FLAG_HAS_VTABPTR | CLASS_FLAG_HAS_RTTI)))
  1375. { //tpid data valid ?
  1376. unsigned char * TypeName = (unsigned char *)mdtpidPtr
  1377. + mdtpidPtr->Name;
  1378. if ((((unsigned)TypeName + sizeof(unsigned char) * 2)
  1379. < ADataRange->DataSecStart) && (*TypeName <= 'z'))
  1380. {
  1381. return mdtpidPtr;
  1382. }
  1383. }
  1384. }
  1385. }
  1386. }
  1387. }
  1388. }
  1389. }
  1390. DataPtr--;
  1391. }
  1392. }
  1393. }
  1394. return NULL;
  1395. }
  1396. char * __fastcall GetCppVirtualObjectTypeName(void * APointer, unsigned ASize)
  1397. {
  1398. TypeDescriptorPtr AtpidPtr = GetCppVirtualObjectTypeIdPtr(APointer, ASize);
  1399. if (AtpidPtr)
  1400. {
  1401. return (char *)AtpidPtr + AtpidPtr->Name;
  1402. }
  1403. else {
  1404. return NULL;
  1405. }
  1406. }
  1407. char * __fastcall GetCppVirtualObjectTypeNameByVTablePtr(void * AVTablePtr,
  1408. unsigned AVTablePtrOffset)
  1409. {
  1410. TypeDescriptorPtr AtpidPtr = GetCppVirtualObjectTypeIdPtrByVTablePtr(AVTablePtr,
  1411. AVTablePtrOffset);
  1412. if (AtpidPtr)
  1413. {
  1414. return (char *)AtpidPtr + AtpidPtr->Name;
  1415. }
  1416. else {
  1417. return NULL;
  1418. }
  1419. }
  1420. unsigned __fastcall GetCppVirtualObjectSizeByTypeIdPtr(TypeDescriptorPtr AtpidPtr)
  1421. {
  1422. if ((AtpidPtr)
  1423. && (AtpidPtr->Mask & (TYPE_MASK_IS_STRUCT | TYPE_MASK_IS_CLASS))
  1424. && (AtpidPtr->Class.Flags & (CLASS_FLAG_HAS_VTABPTR | CLASS_FLAG_HAS_RTTI)))
  1425. {
  1426. return AtpidPtr->Size;
  1427. }
  1428. else {
  1429. return 0;
  1430. }
  1431. }
  1432. char * __fastcall GetCppVirtualObjectTypeNameByTypeIdPtr(TypeDescriptorPtr AtpidPtr)
  1433. {
  1434. if (AtpidPtr)
  1435. {
  1436. return (char *)AtpidPtr + AtpidPtr->Name;
  1437. }
  1438. else {
  1439. return NULL;
  1440. }
  1441. }
  1442. #endif //CheckCppObjectTypeEnabled
  1443. #define BORLANDMM _TEXT("borlndmm")
  1444. #define CRTL_MEM_SIGNATURE_EXPORT "___CRTL_MEM_GetBorMemPtrs"
  1445. #define CRTL_GET_HEAP_REDIRECTOR_INFO "__get_heap_redirector_info"
  1446. bool __fastcall TryHookRTLHeapRedirector(HMODULE AModule, void *AParam)
  1447. {
  1448. if ((FindResource(AModule, DVCLALResName, RT_RCDATA))
  1449. /*&& (GetProcAddress(AModule, CPPdebugHookExport))*/
  1450. && (GetProcAddress(AModule, CRTL_MEM_SIGNATURE_EXPORT)))
  1451. {
  1452. rtl_get_heap_redirector_info_func rtl_get_heap_redirector_info;
  1453. rtl_get_heap_redirector_info
  1454. = (rtl_get_heap_redirector_info_func)GetProcAddress(AModule, CRTL_GET_HEAP_REDIRECTOR_INFO);
  1455. if (rtl_get_heap_redirector_info)
  1456. {
  1457. HeapRedirector * pHRDir = (*rtl_get_heap_redirector_info)();
  1458. if (pHRDir)
  1459. {
  1460. if ((pHRDir->flags < hrfBorlndmm) || (pHRDir->flags == hrfVCLSystem))
  1461. {
  1462. void * PatchAddr;
  1463. HeapRedirectorStorePtr node = (HeapRedirectorStorePtr)FinalGetMem(sizeof(HeapRedirectorStore));
  1464. node->Data = *pHRDir;
  1465. node->Module = AModule;
  1466. //insert node into store list
  1467. node->Next = HeapRedirectorStoreListHeader;
  1468. HeapRedirectorStoreListHeader = node;
  1469. pHRDir->malloc = &Cpp_malloc_Stub;
  1470. pHRDir->free = &Cpp_free_Stub;
  1471. pHRDir->realloc = &Cpp_realloc_Stub;
  1472. pHRDir->terminate = &Cpp_terminate_Stub;
  1473. pHRDir->flags = hrfOther;
  1474. pHRDir->allocated = 1;
  1475. //patch RTL _terminate of this module
  1476. PatchAddr = GetProcAddress(AModule, _terminateExport);
  1477. if ((PatchAddr) && (((PRelativeJmp32)PatchAddr)->JmpInst != RelativeJmp32Inst)
  1478. && (!PatchProc(PatchAddr, &New_terminate, &node->PatchBackup)))
  1479. {
  1480. node->PatchAddress = PatchAddr;
  1481. }
  1482. else
  1483. {
  1484. node->PatchAddress = NULL;
  1485. }
  1486. }
  1487. }
  1488. }
  1489. }
  1490. return true;
  1491. }
  1492. bool __fastcall TryUnhookRTLHeapRedirector(HMODULE AModule, void *AParam)
  1493. {
  1494. if ((FindResource(AModule, DVCLALResName, RT_RCDATA))
  1495. /*&& (GetProcAddress(AModule, CPPdebugHookExport))*/
  1496. && (GetProcAddress(AModule, CRTL_MEM_SIGNATURE_EXPORT)))
  1497. {
  1498. rtl_get_heap_redirector_info_func rtl_get_heap_redirector_info;
  1499. rtl_get_heap_redirector_info
  1500. = (rtl_get_heap_redirector_info_func)GetProcAddress(AModule, CRTL_GET_HEAP_REDIRECTOR_INFO);
  1501. if (rtl_get_heap_redirector_info)
  1502. {
  1503. HeapRedirector * pHRDir = (*rtl_get_heap_redirector_info)();
  1504. if (pHRDir)
  1505. {
  1506. //restore and remove store node
  1507. {
  1508. HeapRedirectorStorePtr prev, node;
  1509. prev = NULL;
  1510. node = HeapRedirectorStoreListHeader;
  1511. while (node)
  1512. {
  1513. if (node->Module == AModule)
  1514. {
  1515. //restore original heap redirector
  1516. if ((pHRDir->flags == hrfOther)
  1517. && (pHRDir->malloc == &Cpp_malloc_Stub)
  1518. && (pHRDir->free == &Cpp_free_Stub)
  1519. && (pHRDir->realloc == &Cpp_realloc_Stub)
  1520. && (pHRDir->terminate == &Cpp_terminate_Stub)
  1521. )
  1522. {
  1523. #ifdef DetectMMOperationsAfterUninstall
  1524. if ((bool)AParam)
  1525. {
  1526. pHRDir->malloc = &Cpp_Invalid_malloc_Stub;
  1527. pHRDir->free = &Cpp_Invalid_free_Stub;
  1528. pHRDir->realloc = &Cpp_Invalid_realloc_Stub;
  1529. }
  1530. else
  1531. #endif
  1532. *pHRDir = node->Data;
  1533. }
  1534. //restore RTL _terminate of this module
  1535. if (node->PatchAddress)
  1536. {
  1537. UnPatchProc(node->PatchAddress, &New_terminate, &node->PatchBackup);
  1538. }
  1539. //remove node from store list
  1540. if (prev)
  1541. {
  1542. prev->Next = node->Next;
  1543. }
  1544. else
  1545. {
  1546. HeapRedirectorStoreListHeader = node->Next;
  1547. }
  1548. FinalFreeMem(node);
  1549. break;
  1550. }
  1551. else
  1552. {
  1553. prev = node;
  1554. node = node->Next;
  1555. }
  1556. }
  1557. }
  1558. }
  1559. }
  1560. }
  1561. return true;
  1562. }
  1563. #endif //PatchBCBTerminate
  1564. void BCBInstallFastMM()
  1565. {
  1566. //#ifdef __DLL__ //not defined even with -tWD ?
  1567. //#endif
  1568. //#if ((!defined(_NO_VCL)) && defined(__DLL__) && defined(_RTLDLL))
  1569. //borlndmm.dll will linked in
  1570. //#else
  1571. InitializeMemoryManager();
  1572. #if __BORLANDC__ >= 0x582
  1573. //>= BDS2006 ?
  1574. //CheckCanInstallMemoryManager will finally call System.GetHeapStatus which is the
  1575. //internal shipped copy of FastGetHeapStatus routine, but the InitializeMemoryManager
  1576. //routine of that copy is not called yet at this point, and thus System.GetHeapStatus
  1577. //will generate an access violation exception.
  1578. //Currently avoid this exception by skip the check
  1579. #ifndef _NO_VCL
  1580. if (CheckCanInstallMemoryManager())
  1581. #endif //!_NO_VCL
  1582. #else
  1583. if (CheckCanInstallMemoryManager())
  1584. #endif //< BDS2006
  1585. {
  1586. #ifdef PatchBCBTerminate
  1587. #if defined(__DLL__) && defined(FullDebugMode) && defined(LoadDebugDLLDynamically)
  1588. //if FastMM_FullDebugMode.dll receive DLL_PROCESS_DETACH before
  1589. //calling FinalizeMemoryManager, exception will occur when calling
  1590. //LogStackTrace in FastMM_FullDebugMode.dll, the following call
  1591. //will delay the processing of DLL_PROCESS_DETACH in DllMain of
  1592. //FastMM_FullDebugMode.dll
  1593. if (!TryHookFullDebugModeDllEntry())
  1594. {
  1595. return;
  1596. }
  1597. #endif
  1598. #endif
  1599. #ifdef FullDebugMode
  1600. #ifdef ClearLogFileOnStartup
  1601. DeleteEventLog();
  1602. #endif //ClearLogFileOnStartup
  1603. #endif //FullDebugMode
  1604. #ifdef PatchBCBTerminate
  1605. #if __BORLANDC__ >= 0x582
  1606. //>= BDS2006 ?
  1607. System::TMemoryManagerEx AMemoryManager;
  1608. #else
  1609. System::TMemoryManager AMemoryManager;
  1610. #endif
  1611. System::GetMemoryManager(AMemoryManager);
  1612. StockGetMemPtr = AMemoryManager.GetMem;
  1613. #endif
  1614. InstallMemoryManager();
  1615. #if __BORLANDC__ < 0x0560
  1616. #if !defined(PURE_CPLUSPLUS)
  1617. #if !defined(PatchBCBTerminate)
  1618. #if __BORLANDC__ >= 0x582
  1619. //>= BDS2006 ?
  1620. System::TMemoryManagerEx AMemoryManager;
  1621. #else
  1622. System::TMemoryManager AMemoryManager;
  1623. #endif
  1624. #endif
  1625. System::GetMemoryManager(AMemoryManager);
  1626. GetMemPtr = AMemoryManager.GetMem;
  1627. FreeMemPtr = AMemoryManager.FreeMem;
  1628. ReallocMemPtr = AMemoryManager.ReallocMem;
  1629. #endif
  1630. #endif
  1631. #ifdef PatchBCBTerminate
  1632. IsMMInstalled = true;
  1633. #endif
  1634. #ifdef PatchBCBTerminate
  1635. HMODULE ThisModule = (HMODULE)System::FindHInstance(&BCBInstallFastMM);
  1636. HMODULE MainModule = GetModuleHandle(0);
  1637. //#ifndef _RTLDLL
  1638. HMODULE BorlandMM_Module = GetModuleHandle(BORLANDMM);
  1639. if (!BorlandMM_Module)
  1640. {
  1641. pHRDir = _get_heap_redirector_info();
  1642. if (pHRDir)
  1643. {
  1644. if ((pHRDir->flags < hrfBorlndmm) || (pHRDir->flags == hrfVCLSystem))
  1645. {
  1646. Old_heap_redirector = *pHRDir;
  1647. pHRDir->malloc = &Cpp_malloc_Stub;
  1648. pHRDir->free = &Cpp_free_Stub;
  1649. pHRDir->realloc = &Cpp_realloc_Stub;
  1650. pHRDir->terminate = &Cpp_terminate_Stub;
  1651. pHRDir->flags = hrfOther;
  1652. pHRDir->allocated = 1;
  1653. }
  1654. else {
  1655. pHRDir = NULL;
  1656. }
  1657. }
  1658. }
  1659. else
  1660. {
  1661. if (BorlandMM_Module == ThisModule)
  1662. {
  1663. IsBorlandMMDLL = true;
  1664. //Try hook heap redirector of RTL modules
  1665. EnumModules(TryHookRTLHeapRedirector, NULL);
  1666. }
  1667. }
  1668. //#endif //!_RTLDLL
  1669. pCppDebugHook = (int *)(GetProcAddress(MainModule, CPPdebugHookExport));
  1670. if (!pCppDebugHook)
  1671. {
  1672. pCppDebugHook = &__CPPdebugHook;
  1673. }
  1674. #ifdef CheckCppObjectTypeEnabled
  1675. GetCppVirtObjSizeByTypeIdPtrFunc =
  1676. (TGetCppVirtObjSizeByTypeIdPtrFunc)&GetCppVirtualObjectSizeByTypeIdPtr;
  1677. GetCppVirtObjTypeIdPtrFunc =
  1678. (TGetCppVirtObjTypeIdPtrFunc)&GetCppVirtualObjectTypeIdPtr;
  1679. GetCppVirtObjTypeNameFunc =
  1680. (TGetCppVirtObjTypeNameFunc)&GetCppVirtualObjectTypeName;
  1681. GetCppVirtObjTypeNameByTypeIdPtrFunc =
  1682. (TGetCppVirtObjTypeNameByTypeIdPtrFunc)&GetCppVirtualObjectTypeNameByTypeIdPtr;
  1683. GetCppVirtObjTypeNameByVTablePtrFunc =
  1684. (TGetCppVirtObjTypeNameByVTablePtrFunc)&GetCppVirtualObjectTypeNameByVTablePtr;
  1685. #endif
  1686. IsInDLL = (MainModule != ThisModule);
  1687. if (!IsInDLL)
  1688. {
  1689. if (Patch_terminate())
  1690. {
  1691. terminatePatched = true;
  1692. #ifdef EnableMemoryLeakReporting
  1693. #if __BORLANDC__ >= 0x582
  1694. //>= BDS2006 ?
  1695. //"ios.cpp", line 136, ios_base::_Init(), "locale" leaks
  1696. RegisterExpectedMemoryLeak(20, 8);
  1697. //"locale0.cpp", line 167, locale::_Init(), "_Locimp" leak due to above leaks
  1698. RegisterExpectedMemoryLeak(68, 1);
  1699. #endif
  1700. #endif
  1701. }
  1702. }
  1703. #ifndef _RTLDLL
  1704. else
  1705. {
  1706. #ifdef EnableMemoryLeakReporting
  1707. #if __BORLANDC__ >= 0x582
  1708. //>= BDS2006 ?
  1709. //"ios.cpp", line 136, ios_base::_Init(), "locale" leaks
  1710. RegisterExpectedMemoryLeak(20, 8);
  1711. //"locale0.cpp", line 167, locale::_Init(), "_Locimp" leak due to above leaks
  1712. RegisterExpectedMemoryLeak(68, 1);
  1713. RegisterExpectedMemoryLeak(228, 1);
  1714. #endif
  1715. #endif
  1716. }
  1717. #endif //_RTLDLL
  1718. #endif //PatchBCBTerminate
  1719. }
  1720. //#endif
  1721. }
  1722. #pragma startup BCBInstallFastMM 0
  1723. #ifdef PatchBCBTerminate
  1724. void BCBUninstallFastMM()
  1725. {
  1726. //Sadly we cannot uninstall here since there are still live pointers.
  1727. //#if ((!defined(_NO_VCL)) && defined(__DLL__) && defined(_RTLDLL))
  1728. //#else
  1729. if (IsMMInstalled && (!terminatePatched))
  1730. {
  1731. //Delphi MemoryManager already installed here
  1732. FinalizeMemoryManager();
  1733. #if __BORLANDC__ >= 0x582
  1734. //>= BDS2006 ?
  1735. System::TMemoryManagerEx AMemoryManager;
  1736. #else
  1737. System::TMemoryManager AMemoryManager;
  1738. #endif
  1739. System::GetMemoryManager(AMemoryManager);
  1740. //MemoryManager uninstalled ?
  1741. bool DelphiMMUninstalled = (AMemoryManager.GetMem != InternalGetMem);
  1742. #ifdef DetectMMOperationsAfterUninstall
  1743. //InvalidMemoryManager get set as Delphi MemoryManager ?
  1744. bool InvalidMMSet = (AMemoryManager.GetMem != StockGetMemPtr);
  1745. #endif
  1746. #if __BORLANDC__ < 0x0560
  1747. #if !defined(PURE_CPLUSPLUS)
  1748. GetMemPtr = NULL;
  1749. FreeMemPtr = NULL;
  1750. ReallocMemPtr = NULL;
  1751. #endif
  1752. #endif
  1753. #ifdef CheckCppObjectTypeEnabled
  1754. GetCppVirtObjSizeByTypeIdPtrFunc = NULL;
  1755. GetCppVirtObjTypeIdPtrFunc = NULL;
  1756. GetCppVirtObjTypeNameFunc = NULL;
  1757. GetCppVirtObjTypeNameByTypeIdPtrFunc = NULL;
  1758. GetCppVirtObjTypeNameByVTablePtrFunc = NULL;
  1759. FinalizeModuleCodeDataRanges();
  1760. #endif
  1761. if (DelphiMMUninstalled)
  1762. {
  1763. if (pHRDir)
  1764. {
  1765. #ifdef DetectMMOperationsAfterUninstall
  1766. if (InvalidMMSet)
  1767. {
  1768. InvalidGetMemPtr = AMemoryManager.GetMem;
  1769. InvalidFreeMemPtr = AMemoryManager.FreeMem;
  1770. InvalidReallocMemPtr = AMemoryManager.ReallocMem;
  1771. pHRDir->malloc = Cpp_Invalid_malloc_Stub;
  1772. pHRDir->free = Cpp_Invalid_free_Stub;
  1773. pHRDir->realloc = Cpp_Invalid_realloc_Stub;
  1774. }
  1775. else
  1776. #endif
  1777. *pHRDir = Old_heap_redirector;
  1778. pHRDir = NULL;
  1779. }
  1780. else
  1781. {
  1782. if (IsBorlandMMDLL)
  1783. {
  1784. //Try unhook heap redirector of RTL modules
  1785. #ifdef DetectMMOperationsAfterUninstall
  1786. EnumModules(TryUnhookRTLHeapRedirector, (void *)InvalidMMSet);
  1787. #else
  1788. EnumModules(TryUnhookRTLHeapRedirector, NULL);
  1789. #endif
  1790. FinalizeHeapRedirectorStoreList();
  1791. }
  1792. }
  1793. }
  1794. #if defined(__DLL__) && defined(FullDebugMode) && defined(LoadDebugDLLDynamically)
  1795. CallOldFullDebugModeDllEntry();
  1796. #endif
  1797. }
  1798. //#endif
  1799. }
  1800. #pragma exit BCBUninstallFastMM 0
  1801. #endif //PatchBCBTerminate
  1802. #ifdef __cplusplus
  1803. } // extern "C"
  1804. #endif
  1805. #pragma option pop
  1806. //#endif //!_NO_VCL