NResult::EEnum Execute(const CFileInfo &oldFileInfo, const CFileInfo &newFileInfo) { const int kYSize = 20; const int kXSize = 76; CFileInfoStrings oldFileInfoStrings; CFileInfoStrings newFileInfoStrings; SetFileInfoStrings(oldFileInfo, oldFileInfoStrings); SetFileInfoStrings(newFileInfo, newFileInfoStrings); AString oldName = UnicodeStringToMultiByte(oldFileInfo.Name, CP_OEMCP); AString newName = UnicodeStringToMultiByte(newFileInfo.Name, CP_OEMCP); struct CInitDialogItem initItems[]={ { DI_DOUBLEBOX, 3, 1, kXSize - 4, kYSize - 2, false, false, 0, false, NMessageID::kOverwriteTitle, NULL, NULL }, { DI_TEXT, 5, 2, 0, 0, false, false, 0, false, NMessageID::kOverwriteMessage1, NULL, NULL }, { DI_TEXT, 3, 3, 0, 0, false, false, DIF_BOXCOLOR|DIF_SEPARATOR, false, -1, "", NULL }, { DI_TEXT, 5, 4, 0, 0, false, false, 0, false, NMessageID::kOverwriteMessageWouldYouLike, NULL, NULL }, { DI_TEXT, 7, 6, 0, 0, false, false, 0, false, -1, oldName, NULL }, { DI_TEXT, 7, 7, 0, 0, false, false, 0, false, -1, oldFileInfoStrings.Size, NULL }, { DI_TEXT, 7, 8, 0, 0, false, false, 0, false, -1, oldFileInfoStrings.Time, NULL }, { DI_TEXT, 5, 10, 0, 0, false, false, 0, false, NMessageID::kOverwriteMessageWithtTisOne, NULL, NULL }, { DI_TEXT, 7, 12, 0, 0, false, false, 0, false, -1, newName, NULL }, { DI_TEXT, 7, 13, 0, 0, false, false, 0, false, -1, newFileInfoStrings.Size, NULL }, { DI_TEXT, 7, 14, 0, 0, false, false, 0, false, -1, newFileInfoStrings.Time, NULL }, { DI_TEXT, 3, kYSize - 5, 0, 0, false, false, DIF_BOXCOLOR|DIF_SEPARATOR, false, -1, "", NULL }, { DI_BUTTON, 0, kYSize - 4, 0, 0, true, false, DIF_CENTERGROUP, true, NMessageID::kOverwriteYes, NULL, NULL }, { DI_BUTTON, 0, kYSize - 4, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kOverwriteYesToAll, NULL, NULL }, { DI_BUTTON, 0, kYSize - 4, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kOverwriteNo, NULL, NULL }, { DI_BUTTON, 0, kYSize - 4, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kOverwriteNoToAll, NULL, NULL }, { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kOverwriteAutoRename, NULL, NULL }, { DI_BUTTON, 0, kYSize - 3, 0, 0, false, false, DIF_CENTERGROUP, false, NMessageID::kOverwriteCancel, NULL, NULL } }; const int kNumDialogItems = ARRAY_SIZE(initItems); FarDialogItem aDialogItems[kNumDialogItems]; g_StartupInfo.InitDialogItems(initItems, aDialogItems, kNumDialogItems); int anAskCode = g_StartupInfo.ShowDialog(kXSize, kYSize, NULL, aDialogItems, kNumDialogItems); const int kButtonStartPos = kNumDialogItems - 6; if (anAskCode >= kButtonStartPos && anAskCode < kNumDialogItems) return NResult::EEnum(anAskCode - kButtonStartPos); return NResult::kCancel; }
void UpdateFileInfoStatus(FILEINFO *pFileinfo, const HWND hwndListView) { pFileinfo->status = InfoToIntValue(pFileinfo); SetFileInfoStrings(pFileinfo, pFileinfo->parentList); if(g_program_options.bHideVerified && pFileinfo->status == STATUS_OK) { LVFINDINFO findInfo; ZeroMemory(&findInfo, sizeof(LVFINDINFO)); findInfo.flags = LVFI_PARAM; findInfo.lParam = (LPARAM)pFileinfo; int pos = ListView_FindItem(hwndListView, -1, &findInfo); if(pos >= 0) ListView_DeleteItem(hwndListView, pos); } }
/***************************************************************************** UINT __stdcall ThreadProc_Calc(VOID * pParam) pParam : (IN/OUT) THREAD_PARAMS_CALC struct pointer special for this thread Return Value: returns 0 Notes: - requests jobs from the queue and calculates hashes until the queue is empty - spawns up to three additional threads, one for each hash value - performs asynchronous I/O with two buffers -> one buffer is filled while the hash-threads work on the other buffer - if an error occured, GetLastError() is saved in the current pFileinfo->dwError - what has be calculated is determined by bDoCalculate[HASH_TYPE_CRC32]/bDoCalculate[HASH_TYPE_MD5]/bDoCalculate[HASH_TYPE_ED2K] of the current job *****************************************************************************/ UINT __stdcall ThreadProc_Calc(VOID * pParam) { THREAD_PARAMS_CALC * CONST pthread_params_calc = (THREAD_PARAMS_CALC *)pParam; CONST HWND * CONST arrHwnd = pthread_params_calc->arrHwnd; SHOWRESULT_PARAMS * CONST pshowresult_params = pthread_params_calc->pshowresult_params; BOOL bDoCalculate[NUM_HASH_TYPES]; QWORD qwStart, qwStop, wqFreq; HANDLE hFile; BYTE *readBuffer = (BYTE *)malloc(MAX_BUFFER_SIZE_CALC); BYTE *calcBuffer = (BYTE *)malloc(MAX_BUFFER_SIZE_CALC); BYTE *tempBuffer; DWORD readWords[2]; DWORD *dwBytesReadRb = &readWords[0]; DWORD *dwBytesReadCb = &readWords[1]; DWORD *dwBytesReadTb; BOOL bSuccess; BOOL bFileDone; BOOL bAsync; HANDLE hEvtThreadGo[NUM_HASH_TYPES]; HANDLE hEvtThreadReady[NUM_HASH_TYPES]; HANDLE hEvtReadDone; OVERLAPPED olp; ZeroMemory(&olp,sizeof(olp)); HANDLE hThread[NUM_HASH_TYPES]; HANDLE hEvtReadyHandles[NUM_HASH_TYPES]; DWORD cEvtReadyHandles; THREAD_PARAMS_HASHCALC calcParams[NUM_HASH_TYPES]; lFILEINFO *fileList; list<FILEINFO*> finalList; if(readBuffer == NULL || calcBuffer == NULL) { ShowErrorMsg(arrHwnd[ID_MAIN_WND],GetLastError()); ExitProcess(1); } // set some UI stuff: // - disable action buttons while in thread EnableWindowsForThread(arrHwnd, FALSE); ShowResult(arrHwnd, NULL, pshowresult_params); while((fileList = SyncQueue.popQueue()) != NULL) { cEvtReadyHandles = 0; for(int i=0;i<NUM_HASH_TYPES;i++) { bDoCalculate[i] = !fileList->bCalculated[i] && fileList->bDoCalculate[i]; if(bDoCalculate[i]) { fileList->bCalculated[i] = TRUE; hEvtThreadGo[i] = CreateEvent(NULL,FALSE,FALSE,NULL); hEvtThreadReady[i] = CreateEvent(NULL,FALSE,FALSE,NULL); if(hEvtThreadGo[i] == NULL || hEvtThreadReady[i] == NULL) { ShowErrorMsg(arrHwnd[ID_MAIN_WND],GetLastError()); ExitProcess(1); } hEvtReadyHandles[cEvtReadyHandles] = hEvtThreadReady[i]; cEvtReadyHandles++; calcParams[i].bFileDone = &bFileDone; calcParams[i].hHandleGo = hEvtThreadGo[i]; calcParams[i].hHandleReady = hEvtThreadReady[i]; calcParams[i].buffer = &calcBuffer; calcParams[i].dwBytesRead = &dwBytesReadCb; } } hEvtReadDone = CreateEvent(NULL,FALSE,FALSE,NULL); if(hEvtReadDone == NULL) { ShowErrorMsg(arrHwnd[ID_MAIN_WND],GetLastError()); ExitProcess(1); } QueryPerformanceFrequency((LARGE_INTEGER*)&wqFreq); if(g_program_options.bEnableQueue && g_pstatus.bHaveComCtrlv6) { if(fileList->iGroupId==0) InsertGroupIntoListView(arrHwnd[ID_LISTVIEW],fileList); else RemoveGroupItems(arrHwnd[ID_LISTVIEW],fileList->iGroupId); } for(list<FILEINFO>::iterator it=fileList->fInfos.begin();it!=fileList->fInfos.end();it++) { pthread_params_calc->pFileinfo_cur = &(*it); pthread_params_calc->qwBytesReadCurFile = 0; FILEINFO& curFileInfo = (*it); if ( (curFileInfo.dwError == NO_ERROR) && cEvtReadyHandles > 0) { DisplayStatusOverview(arrHwnd[ID_EDIT_STATUS]); QueryPerformanceCounter((LARGE_INTEGER*) &qwStart); hFile = CreateFile(curFileInfo.szFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED | FILE_FLAG_SEQUENTIAL_SCAN , 0); if(hFile == INVALID_HANDLE_VALUE){ curFileInfo.dwError = GetLastError(); } else { bFileDone = FALSE; for(int i=0;i<NUM_HASH_TYPES;i++) { if(bDoCalculate[i]) { ResetEvent(hEvtThreadGo[i]); ResetEvent(hEvtThreadReady[i]); calcParams[i].result = &curFileInfo.hashInfo[i].r; hThread[i] = CreateThread(NULL,0,hash_function[i],&calcParams[i],0,NULL); if(hThread[i] == NULL) { ShowErrorMsg(arrHwnd[ID_MAIN_WND],GetLastError()); ExitProcess(1); } } } ZeroMemory(&olp,sizeof(olp)); olp.hEvent = hEvtReadDone; olp.Offset = 0; olp.OffsetHigh = 0; bSuccess = ReadFile(hFile, readBuffer, MAX_BUFFER_SIZE_CALC, dwBytesReadRb, &olp); if(!bSuccess && (GetLastError()==ERROR_IO_PENDING)) bAsync = TRUE; else bAsync = FALSE; do { if(bAsync) bSuccess = GetOverlappedResult(hFile,&olp,dwBytesReadRb,TRUE); if(!bSuccess && (GetLastError() != ERROR_HANDLE_EOF)) { curFileInfo.dwError = GetLastError(); bFileDone = TRUE; } pthread_params_calc->qwBytesReadCurFile += *dwBytesReadRb; //for progress bar pthread_params_calc->qwBytesReadAllFiles += *dwBytesReadRb; olp.Offset = pthread_params_calc->qwBytesReadCurFile & 0xffffffff; olp.OffsetHigh = (pthread_params_calc->qwBytesReadCurFile >> 32) & 0xffffffff; WaitForMultipleObjects(cEvtReadyHandles,hEvtReadyHandles,TRUE,INFINITE); SWAPBUFFERS(); bSuccess = ReadFile(hFile, readBuffer, MAX_BUFFER_SIZE_CALC, dwBytesReadRb, &olp); if(!bSuccess && (GetLastError()==ERROR_IO_PENDING)) bAsync = TRUE; else bAsync = FALSE; if(*dwBytesReadCb<MAX_BUFFER_SIZE_CALC || pthread_params_calc->signalExit) bFileDone=TRUE; for(int i=0;i<NUM_HASH_TYPES;i++) { if(bDoCalculate[i]) SetEvent(hEvtThreadGo[i]); } } while(!bFileDone); WaitForMultipleObjects(cEvtReadyHandles,hEvtReadyHandles,TRUE,INFINITE); if(hFile != NULL) CloseHandle(hFile); for(int i=0;i<NUM_HASH_TYPES;i++) { if(bDoCalculate[i]) CloseHandle(hThread[i]); } if(pthread_params_calc->signalExit) break; QueryPerformanceCounter((LARGE_INTEGER*) &qwStop); curFileInfo.fSeconds = (float)((qwStop - qwStart) / (float)wqFreq); } } curFileInfo.status = InfoToIntValue(&curFileInfo); SetFileInfoStrings(&curFileInfo,fileList); if(!g_pstatus.bHideVerified || curFileInfo.status != STATUS_OK) { InsertItemIntoList(arrHwnd[ID_LISTVIEW], &curFileInfo,fileList); } SyncQueue.getDoneList(); SyncQueue.adjustErrorCounters(&curFileInfo,1); SyncQueue.releaseDoneList(); ShowResult(arrHwnd, &curFileInfo, pshowresult_params); } for(int i=0;i<NUM_HASH_TYPES;i++) { if(bDoCalculate[i]) { CloseHandle(hEvtThreadGo[i]); CloseHandle(hEvtThreadReady[i]); } } if(pthread_params_calc->signalExit) break; if(fileList->uiCmdOpts!=CMD_NORMAL) { for(list<FILEINFO>::iterator it=fileList->fInfos.begin();it!=fileList->fInfos.end();it++) { finalList.push_back(&(*it)); } finalList.sort(ListPointerCompFunction); switch(fileList->uiCmdOpts) { case CMD_SFV: case CMD_MD5: case CMD_SHA1: case CMD_SHA256: case CMD_SHA512: CreateChecksumFiles(arrHwnd,fileList->uiCmdOpts,&finalList); break; case CMD_NAME: ActionHashIntoFilename(arrHwnd, TRUE, &finalList, HASH_TYPE_CRC32); break; case CMD_NTFS: ActionCrcIntoStream(arrHwnd,TRUE,&finalList); break; default: break; } finalList.clear(); } SyncQueue.addToList(fileList); }