Attribute VB_Name = "winscard"
Option Explicit

Public Const DEFAULT_BUFFER_SIZE As Integer = 255

Public Type ByteArray
 b(0 To DEFAULT_BUFFER_SIZE) As Byte
End Type

Public Type SCARD_READERSTATE
 szReader As String 'reader name
 pvUserData As Long 'user defined data
 dwCurrentState As Long 'current state of reader at time of call
 dwEventState As Long 'state of reader after state change
 cbAtr As Long 'Number of bytes in the returned ATR
 rgbAtr(0 To 35) As Byte 'Atr of inserted card, (extra alignment bytes)
End Type

Public Type SCARD_ATRMASK
 cbAtr As Long
 rgbAtr(0 To 35) As Byte
 rgbMask(0 To 35) As Byte
End Type

Public Type VERSION_CONTROL
 SmclibVersion As Long
 DriverMajor As Byte
 DriverMinor As Byte
 FirmwareMajor As Byte
 FirmwareMinor As Byte
 UpdateKey As Byte
End Type

Public Type GUID
 Data1 As Long
 Data2 As Integer
 Data3 As Integer
 Data4(0 To 7) As Byte
End Type

Public Type SCARD_IO_REQUEST
 dwProtocol As Long 'Protocol identifier
 dbPciLength As Long 'Protocol Control Information Length
End Type

'T=0 command
Public Type SCARD_T0_Command
 bCla As Byte 'the instruction class
 bIns As Byte 'the instruction code within the instruction class
 bP1 As Byte 'first parameter of the function
 bP2 As Byte 'second parameter of the function
 bP3 As Byte 'size of the I/O transfer
End Type

'T=0 request
Public Type SCARD_T0_REQUEST
 ioRequest As SCARD_IO_REQUEST 'I/O request control
 bSw1 As Byte 'first return code from the instruction
 bSw2 As Byte 'second return code from the instruction
 CmdBytes As SCARD_T0_Command 'I/O command
End Type

'T=1 request
Public Type SCARD_T1_REQUEST
 ioRequest As SCARD_IO_REQUEST 'I/O request control
End Type

'my custom type
'id = Attribute identifier (i.e. SCARD_ATTR_MAX_CLK)
'name = Attribute friendly name (i.e. "Maximum clock rate")
Public Type SCARD_ATTRIBUTE
 id As Long
 name As String
 display_mode As Byte
End Type

Public Const SHOW_ACTUAL_BYTES As Byte = 0
Public Const SHOW_AS_LONG As Byte = 1
Public Const SHOW_AS_CHANNEL_ID As Byte = 2
Public Const SHOW_AS_HEX As Byte = 3
Public Const SHOW_AS_IFD_VERSION As Byte = 4
Public Const SHOW_AS_CHARS As Byte = 5
Public Const SHOW_AS_ERROR_ENCODING As Byte = 6
Public Const SHOW_AS_MECH As Byte = 7
Public Const SHOW_AS_DWORD As Byte = 8
Public Const SHOW_AS_YES_NO As Byte = 9
Public Const SHOW_AS_CARD_PRESENCE As Byte = 10
Public Const SHOW_AS_CARD_TYPE As Byte = 11
Public Const SHOW_AS_PROTOCOL_TYPES As Byte = 12
Public Const SHOW_AS_CURRENT_PROTOCOL As Byte = 13

'**************************************************************************
' Context Scope
'**************************************************************************
Public Const SCARD_SCOPE_USER As Long = 0 'The context is a user context, and any database operations are performed within the domain of the user.
Public Const SCARD_SCOPE_TERMINAL As Long = 1 'The context is that of the current terminal,and any database operations are performed within the domain of that terminal. (The calling application must have appropriate access permissions for any database actions.)
Public Const SCARD_SCOPE_SYSTEM As Long = 2 'The context is the system context, and any database operations are performed within the domain of the system.  (The calling application must have appropriate access permissions for any database actions.)
Public Const SCARD_AUTOALLOCATE As Long = -1 'Flag to have Resource Manager allocate buffer space

'**************************************************************************
' Provider IDs
'**************************************************************************
Public Const SCARD_PROVIDER_PRIMARY As Long = 1 'Primary Provider Id
Public Const SCARD_PROVIDER_CSP As Long = 2 'Crypto Service Provider Id

'**************************************************************************
' Share Modes
'**************************************************************************
Public Const SCARD_SHARE_EXCLUSIVE As Long = 1 'This application is not willing to share this card with other applications.
Public Const SCARD_SHARE_SHARED As Long = 2 'This application is willing to share this card with other applications.
Public Const SCARD_SHARE_DIRECT As Long = 3 'This application demands direct control of the reader, so it is not available to other applications.

'**************************************************************************
' Protocols
'**************************************************************************
Public Const SCARD_PROTOCOL_UNDEFINED As Long = 0 'There is no active protocol
Public Const SCARD_PROTOCOL_T0 As Long = 1 'T=0 is the active protocol
Public Const SCARD_PROTOCOL_T1 As Long = 2 'T=1 is the active protocol
Public Const SCARD_PROTOCOL_RAW As Long = &H10000 'Raw is the active protocol.
Public Const SCARD_PROTOCOL_Tx As Long = SCARD_PROTOCOL_T0 Or SCARD_PROTOCOL_T1 'This is the mask of ISO defined transmission protocols
Public Const SCARD_PROTOCOL_DEFAULT As Long = &H80000000 'Use the default transmission parameters / card clock freq.
Public Const SCARD_PROTOCOL_OPTIMAL As Long = &H0 'Use optimal transmission parameters / card clock freq.

'**************************************************************************
' Disposition and Initialization Values
'**************************************************************************
'SCardDisconnect() and SCardReconnect()
Public Const SCARD_LEAVE_CARD As Long = 0 'Don't do anything special
Public Const SCARD_RESET_CARD As Long = 1 'Reset the card (Warm Reset).
Public Const SCARD_UNPOWER_CARD As Long = 2 'Power down the card and reset it (Cold Reset).

'SCardDisconnect()
Public Const SCARD_EJECT_CARD As Long = 3 'Eject the card

'**************************************************************************
' IOCTLs
'**************************************************************************
Public Const FILE_DEVICE_SMARTCARD As Long = &H31 'Smartcard IOCTL class

'Smart Card Driver IOCTLs
'http://msdn.microsoft.com/en-us/library/ms801366.aspx
Public Const IOCTL_SMARTCARD_POWER As Long = FILE_DEVICE_SMARTCARD + &H4
Public Const IOCTL_SMARTCARD_GET_ATTRIBUTE As Long = FILE_DEVICE_SMARTCARD + &H8
Public Const IOCTL_SMARTCARD_SET_ATTRIBUTE As Long = FILE_DEVICE_SMARTCARD + &HC
Public Const IOCTL_SMARTCARD_CONFISCATE As Long = FILE_DEVICE_SMARTCARD + &H10
Public Const IOCTL_SMARTCARD_TRANSMIT As Long = FILE_DEVICE_SMARTCARD + &H14
Public Const IOCTL_SMARTCARD_EJECT As Long = FILE_DEVICE_SMARTCARD + &H18
Public Const IOCTL_SMARTCARD_SWALLOW As Long = FILE_DEVICE_SMARTCARD + &H1C
Public Const IOCTL_SMARTCARD_IS_PRESENT As Long = FILE_DEVICE_SMARTCARD + &H28
Public Const IOCTL_SMARTCARD_IS_ABSENT As Long = FILE_DEVICE_SMARTCARD + &H2C
Public Const IOCTL_SMARTCARD_SET_PROTOCOL As Long = FILE_DEVICE_SMARTCARD + &H30
Public Const IOCTL_SMARTCARD_GET_STATE As Long = FILE_DEVICE_SMARTCARD + &H38
Public Const IOCTL_SMARTCARD_GET_LAST_ERROR As Long = FILE_DEVICE_SMARTCARD + &H3C

'SCM IOCTLs
Public Const FILE_ANY_ACCESS As Long = &H0
Public Const FILE_READ_ACCESS As Long = &H1
Public Const FILE_WRITE_ACCESS As Long = &H2

Public Const METHOD_BUFFERED As Long = 0
Public Const METHOD_IN_DIRECT As Long = 1
Public Const METHOD_OUT_DIRECT As Long = 2
Public Const METHOD_NEITHER As Long = 3

Public Const IOCTL_PSCR_COMMAND As Long = (((FILE_DEVICE_SMARTCARD) * (2 ^ 16)) Or ((FILE_ANY_ACCESS) * (2 ^ 14)) Or ((&H800) * (2 ^ 2)) Or (METHOD_BUFFERED))
Public Const IOCTL_GET_VERSIONS As Long = (((FILE_DEVICE_SMARTCARD) * (2 ^ 16)) Or ((FILE_ANY_ACCESS) * (2 ^ 14)) Or ((&H801) * (2 ^ 2)) Or (METHOD_BUFFERED))
Public Const IOCTL_SET_TIMEOUT As Long = (((FILE_DEVICE_SMARTCARD) * (2 ^ 16)) Or ((FILE_ANY_ACCESS) * (2 ^ 14)) Or ((&H802) * (2 ^ 2)) Or (METHOD_BUFFERED))
Public Const IOCTL_RESET_INTERFACE As Long = (((FILE_DEVICE_SMARTCARD) * (2 ^ 16)) Or ((FILE_ANY_ACCESS) * (2 ^ 14)) Or ((&H803) * (2 ^ 2)) Or (METHOD_BUFFERED))
Public Const IOCTL_GET_CONFIGURATION As Long = (((FILE_DEVICE_SMARTCARD) * (2 ^ 16)) Or ((FILE_ANY_ACCESS) * (2 ^ 14)) Or ((&H804) * (2 ^ 2)) Or (METHOD_BUFFERED))
Public Const IOCTL_SCM_PINPAD As Long = (((FILE_DEVICE_SMARTCARD) * (2 ^ 16)) Or ((FILE_ANY_ACCESS) * (2 ^ 14)) Or ((&H805) * (2 ^ 2)) Or (METHOD_BUFFERED))
Public Const IOCTL_SCM_SET_P As Long = (((FILE_DEVICE_SMARTCARD) * (2 ^ 16)) Or ((FILE_ANY_ACCESS) * (2 ^ 14)) Or ((&H811) * (2 ^ 2)) Or (METHOD_BUFFERED))
Public Const IOCTL_SCM_GET_P As Long = (((FILE_DEVICE_SMARTCARD) * (2 ^ 16)) Or ((FILE_ANY_ACCESS) * (2 ^ 14)) Or ((&H812) * (2 ^ 2)) Or (METHOD_BUFFERED))
Public Const IOCTL_GET_DEVICE_NAME As Long = (((FILE_DEVICE_SMARTCARD) * (2 ^ 16)) Or ((FILE_ANY_ACCESS) * (2 ^ 14)) Or ((&H820) * (2 ^ 2)) Or (METHOD_BUFFERED))

'**************************************************************************
' Attribute Identifiers
'**************************************************************************
Public Const SCARD_CLASS_VENDOR_INFO As Long = &H10000 'Vendor information definitions - classes
Public Const SCARD_CLASS_COMMUNICATIONS As Long = &H20000 'Communication definitions
Public Const SCARD_CLASS_PROTOCOL As Long = &H30000 'Protocol definitions
Public Const SCARD_CLASS_POWER_MGMT As Long = &H40000 'Power Management definitions
Public Const SCARD_CLASS_SECURITY As Long = &H50000 'Security Assurance definitions
Public Const SCARD_CLASS_MECHANICAL As Long = &H60000 'Mechanical characteristic definitions
Public Const SCARD_CLASS_VENDOR_DEFINED As Long = &H70000 'Vendor specific definitions
Public Const SCARD_CLASS_IFD_PROTOCOL As Long = &H80000 'Interface Device Protocol options
Public Const SCARD_CLASS_ICC_STATE As Long = &H90000 'ICC State specific definitions
Public Const SCARD_CLASS_SYSTEM As Long = &H7FFF0000 'System-specific definitions

