PC/SC-Sharp GetReaders() выдает исключение InsufficientBuffer

Я использую пакет PC/SC Sharp, загруженный с NuGet, и есть один метод GetReaders() , который возвращает активных считывателей, подключенных к машине.

var contextFactory = ContextFactory.Instance;
using (var context = contextFactory.Establish(SCardScope.System)) {
    Console.WriteLine("Currently connected readers: ");
    var readerNames = context.GetReaders();
    foreach (var readerName in readerNames) {
        Console.WriteLine("\t" + readerName);
    }
}

Когда я вызываю его со своего локального компьютера (Windows 10 Pro x64), он работает правильно и возвращает доступные имена читателей. В любом случае, при подключении через тонкий клиент к Windows Server 2008 R2 выдает исключение InsufficientBuffer

InsufficientBuffer: буфер данных для получения возвращаемых данных слишком мал для возвращаемых данных.


person SᴇM    schedule 03.07.2018    source источник
comment
Есть ли свойство для установки размера буфера в читателе или в контексте?   -  person Pierre    schedule 03.07.2018
comment
В ридми на гитхабе написано Basic rules / best practices: One context per smartcard / reader.   -  person Pierre    schedule 03.07.2018
comment
ИДК, я не нашел ни полезной документации.   -  person SᴇM    schedule 03.07.2018
comment
Ну да, я соблюдаю это правило, но перед этим мне нужно получить список активных читателей, чтобы работать с одним из них.   -  person SᴇM    schedule 03.07.2018
comment
Я только что заметил в разделе Поддерживаемые операционные системы, что Windows Server 2008 R2 отсутствует, это может быть проблемой или нет?   -  person SᴇM    schedule 03.07.2018
comment
Простое предложение, попробуйте установить режим совместимости с Windows 7 или 10, если он доступен в EXE   -  person Pierre    schedule 03.07.2018
comment
Ставил windows 7, не помогло.   -  person SᴇM    schedule 03.07.2018
comment
Есть ли на вашем сервере библиотеки, на которые вы ссылаетесь, которых нет? Зарегистрируйте запрос в пакете github, они могут помочь вам разобраться с проблемой.   -  person Pierre    schedule 03.07.2018
comment
@Pierre хорошо, спасибо за ваше время, я попробую.   -  person SᴇM    schedule 03.07.2018


Ответы (1)


Ну, я нашел решение. Я скачал исходный код 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