based on libpcsclite1 \ rework of [original code by Mounir IDRASSI](https://sourceforge.net/projects/scard4wine/) to use unixlib interface
First step to resolve \ Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=39113 \ Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=37495 \ It will probably also require the implementation of scarddlg.
In order for the tests to work fully in a virtual environment without the appropriate hardware, I suggest using the project https://github.com/Jakuje/virt_cacard
Example for setting up a build server (It is supposed to be Debian): ``` apt-get install -y pcscd vsmartcard-vpcd libpcsclite1 libpcsclite-dev libcacard-dev libsofthsm2 libnss3-tools gnutls-bin opensc service pcscd restart git clone https://github.com/Jakuje/virt_cacard cd virt_cacard ./autogen.sh && ./configure && make ./setup-softhsm2.sh ``` "Insert" smartcard before runing tests: \ `cd /path/to/virt_cacard && SOFTHSM2_CONF=softhsm2.conf ./virt_cacard &`
Partial test can be done if installed vsmartcard-vpcd (only test create/release context and list aviable card readers): \ ``` apt-get install -y pcscd vsmartcard-vpcd service pcscd restart ```
From: Konstantin Romanov incubusrk@gmail.com
based on libpcsclite rework of original code by Mounir IDRASSI to use unixlib interface
Related to Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=39113 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=37495 Also required to implement scarddlg --- dlls/winscard/Makefile.in | 7 +- dlls/winscard/unixlib.c | 315 ++++++ dlls/winscard/unixlib.h | 262 +++++ dlls/winscard/winscard.c | 1905 +++++++++++++++++++++++++++++++++-- dlls/winscard/winscard.spec | 100 +- include/winscard.h | 29 +- include/winsmcrd.h | 123 ++- 7 files changed, 2584 insertions(+), 157 deletions(-) create mode 100644 dlls/winscard/unixlib.c create mode 100644 dlls/winscard/unixlib.h
diff --git a/dlls/winscard/Makefile.in b/dlls/winscard/Makefile.in index 89449698b66..cd1f88c8907 100644 --- a/dlls/winscard/Makefile.in +++ b/dlls/winscard/Makefile.in @@ -1,8 +1,11 @@ MODULE = winscard.dll +UNIXLIB = winscard.so IMPORTLIB = winscard +IMPORTS = ntdll
C_SRCS = \ - winscard.c + winscard.c\ + unixlib.c
RC_SRCS = \ - rsrc.rc + rsrc.rc \ No newline at end of file diff --git a/dlls/winscard/unixlib.c b/dlls/winscard/unixlib.c new file mode 100644 index 00000000000..1abd0664584 --- /dev/null +++ b/dlls/winscard/unixlib.c @@ -0,0 +1,315 @@ +/* + * WinScard Unix library + * + * Copyright (C) 2023 Konstantin Romanov + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * + */ + +#if 0 +#pragma makedep unix +#endif + +#include "config.h" + +#include <stdlib.h> +#include <stdarg.h> +#include <sys/types.h> +#include <unistd.h> +#include <dlfcn.h> + +#define __user +#include "unixlib.h" + +LONG SCardEstablishContext(DWORD_LITE dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2, SCARDCONTEXT *phContext); +LONG SCardReleaseContext(SCARDCONTEXT hContext); +LONG SCardIsValidContext(SCARDCONTEXT hContext); +LONG SCardConnect(SCARDCONTEXT hContext, LPCSTR szReader, DWORD_LITE dwShareMode, DWORD_LITE dwPreferredProtocols, + SCARDHANDLE *phCard, DWORD_LITE *pdwActiveProtocol); +LONG SCardReconnect(SCARDHANDLE hCard, DWORD_LITE dwShareMode, DWORD_LITE dwPreferredProtocols, + DWORD_LITE dwInitialization, DWORD_LITE *pdwActiveProtocol); +LONG SCardDisconnect(SCARDHANDLE hCard, DWORD_LITE dwDisposition); +LONG SCardBeginTransaction(SCARDHANDLE hCard); +LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD_LITE dwDisposition); +LONG SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderName, DWORD_LITE *pcchReaderLen, DWORD_LITE *pdwState, + DWORD_LITE *pdwProtocol, LPBYTE pbAtr, DWORD_LITE *pcbAtrLen); +LONG SCardGetStatusChange(SCARDCONTEXT hContext, DWORD_LITE dwTimeout, SCARD_READERSTATE_LITE *rgReaderStates, DWORD_LITE cReaders); +LONG SCardControl(SCARDHANDLE hCard, DWORD_LITE dwControlCode, LPCVOID pbSendBuffer, DWORD_LITE cbSendLength, + LPVOID pbRecvBuffer, DWORD_LITE cbRecvLength, DWORD_LITE *lpBytesReturned); +LONG SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST_LITE *pioSendPci, LPCBYTE pbSendBuffer, DWORD_LITE cbSendLength, + SCARD_IO_REQUEST_LITE *pioRecvPci, LPBYTE pbRecvBuffer, DWORD_LITE *pcbRecvLength); +LONG SCardListReaderGroups(SCARDCONTEXT hContext, LPSTR mszGroups, DWORD_LITE *pcchGroups); +LONG SCardListReaders(SCARDCONTEXT hContext, LPCSTR mszGroups, LPSTR mszReaders, DWORD_LITE *pcchReaders); +LONG SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem); +LONG SCardCancel(SCARDCONTEXT hContext); +LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD_LITE dwAttrId, LPBYTE pbAttr, DWORD_LITE *pcbAttrLen); +LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD_LITE dwAttrId, LPCBYTE pbAttr, DWORD_LITE cbAttrLen); + +#include "wine/debug.h" +WINE_DEFAULT_DEBUG_CHANNEL(winscard); +WINE_DECLARE_DEBUG_CHANNEL(winediag); + +static void* g_pcscliteHandle = NULL; + +#define MAKE_FUNCPTR(f) static typeof(f) * p##f + MAKE_FUNCPTR(SCardEstablishContext); + MAKE_FUNCPTR(SCardReleaseContext); + MAKE_FUNCPTR(SCardIsValidContext); + MAKE_FUNCPTR(SCardConnect); + MAKE_FUNCPTR(SCardReconnect); + MAKE_FUNCPTR(SCardDisconnect); + MAKE_FUNCPTR(SCardBeginTransaction); + MAKE_FUNCPTR(SCardEndTransaction); + MAKE_FUNCPTR(SCardStatus); + MAKE_FUNCPTR(SCardGetStatusChange); + MAKE_FUNCPTR(SCardControl); + MAKE_FUNCPTR(SCardTransmit); + MAKE_FUNCPTR(SCardListReaderGroups); + MAKE_FUNCPTR(SCardListReaders); + MAKE_FUNCPTR(SCardFreeMemory); + MAKE_FUNCPTR(SCardCancel); + MAKE_FUNCPTR(SCardGetAttrib); + MAKE_FUNCPTR(SCardSetAttrib); +#undef MAKE_FUNCPTR + +static BOOL load_pcsclite(void); + +static LONG pcsclite_process_attach( void *args ) +{ + if (!load_pcsclite()) return SCARD_F_INTERNAL_ERROR; + return SCARD_S_SUCCESS; +} + +static LONG pcsclite_process_detach( void *args ) +{ + if (g_pcscliteHandle) dlclose( g_pcscliteHandle ); + g_pcscliteHandle = NULL; + return SCARD_S_SUCCESS; +} + +static LONG pcsclite_SCardEstablishContext( void *args ) +{ + struct SCardEstablishContext_params *params = args; + if (!pSCardEstablishContext) return SCARD_F_INTERNAL_ERROR; + return pSCardEstablishContext( params->dwScope, params->pvReserved1, params->pvReserved2, params->phContext ); +} + +static LONG pcsclite_SCardReleaseContext( void *args ) +{ + struct SCardReleaseContext_params *params = args; + if (!pSCardReleaseContext) return SCARD_F_INTERNAL_ERROR; + return pSCardReleaseContext( params->hContext ); +} + +static LONG pcsclite_SCardIsValidContext( void *args ) +{ + struct SCardIsValidContext_params *params = args; + if (!pSCardIsValidContext) return SCARD_F_INTERNAL_ERROR; + return pSCardIsValidContext( params->hContext ); +} + +static LONG pcsclite_SCardConnect( void *args ) +{ + struct SCardConnect_params *params = args; + if (!pSCardConnect) return SCARD_F_INTERNAL_ERROR; + return pSCardConnect( params->hContext, params->szReader, params->dwShareMode, params->dwPreferredProtocols, + params->phCard, params->pdwActiveProtocol ); +} + +static LONG pcsclite_SCardReconnect( void *args ) +{ + struct SCardReconnect_params *params = args; + if (!pSCardReconnect) return SCARD_F_INTERNAL_ERROR; + return pSCardReconnect( params->hCard, params->dwShareMode, params->dwPreferredProtocols, params->dwInitialization, params->pdwActiveProtocol ); +} + +static LONG pcsclite_SCardDisconnect( void *args ) +{ + struct SCardDisconnect_params *params = args; + if (!pSCardDisconnect) return SCARD_F_INTERNAL_ERROR; + return pSCardDisconnect( params->hCard, params->dwDisposition ); +} + +static LONG pcsclite_SCardBeginTransaction( void *args ) +{ + struct SCardBeginTransaction_params *params = args; + if (!pSCardBeginTransaction) return SCARD_F_INTERNAL_ERROR; + return pSCardBeginTransaction( params->hCard ); +} + +static LONG pcsclite_SCardEndTransaction( void *args ) +{ + struct SCardEndTransaction_params *params = args; + if (!pSCardEndTransaction) return SCARD_F_INTERNAL_ERROR; + return pSCardEndTransaction( params->hCard, params->dwDisposition ); +} + +static LONG pcsclite_SCardStatus( void *args ) +{ + struct SCardStatus_params *params = args; + if (!pSCardStatus) return SCARD_F_INTERNAL_ERROR; + return pSCardStatus( params->hCard, params->mszReaderName, params->pcchReaderLen, params->pdwState, params->pdwProtocol, + params->pbAtr, params->pcbAtrLen ); +} + +static LONG pcsclite_SCardGetStatusChange( void *args ) +{ + struct SCardGetStatusChange_params *params = args; + if (!pSCardGetStatusChange) return SCARD_F_INTERNAL_ERROR; + return pSCardGetStatusChange( params->hContext, params->dwTimeout, params->rgReaderStates, params->cReaders ); +} + +static LONG pcsclite_SCardControl( void *args ) +{ + struct SCardControl_params *params = args; + if (!pSCardControl) return SCARD_F_INTERNAL_ERROR; + return pSCardControl( params->hCard, params->dwControlCode, params->pbSendBuffer, params->cbSendLength, + params->pbRecvBuffer, params->cbRecvLength, params->lpBytesReturned ); +} + +static LONG pcsclite_SCardTransmit( void *args ) +{ + struct SCardTransmit_params *params = args; + if (!pSCardTransmit) return SCARD_F_INTERNAL_ERROR; + return pSCardTransmit( params->hCard, params->pioSendPci, params->pbSendBuffer, params->cbSendLength, + params->pioRecvPci, params->pbRecvBuffer, params->pcbRecvLength ); +} + +static LONG pcsclite_SCardListReaderGroups( void *args ) +{ + struct SCardListReaderGroups_params *params = args; + if (!pSCardListReaderGroups) return SCARD_F_INTERNAL_ERROR; + return pSCardListReaderGroups( params->hContext, params->mszGroups, params->pcchGroups ); +} + +static LONG pcsclite_SCardListReaders( void *args ) +{ + struct SCardListReaders_params *params = args; + if (!pSCardListReaders) return SCARD_F_INTERNAL_ERROR; + return pSCardListReaders( params->hContext, params->mszGroups, params->mszReaders, params->pcchReaders ); +} + +static LONG pcsclite_SCardFreeMemory( void *args ) +{ + struct SCardFreeMemory_params *params = args; + if (!pSCardFreeMemory) return SCARD_F_INTERNAL_ERROR; + return pSCardFreeMemory( params->hContext, params->pvMem ); +} + +static LONG pcsclite_SCardCancel( void *args ) +{ + struct SCardCancel_params *params = args; + if (!pSCardCancel) return SCARD_F_INTERNAL_ERROR; + return pSCardCancel( params->hContext ); +} + +static LONG pcsclite_SCardGetAttrib( void *args ) +{ + struct SCardGetAttrib_params *params = args; + if (!pSCardGetAttrib) return SCARD_F_INTERNAL_ERROR; + return pSCardGetAttrib( params->hCard, params->dwAttrId, params->pbAttr, params->pcbAttrLen ); +} + +static LONG pcsclite_SCardSetAttrib( void *args ) +{ + struct SCardSetAttrib_params *params = args; + if (!pSCardSetAttrib) return SCARD_F_INTERNAL_ERROR; + return pSCardSetAttrib( params->hCard, params->dwAttrId, params->pbAttr, params->cbAttrLen ); +} + +const unixlib_entry_t __wine_unix_call_funcs[] = +{ + pcsclite_SCardEstablishContext, + pcsclite_SCardReleaseContext, + pcsclite_SCardIsValidContext, + pcsclite_SCardConnect, + pcsclite_SCardReconnect, + pcsclite_SCardDisconnect, + pcsclite_SCardBeginTransaction, + pcsclite_SCardEndTransaction, + pcsclite_SCardStatus, + pcsclite_SCardGetStatusChange, + pcsclite_SCardControl, + pcsclite_SCardTransmit, + pcsclite_SCardListReaderGroups, + pcsclite_SCardListReaders, + pcsclite_SCardFreeMemory, + pcsclite_SCardCancel, + pcsclite_SCardGetAttrib, + pcsclite_SCardSetAttrib, + pcsclite_process_attach, + pcsclite_process_detach, +}; + +static BOOL load_pcsclite(void) +{ + if(!g_pcscliteHandle) + { + /* try to load pcsc-lite */ +#ifdef __APPLE__ + g_pcscliteHandle = dlopen("/System/Library/Frameworks/PCSC.framework/PCSC",RTLD_LAZY | RTLD_GLOBAL); +#else + g_pcscliteHandle = dlopen("libpcsclite.so",RTLD_LAZY | RTLD_GLOBAL); + if(!g_pcscliteHandle) + { + /* error occured. Trying libpcsclite.so.1*/ + g_pcscliteHandle = dlopen("libpcsclite.so.1",RTLD_LAZY | RTLD_GLOBAL); + } +#endif + TRACE("g_pcscliteHandle: %p\n", g_pcscliteHandle); + if(!g_pcscliteHandle) + { + /* error occured*/ +#ifdef __APPLE__ + ERR_(winediag)( "loading PCSC framework failed, scard support will be disabled. Error: %s\n", debugstr_a(dlerror()) ); +#else + ERR_(winediag)( "failed to load libpcsclite.so, scard support will be disabled. Error: %s\n", debugstr_a(dlerror()) ); +#endif + return FALSE; + } + } + +#define LOAD_FUNCPTR(f) \ + if (!(p##f = dlsym( g_pcscliteHandle, #f ))) \ + { \ + ERR( "failed to load %s\n", #f ); \ + goto fail; \ + } + LOAD_FUNCPTR( SCardEstablishContext) + LOAD_FUNCPTR( SCardReleaseContext) + LOAD_FUNCPTR( SCardIsValidContext) + LOAD_FUNCPTR( SCardConnect) + LOAD_FUNCPTR( SCardReconnect) + LOAD_FUNCPTR( SCardDisconnect) + LOAD_FUNCPTR( SCardBeginTransaction) + LOAD_FUNCPTR( SCardEndTransaction) + LOAD_FUNCPTR( SCardStatus) + LOAD_FUNCPTR( SCardGetStatusChange) + LOAD_FUNCPTR( SCardControl) + LOAD_FUNCPTR( SCardTransmit) + LOAD_FUNCPTR( SCardListReaderGroups) + LOAD_FUNCPTR( SCardListReaders) + LOAD_FUNCPTR( SCardFreeMemory) + LOAD_FUNCPTR( SCardCancel) + LOAD_FUNCPTR( SCardGetAttrib) + LOAD_FUNCPTR( SCardSetAttrib) +#undef LOAD_FUNCPTR + return TRUE; +fail: + dlclose( g_pcscliteHandle ); + g_pcscliteHandle = NULL; + return FALSE; +} diff --git a/dlls/winscard/unixlib.h b/dlls/winscard/unixlib.h new file mode 100644 index 00000000000..74efcb47261 --- /dev/null +++ b/dlls/winscard/unixlib.h @@ -0,0 +1,262 @@ +/* + * WinSCard Unix library + * + * Copyright (C) 2023 Konstantin Romanov + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * + */ + +#include <stdarg.h> + +#include "windef.h" +#include "winbase.h" +#include "winternl.h" +#include "wine/unixlib.h" + +#ifndef __unixlib_h__ +#define __unixlib_h__ + + +#ifndef LPCBYTE + typedef const BYTE *LPCBYTE; +#endif + +#define MAX_PCSCLITE_READERNAME 52 + +#ifdef WINE_UNIX_LIB + typedef ULONG_PTR SCARDCONTEXT, *PSCARDCONTEXT, *LPSCARDCONTEXT; + typedef ULONG_PTR SCARDHANDLE, *PSCARDHANDLE, *LPSCARDHANDLE; + typedef unsigned long DWORD_LITE; + typedef unsigned long* LPDWORD_LITE; +#else + #include "winscard.h" + #ifndef SCARD_READERSTATE + typedef SCARD_READERSTATEA SCARD_READERSTATE; + #endif + #ifdef __x86_64 + typedef unsigned long long DWORD_LITE; + typedef unsigned long long* LPDWORD_LITE; + #else + typedef unsigned long DWORD_LITE; + typedef unsigned long* LPDWORD_LITE; + #endif +#endif + +#ifdef __APPLE__ + +#define DWORD_LITE DWORD +#define LPDWORD_LITE LPDWORD + +#define SCARD_READERSTATE_LITE SCARD_READERSTATEA +#define LPSCARD_READERSTATE_LITE LPSCARD_READERSTATEA + + +#define SCARD_IO_REQUEST_LITE SCARD_IO_REQUEST +#define PSCARD_IO_REQUEST_LITE PSCARD_IO_REQUEST +#define LPSCARD_IO_REQUEST_LITE LPSCARD_IO_REQUEST +#define LPCSCARD_IO_REQUEST_LITE LPCSCARD_IO_REQUEST + +#else + +#undef MAX_ATR_SIZE +#define MAX_ATR_SIZE 33 /**< Maximum ATR size */ + +typedef struct +{ + const char *szReader; + void *pvUserData; + DWORD_LITE dwCurrentState; + DWORD_LITE dwEventState; + DWORD_LITE cbAtr; + unsigned char rgbAtr[MAX_ATR_SIZE]; +} +SCARD_READERSTATE_LITE; + +typedef SCARD_READERSTATE_LITE *LPSCARD_READERSTATE_LITE; + +typedef struct +{ + DWORD_LITE dwProtocol; /**< Protocol identifier */ + DWORD_LITE cbPciLength; /**< Protocol Control Inf Length */ +} +SCARD_IO_REQUEST_LITE, *PSCARD_IO_REQUEST_LITE, *LPSCARD_IO_REQUEST_LITE; + +typedef const SCARD_IO_REQUEST_LITE *LPCSCARD_IO_REQUEST_LITE; + +#endif + +enum unix_funcs +{ + unix_SCardEstablishContext, + unix_SCardReleaseContext, + unix_SCardIsValidContext, + unix_SCardConnect, + unix_SCardReconnect, + unix_SCardDisconnect, + unix_SCardBeginTransaction, + unix_SCardEndTransaction, + unix_SCardStatus, + unix_SCardGetStatusChange, + unix_SCardControl, + unix_SCardTransmit, + unix_SCardListReaderGroups, + unix_SCardListReaders, + unix_SCardFreeMemory, + unix_SCardCancel, + unix_SCardGetAttrib, + unix_SCardSetAttrib, + unix_process_attach, + unix_process_detach, +}; + +struct SCardEstablishContext_params +{ + DWORD_LITE dwScope; + LPCVOID pvReserved1; + LPCVOID pvReserved2; + LPSCARDCONTEXT phContext; +}; + +struct SCardReleaseContext_params +{ + SCARDCONTEXT hContext; +}; + +struct SCardIsValidContext_params +{ + SCARDCONTEXT hContext; +}; + +struct SCardConnect_params +{ + SCARDCONTEXT hContext; + LPCSTR szReader; + DWORD_LITE dwShareMode; + DWORD_LITE dwPreferredProtocols; + LPSCARDHANDLE phCard; + DWORD_LITE *pdwActiveProtocol; +}; + +struct SCardReconnect_params +{ + SCARDHANDLE hCard; + DWORD_LITE dwShareMode; + DWORD_LITE dwPreferredProtocols; + DWORD_LITE dwInitialization; + DWORD_LITE *pdwActiveProtocol; +}; + +struct SCardDisconnect_params +{ + SCARDHANDLE hCard; + DWORD_LITE dwDisposition; +}; + +struct SCardBeginTransaction_params +{ + SCARDHANDLE hCard; +}; + +struct SCardEndTransaction_params +{ + SCARDHANDLE hCard; + DWORD_LITE dwDisposition; +}; + +struct SCardStatus_params +{ + SCARDHANDLE hCard; + LPSTR mszReaderName; + DWORD_LITE *pcchReaderLen; + DWORD_LITE *pdwState; + DWORD_LITE *pdwProtocol; + LPBYTE pbAtr; + DWORD_LITE *pcbAtrLen; +}; + +struct SCardGetStatusChange_params +{ + SCARDCONTEXT hContext; + DWORD_LITE dwTimeout; + SCARD_READERSTATE_LITE *rgReaderStates; + DWORD_LITE cReaders; +}; + +struct SCardControl_params +{ + SCARDHANDLE hCard; + DWORD_LITE dwControlCode; + LPCVOID pbSendBuffer; + DWORD_LITE cbSendLength; + LPVOID pbRecvBuffer; + DWORD_LITE cbRecvLength; + DWORD_LITE *lpBytesReturned; +}; + +struct SCardTransmit_params +{ + SCARDHANDLE hCard; + const SCARD_IO_REQUEST_LITE *pioSendPci; + LPCBYTE pbSendBuffer; + DWORD_LITE cbSendLength; + SCARD_IO_REQUEST_LITE *pioRecvPci; + LPBYTE pbRecvBuffer; + DWORD_LITE *pcbRecvLength; +}; + +struct SCardListReaderGroups_params +{ + SCARDCONTEXT hContext; + LPSTR mszGroups; + DWORD_LITE *pcchGroups; +}; + +struct SCardListReaders_params +{ + SCARDCONTEXT hContext; + LPCSTR mszGroups; + LPSTR mszReaders; + DWORD_LITE *pcchReaders; +}; + +struct SCardFreeMemory_params +{ + SCARDCONTEXT hContext; + LPCVOID pvMem; +}; + +struct SCardCancel_params +{ + SCARDCONTEXT hContext; +}; + +struct SCardGetAttrib_params +{ + SCARDHANDLE hCard; + DWORD_LITE dwAttrId; + LPBYTE pbAttr; + DWORD_LITE *pcbAttrLen; +}; + +struct SCardSetAttrib_params +{ + SCARDHANDLE hCard; + DWORD_LITE dwAttrId; + const LPBYTE pbAttr; + DWORD_LITE cbAttrLen; +}; + +#endif \ No newline at end of file diff --git a/dlls/winscard/winscard.c b/dlls/winscard/winscard.c index accbaf75c3d..ea2e1e2433c 100644 --- a/dlls/winscard/winscard.c +++ b/dlls/winscard/winscard.c @@ -1,5 +1,6 @@ /* - * Copyright 2007 Mounir IDRASSI (mounir.idrassi@idrix.fr, for IDRIX) + * Copyright (C) 2007 Mounir IDRASSI (mounir.idrassi@idrix.fr, for IDRIX) + * Copyright (C) 2023 Konstantin Romanov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -15,135 +16,1909 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ - #include <stdarg.h> #include "windef.h" #include "winbase.h" +#include "ntuser.h" +#include "wine/unixlib.h" #include "wine/debug.h" + #include "winscard.h" -#include "winternl.h" +#include "unixlib.h"
WINE_DEFAULT_DEBUG_CHANNEL(winscard);
-static HANDLE g_startedEvent = NULL; +SCARD_IO_REQUEST g_rgSCardT0Pci = { SCARD_PROTOCOL_T0, 8 }; +SCARD_IO_REQUEST g_rgSCardT1Pci = { SCARD_PROTOCOL_T1, 8 }; +SCARD_IO_REQUEST g_rgSCardRawPci = { SCARD_PROTOCOL_RAW, 8 }; + +#define PCSCLITE_SCARD_PROTOCOL_RAW 0x00000004 + +static DWORD_LITE +ms_proto2lite_proto(DWORD dwProtocol) +{ + if (dwProtocol & SCARD_PROTOCOL_RAW) + { + dwProtocol ^= SCARD_PROTOCOL_RAW; + dwProtocol |= PCSCLITE_SCARD_PROTOCOL_RAW; + } + return (DWORD_LITE)dwProtocol; +} + +static DWORD +lite_proto2ms_proto(DWORD_LITE dwProtocol) +{ + if (dwProtocol & PCSCLITE_SCARD_PROTOCOL_RAW) + { + dwProtocol ^= PCSCLITE_SCARD_PROTOCOL_RAW; + dwProtocol |= SCARD_PROTOCOL_RAW; + } + return (DWORD)dwProtocol; +} + +HANDLE g_startedEvent = NULL;
-const SCARD_IO_REQUEST g_rgSCardT0Pci = { SCARD_PROTOCOL_T0, 8 }; -const SCARD_IO_REQUEST g_rgSCardT1Pci = { SCARD_PROTOCOL_T1, 8 }; -const SCARD_IO_REQUEST g_rgSCardRawPci = { SCARD_PROTOCOL_RAW, 8 };
+#define WINSCARD_CALL( func, params ) WINE_UNIX_CALL( unix_ ## func, params )
BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { - TRACE("%p,%lx,%p\n", hinstDLL, fdwReason, lpvReserved); + BOOL is_wow64=FALSE; + TRACE("%p, %#lx, %p\n", hinstDLL, fdwReason, lpvReserved); + IsWow64Process(GetCurrentProcess(), &is_wow64); + if (is_wow64) + WARN("Running in wow64 process. libpcsclite1:i386 must be installed\n");
- switch (fdwReason) - { + switch (fdwReason) { case DLL_PROCESS_ATTACH: + { DisableThreadLibraryCalls(hinstDLL); - /* FIXME: for now, we act as if the pcsc daemon is always started */ + __wine_init_unix_call(); + if(!WINSCARD_CALL( process_attach, NULL )) + WARN("Winscard loading failed."); g_startedEvent = CreateEventA(NULL,TRUE,TRUE,NULL); break; + } case DLL_PROCESS_DETACH: - if (lpvReserved) break; + { + WINSCARD_CALL( process_detach, NULL ); CloseHandle(g_startedEvent); break; + } } - return TRUE; }
-HANDLE WINAPI SCardAccessStartedEvent(void) +static LPVOID SCardAllocate(DWORD dwLength) { - return g_startedEvent; + if(!dwLength) + return NULL; + return HeapAlloc(GetProcessHeap(), 0, dwLength); }
-LONG WINAPI SCardAddReaderToGroupA(SCARDCONTEXT context, LPCSTR reader, LPCSTR group) +static void SCardFree(LPVOID ptr) { - LONG retval; - UNICODE_STRING readerW, groupW; + HeapFree(GetProcessHeap(), 0, ptr); +}
- if(reader) RtlCreateUnicodeStringFromAsciiz(&readerW,reader); - else readerW.Buffer = NULL; - if(group) RtlCreateUnicodeStringFromAsciiz(&groupW,group); - else groupW.Buffer = NULL; +/* + * Convert a wide-char multi-string to an ANSI multi-string + */ +static LONG ConvertListToANSI(LPCWSTR szListW,LPSTR* pszListA,LPDWORD pdwLength) +{ + if(!szListW) + { + *pszListA = NULL; + *pdwLength = 0; + } + else if(!*szListW) /* empty multi-string case */ + { + *pdwLength = 2; + *pszListA = (LPSTR) SCardAllocate(2); + if(!*pszListA) + return SCARD_E_NO_MEMORY; + *pszListA[0] = '\0'; + *pszListA[1] = '\0'; + } + else + { + LPSTR szStr = NULL; + int wlen = 0, alen = 0, totallen = 0; + LPCWSTR szListWPtr = szListW; + + /* compute size of wide-char multi-string */ + while (*szListWPtr) + { + wlen = lstrlenW (szListWPtr) + 1;
- retval = SCardAddReaderToGroupW(context, readerW.Buffer, groupW.Buffer); + totallen += wlen; + szListWPtr += wlen; + } + + totallen++; + + alen = WideCharToMultiByte(CP_ACP, 0, szListW, totallen, NULL, 0, NULL, NULL); + if (alen == 0) + return SCARD_F_INTERNAL_ERROR; + + /* allocate memory */ + szStr = (LPSTR) SCardAllocate (alen); + if(!szStr) + return SCARD_E_NO_MEMORY; + + /* perform the conversion */ + alen = WideCharToMultiByte(CP_ACP, 0, szListW, totallen, szStr, alen, NULL, NULL); + if (alen == 0) + { + SCardFree (szStr); + return SCARD_F_INTERNAL_ERROR; + } + + *pszListA = szStr; + *pdwLength = alen; + } + + return SCARD_S_SUCCESS; +}
- RtlFreeUnicodeString(&readerW); - RtlFreeUnicodeString(&groupW); +/* + * Convert a ANSII multi-string to a wide-char multi-string + */ +static LONG ConvertListToWideChar(LPCSTR szListA,LPWSTR* pszListW,LPDWORD pdwLength) +{ + if(!szListA) + { + *pszListW = NULL; + *pdwLength = 0; + } + else if(!*szListA) /* empty multi-string case */ + { + *pdwLength = 2; + *pszListW = (LPWSTR) SCardAllocate(2*sizeof(WCHAR)); + if(!*pszListW) + return SCARD_E_NO_MEMORY; + *pszListW[0] = '\0'; + *pszListW[1] = '\0'; + } + else + { + LPWSTR szStr = NULL; + int wlen = 0, alen = 0, totallen = 0; + LPCSTR szListAPtr = szListA; + + /* compute size of ANSI multi-string */ + while (*szListAPtr) + { + alen = lstrlenA (szListAPtr) + 1;
- return retval; + totallen += alen; + szListAPtr += alen; + } + + totallen++; + + wlen = MultiByteToWideChar(CP_ACP, 0, szListA, totallen, NULL, 0); + if (wlen == 0) + return SCARD_F_INTERNAL_ERROR; + + /* allocate memory */ + szStr = (LPWSTR) SCardAllocate (wlen * sizeof (WCHAR)); + if(!szStr) + return SCARD_E_NO_MEMORY; + + /* perform the conversion */ + wlen = MultiByteToWideChar(CP_ACP, 0, szListA, totallen, szStr, wlen); + if (wlen == 0) + { + SCardFree (szStr); + return SCARD_F_INTERNAL_ERROR; + } + + *pszListW = szStr; + *pdwLength = wlen; + } + + return SCARD_S_SUCCESS; }
-LONG WINAPI SCardAddReaderToGroupW(SCARDCONTEXT context, LPCWSTR reader, LPCWSTR group) + +/* + * translate PCSC-lite errors to equivalent MS ones + * Actually, the only difference is for SCARD_W_INSERTED_CARD(0x8010006A) and + * SCARD_E_UNSUPPORTED_FEATURE (0x8010001F) + */ + +#define PCSCLITE_SCARD_W_INSERTED_CARD 0x8010006A +#define PCSCLITE_SCARD_E_UNSUPPORTED_FEATURE 0x8010001F + +static LONG TranslateToWin32(LONG lRet) { - FIXME("%x %s %s\n", (unsigned int) context, debugstr_w(reader), debugstr_w(group)); - return SCARD_S_SUCCESS; + if(lRet == PCSCLITE_SCARD_E_UNSUPPORTED_FEATURE) + return SCARD_E_UNSUPPORTED_FEATURE; + else if(lRet == PCSCLITE_SCARD_W_INSERTED_CARD) + return SCARD_F_UNKNOWN_ERROR; /* FIXME: is there a better WIN32 error code */ + else + return lRet; } +
-LONG WINAPI SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1, - LPCVOID pvReserved2, LPSCARDCONTEXT phContext) +/* + * events functions + */ + +HANDLE WINAPI SCardAccessNewReaderEvent(void) { - FIXME("(%lx,%p,%p,%p) stub\n", dwScope, pvReserved1, pvReserved2, phContext); + FIXME("stub\n"); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return SCARD_F_INTERNAL_ERROR; + return NULL; }
-LONG WINAPI SCardIsValidContext(SCARDCONTEXT context) +HANDLE WINAPI SCardAccessStartedEvent() { - FIXME("(%Ix) stub\n", context); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return SCARD_F_INTERNAL_ERROR; + return g_startedEvent; }
-LONG WINAPI SCardListCardsA(SCARDCONTEXT hContext, LPCBYTE pbAtr, LPCGUID rgguidInterfaces, DWORD cguidInterfaceCount, LPSTR mszCards, LPDWORD pcchCards) +void WINAPI SCardReleaseStartedEvent(HANDLE hStartedEventHandle) { - FIXME(": stub\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return SCARD_F_INTERNAL_ERROR; + /* do nothing because we don't implement yet reference couting for the event handle*/ }
-LONG WINAPI SCardReleaseContext(SCARDCONTEXT context) +LONG WINAPI SCardFreeMemory( SCARDCONTEXT hContext,LPCVOID pvMem) { - FIXME("(%Ix) stub\n", context); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return SCARD_F_INTERNAL_ERROR; + if(pvMem) + SCardFree((void*) pvMem); + return SCARD_S_SUCCESS; }
-LONG WINAPI SCardStatusA(SCARDHANDLE context, LPSTR szReaderName, LPDWORD pcchReaderLen, LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen) +/* + * smart cards database functions. Almost all of them are stubs + */ + +LONG WINAPI SCardListCardsA( + SCARDCONTEXT hContext, + const BYTE* pbAtr, + LPCGUID rgquidInterfaces, + DWORD cguidInterfaceCount, + LPSTR mszCards, + LPDWORD pcchCards) { - FIXME("(%Ix) stub\n", context); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return SCARD_F_INTERNAL_ERROR; + TRACE("0x%08X, %p, %p, %#lx, %p, %p - stub\n",(unsigned int) hContext,pbAtr,rgquidInterfaces,cguidInterfaceCount,mszCards,pcchCards); + + /* we simuate the fact that no cards are enregistred on the system by returning an empty multi-string*/ + if(!pcchCards) + return SCARD_E_INVALID_PARAMETER; + else if(!mszCards) + *pcchCards = 2; + else + { + DWORD len = *pcchCards; + if(SCARD_AUTOALLOCATE == len) + { + if(!mszCards) + return SCARD_E_INVALID_PARAMETER; + else + { + /* allocate memory */ + LPSTR* pmszCards = (LPSTR*) mszCards; + LPSTR szResult = (LPSTR) SCardAllocate(2); + if(!szResult) + return SCARD_E_NO_MEMORY; + szResult[0] = '\0'; + szResult[1] = '\0'; + *pcchCards = 2; + *pmszCards = szResult; + } + } + else + { + if(len < 2) + { + *pcchCards = 2; + return SCARD_E_INSUFFICIENT_BUFFER; + } + else + { + /* return a empty multi string */ + mszCards[0] = '\0'; + mszCards[1] = '\0'; + *pcchCards = 2; + } + } + } + + return SCARD_S_SUCCESS; }
-LONG WINAPI SCardStatusW(SCARDHANDLE context, LPWSTR szReaderName, LPDWORD pcchReaderLen, LPDWORD pdwState,LPDWORD pdwProtocol,LPBYTE pbAtr,LPDWORD pcbArtLen) +LONG WINAPI SCardListCardsW( + SCARDCONTEXT hContext, + const BYTE* pbAtr, + LPCGUID rgquidInterfaces, + DWORD cguidInterfaceCount, + LPWSTR mszCards, + LPDWORD pcchCards) { - FIXME("(%Ix) stub\n", context); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return SCARD_F_INTERNAL_ERROR; + TRACE("0x%08X, %p, %p, %#lx, %p, %p - stub\n",(unsigned int)hContext,pbAtr,rgquidInterfaces,cguidInterfaceCount,mszCards,pcchCards); + + /* we simuate the fact that no cards are enregistred on the system by returning an empty multi-string*/ + if(!pcchCards) + return SCARD_E_INVALID_PARAMETER; + else if(!mszCards) + *pcchCards = 2; + else + { + DWORD len = *pcchCards; + if(SCARD_AUTOALLOCATE == len) + { + if(!mszCards) + return SCARD_E_INVALID_PARAMETER; + else + { + /* allocate memory */ + LPWSTR* pmszCards = (LPWSTR*) mszCards; + LPWSTR szResult = (LPWSTR) SCardAllocate(2*sizeof(WCHAR)); + if(!szResult) + return SCARD_E_NO_MEMORY; + szResult[0] = '\0'; + szResult[1] = '\0'; + *pcchCards = 2; + *pmszCards = szResult; + } + } + else + { + if(len < 2) + { + *pcchCards = 2; + return SCARD_E_INSUFFICIENT_BUFFER; + } + else + { + /* return a empty multi string */ + mszCards[0] = '\0'; + mszCards[1] = '\0'; + *pcchCards = 2; + } + } + } + + return SCARD_S_SUCCESS; +} + +LONG WINAPI SCardListInterfacesA( + SCARDCONTEXT hContext, + LPCSTR szCard, + LPGUID pguidInterfaces, + LPDWORD pcguidInterfaces) +{ + FIXME("0x%08X %s %p %p - stub\n",(unsigned int)hContext,debugstr_a(szCard),pguidInterfaces,pcguidInterfaces); + + return SCARD_E_UNKNOWN_CARD; }
-void WINAPI SCardReleaseStartedEvent(void) +LONG WINAPI SCardListInterfacesW( + SCARDCONTEXT hContext, + LPCWSTR szCard, + LPGUID pguidInterfaces, + LPDWORD pcguidInterfaces) +{ + FIXME("0x%08X %s %p %p - stub\n",(unsigned int)hContext,debugstr_w(szCard),pguidInterfaces,pcguidInterfaces); + + return SCARD_E_UNKNOWN_CARD; +} + +LONG WINAPI SCardGetProviderIdA( + SCARDCONTEXT hContext, + LPCSTR szCard, + LPGUID pguidProviderId) { - FIXME("stub\n"); + FIXME("0x%08X %s %p - stub\n",(unsigned int)hContext,debugstr_a(szCard),pguidProviderId); + + if(!pguidProviderId) + return SCARD_E_INVALID_PARAMETER; + + return SCARD_E_UNKNOWN_CARD; +} + +LONG WINAPI SCardGetProviderIdW( + SCARDCONTEXT hContext, + LPCWSTR szCard, + LPGUID pguidProviderId) +{ + FIXME("0x%08X %s %p - stub\n",(unsigned int)hContext,debugstr_w(szCard),pguidProviderId); + + if(!pguidProviderId) + return SCARD_E_INVALID_PARAMETER; + + return SCARD_E_UNKNOWN_CARD; +} + +LONG WINAPI SCardGetCardTypeProviderNameA( + SCARDCONTEXT hContext, + LPCSTR szCardName, + DWORD dwProviderId, + LPSTR szProvider, + LPDWORD pcchProvider) +{ + FIXME("0x%08X %s %#lx %p %p - stub\n",(unsigned int)hContext,debugstr_a(szCardName),dwProviderId,szProvider,pcchProvider); + + return SCARD_E_UNKNOWN_CARD; +} + +LONG WINAPI SCardGetCardTypeProviderNameW( + SCARDCONTEXT hContext, + LPCWSTR szCardName, + DWORD dwProviderId, + LPWSTR szProvider, + LPDWORD pcchProvider) +{ + FIXME("0x%08X %s %#lx %p %p - stub\n",(unsigned int)hContext,debugstr_w(szCardName),dwProviderId,szProvider,pcchProvider); + + return SCARD_E_UNKNOWN_CARD; }
-LONG WINAPI SCardListReadersA(SCARDCONTEXT context, const CHAR *groups, CHAR *readers, DWORD *buflen) + +LONG WINAPI SCardIntroduceReaderGroupA( + SCARDCONTEXT hContext, + LPCSTR szGroupName) +{ + FIXME("0x%08X %s - stub\n",(unsigned int)hContext,debugstr_a(szGroupName)); + + return SCARD_F_UNKNOWN_ERROR; +} + +LONG WINAPI SCardIntroduceReaderGroupW( + SCARDCONTEXT hContext, + LPCWSTR szGroupName) { - FIXME("(%Ix, %s, %p, %p) stub\n", context, debugstr_a(groups), readers, buflen); - return SCARD_E_NO_READERS_AVAILABLE; + FIXME("0x%08X %s - stub\n",(unsigned int)hContext,debugstr_w(szGroupName)); + + return SCARD_F_UNKNOWN_ERROR; }
-LONG WINAPI SCardListReadersW(SCARDCONTEXT context, const WCHAR *groups, WCHAR *readers, DWORD *buflen) +LONG WINAPI SCardForgetReaderGroupA( + SCARDCONTEXT hContext, + LPCSTR szGroupName) +{ + FIXME("0x%08X %s - stub\n",(unsigned int)hContext,debugstr_a(szGroupName)); + + return SCARD_S_SUCCESS; +} + +LONG WINAPI SCardForgetReaderGroupW( + SCARDCONTEXT hContext, + LPCWSTR szGroupName) { - FIXME("(%Ix, %s, %p, %p) stub\n", context, debugstr_w(groups), readers, buflen); - return SCARD_E_NO_READERS_AVAILABLE; + FIXME("0x%08X %s - stub\n",(unsigned int)hContext,debugstr_w(szGroupName)); + + return SCARD_S_SUCCESS; }
-LONG WINAPI SCardCancel(SCARDCONTEXT context) + +LONG WINAPI SCardIntroduceReaderA( + SCARDCONTEXT hContext, + LPCSTR szReaderName, + LPCSTR szDeviceName) { - FIXME("(%Ix) stub\n", context); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return SCARD_F_INTERNAL_ERROR; + FIXME("0x%08X %s %s - stub\n",(unsigned int)hContext,debugstr_a(szReaderName),debugstr_a(szDeviceName)); + + return SCARD_F_UNKNOWN_ERROR; +} + +LONG WINAPI SCardIntroduceReaderW( + SCARDCONTEXT hContext, + LPCWSTR szReaderName, + LPCWSTR szDeviceName) +{ + FIXME("0x%08X %s %s - stub\n",(unsigned int)hContext,debugstr_w(szReaderName),debugstr_w(szDeviceName)); + + return SCARD_F_UNKNOWN_ERROR; +} + +LONG WINAPI SCardForgetReaderA( + SCARDCONTEXT hContext, + LPCSTR szReaderName) +{ + FIXME("0x%08X %s - stub\n",(unsigned int)hContext,debugstr_a(szReaderName)); + + return SCARD_S_SUCCESS; +} + + +LONG WINAPI SCardForgetReaderW( + SCARDCONTEXT hContext, + LPCWSTR szReaderName) +{ + FIXME("0x%08X %s - stub\n",(unsigned int)hContext,debugstr_w(szReaderName)); + + return SCARD_S_SUCCESS; +} + +LONG WINAPI SCardAddReaderToGroupA( + SCARDCONTEXT hContext, + LPCSTR szReaderName, + LPCSTR szGroupName) +{ + FIXME("0x%08X %s %s - stub\n",(unsigned int) hContext, debugstr_a( szReaderName), debugstr_a(szGroupName)); + + return SCARD_F_UNKNOWN_ERROR; +} + +LONG WINAPI SCardAddReaderToGroupW( + SCARDCONTEXT hContext, + LPCWSTR szReaderName, + LPCWSTR szGroupName) +{ + FIXME("0x%08X %s %s - stub\n",(unsigned int) hContext, debugstr_w( szReaderName), debugstr_w(szGroupName)); + + return SCARD_F_UNKNOWN_ERROR; +} + +LONG WINAPI SCardRemoveReaderFromGroupA( + SCARDCONTEXT hContext, + LPCSTR szReaderName, + LPCSTR szGroupName) +{ + FIXME("0x%08X %s %s - stub\n",(unsigned int) hContext, debugstr_a( szReaderName), debugstr_a(szGroupName)); + + return SCARD_S_SUCCESS; +} + +LONG WINAPI SCardRemoveReaderFromGroupW( + SCARDCONTEXT hContext, + LPCWSTR szReaderName, + LPCWSTR szGroupName) +{ + FIXME("0x%08X %s %s - stub\n",(unsigned int) hContext, debugstr_w( szReaderName), debugstr_w(szGroupName)); + + return SCARD_S_SUCCESS; +} + + +LONG WINAPI SCardIntroduceCardTypeA( + SCARDCONTEXT hContext, + LPCSTR szCardName, + LPCGUID pguidPrimaryProvider, + LPCGUID rgguidInterfaces, + DWORD dwInterfaceCount, + const BYTE* pbAtr, + const BYTE* pbAtrMask, + DWORD cbAtrLen) +{ + FIXME("0x%08X %s %p %p %#lx %p %p %#lx - stub\n",(unsigned int) hContext, debugstr_a(szCardName),pguidPrimaryProvider,rgguidInterfaces,dwInterfaceCount,pbAtr,pbAtrMask,cbAtrLen); + + return SCARD_F_UNKNOWN_ERROR; +} + +LONG WINAPI SCardIntroduceCardTypeW( + SCARDCONTEXT hContext, + LPCWSTR szCardName, + LPCGUID pguidPrimaryProvider, + LPCGUID rgguidInterfaces, + DWORD dwInterfaceCount, + const BYTE* pbAtr, + const BYTE* pbAtrMask, + DWORD cbAtrLen) +{ + FIXME("0x%08X %s %p %p %#lx %p %p %#lx - stub\n",(unsigned int) hContext, debugstr_w(szCardName),pguidPrimaryProvider,rgguidInterfaces,dwInterfaceCount,pbAtr,pbAtrMask,cbAtrLen); + + return SCARD_F_UNKNOWN_ERROR; +} + + +LONG WINAPI SCardSetCardTypeProviderNameA( + SCARDCONTEXT hContext, + LPCSTR szCardName, + DWORD dwProviderId, + LPCSTR szProvider) +{ + FIXME("0x%08X %s %#lx %s - stub\n",(unsigned int) hContext, debugstr_a(szCardName),dwProviderId,debugstr_a(szProvider)); + + return SCARD_F_UNKNOWN_ERROR; +} + +LONG WINAPI SCardSetCardTypeProviderNameW( + SCARDCONTEXT hContext, + LPCWSTR szCardName, + DWORD dwProviderId, + LPCWSTR szProvider) +{ + FIXME("0x%08X %s %#lx %s - stub\n",(unsigned int) hContext, debugstr_w(szCardName),dwProviderId,debugstr_w(szProvider)); + + return SCARD_F_UNKNOWN_ERROR; +} + +LONG WINAPI SCardForgetCardTypeA( + SCARDCONTEXT hContext, + LPCSTR szCardName) +{ + FIXME("0x%08X %s - stub\n",(unsigned int) hContext, debugstr_a(szCardName)); + + return SCARD_E_UNKNOWN_CARD; +} + +LONG WINAPI SCardForgetCardTypeW( + SCARDCONTEXT hContext, + LPCWSTR szCardName) +{ + FIXME("0x%08X %s - stub\n",(unsigned int) hContext, debugstr_w(szCardName)); + + return SCARD_E_UNKNOWN_CARD; +} + +LONG WINAPI SCardLocateCardsA( + SCARDCONTEXT hContext, + LPCSTR mszCards, + LPSCARD_READERSTATEA rgReaderStates, + DWORD cReaders) +{ + FIXME("0x%08X %s %p %#lx - stub\n",(unsigned int) hContext, debugstr_a(mszCards),rgReaderStates,cReaders); + + return SCARD_E_UNKNOWN_CARD; +} + +LONG WINAPI SCardLocateCardsW( + SCARDCONTEXT hContext, + LPCWSTR mszCards, + LPSCARD_READERSTATEW rgReaderStates, + DWORD cReaders) +{ + FIXME("0x%08X %s %p %#lx - stub\n",(unsigned int) hContext, debugstr_w(mszCards),rgReaderStates,cReaders); + + return SCARD_E_UNKNOWN_CARD; +} + +LONG WINAPI SCardLocateCardsByATRA( + SCARDCONTEXT hContext, + LPSCARD_ATRMASK rgAtrMasks, + DWORD cAtrs, + LPSCARD_READERSTATEA rgReaderStates, + DWORD cReaders) +{ + FIXME("0x%08X %p %#lx %p %#lx - stub\n",(unsigned int) hContext, rgAtrMasks, cAtrs, rgReaderStates, cReaders); + + return SCARD_F_UNKNOWN_ERROR; +} + +LONG WINAPI SCardLocateCardsByATRW( + SCARDCONTEXT hContext, + LPSCARD_ATRMASK rgAtrMasks, + DWORD cAtrs, + LPSCARD_READERSTATEW rgReaderStates, + DWORD cReaders) +{ + FIXME("0x%08X %p %#lx %p %#lx - stub\n",(unsigned int) hContext, rgAtrMasks, cAtrs, rgReaderStates, cReaders); + + return SCARD_F_UNKNOWN_ERROR; +} + +LONG WINAPI SCardListReaderGroupsA( + SCARDCONTEXT hContext, + LPSTR mszGroups, + LPDWORD pcchGroups) +{ + LONG lRet = SCARD_F_UNKNOWN_ERROR; + DWORD_LITE len ; + struct SCardListReaderGroups_params params; + + TRACE(" 0x%08X %s %p\n",(unsigned int) hContext,debugstr_a(mszGroups),pcchGroups); + + if(!pcchGroups) + lRet = SCARD_E_INVALID_PARAMETER; + else if(mszGroups && *pcchGroups == SCARD_AUTOALLOCATE) + { + LPSTR* pmszGroups = (LPSTR*) mszGroups; + LPSTR szList = NULL; + len = 0; + + /* ask for the length */ + params.hContext = hContext; + params.mszGroups = NULL; + params.pcchGroups = &len; + lRet = WINSCARD_CALL( SCardListReaderGroups, ¶ms ); + + if(SCARD_S_SUCCESS == lRet) + { + /* allocate memory for the list */ + szList = (LPSTR) SCardAllocate((DWORD) len); + if(!szList) + lRet = SCARD_E_NO_MEMORY; + else + { + /* fill the list */ + params.hContext = hContext; + params.mszGroups = szList; + params.pcchGroups = &len; + lRet = WINSCARD_CALL( SCardListReaderGroups, ¶ms ); + if(SCARD_S_SUCCESS != lRet) + SCardFree(szList); + else + { + *pmszGroups = szList; + *pcchGroups = (DWORD) len; + } + } + } + } + else + { + params.hContext = hContext; + params.mszGroups = mszGroups; + + if (pcchGroups) + { + len = *pcchGroups; + params.pcchGroups = &len; + } + else + params.pcchGroups = NULL; + + lRet = WINSCARD_CALL( SCardListReaderGroups, ¶ms ); + if (pcchGroups) + *pcchGroups = len; + } + + return TranslateToWin32(lRet); +} + +LONG WINAPI SCardListReaderGroupsW( + SCARDCONTEXT hContext, + LPWSTR mszGroups, + LPDWORD pcchGroups) +{ + LONG lRet = SCARD_F_UNKNOWN_ERROR; + LPSTR szList = NULL; + LPWSTR szListW = NULL; + DWORD alen = 0,wlen = 0; + + TRACE(" 0x%08X %s %p\n",(unsigned int) hContext,debugstr_w(mszGroups),pcchGroups); + + if(!pcchGroups) + lRet = SCARD_E_INVALID_PARAMETER; + else + { + if(!mszGroups) + { + /* asking for length only + * get the length in ANSI and multiply by sizeof(WCHAR) + */ + alen = 0; + lRet = SCardListReaderGroupsA(hContext,NULL,&alen); + if(lRet == SCARD_S_SUCCESS || lRet == SCARD_E_INSUFFICIENT_BUFFER) + { + *pcchGroups = alen ; + } + goto end_label; + } + + /* get the ASCII list from pcsclite */ + alen = SCARD_AUTOALLOCATE; + lRet = SCardListReaderGroupsA(hContext,(LPSTR) &szList,&alen); + if(SCARD_S_SUCCESS != lRet) + goto end_label; + + /* now convert the list to a wide char list */ + lRet = ConvertListToWideChar(szList,&szListW,&wlen); + + /* free the ASCII list, we don't need it any more */ + SCardFreeMemory(hContext,(LPCVOID) szList); + + if(SCARD_S_SUCCESS != lRet) + goto end_label; + + if(SCARD_AUTOALLOCATE == *pcchGroups) + { + LPWSTR* pmszGroups = (LPWSTR*) mszGroups; + *pmszGroups = szListW; + *pcchGroups = wlen; + szListW = NULL; + lRet = SCARD_S_SUCCESS; + } + else + { + DWORD cchGroups = *pcchGroups; + if(cchGroups < wlen) + { + *pcchGroups = wlen; + lRet = SCARD_E_INSUFFICIENT_BUFFER; + } + else + { + *pcchGroups = wlen; + memcpy(mszGroups,szListW,wlen*sizeof(WCHAR)); + lRet = SCARD_S_SUCCESS; + } + } + } + +end_label: + if(szListW) + SCardFree(szListW); + return TranslateToWin32(lRet); + +} + +LONG WINAPI SCardListReadersA( + SCARDCONTEXT hContext, + LPCSTR mszGroups, + LPSTR mszReaders, + LPDWORD pcchReaders) +{ + LONG lRet; + TRACE("0x%p %s %s %ld\n",(void*)hContext, debugstr_a(mszGroups), debugstr_a(mszReaders), (pcchReaders==NULL?0:*pcchReaders)); + if(!pcchReaders) + lRet = SCARD_E_INVALID_PARAMETER; + else if(mszReaders && SCARD_AUTOALLOCATE == *pcchReaders) + { + /* get list from pcsc-lite */ + LPSTR* pmszReaders = (LPSTR*) mszReaders; + LPSTR szList = NULL; + DWORD_LITE dwListLength = 0; + struct SCardListReaders_params params = { hContext, mszGroups, NULL, &dwListLength }; + lRet = WINSCARD_CALL( SCardListReaders, ¶ms ); + + if(SCARD_S_SUCCESS != lRet && lRet != SCARD_E_INSUFFICIENT_BUFFER) + goto end_label; + + szList = (LPSTR)SCardAllocate((DWORD) dwListLength); + if(!szList) + { + lRet = SCARD_E_NO_MEMORY; + goto end_label; + } + + params.hContext = hContext; + params.mszReaders = szList; + params.pcchReaders = &dwListLength; + + lRet = WINSCARD_CALL( SCardListReaders, ¶ms ); + + if(SCARD_S_SUCCESS != lRet) + SCardFree(szList); + else + { + *pmszReaders = szList; + *pcchReaders = dwListLength; + } + } + else + { + struct SCardListReaders_params params = { hContext, mszGroups, mszReaders, NULL }; + if (pcchReaders) + { + DWORD_LITE dwListLength = *pcchReaders; + params.pcchReaders = &dwListLength; + lRet = WINSCARD_CALL( SCardListReaders, ¶ms ); + *pcchReaders = dwListLength; + } + else + lRet = WINSCARD_CALL( SCardListReaders, ¶ms ); + } + +end_label: + TRACE(" returned %#lx\n",lRet); + return TranslateToWin32(lRet); +} + +LONG WINAPI SCardListReadersW( + SCARDCONTEXT hContext, + LPCWSTR mszGroups, + LPWSTR mszReaders, + LPDWORD pcchReaders) +{ + LONG lRet; + TRACE("0x%p %s %s %p\n",(void*) hContext,debugstr_w(mszGroups),debugstr_w(mszReaders),pcchReaders); + + if(!pcchReaders) + lRet = SCARD_E_INVALID_PARAMETER; + // else if(!liteSCardListReaders) + // lRet = SCARD_F_INTERNAL_ERROR; + else + { + /* call the ANSI version */ + LPSTR mszGroupsA = NULL; + LPSTR mszReadersA = NULL; + LPWSTR szListW = NULL; + DWORD dwLength ; + if(mszGroups) + { + lRet = ConvertListToANSI(mszGroups,&mszGroupsA,&dwLength); + if(SCARD_S_SUCCESS != lRet) + goto end_label; + } + + if(!mszReaders) + { + /* asking for length only + * Assume that number of wide char is the same + * as the number f ANSI characters + */ + dwLength = 0; + lRet = SCardListReadersA(hContext,mszGroupsA,NULL,&dwLength); + if(lRet == SCARD_S_SUCCESS || lRet == SCARD_E_INSUFFICIENT_BUFFER) + { + *pcchReaders = dwLength; + } + if(mszGroupsA) + SCardFree(mszGroupsA); + goto end_label; + } + + dwLength = SCARD_AUTOALLOCATE; + lRet = SCardListReadersA(hContext,mszGroupsA,(LPSTR) &mszReadersA,&dwLength); + + /* free the ANSI list of groups : no more needed */ + if(mszGroupsA) + SCardFree(mszGroupsA); + + if(SCARD_S_SUCCESS != lRet) + goto end_label; + + /* we now have the list in ANSI. Covert it to wide-char format*/ + lRet = ConvertListToWideChar(mszReadersA,&szListW,&dwLength); + + /* ANSI list of readers no more needed */ + SCardFreeMemory(hContext,(LPCVOID) mszReadersA); + + if(SCARD_S_SUCCESS != lRet) + goto end_label; + + if(SCARD_AUTOALLOCATE == *pcchReaders) + { + LPWSTR* pmszReaders = (LPWSTR*) mszReaders; + *pmszReaders = szListW; + szListW = NULL; + *pcchReaders = dwLength; + } + else + { + DWORD inputLength = *pcchReaders; + if(inputLength < dwLength) + lRet = SCARD_E_INSUFFICIENT_BUFFER; + else + memcpy(mszReaders,szListW,dwLength*sizeof(WCHAR)); + *pcchReaders = dwLength; + } + + if(szListW) + SCardFree(szListW); + } +end_label: + return TranslateToWin32(lRet); +} + +/* + * PCS/SC communication functions + */ +LONG WINAPI SCardEstablishContext(DWORD dwScope, LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext) +{ + LONG lRet; + struct SCardEstablishContext_params params = { dwScope, pvReserved1, pvReserved2, phContext}; + TRACE("%#lx %p %p %p\n",dwScope,pvReserved1,pvReserved2,phContext); + + if(!phContext) + lRet = SCARD_E_INVALID_PARAMETER; + else + lRet = WINSCARD_CALL( SCardEstablishContext, ¶ms ); + + TRACE("returned %#lx hContext %p\n", lRet, (void*)*params.phContext); + return TranslateToWin32(lRet); +} + +LONG WINAPI SCardReleaseContext(SCARDCONTEXT hContext) +{ + LONG lRet; + struct SCardReleaseContext_params params = { hContext }; + TRACE("0x%p\n", (void*)hContext); + + lRet = WINSCARD_CALL( SCardReleaseContext, ¶ms ); + + TRACE(" returned %#lx\n",lRet); + return TranslateToWin32(lRet); +} + +LONG WINAPI SCardIsValidContext(SCARDCONTEXT hContext) +{ + struct SCardIsValidContext_params params = { hContext }; + TRACE("0x%p\n", (void*)hContext); + + return TranslateToWin32(WINSCARD_CALL( SCardIsValidContext, ¶ms )); +} + +LONG WINAPI SCardConnectA(SCARDCONTEXT hContext, + LPCSTR szReader, + DWORD dwShareMode, + DWORD dwPreferredProtocols, + LPSCARDHANDLE phCard, + LPDWORD pdwActiveProtocol) +{ + LONG lRet; + struct SCardConnect_params params = { hContext, szReader, dwShareMode, dwPreferredProtocols, phCard, NULL }; + TRACE(" 0x%08X %s %#lx %#lx %p %p\n",(unsigned int) hContext,debugstr_a(szReader),dwShareMode,dwPreferredProtocols,phCard,pdwActiveProtocol); + if(!szReader || !phCard || !pdwActiveProtocol) + lRet = SCARD_E_INVALID_PARAMETER; + else + { + /* the value of SCARD_PROTOCOL_RAW is different between MS implementation and + * pcsc-lite implementation. We must change its value + */ + if(dwPreferredProtocols & SCARD_PROTOCOL_RAW) + { + dwPreferredProtocols ^= SCARD_PROTOCOL_RAW; + dwPreferredProtocols |= PCSCLITE_SCARD_PROTOCOL_RAW; + params.dwPreferredProtocols = dwPreferredProtocols; + } + + if (pdwActiveProtocol) + { + DWORD_LITE dwProtocol = *pdwActiveProtocol; + params.pdwActiveProtocol = &dwProtocol; + lRet = WINSCARD_CALL( SCardConnect, ¶ms ); + *pdwActiveProtocol = (DWORD) dwProtocol; + } + else + lRet = WINSCARD_CALL( SCardConnect, ¶ms ); + if(SCARD_S_SUCCESS == lRet) + { + /* if PCSCLITE_SCARD_PROTOCOL_RAW is set, put back the MS corresponding value */ + if(*pdwActiveProtocol & PCSCLITE_SCARD_PROTOCOL_RAW) + { + *pdwActiveProtocol ^= PCSCLITE_SCARD_PROTOCOL_RAW; + *pdwActiveProtocol |= SCARD_PROTOCOL_RAW; + } + + } + } + + TRACE(" returned %#lx\n",lRet); + return TranslateToWin32(lRet); +} + +LONG WINAPI SCardConnectW(SCARDCONTEXT hContext, + LPCWSTR szReader, + DWORD dwShareMode, + DWORD dwPreferredProtocols, + LPSCARDHANDLE phCard, + LPDWORD pdwActiveProtocol) +{ + LONG lRet; + struct SCardConnect_params params = { hContext, NULL, dwShareMode, dwPreferredProtocols, phCard, NULL}; + TRACE(" 0x%08X %s %#lx %#lx %p %p\n",(unsigned int) hContext,debugstr_w(szReader),dwShareMode,dwPreferredProtocols,phCard,pdwActiveProtocol); + if(!szReader || !phCard || !pdwActiveProtocol) + lRet = SCARD_E_INVALID_PARAMETER; + else + { + LPSTR szReaderA = NULL; + int dwLen = WideCharToMultiByte(CP_ACP,0,szReader,-1,NULL,0,NULL,NULL); + if(!dwLen) + { + lRet = SCARD_F_UNKNOWN_ERROR; + goto end_label; + } + + szReaderA = (LPSTR) SCardAllocate(dwLen); + if(!szReaderA) + { + lRet = SCARD_E_NO_MEMORY; + goto end_label; + } + + dwLen = WideCharToMultiByte(CP_ACP,0,szReader,-1,szReaderA,dwLen,NULL,NULL); + if(!dwLen) + { + SCardFree(szReaderA); + lRet = SCARD_F_UNKNOWN_ERROR; + goto end_label; + } + + /* the value of SCARD_PROTOCOL_RAW is different between MS implementation and + * pcsc-lite implementation. We must change its value + */ + if(dwPreferredProtocols & SCARD_PROTOCOL_RAW) + { + dwPreferredProtocols ^= SCARD_PROTOCOL_RAW; + dwPreferredProtocols |= PCSCLITE_SCARD_PROTOCOL_RAW; + params.dwPreferredProtocols = dwPreferredProtocols; + } + + params.szReader = szReaderA; + if (pdwActiveProtocol) + { + DWORD_LITE dwProtocol = *pdwActiveProtocol; + params.pdwActiveProtocol = &dwProtocol; + lRet = WINSCARD_CALL( SCardConnect, ¶ms ); + *pdwActiveProtocol = (DWORD) dwProtocol; + } + else + lRet = WINSCARD_CALL( SCardConnect, ¶ms ); + if(SCARD_S_SUCCESS == lRet) + { + /* if PCSCLITE_SCARD_PROTOCOL_RAW is set, put back the MS corresponding value */ + if(*pdwActiveProtocol & PCSCLITE_SCARD_PROTOCOL_RAW) + { + *pdwActiveProtocol ^= PCSCLITE_SCARD_PROTOCOL_RAW; + *pdwActiveProtocol |= SCARD_PROTOCOL_RAW; + } + } + + /* free the allocate ANSI string */ + SCardFree(szReaderA); + } +end_label: + TRACE(" returned %#lx\n",lRet); + return TranslateToWin32(lRet); +} + +LONG WINAPI SCardReconnect(SCARDHANDLE hCard, + DWORD dwShareMode, + DWORD dwPreferredProtocols, + DWORD dwInitialization, + LPDWORD pdwActiveProtocol) +{ + LONG lRet; + struct SCardReconnect_params params = { hCard, dwShareMode, dwPreferredProtocols, dwInitialization, NULL}; + TRACE(" 0x%08X %#lx %#lx %#lx %p\n",(unsigned int) hCard,dwShareMode,dwPreferredProtocols,dwInitialization,pdwActiveProtocol); + if(!pdwActiveProtocol) + lRet = SCARD_E_INVALID_PARAMETER; + else + { + /* the value of SCARD_PROTOCOL_RAW is different between MS implementation and + * pcsc-lite implementation. We must change its value + */ + if(dwPreferredProtocols & SCARD_PROTOCOL_RAW) + { + dwPreferredProtocols ^= SCARD_PROTOCOL_RAW; + dwPreferredProtocols |= PCSCLITE_SCARD_PROTOCOL_RAW; + params.dwPreferredProtocols = dwPreferredProtocols; + } + + if (pdwActiveProtocol) + { + DWORD_LITE dwProtocol = *pdwActiveProtocol; + params.pdwActiveProtocol = &dwProtocol; + lRet = WINSCARD_CALL( SCardReconnect, ¶ms ); + *pdwActiveProtocol = (DWORD) dwProtocol; + } + else + lRet = WINSCARD_CALL( SCardReconnect, ¶ms ); + + if(SCARD_S_SUCCESS == lRet) + { + /* if PCSCLITE_SCARD_PROTOCOL_RAW is set, put back the MS corresponding value */ + if(*pdwActiveProtocol & PCSCLITE_SCARD_PROTOCOL_RAW) + { + *pdwActiveProtocol ^= PCSCLITE_SCARD_PROTOCOL_RAW; + *pdwActiveProtocol |= SCARD_PROTOCOL_RAW; + } + } + } + + TRACE(" returned %#lx\n",lRet); + return TranslateToWin32(lRet); +} + +LONG WINAPI SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition) +{ + LONG lRet; + struct SCardDisconnect_params params = { hCard, dwDisposition}; + TRACE(" 0x%08X %#lx\n",(unsigned int) hCard,dwDisposition); + + lRet = WINSCARD_CALL( SCardDisconnect, ¶ms ); + + TRACE(" returned %#lx\n",lRet); + return TranslateToWin32(lRet); +} + +LONG WINAPI SCardBeginTransaction(SCARDHANDLE hCard) +{ + LONG lRet; + struct SCardBeginTransaction_params params = { hCard }; + TRACE(" 0x%08X\n",(unsigned int) hCard); + + lRet = WINSCARD_CALL( SCardBeginTransaction, ¶ms ); + + TRACE(" returned %#lx\n",lRet); + return TranslateToWin32(lRet); +} + +LONG WINAPI SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition) +{ + LONG lRet; + struct SCardEndTransaction_params params = { hCard, dwDisposition }; + TRACE(" 0x%08X %#lx\n",(unsigned int) hCard,dwDisposition); + + lRet = WINSCARD_CALL( SCardEndTransaction, ¶ms ); + + TRACE(" returned %#lx\n",lRet); + return TranslateToWin32(lRet); +} + +LONG WINAPI SCardState( + SCARDHANDLE hCard, + LPDWORD pdwState, + LPDWORD pdwProtocol, + LPBYTE pbAtr, + LPDWORD pcbAtrLen) +{ + LONG lRet ; + LPSTR szName = NULL; + DWORD cchReaderLen = SCARD_AUTOALLOCATE; + TRACE(" 0x%08X %p %p %p %p\n",(unsigned int) hCard,pdwState,pdwProtocol,pbAtr,pcbAtrLen); + lRet = SCardStatusA(hCard,(LPSTR) &szName,&cchReaderLen,pdwState,pdwProtocol,pbAtr,pcbAtrLen); + + /* free szName is allocated by SCardStatusA */ + if(szName) + SCardFree((void*) szName); + + TRACE(" returned %#lx\n",lRet); + return TranslateToWin32(lRet); +} + +LONG WINAPI SCardStatusA( + SCARDHANDLE hCard, + LPSTR mszReaderNames, + LPDWORD pcchReaderLen, + LPDWORD pdwState, + LPDWORD pdwProtocol, + LPBYTE pbAtr, + LPDWORD pcbAtrLen) +{ + LONG lRet; + struct SCardStatus_params params; + TRACE(" 0x%08X %p %p %p %p %p %p\n",(unsigned int) hCard,mszReaderNames,pcchReaderLen,pdwState,pdwProtocol,pbAtr,pcbAtrLen); + if(!pcchReaderLen || !pdwState || !pdwProtocol || !pcbAtrLen) + lRet = SCARD_E_INVALID_PARAMETER; + else + { + DWORD_LITE dwNameLen = 0,dwAtrLen=MAX_ATR_SIZE, dwState, dwProtocol = 0; + LPDWORD_LITE pdwStateLite = NULL, pdwProtocolLite = NULL, pdwNameLenLite = NULL, pdwAtrLenLite = NULL; + BYTE atr[MAX_ATR_SIZE]; + if (pdwState) + { + dwState = *pdwState; + pdwStateLite = &dwState; + } + if (pdwProtocol) + { + pdwProtocolLite = &dwProtocol; + } + + if(!mszReaderNames || !pbAtr + || (*pcchReaderLen == SCARD_AUTOALLOCATE) || (*pcbAtrLen == SCARD_AUTOALLOCATE)) + { + /* retreive the information from pcsc-lite */ + BOOL bHasAutoAllocated = FALSE; + LPSTR szNames = NULL; + + params.hCard = hCard; + params.mszReaderName = NULL; + params.pcchReaderLen = &dwNameLen; + params.pdwState = pdwStateLite; + params.pdwProtocol = pdwProtocolLite; + params.pbAtr = atr; + params.pcbAtrLen = &dwAtrLen; + + lRet = WINSCARD_CALL( SCardStatus, ¶ms ); + if (pdwState) + { + *pdwState = (DWORD) dwState; + } + if (pdwProtocol) + { + *pdwProtocol = lite_proto2ms_proto(dwProtocol); + } + if(lRet != SCARD_S_SUCCESS && lRet != SCARD_E_INSUFFICIENT_BUFFER) + goto end_label; + + /* case 1: asking for reader names length */ + if(!mszReaderNames) + { + lRet = SCARD_S_SUCCESS; + *pcchReaderLen = dwNameLen; + if(!pbAtr) + *pcbAtrLen = (DWORD) dwAtrLen; + else if(*pcbAtrLen == SCARD_AUTOALLOCATE) + { + LPBYTE* ppbAtr = (LPBYTE*) pbAtr; + *ppbAtr = (LPBYTE) SCardAllocate(dwAtrLen); + *pcbAtrLen = (DWORD) dwAtrLen; + memcpy(*ppbAtr,atr,dwAtrLen); + } + else if(*pcbAtrLen < dwAtrLen) + { + *pcbAtrLen = dwAtrLen; + lRet = SCARD_E_INSUFFICIENT_BUFFER; + } + else + { + *pcbAtrLen = dwAtrLen; + memcpy(pbAtr,atr,dwAtrLen); + } + + goto end_label; + } + + /* case 2: reader names pointer provided but its length is unsufficient */ + if(*pcchReaderLen < dwNameLen) + { + *pcchReaderLen = (DWORD) dwNameLen; + lRet = SCARD_E_INSUFFICIENT_BUFFER; + goto end_label; + } + + bHasAutoAllocated = (*pcchReaderLen == SCARD_AUTOALLOCATE)? TRUE : FALSE; + if(bHasAutoAllocated) + szNames = (LPSTR) SCardAllocate(dwNameLen); + else + szNames = mszReaderNames; + + params.hCard = hCard; + params.mszReaderName = szNames; + params.pcchReaderLen = &dwNameLen; + params.pdwState = pdwStateLite; + params.pdwProtocol = pdwProtocolLite; + params.pbAtr = atr; + params.pcbAtrLen = &dwAtrLen; + + lRet = WINSCARD_CALL( SCardStatus, ¶ms ); + if(lRet != SCARD_S_SUCCESS) + { + if(bHasAutoAllocated) + SCardFree(szNames); + goto end_label; + } + + *pcchReaderLen = (DWORD) dwNameLen; + if(bHasAutoAllocated) + { + LPSTR* pmszReaderNames = (LPSTR*) mszReaderNames; + *pmszReaderNames = szNames; + szNames = NULL; + } + + + /* now fill the ATR parameter */ + if(!pbAtr) + *pcbAtrLen = (DWORD) dwAtrLen; + else if(*pcbAtrLen == SCARD_AUTOALLOCATE) + { + LPBYTE* ppbAtr = (LPBYTE*) pbAtr; + *ppbAtr = (LPBYTE) SCardAllocate(dwAtrLen); + *pcbAtrLen = (DWORD) dwAtrLen; + memcpy(*ppbAtr,atr,dwAtrLen); + } + else if(*pcbAtrLen < dwAtrLen) + { + *pcbAtrLen = (DWORD) dwAtrLen; + lRet = SCARD_E_INSUFFICIENT_BUFFER; + } + else + { + *pcbAtrLen = (DWORD) dwAtrLen; + memcpy(pbAtr,atr,dwAtrLen); + } + + if(bHasAutoAllocated && szNames) + SCardFree(szNames); + } + else + { + if (pcchReaderLen) + { + dwNameLen = *pcchReaderLen; + pdwNameLenLite = &dwNameLen; + } + else + pdwNameLenLite = NULL; + if (pcbAtrLen) + { + dwAtrLen = *pcbAtrLen; + pdwAtrLenLite = &dwAtrLen; + } + else + pdwAtrLenLite = NULL; + + params.hCard = hCard; + params.mszReaderName = mszReaderNames; + params.pcchReaderLen = pdwNameLenLite; + params.pdwState = pdwStateLite; + params.pdwProtocol = pdwProtocolLite; + params.pbAtr = pbAtr; + params.pcbAtrLen = pdwAtrLenLite; + + lRet = WINSCARD_CALL( SCardStatus, ¶ms ); + if (pdwState) + { + *pdwState = (DWORD) dwState; + } + if (pdwProtocol) + { + *pdwProtocol = lite_proto2ms_proto(dwProtocol); + } + if (pcchReaderLen) + { + *pcchReaderLen = dwNameLen; + } + if (pcbAtrLen) + { + *pcbAtrLen = dwAtrLen; + } + } + } + +end_label: + TRACE(" returned %#lx\n",lRet); + return TranslateToWin32(lRet); +} + +LONG WINAPI SCardStatusW( + SCARDHANDLE hCard, + LPWSTR mszReaderNames, + LPDWORD pcchReaderLen, + LPDWORD pdwState, + LPDWORD pdwProtocol, + LPBYTE pbAtr, + LPDWORD pcbAtrLen) +{ + LONG lRet; + TRACE(" 0x%08X %p %p %p %p %p %p\n",(unsigned int) hCard,mszReaderNames,pcchReaderLen,pdwState,pdwProtocol,pbAtr,pcbAtrLen); + if(!pcchReaderLen || !pdwState || !pdwProtocol || !pcbAtrLen) + lRet = SCARD_E_INVALID_PARAMETER; + else + { + /* call the ANSI version with SCARD_AUTOALLOCATE */ + LPSTR mszReaderNamesA = NULL; + DWORD dwAnsiNamesLength = SCARD_AUTOALLOCATE; + lRet = SCardStatusA(hCard,(LPSTR) &mszReaderNamesA,&dwAnsiNamesLength,pdwState,pdwProtocol,pbAtr,pcbAtrLen); + if(lRet == SCARD_S_SUCCESS) + { + /* convert mszReaderNamesA to a wide char multi-string */ + LPWSTR mszWideNamesList = NULL; + DWORD dwWideNamesLength = 0; + lRet = ConvertListToWideChar(mszReaderNamesA,&mszWideNamesList,&dwWideNamesLength); + + /* no more needed */ + if(mszReaderNamesA) + SCardFree(mszReaderNamesA); + + if(lRet == SCARD_S_SUCCESS) + { + if(!mszReaderNames) + *pcchReaderLen = dwWideNamesLength; + else if(*pcchReaderLen == SCARD_AUTOALLOCATE) + { + LPWSTR* pmszReaderNames = (LPWSTR*) mszReaderNames; + *pmszReaderNames = mszWideNamesList; + *pcchReaderLen = dwWideNamesLength; + mszWideNamesList = NULL; + } + else if(*pcchReaderLen < dwWideNamesLength) + { + *pcchReaderLen = dwWideNamesLength; + lRet = SCARD_E_INSUFFICIENT_BUFFER; + } + else + { + *pcchReaderLen = dwWideNamesLength; + memcpy(mszReaderNames,mszWideNamesList,dwWideNamesLength); + } + } + + if(mszWideNamesList) + SCardFree(mszWideNamesList); + } + } + + TRACE(" returned %#lx\n",lRet); + return TranslateToWin32(lRet); +} + +LONG WINAPI SCardGetStatusChangeA( + SCARDCONTEXT hContext, + DWORD dwTimeout, + LPSCARD_READERSTATEA rgReaderStates, + DWORD cReaders) +{ + LONG lRet; + struct SCardGetStatusChange_params params; + TRACE(" 0x%08X %#lx %p %#lx\n",(unsigned int) hContext, dwTimeout,rgReaderStates,cReaders); + if(!rgReaderStates && cReaders) + lRet = SCARD_E_INVALID_PARAMETER; + else if(!cReaders) + { + lRet = SCardIsValidContext(hContext); + } + else + { + DWORD i; + LPSCARD_READERSTATE_LITE pStates = (LPSCARD_READERSTATE_LITE) SCardAllocate(cReaders * sizeof(SCARD_READERSTATE_LITE)); + memset(pStates,0,cReaders * sizeof(SCARD_READERSTATE_LITE)); + for(i=0;i<cReaders;i++) + { + pStates[i].szReader = rgReaderStates[i].szReader; + pStates[i].pvUserData = rgReaderStates[i].pvUserData; + } + + /* in pcsclite, dwTimeout = 0 is equivalent to dwTimeout = INFINITE + * In Windows, dwTimeout = 0 means return immediately + * We will simulate an immediate return + */ + if(dwTimeout == 0) + { + /* get the current state of readers and compare it with input + * Return SCARD_S_SUCCESS if a change is detected and + * SCARD_E_TIMEOUT otherwide + */ + params.hContext = hContext; + params.dwTimeout = 0; + params.rgReaderStates = pStates; + params.cReaders = cReaders; + lRet = WINSCARD_CALL( SCardGetStatusChange, ¶ms ); + if(lRet == SCARD_S_SUCCESS) + { + BOOL bStateChanges = FALSE; + for(i=0;i<cReaders;i++) + { + DWORD dwState = pStates[i].dwEventState & (~SCARD_STATE_CHANGED); + rgReaderStates[i].cbAtr = pStates[i].cbAtr; + memcpy(rgReaderStates[i].rgbAtr,pStates[i].rgbAtr,min (rgReaderStates[i].cbAtr, sizeof (rgReaderStates[i].rgbAtr))); + + if(dwState != rgReaderStates[i].dwCurrentState) + { + rgReaderStates[i].dwEventState = pStates[i].dwEventState; + bStateChanges = TRUE; + } + else + rgReaderStates[i].dwEventState = dwState; + } + + if(!bStateChanges) + lRet = SCARD_E_TIMEOUT; + } + } + else + { + for(i=0;i<cReaders;i++) + { + pStates[i].dwCurrentState = rgReaderStates[i].dwCurrentState; + pStates[i].dwEventState = rgReaderStates[i].dwEventState; + pStates[i].cbAtr = min (MAX_ATR_SIZE, rgReaderStates[i].cbAtr); + memcpy(pStates[i].rgbAtr,rgReaderStates[i].rgbAtr,pStates[i].cbAtr); + } + + params.hContext = hContext; + params.dwTimeout = dwTimeout; + params.rgReaderStates = pStates; + params.cReaders = cReaders; + lRet = WINSCARD_CALL( SCardGetStatusChange, ¶ms ); + + for(i=0;i<cReaders;i++) + { + rgReaderStates[i].dwCurrentState = pStates[i].dwCurrentState; + rgReaderStates[i].dwEventState = pStates[i].dwEventState; + rgReaderStates[i].cbAtr = pStates[i].cbAtr; + memcpy(rgReaderStates[i].rgbAtr,pStates[i].rgbAtr, MAX_ATR_SIZE); + } + } + + SCardFree(pStates); + } + + TRACE(" returned %#lx\n",lRet); + return TranslateToWin32(lRet); +} + +LONG WINAPI SCardGetStatusChangeW( + SCARDCONTEXT hContext, + DWORD dwTimeout, + LPSCARD_READERSTATEW rgReaderStates, + DWORD cReaders) +{ + LONG lRet; + TRACE(" 0x%08X %#lx %p %#lx\n",(unsigned int) hContext, dwTimeout,rgReaderStates,cReaders); + if(!rgReaderStates && cReaders) + lRet = SCARD_E_INVALID_PARAMETER; + else if(!cReaders) + { + lRet = SCardIsValidContext(hContext); + } + else + { + /* create an ANSI array of readers states* */ + DWORD i; + LPSCARD_READERSTATEA rgReaderStatesAnsi = (LPSCARD_READERSTATEA) SCardAllocate(cReaders * sizeof(SCARD_READERSTATEA)); + if(!rgReaderStatesAnsi) + return SCARD_E_NO_MEMORY; + memset(rgReaderStatesAnsi,0,cReaders * sizeof(SCARD_READERSTATEA)); + for(i=0;i<cReaders;i++) + { + int alen = WideCharToMultiByte(CP_ACP,0,rgReaderStates[i].szReader,-1,NULL,0,NULL,NULL); + if(!alen) + break; + rgReaderStatesAnsi[i].szReader = (LPSTR) SCardAllocate(alen); + WideCharToMultiByte(CP_ACP,0,rgReaderStates[i].szReader,-1,(LPSTR) rgReaderStatesAnsi[i].szReader,alen,NULL,NULL); + rgReaderStatesAnsi[i].pvUserData = rgReaderStates[i].pvUserData; + rgReaderStatesAnsi[i].dwCurrentState = rgReaderStates[i].dwCurrentState; + rgReaderStatesAnsi[i].dwEventState = rgReaderStates[i].dwEventState; + rgReaderStatesAnsi[i].cbAtr = rgReaderStates[i].cbAtr; + memcpy(rgReaderStatesAnsi[i].rgbAtr,rgReaderStates[i].rgbAtr, sizeof (rgReaderStatesAnsi[i].rgbAtr)); + } + + if(i < cReaders) + lRet = SCARD_F_UNKNOWN_ERROR; + else + { + lRet = SCardGetStatusChangeA(hContext,dwTimeout,rgReaderStatesAnsi,cReaders); + /* copy back the information */ + for(i=0;i<cReaders;i++) + { + rgReaderStates[i].dwEventState = rgReaderStatesAnsi[i].dwEventState; + rgReaderStates[i].cbAtr = rgReaderStatesAnsi[i].cbAtr; + memcpy(rgReaderStates[i].rgbAtr,rgReaderStatesAnsi[i].rgbAtr, sizeof (rgReaderStates[i].rgbAtr)); + } + } + /* free memory */ + for(i=0;i<cReaders;i++) + { + if(rgReaderStatesAnsi[i].szReader) + SCardFree((void*) rgReaderStatesAnsi[i].szReader); + } + SCardFree(rgReaderStatesAnsi); + } + + TRACE(" returned %#lx\n",lRet); + return TranslateToWin32(lRet); +} + +LONG WINAPI SCardControl( + SCARDHANDLE hCard, + DWORD dwControlCode, + LPCVOID pbSendBuffer, + DWORD cbSendLength, + LPVOID pbRecvBuffer, + DWORD cbRecvLength, + LPDWORD lpBytesReturned) +{ + struct SCardControl_params params = { hCard, dwControlCode, pbSendBuffer, cbSendLength, pbRecvBuffer, cbRecvLength, NULL }; + DWORD_LITE dwBytesReturned = 0; + LONG lRet; + if (lpBytesReturned) + { + dwBytesReturned = *lpBytesReturned; + params.lpBytesReturned = &dwBytesReturned; + } + lRet = WINSCARD_CALL( SCardControl, ¶ms ); + if (lpBytesReturned) + *lpBytesReturned = dwBytesReturned; + return TranslateToWin32(lRet); +} + +LONG WINAPI SCardTransmit( + SCARDHANDLE hCard, + LPCSCARD_IO_REQUEST pioSendPci, + const BYTE* pbSendBuffer, + DWORD cbSendLength, + LPSCARD_IO_REQUEST pioRecvPci, + LPBYTE pbRecvBuffer, + LPDWORD pcbRecvLength) +{ + LONG lRet; + struct SCardTransmit_params params; + DWORD_LITE dwRecvLength = 0; + LPDWORD_LITE pdwRecvLengthLite = NULL; + SCARD_IO_REQUEST_LITE ioSendPci, ioRecvPci; + ioSendPci.cbPciLength = sizeof(ioSendPci); + ioRecvPci.cbPciLength = sizeof(ioRecvPci); + + if (pcbRecvLength) + { + dwRecvLength = *pcbRecvLength; + pdwRecvLengthLite = &dwRecvLength; + } + + if (pioRecvPci) { + ioRecvPci.dwProtocol = ms_proto2lite_proto(pioRecvPci->dwProtocol); + } + + if(pioSendPci) + { + ioSendPci.dwProtocol = ms_proto2lite_proto(pioSendPci->dwProtocol); + } + else + { + /* In MS PC/SC, pioSendPci can be NULL. But not in pcsc-lite */ + /* Get the protocol and set the correct value for pioSendPci*/ + DWORD protocol,dwState; + DWORD dwAtrLen,dwNameLen; + lRet = SCardStatusA(hCard,NULL,&dwNameLen,&dwState,&protocol,NULL,&dwAtrLen); + if(lRet == SCARD_S_SUCCESS) + { + ioSendPci.dwProtocol = ms_proto2lite_proto(protocol); + } + else + goto transmit_end; + } + + params.hCard = hCard; + params.pioSendPci = &ioSendPci; + params.pbSendBuffer = pbSendBuffer; + params.cbSendLength = cbSendLength; + params.pioRecvPci = pioRecvPci? &ioRecvPci : NULL; + params.pbRecvBuffer = pbRecvBuffer; + params.pcbRecvLength = pdwRecvLengthLite; + lRet = WINSCARD_CALL( SCardTransmit, ¶ms ); + + if (pcbRecvLength) + *pcbRecvLength = dwRecvLength; + +transmit_end: + return TranslateToWin32(lRet); +} + +LONG WINAPI SCardCancel(SCARDCONTEXT hContext) +{ + LONG lRet; + struct SCardCancel_params params = { hContext }; + TRACE(" 0x%08X \n",(unsigned int) hContext); + lRet = WINSCARD_CALL( SCardCancel, ¶ms ); + + TRACE(" returned %#lx\n",lRet); + return TranslateToWin32(lRet); +} + +LONG WINAPI SCardGetAttrib( + SCARDHANDLE hCard, + DWORD dwAttrId, + LPBYTE pbAttr, + LPDWORD pcbAttrLen) +{ + LONG lRet; + TRACE(" 0x%08X %#lx %p %p \n",(unsigned int) hCard, dwAttrId,pbAttr,pcbAttrLen); + if(!pcbAttrLen) + lRet = SCARD_E_INVALID_PARAMETER; + else + { + LPBYTE ptr = NULL; + DWORD_LITE dwLength = 0; + struct SCardGetAttrib_params params = {hCard, dwAttrId, NULL, &dwLength}; + lRet = WINSCARD_CALL( SCardGetAttrib, ¶ms ); + if(lRet == SCARD_S_SUCCESS || lRet == SCARD_E_INSUFFICIENT_BUFFER) + { + if(!pbAttr) + *pcbAttrLen = (DWORD) dwLength; + else if(*pcbAttrLen < (DWORD) dwLength) + { + *pcbAttrLen = (DWORD) dwLength; + lRet = SCARD_E_INSUFFICIENT_BUFFER; + } + else + { + BOOL bHasAutoAllocate = (*pcbAttrLen == SCARD_AUTOALLOCATE)? TRUE : FALSE; + if(bHasAutoAllocate) + ptr = (LPBYTE) SCardAllocate((DWORD) dwLength); + else + ptr = pbAttr; + + params.hCard = hCard; + params.dwAttrId = dwAttrId; + params.pbAttr = ptr; + params.pcbAttrLen = &dwLength; + lRet = WINSCARD_CALL( SCardGetAttrib, ¶ms ); + + if(lRet == SCARD_S_SUCCESS) + { + *pcbAttrLen = (DWORD) dwLength; + if(bHasAutoAllocate) + { + LPBYTE *ppbAttr = (LPBYTE*) pbAttr; + *ppbAttr = ptr; + ptr = NULL; + } + } + + if(bHasAutoAllocate && ptr) + SCardFree(ptr); + } + } + + if(SCARD_E_UNSUPPORTED_FEATURE == TranslateToWin32(lRet)) + { + /* in case of one of these attributes , do it our selves */ + if(SCARD_ATTR_ICC_PRESENCE == dwAttrId || SCARD_ATTR_CURRENT_PROTOCOL_TYPE == dwAttrId + || SCARD_ATTR_ATR_STRING == dwAttrId || SCARD_ATTR_DEVICE_FRIENDLY_NAME_A == dwAttrId + || SCARD_ATTR_DEVICE_FRIENDLY_NAME_W == dwAttrId + || SCARD_ATTR_DEVICE_SYSTEM_NAME_A == dwAttrId + || SCARD_ATTR_DEVICE_SYSTEM_NAME_W == dwAttrId) + { + DWORD dwState; + DWORD dwProtocol; + BYTE pbAtr[MAX_ATR_SIZE]; + DWORD dwAtrLen =MAX_ATR_SIZE; + LPVOID pszReaderNames = NULL; + DWORD dwNameLength = SCARD_AUTOALLOCATE; + LONG status; + + if(SCARD_ATTR_DEVICE_SYSTEM_NAME_W == dwAttrId + || SCARD_ATTR_DEVICE_FRIENDLY_NAME_W == dwAttrId) + status = SCardStatusW(hCard,(LPWSTR) &pszReaderNames, &dwNameLength, &dwState,&dwProtocol, pbAtr,&dwAtrLen); + else + status = SCardStatusA(hCard,(LPSTR) &pszReaderNames, &dwNameLength, &dwState,&dwProtocol, pbAtr,&dwAtrLen); + if(SCARD_S_SUCCESS == status) + { + BYTE pbValue[MAX_ATR_SIZE]; + DWORD dwValueLen = 0; + LPBYTE pValuePtr = &pbValue[0]; + if(SCARD_ATTR_ICC_PRESENCE == dwAttrId) + { + dwValueLen = 1; + pbValue[0] = 1; /* present by default */ + if(dwState == SCARD_ABSENT) + pbValue[0] = 0; + else if(dwState == SCARD_SWALLOWED) + pbValue[0] = 2; + } + else if(SCARD_ATTR_CURRENT_PROTOCOL_TYPE == dwAttrId) + { + dwValueLen = 4; + memcpy(pbValue,&dwProtocol,4); + } + else if(SCARD_ATTR_DEVICE_FRIENDLY_NAME_A == dwAttrId || + SCARD_ATTR_DEVICE_SYSTEM_NAME_A == dwAttrId) + { + pValuePtr = (LPBYTE) pszReaderNames; + dwValueLen = dwNameLength ; + } + else if(SCARD_ATTR_DEVICE_FRIENDLY_NAME_W == dwAttrId || + SCARD_ATTR_DEVICE_SYSTEM_NAME_W == dwAttrId) + { + pValuePtr = (LPBYTE) pszReaderNames; + dwValueLen = dwNameLength * sizeof(WCHAR); + } + else /* ATR case */ + { + dwValueLen = dwAtrLen; + memcpy(pbValue,pbAtr,dwAtrLen); + } + + lRet = SCARD_S_SUCCESS; + if(!pbAttr) + *pcbAttrLen =dwValueLen; + else if(*pcbAttrLen == SCARD_AUTOALLOCATE) + { + LPBYTE *ppbAttr = (LPBYTE*) pbAttr; + *ppbAttr = (LPBYTE) SCardAllocate(dwValueLen); + memcpy(*ppbAttr,pValuePtr,dwValueLen); + *pcbAttrLen = dwValueLen; + } + else if(*pcbAttrLen < dwValueLen) + { + *pcbAttrLen = dwValueLen; + lRet = SCARD_E_INSUFFICIENT_BUFFER; + } + else + { + *pcbAttrLen = dwValueLen; + memcpy(pbAttr,pValuePtr,dwValueLen); + } + + SCardFree(pszReaderNames); + } + } + } + } + TRACE(" returned %#lx \n",lRet); + return TranslateToWin32(lRet); +} + +LONG WINAPI SCardSetAttrib( + SCARDHANDLE hCard, + DWORD dwAttrId, + const BYTE* pbAttr, + DWORD cbAttrLen) +{ + LONG lRet; + struct SCardSetAttrib_params params = {hCard, dwAttrId, pbAttr, cbAttrLen}; + TRACE(" 0x%08X %#lx %p %#lx \n",(unsigned int) hCard,dwAttrId,pbAttr,cbAttrLen); + lRet = WINSCARD_CALL( SCardGetAttrib, ¶ms ); + TRACE(" returned %#lx \n",lRet); + return TranslateToWin32(lRet); } diff --git a/dlls/winscard/winscard.spec b/dlls/winscard/winscard.spec index 037d3bef903..58c571823b2 100644 --- a/dlls/winscard/winscard.spec +++ b/dlls/winscard/winscard.spec @@ -1,63 +1,63 @@ @ stub ClassInstall32 -@ stub SCardAccessNewReaderEvent -@ stub SCardReleaseAllEvents -@ stub SCardReleaseNewReaderEvent +@ stdcall SCardAccessNewReaderEvent() +@ stub SCardReleaseAllEvents() +@ stub SCardReleaseNewReaderEvent() @ stdcall SCardAccessStartedEvent() @ stdcall SCardAddReaderToGroupA(long str str) @ stdcall SCardAddReaderToGroupW(long wstr wstr) -@ stub SCardBeginTransaction +@ stdcall SCardBeginTransaction(long) @ stdcall SCardCancel(long) -@ stub SCardConnectA -@ stub SCardConnectW -@ stub SCardControl -@ stub SCardDisconnect -@ stub SCardEndTransaction +@ stdcall SCardConnectA(long str long long ptr ptr) +@ stdcall SCardConnectW(long wstr long long ptr ptr) +@ stdcall SCardControl(long long ptr long ptr long ptr) +@ stdcall SCardDisconnect(long long) +@ stdcall SCardEndTransaction(long long) @ stdcall SCardEstablishContext(long ptr ptr ptr) -@ stub SCardForgetCardTypeA -@ stub SCardForgetCardTypeW -@ stub SCardForgetReaderA -@ stub SCardForgetReaderGroupA -@ stub SCardForgetReaderGroupW -@ stub SCardForgetReaderW -@ stub SCardFreeMemory -@ stub SCardGetAttrib -@ stub SCardGetCardTypeProviderNameA -@ stub SCardGetCardTypeProviderNameW -@ stub SCardGetProviderIdA -@ stub SCardGetProviderIdW -@ stub SCardGetStatusChangeA -@ stub SCardGetStatusChangeW -@ stub SCardIntroduceCardTypeA -@ stub SCardIntroduceCardTypeW -@ stub SCardIntroduceReaderA -@ stub SCardIntroduceReaderGroupA -@ stub SCardIntroduceReaderGroupW -@ stub SCardIntroduceReaderW +@ stdcall SCardForgetCardTypeA(long str) +@ stdcall SCardForgetCardTypeW(long wstr) +@ stdcall SCardForgetReaderA(long str) +@ stdcall SCardForgetReaderGroupA(long str) +@ stdcall SCardForgetReaderGroupW(long wstr) +@ stdcall SCardForgetReaderW(long wstr) +@ stdcall SCardFreeMemory(long ptr) +@ stdcall SCardGetAttrib(long long ptr ptr) +@ stdcall SCardGetCardTypeProviderNameA(long str long str ptr) +@ stdcall SCardGetCardTypeProviderNameW(long wstr long wstr ptr) +@ stdcall SCardGetProviderIdA(long str ptr) +@ stdcall SCardGetProviderIdW(long wstr ptr) +@ stdcall SCardGetStatusChangeA(long long ptr long) +@ stdcall SCardGetStatusChangeW(long long ptr long) +@ stdcall SCardIntroduceCardTypeA(long str ptr ptr long ptr ptr long) +@ stdcall SCardIntroduceCardTypeW(long wstr ptr ptr long ptr ptr long) +@ stdcall SCardIntroduceReaderA(long str str) +@ stdcall SCardIntroduceReaderGroupA(long str) +@ stdcall SCardIntroduceReaderGroupW(long wstr) +@ stdcall SCardIntroduceReaderW(long wstr wstr) @ stdcall SCardIsValidContext(long) @ stdcall SCardListCardsA(long ptr ptr long str ptr) -@ stub SCardListCardsW -@ stub SCardListInterfacesA -@ stub SCardListInterfacesW -@ stub SCardListReaderGroupsA -@ stub SCardListReaderGroupsW -@ stdcall SCardListReadersA(long str ptr ptr) -@ stdcall SCardListReadersW(long wstr ptr ptr) -@ stub SCardLocateCardsA -@ stub SCardLocateCardsByATRA -@ stub SCardLocateCardsByATRW -@ stub SCardLocateCardsW -@ stub SCardReconnect +@ stdcall SCardListCardsW(long ptr ptr long wstr ptr) +@ stdcall SCardListInterfacesA(long str ptr ptr) +@ stdcall SCardListInterfacesW(long wstr ptr ptr) +@ stdcall SCardListReaderGroupsA(long str ptr) +@ stdcall SCardListReaderGroupsW(long wstr ptr) +@ stdcall SCardListReadersA(long str str ptr) +@ stdcall SCardListReadersW(long wstr wstr ptr) +@ stdcall SCardLocateCardsA(long str ptr long) +@ stdcall SCardLocateCardsByATRA(long ptr long ptr long) +@ stdcall SCardLocateCardsByATRW(long ptr long ptr long) +@ stdcall SCardLocateCardsW(long wstr ptr long) +@ stdcall SCardReconnect(long long long long ptr) @ stdcall SCardReleaseContext(long) -@ stdcall SCardReleaseStartedEvent() -@ stub SCardRemoveReaderFromGroupA -@ stub SCardRemoveReaderFromGroupW -@ stub SCardSetAttrib -@ stub SCardSetCardTypeProviderNameA -@ stub SCardSetCardTypeProviderNameW -@ stub SCardState +@ stub SCardReleaseStartedEvent() +@ stdcall SCardRemoveReaderFromGroupA(long str str) +@ stdcall SCardRemoveReaderFromGroupW(long wstr wstr) +@ stdcall SCardSetAttrib(long long ptr long) +@ stdcall SCardSetCardTypeProviderNameA(long str long str) +@ stdcall SCardSetCardTypeProviderNameW(long wstr long wstr) +@ stdcall SCardState(long ptr ptr ptr ptr) @ stdcall SCardStatusA(long str ptr ptr ptr ptr ptr) @ stdcall SCardStatusW(long wstr ptr ptr ptr ptr ptr) -@ stub SCardTransmit +@ stdcall SCardTransmit(long ptr ptr long ptr ptr ptr) @ extern g_rgSCardRawPci -@ extern g_rgSCardT0Pci +@ extern g_rgSCardT0Pci @ extern g_rgSCardT1Pci diff --git a/include/winscard.h b/include/winscard.h index 5aee1b3e548..01780280c20 100644 --- a/include/winscard.h +++ b/include/winscard.h @@ -24,11 +24,6 @@ #include <winsmcrd.h> #include <scarderr.h>
-/* Valid scopes for contexts */ -#define SCARD_SCOPE_USER 0 -#define SCARD_SCOPE_TERMINAL 1 -#define SCARD_SCOPE_SYSTEM 2 - #ifndef _LPCBYTE_DEFINED #define _LPCBYTE_DEFINED typedef const BYTE *LPCBYTE; @@ -66,24 +61,6 @@ DECL_WINELIB_TYPE_AW(SCARD_READERSTATE) DECL_WINELIB_TYPE_AW(PSCARD_READERSTATE) DECL_WINELIB_TYPE_AW(LPSCARD_READERSTATE)
-#define SCARD_AUTOALLOCATE (DWORD)(-1) - -#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
#ifdef __cplusplus extern "C" { @@ -138,8 +115,8 @@ LONG WINAPI SCardListCardsW(SCARDCONTEXT,LPCBYTE,LPCGUID,DWORD,LPWSTR,LPD LONG WINAPI SCardListInterfacesA(SCARDCONTEXT,LPCSTR,LPGUID,LPDWORD); LONG WINAPI SCardListInterfacesW(SCARDCONTEXT,LPCWSTR,LPGUID,LPDWORD); #define SCardListInterfaces WINELIB_NAME_AW(SCardListInterfaces) -LONG WINAPI SCardListReadersA(SCARDCONTEXT,const CHAR *,CHAR *,DWORD *); -LONG WINAPI SCardListReadersW(SCARDCONTEXT,const WCHAR *,WCHAR *,DWORD *); +LONG WINAPI SCardListReadersA(SCARDCONTEXT,LPCSTR,LPSTR,LPDWORD); +LONG WINAPI SCardListReadersW(SCARDCONTEXT,LPCWSTR,LPWSTR,LPDWORD); #define SCardListReaders WINELIB_NAME_AW(SCardListReaders) LONG WINAPI SCardListReaderGroupsA(SCARDCONTEXT,LPSTR,LPDWORD); LONG WINAPI SCardListReaderGroupsW(SCARDCONTEXT,LPWSTR,LPDWORD); @@ -152,7 +129,7 @@ LONG WINAPI SCardLocateCardsByATRW(SCARDCONTEXT,LPSCARD_ATRMASK,DWORD,LPS #define SCardLocateCardsByATR WINELIB_NAME_AW(SCardLocateCardsByATR) LONG WINAPI SCardReconnect(SCARDHANDLE,DWORD,DWORD,DWORD,LPDWORD); LONG WINAPI SCardReleaseContext(SCARDCONTEXT); -void WINAPI SCardReleaseStartedEvent(void); +void WINAPI SCardReleaseStartedEvent(HANDLE hStartedEventHandle); LONG WINAPI SCardRemoveReaderFromGroupA(SCARDCONTEXT,LPCSTR,LPCSTR); LONG WINAPI SCardRemoveReaderFromGroupW(SCARDCONTEXT,LPCWSTR,LPCWSTR); #define SCardRemoveReaderFromGroup WINELIB_NAME_AW(SCardRemoveReaderFromGroup) diff --git a/include/winsmcrd.h b/include/winsmcrd.h index 60fdd3e492c..dd045b57afa 100644 --- a/include/winsmcrd.h +++ b/include/winsmcrd.h @@ -1,5 +1,5 @@ /* - * Winscard definitions + * Copyright 2007 Mounir IDRASSI (mounir.idrassi@idrix.fr, for IDRIX) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,22 +16,117 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
-#ifndef __WINE_WINSMCRD_H -#define __WINE_WINSMCRD_H
-#define SCARD_PROTOCOL_UNDEFINED 0x00000000 -#define SCARD_PROTOCOL_OPTIMAL 0x00000000 -#define SCARD_PROTOCOL_T0 0x00000001 -#define SCARD_PROTOCOL_T1 0x00000002 -#define SCARD_PROTOCOL_RAW 0x00010000 -#define SCARD_PROTOCOL_DEFAULT 0x80000000 -#define SCARD_PROTOCOL_Tx (SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1) +#ifndef _WINE_WINSCMCRD_H +#define _WINE_WINSCMCRD_H
+ +#define MAX_ATR_SIZE 36 /* Maximum ATR size */ + +#ifndef SCARD_ATR_LENGTH +#define SCARD_ATR_LENGTH MAX_ATR_SIZE +#endif + +/* + * These values define the protocol used to + * communicate with the card + */ +#define SCARD_PROTOCOL_UNDEFINED 0x00000000 /* No protocol defined */ +#define SCARD_PROTOCOL_T0 0x00000001 /* T=0 protocol. */ +#define SCARD_PROTOCOL_T1 0x00000002 /* T=1 protocol */ +#define SCARD_PROTOCOL_RAW 0x00010000 /* Raw protocol, for memory card for example */ +#define SCARD_PROTOCOL_Tx (SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1) /* Can be used in SCardConnect */ + +/* + * The following value is used as a length value + * in functions where we want the winscard dll + * to allocate memory for us + */ +#define SCARD_AUTOALLOCATE (DWORD)(-1) + +/* + * Values used by SCardEstablishContext + */ +#define SCARD_SCOPE_USER 0x0000 /* context in user scope */ +#define SCARD_SCOPE_TERMINAL 0x0001 /* context in terminal scope */ +#define SCARD_SCOPE_SYSTEM 0x0002 /* context in system scope */ + +/* + * Flags used by SCardGetStatusChange to indicate + * the reader status. + */ +#define SCARD_STATE_UNAWARE 0x0000 /* called want to know the current state */ +#define SCARD_STATE_IGNORE 0x0001 /* don't update the state for the given reader */ +#define SCARD_STATE_CHANGED 0x0002 /* reader state has not changed */ +#define SCARD_STATE_UNKNOWN 0x0004 /* reader state unknown */ +#define SCARD_STATE_UNAVAILABLE 0x0008 /* reader state unavailable */ +#define SCARD_STATE_EMPTY 0x0010 /* no card on the reader*/ +#define SCARD_STATE_PRESENT 0x0020 /* card present on the reader */ +#define SCARD_STATE_ATRMATCH 0x0040 /* card's ATR matches the given ATR */ +#define SCARD_STATE_EXCLUSIVE 0x0080 /* an exclusive connection on the card exists*/ +#define SCARD_STATE_INUSE 0x0100 /* card in use but the connection can be shared */ +#define SCARD_STATE_MUTE 0x0200 /* card is mute, doesn't answer to reset */ +#define SCARD_STATE_UNPOWERED 0x0400 /* card present but not powered */ + + +/* + * These values define how SCardConnect should + * connect to the card + */ +#define SCARD_SHARE_EXCLUSIVE 0x0001 /* connect to the card in exclusive mode (no other connection allowed) */ +#define SCARD_SHARE_SHARED 0x0002 /* connection can be shared with others */ +#define SCARD_SHARE_DIRECT 0x0003 /* access directly the reader, no other connection allowed */ + +/* + * Values used by SCardDisconnect to specify + * how the card should be treated on closing + * the connection + */ +#define SCARD_LEAVE_CARD 0x0000 /* do nothing */ +#define SCARD_RESET_CARD 0x0001 /* reset the card */ +#define SCARD_UNPOWER_CARD 0x0002 /* unpower the card */ +#define SCARD_EJECT_CARD 0x0003 /* eject the card from the reader if supported */ + +/* + * Values returned by SCardStatus indicating + * the reader's state + */ +#define SCARD_UNKNOWN 0x0001 /* state unknown */ +#define SCARD_ABSENT 0x0002 /* no card on the reader */ +#define SCARD_PRESENT 0x0004 /* card is present on the reader */ +#define SCARD_SWALLOWED 0x0008 /* card inside the reader but not powered */ +#define SCARD_POWERED 0x0010 /* card present and powered */ +#define SCARD_NEGOTIABLE 0x0020 /* card present and ready to negotiate protocol */ +#define SCARD_SPECIFIC 0x0040 /* card has ended protocol negotiation */ + +/* + * definitions used by SCardGetAttrib and SCardSetAttrib for + * requesting and setting readers attributes + * Other values maybe supported + */ +#define SCARD_ATTR_ICC_PRESENCE 0x00090300 +#define SCARD_ATTR_CURRENT_PROTOCOL_TYPE 0x00080201 +#define SCARD_ATTR_ATR_STRING 0x00090303 +#define SCARD_ATTR_DEVICE_FRIENDLY_NAME_A 0x7FFF0003 +#define SCARD_ATTR_DEVICE_FRIENDLY_NAME_W 0x7FFF0005 +#define SCARD_ATTR_DEVICE_SYSTEM_NAME_A 0x7FFF0004 +#define SCARD_ATTR_DEVICE_SYSTEM_NAME_W 0x7FFF0006 + +#define SCARD_ATTR_DEVICE_FRIENDLY_NAME WINELIB_NAME_AW(SCARD_ATTR_DEVICE_FRIENDLY_NAME_) +#define SCARD_ATTR_DEVICE_SYSTEM_NAME WINELIB_NAME_AW(SCARD_ATTR_DEVICE_SYSTEM_NAME_) + + +/* + * This structure is used by SCardTransmit to communicate + * with the card + */ typedef struct _SCARD_IO_REQUEST { - DWORD dwProtocol; - DWORD cbPciLength; -} SCARD_IO_REQUEST, *PSCARD_IO_REQUEST, *LPSCARD_IO_REQUEST; + unsigned long dwProtocol; /* protocol used for this request */ + unsigned long cbPciLength; /* total length of the request data, usually sizeof(SCARD_IO_REQUEST) */ +} +SCARD_IO_REQUEST, *PSCARD_IO_REQUEST, *LPSCARD_IO_REQUEST; + typedef const SCARD_IO_REQUEST *LPCSCARD_IO_REQUEST;
-#endif /* __WINE_WINSMCRD_H */ +#endif
From: Konstantin Romanov incubusrk@gmail.com
reqired runing pcscd and libpcsclite1 testing without hardware can be done with github.com/Jakuje/virt_cacard project --- configure | 1 + dlls/winscard/tests/Makefile.in | 5 + dlls/winscard/tests/winscard.c | 384 ++++++++++++++++++++++++++++++++ 3 files changed, 390 insertions(+) create mode 100644 dlls/winscard/tests/Makefile.in create mode 100644 dlls/winscard/tests/winscard.c
diff --git a/configure b/configure index 5164b21486f..2a75ff727c1 100755 --- a/configure +++ b/configure @@ -21798,6 +21798,7 @@ wine_fn_config_makefile dlls/winnls.dll16 enable_win16 wine_fn_config_makefile dlls/winnls32 enable_winnls32 wine_fn_config_makefile dlls/winprint enable_winprint wine_fn_config_makefile dlls/winscard enable_winscard +wine_fn_config_makefile dlls/winscard/tests enable_tests wine_fn_config_makefile dlls/winsock.dll16 enable_win16 wine_fn_config_makefile dlls/winspool.drv enable_winspool_drv wine_fn_config_makefile dlls/winspool.drv/tests enable_tests diff --git a/dlls/winscard/tests/Makefile.in b/dlls/winscard/tests/Makefile.in new file mode 100644 index 00000000000..46fa9577f53 --- /dev/null +++ b/dlls/winscard/tests/Makefile.in @@ -0,0 +1,5 @@ +TESTDLL = winscard.dll +IMPORTS = winscard + +C_SRCS = \ + winscard.c \ No newline at end of file diff --git a/dlls/winscard/tests/winscard.c b/dlls/winscard/tests/winscard.c new file mode 100644 index 00000000000..797d09f912b --- /dev/null +++ b/dlls/winscard/tests/winscard.c @@ -0,0 +1,384 @@ +/* + * Copyright (C) 2023 Konstantin Romanov + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "windows.h" +#include "winscard.h" +#include "winsmcrd.h" +#include "wine/test.h" + +#ifndef SCARD_PCI_T0 +const SCARD_IO_REQUEST g_rgSCardT0Pci = { SCARD_PROTOCOL_T0, 8 }; +const SCARD_IO_REQUEST g_rgSCardT1Pci = { SCARD_PROTOCOL_T1, 8 }; +#define SCARD_PCI_T0 (&g_rgSCardT0Pci) /**< protocol control information (PCI) for T=0 */ +#define SCARD_PCI_T1 (&g_rgSCardT1Pci) /**< protocol control information (PCI) for T=1 */ +#endif + + +SCARDCONTEXT hContext; + +static void test_winscardA(void) +{ + DWORD dwReaders; + LONG lRet; + LPSTR szReaders = NULL; + LPSTR reader; + int i, nbReaders = 0; + char **readers = NULL; + int reader_nb; + SCARDHANDLE hCard; + DWORD dwActiveProtocol, dwAtrLen, dwReaderLen, dwState, dwProt; + LPSCARD_READERSTATEA lpState = NULL; + BYTE pbAtr[33] = ""; + char pbReader[128] = ""; + + const SCARD_IO_REQUEST* pioSendPci; + SCARD_IO_REQUEST pioRecvPci; + BYTE pbRecvBuffer[10]; + BYTE pbSendBuffer[] = { 0x00, 0xA4, 0x00, 0x00, 0x02, 0x3F, 0x00 }; + DWORD dwSendLength, dwRecvLength; + + dwReaders = SCARD_AUTOALLOCATE; + lRet = SCardListReadersA(hContext, NULL, (LPSTR)&szReaders, &dwReaders); + if (lRet == SCARD_E_NO_READERS_AVAILABLE) { + skip("No readers available. Install vsmartcard-vpcd and restart pcscd\n"); + return; + } else { + ok(lRet == SCARD_S_SUCCESS, "got %#lx\n", lRet); + + reader = szReaders; + while (reader != NULL && *reader != '\0') { + trace("Found smart-card reader: %s\n", wine_dbgstr_a(reader)); + reader += strlen(reader) + 1; + nbReaders++; + } + + readers = calloc(nbReaders, sizeof(char *)); + ok(NULL != readers,"Not enough memory"); + + nbReaders = 0; + reader = szReaders; + while (reader != NULL && *reader != '\0') { + readers[nbReaders] = reader; + reader += strlen(reader) + 1; + nbReaders++; + } + + lpState = (LPSCARD_READERSTATEA)calloc(nbReaders, sizeof(SCARD_READERSTATEA)); + for (i = 0; i < nbReaders; ++i) { + memset(lpState + i, 0, sizeof(SCARD_READERSTATEA)); + lpState[i].szReader = readers[i]; + } + + lRet = SCardGetStatusChangeA(hContext, 500, lpState, nbReaders); + /* search first reader with smartcard */ + reader_nb = -1; + for(i=0; i<nbReaders; i++) + { + if(lpState[i].dwEventState & SCARD_STATE_PRESENT) + { + reader_nb = i; + break; + } + } + ok(lRet == SCARD_S_SUCCESS || lRet == SCARD_E_TIMEOUT, "got %#lx\n", lRet); + if(-1==reader_nb) + { + skip("No smartcard available. Install and start virt_cacard\n"); + goto end; + } + + /* Test SCard connection */ + /* connect to a card */ + dwActiveProtocol = -1; + lRet = SCardConnectA(hContext, readers[reader_nb], SCARD_SHARE_SHARED, + SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol); + ok(lRet == SCARD_S_SUCCESS, "got %#lx\n", lRet); + + /* get card status */ + dwAtrLen = sizeof(pbAtr); + dwReaderLen = sizeof(pbReader); + lRet = SCardStatusA(hCard, /*NULL*/ pbReader, &dwReaderLen, &dwState, &dwProt, + pbAtr, &dwAtrLen); + ok(lRet == SCARD_S_SUCCESS, "got %#lx\n", lRet); + + trace(" Reader: %s (length %ld bytes)\n", pbReader, dwReaderLen); + trace(" State: 0x%lX\n", dwState); + trace(" Prot: %ld\n", dwProt); + trace(" ATR (length %ld bytes):", dwAtrLen); + for (i = 0; i < dwAtrLen; i++) + trace(" %02X", pbAtr[i]); + trace("\n"); + + switch (dwActiveProtocol) + { + case SCARD_PROTOCOL_T0: + pioSendPci = SCARD_PCI_T0; + break; + case SCARD_PROTOCOL_T1: + pioSendPci = SCARD_PCI_T1; + break; + default: + skip("Unknown active protocol\n"); + goto end; + } + pioRecvPci.cbPciLength = sizeof(pioRecvPci); + pioRecvPci.dwProtocol = dwActiveProtocol; + + /* exchange APDU */ + dwSendLength = sizeof(pbSendBuffer); + dwRecvLength = sizeof(pbRecvBuffer); + + trace("Sending: "); + for (i = 0; i < dwSendLength; i++) + trace("%02X ", pbSendBuffer[i]); + trace("\n"); + lRet = SCardTransmit(hCard, pioSendPci, pbSendBuffer, dwSendLength, + &pioRecvPci, pbRecvBuffer, &dwRecvLength); + ok(lRet == SCARD_S_SUCCESS, "got %#lx\t%#lx\n", lRet, GetLastError()); + trace("Received: "); + for (i = 0; i < dwRecvLength; i++) + trace("%02X ", pbRecvBuffer[i]); + trace("\n"); + + /* card reconnect */ + lRet = SCardReconnect(hCard, SCARD_SHARE_SHARED, + SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, SCARD_LEAVE_CARD, + &dwActiveProtocol); + ok(lRet == SCARD_S_SUCCESS, "got %#lx\n", lRet); + + /* get card status after reconnect */ + dwAtrLen = sizeof(pbAtr); + dwReaderLen = sizeof(pbReader); + lRet = SCardStatusA(hCard, /*NULL*/ pbReader, &dwReaderLen, &dwState, &dwProt, + pbAtr, &dwAtrLen); + ok(lRet == SCARD_S_SUCCESS, "got %#lx\n", lRet); + + /* begin transaction */ + lRet = SCardBeginTransaction(hCard); + ok(lRet == SCARD_S_SUCCESS, "got %#lx\n", lRet); + + /* exchange APDU */ + dwSendLength = sizeof(pbSendBuffer); + dwRecvLength = sizeof(pbRecvBuffer); + + lRet = SCardTransmit(hCard, pioSendPci, pbSendBuffer, dwSendLength, + &pioRecvPci, pbRecvBuffer, &dwRecvLength); + + ok(lRet == SCARD_S_SUCCESS, "got %#lx\n", lRet); + + /* end transaction */ + lRet = SCardEndTransaction(hCard, SCARD_LEAVE_CARD); + ok(lRet == SCARD_S_SUCCESS, "got %#lx\n", lRet); + + /* card disconnect */ + lRet = SCardDisconnect(hCard, SCARD_UNPOWER_CARD); + ok(lRet == SCARD_S_SUCCESS, "got %#lx\n", lRet); +end: + if (lpState) + free(lpState); + if (readers) + free(readers); + // only do this after being done with the strings, or handle the names another way! + SCardFreeMemory(hContext, szReaders); + } +} + +static void test_winscardW(void) +{ + DWORD dwReaders; + LONG lRet; + LPWSTR szReaders = NULL; + LPWSTR reader; + int i, nbReaders = 0; + WCHAR **readers = NULL; + int reader_nb; + SCARDHANDLE hCard; + DWORD dwActiveProtocol, dwAtrLen, dwReaderLen, dwState, dwProt; + LPSCARD_READERSTATEW lpState = NULL; + BYTE pbAtr[33] = ""; + WCHAR pbReader[128] = L""; + + const SCARD_IO_REQUEST* pioSendPci; + SCARD_IO_REQUEST pioRecvPci; + BYTE pbRecvBuffer[10]; + BYTE pbSendBuffer[] = { 0x00, 0xA4, 0x00, 0x00, 0x02, 0x3F, 0x00 }; + DWORD dwSendLength, dwRecvLength; + + dwReaders = SCARD_AUTOALLOCATE; + lRet = SCardListReadersW(hContext, NULL, (LPWSTR)&szReaders, &dwReaders); + if (lRet == SCARD_E_NO_READERS_AVAILABLE) { + skip("No readers available. Install vsmartcard-vpcd and restart pcscd\n"); + return; + } else { + ok(lRet == SCARD_S_SUCCESS, "got %#lx\n", lRet); + + reader = szReaders; + while (reader != NULL && *reader != '\0') { + trace("Found smartcard reader: %s\n", wine_dbgstr_w(reader)); + reader += wcslen(reader) + 1; + nbReaders++; + } + + readers = calloc(nbReaders, sizeof(WCHAR *)); + ok(NULL != readers,"Not enough memory"); + + nbReaders = 0; + reader = szReaders; + while (reader != NULL && *reader != '\0') { + readers[nbReaders] = reader; + reader += wcslen(reader) + 1; + nbReaders++; + } + + lpState = (LPSCARD_READERSTATEW)calloc(nbReaders, sizeof(SCARD_READERSTATEW)); + for (i = 0; i < nbReaders; ++i) { + memset(lpState + i, 0, sizeof(SCARD_READERSTATEW)); + lpState[i].szReader = readers[i]; + } + + lRet = SCardGetStatusChangeW(hContext, 500, lpState, nbReaders); + /* search first reader with smartcard */ + reader_nb = -1; + for(i=0; i<nbReaders; i++) + { + if(lpState[i].dwEventState & SCARD_STATE_PRESENT) + { + reader_nb = i; + break; + } + } + ok(lRet == SCARD_S_SUCCESS || lRet == SCARD_E_TIMEOUT, "got %#lx\n", lRet); + if(-1==reader_nb) + { + skip("No smartcard available. Install and start virt_cacard\n"); + goto end; + } + + /* Test SCard connection */ + /* connect to a card */ + dwActiveProtocol = -1; + lRet = SCardConnectW(hContext, readers[reader_nb], SCARD_SHARE_SHARED, + SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol); + ok(lRet == SCARD_S_SUCCESS, "got %#lx\n", lRet); + + /* get card status */ + dwAtrLen = sizeof(pbAtr); + dwReaderLen = sizeof(pbReader); + lRet = SCardStatusW(hCard, /*NULL*/ pbReader, &dwReaderLen, &dwState, &dwProt, + pbAtr, &dwAtrLen); + ok(lRet == SCARD_S_SUCCESS, "got %#lx\n", lRet); + + trace(" Reader: %s (length %ld bytes)\n", pbReader, dwReaderLen); + trace(" State: 0x%lX\n", dwState); + trace(" Prot: %ld\n", dwProt); + trace(" ATR (length %ld bytes):", dwAtrLen); + for (i = 0; i < dwAtrLen; i++) + trace(" %02X", pbAtr[i]); + trace("\n"); + + switch (dwActiveProtocol) + { + case SCARD_PROTOCOL_T0: + pioSendPci = SCARD_PCI_T0; + break; + case SCARD_PROTOCOL_T1: + pioSendPci = SCARD_PCI_T1; + break; + default: + skip("Unknown active protocol\n"); + goto end; + } + pioRecvPci.cbPciLength = sizeof(pioRecvPci); + pioRecvPci.dwProtocol = dwActiveProtocol; + + /* exchange APDU */ + dwSendLength = sizeof(pbSendBuffer); + dwRecvLength = sizeof(pbRecvBuffer); + + trace("Sending: "); + for (i = 0; i < dwSendLength; i++) + trace("%02X ", pbSendBuffer[i]); + trace("\n"); + lRet = SCardTransmit(hCard, pioSendPci, pbSendBuffer, dwSendLength, + &pioRecvPci, pbRecvBuffer, &dwRecvLength); + ok(lRet == SCARD_S_SUCCESS, "got %#lx\t%#lx\n", lRet, GetLastError()); + trace("Received: "); + for (i = 0; i < dwRecvLength; i++) + trace("%02X ", pbRecvBuffer[i]); + trace("\n"); + + /* card reconnect */ + lRet = SCardReconnect(hCard, SCARD_SHARE_SHARED, + SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, SCARD_LEAVE_CARD, + &dwActiveProtocol); + ok(lRet == SCARD_S_SUCCESS, "got %#lx\n", lRet); + + /* get card status after reconnect */ + dwAtrLen = sizeof(pbAtr); + dwReaderLen = sizeof(pbReader); + lRet = SCardStatusW(hCard, /*NULL*/ pbReader, &dwReaderLen, &dwState, &dwProt, + pbAtr, &dwAtrLen); + ok(lRet == SCARD_S_SUCCESS, "got %#lx\n", lRet); + + /* begin transaction */ + lRet = SCardBeginTransaction(hCard); + ok(lRet == SCARD_S_SUCCESS, "got %#lx\n", lRet); + + /* exchange APDU */ + dwSendLength = sizeof(pbSendBuffer); + dwRecvLength = sizeof(pbRecvBuffer); + + lRet = SCardTransmit(hCard, pioSendPci, pbSendBuffer, dwSendLength, + &pioRecvPci, pbRecvBuffer, &dwRecvLength); + + ok(lRet == SCARD_S_SUCCESS, "got %#lx\n", lRet); + + /* end transaction */ + lRet = SCardEndTransaction(hCard, SCARD_LEAVE_CARD); + ok(lRet == SCARD_S_SUCCESS, "got %#lx\n", lRet); + + /* card disconnect */ + lRet = SCardDisconnect(hCard, SCARD_UNPOWER_CARD); + ok(lRet == SCARD_S_SUCCESS, "got %#lx\n", lRet); +end: + if (lpState) + free(lpState); + if (readers) + free(readers); + // only do this after being done with the strings, or handle the names another way! + SCardFreeMemory(hContext, szReaders); + } +} + +START_TEST(winscard) +{ + //SCARD_SCOPE_SYSTEM + LONG lRet = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext); + if(lRet == SCARD_E_NO_SERVICE) + { + skip("pcscd daemon not running\n"); + return; + } + ok(lRet == SCARD_S_SUCCESS, "got %#lx\n", lRet); + + test_winscardA(); + test_winscardW(); + + lRet = SCardReleaseContext(hContext); + ok(lRet == SCARD_S_SUCCESS, "got %#lx\n", lRet); +}
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=129801
Your paranoid android.
=== debian11 (32 bit report) ===
winscard: winscard.c:377: Test failed: got 0x80100001 winscard.c:61: Test failed: got 0x80100001 winscard.c:98: Test failed: got 0x80100001 winscard.c:228: Test failed: got 0x80100001 winscard.c:265: Test failed: got 0x80100001 winscard.c:383: Test failed: got 0x80100001
=== debian11 (32 bit ar:MA report) ===
winscard: winscard.c:377: Test failed: got 0x80100001 winscard.c:61: Test failed: got 0x80100001 winscard.c:98: Test failed: got 0x80100001 winscard.c:228: Test failed: got 0x80100001 winscard.c:265: Test failed: got 0x80100001 winscard.c:383: Test failed: got 0x80100001
=== debian11 (32 bit de report) ===
winscard: winscard.c:377: Test failed: got 0x80100001 winscard.c:61: Test failed: got 0x80100001 winscard.c:98: Test failed: got 0x80100001 winscard.c:228: Test failed: got 0x80100001 winscard.c:265: Test failed: got 0x80100001 winscard.c:383: Test failed: got 0x80100001
=== debian11 (32 bit fr report) ===
winscard: winscard.c:377: Test failed: got 0x80100001 winscard.c:61: Test failed: got 0x80100001 winscard.c:98: Test failed: got 0x80100001 winscard.c:228: Test failed: got 0x80100001 winscard.c:265: Test failed: got 0x80100001 winscard.c:383: Test failed: got 0x80100001
=== debian11 (32 bit he:IL report) ===
winscard: winscard.c:377: Test failed: got 0x80100001 winscard.c:61: Test failed: got 0x80100001 winscard.c:98: Test failed: got 0x80100001 winscard.c:228: Test failed: got 0x80100001 winscard.c:265: Test failed: got 0x80100001 winscard.c:383: Test failed: got 0x80100001
=== debian11 (32 bit hi:IN report) ===
winscard: winscard.c:377: Test failed: got 0x80100001 winscard.c:61: Test failed: got 0x80100001 winscard.c:98: Test failed: got 0x80100001 winscard.c:228: Test failed: got 0x80100001 winscard.c:265: Test failed: got 0x80100001 winscard.c:383: Test failed: got 0x80100001
=== debian11 (32 bit ja:JP report) ===
winscard: winscard.c:377: Test failed: got 0x80100001 winscard.c:61: Test failed: got 0x80100001 winscard.c:98: Test failed: got 0x80100001 winscard.c:228: Test failed: got 0x80100001 winscard.c:265: Test failed: got 0x80100001 winscard.c:383: Test failed: got 0x80100001
=== debian11 (32 bit zh:CN report) ===
winscard: winscard.c:377: Test failed: got 0x80100001 winscard.c:61: Test failed: got 0x80100001 winscard.c:98: Test failed: got 0x80100001 winscard.c:228: Test failed: got 0x80100001 winscard.c:265: Test failed: got 0x80100001 winscard.c:383: Test failed: got 0x80100001
=== debian11 (build log) ===
Extracting: windows.gaming.ui.gamebar01e0:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: cannot open shared object file: No such file or directory" 0ed4:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: cannot open shared object file: No such file or directory" 0100:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: cannot open shared object file: No such file or directory" 0108:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: cannot open shared object file: No such file or directory" 0100:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: Kann die Shared-Object-Datei nicht \xc3\xb6ffnen: Datei oder Verzeichnis nicht gefunden" 0108:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: Kann die Shared-Object-Datei nicht \xc3\xb6ffnen: Datei oder Verzeichnis nicht gefunden" 0100:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: Ne peut ouvrir le fichier d'objet partag\xc3\xa9: Aucun fichier ou dossier de ce type" 0108:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: Ne peut ouvrir le fichier d'objet partag\xc3\xa9: Aucun fichier ou dossier de ce type" 0104:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: cannot open shared object file: No such file or directory" 010c:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: cannot open shared object file: No such file or directory" 0100:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: cannot open shared object file: No such file or directory" 0108:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: cannot open shared object file: No such file or directory" 0108:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: \xe5\x85\xb1\xe6\x9c\x89\xe3\x82\xaa\xe3\x83\x96\xe3\x82\xb8\xe3\x82\xa7\xe3\x82\xaf\xe3\x83\x88\xe3\x83\x95\xe3\x82\xa1\xe3\x82\xa4\xe3\x83\xab\xe3\x82\x92\xe9\x96\x8b\xe3\x81\x91\xe3\x81\xbe\xe3\x81\x9b\xe3\x82\x93: \xe3\x81\x9d\xe3\x81\xae\xe3\x82\x88\xe3\x81\x86\xe3\x81"... 0110:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: \xe5\x85\xb1\xe6\x9c\x89\xe3\x82\xaa\xe3\x83\x96\xe3\x82\xb8\xe3\x82\xa7\xe3\x82\xaf\xe3\x83\x88\xe3\x83\x95\xe3\x82\xa1\xe3\x82\xa4\xe3\x83\xab\xe3\x82\x92\xe9\x96\x8b\xe3\x81\x91\xe3\x81\xbe\xe3\x81\x9b\xe3\x82\x93: \xe3\x81\x9d\xe3\x81\xae\xe3\x82\x88\xe3\x81\x86\xe3\x81"... 0100:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: \xe6\x97\xa0\xe6\xb3\x95\xe6\x89\x93\xe5\xbc\x80\xe5\x85\xb1\xe4\xba\xab\xe5\xaf\xb9\xe8\xb1\xa1\xe6\x96\x87\xe4\xbb\xb6: \xe6\xb2\xa1\xe6\x9c\x89\xe9\x82\xa3\xe4\xb8\xaa\xe6\x96\x87\xe4\xbb\xb6\xe6\x88\x96\xe7\x9b\xae\xe5\xbd\x95" 0108:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: \xe6\x97\xa0\xe6\xb3\x95\xe6\x89\x93\xe5\xbc\x80\xe5\x85\xb1\xe4\xba\xab\xe5\xaf\xb9\xe8\xb1\xa1\xe6\x96\x87\xe4\xbb\xb6: \xe6\xb2\xa1\xe6\x9c\x89\xe9\x82\xa3\xe4\xb8\xaa\xe6\x96\x87\xe4\xbb\xb6\xe6\x88\x96\xe7\x9b\xae\xe5\xbd\x95"
=== debian11b (32 bit WoW report) ===
winscard: winscard.c:377: Test failed: got 0x80100001 winscard.c:61: Test failed: got 0x80100001 winscard.c:98: Test failed: got 0x80100001 winscard.c:228: Test failed: got 0x80100001 winscard.c:265: Test failed: got 0x80100001 winscard.c:383: Test failed: got 0x80100001
=== debian11b (64 bit WoW report) ===
winscard: winscard.c:377: Test failed: got 0x80100001 winscard.c:61: Test failed: got 0x80100001 winscard.c:98: Test failed: got 0x80100001 winscard.c:228: Test failed: got 0x80100001 winscard.c:265: Test failed: got 0x80100001 winscard.c:383: Test failed: got 0x80100001
=== debian11b (build log) ===
0100:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: cannot open shared object file: No such file or directory" 0108:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: cannot open shared object file: No such file or directory" 0108:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: cannot open shared object file: No such file or directory" 0110:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: cannot open shared object file: No such file or directory"
Hi Konstantin,
I have also been working on a winscard implementation on top of libpcsclite. I was actually about to submit it when I saw this MR :) I'll do that now so we can compare and try to find a way forward.
On Tue Feb 21 13:57:02 2023 +0000, Hans Leidekker wrote:
Hi Konstantin, I have also been working on a winscard implementation on top of libpcsclite. I was actually about to submit it when I saw this MR :) I'll do that now so we can compare and try to find a way forward.
Hi Hans, interesting coincidence. A substantial part of the code in my RP is written by Mounir IDRASSI. As it works in a production environment, so I decided to share it with the community. Probably together we can finally get the winscard implementation into the repository.
On Tue Feb 21 13:49:58 2023 +0000, **** wrote:
Marvin replied on the mailing list:
Hi, It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated. The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details: The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=129801 Your paranoid android. === debian11 (32 bit report) === winscard: winscard.c:377: Test failed: got 0x80100001 winscard.c:61: Test failed: got 0x80100001 winscard.c:98: Test failed: got 0x80100001 winscard.c:228: Test failed: got 0x80100001 winscard.c:265: Test failed: got 0x80100001 winscard.c:383: Test failed: got 0x80100001 === debian11 (32 bit ar:MA report) === winscard: winscard.c:377: Test failed: got 0x80100001 winscard.c:61: Test failed: got 0x80100001 winscard.c:98: Test failed: got 0x80100001 winscard.c:228: Test failed: got 0x80100001 winscard.c:265: Test failed: got 0x80100001 winscard.c:383: Test failed: got 0x80100001 === debian11 (32 bit de report) === winscard: winscard.c:377: Test failed: got 0x80100001 winscard.c:61: Test failed: got 0x80100001 winscard.c:98: Test failed: got 0x80100001 winscard.c:228: Test failed: got 0x80100001 winscard.c:265: Test failed: got 0x80100001 winscard.c:383: Test failed: got 0x80100001 === debian11 (32 bit fr report) === winscard: winscard.c:377: Test failed: got 0x80100001 winscard.c:61: Test failed: got 0x80100001 winscard.c:98: Test failed: got 0x80100001 winscard.c:228: Test failed: got 0x80100001 winscard.c:265: Test failed: got 0x80100001 winscard.c:383: Test failed: got 0x80100001 === debian11 (32 bit he:IL report) === winscard: winscard.c:377: Test failed: got 0x80100001 winscard.c:61: Test failed: got 0x80100001 winscard.c:98: Test failed: got 0x80100001 winscard.c:228: Test failed: got 0x80100001 winscard.c:265: Test failed: got 0x80100001 winscard.c:383: Test failed: got 0x80100001 === debian11 (32 bit hi:IN report) === winscard: winscard.c:377: Test failed: got 0x80100001 winscard.c:61: Test failed: got 0x80100001 winscard.c:98: Test failed: got 0x80100001 winscard.c:228: Test failed: got 0x80100001 winscard.c:265: Test failed: got 0x80100001 winscard.c:383: Test failed: got 0x80100001 === debian11 (32 bit ja:JP report) === winscard: winscard.c:377: Test failed: got 0x80100001 winscard.c:61: Test failed: got 0x80100001 winscard.c:98: Test failed: got 0x80100001 winscard.c:228: Test failed: got 0x80100001 winscard.c:265: Test failed: got 0x80100001 winscard.c:383: Test failed: got 0x80100001 === debian11 (32 bit zh:CN report) === winscard: winscard.c:377: Test failed: got 0x80100001 winscard.c:61: Test failed: got 0x80100001 winscard.c:98: Test failed: got 0x80100001 winscard.c:228: Test failed: got 0x80100001 winscard.c:265: Test failed: got 0x80100001 winscard.c:383: Test failed: got 0x80100001 === debian11 (build log) === Extracting: windows.gaming.ui.gamebar01e0:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: cannot open shared object file: No such file or directory" 0ed4:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: cannot open shared object file: No such file or directory" 0100:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: cannot open shared object file: No such file or directory" 0108:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: cannot open shared object file: No such file or directory" 0100:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: Kann die Shared-Object-Datei nicht \xc3\xb6ffnen: Datei oder Verzeichnis nicht gefunden" 0108:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: Kann die Shared-Object-Datei nicht \xc3\xb6ffnen: Datei oder Verzeichnis nicht gefunden" 0100:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: Ne peut ouvrir le fichier d'objet partag\xc3\xa9: Aucun fichier ou dossier de ce type" 0108:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: Ne peut ouvrir le fichier d'objet partag\xc3\xa9: Aucun fichier ou dossier de ce type" 0104:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: cannot open shared object file: No such file or directory" 010c:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: cannot open shared object file: No such file or directory" 0100:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: cannot open shared object file: No such file or directory" 0108:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: cannot open shared object file: No such file or directory" 0108:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: \xe5\x85\xb1\xe6\x9c\x89\xe3\x82\xaa\xe3\x83\x96\xe3\x82\xb8\xe3\x82\xa7\xe3\x82\xaf\xe3\x83\x88\xe3\x83\x95\xe3\x82\xa1\xe3\x82\xa4\xe3\x83\xab\xe3\x82\x92\xe9\x96\x8b\xe3\x81\x91\xe3\x81\xbe\xe3\x81\x9b\xe3\x82\x93: \xe3\x81\x9d\xe3\x81\xae\xe3\x82\x88\xe3\x81\x86\xe3\x81"... 0110:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: \xe5\x85\xb1\xe6\x9c\x89\xe3\x82\xaa\xe3\x83\x96\xe3\x82\xb8\xe3\x82\xa7\xe3\x82\xaf\xe3\x83\x88\xe3\x83\x95\xe3\x82\xa1\xe3\x82\xa4\xe3\x83\xab\xe3\x82\x92\xe9\x96\x8b\xe3\x81\x91\xe3\x81\xbe\xe3\x81\x9b\xe3\x82\x93: \xe3\x81\x9d\xe3\x81\xae\xe3\x82\x88\xe3\x81\x86\xe3\x81"... 0100:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: \xe6\x97\xa0\xe6\xb3\x95\xe6\x89\x93\xe5\xbc\x80\xe5\x85\xb1\xe4\xba\xab\xe5\xaf\xb9\xe8\xb1\xa1\xe6\x96\x87\xe4\xbb\xb6: \xe6\xb2\xa1\xe6\x9c\x89\xe9\x82\xa3\xe4\xb8\xaa\xe6\x96\x87\xe4\xbb\xb6\xe6\x88\x96\xe7\x9b\xae\xe5\xbd\x95" 0108:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: \xe6\x97\xa0\xe6\xb3\x95\xe6\x89\x93\xe5\xbc\x80\xe5\x85\xb1\xe4\xba\xab\xe5\xaf\xb9\xe8\xb1\xa1\xe6\x96\x87\xe4\xbb\xb6: \xe6\xb2\xa1\xe6\x9c\x89\xe9\x82\xa3\xe4\xb8\xaa\xe6\x96\x87\xe4\xbb\xb6\xe6\x88\x96\xe7\x9b\xae\xe5\xbd\x95" === debian11b (32 bit WoW report) === winscard: winscard.c:377: Test failed: got 0x80100001 winscard.c:61: Test failed: got 0x80100001 winscard.c:98: Test failed: got 0x80100001 winscard.c:228: Test failed: got 0x80100001 winscard.c:265: Test failed: got 0x80100001 winscard.c:383: Test failed: got 0x80100001 === debian11b (64 bit WoW report) === winscard: winscard.c:377: Test failed: got 0x80100001 winscard.c:61: Test failed: got 0x80100001 winscard.c:98: Test failed: got 0x80100001 winscard.c:228: Test failed: got 0x80100001 winscard.c:265: Test failed: got 0x80100001 winscard.c:383: Test failed: got 0x80100001 === debian11b (build log) === 0100:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: cannot open shared object file: No such file or directory" 0108:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: cannot open shared object file: No such file or directory" 0108:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: cannot open shared object file: No such file or directory" 0110:err:winediag:load_pcsclite failed to load libpcsclite.so, scard support will be disabled. Error: "libpcsclite.so.1: cannot open shared object file: No such file or directory"
Is it possible to install libpcsclite1 on the test servers? Or is it necessary to skip the test on the initialization error?