- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# CDXAReader.cpp

    00001 /*
    00002  *      Copyright (C) 2003-2005 Gabest
    00003  *      http://www.gabest.org
    00004  *
    00005  *  This Program is free software; you can redistribute it and/or modify
    00006  *  it under the terms of the GNU General Public License as published by
    00007  *  the Free Software Foundation; either version 2, or (at your option)
    00008  *  any later version.
    00009  *
    00010  *  This Program is distributed in the hope that it will be useful,
    00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    00013  *  GNU General Public License for more details.
    00014  *
    00015  *  You should have received a copy of the GNU General Public License
    00016  *  along with GNU Make; see the file COPYING.  If not, write to
    00017  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
    00018  *  http://www.gnu.org/copyleft/gpl.html
    00019  *
    00020  */
    00021
    00022 #include "stdafx.h"
    00023 #include <initguid.h>
    00024 #include <uuids.h>
    00025 #include "cdxareader.h"
    00026 #include "..\..\..\..\include\matroska\matroska.h"
    00027 #include "..\..\..\..\include\ogg\OggDS.h"
    00028 #include "..\..\..\..\include\moreuuids.h"
    00029 #include "..\..\..\DSUtil\DSUtil.h"
    00030
    00032
    00033 static DWORD EDC_crctable[256] =
    00034 {
    00035         0x00000000l, 0x90910101l, 0x91210201l, 0x01b00300l,
    00036         0x92410401l, 0x02d00500l, 0x03600600l, 0x93f10701l,
    00037         0x94810801l, 0x04100900l, 0x05a00a00l, 0x95310b01l,
    00038         0x06c00c00l, 0x96510d01l, 0x97e10e01l, 0x07700f00l,
    00039         0x99011001l, 0x09901100l, 0x08201200l, 0x98b11301l,
    00040         0x0b401400l, 0x9bd11501l, 0x9a611601l, 0x0af01700l,
    00041         0x0d801800l, 0x9d111901l, 0x9ca11a01l, 0x0c301b00l,
    00042         0x9fc11c01l, 0x0f501d00l, 0x0ee01e00l, 0x9e711f01l,
    00043         0x82012001l, 0x12902100l, 0x13202200l, 0x83b12301l,
    00044         0x10402400l, 0x80d12501l, 0x81612601l, 0x11f02700l,
    00045         0x16802800l, 0x86112901l, 0x87a12a01l, 0x17302b00l,
    00046         0x84c12c01l, 0x14502d00l, 0x15e02e00l, 0x85712f01l,
    00047         0x1b003000l, 0x8b913101l, 0x8a213201l, 0x1ab03300l,
    00048         0x89413401l, 0x19d03500l, 0x18603600l, 0x88f13701l,
    00049         0x8f813801l, 0x1f103900l, 0x1ea03a00l, 0x8e313b01l,
    00050         0x1dc03c00l, 0x8d513d01l, 0x8ce13e01l, 0x1c703f00l,
    00051         0xb4014001l, 0x24904100l, 0x25204200l, 0xb5b14301l,
    00052         0x26404400l, 0xb6d14501l, 0xb7614601l, 0x27f04700l,
    00053         0x20804800l, 0xb0114901l, 0xb1a14a01l, 0x21304b00l,
    00054         0xb2c14c01l, 0x22504d00l, 0x23e04e00l, 0xb3714f01l,
    00055         0x2d005000l, 0xbd915101l, 0xbc215201l, 0x2cb05300l,
    00056         0xbf415401l, 0x2fd05500l, 0x2e605600l, 0xbef15701l,
    00057         0xb9815801l, 0x29105900l, 0x28a05a00l, 0xb8315b01l,
    00058         0x2bc05c00l, 0xbb515d01l, 0xbae15e01l, 0x2a705f00l,
    00059         0x36006000l, 0xa6916101l, 0xa7216201l, 0x37b06300l,
    00060         0xa4416401l, 0x34d06500l, 0x35606600l, 0xa5f16701l,
    00061         0xa2816801l, 0x32106900l, 0x33a06a00l, 0xa3316b01l,
    00062         0x30c06c00l, 0xa0516d01l, 0xa1e16e01l, 0x31706f00l,
    00063         0xaf017001l, 0x3f907100l, 0x3e207200l, 0xaeb17301l,
    00064         0x3d407400l, 0xadd17501l, 0xac617601l, 0x3cf07700l,
    00065         0x3b807800l, 0xab117901l, 0xaaa17a01l, 0x3a307b00l,
    00066         0xa9c17c01l, 0x39507d00l, 0x38e07e00l, 0xa8717f01l,
    00067         0xd8018001l, 0x48908100l, 0x49208200l, 0xd9b18301l,
    00068         0x4a408400l, 0xdad18501l, 0xdb618601l, 0x4bf08700l,
    00069         0x4c808800l, 0xdc118901l, 0xdda18a01l, 0x4d308b00l,
    00070         0xdec18c01l, 0x4e508d00l, 0x4fe08e00l, 0xdf718f01l,
    00071         0x41009000l, 0xd1919101l, 0xd0219201l, 0x40b09300l,
    00072         0xd3419401l, 0x43d09500l, 0x42609600l, 0xd2f19701l,
    00073         0xd5819801l, 0x45109900l, 0x44a09a00l, 0xd4319b01l,
    00074         0x47c09c00l, 0xd7519d01l, 0xd6e19e01l, 0x46709f00l,
    00075         0x5a00a000l, 0xca91a101l, 0xcb21a201l, 0x5bb0a300l,
    00076         0xc841a401l, 0x58d0a500l, 0x5960a600l, 0xc9f1a701l,
    00077         0xce81a801l, 0x5e10a900l, 0x5fa0aa00l, 0xcf31ab01l,
    00078         0x5cc0ac00l, 0xcc51ad01l, 0xcde1ae01l, 0x5d70af00l,
    00079         0xc301b001l, 0x5390b100l, 0x5220b200l, 0xc2b1b301l,
    00080         0x5140b400l, 0xc1d1b501l, 0xc061b601l, 0x50f0b700l,
    00081         0x5780b800l, 0xc711b901l, 0xc6a1ba01l, 0x5630bb00l,
    00082         0xc5c1bc01l, 0x5550bd00l, 0x54e0be00l, 0xc471bf01l,
    00083         0x6c00c000l, 0xfc91c101l, 0xfd21c201l, 0x6db0c300l,
    00084         0xfe41c401l, 0x6ed0c500l, 0x6f60c600l, 0xfff1c701l,
    00085         0xf881c801l, 0x6810c900l, 0x69a0ca00l, 0xf931cb01l,
    00086         0x6ac0cc00l, 0xfa51cd01l, 0xfbe1ce01l, 0x6b70cf00l,
    00087         0xf501d001l, 0x6590d100l, 0x6420d200l, 0xf4b1d301l,
    00088         0x6740d400l, 0xf7d1d501l, 0xf661d601l, 0x66f0d700l,
    00089         0x6180d800l, 0xf111d901l, 0xf0a1da01l, 0x6030db00l,
    00090         0xf3c1dc01l, 0x6350dd00l, 0x62e0de00l, 0xf271df01l,
    00091         0xee01e001l, 0x7e90e100l, 0x7f20e200l, 0xefb1e301l,
    00092         0x7c40e400l, 0xecd1e501l, 0xed61e601l, 0x7df0e700l,
    00093         0x7a80e800l, 0xea11e901l, 0xeba1ea01l, 0x7b30eb00l,
    00094         0xe8c1ec01l, 0x7850ed00l, 0x79e0ee00l, 0xe971ef01l,
    00095         0x7700f000l, 0xe791f101l, 0xe621f201l, 0x76b0f300l,
    00096         0xe541f401l, 0x75d0f500l, 0x7460f600l, 0xe4f1f701l,
    00097         0xe381f801l, 0x7310f900l, 0x72a0fa00l, 0xe231fb01l,
    00098         0x71c0fc00l, 0xe151fd01l, 0xe0e1fe01l, 0x7070ff00l
    00099 };
    00100
    00101 static DWORD build_edc(const void* in, unsigned from, unsigned upto)
    00102 {
    00103         const BYTE* p = (BYTE*)in + from;
    00104         DWORD result = 0;
    00105
    00106         for(; from < upto; from++)
    00107                 result = EDC_crctable[(result ^ *p++) & 0xffL] ^ (result >> 8);
    00108
    00109         return result;
    00110 }
    00111
    00113
    00114 #ifdef REGISTER_FILTER
    00115
    00116 const AMOVIESETUP_MEDIATYPE sudPinTypesOut[] =
    00117 {
    00118         {&MEDIATYPE_Stream, &MEDIASUBTYPE_NULL}
    00119 };
    00120
    00121 const AMOVIESETUP_PIN sudOpPin[] =
    00122 {
    00123         {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesOut), sudPinTypesOut}
    00124 };
    00125
    00126 const AMOVIESETUP_FILTER sudFilter[] =
    00127 {
    00128         {&__uuidof(CCDXAReader), L"CDXA Reader", MERIT_UNLIKELY, countof(sudOpPin), sudOpPin}
    00129 };
    00130
    00131 CFactoryTemplate g_Templates[] =
    00132 {
    00133         {sudFilter[0].strName, sudFilter[0].clsID, CreateInstance<CCDXAReader>, NULL, &sudFilter[0]}
    00134 };
    00135
    00136 int g_cTemplates = countof(g_Templates);
    00137
    00138 STDAPI DllRegisterServer()
    00139 {
    00140         SetRegKeyValue(
    00141                 _T("Media Type\\{e436eb83-524f-11ce-9f53-0020af0ba770}"), _T("{D367878E-F3B8-4235-A968-F378EF1B9A44}"),
    00142                 _T("0"), _T("0,4,,52494646,8,4,,43445841")); // "RIFFxxxxCDXA"
    00143
    00144         SetRegKeyValue(
    00145                 _T("Media Type\\{e436eb83-524f-11ce-9f53-0020af0ba770}"), _T("{D367878E-F3B8-4235-A968-F378EF1B9A44}"),
    00146                 _T("Source Filter"), _T("{D367878E-F3B8-4235-A968-F378EF1B9A44}"));
    00147
    00148         return AMovieDllRegisterServer2(TRUE);
    00149 }
    00150
    00151 STDAPI DllUnregisterServer()
    00152 {
    00153         DeleteRegKey(_T("Media Type\\{e436eb83-524f-11ce-9f53-0020af0ba770}"), _T("{D367878E-F3B8-4235-A968-F378EF1B9A44}"));
    00154
    00155         return AMovieDllRegisterServer2(FALSE);
    00156 }
    00157
    00158 extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
    00159
    00160 BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
    00161 {
    00162     return DllEntryPoint((HINSTANCE)hModule, dwReason, 0); // "DllMain" of the dshow baseclasses;
    00163 }
    00164
    00165 #endif
    00166
    00167 //
    00168 // CCDXAReader
    00169 //
    00170
    00171 CCDXAReader::CCDXAReader(IUnknown* pUnk, HRESULT* phr)
    00172         : CAsyncReader(NAME("CCDXAReader"), pUnk, &m_stream, phr, __uuidof(this))
    00173 {
    00174         if(phr) *phr = S_OK;
    00175 }
    00176
    00177 CCDXAReader::~CCDXAReader()
    00178 {
    00179 }
    00180
    00181 STDMETHODIMP CCDXAReader::NonDelegatingQueryInterface(REFIID riid, void** ppv)
    00182 {
    00183         return
    00184                 QI(IFileSourceFilter)
    00185                 __super::NonDelegatingQueryInterface(riid, ppv);
    00186 }
    00187
    00188 STDMETHODIMP CCDXAReader::Load(LPCOLESTR pszFileName, const AM_MEDIA_TYPE *pmt)
    00189 {
    00190         CMediaType mt;
    00191         m_mt = mt;
    00192
    00193         if(!m_stream.Load(pszFileName))
    00194                 return E_FAIL;
    00195
    00196         m_fn = pszFileName;
    00197
    00198         mt.majortype = MEDIATYPE_Stream;
    00199         mt.subtype = m_stream.m_subtype;
    00200         m_mt = mt;
    00201
    00202         return S_OK;
    00203 }
    00204
    00205 STDMETHODIMP CCDXAReader::GetCurFile(LPOLESTR* ppszFileName, AM_MEDIA_TYPE* pmt)
    00206 {
    00207         if(!ppszFileName) return E_POINTER;
    00208
    00209         if(!(*ppszFileName = (LPOLESTR)CoTaskMemAlloc((m_fn.GetLength()+1)*sizeof(WCHAR))))
    00210                 return E_OUTOFMEMORY;
    00211
    00212         wcscpy(*ppszFileName, m_fn);
    00213
    00214         return S_OK;
    00215 }
    00216
    00217 // CCDXAStream
    00218
    00219 CCDXAStream::CCDXAStream()
    00220 {
    00221         m_subtype = MEDIASUBTYPE_NULL;
    00222
    00223         m_hFile = INVALID_HANDLE_VALUE;
    00224
    00225         m_llPosition = m_llLength = 0;
    00226         m_nFirstSector = 0;
    00227         m_nBufferedSector = -1;
    00228 }
    00229
    00230 CCDXAStream::~CCDXAStream()
    00231 {
    00232         if(m_hFile != INVALID_HANDLE_VALUE)
    00233         {
    00234                 CloseHandle(m_hFile);
    00235                 m_hFile = INVALID_HANDLE_VALUE;
    00236         }
    00237 }
    00238
    00239 bool CCDXAStream::Load(const WCHAR* fnw)
    00240 {
    00241         if(m_hFile != INVALID_HANDLE_VALUE)
    00242         {
    00243                 CloseHandle(m_hFile);
    00244                 m_hFile = INVALID_HANDLE_VALUE;
    00245         }
    00246
    00247         m_hFile = CreateFile(CString(fnw), GENERIC_READ, FILE_SHARE_READ, NULL,
    00248                 OPEN_EXISTING, FILE_ATTRIBUTE_READONLY|FILE_FLAG_SEQUENTIAL_SCAN, (HANDLE)NULL);
    00249         if(m_hFile == INVALID_HANDLE_VALUE)
    00250         {
    00251                 return(false);
    00252         }
    00253
    00254         BYTE hdr[RIFFCDXA_HEADER_SIZE];
    00255         DWORD NumberOfBytesRead;
    00256         if(!ReadFile(m_hFile, (LPVOID)hdr, RIFFCDXA_HEADER_SIZE, &NumberOfBytesRead, NULL)
    00257         || *((DWORD*)&hdr[0]) != 'FFIR' || *((DWORD*)&hdr[8]) != 'AXDC'
    00258         || *((DWORD*)&hdr[4]) != (*((DWORD*)&hdr[0x28])+0x24))
    00259         {
    00260                 CloseHandle(m_hFile);
    00261                 m_hFile = INVALID_HANDLE_VALUE;
    00262                 return(false);
    00263         }
    00264
    00265         LARGE_INTEGER size = {0, 0};
    00266         size.LowPart = (LONG)GetFileSize(m_hFile, (LPDWORD)&size.HighPart);
    00267
    00268         m_llLength = int((size.QuadPart - RIFFCDXA_HEADER_SIZE) / RAW_SECTOR_SIZE) * RAW_DATA_SIZE;
    00269
    00270         if(!LookForMediaSubType())
    00271         {
    00272                 m_llPosition = m_llLength = 0;
    00273                 CloseHandle(m_hFile);
    00274                 m_hFile = INVALID_HANDLE_VALUE;
    00275                 return(false);
    00276         }
    00277
    00278         m_llPosition = 0;
    00279
    00280         m_nBufferedSector = -1;
    00281
    00282         return(true);
    00283 }
    00284
    00285 HRESULT CCDXAStream::SetPointer(LONGLONG llPos)
    00286 {
    00287         return (llPos >= 0 && llPos < m_llLength) ? m_llPosition = llPos, S_OK : S_FALSE;
    00288 }
    00289
    00290 HRESULT CCDXAStream::Read(PBYTE pbBuffer, DWORD dwBytesToRead, BOOL bAlign, LPDWORD pdwBytesRead)
    00291 {
    00292         CAutoLock lck(&m_csLock);
    00293
    00294         PBYTE pbBufferOrg = pbBuffer;
    00295         LONGLONG pos = m_llPosition;
    00296
    00297         while(pos >= 0 && pos < m_llLength && dwBytesToRead > 0)
    00298         {
    00299                 UINT sector = m_nFirstSector + int(pos/RAW_DATA_SIZE);
    00300                 __int64 offset = pos%RAW_DATA_SIZE;
    00301
    00302                 if(m_nBufferedSector != sector)
    00303                 {
    00304                         LARGE_INTEGER FilePointer;
    00305                         FilePointer.QuadPart = RIFFCDXA_HEADER_SIZE + sector*RAW_SECTOR_SIZE;
    00306                         SetFilePointer(m_hFile, (LONG)FilePointer.LowPart, (PLONG)&FilePointer.HighPart, FILE_BEGIN);
    00307
    00308                         memset(m_sector, 0, sizeof(m_sector));
    00309
    00310                         DWORD NumberOfBytesRead = 0;
    00311
    00312                         int nRetries = 3;
    00313                         while(nRetries--)
    00314                         {
    00315                                 NumberOfBytesRead = 0;
    00316                                 if(!ReadFile(m_hFile, m_sector, RAW_SECTOR_SIZE, &NumberOfBytesRead, NULL)
    00317                                 || NumberOfBytesRead != RAW_SECTOR_SIZE)
    00318                                         break;
    00319
    00320                                 if(*(DWORD*)&m_sector[RAW_SECTOR_SIZE-4] == 0) // no CRC? it happens...
    00321                                         break;
    00322
    00323                                 if(build_edc(m_sector, RAW_SYNC_SIZE + RAW_HEADER_SIZE, RAW_SECTOR_SIZE) == 0)
    00324                                         break;
    00325
    00326                                 TRACE(_T("CCDXAStream: CRC error at sector %d (fp=0x%I64x, retriesleft=%d)\n"), sector, FilePointer.QuadPart, nRetries);
    00327                         }
    00328
    00329                         m_nBufferedSector = sector;
    00330                 }
    00331
    00332                 DWORD l = min(min(dwBytesToRead, RAW_DATA_SIZE - offset), m_llLength - pos);
    00333                 memcpy(pbBuffer, &m_sector[RAW_SYNC_SIZE + RAW_HEADER_SIZE + RAW_SUBHEADER_SIZE + offset], l);
    00334
    00335                 pbBuffer += l;
    00336                 pos += l;
    00337                 dwBytesToRead -= l;
    00338         }
    00339
    00340         if(pdwBytesRead) *pdwBytesRead = pbBuffer - pbBufferOrg;
    00341         m_llPosition += pbBuffer - pbBufferOrg;
    00342
    00343         if(dwBytesToRead != 0) return S_FALSE;
    00344
    00345         return S_OK;
    00346 }
    00347
    00348 LONGLONG CCDXAStream::Size(LONGLONG* pSizeAvailable)
    00349 {
    00350         if(pSizeAvailable) *pSizeAvailable = m_llLength;
    00351     return m_llLength;
    00352 }
    00353
    00354 DWORD CCDXAStream::Alignment()
    00355 {
    00356     return 1;
    00357 }
    00358
    00359 void CCDXAStream::Lock()
    00360 {
    00361     m_csLock.Lock();
    00362 }
    00363
    00364 void CCDXAStream::Unlock()
    00365 {
    00366     m_csLock.Unlock();
    00367 }
    00368
    00369 //
    00370
    00371 bool CCDXAStream::LookForMediaSubType()
    00372 {
    00373         BYTE buff[RAW_DATA_SIZE];
    00374
    00375         m_subtype = MEDIASUBTYPE_NULL;
    00376
    00377         m_llPosition = 0;
    00378
    00379         for(int iSectorsRead = 0;
    00380                 Read(buff, RAW_DATA_SIZE, 1, NULL) == S_OK && iSectorsRead < 1000;
    00381                 iSectorsRead++)
    00382         {
    00383                 if(*((DWORD*)&buff[0]) == 0xba010000)
    00384                 {
    00385                         m_llPosition = 0;
    00386                         m_llLength -= iSectorsRead*RAW_DATA_SIZE;
    00387                         m_nFirstSector = iSectorsRead;
    00388
    00389                         if((buff[4]&0xc4) == 0x44) m_subtype = MEDIASUBTYPE_MPEG2_PROGRAM;
    00390                         else if((buff[4]&0xf1) == 0x21) m_subtype = MEDIASUBTYPE_MPEG1System;
    00391
    00392                         return m_subtype != MEDIASUBTYPE_NULL;
    00393                 }
    00394                 else if(*((DWORD*)&buff[0]) == 'SggO')
    00395                 {
    00396                         m_llPosition = 0;
    00397                         m_llLength -= iSectorsRead*RAW_DATA_SIZE;
    00398                         m_nFirstSector = iSectorsRead;
    00399
    00400                         m_subtype = MEDIASUBTYPE_Ogg;
    00401
    00402                         return(true);
    00403                 }
    00404                 else if(*((DWORD*)&buff[0]) == 0xA3DF451A)
    00405                 {
    00406                         m_llPosition = 0;
    00407                         m_llLength -= iSectorsRead*RAW_DATA_SIZE;
    00408                         m_nFirstSector = iSectorsRead;
    00409
    00410                         m_subtype = MEDIASUBTYPE_Matroska;
    00411
    00412                         return(true);
    00413                 }
    00414                 else if(*((DWORD*)&buff[0]) == 'FMR.')
    00415                 {
    00416                         m_llPosition = 0;
    00417                         m_llLength -= iSectorsRead*RAW_DATA_SIZE;
    00418                         m_nFirstSector = iSectorsRead;
    00419
    00420                         m_subtype = MEDIASUBTYPE_RealMedia;
    00421
    00422                         return(true);
    00423                 }
    00424                 else if(*((DWORD*)&buff[0]) == 'FFIR' && *((DWORD*)&buff[8]) == ' IVA')
    00425                 {
    00426                         m_llPosition = 0;
    00427                         m_llLength = min(m_llLength, *((DWORD*)&buff[4])+8);
    00428                         m_nFirstSector = iSectorsRead;
    00429
    00430                         m_subtype = MEDIASUBTYPE_Avi;
    00431
    00432                         return(true);
    00433                 }
    00434                 else if(*((DWORD*)&buff[4]) == 'voom' || *((DWORD*)&buff[4]) == 'tadm'
    00435                 || *((DWORD*)&buff[4]) == 'pytf' && *((DWORD*)&buff[8]) == 'mosi' && *((DWORD*)&buff[16]) == '14pm')
    00436                 {
    00437                         m_llPosition = 0;
    00438                         m_llLength -= iSectorsRead*RAW_DATA_SIZE;
    00439                         m_nFirstSector = iSectorsRead;
    00440
    00441                         m_subtype = MEDIASUBTYPE_QTMovie;
    00442
    00443                         return(true);
    00444                 }
    00445         }
    00446
    00447         m_llPosition = 0;
    00448
    00449         CRegKey majorkey;
    00450         CString majortype = _T("\\Media Type\\{e436eb83-524f-11ce-9f53-0020af0ba770}");
    00451         if(ERROR_SUCCESS == majorkey.Open(HKEY_CLASSES_ROOT, majortype, KEY_READ))
    00452         {
    00453                 TCHAR subtype[256+1];
    00454                 DWORD len = 256;
    00455                 for(int i = 0; ERROR_SUCCESS == majorkey.EnumKey(i, subtype, &len); i++, len = 256)
    00456                 {
    00457                         CRegKey subkey;
    00458                         if(ERROR_SUCCESS != subkey.Open(HKEY_CLASSES_ROOT, majortype + _T("\\") + subtype, KEY_READ))
    00459                                 continue;
    00460
    00461                         for(int j = 0; true; j++)
    00462                         {
    00463                                 TCHAR number[10];
    00464                                 _stprintf(number, _T("%d"), j);
    00465
    00466                                 TCHAR pattern[256+1];
    00467                                 ULONG len = 256;
    00468                                 if(ERROR_SUCCESS != subkey.QueryStringValue(number, pattern, &len))
    00469                                         break;
    00470
    00471                                 CString p = pattern;
    00472                                 p += ',';
    00473
    00474                                 __int64 offset = 0;
    00475                                 DWORD cb = 0;
    00476                                 CByteArray mask, val;
    00477
    00478                                 int nMatches = 0, nTries = 0;
    00479
    00480                                 for(int k = 0, l; nTries >= 0 && (l = p.Find(',', k)) >= 0; k = l+1, nTries++)
    00481                                 {
    00482                                         CString s = p.Mid(k, l-k);
    00483                                         TRACE(s + '\n');
    00484
    00485                                         TCHAR* end = NULL;
    00486
    00487                                         switch(nTries&3)
    00488                                         {
    00489                                                 case 0: offset = _tcstol(s, &end, 10); break;
    00490                                                 case 1: cb = _tcstol(s, &end, 10); break;
    00491                                                 case 2: StringToBin(s, mask); break;
    00492                                                 case 3: StringToBin(s, val); break;
    00493                                                 default: nTries = -1; break;
    00494                                         }
    00495
    00496                                         if(nTries >= 0 && (nTries&3) == 3)
    00497                                         {
    00498                                                 if(cb > 0 && val.GetSize() > 0 && cb == val.GetSize())
    00499                                                 {
    00500                                                         if(offset >= 0 && S_OK == SetPointer(offset)
    00501                                                         || S_OK == SetPointer(m_llLength + offset))
    00502                                                         {
    00503                                                                 CAutoVectorPtr<BYTE> pData;
    00504                                                                 if(pData.Allocate(cb))
    00505                                                                 {
    00506                                                                         DWORD BytesRead = 0;
    00507                                                                         if(S_OK == Read(pData, cb, 1, &BytesRead) && cb == BytesRead)
    00508                                                                         {
    00509                                                                                 if(mask.GetSize() < cb)
    00510                                                                                 {
    00511                                                                                         int i = mask.GetSize();
    00512                                                                                         mask.SetSize(cb);
    00513                                                                                         for(; i < cb; i++) mask[i] = 0xff;
    00514                                                                                 }
    00515
    00516                                                                                 for(int i = 0; i < cb; i++)
    00517                                                                                         pData[i] &= (BYTE)mask[i];
    00518
    00519                                                                                 if(memcmp(pData, val.GetData(), cb) == 0)
    00520                                                                                         nMatches++;
    00521                                                                         }
    00522                                                                 }
    00523                                                         }
    00524
    00525                                                         offset = 0; cb = 0;
    00526                                                         mask.RemoveAll(); val.RemoveAll();
    00527                                                 }
    00528                                         }
    00529                                 }
    00530
    00531                                 if(nMatches > 0 && nMatches*4 == nTries)
    00532                                 {
    00533                                         m_subtype = GUIDFromCString(subtype);
    00534                                         return S_OK;
    00535                                 }
    00536                         }
    00537                 }
    00538         }
    00539
    00540         return(false);
    00541 }