Remy Lebeau 1269 Posted May 7 (edited) 46 minutes ago, sp0987 said: GetLocalTime is just reference into external Windows DLL in Windows unit I think. Yes. 46 minutes ago, sp0987 said: I'll need to create a wrapper with same name around it with additional logic somewhere within my project which can be reached by the original GetLocalTime in sysUtils? You would write a replacement function in your code, and then detour the original DLL function, and then all calls to the DLL function will go through your replacement function instead. A detour doesn't care whether the original function resides in a DLL or not. It is all in the same address space of the calling process. 46 minutes ago, sp0987 said: Correction: it doesn't need to have same name. I could do something like: // excuse wrong code as I do not have D11 in front of me createNewDetour(@Window.GetLocalTime, @myNewLocalTime, ...); yes? Yes. Edited May 7 by Remy Lebeau Share this post Link to post
David Heffernan 2315 Posted May 8 One thing I find odd is that you feel the need to change the behaviour of basic windows API functions. Why are you doing this? 2 Share this post Link to post
sp0987 0 Posted May 8 4 hours ago, David Heffernan said: One thing I find odd is that you feel the need to change the behaviour of basic windows API functions. Why are you doing this? Because our software needs to operate/tested through time from past to the future in cycles and we can't change the OS time as we did in past. Share this post Link to post
sp0987 0 Posted May 8 before I start, how do I ensure that calling the original Windows.GetLocalTime from within my detoured function does not get also detoured causing circular reference errors? Or that will no longer possible? Example: procedure myNewLocalTime(var st: TSystemTime); begin st := Windows.GetLocalTime(st); // now further modify st end; createNewDetour(@Window.GetLocalTime, @myNewLocalTime, ...); Share this post Link to post
Lajos Juhász 243 Posted May 8 When you create a detour you should store the original function address to be able to return it. we don't know what createNewDetour is doing (it is not part of DDetours that was suggested). Share this post Link to post
sp0987 0 Posted May 8 24 minutes ago, Lajos Juhász said: When you create a detour you should store the original function address to be able to return it. we don't know what createNewDetour is doing (it is not part of DDetours that was suggested). Great idea, thank you. I will save the original reference before the detour and use that from within. FYI, I'm going to rewrite the existing D7 implementation using the mentioned DDetour library and use same or built in D11 as well. Share this post Link to post
Brandon Staggs 198 Posted May 8 6 hours ago, David Heffernan said: One thing I find odd is that you feel the need to change the behaviour of basic windows API functions. Why are you doing this? He explained this earlier. He needs to be able to test operation of code with different dates (past, future). Seems legitimate to me; I've had to do this kind of thing but using RunAsDate has always been sufficient. Share this post Link to post
Remy Lebeau 1269 Posted May 8 (edited) 1 hour ago, sp0987 said: Great idea, thank you. I will save the original reference before the detour and use that from within. That is not how a detour works. If you just save the original function address then you would call back into yourself, as you fear. The original function is still called everywhere, the detour simply modifies the first few bytes of the function to jump to your new function. So creating a detour requires saving the original bytes being modified so the new function can still execute them before jumping back into the original function past the modified bytes to continue the work normally. This is known as a "trampoline". However, in the case of a DLL function, it is simpler to just modify the PE imports table at runtime to redirect the entry of the target function to simply point at a different function, thus bypassing the original function completely. All calls go directly to the new function. In which case, yes, you would need to save the address of the original function so you can call it normally when needed. Since we don't know what your createNewDetour() is actually doing, it's important to know which technique is actually being used. Edited May 8 by Remy Lebeau Share this post Link to post
sp0987 0 Posted May 8 20 minutes ago, Remy Lebeau said: Since we don't know what your createNewDetour() is actually doing, it's important to know which technique is actually being used. I was planning to use the suggested DDetours library and since I didn't have it nor D11 in front of me I called it createNewDetour(). This is the actual function: function InterceptCreate(const TargetProc, InterceptProc: Pointer; const Param: Pointer = nil; const Options: TInterceptOptions = DefaultInterceptOptions): Pointer; overload; 25 minutes ago, Remy Lebeau said: That is not how a detour works. If you just save the original function address then you would call back into yourself, as you fear. Calling reference of the original function will not work then. Thank you for the explanation of the internal DDetours implementation. If there is no other way than I'll look into modifying the PE imports table. That is something I never had to do. Hopefully it is easy. Share this post Link to post
Remy Lebeau 1269 Posted May 8 (edited) 2 hours ago, sp0987 said: This is the actual function: function InterceptCreate(const TargetProc, InterceptProc: Pointer; const Param: Pointer = nil; const Options: TInterceptOptions = DefaultInterceptOptions): Pointer; overload; That function returns a pointer to a trampoline. You must use that pointer when your hook function wants to call the original function. https://github.com/MahdiSafsafi/DDetours/wiki#interceptcreate Quote Return: If the function succeeds, the return value is a pointer to a TrampoLine function that can be used either to call the original function or to call the next hook (if exists). If the function fails, the return value is nil. For example: var TrampolineGetLocalTime: procedure(var st: TSystemTime); stdcall; procedure myNewLocalTime(var st: TSystemTime); stdcall; begin ... TrampolineGetLocalTime(st); ... end; TrampolineGetLocalTime := InterceptCreate(@Windows.GetLocalTime, @myNewLocalTime, ...); This is demonstrated in the DDetours documentation: https://github.com/MahdiSafsafi/DDetours/wiki#hooking-winapi-function Edited May 8 by Remy Lebeau 1 Share this post Link to post
sp0987 0 Posted May 8 26 minutes ago, Remy Lebeau said: That function returns a pointer to a trampoline. You must use that pointer when your hook function wants to call the original function I didn't fully go through their WiKi and examples before, but the "Hooking WinAPI function" example is exactly what I need. I've got the idea how it works now. Thank you ALL for helping out pointing me the right direction! Share this post Link to post