Jump to content
sp0987

Changes in System.sysutils.pas were not reflecting in other unit in Delphi 11

Recommended Posts

Posted (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 by Remy Lebeau

Share this post


Link to post

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? 

  • Like 2

Share this post


Link to post
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

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

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
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
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
Posted (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 by Remy Lebeau

Share this post


Link to post
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
Posted (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 by Remy Lebeau
  • Thanks 1

Share this post


Link to post
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

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×