-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Dynamically reads .replayinfo Dynamically shows teammates
- Loading branch information
1 parent
8505ced
commit adf94f7
Showing
66 changed files
with
2,250 additions
and
12,082 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<Weavers> | ||
<Costura /> | ||
</Weavers> |
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file was deleted.
Oops, something went wrong.
Binary file not shown.
Binary file not shown.
10,760 changes: 0 additions & 10,760 deletions
10,760
PUBG_Replay_Manager/bin/Release/Newtonsoft.Json.xml
This file was deleted.
Oops, something went wrong.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,297 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Diagnostics; | ||
using System.Globalization; | ||
using System.IO; | ||
using System.IO.Compression; | ||
using System.Reflection; | ||
using System.Runtime.InteropServices; | ||
using System.Security.AccessControl; | ||
using System.Security.Cryptography; | ||
using System.Security.Principal; | ||
using System.Text; | ||
using System.Threading; | ||
|
||
static class Common | ||
{ | ||
private const int DelayUntilReboot = 4; | ||
|
||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] | ||
static extern bool MoveFileEx(string lpExistingFileName, string lpNewFileName, int dwFlags); | ||
|
||
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)] | ||
static extern IntPtr LoadLibrary(string dllToLoad); | ||
|
||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] | ||
[return: MarshalAs(UnmanagedType.Bool)] | ||
static extern bool SetDllDirectory(string lpPathName); | ||
|
||
[Conditional("DEBUG")] | ||
public static void Log(string format, params object[] args) | ||
{ | ||
// Should this be trace? | ||
Debug.WriteLine("=== COSTURA === " + string.Format(format, args)); | ||
} | ||
|
||
static void CopyTo(Stream source, Stream destination) | ||
{ | ||
var array = new byte[81920]; | ||
int count; | ||
while ((count = source.Read(array, 0, array.Length)) != 0) | ||
{ | ||
destination.Write(array, 0, count); | ||
} | ||
} | ||
|
||
static void CreateDirectory(string tempBasePath) | ||
{ | ||
if (!Directory.Exists(tempBasePath)) | ||
{ | ||
Directory.CreateDirectory(tempBasePath); | ||
} | ||
} | ||
|
||
static byte[] ReadStream(Stream stream) | ||
{ | ||
var data = new Byte[stream.Length]; | ||
stream.Read(data, 0, data.Length); | ||
return data; | ||
} | ||
|
||
public static string CalculateChecksum(string filename) | ||
{ | ||
using (var fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete)) | ||
using (var bs = new BufferedStream(fs)) | ||
using (var sha1 = new SHA1CryptoServiceProvider()) | ||
{ | ||
var hash = sha1.ComputeHash(bs); | ||
var formatted = new StringBuilder(2 * hash.Length); | ||
foreach (var b in hash) | ||
{ | ||
formatted.AppendFormat("{0:X2}", b); | ||
} | ||
return formatted.ToString(); | ||
} | ||
} | ||
|
||
public static Assembly ReadExistingAssembly(AssemblyName name) | ||
{ | ||
var currentDomain = AppDomain.CurrentDomain; | ||
var assemblies = currentDomain.GetAssemblies(); | ||
foreach (var assembly in assemblies) | ||
{ | ||
var currentName = assembly.GetName(); | ||
if (string.Equals(currentName.Name, name.Name, StringComparison.InvariantCultureIgnoreCase) && | ||
string.Equals(CultureToString(currentName.CultureInfo), CultureToString(name.CultureInfo), StringComparison.InvariantCultureIgnoreCase)) | ||
{ | ||
Log("Assembly '{0}' already loaded, returning existing assembly", assembly.FullName); | ||
|
||
return assembly; | ||
} | ||
} | ||
return null; | ||
} | ||
|
||
static string CultureToString(CultureInfo culture) | ||
{ | ||
if (culture == null) | ||
return ""; | ||
|
||
return culture.Name; | ||
} | ||
|
||
public static Assembly ReadFromDiskCache(string tempBasePath, AssemblyName requestedAssemblyName) | ||
{ | ||
var name = requestedAssemblyName.Name.ToLowerInvariant(); | ||
|
||
if (requestedAssemblyName.CultureInfo != null && !String.IsNullOrEmpty(requestedAssemblyName.CultureInfo.Name)) | ||
name = $"{requestedAssemblyName.CultureInfo.Name}.{name}"; | ||
|
||
var bittyness = IntPtr.Size == 8 ? "64" : "32"; | ||
var assemblyTempFilePath = Path.Combine(tempBasePath, String.Concat(name, ".dll")); | ||
if (File.Exists(assemblyTempFilePath)) | ||
{ | ||
return Assembly.LoadFile(assemblyTempFilePath); | ||
} | ||
assemblyTempFilePath = Path.ChangeExtension(assemblyTempFilePath, "exe"); | ||
if (File.Exists(assemblyTempFilePath)) | ||
{ | ||
return Assembly.LoadFile(assemblyTempFilePath); | ||
} | ||
assemblyTempFilePath = Path.Combine(Path.Combine(tempBasePath, bittyness), String.Concat(name, ".dll")); | ||
if (File.Exists(assemblyTempFilePath)) | ||
{ | ||
return Assembly.LoadFile(assemblyTempFilePath); | ||
} | ||
assemblyTempFilePath = Path.ChangeExtension(assemblyTempFilePath, "exe"); | ||
if (File.Exists(assemblyTempFilePath)) | ||
{ | ||
return Assembly.LoadFile(assemblyTempFilePath); | ||
} | ||
return null; | ||
} | ||
|
||
public static Assembly ReadFromEmbeddedResources(Dictionary<string, string> assemblyNames, Dictionary<string, string> symbolNames, AssemblyName requestedAssemblyName) | ||
{ | ||
var name = requestedAssemblyName.Name.ToLowerInvariant(); | ||
|
||
if (requestedAssemblyName.CultureInfo != null && !String.IsNullOrEmpty(requestedAssemblyName.CultureInfo.Name)) | ||
name = $"{requestedAssemblyName.CultureInfo.Name}.{name}"; | ||
|
||
byte[] assemblyData; | ||
using (var assemblyStream = LoadStream(assemblyNames, name)) | ||
{ | ||
if (assemblyStream == null) | ||
{ | ||
return null; | ||
} | ||
assemblyData = ReadStream(assemblyStream); | ||
} | ||
|
||
using (var pdbStream = LoadStream(symbolNames, name)) | ||
{ | ||
if (pdbStream != null) | ||
{ | ||
var pdbData = ReadStream(pdbStream); | ||
return Assembly.Load(assemblyData, pdbData); | ||
} | ||
} | ||
|
||
return Assembly.Load(assemblyData); | ||
} | ||
|
||
static Stream LoadStream(Dictionary<string, string> resourceNames, string name) | ||
{ | ||
string value; | ||
if (resourceNames.TryGetValue(name, out value)) | ||
return LoadStream(value); | ||
|
||
return null; | ||
} | ||
|
||
static Stream LoadStream(string fullname) | ||
{ | ||
var executingAssembly = Assembly.GetExecutingAssembly(); | ||
|
||
if (fullname.EndsWith(".compressed")) | ||
{ | ||
using (var stream = executingAssembly.GetManifestResourceStream(fullname)) | ||
using (var compressStream = new DeflateStream(stream, CompressionMode.Decompress)) | ||
{ | ||
var memStream = new MemoryStream(); | ||
CopyTo(compressStream, memStream); | ||
memStream.Position = 0; | ||
return memStream; | ||
} | ||
} | ||
|
||
return executingAssembly.GetManifestResourceStream(fullname); | ||
} | ||
|
||
// Mutex code from http://stackoverflow.com/questions/229565/what-is-a-good-pattern-for-using-a-global-mutex-in-c | ||
public static void PreloadUnmanagedLibraries(string hash, string tempBasePath, IEnumerable<string> libs, Dictionary<string, string> checksums) | ||
{ | ||
var mutexId = $"Global\\Costura{hash}"; | ||
|
||
using (var mutex = new Mutex(false, mutexId)) | ||
{ | ||
var allowEveryoneRule = new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), MutexRights.FullControl, AccessControlType.Allow); | ||
var securitySettings = new MutexSecurity(); | ||
securitySettings.AddAccessRule(allowEveryoneRule); | ||
mutex.SetAccessControl(securitySettings); | ||
|
||
var hasHandle = false; | ||
try | ||
{ | ||
try | ||
{ | ||
hasHandle = mutex.WaitOne(60000, false); | ||
if (hasHandle == false) | ||
throw new TimeoutException("Timeout waiting for exclusive access"); | ||
} | ||
catch (AbandonedMutexException) | ||
{ | ||
hasHandle = true; | ||
} | ||
|
||
var bittyness = IntPtr.Size == 8 ? "64" : "32"; | ||
CreateDirectory(Path.Combine(tempBasePath, bittyness)); | ||
InternalPreloadUnmanagedLibraries(tempBasePath, libs, checksums); | ||
} | ||
finally | ||
{ | ||
if (hasHandle) | ||
mutex.ReleaseMutex(); | ||
} | ||
} | ||
} | ||
|
||
static void InternalPreloadUnmanagedLibraries(string tempBasePath, IEnumerable<string> libs, Dictionary<string, string> checksums) | ||
{ | ||
string name; | ||
|
||
foreach (var lib in libs) | ||
{ | ||
name = ResourceNameToPath(lib); | ||
|
||
var assemblyTempFilePath = Path.Combine(tempBasePath, name); | ||
|
||
if (File.Exists(assemblyTempFilePath)) | ||
{ | ||
var checksum = CalculateChecksum(assemblyTempFilePath); | ||
if (checksum != checksums[lib]) | ||
File.Delete(assemblyTempFilePath); | ||
} | ||
|
||
if (!File.Exists(assemblyTempFilePath)) | ||
{ | ||
using (var copyStream = LoadStream(lib)) | ||
using (var assemblyTempFile = File.OpenWrite(assemblyTempFilePath)) | ||
{ | ||
CopyTo(copyStream, assemblyTempFile); | ||
} | ||
if (!MoveFileEx(assemblyTempFilePath, null, DelayUntilReboot)) | ||
{ | ||
//TODO: for now we ignore the return value. | ||
} | ||
} | ||
} | ||
|
||
SetDllDirectory(tempBasePath); | ||
|
||
foreach (var lib in libs) | ||
{ | ||
name = ResourceNameToPath(lib); | ||
|
||
if (name.EndsWith(".dll")) | ||
{ | ||
var assemblyTempFilePath = Path.Combine(tempBasePath, name); | ||
|
||
LoadLibrary(assemblyTempFilePath); | ||
} | ||
} | ||
} | ||
|
||
static string ResourceNameToPath(string lib) | ||
{ | ||
var bittyness = IntPtr.Size == 8 ? "64" : "32"; | ||
|
||
var name = lib; | ||
|
||
if (lib.StartsWith(String.Concat("costura", bittyness, "."))) | ||
{ | ||
name = Path.Combine(bittyness, lib.Substring(10)); | ||
} | ||
else if (lib.StartsWith("costura.")) | ||
{ | ||
name = lib.Substring(8); | ||
} | ||
|
||
if (name.EndsWith(".compressed")) | ||
{ | ||
name = name.Substring(0, name.Length - 11); | ||
} | ||
|
||
return name; | ||
} | ||
} |
Binary file added
BIN
+238 KB
...g/Costura/2FB0BE100DE03680FC4309C9FA5A29E69397A980.costura.newtonsoft.json.dll.compressed
Binary file not shown.
Binary file modified
BIN
+615 Bytes
(110%)
PUBG_Replay_Manager/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache
Binary file not shown.
Oops, something went wrong.