diff libmpdvdkit2/ioctl.c @ 9333:f0f0f176d298

sync with libdvdcss 1.2.5 (including u8->uint8_t and whitespace cosmetics...) patch by Andreas Hess <jaska@gmx.net>
author arpi
date Sat, 08 Feb 2003 00:22:39 +0000
parents c932c17042bf
children 7b0bc557987b
line wrap: on
line diff
--- a/libmpdvdkit2/ioctl.c	Sat Feb 08 00:00:00 2003 +0000
+++ b/libmpdvdkit2/ioctl.c	Sat Feb 08 00:22:39 2003 +0000
@@ -121,8 +121,9 @@
  * Local prototypes, win32 (aspi) specific
  *****************************************************************************/
 #if defined( WIN32 )
-static void WinInitSSC ( struct SRB_ExecSCSICmd *, int );
-static int  WinSendSSC ( int, struct SRB_ExecSCSICmd * );
+static void WinInitSPTD ( SCSI_PASS_THROUGH_DIRECT *, int );
+static void WinInitSSC  ( struct SRB_ExecSCSICmd *, int );
+static int  WinSendSSC  ( int, struct SRB_ExecSCSICmd * );
 #endif
 
 /*****************************************************************************
@@ -190,7 +191,7 @@
 
 #elif defined( SOLARIS_USCSI )
     INIT_USCSI( GPCMD_READ_DVD_STRUCTURE, 8 );
-    
+
     rs_cdb.cdb_opaque[ 6 ] = i_layer;
     rs_cdb.cdb_opaque[ 7 ] = DVD_STRUCT_COPYRIGHT;
 
@@ -199,7 +200,7 @@
     if( i_ret < 0 || sc.uscsi_status ) {
         i_ret = -1;
     }
-    
+
     *pi_copyright = p_buffer[ 4 ];
     /* s->copyright.rmi = p_buffer[ 5 ]; */
 
