home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************/
- /* Copyright (c) 1991 Microsoft Corporation */
- /* Changes copyright (c) 1993 DMC Danmark */
- /* */
- /* Module name...: SCANNER.C */
- /* */
- /* Description...: A minimul SCSI scanner class driver */
- /* */
- /* Environment...: Kernel mode only! */
- /* */
- /* Notes.........: SCSI Tape, CDRom, Scanner and Disk class drivers share */
- /* common routines that can be found in the CLASS directory */
- /* (..\ntos\dd\class). */
- /* */
- /* History.......: 1993: */
- /* - mar 9 : (PS) First change introduced */
- /* - mar 15: (TN) Additional clean-up */
- /* - mar 15: (TN) DebugPrint changed to KdPrint */
- /* - mar 16: (TN) Debugging */
- /* - mar 17: (TN) RtlZeroMemory added */
- /* - mar 17: (TN) Cleaning up */
- /* - mar 29: (TN) Additional comments added */
- /* : (TN) Adding support for multiple scanners */
- /****************************************************************************/
-
- #include "ntddk.h"
- #include "scsi.h"
- #include "class.h"
- #include "string.h"
-
-
- /****************************************************************************/
- /*** Macro definitions ***/
- /****************************************************************************/
-
- #define DEVICE_EXTENSION_SIZE sizeof(DEVICE_EXTENSION)
-
-
- /****************************************************************************/
- /*** Local prototypes ***/
- /****************************************************************************/
-
-
- /* Search the SCSI port for scanner devices */
- BOOLEAN FindScsiScanner(IN PDRIVER_OBJECT DriveObject,
- IN PDEVICE_OBJECT PortDeviceObject,
- IN ULONG PortNumber);
-
- /* Open/close created scanner objects */
- NTSTATUS ScsiScannerOpenClose (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
-
- /* Process calls from DeviceIoControl (I think :-)) */
- NTSTATUS ScsiScannerDeviceControl (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
-
- /* Create a device object for a scanner */
- NTSTATUS CreateScannerDeviceObject (IN PDRIVER_OBJECT DriverObject,
- IN PDEVICE_OBJECT PortDeviceObject,
- IN ULONG PortNumber, IN PULONG DeviceCount,
- IN PIO_SCSI_CAPABILITIES PortCapabilities,
- IN PSCSI_INQUIRY_DATA LunInfo);
-
-
- /****************************************************************************/
- /*** Global functions ***/
- /****************************************************************************/
-
-
- /***************************************************************************/
- /*** Syntax.........: GetScannerStatus ***/
- /*** ***/
- /*** Scope..........: Global ***/
- /*** ***/
- /*** Description....: Returns the status of the scanner ***/
- /*** (Simply sends a SCSI TestUnitReady cdb (0x00) ***/
- /*** ***/
- /*** Parameters.....: DeviceObject, Irp ***/
- /*** ***/
- /*** Return value...: NTSTATUS ***/
- /*** ***/
- /*** External ref...: ***/
- /***************************************************************************/
-
- NTSTATUS GetScannerStatus(
- IN PDEVICE_OBJECT DeviceObject, /* Pointer to deviceObject */
- IN PIRP Irp /* Pointer to request block */
- )
-
- {
- PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
- SCSI_REQUEST_BLOCK srb;
- PCDB cdb = (PCDB)srb.Cdb;
- NTSTATUS status;
-
- KdPrint(("ScannerIoControl: Get Scanner Status\n"));
-
- //
- // Zero CDB in SRB on stack.
- //
-
- RtlZeroMemory(srb.Cdb, MAXIMUM_CDB_SIZE); /* Zero the cdb */
-
- srb.CdbLength = CDB6GENERIC_LENGTH; /* Generic 6 byte cdb */
-
- srb.Cdb[0] = 0x00; /* OP-code = 0x00 */
- srb.Cdb[4] = 0x01;
-
-
- //
- // Set timeout value.
- //
-
- srb.TimeOutValue = deviceExtension->TimeOutValue;
-
- /* ------------------------------------------- */
- /* Send the SCSI cdb - CommandDescriptorBlock */
- /* Using the SendSrbSynchronous function found */
- /* in the CLASS.C file */
- /* ------------------------------------------- */
-
- status = SendSrbSynchronous(DeviceObject,
- &srb, /* the SCSI CommandDescriptor block */
- NULL, /* No transfer buffer */
- 0, /* Length of transfer buffer */
- FALSE); /* Write to device flag */
-
- return status; /* Return the status */
-
- } // end ScannerGetStatus()
-
-
- /***************************************************************************/
- /*** Syntax.........: DriverEntry(PDRIVER_OBJECT DriverObject, ***/
- /*** PUNICODE_STRING RegistryPath) ***/
- /*** ***/
- /*** Scope..........: Global ***/
- /*** ***/
- /*** Description....: This routine initializes the scanner class driver. ***/
- /*** The class driver opens the port driver by name and ***/
- /*** the receives configuration information used to ***/
- /*** attatch to the scanner devices. ***/
- /*** ***/
- /*** Parameters.....: DriverObject, RegistryPath ***/
- /*** ***/
- /*** Return value...: NTSTATUS ***/
- /*** ***/
- /*** External ref...: ***/
- /***************************************************************************/
-
-
- NTSTATUS DriverEntry(
- IN PDRIVER_OBJECT DriverObject, /* Pointer to driver object */
- IN PUNICODE_STRING RegistryPath) /* Path to registry area */
- { /* DriverEntry() */
-
- ULONG portNumber = 0; /* Index of SCSI port */
- NTSTATUS status; /* NT Status code */
- PFILE_OBJECT fileObject; /* Pointer to file object */
- PDEVICE_OBJECT portDeviceObject; /* Pointer to port device object */
- STRING deviceNameString; /* ANSI device name buffer */
- CCHAR deviceNameBuffer[256]; /* Temporary buffer */
- UNICODE_STRING unicodeDeviceName; /* UniCode device name buffer */
- BOOLEAN foundOne = FALSE; /* Flag, set when scanner is found */
-
-
- KdPrint(("\n\nSCSI Scanner Class Driver\n")); /* Debug print string */
-
- /* -------------------------------------- */
- /* Set up the device driver entry points. */
- /* No Read or Write command supported */
- /* -------------------------------------- */
-
- DriverObject->MajorFunction[IRP_MJ_CREATE] = ScsiScannerOpenClose;
- DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiScannerOpenClose;
- DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiScannerDeviceControl;
- DriverObject->MajorFunction[IRP_MJ_SCSI] = ClassInternalDeviceControl;
-
- /* ---------------------------------------- */
- /* Open port driver device objects by name. */
- /* ---------------------------------------- */
-
- do
- {
- /* ------------------------------------- */
- /* Create port driver name (in UniCode). */
- /* ------------------------------------- */
-
- sprintf(deviceNameBuffer, "\\Device\\ScsiPort%d", portNumber); /* SCSI port driver */
-
- KdPrint(("ScsiScannerInitialize: Open %s\n", deviceNameBuffer));
-
- RtlInitString(&deviceNameString, deviceNameBuffer);
-
- status = RtlAnsiStringToUnicodeString(&unicodeDeviceName, /* Convert to UNICODE */
- &deviceNameString,
- TRUE);
-
- if (!NT_SUCCESS(status)) break; /* Exit on error (i.e. */
- /* unknown port adapter) */
-
-
- /* Try to get pointer to SCSI port object */
- status = IoGetDeviceObjectPointer(&unicodeDeviceName, FILE_READ_ATTRIBUTES,
- &fileObject, &portDeviceObject);
-
- /* Release UniCode string */
- RtlFreeUnicodeString(&unicodeDeviceName);
-
- if (NT_SUCCESS(status))
- {
- /* ------------------------ */
- /* SCSI port driver exists. */
- /* ------------------------ */
-
- /* Search this port adapter for a scanner */
- if (FindScsiScanner(DriverObject, portDeviceObject, portNumber++))
- foundOne = TRUE; /* We got it! */
-
- /* ---------------------------------------------------------------- */
- /* Dereference the file object since the port device pointer is no */
- /* longer needed. The claim device code references the port driver */
- /* pointer that is actually being used. */
- /* ---------------------------------------------------------------- */
-
- ObDereferenceObject(fileObject);
- }
-
- } while (NT_SUCCESS(status));
-
- if (foundOne) /* Did we find a scanner? */
- return STATUS_SUCCESS; /* Yes! */
- else
- return STATUS_NO_SUCH_DEVICE; /* No :-< */
-
- } /* DriverEntry() */
-
-
- /***************************************************************************/
- /*** Syntax.........: FindScsiScanner ***/
- /*** ***/
- /*** Scope..........: Global ***/
- /*** ***/
- /*** Description....: Connect to SCSI port driver. Get adapter ***/
- /*** capabilities and SCSI bus configuration. Search ***/
- /*** inquiry data for Scanner devices to process. ***/
- /*** ***/
- /*** Parameters.....: DriverObject, PortDeviceObject, PortNumber ***/
- /*** ***/
- /*** Return value...: NTSTATUS ***/
- /*** ***/
- /*** External ref...: ***/
- /***************************************************************************/
-
-
- BOOLEAN FindScsiScanner (
-
- IN PDRIVER_OBJECT DriverObject, /* Scanner class driver object */
- IN PDEVICE_OBJECT PortDeviceObject, /* SCSI port driver device object */
- IN ULONG PortNumber) /* The system ordinal for this scsi adapter */
- { /* FindScsiScanner() */
-
- PIO_SCSI_CAPABILITIES portCapabilities; /* Port capabilities info */
- PCHAR buffer; /* General buffer area */
- PSCSI_INQUIRY_DATA lunInfo; /* Logical Unit info */
- PSCSI_ADAPTER_BUS_INFO adapterInfo; /* SCSI Adapter info */
- PINQUIRYDATA inquiryData; /* Data buffer for Inquiry cmd. */
- ULONG scsiBus; /* ID number */
- ULONG scannerCount = 0; /* Counts number of scanners */
- NTSTATUS status; /* NT status */
- BOOLEAN foundDevice = FALSE; /* Flag, set if scanner is found */
-
-
- /* --------------------------------------------- */
- /* Call port driver to get adapter capabilities. */
- /* --------------------------------------------- */
-
- status = GetAdapterCapabilities(PortDeviceObject, &portCapabilities);
-
- if (!NT_SUCCESS(status))
- {
- KdPrint(("FindScsiDevices: GetAdapterCapabilities failed\n"));
- return foundDevice;
- }
-
- /* ------------------------------------------------------------- */
- /* Call port driver to get inquiry information to find scanners. */
- /* ------------------------------------------------------------- */
-
- status = GetInquiryData(PortDeviceObject, (PSCSI_ADAPTER_BUS_INFO *) &buffer);
-
- if (!NT_SUCCESS(status))
- {
- KdPrint(("FindScsiDevices: GetInquiryData failed\n"));
- return foundDevice;
- }
-
-
- /* --------------------------------------------------------------------------- */
- /* Get the address of the count of the number of scanners already initialized. */
- /* --------------------------------------------------------------------------- */
-
- adapterInfo = (PVOID) buffer;
-
- /* ------------------------------------------ */
- /* For each SCSI bus this adapter supports... */
- /* ------------------------------------------ */
-
- for (scsiBus=0; scsiBus < adapterInfo->NumberOfBuses; scsiBus++)
- {
- /* ---------------------------------------- */
- /* Get the SCSI bus scan data for this bus. */
- /* ---------------------------------------- */
-
- lunInfo = (PVOID) (buffer + adapterInfo->BusData[scsiBus].InquiryDataOffset);
-
- /* ------------------------------------------ */
- /* Search list for unclaimed scanner devices. */
- /* ------------------------------------------ */
-
- while (adapterInfo->BusData[scsiBus].InquiryDataOffset)
- {
- inquiryData = (PVOID)lunInfo->InquiryData;
- /* --------------------------------------------------------------------------- */
- /* Check if the device found is a scanner device. List of defined SCSI devices */
- /* can be found in the SCSI.H file. */
- /* Thereafter, check if this device haven't been claimed by another driver */
- /* --------------------------------------------------------------------------- */
- if ((inquiryData->DeviceType == SCANNER_DEVICE) && (!lunInfo->DeviceClaimed))
- {
- KdPrint(("FindScsiDevices: Vendor string is %.24s\n",
- inquiryData->VendorId));
-
- /* --------------------------------- */
- /* Create device objects for scanner */
- /* --------------------------------- */
-
- status = CreateScannerDeviceObject(DriverObject, PortDeviceObject,
- PortNumber, &scannerCount,
- portCapabilities, lunInfo);
-
- if (NT_SUCCESS(status))
- {
- scannerCount++;
-
- /* ----------------------------------------- */
- /* Indicate that a scanner device was found. */
- /* ----------------------------------------- */
-
- foundDevice = TRUE;
-
- KdPrint(("We created an device object!!"));
-
-
- break; /* Create only one object for the first LUN */
- }
- }
-
- /* ----------------- */
- /* Get next LunInfo. */
- /* ----------------- */
-
- if (lunInfo->NextInquiryDataOffset == 0)
- break;
-
- lunInfo = (PVOID) (buffer + lunInfo->NextInquiryDataOffset);
- }
- }
-
- ExFreePool(buffer);
-
- return foundDevice;
-
- } /* FindScsiScanner() */
-
-
- /***************************************************************************/
- /*** Syntax.........: CreateScannerDeviceObject ***/
- /*** ***/
- /*** Scope..........: Global ***/
- /*** ***/
- /*** Description....: This routine creates an object for the device ***/
- /*** ***/
- /*** Parameters.....: DriverObject, PortDeviceObject, PortNumber, ***/
- /*** DeviceCount, PortCapabilities ***/
- /*** ***/
- /*** Return value...: NTSTATUS ***/
- /*** ***/
- /*** External ref...: ***/
- /***************************************************************************/
-
- NTSTATUS CreateScannerDeviceObject (
-
- IN PDRIVER_OBJECT DriverObject, /* Pointer to driver object created by system */
- IN PDEVICE_OBJECT PortDeviceObject, /* to connect to SCSI port driver */
- IN ULONG PortNumber, /* Ordinal value of port ID */
- IN PULONG DeviceCount, /* Number of previous installed scanners */
- IN PIO_SCSI_CAPABILITIES PortCapabilities, /* Pointer to structure returned by SCSI port */
- /* driver describing adapter capabilities (and */
- /* limitations). */
- IN PSCSI_INQUIRY_DATA LunInfo) /* Pointer to configuration info for this device */
- { /* CreateScannerDeviceObject() */
-
- UCHAR ntNameBuffer[64];
- UCHAR arcNameBuffer[64];
- STRING ntNameString;
- STRING arcNameString;
- UNICODE_STRING ntUnicodeString;
- UNICODE_STRING arcUnicodeString;
- NTSTATUS status;
- PDEVICE_OBJECT deviceObject = NULL;
- PDEVICE_EXTENSION deviceExtension;
- PVOID senseData = NULL;
-
- OBJECT_ATTRIBUTES LinkAttributes; /* Used for creation of the symbolic link */
- UNICODE_STRING LinkObject;
- HANDLE LinkHandle;
- UCHAR LinkNameBuffer[64];
- STRING LinkNameString;
-
-
-
- /* ------------------------------- */
- /* Claim the device (Get it boys). */
- /* ------------------------------- */
-
- status = ClassClaimDevice(PortDeviceObject, LunInfo, FALSE, &PortDeviceObject);
- if (!NT_SUCCESS(status)) return(status); /* Exit on error */
-
-
-
- /* ------------------------------------- */
- /* Create device object for this device. */
- /* ------------------------------------- */
-
- sprintf(ntNameBuffer, "\\Device\\Scanner%d", *DeviceCount); /* This is actually obsolent */
-
- RtlInitString(&ntNameString, ntNameBuffer);
-
- KdPrint(("CreateScannerDeviceObjects: Create device object %s\n",
- ntNameBuffer));
-
- /* Convert ANSI string to Unicode. */
- status = RtlAnsiStringToUnicodeString(&ntUnicodeString, &ntNameString, TRUE);
-
-
- if (!NT_SUCCESS(status)) /* Get an error? */
- {
- KdPrint(("CreateScannerDeviceObjects: Cannot convert string %s\n",
- ntNameBuffer));
-
- /* ------------------------------------------ */
- /* Release the device since an error occured. */
- /* ------------------------------------------ */
-
- ClassClaimDevice(PortDeviceObject, LunInfo, TRUE, NULL);
-
- return(status);
- }
-
-
- /* -------------------------------------- */
- /* Create device object for this scanner. */
- /* -------------------------------------- */
-
- status = IoCreateDevice(DriverObject,
- DEVICE_EXTENSION_SIZE,
- &ntUnicodeString,
- FILE_DEVICE_SCANNER, /* Type of device */
- FILE_REMOTE_DEVICE, /* Note: Scanner and printer devices */
- FALSE, /* has to specify FILE_READ */
- &deviceObject); /* ONLY_DEVICE and *NOT* FILE_ */
- /* REMOVABLE_DEVICE !!! */
-
- if (!NT_SUCCESS(status)) /* Get an error? */
- {
- KdPrint(("CreateScannerDeviceObjects: Cannot create device %s\n",
- ntNameBuffer));
-
- RtlFreeUnicodeString(&ntUnicodeString); /* Release UniCode buffer */
- deviceObject = NULL; /* No device object created */
- goto CreateScannerDeviceObjectExit; /* Go to error recovery */
- }
-
-
- /* --------------------------------------- */
- /* Indicate that IRPs should include MDLs. */
- /* --------------------------------------- */
-
- deviceObject->Flags |= DO_DIRECT_IO;
-
-
- /* -------------------------------------------- */
- /* Set up required stack size in device object. */
- /* -------------------------------------------- */
-
- deviceObject->StackSize = PortDeviceObject->StackSize + 1;
- deviceExtension = deviceObject->DeviceExtension;
-
-
- /* ----------------------------------------------- */
- /* Allocate spinlock for split request completion. */
- /* ----------------------------------------------- */
-
- KeInitializeSpinLock(&deviceExtension->SplitRequestSpinLock);
-
-
- /* ----------------------------------- */
- /* Fill out the device extension block */
- /* ----------------------------------- */
-
- deviceExtension->PhysicalDevice = deviceObject;
- deviceExtension->PortDeviceObject = PortDeviceObject;
- deviceExtension->PortCapabilities = PortCapabilities;
- deviceExtension->SrbFlags = SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
-
- /* Allocate sense data buffer */
- senseData = ExAllocatePool(NonPagedPoolCacheAligned, SENSE_BUFFER_SIZE);
-
- if (senseData == NULL) /* Get an error? */
- {
- status = STATUS_INSUFFICIENT_RESOURCES; /* Out of memory */
- goto CreateScannerDeviceObjectExit; /* Go to error recovery */
- }
-
- deviceExtension->SenseData = senseData;
-
- deviceExtension->StartingOffset.LowPart = 0; /* From Cd-Rom template */
- deviceExtension->StartingOffset.HighPart = 0;
-
- deviceExtension->PathId = LunInfo->PathId; /* Save device path (PathId\TargetId\Lun) */
- deviceExtension->TargetId = LunInfo->TargetId;
- deviceExtension->Lun = LunInfo->Lun;
-
- /* TN debug stuff */
-
- deviceExtension->TimeOutValue = 180; /* Time out value */
-
- deviceExtension->DeviceObject = deviceObject; /* Back pointer to device object */
-
-
-
- /* Create a symblic link in order to let Win32 recognize the device */
-
- KdPrint(("ScsiScannerSymbolicLink: Converting to UNICODE\n"));
-
- sprintf(LinkNameBuffer, "\\DosDevices\\Scanner%d", PortNumber); /* SCSI Scanner driver number */
-
-
- RtlInitString(&LinkNameString, LinkNameBuffer);
-
- status = RtlAnsiStringToUnicodeString(&LinkObject, /* Convert to UNICODE */
- &LinkNameString,
- TRUE);
-
- if (!NT_SUCCESS(status))
- {
- KdPrint(("ScsiScannerSymblicLink: Could not convert to UNICODE\n"));;
- }
-
-
- InitializeObjectAttributes(&LinkAttributes,
- &LinkObject,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
-
- status = ZwCreateSymbolicLinkObject(&LinkHandle,
- SYMBOLIC_LINK_ALL_ACCESS,
- &LinkAttributes,
- &ntUnicodeString);
-
-
- KdPrint(("Symblic link created:\n", LinkNameBuffer));
-
- if (!NT_SUCCESS(status))
- {
-
- KdPrint(("Symbolic link failed !!!\n"));
-
- }
-
- /* Release UniCode string */
- RtlFreeUnicodeString(&LinkObject);
-
- return(STATUS_SUCCESS); /* Exit with status code */
-
- CreateScannerDeviceObjectExit:
-
- KdPrint(("ErrorRecovery - CreateScannerDeviceObjectExit reached !!"));
-
- /* -------------- */
- /* ERROR RECOVERY */
- /* -------------- */
-
- ClassClaimDevice(PortDeviceObject, /* Release the port device, since */
- LunInfo, TRUE, NULL); /* an error has occured. */
-
- if (senseData != NULL) /* Sense data allocated? */
- ExFreePool(senseData); /* Yes - then free it */
-
- if (deviceObject != NULL) /* Device object created? */
- IoDeleteDevice(deviceObject); /* Yes - Delete it */
-
- return status; /* And exit! */
-
- } /* CreateScannerDeviceObject() */
-
-
- /***************************************************************************/
- /*** Syntax.........: ScsiScannerOpenClose ***/
- /*** ***/
- /*** Scope..........: Global ***/
- /*** ***/
- /*** Description....: Handles the open/close access to the driver ***/
- /*** ***/
- /*** Parameters.....: DeviceObject, Irp ***/
- /*** ***/
- /*** Return value...: Always NTSTATUS ***/
- /*** ***/
- /*** External ref...: ***/
- /***************************************************************************/
-
- NTSTATUS ScsiScannerOpenClose (
-
- IN PDEVICE_OBJECT DeviceObject, /* Device object for the scanner */
- IN PIRP Irp) /* Open or Close request packet */
- { /* ScsiScannerOpenClose() */
-
- /* Set status in Irp. */
- Irp->IoStatus.Status = STATUS_SUCCESS;
-
- /* Complete request at raised IRQ. */
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
- return STATUS_SUCCESS;
-
- } /* ScsiScannerOpenClose() */
-
-
- /***************************************************************************/
- /*** Syntax.........: ScsiScannerDeviceControl ***/
- /*** ***/
- /*** Scope..........: Global ***/
- /*** ***/
- /*** Description....: This is the NT device control handler for scanner ***/
- /*** requests ***/
- /*** ***/
- /*** Parameters.....: DeviceObject, Irp ***/
- /*** ***/
- /*** Return value...: NTSTATUS ***/
- /*** ***/
- /*** External ref...: ***/
- /***************************************************************************/
-
-
- NTSTATUS ScsiScannerDeviceControl (
-
- IN PDEVICE_OBJECT DeviceObject, /* Device object for this scanner */
- IN PIRP Irp) /* IO request packet */
- { /* ScsiScannerDeviceControl() */
-
- PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
- PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
- SCSI_REQUEST_BLOCK srb;
- NTSTATUS status;
-
-
- KdPrint(("ScsiScannerDeviceControl: Entering routine\n"));
-
- /* ------------------------------------------ */
- /* Check the DeviceIoCoontrol control code */
- /* specified in the Win32 calling application */
- /* ------------------------------------------ */
-
- switch (irpStack->Parameters.DeviceIoControl.IoControlCode)
- {
-
- case 100:
-
- KdPrint(("SCSI Control: Get Scanner Status\n"));
-
- status = GetScannerStatus(DeviceObject, Irp); /* TestUnitReady */
- break;
-
-
- default:
- /* ------------------------------------------------------ */
- /* Pass the request to the common device control routine. */
- /* This routine can be found in the CLASS.C file */
- /* The ScsiClassDeviceControl also handles the IOCTL_SCSI */
- /* _PASS_THROUGH ioctl */
- /* ------------------------------------------------------ */
-
- KdPrint(("Passing request to common device control"));
-
- return(ScsiClassDeviceControl(DeviceObject, Irp));
- }
-
- /* Update IRP with completion status. */
- Irp->IoStatus.Status = status;
-
- /* Complete the request. */
- IoCompleteRequest(Irp, IO_DISK_INCREMENT);
- KdPrint(("ScsiScannerDeviceControl: Status is %lx\n", status));
- return status;
-
- } /* ScsiScannerDeviceControl() */
-
- /* EOF */
-