I wrote a little PCSC wrapper to access smartcards. Only the basic functions of the winscard.dll are implemented. I did use the Interface command that is new in PureBasic 3.81. The source code is listed below
Code: Select all
;*******************************************************
;
; PureBasic : PCSC Wrapper
; Author : Leo Mijnders
; Date : 29 March 2004
; Doc : http://msdn.microsoft.com/library/en-us/security/security/authentication_functions.asp?frame=true#smart_card_functions
;
;*******************************************************
#SCARD_SHARE_EXCLUSIVE = 1 ; This application is not willing To share this
; // card with other applications.
#SCARD_SHARE_SHARED = 2 ; This application is willing To share this
; // card with other applications.
#SCARD_SHARE_DIRECT = 3 ; // This application demands direct control of
#SCARD_PROTOCOL_T0 =$0001 ;/* T=0 active protocol. */
#SCARD_PROTOCOL_T1 =$0002 ;/* T=1 active protocol. */
#SCARD_PROTOCOL_RAW =$0004 ;/* Raw active protocol. */
#SCARD_UNKNOWN =$0001 ;/* Unknown state */
#SCARD_ABSENT =$0002 ;/* Card is absent */
#SCARD_PRESENT =$0004 ;/* Card is present */
#SCARD_SWALLOWED =$0008 ;/* Card not powered */
#SCARD_POWERED =$0010 ;/* Card is powered */
#SCARD_NEGOTIABLE =$0020 ;/* Ready For PTS */
#SCARD_SPECIFIC =$0040 ;/* PTS has been set */
#SCARD_LEAVE_CARD =$0000 ;/* Do nothing on close */
#SCARD_RESET_CARD =$0001 ;/* Reset on close */
#SCARD_UNPOWER_CARD =$0002 ;/* Power down on close */
#SCARD_EJECT_CARD =$0003 ;/* Eject on close */
#SCARD_S_SUCCESS =$00000000
#SCARD_E_CANCELLED =$80100002
#SCARD_E_CANT_DISPOSE =$8010000E
#SCARD_E_INSUFFICIENT_BUFFER =$80100008
#SCARD_E_INVALID_ATR =$80100015
#SCARD_E_INVALID_HANDLE =$80100003
#SCARD_E_INVALID_PARAMETER =$80100004
#SCARD_E_INVALID_TARGET =$80100005
#SCARD_E_INVALID_VALUE =$80100011
#SCARD_E_NO_MEMORY =$80100006
#SCARD_F_COMM_ERROR =$80100013
#SCARD_F_INTERNAL_ERROR =$80100001
#SCARD_F_UNKNOWN_ERROR =$80100014
#SCARD_F_WAITED_TOO_LONG =$80100007
#SCARD_E_UNKNOWN_READER =$80100009
#SCARD_E_TIMEOUT =$8010000A
#SCARD_E_SHARING_VIOLATION =$8010000B
#SCARD_E_NO_SMARTCARD =$8010000C
#SCARD_E_UNKNOWN_CARD =$8010000D
#SCARD_E_PROTO_MISMATCH =$8010000F
#SCARD_E_NOT_READY =$80100010
#SCARD_E_SYSTEM_CANCELLED =$80100012
#SCARD_E_NOT_TRANSACTED =$80100016
#SCARD_E_READER_UNAVAILABLE =$80100017
Enumeration
#SCARD_SCOPE_USER ; 0x0000/* Scope in user space */
#SCARD_SCOPE_TERMINAL ; 0x0001/* Scope in terminal */
#SCARD_SCOPE_SYSTEM ; 0x0002/* Scope in system */
EndEnumeration
Global fSCardEstablishContext, fSCardConnect, fSCardStatus, fSCardDisconnect, fSCardTransmit
Global fSCardListReaders
Global g_rgSCardT0Pci, g_rgSCardT1Pci, g_rgSCardRawPci
Procedure.l InitPCSC(Lib.l)
If OpenLibrary(Lib, "winscard.dll")
; Pointers to SCARD_IO_REQUEST structures
g_rgSCardT0Pci=IsFunction(Lib,"g_rgSCardT0Pci")
g_rgSCardT1Pci=IsFunction(Lib,"g_rgSCardT1Pci")
g_rgSCardRawPci=IsFunction(Lib,"g_rgSCardRawPci")
; Pointers to Basic PCSC Functions
fSCardEstablishContext=IsFunction(Lib,"SCardEstablishContext")
fSCardConnect=IsFunction(Lib,"SCardConnectA")
fSCardStatus=IsFunction(Lib,"SCardStatusA")
fSCardDisconnect=IsFunction(Lib,"SCardDisconnect")
fSCardTransmit=IsFunction(Lib,"SCardTransmit")
fSCardListReaders=IsFunction(Lib,"SCardListReadersA")
ProcedureReturn 0
EndIf
ProcedureReturn -1
EndProcedure
Procedure.l sSCardEstablishContext(self.l, a.l, b.l, c.l, d.l)
ProcedureReturn CallFunctionFast(fSCardEstablishContext, a, b, c, d)
EndProcedure
Procedure.l sSCardConnect(self.l, a.l, b.l, c.l, d.l, e.l, f.l)
ProcedureReturn CallFunctionFast(fSCardConnect, a, b, c, d, e, f)
EndProcedure
Procedure.l sSCardStatus(self.l, a.l, b.l, c.l, d.l, e.l, f.l, g.l)
ProcedureReturn CallFunctionFast(fSCardStatus, a, b, c, d, e, f, g)
EndProcedure
Procedure.l sSCardDisconnect(self.l, a.l, b.l)
ProcedureReturn CallFunctionFast(fSCardDisconnect, a, b)
EndProcedure
Procedure.l sSCardTransmit(self.l, a.l, b.l, c.l, d.l, e.l, f.l, g.l)
ProcedureReturn CallFunctionFast(fSCardTransmit, a, b, c, d, e, f, g)
EndProcedure
Procedure.l sSCardListReaders(self.l, a.l, b.l, c.l, d.l)
ProcedureReturn CallFunctionFast(fSCardListReaders, a, b, c, d)
EndProcedure
Interface IF_PCSC
EstablishContext(a.l, b.l, c.l, d.l)
Connect(a.l, b.l, c.l, d.l, e.l, f.l)
Status(a.l, b.l, c.l, d.l, e.l, f.l, g.l)
Disconnect(a.l, b.l)
Transmit(a.l, b.l, c.l, d.l, e.l, f.l, g.l)
ListReaders(a.l, b.l, c.l, d.l)
EndInterface
Structure strucInterface
a.l
b.l
c.l
d.l
e.l
f.l
EndStructure
SCard.IF_PCSC
Struc.strucInterface
Struc\a=@sSCardEstablishContext()
Struc\b=@sSCardConnect()
Struc\c=@sSCardStatus()
Struc\d=@sSCardDisconnect()
Struc\e=@sSCardTransmit()
Struc\f=@sSCardListReaders()
AddStruc.l=@Struc
PokeL(@SCard,@AddStruc)
Structure IO_REQ
P.l
A.l
B.b[512]
EndStructure
outPCI_T0.IO_REQ
outPCI_T0\P=1
outPCI_T0\A=512
; *************************** CompilerIf 0 if used as IncludeFile or 1 = if test IncludeFile
CompilerIf 0
Procedure.s HexString(Source.l, L.l)
result.s = ""
For i = 0 To L-1
result = result + Right("00" + Hex(PeekB(Source+i)), 2)
Next i
ProcedureReturn result
EndProcedure
hCTX.l
Buf.s=Space(1000)
ATRL.l
ATR.l=AllocateMemory(2,100)
hCARD.l
AP.l
L.l
S.L
In.l=AllocateMemory(3,100)
Out.l=AllocateMemory(4,100)
OutL.l
; APDU to genarate 8 byte Random at TB100 smartcard
PokeB(In,$BC)
PokeB(In+1,$C4)
PokeB(In+2,$00)
PokeB(In+3,$00)
PokeB(In+4,$08)
If InitPCSC(10)=0
A=SCard\EstablishContext(0,0,0,@hCTX)
MessageRequester("hCTX", Hex(A)+" "+Hex(hCTX),0)
L.l=1000
A=SCard\ListReaders(hCTX,0,@Buf,@L)
MessageRequester("Reader", Hex(A)+" "+Buf,0)
A=SCard\Connect(hCTX,@"TOWITOKO CHIPDRIVE 0",#SCARD_SHARE_SHARED,#SCARD_PROTOCOL_T0 | #SCARD_PROTOCOL_T1,@hCARD,@AP)
MessageRequester("Connect", Hex(A),0)
A=SCard\Status(hCARD,@Buf,@L,@S,@AP,ATR,@ATRL)
MessageRequester("Status", Hex(A)+" "+Hex(S)+" "+Hex(AP)+" "+Hex(ATRL)+" "+Hex(PeekL(ATR)),0)
A=SCard\DisConnect(hCARD,#SCARD_RESET_CARD)
MessageRequester("Disconnect", Hex(A))
A=SCard\Connect(hCTX,@"TOWITOKO CHIPDRIVE 0",#SCARD_SHARE_SHARED,#SCARD_PROTOCOL_T0 | #SCARD_PROTOCOL_T1,@hCARD,@AP)
MessageRequester("Connect", Hex(A),0)
A=SCard\Status(hCARD,@Buf,@L,@S,@AP,ATR,@ATRL)
MessageRequester("Status", Hex(A)+" "+Hex(S)+" "+Hex(AP)+" "+Hex(ATRL)+" "+HexString(ATR,ATRL),0)
For I=1 To 10
OutL=10
A=SCard\Transmit(hCARD, g_rgSCardT0Pci, In, 5, @outPCI_T0, Out, @OutL)
MessageRequester("Transmit", Hex(A)+" "+HexString(Out,OutL)+" "+Hex(OutL),0)
Next
A=SCard\DisConnect(hCARD,#SCARD_RESET_CARD)
MessageRequester("Disconnect", Hex(A))
Else
MessageRequester("Error", "Lib not loaded",0)
EndIf
CompilerEndIf
Greetings
Leo