+
+#endif
+}
+
+
+#if defined( WIN32 )
+
+/*****************************************************************************
+ * _win32_dvdcss_readv: vectored read using ReadFile for Win2K and
+ * _win32_dvdcss_aread for win9x
+ *****************************************************************************/
+static int _win32_dvdcss_readv( int i_fd, struct iovec *p_iovec,
+ int i_num_buffers, char *p_tmp_buffer )
+{
+ int i_index;
+ int i_blocks, i_blocks_total = 0;
+
+ for( i_index = i_num_buffers; i_index; i_index-- )
+ {
+ i_blocks_total += p_iovec[i_index-1].iov_len;
+ }
+
+ if( i_blocks_total <= 0 ) return 0;
+
+ i_blocks_total /= DVDCSS_BLOCK_SIZE;
+
+ if( WIN2K )
+ {
+ unsigned long int i_bytes;
+ if( !ReadFile( (HANDLE)i_fd, p_tmp_buffer,
+ i_blocks_total * DVDCSS_BLOCK_SIZE, &i_bytes, NULL ) )
+ {
+ return -1;
+ /* The read failed... too bad.
+ As in the posix spec the file postition is left
+ unspecified after a failure */
+ }
+ i_blocks = i_bytes / DVDCSS_BLOCK_SIZE;
+ }
+ else /* Win9x */
+ {
+ i_blocks = _win32_dvdcss_aread( i_fd, p_tmp_buffer, i_blocks_total );
+ if( i_blocks < 0 )
+ {
+ return -1; /* idem */
+ }
+ }
+
+ /* We just have to copy the content of the temp buffer into the iovecs */
+ i_index = 0;
+ i_blocks_total = i_blocks;
+ while( i_blocks_total > 0 )
+ {
+ memcpy( p_iovec[i_index].iov_base,
+ &p_tmp_buffer[(i_blocks - i_blocks_total) * DVDCSS_BLOCK_SIZE],
+ p_iovec[i_index].iov_len );
+ /* if we read less blocks than asked, we'll just end up copying
+ garbage, this isn't an issue as we return the number of
+ blocks actually read */
+ i_blocks_total -= ( p_iovec[i_index].iov_len / DVDCSS_BLOCK_SIZE );
+ i_index++;
+ }
+
+ return i_blocks;
+}
+
+/*****************************************************************************
+ * _win32_dvdcss_aopen: open dvd drive (load aspi and init w32_aspidev
+ * structure)
+ *****************************************************************************/
+static int _win32_dvdcss_aopen( char c_drive, dvdcss_handle dvdcss )
+{
+ HMODULE hASPI;
+ DWORD dwSupportInfo;
+ struct w32_aspidev *fd;
+ int i, j, i_hostadapters;
+ long (*lpGetSupport)( void );
+ long (*lpSendCommand)( void* );
+
+ hASPI = LoadLibrary( "wnaspi32.dll" );
+ if( hASPI == NULL )
+ {
+ _dvdcss_error( dvdcss, "unable to load wnaspi32.dll" );
+ return -1;
+ }
+
+ (FARPROC) lpGetSupport = GetProcAddress( hASPI, "GetASPI32SupportInfo" );
+ (FARPROC) lpSendCommand = GetProcAddress( hASPI, "SendASPI32Command" );
+
+ if(lpGetSupport == NULL || lpSendCommand == NULL )
+ {
+ _dvdcss_debug( dvdcss, "unable to get aspi function pointers" );
+ FreeLibrary( hASPI );
+ return -1;
+ }
+
+ dwSupportInfo = lpGetSupport();
+
+ if( HIBYTE( LOWORD ( dwSupportInfo ) ) == SS_NO_ADAPTERS )
+ {
+ _dvdcss_debug( dvdcss, "no host adapters found (aspi)" );
+ FreeLibrary( hASPI );
+ return -1;
+ }
+
+ if( HIBYTE( LOWORD ( dwSupportInfo ) ) != SS_COMP )
+ {
+ _dvdcss_error( dvdcss, "unable to initalize aspi layer" );
+ FreeLibrary( hASPI );
+ return -1;
+ }
+
+ i_hostadapters = LOBYTE( LOWORD( dwSupportInfo ) );
+ if( i_hostadapters == 0 )
+ {
+ FreeLibrary( hASPI );
+ return -1;
+ }
+
+ fd = malloc( sizeof( struct w32_aspidev ) );
+ if( fd == NULL )
+ {
+ FreeLibrary( hASPI );
+ return -1;
+ }
+
+ fd->i_blocks = 0;
+ fd->hASPI = (long) hASPI;
+ fd->lpSendCommand = lpSendCommand;
+
+ c_drive = c_drive > 'Z' ? c_drive - 'a' : c_drive - 'A';
+
+ for( i = 0; i < i_hostadapters; i++ )
+ {
+ for( j = 0; j < 15; j++ )
+ {
+ struct SRB_GetDiskInfo srbDiskInfo;
+
+ srbDiskInfo.SRB_Cmd = SC_GET_DISK_INFO;
+ srbDiskInfo.SRB_HaId = i;
+ srbDiskInfo.SRB_Flags = 0;
+ srbDiskInfo.SRB_Hdr_Rsvd = 0;
+ srbDiskInfo.SRB_Target = j;
+ srbDiskInfo.SRB_Lun = 0;
+
+ lpSendCommand( (void*) &srbDiskInfo );
+
+ if( (srbDiskInfo.SRB_Status == SS_COMP) &&
+ (srbDiskInfo.SRB_Int13HDriveInfo == c_drive) )
+ {
+ fd->i_sid = MAKEWORD( i, j );
+ return (int) fd;
+ }
+ }
+ }
+
+ free( (void*) fd );
+ FreeLibrary( hASPI );
+ _dvdcss_debug( dvdcss, "unable to get haid and target (aspi)" );
+ return( -1 );
+}
+
+/*****************************************************************************
+ * _win32_dvdcss_aclose: close dvd drive (unload aspi and free w32_aspidev
+ * structure)
+ *****************************************************************************/
+static int _win32_dvdcss_aclose( int i_fd )
+{
+ struct w32_aspidev *fd = (struct w32_aspidev *) i_fd;
+
+ FreeLibrary( (HMODULE) fd->hASPI );
+ free( (void*) i_fd );
+
+ return 0;
+}
+
+/*****************************************************************************
+ * _win32_dvdcss_aseek: aspi version of _dvdcss_seek
+ *
+ * returns the number of blocks read.
+ *****************************************************************************/
+static int _win32_dvdcss_aseek( int i_fd, int i_blocks, int i_method )
+{
+ int i_old_blocks;
+ char sz_buf[ DVDCSS_BLOCK_SIZE ];
+ struct w32_aspidev *fd = (struct w32_aspidev *) i_fd;
+
+ i_old_blocks = fd->i_blocks;
+ fd->i_blocks = i_blocks;
+
+ if( _win32_dvdcss_aread( i_fd, sz_buf, 1 ) == -1 )
+ {
+ fd->i_blocks = i_old_blocks;
+ return -1;
+ }
+
+ (fd->i_blocks)--;
+
+ return fd->i_blocks;