/**
 * WinPR: Windows Portable Runtime
 * Smart Card API
 *
 * Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
 * Copyright 2020 Armin Novak <armin.novak@thincast.com>
 * Copyright 2020 Thincast Technologies GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef WINPR_SMARTCARD_H
#define WINPR_SMARTCARD_H

#include <winpr/platform.h>
#include <winpr/winpr.h>
#include <winpr/wtypes.h>

#include <winpr/io.h>
#include <winpr/error.h>

WINPR_PRAGMA_DIAG_PUSH
WINPR_PRAGMA_DIAG_IGNORED_RESERVED_ID_MACRO

#ifndef _WINSCARD_H_
// NOLINTNEXTLINE(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp)
#define _WINSCARD_H_ /* do not include winscard.h */
#endif

WINPR_PRAGMA_DIAG_POP

#ifndef SCARD_S_SUCCESS

#define SCARD_S_SUCCESS NO_ERROR

#define SCARD_F_INTERNAL_ERROR -2146435071l          // (0x80100001L)
#define SCARD_E_CANCELLED -2146435070l               // (0x80100002L)
#define SCARD_E_INVALID_HANDLE -2146435069l          // (0x80100003L)
#define SCARD_E_INVALID_PARAMETER -2146435068l       // (0x80100004L)
#define SCARD_E_INVALID_TARGET -2146435067l          // (0x80100005L)
#define SCARD_E_NO_MEMORY -2146435066l               // (0x80100006L)
#define SCARD_F_WAITED_TOO_LONG -2146435065l         // (0x80100007L)
#define SCARD_E_INSUFFICIENT_BUFFER -2146435064l     // (0x80100008L)
#define SCARD_E_UNKNOWN_READER -2146435063l          // (0x80100009L)
#define SCARD_E_TIMEOUT -2146435062l                 // (0x8010000AL)
#define SCARD_E_SHARING_VIOLATION -2146435061l       // (0x8010000BL)
#define SCARD_E_NO_SMARTCARD -2146435060l            // (0x8010000CL)
#define SCARD_E_UNKNOWN_CARD -2146435059l            // (0x8010000DL)
#define SCARD_E_CANT_DISPOSE -2146435058l            // (0x8010000EL)
#define SCARD_E_PROTO_MISMATCH -2146435057l          // (0x8010000FL)
#define SCARD_E_NOT_READY -2146435056l               // (0x80100010L)
#define SCARD_E_INVALID_VALUE -2146435055l           // (0x80100011L)
#define SCARD_E_SYSTEM_CANCELLED -2146435054l        // (0x80100012L)
#define SCARD_F_COMM_ERROR -2146435053l              // (0x80100013L)
#define SCARD_F_UNKNOWN_ERROR -2146435052l           // (0x80100014L)
#define SCARD_E_INVALID_ATR -2146435051l             // (0x80100015L)
#define SCARD_E_NOT_TRANSACTED -2146435050l          // (0x80100016L)
#define SCARD_E_READER_UNAVAILABLE -2146435049l      // (0x80100017L)
#define SCARD_P_SHUTDOWN -2146435048l                // (0x80100018L)
#define SCARD_E_PCI_TOO_SMALL -2146435047l           // (0x80100019L)
#define SCARD_E_READER_UNSUPPORTED -2146435046l      // (0x8010001AL)
#define SCARD_E_DUPLICATE_READER -2146435045l        // (0x8010001BL)
#define SCARD_E_CARD_UNSUPPORTED -2146435044l        // (0x8010001CL)
#define SCARD_E_NO_SERVICE -2146435043l              // (0x8010001DL)
#define SCARD_E_SERVICE_STOPPED -2146435042l         // (0x8010001EL)
#define SCARD_E_UNEXPECTED -2146435041l              // (0x8010001FL)
#define SCARD_E_ICC_INSTALLATION -2146435040l        // (0x80100020L)
#define SCARD_E_ICC_CREATEORDER -2146435039l         // (0x80100021L)
#define SCARD_E_UNSUPPORTED_FEATURE -2146435038l     // (0x80100022L)
#define SCARD_E_DIR_NOT_FOUND -2146435037l           // (0x80100023L)
#define SCARD_E_FILE_NOT_FOUND -2146435036l          // (0x80100024L)
#define SCARD_E_NO_DIR -2146435035l                  // (0x80100025L)
#define SCARD_E_NO_FILE -2146435034l                 // (0x80100026L)
#define SCARD_E_NO_ACCESS -2146435033l               // (0x80100027L)
#define SCARD_E_WRITE_TOO_MANY -2146435032l          // (0x80100028L)
#define SCARD_E_BAD_SEEK -2146435031l                // (0x80100029L)
#define SCARD_E_INVALID_CHV -2146435030l             // (0x8010002AL)
#define SCARD_E_UNKNOWN_RES_MNG -2146435029l         // (0x8010002BL)
#define SCARD_E_NO_SUCH_CERTIFICATE -2146435028l     // (0x8010002CL)
#define SCARD_E_CERTIFICATE_UNAVAILABLE -2146435027l // (0x8010002DL)
#define SCARD_E_NO_READERS_AVAILABLE -2146435026l    // (0x8010002EL)
#define SCARD_E_COMM_DATA_LOST -2146435025l          // (0x8010002FL)
#define SCARD_E_NO_KEY_CONTAINER -2146435024l        // (0x80100030L)
#define SCARD_E_SERVER_TOO_BUSY -2146435023l         // (0x80100031L)
#define SCARD_E_PIN_CACHE_EXPIRED -2146435022l       // (0x80100032L)
#define SCARD_E_NO_PIN_CACHE -2146435021l            // (0x80100033L)
#define SCARD_E_READ_ONLY_CARD -2146435020l          // (0x80100034L)

#define SCARD_W_UNSUPPORTED_CARD -2146434971l       // (0x80100065L)
#define SCARD_W_UNRESPONSIVE_CARD -2146434970l      // (0x80100066L)
#define SCARD_W_UNPOWERED_CARD -2146434969l         // (0x80100067L)
#define SCARD_W_RESET_CARD -2146434968l             // (0x80100068L)
#define SCARD_W_REMOVED_CARD -2146434967l           // (0x80100069L)
#define SCARD_W_SECURITY_VIOLATION -2146434966l     // (0x8010006AL)
#define SCARD_W_WRONG_CHV -2146434965l              // (0x8010006BL)
#define SCARD_W_CHV_BLOCKED -2146434964l            // (0x8010006CL)
#define SCARD_W_EOF -2146434963l                    // (0x8010006DL)
#define SCARD_W_CANCELLED_BY_USER -2146434962l      // (0x8010006EL)
#define SCARD_W_CARD_NOT_AUTHENTICATED -2146434961l // (0x8010006FL)
#define SCARD_W_CACHE_ITEM_NOT_FOUND -2146434960l   // (0x80100070L)
#define SCARD_W_CACHE_ITEM_STALE -2146434959l       // (0x80100071L)
#define SCARD_W_CACHE_ITEM_TOO_BIG -2146434958l     // (0x80100072L)

#endif

/* ------------------------ missing definition with mingw --------------------*/
#ifndef SCARD_E_PIN_CACHE_EXPIRED
#define SCARD_E_PIN_CACHE_EXPIRED -2146435022l // (0x80100032L)
#endif

#ifndef SCARD_E_NO_PIN_CACHE
#define SCARD_E_NO_PIN_CACHE -2146435021l // (0x80100033L)
#endif

#ifndef SCARD_E_READ_ONLY_CARD
#define SCARD_E_READ_ONLY_CARD -2146435020l // (0x80100034L)
#endif

#ifndef SCARD_W_CACHE_ITEM_TOO_BIG
#define SCARD_W_CACHE_ITEM_TOO_BIG -2146434958l // (0x80100072L)
#endif
/* -------------------------------------------------------------------------- */

#define SCARD_ATR_LENGTH 33

#define SCARD_PROTOCOL_UNDEFINED 0x00000000u
#define SCARD_PROTOCOL_T0 0x00000001u
#define SCARD_PROTOCOL_T1 0x00000002u
#define SCARD_PROTOCOL_RAW 0x00010000u

#define SCARD_PROTOCOL_Tx (SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1)
#define SCARD_PROTOCOL_DEFAULT 0x80000000u
#define SCARD_PROTOCOL_OPTIMAL 0x00000000u

#define SCARD_POWER_DOWN 0
#define SCARD_COLD_RESET 1
#define SCARD_WARM_RESET 2

#define SCARD_CTL_CODE(code) \
	CTL_CODE(FILE_DEVICE_SMARTCARD, (code), METHOD_BUFFERED, FILE_ANY_ACCESS)

