/// <summary> /// Creates a new instance to be used for updating dat files /// </summary> /// <param name="master">The already updated file to be used as a master</param> public static DatUpdater Create(Settings.IDatFile master) { var du = new DatUpdater() { session = new Session(null) { master = master, }, }; du.Initialize(du.session); return(du); }
/// <summary> /// Lists all accounts using the specified dat file /// </summary> /// <param name="dat"></param> /// <returns></returns> public static List <Settings.IGw2Account> GetAccounts(Settings.IDatFile dat) { var accounts = new List <Settings.IGw2Account>(); foreach (var a in Util.Accounts.GetGw2Accounts()) { if (a.DatFile == dat) { accounts.Add(a); } } return(accounts); }
/// <summary> /// Lists all accounts using the specified dat file /// </summary> /// <param name="dat"></param> /// <returns></returns> public static List <Settings.IAccount> GetAccounts(Settings.IDatFile dat) { List <Settings.IAccount> accounts = new List <Settings.IAccount>(); foreach (ushort uid in Settings.Accounts.GetKeys()) { var account = Settings.Accounts[uid]; if (account.HasValue && account.Value.DatFile == dat) { accounts.Add(account.Value); } } return(accounts); }
/// <summary> /// Updates the Local.dat file based on the supplied master file /// </summary> public bool Update(Settings.IDatFile dat) { try { Update(session, dat); dat.IsPending = false; return(true); } catch { return(false); } }
private void Snapshot(Settings.IDatFile master) { Session s; lock (this) { s = new Session(session) { master = master, }; if (session != null) { session.abort = true; } session = s; } try { using (var r = new BinaryReader(new BufferedStream(File.Open(master.Path, FileMode.Open, FileAccess.Read, FileShare.Read)))) { var mft = DatFile.ReadMft(r); s.snapshot = new Dictionary <int, int>(mft.entries.Length); foreach (var entry in mft.entries) { if (entry.baseId > 0) { s.snapshot[entry.baseId] = entry.fileId; if (entry.baseId == ID_LOCAL) { r.BaseStream.Position = entry.offset; s.snapshot[0] = ReadBuild(s.compressor, r.BaseStream, entry); } } } } } catch { } }
private void Update(Session s) { var ids = Settings.DatFiles.GetKeys(); var dats = new Settings.IDatFile[ids.Length]; var i = 0; if (!BitConverter.IsLittleEndian) { throw new NotSupportedException(); } var hs = new HashSet <ushort>(); var queue = new Queue <Settings.IDatFile>(ids.Length); foreach (var uid in ids) { if (s.master.UID == uid) { continue; } var dat = Settings.DatFiles[uid].Value; if (dat != null && dat.References > 0 && dat.IsPending) { dats[i++] = dat; hs.Add(dat.UID); queue.Enqueue(dat); } } if (i > 0) { Initialize(s); s.task = new Task(DoQueue, TaskCreationOptions.LongRunning); s.task.Start(); } }
public static int GetBuild(Settings.IDatFile dat) { try { using (var r = new BinaryReader(new BufferedStream(File.Open(dat.Path, FileMode.Open, FileAccess.Read, FileShare.Read)))) { var mft = Dat.DatFile.ReadMft(r); foreach (var entry in mft.entries) { switch (entry.baseId) { case ID_LOCAL: return(ReadBuild(new Archive(), r.BaseStream, entry)); } } } } catch { } return(0); }
private void buttonOK_Click(object sender, EventArgs e) { if (textAccountName.Text.Length == 0) { buttonGeneral.Selected = true; MessageBox.Show(this, "An identifier / account or display name is required", "Identifier / name required", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } Rectangle windowBounds; if (checkWindowed.Checked) { Rectangle r = ParseWindowSize(textWindowed.Text); windowBounds = FixSize(r); } else windowBounds = Rectangle.Empty; Settings.IDatFile datFile; try { datFile = GetDatFile(); selectedFile = null; } catch (Exception ex) { MessageBox.Show(this, "An error occured while handling Local.dat.\n\n" + ex.Message, "Failed handling Local.dat", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } if (this.account == null) { this.account = Settings.CreateAccount(); this.account.LastUsedUtc = DateTime.MinValue; this.account.CreatedUtc = DateTime.UtcNow; } this.account.Windowed = checkWindowed.Checked; this.account.Name = textAccountName.Text; this.account.WindowsAccount = textWindowsAccount.Text; this.account.Arguments = textArguments.Text; this.account.ShowDaily = checkShowDaily.Checked; this.account.DatFile = datFile; this.account.WindowBounds = windowBounds; this.account.RecordLaunches = checkRecordLaunch.Checked; if (checkAutomaticLogin.Checked && textAutoLoginEmail.TextLength > 0 && textAutoLoginPassword.TextLength > 0) { this.account.AutomaticLoginEmail = textAutoLoginEmail.Text; this.account.AutomaticLoginPassword = textAutoLoginPassword.Text; } else { this.account.AutomaticLoginEmail = null; this.account.AutomaticLoginPassword = null; } this.DialogResult = System.Windows.Forms.DialogResult.OK; }
private Settings.IDatFile GetDatFile() { if (selectedFile == null) { if (account != null) return account.DatFile; else return null; } else if (selectedFile.DatFile != null) { return selectedFile.DatFile; } else if (selectedFile.Path == null) { return null; } Security.Impersonation.IImpersonationToken impersonation = null; string username = Util.Users.GetUserName(textWindowsAccount.Text); bool isCurrent = Util.Users.IsCurrentUser(username); bool userExists = isCurrent; bool wasMoved = false; string path = null; if (!isCurrent) { try { using (var user = Util.Users.GetPrincipal(username)) { userExists = user != null; } } catch { } if (userExists) { var password = Security.Credentials.GetPassword(username); while (true) { if (password == null) { using (formPassword f = new formPassword("Password for " + username)) { if (f.ShowDialog(this) == DialogResult.OK) { password = f.Password; Security.Credentials.SetPassword(username, password); } else { break; } } } try { impersonation = Security.Impersonation.Impersonate(username, Security.Credentials.GetPassword(username)); break; } catch (Win32Exception ex) { if (ex.NativeErrorCode == 1326) { password = null; continue; } break; } catch (Exception ex) { break; } } } } if (isCurrent || impersonation != null) { try { string folder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData, Environment.SpecialFolderOption.Create); if (!string.IsNullOrWhiteSpace(folder)) { folder = Path.Combine(folder, "Guild Wars 2"); if (!Directory.Exists(folder)) Directory.CreateDirectory(folder); path = Util.FileUtil.GetTemporaryFileName(folder); try { File.Move(selectedFile.Path, path); wasMoved = true; } catch { try { File.Copy(selectedFile.Path, path, true); } catch (Exception e) { throw e; } } } else { //the user exists, but the account hasn't been set up yet } } finally { if (impersonation != null) impersonation.Dispose(); } } if (datFile == null) datFile = Settings.CreateDatFile(); if (path == null) datFile.Path = Path.GetFullPath(selectedFile.Path); else { try { //now that datFile setting has been created, rename the file from its temp name string _path = Path.Combine(Path.GetDirectoryName(path), "Local." + datFile.UID + ".dat"); File.Move(path, _path); path = _path; } catch { } datFile.Path = Path.GetFullPath(path); } if (!wasMoved) { try { File.Delete(selectedFile.Path); } catch { } } return datFile; }
/// <summary> /// Updates the dat file using the master /// </summary> public static bool Create(Settings.IDatFile master, Settings.IDatFile dat) { return(Create(master).Update(dat)); }
/// <summary> /// Waits for a dat file being updated in the background to complete /// </summary> public void Wait(Settings.IDatFile dat) { ManualResetEvent waiter = null; EventHandler <Settings.IDatFile> onComplete = null; while (true) { var found = false; lock (this) { if (session != null && session.queued != null && session.queued.Contains(dat.UID)) { for (var i = session.queue.Count - 1; i >= 0; --i) { if (session.queue.Peek() == dat) { if (waiter == null) { waiter = new ManualResetEvent(false); onComplete = delegate(object o, Settings.IDatFile d) { if (d == dat) { DatComplete -= onComplete; waiter.Set(); } }; DatComplete += onComplete; } found = true; break; } session.queue.Enqueue(session.queue.Dequeue()); } } } if (waiter != null) { if (found && waiter.WaitOne(60000, false)) { waiter.Dispose(); return; } else { DatComplete -= onComplete; if (!found) { waiter.Dispose(); return; } } } else { return; } } }
private void Update(Session s, Settings.IDatFile dat) { using (var r = new BinaryReader(new BufferedStream(System.IO.File.Open(dat.Path, FileMode.Open, FileAccess.ReadWrite, FileShare.Read)))) { DatFile.Mft mft; int mftEntries; if (r.BaseStream.Length > 0) { mft = DatFile.ReadMft(r); mftEntries = mft.entries.Length; } else { mft = null; mftEntries = 0; } var blockSize = s.BlockSize; var custom = new Dictionary <int, CustomEntry>(); var entries = s.entries; var count = s.entriesCount; var remaining = s.snapshot.Count; var changed = false; var size = 0; for (var i = 0; i < mftEntries; i++) { var entry = mft.entries[i]; if (entry.baseId > 0) { if (!changed) { int fileId; if (s.snapshot.TryGetValue(entry.baseId, out fileId)) { --remaining; if (fileId != entry.fileId) { changed = true; } else { if (entry.baseId == ID_CACHE) { var e = FindEntry(s.entries, s.entriesCount, entry.baseId); if (e != null && e.size != entry.size) { changed = true; } } } continue; } } if (entry.baseId == entry.fileId && entry.baseId < 100 && entry.size > 0) { if (changed && s.snapshot.ContainsKey(entry.baseId)) { continue; } switch (entry.baseId) { case ID_LOCAL: byte[] data; int position; var build = ReadBuild(s.compressor, r.BaseStream, entry, out data, out position); if (s.build > build) { changed = true; //updating the build //note that this isn't required var b = BitConverter.GetBytes(s.build); Array.Copy(b, 0, data, position, 4); var c = new CustomEntry() { compress = true, data = data, entry = entry, index = i, length = data.Length, }; custom[entry.baseId] = c; entry.offset = long.MaxValue; entry.size = data.Length; } break; } entries[count++] = entry; size += (entry.size / blockSize + 1) * blockSize; } } } if (!changed && remaining == 0) { return; } size += ((s.entriesCount + count) * 40 / blockSize + 1) * blockSize; //add padding for entries and IDs (24 bytes per entry, 8-16 bytes per id) Array.Sort(entries, s.entriesCount, count - s.entriesCount, Comparer <DatFile.MftEntry> .Create( delegate(DatFile.MftEntry a, DatFile.MftEntry b) { return(a.offset.CompareTo(b.offset)); })); var buffer = s.buffer2; if (buffer == null || buffer.Length < size) { s.buffer2 = buffer = new byte[size + 1024 * 1024]; } var ofs = 0; var fofs = s.buffer1.Length; for (var i = s.entriesCount; i < count; i++) { var e = entries[i]; if (e.size == 0) { e.offset = 0; continue; } if (e.offset != long.MaxValue) { r.BaseStream.Position = e.offset; ReadBytes(r, buffer, ofs, e.size); } else { CustomEntry c; if (custom.TryGetValue(e.baseId, out c)) { e.size = c.WriteTo(buffer, ofs, s.compressor); } } e.offset = ofs + fofs; ofs += (e.size / blockSize + 1) * blockSize; } using (var fs = new Dat.Compression.IO.FileStream(new MemoryStream(buffer), false, true, false)) { using (var w = new BinaryWriter(fs)) { w.BaseStream.Position = ofs; //write ids for (var i = 1; i <= count; i++) { var entry = entries[i - 1]; if (entry.baseId > 0) { w.Write(entry.baseId); w.Write(i); if (entry.baseId != entry.fileId) { w.Write(entry.fileId); w.Write(i); } } } var e = entries[INDEX_IDS]; e.offset = ofs + fofs; e.size = (int)(w.BaseStream.Position - ofs); e.crc = fs.CRC; ofs += (e.size / blockSize + 1) * blockSize; e = entries[INDEX_ENTRIES]; w.BaseStream.Position = ofs; fs.ResetCRC(); //write entries header w.Write(443835981U); w.Write(0L); w.Write(count + 1); w.Write(0L); //write first set of entries for (var i = 0; i < INDEX_ENTRIES; i++) { WriteEntry(w, entries[i]); } var p0 = w.BaseStream.Position; w.BaseStream.Position += 24; //entry is written last //write remaining entries for (var i = INDEX_ENTRIES + 1; i < count; i++) { WriteEntry(w, entries[i]); } e.offset = ofs + fofs; e.size = (int)(w.BaseStream.Position - ofs); e.crc = fs.CRC; ofs += (e.size / blockSize + 1) * blockSize; s.MftOffset = e.offset; s.MftSize = e.size; w.BaseStream.Position = p0; WriteEntry(w, entries[INDEX_ENTRIES]); } } var stream = r.BaseStream; stream.Position = 0; stream.Write(s.buffer1, 0, s.buffer1.Length); stream.Write(buffer, 0, ofs); stream.SetLength(stream.Position); } }
private void DoQueue() { Session s; lock (this) { s = this.session; if (s == null || s.abort) { return; } } var q = s.queue; Settings.IDatFile dat = null; while (true) { lock (this) { if (dat != null) { s.queued.Remove(dat.UID); if (DatComplete != null) { DatComplete(this, dat); } } if (s.abort || q.Count == 0) { if (!s.abort) { session = null; if (Complete != null) { Complete(this, EventArgs.Empty); } } return; } dat = q.Dequeue(); } try { Update(s, dat); lock (this) { if (!s.abort) { dat.IsPending = false; } } } catch (Exception ex) { Util.Logging.Log(ex); } } }
private void buttonOK_Click(object sender, EventArgs e) { const int INDEX_DEFAULT = 0; const int INDEX_SHARED = 1; var accounts = GetAccounts(); byte[] gfxfile = null; var manualcount = 0; var dats = new Settings.IDatFile[2]; var gfxs = new Settings.IGfxFile[2]; var checkDat = new bool[] { true, true }; var checkGfx = new bool[] { true, true }; if (textGw2Path.TextLength > 0 && File.Exists(textGw2Path.Text)) { try { var bits = Util.FileUtil.GetExecutableBits(textGw2Path.Text); if (Environment.Is64BitOperatingSystem && bits == 32) { if (Settings.GuildWars2.Arguments.HasValue) { Settings.GuildWars2.Arguments.Value = Util.Args.AddOrReplace(Settings.GuildWars2.Arguments.Value, "32", "-32"); } else { Settings.GuildWars2.Arguments.Value = "-32"; } } Settings.GuildWars2.Path.Value = textGw2Path.Text; } catch { } } checkGfx[INDEX_DEFAULT] = Settings.GuildWars2.Path.HasValue; foreach (var a in accounts) { if (!a.HasCredentials) { ++manualcount; } } foreach (var a in accounts) { var _account = (Settings.IGw2Account)Settings.CreateAccount(Settings.AccountType.GuildWars2); var dat = INDEX_DEFAULT; var gfx = INDEX_DEFAULT; _account.Name = a.Name; if (a.HasCredentials) { _account.Email = a.Email; _account.Password = Settings.PasswordString.Create(a.Password); _account.AutologinOptions = Settings.AutologinOptions.Login | Settings.AutologinOptions.Play; dat = INDEX_SHARED; } else if (panelLogin.Enabled) { if (radioLoginRemembered.Checked) { _account.AutomaticRememberedLogin = true; dat = -1; } } if (panelGraphics.Enabled) { if (radioGraphicsShared.Checked) { gfx = INDEX_SHARED; } else { gfx = -1; } } if (dat == -1 || checkDat[dat] && dats[dat] == null) { if (dat != -1) { checkDat[dat] = false; } if (dat == INDEX_DEFAULT) { var path = Client.FileManager.GetDefaultPath(Client.FileManager.FileType.Dat); var f = dats[dat] = (Settings.IDatFile)Client.FileManager.FindFile(Client.FileManager.FileType.Dat, path); if (f == null && File.Exists(path)) { dats[dat] = f = Settings.CreateDatFile(); f.Path = path; } _account.DatFile = dats[dat]; } else { var path = CreateTempFile(); if (!string.IsNullOrEmpty(path)) { var f = Settings.CreateDatFile(); f.Path = path; if (dat != -1) { dats[dat] = f; } _account.DatFile = f; } } } else { _account.DatFile = dats[dat]; } if (gfx == -1 || checkGfx[gfx] && gfxs[gfx] == null) { if (gfx != -1) { checkGfx[gfx] = false; } if (gfx == INDEX_DEFAULT) { var path = Client.FileManager.GetDefaultPath(Client.FileManager.FileType.Gfx); var f = gfxs[gfx] = (Settings.IGfxFile)Client.FileManager.FindFile(Client.FileManager.FileType.Gfx, path); if (f == null && File.Exists(path)) { gfxs[gfx] = f = Settings.CreateGfxFile(); f.Path = path; } _account.GfxFile = gfxs[gfx]; } else { var path = CreateTempFile(); if (!string.IsNullOrEmpty(path)) { if (gfxfile == null) { gfxfile = ReadGfxData(); } if (gfxfile.Length > 0) { try { File.WriteAllBytes(path, gfxfile); } catch { } } var f = Settings.CreateGfxFile(); f.Path = path; if (gfx != -1) { gfxs[gfx] = f; } _account.GfxFile = f; } } } else { _account.GfxFile = gfxs[gfx]; } //note some accounts may be given null dat/gfx files - these will be automatically set on launch to the default files used by gw2 } if (radioAddonsAuto.Checked || radioAddonsManual.Checked) { var o = Settings.LocalizeAccountExecutionOptions.Enabled; if (panelDirectUpdates.Enabled && radioDirectUpdateYes.Checked) { o |= Settings.LocalizeAccountExecutionOptions.OnlyIncludeBinFolders; } if (radioAddonsAuto.Checked) { o |= Settings.LocalizeAccountExecutionOptions.AutoSync | Settings.LocalizeAccountExecutionOptions.AutoSyncDeleteUnknowns; } Settings.GuildWars2.LocalizeAccountExecution.Value = o; } if (panelDirectUpdates.Enabled && radioDirectUpdateYes.Checked) { Settings.GuildWars2.DatUpdaterEnabled.Value = true; Settings.GuildWars2.UseCustomGw2Cache.Value = true; } this.DialogResult = System.Windows.Forms.DialogResult.OK; this.Close(); }