Ну, я нашел решение. Я скачал исходный код PC/SC-Sharp с их страницы GitHub и начал анализировать, проблема была в методе SCardListReaders с параметром pcchReaders
, который слишком мал и вызывает исключение, из MSDN:
Длина буфера mszReaders в символах. Этот параметр получает фактическую длину многострочной структуры, включая все нулевые символы в конце. Если длина буфера указана как SCARD_AUTOALLOCATE, то mszReaders преобразуется в указатель на указатель байта и получает адрес блока памяти, содержащего многострочную структуру. Этот блок памяти должен быть освобожден с помощью SCardFreeMemory.
внутри метода ListReaders
(WinSCardAPI) pcsc-sharp вызывается следующим образом:
public SCardError ListReaders(IntPtr hContext, string[] groups, out string[] readers) {
var dwReaders = 0;
// initialize groups array
byte[] mszGroups = null;
if (groups != null)
mszGroups = SCardHelper.ConvertToByteArray(groups, TextEncoding);
// determine the needed buffer size
var rc = SCardHelper.ToSCardError(
SCardListReaders(hContext,
mszGroups,
null,
ref dwReaders));
if (rc != SCardError.Success) {
readers = null;
return rc;
}
// initialize array
var mszReaders = new byte[dwReaders * sizeof(char)];
rc = SCardHelper.ToSCardError(
SCardListReaders(hContext,
mszGroups,
mszReaders,
ref dwReaders));
readers = (rc == SCardError.Success)
? SCardHelper.ConvertToStringArray(mszReaders, TextEncoding)
: null;
return rc;
}
В первый раз он вызывал метод SCardListReaders
для определения необходимого размера буфера с параметром mszReaders
, установленным на null
, поэтому, согласно MSDN:
Многострочный список устройств чтения карт в предоставленных группах устройств чтения. Если это значение равно NULL, SCardListReaders игнорирует длину буфера, указанную в pcchReaders, записывает длину буфера, которая была бы возвращена, если бы этот параметр не был равен NULL, в pcchReaders, и возвращает код успеха.
Таким образом, он должен был назначить dwReaders
правильный размер буфера, который будет использоваться для получения списка подключенных читателей. Что ж, он работал правильно на моем компьютере с Windows 10 pro, со считывателями, подключенными напрямую, но подключенными к серверу Windows 2008 r2 через тонкий клиент, он возвращал то же значение (это было 37
), но это значение вызывало исключение InsufficientBuffer
.
Итак, я начал настраивать это значение и устанавливать вручную (отладка внутри сервера Windows 2008 r2) и обнаружил, что если установить это значение на 48
(и выше), оно будет работать. Я не знаю, в чем причина того, что метод SCardListReaders
возвращает недостаточное значение для этого параметра, но мне удалось вручную удвоить это значение перед передачей во второй раз, поэтому новая версия ListReaders()
выглядела так:
public SCardError ListReaders(IntPtr hContext, string[] groups, out string[] readers) {
var dwReaders = 0;
// initialize groups array
byte[] mszGroups = null;
if (groups != null)
mszGroups = SCardHelper.ConvertToByteArray(groups, TextEncoding);
// determine the needed buffer size
var rc = SCardHelper.ToSCardError(
SCardListReaders(hContext,
mszGroups,
null,
ref dwReaders));
if (rc != SCardError.Success) {
readers = null;
return rc;
}
//doubling buffer size to work through thin clients
dwReaders *= 2; // <------------------ New line
// initialize array
var mszReaders = new byte[dwReaders * sizeof(char)];
rc = SCardHelper.ToSCardError(
SCardListReaders(hContext,
mszGroups,
mszReaders,
ref dwReaders));
readers = (rc == SCardError.Success)
? SCardHelper.ConvertToStringArray(mszReaders, TextEncoding)
: null;
return rc;
}
Итак, теперь это работает, если у вас есть какие-либо идеи и немного менее «хакерское» решение, может быть, я делаю что-то не так, или, может быть, это должно работать по-другому через тонкие клиенты, и это ошибка или что-то в этом роде, пожалуйста, не стесняйтесь комментировать !
person
SᴇM
schedule
04.07.2018
Basic rules / best practices: One context per smartcard / reader.
- person Pierre   schedule 03.07.2018