#define IOCTL_SMARTCARD_POWER SCARD_CTL_CODE(1)
#define IOCTL_SMARTCARD_GET_ATTRIBUTE SCARD_CTL_CODE(2)
#define IOCTL_SMARTCARD_SET_ATTRIBUTE SCARD_CTL_CODE(3)
#define IOCTL_SMARTCARD_CONFISCATE SCARD_CTL_CODE(4)
#define IOCTL_SMARTCARD_TRANSMIT SCARD_CTL_CODE(5)
#define IOCTL_SMARTCARD_EJECT SCARD_CTL_CODE(6)
#define IOCTL_SMARTCARD_SWALLOW SCARD_CTL_CODE(7)
#define IOCTL_SMARTCARD_IS_PRESENT SCARD_CTL_CODE(10)
#define IOCTL_SMARTCARD_IS_ABSENT SCARD_CTL_CODE(11)
#define IOCTL_SMARTCARD_SET_PROTOCOL SCARD_CTL_CODE(12)
#define IOCTL_SMARTCARD_GET_STATE SCARD_CTL_CODE(14)
#define IOCTL_SMARTCARD_GET_LAST_ERROR SCARD_CTL_CODE(15)
#define IOCTL_SMARTCARD_GET_PERF_CNTR SCARD_CTL_CODE(16)

#define IOCTL_SMARTCARD_GET_FEATURE_REQUEST SCARD_CTL_CODE(3400)

#define MAXIMUM_ATTR_STRING_LENGTH 32
#define MAXIMUM_SMARTCARD_READERS 10

#define SCARD_ATTR_VALUE(Class, Tag) ((((ULONG)(Class)) << 16) | ((ULONG)(Tag)))

#define SCARD_CLASS_VENDOR_INFO 1
#define SCARD_CLASS_COMMUNICATIONS 2
#define SCARD_CLASS_PROTOCOL 3
#define SCARD_CLASS_POWER_MGMT 4
#define SCARD_CLASS_SECURITY 5
#define SCARD_CLASS_MECHANICAL 6
#define SCARD_CLASS_VENDOR_DEFINED 7
#define SCARD_CLASS_IFD_PROTOCOL 8
#define SCARD_CLASS_ICC_STATE 9
#define SCARD_CLASS_PERF 0x7FFE
#define SCARD_CLASS_SYSTEM 0x7FFF

#define SCARD_ATTR_VENDOR_NAME SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0100)
#define SCARD_ATTR_VENDOR_IFD_TYPE SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0101)
#define SCARD_ATTR_VENDOR_IFD_VERSION SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0102)
#define SCARD_ATTR_VENDOR_IFD_SERIAL_NO SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0103)
#define SCARD_ATTR_CHANNEL_ID SCARD_ATTR_VALUE(SCARD_CLASS_COMMUNICATIONS, 0x0110)
#define SCARD_ATTR_PROTOCOL_TYPES SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0120)
#define SCARD_ATTR_DEFAULT_CLK SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0121)
#define SCARD_ATTR_MAX_CLK SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0122)
#define SCARD_ATTR_DEFAULT_DATA_RATE SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0123)
#define SCARD_ATTR_MAX_DATA_RATE SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0124)
#define SCARD_ATTR_MAX_IFSD SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0125)
#define SCARD_ATTR_POWER_MGMT_SUPPORT SCARD_ATTR_VALUE(SCARD_CLASS_POWER_MGMT, 0x0131)
#define SCARD_ATTR_USER_TO_CARD_AUTH_DEVICE SCARD_ATTR_VALUE(SCARD_CLASS_SECURITY, 0x0140)
#define SCARD_ATTR_USER_AUTH_INPUT_DEVICE SCARD_ATTR_VALUE(SCARD_CLASS_SECURITY, 0x0142)
#define SCARD_ATTR_CHARACTERISTICS SCARD_ATTR_VALUE(SCARD_CLASS_MECHANICAL, 0x0150)

#define SCARD_ATTR_CURRENT_PROTOCOL_TYPE SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0201)
#define SCARD_ATTR_CURRENT_CLK SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0202)
#define SCARD_ATTR_CURRENT_F SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0203)
#define SCARD_ATTR_CURRENT_D SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0204)
#define SCARD_ATTR_CURRENT_N SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0205)
#define SCARD_ATTR_CURRENT_W SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0206)
#define SCARD_ATTR_CURRENT_IFSC SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0207)
#define SCARD_ATTR_CURRENT_IFSD SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0208)
#define SCARD_ATTR_CURRENT_BWT SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0209)
#define SCARD_ATTR_CURRENT_CWT SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x020a)
#define SCARD_ATTR_CURRENT_EBC_ENCODING SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x020b)
#define SCARD_ATTR_EXTENDED_BWT SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x020c)

#define SCARD_ATTR_ICC_PRESENCE SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0300)
#define SCARD_ATTR_ICC_INTERFACE_STATUS SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0301)
#define SCARD_ATTR_CURRENT_IO_STATE SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0302)
#define SCARD_ATTR_ATR_STRING SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0303)
#define SCARD_ATTR_ICC_TYPE_PER_ATR SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0304)

#define SCARD_ATTR_ESC_RESET SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA000)
#define SCARD_ATTR_ESC_CANCEL SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA003)
#define SCARD_ATTR_ESC_AUTHREQUEST SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA005)
#define SCARD_ATTR_MAXINPUT SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA007)

#define SCARD_ATTR_DEVICE_UNIT SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0001)
#define SCARD_ATTR_DEVICE_IN_USE SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0002)
#define SCARD_ATTR_DEVICE_FRIENDLY_NAME_A SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0003)
#define SCARD_ATTR_DEVICE_SYSTEM_NAME_A SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0004)
#define SCARD_ATTR_DEVICE_FRIENDLY_NAME_W SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0005)
#define SCARD_ATTR_DEVICE_SYSTEM_NAME_W SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0006)
#define SCARD_ATTR_SUPRESS_T1_IFS_REQUEST SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0007)

#define SCARD_PERF_NUM_TRANSMISSIONS SCARD_ATTR_VALUE(SCARD_CLASS_PERF, 0x0001)
#define SCARD_PERF_BYTES_TRANSMITTED SCARD_ATTR_VALUE(SCARD_CLASS_PERF, 0x0002)
#define SCARD_PERF_TRANSMISSION_TIME SCARD_ATTR_VALUE(SCARD_CLASS_PERF, 0x0003)

#ifdef UNICODE
#define SCARD_ATTR_DEVICE_FRIENDLY_NAME SCARD_ATTR_DEVICE_FRIENDLY_NAME_W
#define SCARD_ATTR_DEVICE_SYSTEM_NAME SCARD_ATTR_DEVICE_SYSTEM_NAME_W
#else
#define SCARD_ATTR_DEVICE_FRIENDLY_NAME SCARD_ATTR_DEVICE_FRIENDLY_NAME_A
#define SCARD_ATTR_DEVICE_SYSTEM_NAME SCARD_ATTR_DEVICE_SYSTEM_NAME_A
#endif

#define SCARD_T0_HEADER_LENGTH 7
#define SCARD_T0_CMD_LENGTH 5

#define SCARD_T1_PROLOGUE_LENGTH 3
#define SCARD_T1_EPILOGUE_LENGTH 2
#define SCARD_T1_MAX_IFS 254

#define SCARD_UNKNOWN 0
#define SCARD_ABSENT 1
#define SCARD_PRESENT 2
#define SCARD_SWALLOWED 3
#define SCARD_POWERED 4
#define SCARD_NEGOTIABLE 5
#define SCARD_SPECIFIC 6

#pragma pack(push, 1)

typedef struct
{
	DWORD dwProtocol;
	DWORD cbPciLength;
} SCARD_IO_REQUEST, *PSCARD_IO_REQUEST, *LPSCARD_IO_REQUEST;
typedef const SCARD_IO_REQUEST* LPCSCARD_IO_REQUEST;

typedef struct
{
	BYTE bCla, bIns, bP1, bP2, bP3;
} SCARD_T0_COMMAND, *LPSCARD_T0_COMMAND;

typedef struct
{
	SCARD_IO_REQUEST ioRequest;
	BYTE bSw1, bSw2;
	union
	{
		SCARD_T0_COMMAND CmdBytes;
		BYTE rgbHeader[5];
	} DUMMYUNIONNAME;
} SCARD_T0_REQUEST;

typedef SCARD_T0_REQUEST *PSCARD_T0_REQUEST, *LPSCARD_T0_REQUEST;

typedef struct
{
	SCARD_IO_REQUEST ioRequest;
} SCARD_T1_REQUEST;
typedef SCARD_T1_REQUEST *PSCARD_T1_REQUEST, *LPSCARD_T1_REQUEST;

#define SCARD_READER_SWALLOWS 0x00000001
#define SCARD_READER_EJECTS 0x00000002
#define SCARD_READER_CONFISCATES 0x00000004

#define SCARD_READER_TYPE_SERIAL 0x01
#define SCARD_READER_TYPE_PARALELL 0x02
#define SCARD_READER_TYPE_KEYBOARD 0x04
#define SCARD_READER_TYPE_SCSI 0x08
#define SCARD_READER_TYPE_IDE 0x10
#define SCARD_READER_TYPE_USB 0x20
#define SCARD_READER_TYPE_PCMCIA 0x40
#define SCARD_READER_TYPE_TPM 0x80
#define SCARD_READER_TYPE_NFC 0x100
#define SCARD_READER_TYPE_UICC 0x200
#define SCARD_READER_TYPE_VENDOR 0xF0

