2
FreeRDP: A Remote Desktop Protocol client.
3
Redirected Smart Card Device Service
5
Copyright 2011 O.S. Systems Software Ltda.
6
Copyright 2011 Eduardo Fiss Beloni <beloni@ossystems.com.br>
7
Copyright 2011 Anthony Tong <atong@trustedcs.com>
9
Licensed under the Apache License, Version 2.0 (the "License");
10
you may not use this file except in compliance with the License.
11
You may obtain a copy of the License at
13
http://www.apache.org/licenses/LICENSE-2.0
15
Unless required by applicable law or agreed to in writing, software
16
distributed under the License is distributed on an "AS IS" BASIS,
17
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
See the License for the specific language governing permissions and
19
limitations under the License.
28
#include <freerdp/utils/list.h>
29
#include <freerdp/utils/thread.h>
30
#include <freerdp/utils/svc_plugin.h>
32
#include "rdpdr_types.h"
33
#include "rdpdr_constants.h"
35
#include "scard_main.h"
39
scard_free(DEVICE* dev)
41
SCARD_DEVICE* scard = (SCARD_DEVICE*)dev;
44
freerdp_thread_stop(scard->thread);
45
freerdp_thread_free(scard->thread);
47
while ((irp = (IRP*)list_dequeue(scard->irp_list)) != NULL)
49
list_free(scard->irp_list);
57
scard_process_irp(SCARD_DEVICE* scard, IRP* irp)
59
switch (irp->MajorFunction)
61
case IRP_MJ_DEVICE_CONTROL:
62
scard_device_control(scard, irp);
66
printf("MajorFunction 0x%X unexpected for smartcards.", irp->MajorFunction);
67
DEBUG_WARN("Smartcard MajorFunction 0x%X not supported.", irp->MajorFunction);
68
irp->IoStatus = STATUS_NOT_SUPPORTED;
76
scard_process_irp_list(SCARD_DEVICE* scard)
80
while (!freerdp_thread_is_stopped(scard->thread))
82
freerdp_thread_lock(scard->thread);
83
irp = (IRP *) list_dequeue(scard->irp_list);
84
freerdp_thread_unlock(scard->thread);
89
scard_process_irp(scard, irp);
94
struct scard_irp_thread_args {
97
freerdp_thread* thread;
102
scard_process_irp_thread_func(struct scard_irp_thread_args* args)
104
scard_process_irp(args->scard, args->irp);
106
freerdp_thread_free(args->thread);
112
scard_thread_func(void* arg)
114
SCARD_DEVICE* scard = (SCARD_DEVICE*) arg;
118
freerdp_thread_wait(scard->thread);
120
if (freerdp_thread_is_stopped(scard->thread))
123
freerdp_thread_reset(scard->thread);
124
scard_process_irp_list(scard);
127
freerdp_thread_quit(scard->thread);
134
scard_irp_request(DEVICE* device, IRP* irp)
136
SCARD_DEVICE* scard = (SCARD_DEVICE*)device;
138
if (irp->MajorFunction == IRP_MJ_DEVICE_CONTROL &&
142
* certain potentially long running operations
143
* get their own thread
144
* TODO: revise this mechanism.. maybe worker pool
146
struct scard_irp_thread_args *args = xmalloc(sizeof(struct scard_irp_thread_args));
149
args->thread = freerdp_thread_new();
152
freerdp_thread_start(args->thread, scard_process_irp_thread_func, args);
157
freerdp_thread_lock(scard->thread);
158
list_enqueue(scard->irp_list, irp);
159
freerdp_thread_unlock(scard->thread);
161
freerdp_thread_signal(scard->thread);
166
DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
173
name = (char *)pEntryPoints->plugin_data->data[1];
174
path = (char *)pEntryPoints->plugin_data->data[2];
178
/* TODO: check if server supports sc redirect (version 5.1) */
180
scard = xnew(SCARD_DEVICE);
182
scard->device.type = RDPDR_DTYP_SMARTCARD;
183
scard->device.name = "SCARD";
184
scard->device.IRPRequest = scard_irp_request;
185
scard->device.Free = scard_free;
187
length = strlen(scard->device.name);
188
scard->device.data = stream_new(length + 1);
190
for (i = 0; i <= length; i++)
191
stream_write_uint8(scard->device.data, name[i] < 0 ? '_' : name[i]);
195
scard->irp_list = list_new();
196
scard->thread = freerdp_thread_new();
198
pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE *)scard);
200
freerdp_thread_start(scard->thread, scard_thread_func, scard);