⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cloneburnerdlg.cpp

📁 利用hpCDE sdk在应用程序中实现把数据写入CD_RW
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	dlg.DestroyWindow();
	EnableWindow();
	BringWindowToTop();
	SetActiveWindow();

	m_comboDevices.SelectString(-1, m_arDeviceNames[m_nDevice]);
	SetDeviceControls(m_nDevice);
}

void CCloneBurnerDlg::OnCbnSelchangeComboDevices()
{
	int nCurSel = m_comboDevices.GetCurSel();

	if (-1 !=  nCurSel)
		SetDeviceControls(nCurSel);
}


void CCloneBurnerDlg::OnBnClickedButtonBrowse()
{
	TCHAR* szPath=new TCHAR[MAX_PATH];

	szPath[0] = _T('\0');

	BROWSEINFO bi;
	bi.hwndOwner = m_hWnd;
	bi.pidlRoot = NULL;
	bi.lpszTitle = _T("Select a source folder");
	bi.ulFlags = BIF_EDITBOX;
	bi.lpfn = NULL;
	bi.lParam = NULL;
	bi.pszDisplayName = szPath;

	LPITEMIDLIST pidl = ::SHBrowseForFolder(&bi);
	if (NULL == pidl)
	{
		delete [] szPath;
		return;
	}

	::SHGetPathFromIDList(pidl, szPath);

	m_strRootDir = szPath;
	m_editRootDir.SetWindowText(m_strRootDir);

	delete [] szPath;
}

// Erasing/writing thread...
DWORD CCloneBurnerDlg::ThreadProc(LPVOID pParam) 
{
	CoInitialize(NULL);
	CCloneBurnerDlg* pThis=(CCloneBurnerDlg* )pParam;
	return pThis->Process();

}

int CCloneBurnerDlg::GetInternalCacheStatus()
{
	int nUsedCachePercent = 0;
	if (m_pDevice)
	{
		double dd = (double) m_pDevice->GetInternalCacheUsedSpace();
		dd = dd * 100.0 / (double)m_pDevice->GetInternalCacheCapacity();

		nUsedCachePercent = (int)dd;
	
		// ATLTRACE("CACHE USAGE: %d\n", nUsedCachePercent);
	}

	return nUsedCachePercent;
}

void CCloneBurnerDlg::NotifyProgress(const TCHAR * pszText)
{
	EnterCriticalSection(&m_cs);
	
		m_notify.strText = pszText;
		m_notify.nUsedCachePercent = GetInternalCacheStatus();

	LeaveCriticalSection(&m_cs);
	SetEvent(m_hNotifyEvent);

}

void CCloneBurnerDlg::NotifyProgress(int nProgress)
{
	EnterCriticalSection(&m_cs);
	
		m_notify.nPercent = nProgress;
		m_notify.nUsedCachePercent = GetInternalCacheStatus();

	LeaveCriticalSection(&m_cs);
	SetEvent(m_hNotifyEvent);
}

DWORD CCloneBurnerDlg::Process() 
{
	SetEvent(m_hOperationStartedEvent);

	IDevice12 * pDevice=(IDevice12 *)m_pEnumerator->GetItem(m_arIndices[m_nDevice]);
	m_pDevice = pDevice;

	if (!m_pDevice)
		return -1;

	if (m_ctx.bErasing) 
	{
		pDevice->SetCurrentSpeeds(32, m_ctx.nSpeed);
		pDevice->Erase(m_ctx.bQuick);
		pDevice->Release();
		m_pDevice  = NULL;

		return 0;
	}

	m_pDevice->SetCurrentSpeeds(32, m_ctx.nSpeed);


	CString strIniFile = m_strRootDir + "/" + "IMAGE.CCD";
	CString strDataFile = m_strRootDir + "/" + "IMAGE.IMG";
	CString strSubFile = m_strRootDir + "/" + "IMAGE.SUB";

	// Load session description from the CCD file
	NotifyProgress("Preparing tracks...");
	ISession * ps = LoadSessionLayout(strIniFile, strDataFile);
	if (!ps)
	{
		pDevice->Release();
		m_pDevice  = NULL;

		AfxMessageBox("Could not load session layout.");
		return 0;
	}

	if (0 == ps->GetTracksCount() )
	{
		CString sMessage;
		sMessage.Format("Could not load session layout from %s.", strIniFile);
		AfxMessageBox(sMessage);

		pDevice->Release();
		m_pDevice = NULL;

		return 0;
	}

	// Burn the session to the CD
	Burn(ps, strDataFile, strSubFile);

	pDevice->Release();
	m_pDevice  = NULL;
	return 0;
}