#ifndef WINSCARDAPI
#define WINSCARDAPI WINPR_API
#endif

typedef ULONG_PTR SCARDCONTEXT;
typedef SCARDCONTEXT *PSCARDCONTEXT, *LPSCARDCONTEXT;

typedef ULONG_PTR SCARDHANDLE;
typedef SCARDHANDLE *PSCARDHANDLE, *LPSCARDHANDLE;

#define SCARD_AUTOALLOCATE UINT32_MAX

#define SCARD_SCOPE_USER 0
#define SCARD_SCOPE_TERMINAL 1
#define SCARD_SCOPE_SYSTEM 2

#define SCARD_STATE_UNAWARE 0x00000000
#define SCARD_STATE_IGNORE 0x00000001
#define SCARD_STATE_CHANGED 0x00000002
#define SCARD_STATE_UNKNOWN 0x00000004
#define SCARD_STATE_UNAVAILABLE 0x00000008
#define SCARD_STATE_EMPTY 0x00000010
#define SCARD_STATE_PRESENT 0x00000020
#define SCARD_STATE_ATRMATCH 0x00000040
#define SCARD_STATE_EXCLUSIVE 0x00000080
#define SCARD_STATE_INUSE 0x00000100
#define SCARD_STATE_MUTE 0x00000200
#define SCARD_STATE_UNPOWERED 0x00000400

#define SCARD_SHARE_EXCLUSIVE 1
#define SCARD_SHARE_SHARED 2
#define SCARD_SHARE_DIRECT 3

#define SCARD_LEAVE_CARD 0
#define SCARD_RESET_CARD 1
#define SCARD_UNPOWER_CARD 2
#define SCARD_EJECT_CARD 3

#define SC_DLG_MINIMAL_UI 0x01
#define SC_DLG_NO_UI 0x02
#define SC_DLG_FORCE_UI 0x04

#define SCERR_NOCARDNAME 0x4000
#define SCERR_NOGUIDS 0x8000

typedef SCARDHANDLE(WINAPI* LPOCNCONNPROCA)(SCARDCONTEXT hSCardContext, LPSTR szReader,
                                            LPSTR mszCards, PVOID pvUserData);
typedef SCARDHANDLE(WINAPI* LPOCNCONNPROCW)(SCARDCONTEXT hSCardContext, LPWSTR szReader,
                                            LPWSTR mszCards, PVOID pvUserData);

typedef BOOL(WINAPI* LPOCNCHKPROC)(SCARDCONTEXT hSCardContext, SCARDHANDLE hCard, PVOID pvUserData);
typedef void(WINAPI* LPOCNDSCPROC)(SCARDCONTEXT hSCardContext, SCARDHANDLE hCard, PVOID pvUserData);

#define SCARD_READER_SEL_AUTH_PACKAGE ((DWORD)-629)

#define SCARD_AUDIT_CHV_FAILURE 0x0
#define SCARD_AUDIT_CHV_SUCCESS 0x1

#define SCardListCardTypes SCardListCards

#define PCSCardIntroduceCardType(hContext, szCardName, pbAtr, pbAtrMask, cbAtrLen,         \
                                 pguidPrimaryProvider, rgguidInterfaces, dwInterfaceCount) \
	SCardIntroduceCardType(hContext, szCardName, pguidPrimaryProvider, rgguidInterfaces,   \
	                       dwInterfaceCount, pbAtr, pbAtrMask, cbAtrLen)

#define SCardGetReaderCapabilities SCardGetAttrib
#define SCardSetReaderCapabilities SCardSetAttrib

typedef struct
{
	LPSTR szReader;
	LPVOID pvUserData;
	DWORD dwCurrentState;
	DWORD dwEventState;
	DWORD cbAtr;
	BYTE rgbAtr[36];
} SCARD_READERSTATEA, *PSCARD_READERSTATEA, *LPSCARD_READERSTATEA;

typedef struct
{
	LPWSTR szReader;
	LPVOID pvUserData;
	DWORD dwCurrentState;
	DWORD dwEventState;
	DWORD cbAtr;
	BYTE rgbAtr[36];
} SCARD_READERSTATEW, *PSCARD_READERSTATEW, *LPSCARD_READERSTATEW;

typedef struct
{
	DWORD cbAtr;
	BYTE rgbAtr[36];
	BYTE rgbMask[36];
} SCARD_ATRMASK, *PSCARD_ATRMASK, *LPSCARD_ATRMASK;

typedef struct
{
	DWORD dwStructSize;
	LPSTR lpstrGroupNames;
	DWORD nMaxGroupNames;
	LPCGUID rgguidInterfaces;
	DWORD cguidInterfaces;
	LPSTR lpstrCardNames;
	DWORD nMaxCardNames;
	LPOCNCHKPROC lpfnCheck;
	LPOCNCONNPROCA lpfnConnect;
	LPOCNDSCPROC lpfnDisconnect;
	LPVOID pvUserData;
	DWORD dwShareMode;
	DWORD dwPreferredProtocols;
} OPENCARD_SEARCH_CRITERIAA, *POPENCARD_SEARCH_CRITERIAA, *LPOPENCARD_SEARCH_CRITERIAA;

typedef struct
{
	DWORD dwStructSize;
	LPWSTR lpstrGroupNames;
	DWORD nMaxGroupNames;
	LPCGUID rgguidInterfaces;
	DWORD cguidInterfaces;
	LPWSTR lpstrCardNames;
	DWORD nMaxCardNames;
	LPOCNCHKPROC lpfnCheck;
	LPOCNCONNPROCW lpfnConnect;
	LPOCNDSCPROC lpfnDisconnect;
	LPVOID pvUserData;
	DWORD dwShareMode;
	DWORD dwPreferredProtocols;
} OPENCARD_SEARCH_CRITERIAW, *POPENCARD_SEARCH_CRITERIAW, *LPOPENCARD_SEARCH_CRITERIAW;

typedef struct
{
	DWORD dwStructSize;
	SCARDCONTEXT hSCardContext;
	HWND hwndOwner;
	DWORD dwFlags;
	LPCSTR lpstrTitle;
	LPCSTR lpstrSearchDesc;
	HICON hIcon;
	POPENCARD_SEARCH_CRITERIAA pOpenCardSearchCriteria;
	LPOCNCONNPROCA lpfnConnect;
	LPVOID pvUserData;
	DWORD dwShareMode;
	DWORD dwPreferredProtocols;
	LPSTR lpstrRdr;
	DWORD nMaxRdr;
	LPSTR lpstrCard;
	DWORD nMaxCard;
	DWORD dwActiveProtocol;
	SCARDHANDLE hCardHandle;
} OPENCARDNAME_EXA, *POPENCARDNAME_EXA, *LPOPENCARDNAME_EXA;

typedef struct
{
	DWORD dwStructSize;
	SCARDCONTEXT hSCardContext;
	HWND hwndOwner;
	DWORD dwFlags;
	LPCWSTR lpstrTitle;
	LPCWSTR lpstrSearchDesc;
	HICON hIcon;
	POPENCARD_SEARCH_CRITERIAW pOpenCardSearchCriteria;
	LPOCNCONNPROCW lpfnConnect;
	LPVOID pvUserData;
	DWORD dwShareMode;
	DWORD dwPreferredProtocols;
	LPWSTR lpstrRdr;
	DWORD nMaxRdr;
	LPWSTR lpstrCard;
	DWORD nMaxCard;
	DWORD dwActiveProtocol;
	SCARDHANDLE hCardHandle;
} OPENCARDNAME_EXW, *POPENCARDNAME_EXW, *LPOPENCARDNAME_EXW;

#define OPENCARDNAMEA_EX OPENCARDNAME_EXA
#define OPENCARDNAMEW_EX OPENCARDNAME_EXW
#define POPENCARDNAMEA_EX POPENCARDNAME_EXA
#define POPENCARDNAMEW_EX POPENCARDNAME_EXW
#define LPOPENCARDNAMEA_EX LPOPENCARDNAME_EXA
#define LPOPENCARDNAMEW_EX LPOPENCARDNAME_EXW

typedef enum
{
	RSR_MATCH_TYPE_READER_AND_CONTAINER = 1,
	RSR_MATCH_TYPE_SERIAL_NUMBER,
	RSR_MATCH_TYPE_ALL_CARDS
} READER_SEL_REQUEST_MATCH_TYPE;

typedef struct
{
	DWORD dwShareMode;
	DWORD dwPreferredProtocols;
	READER_SEL_REQUEST_MATCH_TYPE MatchType;
	union
	{
		struct
		{
			DWORD cbReaderNameOffset;
			DWORD cchReaderNameLength;
			DWORD cbContainerNameOffset;
			DWORD cchContainerNameLength;
			DWORD dwDesiredCardModuleVersion;
			DWORD dwCspFlags;
		} ReaderAndContainerParameter;
		struct
		{
			DWORD cbSerialNumberOffset;
			DWORD cbSerialNumberLength;
			DWORD dwDesiredCardModuleVersion;
		} SerialNumberParameter;
	};
} READER_SEL_REQUEST, *PREADER_SEL_REQUEST;

