2012-08-15 01:09:01 +04:00
|
|
|
/**
|
2012-10-09 05:00:07 +04:00
|
|
|
* FreeRDP: A Remote Desktop Protocol Implementation
|
2012-08-15 01:09:01 +04:00
|
|
|
* Smartcard Device Service Virtual Channel
|
|
|
|
*
|
|
|
|
* Copyright (C) Alexi Volkov <alexi@myrealbox.com> 2006
|
|
|
|
* Copyright 2011 O.S. Systems Software Ltda.
|
|
|
|
* Copyright 2011 Anthony Tong <atong@trustedcs.com>
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
2011-10-15 19:30:10 +04:00
|
|
|
#include "config.h"
|
2012-08-15 01:09:01 +04:00
|
|
|
#endif
|
2011-10-15 19:30:10 +04:00
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2014-02-11 07:12:13 +04:00
|
|
|
#include <assert.h>
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2012-11-20 08:49:08 +04:00
|
|
|
#include <winpr/crt.h>
|
2012-12-14 08:54:54 +04:00
|
|
|
#include <winpr/print.h>
|
2013-03-22 00:45:25 +04:00
|
|
|
#include <winpr/stream.h>
|
2014-04-03 23:27:55 +04:00
|
|
|
#include <winpr/smartcard.h>
|
2013-03-22 01:58:18 +04:00
|
|
|
|
|
|
|
#include <freerdp/freerdp.h>
|
2012-10-09 05:00:07 +04:00
|
|
|
#include <freerdp/channels/rdpdr.h>
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
#include "smartcard_main.h"
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-07 00:29:11 +04:00
|
|
|
const char* smartcard_get_ioctl_string(UINT32 ioControlCode, BOOL funcName)
|
2014-04-04 08:56:24 +04:00
|
|
|
{
|
|
|
|
switch (ioControlCode)
|
|
|
|
{
|
|
|
|
case SCARD_IOCTL_ESTABLISHCONTEXT:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardEstablishContext" : "SCARD_IOCTL_ESTABLISHCONTEXT";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_RELEASECONTEXT:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardReleaseContext" : "SCARD_IOCTL_RELEASECONTEXT";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_ISVALIDCONTEXT:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardIsValidContext" : "SCARD_IOCTL_ISVALIDCONTEXT";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_LISTREADERGROUPSA:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardListReaderGroupsA" : "SCARD_IOCTL_LISTREADERGROUPSA";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_LISTREADERGROUPSW:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardListReaderGroupsW" : "SCARD_IOCTL_LISTREADERGROUPSW";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_LISTREADERSA:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardListReadersA" : "SCARD_IOCTL_LISTREADERSA";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_LISTREADERSW:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardListReadersW" : "SCARD_IOCTL_LISTREADERSW";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_INTRODUCEREADERGROUPA:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardIntroduceReaderGroupA" : "SCARD_IOCTL_INTRODUCEREADERGROUPA";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_INTRODUCEREADERGROUPW:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardIntroduceReaderGroupW" : "SCARD_IOCTL_INTRODUCEREADERGROUPW";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_FORGETREADERGROUPA:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardForgetReaderGroupA" : "SCARD_IOCTL_FORGETREADERGROUPA";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_FORGETREADERGROUPW:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardForgetReaderGroupW" : "SCARD_IOCTL_FORGETREADERGROUPW";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_INTRODUCEREADERA:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardIntroduceReaderA" : "SCARD_IOCTL_INTRODUCEREADERA";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_INTRODUCEREADERW:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardIntroduceReaderW" : "SCARD_IOCTL_INTRODUCEREADERW";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_FORGETREADERA:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardForgetReaderA" : "SCARD_IOCTL_FORGETREADERA";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_FORGETREADERW:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardForgetReaderW" : "SCARD_IOCTL_FORGETREADERW";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_ADDREADERTOGROUPA:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardAddReaderToGroupA" : "SCARD_IOCTL_ADDREADERTOGROUPA";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_ADDREADERTOGROUPW:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardAddReaderToGroupW" : "SCARD_IOCTL_ADDREADERTOGROUPW";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_REMOVEREADERFROMGROUPA:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardRemoveReaderFromGroupA" : "SCARD_IOCTL_REMOVEREADERFROMGROUPA";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_REMOVEREADERFROMGROUPW:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardRemoveReaderFromGroupW" : "SCARD_IOCTL_REMOVEREADERFROMGROUPW";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_LOCATECARDSA:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardLocateCardsA" : "SCARD_IOCTL_LOCATECARDSA";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_LOCATECARDSW:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardLocateCardsW" : "SCARD_IOCTL_LOCATECARDSW";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_GETSTATUSCHANGEA:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardGetStatusChangeA" : "SCARD_IOCTL_GETSTATUSCHANGEA";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_GETSTATUSCHANGEW:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardGetStatusChangeW" : "SCARD_IOCTL_GETSTATUSCHANGEW";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_CANCEL:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardCancel" : "SCARD_IOCTL_CANCEL";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_CONNECTA:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardConnectA" : "SCARD_IOCTL_CONNECTA";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_CONNECTW:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardConnectW" : "SCARD_IOCTL_CONNECTW";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_RECONNECT:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardReconnect" : "SCARD_IOCTL_RECONNECT";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_DISCONNECT:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardDisconnect" : "SCARD_IOCTL_DISCONNECT";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_BEGINTRANSACTION:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardBeginTransaction" : "SCARD_IOCTL_BEGINTRANSACTION";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_ENDTRANSACTION:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardEndTransaction" : "SCARD_IOCTL_ENDTRANSACTION";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_STATE:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardState" : "SCARD_IOCTL_STATE";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_STATUSA:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardStatusA" : "SCARD_IOCTL_STATUSA";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_STATUSW:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardStatusW" : "SCARD_IOCTL_STATUSW";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_TRANSMIT:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardTransmit" : "SCARD_IOCTL_TRANSMIT";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_CONTROL:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardControl" : "SCARD_IOCTL_CONTROL";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_GETATTRIB:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardGetAttrib" : "SCARD_IOCTL_GETATTRIB";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_SETATTRIB:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardSetAttrib" : "SCARD_IOCTL_SETATTRIB";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_ACCESSSTARTEDEVENT:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardAccessStartedEvent" : "SCARD_IOCTL_ACCESSSTARTEDEVENT";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_LOCATECARDSBYATRA:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardLocateCardsByATRA" : "SCARD_IOCTL_LOCATECARDSBYATRA";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_LOCATECARDSBYATRW:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardLocateCardsByATRB" : "SCARD_IOCTL_LOCATECARDSBYATRW";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_READCACHEA:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardReadCacheA" : "SCARD_IOCTL_READCACHEA";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_READCACHEW:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardReadCacheW" : "SCARD_IOCTL_READCACHEW";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_WRITECACHEA:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardWriteCacheA" : "SCARD_IOCTL_WRITECACHEA";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_WRITECACHEW:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardWriteCacheW" : "SCARD_IOCTL_WRITECACHEW";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_GETTRANSMITCOUNT:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardGetTransmitCount" : "SCARD_IOCTL_GETTRANSMITCOUNT";
|
2014-04-06 00:06:46 +04:00
|
|
|
case SCARD_IOCTL_RELEASESTARTEDEVENT:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardReleaseStartedEvent" : "SCARD_IOCTL_RELEASESTARTEDEVENT";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_GETREADERICON:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardGetReaderIcon" : "SCARD_IOCTL_GETREADERICON";
|
2014-04-04 08:56:24 +04:00
|
|
|
case SCARD_IOCTL_GETDEVICETYPEID:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardGetDeviceTypeId" : "SCARD_IOCTL_GETDEVICETYPEID";
|
2014-04-04 08:56:24 +04:00
|
|
|
default:
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardUnknown" : "SCARD_IOCTL_UNKNOWN";
|
2014-04-04 08:56:24 +04:00
|
|
|
}
|
|
|
|
|
2014-04-07 00:29:11 +04:00
|
|
|
return funcName ? "SCardUnknown" : "SCARD_IOCTL_UNKNOWN";
|
2014-04-04 08:56:24 +04:00
|
|
|
}
|
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
static UINT32 smartcard_output_string(IRP* irp, char* src, BOOL wide)
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
2012-10-09 11:01:37 +04:00
|
|
|
BYTE* p;
|
2012-10-09 11:26:39 +04:00
|
|
|
UINT32 len;
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2013-04-30 06:35:15 +04:00
|
|
|
p = Stream_Pointer(irp->output);
|
2011-10-15 19:30:10 +04:00
|
|
|
len = strlen(src) + 1;
|
|
|
|
|
|
|
|
if (wide)
|
|
|
|
{
|
2014-04-05 00:45:11 +04:00
|
|
|
UINT32 i;
|
2011-11-22 05:46:58 +04:00
|
|
|
|
2011-10-15 19:30:10 +04:00
|
|
|
for (i = 0; i < len; i++ )
|
|
|
|
{
|
|
|
|
p[2 * i] = src[i] < 0 ? '?' : src[i];
|
|
|
|
p[2 * i + 1] = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
len *= 2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
memcpy(p, src, len);
|
|
|
|
}
|
|
|
|
|
2013-04-30 06:35:15 +04:00
|
|
|
Stream_Seek(irp->output, len);
|
2011-10-15 19:30:10 +04:00
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
static void smartcard_output_alignment(IRP* irp, UINT32 seed)
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
2012-10-09 11:26:39 +04:00
|
|
|
const UINT32 field_lengths = 20;/* Remove the lengths of the fields
|
2012-08-02 02:05:45 +04:00
|
|
|
* RDPDR_HEADER, DeviceID,
|
|
|
|
* CompletionID, and IoStatus
|
|
|
|
* of Section 2.2.1.5.5 of MS-RDPEFS.
|
|
|
|
*/
|
2013-04-30 06:35:15 +04:00
|
|
|
UINT32 size = Stream_GetPosition(irp->output) - field_lengths;
|
2012-10-09 11:26:39 +04:00
|
|
|
UINT32 add = (seed - (size % seed)) % seed;
|
2011-10-15 19:30:10 +04:00
|
|
|
|
|
|
|
if (add > 0)
|
2013-05-09 00:27:21 +04:00
|
|
|
Stream_Zero(irp->output, add);
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
static void smartcard_output_repos(IRP* irp, UINT32 written)
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
2012-10-09 11:26:39 +04:00
|
|
|
UINT32 add = (4 - (written % 4)) % 4;
|
2011-10-15 19:30:10 +04:00
|
|
|
|
|
|
|
if (add > 0)
|
2013-05-09 00:27:21 +04:00
|
|
|
Stream_Zero(irp->output, add);
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
static UINT32 smartcard_output_return(IRP* irp, UINT32 status)
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
2013-05-09 00:27:21 +04:00
|
|
|
Stream_Zero(irp->output, 256);
|
2012-11-21 20:56:40 +04:00
|
|
|
return status;
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
static void smartcard_output_buffer_limit(IRP* irp, char* buffer, unsigned int length, unsigned int highLimit)
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
2014-04-05 00:45:11 +04:00
|
|
|
UINT32 header = (length < 0) ? (0) : ((length > highLimit) ? (highLimit) : (length));
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Write_UINT32(irp->output, header);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
|
|
|
if (length <= 0)
|
|
|
|
{
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Write_UINT32(irp->output, 0);
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (header < length)
|
|
|
|
length = header;
|
|
|
|
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Write(irp->output, buffer, length);
|
2012-11-21 20:56:40 +04:00
|
|
|
smartcard_output_repos(irp, length);
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
static void smartcard_output_buffer(IRP* irp, char* buffer, unsigned int length)
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
2012-11-21 20:56:40 +04:00
|
|
|
smartcard_output_buffer_limit(irp, buffer, length, 0x7FFFFFFF);
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
static void smartcard_output_buffer_start_limit(IRP* irp, int length, int highLimit)
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
|
|
|
int header = (length < 0) ? (0) : ((length > highLimit) ? (highLimit) : (length));
|
|
|
|
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Write_UINT32(irp->output, header);
|
|
|
|
Stream_Write_UINT32(irp->output, 0x00000001); /* Magic DWORD - any non zero */
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
static void smartcard_output_buffer_start(IRP* irp, int length)
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
2012-11-21 20:56:40 +04:00
|
|
|
smartcard_output_buffer_start_limit(irp, length, 0x7FFFFFFF);
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
|
|
|
|
2014-04-04 01:29:12 +04:00
|
|
|
static UINT32 handle_EstablishContext(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
2012-11-21 20:56:40 +04:00
|
|
|
UINT32 status;
|
2011-10-15 19:30:10 +04:00
|
|
|
SCARDCONTEXT hContext = -1;
|
2014-04-06 05:17:54 +04:00
|
|
|
EstablishContext_Call call;
|
|
|
|
EstablishContext_Return ret;
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-04 21:57:28 +04:00
|
|
|
status = smartcard_unpack_establish_context_call(smartcard, irp->input, &call);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-04 21:57:28 +04:00
|
|
|
if (status)
|
|
|
|
return status;
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-04 21:57:28 +04:00
|
|
|
status = SCardEstablishContext(call.dwScope, NULL, NULL, &hContext);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-07 05:28:59 +04:00
|
|
|
ret.Context.cbContext = sizeof(ULONG_PTR);
|
2014-04-06 05:17:54 +04:00
|
|
|
|
|
|
|
Stream_Write_UINT32(irp->output, ret.Context.cbContext); /* cbContext (4 bytes) */
|
2014-04-07 00:29:11 +04:00
|
|
|
Stream_Write_UINT32(irp->output, 0x00020001); /* pbContextNdrPtr (4 bytes) */
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-06 05:17:54 +04:00
|
|
|
Stream_Write_UINT32(irp->output, ret.Context.cbContext);
|
|
|
|
|
|
|
|
if (ret.Context.cbContext > 4)
|
|
|
|
Stream_Write_UINT64(irp->output, hContext);
|
|
|
|
else
|
|
|
|
Stream_Write_UINT32(irp->output, hContext);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-04 01:29:12 +04:00
|
|
|
smartcard->hContext = hContext;
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
smartcard_output_alignment(irp, 8);
|
2014-04-04 01:29:12 +04:00
|
|
|
|
2013-09-13 11:47:18 +04:00
|
|
|
return status;
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
|
|
|
|
2014-04-04 01:29:12 +04:00
|
|
|
static UINT32 handle_ReleaseContext(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
2013-09-12 14:18:35 +04:00
|
|
|
UINT32 status;
|
2014-04-07 05:09:49 +04:00
|
|
|
Context_Call call;
|
|
|
|
SCARDCONTEXT hContext;
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-07 05:09:49 +04:00
|
|
|
status = smartcard_unpack_context_call(smartcard, irp->input, &call);
|
2013-10-24 23:34:14 +04:00
|
|
|
|
2013-09-12 14:18:35 +04:00
|
|
|
if (status)
|
|
|
|
return status;
|
|
|
|
|
2014-04-07 05:09:49 +04:00
|
|
|
hContext = (ULONG_PTR) call.Context.pbContext;
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
status = SCardReleaseContext(hContext);
|
2014-04-07 05:09:49 +04:00
|
|
|
|
|
|
|
smartcard->hContext = 0;
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
smartcard_output_alignment(irp, 8);
|
|
|
|
|
|
|
|
return status;
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
|
|
|
|
2014-04-04 01:29:12 +04:00
|
|
|
static UINT32 handle_IsValidContext(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
2012-11-21 20:56:40 +04:00
|
|
|
UINT32 status;
|
2014-04-07 05:09:49 +04:00
|
|
|
Context_Call call;
|
2011-10-15 19:30:10 +04:00
|
|
|
SCARDCONTEXT hContext;
|
|
|
|
|
2014-04-07 05:09:49 +04:00
|
|
|
status = smartcard_unpack_context_call(smartcard, irp->input, &call);
|
2013-10-24 23:34:14 +04:00
|
|
|
|
2013-09-12 14:18:35 +04:00
|
|
|
if (status)
|
|
|
|
return status;
|
|
|
|
|
2014-04-07 05:09:49 +04:00
|
|
|
hContext = (ULONG_PTR) call.Context.pbContext;
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
status = SCardIsValidContext(hContext);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
smartcard_output_alignment(irp, 8);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
return status;
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
|
|
|
|
2014-04-04 01:29:12 +04:00
|
|
|
static UINT32 handle_ListReaders(SMARTCARD_DEVICE* smartcard, IRP* irp, BOOL wide)
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
2013-09-12 14:18:35 +04:00
|
|
|
UINT32 status;
|
2011-10-15 19:30:10 +04:00
|
|
|
DWORD dwReaders;
|
2014-04-07 05:09:49 +04:00
|
|
|
SCARDCONTEXT hContext;
|
2014-04-04 21:57:28 +04:00
|
|
|
ListReaders_Call call;
|
2014-04-07 05:09:49 +04:00
|
|
|
char *readerList = NULL;
|
|
|
|
char* walker;
|
|
|
|
char* walkerEnd;
|
2011-10-15 19:30:10 +04:00
|
|
|
int elemLength, dataLength;
|
2014-04-07 05:09:49 +04:00
|
|
|
int pos, poslen1, poslen2;
|
2013-09-12 14:18:35 +04:00
|
|
|
|
2014-04-04 21:57:28 +04:00
|
|
|
status = smartcard_unpack_list_readers_call(smartcard, irp->input, &call);
|
2014-04-04 08:56:24 +04:00
|
|
|
|
2014-04-04 21:57:28 +04:00
|
|
|
if (status)
|
2013-09-30 15:29:40 +04:00
|
|
|
goto finish;
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-07 05:09:49 +04:00
|
|
|
hContext = (ULONG_PTR) call.Context.pbContext;
|
2011-10-15 19:30:10 +04:00
|
|
|
|
|
|
|
dwReaders = SCARD_AUTOALLOCATE;
|
2014-04-04 21:57:28 +04:00
|
|
|
status = SCardListReadersA(hContext, (LPCSTR) call.mszGroups, (LPSTR) &readerList, &dwReaders);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
if (status != SCARD_S_SUCCESS)
|
2013-09-12 15:53:15 +04:00
|
|
|
goto finish;
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2013-04-30 06:35:15 +04:00
|
|
|
poslen1 = Stream_GetPosition(irp->output);
|
|
|
|
Stream_Seek_UINT32(irp->output);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Write_UINT32(irp->output, 0x01760650);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2013-04-30 06:35:15 +04:00
|
|
|
poslen2 = Stream_GetPosition(irp->output);
|
|
|
|
Stream_Seek_UINT32(irp->output);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
|
|
|
walker = readerList;
|
2014-04-07 05:09:49 +04:00
|
|
|
walkerEnd = readerList + dwReaders;
|
2011-10-15 19:30:10 +04:00
|
|
|
dataLength = 0;
|
2011-11-22 05:46:58 +04:00
|
|
|
|
2011-10-15 19:30:10 +04:00
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
elemLength = strlen(walker);
|
2014-04-07 05:09:49 +04:00
|
|
|
|
|
|
|
if (!elemLength)
|
2011-10-15 19:30:10 +04:00
|
|
|
break;
|
|
|
|
|
2014-04-07 05:09:49 +04:00
|
|
|
dataLength += smartcard_output_string(irp, walker, wide);
|
|
|
|
walker += elemLength + 1;
|
|
|
|
|
|
|
|
if (walker > walkerEnd)
|
2013-09-12 14:18:35 +04:00
|
|
|
{
|
2014-04-07 05:09:49 +04:00
|
|
|
status = SCARD_F_INTERNAL_ERROR;
|
|
|
|
goto finish;
|
2013-09-12 14:18:35 +04:00
|
|
|
}
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
dataLength += smartcard_output_string(irp, "\0", wide);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2013-04-30 06:35:15 +04:00
|
|
|
pos = Stream_GetPosition(irp->output);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2013-04-30 06:35:15 +04:00
|
|
|
Stream_SetPosition(irp->output, poslen1);
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Write_UINT32(irp->output, dataLength);
|
2013-04-30 06:35:15 +04:00
|
|
|
Stream_SetPosition(irp->output, poslen2);
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Write_UINT32(irp->output, dataLength);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2013-04-30 06:35:15 +04:00
|
|
|
Stream_SetPosition(irp->output, pos);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
smartcard_output_repos(irp, dataLength);
|
|
|
|
smartcard_output_alignment(irp, 8);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2013-09-12 15:53:15 +04:00
|
|
|
finish:
|
|
|
|
if (readerList)
|
|
|
|
{
|
|
|
|
SCardFreeMemory(hContext, readerList);
|
|
|
|
}
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-04 21:57:28 +04:00
|
|
|
if (call.mszGroups)
|
|
|
|
free(call.mszGroups);
|
2013-09-30 15:29:40 +04:00
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
return status;
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
|
|
|
|
2014-04-07 00:29:11 +04:00
|
|
|
static UINT32 handle_GetStatusChangeA(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
2012-11-21 20:56:40 +04:00
|
|
|
LONG status;
|
2014-04-07 00:29:11 +04:00
|
|
|
UINT32 index;
|
2011-10-15 19:30:10 +04:00
|
|
|
SCARDCONTEXT hContext;
|
2014-04-05 19:22:48 +04:00
|
|
|
GetStatusChangeA_Call call;
|
|
|
|
ReaderStateA* readerState = NULL;
|
|
|
|
LPSCARD_READERSTATEA rgReaderState = NULL;
|
|
|
|
LPSCARD_READERSTATEA rgReaderStates = NULL;
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-07 00:29:11 +04:00
|
|
|
status = smartcard_unpack_get_status_change_a_call(smartcard, irp->input, &call);
|
2013-10-24 23:34:14 +04:00
|
|
|
|
2013-09-12 14:18:35 +04:00
|
|
|
if (status)
|
2014-04-07 00:29:11 +04:00
|
|
|
return status;
|
2013-09-12 14:18:35 +04:00
|
|
|
|
2014-04-07 00:29:11 +04:00
|
|
|
hContext = (ULONG_PTR) call.Context.pbContext;
|
|
|
|
|
|
|
|
rgReaderStates = (SCARD_READERSTATEA*) calloc(call.cReaders, sizeof(SCARD_READERSTATEA));
|
|
|
|
|
|
|
|
for (index = 0; index < call.cReaders; index++)
|
2013-09-12 14:18:35 +04:00
|
|
|
{
|
2014-04-07 00:29:11 +04:00
|
|
|
rgReaderState = &rgReaderStates[index];
|
|
|
|
rgReaderState->szReader = (LPCSTR) call.rgReaderStates[index].szReader;
|
|
|
|
rgReaderState->dwCurrentState = call.rgReaderStates[index].Common.dwCurrentState;
|
|
|
|
rgReaderState->dwEventState = call.rgReaderStates[index].Common.dwEventState;
|
|
|
|
rgReaderState->cbAtr = call.rgReaderStates[index].Common.cbAtr;
|
|
|
|
CopyMemory(&(rgReaderState->rgbAtr), &(call.rgReaderStates[index].Common.rgbAtr), 36);
|
2013-09-12 14:18:35 +04:00
|
|
|
}
|
|
|
|
|
2014-04-07 00:29:11 +04:00
|
|
|
status = SCardGetStatusChangeA(hContext, (DWORD) call.dwTimeOut, rgReaderStates, (DWORD) call.cReaders);
|
2013-10-24 23:34:14 +04:00
|
|
|
|
2014-04-07 00:29:11 +04:00
|
|
|
Stream_Write_UINT32(irp->output, call.cReaders); /* (4 bytes) */
|
|
|
|
Stream_Write_UINT32(irp->output, 0x00084dd8); /* (4 bytes) */
|
|
|
|
Stream_Write_UINT32(irp->output, call.cReaders); /* (4 bytes) */
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-07 00:29:11 +04:00
|
|
|
for (index = 0; index < call.cReaders; index++)
|
2013-09-12 15:53:15 +04:00
|
|
|
{
|
2014-04-07 00:29:11 +04:00
|
|
|
rgReaderState = &rgReaderStates[index];
|
|
|
|
Stream_Write_UINT32(irp->output, rgReaderState->dwCurrentState);
|
|
|
|
Stream_Write_UINT32(irp->output, rgReaderState->dwEventState);
|
|
|
|
Stream_Write_UINT32(irp->output, rgReaderState->cbAtr);
|
|
|
|
Stream_Write(irp->output, rgReaderState->rgbAtr, 32);
|
|
|
|
Stream_Zero(irp->output, 4);
|
2013-09-12 15:53:15 +04:00
|
|
|
}
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-07 00:29:11 +04:00
|
|
|
smartcard_output_alignment(irp, 8);
|
2012-11-20 08:49:08 +04:00
|
|
|
|
2014-04-07 00:29:11 +04:00
|
|
|
if (call.rgReaderStates)
|
|
|
|
{
|
|
|
|
for (index = 0; index < call.cReaders; index++)
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
2014-04-07 00:29:11 +04:00
|
|
|
readerState = &call.rgReaderStates[index];
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-07 00:29:11 +04:00
|
|
|
if (readerState->szReader)
|
|
|
|
free((void*) readerState->szReader);
|
|
|
|
readerState->szReader = NULL;
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
2014-04-07 00:29:11 +04:00
|
|
|
free(call.rgReaderStates);
|
|
|
|
free(rgReaderStates);
|
|
|
|
}
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-07 00:29:11 +04:00
|
|
|
return status;
|
|
|
|
}
|
2014-04-05 00:45:11 +04:00
|
|
|
|
2014-04-07 00:29:11 +04:00
|
|
|
static UINT32 handle_GetStatusChangeW(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
|
|
|
{
|
|
|
|
LONG status;
|
|
|
|
UINT32 index;
|
|
|
|
SCARDCONTEXT hContext;
|
|
|
|
GetStatusChangeW_Call call;
|
|
|
|
ReaderStateW* readerState = NULL;
|
|
|
|
LPSCARD_READERSTATEW rgReaderState = NULL;
|
|
|
|
LPSCARD_READERSTATEW rgReaderStates = NULL;
|
2013-09-12 15:53:15 +04:00
|
|
|
|
2014-04-07 00:29:11 +04:00
|
|
|
status = smartcard_unpack_get_status_change_w_call(smartcard, irp->input, &call);
|
2013-09-12 15:53:15 +04:00
|
|
|
|
2014-04-07 00:29:11 +04:00
|
|
|
if (status)
|
|
|
|
return status;
|
2014-04-05 19:22:48 +04:00
|
|
|
|
2014-04-07 00:29:11 +04:00
|
|
|
hContext = (ULONG_PTR) call.Context.pbContext;
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-07 00:29:11 +04:00
|
|
|
rgReaderStates = (SCARD_READERSTATEW*) calloc(call.cReaders, sizeof(SCARD_READERSTATEW));
|
2014-04-05 19:22:48 +04:00
|
|
|
|
2014-04-07 00:29:11 +04:00
|
|
|
for (index = 0; index < call.cReaders; index++)
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
2014-04-07 00:29:11 +04:00
|
|
|
rgReaderState = &rgReaderStates[index];
|
|
|
|
rgReaderState->szReader = (LPCWSTR) call.rgReaderStates[index].szReader;
|
|
|
|
rgReaderState->dwCurrentState = call.rgReaderStates[index].Common.dwCurrentState;
|
|
|
|
rgReaderState->dwEventState = call.rgReaderStates[index].Common.dwEventState;
|
|
|
|
rgReaderState->cbAtr = call.rgReaderStates[index].Common.cbAtr;
|
|
|
|
CopyMemory(&(rgReaderState->rgbAtr), &(call.rgReaderStates[index].Common.rgbAtr), 36);
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
|
|
|
|
2014-04-07 00:29:11 +04:00
|
|
|
status = SCardGetStatusChangeW(hContext, (DWORD) call.dwTimeOut, rgReaderStates, (DWORD) call.cReaders);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-07 00:29:11 +04:00
|
|
|
Stream_Write_UINT32(irp->output, call.cReaders); /* (4 bytes) */
|
|
|
|
Stream_Write_UINT32(irp->output, 0x00084dd8); /* (4 bytes) */
|
|
|
|
Stream_Write_UINT32(irp->output, call.cReaders); /* (4 bytes) */
|
2014-04-05 19:22:48 +04:00
|
|
|
|
2014-04-07 00:29:11 +04:00
|
|
|
for (index = 0; index < call.cReaders; index++)
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
2014-04-07 00:29:11 +04:00
|
|
|
rgReaderState = &rgReaderStates[index];
|
2014-04-05 19:22:48 +04:00
|
|
|
Stream_Write_UINT32(irp->output, rgReaderState->dwCurrentState);
|
|
|
|
Stream_Write_UINT32(irp->output, rgReaderState->dwEventState);
|
|
|
|
Stream_Write_UINT32(irp->output, rgReaderState->cbAtr);
|
|
|
|
Stream_Write(irp->output, rgReaderState->rgbAtr, 32);
|
2013-05-09 00:27:21 +04:00
|
|
|
Stream_Zero(irp->output, 4);
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
smartcard_output_alignment(irp, 8);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-05 19:22:48 +04:00
|
|
|
if (call.rgReaderStates)
|
2013-10-01 15:09:52 +04:00
|
|
|
{
|
2014-04-07 00:29:11 +04:00
|
|
|
for (index = 0; index < call.cReaders; index++)
|
2013-10-01 15:09:52 +04:00
|
|
|
{
|
2014-04-07 00:29:11 +04:00
|
|
|
readerState = &call.rgReaderStates[index];
|
2013-10-01 15:09:52 +04:00
|
|
|
|
2014-04-05 19:22:48 +04:00
|
|
|
if (readerState->szReader)
|
|
|
|
free((void*) readerState->szReader);
|
|
|
|
readerState->szReader = NULL;
|
2013-10-01 15:09:52 +04:00
|
|
|
}
|
2014-04-05 19:22:48 +04:00
|
|
|
free(call.rgReaderStates);
|
|
|
|
free(rgReaderStates);
|
2013-10-01 15:09:52 +04:00
|
|
|
}
|
2013-09-12 15:53:15 +04:00
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
return status;
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
|
|
|
|
2014-04-04 01:29:12 +04:00
|
|
|
static UINT32 handle_Cancel(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
2012-11-21 20:56:40 +04:00
|
|
|
LONG status;
|
2014-04-07 05:09:49 +04:00
|
|
|
Context_Call call;
|
2011-10-15 19:30:10 +04:00
|
|
|
SCARDCONTEXT hContext;
|
|
|
|
|
2014-04-07 05:09:49 +04:00
|
|
|
status = smartcard_unpack_context_call(smartcard, irp->input, &call);
|
2013-10-24 23:34:14 +04:00
|
|
|
|
2013-09-12 14:18:35 +04:00
|
|
|
if (status)
|
|
|
|
return status;
|
|
|
|
|
2014-04-07 05:09:49 +04:00
|
|
|
hContext = (ULONG_PTR) call.Context.pbContext;
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
status = SCardCancel(hContext);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
smartcard_output_alignment(irp, 8);
|
2011-11-22 05:46:58 +04:00
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
return status;
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
|
|
|
|
2014-04-06 00:06:46 +04:00
|
|
|
UINT32 handle_ConnectA(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
2012-11-21 20:56:40 +04:00
|
|
|
LONG status;
|
2011-10-15 19:30:10 +04:00
|
|
|
SCARDCONTEXT hContext;
|
|
|
|
SCARDHANDLE hCard;
|
2014-04-05 19:22:48 +04:00
|
|
|
ConnectA_Call call;
|
|
|
|
Connect_Return ret;
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-05 19:56:02 +04:00
|
|
|
call.szReader = NULL;
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-06 00:06:46 +04:00
|
|
|
status = smartcard_unpack_connect_a_call(smartcard, irp->input, &call);
|
2013-10-24 23:34:14 +04:00
|
|
|
|
2013-09-12 14:18:35 +04:00
|
|
|
if (status)
|
2013-09-12 15:53:15 +04:00
|
|
|
goto finish;
|
2014-04-06 00:06:46 +04:00
|
|
|
|
2014-04-07 00:29:11 +04:00
|
|
|
hContext = (ULONG_PTR) call.Common.Context.pbContext;
|
|
|
|
|
2014-04-06 00:06:46 +04:00
|
|
|
status = SCardConnectA(hContext, (char*) call.szReader, (DWORD) call.Common.dwShareMode,
|
|
|
|
(DWORD) call.Common.dwPreferredProtocols, &hCard, (DWORD*) &ret.dwActiveProtocol);
|
2013-09-12 14:18:35 +04:00
|
|
|
|
2014-04-06 00:06:46 +04:00
|
|
|
smartcard->hCard = hCard;
|
2013-10-24 23:34:14 +04:00
|
|
|
|
2014-04-07 05:09:49 +04:00
|
|
|
ret.hCard.cbHandle = sizeof(ULONG_PTR);
|
2014-04-07 00:29:11 +04:00
|
|
|
ret.hCard.pbHandle = (UINT64) hCard;
|
2014-04-06 04:46:20 +04:00
|
|
|
|
|
|
|
Stream_Write_UINT32(irp->output, 0x00000000); /* (4 bytes) */
|
|
|
|
Stream_Write_UINT32(irp->output, 0x00000000); /* (4 bytes) */
|
|
|
|
Stream_Write_UINT32(irp->output, ret.hCard.cbHandle); /* cbHandle (4 bytes) */
|
2014-04-07 00:29:11 +04:00
|
|
|
Stream_Write_UINT32(irp->output, 0x00020001); /* pbHandleNdrPtr (4 bytes) */
|
2014-04-06 00:06:46 +04:00
|
|
|
Stream_Write_UINT32(irp->output, ret.dwActiveProtocol); /* dwActiveProtocol (4 bytes) */
|
2014-04-06 04:46:20 +04:00
|
|
|
Stream_Write_UINT32(irp->output, ret.hCard.cbHandle);
|
|
|
|
|
|
|
|
if (ret.hCard.cbHandle > 4)
|
2014-04-07 00:29:11 +04:00
|
|
|
Stream_Write_UINT64(irp->output, ret.hCard.pbHandle);
|
2014-04-06 04:46:20 +04:00
|
|
|
else
|
2014-04-07 00:29:11 +04:00
|
|
|
Stream_Write_UINT32(irp->output, ret.hCard.pbHandle);
|
2013-10-24 23:34:14 +04:00
|
|
|
|
2014-04-06 00:06:46 +04:00
|
|
|
smartcard_output_alignment(irp, 8);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-06 00:06:46 +04:00
|
|
|
finish:
|
|
|
|
if (call.szReader)
|
|
|
|
free(call.szReader);
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
UINT32 handle_ConnectW(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
|
|
|
{
|
|
|
|
LONG status;
|
|
|
|
SCARDCONTEXT hContext;
|
|
|
|
SCARDHANDLE hCard;
|
|
|
|
ConnectW_Call call;
|
|
|
|
Connect_Return ret;
|
|
|
|
|
|
|
|
call.szReader = NULL;
|
|
|
|
|
|
|
|
status = smartcard_unpack_connect_w_call(smartcard, irp->input, &call);
|
|
|
|
|
|
|
|
if (status)
|
2013-09-12 15:53:15 +04:00
|
|
|
goto finish;
|
2013-09-12 14:18:35 +04:00
|
|
|
|
2014-04-07 00:29:11 +04:00
|
|
|
hContext = (ULONG_PTR) call.Common.Context.pbContext;
|
|
|
|
|
2014-04-06 00:06:46 +04:00
|
|
|
status = SCardConnectW(hContext, (WCHAR*) call.szReader, (DWORD) call.Common.dwShareMode,
|
2014-04-05 19:22:48 +04:00
|
|
|
(DWORD) call.Common.dwPreferredProtocols, &hCard, (DWORD*) &ret.dwActiveProtocol);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-04 01:29:12 +04:00
|
|
|
smartcard->hCard = hCard;
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-07 05:09:49 +04:00
|
|
|
ret.hCard.cbHandle = sizeof(ULONG_PTR);
|
2014-04-07 00:29:11 +04:00
|
|
|
ret.hCard.pbHandle = (UINT64) hCard;
|
2014-04-06 04:46:20 +04:00
|
|
|
|
|
|
|
Stream_Write_UINT32(irp->output, 0x00000000); /* (4 bytes) */
|
|
|
|
Stream_Write_UINT32(irp->output, 0x00000000); /* (4 bytes) */
|
|
|
|
Stream_Write_UINT32(irp->output, ret.hCard.cbHandle); /* cbHandle (4 bytes) */
|
2014-04-07 00:29:11 +04:00
|
|
|
Stream_Write_UINT32(irp->output, 0x00020001); /* pbHandleNdrPtr (4 bytes) */
|
2014-04-05 19:22:48 +04:00
|
|
|
Stream_Write_UINT32(irp->output, ret.dwActiveProtocol); /* dwActiveProtocol (4 bytes) */
|
2014-04-06 04:46:20 +04:00
|
|
|
Stream_Write_UINT32(irp->output, ret.hCard.cbHandle);
|
|
|
|
|
|
|
|
if (ret.hCard.cbHandle > 4)
|
2014-04-07 00:29:11 +04:00
|
|
|
Stream_Write_UINT64(irp->output, ret.hCard.pbHandle);
|
2014-04-06 04:46:20 +04:00
|
|
|
else
|
2014-04-07 00:29:11 +04:00
|
|
|
Stream_Write_UINT32(irp->output, ret.hCard.pbHandle);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
smartcard_output_alignment(irp, 8);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2013-09-12 15:53:15 +04:00
|
|
|
finish:
|
2014-04-05 19:22:48 +04:00
|
|
|
if (call.szReader)
|
|
|
|
free(call.szReader);
|
2013-09-12 15:53:15 +04:00
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
return status;
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
|
|
|
|
2014-04-04 01:29:12 +04:00
|
|
|
static UINT32 handle_Reconnect(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
2012-11-21 20:56:40 +04:00
|
|
|
LONG status;
|
2011-10-15 19:30:10 +04:00
|
|
|
SCARDHANDLE hCard;
|
2014-04-07 00:29:11 +04:00
|
|
|
SCARDCONTEXT hContext;
|
2014-04-05 19:22:48 +04:00
|
|
|
Reconnect_Call call;
|
|
|
|
Reconnect_Return ret;
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-07 00:29:11 +04:00
|
|
|
status = smartcard_unpack_reconnect_call(smartcard, irp->input, &call);
|
2013-10-24 23:34:14 +04:00
|
|
|
|
2013-09-12 14:18:35 +04:00
|
|
|
if (status)
|
|
|
|
return status;
|
|
|
|
|
2014-04-07 00:29:11 +04:00
|
|
|
hCard = (ULONG_PTR) call.hCard.pbHandle;
|
|
|
|
hContext = (ULONG_PTR) call.hCard.Context.pbContext;
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-05 19:22:48 +04:00
|
|
|
status = SCardReconnect(hCard, (DWORD) call.dwShareMode, (DWORD) call.dwPreferredProtocols,
|
|
|
|
(DWORD) call.dwInitialization, (LPDWORD) &ret.dwActiveProtocol);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-05 19:22:48 +04:00
|
|
|
Stream_Write_UINT32(irp->output, ret.dwActiveProtocol); /* dwActiveProtocol (4 bytes) */
|
2014-04-07 05:28:59 +04:00
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
smartcard_output_alignment(irp, 8);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
return status;
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
|
|
|
|
2014-04-04 01:29:12 +04:00
|
|
|
static UINT32 handle_Disconnect(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
2012-11-21 20:56:40 +04:00
|
|
|
LONG status;
|
2011-10-15 19:30:10 +04:00
|
|
|
SCARDHANDLE hCard;
|
2014-04-07 00:29:11 +04:00
|
|
|
SCARDCONTEXT hContext;
|
2014-04-05 19:22:48 +04:00
|
|
|
HCardAndDisposition_Call call;
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-07 00:29:11 +04:00
|
|
|
status = smartcard_unpack_hcard_and_disposition_call(smartcard, irp->input, &call);
|
2013-10-24 23:34:14 +04:00
|
|
|
|
2013-09-12 14:18:35 +04:00
|
|
|
if (status)
|
|
|
|
return status;
|
|
|
|
|
2014-04-07 00:29:11 +04:00
|
|
|
hCard = (ULONG_PTR) call.hCard.pbHandle;
|
|
|
|
hContext = (ULONG_PTR) call.hCard.Context.pbContext;
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-05 19:22:48 +04:00
|
|
|
status = SCardDisconnect(hCard, (DWORD) call.dwDisposition);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-07 00:29:11 +04:00
|
|
|
smartcard->hCard = 0;
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
smartcard_output_alignment(irp, 8);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
return status;
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
|
|
|
|
2014-04-04 01:29:12 +04:00
|
|
|
static UINT32 handle_BeginTransaction(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
2012-11-21 20:56:40 +04:00
|
|
|
LONG status;
|
2013-09-12 14:18:35 +04:00
|
|
|
SCARDHANDLE hCard;
|
|
|
|
SCARDCONTEXT hContext;
|
2014-04-05 19:22:48 +04:00
|
|
|
HCardAndDisposition_Call call;
|
2013-09-12 14:18:35 +04:00
|
|
|
|
2014-04-07 00:29:11 +04:00
|
|
|
status = smartcard_unpack_hcard_and_disposition_call(smartcard, irp->input, &call);
|
2013-10-24 23:34:14 +04:00
|
|
|
|
2013-09-12 14:18:35 +04:00
|
|
|
if (status)
|
|
|
|
return status;
|
|
|
|
|
2014-04-07 00:29:11 +04:00
|
|
|
hCard = (ULONG_PTR) call.hCard.pbHandle;
|
|
|
|
hContext = (ULONG_PTR) call.hCard.Context.pbContext;
|
2013-09-12 14:18:35 +04:00
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
status = SCardBeginTransaction(hCard);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
smartcard_output_alignment(irp, 8);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
return status;
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
|
|
|
|
2014-04-04 01:29:12 +04:00
|
|
|
static UINT32 handle_EndTransaction(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
2012-11-21 20:56:40 +04:00
|
|
|
LONG status;
|
2013-09-12 14:18:35 +04:00
|
|
|
SCARDHANDLE hCard;
|
|
|
|
SCARDCONTEXT hContext;
|
2014-04-05 19:22:48 +04:00
|
|
|
HCardAndDisposition_Call call;
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-07 00:29:11 +04:00
|
|
|
status = smartcard_unpack_hcard_and_disposition_call(smartcard, irp->input, &call);
|
2013-10-24 23:34:14 +04:00
|
|
|
|
2013-09-12 14:18:35 +04:00
|
|
|
if (status)
|
|
|
|
return status;
|
|
|
|
|
2014-04-07 00:29:11 +04:00
|
|
|
hCard = (ULONG_PTR) call.hCard.pbHandle;
|
|
|
|
hContext = (ULONG_PTR) call.hCard.Context.pbContext;
|
2013-09-12 14:18:35 +04:00
|
|
|
|
2014-04-05 19:22:48 +04:00
|
|
|
status = SCardEndTransaction(hCard, call.dwDisposition);
|
2011-11-22 05:46:58 +04:00
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
smartcard_output_alignment(irp, 8);
|
2011-11-22 05:46:58 +04:00
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
return status;
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
|
|
|
|
2014-04-04 01:29:12 +04:00
|
|
|
static UINT32 handle_State(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
2012-11-21 20:56:40 +04:00
|
|
|
LONG status;
|
2011-10-15 19:30:10 +04:00
|
|
|
SCARDHANDLE hCard;
|
2013-09-12 14:18:35 +04:00
|
|
|
SCARDCONTEXT hContext;
|
2014-04-05 19:22:48 +04:00
|
|
|
State_Call call;
|
|
|
|
State_Return ret;
|
2011-10-15 19:30:10 +04:00
|
|
|
DWORD readerLen;
|
2013-09-13 11:47:18 +04:00
|
|
|
char* readerName = NULL;
|
2014-04-05 19:22:48 +04:00
|
|
|
BYTE atr[SCARD_ATR_LENGTH];
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-07 05:09:49 +04:00
|
|
|
status = smartcard_unpack_state_call(smartcard, irp->input, &call);
|
2013-10-24 23:34:14 +04:00
|
|
|
|
2013-09-12 14:18:35 +04:00
|
|
|
if (status)
|
2013-09-12 15:53:15 +04:00
|
|
|
goto finish;
|
2013-09-12 14:18:35 +04:00
|
|
|
|
2014-04-07 05:09:49 +04:00
|
|
|
hCard = (ULONG_PTR) call.hCard.pbHandle;
|
|
|
|
hContext = (ULONG_PTR) call.hCard.Context.pbContext;
|
2011-10-15 19:30:10 +04:00
|
|
|
|
|
|
|
readerLen = SCARD_AUTOALLOCATE;
|
2014-04-05 19:22:48 +04:00
|
|
|
|
|
|
|
ret.rgAtr = atr;
|
|
|
|
ret.cbAtrLen = SCARD_ATR_LENGTH;
|
|
|
|
|
|
|
|
status = SCardStatusA(hCard, (LPSTR) &readerName, &readerLen,
|
|
|
|
&ret.dwState, &ret.dwProtocol, ret.rgAtr, &ret.cbAtrLen);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
if (status != SCARD_S_SUCCESS)
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
2013-09-12 15:53:15 +04:00
|
|
|
status = smartcard_output_return(irp, status);
|
|
|
|
goto finish;
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
|
|
|
|
2014-04-05 19:22:48 +04:00
|
|
|
Stream_Write_UINT32(irp->output, ret.dwState); /* dwState (4 bytes) */
|
|
|
|
Stream_Write_UINT32(irp->output, ret.dwProtocol); /* dwProtocol (4 bytes) */
|
|
|
|
Stream_Write_UINT32(irp->output, ret.cbAtrLen); /* cbAtrLen (4 bytes) */
|
|
|
|
Stream_Write_UINT32(irp->output, 0x00000001); /* rgAtrPointer (4 bytes) */
|
|
|
|
Stream_Write_UINT32(irp->output, ret.cbAtrLen); /* rgAtrLength (4 bytes) */
|
|
|
|
Stream_Write(irp->output, ret.rgAtr, ret.cbAtrLen); /* rgAtr */
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-05 19:22:48 +04:00
|
|
|
smartcard_output_repos(irp, ret.cbAtrLen);
|
2014-04-07 05:28:59 +04:00
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
smartcard_output_alignment(irp, 8);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2013-09-12 15:53:15 +04:00
|
|
|
finish:
|
|
|
|
if (readerName)
|
|
|
|
{
|
|
|
|
SCardFreeMemory(hContext, readerName);
|
|
|
|
}
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
return status;
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
|
|
|
|
2014-04-04 01:29:12 +04:00
|
|
|
static DWORD handle_Status(SMARTCARD_DEVICE* smartcard, IRP* irp, BOOL wide)
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
2012-11-21 20:56:40 +04:00
|
|
|
LONG status;
|
2011-10-15 19:30:10 +04:00
|
|
|
SCARDHANDLE hCard;
|
2013-09-12 14:18:35 +04:00
|
|
|
SCARDCONTEXT hContext;
|
2014-04-07 05:09:49 +04:00
|
|
|
Status_Call call;
|
2011-10-15 19:30:10 +04:00
|
|
|
DWORD state, protocol;
|
|
|
|
DWORD readerLen = 0;
|
2013-09-13 11:47:18 +04:00
|
|
|
char* readerName = NULL;
|
|
|
|
BYTE *pbAtr = NULL;
|
|
|
|
UINT32 dataLength = 0;
|
2011-10-15 19:30:10 +04:00
|
|
|
int pos, poslen1, poslen2;
|
|
|
|
|
2014-04-07 05:09:49 +04:00
|
|
|
status = smartcard_unpack_status_call(smartcard, irp->input, &call);
|
2013-10-24 23:34:14 +04:00
|
|
|
|
2013-09-12 14:18:35 +04:00
|
|
|
if (status)
|
2013-09-12 15:53:15 +04:00
|
|
|
goto finish;
|
2013-09-12 14:18:35 +04:00
|
|
|
|
2014-04-07 05:09:49 +04:00
|
|
|
hCard = (ULONG_PTR) call.hCard.pbHandle;
|
|
|
|
hContext = (ULONG_PTR) call.hCard.Context.pbContext;
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-07 05:09:49 +04:00
|
|
|
pbAtr = (BYTE*) malloc(call.cbAtrLen);
|
2014-04-04 01:29:12 +04:00
|
|
|
readerLen = SCARD_AUTOALLOCATE;
|
2014-04-06 03:58:48 +04:00
|
|
|
|
2014-04-07 05:09:49 +04:00
|
|
|
status = SCardStatusA(hCard, (LPSTR) &readerName, &readerLen, &state, &protocol, pbAtr, &call.cbAtrLen);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
if (status != SCARD_S_SUCCESS)
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
2013-09-12 15:53:15 +04:00
|
|
|
status = smartcard_output_return(irp, status);
|
|
|
|
goto finish;
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
|
|
|
|
2013-04-30 06:35:15 +04:00
|
|
|
poslen1 = Stream_GetPosition(irp->output);
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Write_UINT32(irp->output, readerLen);
|
2014-04-07 00:29:11 +04:00
|
|
|
Stream_Write_UINT32(irp->output, 0x00020001);
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Write_UINT32(irp->output, state);
|
|
|
|
Stream_Write_UINT32(irp->output, protocol);
|
2014-04-07 05:09:49 +04:00
|
|
|
Stream_Write(irp->output, pbAtr, call.cbAtrLen);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-07 05:09:49 +04:00
|
|
|
if (call.cbAtrLen < 32)
|
|
|
|
Stream_Zero(irp->output, 32 - call.cbAtrLen);
|
|
|
|
Stream_Write_UINT32(irp->output, call.cbAtrLen);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2013-04-30 06:35:15 +04:00
|
|
|
poslen2 = Stream_GetPosition(irp->output);
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Write_UINT32(irp->output, readerLen);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2013-09-13 11:47:18 +04:00
|
|
|
if (readerName)
|
|
|
|
dataLength += smartcard_output_string(irp, readerName, wide);
|
2012-11-21 20:56:40 +04:00
|
|
|
dataLength += smartcard_output_string(irp, "\0", wide);
|
|
|
|
smartcard_output_repos(irp, dataLength);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2013-04-30 06:35:15 +04:00
|
|
|
pos = Stream_GetPosition(irp->output);
|
|
|
|
Stream_SetPosition(irp->output, poslen1);
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Write_UINT32(irp->output,dataLength);
|
2013-04-30 06:35:15 +04:00
|
|
|
Stream_SetPosition(irp->output, poslen2);
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Write_UINT32(irp->output,dataLength);
|
2013-04-30 06:35:15 +04:00
|
|
|
Stream_SetPosition(irp->output, pos);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
smartcard_output_alignment(irp, 8);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2013-09-12 15:53:15 +04:00
|
|
|
finish:
|
|
|
|
if (readerName)
|
|
|
|
{
|
2014-04-04 01:29:12 +04:00
|
|
|
SCardFreeMemory(hContext, readerName);
|
2013-09-12 15:53:15 +04:00
|
|
|
}
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2013-09-13 11:47:18 +04:00
|
|
|
if (pbAtr)
|
|
|
|
free(pbAtr);
|
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
return status;
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
|
|
|
|
2014-04-04 01:29:12 +04:00
|
|
|
static UINT32 handle_Transmit(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
2012-11-21 20:56:40 +04:00
|
|
|
LONG status;
|
2013-09-12 14:18:35 +04:00
|
|
|
SCARDHANDLE hCard;
|
|
|
|
SCARDCONTEXT hContext;
|
2014-04-07 05:09:49 +04:00
|
|
|
Transmit_Call call;
|
|
|
|
DWORD cbRecvLength = 0;
|
|
|
|
BYTE* pbRecvBuffer = NULL;
|
2013-09-12 14:18:35 +04:00
|
|
|
|
2014-04-07 05:09:49 +04:00
|
|
|
status = smartcard_unpack_transmit_call(smartcard, irp->input, &call);
|
2014-04-06 00:06:46 +04:00
|
|
|
|
2013-09-12 14:18:35 +04:00
|
|
|
if (status)
|
2013-09-12 15:53:15 +04:00
|
|
|
goto finish;
|
2013-09-12 14:30:46 +04:00
|
|
|
|
2014-04-07 05:09:49 +04:00
|
|
|
hCard = (ULONG_PTR) call.hCard.pbHandle;
|
|
|
|
hContext = (ULONG_PTR) call.hCard.Context.pbContext;
|
2013-09-12 17:50:12 +04:00
|
|
|
|
2014-04-07 05:09:49 +04:00
|
|
|
if (call.cbRecvLength && !call.fpbRecvBufferIsNULL)
|
2014-04-04 01:29:12 +04:00
|
|
|
{
|
2014-04-07 05:09:49 +04:00
|
|
|
cbRecvLength = call.cbRecvLength;
|
|
|
|
pbRecvBuffer = (BYTE*) malloc(cbRecvLength);
|
2014-04-04 01:29:12 +04:00
|
|
|
}
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-07 05:09:49 +04:00
|
|
|
status = SCardTransmit(hCard, call.pioSendPci, call.pbSendBuffer, call.cbSendLength,
|
|
|
|
call.pioRecvPci, pbRecvBuffer, &cbRecvLength);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
if (status != SCARD_S_SUCCESS)
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
2014-04-04 01:29:12 +04:00
|
|
|
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Write_UINT32(irp->output, 0); /* pioRecvPci 0x00; */
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-07 05:09:49 +04:00
|
|
|
if (pbRecvBuffer)
|
2013-08-30 18:30:27 +04:00
|
|
|
{
|
|
|
|
smartcard_output_buffer_start(irp, cbRecvLength); /* start of recvBuf output */
|
2014-04-07 05:09:49 +04:00
|
|
|
smartcard_output_buffer(irp, (char*) pbRecvBuffer, cbRecvLength);
|
2013-08-30 18:30:27 +04:00
|
|
|
}
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
smartcard_output_alignment(irp, 8);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2013-09-12 15:53:15 +04:00
|
|
|
finish:
|
2014-04-07 05:09:49 +04:00
|
|
|
if (call.pbSendBuffer)
|
|
|
|
free(call.pbSendBuffer);
|
|
|
|
if (pbRecvBuffer)
|
|
|
|
free(pbRecvBuffer);
|
|
|
|
if (call.pioSendPci)
|
|
|
|
free(call.pioSendPci);
|
|
|
|
if (call.pioRecvPci)
|
|
|
|
free(call.pioRecvPci);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
return status;
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
|
|
|
|
2014-04-04 01:29:12 +04:00
|
|
|
static UINT32 handle_Control(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
2012-11-21 20:56:40 +04:00
|
|
|
LONG status;
|
2011-10-15 19:30:10 +04:00
|
|
|
SCARDHANDLE hCard;
|
2014-04-07 05:09:49 +04:00
|
|
|
SCARDCONTEXT hContext;
|
2014-04-05 19:22:48 +04:00
|
|
|
Control_Call call;
|
|
|
|
Control_Return ret;
|
2014-04-07 05:09:49 +04:00
|
|
|
UINT32 controlFunction;
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-07 05:09:49 +04:00
|
|
|
status = smartcard_unpack_control_call(smartcard, irp->input, &call);
|
2013-10-24 23:34:14 +04:00
|
|
|
|
2013-09-12 14:18:35 +04:00
|
|
|
if (status)
|
2013-09-12 15:53:15 +04:00
|
|
|
goto finish;
|
2013-09-12 14:18:35 +04:00
|
|
|
|
2014-04-07 05:09:49 +04:00
|
|
|
hCard = (ULONG_PTR) call.hCard.pbHandle;
|
|
|
|
hContext = (ULONG_PTR) call.hCard.Context.pbContext;
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-05 19:22:48 +04:00
|
|
|
if (DEVICE_TYPE_FROM_CTL_CODE(call.dwControlCode) == FILE_DEVICE_SMARTCARD)
|
2011-11-23 04:22:17 +04:00
|
|
|
{
|
2014-04-05 19:22:48 +04:00
|
|
|
controlFunction = FUNCTION_FROM_CTL_CODE(call.dwControlCode);
|
|
|
|
call.dwControlCode = SCARD_CTL_CODE(controlFunction);
|
2011-11-23 04:22:17 +04:00
|
|
|
}
|
2013-10-24 23:34:14 +04:00
|
|
|
|
2014-04-05 19:22:48 +04:00
|
|
|
ret.cbOutBufferSize = call.cbOutBufferSize;
|
2014-04-06 03:58:48 +04:00
|
|
|
ret.pvOutBuffer = (BYTE*) malloc(call.cbOutBufferSize);
|
2013-09-12 14:18:35 +04:00
|
|
|
|
2014-04-05 19:22:48 +04:00
|
|
|
status = SCardControl(hCard, (DWORD) call.dwControlCode,
|
|
|
|
call.pvInBuffer, (DWORD) call.cbInBufferSize,
|
|
|
|
ret.pvOutBuffer, (DWORD) call.cbOutBufferSize, &ret.cbOutBufferSize);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-05 19:22:48 +04:00
|
|
|
Stream_Write_UINT32(irp->output, (UINT32) ret.cbOutBufferSize); /* cbOutBufferSize (4 bytes) */
|
|
|
|
Stream_Write_UINT32(irp->output, 0x00000004); /* pvOutBufferPointer (4 bytes) */
|
|
|
|
Stream_Write_UINT32(irp->output, ret.cbOutBufferSize); /* pvOutBufferLength (4 bytes) */
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-05 19:22:48 +04:00
|
|
|
if (ret.cbOutBufferSize > 0)
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
2014-04-05 19:22:48 +04:00
|
|
|
Stream_Write(irp->output, ret.pvOutBuffer, ret.cbOutBufferSize); /* pvOutBuffer */
|
|
|
|
smartcard_output_repos(irp, ret.cbOutBufferSize);
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
smartcard_output_alignment(irp, 8);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2013-09-12 15:53:15 +04:00
|
|
|
finish:
|
2014-04-05 19:22:48 +04:00
|
|
|
if (call.pvInBuffer)
|
|
|
|
free(call.pvInBuffer);
|
|
|
|
if (ret.pvOutBuffer)
|
|
|
|
free(ret.pvOutBuffer);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
return status;
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
|
|
|
|
2014-04-04 01:29:12 +04:00
|
|
|
static UINT32 handle_GetAttrib(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
2012-11-21 20:56:40 +04:00
|
|
|
LONG status;
|
2014-04-05 19:22:48 +04:00
|
|
|
DWORD cbAttrLen;
|
2011-10-15 19:30:10 +04:00
|
|
|
SCARDHANDLE hCard;
|
2013-09-12 14:18:35 +04:00
|
|
|
SCARDCONTEXT hContext;
|
2014-04-05 19:22:48 +04:00
|
|
|
GetAttrib_Call call;
|
|
|
|
GetAttrib_Return ret;
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-07 05:09:49 +04:00
|
|
|
status = smartcard_unpack_get_attrib_call(smartcard, irp->input, &call);
|
2013-10-24 23:34:14 +04:00
|
|
|
|
2013-09-12 14:18:35 +04:00
|
|
|
if (status)
|
|
|
|
return status;
|
|
|
|
|
2014-04-07 05:09:49 +04:00
|
|
|
hCard = (ULONG_PTR) call.hCard.pbHandle;
|
|
|
|
hContext = (ULONG_PTR) call.hCard.Context.pbContext;
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-05 19:22:48 +04:00
|
|
|
ret.pbAttr = NULL;
|
2014-04-06 05:17:54 +04:00
|
|
|
cbAttrLen = (!call.cbAttrLen || call.fpbAttrIsNULL) ? 0 : SCARD_AUTOALLOCATE;
|
2014-04-05 19:22:48 +04:00
|
|
|
|
|
|
|
status = SCardGetAttrib(hCard, call.dwAttrId, (cbAttrLen == 0) ? NULL : (BYTE*) &ret.pbAttr, &cbAttrLen);
|
2012-11-21 20:56:40 +04:00
|
|
|
|
|
|
|
if (status != SCARD_S_SUCCESS)
|
|
|
|
{
|
2014-04-05 19:22:48 +04:00
|
|
|
cbAttrLen = (call.cbAttrLen == 0) ? 0 : SCARD_AUTOALLOCATE;
|
2011-12-22 23:23:08 +04:00
|
|
|
}
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-05 19:22:48 +04:00
|
|
|
if (call.dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_A && status == SCARD_E_UNSUPPORTED_FEATURE)
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
2012-11-21 20:56:40 +04:00
|
|
|
status = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME_W,
|
2014-04-05 19:22:48 +04:00
|
|
|
(cbAttrLen == 0) ? NULL : (BYTE*) &ret.pbAttr, &cbAttrLen);
|
2012-11-21 20:56:40 +04:00
|
|
|
|
|
|
|
if (status != SCARD_S_SUCCESS)
|
|
|
|
{
|
2014-04-05 19:22:48 +04:00
|
|
|
cbAttrLen = (call.cbAttrLen == 0) ? 0 : SCARD_AUTOALLOCATE;
|
2011-12-22 23:23:08 +04:00
|
|
|
}
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
2014-04-04 01:29:12 +04:00
|
|
|
|
2014-04-05 19:22:48 +04:00
|
|
|
if (call.dwAttrId == SCARD_ATTR_DEVICE_FRIENDLY_NAME_W && status == SCARD_E_UNSUPPORTED_FEATURE)
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
2012-11-21 20:56:40 +04:00
|
|
|
status = SCardGetAttrib(hCard, SCARD_ATTR_DEVICE_FRIENDLY_NAME_A,
|
2014-04-05 19:22:48 +04:00
|
|
|
(cbAttrLen == 0) ? NULL : (BYTE*) &ret.pbAttr, &cbAttrLen);
|
2012-11-21 20:56:40 +04:00
|
|
|
|
|
|
|
if (status != SCARD_S_SUCCESS)
|
|
|
|
{
|
2014-04-05 19:22:48 +04:00
|
|
|
cbAttrLen = (call.cbAttrLen == 0) ? 0 : SCARD_AUTOALLOCATE;
|
2011-12-22 23:23:08 +04:00
|
|
|
}
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
2014-04-05 19:22:48 +04:00
|
|
|
|
|
|
|
if ((cbAttrLen > call.cbAttrLen) && (ret.pbAttr != NULL))
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
2012-11-21 20:56:40 +04:00
|
|
|
status = SCARD_E_INSUFFICIENT_BUFFER;
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
2014-04-05 19:22:48 +04:00
|
|
|
call.cbAttrLen = cbAttrLen;
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
if (status != SCARD_S_SUCCESS)
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
2013-10-01 15:09:52 +04:00
|
|
|
status = smartcard_output_return(irp, status);
|
|
|
|
goto finish;
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-04-05 19:22:48 +04:00
|
|
|
ret.cbAttrLen = call.cbAttrLen;
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-05 19:22:48 +04:00
|
|
|
Stream_Write_UINT32(irp->output, ret.cbAttrLen); /* cbAttrLen (4 bytes) */
|
2014-04-06 05:17:54 +04:00
|
|
|
Stream_Write_UINT32(irp->output, 0x00020000); /* pbAttrPointer (4 bytes) */
|
2014-04-05 19:22:48 +04:00
|
|
|
Stream_Write_UINT32(irp->output, ret.cbAttrLen); /* pbAttrLength (4 bytes) */
|
|
|
|
|
|
|
|
if (!ret.pbAttr)
|
|
|
|
Stream_Zero(irp->output, ret.cbAttrLen); /* pbAttr */
|
2011-10-15 19:30:10 +04:00
|
|
|
else
|
2014-04-05 19:22:48 +04:00
|
|
|
Stream_Write(irp->output, ret.pbAttr, ret.cbAttrLen); /* pbAttr */
|
|
|
|
|
|
|
|
smartcard_output_repos(irp, ret.cbAttrLen);
|
2011-11-22 05:46:58 +04:00
|
|
|
/* align to multiple of 4 */
|
2013-05-09 00:09:16 +04:00
|
|
|
Stream_Write_UINT32(irp->output, 0);
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
2014-04-07 05:28:59 +04:00
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
smartcard_output_alignment(irp, 8);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2013-10-01 15:09:52 +04:00
|
|
|
finish:
|
2014-04-05 19:22:48 +04:00
|
|
|
SCardFreeMemory(hContext, ret.pbAttr);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
return status;
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|
|
|
|
|
2014-04-04 01:29:12 +04:00
|
|
|
static UINT32 handle_AccessStartedEvent(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
2013-09-12 14:18:35 +04:00
|
|
|
if (Stream_GetRemainingLength(irp->input) < 4)
|
|
|
|
{
|
2014-04-07 05:09:49 +04:00
|
|
|
WLog_Print(smartcard->log, WLOG_WARN, "AccessStartedEvent is too short: %d",
|
|
|
|
(int) Stream_GetRemainingLength(irp->input));
|
2013-09-12 14:18:35 +04:00
|
|
|
return SCARD_F_INTERNAL_ERROR;
|
|
|
|
}
|
2013-10-24 23:34:14 +04:00
|
|
|
|
2014-04-05 19:22:48 +04:00
|
|
|
Stream_Seek(irp->input, 4); /* Unused (4 bytes) */
|
2013-09-12 14:18:35 +04:00
|
|
|
|
2012-11-21 20:56:40 +04:00
|
|
|
smartcard_output_alignment(irp, 8);
|
2013-09-12 14:18:35 +04:00
|
|
|
|
2011-10-15 19:30:10 +04:00
|
|
|
return SCARD_S_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2014-04-06 01:51:13 +04:00
|
|
|
void smartcard_irp_device_control_peek_io_control_code(SMARTCARD_DEVICE* smartcard, IRP* irp, UINT32* ioControlCode)
|
|
|
|
{
|
|
|
|
*ioControlCode = 0;
|
|
|
|
|
|
|
|
if (Stream_GetRemainingLength(irp->input) < 32)
|
|
|
|
{
|
|
|
|
WLog_Print(smartcard->log, WLOG_WARN, "Device Control Request is too short: %d",
|
|
|
|
(int) Stream_GetRemainingLength(irp->input));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Stream_Seek_UINT32(irp->input); /* OutputBufferLength (4 bytes) */
|
|
|
|
Stream_Seek_UINT32(irp->input); /* InputBufferLength (4 bytes) */
|
|
|
|
Stream_Read_UINT32(irp->input, *ioControlCode); /* IoControlCode (4 bytes) */
|
|
|
|
Stream_Rewind(irp->input, (4 + 4 + 4));
|
|
|
|
}
|
|
|
|
|
2014-04-06 01:15:17 +04:00
|
|
|
void smartcard_irp_device_control(SMARTCARD_DEVICE* smartcard, IRP* irp)
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
2012-10-09 11:26:39 +04:00
|
|
|
UINT32 result;
|
2014-04-05 19:56:02 +04:00
|
|
|
UINT32 status;
|
2014-04-06 00:06:46 +04:00
|
|
|
UINT32 ioControlCode;
|
2014-04-04 08:56:24 +04:00
|
|
|
UINT32 outputBufferLength;
|
|
|
|
UINT32 inputBufferLength;
|
2014-04-06 00:06:46 +04:00
|
|
|
UINT32 objectBufferLength;
|
|
|
|
|
|
|
|
/* Device Control Request */
|
2012-11-21 20:56:40 +04:00
|
|
|
|
2013-09-12 14:18:35 +04:00
|
|
|
if (Stream_GetRemainingLength(irp->input) < 32)
|
|
|
|
{
|
2014-04-06 00:06:46 +04:00
|
|
|
WLog_Print(smartcard->log, WLOG_WARN, "Device Control Request is too short: %d",
|
|
|
|
(int) Stream_GetRemainingLength(irp->input));
|
2013-09-12 14:18:35 +04:00
|
|
|
return;
|
|
|
|
}
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-04 08:56:24 +04:00
|
|
|
Stream_Read_UINT32(irp->input, outputBufferLength); /* OutputBufferLength (4 bytes) */
|
|
|
|
Stream_Read_UINT32(irp->input, inputBufferLength); /* InputBufferLength (4 bytes) */
|
|
|
|
Stream_Read_UINT32(irp->input, ioControlCode); /* IoControlCode (4 bytes) */
|
|
|
|
Stream_Seek(irp->input, 20); /* Padding (20 bytes) */
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-06 00:06:46 +04:00
|
|
|
if (Stream_Length(irp->input) != (Stream_GetPosition(irp->input) + inputBufferLength))
|
2014-04-05 19:56:02 +04:00
|
|
|
{
|
2014-04-06 00:06:46 +04:00
|
|
|
WLog_Print(smartcard->log, WLOG_WARN,
|
|
|
|
"InputBufferLength mismatch: Actual: %d Expected: %d\n",
|
|
|
|
Stream_Length(irp->input), Stream_GetPosition(irp->input) + inputBufferLength);
|
2014-04-05 19:56:02 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-04-07 00:29:11 +04:00
|
|
|
WLog_Print(smartcard->log, WLOG_DEBUG, "%s (0x%08X) FileId: %d CompletionId: %d",
|
|
|
|
smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode, irp->FileId, irp->CompletionId);
|
2014-04-05 19:56:02 +04:00
|
|
|
|
2014-04-06 03:58:48 +04:00
|
|
|
#if 1
|
2014-04-07 05:09:49 +04:00
|
|
|
if (/*(ioControlCode != SCARD_IOCTL_TRANSMIT) &&*/
|
2014-04-06 03:58:48 +04:00
|
|
|
(ioControlCode != SCARD_IOCTL_GETSTATUSCHANGEA) &&
|
|
|
|
(ioControlCode != SCARD_IOCTL_GETSTATUSCHANGEW))
|
|
|
|
{
|
2014-04-07 00:29:11 +04:00
|
|
|
printf("%s (0x%08X) FileId: %d CompletionId: %d\n",
|
|
|
|
smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode, irp->FileId, irp->CompletionId);
|
2014-04-06 03:58:48 +04:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-04-06 00:06:46 +04:00
|
|
|
if ((ioControlCode != SCARD_IOCTL_ACCESSSTARTEDEVENT) &&
|
|
|
|
(ioControlCode != SCARD_IOCTL_RELEASESTARTEDEVENT))
|
2014-04-05 19:56:02 +04:00
|
|
|
{
|
2014-04-06 00:06:46 +04:00
|
|
|
status = smartcard_unpack_common_type_header(smartcard, irp->input);
|
2014-04-05 19:56:02 +04:00
|
|
|
|
|
|
|
if (status)
|
|
|
|
return;
|
|
|
|
|
2014-04-06 00:06:46 +04:00
|
|
|
status = smartcard_unpack_private_type_header(smartcard, irp->input);
|
2014-04-05 19:56:02 +04:00
|
|
|
|
|
|
|
if (status)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-04-06 00:06:46 +04:00
|
|
|
/**
|
|
|
|
* [MS-RDPESC] 3.2.5.1: Sending Outgoing Messages:
|
|
|
|
* the output buffer length SHOULD be set to 2048
|
|
|
|
*
|
|
|
|
* Since it's a SHOULD and not a MUST, we don't care
|
|
|
|
* about it, but we still reserve at least 2048 bytes.
|
|
|
|
*/
|
2013-05-02 02:15:55 +04:00
|
|
|
Stream_EnsureRemainingCapacity(irp->output, 2048);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-06 00:06:46 +04:00
|
|
|
/* Device Control Response */
|
|
|
|
Stream_Seek_UINT32(irp->output); /* OutputBufferLength (4 bytes) */
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-06 00:06:46 +04:00
|
|
|
Stream_Seek(irp->output, SMARTCARD_COMMON_TYPE_HEADER_LENGTH); /* CommonTypeHeader (8 bytes) */
|
|
|
|
Stream_Seek(irp->output, SMARTCARD_PRIVATE_TYPE_HEADER_LENGTH); /* PrivateTypeHeader (8 bytes) */
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-06 00:06:46 +04:00
|
|
|
Stream_Seek_UINT32(irp->output); /* Result (4 bytes) */
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-04 02:47:18 +04:00
|
|
|
switch (ioControlCode)
|
2011-10-15 19:30:10 +04:00
|
|
|
{
|
2014-04-04 02:47:18 +04:00
|
|
|
case SCARD_IOCTL_ESTABLISHCONTEXT:
|
2014-04-04 01:29:12 +04:00
|
|
|
result = handle_EstablishContext(smartcard, irp);
|
2011-10-15 19:30:10 +04:00
|
|
|
break;
|
|
|
|
|
2014-04-05 19:56:02 +04:00
|
|
|
case SCARD_IOCTL_RELEASECONTEXT:
|
|
|
|
result = handle_ReleaseContext(smartcard, irp);
|
|
|
|
break;
|
|
|
|
|
2014-04-04 02:47:18 +04:00
|
|
|
case SCARD_IOCTL_ISVALIDCONTEXT:
|
2014-04-04 01:29:12 +04:00
|
|
|
result = handle_IsValidContext(smartcard, irp);
|
2011-10-15 19:30:10 +04:00
|
|
|
break;
|
|
|
|
|
2014-04-05 19:56:02 +04:00
|
|
|
case SCARD_IOCTL_LISTREADERGROUPSA:
|
|
|
|
result = SCARD_F_INTERNAL_ERROR;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SCARD_IOCTL_LISTREADERGROUPSW:
|
|
|
|
result = SCARD_F_INTERNAL_ERROR;
|
2011-10-15 19:30:10 +04:00
|
|
|
break;
|
|
|
|
|
2014-04-04 02:47:18 +04:00
|
|
|
case SCARD_IOCTL_LISTREADERSA:
|
2014-04-04 01:29:12 +04:00
|
|
|
result = handle_ListReaders(smartcard, irp, 0);
|
2011-10-15 19:30:10 +04:00
|
|
|
break;
|
2014-04-05 19:56:02 +04:00
|
|
|
|
2014-04-04 02:47:18 +04:00
|
|
|
case SCARD_IOCTL_LISTREADERSW:
|
2014-04-04 01:29:12 +04:00
|
|
|
result = handle_ListReaders(smartcard, irp, 1);
|
2011-10-15 19:30:10 +04:00
|
|
|
break;
|
|
|
|
|
2014-04-05 19:56:02 +04:00
|
|
|
case SCARD_IOCTL_INTRODUCEREADERGROUPA:
|
2014-04-04 21:57:28 +04:00
|
|
|
result = SCARD_F_INTERNAL_ERROR;
|
|
|
|
break;
|
|
|
|
|
2014-04-05 19:56:02 +04:00
|
|
|
case SCARD_IOCTL_INTRODUCEREADERGROUPW:
|
|
|
|
result = SCARD_F_INTERNAL_ERROR;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SCARD_IOCTL_FORGETREADERGROUPA:
|
|
|
|
result = SCARD_F_INTERNAL_ERROR;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SCARD_IOCTL_FORGETREADERGROUPW:
|
|
|
|
result = SCARD_F_INTERNAL_ERROR;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SCARD_IOCTL_INTRODUCEREADERA:
|
|
|
|
result = SCARD_F_INTERNAL_ERROR;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SCARD_IOCTL_INTRODUCEREADERW:
|
|
|
|
result = SCARD_F_INTERNAL_ERROR;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SCARD_IOCTL_FORGETREADERA:
|
|
|
|
result = SCARD_F_INTERNAL_ERROR;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SCARD_IOCTL_FORGETREADERW:
|
|
|
|
result = SCARD_F_INTERNAL_ERROR;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SCARD_IOCTL_ADDREADERTOGROUPA:
|
|
|
|
result = SCARD_F_INTERNAL_ERROR;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SCARD_IOCTL_ADDREADERTOGROUPW:
|
|
|
|
result = SCARD_F_INTERNAL_ERROR;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SCARD_IOCTL_REMOVEREADERFROMGROUPA:
|
|
|
|
result = SCARD_F_INTERNAL_ERROR;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SCARD_IOCTL_REMOVEREADERFROMGROUPW:
|
|
|
|
result = SCARD_F_INTERNAL_ERROR;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SCARD_IOCTL_LOCATECARDSA:
|
|
|
|
result = SCARD_F_INTERNAL_ERROR;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SCARD_IOCTL_LOCATECARDSW:
|
2011-10-15 19:30:10 +04:00
|
|
|
result = SCARD_F_INTERNAL_ERROR;
|
|
|
|
break;
|
|
|
|
|
2014-04-04 02:47:18 +04:00
|
|
|
case SCARD_IOCTL_GETSTATUSCHANGEA:
|
2014-04-07 00:29:11 +04:00
|
|
|
result = handle_GetStatusChangeA(smartcard, irp);
|
2011-10-15 19:30:10 +04:00
|
|
|
break;
|
2014-04-05 19:56:02 +04:00
|
|
|
|
2014-04-04 02:47:18 +04:00
|
|
|
case SCARD_IOCTL_GETSTATUSCHANGEW:
|
2014-04-07 00:29:11 +04:00
|
|
|
result = handle_GetStatusChangeW(smartcard, irp);
|
2011-10-15 19:30:10 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SCARD_IOCTL_CANCEL:
|
2014-04-04 01:29:12 +04:00
|
|
|
result = handle_Cancel(smartcard, irp);
|
2011-10-15 19:30:10 +04:00
|
|
|
break;
|
|
|
|
|
2014-04-04 02:47:18 +04:00
|
|
|
case SCARD_IOCTL_CONNECTA:
|
2014-04-06 00:06:46 +04:00
|
|
|
result = handle_ConnectA(smartcard, irp);
|
2011-10-15 19:30:10 +04:00
|
|
|
break;
|
2014-04-05 19:56:02 +04:00
|
|
|
|
2014-04-04 02:47:18 +04:00
|
|
|
case SCARD_IOCTL_CONNECTW:
|
2014-04-06 00:06:46 +04:00
|
|
|
result = handle_ConnectW(smartcard, irp);
|
2011-10-15 19:30:10 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SCARD_IOCTL_RECONNECT:
|
2014-04-04 01:29:12 +04:00
|
|
|
result = handle_Reconnect(smartcard, irp);
|
2011-10-15 19:30:10 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SCARD_IOCTL_DISCONNECT:
|
2014-04-04 01:29:12 +04:00
|
|
|
result = handle_Disconnect(smartcard, irp);
|
2011-10-15 19:30:10 +04:00
|
|
|
break;
|
|
|
|
|
2014-04-04 02:47:18 +04:00
|
|
|
case SCARD_IOCTL_BEGINTRANSACTION:
|
2014-04-04 01:29:12 +04:00
|
|
|
result = handle_BeginTransaction(smartcard, irp);
|
2011-10-15 19:30:10 +04:00
|
|
|
break;
|
|
|
|
|
2014-04-04 02:47:18 +04:00
|
|
|
case SCARD_IOCTL_ENDTRANSACTION:
|
2014-04-04 01:29:12 +04:00
|
|
|
result = handle_EndTransaction(smartcard, irp);
|
2011-10-15 19:30:10 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SCARD_IOCTL_STATE:
|
2014-04-04 01:29:12 +04:00
|
|
|
result = handle_State(smartcard, irp);
|
2011-10-15 19:30:10 +04:00
|
|
|
break;
|
|
|
|
|
2014-04-04 02:47:18 +04:00
|
|
|
case SCARD_IOCTL_STATUSA:
|
2014-04-04 01:29:12 +04:00
|
|
|
result = handle_Status(smartcard, irp, 0);
|
2011-10-15 19:30:10 +04:00
|
|
|
break;
|
2014-04-05 19:56:02 +04:00
|
|
|
|
2014-04-04 02:47:18 +04:00
|
|
|
case SCARD_IOCTL_STATUSW:
|
2014-04-04 01:29:12 +04:00
|
|
|
result = handle_Status(smartcard, irp, 1);
|
2011-10-15 19:30:10 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SCARD_IOCTL_TRANSMIT:
|
2014-04-04 01:29:12 +04:00
|
|
|
result = handle_Transmit(smartcard, irp);
|
2011-10-15 19:30:10 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SCARD_IOCTL_CONTROL:
|
2014-04-04 01:29:12 +04:00
|
|
|
result = handle_Control(smartcard, irp);
|
2011-10-15 19:30:10 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SCARD_IOCTL_GETATTRIB:
|
2014-04-04 01:29:12 +04:00
|
|
|
result = handle_GetAttrib(smartcard, irp);
|
2011-10-15 19:30:10 +04:00
|
|
|
break;
|
|
|
|
|
2014-04-05 19:56:02 +04:00
|
|
|
case SCARD_IOCTL_SETATTRIB:
|
|
|
|
result = SCARD_F_INTERNAL_ERROR;
|
|
|
|
break;
|
|
|
|
|
2014-04-04 02:47:18 +04:00
|
|
|
case SCARD_IOCTL_ACCESSSTARTEDEVENT:
|
2014-04-04 01:29:12 +04:00
|
|
|
result = handle_AccessStartedEvent(smartcard, irp);
|
2011-10-15 19:30:10 +04:00
|
|
|
break;
|
|
|
|
|
2014-04-04 02:47:18 +04:00
|
|
|
case SCARD_IOCTL_LOCATECARDSBYATRA:
|
2014-04-07 05:28:59 +04:00
|
|
|
result = SCARD_F_INTERNAL_ERROR;
|
2011-10-15 19:30:10 +04:00
|
|
|
break;
|
2014-04-05 19:56:02 +04:00
|
|
|
|
2014-04-04 02:47:18 +04:00
|
|
|
case SCARD_IOCTL_LOCATECARDSBYATRW:
|
2014-04-07 05:28:59 +04:00
|
|
|
result = SCARD_F_INTERNAL_ERROR;
|
2011-10-15 19:30:10 +04:00
|
|
|
break;
|
|
|
|
|
2014-04-05 19:56:02 +04:00
|
|
|
case SCARD_IOCTL_READCACHEA:
|
|
|
|
result = SCARD_F_INTERNAL_ERROR;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SCARD_IOCTL_READCACHEW:
|
|
|
|
result = SCARD_F_INTERNAL_ERROR;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SCARD_IOCTL_WRITECACHEA:
|
|
|
|
result = SCARD_F_INTERNAL_ERROR;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SCARD_IOCTL_WRITECACHEW:
|
|
|
|
result = SCARD_F_INTERNAL_ERROR;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SCARD_IOCTL_GETTRANSMITCOUNT:
|
|
|
|
result = SCARD_F_INTERNAL_ERROR;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SCARD_IOCTL_RELEASESTARTEDEVENT:
|
|
|
|
result = SCARD_F_INTERNAL_ERROR;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SCARD_IOCTL_GETREADERICON:
|
|
|
|
result = SCARD_F_INTERNAL_ERROR;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SCARD_IOCTL_GETDEVICETYPEID:
|
|
|
|
result = SCARD_F_INTERNAL_ERROR;
|
|
|
|
break;
|
|
|
|
|
2011-10-15 19:30:10 +04:00
|
|
|
default:
|
2014-04-04 08:56:24 +04:00
|
|
|
result = STATUS_UNSUCCESSFUL;
|
2011-10-15 19:30:10 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2014-04-06 00:06:46 +04:00
|
|
|
if ((result != SCARD_S_SUCCESS) && (result != SCARD_E_TIMEOUT))
|
2014-04-05 19:56:02 +04:00
|
|
|
{
|
2014-04-06 00:06:46 +04:00
|
|
|
WLog_Print(smartcard->log, WLOG_WARN,
|
2014-04-07 00:29:11 +04:00
|
|
|
"IRP failure: %s (0x%08X), status: %s (0x%08X)",
|
|
|
|
smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode,
|
2014-04-06 00:06:46 +04:00
|
|
|
SCardGetErrorString(result), result);
|
2014-04-05 19:56:02 +04:00
|
|
|
}
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-06 00:06:46 +04:00
|
|
|
Stream_SealLength(irp->output);
|
|
|
|
outputBufferLength = Stream_Length(irp->output) - RDPDR_DEVICE_IO_RESPONSE_LENGTH - 4;
|
|
|
|
objectBufferLength = outputBufferLength - RDPDR_DEVICE_IO_RESPONSE_LENGTH;
|
|
|
|
Stream_SetPosition(irp->output, RDPDR_DEVICE_IO_RESPONSE_LENGTH);
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-06 00:06:46 +04:00
|
|
|
/* Device Control Response */
|
|
|
|
Stream_Write_UINT32(irp->output, outputBufferLength); /* OutputBufferLength (4 bytes) */
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-06 00:06:46 +04:00
|
|
|
smartcard_pack_common_type_header(smartcard, irp->output); /* CommonTypeHeader (8 bytes) */
|
|
|
|
smartcard_pack_private_type_header(smartcard, irp->output, objectBufferLength); /* PrivateTypeHeader (8 bytes) */
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-06 00:06:46 +04:00
|
|
|
Stream_Write_UINT32(irp->output, result); /* Result (4 bytes) */
|
2011-10-15 19:30:10 +04:00
|
|
|
|
2014-04-06 00:06:46 +04:00
|
|
|
Stream_SetPosition(irp->output, Stream_Length(irp->output));
|
2011-10-15 19:30:10 +04:00
|
|
|
|
|
|
|
irp->IoStatus = 0;
|
2014-04-06 00:57:31 +04:00
|
|
|
smartcard_complete_irp(smartcard, irp);
|
2011-10-15 19:30:10 +04:00
|
|
|
}
|