// Dispatch table for control NTSTATUS NeoNdisDispatch(DEVICE_OBJECT *DeviceObject, IRP *Irp) { NTSTATUS status; IO_STACK_LOCATION *stack; void *buf; BOOL ok; status = STATUS_SUCCESS; if (ctx == NULL) { return NDIS_STATUS_FAILURE; } InterlockedIncrement(&ctx->NumCurrentDispatch); // Get the IRP stack stack = IoGetCurrentIrpStackLocation(Irp); // Initialize the number of bytes Irp->IoStatus.Information = 0; Irp->IoStatus.Status = STATUS_SUCCESS; buf = Irp->UserBuffer; if (ctx->Halting != FALSE) { // Device driver is terminating Irp->IoStatus.Information = STATUS_UNSUCCESSFUL; InterlockedDecrement(&ctx->NumCurrentDispatch); IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } // Branch to each operation switch (stack->MajorFunction) { case IRP_MJ_CREATE: // Device is opened if (NeoNdisOnOpen(Irp, stack) == FALSE) { Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; status = STATUS_UNSUCCESSFUL; } break; case IRP_MJ_CLOSE: // Device is closed if (NeoNdisOnClose(Irp, stack) == FALSE) { Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; status = STATUS_UNSUCCESSFUL; } break; case IRP_MJ_READ: // Read (Reading of the received packet) ok = false; if (buf != NULL) { if (ctx->Opened && ctx->Inited) { if (stack->Parameters.Read.Length == NEO_EXCHANGE_BUFFER_SIZE) { // Address check bool check_ok = true; __try { ProbeForWrite(buf, NEO_EXCHANGE_BUFFER_SIZE, 1); } __except (EXCEPTION_EXECUTE_HANDLER) { check_ok = false; } if (check_ok) { // Address check MDL *mdl = IoAllocateMdl(buf, NEO_EXCHANGE_BUFFER_SIZE, false, false, NULL); if (mdl != NULL) { MmProbeAndLockPages(mdl, KernelMode, IoWriteAccess); } // Read NeoRead(buf); Irp->IoStatus.Information = NEO_EXCHANGE_BUFFER_SIZE; ok = true; if (mdl != NULL) { MmUnlockPages(mdl); IoFreeMdl(mdl); } } } } } if (ok == FALSE) { // An error occurred Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; status = STATUS_UNSUCCESSFUL; } break; case IRP_MJ_WRITE: // Write (Writing of a transmission packet) ok = false; if (buf != NULL) { if (ctx->Opened && ctx->Inited) { if (stack->Parameters.Write.Length == NEO_EXCHANGE_BUFFER_SIZE) { // Address check bool check_ok = true; __try { ProbeForRead(buf, NEO_EXCHANGE_BUFFER_SIZE, 1); } __except (EXCEPTION_EXECUTE_HANDLER) { check_ok = false; } if (check_ok) { // Address check MDL *mdl = IoAllocateMdl(buf, NEO_EXCHANGE_BUFFER_SIZE, false, false, NULL); if (mdl != NULL) { MmProbeAndLockPages(mdl, KernelMode, IoReadAccess); } ProbeForRead(buf, NEO_EXCHANGE_BUFFER_SIZE, 1); // Write NeoWrite(buf); Irp->IoStatus.Information = stack->Parameters.Write.Length; ok = true; if (mdl != NULL) { MmUnlockPages(mdl); IoFreeMdl(mdl); } } } } }
// Dispatch table for control NTSTATUS NeoNdisDispatch(DEVICE_OBJECT *DeviceObject, IRP *Irp) { NTSTATUS status; IO_STACK_LOCATION *stack; void *buf; BOOL ok; status = STATUS_SUCCESS; if (ctx == NULL) { return NDIS_STATUS_FAILURE; } // Get the IRP stack stack = IoGetCurrentIrpStackLocation(Irp); // Initialize the number of bytes Irp->IoStatus.Information = 0; Irp->IoStatus.Status = STATUS_SUCCESS; buf = Irp->UserBuffer; if (ctx->Halting != FALSE) { // Device driver is terminating Irp->IoStatus.Information = STATUS_UNSUCCESSFUL; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_UNSUCCESSFUL; } // Branch to each operation switch (stack->MajorFunction) { case IRP_MJ_CREATE: // Device is opened if (NeoNdisOnOpen(Irp, stack) == FALSE) { Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; status = STATUS_UNSUCCESSFUL; } break; case IRP_MJ_CLOSE: // Device is closed if (NeoNdisOnClose(Irp, stack) == FALSE) { Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; status = STATUS_UNSUCCESSFUL; } break; case IRP_MJ_READ: #ifndef WIN9X // Read (Reading of the received packet) ok = false; if (buf != NULL) { if (ctx->Opened && ctx->Inited) { if (stack->Parameters.Read.Length == NEO_EXCHANGE_BUFFER_SIZE) { // Address check MDL *mdl = IoAllocateMdl(buf, NEO_EXCHANGE_BUFFER_SIZE, false, false, NULL); if (mdl != NULL) { MmProbeAndLockPages(mdl, KernelMode, IoWriteAccess); } if (NeoIsKernelAddress(buf) == FALSE) { // Read NeoRead(buf); Irp->IoStatus.Information = NEO_EXCHANGE_BUFFER_SIZE; ok = true; } if (mdl != NULL) { MmUnlockPages(mdl); IoFreeMdl(mdl); } } } } if (ok == FALSE) { // An error occurred Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; status = STATUS_UNSUCCESSFUL; } #endif // WIN9X break; case IRP_MJ_WRITE: #ifndef WIN9X // Write (Writing of a transmission packet) ok = false; if (buf != NULL) { if (ctx->Opened && ctx->Inited) { if (stack->Parameters.Write.Length == NEO_EXCHANGE_BUFFER_SIZE) { // Address check MDL *mdl = IoAllocateMdl(buf, NEO_EXCHANGE_BUFFER_SIZE, false, false, NULL); if (mdl != NULL) { MmProbeAndLockPages(mdl, KernelMode, IoReadAccess); } if (NeoIsKernelAddress(buf) == FALSE) { // Write NeoWrite(buf); Irp->IoStatus.Information = stack->Parameters.Write.Length; ok = true; } if (mdl != NULL) { MmUnlockPages(mdl); IoFreeMdl(mdl); } } } } if (ok == FALSE) { // An error occurred Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; status = STATUS_UNSUCCESSFUL; } break; #endif // WIN9X case IRP_MJ_DEVICE_CONTROL: #ifdef WIN9X // IO Control switch (stack->Parameters.DeviceIoControl.IoControlCode) { case NEO_IOCTL_SET_EVENT: // Specify a event if (Irp->AssociatedIrp.SystemBuffer == NULL || stack->Parameters.DeviceIoControl.InputBufferLength != sizeof(DWORD)) { // An error occurred Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; } else { DWORD value = *((DWORD *)Irp->AssociatedIrp.SystemBuffer); ctx->Event = NeoCreateWin9xEvent(value); Irp->IoStatus.Information = sizeof(DWORD); } break; case NEO_IOCTL_PUT_PACKET: // Write a packet ok = false; buf = Irp->AssociatedIrp.SystemBuffer; if (buf != NULL) { if (stack->Parameters.DeviceIoControl.InputBufferLength == NEO_EXCHANGE_BUFFER_SIZE) { // Write NeoWrite(buf); Irp->IoStatus.Information = NEO_EXCHANGE_BUFFER_SIZE; ok = true; } } if (ok == false) { // An error occurred Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; status = STATUS_UNSUCCESSFUL; } break; case NEO_IOCTL_GET_PACKET: // Get the packet ok = false; buf = Irp->AssociatedIrp.SystemBuffer; if (buf != NULL) { if (stack->Parameters.DeviceIoControl.OutputBufferLength == NEO_EXCHANGE_BUFFER_SIZE) { // Read NeoRead(buf); Irp->IoStatus.Information = NEO_EXCHANGE_BUFFER_SIZE; ok = true; } } if (ok == false) { // An error occurred Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; status = STATUS_UNSUCCESSFUL; } break; } #endif // WIN9X break; } IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; }