mlang: Fix GetStrCodePages for characters with different codepages.
[wine.git] / dlls / winscard / winscard.c
blob7e53fba45f62e0e10ed7e74ad97ff285d7b7d70c
1 /*
2 * Copyright 2007 Mounir IDRASSI (mounir.idrassi@idrix.fr, for IDRIX)
3 * Copyright 2022 Hans Leidekker for CodeWeavers
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include <stdarg.h>
21 #define WINSCARDAPI
22 #include "windef.h"
23 #include "winbase.h"
24 #include "winscard.h"
25 #include "winternl.h"
27 #include "wine/debug.h"
28 #include "wine/unixlib.h"
29 #include "unixlib.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(winscard);
33 #define UNIX_CALL( func, params ) WINE_UNIX_CALL( unix_ ## func, params )
35 static HANDLE g_startedEvent;
37 const SCARD_IO_REQUEST g_rgSCardT0Pci = { SCARD_PROTOCOL_T0, 8 };
38 const SCARD_IO_REQUEST g_rgSCardT1Pci = { SCARD_PROTOCOL_T1, 8 };
39 const SCARD_IO_REQUEST g_rgSCardRawPci = { SCARD_PROTOCOL_RAW, 8 };
41 static inline int utf16_to_utf8( const WCHAR *src, char **dst )
43 int len = WideCharToMultiByte( CP_UTF8, 0, src, -1, NULL, 0, NULL, NULL );
44 if (dst)
46 if (!(*dst = malloc( len ))) return -1;
47 WideCharToMultiByte( CP_UTF8, 0, src, -1, *dst, len, NULL, NULL );
49 return len;
52 static inline int ansi_to_utf16( const char *src, WCHAR **dst )
54 int len = MultiByteToWideChar( CP_ACP, 0, src, -1, NULL, 0 );
55 if (dst)
57 if (!(*dst = malloc( len * sizeof(WCHAR) ))) return -1;
58 MultiByteToWideChar( CP_ACP, 0, src, -1, *dst, len );
60 return len;
63 static inline int ansi_to_utf8( const char *src, char **dst )
65 WCHAR *tmp;
66 int len;
68 if (ansi_to_utf16( src, &tmp ) < 0) return -1;
69 len = utf16_to_utf8( tmp, dst );
70 free( tmp );
71 return len;
74 static inline int utf8_to_utf16( const char *src, WCHAR **dst )
76 int len = MultiByteToWideChar( CP_UTF8, 0, src, -1, NULL, 0 );
77 if (dst)
79 if (!(*dst = malloc( len * sizeof(WCHAR) ))) return -1;
80 MultiByteToWideChar( CP_UTF8, 0, src, -1, *dst, len );
82 return len;
85 static inline int utf16_to_ansi( const WCHAR *src, char **dst )
87 int len = WideCharToMultiByte( CP_ACP, WC_NO_BEST_FIT_CHARS, src, -1, NULL, 0, NULL, NULL );
88 if (*src && !len)
90 FIXME( "can't convert %s to ANSI codepage\n", debugstr_w(src) );
91 return -1;
93 if (dst)
95 if (!(*dst = malloc( len ))) return -1;
96 WideCharToMultiByte( CP_ACP, WC_NO_BEST_FIT_CHARS, src, -1, *dst, len, NULL, NULL );
98 return len;
101 static inline int utf8_to_ansi( const char *src, char **dst )
103 WCHAR *tmp;
104 int len;
106 if (utf8_to_utf16( src, &tmp ) < 0) return -1;
107 len = utf16_to_ansi( tmp, dst );
108 free( tmp );
109 return len;
112 HANDLE WINAPI SCardAccessStartedEvent(void)
114 FIXME( "stub\n" );
115 return g_startedEvent;
118 LONG WINAPI SCardAddReaderToGroupA( SCARDCONTEXT context, const char *reader, const char *group )
120 WCHAR *readerW = NULL, *groupW = NULL;
121 LONG ret;
123 TRACE( "%Ix, %s, %s\n", context, debugstr_a(reader), debugstr_a(group) );
125 if (reader && ansi_to_utf16( reader, &readerW ) < 0) return SCARD_E_NO_MEMORY;
126 if (group && ansi_to_utf16( group, &groupW ) < 0)
128 free( readerW );
129 return SCARD_E_NO_MEMORY;
131 ret = SCardAddReaderToGroupW( context, readerW, groupW );
132 free( readerW );
133 free( groupW );
134 return ret;
137 LONG WINAPI SCardAddReaderToGroupW( SCARDCONTEXT context, const WCHAR *reader, const WCHAR *group )
139 FIXME( "%Ix, %s, %s\n", context, debugstr_w(reader), debugstr_w(group) );
140 return SCARD_S_SUCCESS;
143 #define CONTEXT_MAGIC (('C' << 24) | ('T' << 16) | ('X' << 8) | '0')
144 #define CONNECT_MAGIC (('C' << 24) | ('O' << 16) | ('N' << 8) | '0')
145 struct handle
147 DWORD magic;
148 UINT64 unix_handle;
151 LONG WINAPI SCardEstablishContext( DWORD scope, const void *reserved1, const void *reserved2, SCARDCONTEXT *context )
153 struct scard_establish_context_params params;
154 struct handle *handle;
155 LONG ret;
157 TRACE( "%#lx, %p, %p, %p\n", scope, reserved1, reserved2, context );
159 if (!context) return SCARD_E_INVALID_PARAMETER;
160 if (!(handle = malloc( sizeof(*handle) ))) return SCARD_E_NO_MEMORY;
161 handle->magic = CONTEXT_MAGIC;
163 params.scope = scope;
164 params.handle = &handle->unix_handle;
165 if (!(ret = UNIX_CALL( scard_establish_context, &params ))) *context = (SCARDCONTEXT)handle;
166 else free( handle );
168 TRACE( "returning %#lx\n", ret );
169 return ret;
172 LONG WINAPI SCardIsValidContext( SCARDCONTEXT context )
174 struct handle *handle = (struct handle *)context;
175 struct scard_is_valid_context_params params;
176 LONG ret;
178 TRACE( "%Ix\n", context );
180 if (!handle || handle->magic != CONTEXT_MAGIC) return ERROR_INVALID_HANDLE;
182 params.handle = handle->unix_handle;
183 ret = UNIX_CALL( scard_is_valid_context, &params );
184 TRACE( "returning %#lx\n", ret );
185 return ret;
188 LONG WINAPI SCardListCardsA( SCARDCONTEXT context, const BYTE *atr, const GUID *interfaces, DWORD interface_count,
189 char *cards, DWORD *cards_len )
191 FIXME( "%Ix, %p, %p, %lu, %p, %p stub\n", context, atr, interfaces, interface_count, cards, cards_len );
192 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
193 return SCARD_F_INTERNAL_ERROR;
196 LONG WINAPI SCardReleaseContext( SCARDCONTEXT context )
198 struct handle *handle = (struct handle *)context;
199 struct scard_release_context_params params;
200 LONG ret;
202 TRACE( "%Ix\n", context );
204 if (!handle || handle->magic != CONTEXT_MAGIC) return ERROR_INVALID_HANDLE;
206 params.handle = handle->unix_handle;
207 ret = UNIX_CALL( scard_release_context, &params );
208 /* Ensure compiler doesn't optimize out the assignment with 0. */
209 SecureZeroMemory( &handle->magic, sizeof(handle->magic) );
210 free( handle );
212 TRACE( "returning %#lx\n", ret );
213 return ret;
216 static LONG copy_multiszA( const char *src, char *dst, DWORD *dst_len )
218 int len, total_len = 0;
219 const char *src_ptr = src;
220 char *dst_ptr;
222 if (!dst && !dst_len) return SCARD_S_SUCCESS;
224 while (*src_ptr)
226 if ((len = utf8_to_ansi( src_ptr, NULL )) < 0) return SCARD_E_INVALID_PARAMETER;
227 total_len += len;
228 src_ptr += len;
230 total_len++; /* double null */
232 if (*dst_len == SCARD_AUTOALLOCATE)
234 if (!(dst_ptr = malloc( total_len ))) return SCARD_E_NO_MEMORY;
236 else
238 if (dst && *dst_len < total_len)
240 *dst_len = total_len;
241 return SCARD_E_INSUFFICIENT_BUFFER;
243 if (!dst)
245 *dst_len = total_len;
246 return SCARD_S_SUCCESS;
248 dst_ptr = dst;
251 src_ptr = src;
252 total_len = 0;
253 while (*src_ptr)
255 char *str;
256 if ((len = utf8_to_ansi( src_ptr, &str )) < 0)
258 if (dst_ptr != dst) free( dst_ptr );
259 return SCARD_E_NO_MEMORY;
261 memcpy( dst_ptr + total_len, str, len );
262 total_len += len;
263 src_ptr += len;
264 free( str );
267 dst_ptr[total_len] = 0;
268 if (dst_ptr != dst) *(char **)dst = dst_ptr;
269 *dst_len = ++total_len;
270 return SCARD_S_SUCCESS;
273 LONG WINAPI SCardStatusA( SCARDHANDLE connect, char *names, DWORD *names_len, DWORD *state, DWORD *protocol,
274 BYTE *atr, DWORD *atr_len )
276 struct handle *handle = (struct handle *)connect;
277 struct scard_status_params params;
278 UINT64 state64, protocol64, atr_len64, names_len_utf8 = 0;
279 LONG ret;
281 TRACE( "%Ix, %p, %p, %p, %p, %p, %p\n", connect, names, names_len, state, protocol, atr, atr_len );
283 if (!handle || handle->magic != CONNECT_MAGIC) return ERROR_INVALID_HANDLE;
284 if (atr_len && *atr_len == SCARD_AUTOALLOCATE)
286 FIXME( "SCARD_AUTOALLOCATE not supported for attr\n" );
287 return SCARD_F_INTERNAL_ERROR;
290 params.handle = handle->unix_handle;
291 params.names = NULL;
292 params.names_len = &names_len_utf8;
293 params.state = &state64;
294 params.protocol = &protocol64;
295 params.atr = NULL;
296 if (!atr_len) params.atr_len = NULL;
297 else
299 atr_len64 = *atr_len;
300 params.atr_len = &atr_len64;
302 if ((ret = UNIX_CALL( scard_status, &params ))) return ret;
304 if (!(params.names = malloc( names_len_utf8 ))) return SCARD_E_NO_MEMORY;
305 if (!(ret = UNIX_CALL( scard_status, &params )) && !(ret = copy_multiszA( params.names, names, names_len )))
307 if (state) *state = state64;
308 if (protocol) *protocol = protocol64;
309 if (atr_len) *atr_len = atr_len64;
312 free( params.names );
313 TRACE( "returning %#lx\n", ret );
314 return ret;
317 static LONG copy_multiszW( const char *src, WCHAR *dst, DWORD *dst_len )
319 int len, total_len = 0;
320 const char *src_ptr = src;
321 WCHAR *dst_ptr;
323 if (!dst && !dst_len) return SCARD_S_SUCCESS;
325 while (*src_ptr)
327 if ((len = utf8_to_utf16( src_ptr, NULL )) < 0) return SCARD_E_INVALID_PARAMETER;
328 total_len += len;
329 src_ptr += len;
331 total_len++; /* double null */
333 if (*dst_len == SCARD_AUTOALLOCATE)
335 if (!(dst_ptr = malloc( total_len * sizeof(WCHAR) ))) return SCARD_E_NO_MEMORY;
337 else
339 if (dst && *dst_len < total_len)
341 *dst_len = total_len;
342 return SCARD_E_INSUFFICIENT_BUFFER;
344 if (!dst)
346 *dst_len = total_len;
347 return SCARD_S_SUCCESS;
349 dst_ptr = dst;
352 src_ptr = src;
353 total_len = 0;
354 while (*src_ptr)
356 WCHAR *str;
357 if ((len = utf8_to_utf16( src_ptr, &str )) < 0)
359 if (dst_ptr != dst) free( dst_ptr );
360 return SCARD_E_NO_MEMORY;
362 memcpy( dst_ptr + total_len, str, len * sizeof(WCHAR) );
363 total_len += len;
364 src_ptr += len;
365 free( str );
368 dst_ptr[total_len] = 0;
369 if (dst_ptr != dst) *(WCHAR **)dst = dst_ptr;
370 *dst_len = ++total_len;
371 return SCARD_S_SUCCESS;
374 LONG WINAPI SCardStatusW( SCARDHANDLE connect, WCHAR *names, DWORD *names_len, DWORD *state, DWORD *protocol,
375 BYTE *atr, DWORD *atr_len )
377 struct handle *handle = (struct handle *)connect;
378 struct scard_status_params params;
379 UINT64 state64, protocol64, atr_len64, names_len_utf8 = 0;
380 LONG ret;
382 TRACE( "%Ix, %p, %p, %p, %p, %p, %p\n", connect, names, names_len, state, protocol, atr, atr_len );
384 if (!handle || handle->magic != CONNECT_MAGIC) return ERROR_INVALID_HANDLE;
385 if (atr_len && *atr_len == SCARD_AUTOALLOCATE)
387 FIXME( "SCARD_AUTOALLOCATE not supported for attr\n" );
388 return SCARD_F_INTERNAL_ERROR;
391 params.handle = handle->unix_handle;
392 params.names = NULL;
393 params.names_len = &names_len_utf8;
394 params.state = &state64;
395 params.protocol = &protocol64;
396 params.atr = atr;
397 if (!atr_len) params.atr_len = NULL;
398 else
400 atr_len64 = *atr_len;
401 params.atr_len = &atr_len64;
403 if ((ret = UNIX_CALL( scard_status, &params ))) return ret;
405 if (!(params.names = malloc( names_len_utf8 ))) return SCARD_E_NO_MEMORY;
406 if (!(ret = UNIX_CALL( scard_status, &params )) && !(ret = copy_multiszW( params.names, names, names_len )))
408 if (state) *state = state64;
409 if (protocol) *protocol = protocol64;
410 if (atr_len) *atr_len = atr_len64;
413 free( params.names );
414 TRACE( "returning %#lx\n", ret );
415 return ret;
418 void WINAPI SCardReleaseStartedEvent(void)
420 FIXME( "stub\n" );
423 LONG WINAPI SCardListReadersA( SCARDCONTEXT context, const char *groups, char *readers, DWORD *readers_len )
425 struct handle *handle = (struct handle *)context;
426 struct scard_list_readers_params params;
427 UINT64 readers_len_utf8;
428 LONG ret;
430 TRACE( "%Ix, %s, %p, %p\n", context, debugstr_a(groups), readers, readers_len );
432 if (!handle || handle->magic != CONTEXT_MAGIC) return ERROR_INVALID_HANDLE;
433 if (!readers_len) return SCARD_E_INVALID_PARAMETER;
435 params.handle = handle->unix_handle;
436 if (!groups) params.groups = NULL;
437 else if (ansi_to_utf8( groups, (char **)&params.groups ) < 0) return SCARD_E_NO_MEMORY;
438 params.readers = NULL;
439 params.readers_len = &readers_len_utf8;
440 if ((ret = UNIX_CALL( scard_list_readers, &params ))) goto done;
442 if (!(params.readers = malloc( readers_len_utf8 )))
444 free( (void *)params.groups );
445 return SCARD_E_NO_MEMORY;
447 if (!(ret = UNIX_CALL( scard_list_readers, &params )))
449 ret = copy_multiszA( params.readers, readers, readers_len );
452 done:
453 free( (void *)params.groups );
454 free( params.readers );
455 TRACE( "returning %#lx\n", ret );
456 return ret;
459 LONG WINAPI SCardListReadersW( SCARDCONTEXT context, const WCHAR *groups, WCHAR *readers, DWORD *readers_len )
461 struct handle *handle = (struct handle *)context;
462 struct scard_list_readers_params params;
463 UINT64 readers_len_utf8;
464 LONG ret;
466 TRACE( "%Ix, %s, %p, %p\n", context, debugstr_w(groups), readers, readers_len );
468 if (!handle || handle->magic != CONTEXT_MAGIC) return ERROR_INVALID_HANDLE;
469 if (!readers_len) return SCARD_E_INVALID_PARAMETER;
471 params.handle = handle->unix_handle;
472 if (!groups) params.groups = NULL;
473 else if (utf16_to_utf8( groups, (char **)&params.groups ) < 0) return SCARD_E_NO_MEMORY;
474 params.readers = NULL;
475 params.readers_len = &readers_len_utf8;
476 if ((ret = UNIX_CALL( scard_list_readers, &params ))) goto done;
478 params.handle = handle->unix_handle;
479 if (!(params.readers = malloc( readers_len_utf8 )))
481 free( (void *)params.groups );
482 return SCARD_E_NO_MEMORY;
484 if (!(ret = UNIX_CALL( scard_list_readers, &params )))
486 ret = copy_multiszW( params.readers, readers, readers_len );
489 done:
490 free( (void *)params.groups );
491 free( params.readers );
492 TRACE( "returning %#lx\n", ret );
493 return ret;
496 LONG WINAPI SCardCancel( SCARDCONTEXT context )
498 struct handle *handle = (struct handle *)context;
499 struct scard_cancel_params params;
500 LONG ret;
502 TRACE( "%Ix\n", context );
504 if (!handle || handle->magic != CONTEXT_MAGIC) return ERROR_INVALID_HANDLE;
506 params.handle = handle->unix_handle;
507 ret = UNIX_CALL( scard_cancel, &params );
508 TRACE( "returning %#lx\n", ret );
509 return ret;
512 LONG WINAPI SCardListReaderGroupsA( SCARDCONTEXT context, char *groups, DWORD *groups_len )
514 struct handle *handle = (struct handle *)context;
515 struct scard_list_reader_groups_params params;
516 UINT64 groups_len_utf8;
517 LONG ret;
519 TRACE( "%Ix, %p, %p\n", context, groups, groups_len );
521 if (!handle || handle->magic != CONTEXT_MAGIC) return ERROR_INVALID_HANDLE;
522 if (!groups_len) return SCARD_E_INVALID_PARAMETER;
524 params.handle = handle->unix_handle;
525 params.groups = NULL;
526 params.groups_len = &groups_len_utf8;
527 if ((ret = UNIX_CALL( scard_list_reader_groups, &params ))) goto done;
529 params.handle = handle->unix_handle;
530 if (!(params.groups = malloc( groups_len_utf8 ))) return SCARD_E_NO_MEMORY;
531 if (!(ret = UNIX_CALL( scard_list_reader_groups, &params )))
533 ret = copy_multiszA( params.groups, groups, groups_len );
536 done:
537 free( params.groups );
538 TRACE( "returning %#lx\n", ret );
539 return ret;
542 LONG WINAPI SCardListReaderGroupsW( SCARDCONTEXT context, WCHAR *groups, DWORD *groups_len )
544 struct handle *handle = (struct handle *)context;
545 struct scard_list_reader_groups_params params;
546 UINT64 groups_len_utf8;
547 LONG ret;
549 TRACE( "%Ix, %p, %p\n", context, groups, groups_len );
551 if (!handle || handle->magic != CONTEXT_MAGIC) return ERROR_INVALID_HANDLE;
552 if (!groups_len) return SCARD_E_INVALID_PARAMETER;
554 params.handle = handle->unix_handle;
555 params.groups = NULL;
556 params.groups_len = &groups_len_utf8;
557 if ((ret = UNIX_CALL( scard_list_reader_groups, &params ))) goto done;
559 if (!(params.groups = malloc( groups_len_utf8 ))) return SCARD_E_NO_MEMORY;
560 if (!(ret = UNIX_CALL( scard_list_reader_groups, &params )))
562 ret = copy_multiszW( params.groups, groups, groups_len );
565 done:
566 TRACE( "returning %#lx\n", ret );
567 free( params.groups );
568 return ret;
571 static LONG map_states_inA( const SCARD_READERSTATEA *src, struct reader_state *dst, DWORD count )
573 DWORD i;
574 memset( dst, 0, sizeof(*dst) * count );
575 for (i = 0; i < count; i++)
577 if (src[i].szReader && ansi_to_utf8( src[i].szReader, (char **)&dst[i].reader ) < 0)
578 return SCARD_E_NO_MEMORY;
580 return SCARD_S_SUCCESS;
583 static void map_states_out( const struct reader_state *src, SCARD_READERSTATEA *dst, DWORD count )
585 DWORD i;
586 for (i = 0; i < count; i++)
588 dst[i].dwCurrentState = src[i].current_state;
589 dst[i].dwEventState = src[i].event_state;
590 dst[i].cbAtr = src[i].atr_size;
591 memcpy( dst[i].rgbAtr, src[i].atr, src[i].atr_size );
595 static void free_states( struct reader_state *states, DWORD count )
597 DWORD i;
598 for (i = 0; i < count; i++) free( (void *)(ULONG_PTR)states[i].reader );
599 free( states );
602 LONG WINAPI SCardGetStatusChangeA( SCARDCONTEXT context, DWORD timeout, SCARD_READERSTATEA *states, DWORD count )
604 struct handle *handle = (struct handle *)context;
605 struct scard_get_status_change_params params;
606 struct reader_state *states_utf8 = NULL;
607 LONG ret;
609 TRACE( "%Ix, %lu, %p, %lu\n", context, timeout, states, count );
611 if (!handle || handle->magic != CONTEXT_MAGIC) return ERROR_INVALID_HANDLE;
613 if (!(states_utf8 = calloc( count, sizeof(*states_utf8) ))) return SCARD_E_NO_MEMORY;
614 if ((ret = map_states_inA( states, states_utf8, count )))
616 free_states( states_utf8, count );
617 return ret;
620 params.handle = handle->unix_handle;
621 params.timeout = timeout;
622 params.states = states_utf8;
623 params.count = count;
624 if (!(ret = UNIX_CALL( scard_get_status_change, &params )) && states)
626 map_states_out( states_utf8, states, count );
629 free_states( states_utf8, count );
630 TRACE( "returning %#lx\n", ret );
631 return ret;
634 static LONG map_states_inW( SCARD_READERSTATEW *src, struct reader_state *dst, DWORD count )
636 DWORD i;
637 memset( dst, 0, sizeof(*dst) * count );
638 for (i = 0; i < count; i++)
640 if (src[i].szReader && utf16_to_utf8( src[i].szReader, (char **)&dst[i].reader ) < 0)
641 return SCARD_E_NO_MEMORY;
643 return SCARD_S_SUCCESS;
646 LONG WINAPI SCardGetStatusChangeW( SCARDCONTEXT context, DWORD timeout, SCARD_READERSTATEW *states, DWORD count )
648 struct handle *handle = (struct handle *)context;
649 struct scard_get_status_change_params params;
650 struct reader_state *states_utf8;
651 LONG ret;
653 TRACE( "%Ix, %lu, %p, %lu\n", context, timeout, states, count );
655 if (!handle || handle->magic != CONTEXT_MAGIC) return ERROR_INVALID_HANDLE;
657 if (!(states_utf8 = calloc( count, sizeof(*states_utf8) ))) return SCARD_E_NO_MEMORY;
658 if ((ret = map_states_inW( states, states_utf8, count )))
660 free_states( states_utf8, count );
661 return ret;
664 params.handle = handle->unix_handle;
665 params.timeout = timeout;
666 params.states = states_utf8;
667 params.count = count;
668 if (!(ret = UNIX_CALL( scard_get_status_change, &params )))
670 map_states_out( states_utf8, (SCARD_READERSTATEA *)states, count );
673 free_states( states_utf8, count );
674 TRACE( "returning %#lx\n", ret );
675 return ret;
678 LONG WINAPI SCardConnectA( SCARDCONTEXT context, const char *reader, DWORD share_mode, DWORD preferred_protocols,
679 SCARDHANDLE *connect, DWORD *protocol )
681 struct handle *context_handle = (struct handle *)context, *connect_handle;
682 struct scard_connect_params params;
683 char *reader_utf8;
684 UINT64 protocol64;
685 LONG ret;
687 TRACE( "%Ix, %s, %#lx, %#lx, %p, %p\n", context, debugstr_a(reader), share_mode, preferred_protocols, connect,
688 protocol );
690 if (!context_handle || context_handle->magic != CONTEXT_MAGIC) return ERROR_INVALID_HANDLE;
691 if (!connect) return SCARD_E_INVALID_PARAMETER;
693 if (!(connect_handle = malloc( sizeof(*connect_handle) ))) return SCARD_E_NO_MEMORY;
694 connect_handle->magic = CONNECT_MAGIC;
696 if (ansi_to_utf8( reader, &reader_utf8 ) < 0)
698 free( connect_handle );
699 return SCARD_E_NO_MEMORY;
702 params.context_handle = context_handle->unix_handle;
703 params.reader = reader_utf8;
704 params.share_mode = share_mode;
705 params.preferred_protocols = preferred_protocols;
706 params.connect_handle = &connect_handle->unix_handle;
707 params.protocol = &protocol64;
708 if ((ret = UNIX_CALL( scard_connect, &params ))) free( connect_handle );
709 else
711 *connect = (SCARDHANDLE)connect_handle;
712 if (protocol) *protocol = protocol64;
715 free( reader_utf8 );
716 TRACE( "returning %#lx\n", ret );
717 return ret;
720 LONG WINAPI SCardConnectW( SCARDCONTEXT context, const WCHAR *reader, DWORD share_mode, DWORD preferred_protocols,
721 SCARDHANDLE *connect, DWORD *protocol )
723 struct handle *context_handle = (struct handle *)context, *connect_handle;
724 struct scard_connect_params params;
725 char *reader_utf8;
726 UINT64 protocol64;
727 LONG ret;
729 TRACE( "%Ix, %s, %#lx, %#lx, %p, %p\n", context, debugstr_w(reader), share_mode, preferred_protocols, connect,
730 protocol );
732 if (!context_handle || context_handle->magic != CONTEXT_MAGIC) return ERROR_INVALID_HANDLE;
733 if (!connect) return SCARD_E_INVALID_PARAMETER;
735 if (!(connect_handle = malloc( sizeof(*connect_handle) ))) return SCARD_E_NO_MEMORY;
736 connect_handle->magic = CONNECT_MAGIC;
738 if (utf16_to_utf8( reader, &reader_utf8 ) < 0)
740 free( connect_handle );
741 return SCARD_E_NO_MEMORY;
744 params.context_handle = context_handle->unix_handle;
745 params.reader = reader_utf8;
746 params.share_mode = share_mode;
747 params.preferred_protocols = preferred_protocols;
748 params.connect_handle = &connect_handle->unix_handle;
749 params.protocol = &protocol64;
750 if ((ret = UNIX_CALL( scard_connect, &params ))) free( connect_handle );
751 else
753 *connect = (SCARDHANDLE)connect_handle;
754 if (protocol) *protocol = protocol64;
757 free( reader_utf8 );
758 TRACE( "returning %#lx\n", ret );
759 return ret;
762 LONG WINAPI SCardReconnect( SCARDHANDLE connect, DWORD share_mode, DWORD preferred_protocols, DWORD initialization,
763 DWORD *protocol )
765 struct handle *handle = (struct handle *)connect;
766 struct scard_reconnect_params params;
767 UINT64 protocol64;
768 LONG ret;
770 TRACE( "%Ix, %#lx, %#lx, %#lx, %p\n", connect, share_mode, preferred_protocols, initialization, protocol );
772 if (!handle || handle->magic != CONNECT_MAGIC) return ERROR_INVALID_HANDLE;
774 params.handle = handle->unix_handle;
775 params.share_mode = share_mode;
776 params.preferred_protocols = preferred_protocols;
777 params.initialization = initialization;
778 params.protocol = &protocol64;
779 if (!(ret = UNIX_CALL( scard_reconnect, &params )) && protocol) *protocol = protocol64;
780 TRACE( "returning %#lx\n", ret );
781 return ret;
784 LONG WINAPI SCardDisconnect( SCARDHANDLE connect, DWORD disposition )
786 struct handle *handle = (struct handle *)connect;
787 struct scard_disconnect_params params;
788 LONG ret;
790 TRACE( "%Ix, %#lx\n", connect, disposition );
792 if (!handle || handle->magic != CONNECT_MAGIC) return ERROR_INVALID_HANDLE;
794 params.handle = handle->unix_handle;
795 params.disposition = disposition;
796 if (!(ret = UNIX_CALL( scard_disconnect, &params )))
798 /* Ensure compiler doesn't optimize out the assignment with 0. */
799 SecureZeroMemory( &handle->magic, sizeof(handle->magic) );
800 free( handle );
802 TRACE( "returning %#lx\n", ret );
803 return ret;
806 LONG WINAPI SCardBeginTransaction( SCARDHANDLE connect )
808 struct handle *handle = (struct handle *)connect;
809 struct scard_begin_transaction_params params;
810 LONG ret;
812 TRACE( "%Ix\n", connect );
814 if (!handle || handle->magic != CONNECT_MAGIC) return ERROR_INVALID_HANDLE;
816 params.handle = handle->unix_handle;
817 ret = UNIX_CALL( scard_begin_transaction, &params );
818 TRACE( "returning %#lx\n", ret );
819 return ret;
822 LONG WINAPI SCardEndTransaction( SCARDHANDLE connect, DWORD disposition )
824 struct handle *handle = (struct handle *)connect;
825 struct scard_end_transaction_params params;
826 LONG ret;
828 TRACE( "%Ix, %#lx\n", connect, disposition );
830 if (!handle || handle->magic != CONNECT_MAGIC) return ERROR_INVALID_HANDLE;
832 params.handle = handle->unix_handle;
833 params.disposition = disposition;
834 ret = UNIX_CALL( scard_end_transaction, &params );
835 TRACE( "returning %#lx\n", ret );
836 return ret;
839 LONG WINAPI SCardTransmit( SCARDHANDLE connect, const SCARD_IO_REQUEST *send, const BYTE *send_buf,
840 DWORD send_buflen, SCARD_IO_REQUEST *recv, BYTE *recv_buf, DWORD *recv_buflen )
842 struct handle *handle = (struct handle *)connect;
843 struct scard_transmit_params params;
844 struct io_request send64 = { send->dwProtocol, send->cbPciLength }, recv64;
845 UINT64 recv_buflen64;
846 LONG ret;
848 TRACE( "%Ix, %p, %p, %lu, %p, %p, %p\n", connect, send, send_buf, send_buflen, recv, recv_buf, recv_buflen );
850 if (!handle || handle->magic != CONNECT_MAGIC) return ERROR_INVALID_HANDLE;
851 if (!recv_buflen) return SCARD_E_INVALID_PARAMETER;
853 params.handle = handle->unix_handle;
854 params.send = &send64;
855 params.send_buf = send_buf;
856 params.send_buflen = send_buflen;
857 params.recv = &recv64;
858 params.recv_buf = recv_buf;
859 recv_buflen64 = *recv_buflen;
860 params.recv_buflen = &recv_buflen64;
861 if (!(ret = UNIX_CALL( scard_transmit, &params )))
863 if (recv)
865 recv->dwProtocol = recv64.protocol;
866 recv->cbPciLength = recv64.pci_len;
868 *recv_buflen = recv_buflen64;
871 TRACE( "returning %#lx\n", ret );
872 return ret;
875 LONG WINAPI SCardControl( SCARDHANDLE connect, DWORD code, const void *in_buf, DWORD in_buflen, void *out_buf,
876 DWORD out_buflen, DWORD *ret_len )
878 struct handle *handle = (struct handle *)connect;
879 struct scard_control_params params;
880 UINT64 ret_len64;
881 LONG ret;
883 TRACE( "%Ix, %#lx, %p, %lu, %p, %lu, %p\n", connect, code, in_buf, in_buflen, out_buf, out_buflen, ret_len );
885 if (!handle || handle->magic != CONNECT_MAGIC) return ERROR_INVALID_HANDLE;
886 if (!ret_len) return SCARD_E_INVALID_PARAMETER;
888 params.handle = handle->unix_handle;
889 params.code = code;
890 params.in_buf = in_buf;
891 params.in_buflen = in_buflen;
892 params.out_buf = out_buf;
893 params.out_buflen = out_buflen;
894 params.ret_len = &ret_len64;
895 if (!(ret = UNIX_CALL( scard_control, &params ))) *ret_len = ret_len64;
896 TRACE( "returning %#lx\n", ret );
897 return ret;
900 LONG WINAPI SCardGetAttrib( SCARDHANDLE connect, DWORD id, BYTE *attr, DWORD *attr_len )
902 struct handle *handle = (struct handle *)connect;
903 struct scard_get_attrib_params params;
904 UINT64 attr_len64;
905 LONG ret;
907 TRACE( "%Ix, %#lx, %p, %p\n", connect, id, attr, attr_len );
909 if (!handle || handle->magic != CONNECT_MAGIC) return ERROR_INVALID_HANDLE;
910 if (!attr_len) return SCARD_E_INVALID_PARAMETER;
912 params.handle = handle->unix_handle;
913 params.id = id;
914 params.attr = attr;
915 attr_len64 = *attr_len;
916 params.attr_len = &attr_len64;
917 if (!(ret = UNIX_CALL( scard_get_attrib, &params ))) *attr_len = attr_len64;
918 TRACE( "returning %#lx\n", ret );
919 return ret;
922 LONG WINAPI SCardSetAttrib( SCARDHANDLE connect, DWORD id, const BYTE *attr, DWORD attr_len )
924 struct handle *handle = (struct handle *)connect;
925 struct scard_set_attrib_params params;
926 LONG ret;
928 TRACE( "%Ix, %#lx, %p, %lu\n", connect, id, attr, attr_len );
930 if (!handle || handle->magic != CONNECT_MAGIC) return ERROR_INVALID_HANDLE;
932 params.handle = handle->unix_handle;
933 params.id = id;
934 params.attr = attr;
935 params.attr_len = attr_len;
936 ret = UNIX_CALL( scard_set_attrib, &params );
937 TRACE( "returning %#lx\n", ret );
938 return ret;
941 LONG WINAPI SCardFreeMemory( SCARDCONTEXT context, const void *mem )
943 TRACE( "%Ix, %p\n", context, mem );
945 free( (void *)mem );
946 return SCARD_S_SUCCESS;
949 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, void *reserved )
951 switch (reason)
953 case DLL_PROCESS_ATTACH:
954 DisableThreadLibraryCalls( hinst );
955 if (__wine_init_unix_call()) ERR( "no pcsclite support, expect problems\n" );
957 /* FIXME: for now, we act as if the pcsc daemon is always started */
958 g_startedEvent = CreateEventW( NULL, TRUE, TRUE, NULL );
959 break;
961 case DLL_PROCESS_DETACH:
962 if (reserved) break;
963 CloseHandle( g_startedEvent );
964 g_startedEvent = NULL;
965 break;
968 return TRUE;