HRESULT CBasePlayer::GetGdiplusEncoderClsid(__in LPCWSTR pwszFormat, __out GUID *pGUID) { HRESULT hr = E_FAIL; UINT nEncoders = 0; // number of image encoders UINT nSize = 0; // size of the image encoder array in bytes CAutoVectorPtr<BYTE> spData; Gdiplus::ImageCodecInfo* pImageCodecInfo = NULL; Gdiplus::Status status; bool fFound = false; // param check if ((pwszFormat == NULL) || (pwszFormat[0] == 0) || (pGUID == NULL)) { return E_POINTER; } *pGUID = GUID_NULL; status = Gdiplus::GetImageEncodersSize(&nEncoders, &nSize); if ((status != Gdiplus::Ok) || (nSize == 0)) { return E_FAIL; } spData.Allocate(nSize); if (spData == NULL) { return E_FAIL; } pImageCodecInfo = (Gdiplus::ImageCodecInfo*)(BYTE*)spData; status = Gdiplus::GetImageEncoders(nEncoders, nSize, pImageCodecInfo); if (status != Gdiplus::Ok) { return E_FAIL; } for (UINT j = 0; j < nEncoders; ++j) { if (wcscmp(pImageCodecInfo[j].MimeType, pwszFormat) == 0) { *pGUID = pImageCodecInfo[j].Clsid; fFound = true; break; } } hr = fFound ? S_OK : E_FAIL; return hr; }
HRESULT CUTF8::Parse(CMatroskaNode* pMN) { Empty(); CAutoVectorPtr<BYTE> buff; if (!buff.Allocate((UINT)pMN->m_len + 1) || S_OK != pMN->Read(buff, pMN->m_len)) { return E_FAIL; } buff[pMN->m_len] = 0; CStringW::operator = (UTF8To16((LPCSTR)(BYTE*)buff)); return S_OK; }
BOOL CAuthDlg::OnInitDialog() { CDialog::OnInitDialog(); CWinApp* pApp = AfxGetApp(); if (pApp->m_pszRegistryKey) { CRegKey hSecKey(pApp->GetSectionKey(IDS_R_LOGINS)); if (hSecKey) { int i = 0; TCHAR username[256], password[256]; for (;;) { DWORD unlen = _countof(username); DWORD pwlen = sizeof(password); DWORD type = REG_SZ; if (ERROR_SUCCESS == RegEnumValue(hSecKey, i++, username, &unlen, 0, &type, (BYTE*)password, &pwlen)) { m_logins[username] = DEncrypt(password); m_usernamectrl.AddString(username); } else { break; } } } } else { CAutoVectorPtr<TCHAR> buff; buff.Allocate(32767/sizeof(TCHAR)); DWORD len = GetPrivateProfileSection(IDS_R_LOGINS, buff, 32767/sizeof(TCHAR), pApp->m_pszProfileName); TCHAR* p = buff; while (*p && len > 0) { CString str = p; p += str.GetLength()+1; len -= str.GetLength()+1; CAtlList<CString> sl; Explode(str, sl, '=', 2); if (sl.GetCount() == 2) { m_logins[sl.GetHead()] = DEncrypt(sl.GetTail()); m_usernamectrl.AddString(sl.GetHead()); } } } m_usernamectrl.SetFocus(); return TRUE; }
LRESULT CALLBACK COpenFileDlg::WindowProcNew(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { if(message == WM_COMMAND && HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDOK && m_fAllowDirSelection) { CAutoVectorPtr<TCHAR> path; path.Allocate(MAX_PATH+1); // MAX_PATH should be bigger for multiple selection, but we are only interested if it's zero length // note: allocating MAX_PATH only will cause a buffer overrun for too long strings, and will result in a silent app disappearing crash, 100% reproducable if(::GetDlgItemText(hwnd, cmb13, (TCHAR*)path, MAX_PATH) == 0) ::SendMessage(hwnd, CDM_SETCONTROLTEXT, edt1, (LPARAM)__DUMMY__); } return CallWindowProc(COpenFileDlg::m_wndProc, hwnd, message, wParam, lParam); }
LRESULT CALLBACK COpenFileDlg::WindowProcNew(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { if (message == WM_COMMAND && HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDOK && m_fAllowDirSelection) { CAutoVectorPtr<TCHAR> path; path.Allocate(_MAX_PATH+1); if (::GetDlgItemText(hwnd, cmb13, (TCHAR*)path, _MAX_PATH) == 0) { ::SendMessage(hwnd, CDM_SETCONTROLTEXT, edt1, (LPARAM)__DUMMY__); } } return CallWindowProc(COpenFileDlg::m_wndProc, hwnd, message, wParam, lParam); }
bool CDVDSession::SendKey(DVD_KEY_TYPE KeyType, BYTE* pKeyData) { CAutoVectorPtr<BYTE> key; DVD_COPY_PROTECT_KEY* pKey = nullptr; auto allocateKey = [&](ULONG len) { bool bSuccess = key.Allocate(len); if (bSuccess) { pKey = (DVD_COPY_PROTECT_KEY*)(BYTE*)key; pKey->KeyLength = len; } return bSuccess; }; switch (KeyType) { case DvdChallengeKey: if (allocateKey(DVD_CHALLENGE_KEY_LENGTH)) { Reverse(pKey->KeyData, pKeyData, 10); } break; case DvdBusKey2: if (allocateKey(DVD_BUS_KEY_LENGTH)) { Reverse(pKey->KeyData, pKeyData, 5); } break; default: break; } if (!pKey) { return false; } pKey->SessionId = m_session; pKey->KeyType = KeyType; pKey->KeyFlags = 0; DWORD dwBytesReturned; return !!DeviceIoControl(m_hDrive, IOCTL_DVD_SEND_KEY, pKey, pKey->KeyLength, nullptr, 0, &dwBytesReturned, nullptr); }
// Save icon referenced by handle 'hIcon' as file with name 'szPath'. // The generated ICO file has the color depth specified in 'nColorBits'. // bool SaveIcon(HICON hIcon, DWORD& szSize ,int nColorBits, const TCHAR* szPath) { ASSERT(nColorBits == 4 || nColorBits == 8 || nColorBits == 24 || nColorBits == 32); if (offsetof(ICONDIRENTRY, nOffset) != 12) { return false; } CDC dc; dc.Attach(::GetDC(NULL)); // ensure that DC is released when function ends // Open file for writing: CFile file; if (!file.Open(szPath, CFile::modeWrite | CFile::modeCreate)) { return false; } // Write header: UCHAR icoHeader[6] = { 0, 0, 1, 0, 1, 0 }; // ICO file with 1 image file.Write(icoHeader, sizeof(icoHeader)); // Get information about icon: ICONINFO iconInfo; GetIconInfo(hIcon, &iconInfo); CGdiHandle handle1(iconInfo.hbmColor), handle2(iconInfo.hbmMask); // free bitmaps when function ends BITMAPINFO bmInfo = { 0 }; bmInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmInfo.bmiHeader.biBitCount = 0; // don't get the color table if (!GetDIBits(dc, iconInfo.hbmColor, 0, 0, NULL, &bmInfo, DIB_RGB_COLORS)) { return false; } // Allocate size of bitmap info header plus space for color table: int nBmInfoSize = sizeof(BITMAPINFOHEADER); if (nColorBits < 24) { nBmInfoSize += sizeof(RGBQUAD) * (int)(1 << nColorBits); } CAutoVectorPtr<UCHAR> bitmapInfo; bitmapInfo.Allocate(nBmInfoSize); BITMAPINFO* pBmInfo = (BITMAPINFO*)(UCHAR*)bitmapInfo; memcpy(pBmInfo, &bmInfo, sizeof(BITMAPINFOHEADER)); // Get bitmap data: ASSERT(bmInfo.bmiHeader.biSizeImage != 0); CAutoVectorPtr<UCHAR> bits; bits.Allocate(bmInfo.bmiHeader.biSizeImage); pBmInfo->bmiHeader.biBitCount = nColorBits; pBmInfo->bmiHeader.biCompression = BI_RGB; if (!GetDIBits(dc, iconInfo.hbmColor, 0, bmInfo.bmiHeader.biHeight, (UCHAR*)bits, pBmInfo, DIB_RGB_COLORS)) { return false; } // Get mask data: BITMAPINFO maskInfo = { 0 }; maskInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); maskInfo.bmiHeader.biBitCount = 0; // don't get the color table if (!GetDIBits(dc, iconInfo.hbmMask, 0, 0, NULL, &maskInfo, DIB_RGB_COLORS)) { return false; } ASSERT(maskInfo.bmiHeader.biBitCount == 1); CAutoVectorPtr<UCHAR> maskBits; maskBits.Allocate(maskInfo.bmiHeader.biSizeImage); CAutoVectorPtr<UCHAR> maskInfoBytes; maskInfoBytes.Allocate(sizeof(BITMAPINFO) + 2 * sizeof(RGBQUAD)); BITMAPINFO* pMaskInfo = (BITMAPINFO*)(UCHAR*)maskInfoBytes; memcpy(pMaskInfo, &maskInfo, sizeof(maskInfo)); if (!GetDIBits(dc, iconInfo.hbmMask, 0, maskInfo.bmiHeader.biHeight, (UCHAR*)maskBits, pMaskInfo, DIB_RGB_COLORS)) { return false; } // Write directory entry: ICONDIRENTRY dir; dir.nWidth = (UCHAR)pBmInfo->bmiHeader.biWidth; dir.nHeight = (UCHAR)pBmInfo->bmiHeader.biHeight; dir.nNumColorsInPalette = (nColorBits == 4 ? 16 : 0); dir.nReserved = 0; dir.nNumColorPlanes = 0; dir.nBitsPerPixel = pBmInfo->bmiHeader.biBitCount; dir.nDataLength = pBmInfo->bmiHeader.biSizeImage + pMaskInfo->bmiHeader.biSizeImage + nBmInfoSize; dir.nOffset = sizeof(dir) + sizeof(icoHeader); file.Write(&dir, sizeof(dir)); // Write DIB header (including color table): int nBitsSize = pBmInfo->bmiHeader.biSizeImage; pBmInfo->bmiHeader.biHeight *= 2; // because the header is for both image and mask pBmInfo->bmiHeader.biCompression = 0; pBmInfo->bmiHeader.biSizeImage += pMaskInfo->bmiHeader.biSizeImage; // because the header is for both image and mask file.Write(&pBmInfo->bmiHeader, nBmInfoSize); // Write image data: file.Write((UCHAR*)bits, nBitsSize); // Write mask data: file.Write((UCHAR*)maskBits, pMaskInfo->bmiHeader.biSizeImage); szSize = file.GetLength(); file.Close(); return true; }
bool CDVDSession::ReadKey(DVD_KEY_TYPE KeyType, BYTE* pKeyData, int lba) { CAutoVectorPtr<BYTE> key; DVD_COPY_PROTECT_KEY* pKey = nullptr; auto allocateKey = [&](ULONG len) { bool bSuccess = key.Allocate(len); if (bSuccess) { pKey = (DVD_COPY_PROTECT_KEY*)(BYTE*)key; pKey->KeyLength = len; } return bSuccess; }; switch (KeyType) { case DvdChallengeKey: if (allocateKey(DVD_CHALLENGE_KEY_LENGTH)) { pKey->Parameters.TitleOffset.QuadPart = 0; } break; case DvdBusKey1: if (allocateKey(DVD_BUS_KEY_LENGTH)) { pKey->Parameters.TitleOffset.QuadPart = 0; } break; case DvdDiskKey: if (allocateKey(DVD_DISK_KEY_LENGTH)) { pKey->Parameters.TitleOffset.QuadPart = 0; } break; case DvdTitleKey: if (allocateKey(DVD_TITLE_KEY_LENGTH)) { pKey->Parameters.TitleOffset.QuadPart = 2048i64 * lba; } break; default: break; } if (!pKey) { return false; } pKey->SessionId = m_session; pKey->KeyType = KeyType; pKey->KeyFlags = 0; DWORD dwBytesReturned; if (!DeviceIoControl(m_hDrive, IOCTL_DVD_READ_KEY, pKey, pKey->KeyLength, pKey, pKey->KeyLength, &dwBytesReturned, nullptr)) { DWORD err = GetLastError(); UNREFERENCED_PARAMETER(err); return false; } switch (KeyType) { case DvdChallengeKey: Reverse(pKeyData, pKey->KeyData, 10); break; case DvdBusKey1: Reverse(pKeyData, pKey->KeyData, 5); break; case DvdDiskKey: memcpy(pKeyData, pKey->KeyData, 2048); for (int i = 0; i < 2048 / 5; i++) { pKeyData[i] ^= m_SessionKey[4 - (i % 5)]; } break; case DvdTitleKey: memcpy(pKeyData, pKey->KeyData, 5); for (int i = 0; i < 5; i++) { pKeyData[i] ^= m_SessionKey[4 - (i % 5)]; } break; default: break; } return true; }
HRESULT ThreadController::EnumeratePropertyMembers(_In_ ULONG propertyId, _In_ UINT radix, _Inout_ vector<shared_ptr<PropertyInfo>>& spPropertyInfos) { ATLENSURE_RETURN_HR(ThreadHelpers::IsOnDispatchThread(m_dispatchThreadId), E_UNEXPECTED); // Lock the callframe access CComCritSecLock<CComAutoCriticalSection> lock(m_csCallFramesLock); if (!this->IsConnected() || !this->IsAtBreak()) { return E_NOT_VALID_STATE; } auto it = m_propertyMap.find(propertyId); if (it != m_propertyMap.end()) { CComPtr<IDebugProperty> spDebugProperty = it->second; // Get all the members for the children CComPtr<IEnumDebugPropertyInfo> spEnumProps; HRESULT hr = spDebugProperty->EnumMembers(PROP_INFO_ALL, radix, IID_IEnumDebugPropertyInfo, &spEnumProps); if (hr == E_NOTIMPL) { // This is reported in Watson, but we do not have a repro. Returning no properties is a // better experience than failing, until we can diagnose and avoid this case. _ASSERT_EXPR(false, L"IEnumDebugPropertyInfo->EnumMembers returned E_NOTIMPL"); return S_OK; } else if (hr == E_FAIL) { // The webcrawler hits an issue where the PDM returns E_FAIL. In this case we want to just // return an empty array back to the front end instead of asserting and blocking with a dialog. return S_OK; } BPT_FAIL_IF_NOT_S_OK(hr); hr = spEnumProps->Reset(); BPT_FAIL_IF_NOT_S_OK(hr); ULONG count; hr = spEnumProps->GetCount(&count); if (hr == S_OK) // Since GetCount can fail when walking the properties, we return the hr which results in an empty array { for (ULONG i = 0; i < count; i++) { // Fetch each child one at a time, if we fail to get all of them, we can return with the successful ones CAutoVectorPtr<DebugPropertyInfo> spDebugPropertyInfo; bool alloced = spDebugPropertyInfo.Allocate(1); ATLENSURE_RETURN_HR(alloced == true, E_OUTOFMEMORY); // Fetch the next child and add it to the list ULONG numFetched = 0; hr = spEnumProps->Next(1, spDebugPropertyInfo.m_p, &numFetched); if (hr == S_OK && numFetched == 1) // This can fail for certain properties (e.g. location) in some conditions (e.g. a navigation), so we just ignore and continue { // Get the property info shared_ptr<PropertyInfo> spPropertyInfo; hr = this->PopulatePropertyInfo(spDebugPropertyInfo[0], spPropertyInfo); if (hr == S_OK) { // Store this to the out parameter spPropertyInfos.push_back(spPropertyInfo); } } } } } else { return E_NOT_FOUND; } return S_OK; }
bool CCDDAStream::Load(const WCHAR* fnw) { CString path(fnw); int iDriveLetter = path.Find(_T(":\\")) - 1; int iTrackIndex = CString(path).MakeLower().Find(_T(".cda")) - 1; if (iDriveLetter < 0 || iTrackIndex <= iDriveLetter) { return false; } CString drive = CString(_T("\\\\.\\")) + path[iDriveLetter] + _T(":"); while (iTrackIndex > 0 && _istdigit(path[iTrackIndex - 1])) { iTrackIndex--; } if (1 != _stscanf_s(path.Mid(iTrackIndex), _T("%d"), &iTrackIndex)) { return false; } if (m_hDrive != INVALID_HANDLE_VALUE) { CloseHandle(m_hDrive); m_hDrive = INVALID_HANDLE_VALUE; } m_hDrive = CreateFile(drive, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY | FILE_FLAG_SEQUENTIAL_SCAN, (HANDLE)nullptr); if (m_hDrive == INVALID_HANDLE_VALUE) { return false; } DWORD BytesReturned; if (!DeviceIoControl(m_hDrive, IOCTL_CDROM_READ_TOC, nullptr, 0, &m_TOC, sizeof(m_TOC), &BytesReturned, 0) || !(m_TOC.FirstTrack <= iTrackIndex && iTrackIndex <= m_TOC.LastTrack)) { CloseHandle(m_hDrive); m_hDrive = INVALID_HANDLE_VALUE; return false; } // MMC-3 Draft Revision 10g: Table 222 - Q Sub-channel control field m_TOC.TrackData[iTrackIndex - 1].Control &= 5; if (!(m_TOC.TrackData[iTrackIndex - 1].Control == 0 || m_TOC.TrackData[iTrackIndex - 1].Control == 1)) { CloseHandle(m_hDrive); m_hDrive = INVALID_HANDLE_VALUE; return false; } if (m_TOC.TrackData[iTrackIndex - 1].Control & 8) { m_header.frm.pcm.wf.nChannels = 4; } m_nStartSector = MSF2UINT(m_TOC.TrackData[iTrackIndex - 1].Address) - 150; m_nStopSector = MSF2UINT(m_TOC.TrackData[iTrackIndex].Address) - 150; m_llLength = LONGLONG(m_nStopSector - m_nStartSector) * RAW_SECTOR_SIZE; m_header.riff.hdr.chunkSize = (long)(m_llLength + sizeof(m_header) - 8); m_header.data.hdr.chunkSize = (long)(m_llLength); // Detect DTS Music Disk m_bDTS = false; // DCA syncwords const DWORD DCA_MARKER_RAW_BE = 0x7FFE8001; const DWORD DCA_MARKER_RAW_LE = 0xFE7F0180; const DWORD DCA_MARKER_14B_BE = 0x1FFFE800; const DWORD DCA_MARKER_14B_LE = 0xFF1F00E8; UINT nMarkerFound = 0, nAttempt = 0; DWORD marker = DWORD_MAX; std::vector<BYTE> data(16384); DWORD dwSizeRead = 0; while (SUCCEEDED(Read(data.data(), (DWORD)data.size(), TRUE, &dwSizeRead)) && dwSizeRead && nAttempt < (4 + nMarkerFound)) { nAttempt++; for (DWORD i = 0; i < dwSizeRead; i++) { marker = (marker << 8) | data[i]; if ((marker == DCA_MARKER_14B_LE && (i < dwSizeRead - 2) && (data[i + 1] & 0xF0) == 0xF0 && data[i + 2] == 0x07) || (marker == DCA_MARKER_14B_BE && (i < dwSizeRead - 2) && data[i + 1] == 0x07 && (data[i + 2] & 0xF0) == 0xF0) || marker == DCA_MARKER_RAW_LE || marker == DCA_MARKER_RAW_BE) { nMarkerFound++; } } dwSizeRead = 0; if (nMarkerFound >= 4) { m_bDTS = true; break; } } SetPointer(0); CDROM_READ_TOC_EX TOCEx; ZeroMemory(&TOCEx, sizeof(TOCEx)); TOCEx.Format = CDROM_READ_TOC_EX_FORMAT_CDTEXT; BYTE header[4] = { 0 }; static_assert(sizeof(header) >= MINIMUM_CDROM_READ_TOC_EX_SIZE, "sizeof(header) must be greater or equal to MINIMUM_CDROM_READ_TOC_EX_SIZE"); if (!DeviceIoControl(m_hDrive, IOCTL_CDROM_READ_TOC_EX, &TOCEx, sizeof(TOCEx), header, sizeof(header), &BytesReturned, 0)) { return true; } DWORD size = 2 + (WORD(header[0]) << 8) + header[1]; if (size <= 4) { // No cd-text information return true; } CAutoVectorPtr<BYTE> pCDTextData; if (!pCDTextData.Allocate(size)) { return true; } ZeroMemory(pCDTextData, size); if (!DeviceIoControl(m_hDrive, IOCTL_CDROM_READ_TOC_EX, &TOCEx, sizeof(TOCEx), pCDTextData, size, &BytesReturned, 0)) { return true; } size = (WORD)(BytesReturned - sizeof(CDROM_TOC_CD_TEXT_DATA)); CDROM_TOC_CD_TEXT_DATA_BLOCK* pDesc = ((CDROM_TOC_CD_TEXT_DATA*)(BYTE*)pCDTextData)->Descriptors; CStringArray str[16]; for (int i = 0; i < _countof(str); i++) { str[i].SetSize(1 + m_TOC.LastTrack); } CString last; for (int i = 0; size >= sizeof(CDROM_TOC_CD_TEXT_DATA_BLOCK); i++, size -= sizeof(CDROM_TOC_CD_TEXT_DATA_BLOCK), pDesc++) { if (pDesc->TrackNumber > m_TOC.LastTrack) { continue; } const int lenU = _countof(pDesc->Text); const int lenW = _countof(pDesc->WText); CString text = !pDesc->Unicode ? CString(CStringA((CHAR*)pDesc->Text, lenU)) : CString(CStringW((WCHAR*)pDesc->WText, lenW)); int tlen = text.GetLength(); CString tmp = (tlen < 12 - 1) ? (!pDesc->Unicode ? CString(CStringA((CHAR*)pDesc->Text + tlen + 1, lenU - (tlen + 1))) : CString(CStringW((WCHAR*)pDesc->WText + tlen + 1, lenW - (tlen + 1)))) : _T(""); if (pDesc->PackType < 0x80 || pDesc->PackType >= 0x80 + 0x10) { continue; } pDesc->PackType -= 0x80; if (pDesc->CharacterPosition == 0) { str[pDesc->PackType][pDesc->TrackNumber] = text; } else { // pDesc->CharacterPosition <= 0xf since CharacterPosition is a 4-bit field if (pDesc->CharacterPosition < 0xf && !last.IsEmpty()) { str[pDesc->PackType][pDesc->TrackNumber] = last + text; } else { str[pDesc->PackType][pDesc->TrackNumber] += text; } } last = tmp; } m_discTitle = str[0][0]; m_trackTitle = str[0][iTrackIndex]; m_discArtist = str[1][0]; m_trackArtist = str[1][iTrackIndex]; return true; }
bool CCDDAStream::Load(const WCHAR* fnw) { CString path(fnw); int iDriveLetter = path.Find(_T(":\\")) - 1; int iTrackIndex = CString(path).MakeLower().Find(_T(".cda")) - 1; if (iDriveLetter < 0 || iTrackIndex <= iDriveLetter) { return false; } CString drive = CString(_T("\\\\.\\")) + path[iDriveLetter] + _T(":"); while (iTrackIndex > 0 && _istdigit(path[iTrackIndex - 1])) { iTrackIndex--; } if (1 != _stscanf_s(path.Mid(iTrackIndex), _T("%d"), &iTrackIndex)) { return false; } if (m_hDrive != INVALID_HANDLE_VALUE) { CloseHandle(m_hDrive); m_hDrive = INVALID_HANDLE_VALUE; } m_hDrive = CreateFile(drive, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY | FILE_FLAG_SEQUENTIAL_SCAN, (HANDLE)nullptr); if (m_hDrive == INVALID_HANDLE_VALUE) { return false; } DWORD BytesReturned; if (!DeviceIoControl(m_hDrive, IOCTL_CDROM_READ_TOC, nullptr, 0, &m_TOC, sizeof(m_TOC), &BytesReturned, 0) || !(m_TOC.FirstTrack <= iTrackIndex && iTrackIndex <= m_TOC.LastTrack)) { CloseHandle(m_hDrive); m_hDrive = INVALID_HANDLE_VALUE; return false; } // MMC-3 Draft Revision 10g: Table 222 - Q Sub-channel control field m_TOC.TrackData[iTrackIndex - 1].Control &= 5; if (!(m_TOC.TrackData[iTrackIndex - 1].Control == 0 || m_TOC.TrackData[iTrackIndex - 1].Control == 1)) { CloseHandle(m_hDrive); m_hDrive = INVALID_HANDLE_VALUE; return false; } if (m_TOC.TrackData[iTrackIndex - 1].Control & 8) { m_header.frm.pcm.wf.nChannels = 4; } m_nStartSector = MSF2UINT(m_TOC.TrackData[iTrackIndex - 1].Address) - 150; //MSF2UINT(m_TOC.TrackData[0].Address); m_nStopSector = MSF2UINT(m_TOC.TrackData[iTrackIndex].Address) - 150;//MSF2UINT(m_TOC.TrackData[0].Address); m_llLength = LONGLONG(m_nStopSector - m_nStartSector) * RAW_SECTOR_SIZE; m_header.riff.hdr.chunkSize = (long)(m_llLength + sizeof(m_header) - 8); m_header.data.hdr.chunkSize = (long)(m_llLength); do { CDROM_READ_TOC_EX TOCEx; ZeroMemory(&TOCEx, sizeof(TOCEx)); TOCEx.Format = CDROM_READ_TOC_EX_FORMAT_CDTEXT; TOCEx.SessionTrack = iTrackIndex; WORD size = 0; ASSERT(MINIMUM_CDROM_READ_TOC_EX_SIZE == sizeof(size)); if (!DeviceIoControl(m_hDrive, IOCTL_CDROM_READ_TOC_EX, &TOCEx, sizeof(TOCEx), &size, sizeof(size), &BytesReturned, 0)) { break; } size = _byteswap_ushort(size) + sizeof(size); CAutoVectorPtr<BYTE> pCDTextData; if (!pCDTextData.Allocate(size)) { break; } ZeroMemory(pCDTextData, size); if (!DeviceIoControl(m_hDrive, IOCTL_CDROM_READ_TOC_EX, &TOCEx, sizeof(TOCEx), pCDTextData, size, &BytesReturned, 0)) { break; } size = (WORD)(BytesReturned - sizeof(CDROM_TOC_CD_TEXT_DATA)); CDROM_TOC_CD_TEXT_DATA_BLOCK* pDesc = ((CDROM_TOC_CD_TEXT_DATA*)(BYTE*)pCDTextData)->Descriptors; CStringArray str[16]; for (int i = 0; i < _countof(str); i++) { str[i].SetSize(1 + m_TOC.LastTrack); } CString last; for (int i = 0; size >= sizeof(CDROM_TOC_CD_TEXT_DATA_BLOCK); i++, size -= sizeof(CDROM_TOC_CD_TEXT_DATA_BLOCK), pDesc++) { if (pDesc->TrackNumber > m_TOC.LastTrack) { continue; } const int lenU = _countof(pDesc->Text); const int lenW = _countof(pDesc->WText); CString text = !pDesc->Unicode ? CString(CStringA((CHAR*)pDesc->Text, lenU)) : CString(CStringW((WCHAR*)pDesc->WText, lenW)); int tlen = text.GetLength(); CString tmp = (tlen < 12 - 1) ? (!pDesc->Unicode ? CString(CStringA((CHAR*)pDesc->Text + tlen + 1, lenU - (tlen + 1))) : CString(CStringW((WCHAR*)pDesc->WText + tlen + 1, lenW - (tlen + 1)))) : _T(""); if (pDesc->PackType < 0x80 || pDesc->PackType >= 0x80 + 0x10) { continue; } pDesc->PackType -= 0x80; if (pDesc->CharacterPosition == 0) { str[pDesc->PackType][pDesc->TrackNumber] = text; } else { // pDesc->CharacterPosition <= 0xf since CharacterPosition is a 4-bit field if (pDesc->CharacterPosition < 0xf && !last.IsEmpty()) { str[pDesc->PackType][pDesc->TrackNumber] = last + text; } else { str[pDesc->PackType][pDesc->TrackNumber] += text; } } last = tmp; } m_discTitle = str[0][0]; m_trackTitle = str[0][iTrackIndex]; m_discArtist = str[1][0]; m_trackArtist = str[1][iTrackIndex]; } while (0); return true; }