如何使用读者检索CAC/智能卡信息?

发布于 2025-01-24 13:56:47 字数 13230 浏览 1 评论 0原文

我在海军陆战队中,正在尝试制作一个数据库,以管理MS Access和SharePoint列表的军械库。我需要添加新朋友在与我签入时,以便我可以立即为他们分配武器。手动输入他们的信息很酷,但是他们有一张CAC/智能卡,其中包含所有这些信息,我想看看我是否可以自动化此步骤。

有一个ActivClient代理应用程序,我可以打开并查看所有信息。有一个名为“我的个人信息”的部分,其中有两个标签,上面有我要获取的数据(中间,最后,分支,等级,edipi)。我最近了解到VBA可以使用Windows API(我也只是了解到这些)。我遇到的问题是弄清楚如何使用政府计算机上安装的资源访问CAC信息。我们不能在这些计算机上下载任何工具或库,必须已经安装。

我发现WinScard.h具有一些似乎有用的功能,但我不知道如何使用它们。我可以使用winscard.h函数访问和读取与计算机连接的第二个CAC的数据吗?我是否应该找到一种不同的方法,例如制作自己的.dll可以使用卡片来完成我需要的所有功能?我已经学习了一些编程,但是当涉及这样的利基主题时,我不确定如何以最好的方式解决问题。

这些步骤通常是:用户使用CAC登录计算机,打开访问数据库,导航到签到表格,将新Join的卡插入第二张卡读取器,以某种方式从卡中获取数据,请自动填写表单有了新的数据,并完成了我所做的一切。我坚持的步骤严格是从卡中获取数据。

OS:仅Windows 10

软件:MS Access 32和64位

硬件:任何智能卡读取器。我计划与许多人共享此软件,这些人除了政府计算机外没有相同的确切设备。大多数计算机都有内置的读取器,有时它们可​​能具有内置读取器的独立读取器或键盘。

或者,获得扫描仪并扫描卡片上的条形码会更容易吗?我相信条形码将具有我需要的相同信息。除非我能够获得扫描仪批准用于使用,否则我仍然想尝试使用第二种智能卡读取器方法,因为那是我现在拥有的。 ActivClient或其资源可以做任何事情吗?它使用ac.scapi.scmd.dll,acpkcs211.dll,acbsi21.dll和acpivapi.dll。我找不到任何这些东西的文档。似乎可以以某种方式使用其中一个或全部来获取我想要的数据。

编辑:

我遵循评论中共享的一些链接,并具有以下代码:

Option Explicit
Option Compare Database

Public AuthDict As Scripting.Dictionary
Public Const SCARD_SCOPE_USER As Long = &H0
Public Const SCARD_SCOPE_SYSTEM As Long = &H2
Public Const SCARD_SHARE_SHARED As Long = &H2
Public Const SCARD_SHARE_EXCLUSIVE As Long = &H1
Public Const SCARD_SHARE_DIRECT As Long = &H3
Public Const SCARD_PROTOCOL_T0 As Long = &H1
Public Const SCARD_PROTOCOL_T1 As Long = &H2
Public Const SCARD_DEFAULT_READERS As String = "SCard$DefaultReaders\000"
Public Const SCARD_ALL_READERS As String = "SCard$AllReaders\000"

Public Declare PtrSafe Function SCardEstablishContext Lib "winscard.dll" ( _
    ByVal dwScope As Long, _
    ByVal pvReserved1 As LongPtr, _
    ByVal pvReserved2 As LongPtr, _
    ByRef phContext As LongPtr _
    ) As Long

Public Declare PtrSafe Function SCardIsValidContext Lib "winscard.dll" ( _
    ByVal hContext As LongPtr _
) As Long

Public Declare PtrSafe Function SCardReleaseContext Lib "winscard.dll" ( _
    ByVal hContext As LongPtr) As Long
    
Public Declare PtrSafe Function SCardConnectA Lib "winscard.dll" ( _
    ByVal hContext As LongPtr, _
    szReader As LongPtr, _
    dwShareMode As LongPtr, _
    dwPreferredProtocols As LongPtr, _
    phCard As LongPtr, _
    pdwActiveProtocol) As LongPtr

