Esempio n. 1
0
/*****************************************************************************
VOID ActionCrcIntoFilename(CONST HWND arrHwnd[ID_NUM_WINDOWS])
	arrHwnd : (IN) window handle array

Return Value:
	returns nothing

Notes:
	- wrapper for the three parameter version
	- calls FillFinalList to get its list
*****************************************************************************/
VOID ActionHashIntoFilename(CONST HWND arrHwnd[ID_NUM_WINDOWS], UINT uiHashType)
{
	list<FILEINFO*> finalList;

	if(CheckIfRehashNecessary(arrHwnd, uiHashType))
		return;

	FillFinalList(arrHwnd[ID_LISTVIEW],&finalList,ListView_GetSelectedCount(arrHwnd[ID_LISTVIEW]));
	if(finalList.size()>1) {
		finalList.sort(ListPointerCompFunction);
		finalList.unique(ListPointerUniqFunction);
	}
	ActionHashIntoFilename(arrHwnd, FALSE, &finalList, uiHashType);
}
/*****************************************************************************
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);

	}