home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / winnt / mswin32 / lib13 / class.lzh / SCANNER.C < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-06  |  29.6 KB  |  709 lines

  1. /****************************************************************************/
  2. /* Copyright (c) 1991  Microsoft Corporation                                */
  3. /* Changes copyright (c) 1993  DMC Danmark                                  */
  4. /*                                                                          */
  5. /* Module name...: SCANNER.C                                                */
  6. /*                                                                          */
  7. /* Description...: A minimul SCSI scanner class driver                      */
  8. /*                                                                          */
  9. /* Environment...: Kernel mode only!                                        */
  10. /*                                                                          */
  11. /* Notes.........: SCSI Tape, CDRom, Scanner and Disk class drivers share   */
  12. /*                 common routines that can be found in the CLASS directory */
  13. /*                 (..\ntos\dd\class).                                      */
  14. /*                                                                          */
  15. /* History.......: 1993:                                                    */
  16. /*                 - mar 9 : (PS) First change introduced                   */
  17. /*                 - mar 15: (TN) Additional clean-up                       */
  18. /*                 - mar 15: (TN) DebugPrint changed to KdPrint             */
  19. /*                 - mar 16: (TN) Debugging                                 */
  20. /*                 - mar 17: (TN) RtlZeroMemory added                       */
  21. /*                 - mar 17: (TN) Cleaning up                               */
  22. /*                 - mar 29: (TN) Additional comments added                 */
  23. /*                         : (TN) Adding support for multiple scanners      */
  24. /****************************************************************************/
  25.  
  26. #include "ntddk.h"
  27. #include "scsi.h"
  28. #include "class.h"
  29. #include "string.h"
  30.  
  31.  
  32. /****************************************************************************/
  33. /***  Macro definitions                                                   ***/
  34. /****************************************************************************/
  35.  
  36. #define DEVICE_EXTENSION_SIZE sizeof(DEVICE_EXTENSION)
  37.  
  38.  
  39. /****************************************************************************/
  40. /*** Local prototypes                                                     ***/
  41. /****************************************************************************/
  42.  
  43.  
  44.   /* Search the SCSI port for scanner devices */
  45. BOOLEAN FindScsiScanner(IN PDRIVER_OBJECT DriveObject,
  46.                         IN PDEVICE_OBJECT PortDeviceObject,
  47.                         IN ULONG PortNumber);
  48.  
  49.   /* Open/close created scanner objects */
  50. NTSTATUS ScsiScannerOpenClose (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
  51.  
  52.   /* Process calls from DeviceIoControl (I think :-)) */
  53. NTSTATUS ScsiScannerDeviceControl (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
  54.  
  55.   /* Create a device object for a scanner */
  56. NTSTATUS CreateScannerDeviceObject (IN PDRIVER_OBJECT DriverObject,
  57.                                     IN PDEVICE_OBJECT PortDeviceObject,
  58.                                     IN ULONG PortNumber, IN PULONG DeviceCount,
  59.                                     IN PIO_SCSI_CAPABILITIES PortCapabilities,
  60.                                     IN PSCSI_INQUIRY_DATA LunInfo);
  61.  
  62.  
  63. /****************************************************************************/
  64. /*** Global functions                                                     ***/
  65. /****************************************************************************/
  66.  
  67.  
  68. /***************************************************************************/
  69. /*** Syntax.........: GetScannerStatus                                   ***/
  70. /***                                                                     ***/
  71. /*** Scope..........: Global                                             ***/
  72. /***                                                                     ***/
  73. /*** Description....: Returns the status of the scanner                  ***/
  74. /***                  (Simply sends a SCSI TestUnitReady cdb (0x00)      ***/
  75. /***                                                                     ***/
  76. /*** Parameters.....: DeviceObject, Irp                                  ***/
  77. /***                                                                     ***/
  78. /*** Return value...: NTSTATUS                                           ***/
  79. /***                                                                     ***/
  80. /*** External ref...:                                                    ***/
  81. /***************************************************************************/
  82.  
  83. NTSTATUS GetScannerStatus(
  84.     IN PDEVICE_OBJECT DeviceObject,       /* Pointer to deviceObject */
  85.     IN PIRP Irp                           /* Pointer to request block */
  86.     )
  87.  
  88. {
  89.     PDEVICE_EXTENSION   deviceExtension = DeviceObject->DeviceExtension;
  90.     SCSI_REQUEST_BLOCK  srb;
  91.     PCDB                cdb = (PCDB)srb.Cdb;
  92.     NTSTATUS            status;
  93.  
  94.     KdPrint(("ScannerIoControl: Get Scanner Status\n"));
  95.  
  96.     //
  97.     // Zero CDB in SRB on stack.
  98.     //
  99.  
  100.     RtlZeroMemory(srb.Cdb, MAXIMUM_CDB_SIZE);      /* Zero the cdb */
  101.  
  102.     srb.CdbLength = CDB6GENERIC_LENGTH;        /* Generic 6 byte cdb */
  103.  
  104.     srb.Cdb[0] = 0x00;  /* OP-code = 0x00 */
  105.     srb.Cdb[4] = 0x01;
  106.  
  107.  
  108.     //
  109.     // Set timeout value.
  110.     //
  111.  
  112.     srb.TimeOutValue = deviceExtension->TimeOutValue;
  113.  
  114.     /* ------------------------------------------- */
  115.     /* Send the SCSI cdb - CommandDescriptorBlock  */
  116.     /* Using the SendSrbSynchronous function found */
  117.     /* in the CLASS.C file                         */
  118.     /* ------------------------------------------- */
  119.  
  120.     status = SendSrbSynchronous(DeviceObject,
  121.                                 &srb,                        /* the SCSI CommandDescriptor block */
  122.                                 NULL,                        /* No transfer buffer */
  123.                                 0,                           /* Length of transfer buffer */
  124.                                 FALSE);                      /* Write to device flag */
  125.  
  126.     return status;     /* Return the status */
  127.  
  128. } // end ScannerGetStatus()
  129.  
  130.  
  131. /***************************************************************************/
  132. /*** Syntax.........: DriverEntry(PDRIVER_OBJECT DriverObject,           ***/
  133. /***                              PUNICODE_STRING RegistryPath)          ***/
  134. /***                                                                     ***/
  135. /*** Scope..........: Global                                             ***/
  136. /***                                                                     ***/
  137. /*** Description....: This routine initializes the scanner class driver. ***/
  138. /***                  The class driver opens the port driver by name and ***/
  139. /***                  the receives configuration information used to     ***/
  140. /***                  attatch to the scanner devices.                    ***/
  141. /***                                                                     ***/
  142. /*** Parameters.....: DriverObject, RegistryPath                         ***/
  143. /***                                                                     ***/
  144. /*** Return value...: NTSTATUS                                           ***/
  145. /***                                                                     ***/
  146. /*** External ref...:                                                    ***/
  147. /***************************************************************************/
  148.  
  149.  
  150. NTSTATUS DriverEntry(
  151.  IN PDRIVER_OBJECT  DriverObject,        /* Pointer to driver object */
  152.  IN PUNICODE_STRING RegistryPath)        /* Path to registry area */
  153. {     /* DriverEntry() */
  154.  
  155.    ULONG        portNumber = 0;        /* Index of SCSI port */
  156.    NTSTATUS        status;            /* NT Status code */
  157.    PFILE_OBJECT        fileObject;        /* Pointer to file object */
  158.    PDEVICE_OBJECT    portDeviceObject;    /* Pointer to port device object */
  159.    STRING        deviceNameString;    /* ANSI device name buffer */
  160.    CCHAR        deviceNameBuffer[256];    /* Temporary buffer */
  161.    UNICODE_STRING    unicodeDeviceName;    /* UniCode device name buffer */
  162.    BOOLEAN        foundOne = FALSE;    /* Flag, set when scanner is found */
  163.  
  164.  
  165.    KdPrint(("\n\nSCSI Scanner Class Driver\n")); /* Debug print string */
  166.  
  167.    /* -------------------------------------- */
  168.    /* Set up the device driver entry points. */
  169.    /* No Read or Write command supported     */
  170.    /* -------------------------------------- */
  171.  
  172.    DriverObject->MajorFunction[IRP_MJ_CREATE]         = ScsiScannerOpenClose;
  173.    DriverObject->MajorFunction[IRP_MJ_CLOSE]          = ScsiScannerOpenClose;
  174.    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiScannerDeviceControl;
  175.    DriverObject->MajorFunction[IRP_MJ_SCSI]           = ClassInternalDeviceControl;
  176.  
  177.    /* ---------------------------------------- */
  178.    /* Open port driver device objects by name. */
  179.    /* ---------------------------------------- */
  180.  
  181.    do
  182.    {
  183.       /* ------------------------------------- */
  184.       /* Create port driver name (in UniCode). */
  185.       /* ------------------------------------- */
  186.  
  187.       sprintf(deviceNameBuffer, "\\Device\\ScsiPort%d", portNumber);  /* SCSI port driver */
  188.  
  189.       KdPrint(("ScsiScannerInitialize: Open %s\n", deviceNameBuffer));
  190.  
  191.       RtlInitString(&deviceNameString, deviceNameBuffer);
  192.  
  193.       status = RtlAnsiStringToUnicodeString(&unicodeDeviceName,       /* Convert to UNICODE */
  194.                                             &deviceNameString,
  195.                                             TRUE);
  196.  
  197.       if (!NT_SUCCESS(status)) break;        /* Exit on error (i.e.   */
  198.                         /* unknown port adapter) */
  199.  
  200.  
  201.         /* Try to get pointer to SCSI port object */
  202.       status = IoGetDeviceObjectPointer(&unicodeDeviceName, FILE_READ_ATTRIBUTES,
  203.                                         &fileObject, &portDeviceObject);
  204.  
  205.         /* Release UniCode string */
  206.       RtlFreeUnicodeString(&unicodeDeviceName);
  207.  
  208.       if (NT_SUCCESS(status))
  209.       {
  210.          /* ------------------------ */
  211.          /* SCSI port driver exists. */
  212.          /* ------------------------ */
  213.  
  214.            /* Search this port adapter for a scanner */
  215.          if (FindScsiScanner(DriverObject, portDeviceObject, portNumber++))
  216.             foundOne = TRUE;        /* We got it! */
  217.  
  218.          /* ---------------------------------------------------------------- */
  219.          /* Dereference the file object since the port device pointer is no  */
  220.          /* longer needed.  The claim device code references the port driver */
  221.          /* pointer that is actually being used.                             */
  222.          /* ---------------------------------------------------------------- */
  223.  
  224.          ObDereferenceObject(fileObject);
  225.       }
  226.  
  227.    } while (NT_SUCCESS(status));
  228.  
  229.    if (foundOne)                /* Did we find a scanner? */
  230.       return STATUS_SUCCESS;            /* Yes! */
  231.    else
  232.       return STATUS_NO_SUCH_DEVICE;        /* No :-< */
  233.  
  234. }     /* DriverEntry() */
  235.  
  236.  
  237. /***************************************************************************/
  238. /*** Syntax.........: FindScsiScanner                                    ***/
  239. /***                                                                     ***/
  240. /*** Scope..........: Global                                             ***/
  241. /***                                                                     ***/
  242. /*** Description....: Connect to SCSI port driver. Get adapter           ***/
  243. /***                  capabilities and SCSI bus configuration. Search    ***/
  244. /***                  inquiry data for Scanner devices to process.       ***/
  245. /***                                                                     ***/
  246. /*** Parameters.....: DriverObject, PortDeviceObject, PortNumber         ***/
  247. /***                                                                     ***/
  248. /*** Return value...: NTSTATUS                                           ***/
  249. /***                                                                     ***/
  250. /*** External ref...:                                                    ***/
  251. /***************************************************************************/
  252.  
  253.  
  254. BOOLEAN FindScsiScanner (
  255.  
  256.  IN PDRIVER_OBJECT DriverObject,    /* Scanner class driver object */
  257.  IN PDEVICE_OBJECT PortDeviceObject,    /* SCSI port driver device object */
  258.  IN ULONG          PortNumber)        /* The system ordinal for this scsi adapter */
  259. {     /* FindScsiScanner() */
  260.  
  261.    PIO_SCSI_CAPABILITIES    portCapabilities;    /* Port capabilities info */
  262.    PCHAR            buffer;            /* General buffer area */
  263.    PSCSI_INQUIRY_DATA        lunInfo;        /* Logical Unit info */
  264.    PSCSI_ADAPTER_BUS_INFO    adapterInfo;        /* SCSI Adapter info */
  265.    PINQUIRYDATA            inquiryData;        /* Data buffer for Inquiry cmd. */
  266.    ULONG            scsiBus;        /* ID number */
  267.    ULONG            scannerCount = 0;    /* Counts number of scanners */
  268.    NTSTATUS            status;            /* NT status */
  269.    BOOLEAN            foundDevice = FALSE;    /* Flag, set if scanner is found */
  270.  
  271.  
  272.    /* --------------------------------------------- */
  273.    /* Call port driver to get adapter capabilities. */
  274.    /* --------------------------------------------- */
  275.  
  276.    status = GetAdapterCapabilities(PortDeviceObject, &portCapabilities);
  277.  
  278.    if (!NT_SUCCESS(status))
  279.    {
  280.       KdPrint(("FindScsiDevices: GetAdapterCapabilities failed\n"));
  281.       return foundDevice;
  282.    }
  283.  
  284.    /* ------------------------------------------------------------- */
  285.    /* Call port driver to get inquiry information to find scanners. */
  286.    /* ------------------------------------------------------------- */
  287.  
  288.    status = GetInquiryData(PortDeviceObject, (PSCSI_ADAPTER_BUS_INFO *) &buffer);
  289.  
  290.    if (!NT_SUCCESS(status))
  291.    {
  292.       KdPrint(("FindScsiDevices: GetInquiryData failed\n"));
  293.       return foundDevice;
  294.    }
  295.  
  296.  
  297.    /* --------------------------------------------------------------------------- */
  298.    /* Get the address of the count of the number of scanners already initialized. */
  299.    /* --------------------------------------------------------------------------- */
  300.  
  301.    adapterInfo = (PVOID) buffer;
  302.  
  303.    /* ------------------------------------------ */
  304.    /* For each SCSI bus this adapter supports... */
  305.    /* ------------------------------------------ */
  306.  
  307.    for (scsiBus=0; scsiBus < adapterInfo->NumberOfBuses; scsiBus++)
  308.    {
  309.       /* ---------------------------------------- */
  310.       /* Get the SCSI bus scan data for this bus. */
  311.       /* ---------------------------------------- */
  312.  
  313.       lunInfo = (PVOID) (buffer + adapterInfo->BusData[scsiBus].InquiryDataOffset);
  314.  
  315.       /* ------------------------------------------ */
  316.       /* Search list for unclaimed scanner devices. */
  317.       /* ------------------------------------------ */
  318.  
  319.       while (adapterInfo->BusData[scsiBus].InquiryDataOffset)
  320.       {
  321.          inquiryData = (PVOID)lunInfo->InquiryData;
  322.          /* --------------------------------------------------------------------------- */
  323.          /* Check if the device found is a scanner device. List of defined SCSI devices */
  324.          /* can be found in the SCSI.H file.                                            */
  325.          /* Thereafter, check if this device haven't been claimed by another driver     */
  326.          /* --------------------------------------------------------------------------- */
  327.          if ((inquiryData->DeviceType == SCANNER_DEVICE) && (!lunInfo->DeviceClaimed))
  328.          {
  329.             KdPrint(("FindScsiDevices: Vendor string is %.24s\n",
  330.                        inquiryData->VendorId));
  331.  
  332.             /* --------------------------------- */
  333.             /* Create device objects for scanner */
  334.             /* --------------------------------- */
  335.  
  336.             status = CreateScannerDeviceObject(DriverObject, PortDeviceObject,
  337.                                                PortNumber, &scannerCount,
  338.                                                portCapabilities, lunInfo);
  339.  
  340.             if (NT_SUCCESS(status))
  341.             {
  342.                scannerCount++;
  343.  
  344.                /* ----------------------------------------- */
  345.                /* Indicate that a scanner device was found. */
  346.                /* ----------------------------------------- */
  347.  
  348.                foundDevice = TRUE;
  349.  
  350.                KdPrint(("We created an device object!!"));
  351.  
  352.  
  353.                break;     /* Create only one object for the first LUN */
  354.             }
  355.          }
  356.  
  357.          /* ----------------- */
  358.          /* Get next LunInfo. */
  359.          /* ----------------- */
  360.  
  361.          if (lunInfo->NextInquiryDataOffset == 0)
  362.             break;
  363.  
  364.          lunInfo = (PVOID) (buffer + lunInfo->NextInquiryDataOffset);
  365.       }
  366.    }
  367.  
  368.    ExFreePool(buffer);
  369.  
  370.    return foundDevice;
  371.  
  372. }     /* FindScsiScanner() */
  373.  
  374.  
  375. /***************************************************************************/
  376. /*** Syntax.........: CreateScannerDeviceObject                          ***/
  377. /***                                                                     ***/
  378. /*** Scope..........: Global                                             ***/
  379. /***                                                                     ***/
  380. /*** Description....: This routine creates an object for the device      ***/
  381. /***                                                                     ***/
  382. /*** Parameters.....: DriverObject, PortDeviceObject, PortNumber,        ***/
  383. /***                  DeviceCount, PortCapabilities                      ***/
  384. /***                                                                     ***/
  385. /*** Return value...: NTSTATUS                                           ***/
  386. /***                                                                     ***/
  387. /*** External ref...:                                                    ***/
  388. /***************************************************************************/
  389.  
  390. NTSTATUS CreateScannerDeviceObject (
  391.  
  392.  IN PDRIVER_OBJECT        DriverObject,        /* Pointer to driver object created by system */
  393.  IN PDEVICE_OBJECT        PortDeviceObject,    /* to connect to SCSI port driver */
  394.  IN ULONG                 PortNumber,        /* Ordinal value of port ID */
  395.  IN PULONG                DeviceCount,        /* Number of previous installed scanners */
  396.  IN PIO_SCSI_CAPABILITIES PortCapabilities,    /* Pointer to structure returned by SCSI port  */
  397.                         /* driver describing adapter capabilities (and */
  398.                         /* limitations).                               */
  399.  IN PSCSI_INQUIRY_DATA    LunInfo)        /* Pointer to configuration info for this device */
  400. {     /* CreateScannerDeviceObject() */
  401.  
  402.    UCHAR        ntNameBuffer[64];
  403.    UCHAR        arcNameBuffer[64];
  404.    STRING        ntNameString;
  405.    STRING        arcNameString;
  406.    UNICODE_STRING    ntUnicodeString;
  407.    UNICODE_STRING    arcUnicodeString;
  408.    NTSTATUS        status;
  409.    PDEVICE_OBJECT    deviceObject = NULL;
  410.    PDEVICE_EXTENSION    deviceExtension;
  411.    PVOID        senseData = NULL;
  412.  
  413.    OBJECT_ATTRIBUTES     LinkAttributes;        /* Used for creation of the symbolic link */
  414.    UNICODE_STRING        LinkObject;
  415.    HANDLE                LinkHandle;
  416.    UCHAR         LinkNameBuffer[64];
  417.    STRING         LinkNameString;
  418.  
  419.  
  420.  
  421.    /* ------------------------------- */
  422.    /* Claim the device (Get it boys). */
  423.    /* ------------------------------- */
  424.  
  425.    status = ClassClaimDevice(PortDeviceObject, LunInfo, FALSE, &PortDeviceObject);
  426.    if (!NT_SUCCESS(status)) return(status);    /* Exit on error */
  427.  
  428.  
  429.  
  430.    /* ------------------------------------- */
  431.    /* Create device object for this device. */
  432.    /* ------------------------------------- */
  433.  
  434.    sprintf(ntNameBuffer, "\\Device\\Scanner%d", *DeviceCount);             /* This is actually obsolent */
  435.  
  436.    RtlInitString(&ntNameString, ntNameBuffer);
  437.  
  438.    KdPrint(("CreateScannerDeviceObjects: Create device object %s\n",
  439.                ntNameBuffer));
  440.  
  441.      /* Convert ANSI string to Unicode. */
  442.    status = RtlAnsiStringToUnicodeString(&ntUnicodeString, &ntNameString, TRUE);
  443.  
  444.  
  445.    if (!NT_SUCCESS(status))            /* Get an error? */
  446.    {
  447.       KdPrint(("CreateScannerDeviceObjects: Cannot convert string %s\n",
  448.                   ntNameBuffer));
  449.  
  450.       /* ------------------------------------------ */
  451.       /* Release the device since an error occured. */
  452.       /* ------------------------------------------ */
  453.  
  454.       ClassClaimDevice(PortDeviceObject, LunInfo, TRUE, NULL);
  455.  
  456.       return(status);
  457.    }
  458.  
  459.  
  460.    /* -------------------------------------- */
  461.    /* Create device object for this scanner. */
  462.    /* -------------------------------------- */
  463.  
  464.    status = IoCreateDevice(DriverObject,
  465.                            DEVICE_EXTENSION_SIZE,
  466.                            &ntUnicodeString,
  467.                            FILE_DEVICE_SCANNER,         /* Type of device */
  468.                            FILE_REMOTE_DEVICE,          /* Note: Scanner and printer devices */
  469.                            FALSE,                       /*       has to specify FILE_READ    */
  470.                            &deviceObject);              /*       ONLY_DEVICE and *NOT* FILE_ */
  471.                                                         /*       REMOVABLE_DEVICE !!!        */
  472.  
  473.    if (!NT_SUCCESS(status))            /* Get an error? */
  474.    {
  475.       KdPrint(("CreateScannerDeviceObjects: Cannot create device %s\n",
  476.                   ntNameBuffer));
  477.  
  478.       RtlFreeUnicodeString(&ntUnicodeString);    /* Release UniCode buffer */
  479.       deviceObject = NULL;            /* No device object created */
  480.       goto CreateScannerDeviceObjectExit;    /* Go to error recovery */
  481.    }
  482.  
  483.  
  484.    /* --------------------------------------- */
  485.    /* Indicate that IRPs should include MDLs. */
  486.    /* --------------------------------------- */
  487.  
  488.    deviceObject->Flags |= DO_DIRECT_IO;
  489.  
  490.  
  491.    /* -------------------------------------------- */
  492.    /* Set up required stack size in device object. */
  493.    /* -------------------------------------------- */
  494.  
  495.    deviceObject->StackSize = PortDeviceObject->StackSize + 1;
  496.    deviceExtension = deviceObject->DeviceExtension;
  497.  
  498.  
  499.    /* ----------------------------------------------- */
  500.    /* Allocate spinlock for split request completion. */
  501.    /* ----------------------------------------------- */
  502.  
  503.    KeInitializeSpinLock(&deviceExtension->SplitRequestSpinLock);
  504.  
  505.  
  506.    /* ----------------------------------- */
  507.    /* Fill out the device extension block */
  508.    /* ----------------------------------- */
  509.  
  510.    deviceExtension->PhysicalDevice = deviceObject;
  511.    deviceExtension->PortDeviceObject = PortDeviceObject;
  512.    deviceExtension->PortCapabilities = PortCapabilities;
  513.    deviceExtension->SrbFlags = SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
  514.  
  515.      /* Allocate sense data buffer */
  516.    senseData = ExAllocatePool(NonPagedPoolCacheAligned, SENSE_BUFFER_SIZE);
  517.  
  518.    if (senseData == NULL)            /* Get an error? */
  519.    {
  520.       status = STATUS_INSUFFICIENT_RESOURCES;    /* Out of memory */
  521.       goto CreateScannerDeviceObjectExit;    /* Go to error recovery */
  522.    }
  523.  
  524.    deviceExtension->SenseData = senseData;
  525.  
  526.    deviceExtension->StartingOffset.LowPart = 0;        /* From Cd-Rom template */
  527.    deviceExtension->StartingOffset.HighPart = 0;
  528.  
  529.    deviceExtension->PathId = LunInfo->PathId;        /* Save device path (PathId\TargetId\Lun) */
  530.    deviceExtension->TargetId = LunInfo->TargetId;
  531.    deviceExtension->Lun = LunInfo->Lun;
  532.  
  533.    /* TN debug stuff */
  534.  
  535.    deviceExtension->TimeOutValue = 180;                  /* Time out value */
  536.  
  537.    deviceExtension->DeviceObject = deviceObject;    /* Back pointer to device object */
  538.  
  539.  
  540.  
  541.     /* Create a symblic link in order to let Win32 recognize the device */
  542.  
  543.     KdPrint(("ScsiScannerSymbolicLink: Converting to UNICODE\n"));
  544.  
  545.     sprintf(LinkNameBuffer, "\\DosDevices\\Scanner%d", PortNumber);      /* SCSI Scanner driver number */
  546.  
  547.  
  548.     RtlInitString(&LinkNameString, LinkNameBuffer);
  549.  
  550.     status = RtlAnsiStringToUnicodeString(&LinkObject,                   /* Convert to UNICODE */
  551.                                           &LinkNameString,
  552.                                           TRUE);
  553.  
  554.     if (!NT_SUCCESS(status))
  555.     {
  556.        KdPrint(("ScsiScannerSymblicLink: Could not convert to UNICODE\n"));;
  557.     }
  558.  
  559.  
  560.     InitializeObjectAttributes(&LinkAttributes,
  561.                                &LinkObject,
  562.                                OBJ_CASE_INSENSITIVE,
  563.                                NULL,
  564.                                NULL);
  565.  
  566.     status = ZwCreateSymbolicLinkObject(&LinkHandle,
  567.                                         SYMBOLIC_LINK_ALL_ACCESS,
  568.                                         &LinkAttributes,
  569.                                         &ntUnicodeString);
  570.  
  571.  
  572.     KdPrint(("Symblic link created:\n", LinkNameBuffer));
  573.  
  574.     if (!NT_SUCCESS(status))
  575.     {
  576.  
  577.       KdPrint(("Symbolic link failed !!!\n"));
  578.  
  579.     }
  580.  
  581.     /* Release UniCode string */
  582.     RtlFreeUnicodeString(&LinkObject);
  583.  
  584.     return(STATUS_SUCCESS);   /* Exit  with status code */
  585.  
  586. CreateScannerDeviceObjectExit:
  587.  
  588.    KdPrint(("ErrorRecovery - CreateScannerDeviceObjectExit reached !!"));
  589.  
  590.    /* -------------- */
  591.    /* ERROR RECOVERY */
  592.    /* -------------- */
  593.  
  594.    ClassClaimDevice(PortDeviceObject,        /* Release the port device, since */
  595.                     LunInfo, TRUE, NULL);    /* an error has occured.          */
  596.  
  597.    if (senseData != NULL)            /* Sense data allocated? */
  598.       ExFreePool(senseData);            /* Yes - then free it    */
  599.  
  600.    if (deviceObject != NULL)            /* Device object created? */
  601.       IoDeleteDevice(deviceObject);        /* Yes - Delete it        */
  602.  
  603.    return status;                /* And exit! */
  604.  
  605. }     /* CreateScannerDeviceObject() */
  606.  
  607.  
  608. /***************************************************************************/
  609. /*** Syntax.........: ScsiScannerOpenClose                               ***/
  610. /***                                                                     ***/
  611. /*** Scope..........: Global                                             ***/
  612. /***                                                                     ***/
  613. /*** Description....: Handles the open/close access to the driver        ***/
  614. /***                                                                     ***/
  615. /*** Parameters.....: DeviceObject, Irp                                  ***/
  616. /***                                                                     ***/
  617. /*** Return value...: Always NTSTATUS                                    ***/
  618. /***                                                                     ***/
  619. /*** External ref...:                                                    ***/
  620. /***************************************************************************/
  621.  
  622. NTSTATUS ScsiScannerOpenClose (
  623.  
  624.  IN PDEVICE_OBJECT DeviceObject,    /* Device object for the scanner */
  625.  IN PIRP           Irp)            /* Open or Close request packet  */
  626. {     /* ScsiScannerOpenClose() */
  627.  
  628.       /* Set status in Irp. */
  629.     Irp->IoStatus.Status = STATUS_SUCCESS;
  630.  
  631.       /* Complete request at raised IRQ. */
  632.     IoCompleteRequest(Irp, IO_NO_INCREMENT);
  633.  
  634.     return STATUS_SUCCESS;
  635.  
  636. }     /* ScsiScannerOpenClose() */
  637.  
  638.  
  639. /***************************************************************************/
  640. /*** Syntax.........: ScsiScannerDeviceControl                           ***/
  641. /***                                                                     ***/
  642. /*** Scope..........: Global                                             ***/
  643. /***                                                                     ***/
  644. /*** Description....: This is the NT device control handler for scanner  ***/
  645. /***                  requests                                           ***/
  646. /***                                                                     ***/
  647. /*** Parameters.....: DeviceObject, Irp                                  ***/
  648. /***                                                                     ***/
  649. /*** Return value...: NTSTATUS                                           ***/
  650. /***                                                                     ***/
  651. /*** External ref...:                                                    ***/
  652. /***************************************************************************/
  653.  
  654.  
  655. NTSTATUS ScsiScannerDeviceControl (
  656.  
  657.  IN PDEVICE_OBJECT DeviceObject,    /* Device object for this scanner */
  658.  IN PIRP           Irp)            /* IO request packet              */
  659. {     /* ScsiScannerDeviceControl() */
  660.  
  661.    PIO_STACK_LOCATION    irpStack = IoGetCurrentIrpStackLocation(Irp);
  662.    PDEVICE_EXTENSION    deviceExtension = DeviceObject->DeviceExtension;
  663.    SCSI_REQUEST_BLOCK    srb;
  664.    NTSTATUS        status;
  665.  
  666.  
  667.    KdPrint(("ScsiScannerDeviceControl: Entering routine\n"));
  668.  
  669.      /* ------------------------------------------ */
  670.      /* Check the DeviceIoCoontrol control code    */
  671.      /* specified in the Win32 calling application */
  672.      /* ------------------------------------------ */
  673.  
  674.    switch (irpStack->Parameters.DeviceIoControl.IoControlCode)
  675.    {
  676.  
  677.       case 100:
  678.  
  679.         KdPrint(("SCSI Control: Get Scanner Status\n"));
  680.  
  681.         status = GetScannerStatus(DeviceObject, Irp);  /* TestUnitReady */
  682.         break;
  683.  
  684.  
  685.       default:
  686.          /* ------------------------------------------------------ */
  687.          /* Pass the request to the common device control routine. */
  688.          /* This routine can be found in the CLASS.C file          */
  689.          /* The ScsiClassDeviceControl also handles the IOCTL_SCSI */
  690.          /* _PASS_THROUGH ioctl                                    */
  691.          /* ------------------------------------------------------ */
  692.  
  693.          KdPrint(("Passing request to common device control"));
  694.  
  695.          return(ScsiClassDeviceControl(DeviceObject, Irp));
  696.    }
  697.  
  698.      /* Update IRP with completion status. */
  699.    Irp->IoStatus.Status = status;
  700.  
  701.      /* Complete the request. */
  702.    IoCompleteRequest(Irp, IO_DISK_INCREMENT);
  703.    KdPrint(("ScsiScannerDeviceControl: Status is %lx\n", status));
  704.    return status;
  705.  
  706. }     /* ScsiScannerDeviceControl() */
  707.  
  708.  /* EOF */
  709.