Home > database >  SendMessageTimeout in Delphi 64-bit code is not changing result parameter
SendMessageTimeout in Delphi 64-bit code is not changing result parameter

Time:10-12

We send a message to another app using SendMessageTimeout(), but we have noticed that the last parameter result doesn't return the expected value. Example:

var
  ReturnValuePtr: PDWORD_PTR;

begin
  ReturnValuePtr := nil;
  SendMessageTimeout(OtherAppHandle,
                     WM_COPYDATA,
                     0,
                     LPARAM(@CopyDataStruct),
                     SMTOFlag,
                     CTimeout,
                     ReturnValuePtr);

  // Here ReturnValuePtr is still nil when we expect it to be a known value.
end;

But if we change the code to pass @ReturnValuePtr to SendMessageTimeout(), like this:

begin
  ReturnValuePtr:= nil;
  SendMessageTimeout(OtherAppHandle,
                     WM_COPYDATA,
                     0,
                     LPARAM(@CopyDataStruct),
                     SMTOFlag,
                     CTimeout,
                     @ReturnValuePtr);  // <- Only change here

  // Here ReturnValuePtr returns the known expected value.
end;

This way we get the correct value in ReturnValuePtr.
This is the main question: Why does this work? Is it still correct?

We were not sure if the above was correct so we ended up implementing this instead:

var
  ReturnValue: NativeUInt;
  ReturnValuePtr: PDWORD_PTR;

begin
  ReturnValue := 0;
  ReturnValuePtr := @ReturnValue;
  SendMessageTimeout(OtherAppHandle,
                     WM_COPYDATA,
                     0,
                     LPARAM(@CopyDataStruct),
                     SMTOFlag,
                     CTimeout,
                     ReturnValuePtr);
  
  // Here we check ReturnValue and it has the known expected value.
end;

CodePudding user response:

You must provide valid address to the last parameter to allow receiver fill it with some result.

When address is nil, receiver (or Windows messaging system) cannot put data at this address.

Perhaps you did expect that function would change this address, but it cannot (otherwise parameter type should be "pointer to pointer")

So your last variant is correct

CodePudding user response:

The last parameter expects a pointer to a valid DWORD_PTR variable. The function will dereference the pointer when assigning a value to the variable.

In your 1st case, you are passing a nil pointer, which is wrong.

You need to do more like your 3rd case, though you don't need an explicit variable for the pointer, eg:

var
  ReturnValue: DWORD_PTR;

begin
  ReturnValue := 0;
  SendMessageTimeout(OtherAppHandle,
                     WM_COPYDATA,
                     0,
                     LPARAM(@CopyDataStruct),
                     SMTOFlag,
                     CTimeout,
                     @ReturnValue);
end;
  • Related