コード例 #1
0
bool OverwriteDlg::_SetStaticText(Window &Wnd, CTSTRING &tsFileName) {

  bool r = false;
  FILESIZE fs;

  if (FileGetSize(tsFileName, fs)) {

    FILETIMES ft;

    if (FileGetTime(tsFileName, ft)) {

     /*
      * Set the text of the static control as follows:
      *
      * [size in bytes] [formatted size]
      * [created date]
      * [modified date]
      */
      TSTRING tsTemp;
      TSTRING tsFormatBytes = _GetNumberFormat(fs.ui64Bytes);                    

      sprintf(tsTemp, _T("%s Bytes (%s)\nCreated: %s\nModified: %s"),
              tsFormatBytes.c_str(), fs.tsStrFmt.c_str(),
              ft.tsLongCreated.c_str(), ft.tsLongModified.c_str());

      Wnd.SetWindowText(tsTemp);
      r = true;

    }

  }

  return r;
}
コード例 #2
0
ファイル: Path.cpp プロジェクト: pedia/raidget
bool FileCopy(const char *oldname, const char *newname)
{
#if defined(PLATFORM_WIN32)
	if(IsWinNT())
		return UnicodeWin32().CopyFileW(ToSystemCharsetW(oldname), ToSystemCharsetW(newname), false);
	else
		return CopyFile(ToSystemCharset(oldname), ToSystemCharset(newname), false);
#elif defined(PLATFORM_POSIX)
	FileIn fi(oldname);
	if(!fi.IsOpen())
		return false;
	FileOut fo(newname);
	if(!fo.IsOpen())
		return false;
	CopyStream(fo, fi, fi.GetLeft());
	fi.Close();
	fo.Close();
	if(fo.IsError())
	{
		unlink(newname);
		return false;
	}
	FileSetTime(newname, FileGetTime(oldname));
	return true;
#else
	#error
#endif//PLATFORM
}
コード例 #3
0
ファイル: TopicBase.cpp プロジェクト: dreamsxin/ultimatepp
void SyncTopicFile(const RichText& text, const String& link, const String& path, const String& title)
{
	LLOG("Scanning topic " << link);
	LTIMING("Scanning topic");
	
	ClearLinkRef(link);
	
	ScanTopicIterator sti;
	sti.link = link;
	text.Iterate(sti);
	
	TopicInfo& ti = topic_info().GetPut(link);
	ti.title = title;
	ti.path = path;
	ti.time = FileGetTime(path);
	ti.words = sti.words.PickKeys();
	
	FileOut out(TopicCacheName(path));
	out << tdx_version << "\n";
	out << title << '\n';
	for(int i = 0; i < sti.ref.GetCount(); i++)
		out << sti.ref[i] << '\n';
	out << '\n';
	const Index<String>& ws = TopicWords();
	for(int i = 0; i < ti.words.GetCount(); i++)
		out << ws[ti.words[i]] << '\n';
}
コード例 #4
0
ファイル: Png.cpp プロジェクト: dreamsxin/ultimatepp
void IdePngDes::Load(const char *_filename)
{
	Clear();
	filename = _filename;
	filetime = FileGetTime(filename);
	Image m = StreamRaster::LoadFileAny(filename);	
	AddImage(filename, m, false);
	SingleMode();
}
コード例 #5
0
ファイル: ppfile.cpp プロジェクト: AbdelghaniDr/mirror
Time GetFileTimeCached(const String& p)
{
	LTIMING("GetFileTimeCached");
	int q = sPathFileTime.Find(p);
	if(q >= 0)
		return sPathFileTime[q];
	Time m = FileGetTime(p);
	sPathFileTime.Put(p, m);
	return m;
}
コード例 #6
0
ファイル: TopicBase.cpp プロジェクト: dreamsxin/ultimatepp
void SyncTopicFile(const String& link)
{
	String path = GetTopicPath(link);
	LLOG("SyncTopicFile " << link << " path: " << path);
	TopicInfo& ti = topic_info().GetPut(link);
	Time tm = FileGetTime(path);
	if(ti.path == ":ide:" || ti.path == path && ti.time == tm)
		return;
	String fn = TopicCacheName(path);
	if(FileGetTime(fn) > tm) {
		LLOG("Loading topic from cache");
		ClearLinkRef(link);
		FileIn in(fn);
		LTIMING("Loading topic from cache");
		if(in) {
			String s = in.GetLine();
			if(s == tdx_version) {
				ti.title = in.GetLine();
				ti.words.Clear();
				ti.path = path;
				ti.time = tm;
				while(!in.IsEof()) {
					String x = in.GetLine();
					if(IsNull(x))
						break;
					AddLinkRef(link, x);
				}
				while(!in.IsEof()) {
					String x = in.GetLine();
					if(IsNull(x))
						break;
					ti.words.Add(TopicWordIndex(x));
				}
				Sort(ti.words);
				return;
			}
		}
	}
	Topic tp = ReadTopic(LoadFile(path));
	SyncTopicFile(ParseQTF(tp.text), link, path, tp.title);
}
コード例 #7
0
ファイル: UppWspc.cpp プロジェクト: AbdelghaniDr/mirror
void WorkspaceWork::LoadActualPackage()
{
	Time utime = FileGetTime(ConfigFile("version"));
	filelist.Clear();
	fileindex.Clear();
	bool open = true;
	Time tm = GetSysTime();
	for(int i = 0; i < actual.file.GetCount(); i++) {
		Package::File& f = actual.file[i];
		if(f.separator) {
			open = closed.Find(Sepfo(actualpackage, f)) < 0;
			filelist.Add(f, open ? IdeImg::SeparatorClose() : IdeImg::SeparatorOpen(),
			             ListFont().Bold(), open ? SColorMark : SColorText, true, 0, Null);
			fileindex.Add(i);
		}
		else
		if(open) {
			Color uln = Null;
			String p = SourcePath(GetActivePackage(), f);
			if(showtime) {
				FindFile ff(p);
				if(ff) {
					Time ftm = Time(ff.GetLastWriteTime());
					if(ftm > utime) {
						int64 t = tm - ftm;
						if(t < 24 * 3600)
							uln = SColorMark;
						else
						if(t < 32 * 24 * 3600)
							uln = SColorDisabled;
					}
				}
			}
			Image m = IdeFileImage(f, f.optimize_speed, false, f.pch);
			if(GetFileExt(p) == ".tpp" && IsFolder(p)) {
				if(FileExists(AppendFileName(p, "all.i")))
					m = TopicImg::IGroup();
				else
					m = TopicImg::Group();
			}
		#ifdef PLATFORM_WIN32
			p = ToLower(p);
		#endif
			if(errorfiles.Find(p) >= 0) {
				m = ImageOverRed(m);
				uln = LtRed;
			}
			filelist.Add(f, m, ListFont(), SColorText, false, 0,
			             Null, SColorMark, Null, Null, Null, uln);
			fileindex.Add(i);
		}
	}
}
コード例 #8
0
ファイル: IconDes.cpp プロジェクト: AbdelghaniDr/mirror
bool IdeIconDes::Load(const char *_filename)
{
	Clear();
	filename = _filename;
	filetime = FileGetTime(filename);
	Array<ImlImage> m;
	int f;
	if(!LoadIml(LoadFile(filename), m, f))
		return false;
	format = f;
	for(int i = 0; i < m.GetCount(); i++)
		AddImage(m[i].name, m[i].image, m[i].exp);
	return true;
}
コード例 #9
0
ファイル: idetool.cpp プロジェクト: guowei8412/upp-mirror
void Ide::Statistics()
{
	Vector< ArrayMap<String, FileStat> > stat;
	Progress pi;
	const Workspace& wspc = IdeWorkspace();
	pi.SetTotal(wspc.GetCount());
	Date now = GetSysDate();
	for(int i = 0; i < wspc.GetCount(); i++) {
		const Package& pk = wspc.GetPackage(i);
		String n = wspc[i];
		pi.SetText(n);
		if(pi.StepCanceled()) return;
		ArrayMap<String, FileStat>& pfs = stat.Add();
		for(int i = 0; i < pk.GetCount(); i++)
			if(!pk[i].separator) {
				String file = SourcePath(n, pk[i]);
				if(FileExists(file)) {
					FileStat& fs = pfs.GetAdd(GetFileExt(file));
					int d = minmax(now - FileGetTime(file), 0, 9999);
					fs.oldest = max(d, fs.oldest);
					fs.newest = min(d, fs.newest);
					String data = LoadFile(file);
					for(const char *s = data; *s; s++)
						if(*s == '\n')
							fs.lines++;
					fs.len += data.GetCount();
					fs.days += d;
					fs.count++;
				}
			}
	}
	String qtf = "[1 ";
	ArrayMap<String, FileStat> all;
	String tab = "{{45:20:25:20:35:30:30:30:30@L [* ";
	String hdr = "]:: [= Files:: Lines:: - avg.:: Length:: - avg.:: Oldest:: Newest:: Avg. age]";
	for(int i = 0; i < wspc.GetCount(); i++) {
		qtf << tab << DeQtf(wspc[i]) << hdr;
		sPut(qtf, stat[i], all);
	}

	qtf << tab << "All packages" << hdr;
	sPut(qtf, all, all);

	WithStatLayout<TopWindow> dlg;
	CtrlLayoutOK(dlg, "Statistics");
	dlg.stat = qtf;
	dlg.Sizeable().Zoomable();
	dlg.Run();
}
コード例 #10
0
ファイル: ide.cpp プロジェクト: kolyden/mirror
const Workspace& Ide::IdeWorkspace() const
{
	static Workspace wspc;
	static String _main;
	if(main != _main || wspc.GetCount() == 0) {
		wspc.Scan(main);
		_main = main;
	}
	else {
		for(int i = 0; i < wspc.GetCount(); i++)
			if(wspc.GetPackage(i).time != FileGetTime(PackagePath(wspc[i]))) {
				wspc.Scan(main);
				break;
			}
	}
	return wspc;
}
コード例 #11
0
ファイル: IconDes.cpp プロジェクト: AbdelghaniDr/mirror
void IdeIconDes::Save()
{
	if(format == 1) {
		for(int i = 0; i < GetCount(); i++) {
			Image m = GetImage(i);
			Point p = m.Get2ndSpot();
			if(m.GetKind() == IMAGE_ALPHA || p.x || p.y) {
				if(PromptYesNo("Legacy file format does not support images "
				               "with full alpha channel or 2nd hotspot - "
				               "the information would be lost.&"
				               "Do you wish to convert the file to the new format?")) {
					format = 0;
				}
				break;
			}
		}
	}
	StoreToGlobal(*this, "icondes-ctrl");
	Array<ImlImage> m;
	VectorMap<Size, Image> exp;
	String folder = GetFileFolder(filename);
	for(int i = 0; i < GetCount(); i++) {
		ImlImage& c = m.Add();
		c.name = GetName(i);
		c.image = GetImage(i);
		c.exp = GetExport(i);
		if(c.exp) {
			Size sz = c.image.GetSize();
			exp.GetAdd(sz) = c.image;
			PNGEncoder png;
			SaveChangedFile(AppendFileName(folder, String().Cat() << "icon" << sz.cx << 'x' << sz.cy << ".png"),
			                png.SaveString(c.image));
		}
	}
	String d = SaveIml(m, format);
	if(!SaveChangedFileFinish(filename, d))
		return;
	filetime = FileGetTime(filename);
	if(exp.GetCount())
		SaveChangedFile(AppendFileName(folder, "icon.ico"), WriteIcon(exp.GetValues()));
}
コード例 #12
0
ファイル: Config.cpp プロジェクト: AbdelghaniDr/mirror
void Ide::LoadConfig()
{
	if(!LoadFromFile(*this) && GetIniKey("DebugClipboard") == "1") {
		Exclamation("LoadConfig has failed!");
		if(!LoadFromFile(*this, ConfigFile() + ".bak")) {
			Exclamation("LoadConfig .bak has failed!");
			if(!LoadFromFile(*this, ConfigFile() + ".bak1"))
				Exclamation("LoadConfig .bak1 has failed!");
		}
	}
	RestoreKeys(LoadFile(ConfigFile("ide.key")));
	editor.LoadHlStyles(LoadFile(ConfigFile("ide.colors")));
	config_time = FileGetTime(ConfigFile());
	UpdateFormat();
	if(filelist.IsCursor()) {
		FlushFile();
		FileCursor();
	}
	SaveLoadPackage();
	SyncCh();
}
コード例 #13
0
ファイル: BaseDlg.cpp プロジェクト: kolyden/mirror
PackageInfo GetPackageInfo(const String& name)
{
    String path = PackagePath(name);
    Time tm = FileGetTime(path);
    int q = sPi.Find(name);
    if(q >= 0) {
        if(path == sPi[q].path && tm == sPi[q].stamp)
            return sPi[q];
    }
    else {
        q = sPi.GetCount();
        sPi.Add(name);
    }
    PackageInfo& pi = sPi[q];
    pi.path = path;
    pi.stamp = tm;
    Package p;
    p.Load(path);
    pi.ink = p.ink;
    pi.italic = p.italic;
    pi.bold = p.bold;
    return pi;
}
コード例 #14
0
ファイル: Png.cpp プロジェクト: dreamsxin/ultimatepp
void IdePngDes::Save()
{
	if(GetCount())
		SaveChangedFileFinish(filename, PNGEncoder().SaveString(GetImage(0)));
	filetime = FileGetTime(filename);
}
コード例 #15
0
ファイル: Setup.cpp プロジェクト: guowei8412/upp-mirror
void Ide::SetupFormat() {
	FormatDlg dlg;
	dlg.Title("Format setup");
	WithSetupFontLayout<ParentCtrl> fnt;
	WithSetupHlLayout<ParentCtrl> hlt;
	WithSetupEditorLayout<ParentCtrl> edt;
	WithSetupIdeLayout<ParentCtrl> ide;
	WithSetupAssistLayout<ParentCtrl> assist;
	WithSetupMobilePlatformsLayout<ParentCtrl> mobile;
	AStyleSetupDialog ast(this);
#ifdef PLATFORM_WIN32
	ide.console_txt.Hide();
	ide.console.Hide();
	ide.kde.Hide();
	ide.gnome.Hide();
	ide.xterm.Hide();
	ide.mate.Hide();
	
#endif
	ide.kde <<= callback2(SetConsole, &ide.console, "/usr/bin/konsole -e");
	ide.gnome <<= callback2(SetConsole, &ide.console, "/usr/bin/gnome-terminal -x");
	ide.mate <<= callback2(SetConsole, &ide.console, "/usr/bin/mate-terminal -x");
	ide.xterm <<= callback2(SetConsole, &ide.console, "/usr/bin/xterm -e");
	
	edt.lineends
		.Add(LF, "LF")
		.Add(CRLF, "CRLF")
		.Add(DETECT_LF, "Detect with default LF")
		.Add(DETECT_CRLF, "Detect with default CRLF");
	
	edt.filetabs
		.Add(AlignedFrame::LEFT, "Left")
		.Add(AlignedFrame::TOP, "Top")
		.Add(AlignedFrame::RIGHT, "Right")
		.Add(AlignedFrame::BOTTOM, "Bottom")
		.Add(-1, "Off");
		
	edt.tabs_crosses
		.Add(AlignedFrame::LEFT, "Left")
		.Add(AlignedFrame::RIGHT, "Right")
		.Add(-1, "Off");
	
	dlg.Add(fnt, "Fonts");
	dlg.Add(hlt, "Syntax highlighting");
	dlg.Add(edt, "Editor");
	dlg.Add(assist, "Assist");
	dlg.Add(ide, "IDE");
	dlg.Add(ast, "Code formatting");
	dlg.Add(mobile, "Mobile platforms");
	dlg.WhenClose = dlg.Acceptor(IDEXIT);
	FontSelectManager ed, vf, con, f1, f2, tf;
	ed.Set(fnt.face, fnt.height, fnt.bold, fnt.italic, fnt.naa);
	vf.Set(fnt.vface, fnt.vheight, fnt.vbold, fnt.vitalic, fnt.vnaa);
	con.Set(fnt.cface, fnt.cheight, fnt.cbold, fnt.citalic, fnt.cnaa);
	tf.Set(fnt.tface, fnt.theight, fnt.tbold, fnt.titalic, fnt.tnaa);
	f1.Set(fnt.face1, fnt.height1, fnt.bold1, fnt.italic1, fnt.naa1);
	f2.Set(fnt.face2, fnt.height2, fnt.bold2, fnt.italic2, fnt.naa2);
	ed.Set(editorfont);
	vf.Set(veditorfont);
	con.Set(consolefont);
	tf.Set(tfont);
	f1.Set(font1);
	f2.Set(font2);
	DlCharset(edt.charset);
	edt.tabsize.MinMax(1, 100).NotNull();
	edt.tabsize <<= editortabsize;
	edt.indent_amount.MinMax(1, 100).NotNull();
	edt.indent_amount <<= indent_spaces ? indent_amount : editortabsize;
	edt.indent_amount.Enable(indent_spaces);
	CtrlRetriever rtvr;
	int hs = hilite_scope;
	rtvr
		(hlt.hilite_scope, hs)
		(hlt.hilite_bracket, hilite_bracket)
		(hlt.hilite_ifdef, hilite_ifdef)
		(hlt.hilite_if_endif, hilite_if_endif)
		(hlt.thousands_separator, thousands_separator)
		(hlt.hline, hline)

		(edt.indent_spaces, indent_spaces)
		(edt.no_parenthesis_indent, no_parenthesis_indent)
		(edt.showtabs, show_tabs)
		(edt.warnwhitespace, warnwhitespace)
		(edt.lineends, line_endings)
		(edt.numbers, line_numbers)
		(edt.bookmark_pos, bookmark_pos)
		(edt.bordercolumn, bordercolumn)
		(edt.bordercolor, bordercolor)
		(edt.findpicksel, find_pick_sel)
		(edt.findpicktext, find_pick_text)
		(edt.deactivate_save, deactivate_save)
		(edt.filetabs, filetabs)
		(edt.tabs_icons, tabs_icons)
		(edt.tabs_crosses, tabs_crosses)
		(edt.tabs_grouping, tabs_grouping)
		(edt.tabs_stacking, tabs_stacking)
		(edt.tabs_serialize, tabs_serialize)
		(edt.persistent_find_replace, persistent_find_replace)
		(edt.find_replace_restore_pos, find_replace_restore_pos)

		(assist.barline, barline)
		(assist.auto_enclose, auto_enclose)
		(assist.commentdp, editor.commentdp)
		(assist.header_guards, header_guards)
		(assist.insert_include, insert_include)
		(assist.mark_lines, mark_lines)
		(assist.qtfsel, qtfsel)
		(assist.assist, editor.auto_assist)

		(ide.showtime, showtime)
		(ide.show_status_bar, show_status_bar)
		(ide.toolbar_in_row, toolbar_in_row)
		(ide.splash_screen, splash_screen)
		(ide.sort, sort)
		(ide.mute_sounds, mute_sounds)
		(ide.wrap_console_text, wrap_console_text)
		(ide.hydra1_threads, hydra1_threads)
		(ide.gdbSelector, gdbSelector)
		(ide.chstyle, chstyle)
		(ide.console, LinuxHostConsole)
		(ide.output_per_assembly, output_per_assembly)

		(ast.BracketIndent,					astyle_BracketIndent)
		(ast.NamespaceIndent,               astyle_NamespaceIndent)
		(ast.BlockIndent,                   astyle_BlockIndent)
		(ast.CaseIndent,                    astyle_CaseIndent)
		(ast.ClassIndent,                   astyle_ClassIndent)
		(ast.LabelIndent,                   astyle_LabelIndent)
		(ast.SwitchIndent,                  astyle_SwitchIndent)
		(ast.PreprocessorIndent,            astyle_PreprocessorIndent)
		(ast.MinInStatementIndentLength,    astyle_MinInStatementIndentLength)
		(ast.MaxInStatementIndentLength,    astyle_MaxInStatementIndentLength)
		(ast.BreakClosingHeaderBracketsMode,astyle_BreakClosingHeaderBracketsMode)
		(ast.BreakElseIfsMode,              astyle_BreakElseIfsMode)
		(ast.BreakOneLineBlocksMode,        astyle_BreakOneLineBlocksMode)
		(ast.SingleStatementsMode,          astyle_SingleStatementsMode)
		(ast.BreakBlocksMode,               astyle_BreakBlocksMode)
		(ast.BreakClosingHeaderBlocksMode,  astyle_BreakClosingHeaderBlocksMode)
		(ast.BracketFormatMode,             astyle_BracketFormatMode)
		(ast.ParensPaddingMode,             astyle_ParensPaddingMode)
		(ast.ParensUnPaddingMode,           astyle_ParensUnPaddingMode)
		(ast.OperatorPaddingMode,           astyle_OperatorPaddingMode)
		(ast.EmptyLineFill,                 astyle_EmptyLineFill)
		(ast.TabSpaceConversionMode,        astyle_TabSpaceConversionMode)
		(ast.TestBox,						astyle_TestBox)
		
		(mobile.AndroidSDKPath, androidSDKPath)
	;
	hlt.hlstyle.AddColumn("Style");
	hlt.hlstyle.AddColumn("Color").Ctrls(HlPusherFactory);
	hlt.hlstyle.AddColumn("Bold").Ctrls<Option>();
	hlt.hlstyle.AddColumn("Italic").Ctrls<Option>();
	hlt.hlstyle.AddColumn("Underline").Ctrls<Option>();
	hlt.hlstyle.ColumnWidths("211 80 45 45 80");
	hlt.hlstyle.EvenRowColor().NoHorzGrid().SetLineCy(EditField::GetStdHeight() + 2);
	ReadHlStyles(hlt.hlstyle);
	edt.charset <<= (int)default_charset;
	edt.tabsize <<= rtvr <<=
		hlt.hlstyle.WhenCtrlsAction = ed.WhenAction = tf.WhenAction =
		con.WhenAction = f1.WhenAction = f2.WhenAction = dlg.Breaker(222);
	ide.showtimeafter <<= Nvl((Date)FileGetTime(ConfigFile("version")), GetSysDate() - 1);
	hlt.hl_restore <<= dlg.Breaker(333);
	ide.chstyle.Add(0, "Host platform");
	ide.chstyle.Add(1, "Standard");
	ide.chstyle.Add(2, "Classic");
	ide.chstyle.Add(3, "Host platform, blue bars");
	ide.chstyle.Add(4, "Standard, blue bars");

	FrameRight<Button> uscBrowse;
	uscBrowse.SetImage(CtrlImg::right_arrow());
	uscBrowse <<= callback1(AddPath, &ide.uscpath);
	ide.uscpath.AddFrame(uscBrowse);
	ide.uscpath <<= LoadFile(GetHomeDirFile("usc.path"));
	
	FrameRight<Button> androidSDKDownload;
	androidSDKDownload.SetImage(IdeImg::DownloadBlack());
	androidSDKDownload.Tip("Download");
	androidSDKDownload <<= callback1(LaunchWebBrowser, AndroidSDK::GetDownloadUrl());
	mobile.AndroidSDKPath.AddFrame(androidSDKDownload);
	
	FrameRight<Button> androidSDKBrowse;
	androidSDKBrowse.SetImage(CtrlImg::right_arrow());
	androidSDKBrowse.Tip("Select directory");
	androidSDKBrowse <<= callback1(InsertPath, &mobile.AndroidSDKPath);
	mobile.AndroidSDKPath.AddFrame(androidSDKBrowse);
	mobile.AndroidSDKPath <<= androidSDKPath;
	
	for(;;) {
		int c = dlg.Run();
		Upp::SaveFile(GetHomeDirFile("usc.path"), ~ide.uscpath);
		editorfont = ed.Get();
		tfont = tf.Get();
		veditorfont = vf.Get();
		consolefont = con.Get();
		font1 = f1.Get();
		font2 = f2.Get();
		editortabsize = Nvl((int)~edt.tabsize, 4);
		rtvr.Retrieve();
		console.SetSlots(minmax(hydra1_threads, 1, 256));
		hilite_scope = hs;
		if(indent_spaces)
			indent_amount = ~edt.indent_amount;
		else {
			indent_amount = editortabsize;
			edt.indent_amount <<= editortabsize;
		}
		edt.indent_amount.Enable(indent_spaces);
		default_charset = (byte)(int)~edt.charset;
		for(int i = 0; i < CodeEditor::HL_COUNT; i++)
			editor.SetHlStyle(i, hlt.hlstyle.Get(i, 1), hlt.hlstyle.Get(i, 2),
			                     hlt.hlstyle.Get(i, 3), hlt.hlstyle.Get(i, 4));
		UpdateFormat();
		if(c == IDEXIT)
			break;
		if(c == 333 && PromptYesNo("Restore default highlighting colors?")) {
			editor.DefaultHlStyles();
			ReadHlStyles(hlt.hlstyle);
		}
	}
	FileSetTime(ConfigFile("version"), ToTime(~ide.showtimeafter));
	FinishConfig();
	SaveConfig();
}
コード例 #16
0
ファイル: SelectPkg.cpp プロジェクト: dreamsxin/ultimatepp
void SelectPackageDlg::Load()
{
	if(selectvars && !base.IsCursor())
		return;
	if(loading) { // If we are called recursively from ProcessEvents, stop current loading and change loadi
		loadi++;
		loading = false;
		return;
	}
	int current_loadi = -1;
	while(current_loadi != loadi) {
		current_loadi = loadi;
		if(selectvars) {
			String assembly = (String)base.Get(0);
			list.Enable(base.IsCursor());
			if(!base.IsCursor())
				return;
			LoadVars(assembly);
		}
		Vector<String> upp = GetUppDirs();
		packages.Clear();
		description.Hide();
		progress.Show();
		loading = true;
		data.Clear();
		Index<String> dir_exists;
		String cache_path = CachePath(GetVarsName());
		LoadFromFile(data, cache_path);
		data.SetCount(upp.GetCount());
		for(int i = 0; i < upp.GetCount(); i++) // Scan nest folders for subfolders (package candidates)
			ScanFolder(upp[i], data[i], GetFileName(upp[i]), dir_exists, Null);
		int update = msecs();
		for(int i = 0; i < data.GetCount() && loading; i++) { // Now investigate individual sub folders
			ArrayMap<String, PkData>& nest = data[i];
			for(int i = 0; i < nest.GetCount() && loading; i++) {
				if(msecs(update) >= 100) { // each 100 ms update the list (and open select dialog after splash screen is closed)
					if(!IsSplashOpen() && !IsOpen())
						Open();
					progress++;
					SyncList();
					update = msecs();
				}
				ProcessEvents(); // keep GUI running
	
				PkData& d = nest[i];
				String path = nest.GetKey(i);
				FindFile ff(path);
				if(ff && ff.IsFolder()) {
					String upp_path = AppendFileName(path, GetFileName(d.package) + ".upp");
					LSLOW();
					Time tm = FileGetTime(upp_path);
					if(IsNull(tm)) // .upp file does not exist - not a package
						d.ispackage = false;
					else
					if(tm != d.tm) { // cached info is outdated
						Package p;
						if(p.Load(upp_path)) {
							d.description = p.description;
							d.main = p.config.GetCount();
							d.tm = tm;
							d.ispackage = true;
						}
						else
							d.ispackage = false;
					}
					else
						d.ispackage = true;
					if(d.ispackage) {
						String icon_path = AppendFileName(path, "icon16x16.png");
						tm = FileGetTime(icon_path);
						if(IsNull(tm)) // package icon does not exist
							d.icon = Null;
						else
						if(tm != d.itm) { // chached package icon outdated
							d.icon = StreamRaster::LoadFileAny(icon_path);
							d.itm = tm;
						}
					}
				}
				else 
					nest.Unlink(i); // cached folder was deleted
				ScanFolder(path, nest, d.nest, dir_exists, d.package + '/');
			}
			nest.Sweep();
		}
	
		StoreToFile(data, cache_path);
		progress.Hide();
		while(IsSplashOpen())
			ProcessEvents();
		if(!IsOpen())
			Open();
		description.Show();
		if(loading) {
			loading = false;
			SyncList();
		}
	}
}
コード例 #17
0
ファイル: handle.cpp プロジェクト: firegiant/wix4
void HandleUnlock(
    __inout CFGDB_STRUCT *pcdb
    )
{
    HRESULT hr = S_OK;
    FILETIME ftRemote = { };
    LPWSTR sczTempRemotePath = NULL;
    BOOL fCopyRemoteBack = FALSE;

    if (1 < pcdb->dwLockRefCount)
    {
        ExitFunction1(hr = S_OK);
    }

    Assert(0 < pcdb->dwLockRefCount);

    // Disconnect from database, if it's a connected remote database
    if (pcdb->fRemote && NULL != pcdb->psceDb)
    {
        fCopyRemoteBack = SceDatabaseChanged(pcdb->psceDb);

        hr = SceCloseDatabase(pcdb->psceDb);
        ExitOnFailure(hr, "Failed to close remote database");
        pcdb->psceDb = NULL;

        if (fCopyRemoteBack)
        {
            hr = FileGetTime(pcdb->sczDbPath, NULL, NULL, &ftRemote);
            ExitOnFailure(hr, "Failed to get modified time of actual remote %ls", &ftRemote);

            // Since DB file wasn't locked, we have to verify that nobody changed it in the meantime.
            // Do it once before we try uploading to the remote (because uploading could be a lengthy operation on a slow connection to remote path)
            if (0 != ::CompareFileTime(&ftRemote, &pcdb->ftBeforeModify))
            {
                hr = HRESULT_FROM_WIN32(ERROR_LOCK_VIOLATION);
                ExitOnFailure(hr, "database %ls was modified (before copy), we can't overwrite it!", pcdb->sczDbPath);
            }

            // Get it on the volume first which may take time
            // TODO: in some cases such as crashes or connection lost to network remote,
            // we'll leave a file behind here. We need a feature to look for and cleanup old files.
            hr = PathConcat(pcdb->sczDbDir, pcdb->sczGuid, &sczTempRemotePath);
            ExitOnFailure(hr, "Failed to get temp path in remote directory");

            hr = FileEnsureCopy(pcdb->sczDbCopiedPath, sczTempRemotePath, TRUE);
            ExitOnFailure(hr, "Failed to copy remote database back to remote location (from %ls to %ls) due to changes", pcdb->sczDbCopiedPath, pcdb->sczDbPath);

            // Now do it again after the upload right before we do the actual move
            hr = FileGetTime(pcdb->sczDbPath, NULL, NULL, &ftRemote);
            ExitOnFailure(hr, "Failed to get modified time of original remote (again) %ls", &ftRemote);

            if (0 != ::CompareFileTime(&ftRemote, &pcdb->ftBeforeModify))
            {
                hr = HRESULT_FROM_WIN32(ERROR_LOCK_VIOLATION);
                ExitOnFailure(hr, "database %ls was modified (after copy), we can't overwrite it!", pcdb->sczDbPath);
            }

            // Use MoveFile to ensure it's done as an atomic operation, so remote can never be left not existing.
            // There is a tiny chance we're reverting someone else's changes here if some other machine just moved the file between
            // the last timestamp check and this MoveFile call. I don't believe there is a way to fix that (we could open a lock on the file,
            // but then we can't use atomic MoveFile() API, meaning we could leave a partial file around in some cases, a HUGE no-no)
            // However, inadvertently overwriting a just-written db file is not a problem - Autosync on all machines will notice the fact
            // that the DB changed, re-sync it, at which time we will try again to re-propagate the changes.
            if (!::MoveFileExW(sczTempRemotePath, pcdb->sczDbPath, MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH))
            {
                ExitWithLastError(hr, "Failed to move uploaded database path back to original remote location %ls", pcdb->sczDbPath);
            }
        }

        if (pcdb->fUpdateLastModified)
        {
            hr = FileGetTime(pcdb->sczDbCopiedPath, NULL, NULL, &pcdb->ftLastModified);
            if (E_FILENOTFOUND == hr || E_NOTFOUND == hr)
            {
                hr = S_OK;
            }
            ExitOnFailure(hr, "Failed to get modified time of copied db: %ls", pcdb->sczDbCopiedPath);
        }

        hr = FileEnsureDelete(pcdb->sczDbCopiedPath);
        ExitOnFailure(hr, "Failed to delete copied remote database from %ls", pcdb->sczDbCopiedPath);

        ReleaseNullStr(pcdb->sczDbCopiedPath);
    }

    for (DWORD i = 0; i < pcdb->cStreamsToDelete; ++i)
    {
        DeleteStream(pcdb->rgsczStreamsToDelete[i]);
    }
    ReleaseNullStrArray(pcdb->rgsczStreamsToDelete, pcdb->cStreamsToDelete);

    pcdb->fUpdateLastModified = FALSE;

LExit:
    --pcdb->dwLockRefCount;
    ::LeaveCriticalSection(&pcdb->cs);
    if (FAILED(hr) && sczTempRemotePath)
    {
        // In case we left a temp file around, try to delete it before exiting (ignoring failure)
        FileEnsureDelete(sczTempRemotePath);
    }
    ReleaseStr(sczTempRemotePath);
}
コード例 #18
0
ファイル: handle.cpp プロジェクト: firegiant/wix4
HRESULT HandleLock(
    __inout CFGDB_STRUCT *pcdb
    )
{
    HRESULT hr = S_OK;

    ::EnterCriticalSection(&pcdb->cs);
    ++pcdb->dwLockRefCount;

    if (1 < pcdb->dwLockRefCount)
    {
        ExitFunction1(hr = S_OK);
    }

    // This should only be set to TRUE if the database was successfully completely synced with local upon unlock
    pcdb->fUpdateLastModified = FALSE;

    // Connect to database, if it's a remote database
    if (pcdb->fRemote)
    {
        // If database path is present right now, clean up conflicted databases
        if (FileExistsEx(pcdb->sczDbPath, NULL))
        {
            hr = CleanConflictedDatabases(pcdb->sczDbDir, pcdb->sczDbPath);
            TraceError(hr, "Failed to clean conflicted databases, continuing");
            hr = S_OK;
        }

        hr = FileCreateTempW(L"Remote", L".sdf", &pcdb->sczDbCopiedPath, NULL);
        ExitOnFailure(hr, "Failed to create temp file to copy database file to");
    
        hr = FileEnsureCopy(pcdb->sczDbPath, pcdb->sczDbCopiedPath, TRUE);
        ExitOnFailure(hr, "Failed to copy remote database locally");

        hr = FileGetTime(pcdb->sczDbCopiedPath, NULL, NULL, &pcdb->ftBeforeModify);
        ExitOnFailure(hr, "Failed to get modified time of copied remote %ls", pcdb->sczDbCopiedPath);

        hr = SceEnsureDatabase(pcdb->sczDbCopiedPath, wzSqlCeDllPath, L"CfgRemote", 1, &pcdb->dsSceDb, &pcdb->psceDb);
        ExitOnFailure(hr, "Failed to ensure SQL CE database at %ls exists", pcdb->sczDbPath);

        // If the remote wasn't up when we initialized, we couldn't get cfg app id or GUID, so get it now
        if (DWORD_MAX == pcdb->dwCfgAppID)
        {
            hr = HandleEnsureSummaryDataTable(pcdb);
            ExitOnFailure(hr, "Failed to ensure remote database summary data");

            hr = GuidListEnsure(pcdb->pcdbLocal, pcdb->sczGuid, &pcdb->sczGuidRemoteInLocalKey);
            ExitOnFailure(hr, "Failed to ensure remote database is in local database's guid table");

            hr = GuidListEnsure(pcdb, pcdb->pcdbLocal->sczGuid, &pcdb->sczGuidLocalInRemoteKey);
            ExitOnFailure(hr, "Failed to ensure local database is in remote database's guid table");

            hr = ProductSet(pcdb, wzCfgProductId, wzCfgVersion, wzCfgPublicKey, TRUE, NULL);
            ExitOnFailure(hr, "Failed to set product to cfg product id");
            pcdb->dwCfgAppID = pcdb->dwAppID;
        }
    }

LExit:
    if (FAILED(hr))
    {
        --pcdb->dwLockRefCount;
        ::LeaveCriticalSection(&pcdb->cs);
    }

    return hr;
}
コード例 #19
0
ファイル: Config.cpp プロジェクト: AbdelghaniDr/mirror
Time Ide::ConfigTime()
{
	return FileGetTime(ConfigFile());
}
コード例 #20
0
ファイル: XmlConfig.cpp プロジェクト: BMurri/wix3
/******************************************************************
 ExecXmlConfigRollback - entry point for XmlConfig rollback Custom Action

*******************************************************************/
extern "C" UINT __stdcall ExecXmlConfigRollback(
    __in MSIHANDLE hInstall
    )
{
//    AssertSz(FALSE, "debug ExecXmlConfigRollback");
    HRESULT hr = S_OK;
    UINT er = ERROR_SUCCESS;

    int iIs64Bit;
    BOOL fIs64Bit = FALSE;

    LPWSTR pwzCustomActionData = NULL;
    LPWSTR pwz = NULL;
    LPWSTR pwzFileName = NULL;
    LPBYTE pbData = NULL;
    DWORD_PTR cbData = 0;
    DWORD cbDataWritten = 0;

    FILETIME ft;

    HANDLE hFile = INVALID_HANDLE_VALUE;

    // initialize
    hr = WcaInitialize(hInstall, "ExecXmlConfigRollback");
    ExitOnFailure(hr, "failed to initialize");


    hr = WcaGetProperty( L"CustomActionData", &pwzCustomActionData);
    ExitOnFailure(hr, "failed to get CustomActionData");

    WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCustomActionData);

    pwz = pwzCustomActionData;

    hr = WcaReadIntegerFromCaData(&pwz, &iIs64Bit);
    ExitOnFailure(hr, "failed to read component bitness from custom action data");

    hr = WcaReadStringFromCaData(&pwz, &pwzFileName);
    ExitOnFailure(hr, "failed to read file name from custom action data");

    hr = WcaReadStreamFromCaData(&pwz, &pbData, &cbData);
    ExitOnFailure(hr, "failed to read file contents from custom action data");

    fIs64Bit = (BOOL)iIs64Bit;

    if (fIs64Bit)
    {
        hr = WcaInitializeWow64();
        if (S_FALSE == hr)
        {
            hr = TYPE_E_DLLFUNCTIONNOTFOUND;
        }
        ExitOnFailure(hr, "failed to initialize Wow64 API");

        if (!WcaIsWow64Process())
        {
            hr = E_NOTIMPL;
            ExitOnFailure(hr, "Custom action was told to rollback a 64-bit component, but the Wow64 API is unavailable.");
        }

        hr = WcaDisableWow64FSRedirection();
        ExitOnFailure(hr, "Custom action was told to rollback a 64-bit component, but was unable to Disable Filesystem Redirection through the Wow64 API.");
    }

    hr = FileGetTime(pwzFileName, NULL, NULL, &ft);
    ExitOnFailure1(hr, "Failed to get modified date of file %ls.", pwzFileName);

    // Open the file
    hFile = ::CreateFileW(pwzFileName, GENERIC_WRITE, NULL, NULL, TRUNCATE_EXISTING, NULL, NULL);
    ExitOnInvalidHandleWithLastError1(hFile, hr, "failed to open file: %ls", pwzFileName);

    // Write out the old data
    if (!::WriteFile(hFile, pbData, (DWORD)cbData, &cbDataWritten, NULL))
    {
        ExitOnLastError1(hr, "failed to write to file: %ls", pwzFileName);
    }

    Assert(cbData == cbDataWritten);

    ReleaseFile(hFile);

    hr = FileSetTime(pwzFileName, NULL, NULL, &ft);
    ExitOnFailure1(hr, "Failed to set modified date of file %ls.", pwzFileName);

