Exemple #1
0
/// Saves given path to registry for ShellExtension, and Context Menu settings
void PropShell::SaveMergePath()
{
	TCHAR temp[MAX_PATH] = {0};
	LONG retVal = 0;
	GetModuleFileName(AfxGetInstanceHandle(), temp, MAX_PATH);

	CRegKeyEx reg;
	retVal = reg.Open(HKEY_CURRENT_USER, f_RegDir);
	if (retVal != ERROR_SUCCESS)
	{
		CString msg;
		msg.Format(_T("Failed to open registry key HKCU/%s:\n\t%d : %s"),
			f_RegDir, retVal, GetSysError(retVal).c_str());
		LogErrorString(msg);
		return;
	}

	// Save path to WinMerge(U).exe
	retVal = reg.WriteString(f_RegValuePath, temp);
	if (retVal != ERROR_SUCCESS)
	{
		CString msg;
		msg.Format(_T("Failed to set registry value %s:\n\t%d : %s"),
			f_RegValuePath, retVal, GetSysError(retVal).c_str());
		LogErrorString(msg);
	}

	// Determine bitmask for shell extension
	DWORD dwContextEnabled = reg.ReadDword(f_RegValueEnabled, 0);
	if (m_bContextAdded)
		dwContextEnabled |= CONTEXT_F_ENABLED;
	else
		dwContextEnabled &= ~CONTEXT_F_ENABLED;

	if (m_bContextAdvanced)
		dwContextEnabled |= CONTEXT_F_ADVANCED;
	else
		dwContextEnabled &= ~CONTEXT_F_ADVANCED;

	if (m_bContextSubfolders)
		dwContextEnabled |= CONTEXT_F_SUBFOLDERS;
	else
		dwContextEnabled &= ~CONTEXT_F_SUBFOLDERS;

	retVal = reg.WriteDword(f_RegValueEnabled, dwContextEnabled);
	if (retVal != ERROR_SUCCESS)
	{
		CString msg;
		msg.Format(_T("Failed to set registry value %s to %d:\n\t%d : %s"),
			f_RegValueEnabled, dwContextEnabled, retVal, GetSysError(retVal).c_str());
		LogErrorString(msg);
	}
}
Exemple #2
0
/// Get registry values for ShellExtension
void PropShell::GetContextRegValues()
{
	CRegKeyEx reg;
	LONG retVal = 0;
	retVal = reg.Open(HKEY_CURRENT_USER, f_RegDir);
	if (retVal != ERROR_SUCCESS)
	{
		CString msg;
		msg.Format(_T("Failed to open registry key HKCU/%s:\n\t%d : %s"),
			f_RegDir, retVal, GetSysError(retVal).c_str());
		LogErrorString(msg);
		return;
	}

	// Read bitmask for shell extension settings
	DWORD dwContextEnabled = reg.ReadDword(f_RegValueEnabled, 0);

	if (dwContextEnabled & CONTEXT_F_ENABLED)
		m_bContextAdded = TRUE;

	if (dwContextEnabled & CONTEXT_F_ADVANCED)
		m_bContextAdvanced = TRUE;

	if (dwContextEnabled & CONTEXT_F_SUBFOLDERS)
		m_bContextSubfolders = TRUE;
}
Exemple #3
0
/** 
 * @brief Get folder for temporary files.
 * This function returns system temp folder.
 * @param [out] pnerr Error code if erorr happened.
 * @return Temp path, or empty string if error happened.
 * @note Temp path is cached after first call.
 * @todo Should we return NULL for error case?
 */
LPCTSTR env_GetTempPath(int * pnerr)
{
	if (strTempPath.empty())
	{
		if (GetOptionsMgr()->GetBool(OPT_USE_SYSTEM_TEMP_PATH))
		{
			int cchTempPath = GetTempPath(0, 0);
			strTempPath.resize(cchTempPath - 1);
			if (!GetTempPath(cchTempPath, &*strTempPath.begin()))
			{
				int err = GetLastError();
				if (pnerr)
					*pnerr = err;
#ifdef _DEBUG
				String sysErr = GetSysError(err); // for debugging
#endif
				return strTempPath.c_str(); // empty
			}
		}
		else
		{
			strTempPath = GetOptionsMgr()->GetString(OPT_CUSTOM_TEMP_PATH);
			if (!paths_EndsWithSlash(strTempPath.c_str()))
				strTempPath += '\\';
		}
		strTempPath = paths_GetLongPath(strTempPath.c_str());
	}
	return strTempPath.c_str();
}
Exemple #4
0
/**
 * @brief Get the error string.
 * @return Error string.
 */
