Module: wine Branch: master Commit: f7c66e642ea83d40fb6306e010ba57257b8d344c URL: https://gitlab.winehq.org/wine/wine/-/commit/f7c66e642ea83d40fb6306e010ba572...
Author: Hans Leidekker hans@codeweavers.com Date: Thu Feb 16 12:01:43 2023 +0100
winscard: Implement SCardListReadersA/W().
---
dlls/winscard/unixlib.c | 8 +++ dlls/winscard/unixlib.h | 9 +++ dlls/winscard/winscard.c | 164 +++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 175 insertions(+), 6 deletions(-)
diff --git a/dlls/winscard/unixlib.c b/dlls/winscard/unixlib.c index 6aca020cd4e..61f179b2eb9 100644 --- a/dlls/winscard/unixlib.c +++ b/dlls/winscard/unixlib.c @@ -36,6 +36,7 @@ LONG SCardReleaseContext( UINT64 ); LONG SCardIsValidContext( UINT64 ); LONG SCardGetStatusChange( UINT64, UINT64, struct reader_state *, UINT64 ); LONG SCardCancel( UINT64 ); +LONG SCardListReaders( UINT64, const char *, char *, UINT64 * );
static NTSTATUS scard_establish_context( void *args ) { @@ -67,6 +68,12 @@ static NTSTATUS scard_cancel( void *args ) return SCardCancel( params->handle ); }
+static NTSTATUS scard_list_readers( void *args ) +{ + struct scard_list_readers_params *params = args; + return SCardListReaders( params->handle, params->groups, params->readers, params->readers_len ); +} + const unixlib_entry_t __wine_unix_call_funcs[] = { scard_establish_context, @@ -74,4 +81,5 @@ const unixlib_entry_t __wine_unix_call_funcs[] = scard_is_valid_context, scard_get_status_change, scard_cancel, + scard_list_readers, }; diff --git a/dlls/winscard/unixlib.h b/dlls/winscard/unixlib.h index c2151a7573e..1be9fe7cf77 100644 --- a/dlls/winscard/unixlib.h +++ b/dlls/winscard/unixlib.h @@ -59,6 +59,14 @@ struct scard_cancel_params UINT64 handle; };
+struct scard_list_readers_params +{ + UINT64 handle; + const char *groups; + char *readers; + UINT64 *readers_len; +}; + enum winscard_funcs { unix_scard_establish_context, @@ -66,4 +74,5 @@ enum winscard_funcs unix_scard_is_valid_context, unix_scard_get_status_change, unix_scard_cancel, + unix_scard_list_readers, }; diff --git a/dlls/winscard/winscard.c b/dlls/winscard/winscard.c index af822b8aef2..a242de9ccce 100644 --- a/dlls/winscard/winscard.c +++ b/dlls/winscard/winscard.c @@ -71,6 +71,45 @@ static inline char *ansi_to_utf8( const char *src ) return dst; }
+static inline WCHAR *utf8_to_utf16( const char *src ) +{ + WCHAR *dst = NULL; + if (src) + { + int len = MultiByteToWideChar( CP_UTF8, 0, src, -1, NULL, 0 ); + if ((dst = malloc( len * sizeof(WCHAR) ))) MultiByteToWideChar( CP_UTF8, 0, src, -1, dst, len ); + } + return dst; +} + +static inline char *utf16_to_ansi( const WCHAR *src ) +{ + char *dst = NULL; + if (src) + { + int len = WideCharToMultiByte( CP_ACP, WC_NO_BEST_FIT_CHARS, src, -1, NULL, 0, NULL, NULL ); + if (*src && !len) + { + FIXME( "can't convert %s to ANSI codepage\n", debugstr_w(src) ); + return NULL; + } + if ((dst = malloc( len ))) WideCharToMultiByte( CP_ACP, WC_NO_BEST_FIT_CHARS, src, -1, dst, len, NULL, NULL ); + } + return dst; +} + +static inline char *utf8_to_ansi( const char *src ) +{ + char *dst = NULL; + if (src) + { + WCHAR *tmp; + if ((tmp = utf8_to_utf16( src ))) dst = utf16_to_ansi( tmp ); + free( tmp ); + } + return dst; +} + HANDLE WINAPI SCardAccessStartedEvent(void) { return g_startedEvent; @@ -170,6 +209,27 @@ LONG WINAPI SCardReleaseContext( SCARDCONTEXT context ) return ret; }
+static LONG copy_multiszA( const char *src, char *dst, DWORD *dst_len ) +{ + DWORD len, total_len = 0; + const char *ptr = src; + + while (*ptr) + { + char *str; + if (!(str = utf8_to_ansi( ptr ))) return SCARD_E_NO_MEMORY; + len = strlen( str ) + 1; + if (dst && dst_len && *dst_len > total_len + len) strcpy( dst + total_len, str ); + total_len += len; + ptr += strlen( ptr ) + 1; + free( str ); + } + + if (dst && dst_len && *dst_len > total_len + 1) dst[total_len] = 0; + if (dst_len) *dst_len = total_len + 1; + return SCARD_S_SUCCESS; +} + LONG WINAPI SCardStatusA(SCARDHANDLE context, LPSTR szReaderName, LPDWORD pcchReaderLen, LPDWORD pdwState, LPDWORD pdwProtocol, LPBYTE pbAtr, LPDWORD pcbAtrLen) { FIXME("(%Ix) stub\n", context); @@ -177,6 +237,27 @@ LONG WINAPI SCardStatusA(SCARDHANDLE context, LPSTR szReaderName, LPDWORD pcchRe return SCARD_F_INTERNAL_ERROR; }
+static LONG copy_multiszW( const char *src, WCHAR *dst, DWORD *dst_len ) +{ + DWORD len, total_len = 0; + const char *ptr = src; + + while (*ptr) + { + WCHAR *str; + if (!(str = utf8_to_utf16( ptr ))) return SCARD_E_NO_MEMORY; + len = wcslen( str ) + 1; + if (dst && dst_len && *dst_len > total_len + len) wcscpy( dst + total_len, str ); + total_len += len; + ptr += strlen( ptr ) + 1; + free( str ); + } + + if (dst && dst_len && *dst_len > total_len + 1) dst[total_len] = 0; + if (dst_len) *dst_len = total_len + 1; + return SCARD_S_SUCCESS; +} + LONG WINAPI SCardStatusW(SCARDHANDLE context, LPWSTR szReaderName, LPDWORD pcchReaderLen, LPDWORD pdwState,LPDWORD pdwProtocol,LPBYTE pbAtr,LPDWORD pcbArtLen) { FIXME("(%Ix) stub\n", context); @@ -189,16 +270,87 @@ void WINAPI SCardReleaseStartedEvent(void) FIXME("stub\n"); }
-LONG WINAPI SCardListReadersA(SCARDCONTEXT context, const CHAR *groups, CHAR *readers, DWORD *buflen) +LONG WINAPI SCardListReadersA( SCARDCONTEXT context, const char *groups, char *readers, DWORD *readers_len ) { - FIXME("(%Ix, %s, %p, %p) stub\n", context, debugstr_a(groups), readers, buflen); - return SCARD_E_NO_READERS_AVAILABLE; + struct handle *handle = (struct handle *)context; + struct scard_list_readers_params params; + UINT64 readers_len_utf8; + LONG ret; + + TRACE( "%Ix, %s, %p, %p\n", context, debugstr_a(groups), readers, readers_len ); + + if (!handle || handle->magic != CONTEXT_MAGIC) return ERROR_INVALID_HANDLE; + if (!readers_len) return SCARD_E_INVALID_PARAMETER; + if (*readers_len == SCARD_AUTOALLOCATE) + { + FIXME( "SCARD_AUTOALLOCATE not supported\n" ); + return SCARD_F_INTERNAL_ERROR; + } + + params.handle = handle->unix_handle; + if (!groups) params.groups = NULL; + else if (!(params.groups = ansi_to_utf8( groups ))) return SCARD_E_NO_MEMORY; + params.readers = NULL; + params.readers_len = &readers_len_utf8; + if ((ret = UNIX_CALL( scard_list_readers, ¶ms ))) goto done; + + if (!(params.readers = malloc( readers_len_utf8 ))) + { + free( (void *)params.groups ); + return SCARD_E_NO_MEMORY; + } + if (!(ret = UNIX_CALL( scard_list_readers, ¶ms ))) + { + ret = copy_multiszA( params.readers, readers, readers_len ); + } + +done: + free( (void *)params.groups ); + free( params.readers ); + TRACE( "returning %#lx\n", ret ); + return ret; }
-LONG WINAPI SCardListReadersW(SCARDCONTEXT context, const WCHAR *groups, WCHAR *readers, DWORD *buflen) +LONG WINAPI SCardListReadersW( SCARDCONTEXT context, const WCHAR *groups, WCHAR *readers, DWORD *readers_len ) { - FIXME("(%Ix, %s, %p, %p) stub\n", context, debugstr_w(groups), readers, buflen); - return SCARD_E_NO_READERS_AVAILABLE; + struct handle *handle = (struct handle *)context; + struct scard_list_readers_params params; + UINT64 readers_len_utf8; + LONG ret; + + TRACE( "%Ix, %s, %p, %p\n", context, debugstr_w(groups), readers, readers_len ); + + if (!handle || handle->magic != CONTEXT_MAGIC) return ERROR_INVALID_HANDLE; + if (!readers_len) return SCARD_E_INVALID_PARAMETER; + if (*readers_len == SCARD_AUTOALLOCATE) + { + FIXME( "SCARD_AUTOALLOCATE not supported\n" ); + return SCARD_F_INTERNAL_ERROR; + } + + params.handle = handle->unix_handle; + if (!groups) params.groups = NULL; + else if (!(params.groups = utf16_to_utf8( groups ))) return SCARD_E_NO_MEMORY; + params.readers = NULL; + params.readers_len = &readers_len_utf8; + if ((ret = UNIX_CALL( scard_list_readers, ¶ms ))) goto done; + + params.handle = handle->unix_handle; + if (!(params.readers = malloc( readers_len_utf8 ))) + { + free( (void *)params.groups ); + return SCARD_E_NO_MEMORY; + } + if (!(ret = UNIX_CALL( scard_list_readers, ¶ms ))) + { + ret = copy_multiszW( params.readers, readers, readers_len ); + } + +done: + free( (void *)params.groups ); + free( params.readers ); + TRACE( "returning %#lx\n", ret ); + return ret; }
LONG WINAPI SCardCancel( SCARDCONTEXT context )