Public Function SCardAuthCode(lReturn As Long)
'Credit: https://stackoverflow.com/questions/67199032/access-vba-and-smart-cards-whats-the-trick
AuthDict.RemoveAll
Dim hreturn As String, hc As String, hd As String
hreturn = "0x" & Right("0000000" & Hex(lReturn), 8)

Select Case hreturn
    Case "0x00000000": hc = "SCARD_S_SUCCESS": hd = "No error was encountered."
    Case "0x00000006": hc = "ERROR_INVALID_HANDLE": hd = "The handle is invalid."
    Case "0x00000109": hc = "ERROR_BROKEN_PIPE": hd = "The client attempted a smart card operation in a remote session, such as a client session running on a terminal server, and the operating system in use does not support smart card redirection."
    Case "0x80100001": hc = "SCARD_F_INTERNAL_ERROR": hd = "An internal consistency check failed."
    Case "0x80100002": hc = "SCARD_E_CANCELLED": hd = "The action was canceled by an SCardCancel request."
    Case "0x80100003": hc = "SCARD_E_INVALID_HANDLE": hd = "The supplied handle was not valid."
    Case "0x80100004": hc = "SCARD_E_INVALID_PARAMETER": hd = "One or more of the supplied parameters could not be properly interpreted."
    Case "0x80100005": hc = "SCARD_E_INVALID_TARGET": hd = "Registry startup information is missing or not valid."
    Case "0x80100006": hc = "SCARD_E_NO_MEMORY": hd = "Not enough memory available to complete this command."
    Case "0x80100007": hc = "SCARD_F_WAITED_TOO_LONG": hd = "An internal consistency timer has expired."
    Case "0x80100008": hc = "SCARD_E_INSUFFICIENT_BUFFER": hd = "The data buffer for returned data is too small for the returned data."
    Case "0x80100009": hc = "SCARD_E_UNKNOWN_READER": hd = "The specified reader name is not recognized."
    Case "0x8010000A": hc = "SCARD_E_TIMEOUT": hd = "The user-specified time-out value has expired."
    Case "0x8010000B": hc = "SCARD_E_SHARING_VIOLATION": hd = "The smart card cannot be accessed because of other outstanding connections."
    Case "0x8010000C": hc = "SCARD_E_NO_SMARTCARD": hd = "The operation requires a smart card, but no smart card is currently in the device."
    Case "0x8010000D": hc = "SCARD_E_UNKNOWN_CARD": hd = "The specified smart card name is not recognized."
    Case "0x8010000E": hc = "SCARD_E_CANT_DISPOSE": hd = "The system could not dispose of the media in the requested manner."
    Case "0x8010000F": hc = "SCARD_E_PROTO_MISMATCH": hd = "The requested protocols are incompatible with the protocol currently in use with the card."
    Case "0x80100010": hc = "SCARD_E_NOT_READY": hd = "The reader or card is not ready to accept commands."
    Case "0x80100011": hc = "SCARD_E_INVALID_VALUE": hd = "One or more of the supplied parameter values could not be properly interpreted."
    Case "0x80100012": hc = "SCARD_E_SYSTEM_CANCELLED": hd = "The action was canceled by the system, presumably to log off or shut down."
    Case "0x80100013": hc = "SCARD_F_COMM_ERROR": hd = "An internal communications error has been detected."
    Case "0x80100014": hc = "SCARD_F_UNKNOWN_ERROR": hd = "An internal error has been detected, but the source is unknown."
    Case "0x80100015": hc = "SCARD_E_INVALID_ATR": hd = "An ATR string obtained from the registry is not a valid ATR string."
    Case "0x80100016": hc = "SCARD_E_NOT_TRANSACTED": hd = "An attempt was made to end a nonexistent transaction."
    Case "0x80100017": hc = "SCARD_E_READER_UNAVAILABLE": hd = "The specified reader is not currently available for use."
    Case "0x80100018": hc = "SCARD_P_SHUTDOWN": hd = "The operation has been aborted to allow the server application to exit."
    Case "0x80100019": hc = "SCARD_E_PCI_TOO_SMALL": hd = "The PCI receive buffer was too small."
    Case "0x8010001A": hc = "SCARD_E_READER_UNSUPPORTED": hd = "The reader driver does not meet minimal requirements for support."
    Case "0x8010001B": hc = "SCARD_E_DUPLICATE_READER": hd = "The reader driver did not produce a unique reader name."
    Case "0x8010001C": hc = "SCARD_E_CARD_UNSUPPORTED": hd = "The smart card does not meet minimal requirements for support."
    Case "0x8010001D": hc = "SCARD_E_NO_SERVICE": hd = "The smart card resource manager is not running."
    Case "0x8010001E": hc = "SCARD_E_SERVICE_STOPPED": hd = "The smart card resource manager has shut down."
    Case "0x8010001F": hc = "SCARD_E_UNEXPECTED": hd = "An unexpected card error has occurred."
    Case "0x80100020": hc = "SCARD_E_ICC_INSTALLATION": hd = "No primary provider can be found for the smart card."
    Case "0x80100021": hc = "SCARD_E_ICC_CREATEORDER": hd = "The requested order of object creation is not supported."
    Case "0x80100022": hc = "SCARD_E_UNSUPPORTED_FEATURE": hd = "This smart card does not support the requested feature."
    Case "0x80100023": hc = "SCARD_E_DIR_NOT_FOUND": hd = "The specified directory does not exist in the smart card."
    Case "0x80100024": hc = "SCARD_E_FILE_NOT_FOUND": hd = "The specified file does not exist in the smart card."
    Case "0x80100025": hc = "SCARD_E_NO_DIR": hd = "The supplied path does not represent a smart card directory."
    Case "0x80100026": hc = "SCARD_E_NO_FILE": hd = "The supplied path does not represent a smart card file."
    Case "0x80100027": hc = "SCARD_E_NO_ACCESS": hd = "Access is denied to the file."
    Case "0x80100028": hc = "SCARD_E_WRITE_TOO_MANY": hd = "An attempt was made to write more data than would fit in the target object."
    Case "0x80100029": hc = "SCARD_E_BAD_SEEK": hd = "An error occurred in setting the smart card file object pointer."
    Case "0x8010002A": hc = "SCARD_E_INVALID_CHV": hd = "The supplied PIN is incorrect."
    Case "0x8010002B": hc = "SCARD_E_UNKNOWN_RES_MNG": hd = "An unrecognized error code was returned."
    Case "0x8010002C": hc = "SCARD_E_NO_SUCH_CERTIFICATE": hd = "The requested certificate does not exist."
    Case "0x8010002D": hc = "SCARD_E_CERTIFICATE_UNAVAILABLE": hd = "The requested certificate could not be obtained."
    Case "0x8010002E": hc = "SCARD_E_NO_READERS_AVAILABLE": hd = "No smart card reader is available."
    Case "0x8010002F": hc = "SCARD_E_COMM_DATA_LOST": hd = "A communications error with the smart card has been detected."
    Case "0x80100030": hc = "SCARD_E_NO_KEY_CONTAINER": hd = "The requested key container does not exist on the smart card."
    Case "0x80100031": hc = "SCARD_E_SERVER_TOO_BUSY": hd = "The smart card resource manager is too busy to complete this operation."
    Case "0x80100032": hc = "SCARD_E_PIN_CACHE_EXPIRED": hd = "The smart card PIN cache has expired."
    Case "0x80100033": hc = "SCARD_E_NO_PIN_CACHE": hd = "The smart card PIN cannot be cached."
    Case "0x80100034": hc = "SCARD_E_READ_ONLY_CARD": hd = "The smart card is read-only and cannot be written to."
    Case "0x80100065": hc = "SCARD_W_UNSUPPORTED_CARD": hd = "The reader cannot communicate with the card, due to ATR string configuration conflicts."
    Case "0x80100066": hc = "SCARD_W_UNRESPONSIVE_CARD": hd = "The smart card is not responding to a reset."
    Case "0x80100067": hc = "SCARD_W_UNPOWERED_CARD": hd = "Power has been removed from the smart card, so that further communication is not possible."
    Case "0x80100068": hc = "SCARD_W_RESET_CARD": hd = "The smart card was reset."
    Case "0x80100069": hc = "SCARD_W_REMOVED_CARD": hd = "The smart card has been removed, so further communication is not possible."
    Case "0x8010006A": hc = "SCARD_W_SECURITY_VIOLATION": hd = "Access was denied because of a security violation."
    Case "0x8010006B": hc = "SCARD_W_WRONG_CHV": hd = "The card cannot be accessed because the wrong PIN was presented."
    Case "0x8010006C": hc = "SCARD_W_CHV_BLOCKED": hd = "The card cannot be accessed because the maximum number of PIN entry attempts has been reached."
    Case "0x8010006D": hc = "SCARD_W_EOF": hd = "The end of the smart card file has been reached."
    Case "0x8010006E": hc = "SCARD_W_CANCELLED_BY_USER": hd = "The action was canceled by the user."
    Case "0x8010006F": hc = "SCARD_W_CARD_NOT_AUTHENTICATED": hd = "No PIN was presented to the smart card."
    Case "0x80100070": hc = "SCARD_W_CACHE_ITEM_NOT_FOUND": hd = "The requested item could not be found in the cache."
    Case "0x80100071": hc = "SCARD_W_CACHE_ITEM_STALE": hd = "The requested cache item is too old and was deleted from the cache."
    Case "0x80100072": hc = "SCARD_W_CACHE_ITEM_TOO_BIG": hd = "The new cache item exceeds the maximum per-item size defined for the cache."
    Case Else: hc = "UNKNOWN VALUE": hd = "Unknown value."