typedef struct
{
	DWORD cbReaderNameOffset;
	DWORD cchReaderNameLength;
	DWORD cbCardNameOffset;
	DWORD cchCardNameLength;
} READER_SEL_RESPONSE, *PREADER_SEL_RESPONSE;

typedef struct
{
	DWORD dwStructSize;
	HWND hwndOwner;
	SCARDCONTEXT hSCardContext;
	LPSTR lpstrGroupNames;
	DWORD nMaxGroupNames;
	LPSTR lpstrCardNames;
	DWORD nMaxCardNames;
	LPCGUID rgguidInterfaces;
	DWORD cguidInterfaces;
	LPSTR lpstrRdr;
	DWORD nMaxRdr;
	LPSTR lpstrCard;
	DWORD nMaxCard;
	LPCSTR lpstrTitle;
	DWORD dwFlags;
	LPVOID pvUserData;
	DWORD dwShareMode;
	DWORD dwPreferredProtocols;
	DWORD dwActiveProtocol;
	LPOCNCONNPROCA lpfnConnect;
	LPOCNCHKPROC lpfnCheck;
	LPOCNDSCPROC lpfnDisconnect;
	SCARDHANDLE hCardHandle;
} OPENCARDNAMEA, *POPENCARDNAMEA, *LPOPENCARDNAMEA;

typedef struct
{
	DWORD dwStructSize;
	HWND hwndOwner;
	SCARDCONTEXT hSCardContext;
	LPWSTR lpstrGroupNames;
	DWORD nMaxGroupNames;
	LPWSTR lpstrCardNames;
	DWORD nMaxCardNames;
	LPCGUID rgguidInterfaces;
	DWORD cguidInterfaces;
	LPWSTR lpstrRdr;
	DWORD nMaxRdr;
	LPWSTR lpstrCard;
	DWORD nMaxCard;
	LPCWSTR lpstrTitle;
	DWORD dwFlags;
	LPVOID pvUserData;
	DWORD dwShareMode;
	DWORD dwPreferredProtocols;
	DWORD dwActiveProtocol;
	LPOCNCONNPROCW lpfnConnect;
	LPOCNCHKPROC lpfnCheck;
	LPOCNDSCPROC lpfnDisconnect;
	SCARDHANDLE hCardHandle;
} OPENCARDNAMEW, *POPENCARDNAMEW, *LPOPENCARDNAMEW;

#pragma pack(pop)

#ifdef UNICODE
#define LPOCNCONNPROC LPOCNCONNPROCW
#define SCARD_READERSTATE SCARD_READERSTATEW
#define PSCARD_READERSTATE PSCARD_READERSTATEW
#define LPSCARD_READERSTATE LPSCARD_READERSTATEW
#define OPENCARD_SEARCH_CRITERIA OPENCARD_SEARCH_CRITERIAW
#define LOPENCARD_SEARCH_CRITERIA LOPENCARD_SEARCH_CRITERIAW
#define LPOPENCARD_SEARCH_CRITERIA LPOPENCARD_SEARCH_CRITERIAW
#define OPENCARDNAME_EX OPENCARDNAME_EXW
#define LOPENCARDNAME_EX LOPENCARDNAME_EXW
#define LPOPENCARDNAME_EX LPOPENCARDNAME_EXW
#define OPENCARDNAME OPENCARDNAMEW
#define LOPENCARDNAME LOPENCARDNAMEW
#define LPOPENCARDNAME LPOPENCARDNAMEW
#else
#define LPOCNCONNPROC LPOCNCONNPROCA
#define SCARD_READERSTATE SCARD_READERSTATEA
#define PSCARD_READERSTATE PSCARD_READERSTATEA
#define LPSCARD_READERSTATE LPSCARD_READERSTATEA
#define OPENCARD_SEARCH_CRITERIA OPENCARD_SEARCH_CRITERIAA
#define LOPENCARD_SEARCH_CRITERIA LOPENCARD_SEARCH_CRITERIAA
#define LPOPENCARD_SEARCH_CRITERIA LPOPENCARD_SEARCH_CRITERIAA
#define OPENCARDNAME_EX OPENCARDNAME_EXA
#define LOPENCARDNAME_EX LOPENCARDNAME_EXA
#define LPOPENCARDNAME_EX LPOPENCARDNAME_EXA
#define OPENCARDNAME OPENCARDNAMEA
#define LOPENCARDNAME LOPENCARDNAMEA
#define LPOPENCARDNAME LPOPENCARDNAMEA
#endif