LExit:
    ReleaseStr(pwzCustomActionData);
    ReleaseStr(pwzFileName);

    ReleaseFile(hFile);

    if (fIs64Bit)
    {
        WcaRevertWow64FSRedirection();
        WcaFinalizeWow64();
    }

    ReleaseMem(pbData);

    if (FAILED(hr))
    {
        er = ERROR_INSTALL_FAILURE;
    }
    return WcaFinalize(er);
}
コード例 #21
0
ファイル: load.cpp プロジェクト: firegiant/wix4
static DWORD WINAPI LoadThreadProc(
    __in LPVOID pvContext
    )
{
    HRESULT hr = S_OK;

    LOAD_THREAD_CONTEXT* pContext = static_cast<LOAD_THREAD_CONTEXT*>(pvContext);
    LPWSTR sczThemePath = pContext->sczThemePath;
    HWND hWnd = pContext->hWnd;

    // We can signal the initialization event as soon as we have copied the context
    // values into local variables.
    ::SetEvent(pContext->hInit);

    BOOL fComInitialized = FALSE;
    HANDLE hDirectory = INVALID_HANDLE_VALUE;
    LPWSTR sczDirectory = NULL;
    LPWSTR wzFileName = NULL;

    THEME* pTheme = NULL;
    HANDLE_THEME* pHandle = NULL;

    hr = ::CoInitialize(NULL);
    ExitOnFailure(hr, "Failed to initialize COM on load thread.");
    fComInitialized = TRUE;

    // Open a handle to the directory so we can put a notification on it.
    hr = PathGetDirectory(sczThemePath, &sczDirectory);
    ExitOnFailure(hr, "Failed to get path directory.");

     wzFileName = PathFile(sczThemePath);

    hDirectory = ::CreateFileW(sczDirectory, FILE_LIST_DIRECTORY, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
    if (INVALID_HANDLE_VALUE == hDirectory)
    {
        ExitWithLastError(hr, "Failed to open directory: %ls", sczDirectory);
    }

    BOOL fUpdated = FALSE;
    do
    {
        // Get the last modified time on the file we're loading for verification that the
        // file actually gets changed down below.
        FILETIME ftModified = { };
        FileGetTime(sczThemePath, NULL, NULL, &ftModified);

        // Try to load the theme file.
        hr = ThemeLoadFromFile(sczThemePath, &pTheme);
        if (FAILED(hr))
        {
            ::SendMessageW(hWnd, WM_THMVWR_THEME_LOAD_ERROR, 0, hr);
        }
        else
        {
            hr = AllocHandleTheme(pTheme, &pHandle);
            ExitOnFailure(hr, "Failed to allocate handle to theme");

            ::SendMessageW(hWnd, WM_THMVWR_NEW_THEME, 0, reinterpret_cast<LPARAM>(pHandle));
            pHandle = NULL;
        }

        fUpdated = FALSE;
        do
        {
            DWORD rgbNotifications[1024];
            DWORD cbRead = 0;
            if (!::ReadDirectoryChangesW(hDirectory, rgbNotifications, sizeof(rgbNotifications), FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE, &cbRead, NULL, NULL))
            {
                ExitWithLastError(hr, "Failed while watching directory: %ls", sczDirectory);
            }

            // Wait for half a second to let all the file handles get closed to minimize access
            // denied errors.
            ::Sleep(500);

            FILE_NOTIFY_INFORMATION* pNotification = reinterpret_cast<FILE_NOTIFY_INFORMATION*>(rgbNotifications);
            while (pNotification)
            {
                // If our file was updated, check to see if the modified time really changed. The notifications
                // are often trigger happy thinking the file changed two or three times in a row. Maybe it's AV
                // software creating the problems but actually checking the modified date works well.
                if (CSTR_EQUAL == ::CompareStringW(LOCALE_NEUTRAL, NORM_IGNORECASE, pNotification->FileName, pNotification->FileNameLength / sizeof(WCHAR), wzFileName, -1))
                {
                    FILETIME ft = { };
                    FileGetTime(sczThemePath, NULL, NULL, &ft);

                    fUpdated = (ftModified.dwHighDateTime < ft.dwHighDateTime) || (ftModified.dwHighDateTime == ft.dwHighDateTime && ftModified.dwLowDateTime < ft.dwLowDateTime);
                    break;
                }

                pNotification = pNotification->NextEntryOffset ? reinterpret_cast<FILE_NOTIFY_INFORMATION*>(reinterpret_cast<BYTE*>(pNotification) + pNotification->NextEntryOffset) : NULL;
            }
        } while (!fUpdated);
    } while(fUpdated);

LExit:
    if (fComInitialized)
    {
        ::CoUninitialize();
    }

    ReleaseFileHandle(hDirectory);
    ReleaseStr(sczDirectory);
    ReleaseStr(sczThemePath);
    return hr;
}
コード例 #22
0
ファイル: XmlConfig.cpp プロジェクト: BMurri/wix3
/******************************************************************
 ExecXmlConfig - entry point for XmlConfig Custom Action

*******************************************************************/
extern "C" UINT __stdcall ExecXmlConfig(
    __in MSIHANDLE hInstall
    )
{
    //AssertSz(FALSE, "debug ExecXmlConfig");
    HRESULT hr = S_OK;
    HRESULT hrOpenFailure = S_OK;
    UINT er = ERROR_SUCCESS;

    BOOL fIsWow64Process = FALSE;
    BOOL fIsFSRedirectDisabled = FALSE;
    BOOL fPreserveDate = FALSE;

    LPWSTR pwzCustomActionData = NULL;
    LPWSTR pwzData = NULL;
    LPWSTR pwzFile = NULL;
    LPWSTR pwzElementPath = NULL;
    LPWSTR pwzVerifyPath = NULL;
    LPWSTR pwzName = NULL;
    LPWSTR pwzValue = NULL;
    LPWSTR pwz = NULL;
    int cAdditionalChanges = 0;

    IXMLDOMDocument* pixd = NULL;
    IXMLDOMNode* pixn = NULL;
    IXMLDOMNode* pixnVerify = NULL;
    IXMLDOMNode* pixnNewNode = NULL;
    IXMLDOMNode* pixnRemovedChild = NULL;

    IXMLDOMDocument* pixdNew = NULL;
    IXMLDOMElement* pixeNew = NULL;

    FILETIME ft;

    int id = IDRETRY;

    eXmlAction xa;
    eXmlPreserveDate xd;

    // initialize
    hr = WcaInitialize(hInstall, "ExecXmlConfig");
    ExitOnFailure(hr, "failed to initialize");

    hr = XmlInitialize();
    ExitOnFailure(hr, "failed to initialize xml utilities");

    hr = WcaGetProperty( L"CustomActionData", &pwzCustomActionData);
    ExitOnFailure(hr, "failed to get CustomActionData");

    WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCustomActionData);

    pwz = pwzCustomActionData;

    hr = WcaReadIntegerFromCaData(&pwz, (int*) &xa);
    ExitOnFailure(hr, "failed to process CustomActionData");

    // Initialize the Wow64 API - store the result in fWow64APIPresent
    // If it fails, this doesn't warrant an error yet, because we only need the Wow64 API in some cases
    WcaInitializeWow64();
    fIsWow64Process = WcaIsWow64Process();

    if (xaOpenFile != xa && xaOpenFilex64 != xa)
    {
        ExitOnFailure(hr = E_INVALIDARG, "invalid custom action data");
    }

    // loop through all the passed in data
    while (pwz && *pwz)
    {
        hr = WcaReadStringFromCaData(&pwz, &pwzFile);
        ExitOnFailure(hr, "failed to read file name from custom action data");

        // Default to not preserve date, preserve it if any modifications require us to
        fPreserveDate = FALSE;

        // Open the file
        ReleaseNullObject(pixd);

        if (xaOpenFilex64 == xa)
        {
            if (!fIsWow64Process)
            {
                hr = E_NOTIMPL;
                ExitOnFailure(hr, "Custom action was told to act on a 64-bit component, but the custom action process is not running in WOW.");
            }

            hr = WcaDisableWow64FSRedirection();
            ExitOnFailure(hr, "Custom action was told to act on a 64-bit component, but was unable to disable filesystem redirection through the Wow64 API.");

            fIsFSRedirectDisabled = TRUE;
        }

        hr = XmlLoadDocumentFromFileEx(pwzFile, XML_LOAD_PRESERVE_WHITESPACE, &pixd);
        if (FAILED(hr))
        {
            // Ignore the return code for now.  If they try to add something, we'll fail the install.  If all they do is remove stuff then it doesn't matter.
            hrOpenFailure = hr;
            hr = S_OK;
        }
        else
        {
            hrOpenFailure = S_OK;
        }

        WcaLog(LOGMSG_VERBOSE, "Configuring Xml File: %ls", pwzFile);

        while (pwz && *pwz)
        {
            // If we skip past an element that has additional changes we need to strip them off the stream before
            // moving on to the next element. Do that now and then restart the outer loop.
            if (cAdditionalChanges > 0)
            {
                while (cAdditionalChanges > 0)
                {
                    hr = WcaReadStringFromCaData(&pwz, &pwzName);
                    ExitOnFailure(hr, "failed to process CustomActionData");
                    hr = WcaReadStringFromCaData(&pwz, &pwzValue);
                    ExitOnFailure(hr, "failed to process CustomActionData");

                    cAdditionalChanges--;
                }
                continue;
            }

            hr = WcaReadIntegerFromCaData(&pwz, (int*) &xa);
            ExitOnFailure(hr, "failed to process CustomActionData");

            // Break if we need to move on to a different file
            if (xaOpenFile == xa || xaOpenFilex64 == xa)
            {
                break;
            }

            hr = WcaReadIntegerFromCaData(&pwz, (int*) &xd);
            ExitOnFailure(hr, "failed to process CustomActionData");

            if (xdPreserve == xd)
            {
                fPreserveDate = TRUE;
            }

            // Get path, name, and value to be written
            hr = WcaReadStringFromCaData(&pwz, &pwzElementPath);
            ExitOnFailure(hr, "failed to process CustomActionData");
            hr = WcaReadStringFromCaData(&pwz, &pwzVerifyPath);
            ExitOnFailure(hr, "failed to process CustomActionData");
            hr = WcaReadStringFromCaData(&pwz, &pwzName);
            ExitOnFailure(hr, "failed to process CustomActionData");
            hr = WcaReadStringFromCaData(&pwz, &pwzValue);
            ExitOnFailure(hr, "failed to process CustomActionData");
            hr = WcaReadIntegerFromCaData(&pwz, &cAdditionalChanges);
            ExitOnFailure(hr, "failed to process CustomActionData");

            // If we failed to open the file and we're adding something to the file, we've got a problem.  Otherwise, just continue on since the file's already gone.
            if (FAILED(hrOpenFailure))
            {
                if (xaCreateElement == xa || xaWriteValue == xa || xaWriteDocument == xa)
                {
                    MessageExitOnFailure1(hr = hrOpenFailure, msierrXmlConfigFailedOpen, "failed to load XML file: %ls", pwzFile);
                }
                else
                {
                    continue;
                }
            }

            // Select the node we're about to modify
            ReleaseNullObject(pixn);

            hr = XmlSelectSingleNode(pixd, pwzElementPath, &pixn);

            // If we failed to find the node that we are going to add to, we've got a problem. Otherwise, just continue since the node's already gone.
            if (S_FALSE == hr)
            {
                if (xaCreateElement == xa || xaWriteValue == xa || xaWriteDocument == xa)
                {
                    hr = HRESULT_FROM_WIN32(ERROR_OBJECT_NOT_FOUND);
                }
                else
                {
                    hr = S_OK;
                    continue;
                }
            }

            MessageExitOnFailure2(hr, msierrXmlConfigFailedSelect, "failed to find node: %ls in XML file: %ls", pwzElementPath, pwzFile);

            // Make the modification
            switch (xa)
            {
            case xaWriteValue:
                if (pwzName && *pwzName)
                {
                    // We're setting an attribute
                    hr = XmlSetAttribute(pixn, pwzName, pwzValue);
                    ExitOnFailure2(hr, "failed to set attribute: %ls to value %ls", pwzName, pwzValue);
                }
                else
                {
                    // We're setting the text of the node
                    hr = XmlSetText(pixn, pwzValue);
                    ExitOnFailure2(hr, "failed to set text to: %ls for element %ls.  Make sure that XPath points to an element.", pwzValue, pwzElementPath);
                }
                break;
            case xaWriteDocument:
                if (NULL != pwzVerifyPath && 0 != pwzVerifyPath[0])
                {
                    hr = XmlSelectSingleNode(pixn, pwzVerifyPath, &pixnVerify);
                    if (S_OK == hr)
                    {
                        // We found the verify path which means we have no further work to do
                        continue;
                    }
                    ExitOnFailure1(hr, "failed to query verify path: %ls", pwzVerifyPath);
                }

                hr = XmlLoadDocumentEx(pwzValue, XML_LOAD_PRESERVE_WHITESPACE, &pixdNew);
                ExitOnFailure(hr, "Failed to load value as document.");

                hr = pixdNew->get_documentElement(&pixeNew);
                ExitOnFailure(hr, "Failed to get document element.");

                hr = pixn->appendChild(pixeNew, NULL);
                ExitOnFailure(hr, "Failed to append document element on to parent element.");

                ReleaseNullObject(pixeNew);
                ReleaseNullObject(pixdNew);
                break;

            case xaCreateElement:
                if (NULL != pwzVerifyPath && 0 != pwzVerifyPath[0])
                {
                    hr = XmlSelectSingleNode(pixn, pwzVerifyPath, &pixnVerify);
                    if (S_OK == hr)
                    {
                        // We found the verify path which means we have no further work to do
                        continue;
                    }
                    ExitOnFailure1(hr, "failed to query verify path: %ls", pwzVerifyPath);
                }

                hr = XmlCreateChild(pixn, pwzName, &pixnNewNode);
                ExitOnFailure1(hr, "failed to create child element: %ls", pwzName);

                if (pwzValue && *pwzValue)
                {
                    hr = XmlSetText(pixnNewNode, pwzValue);
                    ExitOnFailure2(hr, "failed to set text to: %ls for node: %ls", pwzValue, pwzName);
                }

                while (cAdditionalChanges > 0)
                {
                    hr = WcaReadStringFromCaData(&pwz, &pwzName);
                    ExitOnFailure(hr, "failed to process CustomActionData");
                    hr = WcaReadStringFromCaData(&pwz, &pwzValue);
                    ExitOnFailure(hr, "failed to process CustomActionData");

                    // Set the additional attribute
                    hr = XmlSetAttribute(pixnNewNode, pwzName, pwzValue);
                    ExitOnFailure2(hr, "failed to set attribute: %ls to value %ls", pwzName, pwzValue);

                    cAdditionalChanges--;
                }

                ReleaseNullObject(pixnNewNode);
                break;
            case xaDeleteValue:
                if (pwzName && *pwzName)
                {
                    // Delete the attribute
                    hr = XmlRemoveAttribute(pixn, pwzName);
                    ExitOnFailure1(hr, "failed to remove attribute: %ls", pwzName);
                }
                else
                {
                    // Clear the text value for the node
                    hr = XmlSetText(pixn, L"");
                    ExitOnFailure(hr, "failed to clear text value");
                }
                break;
            case xaDeleteElement:
                if (NULL != pwzVerifyPath && 0 != pwzVerifyPath[0])
                {
                    hr = XmlSelectSingleNode(pixn, pwzVerifyPath, &pixnVerify);
                    if (S_OK == hr)
                    {
                        hr = pixn->removeChild(pixnVerify, &pixnRemovedChild);
                        ExitOnFailure(hr, "failed to remove created child element");

                        ReleaseNullObject(pixnRemovedChild);
                    }
                    else
                    {
                        WcaLog(LOGMSG_VERBOSE, "Failed to select path %ls for deleting.  Skipping...", pwzVerifyPath);
                        hr = S_OK;
                    }
                }
                else
                {
                    // TODO: This requires a VerifyPath to delete an element.  Should we support not having one?
                    WcaLog(LOGMSG_VERBOSE, "No VerifyPath specified for delete element of ID: %ls", pwzElementPath);
                }
                break;
            default:
                ExitOnFailure(hr = E_UNEXPECTED, "Invalid modification specified in custom action data");
                break;
            }
        }


        // Now that we've made all of the changes to this file, save it and move on to the next
        if (S_OK == hrOpenFailure)
        {
            if (fPreserveDate)
            {
                hr = FileGetTime(pwzFile, NULL, NULL, &ft);
                ExitOnFailure1(hr, "failed to get modified time of file : %ls", pwzFile);
            }

            int iSaveAttempt = 0;

            do
            {
                hr = XmlSaveDocument(pixd, pwzFile);
                if (FAILED(hr))
                {
                    id = WcaErrorMessage(msierrXmlConfigFailedSave, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 1, pwzFile);
                    switch (id)
                    {
                    case IDABORT:
                        ExitOnFailure1(hr, "Failed to save changes to XML file: %ls", pwzFile);
                    case IDRETRY:
                        hr = S_FALSE;   // hit me, baby, one more time
                        break;
                    case IDIGNORE:
                        hr = S_OK;  // pretend everything is okay and bail
                        break;
                    case 0: // No UI case, MsiProcessMessage returns 0
                        if (STIERR_SHARING_VIOLATION == hr)
                        {
                            // Only in case of sharing violation do we retry 30 times, once a second.
                            if (iSaveAttempt < 30)
                            {
                                hr = S_FALSE;
                                ++iSaveAttempt;
                                WcaLog(LOGMSG_VERBOSE, "Unable to save changes to XML file: %ls, retry attempt: %x", pwzFile, iSaveAttempt);
                                Sleep(1000);
                            }
                            else
                            {
                                ExitOnFailure1(hr, "Failed to save changes to XML file: %ls", pwzFile);
                            }
                        }
                        break;
                    default: // Unknown error
                        ExitOnFailure1(hr, "Failed to save changes to XML file: %ls", pwzFile);
                    }
                }
            } while (S_FALSE == hr);

            if (fPreserveDate)
            {
                hr = FileSetTime(pwzFile, NULL, NULL, &ft);
                ExitOnFailure1(hr, "failed to set modified time of file : %ls", pwzFile);
            }

            if (fIsFSRedirectDisabled)
            {
                fIsFSRedirectDisabled = FALSE;
                WcaRevertWow64FSRedirection();
            }
        }
    }

LExit:
    // Make sure we revert FS Redirection if necessary before exiting
    if (fIsFSRedirectDisabled)
    {
        fIsFSRedirectDisabled = FALSE;
        WcaRevertWow64FSRedirection();
    }
    WcaFinalizeWow64();

    ReleaseStr(pwzCustomActionData);
    ReleaseStr(pwzData);
    ReleaseStr(pwzFile);
    ReleaseStr(pwzElementPath);
    ReleaseStr(pwzVerifyPath);
    ReleaseStr(pwzName);
    ReleaseStr(pwzValue);

    ReleaseObject(pixeNew);
    ReleaseObject(pixdNew);

    ReleaseObject(pixn);
    ReleaseObject(pixd);
    ReleaseObject(pixnNewNode);
    ReleaseObject(pixnRemovedChild);

    XmlUninitialize();

    if (FAILED(hr))
    {
        er = ERROR_INSTALL_FAILURE;
    }
    return WcaFinalize(er);
}