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