M
M
Mingun2014-10-07 19:26:53
C++ / C#
Mingun, 2014-10-07 19:26:53

How to track the appearance of a smart card in a card reader using the PC/SC protocol?

I'm trying to wait for a change, but for some reason the function immediately returns, and on the same machine with the same reader, two different programs behave differently: one almost always returns the SCARD_W_CARD_REMOVED error, the other SCARD_S_SUCCESS. The program code is almost identical, only the second one is also linked with the CEN / XFS library and User32.
Actually, I'm trying to track changes with the following code:

// Тут открыто соединение, все, как полагается
SCARDCONTEXT hContext;
LONG rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
...
SCARD_READERSTATE reader = {0};
// Считыватель со специальным именем, означающем, что необходимо мониторить
// появление/пропажу считывателей.
reader.szReader = "\\\\?PnP?\\Notification";
reader.dwCurrentState = SCARD_STATE_UNAWARE;
// Мониторим появление считывателей, останавливаемся, пока их не подключат.
// Если считыватель уже подключен на момент вызова, вернется сразу.
LONG st = SCardGetStatusChange(hContext, INFINITE, &reader, 1);
...
SCARD_READERSTATE reader = {0};
reader.szReader = <тут он получен от PC/SC подсистемы>;
// Пытался записывать сюда и SCARD_STATE_UNAWARE, и SCARD_STATE_EMPTY,
// и получать его предыдущим вызовом SCardGetStatusChange, но тогда карточка
// не замечается, если на момент выполнения функции она уже в считывателе.
// Как видно из комментариев выше, считыватель в таком случае прекрасно ловится.
// reader.dwCurrentState = SCARD_STATE_UNAWARE;
LONG st = SCardGetStatusChange(hContext, INFINITE, &reader, 1);
// Здесь st == SCARD_W_CARD_REMOVED в первой программе и SCARD_S_SUCCESS во второй.

It is very rare that the first program stops and waits for the card to be entered, but this is more of an accident.
I wanted to ask if I am trying to implement tracking the appearance of cards in the reader correctly? How to do it right? In tests for the PCSC-lite library, they simply set reader.dwCurrentState=SCARD_STATE_EMPTY, someone advises getting the current state first:
DWORD getState(SCARDCONTEXT  hContext, const char* name) {
    SCARD_READERSTATE reader = {0};
    reader.szReader = name;
    reader.dwCurrentState = SCARD_STATE_UNAWARE;
    // Предсказуемо возвращается сразу с результатом SCARD_S_SUCCESS
    // (тестировал только во второй программе, но там всегда SCARD_S_SUCCESS)
    LONG st = SCardGetStatusChange(hContext, INFINITE, &reader, 1);
    return reader.dwEventState;
}
...
SCARD_READERSTATE reader = {0};
reader.szReader = <тут он получен от PC/SC подсистемы>;
reader.dwCurrentState = getState(hContext, reader.szReader);
LONG st = SCardGetStatusChange(hContext, INFINITE, &reader, 1);
...

Also, the first program is the example code , supplemented by the above code of waiting for the reader to connect and the card to appear in it.
Reader -- Omnikey 3121 .

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question