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 "Shareaza.h"
00024 #include "Settings.h"
00025 #include "Library.h"
00026 #include "LibraryFolders.h"
00027 #include "SharedFolder.h"
00028 #include "SharedFile.h"
00029 #include "Uploads.h"
00030 #include "DlgFileCopy.h"
00031 #include "CtrlSharedFolder.h"
00032 #include "Skin.h"
00033
00034 #ifdef _DEBUG
00035 #define new DEBUG_NEW
00036 #undef THIS_FILE
00037 static char THIS_FILE[] = __FILE__;
00038 #endif
00039
00040 BEGIN_MESSAGE_MAP(CFileCopyDlg, CSkinDialog)
00041
00042 ON_WM_TIMER()
00043
00044 END_MESSAGE_MAP()
00045
00046
00048
00049
00050 CFileCopyDlg::CFileCopyDlg(CWnd* pParent, BOOL bMove) : CSkinDialog(CFileCopyDlg::IDD, pParent)
00051 {
00052
00053
00054 m_bMove = bMove;
00055 m_nCookie = 0;
00056 }
00057
00058 void CFileCopyDlg::DoDataExchange(CDataExchange* pDX)
00059 {
00060 CSkinDialog::DoDataExchange(pDX);
00061
00062 DDX_Control(pDX, IDC_MESSAGE_MOVE, m_wndMove);
00063 DDX_Control(pDX, IDC_MESSAGE_COPY, m_wndCopy);
00064 DDX_Control(pDX, IDC_FILE_NAME, m_wndFileName);
00065 DDX_Control(pDX, IDC_PROGRESS_FILE, m_wndFileProg);
00066 DDX_Control(pDX, IDCANCEL, m_wndCancel);
00067 DDX_Control(pDX, IDOK, m_wndOK);
00068 DDX_Control(pDX, IDC_PROGRESS, m_wndProgress);
00069 DDX_Control(pDX, IDC_PLACEHOLDER, m_wndPlaceholder);
00070
00071 }
00072
00074
00075
00076 void CFileCopyDlg::AddFile(CLibraryFile* pFile)
00077 {
00078 m_pFiles.AddTail( (LPVOID)pFile->m_nIndex );
00079 }
00080
00081 BOOL CFileCopyDlg::OnInitDialog()
00082 {
00083 CSkinDialog::OnInitDialog();
00084
00085 SkinMe( _T("CFileCopyDlg"), IDR_LIBRARYFRAME );
00086 SelectCaption( this, m_bMove ? 1 : 0 );
00087
00088 CString strCaption, strBase;
00089
00090 CWnd* pMessage = m_bMove ? &m_wndMove : &m_wndCopy;
00091 pMessage->GetWindowText( strBase );
00092 strCaption.Format( strBase, m_pFiles.GetCount() );
00093 pMessage->SetWindowText( strCaption );
00094 pMessage->ShowWindow( SW_SHOW );
00095
00096 CRect rc;
00097 m_wndPlaceholder.GetWindowRect( &rc );
00098 ScreenToClient( &rc );
00099 if ( ! m_wndTree.Create( WS_VISIBLE|WS_TABSTOP|WS_BORDER, rc, this, IDC_FOLDERS ) ) return -1;
00100 m_wndTree.SetMultiSelect( FALSE );
00101
00102 {
00103 CQuickLock oLock( Library.m_pSection );
00104
00105 m_nCookie = Library.m_nUpdateCookie;
00106 m_wndTree.Update();
00107
00108 if ( CLibraryFolder* pFolder = LibraryFolders.GetFolder( m_sTarget ) )
00109 {
00110 m_wndTree.SelectFolder( pFolder );
00111 }
00112 }
00113
00114 if ( theApp.m_bRTL )
00115 {
00116 m_wndProgress.ModifyStyleEx( WS_EX_LAYOUTRTL, 0, 0 );
00117 m_wndFileProg.ModifyStyleEx( WS_EX_LAYOUTRTL, 0, 0 );
00118 }
00119 m_wndFileProg.SetRange( 0, 400 );
00120
00121 m_hThread = NULL;
00122 m_bThread = FALSE;
00123
00124 PostMessage( WM_TIMER, 1 );
00125 SetTimer( 1, 500, NULL );
00126
00127 return TRUE;
00128 }
00129
00130 void CFileCopyDlg::OnTimer(UINT nIDEvent)
00131 {
00132 if ( m_hThread != NULL )
00133 {
00134 if ( m_bThread ) return;
00135
00136 StopOperation();
00137
00138 PostMessage( WM_COMMAND, IDCANCEL );
00139
00140 return;
00141 }
00142
00143 if ( ! m_wndTree.IsWindowEnabled() ) return;
00144
00145 if ( m_nCookie != Library.m_nUpdateCookie )
00146 {
00147 CSingleLock pLock( &Library.m_pSection );
00148
00149 if ( pLock.Lock( 500 ) )
00150 {
00151 m_nCookie = Library.m_nUpdateCookie;
00152 m_wndTree.Update();
00153 }
00154 }
00155
00156 m_wndOK.EnableWindow( m_wndTree.GetSelectedFolderIterator() != NULL );
00157 }
00158
00159 BOOL CFileCopyDlg::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
00160 {
00161 NMHDR* pNotify = (NMHDR*)lParam;
00162
00163 if ( pNotify->code == NM_DBLCLK )
00164 {
00165 PostMessage( WM_COMMAND, IDOK );
00166 return TRUE;
00167 }
00168
00169 return CSkinDialog::OnNotify(wParam, lParam, pResult);
00170 }
00171
00172 void CFileCopyDlg::OnOK()
00173 {
00174 CSingleLock pLock( &Library.m_pSection, TRUE );
00175
00176 POSITION pos = m_wndTree.GetSelectedFolderIterator();
00177 if ( pos == NULL ) return;
00178
00179 CLibraryFolder* pFolder = m_wndTree.GetNextSelectedFolder( pos );
00180
00181 m_sTarget = pFolder->m_sPath;
00182
00183 pLock.Unlock();
00184
00185 StartOperation();
00186 }
00187
00188 void CFileCopyDlg::OnCancel()
00189 {
00190 if ( m_hThread )
00191 {
00192 StopOperation();
00193 m_wndFileName.SetWindowText( _T("Operation cancelled") );
00194 return;
00195 }
00196
00197 StopOperation();
00198
00199 CSkinDialog::OnCancel();
00200 }
00201
00203
00204
00205 void CFileCopyDlg::StartOperation()
00206 {
00207 if ( m_hThread ) return;
00208
00209 m_wndTree.EnableWindow( FALSE );
00210 m_wndOK.EnableWindow( FALSE );
00211
00212 m_wndProgress.SetRange( 0, m_pFiles.GetCount() );
00213 m_wndProgress.SetPos( 0 );
00214
00215 m_bThread = TRUE;
00216 m_bCancel = FALSE;
00217 CWinThread* pThread = AfxBeginThread( ThreadStart, this, THREAD_PRIORITY_NORMAL );
00218 m_hThread = pThread->m_hThread;
00219 }
00220
00221 void CFileCopyDlg::StopOperation()
00222 {
00223 if ( m_hThread == NULL ) return;
00224
00225 CWaitCursor pCursor;
00226
00227 m_bThread = FALSE;
00228
00229 int nAttempt = 100;
00230 for ( ; nAttempt > 0 ; nAttempt-- )
00231 {
00232 DWORD nCode;
00233
00234 if ( ! GetExitCodeThread( m_hThread, &nCode ) ) break;
00235 if ( nCode != STILL_ACTIVE ) break;
00236 Sleep( 250 );
00237 }
00238
00239 if ( nAttempt == 0 )
00240 {
00241 TerminateThread( m_hThread, 0 );
00242 theApp.Message( MSG_DEBUG, _T("WARNING: Terminating FileOp thread.") );
00243 Sleep( 250 );
00244 }
00245
00246 m_hThread = NULL;
00247
00248
00249 CString sText;
00250 LoadString ( sText, IDS_GENERAL_CLOSE );
00251 m_wndCancel.SetWindowText( sText );
00252 m_wndProgress.EnableWindow( FALSE );
00253 }
00254
00256
00257
00258 UINT CFileCopyDlg::ThreadStart(LPVOID pParam)
00259 {
00260 CFileCopyDlg* pClass = (CFileCopyDlg*)pParam;
00261 pClass->OnRun();
00262 return 0;
00263 }
00264
00265 void CFileCopyDlg::OnRun()
00266 {
00267 while ( m_bThread )
00268 {
00269 CString strName, strPath;
00270 BOOL bMetaData;
00271
00272 CLibraryFile* pFile;
00273 {
00274 CQuickLock oLock( Library.m_pSection );
00275
00276 if ( m_pFiles.IsEmpty() ) break;
00277
00278 DWORD nIndex = (DWORD)m_pFiles.RemoveHead();
00279
00280 pFile = Library.LookupFile( nIndex );
00281
00282 if ( pFile != NULL && pFile->IsAvailable() )
00283 {
00284 strName = pFile->m_sName;
00285 strPath = pFile->m_pFolder->m_sPath;
00286 bMetaData = ( pFile->m_pMetadata != NULL ) && ! pFile->m_bMetadataAuto;
00287 }
00288 }
00289
00290 if ( NULL == pFile || ! pFile->IsAvailable() ) break;
00291
00292 m_wndProgress.OffsetPos( 1 );
00293
00294
00295 m_wndFileName.SetWindowText( strName );
00296 ProcessFile( strName, strPath, bMetaData );
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323 }
00324
00325
00326 m_bThread = FALSE;
00327 }
00328
00330
00331
00332 BOOL CFileCopyDlg::ProcessFile(CString& strName, CString& strPath, BOOL bMetaData)
00333 {
00334 if ( strPath.CompareNoCase( m_sTarget ) == 0 ) return FALSE;
00335
00336 CString sSource, sTarget;
00337
00338
00339 sSource = strPath + _T("\\") + strName;
00340 HANDLE hFile = CreateFile( sSource, GENERIC_WRITE, 0 , NULL,
00341 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
00342 if ( hFile == INVALID_HANDLE_VALUE )
00343 {
00344 CString strMessage, strFormat, strName;
00345 LoadString( strFormat, IDS_LIBRARY_MOVE_FAIL );
00346
00347 m_wndFileName.GetWindowText( strName );
00348 strMessage.Format( strFormat, strName );
00349
00350 switch ( AfxMessageBox( strMessage, MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 ) )
00351 {
00352 case IDYES:
00353 break;
00354 case IDNO:
00355 default:
00356 CloseHandle( hFile );
00357 return FALSE;
00358 }
00359 }
00360 CloseHandle( hFile );
00361
00362
00363 if ( bMetaData )
00364 {
00365 CString strMetaFolder = strPath + _T("\\Metadata");
00366
00367 sSource = strMetaFolder + _T("\\") + strName + _T(".xml");
00368
00369 sTarget = m_sTarget + _T("\\Metadata");
00370 CreateDirectory( sTarget, NULL );
00371 sTarget += _T("\\") + strName + _T(".xml");
00372
00373 if ( sSource.CompareNoCase( sTarget ) == 0 ) return FALSE;
00374
00375 if ( m_bMove )
00376 {
00377 if ( ProcessMove( sSource, sTarget ) )
00378 {
00379 Sleep( 50 );
00380 RemoveDirectory( strMetaFolder );
00381 }
00382 }
00383 else
00384 {
00385 ProcessCopy( sSource, sTarget );
00386 }
00387 }
00388
00389
00390 sSource = strPath + _T("\\") + strName;
00391 sTarget = m_sTarget + _T("\\") + strName;
00392
00393 if ( sSource.CompareNoCase( sTarget ) == 0 ) return FALSE;
00394
00395 if ( m_bMove )
00396 {
00397 if ( ! ProcessMove( sSource, sTarget ) ) return FALSE;
00398 }
00399 else
00400 {
00401 if ( ! ProcessCopy( sSource, sTarget ) ) return FALSE;
00402 }
00403
00404 return TRUE;
00405 }
00406
00407 BOOL CFileCopyDlg::CheckTarget(LPCTSTR pszTarget)
00408 {
00409 if ( GetFileAttributes( pszTarget ) == 0xFFFFFFFF ) return TRUE;
00410
00411 CString strFormat, strMessage;
00412
00413 LoadString( strFormat, IDS_LIBRARY_TARGET_EXISTS );
00414 strMessage.Format( strFormat, pszTarget );
00415
00416 switch ( AfxMessageBox( strMessage, MB_ICONQUESTION|MB_YESNOCANCEL|MB_DEFBUTTON2 ) )
00417 {
00418 case IDYES:
00419 break;
00420 case IDCANCEL:
00421 m_bThread = FALSE;
00422 case IDNO:
00423 default:
00424 return FALSE;
00425 }
00426
00427 if ( DeleteFile( pszTarget ) ) return TRUE;
00428
00429 CString strError = theApp.GetErrorString();
00430
00431 LoadString( strFormat, IDS_LIBRARY_DELETE_FAIL );
00432 strMessage.Format( strFormat, pszTarget );
00433 strMessage += _T("\r\n\r\n") + strError;
00434
00435 AfxMessageBox( strMessage, MB_ICONEXCLAMATION );
00436
00437 return FALSE;
00438 }
00439
00440 BOOL CFileCopyDlg::ProcessMove(LPCTSTR pszSource, LPCTSTR pszTarget)
00441 {
00442 if ( ! CheckTarget( pszTarget ) ) return FALSE;
00443
00444 Uploads.OnRename( pszSource );
00445
00446
00447 if ( MoveFile( pszSource, pszTarget ) )
00448 {
00449 Uploads.OnRename( pszSource, pszTarget );
00450 return TRUE;
00451 }
00452
00453
00454 if ( ProcessCopy( pszSource, pszTarget ) )
00455 {
00456 Uploads.OnRename( pszSource, pszTarget );
00457 return DeleteFile( pszSource );
00458 }
00459
00460 Uploads.OnRename( pszSource, pszSource );
00461
00462 return FALSE;
00463 }
00464
00465 typedef DWORD (WINAPI *LPPROGRESS_ROUTINE_X)(LARGE_INTEGER TotalFileSize, LARGE_INTEGER TotalBytesTransferred, LARGE_INTEGER StreamSize, LARGE_INTEGER StreamBytesTransferred, DWORD dwStreamNumber, DWORD dwCallbackReason, HANDLE hSourceFile, HANDLE hDestinationFile, LPVOID lpData OPTIONAL);
00466
00467 BOOL CFileCopyDlg::ProcessCopy(LPCTSTR pszSource, LPCTSTR pszTarget)
00468 {
00469 if ( ! CheckTarget( pszTarget ) ) return FALSE;
00470
00471 HINSTANCE hKernel = LoadLibrary( _T("kernel32.dll") );
00472
00473 if ( hKernel != NULL )
00474 {
00475 BOOL (WINAPI *pfnCopyFileEx)(LPCTSTR, LPCTSTR, LPPROGRESS_ROUTINE_X, LPVOID, LPBOOL, DWORD);
00476
00477 (FARPROC&)pfnCopyFileEx = GetProcAddress( hKernel, "CopyFileExW" );
00478
00479 if ( pfnCopyFileEx != NULL )
00480 {
00481 m_wndFileProg.SetPos( 0 );
00482 m_nFileProg = 0;
00483
00484 BOOL bResult = (*pfnCopyFileEx)( pszSource, pszTarget, CopyCallback, this,
00485 &m_bCancel, 1 );
00486
00487 FreeLibrary( hKernel );
00488
00489 if ( ! bResult && ! m_bThread ) DeleteFile( pszTarget );
00490
00491 return bResult;
00492 }
00493
00494 FreeLibrary( hKernel );
00495 }
00496
00497 return CopyFile( pszSource, pszTarget, TRUE );
00498 }
00499
00500 DWORD WINAPI CFileCopyDlg::CopyCallback(LARGE_INTEGER TotalFileSize, LARGE_INTEGER TotalBytesTransferred, LARGE_INTEGER StreamSize, LARGE_INTEGER StreamBytesTransferred, DWORD dwStreamNumber, DWORD dwCallbackReason, HANDLE hSourceFile, HANDLE hDestinationFile, LPVOID lpData)
00501 {
00502 CFileCopyDlg* pDlg = (CFileCopyDlg*)lpData;
00503
00504 if ( ! pDlg->m_bThread ) return 1;
00505
00506 if ( TotalFileSize.LowPart )
00507 {
00508 double nProgress = ( (double)TotalBytesTransferred.LowPart / (double)TotalFileSize.LowPart );
00509 int iProgress = (int)( nProgress * 400 );
00510
00511 if ( iProgress != pDlg->m_nFileProg )
00512 {
00513 pDlg->m_wndFileProg.SetPos( pDlg->m_nFileProg = iProgress );
00514 }
00515 }
00516
00517 return 0;
00518 }