'Vendor information definitions - items
Public Const SCARD_ATTR_VENDOR_NAME As Long = SCARD_CLASS_VENDOR_INFO + &H100
Public Const SCARD_ATTR_VENDOR_IFD_TYPE As Long = SCARD_CLASS_VENDOR_INFO + &H101
Public Const SCARD_ATTR_VENDOR_IFD_VERSION As Long = SCARD_CLASS_VENDOR_INFO + &H102
Public Const SCARD_ATTR_VENDOR_IFD_SERIAL_NO As Long = SCARD_CLASS_VENDOR_INFO + &H103
Public Const SCARD_ATTR_CHANNEL_ID As Long = SCARD_CLASS_COMMUNICATIONS + &H110
Public Const SCARD_ATTR_PROTOCOL_TYPES As Long = SCARD_CLASS_PROTOCOL + &H120
Public Const SCARD_ATTR_DEFAULT_CLK As Long = SCARD_CLASS_PROTOCOL + &H121
Public Const SCARD_ATTR_MAX_CLK As Long = SCARD_CLASS_PROTOCOL + &H122
Public Const SCARD_ATTR_DEFAULT_DATA_RATE As Long = SCARD_CLASS_PROTOCOL + &H123
Public Const SCARD_ATTR_MAX_DATA_RATE As Long = SCARD_CLASS_PROTOCOL + &H124
Public Const SCARD_ATTR_MAX_IFSD As Long = SCARD_CLASS_PROTOCOL + &H125
Public Const SCARD_ATTR_POWER_MGMT_SUPPORT As Long = SCARD_CLASS_POWER_MGMT + &H131
Public Const SCARD_ATTR_USER_TO_CARD_AUTH_DEVICE As Long = SCARD_CLASS_SECURITY + &H140
Public Const SCARD_ATTR_USER_AUTH_INPUT_DEVICE As Long = SCARD_CLASS_SECURITY + &H142
Public Const SCARD_ATTR_CHARACTERISTICS As Long = SCARD_CLASS_MECHANICAL + &H150
Public Const SCARD_ATTR_CURRENT_PROTOCOL_TYPE As Long = SCARD_CLASS_IFD_PROTOCOL + &H201
Public Const SCARD_ATTR_CURRENT_CLK As Long = SCARD_CLASS_IFD_PROTOCOL + &H202
Public Const SCARD_ATTR_CURRENT_F As Long = SCARD_CLASS_IFD_PROTOCOL + &H203
Public Const SCARD_ATTR_CURRENT_D As Long = SCARD_CLASS_IFD_PROTOCOL + &H204
Public Const SCARD_ATTR_CURRENT_N As Long = SCARD_CLASS_IFD_PROTOCOL + &H205
Public Const SCARD_ATTR_CURRENT_W As Long = SCARD_CLASS_IFD_PROTOCOL + &H206
Public Const SCARD_ATTR_CURRENT_IFSC As Long = SCARD_CLASS_IFD_PROTOCOL + &H207
Public Const SCARD_ATTR_CURRENT_IFSD As Long = SCARD_CLASS_IFD_PROTOCOL + &H208
Public Const SCARD_ATTR_CURRENT_BWT As Long = SCARD_CLASS_IFD_PROTOCOL + &H209
Public Const SCARD_ATTR_CURRENT_CWT As Long = SCARD_CLASS_IFD_PROTOCOL + &H20A
Public Const SCARD_ATTR_CURRENT_EBC_ENCODING As Long = SCARD_CLASS_IFD_PROTOCOL + &H20B
Public Const SCARD_ATTR_EXTENDED_BWT As Long = SCARD_CLASS_IFD_PROTOCOL + &H20C
Public Const SCARD_ATTR_ICC_PRESENCE As Long = SCARD_CLASS_ICC_STATE + &H300
Public Const SCARD_ATTR_ICC_INTERFACE_STATUS As Long = SCARD_CLASS_ICC_STATE + &H301
Public Const SCARD_ATTR_CURRENT_IO_STATE As Long = SCARD_CLASS_ICC_STATE + &H302
Public Const SCARD_ATTR_ATR_STRING As Long = SCARD_CLASS_ICC_STATE + &H303
Public Const SCARD_ATTR_ICC_TYPE_PER_ATR As Long = SCARD_CLASS_ICC_STATE + &H304
Public Const SCARD_ATTR_ESC_RESET As Long = SCARD_CLASS_VENDOR_DEFINED + &HA000
Public Const SCARD_ATTR_ESC_CANCEL As Long = SCARD_CLASS_VENDOR_DEFINED + &HA003
Public Const SCARD_ATTR_ESC_AUTHREQUEST As Long = SCARD_CLASS_VENDOR_DEFINED + &HA005
Public Const SCARD_ATTR_MAXINPUT As Long = SCARD_CLASS_VENDOR_DEFINED + &HA007
Public Const SCARD_ATTR_DEVICE_UNIT As Long = SCARD_CLASS_SYSTEM + &H1
Public Const SCARD_ATTR_DEVICE_IN_USE As Long = SCARD_CLASS_SYSTEM + &H2
Public Const SCARD_ATTR_DEVICE_FRIENDLY_NAME_A As Long = SCARD_CLASS_SYSTEM + &H3
Public Const SCARD_ATTR_DEVICE_SYSTEM_NAME_A As Long = SCARD_CLASS_SYSTEM + &H4
Public Const SCARD_ATTR_DEVICE_FRIENDLY_NAME_W As Long = SCARD_CLASS_SYSTEM + &H5
Public Const SCARD_ATTR_DEVICE_SYSTEM_NAME_W As Long = SCARD_CLASS_SYSTEM + &H6
Public Const SCARD_ATTR_SUPRESS_T1_IFS_REQUEST As Long = SCARD_CLASS_SYSTEM + &H7

'**************************************************************************
' winscard.h Error Codes
'**************************************************************************
Public Const SCARD_S_SUCCESS As Long = 0 'No error was encountered
Public Const SCARD_F_INTERNAL_ERROR As Long = &H80100001 'An internal consistency check failed.
Public Const SCARD_E_CANCELLED As Long = &H80100002 'The action was canceled by an SCardCancel request.
Public Const SCARD_E_INVALID_HANDLE As Long = &H80100003 'The supplied handle was not valid.
Public Const SCARD_E_INVALID_PARAMETER As Long = &H80100004 'One or more of the supplied parameters could not be properly interpreted.
Public Const SCARD_E_INVALID_TARGET As Long = &H80100005 'Registry startup information is missing or not valid.
Public Const SCARD_E_NO_MEMORY As Long = &H80100006 'Not enough memory available to complete this command.
Public Const SCARD_F_WAITED_TOO_LONG As Long = &H80100007 'An internal consistency timer has expired.
Public Const SCARD_E_INSUFFICIENT_BUFFER As Long = &H80100008 'The data buffer for returned data is too small for the returned data.
Public Const SCARD_E_UNKNOWN_READER As Long = &H80100009 'The specified reader name is not recognized.
Public Const SCARD_E_TIMEOUT As Long = &H8010000A 'The user-specified time-out value has expired.
Public Const SCARD_E_SHARING_VIOLATION As Long = &H8010000B 'The smart card cannot be accessed because of other outstanding connections.
Public Const SCARD_E_NO_SMARTCARD As Long = &H8010000C 'The operation requires a smart card, but no smart card is currently in the device.
Public Const SCARD_E_UNKNOWN_CARD As Long = &H8010000D 'The specified smart card name is not recognized.
Public Const SCARD_E_CANT_DISPOSE As Long = &H8010000E 'The system could not dispose of the media in the requested manner.
Public Const SCARD_E_PROTO_MISMATCH As Long = &H8010000F 'The requested protocols are incompatible with the protocol currently in use with the card.
Public Const SCARD_E_NOT_READY As Long = &H80100010 'The reader or card is not ready to accept commands.
Public Const SCARD_E_INVALID_VALUE As Long = &H80100011 'One or more of the supplied parameter values could not be properly interpreted.
Public Const SCARD_E_SYSTEM_CANCELLED As Long = &H80100012 'The action was canceled by the system, presumably to log off or shut down.
Public Const SCARD_F_COMM_ERROR As Long = &H80100013 'An internal communications error has been detected.
Public Const SCARD_F_UNKNOWN_ERROR As Long = &H80100014 'An internal error has been detected, but the source is unknown.
Public Const SCARD_E_INVALID_ATR As Long = &H80100015 'An ATR string obtained from the registry is not a valid ATR string.
Public Const SCARD_E_NOT_TRANSACTED As Long = &H80100016 'An attempt was made to end a nonexistent transaction.
Public Const SCARD_E_READER_UNAVAILABLE As Long = &H80100017 'The specified reader is not currently available for use.
Public Const SCARD_P_SHUTDOWN As Long = &H80100018 'The operation has been aborted to allow the server application to exit.
Public Const SCARD_E_PCI_TOO_SMALL As Long = &H80100019 'The PCI receive buffer was too small.
Public Const SCARD_E_READER_UNSUPPORTED As Long = &H8010001A 'The reader driver does not meet minimal requirements for support.
Public Const SCARD_E_DUPLICATE_READER As Long = &H8010001B 'The reader driver did not produce a unique reader name.
Public Const SCARD_E_CARD_UNSUPPORTED As Long = &H8010001C 'The smart card does not meet minimal requirements for support.
Public Const SCARD_E_NO_SERVICE As Long = &H8010001D 'The smart card resource manager is not running.
Public Const SCARD_E_SERVICE_STOPPED As Long = &H8010001E 'The smart card resource manager has shut down.
Public Const SCARD_E_UNEXPECTED As Long = &H8010001F 'An unexpected card error has occurred.
Public Const SCARD_E_ICC_INSTALLATION As Long = &H80100020 'No primary provider can be found for the smart card.
Public Const SCARD_E_ICC_CREATEORDER As Long = &H80100021 'The requested order of object creation is not supported.
Public Const SCARD_E_UNSUPPORTED_FEATURE As Long = &H80100022 'This smart card does not support the requested feature.
Public Const SCARD_E_DIR_NOT_FOUND As Long = &H80100023 'The specified directory does not exist in the smart card.
Public Const SCARD_E_FILE_NOT_FOUND As Long = &H80100024 'The specified file does not exist in the smart card.
Public Const SCARD_E_NO_DIR As Long = &H80100025 'The supplied path does not represent a smart card directory.
Public Const SCARD_E_NO_FILE As Long = &H80100026 'The supplied path does not represent a smart card file.
Public Const SCARD_E_NO_ACCESS As Long = &H80100027 'Access is denied to the file.
Public Const SCARD_E_WRITE_TOO_MANY As Long = &H80100028 'An attempt was made to write more data than would fit in the target object.
Public Const SCARD_E_BAD_SEEK As Long = &H80100029 'An error occurred in setting the smart card file object pointer.
Public Const SCARD_E_INVALID_CHV As Long = &H8010002A 'The supplied PIN is incorrect.
Public Const SCARD_E_UNKNOWN_RES_MNG As Long = &H8010002B 'An unrecognized error code was returned from a layered component.
Public Const SCARD_E_NO_SUCH_CERTIFICATE As Long = &H8010002C 'The requested certificate does not exist.
Public Const SCARD_E_CERTIFICATE_UNAVAILABLE As Long = &H8010002D 'The requested certificate could not be obtained.
Public Const SCARD_E_NO_READERS_AVAILABLE As Long = &H8010002E 'No smart card reader is available.
Public Const SCARD_E_COMM_DATA_LOST As Long = &H8010002F 'A communications error with the smart card has been detected.
Public Const SCARD_E_NO_KEY_CONTAINER As Long = &H80100030
Public Const SCARD_W_UNSUPPORTED_CARD As Long = &H80100065 'The reader cannot communicate with the card, due to ATR string configuration conflicts.
Public Const SCARD_W_UNRESPONSIVE_CARD As Long = &H80100066 'The smart card is not responding to a reset.
Public Const SCARD_W_UNPOWERED_CARD As Long = &H80100067 'Power has been removed from the smart card, so that further communication is not possible.
Public Const SCARD_W_RESET_CARD As Long = &H80100068 'The smart card has been reset, so any shared state information is not valid.
Public Const SCARD_W_REMOVED_CARD As Long = &H80100069 'The smart card has been removed, so further communication is not possible.
Public Const SCARD_W_SECURITY_VIOLATION As Long = &H8010006A 'Access was denied because of a security violation.
Public Const SCARD_W_WRONG_CHV As Long = &H8010006B 'The card cannot be accessed because the wrong PIN was presented.
Public Const SCARD_W_CHV_BLOCKED As Long = &H8010006C 'The card cannot be accessed because the maximum number of PIN entry attempts has been reached.
Public Const SCARD_W_EOF As Long = &H8010006D 'The end of the smart card file has been reached.
Public Const SCARD_W_CANCELLED_BY_USER As Long = &H8010006E 'The action was canceled by the user.
Public Const SCARD_W_CARD_NOT_AUTHENTICATED As Long = &H8010006F

Public Const SCARD_E_SERVER_TOO_BUSY As Long = &H80100031
Public Const SCARD_W_CACHE_ITEM_NOT_FOUND As Long = &H80100070
Public Const SCARD_W_CACHE_ITEM_STALE As Long = &H80100071
Public Const SCARD_W_CACHE_ITEM_TOO_BIG As Long = &H80100072

