Re: How do I stop a TSP written in Delphi crashing on Add Provider?



Hi Grant,

Thanks for pointing out my little mistake. However, it is not this part that
causes the problem (I think) as mod is correctly populated and displayed.

I get a reference to the function back and by adding debug, it can be seen
that it fails on the line that actually calls the function, i.e. theResult =
myFunction(tspName);

Best Regards

Paul

"Grant Schenck" <schenckg@xxxxxxxxxxxxx> wrote in message
news:elBgF70TFHA.3188@xxxxxxxxxxxxxxxxxxxxxxx
> In your "C" sample:
>
> char mod[MAXMODULE];
> ...
> GetModuleFileName((HMODULE)hLib, (LPTSTR)mod, MAXMODULE);
>
> You cast mod to a pointer to TCHAR but you declare it a char.
> --
> Grant Schenck
> http://grantschenck.tripod.com
>
>
>
> "Paul Soper" <paul_soper@xxxxxxxxxxx> wrote in message
> news:#XdtTgyTFHA.1600@xxxxxxxxxxxxxxxxxxxxxxx
>> 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
>>
>>
>>
>
>


.