I'm trying to use the SCardGetCardTypeProviderName using interop in C#. One of the parameters is a reference, that is supposed to return the name of the provider for a smart card according to the card context that is passed in. This is the code I'm using:
IntPtr hSC = { value comes from call using SCardEstablishContext }
string cardName = { value comes from SCardUIDlgSelectCard }
int providerNameLength = 256;
string providerName = string.Empty; //doesn't matter how I initialize this
[DllImport("winscard.dll", CharSet = CharSet.Ansi, SetLastError = true)]
public static extern Int32 SCardGetCardTypeProviderName(IntPtr hContext, string szCardName, uint dwProviderId, ref string szProvider, ref int pcchProvider);
int lReturn = SCardGetCardTypeProviderName(hSC, cardName, SCARD_PROVIDER_CSP, ref providerName, ref providerNameLength);
But the providerName always comes back empty, while the providerNameLength changes to 43, which makes me think it's a marshalling problem. But I've tried marshalling providerName as:
In the case of the latter two, instead of an empty string, I get a string of strange characters, again, making me think it's a marshalling/translation issue.
Declare the string parameter as StringBuilder:
[DllImport("winscard.dll"]
public static extern int SCardGetCardTypeProviderName(
IntPtr hContext,
string szCardName,
uint dwProviderId,
StringBuilder szProvider,
ref int pcchProvider
);
....
StringBuilder providerName = new StringBuilder(providerNameLength);
int lReturn = SCardGetCardTypeProviderName(
hSC,
cardName,
SCARD_PROVIDER_CSP,
providerName,
ref providerNameLength
);
No need to repeat the default value of CharSet, and these API functions don't use the Win32 last error mechanism.