'**************************************************************************
' winerror.h Error Codes
'**************************************************************************
Public Const NO_ERROR As Long = 0 'No error was encountered
Public Const ERROR_SUCCESS As Long = 0 'The operation completed successfully
Public Const ERROR_INVALID_FUNCTION As Long = 1 'Incorrect function
Public Const ERROR_FILE_NOT_FOUND As Long = 2 'The system cannot find the file specified
Public Const ERROR_PATH_NOT_FOUND As Long = 3 'The system cannot find the path specified
Public Const ERROR_TOO_MANY_OPEN_FILES As Long = 4 'The system cannot open the file
Public Const ERROR_ACCESS_DENIED As Long = 5 'Access is denied
Public Const ERROR_INVALID_HANDLE As Long = 6 'The handle is invalid
Public Const ERROR_ARENA_TRASHED As Long = 7 'The storage control blocks were destroyed
Public Const ERROR_NOT_ENOUGH_MEMORY As Long = 8 'Not enough storage is available to process this command
Public Const ERROR_INVALID_BLOCK As Long = 9 'The storage control block address is invalid
Public Const ERROR_BAD_ENVIRONMENT As Long = 10 'The environment is incorrect
Public Const ERROR_BAD_FORMAT As Long = 11 'An attempt was made to load a program with an incorrect format
Public Const ERROR_INVALID_ACCESS As Long = 12 'The access code is invalid
Public Const ERROR_INVALID_DATA As Long = 13 'The data is invalid
Public Const ERROR_OUTOFMEMORY As Long = 14 'Not enough storage is available to complete this operation
Public Const ERROR_INVALID_DRIVE As Long = 15 'The system cannot find the drive specified
Public Const ERROR_CURRENT_DIRECTORY As Long = 16 'The directory cannot be removed
Public Const ERROR_NOT_SAME_DEVICE As Long = 17 'The system cannot move the file to a different disk drive
Public Const ERROR_NO_MORE_FILES As Long = 18 'There are no more files
Public Const ERROR_WRITE_PROTECT As Long = 19 'The media is write protected
Public Const ERROR_BAD_UNIT As Long = 20 'The system cannot find the device specified
Public Const ERROR_NOT_READY As Long = 21 'The device is not ready
Public Const ERROR_BAD_COMMAND As Long = 22 'The device does not recognize the command
Public Const ERROR_CRC As Long = 23 'Data error (cyclic redundancy check)
Public Const ERROR_BAD_LENGTH As Long = 24 'The program issued a command but the command length is incorrect
Public Const ERROR_SEEK As Long = 25 'The drive cannot locate a specific area or track on the disk
Public Const ERROR_NOT_DOS_DISK As Long = 26 'The specified disk or diskette cannot be accessed
Public Const ERROR_SECTOR_NOT_FOUND As Long = 27 'The drive cannot find the sector requested
Public Const ERROR_OUT_OF_PAPER As Long = 28 'The printer is out of paper
Public Const ERROR_WRITE_FAULT As Long = 29 'The system cannot write to the specified device
Public Const ERROR_READ_FAULT As Long = 30 'The system cannot read from the specified device
Public Const ERROR_GEN_FAILURE As Long = 31 'A device attached to the system is not functioning
Public Const ERROR_SHARING_VIOLATION As Long = 32 'The process cannot access the file because it is being used by another process
Public Const ERROR_LOCK_VIOLATION As Long = 33 'The process cannot access the file because another process has locked a portion of the file
Public Const ERROR_WRONG_DISK As Long = 34 'The wrong diskette is in the drive
Public Const ERROR_SHARING_BUFFER_EXCEEDED As Long = 36 'Too many files opened for sharing
Public Const ERROR_HANDLE_EOF As Long = 38 'Reached the end of the file
Public Const ERROR_HANDLE_DISK_FULL As Long = 39 'The disk is full
Public Const ERROR_NOT_SUPPORTED As Long = 50 'Attribute value not supported
Public Const ERROR_REM_NOT_LIST As Long = 51 'The remote computer is not available
Public Const ERROR_DUP_NAME As Long = 52 'A duplicate name exists on the network
Public Const ERROR_BAD_NETPATH As Long = 53 'The network path was not found
Public Const ERROR_NETWORK_BUSY As Long = 54 'The network is busy
Public Const ERROR_DEV_NOT_EXIST As Long = 55 'The specified network resource or device is no longer available
Public Const ERROR_TOO_MANY_CMDS As Long = 56 'The network BIOS command limit has been reached
Public Const ERROR_ADAP_HDW_ERR As Long = 57 'A network adapter hardware error occurred
Public Const ERROR_BAD_NET_RESP As Long = 58 'The specified server cannot perform the requested operation
Public Const ERROR_UNEXP_NET_ERR As Long = 59 'An unexpected network error occurred
Public Const ERROR_BAD_REM_ADAP As Long = 60 'The remote adapter is not compatible
Public Const ERROR_PRINTQ_FULL As Long = 61 'The printer queue is full
Public Const ERROR_NO_SPOOL_SPACE As Long = 62 'Space to store the file waiting to be printed is not available on the server
Public Const ERROR_PRINT_CANCELLED As Long = 63 'Your file waiting to be printed was deleted
Public Const ERROR_NETNAME_DELETED As Long = 64 'The specified network name is no longer available
Public Const ERROR_NETWORK_ACCESS_DENIED As Long = 65 'Network access is denied
Public Const ERROR_BAD_DEV_TYPE As Long = 66 'The network resource type is not correct
Public Const ERROR_BAD_NET_NAME As Long = 67 'The network name cannot be found
Public Const ERROR_TOO_MANY_NAMES As Long = 68 'The name limit for the local computer network adapter card was exceeded
Public Const ERROR_TOO_MANY_SESS As Long = 69 'The network BIOS session limit was exceeded
Public Const ERROR_SHARING_PAUSED As Long = 70 'The remote server has been paused or is in the process of being started
Public Const ERROR_REQ_NOT_ACCEP As Long = 71 'No more connections can be made to this remote computer at this time because there are already as many connections as the computer can accept
Public Const ERROR_REDIR_PAUSED As Long = 72 'The specified printer or disk device has been paused
Public Const ERROR_FILE_EXISTS As Long = 80 'The file exists
Public Const ERROR_CANNOT_MAKE As Long = 82 'The directory or file cannot be created
Public Const ERROR_FAIL_I24 As Long = 83 'Fail on INT 24
Public Const ERROR_OUT_OF_STRUCTURES As Long = 84 'Storage to process this request is not available
Public Const ERROR_ALREADY_ASSIGNED As Long = 85 'The local device name is already in use
Public Const ERROR_INVALID_PASSWORD As Long = 86 'The specified network password is not correct
Public Const ERROR_INVALID_PARAMETER As Long = 87 'The parameter is incorrect
Public Const ERROR_NET_WRITE_FAULT As Long = 88 'A write fault occurred on the network
Public Const ERROR_NO_PROC_SLOTS As Long = 89 'The system cannot start another process at this time
Public Const ERROR_TOO_MANY_SEMAPHORES As Long = 100 'Cannot create another system semaphore
Public Const ERROR_EXCL_SEM_ALREADY_OWNED As Long = 101 'The exclusive semaphore is owned by another process
Public Const ERROR_SEM_IS_SET As Long = 102 'The semaphore is set and cannot be closed
Public Const ERROR_TOO_MANY_SEM_REQUESTS As Long = 103 'The semaphore cannot be set again
Public Const ERROR_INVALID_AT_INTERRUPT_TIME As Long = 104 'Cannot request exclusive semaphores at interrupt time
Public Const ERROR_SEM_OWNER_DIED As Long = 105 'The previous ownership of this semaphore has ended
Public Const ERROR_SEM_USER_LIMIT As Long = 106 'Insert the diskette for drive %1
Public Const ERROR_DISK_CHANGE As Long = 107 'The program stopped because an alternate diskette was not inserted
Public Const ERROR_DRIVE_LOCKED As Long = 108 'The disk is in use or locked by another process
Public Const ERROR_BROKEN_PIPE As Long = 109 'The client attempted a smart card operation in a remote session, such as a client session running on a terminal server, and the operating system in use does not support smart card redirection
Public Const ERROR_OPEN_FAILED As Long = 110 'The system cannot open the device or file specified
Public Const ERROR_BUFFER_OVERFLOW As Long = 111 'The file name is too long
Public Const ERROR_DISK_FULL As Long = 112 'There is not enough space on the disk
Public Const ERROR_NO_MORE_SEARCH_HANDLES As Long = 113 'No more internal file identifiers available
Public Const ERROR_INVALID_TARGET_HANDLE As Long = 114 'The target internal file identifier is incorrect
Public Const ERROR_INVALID_CATEGORY As Long = 117 'The IOCTL call made by the application program is not correct
Public Const ERROR_INVALID_VERIFY_SWITCH As Long = 118 'The verify-on-write switch parameter value is not correct
Public Const ERROR_BAD_DRIVER_LEVEL As Long = 119 'The system does not support the command requested
Public Const ERROR_CALL_NOT_IMPLEMENTED As Long = 120 'This function is not supported on this system
Public Const ERROR_SEM_TIMEOUT As Long = 121 'The semaphore timeout period has expired
Public Const ERROR_INSUFFICIENT_BUFFER As Long = 122 'The data area passed to a system call is too small
Public Const ERROR_INVALID_NAME As Long = 123 'The filename, directory name, or volume label syntax is incorrect
Public Const ERROR_INVALID_LEVEL As Long = 124 'The system call level is not correct
Public Const ERROR_NO_VOLUME_LABEL As Long = 125 'The disk has no volume label
Public Const ERROR_MOD_NOT_FOUND As Long = 126 'The specified module could not be found
Public Const ERROR_PROC_NOT_FOUND As Long = 127 'The specified procedure could not be found
Public Const ERROR_WAIT_NO_CHILDREN As Long = 128 'There are no child processes to wait for
Public Const ERROR_CHILD_NOT_COMPLETE As Long = 129 'The %1 application cannot be run in Win32 mode
Public Const ERROR_DIRECT_ACCESS_HANDLE As Long = 130 'Attempt to use a file handle to an open disk partition for an operation other than raw disk I/O
Public Const ERROR_NEGATIVE_SEEK As Long = 131 'An attempt was made to move the file pointer before the beginning of the file
Public Const ERROR_SEEK_ON_DEVICE As Long = 132 'The file pointer cannot be set on the specified device or file
Public Const ERROR_IS_JOIN_TARGET As Long = 133 'A JOIN or SUBST command (cannot be used for a drive that contains previously joined drives)
Public Const ERROR_IS_JOINED As Long = 134 'An attempt was made to use a JOIN or SUBST command on a drive that has already been joined
Public Const ERROR_IS_SUBSTED As Long = 135 'An attempt was made to use a JOIN or SUBST command on a drive that has already been substituted
Public Const ERROR_NOT_JOINED As Long = 136 'The system tried to delete the JOIN of a drive that is not joined
Public Const ERROR_NOT_SUBSTED As Long = 137 'The system tried to delete the substitution of a drive that is not substituted
Public Const ERROR_JOIN_TO_JOIN As Long = 138 'The system tried to join a drive to a directory on a joined drive
Public Const ERROR_SUBST_TO_SUBST As Long = 139 'The system tried to substitute a drive to a directory on a substituted drive
Public Const ERROR_JOIN_TO_SUBST As Long = 140 'The system tried to join a drive to a directory on a substituted drive
Public Const ERROR_SUBST_TO_JOIN As Long = 141 'The system tried to SUBST a drive to a directory on a joined drive
Public Const ERROR_BUSY_DRIVE As Long = 142 'The system cannot perform a JOIN or SUBST at this time
Public Const ERROR_SAME_DRIVE As Long = 143 'The system cannot join or substitute a drive to or for a directory on the same drive
Public Const ERROR_DIR_NOT_ROOT As Long = 144 'The directory is not a subdirectory of the root directory
Public Const ERROR_DIR_NOT_EMPTY As Long = 145 'The directory is not empty
Public Const ERROR_IS_SUBST_PATH As Long = 146 'The path specified is being used in a substitute
Public Const ERROR_IS_JOIN_PATH As Long = 147 'Not enough resources are available to process this command
Public Const ERROR_PATH_BUSY As Long = 148 'The path specified cannot be used at this time
Public Const ERROR_IS_SUBST_TARGET As Long = 149 'An attempt was made to join or substitute a drive for which a directory on the drive is the target of a previous substitute
Public Const ERROR_SYSTEM_TRACE As Long = 150 'System trace information was not specified in your CONFIG.SYS file, or tracing is disallowed
Public Const ERROR_INVALID_EVENT_COUNT As Long = 151 'The number of specified semaphore events for DosMuxSemWait is not correct
Public Const ERROR_TOO_MANY_MUXWAITERS As Long = 152 'DosMuxSemWait did not execute; too many semaphores are already set
Public Const ERROR_INVALID_LIST_FORMAT As Long = 153 'The DosMuxSemWait list is not correct
Public Const ERROR_LABEL_TOO_LONG As Long = 154 'The volume label you entered exceeds the label character limit of the target file system
Public Const ERROR_TOO_MANY_TCBS As Long = 155 'Cannot create another thread
Public Const ERROR_SIGNAL_REFUSED As Long = 156 'The recipient process has refused the signal
Public Const ERROR_DISCARDED As Long = 157 'The segment is already discarded and cannot be locked
Public Const ERROR_NOT_LOCKED As Long = 158 'The segment is already unlocked
Public Const ERROR_BAD_THREADID_ADDR As Long = 159 'The address for the thread ID is not correct
Public Const ERROR_BAD_ARGUMENTS As Long = 160 'The argument string passed to DosExecPgm is not correct
Public Const ERROR_BAD_PATHNAME As Long = 161 'The specified path is invalid
Public Const ERROR_SIGNAL_PENDING As Long = 162 'A signal is already pending
Public Const ERROR_MAX_THRDS_REACHED As Long = 164 'No more threads can be created in the system
Public Const ERROR_LOCK_FAILED As Long = 167 'Unable to lock a region of a file
Public Const ERROR_BUSY As Long = 170 'The requested resource is in use
Public Const ERROR_CANCEL_VIOLATION As Long = 173 'A lock request was not outstanding for the supplied cancel region
Public Const ERROR_ATOMIC_LOCKS_NOT_SUPPORTED As Long = 174 'The file system does not support atomic changes to the lock type
Public Const ERROR_INVALID_SEGMENT_NUMBER As Long = 180 'The system detected a segment number that was not correct
Public Const ERROR_INVALID_ORDINAL As Long = 182 'The operating system cannot run %1
Public Const ERROR_ALREADY_EXISTS As Long = 183 'Cannot create a file when that file already exists
Public Const ERROR_INVALID_FLAG_NUMBER As Long = 186 'The flag passed is not correct
Public Const ERROR_SEM_NOT_FOUND As Long = 187 'The specified system semaphore name was not found
Public Const ERROR_INVALID_STARTING_CODESEG As Long = 188 'The operating system cannot run %1
Public Const ERROR_INVALID_STACKSEG As Long = 189 'The operating system cannot run %1
Public Const ERROR_INVALID_MODULETYPE As Long = 190 'The operating system cannot run %1
Public Const ERROR_INVALID_EXE_SIGNATURE As Long = 191 'Cannot run %1 in Win32 mode
Public Const ERROR_EXE_MARKED_INVALID As Long = 192 'The operating system cannot run %1
Public Const ERROR_BAD_EXE_FORMAT As Long = 193 '%1 is not a valid Win32 application
Public Const ERROR_ITERATED_DATA_EXCEEDS_64k As Long = 194 'The operating system cannot run %1
Public Const ERROR_INVALID_MINALLOCSIZE As Long = 195 'The operating system cannot run %1
Public Const ERROR_DYNLINK_FROM_INVALID_RING As Long = 196 'The operating system cannot run this application program
Public Const ERROR_IOPL_NOT_ENABLED As Long = 197 'The operating system is not presently configured to run this application
Public Const ERROR_INVALID_SEGDPL As Long = 198 'The operating system cannot run %1
Public Const ERROR_AUTODATASEG_EXCEEDS_64k As Long = 199 'The operating system cannot run this application program
Public Const ERROR_RING2SEG_MUST_BE_MOVABLE As Long = 200 'The code segment cannot be greater than or equal to 64K