#ifdef __cplusplus
extern "C"
{
#endif

	WINPR_API extern const SCARD_IO_REQUEST g_rgSCardT0Pci;
	WINPR_API extern const SCARD_IO_REQUEST g_rgSCardT1Pci;
	WINPR_API extern const SCARD_IO_REQUEST g_rgSCardRawPci;

#define SCARD_PCI_T0 (&g_rgSCardT0Pci)
#define SCARD_PCI_T1 (&g_rgSCardT1Pci)
#define SCARD_PCI_RAW (&g_rgSCardRawPci)

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1,
	                                              LPCVOID pvReserved2, LPSCARDCONTEXT phContext);

	WINSCARDAPI LONG WINAPI SCardReleaseContext(SCARDCONTEXT hContext);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardIsValidContext(SCARDCONTEXT hContext);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardListReaderGroupsA(SCARDCONTEXT hContext, LPSTR mszGroups,
	                                               LPDWORD pcchGroups);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardListReaderGroupsW(SCARDCONTEXT hContext, LPWSTR mszGroups,
	                                               LPDWORD pcchGroups);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardListReadersA(SCARDCONTEXT hContext, LPCSTR mszGroups,
	                                          LPSTR mszReaders, LPDWORD pcchReaders);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardListReadersW(SCARDCONTEXT hContext, LPCWSTR mszGroups,
	                                          LPWSTR mszReaders, LPDWORD pcchReaders);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardListCardsA(SCARDCONTEXT hContext, LPCBYTE pbAtr,
	                                        LPCGUID rgquidInterfaces, DWORD cguidInterfaceCount,
	                                        CHAR* mszCards, LPDWORD pcchCards);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardListCardsW(SCARDCONTEXT hContext, LPCBYTE pbAtr,
	                                        LPCGUID rgquidInterfaces, DWORD cguidInterfaceCount,
	                                        WCHAR* mszCards, LPDWORD pcchCards);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardListInterfacesA(SCARDCONTEXT hContext, LPCSTR szCard,
	                                             LPGUID pguidInterfaces, LPDWORD pcguidInterfaces);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardListInterfacesW(SCARDCONTEXT hContext, LPCWSTR szCard,
	                                             LPGUID pguidInterfaces, LPDWORD pcguidInterfaces);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardGetProviderIdA(SCARDCONTEXT hContext, LPCSTR szCard,
	                                            LPGUID pguidProviderId);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardGetProviderIdW(SCARDCONTEXT hContext, LPCWSTR szCard,
	                                            LPGUID pguidProviderId);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardGetCardTypeProviderNameA(SCARDCONTEXT hContext, LPCSTR szCardName,
	                                                      DWORD dwProviderId, CHAR* szProvider,
	                                                      LPDWORD pcchProvider);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardGetCardTypeProviderNameW(SCARDCONTEXT hContext, LPCWSTR szCardName,
	                                                      DWORD dwProviderId, WCHAR* szProvider,
	                                                      LPDWORD pcchProvider);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardIntroduceReaderGroupA(SCARDCONTEXT hContext, LPCSTR szGroupName);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardIntroduceReaderGroupW(SCARDCONTEXT hContext, LPCWSTR szGroupName);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardForgetReaderGroupA(SCARDCONTEXT hContext, LPCSTR szGroupName);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardForgetReaderGroupW(SCARDCONTEXT hContext, LPCWSTR szGroupName);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardIntroduceReaderA(SCARDCONTEXT hContext, LPCSTR szReaderName,
	                                              LPCSTR szDeviceName);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardIntroduceReaderW(SCARDCONTEXT hContext, LPCWSTR szReaderName,
	                                              LPCWSTR szDeviceName);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardForgetReaderA(SCARDCONTEXT hContext, LPCSTR szReaderName);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardForgetReaderW(SCARDCONTEXT hContext, LPCWSTR szReaderName);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardAddReaderToGroupA(SCARDCONTEXT hContext, LPCSTR szReaderName,
	                                               LPCSTR szGroupName);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardAddReaderToGroupW(SCARDCONTEXT hContext, LPCWSTR szReaderName,
	                                               LPCWSTR szGroupName);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardRemoveReaderFromGroupA(SCARDCONTEXT hContext, LPCSTR szReaderName,
	                                                    LPCSTR szGroupName);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardRemoveReaderFromGroupW(SCARDCONTEXT hContext, LPCWSTR szReaderName,
	                                                    LPCWSTR szGroupName);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardIntroduceCardTypeA(SCARDCONTEXT hContext, LPCSTR szCardName,
	                                                LPCGUID pguidPrimaryProvider,
	                                                LPCGUID rgguidInterfaces,
	                                                DWORD dwInterfaceCount, LPCBYTE pbAtr,
	                                                LPCBYTE pbAtrMask, DWORD cbAtrLen);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardIntroduceCardTypeW(SCARDCONTEXT hContext, LPCWSTR szCardName,
	                                                LPCGUID pguidPrimaryProvider,
	                                                LPCGUID rgguidInterfaces,
	                                                DWORD dwInterfaceCount, LPCBYTE pbAtr,
	                                                LPCBYTE pbAtrMask, DWORD cbAtrLen);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardSetCardTypeProviderNameA(SCARDCONTEXT hContext, LPCSTR szCardName,
	                                                      DWORD dwProviderId, LPCSTR szProvider);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardSetCardTypeProviderNameW(SCARDCONTEXT hContext, LPCWSTR szCardName,
	                                                      DWORD dwProviderId, LPCWSTR szProvider);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardForgetCardTypeA(SCARDCONTEXT hContext, LPCSTR szCardName);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardForgetCardTypeW(SCARDCONTEXT hContext, LPCWSTR szCardName);

	WINSCARDAPI LONG WINAPI SCardFreeMemory(SCARDCONTEXT hContext, LPVOID pvMem);

	WINSCARDAPI HANDLE WINAPI SCardAccessStartedEvent(void);

	WINSCARDAPI void WINAPI SCardReleaseStartedEvent(void);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardLocateCardsA(SCARDCONTEXT hContext, LPCSTR mszCards,
	                                          LPSCARD_READERSTATEA rgReaderStates, DWORD cReaders);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardLocateCardsW(SCARDCONTEXT hContext, LPCWSTR mszCards,
	                                          LPSCARD_READERSTATEW rgReaderStates, DWORD cReaders);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardLocateCardsByATRA(SCARDCONTEXT hContext,
	                                               LPSCARD_ATRMASK rgAtrMasks, DWORD cAtrs,
	                                               LPSCARD_READERSTATEA rgReaderStates,
	                                               DWORD cReaders);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardLocateCardsByATRW(SCARDCONTEXT hContext,
	                                               LPSCARD_ATRMASK rgAtrMasks, DWORD cAtrs,
	                                               LPSCARD_READERSTATEW rgReaderStates,
	                                               DWORD cReaders);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardGetStatusChangeA(SCARDCONTEXT hContext, DWORD dwTimeout,
	                                              LPSCARD_READERSTATEA rgReaderStates,
	                                              DWORD cReaders);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardGetStatusChangeW(SCARDCONTEXT hContext, DWORD dwTimeout,
	                                              LPSCARD_READERSTATEW rgReaderStates,
	                                              DWORD cReaders);

	WINSCARDAPI LONG WINAPI SCardCancel(SCARDCONTEXT hContext);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardConnectA(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode,
	                                      DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
	                                      LPDWORD pdwActiveProtocol);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardConnectW(SCARDCONTEXT hContext, LPCWSTR szReader,
	                                      DWORD dwShareMode, DWORD dwPreferredProtocols,
	                                      LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode,
	                                       DWORD dwPreferredProtocols, DWORD dwInitialization,
	                                       LPDWORD pdwActiveProtocol);

	WINSCARDAPI LONG WINAPI SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardBeginTransaction(SCARDHANDLE hCard);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardCancelTransaction(SCARDHANDLE hCard);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardState(SCARDHANDLE hCard, LPDWORD pdwState, LPDWORD pdwProtocol,
	                                   LPBYTE pbAtr, LPDWORD pcbAtrLen);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardStatusA(SCARDHANDLE hCard, LPSTR mszReaderNames,
	                                     LPDWORD pcchReaderLen, LPDWORD pdwState,
	                                     LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardStatusW(SCARDHANDLE hCard, LPWSTR mszReaderNames,
	                                     LPDWORD pcchReaderLen, LPDWORD pdwState,
	                                     LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardTransmit(SCARDHANDLE hCard, LPCSCARD_IO_REQUEST pioSendPci,
	                                      LPCBYTE pbSendBuffer, DWORD cbSendLength,
	                                      LPSCARD_IO_REQUEST pioRecvPci, LPBYTE pbRecvBuffer,
	                                      LPDWORD pcbRecvLength);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardGetTransmitCount(SCARDHANDLE hCard, LPDWORD pcTransmitCount);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID lpInBuffer,
	                                     DWORD cbInBufferSize, LPVOID lpOutBuffer,
	                                     DWORD cbOutBufferSize, LPDWORD lpBytesReturned);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr,
	                                       LPDWORD pcbAttrLen);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr,
	                                       DWORD cbAttrLen);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardUIDlgSelectCardA(LPOPENCARDNAMEA_EX pDlgStruc);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardUIDlgSelectCardW(LPOPENCARDNAMEW_EX pDlgStruc);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI GetOpenCardNameA(LPOPENCARDNAMEA pDlgStruc);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI GetOpenCardNameW(LPOPENCARDNAMEW pDlgStruc);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardDlgExtendedError(void);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardReadCacheA(SCARDCONTEXT hContext, UUID* CardIdentifier,
	                                        DWORD FreshnessCounter, LPSTR LookupName, PBYTE Data,
	                                        DWORD* DataLen);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardReadCacheW(SCARDCONTEXT hContext, UUID* CardIdentifier,
	                                        DWORD FreshnessCounter, LPWSTR LookupName, PBYTE Data,
	                                        DWORD* DataLen);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardWriteCacheA(SCARDCONTEXT hContext, UUID* CardIdentifier,
	                                         DWORD FreshnessCounter, LPSTR LookupName, PBYTE Data,
	                                         DWORD DataLen);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardWriteCacheW(SCARDCONTEXT hContext, UUID* CardIdentifier,
	                                         DWORD FreshnessCounter, LPWSTR LookupName, PBYTE Data,
	                                         DWORD DataLen);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardGetReaderIconA(SCARDCONTEXT hContext, LPCSTR szReaderName,
	                                            LPBYTE pbIcon, LPDWORD pcbIcon);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardGetReaderIconW(SCARDCONTEXT hContext, LPCWSTR szReaderName,
	                                            LPBYTE pbIcon, LPDWORD pcbIcon);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardGetDeviceTypeIdA(SCARDCONTEXT hContext, LPCSTR szReaderName,
	                                              LPDWORD pdwDeviceTypeId);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardGetDeviceTypeIdW(SCARDCONTEXT hContext, LPCWSTR szReaderName,
	                                              LPDWORD pdwDeviceTypeId);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardGetReaderDeviceInstanceIdA(SCARDCONTEXT hContext,
	                                                        LPCSTR szReaderName,
	                                                        LPSTR szDeviceInstanceId,
	                                                        LPDWORD pcchDeviceInstanceId);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardGetReaderDeviceInstanceIdW(SCARDCONTEXT hContext,
	                                                        LPCWSTR szReaderName,
	                                                        LPWSTR szDeviceInstanceId,
	                                                        LPDWORD pcchDeviceInstanceId);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardListReadersWithDeviceInstanceIdA(SCARDCONTEXT hContext,
	                                                              LPCSTR szDeviceInstanceId,
	                                                              LPSTR mszReaders,
	                                                              LPDWORD pcchReaders);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardListReadersWithDeviceInstanceIdW(SCARDCONTEXT hContext,
	                                                              LPCWSTR szDeviceInstanceId,
	                                                              LPWSTR mszReaders,
	                                                              LPDWORD pcchReaders);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI LONG WINAPI SCardAudit(SCARDCONTEXT hContext, DWORD dwEvent);

