Support unrar64.dll
[xy_vsfilter.git] / src / decss / DeCSSInputPin.cpp
blob2d121bf4c30ee70e0216428479015e83fe46e3f4
1 /*
2 * Copyright (C) 2003-2006 Gabest
3 * http://www.gabest.org
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GNU Make; see the file COPYING. If not, write to
17 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18 * http://www.gnu.org/copyleft/gpl.html
22 #include "stdafx.h"
23 #include <atlbase.h>
24 #include <streams.h>
25 #include <dvdmedia.h>
26 #include <ks.h>
27 #include <ksmedia.h>
28 #include "DeCSSInputPin.h"
29 #include "..\DSUtil\DSUtil.h"
30 #include "CSSauth.h"
31 #include "CSSscramble.h"
33 #include <initguid.h>
34 #include "..\..\include\moreuuids.h"
37 // CDeCSSInputPin
40 CDeCSSInputPin::CDeCSSInputPin(TCHAR* pObjectName, CTransformFilter* pFilter, HRESULT* phr, LPWSTR pName)
41 : CTransformInputPin(pObjectName, pFilter, phr, pName)
43 m_varient = -1;
44 memset(m_Challenge, 0, sizeof(m_Challenge));
45 memset(m_KeyCheck, 0, sizeof(m_KeyCheck));
46 memset(m_DiscKey, 0, sizeof(m_DiscKey));
47 memset(m_TitleKey, 0, sizeof(m_TitleKey));
50 STDMETHODIMP CDeCSSInputPin::NonDelegatingQueryInterface(REFIID riid, void** ppv)
52 CheckPointer(ppv, E_POINTER);
54 return
55 QI(IKsPropertySet)
56 __super::NonDelegatingQueryInterface(riid, ppv);
59 // IMemInputPin
61 STDMETHODIMP CDeCSSInputPin::Receive(IMediaSample* pSample)
63 long len = pSample->GetActualDataLength();
65 BYTE* p = NULL;
66 if(SUCCEEDED(pSample->GetPointer(&p)) && len > 0)
68 BYTE* base = p;
70 if(m_mt.majortype == MEDIATYPE_DVD_ENCRYPTED_PACK && len == 2048 && (p[0x14]&0x30))
72 CSSdescramble(p, m_TitleKey);
73 p[0x14] &= ~0x30;
75 if(CComQIPtr<IMediaSample2> pMS2 = pSample)
77 AM_SAMPLE2_PROPERTIES props;
78 memset(&props, 0, sizeof(props));
79 if(SUCCEEDED(pMS2->GetProperties(sizeof(props), (BYTE*)&props))
80 && (props.dwTypeSpecificFlags & AM_UseNewCSSKey))
82 props.dwTypeSpecificFlags &= ~AM_UseNewCSSKey;
83 pMS2->SetProperties(sizeof(props), (BYTE*)&props);
89 HRESULT hr = Transform(pSample);
91 return hr == S_OK ? __super::Receive(pSample) :
92 hr == S_FALSE ? S_OK : hr;
95 void CDeCSSInputPin::StripPacket(BYTE*& p, long& len)
97 GUID majortype = m_mt.majortype;
99 if(majortype == MEDIATYPE_MPEG2_PACK || majortype == MEDIATYPE_DVD_ENCRYPTED_PACK)
100 if(len > 0 && *(DWORD*)p == 0xba010000) // MEDIATYPE_*_PACK
102 len -= 14; p += 14;
103 if(int stuffing = (p[-1]&7)) {len -= stuffing; p += stuffing;}
104 majortype = MEDIATYPE_MPEG2_PES;
107 if(majortype == MEDIATYPE_MPEG2_PES)
108 if(len > 0 && *(DWORD*)p == 0xbb010000)
110 len -= 4; p += 4;
111 int hdrlen = ((p[0]<<8)|p[1]) + 2;
112 len -= hdrlen; p += hdrlen;
115 if(majortype == MEDIATYPE_MPEG2_PES)
116 if(len > 0
117 && ((*(DWORD*)p&0xf0ffffff) == 0xe0010000
118 || (*(DWORD*)p&0xe0ffffff) == 0xc0010000
119 || (*(DWORD*)p&0xbdffffff) == 0xbd010000)) // PES
121 bool ps1 = (*(DWORD*)p&0xbdffffff) == 0xbd010000;
123 len -= 4; p += 4;
124 int expected = ((p[0]<<8)|p[1]);
125 len -= 2; p += 2;
126 BYTE* p0 = p;
128 for(int i = 0; i < 16 && *p == 0xff; i++, len--, p++);
130 if((*p&0xc0) == 0x80) // mpeg2
132 len -= 2; p += 2;
133 len -= *p+1; p += *p+1;
135 else // mpeg1
137 if((*p&0xc0) == 0x40)
139 len -= 2; p += 2;
142 if((*p&0x30) == 0x30 || (*p&0x30) == 0x20)
144 bool pts = !!(*p&0x20), dts = !!(*p&0x10);
145 if(pts) len -= 5; p += 5;
146 if(dts) {ASSERT((*p&0xf0) == 0x10); len -= 5; p += 5;}
148 else
150 len--; p++;
154 if(ps1)
156 len--; p++;
157 if(m_mt.subtype == MEDIASUBTYPE_DVD_LPCM_AUDIO) {len -= 6; p += 6;}
158 else if(m_mt.subtype == MEDIASUBTYPE_DOLBY_AC3 || m_mt.subtype == MEDIASUBTYPE_WAVE_DOLBY_AC3
159 || m_mt.subtype == MEDIASUBTYPE_DTS || m_mt.subtype == MEDIASUBTYPE_WAVE_DTS) {len -= 3; p += 3;}
162 if(expected > 0)
164 expected -= (p - p0);
165 len = min(expected, len);
169 if(len < 0) {ASSERT(0); len = 0;}
172 // IKsPropertySet
174 STDMETHODIMP CDeCSSInputPin::Set(REFGUID PropSet, ULONG Id, LPVOID pInstanceData, ULONG InstanceLength, LPVOID pPropertyData, ULONG DataLength)
176 if(PropSet != AM_KSPROPSETID_CopyProt)
177 return E_NOTIMPL;
179 switch(Id)
181 case AM_PROPERTY_COPY_MACROVISION:
182 break;
183 case AM_PROPERTY_DVDCOPY_CHLG_KEY: // 3. auth: receive drive nonce word, also store and encrypt the buskey made up of the two nonce words
185 AM_DVDCOPY_CHLGKEY* pChlgKey = (AM_DVDCOPY_CHLGKEY*)pPropertyData;
186 for(int i = 0; i < 10; i++)
187 m_Challenge[i] = pChlgKey->ChlgKey[9-i];
189 CSSkey2(m_varient, m_Challenge, &m_Key[5]);
191 CSSbuskey(m_varient, m_Key, m_KeyCheck);
193 break;
194 case AM_PROPERTY_DVDCOPY_DISC_KEY: // 5. receive the disckey
196 AM_DVDCOPY_DISCKEY* pDiscKey = (AM_DVDCOPY_DISCKEY*)pPropertyData; // pDiscKey->DiscKey holds the disckey encrypted with itself and the 408 disckeys encrypted with the playerkeys
198 bool fSuccess = false;
200 for(int j = 0; j < g_nPlayerKeys; j++)
202 for(int k = 1; k < 409; k++)
204 BYTE DiscKey[6];
205 for(int i = 0; i < 5; i++)
206 DiscKey[i] = pDiscKey->DiscKey[k*5+i] ^ m_KeyCheck[4-i];
207 DiscKey[5] = 0;
209 CSSdisckey(DiscKey, g_PlayerKeys[j]);
211 BYTE Hash[6];
212 for(int i = 0; i < 5; i++)
213 Hash[i] = pDiscKey->DiscKey[i] ^ m_KeyCheck[4-i];
214 Hash[5] = 0;
216 CSSdisckey(Hash, DiscKey);
218 if(!memcmp(Hash, DiscKey, 6))
220 memcpy(m_DiscKey, DiscKey, 6);
221 j = g_nPlayerKeys;
222 fSuccess = true;
223 break;
228 if(!fSuccess)
229 return E_FAIL;
231 break;
232 case AM_PROPERTY_DVDCOPY_DVD_KEY1: // 2. auth: receive our drive-encrypted nonce word and decrypt it for verification
234 AM_DVDCOPY_BUSKEY* pKey1 = (AM_DVDCOPY_BUSKEY*)pPropertyData;
235 for(int i = 0; i < 5; i++)
236 m_Key[i] = pKey1->BusKey[4-i];
238 m_varient = -1;
240 for(int i = 31; i >= 0; i--)
242 CSSkey1(i, m_Challenge, m_KeyCheck);
244 if(memcmp(m_KeyCheck, &m_Key[0], 5) == 0)
245 m_varient = i;
248 break;
249 case AM_PROPERTY_DVDCOPY_REGION:
250 break;
251 case AM_PROPERTY_DVDCOPY_SET_COPY_STATE:
252 break;
253 case AM_PROPERTY_DVDCOPY_TITLE_KEY: // 6. receive the title key and decrypt it with the disc key
255 AM_DVDCOPY_TITLEKEY* pTitleKey = (AM_DVDCOPY_TITLEKEY*)pPropertyData;
256 for(int i = 0; i < 5; i++)
257 m_TitleKey[i] = pTitleKey->TitleKey[i] ^ m_KeyCheck[4-i];
258 m_TitleKey[5] = 0;
259 CSStitlekey(m_TitleKey, m_DiscKey);
261 break;
262 default:
263 return E_PROP_ID_UNSUPPORTED;
266 return S_OK;
269 STDMETHODIMP CDeCSSInputPin::Get(REFGUID PropSet, ULONG Id, LPVOID pInstanceData, ULONG InstanceLength, LPVOID pPropertyData, ULONG DataLength, ULONG* pBytesReturned)
271 if(PropSet != AM_KSPROPSETID_CopyProt)
272 return E_NOTIMPL;
274 switch(Id)
276 case AM_PROPERTY_DVDCOPY_CHLG_KEY: // 1. auth: send our nonce word
278 AM_DVDCOPY_CHLGKEY* pChlgKey = (AM_DVDCOPY_CHLGKEY*)pPropertyData;
279 for(int i = 0; i < 10; i++)
280 pChlgKey->ChlgKey[i] = 9 - (m_Challenge[i] = i);
281 *pBytesReturned = sizeof(AM_DVDCOPY_CHLGKEY);
283 break;
284 case AM_PROPERTY_DVDCOPY_DEC_KEY2: // 4. auth: send back the encrypted drive nonce word to finish the authentication
286 AM_DVDCOPY_BUSKEY* pKey2 = (AM_DVDCOPY_BUSKEY*)pPropertyData;
287 for(int i = 0; i < 5; i++)
288 pKey2->BusKey[4-i] = m_Key[5+i];
289 *pBytesReturned = sizeof(AM_DVDCOPY_BUSKEY);
291 break;
292 case AM_PROPERTY_DVDCOPY_REGION:
294 DVD_REGION* pRegion = (DVD_REGION*)pPropertyData;
295 pRegion->RegionData = 0;
296 pRegion->SystemRegion = 0;
297 *pBytesReturned = sizeof(DVD_REGION);
299 break;
300 case AM_PROPERTY_DVDCOPY_SET_COPY_STATE:
302 AM_DVDCOPY_SET_COPY_STATE* pState = (AM_DVDCOPY_SET_COPY_STATE*)pPropertyData;
303 pState->DVDCopyState = AM_DVDCOPYSTATE_AUTHENTICATION_REQUIRED;
304 *pBytesReturned = sizeof(AM_DVDCOPY_SET_COPY_STATE);
306 break;
307 default:
308 return E_PROP_ID_UNSUPPORTED;
311 return S_OK;
314 STDMETHODIMP CDeCSSInputPin::QuerySupported(REFGUID PropSet, ULONG Id, ULONG* pTypeSupport)
316 if(PropSet != AM_KSPROPSETID_CopyProt)
317 return E_NOTIMPL;
319 switch(Id)
321 case AM_PROPERTY_COPY_MACROVISION:
322 *pTypeSupport = KSPROPERTY_SUPPORT_SET;
323 break;
324 case AM_PROPERTY_DVDCOPY_CHLG_KEY:
325 *pTypeSupport = KSPROPERTY_SUPPORT_GET | KSPROPERTY_SUPPORT_SET;
326 break;
327 case AM_PROPERTY_DVDCOPY_DEC_KEY2:
328 *pTypeSupport = KSPROPERTY_SUPPORT_GET;
329 break;
330 case AM_PROPERTY_DVDCOPY_DISC_KEY:
331 *pTypeSupport = KSPROPERTY_SUPPORT_SET;
332 break;
333 case AM_PROPERTY_DVDCOPY_DVD_KEY1:
334 *pTypeSupport = KSPROPERTY_SUPPORT_SET;
335 break;
336 case AM_PROPERTY_DVDCOPY_REGION:
337 *pTypeSupport = KSPROPERTY_SUPPORT_GET | KSPROPERTY_SUPPORT_SET;
338 break;
339 case AM_PROPERTY_DVDCOPY_SET_COPY_STATE:
340 *pTypeSupport = KSPROPERTY_SUPPORT_GET | KSPROPERTY_SUPPORT_SET;
341 break;
342 case AM_PROPERTY_DVDCOPY_TITLE_KEY:
343 *pTypeSupport = KSPROPERTY_SUPPORT_SET;
344 break;
345 default:
346 return E_PROP_ID_UNSUPPORTED;
349 return S_OK;