Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7660705
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 31, 20262026-05-31T13:30:07+00:00 2026-05-31T13:30:07+00:00

I have a 3rd party Delphi DLL which I am calling from C++. Unfortunately,

  • 0

I have a 3rd party Delphi DLL which I am calling from C++. Unfortunately, I have no access to the Pascal DLL code, and am not a Pascal programmer.

There is no lib file, so I’m using GetProcAddress to call many DLL functions, successfully passing parameters by value, address and reference. I also register a callback function which gets called when expected.

My problem is that in the callback function, one of the two parameters cannot be evaluated (address 0x000001).

Here are the Pascal DLL function declarations

type
HANDLE = Pointer;       /// handle

(** This function Registers the callback function OnACLNeeded 
  *)
function RegisterCallback(
    h: HANDLE; 
    OnACLNeeded: MyCallbackFunc; 
    UserData: DWORD): Integer; stdcall;

This is the pascal version of the calling application, the callback function.
Both parameters are passed by reference (var).

function TSNAPICongigF.OnACLNeeded(var keySettings, numOfKeys: Byte): Integer; stdcall;
begin
  keySettings:=$0F;
  numOfKeys:=1;
  Result:=0;
end;

This is my C++ version of the callback function

int __stdcall OnACLNeeded(byte& keySettings, byte& numOfKeys)
{
  keySettings = 0x0F;
  numOfKeys = 1;
  return 1;
}

This is my C++ calling code

int _tmain()
{
    HMODULE hLib = LoadLibrary(PASCAL_DLL);

    // DLL function pointer 
    typedef int (__stdcall *FnRegisterCallback)(HANDLE hKeyProvider,
        int (__stdcall *)(byte&, byte&),
        DWORD);

    FnRegisterCallback pfnRegisterCallback =
        (FnRegisterCallback)GetProcAddress(hLib, "RegisterCallback");

    // register my callback function
    int ret = (*pfnRegisteraCllback)(h, OnACLNeeded, (DWORD)1);
}

When running in the debugger, I reach the breakpoint on the first line of the callback function keySettings = 0x0F;
I find that numOfKeys is valid, but keySettings has an address of 0x00000001 and cannot be assigned to.
The application will crash with an AccessViolation if I continue.

