diff --git a/.gitmodules b/.gitmodules index 8fb51acd..6661a5b6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,9 +1,9 @@ -[submodule "BurnOutSharp/External/hllib"] - path = BurnOutSharp/External/hllib - url = https://github.com/RavuAlHemio/hllib.git [submodule "BurnOutSharp/External/stormlibsharp"] path = BurnOutSharp/External/stormlibsharp url = https://github.com/robpaveza/stormlibsharp.git [submodule "BurnOutSharp/External/WixToolset"] path = WixToolset url = https://github.com/wixtoolset/Dtf.git +[submodule "HLLibSharp"] + path = HLLibSharp + url = https://github.com/mnadareski/HLLibSharp diff --git a/BurnOutSharp.sln b/BurnOutSharp.sln index c182ff06..ad744faa 100644 --- a/BurnOutSharp.sln +++ b/BurnOutSharp.sln @@ -14,16 +14,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution README.md = README.md EndProjectSection EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "WixToolset", "WixToolset", "{09D405CA-CF15-4929-8408-C970F0656C62}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{182E02A8-5E8E-4140-9C9B-61049C33E921}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolset.Dtf.WindowsInstaller", "WixToolset\src\WixToolset.Dtf.WindowsInstaller\WixToolset.Dtf.WindowsInstaller.csproj", "{B3537EB7-CEF6-4D90-A041-47626442A656}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolset.Dtf.Compression", "WixToolset\src\WixToolset.Dtf.Compression\WixToolset.Dtf.Compression.csproj", "{CC76B5EC-976E-4063-8561-1CD50693A034}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolset.Dtf.Compression.Cab", "WixToolset\src\WixToolset.Dtf.Compression.Cab\WixToolset.Dtf.Compression.Cab.csproj", "{AD836467-FC28-46A7-966D-4FDD0F72019B}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HLLibSharp", "HLLibSharp\HLLibSharp\HLLibSharp.csproj", "{14E9764A-A8BF-44C0-A1A8-2C95EA307040}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -50,16 +48,14 @@ Global {AD836467-FC28-46A7-966D-4FDD0F72019B}.Debug|Any CPU.Build.0 = Debug|Any CPU {AD836467-FC28-46A7-966D-4FDD0F72019B}.Release|Any CPU.ActiveCfg = Release|Any CPU {AD836467-FC28-46A7-966D-4FDD0F72019B}.Release|Any CPU.Build.0 = Release|Any CPU + {14E9764A-A8BF-44C0-A1A8-2C95EA307040}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {14E9764A-A8BF-44C0-A1A8-2C95EA307040}.Debug|Any CPU.Build.0 = Debug|Any CPU + {14E9764A-A8BF-44C0-A1A8-2C95EA307040}.Release|Any CPU.ActiveCfg = Release|Any CPU + {14E9764A-A8BF-44C0-A1A8-2C95EA307040}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {182E02A8-5E8E-4140-9C9B-61049C33E921} = {09D405CA-CF15-4929-8408-C970F0656C62} - {B3537EB7-CEF6-4D90-A041-47626442A656} = {182E02A8-5E8E-4140-9C9B-61049C33E921} - {CC76B5EC-976E-4063-8561-1CD50693A034} = {182E02A8-5E8E-4140-9C9B-61049C33E921} - {AD836467-FC28-46A7-966D-4FDD0F72019B} = {182E02A8-5E8E-4140-9C9B-61049C33E921} - EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {0B343DD2-8852-47B0-9647-DFCFBEDF933C} EndGlobalSection diff --git a/BurnOutSharp/BurnOutSharp.csproj b/BurnOutSharp/BurnOutSharp.csproj index f70e3321..487eb05d 100644 --- a/BurnOutSharp/BurnOutSharp.csproj +++ b/BurnOutSharp/BurnOutSharp.csproj @@ -58,6 +58,7 @@ + diff --git a/BurnOutSharp/External/hllib b/BurnOutSharp/External/hllib deleted file mode 160000 index 2063e3e0..00000000 --- a/BurnOutSharp/External/hllib +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2063e3e0cdc2e8eece472c097d11676f4c67aba3 diff --git a/BurnOutSharp/FileType/Valve.cs b/BurnOutSharp/FileType/Valve.cs index 9b386d1a..554ca85b 100644 --- a/BurnOutSharp/FileType/Valve.cs +++ b/BurnOutSharp/FileType/Valve.cs @@ -1,10 +1,10 @@ using System; using System.Collections.Concurrent; -using System.Collections.Generic; using System.IO; -using System.Runtime.InteropServices; using BurnOutSharp.Interfaces; using BurnOutSharp.Tools; +using HLLib.Directory; +using HLLib.Packages; namespace BurnOutSharp.FileType { @@ -13,31 +13,7 @@ namespace BurnOutSharp.FileType /// public bool ShouldScan(byte[] magic) { - // Disabling scanning due to errors with HLLib - // TODO: Port HLLib to C# to avoid P/Invoke issues - return false; - - // GCF - if (magic.StartsWith(new byte?[] { 0x01, 0x00, 0x00, 0x00 })) - return true; - - // PAK - if (magic.StartsWith(new byte?[] { 0x50, 0x41, 0x43, 0x4b })) - return true; - - // SGA - if (magic.StartsWith(new byte?[] { 0x5f, 0x41, 0x52, 0x43, 0x48, 0x49, 0x56, 0x45 })) - return true; - - // VPK - if (magic.StartsWith(new byte?[] { 0x55, 0xaa, 0x12, 0x34 })) - return true; - - // WAD - if (magic.StartsWith(new byte?[] { 0x57, 0x41, 0x44, 0x33 })) - return true; - - return false; + return Package.GetPackageType(magic) != PackageType.HL_PACKAGE_NONE; } /// @@ -62,16 +38,27 @@ namespace BurnOutSharp.FileType string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); Directory.CreateDirectory(tempPath); - string[] args = new string[] - { - "-p", file, - "-x", "root", - "-x", "'extract .'", - "-x", "exit", - "-d", tempPath, - }; + // Get the package type + byte[] magic = stream.ReadBytes(16); + PackageType packageType = Package.GetPackageType(magic); + if (packageType == PackageType.HL_PACKAGE_NONE) + return null; - Run(args); + // Create a new package from the file + var pkg = Package.CreatePackage(packageType); + FileModeFlags mode = FileModeFlags.HL_MODE_READ | FileModeFlags.HL_MODE_WRITE | FileModeFlags.HL_MODE_NO_FILEMAPPING; + bool opened = pkg.Open(file, mode, overwriteFiles: true); + if (!opened) + return null; + + // Create the root directory + var rootDirectory = pkg.GetRoot(); + + // Extract all files + rootDirectory.Extract(tempPath, readEncrypted: true, overwrite: true); + + // Close the package explicitly + pkg.Close(); // Collect and format all found protections var protections = scanner.GetProtections(tempPath); @@ -92,1094 +79,5 @@ namespace BurnOutSharp.FileType return null; } - - // This code was copied over from HLExtract.NET\Program.cs - // It was copied over due to access issues with the existing class. - // This is the only part that should be kept in sync manually - #region HLExtract.Net Main Program - - private static bool bSilent = false; - private static bool bPause = true; - private static string sDestination = string.Empty; - - private static int Run(string[] args) - { - // Arguments. - string sPackage = string.Empty; - List Commands = new List(); - string sNCFRootPath = string.Empty; - - bool bFileMapping = false; - bool bQuickFileMapping = false; - bool bVolatileAccess = false; - bool bWriteAccess = false; - bool bOverwriteFiles = true; - - // Package stuff. - HLLib.HLPackageType ePackageType = HLLib.HLPackageType.HL_PACKAGE_NONE; - uint uiPackage = HLLib.HL_ID_INVALID; - uint uiMode = (uint)HLLib.HLFileMode.HL_MODE_INVALID; - - if(HLLib.hlGetUnsignedInteger(HLLib.HLOption.HL_VERSION) < HLLib.HL_VERSION_NUMBER) - { - Console.WriteLine("Wrong HLLib version: v{0}.", HLLib.hlGetString(HLLib.HLOption.HL_VERSION)); - return 1; - } - - // Process switches. - if(args.Length == 1) - { - sPackage = args[0]; - } - else - { - for(int i = 0; i < args.Length; i++) - { - if(string.Equals(args[i], "-p", StringComparison.CurrentCultureIgnoreCase) || string.Equals(args[i], "--package", StringComparison.CurrentCultureIgnoreCase)) - { - if(sPackage.Length == 0 && i + 1 < args.Length) - { - sPackage = args[++i]; - } - else - { - return 2; - } - } - else if(string.Equals(args[i], "-d", StringComparison.CurrentCultureIgnoreCase) || string.Equals(args[i], "--dest", StringComparison.CurrentCultureIgnoreCase)) - { - if(sDestination.Length == 0 && i + 1 < args.Length) - { - sDestination = args[++i]; - } - else - { - return 2; - } - } - else if(string.Equals(args[i], "-x", StringComparison.CurrentCultureIgnoreCase) || string.Equals(args[i], "--execute", StringComparison.CurrentCultureIgnoreCase)) - { - if(sDestination.Length == 0 && i + 1 < args.Length) - { - Commands.Add(args[++i]); - } - else - { - return 2; - } - } - else if(string.Equals(args[i], "-n", StringComparison.CurrentCultureIgnoreCase) || string.Equals(args[i], "--ncfroot", StringComparison.CurrentCultureIgnoreCase)) - { - if(sNCFRootPath.Length == 0 && i + 1 < args.Length) - { - sNCFRootPath = args[++i]; - } - else - { - return 2; - } - } - else if(string.Equals(args[i], "-s", StringComparison.CurrentCultureIgnoreCase) || string.Equals(args[i], "--silent", StringComparison.CurrentCultureIgnoreCase)) - { - bSilent = true; - } - else if(string.Equals(args[i], "-u", StringComparison.CurrentCultureIgnoreCase) || string.Equals(args[i], "--no-pause", StringComparison.CurrentCultureIgnoreCase)) - { - bPause = false; - } - else if(string.Equals(args[i], "-m", StringComparison.CurrentCultureIgnoreCase) || string.Equals(args[i], "--filemapping", StringComparison.CurrentCultureIgnoreCase)) - { - bFileMapping = true; - } - else if(string.Equals(args[i], "-q", StringComparison.CurrentCultureIgnoreCase) || string.Equals(args[i], "--quick-filemapping", StringComparison.CurrentCultureIgnoreCase)) - { - bFileMapping = true; - bQuickFileMapping = true; - } - else if(string.Equals(args[i], "-v", StringComparison.CurrentCultureIgnoreCase) || string.Equals(args[i], "--volatile", StringComparison.CurrentCultureIgnoreCase)) - { - bVolatileAccess = true; - } - else if(string.Equals(args[i], "-w", StringComparison.CurrentCultureIgnoreCase) || string.Equals(args[i], "--write", StringComparison.CurrentCultureIgnoreCase)) - { - bWriteAccess = true; - } - else if(string.Equals(args[i], "-o", StringComparison.CurrentCultureIgnoreCase) || string.Equals(args[i], "--no-overwrite", StringComparison.CurrentCultureIgnoreCase)) - { - bOverwriteFiles = false; - } - else - { - return 2; - } - } - } - - // Make sure we have something to do. - if(sPackage.Length == 0) - { - return 2; - } - - // If the destination directory is not specified, make it the input directory. - if(sDestination.Length == 0) - { - int iIndex = sPackage.LastIndexOfAny(new char[]{'\\', '/'}); - if(iIndex != -1) - { - sDestination = sPackage.Substring(0, iIndex + 1); - } - } - - HLLib.hlInitialize(); - - // Keep the delegates alive so they don't get garbage collected. - HLLib.HLExtractItemStartProc HLExtractItemStartProc = new HLLib.HLExtractItemStartProc(ExtractItemStartCallback); - HLLib.HLExtractItemEndProc HLExtractItemEndProc = new HLLib.HLExtractItemEndProc(ExtractItemEndCallback); - HLLib.HLExtractFileProgressProc HLExtractFileProgressProc = new HLLib.HLExtractFileProgressProc(FileProgressCallback); - HLLib.HLValidateFileProgressProc HLValidateFileProgressProc = new HLLib.HLValidateFileProgressProc(FileProgressCallback); - HLLib.HLDefragmentFileProgressExProc HLDefragmentFileProgressProc = new HLLib.HLDefragmentFileProgressExProc(DefragmentProgressCallback); - - HLLib.hlSetBoolean(HLLib.HLOption.HL_OVERWRITE_FILES, bOverwriteFiles); - HLLib.hlSetVoid(HLLib.HLOption.HL_PROC_EXTRACT_ITEM_START, Marshal.GetFunctionPointerForDelegate(HLExtractItemStartProc)); - HLLib.hlSetVoid(HLLib.HLOption.HL_PROC_EXTRACT_ITEM_END, Marshal.GetFunctionPointerForDelegate(HLExtractItemEndProc)); - HLLib.hlSetVoid(HLLib.HLOption.HL_PROC_EXTRACT_FILE_PROGRESS, Marshal.GetFunctionPointerForDelegate(HLExtractFileProgressProc)); - HLLib.hlSetVoid(HLLib.HLOption.HL_PROC_VALIDATE_FILE_PROGRESS, Marshal.GetFunctionPointerForDelegate(HLValidateFileProgressProc)); - HLLib.hlSetVoid(HLLib.HLOption.HL_PROC_DEFRAGMENT_PROGRESS_EX, Marshal.GetFunctionPointerForDelegate(HLDefragmentFileProgressProc)); - - // Get the package type from the filename extension. - ePackageType = HLLib.hlGetPackageTypeFromName(sPackage); - - // If the above fails, try getting the package type from the data at the start of the file. - if(ePackageType == HLLib.HLPackageType.HL_PACKAGE_NONE && File.Exists(sPackage)) - { - FileStream Reader = null; - try - { - byte[] lpBuffer = new byte[HLLib.HL_DEFAULT_PACKAGE_TEST_BUFFER_SIZE]; - Reader = new FileStream(sPackage, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); - int iBytesRead = Reader.Read(lpBuffer, 0, lpBuffer.Length); - if(iBytesRead > 0) - { - IntPtr lpBytesRead = Marshal.AllocHGlobal(iBytesRead); - try - { - Marshal.Copy(lpBuffer, 0, lpBytesRead, iBytesRead); - ePackageType = HLLib.hlGetPackageTypeFromMemory(lpBytesRead, (uint)iBytesRead); - } - finally - { - Marshal.FreeHGlobal(lpBytesRead); - } - } - } - finally - { - if(Reader != null) - { - Reader.Close(); - } - } - } - - if(ePackageType == HLLib.HLPackageType.HL_PACKAGE_NONE) - { - Console.WriteLine("Error loading {0}:", sPackage); - Console.WriteLine("Unsupported package type."); - - HLLib.hlShutdown(); - return 3; - } - - // Create a package element, the element is allocated by the library and cleaned - // up by the library. An ID is generated which must be bound to apply operations - // to the package. - if(!HLLib.hlCreatePackage(ePackageType, out uiPackage)) - { - Console.WriteLine("Error loading {0}:", sPackage); - Console.WriteLine(HLLib.hlGetString(HLLib.HLOption.HL_ERROR_SHORT_FORMATED)); - - HLLib. hlShutdown(); - return 3; - } - - HLLib.hlBindPackage(uiPackage); - - uiMode = (uint)HLLib.HLFileMode.HL_MODE_READ; - uiMode |= !bFileMapping ? (uint)HLLib.HLFileMode.HL_MODE_NO_FILEMAPPING : 0; - uiMode |= bQuickFileMapping ? (uint)HLLib.HLFileMode.HL_MODE_QUICK_FILEMAPPING : 0; - uiMode |= bVolatileAccess ? (uint)HLLib.HLFileMode.HL_MODE_VOLATILE : 0; - uiMode |= bWriteAccess ? (uint)HLLib.HLFileMode.HL_MODE_WRITE : 0; - - // Open the package. - // Of the above modes, only HL_MODE_READ is required. HL_MODE_WRITE is present - // only for future use. File mapping is recommended as an efficient way to load - // packages. Quick file mapping maps the entire file (instead of bits as they are - // needed) and thus should only be used in Windows 2000 and up (older versions of - // Windows have poor virtual memory management which means large files won't be able - // to find a continues block and will fail to load). Volatile access allows HLLib - // to share files with other applications that have those file open for writing. - // This is useful for, say, loading .gcf files while Steam is running. - if(!HLLib.hlPackageOpenFile(sPackage, uiMode)) - { - Console.WriteLine("Error loading {0}:", sPackage); - Console.WriteLine(HLLib.hlGetString(HLLib.HLOption.HL_ERROR_SHORT_FORMATED)); - - HLLib. hlShutdown(); - return 3; - } - - // If we have a .ncf file, the package file data is stored externally. In order to - // validate the file data etc., HLLib needs to know where to look. Tell it where. - if(ePackageType == HLLib.HLPackageType.HL_PACKAGE_NCF && sNCFRootPath.Length > 0) - { - HLLib.hlNCFFileSetRootPath(sNCFRootPath); - } - - if(!bSilent) - Console.WriteLine("{0} opened.", sPackage); - - // Interactive console mode. - EnterConsole(uiPackage, Commands); - - // Close the package. - HLLib.hlPackageClose(); - - if(!bSilent) - Console.WriteLine("{0} closed.", sPackage); - - // Free up the allocated memory. - HLLib.hlDeletePackage(uiPackage); - - HLLib.hlShutdown(); - - return 0; - } - - private static readonly uint MAX_PATH_SIZE = 512; - - private static string GetPath(IntPtr pItem) - { - string sPath = string.Empty; - IntPtr lpPath = IntPtr.Zero; - try - { - lpPath = Marshal.AllocHGlobal((int)MAX_PATH_SIZE); - HLLib.hlItemGetPath(pItem, lpPath, MAX_PATH_SIZE); - sPath = Marshal.PtrToStringAnsi(lpPath); - } - finally - { - if(lpPath != IntPtr.Zero) - { - Marshal.FreeHGlobal(lpPath); - } - } - return sPath; - } - -#region Progress Callbacks - private static uint uiProgressLast; - - private static void ProgressStart() - { - uiProgressLast = 0; - Console.Write("0%"); - } - - private static void ProgressUpdate(UInt64 uiBytesDone, UInt64 uiBytesTotal) - { - if(!bSilent) - { - uint uiProgress = uiBytesTotal == 0 ? 100 : (uint)(uiBytesDone * 100 / uiBytesTotal); - while(uiProgress >= uiProgressLast + 10) - { - uiProgressLast += 10; - if(uiProgressLast == 100) - { - Console.Write("100% "); - } - else if(uiProgressLast == 50) - { - Console.Write("50%"); - } - else - { - Console.Write("."); - } - } - } - } - - private static void ExtractItemStartCallback(IntPtr pItem) - { - if(!bSilent) - { - if(HLLib.hlItemGetType(pItem) == HLLib.HLDirectoryItemType.HL_ITEM_FILE) - { - Console.Write(" Extracting {0}: ", HLLib.hlItemGetName(pItem)); - ProgressStart(); - } - else - { - Console.WriteLine(" Extracting {0}:", HLLib.hlItemGetName(pItem)); - } - } - } - - private static void FileProgressCallback(IntPtr pFile, uint uiBytesExtracted, uint uiBytesTotal, ref bool pCancel) - { - ProgressUpdate((UInt64)uiBytesExtracted, (UInt64)uiBytesTotal); - } - - private static void ExtractItemEndCallback(IntPtr pItem, bool bSuccess) - { - if(bSuccess) - { - if(!bSilent) - { - uint uiSize = 0; - HLLib.hlItemGetSize(pItem, out uiSize); - if(HLLib.hlItemGetType(pItem) == HLLib.HLDirectoryItemType.HL_ITEM_FILE) - { - Console.WriteLine("OK ({0} B)", uiSize); - } - else - { - Console.WriteLine(" Done {0}: OK ({1} B)", HLLib.hlItemGetName(pItem), uiSize); - } - } - } - else - { - if(!bSilent) - { - if(HLLib.hlItemGetType(pItem) == HLLib.HLDirectoryItemType.HL_ITEM_FILE) - { - Console.WriteLine("Errored"); - Console.WriteLine(" {0}", HLLib.hlGetString(HLLib.HLOption.HL_ERROR_SHORT_FORMATED)); - } - else - { - Console.WriteLine(" Done {0}: Errored", HLLib.hlItemGetName(pItem)); - } - } - else - { - if(HLLib.hlItemGetType(pItem) == HLLib.HLDirectoryItemType.HL_ITEM_FILE) - { - Console.WriteLine(" Error extracting {0}:", GetPath(pItem)); - Console.WriteLine(" {0}", HLLib.hlGetString(HLLib.HLOption.HL_ERROR_SHORT_FORMATED)); - } - else - { - Console.WriteLine(" Error extracting {0}.", GetPath(pItem)); - } - } - } - } - - private static void DefragmentProgressCallback(IntPtr pFile, uint uiFilesDefragmented, uint uiFilesTotal, UInt64 uiBytesDefragmented, UInt64 uiBytesTotal, ref bool pCancel) - { - ProgressUpdate(uiBytesDefragmented, uiBytesTotal); - } -#endregion - - private static readonly string[] ValidationNames = new string[] { "OK", "Assumed OK", "Incomplete", "Corrupt", "Canceled", "Error" }; - - private static string GetValidation(HLLib.HLValidation eValidation) - { - if(eValidation >= HLLib.HLValidation.HL_VALIDATES_OK && eValidation <= HLLib.HLValidation.HL_VALIDATES_ERROR) - { - return ValidationNames[(uint)eValidation]; - } - return string.Empty; - } - - private static HLLib.HLValidation Validate(IntPtr pItem) - { - HLLib.HLValidation eValidation = HLLib.HLValidation.HL_VALIDATES_OK, eTest; - - switch(HLLib.hlItemGetType(pItem)) - { - case HLLib.HLDirectoryItemType.HL_ITEM_FOLDER: - if(!bSilent) - { - Console.WriteLine(" Validating {0}:", HLLib.hlItemGetName(pItem)); - } - - uint uiItemCount = HLLib.hlFolderGetCount(pItem); - for(uint i = 0; i < uiItemCount; i++) - { - eTest = Validate(HLLib.hlFolderGetItem(pItem, i)); - if(eTest > eValidation) - { - eValidation = eTest; - } - } - - if(!bSilent) - { - Console.WriteLine(" Done {0}: {1}", HLLib.hlItemGetName(pItem), GetValidation(eValidation)); - } - break; - case HLLib.HLDirectoryItemType.HL_ITEM_FILE: - if(!bSilent) - { - Console.Write(" Validating {0}: ", HLLib.hlItemGetName(pItem)); - ProgressStart(); - } - - eValidation = HLLib.hlFileGetValidation(pItem); - - if(bSilent) - { - switch(eValidation) - { - case HLLib.HLValidation.HL_VALIDATES_INCOMPLETE: - case HLLib.HLValidation.HL_VALIDATES_CORRUPT: - Console.WriteLine(" Validating {0}: {1}", GetPath(pItem), GetValidation(eValidation)); - break; - } - } - else - { - Console.WriteLine(GetValidation(eValidation)); - } - break; - } - - return eValidation; - } - - private static void EnterConsole(uint uiPackage, List Commands) - { - IntPtr pItem = HLLib.hlPackageGetRoot(); - - while(true) - { - string sLine; - if(Commands.Count > 0) - { - sLine = Commands[0].Trim(); - - Console.WriteLine("{0}>{1}", HLLib.hlItemGetName(pItem), sLine); - Commands.RemoveAt(0); - } - else - { - // Command prompt. - Console.Write("{0}>", HLLib.hlItemGetName(pItem)); - - // Get and parse line. -- Commented out because we don't want it to read anything in automatic mode - //sLine = Console.ReadLine().Trim(); - sLine = null; - } - if(sLine == null) - { - break; - } - - int iIndex; - for(iIndex = 0; iIndex < sLine.Length; iIndex++) - { - if(!Char.IsLetter(sLine[iIndex])) - { - break; - } - } - - string sCommand, sArgument; - if(iIndex == sLine.Length) - { - sCommand = sLine; - sArgument = string.Empty; - } - else - { - sCommand = sLine.Substring(0, iIndex).TrimEnd(); - sArgument = sLine.Substring(iIndex).TrimStart(); - } - - // Cycle through commands. - - // - // Directory listing. - // Good example of CDirectoryItem::GetType(). - // - if(String.Equals(sCommand, "dir", StringComparison.CurrentCultureIgnoreCase)) - { - uint uiItemCount = HLLib.hlFolderGetCount(pItem); - uint uiFolderCount = 0, uiFileCount = 0; - - Console.WriteLine("Directory of {0}:", GetPath(pItem)); - - Console.WriteLine(); - - if(sArgument.Length == 0) - { - // List all items in the current folder. - for(uint i = 0; i < uiItemCount; i++) - { - IntPtr pSubItem = HLLib.hlFolderGetItem(pItem, i); - if(HLLib.hlItemGetType(pSubItem) == HLLib.HLDirectoryItemType.HL_ITEM_FOLDER) - { - uiFolderCount++; - Console.WriteLine(" <{0}>", HLLib.hlItemGetName(pSubItem)); - } - else if(HLLib.hlItemGetType(pSubItem) == HLLib.HLDirectoryItemType.HL_ITEM_FILE) - { - uiFileCount++; - Console.WriteLine(" {0}", HLLib.hlItemGetName(pSubItem)); - } - } - } - else - { - IntPtr pSubItem = HLLib.hlFolderFindFirst(pItem, sArgument, HLLib.HLFindType.HL_FIND_ALL | HLLib.HLFindType.HL_FIND_NO_RECURSE); - while(pSubItem != IntPtr.Zero) - { - if(HLLib.hlItemGetType(pSubItem) == HLLib.HLDirectoryItemType.HL_ITEM_FOLDER) - { - uiFolderCount++; - Console.WriteLine(" <{0}>", HLLib.hlItemGetName(pSubItem)); - } - else if(HLLib.hlItemGetType(pSubItem) == HLLib.HLDirectoryItemType.HL_ITEM_FILE) - { - uiFileCount++; - Console.WriteLine(" {0}", HLLib.hlItemGetName(pSubItem)); - } - - pSubItem = HLLib.hlFolderFindNext(pItem, pSubItem, sArgument, HLLib.HLFindType.HL_FIND_ALL | HLLib.HLFindType.HL_FIND_NO_RECURSE); - } - } - - Console.WriteLine(); - - // Could also have used hlFolderGetFolderCount() and - // hlFolderGetFileCount(). - - Console.WriteLine("Summary:"); - Console.WriteLine(); - Console.WriteLine(" {0} Folder{1}.", uiFolderCount, uiFolderCount != 1 ? "s" : ""); - Console.WriteLine(" {0} File{1}.", uiFileCount, uiFileCount != 1 ? "s" : ""); - Console.WriteLine(); - } - // - // Change directory. - // Good example of CDirectoryFolder::GetParent() and item casting. - // - else if(String.Equals(sCommand, "cd", StringComparison.CurrentCultureIgnoreCase)) - { - if(sArgument.Length == 0) - { - Console.WriteLine("No argument for command cd supplied."); - } - else - { - if(String.Equals(sArgument, ".", StringComparison.CurrentCultureIgnoreCase)) - { - - } - else if(String.Equals(sArgument, "..", StringComparison.CurrentCultureIgnoreCase)) - { - if(HLLib.hlItemGetParent(pItem) != IntPtr.Zero) - { - pItem = HLLib.hlItemGetParent(pItem); - } - else - { - Console.WriteLine("Folder does not have a parent."); - } - } - else - { - bool bFound = false; - uint uiItemCount = HLLib.hlFolderGetCount(pItem); - for(uint i = 0; i < uiItemCount; i++) - { - IntPtr pSubItem = HLLib.hlFolderGetItem(pItem, i); - if(HLLib.hlItemGetType(pSubItem) == HLLib.HLDirectoryItemType.HL_ITEM_FOLDER && String.Equals(sArgument, HLLib.hlItemGetName(pSubItem), StringComparison.CurrentCultureIgnoreCase)) - { - bFound = true; - pItem = pSubItem; - break; - } - } - - if(!bFound) - { - Console.WriteLine("{0} not found.", sArgument); - } - } - } - } - // - // Go to the root folder. - // - else if(String.Equals(sCommand, "root", StringComparison.CurrentCultureIgnoreCase)) - { - pItem = HLLib.hlPackageGetRoot(); - } - // - // Item information. - // Good example of CPackageUtility helper functions. - // - else if(String.Equals(sCommand, "info", StringComparison.CurrentCultureIgnoreCase)) - { - if(sArgument.Length == 0) - { - Console.WriteLine("No argument for command info supplied."); - } - else - { - IntPtr pSubItem = HLLib.hlFolderGetItemByPath(pItem, sArgument, HLLib.HLFindType.HL_FIND_ALL); - - if(pSubItem != IntPtr.Zero) - { - Console.WriteLine("Information for {0}:", GetPath(pSubItem)); - Console.WriteLine(); - - switch(HLLib.hlItemGetType(pSubItem)) - { - case HLLib.HLDirectoryItemType.HL_ITEM_FOLDER: - Console.WriteLine(" Type: Folder"); - Console.WriteLine(" Size: {0} B", HLLib.hlFolderGetSizeEx(pSubItem, true)); - Console.WriteLine(" Size On Disk: {0} B", HLLib.hlFolderGetSizeOnDiskEx(pSubItem, true)); - Console.WriteLine(" Folders: {0}", HLLib.hlFolderGetFolderCount(pSubItem, true)); - Console.WriteLine(" Files: {0}", HLLib.hlFolderGetFileCount(pSubItem, true)); - break; - case HLLib.HLDirectoryItemType.HL_ITEM_FILE: - Console.WriteLine(" Type: File"); - Console.WriteLine(" Extractable: {0}", HLLib.hlFileGetExtractable(pSubItem) != 0 ? "True" : "False"); - //Console.WriteLine(" Validates: {0}", HLLib.hlFileGetValidates(pSubItem) ? "True" : "False"); - Console.WriteLine(" Size: {0} B", HLLib.hlFileGetSize(pSubItem)); - Console.WriteLine(" Size On Disk: {0} B", HLLib.hlFileGetSizeOnDisk(pSubItem)); - break; - } - - uint uiAttributeCount = HLLib.hlPackageGetItemAttributeCount(); - for(uint i = 0; i < uiAttributeCount; i++) - { - HLLib.HLAttribute Attribute; - if(HLLib.hlPackageGetItemAttribute(pSubItem, (HLLib.HLPackageAttribute)i, out Attribute)) - { - if(Attribute.eAttributeType != HLLib.HLAttributeType.HL_ATTRIBUTE_INVALID) - { - Console.WriteLine(" {0}: {1}", Attribute.GetName(), Attribute.ToString()); - } - } - } - - Console.WriteLine(); - } - else - { - Console.WriteLine("{0} not found.", sArgument); - } - } - } - // - // Extract item. - // Good example of CPackageUtility extract functions. - // - else if(String.Equals(sCommand, "extract", StringComparison.CurrentCultureIgnoreCase)) - { - if(sArgument.Length == 0) - { - Console.WriteLine("No argument for command extract supplied."); - } - else - { - IntPtr pSubItem; - if(String.Equals(sArgument, ".", StringComparison.CurrentCultureIgnoreCase)) - { - pSubItem = pItem; - } - else - { - pSubItem = HLLib.hlFolderGetItemByName(pItem, sArgument, HLLib.HLFindType.HL_FIND_ALL); - } - - if(pSubItem != IntPtr.Zero) - { - // Extract the item. - // Item is extracted to cDestination\Item->GetName(). - if(!bSilent) - { - Console.WriteLine("Extracting {0}...", HLLib.hlItemGetName(pSubItem)); - Console.WriteLine(); - } - - HLLib.hlItemExtract(pSubItem, sDestination); - - if(!bSilent) - { - Console.WriteLine(""); - Console.WriteLine("Done."); - } - } - else - { - Console.WriteLine("{0} not found.", sArgument); - } - } - } - // - // Validate item. - // Validates the checksums of each item. - // - else if(String.Equals(sCommand, "validate", StringComparison.CurrentCultureIgnoreCase)) - { - if(sArgument.Length == 0) - { - Console.WriteLine("No argument for command extract supplied."); - } - else - { - IntPtr pSubItem; - if(String.Equals(sArgument, ".", StringComparison.CurrentCultureIgnoreCase)) - { - pSubItem = pItem; - } - else - { - pSubItem = HLLib.hlFolderGetItemByName(pItem, sArgument, HLLib.HLFindType.HL_FIND_ALL); - } - - if(pSubItem != IntPtr.Zero) - { - if(!bSilent) - { - Console.WriteLine("Validating {0}...", HLLib.hlItemGetName(pSubItem)); - Console.WriteLine(); - } - - Validate(pSubItem); - - if(!bSilent) - { - Console.WriteLine(); - Console.WriteLine("Done."); - } - } - else - { - Console.WriteLine("{0} not found.", sArgument); - } - } - } - // - // Defragment package. - // Validates the checksums of each item. - // - else if(String.Equals(sCommand, "defragment", StringComparison.CurrentCultureIgnoreCase)) - { - bool bForceDefragment = false; - if(sArgument.Length != 0) - { - try - { - bForceDefragment = Convert.ToBoolean(sArgument); - } - catch - { - } - } - - if(!bSilent) - { - Console.WriteLine("Defragmenting..."); - Console.WriteLine(); - } - - HLLib.hlSetBoolean(HLLib.HLOption.HL_FORCE_DEFRAGMENT, bForceDefragment); - - Console.Write(" Progress: "); - ProgressStart(); - if(!HLLib.hlPackageDefragment()) - { - Console.Write(" {0}", HLLib.hlGetString(HLLib.HLOption.HL_ERROR_SHORT_FORMATED)); - } - - if(!bSilent) - { - Console.WriteLine(); - - Console.WriteLine(); - Console.WriteLine("Done."); - } - } - // - // Find items. - // Good example of recursive directory navigation (Search() function). - // - else if(String.Equals(sCommand, "find", StringComparison.CurrentCultureIgnoreCase)) - { - if(sArgument.Length == 0) - { - Console.WriteLine("No argument for command find supplied."); - } - else - { - // Search for the requested items. - if(!bSilent) - { - Console.WriteLine("Searching for {0}...", sArgument); - Console.WriteLine(); - } - - uint uiFolderCount = 0, uiFileCount = 0; - IntPtr pSubItem = HLLib.hlFolderFindFirst(pItem, sArgument, HLLib.HLFindType.HL_FIND_ALL); - while(pSubItem != IntPtr.Zero) - { - switch(HLLib.hlItemGetType(pSubItem)) - { - case HLLib.HLDirectoryItemType.HL_ITEM_FOLDER: - uiFolderCount++; - - Console.WriteLine(" Found folder: {0}", GetPath(pSubItem)); - break; - case HLLib.HLDirectoryItemType.HL_ITEM_FILE: - uiFileCount++; - - Console.WriteLine(" Found file: {0}", GetPath(pSubItem)); - break; - } - - pSubItem = HLLib.hlFolderFindNext(pItem, pSubItem, sArgument, HLLib.HLFindType.HL_FIND_ALL); - } - - if(!bSilent) - { - if(uiFolderCount != 0 || uiFileCount != 0) - { - Console.WriteLine(); - } - - Console.WriteLine(" {0} folder{1} and {2} file{3} found.", uiFolderCount, uiFolderCount != 1 ? "s" : "", uiFileCount, uiFileCount != 1 ? "s" : ""); - Console.WriteLine(); - } - } - } - // - // Type files. - // Good example of reading files into memory. - // - else if(String.Equals(sCommand, "type", StringComparison.CurrentCultureIgnoreCase)) - { - if(sArgument.Length == 0) - { - Console.WriteLine("No argument for command type supplied."); - } - else - { - IntPtr pSubItem = HLLib.hlFolderGetItemByName(pItem, sArgument, HLLib.HLFindType.HL_FIND_FILES); - - if(pSubItem != IntPtr.Zero) - { - if(!bSilent) - { - Console.WriteLine("Type for {0}:", GetPath(pSubItem)); - Console.WriteLine(); - } - - IntPtr pStream; - if(HLLib.hlFileCreateStream(pSubItem, out pStream)) - { - if(HLLib.hlStreamOpen(pStream, (uint)HLLib.HLFileMode.HL_MODE_READ)) - { - char iChar; - while(HLLib.hlStreamReadChar(pStream, out iChar)) - { - if((iChar >= ' ' && iChar <= '~') || iChar == '\n' || iChar == '\t') - { - Console.Write(iChar); - } - } - - HLLib.hlStreamClose(pStream); - } - else - { - Console.WriteLine("Error typing {0}:", HLLib.hlItemGetName(pSubItem)); - Console.WriteLine(HLLib.hlGetString(HLLib.HLOption.HL_ERROR_SHORT_FORMATED)); - } - - HLLib.hlFileReleaseStream(pSubItem, pStream); - } - else - { - Console.WriteLine("Error typing {0}:", HLLib.hlItemGetName(pSubItem)); - Console.WriteLine(HLLib.hlGetString(HLLib.HLOption.HL_ERROR_SHORT_FORMATED)); - } - - if(!bSilent) - { - Console.WriteLine(); - Console.WriteLine("Done."); - } - } - else - { - Console.WriteLine("{0} not found.", sArgument); - } - } - } - // - // Open item. - // Good example of opening packages inside packages. - // - else if(String.Equals(sCommand, "open", StringComparison.CurrentCultureIgnoreCase)) - { - if(sArgument.Length == 0) - { - Console.WriteLine("No argument for command open supplied."); - } - else - { - IntPtr pSubItem = HLLib.hlFolderGetItemByName(pItem, sArgument, HLLib.HLFindType.HL_FIND_FILES); - - if(pSubItem != IntPtr.Zero) - { - IntPtr pStream; - if(HLLib.hlFileCreateStream(pSubItem, out pStream)) - { - if(HLLib.hlStreamOpen(pStream, (uint)HLLib.HLFileMode.HL_MODE_READ)) - { - HLLib.HLPackageType ePackageType = HLLib.hlGetPackageTypeFromStream(pStream); - - uint uiSubPackage; - if(HLLib.hlCreatePackage(ePackageType, out uiSubPackage)) - { - HLLib.hlBindPackage(uiSubPackage); - if(HLLib.hlPackageOpenStream(pStream, (uint)HLLib.HLFileMode.HL_MODE_READ)) - { - if(!bSilent) - Console.WriteLine("{0} opened.", HLLib.hlItemGetName(pSubItem)); - - EnterConsole(uiSubPackage, Commands); - - HLLib.hlPackageClose(); - - if(!bSilent) - Console.WriteLine("{0} closed.", HLLib.hlItemGetName(pSubItem)); - } - else - { - Console.WriteLine("Error opening {0}:", HLLib.hlItemGetName(pSubItem)); - Console.WriteLine(HLLib.hlGetString(HLLib.HLOption.HL_ERROR_SHORT_FORMATED)); - } - - HLLib.hlDeletePackage(uiSubPackage); - - HLLib.hlBindPackage(uiPackage); - } - else - { - Console.WriteLine("Error opening {0}:", HLLib.hlItemGetName(pSubItem)); - Console.WriteLine(HLLib.hlGetString(HLLib.HLOption.HL_ERROR_SHORT_FORMATED)); - } - - HLLib.hlStreamClose(pStream); - } - else - { - Console.WriteLine("Error opening {0}:", HLLib.hlItemGetName(pSubItem)); - Console.WriteLine(HLLib.hlGetString(HLLib.HLOption.HL_ERROR_SHORT_FORMATED)); - } - - HLLib.hlFileReleaseStream(pSubItem, pStream); - } - else - { - Console.WriteLine("Error opening {0}:", HLLib.hlItemGetName(pSubItem)); - Console.WriteLine(HLLib.hlGetString(HLLib.HLOption.HL_ERROR_SHORT_FORMATED)); - } - } - else - { - Console.WriteLine("{0} not found.", sArgument); - } - } - } - // - // Clear screen. - // - else if(String.Equals(sCommand, "status", StringComparison.CurrentCultureIgnoreCase)) - { - Console.WriteLine("Total size: {0} B", HLLib.hlGetUnsignedLong(HLLib.HLOption.HL_PACKAGE_SIZE)); - Console.WriteLine("Total mapping allocations: {0}", HLLib.hlGetUnsignedInteger(HLLib.HLOption.HL_PACKAGE_TOTAL_ALLOCATIONS)); - Console.WriteLine("Total mapping memory allocated: {0} B", HLLib.hlGetUnsignedLong(HLLib.HLOption.HL_PACKAGE_TOTAL_MEMORY_ALLOCATED)); - Console.WriteLine("Total mapping memory used: {0} B", HLLib.hlGetUnsignedLong(HLLib.HLOption.HL_PACKAGE_TOTAL_MEMORY_USED)); - - uint uiAttributeCount = HLLib.hlPackageGetAttributeCount(); - for(uint i = 0; i < uiAttributeCount; i++) - { - HLLib.HLAttribute Attribute; - if(HLLib.hlPackageGetAttribute((HLLib.HLPackageAttribute)i, out Attribute)) - { - if(Attribute.eAttributeType != HLLib.HLAttributeType.HL_ATTRIBUTE_INVALID) - { - Console.WriteLine("{0}: {1}", Attribute.GetName(), Attribute.ToString()); - } - } - } - } - else if(String.Equals(sCommand, "exec", StringComparison.CurrentCultureIgnoreCase) || String.Equals(sCommand, "execute", StringComparison.CurrentCultureIgnoreCase)) - { - if(sArgument.Length == 0) - { - Console.WriteLine("No argument for command open supplied."); - } - else - { - string[] NewCommands = sArgument.Split(new char[] { '|' }); - Commands.AddRange(NewCommands); - } - } - else if(String.Equals(sCommand, "cls", StringComparison.CurrentCultureIgnoreCase)) - { - try - { - Console.Clear(); - } - catch - { - } - } - else if(String.Equals(sCommand, "help", StringComparison.CurrentCultureIgnoreCase)) - { - Console.WriteLine("Valid commands:"); - Console.WriteLine(); - Console.WriteLine("dir (Directory list.)"); - Console.WriteLine("cd (Change directroy.)"); - Console.WriteLine("info (Item information.)"); - Console.WriteLine("extract (Extract item.)"); - Console.WriteLine("validate (Validate item.)"); - Console.WriteLine("defragment [force] (Defragment package.)"); - Console.WriteLine("find (Find item.)"); - Console.WriteLine("type (Type a file.)"); - Console.WriteLine("open (Open a nested package.)"); - Console.WriteLine("root (Go to the root folder.)"); - Console.WriteLine("status (Package information.)"); - Console.WriteLine("execute |... (Execute 1 or more pipe delimited commands.)"); - Console.WriteLine("cls (Clear the screen.)"); - Console.WriteLine("help (Program help.)"); - Console.WriteLine("exit (Quit program.)"); - Console.WriteLine(); - } - else if(String.Equals(sCommand, "exit", StringComparison.CurrentCultureIgnoreCase)) - { - break; - } - else - { - Console.WriteLine("Unkown command: {0}", sCommand); - } - } - } - - #endregion } } diff --git a/BurnOutSharp/HLLib.x64.dll b/BurnOutSharp/HLLib.x64.dll deleted file mode 100644 index e1cf3fa1..00000000 Binary files a/BurnOutSharp/HLLib.x64.dll and /dev/null differ diff --git a/BurnOutSharp/HLLib.x86.dll b/BurnOutSharp/HLLib.x86.dll deleted file mode 100644 index 087a5416..00000000 Binary files a/BurnOutSharp/HLLib.x86.dll and /dev/null differ diff --git a/HLLibSharp b/HLLibSharp new file mode 160000 index 00000000..d712f378 --- /dev/null +++ b/HLLibSharp @@ -0,0 +1 @@ +Subproject commit d712f378067055850176ac1f9cacc09f6b19071a diff --git a/README.md b/README.md index 8643c1e2..7ed5b47e 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ C# port of the protection scanning ability of [BurnOut](http://burnout.sourcefor In addition to the original BurnOut code, the following libraries (or ports thereof) are used for file handling: -- [HLExtract](https://github.com/Rupan/HLLib) - Various Valve archive format extraction +- [HLLibSharp](https://github.com/mnadareski/HLLibSharp) - Various Valve archive format extraction - [psxt001z](https://github.com/Dremora/psxt001z) - PS1 LibCrypt detection - [SharpCompress](https://github.com/adamhathcock/sharpcompress) - 7zip/GZip/RAR/PKZIP extraction - [StormLibSharp](https://github.com/robpaveza/stormlibsharp) - MPQ extraction