ref: 95671de3719a6b0943d7c86766e29c5646d191d8
parent: 3adf615d8ed7c70804844131e808ffaec923cb10
author: Gildas Bazin <[email protected]>
date: Thu Oct 10 08:44:28 EDT 2002
* src/css.c, src/device.c, src/ioctl.[ch]: We don't need to be in administrator mode anymore to authenticate the drive on Windows NT/2k/XP. As a result any user can now play a DVD on these OSs :) * src/ioctl.c: fixed ioctl_ReadTitleKey which wasn't working on Windows NT/2k/XP. Because of this bug, the disc and key methods for key decryption where not working.
--- a/AUTHORS
+++ b/AUTHORS
@@ -58,3 +58,7 @@
E: [email protected]
D: FreeBSD DVD input patch
+N: Gildas Bazin
+E: [email protected]
+C: gbazin
+D: various fixes to the Win32 port
--- a/src/css.c
+++ b/src/css.c
@@ -2,7 +2,7 @@
* css.c: Functions for DVD authentication and descrambling
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
- * $Id: css.c,v 1.15 2002/08/10 21:19:55 sam Exp $
+ * $Id: css.c,v 1.16 2002/10/10 12:44:28 gbazin Exp $
*
* Author: St�phane Borel <[email protected]>
* H�kan Hjort <[email protected]>
@@ -83,13 +83,7 @@
/* Since it's the first ioctl we try to issue, we add a notice */
_dvdcss_error( dvdcss, "css error: ioctl_ReadCopyright failed, "
"make sure there is a DVD in the drive, and that "
- "you have used the correct device node."
-#if defined( WIN32 )
- "\nAlso note that if you are using Windows NT/2000/XP "
- "you need to have administrator priviledges to be able "
- "to use ioctls."
-#endif
- );
+ "you have used the correct device node." );
return i_ret;
}
--- a/src/device.c
+++ b/src/device.c
@@ -2,7 +2,7 @@
* device.h: DVD device access
*****************************************************************************
* Copyright (C) 1998-2002 VideoLAN
- * $Id: device.c,v 1.3 2002/08/10 17:42:09 sam Exp $
+ * $Id: device.c,v 1.4 2002/10/10 12:44:28 gbazin Exp $
*
* Authors: St�phane Borel <[email protected]>
* Samuel Hocevar <[email protected]>
@@ -169,10 +169,12 @@
char psz_dvd[7];
_snprintf( psz_dvd, 7, "\\\\.\\%c:", psz_device[0] );
- /* To have access to ioctls, we need read and write access to the
- * device. This is only allowed if you have administrator priviledges
- * so we allow for a fallback method where ioctls are not available but
- * we at least have read access to the device.
+ /* To work around an M$ bug in IOCTL_DVD_READ_STRUCTURE, we need read
+ * _and_ write access to the device (so we can make SCSI Pass Through
+ * Requests). Unfortunately this is only allowed if you have
+ * administrator priviledges so we allow for a fallback method with
+ * only read access to the device (in this case ioctl_ReadCopyright()
+ * won't send back the right result).
* (See Microsoft Q241374: Read and Write Access Required for SCSI
* Pass Through Requests) */
(HANDLE) dvdcss->i_fd =
--- a/src/ioctl.c
+++ b/src/ioctl.c
@@ -2,7 +2,7 @@
* ioctl.c: DVD ioctl replacement function
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
- * $Id: ioctl.c,v 1.13 2002/08/10 17:42:09 sam Exp $
+ * $Id: ioctl.c,v 1.14 2002/10/10 12:44:28 gbazin Exp $
*
* Authors: Markus Kuespert <[email protected]>
* Samuel Hocevar <[email protected]>
@@ -11,6 +11,7 @@
* Eugenio Jarosiewicz <[email protected]>
* David Sieb�rger <[email protected]>
* Alex Strelnikov <[email protected]>
+ * Gildas Bazin <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -210,19 +211,21 @@
*pi_copyright = dvdbs.copyrightProtectionSystemType;
#elif defined( WIN32 )
- if( WIN2K ) /* NT/Win2000/Whistler */
+ if( WIN2K ) /* NT/2k/XP */
{
DWORD tmp;
u8 p_buffer[ 8 ];
SCSI_PASS_THROUGH_DIRECT sptd;
- memset( &sptd, 0, sizeof( sptd ) );
- memset( &p_buffer, 0, sizeof( p_buffer ) );
-
/* When using IOCTL_DVD_READ_STRUCTURE and
DVD_COPYRIGHT_DESCRIPTOR, CopyrightProtectionType
- is always 6. So we send a raw scsi command instead. */
+ seems to be always 6 ???
+ To work around this M$ 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;
@@ -241,7 +244,30 @@
&sptd, sizeof( SCSI_PASS_THROUGH_DIRECT ),
&tmp, NULL ) ? 0 : -1;
- *pi_copyright = p_buffer[ 4 ];
+ if( i_ret == 0 )
+ {
+ *pi_copyright = p_buffer[ 4 ];
+ }
+ else
+ {
+ /* We don't have the privileges to send a SCSI_PASS_THROUGH
+ command, let's try the buggy IOCTL_DVD_READ_STRUCTURE anyway */
+
+ DVD_READ_STRUCTURE dvd_struct;
+ DVD_COPYRIGHT_DESCRIPTOR dvd_descr;
+
+ memset( &dvd_struct, 0, sizeof( DVD_READ_STRUCTURE ) );
+
+ dvd_struct.Format = DvdCopyrightDescriptor;
+ dvd_struct.LayerNumber = i_layer;
+
+ i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_STRUCTURE,
+ &dvd_struct, sizeof(DVD_READ_STRUCTURE),
+ &dvd_descr, sizeof(DVD_COPYRIGHT_DESCRIPTOR),
+ &tmp, NULL ) ? 0 : -1;
+
+ *pi_copyright = dvd_descr.CopyrightProtectionType;
+ }
}
else
{
@@ -383,7 +409,7 @@
memcpy( p_key, dvdbs.discKeyStructures, DVD_DISCKEY_SIZE );
#elif defined( WIN32 )
- if( WIN2K ) /* NT/Win2000/Whistler */
+ if( WIN2K ) /* NT/2k/XP */
{
DWORD tmp;
u8 buffer[DVD_DISK_KEY_LENGTH];
@@ -551,7 +577,7 @@
memcpy( p_key, dvdbs.titleKeyValue, DVD_KEY_SIZE );
#elif defined( WIN32 )
- if( WIN2K ) /* NT/Win2000/Whistler */
+ if( WIN2K ) /* NT/2k/XP */
{
DWORD tmp;
u8 buffer[DVD_BUS_KEY_LENGTH];
@@ -563,7 +589,8 @@
key->SessionId = *pi_agid;
key->KeyType = DvdTitleKey;
key->KeyFlags = 0;
- key->Parameters.TitleOffset.QuadPart = (LONGLONG) i_pos;
+ key->Parameters.TitleOffset.QuadPart = (LONGLONG) i_pos *
+ 2048 /*DVDCSS_BLOCK_SIZE*/;
i_ret = DeviceIoControl( (HANDLE) i_fd, IOCTL_DVD_READ_KEY, key,
key->KeyLength, key, key->KeyLength, &tmp, NULL ) ? 0 : -1;
@@ -696,7 +723,7 @@
*pi_agid = dvdbs.grantID;
#elif defined( WIN32 )
- if( WIN2K ) /* NT/Win2000/Whistler */
+ if( WIN2K ) /* NT/2k/XP */
{
ULONG id;
DWORD tmp;
@@ -817,7 +844,7 @@
memcpy( p_challenge, dvdbs.challengeKeyValue, DVD_CHALLENGE_SIZE );
#elif defined( WIN32 )
- if( WIN2K ) /* NT/Win2000/Whistler */
+ if( WIN2K ) /* NT/2k/XP */
{
DWORD tmp;
u8 buffer[DVD_CHALLENGE_KEY_LENGTH];
@@ -949,7 +976,7 @@
*pi_asf = dvdbs.successFlag;
#elif defined( WIN32 )
- if( WIN2K ) /* NT/Win2000/Whistler */
+ if( WIN2K ) /* NT/2k/XP */
{
DWORD tmp;
u8 buffer[DVD_ASF_LENGTH];
@@ -1084,7 +1111,7 @@
memcpy( p_key, dvdbs.key1Value, DVD_KEY_SIZE );
#elif defined( WIN32 )
- if( WIN2K ) /* NT/Win2000/Whistler */
+ if( WIN2K ) /* NT/2k/XP */
{
DWORD tmp;
u8 buffer[DVD_BUS_KEY_LENGTH];
@@ -1201,7 +1228,7 @@
i_ret = ioctl( i_fd, DKIOCDVDSENDKEY, &dvd );
#elif defined( WIN32 )
- if( WIN2K ) /* NT/Win2000/Whistler */
+ if( WIN2K ) /* NT/2k/XP */
{
DWORD tmp;
@@ -1329,7 +1356,7 @@
i_ret = ioctl( i_fd, DKIOCDVDSENDKEY, &dvd );
#elif defined( WIN32 )
- if( WIN2K ) /* NT/Win2000/Whistler */
+ if( WIN2K ) /* NT/2k/XP */
{
DWORD tmp;
u8 buffer[DVD_CHALLENGE_KEY_LENGTH];
@@ -1466,7 +1493,7 @@
i_ret = ioctl( i_fd, DKIOCDVDSENDKEY, &dvd );
#elif defined( WIN32 )
- if( WIN2K ) /* NT/Win2000/Whistler */
+ if( WIN2K ) /* NT/2k/XP */
{
DWORD tmp;
u8 buffer[DVD_BUS_KEY_LENGTH];
@@ -1612,7 +1639,7 @@
*p_scheme = dvdbs.rpcScheme;
#elif defined( WIN32 )
- if( WIN2K ) /* NT/Win2000/Whistler */
+ if( WIN2K ) /* NT/2k/XP */
{
DWORD tmp;
u8 buffer[ DVD_REGION_LENGTH ];
@@ -1624,19 +1651,19 @@
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? */
+ /* 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;
- }
- else
- {
- *p_type = 0; /* ?? */
- *p_mask = 0xff;
- *p_scheme = 1; /* ?? */
- }
+ *p_type = region->ResetCount > 1 ? 1 : 3 - region->ResetCount;
+ *p_mask = 0xff ^ (1 << (region->SystemRegion - 1));
+ *p_scheme = 1;
+ }
+ else
+ {
+ *p_type = 0; /* ?? */
+ *p_mask = 0xff;
+ *p_scheme = 1; /* ?? */
+ }
}
else
{
@@ -1878,7 +1905,7 @@
p_cpt->cam_cdb[ 9 ] = p_cpt->cam_dxfer_len & 0xff;
p_cpt->cam_cdb_len = 12;
- p_cpt->cam_timeout = CAM_TIME_DEFAULT;
+ p_cpt->cam_timeout = CAM_TIME_DEFAULT;
}
#endif
--- a/src/ioctl.h
+++ b/src/ioctl.h
@@ -2,7 +2,7 @@
* ioctl.h: DVD ioctl replacement function
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
- * $Id: ioctl.h,v 1.7 2002/08/10 17:42:09 sam Exp $
+ * $Id: ioctl.h,v 1.8 2002/10/10 12:44:28 gbazin Exp $
*
* Authors: Samuel Hocevar <[email protected]>
*
@@ -188,7 +188,7 @@
#define IOCTL_DVD_END_SESSION CTL_CODE(FILE_DEVICE_DVD, 0x0403, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_DVD_GET_REGION CTL_CODE(FILE_DEVICE_DVD, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_DVD_SEND_KEY2 CTL_CODE(FILE_DEVICE_DVD, 0x0406, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
-
+#define IOCTL_DVD_READ_STRUCTURE CTL_CODE(FILE_DEVICE_DVD, 0x0450, METHOD_BUFFERED, FILE_READ_ACCESS)
#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))
@@ -202,6 +202,28 @@
#define SCSI_IOCTL_DATA_IN 1
typedef ULONG DVD_SESSION_ID, *PDVD_SESSION_ID;
+
+typedef enum DVD_STRUCTURE_FORMAT {
+ DvdPhysicalDescriptor,
+ DvdCopyrightDescriptor,
+ DvdDiskKeyDescriptor,
+ DvdBCADescriptor,
+ DvdManufacturerDescriptor,
+ DvdMaxDescriptor
+} DVD_STRUCTURE_FORMAT, *PDVD_STRUCTURE_FORMAT;
+
+typedef struct DVD_READ_STRUCTURE {
+ LARGE_INTEGER BlockByteOffset;
+ DVD_STRUCTURE_FORMAT Format;
+ DVD_SESSION_ID SessionId;
+ UCHAR LayerNumber;
+} DVD_READ_STRUCTURE, *PDVD_READ_STRUCTURE;
+
+typedef struct _DVD_COPYRIGHT_DESCRIPTOR {
+ UCHAR CopyrightProtectionType;
+ UCHAR RegionManagementInformation;
+ USHORT Reserved;
+} DVD_COPYRIGHT_DESCRIPTOR, *PDVD_COPYRIGHT_DESCRIPTOR;
typedef enum
{