예제 #1
0
VOID WINAPI HashSaveStart( HWND hWndOwner, HSIMPLELIST hListRaw )
{
    // Explorer will be blocking as long as this function is running, so we
    // want to return as quickly as possible and leave the work up to the
    // thread that we are going to spawn

    PHASHSAVECONTEXT phsctx = SLSetContextSize(hListRaw, sizeof(HASHSAVECONTEXT));

    if (phsctx)
    {
        HANDLE hThread;

        phsctx->hWnd = hWndOwner;
        phsctx->hListRaw = hListRaw;

        InterlockedIncrement(&g_cRefThisDll);
        SLAddRef(hListRaw);

        if (hThread = CreateThreadCRT(HashSaveThread, phsctx))
        {
            CloseHandle(hThread);
            return;
        }

        // If the thread creation was successful, the thread will be
        // responsible for decrementing the ref count
        SLRelease(hListRaw);
        InterlockedDecrement(&g_cRefThisDll);
    }
}
예제 #2
0
VOID WINAPI HashVerifyParseData( PHASHVERIFYCONTEXT phvctx )
{
	PTSTR pszData = phvctx->pszFileData;  // Points to the next line to process

	UINT cchChecksum;             // Expected length of the checksum in TCHARs
	BOOL bReverseFormat = FALSE;  // TRUE if using SFV's format of putting the checksum last
	BOOL bLinesRemaining = TRUE;  // TRUE if we have not reached the end of the data

	// Try to determine the file type from the extension
	{
		PTSTR pszExt = StrRChr(phvctx->pszPath, NULL, TEXT('.'));

		if (pszExt)
		{
			if (StrCmpI(pszExt, TEXT(".sfv")) == 0)
			{
				phvctx->whctx.flags = WHEX_CHECKCRC32;
				cchChecksum = 8;
				bReverseFormat = TRUE;
			}
			else if (StrCmpI(pszExt, TEXT(".md4")) == 0)
			{
				phvctx->whctx.flags = WHEX_CHECKMD4;
				cchChecksum = 32;
			}
			else if (StrCmpI(pszExt, TEXT(".md5")) == 0)
			{
				phvctx->whctx.flags = WHEX_CHECKMD5;
				cchChecksum = 32;
			}
			else if (StrCmpI(pszExt - 1, TEXT(".sha1")) == 0)
			{
				phvctx->whctx.flags = WHEX_CHECKSHA1;
				cchChecksum = 40;
			}
		}
	}

	while (bLinesRemaining)
	{
		PTSTR pszStartOfLine;  // First non-whitespace character of the line
		PTSTR pszEndOfLine;    // Last non-whitespace character of the line
        PTSTR pszChecksum = NULL, pszFileName = NULL;
		INT16 cchPath;         // This INCLUDES the NULL terminator!

		// Step 1: Isolate the current line as a NULL-terminated string
		{
			pszStartOfLine = pszData;

			// Find the end of the line
			while (*pszData && *pszData != TEXT('\n'))
				++pszData;

			// Terminate it if necessary, otherwise flag the end of the data
			if (*pszData)
				*pszData = 0;
			else
				bLinesRemaining = FALSE;

			pszEndOfLine = pszData;

			// Strip spaces from the end of the line...
			while (--pszEndOfLine >= pszStartOfLine && *pszEndOfLine == TEXT(' '))
				*pszEndOfLine = 0;

			// ...and from the start of the line
			while (*pszStartOfLine == TEXT(' '))
				++pszStartOfLine;

			// Skip past this line's terminator; point at the remaining data
			++pszData;
		}

		// Step 2a: Parse the line as SFV
		if (bReverseFormat)
		{
			pszEndOfLine -= 7;

			if (pszEndOfLine > pszStartOfLine && ValidateHexSequence(pszEndOfLine, 8))
			{
				pszChecksum = pszEndOfLine;

				// Trim spaces between the checksum and the file name
				while (--pszEndOfLine >= pszStartOfLine && *pszEndOfLine == TEXT(' '))
					*pszEndOfLine = 0;

				// Lines that begin with ';' are comments in SFV
				if (*pszStartOfLine && *pszStartOfLine != TEXT(';'))
					pszFileName = pszStartOfLine;
			}
		}

		// Step 2b: All other file formats
		else
		{
			// If we do not know the type yet, make a stab at detecting it
			if (phvctx->whctx.flags == 0)
			{
				if (ValidateHexSequence(pszStartOfLine, 8))
				{
					cchChecksum = 8;
					phvctx->whctx.flags = WHEX_ALL32;  // WHEX_CHECKCRC32
				}
				else if (ValidateHexSequence(pszStartOfLine, 32))
				{
					cchChecksum = 32;
					phvctx->whctx.flags = WHEX_ALL128;  // WHEX_CHECKMD4 | WHEX_CHECKMD5

					// Disambiguate from the filename, if possible
					if (StrStrI(phvctx->pszPath, TEXT("MD5")))
						phvctx->whctx.flags = WHEX_CHECKMD5;
					else if (StrStrI(phvctx->pszPath, TEXT("MD4")))
						phvctx->whctx.flags = WHEX_CHECKMD4;
				}
				else if (ValidateHexSequence(pszStartOfLine, 40))
				{
					cchChecksum = 40;
					phvctx->whctx.flags = WHEX_ALL160;  // WHEX_CHECKSHA1
				}
			}

			// Parse the line
			if ( phvctx->whctx.flags && pszEndOfLine > pszStartOfLine + cchChecksum &&
			     ValidateHexSequence(pszStartOfLine, cchChecksum) )
			{
				pszChecksum = pszStartOfLine;
				pszStartOfLine += cchChecksum + 1;

				// Skip over spaces between the checksum and filename
				while (*pszStartOfLine == TEXT(' '))
					++pszStartOfLine;

				if (*pszStartOfLine)
					pszFileName = pszStartOfLine;
			}
		}

		// Step 3: Do something useful with the results
		if (pszFileName && (cchPath = (INT16)(pszEndOfLine + 2 - pszFileName)) > 1)
		{
			// Since pszEndOfLine points to the character BEFORE the terminator,
			// cchLine == 1 + pszEnd - pszStart, and then +1 for the NULL
			// terminator means that we need to add 2 TCHARs to the length

			// By treating cchPath as INT16 and checking the sign, we ensure
			// that the path does not exceed 32K.

			// Create the new data block
			PHASHVERIFYITEM pItem = SLAddItem(phvctx->hList, NULL, sizeof(HASHVERIFYITEM));

			// Abort if we are out of memory
			if (!pItem) break;

			pItem->filesize.ui64 = -1;
			pItem->filesize.sz[0] = 0;
			pItem->pszDisplayName = pszFileName;
			pItem->pszExpected = pszChecksum;
			pItem->cchDisplayName = cchPath;
			pItem->uStatusID = HV_STATUS_NULL;
			pItem->szActual[0] = 0;

			++phvctx->cTotal;

		} // If the current line was found to be valid

	} // Loop until there are no lines left

	// Build the index
	if ( phvctx->cTotal && (phvctx->index =
	     SLSetContextSize(phvctx->hList, phvctx->cTotal * sizeof(PHVITEM))) )
	{
		SLBuildIndex(phvctx->hList, phvctx->index);
	}
	else
	{
		phvctx->cTotal = 0;
	}
}