Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

DlgFileCopy.cpp

Go to the documentation of this file.
00001 //
00002 // DlgFileCopy.cpp
00003 //
00004 // Copyright (c) Shareaza Development Team, 2002-2005.
00005 // This file is part of SHAREAZA (www.shareaza.com)
00006 //
00007 // Shareaza is free software; you can redistribute it
00008 // and/or modify it under the terms of the GNU General Public License
00009 // as published by the Free Software Foundation; either version 2 of
00010 // the License, or (at your option) any later version.
00011 //
00012 // Shareaza is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 //
00017 // You should have received a copy of the GNU General Public License
00018 // along with Shareaza; if not, write to the Free Software
00019 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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         //{{AFX_MSG_MAP(CFileCopyDlg)
00042         ON_WM_TIMER()
00043         //}}AFX_MSG_MAP
00044 END_MESSAGE_MAP()
00045 
00046 
00048 // CFileCopyDlg dialog
00049 
00050 CFileCopyDlg::CFileCopyDlg(CWnd* pParent, BOOL bMove) : CSkinDialog(CFileCopyDlg::IDD, pParent)
00051 {
00052         //{{AFX_DATA_INIT(CFileCopyDlg)
00053         //}}AFX_DATA_INIT
00054         m_bMove         = bMove;
00055         m_nCookie       = 0;
00056 }
00057 
00058 void CFileCopyDlg::DoDataExchange(CDataExchange* pDX)
00059 {
00060         CSkinDialog::DoDataExchange(pDX);
00061         //{{AFX_DATA_MAP(CFileCopyDlg)
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         //}}AFX_DATA_MAP
00071 }
00072 
00074 // CFileCopyDlg message handlers
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 // CFileCopyDlg operation control
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         //m_wndCancel.SetWindowText( _T("&Close") );
00249         CString sText;
00250         LoadString ( sText, IDS_GENERAL_CLOSE );
00251         m_wndCancel.SetWindowText( sText );
00252         m_wndProgress.EnableWindow( FALSE );
00253 }
00254 
00256 // CFileCopyDlg operation thread
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                 // Alternate code to check if file is hashing first
00301                 CString sCurrent, sFile;
00302                 int nRemaining;
00303                 LibraryBuilder.UpdateStatus( &sCurrent, &nRemaining );
00304                 sFile = strPath + _T("\\") + strName;
00305 
00306                 if ( sFile == sCurrent )
00307                 {
00308                         LoadString ( sFile, IDS_LIBRARY_BITZI_HASHED );
00309                         sCurrent.Format( sFile, strName );
00310                         theApp.Message( MSG_SYSTEM, sCurrent  );
00311 
00312                         LoadString ( sCurrent, IDS_STATUS_FILEERROR );
00313                         m_wndFileName.SetWindowText( sCurrent );
00314                         
00315                 }
00316                 else
00317                 {
00318                         m_wndFileName.SetWindowText( strName );
00319                         ProcessFile( strName, strPath, bMetaData );
00320                 }
00321                 //
00322 */
00323         }
00324 
00325 
00326         m_bThread = FALSE;
00327 }
00328 
00330 // CFileCopyDlg file processing
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         // Check if we can move the file first
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         // Move the metadata
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         // Move the file
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         // Try moving the file
00447         if ( MoveFile( pszSource, pszTarget ) )
00448         {
00449                 Uploads.OnRename( pszSource, pszTarget );
00450                 return TRUE;
00451         }
00452 
00453         // Try a copy/delete. (Will usually make a duplicate of the file)
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 );        // COPY_FILE_FAIL_IF_EXISTS
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 }

Generated on Thu Dec 15 10:39:39 2005 for Shareaza 2.2.1.0 by  doxygen 1.4.2