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);