String UniFile::UniError::GetError() const
{
	String sError;
	if (apiname.empty())
		sError = desc;
	else
		sError = GetSysError(syserrnum);
	return sError;
}
// for OLECHAR files, transform to UTF8 for diffutils
// TODO : convert Ansi to UTF8 if other file is unicode or uses a different codepage
BOOL FileTransform_UCS2ToUTF8(String & filepath, BOOL bMayOverwrite)
{
	String tempDir = env_GetTempPath();
	if (tempDir.empty())
		return FALSE;
	String tempFilepath = env_GetTempFileName(tempDir.c_str(), _T("_WM"));
	if (tempFilepath.empty())
		return FALSE;

	// TODO : is it better with the BOM or without (just change the last argument)
	int nFileChanged = 0;
	BOOL bSuccess = OlecharToUTF8(filepath.c_str(), tempFilepath.c_str(), nFileChanged, FALSE); 
	if (!bSuccess)
		return FALSE;

	if (nFileChanged)
	{
		// we do not overwrite so we delete the old file
		if (bMayOverwrite)
		{
			if (!::DeleteFile(filepath.c_str()))
			{
				LogErrorString(Fmt(_T("DeleteFile(%s) failed: %s"),
					filepath.c_str(), GetSysError(GetLastError()).c_str()));
			}
		}
		// and change the filepath if everything works
		filepath = tempFilepath;
	}
	else
	{
		if (!::DeleteFile(tempFilepath.c_str()))
		{
			LogErrorString(Fmt(_T("DeleteFile(%s) failed: %s"),
				tempFilepath.c_str(), GetSysError(GetLastError()).c_str()));
		}
	}

	return TRUE;
}
BOOL FileTransform_NormalizeUnicode(String & filepath, BOOL bMayOverwrite)
{
	String tempDir = env_GetTempPath();
	if (tempDir.empty())
		return FALSE;
	String tempFilepath = env_GetTempFileName(tempDir.c_str(), _T("_WM"));
	if (tempFilepath.empty())
		return FALSE;

	int nFileChanged = 0;
	BOOL bSuccess = UnicodeFileToOlechar(filepath.c_str(), tempFilepath.c_str(), nFileChanged); 
	if (!bSuccess)
		return FALSE;

	if (nFileChanged)
	{
		// we do not overwrite so we delete the old file
		if (bMayOverwrite)
		{
			if (!::DeleteFile(filepath.c_str()))
			{
				LogErrorString(Fmt(_T("DeleteFile(%s) failed: %s"),
					filepath.c_str(), GetSysError(GetLastError()).c_str()));
			}
		}
		// and change the filepath if everything works
		filepath = tempFilepath;
	}
	else
	{
		if (!::DeleteFile(tempFilepath.c_str()))
		{
			LogErrorString(Fmt(_T("DeleteFile(%s) failed: %s"),
				tempFilepath.c_str(), GetSysError(GetLastError()).c_str()));
		}
	}


	return TRUE;
}
Exemple #7
0
/**
 * @brief Get filename for temporary file.
 * @param [in] lpPathName Temporary file folder.
 * @param [in] lpPrefixString Prefix to use for filename.
 * @param [out] pnerr Error code if error happened.
 * @return Full path for temporary file or empty string if error happened.
 */
String env_GetTempFileName(LPCTSTR lpPathName, LPCTSTR lpPrefixString, int * pnerr)
{
	TCHAR buffer[MAX_PATH] = {0};
	if (_tcslen(lpPathName) > MAX_PATH-14)
		return _T(""); // failure
	int rtn = GetTempFileName(lpPathName, lpPrefixString, 0, buffer);
	if (!rtn)
	{
		int err = GetLastError();
		if (pnerr)
			*pnerr = err;
#ifdef _DEBUG
		String sysErr = GetSysError(err); // for debugging
#endif
		return _T("");
	}
	return buffer;
}
Exemple #8
0
/**
 * @brief Open file as memory-mapped file.
 * @param [in,out] fileData Memory-mapped file's info.
 * @return TRUE if opening succeeded, FALSE otherwise.
 */