@@ -216,41 +217,23 @@
 #elif defined( WIN32 )
     if( WIN2K ) /* NT/2k/XP */
     {
-        DWORD tmp;
-        u8 p_buffer[ 8 ];
-        SCSI_PASS_THROUGH_DIRECT sptd;
-
-        /*  When using IOCTL_DVD_READ_STRUCTURE and 
+        INIT_SPTD( GPCMD_READ_DVD_STRUCTURE, 8 );
+
+        /*  When using IOCTL_DVD_READ_STRUCTURE and
             DVD_COPYRIGHT_DESCRIPTOR, CopyrightProtectionType
             seems to be always 6 ???
-            To work around this M$ bug we try to send a raw scsi command
+            To work around this MS bug we try to send a raw scsi command
             instead (if we've got enough privileges to do so). */
 
-        memset( &sptd, 0, sizeof( sptd ) );
-        memset( &p_buffer, 0, sizeof( p_buffer ) );
-
-        sptd.Length             = sizeof( SCSI_PASS_THROUGH_DIRECT );
-        sptd.CdbLength          = 12;
-        sptd.DataIn             = SCSI_IOCTL_DATA_IN;
-        sptd.DataTransferLength = 8;
-        sptd.TimeOutValue       = 2;
-        sptd.DataBuffer         = p_buffer;
-        sptd.Cdb[ 0 ]           = GPCMD_READ_DVD_STRUCTURE;
-        sptd.Cdb[ 6 ]           = i_layer;
-        sptd.Cdb[ 7 ]           = DVD_STRUCT_COPYRIGHT;
-        sptd.Cdb[ 8 ]           = (8 >> 8) & 0xff;
-        sptd.Cdb[ 9 ]           =  8       & 0xff;
-
-        i_ret = DeviceIoControl( (HANDLE) i_fd,
-                             IOCTL_SCSI_PASS_THROUGH_DIRECT,
-                             &sptd, sizeof( SCSI_PASS_THROUGH_DIRECT ),
-                             &sptd, sizeof( SCSI_PASS_THROUGH_DIRECT ),
-                             &tmp, NULL ) ? 0 : -1;
+        sptd.Cdb[ 6 ] = i_layer;
+        sptd.Cdb[ 7 ] = DVD_STRUCT_COPYRIGHT;
+
+        i_ret = SEND_SPTD( i_fd, &sptd, &tmp );
 
         if( i_ret == 0 )
         {
-        *pi_copyright = p_buffer[ 4 ];
-    }
+            *pi_copyright = p_buffer[ 4 ];
+        }
     }
     else
     {
@@ -297,7 +280,7 @@
 /*****************************************************************************
  * ioctl_ReadDiscKey: get the disc key
  *****************************************************************************/
-int ioctl_ReadDiscKey( int i_fd, int *pi_agid, u8 *p_key )
+int ioctl_ReadDiscKey( int i_fd, int *pi_agid, uint8_t *p_key )
 {
     int i_ret;
 
@@ -340,7 +323,7 @@
 
     rdc.command[ 7 ]  = DVD_STRUCT_DISCKEY;
     rdc.command[ 10 ] = *pi_agid << 6;
-    
+
     i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
 
     if( i_ret < 0 )
@@ -355,7 +338,7 @@
 
     sctl_io.cdb[ 7 ]  = DVD_STRUCT_DISCKEY;
     sctl_io.cdb[ 10 ] = *pi_agid << 6;
-    
+
     i_ret = ioctl( i_fd, SIOC_IO, &sctl_io );
 
     if( i_ret < 0 )
@@ -367,12 +350,12 @@
 
 #elif defined( SOLARIS_USCSI )
     INIT_USCSI( GPCMD_READ_DVD_STRUCTURE, DVD_DISCKEY_SIZE + 4 );
-    
+
     rs_cdb.cdb_opaque[ 7 ] = DVD_STRUCT_DISCKEY;
     rs_cdb.cdb_opaque[ 10 ] = *pi_agid << 6;
-    
+
     i_ret = SolarisSendUSCSI( i_fd, &sc );
-    
+
     if( i_ret < 0 || sc.uscsi_status )
     {
         i_ret = -1;
@@ -384,7 +367,7 @@
 #elif defined( DARWIN_DVD_IOCTL )
     INIT_DVDIOCTL( dk_dvd_read_structure_t, DVDDiscKeyInfo,
                    kDVDStructureFormatDiscKeyInfo );
-  
+
     dvd.grantID = *pi_agid;
 
     i_ret = ioctl( i_fd, DKIOCDVDREADSTRUCTURE, &dvd );
@@ -395,7 +378,7 @@
     if( WIN2K ) /* NT/2k/XP */
     {
         DWORD tmp;
-        u8 buffer[DVD_DISK_KEY_LENGTH];
+        uint8_t buffer[DVD_DISK_KEY_LENGTH];
         PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
 
         memset( &buffer, 0, sizeof( buffer ) );
@@ -405,11 +388,11 @@
         key->KeyType    = DvdDiskKey;
         key->KeyFlags   = 0;
 
-        i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key, 
+        i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key,
                 key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
 
         if( i_ret < 0 )
-        {   
+        {
             return i_ret;
         }
 
@@ -421,7 +404,7 @@
 
         ssc.CDBByte[ 7 ]  = DVD_STRUCT_DISCKEY;
         ssc.CDBByte[ 10 ] = *pi_agid << 6;
-    
+
         i_ret = WinSendSSC( i_fd, &ssc );
 
         if( i_ret < 0 )
@@ -448,7 +431,7 @@
 
     sdc.command[ 7 ]  = DVD_STRUCT_DISCKEY;
     sdc.command[ 10 ] = *pi_agid << 6;
-    
+
     i_ret = DosDevIOCtl(i_fd, IOCTL_CDROMDISK, CDROMDISK_EXECMD,
                         &sdc, sizeof(sdc), &ulParamLen,
                         p_buffer, sizeof(p_buffer), &ulDataLen);
@@ -470,7 +453,7 @@
 /*****************************************************************************
  * ioctl_ReadTitleKey: get the title key
  *****************************************************************************/
-int ioctl_ReadTitleKey( int i_fd, int *pi_agid, int i_pos, u8 *p_key )
+int ioctl_ReadTitleKey( int i_fd, int *pi_agid, int i_pos, uint8_t *p_key )
 {
     int i_ret;
 
@@ -526,15 +509,15 @@
 
 #elif defined( SOLARIS_USCSI )
     INIT_USCSI( GPCMD_REPORT_KEY, 12 );
-    
+
     rs_cdb.cdb_opaque[ 2 ] = ( i_pos >> 24 ) & 0xff;
     rs_cdb.cdb_opaque[ 3 ] = ( i_pos >> 16 ) & 0xff;
     rs_cdb.cdb_opaque[ 4 ] = ( i_pos >>  8 ) & 0xff;
     rs_cdb.cdb_opaque[ 5 ] = ( i_pos       ) & 0xff;
     rs_cdb.cdb_opaque[ 10 ] = DVD_REPORT_TITLE_KEY | (*pi_agid << 6);
-    
+
     i_ret = SolarisSendUSCSI( i_fd, &sc );
-    
+
     if( i_ret < 0 || sc.uscsi_status )
     {
         i_ret = -1;
@@ -544,9 +527,9 @@
     /* a->lstk.cpm    = (buf[ 4 ] >> 7) & 1; */
     /* a->lstk.cp_sec = (buf[ 4 ] >> 6) & 1; */
     /* a->lstk.cgms   = (buf[ 4 ] >> 4) & 3; */
- 
-    memcpy( p_key, p_buffer + 5, DVD_KEY_SIZE ); 
-    
+
+    memcpy( p_key, p_buffer + 5, DVD_KEY_SIZE );
+
 #elif defined( DARWIN_DVD_IOCTL )
     INIT_DVDIOCTL( dk_dvd_report_key_t, DVDTitleKeyInfo,
                    kDVDKeyFormatTitleKey );
@@ -563,7 +546,7 @@
     if( WIN2K ) /* NT/2k/XP */
     {
         DWORD tmp;
-        u8 buffer[DVD_BUS_KEY_LENGTH];
+        uint8_t buffer[DVD_TITLE_KEY_LENGTH];
         PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
 
         memset( &buffer, 0, sizeof( buffer ) );
@@ -575,7 +558,7 @@
         key->Parameters.TitleOffset.QuadPart = (LONGLONG) i_pos *
                                                    2048 /*DVDCSS_BLOCK_SIZE*/;
 
-        i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key, 
+        i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key,
                 key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
 
         memcpy( p_key, key->KeyData, DVD_KEY_SIZE );
@@ -682,22 +665,22 @@
 
 #elif defined( SOLARIS_USCSI )
     INIT_USCSI( GPCMD_REPORT_KEY, 8 );
-    
+
     rs_cdb.cdb_opaque[ 10 ] = DVD_REPORT_AGID | (*pi_agid << 6);
-    
+
     i_ret = SolarisSendUSCSI( i_fd, &sc );
-    
+
     if( i_ret < 0 || sc.uscsi_status )
     {
         i_ret = -1;
     }
 
     *pi_agid = p_buffer[ 7 ] >> 6;
-    
+
 #elif defined( DARWIN_DVD_IOCTL )
     INIT_DVDIOCTL( dk_dvd_report_key_t, DVDAuthenticationGrantIDInfo,
                    kDVDKeyFormatAGID_CSS );
-  
+
     dvd.grantID = *pi_agid;
     dvd.keyClass = kDVDKeyClassCSS_CPPM_CPRM;
 
@@ -711,7 +694,7 @@
         ULONG id;
         DWORD tmp;
 
-        i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_START_SESSION, 
+        i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_START_SESSION,
                         &tmp, 4, &id, sizeof( id ), &tmp, NULL ) ? 0 : -1;
 
         *pi_agid = id;
@@ -758,7 +741,7 @@
 /*****************************************************************************
  * ioctl_ReportChallenge: get challenge from the drive
  *****************************************************************************/
-int ioctl_ReportChallenge( int i_fd, int *pi_agid, u8 *p_challenge )
+int ioctl_ReportChallenge( int i_fd, int *pi_agid, uint8_t *p_challenge )
 {
     int i_ret;
 
@@ -804,22 +787,22 @@
 
 #elif defined( SOLARIS_USCSI )
     INIT_USCSI( GPCMD_REPORT_KEY, 16 );
-    
+
     rs_cdb.cdb_opaque[ 10 ] = DVD_REPORT_CHALLENGE | (*pi_agid << 6);
-    
+
     i_ret = SolarisSendUSCSI( i_fd, &sc );
-    
+
     if( i_ret < 0 || sc.uscsi_status )
     {
         i_ret = -1;
     }
 
     memcpy( p_challenge, p_buffer + 4, DVD_CHALLENGE_SIZE );
-    
+
 #elif defined( DARWIN_DVD_IOCTL )
     INIT_DVDIOCTL( dk_dvd_report_key_t, DVDChallengeKeyInfo,
                    kDVDKeyFormatChallengeKey );
-  
+
     dvd.grantID = *pi_agid;
 
     i_ret = ioctl( i_fd, DKIOCDVDREPORTKEY, &dvd );
@@ -830,7 +813,7 @@
     if( WIN2K ) /* NT/2k/XP */
     {
         DWORD tmp;
-        u8 buffer[DVD_CHALLENGE_KEY_LENGTH];
+        uint8_t buffer[DVD_CHALLENGE_KEY_LENGTH];
         PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
 
         memset( &buffer, 0, sizeof( buffer ) );
@@ -840,7 +823,7 @@
         key->KeyType    = DvdChallengeKey;
         key->KeyFlags   = 0;
 
-        i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key, 
+        i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key,
                 key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
 
         if( i_ret < 0 )
@@ -938,22 +921,22 @@
 
 #elif defined( SOLARIS_USCSI )
     INIT_USCSI( GPCMD_REPORT_KEY, 8 );
-    
+
     rs_cdb.cdb_opaque[ 10 ] = DVD_REPORT_ASF;
-    
+
     i_ret = SolarisSendUSCSI( i_fd, &sc );
-    
+
     if( i_ret < 0 || sc.uscsi_status )
     {
         i_ret = -1;
     }
 
     *pi_asf = p_buffer[ 7 ] & 1;
-    
+
 #elif defined( DARWIN_DVD_IOCTL )
     INIT_DVDIOCTL( dk_dvd_report_key_t, DVDAuthenticationSuccessFlagInfo,
                    kDVDKeyFormatASF );
-  
+
     i_ret = ioctl( i_fd, DKIOCDVDREPORTKEY, &dvd );
 
     *pi_asf = dvdbs.successFlag;
@@ -962,7 +945,7 @@
     if( WIN2K ) /* NT/2k/XP */
     {
         DWORD tmp;
-        u8 buffer[DVD_ASF_LENGTH];
+        uint8_t buffer[DVD_ASF_LENGTH];
         PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
 
         memset( &buffer, 0, sizeof( buffer ) );
@@ -973,7 +956,7 @@
 
         ((PDVD_ASF)key->KeyData)->SuccessFlag = *pi_asf;
 
-        i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key, 
+        i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key,
                 key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
 
         if( i_ret < 0 )
@@ -1025,7 +1008,7 @@
 /*****************************************************************************
  * ioctl_ReportKey1: get the first key from the drive
  *****************************************************************************/
-int ioctl_ReportKey1( int i_fd, int *pi_agid, u8 *p_key )
+int ioctl_ReportKey1( int i_fd, int *pi_agid, uint8_t *p_key )
 {
     int i_ret;
 
@@ -1071,24 +1054,24 @@
 
 #elif defined( SOLARIS_USCSI )
     INIT_USCSI( GPCMD_REPORT_KEY, 12 );
-    
+
     rs_cdb.cdb_opaque[ 10 ] = DVD_REPORT_KEY1 | (*pi_agid << 6);
-    
+
     i_ret = SolarisSendUSCSI( i_fd, &sc );
-    
+
     if( i_ret < 0 || sc.uscsi_status )
     {
         i_ret = -1;
     }
 
     memcpy( p_key, p_buffer + 4, DVD_KEY_SIZE );
-    
+
 #elif defined( DARWIN_DVD_IOCTL )
     INIT_DVDIOCTL( dk_dvd_report_key_t, DVDKey1Info,
                    kDVDKeyFormatKey1 );
-  
+
     dvd.grantID = *pi_agid;
-  
+
     i_ret = ioctl( i_fd, DKIOCDVDREPORTKEY, &dvd );
 
     memcpy( p_key, dvdbs.key1Value, DVD_KEY_SIZE );
@@ -1097,7 +1080,7 @@
     if( WIN2K ) /* NT/2k/XP */
     {
         DWORD tmp;
-        u8 buffer[DVD_BUS_KEY_LENGTH];
+        uint8_t buffer[DVD_BUS_KEY_LENGTH];
         PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
 
         memset( &buffer, 0, sizeof( buffer ) );
@@ -1107,7 +1090,7 @@
         key->KeyType    = DvdBusKey1;
         key->KeyFlags   = 0;
 
-        i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key, 
+        i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key,
                 key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
 
         memcpy( p_key, key->KeyData, DVD_KEY_SIZE );
@@ -1192,11 +1175,11 @@
 
 #elif defined( SOLARIS_USCSI )
     INIT_USCSI( GPCMD_REPORT_KEY, 0 );
-    
+
     rs_cdb.cdb_opaque[ 10 ] = DVD_INVALIDATE_AGID | (*pi_agid << 6);
-    
+
     i_ret = SolarisSendUSCSI( i_fd, &sc );
-    
+
     if( i_ret < 0 || sc.uscsi_status )
     {
         i_ret = -1;
@@ -1205,9 +1188,9 @@
 #elif defined( DARWIN_DVD_IOCTL )
     INIT_DVDIOCTL( dk_dvd_send_key_t, DVDAuthenticationGrantIDInfo,
                    kDVDKeyFormatAGID_Invalidate );
-  
+
     dvd.grantID = *pi_agid;
-  
+
     i_ret = ioctl( i_fd, DKIOCDVDSENDKEY, &dvd );
 
 #elif defined( WIN32 )
@@ -1215,7 +1198,7 @@
     {
         DWORD tmp;
 
-        i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_END_SESSION, 
+        i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_END_SESSION,
                     pi_agid, sizeof( *pi_agid ), NULL, 0, &tmp, NULL ) ? 0 : -1;
     }
     else
@@ -1265,7 +1248,7 @@
 /*****************************************************************************
  * ioctl_SendChallenge: send challenge to the drive
  *****************************************************************************/
-int ioctl_SendChallenge( int i_fd, int *pi_agid, u8 *p_challenge )
+int ioctl_SendChallenge( int i_fd, int *pi_agid, uint8_t *p_challenge )
 {
     int i_ret;
 
@@ -1278,7 +1261,7 @@
 
     memcpy( auth_info.hsc.chal, p_challenge, DVD_CHALLENGE_SIZE );
 
-    return ioctl( i_fd, DVD_AUTH, &auth_info );
+    i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
 
 #elif defined( HAVE_BSD_DVD_STRUCT )
     struct dvd_authinfo auth_info;
@@ -1289,7 +1272,7 @@
 
     memcpy( auth_info.keychal, p_challenge, DVD_CHALLENGE_SIZE );
 
-    return ioctl( i_fd, DVDIOCSENDKEY, &auth_info );
+    i_ret = ioctl( i_fd, DVDIOCSENDKEY, &auth_info );
 
 #elif defined( SYS_BEOS )
     INIT_RDC( GPCMD_SEND_KEY, 16 );
@@ -1299,7 +1282,7 @@
     p_buffer[ 1 ] = 0xe;
     memcpy( p_buffer + 4, p_challenge, DVD_CHALLENGE_SIZE );
 
-    return ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
+    i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
 
 #elif defined( HPUX_SCTL_IO )
     INIT_SCTL_IO( GPCMD_SEND_KEY, 16 );
@@ -1309,27 +1292,27 @@
     p_buffer[ 1 ] = 0xe;
     memcpy( p_buffer + 4, p_challenge, DVD_CHALLENGE_SIZE );
 
-    return ioctl( i_fd, SIOC_IO, &sctl_io );
+    i_ret = ioctl( i_fd, SIOC_IO, &sctl_io );
 
 #elif defined( SOLARIS_USCSI )
     INIT_USCSI( GPCMD_SEND_KEY, 16 );
-    
+
     rs_cdb.cdb_opaque[ 10 ] = DVD_SEND_CHALLENGE | (*pi_agid << 6);
-    
+
     p_buffer[ 1 ] = 0xe;
     memcpy( p_buffer + 4, p_challenge, DVD_CHALLENGE_SIZE );
-    
+
     if( SolarisSendUSCSI( i_fd, &sc ) < 0 || sc.uscsi_status )
     {
         return -1;
     }
 
-    return 0;
-    
+    i_ret = 0;
+
 #elif defined( DARWIN_DVD_IOCTL )
     INIT_DVDIOCTL( dk_dvd_send_key_t, DVDChallengeKeyInfo,
                    kDVDKeyFormatChallengeKey );
-  
+
     dvd.grantID = *pi_agid;
     dvd.keyClass = kDVDKeyClassCSS_CPPM_CPRM;
 
@@ -1342,7 +1325,7 @@
     if( WIN2K ) /* NT/2k/XP */
     {
         DWORD tmp;
-        u8 buffer[DVD_CHALLENGE_KEY_LENGTH];
+        uint8_t buffer[DVD_CHALLENGE_KEY_LENGTH];
         PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
 
         memset( &buffer, 0, sizeof( buffer ) );
@@ -1354,8 +1337,8 @@
 
         memcpy( key->KeyData, p_challenge, DVD_CHALLENGE_SIZE );
 
-        return DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_SEND_KEY, key, 
-                key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
+        i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_SEND_KEY, key,
+                 key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
     }
     else
     {
@@ -1366,7 +1349,7 @@
         p_buffer[ 1 ] = 0xe;
         memcpy( p_buffer + 4, p_challenge, DVD_CHALLENGE_SIZE );
 
-        return WinSendSSC( i_fd, &ssc );
+        i_ret = WinSendSSC( i_fd, &ssc );
     }
 
 #elif defined( __QNXNTO__ )
@@ -1388,9 +1371,9 @@
     p_buffer[ 1 ] = 0xe;
     memcpy( p_buffer + 4, p_challenge, DVD_CHALLENGE_SIZE );
 
-    return DosDevIOCtl(i_fd, IOCTL_CDROMDISK, CDROMDISK_EXECMD,
-                       &sdc, sizeof(sdc), &ulParamLen,
-                       p_buffer, sizeof(p_buffer), &ulDataLen);
+    i_ret = DosDevIOCtl( i_fd, IOCTL_CDROMDISK, CDROMDISK_EXECMD,
+                         &sdc, sizeof(sdc), &ulParamLen,
+                         p_buffer, sizeof(p_buffer), &ulDataLen );
 
 #else
 #   error "DVD ioctls are unavailable on this system"
@@ -1402,7 +1385,7 @@
 /*****************************************************************************
  * ioctl_SendKey2: send the second key to the drive
  *****************************************************************************/
-int ioctl_SendKey2( int i_fd, int *pi_agid, u8 *p_key )
+int ioctl_SendKey2( int i_fd, int *pi_agid, uint8_t *p_key )
 {
     int i_ret;
 
@@ -1415,7 +1398,7 @@
 
     memcpy( auth_info.hsk.key, p_key, DVD_KEY_SIZE );
 
-    return ioctl( i_fd, DVD_AUTH, &auth_info );
+    i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
 
 #elif defined( HAVE_BSD_DVD_STRUCT )
     struct dvd_authinfo auth_info;
@@ -1426,7 +1409,7 @@
 
     memcpy( auth_info.keychal, p_key, DVD_KEY_SIZE );
 
-    return ioctl( i_fd, DVDIOCSENDKEY, &auth_info );
+    i_ret = ioctl( i_fd, DVDIOCSENDKEY, &auth_info );
 
 #elif defined( SYS_BEOS )
     INIT_RDC( GPCMD_SEND_KEY, 12 );
@@ -1436,7 +1419,7 @@
     p_buffer[ 1 ] = 0xa;
     memcpy( p_buffer + 4, p_key, DVD_KEY_SIZE );
 
-    return ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
+    i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
 
 #elif defined( HPUX_SCTL_IO )
     INIT_SCTL_IO( GPCMD_SEND_KEY, 12 );
@@ -1446,23 +1429,23 @@
     p_buffer[ 1 ] = 0xa;
     memcpy( p_buffer + 4, p_key, DVD_KEY_SIZE );
 
-    return ioctl( i_fd, SIOC_IO, &sctl_io );
+    i_ret = ioctl( i_fd, SIOC_IO, &sctl_io );
 
 #elif defined( SOLARIS_USCSI )
     INIT_USCSI( GPCMD_SEND_KEY, 12 );
-    
+
     rs_cdb.cdb_opaque[ 10 ] = DVD_SEND_KEY2 | (*pi_agid << 6);
-    
+
     p_buffer[ 1 ] = 0xa;
     memcpy( p_buffer + 4, p_key, DVD_KEY_SIZE );
-    
+
     if( SolarisSendUSCSI( i_fd, &sc ) < 0 || sc.uscsi_status )
     {
         return -1;
     }
 
-    return 0;
-    
+    i_ret = 0;
+
 #elif defined( DARWIN_DVD_IOCTL )
     INIT_DVDIOCTL( dk_dvd_send_key_t, DVDKey2Info,
                    kDVDKeyFormatKey2 );
@@ -1479,7 +1462,7 @@
     if( WIN2K ) /* NT/2k/XP */
     {
         DWORD tmp;
-        u8 buffer[DVD_BUS_KEY_LENGTH];
+        uint8_t buffer[DVD_BUS_KEY_LENGTH];
         PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
 
         memset( &buffer, 0, sizeof( buffer ) );
@@ -1491,8 +1474,8 @@
 
         memcpy( key->KeyData, p_key, DVD_KEY_SIZE );
 
-        return DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_SEND_KEY, key, 
-                key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
+        i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_SEND_KEY, key,
+                 key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
     }
     else
     {
@@ -1503,7 +1486,7 @@
         p_buffer[ 1 ] = 0xa;
         memcpy( p_buffer + 4, p_key, DVD_KEY_SIZE );
 
-        return WinSendSSC( i_fd, &ssc );
+        i_ret = WinSendSSC( i_fd, &ssc );
     }
 
 #elif defined( __QNXNTO__ )
@@ -1525,9 +1508,9 @@
     p_buffer[ 1 ] = 0xa;
     memcpy( p_buffer + 4, p_key, DVD_KEY_SIZE );
 
-    return DosDevIOCtl(i_fd, IOCTL_CDROMDISK, CDROMDISK_EXECMD,
-                       &sdc, sizeof(sdc), &ulParamLen,
-                       p_buffer, sizeof(p_buffer), &ulDataLen);
+    i_ret = DosDevIOCtl( i_fd, IOCTL_CDROMDISK, CDROMDISK_EXECMD,
+                         &sdc, sizeof(sdc), &ulParamLen,
+                         p_buffer, sizeof(p_buffer), &ulDataLen );
 
 #else
 #   error "DVD ioctls are unavailable on this system"
@@ -1595,20 +1578,20 @@
 
 #elif defined( SOLARIS_USCSI )
     INIT_USCSI( GPCMD_REPORT_KEY, 8 );
-    
+
     rs_cdb.cdb_opaque[ 10 ] = DVD_REPORT_RPC;
-    
+
     i_ret = SolarisSendUSCSI( i_fd, &sc );
-    
+
     if( i_ret < 0 || sc.uscsi_status )
     {
         i_ret = -1;
     }
-    
+
     *p_type = p_buffer[ 4 ] >> 6;
     *p_mask = p_buffer[ 5 ];
     *p_scheme = p_buffer[ 6 ];
-    
+
 #elif defined( DARWIN_DVD_IOCTL )
     INIT_DVDIOCTL( dk_dvd_report_key_t, DVDRegionPlaybackControlInfo,
                    kDVDKeyFormatRegionState );
@@ -1625,28 +1608,26 @@
     if( WIN2K ) /* NT/2k/XP */
     {
         DWORD tmp;
-        u8 buffer[ DVD_REGION_LENGTH ];
-        PDVD_REGION region = (PDVD_REGION) &buffer;
+        uint8_t buffer[DVD_RPC_KEY_LENGTH];
+        PDVD_COPY_PROTECT_KEY key = (PDVD_COPY_PROTECT_KEY) &buffer;
 
         memset( &buffer, 0, sizeof( buffer ) );
 
-        i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_GET_REGION, NULL, 0,
-                region, DVD_REGION_LENGTH, &tmp, NULL ) ? 0 : -1;
-
-        /* Someone who has the headers should correct all this. */
-        /* Use the IOCTL_SCSI_PASS_THROUGH_DIRECT so we get the real
-         * values of theses entities?  */
-        if(region->SystemRegion != 0) {
-            *p_type = region->ResetCount > 1 ? 1 : 3 - region->ResetCount;
-            *p_mask =  0xff ^ (1 << (region->SystemRegion - 1));
-            *p_scheme = 1;
+        key->KeyLength  = DVD_RPC_KEY_LENGTH;
+        key->KeyType    = DvdGetRpcKey;
+        key->KeyFlags   = 0;
+
+        i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key,
+                key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
+
+        if( i_ret < 0 )
+        {
+            return i_ret;
         }
-        else
-        {
-            *p_type = 0;  /* ?? */
-            *p_mask = 0xff;
-            *p_scheme = 1; /* ?? */
-        }
+
+        *p_type = ((PDVD_RPC_KEY)key->KeyData)->TypeCode;
+        *p_mask = ((PDVD_RPC_KEY)key->KeyData)->RegionMask;
+        *p_scheme = ((PDVD_RPC_KEY)key->KeyData)->RpcScheme;
     }
     else
     {
@@ -1693,6 +1674,133 @@
     return i_ret;
 }
 
+/*****************************************************************************
+ * ioctl_SendRPC: set RPC status for the drive
+ *****************************************************************************/
+int ioctl_SendRPC( int i_fd, int i_pdrc )
+{
+    int i_ret;
+
+#if defined( HAVE_LINUX_DVD_STRUCT ) && defined( DVD_HOST_SEND_RPC_STATE )
+    dvd_authinfo auth_info;
+
+    memset( &auth_info, 0, sizeof( auth_info ) );
+    auth_info.type = DVD_HOST_SEND_RPC_STATE;
+    auth_info.hrpcs.pdrc = i_pdrc;
+
+    i_ret = ioctl( i_fd, DVD_AUTH, &auth_info );
+
+#elif defined( HAVE_LINUX_DVD_STRUCT )
+    /* FIXME: OpenBSD doesn't know this */
+    i_ret = -1;
+
+#elif defined( HAVE_BSD_DVD_STRUCT )
+    struct dvd_authinfo auth_info;
+
+    memset( &auth_info, 0, sizeof( auth_info ) );
+    auth_info.format = DVD_SEND_RPC;
+    auth_info.region = i_pdrc;
+
+    i_ret = ioctl( i_fd, DVDIOCSENDKEY, &auth_info );
+
+#elif defined( SYS_BEOS )
+    INIT_RDC( GPCMD_SEND_KEY, 8 );
+
+    rdc.command[ 10 ] = DVD_SEND_RPC;
+
+    p_buffer[ 1 ] = 6;
+    p_buffer[ 4 ] = i_pdrc;
+
+    i_ret = ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
+
+#elif defined( HPUX_SCTL_IO )
+    INIT_SCTL_IO( GPCMD_SEND_KEY, 8 );
+
+    sctl_io.cdb[ 10 ] = DVD_SEND_RPC;
+
+    p_buffer[ 1 ] = 6;
+    p_buffer[ 4 ] = i_pdrc;
+
+    i_ret = ioctl( i_fd, SIOC_IO, &sctl_io );
+
+#elif defined( SOLARIS_USCSI )
+    INIT_USCSI( GPCMD_SEND_KEY, 8 );
+
+    rs_cdb.cdb_opaque[ 10 ] = DVD_SEND_RPC;
+
+    p_buffer[ 1 ] = 6;
+    p_buffer[ 4 ] = i_pdrc;
+
+    i_ret = SolarisSendUSCSI( i_fd, &sc );
+
+    if( i_ret < 0 || sc.uscsi_status )
+    {
+        i_ret = -1;
+    }
+
+#elif defined( DARWIN_DVD_IOCTL )
+    INIT_DVDIOCTL( dk_dvd_send_key_t, DVDRegionPlaybackControlInfo,
+                   kDVDKeyFormatSetRegion );
+
+    dvd.keyClass = kDVDKeyClassCSS_CPPM_CPRM;
+    dvdbs.driveRegion = i_pdrc;
+
+    i_ret = ioctl( i_fd, DKIOCDVDSENDKEY, &dvd );
+
+#elif defined( WIN32 )
+    if( WIN2K ) /* NT/2k/XP */
+    {
+        INIT_SPTD( GPCMD_SEND_KEY, 8 );
+
+        sptd.Cdb[ 10 ] = DVD_SEND_RPC;
+
+        p_buffer[ 1 ] = 6;
+        p_buffer[ 4 ] = i_pdrc;
+
+        i_ret = SEND_SPTD( i_fd, &sptd, &tmp );
+    }
+    else
+    {
+        INIT_SSC( GPCMD_SEND_KEY, 8 );
+
+        ssc.CDBByte[ 10 ] = DVD_SEND_RPC;
+
+        p_buffer[ 1 ] = 6;
+        p_buffer[ 4 ] = i_pdrc;
+
+        i_ret = WinSendSSC( i_fd, &ssc );
+    }
+
+#elif defined( __QNXNTO__ )
+
+    INIT_CPT( GPCMD_SEND_KEY, 8 );
+
+    p_cpt->cam_cdb[ 10 ] = DVD_SEND_RPC;
+
+    p_buffer[ 1 ] = 6;
+    p_buffer[ 4 ] = i_pdrc;
+
+    i_ret = devctl(i_fd, DCMD_CAM_PASS_THRU, p_cpt, structSize, NULL);
+
+#elif defined( SYS_OS2 )
+    INIT_SSC( GPCMD_SEND_KEY, 8 );
+
+    sdc.command[ 10 ] = DVD_SEND_RPC;
+
+    p_buffer[ 1 ] = 6;
+    p_buffer[ 4 ] = i_pdrc;
+
+    i_ret = DosDevIOCtl( i_fd, IOCTL_CDROMDISK, CDROMDISK_EXECMD,
+                         &sdc, sizeof(sdc), &ulParamLen,
+                         p_buffer, sizeof(p_buffer), &ulDataLen );
+
+#else
+#   error "DVD ioctls are unavailable on this system"
+
+#endif
+    return i_ret;
+}
+
 /* Local prototypes */
 
 #if defined( SYS_BEOS )
@@ -1765,15 +1873,15 @@
 /*****************************************************************************
  * SolarisInitUSCSI: initialize a USCSICMD structure for the Solaris kernel
  *****************************************************************************
- * This function initializes a Solaris userspace scsi command structure for 
+ * This function initializes a Solaris userspace scsi command structure for
  * future use, either a read command or a write command.
  *****************************************************************************/
 static void SolarisInitUSCSI( struct uscsi_cmd *p_sc, int i_type )
-{   
+{
     union scsi_cdb *rs_cdb;
     memset( p_sc->uscsi_cdb, 0, sizeof( union scsi_cdb ) );
     memset( p_sc->uscsi_bufaddr, 0, p_sc->uscsi_buflen );
-    
+
     switch( i_type )
     {
         case GPCMD_SEND_KEY:
@@ -1785,9 +1893,9 @@
             p_sc->uscsi_flags = USCSI_ISOLATE | USCSI_READ;
             break;
     }
-    
+
     rs_cdb = (union scsi_cdb *)p_sc->uscsi_cdb;
-    
+
     rs_cdb->scc_cmd = i_type;
 
     rs_cdb->cdb_opaque[ 8 ] = (p_sc->uscsi_buflen >> 8) & 0xff;
@@ -1848,6 +1956,36 @@
 
 #if defined( WIN32 )
 /*****************************************************************************
+ * WinInitSPTD: initialize a sptd structure
+ *****************************************************************************
+ * This function initializes a SCSI pass through command structure for future
+ * use, either a read command or a write command.
+ *****************************************************************************/
+static void WinInitSPTD( SCSI_PASS_THROUGH_DIRECT *p_sptd, int i_type )
+{
+    memset( p_sptd->DataBuffer, 0, p_sptd->DataTransferLength );
+
+    switch( i_type )
+    {
+        case GPCMD_SEND_KEY:
+            p_sptd->DataIn = SCSI_IOCTL_DATA_OUT;
+            break;
+
+        case GPCMD_READ_DVD_STRUCTURE:
+        case GPCMD_REPORT_KEY:
+            p_sptd->DataIn = SCSI_IOCTL_DATA_IN;
+            break;
+    }
+
+    p_sptd->Cdb[ 0 ] = i_type;
+    p_sptd->Cdb[ 8 ] = (uint8_t)(p_sptd->DataTransferLength >> 8) & 0xff;
+    p_sptd->Cdb[ 9 ] = (uint8_t) p_sptd->DataTransferLength       & 0xff;
+    p_sptd->CdbLength = 12;
+
+    p_sptd->TimeOutValue = 2;
+}
+
+/*****************************************************************************
  * WinInitSSC: initialize a ssc structure for the win32 aspi layer
  *****************************************************************************
  * This function initializes a ssc raw device command structure for future
@@ -1874,8 +2012,8 @@
 
     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->CDBByte[ 8 ] = (uint8_t)(p_ssc->SRB_BufLen >> 8) & 0xff;
+    p_ssc->CDBByte[ 9 ] = (uint8_t) p_ssc->SRB_BufLen       & 0xff;
     p_ssc->SRB_CDBLen   = 12;
 
     p_ssc->SRB_SenseLen = SENSE_LEN;
@@ -1944,7 +2082,7 @@
 /*****************************************************************************
  * OS2InitSDC: initialize a SDC structure for the Execute SCSI-command
  *****************************************************************************
- * This function initializes a OS2 'execute SCSI command' structure for 
+ * This function initializes a OS2 'execute SCSI command' structure for
  * future use, either a read command or a write command.
  *****************************************************************************/
 static void OS2InitSDC( struct OS2_ExecSCSICmd *p_sdc, int i_type )