
> Log Message:
> 
>   * Exported the CSS part of the dvd plugin into a library.

The dvd plugin is now causing the video and audio to stutter 
under both GNU/Linux and Win2k. I'll have a look at this
tomorrow (today) unless someone beats me to it. 

Anyway, attached is a patch which adds win32 aspi support.

-- 
Jon Johansen
nanocrew.net


-- Attached file included as plaintext by Listar --

diff -urN vlc.cvs/extras/libdvdcss/css.c vlc/extras/libdvdcss/css.c
--- vlc.cvs/extras/libdvdcss/css.c	Thu Jun 14 02:22:03 2001
+++ vlc/extras/libdvdcss/css.c	Thu Jun 14 02:22:18 2001
@@ -39,7 +39,7 @@
 
 #ifdef HAVE_UNISTD_H
 #   include <unistd.h>
-#elif defined( _MSC_VER ) && defined( _WIN32 )
+#elif defined( WIN32 )
 #   include <io.h>
 #endif
 
@@ -322,7 +322,7 @@
     off_t       i_pos;
     boolean_t   b_encrypted;
     boolean_t   b_stop_scanning;
-    int         i_bytes_read;
+    int         i_blocks_read;
     int         i_best_plen;
     int         i_best_p;
     int         i,j;
@@ -336,16 +336,11 @@
     b_stop_scanning = 0;
 
     /* Position of the title on the disc */
-    i_pos = (off_t)DVDCSS_BLOCK_SIZE * (off_t)dvdcss->css.i_title_pos;
+    i_pos = (off_t)dvdcss->css.i_title_pos;
 
     do {
-#if !defined( WIN32 )
-    i_pos = lseek( dvdcss->i_fd, i_pos, SEEK_SET );
-    i_bytes_read = read( dvdcss->i_fd, pi_buf, 0x800 );
-#else
-    i_pos = SetFilePointer( (HANDLE) dvdcss->i_fd, i_pos, 0, FILE_BEGIN );
-    ReadFile( (HANDLE) dvdcss->i_fd, pi_buf, 0x800, &i_bytes_read, NULL );
-#endif
+    i_pos = dvdcss_seek( dvdcss, i_pos );
+    i_blocks_read = dvdcss_read( dvdcss, pi_buf, 1, DVDCSS_NOFLAGS );
 
     /* PES_scrambling_control */
     if( pi_buf[0x14] & 0x30 )
@@ -377,8 +372,8 @@
         }
     }
 