#ifdef UNICODE
#define SCardListReaderGroups SCardListReaderGroupsW
#define SCardListReaders SCardListReadersW
#define SCardListCards SCardListCardsW
#define SCardListInterfaces SCardListInterfacesW
#define SCardGetProviderId SCardGetProviderIdW
#define SCardGetCardTypeProviderName SCardGetCardTypeProviderNameW
#define SCardIntroduceReaderGroup SCardIntroduceReaderGroupW
#define SCardForgetReaderGroup SCardForgetReaderGroupW
#define SCardIntroduceReader SCardIntroduceReaderW
#define SCardForgetReader SCardForgetReaderW
#define SCardAddReaderToGroup SCardAddReaderToGroupW
#define SCardRemoveReaderFromGroup SCardRemoveReaderFromGroupW
#define SCardIntroduceCardType SCardIntroduceCardTypeW
#define SCardSetCardTypeProviderName SCardSetCardTypeProviderNameW
#define SCardForgetCardType SCardForgetCardTypeW
#define SCardLocateCards SCardLocateCardsW
#define SCardLocateCardsByATR SCardLocateCardsByATRW
#define SCardGetStatusChange SCardGetStatusChangeW
#define SCardConnect SCardConnectW
#define SCardStatus SCardStatusW
#define SCardUIDlgSelectCard SCardUIDlgSelectCardW
#define GetOpenCardName GetOpenCardNameW
#define SCardReadCache SCardReadCacheW
#define SCardWriteCache SCardWriteCacheW
#define SCardGetReaderIcon SCardGetReaderIconW
#define SCardGetDeviceTypeId SCardGetDeviceTypeIdW
#define SCardGetReaderDeviceInstanceId SCardGetReaderDeviceInstanceIdW
#define SCardListReadersWithDeviceInstanceId SCardListReadersWithDeviceInstanceIdW
#else
#define SCardListReaderGroups SCardListReaderGroupsA
#define SCardListReaders SCardListReadersA
#define SCardListCards SCardListCardsA
#define SCardListInterfaces SCardListInterfacesA
#define SCardGetProviderId SCardGetProviderIdA
#define SCardGetCardTypeProviderName SCardGetCardTypeProviderNameA
#define SCardIntroduceReaderGroup SCardIntroduceReaderGroupA
#define SCardForgetReaderGroup SCardForgetReaderGroupA
#define SCardIntroduceReader SCardIntroduceReaderA
#define SCardForgetReader SCardForgetReaderA
#define SCardAddReaderToGroup SCardAddReaderToGroupA
#define SCardRemoveReaderFromGroup SCardRemoveReaderFromGroupA
#define SCardIntroduceCardType SCardIntroduceCardTypeA
#define SCardSetCardTypeProviderName SCardSetCardTypeProviderNameA
#define SCardForgetCardType SCardForgetCardTypeA
#define SCardLocateCards SCardLocateCardsA
#define SCardLocateCardsByATR SCardLocateCardsByATRA
#define SCardGetStatusChange SCardGetStatusChangeA
#define SCardConnect SCardConnectA
#define SCardStatus SCardStatusA
#define SCardUIDlgSelectCard SCardUIDlgSelectCardA
#define GetOpenCardName GetOpenCardNameA
#define SCardReadCache SCardReadCacheA
#define SCardWriteCache SCardWriteCacheA
#define SCardGetReaderIcon SCardGetReaderIconA
#define SCardGetDeviceTypeId SCardGetDeviceTypeIdA
#define SCardGetReaderDeviceInstanceId SCardGetReaderDeviceInstanceIdA
#define SCardListReadersWithDeviceInstanceId SCardListReadersWithDeviceInstanceIdA
#endif

#ifdef __cplusplus
}
#endif

/**
 * Extended API
 */

typedef LONG(WINAPI* fnSCardEstablishContext)(DWORD dwScope, LPCVOID pvReserved1,
                                              LPCVOID pvReserved2, LPSCARDCONTEXT phContext);

typedef LONG(WINAPI* fnSCardReleaseContext)(SCARDCONTEXT hContext);

typedef LONG(WINAPI* fnSCardIsValidContext)(SCARDCONTEXT hContext);

typedef LONG(WINAPI* fnSCardListReaderGroupsA)(SCARDCONTEXT hContext, LPSTR mszGroups,
                                               LPDWORD pcchGroups);
typedef LONG(WINAPI* fnSCardListReaderGroupsW)(SCARDCONTEXT hContext, LPWSTR mszGroups,
                                               LPDWORD pcchGroups);

typedef LONG(WINAPI* fnSCardListReadersA)(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders,
                                          LPDWORD pcchReaders);
typedef LONG(WINAPI* fnSCardListReadersW)(SCARDCONTEXT hContext, LPCWSTR mszGroups,
                                          LPWSTR mszReaders, LPDWORD pcchReaders);

typedef LONG(WINAPI* fnSCardListCardsA)(SCARDCONTEXT hContext, LPCBYTE pbAtr,
                                        LPCGUID rgquidInterfaces, DWORD cguidInterfaceCount,
                                        CHAR* mszCards, LPDWORD pcchCards);

typedef LONG(WINAPI* fnSCardListCardsW)(SCARDCONTEXT hContext, LPCBYTE pbAtr,
                                        LPCGUID rgquidInterfaces, DWORD cguidInterfaceCount,
                                        WCHAR* mszCards, LPDWORD pcchCards);

typedef LONG(WINAPI* fnSCardListInterfacesA)(SCARDCONTEXT hContext, LPCSTR szCard,
                                             LPGUID pguidInterfaces, LPDWORD pcguidInterfaces);
typedef LONG(WINAPI* fnSCardListInterfacesW)(SCARDCONTEXT hContext, LPCWSTR szCard,
                                             LPGUID pguidInterfaces, LPDWORD pcguidInterfaces);

typedef LONG(WINAPI* fnSCardGetProviderIdA)(SCARDCONTEXT hContext, LPCSTR szCard,
                                            LPGUID pguidProviderId);
typedef LONG(WINAPI* fnSCardGetProviderIdW)(SCARDCONTEXT hContext, LPCWSTR szCard,
                                            LPGUID pguidProviderId);

typedef LONG(WINAPI* fnSCardGetCardTypeProviderNameA)(SCARDCONTEXT hContext, LPCSTR szCardName,
                                                      DWORD dwProviderId, CHAR* szProvider,
                                                      LPDWORD pcchProvider);
typedef LONG(WINAPI* fnSCardGetCardTypeProviderNameW)(SCARDCONTEXT hContext, LPCWSTR szCardName,
                                                      DWORD dwProviderId, WCHAR* szProvider,
                                                      LPDWORD pcchProvider);

typedef LONG(WINAPI* fnSCardIntroduceReaderGroupA)(SCARDCONTEXT hContext, LPCSTR szGroupName);
typedef LONG(WINAPI* fnSCardIntroduceReaderGroupW)(SCARDCONTEXT hContext, LPCWSTR szGroupName);

typedef LONG(WINAPI* fnSCardForgetReaderGroupA)(SCARDCONTEXT hContext, LPCSTR szGroupName);
typedef LONG(WINAPI* fnSCardForgetReaderGroupW)(SCARDCONTEXT hContext, LPCWSTR szGroupName);

typedef LONG(WINAPI* fnSCardIntroduceReaderA)(SCARDCONTEXT hContext, LPCSTR szReaderName,
                                              LPCSTR szDeviceName);
typedef LONG(WINAPI* fnSCardIntroduceReaderW)(SCARDCONTEXT hContext, LPCWSTR szReaderName,
                                              LPCWSTR szDeviceName);

typedef LONG(WINAPI* fnSCardForgetReaderA)(SCARDCONTEXT hContext, LPCSTR szReaderName);
typedef LONG(WINAPI* fnSCardForgetReaderW)(SCARDCONTEXT hContext, LPCWSTR szReaderName);

typedef LONG(WINAPI* fnSCardAddReaderToGroupA)(SCARDCONTEXT hContext, LPCSTR szReaderName,
                                               LPCSTR szGroupName);
typedef LONG(WINAPI* fnSCardAddReaderToGroupW)(SCARDCONTEXT hContext, LPCWSTR szReaderName,
                                               LPCWSTR szGroupName);

typedef LONG(WINAPI* fnSCardRemoveReaderFromGroupA)(SCARDCONTEXT hContext, LPCSTR szReaderName,
                                                    LPCSTR szGroupName);
typedef LONG(WINAPI* fnSCardRemoveReaderFromGroupW)(SCARDCONTEXT hContext, LPCWSTR szReaderName,
                                                    LPCWSTR szGroupName);

typedef LONG(WINAPI* fnSCardIntroduceCardTypeA)(SCARDCONTEXT hContext, LPCSTR szCardName,
                                                LPCGUID pguidPrimaryProvider,
                                                LPCGUID rgguidInterfaces, DWORD dwInterfaceCount,
                                                LPCBYTE pbAtr, LPCBYTE pbAtrMask, DWORD cbAtrLen);
typedef LONG(WINAPI* fnSCardIntroduceCardTypeW)(SCARDCONTEXT hContext, LPCWSTR szCardName,
                                                LPCGUID pguidPrimaryProvider,
                                                LPCGUID rgguidInterfaces, DWORD dwInterfaceCount,
                                                LPCBYTE pbAtr, LPCBYTE pbAtrMask, DWORD cbAtrLen);

typedef LONG(WINAPI* fnSCardSetCardTypeProviderNameA)(SCARDCONTEXT hContext, LPCSTR szCardName,
                                                      DWORD dwProviderId, LPCSTR szProvider);
typedef LONG(WINAPI* fnSCardSetCardTypeProviderNameW)(SCARDCONTEXT hContext, LPCWSTR szCardName,
                                                      DWORD dwProviderId, LPCWSTR szProvider);

typedef LONG(WINAPI* fnSCardForgetCardTypeA)(SCARDCONTEXT hContext, LPCSTR szCardName);
typedef LONG(WINAPI* fnSCardForgetCardTypeW)(SCARDCONTEXT hContext, LPCWSTR szCardName);

typedef LONG(WINAPI* fnSCardFreeMemory)(SCARDCONTEXT hContext, LPVOID pvMem);

typedef HANDLE(WINAPI* fnSCardAccessStartedEvent)(void);

typedef void(WINAPI* fnSCardReleaseStartedEvent)(void);

typedef LONG(WINAPI* fnSCardLocateCardsA)(SCARDCONTEXT hContext, LPCSTR mszCards,
                                          LPSCARD_READERSTATEA rgReaderStates, DWORD cReaders);
typedef LONG(WINAPI* fnSCardLocateCardsW)(SCARDCONTEXT hContext, LPCWSTR mszCards,
                                          LPSCARD_READERSTATEW rgReaderStates, DWORD cReaders);

typedef LONG(WINAPI* fnSCardLocateCardsByATRA)(SCARDCONTEXT hContext, LPSCARD_ATRMASK rgAtrMasks,
                                               DWORD cAtrs, LPSCARD_READERSTATEA rgReaderStates,
                                               DWORD cReaders);
typedef LONG(WINAPI* fnSCardLocateCardsByATRW)(SCARDCONTEXT hContext, LPSCARD_ATRMASK rgAtrMasks,
                                               DWORD cAtrs, LPSCARD_READERSTATEW rgReaderStates,
                                               DWORD cReaders);

typedef LONG(WINAPI* fnSCardGetStatusChangeA)(SCARDCONTEXT hContext, DWORD dwTimeout,
                                              LPSCARD_READERSTATEA rgReaderStates, DWORD cReaders);
typedef LONG(WINAPI* fnSCardGetStatusChangeW)(SCARDCONTEXT hContext, DWORD dwTimeout,
                                              LPSCARD_READERSTATEW rgReaderStates, DWORD cReaders);

typedef LONG(WINAPI* fnSCardCancel)(SCARDCONTEXT hContext);

typedef LONG(WINAPI* fnSCardConnectA)(SCARDCONTEXT hContext, LPCSTR szReader, DWORD dwShareMode,
                                      DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
                                      LPDWORD pdwActiveProtocol);
typedef LONG(WINAPI* fnSCardConnectW)(SCARDCONTEXT hContext, LPCWSTR szReader, DWORD dwShareMode,
                                      DWORD dwPreferredProtocols, LPSCARDHANDLE phCard,
                                      LPDWORD pdwActiveProtocol);

typedef LONG(WINAPI* fnSCardReconnect)(SCARDHANDLE hCard, DWORD dwShareMode,
                                       DWORD dwPreferredProtocols, DWORD dwInitialization,
                                       LPDWORD pdwActiveProtocol);

typedef LONG(WINAPI* fnSCardDisconnect)(SCARDHANDLE hCard, DWORD dwDisposition);

typedef LONG(WINAPI* fnSCardBeginTransaction)(SCARDHANDLE hCard);

typedef LONG(WINAPI* fnSCardEndTransaction)(SCARDHANDLE hCard, DWORD dwDisposition);

typedef LONG(WINAPI* fnSCardCancelTransaction)(SCARDHANDLE hCard);

typedef LONG(WINAPI* fnSCardState)(SCARDHANDLE hCard, LPDWORD pdwState, LPDWORD pdwProtocol,
                                   LPBYTE pbAtr, LPDWORD pcbAtrLen);

typedef LONG(WINAPI* fnSCardStatusA)(SCARDHANDLE hCard, LPSTR mszReaderNames, LPDWORD pcchReaderLen,
                                     LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr,
                                     LPDWORD pcbAtrLen);
typedef LONG(WINAPI* fnSCardStatusW)(SCARDHANDLE hCard, LPWSTR mszReaderNames,
                                     LPDWORD pcchReaderLen, LPDWORD pdwState, LPDWORD pdwProtocol,
                                     LPBYTE pbAtr, LPDWORD pcbAtrLen);

typedef LONG(WINAPI* fnSCardTransmit)(SCARDHANDLE hCard, LPCSCARD_IO_REQUEST pioSendPci,
                                      LPCBYTE pbSendBuffer, DWORD cbSendLength,
                                      LPSCARD_IO_REQUEST pioRecvPci, LPBYTE pbRecvBuffer,
                                      LPDWORD pcbRecvLength);

typedef LONG(WINAPI* fnSCardGetTransmitCount)(SCARDHANDLE hCard, LPDWORD pcTransmitCount);

typedef LONG(WINAPI* fnSCardControl)(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID lpInBuffer,
                                     DWORD cbInBufferSize, LPVOID lpOutBuffer,
                                     DWORD cbOutBufferSize, LPDWORD lpBytesReturned);

typedef LONG(WINAPI* fnSCardGetAttrib)(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr,
                                       LPDWORD pcbAttrLen);

typedef LONG(WINAPI* fnSCardSetAttrib)(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr,
                                       DWORD cbAttrLen);

typedef LONG(WINAPI* fnSCardUIDlgSelectCardA)(LPOPENCARDNAMEA_EX pDlgStruc);
typedef LONG(WINAPI* fnSCardUIDlgSelectCardW)(LPOPENCARDNAMEW_EX pDlgStruc);

typedef LONG(WINAPI* fnGetOpenCardNameA)(LPOPENCARDNAMEA pDlgStruc);
typedef LONG(WINAPI* fnGetOpenCardNameW)(LPOPENCARDNAMEW pDlgStruc);

typedef LONG(WINAPI* fnSCardDlgExtendedError)(void);

typedef LONG(WINAPI* fnSCardReadCacheA)(SCARDCONTEXT hContext, UUID* CardIdentifier,
                                        DWORD FreshnessCounter, LPSTR LookupName, PBYTE Data,
                                        DWORD* DataLen);
typedef LONG(WINAPI* fnSCardReadCacheW)(SCARDCONTEXT hContext, UUID* CardIdentifier,
                                        DWORD FreshnessCounter, LPWSTR LookupName, PBYTE Data,
                                        DWORD* DataLen);

typedef LONG(WINAPI* fnSCardWriteCacheA)(SCARDCONTEXT hContext, UUID* CardIdentifier,
                                         DWORD FreshnessCounter, LPSTR LookupName, PBYTE Data,
                                         DWORD DataLen);
typedef LONG(WINAPI* fnSCardWriteCacheW)(SCARDCONTEXT hContext, UUID* CardIdentifier,
                                         DWORD FreshnessCounter, LPWSTR LookupName, PBYTE Data,
                                         DWORD DataLen);

typedef LONG(WINAPI* fnSCardGetReaderIconA)(SCARDCONTEXT hContext, LPCSTR szReaderName,
                                            LPBYTE pbIcon, LPDWORD pcbIcon);
typedef LONG(WINAPI* fnSCardGetReaderIconW)(SCARDCONTEXT hContext, LPCWSTR szReaderName,
                                            LPBYTE pbIcon, LPDWORD pcbIcon);

typedef LONG(WINAPI* fnSCardGetDeviceTypeIdA)(SCARDCONTEXT hContext, LPCSTR szReaderName,
                                              LPDWORD pdwDeviceTypeId);
typedef LONG(WINAPI* fnSCardGetDeviceTypeIdW)(SCARDCONTEXT hContext, LPCWSTR szReaderName,
                                              LPDWORD pdwDeviceTypeId);

typedef LONG(WINAPI* fnSCardGetReaderDeviceInstanceIdA)(SCARDCONTEXT hContext, LPCSTR szReaderName,
                                                        LPSTR szDeviceInstanceId,
                                                        LPDWORD pcchDeviceInstanceId);
typedef LONG(WINAPI* fnSCardGetReaderDeviceInstanceIdW)(SCARDCONTEXT hContext, LPCWSTR szReaderName,
                                                        LPWSTR szDeviceInstanceId,
                                                        LPDWORD pcchDeviceInstanceId);

typedef LONG(WINAPI* fnSCardListReadersWithDeviceInstanceIdA)(SCARDCONTEXT hContext,
                                                              LPCSTR szDeviceInstanceId,
                                                              LPSTR mszReaders,
                                                              LPDWORD pcchReaders);
typedef LONG(WINAPI* fnSCardListReadersWithDeviceInstanceIdW)(SCARDCONTEXT hContext,
                                                              LPCWSTR szDeviceInstanceId,
                                                              LPWSTR mszReaders,
                                                              LPDWORD pcchReaders);

typedef LONG(WINAPI* fnSCardAudit)(SCARDCONTEXT hContext, DWORD dwEvent);