'**************************************************************************
' State Values
'**************************************************************************
'The application is unaware of the current state, and would like to know.
'The use of this value results in an immediate return from state transition monitoring
'services.  This is represented by all bits set to zero.
Public Const SCARD_STATE_UNAWARE As Long = &H0

'The application requested that this reader be ignored. No other bits will be set.
Public Const SCARD_STATE_IGNORE As Long = &H1

'This implies that there is a difference between the state believed by the
'application, and the state known by the Service Manager.  When this bit is set,
'the application may assume a significant state change has occurred on this reader.
Public Const SCARD_STATE_CHANGED As Long = &H2

'This implies that the given reader name is not recognized by the Service Manager.
'If this bit is set, then SCARD_STATE_CHANGED and SCARD_STATE_IGNORE will also be set.
Public Const SCARD_STATE_UNKNOWN As Long = &H4

'This implies that the actual state of this reader is not available.
'If this bit is set, then all the following bits are clear.
Public Const SCARD_STATE_UNAVAILABLE As Long = &H8

'This implies that there IS NOT a card in the reader.
'If this bit is set, all the following bits will be clear.
Public Const SCARD_STATE_EMPTY As Long = &H10

'This implies that there IS a card in the reader.
Public Const SCARD_STATE_PRESENT As Long = &H20

'This implies that there is a card in the reader with an ATR matching one of the
'target cards. If this bit is set, SCARD_STATE_PRESENT will also be set. This bit
'is only returned on the SCardLocateCard() service.
Public Const SCARD_STATE_ATRMATCH As Long = &H40
                                            
'This implies that the card in the reader is allocated for exclusive use by
'another application. If this bit is set, SCARD_STATE_PRESENT will also be set.
Public Const SCARD_STATE_EXCLUSIVE As Long = &H80
                                            
'This implies that the card in the reader is in use by one or more other
'applications, but may be connected to in shared mode. If this bit is set,
'SCARD_STATE_PRESENT will also be set.
Public Const SCARD_STATE_INUSE As Long = &H100

'This implies that the card in the reader is unresponsive or not supported by the
'reader or software.
Public Const SCARD_STATE_MUTE As Long = &H200

'This implies that the card in the reader has not been powered up.
Public Const SCARD_STATE_UNPOWERED As Long = &H400

'**************************************************************************
' Card State Values
'**************************************************************************
'This value implies the driver is unaware of the current state of the reader.
Public Const SCARD_UNKNOWN As Long = 0

'This value implies there is no card in the reader.
Public Const SCARD_ABSENT As Long = 1
                                  
'This value implies there is a card is present in the reader,
'but that it has not been moved into position for use.
Public Const SCARD_PRESENT As Long = 2

'This value implies there is a card in the reader in position for use.
'The card is not powered.
Public Const SCARD_SWALLOWED As Long = 3

'This value implies there is power being provided to the card,
'but the Reader Driver is unaware of the mode of the card.
Public Const SCARD_POWERED As Long = 4

'This value implies the card has been reset and is awaiting PTS negotiation.
Public Const SCARD_NEGOTIABLE As Long = 5

'This value implies the card has been reset and specific communication protocols
'have been established.
Public Const SCARD_SPECIFIC As Long = 6

'**************************************************************************
' winscard.dll Prototypes
'**************************************************************************
'SCardAccessStartedEvent
'http://msdn.microsoft.com/en-us/library/aa379466(VS.85).aspx
'HANDLE STDCALL SCardAccessStartedEvent(VOID)
Public Declare Function SCardAccessStartedEvent Lib "winscard.dll" () As Long

'SCardAddReaderToGroup
'http://msdn.microsoft.com/en-us/library/aa379468(VS.85).aspx
'LONG STDCALL SCardAddReaderToGroupA(SCARDCONTEXT(in), LPCSTR(in), LPCSTR(in))
Public Declare Function SCardAddReaderToGroup Lib "winscard.dll" Alias "SCardAddReaderToGroupA" ( _
    ByVal hContext As Long, _
    ByVal szReaderName As String, _
    ByVal szGroupName As String _
    ) As Long

'SCardBeginTransaction
'http://msdn.microsoft.com/en-us/library/aa379469(VS.85).aspx
'LONG STDCALL SCardBeginTransaction(SCARDHANDLE(in))
Public Declare Function SCardBeginTransaction Lib "winscard.dll" ( _
    ByVal hCard As Long _
    ) As Long
    
'SCardCancel
'http://msdn.microsoft.com/en-us/library/aa379470(VS.85).aspx
'LONG STDCALL SCardCancel(SCARDCONTEXT(in))
Public Declare Function SCardCancel Lib "winscard.dll" ( _
    ByVal hContext As Long _
    ) As Long

'SCardConnect
'http://msdn.microsoft.com/en-us/library/aa379473(VS.85).aspx
'LONG STDCALL SCardConnectA(SCARDCONTEXT(in), LPCSTR(in), DWORD(in), DWORD(in),
' LPSCARDHANDLE(out), LPDWORD(out))
Public Declare Function SCardConnect Lib "winscard.dll" Alias "SCardConnectA" ( _
    ByVal hContext As Long, _
    ByVal szReader As String, _
    ByVal dwShareMode As Long, _
    ByVal dwPreferredProtocols As Long, _
    ByRef phCard As Long, _
    ByRef pdwActiveProtocol As Long _
    ) As Long

'SCardControl
'http://msdn.microsoft.com/en-us/library/aa379474(VS.85).aspx
'LONG STDCALL SCardControl(SCARDHANDLE(in), DWORD(in), LPCVOID(in), DWORD(in),
' LPVOID(out), DWORD(in), LPDWORD(out))
Public Declare Function SCardControl Lib "winscard.dll" ( _
    ByVal hCard As Long, _
    ByVal dwControlCode As Long, _
    ByRef lpInBuffer As Long, _
    ByVal nInBufferSize As Long, _
    ByRef lpOutBuffer As Long, _
    ByVal nOutBufferSize As Long, _
    ByRef lpBytesReturned As Long _
    ) As Long

'SCardDisconnect
'http://msdn.microsoft.com/en-us/library/aa379475(VS.85).aspx
'LONG STDCALL SCardDisconnect(SCARDHANDLE(in), DWORD(in))
Public Declare Function SCardDisconnect Lib "winscard.dll" ( _
    ByVal hCard As Long, _
    ByVal dwDisposition As Long _
    ) As Long
    
'SCardEndTransaction
'http://msdn.microsoft.com/en-us/library/aa379477(VS.85).aspx
'LONG STDCALL SCardEndTransaction(SCARDHANDLE(in), DWORD(in))
Public Declare Function SCardEndTransaction Lib "winscard.dll" ( _
    ByVal hCard As Long, _
    ByVal dwDisposition As Long _
    ) As Long
    
'SCardEstablishContext
'http://msdn.microsoft.com/en-us/library/aa379479(VS.85).aspx
'LONG STDCALL SCardEstablishContext(DWORD(in), LPCVOID(in), LPCVOID(in),
' LPSCARDCONTEXT(out))
Public Declare Function SCardEstablishContext Lib "winscard.dll" ( _
    ByVal dwScope As Long, _
    ByVal pvReserved1 As Long, _
    ByVal pvReserved2 As Long, _
    ByRef phContext As Long _
    ) As Long

'SCardForgetCardType
'http://msdn.microsoft.com/en-us/library/aa379482(VS.85).aspx
'LONG STDCALL SCardForgetCardTypeA(SCARDCONTEXT(in), LPCSTR(in))
Public Declare Function SCardForgetCardType Lib "winscard.dll" Alias "SCardForgetCardTypeA" ( _
    ByVal hContext As Long, _
    ByVal szCardName As String _
    ) As Long

'SCardForgetReader
'http://msdn.microsoft.com/en-us/library/aa379484(VS.85).aspx
'LONG STDCALL SCardForgetReaderA(SCARDCONTEXT(in), LPCSTR(in))
Public Declare Function SCardForgetReader Lib "winscard.dll" Alias "SCardForgetReaderA" ( _
    ByVal hContext As Long, _
    ByVal szReaderName As String _
    ) As Long

'SCardForgetReaderGroup
'http://msdn.microsoft.com/en-us/library/aa379486(VS.85).aspx
'LONG STDCALL SCardForgetReaderGroupA(SCARDCONTEXT(in), LPCSTR(in))
Public Declare Function SCardForgetReaderGroup Lib "winscard.dll" Alias "SCardForgetReaderGroupA" ( _
    ByVal hContext As Long, _
    ByVal szGroupName As String _
    ) As Long

'SCardFreeMemory
'http://msdn.microsoft.com/en-us/library/aa379488(VS.85).aspx
'LONG STDCALL SCardFreeMemory(SCARDCONTEXT(in), LPCVOID(in))
Public Declare Function SCardFreeMemory Lib "winscard.dll" ( _
    ByVal hContext As Long, _
    ByVal pvMem As Long _
    ) As Long

'SCardGetAttrib
'http://msdn.microsoft.com/en-us/library/aa379559(VS.85).aspx
'LONG STDCALL SCardGetAttrib(SCARDHANDLE(in), DWORD(in), LPBYTE(out), LPDWORD(inout))
Public Declare Function SCardGetAttrib Lib "winscard.dll" ( _
    ByVal hCard As Long, _
    ByVal dwAttrId As Long, _
    ByRef pbAttr As ByteArray, _
    ByRef pcbAttrLen As Long _
    ) As Long

'SCardGetCardTypeProviderName
'http://msdn.microsoft.com/en-us/library/aa379655(VS.85).aspx
'LONG STDCALL SCardGetCardTypeProviderNameA(SCARDCONTEXT(in), LPCSTR(in), DWORD(in),
' LPSTR(out), LPDWORD(inout))
Public Declare Function SCardGetCardTypeProviderName Lib "winscard.dll" Alias "SCardGetCardTypeProviderNameA" ( _
    ByVal hContext As Long, _
    ByVal szCardName As String, _
    ByVal dwProviderId As Long, _
    ByVal szProvider As String, _
    ByRef pcchProvider As Long _
    ) As Long
    
'SCardGetProviderId
'http://msdn.microsoft.com/en-us/library/aa379761(VS.85).aspx
'LONG STDCALL SCardGetProviderIdA(SCARDCONTEXT(in), LPCSTR(in), LPGUID(out))
Public Declare Function SCardGetProviderId Lib "winscard.dll" Alias "SCardGetProviderIdA" ( _
    ByVal hContext As Long, _
    ByVal szCard As String, _
    ByRef pguidProviderId As GUID _
    ) As Long

'SCardGetStatusChange
'http://msdn.microsoft.com/en-us/library/aa379773(VS.85).aspx
'LONG STDCALL SCardGetStatusChangeA(SCARDCONTEXT(in), DWORD(in),
' LPSCARD_READERSTATEA(inout), DWORD(in))
Public Declare Function SCardGetStatusChange Lib "winscard.dll" Alias "SCardGetStatusChangeA" ( _
    ByVal hContext As Long, _
    ByVal dwTimeout As Long, _
    ByRef rgReaderStates() As SCARD_READERSTATE, _
    ByVal cReaders As Long _
    ) As Long

'SCardIntroduceCardType
'http://msdn.microsoft.com/en-us/library/aa379784(VS.85).aspx
'LONG STDCALL SCardIntroduceCardTypeA(SCARDCONTEXT(in), LPCSTR(in), LPCGUID(in),
' LPCGUID(in), DWORD(in), LPCBYTE(in), LPCBYTE(in), DWORD(in))
Public Declare Function SCardIntroduceCardType Lib "winscard.dll" Alias "SCardIntroduceCardTypeA" ( _
    ByVal hContext As Long, _
    ByVal szCardName As String, _
    ByRef pguidPrimaryProvider As GUID, _
    ByRef pguidInterfaces As GUID, _
    ByVal dwInterfaceCount As Long, _
    ByVal pbAtr As ByteArray, _
    ByVal pbAtrMask As ByteArray, _
    ByVal cbAtrLen As Long _
    ) As Long

'SCardIntroduceReader
'http://msdn.microsoft.com/en-us/library/aa379786(VS.85).aspx
'LONG STDCALL SCardIntroduceReaderA(SCARDCONTEXT(in), LPCSTR(in), LPCSTR(in))
Public Declare Function SCardIntroduceReader Lib "winscard.dll" Alias "SCardIntroduceReaderA" ( _
    ByVal hContext As Long, _
    ByVal szReaderName As String, _
    ByVal szDeviceName As String _
    ) As Long

'SCardIntroduceReaderGroup
'http://msdn.microsoft.com/en-us/library/aa379787(VS.85).aspx
'LONG STDCALL SCardIntroduceReaderGroupA(SCARDCONTEXT(in), LPCSTR(in))
Public Declare Function SCardIntroduceReaderGroup Lib "winscard.dll" Alias "SCardIntroduceReaderGroupA" ( _
    ByVal hContext As Long, _
    ByVal szGroupName As String _
    ) As Long

'SCardIsValidContext
'http://msdn.microsoft.com/en-us/library/aa379788(VS.85).aspx
'LONG STDCALL SCardIsValidContext(SCARDCONTEXT(in))
Public Declare Function SCardIsValidContext Lib "winscard.dll" ( _
    ByVal hContext As Long _
) As Long

'SCardListCards
'http://msdn.microsoft.com/en-us/library/aa379789(VS.85).aspx
'LONG STDCALL SCardListCardsA(SCARDCONTEXT(in), LPCBYTE(in), LPCGUID(in), DWORD(in),
' LPCSTR(out), LPDWORD(inout))
Public Declare Function SCardListCards Lib "winscard.dll" Alias "SCardListCardsA" ( _
    ByVal hContext As Long, _
    ByVal pbAtr As ByteArray, _
    ByVal rgguidInterfaces As Long, _
    ByVal cguidInterfaceCount As Long, _
    ByVal mszCards As String, _
    ByRef pcchCards As Long _
    ) As Long
    
'SCardListInterfaces
'http://msdn.microsoft.com/en-us/library/aa379790(VS.85).aspx
'LONG STDCALL SCardListInterfacesA(SCARDCONTEXT(in), LPCSTR(in), LPGUID(out),
' LPDWORD(inout))
Public Declare Function SCardListInterfaces Lib "winscard.dll" Alias "SCardListInterfacesA" ( _
    ByVal hContext As Long, _
    ByVal szCard As String, _
    ByRef pguidInterfaces As GUID, _
    ByRef pcguidInterfaces As Long _
    ) As Long
    
'SCardListReaderGroups
'http://msdn.microsoft.com/en-us/library/aa379792(VS.85).aspx
'LONG STDCALL SCardListReaderGroupsA(SCARDCONTEXT(in), LPSTR(out), LPDWORD(inout))
Public Declare Function SCardListReaderGroups Lib "winscard.dll" Alias "SCardListReaderGroupsA" ( _
    ByVal hContext As Long, _
    ByVal mszGroups As String, _
    ByRef pcchGroups As Long _
    ) As Long

'SCardListReaders
'http://msdn.microsoft.com/en-us/library/aa379793(VS.85).aspx
'LONG STDCALL SCardListReadersA(SCARDCONTEXT(in), LPCSTR(in), LPSTR(out), LPDWORD(inout))
Public Declare Function SCardListReaders Lib "winscard.dll" Alias "SCardListReadersA" ( _
    ByVal hContext As Long, _
    ByVal mszGroups As String, _
    ByVal mszReaders As String, _
    ByRef pcchReaders As Long _
    ) As Long

'SCardLocateCards
'http://msdn.microsoft.com/en-us/library/aa379794(VS.85).aspx
'LONG STDCALL SCardLocateCardsA(SCARDCONTEXT(in), LPCSTR(in),
' LPSCARD_READERSTATEA(inout), DWORD(in))
Public Declare Function SCardLocateCards Lib "winscard.dll" Alias "SCardLocateCardsA" ( _
    ByVal hContext As Long, _
    ByVal mszCards As String, _
    ByRef rgReaderStates() As SCARD_READERSTATE, _
    ByVal cReaders As Long _
    ) As Long
    
'SCardLocateCardsByATR
'http://msdn.microsoft.com/en-us/library/aa379796(VS.85).aspx
'LONG STDCALL SCardLocateCardsByATRA(SCARDCONTEXT(in), LPSCARD_ATRMASK(in), DWORD(in),
' LPSCARD_READERSTATEA(inout), DWORD(in))
Public Declare Function SCardLocateCardsByATR Lib "winscard.dll" Alias "SCardLocateCardsByATRA" ( _
    ByVal hContext As Long, _
    ByRef rgAtrMasks() As SCARD_ATRMASK, _
    ByVal cAtrs As Long, _
    ByRef rgReaderStates() As SCARD_READERSTATE, _
    ByVal cReaders As Long _
    ) As Long

'SCardReconnect
'http://msdn.microsoft.com/en-us/library/aa379797(VS.85).aspx
'LONG STDCALL SCardReconnect(SCARDHANDLE(in), DWORD(in), DWORD(in), DWORD(in),
' LPDWORD(out))
Public Declare Function SCardReconnect Lib "winscard.dll" ( _
    ByVal hCard As Long, _
    ByVal dwShareMode As Long, _
    ByVal dwPreferredProtocols As Long, _
    ByVal dwInitialization As Long, _
    ByRef pdwActiveProtocol As Long _
    ) As Long
    
'SCardReleaseContext
'http://msdn.microsoft.com/en-us/library/aa379798(VS.85).aspx
'LONG STDCALL SCardReleaseContext(SCARDCONTEXT(in))
Public Declare Function SCardReleaseContext Lib "winscard.dll" ( _
    ByVal hContext As Long _
    ) As Long

'SCardReleaseStartedEvent
'http://msdn.microsoft.com/en-us/library/aa379799(VS.85).aspx
'VOID STDCALL SCardReleaseStartedEvent(HANDLE(in))
Public Declare Sub SCardReleaseStartedEvent Lib "winscard.dll" ( _
    ByVal hStartedEventHandle As Long _
    )

'SCardRemoveReaderFromGroup
'http://msdn.microsoft.com/en-us/library/aa379800(VS.85).aspx
'LONG STDCALL SCardRemoveReaderFromGroupA(SCARDCONTEXT(in), LPCSTR(in), LPCSTR(in))
Public Declare Function SCardRemoveReaderFromGroup Lib "winscard.dll" Alias "SCardRemoveReaderFromGroupA" ( _
    ByVal hContext As Long, _
    ByVal szReaderName As String, _
    ByVal szGroupName As String _
    ) As Long
    
'SCardSetAttrib
'http://msdn.microsoft.com/en-us/library/aa379801(VS.85).aspx
'LONG STDCALL SCardSetAttrib(SCARDHANDLE(in), DWORD(in), LPCBYTE(in), DWORD(in))
Public Declare Function SCardSetAttrib Lib "winscard.dll" ( _
    ByVal hCard As Long, _
    ByVal dwAttrId As Long, _
    ByVal pbAttr As ByteArray, _
    ByVal cbAttrLen As Long _
    ) As Long

'SCardSetCardTypeProviderName
'http://msdn.microsoft.com/en-us/library/aa379802(VS.85).aspx
'LONG STDCALL SCardSetCardTypeProviderNameA(SCARDCONTEXT(in), LPCSTR(in), DWORD(in),
' LPCSTR(in))
Public Declare Function SCardSetCardTypeProviderName Lib "winscard.dll" Alias "SCardSetCardTypeProviderNameA" ( _
    ByVal hContext As Long, _
    ByVal szCardName As String, _
    ByVal dwProviderId As Long, _
    ByVal szProvider As String _
    ) As Long

'SCardState
'LONG STDCALL SCardState(SCARDHANDLE(in), LPDWORD(out), LPDWORD(out), LPBYTE(out),
' LPDWORD(out))
Public Declare Function SCardState Lib "winscard.dll" ( _
    ByVal hCard As Long, _
    ByRef pdwState As Long, _
    ByRef pdwProtocol As Long, _
    ByRef pbAtr As ByteArray, _
    ByRef pcbAtrLen As Long _
) As Long

'SCardStatus
'http://msdn.microsoft.com/en-us/library/aa379803(VS.85).aspx
'LONG STDCALL SCardStatusA(SCARDHANDLE(in), LPSTR(out), LPDWORD(inout), LPDWORD(out),
' LPDWORD(out), LPBYTE(out), LPDWORD(inout))
Public Declare Function SCardStatus Lib "winscard.dll" Alias "SCardStatusA" ( _
    ByVal hCard As Long, _
    ByVal szReaderName As String, _
    ByRef pcchReaderLen As Long, _
    ByRef pdwState As Long, _
    ByRef pdwProtocol As Long, _
    ByRef pbAtr As ByteArray, _
    ByRef pcbAtrLen As Long _
    ) As Long
    
'SCardTransmit
'http://msdn.microsoft.com/en-us/library/aa379804.aspx
'LONG STDCALL SCardTransmit(SCARDHANDLE(in), LPCSCARD_IO_REQUEST(in), LPCBYTE(in),
' DWORD(in), LPSCARD_IO_REQUEST(inout), LPBYTE(out), LPDWORD(inout))
Public Declare Function SCardTransmit Lib "winscard.dll" ( _
    ByVal hCard As Long, _
    ByRef pioSendPci As SCARD_IO_REQUEST, _
    ByRef pbSendBuffer As Byte, _
    ByVal cbSendLength As Long, _
    ByRef pioRecvPci As SCARD_IO_REQUEST, _
    ByRef pbRecvBuffer As Byte, _
    ByRef pcbRecvLength As Long _
) As Long

Public Declare Function SCardTransmitLong Lib "winscard.dll" Alias "SCardTransmit" ( _
    ByVal hCard As Long, _
    ByRef pioSendPci As SCARD_IO_REQUEST, _
    ByRef pbSendBuffer As Byte, _
    ByVal cbSendLength As Long, _
    ByVal pioRecvPci As Long, _
    ByRef pbRecvBuffer As Byte, _
    ByRef pcbRecvLength As Long _
) As Long

'**************************************************************************
' scarddlg.dll Prototypes
'**************************************************************************
'SCardUIDlgSelectCard
'http://msdn.microsoft.com/en-us/library/aa379805(VS.85).aspx
'LPOPENCARDNAME_EX(in)
Public Declare Function SCardUIDlgSelectCard Lib "scarddlg.dll" Alias "SCardUIDlgSelectCardA" ( _
 ByRef pDlgStruc As OPENCARDNAMEA_EX _
 ) As Long
 
Public Const SC_DLG_MINIMAL_UI As Long = &H1
Public Const SC_DLG_NO_UI As Long = &H2
Public Const SC_DLG_FORCE_UI As Long = &H4
 
Public Type OPENCARD_SEARCH_CRITERIA
 dwStructSize As Long
 lpstrGroupNames As String
 nMaxGroupNames As Long
 rgguidInterfaces As Long
 cguidInterfaces As Long
 lpstrCardNames As String
 nMaxCardNames As Long
 lpfnCheck As Long
 lpfnConnect As Long
 lpfnDisconnect As Long
 pvUserData As Long
 dwShareMode As Long
 dwPreferredProtocols As Long
End Type
 
Public Type OPENCARDNAMEA_EX
 dwStructSize As Long
 hSCardContext As Long
 hwndOwner As Long
 dwFlags As Long
 lpstrTitle As String
 lpstrSearchDesc As String
 hIcon As Long
 pOpenCardSearchCriteria As OPENCARD_SEARCH_CRITERIA
 lpfnConnect As Long
 pvUserData As Long
 dwShareMode As Long
 dwPreferredProtocols As Long
 lpstrRdr As String
 nMaxRdr As Long
 lpstrCard As String
 nMaxCard As Long
 dwActiveProtocol As Long
 hCardHandle As Long
End Type

'**************************************************************************
' SCard32.dll Prototypes
'**************************************************************************
'SCardComand
'Handle = In case more instances of DLL are required by the application this handle can
' be used to distinguish between object instances. The value can be set to zero
' only a single instance is used. The SCardServer in this case will do the
' assignment via the thread- / task handle of your application.
'Cmd = SCardServer command (zero terminated string)
'CmdLen = Length of the command string if the data transfer to the SCardServer is
' encrypted; if unencrypted transfer is used, this value must be set to zero.
'DataIn = Pointer to the input data.
'DataInLen = Length of the input data.
'DataOut = pointer to buffer for output data.
'DataOutLen = Maximum length for returned data. Is set to the actual length of the
' returned data.
Public Declare Function SCardComand Lib "SCard32.dll" ( _
    ByRef Handle As Long, _
    ByVal cmd As String, _
    ByRef CmdLen As Long, _
    ByVal DataIn As String, _
    ByRef DataInLen As Long, _
    ByVal DataOut As String, _
    ByRef DataOutLen As Long _
    ) As Long

'**************************************************************************
' Win32 API Prototypes
'**************************************************************************
Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

'LoadLibrary
'http://msdn.microsoft.com/en-us/library/ms684175(VS.85).aspx
'Loads the specified module into the address space of the calling process.
'The specified module may cause other modules to be loaded.
'LPCTSTR(in)
Public Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" ( _
    ByVal lpLibFileName As String _
    ) As Long

'FreeLibrary
'http://msdn.microsoft.com/en-us/library/ms683152(VS.85).aspx
'Frees the loaded dynamic-link library (DLL) module and, if necessary, decrements
'its reference count. When the reference count reaches zero, the module is unloaded
'from the address space of the calling process and the handle is no longer valid.
'HMODULE(in)
Public Declare Function FreeLibrary Lib "kernel32" ( _
    ByVal hLibModule As Long _
    ) As Long

'GetProcAddress
'http://msdn.microsoft.com/en-us/library/ms683212.aspx
'Retrieves the address of an exported function or variable from the specified DLL.
'HMODULE(in), LPCSTR(in)
Public Declare Function GetProcAddress Lib "kernel32" ( _
    ByVal hModule As Long, _
    ByVal lpProcName As String _
    ) As Long

'CopyMemory
'http://msdn.microsoft.com/en-us/library/aa366535(VS.85).aspx
'Copies a block of memory from one location to another.
'PVOID(in), const VOID(in), SIZE_T(in)
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
    ByRef Destination As Any, _
    ByRef Source As Any, _
    ByVal Length As Long _
    )

'ReadFile
'http://msdn.microsoft.com/en-us/library/aa365467.aspx
'Reads data from the specified file or input/output (I/O) device. Reads occur
'at the position specified by the file pointer if supported by the device.
'HANDLE(in), LPVOID(out), DWORD(in), LPDWORD(out_opt), LPOVERLAPPED(inout_opt)
Public Declare Function ReadFile Lib "kernel32" ( _
    ByVal hFile As Long, _
    ByRef lpBuffer As ByteArray, _
    ByVal nNumberOfBytesToRead As Long, _
    ByRef lpNumberOfBytesRead As Long, _
    ByRef lpOverlapped As OVERLAPPED _
    ) As Long
    
'WriteFile
'http://msdn.microsoft.com/en-us/library/aa365747(VS.85).aspx
'Writes data to the specified file or input/output (I/O) device. Writes occur at the
'position specified by the file pointer, if the handle refers to a seeking device.
'HANDLE(in), LPCVOID(in), DWORD(in), LPDWORD(out_opt), LPOVERLAPPED(inout_opt)
Public Declare Function WriteFile Lib "kernel32" ( _
    ByVal hFile As Long, _
    ByRef lpBuffer As ByteArray, _
    ByVal nNumberOfBytesToWrite As Long, _
    ByRef lpNumberOfBytesWritten As Long, _
    ByRef lpOverlapped As OVERLAPPED _
    ) As Long

'CreateFile
'http://msdn.microsoft.com/en-us/library/aa363858(VS.85).aspx
'Creates or opens a file or I/O device. The function returns a handle that can
'be used to access the file or device for various types of I/O depending on the
'file or device and the flags and attributes specified.
'LPCSTR(in), DWORD(in), DWORD(in), LPSECURITY_ATTRIBUTES(in_opt), DWORD(in),
'DWORD(in), HANDLE(in_opt)
Public Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" ( _
    ByVal lpFileName As String, _
    ByVal dwDesiredAccess As Long, _
    ByVal dwShareMode As Long, _
    ByRef lpSecurityAttributes As SECURITY_ATTRIBUTES, _
    ByVal dwCreationDisposition As Long, _
    ByVal dwFlagsAndAttributes As Long, _
    ByVal hTemplateFile As Long _
    ) As Long
    
'CloseHandle
'http://msdn.microsoft.com/en-us/library/ms724211.aspx
'Closes an open object handle.
'HANDLE(in)
Public Declare Function CloseHandle Lib "kernel32" ( _
    ByVal hObject As Long _
    ) As Long
    
'SetCommState
'http://msdn.microsoft.com/en-us/library/aa363436(VS.85).aspx
'Configures a communications device according to the specifications in a
'device-control block (a DCB structure). The function reinitializes all hardware
'and control settings, but it does not empty output or input queues.
'HANDLE(in), LPDCB(in)
Public Declare Function SetCommState Lib "kernel32" ( _
    ByVal hFile As Long, _
    ByRef lpDCB As DCB _
    ) As Long

'GetCommState
'http://msdn.microsoft.com/en-us/library/aa363260(VS.85).aspx
'Retrieves the current control settings for a specified communications device.
'HANDLE(in), LPDCB (inout)
Public Declare Function GetCommState Lib "kernel32" ( _
    ByVal hFile As Long, _
    ByRef lpDCB As DCB _
    ) As Long
    
'GetCommTimeouts
'http://msdn.microsoft.com/en-us/library/aa363261(VS.85).aspx
'Retrieves the time-out parameters for all read and write operations on a specified
'communications device.
'HANDLE(in), LPCOMMTIMEOUTS(out)
Public Declare Function GetCommTimeouts Lib "kernel32" ( _
    ByVal hFile As Long, _
    ByRef lpCommTimeouts As COMMTIMEOUTS _
    ) As Long
    
'GetLastError
'http://msdn.microsoft.com/en-us/library/ms679360.aspx
'Retrieves the calling thread's last-error code value. The last-error code is
'maintained on a per-thread basis. Multiple threads do not overwrite each other's
'last-error code. Visual Basic applications should call err.LastDllError instead
'of GetLastError.
Public Declare Function GetLastError Lib "kernel32" () As Long

'FormatMessage
'http://msdn.microsoft.com/en-us/library/ms679351(VS.85).aspx
'Formats a message string. The function requires a message definition as input.
'The message definition can come from a buffer passed into the function. It can
'come from a message table resource in an already-loaded module. Or the caller
'can ask the function to search the system's message table resource(s) for the
'message definition. The function finds the message definition in a message table
'resource based on a message identifier and a language identifier. The function
'copies the formatted message text to an output buffer, processing any embedded
'insert sequences if requested.
'DWORD(in), LPCVOID(in_opt), DWORD(in), DWORD(in), LPTSTR(out), DWORD(in), va_list (in_opt)
Public Declare Function FormatMessage Lib "kernel32" Alias "FormatMessageA" ( _
    ByVal dwFlags As Long, _
    ByRef lpSource As Any, _
    ByVal dwMessageId As Long, _
    ByVal dwLanguageId As Long, _
    ByVal lpBuffer As String, _
    ByVal nSize As Long, _
    ByVal Arguments As Long _
    ) As Long
    
'BuildCommDCB
'http://msdn.microsoft.com/en-us/library/aa363143(VS.85).aspx
'Fills a specified DCB structure with values specified in a device-control string.
'The device-control string uses the syntax of the "mode" command.
'LPCTSTR(in), LPDCB(out)
Public Declare Function BuildCommDCB Lib "kernel32" Alias "BuildCommDCBA" ( _
    ByVal lpDef As String, _
    ByRef lpDCB As DCB _
    ) As Long

'**************************************************************************
' Win32 API Types
'**************************************************************************
Public Type OVERLAPPED
 Internal As Long
 InternalHigh As Long
 Offset As Long
 OffsetHigh As Long
 hEvent As Long
End Type

Public Type SECURITY_ATTRIBUTES
 nLength As Long
 lpSecurityDescriptor As Long
 bInheritHandle As Long
End Type

Public Type COMMTIMEOUTS
 ReadIntervalTimeout As Long
 ReadTotalTimeoutMultiplier As Long
 ReadTotalTimeoutConstant As Long
 WriteTotalTimeoutMultiplier As Long
 WriteTotalTimeoutConstant As Long
End Type

Public Type DCB
 DCBlength As Long
 BaudRate As Long
 fBitFields As Long 'See Comments
 wReserved As Integer
 XonLim As Integer
 XoffLim As Integer
 ByteSize As Byte
 Parity As Byte
 StopBits As Byte
 XonChar As Byte
 XoffChar As Byte
 ErrorChar As Byte
 EofChar As Byte
 EvtChar As Byte
 wReserved1 As Integer 'Reserved; Do Not Use
End Type
' Note about fBitFields:
' The fourteen actual DCB bit-sized data fields within the four bytes of
' fBitFields can be manipulated by bitwise logical And/Or operations.
' FieldName             Bit #     Description
' -----------------     -----     ------------------------------
' fBinary                 1       binary mode, no EOF check
' fParity                 2       enable parity checking
' fOutxCtsFlow            3       CTS output flow control
' fOutxDsrFlow            4       DSR output flow control
' fDtrControl             5       DTR flow control type (2 bits)
' fDsrSensitivity         7       DSR sensitivity
' fTXContinueOnXoff       8       XOFF continues Tx
' fOutX                   9       XON/XOFF out flow control
' fInX                   10       XON/XOFF in flow control
' fErrorChar             11       enable error replacement
' fNull                  12       enable null stripping
' fRtsControl            13       RTS flow control (2 bits)
' fAbortOnError          15       abort reads/writes on error
' fDummy2                16       reserved

'**************************************************************************
' Win32 API Constants
'**************************************************************************
Public Const FILE_SHARE_READ As Long = &H1
Public Const FILE_SHARE_WRITE As Long = &H2
Public Const OPEN_EXISTING As Long = 3
Public Const FILE_ATTRIBUTE_NORMAL As Long = &H80
Public Const GENERIC_READ As Long = &H80000000
Public Const GENERIC_WRITE As Long = &H40000000

'===========================================
'C to VB Data Type Conversion Chart
'===========================================
'SCARDCONTEXT   ByVal someName As Long
'DWORD          ByVal someName As Long
'LPBYTE         ByVal someName As String
'LPCBYTE        ByVal someName As String (prevents the callers copy from being modified)
'LPCSTR         ByVal someName As String (prevents the callers copy from being modified)
'LPTSTR         ByVal someName As String (use a fixed-length string)
'LPCTSTR        ByVal someName As String (prevents the callers copy from being modified)
'===========================================

'===========================================
'Type Declaration Characters Reference Chart
'===========================================
'Data Type  Character   Example     Equivalent To
'---------  ---------   --------    -------------
'Currency   @           Dim var@    Dim var As Currency
'Double     #           Dim var#    Dim var As Double
'Integer    %           Dim var%    Dim var As Integer
'Long       &           Dim var&    Dim var As Long
'Single     !           Dim var!    Dim var As Single
'String     $           Dim var$    Dim var As String
'===========================================

Public Function show_byte_array_as(ByRef byte_array As ByteArray, ByRef array_length As Long, Optional ByVal show_as As Byte = SHOW_AS_LONG, Optional ByVal add_spaces As Boolean = False) As String
 If array_length <= 0 Then Exit Function
 
 Dim i As Long
 Dim one_byte As Byte
 Dim temp_long As Long
 Dim to_return As String
 
 'display byte array in hex
 If show_as = SHOW_AS_HEX Then
  For i = 0 To (array_length - 1)
   one_byte = byte_array.b(i)
   If (one_byte < 16) Then
    to_return = to_return & "0"
   End If
   to_return = to_return + Hex(one_byte)
   If add_spaces = True Then
    to_return = to_return & " "
   End If
  Next
  
 'display byte array as chars
 ElseIf show_as = SHOW_AS_CHARS Then
  For i = 0 To (array_length - 1)
   to_return = to_return & Chr(byte_array.b(i))
   If add_spaces = True Then
    to_return = to_return & " "
   End If
  Next
  
 'display as Yes or No
 ElseIf show_as = SHOW_AS_YES_NO Then
  If byte_array.b(0) = 0 Then
   to_return = "No"
  Else
   to_return = "Yes"
  End If
  
 'display as card type
 ElseIf show_as = SHOW_AS_CARD_TYPE Then
  Select Case byte_array.b(0)
   Case 0
    to_return = "unknown type"
   Case 1
    to_return = "7816 Asynchronous"
   Case 2
    to_return = "7816 Synchronous"
   Case Else
    to_return = "RFU"
  End Select
  
 'display as card presence
 ElseIf show_as = SHOW_AS_CARD_PRESENCE Then
  Select Case byte_array.b(0)
   Case 0
    to_return = "card is not present"
   Case 1
    to_return = "card is present, but not swallowed"
   Case 2
    to_return = "card is present"
   Case 4
     to_return = "card is confiscated"
   Case Else
    to_return = "unknown"
  End Select
  
 'display actual byte values
 ElseIf show_as = SHOW_ACTUAL_BYTES Then
  For i = (array_length - 1) To 0 Step -1
   to_return = to_return & Str$(byte_array.b(i))
   If add_spaces = True Then
    to_return = to_return & " "
   End If
  Next
  
 'display byte array as an IFD Version
 ElseIf show_as = SHOW_AS_IFD_VERSION Then
  For i = (array_length - 1) To 2 Step -1
   to_return = to_return + Trim$(Str$(Hex(byte_array.b(i)))) + "."
  Next
  Dim build_number As Long
  build_number = byte_array.b(1) * (2 ^ 8) + byte_array.b(0)
  to_return = to_return + Trim$(Str$(Hex(build_number)))
  
 'display byte array as a long
 Else
 
  For i = 0 To (array_length - 1)
   temp_long = temp_long + (byte_array.b(i) * (2 ^ (i * 8)))
  Next
  'CopyMemory temp_long, byte_array.b(0), array_length
  to_return = Str$(temp_long)
  
  'Error Encoding
  If show_as = SHOW_AS_ERROR_ENCODING Then
   If temp_long = 0 Then
    to_return = "LRC (longitudinal redundancy check)"
   ElseIf temp_long = 1 Then
    to_return = "CRC (cyclical redundancy check)"
   End If
  End If
  
  'Mechanical Characteristics
  'DWORD indicating which mechanical characteristics are supported.
  'If zero, no special characteristics are supported.
  'Note that multiple bits can be set:
  ' 0x00000001 Card swallowing mechanism
  ' 0x00000002 Card ejection mechanism
  ' 0x00000004 Card capture mechanism
  'All other values are reserved for future use (RFU).
  If show_as = SHOW_AS_MECH Then
   Dim supports_card_swallowing As String
   Dim supports_card_ejection As String
   Dim supports_card_capture As String
   supports_card_swallowing = "NO"
   supports_card_ejection = "NO"
   supports_card_capture = "NO"
   If temp_long And &H1 = &H1 Then supports_card_swallowing = "YES"
   If temp_long And &H2 = &H2 Then supports_card_ejection = "YES"
   If temp_long And &H4 = &H4 Then supports_card_capture = "YES"
   to_return = "Card swallowing [" & supports_card_swallowing & "] " _
   & "Card ejection [" & supports_card_ejection & "] " _
   & "Card capture [" & supports_card_capture & "]"
  End If
  
  'DWORD
  If show_as = SHOW_AS_DWORD Then
   to_return = Trim$(Str$(Hex(temp_long)))
   While Len(to_return) < 8
    to_return = "0" & to_return
   Wend
   to_return = "0x" & to_return
  End If
  
  'Current Protocol
  If show_as = SHOW_AS_CURRENT_PROTOCOL Then
   Select Case temp_long
    Case &H1 '0001
     to_return = "T=0"
    Case &H2 '0010
     to_return = "T=1"
    Case Else
     to_return = "Unknown"
   End Select
  End If
  
  'Protocol Types
  If show_as = SHOW_AS_PROTOCOL_TYPES Then
   Select Case temp_long
    Case &H0 '0000
     to_return = "T=0 Not Supported, T=1 Not Supported"
    Case &H1 '0001
     to_return = "T=0 Supported, T=1 Not Supported"
    Case &H2 '0010
     to_return = "T=0 Not Supported, T=1 Supported"
    Case &H3 '0011
     to_return = "T=0 Supported, T=1 Supported"
    Case Else
     to_return = "Unknown"
   End Select
  End If
  
  'Channel ID
  '0001 0000
  'DWORD encoded as 0x DDDD CCCC
  'DDDD = data channel type
  'CCCC = channel number
  'The following encodings are defined for DDDD:
  ' 0x01 serial I/O; CCCC is a port number.
  ' 0x02 parallel I/O; CCCC is a port number.
  ' 0x04 PS/2 keyboard port; CCCC is zero.
  ' 0x08 SCSI; CCCC is SCSI ID number.
  ' 0x10 IDE; CCCC is device number.
  ' 0x20 USB; CCCC is device number.
  ' 0xFy vendor-defined interface with y in the range zero through 15,
  ' CCCC is vendor defined.
  If show_as = SHOW_AS_CHANNEL_ID And array_length = 4 Then
   to_return = Trim$(Str$(Hex(temp_long)))
   While Len(to_return) < 8
    to_return = "0" & to_return
   Wend
   Dim data_channel_type As Double
   Dim channel_number As Double
   data_channel_type = Val("&H" & Mid(to_return, 1, 4))
   channel_number = Val("&H" & Mid(to_return, 5, 4))
   Select Case data_channel_type
    Case &H1
     to_return = "Serial, port " + Hex$(channel_number)
    Case &H2
     to_return = "Parallel, port " + Hex$(channel_number)
    Case &H4
     to_return = "PS/2"
    Case &H8
     to_return = "SCSI, SCSI ID " + Hex$(channel_number)
    Case &H10
     to_return = "IDE, device number " + Hex$(channel_number)
    Case &H20
     to_return = "USB, device number " + Hex$(channel_number)
    Case &H40
     to_return = "PCMCIA"
    Case Else
     to_return = "Unknown Channel, 0x" + to_return
    End Select
  End If
   
 End If
 
 show_byte_array_as = Trim$(to_return)
End Function

'convert hex to binary
Public Function hex_2_binary(sHex As String) As String
 Dim iLength As Integer, iCounter As Integer, sResult As String
 sResult = ""
 If sHex <> "" Then
  iLength = Len(Trim$(sHex))
  For iCounter = 1 To iLength
   Select Case Mid(sHex, iCounter, 1)
    Case "0"
     sResult = sResult & "0000"
    Case "1"
     sResult = sResult & "0001"
    Case "2"
     sResult = sResult & "0010"
    Case "3"
     sResult = sResult & "0011"
    Case "4"
     sResult = sResult & "0100"
    Case "5"
     sResult = sResult & "0101"
    Case "6"
     sResult = sResult & "0110"
    Case "7"
     sResult = sResult & "0111"
    Case "8"
     sResult = sResult & "1000"
    Case "9"
     sResult = sResult & "1001"
    Case "A"
     sResult = sResult & "1010"
    Case "B"
     sResult = sResult & "1011"
    Case "C"
     sResult = sResult & "1100"
    Case "D"
     sResult = sResult & "1101"
    Case "E"
     sResult = sResult & "1110"
    Case "F"
     sResult = sResult & "1111"
   End Select
  Next
 End If
 hex_2_binary = sResult
End Function

'example showing how to grab variable values from a dll
Public Sub get_winscard_variables()
 Dim load_library_result As Long
 load_library_result = LoadLibrary("winscard.dll")
 If (load_library_result <> 0) Then
  Dim get_proc_address_result As Long
  Dim SCARD_PCI_T0_LONG As Long
  Dim SCARD_PCI_T1_LONG As Long
  Dim SCARD_PCI_RAW_LONG As Long
  get_proc_address_result = GetProcAddress(load_library_result, "g_rgSCardT0Pci")
  If get_proc_address_result <> 0 Then
   CopyMemory SCARD_PCI_T0_LONG, ByVal get_proc_address_result, 4 'long = 4 bytes
  End If
  get_proc_address_result = GetProcAddress(load_library_result, "g_rgSCardT1Pci")
  If get_proc_address_result <> 0 Then
   CopyMemory SCARD_PCI_T1_LONG, ByVal get_proc_address_result, 4 'long = 4 bytes
  End If
  get_proc_address_result = GetProcAddress(load_library_result, "g_rgSCardRawPci")
  If get_proc_address_result <> 0 Then
   CopyMemory SCARD_PCI_RAW_LONG, ByVal get_proc_address_result, 4 'long = 4 bytes
  End If
  MsgBox "T0: " & SCARD_PCI_T0_LONG & vbNewLine & "T1: " & SCARD_PCI_T1_LONG & vbNewLine & "RAW: " & SCARD_PCI_RAW_LONG
  Dim free_library_result As Long
  free_library_result = FreeLibrary(load_library_result)
 End If
End Sub

Public Function print_winscard_error(function_name As String, the_result As Long, Optional silent As Boolean = False) As String
 Dim error_code_name As String
 Dim error_code_desc As String
 Dim to_return As String
 Select Case the_result
  Case SCARD_S_SUCCESS
   error_code_name = "SCARD_S_SUCCESS"
   error_code_desc = "No error was encountered."
  Case ERROR_BROKEN_PIPE
   error_code_name = "ERROR_BROKEN_PIPE"
   error_code_desc = "The client attempted a smart card operation in a remote session, such as a client session running on a terminal server, and the operating system in use does not support smart card redirection."
  Case SCARD_E_BAD_SEEK
   error_code_name = "SCARD_E_BAD_SEEK"
   error_code_desc = "An error occurred in setting the smart card file object pointer."
  Case SCARD_E_CANCELLED
   error_code_name = "SCARD_E_CANCELLED"
   error_code_desc = "The action was canceled by an SCardCancel request."
  Case SCARD_E_CANT_DISPOSE
   error_code_name = "SCARD_E_CANT_DISPOSE"
   error_code_desc = "The system could not dispose of the media in the requested manner."
  Case SCARD_E_CARD_UNSUPPORTED
   error_code_name = "SCARD_E_CARD_UNSUPPORTED"
   error_code_desc = "The smart card does not meet minimal requirements for support."
  Case SCARD_E_CERTIFICATE_UNAVAILABLE
   error_code_name = "SCARD_E_CERTIFICATE_UNAVAILABLE"
   error_code_desc = "The requested certificate could not be obtained."
  Case SCARD_E_COMM_DATA_LOST
   error_code_name = "SCARD_E_COMM_DATA_LOST"
   error_code_desc = "A communications error with the smart card has been detected."
  Case SCARD_E_DIR_NOT_FOUND
   error_code_name = "SCARD_E_DIR_NOT_FOUND"
   error_code_desc = "The specified directory does not exist in the smart card."
  Case SCARD_E_DUPLICATE_READER
   error_code_name = "SCARD_E_DUPLICATE_READER"
   error_code_desc = "The reader driver did not produce a unique reader name."
  Case SCARD_E_FILE_NOT_FOUND
   error_code_name = "SCARD_E_FILE_NOT_FOUND"
   error_code_desc = "The specified file does not exist in the smart card."
  Case SCARD_E_ICC_CREATEORDER
   error_code_name = "SCARD_E_ICC_CREATEORDER"
   error_code_desc = "The requested order of object creation is not supported."
  Case SCARD_E_ICC_INSTALLATION
   error_code_name = "SCARD_E_ICC_INSTALLATION"
   error_code_desc = "No primary provider can be found for the smart card."
  Case SCARD_E_INSUFFICIENT_BUFFER
   error_code_name = "SCARD_E_INSUFFICIENT_BUFFER"
   error_code_desc = "The data buffer for returned data is too small for the returned data."
  Case SCARD_E_INVALID_ATR
   error_code_name = "SCARD_E_INVALID_ATR"
   error_code_desc = "An ATR string obtained from the registry is not a valid ATR string."
  Case SCARD_E_INVALID_CHV
   error_code_name = "SCARD_E_INVALID_CHV"
   error_code_desc = "The supplied PIN is incorrect."
  Case SCARD_E_INVALID_HANDLE
   error_code_name = "SCARD_E_INVALID_HANDLE"
   error_code_desc = "The supplied handle was not valid."
  Case SCARD_E_INVALID_PARAMETER
   error_code_name = "SCARD_E_INVALID_PARAMETER"
   error_code_desc = "One or more of the supplied parameters could not be properly interpreted."
  Case SCARD_E_INVALID_TARGET
   error_code_name = "SCARD_E_INVALID_TARGET"
   error_code_desc = "Registry startup information is missing or not valid."
  Case SCARD_E_INVALID_VALUE
   error_code_name = "SCARD_E_INVALID_VALUE"
   error_code_desc = "One or more of the supplied parameter values could not be properly interpreted."
  Case SCARD_E_NO_ACCESS
   error_code_name = "SCARD_E_NO_ACCESS"
   error_code_desc = "Access is denied to the file."
  Case SCARD_E_NO_DIR
   error_code_name = "SCARD_E_NO_DIR"
   error_code_desc = "The supplied path does not represent a smart card directory."
  Case SCARD_E_NO_FILE
   error_code_name = "SCARD_E_NO_FILE"
   error_code_desc = "The supplied path does not represent a smart card file."
  Case SCARD_E_NO_MEMORY
   error_code_name = "SCARD_E_NO_MEMORY"
   error_code_desc = "Not enough memory available to complete this command."
  Case SCARD_E_NO_READERS_AVAILABLE
   error_code_name = "SCARD_E_NO_READERS_AVAILABLE"
   error_code_desc = "No smart card reader is available."
  Case SCARD_E_NO_SERVICE
   error_code_name = "SCARD_E_NO_SERVICE"
   error_code_desc = "The smart card resource manager is not running."
  Case SCARD_E_NO_SMARTCARD
   error_code_name = "SCARD_E_NO_SMARTCARD"
   error_code_desc = "The operation requires a smart card, but no smart card is currently in the device."
  Case SCARD_E_NO_SUCH_CERTIFICATE
   error_code_name = "SCARD_E_NO_SUCH_CERTIFICATE"
   error_code_desc = "The requested certificate does not exist."
  Case SCARD_E_NOT_READY
   error_code_name = "SCARD_E_NOT_READY"
   error_code_desc = "The reader or card is not ready to accept commands."
  Case SCARD_E_NOT_TRANSACTED
   error_code_name = "SCARD_E_NOT_TRANSACTED"
   error_code_desc = "An attempt was made to end a nonexistent transaction."
  Case SCARD_E_PCI_TOO_SMALL
   error_code_name = "SCARD_E_PCI_TOO_SMALL"
   error_code_desc = "The PCI receive buffer was too small."
  Case SCARD_E_PROTO_MISMATCH
   error_code_name = "SCARD_E_PROTO_MISMATCH"
   error_code_desc = "The requested protocols are incompatible with the protocol currently in use with the card."
  Case SCARD_E_READER_UNAVAILABLE
   error_code_name = "SCARD_E_READER_UNAVAILABLE"
   error_code_desc = "The specified reader is not currently available for use."
  Case SCARD_E_READER_UNSUPPORTED
   error_code_name = "SCARD_E_READER_UNSUPPORTED"
   error_code_desc = "The reader driver does not meet minimal requirements for support."
  Case SCARD_E_SERVICE_STOPPED
   error_code_name = "SCARD_E_SERVICE_STOPPED"
   error_code_desc = "The smart card resource manager has shut down."
  Case SCARD_E_SHARING_VIOLATION
   error_code_name = "SCARD_E_SHARING_VIOLATION"
   error_code_desc = "The smart card cannot be accessed because of other outstanding connections."
  Case SCARD_E_SYSTEM_CANCELLED
   error_code_name = "SCARD_E_SYSTEM_CANCELLED"
   error_code_desc = "The action was canceled by the system, presumably to log off or shut down."
  Case SCARD_E_TIMEOUT
   error_code_name = "SCARD_E_TIMEOUT"
   error_code_desc = "The user-specified time-out value has expired."
  Case SCARD_E_UNEXPECTED
   error_code_name = "SCARD_E_UNEXPECTED"
   error_code_desc = "An unexpected card error has occurred."
  Case SCARD_E_UNKNOWN_CARD
   error_code_name = "SCARD_E_UNKNOWN_CARD"
   error_code_desc = "The specified smart card name is not recognized."
  Case SCARD_E_UNKNOWN_READER
   error_code_name = "SCARD_E_UNKNOWN_READER"
   error_code_desc = "The specified reader name is not recognized."
  Case SCARD_E_UNKNOWN_RES_MNG
   error_code_name = "SCARD_E_UNKNOWN_RES_MNG"
   error_code_desc = "An unrecognized error code was returned from a layered component."
  Case SCARD_E_UNSUPPORTED_FEATURE
   error_code_name = "SCARD_E_UNSUPPORTED_FEATURE"
   error_code_desc = "This smart card does not support the requested feature."
  Case SCARD_E_WRITE_TOO_MANY
   error_code_name = "SCARD_E_WRITE_TOO_MANY"
   error_code_desc = "An attempt was made to write more data than would fit in the target object."
  Case SCARD_F_COMM_ERROR
   error_code_name = "SCARD_F_COMM_ERROR"
   error_code_desc = "An internal communications error has been detected." & vbNewLine & "A communication error occured with the reader."
  Case SCARD_F_INTERNAL_ERROR
   error_code_name = "SCARD_F_INTERNAL_ERROR"
   error_code_desc = "An internal consistency check failed."
  Case SCARD_F_UNKNOWN_ERROR
   error_code_name = "SCARD_F_UNKNOWN_ERROR"
   error_code_desc = "An internal error has been detected, but the source is unknown."
  Case SCARD_F_WAITED_TOO_LONG
   error_code_name = "SCARD_F_WAITED_TOO_LONG"
   error_code_desc = "An internal consistency timer has expired."
  Case SCARD_P_SHUTDOWN
   error_code_name = "SCARD_P_SHUTDOWN"
   error_code_desc = "The operation has been aborted to allow the server application to exit."
  Case SCARD_W_CANCELLED_BY_USER
   error_code_name = "SCARD_W_CANCELLED_BY_USER"
   error_code_desc = "The action was canceled by the user."
  Case SCARD_W_CHV_BLOCKED
   error_code_name = "SCARD_W_CHV_BLOCKED"
   error_code_desc = "The card cannot be accessed because the maximum number of PIN entry attempts has been reached."
  Case SCARD_W_EOF
   error_code_name = "SCARD_W_EOF"
   error_code_desc = "The end of the smart card file has been reached."
  Case SCARD_W_REMOVED_CARD
   error_code_name = "SCARD_W_REMOVED_CARD"
   error_code_desc = "The smart card has been removed, so further communication is not possible."
  Case SCARD_W_RESET_CARD
   error_code_name = "SCARD_W_RESET_CARD"
   error_code_desc = "The smart card has been reset, so any shared state information is not valid."
  Case SCARD_W_SECURITY_VIOLATION
   error_code_name = "SCARD_W_SECURITY_VIOLATION"
   error_code_desc = "Access was denied because of a security violation."
  Case SCARD_W_UNPOWERED_CARD
   error_code_name = "SCARD_W_UNPOWERED_CARD"
   error_code_desc = "Power has been removed from the smart card, so that further communication is not possible."
  Case SCARD_W_UNRESPONSIVE_CARD
   error_code_name = "SCARD_W_UNRESPONSIVE_CARD"
   error_code_desc = "The smart card is not responding to a reset."
  Case SCARD_W_UNSUPPORTED_CARD
   error_code_name = "SCARD_W_UNSUPPORTED_CARD"
   error_code_desc = "The reader cannot communicate with the card, due to ATR string configuration conflicts."
  Case SCARD_W_WRONG_CHV
   error_code_name = "SCARD_W_WRONG_CHV"
   error_code_desc = "The card cannot be accessed because the wrong PIN was presented."
  Case SCARD_E_NO_KEY_CONTAINER
   error_code_name = "SCARD_E_NO_KEY_CONTAINER"
   error_code_desc = "SCARD_E_NO_KEY_CONTAINER"
  Case SCARD_W_CARD_NOT_AUTHENTICATED
   error_code_name = "SCARD_W_CARD_NOT_AUTHENTICATED"
   error_code_desc = "SCARD_W_CARD_NOT_AUTHENTICATED"
  Case SCARD_E_SERVER_TOO_BUSY
   error_code_name = "SCARD_E_SERVER_TOO_BUSY"
   error_code_desc = "SCARD_E_SERVER_TOO_BUSY"
  Case SCARD_W_CACHE_ITEM_NOT_FOUND
   error_code_name = "SCARD_W_CACHE_ITEM_NOT_FOUND"
   error_code_desc = "SCARD_W_CACHE_ITEM_NOT_FOUND"
  Case SCARD_W_CACHE_ITEM_STALE
   error_code_name = "SCARD_W_CACHE_ITEM_STALE"
   error_code_desc = "SCARD_W_CACHE_ITEM_STALE"
  Case SCARD_W_CACHE_ITEM_TOO_BIG
   error_code_name = "SCARD_W_CACHE_ITEM_TOO_BIG"
   error_code_desc = "SCARD_W_CACHE_ITEM_TOO_BIG"
  Case ERROR_INVALID_PARAMETER
   error_code_name = "ERROR_INVALID_PARAMETER"
   error_code_desc = "The parameter is incorrect."
  Case ERROR_NOT_SUPPORTED
   error_code_name = "ERROR_NOT_SUPPORTED"
   error_code_desc = "Attribute value not supported."
  Case ERROR_BROKEN_PIPE
   error_code_name = "ERROR_BROKEN_PIPE"
   error_code_desc = "ERROR_BROKEN_PIPE"
  Case ERROR_GEN_FAILURE
   error_code_name = "ERROR_GEN_FAILURE"
   error_code_desc = "A device attached to the system is not functioning."
  Case ERROR_BAD_COMMAND
   error_code_name = "STATUS_INVALID_DEVICE_STATE"
   error_code_desc = "The reader is not in the correct state to select a protocol. That is, a smart card is inserted, but not reset."
  Case Else
   error_code_name = "UNKNOWN_ERROR"
   error_code_desc = "Error Code (Hex): 0x" & Hex(the_result) & vbNewLine & "Error Code (Decimal): " & the_result
 End Select
 If silent = False Then
  Call MsgBox("The function " & function_name & "() returned an error..." & vbNewLine & vbNewLine & "Error Code: " & vbNewLine & error_code_name & vbNewLine & vbNewLine & "Error Description:" & vbNewLine & error_code_desc, vbInformation + vbOKOnly, "winscard.dll Error")
 Else
  to_return = error_code_name
 End If
 print_winscard_error = to_return
End Function

Public Function print_scard_comand_error(the_result As Long, Optional silent As Boolean = False) As String
 Dim error_code_number As String
 Dim error_code_desc_line1 As String
 Dim error_code_desc_line2 As String
 Dim to_return As String
 Select Case the_result
  Case &H0
   error_code_number = "0x0000"
   error_code_desc_line1 = "OK"
   error_code_desc_line2 = "Command was successfully executed."
  Case &H1001
   error_code_number = "0x1001"
   error_code_desc_line1 = "Serial port not available"
   error_code_desc_line2 = "The search on the selected COM port was not possible because the port is not available on the Windows system. The port needs to be configured to be properly recognized by the system."
  Case &H1002
   error_code_number = "0x1002"
   error_code_desc_line1 = "Serial port is used by another application"
   error_code_desc_line2 = "The COM-port is used by another application, e.g. a mouse or a modem."
  Case &H1008
   error_code_number = "0x1008"
   error_code_desc_line1 = "No terminal detected on selected port"
   error_code_desc_line2 = "The COM-port configured properly but no terminal was detected, check the connection."
  Case &H1009
   error_code_number = "0x1009"
   error_code_desc_line1 = "Terminal is locked by X"
   error_code_desc_line2 = "At the moment access to the terminal is not possible because another application is accessing a card or has not released the card yet. X will be replaced by the application’s name."
  Case &H1010
   error_code_number = "0x1010"
   error_code_desc_line1 = "The application is with this reader does not compatible."
   error_code_desc_line2 = "TOWITOKO distributes OEM terminals that is inconsistent with the TOWITOKO standard software compatible. The devices can upgrade (see www.towitoko.de)"
  Case &H4000
   error_code_number = "0x4000"
   error_code_desc_line1 = "No card present in terminal"
   error_code_desc_line2 = ""
  Case &H4001
   error_code_number = "0x4001"
   error_code_desc_line1 = "Card was removed during access"
   error_code_desc_line2 = ""
  Case &H4002
   error_code_number = "0x4002"
   error_code_desc_line1 = "Invalid card present in terminal"
   error_code_desc_line2 = ""
  Case &H4004
   error_code_number = "0x4004"
   error_code_desc_line1 = "Card ejection failed"
   error_code_desc_line2 = "Reserved for future terminals with automatic card ejection."
  Case &H1200
   error_code_number = "0x1200"
   error_code_desc_line1 = "Unknown command"
   error_code_desc_line2 = "The command string was not recognized."
  Case &H1201
   error_code_number = "0x1201"
   error_code_desc_line1 = "Command execution not possible with current card"
   error_code_desc_line2 = "Not all commands can be used with all cards - especially those for memory and processor cards"
  Case &H1202
   error_code_number = "0x1202"
   error_code_desc_line1 = "Command execution not possible with this terminal"
   error_code_desc_line2 = "Occurs e.g. if a T0 command is sent to a terminal not supporting processor cards"
  Case &H1203
   error_code_number = "0x1203"
   error_code_desc_line1 = "Invalid command parameter"
   error_code_desc_line2 = "e.g. invalid address range for the command Card,MemRead"
  Case &H1310
   error_code_number = "0x1310"
   error_code_desc_line1 = "Smartcard access failed"
   error_code_desc_line2 = "A non recoverable error occurred during access to the smartcard"
  Case &H1311
   error_code_number = "0x1311"
   error_code_desc_line1 = "PIN error! X trial(s) left"
   error_code_desc_line2 = "PIN-Error for memory smartcards. X is replaced by the remaining number of trials"
  Case &H2000
   error_code_number = "0x2000"
   error_code_desc_line1 = "Server not available"
   error_code_desc_line2 = "The SCardServer failed to start"
 End Select
 If silent = False Then
  Call MsgBox("The function SCardComand() returned an error..." & vbNewLine & vbNewLine & "Error Code: " & error_code_number & vbNewLine & vbNewLine & "Error Description:" & vbNewLine & error_code_desc_line1 & vbNewLine & error_code_desc_line2, vbInformation + vbOKOnly, "SCard32.dll Error")
 Else
  to_return = error_code_desc_line1
 End If
 print_scard_comand_error = to_return
End Function