BOOL files_openFileMapped(MAPPEDFILEDATA *fileData)
{
	DWORD dwProtectFlag = 0;
	DWORD dwMapAccess = 0;
	DWORD dwOpenAccess = 0;
	DWORD dwFileSizeHigh = 0;
	DWORD dwSharedMode = FILE_SHARE_READ;
	HANDLE hTemplateFile = NULL; // for creating new file
	BOOL bSuccess = TRUE;

	if (fileData->bWritable)
	{
		dwProtectFlag = PAGE_READWRITE;
		dwMapAccess = FILE_MAP_ALL_ACCESS;
		dwOpenAccess = GENERIC_READ | GENERIC_WRITE;
	}
	else
	{
		dwProtectFlag = PAGE_READONLY;
		dwMapAccess = FILE_MAP_READ;
		dwOpenAccess = GENERIC_READ;
	}

	fileData->hFile = CreateFile(fileData->fileName,
		dwOpenAccess, dwSharedMode, NULL, fileData->dwOpenFlags,
		FILE_ATTRIBUTE_NORMAL, hTemplateFile);

	if (fileData->hFile == INVALID_HANDLE_VALUE)
	{
		bSuccess = FALSE;
		LogErrorString(Fmt(_T("CreateFile(%s) failed in files_openFileMapped: %s")
			, fileData->fileName, GetSysError(GetLastError()).c_str()));
	}
	else
	{
		if (fileData->dwSize == 0)
		{
			fileData->dwSize = GetFileSize(fileData->hFile,
				 &dwFileSizeHigh);
			if (fileData->dwSize == 0xFFFFFFFF || dwFileSizeHigh)
			{
				fileData->dwSize = 0;
				bSuccess = FALSE;
			}
		}
	}
		
	if (bSuccess)
	{
		if (fileData->dwSize == 0 && dwFileSizeHigh == 0)
			// Empty file (but should be accepted anyway)
			return bSuccess;

		fileData->hMapping = CreateFileMapping(fileData->hFile,
				NULL, dwProtectFlag, 0, fileData->dwSize, NULL);
		if (!fileData->hMapping)
		{
			bSuccess = FALSE;
			LogErrorString(Fmt(_T("CreateFileMapping(%s) failed: %s")
				, fileData->fileName, GetSysError(GetLastError()).c_str()));
		}
		else
		{
			fileData->pMapBase = MapViewOfFile(fileData->hMapping,
				dwMapAccess, 0, 0, 0);
			if (!fileData->pMapBase)
			{
				bSuccess = FALSE;
				LogErrorString(Fmt(_T("MapViewOfFile(%s) failed: %s")
					, fileData->fileName, GetSysError(GetLastError()).c_str()));
			}
		}
	}

	if (!bSuccess)
	{
		UnmapViewOfFile(fileData->pMapBase);
		fileData->pMapBase = NULL;
		CloseHandle(fileData->hMapping);
		fileData->hMapping = NULL;
		CloseHandle(fileData->hFile);
		fileData->hFile = NULL;
	}
	return bSuccess;
}
Exemple #9
0
/**
 * @brief Runs diff-engine.
 */