DWORD CCloneBurnerDlg::GetSessionLength(ISession * ps)
{
	DWORD dwRet = 0;
	dwRet = ps->GetLength();

	ISession * pNext = NULL;
	if (ps->GetNextSession(&pNext))
	{
		dwRet += GetSessionLength(pNext);
		pNext->Release();
	}	

	return dwRet;
}

int CCloneBurnerDlg::GetDataOffset(ETrackType tt)
{
	switch (tt) 
	{
		case TT_AUDIO:
			return 0;
		case TT_MODE0:
			return 16;
		case TT_MODE1:
			return 16;
		case TT_MODE2_FORMLESS:
			return 16;
		case TT_MODE2_FORM1:
		case TT_MODE2_MIXED: 
			return 24;
		break;
		case TT_MODE2_FORM2:
			return 24;
		break;
    }

	return TRUE;
};

void CCloneBurnerDlg::WriteData(ISession * ps, HANDLE hData, HANDLE hSub, EWriteMethod wm)
{
	// Get total length of all sessions
	DWORD dwTotalBlocks = GetSessionLength(ps);
	
	// Get data file size and verify it is ok
	DWORD dwSize = GetFileSize(hData, NULL);
	assert(0 == (dwSize % CDDA_BLOCKSIZE));
	assert(dwTotalBlocks == dwSize / CDDA_BLOCKSIZE);

	// get subchannel file size and verify it is ok
	DWORD dwSubSize = GetFileSize(hSub, NULL);
	assert(0 == (dwSubSize % PW_CHANNEL_SIZE));

	// if sub-channle file is empty, switch to RAW 2352
	// let hpCDE generate the sub-channles
	if (0 == dwSubSize && WRITE_METHOD_FULL_RAW_DAO == wm)
		wm = WRITE_METHOD_RAW_DAO_2352;	

	NotifyProgress("Writing lead-in ...");

	// start session
	if (m_pDevice->StartCDSession(m_ctx.bSimulate, ps, wm))
	{
		NotifyProgress("Writing session ...");

		DWORD  dwStartBlock = 0;
		while (dwStartBlock < dwTotalBlocks)
		{
			if (m_ctx.bStopRequest) 
				break;

			DWORD dwBlocksAtOnce = min(BLOCKS_AT_ONCE, dwTotalBlocks - dwStartBlock);
			LONG lPrevBlockSize = 0;
			
			BYTE * pBuf1 = NULL, * pBuf2 = NULL; 
			DWORD dw1 = 0, dw2 = 0;
			if (m_pDevice->WriteLockBuffer(dwBlocksAtOnce, &pBuf1, &dw1, &pBuf2, &dw2)) 
			{
				if (dw1) 
				{
					for (DWORD dw = 0; dw < dw1; dw++)
					{	
						DWORD dwRead;
						if (WRITE_METHOD_FULL_RAW_DAO == wm)
						{
							ReadFile(hData, pBuf1, CDDA_BLOCKSIZE, &dwRead, NULL);
							ReadFile(hSub, pBuf1 + CDDA_BLOCKSIZE, PW_CHANNEL_SIZE, &dwRead, NULL);

							pBuf1 += CD_RAW_BLOCKSIZE;
						}
						else if (WRITE_METHOD_RAW_DAO_2352 == wm)
						{
							ReadFile(hData, pBuf1, CDDA_BLOCKSIZE, &dwRead, NULL);
							pBuf1 += CDDA_BLOCKSIZE;
						}
						else if (WRITE_METHOD_RAW_DAO == wm)
						{
							// This is a hack to get the user data in the raw block and is used to 
							// simulate non RAW blocks to demonstrate RAW burning from non RAW blocks
							BYTE pRawBuffer[CDDA_BLOCKSIZE];
							ReadFile(hData, pRawBuffer, CDDA_BLOCKSIZE, &dwRead, NULL);
							
							// Get user data block size
							ETrackType tt = m_pDevice->GetTrackType(pRawBuffer);
							LONG lBlockSize = m_pDevice->GetTrackBlockSize(tt);
							if (dw == 0)
								lPrevBlockSize = lBlockSize;

							if (lPrevBlockSize != lBlockSize)
							{
								// WriteLockBuffer\WriteUnlockBuffer do not support writing blocks of different size at once
								dw1 = dw; dw2 = 0;
								// move back one block in the file
								SetFilePointer(hData, -CDDA_BLOCKSIZE, NULL, FILE_CURRENT);
							}
							else
							{
								// same block size
								memcpy(pBuf1, pRawBuffer + GetDataOffset(tt), lBlockSize); 
								pBuf1 += lBlockSize;
							}
						}
					}
				}

				if (dw2) 
				{
					for (DWORD dw = 0; dw < dw2; dw++)
					{	
						DWORD dwRead;
						if (WRITE_METHOD_FULL_RAW_DAO == wm)
						{
							ReadFile(hData, pBuf2, CDDA_BLOCKSIZE, &dwRead, NULL);
							ReadFile(hSub, pBuf2 + CDDA_BLOCKSIZE, PW_CHANNEL_SIZE, &dwRead, NULL);

							pBuf2 += CD_RAW_BLOCKSIZE;
						}
						else if (WRITE_METHOD_RAW_DAO_2352 == wm)
						{
							ReadFile(hData, pBuf2, CDDA_BLOCKSIZE, &dwRead, NULL);
							pBuf2 += CDDA_BLOCKSIZE;
						}
						else if (WRITE_METHOD_RAW_DAO == wm)
						{
							// This is a hack to get the user data in the raw block and is used to 
							// simulate non RAW blocks to demonstrate RAW burning from non RAW blocks
							BYTE pRawBuffer[CDDA_BLOCKSIZE];
							ReadFile(hData, pRawBuffer, CDDA_BLOCKSIZE, &dwRead, NULL);
							
							// Get user data block size
							ETrackType tt = m_pDevice->GetTrackType(pRawBuffer);
							LONG lBlockSize = m_pDevice->GetTrackBlockSize(tt);
							if (dw1 == 0 && dw == 0)
								lPrevBlockSize = lBlockSize;

							if (lPrevBlockSize != lBlockSize)
							{
								// WriteLockBuffer\WriteUnlockBuffer do not support writing blocks of different size at once
								dw2 = dw;
								// move back one block in the file
								SetFilePointer(hData, -CDDA_BLOCKSIZE, NULL, FILE_CURRENT);
							}
							else
							{
								// same block size
								memcpy(pBuf2, pRawBuffer + GetDataOffset(tt), lBlockSize); 
								pBuf2 += lBlockSize;
							}
						}
					}
				}

				m_pDevice->WriteUnlockBuffer(dw1 + dw2);
				dwStartBlock += dw1 + dw2;

				NotifyProgress((int) ((double) dwStartBlock * 100. / dwTotalBlocks)); 
			}
		}

		NotifyProgress("Writing lead-out...");
		m_pDevice->EndCDSession();
	}
	else
	{
		CString sMessage;
		sMessage.Format("Unable to initialize device. Error: 0x%X - %s", m_pDevice->GetLastError(), m_pDevice->GetLastErrorDescription());
		AfxMessageBox(sMessage);
	}
}