End Select

AuthDict.Add "hr", hreturn
AuthDict.Add "hc", hc
AuthDict.Add "hd", hd
End Function

Public Sub GetContext()
'https://learn.microsoft.com/en-us/windows/win32/secauthn/authentication-return-values?redirectedfrom=MSDN#smart_card_return_values
'https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499-?redirectedfrom=MSDN
'Credit: https://stackoverflow.com/questions/67199032/access-vba-and-smart-cards-whats-the-trick

'TODO: Finish SCardConnectA

Dim lReturn As Long
Dim RSVD1 As Long, RSVD2 As Long
Dim myContext, cardCon As LongPtr
Set AuthDict = New Scripting.Dictionary

Debug.Print "-----------------------------------------------------------------------------"

lReturn = SCardEstablishContext(SCARD_SCOPE_USER, RSVD1, RSVD2, myContext)
SCardAuthCode lReturn
Debug.Print "SCardEstablishContext:" & vbCrLf & _
    "   Return = " & AuthDict("hr") & vbCrLf & _
    "   Value = " & AuthDict("hc") & vbCrLf & _
    "   Description = " & AuthDict("hd") & vbCrLf
    
lReturn = SCardIsValidContext(myContext)
SCardAuthCode lReturn
Debug.Print "SCardIsValidContext:" & vbCrLf & _
    "   Return = " & AuthDict("hr") & vbCrLf & _
    "   Value = " & AuthDict("hc") & vbCrLf & _
    "   Description = " & AuthDict("hd") & vbCrLf

