Exemple #1
0
VOID WINAPI HashCalcInitSave( PHASHCALCCONTEXT phcctx )
{
	HWND hWnd = phcctx->hWnd;

	// We can use the extended portion of the scratch buffer for the file name
	PTSTR pszFile = (PTSTR)phcctx->scratch.ext;

	// Default result value
	phcctx->hFileOut = INVALID_HANDLE_VALUE;

	// Load settings
	phcctx->opt.dwFlags = HCOF_FILTERINDEX | HCOF_SAVEENCODING;
	OptionsLoad(&phcctx->opt);

	// Initialize the struct for the first time, if needed
	if (phcctx->ofn.lStructSize == 0)
	{
		phcctx->ofn.lStructSize = sizeof(phcctx->ofn);
		phcctx->ofn.hwndOwner = hWnd;
		phcctx->ofn.lpstrFilter = SAVE_FILTERS;
		phcctx->ofn.nFilterIndex = phcctx->opt.dwFilterIndex;
		phcctx->ofn.lpstrFile = pszFile;
		phcctx->ofn.nMaxFile = MAX_PATH_BUFFER + 10;
		phcctx->ofn.Flags = OFN_DONTADDTORECENT | OFN_NOCHANGEDIR | OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST;
		phcctx->ofn.lpstrDefExt = TEXT("");

		// Set the initial file name
		{
			PTSTR pszOrigPath;

			SLReset(phcctx->hListRaw);
			pszOrigPath = SLGetDataAndStep(phcctx->hListRaw);

			if (SLCheck(phcctx->hListRaw))
			{
				// Multiple items were selected in Explorer
				SSChainNCpy2(
					pszFile,
					pszOrigPath, phcctx->cchPrefix,
					SAVE_DEFAULT_NAME, countof(SAVE_DEFAULT_NAME)
				);
			}
			else
			{
				// Only one item was selected in Explorer (may be a single
				// file or a directory containing multiple files)
				SSChainCpyCat(pszFile, pszOrigPath, SAVE_EXTS[phcctx->ofn.nFilterIndex]);
			}
		}
	}

	// We should also do a sanity check to make sure that the filter index
	// is set to a valid value since we depend on that to determine the format
	if ( GetSaveFileName(&phcctx->ofn) &&
	     phcctx->ofn.nFilterIndex &&
	     phcctx->ofn.nFilterIndex <= 4 )
	{
		BOOL bSuccess = FALSE;

		// Save the filter in the user's preferences
		if (phcctx->opt.dwFilterIndex != phcctx->ofn.nFilterIndex)
		{
			phcctx->opt.dwFilterIndex = phcctx->ofn.nFilterIndex;
			phcctx->opt.dwFlags = HCOF_FILTERINDEX;
			OptionsSave(&phcctx->opt);
		}

		// Extension fixup: Correct the extension to match the selected
		// type, but only if the extension was one of the 4 in the list
		if (phcctx->ofn.nFileExtension)
		{
			PTSTR pszExt = pszFile + phcctx->ofn.nFileExtension - 1;

			if ( StrCmpI(pszExt, TEXT(".sfv")) == 0 ||
			     StrCmpI(pszExt, TEXT(".md4")) == 0 ||
			     StrCmpI(pszExt, TEXT(".md5")) == 0 ||
			     StrCmpI(pszExt, TEXT(".sha1")) == 0 )
			{
				if (StrCmpI(pszExt, SAVE_EXTS[phcctx->ofn.nFilterIndex]))
					SSCpy(pszExt, SAVE_EXTS[phcctx->ofn.nFilterIndex]);
			}
		}

		// Adjust the file paths for the output path, if necessary
		HashCalcSetSavePrefix(phcctx, pszFile);

		// Open the file for output
		phcctx->hFileOut = CreateFile(
			pszFile,
			GENERIC_WRITE,
			FILE_SHARE_READ,
			NULL,
			CREATE_ALWAYS,
			FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
			NULL
		);

		if (phcctx->hFileOut != INVALID_HANDLE_VALUE)
		{
			// The actual format will be set when HashCalcWriteResult is called
			phcctx->szFormat[0] = 0;

			if (phcctx->opt.dwSaveEncoding == 1)
			{
				// Write the BOM for UTF-16LE
				WCHAR BOM = 0xFEFF;
				DWORD cbWritten;
				WriteFile(phcctx->hFileOut, &BOM, sizeof(WCHAR), &cbWritten, NULL);
			}
		}
		else
		{
			TCHAR szMessage[MAX_STRINGMSG];
			LoadString(g_hModThisDll, IDS_HC_SAVE_ERROR, szMessage, countof(szMessage));
			MessageBox(hWnd, szMessage, NULL, MB_OK | MB_ICONERROR);
		}
	}
}
Exemple #2
0
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);
}