BOOL CCloneBurnerDlg::Burn(ISession * ps, LPCTSTR lpDataFilename, LPCTSTR lpSubFilename)
{
	HANDLE hData = CreateFile (lpDataFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
	if (INVALID_HANDLE_VALUE == hData)
		return FALSE;

	HANDLE hSub = CreateFile (lpSubFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
	if (INVALID_HANDLE_VALUE == hSub)
	{
		CloseHandle(hData);
		return FALSE;
	}

	switch(m_ctx.nRawMode)
	{
		case 0:
			WriteData(ps, hData, hSub, WRITE_METHOD_RAW_DAO);
		break;
		case 1:
			WriteData(ps, hData, hSub, WRITE_METHOD_RAW_DAO_2352);
		break;
		case 2:
			WriteData(ps, hData, hSub, WRITE_METHOD_FULL_RAW_DAO);
		break;
	}

	CloseHandle(hSub);
	CloseHandle(hData);

	if (m_ctx.bEject)
		m_pDevice->Eject(TRUE);

	return TRUE;
}

ISession * CCloneBurnerDlg::LoadSessionLayout(LPCTSTR lpIniFilename, LPCTSTR lpDataFilename)
{
	CIniFile ini;
	ini.Initialize(lpIniFilename);

	int nSessions = ini.ReadInt(_T("Sessions"), _T("Disc"));
	int nTocEntries = ini.ReadInt(_T("TocEntries"), _T("Disc"));

	if (0 == nTocEntries || 0 == nSessions)
		return FALSE;

	// Get all the entries from the ini file
	CTOCEntry * pEntries = new CTOCEntry[nTocEntries];
	for (int i = 0; i < nTocEntries; i++)
	{	
		pEntries[i].SetEntryIndex(i);	
		pEntries[i].Serialize(&ini, FALSE);
	}			

	ISession * pFirstSession = NULL;
	ISession * ps = NULL;

	// Get the first session only, for now
	for (int nSessionNumber = 1; nSessionNumber <= nSessions; nSessionNumber++)
	{
		ISession * psNew = hpCDE::CreateSession();

		// link sessions
		if (nSessionNumber > 1)
			ps->SetNextSession(psNew);
		
		ps = psNew;
	
		// session must be a RAW session
		ps->SetType(ST_RAW);

		long lLeadoutLba = 0; 
		long lSessionStartLba = 0;
		BOOL bFirstTrack = TRUE;

		for (int nTrack = 0; nTrack < nTocEntries; nTrack++)
		{
			CTOCEntry & rt = pEntries[nTrack];
			if (nSessionNumber == rt.SessionNumber)
			{
				// skip 1 to 0x63 which is 1 to 99 tracks
				if (rt.POINT > 0x63)	
				{
					ps->SetRawPoint((ERawPoint)rt.POINT, &rt);

					// 0xA2 is the lead out
					if (rt.POINT == 0xA2)
						lLeadoutLba = rt.m_lPLBA;
				}
				else
				{
					ITrackEntry * pTrack = NULL;
					ps->GetTrack(rt.POINT - 1, &pTrack);
					if (!pTrack)
					{
						// Create a track entry and add it to the session object
						pTrack = hpCDE::CreateTrackEntry();
						ps->AppendTrack(pTrack);
					}

					// is this the first track
					if (bFirstTrack)
					{
						lSessionStartLba = rt.m_lPLBA;
						bFirstTrack = FALSE;
					}

					// Determine the type of the track from the block data
					BYTE pBlockData[CD_RAW_BLOCKSIZE];

					HANDLE hData = CreateFile (lpDataFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
					if (INVALID_HANDLE_VALUE == hData)
						return FALSE;

					// lead out is 6750, lead in is 4500 and first pregap is 150 blocks
					// those are not ripped 
					LONG lTrackStart = rt.m_lPLBA - (6750 + 4500 + 150) * (nSessionNumber - 1);
					SetFilePointer(hData, lTrackStart * CDDA_BLOCKSIZE, NULL, FILE_BEGIN);
					
					DWORD dwRead;
					ReadFile(hData, pBlockData, CDDA_BLOCKSIZE, &dwRead, NULL);

					// Assume the track type is audio if the block type is TT_MODE0
					ETrackType tt = m_pDevice->GetTrackType(pBlockData);
					pTrack->SetType(TT_MODE0 == tt ? TT_AUDIO : tt);
					CloseHandle(hData);

					// track lba should be relative to the session start
					pTrack->SetPregapStart(rt.m_lPLBA - lSessionStartLba);
					pTrack->SetTrackStart(rt.m_lPLBA - lSessionStartLba);

					if (nTrack < nTocEntries - 1 && pEntries[nTrack + 1].POINT < 0x63)
					{
						// track end is the beginning of next track
						pTrack->SetTrackEnd(pEntries[nTrack + 1].m_lPLBA - lSessionStartLba);
						pTrack->SetPostgapEnd(pEntries[nTrack + 1].m_lPLBA - lSessionStartLba);
					}
					else
					{
						// last track ends at lead out start
						pTrack->SetTrackEnd(lLeadoutLba - lSessionStartLba);
						pTrack->SetPostgapEnd(lLeadoutLba - lSessionStartLba);
					}

					pTrack->Release();
				}
			}
		}


		if (1 == nSessionNumber)
			pFirstSession = ps;
	}

	delete [] pEntries;
	return pFirstSession;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -