Template Information

Trang

IOCTL program in Windows Device Driver

Thứ Bảy, 4 tháng 6, 2011 / 21:26

extern "C"
{
    #include <NTDDK.h>
    #include <myioctl.h>
}
    #include <Unicode.h>

typedef struct _DEVICE_EXTENSION
{
         PDEVICE_OBJECT pDevice;
         ULONG DeviceNumber;
         CUString DeviceName;
         CUString SymLinkName;
         PCHAR deviceBuffer;
         ULONG deviceBufferSize;
         ULONG xferSize;
         ULONG CurrentSize;
         ULONG currentrpos;
         ULONG currentwpos;

} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

static NTSTATUS CreateDevice (IN PDRIVER_OBJECT pDriverObject,IN ULONG DeviceNumber);
NTSTATUS DispatchRead(  IN PDEVICE_OBJECT pDO,IN PIRP pIrp);
NTSTATUS DispatchWrite(  IN PDEVICE_OBJECT pDO, IN PIRP pIrp);
NTSTATUS DispatchCreate(IN PDEVICE_OBJECT DeviceObject,IN PIRP pIrp);
NTSTATUS DispatchClose(IN PDEVICE_OBJECT DeviceObject,IN PIRP pIrp);
NTSTATUS DispatchIoControl(IN PDEVICE_OBJECT pDO,IN PIRP pIrp );
static VOID DriverUnload (IN PDRIVER_OBJECT pDriverObject);



extern "C" NTSTATUS DriverEntry (IN PDRIVER_OBJECT pDriverObject,
                                                            IN PUNICODE_STRING pRegistryPath)
{
         ULONG ulDeviceNumber = 0;
         NTSTATUS status;
         DbgPrint(("Driver Entry Called"));

         pDriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
         pDriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
         pDriverObject->MajorFunction[IRP_MJ_READ] = DispatchRead;
         pDriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchWrite;
         pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoControl;
         pDriverObject->DriverUnload = DriverUnload;

         status = CreateDevice(pDriverObject, ulDeviceNumber);
         return status;
}

NTSTATUS CreateDevice (IN PDRIVER_OBJECT pDriverObject, IN ULONG ulDeviceNumber)
{
         NTSTATUS status;
         PDEVICE_OBJECT pDevObj;
         PDEVICE_EXTENSION pDevExt;
         CUString devName("\\Device\\MINIMAL");
         devName += CUString(ulDeviceNumber);
         status =IoCreateDevice( pDriverObject,sizeof(DEVICE_EXTENSION),
                               &(UNICODE_STRING)devName,FILE_DEVICE_UNKNOWN,0,TRUE,&pDevObj );
         if (!NT_SUCCESS(status))
         return status;
         DbgPrint(("device is created"));
        
         pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
         pDevExt->pDevice = pDevObj;
         pDevExt->DeviceNumber = ulDeviceNumber;
         pDevExt->DeviceName = devName;
         CUString symLinkName("\\??\\MIN");
         symLinkName += CUString(ulDeviceNumber+1);
         pDevExt->SymLinkName = symLinkName;
         pDevObj->Flags |= DO_BUFFERED_IO;
         status = IoCreateSymbolicLink( &(UNICODE_STRING)symLinkName, &(UNICODE_STRING)devName );
         pDevExt->xferSize = 8192;
         pDevExt->deviceBuffer = (PCHAR)ExAllocatePool(PagedPool,pDevExt->xferSize);
         pDevExt->CurrentSize = 0;
         pDevExt->currentrpos = 0;
         pDevExt->currentwpos = 0;
        
         if (pDevExt->deviceBuffer == NULL)
         {
             status = STATUS_INSUFFICIENT_RESOURCES;
             pDevExt->xferSize = 0;
             DbgPrint("Buffer is failed");
         }
     
         if (!NT_SUCCESS(status))
     {
             IoDeleteDevice( pDevObj );
             return status;
         }
         return STATUS_SUCCESS;
}

NTSTATUS DispatchCreate(IN PDEVICE_OBJECT DeviceObject,IN PIRP pIrp)
{
         PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
         pIrp->IoStatus.Status = STATUS_SUCCESS;
         pIrp->IoStatus.Information = 0;
         DbgPrint("flags is %x",DeviceObject->Characteristics);
        
         if((pIrp -> Flags & IRP_WRITE_OPERATION) == IRP_WRITE_OPERATION)
         DbgPrint(("WRITE ONLYOUTBUFFER->osize=pDE->xferSize; CALLED"));
        
         IoCompleteRequest(pIrp,IO_NO_INCREMENT);
         DbgPrint(("CREATE CALLED"));
         return STATUS_SUCCESS;
}

