Template Information

Trang

Pipe Programming in Windows

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



extern "C" {
#include <ntddk.h>

}
#include "Unicode.h"
#define MEMSIZE 25

typedef struct DEVICE_EXTENSION {
    PDEVICE_OBJECT pDevice;
    ULONG DeviceNumber;
    CUString ustrDeviceName;   
    CUString ustrSymLinkName;
    char *write;
    char *read;
    char *deviceBuffer;
    char *devBufferEnd,*rtempBuffer,*wtempBuffer;
    ULONG deviceBufferSize;
    int memSize,freeSize;
    ULONG rxSize,wxSize,wnewSize,rnewSize;
    int wflag ,rflag,rpend,wpend ;

} DEVICE_EXTENSION, *PDEVICE_EXTENSION;


static VOID DriverUnload(PDRIVER_OBJECT  );
NTSTATUS CreateDevice(IN PDRIVER_OBJECT pDriverObject,IN ULONG ulDeviceNumber);
NTSTATUS DispatchCreate(IN PDEVICE_OBJECT pDevObject,IN PIRP pIrp);
NTSTATUS DispatchClose(IN PDEVICE_OBJECT pDevObject,IN PIRP pIrp);
NTSTATUS DispatchWrite(IN PDEVICE_OBJECT pDevObject,IN PIRP pIrp);
NTSTATUS DispatchRead(IN PDEVICE_OBJECT pDevObject,IN PIRP pIrp);

//VOID StartIo(IN PDEVICE_OBJECT pDO,    IN PIRP pIrp);

KEVENT rEvent,wEvent;


extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,IN PUNICODE_STRING pRegistryPath)
{
    ULONG ulDeviceNumber = 0;
    NTSTATUS status;
    DbgPrint("Pipe Driver's DriverEntry\n");
    pDriverObject->DriverUnload = DriverUnload;
   
   
    status=CreateDevice(pDriverObject,ulDeviceNumber);
   
    pDriverObject->MajorFunction[IRP_MJ_CREATE]=DispatchCreate;
    pDriverObject->MajorFunction[IRP_MJ_CLOSE]=DispatchClose;
    pDriverObject->MajorFunction[IRP_MJ_READ]=DispatchRead;
    pDriverObject->MajorFunction[IRP_MJ_WRITE]=DispatchWrite;

    KeInitializeEvent(&wEvent,NotificationEvent ,FALSE);
    KeInitializeEvent(&rEvent,NotificationEvent ,FALSE);

    return status;
}

VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
    PDEVICE_OBJECT pNextObj;
    pNextObj=pDriverObject->DeviceObject;
    DbgPrint("Pipe DriverUnload\n");
    while(pNextObj!=NULL)
    {
        PDEVICE_EXTENSION pDevExt=(PDEVICE_EXTENSION)pNextObj->DeviceExtension;

        if (pDevExt->deviceBuffer != NULL)
        {
            ExFreePool(pDevExt->deviceBuffer);
            pDevExt->deviceBuffer = NULL;
            pDevExt->deviceBufferSize = 0;
            DbgPrint("Memory will be Freed\n" );
        }

        UNICODE_STRING pLinkName=pDevExt->ustrSymLinkName;
        IoDeleteSymbolicLink(&pLinkName);
        pNextObj=pNextObj->NextDevice;
        IoDeleteDevice(pDevExt->pDevice);
    }
}



