smartcard 0.4.11 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,195 +0,0 @@
1
- #include "pcsc.h"
2
-
3
- #ifdef MAKE_RDOC_HAPPY
4
- mSmartcard = rb_define_module("Smartcard");
5
- mPcsc = rb_define_module_under(mSmartcard, "PCSC");
6
- #endif
7
-
8
- void Init_PCSC_Consts() {
9
- /* MAX_ATR_SIZE : Maximum ATR size. */
10
- rb_define_const(mPcsc, "MAX_ATR_SIZE", INT2NUM(MAX_ATR_SIZE));
11
-
12
- /* SCARD_S_SUCCESS : All is good. */
13
- rb_define_const(mPcsc, "SCARD_S_SUCCESS", INT2NUM(SCARD_S_SUCCESS));
14
- /* SCARD_F_INTERNAL_ERROR : An internal consistency check failed. */
15
- rb_define_const(mPcsc, "SCARD_F_INTERNAL_ERROR", INT2NUM(SCARD_F_INTERNAL_ERROR));
16
- /* SCARD_E_CANCELLED : The action was cancelled by an SCardCancel request. */
17
- rb_define_const(mPcsc, "SCARD_E_CANCELLED", INT2NUM(SCARD_E_CANCELLED));
18
- /* SCARD_E_INVALID_HANDLE : The supplied handle was invalid. */
19
- rb_define_const(mPcsc, "SCARD_E_INVALID_HANDLE", INT2NUM(SCARD_E_INVALID_HANDLE));
20
- /* MAX_ATR_SIZE : One or more of the supplied parameters could not be properly interpreted. */
21
- rb_define_const(mPcsc, "SCARD_E_INVALID_PARAMETER", INT2NUM(MAX_ATR_SIZE));
22
- /* SCARD_E_INVALID_TARGET : Registry startup information is missing or invalid. */
23
- rb_define_const(mPcsc, "SCARD_E_INVALID_TARGET", INT2NUM(SCARD_E_INVALID_TARGET));
24
- /* SCARD_E_NO_MEMORY : Not enough memory available to complete this command. */
25
- rb_define_const(mPcsc, "SCARD_E_NO_MEMORY", INT2NUM(SCARD_E_NO_MEMORY));
26
- /* SCARD_F_WAITED_TOO_LONG : An internal consistency timer has expired. */
27
- rb_define_const(mPcsc, "SCARD_F_WAITED_TOO_LONG", INT2NUM(SCARD_F_WAITED_TOO_LONG));
28
- /* SCARD_E_INSUFFICIENT_BUFFER : The data buffer to receive returned data is too small for the returned data. */
29
- rb_define_const(mPcsc, "SCARD_E_INSUFFICIENT_BUFFER", INT2NUM(SCARD_E_INSUFFICIENT_BUFFER));
30
- /* SCARD_E_UNKNOWN_READER : The specified reader name is not recognized. */
31
- rb_define_const(mPcsc, "SCARD_E_UNKNOWN_READER", INT2NUM(SCARD_E_UNKNOWN_READER));
32
- /* SCARD_E_SHARING_VIOLATION : The user-specified timeout value has expired. */
33
- rb_define_const(mPcsc, "SCARD_E_SHARING_VIOLATION", INT2NUM(SCARD_E_SHARING_VIOLATION));
34
- /* SCARD_E_NO_SMARTCARD : The smart card cannot be accessed because of other connections outstanding. */
35
- rb_define_const(mPcsc, "SCARD_E_NO_SMARTCARD", INT2NUM(SCARD_E_NO_SMARTCARD));
36
- /* SCARD_E_TIMEOUT : The operation requires a Smart Card, but no Smart Card is currently in the device. */
37
- rb_define_const(mPcsc, "SCARD_E_TIMEOUT", INT2NUM(SCARD_E_TIMEOUT));
38
- /* SCARD_E_UNKNOWN_CARD : The specified smart card name is not recognized. */
39
- rb_define_const(mPcsc, "SCARD_E_UNKNOWN_CARD", INT2NUM(SCARD_E_UNKNOWN_CARD));
40
- /* SCARD_E_CANT_DISPOSE : The system could not dispose of the media in the requested manner. */
41
- rb_define_const(mPcsc, "SCARD_E_CANT_DISPOSE", INT2NUM(SCARD_E_CANT_DISPOSE));
42
- /* SCARD_E_PROTO_MISMATCH : The requested protocols are incompatible with the protocol currently in use with the smart card. */
43
- rb_define_const(mPcsc, "SCARD_E_PROTO_MISMATCH", INT2NUM(SCARD_E_PROTO_MISMATCH));
44
- /* SCARD_E_NOT_READY : The reader or smart card is not ready to accept commands. */
45
- rb_define_const(mPcsc, "SCARD_E_NOT_READY", INT2NUM(SCARD_E_NOT_READY));
46
- /* SCARD_E_INVALID_VALUE : One or more of the supplied parameters values could not be properly interpreted. */
47
- rb_define_const(mPcsc, "SCARD_E_INVALID_VALUE", INT2NUM(SCARD_E_INVALID_VALUE));
48
- /* SCARD_E_SYSTEM_CANCELLED : The action was cancelled by the system, presumably to log off or shut down. */
49
- rb_define_const(mPcsc, "SCARD_E_SYSTEM_CANCELLED", INT2NUM(SCARD_E_SYSTEM_CANCELLED));
50
- /* SCARD_F_COMM_ERROR : An internal communications error has been detected. */
51
- rb_define_const(mPcsc, "SCARD_F_COMM_ERROR", INT2NUM(SCARD_F_COMM_ERROR));
52
- /* SCARD_F_UNKNOWN_ERROR : An internal error has been detected, but the source is unknown. */
53
- rb_define_const(mPcsc, "SCARD_F_UNKNOWN_ERROR", INT2NUM(SCARD_F_UNKNOWN_ERROR));
54
- /* SCARD_E_INVALID_ATR : An ATR obtained from the registry is not a valid ATR string. */
55
- rb_define_const(mPcsc, "SCARD_E_INVALID_ATR", INT2NUM(SCARD_E_INVALID_ATR));
56
- /* SCARD_E_NOT_TRANSACTED : An attempt was made to end a non-existent transaction. */
57
- rb_define_const(mPcsc, "SCARD_E_NOT_TRANSACTED", INT2NUM(SCARD_E_NOT_TRANSACTED));
58
- /* SCARD_E_READER_UNAVAILABLE : The specified reader is not currently available for use. */
59
- rb_define_const(mPcsc, "SCARD_E_READER_UNAVAILABLE", INT2NUM(SCARD_E_READER_UNAVAILABLE));
60
- /* SCARD_W_UNSUPPORTED_CARD : The reader cannot communicate with the card, due to ATR string configuration conflicts. */
61
- rb_define_const(mPcsc, "SCARD_W_UNSUPPORTED_CARD", INT2NUM(SCARD_W_UNSUPPORTED_CARD));
62
- /* SCARD_W_UNRESPONSIVE_CARD : The smart card is not responding to a reset. */
63
- rb_define_const(mPcsc, "SCARD_W_UNRESPONSIVE_CARD", INT2NUM(SCARD_W_UNRESPONSIVE_CARD));
64
- /* SCARD_W_UNPOWERED_CARD : Power has been removed from the smart card, so that further communication is not possible. */
65
- rb_define_const(mPcsc, "SCARD_W_UNPOWERED_CARD", INT2NUM(SCARD_W_UNPOWERED_CARD));
66
- /* SCARD_W_RESET_CARD : The smart card has been reset, so any shared state information is invalid. */
67
- rb_define_const(mPcsc, "SCARD_W_RESET_CARD", INT2NUM(SCARD_W_RESET_CARD));
68
- /* SCARD_W_REMOVED_CARD : The smart card has been removed, so further communication is not possible. */
69
- rb_define_const(mPcsc, "SCARD_W_REMOVED_CARD", INT2NUM(SCARD_W_REMOVED_CARD));
70
- /* SCARD_E_PCI_TOO_SMALL : The PCI Receive buffer was too small. */
71
- rb_define_const(mPcsc, "SCARD_E_PCI_TOO_SMALL", INT2NUM(SCARD_E_PCI_TOO_SMALL));
72
- /* SCARD_E_READER_UNSUPPORTED : The reader driver does not meet minimal requirements for support. */
73
- rb_define_const(mPcsc, "SCARD_E_READER_UNSUPPORTED", INT2NUM(SCARD_E_READER_UNSUPPORTED));
74
- /* SCARD_E_DUPLICATE_READER : The reader driver did not produce a unique reader name. */
75
- rb_define_const(mPcsc, "SCARD_E_DUPLICATE_READER", INT2NUM(SCARD_E_DUPLICATE_READER));
76
- /* SCARD_E_CARD_UNSUPPORTED : The smart card does not meet minimal requirements for support. */
77
- rb_define_const(mPcsc, "SCARD_E_CARD_UNSUPPORTED", INT2NUM(SCARD_E_CARD_UNSUPPORTED));
78
- /* SCARD_E_NO_SERVICE : The Smart card resource manager is not running. */
79
- rb_define_const(mPcsc, "SCARD_E_NO_SERVICE", INT2NUM(SCARD_E_NO_SERVICE));
80
- /* SCARD_E_SERVICE_STOPPED : The Smart card resource manager has shut down. */
81
- rb_define_const(mPcsc, "SCARD_E_SERVICE_STOPPED", INT2NUM(SCARD_E_SERVICE_STOPPED));
82
- #if defined(SCARD_E_NO_READERS_AVAILABLE)
83
- /* SCARD_E_NO_READERS_AVAILABLE : Cannot find a smart card reader. */
84
- rb_define_const(mPcsc, "SCARD_E_NO_READERS_AVAILABLE", INT2NUM(SCARD_E_NO_READERS_AVAILABLE));
85
- #endif /* SCARD_E_NO_READERS_AVAILABLE */
86
-
87
- /* SCARD_SCOPE_USER : Scope in user space. */
88
- rb_define_const(mPcsc, "SCOPE_USER", INT2NUM(SCARD_SCOPE_USER));
89
- /* SCARD_SCOPE_TERMINAL : Scope in terminal. */
90
- rb_define_const(mPcsc, "SCOPE_TERMINAL", INT2NUM(SCARD_SCOPE_TERMINAL));
91
- /* SCARD_SCOPE_SYSTEM : Scope in system. */
92
- rb_define_const(mPcsc, "SCOPE_SYSTEM", INT2NUM(SCARD_SCOPE_SYSTEM));
93
-
94
- /* SCARD_STATE_UNAWARE : App wants status. */
95
- rb_define_const(mPcsc, "STATE_UNAWARE", INT2NUM(SCARD_STATE_UNAWARE));
96
- /* SCARD_STATE_IGNORE : Ignore this reader. */
97
- rb_define_const(mPcsc, "STATE_IGNORE", INT2NUM(SCARD_STATE_IGNORE));
98
- /* SCARD_STATE_CHANGED : State has changed. */
99
- rb_define_const(mPcsc, "STATE_CHANGED", INT2NUM(SCARD_STATE_CHANGED));
100
- /* SCARD_STATE_UNKNOWN : Reader unknown. */
101
- rb_define_const(mPcsc, "STATE_UNKNOWN", INT2NUM(SCARD_STATE_UNKNOWN));
102
- /* SCARD_STATE_UNAVAILABLE : Status unavailable. */
103
- rb_define_const(mPcsc, "STATE_UNAVAILABLE", INT2NUM(SCARD_STATE_UNAVAILABLE));
104
- /* SCARD_STATE_EMPTY : Card removed. */
105
- rb_define_const(mPcsc, "STATE_EMPTY", INT2NUM(SCARD_STATE_EMPTY));
106
- /* SCARD_STATE_PRESENT : Card inserted. */
107
- rb_define_const(mPcsc, "STATE_PRESENT", INT2NUM(SCARD_STATE_PRESENT));
108
- /* SCARD_STATE_ATRMATCH : ATR matches card. */
109
- rb_define_const(mPcsc, "STATE_ATRMATCH", INT2NUM(SCARD_STATE_ATRMATCH));
110
- /* SCARD_STATE_EXCLUSIVE : Exclusive Mode. */
111
- rb_define_const(mPcsc, "STATE_EXCLUSIVE", INT2NUM(SCARD_STATE_EXCLUSIVE));
112
- /* SCARD_STATE_INUSE : Shared Mode. */
113
- rb_define_const(mPcsc, "STATE_INUSE", INT2NUM(SCARD_STATE_INUSE));
114
- /* SCARD_STATE_MUTE : Unresponsive card. */
115
- rb_define_const(mPcsc, "STATE_MUTE", INT2NUM(SCARD_STATE_MUTE));
116
- #if defined(SCARD_STATE_UNPOWERED)
117
- /* SCARD_STATE_UNPOWERED : Unpowered card. */
118
- rb_define_const(mPcsc, "STATE_UNPOWERED", INT2NUM(SCARD_STATE_UNPOWERED));
119
- #endif /* SCARD_STATE_UNPOWERED */
120
-
121
- /* INFINITE : Infinite timeout. */
122
- rb_define_const(mPcsc, "INFINITE_TIMEOUT", UINT2NUM(INFINITE));
123
-
124
-
125
- /* SCARD_UNKNOWNU : Card is absent. */
126
- rb_define_const(mPcsc, "STATUS_ABSENT", INT2NUM(SCARD_ABSENT));
127
- /* SCARD_PRESENT : Card is present. */
128
- rb_define_const(mPcsc, "STATUS_PRESENT", INT2NUM(SCARD_PRESENT));
129
- /* SCARD_SWALLOWED : Card not powered. */
130
- rb_define_const(mPcsc, "STATUS_SWALLOWED", INT2NUM(SCARD_SWALLOWED));
131
- /* SCARD_POWERED : Card is powered. */
132
- rb_define_const(mPcsc, "STATUS_POWERED", INT2NUM(SCARD_POWERED));
133
- /* SCARD_NEGOTIABLE : Ready for PTS. */
134
- rb_define_const(mPcsc, "STATUS_NEGOTIABLE", INT2NUM(SCARD_NEGOTIABLE));
135
- /* SCARD_SPECIFIC : PTS has been set. */
136
- rb_define_const(mPcsc, "STATUS_SPECIFIC", INT2NUM(SCARD_SPECIFIC));
137
-
138
- #if defined(SCARD_PROTOCOL_UNSET)
139
- /* SCARD_PROTOCOL_UNSET : Protocol not set. */
140
- rb_define_const(mPcsc, "PROTOCOL_UNSET", INT2NUM(SCARD_PROTOCOL_UNSET));
141
- #endif /* SCARD_PROTOCOL_UNSET */
142
- /* SCARD_PROTOCOL_T0 : T=0 active protocol. */
143
- rb_define_const(mPcsc, "PROTOCOL_T0", INT2NUM(SCARD_PROTOCOL_T0));
144
- /* SCARD_PROTOCOL_T1 : T=1 active protocol. */
145
- rb_define_const(mPcsc, "PROTOCOL_T1", INT2NUM(SCARD_PROTOCOL_T1));
146
- /* SCARD_PROTOCOL_RAW : Raw active protocol. */
147
- rb_define_const(mPcsc, "PROTOCOL_RAW", INT2NUM(SCARD_PROTOCOL_RAW));
148
- #if defined(SCARD_PROTOCOL_UNSET)
149
- /* SCARD_PROTOCOL_T15 : T=15 protocol. */
150
- rb_define_const(mPcsc, "PROTOCOL_T15", INT2NUM(SCARD_PROTOCOL_T15));
151
- #endif /* SCARD_PROTOCOL_UNSET */
152
- /* SCARD_PROTOCOL_ANY : IFD determines protocol. */
153
- rb_define_const(mPcsc, "PROTOCOL_ANY", INT2NUM(SCARD_PROTOCOL_ANY));
154
-
155
- /* SCARD_SHARE_EXCLUSIVE : Exclusive mode only. */
156
- rb_define_const(mPcsc, "SHARE_EXCLUSIVE", INT2NUM(SCARD_SHARE_EXCLUSIVE));
157
- /* SCARD_SHARE_SHARED : Shared mode only. */
158
- rb_define_const(mPcsc, "SHARE_SHARED", INT2NUM(SCARD_SHARE_SHARED));
159
- /* SCARD_SHARE_DIRECT : Raw mode only. */
160
- rb_define_const(mPcsc, "SHARE_DIRECT", INT2NUM(SCARD_SHARE_DIRECT));
161
-
162
- /* SCARD_LEAVE_CARD : Do nothing on close. */
163
- rb_define_const(mPcsc, "DISPOSITION_LEAVE", INT2NUM(SCARD_LEAVE_CARD));
164
- /* SCARD_RESET_CARD : Reset on close. */
165
- rb_define_const(mPcsc, "DISPOSITION_RESET", INT2NUM(SCARD_RESET_CARD));
166
- /* SCARD_UNPOWER_CARD : Power down on close. */
167
- rb_define_const(mPcsc, "DISPOSITION_UNPOWER", INT2NUM(SCARD_UNPOWER_CARD));
168
- /* SCARD_EJECT_CARD : Eject on close. */
169
- rb_define_const(mPcsc, "DISPOSITION_EJECT", INT2NUM(SCARD_EJECT_CARD));
170
-
171
- /* SCARD_LEAVE_CARD : Do nothing. */
172
- rb_define_const(mPcsc, "INITIALIZATION_LEAVE", INT2NUM(SCARD_LEAVE_CARD));
173
- /* SCARD_RESET_CARD : Reset the card (warm reset). */
174
- rb_define_const(mPcsc, "INITIALIZATION_RESET", INT2NUM(SCARD_RESET_CARD));
175
- /* SCARD_UNPOWER_CARD : Power down the card (cold reset). */
176
- rb_define_const(mPcsc, "INITIALIZATION_UNPOWER", INT2NUM(SCARD_UNPOWER_CARD));
177
- /* SCARD_EJECT_CARD : Eject the card. */
178
- rb_define_const(mPcsc, "INITIALIZATION_EJECT", INT2NUM(SCARD_EJECT_CARD));
179
-
180
- /* SCARD_ATTR_ATR_STRING : ATR of the card. */
181
- rb_define_const(mPcsc, "ATTR_ATR_STRING", INT2NUM(SCARD_ATTR_ATR_STRING));
182
- /* SCARD_ATTR_VENDOR_IFD_VERSION : Vendor-supplied interface driver version. */
183
- rb_define_const(mPcsc, "ATTR_VENDOR_IFD_VERSION", INT2NUM(SCARD_ATTR_VENDOR_IFD_VERSION));
184
- /* SCARD_ATTR_VENDOR_NAME : Name of the interface driver version. */
185
- rb_define_const(mPcsc, "ATTR_VENDOR_NAME", INT2NUM(SCARD_ATTR_VENDOR_NAME));
186
- /* SCARD_ATTR_MAXINPUT : Maximum size of an APDU supported by the reader. */
187
- rb_define_const(mPcsc, "ATTR_MAXINPUT", INT2NUM(SCARD_ATTR_MAXINPUT));
188
-
189
- /* SCARD_PCI_T0 : IoRequest for transmitting using the T=0 protocol. */
190
- rb_define_const(mPcsc, "IOREQUEST_T0", _PCSC_IoRequest_lowlevel_new(SCARD_PCI_T0));
191
- /* SCARD_PCI_T1 : IoRequest for transmitting using the T=1 protocol. */
192
- rb_define_const(mPcsc, "IOREQUEST_T1", _PCSC_IoRequest_lowlevel_new(SCARD_PCI_T1));
193
- /* SCARD_PCI_RAW : IoRequest for transmitting using the RAW protocol. */
194
- rb_define_const(mPcsc, "IOREQUEST_RAW", _PCSC_IoRequest_lowlevel_new(SCARD_PCI_RAW));
195
- }
@@ -1,290 +0,0 @@
1
- #include "pcsc.h"
2
-
3
- VALUE cPcscContext;
4
-
5
- /* Wraps a SCARDHANDLE, tracking whether it was released or not, together with the last error that occured on it. */
6
- struct SCardContextEx {
7
- SCARDCONTEXT pcsc_context;
8
- DWORD pcsc_error;
9
- int released;
10
- };
11
-
12
-
13
- /* Custom free for Smartcard::PCSC::Context. Releases the PC/SC context if that was not already done. */
14
- static void PCSC_Context_free(struct SCardContextEx *_context) {
15
- if(_context != NULL) {
16
- if(!_context->released)
17
- SCardReleaseContext(_context->pcsc_context);
18
- xfree(_context);
19
- }
20
- }
21
-
22
- /* Custom allocation for Smartcard::PCSC::Context. Wraps a SCardContextEx structure. */
23
- static VALUE PCSC_Context_alloc(VALUE klass) {
24
- struct SCardContextEx *context;
25
-
26
- VALUE rbContext = Data_Make_Struct(klass, struct SCardContextEx, NULL, PCSC_Context_free, context);
27
- context->released = 1;
28
- return rbContext;
29
- }
30
-
31
- /* :Document-method: new
32
- * call-seq:
33
- * new(scope) --> context
34
- *
35
- * Creates an application context connecting to the PC/SC resource manager.
36
- * A context is required to access every piece of PC/SC functionality.
37
- * Wraps _SCardEstablishContext_ in PC/SC.
38
- *
39
- * +scope+:: scope of the context; use one of the Smartcard::PCSC::SCOPE_ constants
40
- */
41
- static VALUE PCSC_Context_initialize(VALUE self, VALUE scope) {
42
- struct SCardContextEx *context;
43
-
44
- Data_Get_Struct(self, struct SCardContextEx, context);
45
-
46
- context->pcsc_error = SCardEstablishContext(NUM2INT(scope), NULL, NULL, &context->pcsc_context);
47
- if(context->pcsc_error != SCARD_S_SUCCESS)
48
- _PCSC_Exception_raise(context->pcsc_error, "SCardEstablishContext");
49
- else
50
- context->released = 0;
51
- return self;
52
- }
53
-
54
- /* :Document-method: release
55
- * call-seq:
56
- * release() --> self
57
- *
58
- * Destroys the communication context connecting to the PC/SC Resource Manager.
59
- * Should be the last PC/SC function called, because a context is required to access every piece of PC/SC functionality.
60
- * Wraps _SCardReleaseContext_ in PC/SC.
61
- */
62
- static VALUE PCSC_Context_release(VALUE self) {
63
- struct SCardContextEx *context;
64
-
65
- Data_Get_Struct(self, struct SCardContextEx, context);
66
- if(context == NULL) return self;
67
-
68
- if(!context->released) {
69
- context->pcsc_error = SCardReleaseContext(context->pcsc_context);
70
- context->released = 1;
71
- if(context->pcsc_error != SCARD_S_SUCCESS)
72
- _PCSC_Exception_raise(context->pcsc_error, "SCardReleaseContext");
73
- }
74
- return self;
75
- }
76
-
77
- /* :Document-method: is_valid
78
- * call-seq:
79
- * is_valid() --> valid_boolean
80
- *
81
- * Checks if the PC/SC context is still valid.
82
- * A context may become invalid if the resource manager service has been shut down.
83
- * Wraps _SCardIsValidContext_ in PC/SC.
84
- *
85
- * Returns a boolean value with the obvious meaning.
86
- */
87
- static VALUE PCSC_Context_is_valid(VALUE self) {
88
- struct SCardContextEx *context;
89
- Data_Get_Struct(self, struct SCardContextEx, context);
90
- if(context == NULL) return self;
91
-
92
- #if defined(RB_SMARTCARD_OSX_TIGER_HACK) || defined(PCSC_SURROGATE_SCARD_IS_VALID_CONTEXT)
93
- return Qtrue;
94
- #else
95
- context->pcsc_error = SCardIsValidContext(context->pcsc_context);
96
- return (context->pcsc_error == SCARD_S_SUCCESS) ? Qtrue : Qfalse;
97
- #endif
98
- }
99
-
100
- /* :Document-method: list_reader_groups
101
- * call-seq:
102
- * list_reader_groups() --> reader_groups
103
- *
104
- * Retrieves the currently available reader groups on the system.
105
- * Wraps _SCardListReaderGroups_ in PC/SC.
106
- *
107
- * Returns an array of strings containing the names of all the smart-card readers in the system.
108
- */
109
- static VALUE PCSC_Context_list_reader_groups(VALUE self) {
110
- struct SCardContextEx *context;
111
- VALUE rbGroups;
112
- char *groups;
113
- DWORD groups_length;
114
-
115
- Data_Get_Struct(self, struct SCardContextEx, context);
116
- if(context == NULL) return Qnil;
117
-
118
- context->pcsc_error = SCardListReaderGroups(context->pcsc_context, NULL, &groups_length);
119
- if(context->pcsc_error == SCARD_S_SUCCESS) {
120
- groups = ALLOC_N(char, groups_length);
121
- if(groups != NULL) {
122
- context->pcsc_error = SCardListReaderGroups(context->pcsc_context, groups, &groups_length);
123
- if(context->pcsc_error == SCARD_S_SUCCESS) {
124
- rbGroups = PCSC_Internal_multistring_to_ruby_array(groups, groups_length);
125
- xfree(groups);
126
- return rbGroups;
127
- }
128
- else
129
- xfree(groups);
130
- }
131
- }
132
- if(context->pcsc_error != SCARD_S_SUCCESS)
133
- _PCSC_Exception_raise(context->pcsc_error, "SCardListReaderGroups");
134
- return Qnil;
135
- }
136
-
137
- /* :Document-method: list_readers
138
- * call-seq:
139
- * list_readers(reader_groups) --> readers
140
- *
141
- * Retrieves a subset of the currently available card readers in the system.
142
- * Wraps _SCardListReaders_ in PC/SC.
143
- *
144
- * Returns an array of strings containing the names of the card readers in the given groups.
145
- *
146
- * +reader_groups+:: array of strings indicating the reader groups to list; also accepts a string or +nil+ (meaning all readers)
147
- */
148
- static VALUE PCSC_Context_list_readers(VALUE self, VALUE rbGroups) {
149
- struct SCardContextEx *context;
150
- VALUE rbReaders;
151
- char *groups;
152
- DWORD readers_length;
153
-
154
- Data_Get_Struct(self, struct SCardContextEx, context);
155
- if(context == NULL) return Qnil;
156
-
157
- if(PCSC_Internal_ruby_strings_to_multistring(rbGroups, &groups) == 0) {
158
- rb_raise(rb_eArgError, "invalid reader groups set (expecting nil or string or array of strings)");
159
- return Qnil;
160
- }
161
-
162
- context->pcsc_error = SCardListReaders(context->pcsc_context, groups, NULL, &readers_length);
163
- if(context->pcsc_error == SCARD_S_SUCCESS) {
164
- char *readers = ALLOC_N(char, readers_length);
165
- if(readers != NULL) {
166
- context->pcsc_error = SCardListReaders(context->pcsc_context, groups, readers, &readers_length);
167
- if(context->pcsc_error == SCARD_S_SUCCESS) {
168
- rbReaders = PCSC_Internal_multistring_to_ruby_array(readers, readers_length);
169
- xfree(readers);
170
- if(groups != NULL) xfree(groups);
171
- return rbReaders;
172
- }
173
- else
174
- xfree(readers);
175
- }
176
- }
177
- if(groups != NULL) xfree(groups);
178
- if(context->pcsc_error != SCARD_S_SUCCESS)
179
- _PCSC_Exception_raise(context->pcsc_error, "SCardListReaders");
180
- return Qnil;
181
- }
182
-
183
- /* :Document-method: cancel
184
- * call-seq:
185
- * cancel() --> self
186
- *
187
- * Cancels all pending blocking requests on the Context#get_status_change function.
188
- * Wraps _SCardCancel_ in PC/SC.
189
- */
190
- static VALUE PCSC_Context_cancel(VALUE self) {
191
- struct SCardContextEx *context;
192
-
193
- Data_Get_Struct(self, struct SCardContextEx, context);
194
- if(context == NULL) return self;
195
-
196
- context->pcsc_error = SCardCancel(context->pcsc_context);
197
- if(context->pcsc_error != SCARD_S_SUCCESS)
198
- _PCSC_Exception_raise(context->pcsc_error, "SCardCancel");
199
- return self;
200
- }
201
-
202
- /* :Document-method: get_status_change
203
- * call-seq:
204
- * get_status_change(reader_states, timeout) --> self
205
- *
206
- * Blocks until a status change occurs in one of the given readers.
207
- * Wraps _SCardGetStatusChange_ in PC/SC.
208
- *
209
- * +reader_states+:: Smartcard::PCSC::ReaderStates instance indicating the readers to be monitored, and the interesting state changes
210
- * +timeout+:: maximum ammount of time (in milliseconds) to block; use Smartcard::PCSC::INFINITE_TIMEOUT to block forever
211
- *
212
- * The function blocks until the state of one of the readers in +reader_states+ becomes different from the +current_state+ (accessible via
213
- * ReaderStates#set_current_state_of and ReaderStates#current_state_of). The new state is stored in +event_state+ (accessible via
214
- * ReaderStates#set_event_state_of and ReaderStates#event_state_of)
215
- */
216
- static VALUE PCSC_Context_get_status_change(VALUE self, VALUE rbReaderStates, VALUE rbTimeout) {
217
- struct SCardContextEx *context;
218
- SCARD_READERSTATE *reader_states;
219
- size_t reader_states_count;
220
- DWORD timeout;
221
-
222
- Data_Get_Struct(self, struct SCardContextEx, context);
223
- if(context == NULL) return self;
224
-
225
- if(TYPE(rbTimeout) == T_NIL || TYPE(rbTimeout) == T_FALSE)
226
- timeout = INFINITE;
227
- else
228
- timeout = NUM2UINT(rbTimeout);
229
-
230
- if(_PCSC_ReaderStates_lowlevel_get(rbReaderStates, &reader_states, &reader_states_count) == 0)
231
- rb_raise(rb_eArgError, "first parameter is not a ReaderStates instance or nil");
232
- else {
233
- context->pcsc_error = SCardGetStatusChange(context->pcsc_context, timeout, reader_states, reader_states_count);
234
- if(context->pcsc_error != SCARD_S_SUCCESS)
235
- _PCSC_Exception_raise(context->pcsc_error, "SCardGetStatusChange");
236
- }
237
- return self;
238
- }
239
-
240
- /* :Document-method: last_error
241
- * call-seq:
242
- * card.last_error() --> last_error
243
- *
244
- * The error code returned by the last PC/SC call. Useful for recovering from exceptions.
245
- *
246
- * The returned code is a number, and should be one of the Smartcard::PCSC::SCARD_ constants.
247
- * The code indicating correct operation is Smartcard::PCSC::SCARD_S_SUCCESS.
248
- */
249
- static VALUE PCSC_Context_last_error(VALUE self) {
250
- struct SCardContextEx *context;
251
-
252
- Data_Get_Struct(self, struct SCardContextEx, context);
253
- if(context == NULL) return Qnil;
254
-
255
- return UINT2NUM(context->pcsc_error);
256
- }
257
-
258
- #ifdef MAKE_RDOC_HAPPY
259
- mSmartcard = rb_define_module("Smartcard");
260
- mPcsc = rb_define_module_under(mSmartcard, "PCSC");
261
- #endif
262
-
263
- /* :Document-class: Smartcard::PCSC::Context
264
- * Connects Ruby to the PC/SC resource manager.
265
- * Wraps a _SCARDCONTEXT_ structure.
266
- */
267
- void Init_PCSC_Context() {
268
- cPcscContext = rb_define_class_under(mPcsc, "Context", rb_cObject);
269
- rb_define_alloc_func(cPcscContext, PCSC_Context_alloc);
270
- rb_define_method(cPcscContext, "initialize", PCSC_Context_initialize, 1);
271
- rb_define_method(cPcscContext, "release", PCSC_Context_release, 0);
272
- rb_define_method(cPcscContext, "is_valid", PCSC_Context_is_valid, 0);
273
- rb_define_method(cPcscContext, "list_reader_groups", PCSC_Context_list_reader_groups, 0);
274
- rb_define_method(cPcscContext, "list_readers", PCSC_Context_list_readers, 1);
275
- rb_define_method(cPcscContext, "cancel", PCSC_Context_cancel, 0);
276
- rb_define_method(cPcscContext, "get_status_change", PCSC_Context_get_status_change, 2);
277
- rb_define_method(cPcscContext, "last_error", PCSC_Context_last_error, 0);
278
- }
279
-
280
- /* Retrieves the SCARDCONTEXT wrapped into a Smartcard::PCSC::Context instance. */
281
- int _PCSC_Context_lowlevel_get(VALUE rbContext, SCARDCONTEXT *pcsc_context) {
282
- struct SCardContextEx *context;
283
-
284
- if(TYPE(rbContext) != T_DATA || RDATA(rbContext)->dfree != (void (*)(void *))PCSC_Context_free)
285
- return 0;
286
-
287
- Data_Get_Struct(rbContext, struct SCardContextEx, context);
288
- *pcsc_context = context->pcsc_context;
289
- return 1;
290
- }