00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "stdafx.h"
00023 #include <atlbase.h>
00024 #include <streams.h>
00025 #include <dvdmedia.h>
00026 #include <ks.h>
00027 #include <ksmedia.h>
00028 #include "DeCSSInputPin.h"
00029 #include "..\DSUtil\DSUtil.h"
00030 #include "CSSauth.h"
00031 #include "CSSscramble.h"
00032
00033 #include <initguid.h>
00034 #include "..\..\include\moreuuids.h"
00035
00036
00037
00038
00039
00040 CDeCSSInputPin::CDeCSSInputPin(TCHAR* pObjectName, CTransformFilter* pFilter, HRESULT* phr, LPWSTR pName)
00041 : CTransformInputPin(pObjectName, pFilter, phr, pName)
00042 {
00043 m_varient = -1;
00044 memset(m_Challenge, 0, sizeof(m_Challenge));
00045 memset(m_KeyCheck, 0, sizeof(m_KeyCheck));
00046 memset(m_DiscKey, 0, sizeof(m_DiscKey));
00047 memset(m_TitleKey, 0, sizeof(m_TitleKey));
00048 }
00049
00050 STDMETHODIMP CDeCSSInputPin::NonDelegatingQueryInterface(REFIID riid, void** ppv)
00051 {
00052 CheckPointer(ppv, E_POINTER);
00053
00054 return
00055 QI(IKsPropertySet)
00056 __super::NonDelegatingQueryInterface(riid, ppv);
00057 }
00058
00059
00060
00061 STDMETHODIMP CDeCSSInputPin::Receive(IMediaSample* pSample)
00062 {
00063 long len = pSample->GetActualDataLength();
00064
00065 BYTE* p = NULL;
00066 if(SUCCEEDED(pSample->GetPointer(&p)) && len > 0)
00067 {
00068 BYTE* base = p;
00069
00070 if(m_mt.majortype == MEDIATYPE_DVD_ENCRYPTED_PACK && len == 2048 && (p[0x14]&0x30))
00071 {
00072 CSSdescramble(p, m_TitleKey);
00073 p[0x14] &= ~0x30;
00074
00075 if(CComQIPtr<IMediaSample2> pMS2 = pSample)
00076 {
00077 AM_SAMPLE2_PROPERTIES props;
00078 memset(&props, 0, sizeof(props));
00079 if(SUCCEEDED(pMS2->GetProperties(sizeof(props), (BYTE*)&props))
00080 && (props.dwTypeSpecificFlags & AM_UseNewCSSKey))
00081 {
00082 props.dwTypeSpecificFlags &= ~AM_UseNewCSSKey;
00083 pMS2->SetProperties(sizeof(props), (BYTE*)&props);
00084 }
00085 }
00086 }
00087 }
00088
00089 HRESULT hr = Transform(pSample);
00090
00091 return hr == S_OK ? __super::Receive(pSample) :
00092 hr == S_FALSE ? S_OK : hr;
00093 }
00094
00095 void CDeCSSInputPin::StripPacket(BYTE*& p, long& len)
00096 {
00097 GUID majortype = m_mt.majortype;
00098
00099 if(majortype == MEDIATYPE_MPEG2_PACK || majortype == MEDIATYPE_DVD_ENCRYPTED_PACK)
00100 if(len > 0 && *(DWORD*)p == 0xba010000)
00101 {
00102 len -= 14; p += 14;
00103 if(int stuffing = (p[-1]&7)) {len -= stuffing; p += stuffing;}
00104 majortype = MEDIATYPE_MPEG2_PES;
00105 }
00106
00107 if(majortype == MEDIATYPE_MPEG2_PES)
00108 if(len > 0 && *(DWORD*)p == 0xbb010000)
00109 {
00110 len -= 4; p += 4;
00111 int hdrlen = ((p[0]<<8)|p[1]) + 2;
00112 len -= hdrlen; p += hdrlen;
00113 }
00114
00115 if(majortype == MEDIATYPE_MPEG2_PES)
00116 if(len > 0
00117 && ((*(DWORD*)p&0xf0ffffff) == 0xe0010000
00118 || (*(DWORD*)p&0xe0ffffff) == 0xc0010000
00119 || (*(DWORD*)p&0xbdffffff) == 0xbd010000))
00120 {
00121 bool ps1 = (*(DWORD*)p&0xbdffffff) == 0xbd010000;
00122
00123 len -= 4; p += 4;
00124 int expected = ((p[0]<<8)|p[1]);
00125 len -= 2; p += 2;
00126 BYTE* p0 = p;
00127
00128 for(int i = 0; i < 16 && *p == 0xff; i++, len--, p++);
00129
00130 if((*p&0xc0) == 0x80)
00131 {
00132 len -= 2; p += 2;
00133 len -= *p+1; p += *p+1;
00134 }
00135 else
00136 {
00137 if((*p&0xc0) == 0x40)
00138 {
00139 len -= 2; p += 2;
00140 }
00141
00142 if((*p&0x30) == 0x30 || (*p&0x30) == 0x20)
00143 {
00144 bool pts = !!(*p&0x20), dts = !!(*p&0x10);
00145 if(pts) len -= 5; p += 5;
00146 if(dts) {ASSERT((*p&0xf0) == 0x10); len -= 5; p += 5;}
00147 }
00148 else
00149 {
00150 len--; p++;
00151 }
00152 }
00153
00154 if(ps1)
00155 {
00156 len--; p++;
00157 if(m_mt.subtype == MEDIASUBTYPE_DVD_LPCM_AUDIO) {len -= 6; p += 6;}
00158 else if(m_mt.subtype == MEDIASUBTYPE_DOLBY_AC3 || m_mt.subtype == MEDIASUBTYPE_WAVE_DOLBY_AC3
00159 || m_mt.subtype == MEDIASUBTYPE_DTS || m_mt.subtype == MEDIASUBTYPE_WAVE_DTS) {len -= 3; p += 3;}
00160 }
00161
00162 if(expected > 0)
00163 {
00164 expected -= (p - p0);
00165 len = min(expected, len);
00166 }
00167 }
00168
00169 if(len < 0) {ASSERT(0); len = 0;}
00170 }
00171
00172
00173
00174 STDMETHODIMP CDeCSSInputPin::Set(REFGUID PropSet, ULONG Id, LPVOID pInstanceData, ULONG InstanceLength, LPVOID pPropertyData, ULONG DataLength)
00175 {
00176 if(PropSet != AM_KSPROPSETID_CopyProt)
00177 return E_NOTIMPL;
00178
00179 switch(Id)
00180 {
00181 case AM_PROPERTY_COPY_MACROVISION:
00182 break;
00183 case AM_PROPERTY_DVDCOPY_CHLG_KEY:
00184 {
00185 AM_DVDCOPY_CHLGKEY* pChlgKey = (AM_DVDCOPY_CHLGKEY*)pPropertyData;
00186 for(int i = 0; i < 10; i++)
00187 m_Challenge[i] = pChlgKey->ChlgKey[9-i];
00188
00189 CSSkey2(m_varient, m_Challenge, &m_Key[5]);
00190
00191 CSSbuskey(m_varient, m_Key, m_KeyCheck);
00192 }
00193 break;
00194 case AM_PROPERTY_DVDCOPY_DISC_KEY:
00195 {
00196 AM_DVDCOPY_DISCKEY* pDiscKey = (AM_DVDCOPY_DISCKEY*)pPropertyData;
00197
00198 bool fSuccess = false;
00199
00200 for(int j = 0; j < g_nPlayerKeys; j++)
00201 {
00202 for(int k = 1; k < 409; k++)
00203 {
00204 BYTE DiscKey[6];
00205 for(int i = 0; i < 5; i++)
00206 DiscKey[i] = pDiscKey->DiscKey[k*5+i] ^ m_KeyCheck[4-i];
00207 DiscKey[5] = 0;
00208
00209 CSSdisckey(DiscKey, g_PlayerKeys[j]);
00210
00211 BYTE Hash[6];
00212 for(int i = 0; i < 5; i++)
00213 Hash[i] = pDiscKey->DiscKey[i] ^ m_KeyCheck[4-i];
00214 Hash[5] = 0;
00215
00216 CSSdisckey(Hash, DiscKey);
00217
00218 if(!memcmp(Hash, DiscKey, 6))
00219 {
00220 memcpy(m_DiscKey, DiscKey, 6);
00221 j = g_nPlayerKeys;
00222 fSuccess = true;
00223 break;
00224 }
00225 }
00226 }
00227
00228 if(!fSuccess)
00229 return E_FAIL;
00230 }
00231 break;
00232 case AM_PROPERTY_DVDCOPY_DVD_KEY1:
00233 {
00234 AM_DVDCOPY_BUSKEY* pKey1 = (AM_DVDCOPY_BUSKEY*)pPropertyData;
00235 for(int i = 0; i < 5; i++)
00236 m_Key[i] = pKey1->BusKey[4-i];
00237
00238 m_varient = -1;
00239
00240 for(int i = 31; i >= 0; i--)
00241 {
00242 CSSkey1(i, m_Challenge, m_KeyCheck);
00243
00244 if(memcmp(m_KeyCheck, &m_Key[0], 5) == 0)
00245 m_varient = i;
00246 }
00247 }
00248 break;
00249 case AM_PROPERTY_DVDCOPY_REGION:
00250 break;
00251 case AM_PROPERTY_DVDCOPY_SET_COPY_STATE:
00252 break;
00253 case AM_PROPERTY_DVDCOPY_TITLE_KEY:
00254 {
00255 AM_DVDCOPY_TITLEKEY* pTitleKey = (AM_DVDCOPY_TITLEKEY*)pPropertyData;
00256 for(int i = 0; i < 5; i++)
00257 m_TitleKey[i] = pTitleKey->TitleKey[i] ^ m_KeyCheck[4-i];
00258 m_TitleKey[5] = 0;
00259 CSStitlekey(m_TitleKey, m_DiscKey);
00260 }
00261 break;
00262 default:
00263 return E_PROP_ID_UNSUPPORTED;
00264 }
00265
00266 return S_OK;
00267 }
00268
00269 STDMETHODIMP CDeCSSInputPin::Get(REFGUID PropSet, ULONG Id, LPVOID pInstanceData, ULONG InstanceLength, LPVOID pPropertyData, ULONG DataLength, ULONG* pBytesReturned)
00270 {
00271 if(PropSet != AM_KSPROPSETID_CopyProt)
00272 return E_NOTIMPL;
00273
00274 switch(Id)
00275 {
00276 case AM_PROPERTY_DVDCOPY_CHLG_KEY:
00277 {
00278 AM_DVDCOPY_CHLGKEY* pChlgKey = (AM_DVDCOPY_CHLGKEY*)pPropertyData;
00279 for(int i = 0; i < 10; i++)
00280 pChlgKey->ChlgKey[i] = 9 - (m_Challenge[i] = i);
00281 *pBytesReturned = sizeof(AM_DVDCOPY_CHLGKEY);
00282 }
00283 break;
00284 case AM_PROPERTY_DVDCOPY_DEC_KEY2:
00285 {
00286 AM_DVDCOPY_BUSKEY* pKey2 = (AM_DVDCOPY_BUSKEY*)pPropertyData;
00287 for(int i = 0; i < 5; i++)
00288 pKey2->BusKey[4-i] = m_Key[5+i];
00289 *pBytesReturned = sizeof(AM_DVDCOPY_BUSKEY);
00290 }
00291 break;
00292 case AM_PROPERTY_DVDCOPY_REGION:
00293 {
00294 DVD_REGION* pRegion = (DVD_REGION*)pPropertyData;
00295 pRegion->RegionData = 0;
00296 pRegion->SystemRegion = 0;
00297 *pBytesReturned = sizeof(DVD_REGION);
00298 }
00299 break;
00300 case AM_PROPERTY_DVDCOPY_SET_COPY_STATE:
00301 {
00302 AM_DVDCOPY_SET_COPY_STATE* pState = (AM_DVDCOPY_SET_COPY_STATE*)pPropertyData;
00303 pState->DVDCopyState = AM_DVDCOPYSTATE_AUTHENTICATION_REQUIRED;
00304 *pBytesReturned = sizeof(AM_DVDCOPY_SET_COPY_STATE);
00305 }
00306 break;
00307 default:
00308 return E_PROP_ID_UNSUPPORTED;
00309 }
00310
00311 return S_OK;
00312 }
00313
00314 STDMETHODIMP CDeCSSInputPin::QuerySupported(REFGUID PropSet, ULONG Id, ULONG* pTypeSupport)
00315 {
00316 if(PropSet != AM_KSPROPSETID_CopyProt)
00317 return E_NOTIMPL;
00318
00319 switch(Id)
00320 {
00321 case AM_PROPERTY_COPY_MACROVISION:
00322 *pTypeSupport = KSPROPERTY_SUPPORT_SET;
00323 break;
00324 case AM_PROPERTY_DVDCOPY_CHLG_KEY:
00325 *pTypeSupport = KSPROPERTY_SUPPORT_GET | KSPROPERTY_SUPPORT_SET;
00326 break;
00327 case AM_PROPERTY_DVDCOPY_DEC_KEY2:
00328 *pTypeSupport = KSPROPERTY_SUPPORT_GET;
00329 break;
00330 case AM_PROPERTY_DVDCOPY_DISC_KEY:
00331 *pTypeSupport = KSPROPERTY_SUPPORT_SET;
00332 break;
00333 case AM_PROPERTY_DVDCOPY_DVD_KEY1:
00334 *pTypeSupport = KSPROPERTY_SUPPORT_SET;
00335 break;
00336 case AM_PROPERTY_DVDCOPY_REGION:
00337 *pTypeSupport = KSPROPERTY_SUPPORT_GET | KSPROPERTY_SUPPORT_SET;
00338 break;
00339 case AM_PROPERTY_DVDCOPY_SET_COPY_STATE:
00340 *pTypeSupport = KSPROPERTY_SUPPORT_GET | KSPROPERTY_SUPPORT_SET;
00341 break;
00342 case AM_PROPERTY_DVDCOPY_TITLE_KEY:
00343 *pTypeSupport = KSPROPERTY_SUPPORT_SET;
00344 break;
00345 default:
00346 return E_PROP_ID_UNSUPPORTED;
00347 }
00348
00349 return S_OK;
00350 }