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

📄 pnp.c

📁 windows平台下虚拟串口的driver文件
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <ntddk.h>
#include <ntddser.h>

#include "main.h"
#include "..\inc\wdmioctl.h"


#ifdef ALLOC_PRAGMA
#pragma alloc_text (PAGE, DispatchPnp)
#endif


extern DEVICE_ARRAY	gDeviceArray[ MAX_NUM_DEV ];
extern KSPIN_LOCK		gSpinLock;

NTSTATUS
DispatchPnp (
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
/*++

Routine Description:

    The plug and play dispatch routines.

    Most of these the driver will completely ignore.
    In all cases it must pass on the IRP to the lower driver.

Arguments:

   DeviceObject - pointer to a device object.

   Irp - pointer to an I/O Request Packet.

Return Value:

      NT status code

--*/
{
    PDEVICE_EXTENSION           deviceExtension; 
    PIO_STACK_LOCATION          irpStack;
    NTSTATUS                    status;
    KEVENT                      event;        

    PAGED_CODE();

    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
    irpStack = IoGetCurrentIrpStackLocation(Irp);

    DebugPrint(("Sample %s IRP:0x%x \n", 
                PnPMinorFunctionString(irpStack->MinorFunction), Irp));

    status = STATUS_SUCCESS;
    
    switch (irpStack->MinorFunction) {
    case IRP_MN_START_DEVICE:

		status = PnpStartDevice( DeviceObject, Irp);
		return status;

    case IRP_MN_REMOVE_DEVICE:
		status = PnpRemoveDevice( DeviceObject, Irp );        
        return status;
        
        
    case IRP_MN_QUERY_STOP_DEVICE:
        SET_NEW_PNP_STATE(deviceExtension, StopPending);
        status = STATUS_SUCCESS;
        break;
        
    case IRP_MN_CANCEL_STOP_DEVICE:

        //
        // Check to see whether you have received cancel-stop
        // without first receiving a query-stop. This could happen if someone
        // above us fails a query-stop and passes down the subsequent
        // cancel-stop.
        //
        
        if(StopPending == deviceExtension->DevicePnPState)
        {
            //
            // We did receive a query-stop, so restore.
            //             
            RESTORE_PREVIOUS_PNP_STATE(deviceExtension);
        }
        status = STATUS_SUCCESS; // We must not fail this IRP.
        break;
        
    case IRP_MN_STOP_DEVICE:
        SET_NEW_PNP_STATE(deviceExtension, StopPending);
        status = STATUS_SUCCESS;
        break;

    case IRP_MN_QUERY_REMOVE_DEVICE:

        SET_NEW_PNP_STATE(deviceExtension, RemovePending);
        status = STATUS_SUCCESS;
        break;
       
    case IRP_MN_SURPRISE_REMOVAL:

        SET_NEW_PNP_STATE(deviceExtension, SurpriseRemovePending);
        status = STATUS_SUCCESS;
        break;

    case IRP_MN_CANCEL_REMOVE_DEVICE:

        //
        // Check to see whether you have received cancel-remove
        // without first receiving a query-remove. This could happen if 
        // someone above us fails a query-remove and passes down the 
        // subsequent cancel-remove.
        //
        
        if(RemovePending == deviceExtension->DevicePnPState)
        {
            //
            // We did receive a query-remove, so restore.
            //             
            RESTORE_PREVIOUS_PNP_STATE(deviceExtension);
        }
        status = STATUS_SUCCESS; // We must not fail this IRP.
        break;
         
        
    default:
        //
        // If you don't handle any IRP you must leave the
        // status as is.
        //        
        status = Irp->IoStatus.Status;

        break;
    }

    //
    // Pass the IRP down and forget it.
    //
    Irp->IoStatus.Status = status;
    return DefaultPnpHandler( DeviceObject, Irp );
}



NTSTATUS PnpStartDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
    NTSTATUS			status;
	PDEVICE_EXTENSION	deviceExtension;
	PIO_STACK_LOCATION stack;

	deviceExtension = DeviceObject->DeviceExtension;
	status = ForwardAndWait( DeviceObject, Irp);
    if (!NT_SUCCESS(status))
        return CompleteRequest(Irp, status, Irp->IoStatus.Information);

	stack = IoGetCurrentIrpStackLocation( Irp );
	// TODO: other work to start the device in this layer driver

	status = SerialFinishStartDevice( deviceExtension );
	if( !NT_SUCCESS( status ) ){
		return CompleteRequest( Irp, status, 0 );
	}
	// 添加Interface,给win32 App提供访问接口
	status = AddInterface( deviceExtension );
	if( NT_SUCCESS( status ) && NT_SUCCESS( Irp->IoStatus.Status ) ){
		SET_NEW_PNP_STATE( deviceExtension, Started );
	}
    return CompleteRequest(Irp, status, 0);
}

