Reputation: 1298
I have an application that calls to a Win32 Dll written in Delphi. My application is developed in C# and running under IIS. I can successfully call the Delphi Dll on every Windows release from Server 2003 upwards with the exception of Windows Server 2012. The call to the external method doesn't return any errors nor is there anything in the error log. It just never returns any data.
In my C# I declare:
[DllImport("MyTest.dll", CharSet = CharSet.Unicode,
CallingConvention = CallingConvention.StdCall)]
public static extern void Encrypt(string szPlainText, StringBuilder szCipherText);
I then call the function with the following:
StringBuilder encText = new StringBuilder(128);
StringBuilder plainString = new StringBuilder("test");
Encrypt(plainString.ToString(), encText);
Has something changed in WinServer 2012 that would stop this from working?
The Delphi Code that I have access to looks like:
procedure Encrypt(szPlainText: PChar; szCipherText : PChar) ; stdcall ; export;
var
sTemp : String ;
sPlainText : String ;
cipher : TCipher ;
begin
cipher := TLogixCipher.Create ;
sPlainText := szPlainText ;
sTemp := cipher.Encrypt(sPlainText ) ;
StrPCopy(szCipherText,sTemp);
FreeAndNil(cipher) ;
end;
Upvotes: 0
Views: 695
Reputation: 613461
Note: This answer was written to match the original version of the question. Since it was written the question was changed to incorporate the changes suggested below.
The p/invoke declaration is probably wrong for a start. The first parameter is an input parameter (I presume) and so should be declared as string. I'd declare the p/invoke like this:
public static extern void Encrypt(
string szPlainText,
StringBuilder szCipherText
);
This won't really matter, but there's little point in marshalling the plain text back to the managed code when the function returns since the plain text won't have changed.
The second issue is that you need to allocate the buffer in the szCipherText
parameter before calling.
So, suppose that you knew that the buffer needed to be of length 100, you would write it like this:
StringBuilder CipherText = new StringBuilder(100);
Encrypt(PlainText, CipherText);
Perhaps the mechanism for this function is that the cipher text is the same length and the plain text. In which case your call would be:
StringBuilder CipherText = new StringBuilder(PlainText.Length);
Encrypt(PlainText, CipherText);
You note that the function you call does not return any errors. That's not very surprising since there is no mechanism for it to do so.
Why has your code started mis-behaving now? You've switch operating system and that appears to have induced a change. But all that means is that your code has always been wrong, and that you just got away with it before now. And the new version of the OS that you are using happens to behave differently with your incorrect code.
After your various updates, the code in the question is now correct. Which leads me to suspect that the Delphi code is indeed returning the empty string. In which case the logical conclusion is that cipher.Encrypt
returns the empty string. Try replacing the Delphi code with this function to test the interface:
procedure Encrypt(szPlainText: PChar; szCipherText: PChar); stdcall;
begin
StrPCopy(szCipherText, szPlainText);
end;
Upvotes: 2