⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tlp3cb.c

📁 SmardCard Windows驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
					        (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 + -