NTSTATUS PnpRemoveDevice( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
	NTSTATUS			status;
	PDEVICE_EXTENSION	deviceExtension;

	DebugPrint(("+Enter RemoveDevice routine\n" ));
	deviceExtension = DeviceObject->DeviceExtension;
	//  TODO: handle our remove work at first

	SerialUndoExternalNaming( deviceExtension );

	// 删除Interface
	DelInterface( deviceExtension );
	
	SerialRemoveDevObj( DeviceObject );

	// Pass down the IRP
	IoSkipCurrentIrpStackLocation( Irp );
	status = IoCallDriver( deviceExtension->NextLowerDriver, Irp );

	SET_NEW_PNP_STATE(deviceExtension, Deleted);
	DebugPrint( ("NextLowerDriver:  0x%x\n", deviceExtension->NextLowerDriver ));

	IoDetachDevice( deviceExtension->NextLowerDriver );
	gDeviceArray[ deviceExtension->localInstance ].deviceExtension = NULL;
	IoDeleteDevice( DeviceObject );
	DebugPrint(("-Exit RemoveDevice routine\n"));
	
	return status;
}



NTSTATUS
SerialCreateDevObj(
	IN PDRIVER_OBJECT DriverObject,
	OUT PDEVICE_OBJECT *NewDeviceObject
	)
{
	UNICODE_STRING		deviceObjName;
	UNICODE_STRING		instanceStr;
	PDEVICE_OBJECT		deviceObject = NULL;
	PDEVICE_EXTENSION	pDevExt;
	NTSTATUS			status = STATUS_SUCCESS;
	WCHAR				instanceNumberBuffer[20];
	ULONG				currentInstance;
	
	PAGED_CODE();
	
	DebugPrint(("Enter SerialCreateDevObj\n"));

	for( currentInstance = 0; currentInstance < MAX_NUM_DEV; currentInstance++){
		// find the first empty device description in gDeviceArray
		if( gDeviceArray[ currentInstance ].deviceExtension == NULL ){
			break;
		}
	}
	if( currentInstance == MAX_NUM_DEV ){
		DebugPrint(("There is no memory in gDeviceArray\n"));
		status = STATUS_INSUFFICIENT_RESOURCES;
		*NewDeviceObject = NULL;
		return status;
	}
	// 首先处理deviceObjName,这是一个核心态使用的设备名,形如"\\Device\\SiSerial0"
	// Zero out allocated memory pointers so we know if they must be freed
	RtlZeroMemory(&deviceObjName, sizeof(UNICODE_STRING));
	deviceObjName.MaximumLength = DEVICE_OBJECT_NAME_LENGTH * sizeof(WCHAR);
	deviceObjName.Buffer = ExAllocatePool(PagedPool, deviceObjName.MaximumLength + sizeof(WCHAR));
	if (deviceObjName.Buffer == NULL) {
		DebugPrint(("Couldn't allocate memory for device name\n"));
		return STATUS_INSUFFICIENT_RESOURCES;
	}
	RtlZeroMemory( deviceObjName.Buffer, deviceObjName.MaximumLength + sizeof(WCHAR));
	// now, the size of deviceObjName.Buffer is (128 + 1)(WCHAR)
	RtlAppendUnicodeToString(&deviceObjName, DEVICE_NAME);	// L"\\Device\\SiSerial"

	// 处理deviceObjName的后缀序号
	RtlInitUnicodeString(&instanceStr, NULL);
	instanceStr.MaximumLength = sizeof(instanceNumberBuffer);
	instanceStr.Buffer = instanceNumberBuffer;	// 20 WCHAR
	RtlIntegerToUnicodeString( currentInstance, 10, &instanceStr);
	RtlAppendUnicodeStringToString( &deviceObjName, &instanceStr);
	DebugPrint(("DeviceName:\n"));
	DebugPrint(("----------- %ws\n", deviceObjName.Buffer ));
	
	//
	// Create the device object
	//
	status = IoCreateDevice(DriverObject, sizeof( DEVICE_EXTENSION ),
		&deviceObjName, FILE_DEVICE_SERIAL_PORT,
		FILE_DEVICE_SECURE_OPEN, TRUE, &deviceObject);
	if (!NT_SUCCESS(status)) {
		DebugPrint(("SerialAddDevice: Create device failed - %x \n", status ));
		goto SerialCreateDevObjError;
	}
	ASSERT(deviceObject != NULL);
	gDeviceArray[ currentInstance ].deviceExtension = deviceObject->DeviceExtension;
	pDevExt = deviceObject->DeviceExtension;

	//
	// The device object has a pointer to an area of non-paged
	// pool allocated for this device.  This will be the device
	// extension. Zero it out.
	//
	RtlZeroMemory( pDevExt, sizeof( DEVICE_EXTENSION ) );


	// 在DeviceExtension中保存deviceName
	pDevExt->DeviceName.Buffer =
		ExAllocatePool(PagedPool, deviceObjName.Length + sizeof(WCHAR));
	if (!pDevExt->DeviceName.Buffer) {
		DebugPrint(("SERIAL: Couldn't allocate memory for DeviceName\n"));
		status = STATUS_INSUFFICIENT_RESOURCES;
		goto SerialCreateDevObjError;
	}
	pDevExt->DeviceName.MaximumLength = deviceObjName.Length + sizeof(WCHAR);
	// Zero fill it.
	RtlZeroMemory(pDevExt->DeviceName.Buffer, pDevExt->DeviceName.MaximumLength);
	RtlAppendUnicodeStringToString(&pDevExt->DeviceName, &deviceObjName);
	
	//++	Initialize common devExtension
	// 设置本设备的instance序号和与其相联接的设备序号(目前是没有连接,所以设为Invalid_Instance
	pDevExt->localInstance	= currentInstance;
	pDevExt->remoteInstance	= INVALID_INSTANCE;

	pDevExt->Self					= deviceObject;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -