winscard: Implement SCardGetStatusChangeA/W().

This commit is contained in:
Hans Leidekker 2023-02-16 10:50:32 +01:00 committed by Alexandre Julliard
parent 9d40ac4635
commit 3f325721c3
4 changed files with 177 additions and 2 deletions

View file

@ -34,6 +34,7 @@
LONG SCardEstablishContext( UINT64, const void *, const void *, UINT64 * );
LONG SCardReleaseContext( UINT64 );
LONG SCardIsValidContext( UINT64 );
LONG SCardGetStatusChange( UINT64, UINT64, struct reader_state *, UINT64 );
static NTSTATUS scard_establish_context( void *args )
{
@ -53,9 +54,16 @@ static NTSTATUS scard_is_valid_context( void *args )
return SCardIsValidContext( params->handle );
}
static NTSTATUS scard_get_status_change( void *args )
{
struct scard_get_status_change_params *params = args;
return SCardGetStatusChange( params->handle, params->timeout, params->states, params->count );
}
const unixlib_entry_t __wine_unix_call_funcs[] =
{
scard_establish_context,
scard_release_context,
scard_is_valid_context,
scard_get_status_change,
};

View file

@ -35,9 +35,29 @@ struct scard_is_valid_context_params
UINT64 handle;
};
#define MAX_ATR_SIZE 33
struct reader_state
{
UINT64 reader;
UINT64 userdata;
UINT64 current_state;
UINT64 event_state;
UINT64 atr_size;
unsigned char atr[MAX_ATR_SIZE];
};
struct scard_get_status_change_params
{
UINT64 handle;
UINT64 timeout;
struct reader_state *states;
UINT64 count;
};
enum winscard_funcs
{
unix_scard_establish_context,
unix_scard_release_context,
unix_scard_is_valid_context,
unix_scard_get_status_change,
};

View file

@ -37,6 +37,40 @@ 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 };
static inline char *utf16_to_utf8( const WCHAR *src )
{
char *dst = NULL;
if (src)
{
int len = WideCharToMultiByte( CP_UTF8, 0, src, -1, NULL, 0, NULL, NULL );
if ((dst = malloc( len ))) WideCharToMultiByte( CP_UTF8, 0, src, -1, dst, len, NULL, NULL );
}
return dst;
}
static inline WCHAR *ansi_to_utf16( const char *src )
{
WCHAR *dst = NULL;
if (src)
{
int len = MultiByteToWideChar( CP_ACP, 0, src, -1, NULL, 0 );
if ((dst = malloc( len * sizeof(WCHAR) ))) MultiByteToWideChar( CP_ACP, 0, src, -1, dst, len );
}
return dst;
}
static inline char *ansi_to_utf8( const char *src )
{
char *dst = NULL;
if (src)
{
WCHAR *tmp;
if ((tmp = ansi_to_utf16( src ))) dst = utf16_to_utf8( tmp );
free( tmp );
}
return dst;
}
HANDLE WINAPI SCardAccessStartedEvent(void)
{
return g_startedEvent;
@ -174,6 +208,119 @@ LONG WINAPI SCardCancel(SCARDCONTEXT context)
return SCARD_F_INTERNAL_ERROR;
}
static LONG map_states_inA( const SCARD_READERSTATEA *src, struct reader_state *dst, DWORD count )
{
DWORD i;
for (i = 0; i < count; i++)
{
if (src[i].szReader && !(dst[i].reader = (UINT64)(ULONG_PTR)ansi_to_utf8( src[i].szReader )))
return SCARD_E_NO_MEMORY;
dst[i].current_state = src[i].dwCurrentState;
dst[i].event_state = src[i].dwEventState;
dst[i].atr_size = src[i].cbAtr;
memcpy( dst[i].atr, src[i].rgbAtr, src[i].cbAtr );
}
return SCARD_S_SUCCESS;
}
static void map_states_out( const struct reader_state *src, SCARD_READERSTATEA *dst, DWORD count )
{
DWORD i;
for (i = 0; i < count; i++)
{
dst[i].dwCurrentState = src[i].current_state;
dst[i].dwEventState = src[i].event_state;
dst[i].cbAtr = src[i].atr_size;
memcpy( dst[i].rgbAtr, src[i].atr, src[i].atr_size );
}
}
static void free_states( struct reader_state *states, DWORD count )
{
DWORD i;
for (i = 0; i < count; i++) free( (void *)(ULONG_PTR)states[i].reader );
free( states );
}
LONG WINAPI SCardGetStatusChangeA( SCARDCONTEXT context, DWORD timeout, SCARD_READERSTATEA *states, DWORD count )
{
struct handle *handle = (struct handle *)context;
struct scard_get_status_change_params params;
struct reader_state *states_utf8 = NULL;
LONG ret;
TRACE( "%Ix, %lu, %p, %lu\n", context, timeout, states, count );
if (!handle || handle->magic != CONTEXT_MAGIC) return ERROR_INVALID_HANDLE;
if (!(states_utf8 = calloc( count, sizeof(*states_utf8) ))) return SCARD_E_NO_MEMORY;
if ((ret = map_states_inA( states, states_utf8, count )))
{
free_states( states_utf8, count );
return ret;
}
params.handle = handle->unix_handle;
params.timeout = timeout;
params.states = states_utf8;
params.count = count;
if (!(ret = UNIX_CALL( scard_get_status_change, &params )) && states)
{
map_states_out( states_utf8, states, count );
}
free_states( states_utf8, count );
TRACE( "returning %#lx\n", ret );
return ret;
}
static LONG map_states_inW( SCARD_READERSTATEW *src, struct reader_state *dst, DWORD count )
{
DWORD i;
for (i = 0; i < count; i++)
{
if (src[i].szReader && !(dst[i].reader = (UINT64)(ULONG_PTR)utf16_to_utf8( src[i].szReader )))
return SCARD_E_NO_MEMORY;
dst[i].current_state = src[i].dwCurrentState;
dst[i].event_state = src[i].dwEventState;
dst[i].atr_size = src[i].cbAtr;
memcpy( dst[i].atr, src[i].rgbAtr, src[i].cbAtr );
}
return SCARD_S_SUCCESS;
}
LONG WINAPI SCardGetStatusChangeW( SCARDCONTEXT context, DWORD timeout, SCARD_READERSTATEW *states, DWORD count )
{
struct handle *handle = (struct handle *)context;
struct scard_get_status_change_params params;
struct reader_state *states_utf8;
LONG ret;
TRACE( "%Ix, %lu, %p, %lu\n", context, timeout, states, count );
if (!handle || handle->magic != CONTEXT_MAGIC) return ERROR_INVALID_HANDLE;
if (!(states_utf8 = calloc( count, sizeof(*states_utf8) ))) return SCARD_E_NO_MEMORY;
if ((ret = map_states_inW( states, states_utf8, count )))
{
free_states( states_utf8, count );
return ret;
}
params.handle = handle->unix_handle;
params.timeout = timeout;
params.states = states_utf8;
params.count = count;
if (!(ret = UNIX_CALL( scard_get_status_change, &params )))
{
map_states_out( states_utf8, (SCARD_READERSTATEA *)states, count );
}
free_states( states_utf8, count );
TRACE( "returning %#lx\n", ret );
return ret;
}
BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, void *reserved )
{
switch (reason)

View file

@ -25,8 +25,8 @@
@ stub SCardGetCardTypeProviderNameW
@ stub SCardGetProviderIdA
@ stub SCardGetProviderIdW
@ stub SCardGetStatusChangeA
@ stub SCardGetStatusChangeW
@ stdcall SCardGetStatusChangeA(long long ptr long)
@ stdcall SCardGetStatusChangeW(long long ptr long)
@ stub SCardIntroduceCardTypeA
@ stub SCardIntroduceCardTypeW
@ stub SCardIntroduceReaderA