-    i_pos += i_bytes_read;
-    } while( i_bytes_read == 0x800 && !b_stop_scanning);
+    i_pos += i_blocks_read;
+    } while( i_blocks_read == 0x1 && !b_stop_scanning);
 
     if( b_stop_scanning)
     {
diff -urN vlc.cvs/extras/libdvdcss/ioctl.c vlc/extras/libdvdcss/ioctl.c
--- vlc.cvs/extras/libdvdcss/ioctl.c	Thu Jun 14 02:22:03 2001
+++ vlc/extras/libdvdcss/ioctl.c	Thu Jun 14 02:22:18 2001
@@ -70,6 +70,14 @@
 #endif
 
 /*****************************************************************************
+ * Local prototypes, win32 (aspi) specific
+ *****************************************************************************/
+#if defined( WIN32 )
+static void WinInitSSC ( struct SRB_ExecSCSICmd *, int );
+static int  WinSendSSC ( int, struct SRB_ExecSCSICmd * );
+#endif
+
+/*****************************************************************************
  * ioctl_ReadCopyright: check whether the disc is encrypted or not
  *****************************************************************************/
 int ioctl_ReadCopyright( int i_fd, int i_layer, int *pi_copyright )
@@ -115,7 +123,7 @@
     i_ret = 0;
 
 #elif defined( WIN32 )
-    if( GetVersion() < 0x80000000 ) /* NT/Win2000/Whistler */
+    if( WIN2K ) /* NT/Win2000/Whistler */
     {
         DWORD tmp;
         u8 p_buffer[ 8 ];
@@ -150,11 +158,14 @@
     }
     else
     {
-        /* TODO: add WNASPI support for Win9x */
-        _dvd_error( dvdcss, "DVD ioctls not functional yet, "
-                               "assuming disc is unencrypted" );
-        *pi_copyright = 0;
-        i_ret = 0;
+        INIT_SSC( GPCMD_READ_DVD_STRUCTURE, 8 );
+
+        ssc.CDBByte[ 6 ] = i_layer;
+        ssc.CDBByte[ 7 ] = DVD_STRUCT_COPYRIGHT;
+
+        i_ret = WinSendSSC( i_fd, &ssc );
+
+        *pi_copyright = p_buffer[ 4 ];
     }
 
 #else
@@ -228,7 +239,7 @@
     memset( p_key, 0x00, 2048 );
 
 #elif defined( WIN32 )
-    if( GetVersion() < 0x80000000 ) /* NT/Win2000/Whistler */
+    if( WIN2K ) /* NT/Win2000/Whistler */
     {
         DWORD tmp;
         u8 buffer[DVD_DISK_KEY_LENGTH];
@@ -253,7 +264,19 @@
     }
     else
     {
-        i_ret = -1;
+        INIT_SSC( GPCMD_READ_DVD_STRUCTURE, 2048 + 4 );
+
+        ssc.CDBByte[ 7 ]  = DVD_STRUCT_DISCKEY;
+        ssc.CDBByte[ 10 ] = *pi_agid << 6;
+    
+        i_ret = WinSendSSC( i_fd, &ssc );
+
+        if( i_ret < 0 )
+        {
+            return i_ret;
+        }
+
+        memcpy( p_key, p_buffer + 4, 2048 );
     }
 
 #else
@@ -312,7 +335,7 @@
     *pi_agid = p_buffer[ 7 ] >> 6;
 
 #elif defined( WIN32 )
-    if( GetVersion() < 0x80000000 ) /* NT/Win2000/Whistler */
+    if( WIN2K ) /* NT/Win2000/Whistler */
     {
         ULONG id;
         DWORD tmp;
@@ -324,7 +347,13 @@
     }
     else
     {
-        i_ret = -1;
+        INIT_SSC( GPCMD_REPORT_KEY, 8 );
+
+        ssc.CDBByte[ 10 ] = DVD_REPORT_AGID | (*pi_agid << 6);
+
+        i_ret = WinSendSSC( i_fd, &ssc );
+
+        *pi_agid = p_buffer[ 7 ] >> 6;
     }
 
 #else
@@ -383,7 +412,7 @@
     memcpy( p_challenge, p_buffer + 4, 12 );
 
 #elif defined( WIN32 )
-    if( GetVersion() < 0x80000000 ) /* NT/Win2000/Whistler */
+    if( WIN2K ) /* NT/Win2000/Whistler */
     {
         DWORD tmp;
         u8 buffer[DVD_CHALLENGE_KEY_LENGTH];
@@ -408,7 +437,13 @@
     }
     else
     {
-        i_ret = -1;
+        INIT_SSC( GPCMD_REPORT_KEY, 16 );
+
+        ssc.CDBByte[ 10 ] = DVD_REPORT_CHALLENGE | (*pi_agid << 6);
+
+        i_ret = WinSendSSC( i_fd, &ssc );
+
+        memcpy( p_challenge, p_buffer + 4, 12 );
     }
 
 #else
@@ -469,7 +504,7 @@
     *pi_asf = p_buffer[ 7 ] & 1;
 
 #elif defined( WIN32 )
-    if( GetVersion() < 0x80000000 ) /* NT/Win2000/Whistler */
+    if( WIN2K ) /* NT/Win2000/Whistler */
     {
         DWORD tmp;
         u8 buffer[DVD_ASF_LENGTH];
@@ -496,7 +531,13 @@
     }
     else
     {
-        i_ret = -1;
+        INIT_SSC( GPCMD_REPORT_KEY, 8 );
+
+        ssc.CDBByte[ 10 ] = DVD_REPORT_ASF | (*pi_agid << 6);
+
+        i_ret = WinSendSSC( i_fd, &ssc );
+
+        *pi_asf = p_buffer[ 7 ] & 1;
     }
 
 #else
@@ -554,7 +595,7 @@
     memcpy( p_key, p_buffer + 4, 8 );
 
 #elif defined( WIN32 )
-    if( GetVersion() < 0x80000000 ) /* NT/Win2000/Whistler */
+    if( WIN2K ) /* NT/Win2000/Whistler */
     {
         DWORD tmp;
         u8 buffer[DVD_BUS_KEY_LENGTH];
@@ -574,7 +615,13 @@
     }
     else
     {
-        i_ret = -1;
+        INIT_SSC( GPCMD_REPORT_KEY, 12 );
+
+        ssc.CDBByte[ 10 ] = DVD_REPORT_KEY1 | (*pi_agid << 6);
+
+        i_ret = WinSendSSC( i_fd, &ssc );
+
+        memcpy( p_key, p_buffer + 4, 8 );
     }
 
 #else
@@ -628,7 +675,7 @@
     i_ret = ioctl( i_fd, IODVD_SEND_KEY, &dvdioctl );
 
 #elif defined( WIN32 )
-    if( GetVersion() < 0x80000000 ) /* NT/Win2000/Whistler */
+    if( WIN2K ) /* NT/Win2000/Whistler */
     {
         DWORD tmp;
 
@@ -637,7 +684,19 @@
     }
     else
     {
-        i_ret = -1;
+#if defined( __MINGW32__ )
+        INIT_SSC( GPCMD_REPORT_KEY, 0 );
+#else
+        INIT_SSC( GPCMD_REPORT_KEY, 1 );
+
+        ssc.SRB_BufLen    = 0;
+        ssc.CDBByte[ 8 ]  = 0;
+        ssc.CDBByte[ 9 ]  = 0;
+#endif
+
+        ssc.CDBByte[ 10 ] = DVD_INVALIDATE_AGID | (*pi_agid << 6);
+
+        i_ret = WinSendSSC( i_fd, &ssc );
     }
 
 #else
@@ -695,7 +754,7 @@
     return ioctl( i_fd, IODVD_SEND_KEY, &dvdioctl );
 
 #elif defined( WIN32 )
-    if( GetVersion() < 0x80000000 ) /* NT/Win2000/Whistler */
+    if( WIN2K ) /* NT/Win2000/Whistler */
     {
         DWORD tmp;
         u8 buffer[DVD_CHALLENGE_KEY_LENGTH];
@@ -715,7 +774,14 @@
     }
     else
     {
-        return -1;
+        INIT_SSC( GPCMD_SEND_KEY, 16 );
+
+        ssc.CDBByte[ 10 ] = DVD_SEND_CHALLENGE | (*pi_agid << 6);
+
+        p_buffer[ 1 ] = 0xe;
+        memcpy( p_buffer + 4, p_challenge, 12 );
+
+        return WinSendSSC( i_fd, &ssc );
     }
 
 #else
@@ -761,7 +827,7 @@
     return ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
 
 #elif defined( WIN32 )
-    if( GetVersion() < 0x80000000 ) /* NT/Win2000/Whistler */
+    if( WIN2K ) /* NT/Win2000/Whistler */
     {
         DWORD tmp;
         u8 buffer[DVD_BUS_KEY_LENGTH];
@@ -781,7 +847,14 @@
     }
     else
     {
-        return -1;
+        INIT_SSC( GPCMD_SEND_KEY, 12 );
+
+        ssc.CDBByte[ 10 ] = DVD_SEND_KEY2 | (*pi_agid << 6);
+
+        p_buffer[ 1 ] = 0xa;
+        memcpy( p_buffer + 4, p_key, 8 );
+
+        return WinSendSSC( i_fd, &ssc );
     }
 
 #elif defined( SYS_DARWIN1_3 )
@@ -840,3 +913,65 @@
 }
 #endif
 
