Tutorial :How to call API with PUCHAR?



Question:

I'm trying to use an API under Delphi. Here's the API documentation

OKERR ENTRY SCardCLMifareStdAuthent       (IN SCARDHANDLE ulHandleCard,IN ULONG ulMifareBlockNr,      IN UCHAR ucMifareAuthMode,IN UCHAR ucMifareAccessType,IN UCHAR ucMifareKeyNr,      IN PUCHAR pucMifareKey,IN ULONG ulMifareKeyLen);  

Whereas pucMifareKey: A pointer to the six byte Mifare key. The code i've been trying so far;

function Auth():Integer;  type    TSCardCLMifareStdAuthent = function(SCARDHANDLE: cardinal; ulMifareBlockNr: ULONG;     ucMifareAuthMode, ucMifareAccessType, ucMifareKeyNr: byte; pucMifareKey: puchar;     ulMifareKeyLen: cardinal):LONG;  var    SCardCLMifareStdAuthent: TSCardCLMifareStdAuthent;    hDLL: Integer;    CardHandle: cardinal;    i: integer;    Key: array of UCHAR;  begin    Result:=1;    //CardHandle is defined here    SetLength(Key, 6);    for i := low(key) to high(key) do      Key[i] := $FF;    hDLL := LoadLibrary('scardsyn.dll');    @SCardCLMifareStdAuthent := GetProcAddress(hDLL, 'SCardCLMifareStdAuthent');    if @SCardCLMifareStdAuthent <> nil then      Result:=SCardCLMifareStdAuthent(CardHandle, $00, 96, 0, 0, ^Key, 6);    FreeLibrary(hDLL);  end;  

The error i'm getting is Incompatible types: 'Byte' and 'Char' at the line of Result:=SCardCL.... due ^Key pointer. Any ideas?


Solution:1

I don't know the DLL in question, but for a Delphi pre 2009 I would do the following:

function Auth: integer;  type    TSCardCLMifareStdAuthent = function(SCARDHANDLE: cardinal;      ulMifareBlockNr: ULONG; ucMifareAuthMode, ucMifareAccessType,      ucMifareKeyNr: byte; pucMifareKey: PAnsiChar;      ulMifareKeyLen: Cardinal): longint;  var    SCardCLMifareStdAuthent: TSCardCLMifareStdAuthent;    hDLL: Integer;    CardHandle: Cardinal;    Key: string;  begin    Result := 1;    //CardHandle is defined here...    Key := StringOfChar(Chr($FF), 6);    hDLL := LoadLibrary('scardsyn.dll');    if hDLL <> 0 then begin      @SCardCLMifareStdAuthent := GetProcAddress(hDLL, 'SCardCLMifareStdAuthent');      if @SCardCLMifareStdAuthent <> nil then begin        Result := SCardCLMifareStdAuthent(CardHandle, $00, 96, 0, 0,          PChar(Key), Length(Key));      end;      FreeLibrary(hDLL);    end;  end;  

The access violation you get probably comes from the C string not being 0-terminated. Using a string and casting it to PChar will make things easier.


Solution:2

type    TSCardCLMifareStdAuthent = function(SCARDHANDLE: cardinal; ulMifareBlockNr: ULONG;      ucMifareAuthMode, ucMifareAccessType, ucMifareKeyNr: byte; pucMifareKey: puchar;      ulMifareKeyLen: cardinal):LONG;  

I think you should replace 'byte' with 'UCHAR':

ucMifareAuthMode, ucMifareAccessType, ucMifareKeyNr: byte;  

It is a bad practice to treat 'byte' as a 'char'.


Solution:3

You wouldn't happen to be in Delphi 2009? If so, "char" is defined as 2 bytes. Try "AnsiChar" instead.


Solution:4

You stated that the key is a 6 byte (uchar) array. You are declaring a dynamic array to pass along, why not just declare an array?

var    {...}    MyKey: array[0..5] of UCHAR;  begin    {...}    Result:=SCardCLMifareStdAuthent(CardHandle, $00, 96, 0, 0, @MyKey, 6);  


Solution:5

Try this:

  1. Introduce new type for array of UCHAR.
  2. Introduce new local variable of pointer type.
  3. Set this variable to be pointer to your Key array
  4. Use this pointer in function call

    type     TArrayOfUchar = array of UCHAR;    var     ...    Key  : TArrayOfUchar;    PKey : ^TArrayOfUchar;   begin    ...    PKey = @Key;    if @SCardCLMifareStdAuthent <> nil then      Result:=SCardCLMifareStdAuthent(CardHandle, $00, 96, 0, 0, PKey, 6);  

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »