Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

DLL call from PAL causes GPF

Status
Not open for further replies.

jartman

Programmer
Oct 16, 2001
34
US
I'm trying to call a DLL routine which calculates the MD5 message digest on a file. To test the DLL I put two fields and a button on a form. In one field you type a filename. When you press the button, the DLL routine gets called, passes the filename, and also passes a string by reference to get back the digest (16 bytes). PAL copies the digest into the other field so you can look at it.

The problem I'm having is that any filenames longer than 4 characters cause a GPF. Also the digest gets truncated to 6 bytes.

I used Microsoft Virtual C++ .NET Framework SDK to create the DLL - it's compiled as a regular non-MFC DLL.

Also, while we're at it, the PAL help file says referenced DLLs are searched for first in the "current directory". What's the current directory when running the application? Apparently it's neither where the app's forms nor exe file is. For the moment I'm copying the DLL into the windows system directory.

Here's the code:
method pushButton(var eventInfo Event)
var
result_code LongInt
dig,fn String
endVar
fn = filename ;filename is a field on the form
result_code = file_md5(fn,dig)

if result_code <> 0 then
msgInfo("Error","Result from dll call to file_md5 is: "+ string(result_code))
endIf
digest = dig ;digest is a field on the form
endMethod

Here's the uses block:
Uses md5jra
file_md5(filename CPTR, digest CPTR) CLONG
endUses

and here's the DLL code:
__declspec(dllexport)int file_md5(char *fnm,char *retdig)
{
md5_state_t state;
md5_byte_t digest[16];
FILE *infile;
unsigned int n;
char data[64];

if ((infile = fopen(fnm,"rb")) == NULL)
return -1;
md5_init(&state);
while (!feof(infile)){
n = fread(data,1,64,infile);
md5_append(&state,data,n);
}
md5_finish(&state,digest);
for (n=0;n<16;n++)
retdig[n] = digest[n];
fclose(infile);
return 0;
}
 
First, the current directory is the Working Directory or :WORK: in ObjectPAL. You can set it in the command line or by code.

As I read this the dig string doesn't need to get passed, as it should actually be a place holder for a return value on the ObjectPAL side. Since you only return one value (a switch) and assign it to variable result_code, the dig variable remains unassigned as far as I can tell.

I would change the return value and type of the dll to be a string assigned directly to the dig variable. Send back something inocuous on a fail (like a hyphen) and test on the ObjectPAL side.

i.e. in quasi-code on the ObjectPAL side

Code:
dig = myDLL(fileName)

if dig <> "-"
   then digest.value = dig
     else msgInfo("Error", "MyDLL failed to hash the file")
endif

etc...

Of course, I might be misreading your intent, but that's what I got out of it.

Hope this helps,

Mac


Mac :)

&quot;There are only 10 kinds of people in this world... those who understand binary and those who don't&quot;

langley_mckelvy@cd4.co.harris.tx.us
 
I tried moving the result string to be the return value of the DLL routine, but I still have the same problems. In fact, I can't even get the integer return code back with the code written as above.

Does anyone have any example source for a DLL written in C? I think it's just a matter of having the right directives and compiler settings - here's why:

I've compiled the DLL in both Visual Studio .NET and in Borland C++ 5.5 (in all cases the DLL code is in C, not C++). I've also written a test console app, and both versions of the DLL work with it. But Paradox behaves differently depending on which DLL I use.

For the MS-compiled DLL called from my Paradox form, I get the problems described above. For the Borland-compiled DLL, Paradox won't even open the form (as if the uses block was wrong). How does Paradox check the DLL before opening the form?? I'm surprised to see that it can detect a bad parameter type in the uses block, because there's no such information in the DLL file...

One additional bit of info - I added code in the DLL routine which proves that the parameters and the return value are intact and correct right up to the return statement - so the problem must either be with Paradox's handling of the variables after the call or with Windows stack checking on return. Any more ideas?

- John
 
OK, I solved it. I thought I had exhausted all the permutations of calling convention and name decoration, but I guess not. The calling convention needs to be stdcall (so the called function cleans up the stack) but the files need to go out with no name decoration. A module definition file was required for both MS and Borland to get the exported name right.

The problem with the two DLLs behaving differently went away when I added the -tWD compiler option on bcc32's command line. Previously I had been compiling to object files (no link) and then linking explicitly with the -Tpd option. Not sure why that didn't work, but I guess I'll leave that little mystery for another rainy day.

- John
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top