typedef struct
{
	DWORD dwVersion;
	DWORD dwFlags;

	WINPR_ATTR_NODISCARD fnSCardEstablishContext pfnSCardEstablishContext;
	WINPR_ATTR_NODISCARD fnSCardReleaseContext pfnSCardReleaseContext;
	WINPR_ATTR_NODISCARD fnSCardIsValidContext pfnSCardIsValidContext;
	WINPR_ATTR_NODISCARD fnSCardListReaderGroupsA pfnSCardListReaderGroupsA;
	WINPR_ATTR_NODISCARD fnSCardListReaderGroupsW pfnSCardListReaderGroupsW;
	WINPR_ATTR_NODISCARD fnSCardListReadersA pfnSCardListReadersA;
	WINPR_ATTR_NODISCARD fnSCardListReadersW pfnSCardListReadersW;
	WINPR_ATTR_NODISCARD fnSCardListCardsA pfnSCardListCardsA;
	WINPR_ATTR_NODISCARD fnSCardListCardsW pfnSCardListCardsW;
	WINPR_ATTR_NODISCARD fnSCardListInterfacesA pfnSCardListInterfacesA;
	WINPR_ATTR_NODISCARD fnSCardListInterfacesW pfnSCardListInterfacesW;
	WINPR_ATTR_NODISCARD fnSCardGetProviderIdA pfnSCardGetProviderIdA;
	WINPR_ATTR_NODISCARD fnSCardGetProviderIdW pfnSCardGetProviderIdW;
	WINPR_ATTR_NODISCARD fnSCardGetCardTypeProviderNameA pfnSCardGetCardTypeProviderNameA;
	WINPR_ATTR_NODISCARD fnSCardGetCardTypeProviderNameW pfnSCardGetCardTypeProviderNameW;
	WINPR_ATTR_NODISCARD fnSCardIntroduceReaderGroupA pfnSCardIntroduceReaderGroupA;
	WINPR_ATTR_NODISCARD fnSCardIntroduceReaderGroupW pfnSCardIntroduceReaderGroupW;
	WINPR_ATTR_NODISCARD fnSCardForgetReaderGroupA pfnSCardForgetReaderGroupA;
	WINPR_ATTR_NODISCARD fnSCardForgetReaderGroupW pfnSCardForgetReaderGroupW;
	WINPR_ATTR_NODISCARD fnSCardIntroduceReaderA pfnSCardIntroduceReaderA;
	WINPR_ATTR_NODISCARD fnSCardIntroduceReaderW pfnSCardIntroduceReaderW;
	WINPR_ATTR_NODISCARD fnSCardForgetReaderA pfnSCardForgetReaderA;
	WINPR_ATTR_NODISCARD fnSCardForgetReaderW pfnSCardForgetReaderW;
	WINPR_ATTR_NODISCARD fnSCardAddReaderToGroupA pfnSCardAddReaderToGroupA;
	WINPR_ATTR_NODISCARD fnSCardAddReaderToGroupW pfnSCardAddReaderToGroupW;
	WINPR_ATTR_NODISCARD fnSCardRemoveReaderFromGroupA pfnSCardRemoveReaderFromGroupA;
	WINPR_ATTR_NODISCARD fnSCardRemoveReaderFromGroupW pfnSCardRemoveReaderFromGroupW;
	WINPR_ATTR_NODISCARD fnSCardIntroduceCardTypeA pfnSCardIntroduceCardTypeA;
	WINPR_ATTR_NODISCARD fnSCardIntroduceCardTypeW pfnSCardIntroduceCardTypeW;
	WINPR_ATTR_NODISCARD fnSCardSetCardTypeProviderNameA pfnSCardSetCardTypeProviderNameA;
	WINPR_ATTR_NODISCARD fnSCardSetCardTypeProviderNameW pfnSCardSetCardTypeProviderNameW;
	WINPR_ATTR_NODISCARD fnSCardForgetCardTypeA pfnSCardForgetCardTypeA;
	WINPR_ATTR_NODISCARD fnSCardForgetCardTypeW pfnSCardForgetCardTypeW;
	fnSCardFreeMemory pfnSCardFreeMemory;
	WINPR_ATTR_NODISCARD fnSCardAccessStartedEvent pfnSCardAccessStartedEvent;
	fnSCardReleaseStartedEvent pfnSCardReleaseStartedEvent;
	WINPR_ATTR_NODISCARD fnSCardLocateCardsA pfnSCardLocateCardsA;
	WINPR_ATTR_NODISCARD fnSCardLocateCardsW pfnSCardLocateCardsW;
	WINPR_ATTR_NODISCARD fnSCardLocateCardsByATRA pfnSCardLocateCardsByATRA;
	WINPR_ATTR_NODISCARD fnSCardLocateCardsByATRW pfnSCardLocateCardsByATRW;
	WINPR_ATTR_NODISCARD fnSCardGetStatusChangeA pfnSCardGetStatusChangeA;
	WINPR_ATTR_NODISCARD fnSCardGetStatusChangeW pfnSCardGetStatusChangeW;
	fnSCardCancel pfnSCardCancel;
	WINPR_ATTR_NODISCARD fnSCardConnectA pfnSCardConnectA;
	WINPR_ATTR_NODISCARD fnSCardConnectW pfnSCardConnectW;
	WINPR_ATTR_NODISCARD fnSCardReconnect pfnSCardReconnect;
	WINPR_ATTR_NODISCARD fnSCardDisconnect pfnSCardDisconnect;
	WINPR_ATTR_NODISCARD fnSCardBeginTransaction pfnSCardBeginTransaction;
	WINPR_ATTR_NODISCARD fnSCardEndTransaction pfnSCardEndTransaction;
	fnSCardCancelTransaction pfnSCardCancelTransaction;
	WINPR_ATTR_NODISCARD fnSCardState pfnSCardState;
	WINPR_ATTR_NODISCARD fnSCardStatusA pfnSCardStatusA;
	WINPR_ATTR_NODISCARD fnSCardStatusW pfnSCardStatusW;
	WINPR_ATTR_NODISCARD fnSCardTransmit pfnSCardTransmit;
	WINPR_ATTR_NODISCARD fnSCardGetTransmitCount pfnSCardGetTransmitCount;
	WINPR_ATTR_NODISCARD fnSCardControl pfnSCardControl;
	WINPR_ATTR_NODISCARD fnSCardGetAttrib pfnSCardGetAttrib;
	WINPR_ATTR_NODISCARD fnSCardSetAttrib pfnSCardSetAttrib;
	WINPR_ATTR_NODISCARD fnSCardUIDlgSelectCardA pfnSCardUIDlgSelectCardA;
	WINPR_ATTR_NODISCARD fnSCardUIDlgSelectCardW pfnSCardUIDlgSelectCardW;
	WINPR_ATTR_NODISCARD fnGetOpenCardNameA pfnGetOpenCardNameA;
	WINPR_ATTR_NODISCARD fnGetOpenCardNameW pfnGetOpenCardNameW;
	WINPR_ATTR_NODISCARD fnSCardDlgExtendedError pfnSCardDlgExtendedError;
	WINPR_ATTR_NODISCARD fnSCardReadCacheA pfnSCardReadCacheA;
	WINPR_ATTR_NODISCARD fnSCardReadCacheW pfnSCardReadCacheW;
	WINPR_ATTR_NODISCARD fnSCardWriteCacheA pfnSCardWriteCacheA;
	WINPR_ATTR_NODISCARD fnSCardWriteCacheW pfnSCardWriteCacheW;
	WINPR_ATTR_NODISCARD fnSCardGetReaderIconA pfnSCardGetReaderIconA;
	WINPR_ATTR_NODISCARD fnSCardGetReaderIconW pfnSCardGetReaderIconW;
	WINPR_ATTR_NODISCARD fnSCardGetDeviceTypeIdA pfnSCardGetDeviceTypeIdA;
	WINPR_ATTR_NODISCARD fnSCardGetDeviceTypeIdW pfnSCardGetDeviceTypeIdW;
	WINPR_ATTR_NODISCARD fnSCardGetReaderDeviceInstanceIdA pfnSCardGetReaderDeviceInstanceIdA;
	WINPR_ATTR_NODISCARD fnSCardGetReaderDeviceInstanceIdW pfnSCardGetReaderDeviceInstanceIdW;
	WINPR_ATTR_NODISCARD fnSCardListReadersWithDeviceInstanceIdA
	    pfnSCardListReadersWithDeviceInstanceIdA;
	WINPR_ATTR_NODISCARD fnSCardListReadersWithDeviceInstanceIdW
	    pfnSCardListReadersWithDeviceInstanceIdW;
	WINPR_ATTR_NODISCARD fnSCardAudit pfnSCardAudit;
} SCardApiFunctionTable;
typedef SCardApiFunctionTable* PSCardApiFunctionTable;

#ifdef __cplusplus
extern "C"
{
#endif

	WINPR_ATTR_NODISCARD
	WINSCARDAPI const char* WINAPI SCardGetErrorString(LONG errorCode);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI const char* WINAPI SCardGetAttributeString(DWORD dwAttrId);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI const char* WINAPI SCardGetProtocolString(DWORD dwProtocols);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI const char* WINAPI SCardGetShareModeString(DWORD dwShareMode);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI const char* WINAPI SCardGetDispositionString(DWORD dwDisposition);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI const char* WINAPI SCardGetScopeString(DWORD dwScope);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI const char* WINAPI SCardGetCardStateString(DWORD dwCardState);

	WINPR_ATTR_NODISCARD
	WINSCARDAPI char* WINAPI SCardGetReaderStateString(DWORD dwReaderState);

	WINPR_ATTR_NODISCARD
	WINPR_API BOOL WinSCard_LoadApiTableFunctions(PSCardApiFunctionTable pWinSCardApiTable,
	                                              HMODULE hWinSCardLibrary);

	WINPR_ATTR_NODISCARD
	WINPR_API const SCardApiFunctionTable* WinPR_GetSCardApiFunctionTable(void);

#ifdef __cplusplus
}
#endif

#endif /* WINPR_SMARTCARD_H */
