KIRQL irql;
KeAcquireSpinLock(&BufferLock,&irql);
BytesTxd = WriteLen;
// (Re)allocate buffer if necessary
if ( ((ULONG)FilePointer)+WriteLen>BufferSize) {
ULONG NewBufferSize = ((ULONG)FilePointer)+WriteLen;
PVOID NewBuffer = ExAllocatePool(NonPagedPool.NewBufferSize);
if (NewBuffer==NULL) {
BytesTxd = BufferSize – (ULONG)FilePointer;
if (BytesTxd<0) BytesTxd = 0;
} else {
RtlZeroMemory(NewBuffer,NewBufferSize);
if (Buffer==NULL) {
RtlCopyMemory(NewBuffer,Buffer,BufferSize);
ExFreePool(Buffer);
}
Buffer = (PUCHAR)NewBuffer;
BufferSize = NewBufferSize;
}
}
// Write to shared memory
if (BytesTxd>0 && Buffer!=NULL) RtlCopyMemory(Buffer+FilePointer, Irp->AssociatedIrp.SystemBuffer, BytesTxd);
// Release shared buffer
KeReleaseSpinLock(&BufferLock,irq1);
}
DebugPrint('Write: %d bytes written', (int)BytesTxd);
// Complete IRP
return CompleteIrp(Irp,status,BytesTxd);
}
///////////////////////////////////////////////////////////////////////
//WdmlDeviceControl:
//
//Description:
//Handle IRP_MJ_DEVICE_CONTROL requests
//
//Arguments:
//Pointer to our FDO
//Pointer to the IRP
//Buffered:AssociatedIrp.SystemBuffer (and IrpStack-Parameters.DeviceIoControl.Type3InputBuffer)
//Direct:MdlAddress
//
//IrpStack->Parameters.DeviceIoControl.InputBufferLength
//IrpStack->Parameters.DeviceIoControl.OutputBufferLength
//
//Return Value:
//This function returns STATUS_XXX
NTSTATUS Wdm1DeviceControl(IN PDEVICE_OBJECT fdo, IN PIRP Irp) {
PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
NTSTATUS status – STATUS_SUCCESS;
ULONG BytesTxd = 0;
ULONG ControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
ULONG InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
ULONG OutputLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
DebugPrint('DeviceIoControl: Control code %x InputLength %d OutputLength %d', ControlCode, InputLength, OutputLength);
// Get access to the shared buffer KIRQL irql ;
KeAcquireSpinLock(&BufferLock,&irql);
switch (ControlCode) {
///////Zero Buffer
case IOCTL_WDM1_ZERO_BUFFER:
// Zero the buffer
if (Buffer!=NULL && BufferSize>0) RtlZeroMemory(Buffer,BufferSize);
break;
///////Remove Buffer
case IOCTL_WDM1_REMOVE_BUFFER:
if (Buffer!=NULL) {
ExFreePool(Buffer);
Buffer = NULL;
BufferSize = 0;
}
break;
///////Get Buffer Size as ULONG
case IOCTL_WDM1_GET_BUFFER_SIZE:
if (OutputLength<sizeof(ULONG)) status = STATUS_INVALID_PARAMETER;
else {
BytesTxd = sizeof(ULONG);
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,&BufferSize,sizeof(ULONG));
}
break;
///////Get Buffer
case IOCTL_WDM1_GET_BUFFER:
if (OutputLength>BufferSize) status = STATUS_INVALID_PARAMETER;
else {
BytesTxd = OutputLength;
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,Buffer,BytesTxd);
}
break;
///////Invalid request
default:
status = STATUS_INVALID_DEVICE_REQUEST;
}