| 1 | // |
|---|
| 2 | // DlgTorrentSeed.cpp |
|---|
| 3 | // |
|---|
| 4 | // Copyright (c) Shareaza Development Team, 2002-2007. |
|---|
| 5 | // This file is part of SHAREAZA (shareaza.sourceforge.net) |
|---|
| 6 | // |
|---|
| 7 | // Shareaza is free software; you can redistribute it |
|---|
| 8 | // and/or modify it under the terms of the GNU General Public License |
|---|
| 9 | // as published by the Free Software Foundation; either version 2 of |
|---|
| 10 | // the License, or (at your option) any later version. |
|---|
| 11 | // |
|---|
| 12 | // Shareaza is distributed in the hope that it will be useful, |
|---|
| 13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 14 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 15 | // GNU General Public License for more details. |
|---|
| 16 | // |
|---|
| 17 | // You should have received a copy of the GNU General Public License |
|---|
| 18 | // along with Shareaza; if not, write to the Free Software |
|---|
| 19 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|---|
| 20 | // |
|---|
| 21 | |
|---|
| 22 | #include "StdAfx.h" |
|---|
| 23 | #include "Shareaza.h" |
|---|
| 24 | #include "Settings.h" |
|---|
| 25 | #include "Network.h" |
|---|
| 26 | #include "Library.h" |
|---|
| 27 | #include "SharedFile.h" |
|---|
| 28 | #include "Transfers.h" |
|---|
| 29 | #include "Downloads.h" |
|---|
| 30 | #include "Download.h" |
|---|
| 31 | #include "ShareazaURL.h" |
|---|
| 32 | #include "HttpRequest.h" |
|---|
| 33 | #include "DlgTorrentSeed.h" |
|---|
| 34 | #include "WndMain.h" |
|---|
| 35 | #include "WndDownloads.h" |
|---|
| 36 | #include "DlgHelp.h" |
|---|
| 37 | |
|---|
| 38 | #include "LibraryHistory.h" |
|---|
| 39 | |
|---|
| 40 | #ifdef _DEBUG |
|---|
| 41 | #undef THIS_FILE |
|---|
| 42 | static char THIS_FILE[]=__FILE__; |
|---|
| 43 | #define new DEBUG_NEW |
|---|
| 44 | #endif |
|---|
| 45 | |
|---|
| 46 | IMPLEMENT_DYNAMIC(CTorrentSeedDlg, CSkinDialog) |
|---|
| 47 | |
|---|
| 48 | BEGIN_MESSAGE_MAP(CTorrentSeedDlg, CSkinDialog) |
|---|
| 49 | ON_BN_CLICKED(IDC_DOWNLOAD, OnDownload) |
|---|
| 50 | ON_BN_CLICKED(IDC_SEED, OnSeed) |
|---|
| 51 | ON_WM_DESTROY() |
|---|
| 52 | ON_WM_TIMER() |
|---|
| 53 | END_MESSAGE_MAP() |
|---|
| 54 | |
|---|
| 55 | const DWORD BUFFER_SIZE = 2 * 1024 * 1024u; |
|---|
| 56 | |
|---|
| 57 | |
|---|
| 58 | ///////////////////////////////////////////////////////////////////////////// |
|---|
| 59 | // CTorrentSeedDlg construction |
|---|
| 60 | |
|---|
| 61 | CTorrentSeedDlg::CTorrentSeedDlg(LPCTSTR pszTorrent, BOOL bForceSeed, CWnd* pParent) : CSkinDialog( CTorrentSeedDlg::IDD, pParent ) |
|---|
| 62 | { |
|---|
| 63 | m_hThread = NULL; |
|---|
| 64 | m_sTorrent = pszTorrent; |
|---|
| 65 | m_bForceSeed = bForceSeed; |
|---|
| 66 | } |
|---|
| 67 | |
|---|
| 68 | CTorrentSeedDlg::~CTorrentSeedDlg() |
|---|
| 69 | { |
|---|
| 70 | ASSERT( m_hThread == NULL ); |
|---|
| 71 | } |
|---|
| 72 | |
|---|
| 73 | void CTorrentSeedDlg::DoDataExchange(CDataExchange* pDX) |
|---|
| 74 | { |
|---|
| 75 | CDialog::DoDataExchange( pDX ); |
|---|
| 76 | DDX_Control( pDX, IDC_DOWNLOAD, m_wndDownload ); |
|---|
| 77 | DDX_Control( pDX, IDC_SEED, m_wndSeed ); |
|---|
| 78 | DDX_Control( pDX, IDC_PROGRESS, m_wndProgress ); |
|---|
| 79 | } |
|---|
| 80 | |
|---|
| 81 | ///////////////////////////////////////////////////////////////////////////// |
|---|
| 82 | // CTorrentSeedDlg message handlers |
|---|
| 83 | |
|---|
| 84 | BOOL CTorrentSeedDlg::OnInitDialog() |
|---|
| 85 | { |
|---|
| 86 | CSkinDialog::OnInitDialog(); |
|---|
| 87 | |
|---|
| 88 | SkinMe( NULL, IDR_MAINFRAME ); |
|---|
| 89 | |
|---|
| 90 | if ( Settings.General.LanguageRTL ) m_wndProgress.ModifyStyleEx( WS_EX_LAYOUTRTL, 0, 0 ); |
|---|
| 91 | m_wndProgress.SetRange( 0, 1000 ); |
|---|
| 92 | m_wndProgress.SetPos( 0 ); |
|---|
| 93 | |
|---|
| 94 | if ( m_bForceSeed ) |
|---|
| 95 | { |
|---|
| 96 | m_wndDownload.EnableWindow( FALSE ); |
|---|
| 97 | if ( Settings.BitTorrent.AutoSeed ) PostMessage( WM_TIMER, 4 ); |
|---|
| 98 | |
|---|
| 99 | } |
|---|
| 100 | // if ( m_bForceSeed ) m_wndDownload.ShowWindow( SW_HIDE ); |
|---|
| 101 | |
|---|
| 102 | return TRUE; |
|---|
| 103 | } |
|---|
| 104 | |
|---|
| 105 | void CTorrentSeedDlg::OnDownload() |
|---|
| 106 | { |
|---|
| 107 | /*CWnd* pWnd =*/ AfxGetMainWnd(); |
|---|
| 108 | CBTInfo* pTorrent = new CBTInfo(); |
|---|
| 109 | |
|---|
| 110 | if ( pTorrent->LoadTorrentFile( m_sTorrent ) ) |
|---|
| 111 | { |
|---|
| 112 | if ( pTorrent->HasEncodingError() ) // Check the torrent is valid |
|---|
| 113 | { |
|---|
| 114 | CHelpDlg::Show( _T("GeneralHelp.BadTorrentEncoding") ); |
|---|
| 115 | } |
|---|
| 116 | |
|---|
| 117 | CShareazaURL* pURL = new CShareazaURL( pTorrent ); |
|---|
| 118 | //if ( ! pWnd->PostMessage( WM_URL, (WPARAM)pURL ) ) delete pURL; |
|---|
| 119 | CLibraryFile* pFile; |
|---|
| 120 | |
|---|
| 121 | |
|---|
| 122 | CSingleLock oLibraryLock( &Library.m_pSection, TRUE ); |
|---|
| 123 | if ( ( pFile = LibraryMaps.LookupFileBySHA1( pURL->m_oSHA1 ) ) != NULL |
|---|
| 124 | || ( pFile = LibraryMaps.LookupFileByED2K( pURL->m_oED2K ) ) != NULL |
|---|
| 125 | || ( pFile = LibraryMaps.LookupFileByBTH( pURL->m_oBTH ) ) != NULL |
|---|
| 126 | || ( pFile = LibraryMaps.LookupFileByMD5( pURL->m_oMD5 ) ) != NULL ) |
|---|
| 127 | { |
|---|
| 128 | CString strFormat, strMessage; |
|---|
| 129 | LoadString( strFormat, IDS_URL_ALREADY_HAVE ); |
|---|
| 130 | strMessage.Format( strFormat, (LPCTSTR)pFile->m_sName ); |
|---|
| 131 | oLibraryLock.Unlock(); |
|---|
| 132 | |
|---|
| 133 | if ( AfxMessageBox( strMessage, MB_ICONINFORMATION|MB_YESNOCANCEL|MB_DEFBUTTON2 ) == IDNO ) |
|---|
| 134 | { |
|---|
| 135 | delete pURL; |
|---|
| 136 | EndDialog( IDOK ); |
|---|
| 137 | return; |
|---|
| 138 | } |
|---|
| 139 | } |
|---|
| 140 | else |
|---|
| 141 | { |
|---|
| 142 | oLibraryLock.Unlock(); |
|---|
| 143 | } |
|---|
| 144 | |
|---|
| 145 | CDownload* pDownload = Downloads.Add( pURL ); |
|---|
| 146 | |
|---|
| 147 | // Downloads.Add() took a copy of the CBTInfo, so we need to delete the original |
|---|
| 148 | delete pURL; |
|---|
| 149 | |
|---|
| 150 | if ( pDownload == NULL ) |
|---|
| 151 | { |
|---|
| 152 | EndDialog( IDOK ); |
|---|
| 153 | return; |
|---|
| 154 | } |
|---|
| 155 | |
|---|
| 156 | if ( ( GetAsyncKeyState( VK_SHIFT ) & 0x8000 ) == 0 ) |
|---|
| 157 | { |
|---|
| 158 | if ( ! Network.IsWellConnected() ) Network.Connect( TRUE ); |
|---|
| 159 | } |
|---|
| 160 | |
|---|
| 161 | CMainWnd* pMainWnd = (CMainWnd*)AfxGetMainWnd(); |
|---|
| 162 | pMainWnd->m_pWindows.Open( RUNTIME_CLASS(CDownloadsWnd) ); |
|---|
| 163 | |
|---|
| 164 | if ( Settings.Downloads.ShowMonitorURLs ) |
|---|
| 165 | { |
|---|
| 166 | CSingleLock pTransfersLock( &Transfers.m_pSection, TRUE ); |
|---|
| 167 | if ( Downloads.Check( pDownload ) ) pDownload->ShowMonitor( &pTransfersLock ); |
|---|
| 168 | } |
|---|
| 169 | |
|---|
| 170 | EndDialog( IDOK ); |
|---|
| 171 | return; |
|---|
| 172 | } |
|---|
| 173 | else |
|---|
| 174 | delete pTorrent; |
|---|
| 175 | theApp.Message( MSG_DISPLAYED_ERROR, IDS_BT_PREFETCH_ERROR, (LPCTSTR)m_sTorrent ); |
|---|
| 176 | EndDialog( IDOK ); |
|---|
| 177 | } |
|---|
| 178 | |
|---|
| 179 | void CTorrentSeedDlg::OnSeed() |
|---|
| 180 | { |
|---|
| 181 | m_wndDownload.EnableWindow( FALSE ); |
|---|
| 182 | m_wndSeed.EnableWindow( FALSE ); |
|---|
| 183 | m_bCancel = FALSE; |
|---|
| 184 | |
|---|
| 185 | if ( m_pInfo.LoadTorrentFile( m_sTorrent ) ) |
|---|
| 186 | { |
|---|
| 187 | if ( m_pInfo.HasEncodingError() ) // Check the torrent is valid |
|---|
| 188 | { |
|---|
| 189 | CHelpDlg::Show( _T("GeneralHelp.BadTorrentEncoding") ); |
|---|
| 190 | } |
|---|
| 191 | if ( Downloads.FindByBTH( m_pInfo.m_oBTH ) == NULL ) |
|---|
| 192 | { |
|---|
| 193 | // Connect if (we aren't) |
|---|
| 194 | if ( ! Network.IsConnected() ) Network.Connect(); |
|---|
| 195 | |
|---|
| 196 | // Update the last seeded torrent |
|---|
| 197 | CSingleLock pLock( &Library.m_pSection ); |
|---|
| 198 | if ( pLock.Lock( 250 ) ) |
|---|
| 199 | { |
|---|
| 200 | LibraryHistory.LastSeededTorrent.m_sName = m_pInfo.m_sName.Left( 40 ); |
|---|
| 201 | LibraryHistory.LastSeededTorrent.m_sPath = m_sTorrent; |
|---|
| 202 | LibraryHistory.LastSeededTorrent.m_tLastSeeded = static_cast< DWORD >( time( NULL ) ); |
|---|
| 203 | |
|---|
| 204 | // If it's a 'new' torrent, reset the counters |
|---|
| 205 | if ( !validAndEqual( LibraryHistory.LastSeededTorrent.m_oBTH, m_pInfo.m_oBTH ) ) |
|---|
| 206 | { |
|---|
| 207 | LibraryHistory.LastSeededTorrent.m_nUploaded = 0; |
|---|
| 208 | LibraryHistory.LastSeededTorrent.m_nDownloaded = 0; |
|---|
| 209 | LibraryHistory.LastSeededTorrent.m_oBTH = m_pInfo.m_oBTH; |
|---|
| 210 | } |
|---|
| 211 | } |
|---|
| 212 | |
|---|
| 213 | // Start the torrent seed process |
|---|
| 214 | m_hThread = BeginThread( "DlgTorrentSeed", ThreadStart, this ); |
|---|
| 215 | } |
|---|
| 216 | else // We are already seeding the torrent |
|---|
| 217 | { |
|---|
| 218 | CString strFormat, strMessage; |
|---|
| 219 | LoadString(strFormat, IDS_BT_SEED_ALREADY ); |
|---|
| 220 | strMessage.Format( strFormat, (LPCTSTR)m_pInfo.m_sName ); |
|---|
| 221 | AfxMessageBox( strMessage, MB_ICONEXCLAMATION ); |
|---|
| 222 | EndDialog( IDOK ); |
|---|
| 223 | } |
|---|
| 224 | } |
|---|
| 225 | else |
|---|
| 226 | { |
|---|
| 227 | // We couldn't load the .torrent file |
|---|
| 228 | CString strFormat, strMessage; |
|---|
| 229 | LoadString(strFormat, IDS_BT_SEED_PARSE_ERROR ); |
|---|
| 230 | strMessage.Format( strFormat, (LPCTSTR)m_sTorrent ); |
|---|
| 231 | AfxMessageBox( strMessage, MB_ICONEXCLAMATION ); |
|---|
| 232 | EndDialog( IDOK ); |
|---|
| 233 | } |
|---|
| 234 | } |
|---|
| 235 | |
|---|
| 236 | void CTorrentSeedDlg::OnCancel() |
|---|
| 237 | { |
|---|
| 238 | if ( m_wndDownload.IsWindowEnabled() || m_bCancel ) |
|---|
| 239 | { |
|---|
| 240 | CSkinDialog::OnCancel(); |
|---|
| 241 | } |
|---|
| 242 | else |
|---|
| 243 | { |
|---|
| 244 | m_bCancel = TRUE; |
|---|
| 245 | } |
|---|
| 246 | } |
|---|
| 247 | |
|---|
| 248 | void CTorrentSeedDlg::OnDestroy() |
|---|
| 249 | { |
|---|
| 250 | if ( m_hThread != NULL ) |
|---|
| 251 | { |
|---|
| 252 | m_bCancel = TRUE; |
|---|
| 253 | CloseThread( &m_hThread ); |
|---|
| 254 | } |
|---|
| 255 | |
|---|
| 256 | CSkinDialog::OnDestroy(); |
|---|
| 257 | } |
|---|
| 258 | |
|---|
| 259 | void CTorrentSeedDlg::OnTimer(UINT_PTR nIDEvent) |
|---|
| 260 | { |
|---|
| 261 | CSkinDialog::OnTimer( nIDEvent ); |
|---|
| 262 | |
|---|
| 263 | if ( nIDEvent == 1 ) |
|---|
| 264 | { |
|---|
| 265 | EndDialog( IDOK ); |
|---|
| 266 | } |
|---|
| 267 | else if ( nIDEvent == 2 ) |
|---|
| 268 | { |
|---|
| 269 | if ( m_bCancel == FALSE ) AfxMessageBox( m_sMessage, MB_ICONEXCLAMATION ); |
|---|
| 270 | EndDialog( IDCANCEL ); |
|---|
| 271 | } |
|---|
| 272 | else if ( nIDEvent == 3 ) |
|---|
| 273 | { |
|---|
| 274 | if ( m_nScaled != m_nOldScaled ) |
|---|
| 275 | { |
|---|
| 276 | m_nOldScaled = m_nScaled; |
|---|
| 277 | m_wndProgress.SetPos( m_nScaled ); |
|---|
| 278 | } |
|---|
| 279 | } |
|---|
| 280 | else if ( nIDEvent == 4 ) |
|---|
| 281 | { |
|---|
| 282 | OnSeed(); |
|---|
| 283 | } |
|---|
| 284 | } |
|---|
| 285 | |
|---|
| 286 | ///////////////////////////////////////////////////////////////////////////// |
|---|
| 287 | // CTorrentSeedDlg thread run |
|---|
| 288 | |
|---|
| 289 | UINT CTorrentSeedDlg::ThreadStart(LPVOID pParam) |
|---|
| 290 | { |
|---|
| 291 | ((CTorrentSeedDlg*)pParam)->OnRun(); |
|---|
| 292 | return 0; |
|---|
| 293 | } |
|---|
| 294 | |
|---|
| 295 | void CTorrentSeedDlg::OnRun() |
|---|
| 296 | { |
|---|
| 297 | if ( m_pInfo.m_nFiles == 1 ) |
|---|
| 298 | { |
|---|
| 299 | RunSingleFile(); |
|---|
| 300 | } |
|---|
| 301 | else |
|---|
| 302 | { |
|---|
| 303 | RunMultiFile(); |
|---|
| 304 | } |
|---|
| 305 | } |
|---|
| 306 | |
|---|
| 307 | void CTorrentSeedDlg::RunSingleFile() |
|---|
| 308 | { |
|---|
| 309 | m_sTarget = FindFile( &m_pInfo.m_pFiles[0] ); |
|---|
| 310 | |
|---|
| 311 | if ( m_sTarget.IsEmpty() || GetFileAttributes( m_sTarget ) == INVALID_FILE_ATTRIBUTES ) |
|---|
| 312 | { |
|---|
| 313 | CString strFormat; |
|---|
| 314 | LoadString(strFormat, IDS_BT_SEED_SOURCE_LOST ); |
|---|
| 315 | m_sMessage.Format( strFormat, (LPCTSTR)m_pInfo.m_pFiles[0].m_sPath ); |
|---|
| 316 | PostMessage( WM_TIMER, 2 ); |
|---|
| 317 | return; |
|---|
| 318 | } |
|---|
| 319 | |
|---|
| 320 | if ( CreateDownload() ) |
|---|
| 321 | { |
|---|
| 322 | PostMessage( WM_TIMER, 1 ); |
|---|
| 323 | } |
|---|
| 324 | else |
|---|
| 325 | { |
|---|
| 326 | PostMessage( WM_TIMER, 2 ); |
|---|
| 327 | } |
|---|
| 328 | } |
|---|
| 329 | |
|---|
| 330 | void CTorrentSeedDlg::RunMultiFile() |
|---|
| 331 | { |
|---|
| 332 | HANDLE hTarget = CreateTarget(); |
|---|
| 333 | |
|---|
| 334 | if ( hTarget != INVALID_HANDLE_VALUE ) |
|---|
| 335 | { |
|---|
| 336 | BOOL bBuild = BuildFiles( hTarget ); |
|---|
| 337 | CloseHandle( hTarget ); |
|---|
| 338 | |
|---|
| 339 | if ( bBuild && CreateDownload() ) |
|---|
| 340 | { |
|---|
| 341 | PostMessage( WM_TIMER, 1 ); |
|---|
| 342 | } |
|---|
| 343 | else |
|---|
| 344 | { |
|---|
| 345 | DeleteFile( m_sTarget ); |
|---|
| 346 | PostMessage( WM_TIMER, 2 ); |
|---|
| 347 | } |
|---|
| 348 | } |
|---|
| 349 | else |
|---|
| 350 | { |
|---|
| 351 | PostMessage( WM_TIMER, 2 ); |
|---|
| 352 | } |
|---|
| 353 | } |
|---|
| 354 | |
|---|
| 355 | CString CTorrentSeedDlg::FindFile(LPVOID pVoid) |
|---|
| 356 | { |
|---|
| 357 | CBTInfo::CBTFile* pFile = reinterpret_cast<CBTInfo::CBTFile*>(pVoid); |
|---|
| 358 | CString strFile; |
|---|
| 359 | |
|---|
| 360 | CString strPath = m_sTorrent; |
|---|
| 361 | int nSlash = strPath.ReverseFind( '\\' ); |
|---|
| 362 | if ( nSlash >= 0 ) strPath = strPath.Left( nSlash + 1 ); |
|---|
| 363 | |
|---|
| 364 | if ( pFile->m_oSHA1 ) |
|---|
| 365 | { |
|---|
| 366 | CSingleLock oLibraryLock( &Library.m_pSection, TRUE ); |
|---|
| 367 | if ( CLibraryFile* pShared = LibraryMaps.LookupFileBySHA1( pFile->m_oSHA1, FALSE, TRUE ) ) |
|---|
| 368 | { |
|---|
| 369 | strFile = pShared->GetPath(); |
|---|
| 370 | oLibraryLock.Unlock(); |
|---|
| 371 | if ( GetFileAttributes( strFile ) != INVALID_FILE_ATTRIBUTES ) return strFile; |
|---|
| 372 | } |
|---|
| 373 | } |
|---|
| 374 | |
|---|
| 375 | strFile = Settings.Downloads.CompletePath + "\\" + pFile->m_sPath; |
|---|
| 376 | if ( GetFileAttributes( strFile ) != INVALID_FILE_ATTRIBUTES ) return strFile; |
|---|
| 377 | |
|---|
| 378 | strFile = strPath + pFile->m_sPath; |
|---|
| 379 | if ( GetFileAttributes( strFile ) != INVALID_FILE_ATTRIBUTES ) return strFile; |
|---|
| 380 | |
|---|
| 381 | //Try removing the outer directory in case of multi-file torrent oddities |
|---|
| 382 | LPCTSTR pszName = _tcsrchr( pFile->m_sPath, '\\' ); |
|---|
| 383 | if ( pszName == NULL ) pszName = pFile->m_sPath; else pszName ++; |
|---|
| 384 | |
|---|
| 385 | strFile = Settings.Downloads.CompletePath + "\\" + pszName; |
|---|
| 386 | if ( GetFileAttributes( strFile ) != INVALID_FILE_ATTRIBUTES ) return strFile; |
|---|
| 387 | |
|---|
| 388 | strFile = strPath + pszName; |
|---|
| 389 | if ( GetFileAttributes( strFile ) != INVALID_FILE_ATTRIBUTES ) return strFile; |
|---|
| 390 | |
|---|
| 391 | strFile.Empty(); |
|---|
| 392 | return strFile; |
|---|
| 393 | } |
|---|
| 394 | |
|---|
| 395 | HANDLE CTorrentSeedDlg::CreateTarget() |
|---|
| 396 | { |
|---|
| 397 | m_sTarget = Settings.Downloads.IncompletePath + '\\'; |
|---|
| 398 | m_sTarget += m_pInfo.m_oBTH.toString< Hashes::base16Encoding >(); |
|---|
| 399 | |
|---|
| 400 | HANDLE hTarget = CreateFile( m_sTarget, GENERIC_WRITE, 0, NULL, CREATE_NEW, |
|---|
| 401 | FILE_ATTRIBUTE_NORMAL, NULL ); |
|---|
| 402 | VERIFY_FILE_ACCESS( hTarget, m_sTarget ) |
|---|
| 403 | if ( hTarget == INVALID_HANDLE_VALUE ) |
|---|
| 404 | { |
|---|
| 405 | CString strFormat; |
|---|
| 406 | LoadString(strFormat, IDS_BT_SEED_CREATE_FAIL ); |
|---|
| 407 | m_sMessage.Format( strFormat, (LPCTSTR)m_sTarget ); |
|---|
| 408 | } |
|---|
| 409 | |
|---|
| 410 | return hTarget; |
|---|
| 411 | } |
|---|
| 412 | |
|---|
| 413 | BOOL CTorrentSeedDlg::BuildFiles(HANDLE hTarget) |
|---|
| 414 | { |
|---|
| 415 | m_nVolume = m_nTotal = 0; |
|---|
| 416 | m_nScaled = m_nOldScaled = 0; |
|---|
| 417 | |
|---|
| 418 | for ( int nFile = 0 ; nFile < m_pInfo.m_nFiles ; nFile++ ) |
|---|
| 419 | { |
|---|
| 420 | CBTInfo::CBTFile* pFile = &m_pInfo.m_pFiles[ nFile ]; |
|---|
| 421 | m_nTotal += pFile->m_nSize; |
|---|
| 422 | } |
|---|
| 423 | |
|---|
| 424 | m_pInfo.BeginBlockTest(); |
|---|
| 425 | m_nBlockNumber = 0; |
|---|
| 426 | m_nBlockLength = m_pInfo.m_nBlockSize; |
|---|
| 427 | |
|---|
| 428 | for ( int nFile = 0 ; nFile < m_pInfo.m_nFiles ; nFile++ ) |
|---|
| 429 | { |
|---|
| 430 | CBTInfo::CBTFile* pFile = &m_pInfo.m_pFiles[ nFile ]; |
|---|
| 431 | CString strSource = FindFile( pFile ); |
|---|
| 432 | HANDLE hSource = INVALID_HANDLE_VALUE; |
|---|
| 433 | |
|---|
| 434 | if ( strSource.GetLength() > 0 ) |
|---|
| 435 | { |
|---|
| 436 | hSource = CreateFile( strSource, GENERIC_READ, |
|---|
| 437 | FILE_SHARE_READ | ( theApp.m_bNT ? FILE_SHARE_DELETE : 0 ), |
|---|
| 438 | NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); |
|---|
| 439 | VERIFY_FILE_ACCESS( hSource, strSource ) |
|---|
| 440 | } |
|---|
| 441 | |
|---|
| 442 | if ( hSource == INVALID_HANDLE_VALUE ) |
|---|
| 443 | { |
|---|
| 444 | CString strFormat; |
|---|
| 445 | LoadString(strFormat, IDS_BT_SEED_SOURCE_LOST ); |
|---|
| 446 | m_sMessage.Format( strFormat, (LPCTSTR)pFile->m_sPath ); |
|---|
| 447 | return FALSE; |
|---|
| 448 | } |
|---|
| 449 | |
|---|
| 450 | DWORD nSizeHigh = 0; |
|---|
| 451 | DWORD nSizeLow = GetFileSize( hSource, &nSizeHigh ); |
|---|
| 452 | QWORD nSize = (QWORD)nSizeLow + ( (QWORD)nSizeHigh << 32 ); |
|---|
| 453 | |
|---|
| 454 | if ( nSize != pFile->m_nSize ) |
|---|
| 455 | { |
|---|
| 456 | CloseHandle( hSource ); |
|---|
| 457 | m_sMessage.Format( IDS_BT_SEED_SOURCE_SIZE, |
|---|
| 458 | pFile->m_sPath, |
|---|
| 459 | Settings.SmartVolume( pFile->m_nSize ), |
|---|
| 460 | Settings.SmartVolume( nSize ) ); |
|---|
| 461 | return FALSE; |
|---|
| 462 | } |
|---|
| 463 | |
|---|
| 464 | BOOL bSuccess = CopyFile( hTarget, hSource, pFile->m_nSize, pFile->m_sPath ); |
|---|
| 465 | |
|---|
| 466 | CloseHandle( hSource ); |
|---|
| 467 | |
|---|
| 468 | if ( m_bCancel || ! bSuccess ) return FALSE; |
|---|
| 469 | } |
|---|
| 470 | |
|---|
| 471 | return VerifyData( NULL, 0, m_pInfo.m_pFiles[ m_pInfo.m_nFiles - 1 ].m_sPath ); |
|---|
| 472 | } |
|---|
| 473 | |
|---|
| 474 | BOOL CTorrentSeedDlg::CopyFile(HANDLE hTarget, HANDLE hSource, QWORD nLength, LPCTSTR pszPath) |
|---|
| 475 | { |
|---|
| 476 | auto_array< BYTE > pBuffer( new BYTE[ BUFFER_SIZE ] ); |
|---|
| 477 | |
|---|
| 478 | while ( nLength ) |
|---|
| 479 | { |
|---|
| 480 | DWORD nBuffer = min( nLength, BUFFER_SIZE ); |
|---|
| 481 | DWORD nSuccess = 0; |
|---|
| 482 | DWORD tStart = GetTickCount(); |
|---|
| 483 | |
|---|
| 484 | if ( ! ReadFile( hSource, pBuffer.get(), nBuffer, &nBuffer, NULL ) || |
|---|
| 485 | ! VerifyData( pBuffer.get(), nBuffer, pszPath ) || |
|---|
| 486 | ! WriteFile( hTarget, pBuffer.get(), nBuffer, &nSuccess, NULL ) ) |
|---|
| 487 | { |
|---|
| 488 | return FALSE; |
|---|
| 489 | } |
|---|
| 490 | |
|---|
| 491 | if ( nSuccess == nBuffer ) |
|---|
| 492 | { |
|---|
| 493 | nLength -= nBuffer; |
|---|
| 494 | } |
|---|
| 495 | else |
|---|
| 496 | { |
|---|
| 497 | break; |
|---|
| 498 | } |
|---|
| 499 | |
|---|
| 500 | m_nVolume += nBuffer; |
|---|
| 501 | m_nScaled = (int)( (double)m_nVolume / (double)m_nTotal * 1000.0f ); |
|---|
| 502 | if ( m_nScaled != m_nOldScaled ) PostMessage( WM_TIMER, 3 ); |
|---|
| 503 | |
|---|
| 504 | if ( m_bCancel ) break; |
|---|
| 505 | tStart = ( GetTickCount() - tStart ) / 2; |
|---|
| 506 | Sleep( min( tStart, 50ul ) ); |
|---|
| 507 | if ( m_bCancel ) break; |
|---|
| 508 | } |
|---|
| 509 | |
|---|
| 510 | if ( nLength == 0 ) |
|---|
| 511 | { |
|---|
| 512 | return TRUE; |
|---|
| 513 | } |
|---|
| 514 | else |
|---|
| 515 | { |
|---|
| 516 | CString strFormat; |
|---|
| 517 | LoadString(strFormat, IDS_BT_SEED_COPY_FAIL ); |
|---|
| 518 | m_sMessage.Format( strFormat, (LPCTSTR)pszPath ); |
|---|
| 519 | return FALSE; |
|---|
| 520 | } |
|---|
| 521 | } |
|---|
| 522 | |
|---|
| 523 | BOOL CTorrentSeedDlg::VerifyData(BYTE* pBuffer, DWORD nLength, LPCTSTR pszPath) |
|---|
| 524 | { |
|---|
| 525 | if ( pBuffer == NULL ) |
|---|
| 526 | { |
|---|
| 527 | if ( m_nBlockNumber >= m_pInfo.m_nBlockCount ) return TRUE; |
|---|
| 528 | if ( m_pInfo.FinishBlockTest( m_nBlockNumber++ ) ) return TRUE; |
|---|
| 529 | |
|---|
| 530 | CString strFormat; |
|---|
| 531 | LoadString(strFormat, IDS_BT_SEED_VERIFY_FAIL ); |
|---|
| 532 | m_sMessage.Format( strFormat, (LPCTSTR)pszPath ); |
|---|
| 533 | return FALSE; |
|---|
| 534 | } |
|---|
| 535 | |
|---|
| 536 | while ( nLength > 0 ) |
|---|
| 537 | { |
|---|
| 538 | DWORD nBlock = min( nLength, m_nBlockLength ); |
|---|
| 539 | |
|---|
| 540 | m_pInfo.AddToTest( pBuffer, nBlock ); |
|---|
| 541 | |
|---|
| 542 | pBuffer += nBlock; |
|---|
| 543 | nLength -= nBlock; |
|---|
| 544 | m_nBlockLength -= nBlock; |
|---|
| 545 | |
|---|
| 546 | if ( m_nBlockLength == 0 ) |
|---|
| 547 | { |
|---|
| 548 | if ( ! m_pInfo.FinishBlockTest( m_nBlockNumber++ ) ) |
|---|
| 549 | { |
|---|
| 550 | CString strFormat; |
|---|
| 551 | LoadString(strFormat, IDS_BT_SEED_VERIFY_FAIL ); |
|---|
| 552 | m_sMessage.Format( strFormat, (LPCTSTR)pszPath ); |
|---|
| 553 | return FALSE; |
|---|
| 554 | } |
|---|
| 555 | |
|---|
| 556 | if ( m_nBlockNumber < m_pInfo.m_nBlockCount ) |
|---|
| 557 | { |
|---|
| 558 | m_nBlockLength = m_pInfo.m_nBlockSize; |
|---|
| 559 | m_pInfo.BeginBlockTest(); |
|---|
| 560 | } |
|---|
| 561 | } |
|---|
| 562 | } |
|---|
| 563 | |
|---|
| 564 | return TRUE; |
|---|
| 565 | } |
|---|
| 566 | |
|---|
| 567 | BOOL CTorrentSeedDlg::CreateDownload() |
|---|
| 568 | { |
|---|
| 569 | CSingleLock pTransfersLock( &Transfers.m_pSection ); |
|---|
| 570 | if ( ! pTransfersLock.Lock( 2000 ) ) return FALSE; |
|---|
| 571 | |
|---|
| 572 | if ( Downloads.FindByBTH( m_pInfo.m_oBTH ) != NULL ) |
|---|
| 573 | { |
|---|
| 574 | CString strFormat; |
|---|
| 575 | LoadString(strFormat, IDS_BT_SEED_ALREADY ); |
|---|
| 576 | m_sMessage.Format( strFormat, (LPCTSTR)m_pInfo.m_sName ); |
|---|
| 577 | return FALSE; |
|---|
| 578 | } |
|---|
| 579 | |
|---|
| 580 | CBTInfo* pInfo = new CBTInfo(); |
|---|
| 581 | pInfo->Copy( &m_pInfo ); |
|---|
| 582 | CShareazaURL pURL( pInfo ); |
|---|
| 583 | CDownload* pDownload = Downloads.Add( &pURL ); |
|---|
| 584 | |
|---|
| 585 | if ( pDownload != NULL && pDownload->SeedTorrent( m_sTarget ) ) |
|---|
| 586 | { |
|---|
| 587 | if ( pInfo->m_nFiles == 1 ) |
|---|
| 588 | { |
|---|
| 589 | pDownload->MakeComplete(); |
|---|
| 590 | pDownload->ResetVerification(); |
|---|
| 591 | pDownload->SetModified(); |
|---|
| 592 | } |
|---|
| 593 | return TRUE; |
|---|
| 594 | } |
|---|
| 595 | else |
|---|
| 596 | { |
|---|
| 597 | CString strFormat; |
|---|
| 598 | LoadString(strFormat, IDS_BT_SEED_ERROR ); |
|---|
| 599 | m_sMessage.Format( strFormat, (LPCTSTR)m_pInfo.m_sName ); |
|---|
| 600 | return FALSE; |
|---|
| 601 | } |
|---|
| 602 | } |
|---|