📄 pscrcb.c
字号:
}
}
}
SmartcardDebug(
DEBUG_TRACE,
( "PSCR!CBRawTransmit: Exit (%lx)\n", NTStatus )
);
return ( NTStatus );
}
NTSTATUS
CBT1Transmit(
PSMARTCARD_EXTENSION SmartcardExtension
)
/*++
CBT1Transmit:
finishes the callback RDF_TRANSMIT for the T1 protocol
Arguments:
SmartcardExtension context of call
Return Value:
STATUS_SUCCESS
STATUS_NO_MEDIA
STATUS_TIMEOUT
STATUS_INVALID_DEVICE_REQUEST
--*/
{
NTSTATUS NTStatus = STATUS_SUCCESS;
ULONG IOBytes;
SmartcardDebug(
DEBUG_TRACE,
( "PSCR!CBT1Transmit: Enter\n" )
);
//
// use the lib support to construct the T=1 packets
//
do {
//
// no header for the T=1 protocol
//
SmartcardExtension->SmartcardRequest.BufferLength = 0;
//
// SCM-TM: Siemens 4440 accepts only NAD=0!!!
//
SmartcardExtension->T1.NAD = 0;
//
// let the lib setup the T=1 APDU & check for errors
//
NTStatus = SmartcardT1Request( SmartcardExtension );
if( NT_SUCCESS( NTStatus ))
{
// send command (don't calculate LRC because CRC may be used!)
IOBytes = 0;
NTStatus = PscrWriteDirect(
SmartcardExtension->ReaderExtension,
SmartcardExtension->SmartcardRequest.Buffer,
SmartcardExtension->SmartcardRequest.BufferLength,
&IOBytes
);
//
// extend the timeout if a Wtx request was sent by the card. if the
// card responds before the waiting time extension expires, the data are
// buffered in the reader. A delay without polling the reader status
// slows down the performance of the driver, but wtx is an exeption,
// not the rule.
//
if (SmartcardExtension->T1.Wtx)
{
SysDelay(
(( SmartcardExtension->T1.Wtx *
SmartcardExtension->CardCapabilities.T1.BWT + 999L )/
1000L)
);
}
// get response
SmartcardExtension->SmartcardReply.BufferLength = 0;
NTStatus = PscrRead(
SmartcardExtension->ReaderExtension,
SmartcardExtension->SmartcardReply.Buffer,
MAX_T1_BLOCK_SIZE,
&SmartcardExtension->SmartcardReply.BufferLength
);
// if PscrRead detects an LRC error, ignore it (maybe CRC used)
if( NTStatus == STATUS_CRC_ERROR )
{
NTStatus = STATUS_SUCCESS;
}
//
// We even continue if the prev. read failed.
// We let the smart card library continue, because it might
// send a resynch. request in case of a timeout
//
NTStatus = SmartcardT1Reply( SmartcardExtension );
}
// continue if the lib wants to send the next packet
} while( NTStatus == STATUS_MORE_PROCESSING_REQUIRED );
SmartcardDebug(
DEBUG_TRACE,
( "PSCR!CBT1Transmit: Exit (%lx)\n", NTStatus )
);
return ( NTStatus );
}
NTSTATUS
CBT0Transmit(
PSMARTCARD_EXTENSION SmartcardExtension
)
/*++
CBT0Transmit:
finishes the callback RDF_TRANSMIT for the T0 protocol
Arguments:
SmartcardExtension context of call
Return Value:
STATUS_SUCCESS
STATUS_NO_MEDIA
STATUS_TIMEOUT
STATUS_INVALID_DEVICE_REQUEST
--*/
{
NTSTATUS NTStatus = STATUS_SUCCESS;
PUCHAR pRequest,pReply;
ULONG IOBytes, APDULength, RequestLength;
UCHAR IOData[ MAX_T1_BLOCK_SIZE ];
UCHAR WtxReply[16];
SmartcardDebug(
DEBUG_TRACE,
( "PSCR!CBT0Transmit: Enter\n" )
);
pRequest = SmartcardExtension->SmartcardRequest.Buffer;
pReply = SmartcardExtension->SmartcardReply.Buffer;
// setup the command header
pRequest[ PSCR_NAD ] =
( SmartcardExtension->ReaderExtension->Device == DEVICE_ICC1 ) ?
NAD_TO_ICC1 : NAD_TO_ICC1;
pRequest[ PSCR_PCB ] = PCB_DEFAULT;
//
// get the length of the user data packet & set the appropriate LEN
// information the complete user packet consists of a SCARD_IO_REQUEST
// structure followed by the APDU. the length of SCARD_IO_REQUEST is
// transferred in the member cbPciLength of the structure
//
APDULength = SmartcardExtension->IoRequest.RequestBufferLength;
APDULength -= ((PSCARD_IO_REQUEST) SmartcardExtension->
IoRequest.RequestBuffer)->cbPciLength;
//
// a 4 byte APDU will be patched to a 5 byte TPDU by the lib; see
// annex of the ISO
//
if( APDULength == 4 ) APDULength++;
//
// if the total length of the T1 (reader) packet is larger than 0xFF
// the extended length notation will be used
//
if( APDULength >= 0xFF )
{
pRequest[ PSCR_LEN ] = 0xFF;
pRequest[ PSCR_LEN+1 ] = HIBYTE( APDULength );
pRequest[ PSCR_LEN+2 ] = LOBYTE( APDULength );
SmartcardExtension->SmartcardRequest.BufferLength =
PSCR_EXT_PROLOGUE_LENGTH;
}
else
{
pRequest[ PSCR_LEN ] = ( UCHAR ) APDULength;
SmartcardExtension->SmartcardRequest.BufferLength =
PSCR_PROLOGUE_LENGTH;
}
// let the lib setup the T=1 APDU & check for errors
NTStatus = SmartcardT0Request( SmartcardExtension );
RequestLength = SmartcardExtension->SmartcardRequest.BufferLength;
while( NT_SUCCESS( NTStatus ))
{
// send command
IOBytes = 0;
NTStatus = PscrWrite(
SmartcardExtension->ReaderExtension,
pRequest,
RequestLength,
&IOBytes
);
// get response
if( NT_SUCCESS( NTStatus ))
{
IOBytes = 0;
NTStatus = PscrRead(
SmartcardExtension->ReaderExtension,
IOData,
MAX_T1_BLOCK_SIZE,
&IOBytes
);
// extract APDU from T=1 transport packet
if( NT_SUCCESS( NTStatus ))
{
if (IOData[ PSCR_PCB ] == WTX_REQUEST) {
WtxReply[PSCR_NAD] = NAD_TO_PSCR;
WtxReply[PSCR_PCB] = WTX_REPLY;
WtxReply[PSCR_LEN] = 1;
WtxReply[PSCR_INF] = IOData[PSCR_INF];
RequestLength = 4;
pRequest = WtxReply;
continue;
}
if( IOData[ PSCR_LEN ] == 0xFF )
{
//
// extended length byte used
//
APDULength = IOData[ PSCR_LEN + 1 ] << 8;
APDULength += IOData[ PSCR_LEN + 2 ];
SmartcardExtension->SmartcardReply.BufferLength = APDULength ;
SysCopyMemory( pReply, &IOData[ PSCR_APDU + 2 ], APDULength );
}
else
{
SmartcardExtension->SmartcardReply.BufferLength =
IOData[ PSCR_LEN ];
SysCopyMemory(
pReply,
&IOData[ PSCR_APDU ],
IOData[ PSCR_LEN ]
);
}
// let the lib evaluate the result & tansfer the data
NTStatus = SmartcardT0Reply( SmartcardExtension );
break;
}
}
}
SmartcardDebug(
DEBUG_TRACE,
( "PSCR!CBT0Transmit: Exit (%lx)\n", NTStatus )
);
return( NTStatus );
}
NTSTATUS
CBCardTracking(
PSMARTCARD_EXTENSION SmartcardExtension
)
/*++
CBCardTracking:
callback handler for SMCLIB RDF_CARD_TRACKING. the requested event was
validated by the smclib (i.e. a card removal request will only be passed
if a card is present).
for a win95 build STATUS_PENDING will be returned without any other action.
for NT the cancel routine for the irp will be set to the drivers cancel
routine.
Arguments:
SmartcardExtension context of call
Return Value:
STATUS_PENDING
--*/
{
KIRQL CancelIrql;
SmartcardDebug(
DEBUG_TRACE,
( "PSCR!CBCardTracking: Enter\n" )
);
// set cancel routine
IoAcquireCancelSpinLock( &CancelIrql );
IoSetCancelRoutine(
SmartcardExtension->OsData->NotificationIrp,
PscrCancel
);
IoReleaseCancelSpinLock( CancelIrql );
SmartcardDebug(
DEBUG_TRACE,
( "PSCR!CBCardTracking: Exit \n" )
);
return( STATUS_PENDING );
}
VOID
CBUpdateCardState(
PSMARTCARD_EXTENSION SmartcardExtension,
UCHAR IccState,
BOOLEAN SystemWakeUp
)
{
ULONG oldState;
KIRQL currentIrql, irql;
KeAcquireSpinLock(
&SmartcardExtension->OsData->SpinLock,
&irql
);
SmartcardDebug(
DEBUG_TRACE,
( "PSCR!CBUpdateCardState: Enter \n" )
);
oldState =
(SmartcardExtension->ReaderCapabilities.CurrentState > SCARD_ABSENT ?
SCARD_PRESENT : SCARD_ABSENT);
SmartcardExtension->ReaderCapabilities.CurrentState =
(IccState == PSCR_ICC_PRESENT ? SCARD_PRESENT : SCARD_ABSENT);
SmartcardDebug(
DEBUG_DRIVER,
( "PSCR!CBUpdateCardState: Smart card %s\n",
IccState == PSCR_ICC_PRESENT ? "inserted" : "removed")
);
IoAcquireCancelSpinLock( ¤tIrql );
if( SmartcardExtension->OsData->NotificationIrp != NULL && (
SystemWakeUp && (
oldState == SCARD_PRESENT ||
SmartcardExtension->ReaderCapabilities.CurrentState == SCARD_PRESENT) ||
SmartcardExtension->ReaderCapabilities.CurrentState != oldState)) {
PIRP notificationIrp = InterlockedExchangePointer(
&(SmartcardExtension->OsData->NotificationIrp),
NULL
);
IoSetCancelRoutine(
notificationIrp,
NULL
);
IoReleaseCancelSpinLock( currentIrql );
if (notificationIrp->Cancel == FALSE) {
// finish the request
notificationIrp->IoStatus.Status = STATUS_SUCCESS;
notificationIrp->IoStatus.Information = 0;
SmartcardDebug(
DEBUG_DRIVER,
( "PSCR!CBUpdateCardState: Completing Irp %lx\n",
notificationIrp)
);
IoCompleteRequest(notificationIrp, IO_NO_INCREMENT );
}
} else {
IoReleaseCancelSpinLock( currentIrql );
}
SmartcardDebug(
DEBUG_TRACE,
( "PSCR!CBUpdateCardState: Exit \n" )
);
KeReleaseSpinLock(
&SmartcardExtension->OsData->SpinLock,
irql
);
}
UCHAR
CBGetCardState(
PSMARTCARD_EXTENSION SmartcardExtension
)
/*++
CBUpdateCardState:
updates the variable CurrentState in SmartcardExtension
Arguments:
SmartcardExtension context of call
Return Value:
STATUS_SUCCESS
--*/
{
NTSTATUS NTStatus = STATUS_SUCCESS;
UCHAR TLVList[ TLV_BUFFER_SIZE ], Val, Len;
ULONG TLVListLen;
PREADER_EXTENSION ReaderExtension = SmartcardExtension->ReaderExtension;
// read the status file of ICC1 from the reader
TLVListLen = TLV_BUFFER_SIZE;
if( NT_SUCCESS( CmdReadStatusFile(
ReaderExtension,
ReaderExtension->Device,
TLVList,
&TLVListLen
))) {
// get reader status value
CmdGetTagValue(
TAG_READER_STATUS,
TLVList,
TLVListLen,
&Len,
( PVOID ) &Val
);
}
else
{
// IO-error is interpreted as card absent
ASSERT(FALSE);
Val = PSCR_ICC_ABSENT;
}
return Val;
}
// -------------------------------- END OF FILE ------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -