smartcard 3.7.1 → 3.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "smartcard",
3
- "version": "3.7.1",
3
+ "version": "3.7.2",
4
4
  "description": "PC/SC bindings for Node.js using N-API - ABI stable across Node.js versions",
5
5
  "author": "Tom KP",
6
6
  "license": "MIT",
@@ -245,39 +245,57 @@ void ReaderMonitor::MonitorLoop() {
245
245
  }
246
246
 
247
247
  if (result == SCARD_E_TIMEOUT) {
248
- // Timeout - check for state divergence on Windows (Issue #111)
249
- // Windows PC/SC may not always set SCARD_STATE_CHANGED correctly
248
+ // Timeout - query fresh state to detect missed events (Issue #111)
249
+ // On Windows, dwEventState after timeout may just mirror dwCurrentState
250
+ // rather than reflecting actual hardware state. We must explicitly
251
+ // query with SCARD_STATE_UNAWARE to get the real current state.
250
252
  std::lock_guard<std::mutex> lock(mutex_);
251
253
 
252
- // Guard against underflow if states only has PnP entry
253
- if (states.size() <= 1) {
254
+ if (readerStates_.empty()) {
254
255
  continue;
255
256
  }
256
257
 
257
- for (size_t i = 0; i < states.size() - 1; i++) { // Skip PnP entry
258
- const std::string& name = readerNames[i];
258
+ // Build fresh state query for all readers
259
+ std::vector<SCARD_READERSTATE> freshStates;
260
+ std::vector<std::string> freshNames;
261
+
262
+ for (const auto& pair : readerStates_) {
263
+ freshNames.push_back(pair.first);
264
+ SCARD_READERSTATE state = {};
265
+ state.szReader = freshNames.back().c_str();
266
+ state.dwCurrentState = SCARD_STATE_UNAWARE;
267
+ freshStates.push_back(state);
268
+ }
269
+
270
+ LONG freshResult = SCardGetStatusChange(context_, 0, freshStates.data(), freshStates.size());
271
+ if (freshResult != SCARD_S_SUCCESS) {
272
+ continue;
273
+ }
274
+
275
+ for (size_t i = 0; i < freshStates.size(); i++) {
276
+ const std::string& name = freshNames[i];
259
277
  auto it = readerStates_.find(name);
260
278
  if (it != readerStates_.end()) {
261
- DWORD currentState = states[i].dwEventState & ~SCARD_STATE_CHANGED;
279
+ DWORD freshState = freshStates[i].dwEventState & ~SCARD_STATE_CHANGED;
262
280
  DWORD storedState = it->second.lastState;
263
281
 
264
282
  bool wasPresent = (storedState & SCARD_STATE_PRESENT) != 0;
265
- bool isPresent = (currentState & SCARD_STATE_PRESENT) != 0;
283
+ bool isPresent = (freshState & SCARD_STATE_PRESENT) != 0;
266
284
 
267
- // If the PRESENT flag differs, we missed an event
268
285
  if (wasPresent != isPresent) {
269
286
  std::vector<uint8_t> atr;
270
- if (states[i].cbAtr > 0) {
271
- atr.assign(states[i].rgbAtr, states[i].rgbAtr + states[i].cbAtr);
287
+ if (freshStates[i].cbAtr > 0) {
288
+ atr.assign(freshStates[i].rgbAtr,
289
+ freshStates[i].rgbAtr + freshStates[i].cbAtr);
272
290
  }
273
291
 
274
- it->second.lastState = currentState;
292
+ it->second.lastState = freshState;
275
293
  it->second.atr = atr;
276
294
 
277
295
  if (isPresent) {
278
- EmitEvent("card-inserted", name, currentState, atr);
296
+ EmitEvent("card-inserted", name, freshState, atr);
279
297
  } else {
280
- EmitEvent("card-removed", name, currentState, {});
298
+ EmitEvent("card-removed", name, freshState, {});
281
299
  }
282
300
  }
283
301
  }