Re: How do I stop a TSP written in Delphi crashing on Add Provider?
- From: "Paul Soper" <paul_soper@xxxxxxxxxxx>
- Date: Mon, 2 May 2005 16:03:52 -0000
Hi everyone,
I know this is not a general programming discussion about accessing DLLs,
but I want to disclose
my findings because this is TAPI related. I need help to check that I'm not
missing something stupid in my C code at the bottom of this post.
If I use the Delphi code:
-------------
function TSPI_providerUIIdentify(var lpszUIDLLName : LPWSTR): Longint;
stdcall; external 'PSTSP.DLL';
procedure TForm1.Button1Click(Sender: TObject);
var buffer : LPWSTR;
begin
GetMem(buffer, MAX_PATH);
TSPI_providerUIIdentify(buffer);
ShowMessage(' >' + WideCharToString(buffer) + '<');
FreeMem(buffer);
end;
--------------
Or, if I use the Visual Basic code:
--------------
Private Declare Function TSPI_providerUIIdentify Lib "PSTSP.DLL" (ByRef
myString As Long) As Long
Private Sub Command1_Click()
Dim buffer As String
Dim answer As Long
Dim count As Integer
'Allocate 300 chars in to the String
For count = 0 To 299
buffer = buffer & "a"
Next count
answer = TSPI_providerUIIdentify(StrPtr(buffer))
MsgBox buffer
End Sub
--------------
all works fine in both cases and I get the correct name back in "buffer".
But, if I use the C code (in a console application to keep it simple -
Visual C creates masses of code that would complicate the example):
--------------
#include "stdafx.h"
#include <windows.h>
#include <iostream.h>
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <malloc.h>
#define MAXMODULE 300
typedef LONG (WINAPI *cfunc)(LPWSTR lpzUIDLLName);
cfunc myFunction;
char mod[MAXMODULE];
LPWSTR tspName;
long theResult;
/* very quick and dirty */
int main(int argc, char* argv[])
{
HINSTANCE hLib = LoadLibrary("PSTSP.DLL");
if(hLib == NULL) {
cout << "Unable to load library!" << endl;
getch();
return 1;
}
GetModuleFileName((HMODULE)hLib, (LPTSTR)mod, MAXMODULE);
cout << "Library loaded: " << mod << endl;
myFunction = (cfunc) GetProcAddress((HMODULE)hLib,
"TSPI_providerUIIdentify");
if(myFunction == NULL) {
cout << "Unable to get access to the function!" << endl;
FreeLibrary((HMODULE)hLib);
getch();
return 1;
}
//malloc 2 bytes per char and 2 for the null
tspName = (LPWSTR) malloc((MAX_PATH * 2) + 2);
if(tspName == NULL) {
cout << "Unable to allocate memory!" << endl;
FreeLibrary((HMODULE)hLib);
getch();
return 1;
}
else {
cout << "Press enter to call the function..." << endl;
getch();
theResult = myFunction(tspName);
cout << tspName << endl;
free(tspName);
}
FreeLibrary((HMODULE)hLib);
cout << "Finished... Press enter to close the window." << endl;
getch();
return 0;
}
--------------
It crashes in a similar way to TAPI when calling this function. Am I missing
something? (i.e. is my C code OK?). When running this I get the program "has
encountered a problem and needs to close". The error signature is ModName:
kernel32.dll ModVer: 5.1.2600.2180 Offset: 0000 9e4f.
I can successfully use the code above to access a functions in the Delphi
DLL that print a message to the console, return a long, add two numbers and
return a result etc. The problem comes when I try and pass a pointer - for
example a char*, if I declare my Delphi function signature like this
function paultest(instring: PChar) : Longint; stdcall;
I can read the value of instring and use it, obviously if I modify it, this
only modified the local copy (for non Delphi guys, declaring it like the
above is pass by value). If I declare it like this
function paultest(var instring: PChar) : Longint; stdcall;
I cannot read it or write to it without experiencing a C Program crash (var
indicates pass by reference - basically give me a pointer). I have tried
direct assignment and StrCopy etc to write, and reading is simply a case of
trying to writeln it out.
Trying the var/no var scenario with an integer yields the following results:
1. c: declare and pass an int, delphi: declare var parameter => crash
2. c: declare and pass an int, delphi: don't declare var => can read the
int, but writing affects only the local copy
3. c: declare int and declare int* in external function signature, pass &int
delphi: declare var parameter => read and write (i.e. modify OK)
4. c: declare int and declare int* in external function signature, pass &int
delphi: don't declare var => delphi gets the int representation of the
pointer (i.e. the address, modification only affects local variable).
This is what I would have thought of as "correct behaviour" anyway.
All of this indicates to me that there is some problem when trying to access
any "string" based pointers from Delphi. I think I know need to approach
another relevent forum to get the answers I need, as this is no longer in
the realm of TAPI.
A note to Bram: your function in your code is decalred function
TSPI_providerUIIdentify(lpszUIDLLName : LPWSTR) : LONG;
stdcall; I don;t understand how this can actually be modifying the
lpszUIDLLName. Can you confirm that this actually sets the value external to
DLL please?
Thanks for everyone's help so far. I will report back if I solve this
problem.
Kind Regards
Paul
.
- Follow-Ups:
- Re: How do I stop a TSP written in Delphi crashing on Add Provider?
- From: Grant Schenck
- Re: How do I stop a TSP written in Delphi crashing on Add Provider?
- References:
- Re: How do I stop a TSP written in Delphi crashing on Add Provider?
- From: Paul Soper
- Re: How do I stop a TSP written in Delphi crashing on Add Provider?
- Prev by Date: Re: Dissable from picking up?
- Next by Date: Re: LINE_NEWCALL during TSPI_lineOpen or TSPI_lineSetDefaultMediaDetection
- Previous by thread: Re: How do I stop a TSP written in Delphi crashing on Add Provider?
- Next by thread: Re: How do I stop a TSP written in Delphi crashing on Add Provider?
- Index(es):