int __stdcall OnACLNeeded(byte& keySettings, byte& numOfKeys)
{
    keySettings = 0x0F;

I’ve tried declaring as __cdecl to no effect.
I’ve tried declaring the byte params as byte*, and I get the same invalid parameter.

I’m using Visual Studio 2010 running on Win7 64-bit, but compiling as Win32.
These are my compile and link commands

/ZI /nologo /W3 /WX- /Od /Oy- /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /Gm /EHsc /RTC1 /GS /fp:precise /Zc:wchar_t /Zc:forScope /Fp"Debug\CallPascal.pch" /Fa"Debug\" /Fo"Debug\" /Fd"Debug\vc100.pdb" /Gd /analyze- /errorReport:queue 

/OUT:"...\Debug\CallPascal.exe" /INCREMENTAL /NOLOGO "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" /MANIFEST /ManifestFile:"Debug\CallPascal.exe.intermediate.manifest" /ALLOWISOLATION /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"...\Debug\CallPascal.pdb" /SUBSYSTEM:CONSOLE /PGD:"...y\Debug\CallPascal.pgd" /TLBID:1 /DYNAMICBASE /NXCOMPAT /MACHINE:X86 /ERRORREPORT:QUEUE

Any suggestions very gratefully received. Thank you.

—— edit —–

I added the struct

struct Bodge {
  void* code;
  void* instance;
};

Bodge bodge;

bodge.code = OnACLNeeded;
bodge.instance = (void*)0x99; // just to test

My callback becomes

Integer __stdcall OnACLNeeded(void* instance, Byte& keySettings, Byte& numOfKeys);

And my function call to register the callback becomes

typedef Integer (__stdcall *FnRegisterCallback)(
    HANDLE,
    Bodge,
    DWORD);

and is called like this

ret = (*pfnRegisterCallback)(
    h, 
    bodge, 
    (DWORD)1);

This call produces an error

The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.

which may also indicate a corrupt stack, I think.
BUT if I ignore the error and continue, I get into the callback function body, and BOTH parameters are now valid!
So success of a kind, but also, the void* instance param has a value of zero, not the 0x99 that I set.
I feel we are getting there though!

—– edit —–

This is the function call to register the callback, from the original Pascal calling code.

  * @param hKeyProvider the key provider handle for Desfire card created previously with LASSeOKeyProvider_CreateHandle
  * @param OnACLNeeded supplies a callback to be called for quering host application for the PICC master key settings
  * @param UserData unsigned integer values specifiing any custom provided data to be returned when the callback is called
  * @return 0 - on success; <>0 - denotes error code

  RegisterCallback(hKeyProv,
                  @TSNAPICongigF.OnACLNeeded,
                  (Self));

Note the “self” reference. What would be the C++ equivalent? (I’m not using classes)

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-31T13:30:07+00:00Added an answer on May 31, 2026 at 1:30 pm

    The problem is that the Delphi version of the callback is an instance method. Your C++ callback it not. This is a significant mismatch. This Delphi interface is badly designed and not callable from C++ without some trickery.

    A Delphi instance method is passed as two pointers, one to the code and one to the instance. You can fake this in C++ by declaring the RegisterCallback function like this:

    typedef int (__stdcall *FnRegisterCallback)(
        HANDLE hKeyProvider,
        void* code,
        void* instance,
        DWORD
    );
    

    Then, once you have loaded it with GetProcAddress, call it like this:

    int ret = (*pfnRegisterCallback)(h, OnACLNeeded, NULL, (DWORD)1);
    

    It doesn’t matter what the instance parameter is since we are going to ignore that when it is passed on to OnACLNeeded.

    The final step is to arrange that your function behaves like a Delphi instance method. Do that by adding an extra parameter to represent the instance.

    int __stdcall OnACLNeeded(void* instance, byte& keySettings, byte& numOfKeys)
    {
        keySettings = 0x0F;
        numOfKeys = 1;
        return 1;
    }
    

    You will receive in the instance parameter, whatever you passed as the instance parameter when you called RegisterCallback.

    With these changes you should be able to fake out the Delphi DLL into believing that your code is a Delphi instance method!

    For reference I suggest your read the Program Control topic of the Delphi Language Guide.

    Finally, good luck!


    Update

    The latest edit to the question sheds some new light on what is happening. Specifically this code:

    RegisterCallback(
        hKeyProv,
        @TSNAPICongigF.OnACLNeeded,
        DWORD(Self)
    );
    

    The @TSNAPICongigF.OnACLNeeded parameter results in just the code part of the method. That is it is just a single pointer. The instance is passed in the following parameter with DWORD(Self). The assumption that the author of this code has made is that the callback function will be passed three parameters, the user data followed by the two by var bytes. The trick is that such a function is equivalent to a method call because a method call is implemented behind the scenes by passing the instance as a hidden, implicit, parameter before the actual parameters.

    So, I believe you can solve the problem quite easily. Simply roll all the way back to where your code was when you asked the question. Then change your callback function to accept this extra parameter:

    int __stdcall OnACLNeeded(DWORD UserData, byte& keySettings, byte& numOfKeys)
    {
        keySettings = 0x0F;
        numOfKeys = 1;
        return 1;
    }
    

    I am now confident that this will work.

    You call the register function like this:

    int ret = (*pfnRegisteraCllback)(h, OnACLNeeded, (DWORD)1);
    

    and your callback function should see the value of 1 in the UserData parameter.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I Have a 3rd Party component ArchestrA.MxAccess.dll (which is build on x86 by corgflags)
I have a 3rd party C++ DLL that I call from C#. The methods
I have a 3rd party application from which I need to copy texts and
We have a 3rd party web application which works on in IE6, but not
I have 3rd party libraries for my mac applications which used to link nicely
I have a 3rd party .dll that I have successfully added as a reference
I have 3rd party library function which only takes Reader as parameter. And I
I have 3rd party user control (a captcha control), which has a captcha image,
I have a 3rd party DLL that needs to be loaded dynamically using LoadLibrary()
I have an 3rd Party API I'm wanting to use from my Silverlight 4

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.