5 #include "CSSscramble.h"
12 CDVDSession::CDVDSession()
13 : m_session(DVD_END_ALL_SESSIONS
)
14 , m_hDrive(INVALID_HANDLE_VALUE
)
18 CDVDSession::~CDVDSession()
23 bool CDVDSession::Open(LPCTSTR path
)
28 CString drive
= _T("\\\\.\\") + fn
.Left(fn
.Find(':')+1);
30 m_hDrive
= CreateFile(drive
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
31 OPEN_EXISTING
, FILE_ATTRIBUTE_READONLY
|FILE_FLAG_SEQUENTIAL_SCAN
, (HANDLE
)NULL
);
32 if(m_hDrive
== INVALID_HANDLE_VALUE
)
38 void CDVDSession::Close()
40 if(m_hDrive
!= INVALID_HANDLE_VALUE
)
42 CloseHandle(m_hDrive
);
43 m_hDrive
= INVALID_HANDLE_VALUE
;
47 bool CDVDSession::BeginSession()
51 if(m_hDrive
== INVALID_HANDLE_VALUE
)
55 if(!DeviceIoControl(m_hDrive
, IOCTL_DVD_START_SESSION
, NULL
, 0, &m_session
, sizeof(m_session
), &BytesReturned
, NULL
))
57 m_session
= DVD_END_ALL_SESSIONS
;
58 if(!DeviceIoControl(m_hDrive
, IOCTL_DVD_END_SESSION
, &m_session
, sizeof(m_session
), NULL
, 0, &BytesReturned
, NULL
)
59 || !DeviceIoControl(m_hDrive
, IOCTL_DVD_START_SESSION
, NULL
, 0, &m_session
, sizeof(m_session
), &BytesReturned
, NULL
))
61 CloseHandle(m_hDrive
);
62 DWORD err
= GetLastError();
70 void CDVDSession::EndSession()
72 if(m_session
!= DVD_END_ALL_SESSIONS
)
75 DeviceIoControl(m_hDrive
, IOCTL_DVD_END_SESSION
, &m_session
, sizeof(m_session
), NULL
, 0, &BytesReturned
, NULL
);
76 m_session
= DVD_END_ALL_SESSIONS
;
80 bool CDVDSession::Authenticate()
82 if(m_session
== DVD_END_ALL_SESSIONS
)
85 BYTE Challenge
[10], Key
[10];
87 for(int i
= 0; i
< 10; i
++) Challenge
[i
] = i
;
89 if(!SendKey(DvdChallengeKey
, Challenge
))
92 if(!ReadKey(DvdBusKey1
, Key
))
97 for(int i
= 31; i
>= 0; i
--)
100 CSSkey1(i
, Challenge
, KeyCheck
);
101 if(!memcmp(KeyCheck
, Key
, 5))
105 if(!ReadKey(DvdChallengeKey
, Challenge
))
108 CSSkey2(varient
, Challenge
, &Key
[5]);
110 if(!SendKey(DvdBusKey2
, &Key
[5]))
113 CSSbuskey(varient
, Key
, m_SessionKey
);
118 bool CDVDSession::GetDiscKey()
120 if(m_session
== DVD_END_ALL_SESSIONS
)
124 if(!ReadKey(DvdDiskKey
, DiscKeys
))
127 for(int i
= 0; i
< g_nPlayerKeys
; i
++)
129 for(int j
= 1; j
< 409; j
++)
132 memcpy(DiscKey
, &DiscKeys
[j
*5], 5);
135 CSSdisckey(DiscKey
, g_PlayerKeys
[i
]);
138 memcpy(Hash
, &DiscKeys
[0], 5);
141 CSSdisckey(Hash
, DiscKey
);
143 if(!memcmp(Hash
, DiscKey
, 6))
145 memcpy(m_DiscKey
, DiscKey
, 6);
154 bool CDVDSession::GetTitleKey(int lba
, BYTE
* pKey
)
156 if(m_session
== DVD_END_ALL_SESSIONS
)
159 if(!ReadKey(DvdTitleKey
, pKey
, lba
))
162 if(!(pKey
[0]|pKey
[1]|pKey
[2]|pKey
[3]|pKey
[4]))
167 CSStitlekey(pKey
, m_DiscKey
);
172 static void Reverse(BYTE
* d
, BYTE
* s
, int len
)
176 for(s
+= len
-1; d
< s
; d
++, s
--)
177 *d
^= *s
, *s
^= *d
, *d
^= *s
;
181 for(int i
= 0; i
< len
; i
++)
186 bool CDVDSession::SendKey(DVD_KEY_TYPE KeyType
, BYTE
* pKeyData
)
188 CAutoPtr
<DVD_COPY_PROTECT_KEY
> key
;
192 case DvdChallengeKey
:
193 key
.Attach((DVD_COPY_PROTECT_KEY
*)new BYTE
[DVD_CHALLENGE_KEY_LENGTH
]);
194 key
->KeyLength
= DVD_CHALLENGE_KEY_LENGTH
;
195 Reverse(key
->KeyData
, pKeyData
, 10);
198 key
.Attach((DVD_COPY_PROTECT_KEY
*)new BYTE
[DVD_BUS_KEY_LENGTH
]);
199 key
->KeyLength
= DVD_BUS_KEY_LENGTH
;
200 Reverse(key
->KeyData
, pKeyData
, 5);
209 key
->SessionId
= m_session
;
210 key
->KeyType
= KeyType
;
214 return(!!DeviceIoControl(m_hDrive
, IOCTL_DVD_SEND_KEY
, key
, key
->KeyLength
, NULL
, 0, &BytesReturned
, NULL
));
217 bool CDVDSession::ReadKey(DVD_KEY_TYPE KeyType
, BYTE
* pKeyData
, int lba
)
219 CAutoPtr
<DVD_COPY_PROTECT_KEY
> key
;
223 case DvdChallengeKey
:
224 key
.Attach((DVD_COPY_PROTECT_KEY
*)new BYTE
[DVD_CHALLENGE_KEY_LENGTH
]);
225 key
->KeyLength
= DVD_CHALLENGE_KEY_LENGTH
;
226 key
->Parameters
.TitleOffset
.QuadPart
= 0;
229 key
.Attach((DVD_COPY_PROTECT_KEY
*)new BYTE
[DVD_BUS_KEY_LENGTH
]);
230 key
->KeyLength
= DVD_BUS_KEY_LENGTH
;
231 key
->Parameters
.TitleOffset
.QuadPart
= 0;
234 key
.Attach((DVD_COPY_PROTECT_KEY
*)new BYTE
[DVD_DISK_KEY_LENGTH
]);
235 key
->KeyLength
= DVD_DISK_KEY_LENGTH
;
236 key
->Parameters
.TitleOffset
.QuadPart
= 0;
239 key
.Attach((DVD_COPY_PROTECT_KEY
*)new BYTE
[DVD_TITLE_KEY_LENGTH
]);
240 key
->KeyLength
= DVD_TITLE_KEY_LENGTH
;
241 key
->Parameters
.TitleOffset
.QuadPart
= 2048i64
*lba
;
250 key
->SessionId
= m_session
;
251 key
->KeyType
= KeyType
;
255 if(!DeviceIoControl(m_hDrive
, IOCTL_DVD_READ_KEY
, key
, key
->KeyLength
, key
, key
->KeyLength
, &BytesReturned
, NULL
))
257 DWORD err
= GetLastError();
263 case DvdChallengeKey
:
264 Reverse(pKeyData
, key
->KeyData
, 10);
267 Reverse(pKeyData
, key
->KeyData
, 5);
270 memcpy(pKeyData
, key
->KeyData
, 2048);
271 for(int i
= 0; i
< 2048/5; i
++)
272 pKeyData
[i
] ^= m_SessionKey
[4-(i
%5)];
275 memcpy(pKeyData
, key
->KeyData
, 5);
276 for(int i
= 0; i
< 5; i
++)
277 pKeyData
[i
] ^= m_SessionKey
[4-(i
%5)];
294 CLBAFile::~CLBAFile()
298 bool CLBAFile::IsOpen()
300 return(m_hFile
!= hFileNull
);
303 bool CLBAFile::Open(LPCTSTR path
)
307 return(!!CFile::Open(path
, modeRead
|typeBinary
|shareDenyWrite
|osSequentialScan
));
310 void CLBAFile::Close()
312 if(m_hFile
!= hFileNull
)
316 int CLBAFile::GetLength()
318 return (int)(CFile::GetLength()/2048);
321 int CLBAFile::GetPosition()
323 return (int)(CFile::GetPosition()/2048);
326 int CLBAFile::Seek(int lba
)
328 return (int)(CFile::Seek(2048i64
*lba
, CFile::begin
)/2048);
331 bool CLBAFile::Read(BYTE
* buff
)
333 return CFile::Read(buff
, 2048) == 2048;
345 CVobFile::~CVobFile()
349 bool CVobFile::IsDVD()
354 bool CVobFile::HasDiscKey(BYTE
* key
)
356 if(key
) memcpy(key
, m_DiscKey
, 5);
357 return m_fHasDiscKey
;
360 bool CVobFile::HasTitleKey(BYTE
* key
)
362 if(key
) memcpy(key
, m_TitleKey
, 5);
363 return m_fHasTitleKey
;
366 bool CVobFile::Open(CString fn
, CAtlList
<CString
>& vobs
)
369 if(!f
.Open(fn
, CFile::modeRead
|CFile::typeBinary
|CFile::shareDenyWrite
))
375 if(strcmp(hdr
, "DVDVIDEO-VTS"))
384 fn
= fn
.Left(fn
.ReverseFind('.')+1);
385 fn
.TrimRight(_T(".0123456789"));
386 for(int i
= 0; i
< 100; i
++)
389 vob
.Format(_T("%s%d.vob"), fn
, i
);
392 if(!CFile::GetStatus(vob
, status
))
398 if(status
.m_size
&0x7ff)
404 if(status
.m_size
> 0)
408 offset
= (int)(status
.m_size
/0x800);
411 return Open(vobs
, offset
);
414 bool CVobFile::Open(CAtlList
<CString
>& vobs
, int offset
)
418 if(vobs
.GetCount() == 0)
421 if(vobs
.GetCount() == 1)
426 POSITION pos
= vobs
.GetHeadPosition();
429 CString fn
= vobs
.GetNext(pos
);
432 HANDLE h
= FindFirstFile(fn
, &fd
);
433 if(h
== INVALID_HANDLE_VALUE
)
442 f
.size
= (int)(((__int64(fd
.nFileSizeHigh
)<<32)|fd
.nFileSizeLow
)/2048);
448 if(m_files
.GetCount() > 0 && CDVDSession::Open(m_files
[0].fn
))
450 for(int i
= 0; !m_fHasTitleKey
&& i
< m_files
.GetCount(); i
++)
456 m_fHasDiscKey
= GetDiscKey();
461 CString fn
= m_files
[0].fn
;
464 if(fn
.Find(_T(":\\video_ts")) == 1 && GetDriveType(fn
.Left(3)) == DRIVE_CDROM
)
472 if(tp_udf_file f
= udf_find_file(m_hDrive
, 0, CStringA(m_files
[i
].fn
.Mid(m_files
[i
].fn
.Find(':')+1))))
475 if(udf_get_lba(m_hDrive
, f
, &start
, &end
))
480 m_fHasTitleKey
= GetTitleKey(start
+ f
->partition_lba
, m_TitleKey
);
489 if(HasTitleKey(key
) && i
== 0 && offset
>= 0)
497 m_fHasDiscKey
= GetDiscKey();
505 if(tp_udf_file f
= udf_find_file(m_hDrive
, 0, CStringA(m_files
[i
].fn
.Mid(m_files
[i
].fn
.Find(':')+1))))
508 if(udf_get_lba(m_hDrive
, f
, &start
, &end
))
513 m_fHasTitleKey
= GetTitleKey(start
+ f
->partition_lba
, m_TitleKey
);
523 memcpy(m_TitleKey
, key
, 5);
524 m_fHasTitleKey
= true;
530 if(m_files.GetCount() > 0 && !m_fDVD)
532 CString fn = m_files[0].fn;
535 if(fn.Find(_T(":\\video_ts")) == 1 && GetDriveType(fn.Left(3)) == DRIVE_CDROM)
541 m_offset
= max(offset
, 0);
546 void CVobFile::Close()
548 CDVDSession::Close();
551 m_pos
= m_size
= m_offset
= 0;
553 m_fDVD
= m_fHasDiscKey
= m_fHasTitleKey
= false;
556 int CVobFile::GetLength()
558 return(m_size
- m_offset
);
561 int CVobFile::GetPosition()
563 return(m_pos
- m_offset
);
566 int CVobFile::Seek(int pos
)
568 pos
= min(max(pos
+m_offset
, m_offset
), m_size
-1);
573 // this suxx, but won't take long
574 do size
+= m_files
[++i
].size
;
575 while(i
< m_files
.GetCount() && pos
>= size
);
577 if(i
!= m_iFile
&& i
< m_files
.GetCount())
579 if(!m_file
.Open(m_files
[i
].fn
))
587 pos
-= (size
- m_files
[i
].size
);
590 return(GetPosition());
593 bool CVobFile::Read(BYTE
* buff
)
595 if(m_pos
>= m_size
) return(false);
597 if(m_file
.IsOpen() && m_file
.GetPosition() == m_file
.GetLength())
604 if(m_iFile
>= m_files
.GetCount()-1)
609 if(!m_file
.Open(m_files
[++m_iFile
].fn
))
616 if(!m_file
.Read(buff
))
624 if(buff
[0x14] & 0x30)
628 CSSdescramble(buff
, m_TitleKey
);
633 // under win9x this is normal, but I'm not developing under win9x :P