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
27 #include "wine/debug.h"
28 #include "wine/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
);
46 if (!(*dst
= malloc( len
))) return -1;
47 WideCharToMultiByte( CP_UTF8
, 0, src
, -1, *dst
, len
, NULL
, NULL
);
52 static inline int ansi_to_utf16( const char *src
, WCHAR
**dst
)
54 int len
= MultiByteToWideChar( CP_ACP
, 0, src
, -1, NULL
, 0 );
57 if (!(*dst
= malloc( len
* sizeof(WCHAR
) ))) return -1;
58 MultiByteToWideChar( CP_ACP
, 0, src
, -1, *dst
, len
);
63 static inline int ansi_to_utf8( const char *src
, char **dst
)
68 if (ansi_to_utf16( src
, &tmp
) < 0) return -1;
69 len
= utf16_to_utf8( tmp
, dst
);
74 static inline int utf8_to_utf16( const char *src
, WCHAR
**dst
)
76 int len
= MultiByteToWideChar( CP_UTF8
, 0, src
, -1, NULL
, 0 );
79 if (!(*dst
= malloc( len
* sizeof(WCHAR
) ))) return -1;
80 MultiByteToWideChar( CP_UTF8
, 0, src
, -1, *dst
, 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
);
90 FIXME( "can't convert %s to ANSI codepage\n", debugstr_w(src
) );
95 if (!(*dst
= malloc( len
))) return -1;
96 WideCharToMultiByte( CP_ACP
, WC_NO_BEST_FIT_CHARS
, src
, -1, *dst
, len
, NULL
, NULL
);
101 static inline int utf8_to_ansi( const char *src
, char **dst
)
106 if (utf8_to_utf16( src
, &tmp
) < 0) return -1;
107 len
= utf16_to_ansi( tmp
, dst
);
112 HANDLE WINAPI
SCardAccessStartedEvent(void)
115 return g_startedEvent
;
118 LONG WINAPI
SCardAddReaderToGroupA( SCARDCONTEXT context
, const char *reader
, const char *group
)
120 WCHAR
*readerW
= NULL
, *groupW
= NULL
;
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)
129 return SCARD_E_NO_MEMORY
;
131 ret
= SCardAddReaderToGroupW( context
, readerW
, groupW
);
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')
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
;
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
, ¶ms
))) *context
= (SCARDCONTEXT
)handle
;
168 TRACE( "returning %#lx\n", ret
);
172 LONG WINAPI
SCardIsValidContext( SCARDCONTEXT context
)
174 struct handle
*handle
= (struct handle
*)context
;
175 struct scard_is_valid_context_params params
;
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
, ¶ms
);
184 TRACE( "returning %#lx\n", 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
;
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
, ¶ms
);
208 /* Ensure compiler doesn't optimize out the assignment with 0. */
209 SecureZeroMemory( &handle
->magic
, sizeof(handle
->magic
) );
212 TRACE( "returning %#lx\n", 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
;
222 if (!dst
&& !dst_len
) return SCARD_S_SUCCESS
;
226 if ((len
= utf8_to_ansi( src_ptr
, NULL
)) < 0) return SCARD_E_INVALID_PARAMETER
;
230 total_len
++; /* double null */
232 if (*dst_len
== SCARD_AUTOALLOCATE
)
234 if (!(dst_ptr
= malloc( total_len
))) return SCARD_E_NO_MEMORY
;
238 if (dst
&& *dst_len
< total_len
)
240 *dst_len
= total_len
;
241 return SCARD_E_INSUFFICIENT_BUFFER
;
245 *dst_len
= total_len
;
246 return SCARD_S_SUCCESS
;
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
);
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;
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
;
292 params
.names_len
= &names_len_utf8
;
293 params
.state
= &state64
;
294 params
.protocol
= &protocol64
;
296 if (!atr_len
) params
.atr_len
= NULL
;
299 atr_len64
= *atr_len
;
300 params
.atr_len
= &atr_len64
;
302 if ((ret
= UNIX_CALL( scard_status
, ¶ms
))) return ret
;
304 if (!(params
.names
= malloc( names_len_utf8
))) return SCARD_E_NO_MEMORY
;
305 if (!(ret
= UNIX_CALL( scard_status
, ¶ms
)) && !(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
);
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
;
323 if (!dst
&& !dst_len
) return SCARD_S_SUCCESS
;
327 if ((len
= utf8_to_utf16( src_ptr
, NULL
)) < 0) return SCARD_E_INVALID_PARAMETER
;
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
;
339 if (dst
&& *dst_len
< total_len
)
341 *dst_len
= total_len
;
342 return SCARD_E_INSUFFICIENT_BUFFER
;
346 *dst_len
= total_len
;
347 return SCARD_S_SUCCESS
;
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
) );
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;
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
;
393 params
.names_len
= &names_len_utf8
;
394 params
.state
= &state64
;
395 params
.protocol
= &protocol64
;
397 if (!atr_len
) params
.atr_len
= NULL
;
400 atr_len64
= *atr_len
;
401 params
.atr_len
= &atr_len64
;
403 if ((ret
= UNIX_CALL( scard_status
, ¶ms
))) return ret
;
405 if (!(params
.names
= malloc( names_len_utf8
))) return SCARD_E_NO_MEMORY
;
406 if (!(ret
= UNIX_CALL( scard_status
, ¶ms
)) && !(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
);
418 void WINAPI
SCardReleaseStartedEvent(void)
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
;
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 **)¶ms
.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
, ¶ms
))) 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
, ¶ms
)))
449 ret
= copy_multiszA( params
.readers
, readers
, readers_len
);
453 free( (void *)params
.groups
);
454 free( params
.readers
);
455 TRACE( "returning %#lx\n", 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
;
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 **)¶ms
.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
, ¶ms
))) 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
, ¶ms
)))
486 ret
= copy_multiszW( params
.readers
, readers
, readers_len
);
490 free( (void *)params
.groups
);
491 free( params
.readers
);
492 TRACE( "returning %#lx\n", ret
);
496 LONG WINAPI
SCardCancel( SCARDCONTEXT context
)
498 struct handle
*handle
= (struct handle
*)context
;
499 struct scard_cancel_params params
;
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
, ¶ms
);
508 TRACE( "returning %#lx\n", 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
;
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
, ¶ms
))) 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
, ¶ms
)))
533 ret
= copy_multiszA( params
.groups
, groups
, groups_len
);
537 free( params
.groups
);
538 TRACE( "returning %#lx\n", 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
;
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
, ¶ms
))) goto done
;
559 if (!(params
.groups
= malloc( groups_len_utf8
))) return SCARD_E_NO_MEMORY
;
560 if (!(ret
= UNIX_CALL( scard_list_reader_groups
, ¶ms
)))
562 ret
= copy_multiszW( params
.groups
, groups
, groups_len
);
566 TRACE( "returning %#lx\n", ret
);
567 free( params
.groups
);
571 static LONG
map_states_inA( const SCARD_READERSTATEA
*src
, struct reader_state
*dst
, DWORD count
)
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
)
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
)
598 for (i
= 0; i
< count
; i
++) free( (void *)(ULONG_PTR
)states
[i
].reader
);
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
;
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
);
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
, ¶ms
)) && states
)
626 map_states_out( states_utf8
, states
, count
);
629 free_states( states_utf8
, count
);
630 TRACE( "returning %#lx\n", ret
);
634 static LONG
map_states_inW( SCARD_READERSTATEW
*src
, struct reader_state
*dst
, DWORD count
)
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
;
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
);
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
, ¶ms
)))
670 map_states_out( states_utf8
, (SCARD_READERSTATEA
*)states
, count
);
673 free_states( states_utf8
, count
);
674 TRACE( "returning %#lx\n", 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
;
687 TRACE( "%Ix, %s, %#lx, %#lx, %p, %p\n", context
, debugstr_a(reader
), share_mode
, preferred_protocols
, connect
,
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
, ¶ms
))) free( connect_handle
);
711 *connect
= (SCARDHANDLE
)connect_handle
;
712 if (protocol
) *protocol
= protocol64
;
716 TRACE( "returning %#lx\n", 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
;
729 TRACE( "%Ix, %s, %#lx, %#lx, %p, %p\n", context
, debugstr_w(reader
), share_mode
, preferred_protocols
, connect
,
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
, ¶ms
))) free( connect_handle
);
753 *connect
= (SCARDHANDLE
)connect_handle
;
754 if (protocol
) *protocol
= protocol64
;
758 TRACE( "returning %#lx\n", ret
);
762 LONG WINAPI
SCardReconnect( SCARDHANDLE connect
, DWORD share_mode
, DWORD preferred_protocols
, DWORD initialization
,
765 struct handle
*handle
= (struct handle
*)connect
;
766 struct scard_reconnect_params params
;
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
, ¶ms
)) && protocol
) *protocol
= protocol64
;
780 TRACE( "returning %#lx\n", ret
);
784 LONG WINAPI
SCardDisconnect( SCARDHANDLE connect
, DWORD disposition
)
786 struct handle
*handle
= (struct handle
*)connect
;
787 struct scard_disconnect_params params
;
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
, ¶ms
)))
798 /* Ensure compiler doesn't optimize out the assignment with 0. */
799 SecureZeroMemory( &handle
->magic
, sizeof(handle
->magic
) );
802 TRACE( "returning %#lx\n", ret
);
806 LONG WINAPI
SCardBeginTransaction( SCARDHANDLE connect
)
808 struct handle
*handle
= (struct handle
*)connect
;
809 struct scard_begin_transaction_params params
;
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
, ¶ms
);
818 TRACE( "returning %#lx\n", ret
);
822 LONG WINAPI
SCardEndTransaction( SCARDHANDLE connect
, DWORD disposition
)
824 struct handle
*handle
= (struct handle
*)connect
;
825 struct scard_end_transaction_params params
;
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
, ¶ms
);
835 TRACE( "returning %#lx\n", 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
;
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
, ¶ms
)))
865 recv
->dwProtocol
= recv64
.protocol
;
866 recv
->cbPciLength
= recv64
.pci_len
;
868 *recv_buflen
= recv_buflen64
;
871 TRACE( "returning %#lx\n", 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
;
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
;
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
, ¶ms
))) *ret_len
= ret_len64
;
896 TRACE( "returning %#lx\n", 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
;
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
;
915 attr_len64
= *attr_len
;
916 params
.attr_len
= &attr_len64
;
917 if (!(ret
= UNIX_CALL( scard_get_attrib
, ¶ms
))) *attr_len
= attr_len64
;
918 TRACE( "returning %#lx\n", 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
;
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
;
935 params
.attr_len
= attr_len
;
936 ret
= UNIX_CALL( scard_set_attrib
, ¶ms
);
937 TRACE( "returning %#lx\n", ret
);
941 LONG WINAPI
SCardFreeMemory( SCARDCONTEXT context
, const void *mem
)
943 TRACE( "%Ix, %p\n", context
, mem
);
946 return SCARD_S_SUCCESS
;
949 BOOL WINAPI
DllMain( HINSTANCE hinst
, DWORD reason
, void *reserved
)
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
);
961 case DLL_PROCESS_DETACH
:
963 CloseHandle( g_startedEvent
);
964 g_startedEvent
= NULL
;