+#if defined( WIN32 )
+/*****************************************************************************
+ * WinInitSSC: initialize a ssc structure for the win32 aspi layer
+ *****************************************************************************
+ * This function initializes a ssc raw device command structure for future
+ * use, either a read command or a write command.
+ *****************************************************************************/
+static void WinInitSSC( struct SRB_ExecSCSICmd *p_ssc, int i_type )
+{
+    memset( p_ssc->SRB_BufPointer, 0, p_ssc->SRB_BufLen );
+
+    switch( i_type )
+    {
+        case GPCMD_SEND_KEY:
+            p_ssc->SRB_Flags = SRB_DIR_OUT;
+            break;
+
+        case GPCMD_READ_DVD_STRUCTURE:
+        case GPCMD_REPORT_KEY:
+            p_ssc->SRB_Flags = SRB_DIR_IN;
+            break;
+    }
+
+    p_ssc->SRB_Cmd      = SC_EXEC_SCSI_CMD;
+    p_ssc->SRB_Flags    |= SRB_EVENT_NOTIFY;
+
+    p_ssc->CDBByte[ 0 ] = i_type;
+
+    p_ssc->CDBByte[ 8 ] = (u8)(p_ssc->SRB_BufLen >> 8) & 0xff;
+    p_ssc->CDBByte[ 9 ] = (u8) p_ssc->SRB_BufLen       & 0xff;
+    p_ssc->SRB_CDBLen   = 12;
+
+    p_ssc->SRB_SenseLen = SENSE_LEN;
+}
+
+/*****************************************************************************
+ * WinSendSSC: send a ssc structure to the aspi layer
+ *****************************************************************************/
+static int WinSendSSC( int i_fd, struct SRB_ExecSCSICmd *p_ssc )
+{
+    HANDLE hEvent = NULL;
+    struct w32_aspidev *fd = (struct w32_aspidev *) i_fd;
+
+    hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
+    if( hEvent == NULL )
+    {
+        return -1;
+    }
+
+    p_ssc->SRB_PostProc  = hEvent;
+    p_ssc->SRB_HaId      = LOBYTE( fd->i_sid );
+    p_ssc->SRB_Target    = HIBYTE( fd->i_sid );
+
+    ResetEvent( hEvent );
+    if( fd->lpSendCommand( (void*) p_ssc ) == SS_PENDING )
+        WaitForSingleObject( hEvent, INFINITE );
+
+    CloseHandle( hEvent );
+
+    return p_ssc->SRB_Status == SS_COMP ? 0 : -1;
+}
+#endif
diff -urN vlc.cvs/extras/libdvdcss/ioctl.h vlc/extras/libdvdcss/ioctl.h
--- vlc.cvs/extras/libdvdcss/ioctl.h	Thu Jun 14 02:22:03 2001
+++ vlc/extras/libdvdcss/ioctl.h	Thu Jun 14 02:22:18 2001
@@ -59,6 +59,19 @@
 #endif
 
 /*****************************************************************************
+ * Common macro, win32 (ASPI) specific
+ *****************************************************************************/
+#if defined( WIN32 )
+#define INIT_SSC( TYPE, SIZE ) \
+    struct SRB_ExecSCSICmd ssc; \
+    u8 p_buffer[ (SIZE) ]; \
+    memset( &ssc, 0, sizeof( struct SRB_ExecSCSICmd ) ); \
+    ssc.SRB_BufPointer = (char *)p_buffer; \
+    ssc.SRB_BufLen = (SIZE); \
+    WinInitSSC( &ssc, (TYPE) );
+#endif
+
+/*****************************************************************************
  * Various DVD I/O tables
  *****************************************************************************/
 
@@ -83,6 +96,10 @@
 
 #if defined( WIN32 )
 
