📄 tlp3cb.c
字号:
(SmartcardExtension->CardCapabilities.T1.EDC & 0x01 ? 2 : 1);
// We want to have the remaining bytes just after the first 3
SmartcardExtension->SmartcardReply.Buffer += 3;
status = TLP3SerialIo(SmartcardExtension);
SmartcardExtension->SmartcardReply.Buffer -= 3;
SmartcardExtension->SmartcardReply.BufferLength += 3;
if (status != STATUS_SUCCESS && status != STATUS_TIMEOUT) {
leave;
}
}
if (status == STATUS_TIMEOUT) {
//
// Since the card did not reply we set the number of
// bytes received to 0. This will trigger a resend
// request
//
SmartcardDebug(
DEBUG_PROTOCOL,
("%s!TLP3TransmitT1: Timeout\n",
DRIVER_NAME)
);
SmartcardExtension->SmartcardReply.BufferLength = 0;
}
status = SmartcardT1Reply(SmartcardExtension);
break;
default:
status = STATUS_INVALID_DEVICE_REQUEST;
leave;
}
} while (status == STATUS_MORE_PROCESSING_REQUIRED);
}
_finally {
if (status == STATUS_TIMEOUT) {
// STATUS_TIMEOUT is not mapped to a Win32 error code
status = STATUS_IO_TIMEOUT;
}
}
#if defined (DEBUG) && defined (DETECT_SERIAL_OVERRUNS)
if (status != STATUS_SUCCESS) {
NTSTATUS status;
PSERIALPERF_STATS perfData =
(PSERIALPERF_STATS) SmartcardExtension->SmartcardReply.Buffer;
// we have to call GetCommStatus to reset the error condition
SmartcardExtension->ReaderExtension->SerialIoControlCode =
IOCTL_SERIAL_GET_COMMSTATUS;
SmartcardExtension->SmartcardRequest.BufferLength = 0;
SmartcardExtension->SmartcardReply.BufferLength =
sizeof(SERIAL_STATUS);
status = TLP3SerialIo(SmartcardExtension);
ASSERT(status == STATUS_SUCCESS);
// now get the reason for the transmission error
SmartcardExtension->ReaderExtension->SerialIoControlCode =
IOCTL_SERIAL_GET_STATS;
SmartcardExtension->SmartcardRequest.BufferLength = 0;
SmartcardExtension->SmartcardReply.BufferLength =
sizeof(SERIALPERF_STATS);
status = TLP3SerialIo(SmartcardExtension);
ASSERT(status == STATUS_SUCCESS);
SmartcardDebug(
DEBUG_ERROR,
("%s!TLP3Transmit: Serial error statistics:\n FrameErrors: %ld\n SerialOverrunErrors: %ld\n BufferOverrunErrors: %ld\n ParityErrors: %ld\n",
DRIVER_NAME,
perfData->FrameErrorCount,
perfData->SerialOverrunErrorCount,
perfData->BufferOverrunErrorCount,
perfData->ParityErrorCount)
);
SmartcardExtension->ReaderExtension->SerialIoControlCode =
IOCTL_SERIAL_CLEAR_STATS;
SmartcardExtension->SmartcardRequest.BufferLength = 0;
SmartcardExtension->SmartcardReply.BufferLength = 0;
status = TLP3SerialIo(SmartcardExtension);
ASSERT(status == STATUS_SUCCESS);
}
#if DEBUG && TIMEOUT_TEST
else {
// inject some timeout errors
LARGE_INTEGER Ticks;
UCHAR RandomVal;
KeQueryTickCount(&Ticks);
RandomVal = (UCHAR) Ticks.LowPart % 4;
if (RandomVal == 0) {
status = STATUS_IO_TIMEOUT;
SmartcardDebug(
DEBUG_ERROR,
("%s!TLP3Transmit: Simulating timeout\n",
DRIVER_NAME)
);
}
}
#endif
#endif
#ifdef SIMULATION
if (SmartcardExtension->ReaderExtension->SimulationLevel &
SIM_IO_TIMEOUT) {
status = STATUS_IO_TIMEOUT;
SmartcardDebug(
DEBUG_SIMULATION,
("%s!TLP3Transmit: SIM STATUS_IO_TIMEOUT\n",
DRIVER_NAME)
);
}
#endif
SmartcardDebug(
DEBUG_TRACE,
("%s!TLP3Transmit: Exit(%lx)\n",
DRIVER_NAME,
status)
);
return status;
}
NTSTATUS
TLP3CardTracking(
PSMARTCARD_EXTENSION SmartcardExtension
)
/*++
Routine Description:
The smart card lib requires to have this function. It is called
to setup event tracking for card insertion and removal events.
Arguments:
SmartcardExtension - pointer to the smart card data struct.
Return Value:
NTSTATUS
--*/
{
KIRQL ioIrql, keIrql;
//
// Set cancel routine for the notification irp
//
KeAcquireSpinLock(
&SmartcardExtension->OsData->SpinLock,
&keIrql
);
IoAcquireCancelSpinLock(&ioIrql);
if (SmartcardExtension->OsData->NotificationIrp) {
IoSetCancelRoutine(
SmartcardExtension->OsData->NotificationIrp,
TLP3Cancel
);
}
IoReleaseCancelSpinLock(ioIrql);
KeReleaseSpinLock(
&SmartcardExtension->OsData->SpinLock,
keIrql
);
return STATUS_PENDING;
}
NTSTATUS
TLP3VendorIoctl(
PSMARTCARD_EXTENSION SmartcardExtension
)
{
NTSTATUS status;
static char answer[] = "Vendor IOCTL";
PAGED_CODE();
SmartcardDebug(
DEBUG_PROTOCOL,
("%s!TLP3VendorIoctl: Enter\n",
DRIVER_NAME)
);
if (SmartcardExtension->IoRequest.ReplyBuffer != NULL &&
SmartcardExtension->IoRequest.ReplyBufferLength >= strlen(answer) + 1) {
strcpy(SmartcardExtension->IoRequest.ReplyBuffer, answer);
*SmartcardExtension->IoRequest.Information = strlen(answer);
status = STATUS_SUCCESS;
} else {
status = STATUS_BUFFER_TOO_SMALL;
}
SmartcardDebug(
DEBUG_PROTOCOL,
("%s!TLP3VendorIoctl: Exit(%lx)\n",
DRIVER_NAME,
status)
);
return status;
}
NTSTATUS
TLP3SerialIo(
PSMARTCARD_EXTENSION SmartcardExtension
)
/*++
Routine Description:
This routine sends IOCTL's to the serial driver. It waits on for their
completion, and then returns.
Arguments:
Return Value:
NTSTATUS
--*/
{
NTSTATUS status;
ULONG currentByte = 0;
if (KeReadStateEvent(&READER_EXTENSION(SerialCloseDone))) {
//
// we have no connection to serial, fail the call
// this could be the case if the reader was removed
// during stand by / hibernation
//
return STATUS_UNSUCCESSFUL;
}
// Check if the buffers are large enough
ASSERT(SmartcardExtension->SmartcardReply.BufferLength <=
SmartcardExtension->SmartcardReply.BufferSize);
ASSERT(SmartcardExtension->SmartcardRequest.BufferLength <=
SmartcardExtension->SmartcardRequest.BufferSize);
if (SmartcardExtension->SmartcardReply.BufferLength >
SmartcardExtension->SmartcardReply.BufferSize ||
SmartcardExtension->SmartcardRequest.BufferLength >
SmartcardExtension->SmartcardRequest.BufferSize) {
SmartcardLogError(
SmartcardExtension->OsData->DeviceObject,
TLP3_BUFFER_TOO_SMALL,
NULL,
0
);
return STATUS_BUFFER_TOO_SMALL;
}
do {
IO_STATUS_BLOCK ioStatus;
KEVENT event;
PIRP irp;
PIO_STACK_LOCATION irpNextStack;
PUCHAR requestBuffer = NULL;
PUCHAR replyBuffer = SmartcardExtension->SmartcardReply.Buffer;
ULONG requestBufferLength = SmartcardExtension->SmartcardRequest.BufferLength;
ULONG replyBufferLength = SmartcardExtension->SmartcardReply.BufferLength;
KeInitializeEvent(
&event,
NotificationEvent,
FALSE
);
if (READER_EXTENSION(SerialIoControlCode) == SMARTCARD_WRITE) {
if (SmartcardExtension->CardCapabilities.GT != 0) {
//
// If the guardtime isn't 0 and we write data to the smart card
// we only write byte by byte, because we have to insert a delay
// between every sent byte
//
requestBufferLength = 1;
}
requestBuffer =
&SmartcardExtension->SmartcardRequest.Buffer[currentByte++];
replyBuffer = NULL;
replyBufferLength = 0;
} else {
requestBuffer =
(requestBufferLength ?
SmartcardExtension->SmartcardRequest.Buffer : NULL);
}
// Build irp to be sent to serial driver
irp = IoBuildDeviceIoControlRequest(
READER_EXTENSION(SerialIoControlCode),
SmartcardExtension->ReaderExtension->AttachedDeviceObject,
requestBuffer,
requestBufferLength,
replyBuffer,
replyBufferLength,
FALSE,
&event,
&ioStatus
);
ASSERT(irp != NULL);
if (irp == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
irpNextStack = IoGetNextIrpStackLocation(irp);
switch (SmartcardExtension->ReaderExtension->SerialIoControlCode) {
//
// The serial driver trasfers data from/to irp->AssociatedIrp.SystemBuffer
//
case SMARTCARD_WRITE:
//
// Since we 'manually' change parameters, the io-manager
// does not really know if this is an input or an ouput operation
// unless the reply buffer is 0. We do the assertion here, because
// if the reply buffer is not NULL, the io-manager will copy
// data back to the reply buffer.
//
ASSERT(replyBuffer == NULL);
irpNextStack->MajorFunction = IRP_MJ_WRITE;
irpNextStack->Parameters.Write.Length = requestBufferLength;
irpNextStack->Parameters.Write.ByteOffset.QuadPart = 0;
break;
case SMARTCARD_READ:
irpNextStack->MajorFunction = IRP_MJ_READ;
irpNextStack->Parameters.Read.Length = replyBufferLength;
irpNextStack->Parameters.Read.ByteOffset.QuadPart = 0;
break;
default:
ASSERT(irpNextStack->MajorFunction = IRP_MJ_DEVICE_CONTROL);
ASSERT(
DEVICE_TYPE_FROM_CTL_CODE(READER_EXTENSION(SerialIoControlCode)) ==
FILE_DEVICE_SERIAL_PORT
);
}
status = IoCallDriver(
SmartcardExtension->ReaderExtension->AttachedDeviceObject,
irp
);
if (status == STATUS_PENDING) {
KeWaitForSingleObject(
&event,
Executive,
KernelMode,
FALSE,
NULL
);
status = ioStatus.Status;
// save the number of bytes received
SmartcardExtension->SmartcardReply.BufferLength =
(ULONG) ioStatus.Information;
}
// Check if we have to write more bytes to the reader
if (SmartcardExtension->ReaderExtension->SerialIoControlCode ==
SMARTCARD_WRITE &&
SmartcardExtension->CardCapabilities.GT != 0 &&
currentByte <
SmartcardExtension->SmartcardRequest.BufferLength) {
// Now wait the required guard time
KeStallExecutionProcessor(SmartcardExtension->CardCapabilities.GT);
status = STATUS_MORE_PROCESSING_REQUIRED;
}
} while (status == STATUS_MORE_PROCESSING_REQUIRED);
return status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -