Hi,
I’m new to this forum. I was trying to figure out a way to perform direct reads and writes to disk. I tried using the ZwXX functions as mentioned in http://www.osronline.com/showthread.cfm?link=178960 but found that ZwWriteFile fails with Access denied error because SL_FORCE_DIRECT_WRITE is not set and that could not be set unless I create my own IRP.
Then I tried out http://www.codeproject.com/Articles/28314/Reading-and-Writing-to-Raw-Disk-Sectors
But a similar problem is occurring for this approach as well. I’m getting back STATUS_INVALID_DEVICE_REQUEST.
I replaced the classpnp.sys and disk.sys drivers with the wdk example drivers to step through them. I found out that IoStatus is being set to this value in classpnp’s completion routine TransferPktComplete:
pkt->OriginalIrp->IoStatus.Status = Irp->IoStatus.Status;
Now, When I add a write access breakpoint on pkt->OriginalIrp->IoStatus.Status, I find that its being set in storport:
Breakpoint 16 hit
storport!RaUnitAsyncError+0x142:
83a127ea 0fb64703 movzx eax,byte ptr [edi+3]
0: kd> kp
ChildEBP RetAddr
8078aeec 83a12a65 storport!RaUnitAsyncError+0x142
8078af20 83a041d9 storport!RaidUnitCompleteRequest+0x101
8078af48 828733b5 storport!RaidpAdapterDpcRoutine+0x51
8078afa4 82873218 nt!KiExecuteAllDpcs+0xf9
8078aff4 828729dc nt!KiRetireDpcList+0xd5
8078aff8 903d3674 nt!KiDispatchInterrupt+0x2c
WARNING: Frame IP not in any known module. Following frames may be wrong.
828729dc 00000000 0x903d3674
Read is working for both the aproaches (Zwxx and IRP). In the IRP approach, I just changed it to include the SL_FORCE_DIRECT_WRITE flag:
IoCtl = pIsl->Parameters.DeviceIoControl.IoControlCode;
switch(IoCtl)
{
case IOCTL_GET_SECTOR_SIZE:
if (BuffSize >= sizeof(ULONG))
{
*(PULONG) pBuff = pDiskObj->ulSectorSize;
Irp->IoStatus.Information = sizeof(ULONG);
status = STATUS_SUCCESS;
}
else
status = STATUS_INFO_LENGTH_MISMATCH;
break;
case IOCTL_SECTOR_WRITE:
sprintf(fa, “BAASDFASDFASFESVDVDFSDFGDFGSDFGSDGSDFGDGSDFGSDFGSDFGSDFG”);
(ULONG) pBuff = ((ULONG) pBuff) + sizeof(DISK_LOCATION); // To accomodate the very ugly hack of transferring write
// information and input buffer into the same buffer
InputBuffLen = InputBuffLen + (pDiskObj->ulSectorSize); // Inputbufflen shud be DISK_LOCATION + sectorsize as we
// are recieving data in the same buffer
OutputBuffLen = 0; //Outputbufflen for write operations shud be zero
DbgPrint(“Inside DriverIoDeviceDispatchRoutine, called for write operation\n”);
send_write(pDiskObj->pDiskDevObj, pDiskLoc->ullSectorNum, pBuff, pDiskObj->ulSectorSize);
break;
case IOCTL_SECTOR_READ:
if (InputBuffLen > pIsl->Parameters.DeviceIoControl.InputBufferLength)
{
status = STATUS_INFO_LENGTH_MISMATCH;
goto end;
}
if (OutputBuffLen > pIsl->Parameters.DeviceIoControl.OutputBufferLength)
{
status = STATUS_INFO_LENGTH_MISMATCH;
goto end;
}
MajorFunc = (IoCtl==IOCTL_SECTOR_READ) ? IRP_MJ_READ : IRP_MJ_WRITE;
lDiskOffset.QuadPart = (pDiskObj->ulSectorSize) * (pDiskLoc->ullSectorNum);
KeInitializeEvent(&Event, NotificationEvent, FALSE);
pIrp = IoBuildSynchronousFsdRequest(MajorFunc, pDiskObj->pDiskDevObj, fa, // pBuff,
pDiskObj->ulSectorSize, &lDiskOffset,
&Event, &ioStatus);
if (!pIrp) {
status = STATUS_INSUFFICIENT_RESOURCES;
goto end;
}
if(IoCtl != IOCTL_SECTOR_READ) {
IrpSp = IoGetNextIrpStackLocation(pIrp);
IrpSp->Flags = IrpSp->Flags | SL_FORCE_DIRECT_WRITE;
}
status = IoCallDriver(pDiskObj->pDiskDevObj, pIrp);
if (status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
status = ioStatus.Status;
if (NT_SUCCESS(status))
{
Irp->IoStatus.Information = pDiskObj->ulSectorSize;
}
}
break;
}
Am I missing something? Is it something to do with NotificationEvent? Do writes have to be asynchronous?