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