If lReturn <> 0 Then GoTo GetContextExit

GetContextExit:
    Debug.Print "-----------------------------------------------------------------------------" & vbCrLf
    SCardReleaseContext myContext
    Exit Sub
    
ErrorHandler:
    'TODO: handle the errors...
    Resume GetContextExit
    
End Sub

我不确定

Public Type SCARDCONTEXT
    CardContext1 As Long
    ReaderName As String
End Type

我遵循的代码中的意义是什么。这导致了我错误,所以我只是将其删除。代码输出

-----------------------------------------------------------------------------
SCardEstablishContext:
   Return = 0x00000000
   Value = SCARD_S_SUCCESS
   Description = No error was encountered.

SCardIsValidContext:
   Return = 0x00000000
   Value = SCARD_S_SUCCESS
   Description = No error was encountered.

-----------------------------------------------------------------------------

我不太确定下一步需要做什么。似乎现在我需要确定我想要的CAC的名称(getopencardnamea?),连接到它(scardConnecta),然后使用scardtransmit从卡中接收数据?我不确定这些功能是否有效。

I'm in the Marines and am trying to make a database to manage an armory with MS Access and SharePoint Lists. I need to add new people when they check in with me so I can immediately assign them a weapon. Entering their information manually is cool, but they have a CAC/Smart Card with all this info on it and I want to see if I can automate this step.

