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

  1. /***************************************************************************/
  2. /*** File...........: DEV.C                                              ***/
  3. /***                                                                     ***/
  4. /*** Description....: Generic Win32 sample how to access SCSI class      ***/
  5. /***                  drivers using user-defined IOCTLs and the          ***/
  6. /***                  IOCTL_SCSI_PASS_THROUGH ioctl.                     ***/
  7. /***                                                                     ***/
  8. /*** Copyright......: DMC Denmark                                        ***/
  9. /*** Author.........: Thomas Nielsen (TN)                                ***/
  10. /*** Edition........: 4                                                  ***/
  11. /***                                                                     ***/
  12. /*** Created........: 31/03-1993                                         ***/
  13. /*** Last modified..: 03/04-1993                                         ***/
  14. /***                                                                     ***/
  15. /*** History........: 31/03 - Creation of file                           ***/
  16. /***                  01/04 - Adding Inquiry function                    ***/
  17. /***                  02/04 - Cleaning up & adding comments              ***/
  18. /***************************************************************************/
  19.  
  20. #include <windows.h>
  21. #include <memory.h>
  22.  
  23. #include <ntddscsi.h>
  24. #include <devioctl.h>
  25. #include <ntddscsi.h>
  26. #include <ntdddisk.h>
  27.  
  28. typedef struct
  29. {
  30.    SCSI_PASS_THROUGH    sptCmd;
  31.    UCHAR        ucSenseBuf[32];      /* Allocated sense data buffer */
  32.    UCHAR        ucDataBuf[2048];     /* Allocated data buffer */
  33. } PASS_THROUGH_STRUCT;
  34.  
  35.  
  36.  
  37. /*** Local prototypes ***/
  38.  
  39. static DWORD Inquiry(HANDLE hDev, UCHAR *DataBuffer);
  40. static DWORD TestUnitReady(HANDLE hDev);
  41. static DWORD SendScsi (HANDLE hDev,
  42.                        UCHAR *cdb,
  43.                        int cdbLength,
  44.                        BOOL TransferDirection,
  45.                        UCHAR *buffer,
  46.                        ULONG BufSize);
  47.  
  48.  
  49.  
  50. /***************************************************************************/
  51. /*** Syntax.........: TestUnitReady                                      ***/
  52. /***                                                                     ***/
  53. /*** Scope..........: Global                                             ***/
  54. /***                                                                     ***/
  55. /*** Description....: Returns the status of the scanner                  ***/
  56. /***                  (Simply sends a SCSI TestUnitReady cdb (0x00)      ***/
  57. /***                                                                     ***/
  58. /*** Parameters.....: hDev - Handle to device                            ***/
  59. /***                                                                     ***/
  60. /*** Return value...: SCSI status code (0,2,8)                           ***/
  61. /***                                                                     ***/
  62. /*** External ref...:                                                    ***/
  63. /***************************************************************************/
  64.  
  65. static DWORD TestUnitReady(HANDLE hDev)
  66. {
  67.    UCHAR  cdb[6];
  68.    memset(cdb, 0, sizeof(cdb));
  69.  
  70.    cdb[0] = 0x0;   /* SCSI opcode for TUR = 0x00 */
  71.  
  72.    /* Pass the request with no data buffer, and no data transfered during */
  73.    /* The DATA IN phase                                                   */
  74.    return SendScsi(hDev, cdb, 6, FALSE, NULL, 0);
  75. }
  76.  
  77.  
  78. /***************************************************************************/
  79. /*** Syntax.........: Inquiry                                            ***/
  80. /***                                                                     ***/
  81. /*** Scope..........: Global                                             ***/
  82. /***                                                                     ***/
  83. /*** Description....: Sends an inquriy (0x12) and reads in the           ***/
  84. /***                  retuned data during the DATA IN phase.             ***/
  85. /***                  The length of the inquiry data may differ from     ***/
  86. /***                  device to device.                                  ***/
  87. /***                                                                     ***/
  88. /*** Parameters.....: hDev - Handle to device                            ***/
  89. /***                  *DataBuffer - buffer to hold the data returned     ***/
  90. /***                                                                     ***/
  91. /*** Return value...: SCSI status code                                   ***/
  92. /***                                                                     ***/
  93. /*** External ref...:                                                    ***/
  94. /***************************************************************************/
  95.  
  96. static DWORD Inquiry(HANDLE hDev, UCHAR *DataBuffer)
  97. {
  98.    UCHAR  cdb[6];                /* Inquiry is a 6-bytes command */
  99.    memset(cdb, 0, sizeof(cdb));  /* Zero the SCSI cdb */
  100.  
  101.    cdb[0] = 0x12;      /* Inquiry SCSI op-code   */
  102.    cdb[4] = 0x24;      /* Length of inquiry data */
  103.  
  104.    /* Pass the request to the IOCTL_SCSI_PASS_THROUGH control */
  105.    return SendScsi(hDev, cdb, 6, TRUE, DataBuffer, 24);
  106. }
  107.  
  108.  
  109. /***************************************************************************/
  110. /*** Syntax.........: SendScsi                                           ***/
  111. /***                                                                     ***/
  112. /*** Scope..........: Global                                             ***/
  113. /***                                                                     ***/
  114. /*** Description....: Initializes the IOCTL_SCSI_PASS_THROGH structure,  ***/
  115. /***                  according to the TransferDirection flag and        ***/
  116. /***                  pass the request to the SCSI class driver via tha  ***/
  117. /***                  DeviceIoControl API call                           ***/
  118. /***                                                                     ***/
  119. /*** Parameters.....: hDev - Handle to device                            ***/
  120. /***                  cdb  - SCSI command block                          ***/
  121. /***                  cdbLength - Length of cdb                          ***/
  122. /***                  TransferDirection - Flag specifying data in/out    ***/
  123. /***                  buffer - Holds the data returned/send              ***/
  124. /***                  BufSize - size of databuffer                       ***/
  125. /***                                                                     ***/
  126. /*** Return value...: SCSI status code                                   ***/
  127. /***                                                                     ***/
  128. /*** External ref...:                                                    ***/
  129. /***************************************************************************/
  130.  
  131. static DWORD SendScsi (HANDLE hDev, UCHAR *cdb, int cdbLength, BOOL TransferDirection,
  132.                        UCHAR *buffer, ULONG BufSize)
  133. {
  134.    PASS_THROUGH_STRUCT spt;
  135.    DWORD               bRc,
  136.                        cbReturnedData;
  137.  
  138.    memset(&spt, 0, sizeof(spt));    /* Zero the structure */
  139.  
  140.    /* Fill out the structure */
  141.    spt.sptCmd.Length = sizeof(SCSI_PASS_THROUGH);
  142.    spt.sptCmd.ScsiStatus = 0;  /* We assume no error has occured (-:  */
  143.    spt.sptCmd.DataBufferOffset = spt.ucDataBuf - (UCHAR*)&spt;
  144.    spt.sptCmd.SenseInfoOffset  = spt.ucSenseBuf - (UCHAR*)&spt;
  145.    spt.sptCmd.SenseInfoLength  = sizeof(spt.ucSenseBuf);
  146.    spt.sptCmd.PathId = 0;        /* Obsolent - initialized by the class driver */
  147.    spt.sptCmd.TargetId = 0x03;   /* Also obsolent */
  148.    spt.sptCmd.Lun = 0;
  149.    spt.sptCmd.DataTransferLength = 2048;   /* I think..... */
  150.    spt.sptCmd.CdbLength = cdbLength;
  151.    spt.sptCmd.TimeOutValue = 10;
  152.    spt.sptCmd.DataIn = TransferDirection;
  153.  
  154.    memcpy(spt.sptCmd.Cdb, cdb, cdbLength);   /* Zero SCSI cdb */
  155.  
  156.    /* If we want to send data during the DATA OUT phase */
  157.    if (buffer != NULL && TransferDirection == FALSE)
  158.       memcpy(spt.ucDataBuf, buffer, BufSize);
  159.  
  160.  
  161.    /* Pass the request to the SCSI class driver using the IOCTL_SCSI */
  162.    /* _PASS_THROUGH structure. The syntax for DeviceIoControl can    */
  163.    /* be found in the Win32 help system.                             */
  164.  
  165.    bRc = DeviceIoControl(hDev,                 // device handle
  166.                IOCTL_SCSI_PASS_THROUGH,        // io control code
  167.                &spt,                           // input buffer
  168.                3048,                           // input buffer length
  169.                &spt,                           // output buffer
  170.                3048,                           // output buffer length
  171.                &cbReturnedData,                // # bytes returned
  172.                NULL);                          // synchronous call
  173.  
  174.  
  175.    /* Copy the data received during the DATA IN phase to the return buffer */
  176.    if (buffer != NULL && TransferDirection == TRUE)
  177.       memcpy(buffer, spt.ucDataBuf, sizeof(spt.ucDataBuf));
  178.  
  179.    return spt.sptCmd.ScsiStatus;               /* Return SCSI status code */
  180. }
  181.  
  182. int PASCAL WinMain (
  183.  
  184.  HINSTANCE hinstCurrent,
  185.  HINSTANCE hinstPrevious,
  186.  LPSTR     lpCmdLine,
  187.  int       nCmdShow)
  188. {     /* WinMain() */
  189.  
  190.    HANDLE hDev;
  191.    DWORD  stat;
  192.    UCHAR  ReturnData[2048];  /* Buffer for retuned data during DATA IN phase */
  193.  
  194.    /* Get a handle to the Scanner device. The first found device will */
  195.    /* be named "Scanner0", the next "Scanner1", etc. Do not use       */
  196.    /* overlapped IO control                                           */
  197.  
  198.    hDev = CreateFile("\\\\.\\Scanner0", GENERIC_READ | GENERIC_WRITE,
  199.                      FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
  200.                      OPEN_EXISTING, 0, NULL);
  201.  
  202.  
  203.    /* If we got a valid handle to the device - the proceed.... */
  204.    if (hDev != INVALID_HANDLE_VALUE)
  205.    {
  206.  
  207.       stat = TestUnitReady(hDev);
  208.       stat = Inquiry(hDev, ReturnData);
  209.  
  210.       CloseHandle(hDev);
  211.    }
  212.  
  213.    return 0;
  214. }     /* WinMain() */
  215.