+/*****************************************************************************
+ * win32 ioctl specific
+ *****************************************************************************/
+
 #define IOCTL_DVD_START_SESSION         CTL_CODE(FILE_DEVICE_DVD, 0x0400, METHOD_BUFFERED, FILE_READ_ACCESS)
 #define IOCTL_DVD_READ_KEY              CTL_CODE(FILE_DEVICE_DVD, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS)
 #define IOCTL_DVD_SEND_KEY              CTL_CODE(FILE_DEVICE_DVD, 0x0402, METHOD_BUFFERED, FILE_READ_ACCESS)
@@ -90,10 +107,13 @@
 
 #define IOCTL_SCSI_PASS_THROUGH_DIRECT  CTL_CODE(FILE_DEVICE_CONTROLLER, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
 
-#define DVD_CHALLENGE_KEY_LENGTH    (12 + sizeof(DVD_COPY_PROTECT_KEY))
-#define DVD_BUS_KEY_LENGTH          (8 + sizeof(DVD_COPY_PROTECT_KEY))
-#define DVD_DISK_KEY_LENGTH         (2048 + sizeof(DVD_COPY_PROTECT_KEY))
-#define DVD_ASF_LENGTH              (sizeof(DVD_ASF) + sizeof(DVD_COPY_PROTECT_KEY))
+#define DVD_CHALLENGE_KEY_LENGTH        (12 + sizeof(DVD_COPY_PROTECT_KEY))
+#define DVD_BUS_KEY_LENGTH              (8 + sizeof(DVD_COPY_PROTECT_KEY))
+#define DVD_DISK_KEY_LENGTH             (2048 + sizeof(DVD_COPY_PROTECT_KEY))
+#define DVD_ASF_LENGTH                  (sizeof(DVD_ASF) + sizeof(DVD_COPY_PROTECT_KEY))
+
+#define SCSI_IOCTL_DATA_OUT             0
+#define SCSI_IOCTL_DATA_IN              1
 
 typedef ULONG DVD_SESSION_ID, *PDVD_SESSION_ID;
 
@@ -152,8 +172,73 @@
     UCHAR Cdb[16];
 } SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT;
 
-#define SCSI_IOCTL_DATA_OUT         0
-#define SCSI_IOCTL_DATA_IN          1
+/*****************************************************************************
+ * win32 aspi specific
+ *****************************************************************************/
+
+#define WIN2K               ( GetVersion() < 0x80000000 )
+#define ASPI_HAID           0
+#define ASPI_TARGET         0
+
+#define SENSE_LEN           0x0E
+#define SC_EXEC_SCSI_CMD    0x02
+#define SC_GET_DISK_INFO    0x06
+#define SS_COMP             0x01
+#define SS_PENDING          0x00
+#define SS_NO_ADAPTERS      0xE8
+#define SRB_DIR_IN          0x08
+#define SRB_DIR_OUT         0x10
+#define SRB_EVENT_NOTIFY    0x40
+
+struct w32_aspidev
+{
+    long hASPI;
+    short i_sid;
+    off_t i_pos;
+    long (*lpSendCommand)( void* );
+};
+
+#pragma pack(1)
+
+struct SRB_GetDiskInfo
+{
+    unsigned char   SRB_Cmd;
+    unsigned char   SRB_Status;
+    unsigned char   SRB_HaId;
+    unsigned char   SRB_Flags;
+    unsigned long   SRB_Hdr_Rsvd;
+    unsigned char   SRB_Target;
+    unsigned char   SRB_Lun;
+    unsigned char   SRB_DriveFlags;
+    unsigned char   SRB_Int13HDriveInfo;
+    unsigned char   SRB_Heads;
+    unsigned char   SRB_Sectors;
+    unsigned char   SRB_Rsvd1[22];
+};
+
+struct SRB_ExecSCSICmd
+{
+    unsigned char   SRB_Cmd;
+    unsigned char   SRB_Status;
+    unsigned char   SRB_HaId;
+    unsigned char   SRB_Flags;
+    unsigned long   SRB_Hdr_Rsvd;
+    unsigned char   SRB_Target;
+    unsigned char   SRB_Lun;
+    unsigned short  SRB_Rsvd1;
+    unsigned long   SRB_BufLen;
+    unsigned char   *SRB_BufPointer;
+    unsigned char   SRB_SenseLen;
+    unsigned char   SRB_CDBLen;
+    unsigned char   SRB_HaStat;
+    unsigned char   SRB_TargStat;
+    unsigned long   *SRB_PostProc;
+    unsigned char   SRB_Rsvd2[20];
+    unsigned char   CDBByte[16];
+    unsigned char   SenseArea[SENSE_LEN+2];
+};
+
+#pragma pack()
 
 #endif
 
diff -urN vlc.cvs/extras/libdvdcss/libdvdcss.c vlc/extras/libdvdcss/libdvdcss.c
--- vlc.cvs/extras/libdvdcss/libdvdcss.c	Thu Jun 14 02:22:03 2001
+++ vlc/extras/libdvdcss/libdvdcss.c	Thu Jun 14 02:22:39 2001
@@ -32,7 +32,10 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
-#include <unistd.h>
+
+#ifdef HAVE_UNISTD_H
+#   include <unistd.h>
+#endif
 
 #if defined( WIN32 )
 #   include <io.h>
@@ -46,6 +49,7 @@
 
 #include "videolan/dvdcss.h"
 #include "libdvdcss.h"