There is an ActivClient Agent application I can open and see all of my info. There's a section called "My Personal Info" with two tabs that have the data I'm trying to get (first name, middle, last, branch, rank, EDIPI). I've recently learned that VBA can use Windows APIs (I also just learned that these exist). The issue I'm having is figuring how to use the resources that are installed on the government computer to access the CAC information. We cannot download any tools or libraries on these computers, it has to be already installed.

I've found winscard.h has some functions that seem like they would be useful, but I don't know how to use them. Can I use winscard.h functions to access and read the data from a second CAC connected to my computer? Should I find a different approach, like making my own .dll that has the functions to do everything I need with the card? I've been learning to program for a bit now, but when it comes to niche topics like this, I'm unsure how to approach the problem the best way.

The steps would generally be: user logs into computer using CAC, open the Access database, navigate to the check-in form, insert the new-join's card into the second card reader, somehow get data from the card, auto-fill the form with the fresh data, and finish doing whatever I make it do. The step I'm stuck on is strictly getting the data from the card.

OS: Windows 10 only

Software: MS Access 32 and 64 bit

Hardware: any Smart Card reader. I plan to share this software with a lot of people that won't have the same exact equipment except for the government computer. Most of the computers have a built in reader, and sometimes they might have standalone readers or keyboards with built in readers.

Alternatively, would it be easier to get a scanner and scan the barcode on the card? I believe the barcode will have the same information I need. Until I can get a scanner approved for use, I would still like to try to use the second Smart Card reader approach since that's what I have right now. Can anything be done with ActivClient or its resources? It uses ac.scapi.scmd.dll, acpkcs211.dll, acbsi21.dll, and acpivapi.dll. I can't find documentation for any of these things. It seems like one or all of them can somehow be used to get the data I want.

Edit:

I followed some of the links shared in the comments and have the following code:

Option Explicit
Option Compare Database

Public AuthDict As Scripting.Dictionary
Public Const SCARD_SCOPE_USER As Long = &H0
Public Const SCARD_SCOPE_SYSTEM As Long = &H2
Public Const SCARD_SHARE_SHARED As Long = &H2
Public Const SCARD_SHARE_EXCLUSIVE As Long = &H1
Public Const SCARD_SHARE_DIRECT As Long = &H3
Public Const SCARD_PROTOCOL_T0 As Long = &H1
Public Const SCARD_PROTOCOL_T1 As Long = &H2
Public Const SCARD_DEFAULT_READERS As String = "SCard$DefaultReaders\000"
Public Const SCARD_ALL_READERS As String = "SCard$AllReaders\000"

Public Declare PtrSafe Function SCardEstablishContext Lib "winscard.dll" ( _
    ByVal dwScope As Long, _
    ByVal pvReserved1 As LongPtr, _
    ByVal pvReserved2 As LongPtr, _
    ByRef phContext As LongPtr _
    ) As Long

Public Declare PtrSafe Function SCardIsValidContext Lib "winscard.dll" ( _
    ByVal hContext As LongPtr _
) As Long

Public Declare PtrSafe Function SCardReleaseContext Lib "winscard.dll" ( _
    ByVal hContext As LongPtr) As Long
    
Public Declare PtrSafe Function SCardConnectA Lib "winscard.dll" ( _
    ByVal hContext As LongPtr, _
    szReader As LongPtr, _
    dwShareMode As LongPtr, _
    dwPreferredProtocols As LongPtr, _
    phCard As LongPtr, _
    pdwActiveProtocol) As LongPtr

Public Function SCardAuthCode(lReturn As Long)
'Credit: https://stackoverflow.com/questions/67199032/access-vba-and-smart-cards-whats-the-trick
AuthDict.RemoveAll
Dim hreturn As String, hc As String, hd As String
hreturn = "0x" & Right("0000000" & Hex(lReturn), 8)

Select Case hreturn
    Case "0x00000000": hc = "SCARD_S_SUCCESS": hd = "No error was encountered."
    Case "0x00000006": hc = "ERROR_INVALID_HANDLE": hd = "The handle is invalid."
    Case "0x00000109": hc = "ERROR_BROKEN_PIPE": hd = "The client attempted a smart card operation in a remote session, such as a client session running on a terminal server, and the operating system in use does not support smart card redirection."
    Case "0x80100001": hc = "SCARD_F_INTERNAL_ERROR": hd = "An internal consistency check failed."
    Case "0x80100002": hc = "SCARD_E_CANCELLED": hd = "The action was canceled by an SCardCancel request."
    Case "0x80100003": hc = "SCARD_E_INVALID_HANDLE": hd = "The supplied handle was not valid."
    Case "0x80100004": hc = "SCARD_E_INVALID_PARAMETER": hd = "One or more of the supplied parameters could not be properly interpreted."
    Case "0x80100005": hc = "SCARD_E_INVALID_TARGET": hd = "Registry startup information is missing or not valid."
    Case "0x80100006": hc = "SCARD_E_NO_MEMORY": hd = "Not enough memory available to complete this command."
    Case "0x80100007": hc = "SCARD_F_WAITED_TOO_LONG": hd = "An internal consistency timer has expired."
    Case "0x80100008": hc = "SCARD_E_INSUFFICIENT_BUFFER": hd = "The data buffer for returned data is too small for the returned data."
    Case "0x80100009": hc = "SCARD_E_UNKNOWN_READER": hd = "The specified reader name is not recognized."
    Case "0x8010000A": hc = "SCARD_E_TIMEOUT": hd = "The user-specified time-out value has expired."
    Case "0x8010000B": hc = "SCARD_E_SHARING_VIOLATION": hd = "The smart card cannot be accessed because of other outstanding connections."
    Case "0x8010000C": hc = "SCARD_E_NO_SMARTCARD": hd = "The operation requires a smart card, but no smart card is currently in the device."
    Case "0x8010000D": hc = "SCARD_E_UNKNOWN_CARD": hd = "The specified smart card name is not recognized."
    Case "0x8010000E": hc = "SCARD_E_CANT_DISPOSE": hd = "The system could not dispose of the media in the requested manner."
    Case "0x8010000F": hc = "SCARD_E_PROTO_MISMATCH": hd = "The requested protocols are incompatible with the protocol currently in use with the card."
    Case "0x80100010": hc = "SCARD_E_NOT_READY": hd = "The reader or card is not ready to accept commands."
    Case "0x80100011": hc = "SCARD_E_INVALID_VALUE": hd = "One or more of the supplied parameter values could not be properly interpreted."
    Case "0x80100012": hc = "SCARD_E_SYSTEM_CANCELLED": hd = "The action was canceled by the system, presumably to log off or shut down."
    Case "0x80100013": hc = "SCARD_F_COMM_ERROR": hd = "An internal communications error has been detected."
    Case "0x80100014": hc = "SCARD_F_UNKNOWN_ERROR": hd = "An internal error has been detected, but the source is unknown."
    Case "0x80100015": hc = "SCARD_E_INVALID_ATR": hd = "An ATR string obtained from the registry is not a valid ATR string."
    Case "0x80100016": hc = "SCARD_E_NOT_TRANSACTED": hd = "An attempt was made to end a nonexistent transaction."
    Case "0x80100017": hc = "SCARD_E_READER_UNAVAILABLE": hd = "The specified reader is not currently available for use."
    Case "0x80100018": hc = "SCARD_P_SHUTDOWN": hd = "The operation has been aborted to allow the server application to exit."
    Case "0x80100019": hc = "SCARD_E_PCI_TOO_SMALL": hd = "The PCI receive buffer was too small."
    Case "0x8010001A": hc = "SCARD_E_READER_UNSUPPORTED": hd = "The reader driver does not meet minimal requirements for support."
    Case "0x8010001B": hc = "SCARD_E_DUPLICATE_READER": hd = "The reader driver did not produce a unique reader name."
    Case "0x8010001C": hc = "SCARD_E_CARD_UNSUPPORTED": hd = "The smart card does not meet minimal requirements for support."
    Case "0x8010001D": hc = "SCARD_E_NO_SERVICE": hd = "The smart card resource manager is not running."
    Case "0x8010001E": hc = "SCARD_E_SERVICE_STOPPED": hd = "The smart card resource manager has shut down."
    Case "0x8010001F": hc = "SCARD_E_UNEXPECTED": hd = "An unexpected card error has occurred."
    Case "0x80100020": hc = "SCARD_E_ICC_INSTALLATION": hd = "No primary provider can be found for the smart card."
    Case "0x80100021": hc = "SCARD_E_ICC_CREATEORDER": hd = "The requested order of object creation is not supported."
    Case "0x80100022": hc = "SCARD_E_UNSUPPORTED_FEATURE": hd = "This smart card does not support the requested feature."
    Case "0x80100023": hc = "SCARD_E_DIR_NOT_FOUND": hd = "The specified directory does not exist in the smart card."
    Case "0x80100024": hc = "SCARD_E_FILE_NOT_FOUND": hd = "The specified file does not exist in the smart card."
    Case "0x80100025": hc = "SCARD_E_NO_DIR": hd = "The supplied path does not represent a smart card directory."
    Case "0x80100026": hc = "SCARD_E_NO_FILE": hd = "The supplied path does not represent a smart card file."
    Case "0x80100027": hc = "SCARD_E_NO_ACCESS": hd = "Access is denied to the file."
    Case "0x80100028": hc = "SCARD_E_WRITE_TOO_MANY": hd = "An attempt was made to write more data than would fit in the target object."
    Case "0x80100029": hc = "SCARD_E_BAD_SEEK": hd = "An error occurred in setting the smart card file object pointer."
    Case "0x8010002A": hc = "SCARD_E_INVALID_CHV": hd = "The supplied PIN is incorrect."
    Case "0x8010002B": hc = "SCARD_E_UNKNOWN_RES_MNG": hd = "An unrecognized error code was returned."
    Case "0x8010002C": hc = "SCARD_E_NO_SUCH_CERTIFICATE": hd = "The requested certificate does not exist."
    Case "0x8010002D": hc = "SCARD_E_CERTIFICATE_UNAVAILABLE": hd = "The requested certificate could not be obtained."
    Case "0x8010002E": hc = "SCARD_E_NO_READERS_AVAILABLE": hd = "No smart card reader is available."
    Case "0x8010002F": hc = "SCARD_E_COMM_DATA_LOST": hd = "A communications error with the smart card has been detected."
    Case "0x80100030": hc = "SCARD_E_NO_KEY_CONTAINER": hd = "The requested key container does not exist on the smart card."
    Case "0x80100031": hc = "SCARD_E_SERVER_TOO_BUSY": hd = "The smart card resource manager is too busy to complete this operation."
    Case "0x80100032": hc = "SCARD_E_PIN_CACHE_EXPIRED": hd = "The smart card PIN cache has expired."
    Case "0x80100033": hc = "SCARD_E_NO_PIN_CACHE": hd = "The smart card PIN cannot be cached."
    Case "0x80100034": hc = "SCARD_E_READ_ONLY_CARD": hd = "The smart card is read-only and cannot be written to."
    Case "0x80100065": hc = "SCARD_W_UNSUPPORTED_CARD": hd = "The reader cannot communicate with the card, due to ATR string configuration conflicts."
    Case "0x80100066": hc = "SCARD_W_UNRESPONSIVE_CARD": hd = "The smart card is not responding to a reset."
    Case "0x80100067": hc = "SCARD_W_UNPOWERED_CARD": hd = "Power has been removed from the smart card, so that further communication is not possible."
    Case "0x80100068": hc = "SCARD_W_RESET_CARD": hd = "The smart card was reset."
    Case "0x80100069": hc = "SCARD_W_REMOVED_CARD": hd = "The smart card has been removed, so further communication is not possible."
    Case "0x8010006A": hc = "SCARD_W_SECURITY_VIOLATION": hd = "Access was denied because of a security violation."
    Case "0x8010006B": hc = "SCARD_W_WRONG_CHV": hd = "The card cannot be accessed because the wrong PIN was presented."
    Case "0x8010006C": hc = "SCARD_W_CHV_BLOCKED": hd = "The card cannot be accessed because the maximum number of PIN entry attempts has been reached."
    Case "0x8010006D": hc = "SCARD_W_EOF": hd = "The end of the smart card file has been reached."
    Case "0x8010006E": hc = "SCARD_W_CANCELLED_BY_USER": hd = "The action was canceled by the user."
    Case "0x8010006F": hc = "SCARD_W_CARD_NOT_AUTHENTICATED": hd = "No PIN was presented to the smart card."
    Case "0x80100070": hc = "SCARD_W_CACHE_ITEM_NOT_FOUND": hd = "The requested item could not be found in the cache."
    Case "0x80100071": hc = "SCARD_W_CACHE_ITEM_STALE": hd = "The requested cache item is too old and was deleted from the cache."
    Case "0x80100072": hc = "SCARD_W_CACHE_ITEM_TOO_BIG": hd = "The new cache item exceeds the maximum per-item size defined for the cache."
    Case Else: hc = "UNKNOWN VALUE": hd = "Unknown value."
End Select

AuthDict.Add "hr", hreturn
AuthDict.Add "hc", hc
AuthDict.Add "hd", hd
End Function

Public Sub GetContext()
'https://learn.microsoft.com/en-us/windows/win32/secauthn/authentication-return-values?redirectedfrom=MSDN#smart_card_return_values
'https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499-?redirectedfrom=MSDN
'Credit: https://stackoverflow.com/questions/67199032/access-vba-and-smart-cards-whats-the-trick

'TODO: Finish SCardConnectA

Dim lReturn As Long
Dim RSVD1 As Long, RSVD2 As Long
Dim myContext, cardCon As LongPtr
Set AuthDict = New Scripting.Dictionary

Debug.Print "-----------------------------------------------------------------------------"

lReturn = SCardEstablishContext(SCARD_SCOPE_USER, RSVD1, RSVD2, myContext)
SCardAuthCode lReturn
Debug.Print "SCardEstablishContext:" & vbCrLf & _
    "   Return = " & AuthDict("hr") & vbCrLf & _
    "   Value = " & AuthDict("hc") & vbCrLf & _
    "   Description = " & AuthDict("hd") & vbCrLf
    
lReturn = SCardIsValidContext(myContext)
SCardAuthCode lReturn
Debug.Print "SCardIsValidContext:" & vbCrLf & _
    "   Return = " & AuthDict("hr") & vbCrLf & _
    "   Value = " & AuthDict("hc") & vbCrLf & _
    "   Description = " & AuthDict("hd") & vbCrLf

If lReturn <> 0 Then GoTo GetContextExit

GetContextExit:
    Debug.Print "-----------------------------------------------------------------------------" & vbCrLf
    SCardReleaseContext myContext
    Exit Sub
    
ErrorHandler:
    'TODO: handle the errors...
    Resume GetContextExit
    
End Sub

I'm not sure what the point of

Public Type SCARDCONTEXT
    CardContext1 As Long
    ReaderName As String
End Type

is in the code I was following. It was causing me errors, so I just removed it. The code outputs

-----------------------------------------------------------------------------
SCardEstablishContext:
   Return = 0x00000000
   Value = SCARD_S_SUCCESS
   Description = No error was encountered.

SCardIsValidContext:
   Return = 0x00000000
   Value = SCARD_S_SUCCESS
   Description = No error was encountered.

-----------------------------------------------------------------------------

I'm not quite sure what I need to do next. It seems like now I need to identify the name of the CAC I want the data from (GetOpenCardNameA?), connect to it (SCardConnectA), and then use SCardTransmit to receive data from the card? I'm not sure if that's how these functions work.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

白况 2025-01-31 13:56:47

不是100%确定您是否可以将CAC信息删除,但我确实知道大多数空军CTK程序都使用具有CAC功能的TCMAX,并且您可以100%将其设置为Armarory使用,并生成Excel状态跟踪器和武器分配方式。我建议您与您的通讯讨论TCMAX,因为它是DOD使用的程序。

Not 100% on sure if you can pull CAC information like that, but I do know that most Air Force CTK programs use TCMax which has a CAC function, and you can 100% set it up for armory use and generate excel status trackers and weapon assignments that way. I would suggest talk to your COMM about TCMax since it is program DOD uses anyway.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文