NTSTATUS CreateDevice(IN PDRIVER_OBJECT pDriverObject,IN ULONG ulDeviceNumber)
{
    NTSTATUS status;
    PDEVICE_OBJECT pDevObj;
    PDEVICE_EXTENSION pDevExt;
   
    DbgPrint("Pipe device\n");
   
    CUString devName("\\Device\\PipeDevice");
    devName+=CUString(ulDeviceNumber);
    status=IoCreateDevice(pDriverObject,sizeof(DEVICE_EXTENSION),&(UNICODE_STRING)devName,
                            FILE_DEVICE_UNKNOWN,FILE_WRITE_ONCE_MEDIA,FALSE,&pDevObj);

    if(!NT_SUCCESS(status))
        return status;

    pDevObj->Flags |= DO_BUFFERED_IO;

    pDevExt=(PDEVICE_EXTENSION)pDevObj->DeviceExtension;
    pDevExt->pDevice=pDevObj;
    pDevExt->DeviceNumber=ulDeviceNumber;
    pDevExt->ustrDeviceName=devName;
    pDevExt->deviceBuffer=NULL;
    pDevExt->deviceBufferSize=0;
    pDevExt->memSize = MEMSIZE;

    CUString symLinkName("\\??\\pipe");
    symLinkName+=CUString(ulDeviceNumber+1);
    pDevExt->ustrSymLinkName=symLinkName;


    status=IoCreateSymbolicLink(&(UNICODE_STRING)symLinkName,
                                &(UNICODE_STRING)devName);
    if(!NT_SUCCESS(status))
    {
        IoDeleteDevice(pDevObj);
        return status;
    }
   
    pDevExt->deviceBuffer=(char *)ExAllocatePool(PagedPool,pDevExt->memSize + 1);

    if(pDevExt->deviceBuffer==NULL)
        return STATUS_INSUFFICIENT_RESOURCES;

    DbgPrint("Memory will be Created with Add: %x\n",pDevExt->deviceBuffer);
    pDevExt->deviceBufferSize=0;

    pDevExt->write=pDevExt->read=pDevExt->deviceBuffer;
    pDevExt->devBufferEnd = pDevExt->deviceBuffer + pDevExt->memSize ;
    pDevExt->freeSize = MEMSIZE ;//pDevExt->memSize - pDevExt->deviceBufferSize;
    pDevExt->rxSize = pDevExt->wxSize = pDevExt->wnewSize = pDevExt->rnewSize = 0;
    pDevExt->rtempBuffer = pDevExt->wtempBuffer = NULL;
    pDevExt->rflag = 0;
    pDevExt->wflag = 1;
    pDevExt->rpend = pDevExt->wpend = 0;

    return STATUS_SUCCESS;
}


NTSTATUS DispatchCreate(IN PDEVICE_OBJECT pDevObj,IN PIRP pIrp)
{
   
   
    pIrp->IoStatus.Status=STATUS_SUCCESS;
    pIrp->IoStatus.Information =0;
    IoCompleteRequest(pIrp,IO_NO_INCREMENT);
   
    DbgPrint(("Dispatch Create function\n"));
    return STATUS_SUCCESS;
}


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

    pIrp->IoStatus.Status=STATUS_SUCCESS;
    pIrp->IoStatus.Information=0;
    IoCompleteRequest(pIrp,IO_NO_INCREMENT);


           
    DbgPrint("DispatchClose Function\n");

    return STATUS_SUCCESS;
}

NTSTATUS DispatchWrite(IN PDEVICE_OBJECT pDevObject,IN PIRP pIrp)
{

    NTSTATUS status=STATUS_SUCCESS,wStatus;
    PDEVICE_EXTENSION pDE=(PDEVICE_EXTENSION)pDevObject->DeviceExtension;
    char *userBuffer;
    PIO_STACK_LOCATION pIrpStack;
   
    pIrpStack=IoGetCurrentIrpStackLocation(pIrp);

    userBuffer=(char *)pIrp->AssociatedIrp.SystemBuffer;
    ULONG xferSize=pIrpStack->Parameters.Write.Length;
    pDE->wtempBuffer = userBuffer;
    pDE->wnewSize =  xferSize;
   
    while(pDE->wnewSize >0)
    {
        pDE->wxSize = pDE->wnewSize;

        if(pDE->wflag == 0)
        {
            KeResetEvent(&wEvent);
            DbgPrint("Write in Sleep \n");
            wStatus =  KeWaitForSingleObject(&wEvent,Executive, KernelMode,FALSE,NULL);
           
        }

        if(pDE->write >= pDE->read)
            pDE->wxSize = (pDE->wxSize <= (ULONG)(pDE->devBufferEnd - pDE->write)) ? pDE->wxSize : pDE->devBufferEnd-pDE->write;
        else
            pDE->wxSize = (pDE->wxSize <= (ULONG)(pDE->read - pDE->write)) ? pDE->wxSize : (pDE->read - pDE->write);

        RtlCopyMemory(pDE->write,pDE->wtempBuffer,pDE->wxSize);

         pDE->write         += pDE->wxSize;
        pDE->freeSize     -= pDE->wxSize;
        pDE->wnewSize    -= pDE->wxSize;
        pDE->wtempBuffer += pDE->wxSize;
        pDE->deviceBufferSize += pDE->wxSize;

        if(pDE->write >= pDE->devBufferEnd){
            pDE->write = pDE->deviceBuffer;
           
        }

        //if(pDE->deviceBufferSize > 0)
       
               
        if(pDE->freeSize <= 0)
        {
            pDE->freeSize = 0;
            pDE->wflag    = 0;
        }
        DbgPrint("device Buffer SIZE [%d]",pDE->deviceBufferSize);
        KdPrint(("Free Size [%d]", pDE->freeSize));
       
       
        KeSetEvent(&rEvent,0,FALSE);
        pDE->rflag = 1;
       
    }
   
    //pDE->wtempBuffer = NULL;
    pIrp->IoStatus.Status=status;
    pIrp->IoStatus.Information=xferSize;
    IoCompleteRequest(pIrp,IO_NO_INCREMENT);
    IoStartNextPacket(pDevObject,NULL);


    DbgPrint("\n WRITE FUNCTON \n");

    return status;
}


