FreeRDP
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Modules Pages
smartcard_pack.c
1
24#include <freerdp/config.h>
25
26#include <winpr/crt.h>
27#include <winpr/print.h>
28
29#include <freerdp/channels/scard.h>
30#include <freerdp/utils/smartcard_pack.h>
31#include "smartcard_pack.h"
32
33#include <freerdp/log.h>
34#define SCARD_TAG FREERDP_TAG("scard.pack")
35
36static const DWORD g_LogLevel = WLOG_DEBUG;
37
38static wLog* scard_log(void)
39{
40 static wLog* log = NULL;
41 if (!log)
42 log = WLog_Get(SCARD_TAG);
43 return log;
44}
45
46#define smartcard_unpack_redir_scard_context(log, s, context, index, ndr) \
47 smartcard_unpack_redir_scard_context_((log), (s), (context), (index), (ndr), __FILE__, \
48 __func__, __LINE__)
49#define smartcard_unpack_redir_scard_handle(log, s, context, index) \
50 smartcard_unpack_redir_scard_handle_((log), (s), (context), (index), __FILE__, __func__, \
51 __LINE__)
52
53static LONG smartcard_unpack_redir_scard_context_(wLog* log, wStream* s,
54 REDIR_SCARDCONTEXT* context, UINT32* index,
55 UINT32* ppbContextNdrPtr, const char* file,
56 const char* function, size_t line);
57static LONG smartcard_pack_redir_scard_context(wLog* log, wStream* s,
58 const REDIR_SCARDCONTEXT* context, DWORD* index);
59static LONG smartcard_unpack_redir_scard_handle_(wLog* log, wStream* s, REDIR_SCARDHANDLE* handle,
60 UINT32* index, const char* file,
61 const char* function, size_t line);
62static LONG smartcard_pack_redir_scard_handle(wLog* log, wStream* s,
63 const REDIR_SCARDHANDLE* handle, DWORD* index);
64static LONG smartcard_unpack_redir_scard_context_ref(wLog* log, wStream* s, UINT32 pbContextNdrPtr,
65 REDIR_SCARDCONTEXT* context);
66static LONG smartcard_pack_redir_scard_context_ref(wLog* log, wStream* s,
67 const REDIR_SCARDCONTEXT* context);
68
69static LONG smartcard_unpack_redir_scard_handle_ref(wLog* log, wStream* s,
70 REDIR_SCARDHANDLE* handle);
71static LONG smartcard_pack_redir_scard_handle_ref(wLog* log, wStream* s,
72 const REDIR_SCARDHANDLE* handle);
73
74typedef enum
75{
76 NDR_PTR_FULL,
77 NDR_PTR_SIMPLE,
78 NDR_PTR_FIXED
79} ndr_ptr_t;
80
81/* Reads a NDR pointer and checks if the value read has the expected relative
82 * addressing */
83#define smartcard_ndr_pointer_read(log, s, index, ptr) \
84 smartcard_ndr_pointer_read_((log), (s), (index), (ptr), __FILE__, __func__, __LINE__)
85static BOOL smartcard_ndr_pointer_read_(wLog* log, wStream* s, UINT32* index, UINT32* ptr,
86 const char* file, const char* fkt, size_t line)
87{
88 const UINT32 expect = 0x20000 + (*index) * 4;
89 UINT32 ndrPtr = 0;
90 WINPR_UNUSED(file);
91 if (!s)
92 return FALSE;
93 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
94 return FALSE;
95
96 Stream_Read_UINT32(s, ndrPtr); /* mszGroupsNdrPtr (4 bytes) */
97 if (ptr)
98 *ptr = ndrPtr;
99 if (expect != ndrPtr)
100 {
101 /* Allow NULL pointer if we read the result */
102 if (ptr && (ndrPtr == 0))
103 return TRUE;
104 WLog_Print(log, WLOG_WARN,
105 "[%s:%" PRIuz "] Read context pointer 0x%08" PRIx32 ", expected 0x%08" PRIx32,
106 fkt, line, ndrPtr, expect);
107 return FALSE;
108 }
109
110 (*index) = (*index) + 1;
111 return TRUE;
112}
113
114static LONG smartcard_ndr_read(wLog* log, wStream* s, BYTE** data, size_t min, size_t elementSize,
115 ndr_ptr_t type)
116{
117 size_t len = 0;
118 size_t offset = 0;
119 size_t len2 = 0;
120 void* r = NULL;
121 size_t required = 0;
122
123 *data = NULL;
124 switch (type)
125 {
126 case NDR_PTR_FULL:
127 required = 12;
128 break;
129 case NDR_PTR_SIMPLE:
130 required = 4;
131 break;
132 case NDR_PTR_FIXED:
133 required = min;
134 break;
135 default:
136 return STATUS_INVALID_PARAMETER;
137 }
138
139 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, required))
140 return STATUS_BUFFER_TOO_SMALL;
141
142 switch (type)
143 {
144 case NDR_PTR_FULL:
145 Stream_Read_UINT32(s, len);
146 Stream_Read_UINT32(s, offset);
147 Stream_Read_UINT32(s, len2);
148 if (len != offset + len2)
149 {
150 WLog_Print(log, WLOG_ERROR,
151 "Invalid data when reading full NDR pointer: total=%" PRIu32
152 ", offset=%" PRIu32 ", remaining=%" PRIu32,
153 len, offset, len2);
154 return STATUS_BUFFER_TOO_SMALL;
155 }
156 break;
157 case NDR_PTR_SIMPLE:
158 Stream_Read_UINT32(s, len);
159
160 if ((len != min) && (min > 0))
161 {
162 WLog_Print(log, WLOG_ERROR,
163 "Invalid data when reading simple NDR pointer: total=%" PRIu32
164 ", expected=%" PRIu32,
165 len, min);
166 return STATUS_BUFFER_TOO_SMALL;
167 }
168 break;
169 case NDR_PTR_FIXED:
170 len = (UINT32)min;
171 break;
172 default:
173 return STATUS_INVALID_PARAMETER;
174 }
175
176 if (min > len)
177 {
178 WLog_Print(log, WLOG_ERROR,
179 "Invalid length read from NDR pointer, minimum %" PRIu32 ", got %" PRIu32, min,
180 len);
181 return STATUS_DATA_ERROR;
182 }
183
184 if (len > SIZE_MAX / 2)
185 return STATUS_BUFFER_TOO_SMALL;
186
187 if (!Stream_CheckAndLogRequiredLengthOfSizeWLog(log, s, len, elementSize))
188 return STATUS_BUFFER_TOO_SMALL;
189
190 len *= elementSize;
191
192 /* Ensure proper '\0' termination for all kinds of unicode strings
193 * as we do not know if the data from the wire contains one.
194 */
195 r = calloc(len + sizeof(WCHAR), sizeof(CHAR));
196 if (!r)
197 return SCARD_E_NO_MEMORY;
198 Stream_Read(s, r, len);
199 smartcard_unpack_read_size_align(s, len, 4);
200 *data = r;
201 return STATUS_SUCCESS;
202}
203
204static BOOL smartcard_ndr_pointer_write(wStream* s, UINT32* index, DWORD length)
205{
206 const UINT32 ndrPtr = 0x20000 + (*index) * 4;
207
208 if (!s)
209 return FALSE;
210 if (!Stream_EnsureRemainingCapacity(s, 4))
211 return FALSE;
212
213 if (length > 0)
214 {
215 Stream_Write_UINT32(s, ndrPtr); /* mszGroupsNdrPtr (4 bytes) */
216 (*index) = (*index) + 1;
217 }
218 else
219 Stream_Write_UINT32(s, 0);
220 return TRUE;
221}
222
223static LONG smartcard_ndr_write(wStream* s, const BYTE* data, UINT32 size, UINT32 elementSize,
224 ndr_ptr_t type)
225{
226 const UINT32 offset = 0;
227 const UINT32 len = size;
228 const UINT32 dataLen = size * elementSize;
229 size_t required = 0;
230
231 if (size == 0)
232 return SCARD_S_SUCCESS;
233
234 switch (type)
235 {
236 case NDR_PTR_FULL:
237 required = 12;
238 break;
239 case NDR_PTR_SIMPLE:
240 required = 4;
241 break;
242 case NDR_PTR_FIXED:
243 required = 0;
244 break;
245 default:
246 return SCARD_E_INVALID_PARAMETER;
247 }
248
249 if (!Stream_EnsureRemainingCapacity(s, required + dataLen + 4))
250 return STATUS_BUFFER_TOO_SMALL;
251
252 switch (type)
253 {
254 case NDR_PTR_FULL:
255 Stream_Write_UINT32(s, len);
256 Stream_Write_UINT32(s, offset);
257 Stream_Write_UINT32(s, len);
258 break;
259 case NDR_PTR_SIMPLE:
260 Stream_Write_UINT32(s, len);
261 break;
262 case NDR_PTR_FIXED:
263 break;
264 default:
265 return SCARD_E_INVALID_PARAMETER;
266 }
267
268 if (data)
269 Stream_Write(s, data, dataLen);
270 else
271 Stream_Zero(s, dataLen);
272 return smartcard_pack_write_size_align(s, len, 4);
273}
274
275static LONG smartcard_ndr_write_state(wStream* s, const ReaderState_Return* data, UINT32 size,
276 ndr_ptr_t type)
277{
278 union
279 {
280 const ReaderState_Return* reader;
281 const BYTE* data;
282 } cnv;
283
284 WINPR_ASSERT(data || (size == 0));
285 cnv.reader = data;
286 return smartcard_ndr_write(s, cnv.data, size, sizeof(ReaderState_Return), type);
287}
288
289static LONG smartcard_ndr_read_atrmask(wLog* log, wStream* s, LocateCards_ATRMask** data,
290 size_t min, ndr_ptr_t type)
291{
292 union
293 {
295 BYTE** ppv;
296 } u;
297 u.ppc = data;
298 return smartcard_ndr_read(log, s, u.ppv, min, sizeof(LocateCards_ATRMask), type);
299}
300
301static LONG smartcard_ndr_read_fixed_string_a(wLog* log, wStream* s, CHAR** data, size_t min,
302 ndr_ptr_t type)
303{
304 union
305 {
306 CHAR** ppc;
307 BYTE** ppv;
308 } u;
309 u.ppc = data;
310 return smartcard_ndr_read(log, s, u.ppv, min, sizeof(CHAR), type);
311}
312
313static LONG smartcard_ndr_read_fixed_string_w(wLog* log, wStream* s, WCHAR** data, size_t min,
314 ndr_ptr_t type)
315{
316 union
317 {
318 WCHAR** ppc;
319 BYTE** ppv;
320 } u;
321 u.ppc = data;
322 return smartcard_ndr_read(log, s, u.ppv, min, sizeof(WCHAR), type);
323}
324
325static LONG smartcard_ndr_read_a(wLog* log, wStream* s, CHAR** data, ndr_ptr_t type)
326{
327 union
328 {
329 CHAR** ppc;
330 BYTE** ppv;
331 } u;
332 u.ppc = data;
333 return smartcard_ndr_read(log, s, u.ppv, 0, sizeof(CHAR), type);
334}
335
336static LONG smartcard_ndr_read_w(wLog* log, wStream* s, WCHAR** data, ndr_ptr_t type)
337{
338 union
339 {
340 WCHAR** ppc;
341 BYTE** ppv;
342 } u;
343 u.ppc = data;
344 return smartcard_ndr_read(log, s, u.ppv, 0, sizeof(WCHAR), type);
345}
346
347static LONG smartcard_ndr_read_u(wLog* log, wStream* s, UUID** data)
348{
349 union
350 {
351 UUID** ppc;
352 BYTE** ppv;
353 } u;
354 u.ppc = data;
355 return smartcard_ndr_read(log, s, u.ppv, 1, sizeof(UUID), NDR_PTR_FIXED);
356}
357
358static char* smartcard_convert_string_list(const void* in, size_t bytes, BOOL unicode)
359{
360 size_t length = 0;
361 union
362 {
363 const void* pv;
364 const char* sz;
365 const WCHAR* wz;
366 } string;
367 char* mszA = NULL;
368
369 string.pv = in;
370
371 if (bytes < 1)
372 return NULL;
373
374 if (in == NULL)
375 return NULL;
376
377 if (unicode)
378 {
379 mszA = ConvertMszWCharNToUtf8Alloc(string.wz, bytes / sizeof(WCHAR), &length);
380 if (!mszA)
381 return NULL;
382 }
383 else
384 {
385 mszA = (char*)calloc(bytes, sizeof(char));
386 if (!mszA)
387 return NULL;
388 CopyMemory(mszA, string.sz, bytes - 1);
389 length = bytes;
390 }
391
392 if (length < 1)
393 {
394 free(mszA);
395 return NULL;
396 }
397 for (size_t index = 0; index < length - 1; index++)
398 {
399 if (mszA[index] == '\0')
400 mszA[index] = ',';
401 }
402
403 return mszA;
404}
405
406static char* smartcard_msz_dump_a(const char* msz, size_t len, char* buffer, size_t bufferLen)
407{
408 char* buf = buffer;
409 const char* cur = msz;
410
411 while ((len > 0) && cur && cur[0] != '\0' && (bufferLen > 0))
412 {
413 size_t clen = strnlen(cur, len);
414 int rc = _snprintf(buf, bufferLen, "%s", cur);
415 bufferLen -= (size_t)rc;
416 buf += rc;
417
418 cur += clen;
419 }
420
421 return buffer;
422}
423
424static char* smartcard_msz_dump_w(const WCHAR* msz, size_t len, char* buffer, size_t bufferLen)
425{
426 size_t szlen = 0;
427 if (!msz)
428 return NULL;
429 char* sz = ConvertMszWCharNToUtf8Alloc(msz, len, &szlen);
430 if (!sz)
431 return NULL;
432
433 smartcard_msz_dump_a(sz, szlen, buffer, bufferLen);
434 free(sz);
435 return buffer;
436}
437
438static char* smartcard_array_dump(const void* pd, size_t len, char* buffer, size_t bufferLen)
439{
440 const BYTE* data = pd;
441 int rc = 0;
442 char* start = buffer;
443
444 WINPR_ASSERT(buffer || (bufferLen == 0));
445
446 if (!data && (len > 0))
447 {
448 (void)_snprintf(buffer, bufferLen, "{ NULL [%" PRIuz "] }", len);
449 goto fail;
450 }
451
452 rc = _snprintf(buffer, bufferLen, "{ ");
453 if ((rc < 0) || ((size_t)rc >= bufferLen))
454 goto fail;
455 buffer += rc;
456 bufferLen -= (size_t)rc;
457
458 for (size_t x = 0; x < len; x++)
459 {
460 rc = _snprintf(buffer, bufferLen, "%02X", data[x]);
461 if ((rc < 0) || ((size_t)rc >= bufferLen))
462 goto fail;
463 buffer += rc;
464 bufferLen -= (size_t)rc;
465 }
466
467 rc = _snprintf(buffer, bufferLen, " }");
468 if ((rc < 0) || ((size_t)rc >= bufferLen))
469 goto fail;
470
471fail:
472 return start;
473}
474
475static void smartcard_log_redir_handle(wLog* log, const REDIR_SCARDHANDLE* pHandle)
476{
477 char buffer[128] = { 0 };
478
479 WINPR_ASSERT(pHandle);
480 WLog_Print(log, g_LogLevel, " hContext: %s",
481 smartcard_array_dump(pHandle->pbHandle, pHandle->cbHandle, buffer, sizeof(buffer)));
482}
483
484static void smartcard_log_context(wLog* log, const REDIR_SCARDCONTEXT* phContext)
485{
486 char buffer[128] = { 0 };
487
488 WINPR_ASSERT(phContext);
489 WLog_Print(
490 log, g_LogLevel, "hContext: %s",
491 smartcard_array_dump(phContext->pbContext, phContext->cbContext, buffer, sizeof(buffer)));
492}
493
494static void smartcard_trace_context_and_string_call_a(wLog* log, const char* name,
495 const REDIR_SCARDCONTEXT* phContext,
496 const CHAR* sz)
497{
498 if (!WLog_IsLevelActive(log, g_LogLevel))
499 return;
500
501 WLog_Print(log, g_LogLevel, "%s {", name);
502 smartcard_log_context(log, phContext);
503 WLog_Print(log, g_LogLevel, " sz=%s", sz);
504
505 WLog_Print(log, g_LogLevel, "}");
506}
507
508static void smartcard_trace_context_and_string_call_w(wLog* log, const char* name,
509 const REDIR_SCARDCONTEXT* phContext,
510 const WCHAR* sz)
511{
512 char tmp[1024] = { 0 };
513
514 if (!WLog_IsLevelActive(log, g_LogLevel))
515 return;
516
517 if (sz)
518 (void)ConvertWCharToUtf8(sz, tmp, ARRAYSIZE(tmp));
519
520 WLog_Print(log, g_LogLevel, "%s {", name);
521 smartcard_log_context(log, phContext);
522 WLog_Print(log, g_LogLevel, " sz=%s", tmp);
523 WLog_Print(log, g_LogLevel, "}");
524}
525
526static void smartcard_trace_context_call(wLog* log, const Context_Call* call, const char* name)
527{
528 WINPR_ASSERT(call);
529
530 if (!WLog_IsLevelActive(log, g_LogLevel))
531 return;
532
533 WLog_Print(log, g_LogLevel, "%s_Call {", name);
534 smartcard_log_context(log, &call->handles.hContext);
535
536 WLog_Print(log, g_LogLevel, "}");
537}
538
539static void smartcard_trace_list_reader_groups_call(wLog* log, const ListReaderGroups_Call* call,
540 BOOL unicode)
541{
542 WINPR_ASSERT(call);
543
544 if (!WLog_IsLevelActive(log, g_LogLevel))
545 return;
546
547 WLog_Print(log, g_LogLevel, "ListReaderGroups%S_Call {", unicode ? "W" : "A");
548 smartcard_log_context(log, &call->handles.hContext);
549
550 WLog_Print(log, g_LogLevel, "fmszGroupsIsNULL: %" PRId32 " cchGroups: 0x%08" PRIx32,
551 call->fmszGroupsIsNULL, call->cchGroups);
552 WLog_Print(log, g_LogLevel, "}");
553}
554
555static void dump_reader_states_return(wLog* log, const ReaderState_Return* rgReaderStates,
556 UINT32 cReaders)
557{
558 WINPR_ASSERT(rgReaderStates || (cReaders == 0));
559 for (UINT32 index = 0; index < cReaders; index++)
560 {
561 char buffer[1024] = { 0 };
562
563 const ReaderState_Return* readerState = &rgReaderStates[index];
564 char* szCurrentState = SCardGetReaderStateString(readerState->dwCurrentState);
565 char* szEventState = SCardGetReaderStateString(readerState->dwEventState);
566 WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: dwCurrentState: %s (0x%08" PRIX32 ")", index,
567 szCurrentState, readerState->dwCurrentState);
568 WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: dwEventState: %s (0x%08" PRIX32 ")", index,
569 szEventState, readerState->dwEventState);
570 free(szCurrentState);
571 free(szEventState);
572
573 WLog_Print(
574 log, g_LogLevel, "\t[%" PRIu32 "]: cbAttr: %" PRIu32 " { %s }", index,
575 readerState->cbAtr,
576 smartcard_array_dump(readerState->rgbAtr, readerState->cbAtr, buffer, sizeof(buffer)));
577 }
578}
579
580static void dump_reader_states_a(wLog* log, const SCARD_READERSTATEA* rgReaderStates,
581 UINT32 cReaders)
582{
583 WINPR_ASSERT(rgReaderStates || (cReaders == 0));
584 for (UINT32 index = 0; index < cReaders; index++)
585 {
586 char buffer[1024] = { 0 };
587
588 const SCARD_READERSTATEA* readerState = &rgReaderStates[index];
589
590 WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: szReader: %s cbAtr: %" PRIu32 "", index,
591 readerState->szReader, readerState->cbAtr);
592 char* szCurrentState = SCardGetReaderStateString(readerState->dwCurrentState);
593 char* szEventState = SCardGetReaderStateString(readerState->dwEventState);
594 WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: dwCurrentState: %s (0x%08" PRIX32 ")", index,
595 szCurrentState, readerState->dwCurrentState);
596 WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: dwEventState: %s (0x%08" PRIX32 ")", index,
597 szEventState, readerState->dwEventState);
598 free(szCurrentState);
599 free(szEventState);
600
601 WLog_Print(
602 log, g_LogLevel, "\t[%" PRIu32 "]: cbAttr: %" PRIu32 " { %s }", index,
603 readerState->cbAtr,
604 smartcard_array_dump(readerState->rgbAtr, readerState->cbAtr, buffer, sizeof(buffer)));
605 }
606}
607
608static void dump_reader_states_w(wLog* log, const SCARD_READERSTATEW* rgReaderStates,
609 UINT32 cReaders)
610{
611 WINPR_ASSERT(rgReaderStates || (cReaders == 0));
612 for (UINT32 index = 0; index < cReaders; index++)
613 {
614 char buffer[1024] = { 0 };
615
616 const SCARD_READERSTATEW* readerState = &rgReaderStates[index];
617 (void)ConvertWCharToUtf8(readerState->szReader, buffer, sizeof(buffer));
618 WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: szReader: %s cbAtr: %" PRIu32 "", index,
619 buffer, readerState->cbAtr);
620 char* szCurrentState = SCardGetReaderStateString(readerState->dwCurrentState);
621 char* szEventState = SCardGetReaderStateString(readerState->dwEventState);
622 WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: dwCurrentState: %s (0x%08" PRIX32 ")", index,
623 szCurrentState, readerState->dwCurrentState);
624 WLog_Print(log, g_LogLevel, "\t[%" PRIu32 "]: dwEventState: %s (0x%08" PRIX32 ")", index,
625 szEventState, readerState->dwEventState);
626 free(szCurrentState);
627 free(szEventState);
628
629 WLog_Print(
630 log, g_LogLevel, "\t[%" PRIu32 "]: cbAttr: %" PRIu32 " { %s }", index,
631 readerState->cbAtr,
632 smartcard_array_dump(readerState->rgbAtr, readerState->cbAtr, buffer, sizeof(buffer)));
633 }
634}
635
636static void smartcard_trace_get_status_change_w_call(wLog* log, const GetStatusChangeW_Call* call)
637{
638 WINPR_ASSERT(call);
639
640 if (!WLog_IsLevelActive(log, g_LogLevel))
641 return;
642
643 WLog_Print(log, g_LogLevel, "GetStatusChangeW_Call {");
644 smartcard_log_context(log, &call->handles.hContext);
645
646 WLog_Print(log, g_LogLevel, "dwTimeOut: 0x%08" PRIX32 " cReaders: %" PRIu32 "", call->dwTimeOut,
647 call->cReaders);
648
649 dump_reader_states_w(log, call->rgReaderStates, call->cReaders);
650
651 WLog_Print(log, g_LogLevel, "}");
652}
653
654static void smartcard_trace_list_reader_groups_return(wLog* log, const ListReaderGroups_Return* ret,
655 BOOL unicode)
656{
657 WINPR_ASSERT(ret);
658
659 if (!WLog_IsLevelActive(log, g_LogLevel))
660 return;
661
662 char* mszA = smartcard_convert_string_list(ret->msz, ret->cBytes, unicode);
663
664 WLog_Print(log, g_LogLevel, "ListReaderGroups%s_Return {", unicode ? "W" : "A");
665 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIx32 ")",
666 SCardGetErrorString(ret->ReturnCode), ret->ReturnCode);
667 WLog_Print(log, g_LogLevel, " cBytes: %" PRIu32 " msz: %s", ret->cBytes, mszA);
668 WLog_Print(log, g_LogLevel, "}");
669 free(mszA);
670}
671
672static void smartcard_trace_list_readers_call(wLog* log, const ListReaders_Call* call, BOOL unicode)
673{
674 WINPR_ASSERT(call);
675
676 if (!WLog_IsLevelActive(log, g_LogLevel))
677 return;
678
679 char* mszGroupsA = smartcard_convert_string_list(call->mszGroups, call->cBytes, unicode);
680
681 WLog_Print(log, g_LogLevel, "ListReaders%s_Call {", unicode ? "W" : "A");
682 smartcard_log_context(log, &call->handles.hContext);
683
684 WLog_Print(log, g_LogLevel,
685 "cBytes: %" PRIu32 " mszGroups: %s fmszReadersIsNULL: %" PRId32
686 " cchReaders: 0x%08" PRIX32 "",
687 call->cBytes, mszGroupsA, call->fmszReadersIsNULL, call->cchReaders);
688 WLog_Print(log, g_LogLevel, "}");
689
690 free(mszGroupsA);
691}
692
693static void smartcard_trace_locate_cards_by_atr_a_call(wLog* log,
694 const LocateCardsByATRA_Call* call)
695{
696 WINPR_ASSERT(call);
697
698 if (!WLog_IsLevelActive(log, g_LogLevel))
699 return;
700
701 WLog_Print(log, g_LogLevel, "LocateCardsByATRA_Call {");
702 smartcard_log_context(log, &call->handles.hContext);
703
704 dump_reader_states_a(log, call->rgReaderStates, call->cReaders);
705
706 WLog_Print(log, g_LogLevel, "}");
707}
708
709static void smartcard_trace_locate_cards_a_call(wLog* log, const LocateCardsA_Call* call)
710{
711 char buffer[8192] = { 0 };
712
713 WINPR_ASSERT(call);
714
715 if (!WLog_IsLevelActive(log, g_LogLevel))
716 return;
717
718 WLog_Print(log, g_LogLevel, "LocateCardsA_Call {");
719 smartcard_log_context(log, &call->handles.hContext);
720 WLog_Print(log, g_LogLevel, " cBytes=%" PRId32, call->cBytes);
721 WLog_Print(log, g_LogLevel, " mszCards=%s",
722 smartcard_msz_dump_a(call->mszCards, call->cBytes, buffer, sizeof(buffer)));
723 WLog_Print(log, g_LogLevel, " cReaders=%" PRId32, call->cReaders);
724 dump_reader_states_a(log, call->rgReaderStates, call->cReaders);
725
726 WLog_Print(log, g_LogLevel, "}");
727}
728
729static void smartcard_trace_locate_cards_return(wLog* log, const LocateCards_Return* ret)
730{
731 WINPR_ASSERT(ret);
732
733 if (!WLog_IsLevelActive(log, g_LogLevel))
734 return;
735
736 WLog_Print(log, g_LogLevel, "LocateCards_Return {");
737 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
738 SCardGetErrorString(ret->ReturnCode), ret->ReturnCode);
739
740 if (ret->ReturnCode == SCARD_S_SUCCESS)
741 {
742 WLog_Print(log, g_LogLevel, " cReaders=%" PRId32, ret->cReaders);
743 }
744 WLog_Print(log, g_LogLevel, "}");
745}
746
747static void smartcard_trace_get_reader_icon_return(wLog* log, const GetReaderIcon_Return* ret)
748{
749 WINPR_ASSERT(ret);
750
751 if (!WLog_IsLevelActive(log, g_LogLevel))
752 return;
753
754 WLog_Print(log, g_LogLevel, "GetReaderIcon_Return {");
755 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
756 SCardGetErrorString(ret->ReturnCode), ret->ReturnCode);
757
758 if (ret->ReturnCode == SCARD_S_SUCCESS)
759 {
760 WLog_Print(log, g_LogLevel, " cbDataLen=%" PRId32, ret->cbDataLen);
761 }
762 WLog_Print(log, g_LogLevel, "}");
763}
764
765static void smartcard_trace_get_transmit_count_return(wLog* log, const GetTransmitCount_Return* ret)
766{
767 WINPR_ASSERT(ret);
768
769 if (!WLog_IsLevelActive(log, g_LogLevel))
770 return;
771
772 WLog_Print(log, g_LogLevel, "GetTransmitCount_Return {");
773 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
774 SCardGetErrorString(ret->ReturnCode), ret->ReturnCode);
775
776 WLog_Print(log, g_LogLevel, " cTransmitCount=%" PRIu32, ret->cTransmitCount);
777 WLog_Print(log, g_LogLevel, "}");
778}
779
780static void smartcard_trace_read_cache_return(wLog* log, const ReadCache_Return* ret)
781{
782 WINPR_ASSERT(ret);
783
784 if (!WLog_IsLevelActive(log, g_LogLevel))
785 return;
786
787 WLog_Print(log, g_LogLevel, "ReadCache_Return {");
788 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
789 SCardGetErrorString(ret->ReturnCode), ret->ReturnCode);
790
791 if (ret->ReturnCode == SCARD_S_SUCCESS)
792 {
793 char buffer[1024] = { 0 };
794 WLog_Print(log, g_LogLevel, " cbDataLen=%" PRId32, ret->cbDataLen);
795 WLog_Print(log, g_LogLevel, " cbData: %s",
796 smartcard_array_dump(ret->pbData, ret->cbDataLen, buffer, sizeof(buffer)));
797 }
798 WLog_Print(log, g_LogLevel, "}");
799}
800
801static void smartcard_trace_locate_cards_w_call(wLog* log, const LocateCardsW_Call* call)
802{
803 WINPR_ASSERT(call);
804 char buffer[8192] = { 0 };
805
806 if (!WLog_IsLevelActive(log, g_LogLevel))
807 return;
808
809 WLog_Print(log, g_LogLevel, "LocateCardsW_Call {");
810 smartcard_log_context(log, &call->handles.hContext);
811 WLog_Print(log, g_LogLevel, " cBytes=%" PRId32, call->cBytes);
812 WLog_Print(log, g_LogLevel, " sz2=%s",
813 smartcard_msz_dump_w(call->mszCards, call->cBytes, buffer, sizeof(buffer)));
814 WLog_Print(log, g_LogLevel, " cReaders=%" PRId32, call->cReaders);
815 dump_reader_states_w(log, call->rgReaderStates, call->cReaders);
816 WLog_Print(log, g_LogLevel, "}");
817}
818
819static void smartcard_trace_list_readers_return(wLog* log, const ListReaders_Return* ret,
820 BOOL unicode)
821{
822 WINPR_ASSERT(ret);
823
824 if (!WLog_IsLevelActive(log, g_LogLevel))
825 return;
826
827 WLog_Print(log, g_LogLevel, "ListReaders%s_Return {", unicode ? "W" : "A");
828 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
829 SCardGetErrorString(ret->ReturnCode), ret->ReturnCode);
830
831 if (ret->ReturnCode != SCARD_S_SUCCESS)
832 {
833 WLog_Print(log, g_LogLevel, "}");
834 return;
835 }
836
837 char* mszA = smartcard_convert_string_list(ret->msz, ret->cBytes, unicode);
838
839 WLog_Print(log, g_LogLevel, " cBytes: %" PRIu32 " msz: %s", ret->cBytes, mszA);
840 WLog_Print(log, g_LogLevel, "}");
841 free(mszA);
842}
843
844static void smartcard_trace_get_status_change_return(wLog* log, const GetStatusChange_Return* ret,
845 BOOL unicode)
846{
847 WINPR_ASSERT(ret);
848
849 if (!WLog_IsLevelActive(log, g_LogLevel))
850 return;
851
852 WLog_Print(log, g_LogLevel, "GetStatusChange%s_Return {", unicode ? "W" : "A");
853 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
854 SCardGetErrorString(ret->ReturnCode), ret->ReturnCode);
855 WLog_Print(log, g_LogLevel, " cReaders: %" PRIu32 "", ret->cReaders);
856
857 dump_reader_states_return(log, ret->rgReaderStates, ret->cReaders);
858
859 if (!ret->rgReaderStates && (ret->cReaders > 0))
860 {
861 WLog_Print(log, g_LogLevel, " [INVALID STATE] rgReaderStates=NULL, cReaders=%" PRIu32,
862 ret->cReaders);
863 }
864 else if (ret->ReturnCode != SCARD_S_SUCCESS)
865 {
866 WLog_Print(log, g_LogLevel, " [INVALID RETURN] rgReaderStates, cReaders=%" PRIu32,
867 ret->cReaders);
868 }
869 else
870 {
871 for (UINT32 index = 0; index < ret->cReaders; index++)
872 {
873 char buffer[1024] = { 0 };
874 const ReaderState_Return* rgReaderState = &(ret->rgReaderStates[index]);
875 char* szCurrentState = SCardGetReaderStateString(rgReaderState->dwCurrentState);
876 char* szEventState = SCardGetReaderStateString(rgReaderState->dwEventState);
877 WLog_Print(log, g_LogLevel, " [%" PRIu32 "]: dwCurrentState: %s (0x%08" PRIX32 ")",
878 index, szCurrentState, rgReaderState->dwCurrentState);
879 WLog_Print(log, g_LogLevel, " [%" PRIu32 "]: dwEventState: %s (0x%08" PRIX32 ")",
880 index, szEventState, rgReaderState->dwEventState);
881 WLog_Print(log, g_LogLevel, " [%" PRIu32 "]: cbAtr: %" PRIu32 " rgbAtr: %s", index,
882 rgReaderState->cbAtr,
883 smartcard_array_dump(rgReaderState->rgbAtr, rgReaderState->cbAtr, buffer,
884 sizeof(buffer)));
885 free(szCurrentState);
886 free(szEventState);
887 }
888 }
889
890 WLog_Print(log, g_LogLevel, "}");
891}
892
893static void smartcard_trace_context_and_two_strings_a_call(wLog* log,
894 const ContextAndTwoStringA_Call* call)
895{
896 WINPR_ASSERT(call);
897
898 if (!WLog_IsLevelActive(log, g_LogLevel))
899 return;
900
901 WLog_Print(log, g_LogLevel, "ContextAndTwoStringW_Call {");
902 smartcard_log_context(log, &call->handles.hContext);
903 WLog_Print(log, g_LogLevel, " sz1=%s", call->sz1);
904 WLog_Print(log, g_LogLevel, " sz2=%s", call->sz2);
905 WLog_Print(log, g_LogLevel, "}");
906}
907
908static void smartcard_trace_context_and_two_strings_w_call(wLog* log,
909 const ContextAndTwoStringW_Call* call)
910{
911 WINPR_ASSERT(call);
912 char sz1[1024] = { 0 };
913 char sz2[1024] = { 0 };
914
915 if (!WLog_IsLevelActive(log, g_LogLevel))
916 return;
917 if (call->sz1)
918 (void)ConvertWCharToUtf8(call->sz1, sz1, ARRAYSIZE(sz1));
919 if (call->sz2)
920 (void)ConvertWCharToUtf8(call->sz2, sz2, ARRAYSIZE(sz2));
921
922 WLog_Print(log, g_LogLevel, "ContextAndTwoStringW_Call {");
923 smartcard_log_context(log, &call->handles.hContext);
924 WLog_Print(log, g_LogLevel, " sz1=%s", sz1);
925 WLog_Print(log, g_LogLevel, " sz2=%s", sz2);
926 WLog_Print(log, g_LogLevel, "}");
927}
928
929static void smartcard_trace_get_transmit_count_call(wLog* log, const GetTransmitCount_Call* call)
930{
931 WINPR_ASSERT(call);
932
933 if (!WLog_IsLevelActive(log, g_LogLevel))
934 return;
935
936 WLog_Print(log, g_LogLevel, "GetTransmitCount_Call {");
937 smartcard_log_context(log, &call->handles.hContext);
938 smartcard_log_redir_handle(log, &call->handles.hCard);
939
940 WLog_Print(log, g_LogLevel, "}");
941}
942
943static void smartcard_trace_write_cache_a_call(wLog* log, const WriteCacheA_Call* call)
944{
945 WINPR_ASSERT(call);
946 char buffer[1024] = { 0 };
947
948 if (!WLog_IsLevelActive(log, g_LogLevel))
949 return;
950
951 WLog_Print(log, g_LogLevel, "WriteCacheA_Call {");
952
953 WLog_Print(log, g_LogLevel, " szLookupName=%s", call->szLookupName);
954
955 smartcard_log_context(log, &call->Common.handles.hContext);
956 WLog_Print(
957 log, g_LogLevel, "..CardIdentifier=%s",
958 smartcard_array_dump(call->Common.CardIdentifier, sizeof(UUID), buffer, sizeof(buffer)));
959 WLog_Print(log, g_LogLevel, " FreshnessCounter=%" PRIu32, call->Common.FreshnessCounter);
960 WLog_Print(log, g_LogLevel, " cbDataLen=%" PRIu32, call->Common.cbDataLen);
961 WLog_Print(
962 log, g_LogLevel, " pbData=%s",
963 smartcard_array_dump(call->Common.pbData, call->Common.cbDataLen, buffer, sizeof(buffer)));
964 WLog_Print(log, g_LogLevel, "}");
965}
966
967static void smartcard_trace_write_cache_w_call(wLog* log, const WriteCacheW_Call* call)
968{
969 WINPR_ASSERT(call);
970 char tmp[1024] = { 0 };
971 char buffer[1024] = { 0 };
972
973 if (!WLog_IsLevelActive(log, g_LogLevel))
974 return;
975
976 WLog_Print(log, g_LogLevel, "WriteCacheW_Call {");
977
978 if (call->szLookupName)
979 (void)ConvertWCharToUtf8(call->szLookupName, tmp, ARRAYSIZE(tmp));
980 WLog_Print(log, g_LogLevel, " szLookupName=%s", tmp);
981
982 smartcard_log_context(log, &call->Common.handles.hContext);
983 WLog_Print(
984 log, g_LogLevel, "..CardIdentifier=%s",
985 smartcard_array_dump(call->Common.CardIdentifier, sizeof(UUID), buffer, sizeof(buffer)));
986 WLog_Print(log, g_LogLevel, " FreshnessCounter=%" PRIu32, call->Common.FreshnessCounter);
987 WLog_Print(log, g_LogLevel, " cbDataLen=%" PRIu32, call->Common.cbDataLen);
988 WLog_Print(
989 log, g_LogLevel, " pbData=%s",
990 smartcard_array_dump(call->Common.pbData, call->Common.cbDataLen, buffer, sizeof(buffer)));
991 WLog_Print(log, g_LogLevel, "}");
992}
993
994static void smartcard_trace_read_cache_a_call(wLog* log, const ReadCacheA_Call* call)
995{
996 WINPR_ASSERT(call);
997 char buffer[1024] = { 0 };
998
999 if (!WLog_IsLevelActive(log, g_LogLevel))
1000 return;
1001
1002 WLog_Print(log, g_LogLevel, "ReadCacheA_Call {");
1003
1004 WLog_Print(log, g_LogLevel, " szLookupName=%s", call->szLookupName);
1005 smartcard_log_context(log, &call->Common.handles.hContext);
1006 WLog_Print(
1007 log, g_LogLevel, "..CardIdentifier=%s",
1008 smartcard_array_dump(call->Common.CardIdentifier, sizeof(UUID), buffer, sizeof(buffer)));
1009 WLog_Print(log, g_LogLevel, " FreshnessCounter=%" PRIu32, call->Common.FreshnessCounter);
1010 WLog_Print(log, g_LogLevel, " fPbDataIsNULL=%" PRId32, call->Common.fPbDataIsNULL);
1011 WLog_Print(log, g_LogLevel, " cbDataLen=%" PRIu32, call->Common.cbDataLen);
1012
1013 WLog_Print(log, g_LogLevel, "}");
1014}
1015
1016static void smartcard_trace_read_cache_w_call(wLog* log, const ReadCacheW_Call* call)
1017{
1018 WINPR_ASSERT(call);
1019 char tmp[1024] = { 0 };
1020 char buffer[1024] = { 0 };
1021
1022 if (!WLog_IsLevelActive(log, g_LogLevel))
1023 return;
1024
1025 WLog_Print(log, g_LogLevel, "ReadCacheW_Call {");
1026 if (call->szLookupName)
1027 (void)ConvertWCharToUtf8(call->szLookupName, tmp, ARRAYSIZE(tmp));
1028 WLog_Print(log, g_LogLevel, " szLookupName=%s", tmp);
1029
1030 smartcard_log_context(log, &call->Common.handles.hContext);
1031 WLog_Print(
1032 log, g_LogLevel, "..CardIdentifier=%s",
1033 smartcard_array_dump(call->Common.CardIdentifier, sizeof(UUID), buffer, sizeof(buffer)));
1034 WLog_Print(log, g_LogLevel, " FreshnessCounter=%" PRIu32, call->Common.FreshnessCounter);
1035 WLog_Print(log, g_LogLevel, " fPbDataIsNULL=%" PRId32, call->Common.fPbDataIsNULL);
1036 WLog_Print(log, g_LogLevel, " cbDataLen=%" PRIu32, call->Common.cbDataLen);
1037
1038 WLog_Print(log, g_LogLevel, "}");
1039}
1040
1041static void smartcard_trace_transmit_call(wLog* log, const Transmit_Call* call)
1042{
1043 WINPR_ASSERT(call);
1044 UINT32 cbExtraBytes = 0;
1045 BYTE* pbExtraBytes = NULL;
1046
1047 if (!WLog_IsLevelActive(log, g_LogLevel))
1048 return;
1049
1050 WLog_Print(log, g_LogLevel, "Transmit_Call {");
1051 smartcard_log_context(log, &call->handles.hContext);
1052 smartcard_log_redir_handle(log, &call->handles.hCard);
1053
1054 if (call->pioSendPci)
1055 {
1056 cbExtraBytes = (UINT32)(call->pioSendPci->cbPciLength - sizeof(SCARD_IO_REQUEST));
1057 pbExtraBytes = &((BYTE*)call->pioSendPci)[sizeof(SCARD_IO_REQUEST)];
1058 WLog_Print(log, g_LogLevel, "pioSendPci: dwProtocol: %" PRIu32 " cbExtraBytes: %" PRIu32 "",
1059 call->pioSendPci->dwProtocol, cbExtraBytes);
1060
1061 if (cbExtraBytes)
1062 {
1063 char buffer[1024] = { 0 };
1064 WLog_Print(log, g_LogLevel, "pbExtraBytes: %s",
1065 smartcard_array_dump(pbExtraBytes, cbExtraBytes, buffer, sizeof(buffer)));
1066 }
1067 }
1068 else
1069 {
1070 WLog_Print(log, g_LogLevel, "pioSendPci: null");
1071 }
1072
1073 WLog_Print(log, g_LogLevel, "cbSendLength: %" PRIu32 "", call->cbSendLength);
1074
1075 if (call->pbSendBuffer)
1076 {
1077 char buffer[1024] = { 0 };
1078 WLog_Print(
1079 log, g_LogLevel, "pbSendBuffer: %s",
1080 smartcard_array_dump(call->pbSendBuffer, call->cbSendLength, buffer, sizeof(buffer)));
1081 }
1082 else
1083 {
1084 WLog_Print(log, g_LogLevel, "pbSendBuffer: null");
1085 }
1086
1087 if (call->pioRecvPci)
1088 {
1089 cbExtraBytes = (UINT32)(call->pioRecvPci->cbPciLength - sizeof(SCARD_IO_REQUEST));
1090 pbExtraBytes = &((BYTE*)call->pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
1091 WLog_Print(log, g_LogLevel, "pioRecvPci: dwProtocol: %" PRIu32 " cbExtraBytes: %" PRIu32 "",
1092 call->pioRecvPci->dwProtocol, cbExtraBytes);
1093
1094 if (cbExtraBytes)
1095 {
1096 char buffer[1024] = { 0 };
1097 WLog_Print(log, g_LogLevel, "pbExtraBytes: %s",
1098 smartcard_array_dump(pbExtraBytes, cbExtraBytes, buffer, sizeof(buffer)));
1099 }
1100 }
1101 else
1102 {
1103 WLog_Print(log, g_LogLevel, "pioRecvPci: null");
1104 }
1105
1106 WLog_Print(log, g_LogLevel, "fpbRecvBufferIsNULL: %" PRId32 " cbRecvLength: %" PRIu32 "",
1107 call->fpbRecvBufferIsNULL, call->cbRecvLength);
1108 WLog_Print(log, g_LogLevel, "}");
1109}
1110
1111static void smartcard_trace_locate_cards_by_atr_w_call(wLog* log,
1112 const LocateCardsByATRW_Call* call)
1113{
1114 WINPR_ASSERT(call);
1115
1116 if (!WLog_IsLevelActive(log, g_LogLevel))
1117 return;
1118
1119 WLog_Print(log, g_LogLevel, "LocateCardsByATRW_Call {");
1120 smartcard_log_context(log, &call->handles.hContext);
1121
1122 dump_reader_states_w(log, call->rgReaderStates, call->cReaders);
1123
1124 WLog_Print(log, g_LogLevel, "}");
1125}
1126
1127static void smartcard_trace_transmit_return(wLog* log, const Transmit_Return* ret)
1128{
1129 WINPR_ASSERT(ret);
1130 UINT32 cbExtraBytes = 0;
1131 BYTE* pbExtraBytes = NULL;
1132
1133 if (!WLog_IsLevelActive(log, g_LogLevel))
1134 return;
1135
1136 WLog_Print(log, g_LogLevel, "Transmit_Return {");
1137 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
1138 SCardGetErrorString(ret->ReturnCode), ret->ReturnCode);
1139
1140 if (ret->pioRecvPci)
1141 {
1142 cbExtraBytes = (UINT32)(ret->pioRecvPci->cbPciLength - sizeof(SCARD_IO_REQUEST));
1143 pbExtraBytes = &((BYTE*)ret->pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
1144 WLog_Print(log, g_LogLevel,
1145 " pioRecvPci: dwProtocol: %" PRIu32 " cbExtraBytes: %" PRIu32 "",
1146 ret->pioRecvPci->dwProtocol, cbExtraBytes);
1147
1148 if (cbExtraBytes)
1149 {
1150 char buffer[1024] = { 0 };
1151 WLog_Print(log, g_LogLevel, " pbExtraBytes: %s",
1152 smartcard_array_dump(pbExtraBytes, cbExtraBytes, buffer, sizeof(buffer)));
1153 }
1154 }
1155 else
1156 {
1157 WLog_Print(log, g_LogLevel, " pioRecvPci: null");
1158 }
1159
1160 WLog_Print(log, g_LogLevel, " cbRecvLength: %" PRIu32 "", ret->cbRecvLength);
1161
1162 if (ret->pbRecvBuffer)
1163 {
1164 char buffer[1024] = { 0 };
1165 WLog_Print(
1166 log, g_LogLevel, " pbRecvBuffer: %s",
1167 smartcard_array_dump(ret->pbRecvBuffer, ret->cbRecvLength, buffer, sizeof(buffer)));
1168 }
1169 else
1170 {
1171 WLog_Print(log, g_LogLevel, " pbRecvBuffer: null");
1172 }
1173
1174 WLog_Print(log, g_LogLevel, "}");
1175}
1176
1177static void smartcard_trace_control_return(wLog* log, const Control_Return* ret)
1178{
1179 WINPR_ASSERT(ret);
1180
1181 if (!WLog_IsLevelActive(log, g_LogLevel))
1182 return;
1183
1184 WLog_Print(log, g_LogLevel, "Control_Return {");
1185 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
1186 SCardGetErrorString(ret->ReturnCode), ret->ReturnCode);
1187 WLog_Print(log, g_LogLevel, " cbOutBufferSize: %" PRIu32 "", ret->cbOutBufferSize);
1188
1189 if (ret->pvOutBuffer)
1190 {
1191 char buffer[1024] = { 0 };
1192 WLog_Print(
1193 log, g_LogLevel, "pvOutBuffer: %s",
1194 smartcard_array_dump(ret->pvOutBuffer, ret->cbOutBufferSize, buffer, sizeof(buffer)));
1195 }
1196 else
1197 {
1198 WLog_Print(log, g_LogLevel, "pvOutBuffer: null");
1199 }
1200
1201 WLog_Print(log, g_LogLevel, "}");
1202}
1203
1204static void smartcard_trace_control_call(wLog* log, const Control_Call* call)
1205{
1206 WINPR_ASSERT(call);
1207
1208 if (!WLog_IsLevelActive(log, g_LogLevel))
1209 return;
1210
1211 WLog_Print(log, g_LogLevel, "Control_Call {");
1212 smartcard_log_context(log, &call->handles.hContext);
1213 smartcard_log_redir_handle(log, &call->handles.hCard);
1214
1215 WLog_Print(log, g_LogLevel,
1216 "dwControlCode: 0x%08" PRIX32 " cbInBufferSize: %" PRIu32
1217 " fpvOutBufferIsNULL: %" PRId32 " cbOutBufferSize: %" PRIu32 "",
1218 call->dwControlCode, call->cbInBufferSize, call->fpvOutBufferIsNULL,
1219 call->cbOutBufferSize);
1220
1221 if (call->pvInBuffer)
1222 {
1223 char buffer[1024] = { 0 };
1224 WLog_Print(
1225 log, WLOG_DEBUG, "pbInBuffer: %s",
1226 smartcard_array_dump(call->pvInBuffer, call->cbInBufferSize, buffer, sizeof(buffer)));
1227 }
1228 else
1229 {
1230 WLog_Print(log, g_LogLevel, "pvInBuffer: null");
1231 }
1232
1233 WLog_Print(log, g_LogLevel, "}");
1234}
1235
1236static void smartcard_trace_set_attrib_call(wLog* log, const SetAttrib_Call* call)
1237{
1238 WINPR_ASSERT(call);
1239 char buffer[8192] = { 0 };
1240
1241 if (!WLog_IsLevelActive(log, g_LogLevel))
1242 return;
1243
1244 WLog_Print(log, g_LogLevel, "GetAttrib_Call {");
1245 smartcard_log_context(log, &call->handles.hContext);
1246 smartcard_log_redir_handle(log, &call->handles.hCard);
1247 WLog_Print(log, g_LogLevel, "dwAttrId: 0x%08" PRIX32, call->dwAttrId);
1248 WLog_Print(log, g_LogLevel, "cbAttrLen: 0x%08" PRId32, call->cbAttrLen);
1249 WLog_Print(log, g_LogLevel, "pbAttr: %s",
1250 smartcard_array_dump(call->pbAttr, call->cbAttrLen, buffer, sizeof(buffer)));
1251 WLog_Print(log, g_LogLevel, "}");
1252}
1253
1254static void smartcard_trace_get_attrib_return(wLog* log, const GetAttrib_Return* ret,
1255 DWORD dwAttrId)
1256{
1257 WINPR_ASSERT(ret);
1258 char buffer[1024] = { 0 };
1259
1260 if (!WLog_IsLevelActive(log, g_LogLevel))
1261 return;
1262
1263 WLog_Print(log, g_LogLevel, "GetAttrib_Return {");
1264 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
1265 SCardGetErrorString(ret->ReturnCode), ret->ReturnCode);
1266 WLog_Print(log, g_LogLevel, " dwAttrId: %s (0x%08" PRIX32 ") cbAttrLen: 0x%08" PRIX32 "",
1267 SCardGetAttributeString(dwAttrId), dwAttrId, ret->cbAttrLen);
1268 WLog_Print(log, g_LogLevel, " %s",
1269 smartcard_array_dump(ret->pbAttr, ret->cbAttrLen, buffer, sizeof(buffer)));
1270
1271 WLog_Print(log, g_LogLevel, "}");
1272}
1273
1274static void smartcard_trace_get_attrib_call(wLog* log, const GetAttrib_Call* call)
1275{
1276 WINPR_ASSERT(call);
1277
1278 if (!WLog_IsLevelActive(log, g_LogLevel))
1279 return;
1280
1281 WLog_Print(log, g_LogLevel, "GetAttrib_Call {");
1282 smartcard_log_context(log, &call->handles.hContext);
1283 smartcard_log_redir_handle(log, &call->handles.hCard);
1284
1285 WLog_Print(log, g_LogLevel,
1286 "dwAttrId: %s (0x%08" PRIX32 ") fpbAttrIsNULL: %" PRId32 " cbAttrLen: 0x%08" PRIX32
1287 "",
1288 SCardGetAttributeString(call->dwAttrId), call->dwAttrId, call->fpbAttrIsNULL,
1289 call->cbAttrLen);
1290 WLog_Print(log, g_LogLevel, "}");
1291}
1292
1293static void smartcard_trace_status_call(wLog* log, const Status_Call* call, BOOL unicode)
1294{
1295 WINPR_ASSERT(call);
1296
1297 if (!WLog_IsLevelActive(log, g_LogLevel))
1298 return;
1299
1300 WLog_Print(log, g_LogLevel, "Status%s_Call {", unicode ? "W" : "A");
1301 smartcard_log_context(log, &call->handles.hContext);
1302 smartcard_log_redir_handle(log, &call->handles.hCard);
1303
1304 WLog_Print(log, g_LogLevel,
1305 "fmszReaderNamesIsNULL: %" PRId32 " cchReaderLen: %" PRIu32 " cbAtrLen: %" PRIu32 "",
1306 call->fmszReaderNamesIsNULL, call->cchReaderLen, call->cbAtrLen);
1307 WLog_Print(log, g_LogLevel, "}");
1308}
1309
1310static void smartcard_trace_status_return(wLog* log, const Status_Return* ret, BOOL unicode)
1311{
1312 WINPR_ASSERT(ret);
1313 char* mszReaderNamesA = NULL;
1314 char buffer[1024] = { 0 };
1315 DWORD cBytes = 0;
1316
1317 if (!WLog_IsLevelActive(log, g_LogLevel))
1318 return;
1319 cBytes = ret->cBytes;
1320 if (ret->ReturnCode != SCARD_S_SUCCESS)
1321 cBytes = 0;
1322 if (cBytes == SCARD_AUTOALLOCATE)
1323 cBytes = 0;
1324 mszReaderNamesA = smartcard_convert_string_list(ret->mszReaderNames, cBytes, unicode);
1325
1326 WLog_Print(log, g_LogLevel, "Status%s_Return {", unicode ? "W" : "A");
1327 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
1328 SCardGetErrorString(ret->ReturnCode), ret->ReturnCode);
1329 WLog_Print(log, g_LogLevel, " dwState: %s (0x%08" PRIX32 ") dwProtocol: %s (0x%08" PRIX32 ")",
1330 SCardGetCardStateString(ret->dwState), ret->dwState,
1331 SCardGetProtocolString(ret->dwProtocol), ret->dwProtocol);
1332
1333 WLog_Print(log, g_LogLevel, " cBytes: %" PRIu32 " mszReaderNames: %s", ret->cBytes,
1334 mszReaderNamesA);
1335
1336 WLog_Print(log, g_LogLevel, " cbAtrLen: %" PRIu32 " pbAtr: %s", ret->cbAtrLen,
1337 smartcard_array_dump(ret->pbAtr, ret->cbAtrLen, buffer, sizeof(buffer)));
1338 WLog_Print(log, g_LogLevel, "}");
1339 free(mszReaderNamesA);
1340}
1341
1342static void smartcard_trace_state_return(wLog* log, const State_Return* ret)
1343{
1344 WINPR_ASSERT(ret);
1345 char buffer[1024] = { 0 };
1346 char* state = NULL;
1347
1348 if (!WLog_IsLevelActive(log, g_LogLevel))
1349 return;
1350
1351 state = SCardGetReaderStateString(ret->dwState);
1352 WLog_Print(log, g_LogLevel, "Reconnect_Return {");
1353 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
1354 SCardGetErrorString(ret->ReturnCode), ret->ReturnCode);
1355 WLog_Print(log, g_LogLevel, " dwState: %s (0x%08" PRIX32 ")", state, ret->dwState);
1356 WLog_Print(log, g_LogLevel, " dwProtocol: %s (0x%08" PRIX32 ")",
1357 SCardGetProtocolString(ret->dwProtocol), ret->dwProtocol);
1358 WLog_Print(log, g_LogLevel, " cbAtrLen: (0x%08" PRIX32 ")", ret->cbAtrLen);
1359 WLog_Print(log, g_LogLevel, " rgAtr: %s",
1360 smartcard_array_dump(ret->rgAtr, sizeof(ret->rgAtr), buffer, sizeof(buffer)));
1361 WLog_Print(log, g_LogLevel, "}");
1362 free(state);
1363}
1364
1365static void smartcard_trace_reconnect_return(wLog* log, const Reconnect_Return* ret)
1366{
1367 WINPR_ASSERT(ret);
1368
1369 if (!WLog_IsLevelActive(log, g_LogLevel))
1370 return;
1371
1372 WLog_Print(log, g_LogLevel, "Reconnect_Return {");
1373 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
1374 SCardGetErrorString(ret->ReturnCode), ret->ReturnCode);
1375 WLog_Print(log, g_LogLevel, " dwActiveProtocol: %s (0x%08" PRIX32 ")",
1376 SCardGetProtocolString(ret->dwActiveProtocol), ret->dwActiveProtocol);
1377 WLog_Print(log, g_LogLevel, "}");
1378}
1379
1380static void smartcard_trace_connect_a_call(wLog* log, const ConnectA_Call* call)
1381{
1382 WINPR_ASSERT(call);
1383
1384 if (!WLog_IsLevelActive(log, g_LogLevel))
1385 return;
1386
1387 WLog_Print(log, g_LogLevel, "ConnectA_Call {");
1388 smartcard_log_context(log, &call->Common.handles.hContext);
1389
1390 WLog_Print(log, g_LogLevel,
1391 "szReader: %s dwShareMode: %s (0x%08" PRIX32
1392 ") dwPreferredProtocols: %s (0x%08" PRIX32 ")",
1393 call->szReader, SCardGetShareModeString(call->Common.dwShareMode),
1394 call->Common.dwShareMode, SCardGetProtocolString(call->Common.dwPreferredProtocols),
1395 call->Common.dwPreferredProtocols);
1396 WLog_Print(log, g_LogLevel, "}");
1397}
1398
1399static void smartcard_trace_connect_w_call(wLog* log, const ConnectW_Call* call)
1400{
1401 WINPR_ASSERT(call);
1402 char szReaderA[1024] = { 0 };
1403
1404 if (!WLog_IsLevelActive(log, g_LogLevel))
1405 return;
1406
1407 if (call->szReader)
1408 (void)ConvertWCharToUtf8(call->szReader, szReaderA, ARRAYSIZE(szReaderA));
1409 WLog_Print(log, g_LogLevel, "ConnectW_Call {");
1410 smartcard_log_context(log, &call->Common.handles.hContext);
1411
1412 WLog_Print(log, g_LogLevel,
1413 "szReader: %s dwShareMode: %s (0x%08" PRIX32
1414 ") dwPreferredProtocols: %s (0x%08" PRIX32 ")",
1415 szReaderA, SCardGetShareModeString(call->Common.dwShareMode),
1416 call->Common.dwShareMode, SCardGetProtocolString(call->Common.dwPreferredProtocols),
1417 call->Common.dwPreferredProtocols);
1418 WLog_Print(log, g_LogLevel, "}");
1419}
1420
1421static void smartcard_trace_hcard_and_disposition_call(wLog* log,
1422 const HCardAndDisposition_Call* call,
1423 const char* name)
1424{
1425 WINPR_ASSERT(call);
1426
1427 if (!WLog_IsLevelActive(log, g_LogLevel))
1428 return;
1429
1430 WLog_Print(log, g_LogLevel, "%s_Call {", name);
1431 smartcard_log_context(log, &call->handles.hContext);
1432 smartcard_log_redir_handle(log, &call->handles.hCard);
1433
1434 WLog_Print(log, g_LogLevel, "dwDisposition: %s (0x%08" PRIX32 ")",
1435 SCardGetDispositionString(call->dwDisposition), call->dwDisposition);
1436 WLog_Print(log, g_LogLevel, "}");
1437}
1438
1439static void smartcard_trace_establish_context_call(wLog* log, const EstablishContext_Call* call)
1440{
1441 WINPR_ASSERT(call);
1442
1443 if (!WLog_IsLevelActive(log, g_LogLevel))
1444 return;
1445
1446 WLog_Print(log, g_LogLevel, "EstablishContext_Call {");
1447 WLog_Print(log, g_LogLevel, "dwScope: %s (0x%08" PRIX32 ")", SCardGetScopeString(call->dwScope),
1448 call->dwScope);
1449 WLog_Print(log, g_LogLevel, "}");
1450}
1451
1452static void smartcard_trace_establish_context_return(wLog* log, const EstablishContext_Return* ret)
1453{
1454 WINPR_ASSERT(ret);
1455
1456 if (!WLog_IsLevelActive(log, g_LogLevel))
1457 return;
1458
1459 WLog_Print(log, g_LogLevel, "EstablishContext_Return {");
1460 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
1461 SCardGetErrorString(ret->ReturnCode), ret->ReturnCode);
1462 smartcard_log_context(log, &ret->hContext);
1463
1464 WLog_Print(log, g_LogLevel, "}");
1465}
1466
1467void smartcard_trace_long_return(const Long_Return* ret, const char* name)
1468{
1469 wLog* log = scard_log();
1470 smartcard_trace_long_return_int(log, ret, name);
1471}
1472
1473void smartcard_trace_long_return_int(wLog* log, const Long_Return* ret, const char* name)
1474{
1475 WINPR_ASSERT(ret);
1476
1477 if (!WLog_IsLevelActive(log, g_LogLevel))
1478 return;
1479
1480 WLog_Print(log, g_LogLevel, "%s_Return {", name);
1481 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
1482 SCardGetErrorString(ret->ReturnCode), ret->ReturnCode);
1483 WLog_Print(log, g_LogLevel, "}");
1484}
1485
1486static void smartcard_trace_connect_return(wLog* log, const Connect_Return* ret)
1487{
1488 WINPR_ASSERT(ret);
1489
1490 if (!WLog_IsLevelActive(log, g_LogLevel))
1491 return;
1492
1493 WLog_Print(log, g_LogLevel, "Connect_Return {");
1494 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
1495 SCardGetErrorString(ret->ReturnCode), ret->ReturnCode);
1496 smartcard_log_context(log, &ret->hContext);
1497 smartcard_log_redir_handle(log, &ret->hCard);
1498
1499 WLog_Print(log, g_LogLevel, " dwActiveProtocol: %s (0x%08" PRIX32 ")",
1500 SCardGetProtocolString(ret->dwActiveProtocol), ret->dwActiveProtocol);
1501 WLog_Print(log, g_LogLevel, "}");
1502}
1503
1504static void smartcard_trace_reconnect_call(wLog* log, const Reconnect_Call* call)
1505{
1506 WINPR_ASSERT(call);
1507
1508 if (!WLog_IsLevelActive(log, g_LogLevel))
1509 return;
1510
1511 WLog_Print(log, g_LogLevel, "Reconnect_Call {");
1512 smartcard_log_context(log, &call->handles.hContext);
1513 smartcard_log_redir_handle(log, &call->handles.hCard);
1514
1515 WLog_Print(log, g_LogLevel,
1516 "dwShareMode: %s (0x%08" PRIX32 ") dwPreferredProtocols: %s (0x%08" PRIX32
1517 ") dwInitialization: %s (0x%08" PRIX32 ")",
1518 SCardGetShareModeString(call->dwShareMode), call->dwShareMode,
1519 SCardGetProtocolString(call->dwPreferredProtocols), call->dwPreferredProtocols,
1520 SCardGetDispositionString(call->dwInitialization), call->dwInitialization);
1521 WLog_Print(log, g_LogLevel, "}");
1522}
1523
1524static void smartcard_trace_device_type_id_return(wLog* log, const GetDeviceTypeId_Return* ret)
1525{
1526 WINPR_ASSERT(ret);
1527
1528 if (!WLog_IsLevelActive(log, g_LogLevel))
1529 return;
1530
1531 WLog_Print(log, g_LogLevel, "GetDeviceTypeId_Return {");
1532 WLog_Print(log, g_LogLevel, " ReturnCode: %s (0x%08" PRIX32 ")",
1533 SCardGetErrorString(ret->ReturnCode), ret->ReturnCode);
1534 WLog_Print(log, g_LogLevel, " dwDeviceId=%08" PRIx32, ret->dwDeviceId);
1535
1536 WLog_Print(log, g_LogLevel, "}");
1537}
1538
1539static LONG smartcard_unpack_common_context_and_string_a(wLog* log, wStream* s,
1540 REDIR_SCARDCONTEXT* phContext,
1541 CHAR** pszReaderName)
1542{
1543 UINT32 index = 0;
1544 UINT32 pbContextNdrPtr = 0;
1545 LONG status = smartcard_unpack_redir_scard_context(log, s, phContext, &index, &pbContextNdrPtr);
1546 if (status != SCARD_S_SUCCESS)
1547 return status;
1548
1549 if (!smartcard_ndr_pointer_read(log, s, &index, NULL))
1550 return ERROR_INVALID_DATA;
1551
1552 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr, phContext);
1553 if (status != SCARD_S_SUCCESS)
1554 return status;
1555
1556 status = smartcard_ndr_read_a(log, s, pszReaderName, NDR_PTR_FULL);
1557 if (status != SCARD_S_SUCCESS)
1558 return status;
1559
1560 smartcard_trace_context_and_string_call_a(log, __func__, phContext, *pszReaderName);
1561 return SCARD_S_SUCCESS;
1562}
1563
1564static LONG smartcard_unpack_common_context_and_string_w(wLog* log, wStream* s,
1565 REDIR_SCARDCONTEXT* phContext,
1566 WCHAR** pszReaderName)
1567{
1568 UINT32 index = 0;
1569 UINT32 pbContextNdrPtr = 0;
1570
1571 LONG status = smartcard_unpack_redir_scard_context(log, s, phContext, &index, &pbContextNdrPtr);
1572 if (status != SCARD_S_SUCCESS)
1573 return status;
1574
1575 if (!smartcard_ndr_pointer_read(log, s, &index, NULL))
1576 return ERROR_INVALID_DATA;
1577
1578 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr, phContext);
1579 if (status != SCARD_S_SUCCESS)
1580 return status;
1581
1582 status = smartcard_ndr_read_w(log, s, pszReaderName, NDR_PTR_FULL);
1583 if (status != SCARD_S_SUCCESS)
1584 return status;
1585
1586 smartcard_trace_context_and_string_call_w(log, __func__, phContext, *pszReaderName);
1587 return SCARD_S_SUCCESS;
1588}
1589
1590LONG smartcard_unpack_common_type_header(wStream* s)
1591{
1592 wLog* log = scard_log();
1593 UINT8 version = 0;
1594 UINT32 filler = 0;
1595 UINT8 endianness = 0;
1596 UINT16 commonHeaderLength = 0;
1597
1598 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
1599 return STATUS_BUFFER_TOO_SMALL;
1600
1601 /* Process CommonTypeHeader */
1602 Stream_Read_UINT8(s, version); /* Version (1 byte) */
1603 Stream_Read_UINT8(s, endianness); /* Endianness (1 byte) */
1604 Stream_Read_UINT16(s, commonHeaderLength); /* CommonHeaderLength (2 bytes) */
1605 Stream_Read_UINT32(s, filler); /* Filler (4 bytes), should be 0xCCCCCCCC */
1606
1607 if (version != 1)
1608 {
1609 WLog_Print(log, WLOG_WARN, "Unsupported CommonTypeHeader Version %" PRIu8 "", version);
1610 return STATUS_INVALID_PARAMETER;
1611 }
1612
1613 if (endianness != 0x10)
1614 {
1615 WLog_Print(log, WLOG_WARN, "Unsupported CommonTypeHeader Endianness %" PRIu8 "",
1616 endianness);
1617 return STATUS_INVALID_PARAMETER;
1618 }
1619
1620 if (commonHeaderLength != 8)
1621 {
1622 WLog_Print(log, WLOG_WARN, "Unsupported CommonTypeHeader CommonHeaderLength %" PRIu16 "",
1623 commonHeaderLength);
1624 return STATUS_INVALID_PARAMETER;
1625 }
1626
1627 if (filler != 0xCCCCCCCC)
1628 {
1629 WLog_Print(log, WLOG_WARN, "Unexpected CommonTypeHeader Filler 0x%08" PRIX32 "", filler);
1630 return STATUS_INVALID_PARAMETER;
1631 }
1632
1633 return SCARD_S_SUCCESS;
1634}
1635
1636void smartcard_pack_common_type_header(wStream* s)
1637{
1638 Stream_Write_UINT8(s, 1); /* Version (1 byte) */
1639 Stream_Write_UINT8(s, 0x10); /* Endianness (1 byte) */
1640 Stream_Write_UINT16(s, 8); /* CommonHeaderLength (2 bytes) */
1641 Stream_Write_UINT32(s, 0xCCCCCCCC); /* Filler (4 bytes), should be 0xCCCCCCCC */
1642}
1643
1644LONG smartcard_unpack_private_type_header(wStream* s)
1645{
1646 wLog* log = scard_log();
1647 UINT32 filler = 0;
1648 UINT32 objectBufferLength = 0;
1649
1650 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
1651 return STATUS_BUFFER_TOO_SMALL;
1652
1653 Stream_Read_UINT32(s, objectBufferLength); /* ObjectBufferLength (4 bytes) */
1654 Stream_Read_UINT32(s, filler); /* Filler (4 bytes), should be 0x00000000 */
1655
1656 if (filler != 0x00000000)
1657 {
1658 WLog_Print(log, WLOG_WARN, "Unexpected PrivateTypeHeader Filler 0x%08" PRIX32 "", filler);
1659 return STATUS_INVALID_PARAMETER;
1660 }
1661
1662 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, objectBufferLength))
1663 return STATUS_INVALID_PARAMETER;
1664
1665 return SCARD_S_SUCCESS;
1666}
1667
1668void smartcard_pack_private_type_header(wStream* s, UINT32 objectBufferLength)
1669{
1670 Stream_Write_UINT32(s, objectBufferLength); /* ObjectBufferLength (4 bytes) */
1671 Stream_Write_UINT32(s, 0x00000000); /* Filler (4 bytes), should be 0x00000000 */
1672}
1673
1674LONG smartcard_unpack_read_size_align(wStream* s, size_t size, UINT32 alignment)
1675{
1676 size_t pad = 0;
1677
1678 pad = size;
1679 size = (size + alignment - 1) & ~(alignment - 1);
1680 pad = size - pad;
1681
1682 if (pad)
1683 Stream_Seek(s, pad);
1684
1685 return (LONG)pad;
1686}
1687
1688LONG smartcard_pack_write_size_align(wStream* s, size_t size, UINT32 alignment)
1689{
1690 size_t pad = 0;
1691
1692 pad = size;
1693 size = (size + alignment - 1) & ~(alignment - 1);
1694 pad = size - pad;
1695
1696 if (pad)
1697 {
1698 if (!Stream_EnsureRemainingCapacity(s, pad))
1699 {
1700 wLog* log = scard_log();
1701 WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
1702 return SCARD_F_INTERNAL_ERROR;
1703 }
1704
1705 Stream_Zero(s, pad);
1706 }
1707
1708 return SCARD_S_SUCCESS;
1709}
1710
1711SCARDCONTEXT smartcard_scard_context_native_from_redir(REDIR_SCARDCONTEXT* context)
1712{
1713 SCARDCONTEXT hContext = { 0 };
1714
1715 WINPR_ASSERT(context);
1716 if ((context->cbContext != sizeof(ULONG_PTR)) && (context->cbContext != 0))
1717 {
1718 wLog* log = scard_log();
1719 WLog_Print(log, WLOG_WARN,
1720 "REDIR_SCARDCONTEXT does not match native size: Actual: %" PRIu32
1721 ", Expected: %" PRIuz "",
1722 context->cbContext, sizeof(ULONG_PTR));
1723 return 0;
1724 }
1725
1726 if (context->cbContext)
1727 CopyMemory(&hContext, &(context->pbContext), context->cbContext);
1728
1729 return hContext;
1730}
1731
1732void smartcard_scard_context_native_to_redir(REDIR_SCARDCONTEXT* context, SCARDCONTEXT hContext)
1733{
1734 WINPR_ASSERT(context);
1735 ZeroMemory(context, sizeof(REDIR_SCARDCONTEXT));
1736 context->cbContext = sizeof(ULONG_PTR);
1737 CopyMemory(&(context->pbContext), &hContext, context->cbContext);
1738}
1739
1740SCARDHANDLE smartcard_scard_handle_native_from_redir(REDIR_SCARDHANDLE* handle)
1741{
1742 SCARDHANDLE hCard = 0;
1743
1744 WINPR_ASSERT(handle);
1745 if (handle->cbHandle == 0)
1746 return hCard;
1747
1748 if (handle->cbHandle != sizeof(ULONG_PTR))
1749 {
1750 wLog* log = scard_log();
1751 WLog_Print(log, WLOG_WARN,
1752 "REDIR_SCARDHANDLE does not match native size: Actual: %" PRIu32
1753 ", Expected: %" PRIuz "",
1754 handle->cbHandle, sizeof(ULONG_PTR));
1755 return 0;
1756 }
1757
1758 if (handle->cbHandle)
1759 CopyMemory(&hCard, &(handle->pbHandle), handle->cbHandle);
1760
1761 return hCard;
1762}
1763
1764void smartcard_scard_handle_native_to_redir(REDIR_SCARDHANDLE* handle, SCARDHANDLE hCard)
1765{
1766 WINPR_ASSERT(handle);
1767 ZeroMemory(handle, sizeof(REDIR_SCARDHANDLE));
1768 handle->cbHandle = sizeof(ULONG_PTR);
1769 CopyMemory(&(handle->pbHandle), &hCard, handle->cbHandle);
1770}
1771
1772#define smartcard_context_supported(log, size) \
1773 smartcard_context_supported_((log), (size), __FILE__, __func__, __LINE__)
1774static LONG smartcard_context_supported_(wLog* log, uint32_t size, const char* file,
1775 const char* fkt, size_t line)
1776{
1777 switch (size)
1778 {
1779 case 0:
1780 case 4:
1781 case 8:
1782 return SCARD_S_SUCCESS;
1783 default:
1784 {
1785 const uint32_t level = WLOG_WARN;
1786 if (WLog_IsLevelActive(log, level))
1787 {
1788 WLog_PrintMessage(log, WLOG_MESSAGE_TEXT, level, line, file, fkt,
1789 "REDIR_SCARDCONTEXT length is not 0, 4 or 8: %" PRIu32 "", size);
1790 }
1791 return STATUS_INVALID_PARAMETER;
1792 }
1793 }
1794}
1795
1796LONG smartcard_unpack_redir_scard_context_(wLog* log, wStream* s, REDIR_SCARDCONTEXT* context,
1797 UINT32* index, UINT32* ppbContextNdrPtr,
1798 const char* file, const char* function, size_t line)
1799{
1800 UINT32 pbContextNdrPtr = 0;
1801
1802 WINPR_UNUSED(file);
1803 WINPR_ASSERT(context);
1804
1805 ZeroMemory(context, sizeof(REDIR_SCARDCONTEXT));
1806
1807 if (!Stream_CheckAndLogRequiredLengthWLogEx(log, WLOG_WARN, s, 4, 1, "%s(%s:%" PRIuz ")", file,
1808 function, line))
1809 return STATUS_BUFFER_TOO_SMALL;
1810
1811 const LONG status = smartcard_context_supported_(log, context->cbContext, file, function, line);
1812 if (status != SCARD_S_SUCCESS)
1813 return status;
1814
1815 Stream_Read_UINT32(s, context->cbContext); /* cbContext (4 bytes) */
1816
1817 if (!smartcard_ndr_pointer_read_(log, s, index, &pbContextNdrPtr, file, function, line))
1818 return ERROR_INVALID_DATA;
1819
1820 if (((context->cbContext == 0) && pbContextNdrPtr) ||
1821 ((context->cbContext != 0) && !pbContextNdrPtr))
1822 {
1823 WLog_Print(log, WLOG_WARN,
1824 "REDIR_SCARDCONTEXT cbContext (%" PRIu32 ") pbContextNdrPtr (%" PRIu32
1825 ") inconsistency",
1826 context->cbContext, pbContextNdrPtr);
1827 return STATUS_INVALID_PARAMETER;
1828 }
1829
1830 if (!Stream_CheckAndLogRequiredLengthWLogEx(log, WLOG_WARN, s, context->cbContext, 1,
1831 "%s(%s:%" PRIuz ")", file, function, line))
1832 return STATUS_INVALID_PARAMETER;
1833
1834 *ppbContextNdrPtr = pbContextNdrPtr;
1835 return SCARD_S_SUCCESS;
1836}
1837
1838LONG smartcard_pack_redir_scard_context(WINPR_ATTR_UNUSED wLog* log, wStream* s,
1839 const REDIR_SCARDCONTEXT* context, DWORD* index)
1840{
1841 const UINT32 pbContextNdrPtr = 0x00020000 + *index * 4;
1842
1843 WINPR_ASSERT(context);
1844 if (context->cbContext != 0)
1845 {
1846 Stream_Write_UINT32(s, context->cbContext); /* cbContext (4 bytes) */
1847 Stream_Write_UINT32(s, pbContextNdrPtr); /* pbContextNdrPtr (4 bytes) */
1848 *index = *index + 1;
1849 }
1850 else
1851 Stream_Zero(s, 8);
1852
1853 return SCARD_S_SUCCESS;
1854}
1855
1856LONG smartcard_unpack_redir_scard_context_ref(wLog* log, wStream* s,
1857 WINPR_ATTR_UNUSED UINT32 pbContextNdrPtr,
1858 REDIR_SCARDCONTEXT* context)
1859{
1860 UINT32 length = 0;
1861
1862 WINPR_ASSERT(context);
1863 if (context->cbContext == 0)
1864 return SCARD_S_SUCCESS;
1865
1866 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
1867 return STATUS_BUFFER_TOO_SMALL;
1868
1869 Stream_Read_UINT32(s, length); /* Length (4 bytes) */
1870
1871 if (length != context->cbContext)
1872 {
1873 WLog_Print(log, WLOG_WARN,
1874 "REDIR_SCARDCONTEXT length (%" PRIu32 ") cbContext (%" PRIu32 ") mismatch",
1875 length, context->cbContext);
1876 return STATUS_INVALID_PARAMETER;
1877 }
1878
1879 const LONG status = smartcard_context_supported(log, context->cbContext);
1880 if (status != SCARD_S_SUCCESS)
1881 return status;
1882
1883 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, context->cbContext))
1884 return STATUS_BUFFER_TOO_SMALL;
1885
1886 if (context->cbContext)
1887 Stream_Read(s, &(context->pbContext), context->cbContext);
1888 else
1889 ZeroMemory(&(context->pbContext), sizeof(context->pbContext));
1890
1891 return SCARD_S_SUCCESS;
1892}
1893
1894LONG smartcard_pack_redir_scard_context_ref(WINPR_ATTR_UNUSED wLog* log, wStream* s,
1895 const REDIR_SCARDCONTEXT* context)
1896{
1897 WINPR_ASSERT(context);
1898 Stream_Write_UINT32(s, context->cbContext); /* Length (4 bytes) */
1899
1900 if (context->cbContext)
1901 {
1902 Stream_Write(s, &(context->pbContext), context->cbContext);
1903 }
1904
1905 return SCARD_S_SUCCESS;
1906}
1907
1908LONG smartcard_unpack_redir_scard_handle_(wLog* log, wStream* s, REDIR_SCARDHANDLE* handle,
1909 UINT32* index, const char* file, const char* function,
1910 size_t line)
1911{
1912 WINPR_ASSERT(handle);
1913 ZeroMemory(handle, sizeof(REDIR_SCARDHANDLE));
1914
1915 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
1916 return STATUS_BUFFER_TOO_SMALL;
1917
1918 Stream_Read_UINT32(s, handle->cbHandle); /* Length (4 bytes) */
1919
1920 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, handle->cbHandle))
1921 return STATUS_BUFFER_TOO_SMALL;
1922
1923 if (!smartcard_ndr_pointer_read_(log, s, index, NULL, file, function, line))
1924 return ERROR_INVALID_DATA;
1925
1926 return SCARD_S_SUCCESS;
1927}
1928
1929LONG smartcard_pack_redir_scard_handle(WINPR_ATTR_UNUSED wLog* log, wStream* s,
1930 const REDIR_SCARDHANDLE* handle, DWORD* index)
1931{
1932 const UINT32 pbContextNdrPtr = 0x00020000 + *index * 4;
1933
1934 WINPR_ASSERT(handle);
1935 if (handle->cbHandle != 0)
1936 {
1937 Stream_Write_UINT32(s, handle->cbHandle); /* cbContext (4 bytes) */
1938 Stream_Write_UINT32(s, pbContextNdrPtr); /* pbContextNdrPtr (4 bytes) */
1939 *index = *index + 1;
1940 }
1941 else
1942 Stream_Zero(s, 8);
1943 return SCARD_S_SUCCESS;
1944}
1945
1946LONG smartcard_unpack_redir_scard_handle_ref(wLog* log, wStream* s, REDIR_SCARDHANDLE* handle)
1947{
1948 UINT32 length = 0;
1949
1950 WINPR_ASSERT(handle);
1951 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
1952 return STATUS_BUFFER_TOO_SMALL;
1953
1954 Stream_Read_UINT32(s, length); /* Length (4 bytes) */
1955
1956 if (length != handle->cbHandle)
1957 {
1958 WLog_Print(log, WLOG_WARN,
1959 "REDIR_SCARDHANDLE length (%" PRIu32 ") cbHandle (%" PRIu32 ") mismatch", length,
1960 handle->cbHandle);
1961 return STATUS_INVALID_PARAMETER;
1962 }
1963
1964 if ((handle->cbHandle != 4) && (handle->cbHandle != 8))
1965 {
1966 WLog_Print(log, WLOG_WARN, "REDIR_SCARDHANDLE length is not 4 or 8: %" PRIu32 "",
1967 handle->cbHandle);
1968 return STATUS_INVALID_PARAMETER;
1969 }
1970
1971 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, handle->cbHandle))
1972 return STATUS_BUFFER_TOO_SMALL;
1973
1974 if (handle->cbHandle)
1975 Stream_Read(s, &(handle->pbHandle), handle->cbHandle);
1976
1977 return SCARD_S_SUCCESS;
1978}
1979
1980LONG smartcard_pack_redir_scard_handle_ref(WINPR_ATTR_UNUSED wLog* log, wStream* s,
1981 const REDIR_SCARDHANDLE* handle)
1982{
1983 WINPR_ASSERT(handle);
1984 Stream_Write_UINT32(s, handle->cbHandle); /* Length (4 bytes) */
1985
1986 if (handle->cbHandle)
1987 Stream_Write(s, &(handle->pbHandle), handle->cbHandle);
1988
1989 return SCARD_S_SUCCESS;
1990}
1991
1992LONG smartcard_unpack_establish_context_call(wStream* s, EstablishContext_Call* call)
1993{
1994 WINPR_ASSERT(call);
1995 wLog* log = scard_log();
1996
1997 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
1998 return STATUS_BUFFER_TOO_SMALL;
1999
2000 Stream_Read_UINT32(s, call->dwScope); /* dwScope (4 bytes) */
2001 smartcard_trace_establish_context_call(log, call);
2002 return SCARD_S_SUCCESS;
2003}
2004
2005LONG smartcard_pack_establish_context_return(wStream* s, const EstablishContext_Return* ret)
2006{
2007 WINPR_ASSERT(ret);
2008 wLog* log = scard_log();
2009 LONG status = 0;
2010 DWORD index = 0;
2011
2012 smartcard_trace_establish_context_return(log, ret);
2013 if (ret->ReturnCode != SCARD_S_SUCCESS)
2014 return ret->ReturnCode;
2015
2016 status = smartcard_pack_redir_scard_context(log, s, &(ret->hContext), &index);
2017 if (status != SCARD_S_SUCCESS)
2018 return status;
2019
2020 return smartcard_pack_redir_scard_context_ref(log, s, &(ret->hContext));
2021}
2022
2023LONG smartcard_unpack_context_call(wStream* s, Context_Call* call, const char* name)
2024{
2025 UINT32 index = 0;
2026 UINT32 pbContextNdrPtr = 0;
2027 wLog* log = scard_log();
2028
2029 WINPR_ASSERT(call);
2030 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2031 &pbContextNdrPtr);
2032 if (status != SCARD_S_SUCCESS)
2033 return status;
2034
2035 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2036 &(call->handles.hContext));
2037 if (status != SCARD_S_SUCCESS)
2038 WLog_Print(log, WLOG_ERROR,
2039 "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "",
2040 status);
2041
2042 smartcard_trace_context_call(log, call, name);
2043 return status;
2044}
2045
2046LONG smartcard_unpack_list_reader_groups_call(wStream* s, ListReaderGroups_Call* call, BOOL unicode)
2047{
2048 UINT32 index = 0;
2049 UINT32 pbContextNdrPtr = 0;
2050 wLog* log = scard_log();
2051
2052 WINPR_ASSERT(call);
2053 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2054 &pbContextNdrPtr);
2055
2056 if (status != SCARD_S_SUCCESS)
2057 return status;
2058
2059 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2060 return STATUS_BUFFER_TOO_SMALL;
2061
2062 Stream_Read_INT32(s, call->fmszGroupsIsNULL); /* fmszGroupsIsNULL (4 bytes) */
2063 Stream_Read_UINT32(s, call->cchGroups); /* cchGroups (4 bytes) */
2064 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2065 &(call->handles.hContext));
2066
2067 if (status != SCARD_S_SUCCESS)
2068 return status;
2069
2070 smartcard_trace_list_reader_groups_call(log, call, unicode);
2071 return SCARD_S_SUCCESS;
2072}
2073
2074LONG smartcard_pack_list_reader_groups_return(wStream* s, const ListReaderGroups_Return* ret,
2075 BOOL unicode)
2076{
2077 WINPR_ASSERT(ret);
2078 wLog* log = scard_log();
2079 LONG status = 0;
2080 DWORD cBytes = ret->cBytes;
2081 UINT32 index = 0;
2082
2083 smartcard_trace_list_reader_groups_return(log, ret, unicode);
2084 if (ret->ReturnCode != SCARD_S_SUCCESS)
2085 cBytes = 0;
2086 if (cBytes == SCARD_AUTOALLOCATE)
2087 cBytes = 0;
2088
2089 if (!Stream_EnsureRemainingCapacity(s, 4))
2090 return SCARD_E_NO_MEMORY;
2091
2092 Stream_Write_UINT32(s, cBytes); /* cBytes (4 bytes) */
2093 if (!smartcard_ndr_pointer_write(s, &index, cBytes))
2094 return SCARD_E_NO_MEMORY;
2095
2096 status = smartcard_ndr_write(s, ret->msz, cBytes, 1, NDR_PTR_SIMPLE);
2097 if (status != SCARD_S_SUCCESS)
2098 return status;
2099 return ret->ReturnCode;
2100}
2101
2102LONG smartcard_unpack_list_readers_call(wStream* s, ListReaders_Call* call, BOOL unicode)
2103{
2104 UINT32 index = 0;
2105 UINT32 mszGroupsNdrPtr = 0;
2106 UINT32 pbContextNdrPtr = 0;
2107 wLog* log = scard_log();
2108
2109 WINPR_ASSERT(call);
2110 call->mszGroups = NULL;
2111
2112 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2113 &pbContextNdrPtr);
2114 if (status != SCARD_S_SUCCESS)
2115 return status;
2116
2117 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2118 return STATUS_BUFFER_TOO_SMALL;
2119
2120 Stream_Read_UINT32(s, call->cBytes); /* cBytes (4 bytes) */
2121 if (!smartcard_ndr_pointer_read(log, s, &index, &mszGroupsNdrPtr))
2122 return ERROR_INVALID_DATA;
2123
2124 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2125 return STATUS_BUFFER_TOO_SMALL;
2126 Stream_Read_INT32(s, call->fmszReadersIsNULL); /* fmszReadersIsNULL (4 bytes) */
2127 Stream_Read_UINT32(s, call->cchReaders); /* cchReaders (4 bytes) */
2128
2129 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2130 &(call->handles.hContext));
2131 if (status != SCARD_S_SUCCESS)
2132 return status;
2133
2134 if (mszGroupsNdrPtr)
2135 {
2136 status = smartcard_ndr_read(log, s, &call->mszGroups, call->cBytes, 1, NDR_PTR_SIMPLE);
2137 if (status != SCARD_S_SUCCESS)
2138 return status;
2139 }
2140
2141 smartcard_trace_list_readers_call(log, call, unicode);
2142 return SCARD_S_SUCCESS;
2143}
2144
2145LONG smartcard_pack_list_readers_return(wStream* s, const ListReaders_Return* ret, BOOL unicode)
2146{
2147 WINPR_ASSERT(ret);
2148 wLog* log = scard_log();
2149 LONG status = 0;
2150 UINT32 index = 0;
2151 UINT32 size = ret->cBytes;
2152
2153 smartcard_trace_list_readers_return(log, ret, unicode);
2154 if (ret->ReturnCode != SCARD_S_SUCCESS)
2155 size = 0;
2156
2157 if (!Stream_EnsureRemainingCapacity(s, 4))
2158 {
2159 WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
2160 return SCARD_F_INTERNAL_ERROR;
2161 }
2162
2163 Stream_Write_UINT32(s, size); /* cBytes (4 bytes) */
2164 if (!smartcard_ndr_pointer_write(s, &index, size))
2165 return SCARD_E_NO_MEMORY;
2166
2167 status = smartcard_ndr_write(s, ret->msz, size, 1, NDR_PTR_SIMPLE);
2168 if (status != SCARD_S_SUCCESS)
2169 return status;
2170 return ret->ReturnCode;
2171}
2172
2173static LONG smartcard_unpack_connect_common(wLog* log, wStream* s, Connect_Common_Call* common,
2174 UINT32* index, UINT32* ppbContextNdrPtr)
2175{
2176 WINPR_ASSERT(common);
2177 LONG status = smartcard_unpack_redir_scard_context(log, s, &(common->handles.hContext), index,
2178 ppbContextNdrPtr);
2179 if (status != SCARD_S_SUCCESS)
2180 return status;
2181
2182 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2183 return STATUS_BUFFER_TOO_SMALL;
2184
2185 Stream_Read_UINT32(s, common->dwShareMode); /* dwShareMode (4 bytes) */
2186 Stream_Read_UINT32(s, common->dwPreferredProtocols); /* dwPreferredProtocols (4 bytes) */
2187 return SCARD_S_SUCCESS;
2188}
2189
2190LONG smartcard_unpack_connect_a_call(wStream* s, ConnectA_Call* call)
2191{
2192 LONG status = 0;
2193 UINT32 index = 0;
2194 UINT32 pbContextNdrPtr = 0;
2195
2196 WINPR_ASSERT(call);
2197 wLog* log = scard_log();
2198
2199 call->szReader = NULL;
2200
2201 if (!smartcard_ndr_pointer_read(log, s, &index, NULL))
2202 return ERROR_INVALID_DATA;
2203
2204 status = smartcard_unpack_connect_common(log, s, &(call->Common), &index, &pbContextNdrPtr);
2205 if (status != SCARD_S_SUCCESS)
2206 {
2207 WLog_Print(log, WLOG_ERROR, "smartcard_unpack_connect_common failed with error %" PRId32 "",
2208 status);
2209 return status;
2210 }
2211
2212 status = smartcard_ndr_read_a(log, s, &call->szReader, NDR_PTR_FULL);
2213 if (status != SCARD_S_SUCCESS)
2214 return status;
2215
2216 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2217 &(call->Common.handles.hContext));
2218 if (status != SCARD_S_SUCCESS)
2219 WLog_Print(log, WLOG_ERROR,
2220 "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "",
2221 status);
2222
2223 smartcard_trace_connect_a_call(log, call);
2224 return status;
2225}
2226
2227LONG smartcard_unpack_connect_w_call(wStream* s, ConnectW_Call* call)
2228{
2229 LONG status = 0;
2230 UINT32 index = 0;
2231 UINT32 pbContextNdrPtr = 0;
2232
2233 WINPR_ASSERT(call);
2234 wLog* log = scard_log();
2235 call->szReader = NULL;
2236
2237 if (!smartcard_ndr_pointer_read(log, s, &index, NULL))
2238 return ERROR_INVALID_DATA;
2239
2240 status = smartcard_unpack_connect_common(log, s, &(call->Common), &index, &pbContextNdrPtr);
2241 if (status != SCARD_S_SUCCESS)
2242 {
2243 WLog_Print(log, WLOG_ERROR, "smartcard_unpack_connect_common failed with error %" PRId32 "",
2244 status);
2245 return status;
2246 }
2247
2248 status = smartcard_ndr_read_w(log, s, &call->szReader, NDR_PTR_FULL);
2249 if (status != SCARD_S_SUCCESS)
2250 return status;
2251
2252 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2253 &(call->Common.handles.hContext));
2254 if (status != SCARD_S_SUCCESS)
2255 WLog_Print(log, WLOG_ERROR,
2256 "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "",
2257 status);
2258
2259 smartcard_trace_connect_w_call(log, call);
2260 return status;
2261}
2262
2263LONG smartcard_pack_connect_return(wStream* s, const Connect_Return* ret)
2264{
2265 LONG status = 0;
2266 DWORD index = 0;
2267
2268 WINPR_ASSERT(ret);
2269 wLog* log = scard_log();
2270 smartcard_trace_connect_return(log, ret);
2271
2272 status = smartcard_pack_redir_scard_context(log, s, &ret->hContext, &index);
2273 if (status != SCARD_S_SUCCESS)
2274 return status;
2275
2276 status = smartcard_pack_redir_scard_handle(log, s, &ret->hCard, &index);
2277 if (status != SCARD_S_SUCCESS)
2278 return status;
2279
2280 if (!Stream_EnsureRemainingCapacity(s, 4))
2281 return SCARD_E_NO_MEMORY;
2282
2283 Stream_Write_UINT32(s, ret->dwActiveProtocol); /* dwActiveProtocol (4 bytes) */
2284 status = smartcard_pack_redir_scard_context_ref(log, s, &ret->hContext);
2285 if (status != SCARD_S_SUCCESS)
2286 return status;
2287 return smartcard_pack_redir_scard_handle_ref(log, s, &(ret->hCard));
2288}
2289
2290LONG smartcard_unpack_reconnect_call(wStream* s, Reconnect_Call* call)
2291{
2292 UINT32 index = 0;
2293 UINT32 pbContextNdrPtr = 0;
2294
2295 WINPR_ASSERT(call);
2296 wLog* log = scard_log();
2297 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2298 &pbContextNdrPtr);
2299 if (status != SCARD_S_SUCCESS)
2300 return status;
2301
2302 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
2303 if (status != SCARD_S_SUCCESS)
2304 return status;
2305
2306 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
2307 return STATUS_BUFFER_TOO_SMALL;
2308
2309 Stream_Read_UINT32(s, call->dwShareMode); /* dwShareMode (4 bytes) */
2310 Stream_Read_UINT32(s, call->dwPreferredProtocols); /* dwPreferredProtocols (4 bytes) */
2311 Stream_Read_UINT32(s, call->dwInitialization); /* dwInitialization (4 bytes) */
2312
2313 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2314 &(call->handles.hContext));
2315 if (status != SCARD_S_SUCCESS)
2316 {
2317 WLog_Print(log, WLOG_ERROR,
2318 "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "",
2319 status);
2320 return status;
2321 }
2322
2323 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
2324 if (status != SCARD_S_SUCCESS)
2325 WLog_Print(log, WLOG_ERROR,
2326 "smartcard_unpack_redir_scard_handle_ref failed with error %" PRId32 "", status);
2327
2328 smartcard_trace_reconnect_call(log, call);
2329 return status;
2330}
2331
2332LONG smartcard_pack_reconnect_return(wStream* s, const Reconnect_Return* ret)
2333{
2334 WINPR_ASSERT(ret);
2335 wLog* log = scard_log();
2336 smartcard_trace_reconnect_return(log, ret);
2337
2338 if (!Stream_EnsureRemainingCapacity(s, 4))
2339 return SCARD_E_NO_MEMORY;
2340 Stream_Write_UINT32(s, ret->dwActiveProtocol); /* dwActiveProtocol (4 bytes) */
2341 return ret->ReturnCode;
2342}
2343
2344LONG smartcard_unpack_hcard_and_disposition_call(wStream* s, HCardAndDisposition_Call* call,
2345 const char* name)
2346{
2347 UINT32 index = 0;
2348 UINT32 pbContextNdrPtr = 0;
2349
2350 WINPR_ASSERT(call);
2351 wLog* log = scard_log();
2352
2353 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2354 &pbContextNdrPtr);
2355 if (status != SCARD_S_SUCCESS)
2356 return status;
2357
2358 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
2359 if (status != SCARD_S_SUCCESS)
2360 return status;
2361
2362 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2363 return STATUS_BUFFER_TOO_SMALL;
2364
2365 Stream_Read_UINT32(s, call->dwDisposition); /* dwDisposition (4 bytes) */
2366
2367 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2368 &(call->handles.hContext));
2369 if (status != SCARD_S_SUCCESS)
2370 return status;
2371
2372 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
2373 if (status != SCARD_S_SUCCESS)
2374 return status;
2375
2376 smartcard_trace_hcard_and_disposition_call(log, call, name);
2377 return status;
2378}
2379
2380static void smartcard_trace_get_status_change_a_call(wLog* log, const GetStatusChangeA_Call* call)
2381{
2382 WINPR_ASSERT(call);
2383
2384 if (!WLog_IsLevelActive(log, g_LogLevel))
2385 return;
2386
2387 WLog_Print(log, g_LogLevel, "GetStatusChangeA_Call {");
2388 smartcard_log_context(log, &call->handles.hContext);
2389
2390 WLog_Print(log, g_LogLevel, "dwTimeOut: 0x%08" PRIX32 " cReaders: %" PRIu32 "", call->dwTimeOut,
2391 call->cReaders);
2392
2393 dump_reader_states_a(log, call->rgReaderStates, call->cReaders);
2394
2395 WLog_Print(log, g_LogLevel, "}");
2396}
2397
2398static LONG smartcard_unpack_reader_state_a(wLog* log, wStream* s, LPSCARD_READERSTATEA* ppcReaders,
2399 UINT32 cReaders, UINT32* ptrIndex)
2400{
2401 LONG status = SCARD_E_NO_MEMORY;
2402
2403 WINPR_ASSERT(ppcReaders || (cReaders == 0));
2404 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2405 return status;
2406
2407 const UINT32 len = Stream_Get_UINT32(s);
2408 if (len != cReaders)
2409 {
2410 WLog_Print(log, WLOG_ERROR, "Count mismatch when reading LPSCARD_READERSTATEA");
2411 return status;
2412 }
2413
2414 LPSCARD_READERSTATEA rgReaderStates =
2415 (LPSCARD_READERSTATEA)calloc(cReaders, sizeof(SCARD_READERSTATEA));
2416 BOOL* states = calloc(cReaders, sizeof(BOOL));
2417 if (!rgReaderStates || !states)
2418 goto fail;
2419 status = ERROR_INVALID_DATA;
2420
2421 for (UINT32 index = 0; index < cReaders; index++)
2422 {
2423 UINT32 ptr = UINT32_MAX;
2424 LPSCARD_READERSTATEA readerState = &rgReaderStates[index];
2425
2426 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 52))
2427 goto fail;
2428
2429 if (!smartcard_ndr_pointer_read(log, s, ptrIndex, &ptr))
2430 {
2431 if (ptr != 0)
2432 goto fail;
2433 }
2434 /* Ignore NULL length strings */
2435 states[index] = ptr != 0;
2436 Stream_Read_UINT32(s, readerState->dwCurrentState); /* dwCurrentState (4 bytes) */
2437 Stream_Read_UINT32(s, readerState->dwEventState); /* dwEventState (4 bytes) */
2438 Stream_Read_UINT32(s, readerState->cbAtr); /* cbAtr (4 bytes) */
2439 Stream_Read(s, readerState->rgbAtr, 36); /* rgbAtr [0..36] (36 bytes) */
2440 }
2441
2442 for (UINT32 index = 0; index < cReaders; index++)
2443 {
2444 LPSCARD_READERSTATEA readerState = &rgReaderStates[index];
2445
2446 /* Ignore empty strings */
2447 if (!states[index])
2448 continue;
2449 status = smartcard_ndr_read_a(log, s, &readerState->szReader, NDR_PTR_FULL);
2450 if (status != SCARD_S_SUCCESS)
2451 goto fail;
2452 }
2453
2454 *ppcReaders = rgReaderStates;
2455 free(states);
2456 return SCARD_S_SUCCESS;
2457fail:
2458 if (rgReaderStates)
2459 {
2460 for (UINT32 index = 0; index < cReaders; index++)
2461 {
2462 LPSCARD_READERSTATEA readerState = &rgReaderStates[index];
2463 free(readerState->szReader);
2464 }
2465 }
2466 free(rgReaderStates);
2467 free(states);
2468 return status;
2469}
2470
2471static LONG smartcard_unpack_reader_state_w(wLog* log, wStream* s, LPSCARD_READERSTATEW* ppcReaders,
2472 UINT32 cReaders, UINT32* ptrIndex)
2473{
2474 LONG status = SCARD_E_NO_MEMORY;
2475
2476 WINPR_ASSERT(ppcReaders || (cReaders == 0));
2477 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
2478 return status;
2479
2480 const UINT32 len = Stream_Get_UINT32(s);
2481 if (len != cReaders)
2482 {
2483 WLog_Print(log, WLOG_ERROR, "Count mismatch when reading LPSCARD_READERSTATEW");
2484 return status;
2485 }
2486
2487 LPSCARD_READERSTATEW rgReaderStates =
2488 (LPSCARD_READERSTATEW)calloc(cReaders, sizeof(SCARD_READERSTATEW));
2489 BOOL* states = calloc(cReaders, sizeof(BOOL));
2490
2491 if (!rgReaderStates || !states)
2492 goto fail;
2493
2494 status = ERROR_INVALID_DATA;
2495 for (UINT32 index = 0; index < cReaders; index++)
2496 {
2497 UINT32 ptr = UINT32_MAX;
2498 LPSCARD_READERSTATEW readerState = &rgReaderStates[index];
2499
2500 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 52))
2501 goto fail;
2502
2503 if (!smartcard_ndr_pointer_read(log, s, ptrIndex, &ptr))
2504 {
2505 if (ptr != 0)
2506 goto fail;
2507 }
2508 /* Ignore NULL length strings */
2509 states[index] = ptr != 0;
2510 Stream_Read_UINT32(s, readerState->dwCurrentState); /* dwCurrentState (4 bytes) */
2511 Stream_Read_UINT32(s, readerState->dwEventState); /* dwEventState (4 bytes) */
2512 Stream_Read_UINT32(s, readerState->cbAtr); /* cbAtr (4 bytes) */
2513 Stream_Read(s, readerState->rgbAtr, 36); /* rgbAtr [0..36] (36 bytes) */
2514 }
2515
2516 for (UINT32 index = 0; index < cReaders; index++)
2517 {
2518 LPSCARD_READERSTATEW readerState = &rgReaderStates[index];
2519
2520 /* Skip NULL pointers */
2521 if (!states[index])
2522 continue;
2523
2524 status = smartcard_ndr_read_w(log, s, &readerState->szReader, NDR_PTR_FULL);
2525 if (status != SCARD_S_SUCCESS)
2526 goto fail;
2527 }
2528
2529 *ppcReaders = rgReaderStates;
2530 free(states);
2531 return SCARD_S_SUCCESS;
2532fail:
2533 if (rgReaderStates)
2534 {
2535 for (UINT32 index = 0; index < cReaders; index++)
2536 {
2537 LPSCARD_READERSTATEW readerState = &rgReaderStates[index];
2538 free(readerState->szReader);
2539 }
2540 }
2541 free(rgReaderStates);
2542 free(states);
2543 return status;
2544}
2545
2546/******************************************************************************/
2547/************************************* End Trace Functions ********************/
2548/******************************************************************************/
2549
2550LONG smartcard_unpack_get_status_change_a_call(wStream* s, GetStatusChangeA_Call* call)
2551{
2552 UINT32 ndrPtr = 0;
2553 UINT32 index = 0;
2554 UINT32 pbContextNdrPtr = 0;
2555
2556 WINPR_ASSERT(call);
2557 wLog* log = scard_log();
2558
2559 call->rgReaderStates = NULL;
2560
2561 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2562 &pbContextNdrPtr);
2563 if (status != SCARD_S_SUCCESS)
2564 return status;
2565
2566 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2567 return STATUS_BUFFER_TOO_SMALL;
2568
2569 Stream_Read_UINT32(s, call->dwTimeOut); /* dwTimeOut (4 bytes) */
2570 Stream_Read_UINT32(s, call->cReaders); /* cReaders (4 bytes) */
2571 if (!smartcard_ndr_pointer_read(log, s, &index, &ndrPtr))
2572 return ERROR_INVALID_DATA;
2573
2574 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2575 &(call->handles.hContext));
2576 if (status != SCARD_S_SUCCESS)
2577 return status;
2578
2579 if (ndrPtr)
2580 {
2581 status =
2582 smartcard_unpack_reader_state_a(log, s, &call->rgReaderStates, call->cReaders, &index);
2583 if (status != SCARD_S_SUCCESS)
2584 return status;
2585 }
2586 else
2587 {
2588 WLog_Print(log, WLOG_WARN, "ndrPtr=0x%08" PRIx32 ", can not read rgReaderStates", ndrPtr);
2589 return SCARD_E_UNEXPECTED;
2590 }
2591
2592 smartcard_trace_get_status_change_a_call(log, call);
2593 return SCARD_S_SUCCESS;
2594}
2595
2596LONG smartcard_unpack_get_status_change_w_call(wStream* s, GetStatusChangeW_Call* call)
2597{
2598 UINT32 ndrPtr = 0;
2599 UINT32 index = 0;
2600 UINT32 pbContextNdrPtr = 0;
2601
2602 WINPR_ASSERT(call);
2603 wLog* log = scard_log();
2604 call->rgReaderStates = NULL;
2605
2606 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2607 &pbContextNdrPtr);
2608 if (status != SCARD_S_SUCCESS)
2609 return status;
2610
2611 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2612 return STATUS_BUFFER_TOO_SMALL;
2613
2614 Stream_Read_UINT32(s, call->dwTimeOut); /* dwTimeOut (4 bytes) */
2615 Stream_Read_UINT32(s, call->cReaders); /* cReaders (4 bytes) */
2616 if (!smartcard_ndr_pointer_read(log, s, &index, &ndrPtr))
2617 return ERROR_INVALID_DATA;
2618
2619 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2620 &(call->handles.hContext));
2621 if (status != SCARD_S_SUCCESS)
2622 return status;
2623
2624 if (ndrPtr)
2625 {
2626 status =
2627 smartcard_unpack_reader_state_w(log, s, &call->rgReaderStates, call->cReaders, &index);
2628 if (status != SCARD_S_SUCCESS)
2629 return status;
2630 }
2631 else
2632 {
2633 WLog_Print(log, WLOG_WARN, "ndrPtr=0x%08" PRIx32 ", can not read rgReaderStates", ndrPtr);
2634 return SCARD_E_UNEXPECTED;
2635 }
2636
2637 smartcard_trace_get_status_change_w_call(log, call);
2638 return SCARD_S_SUCCESS;
2639}
2640
2641LONG smartcard_pack_get_status_change_return(wStream* s, const GetStatusChange_Return* ret,
2642 BOOL unicode)
2643{
2644 WINPR_ASSERT(ret);
2645 wLog* log = scard_log();
2646
2647 LONG status = 0;
2648 DWORD cReaders = ret->cReaders;
2649 UINT32 index = 0;
2650
2651 smartcard_trace_get_status_change_return(log, ret, unicode);
2652 if (ret->ReturnCode != SCARD_S_SUCCESS)
2653 cReaders = 0;
2654 if (cReaders == SCARD_AUTOALLOCATE)
2655 cReaders = 0;
2656
2657 if (!Stream_EnsureRemainingCapacity(s, 4))
2658 return SCARD_E_NO_MEMORY;
2659
2660 Stream_Write_UINT32(s, cReaders); /* cReaders (4 bytes) */
2661 if (!smartcard_ndr_pointer_write(s, &index, cReaders))
2662 return SCARD_E_NO_MEMORY;
2663 status = smartcard_ndr_write_state(s, ret->rgReaderStates, cReaders, NDR_PTR_SIMPLE);
2664 if (status != SCARD_S_SUCCESS)
2665 return status;
2666 return ret->ReturnCode;
2667}
2668
2669LONG smartcard_unpack_state_call(wStream* s, State_Call* call)
2670{
2671 UINT32 index = 0;
2672 UINT32 pbContextNdrPtr = 0;
2673
2674 wLog* log = scard_log();
2675
2676 WINPR_ASSERT(call);
2677 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2678 &pbContextNdrPtr);
2679 if (status != SCARD_S_SUCCESS)
2680 return status;
2681
2682 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
2683 if (status != SCARD_S_SUCCESS)
2684 return status;
2685
2686 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
2687 return STATUS_BUFFER_TOO_SMALL;
2688
2689 Stream_Read_INT32(s, call->fpbAtrIsNULL); /* fpbAtrIsNULL (4 bytes) */
2690 Stream_Read_UINT32(s, call->cbAtrLen); /* cbAtrLen (4 bytes) */
2691
2692 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2693 &(call->handles.hContext));
2694 if (status != SCARD_S_SUCCESS)
2695 return status;
2696
2697 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
2698 if (status != SCARD_S_SUCCESS)
2699 return status;
2700
2701 return status;
2702}
2703
2704LONG smartcard_pack_state_return(wStream* s, const State_Return* ret)
2705{
2706 WINPR_ASSERT(ret);
2707 wLog* log = scard_log();
2708 LONG status = 0;
2709 DWORD cbAtrLen = ret->cbAtrLen;
2710 UINT32 index = 0;
2711
2712 smartcard_trace_state_return(log, ret);
2713 if (ret->ReturnCode != SCARD_S_SUCCESS)
2714 cbAtrLen = 0;
2715 if (cbAtrLen == SCARD_AUTOALLOCATE)
2716 cbAtrLen = 0;
2717
2718 Stream_Write_UINT32(s, ret->dwState); /* dwState (4 bytes) */
2719 Stream_Write_UINT32(s, ret->dwProtocol); /* dwProtocol (4 bytes) */
2720 Stream_Write_UINT32(s, cbAtrLen); /* cbAtrLen (4 bytes) */
2721 if (!smartcard_ndr_pointer_write(s, &index, cbAtrLen))
2722 return SCARD_E_NO_MEMORY;
2723 status = smartcard_ndr_write(s, ret->rgAtr, cbAtrLen, 1, NDR_PTR_SIMPLE);
2724 if (status != SCARD_S_SUCCESS)
2725 return status;
2726 return ret->ReturnCode;
2727}
2728
2729LONG smartcard_unpack_status_call(wStream* s, Status_Call* call, BOOL unicode)
2730{
2731 UINT32 index = 0;
2732 UINT32 pbContextNdrPtr = 0;
2733
2734 WINPR_ASSERT(call);
2735 wLog* log = scard_log();
2736
2737 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2738 &pbContextNdrPtr);
2739 if (status != SCARD_S_SUCCESS)
2740 return status;
2741
2742 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
2743 if (status != SCARD_S_SUCCESS)
2744 return status;
2745
2746 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
2747 return STATUS_BUFFER_TOO_SMALL;
2748
2749 Stream_Read_INT32(s, call->fmszReaderNamesIsNULL); /* fmszReaderNamesIsNULL (4 bytes) */
2750 Stream_Read_UINT32(s, call->cchReaderLen); /* cchReaderLen (4 bytes) */
2751 Stream_Read_UINT32(s, call->cbAtrLen); /* cbAtrLen (4 bytes) */
2752
2753 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2754 &(call->handles.hContext));
2755 if (status != SCARD_S_SUCCESS)
2756 return status;
2757
2758 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
2759 if (status != SCARD_S_SUCCESS)
2760 return status;
2761
2762 smartcard_trace_status_call(log, call, unicode);
2763 return status;
2764}
2765
2766LONG smartcard_pack_status_return(wStream* s, const Status_Return* ret, BOOL unicode)
2767{
2768 WINPR_ASSERT(ret);
2769 wLog* log = scard_log();
2770
2771 LONG status = 0;
2772 UINT32 index = 0;
2773 DWORD cBytes = ret->cBytes;
2774
2775 smartcard_trace_status_return(log, ret, unicode);
2776 if (ret->ReturnCode != SCARD_S_SUCCESS)
2777 cBytes = 0;
2778 if (cBytes == SCARD_AUTOALLOCATE)
2779 cBytes = 0;
2780
2781 if (!Stream_EnsureRemainingCapacity(s, 4))
2782 return SCARD_F_INTERNAL_ERROR;
2783
2784 Stream_Write_UINT32(s, cBytes); /* cBytes (4 bytes) */
2785 if (!smartcard_ndr_pointer_write(s, &index, cBytes))
2786 return SCARD_E_NO_MEMORY;
2787
2788 if (!Stream_EnsureRemainingCapacity(s, 44))
2789 return SCARD_F_INTERNAL_ERROR;
2790
2791 Stream_Write_UINT32(s, ret->dwState); /* dwState (4 bytes) */
2792 Stream_Write_UINT32(s, ret->dwProtocol); /* dwProtocol (4 bytes) */
2793 Stream_Write(s, ret->pbAtr, sizeof(ret->pbAtr)); /* pbAtr (32 bytes) */
2794 Stream_Write_UINT32(s, ret->cbAtrLen); /* cbAtrLen (4 bytes) */
2795 status = smartcard_ndr_write(s, ret->mszReaderNames, cBytes, 1, NDR_PTR_SIMPLE);
2796 if (status != SCARD_S_SUCCESS)
2797 return status;
2798 return ret->ReturnCode;
2799}
2800
2801LONG smartcard_unpack_get_attrib_call(wStream* s, GetAttrib_Call* call)
2802{
2803 WINPR_ASSERT(call);
2804 wLog* log = scard_log();
2805 UINT32 index = 0;
2806 UINT32 pbContextNdrPtr = 0;
2807
2808 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2809 &pbContextNdrPtr);
2810 if (status != SCARD_S_SUCCESS)
2811 return status;
2812
2813 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
2814 if (status != SCARD_S_SUCCESS)
2815 return status;
2816
2817 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
2818 return STATUS_BUFFER_TOO_SMALL;
2819
2820 Stream_Read_UINT32(s, call->dwAttrId); /* dwAttrId (4 bytes) */
2821 Stream_Read_INT32(s, call->fpbAttrIsNULL); /* fpbAttrIsNULL (4 bytes) */
2822 Stream_Read_UINT32(s, call->cbAttrLen); /* cbAttrLen (4 bytes) */
2823
2824 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2825 &(call->handles.hContext));
2826 if (status != SCARD_S_SUCCESS)
2827 return status;
2828
2829 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
2830 if (status != SCARD_S_SUCCESS)
2831 return status;
2832
2833 smartcard_trace_get_attrib_call(log, call);
2834 return status;
2835}
2836
2837LONG smartcard_pack_get_attrib_return(wStream* s, const GetAttrib_Return* ret, DWORD dwAttrId,
2838 DWORD cbAttrCallLen)
2839{
2840 WINPR_ASSERT(ret);
2841 wLog* log = scard_log();
2842 LONG status = 0;
2843 DWORD cbAttrLen = 0;
2844 UINT32 index = 0;
2845 smartcard_trace_get_attrib_return(log, ret, dwAttrId);
2846
2847 if (!Stream_EnsureRemainingCapacity(s, 4))
2848 return SCARD_F_INTERNAL_ERROR;
2849
2850 cbAttrLen = ret->cbAttrLen;
2851 if (ret->ReturnCode != SCARD_S_SUCCESS)
2852 cbAttrLen = 0;
2853 if (cbAttrLen == SCARD_AUTOALLOCATE)
2854 cbAttrLen = 0;
2855
2856 if (ret->pbAttr)
2857 {
2858 if (cbAttrCallLen < cbAttrLen)
2859 cbAttrLen = cbAttrCallLen;
2860 }
2861 Stream_Write_UINT32(s, cbAttrLen); /* cbAttrLen (4 bytes) */
2862 if (!smartcard_ndr_pointer_write(s, &index, cbAttrLen))
2863 return SCARD_E_NO_MEMORY;
2864
2865 status = smartcard_ndr_write(s, ret->pbAttr, cbAttrLen, 1, NDR_PTR_SIMPLE);
2866 if (status != SCARD_S_SUCCESS)
2867 return status;
2868 return ret->ReturnCode;
2869}
2870
2871LONG smartcard_unpack_control_call(wStream* s, Control_Call* call)
2872{
2873 WINPR_ASSERT(call);
2874 wLog* log = scard_log();
2875
2876 UINT32 index = 0;
2877 UINT32 pvInBufferNdrPtr = 0;
2878 UINT32 pbContextNdrPtr = 0;
2879
2880 call->pvInBuffer = NULL;
2881
2882 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2883 &pbContextNdrPtr);
2884 if (status != SCARD_S_SUCCESS)
2885 return status;
2886
2887 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
2888 if (status != SCARD_S_SUCCESS)
2889 return status;
2890
2891 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 20))
2892 return STATUS_BUFFER_TOO_SMALL;
2893
2894 Stream_Read_UINT32(s, call->dwControlCode); /* dwControlCode (4 bytes) */
2895 Stream_Read_UINT32(s, call->cbInBufferSize); /* cbInBufferSize (4 bytes) */
2896 if (!smartcard_ndr_pointer_read(log, s, &index,
2897 &pvInBufferNdrPtr)) /* pvInBufferNdrPtr (4 bytes) */
2898 return ERROR_INVALID_DATA;
2899 Stream_Read_INT32(s, call->fpvOutBufferIsNULL); /* fpvOutBufferIsNULL (4 bytes) */
2900 Stream_Read_UINT32(s, call->cbOutBufferSize); /* cbOutBufferSize (4 bytes) */
2901
2902 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
2903 &(call->handles.hContext));
2904 if (status != SCARD_S_SUCCESS)
2905 return status;
2906
2907 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
2908 if (status != SCARD_S_SUCCESS)
2909 return status;
2910
2911 if (pvInBufferNdrPtr)
2912 {
2913 status =
2914 smartcard_ndr_read(log, s, &call->pvInBuffer, call->cbInBufferSize, 1, NDR_PTR_SIMPLE);
2915 if (status != SCARD_S_SUCCESS)
2916 return status;
2917 }
2918
2919 smartcard_trace_control_call(log, call);
2920 return SCARD_S_SUCCESS;
2921}
2922
2923LONG smartcard_pack_control_return(wStream* s, const Control_Return* ret)
2924{
2925 WINPR_ASSERT(ret);
2926 wLog* log = scard_log();
2927
2928 LONG status = 0;
2929 DWORD cbDataLen = ret->cbOutBufferSize;
2930 UINT32 index = 0;
2931
2932 smartcard_trace_control_return(log, ret);
2933 if (ret->ReturnCode != SCARD_S_SUCCESS)
2934 cbDataLen = 0;
2935 if (cbDataLen == SCARD_AUTOALLOCATE)
2936 cbDataLen = 0;
2937
2938 if (!Stream_EnsureRemainingCapacity(s, 4))
2939 return SCARD_F_INTERNAL_ERROR;
2940
2941 Stream_Write_UINT32(s, cbDataLen); /* cbOutBufferSize (4 bytes) */
2942 if (!smartcard_ndr_pointer_write(s, &index, cbDataLen))
2943 return SCARD_E_NO_MEMORY;
2944
2945 status = smartcard_ndr_write(s, ret->pvOutBuffer, cbDataLen, 1, NDR_PTR_SIMPLE);
2946 if (status != SCARD_S_SUCCESS)
2947 return status;
2948 return ret->ReturnCode;
2949}
2950
2951LONG smartcard_unpack_transmit_call(wStream* s, Transmit_Call* call)
2952{
2953 UINT32 length = 0;
2954 BYTE* pbExtraBytes = NULL;
2955 UINT32 pbExtraBytesNdrPtr = 0;
2956 UINT32 pbSendBufferNdrPtr = 0;
2957 UINT32 pioRecvPciNdrPtr = 0;
2958 SCardIO_Request ioSendPci;
2959 SCardIO_Request ioRecvPci;
2960 UINT32 index = 0;
2961 UINT32 pbContextNdrPtr = 0;
2962
2963 WINPR_ASSERT(call);
2964 wLog* log = scard_log();
2965
2966 call->pioSendPci = NULL;
2967 call->pioRecvPci = NULL;
2968 call->pbSendBuffer = NULL;
2969
2970 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
2971 &pbContextNdrPtr);
2972 if (status != SCARD_S_SUCCESS)
2973 return status;
2974
2975 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
2976 if (status != SCARD_S_SUCCESS)
2977 return status;
2978
2979 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 32))
2980 return STATUS_BUFFER_TOO_SMALL;
2981
2982 Stream_Read_UINT32(s, ioSendPci.dwProtocol); /* dwProtocol (4 bytes) */
2983 Stream_Read_UINT32(s, ioSendPci.cbExtraBytes); /* cbExtraBytes (4 bytes) */
2984 if (!smartcard_ndr_pointer_read(log, s, &index,
2985 &pbExtraBytesNdrPtr)) /* pbExtraBytesNdrPtr (4 bytes) */
2986 return ERROR_INVALID_DATA;
2987
2988 Stream_Read_UINT32(s, call->cbSendLength); /* cbSendLength (4 bytes) */
2989 if (!smartcard_ndr_pointer_read(log, s, &index,
2990 &pbSendBufferNdrPtr)) /* pbSendBufferNdrPtr (4 bytes) */
2991 return ERROR_INVALID_DATA;
2992
2993 if (!smartcard_ndr_pointer_read(log, s, &index,
2994 &pioRecvPciNdrPtr)) /* pioRecvPciNdrPtr (4 bytes) */
2995 return ERROR_INVALID_DATA;
2996
2997 Stream_Read_INT32(s, call->fpbRecvBufferIsNULL); /* fpbRecvBufferIsNULL (4 bytes) */
2998 Stream_Read_UINT32(s, call->cbRecvLength); /* cbRecvLength (4 bytes) */
2999
3000 if (ioSendPci.cbExtraBytes > 1024)
3001 {
3002 WLog_Print(log, WLOG_WARN,
3003 "Transmit_Call ioSendPci.cbExtraBytes is out of bounds: %" PRIu32 " (max: 1024)",
3004 ioSendPci.cbExtraBytes);
3005 return STATUS_INVALID_PARAMETER;
3006 }
3007
3008 if (call->cbSendLength > 66560)
3009 {
3010 WLog_Print(log, WLOG_WARN,
3011 "Transmit_Call cbSendLength is out of bounds: %" PRIu32 " (max: 66560)",
3012 ioSendPci.cbExtraBytes);
3013 return STATUS_INVALID_PARAMETER;
3014 }
3015
3016 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3017 &(call->handles.hContext));
3018 if (status != SCARD_S_SUCCESS)
3019 return status;
3020
3021 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
3022 if (status != SCARD_S_SUCCESS)
3023 return status;
3024
3025 if (ioSendPci.cbExtraBytes && !pbExtraBytesNdrPtr)
3026 {
3027 WLog_Print(
3028 log, WLOG_WARN,
3029 "Transmit_Call ioSendPci.cbExtraBytes is non-zero but pbExtraBytesNdrPtr is null");
3030 return STATUS_INVALID_PARAMETER;
3031 }
3032
3033 if (pbExtraBytesNdrPtr)
3034 {
3035 // TODO: Use unified pointer reading
3036 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
3037 return STATUS_BUFFER_TOO_SMALL;
3038
3039 Stream_Read_UINT32(s, length); /* Length (4 bytes) */
3040
3041 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, ioSendPci.cbExtraBytes))
3042 return STATUS_BUFFER_TOO_SMALL;
3043
3044 ioSendPci.pbExtraBytes = Stream_Pointer(s);
3045 call->pioSendPci =
3046 (LPSCARD_IO_REQUEST)malloc(sizeof(SCARD_IO_REQUEST) + ioSendPci.cbExtraBytes);
3047
3048 if (!call->pioSendPci)
3049 {
3050 WLog_Print(log, WLOG_WARN, "Transmit_Call out of memory error (pioSendPci)");
3051 return STATUS_NO_MEMORY;
3052 }
3053
3054 call->pioSendPci->dwProtocol = ioSendPci.dwProtocol;
3055 call->pioSendPci->cbPciLength = (DWORD)(ioSendPci.cbExtraBytes + sizeof(SCARD_IO_REQUEST));
3056 pbExtraBytes = &((BYTE*)call->pioSendPci)[sizeof(SCARD_IO_REQUEST)];
3057 Stream_Read(s, pbExtraBytes, ioSendPci.cbExtraBytes);
3058 smartcard_unpack_read_size_align(s, ioSendPci.cbExtraBytes, 4);
3059 }
3060 else
3061 {
3062 call->pioSendPci = (LPSCARD_IO_REQUEST)calloc(1, sizeof(SCARD_IO_REQUEST));
3063
3064 if (!call->pioSendPci)
3065 {
3066 WLog_Print(log, WLOG_WARN, "Transmit_Call out of memory error (pioSendPci)");
3067 return STATUS_NO_MEMORY;
3068 }
3069
3070 call->pioSendPci->dwProtocol = ioSendPci.dwProtocol;
3071 call->pioSendPci->cbPciLength = sizeof(SCARD_IO_REQUEST);
3072 }
3073
3074 if (pbSendBufferNdrPtr)
3075 {
3076 status =
3077 smartcard_ndr_read(log, s, &call->pbSendBuffer, call->cbSendLength, 1, NDR_PTR_SIMPLE);
3078 if (status != SCARD_S_SUCCESS)
3079 return status;
3080 }
3081
3082 if (pioRecvPciNdrPtr)
3083 {
3084 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
3085 return STATUS_BUFFER_TOO_SMALL;
3086
3087 Stream_Read_UINT32(s, ioRecvPci.dwProtocol); /* dwProtocol (4 bytes) */
3088 Stream_Read_UINT32(s, ioRecvPci.cbExtraBytes); /* cbExtraBytes (4 bytes) */
3089 if (!smartcard_ndr_pointer_read(log, s, &index,
3090 &pbExtraBytesNdrPtr)) /* pbExtraBytesNdrPtr (4 bytes) */
3091 return ERROR_INVALID_DATA;
3092
3093 if (ioRecvPci.cbExtraBytes && !pbExtraBytesNdrPtr)
3094 {
3095 WLog_Print(
3096 log, WLOG_WARN,
3097 "Transmit_Call ioRecvPci.cbExtraBytes is non-zero but pbExtraBytesNdrPtr is null");
3098 return STATUS_INVALID_PARAMETER;
3099 }
3100
3101 if (pbExtraBytesNdrPtr)
3102 {
3103 // TODO: Unify ndr pointer reading
3104 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
3105 return STATUS_BUFFER_TOO_SMALL;
3106
3107 Stream_Read_UINT32(s, length); /* Length (4 bytes) */
3108
3109 if (ioRecvPci.cbExtraBytes > 1024)
3110 {
3111 WLog_Print(log, WLOG_WARN,
3112 "Transmit_Call ioRecvPci.cbExtraBytes is out of bounds: %" PRIu32
3113 " (max: 1024)",
3114 ioRecvPci.cbExtraBytes);
3115 return STATUS_INVALID_PARAMETER;
3116 }
3117
3118 if (length != ioRecvPci.cbExtraBytes)
3119 {
3120 WLog_Print(log, WLOG_WARN,
3121 "Transmit_Call unexpected length: Actual: %" PRIu32
3122 ", Expected: %" PRIu32 " (ioRecvPci.cbExtraBytes)",
3123 length, ioRecvPci.cbExtraBytes);
3124 return STATUS_INVALID_PARAMETER;
3125 }
3126
3127 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, ioRecvPci.cbExtraBytes))
3128 return STATUS_BUFFER_TOO_SMALL;
3129
3130 ioRecvPci.pbExtraBytes = Stream_Pointer(s);
3131 call->pioRecvPci =
3132 (LPSCARD_IO_REQUEST)malloc(sizeof(SCARD_IO_REQUEST) + ioRecvPci.cbExtraBytes);
3133
3134 if (!call->pioRecvPci)
3135 {
3136 WLog_Print(log, WLOG_WARN, "Transmit_Call out of memory error (pioRecvPci)");
3137 return STATUS_NO_MEMORY;
3138 }
3139
3140 call->pioRecvPci->dwProtocol = ioRecvPci.dwProtocol;
3141 call->pioRecvPci->cbPciLength =
3142 (DWORD)(ioRecvPci.cbExtraBytes + sizeof(SCARD_IO_REQUEST));
3143 pbExtraBytes = &((BYTE*)call->pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
3144 Stream_Read(s, pbExtraBytes, ioRecvPci.cbExtraBytes);
3145 smartcard_unpack_read_size_align(s, ioRecvPci.cbExtraBytes, 4);
3146 }
3147 else
3148 {
3149 call->pioRecvPci = (LPSCARD_IO_REQUEST)calloc(1, sizeof(SCARD_IO_REQUEST));
3150
3151 if (!call->pioRecvPci)
3152 {
3153 WLog_Print(log, WLOG_WARN, "Transmit_Call out of memory error (pioRecvPci)");
3154 return STATUS_NO_MEMORY;
3155 }
3156
3157 call->pioRecvPci->dwProtocol = ioRecvPci.dwProtocol;
3158 call->pioRecvPci->cbPciLength = sizeof(SCARD_IO_REQUEST);
3159 }
3160 }
3161
3162 smartcard_trace_transmit_call(log, call);
3163 return SCARD_S_SUCCESS;
3164}
3165
3166LONG smartcard_pack_transmit_return(wStream* s, const Transmit_Return* ret)
3167{
3168 WINPR_ASSERT(ret);
3169 wLog* log = scard_log();
3170
3171 LONG status = 0;
3172 UINT32 index = 0;
3173 LONG error = 0;
3174 UINT32 cbRecvLength = ret->cbRecvLength;
3175 UINT32 cbRecvPci = ret->pioRecvPci ? ret->pioRecvPci->cbPciLength : 0;
3176
3177 smartcard_trace_transmit_return(log, ret);
3178
3179 if (!ret->pbRecvBuffer)
3180 cbRecvLength = 0;
3181
3182 if (!smartcard_ndr_pointer_write(s, &index, cbRecvPci))
3183 return SCARD_E_NO_MEMORY;
3184 if (!Stream_EnsureRemainingCapacity(s, 4))
3185 return SCARD_E_NO_MEMORY;
3186 Stream_Write_UINT32(s, cbRecvLength); /* cbRecvLength (4 bytes) */
3187 if (!smartcard_ndr_pointer_write(s, &index, cbRecvLength))
3188 return SCARD_E_NO_MEMORY;
3189
3190 if (ret->pioRecvPci)
3191 {
3192 UINT32 cbExtraBytes = (UINT32)(ret->pioRecvPci->cbPciLength - sizeof(SCARD_IO_REQUEST));
3193 BYTE* pbExtraBytes = &((BYTE*)ret->pioRecvPci)[sizeof(SCARD_IO_REQUEST)];
3194
3195 if (!Stream_EnsureRemainingCapacity(s, cbExtraBytes + 16))
3196 {
3197 WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
3198 return SCARD_F_INTERNAL_ERROR;
3199 }
3200
3201 Stream_Write_UINT32(s, ret->pioRecvPci->dwProtocol); /* dwProtocol (4 bytes) */
3202 Stream_Write_UINT32(s, cbExtraBytes); /* cbExtraBytes (4 bytes) */
3203 if (!smartcard_ndr_pointer_write(s, &index, cbExtraBytes))
3204 return SCARD_E_NO_MEMORY;
3205 error = smartcard_ndr_write(s, pbExtraBytes, cbExtraBytes, 1, NDR_PTR_SIMPLE);
3206 if (error)
3207 return error;
3208 }
3209
3210 status = smartcard_ndr_write(s, ret->pbRecvBuffer, ret->cbRecvLength, 1, NDR_PTR_SIMPLE);
3211 if (status != SCARD_S_SUCCESS)
3212 return status;
3213 return ret->ReturnCode;
3214}
3215
3216LONG smartcard_unpack_locate_cards_by_atr_a_call(wStream* s, LocateCardsByATRA_Call* call)
3217{
3218 UINT32 rgReaderStatesNdrPtr = 0;
3219 UINT32 rgAtrMasksNdrPtr = 0;
3220 UINT32 index = 0;
3221 UINT32 pbContextNdrPtr = 0;
3222
3223 WINPR_ASSERT(call);
3224 wLog* log = scard_log();
3225
3226 call->rgReaderStates = NULL;
3227
3228 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3229 &pbContextNdrPtr);
3230 if (status != SCARD_S_SUCCESS)
3231 return status;
3232
3233 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 16))
3234 return STATUS_BUFFER_TOO_SMALL;
3235
3236 Stream_Read_UINT32(s, call->cAtrs);
3237 if (!smartcard_ndr_pointer_read(log, s, &index, &rgAtrMasksNdrPtr))
3238 return ERROR_INVALID_DATA;
3239 Stream_Read_UINT32(s, call->cReaders); /* cReaders (4 bytes) */
3240 if (!smartcard_ndr_pointer_read(log, s, &index, &rgReaderStatesNdrPtr))
3241 return ERROR_INVALID_DATA;
3242
3243 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3244 &(call->handles.hContext));
3245 if (status != SCARD_S_SUCCESS)
3246 return status;
3247
3248 if ((rgAtrMasksNdrPtr && !call->cAtrs) || (!rgAtrMasksNdrPtr && call->cAtrs))
3249 {
3250 WLog_Print(log, WLOG_WARN,
3251 "LocateCardsByATRA_Call rgAtrMasksNdrPtr (0x%08" PRIX32
3252 ") and cAtrs (0x%08" PRIX32 ") inconsistency",
3253 rgAtrMasksNdrPtr, call->cAtrs);
3254 return STATUS_INVALID_PARAMETER;
3255 }
3256
3257 if (rgAtrMasksNdrPtr)
3258 {
3259 status = smartcard_ndr_read_atrmask(log, s, &call->rgAtrMasks, call->cAtrs, NDR_PTR_SIMPLE);
3260 if (status != SCARD_S_SUCCESS)
3261 return status;
3262 }
3263
3264 if (rgReaderStatesNdrPtr)
3265 {
3266 status =
3267 smartcard_unpack_reader_state_a(log, s, &call->rgReaderStates, call->cReaders, &index);
3268 if (status != SCARD_S_SUCCESS)
3269 return status;
3270 }
3271
3272 smartcard_trace_locate_cards_by_atr_a_call(log, call);
3273 return SCARD_S_SUCCESS;
3274}
3275
3276LONG smartcard_unpack_context_and_two_strings_a_call(wStream* s, ContextAndTwoStringA_Call* call)
3277{
3278 UINT32 sz1NdrPtr = 0;
3279 UINT32 sz2NdrPtr = 0;
3280 UINT32 index = 0;
3281 UINT32 pbContextNdrPtr = 0;
3282
3283 WINPR_ASSERT(call);
3284 wLog* log = scard_log();
3285
3286 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3287 &pbContextNdrPtr);
3288 if (status != SCARD_S_SUCCESS)
3289 return status;
3290
3291 if (!smartcard_ndr_pointer_read(log, s, &index, &sz1NdrPtr))
3292 return ERROR_INVALID_DATA;
3293 if (!smartcard_ndr_pointer_read(log, s, &index, &sz2NdrPtr))
3294 return ERROR_INVALID_DATA;
3295
3296 status =
3297 smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr, &call->handles.hContext);
3298 if (status != SCARD_S_SUCCESS)
3299 return status;
3300
3301 if (sz1NdrPtr)
3302 {
3303 status = smartcard_ndr_read_a(log, s, &call->sz1, NDR_PTR_FULL);
3304 if (status != SCARD_S_SUCCESS)
3305 return status;
3306 }
3307 if (sz2NdrPtr)
3308 {
3309 status = smartcard_ndr_read_a(log, s, &call->sz2, NDR_PTR_FULL);
3310 if (status != SCARD_S_SUCCESS)
3311 return status;
3312 }
3313 smartcard_trace_context_and_two_strings_a_call(log, call);
3314 return SCARD_S_SUCCESS;
3315}
3316
3317LONG smartcard_unpack_context_and_two_strings_w_call(wStream* s, ContextAndTwoStringW_Call* call)
3318{
3319 UINT32 sz1NdrPtr = 0;
3320 UINT32 sz2NdrPtr = 0;
3321 UINT32 index = 0;
3322 UINT32 pbContextNdrPtr = 0;
3323
3324 WINPR_ASSERT(call);
3325 wLog* log = scard_log();
3326
3327 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3328 &pbContextNdrPtr);
3329 if (status != SCARD_S_SUCCESS)
3330 return status;
3331
3332 if (!smartcard_ndr_pointer_read(log, s, &index, &sz1NdrPtr))
3333 return ERROR_INVALID_DATA;
3334 if (!smartcard_ndr_pointer_read(log, s, &index, &sz2NdrPtr))
3335 return ERROR_INVALID_DATA;
3336
3337 status =
3338 smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr, &call->handles.hContext);
3339 if (status != SCARD_S_SUCCESS)
3340 return status;
3341
3342 if (sz1NdrPtr)
3343 {
3344 status = smartcard_ndr_read_w(log, s, &call->sz1, NDR_PTR_FULL);
3345 if (status != SCARD_S_SUCCESS)
3346 return status;
3347 }
3348 if (sz2NdrPtr)
3349 {
3350 status = smartcard_ndr_read_w(log, s, &call->sz2, NDR_PTR_FULL);
3351 if (status != SCARD_S_SUCCESS)
3352 return status;
3353 }
3354 smartcard_trace_context_and_two_strings_w_call(log, call);
3355 return SCARD_S_SUCCESS;
3356}
3357
3358LONG smartcard_unpack_locate_cards_a_call(wStream* s, LocateCardsA_Call* call)
3359{
3360 UINT32 sz1NdrPtr = 0;
3361 UINT32 sz2NdrPtr = 0;
3362 UINT32 index = 0;
3363 UINT32 pbContextNdrPtr = 0;
3364
3365 WINPR_ASSERT(call);
3366 wLog* log = scard_log();
3367
3368 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3369 &pbContextNdrPtr);
3370 if (status != SCARD_S_SUCCESS)
3371 return status;
3372
3373 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 16))
3374 return STATUS_BUFFER_TOO_SMALL;
3375
3376 Stream_Read_UINT32(s, call->cBytes);
3377 if (!smartcard_ndr_pointer_read(log, s, &index, &sz1NdrPtr))
3378 return ERROR_INVALID_DATA;
3379
3380 Stream_Read_UINT32(s, call->cReaders);
3381 if (!smartcard_ndr_pointer_read(log, s, &index, &sz2NdrPtr))
3382 return ERROR_INVALID_DATA;
3383
3384 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3385 &(call->handles.hContext));
3386 if (status != SCARD_S_SUCCESS)
3387 return status;
3388
3389 if (sz1NdrPtr)
3390 {
3391 status = smartcard_ndr_read_fixed_string_a(log, s, &call->mszCards, call->cBytes,
3392 NDR_PTR_SIMPLE);
3393 if (status != SCARD_S_SUCCESS)
3394 return status;
3395 }
3396 if (sz2NdrPtr)
3397 {
3398 status =
3399 smartcard_unpack_reader_state_a(log, s, &call->rgReaderStates, call->cReaders, &index);
3400 if (status != SCARD_S_SUCCESS)
3401 return status;
3402 }
3403 smartcard_trace_locate_cards_a_call(log, call);
3404 return SCARD_S_SUCCESS;
3405}
3406
3407LONG smartcard_unpack_locate_cards_w_call(wStream* s, LocateCardsW_Call* call)
3408{
3409 UINT32 sz1NdrPtr = 0;
3410 UINT32 sz2NdrPtr = 0;
3411 UINT32 index = 0;
3412 UINT32 pbContextNdrPtr = 0;
3413
3414 WINPR_ASSERT(call);
3415 wLog* log = scard_log();
3416
3417 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3418 &pbContextNdrPtr);
3419 if (status != SCARD_S_SUCCESS)
3420 return status;
3421
3422 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 16))
3423 return STATUS_BUFFER_TOO_SMALL;
3424
3425 Stream_Read_UINT32(s, call->cBytes);
3426 if (!smartcard_ndr_pointer_read(log, s, &index, &sz1NdrPtr))
3427 return ERROR_INVALID_DATA;
3428
3429 Stream_Read_UINT32(s, call->cReaders);
3430 if (!smartcard_ndr_pointer_read(log, s, &index, &sz2NdrPtr))
3431 return ERROR_INVALID_DATA;
3432
3433 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3434 &(call->handles.hContext));
3435 if (status != SCARD_S_SUCCESS)
3436 return status;
3437
3438 if (sz1NdrPtr)
3439 {
3440 status = smartcard_ndr_read_fixed_string_w(log, s, &call->mszCards, call->cBytes,
3441 NDR_PTR_SIMPLE);
3442 if (status != SCARD_S_SUCCESS)
3443 return status;
3444 }
3445 if (sz2NdrPtr)
3446 {
3447 status =
3448 smartcard_unpack_reader_state_w(log, s, &call->rgReaderStates, call->cReaders, &index);
3449 if (status != SCARD_S_SUCCESS)
3450 return status;
3451 }
3452 smartcard_trace_locate_cards_w_call(log, call);
3453 return SCARD_S_SUCCESS;
3454}
3455
3456LONG smartcard_unpack_set_attrib_call(wStream* s, SetAttrib_Call* call)
3457{
3458 UINT32 index = 0;
3459 UINT32 ndrPtr = 0;
3460 UINT32 pbContextNdrPtr = 0;
3461
3462 WINPR_ASSERT(call);
3463 wLog* log = scard_log();
3464
3465 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3466 &pbContextNdrPtr);
3467 if (status != SCARD_S_SUCCESS)
3468 return status;
3469 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
3470 if (status != SCARD_S_SUCCESS)
3471 return status;
3472
3473 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
3474 return STATUS_BUFFER_TOO_SMALL;
3475 Stream_Read_UINT32(s, call->dwAttrId);
3476 Stream_Read_UINT32(s, call->cbAttrLen);
3477
3478 if (!smartcard_ndr_pointer_read(log, s, &index, &ndrPtr))
3479 return ERROR_INVALID_DATA;
3480
3481 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3482 &(call->handles.hContext));
3483 if (status != SCARD_S_SUCCESS)
3484 return status;
3485
3486 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
3487 if (status != SCARD_S_SUCCESS)
3488 return status;
3489
3490 if (ndrPtr)
3491 {
3492 // TODO: call->cbAttrLen was larger than the pointer value.
3493 // TODO: Maybe need to refine the checks?
3494 status = smartcard_ndr_read(log, s, &call->pbAttr, 0, 1, NDR_PTR_SIMPLE);
3495 if (status != SCARD_S_SUCCESS)
3496 return status;
3497 }
3498 smartcard_trace_set_attrib_call(log, call);
3499 return SCARD_S_SUCCESS;
3500}
3501
3502LONG smartcard_unpack_locate_cards_by_atr_w_call(wStream* s, LocateCardsByATRW_Call* call)
3503{
3504 UINT32 rgReaderStatesNdrPtr = 0;
3505 UINT32 rgAtrMasksNdrPtr = 0;
3506 UINT32 index = 0;
3507 UINT32 pbContextNdrPtr = 0;
3508
3509 WINPR_ASSERT(call);
3510 wLog* log = scard_log();
3511
3512 call->rgReaderStates = NULL;
3513
3514 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3515 &pbContextNdrPtr);
3516 if (status != SCARD_S_SUCCESS)
3517 return status;
3518
3519 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 16))
3520 return STATUS_BUFFER_TOO_SMALL;
3521
3522 Stream_Read_UINT32(s, call->cAtrs);
3523 if (!smartcard_ndr_pointer_read(log, s, &index, &rgAtrMasksNdrPtr))
3524 return ERROR_INVALID_DATA;
3525
3526 Stream_Read_UINT32(s, call->cReaders); /* cReaders (4 bytes) */
3527 if (!smartcard_ndr_pointer_read(log, s, &index, &rgReaderStatesNdrPtr))
3528 return ERROR_INVALID_DATA;
3529
3530 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3531 &(call->handles.hContext));
3532 if (status != SCARD_S_SUCCESS)
3533 return status;
3534
3535 if ((rgAtrMasksNdrPtr && !call->cAtrs) || (!rgAtrMasksNdrPtr && call->cAtrs))
3536 {
3537 WLog_Print(log, WLOG_WARN,
3538 "LocateCardsByATRW_Call rgAtrMasksNdrPtr (0x%08" PRIX32
3539 ") and cAtrs (0x%08" PRIX32 ") inconsistency",
3540 rgAtrMasksNdrPtr, call->cAtrs);
3541 return STATUS_INVALID_PARAMETER;
3542 }
3543
3544 if (rgAtrMasksNdrPtr)
3545 {
3546 status = smartcard_ndr_read_atrmask(log, s, &call->rgAtrMasks, call->cAtrs, NDR_PTR_SIMPLE);
3547 if (status != SCARD_S_SUCCESS)
3548 return status;
3549 }
3550
3551 if (rgReaderStatesNdrPtr)
3552 {
3553 status =
3554 smartcard_unpack_reader_state_w(log, s, &call->rgReaderStates, call->cReaders, &index);
3555 if (status != SCARD_S_SUCCESS)
3556 return status;
3557 }
3558
3559 smartcard_trace_locate_cards_by_atr_w_call(log, call);
3560 return SCARD_S_SUCCESS;
3561}
3562
3563LONG smartcard_unpack_read_cache_a_call(wStream* s, ReadCacheA_Call* call)
3564{
3565 UINT32 mszNdrPtr = 0;
3566 UINT32 contextNdrPtr = 0;
3567 UINT32 index = 0;
3568 UINT32 pbContextNdrPtr = 0;
3569
3570 WINPR_ASSERT(call);
3571 wLog* log = scard_log();
3572
3573 if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
3574 return ERROR_INVALID_DATA;
3575
3576 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->Common.handles.hContext),
3577 &index, &pbContextNdrPtr);
3578 if (status != SCARD_S_SUCCESS)
3579 return status;
3580
3581 if (!smartcard_ndr_pointer_read(log, s, &index, &contextNdrPtr))
3582 return ERROR_INVALID_DATA;
3583
3584 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
3585 return STATUS_BUFFER_TOO_SMALL;
3586 Stream_Read_UINT32(s, call->Common.FreshnessCounter);
3587 Stream_Read_INT32(s, call->Common.fPbDataIsNULL);
3588 Stream_Read_UINT32(s, call->Common.cbDataLen);
3589
3590 call->szLookupName = NULL;
3591 if (mszNdrPtr)
3592 {
3593 status = smartcard_ndr_read_a(log, s, &call->szLookupName, NDR_PTR_FULL);
3594 if (status != SCARD_S_SUCCESS)
3595 return status;
3596 }
3597
3598 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3599 &call->Common.handles.hContext);
3600 if (status != SCARD_S_SUCCESS)
3601 return status;
3602
3603 if (contextNdrPtr)
3604 {
3605 status = smartcard_ndr_read_u(log, s, &call->Common.CardIdentifier);
3606 if (status != SCARD_S_SUCCESS)
3607 return status;
3608 }
3609 smartcard_trace_read_cache_a_call(log, call);
3610 return SCARD_S_SUCCESS;
3611}
3612
3613LONG smartcard_unpack_read_cache_w_call(wStream* s, ReadCacheW_Call* call)
3614{
3615 UINT32 mszNdrPtr = 0;
3616 UINT32 contextNdrPtr = 0;
3617 UINT32 index = 0;
3618 UINT32 pbContextNdrPtr = 0;
3619
3620 WINPR_ASSERT(call);
3621 wLog* log = scard_log();
3622
3623 if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
3624 return ERROR_INVALID_DATA;
3625
3626 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->Common.handles.hContext),
3627 &index, &pbContextNdrPtr);
3628 if (status != SCARD_S_SUCCESS)
3629 return status;
3630
3631 if (!smartcard_ndr_pointer_read(log, s, &index, &contextNdrPtr))
3632 return ERROR_INVALID_DATA;
3633
3634 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 12))
3635 return STATUS_BUFFER_TOO_SMALL;
3636 Stream_Read_UINT32(s, call->Common.FreshnessCounter);
3637 Stream_Read_INT32(s, call->Common.fPbDataIsNULL);
3638 Stream_Read_UINT32(s, call->Common.cbDataLen);
3639
3640 call->szLookupName = NULL;
3641 if (mszNdrPtr)
3642 {
3643 status = smartcard_ndr_read_w(log, s, &call->szLookupName, NDR_PTR_FULL);
3644 if (status != SCARD_S_SUCCESS)
3645 return status;
3646 }
3647
3648 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3649 &call->Common.handles.hContext);
3650 if (status != SCARD_S_SUCCESS)
3651 return status;
3652
3653 if (contextNdrPtr)
3654 {
3655 status = smartcard_ndr_read_u(log, s, &call->Common.CardIdentifier);
3656 if (status != SCARD_S_SUCCESS)
3657 return status;
3658 }
3659 smartcard_trace_read_cache_w_call(log, call);
3660 return SCARD_S_SUCCESS;
3661}
3662
3663LONG smartcard_unpack_write_cache_a_call(wStream* s, WriteCacheA_Call* call)
3664{
3665 UINT32 mszNdrPtr = 0;
3666 UINT32 contextNdrPtr = 0;
3667 UINT32 pbDataNdrPtr = 0;
3668 UINT32 index = 0;
3669 UINT32 pbContextNdrPtr = 0;
3670
3671 WINPR_ASSERT(call);
3672 wLog* log = scard_log();
3673
3674 if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
3675 return ERROR_INVALID_DATA;
3676
3677 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->Common.handles.hContext),
3678 &index, &pbContextNdrPtr);
3679 if (status != SCARD_S_SUCCESS)
3680 return status;
3681
3682 if (!smartcard_ndr_pointer_read(log, s, &index, &contextNdrPtr))
3683 return ERROR_INVALID_DATA;
3684
3685 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
3686 return STATUS_BUFFER_TOO_SMALL;
3687
3688 Stream_Read_UINT32(s, call->Common.FreshnessCounter);
3689 Stream_Read_UINT32(s, call->Common.cbDataLen);
3690
3691 if (!smartcard_ndr_pointer_read(log, s, &index, &pbDataNdrPtr))
3692 return ERROR_INVALID_DATA;
3693
3694 call->szLookupName = NULL;
3695 if (mszNdrPtr)
3696 {
3697 status = smartcard_ndr_read_a(log, s, &call->szLookupName, NDR_PTR_FULL);
3698 if (status != SCARD_S_SUCCESS)
3699 return status;
3700 }
3701
3702 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3703 &call->Common.handles.hContext);
3704 if (status != SCARD_S_SUCCESS)
3705 return status;
3706
3707 call->Common.CardIdentifier = NULL;
3708 if (contextNdrPtr)
3709 {
3710 status = smartcard_ndr_read_u(log, s, &call->Common.CardIdentifier);
3711 if (status != SCARD_S_SUCCESS)
3712 return status;
3713 }
3714
3715 call->Common.pbData = NULL;
3716 if (pbDataNdrPtr)
3717 {
3718 status = smartcard_ndr_read(log, s, &call->Common.pbData, call->Common.cbDataLen, 1,
3719 NDR_PTR_SIMPLE);
3720 if (status != SCARD_S_SUCCESS)
3721 return status;
3722 }
3723 smartcard_trace_write_cache_a_call(log, call);
3724 return SCARD_S_SUCCESS;
3725}
3726
3727LONG smartcard_unpack_write_cache_w_call(wStream* s, WriteCacheW_Call* call)
3728{
3729 UINT32 mszNdrPtr = 0;
3730 UINT32 contextNdrPtr = 0;
3731 UINT32 pbDataNdrPtr = 0;
3732 UINT32 index = 0;
3733 UINT32 pbContextNdrPtr = 0;
3734
3735 WINPR_ASSERT(call);
3736 wLog* log = scard_log();
3737
3738 if (!smartcard_ndr_pointer_read(log, s, &index, &mszNdrPtr))
3739 return ERROR_INVALID_DATA;
3740
3741 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->Common.handles.hContext),
3742 &index, &pbContextNdrPtr);
3743 if (status != SCARD_S_SUCCESS)
3744 return status;
3745
3746 if (!smartcard_ndr_pointer_read(log, s, &index, &contextNdrPtr))
3747 return ERROR_INVALID_DATA;
3748
3749 if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 8))
3750 return STATUS_BUFFER_TOO_SMALL;
3751 Stream_Read_UINT32(s, call->Common.FreshnessCounter);
3752 Stream_Read_UINT32(s, call->Common.cbDataLen);
3753
3754 if (!smartcard_ndr_pointer_read(log, s, &index, &pbDataNdrPtr))
3755 return ERROR_INVALID_DATA;
3756
3757 call->szLookupName = NULL;
3758 if (mszNdrPtr)
3759 {
3760 status = smartcard_ndr_read_w(log, s, &call->szLookupName, NDR_PTR_FULL);
3761 if (status != SCARD_S_SUCCESS)
3762 return status;
3763 }
3764
3765 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3766 &call->Common.handles.hContext);
3767 if (status != SCARD_S_SUCCESS)
3768 return status;
3769
3770 call->Common.CardIdentifier = NULL;
3771 if (contextNdrPtr)
3772 {
3773 status = smartcard_ndr_read_u(log, s, &call->Common.CardIdentifier);
3774 if (status != SCARD_S_SUCCESS)
3775 return status;
3776 }
3777
3778 call->Common.pbData = NULL;
3779 if (pbDataNdrPtr)
3780 {
3781 status = smartcard_ndr_read(log, s, &call->Common.pbData, call->Common.cbDataLen, 1,
3782 NDR_PTR_SIMPLE);
3783 if (status != SCARD_S_SUCCESS)
3784 return status;
3785 }
3786 smartcard_trace_write_cache_w_call(log, call);
3787 return status;
3788}
3789
3790LONG smartcard_unpack_get_transmit_count_call(wStream* s, GetTransmitCount_Call* call)
3791{
3792 WINPR_ASSERT(call);
3793 wLog* log = scard_log();
3794
3795 UINT32 index = 0;
3796 UINT32 pbContextNdrPtr = 0;
3797
3798 LONG status = smartcard_unpack_redir_scard_context(log, s, &(call->handles.hContext), &index,
3799 &pbContextNdrPtr);
3800 if (status != SCARD_S_SUCCESS)
3801 return status;
3802
3803 status = smartcard_unpack_redir_scard_handle(log, s, &(call->handles.hCard), &index);
3804 if (status != SCARD_S_SUCCESS)
3805 return status;
3806
3807 status = smartcard_unpack_redir_scard_context_ref(log, s, pbContextNdrPtr,
3808 &(call->handles.hContext));
3809 if (status != SCARD_S_SUCCESS)
3810 {
3811 WLog_Print(log, WLOG_ERROR,
3812 "smartcard_unpack_redir_scard_context_ref failed with error %" PRId32 "",
3813 status);
3814 return status;
3815 }
3816
3817 status = smartcard_unpack_redir_scard_handle_ref(log, s, &(call->handles.hCard));
3818 if (status != SCARD_S_SUCCESS)
3819 WLog_Print(log, WLOG_ERROR,
3820 "smartcard_unpack_redir_scard_handle_ref failed with error %" PRId32 "", status);
3821
3822 smartcard_trace_get_transmit_count_call(log, call);
3823 return status;
3824}
3825
3826LONG smartcard_unpack_get_reader_icon_call(wStream* s, GetReaderIcon_Call* call)
3827{
3828 WINPR_ASSERT(call);
3829 wLog* log = scard_log();
3830 return smartcard_unpack_common_context_and_string_w(log, s, &call->handles.hContext,
3831 &call->szReaderName);
3832}
3833
3834LONG smartcard_unpack_context_and_string_a_call(wStream* s, ContextAndStringA_Call* call)
3835{
3836 WINPR_ASSERT(call);
3837 wLog* log = scard_log();
3838 return smartcard_unpack_common_context_and_string_a(log, s, &call->handles.hContext, &call->sz);
3839}
3840
3841LONG smartcard_unpack_context_and_string_w_call(wStream* s, ContextAndStringW_Call* call)
3842{
3843 WINPR_ASSERT(call);
3844 wLog* log = scard_log();
3845 return smartcard_unpack_common_context_and_string_w(log, s, &call->handles.hContext, &call->sz);
3846}
3847
3848LONG smartcard_unpack_get_device_type_id_call(wStream* s, GetDeviceTypeId_Call* call)
3849{
3850 WINPR_ASSERT(call);
3851 wLog* log = scard_log();
3852 return smartcard_unpack_common_context_and_string_w(log, s, &call->handles.hContext,
3853 &call->szReaderName);
3854}
3855
3856LONG smartcard_pack_device_type_id_return(wStream* s, const GetDeviceTypeId_Return* ret)
3857{
3858 WINPR_ASSERT(ret);
3859 wLog* log = scard_log();
3860 smartcard_trace_device_type_id_return(log, ret);
3861
3862 if (!Stream_EnsureRemainingCapacity(s, 4))
3863 {
3864 WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
3865 return SCARD_F_INTERNAL_ERROR;
3866 }
3867
3868 Stream_Write_UINT32(s, ret->dwDeviceId); /* cBytes (4 bytes) */
3869
3870 return ret->ReturnCode;
3871}
3872
3873LONG smartcard_pack_locate_cards_return(wStream* s, const LocateCards_Return* ret)
3874{
3875 WINPR_ASSERT(ret);
3876 wLog* log = scard_log();
3877
3878 LONG status = 0;
3879 DWORD cbDataLen = ret->cReaders;
3880 UINT32 index = 0;
3881
3882 smartcard_trace_locate_cards_return(log, ret);
3883 if (ret->ReturnCode != SCARD_S_SUCCESS)
3884 cbDataLen = 0;
3885 if (cbDataLen == SCARD_AUTOALLOCATE)
3886 cbDataLen = 0;
3887
3888 if (!Stream_EnsureRemainingCapacity(s, 4))
3889 {
3890 WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
3891 return SCARD_F_INTERNAL_ERROR;
3892 }
3893
3894 Stream_Write_UINT32(s, cbDataLen); /* cBytes (4 cbDataLen) */
3895 if (!smartcard_ndr_pointer_write(s, &index, cbDataLen))
3896 return SCARD_E_NO_MEMORY;
3897
3898 status = smartcard_ndr_write_state(s, ret->rgReaderStates, cbDataLen, NDR_PTR_SIMPLE);
3899 if (status != SCARD_S_SUCCESS)
3900 return status;
3901 return ret->ReturnCode;
3902}
3903
3904LONG smartcard_pack_get_reader_icon_return(wStream* s, const GetReaderIcon_Return* ret)
3905{
3906 WINPR_ASSERT(ret);
3907 wLog* log = scard_log();
3908
3909 LONG status = 0;
3910 UINT32 index = 0;
3911 DWORD cbDataLen = ret->cbDataLen;
3912 smartcard_trace_get_reader_icon_return(log, ret);
3913 if (ret->ReturnCode != SCARD_S_SUCCESS)
3914 cbDataLen = 0;
3915 if (cbDataLen == SCARD_AUTOALLOCATE)
3916 cbDataLen = 0;
3917
3918 if (!Stream_EnsureRemainingCapacity(s, 4))
3919 {
3920 WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
3921 return SCARD_F_INTERNAL_ERROR;
3922 }
3923
3924 Stream_Write_UINT32(s, cbDataLen); /* cBytes (4 cbDataLen) */
3925 if (!smartcard_ndr_pointer_write(s, &index, cbDataLen))
3926 return SCARD_E_NO_MEMORY;
3927
3928 status = smartcard_ndr_write(s, ret->pbData, cbDataLen, 1, NDR_PTR_SIMPLE);
3929 if (status != SCARD_S_SUCCESS)
3930 return status;
3931 return ret->ReturnCode;
3932}
3933
3934LONG smartcard_pack_get_transmit_count_return(wStream* s, const GetTransmitCount_Return* ret)
3935{
3936 WINPR_ASSERT(ret);
3937 wLog* log = scard_log();
3938
3939 smartcard_trace_get_transmit_count_return(log, ret);
3940
3941 if (!Stream_EnsureRemainingCapacity(s, 4))
3942 {
3943 WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
3944 return SCARD_F_INTERNAL_ERROR;
3945 }
3946
3947 Stream_Write_UINT32(s, ret->cTransmitCount); /* cBytes (4 cbDataLen) */
3948
3949 return ret->ReturnCode;
3950}
3951
3952LONG smartcard_pack_read_cache_return(wStream* s, const ReadCache_Return* ret)
3953{
3954 WINPR_ASSERT(ret);
3955 wLog* log = scard_log();
3956
3957 LONG status = 0;
3958 UINT32 index = 0;
3959 DWORD cbDataLen = ret->cbDataLen;
3960 smartcard_trace_read_cache_return(log, ret);
3961 if (ret->ReturnCode != SCARD_S_SUCCESS)
3962 cbDataLen = 0;
3963
3964 if (cbDataLen == SCARD_AUTOALLOCATE)
3965 cbDataLen = 0;
3966
3967 if (!Stream_EnsureRemainingCapacity(s, 4))
3968 {
3969 WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
3970 return SCARD_F_INTERNAL_ERROR;
3971 }
3972
3973 Stream_Write_UINT32(s, cbDataLen); /* cBytes (4 cbDataLen) */
3974 if (!smartcard_ndr_pointer_write(s, &index, cbDataLen))
3975 return SCARD_E_NO_MEMORY;
3976
3977 status = smartcard_ndr_write(s, ret->pbData, cbDataLen, 1, NDR_PTR_SIMPLE);
3978 if (status != SCARD_S_SUCCESS)
3979 return status;
3980 return ret->ReturnCode;
3981}
Definition wtypes.h:254