aspilib.c
上传用户:xmgzy123
上传日期:2007-01-07
资源大小:373k
文件大小:43k
源码类别:

SCSI/ASPI

开发平台:

WINDOWS

  1. /*
  2.  * aspilib.c - Copyright (C) 1999 Jay A. Key
  3.  *
  4.  * Generic routines to access wnaspi32.dll
  5.  *
  6.  **********************************************************************
  7.  *
  8.  * This program is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU Lesser General Public License as published
  10.  * by the Free Software Foundation; either version 2 of the License, or
  11.  * (at your option) any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  * GNU General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Lesser General Public License
  19.  * along with this program; if not, write to the Free Software
  20.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  21.  *
  22.  **********************************************************************
  23.  *
  24.  * $Id: aspilib.c,v 1.2 2000/02/25 10:47:37 akey Exp $
  25.  * $Date: 2000/02/25 10:47:37 $
  26.  * $Locker:  $
  27.  * $Log: aspilib.c,v $
  28.  * Revision 1.2  2000/02/25 10:47:37  akey
  29.  * sync'ed with akrip32.dll v0.94
  30.  *
  31.  * Revision 1.7  2000/02/25 10:14:36  akey
  32.  * v0.94 release
  33.  *
  34.  * Revision 1.6  2000/02/14 09:56:25  akey
  35.  * cleaned up #ifdef _DEBUG code considerably
  36.  *
  37.  * Revision 1.5  2000/02/11 10:00:35  akey
  38.  * added access to cdplayer.ini
  39.  *
  40.  * Revision 1.4  2000/01/31 15:35:40  akey
  41.  * v0.93: added CDDBGetServerList and fixed problem with Win2000 scsi pass through code
  42.  *
  43.  * Revision 1.3  2000/01/12 10:07:41  akey
  44.  * Added minimal SCSI passthrough IOCTL support
  45.  *
  46.  * Revision 1.2  2000/01/03 12:29:43  akey
  47.  * v0.91 release -- added CDDB and bug fixes
  48.  *
  49.  *
  50.  */
  51. #define _AKRIP32_
  52. #include <windows.h>
  53. #include <stdio.h>
  54. #include "aspilib.h"
  55. #include "scsidefs.h"
  56. typedef union {
  57.   CDHANDLEREC cdHandles[MAXCDHAND];
  58.   HANDLE cdMutex[MAXCDHAND];
  59.   int nextHandle;
  60. } AKSHAREDMEM, FAR *LPAKSHAREDMEM;
  61. DWORD deinitREAD10( HCDROM hCD );
  62. DWORD initREAD10( HCDROM hCD );
  63. DWORD readCDParameters( HCDROM hCD, BOOL bChangeMask );
  64. DWORD setCDSpeed( HCDROM hCD, DWORD speed );
  65. DWORD pauseResumeCD( HCDROM hCD, BOOL bPause );
  66. DWORD startStopUnit( HCDROM hCD, BOOL bLoEj, BOOL bStart );
  67. int loadAspi( void );
  68. void unloadAspi( void );
  69. BOOL initMutexes( void );
  70. BOOL deinitMutexes( void );
  71. DWORD CDDBSum( DWORD n );
  72. int compBuf( BYTE *b1, BYTE *b2, int n );
  73. DWORD testReadCDAudio( HCDROM hCD, LPTRACKBUF t );
  74. DWORD dummyGetASPI32SupportInfo( void );
  75. DWORD dummySendASPI32Command( LPSRB lpsrb );
  76. BOOL dummyGetASPI32Buffer( PASPI32BUFF pbuf );
  77. BOOL dummyFreeASPI32Buffer( PASPI32BUFF pbuf );
  78. BOOL dummyTranslateASPI32Address( PDWORD p1, PDWORD p2 );
  79. DWORD dummyGetASPI32DLLVersion( void );
  80. int InitSCSIPT( void );
  81. int DeinitSCSIPT( void );
  82. DWORD SPTIGetASPI32SupportInfo( void );
  83. DWORD SPTISendASPI32Command( LPSRB lpsrb );
  84. /*
  85.  * static variables
  86.  */
  87. static char *copyrightInfo = "Released under the GNU Lesser General Public License (http://www.fsf.org/).";
  88. static char *aSCSIDevTypes[] = {
  89.     "Direct-access device",
  90.     "Sequential-access device",
  91.     "Printer device",
  92.     "Processor device",
  93.     "Write-once device",
  94.     "CD-ROM device",
  95.     "Scanner device",
  96.     "Optical memory device",
  97.     "Medium changer device",
  98.     "Communication device",
  99.     "ASC IT8 device",
  100.     "ASC IT8 device"
  101. };
  102. #define MAXCDTYPE   8
  103. static CDREADFN aReadFn[] = {
  104.   NULL, readCDAudioLBA_ATAPI, readCDAudioLBA_ATAPI, readCDAudioLBA_READ10,
  105.   readCDAudioLBA_READ10, readCDAudioLBA_D8, readCDAudioLBA_D4,
  106.   readCDAudioLBA_D4, readCDAudioLBA_READ10
  107. };
  108. static HINSTANCE hinstWNASPI32 = NULL;
  109. int alErrCode = 0;
  110. BYTE alAspiErr = 0;
  111. static LPAKSHAREDMEM pcdShared;
  112. CDHANDLEREC *cdHandles;
  113. HANDLE *cdMutexes;
  114. int *nextHandle = NULL;
  115. CRITICAL_SECTION getHandle;
  116. HANDLE hCacheMutex = NULL;
  117. CRITICAL_SECTION csCache;
  118. //CRITICAL_SECTION useDbbuf;
  119. //char dbbuf[512];
  120. #define MAJVER   0
  121. #define MINVER   94
  122. DWORD (*pfnGetASPI32SupportInfo)(void);
  123. DWORD (*pfnSendASPI32Command)(LPSRB);
  124. BOOL  (*pfnGetASPI32Buffer)(PASPI32BUFF);
  125. BOOL  (*pfnFreeASPI32Buffer)(PASPI32BUFF);
  126. BOOL  (*pfnTranslateASPI32Address)(PDWORD,PDWORD);
  127. DWORD (*pfnGetASPI32DLLVersion)(void);
  128. BOOL  aspiLoaded = FALSE;
  129. /*
  130.  * local prototypes
  131.  */
  132. static char *devType( int i );
  133. /***************************************************************************
  134.  * DllMain
  135.  ***************************************************************************/
  136. BOOL WINAPI DllMain( HANDLE hModule, DWORD dwReason, LPVOID lpReserved )
  137. {
  138.   BOOL fInit;
  139.   static HANDLE hMapObject = NULL;
  140.   HANDLE hInitMutex = NULL;
  141.   BOOL retVal = FALSE;
  142.   hModule = hModule;
  143.   lpReserved = lpReserved;
  144.   hInitMutex = CreateMutex( NULL, FALSE, "AKRipDllMainMutex" );
  145.   if ( !hInitMutex )
  146.     {
  147.       dwReason = 0xFFFFFFFF;  // do not execute any attach/detach code
  148.     }
  149.   else if ( WaitForSingleObject( hInitMutex, 15 * 1000 ) != WAIT_OBJECT_0 )
  150.     {
  151.       CloseHandle( hInitMutex );
  152.       dwReason = 0xFFFFFFFF;    // do not execute any attach/detach code
  153.     }
  154.   switch( dwReason )
  155.     {
  156.     case DLL_PROCESS_ATTACH:
  157.       //InitializeCriticalSection( &useDbbuf );
  158.       InitializeCriticalSection( &getHandle );
  159. #ifdef _DBLIBMAIN
  160.       dbprintf( "akrip32: DLL_PROCESS_ATTACH (hModule=%04X)", hModule );
  161. #endif
  162.       loadAspi();
  163.       hMapObject = CreateFileMapping( (HANDLE)0xFFFFFFFF, NULL,
  164.       PAGE_READWRITE, 0, sizeof(AKSHAREDMEM),
  165.       "akrip32memmap" );
  166.       if ( hMapObject == NULL )
  167. break;
  168.       fInit = ( GetLastError() != ERROR_ALREADY_EXISTS );
  169.       pcdShared = MapViewOfFile( hMapObject, FILE_MAP_WRITE, 0, 0, 0 );
  170.       if ( !pcdShared )
  171. break;
  172.       if ( fInit )
  173. memset( pcdShared, 0, sizeof(AKSHAREDMEM) );
  174.       cdHandles = pcdShared->cdHandles;
  175.       cdMutexes = pcdShared->cdMutex;
  176.       nextHandle = &(pcdShared->nextHandle);
  177.       initMutexes( );
  178.       retVal = TRUE;
  179.       break;
  180.     case DLL_THREAD_ATTACH:
  181. #ifdef _DBLIBMAIN
  182.       dbprintf( "akrip32: DLL_THREAD_ATTACH (hModule=%04X)", hModule );
  183. #endif
  184.       retVal = TRUE;
  185.       break;
  186.     case DLL_THREAD_DETACH:
  187. #ifdef _DBLIBMAIN
  188.       dbprintf( "akrip32: DLL_THREAD_DETACH (hModule=%04X)", hModule );
  189. #endif
  190.       retVal = TRUE;
  191.       break;
  192.     case DLL_PROCESS_DETACH:
  193. #ifdef _DBLIBMAIN
  194.       OutputDebugString( "akrip32: DLL_PROCESS_DETACH" );
  195. #endif
  196.       deinitMutexes();
  197.       UnmapViewOfFile( pcdShared );
  198.       CloseHandle( hMapObject );
  199.       unloadAspi();
  200.       retVal = TRUE;
  201.       break;
  202.     }
  203.   if ( hInitMutex )
  204.     {
  205.       ReleaseMutex( hInitMutex );
  206.       CloseHandle( hInitMutex );
  207.     }
  208.   return retVal;
  209. }
  210. BOOL initMutexes( void )
  211. {
  212.   int i;
  213.   char tmp[32];
  214.   for( i = 0; i < MAXCDHAND; i++ )
  215.     {
  216.       wsprintf( tmp, "akrip32_cdMtx%02d", i );
  217.       cdMutexes[i] = CreateMutex( NULL, FALSE, tmp );
  218.       if ( !cdMutexes[i] )
  219. return FALSE;
  220.     }
  221.   hCacheMutex = CreateMutex( NULL, FALSE, "AKRipCacheMutex" );
  222.   InitializeCriticalSection( &csCache );
  223.   return TRUE;
  224. }
  225. BOOL deinitMutexes( void )
  226. {
  227.   int i;
  228.   for( i = 0; i < MAXCDHAND; i++ )
  229.     {
  230.       if ( cdMutexes[i] )
  231. CloseHandle( cdMutexes[i] );
  232.     }
  233.   if ( hCacheMutex )
  234.     CloseHandle( hCacheMutex );
  235.   DeleteCriticalSection( &csCache );
  236.   return TRUE;
  237. }
  238. static char *devType( int i )
  239.   if ( i >= 0x20 )
  240.     return "";
  241.   if ( i == 0x1F )
  242.     return "Unknown or no device";
  243.   if ( i >= 0x0C )
  244.     return "";
  245.   return aSCSIDevTypes[i];
  246. }
  247. /*
  248.  * Assumes that loadAspi has already been called
  249.  */
  250. int  getSCSIDevType( BYTE bHostAdapter, BYTE bTarget, BYTE bLUN,
  251.      LPBYTE pDevType, LPSTR lpDevTypeStr, int iDevTypeLen )
  252. {
  253.   SRB_GDEVBlock s;
  254.   DWORD dwStatus;
  255.   memset( &s, 0, sizeof(SRB_GDEVBlock) );
  256.   s.SRB_Cmd = SC_GET_DEV_TYPE;
  257.   s.SRB_HaID = bHostAdapter;
  258.   s.SRB_Target = bTarget;
  259.   s.SRB_Lun = bLUN;
  260.   //DebugBreak();
  261.   dwStatus = pfnSendASPI32Command( (LPSRB)&s );
  262.   switch( dwStatus )
  263.     {
  264.     case SS_COMP:
  265. #ifdef _DEBUG
  266.       dbprintf( "akrip32: getSCSIDevType() -> SS_COMP: %04X",
  267. s.SRB_DeviceType );
  268.       dbprintf( "akrip32: getSCSIDevType(): pDevType == 0x%08X", pDevType );
  269. #endif
  270.       if ( pDevType )
  271. *pDevType = s.SRB_DeviceType;
  272.       if ( lpDevTypeStr )
  273. strncpy( lpDevTypeStr, devType( s.SRB_DeviceType ), iDevTypeLen );
  274.       break;
  275.     case SS_NO_DEVICE:
  276. #ifdef _DEBUG
  277.       dbprintf( "akrip32: getSCSIDevType() -> SS_NO_DEVICE" );
  278. #endif
  279.       if ( pDevType )
  280. *pDevType = 0x1F;
  281.       if ( lpDevTypeStr )
  282. strncpy( lpDevTypeStr, "SS_NO_DEVICE", iDevTypeLen );
  283.       return FALSE;
  284.     default:
  285. #ifdef _DEBUG
  286.       dbprintf( "akrip32: getSCSIDevType(): unexpected return from ASPI (%04X)", dwStatus );
  287. #endif
  288.       if ( pDevType )
  289. *pDevType = 0x1F;
  290.       if ( lpDevTypeStr )
  291. strncpy( lpDevTypeStr, "Unknown return", iDevTypeLen );
  292.       return FALSE;
  293.     }
  294.   return TRUE;
  295. }
  296. DWORD dummyGetASPI32SupportInfo( void )
  297. {
  298.   return SS_NO_ASPI;
  299. }
  300. DWORD dummySendASPI32Command( LPSRB lpsrb )
  301. {
  302.   lpsrb->SRB_Status = SS_NO_ASPI;
  303.   return SS_NO_ASPI;
  304. }
  305. BOOL dummyGetASPI32Buffer( PASPI32BUFF pbuf )
  306. {
  307.   return FALSE;
  308. }
  309. BOOL dummyFreeASPI32Buffer( PASPI32BUFF pbuf )
  310. {
  311.   return FALSE;
  312. }
  313. BOOL dummyTranslateASPI32Address( PDWORD p1, PDWORD p2 )
  314. {
  315.   return FALSE;
  316. }
  317. DWORD dummyGetASPI32DLLVersion( void )
  318. {
  319.   return 0;
  320. }
  321. /***************************************************************************
  322.  * int loadAspi( void )
  323.  ***************************************************************************/
  324. int loadAspi( void )
  325. {
  326.   DWORD dwErr;
  327.   hinstWNASPI32 = LoadLibrary( "WNASPI32.DLL" );
  328.   if ( hinstWNASPI32 )
  329.     {
  330.       pfnGetASPI32SupportInfo =
  331. (DWORD(*)(void))GetProcAddress( hinstWNASPI32, "GetASPI32SupportInfo" );
  332.       pfnSendASPI32Command =
  333. (DWORD(*)(LPSRB))GetProcAddress( hinstWNASPI32, "SendASPI32Command" );
  334.       pfnGetASPI32Buffer =
  335. (BOOL(*)(PASPI32BUFF))GetProcAddress( hinstWNASPI32, "GetASPI32Buffer" );
  336.       pfnFreeASPI32Buffer =
  337. (BOOL(*)(PASPI32BUFF))GetProcAddress( hinstWNASPI32, "FreeASPI32Buffer" );
  338.       pfnTranslateASPI32Address =
  339. (BOOL(*)(PDWORD,PDWORD))GetProcAddress( hinstWNASPI32, "TranslateASPI32Address" );
  340.       pfnGetASPI32DLLVersion =
  341. (DWORD(*)(void))GetProcAddress( hinstWNASPI32, "GetASPI32DLLVersion" );
  342.       if ( !pfnGetASPI32SupportInfo || !pfnSendASPI32Command )
  343. {
  344.   if ( !pfnGetASPI32SupportInfo )
  345.     alErrCode = ALERR_NOGETASPI32SUPP;
  346.   else
  347.     alErrCode = ALERR_NOSENDASPICMD;
  348. #ifdef _DEBUG
  349.   dbprintf( "akrip32: GetASPI32SupportInfo == 0x%08X", 
  350.    pfnGetASPI32SupportInfo );
  351.   dbprintf( "akrip32: SendASPI32Command == 0x%08X", pfnSendASPI32Command );
  352. #endif
  353.   return 0;
  354. }
  355.     }
  356.   else if ( InitSCSIPT() )
  357.     {
  358.       pfnGetASPI32SupportInfo = SPTIGetASPI32SupportInfo;
  359.       pfnSendASPI32Command    = SPTISendASPI32Command;
  360.     }
  361.   else
  362.     {
  363.       dwErr = GetLastError();
  364.       alErrCode = ALERR_NOWNASPI;
  365.       pfnGetASPI32SupportInfo = dummyGetASPI32SupportInfo;
  366.       pfnSendASPI32Command = dummySendASPI32Command;
  367.       pfnGetASPI32Buffer = dummyGetASPI32Buffer;
  368.       pfnFreeASPI32Buffer = dummyFreeASPI32Buffer;
  369.       pfnTranslateASPI32Address = dummyTranslateASPI32Address;
  370.       pfnGetASPI32DLLVersion = dummyGetASPI32DLLVersion;
  371. #ifdef _DEBUG
  372.       dwErr = GetLastError();
  373.       dbprintf( "Unable to load WNASPI32.DLL" );
  374.       dbprintf( "akrip32: GetLastError() -> %d (%04X)", dwErr, dwErr );
  375. #endif
  376.       return 0;
  377.     }
  378.    aspiLoaded = TRUE;
  379.    return 1;
  380. }
  381. void unloadAspi( void )
  382. {
  383.   DeinitSCSIPT();
  384.   if ( hinstWNASPI32 )
  385.     {
  386.       aspiLoaded = FALSE;
  387.       pfnGetASPI32SupportInfo = NULL;
  388.       pfnSendASPI32Command = NULL;
  389.       pfnGetASPI32Buffer = NULL;
  390.       pfnFreeASPI32Buffer = NULL;
  391.       pfnTranslateASPI32Address = NULL;
  392.       pfnGetASPI32DLLVersion = NULL;
  393.       FreeLibrary( hinstWNASPI32 );
  394.       hinstWNASPI32 = NULL;
  395.     }
  396. }
  397. /***************************************************************************
  398.  * GetNumAdapters
  399.  ***************************************************************************/
  400. int GetNumAdapters( void )
  401. {
  402.   DWORD d;
  403.   BYTE bHACount;
  404.   BYTE bASPIStatus;
  405.   d = pfnGetASPI32SupportInfo();
  406.   bASPIStatus = HIBYTE(LOWORD(d));
  407.   bHACount    = LOBYTE(LOWORD(d));
  408.   if ( bASPIStatus != SS_COMP && bASPIStatus != SS_NO_ADAPTERS )
  409.     {
  410.       alErrCode = ALERR_ASPI;
  411.       alAspiErr = bASPIStatus;
  412. #ifdef _DEBUG
  413.       dbprintf( "akrip32: GetNumAdapters: bASPIStatus == 0x%02X", bASPIStatus );
  414. #endif
  415.       return -1;
  416.     }
  417.   return (int)bHACount;
  418. }
  419. /***************************************************************************
  420.  * GetDriveInfo
  421.  ***************************************************************************/
  422. DWORD GetDriveInfo( BYTE ha, BYTE tgt, BYTE lun, LPCDREC cdrec )
  423. {
  424.   DWORD dwStatus;
  425.   HANDLE heventSRB;
  426.   SRB_ExecSCSICmd s;
  427.   BYTE buf[100];
  428.   char outBuf[101];
  429.   CDREC cdrecTmp;
  430.   heventSRB = CreateEvent( NULL, TRUE, FALSE, NULL );
  431.   if ( cdrec )
  432.     cdrecTmp = *cdrec;
  433.   memset( &cdrecTmp.info, 0, sizeof(CDINFO) );
  434.   memset( &s, 0, sizeof( s ) );
  435.   memset( buf, 0, 100 );
  436.   s.SRB_Cmd        = SC_EXEC_SCSI_CMD;
  437.   s.SRB_HaID       = ha;
  438.   s.SRB_Target     = tgt;
  439.   s.SRB_Lun        = lun;
  440.   s.SRB_Flags      = SRB_DIR_IN | SRB_EVENT_NOTIFY;
  441.   s.SRB_BufLen     = 100;
  442.   s.SRB_BufPointer = buf;
  443.   s.SRB_SenseLen   = SENSE_LEN;
  444.   s.SRB_CDBLen     = 6;
  445.   s.SRB_PostProc   = (LPVOID)heventSRB;
  446.   s.CDBByte[0]     = SCSI_INQUIRY;
  447.   s.CDBByte[4]     = 100;
  448.   ResetEvent( heventSRB );
  449.   dwStatus = pfnSendASPI32Command( (LPSRB)&s );
  450.   if ( dwStatus == SS_PENDING )
  451.     {
  452.       WaitForSingleObject( heventSRB, DEFWAITLEN );
  453.     }
  454.   CloseHandle( heventSRB );
  455.   if ( s.SRB_Status != SS_COMP )
  456.     {
  457.       alErrCode = ALERR_ASPI;
  458.       alAspiErr = s.SRB_Status;
  459. #ifdef _DEBUG
  460.       dbprintf( "akrip32: GetDriveInfo: Error status: 0x%04Xn", s.SRB_Status );
  461. #endif
  462.       return SS_ERR;
  463.     }
  464. #ifdef _DEBUG
  465.   {
  466.     FILE *fp = fopen( "inquiry.dat", "wb" );
  467.     fwrite( buf, 1, 100, fp );
  468.     fclose( fp );
  469.   }
  470. #endif
  471.   memcpy( cdrecTmp.info.vendor, &buf[8], 8 );
  472.   memcpy( cdrecTmp.info.prodId, &buf[16], 16 );
  473.   memcpy( cdrecTmp.info.rev, &buf[32], 4 );
  474.   memcpy( cdrecTmp.info.vendSpec, &buf[36], 20 );
  475.   wsprintf( outBuf, "%s, %s v%s (%d:%d:%d)", 
  476.     cdrecTmp.info.vendor, cdrecTmp.info.prodId, cdrecTmp.info.rev,
  477.     ha, tgt, lun );
  478. #ifdef _DEBUG
  479.   dbprintf( "akrip32: GetDriveInfo: %s", outBuf );
  480. #endif
  481.   strncpy( cdrecTmp.id, outBuf, MAXIDLEN );
  482.   cdrecTmp.id[MAXIDLEN] = 0;
  483.   if ( cdrec )
  484.     *cdrec = cdrecTmp;
  485.   return SS_COMP;
  486. }
  487. /***************************************************************************
  488.  * Function Name    ReadTOC
  489.  *
  490.  * 
  491.  ***************************************************************************/
  492. DWORD ReadTOC( HCDROM hCD, LPTOC toc )
  493. {
  494.   DWORD dwStatus;
  495.   DWORD retVal = SS_COMP;
  496.   HANDLE heventSRB;
  497.   SRB_ExecSCSICmd s;
  498.   int idx = (int)hCD - 1;
  499.   if ( (idx<0) || (idx>=MAXCDHAND) )
  500.     {
  501.       alErrCode = ALERR_INVHANDLE;
  502.       return SS_ERR;
  503.     }
  504.   if ( WaitForSingleObject( cdMutexes[idx], TIMEOUT ) != WAIT_OBJECT_0 )
  505.     {
  506.       alErrCode = ALERR_LOCK;
  507.       return SS_ERR;
  508.     }
  509.   if ( !cdHandles[idx].used )
  510.     {
  511.       alErrCode = ALERR_INVHANDLE;
  512.       ReleaseMutex( cdMutexes[idx] );
  513.       return SS_ERR;
  514.     }
  515.   heventSRB = CreateEvent( NULL, TRUE, FALSE, NULL );
  516.   memset( &s, 0, sizeof( s ) );
  517.   s.SRB_Cmd        = SC_EXEC_SCSI_CMD;
  518.   s.SRB_HaID       = cdHandles[idx].ha;
  519.   s.SRB_Target     = cdHandles[idx].tgt;
  520.   s.SRB_Lun        = cdHandles[idx].lun;
  521.   s.SRB_Flags      = SRB_DIR_IN | SRB_EVENT_NOTIFY;
  522.   s.SRB_BufLen     = 0x324;
  523.   s.SRB_BufPointer = (BYTE FAR *)toc;
  524.   s.SRB_SenseLen   = 0x0E;
  525.   s.SRB_CDBLen     = 0x0A;
  526.   s.SRB_PostProc   = (LPVOID)heventSRB;
  527.   s.CDBByte[0]     = 0x43;
  528.   s.CDBByte[1]     = cdHandles[idx].bMSF?0x02:0x00;
  529.   //  s.CDBByte[1] = 0x02;               /* 0x02 == MSF format, 0x00 == LBA */
  530.   s.CDBByte[7]     = 0x03;               /* length of buffer to hold TOC    */
  531.   s.CDBByte[8]     = 0x24;               /*      == 0x324                   */
  532.   ResetEvent( heventSRB );
  533.   dwStatus = pfnSendASPI32Command( (LPSRB)&s );
  534.   if ( dwStatus == SS_PENDING )
  535.     {
  536.       WaitForSingleObject( heventSRB, 4000 );
  537.     }
  538.   CloseHandle( heventSRB );
  539.   if ( s.SRB_Status != SS_COMP )
  540.     {
  541.       alErrCode = ALERR_ASPI;
  542.       alAspiErr = s.SRB_Status;
  543.       retVal = SS_ERR;
  544.     }
  545. #ifdef _DEBUG
  546.   {
  547.     FILE *fp = fopen( "toc.dat", "wb" );
  548.     fwrite( toc, 1, sizeof(TOC), fp );
  549.     fclose( fp );
  550.   }
  551. #endif
  552.   ReleaseMutex( cdMutexes[idx] );
  553.   return retVal;
  554. }
  555. /***************************************************************************
  556.  * resetSCSIBus
  557.  * 
  558.  * According to Adaptec, this command can cause problems in Win95
  559.  *
  560.  ***************************************************************************/
  561. void resetSCSIBus( void )
  562. {
  563.   DWORD dwStatus;
  564.   HANDLE heventSRB;
  565.   SRB_BusDeviceReset s;
  566.   dbprintf( "akrip32: reset bus!" );
  567.   heventSRB = CreateEvent( NULL, TRUE, FALSE, NULL );
  568.   memset( &s, 0, sizeof( s ) );
  569.   s.SRB_Cmd = SC_RESET_DEV;
  570.   s.SRB_PostProc = (LPVOID)heventSRB;
  571.   ResetEvent( heventSRB );
  572.   dwStatus = pfnSendASPI32Command( (LPSRB)&s );
  573.   if ( dwStatus == SS_PENDING )
  574.     {
  575.       WaitForSingleObject( heventSRB, DEFWAITLEN );
  576.     }
  577.   CloseHandle( heventSRB );
  578. #ifdef _DEBUG
  579.   if ( s.SRB_Status != SS_COMP )
  580.     {
  581.       dbprintf( "akrip32: RESET BUS aspi status: 0x%08Xn", s.SRB_Status );
  582.     }
  583. #endif
  584. }
  585. /******************************************************************
  586.  * GetCDList
  587.  *
  588.  * Scans all host adapters for CD-ROM units, and stores information
  589.  * for all units located
  590.  ******************************************************************/
  591. int GetCDList( LPCDLIST cd )
  592. {
  593.   SRB_HAInquiry sh;
  594.   SRB_GDEVBlock sd;
  595.   int numAdapters, i, j, k;
  596.   int maxTgt;
  597.   /* initialize cd list */
  598.   maxTgt = cd->max;
  599.   memset( cd, 0, sizeof(*cd) );
  600.   cd->max = maxTgt;
  601.   numAdapters = GetNumAdapters();
  602. #ifdef _DEBUG
  603.   dbprintf( "AKRip32: GetCDList(): numAdapters == %d", numAdapters );
  604. #endif
  605.   //return 0;
  606.   for( i = 0; i < numAdapters; i++ )
  607.     {
  608.       memset( &sh, 0, sizeof( sh ) );
  609.       sh.SRB_Cmd   = SC_HA_INQUIRY;
  610.       sh.SRB_HaID  = i;
  611.       pfnSendASPI32Command( (LPSRB)&sh );
  612.       /* on error skip to next adapter */
  613.       if ( sh.SRB_Status != SS_COMP )
  614. continue;
  615.       maxTgt = (int)sh.HA_Unique[3];
  616.       if ( maxTgt == 0 )
  617. maxTgt = 8;
  618.       for( j = 0; j < maxTgt; j++ )
  619. {
  620.   for( k = 0; k < 8; k++ )
  621.     {
  622.       memset( &sd, 0, sizeof( sd ) );
  623.       sd.SRB_Cmd   = SC_GET_DEV_TYPE;
  624.       sd.SRB_HaID  = i;
  625.       sd.SRB_Target = j;
  626.       sd.SRB_Lun   = k;
  627.       pfnSendASPI32Command( (LPSRB)&sd );
  628.       if ( sd.SRB_Status == SS_COMP )
  629. {
  630.   if ( sd.SRB_DeviceType == DTYPE_CDROM )
  631.     {
  632.       cd->cd[cd->num].ha = i;
  633.       cd->cd[cd->num].tgt = j;
  634.       cd->cd[cd->num].lun = k;
  635.       memset( cd->cd[cd->num].id, 0, MAXIDLEN+1 );
  636.       GetDriveInfo( i, j, k, &(cd->cd[cd->num]) );
  637.       // getDriveInfo( i, j, k, cd->cd[cd->num].id, MAXIDLEN+1 );
  638.       cd->num++;
  639.     }
  640. #ifdef _DEBUG
  641.   else
  642.     {
  643.       dbprintf( "       : sd.SRB_DeviceType == %d", sd.SRB_DeviceType );
  644.       GetDriveInfo( i, j, k, NULL );
  645.     }
  646. #endif
  647. }
  648.     }
  649. }
  650.     }
  651.   return 1;
  652. }
  653. DWORD ReadCDAudioLBA( HCDROM hCD, LPTRACKBUF t )
  654. {
  655.   int idx = (int)hCD - 1;
  656.   DWORD retVal;
  657.   if ( (idx<0) || (idx>=MAXCDHAND) )
  658.     {
  659.       alErrCode = ALERR_INVHANDLE;
  660.       return SS_ERR;
  661.     }
  662.   retVal = WaitForSingleObject( cdMutexes[idx], TIMEOUT );
  663.   if ( retVal != WAIT_OBJECT_0 )
  664.     {
  665.       alErrCode = ALERR_LOCK;
  666.       return SS_ERR;
  667.     }
  668.   if ( !cdHandles[idx].used )
  669.     {
  670.       alErrCode = ALERR_INVHANDLE;
  671.       ReleaseMutex( cdMutexes[idx] );
  672.       return SS_ERR;
  673.     }
  674.   retVal = cdHandles[idx].pfnRead( hCD, t );
  675.   ReleaseMutex( cdMutexes[idx] );
  676.   return retVal;
  677. }
  678. /*
  679.  * Test the currently set read function.  Fills the buffer with 0xAA
  680.  * prior to reading, and then checks the read area for a series of 0xAA
  681.  * bytes.  This is because some read commands do not return an error, but
  682.  * also don't read correct data or a full buffer.
  683.  */
  684. DWORD testReadCDAudio( HCDROM hCD, LPTRACKBUF t )
  685. {
  686.   DWORD i;
  687.   DWORD dwStatus;
  688.   BYTE *p;
  689.   int idx = (int)hCD - 1;
  690.   int count;
  691.   // fill buffer with dummy data
  692.   memset( t->buf, 0xAA, t->len );
  693.   dwStatus = cdHandles[idx].pfnRead( hCD, t );
  694.   if ( dwStatus != SS_COMP )
  695.     {
  696.       return dwStatus;
  697.     }
  698.   p = &(t->buf[t->startOffset]);
  699.   for( i = 0, count = 0; i < t->len; i += 4 )
  700.     {
  701.       if ( *((DWORD *)p) == 0xAAAAAAAA )
  702. count += 1;
  703.       else
  704. count = 0;
  705.       if ( count == 8 )
  706. {
  707.   return SS_ERR;
  708. }
  709.       p += 4;
  710.     }
  711.   return dwStatus;
  712. }
  713. /***************************************************************************
  714.  * readCDAudioLBA_ANY
  715.  *
  716.  * Attempts to autodetect the proper read function for the CD.  It tries
  717.  * ATAPI2, ATAPI1, and then finally READ10
  718.  *
  719.  ***************************************************************************/
  720. DWORD readCDAudioLBA_ANY( HCDROM hCD, LPTRACKBUF t )
  721. {
  722.   DWORD dwStatus;
  723.   int idx = (int)hCD - 1;
  724.   int i, j;
  725.   int ord[7] = { 2, 1, 8, 4, 5, 6, 7 };
  726.   if ( (idx<0) || (idx>=MAXCDHAND) || !cdHandles[idx].used )
  727.     {
  728.       alErrCode = ALERR_INVHANDLE;
  729.       return SS_ERR;
  730.     }
  731.   if ( t->numFrames * 2352 > t->maxLen )
  732.     {
  733.       alErrCode = ALERR_BUFTOOSMALL;
  734.       return SS_ERR;
  735.     }
  736.   for( i = 0; i < 7; i++ )
  737.     {
  738. #ifdef _DEBUG
  739.       dbprintf( "akrip32: testing read fn %d", ord[i] );
  740. #endif
  741.       cdHandles[idx].readType = ord[i];
  742.       cdHandles[idx].pfnRead = aReadFn[ord[i]];
  743.       cdHandles[idx].pfnDeinit = NULL;
  744.       cdHandles[idx].bInit = FALSE;
  745.       for( j = 0; j < 3; j++ )
  746. {
  747.   dwStatus = testReadCDAudio( hCD, t );
  748.   if ( dwStatus == SS_COMP )
  749.     {
  750.       return dwStatus;
  751.     }
  752. }
  753.     }
  754.   // Failed to find compatible read mode, so we reset to the default
  755.   // and return the error
  756.   cdHandles[idx].readType = CDR_ANY;
  757.   cdHandles[idx].pfnRead  = readCDAudioLBA_ANY;
  758.   return dwStatus;
  759. }
  760. DWORD GetASPI32SupportInfo( void )
  761. {
  762.   return pfnGetASPI32SupportInfo();
  763. }
  764. DWORD SendASPI32Command( LPSRB s )
  765. {
  766.   return pfnSendASPI32Command( s );
  767. }
  768. #define _GEN_CDPARMS 0
  769. DWORD readCDParameters( HCDROM hCD, BOOL bChangeMask )
  770. {
  771.   HANDLE h;
  772.   SRB_ExecSCSICmd s;
  773.   DWORD d;
  774.   BYTE b[256];
  775.   int lenData;
  776.   BYTE *p;
  777.   BYTE *pMax = b + 256;
  778.   LPSENSEMASK psm;
  779.   int idx = (int)hCD - 1;
  780. #if _GEN_CDPARMS
  781.   FILE *fp;
  782. #endif
  783.   if ( (idx<0) || (idx>=MAXCDHAND) || !cdHandles[idx].used )
  784.     {
  785.       alErrCode = ALERR_INVHANDLE;
  786.       return SS_ERR;
  787.     }
  788.   cdHandles[idx].smRead = FALSE;
  789.   psm = &cdHandles[idx].sm;
  790.   memset( psm, 0, sizeof( SENSEMASK ) );
  791.   h = CreateEvent( NULL, TRUE, FALSE, NULL );
  792.   memset( &s, 0, sizeof( s ) );
  793.   memset( b, 0xFF, 256 );
  794.   s.SRB_Cmd      = SC_EXEC_SCSI_CMD;
  795.   s.SRB_HaID     = cdHandles[idx].ha;
  796.   s.SRB_Target   = cdHandles[idx].tgt;
  797.   s.SRB_Lun      = cdHandles[idx].lun;
  798.   s.SRB_Flags    = SRB_DIR_IN | SRB_EVENT_NOTIFY;
  799.   s.SRB_BufLen   = 256;
  800.   s.SRB_BufPointer = b;
  801.   s.SRB_CDBLen   = 12;
  802.   s.SRB_PostProc = (LPVOID)h;
  803.   s.CDBByte[0]   = 0x5A;
  804.   s.CDBByte[2]   = 0x3F;
  805.   s.CDBByte[7]   = 0x01;
  806.   s.CDBByte[8]   = 0x00;
  807.   /* do we want just a mask of changable items? */
  808.   if ( bChangeMask )
  809.     s.CDBByte[2] |= 0x40;
  810.   ResetEvent( h );
  811.   d = pfnSendASPI32Command( (LPSRB)&s );
  812.   if ( d == SS_PENDING )
  813.     {
  814.       WaitForSingleObject( h, 500 );
  815.     }
  816.   CloseHandle( h );
  817.   if ( s.SRB_Status != SS_COMP )
  818.     {
  819.       alErrCode = ALERR_ASPI;
  820.       alAspiErr = s.SRB_Status;
  821.       ReleaseMutex( cdMutexes[idx] );
  822.       return SS_ERR;
  823.     }
  824. #if _GEN_CDPARMS
  825.   fp = fopen( "cdparms.dat", "wb" );
  826.   if ( fp )
  827.     {
  828.       fwrite( b, 1, 256, fp );
  829.       fclose( fp );
  830.     }
  831. #endif
  832.   lenData = ((unsigned int)b[0] << 8) + b[1];
  833.   /* set to first sense mask, and then walk through the masks */
  834.   p = b + 8;
  835.   while( (p < &(b[2+lenData])) && (p < pMax) )
  836.     {
  837.       BYTE which;
  838.       which = p[0] & 0x3F;
  839.       switch( which )
  840. {
  841. case READERRREC:
  842.   psm->rerAvail = TRUE;
  843.   memcpy( psm->rer, p, p[1]+2 );
  844.   break;
  845. case CDRPARMS:
  846.   psm->cpmAvail = TRUE;
  847.   memcpy( psm->cpm, p, p[1]+2 );
  848.   break;
  849. case CDRAUDIOCTL:
  850.   psm->cacmAvail = TRUE;
  851.   memcpy( psm->cacm, p, p[1]+2 );
  852.   break;
  853. case CDRCAPS:
  854.   psm->ccsmAvail = TRUE;
  855.   memcpy( psm->ccsm, p, p[1]+2 );
  856.   break;
  857. }
  858.       p += (p[1] + 2);
  859.     }
  860.   cdHandles[idx].smRead = TRUE;
  861.   return s.SRB_Status;
  862. }
  863. /****************************************************************
  864.  * Generic function to query CD unit capabilities and parameters
  865.  *
  866.  * which:   specifies the parm we wish to query
  867.  * pNum:    pointer to DWORD to return data
  868.  *
  869.  * returns: If the parm is not available, returns FALSE.  Otherwise
  870.  *          returns TRUE.
  871.  *
  872.  * The data requested will either be returned as a BOOL, or copied
  873.  * to pNum, depending on the parameter requested.
  874.  ****************************************************************/
  875. BOOL QueryCDParms( HCDROM hCD, int which, DWORD *pNum )
  876. {
  877.   BOOL retVal = FALSE;
  878.   DWORD dwTmp;
  879.   int idx = (int)hCD - 1;
  880.   if ( (idx<0) || (idx>=MAXCDHAND) || !cdHandles[idx].used )
  881.     {
  882.       alErrCode = ALERR_INVHANDLE;
  883.       return FALSE;
  884.     }
  885.   if ( WaitForSingleObject( cdMutexes[idx], TIMEOUT ) != WAIT_OBJECT_0 )
  886.     {
  887.       alErrCode = ALERR_LOCK;
  888.       return SS_ERR;
  889.     }
  890.   if ( pNum )
  891.     *pNum = 0;
  892.   else
  893.     pNum = &dwTmp;
  894.   if ( !cdHandles[idx].smRead )
  895.     {
  896.       if ( readCDParameters( hCD, FALSE ) != SS_COMP )
  897. {
  898.   ReleaseMutex( cdMutexes[idx] );
  899.   return FALSE;
  900. }
  901.     }
  902.   switch( which )
  903.     {
  904.     case CDP_READCDR:
  905.       retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[2] & 0x01);
  906.       break;
  907.     case CDP_READCDE:
  908.       retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[2] & 0x02);
  909.       break;
  910.     case CDP_METHOD2:
  911.       retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[2] & 0x04);
  912.       break;
  913.     case CDP_WRITECDR:
  914.       retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[3] & 0x01);
  915.       break;
  916.     case CDP_WRITECDE:
  917.       retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[3] & 0x02);
  918.       break;
  919.     case CDP_AUDIOPLAY:
  920.       retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[4] & 0x01);
  921.       break;
  922.     case CDP_COMPOSITE:
  923.       retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[4] & 0x02);
  924.       break;
  925.     case CDP_DIGITAL1:
  926.       retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[4] & 0x04);
  927.       break;
  928.     case CDP_DIGITAL2:
  929.       retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[4] & 0x08);
  930.       break;
  931.     case CDP_M2FORM1:
  932.       retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[4] & 0x10);
  933.       break;
  934.     case CDP_M2FORM2:
  935.       retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[4] & 0x20);
  936.       break;
  937.     case CDP_MULTISES:
  938.       retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[4] & 0x40);
  939.       break;
  940.     case CDP_CDDA:
  941.       retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[5] & 0x01);
  942.       break;
  943.     case CDP_RW:
  944.       retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[5] & 0x04);
  945.       break;
  946.     case CDP_RWCORR:
  947.       retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[5] & 0x08);
  948.       break;
  949.     case CDP_C2SUPP:
  950.       retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[5] & 0x10);
  951.       break;
  952.     case CDP_ISRC:
  953.       retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[5] & 0x20);
  954.       break;
  955.     case CDP_UPC:
  956.       retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[5] & 0x40);
  957.       break;
  958.     case CDP_CANLOCK:
  959.       retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[6] & 0x01);
  960.       break;
  961.     case CDP_LOCKED:
  962.       retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[6] & 0x02);
  963.       break;
  964.     case CDP_PREVJUMP:
  965.       retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[6] & 0x04);
  966.       break;
  967.     case CDP_CANEJECT:
  968.       retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[6] & 0x08);
  969.       break;
  970.     case CDP_SEPVOL:
  971.       retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[7] & 0x01);
  972.       break;
  973.     case CDP_SEPMUTE:
  974.       retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[7] & 0x02);
  975.       break;
  976.     case CDP_SDP:
  977.       retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[7] & 0x04);
  978.       break;
  979.     case CDP_SSS:
  980.       retVal = cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[7] & 0x08);
  981.       break;
  982.     case CDP_MECHTYPE:
  983.       if ( cdHandles[idx].sm.ccsmAvail )
  984. {
  985.   retVal = TRUE;
  986.   *pNum = (DWORD)(cdHandles[idx].sm.ccsm[6] >> 5);
  987. }
  988.       break;
  989.     case CDP_STREAMACC:
  990.       return cdHandles[idx].sm.ccsmAvail && (cdHandles[idx].sm.ccsm[5] & 0x02);
  991.       break;
  992.     case CDP_MAXSPEED:
  993.       if ( cdHandles[idx].sm.ccsmAvail )
  994. {
  995.   retVal = TRUE;
  996.   *pNum = ((DWORD)cdHandles[idx].sm.ccsm[8] << 8) + (DWORD)cdHandles[idx].sm.ccsm[9];
  997. }
  998.       break;
  999.     case CDP_NUMVOL:
  1000.       if ( cdHandles[idx].sm.ccsmAvail )
  1001. {
  1002.   retVal = TRUE;
  1003.   *pNum = ((DWORD)cdHandles[idx].sm.ccsm[10] << 8) + (DWORD)cdHandles[idx].sm.ccsm[11];
  1004. }
  1005.       break;
  1006.     case CDP_BUFSIZE:
  1007.       if ( cdHandles[idx].sm.ccsmAvail )
  1008. {
  1009.   retVal = TRUE;
  1010.   *pNum = ((DWORD)cdHandles[idx].sm.ccsm[12] << 8) + (DWORD)cdHandles[idx].sm.ccsm[13];
  1011. }
  1012.       break;
  1013.     case CDP_CURRSPEED:
  1014.       if ( cdHandles[idx].sm.ccsmAvail )
  1015. {
  1016.   retVal = TRUE;
  1017.   *pNum = ((DWORD)cdHandles[idx].sm.ccsm[14] << 8) + (DWORD)cdHandles[idx].sm.ccsm[15];
  1018. }
  1019.       break;
  1020.     case CDP_SPM:
  1021.       if ( cdHandles[idx].sm.cpmAvail )
  1022. {
  1023.   retVal = TRUE;
  1024.   *pNum = ((DWORD)cdHandles[idx].sm.cpm[4] << 8) + (DWORD)cdHandles[idx].sm.cpm[5];
  1025. }
  1026.       break;
  1027.     case CDP_FPS:
  1028.       if ( cdHandles[idx].sm.cpmAvail )
  1029. {
  1030.   retVal = TRUE;
  1031.   *pNum = ((DWORD)cdHandles[idx].sm.cpm[6] << 8) + (DWORD)cdHandles[idx].sm.cpm[7];
  1032. }
  1033.       break;
  1034.     case CDP_INACTMULT:
  1035.       if ( cdHandles[idx].sm.cpmAvail )
  1036. {
  1037.   retVal = TRUE;
  1038.   *pNum = (DWORD)(cdHandles[idx].sm.cpm[3] & 0x0F);
  1039. }
  1040.       break;
  1041.     case CDP_MSF:
  1042.       retVal = cdHandles[idx].bMSF;
  1043.       break;
  1044.     case CDP_JITTER:
  1045.       retVal = TRUE;
  1046.       *pNum = (DWORD)(cdHandles[idx].numCheck);
  1047.       break;
  1048.     case CDP_OVERLAP:
  1049.       retVal = TRUE;
  1050.       *pNum = (DWORD)(cdHandles[idx].numOverlap);
  1051.       break;
  1052.     case CDP_READMODE:
  1053.       retVal = TRUE;
  1054.       *pNum = (DWORD)(cdHandles[idx].readMode);
  1055.       break;
  1056.     default:
  1057.       break;
  1058.     }
  1059.   ReleaseMutex( cdMutexes[idx] );
  1060.   return retVal;
  1061. }
  1062. /*
  1063.  * Complement to queryCDParms -- used to set values in the various control
  1064.  * pages on the CD drive.
  1065.  */
  1066. BOOL ModifyCDParms( HCDROM hCD, int which, DWORD val )
  1067. {
  1068.   //SENSEMASK smask;
  1069.   //BOOL smRead = FALSE;
  1070.   BOOL retVal = FALSE;
  1071.   int idx = (int)hCD - 1;
  1072.   if ( (idx<0) || (idx>=MAXCDHAND) || !cdHandles[idx].used )
  1073.     {
  1074.       alErrCode = ALERR_INVHANDLE;
  1075.       return FALSE;
  1076.     }
  1077.   if ( WaitForSingleObject( cdMutexes[idx], TIMEOUT ) != WAIT_OBJECT_0 )
  1078.     {
  1079.       alErrCode = ALERR_LOCK;
  1080.       return SS_ERR;
  1081.     }
  1082. #if 0
  1083.   if ( readCDParameters( hCD, TRUE ) != SS_COMP )
  1084.     {
  1085.       ReleaseMutex( cdMutexes[idx] );
  1086.       return FALSE;
  1087.     }
  1088. #endif
  1089.   switch( which )
  1090.     {
  1091.     case CDP_CURRSPEED:
  1092.       if ( setCDSpeed( hCD, val ) == SS_COMP )
  1093. retVal = TRUE;
  1094.       break;
  1095.     case CDP_MSF:
  1096.       cdHandles[idx].bMSF = (BOOL)val;
  1097.       retVal = TRUE;
  1098.       break;
  1099.     case CDP_JITTER:
  1100.       cdHandles[idx].numCheck = (int)val;
  1101.       retVal = TRUE;
  1102.       break;
  1103.     case CDP_OVERLAP:
  1104.       cdHandles[idx].numOverlap = (int)val;
  1105.       retVal = TRUE;
  1106.       break;
  1107.     case CDP_READMODE:
  1108.       cdHandles[idx].readMode = (int)val;
  1109.       retVal = TRUE;
  1110.       break;
  1111.     }
  1112.   ReleaseMutex( cdMutexes[idx] );
  1113.   return retVal;
  1114. }
  1115. /*
  1116.  * Speed is specified in KB/sec: 1x == 176, 2x == 353, 4x == 706
  1117.  *
  1118.  * To set to the maximum allowed speed, specify 0xFFFF.  Attempting to set
  1119.  * a speed higher than the allowed maximum speed should not cause an error,
  1120.  * but should set the speed at the highest allowed value.
  1121.  */
  1122. DWORD setCDSpeed( HCDROM hCD, DWORD speed )
  1123. {
  1124.   DWORD dwStatus;
  1125.   HANDLE heventSRB;
  1126.   SRB_ExecSCSICmd s;
  1127.   int idx = (int)hCD - 1;
  1128.   if ( (idx<0) || (idx>=MAXCDHAND) || !cdHandles[idx].used )
  1129.     {
  1130.       alErrCode = ALERR_INVHANDLE;
  1131.       return SS_ERR;
  1132.     }
  1133.   heventSRB = CreateEvent( NULL, TRUE, FALSE, NULL );
  1134.   memset( &s, 0, sizeof( s ) );
  1135.   s.SRB_Cmd      = SC_EXEC_SCSI_CMD;
  1136.   s.SRB_HaID     = cdHandles[idx].ha;
  1137.   s.SRB_Target   = cdHandles[idx].tgt;
  1138.   s.SRB_Lun      = cdHandles[idx].lun;
  1139.   s.SRB_Flags    = SRB_DIR_OUT | SRB_EVENT_NOTIFY;
  1140.   s.SRB_SenseLen = SENSE_LEN;
  1141.   s.SRB_CDBLen   = 12;
  1142.   s.SRB_PostProc = (LPVOID)heventSRB;
  1143.   s.CDBByte[0]   = 0xBB;
  1144.   s.CDBByte[2]   = (BYTE)(speed >> 8);
  1145.   s.CDBByte[3]   = (BYTE)speed;
  1146.   ResetEvent( heventSRB );
  1147.   dwStatus = pfnSendASPI32Command( (LPSRB)&s );
  1148.   if ( dwStatus == SS_PENDING )
  1149.     {
  1150.       WaitForSingleObject( heventSRB, DEFWAITLEN );
  1151.     }
  1152.   CloseHandle( heventSRB );
  1153.   if ( s.SRB_Status != SS_COMP )
  1154.     {
  1155.       alErrCode = ALERR_ASPI;
  1156.       alAspiErr = s.SRB_Status;
  1157.       CloseHandle( cdMutexes[idx] );
  1158.       return SS_ERR;
  1159.     }
  1160.   return s.SRB_Status;
  1161. }
  1162. DWORD pauseResumeCD( HCDROM hCD, BOOL bPause )
  1163. {
  1164.   DWORD dwStatus;
  1165.   HANDLE heventSRB;
  1166.   SRB_ExecSCSICmd s;
  1167.   int idx = (int)hCD - 1;
  1168.   if ( (idx<0) || (idx>=MAXCDHAND) || !cdHandles[idx].used )
  1169.     {
  1170.       alErrCode = ALERR_INVHANDLE;
  1171.       return SS_ERR;
  1172.     }
  1173.   if ( WaitForSingleObject( cdMutexes[idx], TIMEOUT ) != WAIT_OBJECT_0 )
  1174.     {
  1175.       alErrCode = ALERR_LOCK;
  1176.       return SS_ERR;
  1177.     }
  1178.   heventSRB = CreateEvent( NULL, TRUE, FALSE, NULL );
  1179.   memset( &s, 0, sizeof( s ) );
  1180.   s.SRB_Cmd      = SC_EXEC_SCSI_CMD;
  1181.   s.SRB_HaID     = cdHandles[idx].ha;
  1182.   s.SRB_Target   = cdHandles[idx].tgt;
  1183.   s.SRB_Lun      = cdHandles[idx].lun;
  1184.   s.SRB_Flags    = SRB_EVENT_NOTIFY;
  1185.   s.SRB_SenseLen = SENSE_LEN;
  1186.   s.SRB_CDBLen   = 10;
  1187.   s.SRB_PostProc = (LPVOID)heventSRB;
  1188.   s.CDBByte[0]   = 0x4B;
  1189.   s.CDBByte[8]   = bPause?0:1;
  1190.   ResetEvent( heventSRB );
  1191.   dwStatus = pfnSendASPI32Command( (LPSRB)&s );
  1192.   if ( dwStatus == SS_PENDING )
  1193.     {
  1194.       WaitForSingleObject( heventSRB, DEFWAITLEN );
  1195.     }
  1196.   CloseHandle( heventSRB );
  1197.   if ( s.SRB_Status != SS_COMP )
  1198.     {
  1199.       alErrCode = ALERR_ASPI;
  1200.       alAspiErr = s.SRB_Status;
  1201.       ReleaseMutex( cdMutexes[idx] );
  1202.       return SS_ERR;
  1203.     }
  1204.   ReleaseMutex( cdMutexes[idx] );
  1205.   return s.SRB_Status;
  1206. }
  1207. DWORD startStopUnit( HCDROM hCD, BOOL bLoEj, BOOL bStart )
  1208. {
  1209.   DWORD dwStatus;
  1210.   HANDLE heventSRB;
  1211.   SRB_ExecSCSICmd s;
  1212.   int idx = (int)hCD - 1;
  1213.   if ( (idx<0) || (idx>=MAXCDHAND) || !cdHandles[idx].used )
  1214.     {
  1215.       alErrCode = ALERR_INVHANDLE;
  1216.       return SS_ERR;
  1217.     }
  1218.  
  1219.   if ( WaitForSingleObject( cdMutexes[idx], TIMEOUT ) != WAIT_OBJECT_0 )
  1220.     {
  1221.       alErrCode = ALERR_LOCK;
  1222.       return SS_ERR;
  1223.     }
  1224.   heventSRB = CreateEvent( NULL, TRUE, FALSE, NULL );
  1225.   memset( &s, 0, sizeof( s ) );
  1226.   s.SRB_Cmd      = SC_EXEC_SCSI_CMD;
  1227.   s.SRB_HaID     = cdHandles[idx].ha;
  1228.   s.SRB_Target   = cdHandles[idx].tgt;
  1229.   s.SRB_Lun      = cdHandles[idx].lun;
  1230.   s.SRB_Flags    = SRB_EVENT_NOTIFY;
  1231.   s.SRB_SenseLen = SENSE_LEN;
  1232.   s.SRB_CDBLen   = 6;
  1233.   s.SRB_PostProc = (LPVOID)heventSRB;
  1234.   s.CDBByte[0]   = 0x1B;
  1235.   s.CDBByte[4]  |= bLoEj?0x02:0x00;
  1236.   s.CDBByte[4]  |= bStart?0x01:0x00;
  1237.   ResetEvent( heventSRB );
  1238.   dwStatus = pfnSendASPI32Command( (LPSRB)&s );
  1239.   if ( dwStatus == SS_PENDING )
  1240.     {
  1241.       WaitForSingleObject( heventSRB, DEFWAITLEN );
  1242.     }
  1243.   CloseHandle( heventSRB );
  1244.   if ( s.SRB_Status != SS_COMP )
  1245.     {
  1246.       alErrCode = ALERR_ASPI;
  1247.       alAspiErr = s.SRB_Status;
  1248.       ReleaseMutex( cdMutexes[idx] );
  1249.       return SS_ERR;
  1250.     }
  1251.   ReleaseMutex( cdMutexes[idx] );
  1252.   return s.SRB_Status;
  1253. }
  1254. /****************************************************************
  1255.  * GetAspiLibError
  1256.  *
  1257.  * Used after functions return SS_ERR to get more specific error
  1258.  * information.  If it returns AL_ERRASPI, call getAspiLibAspiError
  1259.  * to get the actual status code returned by the calls to the ASPI
  1260.  * manager.  After reading, the error code is cleared.
  1261.  *
  1262.  ****************************************************************/
  1263. int GetAspiLibError( void )
  1264. {
  1265.   int retVal;
  1266.   retVal = alErrCode;
  1267.   alErrCode = ALERR_NOERROR;
  1268.   return retVal;
  1269. }
  1270. /****************************************************************
  1271.  * GetAspiLibAspiError
  1272.  *
  1273.  * Returns the last error completion code from the ASPI manager.
  1274.  * After reading, the error code is cleared.
  1275.  *
  1276.  ****************************************************************/
  1277. BYTE GetAspiLibAspiError( void )
  1278. {
  1279.   BYTE retVal;
  1280.   retVal = alAspiErr;
  1281.   alAspiErr = SS_COMP;
  1282.   return retVal;
  1283. }
  1284. /****************************************************************
  1285.  * GetCDId
  1286.  *
  1287.  * Generates an identifier string for the CD drive identified by
  1288.  * hCD
  1289.  *
  1290.  ****************************************************************/
  1291. DWORD  GetCDId( HCDROM hCD, char *buf, int maxBuf )
  1292. {
  1293.   int idx = (int)hCD - 1;
  1294.   CDREC cd;
  1295.   if ( (idx<0) || (idx>=MAXCDHAND) || !cdHandles[idx].used )
  1296.     {
  1297.       alErrCode = ALERR_INVHANDLE;
  1298.       return SS_ERR;
  1299.     }
  1300.   if ( !buf )
  1301.     {
  1302.       alErrCode = ALERR_BUFPTR;
  1303.       return SS_ERR;
  1304.     }
  1305.   if ( WaitForSingleObject( cdMutexes[idx], TIMEOUT ) != WAIT_OBJECT_0 )
  1306.     {
  1307.       alErrCode = ALERR_LOCK;
  1308.       return SS_ERR;
  1309.     }
  1310.   memset( &cd, 0, sizeof(cd) );
  1311.   GetDriveInfo( cdHandles[idx].ha, cdHandles[idx].tgt, cdHandles[idx].lun,
  1312. &cd );
  1313.   if ( strlen( cd.id ) > maxBuf-1 )
  1314.     {
  1315.       alErrCode = ALERR_BUFTOOSMALL;
  1316.       strncpy( buf, cd.id, maxBuf );
  1317.       buf[maxBuf-1] = '';
  1318.       ReleaseMutex( cdMutexes[idx] );
  1319.       return SS_ERR;
  1320.     }
  1321.   else
  1322.     strcpy( buf, cd.id );
  1323.   ReleaseMutex( cdMutexes[idx] );
  1324.   return SS_COMP;
  1325. }
  1326. /*
  1327.  * Returns TRUE if the overlap buffer is located in the track buffer.  The
  1328.  * track buffer startOffset is adjusted to reflect where in the buffer the
  1329.  * aligned data begins.  numFrames and len are also adjusted to reflect the
  1330.  * number of complete frames are contained in the buffer.
  1331.  */
  1332. int jitterAdjust( LPTRACKBUF tbuf, LPTRACKBUF tover, int checkFrames )
  1333. {
  1334.   int i;
  1335.   int max;
  1336.   int bFound = 0;
  1337.   BYTE *p;
  1338.   int checkLen = checkFrames * 2352;
  1339.   max = tbuf->len - checkLen;
  1340.   if ( tover->len == 0 )
  1341.     return 1;
  1342.   p = &tover->buf[tover->startOffset];
  1343.   bFound = 0;
  1344.   for( i = 0; i < max; i++ )
  1345.     {
  1346.       if ( compBuf( p, &(tbuf->buf[i]), checkLen ) )
  1347. {
  1348.   tbuf->startOffset = i + checkLen;
  1349.   tbuf->len -= (i + checkLen);
  1350.   tbuf->startFrame = tover->startFrame + checkFrames;
  1351.   i = max + 1;
  1352.   bFound = -1;
  1353. }
  1354.     }
  1355.   /* adjust frame count and crop length */
  1356.   tbuf->numFrames = tbuf->len / 2352;
  1357.   tbuf->len = 2352 * tbuf->numFrames;
  1358.   //  return (tbuf->startOffset == 0);
  1359.   return bFound;
  1360. }
  1361. /*
  1362.  * Reads CD-DA audio, implementing jitter correction.  tOver is used to align
  1363.  * the current read, if possible.  After a successful read, numOverlap frames
  1364.  * are copied to tOver.
  1365.  */
  1366. DWORD ReadCDAudioLBAEx( HCDROM hCD, LPTRACKBUF t, LPTRACKBUF tOver )
  1367. {
  1368.   DWORD retVal;
  1369.   int idx = (int)hCD - 1;
  1370.   int j, o;
  1371.   unsigned char *pOverAddr;
  1372.   BOOL bJitterCorr;
  1373.   if ( (idx<0) || (idx>=MAXCDHAND) )
  1374.     {
  1375.       alErrCode = ALERR_INVHANDLE;
  1376.       return SS_ERR;
  1377.     }
  1378.   retVal = WaitForSingleObject( cdMutexes[idx], TIMEOUT );
  1379.   if ( retVal != WAIT_OBJECT_0 )
  1380.     {
  1381.       alErrCode = ALERR_LOCK;
  1382.       return SS_ERR;
  1383.     }
  1384.   if ( !cdHandles[idx].used )
  1385.     {
  1386.       alErrCode = ALERR_INVHANDLE;
  1387.       ReleaseMutex( cdMutexes[idx] );
  1388.       return SS_ERR;
  1389.     }
  1390.   j = cdHandles[idx].numCheck;
  1391.   o = cdHandles[idx].numOverlap;
  1392.   // check that the overlap buffer is large enough -- if not, disable
  1393.   // jitter correction.  We may want to eventually throw an error
  1394.   bJitterCorr = ((tOver->maxLen / 2352) >= o);
  1395. #ifdef _DEBUG
  1396.   dbprintf( "akrip32: ReadCDAudioLBAEx( t->startFrame == %08X, tOver->startFrame == %08X, j == %d )", t->startFrame, tOver->startFrame, j );
  1397.   dbprintf( "       : t: %08X %d %d", t->startFrame, t->numFrames, t->len );
  1398.   dbprintf( "       : tOver: %08X %d %d", tOver->startFrame, tOver->numFrames, tOver->len );
  1399. #endif
  1400.   // adjust the starting address of the read if necessary
  1401.   if ( bJitterCorr && tOver->startFrame && tOver->numFrames && tOver->len )
  1402.     {
  1403.       // is this tOver from the last sequential read?
  1404.       if ( tOver->startFrame == (t->startFrame - j) )
  1405. {
  1406. #ifdef _DEBUG
  1407.   dbprintf( "Rolling back the read..." );
  1408. #endif
  1409.   t->startFrame -= o;
  1410. }
  1411.       else
  1412. {
  1413. #ifdef _DEBUG
  1414.   dbprintf( "Zeroing out the overlap!" );
  1415. #endif
  1416.   tOver->len = tOver->startFrame = tOver->numFrames = 0;
  1417. }
  1418.     }
  1419.   retVal = cdHandles[idx].pfnRead( hCD, t );
  1420.   if ( (retVal == SS_COMP) && bJitterCorr )
  1421.     {
  1422. #ifdef _DEBUG
  1423.       dbprintf( "akrip32: ReadCDAudioLBAEx: read itself OK" );
  1424. #endif
  1425.       j = cdHandles[idx].numCheck;
  1426.       if ( !jitterAdjust( t, tOver, j ) )
  1427. {
  1428. #ifdef _DEBUG
  1429.   dbprintf( "akrip32: ... jitterAdjust failed!" );
  1430. #endif
  1431.   alErrCode = ALERR_JITTER;
  1432.   ReleaseMutex( cdMutexes[idx] );
  1433.   return SS_ERR;
  1434. }
  1435. #ifdef _DEBUG
  1436.       dbprintf( "akrip32: ... after successful jitter adjust" );
  1437. #endif
  1438.       pOverAddr = &(t->buf[2352*(t->numFrames-j)+t->startOffset]);
  1439.       memcpy( tOver->buf, pOverAddr, 2352*j );
  1440.       tOver->startFrame = t->startFrame + t->numFrames - j;
  1441.       tOver->numFrames = j;
  1442.       tOver->len = 2352 * j;
  1443.       tOver->startOffset = 0;
  1444.     }
  1445. #ifdef _DEBUG
  1446.   else
  1447.     dbprintf( "akrip32: ReadCDAudioLBAEx: read failed" );
  1448. #endif
  1449.   ReleaseMutex( cdMutexes[idx] );
  1450. #ifdef _DEBUG
  1451.   dbprintf( "akrip32: readCDAudioLBAEx: returning %04X", retVal );
  1452. #endif
  1453.   return retVal;
  1454. }
  1455. /********************************************************************
  1456.  * compBuf
  1457.  *
  1458.  * Compares two buffers up to n bytes, returning 1 if they contain the
  1459.  * same data, or zero if they are different.
  1460.  *
  1461.  ********************************************************************/
  1462. int compBuf( BYTE *b1, BYTE *b2, int n )
  1463. {
  1464. #if 0
  1465.   int i;
  1466.   for( i = 0; i < n; i++ )
  1467.     if ( b1[i] != b2[i] )
  1468.       {
  1469. return 0;
  1470.       }
  1471.   return 1;
  1472. #else
  1473.   return !memcmp( b1, b2, n );
  1474. #endif
  1475. }
  1476. DWORD GetAKRipDllVersion( void )
  1477. {
  1478.   DWORD retVal;
  1479.   retVal = (DWORD)( (((WORD)MAJVER)<<16) | (WORD)MINVER );
  1480.   return retVal;
  1481. }
  1482. void dbprintf( char *fmt, ... )
  1483. {
  1484.   char buf[512];
  1485.   va_list arg;
  1486.   va_start( arg, fmt );
  1487.   vsprintf( buf, fmt, arg );
  1488.   OutputDebugString( buf );
  1489.   va_end( arg );
  1490. }