Ну, я нашел решение. Я загрузил исходный код PC / SC-Sharp со страницы GitHub и приступил к анализу, проблема заключалась в методе SCardListReaders , который имеет параметр pcchReaders
, этот параметр был маленьким и вызывал исключение от MSDN:
Длина буфера mszReaders в символах. Этот параметр получает фактическую длину многострочной структуры, включая все завершающие нулевые символы. Если длина буфера указана как SCARD_AUTOALLOCATE, то mszReaders преобразуется в указатель на указатель байта и получает адрес блока памяти, содержащего многострочную структуру. Этот блок памяти должен быть освобожден с помощью SCardFreeMemory.
был вызван вот так внутри метода ListReaders
pcsc-sharp (WinSCardAPI):
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;
}
Так что это работает сейчас, если у вас есть какие-то идеи и немного менее «хакерское» решение, возможно, я делаю что-то не так, или, возможно, оно должно работать по-другому на тонких клиентах, и это ошибка или что-то в этом роде, пожалуйста свободно комментировать!