コード例 #1
0
ファイル: HashCheck.cpp プロジェクト: gurnec/HashCheck
BOOL WINAPI InstallFile( LPCTSTR lpszSource, LPTSTR lpszDest, LPTSTR lpszDestAppend )
{
	static const TCHAR szShellExt[] = TEXT("ShellExt");
	static const TCHAR szDestFile[] = TEXT("\\") TEXT(HASHCHECK_FILENAME_STR);

	SSStaticCpy(lpszDestAppend, szShellExt);
	lpszDestAppend += countof(szShellExt) - 1;

	// Create directory if necessary
	if (! PathFileExists(lpszDest))
		CreateDirectory(lpszDest, NULL);

	SSStaticCpy(lpszDestAppend, szDestFile);
	lpszDestAppend += countof(szDestFile) - 1;

	// No need to copy if the source and destination are the same
	if (StrCmpI(lpszSource, lpszDest) == 0)
		return(TRUE);

	// If the destination file does not already exist, just copy
	if (! PathFileExists(lpszDest))
		return(CopyFile(lpszSource, lpszDest, FALSE));

	// If destination file exists and cannot be overwritten
	TCHAR szTemp[MAX_PATH + 0x20];
	SIZE_T cbDest = BYTEDIFF(lpszDestAppend, lpszDest);
	LPTSTR lpszTempAppend = (LPTSTR)BYTEADD(szTemp, cbDest);

	StringCbCopy(szTemp, sizeof(szTemp), lpszDest);
	*lpszTempAppend++ = TEXT('.');
	SSCpy2Ch(lpszTempAppend, 0, 0);

	for (TCHAR ch = TEXT('0'); ch <= TEXT('9'); ++ch)
	{
		if (CopyFile(lpszSource, lpszDest, FALSE))
			return(TRUE);

		*lpszTempAppend = ch;

		if (MoveFileEx(lpszDest, szTemp, MOVEFILE_REPLACE_EXISTING))
			MoveFileEx(szTemp, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
	}

	return(FALSE);
}
コード例 #2
0
ファイル: HashCheck.cpp プロジェクト: gurnec/HashCheck
HRESULT Uninstall( )
{
	HRESULT hr = S_OK;

	TCHAR szCurrentDllPath[MAX_PATH << 1];
	TCHAR szTemp[MAX_PATH << 1];

	LPTSTR lpszFileToDelete = szCurrentDllPath;
	LPTSTR lpszTempAppend = szTemp + GetModuleFileName(g_hModThisDll, szTemp, countof(szTemp));

    StringCbCopy(szCurrentDllPath, sizeof(szCurrentDllPath), szTemp);

#ifdef _WIN64
    // If this 64-bit dll was installed to the default location,
    // uninstall the 32-bit dll if it exists in its default location

    TCHAR lpszDefInstallPath[MAX_PATH + 0x20];
    UINT uSize = GetSystemDirectory(lpszDefInstallPath, MAX_PATH);

    if (uSize && uSize < MAX_PATH)
    {
        LPTSTR lpszPathAppend = lpszDefInstallPath + uSize;

        if (*(lpszPathAppend - 1) != TEXT('\\'))
            *lpszPathAppend++ = TEXT('\\');

        static const TCHAR szFolderAndFilename[] = TEXT("ShellExt") TEXT("\\") TEXT(HASHCHECK_FILENAME_STR);
        SSStaticCpy(lpszPathAppend, szFolderAndFilename);

        // If this 64-bit dll was installed to the default location
        if (StrCmpI(szCurrentDllPath, lpszDefInstallPath) == 0)
        {
            TCHAR lpszSystemWow64[MAX_PATH + 0x20];
            uSize = GetSystemWow64Directory(lpszSystemWow64, MAX_PATH);

            if (uSize && uSize < MAX_PATH)
            {
                LPTSTR lpszSystemWow64Append = lpszSystemWow64 + uSize;

                if (*(lpszSystemWow64Append - 1) != TEXT('\\'))
                    SSCpy2Ch(lpszSystemWow64Append++, TEXT('\\'), 0);

                StringCbCopyEx(lpszDefInstallPath, sizeof(lpszDefInstallPath), lpszSystemWow64, &lpszPathAppend, NULL, 0);

                SSStaticCpy(lpszPathAppend, szFolderAndFilename);

                // If the 32-bit dll exists in its default location
                if (PathFileExists(lpszDefInstallPath))
                {
                    static const TCHAR szRegsvr32[] = TEXT("regsvr32.exe");
                    SSStaticCpy(lpszSystemWow64Append, szRegsvr32);
                    // the lpszSystemWow64 buffer now contains the full regsvr32.exe path

                    TCHAR lpszCommandLine[MAX_PATH + 0x20];
                    LPTSTR lpszCommandLineAppend;
                    
                    static const TCHAR szCommandOpts[] = TEXT("regsvr32.exe /u /i /n /s ");
                    lpszCommandLineAppend = SSStaticCpy(lpszCommandLine, szCommandOpts) - 1;

                    StringCbCopy(lpszCommandLineAppend, sizeof(lpszCommandLine)-sizeof(szCommandOpts), lpszDefInstallPath);

                    STARTUPINFO si;
                    memset(&si, 0, sizeof(si));
                    si.cb = sizeof(si);

                    PROCESS_INFORMATION pi;
                    memset(&pi, 0, sizeof(pi));

                    if (!CreateProcess(lpszSystemWow64, lpszCommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
                        return E_FAIL;

                    DWORD dwExit;
                    WaitForSingleObject(pi.hProcess, INFINITE);
                    GetExitCodeProcess(pi.hProcess, &dwExit);
                    CloseHandle(pi.hThread);
                    CloseHandle(pi.hProcess);

                    if (dwExit != 0)
                        return E_FAIL;
                }
            }
        }
    }
#endif

	// Rename the DLL prior to scheduling it for deletion
	*lpszTempAppend++ = TEXT('.');
	SSCpy2Ch(lpszTempAppend, 0, 0);

	for (TCHAR ch = TEXT('0'); ch <= TEXT('9'); ++ch)
	{
		*lpszTempAppend = ch;

		if (MoveFileEx(szCurrentDllPath, szTemp, MOVEFILE_REPLACE_EXISTING))
		{
			lpszFileToDelete = szTemp;
			break;
		}
	}

	// Schedule the DLL to be deleted at shutdown/reboot
	if (!MoveFileEx(lpszFileToDelete, NULL, MOVEFILE_DELAY_UNTIL_REBOOT)) hr = E_FAIL;

	// Unregister
	if (DllUnregisterServer() != S_OK) hr = E_FAIL;

	// Disassociate file extensions; see the comment in DllUnregisterServer for
	// why this step is skipped for Wow64 processes
	if (!Wow64CheckProcess())
	{
		for (UINT i = 0; i < countof(g_szHashExtsTab); ++i)
		{
			HKEY hKey;

			if (hKey = RegOpen(HKEY_CLASSES_ROOT, g_szHashExtsTab[i], NULL, FALSE))
			{
                RegGetSZ(hKey, NULL, szTemp, sizeof(szTemp));
                if (_tcscmp(szTemp, PROGID_STR_HashCheck) == 0)
                    RegDeleteValue(hKey, NULL);
                RegCloseKey(hKey);
			}
		}
	}

	// We don't need the uninstall strings any more...
	RegDelete(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\%s"), CLSNAME_STR_HashCheck);

	return(hr);
}
コード例 #3
0
ファイル: HashCalc.c プロジェクト: x64ports/kliu-code
BOOL WINAPI HashCalcWriteResult( PHASHCALCCONTEXT phcctx, PHASHCALCITEM pItem )
{
	PCTSTR pszHash;
	PVOID pvLine;
	INT cchLine, cbLine;  // Length of line, in TCHARs or BYTEs, EXCLUDING the terminator

	if (!pItem->bValid)
		return(FALSE);

	// Set szFormat is necessary
	if (phcctx->szFormat[0] == 0)
	{
		// Did I ever mention that I hate SFV?
		// The reason we tracked cchMax was because of this idiotic format
		if (phcctx->ofn.nFilterIndex == 1)
		{
			wnsprintf(
				phcctx->szFormat,
				countof(phcctx->szFormat),
				TEXT("%%-%ds %%s\r\n"),
				phcctx->cchMax - phcctx->cchAdjusted
			);
		}
		else
		{
			SSStaticCpy(phcctx->szFormat, TEXT("%s *%s\r\n"));
		}
	}

	// Translate the filter index to a hash
	switch (phcctx->ofn.nFilterIndex)
	{
		case 1: pszHash = pItem->results.szHexCRC32; break;
		case 2: pszHash = pItem->results.szHexMD4;   break;
		case 3: pszHash = pItem->results.szHexMD5;   break;
		case 4: pszHash = pItem->results.szHexSHA1;  break;
	}

	// Format the line
	#define HashCalcFormat(a, b) wnsprintf(phcctx->scratch.sz, MAX_PATH_BUFFER, phcctx->szFormat, a, b)
	cchLine = (phcctx->ofn.nFilterIndex == 1) ?
		HashCalcFormat(pItem->szPath + phcctx->cchAdjusted, pszHash) : // SFV
		HashCalcFormat(pszHash, pItem->szPath + phcctx->cchAdjusted);  // everything else
	#undef HashCalcFormat

	if (cchLine > 0)
	{
		// Convert to the correct encoding
		switch (phcctx->opt.dwSaveEncoding)
		{
			case 0:
			{
				// UTF-8
				#ifdef UNICODE
				cbLine = WStrToUTF8(phcctx->scratch.szW, phcctx->scratch.szA, countof(phcctx->scratch.szA)) - 1;
				#else
				         AStrToWStr(phcctx->scratch.szA, phcctx->scratch.szW, countof(phcctx->scratch.szW));
				cbLine = WStrToUTF8(phcctx->scratch.szW, phcctx->scratch.szA, countof(phcctx->scratch.szA)) - 1;
				#endif

				pvLine = phcctx->scratch.szA;
				break;
			}

			case 1:
			{
				// UTF-16
				#ifndef UNICODE
				cchLine = AStrToWStr(phcctx->scratch.szA, phcctx->scratch.szW, countof(phcctx->scratch.szW)) - 1;
				#endif

				cbLine = cchLine * sizeof(WCHAR);
				pvLine = phcctx->scratch.szW;
				break;
			}

			case 2:
			{
				// ANSI
				#ifdef UNICODE
				cbLine = WStrToAStr(phcctx->scratch.szW, phcctx->scratch.szA, countof(phcctx->scratch.szA)) - 1;
				#else
				cbLine = cchLine;
				#endif

				pvLine = phcctx->scratch.szA;
				break;
			}
		}

		if (cbLine > 0)
		{
			INT cbWritten;
			WriteFile(phcctx->hFileOut, pvLine, cbLine, &cbWritten, NULL);
			if (cbLine != cbWritten) return(FALSE);
		}
		else return(FALSE);
	}
	else return(FALSE);

	return(TRUE);
}
コード例 #4
0
ファイル: HashCheck.cpp プロジェクト: gurnec/HashCheck
HRESULT Install( BOOL bRegisterUninstaller, BOOL bCopyFile )
{
	TCHAR szCurrentDllPath[MAX_PATH << 1];
	GetModuleFileName(g_hModThisDll, szCurrentDllPath, countof(szCurrentDllPath));

	TCHAR szSysDir[MAX_PATH + 0x20];
	UINT uSize = GetSystemDirectory(szSysDir, MAX_PATH);

	if (uSize && uSize < MAX_PATH)
	{
		LPTSTR lpszPath = szSysDir;
		LPTSTR lpszPathAppend = lpszPath + uSize;

		if (*(lpszPathAppend - 1) != TEXT('\\'))
			*lpszPathAppend++ = TEXT('\\');

		LPTSTR lpszTargetPath = (bCopyFile) ? lpszPath : szCurrentDllPath;

		if ( (!bCopyFile || InstallFile(szCurrentDllPath, lpszTargetPath, lpszPathAppend)) &&
		     DllRegisterServerEx(lpszTargetPath) == S_OK )
		{
			HKEY hKey, hKeySub;

			// Associate file extensions
			for (UINT i = 0; i < countof(g_szHashExtsTab); ++i)
			{
				if (hKey = RegOpen(HKEY_CLASSES_ROOT, g_szHashExtsTab[i], NULL, TRUE))
				{
					RegSetSZ(hKey, NULL, PROGID_STR_HashCheck);
					RegSetSZ(hKey, TEXT("PerceivedType"), TEXT("text"));

					if (hKeySub = RegOpen(hKey, TEXT("PersistentHandler"), NULL, TRUE))
					{
						RegSetSZ(hKeySub, NULL, TEXT("{5e941d80-bf96-11cd-b579-08002b30bfeb}"));
						RegCloseKey(hKeySub);
					}

					RegCloseKey(hKey);
				}
			}

            // Disassociate former file extensions; see the comment in DllUnregisterServer for
            // why this step is skipped for Wow64 processes
            if (!Wow64CheckProcess())
            {
                for (UINT i = 0; i < countof(szFormerHashExtsTab); ++i)
                {
                    HKEY hKey;

                    if (hKey = RegOpen(HKEY_CLASSES_ROOT, szFormerHashExtsTab[i], NULL, FALSE))
                    {
                        TCHAR szTemp[countof(PROGID_STR_HashCheck)];
                        RegGetSZ(hKey, NULL, szTemp, sizeof(szTemp));
                        if (_tcscmp(szTemp, PROGID_STR_HashCheck) == 0)
                            RegDeleteValue(hKey, NULL);
                        RegCloseKey(hKey);
                    }
                }
            }

			// Uninstaller entries
			RegDelete(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\%s"), CLSNAME_STR_HashCheck);

			if (bRegisterUninstaller && (hKey = RegOpen(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\%s"), CLSNAME_STR_HashCheck, TRUE)))
			{
				TCHAR szUninstall[MAX_PATH << 1];
				StringCchPrintf(szUninstall, countof(szUninstall), TEXT("regsvr32.exe /u /i /n \"%s\""), lpszTargetPath);

				static const TCHAR szURLFull[] = TEXT("https://github.com/gurnec/HashCheck/issues");
				TCHAR szURLBase[countof(szURLFull)];
				SSStaticCpy(szURLBase, szURLFull);
				szURLBase[35] = 0; // strlen("https://github.com/gurnec/HashCheck")

				RegSetSZ(hKey, TEXT("DisplayIcon"), lpszTargetPath);
				RegSetSZ(hKey, TEXT("DisplayName"), TEXT(HASHCHECK_NAME_STR));
				RegSetSZ(hKey, TEXT("DisplayVersion"), TEXT(HASHCHECK_VERSION_STR));
				RegSetDW(hKey, TEXT("EstimatedSize"), 1073);
				RegSetSZ(hKey, TEXT("HelpLink"), szURLFull);
				RegSetDW(hKey, TEXT("NoModify"), 1);
				RegSetDW(hKey, TEXT("NoRepair"), 1);
				RegSetSZ(hKey, TEXT("UninstallString"), szUninstall);
				RegSetSZ(hKey, TEXT("URLInfoAbout"), szURLBase);
				RegSetSZ(hKey, TEXT("URLUpdateInfo"), TEXT("https://github.com/gurnec/HashCheck/releases/latest"));
				RegCloseKey(hKey);
			}

			return(S_OK);

		} // if copied & registered

	} // if valid sysdir

	return(E_FAIL);
}
コード例 #5
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);
}