NTSTATUS DispatchIoControl(IN PDEVICE_OBJECT pDO,IN PIRP pIrp )
{
         NTSTATUS status = STATUS_SUCCESS;
         PDEVICE_EXTENSION pDE=(PDEVICE_EXTENSION)pDO->DeviceExtension;
         PCHAR temp;
         ULONG inSize;
         ULONG outSize;
         ULONG controlCode;
         IN_BUFFER *PIN_BUFFER;
         OUT_BUFFER *POUT_BUFFER;
         PIO_STACK_LOCATION pIrpStack;
         pIrpStack = IoGetCurrentIrpStackLocation( pIrp );
         PIN_BUFFER = (struct _IN_BUFFER *)pIrp->AssociatedIrp.SystemBuffer;
         POUT_BUFFER = (struct _OUT_BUFFER *)pIrp->UserBuffer;
         controlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
         inSize = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
         outSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
      
         if (inSize < sizeof(PIN_BUFFER) ||outSize < sizeof(POUT_BUFFER))
         {
             status = STATUS_INVALID_BUFFER_SIZE;
             return status;
         }
    
         switch(controlCode)
         {
         case IOCTL_GET_SIZE:
             POUT_BUFFER->devBufferSize=pDE->xferSize;
         break;

         case IOCTL_SET_SIZE:
             temp = (PCHAR)ExAllocatePool(PagedPool,pDE->xferSize);
             RtlCopyMemory(temp,pDE->deviceBuffer,pDE->xferSize);
             ExFreePool( pDE->deviceBuffer );
             pDE->xferSize=PIN_BUFFER->devBufferSize;
             DbgPrint(("Buffer Size sufficient"));
            
             pDE->deviceBuffer = (PCHAR)ExAllocatePool(PagedPool,pDE->xferSize);
             RtlCopyMemory(pDE->deviceBuffer,temp,pDE->xferSize);
             POUT_BUFFER->devBufferSize=pDE->xferSize;
         break;
        
         default:
             status = STATUS_INVALID_DEVICE_REQUEST;
         break;
         }

         pIrp->IoStatus.Information = 0;
         IoCompleteRequest( pIrp, IO_NO_INCREMENT );
         return status;
}

NTSTATUS DispatchClose(IN PDEVICE_OBJECT DeviceObject,IN PIRP pIrp)
{

         PDEVICE_EXTENSION pDE = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
         pIrp->IoStatus.Status = STATUS_SUCCESS;
         pIrp->IoStatus.Information = 0;

         ExFreePool( pDE->deviceBuffer );
         IoCompleteRequest(pIrp,IO_NO_INCREMENT);
         DbgPrint(("CLOSE CALLED"));
    return STATUS_SUCCESS;

}

NTSTATUS DispatchRead(IN PDEVICE_OBJECT pDO,IN PIRP pIrp)

{
         NTSTATUS status = STATUS_SUCCESS;
         PCHAR userBuffer;
         ULONG xferSize;

         PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation( pIrp );
         PDEVICE_EXTENSION pDE = (PDEVICE_EXTENSION)pDO->DeviceExtension;

         xferSize = pIrpStack->Parameters.Read.Length;
         userBuffer = (PCHAR)pIrp->AssociatedIrp.SystemBuffer;
       
         if(pDE->currentrpos >= pDE->CurrentSize)
     goto out;
   
         if(xferSize + pDE->currentrpos > pDE -> CurrentSize)
     xferSize =  pDE->CurrentSize-pDE->currentrpos;
         RtlCopyMemory(userBuffer,pDE->deviceBuffer+ pDE->currentrpos,xferSize);
         pIrp->IoStatus.Status = status;
         pIrp->IoStatus.Information = xferSize;
         pDE->currentrpos += xferSize;
   
        out:
             DbgPrint(("Read entry called"));
   
             IoCompleteRequest( pIrp, IO_NO_INCREMENT );
   
         return status;
}


NTSTATUS DispatchWrite(IN PDEVICE_OBJECT pDO, IN PIRP pIrp)
{
         NTSTATUS status = STATUS_SUCCESS;
         PCHAR userBuffer;
         ULONG xferSize;
         PDEVICE_EXTENSION pDE;
         PIO_STACK_LOCATION pIrpStack;

         pIrpStack = IoGetCurrentIrpStackLocation( pIrp );
         pDE = (PDEVICE_EXTENSION)pDO->DeviceExtension;
         xferSize = pIrpStack->Parameters.Write.Length;
         userBuffer =(PCHAR)pIrp->AssociatedIrp.SystemBuffer;

         if (userBuffer == NULL)
         {
             status = STATUS_INSUFFICIENT_RESOURCES;
             xferSize = 0;
         DbgPrint("Userbuffer is Failed");
             goto out;
         }
   
         if(pDE->currentwpos >= pDE->xferSize)
     goto out;
   
         if(pDE->currentwpos+xferSize > pDE -> xferSize)
     xferSize = pDE -> xferSize - pDE->currentwpos;
         RtlCopyMemory( pDE->deviceBuffer, userBuffer,xferSize );
         pIrp->IoStatus.Status = status;
         pIrp->IoStatus.Information = xferSize;
         pDE->CurrentSize += xferSize;
         pDE->currentwpos += xferSize;
   
         out:
             DbgPrint(("Write entry called"));
             IoCompleteRequest( pIrp, IO_NO_INCREMENT );
         return status;
}

VOID DriverUnload (IN PDRIVER_OBJECT pDriverObject)
{
         PDEVICE_OBJECT pDevObj;
         PDEVICE_EXTENSION pDevExt;
         UNICODE_STRING pLinkName;

         pDevObj= pDriverObject->DeviceObject;
         pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
         pLinkName =  pDevExt->SymLinkName;
         IoDeleteSymbolicLink(&pLinkName);
         pDevExt->SymLinkName.Free();
         pDevExt->DeviceName.Free();
         IoDeleteDevice( pDevExt->pDevice );
         DbgPrint(("Driver Unload completed"));
}

0 nhận xét:

Đăng nhận xét