+#include "ioctl.h"
 
 /*****************************************************************************
  * Local prototypes
@@ -57,6 +61,18 @@
 static int _dvdcss_readv ( dvdcss_handle, struct iovec *p_iovec, int i_blocks );
 
 /*****************************************************************************
+ * Local prototypes, win32 specific
+ *****************************************************************************/
+#if defined( WIN32 )
+static int _win32_readv  ( int i_fd, struct iovec *p_iovec, int i_blocks );
+static int _win32_aopen  ( char c_drive, dvdcss_handle dvdcss );
+static int _win32_aclose ( int i_fd );
+static int _win32_aseek  ( int i_fd, off_t i_pos, int i_method );
+static int _win32_aread  ( int i_fd, void *p_data, int i_len );
+static int _win32_areadv ( int i_fd, struct iovec *p_iovec, int i_blocks );
+#endif
+
+/*****************************************************************************
  * dvdcss_init: initialize libdvdcss
  *****************************************************************************/
 extern dvdcss_handle dvdcss_init ( int i_flags )
@@ -341,15 +357,28 @@
 static int _dvdcss_open ( dvdcss_handle dvdcss, char *psz_target )
 {
 #if defined( WIN32 )
-    snprintf( buf, 7, "\\\\.\\%c:", psz_target[0] );
-    (HANDLE) dvdcss->i_fd =
-            CreateFile( psz_target, GENERIC_READ | GENERIC_WRITE,
-                                    FILE_SHARE_READ | FILE_SHARE_WRITE,
-                                    NULL, OPEN_EXISTING, 0, NULL );
-    if( (HANDLE) dvdcss->i_fd == INVALID_HANDLE_VALUE )
+    if( WIN2K )
     {
-        _dvdcss_error( dvdcss, "failed opening device" );
-        return -1;
+        char sz_dvd[7];
+        _snprintf( sz_dvd, 7, "\\\\.\\%c:", psz_target[0] );
+        (HANDLE) dvdcss->i_fd =
+                CreateFile( sz_dvd, GENERIC_READ | GENERIC_WRITE,
+                                FILE_SHARE_READ | FILE_SHARE_WRITE,
+                                NULL, OPEN_EXISTING, 0, NULL );
+        if( (HANDLE) dvdcss->i_fd == INVALID_HANDLE_VALUE )
+        {
+            _dvdcss_error( dvdcss, "failed opening device" );
+            return -1;
+        }
+    }
+    else
+    {
+        dvdcss->i_fd = _win32_aopen( psz_target[0], dvdcss );
+        if( dvdcss->i_fd == -1 )
+        {
+            _dvdcss_error( dvdcss, "failed opening device" );
+            return -1;
+        }
     }
 
 #else
@@ -369,7 +398,14 @@
 static int _dvdcss_close ( dvdcss_handle dvdcss )
 {
 #if defined( WIN32 )
-    CloseHandle( (HANDLE) dvdcss->i_fd );
+    if( WIN2K )
+    {
+        CloseHandle( (HANDLE) dvdcss->i_fd );
+    }
+    else
+    {
+        _win32_aclose( dvdcss->i_fd );
+    }
 #else
     close( dvdcss->i_fd );
 #endif
@@ -382,9 +418,17 @@
     off_t i_read;
 
 #if defined( WIN32 )
-    i_read = SetFilePointer( (HANDLE) dvdcss->i_fd,
+    if( WIN2K )
+    {
+        i_read = SetFilePointer( (HANDLE) dvdcss->i_fd,
                              (off_t)i_blocks * (off_t)DVDCSS_BLOCK_SIZE,
                              NULL, FILE_BEGIN );
+    }
+    else
+    {
+        i_read = _win32_aseek( dvdcss->i_fd,
+                    (off_t)i_blocks * (off_t)DVDCSS_BLOCK_SIZE, SEEK_SET );
+    }
 #else
     i_read = lseek( dvdcss->i_fd,
                     (off_t)i_blocks * (off_t)DVDCSS_BLOCK_SIZE, SEEK_SET );
@@ -396,17 +440,25 @@
 
 static int _dvdcss_read ( dvdcss_handle dvdcss, void *p_buffer, int i_blocks )
 {
-#if defined( WIN32 )
-    DWORD i_read;
-    if( ReadFile( (HANDLE) dvdcss->i_fd, p_buffer,
+    off_t i_read;
+
+#if defined( WIN32 ) 
+    if( WIN2K )
+    {
+        if( ReadFile( (HANDLE) dvdcss->i_fd, p_buffer,
                   (off_t)i_blocks * (off_t)DVDCSS_BLOCK_SIZE,
                   &i_read, NULL ) == -1 )
+        {
+            return 0;
+        }
+    }
+    else
     {
-        return 0;
+        i_read = _win32_aread( dvdcss->i_fd, p_buffer,
+                   (off_t)i_blocks * (off_t)DVDCSS_BLOCK_SIZE );
     }
 
-#else
-    off_t i_read;
+#else   
     i_read = read( dvdcss->i_fd, p_buffer,
                    (off_t)i_blocks * (off_t)DVDCSS_BLOCK_SIZE );
 
@@ -418,8 +470,351 @@
 static int _dvdcss_readv ( dvdcss_handle dvdcss, struct iovec *p_iovec, int i_blocks )
 {
     off_t i_read;
+
+#if defined( WIN32 )
+    if( WIN2K )
+    {
+        i_read = _win32_readv( dvdcss->i_fd, p_iovec, i_blocks );
+    }
+    else
+    {
+        i_read = _win32_areadv( dvdcss->i_fd, p_iovec, i_blocks );
+    }
+#else
     i_read = readv( dvdcss->i_fd, p_iovec, i_blocks );
+#endif
 
     return i_read / DVDCSS_BLOCK_SIZE;
 }
 
+#if defined( WIN32 )
+
+/*****************************************************************************
+ * _win32_readv: vectored read using ReadFile instead of read
+ *****************************************************************************/
+static int _win32_readv( int i_fd, struct iovec *p_iovec, int i_blocks )
+{
+    int i_index, i_len, i_total = 0;
+    char *p_base;
+
+    for( i_index = i_blocks; i_index; i_index-- )
+    {
+        unsigned long i_bytes;
+
+        i_len  = p_iovec->iov_len;
+        p_base = p_iovec->iov_base;
+
+        /* Loop is unrolled one time to spare the (i_bytes < 0) test */
+        if( i_len > 0 )
+        {
+            if( !ReadFile( (HANDLE) i_fd, p_base, i_len, &i_bytes, NULL ) )
+            {
+                i_bytes = -1;
+            }
+
+            if( ( i_total == 0 ) && ( i_bytes < 0 ) )
+            {
+                return -1;
+            }
+
+            if( i_bytes <= 0 )
+            {
+                return i_total;
+            }
+
+            i_len   -= i_bytes;
+            i_total += i_bytes;
+            p_base  += i_bytes;
+
+            while( i_len > 0 )
+            {
+                if( !ReadFile( (HANDLE) i_fd, p_base, i_len, &i_bytes, NULL ) )
+                {
+                    return i_total;
+                }
+
+                i_len   -= i_bytes;
+                i_total += i_bytes;
+                p_base  += i_bytes;
+            }
+        }
+
+        p_iovec++;
+    }
+
+    return i_total;
+}
+
+/*****************************************************************************
+ * _win32_aopen: open dvd drive (load aspi and init w32_aspidev structure)
+ *****************************************************************************/
+static int _win32_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_pos = 0;
+    fd->hASPI = (long) hASPI;
+    fd->lpSendCommand = lpSendCommand;
+
+    if( !WIN2K )
+    {
+        fd->i_sid = MAKEWORD( ASPI_HAID, ASPI_TARGET );
+        return (int) fd;
+    }
+
+    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_aclose: close dvd drive (unload aspi and free w32_aspidev structure)
+ *****************************************************************************/
+static int _win32_aclose( int i_fd )
+{
+    struct w32_aspidev *fd = (struct w32_aspidev *) i_fd;
+
+    FreeLibrary( (HMODULE) fd->hASPI );
+    free( (void*) i_fd );
+
+    return 0;
+}
+
+/*****************************************************************************
+ * _win32_aseek: aspi version of lseek
+ *****************************************************************************/
+static int _win32_aseek( int i_fd, off_t i_pos, int i_method )
+{
+    int i_oldpos;
+    char sz_buf[ 2048 ];
+    struct w32_aspidev *fd = (struct w32_aspidev *) i_fd;
+    
+    i_oldpos = fd->i_pos;
+    fd->i_pos = i_pos;
+
+    if( _win32_aread( i_fd, sz_buf, sizeof(sz_buf) ) == -1 )
+    {
+        fd->i_pos = i_oldpos;
+        return -1;
+    }
+
+    fd->i_pos -= sizeof(sz_buf);
+
+    return fd->i_pos;
+}
+
+/*****************************************************************************
+ * _win32_aread: aspi version of read
+ *****************************************************************************/
+static int _win32_aread( int i_fd, void *p_data, int i_len )
+{
+    HANDLE hEvent;
+    char *p_buf = NULL;
+    DWORD dwStart, dwLen;
+    struct SRB_ExecSCSICmd ssc;
+    struct w32_aspidev *fd = (struct w32_aspidev *) i_fd;
+
+    memset( &ssc, 0, sizeof( ssc ) );
+
+    dwStart = fd->i_pos / 2048;
+    dwLen = ( i_len % 2048 ? ( i_len / 2048 ) + 1 : ( i_len / 2048 ) ) + 
+            (int)( fd->i_pos % 2048 ? 1 : 0 );
+
+    if( fd->i_pos % 2048 || i_len % 2048 )
+    {
+        p_buf = malloc( dwLen * 2048 );
+        if( p_buf == NULL )
+        {
+            return -1;
+        }
+    }
+
+    hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
+    if( hEvent == NULL )
+    {
+        if( p_buf != NULL )
+        {
+            free( p_buf );
+        }
+        return -1;
+    }
+
+    ssc.SRB_Cmd         = SC_EXEC_SCSI_CMD;
+    ssc.SRB_Flags       = SRB_DIR_IN | SRB_EVENT_NOTIFY;
+    ssc.SRB_HaId        = LOBYTE( fd->i_sid );
+    ssc.SRB_Target      = HIBYTE( fd->i_sid );
+    ssc.SRB_SenseLen    = SENSE_LEN;
+    ssc.SRB_PostProc    = (LPVOID) hEvent;
+
+    ssc.SRB_BufLen      = dwLen * 2048;
+    ssc.SRB_BufPointer  = p_buf ? p_buf : p_data;
+    ssc.SRB_CDBLen      = 12;
+
+    ssc.CDBByte[0]      = 0xA8; /* RAW */
+    ssc.CDBByte[2]      = (UCHAR) dwStart >> 24;
+    ssc.CDBByte[3]      = (UCHAR) (dwStart >> 16) & 0xff;
+    ssc.CDBByte[4]      = (UCHAR) (dwStart >> 8) & 0xff;
+    ssc.CDBByte[5]      = (UCHAR) (dwStart) & 0xff;
+    ssc.CDBByte[6]      = (UCHAR) dwLen >> 24;
+    ssc.CDBByte[7]      = (UCHAR) (dwLen >> 16) & 0xff;
+    ssc.CDBByte[8]      = (UCHAR) (dwLen >> 8) & 0xff;
+    ssc.CDBByte[9]      = (UCHAR) (dwLen) & 0xff;
+
+    ResetEvent( hEvent );
+    if( fd->lpSendCommand( (void*) &ssc ) == SS_PENDING )
+        WaitForSingleObject( hEvent, INFINITE );
+
+    CloseHandle( hEvent );
+
+    if( p_buf != NULL )
+    {
+        memcpy( p_data, p_buf + ( fd->i_pos - ( dwStart * 2048 ) ), i_len );
+        free( p_buf );
+    }
+
+    if(ssc.SRB_Status != SS_COMP)
+    {
+		return -1;
+    }
+	
+    fd->i_pos += i_len;
+
+    return i_len;
+}
+
+/*****************************************************************************
+ * _win32_areadv: aspi version of readv
+ *****************************************************************************/
+static int _win32_areadv( int i_fd, struct iovec *p_iovec, int i_blocks )
+{
+    int i_index, i_len, i_total = 0;
+    char *p_base;
+
+    for( i_index = i_blocks; i_index; i_index-- )
+    {
+        register signed int i_bytes;
+
+        i_len  = p_iovec->iov_len;
+        p_base = p_iovec->iov_base;
+
+        /* Loop is unrolled one time to spare the (i_bytes < 0) test */
+        if( i_len > 0 )
+        {
+            i_bytes = _win32_aread( i_fd, p_base, i_len );
+
+            if( ( i_total == 0 ) && ( i_bytes < 0 ) )
+            {
+                return -1;
+            }
+
+            if( i_bytes <= 0 )
+            {
+                return i_total;
+            }
+
+            i_len   -= i_bytes;
+            i_total += i_bytes;
+            p_base  += i_bytes;
+
+            while( i_len > 0 )
+            {
+                i_bytes = _win32_aread( i_fd, p_base, i_len );
+                
+                if( i_bytes <= 0 )
+                {
+                    return i_total;
+                }
+
+                i_len   -= i_bytes;
+                i_total += i_bytes;
+                p_base  += i_bytes;
+            }
+        }
+
+        p_iovec++;
+    }
+
+    return i_total;
+}
+
+#endif
diff -urN vlc.cvs/extras/libdvdcss/libdvdcss.h vlc/extras/libdvdcss/libdvdcss.h
--- vlc.cvs/extras/libdvdcss/libdvdcss.h	Thu Jun 14 02:22:03 2001
+++ vlc/extras/libdvdcss/libdvdcss.h	Thu Jun 14 02:22:18 2001
@@ -59,8 +59,13 @@
 /*****************************************************************************
  * Error management
  *****************************************************************************/
-#define DVDCSS_ERROR( x... ) fprintf( stderr, "libdvdcss error: %s\n", ##x );
-#define DVDCSS_DEBUG( x... ) fprintf( stderr, "libdvdcss debug: %s\n", ##x );
+#if defined( _WIN32 ) && defined( _MSC_VER )
+#   define DVDCSS_ERROR( x ) fprintf( stderr, "libdvdcss error: %s\n", x );
+#   define DVDCSS_DEBUG( x ) fprintf( stderr, "libdvdcss debug: %s\n", x );
+#else
+#   define DVDCSS_ERROR( x... ) fprintf( stderr, "libdvdcss error: %s\n", ##x );
+#   define DVDCSS_DEBUG( x... ) fprintf( stderr, "libdvdcss debug: %s\n", ##x );
+#endif
 
 static __inline__ void _dvdcss_error( dvdcss_handle dvdcss, char *psz_string )
 {
diff -urN vlc.cvs/plugins/dvd/input_dvd.c vlc/plugins/dvd/input_dvd.c
--- vlc.cvs/plugins/dvd/input_dvd.c	Thu Jun 14 02:22:03 2001
+++ vlc/plugins/dvd/input_dvd.c	Thu Jun 14 02:22:18 2001
@@ -157,11 +157,8 @@
     input_thread_t * p_input = (input_thread_t *)p_data;
 
     char * psz_name = p_input->p_source;
-    int i_handle;
+    dvdcss_handle dvdhandle;
     int i_score = 5;
-#if defined( WIN32 )
-    char buf[7];
-#endif
 
     if( TestMethod( INPUT_METHOD_VAR, "dvd" ) )
     {
@@ -183,25 +180,22 @@
         psz_name += 4;
     }
 
-#if !defined( WIN32 )
-    i_handle = open( psz_name, 0 );
-    if( i_handle == -1 )
+    dvdhandle = dvdcss_init( DVDCSS_INIT_QUIET );
+    if( dvdhandle == NULL )
     {
         return( 0 );
     }
-    close( i_handle );
-#else
-    snprintf( buf, 7, "\\\\.\\%c:", psz_name[0] );
-    (HANDLE) i_handle = CreateFile( i_score < 90 ? psz_name : buf, 
-                        GENERIC_READ | GENERIC_WRITE,
-                        FILE_SHARE_READ | FILE_SHARE_WRITE,
-                        NULL, OPEN_EXISTING, 0, NULL );
-    if( (HANDLE) i_handle == INVALID_HANDLE_VALUE )
+
+    if( dvdcss_open( dvdhandle, psz_name ) < 0 )
     {
-        return( 0 );
+        i_score = 0;
     }
-    CloseHandle( (HANDLE) i_handle );
-#endif
+    else
+    {
+        dvdcss_close( dvdhandle );
+    }
+
+    dvdcss_end( dvdhandle );
 
     return( i_score );
 }
diff -urN vlc.cvs/src/input/input.c vlc/src/input/input.c
--- vlc.cvs/src/input/input.c	Thu Jun 14 02:22:03 2001
+++ vlc/src/input/input.c	Thu Jun 14 02:22:18 2001
@@ -518,10 +518,6 @@
     struct stat         stat_info;
     int                 i_stat;
 
-#if defined( WIN32 )
-    char buf[7] = { 0 };
-#endif
-
     char *psz_name = p_input->p_source;
 
     /* FIXME: this code ought to be in the plugin so that code can
@@ -536,9 +532,6 @@
             /* get rid of the 'dvd:' stuff and try again */
             psz_name += 4;
             i_stat = stat( psz_name, &stat_info );
-#if defined( WIN32 )
-            _snprintf( buf, 7, "\\\\.\\%c:", psz_name[0] );
-#endif
         }
         else if( ( i_size > 5 )
                  && !strncasecmp( psz_name, "file:", 5 ) )
@@ -548,11 +541,7 @@
             i_stat = stat( psz_name, &stat_info );
         }
 
-        if( i_stat == (-1) 
-#if defined( WIN32 )
-        && !buf[0]      
-#endif
-            )
+        if( i_stat == (-1) )
         {
             intf_ErrMsg( "input error: cannot stat() file `%s' (%s)",
                          psz_name, strerror(errno));
@@ -567,11 +556,7 @@
     p_input->stream.b_pace_control = 1;
 
     if( S_ISREG(stat_info.st_mode) || S_ISCHR(stat_info.st_mode)
-         || S_ISBLK(stat_info.st_mode)
-#if defined( WIN32 )
-         || ( buf[0] && ( ( stat_info.st_size = 0 ) == 0 ) )
-#endif
-         )
+         || S_ISBLK(stat_info.st_mode) )
     {
         p_input->stream.b_seekable = 1;
         p_input->stream.p_selected_area->i_size = stat_info.st_size;
@@ -598,14 +583,11 @@
     vlc_mutex_unlock( &p_input->stream.stream_lock );
 
     intf_WarnMsg( 1, "input: opening file `%s'", p_input->p_source );
-#ifndef WIN32
+#if defined( WIN32 )
+    if( (p_input->i_handle = open( psz_name, O_BINARY ) ) == (-1) )
+#else
     if( (p_input->i_handle = open( psz_name,
                                    /*O_NONBLOCK | O_LARGEFILE*/0 )) == (-1) )
-#else
-    if( ( buf[0] && ( (HANDLE) p_input->i_handle = CreateFile( buf, 
-        GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 
-        NULL, OPEN_EXISTING, 0, NULL ) ) == INVALID_HANDLE_VALUE ) ||
-        ( !buf[0] && (p_input->i_handle = open( psz_name, O_BINARY ) ) == (-1) ) )
 #endif
     {
         intf_ErrMsg( "input error: cannot open file (%s)", strerror(errno) );
@@ -621,14 +603,7 @@
 static void FileClose( input_thread_t * p_input )
 {
     intf_WarnMsg( 1, "input: closing file `%s'", p_input->p_source );
-#if defined( WIN32 )
-    if( ( strlen( p_input->p_source ) > 4 ) &&
-        !strncasecmp( p_input->p_source, "dvd:", 4 ) )
-    {
-        CloseHandle( (HANDLE) p_input->i_handle );
-    }
-    else
-#endif
+
     close( p_input->i_handle );
 
     return;
diff -urN vlc.cvs/src/misc/modules.c vlc/src/misc/modules.c
--- vlc.cvs/src/misc/modules.c	Thu Jun 14 02:22:03 2001
+++ vlc/src/misc/modules.c	Thu Jun 14 02:22:18 2001
@@ -45,7 +45,7 @@
 #elif defined(HAVE_IMAGE_H)                                          /* BeOS */
 #   include <image.h>
 #   define HAVE_DYNAMIC_PLUGINS
-#elif defined(WIN32)
+#elif defined(WIN32) && defined( __MINGW32__ )
 #   define HAVE_DYNAMIC_PLUGINS
 #else
 #   undef HAVE_DYNAMIC_PLUGINS



