コード例 #1
0
ファイル: HashSave.c プロジェクト: modelrockettier/HashCheck
VOID __fastcall HashSaveWorkerMain( PHASHSAVECONTEXT phsctx )
{
    // Note that ALL message communication to and from the main window MUST
    // be asynchronous, or else there may be a deadlock.

    PHASHSAVEITEM pItem;

    // Prep: expand directories, max path, etc. (prefix was set by earlier call)
    PostMessage(phsctx->hWnd, HM_WORKERTHREAD_TOGGLEPREP, (WPARAM)phsctx, TRUE);
    HashCalcPrepare(phsctx);
    PostMessage(phsctx->hWnd, HM_WORKERTHREAD_TOGGLEPREP, (WPARAM)phsctx, FALSE);

    // Indicate which hash type we are after, see WHEX... values in WinHash.h
    phsctx->whctx.flags = 1 << (phsctx->ofn.nFilterIndex - 1);

    while (pItem = SLGetDataAndStep(phsctx->hList))
    {
        // Get the hash
        WorkerThreadHashFile(
            (PCOMMONCONTEXT)phsctx,
            pItem->szPath,
            &pItem->bValid,
            &phsctx->whctx,
            &pItem->results,
            NULL
        );

        if (phsctx->status == CANCEL_REQUESTED)
            return;

        // Write the data
        HashCalcWriteResult(phsctx, pItem);

        // Update the UI
        ++phsctx->cSentMsgs;
        PostMessage(phsctx->hWnd, HM_WORKERTHREAD_UPDATE, (WPARAM)phsctx, (LPARAM)pItem);
    }
}
コード例 #2
0
ファイル: HashVerify.c プロジェクト: da2ce7/HashCheck
VOID __fastcall HashVerifyWorkerMain( PHASHVERIFYCONTEXT phvctx )
{
	// Note that ALL message communication to and from the main window MUST
	// be asynchronous, or else there may be a deadlock

	PHASHVERIFYITEM pItem;

	// We need to keep track of the thread's execution time so that we can do a
	// sound notification of completion when appropriate
	DWORD dwTickStart = GetTickCount();

	// Initialize the path prefix length; used for building the full path
	PTSTR pszPathTail = StrRChr(phvctx->pszPath, NULL, TEXT('\\'));
	SIZE_T cchPathPrefix = (pszPathTail) ? pszPathTail + 1 - phvctx->pszPath : 0;

	while (pItem = SLGetDataAndStep(phvctx->hList))
	{
		BOOL bSuccess;

		// Part 1: Build the path
		{
			SIZE_T cchPrefix = cchPathPrefix;

			// Do not use the prefix if pszDisplayName is an absolute path
			if ( pItem->pszDisplayName[0] == TEXT('\\') ||
			     pItem->pszDisplayName[1] == TEXT(':') )
			{
				cchPrefix = 0;
			}

			SSChainNCpy2(
				phvctx->ex.pszPath,
				phvctx->pszPath, cchPrefix,
				pItem->pszDisplayName, pItem->cchDisplayName
			);
		}

		// Part 2: Calculate the checksum
		WorkerThreadHashFile(
			(PCOMMONCONTEXT)phvctx,
			phvctx->ex.pszPath,
			&bSuccess,
			&phvctx->whctx,
			NULL,
			&pItem->filesize
		);

		if (phvctx->status == CANCEL_REQUESTED)
			return;

		// Part 3: Do something with the results
		if (bSuccess)
		{
			if (phvctx->whctx.flags == WHEX_ALL128)
			{
				// If the MD4/MD5 STILL has not been settled by this point, then
				// settle it by a simple heuristic: if the checksum matches MD4,
				// go with that, otherwise default to MD5.

				if (StrCmpI(pItem->pszExpected, phvctx->whctx.results.szHexMD4) == 0)
					phvctx->whctx.flags = WHEX_CHECKMD4;
				else
					phvctx->whctx.flags = WHEX_CHECKMD5;
			}

			switch (phvctx->whctx.flags)
			{
				case WHEX_CHECKCRC32:
					SSStaticCpy(pItem->szActual, phvctx->whctx.results.szHexCRC32);
					break;
				case WHEX_CHECKMD4:
					SSStaticCpy(pItem->szActual, phvctx->whctx.results.szHexMD4);
					break;
				case WHEX_CHECKMD5:
					SSStaticCpy(pItem->szActual, phvctx->whctx.results.szHexMD5);
					break;
				case WHEX_CHECKSHA1:
					SSStaticCpy(pItem->szActual, phvctx->whctx.results.szHexSHA1);
					break;
			}

			if (StrCmpI(pItem->pszExpected, pItem->szActual) == 0)
				pItem->uStatusID = HV_STATUS_MATCH;
			else
				pItem->uStatusID = HV_STATUS_MISMATCH;
		}
		else
		{
			pItem->uStatusID = HV_STATUS_UNREADABLE;
		}

		// Part 4: Update the UI
		++phvctx->cSentMsgs;
		PostMessage(phvctx->hWnd, HM_WORKERTHREAD_UPDATE, (WPARAM)phvctx, (LPARAM)pItem);
	}

	// Play a sound to signal the normal, successful termination of operations,
	// but exempt operations that were nearly instantaneous
	if (phvctx->cTotal && GetTickCount() - dwTickStart >= 2000)
		MessageBeep(MB_ICONASTERISK);
}
コード例 #3
0
ファイル: HashSave.cpp プロジェクト: gurnec/HashCheck
VOID __fastcall HashSaveWorkerMain( PHASHSAVECONTEXT phsctx )
{
	// Note that ALL message communication to and from the main window MUST
	// be asynchronous, or else there may be a deadlock.

	// Prep: expand directories, max path, etc. (prefix was set by earlier call)
	PostMessage(phsctx->hWnd, HM_WORKERTHREAD_TOGGLEPREP, (WPARAM)phsctx, TRUE);
	if (! HashCalcPrepare(phsctx))
        return;
    HashCalcSetSaveFormat(phsctx);
	PostMessage(phsctx->hWnd, HM_WORKERTHREAD_TOGGLEPREP, (WPARAM)phsctx, FALSE);

    // Extract the slist into a vector for parallel_for_each
    std::vector<PHASHSAVEITEM> vecpItems;
    vecpItems.resize(phsctx->cTotal + 1);
    SLBuildIndex(phsctx->hList, (PVOID*)vecpItems.data());
    assert(vecpItems.back() == nullptr);
    vecpItems.pop_back();
    assert(vecpItems.back() != nullptr);

#ifdef USE_PPL
    const bool bMultithreaded = vecpItems.size() > 1 && IsSSD(vecpItems[0]->szPath);
    concurrency::concurrent_vector<void*> vecBuffers;  // a vector of all allocated read buffers (one per thread)
    DWORD dwBufferTlsIndex = TlsAlloc();               // TLS index of the current thread's read buffer
    if (dwBufferTlsIndex == TLS_OUT_OF_INDEXES)
        return;
#else
    constexpr bool bMultithreaded = false;
#endif

    PBYTE pbTheBuffer;  // file read buffer, used iff not multithreaded
    if (! bMultithreaded)
    {
        pbTheBuffer = (PBYTE)VirtualAlloc(NULL, READ_BUFFER_SIZE, MEM_COMMIT, PAGE_READWRITE);
        if (pbTheBuffer == NULL)
            return;
    }

    // Initialize the progress bar update synchronization vars
    CRITICAL_SECTION updateCritSec;
    volatile ULONGLONG cbCurrentMaxSize = 0;
    if (bMultithreaded)
        InitializeCriticalSection(&updateCritSec);

#ifdef _TIMED
    DWORD dwStarted;
    dwStarted = GetTickCount();
#endif

    class CanceledException {};

    // concurrency::parallel_for_each(vecpItems.cbegin(), vecpItems.cend(), ...
    auto per_file_worker = [&](PHASHSAVEITEM pItem)
	{
        WHCTXEX whctx;

        // Indicate which hash type we are after, see WHEX... values in WinHash.h
        whctx.dwFlags = 1 << (phsctx->ofn.nFilterIndex - 1);

        PBYTE pbBuffer;
#ifdef USE_PPL
        if (bMultithreaded)
        {
            // Allocate or retrieve the already-allocated read buffer for the current thread
            pbBuffer = (PBYTE)TlsGetValue(dwBufferTlsIndex);
            if (pbBuffer == NULL)
            {
                pbBuffer = (PBYTE)VirtualAlloc(NULL, READ_BUFFER_SIZE, MEM_COMMIT, PAGE_READWRITE);
                if (pbBuffer == NULL)
                    throw CanceledException();
                // Cache the read buffer for the current thread
                vecBuffers.push_back(pbBuffer);
                TlsSetValue(dwBufferTlsIndex, pbBuffer);
            }
        }
#endif

#pragma warning(push)
#pragma warning(disable: 4700 4703)  // potentially uninitialized local pointer variable 'pbBuffer' used
		// Get the hash
		WorkerThreadHashFile(
			(PCOMMONCONTEXT)phsctx,
			pItem->szPath,
			&whctx,
			&pItem->results,
            bMultithreaded ? pbBuffer : pbTheBuffer,
			NULL, 0,
            bMultithreaded ? &updateCritSec : NULL, &cbCurrentMaxSize
#ifdef _TIMED
          , &pItem->dwElapsed
#endif
        );

        if (phsctx->status == PAUSED)
            WaitForSingleObject(phsctx->hUnpauseEvent, INFINITE);
		if (phsctx->status == CANCEL_REQUESTED)
            throw CanceledException();

		// Write the data
		HashCalcWriteResult(phsctx, pItem);

		// Update the UI
		InterlockedIncrement(&phsctx->cSentMsgs);
		PostMessage(phsctx->hWnd, HM_WORKERTHREAD_UPDATE, (WPARAM)phsctx, (LPARAM)pItem);
    };
#pragma warning(pop)

    try
    {
#ifdef USE_PPL
        if (bMultithreaded)
            concurrency::parallel_for_each(vecpItems.cbegin(), vecpItems.cend(), per_file_worker);
        else
#endif
            std::for_each(vecpItems.cbegin(), vecpItems.cend(), per_file_worker);
    }
    catch (CanceledException) {}  // ignore cancellation requests

#ifdef _TIMED
    if (phsctx->cTotal > 1 && phsctx->status != CANCEL_REQUESTED)
    {
        union {
            CHAR  szA[MAX_STRINGMSG];
            WCHAR szW[MAX_STRINGMSG];
        } buffer;
        size_t cbBufferLeft;
        if (phsctx->opt.dwSaveEncoding == 1)  // UTF-16
        {
            StringCbPrintfExW(buffer.szW, sizeof(buffer), NULL, &cbBufferLeft, 0, L"; Total elapsed: %d ms\r\n", GetTickCount() - dwStarted);
        }
        else                                  // UTF-8 or ANSI
        {
            StringCbPrintfExA(buffer.szA, sizeof(buffer), NULL, &cbBufferLeft, 0,  "; Total elapsed: %d ms\r\n", GetTickCount() - dwStarted);
        }
        DWORD dwUnused;
        WriteFile(phsctx->hFileOut, buffer.szA, (DWORD) (sizeof(buffer) - cbBufferLeft), &dwUnused, NULL);
    }
#endif

#ifdef USE_PPL
    if (bMultithreaded)
    {
        for (void* pBuffer : vecBuffers)
            VirtualFree(pBuffer, 0, MEM_RELEASE);
        DeleteCriticalSection(&updateCritSec);
    }
    else
#endif
        VirtualFree(pbTheBuffer, 0, MEM_RELEASE);
}