Пытаюсь ожидать изменения, но функция почему-то сразу возвращается, причем на одной машине с одним и тем же ридером две разных программы ведут себя по разному: у одной почти постоянно возвращается ошибка SCARD_W_CARD_REMOVED, у другого -- SCARD_S_SUCCESS. Код программ практически идентичный, только вторая линкуется еще и с библиотекой CEN/XFS и User32.
Собственно, пытаюсь отслеживать изменения таким кодом:
// Тут открыто соединение, все, как полагается
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 во второй.
Очень редко бывает, что первая программа останавливается и ждет ввода карты, но это скорее случайность.
Вот хотел спросить, правильно ли я пытаюсь реализовать отслеживание появления карт в считывателе? Как это делать правильно? В тестах к библиотеке PCSC-lite просто выставляют reader.dwCurrentState=SCARD_STATE_EMPTY, кто-то советует сначала получить текущее состояние:
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);
...
Также первая программа -- это
код примера, дополненный вышеуказанным кодом ожидания подключения считывателя и появления в нем карточки.
Считыватель --
Omnikey 3121.