BOOL CDiffWrapper::RunFileDiff()
{
	String filepath1(m_s1File);
	String filepath2(m_s2File);
	replace_char(&*filepath1.begin(), '/', '\\');
	replace_char(&*filepath2.begin(), '/', '\\');

	BOOL bRet = TRUE;
	String strFile1Temp(filepath1);
	String strFile2Temp(filepath2);
	
	m_options.SetToDiffUtils();

	if (m_bUseDiffList)
		m_nDiffs = m_pDiffList->GetSize();

	if (m_bPluginsEnabled)
	{
		// Do the preprocessing now, overwrite the temp files
		// NOTE: FileTransform_UCS2ToUTF8() may create new temp
		// files and return new names, those created temp files
		// are deleted in end of function.
		if (m_infoPrediffer->bToBeScanned)
		{
			// this can only fail if the data can not be saved back (no more
			// place on disk ???) What to do then ??
			FileTransform_Prediffing(strFile1Temp, m_sToFindPrediffer.c_str(), m_infoPrediffer,
				m_bPathsAreTemp);
		}
		else
		{
			// This can fail if the prediffer has a problem
			if (FileTransform_Prediffing(strFile1Temp, *m_infoPrediffer,
				m_bPathsAreTemp) == FALSE)
			{
				// display a message box
				CString sError;
				LangFormatString2(sError, IDS_PREDIFFER_ERROR, strFile1Temp.c_str(),
					m_infoPrediffer->pluginName.c_str());
				AfxMessageBox(sError, MB_OK | MB_ICONSTOP);
				// don't use any more this prediffer
				m_infoPrediffer->bToBeScanned = FALSE;
				m_infoPrediffer->pluginName.erase();
			}
		}

		// We use the same plugin for both files, so it must be defined before
		// second file
		ASSERT(m_infoPrediffer->bToBeScanned == FALSE);
		if (FileTransform_Prediffing(strFile2Temp, *m_infoPrediffer,
			m_bPathsAreTemp) == FALSE)
		{
			// display a message box
			CString sError;
			LangFormatString2(sError, IDS_PREDIFFER_ERROR, strFile2Temp.c_str(),
				m_infoPrediffer->pluginName.c_str());
			AfxMessageBox(sError, MB_OK | MB_ICONSTOP);
			// don't use any more this prediffer
			m_infoPrediffer->bToBeScanned = FALSE;
			m_infoPrediffer->pluginName.erase();
		}
	}

	// Comparing UTF-8 files seems to require this conversion?
	// I'm still very confused about why, as what the functions
	// document doing is UCS2 to UTF-8 conversion, nothing else.
	// Something is wrong here. - Kimmo
	FileTransform_UCS2ToUTF8(strFile1Temp, m_bPathsAreTemp);
	FileTransform_UCS2ToUTF8(strFile2Temp, m_bPathsAreTemp);

	DiffFileData diffdata;
	diffdata.SetDisplayFilepaths(filepath1.c_str(), filepath2.c_str()); // store true names for diff utils patch file
	// This opens & fstats both files (if it succeeds)
	if (!diffdata.OpenFiles(strFile1Temp.c_str(), strFile2Temp.c_str()))
	{
		return FALSE;
	}

	// Compare the files, if no error was found.
	// Last param (bin_file) is NULL since we don't
	// (yet) need info about binary sides.
	int bin_flag = 0;
	struct change *script = NULL;
	bRet = Diff2Files(&script, &diffdata, &bin_flag, NULL);

	// We don't anymore create diff-files for every rescan.
	// User can create patch-file whenever one wants to.
	// We don't need to waste time. But lets keep this as
	// debugging aid. Sometimes it is very useful to see
	// what differences diff-engine sees!
#ifdef _DEBUG
	// throw the diff into a temp file
	String sTempPath = env_GetTempPath(); // get path to Temp folder
	String path = paths_ConcatPath(sTempPath, _T("Diff.txt"));

	outfile = _tfopen(path.c_str(), _T("w+"));
	if (outfile != NULL)
	{
		print_normal_script(script);
		fclose(outfile);
		outfile = NULL;
	}
#endif

	// First determine what happened during comparison
	// If there were errors or files were binaries, don't bother
	// creating diff-lists or patches
	
	// diff_2_files set bin_flag to -1 if different binary
	// diff_2_files set bin_flag to +1 if same binary
	if (bin_flag != 0)
	{
		m_status.bBinaries = TRUE;
		if (bin_flag == -1)
			m_status.bIdentical = FALSE;
		else
			m_status.bIdentical = TRUE;
	}
	else
	{ // text files according to diffutils, so change script exists
		m_status.bIdentical = (script == 0);
		m_status.bBinaries = FALSE;
	}
	file_data * inf = diffdata.m_inf;
	m_status.bLeftMissingNL = inf[0].missing_newline;
	m_status.bRightMissingNL = inf[1].missing_newline;


	// Create patch file
	if (!m_status.bBinaries && m_bCreatePatchFile)
	{
		WritePatchFile(script, &inf[0]);
	}
	
	// Go through diffs adding them to WinMerge's diff list
	// This is done on every WinMerge's doc rescan!
	if (!m_status.bBinaries && m_bUseDiffList)
	{
		LoadWinMergeDiffsFromDiffUtilsScript(script, diffdata.m_inf);
	}			

	FreeDiffUtilsScript(script);

	// Done with diffutils filedata
	diffdata.Close();

	if (m_bPluginsEnabled)
	{
		// Delete temp files transformation functions possibly created
		if (lstrcmpi(filepath1.c_str(), strFile1Temp.c_str()) != 0)
		{
			if (!::DeleteFile(strFile1Temp.c_str()))
			{
				LogErrorString(Fmt(_T("DeleteFile(%s) failed: %s"),
					strFile1Temp.c_str(), GetSysError(GetLastError()).c_str()));
			}
			strFile1Temp.erase();
		}
		if (lstrcmpi(filepath2.c_str(), strFile2Temp.c_str()) != 0)
		{
			if (!::DeleteFile(strFile2Temp.c_str()))
			{
				LogErrorString(Fmt(_T("DeleteFile(%s) failed: %s"),
					strFile2Temp.c_str(), GetSysError(GetLastError()).c_str()));
			}
			strFile2Temp.erase();
		}
	}
	return bRet;
}