代码之家  ›  专栏  ›  技术社区  ›  SᴇM

pc/sc sharp getreaders()引发InsufficientBuffer异常

  •  2
  • SᴇM  · 技术社区  · 6 年前

    我在用 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 例外

    缓冲区不足:接收返回数据的数据缓冲区对于返回的数据来说太小。

    1 回复  |  直到 6 年前
        1
  •  0
  •   SᴇM    6 年前

    我找到了解决办法。我从他们的github页面下载了pc/sc sharp的源代码并开始分析,问题出在方法上 SCardListReaders 有参数的 pcchReaders 这个参数太小,导致了一个异常,来自msdn:

    mszreaders缓冲区的长度(以字符为单位)。此参数接收多字符串结构的实际长度,包括所有尾随的空字符。如果将缓冲区长度指定为scard_autoallocate,则mszreaders将转换为指向字节指针的指针,并接收包含多字符串结构的内存块的地址。此内存块必须用scardfreemory释放。

    在PCSC夏普的房间里是这样叫的 ListReaders 方法(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:

    列出所提供读卡器组中读卡器的多字符串。 如果此值为空,scardListReaders将忽略pccreaders中提供的缓冲区长度,将如果此参数不是空的话本应返回的缓冲区长度写入pccreaders,并返回成功代码 是的。

    所以它应该分配给 dwReaders 将用于获取连接的读卡器列表的正确缓冲区大小。它在我的Windows10Pro机器上工作正常,读卡器直接连接,但是通过瘦客户机连接到Windows2008R2服务器,它返回的值相同(它是 37 ,但该值导致 InsufficientBuffer 例外。

    所以我已经开始调整这个值并手动设置(在windows 2008 r2服务器中调试),我发现如果将这个值设置为 48 (和更高)它会起作用的。我不知道是什么原因 恐怖分子 方法为该参数返回的值不足,但我已设法在第二次传递之前手动将该值加倍,因此 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;
    }
    

    所以它现在是有效的,如果你有任何想法和少一点“黑客”的解决方案,也许我做错了什么,或者也许它应该通过瘦客户机不同的工作,这是一个错误或什么,请随时评论!