I have a third-party Delphi DLL that I call from C ++. Unfortunately, I do not have access to the Pascal DLL file, and I am not a Pascal programmer.
There is no lib file, so I use GetProcAddress to call many DLL functions that successfully pass parameters by value, address and link. I also register a callback function that is 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, a 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 for callback function
int __stdcall OnACLNeeded(byte& keySettings, byte& numOfKeys) { keySettings = 0x0F; numOfKeys = 1; return 1; }
This is my C ++ call 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 starting in the debugger, I reach the breakpoint in the first line of the callback function keySettings = 0x0F;
I believe numOfKeys valid, but keySettings has the address 0x00000001 and cannot be assigned.
The application will crash with AccessViolation if I continue.
int __stdcall OnACLNeeded(byte& keySettings, byte& numOfKeys) { keySettings = 0x0F;
I tried declaring as __cdecl without effect.
I tried declaring the byte parameters as byte *, and I get the same invalid parameter.
I am using Visual Studio 2010, running on a 64-bit version of Win7, but compiling as Win32.
These are my compilation commands and links.
/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 are greatly appreciated. Thanks.
------ edit -----
I added structure
struct Bodge { void* code; void* instance; }; Bodge bodge; bodge.code = OnACLNeeded; bodge.instance = (void*)0x99;
My callback is getting
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 so called
ret = (*pfnRegisterCallback)( h, bodge, (DWORD)1);
This call causes an error.
The ESP value was not properly stored in the function call. This is usually the result of calling a function declared with one call, with a function pointer declared with another calling convention.
which may also indicate a damaged stack. BUT, if I ignore the error and continue, I fall into the body of the callback function, and now the BOTH parameters apply!
Thus, success of this kind, but also, the void* instance parameter has a value of 0, not 0x99, which I set.
I feel like we are getting there!
----- edit -----
This is a function call to register a callback from the source code of a Pascal call.
* @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));
Pay attention to the link "self". What is the C ++ equivalent? (I do not use classes)