NTSTATUS DispatchRead(IN PDEVICE_OBJECT pDevObject,IN PIRP pIrp)
{
   

    NTSTATUS status=STATUS_SUCCESS,rStatus;
    PDEVICE_EXTENSION pDE=(PDEVICE_EXTENSION)pDevObject->DeviceExtension;
    char *userBuffer;
    PIO_STACK_LOCATION pIrpStack;
   
    pIrpStack=IoGetCurrentIrpStackLocation(pIrp);

    userBuffer=(char *)pIrp->AssociatedIrp.SystemBuffer;

    ULONG xferSize=pIrpStack->Parameters.Read.Length;

    pDE->rnewSize = xferSize ; //pDE->deviceBufferSize;
    pDE->rtempBuffer = userBuffer;
       
    while(pDE->rnewSize > 0)
    {
        pDE->rxSize = pDE->rnewSize;
   
        if(pDE->rflag ==0)
        {
            KeResetEvent(&rEvent);
            DbgPrint("Read in Sleep \n");
            rStatus =  KeWaitForSingleObject(&rEvent,Executive, KernelMode,FALSE,NULL);
        }

        if(pDE->write <= pDE->read)
            pDE->rxSize = (pDE->rxSize <= (ULONG)(pDE->devBufferEnd-pDE->read)) ? pDE->rxSize : (ULONG)(pDE->devBufferEnd-pDE->read);
        else
            pDE->rxSize = (pDE->rxSize <= (ULONG)(pDE->write - pDE->read)) ? pDE->rxSize : (ULONG)(pDE->write - pDE->read);

       

        RtlCopyMemory(pDE->rtempBuffer,pDE->read,pDE->rxSize);

        pDE->read        += pDE->rxSize;
        pDE->freeSize   += pDE->rxSize;
        pDE->rnewSize    -= pDE->rxSize;
        pDE->rtempBuffer        += pDE->rxSize;
        pDE->deviceBufferSize -= pDE->rxSize;

        if(pDE->read >= pDE->devBufferEnd){
            pDE->read = pDE->deviceBuffer;
            DbgPrint("Buffer Initialized\n");
        }
   
        if(pDE->deviceBufferSize <= 0)
        {
            pDE->rflag = 0;
            pDE->freeSize = pDE->memSize;
        }
        DbgPrint("device Buffer SIZE [%d]",pDE->deviceBufferSize);
        DbgPrint("XferSize [%d]",pDE->rxSize);   
       
        KeSetEvent(&wEvent,0,FALSE);
        pDE->wflag = 1;
    }
   
    pIrp->IoStatus.Status=status;
    pIrp->IoStatus.Information=xferSize;
    IoCompleteRequest(pIrp,IO_NO_INCREMENT);
    IoStartNextPacket(pDevObject,NULL);

    return status;
}

0 nhận xét:

Đăng nhận xét