smartcard 1.0.46 → 2.0.1
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/LICENSE +1 -1
- package/README.md +453 -0
- package/binding.gyp +45 -0
- package/lib/devices.js +283 -0
- package/lib/errors.js +77 -0
- package/lib/index.d.ts +247 -0
- package/lib/index.js +75 -14
- package/package.json +56 -39
- package/src/addon.cpp +54 -0
- package/src/async_workers.cpp +234 -0
- package/src/async_workers.h +100 -0
- package/src/pcsc_card.cpp +248 -0
- package/src/pcsc_card.h +41 -0
- package/src/pcsc_context.cpp +224 -0
- package/src/pcsc_context.h +32 -0
- package/src/pcsc_errors.h +49 -0
- package/src/pcsc_reader.cpp +89 -0
- package/src/pcsc_reader.h +39 -0
- package/src/platform/pcsc.h +36 -0
- package/src/reader_monitor.cpp +352 -0
- package/src/reader_monitor.h +57 -0
- package/.prettierrc +0 -3
- package/README.MD +0 -371
- package/babel.config.json +0 -3
- package/demo/device-activated-promise.js +0 -12
- package/demo/device-activated.js +0 -12
- package/demo/device-deactivated-promise.js +0 -12
- package/demo/device-deactivated.js +0 -12
- package/demo/smartcard-demo.js +0 -100
- package/lib/Card.js +0 -129
- package/lib/CommandApdu.js +0 -109
- package/lib/Device.js +0 -138
- package/lib/Devices.js +0 -134
- package/lib/Iso7816Application.js +0 -169
- package/lib/ResponseApdu.js +0 -129
package/package.json
CHANGED
|
@@ -1,41 +1,58 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
"
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
2
|
+
"name": "smartcard",
|
|
3
|
+
"version": "2.0.1",
|
|
4
|
+
"description": "PC/SC bindings for Node.js using N-API - ABI stable across Node.js versions",
|
|
5
|
+
"author": "Tom KP",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/tomkp/smartcard.git"
|
|
10
|
+
},
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/tomkp/smartcard/issues"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://github.com/tomkp/smartcard#readme",
|
|
15
|
+
"main": "lib/index.js",
|
|
16
|
+
"types": "lib/index.d.ts",
|
|
17
|
+
"gypfile": true,
|
|
18
|
+
"scripts": {
|
|
19
|
+
"install": "node-gyp rebuild",
|
|
20
|
+
"build": "node-gyp rebuild",
|
|
21
|
+
"rebuild": "node-gyp rebuild",
|
|
22
|
+
"test": "node test/test.js"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"lib/",
|
|
26
|
+
"src/",
|
|
27
|
+
"binding.gyp",
|
|
28
|
+
"README.md",
|
|
29
|
+
"LICENSE"
|
|
30
|
+
],
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"node-addon-api": "^7.0.0"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"node-gyp": "^10.0.0"
|
|
36
|
+
},
|
|
37
|
+
"engines": {
|
|
38
|
+
"node": ">=12.0.0"
|
|
39
|
+
},
|
|
40
|
+
"os": [
|
|
41
|
+
"darwin",
|
|
42
|
+
"linux",
|
|
43
|
+
"win32"
|
|
44
|
+
],
|
|
45
|
+
"keywords": [
|
|
46
|
+
"pcsc",
|
|
47
|
+
"pcsclite",
|
|
48
|
+
"smartcard",
|
|
49
|
+
"smart-card",
|
|
50
|
+
"nfc",
|
|
51
|
+
"rfid",
|
|
52
|
+
"contactless",
|
|
53
|
+
"napi",
|
|
54
|
+
"node-addon-api",
|
|
55
|
+
"acr122",
|
|
56
|
+
"card-reader"
|
|
57
|
+
]
|
|
41
58
|
}
|
package/src/addon.cpp
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#include <napi.h>
|
|
2
|
+
#include "pcsc_context.h"
|
|
3
|
+
#include "pcsc_reader.h"
|
|
4
|
+
#include "pcsc_card.h"
|
|
5
|
+
#include "reader_monitor.h"
|
|
6
|
+
#include "platform/pcsc.h"
|
|
7
|
+
|
|
8
|
+
// Export PC/SC constants
|
|
9
|
+
void ExportConstants(Napi::Env env, Napi::Object exports) {
|
|
10
|
+
// Share modes
|
|
11
|
+
exports.Set("SCARD_SHARE_EXCLUSIVE", Napi::Number::New(env, SCARD_SHARE_EXCLUSIVE));
|
|
12
|
+
exports.Set("SCARD_SHARE_SHARED", Napi::Number::New(env, SCARD_SHARE_SHARED));
|
|
13
|
+
exports.Set("SCARD_SHARE_DIRECT", Napi::Number::New(env, SCARD_SHARE_DIRECT));
|
|
14
|
+
|
|
15
|
+
// Protocols
|
|
16
|
+
exports.Set("SCARD_PROTOCOL_T0", Napi::Number::New(env, SCARD_PROTOCOL_T0));
|
|
17
|
+
exports.Set("SCARD_PROTOCOL_T1", Napi::Number::New(env, SCARD_PROTOCOL_T1));
|
|
18
|
+
exports.Set("SCARD_PROTOCOL_RAW", Napi::Number::New(env, SCARD_PROTOCOL_RAW));
|
|
19
|
+
exports.Set("SCARD_PROTOCOL_UNDEFINED", Napi::Number::New(env, SCARD_PROTOCOL_UNDEFINED));
|
|
20
|
+
|
|
21
|
+
// Disposition
|
|
22
|
+
exports.Set("SCARD_LEAVE_CARD", Napi::Number::New(env, SCARD_LEAVE_CARD));
|
|
23
|
+
exports.Set("SCARD_RESET_CARD", Napi::Number::New(env, SCARD_RESET_CARD));
|
|
24
|
+
exports.Set("SCARD_UNPOWER_CARD", Napi::Number::New(env, SCARD_UNPOWER_CARD));
|
|
25
|
+
exports.Set("SCARD_EJECT_CARD", Napi::Number::New(env, SCARD_EJECT_CARD));
|
|
26
|
+
|
|
27
|
+
// State flags
|
|
28
|
+
exports.Set("SCARD_STATE_UNAWARE", Napi::Number::New(env, SCARD_STATE_UNAWARE));
|
|
29
|
+
exports.Set("SCARD_STATE_IGNORE", Napi::Number::New(env, SCARD_STATE_IGNORE));
|
|
30
|
+
exports.Set("SCARD_STATE_CHANGED", Napi::Number::New(env, SCARD_STATE_CHANGED));
|
|
31
|
+
exports.Set("SCARD_STATE_UNKNOWN", Napi::Number::New(env, SCARD_STATE_UNKNOWN));
|
|
32
|
+
exports.Set("SCARD_STATE_UNAVAILABLE", Napi::Number::New(env, SCARD_STATE_UNAVAILABLE));
|
|
33
|
+
exports.Set("SCARD_STATE_EMPTY", Napi::Number::New(env, SCARD_STATE_EMPTY));
|
|
34
|
+
exports.Set("SCARD_STATE_PRESENT", Napi::Number::New(env, SCARD_STATE_PRESENT));
|
|
35
|
+
exports.Set("SCARD_STATE_ATRMATCH", Napi::Number::New(env, SCARD_STATE_ATRMATCH));
|
|
36
|
+
exports.Set("SCARD_STATE_EXCLUSIVE", Napi::Number::New(env, SCARD_STATE_EXCLUSIVE));
|
|
37
|
+
exports.Set("SCARD_STATE_INUSE", Napi::Number::New(env, SCARD_STATE_INUSE));
|
|
38
|
+
exports.Set("SCARD_STATE_MUTE", Napi::Number::New(env, SCARD_STATE_MUTE));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
Napi::Object Init(Napi::Env env, Napi::Object exports) {
|
|
42
|
+
// Initialize wrapper classes
|
|
43
|
+
PCSCContext::Init(env, exports);
|
|
44
|
+
PCSCReader::Init(env, exports);
|
|
45
|
+
PCSCCard::Init(env, exports);
|
|
46
|
+
ReaderMonitor::Init(env, exports);
|
|
47
|
+
|
|
48
|
+
// Export constants
|
|
49
|
+
ExportConstants(env, exports);
|
|
50
|
+
|
|
51
|
+
return exports;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
NODE_API_MODULE(smartcard_napi, Init)
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
#include "async_workers.h"
|
|
2
|
+
#include "pcsc_card.h"
|
|
3
|
+
#include "pcsc_errors.h"
|
|
4
|
+
#include <cstring>
|
|
5
|
+
|
|
6
|
+
// ============================================================================
|
|
7
|
+
// WaitForChangeWorker
|
|
8
|
+
// ============================================================================
|
|
9
|
+
|
|
10
|
+
WaitForChangeWorker::WaitForChangeWorker(
|
|
11
|
+
Napi::Env env,
|
|
12
|
+
SCARDCONTEXT context,
|
|
13
|
+
std::vector<std::string> readerNames,
|
|
14
|
+
std::vector<DWORD> currentStates,
|
|
15
|
+
DWORD timeout,
|
|
16
|
+
Napi::Promise::Deferred deferred)
|
|
17
|
+
: Napi::AsyncWorker(env),
|
|
18
|
+
context_(context),
|
|
19
|
+
readerNames_(std::move(readerNames)),
|
|
20
|
+
timeout_(timeout),
|
|
21
|
+
result_(SCARD_S_SUCCESS),
|
|
22
|
+
deferred_(deferred) {
|
|
23
|
+
|
|
24
|
+
// Initialize reader states
|
|
25
|
+
states_.resize(readerNames_.size());
|
|
26
|
+
for (size_t i = 0; i < readerNames_.size(); i++) {
|
|
27
|
+
memset(&states_[i], 0, sizeof(SCARD_READERSTATE));
|
|
28
|
+
states_[i].szReader = readerNames_[i].c_str();
|
|
29
|
+
states_[i].dwCurrentState = (i < currentStates.size()) ? currentStates[i] : SCARD_STATE_UNAWARE;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
void WaitForChangeWorker::Execute() {
|
|
34
|
+
// This runs on worker thread - safe to block
|
|
35
|
+
result_ = SCardGetStatusChange(context_, timeout_, states_.data(), states_.size());
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
void WaitForChangeWorker::OnOK() {
|
|
39
|
+
Napi::Env env = Env();
|
|
40
|
+
|
|
41
|
+
if (result_ == SCARD_S_SUCCESS) {
|
|
42
|
+
// Build array of reader states
|
|
43
|
+
Napi::Array changes = Napi::Array::New(env);
|
|
44
|
+
|
|
45
|
+
for (size_t i = 0; i < states_.size(); i++) {
|
|
46
|
+
Napi::Object reader = Napi::Object::New(env);
|
|
47
|
+
reader.Set("name", Napi::String::New(env, readerNames_[i]));
|
|
48
|
+
reader.Set("state", Napi::Number::New(env, states_[i].dwEventState));
|
|
49
|
+
reader.Set("changed", Napi::Boolean::New(env,
|
|
50
|
+
(states_[i].dwEventState & SCARD_STATE_CHANGED) != 0));
|
|
51
|
+
|
|
52
|
+
if (states_[i].cbAtr > 0) {
|
|
53
|
+
reader.Set("atr", Napi::Buffer<uint8_t>::Copy(
|
|
54
|
+
env, states_[i].rgbAtr, states_[i].cbAtr));
|
|
55
|
+
} else {
|
|
56
|
+
reader.Set("atr", env.Null());
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
changes.Set(static_cast<uint32_t>(i), reader);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
deferred_.Resolve(changes);
|
|
63
|
+
} else if (result_ == SCARD_E_CANCELLED) {
|
|
64
|
+
// Cancelled - resolve with null
|
|
65
|
+
deferred_.Resolve(env.Null());
|
|
66
|
+
} else if (result_ == SCARD_E_TIMEOUT) {
|
|
67
|
+
// Timeout - resolve with empty array
|
|
68
|
+
deferred_.Resolve(Napi::Array::New(env, 0));
|
|
69
|
+
} else {
|
|
70
|
+
deferred_.Reject(Napi::Error::New(env, GetPCSCErrorString(result_)).Value());
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
void WaitForChangeWorker::OnError(const Napi::Error& error) {
|
|
75
|
+
deferred_.Reject(error.Value());
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// ============================================================================
|
|
79
|
+
// TransmitWorker
|
|
80
|
+
// ============================================================================
|
|
81
|
+
|
|
82
|
+
TransmitWorker::TransmitWorker(
|
|
83
|
+
Napi::Env env,
|
|
84
|
+
SCARDHANDLE card,
|
|
85
|
+
DWORD protocol,
|
|
86
|
+
std::vector<uint8_t> sendBuffer,
|
|
87
|
+
Napi::Promise::Deferred deferred)
|
|
88
|
+
: Napi::AsyncWorker(env),
|
|
89
|
+
card_(card),
|
|
90
|
+
protocol_(protocol),
|
|
91
|
+
sendBuffer_(std::move(sendBuffer)),
|
|
92
|
+
recvLength_(0),
|
|
93
|
+
result_(SCARD_S_SUCCESS),
|
|
94
|
+
deferred_(deferred) {
|
|
95
|
+
// Pre-allocate receive buffer (max APDU response size)
|
|
96
|
+
recvBuffer_.resize(258);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
void TransmitWorker::Execute() {
|
|
100
|
+
// Select protocol-specific PCI structure
|
|
101
|
+
const SCARD_IO_REQUEST* pioSendPci;
|
|
102
|
+
if (protocol_ == SCARD_PROTOCOL_T0) {
|
|
103
|
+
pioSendPci = SCARD_PCI_T0;
|
|
104
|
+
} else if (protocol_ == SCARD_PROTOCOL_T1) {
|
|
105
|
+
pioSendPci = SCARD_PCI_T1;
|
|
106
|
+
} else {
|
|
107
|
+
pioSendPci = SCARD_PCI_RAW;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
recvLength_ = static_cast<DWORD>(recvBuffer_.size());
|
|
111
|
+
|
|
112
|
+
result_ = SCardTransmit(
|
|
113
|
+
card_,
|
|
114
|
+
pioSendPci,
|
|
115
|
+
sendBuffer_.data(),
|
|
116
|
+
static_cast<DWORD>(sendBuffer_.size()),
|
|
117
|
+
nullptr,
|
|
118
|
+
recvBuffer_.data(),
|
|
119
|
+
&recvLength_
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
void TransmitWorker::OnOK() {
|
|
124
|
+
Napi::Env env = Env();
|
|
125
|
+
|
|
126
|
+
if (result_ == SCARD_S_SUCCESS) {
|
|
127
|
+
Napi::Buffer<uint8_t> buffer = Napi::Buffer<uint8_t>::Copy(
|
|
128
|
+
env, recvBuffer_.data(), recvLength_);
|
|
129
|
+
deferred_.Resolve(buffer);
|
|
130
|
+
} else {
|
|
131
|
+
deferred_.Reject(Napi::Error::New(env, GetPCSCErrorString(result_)).Value());
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
void TransmitWorker::OnError(const Napi::Error& error) {
|
|
136
|
+
deferred_.Reject(error.Value());
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// ============================================================================
|
|
140
|
+
// ControlWorker
|
|
141
|
+
// ============================================================================
|
|
142
|
+
|
|
143
|
+
ControlWorker::ControlWorker(
|
|
144
|
+
Napi::Env env,
|
|
145
|
+
SCARDHANDLE card,
|
|
146
|
+
DWORD controlCode,
|
|
147
|
+
std::vector<uint8_t> sendBuffer,
|
|
148
|
+
Napi::Promise::Deferred deferred)
|
|
149
|
+
: Napi::AsyncWorker(env),
|
|
150
|
+
card_(card),
|
|
151
|
+
controlCode_(controlCode),
|
|
152
|
+
sendBuffer_(std::move(sendBuffer)),
|
|
153
|
+
bytesReturned_(0),
|
|
154
|
+
result_(SCARD_S_SUCCESS),
|
|
155
|
+
deferred_(deferred) {
|
|
156
|
+
// Pre-allocate receive buffer
|
|
157
|
+
recvBuffer_.resize(256);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
void ControlWorker::Execute() {
|
|
161
|
+
result_ = SCardControl(
|
|
162
|
+
card_,
|
|
163
|
+
controlCode_,
|
|
164
|
+
sendBuffer_.empty() ? nullptr : sendBuffer_.data(),
|
|
165
|
+
static_cast<DWORD>(sendBuffer_.size()),
|
|
166
|
+
recvBuffer_.data(),
|
|
167
|
+
static_cast<DWORD>(recvBuffer_.size()),
|
|
168
|
+
&bytesReturned_
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
void ControlWorker::OnOK() {
|
|
173
|
+
Napi::Env env = Env();
|
|
174
|
+
|
|
175
|
+
if (result_ == SCARD_S_SUCCESS) {
|
|
176
|
+
Napi::Buffer<uint8_t> buffer = Napi::Buffer<uint8_t>::Copy(
|
|
177
|
+
env, recvBuffer_.data(), bytesReturned_);
|
|
178
|
+
deferred_.Resolve(buffer);
|
|
179
|
+
} else {
|
|
180
|
+
deferred_.Reject(Napi::Error::New(env, GetPCSCErrorString(result_)).Value());
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
void ControlWorker::OnError(const Napi::Error& error) {
|
|
185
|
+
deferred_.Reject(error.Value());
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// ============================================================================
|
|
189
|
+
// ConnectWorker
|
|
190
|
+
// ============================================================================
|
|
191
|
+
|
|
192
|
+
ConnectWorker::ConnectWorker(
|
|
193
|
+
Napi::Env env,
|
|
194
|
+
SCARDCONTEXT context,
|
|
195
|
+
std::string readerName,
|
|
196
|
+
DWORD shareMode,
|
|
197
|
+
DWORD preferredProtocols,
|
|
198
|
+
Napi::Promise::Deferred deferred)
|
|
199
|
+
: Napi::AsyncWorker(env),
|
|
200
|
+
context_(context),
|
|
201
|
+
readerName_(std::move(readerName)),
|
|
202
|
+
shareMode_(shareMode),
|
|
203
|
+
preferredProtocols_(preferredProtocols),
|
|
204
|
+
card_(0),
|
|
205
|
+
activeProtocol_(0),
|
|
206
|
+
result_(SCARD_S_SUCCESS),
|
|
207
|
+
deferred_(deferred) {
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
void ConnectWorker::Execute() {
|
|
211
|
+
result_ = SCardConnect(
|
|
212
|
+
context_,
|
|
213
|
+
readerName_.c_str(),
|
|
214
|
+
shareMode_,
|
|
215
|
+
preferredProtocols_,
|
|
216
|
+
&card_,
|
|
217
|
+
&activeProtocol_
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
void ConnectWorker::OnOK() {
|
|
222
|
+
Napi::Env env = Env();
|
|
223
|
+
|
|
224
|
+
if (result_ == SCARD_S_SUCCESS) {
|
|
225
|
+
Napi::Object card = PCSCCard::NewInstance(env, card_, activeProtocol_, readerName_);
|
|
226
|
+
deferred_.Resolve(card);
|
|
227
|
+
} else {
|
|
228
|
+
deferred_.Reject(Napi::Error::New(env, GetPCSCErrorString(result_)).Value());
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
void ConnectWorker::OnError(const Napi::Error& error) {
|
|
233
|
+
deferred_.Reject(error.Value());
|
|
234
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <napi.h>
|
|
4
|
+
#include <vector>
|
|
5
|
+
#include <string>
|
|
6
|
+
#include "platform/pcsc.h"
|
|
7
|
+
|
|
8
|
+
// Async worker for SCardGetStatusChange
|
|
9
|
+
class WaitForChangeWorker : public Napi::AsyncWorker {
|
|
10
|
+
public:
|
|
11
|
+
WaitForChangeWorker(Napi::Env env,
|
|
12
|
+
SCARDCONTEXT context,
|
|
13
|
+
std::vector<std::string> readerNames,
|
|
14
|
+
std::vector<DWORD> currentStates,
|
|
15
|
+
DWORD timeout,
|
|
16
|
+
Napi::Promise::Deferred deferred);
|
|
17
|
+
|
|
18
|
+
void Execute() override;
|
|
19
|
+
void OnOK() override;
|
|
20
|
+
void OnError(const Napi::Error& error) override;
|
|
21
|
+
|
|
22
|
+
private:
|
|
23
|
+
SCARDCONTEXT context_;
|
|
24
|
+
std::vector<std::string> readerNames_;
|
|
25
|
+
std::vector<SCARD_READERSTATE> states_;
|
|
26
|
+
DWORD timeout_;
|
|
27
|
+
LONG result_;
|
|
28
|
+
Napi::Promise::Deferred deferred_;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// Async worker for SCardTransmit
|
|
32
|
+
class TransmitWorker : public Napi::AsyncWorker {
|
|
33
|
+
public:
|
|
34
|
+
TransmitWorker(Napi::Env env,
|
|
35
|
+
SCARDHANDLE card,
|
|
36
|
+
DWORD protocol,
|
|
37
|
+
std::vector<uint8_t> sendBuffer,
|
|
38
|
+
Napi::Promise::Deferred deferred);
|
|
39
|
+
|
|
40
|
+
void Execute() override;
|
|
41
|
+
void OnOK() override;
|
|
42
|
+
void OnError(const Napi::Error& error) override;
|
|
43
|
+
|
|
44
|
+
private:
|
|
45
|
+
SCARDHANDLE card_;
|
|
46
|
+
DWORD protocol_;
|
|
47
|
+
std::vector<uint8_t> sendBuffer_;
|
|
48
|
+
std::vector<uint8_t> recvBuffer_;
|
|
49
|
+
DWORD recvLength_;
|
|
50
|
+
LONG result_;
|
|
51
|
+
Napi::Promise::Deferred deferred_;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// Async worker for SCardControl
|
|
55
|
+
class ControlWorker : public Napi::AsyncWorker {
|
|
56
|
+
public:
|
|
57
|
+
ControlWorker(Napi::Env env,
|
|
58
|
+
SCARDHANDLE card,
|
|
59
|
+
DWORD controlCode,
|
|
60
|
+
std::vector<uint8_t> sendBuffer,
|
|
61
|
+
Napi::Promise::Deferred deferred);
|
|
62
|
+
|
|
63
|
+
void Execute() override;
|
|
64
|
+
void OnOK() override;
|
|
65
|
+
void OnError(const Napi::Error& error) override;
|
|
66
|
+
|
|
67
|
+
private:
|
|
68
|
+
SCARDHANDLE card_;
|
|
69
|
+
DWORD controlCode_;
|
|
70
|
+
std::vector<uint8_t> sendBuffer_;
|
|
71
|
+
std::vector<uint8_t> recvBuffer_;
|
|
72
|
+
DWORD bytesReturned_;
|
|
73
|
+
LONG result_;
|
|
74
|
+
Napi::Promise::Deferred deferred_;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
// Async worker for SCardConnect
|
|
78
|
+
class ConnectWorker : public Napi::AsyncWorker {
|
|
79
|
+
public:
|
|
80
|
+
ConnectWorker(Napi::Env env,
|
|
81
|
+
SCARDCONTEXT context,
|
|
82
|
+
std::string readerName,
|
|
83
|
+
DWORD shareMode,
|
|
84
|
+
DWORD preferredProtocols,
|
|
85
|
+
Napi::Promise::Deferred deferred);
|
|
86
|
+
|
|
87
|
+
void Execute() override;
|
|
88
|
+
void OnOK() override;
|
|
89
|
+
void OnError(const Napi::Error& error) override;
|
|
90
|
+
|
|
91
|
+
private:
|
|
92
|
+
SCARDCONTEXT context_;
|
|
93
|
+
std::string readerName_;
|
|
94
|
+
DWORD shareMode_;
|
|
95
|
+
DWORD preferredProtocols_;
|
|
96
|
+
SCARDHANDLE card_;
|
|
97
|
+
DWORD activeProtocol_;
|
|
98
|
+
LONG result_;
|
|
99
|
+
Napi::Promise::Deferred deferred_;
|
|
100
|
+
};
|