From 5af4de287873173b6a67aaacb543e2efd40eb1eb Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Fri, 26 Sep 2025 12:09:34 -0400 Subject: [PATCH] Migrate remaining models from Models --- .../SabreTools.Serialization.Test.csproj | 1 - .../Deserializers/LinearExecutable.cs | 4 +- .../Deserializers/MSDOS.cs | 4 +- .../Deserializers/NewExecutable.cs | 6 +- .../Deserializers/PortableExecutable.cs | 150 +- .../Deserializers/SecuROMAddD.cs | 2 +- .../Deserializers/SecuROMDFA.cs | 4 +- .../Deserializers/SecuROMMatroschkaPackage.cs | 4 +- .../Deserializers/WiseOverlayHeader.cs | 2 +- .../Deserializers/WiseScript.cs | 4 +- .../Deserializers/WiseSectionHeader.cs | 4 +- .../Extensions/NewExecutable.cs | 2 +- .../Extensions/PortableExecutable.cs | 40 +- .../Models/AdvancedInstaller/FileEntry.cs | 61 + .../Models/AdvancedInstaller/Footer.cs | 109 ++ .../Models/AdvancedInstaller/SFX.cs | 29 + .../Models/COFF/Constants.cs | 20 + SabreTools.Serialization/Models/COFF/Enums.cs | 1726 +++++++++++++++++ .../Models/COFF/FileHeader.cs | 58 + .../Models/COFF/LineNumber.cs | 42 + .../Models/COFF/OptionalHeader.cs | 88 + .../Models/COFF/Relocation.cs | 47 + .../Models/COFF/SectionHeader.cs | 111 ++ .../Models/COFF/StringTable.cs | 25 + .../COFF/SymbolTableEntries/BaseEntry.cs | 32 + .../SymbolTableEntries/CLRTokenDefinition.cs | 33 + .../COFF/SymbolTableEntries/Descriptor.cs | 53 + .../COFF/SymbolTableEntries/FileRecord.cs | 20 + .../SymbolTableEntries/FunctionDefinition.cs | 47 + .../SymbolTableEntries/SectionDefinition.cs | 54 + .../COFF/SymbolTableEntries/StandardRecord.cs | 58 + .../COFF/SymbolTableEntries/WeakExternal.cs | 45 + .../Models/Delphi/Constants.cs | 14 + .../Models/Delphi/PackageInfoTable.cs | 14 + .../Models/Delphi/PackageTypeInfo.cs | 19 + .../Models/Delphi/PackageUnitEntry.cs | 21 + .../Models/LinearExecutable/Constants.cs | 21 + .../LinearExecutable/DebugInformation.cs | 35 + .../LinearExecutable/EntryTableBundle.cs | 56 + .../LinearExecutable/EntryTableEntry.cs | 190 ++ .../Models/LinearExecutable/Enums.cs | 680 +++++++ .../Models/LinearExecutable/Executable.cs | 97 + .../LinearExecutable/FixupPageTableEntry.cs | 36 + .../LinearExecutable/FixupRecordTableEntry.cs | 363 ++++ .../ImportModuleNameTableEntry.cs | 38 + .../ImportProcedureNameTableEntry.cs | 46 + .../LinearExecutable/InformationBlock.cs | 432 +++++ .../ModuleFormatDirectivesTableEntry.cs | 49 + .../NonResidentNamesTableEntry.cs | 64 + .../LinearExecutable/ObjectPageMapEntry.cs | 61 + .../LinearExecutable/ObjectTableEntry.cs | 83 + .../PerPageChecksumTableEntry.cs | 24 + .../ResidentNamesTableEntry.cs | 61 + .../LinearExecutable/ResourceTableEntry.cs | 47 + .../VerifyRecordDirectiveTableEntry.cs | 85 + .../Models/MSDOS/Constants.cs | 11 + .../Models/MSDOS/Executable.cs | 29 + .../Models/MSDOS/ExecutableHeader.cs | 133 ++ .../Models/MSDOS/RelocationEntry.cs | 22 + .../Models/NewExecutable/Constants.cs | 11 + .../Models/NewExecutable/EntryTableBundle.cs | 84 + .../Models/NewExecutable/Enums.cs | 325 ++++ .../Models/NewExecutable/Executable.cs | 67 + .../Models/NewExecutable/ExecutableHeader.cs | 209 ++ .../ImportNameRelocationRecord.cs | 19 + .../ImportOrdinalRelocationRecord.cs | 19 + .../NewExecutable/ImportedNameTableEntry.cs | 25 + .../InternalRefRelocationRecord.cs | 26 + .../ModuleReferenceTableEntry.cs | 19 + .../NonResidentNameTableEntry.cs | 31 + .../NewExecutable/OSFixupRelocationRecord.cs | 21 + .../Models/NewExecutable/PerSegmentData.cs | 30 + .../Models/NewExecutable/RelocationRecord.cs | 57 + .../NewExecutable/ResidentNameTableEntry.cs | 30 + .../Models/NewExecutable/ResourceTable.cs | 34 + .../ResourceTypeAndNameString.cs | 23 + .../ResourceTypeInformationEntry.cs | 34 + .../ResourceTypeResourceEntry.cs | 48 + .../Models/NewExecutable/SegmentTableEntry.cs | 60 + .../AttributeCertificate/Entry.cs | 63 + .../BaseRelocation/Block.cs | 51 + .../BaseRelocation/TypeOffsetFieldEntry.cs | 22 + .../Models/PortableExecutable/Constants.cs | 13 + .../PortableExecutable/DataDirectory.cs | 29 + .../PortableExecutable/DebugData/Entry.cs | 67 + .../DebugData/NB10ProgramDatabase.cs | 44 + .../DebugData/RSDSProgramDatabase.cs | 41 + .../PortableExecutable/DebugData/Table.cs | 38 + .../DelayLoad/DirectoryTable.cs | 107 + .../Models/PortableExecutable/Enums.cs | 1678 ++++++++++++++++ .../Models/PortableExecutable/Executable.cs | 250 +++ .../Export/AddressTableEntry.cs | 37 + .../Export/DirectoryTable.cs | 78 + .../Export/NamePointerTable.cs | 18 + .../PortableExecutable/Export/NameTable.cs | 27 + .../PortableExecutable/Export/OrdinalTable.cs | 42 + .../Import/AddressTableEntry.cs | 36 + .../Import/DirectoryTableEntry.cs | 50 + .../Import/HintNameTableEntry.cs | 27 + .../Import/LookupTableEntry.cs | 36 + .../LoadConfiguration/Directory.cs | 189 ++ .../PortableExecutable/OptionalHeader.cs | 245 +++ .../PortableExecutable/Resource/DataEntry.cs | 40 + .../Resource/DirectoryEntry.cs | 68 + .../Resource/DirectoryString.cs | 23 + .../Resource/DirectoryTable.cs | 59 + .../Resource/Entries/AcceleratorTable.cs | 19 + .../Resource/Entries/AcceleratorTableEntry.cs | 35 + .../Resource/Entries/AssemblyManifest.cs | 390 ++++ .../Resource/Entries/CursorAndIconResource.cs | 40 + .../Resource/Entries/DialogBoxResource.cs | 46 + .../Resource/Entries/DialogItemTemplate.cs | 130 ++ .../Entries/DialogItemTemplateExtended.cs | 128 ++ .../Resource/Entries/DialogTemplate.cs | 160 ++ .../Entries/DialogTemplateExtended.cs | 185 ++ .../Resource/Entries/DirEntry.cs | 21 + .../Resource/Entries/FixedFileInfo.cs | 92 + .../Resource/Entries/FontDirEntry.cs | 174 ++ .../Resource/Entries/FontGroupHeader.cs | 21 + .../Resource/Entries/MenuHeader.cs | 12 + .../Resource/Entries/MenuHeaderExtended.cs | 30 + .../Resource/Entries/MenuItem.cs | 12 + .../Resource/Entries/MenuItemExtended.cs | 44 + .../Resource/Entries/MenuResource.cs | 22 + .../Resource/Entries/MessageResourceBlock.cs | 30 + .../Resource/Entries/MessageResourceData.cs | 27 + .../Resource/Entries/MessageResourceEntry.cs | 25 + .../Resource/Entries/NewHeader.cs | 31 + .../Resource/Entries/NormalMenuHeader.cs | 25 + .../Resource/Entries/NormalMenuItem.cs | 27 + .../Resource/Entries/PopupMenuItem.cs | 45 + .../Resource/Entries/StringData.cs | 79 + .../Resource/Entries/StringFileInfo.cs | 43 + .../Resource/Entries/StringTable.cs | 46 + .../Resource/Entries/VarData.cs | 50 + .../Resource/Entries/VarFileInfo.cs | 41 + .../Resource/Entries/VersionInfo.cs | 61 + .../Resource/ResourceHeader.cs | 99 + .../PortableExecutable/TLS/Directory.cs | 55 + .../Models/SafeDisc/Constants.cs | 9 + .../Models/SafeDisc/EncryptedFileEntry.cs | 33 + .../Models/SecuROM/AddD.cs | 61 + .../Models/SecuROM/AddDEntry.cs | 79 + .../Models/SecuROM/Constants.cs | 130 ++ .../Models/SecuROM/DFAEntry.cs | 24 + .../Models/SecuROM/DFAFile.cs | 27 + .../Models/SecuROM/Enums.cs | 36 + .../Models/SecuROM/MatroshkaEntry.cs | 65 + .../Models/SecuROM/MatroshkaPackage.cs | 86 + .../Actions/AddDirectoryToPath.cs | 36 + .../Actions/AddTextToInstallLog.cs | 28 + .../WiseInstaller/Actions/AddToAutoexecBat.cs | 62 + .../WiseInstaller/Actions/AddToConfigSys.cs | 60 + .../WiseInstaller/Actions/AddToSystemIni.cs | 24 + .../WiseInstaller/Actions/CallDllFunction.cs | 61 + .../Actions/CheckConfiguration.cs | 42 + .../WiseInstaller/Actions/CheckDiskSpace.cs | 44 + .../Actions/CheckHttpConnection.cs | 45 + .../Actions/CheckIfFileDirExists.cs | 47 + .../Actions/ConfigODBCDataSource.cs | 46 + .../WiseInstaller/Actions/CopyLocalFile.cs | 42 + .../WiseInstaller/Actions/CreateDirectory.cs | 23 + .../WiseInstaller/Actions/CustomDialogSet.cs | 38 + .../WiseInstaller/Actions/DeflateEntry.cs | 24 + .../WiseInstaller/Actions/DeleteFile.cs | 30 + .../WiseInstaller/Actions/DisplayBillboard.cs | 57 + .../WiseInstaller/Actions/DisplayMessage.cs | 30 + .../WiseInstaller/Actions/EditIniFile.cs | 31 + .../WiseInstaller/Actions/EditRegistry.cs | 63 + .../WiseInstaller/Actions/ElseIfStatement.cs | 30 + .../WiseInstaller/Actions/ElseStatement.cs | 20 + .../Actions/EndBlockStatement.cs | 28 + .../Actions/EndUserDefinedAction.cs | 19 + .../WiseInstaller/Actions/ExecuteProgram.cs | 38 + .../WiseInstaller/Actions/ExitInstallation.cs | 18 + .../WiseInstaller/Actions/ExternalDllCall.cs | 20 + .../WiseInstaller/Actions/FindFileInPath.cs | 55 + .../WiseInstaller/Actions/FunctionData.cs | 7 + .../Actions/GetEnvironmentVariable.cs | 40 + .../Actions/GetRegistryKeyValue.cs | 51 + .../Actions/GetSystemInformation.cs | 57 + .../Actions/GetTemporaryFilename.cs | 21 + .../WiseInstaller/Actions/IfWhileStatement.cs | 70 + .../WiseInstaller/Actions/IncludeScript.cs | 25 + .../Actions/InsertLineIntoTextFile.cs | 55 + .../Actions/InstallDirectXComponents.cs | 43 + .../WiseInstaller/Actions/InstallFile.cs | 102 + .../WiseInstaller/Actions/InvalidOperation.cs | 15 + .../WiseInstaller/Actions/MachineStateData.cs | 7 + .../Models/WiseInstaller/Actions/NewEvent.cs | 38 + .../Models/WiseInstaller/Actions/NoOp.cs | 15 + .../Actions/OpenCloseInstallLog.cs | 35 + .../WiseInstaller/Actions/ParseString.cs | 69 + .../Actions/PlayMultimediaFile.cs | 41 + .../WiseInstaller/Actions/PostToHttpServer.cs | 45 + .../Actions/PromptForFilename.cs | 61 + .../WiseInstaller/Actions/ReadIniValue.cs | 50 + .../Actions/ReadUpdateTextFile.cs | 46 + .../Actions/ReadWriteBinaryFile.cs | 52 + .../WiseInstaller/Actions/RegisterFont.cs | 25 + .../Actions/RenameFileDirectory.cs | 24 + .../WiseInstaller/Actions/SearchForFile.cs | 48 + .../Actions/SelfRegisterOCXsDLLs.cs | 31 + .../Actions/SetFileAttributes.cs | 35 + .../WiseInstaller/Actions/SetFilesBuffers.cs | 28 + .../WiseInstaller/Actions/SetVariable.cs | 49 + .../WiseInstaller/Actions/StartStopService.cs | 35 + .../Actions/StartUserDefinedAction.cs | 19 + .../WiseInstaller/Actions/Unknown0x19.cs | 26 + .../WiseInstaller/Actions/Unknown0x24.cs | 17 + .../WiseInstaller/Actions/Unknown0x25.cs | 17 + .../Actions/UserDefinedActionStep.cs | 29 + .../Actions/Win32SystemDirectory.cs | 22 + .../WiseInstaller/Actions/WizardBlockLoop.cs | 81 + .../Models/WiseInstaller/Constants.cs | 106 + .../Models/WiseInstaller/Enums.cs | 418 ++++ .../Models/WiseInstaller/MachineState.cs | 22 + .../Models/WiseInstaller/OverlayHeader.cs | 182 ++ .../Models/WiseInstaller/ScriptFile.cs | 19 + .../Models/WiseInstaller/ScriptHeader.cs | 171 ++ .../Models/WiseInstaller/SectionHeader.cs | 180 ++ .../Printers/LinearExecutable.cs | 4 +- SabreTools.Serialization/Printers/MSDOS.cs | 2 +- .../Printers/NewExecutable.cs | 6 +- .../Printers/PortableExecutable.cs | 92 +- .../Printers/SecuROMDFA.cs | 4 +- .../Printers/WiseOverlayHeader.cs | 2 +- .../Printers/WiseScript.cs | 4 +- .../Printers/WiseSectionHeader.cs | 2 +- .../SabreTools.Serialization.csproj | 1 - SabreTools.Serialization/WrapperFactory.cs | 12 +- .../Wrappers/LinearExecutable.cs | 4 +- SabreTools.Serialization/Wrappers/MSDOS.cs | 2 +- .../Wrappers/NewExecutable.Extraction.cs | 2 +- .../Wrappers/NewExecutable.cs | 4 +- .../Wrappers/PortableExecutable.Extraction.cs | 4 +- .../Wrappers/PortableExecutable.cs | 46 +- .../Wrappers/SecuROMDFA.cs | 2 +- .../SecuROMMatroschkaPackage.Extraction.cs | 2 +- .../Wrappers/SecuROMMatroschkaPackage.cs | 4 +- .../Wrappers/WiseOverlayHeader.Extraction.cs | 2 +- .../Wrappers/WiseOverlayHeader.cs | 2 +- .../Wrappers/WiseScript.cs | 4 +- .../Wrappers/WiseSectionHeader.cs | 2 +- 244 files changed, 16541 insertions(+), 219 deletions(-) create mode 100644 SabreTools.Serialization/Models/AdvancedInstaller/FileEntry.cs create mode 100644 SabreTools.Serialization/Models/AdvancedInstaller/Footer.cs create mode 100644 SabreTools.Serialization/Models/AdvancedInstaller/SFX.cs create mode 100644 SabreTools.Serialization/Models/COFF/Constants.cs create mode 100644 SabreTools.Serialization/Models/COFF/Enums.cs create mode 100644 SabreTools.Serialization/Models/COFF/FileHeader.cs create mode 100644 SabreTools.Serialization/Models/COFF/LineNumber.cs create mode 100644 SabreTools.Serialization/Models/COFF/OptionalHeader.cs create mode 100644 SabreTools.Serialization/Models/COFF/Relocation.cs create mode 100644 SabreTools.Serialization/Models/COFF/SectionHeader.cs create mode 100644 SabreTools.Serialization/Models/COFF/StringTable.cs create mode 100644 SabreTools.Serialization/Models/COFF/SymbolTableEntries/BaseEntry.cs create mode 100644 SabreTools.Serialization/Models/COFF/SymbolTableEntries/CLRTokenDefinition.cs create mode 100644 SabreTools.Serialization/Models/COFF/SymbolTableEntries/Descriptor.cs create mode 100644 SabreTools.Serialization/Models/COFF/SymbolTableEntries/FileRecord.cs create mode 100644 SabreTools.Serialization/Models/COFF/SymbolTableEntries/FunctionDefinition.cs create mode 100644 SabreTools.Serialization/Models/COFF/SymbolTableEntries/SectionDefinition.cs create mode 100644 SabreTools.Serialization/Models/COFF/SymbolTableEntries/StandardRecord.cs create mode 100644 SabreTools.Serialization/Models/COFF/SymbolTableEntries/WeakExternal.cs create mode 100644 SabreTools.Serialization/Models/Delphi/Constants.cs create mode 100644 SabreTools.Serialization/Models/Delphi/PackageInfoTable.cs create mode 100644 SabreTools.Serialization/Models/Delphi/PackageTypeInfo.cs create mode 100644 SabreTools.Serialization/Models/Delphi/PackageUnitEntry.cs create mode 100644 SabreTools.Serialization/Models/LinearExecutable/Constants.cs create mode 100644 SabreTools.Serialization/Models/LinearExecutable/DebugInformation.cs create mode 100644 SabreTools.Serialization/Models/LinearExecutable/EntryTableBundle.cs create mode 100644 SabreTools.Serialization/Models/LinearExecutable/EntryTableEntry.cs create mode 100644 SabreTools.Serialization/Models/LinearExecutable/Enums.cs create mode 100644 SabreTools.Serialization/Models/LinearExecutable/Executable.cs create mode 100644 SabreTools.Serialization/Models/LinearExecutable/FixupPageTableEntry.cs create mode 100644 SabreTools.Serialization/Models/LinearExecutable/FixupRecordTableEntry.cs create mode 100644 SabreTools.Serialization/Models/LinearExecutable/ImportModuleNameTableEntry.cs create mode 100644 SabreTools.Serialization/Models/LinearExecutable/ImportProcedureNameTableEntry.cs create mode 100644 SabreTools.Serialization/Models/LinearExecutable/InformationBlock.cs create mode 100644 SabreTools.Serialization/Models/LinearExecutable/ModuleFormatDirectivesTableEntry.cs create mode 100644 SabreTools.Serialization/Models/LinearExecutable/NonResidentNamesTableEntry.cs create mode 100644 SabreTools.Serialization/Models/LinearExecutable/ObjectPageMapEntry.cs create mode 100644 SabreTools.Serialization/Models/LinearExecutable/ObjectTableEntry.cs create mode 100644 SabreTools.Serialization/Models/LinearExecutable/PerPageChecksumTableEntry.cs create mode 100644 SabreTools.Serialization/Models/LinearExecutable/ResidentNamesTableEntry.cs create mode 100644 SabreTools.Serialization/Models/LinearExecutable/ResourceTableEntry.cs create mode 100644 SabreTools.Serialization/Models/LinearExecutable/VerifyRecordDirectiveTableEntry.cs create mode 100644 SabreTools.Serialization/Models/MSDOS/Constants.cs create mode 100644 SabreTools.Serialization/Models/MSDOS/Executable.cs create mode 100644 SabreTools.Serialization/Models/MSDOS/ExecutableHeader.cs create mode 100644 SabreTools.Serialization/Models/MSDOS/RelocationEntry.cs create mode 100644 SabreTools.Serialization/Models/NewExecutable/Constants.cs create mode 100644 SabreTools.Serialization/Models/NewExecutable/EntryTableBundle.cs create mode 100644 SabreTools.Serialization/Models/NewExecutable/Enums.cs create mode 100644 SabreTools.Serialization/Models/NewExecutable/Executable.cs create mode 100644 SabreTools.Serialization/Models/NewExecutable/ExecutableHeader.cs create mode 100644 SabreTools.Serialization/Models/NewExecutable/ImportNameRelocationRecord.cs create mode 100644 SabreTools.Serialization/Models/NewExecutable/ImportOrdinalRelocationRecord.cs create mode 100644 SabreTools.Serialization/Models/NewExecutable/ImportedNameTableEntry.cs create mode 100644 SabreTools.Serialization/Models/NewExecutable/InternalRefRelocationRecord.cs create mode 100644 SabreTools.Serialization/Models/NewExecutable/ModuleReferenceTableEntry.cs create mode 100644 SabreTools.Serialization/Models/NewExecutable/NonResidentNameTableEntry.cs create mode 100644 SabreTools.Serialization/Models/NewExecutable/OSFixupRelocationRecord.cs create mode 100644 SabreTools.Serialization/Models/NewExecutable/PerSegmentData.cs create mode 100644 SabreTools.Serialization/Models/NewExecutable/RelocationRecord.cs create mode 100644 SabreTools.Serialization/Models/NewExecutable/ResidentNameTableEntry.cs create mode 100644 SabreTools.Serialization/Models/NewExecutable/ResourceTable.cs create mode 100644 SabreTools.Serialization/Models/NewExecutable/ResourceTypeAndNameString.cs create mode 100644 SabreTools.Serialization/Models/NewExecutable/ResourceTypeInformationEntry.cs create mode 100644 SabreTools.Serialization/Models/NewExecutable/ResourceTypeResourceEntry.cs create mode 100644 SabreTools.Serialization/Models/NewExecutable/SegmentTableEntry.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/AttributeCertificate/Entry.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/BaseRelocation/Block.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/BaseRelocation/TypeOffsetFieldEntry.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Constants.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/DataDirectory.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/DebugData/Entry.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/DebugData/NB10ProgramDatabase.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/DebugData/RSDSProgramDatabase.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/DebugData/Table.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/DelayLoad/DirectoryTable.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Enums.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Executable.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Export/AddressTableEntry.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Export/DirectoryTable.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Export/NamePointerTable.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Export/NameTable.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Export/OrdinalTable.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Import/AddressTableEntry.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Import/DirectoryTableEntry.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Import/HintNameTableEntry.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Import/LookupTableEntry.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/LoadConfiguration/Directory.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/OptionalHeader.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Resource/DataEntry.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Resource/DirectoryEntry.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Resource/DirectoryString.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Resource/DirectoryTable.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/AcceleratorTable.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/AcceleratorTableEntry.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/AssemblyManifest.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/CursorAndIconResource.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/DialogBoxResource.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/DialogItemTemplate.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/DialogItemTemplateExtended.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/DialogTemplate.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/DialogTemplateExtended.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/DirEntry.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/FixedFileInfo.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/FontDirEntry.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/FontGroupHeader.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/MenuHeader.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/MenuHeaderExtended.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/MenuItem.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/MenuItemExtended.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/MenuResource.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/MessageResourceBlock.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/MessageResourceData.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/MessageResourceEntry.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/NewHeader.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/NormalMenuHeader.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/NormalMenuItem.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/PopupMenuItem.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/StringData.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/StringFileInfo.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/StringTable.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/VarData.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/VarFileInfo.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/VersionInfo.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/Resource/ResourceHeader.cs create mode 100644 SabreTools.Serialization/Models/PortableExecutable/TLS/Directory.cs create mode 100644 SabreTools.Serialization/Models/SafeDisc/Constants.cs create mode 100644 SabreTools.Serialization/Models/SafeDisc/EncryptedFileEntry.cs create mode 100644 SabreTools.Serialization/Models/SecuROM/AddD.cs create mode 100644 SabreTools.Serialization/Models/SecuROM/AddDEntry.cs create mode 100644 SabreTools.Serialization/Models/SecuROM/Constants.cs create mode 100644 SabreTools.Serialization/Models/SecuROM/DFAEntry.cs create mode 100644 SabreTools.Serialization/Models/SecuROM/DFAFile.cs create mode 100644 SabreTools.Serialization/Models/SecuROM/Enums.cs create mode 100644 SabreTools.Serialization/Models/SecuROM/MatroshkaEntry.cs create mode 100644 SabreTools.Serialization/Models/SecuROM/MatroshkaPackage.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/AddDirectoryToPath.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/AddTextToInstallLog.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/AddToAutoexecBat.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/AddToConfigSys.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/AddToSystemIni.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/CallDllFunction.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/CheckConfiguration.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/CheckDiskSpace.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/CheckHttpConnection.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/CheckIfFileDirExists.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/ConfigODBCDataSource.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/CopyLocalFile.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/CreateDirectory.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/CustomDialogSet.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/DeflateEntry.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/DeleteFile.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/DisplayBillboard.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/DisplayMessage.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/EditIniFile.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/EditRegistry.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/ElseIfStatement.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/ElseStatement.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/EndBlockStatement.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/EndUserDefinedAction.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/ExecuteProgram.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/ExitInstallation.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/ExternalDllCall.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/FindFileInPath.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/FunctionData.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/GetEnvironmentVariable.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/GetRegistryKeyValue.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/GetSystemInformation.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/GetTemporaryFilename.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/IfWhileStatement.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/IncludeScript.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/InsertLineIntoTextFile.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/InstallDirectXComponents.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/InstallFile.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/InvalidOperation.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/MachineStateData.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/NewEvent.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/NoOp.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/OpenCloseInstallLog.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/ParseString.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/PlayMultimediaFile.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/PostToHttpServer.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/PromptForFilename.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/ReadIniValue.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/ReadUpdateTextFile.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/ReadWriteBinaryFile.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/RegisterFont.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/RenameFileDirectory.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/SearchForFile.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/SelfRegisterOCXsDLLs.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/SetFileAttributes.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/SetFilesBuffers.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/SetVariable.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/StartStopService.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/StartUserDefinedAction.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/Unknown0x19.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/Unknown0x24.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/Unknown0x25.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/UserDefinedActionStep.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/Win32SystemDirectory.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Actions/WizardBlockLoop.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Constants.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/Enums.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/MachineState.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/OverlayHeader.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/ScriptFile.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/ScriptHeader.cs create mode 100644 SabreTools.Serialization/Models/WiseInstaller/SectionHeader.cs diff --git a/SabreTools.Serialization.Test/SabreTools.Serialization.Test.csproj b/SabreTools.Serialization.Test/SabreTools.Serialization.Test.csproj index df50e683..698dfe96 100644 --- a/SabreTools.Serialization.Test/SabreTools.Serialization.Test.csproj +++ b/SabreTools.Serialization.Test/SabreTools.Serialization.Test.csproj @@ -28,7 +28,6 @@ - runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/SabreTools.Serialization/Deserializers/LinearExecutable.cs b/SabreTools.Serialization/Deserializers/LinearExecutable.cs index e9a47460..b5d0c339 100644 --- a/SabreTools.Serialization/Deserializers/LinearExecutable.cs +++ b/SabreTools.Serialization/Deserializers/LinearExecutable.cs @@ -2,8 +2,8 @@ using System.Collections.Generic; using System.IO; using System.Text; using SabreTools.IO.Extensions; -using SabreTools.Models.LinearExecutable; -using static SabreTools.Models.LinearExecutable.Constants; +using SabreTools.Serialization.Models.LinearExecutable; +using static SabreTools.Serialization.Models.LinearExecutable.Constants; namespace SabreTools.Serialization.Deserializers { diff --git a/SabreTools.Serialization/Deserializers/MSDOS.cs b/SabreTools.Serialization/Deserializers/MSDOS.cs index b026a24a..48c18296 100644 --- a/SabreTools.Serialization/Deserializers/MSDOS.cs +++ b/SabreTools.Serialization/Deserializers/MSDOS.cs @@ -1,8 +1,8 @@ using System.IO; using System.Text; using SabreTools.IO.Extensions; -using SabreTools.Models.MSDOS; -using static SabreTools.Models.MSDOS.Constants; +using SabreTools.Serialization.Models.MSDOS; +using static SabreTools.Serialization.Models.MSDOS.Constants; namespace SabreTools.Serialization.Deserializers { diff --git a/SabreTools.Serialization/Deserializers/NewExecutable.cs b/SabreTools.Serialization/Deserializers/NewExecutable.cs index 313cab6e..8e59dc3e 100644 --- a/SabreTools.Serialization/Deserializers/NewExecutable.cs +++ b/SabreTools.Serialization/Deserializers/NewExecutable.cs @@ -2,9 +2,9 @@ using System.Collections.Generic; using System.IO; using System.Text; using SabreTools.IO.Extensions; -using SabreTools.Models.NewExecutable; using SabreTools.Serialization.Extensions; -using static SabreTools.Models.NewExecutable.Constants; +using SabreTools.Serialization.Models.NewExecutable; +using static SabreTools.Serialization.Models.NewExecutable.Constants; namespace SabreTools.Serialization.Deserializers { @@ -253,7 +253,7 @@ namespace SabreTools.Serialization.Deserializers obj.MovableEntriesCount = data.ReadUInt16LittleEndian(); obj.SegmentAlignmentShiftCount = data.ReadUInt16LittleEndian(); obj.ResourceEntriesCount = data.ReadUInt16LittleEndian(); - obj.TargetOperatingSystem = (SabreTools.Models.NewExecutable.OperatingSystem)data.ReadByteValue(); + obj.TargetOperatingSystem = (SabreTools.Serialization.Models.NewExecutable.OperatingSystem)data.ReadByteValue(); obj.AdditionalFlags = (OS2Flag)data.ReadByteValue(); obj.ReturnThunkOffset = data.ReadUInt16LittleEndian(); obj.SegmentReferenceThunkOffset = data.ReadUInt16LittleEndian(); diff --git a/SabreTools.Serialization/Deserializers/PortableExecutable.cs b/SabreTools.Serialization/Deserializers/PortableExecutable.cs index dd7ac092..36bbfaa8 100644 --- a/SabreTools.Serialization/Deserializers/PortableExecutable.cs +++ b/SabreTools.Serialization/Deserializers/PortableExecutable.cs @@ -3,12 +3,12 @@ using System.Collections.Generic; using System.IO; using System.Text; using SabreTools.IO.Extensions; -using SabreTools.Models.COFF; -using SabreTools.Models.COFF.SymbolTableEntries; -using SabreTools.Models.PortableExecutable; using SabreTools.Serialization.Extensions; -using static SabreTools.Models.COFF.Constants; -using static SabreTools.Models.PortableExecutable.Constants; +using SabreTools.Serialization.Models.COFF; +using SabreTools.Serialization.Models.COFF.SymbolTableEntries; +using SabreTools.Serialization.Models.PortableExecutable; +using static SabreTools.Serialization.Models.COFF.Constants; +using static SabreTools.Serialization.Models.PortableExecutable.Constants; namespace SabreTools.Serialization.Deserializers { @@ -74,7 +74,7 @@ namespace SabreTools.Serialization.Deserializers #region Optional Header // If the optional header exists - SabreTools.Models.PortableExecutable.OptionalHeader? optionalHeader = null; + SabreTools.Serialization.Models.PortableExecutable.OptionalHeader? optionalHeader = null; if (fileHeader.SizeOfOptionalHeader > 0) { // Parse the optional header @@ -337,12 +337,12 @@ namespace SabreTools.Serialization.Deserializers int length = tableSize - tableOffset; // Add the hidden entry - pex.ResourceDirectoryTable.Entries[localEntries.Length - 1] = new SabreTools.Models.PortableExecutable.Resource.DirectoryEntry + pex.ResourceDirectoryTable.Entries[localEntries.Length - 1] = new SabreTools.Serialization.Models.PortableExecutable.Resource.DirectoryEntry { - Name = new SabreTools.Models.PortableExecutable.Resource.DirectoryString { UnicodeString = Encoding.Unicode.GetBytes("HIDDEN RESOURCE") }, + Name = new SabreTools.Serialization.Models.PortableExecutable.Resource.DirectoryString { UnicodeString = Encoding.Unicode.GetBytes("HIDDEN RESOURCE") }, IntegerID = uint.MaxValue, DataEntryOffset = (uint)tableOffset, - DataEntry = new SabreTools.Models.PortableExecutable.Resource.DataEntry + DataEntry = new SabreTools.Serialization.Models.PortableExecutable.Resource.DataEntry { Size = (uint)length, Data = tableData.ReadBytes(ref tableOffset, length), @@ -471,12 +471,12 @@ namespace SabreTools.Serialization.Deserializers /// /// Byte array to parse /// Filled attribute certificate on success, null on error - public static SabreTools.Models.PortableExecutable.AttributeCertificate.Entry[]? ParseAttributeCertificateTable(byte[]? data) + public static SabreTools.Serialization.Models.PortableExecutable.AttributeCertificate.Entry[]? ParseAttributeCertificateTable(byte[]? data) { if (data == null) return null; - var obj = new List(); + var obj = new List(); int offset = 0; while (offset < data.Length) @@ -502,9 +502,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Byte array to parse /// Filled AttributeCertificateTableEntry on success, null on error - public static SabreTools.Models.PortableExecutable.AttributeCertificate.Entry? ParseAttributeCertificateTableEntry(byte[] data, ref int offset) + public static SabreTools.Serialization.Models.PortableExecutable.AttributeCertificate.Entry? ParseAttributeCertificateTableEntry(byte[] data, ref int offset) { - var obj = new SabreTools.Models.PortableExecutable.AttributeCertificate.Entry(); + var obj = new SabreTools.Serialization.Models.PortableExecutable.AttributeCertificate.Entry(); obj.Length = data.ReadUInt32LittleEndian(ref offset); if (obj.Length < 8) @@ -526,9 +526,9 @@ namespace SabreTools.Serialization.Deserializers /// Byte array to parse /// Offset into the byte array /// Filled BaseRelocationBlock on success, null on error - public static SabreTools.Models.PortableExecutable.BaseRelocation.Block? ParseBaseRelocationBlock(byte[] data, ref int offset) + public static SabreTools.Serialization.Models.PortableExecutable.BaseRelocation.Block? ParseBaseRelocationBlock(byte[] data, ref int offset) { - var obj = new SabreTools.Models.PortableExecutable.BaseRelocation.Block(); + var obj = new SabreTools.Serialization.Models.PortableExecutable.BaseRelocation.Block(); obj.PageRVA = data.ReadUInt32LittleEndian(ref offset); obj.BlockSize = data.ReadUInt32LittleEndian(ref offset); @@ -542,7 +542,7 @@ namespace SabreTools.Serialization.Deserializers return obj; int entryCount = ((int)obj.BlockSize - 8) / 2; - obj.TypeOffsetFieldEntries = new SabreTools.Models.PortableExecutable.BaseRelocation.TypeOffsetFieldEntry[entryCount]; + obj.TypeOffsetFieldEntries = new SabreTools.Serialization.Models.PortableExecutable.BaseRelocation.TypeOffsetFieldEntry[entryCount]; for (int i = 0; i < obj.TypeOffsetFieldEntries.Length; i++) { if (offset + 2 >= data.Length) @@ -559,12 +559,12 @@ namespace SabreTools.Serialization.Deserializers /// /// Byte array to parse /// Filled base relocation table on success, null on error - public static SabreTools.Models.PortableExecutable.BaseRelocation.Block[]? ParseBaseRelocationTable(byte[]? data) + public static SabreTools.Serialization.Models.PortableExecutable.BaseRelocation.Block[]? ParseBaseRelocationTable(byte[]? data) { if (data == null) return null; - var obj = new List(); + var obj = new List(); int offset = 0; while (offset + 8 <= data.Length) @@ -591,9 +591,9 @@ namespace SabreTools.Serialization.Deserializers /// Byte array to parse /// Offset into the byte array /// Filled BaseRelocationTypeOffsetFieldEntry on success, null on error - public static SabreTools.Models.PortableExecutable.BaseRelocation.TypeOffsetFieldEntry ParseBaseRelocationTypeOffsetFieldEntry(byte[] data, ref int offset) + public static SabreTools.Serialization.Models.PortableExecutable.BaseRelocation.TypeOffsetFieldEntry ParseBaseRelocationTypeOffsetFieldEntry(byte[] data, ref int offset) { - var obj = new SabreTools.Models.PortableExecutable.BaseRelocation.TypeOffsetFieldEntry(); + var obj = new SabreTools.Serialization.Models.PortableExecutable.BaseRelocation.TypeOffsetFieldEntry(); ushort typeAndOffsetField = data.ReadUInt16LittleEndian(ref offset); obj.BaseRelocationType = (BaseRelocationTypes)(typeAndOffsetField >> 12); @@ -640,9 +640,9 @@ namespace SabreTools.Serialization.Deserializers /// Byte array to parse /// Offset into the byte array /// Filled DebugDirectoryEntry on success, null on error - public static SabreTools.Models.PortableExecutable.DebugData.Entry ParseDebugDirectoryEntry(byte[] data, ref int offset) + public static SabreTools.Serialization.Models.PortableExecutable.DebugData.Entry ParseDebugDirectoryEntry(byte[] data, ref int offset) { - var obj = new SabreTools.Models.PortableExecutable.DebugData.Entry(); + var obj = new SabreTools.Serialization.Models.PortableExecutable.DebugData.Entry(); obj.Characteristics = data.ReadUInt32LittleEndian(ref offset); obj.TimeDateStamp = data.ReadUInt32LittleEndian(ref offset); @@ -661,14 +661,14 @@ namespace SabreTools.Serialization.Deserializers /// /// Byte array to parse /// Filled DebugTable on success, null on error - public static SabreTools.Models.PortableExecutable.DebugData.Table? ParseDebugTable(byte[]? data) + public static SabreTools.Serialization.Models.PortableExecutable.DebugData.Table? ParseDebugTable(byte[]? data) { if (data == null) return null; - var obj = new SabreTools.Models.PortableExecutable.DebugData.Table(); + var obj = new SabreTools.Serialization.Models.PortableExecutable.DebugData.Table(); - var table = new List(); + var table = new List(); int offset = 0; while (offset < data.Length) @@ -693,12 +693,12 @@ namespace SabreTools.Serialization.Deserializers /// /// Byte array to parse /// Filled DelayLoadDirectoryTable on success, null on error - public static SabreTools.Models.PortableExecutable.DelayLoad.DirectoryTable? ParseDelayLoadDirectoryTable(byte[]? data) + public static SabreTools.Serialization.Models.PortableExecutable.DelayLoad.DirectoryTable? ParseDelayLoadDirectoryTable(byte[]? data) { if (data == null) return null; - var obj = new SabreTools.Models.PortableExecutable.DelayLoad.DirectoryTable(); + var obj = new SabreTools.Serialization.Models.PortableExecutable.DelayLoad.DirectoryTable(); int offset = 0; obj.Attributes = data.ReadUInt32LittleEndian(ref offset); @@ -737,9 +737,9 @@ namespace SabreTools.Serialization.Deserializers /// Stream to parse /// Number of entries in the table /// Filled ExportAddressTable on success, null on error - public static SabreTools.Models.PortableExecutable.Export.AddressTableEntry[] ParseExportAddressTable(Stream data, uint entries) + public static SabreTools.Serialization.Models.PortableExecutable.Export.AddressTableEntry[] ParseExportAddressTable(Stream data, uint entries) { - var obj = new SabreTools.Models.PortableExecutable.Export.AddressTableEntry[entries]; + var obj = new SabreTools.Serialization.Models.PortableExecutable.Export.AddressTableEntry[entries]; for (int i = 0; i < obj.Length; i++) { @@ -754,9 +754,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled ExportAddressTableEntry on success, null on error - public static SabreTools.Models.PortableExecutable.Export.AddressTableEntry ParseExportAddressTableEntry(Stream data) + public static SabreTools.Serialization.Models.PortableExecutable.Export.AddressTableEntry ParseExportAddressTableEntry(Stream data) { - var obj = new SabreTools.Models.PortableExecutable.Export.AddressTableEntry(); + var obj = new SabreTools.Serialization.Models.PortableExecutable.Export.AddressTableEntry(); obj.ExportRVA = data.ReadUInt32LittleEndian(); obj.ForwarderRVA = obj.ExportRVA; @@ -770,9 +770,9 @@ namespace SabreTools.Serialization.Deserializers /// Byte array to parse /// Offset into the byte array /// Filled ExportDirectoryTable on success, null on error - public static SabreTools.Models.PortableExecutable.Export.DirectoryTable ParseExportDirectoryTable(byte[] data, ref int offset) + public static SabreTools.Serialization.Models.PortableExecutable.Export.DirectoryTable ParseExportDirectoryTable(byte[] data, ref int offset) { - var obj = new SabreTools.Models.PortableExecutable.Export.DirectoryTable(); + var obj = new SabreTools.Serialization.Models.PortableExecutable.Export.DirectoryTable(); obj.ExportFlags = data.ReadUInt32LittleEndian(ref offset); obj.TimeDateStamp = data.ReadUInt32LittleEndian(ref offset); @@ -797,9 +797,9 @@ namespace SabreTools.Serialization.Deserializers /// Set of pointers to process /// Section table to use for virtual address translation /// Filled ExportNameTable on success, null on error - public static SabreTools.Models.PortableExecutable.Export.NameTable ParseExportNameTable(Stream data, long initialOffset, uint[] pointers, SectionHeader[] sections) + public static SabreTools.Serialization.Models.PortableExecutable.Export.NameTable ParseExportNameTable(Stream data, long initialOffset, uint[] pointers, SectionHeader[] sections) { - var obj = new SabreTools.Models.PortableExecutable.Export.NameTable(); + var obj = new SabreTools.Serialization.Models.PortableExecutable.Export.NameTable(); obj.Strings = new string[pointers.Length]; for (int i = 0; i < obj.Strings.Length; i++) @@ -827,9 +827,9 @@ namespace SabreTools.Serialization.Deserializers /// Stream to parse /// Number of entries in the table /// Filled ExportNamePointerTable on success, null on error - public static SabreTools.Models.PortableExecutable.Export.NamePointerTable ParseExportNamePointerTable(Stream data, uint entries) + public static SabreTools.Serialization.Models.PortableExecutable.Export.NamePointerTable ParseExportNamePointerTable(Stream data, uint entries) { - var obj = new SabreTools.Models.PortableExecutable.Export.NamePointerTable(); + var obj = new SabreTools.Serialization.Models.PortableExecutable.Export.NamePointerTable(); obj.Pointers = new uint[entries]; for (int i = 0; i < obj.Pointers.Length; i++) @@ -846,9 +846,9 @@ namespace SabreTools.Serialization.Deserializers /// Stream to parse /// Number of entries in the table /// Filled ExportOrdinalTable on success, null on error - public static SabreTools.Models.PortableExecutable.Export.OrdinalTable ParseExportOrdinalTable(Stream data, uint entries) + public static SabreTools.Serialization.Models.PortableExecutable.Export.OrdinalTable ParseExportOrdinalTable(Stream data, uint entries) { - var obj = new SabreTools.Models.PortableExecutable.Export.OrdinalTable(); + var obj = new SabreTools.Serialization.Models.PortableExecutable.Export.OrdinalTable(); obj.Indexes = new ushort[entries]; for (int i = 0; i < obj.Indexes.Length; i++) @@ -921,13 +921,13 @@ namespace SabreTools.Serialization.Deserializers /// Import address tables /// Section table to use for virtual address translation /// Filled HintNameTable on success, null on error - public static SabreTools.Models.PortableExecutable.Import.HintNameTableEntry[] ParseHintNameTable(Stream data, + public static SabreTools.Serialization.Models.PortableExecutable.Import.HintNameTableEntry[] ParseHintNameTable(Stream data, long initialOffset, - Dictionary importLookupTables, - Dictionary importAddressTables, + Dictionary importLookupTables, + Dictionary importAddressTables, SectionHeader[] sections) { - var importHintNameTable = new List(); + var importHintNameTable = new List(); if (importLookupTables.Count > 0 || importAddressTables.Count > 0) { @@ -1005,9 +1005,9 @@ namespace SabreTools.Serialization.Deserializers /// /// Stream to parse /// Filled HintNameTableEntry on success, null on error - public static SabreTools.Models.PortableExecutable.Import.HintNameTableEntry ParseHintNameTableEntry(Stream data) + public static SabreTools.Serialization.Models.PortableExecutable.Import.HintNameTableEntry ParseHintNameTableEntry(Stream data) { - var obj = new SabreTools.Models.PortableExecutable.Import.HintNameTableEntry(); + var obj = new SabreTools.Serialization.Models.PortableExecutable.Import.HintNameTableEntry(); obj.Hint = data.ReadUInt16LittleEndian(); obj.Name = data.ReadNullTerminatedAnsiString(); @@ -1021,9 +1021,9 @@ namespace SabreTools.Serialization.Deserializers /// Stream to parse /// Optional header magic number indicating PE32 or PE32+ /// Filled ImportAddressTable on success, null on error - public static SabreTools.Models.PortableExecutable.Import.AddressTableEntry[] ParseImportAddressTable(Stream data, OptionalHeaderMagicNumber magic) + public static SabreTools.Serialization.Models.PortableExecutable.Import.AddressTableEntry[] ParseImportAddressTable(Stream data, OptionalHeaderMagicNumber magic) { - var obj = new List(); + var obj = new List(); // Loop until the last item (all nulls) are found while (data.Position < data.Length) @@ -1050,13 +1050,13 @@ namespace SabreTools.Serialization.Deserializers /// Directory table entries containing the addresses /// Section table to use for virtual address translation /// Filled ImportAddressTables on success, null on error - public static Dictionary ParseImportAddressTables(Stream data, + public static Dictionary ParseImportAddressTables(Stream data, long initialOffset, OptionalHeaderMagicNumber magic, - SabreTools.Models.PortableExecutable.Import.DirectoryTableEntry[] entries, + SabreTools.Serialization.Models.PortableExecutable.Import.DirectoryTableEntry[] entries, SectionHeader[] sections) { - var obj = new Dictionary(); + var obj = new Dictionary(); for (int i = 0; i < entries.Length; i++) { @@ -1083,9 +1083,9 @@ namespace SabreTools.Serialization.Deserializers /// Stream to parse /// Optional header magic number /// Filled ImportAddressTableEntry on success, null on error - public static SabreTools.Models.PortableExecutable.Import.AddressTableEntry ParseImportAddressTableEntry(Stream data, OptionalHeaderMagicNumber magic) + public static SabreTools.Serialization.Models.PortableExecutable.Import.AddressTableEntry ParseImportAddressTableEntry(Stream data, OptionalHeaderMagicNumber magic) { - var obj = new SabreTools.Models.PortableExecutable.Import.AddressTableEntry(); + var obj = new SabreTools.Serialization.Models.PortableExecutable.Import.AddressTableEntry(); if (magic == OptionalHeaderMagicNumber.PE32) { @@ -1115,9 +1115,9 @@ namespace SabreTools.Serialization.Deserializers /// Byte array to parse /// Offset into the byte array /// Filled ImportDirectoryTable on success, null on error - public static SabreTools.Models.PortableExecutable.Import.DirectoryTableEntry[] ParseImportDirectoryTable(byte[] data, ref int offset) + public static SabreTools.Serialization.Models.PortableExecutable.Import.DirectoryTableEntry[] ParseImportDirectoryTable(byte[] data, ref int offset) { - var obj = new List(); + var obj = new List(); // Loop until the last item (all nulls) are found while (offset < data.Length) @@ -1143,9 +1143,9 @@ namespace SabreTools.Serialization.Deserializers /// Byte array to parse /// Offset into the byte array /// Filled ImportDirectoryTableEntry on success, null on error - public static SabreTools.Models.PortableExecutable.Import.DirectoryTableEntry ParseImportDirectoryTableEntry(byte[] data, ref int offset) + public static SabreTools.Serialization.Models.PortableExecutable.Import.DirectoryTableEntry ParseImportDirectoryTableEntry(byte[] data, ref int offset) { - var obj = new SabreTools.Models.PortableExecutable.Import.DirectoryTableEntry(); + var obj = new SabreTools.Serialization.Models.PortableExecutable.Import.DirectoryTableEntry(); obj.ImportLookupTableRVA = data.ReadUInt32LittleEndian(ref offset); obj.TimeDateStamp = data.ReadUInt32LittleEndian(ref offset); @@ -1162,9 +1162,9 @@ namespace SabreTools.Serialization.Deserializers /// Stream to parse /// Optional header magic number indicating PE32 or PE32+ /// Filled ImportLookupTable on success, null on error - public static SabreTools.Models.PortableExecutable.Import.LookupTableEntry[] ParseImportLookupTable(Stream data, OptionalHeaderMagicNumber magic) + public static SabreTools.Serialization.Models.PortableExecutable.Import.LookupTableEntry[] ParseImportLookupTable(Stream data, OptionalHeaderMagicNumber magic) { - var obj = new List(); + var obj = new List(); // Loop until the last item (all nulls) are found while (data.Position < data.Length) @@ -1191,14 +1191,14 @@ namespace SabreTools.Serialization.Deserializers /// Directory table entries containing the addresses /// Section table to use for virtual address translation /// Filled ImportLookupTables on success, null on error - public static Dictionary ParseImportLookupTables(Stream data, + public static Dictionary ParseImportLookupTables(Stream data, long initialOffset, OptionalHeaderMagicNumber magic, - SabreTools.Models.PortableExecutable.Import.DirectoryTableEntry[] entries, + SabreTools.Serialization.Models.PortableExecutable.Import.DirectoryTableEntry[] entries, SectionHeader[] sections) { // Lookup tables - var obj = new Dictionary(); + var obj = new Dictionary(); for (int i = 0; i < entries.Length; i++) { @@ -1225,9 +1225,9 @@ namespace SabreTools.Serialization.Deserializers /// Stream to parse /// Optional header magic number /// Filled ImportLookupTableEntry on success, null on error - public static SabreTools.Models.PortableExecutable.Import.LookupTableEntry ParseImportLookupTableEntry(Stream data, OptionalHeaderMagicNumber magic) + public static SabreTools.Serialization.Models.PortableExecutable.Import.LookupTableEntry ParseImportLookupTableEntry(Stream data, OptionalHeaderMagicNumber magic) { - var obj = new SabreTools.Models.PortableExecutable.Import.LookupTableEntry(); + var obj = new SabreTools.Serialization.Models.PortableExecutable.Import.LookupTableEntry(); if (magic == OptionalHeaderMagicNumber.PE32) { @@ -1275,11 +1275,11 @@ namespace SabreTools.Serialization.Deserializers /// Stream to parse /// Size of the optional header /// Filled OptionalHeader on success, null on error - public static SabreTools.Models.PortableExecutable.OptionalHeader ParseOptionalHeader(Stream data, int optionalSize) + public static SabreTools.Serialization.Models.PortableExecutable.OptionalHeader ParseOptionalHeader(Stream data, int optionalSize) { long initialOffset = data.Position; - var obj = new SabreTools.Models.PortableExecutable.OptionalHeader(); + var obj = new SabreTools.Serialization.Models.PortableExecutable.OptionalHeader(); #region Standard Fields @@ -1431,7 +1431,7 @@ namespace SabreTools.Serialization.Deserializers ref int dataOffset, long tableStart, long tableLength, - SabreTools.Models.PortableExecutable.Resource.DirectoryTable? table, + SabreTools.Serialization.Models.PortableExecutable.Resource.DirectoryTable? table, SectionHeader[] sections) { if (tableData == null) @@ -1484,9 +1484,9 @@ namespace SabreTools.Serialization.Deserializers /// Byte array to parse /// Offset into the byte array /// Filled ResourceDataEntry on success, null on error - public static SabreTools.Models.PortableExecutable.Resource.DataEntry ParseResourceDataEntry(byte[] data, ref int offset) + public static SabreTools.Serialization.Models.PortableExecutable.Resource.DataEntry ParseResourceDataEntry(byte[] data, ref int offset) { - var obj = new SabreTools.Models.PortableExecutable.Resource.DataEntry(); + var obj = new SabreTools.Serialization.Models.PortableExecutable.Resource.DataEntry(); obj.DataRVA = data.ReadUInt32LittleEndian(ref offset); obj.Size = data.ReadUInt32LittleEndian(ref offset); @@ -1503,9 +1503,9 @@ namespace SabreTools.Serialization.Deserializers /// Offset into the byte array /// Indicates if the value is a name entry or not /// Filled ResourceDirectoryEntry on success, null on error - public static SabreTools.Models.PortableExecutable.Resource.DirectoryEntry ParseResourceDirectoryEntry(byte[] data, ref int offset, bool nameEntry) + public static SabreTools.Serialization.Models.PortableExecutable.Resource.DirectoryEntry ParseResourceDirectoryEntry(byte[] data, ref int offset, bool nameEntry) { - var obj = new SabreTools.Models.PortableExecutable.Resource.DirectoryEntry(); + var obj = new SabreTools.Serialization.Models.PortableExecutable.Resource.DirectoryEntry(); // TODO: Figure out why the high bit is set for names // The original version of this code also had this fix, but there @@ -1532,9 +1532,9 @@ namespace SabreTools.Serialization.Deserializers /// Byte array to parse /// Offset into the byte array /// Filled ResourceDirectoryString on success, null on error - public static SabreTools.Models.PortableExecutable.Resource.DirectoryString ParseResourceDirectoryString(byte[] data, ref int offset) + public static SabreTools.Serialization.Models.PortableExecutable.Resource.DirectoryString ParseResourceDirectoryString(byte[] data, ref int offset) { - var obj = new SabreTools.Models.PortableExecutable.Resource.DirectoryString(); + var obj = new SabreTools.Serialization.Models.PortableExecutable.Resource.DirectoryString(); obj.Length = data.ReadUInt16LittleEndian(ref offset); if (obj.Length > 0 && offset + (obj.Length * 2) <= data.Length) @@ -1549,12 +1549,12 @@ namespace SabreTools.Serialization.Deserializers /// Byte array to parse /// Offset into the byte array /// Filled ResourceDirectoryTable on success, null on error - public static SabreTools.Models.PortableExecutable.Resource.DirectoryTable? ParseResourceDirectoryTable(byte[]? tableData, ref int offset) + public static SabreTools.Serialization.Models.PortableExecutable.Resource.DirectoryTable? ParseResourceDirectoryTable(byte[]? tableData, ref int offset) { if (tableData == null) return null; - var obj = new SabreTools.Models.PortableExecutable.Resource.DirectoryTable(); + var obj = new SabreTools.Serialization.Models.PortableExecutable.Resource.DirectoryTable(); obj.Characteristics = tableData.ReadUInt32LittleEndian(ref offset); if (obj.Characteristics != 0) @@ -1568,7 +1568,7 @@ namespace SabreTools.Serialization.Deserializers // Create the entry array int totalEntryCount = obj.NumberOfNameEntries + obj.NumberOfIDEntries; - obj.Entries = new SabreTools.Models.PortableExecutable.Resource.DirectoryEntry[totalEntryCount]; + obj.Entries = new SabreTools.Serialization.Models.PortableExecutable.Resource.DirectoryEntry[totalEntryCount]; if (obj.Entries.Length == 0) return obj; diff --git a/SabreTools.Serialization/Deserializers/SecuROMAddD.cs b/SabreTools.Serialization/Deserializers/SecuROMAddD.cs index dbcd9553..ac263574 100644 --- a/SabreTools.Serialization/Deserializers/SecuROMAddD.cs +++ b/SabreTools.Serialization/Deserializers/SecuROMAddD.cs @@ -1,7 +1,7 @@ using System.IO; using System.Text; using SabreTools.IO.Extensions; -using SabreTools.Models.SecuROM; +using SabreTools.Serialization.Models.SecuROM; namespace SabreTools.Serialization.Deserializers { diff --git a/SabreTools.Serialization/Deserializers/SecuROMDFA.cs b/SabreTools.Serialization/Deserializers/SecuROMDFA.cs index 78265255..65690441 100644 --- a/SabreTools.Serialization/Deserializers/SecuROMDFA.cs +++ b/SabreTools.Serialization/Deserializers/SecuROMDFA.cs @@ -2,8 +2,8 @@ using System.Collections.Generic; using System.IO; using System.Text; using SabreTools.IO.Extensions; -using SabreTools.Models.SecuROM; -using static SabreTools.Models.SecuROM.Constants; +using SabreTools.Serialization.Models.SecuROM; +using static SabreTools.Serialization.Models.SecuROM.Constants; namespace SabreTools.Serialization.Deserializers { diff --git a/SabreTools.Serialization/Deserializers/SecuROMMatroschkaPackage.cs b/SabreTools.Serialization/Deserializers/SecuROMMatroschkaPackage.cs index 671cc45d..3fbdfb4c 100644 --- a/SabreTools.Serialization/Deserializers/SecuROMMatroschkaPackage.cs +++ b/SabreTools.Serialization/Deserializers/SecuROMMatroschkaPackage.cs @@ -1,8 +1,8 @@ using System.IO; using System.Text; using SabreTools.IO.Extensions; -using SabreTools.Models.SecuROM; -using static SabreTools.Models.SecuROM.Constants; +using SabreTools.Serialization.Models.SecuROM; +using static SabreTools.Serialization.Models.SecuROM.Constants; namespace SabreTools.Serialization.Deserializers { diff --git a/SabreTools.Serialization/Deserializers/WiseOverlayHeader.cs b/SabreTools.Serialization/Deserializers/WiseOverlayHeader.cs index 6dc54c7f..4b186f9c 100644 --- a/SabreTools.Serialization/Deserializers/WiseOverlayHeader.cs +++ b/SabreTools.Serialization/Deserializers/WiseOverlayHeader.cs @@ -2,7 +2,7 @@ using System; using System.IO; using System.Text; using SabreTools.IO.Extensions; -using SabreTools.Models.WiseInstaller; +using SabreTools.Serialization.Models.WiseInstaller; namespace SabreTools.Serialization.Deserializers { diff --git a/SabreTools.Serialization/Deserializers/WiseScript.cs b/SabreTools.Serialization/Deserializers/WiseScript.cs index 863b0b92..14466ec4 100644 --- a/SabreTools.Serialization/Deserializers/WiseScript.cs +++ b/SabreTools.Serialization/Deserializers/WiseScript.cs @@ -2,8 +2,8 @@ using System; using System.Collections.Generic; using System.IO; using SabreTools.IO.Extensions; -using SabreTools.Models.WiseInstaller; -using SabreTools.Models.WiseInstaller.Actions; +using SabreTools.Serialization.Models.WiseInstaller; +using SabreTools.Serialization.Models.WiseInstaller.Actions; namespace SabreTools.Serialization.Deserializers { diff --git a/SabreTools.Serialization/Deserializers/WiseSectionHeader.cs b/SabreTools.Serialization/Deserializers/WiseSectionHeader.cs index 87a12e8a..541cea5d 100644 --- a/SabreTools.Serialization/Deserializers/WiseSectionHeader.cs +++ b/SabreTools.Serialization/Deserializers/WiseSectionHeader.cs @@ -2,8 +2,8 @@ using System.Collections.Generic; using System.IO; using System.Text; using SabreTools.IO.Extensions; -using SabreTools.Models.WiseInstaller; -using static SabreTools.Models.WiseInstaller.Constants; +using SabreTools.Serialization.Models.WiseInstaller; +using static SabreTools.Serialization.Models.WiseInstaller.Constants; namespace SabreTools.Serialization.Deserializers { diff --git a/SabreTools.Serialization/Extensions/NewExecutable.cs b/SabreTools.Serialization/Extensions/NewExecutable.cs index 319daee7..55b6b6c0 100644 --- a/SabreTools.Serialization/Extensions/NewExecutable.cs +++ b/SabreTools.Serialization/Extensions/NewExecutable.cs @@ -1,4 +1,4 @@ -using SabreTools.Models.NewExecutable; +using SabreTools.Serialization.Models.NewExecutable; namespace SabreTools.Serialization.Extensions { diff --git a/SabreTools.Serialization/Extensions/PortableExecutable.cs b/SabreTools.Serialization/Extensions/PortableExecutable.cs index 5a86c4e8..dd1521ee 100644 --- a/SabreTools.Serialization/Extensions/PortableExecutable.cs +++ b/SabreTools.Serialization/Extensions/PortableExecutable.cs @@ -4,10 +4,10 @@ using System.IO; using System.Text; using System.Xml.Serialization; using SabreTools.IO.Extensions; -using SabreTools.Models.COFF; -using SabreTools.Models.PortableExecutable; -using SabreTools.Models.PortableExecutable.Resource.Entries; -using SabreTools.Models.SecuROM; +using SabreTools.Serialization.Models.COFF; +using SabreTools.Serialization.Models.PortableExecutable; +using SabreTools.Serialization.Models.PortableExecutable.Resource.Entries; +using SabreTools.Serialization.Models.SecuROM; namespace SabreTools.Serialization.Extensions { @@ -110,9 +110,9 @@ namespace SabreTools.Serialization.Extensions /// Data to parse /// Offset into the byte array /// A filled NB10ProgramDatabase on success, null on error - public static SabreTools.Models.PortableExecutable.DebugData.NB10ProgramDatabase? ParseNB10ProgramDatabase(this byte[] data, ref int offset) + public static SabreTools.Serialization.Models.PortableExecutable.DebugData.NB10ProgramDatabase? ParseNB10ProgramDatabase(this byte[] data, ref int offset) { - var obj = new SabreTools.Models.PortableExecutable.DebugData.NB10ProgramDatabase(); + var obj = new SabreTools.Serialization.Models.PortableExecutable.DebugData.NB10ProgramDatabase(); obj.Signature = data.ReadUInt32LittleEndian(ref offset); if (obj.Signature != 0x3031424E) @@ -132,9 +132,9 @@ namespace SabreTools.Serialization.Extensions /// Data to parse /// Offset into the byte array /// A filled RSDSProgramDatabase on success, null on error - public static SabreTools.Models.PortableExecutable.DebugData.RSDSProgramDatabase? ParseRSDSProgramDatabase(this byte[] data, ref int offset) + public static SabreTools.Serialization.Models.PortableExecutable.DebugData.RSDSProgramDatabase? ParseRSDSProgramDatabase(this byte[] data, ref int offset) { - var obj = new SabreTools.Models.PortableExecutable.DebugData.RSDSProgramDatabase(); + var obj = new SabreTools.Serialization.Models.PortableExecutable.DebugData.RSDSProgramDatabase(); obj.Signature = data.ReadUInt32LittleEndian(ref offset); if (obj.Signature != 0x53445352) @@ -231,7 +231,7 @@ namespace SabreTools.Serialization.Extensions /// /// Resource data entry to parse into an accelerator table resource /// A filled accelerator table resource on success, null on error - public static AcceleratorTableEntry[]? AsAcceleratorTableResource(this SabreTools.Models.PortableExecutable.Resource.DataEntry? entry) + public static AcceleratorTableEntry[]? AsAcceleratorTableResource(this SabreTools.Serialization.Models.PortableExecutable.Resource.DataEntry? entry) { // If we have data that's invalid for this resource type, we can't do anything if (entry?.Data == null || entry.Data.Length % 8 != 0) @@ -260,7 +260,7 @@ namespace SabreTools.Serialization.Extensions /// /// Resource data entry to parse into a side-by-side assembly manifest /// A filled side-by-side assembly manifest on success, null on error - public static AssemblyManifest? AsAssemblyManifest(this SabreTools.Models.PortableExecutable.Resource.DataEntry? entry) + public static AssemblyManifest? AsAssemblyManifest(this SabreTools.Serialization.Models.PortableExecutable.Resource.DataEntry? entry) { // If we have an invalid entry, just skip if (entry?.Data == null) @@ -282,7 +282,7 @@ namespace SabreTools.Serialization.Extensions /// /// Resource data entry to parse into a dialog box /// A filled dialog box on success, null on error - public static DialogBoxResource? AsDialogBox(this SabreTools.Models.PortableExecutable.Resource.DataEntry? entry) + public static DialogBoxResource? AsDialogBox(this SabreTools.Serialization.Models.PortableExecutable.Resource.DataEntry? entry) { // If we have an invalid entry, just skip if (entry?.Data == null) @@ -759,7 +759,7 @@ namespace SabreTools.Serialization.Extensions /// /// Resource data entry to parse into a font group /// A filled font group on success, null on error - public static FontGroupHeader? AsFontGroup(this SabreTools.Models.PortableExecutable.Resource.DataEntry? entry) + public static FontGroupHeader? AsFontGroup(this SabreTools.Serialization.Models.PortableExecutable.Resource.DataEntry? entry) { // If we have an invalid entry, just skip if (entry?.Data == null) @@ -828,7 +828,7 @@ namespace SabreTools.Serialization.Extensions /// /// Resource data entry to parse into a menu /// A filled menu on success, null on error - public static MenuResource? AsMenu(this SabreTools.Models.PortableExecutable.Resource.DataEntry? entry) + public static MenuResource? AsMenu(this SabreTools.Serialization.Models.PortableExecutable.Resource.DataEntry? entry) { // If we have an invalid entry, just skip if (entry?.Data == null) @@ -924,7 +924,7 @@ namespace SabreTools.Serialization.Extensions /// /// Resource data entry to parse into a message table resource /// A filled message table resource on success, null on error - public static MessageResourceData? AsMessageResourceData(this SabreTools.Models.PortableExecutable.Resource.DataEntry? entry) + public static MessageResourceData? AsMessageResourceData(this SabreTools.Serialization.Models.PortableExecutable.Resource.DataEntry? entry) { // If we have an invalid entry, just skip if (entry?.Data == null) @@ -1012,10 +1012,10 @@ namespace SabreTools.Serialization.Extensions // Align to the DWORD boundary if we're not at the end data.AlignToBoundary(ref offset, 4); - var stringFileInfoChildren = new List(); + var stringFileInfoChildren = new List(); while ((offset - currentOffset) < stringFileInfo.Length) { - var stringTable = new SabreTools.Models.PortableExecutable.Resource.Entries.StringTable(); + var stringTable = new SabreTools.Serialization.Models.PortableExecutable.Resource.Entries.StringTable(); stringTable.Length = data.ReadUInt16LittleEndian(ref offset); stringTable.ValueLength = data.ReadUInt16LittleEndian(ref offset); @@ -1069,7 +1069,7 @@ namespace SabreTools.Serialization.Extensions /// /// Resource data entry to parse into a string table resource /// A filled string table resource on success, null on error - public static Dictionary? AsStringTable(this SabreTools.Models.PortableExecutable.Resource.DataEntry? entry) + public static Dictionary? AsStringTable(this SabreTools.Serialization.Models.PortableExecutable.Resource.DataEntry? entry) { // If we have an invalid entry, just skip if (entry?.Data == null) @@ -1161,7 +1161,7 @@ namespace SabreTools.Serialization.Extensions /// /// Resource data entry to parse into a version info resource /// A filled version info resource on success, null on error - public static VersionInfo? AsVersionInfo(this SabreTools.Models.PortableExecutable.Resource.DataEntry? entry) + public static VersionInfo? AsVersionInfo(this SabreTools.Serialization.Models.PortableExecutable.Resource.DataEntry? entry) { // If we have an invalid entry, just skip if (entry?.Data == null) @@ -1358,10 +1358,10 @@ namespace SabreTools.Serialization.Extensions /// Data to parse /// Offset into the byte array /// A filled ResourceHeader on success, null on error - public static SabreTools.Models.PortableExecutable.Resource.ResourceHeader ParseResourceHeader(this byte[] data, ref int offset) + public static SabreTools.Serialization.Models.PortableExecutable.Resource.ResourceHeader ParseResourceHeader(this byte[] data, ref int offset) { // Read in the table - var obj = new SabreTools.Models.PortableExecutable.Resource.ResourceHeader(); + var obj = new SabreTools.Serialization.Models.PortableExecutable.Resource.ResourceHeader(); obj.DataSize = data.ReadUInt32LittleEndian(ref offset); obj.HeaderSize = data.ReadUInt32LittleEndian(ref offset); diff --git a/SabreTools.Serialization/Models/AdvancedInstaller/FileEntry.cs b/SabreTools.Serialization/Models/AdvancedInstaller/FileEntry.cs new file mode 100644 index 00000000..733afeed --- /dev/null +++ b/SabreTools.Serialization/Models/AdvancedInstaller/FileEntry.cs @@ -0,0 +1,61 @@ +namespace SabreTools.Serialization.Models.AdvancedInstaller +{ + /// + /// Single entry in the file table + /// + public class FileEntry + { + /// + /// Unknown + /// + /// + /// Observed values: + /// - 00 00 00 00 (INI) + /// - 01 00 00 00 (MSI, CAB) + /// - 05 00 00 00 (DLL) + /// + public uint Unknown0 { get; set; } + + /// + /// Unknown + /// + /// + /// Observed values: + /// - 00 00 00 00 (MSI) + /// - 01 00 00 00 (CAB) + /// - 03 00 00 00 (INI) + /// - 0C 00 00 00 (DLL) + /// + public uint? Unknown1 { get; set; } + + /// + /// Unknown, always 0? + /// + /// + /// Observed values: + /// - 00 00 00 00 (DLL, MSI, CAB, INI) + /// + public uint? Unknown2 { get; set; } + + /// + /// Size of the file + /// + public uint FileSize { get; set; } + + /// + /// Offset of the file relative to the start + /// of the SFX stub + /// + public uint FileOffset { get; set; } + + /// + /// Size of the file name in characters + /// + public uint NameSize { get; set; } + + /// + /// Unicode-encoded file name + /// + public string? Name { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/AdvancedInstaller/Footer.cs b/SabreTools.Serialization/Models/AdvancedInstaller/Footer.cs new file mode 100644 index 00000000..b237ac6a --- /dev/null +++ b/SabreTools.Serialization/Models/AdvancedInstaller/Footer.cs @@ -0,0 +1,109 @@ +namespace SabreTools.Serialization.Models.AdvancedInstaller +{ + /// + /// Structure similar to the end of central directory + /// header in PKZIP files + /// + public class Footer + { + /// + /// Unknown + /// + /// + /// Observed values: + /// - 00 00 00 00 + /// + public uint Unknown0 { get; set; } + + /// + /// Size of the original filename? + /// + /// Doesn't exist in some cases? + public uint? OriginalFilenameSize { get; set; } + + /// + /// Unicode-encoded original filename? + /// + /// Doesn't exist in some cases? + public string? OriginalFilename { get; set; } + + /// + /// Unknown, possibly a string count? + /// + /// + /// Only seen when the preceeding two fields exist + /// + /// Observed values: + /// - 01 00 00 00 + /// + public uint? Unknown1 { get; set; } + + /// + /// Pointer to ? + /// + public uint FooterOffset { get; set; } + + /// + /// Number of entries that preceed the footer + /// + public uint EntryCount { get; set; } + + /// + /// Unknown + /// + /// + /// Observed values: + /// - 64 00 00 00 + /// + public uint Unknown2 { get; set; } + + /// + /// Unknown offset + /// + /// + /// Points to if no original filename. + /// Points to if contains an original filename. + /// + public uint UnknownOffset { get; set; } + + /// + /// Offset of the start of the file table + /// + public uint TablePointer { get; set; } + + /// + /// Offset to the start of the file data + /// + public uint FileDataStart { get; set; } + + /// + /// Hex string that looks like a key or other identifier + /// + /// 32 bytes + public string? HexString { get; set; } + + /// + /// Unknown + /// + /// + /// Offset pointer to + /// relative to the end of the signature if no filename + /// exists. + /// + /// Observed values: + /// - 32 00 00 00 (No original filename) + /// - 13 02 00 00 (Original filename) + /// + public uint Unknown3 { get; set; } + + /// + /// "ADVINSTSFX" + /// + public string? Signature { get; set; } + + /// + /// Unknown, always 0? Padding? + /// + public ushort? Unknown4 { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/AdvancedInstaller/SFX.cs b/SabreTools.Serialization/Models/AdvancedInstaller/SFX.cs new file mode 100644 index 00000000..537f9190 --- /dev/null +++ b/SabreTools.Serialization/Models/AdvancedInstaller/SFX.cs @@ -0,0 +1,29 @@ +namespace SabreTools.Serialization.Models.AdvancedInstaller +{ + /// + /// Represents the structure at the end of a Caphyon + /// Advanced Installer SFX file. These SFX files store + /// all files uncompressed sequentially in the overlay + /// of an executable. + /// + /// The design is similar to the end of central directory + /// in a PKZIP file. The footer needs to be read before + /// the entry table as both the pointer to the start of + /// the table as well as the entry count are included there. + /// + /// The layout of this is derived from the layout in the + /// physical file. + /// + public class SFX + { + /// + /// Set of file entries + /// + public FileEntry[]? Entries { get; set; } + + /// + /// Footer representing the central directory + /// + public Footer? Footer { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/COFF/Constants.cs b/SabreTools.Serialization/Models/COFF/Constants.cs new file mode 100644 index 00000000..202dc33a --- /dev/null +++ b/SabreTools.Serialization/Models/COFF/Constants.cs @@ -0,0 +1,20 @@ +namespace SabreTools.Serialization.Models.COFF +{ + public static class Constants + { + /// + /// Fixed size of + /// + public const int FileHeaderSize = 20; + + /// + /// Fixed size of + /// + public const int SectionHeaderSize = 40; + + /// + /// Fixed size of + /// + public const int SymbolTableEntrySize = 18; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/COFF/Enums.cs b/SabreTools.Serialization/Models/COFF/Enums.cs new file mode 100644 index 00000000..cf9acfbd --- /dev/null +++ b/SabreTools.Serialization/Models/COFF/Enums.cs @@ -0,0 +1,1726 @@ +using System; + +namespace SabreTools.Serialization.Models.COFF +{ + [Flags] + public enum Characteristics : ushort + { + /// + /// Image only, Windows CE, and Microsoft Windows NT and later. + /// This indicates that the file does not contain base relocations + /// and must therefore be loaded at its preferred base address. + /// If the base address is not available, the loader reports an + /// error. The default behavior of the linker is to strip base + /// relocations from executable (EXE) files. + /// + IMAGE_FILE_RELOCS_STRIPPED = 0x0001, + + /// + /// Image only. This indicates that the image file is valid and + /// can be run. If this flag is not set, it indicates a linker error. + /// + IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002, + + /// + /// COFF line numbers have been removed. This flag is deprecated + /// and should be zero. + /// + IMAGE_FILE_LINE_NUMS_STRIPPED = 0x0004, + + /// + /// COFF symbol table entries for local symbols have been removed. + /// This flag is deprecated and should be zero. + /// + IMAGE_FILE_LOCAL_SYMS_STRIPPED = 0x0008, + + /// + /// Obsolete. Aggressively trim working set. This flag is deprecated + /// for Windows 2000 and later and must be zero. + /// + IMAGE_FILE_AGGRESSIVE_WS_TRIM = 0x0010, + + /// + /// Application can handle > 2-GB addresses. + /// + IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020, + + /// + /// This flag is reserved for future use. + /// + RESERVED = 0x0040, + + /// + /// Little endian: the least significant bit (LSB) precedes the most + /// significant bit (MSB) in memory. This flag is deprecated and + /// should be zero. + /// + IMAGE_FILE_BYTES_REVERSED_LO = 0x0080, + + /// + /// Machine is based on a 32-bit-word architecture. + /// + IMAGE_FILE_32BIT_MACHINE = 0x0100, + + /// + /// Debugging information is removed from the image file. + /// + IMAGE_FILE_DEBUG_STRIPPED = 0x0200, + + /// + /// If the image is on removable media, fully load it and + /// copy it to the swap file. + /// + IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = 0x0400, + + /// + /// If the image is on network media, fully load it and copy + /// it to the swap file. + /// + IMAGE_FILE_NET_RUN_FROM_SWAP = 0x0800, + + /// + /// The image file is a system file, not a user program. + /// + IMAGE_FILE_SYSTEM = 0x1000, + + /// + /// The image file is a dynamic-link library (DLL). Such files + /// are considered executable files for almost all purposes, + /// although they cannot be directly run. + /// + IMAGE_FILE_DLL = 0x2000, + + /// + /// The file should be run only on a uniprocessor machine. + /// + IMAGE_FILE_UP_SYSTEM_ONLY = 0x4000, + + /// + /// Big endian: the MSB precedes the LSB in memory. This flag + /// is deprecated and should be zero. + /// + IMAGE_FILE_BYTES_REVERSED_HI = 0x8000, + } + + public enum MachineType : ushort + { + /// + /// The content of this field is assumed to be applicable to any machine type + /// + IMAGE_FILE_MACHINE_UNKNOWN = 0x0000, + + /// + /// Matsushita AM33 + /// + IMAGE_FILE_MACHINE_AM33 = 0x01D3, + + /// + /// x64 + /// + IMAGE_FILE_MACHINE_AMD64 = 0x8664, + + /// + /// ARM little endian + /// + IMAGE_FILE_MACHINE_ARM = 0x01C0, + + /// + /// ARM64 little endian + /// + IMAGE_FILE_MACHINE_ARM64 = 0xAA64, + + /// + /// ARM Thumb-2 little endian + /// + IMAGE_FILE_MACHINE_ARMNT = 0x01C4, + + /// + /// EFI byte code + /// + IMAGE_FILE_MACHINE_EBC = 0x0EBC, + + /// + /// Intel 386 or later processors and compatible processors + /// + IMAGE_FILE_MACHINE_I386 = 0x014C, + + /// + /// Intel Itanium processor family + /// + IMAGE_FILE_MACHINE_IA64 = 0x0200, + + /// + /// LoongArch 32-bit processor family + /// + IMAGE_FILE_MACHINE_LOONGARCH32 = 0x6232, + + /// + /// LoongArch 64-bit processor family + /// + IMAGE_FILE_MACHINE_LOONGARCH64 = 0x6264, + + /// + /// Mitsubishi M32R little endian + /// + IMAGE_FILE_MACHINE_M32R = 0x9041, + + /// + /// MIPS16 + /// + IMAGE_FILE_MACHINE_MIPS16 = 0x0266, + + /// + /// MIPS with FPU + /// + IMAGE_FILE_MACHINE_MIPSFPU = 0x0366, + + /// + /// MIPS16 with FPU + /// + IMAGE_FILE_MACHINE_MIPSFPU16 = 0x0466, + + /// + /// Power PC little endian + /// + IMAGE_FILE_MACHINE_POWERPC = 0x01F0, + + /// + /// Power PC with floating point support + /// + IMAGE_FILE_MACHINE_POWERPCFP = 0x01F1, + + /// + /// MIPS little endian + /// + IMAGE_FILE_MACHINE_R4000 = 0x0166, + + /// + /// RISC-V 32-bit address space + /// + IMAGE_FILE_MACHINE_RISCV32 = 0x5032, + + /// + /// RISC-V 64-bit address space + /// + IMAGE_FILE_MACHINE_RISCV64 = 0x5064, + + /// + /// RISC-V 128-bit address space + /// + IMAGE_FILE_MACHINE_RISCV128 = 0x5128, + + /// + /// Hitachi SH3 + /// + IMAGE_FILE_MACHINE_SH3 = 0x01A2, + + /// + /// Hitachi SH3 DSP + /// + IMAGE_FILE_MACHINE_SH3DSP = 0x01A3, + + /// + /// Hitachi SH4 + /// + IMAGE_FILE_MACHINE_SH4 = 0x01A6, + + /// + /// Hitachi SH5 + /// + IMAGE_FILE_MACHINE_SH5 = 0x01A8, + + /// + /// Thumb + /// + IMAGE_FILE_MACHINE_THUMB = 0x01C2, + + /// + /// MIPS little-endian WCE v2 + /// + IMAGE_FILE_MACHINE_WCEMIPSV2 = 0x0169, + } + + public enum OptionalHeaderMagicNumber : ushort + { + ROMImage = 0x0107, + + PE32 = 0x010B, + + PE32Plus = 0x020B, + } + + public enum RelocationType : ushort + { + #region x64 Processors + + /// + /// The relocation is ignored. + /// + IMAGE_REL_AMD64_ABSOLUTE = 0x0000, + + /// + /// The 64-bit VA of the relocation target. + /// + IMAGE_REL_AMD64_ADDR64 = 0x0001, + + /// + /// The 32-bit VA of the relocation target. + /// + IMAGE_REL_AMD64_ADDR32 = 0x0002, + + /// + /// The 32-bit address without an image base (RVA). + /// + IMAGE_REL_AMD64_ADDR32NB = 0x0003, + + /// + /// The 32-bit relative address from the byte following the relocation. + /// + IMAGE_REL_AMD64_REL32 = 0x0004, + + /// + /// The 32-bit address relative to byte distance 1 from the relocation. + /// + IMAGE_REL_AMD64_REL32_1 = 0x0005, + + /// + /// The 32-bit address relative to byte distance 2 from the relocation. + /// + IMAGE_REL_AMD64_REL32_2 = 0x0006, + + /// + /// The 32-bit address relative to byte distance 3 from the relocation. + /// + IMAGE_REL_AMD64_REL32_3 = 0x0007, + + /// + /// The 32-bit address relative to byte distance 4 from the relocation. + /// + IMAGE_REL_AMD64_REL32_4 = 0x0008, + + /// + /// The 32-bit address relative to byte distance 5 from the relocation. + /// + IMAGE_REL_AMD64_REL32_5 = 0x0009, + + /// + /// The 16-bit section index of the section that contains the target. + /// This is used to support debugging information. + /// + IMAGE_REL_AMD64_SECTION = 0x000A, + + /// + /// The 32-bit offset of the target from the beginning of its section. + /// This is used to support debugging information and static thread + /// local storage. + /// + IMAGE_REL_AMD64_SECREL = 0x000B, + + /// + /// A 7-bit unsigned offset from the base of the section that contains + /// the target. + /// + IMAGE_REL_AMD64_SECREL7 = 0x000C, + + /// + /// CLR tokens. + /// + IMAGE_REL_AMD64_TOKEN = 0x000D, + + /// + /// A 32-bit signed span-dependent value emitted into the object. + /// + IMAGE_REL_AMD64_SREL32 = 0x000E, + + /// + /// A pair that must immediately follow every span-dependent value. + /// + IMAGE_REL_AMD64_PAIR = 0x000F, + + /// + /// A 32-bit signed span-dependent value that is applied at link time. + /// + IMAGE_REL_AMD64_SSPAN32 = 0x0010, + + #endregion + + #region ARM Processors + + /// + /// The relocation is ignored. + /// + IMAGE_REL_ARM_ABSOLUTE = 0x0000, + + /// + /// The 32-bit VA of the target. + /// + IMAGE_REL_ARM_ADDR32 = 0x0001, + + /// + /// The 32-bit RVA of the target. + /// + IMAGE_REL_ARM_ADDR32NB = 0x0002, + + /// + /// The 24-bit relative displacement to the target. + /// + IMAGE_REL_ARM_BRANCH24 = 0x0003, + + /// + /// The reference to a subroutine call. The reference + /// consists of two 16-bit instructions with 11-bit offsets. + /// + IMAGE_REL_ARM_BRANCH11 = 0x0004, + + /// + /// The 32-bit relative address from the byte following the relocation. + /// + IMAGE_REL_ARM_REL32 = 0x000A, + + /// + /// The 16-bit section index of the section that contains the target. + /// This is used to support debugging information. + /// + IMAGE_REL_ARM_SECTION = 0x000E, + + /// + /// The 32-bit offset of the target from the beginning of its section. + /// This is used to support debugging information and static thread + /// local storage. + /// + IMAGE_REL_ARM_SECREL = 0x000F, + + /// + /// The 32-bit VA of the target.This relocation is applied using a MOVW + /// instruction for the low 16 bits followed by a MOVT for the high 16 bits. + /// + IMAGE_REL_ARM_MOV32 = 0x0010, + + /// + /// The 32-bit VA of the target.This relocation is applied using a MOVW + /// instruction for the low 16 bits followed by a MOVT for the high 16 bits. + /// + IMAGE_REL_THUMB_MOV32 = 0x0011, + + /// + /// The instruction is fixed up with the 21 - bit relative displacement to + /// the 2-byte aligned target. The least significant bit of the displacement + /// is always zero and is not stored. This relocation corresponds to a + /// Thumb-2 32-bit conditional B instruction. + /// + IMAGE_REL_THUMB_BRANCH20 = 0x0012, + + Unused = 0x0013, + + /// + /// The instruction is fixed up with the 25-bit relative displacement to + /// the 2-byte aligned target. The least significant bit of the displacement + /// is zero and is not stored. This relocation corresponds to a Thumb-2 B + /// instruction. + /// + IMAGE_REL_THUMB_BRANCH24 = 0x0014, + + /// + /// The instruction is fixed up with the 25-bit relative displacement to + /// the 4-byte aligned target. The low 2 bits of the displacement are zero + /// and are not stored. This relocation corresponds to a Thumb-2 BLX instruction. + /// + IMAGE_REL_THUMB_BLX23 = 0x0015, + + /// + /// The relocation is valid only when it immediately follows a ARM_REFHI or + /// THUMB_REFHI. Its SymbolTableIndex contains a displacement and not an index + /// into the symbol table. + /// + IMAGE_REL_ARM_PAIR = 0x0016, + + #endregion + + #region ARM64 Processors + + /// + /// The relocation is ignored. + /// + IMAGE_REL_ARM64_ABSOLUTE = 0x0000, + + /// + /// The 32-bit VA of the target. + /// + IMAGE_REL_ARM64_ADDR32 = 0x0001, + + /// + /// The 32-bit RVA of the target. + /// + IMAGE_REL_ARM64_ADDR32NB = 0x0002, + + /// + /// The 26-bit relative displacement to the target, for B and BL instructions. + /// + IMAGE_REL_ARM64_BRANCH26 = 0x0003, + + /// + /// The page base of the target, for ADRP instruction. + /// + IMAGE_REL_ARM64_PAGEBASE_REL21 = 0x0004, + + /// + /// The 12-bit relative displacement to the target, for instruction ADR + /// + IMAGE_REL_ARM64_REL21 = 0x0005, + + /// + /// The 12-bit page offset of the target, for instructions ADD/ADDS (immediate) + /// with zero shift. + /// + IMAGE_REL_ARM64_PAGEOFFSET_12A = 0x0006, + + /// + /// The 12-bit page offset of the target, for instruction LDR (indexed, + /// unsigned immediate). + /// + IMAGE_REL_ARM64_PAGEOFFSET_12L = 0x0007, + + /// + /// The 32-bit offset of the target from the beginning of its section. + /// This is used to support debugging information and static thread local storage. + /// + IMAGE_REL_ARM64_SECREL = 0x0008, + + /// + /// Bit 0:11 of section offset of the target, for instructions ADD/ADDS(immediate) + /// with zero shift. + /// + IMAGE_REL_ARM64_SECREL_LOW12A = 0x0009, + + /// + /// Bit 12:23 of section offset of the target, for instructions ADD/ADDS(immediate) + /// with zero shift. + /// + IMAGE_REL_ARM64_SECREL_HIGH12A = 0x000A, + + /// + /// Bit 0:11 of section offset of the target, for instruction LDR(indexed, + /// unsigned immediate). + /// + IMAGE_REL_ARM64_SECREL_LOW12L = 0x000B, + + /// + /// CLR token. + /// + IMAGE_REL_ARM64_TOKEN = 0x000C, + + /// + /// The 16-bit section index of the section that contains the target. + /// This is used to support debugging information. + /// + IMAGE_REL_ARM64_SECTION = 0x000D, + + /// + /// The 64-bit VA of the relocation target. + /// + IMAGE_REL_ARM64_ADDR64 = 0x000E, + + /// + /// The 19-bit offset to the relocation target, for conditional B instruction. + /// + IMAGE_REL_ARM64_BRANCH19 = 0x000F, + + /// + /// The 14-bit offset to the relocation target, for instructions TBZ and TBNZ. + /// + IMAGE_REL_ARM64_BRANCH14 = 0x0010, + + /// + /// The 32-bit relative address from the byte following the relocation. + /// + IMAGE_REL_ARM64_REL32 = 0x0011, + + #endregion + + #region Hitachi SuperH Processors + + /// + /// The relocation is ignored. + /// + IMAGE_REL_SH3_ABSOLUTE = 0x0000, + + /// + /// A reference to the 16-bit location that contains the VA of + /// the target symbol. + /// + IMAGE_REL_SH3_DIRECT16 = 0x0001, + + /// + /// The 32-bit VA of the target symbol. + /// + IMAGE_REL_SH3_DIRECT32 = 0x0002, + + /// + /// A reference to the 8-bit location that contains the VA of + /// the target symbol. + /// + IMAGE_REL_SH3_DIRECT8 = 0x0003, + + /// + /// A reference to the 8-bit instruction that contains the + /// effective 16-bit VA of the target symbol. + /// + IMAGE_REL_SH3_DIRECT8_WORD = 0x0004, + + /// + /// A reference to the 8-bit instruction that contains the + /// effective 32-bit VA of the target symbol. + /// + IMAGE_REL_SH3_DIRECT8_LONG = 0x0005, + + /// + /// A reference to the 8-bit location whose low 4 bits contain + /// the VA of the target symbol. + /// + IMAGE_REL_SH3_DIRECT4 = 0x0006, + + /// + /// A reference to the 8-bit instruction whose low 4 bits contain + /// the effective 16-bit VA of the target symbol. + /// + IMAGE_REL_SH3_DIRECT4_WORD = 0x0007, + + /// + /// A reference to the 8-bit instruction whose low 4 bits contain + /// the effective 32-bit VA of the target symbol. + /// + IMAGE_REL_SH3_DIRECT4_LONG = 0x0008, + + /// + /// A reference to the 8-bit instruction that contains the + /// effective 16-bit relative offset of the target symbol. + /// + IMAGE_REL_SH3_PCREL8_WORD = 0x0009, + + /// + /// A reference to the 8-bit instruction that contains the + /// effective 32-bit relative offset of the target symbol. + /// + IMAGE_REL_SH3_PCREL8_LONG = 0x000A, + + /// + /// A reference to the 16-bit instruction whose low 12 bits contain + /// the effective 16-bit relative offset of the target symbol. + /// + IMAGE_REL_SH3_PCREL12_WORD = 0x000B, + + /// + /// A reference to a 32-bit location that is the VA of the + /// section that contains the target symbol. + /// + IMAGE_REL_SH3_STARTOF_SECTION = 0x000C, + + /// + /// A reference to the 32-bit location that is the size of the + /// section that contains the target symbol. + /// + IMAGE_REL_SH3_SIZEOF_SECTION = 0x000D, + + /// + /// The 16-bit section index of the section that contains the target. + /// This is used to support debugging information. + /// + IMAGE_REL_SH3_SECTION = 0x000E, + + /// + /// The 32-bit offset of the target from the beginning of its section. + /// This is used to support debugging information and static thread + /// local storage. + /// + IMAGE_REL_SH3_SECREL = 0x000F, + + /// + /// The 32-bit RVA of the target symbol. + /// + IMAGE_REL_SH3_DIRECT32_NB = 0x0010, + + /// + /// GP relative. + /// + IMAGE_REL_SH3_GPREL4_LONG = 0x0011, + + /// + /// CLR token. + /// + IMAGE_REL_SH3_TOKEN = 0x0012, + + /// + /// The offset from the current instruction in longwords. If the NOMODE + /// bit is not set, insert the inverse of the low bit at bit 32 to + /// select PTA or PTB. + /// + IMAGE_REL_SHM_PCRELPT = 0x0013, + + /// + /// The low 16 bits of the 32-bit address. + /// + IMAGE_REL_SHM_REFLO = 0x0014, + + /// + /// The high 16 bits of the 32-bit address. + /// + IMAGE_REL_SHM_REFHALF = 0x0015, + + /// + /// The low 16 bits of the relative address. + /// + IMAGE_REL_SHM_RELLO = 0x0016, + + /// + /// The high 16 bits of the relative address. + /// + IMAGE_REL_SHM_RELHALF = 0x0017, + + /// + /// The relocation is valid only when it immediately follows a REFHALF, + /// RELHALF, or RELLO relocation. The SymbolTableIndex field of the + /// relocation contains a displacement and not an index into the symbol table. + /// + IMAGE_REL_SHM_PAIR = 0x0018, + + /// + /// The relocation ignores section mode. + /// + IMAGE_REL_SHM_NOMODE = 0x8000, + + #endregion + + #region IBM PowerPC Processors + + /// + /// The relocation is ignored. + /// + IMAGE_REL_PPC_ABSOLUTE = 0x0000, + + /// + /// The 64-bit VA of the target. + /// + IMAGE_REL_PPC_ADDR64 = 0x0001, + + /// + /// The 32-bit VA of the target. + /// + IMAGE_REL_PPC_ADDR32 = 0x0002, + + /// + /// The low 24 bits of the VA of the target. This is valid only when + /// the target symbol is absolute and can be sign-extended to its + /// original value. + /// + IMAGE_REL_PPC_ADDR24 = 0x0003, + + /// + /// The low 16 bits of the target's VA. + /// + IMAGE_REL_PPC_ADDR16 = 0x0004, + + /// + /// The low 14 bits of the target's VA. This is valid only when the + /// target symbol is absolute and can be sign-extended to its original + /// value. + /// + IMAGE_REL_PPC_ADDR14 = 0x0005, + + /// + /// A 24-bit PC-relative offset to the symbol's location. + /// + IMAGE_REL_PPC_REL24 = 0x0006, + + /// + /// A 14-bit PC-relative offset to the symbol's location. + /// + IMAGE_REL_PPC_REL14 = 0x0007, + + /// + /// The 32-bit RVA of the target. + /// + IMAGE_REL_PPC_ADDR32NB = 0x000A, + + /// + /// The 32-bit offset of the target from the beginning of its section. + /// This is used to support debugging information and static thread + /// local storage. + /// + IMAGE_REL_PPC_SECREL = 0x000B, + + /// + /// The 16-bit section index of the section that contains the target. + /// This is used to support debugging information. + /// + IMAGE_REL_PPC_SECTION = 0x000C, + + /// + /// The 16-bit offset of the target from the beginning of its section. + /// This is used to support debugging information and static thread + /// local storage. + /// + IMAGE_REL_PPC_SECREL16 = 0x000F, + + /// + /// The high 16 bits of the target's 32-bit VA. This is used for the + /// first instruction in a two-instruction sequence that loads a full + /// address. This relocation must be immediately followed by a PAIR + /// relocation whose SymbolTableIndex contains a signed 16-bit + /// displacement that is added to the upper 16 bits that was taken + /// from the location that is being relocated. + /// + IMAGE_REL_PPC_REFHI = 0x0010, + + /// + /// The low 16 bits of the target's VA. + /// + IMAGE_REL_PPC_REFLO = 0x0011, + + /// + /// A relocation that is valid only when it immediately follows a REFHI + /// or SECRELHI relocation. Its SymbolTableIndex contains a displacement + /// and not an index into the symbol table. + /// + IMAGE_REL_PPC_PAIR = 0x0012, + + /// + /// The low 16 bits of the 32-bit offset of the target from the beginning + /// of its section. + /// + IMAGE_REL_PPC_SECRELLO = 0x0013, + + /// + /// The 16-bit signed displacement of the target relative to the GP register. + /// + IMAGE_REL_PPC_GPREL = 0x0015, + + /// + /// The CLR token. + /// + IMAGE_REL_PPC_TOKEN = 0x0016, + + #endregion + + #region Intel 386 Processors + + /// + /// The relocation is ignored. + /// + IMAGE_REL_I386_ABSOLUTE = 0x0000, + + /// + /// Not supported. + /// + IMAGE_REL_I386_DIR16 = 0x0001, + + /// + /// Not supported. + /// + IMAGE_REL_I386_REL16 = 0x0002, + + /// + /// The target's 32-bit VA. + /// + IMAGE_REL_I386_DIR32 = 0x0006, + + /// + /// The target's 32-bit RVA. + /// + IMAGE_REL_I386_DIR32NB = 0x0007, + + /// + /// Not supported. + /// + IMAGE_REL_I386_SEG12 = 0x0009, + + /// + /// The 16-bit section index of the section that contains the target. + /// This is used to support debugging information. + /// + IMAGE_REL_I386_SECTION = 0x000A, + + /// + /// The 32-bit offset of the target from the beginning of its section. + /// This is used to support debugging information and static thread + /// local storage. + /// + IMAGE_REL_I386_SECREL = 0x000B, + + /// + /// The CLR token. + /// + IMAGE_REL_I386_TOKEN = 0x000C, + + /// + /// A 7-bit offset from the base of the section that contains the target. + /// + IMAGE_REL_I386_SECREL7 = 0x000D, + + /// + /// The 32-bit relative displacement to the target.This supports the x86 relative branch and call instructions. + /// + IMAGE_REL_I386_REL32 = 0x0014, + + #endregion + + #region Intel Itanium Processor Family (IPF) + + /// + /// The relocation is ignored. + /// + IMAGE_REL_IA64_ABSOLUTE = 0x0000, + + /// + /// The instruction relocation can be followed by an ADDEND relocation whose value is + /// added to the target address before it is inserted into the specified slot in the + /// IMM14 bundle. The relocation target must be absolute or the image must be fixed. + /// + IMAGE_REL_IA64_IMM14 = 0x0001, + + /// + /// The instruction relocation can be followed by an ADDEND relocation whose value is + /// added to the target address before it is inserted into the specified slot in the + /// IMM22 bundle. The relocation target must be absolute or the image must be fixed. + /// + IMAGE_REL_IA64_IMM22 = 0x0002, + + /// + /// The slot number of this relocation must be one (1). The relocation can be followed + /// by an ADDEND relocation whose value is added to the target address before it is + /// stored in all three slots of the IMM64 bundle. + /// + IMAGE_REL_IA64_IMM64 = 0x0003, + + /// + /// The target's 32-bit VA. This is supported only for /LARGEADDRESSAWARE:NO images. + /// + IMAGE_REL_IA64_DIR32 = 0x0004, + + /// + /// The target's 64-bit VA. + /// + IMAGE_REL_IA64_DIR64 = 0x0005, + + /// + /// The instruction is fixed up with the 25-bit relative displacement to the 16-bit + /// aligned target. The low 4 bits of the displacement are zero and are not stored. + /// + IMAGE_REL_IA64_PCREL21B = 0x0006, + + /// + /// The instruction is fixed up with the 25-bit relative displacement to the 16-bit + /// aligned target. The low 4 bits of the displacement, which are zero, are not stored. + /// + IMAGE_REL_IA64_PCREL21M = 0x0007, + + /// + /// The LSBs of this relocation's offset must contain the slot number whereas the rest + /// is the bundle address. The bundle is fixed up with the 25-bit relative displacement + /// to the 16-bit aligned target. The low 4 bits of the displacement are zero and are + /// not stored. + /// + IMAGE_REL_IA64_PCREL21F = 0x0008, + + /// + /// The instruction relocation can be followed by an ADDEND relocation whose value is + /// added to the target address and then a 22-bit GP-relative offset that is calculated + /// and applied to the GPREL22 bundle. + /// + IMAGE_REL_IA64_GPREL22 = 0x0009, + + /// + /// The instruction is fixed up with the 22-bit GP-relative offset to the target symbol's + /// literal table entry. The linker creates this literal table entry based on this + /// relocation and the ADDEND relocation that might follow. + /// + IMAGE_REL_IA64_LTOFF22 = 0x000A, + + /// + /// The 16-bit section index of the section contains the target. This is used to support + /// debugging information. + /// + IMAGE_REL_IA64_SECTION = 0x000B, + + /// + /// The instruction is fixed up with the 22-bit offset of the target from the beginning of + /// its section.This relocation can be followed immediately by an ADDEND relocation, + /// whose Value field contains the 32-bit unsigned offset of the target from the beginning + /// of the section. + /// + IMAGE_REL_IA64_SECREL22 = 0x000C, + + /// + /// The slot number for this relocation must be one (1). The instruction is fixed up with + /// the 64-bit offset of the target from the beginning of its section. This relocation can + /// be followed immediately by an ADDEND relocation whose Value field contains the 32-bit + /// unsigned offset of the target from the beginning of the section. + /// + IMAGE_REL_IA64_SECREL64I = 0x000D, + + /// + /// The address of data to be fixed up with the 32-bit offset of the target from the beginning + /// of its section. + /// + IMAGE_REL_IA64_SECREL32 = 0x000E, + + /// + /// The target's 32-bit RVA. + /// + IMAGE_REL_IA64_DIR32NB = 0x0010, + + /// + /// This is applied to a signed 14-bit immediate that contains the difference between two + /// relocatable targets. This is a declarative field for the linker that indicates that the + /// compiler has already emitted this value. + /// + IMAGE_REL_IA64_SREL14 = 0x0011, + + /// + /// This is applied to a signed 22-bit immediate that contains the difference between two + /// relocatable targets. This is a declarative field for the linker that indicates that the + /// compiler has already emitted this value. + /// + IMAGE_REL_IA64_SREL22 = 0x0012, + + /// + /// This is applied to a signed 32-bit immediate that contains the difference between two + /// relocatable values.This is a declarative field for the linker that indicates that the + /// compiler has already emitted this value. + /// + IMAGE_REL_IA64_SREL32 = 0x0013, + + /// + /// This is applied to an unsigned 32-bit immediate that contains the difference between + /// two relocatable values. This is a declarative field for the linker that indicates that + /// the compiler has already emitted this value. + /// + IMAGE_REL_IA64_UREL32 = 0x0014, + + /// + /// A 60-bit PC-relative fixup that always stays as a BRL instruction of an MLX bundle. + /// + IMAGE_REL_IA64_PCREL60X = 0x0015, + + /// + /// A 60-bit PC-relative fixup. If the target displacement fits in a signed 25-bit field, + /// convert the entire bundle to an MBB bundle with NOP. B in slot 1 and a 25-bit BR + /// instruction (with the 4 lowest bits all zero and dropped) in slot 2. + /// + IMAGE_REL_IA64_PCREL60B = 0x0016, + + /// + /// A 60-bit PC-relative fixup. If the target displacement fits in a signed 25-bit field, + /// convert the entire bundle to an MFB bundle with NOP. F in slot 1 and a 25-bit + /// (4 lowest bits all zero and dropped) BR instruction in slot 2. + /// + IMAGE_REL_IA64_PCREL60F = 0x0017, + + /// + /// A 60-bit PC-relative fixup. If the target displacement fits in a signed 25-bit field, + /// convert the entire bundle to an MIB bundle with NOP. I in slot 1 and a 25-bit + /// (4 lowest bits all zero and dropped) BR instruction in slot 2. + /// + IMAGE_REL_IA64_PCREL60I = 0x0018, + + /// + /// A 60-bit PC-relative fixup. If the target displacement fits in a signed 25-bit field, + /// convert the entire bundle to an MMB bundle with NOP. M in slot 1 and a 25-bit + /// (4 lowest bits all zero and dropped) BR instruction in slot 2. + /// + IMAGE_REL_IA64_PCREL60M = 0x0019, + + /// + /// A 64-bit GP-relative fixup. + /// + IMAGE_REL_IA64_IMMGPREL64 = 0x001a, + + /// + /// A CLR token. + /// + IMAGE_REL_IA64_TOKEN = 0x001b, + + /// + /// A 32-bit GP-relative fixup. + /// + IMAGE_REL_IA64_GPREL32 = 0x001c, + + /// + /// The relocation is valid only when it immediately follows one of the following relocations: + /// IMM14, IMM22, IMM64, GPREL22, LTOFF22, LTOFF64, SECREL22, SECREL64I, or SECREL32. + /// Its value contains the addend to apply to instructions within a bundle, not for data. + /// + IMAGE_REL_IA64_ADDEND = 0x001F, + + #endregion + + #region MIPS Processors + + /// + /// The relocation is ignored. + /// + IMAGE_REL_MIPS_ABSOLUTE = 0x0000, + + /// + /// The high 16 bits of the target's 32-bit VA. + /// + IMAGE_REL_MIPS_REFHALF = 0x0001, + + /// + /// The target's 32-bit VA. + /// + IMAGE_REL_MIPS_REFWORD = 0x0002, + + /// + /// The low 26 bits of the target's VA. This supports the MIPS J and JAL instructions. + /// + IMAGE_REL_MIPS_JMPADDR = 0x0003, + + /// + /// The high 16 bits of the target's 32-bit VA. This is used for the first instruction in a + /// two-instruction sequence that loads a full address. This relocation must be immediately + /// followed by a PAIR relocation whose SymbolTableIndex contains a signed 16-bit displacement + /// that is added to the upper 16 bits that are taken from the location that is being relocated. + /// + IMAGE_REL_MIPS_REFHI = 0x0004, + + /// + /// The low 16 bits of the target's VA. + /// + IMAGE_REL_MIPS_REFLO = 0x0005, + + /// + /// A 16-bit signed displacement of the target relative to the GP register. + /// + IMAGE_REL_MIPS_GPREL = 0x0006, + + /// + /// The same as IMAGE_REL_MIPS_GPREL. + /// + IMAGE_REL_MIPS_LITERAL = 0x0007, + + /// + /// The 16-bit section index of the section contains the target. + /// This is used to support debugging information. + /// + IMAGE_REL_MIPS_SECTION = 0x000A, + + /// + /// The 32-bit offset of the target from the beginning of its section. + /// This is used to support debugging information and static thread local storage. + /// + IMAGE_REL_MIPS_SECREL = 0x000B, + + /// + /// The low 16 bits of the 32-bit offset of the target from the beginning of its section. + /// + IMAGE_REL_MIPS_SECRELLO = 0x000C, + + /// + /// The high 16 bits of the 32-bit offset of the target from the beginning of its section. + /// An IMAGE_REL_MIPS_PAIR relocation must immediately follow this one. The SymbolTableIndex + /// of the PAIR relocation contains a signed 16-bit displacement that is added to the upper + /// 16 bits that are taken from the location that is being relocated. + /// + IMAGE_REL_MIPS_SECRELHI = 0x000D, + + /// + /// The low 26 bits of the target's VA. This supports the MIPS16 JAL instruction. + /// + IMAGE_REL_MIPS_JMPADDR16 = 0x0010, + + /// + /// The target's 32-bit RVA. + /// + IMAGE_REL_MIPS_REFWORDNB = 0x0022, + + /// + /// The relocation is valid only when it immediately follows a REFHI or SECRELHI relocation. + /// Its SymbolTableIndex contains a displacement and not an index into the symbol table. + /// + IMAGE_REL_MIPS_PAIR = 0x0025, + + #endregion + + #region Mitsubishi M32R + + /// + /// The relocation is ignored. + /// + IMAGE_REL_M32R_ABSOLUTE = 0x0000, + + /// + /// The target's 32-bit VA. + /// + IMAGE_REL_M32R_ADDR32 = 0x0001, + + /// + /// The target's 32-bit RVA. + /// + IMAGE_REL_M32R_ADDR32NB = 0x0002, + + /// + /// The target's 24-bit VA. + /// + IMAGE_REL_M32R_ADDR24 = 0x0003, + + /// + /// The target's 16-bit offset from the GP register. + /// + IMAGE_REL_M32R_GPREL16 = 0x0004, + + /// + /// The target's 24-bit offset from the program counter (PC), shifted left by + /// 2 bits and sign-extended + /// + IMAGE_REL_M32R_PCREL24 = 0x0005, + + /// + /// The target's 16-bit offset from the PC, shifted left by 2 bits and + /// sign-extended + /// + IMAGE_REL_M32R_PCREL16 = 0x0006, + + /// + /// The target's 8-bit offset from the PC, shifted left by 2 bits and + /// sign-extended + /// + IMAGE_REL_M32R_PCREL8 = 0x0007, + + /// + /// The 16 MSBs of the target VA. + /// + IMAGE_REL_M32R_REFHALF = 0x0008, + + /// + /// The 16 MSBs of the target VA, adjusted for LSB sign extension. This is used for + /// the first instruction in a two-instruction sequence that loads a full 32-bit address. + /// This relocation must be immediately followed by a PAIR relocation whose SymbolTableIndex + /// contains a signed 16-bit displacement that is added to the upper 16 bits that are + /// taken from the location that is being relocated. + /// + IMAGE_REL_M32R_REFHI = 0x0009, + + /// + /// The 16 LSBs of the target VA. + /// + IMAGE_REL_M32R_REFLO = 0x000A, + + /// + /// The relocation must follow the REFHI relocation.Its SymbolTableIndex contains a displacement + /// and not an index into the symbol table. + /// + IMAGE_REL_M32R_PAIR = 0x000B, + + /// + /// The 16-bit section index of the section that contains the target. This is used to support + /// debugging information. + /// + IMAGE_REL_M32R_SECTION = 0x000C, + + /// + /// The 32-bit offset of the target from the beginning of its section.This is used to support + /// debugging information and static thread local storage. + /// + IMAGE_REL_M32R_SECREL = 0x000D, + + /// + /// The CLR token. + /// + IMAGE_REL_M32R_TOKEN = 0x000E, + + #endregion + } + + [Flags] + public enum SectionFlags : uint + { + /// + /// Reserved for future use. + /// + RESERVED0 = 0x00000001, + + /// + /// Reserved for future use. + /// + RESERVED1 = 0x00000002, + + /// + /// Reserved for future use. + /// + RESERVED2 = 0x00000004, + + /// + /// The section should not be padded to the next boundary. + /// This flag is obsolete and is replaced by IMAGE_SCN_ALIGN_1BYTES. + /// This is valid only for object files. + /// + IMAGE_SCN_TYPE_NO_PAD = 0x00000008, + + /// + /// Reserved for future use. + /// + RESERVED4 = 0x00000010, + + /// + /// The section contains executable code. + /// + IMAGE_SCN_CNT_CODE = 0x00000020, + + /// + /// The section contains initialized data. + /// + IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040, + + /// + /// The section contains uninitialized data. + /// + IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080, + + /// + /// Reserved for future use. + /// + IMAGE_SCN_LNK_OTHER = 0x00000100, + + /// + /// The section contains comments or other information. The .drectve + /// section has this type. This is valid for object files only. + /// + IMAGE_SCN_LNK_INFO = 0x00000200, + + /// + /// Reserved for future use. + /// + RESERVED10 = 0x00000400, + + /// + /// The section will not become part of the image. This is valid + /// only for object files. + /// + IMAGE_SCN_LNK_REMOVE = 0x00000800, + + /// + /// The section contains COMDAT data. For more information, see COMDAT Sections + /// (Object Only). This is valid only for object files. + /// + IMAGE_SCN_LNK_COMDAT = 0x00001000, + + /// + /// The section contains data referenced through the global pointer (GP). + /// + IMAGE_SCN_GPREL = 0x00008000, + + /// + /// Reserved for future use. + /// + IMAGE_SCN_MEM_PURGEABLE = 0x00010000, + + /// + /// Reserved for future use. + /// + IMAGE_SCN_MEM_16BIT = 0x00020000, + + /// + /// Reserved for future use. + /// + IMAGE_SCN_MEM_LOCKED = 0x00040000, + + /// + /// Reserved for future use. + /// + IMAGE_SCN_MEM_PRELOAD = 0x00080000, + + /// + /// Align data on a 1-byte boundary. Valid only for object files. + /// + IMAGE_SCN_ALIGN_1BYTES = 0x00100000, + + /// + /// Align data on a 2-byte boundary. Valid only for object files. + /// + IMAGE_SCN_ALIGN_2BYTES = 0x00200000, + + /// + /// Align data on a 4-byte boundary. Valid only for object files. + /// + IMAGE_SCN_ALIGN_4BYTES = 0x00300000, + + /// + /// Align data on an 8-byte boundary. Valid only for object files. + /// + IMAGE_SCN_ALIGN_8BYTES = 0x00400000, + + /// + /// Align data on a 16-byte boundary. Valid only for object files. + /// + IMAGE_SCN_ALIGN_16BYTES = 0x00500000, + + /// + /// Align data on a 32-byte boundary. Valid only for object files. + /// + IMAGE_SCN_ALIGN_32BYTES = 0x00600000, + + /// + /// Align data on a 64-byte boundary. Valid only for object files. + /// + IMAGE_SCN_ALIGN_64BYTES = 0x00700000, + + /// + /// Align data on a 128-byte boundary. Valid only for object files. + /// + IMAGE_SCN_ALIGN_128BYTES = 0x00800000, + + /// + /// Align data on a 256-byte boundary. Valid only for object files. + /// + IMAGE_SCN_ALIGN_256BYTES = 0x00900000, + + /// + /// Align data on a 512-byte boundary. Valid only for object files. + /// + IMAGE_SCN_ALIGN_512BYTES = 0x00A00000, + + /// + /// Align data on a 1024-byte boundary. Valid only for object files. + /// + IMAGE_SCN_ALIGN_1024BYTES = 0x00B00000, + + /// + /// Align data on a 2048-byte boundary. Valid only for object files. + /// + IMAGE_SCN_ALIGN_2048BYTES = 0x00C00000, + + /// + /// Align data on a 4096-byte boundary. Valid only for object files. + /// + IMAGE_SCN_ALIGN_4096BYTES = 0x00D00000, + + /// + /// Align data on an 8192-byte boundary. Valid only for object files. + /// + IMAGE_SCN_ALIGN_8192BYTES = 0x00E00000, + + /// + /// The section contains extended relocations. + /// + IMAGE_SCN_LNK_NRELOC_OVFL = 0x01000000, + + /// + /// The section can be discarded as needed. + /// + IMAGE_SCN_MEM_DISCARDABLE = 0x02000000, + + /// + /// The section cannot be cached. + /// + IMAGE_SCN_MEM_NOT_CACHED = 0x04000000, + + /// + /// The section is not pageable. + /// + IMAGE_SCN_MEM_NOT_PAGED = 0x08000000, + + /// + /// The section can be shared in memory. + /// + IMAGE_SCN_MEM_SHARED = 0x10000000, + + /// + /// The section can be executed as code. + /// + IMAGE_SCN_MEM_EXECUTE = 0x20000000, + + /// + /// The section can be read. + /// + IMAGE_SCN_MEM_READ = 0x40000000, + + /// + /// The section can be written to. + /// + IMAGE_SCN_MEM_WRITE = 0x80000000, + } + + public enum SectionNumber : short + { + /// + /// The symbol record is not yet assigned a section. A value of + /// zero indicates that a reference to an external symbol is + /// defined elsewhere. A value of non-zero is a common symbol + /// with a size that is specified by the value. + /// + IMAGE_SYM_UNDEFINED = 0, + + /// + /// The symbol has an absolute (non-relocatable) value and + /// is not an address. + /// + IMAGE_SYM_ABSOLUTE = -1, + + /// + /// The symbol provides general type or debugging information + /// but does not correspond to a section. Microsoft tools use + /// this setting along with .file records (storage class FILE). + /// + IMAGE_SYM_DEBUG = -2, + } + + public enum StorageClass : byte + { + /// + /// A special symbol that represents the end of function, for debugging purposes. + /// + IMAGE_SYM_CLASS_END_OF_FUNCTION = 0xFF, + + /// + /// No assigned storage class. + /// + IMAGE_SYM_CLASS_NULL = 0x00, + + /// + /// The automatic (stack) variable.The Value field specifies the stack frame offset. + /// + IMAGE_SYM_CLASS_AUTOMATIC = 0x01, + + /// + /// A value that Microsoft tools use for external symbols. The Value field indicates + /// the size if the section number is IMAGE_SYM_UNDEFINED (0). If the section number + /// is not zero, then the Value field specifies the offset within the section. + /// + IMAGE_SYM_CLASS_EXTERNAL = 0x02, + + /// + /// The offset of the symbol within the section. If the Value field is zero, then + /// the symbol represents a section name. + /// + IMAGE_SYM_CLASS_STATIC = 0x03, + + /// + /// A register variable.The Value field specifies the register number. + /// + IMAGE_SYM_CLASS_REGISTER = 0x04, + + /// + /// A symbol that is defined externally. + /// + IMAGE_SYM_CLASS_EXTERNAL_DEF = 0x05, + + /// + /// A code label that is defined within the module. The Value field specifies the + /// offset of the symbol within the section. + /// + IMAGE_SYM_CLASS_LABEL = 0x06, + + /// + /// A reference to a code label that is not defined. + /// + IMAGE_SYM_CLASS_UNDEFINED_LABEL = 0x07, + + /// + /// The structure member. The Value field specifies the n th member. + /// + IMAGE_SYM_CLASS_MEMBER_OF_STRUCT = 0x08, + + /// + /// A formal argument (parameter) of a function. The Value field specifies the + /// n th argument. + /// + IMAGE_SYM_CLASS_ARGUMENT = 0x09, + + /// + /// The structure tag-name entry. + /// + IMAGE_SYM_CLASS_STRUCT_TAG = 0x0A, + + /// + /// A union member. The Value field specifies the n th member. + /// + IMAGE_SYM_CLASS_MEMBER_OF_UNION = 0x0B, + + /// + /// The Union tag-name entry. + /// + IMAGE_SYM_CLASS_UNION_TAG = 0x0C, + + /// + /// A Typedef entry. + /// + IMAGE_SYM_CLASS_TYPE_DEFINITION = 0x0D, + + /// + /// A static data declaration. + /// + IMAGE_SYM_CLASS_UNDEFINED_STATIC = 0x0E, + + /// + /// An enumerated type tagname entry. + /// + IMAGE_SYM_CLASS_ENUM_TAG = 0x0F, + + /// + /// A member of an enumeration. The Value field specifies the + /// n th member. + /// + IMAGE_SYM_CLASS_MEMBER_OF_ENUM = 0x10, + + /// + /// A register parameter. + /// + IMAGE_SYM_CLASS_REGISTER_PARAM = 0x11, + + /// + /// A bit-field reference. The Value field specifies the + /// n th bit in the bit field. + /// + IMAGE_SYM_CLASS_BIT_FIELD = 0x12, + + /// + /// A .bb (beginning of block) or .eb (end of block) record. + /// The Value field is the relocatable address of the code location. + /// + IMAGE_SYM_CLASS_BLOCK = 0x64, + + /// + /// A value that Microsoft tools use for symbol records that define the extent + /// of a function: begin function (.bf ), end function (.ef), and lines in + /// function (.lf). For .lf records, the Value field gives the number of source + /// lines in the function. For .ef records, the Value field gives the size of + /// the function code. + /// + IMAGE_SYM_CLASS_FUNCTION = 0x65, + + /// + /// An end-of-structure entry. + /// + IMAGE_SYM_CLASS_END_OF_STRUCT = 0x66, + + /// + /// A value that Microsoft tools, as well as traditional COFF format, use for the + /// source-file symbol record. The symbol is followed by auxiliary records that + /// name the file. + /// + IMAGE_SYM_CLASS_FILE = 0x67, + + /// + /// A definition of a section (Microsoft tools use STATIC storage class instead). + /// + IMAGE_SYM_CLASS_SECTION = 0x68, + + /// + /// A weak external.For more information, see Auxiliary Format 3: Weak Externals. + /// + IMAGE_SYM_CLASS_WEAK_EXTERNAL = 0x69, + + /// + /// A CLR token symbol. The name is an ASCII string that consists of the hexadecimal + /// value of the token. For more information, see CLR Token Definition (Object Only). + /// + IMAGE_SYM_CLASS_CLR_TOKEN = 0x6A, + } + + [Flags] + public enum SymbolType : ushort + { + #region Simple (Base) Data Type + + /// + /// No type information or unknown base type. Microsoft tools use this setting + /// + IMAGE_SYM_TYPE_NULL = 0x00, + + /// + /// No valid type; used with void pointers and functions + /// + IMAGE_SYM_TYPE_VOID = 0x01, + + /// + /// A character (signed byte) + /// + IMAGE_SYM_TYPE_CHAR = 0x02, + + /// + /// A 2-byte signed integer + /// + IMAGE_SYM_TYPE_SHORT = 0x03, + + /// + /// A natural integer type (normally 4 bytes in Windows) + /// + IMAGE_SYM_TYPE_INT = 0x04, + + /// + /// A 4-byte signed integer + /// + IMAGE_SYM_TYPE_LONG = 0x05, + + /// + /// A 4-byte floating-point number + /// + IMAGE_SYM_TYPE_FLOAT = 0x06, + + /// + /// An 8-byte floating-point number + /// + IMAGE_SYM_TYPE_DOUBLE = 0x07, + + /// + /// A structure + /// + IMAGE_SYM_TYPE_STRUCT = 0x08, + + /// + /// A union + /// + IMAGE_SYM_TYPE_UNION = 0x09, + + /// + /// An enumerated type + /// + IMAGE_SYM_TYPE_ENUM = 0x0A, + + /// + /// A member of enumeration (a specific value) + /// + IMAGE_SYM_TYPE_MOE = 0x0B, + + /// + /// A byte; unsigned 1-byte integer + /// + IMAGE_SYM_TYPE_BYTE = 0x0C, + + /// + /// A word; unsigned 2-byte integer + /// + IMAGE_SYM_TYPE_WORD = 0x0D, + + /// + /// An unsigned integer of natural size (normally, 4 bytes) + /// + IMAGE_SYM_TYPE_UINT = 0x0E, + + /// + /// An unsigned 4-byte integer + /// + IMAGE_SYM_TYPE_DWORD = 0x0F, + + #endregion + + #region Complex Type + + /// + /// The symbol is a pointer to base type + /// + IMAGE_SYM_DTYPE_POINTER = 0x10, + + /// + /// The symbol is a function that returns a base type + /// + IMAGE_SYM_DTYPE_FUNCTION = 0x20, + + /// + /// The symbol is an array of base type + /// + IMAGE_SYM_DTYPE_ARRAY = 0x30, + + #endregion + } +} diff --git a/SabreTools.Serialization/Models/COFF/FileHeader.cs b/SabreTools.Serialization/Models/COFF/FileHeader.cs new file mode 100644 index 00000000..86ed66ab --- /dev/null +++ b/SabreTools.Serialization/Models/COFF/FileHeader.cs @@ -0,0 +1,58 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.COFF +{ + /// + /// At the beginning of an object file, or immediately after the signature + /// of an image file, is a standard COFF file header in the following format. + /// Note that the Windows loader limits the number of sections to 96. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class FileHeader + { + /// + /// The number that identifies the type of target machine. + /// + [MarshalAs(UnmanagedType.U2)] + public MachineType Machine; + + /// + /// The number of sections. This indicates the size of the section table, + /// which immediately follows the headers. + /// + public ushort NumberOfSections; + + /// + /// The low 32 bits of the number of seconds since 00:00 January 1, 1970 + /// (a C run-time time_t value), which indicates when the file was created. + /// + public uint TimeDateStamp; + + /// + /// The file offset of the COFF symbol table, or zero if no COFF symbol table + /// is present. This value should be zero for an image because COFF debugging + /// information is deprecated. + /// + public uint PointerToSymbolTable; + + /// + /// The number of entries in the symbol table. This data can be used to locate + /// the string table, which immediately follows the symbol table. This value + /// should be zero for an image because COFF debugging information is deprecated. + /// + public uint NumberOfSymbols; + + /// + /// The size of the optional header, which is required for executable files but + /// not for object files. This value should be zero for an object file. + /// + public ushort SizeOfOptionalHeader; + + /// + /// The flags that indicate the attributes of the file. + /// + [MarshalAs(UnmanagedType.U2)] + public Characteristics Characteristics; + } +} diff --git a/SabreTools.Serialization/Models/COFF/LineNumber.cs b/SabreTools.Serialization/Models/COFF/LineNumber.cs new file mode 100644 index 00000000..8311eb42 --- /dev/null +++ b/SabreTools.Serialization/Models/COFF/LineNumber.cs @@ -0,0 +1,42 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.COFF +{ + /// + /// COFF line numbers are no longer produced and, in the future, will + /// not be consumed. + /// + /// COFF line numbers indicate the relationship between code and line + /// numbers in source files. The Microsoft format for COFF line numbers + /// is similar to standard COFF, but it has been extended to allow a + /// single section to relate to line numbers in multiple source files. + /// + /// COFF line numbers consist of an array of fixed-length records. + /// The location (file offset) and size of the array are specified in + /// the section header. + /// + /// + [StructLayout(LayoutKind.Explicit)] + public sealed class LineNumber + { + /// + /// Used when Linenumber is zero: index to symbol table entry for a function. + /// This format is used to indicate the function to which a group of + /// line-number records refers. + /// + [FieldOffset(0)] public uint SymbolTableIndex; + + /// + /// Used when Linenumber is non-zero: the RVA of the executable code that + /// corresponds to the source line indicated. In an object file, this + /// contains the VA within the section. + /// + [FieldOffset(0)] public uint VirtualAddress; + + /// + /// When nonzero, this field specifies a one-based line number. When zero, + /// the Type field is interpreted as a symbol table index for a function. + /// + [FieldOffset(4)] public ushort Linenumber; + } +} diff --git a/SabreTools.Serialization/Models/COFF/OptionalHeader.cs b/SabreTools.Serialization/Models/COFF/OptionalHeader.cs new file mode 100644 index 00000000..95ee2694 --- /dev/null +++ b/SabreTools.Serialization/Models/COFF/OptionalHeader.cs @@ -0,0 +1,88 @@ +namespace SabreTools.Serialization.Models.COFF +{ + /// + /// Every image file has an optional header that provides information to the loader. + /// This header is optional in the sense that some files (specifically, object files) + /// do not have it. For image files, this header is required. An object file can have + /// an optional header, but generally this header has no function in an object file + /// except to increase its size. + /// + /// Note that the size of the optional header is not fixed. The SizeOfOptionalHeader + /// field in the COFF header must be used to validate that a probe into the file for + /// a particular data directory does not go beyond SizeOfOptionalHeader. + /// + /// The NumberOfRvaAndSizes field of the optional header should also be used to ensure + /// that no probe for a particular data directory entry goes beyond the optional header. + /// In addition, it is important to validate the optional header magic number for format + /// compatibility. + /// + /// The optional header magic number determines whether an image is a PE32 or + /// PE32+ executable. + /// + /// PE32+ images allow for a 64-bit address space while limiting the image size to + /// 2 gigabytes. Other PE32+ modifications are addressed in their respective sections. + /// + /// The first eight fields of the optional header are standard fields that are defined + /// for every implementation of COFF. These fields contain general information that is + /// useful for loading and running an executable file. They are unchanged for the + /// PE32+ format. + /// + /// + public class OptionalHeader + { + /// + /// The unsigned integer that identifies the state of the image file. The most + /// common number is 0x10B, which identifies it as a normal executable file. + /// 0x107 identifies it as a ROM image, and 0x20B identifies it as a PE32+ executable. + /// + public OptionalHeaderMagicNumber Magic { get; set; } + + /// + /// The linker major version number. + /// + public byte MajorLinkerVersion { get; set; } + + /// + /// The linker minor version number. + /// + public byte MinorLinkerVersion { get; set; } + + /// + /// The size of the code (text) section, or the sum of all code sections if there + /// are multiple sections. + /// + public uint SizeOfCode { get; set; } + + /// + /// The size of the initialized data section, or the sum of all such sections if + /// there are multiple data sections. + /// + public uint SizeOfInitializedData { get; set; } + + /// + /// The size of the uninitialized data section (BSS), or the sum of all such sections + /// if there are multiple BSS sections. + /// + public uint SizeOfUninitializedData { get; set; } + + /// + /// The address of the entry point relative to the image base when the executable file + /// is loaded into memory. For program images, this is the starting address. For + /// device drivers, this is the address of the initialization function. An entry point + /// is optional for DLLs. When no entry point is present, this field must be zero. + /// + public uint AddressOfEntryPoint { get; set; } + + /// + /// The address that is relative to the image base of the beginning-of-code section when + /// it is loaded into memory. + /// + public uint BaseOfCode { get; set; } + + /// + /// The address that is relative to the image base of the beginning-of-data section when + /// it is loaded into memory. + /// + public uint BaseOfData { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/COFF/Relocation.cs b/SabreTools.Serialization/Models/COFF/Relocation.cs new file mode 100644 index 00000000..1f5f5022 --- /dev/null +++ b/SabreTools.Serialization/Models/COFF/Relocation.cs @@ -0,0 +1,47 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.COFF +{ + /// + /// Object files contain COFF relocations, which specify how the section data + /// should be modified when placed in the image file and subsequently loaded + /// into memory. + /// + /// Image files do not contain COFF relocations, because all referenced symbols + /// have already been assigned addresses in a flat address space. An image + /// contains relocation information in the form of base relocations in the + /// .reloc section (unless the image has the IMAGE_FILE_RELOCS_STRIPPED attribute). + /// + /// For each section in an object file, an array of fixed-length records holds + /// the section's COFF relocations. The position and length of the array are + /// specified in the section header. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class Relocation + { + /// + /// The address of the item to which relocation is applied. This is the + /// offset from the beginning of the section, plus the value of the + /// section's RVA/Offset field. See Section Table (Section Headers). + /// For example, if the first byte of the section has an address of 0x10, + /// the third byte has an address of 0x12. + /// + public uint VirtualAddress; + + /// + /// A zero-based index into the symbol table. This symbol gives the address + /// that is to be used for the relocation. If the specified symbol has section + /// storage class, then the symbol's address is the address with the first + /// section of the same name. + /// + public uint SymbolTableIndex; + + /// + /// A value that indicates the kind of relocation that should be performed. + /// Valid relocation types depend on machine type. + /// + [MarshalAs(UnmanagedType.U2)] + public RelocationType TypeIndicator; + } +} diff --git a/SabreTools.Serialization/Models/COFF/SectionHeader.cs b/SabreTools.Serialization/Models/COFF/SectionHeader.cs new file mode 100644 index 00000000..42b133d7 --- /dev/null +++ b/SabreTools.Serialization/Models/COFF/SectionHeader.cs @@ -0,0 +1,111 @@ +namespace SabreTools.Serialization.Models.COFF +{ + /// + /// Each row of the section table is, in effect, a section header. This table + /// immediately follows the optional header, if any. This positioning is required + /// because the file header does not contain a direct pointer to the section table. + /// Instead, the location of the section table is determined by calculating the + /// location of the first byte after the headers. Make sure to use the size of + /// the optional header as specified in the file header. + /// + /// The number of entries in the section table is given by the NumberOfSections + /// field in the file header. Entries in the section table are numbered starting + /// from one (1). The code and data memory section entries are in the order chosen + /// by the linker. + /// + /// In an image file, the VAs for sections must be assigned by the linker so that + /// they are in ascending order and adjacent, and they must be a multiple of the + /// SectionAlignment value in the optional header. + /// + /// + public sealed class SectionHeader + { + /// + /// An 8-byte, null-padded UTF-8 encoded string. If the string is exactly 8 + /// characters long, there is no terminating null. For longer names, this field + /// contains a slash (/) that is followed by an ASCII representation of a + /// decimal number that is an offset into the string table. Executable images + /// do not use a string table and do not support section names longer than 8 + /// characters. Long names in object files are truncated if they are emitted + /// to an executable file. + /// + /// 8 bytes + public byte[]? Name { get; set; } + + /// + /// The total size of the section when loaded into memory. If this value is + /// greater than SizeOfRawData, the section is zero-padded. This field is valid + /// only for executable images and should be set to zero for object files. + /// + public uint VirtualSize { get; set; } + + /// + /// For executable images, the address of the first byte of the section relative + /// to the image base when the section is loaded into memory. For object files, + /// this field is the address of the first byte before relocation is applied { get; set; } + /// for simplicity, compilers should set this to zero. Otherwise, it is an + /// arbitrary value that is subtracted from offsets during relocation. + /// + public uint VirtualAddress { get; set; } + + /// + /// The size of the section (for object files) or the size of the initialized + /// data on disk (for image files). For executable images, this must be a multiple + /// of FileAlignment from the optional header. If this is less than VirtualSize, + /// the remainder of the section is zero-filled. Because the SizeOfRawData field + /// is rounded but the VirtualSize field is not, it is possible for SizeOfRawData + /// to be greater than VirtualSize as well. When a section contains only + /// uninitialized data, this field should be zero. + /// + public uint SizeOfRawData { get; set; } + + /// + /// The file pointer to the first page of the section within the COFF file. For + /// executable images, this must be a multiple of FileAlignment from the optional + /// header. For object files, the value should be aligned on a 4-byte boundary + /// for best performance. When a section contains only uninitialized data, this + /// field should be zero. + /// + public uint PointerToRawData { get; set; } + + /// + /// The file pointer to the beginning of relocation entries for the section. This + /// is set to zero for executable images or if there are no relocations. + /// + public uint PointerToRelocations { get; set; } + + /// + /// The file pointer to the beginning of line-number entries for the section. This + /// is set to zero if there are no COFF line numbers. This value should be zero for + /// an image because COFF debugging information is deprecated. + /// + public uint PointerToLinenumbers { get; set; } + + /// + /// The number of relocation entries for the section. This is set to zero for + /// executable images. + /// + public ushort NumberOfRelocations { get; set; } + + /// + /// The number of line-number entries for the section. This value should be zero + /// for an image because COFF debugging information is deprecated. + /// + public ushort NumberOfLinenumbers { get; set; } + + /// + /// The flags that describe the characteristics of the section. + /// + public SectionFlags Characteristics { get; set; } + + /// + /// COFF Relocations (Object Only) + /// + public Relocation[]? COFFRelocations { get; set; } + + /// + /// COFF Line Numbers (Deprecated) + /// + public LineNumber[]? COFFLineNumbers { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/COFF/StringTable.cs b/SabreTools.Serialization/Models/COFF/StringTable.cs new file mode 100644 index 00000000..d45708d4 --- /dev/null +++ b/SabreTools.Serialization/Models/COFF/StringTable.cs @@ -0,0 +1,25 @@ +namespace SabreTools.Serialization.Models.COFF +{ + /// + /// Immediately following the COFF symbol table is the COFF string table. The + /// position of this table is found by taking the symbol table address in the + /// COFF header and adding the number of symbols multiplied by the size of a symbol. + /// + /// + public sealed class StringTable + { + /// + /// At the beginning of the COFF string table are 4 bytes that contain the + /// total size (in bytes) of the rest of the string table. This size includes + /// the size field itself, so that the value in this location would be 4 if no + /// strings were present. + /// + public uint TotalSize { get; set; } + + /// + /// Following the size are null-terminated strings that are pointed to by symbols + /// in the COFF symbol table. + /// + public string[]? Strings { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/COFF/SymbolTableEntries/BaseEntry.cs b/SabreTools.Serialization/Models/COFF/SymbolTableEntries/BaseEntry.cs new file mode 100644 index 00000000..f7478984 --- /dev/null +++ b/SabreTools.Serialization/Models/COFF/SymbolTableEntries/BaseEntry.cs @@ -0,0 +1,32 @@ +namespace SabreTools.Serialization.Models.COFF.SymbolTableEntries +{ + /// + /// The symbol table in this section is inherited from the traditional + /// COFF format. It is distinct from Microsoft Visual C++ debug information. + /// A file can contain both a COFF symbol table and Visual C++ debug + /// information, and the two are kept separate. Some Microsoft tools use + /// the symbol table for limited but important purposes, such as + /// communicating COMDAT information to the linker. Section names and file + /// names, as well as code and data symbols, are listed in the symbol table. + /// + /// The location of the symbol table is indicated in the COFF header. + /// + /// The symbol table is an array of records, each 18 bytes long. Each record + /// is either a standard or auxiliary symbol-table record. A standard record + /// defines a symbol or name. + /// + /// Auxiliary symbol table records always follow, and apply to, some standard + /// symbol table record. An auxiliary record can have any format that the tools + /// can recognize, but 18 bytes must be allocated for them so that symbol table + /// is maintained as an array of regular size. Currently, Microsoft tools + /// recognize auxiliary formats for the following kinds of records: function + /// definitions, function begin and end symbols (.bf and .ef), weak externals, + /// file names, and section definitions. + /// + /// The traditional COFF design also includes auxiliary-record formats for arrays + /// and structures.Microsoft tools do not use these, but instead place that + /// symbolic information in Visual C++ debug format in the debug sections. + /// + /// + public abstract class BaseEntry { } +} diff --git a/SabreTools.Serialization/Models/COFF/SymbolTableEntries/CLRTokenDefinition.cs b/SabreTools.Serialization/Models/COFF/SymbolTableEntries/CLRTokenDefinition.cs new file mode 100644 index 00000000..18c5f20f --- /dev/null +++ b/SabreTools.Serialization/Models/COFF/SymbolTableEntries/CLRTokenDefinition.cs @@ -0,0 +1,33 @@ +namespace SabreTools.Serialization.Models.COFF.SymbolTableEntries +{ + /// + /// Auxiliary Format 6: CLR Token Definition (Object Only) + /// + /// This auxiliary symbol generally follows the IMAGE_SYM_CLASS_CLR_TOKEN. It is + /// used to associate a token with the COFF symbol table's namespace. + /// + /// + public class CLRTokenDefinition : BaseEntry + { + /// + /// Must be IMAGE_AUX_SYMBOL_TYPE_TOKEN_DEF (1). + /// + public byte AuxType { get; set; } + + /// + /// Reserved, must be zero. + /// + public byte Reserved1 { get; set; } + + /// + /// The symbol index of the COFF symbol to which this CLR token definition refers. + /// + public uint SymbolTableIndex { get; set; } + + /// + /// Reserved, must be zero. + /// + /// 12 bytes + public byte[]? Reserved2 { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/COFF/SymbolTableEntries/Descriptor.cs b/SabreTools.Serialization/Models/COFF/SymbolTableEntries/Descriptor.cs new file mode 100644 index 00000000..fc766f09 --- /dev/null +++ b/SabreTools.Serialization/Models/COFF/SymbolTableEntries/Descriptor.cs @@ -0,0 +1,53 @@ +namespace SabreTools.Serialization.Models.COFF.SymbolTableEntries +{ + /// + /// Auxiliary Format 2: .bf and .ef Symbols + /// + /// For each function definition in the symbol table, three items describe + /// the beginning, ending, and number of lines. Each of these symbols has + /// storage class FUNCTION (101): + /// + /// A symbol record named .bf (begin function). The Value field is unused. + /// + /// A symbol record named .lf (lines in function). The Value field gives the + /// number of lines in the function. + /// + /// A symbol record named .ef (end of function). The Value field has the same + /// number as the Total Size field in the function-definition symbol record. + /// + // The .bf and .ef symbol records (but not .lf records) are followed by an + // auxiliary record with the following format: + /// + /// + public class Descriptor : BaseEntry + { + /// + /// Unused + /// + public uint Unused1 { get; set; } + + /// + /// The actual ordinal line number (1, 2, 3, and so on) within the source file, + /// corresponding to the .bf or .ef record. + /// + public ushort Linenumber { get; set; } + + /// + /// Unused + /// + /// 6 bytes + public byte[]? Unused2 { get; set; } + + /// + /// The symbol-table index of the next .bf symbol record. If the function is the + /// last in the symbol table, this field is set to zero. It is not used for + /// .ef records. + /// + public uint PointerToNextFunction { get; set; } + + /// + /// Unused + /// + public ushort Unused3 { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/COFF/SymbolTableEntries/FileRecord.cs b/SabreTools.Serialization/Models/COFF/SymbolTableEntries/FileRecord.cs new file mode 100644 index 00000000..8d84283a --- /dev/null +++ b/SabreTools.Serialization/Models/COFF/SymbolTableEntries/FileRecord.cs @@ -0,0 +1,20 @@ +namespace SabreTools.Serialization.Models.COFF.SymbolTableEntries +{ + /// + /// Auxiliary Format 4: Files + /// + /// This format follows a symbol-table record with storage class FILE (103). + /// The symbol name itself should be .file, and the auxiliary record that + /// follows it gives the name of a source-code file. + /// + /// + public class FileRecord : BaseEntry + { + /// + /// An ANSI string that gives the name of the source file. This is padded + /// with nulls if it is less than the maximum length. + /// + /// 18 bytes + public byte[]? FileName { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/COFF/SymbolTableEntries/FunctionDefinition.cs b/SabreTools.Serialization/Models/COFF/SymbolTableEntries/FunctionDefinition.cs new file mode 100644 index 00000000..7a460a90 --- /dev/null +++ b/SabreTools.Serialization/Models/COFF/SymbolTableEntries/FunctionDefinition.cs @@ -0,0 +1,47 @@ +namespace SabreTools.Serialization.Models.COFF.SymbolTableEntries +{ + /// + /// Auxiliary Format 1: Function Definitions + /// + /// A symbol table record marks the beginning of a function definition if it + /// has all of the following: a storage class of EXTERNAL (2), a Type value + /// that indicates it is a function (0x20), and a section number that is + /// greater than zero. Note that a symbol table record that has a section + /// number of UNDEFINED (0) does not define the function and does not have + /// an auxiliary record. Function-definition symbol records are followed by + /// an auxiliary record in the format described below: + /// + /// + public class FunctionDefinition : BaseEntry + { + /// + /// The symbol-table index of the corresponding .bf (begin function) + /// symbol record. + /// + public uint TagIndex { get; set; } + + /// + /// The size of the executable code for the function itself. If the function + /// is in its own section, the SizeOfRawData in the section header is greater + /// or equal to this field, depending on alignment considerations. + /// + public uint TotalSize { get; set; } + + /// + /// The file offset of the first COFF line-number entry for the function, or + /// zero if none exists. + /// + public uint PointerToLinenumber { get; set; } + + /// + /// The symbol-table index of the record for the next function. If the function + /// is the last in the symbol table, this field is set to zero. + /// + public uint PointerToNextFunction { get; set; } + + /// + /// Unused + /// + public ushort Unused { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/COFF/SymbolTableEntries/SectionDefinition.cs b/SabreTools.Serialization/Models/COFF/SymbolTableEntries/SectionDefinition.cs new file mode 100644 index 00000000..881b1efd --- /dev/null +++ b/SabreTools.Serialization/Models/COFF/SymbolTableEntries/SectionDefinition.cs @@ -0,0 +1,54 @@ +namespace SabreTools.Serialization.Models.COFF.SymbolTableEntries +{ + /// + /// Auxiliary Format 5: Section Definitions + /// + /// This format follows a symbol-table record that defines a section. Such a + /// record has a symbol name that is the name of a section (such as .text or + /// .drectve) and has storage class STATIC (3). The auxiliary record provides + /// information about the section to which it refers. Thus, it duplicates some + /// of the information in the section header. + /// + /// + public class SectionDefinition : BaseEntry + { + /// + /// The size of section data; the same as SizeOfRawData in the section header. + /// + public uint Length { get; set; } + + /// + /// The number of relocation entries for the section. + /// + public ushort NumberOfRelocations { get; set; } + + /// + /// The number of line-number entries for the section. + /// + public ushort NumberOfLinenumbers { get; set; } + + /// + /// The checksum for communal data. It is applicable if the IMAGE_SCN_LNK_COMDAT + /// flag is set in the section header. + /// + public uint CheckSum { get; set; } + + /// + /// One-based index into the section table for the associated section. This is + /// used when the COMDAT selection setting is 5. + /// + public ushort Number { get; set; } + + /// + /// The COMDAT selection number. This is applicable if the section is a + /// COMDAT section. + /// + public byte Selection { get; set; } + + /// + /// Unused + /// + /// 3 bytes + public byte[]? Unused { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/COFF/SymbolTableEntries/StandardRecord.cs b/SabreTools.Serialization/Models/COFF/SymbolTableEntries/StandardRecord.cs new file mode 100644 index 00000000..a79ad94f --- /dev/null +++ b/SabreTools.Serialization/Models/COFF/SymbolTableEntries/StandardRecord.cs @@ -0,0 +1,58 @@ +namespace SabreTools.Serialization.Models.COFF.SymbolTableEntries +{ + /// + /// A standard record defines a symbol or name. + /// + /// + public class StandardRecord : BaseEntry + { + #region Symbol Name + + /// + /// An array of 8 bytes. This array is padded with nulls on the right if + /// the name is less than 8 bytes long. + /// + public byte[]? ShortName { get; set; } = new byte[8]; + + /// + /// A field that is set to all zeros if the name is longer than 8 bytes. + /// + public uint Zeroes { get; set; } + + /// + /// An offset into the string table. + /// + public uint Offset { get; set; } + + #endregion + + /// + /// The value that is associated with the symbol. The interpretation of this + /// field depends on SectionNumber and StorageClass. A typical meaning is the + /// relocatable address. + /// + public uint Value { get; set; } + + /// + /// The signed integer that identifies the section, using a one-based index + /// into the section table. Some values have special meaning. + /// + public SectionNumber SectionNumber { get; set; } + + /// + /// A number that represents type. Microsoft tools set this field to 0x20 + /// (function) or 0x0 (not a function). + /// + public SymbolType SymbolType { get; set; } + + /// + /// An enumerated value that represents storage class. + /// + public StorageClass StorageClass { get; set; } + + /// + /// The number of auxiliary symbol table entries that follow this record. + /// + public byte NumberOfAuxSymbols { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/COFF/SymbolTableEntries/WeakExternal.cs b/SabreTools.Serialization/Models/COFF/SymbolTableEntries/WeakExternal.cs new file mode 100644 index 00000000..a96a5b16 --- /dev/null +++ b/SabreTools.Serialization/Models/COFF/SymbolTableEntries/WeakExternal.cs @@ -0,0 +1,45 @@ +namespace SabreTools.Serialization.Models.COFF.SymbolTableEntries +{ + /// + /// Auxiliary Format 3: Weak Externals + /// + /// "Weak externals" are a mechanism for object files that allows flexibility at + /// link time. A module can contain an unresolved external symbol (sym1), but it + /// can also include an auxiliary record that indicates that if sym1 is not + /// present at link time, another external symbol (sym2) is used to resolve + /// references instead. + /// + /// If a definition of sym1 is linked, then an external reference to the symbol + /// is resolved normally. If a definition of sym1 is not linked, then all references + /// to the weak external for sym1 refer to sym2 instead. The external symbol, sym2, + /// must always be linked; typically, it is defined in the module that contains + /// the weak reference to sym1. + /// + /// Weak externals are represented by a symbol table record with EXTERNAL storage + /// class, UNDEF section number, and a value of zero. The weak-external symbol + /// record is followed by an auxiliary record with the following format: + /// + /// + public class WeakExternal : BaseEntry + { + /// + /// The symbol-table index of sym2, the symbol to be linked if sym1 is not found. + /// + public uint TagIndex { get; set; } + + /// + /// A value of IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY indicates that no library search + /// for sym1 should be performed. + /// A value of IMAGE_WEAK_EXTERN_SEARCH_LIBRARY indicates that a library search for + /// sym1 should be performed. + /// A value of IMAGE_WEAK_EXTERN_SEARCH_ALIAS indicates that sym1 is an alias for sym2. + /// + public uint Characteristics { get; set; } + + /// + /// Unused + /// + /// 10 bytes + public byte[]? Unused { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/Delphi/Constants.cs b/SabreTools.Serialization/Models/Delphi/Constants.cs new file mode 100644 index 00000000..1e5928a0 --- /dev/null +++ b/SabreTools.Serialization/Models/Delphi/Constants.cs @@ -0,0 +1,14 @@ +/// +/// Information sourced from https://stackoverflow.com/questions/18720045/what-are-the-list-of-all-possible-values-for-dvclal +/// +namespace SabreTools.Serialization.Models.Delphi +{ + public static class Constants + { + public static readonly byte[] DVCLALStandard = [0x23, 0x78, 0x5D, 0x23, 0xB6, 0xA5, 0xF3, 0x19, 0x43, 0xF3, 0x40, 0x02, 0x26, 0xD1, 0x11, 0xC7]; + + public static readonly byte[] DVCLALProfessional = [0xA2, 0x8C, 0xDF, 0x98, 0x7B, 0x3C, 0x3A, 0x79, 0x26, 0x71, 0x3F, 0x09, 0x0F, 0x2A, 0x25, 0x17]; + + public static readonly byte[] DVCLALEnterprise = [0x26, 0x3D, 0x4F, 0x38, 0xC2, 0x82, 0x37, 0xB8, 0xF3, 0x24, 0x42, 0x03, 0x17, 0x9B, 0x3A, 0x83]; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/Delphi/PackageInfoTable.cs b/SabreTools.Serialization/Models/Delphi/PackageInfoTable.cs new file mode 100644 index 00000000..f7e9ff0f --- /dev/null +++ b/SabreTools.Serialization/Models/Delphi/PackageInfoTable.cs @@ -0,0 +1,14 @@ +/// +/// Information sourced from https://docwiki.embarcadero.com/Libraries/Alexandria/en/System.PackageInfoTable +/// +namespace SabreTools.Serialization.Models.Delphi +{ + public class PackageInfoTable + { + public int UnitCount { get; set; } + + public PackageUnitEntry[]? UnitInfo { get; set; } + + public PackageTypeInfo? TypeInfo { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/Delphi/PackageTypeInfo.cs b/SabreTools.Serialization/Models/Delphi/PackageTypeInfo.cs new file mode 100644 index 00000000..2dc4e7c2 --- /dev/null +++ b/SabreTools.Serialization/Models/Delphi/PackageTypeInfo.cs @@ -0,0 +1,19 @@ +/// +/// Information sourced from https://docwiki.embarcadero.com/Libraries/Sydney/en/System.TPackageTypeInfo +/// +namespace SabreTools.Serialization.Models.Delphi +{ + public class PackageTypeInfo + { + public int TypeCount { get; set; } + + /// + /// System-dependent pointer type, assumed to be encoded for x86 + /// + public uint[]? TypeTable { get; set; } + + public int UnitCount { get; set; } + + public string[]? UnitNames { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/Delphi/PackageUnitEntry.cs b/SabreTools.Serialization/Models/Delphi/PackageUnitEntry.cs new file mode 100644 index 00000000..1604d931 --- /dev/null +++ b/SabreTools.Serialization/Models/Delphi/PackageUnitEntry.cs @@ -0,0 +1,21 @@ +using System.Runtime.InteropServices; + +/// +/// Information sourced from https://docwiki.embarcadero.com/Libraries/Alexandria/en/System.PackageUnitEntry +/// +namespace SabreTools.Serialization.Models.Delphi +{ + [StructLayout(LayoutKind.Sequential)] + public class PackageUnitEntry + { + /// + /// System-dependent pointer type, assumed to be encoded for x86 + /// + public uint Init; + + /// + /// System-dependent pointer type, assumed to be encoded for x86 + /// + public uint FInit; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/LinearExecutable/Constants.cs b/SabreTools.Serialization/Models/LinearExecutable/Constants.cs new file mode 100644 index 00000000..4948a169 --- /dev/null +++ b/SabreTools.Serialization/Models/LinearExecutable/Constants.cs @@ -0,0 +1,21 @@ +namespace SabreTools.Serialization.Models.LinearExecutable +{ + public static class Constants + { + public static readonly byte[] DebugInformationSignatureBytes = [0x4e, 0x42, 0x30]; + + public const string DebugInformationSignatureString = "NB0"; + + public static readonly byte[] LESignatureBytes = [0x4c, 0x45]; + + public const string LESignatureString = "LE"; + + public const ushort LESignatureUInt16 = 0x454c; + + public static readonly byte[] LXSignatureBytes = [0x4c, 0x58]; + + public const string LXSignatureString = "LX"; + + public const ushort LXSignatureUInt16 = 0x584c; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/LinearExecutable/DebugInformation.cs b/SabreTools.Serialization/Models/LinearExecutable/DebugInformation.cs new file mode 100644 index 00000000..cc6e815e --- /dev/null +++ b/SabreTools.Serialization/Models/LinearExecutable/DebugInformation.cs @@ -0,0 +1,35 @@ +namespace SabreTools.Serialization.Models.LinearExecutable +{ + /// + /// The debug information is defined by the debugger and is not controlled by + /// the linear EXE format or linker. The only data defined by the linear EXE + /// format relative to the debug information is it's offset in the EXE file and + /// length in bytes as defined in the linear EXE header. + /// + /// To support multiple debuggers the first word of the debug information is a + /// type field which determines the format of the debug information. + /// + /// + /// + public sealed class DebugInformation + { + /// + /// The signature consists of a string of three (3) ASCII characters: "NB0" + /// + public string? Signature { get; set; } + + /// + /// This defines the type of debugger data that exists in the remainder of the + /// debug information. + /// + public DebugFormatType FormatType { get; set; } + + /// + /// The format of the debugger data is defined by the debugger that is being used. + /// The values defined for the type field are not enforced by the system. It is + /// the responsibility of the linker or debugging tools to follow the convention + /// for the type field that is defined here. + /// + public byte[]? DebuggerData { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/LinearExecutable/EntryTableBundle.cs b/SabreTools.Serialization/Models/LinearExecutable/EntryTableBundle.cs new file mode 100644 index 00000000..1998bc47 --- /dev/null +++ b/SabreTools.Serialization/Models/LinearExecutable/EntryTableBundle.cs @@ -0,0 +1,56 @@ +namespace SabreTools.Serialization.Models.LinearExecutable +{ + /// + /// The entry table contains object and offset information that is used to resolve + /// fixup references to the entry points within this module. Not all entry points + /// in the entry table will be exported, some entry points will only be used + /// within the module. An ordinal number is used to index into the entry table. + /// The entry table entries are numbered starting from one. + /// + /// The list of entries are compressed into 'bundles', where possible. The entries + /// within each bundle are all the same size. A bundle starts with a count field + /// which indicates the number of entries in the bundle. The count is followed by + /// a type field which identifies the bundle format. This provides both a means + /// for saving space as well as a mechanism for extending the bundle types. + /// + /// + /// + public sealed class EntryTableBundle + { + /// + /// Number of entries. + /// + /// + /// This is the number of entries in this bundle. + /// + /// A zero value for the number of entries identifies the end of the + /// entry table. There is no further bundle information when the number + /// of entries is zero. In other words the entry table is terminated by + /// a single zero byte. + /// + /// For , this is the number of unused + /// entries to skip. + /// For , this is the number of 16-bit + /// entries in this bundle. The flags and offset value are repeated this + /// number of times. + /// For , this is the number + /// of 286 call gate entries in this bundle. The flags, callgate, and offset + /// value are repeated this number of times. + /// For , this is the number + /// of 32-bit entries in this bundle. The flags and offset value are repeated + /// this number of times. + /// For , this field is reserved for future use. + /// + public byte Entries { get; set; } + + /// + /// This defines the bundle type which determines the contents of the BUNDLE INFO. + /// + public BundleType BundleType { get; set; } + + /// + /// Table entries in the bundle + /// + public EntryTableEntry[]? TableEntries { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/LinearExecutable/EntryTableEntry.cs b/SabreTools.Serialization/Models/LinearExecutable/EntryTableEntry.cs new file mode 100644 index 00000000..ba301b85 --- /dev/null +++ b/SabreTools.Serialization/Models/LinearExecutable/EntryTableEntry.cs @@ -0,0 +1,190 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.LinearExecutable +{ + /// + /// + [StructLayout(LayoutKind.Explicit)] + public sealed class EntryTableEntry + { + #region 16-bit Entry + + /// + /// Object number. + /// + /// + /// This is the object number for the entries in this bundle. + /// + [FieldOffset(0)] public ushort SixteenBitObjectNumber; + + /// + /// Entry flags. + /// + /// + /// These are the flags for this entry point. + /// + [FieldOffset(2)] public EntryFlags SixteenBitEntryFlags; + + /// + /// Offset in object. + /// + /// + /// This is the offset in the object for the entry point defined at this ordinal number. + /// + [FieldOffset(3)] public ushort SixteenBitOffset; + + #endregion + + #region 286 Call Gate Entry + + /// + /// Object number. + /// + /// + /// This is the object number for the entries in this bundle. + /// + [FieldOffset(0)] public ushort TwoEightySixObjectNumber; + + /// + /// Entry flags. + /// + /// + /// These are the flags for this entry point. + /// + [FieldOffset(2)] public EntryFlags TwoEightySixEntryFlags; + + /// + /// Offset in object. + /// + /// + /// This is the offset in the object for the entry point defined at this ordinal number. + /// + [FieldOffset(3)] public ushort TwoEightySixOffset; + + /// + /// Callgate selector. + /// + /// + /// The callgate selector is a reserved field used by the loader to store a call + /// gate selector value for references to ring 2 entry points. When a ring 3 + /// reference to a ring 2 entry point is made, the callgate selector with a zero + /// offset is place in the relocation fixup address. The segment number and offset + /// in segment is placed in the LDT callgate. + /// + [FieldOffset(5)] public ushort TwoEightySixCallgate; + + #endregion + + #region 32-bit Entry + + /// + /// Object number. + /// + /// + /// This is the object number for the entries in this bundle. + /// + [FieldOffset(0)] public ushort ThirtyTwoBitObjectNumber; + + /// + /// Entry flags. + /// + /// + /// These are the flags for this entry point. + /// + [FieldOffset(2)] public EntryFlags ThirtyTwoBitEntryFlags; + + /// + /// Offset in object. + /// + /// + /// This is the offset in the object for the entry point defined at this ordinal number. + /// + [FieldOffset(3)] public uint ThirtyTwoBitOffset; + + #endregion + + #region Forwarder Entry + + /// + /// 0 + /// + /// + /// This field is reserved for future use. + /// + [FieldOffset(0)] public ushort ForwarderReserved; + + /// + /// Forwarder flags. + /// + /// + /// These are the flags for this entry point. + /// + [FieldOffset(2)] public ForwarderFlags ForwarderFlags; + + /// + /// Module Ordinal Number + /// + /// + /// This is the index into the Import Module Name Table for this forwarder. + /// + [FieldOffset(3)] public ushort ForwarderModuleOrdinalNumber; + + /// + /// Procedure Name Offset + /// + /// + /// If the FLAGS field indicates import by ordinal, then this field is the + /// ordinal number into the Entry Table of the target module, otherwise this + /// field is the offset into the Procedure Names Table of the target module. + /// + /// A Forwarder entry (type = 4) is an entry point whose value is an imported + /// reference. When a load time fixup occurs whose target is a forwarder, the + /// loader obtains the address imported by the forwarder and uses that imported + /// address to resolve the fixup. + /// + /// A forwarder may refer to an entry point in another module which is itself a + /// forwarder, so there can be a chain of forwarders. The loader will traverse + /// the chain until it finds a non-forwarded entry point which terminates the + /// chain, and use this to resolve the original fixup. Circular chains are + /// detected by the loader and result in a load time error. A maximum of 1024 + /// forwarders is allowed in a chain; more than this results in a load time error. + /// + /// Forwarders are useful for merging and recombining API calls into different + /// sets of libraries, while maintaining compatibility with applications. For + /// example, if one wanted to combine MONCALLS, MOUCALLS, and VIOCALLS into a + /// single libraries, one could provide entry points for the three libraries + /// that are forwarders pointing to the common implementation. + /// + [FieldOffset(5)] public uint ProcedureNameOffset; + + /// + /// Import Ordinal Number + /// + /// + /// If the FLAGS field indicates import by ordinal, then this field is the + /// ordinal number into the Entry Table of the target module, otherwise this + /// field is the offset into the Procedure Names Table of the target module. + /// + /// A Forwarder entry (type = 4) is an entry point whose value is an imported + /// reference. When a load time fixup occurs whose target is a forwarder, the + /// loader obtains the address imported by the forwarder and uses that imported + /// address to resolve the fixup. + /// + /// A forwarder may refer to an entry point in another module which is itself a + /// forwarder, so there can be a chain of forwarders. The loader will traverse + /// the chain until it finds a non-forwarded entry point which terminates the + /// chain, and use this to resolve the original fixup. Circular chains are + /// detected by the loader and result in a load time error. A maximum of 1024 + /// forwarders is allowed in a chain; more than this results in a load time error. + /// + /// Forwarders are useful for merging and recombining API calls into different + /// sets of libraries, while maintaining compatibility with applications. For + /// example, if one wanted to combine MONCALLS, MOUCALLS, and VIOCALLS into a + /// single libraries, one could provide entry points for the three libraries + /// that are forwarders pointing to the common implementation. + /// + [FieldOffset(5)] public uint ImportOrdinalNumber; + + #endregion + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/LinearExecutable/Enums.cs b/SabreTools.Serialization/Models/LinearExecutable/Enums.cs new file mode 100644 index 00000000..21fc1fac --- /dev/null +++ b/SabreTools.Serialization/Models/LinearExecutable/Enums.cs @@ -0,0 +1,680 @@ +using System; + +namespace SabreTools.Serialization.Models.LinearExecutable +{ + [Flags] + public enum BundleType : byte + { + /// + /// Unused Entry. + /// + UnusedEntry = 0x00, + + /// + /// 16-bit Entry. + /// + SixteenBitEntry = 0x01, + + /// + /// 286 Call Gate Entry. + /// + TwoEightySixCallGateEntry = 0x02, + + /// + /// 32-bit Entry. + /// + ThirtyTwoBitEntry = 0x03, + + /// + /// Forwarder Entry. + /// + ForwarderEntry = 0x04, + + /// + /// Parameter Typing Information Present. + /// + /// + /// This bit signifies that additional information is contained in the + /// linear EXE module and will be used in the future for parameter type checking. + /// + ParameterTypingInformationPresent = 0x80, + } + + public enum ByteOrder : byte + { + /// + /// little-endian + /// + LE = 0x00, + + /// + /// big-endian + /// + /// non-zero + BE = 0x01, + } + + public enum CPUType : ushort + { + /// + /// Intel 80286 or upwardly compatible + /// + Intel80286 = 0x01, + + /// + /// Intel 80386 or upwardly compatible + /// + Intel80386 = 0x02, + + /// + /// Intel 80486 or upwardly compatible + /// + Intel80486 = 0x03, + + /// + /// Intel 80586 or upwardly compatible + /// + Intel80586 = 0x04, + + /// + /// Intel i860 (N10) or compatible + /// + Inteli860 = 0x20, + + /// + /// Intel "N11" or compatible + /// + IntelN11 = 0x21, + + /// + /// MIPS Mark I (R2000, R3000) or compatible + /// + MIPSMarkI = 0x40, + + /// + /// MIPS Mark II ( R6000 ) or compatible + /// + MIPSMarkII = 0x41, + + /// + /// MIPS Mark III ( R4000 ) or compatible + /// + MIPSMarkIII = 0x42, + } + + public enum DebugFormatType : byte + { + /// + /// 32-bit CodeView debugger format. + /// + CodeView32Bit = 0x00, + + /// + /// AIX debugger format. + /// + AIXDebugger = 0x01, + + /// + /// 16-bit CodeView debugger format. + /// + CodeView16Bit = 0x02, + + /// + /// 32-bit OS/2 PM debugger (IBM) format. + /// + OS2PM32Bit = 0x04, + } + + public enum DirectiveNumber : ushort + { + /// + /// Resident Flag Mask. + /// + /// + /// Directive numbers with this bit set indicate that the directive data + /// is in the resident area and will be kept resident in memory when the + /// module is loaded. + /// + ResidentFlagMask = 0x8000, + + /// + /// Verify Record Directive. (Verify record is a resident table.) + /// + VerifyRecordDirective = 0x8001, + + /// + /// Language Information Directive. (This is a non-resident table.) + /// + LanguageInformationDirective = 0x0002, + + /// + /// Co-Processor Required Support Table. + /// + CoProcessorRequiredSupportTable = 0x0003, + + /// + /// Thread State Initialization Directive. + /// + ThreadStateInitializationDirective = 0x0004, + + // Additional directives can be added as needed in the future, as long as + // they do not overlap previously defined directive numbers. + } + + [Flags] + public enum EntryFlags : byte + { + /// + /// Exported entry flag. + /// + ExportedEntry = 0x01, + + /// + /// Parameter word count mask. + /// + ParameterWordCountMask = 0xF8, + } + + [Flags] + public enum FixupRecordSourceType : byte + { + /// + /// Source mask. + /// + SourceMask = 0x0F, + + /// + /// Byte fixup (8-bits). + /// + ByteFixup = 0x00, + + /// + /// (undefined). + /// + Undefined1 = 0x01, + + /// + /// 16-bit Selector fixup (16-bits). + /// + SixteenBitSelectorFixup = 0x02, + + /// + /// 16:16 Pointer fixup (32-bits). + /// + SixteenSixteenPointerFixup = 0x03, + + /// + /// (undefined). + /// + Undefined4 = 0x04, + + /// + /// 16-bit Offset fixup (16-bits). + /// + SixteenBitOffsetFixup = 0x05, + + /// + /// 16:32 Pointer fixup (48-bits). + /// + SixteenThirtyTwoPointerFixup = 0x06, + + /// + /// 32-bit Offset fixup (32-bits). + /// + ThirtyTwoBitOffsetFixup = 0x07, + + /// + /// 32-bit Self-relative offset fixup (32-bits). + /// + ThirtyTwoBitSelfRelativeOffsetFixup = 0x08, + + /// + /// Fixup to Alias Flag. + /// + /// + /// When the 'Fixup to Alias' Flag is set, the source fixup refers to + /// the 16:16 alias for the object. This is only valid for source types + /// of 2, 3, and 6. For fixups such as this, the linker and loader will + /// be required to perform additional checks such as ensuring that the + /// target offset for this fixup is less than 64K. + /// + FixupToAliasFlag = 0x10, + + /// + /// Source List Flag. + /// + /// + /// When the 'Source List' Flag is set, the SRCOFF field is compressed + /// to a byte and contains the number of source offsets, and a list of source + /// offsets follows the end of fixup record (after the optional additive value). + /// + SourceListFlag = 0x20, + } + + [Flags] + public enum FixupRecordTargetFlags : byte + { + /// + /// Fixup target type mask. + /// + FixupTargetTypeMask = 0x03, + + /// + /// Internal reference. + /// + InternalReference = 0x00, + + /// + /// Imported reference by ordinal. + /// + ImportedReferenceByOrdinal = 0x01, + + /// + /// Imported reference by name. + /// + ImportedReferenceByName = 0x02, + + /// + /// Internal reference via entry table. + /// + InternalReferenceViaEntryTable = 0x03, + + /// + /// Additive Fixup Flag. + /// + /// + /// When set, an additive value trails the fixup record (before the optional + /// source offset list). + /// + AdditiveFixupFlag = 0x04, + + /// + /// Reserved. Must be zero. + /// + Reserved = 0x08, + + /// + /// 32-bit Target Offset Flag. + /// + /// + /// When set, the target offset is 32-bits, otherwise it is 16-bits. + /// + ThirtyTwoBitTargetOffsetFlag = 0x10, + + /// + /// 32-bit Additive Fixup Flag. + /// + /// When set, the additive value is 32-bits, otherwise it is 16-bits. + /// + ThirtyTwoBitAdditiveFixupFlag = 0x20, + + /// + /// 16-bit Object Number/Module Ordinal Flag. + /// + /// + /// When set, the object number or module ordinal number is 16-bits, + /// otherwise it is 8-bits. + /// + SixteenBitObjectNumberModuleOrdinalFlag = 0x40, + + /// + /// 8-bit Ordinal Flag. + /// + /// + /// When set, the ordinal number is 8-bits, otherwise it is 16-bits. + /// + EightBitOrdinalFlag = 0x80, + } + + [Flags] + public enum ForwarderFlags : byte + { + /// + /// Import by ordinal. + /// + ImportByOrdinal = 0x01, + + /// + /// Reserved for future use; should be zero. + /// + Reserved = 0xF7, + } + + [Flags] + public enum ModuleFlags : uint + { + /// + /// Reserved for system use. + /// + Reserved0 = 0x00000001, + + /// + /// Reserved for system use. + /// + Reserved1 = 0x00000002, + + /// + /// Per-Process Library Initialization. + /// + /// + /// The setting of this bit requires the EIP Object # and EIP fields + /// to have valid values. If the EIP Object # and EIP fields are + /// valid and this bit is NOT set, then Global Library Initialization + /// is assumed. Setting this bit for an EXE file is invalid. + /// + Initialization = 0x00000004, + + /// + /// Reserved for system use. + /// + Reserved3 = 0x00000008, + + /// + /// Internal fixups for the module have been applied. + /// + /// + /// The setting of this bit in a Linear Executable Module indicates that + /// each object of the module has a preferred load address specified in + /// the Object Table Reloc Base Addr. If the module's objects can not be + /// loaded at these preferred addresses, then the relocation records that + /// have been retained in the file data will be applied. + /// + InternalFixupsApplied = 0x00000010, + + /// + /// External fixups for the module have been applied. + /// + ExternalFixupsApplied = 0x00000020, + + /// + /// Reserved for system use. + /// + Reserved6 = 0x00000040, + + /// + /// Reserved for system use. + /// + Reserved7 = 0x00000080, + + /// + /// Incompatible with PM windowing. + /// + IncompatibleWithPMWindowing = 0x00000100, + + /// + /// Incompatible with PM windowing. + /// + CompatibleWithPMWindowing = 0x00000200, + + /// + /// Uses PM windowing API. + /// + UsesPMWindowing = 0x00000300, + + /// + /// Reserved for system use. + /// + Reserved10 = 0x00000400, + + /// + /// Reserved for system use. + /// + Reserved11 = 0x00000800, + + /// + /// Reserved for system use. + /// + Reserved12 = 0x00001000, + + /// + /// Module is not loadable. + /// + /// + /// When the 'Module is not loadable' flag is set, it indicates that + /// either errors were detected at link time or that the module is + /// being incrementally linked and therefore can't be loaded. + /// + ModuleNotLoadable = 0x00002000, + + /// + /// Reserved for system use. + /// + Reserved14 = 0x00004000, + + /// + /// Module type mask. + /// + ModuleTypeMask = 0x00038000, + + /// + /// Program module. + /// + /// + /// A module can not contain dynamic links to other modules that have + /// the 'program module' type. + /// + ProgramModule = 0x00000000, + + /// + /// Library module. + /// + LibraryModule = 0x00008000, + + /// + /// Protected Memory Library module. + /// + ProtectedMemoryLibraryModule = 0x00018000, + + /// + /// Physical Device Driver module. + /// + PhysicalDeviceDriverModule = 0x00020000, + + /// + /// Virtual Device Driver module. + /// + VirtualDeviceDriverModule = 0x00028000, + + /// + /// Per-process Library Termination. + /// + /// + /// The setting of this bit requires the EIP Object # and EIP fields + /// to have valid values. If the EIP Object # and EIP fields are + /// valid and this bit is NOT set, then Global Library Termination + /// is assumed. Setting this bit for an EXE file is invalid. + /// + PerProcessLibraryTermination = 0x40000000, + } + + [Flags] + public enum ObjectFlags : ushort + { + /// + /// Readable Object. + /// + ReadableObject = 0x0001, + + /// + /// Writable Object. + /// + WritableObject = 0x0002, + + /// + /// Executable Object. + /// + ExecutableObject = 0x0004, + + // The readable, writable and executable flags provide support for all possible + // protections. In systems where all of these protections are not supported, + // the loader will be responsible for making the appropriate protection match + // for the system. + + /// + /// Resource Object. + /// + ResourceObject = 0x0008, + + /// + /// Discardable Object. + /// + DiscardableObject = 0x0010, + + /// + /// Object is Shared. + /// + Shared = 0x0020, + + /// + /// Object has Preload Pages. + /// + HasPreloadPages = 0x0040, + + /// + /// Object has Invalid Pages. + /// + HasInvalidPages = 0x0080, + + /// + /// Object has Zero Filled Pages. + /// + HasZeroFilledPages = 0x0100, + + /// + /// Object is Resident (valid for VDDs, PDDs only). + /// + Resident = 0x0200, + + /// + /// Object is Resident & Contiguous (VDDs, PDDs only). + /// + ResidentAndContiguous = 0x0300, + + /// + /// Object is Resident & 'long-lockable' (VDDs, PDDs only). + /// + ResidentAndLongLockable = 0x0400, + + /// + /// Reserved for system use. + /// + Reserved = 0x0800, + + /// + /// 16:16 Alias Required (80x86 Specific). + /// + AliasRequired = 0x1000, + + /// + /// Big/Default Bit Setting (80x86 Specific). + /// + BitSetting = 0x2000, + + // The 'big/default' bit, for data segments, controls the setting of the + // Big bit in the segment descriptor. (The Big bit, or B-bit, determines + // whether ESP or SP is used as the stack pointer.) For code segments, + // this bit controls the setting of the Default bit in the segment + // descriptor. (The Default bit, or D-bit, determines whether the default + // word size is 32-bits or 16-bits. It also affects the interpretation of + // the instruction stream.) + + /// + /// Object is conforming for code (80x86 Specific). + /// + Conforming = 0x4000, + + /// + /// Object I/O privilege level (80x86 Specific). Only used for 16:16 Alias Objects. + /// + PrivilegeLevel = 0x8000, + } + + [Flags] + public enum ObjectPageFlags : ushort + { + /// + /// Legal Physical Page in the module (Offset from Preload Page Section). + /// + LegalPhysicalPage = 0x0000, + + /// + /// Iterated Data Page (Offset from Iterated Data Pages Section). + /// + IteratedDataPage = 0x0001, + + /// + /// Invalid Page (zero). + /// + InvalidPage = 0x0002, + + /// + /// Zero Filled Page (zero). + /// + ZeroFilledPage = 0x0003, + + /// + /// Range of Pages. + /// + RangeOfPages = 0x0004, + } + + public enum OperatingSystem : ushort + { + /// + /// Unknown (any "new-format" OS) + /// + Unknown = 0x00, + + /// + /// OS/2 (default) + /// + OS2 = 0x01, + + /// + /// Windows + /// + Windows = 0x02, + + /// + /// DOS 4.x + /// + DOS4x = 0x03, + + /// + /// Windows 386 + /// + Windows386 = 0x04, + } + + public enum ResourceTableEntryType : uint + { + /// + /// "BTMP" - Bitmap + /// + BTMP = 0x504d5442, + + /// + /// "EMSG" - Error message string + /// + EMSG = 0x47534d45, + + /// + /// "FONT" - Fonts + /// + FONT = 0x544e4f46, + } + + public enum WordOrder : byte + { + /// + /// little-endian + /// + LE = 0x00, + + /// + /// big-endian + /// + /// non-zero + BE = 0x01, + } +} diff --git a/SabreTools.Serialization/Models/LinearExecutable/Executable.cs b/SabreTools.Serialization/Models/LinearExecutable/Executable.cs new file mode 100644 index 00000000..39f35c60 --- /dev/null +++ b/SabreTools.Serialization/Models/LinearExecutable/Executable.cs @@ -0,0 +1,97 @@ +namespace SabreTools.Serialization.Models.LinearExecutable +{ + /// + /// The `LINEAR` executable-file header contains information that the loader requires for + /// segmented executable files. This information includes the linker version number, data + /// specified by linker, data specified by resource compiler, tables of segment data, tables + /// of resource data, and so on. The following illustrations shows the LE file header: + /// + /// + /// + public sealed class Executable + { + /// + /// MS-DOS executable stub + /// + public MSDOS.Executable? Stub { get; set; } + + /// + /// Information block + /// + public InformationBlock? InformationBlock { get; set; } + + /// + /// Object table + /// + public ObjectTableEntry[]? ObjectTable { get; set; } + + /// + /// Object page map + /// + public ObjectPageMapEntry[]? ObjectPageMap { get; set; } + + // TODO: Object iterate data map table (Undefined) + + /// + /// Resource table + /// + public ResourceTableEntry[]? ResourceTable { get; set; } + + /// + /// Resident Name table + /// + public ResidentNamesTableEntry[]? ResidentNamesTable { get; set; } + + /// + /// Entry table + /// + public EntryTableBundle[]? EntryTable { get; set; } + + /// + /// Module format directives table (optional) + /// + public ModuleFormatDirectivesTableEntry[]? ModuleFormatDirectivesTable { get; set; } + + /// + /// Verify record directive table (optional) + /// + public VerifyRecordDirectiveTableEntry[]? VerifyRecordDirectiveTable { get; set; } + + /// + /// Fix-up page table + /// + public FixupPageTableEntry[]? FixupPageTable { get; set; } + + /// + /// Fix-up record table + /// + public FixupRecordTableEntry[]? FixupRecordTable { get; set; } + + /// + /// Import module name table + /// + public ImportModuleNameTableEntry[]? ImportModuleNameTable { get; set; } + + /// + /// Import procedure name table + /// + public ImportModuleProcedureNameTableEntry[]? ImportModuleProcedureNameTable { get; set; } + + /// + /// Per-Page checksum table + /// + public PerPageChecksumTableEntry[]? PerPageChecksumTable { get; set; } + + /// + /// Non-Resident Name table + /// + public NonResidentNamesTableEntry[]? NonResidentNamesTable { get; set; } + + // TODO: Non-resident directives data (Undefined) + + /// + /// Debug information + /// + public DebugInformation? DebugInformation { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/LinearExecutable/FixupPageTableEntry.cs b/SabreTools.Serialization/Models/LinearExecutable/FixupPageTableEntry.cs new file mode 100644 index 00000000..a4171d16 --- /dev/null +++ b/SabreTools.Serialization/Models/LinearExecutable/FixupPageTableEntry.cs @@ -0,0 +1,36 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.LinearExecutable +{ + /// + /// The Fixup Page Table provides a simple mapping of a logical page number + /// to an offset into the Fixup Record Table for that page. + /// + /// This table is parallel to the Object Page Table, except that there is + /// one additional entry in this table to indicate the end of the Fixup + /// Record Table. + /// + /// The fixup records are kept in order by logical page in the fixup record + /// table. This allows the end of each page's fixup records is defined by the + /// offset for the next logical page's fixup records. This last entry provides + /// support of this mechanism for the last page in the fixup page table. + /// + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class FixupPageTableEntry + { + /// + /// Offset for fixup record for this page. (1 to n) + /// Offset to the end of the fixup records. (n + 1) + /// + /// + /// This field specifies the offset, from the beginning of the fixup record + /// table, to the first fixup record for this page. (1 to n) + /// + /// This field specifies the offset following the last fixup record in the + /// fixup record table. This is the last entry in the fixup page table. (n + 1) + /// + public uint Offset; + } +} diff --git a/SabreTools.Serialization/Models/LinearExecutable/FixupRecordTableEntry.cs b/SabreTools.Serialization/Models/LinearExecutable/FixupRecordTableEntry.cs new file mode 100644 index 00000000..2ff41447 --- /dev/null +++ b/SabreTools.Serialization/Models/LinearExecutable/FixupRecordTableEntry.cs @@ -0,0 +1,363 @@ +namespace SabreTools.Serialization.Models.LinearExecutable +{ + /// + /// The Fixup Record Table contains entries for all fixups in the linear EXE module. + /// The fixup records for a logical page are grouped together and kept in sorted + /// order by logical page number. The fixups for each page are further sorted such + /// that all external fixups and internal selector/pointer fixups come before + /// internal non-selector/non-pointer fixups. This allows the loader to ignore + /// internal fixups if the loader is able to load all objects at the addresses + /// specified in the object table. + /// + /// + /// + public sealed class FixupRecordTableEntry + { + /// + /// Source type. + /// + /// + /// The source type specifies the size and type of the fixup to be performed + /// on the fixup source. + /// + public FixupRecordSourceType SourceType { get; set; } + + /// + /// Target Flags. + /// + /// + /// The target flags specify how the target information is interpreted. + /// + public FixupRecordTargetFlags TargetFlags { get; set; } + + #region Source List Flag + + #region Set + + /// + /// Source offset. + /// + /// + /// This field contains either an offset or a count depending on the Source + /// List Flag. If the Source List Flag is set, a list of source offsets + /// follows the additive field and this field contains the count of the + /// entries in the source offset list. Otherwise, this is the single source + /// offset for the fixup. Source offsets are relative to the beginning of + /// the page where the fixup is to be made. + /// + /// Note that for fixups that cross page boundaries, a separate fixup record + /// is specified for each page. An offset is still used for the 2nd page but + /// it now becomes a negative offset since the fixup originated on the + /// preceding page. (For example, if only the last one byte of a 32-bit + /// address is on the page to be fixed up, then the offset would have a value + /// of -3.) + /// + public ushort SourceOffset { get; set; } + + #endregion + + #region Unset + + /// + /// Source offset list count. + /// + /// + /// This field contains either an offset or a count depending on the Source + /// List Flag. If the Source List Flag is set, a list of source offsets + /// follows the additive field and this field contains the count of the + /// entries in the source offset list. Otherwise, this is the single source + /// offset for the fixup. Source offsets are relative to the beginning of + /// the page where the fixup is to be made. + /// + /// Note that for fixups that cross page boundaries, a separate fixup record + /// is specified for each page. An offset is still used for the 2nd page but + /// it now becomes a negative offset since the fixup originated on the + /// preceding page. (For example, if only the last one byte of a 32-bit + /// address is on the page to be fixed up, then the offset would have a value + /// of -3.) + /// + public byte SourceOffsetListCount { get; set; } + + #endregion + + #endregion + + #region OBJECT / TRGOFF + + #region 16-bit Object Number/Module Ordinal Flag + + #region Set + + /// + /// Target object number. + /// + /// + /// This field is an index into the current module's Object Table to specify + /// the target Object. It is a Byte value when the '16-bit Object Number/Module + /// Ordinal Flag' bit in the target flags field is clear and a Word value when + /// the bit is set. + /// + public ushort TargetObjectNumberWORD { get; set; } + + #endregion + + #region Unset + + /// + /// Target object number. + /// + /// + /// This field is an index into the current module's Object Table to specify + /// the target Object. It is a Byte value when the '16-bit Object Number/Module + /// Ordinal Flag' bit in the target flags field is clear and a Word value when + /// the bit is set. + /// + public byte TargetObjectNumberByte { get; set; } + + #endregion + + #endregion + + #region 32-bit Target Offset Flag + + #region Set + + /// + /// Target offset. + /// + /// + /// This field is an offset into the specified target Object. It is not + /// present when the Source Type specifies a 16-bit Selector fixup. It + /// is a Word value when the '32-bit Target Offset Flag' bit in the target + /// flags field is clear and a Dword value when the bit is set. + /// + public uint TargetOffsetDWORD { get; set; } + + #endregion + + #region Unset + + /// + /// Target offset. + /// + /// + /// This field is an offset into the specified target Object. It is not + /// present when the Source Type specifies a 16-bit Selector fixup. It + /// is a Word value when the '32-bit Target Offset Flag' bit in the target + /// flags field is clear and a Dword value when the bit is set. + /// + public ushort TargetOffsetWORD { get; set; } + + #endregion + + #endregion + + #endregion + + #region 16-bit Object Number/Module Ordinal Flag [Incompatible with OBJECT / TRGOFF] + + #region Set + + /// + /// Ordinal index into the Import Module Name Table. + /// + /// + /// This value is an ordered index in to the Import Module Name Table for + /// the module containing the procedure entry point. It is a Byte value + /// when the '16-bit Object Number/Module Ordinal' Flag bit in the target + /// flags field is clear and a Word value when the bit is set. The loader + /// creates a table of pointers with each pointer in the table corresponds + /// to the modules named in the Import Module Name Table. This value is used + /// by the loader to index into this table created by the loader to locate + /// the referenced module. + /// + public ushort OrdinalIndexImportModuleNameTableWORD { get; set; } + + #endregion + + #region Unset + + /// + /// Ordinal index into the Import Module Name Table. + /// + /// + /// This value is an ordered index in to the Import Module Name Table for + /// the module containing the procedure entry point. It is a Byte value + /// when the '16-bit Object Number/Module Ordinal' Flag bit in the target + /// flags field is clear and a Word value when the bit is set. The loader + /// creates a table of pointers with each pointer in the table corresponds + /// to the modules named in the Import Module Name Table. This value is used + /// by the loader to index into this table created by the loader to locate + /// the referenced module. + /// + public byte OrdinalIndexImportModuleNameTableByte { get; set; } + + #endregion + + #endregion + + #region MOD ORD# / PROCEDURE NAME OFFSET / ADDITIVE + + #region 32-bit Target Offset Flag + + #region Set + + /// + /// Offset into the Import Procedure Name Table. + /// + /// + /// This field is an offset into the Import Procedure Name Table. It is + /// a Word value when the '32-bit Target Offset Flag' bit in the target + /// flags field is clear and a Dword value when the bit is set. + /// + public uint OffsetImportProcedureNameTableDWORD { get; set; } + + #endregion + + #region Unset + + /// + /// Offset into the Import Procedure Name Table. + /// + /// + /// This field is an offset into the Import Procedure Name Table. It is + /// a Word value when the '32-bit Target Offset Flag' bit in the target + /// flags field is clear and a Dword value when the bit is set. + /// + public ushort OffsetImportProcedureNameTableWORD { get; set; } + + #endregion + + #endregion + + #endregion + + #region MOD ORD# / IMPORT ORD / ADDITIVE + + #region 8-bit Ordinal Flag + + #region Set + + /// + /// Imported ordinal number. + /// + /// + /// This is the imported procedure's ordinal number. It is a Byte value when the + /// '8-bit Ordinal' bit in the target flags field is set. Otherwise it is a Word value + /// when the '32-bit Target Offset Flag' bit in the target flags field is clear and a + /// Dword value when the bit is set. + /// + public byte ImportedOrdinalNumberByte { get; set; } + + #endregion + + #region Unset + + #region 32-bit Target Offset Flag + + #region Set + + /// + /// Imported ordinal number. + /// + /// + /// This is the imported procedure's ordinal number. It is a Byte value when the + /// '8-bit Ordinal' bit in the target flags field is set. Otherwise it is a Word value + /// when the '32-bit Target Offset Flag' bit in the target flags field is clear and a + /// Dword value when the bit is set. + /// + public uint ImportedOrdinalNumberDWORD { get; set; } + + #endregion + + #region Unset + + /// + /// Imported ordinal number. + /// + /// + /// This is the imported procedure's ordinal number. It is a Byte value when the + /// '8-bit Ordinal' bit in the target flags field is set. Otherwise it is a Word value + /// when the '32-bit Target Offset Flag' bit in the target flags field is clear and a + /// Dword value when the bit is set. + /// + public uint ImportedOrdinalNumberWORD { get; set; } + + #endregion + + #endregion + + #endregion + + #endregion + + #endregion + + #region Additive Fixup Flag [Incompatible with OBJECT / TRGOFF] + + #region Set + + #region 32-bit Additive Fixup Flag + + #region Set + + /// + /// Additive fixup value. + /// + /// + /// This field exists in the fixup record only when the 'Additive Fixup Flag' + /// bit in the target flags field is set. When the 'Additive Fixup Flag' is + /// clear the fixup record does not contain this field and is immediately + /// followed by the next fixup record (or by the source offset list for this + /// fixup record). + /// + /// This value is added to the address derived from the target entry point. + /// This field is a Word value when the '32-bit Additive Flag' bit in the + /// target flags field is clear and a Dword value when the bit is set. + /// + public uint AdditiveFixupValueDWORD { get; set; } + + #endregion + + #region Unset + + /// + /// Additive fixup value. + /// + /// + /// This field exists in the fixup record only when the 'Additive Fixup Flag' + /// bit in the target flags field is set. When the 'Additive Fixup Flag' is + /// clear the fixup record does not contain this field and is immediately + /// followed by the next fixup record (or by the source offset list for this + /// fixup record). + /// + /// This value is added to the address derived from the target entry point. + /// This field is a Word value when the '32-bit Additive Flag' bit in the + /// target flags field is clear and a Dword value when the bit is set. + /// + public ushort AdditiveFixupValueWORD { get; set; } + + #endregion + + #endregion + + #endregion + + #endregion + + #region SCROFFn + + /// + /// Source offset list. + /// + /// + /// This list is present if the Source List Flag is set in the Target Flags field. + /// The number of entries in the source offset list is defined in the SRCOFF/CNT + /// field. The source offsets are relative to the beginning of the page where the + /// fixups are to be made. + /// + public ushort[]? SourceOffsetList { get; set; } + + #endregion + } +} diff --git a/SabreTools.Serialization/Models/LinearExecutable/ImportModuleNameTableEntry.cs b/SabreTools.Serialization/Models/LinearExecutable/ImportModuleNameTableEntry.cs new file mode 100644 index 00000000..5c352a83 --- /dev/null +++ b/SabreTools.Serialization/Models/LinearExecutable/ImportModuleNameTableEntry.cs @@ -0,0 +1,38 @@ +namespace SabreTools.Serialization.Models.LinearExecutable +{ + /// + /// The import module name table defines the module name strings imported through + /// dynamic link references. These strings are referenced through the imported + /// relocation fixups. + /// + /// To determine the length of the import module name table subtract the import + /// module name table offset from the import procedure name table offset. These + /// values are located in the linear EXE header. The end of the import module + /// name table is not terminated by a special character, it is followed directly + /// by the import procedure name table. + /// + /// The strings are CASE SENSITIVE and NOT NULL TERMINATED. + /// + /// + /// + public sealed class ImportModuleNameTableEntry + { + /// + /// String Length. + /// + /// + /// This defines the length of the string in bytes. The length of each + /// ascii name string is limited to 127 characters. + /// + public byte Length { get; set; } // TODO: Remove in lieu of AnsiBStr + + /// + /// ASCII String. + /// + /// + /// This is a variable length string with it's length defined in bytes by + /// the LEN field. The string is case sensitive and is not null terminated. + /// + public string? Name { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/LinearExecutable/ImportProcedureNameTableEntry.cs b/SabreTools.Serialization/Models/LinearExecutable/ImportProcedureNameTableEntry.cs new file mode 100644 index 00000000..34fe3eac --- /dev/null +++ b/SabreTools.Serialization/Models/LinearExecutable/ImportProcedureNameTableEntry.cs @@ -0,0 +1,46 @@ +namespace SabreTools.Serialization.Models.LinearExecutable +{ + /// + /// The import procedure name table defines the procedure name strings imported + /// by this module through dynamic link references. These strings are referenced + /// through the imported relocation fixups. + /// + /// To determine the length of the import procedure name table add the fixup + /// section size to the fixup page table offset, this computes the offset to + /// the end of the fixup section, then subtract the import procedure name table + /// offset. These values are located in the linear EXE header. The import + /// procedure name table is followed by the data pages section. Since the data + /// pages section is aligned on a 'page size' boundary, padded space may exist + /// between the last import name string and the first page in the data pages + /// section. If this padded space exists it will be zero filled. + /// + /// The strings are CASE SENSITIVE and NOT NULL TERMINATED. + /// + /// + /// + public sealed class ImportModuleProcedureNameTableEntry + { + /// + /// String Length. + /// + /// + /// This defines the length of the string in bytes. The length of each + /// ascii name string is limited to 127 characters. + /// + /// The high bit in the LEN field (bit 7) is defined as an Overload bit. + /// This bit signifies that additional information is contained in the + /// linear EXE module and will be used in the future for parameter type + /// checking. + /// + public byte Length { get; set; } // TODO: Remove in lieu of AnsiBStr + + /// + /// ASCII String. + /// + /// + /// This is a variable length string with it's length defined in bytes by + /// the LEN field. The string is case sensitive and is not null terminated. + /// + public string? Name { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/LinearExecutable/InformationBlock.cs b/SabreTools.Serialization/Models/LinearExecutable/InformationBlock.cs new file mode 100644 index 00000000..67970046 --- /dev/null +++ b/SabreTools.Serialization/Models/LinearExecutable/InformationBlock.cs @@ -0,0 +1,432 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.LinearExecutable +{ + /// + /// The `information block` in the LE header contains the linker version number, + /// length of various tables that further describe the executable file, the + /// offsets from the beginning of the header to the beginning of these tables, + /// the heap and stack sizes, and so on. The following list summarizes the + /// contents of the header `information block` (the locations are relative to + /// the beginning of the block): + /// + /// + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public sealed class InformationBlock + { + /// + /// Specifies the signature word + /// 'LE' (4Ch 45H) + /// 'LX' (4Ch 58H) + /// + /// + /// The signature word is used by the loader to identify the EXE + /// file as a valid 32-bit Linear Executable Module Format. + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 2)] + public string? Signature; + + /// + /// Byte Ordering. + /// + /// + /// This byte specifies the byte ordering for the linear EXE format. + /// + [MarshalAs(UnmanagedType.U1)] + public ByteOrder ByteOrder; + + /// + /// Word Ordering. + /// + /// + /// This byte specifies the Word ordering for the linear EXE format. + /// + [MarshalAs(UnmanagedType.U1)] + public WordOrder WordOrder; + + /// + /// Linear EXE Format Level. + /// + /// + /// The Linear EXE Format Level is set to 0 for the initial version of the + /// 32-bit linear EXE format. Each incompatible change to the linear EXE + /// format must increment this value. This allows the system to recognized + /// future EXE file versions so that an appropriate error message may be + /// displayed if an attempt is made to load them. + /// + public uint ExecutableFormatLevel; + + /// + /// Module CPU Type. + /// + /// + /// This field specifies the type of CPU required by this module to run. + /// + [MarshalAs(UnmanagedType.U2)] + public CPUType CPUType; + + /// + /// Module OS Type. + /// + /// + /// This field specifies the type of Operating system required to run this module. + /// + [MarshalAs(UnmanagedType.U2)] + public OperatingSystem ModuleOS; + + /// + /// Module version + /// + /// + /// This is useful for differentiating between revisions of dynamic linked modules. + /// This value is specified at link time by the user. + /// + public uint ModuleVersion; + + /// + /// Module type flags + /// + [MarshalAs(UnmanagedType.U4)] + public ModuleFlags ModuleTypeFlags; + + /// + /// Number of pages in module. + /// + /// + /// This field specifies the number of pages physically contained in this module. + /// In other words, pages containing either enumerated or iterated data, or + /// zero-fill pages that have relocations, not invalid or zero-fill pages implied + /// by the Virtual Size in the Object Table being larger than the number of pages + /// actually in the linear EXE file. These pages are contained in the 'preload + /// pages', 'demand load pages' and 'iterated data pages' sections of the linear + /// EXE module. This is used to determine the size of the page information tables + /// in the linear EXE module. + /// + public uint ModuleNumberPages; + + /// + /// The Object number to which the Entry Address is relative. + /// + /// + /// This specifies the object to which the Entry Address is relative. This must be + /// a nonzero value for a program module to be correctly loaded. A zero value for + /// a library module indicates that no library entry routine exists. If this value + /// is zero, then both the Per-process Library Initialization bit and the Per-process + /// Library Termination bit must be clear in the module flags, or else the loader + /// will fail to load the module. Further, if the Per-process Library Termination bit + /// is set, then the object to which this field refers must be a 32-bit object (i.e., + /// the Big/Default bit must be set in the object flags; see below). + /// + public uint InitialObjectCS; + + /// + /// Entry Address of module. + /// + /// + /// The Entry Address is the starting address for program modules and the library + /// initialization and Library termination address for library modules. + /// + public uint InitialEIP; + + /// + /// The Object number to which the ESP is relative. + /// + /// + /// This specifies the object to which the starting ESP is relative. This must be a + /// nonzero value for a program module to be correctly loaded. This field is ignored + /// for a library module. + /// + public uint InitialObjectSS; + + /// + /// Starting stack address of module. + /// + /// + /// The ESP defines the starting stack pointer address for program modules. A zero + /// value in this field indicates that the stack pointer is to be initialized to the + /// highest address/offset in the object. This field is ignored for a library module. + /// + public uint InitialESP; + + /// + /// The size of one page for this system. + /// + /// + /// This field specifies the page size used by the linear EXE format and the system. + /// For the initial version of this linear EXE format the page size is 4Kbytes. + /// (The 4K page size is specified by a value of 4096 in this field.) + /// + public uint MemoryPageSize; + + /// + /// The shift left bits for page offsets. + /// + /// + /// This field gives the number of bit positions to shift left when interpreting + /// the Object Page Table entries' page offset field. This determines the alignment + /// of the page information in the file. For example, a value of 4 in this field + /// would align all pages in the Data Pages and Iterated Pages sections on 16 byte + /// (paragraph) boundaries. A Page Offset Shift of 9 would align all pages on a + /// 512 byte (disk sector) basis. The default value for this field is 12 (decimal), + /// which give a 4096 byte alignment. All other offsets are byte aligned. + /// + public uint BytesOnLastPage; + + /// + /// Total size of the fixup information in bytes. + /// + /// + /// This includes the following 4 tables: + /// - Fixup Page Table + /// - Fixup Record Table + /// - Import Module name Table + /// - Import Procedure Name Table + /// + public uint FixupSectionSize; + + /// + /// Checksum for fixup information. + /// + /// + /// This is a cryptographic checksum covering all of the fixup information. The + /// checksum for the fixup information is kept separate because the fixup data is + /// not always loaded into main memory with the 'loader section'. If the checksum + /// feature is not implemented, then the linker will set these fields to zero. + /// + public uint FixupSectionChecksum; + + /// + /// Size of memory resident tables. + /// + /// + /// This is the total size in bytes of the tables required to be memory resident + /// for the module, while the module is in use. This total size includes all + /// tables from the Object Table down to and including the Per-Page Checksum Table. + /// + public uint LoaderSectionSize; + + /// + /// Checksum for loader section. + /// + /// + /// This is a cryptographic checksum covering all of the loader section information. + /// If the checksum feature is not implemented, then the linker will set these fields + /// to zero. + /// + public uint LoaderSectionChecksum; + + /// + /// Object Table offset. + /// + /// + /// This offset is relative to the beginning of the linear EXE header. + /// + public uint ObjectTableOffset; + + /// + /// Object Table Count. + /// + /// + /// This defines the number of entries in Object Table. + /// + public uint ObjectTableCount; + + /// + /// Object Page Table offset + /// + /// + /// This offset is relative to the beginning of the linear EXE header. + /// + public uint ObjectPageMapOffset; + + /// + /// Object Iterated Pages offset. + /// + /// + /// This offset is relative to the beginning of the linear EXE header. + /// + public uint ObjectIterateDataMapOffset; + + /// + /// Resource Table offset + /// + /// + /// This offset is relative to the beginning of the linear EXE header. + /// + public uint ResourceTableOffset; + + /// + /// Number of entries in Resource Table. + /// + public uint ResourceTableCount; + + /// + /// Resident Name Table offset. + /// + /// + /// This offset is relative to the beginning of the linear EXE header. + /// + public uint ResidentNamesTableOffset; + + /// + /// Entry Table offset. + /// + /// + /// This offset is relative to the beginning of the linear EXE header. + /// + public uint EntryTableOffset; + + /// + /// Module Format Directives Table offset. + /// + /// + /// This offset is relative to the beginning of the linear EXE header. + /// + public uint ModuleDirectivesTableOffset; + + /// + /// Number of Module Format Directives in the Table. + /// + /// + /// This field specifies the number of entries in the + /// Module Format Directives Table. + /// + public uint ModuleDirectivesCount; + + /// + /// Fixup Page Table offset. + /// + /// + /// This offset is relative to the beginning of the linear EXE header. + /// + public uint FixupPageTableOffset; + + /// + /// Fixup Record Table offset. + /// + /// + /// This offset is relative to the beginning of the linear EXE header. + /// + public uint FixupRecordTableOffset; + + /// + /// Import Module Name Table offset. + /// + /// + /// This offset is relative to the beginning of the linear EXE header. + /// + public uint ImportedModulesNameTableOffset; + + /// + /// The number of entries in the Import Module Name Table. + /// + public uint ImportedModulesCount; + + /// + /// Import Procedure Name Table offset. + /// + /// + /// This offset is relative to the beginning of the linear EXE header. + /// + public uint ImportProcedureNameTableOffset; + + /// + /// Per-page Checksum Table offset. + /// + /// + /// This offset is relative to the beginning of the linear EXE header. + /// + public uint PerPageChecksumTableOffset; + + /// + /// Data Pages Offset. + /// + /// + /// This offset is relative to the beginning of the EXE file. + /// + public uint DataPagesOffset; + + /// + /// Number of Preload pages for this module. + /// + /// + /// Note that OS/2 2.0 does not respect the preload of pages as specified + /// in the executable file for performance reasons. + /// + public uint PreloadPageCount; + + /// + /// Non-Resident Name Table offset. + /// + /// + /// This offset is relative to the beginning of the EXE file. + /// + public uint NonResidentNamesTableOffset; + + /// + /// Number of bytes in the Non-resident name table. + /// + public uint NonResidentNamesTableLength; + + /// + /// Non-Resident Name Table Checksum. + /// + /// + /// This is a cryptographic checksum of the Non-Resident Name Table. + /// + public uint NonResidentNamesTableChecksum; + + /// + /// The Auto Data Segment Object number. + /// + /// + /// This is the object number for the Auto Data Segment used by 16-bit modules. + /// This field is supported for 16-bit compatibility only and is not used by + /// 32-bit modules. + /// + public uint AutomaticDataObject; + + /// + /// Debug Information offset. + /// + /// + /// This offset is relative to the beginning of the linear EXE header. + /// + public uint DebugInformationOffset; + + /// + /// Debug Information length. + /// + /// + /// The length of the debug information in bytes. + /// + public uint DebugInformationLength; + + /// + /// Instance pages in preload section. + /// + /// + /// The number of instance data pages found in the preload section. + /// + public uint PreloadInstancePagesNumber; + + /// + /// Instance pages in demand section. + /// + /// + /// The number of instance data pages found in the demand section. + /// + public uint DemandInstancePagesNumber; + + /// + /// Heap size added to the Auto DS Object. + /// + /// + /// The heap size is the number of bytes added to the Auto Data Segment + /// by the loader. This field is supported for 16-bit compatibility only and + /// is not used by 32-bit modules. + /// + public uint ExtraHeapAllocation; + } +} diff --git a/SabreTools.Serialization/Models/LinearExecutable/ModuleFormatDirectivesTableEntry.cs b/SabreTools.Serialization/Models/LinearExecutable/ModuleFormatDirectivesTableEntry.cs new file mode 100644 index 00000000..c5770cfe --- /dev/null +++ b/SabreTools.Serialization/Models/LinearExecutable/ModuleFormatDirectivesTableEntry.cs @@ -0,0 +1,49 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.LinearExecutable +{ + /// + /// The Module Format Directives Table is an optional table that allows additional + /// options to be specified. It also allows for the extension of the linear EXE + /// format by allowing additional tables of information to be added to the linear + /// EXE module without affecting the format of the linear EXE header. Likewise, + /// module format directives provide a place in the linear EXE module for + /// 'temporary tables' of information, such as incremental linking information + /// and statistic information gathered on the module. When there are no module + /// format directives for a linear EXE module, the fields in the linear EXE header + /// referencing the module format directives table are zero. + /// + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class ModuleFormatDirectivesTableEntry + { + /// + /// Directive number. + /// + /// + /// The directive number specifies the type of directive defined. This can be + /// used to determine the format of the information in the directive data. + /// + [MarshalAs(UnmanagedType.U2)] + public DirectiveNumber DirectiveNumber; + + /// + /// Directive data length. + /// + /// + /// This specifies the length in byte of the directive data for this directive number. + /// + public ushort DirectiveDataLength; + + /// + /// Directive data offset. + /// + /// + /// This is the offset to the directive data for this directive number. It is relative + /// to beginning of linear EXE header for a resident table, and relative to the + /// beginning of the EXE file for non-resident tables. + /// + public uint DirectiveDataOffset; + } +} diff --git a/SabreTools.Serialization/Models/LinearExecutable/NonResidentNamesTableEntry.cs b/SabreTools.Serialization/Models/LinearExecutable/NonResidentNamesTableEntry.cs new file mode 100644 index 00000000..87437363 --- /dev/null +++ b/SabreTools.Serialization/Models/LinearExecutable/NonResidentNamesTableEntry.cs @@ -0,0 +1,64 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.LinearExecutable +{ + /// + /// The resident and non-resident name tables define the ASCII names and ordinal + /// numbers for exported entries in the module. In addition the first entry in + /// the resident name table contains the module name. These tables are used to + /// translate a procedure name string into an ordinal number by searching for a + /// matching name string. The ordinal number is used to locate the entry point + /// information in the entry table. + /// + /// The resident name table is kept resident in system memory while the module is + /// loaded.It is intended to contain the exported entry point names that are + /// frequently dynamically linked to by name.Non-resident names are not kept in + /// memory and are read from the EXE file when a dynamic link reference is made. + /// Exported entry point names that are infrequently dynamically linked to by name + /// or are commonly referenced by ordinal number should be placed in the + /// non-resident name table.The trade off made for references by name is performance + /// vs memory usage. + /// + /// Import references by name require these tables to be searched to obtain the entry + /// point ordinal number.Import references by ordinal number provide the fastest + /// lookup since the search of these tables is not required. + /// + /// The strings are CASE SENSITIVE and are NOT NULL TERMINATED. + /// + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class NonResidentNamesTableEntry + { + /// + /// String Length. + /// + /// + /// This defines the length of the string in bytes. A zero length indicates there are + /// no more entries in table. The length of each ascii name string is limited to 127 + /// characters. + /// + /// The high bit in the LEN field (bit 7) is defined as an Overload bit. This bit + /// signifies that additional information is contained in the linear EXE module and + /// will be used in the future for parameter type checking. + /// + public byte Length { get; set; } + + /// + /// ASCII String. + /// + /// + /// This is a variable length string with it's length defined in bytes by the LEN field. + /// The string is case case sensitive and is not null terminated. + /// + public string? Name { get; set; } + + /// + /// Ordinal number. + /// + /// + /// The ordinal number in an ordered index into the entry table for this entry point. + /// + public ushort OrdinalNumber { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/LinearExecutable/ObjectPageMapEntry.cs b/SabreTools.Serialization/Models/LinearExecutable/ObjectPageMapEntry.cs new file mode 100644 index 00000000..3e3076db --- /dev/null +++ b/SabreTools.Serialization/Models/LinearExecutable/ObjectPageMapEntry.cs @@ -0,0 +1,61 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.LinearExecutable +{ + /// + /// The Object page table provides information about a logical page in an object. + /// A logical page may be an enumerated page, a pseudo page or an iterated page. + /// The structure of the object page table in conjunction with the structure of + /// the object table allows for efficient access of a page when a page fault occurs, + /// while still allowing the physical page data to be located in the preload page, + /// demand load page or iterated data page sections in the linear EXE module. The + /// logical page entries in the Object Page Table are numbered starting from one. + /// The Object Page Table is parallel to the Fixup Page Table as they are both + /// indexed by the logical page number. + /// + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class ObjectPageMapEntry + { + /// + /// Offset to the page data in the EXE file. + /// + /// + /// This field, when bit shifted left by the PAGE OFFSET SHIFT from the module + /// header, specifies the offset from the beginning of the Preload Page section + /// of the physical page data in the EXE file that corresponds to this logical + /// page entry. The page data may reside in the Preload Pages, Demand Load Pages + /// or the Iterated Data Pages sections. + /// + /// If the FLAGS field specifies that this is a zero-Filled page then the PAGE + /// DATA OFFSET field will contain a 0. + /// + /// If the logical page is specified as an iterated data page, as indicated by + /// the FLAGS field, then this field specifies the offset into the Iterated Data + /// Pages section. + /// + /// The logical page number (Object Page Table index), is used to index the Fixup + /// Page Table to find any fixups associated with the logical page. + /// + public uint PageDataOffset; + + /// + /// Number of bytes of data for this page. + /// + /// + /// This field specifies the actual number of bytes that represent the page in the + /// file. If the PAGE SIZE field from the module header is greater than the value + /// of this field and the FLAGS field indicates a Legal Physical Page, the remaining + /// bytes are to be filled with zeros. If the FLAGS field indicates an Iterated Data + /// Page, the iterated data records will completely fill out the remainder. + /// + public ushort DataSize; + + /// + /// Attributes specifying characteristics of this logical page. + /// + [MarshalAs(UnmanagedType.U2)] + public ObjectPageFlags Flags; + } +} diff --git a/SabreTools.Serialization/Models/LinearExecutable/ObjectTableEntry.cs b/SabreTools.Serialization/Models/LinearExecutable/ObjectTableEntry.cs new file mode 100644 index 00000000..74226357 --- /dev/null +++ b/SabreTools.Serialization/Models/LinearExecutable/ObjectTableEntry.cs @@ -0,0 +1,83 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.LinearExecutable +{ + /// + /// The object table contains information that describes each segment in + /// an executable file. This information includes segment length, segment + /// type, and segment-relocation data. The following list summarizes the + /// values found in in the segment table (the locations are relative to + /// the beginning of each entry): + /// + /// + /// Entries in the Object Table are numbered starting from one. + /// + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class ObjectTableEntry + { + /// + /// Virtual memory size. + /// + /// + /// This is the size of the object that will be allocated when the object + /// is loaded. The object's virtual size (rounded up to the page size value) + /// must be greater than or equal to the total size of the pages in the EXE + /// file for the object. This memory size must also be large enough to + /// contain all of the iterated data and uninitialized data in the EXE file. + /// + public uint VirtualSegmentSize; + + /// + /// Relocation Base Address. + /// + /// + /// The relocation base address the object is currently relocated to. If the + /// internal relocation fixups for the module have been removed, this is the + /// address the object will be allocated at by the loader. + /// + public uint RelocationBaseAddress; + + /// + /// Flag bits for the object. + /// + [MarshalAs(UnmanagedType.U2)] + public ObjectFlags ObjectFlags; + + /// + /// Object Page Table Index. + /// + /// + /// This specifies the number of the first object page table entry for this object. + /// The object page table specifies where in the EXE file a page can be found for + /// a given object and specifies per-page attributes. + /// + /// The object table entries are ordered by logical page in the object table. In + /// other words the object table entries are sorted based on the object page table + /// index value. + /// + public uint PageTableIndex; + + /// + /// # of object page table entries for this object. + /// + /// + /// Any logical pages at the end of an object that do not have an entry in the object + /// page table associated with them are handled as zero filled or invalid pages by + /// the loader. + /// + /// When the last logical pages of an object are not specified with an object page + /// table entry, they are treated as either zero filled pages or invalid pages based + /// on the last entry in the object page table for that object. If the last entry + /// was neither a zero filled or invalid page, then the additional pages are treated + /// as zero filled pages. + /// + public uint PageTableEntries; + + /// + /// Reserved for future use. Must be set to zero. + /// + public uint Reserved; + } +} diff --git a/SabreTools.Serialization/Models/LinearExecutable/PerPageChecksumTableEntry.cs b/SabreTools.Serialization/Models/LinearExecutable/PerPageChecksumTableEntry.cs new file mode 100644 index 00000000..89fac5fe --- /dev/null +++ b/SabreTools.Serialization/Models/LinearExecutable/PerPageChecksumTableEntry.cs @@ -0,0 +1,24 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.LinearExecutable +{ + /// + /// The Per-Page Checksum table provides space for a cryptographic checksum for + /// each physical page in the EXE file. + /// + /// The checksum table is arranged such that the first entry in the table corresponds + /// to the first logical page of code/data in the EXE file (usually a preload page) + /// and the last entry corresponds to the last logical page in the EXE file (usually + /// a iterated data page). + /// + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class PerPageChecksumTableEntry + { + /// + /// Cryptographic checksum. + /// + public uint Checksum; + } +} diff --git a/SabreTools.Serialization/Models/LinearExecutable/ResidentNamesTableEntry.cs b/SabreTools.Serialization/Models/LinearExecutable/ResidentNamesTableEntry.cs new file mode 100644 index 00000000..955796b1 --- /dev/null +++ b/SabreTools.Serialization/Models/LinearExecutable/ResidentNamesTableEntry.cs @@ -0,0 +1,61 @@ +namespace SabreTools.Serialization.Models.LinearExecutable +{ + /// + /// The resident and non-resident name tables define the ASCII names and ordinal + /// numbers for exported entries in the module. In addition the first entry in + /// the resident name table contains the module name. These tables are used to + /// translate a procedure name string into an ordinal number by searching for a + /// matching name string. The ordinal number is used to locate the entry point + /// information in the entry table. + /// + /// The resident name table is kept resident in system memory while the module is + /// loaded. It is intended to contain the exported entry point names that are + /// frequently dynamically linked to by name. Non-resident names are not kept in + /// memory and are read from the EXE file when a dynamic link reference is made. + /// Exported entry point names that are infrequently dynamically linked to by name + /// or are commonly referenced by ordinal number should be placed in the + /// non-resident name table. The trade off made for references by name is performance + /// vs memory usage. + /// + /// Import references by name require these tables to be searched to obtain the entry + /// point ordinal number.Import references by ordinal number provide the fastest + /// lookup since the search of these tables is not required. + /// + /// The strings are CASE SENSITIVE and are NOT NULL TERMINATED. + /// + /// + /// + public sealed class ResidentNamesTableEntry + { + /// + /// String Length. + /// + /// + /// This defines the length of the string in bytes. A zero length indicates there are + /// no more entries in table. The length of each ascii name string is limited to 127 + /// characters. + /// + /// The high bit in the LEN field (bit 7) is defined as an Overload bit. This bit + /// signifies that additional information is contained in the linear EXE module and + /// will be used in the future for parameter type checking. + /// + public byte Length { get; set; } // TODO: Remove in lieu of AnsiBStr + + /// + /// ASCII String. + /// + /// + /// This is a variable length string with it's length defined in bytes by the LEN field. + /// The string is case case sensitive and is not null terminated. + /// + public string? Name { get; set; } + + /// + /// Ordinal number. + /// + /// + /// The ordinal number in an ordered index into the entry table for this entry point. + /// + public ushort OrdinalNumber { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/LinearExecutable/ResourceTableEntry.cs b/SabreTools.Serialization/Models/LinearExecutable/ResourceTableEntry.cs new file mode 100644 index 00000000..714a8a14 --- /dev/null +++ b/SabreTools.Serialization/Models/LinearExecutable/ResourceTableEntry.cs @@ -0,0 +1,47 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.LinearExecutable +{ + /// + /// The resource table is an array of resource table entries. Each resource table + /// entry contains a type ID and name ID. These entries are used to locate resource + /// objects contained in the Object table. The number of entries in the resource + /// table is defined by the Resource Table Count located in the linear EXE header. + /// More than one resource may be contained within a single object. Resource table + /// entries are in a sorted order, (ascending, by Resource Name ID within the + /// Resource Type ID). This allows the DosGetResource API function to use a binary + /// search when looking up a resource in a 32-bit module instead of the linear search + /// being used in the current 16-bit module. + /// + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class ResourceTableEntry + { + /// + /// Resource type ID. + /// + [MarshalAs(UnmanagedType.U4)] + public ResourceTableEntryType TypeID; + + /// + /// An ID used as a name for the resource when referred to. + /// + public ushort NameID; + + /// + /// The number of bytes the resource consists of. + /// + public uint ResourceSize; + + /// + /// The number of the object which contains the resource. + /// + public ushort ObjectNumber; + + /// + /// The offset within the specified object where the resource begins. + /// + public uint Offset; + } +} diff --git a/SabreTools.Serialization/Models/LinearExecutable/VerifyRecordDirectiveTableEntry.cs b/SabreTools.Serialization/Models/LinearExecutable/VerifyRecordDirectiveTableEntry.cs new file mode 100644 index 00000000..7546c128 --- /dev/null +++ b/SabreTools.Serialization/Models/LinearExecutable/VerifyRecordDirectiveTableEntry.cs @@ -0,0 +1,85 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.LinearExecutable +{ + /// + /// The Verify Record Directive Table is an optional table. It maintains a record + /// of the pages in the EXE file that have been fixed up and written back to the + /// original linear EXE module, along with the module dependencies used to perform + /// these fixups. This table provides an efficient means for verifying the virtual + /// addresses required for the fixed up pages when the module is loaded. + /// + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class VerifyRecordDirectiveTableEntry + { + /// + /// Number of module dependencies. + /// + /// + /// This field specifies how many entries there are in the verify record + /// directive table. This is equal to the number of modules referenced by + /// this module. + /// + public ushort EntryCount; + + /// + /// Ordinal index into the Import Module Name Table. + /// + /// + /// This value is an ordered index in to the Import Module Name Table for + /// the referenced module. + /// + public ushort OrdinalIndex; + + /// + /// Module Version. + /// + /// + /// This is the version of the referenced module that the fixups were + /// originally performed.This is used to insure the same version of the + /// referenced module is loaded that was fixed up in this module and + /// therefore the fixups are still correct. This requires the version + /// number in a module to be incremented anytime the entry point offsets + /// change. + /// + public ushort Version; + + /// + /// Module # of Object Entries. + /// + /// + /// This field is used to identify the number of object verify entries + /// that follow for the referenced module. + /// + public ushort ObjectEntriesCount; + + /// + /// Object # in Module. + /// + /// + /// This field specifies the object number in the referenced module that + /// is being verified. + /// + public ushort ObjectNumberInModule; + + /// + /// Object load base address. + /// + /// + /// This is the address that the object was loaded at when the fixups were + /// performed. + /// + public ushort ObjectLoadBaseAddress; + + /// + /// Object virtual address size. + /// + /// + /// This field specifies the total amount of virtual memory required for + /// this object. + /// + public ushort ObjectVirtualAddressSize; + } +} diff --git a/SabreTools.Serialization/Models/MSDOS/Constants.cs b/SabreTools.Serialization/Models/MSDOS/Constants.cs new file mode 100644 index 00000000..c20d9d54 --- /dev/null +++ b/SabreTools.Serialization/Models/MSDOS/Constants.cs @@ -0,0 +1,11 @@ +namespace SabreTools.Serialization.Models.MSDOS +{ + public static class Constants + { + public static readonly byte[] SignatureBytes = [0x4d, 0x5a]; + + public const string SignatureString = "MZ"; + + public const ushort SignatureUInt16 = 0x5a4d; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/MSDOS/Executable.cs b/SabreTools.Serialization/Models/MSDOS/Executable.cs new file mode 100644 index 00000000..3a2bd3dc --- /dev/null +++ b/SabreTools.Serialization/Models/MSDOS/Executable.cs @@ -0,0 +1,29 @@ +namespace SabreTools.Serialization.Models.MSDOS +{ + /// + /// The MS-DOS EXE format, also known as MZ after its signature (the initials of Microsoft engineer Mark Zbykowski), + /// was introduced with MS-DOS 2.0 (version 1.0 only sported the simple COM format). It is designed as a relocatable + /// executable running under real mode. As such, only DOS and Windows 9x can use this format natively, but there are + /// several free DOS emulators (e.g., DOSBox) that support it and that run under various operating systems (e.g., + /// Linux, Amiga, Windows NT, etc.). Although they can exist on their own, MZ executables are embedded in all NE, LE, + /// and PE executables, usually as stubs so that when they are ran under DOS, they display a warning. + /// + /// + public sealed class Executable + { + /// + /// MS-DOS executable header + /// + public ExecutableHeader? Header { get; set; } + + /// + /// After loading the executable into memory, the program loader goes through + /// every entry in relocation table. For each relocation entry, the loader + /// adds the start segment address into word value pointed to by the + /// segment:offset pair. So, for example, a relocation entry 0001:001A will + /// make the loader add start segment address to the value at offset + /// 1*0x10+0x1A=0x2A within the program data. + /// + public RelocationEntry[]? RelocationTable { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/MSDOS/ExecutableHeader.cs b/SabreTools.Serialization/Models/MSDOS/ExecutableHeader.cs new file mode 100644 index 00000000..3ff62962 --- /dev/null +++ b/SabreTools.Serialization/Models/MSDOS/ExecutableHeader.cs @@ -0,0 +1,133 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.MSDOS +{ + /// + /// MZ executables only consists of 2 structures: the header and the relocation table. + /// The header, which is followed by the program image, looks like this. + /// + /// + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public sealed class ExecutableHeader + { + #region Standard Fields + + /// + /// 0x5A4D (ASCII for 'M' and 'Z') + /// + /// 15 bytes + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 2)] + public string? Magic; + + /// + /// Number of bytes in the last page. + /// + public ushort LastPageBytes; + + /// + /// Number of whole/partial pages. + /// + /// A page (or block) is 512 bytes long. + public ushort Pages; + + /// + /// Number of entries in the relocation table. + /// + public ushort RelocationItems; + + /// + /// The number of paragraphs taken up by the header. It can be any value, as the loader + /// just uses it to find where the actual executable data starts. It may be larger than + /// what the "standard" fields take up, and you may use it if you want to include your + /// own header metadata, or put the relocation table there, or use it for any other purpose. [08] + /// + /// A paragraph is 16 bytes in size + public ushort HeaderParagraphSize; + + /// + /// The number of paragraphs required by the program, excluding the PSP and program image. + /// If no free block is big enough, the loading stops. + /// + /// A paragraph is 16 bytes in size + public ushort MinimumExtraParagraphs; + + /// + /// The number of paragraphs requested by the program. + /// If no free block is big enough, the biggest one possible is allocated. + /// + /// A paragraph is 16 bytes in size + public ushort MaximumExtraParagraphs; + + /// + /// Relocatable segment address for SS. + /// + public ushort InitialSSValue; + + /// + /// Initial value for SP. + /// + public ushort InitialSPValue; + + /// + /// When added to the sum of all other words in the file, the result should be zero. + /// + public ushort Checksum; + + /// + /// Initial value for IP. [14] + /// + public ushort InitialIPValue; + + /// + /// Relocatable segment address for CS. + /// + public ushort InitialCSValue; + + /// + /// The (absolute) offset to the relocation table. + /// + public ushort RelocationTableAddr; + + /// + /// Value used for overlay management. + /// If zero, this is the main executable. + /// + public ushort OverlayNumber; + + #endregion + + #region PE Extensions + + /// + /// Reserved words + /// + /// 4 entries/remarks> + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public ushort[]? Reserved1; + + /// + /// Defined by name but no other information is given; typically zeroes + /// + public ushort OEMIdentifier; + + /// + /// Defined by name but no other information is given; typically zeroes + /// + public ushort OEMInformation; + + /// + /// Reserved words + /// + /// 10 entries/remarks> + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] + public ushort[]? Reserved2; + + /// + /// Starting address of the PE header + /// + public uint NewExeHeaderAddr; + + #endregion + } +} diff --git a/SabreTools.Serialization/Models/MSDOS/RelocationEntry.cs b/SabreTools.Serialization/Models/MSDOS/RelocationEntry.cs new file mode 100644 index 00000000..82d9625e --- /dev/null +++ b/SabreTools.Serialization/Models/MSDOS/RelocationEntry.cs @@ -0,0 +1,22 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.MSDOS +{ + /// + /// Each pointer in the relocation table looks as such + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class RelocationEntry + { + /// + /// Offset of the relocation within provided segment. + /// + public ushort Offset; + + /// + /// Segment of the relocation, relative to the load segment address. + /// + public ushort Segment; + } +} diff --git a/SabreTools.Serialization/Models/NewExecutable/Constants.cs b/SabreTools.Serialization/Models/NewExecutable/Constants.cs new file mode 100644 index 00000000..5684d231 --- /dev/null +++ b/SabreTools.Serialization/Models/NewExecutable/Constants.cs @@ -0,0 +1,11 @@ +namespace SabreTools.Serialization.Models.NewExecutable +{ + public static class Constants + { + public static readonly byte[] SignatureBytes = [0x4e, 0x45]; + + public const string SignatureString = "NE"; + + public const ushort SignatureUInt16 = 0x454e; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/NewExecutable/EntryTableBundle.cs b/SabreTools.Serialization/Models/NewExecutable/EntryTableBundle.cs new file mode 100644 index 00000000..c779d56c --- /dev/null +++ b/SabreTools.Serialization/Models/NewExecutable/EntryTableBundle.cs @@ -0,0 +1,84 @@ +namespace SabreTools.Serialization.Models.NewExecutable +{ + /// + /// The entry table follows the imported-name table. This table contains + /// bundles of entry-point definitions. Bundling is done to save space in + /// the entry table. The entry table is accessed by an ordinal value. + /// Ordinal number one is defined to index the first entry in the entry + /// table. To find an entry point, the bundles are scanned searching for a + /// specific entry point using an ordinal number. The ordinal number is + /// adjusted as each bundle is checked. When the bundle that contains the + /// entry point is found, the ordinal number is multiplied by the size of + /// the bundle's entries to index the proper entry. + /// + /// + /// The linker forms bundles in the most dense manner it can, under the + /// restriction that it cannot reorder entry points to improve bundling. + /// The reason for this restriction is that other .EXE files may refer to + /// entry points within this bundle by their ordinal number. The following + /// describes the format of the entry table bundles. + /// + /// + public sealed class EntryTableBundle + { + /// + /// Number of entries in this bundle. All records in one bundle + /// are either moveable or refer to the same fixed segment. A zero + /// value in this field indicates the end of the entry table. + /// + public byte EntryCount { get; set; } + + /// + /// Segment indicator for this bundle. This defines the type of + /// entry table entry data within the bundle. There are three + /// types of entries that are defined. + /// - 000h = Unused entries. There is no entry data in an unused + /// bundle. The next bundle follows this field. This is + /// used by the linker to skip ordinal numbers. + /// - 001h-0FEh = Segment number for fixed segment entries. A fixed + /// segment entry is 3 bytes long. + /// - 0FFH = Moveable segment entries. The entry data contains the + /// segment number for the entry points. A moveable segment + /// entry is 6 bytes long. + /// + public byte SegmentIndicator { get; set; } + + #region Fixed Segment Entry + + /// + /// Flag word. + /// + public FixedSegmentEntryFlag FixedFlagWord { get; set; } + + /// + /// Offset within segment to entry point. + /// + public ushort FixedOffset { get; set; } + + #endregion + + #region Moveable Segment Entry + + /// + /// Flag word. + /// + public MoveableSegmentEntryFlag MoveableFlagWord { get; set; } + + /// + /// INT 3FH. + /// + public ushort MoveableReserved { get; set; } + + /// + /// Segment number. + /// + public byte MoveableSegmentNumber { get; set; } + + /// + /// Offset within segment to entry point. + /// + public ushort MoveableOffset { get; set; } + + #endregion + } +} diff --git a/SabreTools.Serialization/Models/NewExecutable/Enums.cs b/SabreTools.Serialization/Models/NewExecutable/Enums.cs new file mode 100644 index 00000000..bfb2ec1d --- /dev/null +++ b/SabreTools.Serialization/Models/NewExecutable/Enums.cs @@ -0,0 +1,325 @@ +using System; + +namespace SabreTools.Serialization.Models.NewExecutable +{ + [Flags] + public enum FixedSegmentEntryFlag : byte + { + /// + /// Set if the entry is exported. + /// + Exported = 0x01, + + /// + /// Set if the entry uses a global (shared) data segments. + /// + /// + /// The first assembly-language instruction in the + /// entry point prologue must be "MOV AX,data + /// segment number". This may be set only for + /// SINGLEDATA library modules. + /// + Global = 0x02, + } + + [Flags] + public enum HeaderFlag : ushort + { + #region Program Flags + + NOAUTODATA = 0x0000, + + /// + /// Shared automatic data segment + /// + SINGLEDATA = 0x0001, + + /// + /// Instanced automatic data segment + /// + MULTIPLEDATA = 0x0002, + + /// + /// Global initialization + /// + GlobalInitialization = 0x0004, + + /// + /// Protected mode only + /// + ProtectedModeOnly = 0x0008, + + /// + /// 8086 instructions + /// + Instructions8086 = 0x0010, + + /// + /// 80286 instructions + /// + Instructions80286 = 0x0020, + + /// + /// 80386 instructions + /// + Instructions80386 = 0x0040, + + /// + /// 80x87 instructions + /// + Instructions80x87 = 0x0080, + + #endregion + + #region Application Flags + + /// + /// Full screen (not aware of Windows/P.M. API) + /// + FullScreen = 0x0100, + + /// + /// Compatible with Windows/P.M. API + /// + WindowsPMCompatible = 0x0200, + + /// + /// Uses Windows/P.M. API + /// + WindowsPM = 0x0400, + + /// + /// OS/2 family application + /// + OS2FamilyApplication = 0x0800, + + /// + /// Unknown (Reserved?) + /// + UnknownReserved = 0x1000, + + /// + /// Errors detected at link time, module will not load + /// + ErrorsDetectedAtLinkTime = 0x2000, + + /// + /// Unknown (non-conforming program) + /// + UnknownNonConforming = 0x4000, + + /// + /// Library module. + /// The SS:SP information is invalid, CS:IP points + /// to an initialization procedure that is called + /// with AX equal to the module handle. This + /// initialization procedure must perform a far + /// return to the caller, with AX not equal to + /// zero to indicate success, or AX equal to zero + /// to indicate failure to initialize. DS is set + /// to the library's data segment if the + /// SINGLEDATA flag is set. Otherwise, DS is set + /// to the caller's data segment. + /// + /// + /// A program or DLL can only contain dynamic + /// links to executable files that have this + /// library module flag set. One program cannot + /// dynamic-link to another program. + /// + LibraryModule = 0x8000, + + #endregion + } + + [Flags] + public enum MoveableSegmentEntryFlag : byte + { + /// + /// Set if the entry is exported. + /// + Exported = 0x01, + + /// + /// Set if the entry uses a global (shared) data segments. + /// + Global = 0x02, + } + + public enum OperatingSystem : byte + { + Unknown = 0x00, + OS2 = 0x01, + WINDOWS = 0x02, + EU_MSDOS4 = 0x03, + WINDOWS_386 = 0x04, + BOSS = 0x05, + } + + [Flags] + public enum OS2Flag : byte + { + /// + /// Long filename support + /// + LongFilenameSupport = 0x01, + + /// + /// 2.x protected mode + /// + ProtectedMode = 0x02, + + /// + /// 2.x proportional fonts + /// + ProportionalFonts = 0x04, + + /// + /// Executable has gangload area + /// + HasGangload = 0x08, + + /// + /// Unknown + /// + Unknown = 0xF0, + } + + public enum OSFixupType : ushort + { + /// + /// FIARQQ, FJARQQ + /// + FIARQQ = 0x0001, + + /// + /// FISRQQ, FJSRQQ + /// + FISRQQ = 0x0002, + + /// + /// FICRQQ, FJCRQQ + /// + FICRQQ = 0x0003, + + FIERQQ = 0x0004, + + FIDRQQ = 0x0005, + + FIWRQQ = 0x0006, + } + + [Flags] + public enum RelocationRecordFlag : byte + { + TARGET_MASK = 0x03, + + INTERNALREF = 0x00, + + IMPORTORDINAL = 0x01, + + IMPORTNAME = 0x02, + + OSFIXUP = 0x03, + + ADDITIVE = 0x04, + } + + public enum RelocationRecordSourceType : byte + { + SOURCE_MASK = 0x0F, + + LOBYTE = 0x00, + + SEGMENT = 0x02, + + /// + /// 32-bit pointer + /// + FAR_ADDR = 0x03, + + /// + /// 16-bit offset + /// + OFFSET = 0x05, + } + + [Flags] + public enum ResourceTypeResourceFlag : ushort + { + /// + /// Resource is not fixed. + /// + MOVEABLE = 0x0010, + + /// + /// Resource can be shared. + /// + PURE = 0x0020, + + /// + /// Resource is preloaded. + /// + PRELOAD = 0x0040, + } + + public enum SegmentEntryType + { + /// + /// 000h - There is no entry data in an unused bundle. The next bundle + /// follows this field. This is used by the linker to skip ordinal numbers. + /// + Unused, + + /// + /// 001h-0FEh - Segment number for fixed segment entries. A fixed segment + /// entry is 3 bytes long. + /// + FixedSegment, + + /// + /// 0FFH - Moveable segment entries. The entry data contains the segment + /// number for the entry points. A moveable segment entry is 6 bytes long. + /// + MoveableSegment, + } + + [Flags] + public enum SegmentTableEntryFlag : ushort + { + /// + /// Segment-type field. + /// + TYPE_MASK = 0x0007, + + /// + /// Code-segment type. + /// + CODE = 0x0000, + + /// + /// Data-segment type. + /// + DATA = 0x0001, + + /// + /// Segment is not fixed. + /// + MOVEABLE = 0x0010, + + /// + /// Segment will be preloaded; read-only if this is a data segment. + /// + PRELOAD = 0x0040, + + /// + /// Set if segment has relocation records. + /// + RELOCINFO = 0x0100, + + /// + /// Discard priority. + /// + DISCARD = 0xF000, + } +} diff --git a/SabreTools.Serialization/Models/NewExecutable/Executable.cs b/SabreTools.Serialization/Models/NewExecutable/Executable.cs new file mode 100644 index 00000000..4ae94ee1 --- /dev/null +++ b/SabreTools.Serialization/Models/NewExecutable/Executable.cs @@ -0,0 +1,67 @@ +using System.Collections.Generic; + +namespace SabreTools.Serialization.Models.NewExecutable +{ + /// + /// The segmented EXE header contains general information about the EXE + /// file and contains information on the location and size of the other + /// sections. The Windows loader copies this section, along with other + /// data, into the module table in the system data. The module table is + /// internal data used by the loader to manage the loaded executable + /// modules in the system and to support dynamic linking. + /// + /// + /// + public sealed class Executable + { + /// + /// MS-DOS executable stub + /// + public MSDOS.Executable? Stub { get; set; } + + /// + /// New Executable header + /// + public ExecutableHeader? Header { get; set; } + + /// + /// Segment table + /// + public SegmentTableEntry[]? SegmentTable { get; set; } + + /// + /// Resource table + /// + public ResourceTable? ResourceTable { get; set; } + + /// + /// Resident-Name table + /// + public ResidentNameTableEntry[]? ResidentNameTable { get; set; } + + /// + /// Module-Reference table + /// + public ModuleReferenceTableEntry[]? ModuleReferenceTable { get; set; } + + /// + /// Imported-Name table + /// + public Dictionary? ImportedNameTable { get; set; } + + /// + /// Entry table + /// + public EntryTableBundle[]? EntryTable { get; set; } + + /// + /// Nonresident-Name table + /// + public NonResidentNameTableEntry[]? NonResidentNameTable { get; set; } + + /// + /// Segment relocation data + /// + public PerSegmentData[]? SegmentRelocationData { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/NewExecutable/ExecutableHeader.cs b/SabreTools.Serialization/Models/NewExecutable/ExecutableHeader.cs new file mode 100644 index 00000000..fecca6c1 --- /dev/null +++ b/SabreTools.Serialization/Models/NewExecutable/ExecutableHeader.cs @@ -0,0 +1,209 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.NewExecutable +{ + /// + /// The NE header is a relatively large structure with multiple characteristics. + /// Because of the age of the format some items are unclear in meaning. + /// + /// + /// + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public sealed class ExecutableHeader + { + /// + /// "NE" + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 2)] + public string? Magic; + + /// + /// Version number of the linker. + /// + /// Also known as the major linker version + public byte LinkerVersion; + + /// + /// Revision number of the linker. + /// + /// Also known as the minor linker version + public byte LinkerRevision; + + /// + /// Entry Table file offset, relative to the beginning of the segmented EXE header. + /// + public ushort EntryTableOffset; + + /// + /// Length of entry table in bytes + /// + public ushort EntryTableSize; + + /// + /// 32-bit CRC of entire contents of file. + /// + /// These words are taken as 00 during the calculation. + public uint CrcChecksum; + + /// + /// Flag word + /// + [MarshalAs(UnmanagedType.U2)] + public HeaderFlag FlagWord; + + /// + /// Segment number of automatic data segment. + /// This value is set to zero if SINGLEDATA and + /// MULTIPLEDATA flag bits are clear, NOAUTODATA is + /// indicated in the flags word. + /// + /// + /// A Segment number is an index into the module's segment + /// table. The first entry in the segment table is segment + /// number 1. + /// + public ushort AutomaticDataSegmentNumber; + + /// + /// Initial size, in bytes, of dynamic heap added to the + /// data segment. This value is zero if no initial local + /// heap is allocated. + /// + public ushort InitialHeapAlloc; + + /// + /// Initial size, in bytes, of stack added to the data + /// segment. This value is zero to indicate no initial + /// stack allocation, or when SS is not equal to DS. + /// + public ushort InitialStackAlloc; + + /// + /// Segment number:offset of CS:IP. + /// + /// CS:IP entry point, CS is index into segment table + public uint InitialCSIPSetting; + + /// + /// Segment number:offset of SS:SP. + /// + /// + /// SS:SP initial stack pointer, SS is index into segment table + /// + /// If SS equals the automatic data segment and SP equals + /// zero, the stack pointer is set to the top of the + /// automatic data segment just below the additional heap + /// area. + /// + public uint InitialSSSPSetting; + + /// + /// Number of entries in the Segment Table. + /// + public ushort FileSegmentCount; + + /// + /// Number of entries in the Module Reference Table. + /// + public ushort ModuleReferenceTableSize; + + /// + /// Size of non-resident names table in bytes + /// + public ushort NonResidentNameTableSize; + + /// + /// Segment Table file offset, relative to the beginning + /// of the segmented EXE header. + /// + public ushort SegmentTableOffset; + + /// + /// Resource Table file offset, relative to the beginning + /// of the segmented EXE header. + /// + public ushort ResourceTableOffset; + + /// + /// Resident Name Table file offset, relative to the + /// beginning of the segmented EXE header. + /// + public ushort ResidentNameTableOffset; + + /// + /// Module Reference Table file offset, relative to the + /// beginning of the segmented EXE header. + /// + public ushort ModuleReferenceTableOffset; + + /// + /// Imported Names Table file offset, relative to the + /// beginning of the segmented EXE header. + /// + public ushort ImportedNamesTableOffset; + + /// + /// Non-Resident Name Table offset, relative to the + /// beginning of the file. + /// + public uint NonResidentNamesTableOffset; + + /// + /// Number of movable entries in the Entry Table. + /// + public ushort MovableEntriesCount; + + /// + /// Logical sector alignment shift count, log(base 2) of + /// the segment sector size (default 9). + /// + public ushort SegmentAlignmentShiftCount; + + /// + /// Number of resource entries. + /// + public ushort ResourceEntriesCount; + + /// + /// Executable type, used by loader. + /// + [MarshalAs(UnmanagedType.U1)] + public OperatingSystem TargetOperatingSystem; + + #region OS/2 Specific + + /// + /// Other OS/2 flags + /// + [MarshalAs(UnmanagedType.U1)] + public OS2Flag AdditionalFlags; + + /// + /// Offset to return thunks or start of gangload area + /// + public ushort ReturnThunkOffset; + + /// + /// Offset to segment reference thunks or size of gangload area + /// + public ushort SegmentReferenceThunkOffset; + + /// + /// Minimum code swap area size + /// + public ushort MinCodeSwapAreaSize; + + /// + /// Windows SDK revison number + /// + public byte WindowsSDKRevision; + + /// + /// Windows SDK version number + /// + public byte WindowsSDKVersion; + + #endregion + } +} diff --git a/SabreTools.Serialization/Models/NewExecutable/ImportNameRelocationRecord.cs b/SabreTools.Serialization/Models/NewExecutable/ImportNameRelocationRecord.cs new file mode 100644 index 00000000..8b915bef --- /dev/null +++ b/SabreTools.Serialization/Models/NewExecutable/ImportNameRelocationRecord.cs @@ -0,0 +1,19 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.NewExecutable +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class ImportNameRelocationRecord + { + /// + /// Index into module reference table for the imported module. + /// + public ushort Index; + + /// + /// Offset within Imported Names Table to procedure name string. + /// + public ushort Offset; + } +} diff --git a/SabreTools.Serialization/Models/NewExecutable/ImportOrdinalRelocationRecord.cs b/SabreTools.Serialization/Models/NewExecutable/ImportOrdinalRelocationRecord.cs new file mode 100644 index 00000000..03054078 --- /dev/null +++ b/SabreTools.Serialization/Models/NewExecutable/ImportOrdinalRelocationRecord.cs @@ -0,0 +1,19 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.NewExecutable +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class ImportOrdinalRelocationRecord + { + /// + /// Index into module reference table for the imported module. + /// + public ushort Index; + + /// + /// Procedure ordinal number. + /// + public ushort Ordinal; + } +} diff --git a/SabreTools.Serialization/Models/NewExecutable/ImportedNameTableEntry.cs b/SabreTools.Serialization/Models/NewExecutable/ImportedNameTableEntry.cs new file mode 100644 index 00000000..22d0d18c --- /dev/null +++ b/SabreTools.Serialization/Models/NewExecutable/ImportedNameTableEntry.cs @@ -0,0 +1,25 @@ +namespace SabreTools.Serialization.Models.NewExecutable +{ + /// + /// The imported-name table follows the module-reference table. This table + /// contains the names of modules and procedures that are imported by the + /// executable file. Each entry is composed of a 1-byte field that + /// contains the length of the string, followed by any number of + /// characters. The strings are not null-terminated and are case + /// sensitive. + /// + /// + public sealed class ImportedNameTableEntry + { + /// + /// Length of the name string that follows. A zero value indicates + /// the end of the name table. + /// + public byte Length { get; set; } // TODO: Remove in lieu of AnsiBStr + + /// + /// ASCII text of the name string. + /// + public byte[]? NameString { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/NewExecutable/InternalRefRelocationRecord.cs b/SabreTools.Serialization/Models/NewExecutable/InternalRefRelocationRecord.cs new file mode 100644 index 00000000..33501eae --- /dev/null +++ b/SabreTools.Serialization/Models/NewExecutable/InternalRefRelocationRecord.cs @@ -0,0 +1,26 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.NewExecutable +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class InternalRefRelocationRecord + { + /// + /// Segment number for a fixed segment, or 0FFh for a + /// movable segment. + /// + public byte SegmentNumber; + + /// + /// Always 0 + /// + public byte Reserved; + + /// + /// Offset into segment if fixed segment, or ordinal + /// number index into Entry Table if movable segment. + /// + public ushort Offset; + } +} diff --git a/SabreTools.Serialization/Models/NewExecutable/ModuleReferenceTableEntry.cs b/SabreTools.Serialization/Models/NewExecutable/ModuleReferenceTableEntry.cs new file mode 100644 index 00000000..be15e73d --- /dev/null +++ b/SabreTools.Serialization/Models/NewExecutable/ModuleReferenceTableEntry.cs @@ -0,0 +1,19 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.NewExecutable +{ + /// + /// The module-reference table follows the resident-name table. Each entry + /// contains an offset for the module-name string within the imported- + /// names table; each entry is 2 bytes long. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class ModuleReferenceTableEntry + { + /// + /// Offset within Imported Names Table to referenced module name string. + /// + public ushort Offset; + } +} diff --git a/SabreTools.Serialization/Models/NewExecutable/NonResidentNameTableEntry.cs b/SabreTools.Serialization/Models/NewExecutable/NonResidentNameTableEntry.cs new file mode 100644 index 00000000..89ffd4e6 --- /dev/null +++ b/SabreTools.Serialization/Models/NewExecutable/NonResidentNameTableEntry.cs @@ -0,0 +1,31 @@ +namespace SabreTools.Serialization.Models.NewExecutable +{ + /// + /// The nonresident-name table follows the entry table, and contains a + /// module description and nonresident exported procedure name strings. + /// The first string in this table is a module description. These name + /// strings are case-sensitive and are not null-terminated. The name + /// strings follow the same format as those defined in the resident name + /// table. + /// + /// + public sealed class NonResidentNameTableEntry + { + /// + /// Length of the name string that follows. A zero value indicates + /// the end of the name table. + /// + public byte Length { get; set; } // TODO: Remove in lieu of AnsiBStr + + /// + /// ASCII text of the name string. + /// + public byte[]? NameString { get; set; } + + /// + /// Ordinal number (index into entry table). This value is ignored + /// for the module name. + /// + public ushort OrdinalNumber { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/NewExecutable/OSFixupRelocationRecord.cs b/SabreTools.Serialization/Models/NewExecutable/OSFixupRelocationRecord.cs new file mode 100644 index 00000000..e0105cf6 --- /dev/null +++ b/SabreTools.Serialization/Models/NewExecutable/OSFixupRelocationRecord.cs @@ -0,0 +1,21 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.NewExecutable +{ + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class OSFixupRelocationRecord + { + /// + /// Operating system fixup type. + /// Floating-point fixups. + /// + [MarshalAs(UnmanagedType.U2)] + public OSFixupType FixupType; + + /// + /// 0 + /// + public ushort Reserved; + } +} diff --git a/SabreTools.Serialization/Models/NewExecutable/PerSegmentData.cs b/SabreTools.Serialization/Models/NewExecutable/PerSegmentData.cs new file mode 100644 index 00000000..1ab42db8 --- /dev/null +++ b/SabreTools.Serialization/Models/NewExecutable/PerSegmentData.cs @@ -0,0 +1,30 @@ +namespace SabreTools.Serialization.Models.NewExecutable +{ + /// + /// The location and size of the per-segment data is defined in the + /// segment table entry for the segment. If the segment has relocation + /// fixups, as defined in the segment table entry flags, they directly + /// follow the segment data in the file. The relocation fixup information + /// is defined as follows: + /// + /// + /// To find the relocation data for a segment, seek to: + /// + /// * (1 << ) + /// + + /// + /// + /// + public sealed class PerSegmentData + { + /// + /// Number of relocation records that follow. + /// + public ushort RelocationRecordCount { get; set; } + + /// + /// A table of relocation records follows. + /// + public RelocationRecord[]? RelocationRecords { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/NewExecutable/RelocationRecord.cs b/SabreTools.Serialization/Models/NewExecutable/RelocationRecord.cs new file mode 100644 index 00000000..1f0c6eb3 --- /dev/null +++ b/SabreTools.Serialization/Models/NewExecutable/RelocationRecord.cs @@ -0,0 +1,57 @@ +namespace SabreTools.Serialization.Models.NewExecutable +{ + /// + /// A table of relocation records follows. The following is the format + /// of each relocation record. + /// + /// + public sealed class RelocationRecord + { + /// + /// Source type. + /// + public RelocationRecordSourceType SourceType { get; set; } + + /// + /// Flags byte. + /// + /// The target value has four types that are defined in the flag + /// byte field. + /// + public RelocationRecordFlag Flags { get; set; } + + /// + /// Offset within this segment of the source chain. + /// If the ADDITIVE flag is set, then target value is added to + /// the source contents, instead of replacing the source and + /// following the chain. The source chain is an 0FFFFh + /// terminated linked list within this segment of all + /// references to the target. + /// + public ushort Offset { get; set; } + + /// + /// INTERNALREF + /// + /// Must be null if is not set to + public InternalRefRelocationRecord? InternalRefRelocationRecord { get; set; } + + /// + /// IMPORTNAME + /// + /// Must be null if is not set to + public ImportNameRelocationRecord? ImportNameRelocationRecord { get; set; } + + /// + /// IMPORTORDINAL + /// + /// Must be null if is not set to + public ImportOrdinalRelocationRecord? ImportOrdinalRelocationRecord { get; set; } + + /// + /// IMPORTORDINAL + /// + /// Must be null if is not set to + public OSFixupRelocationRecord? OSFixupRelocationRecord { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/NewExecutable/ResidentNameTableEntry.cs b/SabreTools.Serialization/Models/NewExecutable/ResidentNameTableEntry.cs new file mode 100644 index 00000000..7ba15dc6 --- /dev/null +++ b/SabreTools.Serialization/Models/NewExecutable/ResidentNameTableEntry.cs @@ -0,0 +1,30 @@ +namespace SabreTools.Serialization.Models.NewExecutable +{ + /// + /// The resident-name table follows the resource table, and contains this + /// module's name string and resident exported procedure name strings. The + /// first string in this table is this module's name. These name strings + /// are case-sensitive and are not null-terminated. The following + /// describes the format of the name strings: + /// + /// + public sealed class ResidentNameTableEntry + { + /// + /// Length of the name string that follows. A zero value indicates + /// the end of the name table. + /// + public byte Length { get; set; } // TODO: Remove in lieu of AnsiBStr + + /// + /// ASCII text of the name string. + /// + public byte[]? NameString { get; set; } + + /// + /// Ordinal number (index into entry table). This value is ignored + /// for the module name. + /// + public ushort OrdinalNumber { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/NewExecutable/ResourceTable.cs b/SabreTools.Serialization/Models/NewExecutable/ResourceTable.cs new file mode 100644 index 00000000..c41f18a2 --- /dev/null +++ b/SabreTools.Serialization/Models/NewExecutable/ResourceTable.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; + +namespace SabreTools.Serialization.Models.NewExecutable +{ + /// + /// The resource table follows the segment table and contains entries for + /// each resource in the executable file. The resource table consists of + /// an alignment shift count, followed by a table of resource records. The + /// resource records define the type ID for a set of resources. Each + /// resource record contains a table of resource entries of the defined + /// type. The resource entry defines the resource ID or name ID for the + /// resource. It also defines the location and size of the resource. The + /// following describes the contents of each of these structures: + /// + /// + public sealed class ResourceTable + { + /// + /// Alignment shift count for resource data. + /// + public ushort AlignmentShiftCount { get; set; } + + /// + /// A table of resource type information blocks follows. + /// + public ResourceTypeInformationEntry[]? ResourceTypes { get; set; } + + /// + /// Resource type and name strings are stored at the end of the + /// resource table. + /// + public Dictionary? TypeAndNameStrings { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/NewExecutable/ResourceTypeAndNameString.cs b/SabreTools.Serialization/Models/NewExecutable/ResourceTypeAndNameString.cs new file mode 100644 index 00000000..c321076a --- /dev/null +++ b/SabreTools.Serialization/Models/NewExecutable/ResourceTypeAndNameString.cs @@ -0,0 +1,23 @@ +namespace SabreTools.Serialization.Models.NewExecutable +{ + /// + /// Resource type and name strings are stored at the end of the + /// resource table. Note that these strings are NOT null terminated and + /// are case sensitive. + /// + /// + public sealed class ResourceTypeAndNameString + { + /// + /// Length of the type or name string that follows. A zero value + /// indicates the end of the resource type and name string, also + /// the end of the resource table. + /// + public byte Length { get; set; } // TODO: Remove in lieu of AnsiBStr + + /// + /// ASCII text of the type or name string. + /// + public byte[]? Text { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/NewExecutable/ResourceTypeInformationEntry.cs b/SabreTools.Serialization/Models/NewExecutable/ResourceTypeInformationEntry.cs new file mode 100644 index 00000000..b6f7efa7 --- /dev/null +++ b/SabreTools.Serialization/Models/NewExecutable/ResourceTypeInformationEntry.cs @@ -0,0 +1,34 @@ +namespace SabreTools.Serialization.Models.NewExecutable +{ + /// + /// A table of resource type information blocks follows. The following + /// is the format of each type information block: + /// + /// + public sealed class ResourceTypeInformationEntry + { + /// + /// Type ID. This is an integer type if the high-order bit is + /// set (8000h); otherwise, it is an offset to the type string, + /// the offset is relative to the beginning of the resource + /// table. A zero type ID marks the end of the resource type + /// information blocks. + /// + public ushort TypeID { get; set; } + + /// + /// Number of resources for this type. + /// + public ushort ResourceCount { get; set; } + + /// + /// Reserved. + /// + public uint Reserved { get; set; } + + /// + /// A table of resources for this type follows. + /// + public ResourceTypeResourceEntry[]? Resources { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/NewExecutable/ResourceTypeResourceEntry.cs b/SabreTools.Serialization/Models/NewExecutable/ResourceTypeResourceEntry.cs new file mode 100644 index 00000000..304cb90a --- /dev/null +++ b/SabreTools.Serialization/Models/NewExecutable/ResourceTypeResourceEntry.cs @@ -0,0 +1,48 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.NewExecutable +{ + /// + /// A table of resources for this type follows. The following is + /// the format of each resource (8 bytes each): + /// + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class ResourceTypeResourceEntry + { + /// + /// File offset to the contents of the resource data, + /// relative to beginning of file. The offset is in terms + /// of the alignment shift count value specified at + /// beginning of the resource table. + /// + /// Byte offset is: Offset * (1 << ) + public ushort Offset; + + /// + /// Length of the resource in the file (in bytes). + /// + /// Byte length is: Length * (1 << ) + public ushort Length; + + /// + /// Flag word. + /// + [MarshalAs(UnmanagedType.U2)] + public ResourceTypeResourceFlag FlagWord; + + /// + /// Resource ID. This is an integer type if the high-order + /// bit is set (8000h), otherwise it is the offset to the + /// resource string, the offset is relative to the + /// beginning of the resource table. + /// + public ushort ResourceID; + + /// + /// Reserved. + /// + public uint Reserved; + } +} diff --git a/SabreTools.Serialization/Models/NewExecutable/SegmentTableEntry.cs b/SabreTools.Serialization/Models/NewExecutable/SegmentTableEntry.cs new file mode 100644 index 00000000..ab709d8e --- /dev/null +++ b/SabreTools.Serialization/Models/NewExecutable/SegmentTableEntry.cs @@ -0,0 +1,60 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.NewExecutable +{ + /// + /// The segment table contains an entry for each segment in the executable + /// file. The number of segment table entries are defined in the segmented + /// EXE header. The first entry in the segment table is segment number 1. + /// The following is the structure of a segment table entry. + /// + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class SegmentTableEntry + { + /// + /// Logical-sector offset (n byte) to the contents of the segment + /// data, relative to the beginning of the file. Zero means no + /// file data. + /// + /// Byte offset is: Offset * (1 << ) + public ushort Offset { get; set; } + + /// + /// Length of the segment in the file, in bytes. Zero means 64K. + /// + public ushort Length { get; set; } + + /// + /// Flag word. + /// + [MarshalAs(UnmanagedType.U2)] + public SegmentTableEntryFlag FlagWord; + + /// + /// Minimum allocation size of the segment, in bytes. Total size + /// of the segment. Zero means 64K. + /// + public ushort MinimumAllocationSize { get; set; } + + /// + /// Segment data + /// + /// + /// Data is not sequential to the entry header. It lives at + /// the and has a size of + /// + public byte[]? Data { get; set; } + + /// + /// Per-segment data + /// + /// + /// This only exists if has a flag value + /// of . It immediately + /// follows . + /// + public PerSegmentData? PerSegmentData { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/AttributeCertificate/Entry.cs b/SabreTools.Serialization/Models/PortableExecutable/AttributeCertificate/Entry.cs new file mode 100644 index 00000000..d008ff64 --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/AttributeCertificate/Entry.cs @@ -0,0 +1,63 @@ +namespace SabreTools.Serialization.Models.PortableExecutable.AttributeCertificate +{ + /// + /// Attribute certificates can be associated with an image by adding an attribute + /// certificate table. The attribute certificate table is composed of a set of + /// contiguous, quadword-aligned attribute certificate entries. Zero padding is + /// inserted between the original end of the file and the beginning of the attribute + /// certificate table to achieve this alignment. + /// + /// The virtual address value from the Certificate Table entry in the Optional + /// Header Data Directory is a file offset to the first attribute certificate + /// entry. Subsequent entries are accessed by advancing that entry's dwLength + /// bytes, rounded up to an 8-byte multiple, from the start of the current + /// attribute certificate entry. This continues until the sum of the rounded dwLength + /// values equals the Size value from the Certificates Table entry in the Optional + /// Header Data Directory. If the sum of the rounded dwLength values does not equal + /// the Size value, then either the attribute certificate table or the Size field + /// is corrupted. + /// + /// The first certificate starts at offset 0x5000 from the start of the file on disk. + /// To advance through all the attribute certificate entries: + /// + /// 1. Add the first attribute certificate's dwLength value to the starting offset. + /// 2. Round the value from step 1 up to the nearest 8-byte multiple to find the offset + /// of the second attribute certificate entry. + /// 3. Add the offset value from step 2 to the second attribute certificate entry's + /// dwLength value and round up to the nearest 8-byte multiple to determine the offset + /// of the third attribute certificate entry. + /// 4. Repeat step 3 for each successive certificate until the calculated offset equals + /// 0x6000 (0x5000 start + 0x1000 total size), which indicates that you've walked + /// the entire table. + /// + /// Attribute certificate table entries can contain any certificate type, as long as + /// the entry has the correct dwLength value, a unique wRevision value, and a unique + /// wCertificateType value. The most common type of certificate table entry is a + /// WIN_CERTIFICATE structure, which is documented in Wintrust.h and discussed in + /// the remainder of this section. + /// + /// + public sealed class Entry + { + /// + /// Specifies the length of the attribute certificate entry. + /// + public uint Length { get; set; } + + /// + /// Contains the certificate version number. + /// + public WindowsCertificateRevision Revision { get; set; } + + /// + /// Specifies the type of content in Certificate. + /// + public WindowsCertificateType CertificateType { get; set; } + + /// + /// Contains a certificate, such as an Authenticode signature. + /// + /// + public byte[]? Certificate { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/BaseRelocation/Block.cs b/SabreTools.Serialization/Models/PortableExecutable/BaseRelocation/Block.cs new file mode 100644 index 00000000..07f5b4da --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/BaseRelocation/Block.cs @@ -0,0 +1,51 @@ +namespace SabreTools.Serialization.Models.PortableExecutable.BaseRelocation +{ + /// + /// The base relocation table contains entries for all base relocations in + /// the image. The Base Relocation Table field in the optional header data + /// directories gives the number of bytes in the base relocation table. For + /// more information, see Optional Header Data Directories (Image Only). + /// The base relocation table is divided into blocks. Each block represents + /// the base relocations for a 4K page. Each block must start on a 32-bit boundary. + /// + /// The loader is not required to process base relocations that are resolved by + /// the linker, unless the load image cannot be loaded at the image base that is + /// specified in the PE header. + /// + /// To apply a base relocation, the difference is calculated between the preferred + /// base address and the base where the image is actually loaded. If the image is + /// loaded at its preferred base, the difference is zero and thus the base + /// relocations do not have to be applied. + /// + /// + public sealed class Block + { + /// + /// The image base plus the page RVA is added to each offset to create + /// the VA where the base relocation must be applied. + /// + public uint PageRVA { get; set; } + + /// + /// The total number of bytes in the base relocation block, including + /// the Page RVA and Block Size fields and the Type/Offset fields that + /// follow. + /// + public uint BlockSize { get; set; } + + /// + /// The Block Size field is then followed by any number of Type or Offset + /// field entries. Each entry is a WORD (2 bytes) and has the following + /// structure: + /// + /// 4 bits - Type - Stored in the high 4 bits of the WORD, a value + /// that indicates the type of base relocation to be + /// applied. For more information, see + /// 12 bits - Offset - Stored in the remaining 12 bits of the WORD, an + /// offset from the starting address that was specified + /// in the Page RVA field for the block. This offset + /// specifies where the base relocation is to be applied. + /// + public TypeOffsetFieldEntry[]? TypeOffsetFieldEntries { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/BaseRelocation/TypeOffsetFieldEntry.cs b/SabreTools.Serialization/Models/PortableExecutable/BaseRelocation/TypeOffsetFieldEntry.cs new file mode 100644 index 00000000..94ecd2de --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/BaseRelocation/TypeOffsetFieldEntry.cs @@ -0,0 +1,22 @@ +namespace SabreTools.Serialization.Models.PortableExecutable.BaseRelocation +{ + /// + /// Type or Offset field entry is a WORD (2 bytes). + /// + /// + public sealed class TypeOffsetFieldEntry + { + /// + /// Stored in the high 4 bits of the WORD, a value that indicates the type + /// of base relocation to be applied. For more information, see + /// + public BaseRelocationTypes BaseRelocationType { get; set; } + + /// + /// Stored in the remaining 12 bits of the WORD, an offset from the starting + /// address that was specified in the Page RVA field for the block. This + /// offset specifies where the base relocation is to be applied. + /// + public ushort Offset { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Constants.cs b/SabreTools.Serialization/Models/PortableExecutable/Constants.cs new file mode 100644 index 00000000..b201cc00 --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Constants.cs @@ -0,0 +1,13 @@ +namespace SabreTools.Serialization.Models.PortableExecutable +{ + // TODO: Add more constants around sizes + // - Debug Directory entry size is a constant value of 28 (0x1C) + public static class Constants + { + public static readonly byte[] SignatureBytes = [0x50, 0x45, 0x00, 0x00]; + + public const string SignatureString = "PE\0\0"; + + public const uint SignatureUInt32 = 0x00004550; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/PortableExecutable/DataDirectory.cs b/SabreTools.Serialization/Models/PortableExecutable/DataDirectory.cs new file mode 100644 index 00000000..6a4950b1 --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/DataDirectory.cs @@ -0,0 +1,29 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.PortableExecutable +{ + /// + /// Each data directory gives the address and size of a table or string that Windows uses. + /// These data directory entries are all loaded into memory so that the system can use them + /// at run time. + /// + /// Also, do not assume that the RVAs in this table point to the beginning of a section or + /// that the sections that contain specific tables have specific names. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class DataDirectory + { + /// + /// The first field, VirtualAddress, is actually the RVA of the table. The RVA + /// is the address of the table relative to the base address of the image when + /// the table is loaded. + /// + public uint VirtualAddress; + + /// + /// The second field gives the size in bytes. + /// + public uint Size; + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/DebugData/Entry.cs b/SabreTools.Serialization/Models/PortableExecutable/DebugData/Entry.cs new file mode 100644 index 00000000..dd43a34a --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/DebugData/Entry.cs @@ -0,0 +1,67 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.PortableExecutable.DebugData +{ + /// + /// Image files contain an optional debug directory that indicates what form + /// of debug information is present and where it is. This directory consists + /// of an array of debug directory entries whose location and size are indicated + /// in the image optional header. + /// + /// The debug directory can be in a discardable .debug section (if one exists), + /// or it can be included in any other section in the image file, or not be in + /// a section at all. + /// + /// Each debug directory entry identifies the location and size of a block of + /// debug information. The specified RVA can be zero if the debug information + /// is not covered by a section header (that is, it resides in the image file + /// and is not mapped into the run-time address space). If it is mapped, the + /// RVA is its address. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class Entry + { + /// + /// Reserved, must be zero. + /// + public uint Characteristics; + + /// + /// The time and date that the debug data was created. + /// + public uint TimeDateStamp; + + /// + /// The major version number of the debug data format. + /// + public ushort MajorVersion; + + /// + /// The minor version number of the debug data format. + /// + public ushort MinorVersion; + + /// + /// The format of debugging information. This field enables support + /// of multiple debuggers. + /// + [MarshalAs(UnmanagedType.U4)] + public DebugType DebugType; + + /// + /// The size of the debug data (not including the debug directory itself). + /// + public uint SizeOfData; + + /// + /// The address of the debug data when loaded, relative to the image base. + /// + public uint AddressOfRawData; + + /// + /// The file pointer to the debug data. + /// + public uint PointerToRawData; + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/DebugData/NB10ProgramDatabase.cs b/SabreTools.Serialization/Models/PortableExecutable/DebugData/NB10ProgramDatabase.cs new file mode 100644 index 00000000..20c4d460 --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/DebugData/NB10ProgramDatabase.cs @@ -0,0 +1,44 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.PortableExecutable.DebugData +{ + /// + /// PDB 2.0 files + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class NB10ProgramDatabase + { + /// + /// "CodeView signature, equal to “NB10” + /// + public uint Signature; + + /// + /// CodeView offset. Set to 0, because debug information + /// is stored in a separate file. + /// + public uint Offset; + + /// + /// The time when debug information was created (in seconds + /// since 01.01.1970) + /// + public uint Timestamp; + + /// + /// Ever-incrementing value, which is initially set to 1 and + /// incremented every time when a part of the PDB file is updated + /// without rewriting the whole file. + /// + public uint Age; + + /// + /// Null-terminated name of the PDB file. It can also contain full + /// or partial path to the file. + /// + /// Is this Unicode? + [MarshalAs(UnmanagedType.LPStr)] + public string? PdbFileName; + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/DebugData/RSDSProgramDatabase.cs b/SabreTools.Serialization/Models/PortableExecutable/DebugData/RSDSProgramDatabase.cs new file mode 100644 index 00000000..433de95b --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/DebugData/RSDSProgramDatabase.cs @@ -0,0 +1,41 @@ +using System; +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.PortableExecutable.DebugData +{ + /// + /// This file describes the format of the pdb (Program Database) files of the "RSDS" + /// or "DS" type which are emitted by Miscrosoft's link.exe from version 7 and above. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class RSDSProgramDatabase + { + /// + /// "RSDS" signature + /// + public uint Signature; + + /// + /// 16-byte Globally Unique Identifier + /// + public Guid GUID; + + /// + /// Ever-incrementing value, which is initially set to 1 and + /// incremented every time when a part of the PDB file is updated + /// without rewriting the whole file. + /// + public uint Age; + + /// + /// zero terminated UTF8 path and file name + /// +#if NET472_OR_GREATER || NETCOREAPP + [MarshalAs(UnmanagedType.LPUTF8Str)] +#else + [MarshalAs(UnmanagedType.LPStr)] +#endif + public string? PathAndFileName; + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/DebugData/Table.cs b/SabreTools.Serialization/Models/PortableExecutable/DebugData/Table.cs new file mode 100644 index 00000000..da052f8d --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/DebugData/Table.cs @@ -0,0 +1,38 @@ +namespace SabreTools.Serialization.Models.PortableExecutable.DebugData +{ + /// + /// The .debug section is used in object files to contain compiler-generated debug + /// information and in image files to contain all of the debug information that is + /// generated. This section describes the packaging of debug information in object + /// and image files. + /// + /// The next section describes the format of the debug directory, which can be + /// anywhere in the image. Subsequent sections describe the "groups" in object + /// files that contain debug information. + /// + /// The default for the linker is that debug information is not mapped into the + /// address space of the image. A .debug section exists only when debug information + /// is mapped in the address space. + /// + /// + public sealed class Table + { + /// + /// Image files contain an optional debug directory that indicates what form + /// of debug information is present and where it is. This directory consists + /// of an array of debug directory entries whose location and size are + /// indicated in the image optional header. + /// + /// The debug directory can be in a discardable .debug section (if one exists), + /// or it can be included in any other section in the image file, or not be + /// in a section at all. + /// + /// Each debug directory entry identifies the location and size of a block of + /// debug information. The specified RVA can be zero if the debug information + /// is not covered by a section header (that is, it resides in the image + /// file and is not mapped into the run-time address space). If it is mapped, + /// the RVA is its address. + /// + public Entry[]? DebugDirectoryTable { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/DelayLoad/DirectoryTable.cs b/SabreTools.Serialization/Models/PortableExecutable/DelayLoad/DirectoryTable.cs new file mode 100644 index 00000000..1b78a62c --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/DelayLoad/DirectoryTable.cs @@ -0,0 +1,107 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.PortableExecutable.DelayLoad +{ + /// + /// The delay-load directory table is the counterpart to the import directory + /// table. It can be retrieved through the Delay Import Descriptor entry in + /// the optional header data directories list (offset 200). + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class DirectoryTable + { + /// + /// Must be zero. + /// + /// + /// As yet, no attribute flags are defined. The linker sets this field to + /// zero in the image. This field can be used to extend the record by + /// indicating the presence of new fields, or it can be used to indicate + /// behaviors to the delay or unload helper functions. + /// + public uint Attributes; + + /// + /// The RVA of the name of the DLL to be loaded. The name resides in the + /// read-only data section of the image. + /// + /// + /// The name of the DLL to be delay-loaded resides in the read-only data + /// section of the image. It is referenced through the szName field. + /// + public uint NameRVA; + + /// + /// The RVA of the module handle (in the data section of the image) of the DLL + /// to be delay-loaded. It is used for storage by the routine that is supplied + /// to manage delay-loading. + /// + /// + /// The handle of the DLL to be delay-loaded is in the data section of the image. + /// The phmod field points to the handle. The supplied delay-load helper uses + /// this location to store the handle to the loaded DLL. + /// + public uint ModuleHandle; + + /// + /// The RVA of the delay-load import address table. + /// + /// + /// The delay import address table (IAT) is referenced by the delay import + /// descriptor through the pIAT field. The delay-load helper updates these + /// pointers with the real entry points so that the thunks are no longer in + /// the calling loop. The function pointers are accessed by using the expression + /// pINT->u1.Function. + /// + public uint DelayImportAddressTable; + + /// + /// The RVA of the delay-load name table, which contains the names of the imports + /// that might need to be loaded. This matches the layout of the import name table. + /// + /// + /// The delay import name table (INT) contains the names of the imports that might + /// require loading. They are ordered in the same fashion as the function pointers + /// in the IAT. They consist of the same structures as the standard INT and are + /// accessed by using the expression pINT->u1.AddressOfData->Name[0]. + /// + public uint DelayImportNameTable; + + /// + /// The RVA of the bound delay-load address table, if it exists. + /// + /// + /// The delay bound import address table (BIAT) is an optional table of + /// IMAGE_THUNK_DATA items that is used along with the timestamp field of the + /// delay-load directory table by a post-process binding phase. + /// + public uint BoundDelayImportTable; + + /// + /// The RVA of the unload delay-load address table, if it exists. This is an exact + /// copy of the delay import address table. If the caller unloads the DLL, this + /// table should be copied back over the delay import address table so that + /// subsequent calls to the DLL continue to use the thunking mechanism correctly. + /// + /// + /// The delay unload import address table (UIAT) is an optional table of + /// IMAGE_THUNK_DATA items that the unload code uses to handle an explicit unload + /// request. It consists of initialized data in the read-only section that is an + /// exact copy of the original IAT that referred the code to the delay-load thunks. + /// On the unload request, the library can be freed, the *phmod cleared, and the + /// UIAT written over the IAT to restore everything to its preload state. + /// + public uint UnloadDelayImportTable; + + /// + /// The timestamp of the DLL to which this image has been bound. + /// + /// + /// The delay bound import address table (BIAT) is an optional table of + /// IMAGE_THUNK_DATA items that is used along with the timestamp field of the + /// delay-load directory table by a post-process binding phase. + /// + public uint TimeStamp; + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Enums.cs b/SabreTools.Serialization/Models/PortableExecutable/Enums.cs new file mode 100644 index 00000000..3a0f5639 --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Enums.cs @@ -0,0 +1,1678 @@ +using System; + +namespace SabreTools.Serialization.Models.PortableExecutable +{ + [Flags] + public enum AcceleratorTableFlags : ushort + { + /// + /// The accelerator key is a virtual-key code. If this flag is not specified, + /// the accelerator key is assumed to specify an ASCII character code. + /// + FVIRTKEY = 0x01, + + /// + /// A menu item on the menu bar is not highlighted when an accelerator is used. + /// This attribute is obsolete and retained only for backward compatibility with + /// resource files designed for 16-bit Windows. + /// + FNOINVERT = 0x02, + + /// + /// The accelerator is activated only if the user presses the SHIFT key. This flag + /// applies only to virtual keys. + /// + FSHIFT = 0x04, + + /// + /// The accelerator is activated only if the user presses the CTRL key. This flag + /// applies only to virtual keys. + /// + FCONTROL = 0x08, + + /// + /// The accelerator is activated only if the user presses the ALT key. This flag + /// applies only to virtual keys. + /// + FALT = 0x10, + + /// + /// The entry is last in an accelerator table. + /// + LastEntry = 0x80, + } + + public enum BaseRelocationTypes : ushort + { + /// + /// The base relocation is skipped. This type can be used to pad a block. + /// + IMAGE_REL_BASED_ABSOLUTE = 0, + + /// + /// The base relocation adds the high 16 bits of the difference to the 16-bit + /// field at offset. The 16-bit field represents the high value of a 32-bit word. + /// + IMAGE_REL_BASED_HIGH = 1, + + /// + /// The base relocation adds the low 16 bits of the difference to the 16-bit + /// field at offset. The 16-bit field represents the low half of a 32-bit word. + /// + IMAGE_REL_BASED_LOW = 2, + + /// + /// The base relocation applies all 32 bits of the difference to the 32-bit + /// field at offset. + /// + IMAGE_REL_BASED_HIGHLOW = 3, + + /// + /// The base relocation adds the high 16 bits of the difference to the 16-bit + /// field at offset. The 16-bit field represents the high value of a 32-bit word. + /// The low 16 bits of the 32-bit value are stored in the 16-bit word that follows + /// this base relocation. This means that this base relocation occupies two slots. + /// + IMAGE_REL_BASED_HIGHADJ = 4, + + /// + /// The relocation interpretation is dependent on the machine type. + /// When the machine type is MIPS, the base relocation applies to a MIPS jump + /// instruction. + /// + IMAGE_REL_BASED_MIPS_JMPADDR = 5, + + /// + /// This relocation is meaningful only when the machine type is ARM or Thumb. + /// The base relocation applies the 32-bit address of a symbol across a consecutive + /// MOVW/MOVT instruction pair. + /// + IMAGE_REL_BASED_ARM_MOV32 = 5, + + /// + /// This relocation is only meaningful when the machine type is RISC-V. The base + /// relocation applies to the high 20 bits of a 32-bit absolute address. + /// + IMAGE_REL_BASED_RISCV_HIGH20 = 5, + + /// + /// Reserved, must be zero. + /// + RESERVED6 = 6, + + /// + /// This relocation is meaningful only when the machine type is Thumb. The base + /// relocation applies the 32-bit address of a symbol to a consecutive MOVW/MOVT + /// instruction pair. + /// + IMAGE_REL_BASED_THUMB_MOV32 = 7, + + /// + /// This relocation is only meaningful when the machine type is RISC-V. The base + /// relocation applies to the low 12 bits of a 32-bit absolute address formed in + /// RISC-V I-type instruction format. + /// + IMAGE_REL_BASED_RISCV_LOW12I = 7, + + /// + /// This relocation is only meaningful when the machine type is RISC-V. The base + /// relocation applies to the low 12 bits of a 32-bit absolute address formed in + /// RISC-V S-type instruction format. + /// + IMAGE_REL_BASED_RISCV_LOW12S = 8, + + /// + /// This relocation is only meaningful when the machine type is LoongArch 32-bit. + /// The base relocation applies to a 32-bit absolute address formed in two + /// consecutive instructions. + /// + IMAGE_REL_BASED_LOONGARCH32_MARK_LA = 8, + + /// + /// This relocation is only meaningful when the machine type is LoongArch 64-bit. + /// The base relocation applies to a 64-bit absolute address formed in four + /// consecutive instructions. + /// + IMAGE_REL_BASED_LOONGARCH64_MARK_LA = 8, + + /// + /// The relocation is only meaningful when the machine type is MIPS. The base + /// relocation applies to a MIPS16 jump instruction. + /// + IMAGE_REL_BASED_MIPS_JMPADDR16 = 9, + + /// + /// The base relocation applies the difference to the 64-bit field at offset. + /// + IMAGE_REL_BASED_DIR64 = 10, + } + + public enum CallbackReason : ushort + { + /// + /// A new process has started, including the first thread. + /// + DLL_PROCESS_ATTACH = 1, + + /// + /// A new thread has been created. This notification sent for + /// all but the first thread. + /// + DLL_THREAD_ATTACH = 2, + + /// + /// A thread is about to be terminated. This notification sent + /// for all but the first thread. + /// + DLL_THREAD_DETACH = 3, + + /// + /// A process is about to terminate, including the original thread. + /// + DLL_PROCESS_DETACH = 0, + } + + public enum COMDATSelect : byte + { + /// + /// If this symbol is already defined, the linker issues a "multiply + /// defined symbol" error. + /// + IMAGE_COMDAT_SELECT_NODUPLICATES = 0x01, + + /// + /// Any section that defines the same COMDAT symbol can be linked; + /// the rest are removed. + /// + IMAGE_COMDAT_SELECT_ANY = 0x02, + + /// + /// The linker chooses an arbitrary section among the definitions + /// for this symbol. If all definitions are not the same size, a + /// "multiply defined symbol" error is issued. + /// + IMAGE_COMDAT_SELECT_SAME_SIZE = 0x03, + + /// + /// The linker chooses an arbitrary section among the definitions + /// for this symbol. If all definitions do not match exactly, a + /// "multiply defined symbol" error is issued. + /// + IMAGE_COMDAT_SELECT_EXACT_MATCH = 0x04, + + /// + /// The section is linked if a certain other COMDAT section is linked. + /// This other section is indicated by the Number field of the + /// auxiliary symbol record for the section definition. This setting + /// is useful for definitions that have components in multiple sections + /// (for example, code in one and data in another), but where all must + /// be linked or discarded as a set. The other section this section is + /// associated with must be a COMDAT section, which can be another + /// associative COMDAT section. An associative COMDAT section's section + /// association chain can't form a loop. The section association chain + /// must eventually come to a COMDAT section that doesn't have + /// IMAGE_COMDAT_SELECT_ASSOCIATIVE set. + /// + IMAGE_COMDAT_SELECT_ASSOCIATIVE = 0x05, + + /// + /// The linker chooses the largest definition from among all of the + /// definitions for this symbol. If multiple definitions have this size, + /// the choice between them is arbitrary. + /// + IMAGE_COMDAT_SELECT_LARGEST = 0x06, + } + + public enum DebugType : uint + { + /// + /// An unknown value that is ignored by all tools. + /// + IMAGE_DEBUG_TYPE_UNKNOWN = 0, + + /// + /// The COFF debug information (line numbers, symbol table, and string table). + /// This type of debug information is also pointed to by fields in the file + /// headers. + /// + IMAGE_DEBUG_TYPE_COFF = 1, + + /// + /// The Visual C++ debug information. + /// + IMAGE_DEBUG_TYPE_CODEVIEW = 2, + + /// + /// The frame pointer omission (FPO) information. This information tells the + /// debugger how to interpret nonstandard stack frames, which use the EBP + /// register for a purpose other than as a frame pointer. + /// + IMAGE_DEBUG_TYPE_FPO = 3, + + /// + /// The location of DBG file. + /// + IMAGE_DEBUG_TYPE_MISC = 4, + + /// + /// A copy of .pdata section. + /// + IMAGE_DEBUG_TYPE_EXCEPTION = 5, + + /// + /// Reserved. + /// + IMAGE_DEBUG_TYPE_FIXUP = 6, + + /// + /// The mapping from an RVA in image to an RVA in source image. + /// + IMAGE_DEBUG_TYPE_OMAP_TO_SRC = 7, + + /// + /// The mapping from an RVA in source image to an RVA in image. + /// + IMAGE_DEBUG_TYPE_OMAP_FROM_SRC = 8, + + /// + /// Reserved for Borland. + /// + IMAGE_DEBUG_TYPE_BORLAND = 9, + + /// + /// Reserved. + /// + IMAGE_DEBUG_TYPE_RESERVED10 = 10, + + /// + /// Reserved. + /// + IMAGE_DEBUG_TYPE_CLSID = 11, + + /// + /// PE determinism or reproducibility. + /// + IMAGE_DEBUG_TYPE_REPRO = 16, + + /// + /// Extended DLL characteristics bits. + /// + IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS = 20, + } + + public enum DialogItemTemplateOrdinal : ushort + { + Button = 0x0080, + Edit = 0x0081, + Static = 0x0082, + ListBox = 0x0083, + ScrollBar = 0x0084, + ComboBox = 0x0085, + } + + [Flags] + public enum DllCharacteristics : ushort + { + /// + /// Reserved, must be zero. + /// + RESERVED0 = 0x0001, + + /// + /// Reserved, must be zero. + /// + RESERVED1 = 0x0002, + + /// + /// Reserved, must be zero. + /// + RESERVED2 = 0x0004, + + /// + /// Reserved, must be zero. + /// + RESERVED3 = 0x0008, + + /// + /// Image can handle a high entropy 64-bit virtual address space. + /// + IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA = 0x0020, + + /// + /// DLL can be relocated at load time. + /// + IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE = 0x0040, + + /// + /// Code Integrity checks are enforced. + /// + IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY = 0x0080, + + /// + /// Image is NX compatible. + /// + IMAGE_DLLCHARACTERISTICS_NX_COMPAT = 0x0100, + + /// + /// Isolation aware, but do not isolate the image. + /// + IMAGE_DLLCHARACTERISTICS_NO_ISOLATION = 0x0200, + + /// + /// Does not use structured exception (SE) handling. + /// No SE handler may be called in this image. + /// + IMAGE_DLLCHARACTERISTICS_NO_SEH = 0x0400, + + /// + /// Do not bind the image. + /// + IMAGE_DLLCHARACTERISTICS_NO_BIND = 0x0800, + + /// + /// Image must execute in an AppContainer. + /// + IMAGE_DLLCHARACTERISTICS_APPCONTAINER = 0x1000, + + /// + /// A WDM driver. + /// + IMAGE_DLLCHARACTERISTICS_WDM_DRIVER = 0x2000, + + /// + /// Image supports Control Flow Guard. + /// + IMAGE_DLLCHARACTERISTICS_GUARD_CF = 0x4000, + + /// + /// Terminal Server aware. + /// + IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000, + } + + [Flags] + public enum ExtendedDllCharacteristics : ushort + { + /// + /// Image is Control-flow Enforcement Technology (CET) Shadow Stack compatible + /// + IMAGE_DLLCHARACTERISTICS_EX_CET_COMPAT = 0x0001, + + /// + /// All branch targets in all image code sections are annotated with forward-edge + /// control flow integrity guard instructions such as x86 CET-Indirect Branch + /// Tracking (IBT) or ARM Branch Target Identification (BTI) instructions. + /// This bit is not used by Windows. + /// + IMAGE_DLLCHARACTERISTICS_EX_FORWARD_CFI_COMPAT = 0x0040, + } + + [Flags] + public enum ExtendedWindowStyles : uint + { + /// + /// The window has generic left-aligned properties. This is the default. + /// + WS_EX_LEFT = 0x00000000, + + /// + /// The window text is displayed using left-to-right reading-order properties. + /// This is the default. + /// + WS_EX_LTRREADING = 0x00000000, + + /// + /// The vertical scroll bar (if present) is to the right of the client area. + /// This is the default. + /// + WS_EX_RIGHTSCROLLBAR = 0x00000000, + + /// + /// The window has a double border; the window can, optionally, be created with + /// a title bar by specifying the WS_CAPTION style in the dwStyle parameter. + /// + WS_EX_DLGMODALFRAME = 0x00000001, + + /// + /// The child window created with this style does not send the WM_PARENTNOTIFY + /// message to its parent window when it is created or destroyed. + /// + WS_EX_NOPARENTNOTIFY = 0x00000004, + + /// + /// The window should be placed above all non-topmost windows and should stay above them, + /// even when the window is deactivated. To add or remove this style, use the + /// SetWindowPos function. + /// + WS_EX_TOPMOST = 0x00000008, + + /// + /// The window accepts drag-drop files. + /// + WS_EX_ACCEPTFILES = 0x00000010, + + /// + /// The window should not be painted until siblings beneath the window (that were created + /// by the same thread) have been painted. The window appears transparent because the bits + /// of underlying sibling windows have already been painted. + /// + /// To achieve transparency without these restrictions, use the SetWindowRgn function. + /// + WS_EX_TRANSPARENT = 0x00000020, + + /// + /// The window is a MDI child window. + /// + WS_EX_MDICHILD = 0x00000040, + + /// + /// The window is intended to be used as a floating toolbar. A tool window has a title + /// bar that is shorter than a normal title bar, and the window title is drawn using a + /// smaller font. A tool window does not appear in the taskbar or in the dialog that + /// appears when the user presses ALT+TAB. If a tool window has a system menu, its icon + /// is not displayed on the title bar. However, you can display the system menu by + /// right-clicking or by typing ALT+SPACE. + /// + WS_EX_TOOLWINDOW = 0x00000080, + + /// + /// The window has a border with a raised edge. + /// + WS_EX_WINDOWEDGE = 0x00000100, + + /// + /// The window has a border with a sunken edge. + /// + WS_EX_CLIENTEDGE = 0x00000200, + + /// + /// The title bar of the window includes a question mark. When the user clicks + /// the question mark, the cursor changes to a question mark with a pointer. If + /// the user then clicks a child window, the child receives a WM_HELP message. + /// The child window should pass the message to the parent window procedure, + /// which should call the WinHelp function using the HELP_WM_HELP command. The + /// Help application displays a pop-up window that typically contains help for + /// the child window. + /// + /// WS_EX_CONTEXTHELP cannot be used with the WS_MAXIMIZEBOX or WS_MINIMIZEBOX + /// styles. + /// + WS_EX_CONTEXTHELP = 0x00000400, + + /// + /// The window has generic "right-aligned" properties. This depends on the window class. + /// This style has an effect only if the shell language is Hebrew, Arabic, or another + /// language that supports reading-order alignment; otherwise, the style is ignored. + /// + /// Using the WS_EX_RIGHT style for static or edit controls has the same effect as using + /// the SS_RIGHT or ES_RIGHT style, respectively. Using this style with button controls + /// has the same effect as using BS_RIGHT and BS_RIGHTBUTTON styles. + /// + WS_EX_RIGHT = 0x00001000, + + /// + /// If the shell language is Hebrew, Arabic, or another language that supports reading-order + /// alignment, the window text is displayed using right-to-left reading-order properties. + /// For other languages, the style is ignored. + /// + WS_EX_RTLREADING = 0x00002000, + + /// + /// If the shell language is Hebrew, Arabic, or another language that supports + /// reading order alignment, the vertical scroll bar (if present) is to the left + /// of the client area. For other languages, the style is ignored. + /// + WS_EX_LEFTSCROLLBAR = 0x00004000, + + /// + /// The window itself contains child windows that should take part in dialog box + /// navigation. If this style is specified, the dialog manager recurses into + /// children of this window when performing navigation operations such as handling + /// the TAB key, an arrow key, or a keyboard mnemonic. + /// + WS_EX_CONTROLPARENT = 0x00010000, + + /// + /// The window has a three-dimensional border style intended to be used for items that do + /// not accept user input. + /// + WS_EX_STATICEDGE = 0x00020000, + + /// + /// Forces a top-level window onto the taskbar when the window is visible. + /// + WS_EX_APPWINDOW = 0x00040000, + + /// + /// The window is a layered window. This style cannot be used if the window has a + /// class style of either CS_OWNDC or CS_CLASSDC. + /// + /// Windows 8: The WS_EX_LAYERED style is supported for top-level windows and child + /// windows. Previous Windows versions support WS_EX_LAYERED only for top-level windows. + /// + WS_EX_LAYERED = 0x00080000, + + /// + /// The window does not pass its window layout to its child windows. + /// + WS_EX_NOINHERITLAYOUT = 0x00100000, + + /// + /// The window does not render to a redirection surface. This is for windows that do not + /// have visible content or that use mechanisms other than surfaces to provide their visual. + /// + WS_EX_NOREDIRECTIONBITMAP = 0x00200000, + + /// + /// If the shell language is Hebrew, Arabic, or another language that supports reading + /// order alignment, the horizontal origin of the window is on the right edge. + /// Increasing horizontal values advance to the left. + /// + WS_EX_LAYOUTRTL = 0x00400000, + + /// + /// Paints all descendants of a window in bottom-to-top painting order using + /// double-buffering. Bottom-to-top painting order allows a descendent window + /// to have translucency (alpha) and transparency (color-key) effects, but only + /// if the descendent window also has the WS_EX_TRANSPARENT bit set. + /// Double-buffering allows the window and its descendents to be painted without + /// flicker. This cannot be used if the window has a class style of either + /// CS_OWNDC or CS_CLASSDC. + /// + /// Windows 2000: This style is not supported. + /// + WS_EX_COMPOSITED = 0x02000000, + + /// + /// A top-level window created with this style does not become the foreground window when + /// the user clicks it. The system does not bring this window to the foreground when the + /// user minimizes or closes the foreground window. + /// + /// The window should not be activated through programmatic access or via keyboard + /// navigation by accessible technology, such as Narrator. + /// + /// To activate the window, use the SetActiveWindow or SetForegroundWindow function. + /// + /// The window does not appear on the taskbar by default. To force the window to appear on + /// the taskbar, use the WS_EX_APPWINDOW style. + /// + WS_EX_NOACTIVATE = 0x08000000, + + /// + /// The window is an overlapped window. + /// + WS_EX_OVERLAPPEDWINDOW = WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE, + + /// + /// The window is palette window, which is a modeless dialog box that presents an array of + /// commands. + /// + WS_EX_PALETTEWINDOW = WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST, + } + + public enum FixedFileInfoFileSubtype : uint + { + /// + /// The driver type is unknown by the system. + /// The font type is unknown by the system. + /// + VFT2_UNKNOWN = 0x00000000, + + #region VFT_DRV + + /// + /// The file contains a printer driver. + /// + VFT2_DRV_PRINTER = 0x00000001, + + /// + /// The file contains a keyboard driver. + /// + VFT2_DRV_KEYBOARD = 0x00000002, + + /// + /// The file contains a language driver. + /// + VFT2_DRV_LANGUAGE = 0x00000003, + + /// + /// The file contains a display driver. + /// + VFT2_DRV_DISPLAY = 0x00000004, + + /// + /// The file contains a mouse driver. + /// + VFT2_DRV_MOUSE = 0x00000005, + + /// + /// The file contains a network driver. + /// + VFT2_DRV_NETWORK = 0x00000006, + + /// + /// The file contains a system driver. + /// + VFT2_DRV_SYSTEM = 0x00000007, + + /// + /// The file contains an installable driver. + /// + VFT2_DRV_INSTALLABLE = 0x00000008, + + /// + /// The file contains a sound driver. + /// + VFT2_DRV_SOUND = 0x00000009, + + /// + /// The file contains a communications driver. + /// + VFT2_DRV_COMM = 0x0000000A, + + /// + /// The file contains a versioned printer driver. + /// + VFT2_DRV_VERSIONED_PRINTER = 0x0000000C, + + #endregion + + #region VFT_FONT + + /// + /// The file contains a raster font. + /// + VFT2_FONT_RASTER = 0x00000001, + + /// + /// The file contains a vector font. + /// + VFT2_FONT_VECTOR = 0x00000002, + + /// + /// The file contains a TrueType font. + /// + VFT2_FONT_TRUETYPE = 0x00000003, + + #endregion + } + + public enum FixedFileInfoFileType : uint + { + /// + /// The file type is unknown to the system. + /// + VFT_UNKNOWN = 0x00000000, + + /// + /// The file contains an application. + /// + VFT_APP = 0x00000001, + + /// + /// The file contains a DLL. + /// + VFT_DLL = 0x00000002, + + /// + /// The file contains a device driver. If FileType is VFT_DRV, FileSubtype + /// contains a more specific description of the driver. + /// + VFT_DRV = 0x00000003, + + /// + /// The file contains a font. If FileType is VFT_FONT, FileSubtype contains + /// a more specific description of the font file. + /// + VFT_FONT = 0x00000004, + + /// + /// The file contains a virtual device. + /// + VFT_VXD = 0x00000005, + + /// + /// The file contains a static-link library. + /// + VFT_STATIC_LIB = 0x00000007, + } + + [Flags] + public enum FixedFileInfoFlags : uint + { + /// + /// The file contains debugging information or is compiled with debugging + /// features enabled. + /// + VS_FF_DEBUG = 0x00000001, + + /// + /// The file is a development version, not a commercially released product. + /// + VS_FF_PRERELEASE = 0x00000002, + + /// + /// The file has been modified and is not identical to the original shipping + /// file of the same version number. + /// + VS_FF_PATCHED = 0x00000004, + + /// + /// The file was not built using standard release procedures. If this flag is + /// set, the StringFileInfo structure should contain a PrivateBuild entry. + /// + VS_FF_PRIVATEBUILD = 0x00000008, + + /// + /// The file's version structure was created dynamically; therefore, some + /// of the members in this structure may be empty or incorrect. This flag + /// should never be set in a file's VS_VERSIONINFO data. + /// + VS_FF_INFOINFERRED = 0x00000010, + + /// + /// The file was built by the original company using standard release + /// procedures but is a variation of the normal file of the same version number. + /// If this flag is set, the StringFileInfo structure should contain a SpecialBuild + /// entry. + /// + VS_FF_SPECIALBUILD = 0x00000020, + } + + [Flags] + public enum FixedFileInfoOS : uint + { + /// + /// The operating system for which the file was designed is + /// unknown to the system. + /// + VOS_UNKNOWN = 0x00000000, + + /// + /// The file was designed for 16-bit Windows. + /// + VOS__WINDOWS16 = 0x00000001, + + /// + /// The file was designed for 16-bit Presentation Manager. + /// + VOS__PM16 = 0x00000002, + + /// + /// The file was designed for 32-bit Presentation Manager. + /// + VOS__PM32 = 0x00000003, + + /// + /// The file was designed for 32-bit Windows. + /// + VOS__WINDOWS32 = 0x00000004, + + /// + /// The file was designed for MS-DOS. + /// + VOS_DOS = 0x00010000, + + /// + /// The file was designed for 16-bit OS/2. + /// + VOS_OS216 = 0x00020000, + + /// + /// The file was designed for 32-bit OS/2. + /// + VOS_OS232 = 0x00030000, + + /// + /// The file was designed for Windows NT. + /// + VOS_NT = 0x00040000, + } + + [Flags] + public enum GuardFlags : uint + { + /// + /// Module performs control flow integrity checks using + /// system-supplied support. + /// + IMAGE_GUARD_CF_INSTRUMENTED = 0x00000100, + + /// + /// Module performs control flow and write integrity checks. + /// + IMAGE_GUARD_CFW_INSTRUMENTED = 0x00000200, + + /// + /// Module contains valid control flow target metadata. + /// + IMAGE_GUARD_CF_FUNCTION_TABLE_PRESENT = 0x00000400, + + /// + /// Module does not make use of the /GS security cookie. + /// + IMAGE_GUARD_SECURITY_COOKIE_UNUSED = 0x00000800, + + /// + /// Module supports read only delay load IAT. + /// + IMAGE_GUARD_PROTECT_DELAYLOAD_IAT = 0x00001000, + + /// + /// Delayload import table in its own .didat section (with + /// nothing else in it) that can be freely reprotected. + /// + IMAGE_GUARD_DELAYLOAD_IAT_IN_ITS_OWN_SECTION = 0x00002000, + + /// + /// Module contains suppressed export information. This also + /// infers that the address taken IAT table is also present + /// in the load config. + /// + IMAGE_GUARD_CF_EXPORT_SUPPRESSION_INFO_PRESENT = 0x00004000, + + /// + /// Module enables suppression of exports. + /// + IMAGE_GUARD_CF_ENABLE_EXPORT_SUPPRESSION = 0x00008000, + + /// + /// Module contains longjmp target information. + /// + IMAGE_GUARD_CF_LONGJUMP_TABLE_PRESENT = 0x00010000, + + /// + /// Mask for the subfield that contains the stride of Control + /// Flow Guard function table entries (that is, the additional + /// count of bytes per table entry). + /// + IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_MASK = 0xF0000000, + + /// + /// Additionally, the Windows SDK winnt.h header defines this + /// macro for the amount of bits to right-shift the GuardFlags + /// value to right-justify the Control Flow Guard function table + /// stride: + /// + IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_SHIFT = 28, + } + + public enum ImportType : ushort + { + /// + /// Executable code. + /// + IMPORT_CODE = 0, + + /// + /// Data. + /// + IMPORT_DATA = 1, + + /// + /// Specified as CONST in the .def file. + /// + IMPORT_CONST = 2, + } + + // Actually 3 bits + public enum ImportNameType : ushort + { + /// + /// The import is by ordinal. This indicates that the value in the + /// Ordinal/Hint field of the import header is the import's ordinal. + /// If this constant is not specified, then the Ordinal/Hint field + /// should always be interpreted as the import's hint. + /// + IMPORT_ORDINAL = 0, + + /// + /// The import name is identical to the public symbol name. + /// + IMPORT_NAME = 1, + + /// + /// The import name is the public symbol name, but skipping the leading + /// ?, @, or optionally _. + /// + IMPORT_NAME_NOPREFIX = 2, + + /// + /// The import name is the public symbol name, but skipping the leading + /// ?, @, or optionally _, and truncating at the first @. + /// + IMPORT_NAME_UNDECORATE = 3, + } + + [Flags] + public enum MemoryFlags : ushort + { + // TODO: Validate the ~ statements + MOVEABLE = 0x0010, + FIXED = 0xFFEF, // ~MOVEABLE + + PURE = 0x0020, + IMPURE = 0xFFDF, // ~PURE + + PRELOAD = 0x0040, + LOADONCALL = 0xFFBF, // ~PRELOAD + + DISCARDABLE = 0x1000, + } + + [Flags] + public enum MenuFlags : uint + { + MF_INSERT = 0x00000000, + MF_CHANGE = 0x00000080, + MF_APPEND = 0x00000100, + MF_DELETE = 0x00000200, + MF_REMOVE = 0x00001000, + + MF_BYCOMMAND = 0x00000000, + MF_BYPOSITION = 0x00000400, + + MF_SEPARATOR = 0x00000800, + + MF_ENABLED = 0x00000000, + MF_GRAYED = 0x00000001, + MF_DISABLED = 0x00000002, + + MF_UNCHECKED = 0x00000000, + MF_CHECKED = 0x00000008, + MF_USECHECKBITMAPS = 0x00000200, + + MF_STRING = 0x00000000, + MF_BITMAP = 0x00000004, + MF_OWNERDRAW = 0x00000100, + + MF_POPUP = 0x00000010, + MF_MENUBARBREAK = 0x00000020, + MF_MENUBREAK = 0x00000040, + + MF_UNHILITE = 0x00000000, + MF_HILITE = 0x00000080, + + MF_DEFAULT = 0x00001000, + MF_SYSMENU = 0x00002000, + MF_HELP = 0x00004000, + MF_RIGHTJUSTIFY = 0x00004000, + + MF_MOUSESELECT = 0x00008000, + MF_END = 0x00000080, + + MFT_STRING = MF_STRING, + MFT_BITMAP = MF_BITMAP, + MFT_MENUBARBREAK = MF_MENUBARBREAK, + MFT_MENUBREAK = MF_MENUBREAK, + MFT_OWNERDRAW = MF_OWNERDRAW, + MFT_RADIOCHECK = 0x00000200, + MFT_SEPARATOR = MF_SEPARATOR, + MFT_RIGHTORDER = 0x00002000, + MFT_RIGHTJUSTIFY = MF_RIGHTJUSTIFY, + + MFS_GRAYED = 0x00000003, + MFS_DISABLED = MFS_GRAYED, + MFS_CHECKED = MF_CHECKED, + MFS_HILITE = MF_HILITE, + MFS_ENABLED = MF_ENABLED, + MFS_UNCHECKED = MF_UNCHECKED, + MFS_UNHILITE = MF_UNHILITE, + MFS_DEFAULT = MF_DEFAULT, + } + + public enum ResourceType : uint + { + RT_NEWRESOURCE = 0x2000, + RT_ERROR = 0x7FFF, + + /// + /// Hardware-dependent cursor resource. + /// + RT_CURSOR = 1, + + /// + /// Bitmap resource. + /// + RT_BITMAP = 2, + + /// + /// Hardware-dependent icon resource. + /// + RT_ICON = 3, + + /// + /// Menu resource. + /// + RT_MENU = 4, + + /// + /// Dialog box. + /// + RT_DIALOG = 5, + + /// + /// String-table entry. + /// + RT_STRING = 6, + + /// + /// Font directory resource. + /// + RT_FONTDIR = 7, + + /// + /// Font resource. + /// + RT_FONT = 8, + + /// + /// Accelerator table. + /// + RT_ACCELERATOR = 9, + + /// + /// Application-defined resource (raw data). + /// + RT_RCDATA = 10, + + /// + /// Message-table entry. + /// + RT_MESSAGETABLE = 11, + + /// + /// Hardware-independent cursor resource. + /// + RT_GROUP_CURSOR = RT_CURSOR + 11, + + /// + /// Hardware-independent icon resource. + /// + RT_GROUP_ICON = RT_ICON + 11, + + /// + /// Version resource. + /// + RT_VERSION = 16, + + /// + /// Allows a resource editing tool to associate a string with an .rc file. + /// Typically, the string is the name of the header file that provides symbolic + /// names. The resource compiler parses the string but otherwise ignores the + /// value. For example, `1 DLGINCLUDE "MyFile.h"` + /// + RT_DLGINCLUDE = 17, + + /// + /// Plug and Play resource. + /// + RT_PLUGPLAY = 19, + + /// + /// VXD. + /// + RT_VXD = 20, + + /// + /// Animated cursor. + /// + RT_ANICURSOR = 21, + + /// + /// Animated icon. + /// + RT_ANIICON = 22, + + /// + /// HTML resource. + /// + RT_HTML = 23, + + /// + /// Side-by-Side Assembly Manifest. + /// + RT_MANIFEST = 24, + + RT_NEWBITMAP = (RT_BITMAP | RT_NEWRESOURCE), + RT_NEWMENU = (RT_MENU | RT_NEWRESOURCE), + RT_NEWDIALOG = (RT_DIALOG | RT_NEWRESOURCE), + } + + public enum SymbolDerivedType : byte + { + /// + /// No derived type; the symbol is a simple scalar variable. + /// + IMAGE_SYM_DTYPE_NULL = 0x00, + + /// + /// The symbol is a pointer to base type. + /// + IMAGE_SYM_DTYPE_POINTER = 0x01, + + /// + /// The symbol is a function that returns a base type. + /// + IMAGE_SYM_DTYPE_FUNCTION = 0x02, + + /// + /// The symbol is an array of base type. + /// + IMAGE_SYM_DTYPE_ARRAY = 0x03, + } + + public enum VersionResourceType : ushort + { + BinaryData = 0, + TextData = 1, + } + + [Flags] + public enum WindowStyles : uint + { + #region Standard Styles + + /// + /// The window is an overlapped window. An overlapped window has a title + /// bar and a border. Same as the WS_TILED style. + /// + WS_OVERLAPPED = 0x00000000, + + /// + /// The window is an overlapped window. An overlapped window has a title bar + /// and a border. Same as the WS_OVERLAPPED style. + /// + WS_TILED = 0x00000000, + + /// + /// The window has a maximize button. Cannot be combined with the + /// WS_EX_CONTEXTHELP style. The WS_SYSMENU style must also be specified. + /// + WS_MAXIMIZEBOX = 0x00010000, + + /// + /// The window is a control that can receive the keyboard focus when the user + /// presses the TAB key. Pressing the TAB key changes the keyboard focus to + /// the next control with the WS_TABSTOP style. + /// + /// You can turn this style on and off to change dialog box navigation. To + /// change this style after a window has been created, use the SetWindowLong + /// function. For user-created windows and modeless dialogs to work with tab + /// stops, alter the message loop to call the IsDialogMessage function. + /// + WS_TABSTOP = 0x00010000, + + /// + /// The window has a minimize button. Cannot be combined with the + /// WS_EX_CONTEXTHELP style. The WS_SYSMENU style must also be specified. + /// + WS_MINIMIZEBOX = 0x00020000, + + /// + /// The window is the first control of a group of controls. The group consists + /// of this first control and all controls defined after it, up to the next + /// control with the WS_GROUP style. The first control in each group usually + /// has the WS_TABSTOP style so that the user can move from group to group. + /// The user can subsequently change the keyboard focus from one control in + /// the group to the next control in the group by using the direction keys. + /// + /// You can turn this style on and off to change dialog box navigation. To + /// change this style after a window has been created, use the SetWindowLong + /// function. + /// + WS_GROUP = 0x00020000, + + /// + /// The window has a sizing border. Same as the WS_THICKFRAME style. + /// + WS_SIZEBOX = 0x00040000, + + /// + /// The window has a sizing border. Same as the WS_SIZEBOX style. + /// + WS_THICKFRAME = 0x00040000, + + /// + /// The window has a window menu on its title bar. The WS_CAPTION style must + /// also be specified. + /// + WS_SYSMENU = 0x00080000, + + /// + /// The window has a horizontal scroll bar. + /// + WS_HSCROLL = 0x00100000, + + /// + /// The window has a vertical scroll bar. + /// + WS_VSCROLL = 0x00200000, + + /// + /// The window has a border of a style typically used with dialog boxes. A + /// window with this style cannot have a title bar. + /// + WS_DLGFRAME = 0x00400000, + + /// + /// The window has a thin-line border + /// + WS_BORDER = 0x00800000, + + /// + /// The window has a title bar + /// + WS_CAPTION = 0x00C00000, + + /// + /// The window is initially maximized. + /// + WS_MAXIMIZE = 0x01000000, + + /// + /// Excludes the area occupied by child windows when drawing occurs within the + /// parent window. This style is used when creating the parent window. + /// + WS_CLIPCHILDREN = 0x02000000, + + /// + /// Clips child windows relative to each other; that is, when a particular child + /// window receives a WM_PAINT message, the WS_CLIPSIBLINGS style clips all other + /// overlapping child windows out of the region of the child window to be updated. + /// If WS_CLIPSIBLINGS is not specified and child windows overlap, it is possible, + /// when drawing within the client area of a child window, to draw within the + /// client area of a neighboring child window. + /// + WS_CLIPSIBLINGS = 0x04000000, + + /// + /// The window is initially disabled. A disabled window cannot receive input from + /// the user. To change this after a window has been created, use the EnableWindow + /// function. + /// + WS_DISABLED = 0x08000000, + + /// + /// The window is initially visible. + /// This style can be turned on and off by using the ShowWindow or SetWindowPos + /// function. + /// + WS_VISIBLE = 0x10000000, + + /// + /// The window is initially minimized. Same as the WS_MINIMIZE style. + /// + WS_ICONIC = 0x20000000, + + /// + /// The window is initially minimized. Same as the WS_ICONIC style. + /// + WS_MINIMIZE = 0x20000000, + + /// + /// The window is a child window. A window with this style cannot have a menu + /// bar. This style cannot be used with the WS_POPUP style. + /// + WS_CHILD = 0x40000000, + + /// + /// Same as the WS_CHILD style. + /// + WS_CHILDWINDOW = 0x40000000, + + /// + /// The window is a pop-up window. This style cannot be used with the WS_CHILD style. + /// + WS_POPUP = 0x80000000, + + /// + /// The window is an overlapped window. Same as the WS_TILEDWINDOW style. + /// + WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX, + + /// + /// The window is a pop-up window. The WS_CAPTION and WS_POPUPWINDOW styles must be + /// combined to make the window menu visible. + /// + WS_POPUPWINDOW = WS_POPUP | WS_BORDER | WS_SYSMENU, + + /// + /// The window is an overlapped window. Same as the WS_OVERLAPPEDWINDOW style. + /// + WS_TILEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX, + + #endregion + + #region Common Control Styles + + /// + /// Causes the control to position itself at the top of the parent window's + /// client area and sets the width to be the same as the parent window's width. + /// Toolbars have this style by default. + /// + CCS_TOP = 0x00000001, + + /// + /// Causes the control to resize and move itself horizontally, but not vertically, + /// in response to a WM_SIZE message. If CCS_NORESIZE is used, this style does not + /// apply. Header windows have this style by default. + /// + CCS_NOMOVEY = 0x00000002, + + /// + /// Causes the control to position itself at the bottom of the parent window's + /// client area and sets the width to be the same as the parent window's width. + /// Status windows have this style by default. + /// + CCS_BOTTOM = 0x00000003, + + /// + /// Prevents the control from using the default width and height when setting its + /// initial size or a new size. Instead, the control uses the width and height + /// specified in the request for creation or sizing. + /// + CCS_NORESIZE = 0x00000004, + + /// + /// Prevents the control from automatically moving to the top or bottom of the parent + /// window. Instead, the control keeps its position within the parent window despite + /// changes to the size of the parent. If CCS_TOP or CCS_BOTTOM is also used, the + /// height is adjusted to the default, but the position and width remain unchanged. + /// + CCS_NOPARENTALIGN = 0x00000008, + + /// + /// Enables a toolbar's built-in customization features, which let the user to drag a + /// button to a new position or to remove a button by dragging it off the toolbar. + /// In addition, the user can double-click the toolbar to display the Customize Toolbar + /// dialog box, which enables the user to add, delete, and rearrange toolbar buttons. + /// + CCS_ADJUSTABLE = 0x00000020, + + /// + /// Prevents a two-pixel highlight from being drawn at the top of the control. + /// + CCS_NODIVIDER = 0x00000040, + + /// + /// Version 4.70. Causes the control to be displayed vertically. + /// + CCS_VERT = 0x00000080, + + /// + /// Version 4.70. Causes the control to be displayed vertically on the left side of the + /// parent window. + /// + CCS_LEFT = CCS_VERT | CCS_TOP, + + /// + /// Version 4.70. Causes the control to be displayed vertically on the right side of the + /// parent window. + /// + CCS_RIGHT = CCS_VERT | CCS_BOTTOM, + + /// + /// Version 4.70. Causes the control to resize and move itself vertically, but not + /// horizontally, in response to a WM_SIZE message. If CCS_NORESIZE is used, this style + /// does not apply. + /// + CCS_NOMOVEX = CCS_VERT | CCS_NOMOVEY, + + #endregion + + #region Dialog Box Styles + + /// + /// Indicates that the coordinates of the dialog box are screen coordinates. + /// If this style is not specified, the coordinates are client coordinates. + /// + DS_ABSALIGN = 0x00000001, + + /// + /// This style is obsolete and is included for compatibility with 16-bit versions + /// of Windows. If you specify this style, the system creates the dialog box with + /// the WS_EX_TOPMOST style. This style does not prevent the user from accessing + /// other windows on the desktop. + /// + /// Do not combine this style with the DS_CONTROL style. + /// + DS_SYSMODAL = 0x00000002, + + /// + /// Obsolete. The system automatically applies the three-dimensional look to dialog + /// boxes created by applications. + /// + DS_3DLOOK = 0x00000004, + + /// + /// Causes the dialog box to use the SYSTEM_FIXED_FONT instead of the default + /// SYSTEM_FONT. This is a monospace font compatible with the System font in 16-bit + /// versions of Windows earlier than 3.0. + /// + DS_FIXEDSYS = 0x00000008, + + /// + /// Creates the dialog box even if errors occur for example, if a child window cannot + /// be created or if the system cannot create a special data segment for an edit control. + /// + DS_NOFAILCREATE = 0x00000010, + + /// + /// Applies to 16-bit applications only. This style directs edit controls in the + /// dialog box to allocate memory from the application's data segment. Otherwise, + /// edit controls allocate storage from a global memory object. + /// + DS_LOCALEDIT = 0x00000020, + + /// + /// Indicates that the header of the dialog box template (either standard or extended) + /// contains additional data specifying the font to use for text in the client area + /// and controls of the dialog box. If possible, the system selects a font according + /// to the specified font data. The system passes a handle to the font to the dialog + /// box and to each control by sending them the WM_SETFONT message. For descriptions + /// of the format of this font data, see DLGTEMPLATE and DLGTEMPLATEEX. + /// + /// If neither DS_SETFONT nor DS_SHELLFONT is specified, the dialog box template does + /// not include the font data. + /// + DS_SETFONT = 0x00000040, + + /// + /// Creates a dialog box with a modal dialog-box frame that can be combined with a + /// title bar and window menu by specifying the WS_CAPTION and WS_SYSMENU styles. + /// + DS_MODALFRAME = 0x00000080, + + /// + /// Suppresses WM_ENTERIDLE messages that the system would otherwise send to the owner + /// of the dialog box while the dialog box is displayed. + /// + DS_NOIDLEMSG = 0x00000100, + + /// + /// Causes the system to use the SetForegroundWindow function to bring the dialog box + /// to the foreground. This style is useful for modal dialog boxes that require immediate + /// attention from the user regardless of whether the owner window is the foreground + /// window. + /// + /// The system restricts which processes can set the foreground window. For more + /// information, see Foreground and Background Windows. + /// + DS_SETFOREGROUND = 0x00000200, + + /// + /// Creates a dialog box that works well as a child window of another dialog box, much like + /// a page in a property sheet. This style allows the user to tab among the control windows + /// of a child dialog box, use its accelerator keys, and so on. + /// + DS_CONTROL = 0x00000400, + + /// + /// Centers the dialog box in the working area of the monitor that contains the owner window. + /// If no owner window is specified, the dialog box is centered in the working area of a + /// monitor determined by the system. The working area is the area not obscured by the taskbar + /// or any appbars. + /// + DS_CENTER = 0x00000800, + + /// + /// Centers the dialog box on the mouse cursor. + /// + DS_CENTERMOUSE = 0x00001000, + + /// + /// Includes a question mark in the title bar of the dialog box. When the user clicks the + /// question mark, the cursor changes to a question mark with a pointer. If the user then clicks + /// a control in the dialog box, the control receives a WM_HELP message. The control should pass + /// the message to the dialog box procedure, which should call the function using the + /// HELP_WM_HELP command. The help application displays a pop-up window that typically contains + /// help for the control. + /// + /// Note that DS_CONTEXTHELP is only a placeholder. When the dialog box is created, the system + /// checks for DS_CONTEXTHELP and, if it is there, adds WS_EX_CONTEXTHELP to the extended style + /// of the dialog box. WS_EX_CONTEXTHELP cannot be used with the WS_MAXIMIZEBOX or WS_MINIMIZEBOX + /// styles. + /// + DS_CONTEXTHELP = 0x00002000, + + /// + /// Windows CE Version 5.0 and later + /// + DS_USEPIXELS = 0x00008000, + + /// + /// Indicates that the dialog box should use the system font. The typeface member of the extended + /// dialog box template must be set to MS Shell Dlg. Otherwise, this style has no effect. It is + /// also recommended that you use the DIALOGEX Resource, rather than the DIALOG Resource. For + /// more information, see Dialog Box Fonts. + /// + /// The system selects a font using the font data specified in the pointsize, weight, and italic + /// members. The system passes a handle to the font to the dialog box and to each control by + /// sending them the WM_SETFONT message. For descriptions of the format of this font data, see + /// DLGTEMPLATEEX. + /// + /// If neither DS_SHELLFONT nor DS_SETFONT is specified, the extended dialog box template does + /// not include the font data. + /// + DS_SHELLFONT = DS_SETFONT | DS_FIXEDSYS, + + #endregion + } + + public enum WindowsCertificateRevision : ushort + { + /// + /// Version 1, legacy version of the Win_Certificate structure. It is supported + /// only for purposes of verifying legacy Authenticode signatures + /// + WIN_CERT_REVISION_1_0 = 0x0100, + + /// + /// Version 2 is the current version of the Win_Certificate structure. + /// + WIN_CERT_REVISION_2_0 = 0x0200, + } + + public enum WindowsCertificateType : ushort + { + /// + /// bCertificate contains an X.509 Certificate + /// + /// + /// Not Supported + /// + WIN_CERT_TYPE_X509 = 0x0001, + + /// + /// bCertificate contains a PKCS#7 SignedData structure + /// + WIN_CERT_TYPE_PKCS_SIGNED_DATA = 0x0002, + + /// + /// Reserved + /// + WIN_CERT_TYPE_RESERVED_1 = 0x0003, + + /// + /// Terminal Server Protocol Stack Certificate signing + /// + /// + /// Not Supported + /// + WIN_CERT_TYPE_TS_STACK_SIGNED = 0x0004, + } + + public enum WindowsSubsystem : ushort + { + /// + /// An unknown subsystem + /// + IMAGE_SUBSYSTEM_UNKNOWN = 0x0000, + + /// + /// Device drivers and native Windows processes + /// + IMAGE_SUBSYSTEM_NATIVE = 0x0001, + + /// + /// The Windows graphical user interface (GUI) subsystem + /// + IMAGE_SUBSYSTEM_WINDOWS_GUI = 0x0002, + + /// + /// The Windows character subsystem + /// + IMAGE_SUBSYSTEM_WINDOWS_CUI = 0x0003, + + /// + /// The OS/2 character subsystem + /// + IMAGE_SUBSYSTEM_OS2_CUI = 0x0005, + + /// + /// The Posix character subsystem + /// + IMAGE_SUBSYSTEM_POSIX_CUI = 0x0007, + + /// + /// Native Win9x driver + /// + IMAGE_SUBSYSTEM_NATIVE_WINDOWS = 0x0008, + + /// + /// Windows CE + /// + IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 0x0009, + + /// + /// An Extensible Firmware Interface (EFI) application + /// + IMAGE_SUBSYSTEM_EFI_APPLICATION = 0x000A, + + /// + /// An EFI driver with boot services + /// + IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 0x000B, + + /// + /// An EFI driver with run-time services + /// + IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER = 0x000C, + + /// + /// An EFI ROM image + /// + IMAGE_SUBSYSTEM_EFI_ROM = 0x000D, + + /// + /// XBOX + /// + IMAGE_SUBSYSTEM_XBOX = 0x000E, + + /// + /// Windows boot application. + /// + IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION = 0x0010, + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Executable.cs b/SabreTools.Serialization/Models/PortableExecutable/Executable.cs new file mode 100644 index 00000000..5cc08440 --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Executable.cs @@ -0,0 +1,250 @@ +using System.Collections.Generic; + +namespace SabreTools.Serialization.Models.PortableExecutable +{ + /// + /// The following list describes the Microsoft PE executable format, with the + /// base of the image header at the top. The section from the MS-DOS 2.0 + /// Compatible EXE Header through to the unused section just before the PE header + /// is the MS-DOS 2.0 Section, and is used for MS-DOS compatibility only. + /// + /// + public sealed class Executable + { + /// + /// MS-DOS executable stub + /// + public MSDOS.Executable? Stub { get; set; } + + /// + /// After the MS-DOS stub, at the file offset specified at offset 0x3c, is a 4-byte + /// signature that identifies the file as a PE format image file. This signature is "PE\0\0" + /// (the letters "P" and "E" followed by two null bytes). + /// + public string? Signature { get; set; } + + /// + /// File header + /// + public COFF.FileHeader? FileHeader { get; set; } + + /// + /// Microsoft extended optional header + /// + public OptionalHeader? OptionalHeader { get; set; } + + /// + /// Section table + /// + public COFF.SectionHeader[]? SectionTable { get; set; } + + /// + /// Symbol table + /// + public COFF.SymbolTableEntries.BaseEntry[]? SymbolTable { get; set; } + + /// + /// String table + /// + public COFF.StringTable? StringTable { get; set; } + + #region Data Directories + + /// + /// The export data section, named .edata, contains information about symbols that other images + /// can access through dynamic linking. Exported symbols are generally found in DLLs, but DLLs + /// can also import symbols. + /// + /// An overview of the general structure of the export section is described below. The tables + /// described are usually contiguous in the file in the order shown (though this is not + /// required). Only the export directory table and export address table are required to export + /// symbols as ordinals. (An ordinal is an export that is accessed directly by its export + /// address table index.) The name pointer table, ordinal table, and export name table all + /// exist to support use of export names. + /// + /// + #region Export Table (.edata) + + /// + /// A table with just one row (unlike the debug directory). This table indicates the + /// locations and sizes of the other export tables. + /// + public Export.DirectoryTable? ExportDirectoryTable { get; set; } + + /// + /// An array of RVAs of exported symbols. These are the actual addresses of the exported + /// functions and data within the executable code and data sections. Other image files + /// can import a symbol by using an index to this table (an ordinal) or, optionally, by + /// using the public name that corresponds to the ordinal if a public name is defined. + /// + public Export.AddressTableEntry[]? ExportAddressTable { get; set; } + + /// + /// An array of pointers to the public export names, sorted in ascending order. + /// + public Export.NamePointerTable? NamePointerTable { get; set; } + + /// + /// An array of the ordinals that correspond to members of the name pointer table. The + /// correspondence is by position; therefore, the name pointer table and the ordinal table + /// must have the same number of members. Each ordinal is an index into the export address + /// table. + /// + public Export.OrdinalTable? OrdinalTable { get; set; } + + /// + /// A series of null-terminated ASCII strings. Members of the name pointer table point into + /// this area. These names are the public names through which the symbols are imported and + /// exported; they are not necessarily the same as the private names that are used within + /// the image file. + /// + public Export.NameTable? ExportNameTable { get; set; } + + #endregion + + /// + /// All image files that import symbols, including virtually all executable (EXE) files, + /// have an .idata section. A typical file layout for the import information follows: + /// + /// - Directory Table + /// Null Directory Entry + /// - DLL1 Import Lookup Table + /// Null + /// - DLL2 Import Lookup Table + /// Null + /// - DLL3 Import Lookup Table + /// Null + /// - Hint-Name Table + /// + /// + #region Import Table (.idata) and Import Address Table + + /// + /// The import information begins with the import directory table, which describes the + /// remainder of the import information. + /// + public Import.DirectoryTableEntry[]? ImportDirectoryTable { get; set; } + + /// + /// An import lookup table is an array of 32-bit numbers for PE32 or an array of 64-bit + /// numbers for PE32+. + /// + public Dictionary? ImportLookupTables { get; set; } + + /// + /// These addresses are the actual memory addresses of the symbols, although technically + /// they are still called "virtual addresses". + /// + public Dictionary? ImportAddressTables { get; set; } + + /// + /// One hint/name table suffices for the entire import section. + /// + public Import.HintNameTableEntry[]? HintNameTable { get; set; } + + #endregion + + #region Resource Table (.rsrc) + + /// + /// Resource directory table (.rsrc) + /// + public Resource.DirectoryTable? ResourceDirectoryTable { get; set; } + + #endregion + + // TODO: Handle Exception Table + + #region Certificate Table + + /// + /// Attribute certificate table + /// + public AttributeCertificate.Entry[]? AttributeCertificateTable { get; set; } + + #endregion + + #region Base Relocation Table (.reloc) + + /// + /// Base relocation table + /// + public BaseRelocation.Block[]? BaseRelocationTable { get; set; } + + #endregion + + #region Debug Data (.debug*) + + /// + /// Debug table + /// + public DebugData.Table? DebugTable { get; set; } + + #endregion + + // TODO: Handle Architecture + // TODO: Handle Global Ptr + // TODO: Thread Local Storage (.tls) + // TODO: Load Configuration Table + // TODO: Bound Import Table + + #region Delay Load Table + + /// + /// Delay-load directory table + /// + public DelayLoad.DirectoryTable? DelayLoadDirectoryTable { get; set; } + + #endregion + + // TODO: CLR Runtime Header (.cormeta) + // TODO: Reserved + + #endregion + + #region Named Sections + + // TODO: Support grouped sections in section reading and parsing + // https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#grouped-sections-object-only + // Grouped sections are ordered and mean that the data in the sections contributes + // to the "base" section (the one without the "$X" suffix). This may negatively impact + // the use of some of the different types of executables. + + // .cormeta - CLR metadata is stored in this section. It is used to indicate that + // the object file contains managed code. The format of the metadata is not + // documented, but can be handed to the CLR interfaces for handling metadata. + + // .drectve - A section is a directive section if it has the IMAGE_SCN_LNK_INFO + // flag set in the section header and has the .drectve section name. The linker + // removes a .drectve section after processing the information, so the section + // does not appear in the image file that is being linked. + // + // A .drectve section consists of a string of text that can be encoded as ANSI + // or UTF-8. If the UTF-8 byte order marker (BOM, a three-byte prefix that + // consists of 0xEF, 0xBB, and 0xBF) is not present, the directive string is + // interpreted as ANSI. The directive string is a series of linker options that + // are separated by spaces. Each option contains a hyphen, the option name, and + // any appropriate attribute. If an option contains spaces, the option must be + // enclosed in quotes. The .drectve section must not have relocations or line + // numbers. + // + // TODO: Can we implement reading/parsing the .drectve section? + + // .pdata Section - Multiple formats per entry + + // .sxdata - The valid exception handlers of an object are listed in the .sxdata + // section of that object. The section is marked IMAGE_SCN_LNK_INFO. It contains + // the COFF symbol index of each valid handler, using 4 bytes per index. + // + // Additionally, the compiler marks a COFF object as registered SEH by emitting + // the absolute symbol "@feat.00" with the LSB of the value field set to 1. A + // COFF object with no registered SEH handlers would have the "@feat.00" symbol, + // but no .sxdata section. + // + // TODO: Can we implement reading/parsing the .sxdata section? + + #endregion + + // TODO: Determine if "Archive (Library) File Format" is worth modelling + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Export/AddressTableEntry.cs b/SabreTools.Serialization/Models/PortableExecutable/Export/AddressTableEntry.cs new file mode 100644 index 00000000..733f2d4e --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Export/AddressTableEntry.cs @@ -0,0 +1,37 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.PortableExecutable.Export +{ + /// + /// The export address table contains the address of exported entry points + /// and exported data and absolutes. An ordinal number is used as an index + /// into the export address table. + /// + /// Each entry in the export address table is a field that uses one of two + /// formats in the following table. If the address specified is not within + /// the export section (as defined by the address and length that are + /// indicated in the optional header), the field is an export RVA, which is + /// an actual address in code or data. Otherwise, the field is a forwarder RVA, + /// which names a symbol in another DLL. + /// + /// + [StructLayout(LayoutKind.Explicit)] + public sealed class AddressTableEntry + { + /// + /// The address of the exported symbol when loaded into memory, relative to + /// the image base. For example, the address of an exported function. + /// + [FieldOffset(0)] public uint ExportRVA; + + /// + /// The pointer to a null-terminated ASCII string in the export section. This + /// string must be within the range that is given by the export table data + /// directory entry. See Optional Header Data Directories (Image Only). This + /// string gives the DLL name and the name of the export (for example, + /// "MYDLL.expfunc") or the DLL name and the ordinal number of the export + /// (for example, "MYDLL.#27"). + /// + [FieldOffset(0)] public uint ForwarderRVA; + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Export/DirectoryTable.cs b/SabreTools.Serialization/Models/PortableExecutable/Export/DirectoryTable.cs new file mode 100644 index 00000000..a4dbe79d --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Export/DirectoryTable.cs @@ -0,0 +1,78 @@ +namespace SabreTools.Serialization.Models.PortableExecutable.Export +{ + /// + /// The export symbol information begins with the export directory table, + /// which describes the remainder of the export symbol information. The + /// export directory table contains address information that is used to resolve + /// imports to the entry points within this image. + /// + /// + public sealed class DirectoryTable + { + /// + /// Reserved, must be 0. + /// + public uint ExportFlags { get; set; } + + /// + /// The time and date that the export data was created. + /// + public uint TimeDateStamp { get; set; } + + /// + /// The major version number. The major and minor version numbers can be set + /// by the user. + /// + public ushort MajorVersion { get; set; } + + /// + /// The minor version number. + /// + public ushort MinorVersion { get; set; } + + /// + /// The address of the ASCII string that contains the name of the DLL. This + /// address is relative to the image base. + /// + public uint NameRVA { get; set; } + + /// + /// ASCII string that contains the name of the DLL. + /// + public string? Name { get; set; } + + /// + /// The starting ordinal number for exports in this image. This field specifies + /// the starting ordinal number for the export address table. It is usually set + /// to 1. + /// + public uint OrdinalBase { get; set; } + + /// + /// The number of entries in the export address table. + /// + public uint AddressTableEntries { get; set; } + + /// + /// The number of entries in the name pointer table. This is also the number of + /// entries in the ordinal table. + /// + public uint NumberOfNamePointers { get; set; } + + /// + /// The address of the export address table, relative to the image base. + /// + public uint ExportAddressTableRVA { get; set; } + + /// + /// The address of the export name pointer table, relative to the image base. + /// The table size is given by the Number of Name Pointers field. + /// + public uint NamePointerRVA { get; set; } + + /// + /// The address of the ordinal table, relative to the image base. + /// + public uint OrdinalTableRVA { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Export/NamePointerTable.cs b/SabreTools.Serialization/Models/PortableExecutable/Export/NamePointerTable.cs new file mode 100644 index 00000000..108b4768 --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Export/NamePointerTable.cs @@ -0,0 +1,18 @@ +namespace SabreTools.Serialization.Models.PortableExecutable.Export +{ + /// + /// The export name pointer table is an array of addresses (RVAs) into the export name table. + /// The pointers are 32 bits each and are relative to the image base. The pointers are ordered + /// lexically to allow binary searches. + /// + /// An export name is defined only if the export name pointer table contains a pointer to it. + /// + /// + public sealed class NamePointerTable + { + /// + /// The pointers are 32 bits each and are relative to the image base. + /// + public uint[]? Pointers { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Export/NameTable.cs b/SabreTools.Serialization/Models/PortableExecutable/Export/NameTable.cs new file mode 100644 index 00000000..cf8dc35c --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Export/NameTable.cs @@ -0,0 +1,27 @@ +namespace SabreTools.Serialization.Models.PortableExecutable.Export +{ + /// + /// The export name table contains the actual string data that was pointed to by the export + /// name pointer table. The strings in this table are public names that other images can use + /// to import the symbols. These public export names are not necessarily the same as the + /// private symbol names that the symbols have in their own image file and source code, + /// although they can be. + /// + /// Every exported symbol has an ordinal value, which is just the index into the export + /// address table. Use of export names, however, is optional. Some, all, or none of the + /// exported symbols can have export names. For exported symbols that do have export names, + /// corresponding entries in the export name pointer table and export ordinal table work + /// together to associate each name with an ordinal. + /// + /// The structure of the export name table is a series of null-terminated ASCII strings + /// of variable length. + /// + /// + public sealed class NameTable + { + /// + /// A series of null-terminated ASCII strings of variable length. + /// + public string[]? Strings { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Export/OrdinalTable.cs b/SabreTools.Serialization/Models/PortableExecutable/Export/OrdinalTable.cs new file mode 100644 index 00000000..1e189490 --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Export/OrdinalTable.cs @@ -0,0 +1,42 @@ +namespace SabreTools.Serialization.Models.PortableExecutable.Export +{ + /// + /// The export ordinal table is an array of 16-bit unbiased indexes into the export address table. + /// Ordinals are biased by the Ordinal Base field of the export directory table. In other words, + /// the ordinal base must be subtracted from the ordinals to obtain true indexes into the export + /// address table. + /// + /// The export name pointer table and the export ordinal table form two parallel arrays that are + /// separated to allow natural field alignment. These two tables, in effect, operate as one table, + /// in which the Export Name Pointer column points to a public (exported) name and the Export + /// Ordinal column gives the corresponding ordinal for that public name. A member of the export + /// name pointer table and a member of the export ordinal table are associated by having the same + /// position (index) in their respective arrays. + /// + /// Thus, when the export name pointer table is searched and a matching string is found at position + /// i, the algorithm for finding the symbol's RVA and biased ordinal is: + /// + /// i = Search_ExportNamePointerTable(name); + /// ordinal = ExportOrdinalTable[i]; + /// + /// rva = ExportAddressTable[ordinal]; + /// biased_ordinal = ordinal + OrdinalBase; + /// + /// When searching for a symbol by(biased) ordinal, the algorithm for finding the symbol's RVA + /// and name is: + /// + /// ordinal = biased_ordinal - OrdinalBase; + /// i = Search_ExportOrdinalTable(ordinal); + /// + /// rva = ExportAddressTable[ordinal]; + /// name = ExportNameTable[i]; + /// + /// + public sealed class OrdinalTable + { + /// + /// An array of 16-bit unbiased indexes into the export address table + /// + public ushort[]? Indexes { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Import/AddressTableEntry.cs b/SabreTools.Serialization/Models/PortableExecutable/Import/AddressTableEntry.cs new file mode 100644 index 00000000..5d51c0b4 --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Import/AddressTableEntry.cs @@ -0,0 +1,36 @@ +namespace SabreTools.Serialization.Models.PortableExecutable.Import +{ + /// + /// The structure and content of the import address table are identical to those of + /// the import lookup table, until the file is bound. During binding, the entries in + /// the import address table are overwritten with the 32-bit (for PE32) or 64-bit + /// (for PE32+) addresses of the symbols that are being imported. These addresses are + /// the actual memory addresses of the symbols, although technically they are still + /// called "virtual addresses." The loader typically processes the binding. + /// + /// + public sealed class AddressTableEntry + { + /// + /// If this bit is set, import by ordinal. Otherwise, import by name. Bit is + /// masked as 0x80000000 for PE32, 0x8000000000000000 for PE32+. + /// + /// Bit 31/63 + public bool OrdinalNameFlag { get; set; } + + /// + /// A 16-bit ordinal number. This field is used only if the Ordinal/Name Flag + /// bit field is 1 (import by ordinal). Bits 30-15 or 62-15 must be 0. + /// + /// Bits 15-0 + public ushort OrdinalNumber { get; set; } + + /// + /// A 31-bit RVA of a hint/name table entry. This field is used only if the + /// Ordinal/Name Flag bit field is 0 (import by name). For PE32+ bits 62-31 + /// must be zero. + /// + /// Bits 30-0 + public uint HintNameTableRVA { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Import/DirectoryTableEntry.cs b/SabreTools.Serialization/Models/PortableExecutable/Import/DirectoryTableEntry.cs new file mode 100644 index 00000000..ae26b6ea --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Import/DirectoryTableEntry.cs @@ -0,0 +1,50 @@ +namespace SabreTools.Serialization.Models.PortableExecutable.Import +{ + /// + /// The import information begins with the import directory table, which + /// describes the remainder of the import information. The import directory + /// table contains address information that is used to resolve fixup references + /// to the entry points within a DLL image. The import directory table consists + /// of an array of import directory entries, one entry for each DLL to which + /// the image refers. The last directory entry is empty (filled with null values), + /// which indicates the end of the directory table. + /// + /// + public sealed class DirectoryTableEntry + { + /// + /// The RVA of the import lookup table. This table contains a name or ordinal + /// for each import. (The name "Characteristics" is used in Winnt.h, but no + /// longer describes this field.) + /// + public uint ImportLookupTableRVA { get; set; } + + /// + /// The stamp that is set to zero until the image is bound. After the image is + /// bound, this field is set to the time/data stamp of the DLL. + /// + public uint TimeDateStamp { get; set; } + + /// + /// The index of the first forwarder reference. + /// + public uint ForwarderChain { get; set; } + + /// + /// The address of an ASCII string that contains the name of the DLL. This address + /// is relative to the image base. + /// + public uint NameRVA { get; set; } + + /// + /// ASCII string that contains the name of the DLL. + /// + public string? Name { get; set; } + + /// + /// The RVA of the import address table. The contents of this table are identical + /// to the contents of the import lookup table until the image is bound. + /// + public uint ImportAddressTableRVA { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Import/HintNameTableEntry.cs b/SabreTools.Serialization/Models/PortableExecutable/Import/HintNameTableEntry.cs new file mode 100644 index 00000000..50958e9e --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Import/HintNameTableEntry.cs @@ -0,0 +1,27 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.PortableExecutable.Import +{ + /// + /// One hint/name table suffices for the entire import section. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class HintNameTableEntry + { + /// + /// An index into the export name pointer table. A match is attempted first + /// with this value. If it fails, a binary search is performed on the DLL's + /// export name pointer table. + /// + public ushort Hint; + + /// + /// An ASCII string that contains the name to import. This is the string that + /// must be matched to the public name in the DLL. This string is case sensitive + /// and terminated by a null byte. + /// + [MarshalAs(UnmanagedType.LPStr)] + public string? Name; + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Import/LookupTableEntry.cs b/SabreTools.Serialization/Models/PortableExecutable/Import/LookupTableEntry.cs new file mode 100644 index 00000000..2179e071 --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Import/LookupTableEntry.cs @@ -0,0 +1,36 @@ +namespace SabreTools.Serialization.Models.PortableExecutable.Import +{ + /// + /// An import lookup table is an array of 32-bit numbers for PE32 or an array of + /// 64-bit numbers for PE32+. Each entry uses the bit-field format that is described + /// in the following table. In this format, bit 31 is the most significant bit for + /// PE32 and bit 63 is the most significant bit for PE32+. The collection of these + /// entries describes all imports from a given DLL. The last entry is set to zero + /// (NULL) to indicate the end of the table. + /// + /// + public sealed class LookupTableEntry + { + /// + /// If this bit is set, import by ordinal. Otherwise, import by name. Bit is + /// masked as 0x80000000 for PE32, 0x8000000000000000 for PE32+. + /// + /// Bit 31/63 + public bool OrdinalNameFlag { get; set; } + + /// + /// A 16-bit ordinal number. This field is used only if the Ordinal/Name Flag + /// bit field is 1 (import by ordinal). Bits 30-15 or 62-15 must be 0. + /// + /// Bits 15-0 + public ushort OrdinalNumber { get; set; } + + /// + /// A 31-bit RVA of a hint/name table entry. This field is used only if the + /// Ordinal/Name Flag bit field is 0 (import by name). For PE32+ bits 62-31 + /// must be zero. + /// + /// Bits 30-0 + public uint HintNameTableRVA { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/LoadConfiguration/Directory.cs b/SabreTools.Serialization/Models/PortableExecutable/LoadConfiguration/Directory.cs new file mode 100644 index 00000000..f1af9a8d --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/LoadConfiguration/Directory.cs @@ -0,0 +1,189 @@ +namespace SabreTools.Serialization.Models.PortableExecutable.LoadConfiguration +{ + /// + /// The data directory entry for a pre-reserved SEH load configuration + /// structure must specify a particular size of the load configuration + /// structure because the operating system loader always expects it to + /// be a certain value. In that regard, the size is really only a + /// version check. For compatibility with Windows XP and earlier versions + /// of Windows, the size must be 64 for x86 images. + /// + /// + public sealed class Directory + { + /// + /// Flags that indicate attributes of the file, currently unused. + /// + public uint Characteristics { get; set; } + + /// + /// Date and time stamp value. The value is represented in the number of + /// seconds that have elapsed since midnight (00:00:00), January 1, 1970, + /// Universal Coordinated Time, according to the system clock. The time + /// stamp can be printed by using the C runtime (CRT) time function. + /// + public uint TimeDateStamp { get; set; } + + /// + /// Major version number. + /// + public ushort MajorVersion { get; set; } + + /// + /// Minor version number. + /// + public ushort MinorVersion { get; set; } + + /// + /// The global loader flags to clear for this process as the loader starts + /// the process. + /// + public uint GlobalFlagsClear { get; set; } + + /// + /// The global loader flags to set for this process as the loader starts + /// the process. + /// + public uint GlobalFlagsSet { get; set; } + + /// + /// Memory that must be freed before it is returned to the system, in bytes. + /// + /// This value is 32-bit if PE32 and 64-bit if PE32+ + public ulong DeCommitFreeBlockThreshold { get; set; } + + /// + /// Total amount of free memory, in bytes. + /// + /// This value is 32-bit if PE32 and 64-bit if PE32+ + public ulong DeCommitTotalFreeThreshold { get; set; } + + /// + /// [x86 only] The VA of a list of addresses where the LOCK prefix is used so + /// that they can be replaced with NOP on single processor machines. + /// + /// This value is 32-bit if PE32 and 64-bit if PE32+ + public ulong LockPrefixTable { get; set; } + + /// + /// Maximum allocation size, in bytes. + /// + /// This value is 32-bit if PE32 and 64-bit if PE32+ + public ulong MaximumAllocationSize { get; set; } + + /// + /// Maximum virtual memory size, in bytes. + /// + /// This value is 32-bit if PE32 and 64-bit if PE32+ + public ulong VirtualMemoryThreshold { get; set; } + + /// + /// Setting this field to a non-zero value is equivalent to calling + /// SetProcessAffinityMask with this value during process startup (.exe only) + /// + /// This value is 32-bit if PE32 and 64-bit if PE32+ + public ulong ProcessAffinityMask { get; set; } + + /// + /// Process heap flags that correspond to the first argument of the + /// HeapCreate function. These flags apply to the process heap that + /// is created during process startup. + /// + public uint ProcessHeapFlags { get; set; } + + /// + /// The service pack version identifier. + /// + public ushort CSDVersion { get; set; } + + /// + /// Must be zero. + /// + public ushort Reserved { get; set; } + + /// + /// Reserved for use by the system. + /// + /// This value is 32-bit if PE32 and 64-bit if PE32+ + public ulong EditList { get; set; } + + // + /// A pointer to a cookie that is used by Visual C++ or GS implementation. + /// + /// This value is 32-bit if PE32 and 64-bit if PE32+ + public ulong SecurityCookie { get; set; } + + /// + /// [x86 only] The VA of the sorted table of RVAs of each valid, unique + /// SE handler in the image. + /// + /// This value is 32-bit if PE32 and 64-bit if PE32+ + public ulong SEHandlerTable { get; set; } + + /// + /// [x86 only] The count of unique handlers in the table. + /// + /// This value is 32-bit if PE32 and 64-bit if PE32+ + public ulong SEHandlerCount { get; set; } + + /// + /// The VA where Control Flow Guard check-function pointer is stored. + /// + /// This value is 32-bit if PE32 and 64-bit if PE32+ + public ulong GuardCFCheckFunctionPointer { get; set; } + + /// + /// The VA where Control Flow Guard dispatch-function pointer is stored. + /// + /// This value is 32-bit if PE32 and 64-bit if PE32+ + public ulong GuardCFDispatchFunctionPointer { get; set; } + + /// + /// The VA of the sorted table of RVAs of each Control Flow Guard + /// function in the image. + /// + /// This value is 32-bit if PE32 and 64-bit if PE32+ + public ulong GuardCFFunctionTable { get; set; } + + /// + /// The count of unique RVAs in the above table. + /// + /// This value is 32-bit if PE32 and 64-bit if PE32+ + public ulong GuardCFFunctionCount { get; set; } + + /// + /// Control Flow Guard related flags. + /// + public GuardFlags GuardFlags { get; set; } + + /// + /// Code integrity information. + /// + /// 12 bytes + public byte[]? CodeIntegrity { get; set; } + + /// + /// The VA where Control Flow Guard address taken IAT table is stored. + /// + /// This value is 32-bit if PE32 and 64-bit if PE32+ + public ulong GuardAddressTakenIatEntryTable { get; set; } + + /// + /// The count of unique RVAs in the above table. + /// + /// This value is 32-bit if PE32 and 64-bit if PE32+ + public ulong GuardAddressTakenIatEntryCount { get; set; } + + /// + /// The VA where Control Flow Guard long jump target table is stored. + /// + /// This value is 32-bit if PE32 and 64-bit if PE32+ + public ulong GuardLongJumpTargetTable { get; set; } + + /// + /// The count of unique RVAs in the above table. + /// + /// This value is 32-bit if PE32 and 64-bit if PE32+ + public ulong GuardLongJumpTargetCount { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/OptionalHeader.cs b/SabreTools.Serialization/Models/PortableExecutable/OptionalHeader.cs new file mode 100644 index 00000000..f947f436 --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/OptionalHeader.cs @@ -0,0 +1,245 @@ +namespace SabreTools.Serialization.Models.PortableExecutable +{ + /// + /// Every image file has an optional header that provides information to the loader. + /// This header is optional in the sense that some files (specifically, object files) + /// do not have it. For image files, this header is required. An object file can have + /// an optional header, but generally this header has no function in an object file + /// except to increase its size. + /// + /// Note that the size of the optional header is not fixed. The SizeOfOptionalHeader + /// field in the COFF header must be used to validate that a probe into the file for + /// a particular data directory does not go beyond SizeOfOptionalHeader. + /// + /// The NumberOfRvaAndSizes field of the optional header should also be used to ensure + /// that no probe for a particular data directory entry goes beyond the optional header. + /// In addition, it is important to validate the optional header magic number for format + /// compatibility. + /// + /// The optional header magic number determines whether an image is a PE32 or + /// PE32+ executable. + /// + /// PE32+ images allow for a 64-bit address space while limiting the image size to + /// 2 gigabytes. Other PE32+ modifications are addressed in their respective sections. + /// + /// The first eight fields of the optional header are standard fields that are defined + /// for every implementation of COFF. These fields contain general information that is + /// useful for loading and running an executable file. They are unchanged for the + /// PE32+ format. + /// + /// + public sealed class OptionalHeader : COFF.OptionalHeader + { + /// + /// The preferred address of the first byte of image when loaded into memory { get; set; } + /// must be a multiple of 64 K. The default for DLLs is 0x10000000. The default + /// for Windows CE EXEs is 0x00010000. The default for Windows NT, Windows 2000, + /// Windows XP, Windows 95, Windows 98, and Windows Me is 0x00400000. + /// + /// This value is 32-bit if PE32 and 64-bit if PE32+ + public ulong ImageBase { get; set; } + + /// + /// The alignment (in bytes) of sections when they are loaded into memory. It must + /// be greater than or equal to FileAlignment. The default is the page size for + /// the architecture. + /// + public uint SectionAlignment { get; set; } + + /// + /// The alignment factor (in bytes) that is used to align the raw data of sections + /// in the image file. The value should be a power of 2 between 512 and 64 K, + /// inclusive. The default is 512. If the SectionAlignment is less than the + /// architecture's page size, then FileAlignment must match SectionAlignment. + /// + public uint FileAlignment { get; set; } + + /// + /// The major version number of the required operating system. + /// + public ushort MajorOperatingSystemVersion { get; set; } + + /// + /// The minor version number of the required operating system. + /// + public ushort MinorOperatingSystemVersion { get; set; } + + /// + /// The major version number of the image. + /// + public ushort MajorImageVersion { get; set; } + + /// + /// The minor version number of the image. + /// + public ushort MinorImageVersion { get; set; } + + /// + /// The major version number of the subsystem. + /// + public ushort MajorSubsystemVersion { get; set; } + + /// + /// The minor version number of the subsystem. + /// + public ushort MinorSubsystemVersion { get; set; } + + /// + /// Reserved, must be zero. + /// + public uint Win32VersionValue { get; set; } + + /// + /// The size (in bytes) of the image, including all headers, as the image + /// is loaded in memory. It must be a multiple of SectionAlignment. + /// + public uint SizeOfImage { get; set; } + + /// + /// The combined size of an MS-DOS stub, PE header, and section headers rounded + /// up to a multiple of FileAlignment. + /// + public uint SizeOfHeaders { get; set; } + + /// + /// The image file checksum. The algorithm for computing the checksum is + /// incorporated into IMAGHELP.DLL. The following are checked for validation at + /// load time: all drivers, any DLL loaded at boot time, and any DLL that is + /// loaded into a critical Windows process. + /// + public uint CheckSum { get; set; } + + /// + /// The subsystem that is required to run this image. + /// + public WindowsSubsystem Subsystem { get; set; } + + /// + /// DLL characteristics + /// + public DllCharacteristics DllCharacteristics { get; set; } + + /// + /// The size of the stack to reserve. Only SizeOfStackCommit is committed; the rest + /// is made available one page at a time until the reserve size is reached. + /// + /// This value is 32-bit if PE32 and 64-bit if PE32+ + public ulong SizeOfStackReserve { get; set; } + + /// + /// The size of the stack to commit. + /// + /// This value is 32-bit if PE32 and 64-bit if PE32+ + public ulong SizeOfStackCommit { get; set; } + + /// + /// The size of the local heap space to reserve. Only SizeOfHeapCommit is + /// committed; the rest is made available one page at a time until the reserve + /// size is reached. + /// + /// This value is 32-bit if PE32 and 64-bit if PE32+ + public ulong SizeOfHeapReserve { get; set; } + + /// + /// The size of the local heap space to commit. + /// + /// This value is 32-bit if PE32 and 64-bit if PE32+ + public ulong SizeOfHeapCommit { get; set; } + + /// + /// Reserved, must be zero. + /// + public uint LoaderFlags { get; set; } + + /// + /// The number of data-directory entries in the remainder of the optional header. + /// Each describes a location and size. + /// + public uint NumberOfRvaAndSizes { get; set; } + + #region Data Directories (Image Only) + + /// + /// The export table address and size. + /// + public DataDirectory? ExportTable { get; set; } + + /// + /// The import table address and size. + /// + public DataDirectory? ImportTable { get; set; } + + /// + /// The resource table address and size. + /// + public DataDirectory? ResourceTable { get; set; } + + /// + /// The exception table address and size. + /// + public DataDirectory? ExceptionTable { get; set; } + + /// + /// The attribute certificate table address and size. + /// + public DataDirectory? CertificateTable { get; set; } + + /// + /// The base relocation table address and size. + /// + public DataDirectory? BaseRelocationTable { get; set; } + + /// + /// The debug data starting address and size. + /// + public DataDirectory? Debug { get; set; } + + /// + /// Reserved, must be 0 + /// + public ulong Architecture { get; set; } + + /// + /// The RVA of the value to be stored in the global pointer register. + /// The size member of this structure must be set to zero. + /// + public DataDirectory? GlobalPtr { get; set; } + + /// + /// The thread local storage (TLS) table address and size. + /// + public DataDirectory? ThreadLocalStorageTable { get; set; } + + /// + /// The load configuration table address and size. + /// + public DataDirectory? LoadConfigTable { get; set; } + + /// + /// The bound import table address and size. + /// + public DataDirectory? BoundImport { get; set; } + + /// + /// The import address table address and size + /// + public DataDirectory? ImportAddressTable { get; set; } + + /// + /// The delay import descriptor address and size. + /// + public DataDirectory? DelayImportDescriptor { get; set; } + + /// + /// The CLR runtime header address and size. + /// + public DataDirectory? CLRRuntimeHeader { get; set; } + + /// + /// Reserved, must be zero + /// + public ulong Reserved { get; set; } + + #endregion + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Resource/DataEntry.cs b/SabreTools.Serialization/Models/PortableExecutable/Resource/DataEntry.cs new file mode 100644 index 00000000..b0b6c8ce --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Resource/DataEntry.cs @@ -0,0 +1,40 @@ +namespace SabreTools.Serialization.Models.PortableExecutable.Resource +{ + /// + /// The resource directory string area consists of Unicode strings, which + /// are word-aligned. These strings are stored together after the last + /// Resource Directory entry and before the first Resource Data entry. + /// This minimizes the impact of these variable-length strings on the + /// alignment of the fixed-size directory entries. + /// + /// + public sealed class DataEntry + { + /// + /// The address of a unit of resource data in the Resource Data area. + /// + public uint DataRVA { get; set; } + + /// + /// The size, in bytes, of the resource data that is pointed to by the + /// Data RVA field. + /// + public uint Size { get; set; } + + /// + /// The resource data that is pointed to by the Data RVA field. + /// + public byte[]? Data { get; set; } + + /// + /// The code page that is used to decode code point values within the + /// resource data. Typically, the code page would be the Unicode code page. + /// + public uint Codepage { get; set; } + + /// + /// Reserved, must be 0. + /// + public uint Reserved { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Resource/DirectoryEntry.cs b/SabreTools.Serialization/Models/PortableExecutable/Resource/DirectoryEntry.cs new file mode 100644 index 00000000..47f7cd0b --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Resource/DirectoryEntry.cs @@ -0,0 +1,68 @@ +namespace SabreTools.Serialization.Models.PortableExecutable.Resource +{ + /// + /// A leaf's Type, Name, and Language IDs are determined by the path that is + /// taken through directory tables to reach the leaf. The first table + /// determines Type ID, the second table (pointed to by the directory entry + /// in the first table) determines Name ID, and the third table determines + /// Language ID. + /// + /// The directory entries make up the rows of a table. Each resource directory + /// entry has the following format. Whether the entry is a Name or ID entry + /// is indicated by the resource directory table, which indicates how many + /// Name and ID entries follow it (remember that all the Name entries precede + /// all the ID entries for the table). All entries for the table are sorted + /// in ascending order: the Name entries by case-sensitive string and the ID + /// entries by numeric value. Offsets are relative to the address in the + /// IMAGE_DIRECTORY_ENTRY_RESOURCE DataDirectory. + /// + /// + public sealed class DirectoryEntry + { + #region Offset 0x00 + + /// + /// The offset of a string that gives the Type, Name, or Language ID entry, + /// depending on level of table. + /// + public uint NameOffset { get; set; } + + /// + /// A string that gives the Type, Name, or Language ID entry, depending on + /// level of table. + /// + public DirectoryString? Name { get; set; } + + /// + /// A 32-bit integer that identifies the Type, Name, or Language ID entry. + /// + public uint IntegerID { get; set; } + + #endregion + + #region Offset 0x04 + + /// + /// High bit 0. Address of a Resource Data entry (a leaf). + /// + public uint DataEntryOffset { get; set; } + + /// + /// Resource data entry (a leaf). + /// + public DataEntry? DataEntry { get; set; } + + /// + /// High bit 1. The lower 31 bits are the address of another resource + /// directory table (the next level down). + /// + public uint SubdirectoryOffset { get; set; } + + /// + /// Another resource directory table (the next level down). + /// + public DirectoryTable? Subdirectory { get; set; } + + #endregion + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Resource/DirectoryString.cs b/SabreTools.Serialization/Models/PortableExecutable/Resource/DirectoryString.cs new file mode 100644 index 00000000..4ea26f4b --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Resource/DirectoryString.cs @@ -0,0 +1,23 @@ +namespace SabreTools.Serialization.Models.PortableExecutable.Resource +{ + /// + /// The resource directory string area consists of Unicode strings, which + /// are word-aligned. These strings are stored together after the last + /// Resource Directory entry and before the first Resource Data entry. + /// This minimizes the impact of these variable-length strings on the + /// alignment of the fixed-size directory entries. + /// + /// + public sealed class DirectoryString + { + /// + /// The size of the string, not including length field itself. + /// + public ushort Length { get; set; } // TODO: Remove in lieu of BStr + + /// + /// The variable-length Unicode string data, word-aligned. + /// + public byte[]? UnicodeString { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Resource/DirectoryTable.cs b/SabreTools.Serialization/Models/PortableExecutable/Resource/DirectoryTable.cs new file mode 100644 index 00000000..8b9da20e --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Resource/DirectoryTable.cs @@ -0,0 +1,59 @@ +namespace SabreTools.Serialization.Models.PortableExecutable.Resource +{ + /// + /// Each directory table is followed by a series of directory entries that + /// give the name or identifier (ID) for that level (Type, Name, or Language + /// level) and an address of either a data description or another directory + /// table. If the address points to a data description, then the data is a + /// leaf in the tree. If the address points to another directory table, + /// then that table lists directory entries at the next level down. + /// + /// Each resource directory table has the following format. This data + /// structure should be considered the heading of a table because the table + /// actually consists of directory entries. + /// + /// + public sealed class DirectoryTable + { + /// + /// Resource flags. This field is reserved for future use. It is currently + /// set to zero. + /// + public uint Characteristics { get; set; } + + /// + /// The time that the resource data was created by the resource compiler. + /// + public uint TimeDateStamp { get; set; } + + /// + /// The major version number, set by the user. + /// + public ushort MajorVersion { get; set; } + + /// + /// The minor version number, set by the user. + /// + public ushort MinorVersion { get; set; } + + /// + /// The number of directory entries immediately following the table that use + /// strings to identify Type, Name, or Language entries (depending on the + /// level of the table). + /// + public ushort NumberOfNameEntries { get; set; } + + /// + /// The number of directory entries immediately following the Name entries that + /// use numeric IDs for Type, Name, or Language entries. + /// + public ushort NumberOfIDEntries { get; set; } + + /// + /// Directory entries immediately following the table that use + /// strings to identify Type, Name, or Language entries (depending on the + /// level of the table). + /// + public DirectoryEntry[]? Entries { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/AcceleratorTable.cs b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/AcceleratorTable.cs new file mode 100644 index 00000000..b6e592e3 --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/AcceleratorTable.cs @@ -0,0 +1,19 @@ + +namespace SabreTools.Serialization.Models.PortableExecutable.Resource.Entries +{ + /// + /// The ACCELTABLEENTRY structure is repeated for all accelerator table entries in the resource. + /// The last entry in the table is flagged with the value 0x0080. + /// + /// You can compute the number of elements in the table if you divide the length of the resource + /// by eight. Then your application can randomly access the individual fixed-length entries. + /// + /// + public sealed class AcceleratorTable + { + /// + /// Accelerator table entries + /// + public AcceleratorTableEntry[]? Entries { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/AcceleratorTableEntry.cs b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/AcceleratorTableEntry.cs new file mode 100644 index 00000000..30f8fc50 --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/AcceleratorTableEntry.cs @@ -0,0 +1,35 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.PortableExecutable.Resource.Entries +{ + /// + /// Describes the data in an individual accelerator table resource. The structure definition + /// provided here is for explanation only; it is not present in any standard header file. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class AcceleratorTableEntry + { + /// + /// Describes keyboard accelerator characteristics. + /// + [MarshalAs(UnmanagedType.U2)] + public AcceleratorTableFlags Flags; + + /// + /// An ANSI character value or a virtual-key code that identifies the accelerator key. + /// + public ushort Ansi; + + /// + /// An identifier for the keyboard accelerator. This is the value passed to the window + /// procedure when the user presses the specified key. + /// + public ushort Id; + + /// + /// The number of bytes inserted to ensure that the structure is aligned on a DWORD boundary. + /// + public ushort Padding; + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/AssemblyManifest.cs b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/AssemblyManifest.cs new file mode 100644 index 00000000..f7c35c3d --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/AssemblyManifest.cs @@ -0,0 +1,390 @@ +using System.Xml.Serialization; + +namespace SabreTools.Serialization.Models.PortableExecutable.Resource.Entries +{ + /// + [XmlRoot(ElementName = "assembly", Namespace = "urn:schemas-microsoft-com:asm.v1")] + public sealed class AssemblyManifest + { + [XmlAttribute("manifestVersion")] + public string? ManifestVersion { get; set; } + + #region Group + + [XmlElement("assemblyIdentity")] + public AssemblyIdentity[]? AssemblyIdentities { get; set; } + + [XmlElement("noInheritable")] + public AssemblyNoInheritable[]? NoInheritables { get; set; } + + #endregion + + #region Group + + [XmlElement("description")] + public AssemblyDescription? Description { get; set; } + + [XmlElement("noInherit")] + public AssemblyNoInherit? NoInherit { get; set; } + + //[XmlElement("noInheritable")] + //public AssemblyNoInheritable NoInheritable { get; set; } + + [XmlElement("comInterfaceExternalProxyStub")] + public AssemblyCOMInterfaceExternalProxyStub[]? COMInterfaceExternalProxyStub { get; set; } + + [XmlElement("dependency")] + public AssemblyDependency[]? Dependency { get; set; } + + [XmlElement("file")] + public AssemblyFile[]? File { get; set; } + + [XmlElement("clrClass")] + public AssemblyCommonLanguageRuntimeClass[]? CLRClass { get; set; } + + [XmlElement("clrSurrogate")] + public AssemblyCommonLanguageSurrogateClass[]? CLRSurrogate { get; set; } + + #endregion + + [XmlAnyElement] + public object[]? EverythingElse { get; set; } + } + + /// + public sealed class AssemblyActiveCodePage + { + [XmlText] + public string? Value { get; set; } + } + + /// + public sealed class AssemblyAutoElevate + { + [XmlText] + public string? Value { get; set; } + } + + /// + public sealed class AssemblyBindingRedirect + { + [XmlAttribute("oldVersion")] + public string? OldVersion { get; set; } + + [XmlAttribute("newVersion")] + public string? NewVersion { get; set; } + } + + /// + public sealed class AssemblyCOMClass + { + [XmlAttribute("clsid")] + public string? CLSID { get; set; } + + [XmlAttribute("threadingModel")] + public string? ThreadingModel { get; set; } + + [XmlAttribute("progid")] + public string? ProgID { get; set; } + + [XmlAttribute("tlbid")] + public string? TLBID { get; set; } + + [XmlAttribute("description")] + public string? Description { get; set; } + + [XmlElement("progid")] + public AssemblyProgID[]? ProgIDs { get; set; } + } + + /// + public sealed class AssemblyCOMInterfaceExternalProxyStub + { + [XmlAttribute("iid")] + public string? IID { get; set; } + + [XmlAttribute("name")] + public string? Name { get; set; } + + [XmlAttribute("tlbid")] + public string? TLBID { get; set; } + + [XmlAttribute("numMethods")] + public string? NumMethods { get; set; } + + [XmlAttribute("proxyStubClsid32")] + public string? ProxyStubClsid32 { get; set; } + + [XmlAttribute("baseInterface")] + public string? BaseInterface { get; set; } + } + + /// + public sealed class AssemblyCOMInterfaceProxyStub + { + [XmlAttribute("iid")] + public string? IID { get; set; } + + [XmlAttribute("name")] + public string? Name { get; set; } + + [XmlAttribute("tlbid")] + public string? TLBID { get; set; } + + [XmlAttribute("numMethods")] + public string? NumMethods { get; set; } + + [XmlAttribute("proxyStubClsid32")] + public string? ProxyStubClsid32 { get; set; } + + [XmlAttribute("baseInterface")] + public string? BaseInterface { get; set; } + } + + /// + public sealed class AssemblyCommonLanguageRuntimeClass + { + [XmlAttribute("name")] + public string? Name { get; set; } + + [XmlAttribute("clsid")] + public string? CLSID { get; set; } + + [XmlAttribute("progid")] + public string? ProgID { get; set; } + + [XmlAttribute("tlbid")] + public string? TLBID { get; set; } + + [XmlAttribute("description")] + public string? Description { get; set; } + + [XmlAttribute("runtimeVersion")] + public string? RuntimeVersion { get; set; } + + [XmlAttribute("threadingModel")] + public string? ThreadingModel { get; set; } + + [XmlElement("progid")] + public AssemblyProgID[]? ProgIDs { get; set; } + } + + /// + public sealed class AssemblyCommonLanguageSurrogateClass + { + [XmlAttribute("clsid")] + public string? CLSID { get; set; } + + [XmlAttribute("name")] + public string? Name { get; set; } + + [XmlAttribute("runtimeVersion")] + public string? RuntimeVersion { get; set; } + } + + /// + public sealed class AssemblyDependency + { + [XmlElement("dependentAssembly")] + public AssemblyDependentAssembly? DependentAssembly { get; set; } + + [XmlAttribute("optional")] + public string? Optional { get; set; } + } + + /// + public sealed class AssemblyDependentAssembly + { + [XmlElement("assemblyIdentity")] + public AssemblyIdentity? AssemblyIdentity { get; set; } + + [XmlElement("bindingRedirect")] + public AssemblyBindingRedirect[]? BindingRedirect { get; set; } + } + + /// + public sealed class AssemblyDescription + { + [XmlText] + public string? Value { get; set; } + } + + /// + public sealed class AssemblyDisableTheming + { + [XmlText] + public string? Value { get; set; } + } + + /// + public sealed class AssemblyDisableWindowFiltering + { + [XmlText] + public string? Value { get; set; } + } + + /// + public sealed class AssemblyDPIAware + { + [XmlText] + public string? Value { get; set; } + } + + /// + public sealed class AssemblyDPIAwareness + { + [XmlText] + public string? Value { get; set; } + } + + /// + public sealed class AssemblyFile + { + [XmlAttribute("name")] + public string? Name { get; set; } + + [XmlAttribute("hash")] + public string? Hash { get; set; } + + [XmlAttribute("hashalg")] + public string? HashAlgorithm { get; set; } + + [XmlAttribute("size")] + public string? Size { get; set; } + + #region Group + + [XmlElement("comClass")] + public AssemblyCOMClass[]? COMClass { get; set; } + + [XmlElement("comInterfaceProxyStub")] + public AssemblyCOMInterfaceProxyStub[]? COMInterfaceProxyStub { get; set; } + + [XmlElement("typelib")] + public AssemblyTypeLib[]? Typelib { get; set; } + + [XmlElement("windowClass")] + public AssemblyWindowClass[]? WindowClass { get; set; } + + #endregion + } + + /// + public sealed class AssemblyGDIScaling + { + [XmlText] + public string? Value { get; set; } + } + + /// + public sealed class AssemblyHeapType + { + [XmlText] + public string? Value { get; set; } + } + + /// + public sealed class AssemblyHighResolutionScrollingAware + { + [XmlText] + public string? Value { get; set; } + } + + /// + public sealed class AssemblyIdentity + { + [XmlAttribute("name")] + public string? Name { get; set; } + + [XmlAttribute("version")] + public string? Version { get; set; } + + [XmlAttribute("type")] + public string? Type { get; set; } + + [XmlAttribute("processorArchitecture")] + public string? ProcessorArchitecture { get; set; } + + [XmlAttribute("publicKeyToken")] + public string? PublicKeyToken { get; set; } + + [XmlAttribute("language")] + public string? Language { get; set; } + } + + /// + public sealed class AssemblyLongPathAware + { + [XmlText] + public string? Value { get; set; } + } + + /// + public sealed class AssemblyNoInherit + { + } + + /// + public sealed class AssemblyNoInheritable + { + } + + /// + public sealed class AssemblyPrinterDriverIsolation + { + [XmlText] + public string? Value { get; set; } + } + + /// + public sealed class AssemblyProgID + { + [XmlText] + public string? Value { get; set; } + } + + /// + public sealed class AssemblySupportedOS + { + [XmlAttribute("Id")] + public string? Id { get; set; } + } + + /// + public sealed class AssemblyTypeLib + { + [XmlElement("tlbid")] + public string? TLBID { get; set; } + + [XmlElement("version")] + public string? Version { get; set; } + + [XmlElement("helpdir")] + public string? HelpDir { get; set; } + + [XmlElement("resourceid")] + public string? ResourceID { get; set; } + + [XmlElement("flags")] + public string? Flags { get; set; } + } + + /// + public sealed class AssemblyUltraHighResolutionScrollingAware + { + [XmlText] + public string? Value { get; set; } + } + + /// + public sealed class AssemblyWindowClass + { + [XmlAttribute("versioned")] + public string? Versioned { get; set; } + + [XmlText] + public string? Value { get; set; } + } + + // TODO: Left off at +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/CursorAndIconResource.cs b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/CursorAndIconResource.cs new file mode 100644 index 00000000..8c94d538 --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/CursorAndIconResource.cs @@ -0,0 +1,40 @@ +namespace SabreTools.Serialization.Models.PortableExecutable.Resource.Entries +{ + /// + /// The system handles each icon and cursor as a single file. However, these are stored in + /// .res files and in executable files as a group of icon resources or a group of cursor + /// resources. The file formats of icon and cursor resources are similar. In the .res file + /// a resource group header follows all of the individual icon or cursor group components. + /// + /// The format of each icon component closely resembles the format of the .ico file. Each + /// icon image is stored in a BITMAPINFO structure followed by the color device-independent + /// bitmap (DIB) bits of the icon's XOR mask. The monochrome DIB bits of the icon's AND + /// mask follow the color DIB bits. + /// + /// The format of each cursor component resembles the format of the .cur file. Each cursor + /// image is stored in a BITMAPINFO structure followed by the monochrome DIB bits of the + /// cursor's XOR mask, and then by the monochrome DIB bits of the cursor's AND mask. Note + /// that there is a difference in the bitmaps of the two resources: Unlike icons, cursor + /// XOR masks do not have color DIB bits. Although the bitmaps of the cursor masks are + /// monochrome and do not have DIB headers or color tables, the bits are still in DIB + /// format with respect to alignment and direction. Another significant difference + /// between cursors and icons is that cursors have a hotspot and icons do not. + /// + /// The group header for both icon and cursor resources consists of a NEWHEADER structure + /// plus one or more RESDIR structures. There is one RESDIR structure for each icon or + /// cursor. The group header contains the information an application needs to select the + /// correct icon or cursor to display. Both the group header and the data that repeats for + /// each icon or cursor in the group have a fixed length. This allows the application to + /// randomly access the information. + /// + /// + public sealed class CursorAndIconResource + { + /// + /// Describes keyboard accelerator characteristics. + /// + public NewHeader? NEWHEADER { get; set; } + + // TODO: Add array of entries in the resource + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/DialogBoxResource.cs b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/DialogBoxResource.cs new file mode 100644 index 00000000..48e16e9b --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/DialogBoxResource.cs @@ -0,0 +1,46 @@ +namespace SabreTools.Serialization.Models.PortableExecutable.Resource.Entries +{ + /// + /// A dialog box is also one resource entry in the resource file. It consists of one + /// DLGTEMPLATE dialog box header structure plus one DLGITEMTEMPLATE structure for each + /// control in the dialog box. The DLGTEMPLATEEX and the DLGITEMTEMPLATEEX structures + /// describe the format of extended dialog box resources. + /// + /// + public sealed class DialogBoxResource + { + #region Dialog template + + /// + /// Dialog box header structure + /// + public DialogTemplate? DialogTemplate { get; set; } + + /// + /// Dialog box extended header structure + /// + public DialogTemplateExtended? ExtendedDialogTemplate { get; set; } + + #endregion + + #region Dialog item templates + + /// + /// Following the DLGTEMPLATE header in a standard dialog box template are one or more + /// DLGITEMTEMPLATE structures that define the dimensions and style of the controls in the dialog + /// box. The cdit member specifies the number of DLGITEMTEMPLATE structures in the template. + /// These DLGITEMTEMPLATE structures must be aligned on DWORD boundaries. + /// + public DialogItemTemplate[]? DialogItemTemplates { get; set; } + + /// + /// Following the DLGTEMPLATEEX header in an extended dialog box template is one or more + /// DLGITEMTEMPLATEEX structures that describe the controls of the dialog box. The cDlgItems + /// member of the DLGITEMTEMPLATEEX structure specifies the number of DLGITEMTEMPLATEEX + /// structures that follow in the template. + /// + public DialogItemTemplateExtended[]? ExtendedDialogItemTemplates { get; set; } + + #endregion + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/DialogItemTemplate.cs b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/DialogItemTemplate.cs new file mode 100644 index 00000000..2fbce08e --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/DialogItemTemplate.cs @@ -0,0 +1,130 @@ +namespace SabreTools.Serialization.Models.PortableExecutable.Resource.Entries +{ + /// + /// Defines the dimensions and style of a control in a dialog box. One or more of these + /// structures are combined with a DLGTEMPLATE structure to form a standard template + /// for a dialog box. + /// + /// + public sealed class DialogItemTemplate + { + /// + /// The style of the control. This member can be a combination of window style values + /// (such as WS_BORDER) and one or more of the control style values (such as + /// BS_PUSHBUTTON and ES_LEFT). + /// + public WindowStyles Style { get; set; } + + /// + /// The extended styles for a window. This member is not used to create dialog boxes, + /// but applications that use dialog box templates can use it to create other types + /// of windows. + /// + public ExtendedWindowStyles ExtendedStyle { get; set; } + + /// + /// The x-coordinate, in dialog box units, of the upper-left corner of the control. + /// This coordinate is always relative to the upper-left corner of the dialog box's + /// client area. + /// + /// + /// The x, y, cx, and cy members specify values in dialog box units. You can convert these values to screen + /// units (pixels) by using the MapDialogRect function. + /// + public short PositionX { get; set; } + + /// + /// The y-coordinate, in dialog box units, of the upper-left corner of the control. + /// This coordinate is always relative to the upper-left corner of the dialog box's + /// client area. + /// + /// + /// The x, y, cx, and cy members specify values in dialog box units. You can convert these values to screen + /// units (pixels) by using the MapDialogRect function. + /// + public short PositionY { get; set; } + + /// + /// The width, in dialog box units, of the control. + /// + /// + /// The x, y, cx, and cy members specify values in dialog box units. You can convert these values to screen + /// units (pixels) by using the MapDialogRect function. + /// + public short WidthX { get; set; } + + /// + /// The height, in dialog box units, of the control. + /// + /// + /// The x, y, cx, and cy members specify values in dialog box units. You can convert these values to screen + /// units (pixels) by using the MapDialogRect function. + /// + public short HeightY { get; set; } + + /// + /// The control identifier. + /// + public ushort ID { get; set; } + + // In a standard template for a dialog box, the DLGITEMTEMPLATE structure is always immediately + // followed by three variable-length arrays specifying the class, title, and creation data for + // the control. Each array consists of one or more 16-bit elements. + // + // Each DLGITEMTEMPLATE structure in the template must be aligned on a DWORD boundary. The class + // and title arrays must be aligned on WORD boundaries. The creation data array must be aligned + // on a WORD boundary. + + /// + /// Immediately following each DLGITEMTEMPLATE structure is a class array that specifies the window + /// class of the control. If the first element of this array is any value other than 0xFFFF, the + /// system treats the array as a null-terminated Unicode string that specifies the name of a + /// registered window class. If the first element is 0xFFFF, the array has one additional element + /// that specifies the ordinal value of a predefined system class. + /// + /// + /// If you specify character strings in the class and title arrays, you must use Unicode strings. Use the + /// MultiByteToWideChar function to generate Unicode strings from ANSI strings. + /// + public string? ClassResource { get; set; } + + /// + /// The ordinal value of a predefined system class. + /// + public DialogItemTemplateOrdinal ClassResourceOrdinal { get; set; } + + /// + /// Following the class array is a title array that contains the initial text or resource identifier + /// of the control. If the first element of this array is 0xFFFF, the array has one additional element + /// that specifies an ordinal value of a resource, such as an icon, in an executable file. You can use + /// a resource identifier for controls, such as static icon controls, that load and display an icon + /// or other resource rather than text. If the first element is any value other than 0xFFFF, the system + /// treats the array as a null-terminated Unicode string that specifies the initial text. + /// + /// + /// If you specify character strings in the class and title arrays, you must use Unicode strings. Use the + /// MultiByteToWideChar function to generate Unicode strings from ANSI strings. + /// + public string? TitleResource { get; set; } + + /// + /// An ordinal value of a resource, such as an icon, in an executable file + /// + public ushort TitleResourceOrdinal { get; set; } + + /// + /// The creation data array begins at the next WORD boundary after the title array. This creation data + /// can be of any size and format. If the first word of the creation data array is nonzero, it indicates + /// the size, in bytes, of the creation data (including the size word). + /// + public ushort CreationDataSize { get; set; } + + /// + /// The creation data array begins at the next WORD boundary after the title array. This creation data + /// can be of any size and format. The control's window procedure must be able to interpret the data. + /// When the system creates the control, it passes a pointer to this data in the lParam parameter of the + /// WM_CREATE message that it sends to the control. + /// + public byte[]? CreationData { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/DialogItemTemplateExtended.cs b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/DialogItemTemplateExtended.cs new file mode 100644 index 00000000..85e10a6e --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/DialogItemTemplateExtended.cs @@ -0,0 +1,128 @@ +namespace SabreTools.Serialization.Models.PortableExecutable.Resource.Entries +{ + /// + /// A block of text used by an extended dialog box template to describe the extended dialog box. + /// For a description of the format of an extended dialog box template, see DLGTEMPLATEEX. + /// + /// + public sealed class DialogItemTemplateExtended + { + /// + /// The help context identifier for the control. When the system sends a WM_HELP message, + /// it passes the helpID value in the dwContextId member of the HELPINFO structure. + /// + public uint HelpID { get; set; } + + /// + /// The extended styles for a window. This member is not used to create controls in dialog + /// boxes, but applications that use dialog box templates can use it to create other types + /// of windows. + /// + public ExtendedWindowStyles ExtendedStyle { get; set; } + + /// + /// The style of the control. This member can be a combination of window style values + /// (such as WS_BORDER) and one or more of the control style values (such as + /// BS_PUSHBUTTON and ES_LEFT). + /// + public WindowStyles Style { get; set; } + + /// + /// The x-coordinate, in dialog box units, of the upper-left corner of the control. + /// This coordinate is always relative to the upper-left corner of the dialog box's + /// client area. + /// + /// + /// The x, y, cx, and cy members specify values in dialog box units. You can convert these values to screen + /// units (pixels) by using the MapDialogRect function. + /// + public short PositionX { get; set; } + + /// + /// The y-coordinate, in dialog box units, of the upper-left corner of the control. + /// This coordinate is always relative to the upper-left corner of the dialog box's + /// client area. + /// + /// + /// The x, y, cx, and cy members specify values in dialog box units. You can convert these values to screen + /// units (pixels) by using the MapDialogRect function. + /// + public short PositionY { get; set; } + + /// + /// The width, in dialog box units, of the control. + /// + /// + /// The x, y, cx, and cy members specify values in dialog box units. You can convert these values to screen + /// units (pixels) by using the MapDialogRect function. + /// + public short WidthX { get; set; } + + /// + /// The height, in dialog box units, of the control. + /// + /// + /// The x, y, cx, and cy members specify values in dialog box units. You can convert these values to screen + /// units (pixels) by using the MapDialogRect function. + /// + public short HeightY { get; set; } + + /// + /// The control identifier. + /// + public uint ID { get; set; } + + /// + /// A variable-length array of 16-bit elements that specifies the window class of the control. If + /// the first element of this array is any value other than 0xFFFF, the system treats the array as + /// a null-terminated Unicode string that specifies the name of a registered window class. + /// + /// If the first element is 0xFFFF, the array has one additional element that specifies the ordinal + /// value of a predefined system class. + /// + /// + /// If you specify character strings in the class and title arrays, you must use Unicode strings. Use the + /// MultiByteToWideChar function to generate Unicode strings from ANSI strings. + /// + public string? ClassResource { get; set; } + + /// + /// The ordinal value of a predefined system class. + /// + public DialogItemTemplateOrdinal ClassResourceOrdinal { get; set; } + + /// + /// A variable-length array of 16-bit elements that contains the initial text or resource identifier of the + /// control. If the first element of this array is 0xFFFF, the array has one additional element that + /// specifies the ordinal value of a resource, such as an icon, in an executable file. You can use a + /// resource identifier for controls, such as static icon controls, that load and display an icon or other + /// resource rather than text. If the first element is any value other than 0xFFFF, the system treats the + /// array as a null-terminated Unicode string that specifies the initial text. + /// + /// + /// If you specify character strings in the class and title arrays, you must use Unicode strings. Use the + /// MultiByteToWideChar function to generate Unicode strings from ANSI strings. + /// + public string? TitleResource { get; set; } + + /// + /// An ordinal value of a resource, such as an icon, in an executable file + /// + public ushort TitleResourceOrdinal { get; set; } + + /// + /// The creation data array begins at the next WORD boundary after the title array. This creation data + /// can be of any size and format. If the first word of the creation data array is nonzero, it indicates + /// the size, in bytes, of the creation data (including the size word). + /// + public ushort CreationDataSize { get; set; } + + /// + /// The creation data array begins at the next WORD boundary after the title array. This creation data + /// can be of any size and format. The control's window procedure must be able to interpret the data. + /// When the system creates the control, it passes a pointer to this data in the lParam parameter of the + /// WM_CREATE message that it sends to the control. + /// + public byte[]? CreationData { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/DialogTemplate.cs b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/DialogTemplate.cs new file mode 100644 index 00000000..20a83ad9 --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/DialogTemplate.cs @@ -0,0 +1,160 @@ +namespace SabreTools.Serialization.Models.PortableExecutable.Resource.Entries +{ + /// + /// Defines the dimensions and style of a dialog box. This structure, always the first + /// in a standard template for a dialog box, also specifies the number of controls in + /// the dialog box and therefore specifies the number of subsequent DLGITEMTEMPLATE + /// structures in the template. + /// + /// + public sealed class DialogTemplate + { + /// + /// The style of the dialog box. This member can be a combination of window style + /// values (such as WS_CAPTION and WS_SYSMENU) and dialog box style values (such + /// as DS_CENTER). + /// + /// If the style member includes the DS_SETFONT style, the header of the dialog box + /// template contains additional data specifying the font to use for text in the + /// client area and controls of the dialog box. The font data begins on the WORD + /// boundary that follows the title array. The font data specifies a 16-bit point + /// size value and a Unicode font name string. If possible, the system creates a + /// font according to the specified values. Then the system sends a WM_SETFONT + /// message to the dialog box and to each control to provide a handle to the font. + /// If DS_SETFONT is not specified, the dialog box template does not include the + /// font data. + /// + /// The DS_SHELLFONT style is not supported in the DLGTEMPLATE header. + /// + public WindowStyles Style { get; set; } + + /// + /// The extended styles for a window. This member is not used to create dialog boxes, + /// but applications that use dialog box templates can use it to create other types + /// of windows. + /// + public ExtendedWindowStyles ExtendedStyle { get; set; } + + /// + /// The number of items in the dialog box. + /// + public ushort ItemCount { get; set; } + + /// + /// The x-coordinate, in dialog box units, of the upper-left corner of the dialog box. + /// + /// + /// The x, y, cx, and cy members specify values in dialog box units. You can convert these values + /// to screen units (pixels) by using the MapDialogRect function. + /// + public short PositionX { get; set; } + + /// + /// The y-coordinate, in dialog box units, of the upper-left corner of the dialog box. + /// + /// + /// The x, y, cx, and cy members specify values in dialog box units. You can convert these values + /// to screen units (pixels) by using the MapDialogRect function. + /// + public short PositionY { get; set; } + + /// + /// The width, in dialog box units, of the dialog box. + /// + /// + /// The x, y, cx, and cy members specify values in dialog box units. You can convert these values + /// to screen units (pixels) by using the MapDialogRect function. + /// + public short WidthX { get; set; } + + /// + /// The height, in dialog box units, of the dialog box. + /// + /// + /// The x, y, cx, and cy members specify values in dialog box units. You can convert these values + /// to screen units (pixels) by using the MapDialogRect function. + /// + public short HeightY { get; set; } + + // In a standard template for a dialog box, the DLGTEMPLATE structure is always immediately + // followed by three variable-length arrays that specify the menu, class, and title for the + // dialog box. When the DS_SETFONT style is specified, these arrays are also followed by a + // 16-bit value specifying point size and another variable-length array specifying a + // typeface name. Each array consists of one or more 16-bit elements. The menu, class, title, + // and font arrays must be aligned on WORD boundaries. + + /// + /// Immediately following the DLGTEMPLATE structure is a menu array that identifies a menu + /// resource for the dialog box. If the first element of this array is 0x0000, the dialog box + /// has no menu and the array has no other elements. If the first element is 0xFFFF, the array + /// has one additional element that specifies the ordinal value of a menu resource in an + /// executable file. If the first element has any other value, the system treats the array as + /// a null-terminated Unicode string that specifies the name of a menu resource in an executable + /// file. + /// + /// + /// If you specify character strings in the menu, class, title, or typeface arrays, you must use + /// Unicode strings. + /// + public string? MenuResource { get; set; } + + /// + /// The ordinal value of a menu resource in an executable file. + /// + public ushort MenuResourceOrdinal { get; set; } + + /// + /// Following the menu array is a class array that identifies the window class of the dialog box. + /// If the first element of the array is 0x0000, the system uses the predefined dialog box class + /// for the dialog box and the array has no other elements. If the first element is 0xFFFF, + /// the array has one additional element that specifies the ordinal value of a predefined system + /// window class. If the first element has any other value, the system treats the array as a + /// null-terminated Unicode string that specifies the name of a registered window class. + /// + /// + /// If you specify character strings in the menu, class, title, or typeface arrays, you must use + /// Unicode strings. + /// + public string? ClassResource { get; set; } + + /// + /// The ordinal value of a predefined system class. + /// + public ushort ClassResourceOrdinal { get; set; } + + /// + /// Following the class array is a title array that specifies a null-terminated Unicode string + /// that contains the title of the dialog box. If the first element of this array is 0x0000, + /// the dialog box has no title and the array has no other elements. + /// + /// + /// If you specify character strings in the menu, class, title, or typeface arrays, you must use + /// Unicode strings. + /// + public string? TitleResource { get; set; } + + /// + /// The 16-bit point size value and the typeface array follow the title array, but only if the + /// style member specifies the DS_SETFONT style. The point size value specifies the point size + /// of the font to use for the text in the dialog box and its controls. When these values are + /// specified, the system creates a font having the specified size and typeface (if possible) + /// and sends a WM_SETFONT message to the dialog box procedure and the control window + /// procedures as it creates the dialog box and controls. + /// + public ushort PointSizeValue { get; set; } + + /// + /// The 16-bit point size value and the typeface array follow the title array, but only if the + /// style member specifies the DS_SETFONT style. The typeface array is a null-terminated Unicode + /// string specifying the name of the typeface for the font. When these values are specified, + /// the system creates a font having the specified size and typeface (if possible) and sends a + /// WM_SETFONT message to the dialog box procedure and the control window procedures as it + /// creates the dialog box and controls. + /// + /// + /// If you specify character strings in the menu, class, title, or typeface arrays, you must use + /// Unicode strings. + /// + public string? Typeface { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/DialogTemplateExtended.cs b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/DialogTemplateExtended.cs new file mode 100644 index 00000000..ebef4ca9 --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/DialogTemplateExtended.cs @@ -0,0 +1,185 @@ +namespace SabreTools.Serialization.Models.PortableExecutable.Resource.Entries +{ + /// + /// An extended dialog box template begins with a DLGTEMPLATEEX header that describes + /// the dialog box and specifies the number of controls in the dialog box. For each + /// control in a dialog box, an extended dialog box template has a block of data that + /// uses the DLGITEMTEMPLATEEX format to describe the control. + /// + /// The DLGTEMPLATEEX structure is not defined in any standard header file. The + /// structure definition is provided here to explain the format of an extended template + /// for a dialog box. + /// + /// + public sealed class DialogTemplateExtended + { + /// + /// The version number of the extended dialog box template. This member must be + /// set to 1. + /// + public ushort Version { get; set; } + + /// + /// Indicates whether a template is an extended dialog box template. If signature + /// is 0xFFFF, this is an extended dialog box template. In this case, the dlgVer + /// member specifies the template version number. If signature is any value other + /// than 0xFFFF, this is a standard dialog box template that uses the DLGTEMPLATE + /// and DLGITEMTEMPLATE structures. + /// + public ushort Signature { get; set; } + + /// + /// The help context identifier for the dialog box window. When the system sends a + /// WM_HELP message, it passes this value in the wContextId member of the HELPINFO + /// structure. + /// + public uint HelpID { get; set; } + + /// + /// The extended windows styles. This member is not used when creating dialog boxes, + /// but applications that use dialog box templates can use it to create other types + /// of windows. + /// + public ExtendedWindowStyles ExtendedStyle { get; set; } + + /// + /// The style of the dialog box. + /// + /// If style includes the DS_SETFONT or DS_SHELLFONT dialog box style, the DLGTEMPLATEEX + /// header of the extended dialog box template contains four additional members (pointsize, + /// weight, italic, and typeface) that describe the font to use for the text in the client + /// area and controls of the dialog box. If possible, the system creates a font according + /// to the values specified in these members. Then the system sends a WM_SETFONT message + /// to the dialog box and to each control to provide a handle to the font. + /// + public WindowStyles Style { get; set; } + + /// + /// The number of controls in the dialog box. + /// + public ushort DialogItems { get; set; } + + /// + /// The x-coordinate, in dialog box units, of the upper-left corner of the dialog box. + /// + /// + /// The x, y, cx, and cy members specify values in dialog box units. You can convert these values + /// to screen units (pixels) by using the MapDialogRect function. + /// + public short PositionX { get; set; } + + /// + /// The y-coordinate, in dialog box units, of the upper-left corner of the dialog box. + /// + /// + /// The x, y, cx, and cy members specify values in dialog box units. You can convert these values + /// to screen units (pixels) by using the MapDialogRect function. + /// + public short PositionY { get; set; } + + /// + /// The width, in dialog box units, of the dialog box. + /// + /// + /// The x, y, cx, and cy members specify values in dialog box units. You can convert these values + /// to screen units (pixels) by using the MapDialogRect function. + /// + public short WidthX { get; set; } + + /// + /// The height, in dialog box units, of the dialog box. + /// + /// + /// The x, y, cx, and cy members specify values in dialog box units. You can convert these values + /// to screen units (pixels) by using the MapDialogRect function. + /// + public short HeightY { get; set; } + + /// + /// A variable-length array of 16-bit elements that identifies a menu resource for the dialog box. + /// If the first element of this array is 0x0000, the dialog box has no menu and the array has no + /// other elements. If the first element is 0xFFFF, the array has one additional element that + /// specifies the ordinal value of a menu resource in an executable file. If the first element has + /// any other value, the system treats the array as a null-terminated Unicode string that specifies + /// the name of a menu resource in an executable file. + /// + /// + /// If you specify character strings in the class and title arrays, you must use Unicode strings. Use the + /// MultiByteToWideChar function to generate Unicode strings from ANSI strings. + /// + public string? MenuResource { get; set; } + + /// + /// The ordinal value of a menu resource in an executable file. + /// + public ushort MenuResourceOrdinal { get; set; } + + /// A variable-length array of 16-bit elements that identifies the window class of the + /// dialog box. If the first element of the array is 0x0000, the system uses the predefined dialog + /// box class for the dialog box and the array has no other elements. If the first element is 0xFFFF, + /// the array has one additional element that specifies the ordinal value of a predefined system + /// window class. If the first element has any other value, the system treats the array as a + /// null-terminated Unicode string that specifies the name of a registered window class. + /// + /// + /// If you specify character strings in the class and title arrays, you must use Unicode strings. Use the + /// MultiByteToWideChar function to generate Unicode strings from ANSI strings. + /// + public string? ClassResource { get; set; } + + /// + /// The ordinal value of a predefined system window class. + /// + public ushort ClassResourceOrdinal { get; set; } + + /// + /// The title of the dialog box. If the first element of this array is 0x0000, the dialog box has no + /// title and the array has no other elements. + /// + /// + /// If you specify character strings in the class and title arrays, you must use Unicode strings. Use the + /// MultiByteToWideChar function to generate Unicode strings from ANSI strings. + /// + public string? TitleResource { get; set; } + + /// + /// The point size of the font to use for the text in the dialog box and its controls. + /// + /// This member is present only if the style member specifies DS_SETFONT or DS_SHELLFONT. + /// + public ushort PointSize { get; set; } + + /// + /// The weight of the font. Note that, although this can be any of the values listed for the lfWeight + /// member of the LOGFONT structure, any value that is used will be automatically changed to FW_NORMAL. + /// + /// This member is present only if the style member specifies DS_SETFONT or DS_SHELLFONT. + /// + public ushort Weight { get; set; } + + /// + /// Indicates whether the font is italic. If this value is TRUE, the font is italic. + /// + /// This member is present only if the style member specifies DS_SETFONT or DS_SHELLFONT. + /// + public byte Italic { get; set; } + + /// + /// The character set to be used. For more information, see the lfcharset member of LOGFONT. + /// + /// This member is present only if the style member specifies DS_SETFONT or DS_SHELLFONT. + /// + public byte CharSet { get; set; } + + /// + /// The name of the typeface for the font. + /// + /// This member is present only if the style member specifies DS_SETFONT or DS_SHELLFONT. + /// + /// + /// If you specify character strings in the class and title arrays, you must use Unicode strings. Use the + /// MultiByteToWideChar function to generate Unicode strings from ANSI strings. + /// + public string? Typeface { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/DirEntry.cs b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/DirEntry.cs new file mode 100644 index 00000000..185d7f4b --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/DirEntry.cs @@ -0,0 +1,21 @@ +namespace SabreTools.Serialization.Models.PortableExecutable.Resource.Entries +{ + /// + /// Contains the information necessary for an application to access a specific font. The structure + /// definition provided here is for explanation only; it is not present in any standard header file. + /// + /// + public sealed class DirEntry + { + /// + /// A unique ordinal identifier for an individual font in a font resource group. + /// + public ushort FontOrdinal { get; set; } + + /// + /// The FONTDIRENTRY structure for the specified font directly follows the DIRENTRY structure + /// for that font. + /// + public FontDirEntry? Entry { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/FixedFileInfo.cs b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/FixedFileInfo.cs new file mode 100644 index 00000000..e6f75f56 --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/FixedFileInfo.cs @@ -0,0 +1,92 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.PortableExecutable.Resource.Entries +{ + /// + /// Contains version information for a file. This information is language and + /// code page independent. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class FixedFileInfo + { + /// + /// Contains the value 0xFEEF04BD. This is used with the szKey member of the VS_VERSIONINFO + /// structure when searching a file for the FixedFileInfo structure. + /// + public uint Signature; + + /// + /// The binary version number of this structure. The high-order word of this member contains + /// the major version number, and the low-order word contains the minor version number. + /// + public uint StrucVersion; + + /// + /// The most significant 32 bits of the file's binary version number. This member is used with + /// FileVersionLS to form a 64-bit value used for numeric comparisons. + /// + public uint FileVersionMS; + + /// + /// The least significant 32 bits of the file's binary version number. This member is used with + /// FileVersionMS to form a 64-bit value used for numeric comparisons. + /// + public uint FileVersionLS; + + /// + /// The most significant 32 bits of the binary version number of the product with which this file + /// was distributed. This member is used with ProductVersionLS to form a 64-bit value used for + /// numeric comparisons. + /// + public uint ProductVersionMS; + + /// + /// The least significant 32 bits of the binary version number of the product with which this file + /// was distributed. This member is used with ProductVersionMS to form a 64-bit value used for + /// numeric comparisons. + /// + public uint ProductVersionLS; + + /// + /// Contains a bitmask that specifies the valid bits in FileFlags. A bit is valid only if it was + /// defined when the file was created. + /// + public uint FileFlagsMask; + + /// + /// Contains a bitmask that specifies the Boolean attributes of the file. + /// + [MarshalAs(UnmanagedType.U4)] + public FixedFileInfoFlags FileFlags; + + /// + /// The operating system for which this file was designed. + /// + [MarshalAs(UnmanagedType.U4)] + public FixedFileInfoOS FileOS; + + /// + /// The general type of file. + /// + [MarshalAs(UnmanagedType.U4)] + public FixedFileInfoFileType FileType; + + /// + /// The function of the file. The possible values depend on the value of FileType. For all values + /// of FileType not described in the following list, FileSubtype is zero. + /// + [MarshalAs(UnmanagedType.U4)] + public FixedFileInfoFileSubtype FileSubtype; + + /// + /// The most significant 32 bits of the file's 64-bit binary creation date and time stamp. + /// + public uint FileDateMS; + + /// + /// The least significant 32 bits of the file's 64-bit binary creation date and time stamp. + /// + public uint FileDateLS; + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/FontDirEntry.cs b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/FontDirEntry.cs new file mode 100644 index 00000000..9c3189d8 --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/FontDirEntry.cs @@ -0,0 +1,174 @@ +namespace SabreTools.Serialization.Models.PortableExecutable.Resource.Entries +{ + /// + /// Contains information about an individual font in a font resource group. The structure definition + /// provided here is for explanation only; it is not present in any standard header file. + /// + /// + public sealed class FontDirEntry + { + /// + /// A user-defined version number for the resource data that tools can use to read and write + /// resource files. + /// + public ushort Version { get; set; } + + /// + /// The size of the file, in bytes. + /// + public uint Size { get; set; } + + /// + /// The font supplier's copyright information. + /// + /// 60 characters + public byte[]? Copyright { get; set; } + + /// + /// The type of font file. + /// + public ushort Type { get; set; } + + /// + /// The point size at which this character set looks best. + /// + public ushort Points { get; set; } + + /// + /// The vertical resolution, in dots per inch, at which this character set was digitized. + /// + public ushort VertRes { get; set; } + + /// + /// The horizontal resolution, in dots per inch, at which this character set was digitized. + /// + public ushort HorizRes { get; set; } + + /// + /// The distance from the top of a character definition cell to the baseline of the typographical + /// font. + /// + public ushort Ascent { get; set; } + + /// + /// The amount of leading inside the bounds set by the PixHeight member. Accent marks and other + /// diacritical characters can occur in this area. + /// + public ushort InternalLeading { get; set; } + + /// + /// The amount of extra leading that the application adds between rows. + /// + public ushort ExternalLeading { get; set; } + + /// + /// An italic font if not equal to zero. + /// + public byte Italic { get; set; } + + /// + /// An underlined font if not equal to zero. + /// + public byte Underline { get; set; } + + /// + /// A strikeout font if not equal to zero. + /// + public byte StrikeOut { get; set; } + + /// + /// The weight of the font in the range 0 through 1000. For example, 400 is roman and 700 is bold. + /// If this value is zero, a default weight is used. For additional defined values, see the + /// description of the LOGFONT structure. + /// + public ushort Weight { get; set; } + + /// + /// The character set of the font. For predefined values, see the description of the LOGFONT + /// structure. + /// + public byte CharSet { get; set; } + + /// + /// The width of the grid on which a vector font was digitized. For raster fonts, if the member + /// is not equal to zero, it represents the width for all the characters in the bitmap. If the + /// member is equal to zero, the font has variable-width characters. + /// + public ushort PixWidth { get; set; } + + /// + /// The height of the character bitmap for raster fonts or the height of the grid on which a + /// vector font was digitized. + /// + public ushort PixHeight { get; set; } + + /// + /// The pitch and the family of the font. For additional information, see the description of + /// the LOGFONT structure. + /// + public byte PitchAndFamily { get; set; } + + /// + /// The average width of characters in the font (generally defined as the width of the letter x). + /// This value does not include the overhang required for bold or italic characters. + /// + public ushort AvgWidth { get; set; } + + /// + /// The width of the widest character in the font. + /// + public ushort MaxWidth { get; set; } + + /// + /// The first character code defined in the font. + /// + public byte FirstChar { get; set; } + + /// + /// The last character code defined in the font. + /// + public byte LastChar { get; set; } + + /// + /// The character to substitute for characters not in the font. + /// + public byte DefaultChar { get; set; } + + /// + /// The character that will be used to define word breaks for text justification. + /// + public byte BreakChar { get; set; } + + /// + /// The number of bytes in each row of the bitmap. This value is always even so that the rows + /// start on word boundaries. For vector fonts, this member has no meaning. + /// + public ushort WidthBytes { get; set; } + + /// + /// The offset in the file to a null-terminated string that specifies a device name. For a + /// generic font, this value is zero. + /// + public uint Device { get; set; } + + /// + /// The offset in the file to a null-terminated string that names the typeface. + /// + public uint Face { get; set; } + + /// + /// This member is reserved. + /// + public uint Reserved { get; set; } + + /// + /// The name of the device if this font file is designated for a specific device. + /// + public string? DeviceName { get; set; } + + /// + /// The typeface name of the font. + /// + public string? FaceName { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/FontGroupHeader.cs b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/FontGroupHeader.cs new file mode 100644 index 00000000..b95e9632 --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/FontGroupHeader.cs @@ -0,0 +1,21 @@ +namespace SabreTools.Serialization.Models.PortableExecutable.Resource.Entries +{ + /// + /// Contains the information necessary for an application to access a specific font. The structure + /// definition provided here is for explanation only; it is not present in any standard header file. + /// + /// + public sealed class FontGroupHeader + { + /// + /// The number of individual fonts associated with this resource. + /// + public ushort NumberOfFonts { get; set; } + + /// + /// A structure that contains a unique ordinal identifier for each font in the resource. The DE + /// member is a placeholder for the variable-length array of DIRENTRY structures. + /// + public DirEntry[]? DE { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/MenuHeader.cs b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/MenuHeader.cs new file mode 100644 index 00000000..da9d7de8 --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/MenuHeader.cs @@ -0,0 +1,12 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.PortableExecutable.Resource.Entries +{ + /// + /// Common base class for menu item types + /// + /// + /// + [StructLayout(LayoutKind.Sequential)] + public abstract class MenuHeader { } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/MenuHeaderExtended.cs b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/MenuHeaderExtended.cs new file mode 100644 index 00000000..a64cd245 --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/MenuHeaderExtended.cs @@ -0,0 +1,30 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.PortableExecutable.Resource.Entries +{ + /// + /// Defines the header for an extended menu template. This structure definition is for + /// explanation only; it is not present in any standard header file. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class MenuHeaderExtended : MenuHeader + { + /// + /// The template version number. This member must be 1 for extended menu templates. + /// + public ushort Version; + + /// + /// The offset to the first MENUEX_TEMPLATE_ITEM structure, relative to the end of + /// this structure member. If the first item definition immediately follows the + /// dwHelpId member, this member should be 4. + /// + public ushort Offset; + + /// + /// The help identifier of menu bar. + /// + public uint HelpID; + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/MenuItem.cs b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/MenuItem.cs new file mode 100644 index 00000000..9870fb91 --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/MenuItem.cs @@ -0,0 +1,12 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.PortableExecutable.Resource.Entries +{ + /// + /// Common base class for menu item types + /// + /// + /// + [StructLayout(LayoutKind.Sequential)] + public abstract class MenuItem { } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/MenuItemExtended.cs b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/MenuItemExtended.cs new file mode 100644 index 00000000..61e057d2 --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/MenuItemExtended.cs @@ -0,0 +1,44 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.PortableExecutable.Resource.Entries +{ + /// + /// Defines a menu item in an extended menu template. This structure definition is for + /// explanation only; it is not present in any standard header file. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class MenuItemExtended : MenuItem + { + /// + /// Describes the menu item. + /// + [MarshalAs(UnmanagedType.U4)] + public MenuFlags ItemType; + + /// + /// Describes the menu item. + /// + [MarshalAs(UnmanagedType.U4)] + public MenuFlags State; + + /// + /// A numeric expression that identifies the menu item that is passed in the + /// WM_COMMAND message. + /// + public uint ID; + + /// + /// A set of bit flags that specify the type of menu item. + /// + [MarshalAs(UnmanagedType.U4)] + public MenuFlags Flags; + + /// + /// A null-terminated Unicode string that contains the text for this menu item. + /// There is no fixed limit on the size of this string. + /// + [MarshalAs(UnmanagedType.LPWStr)] + public string? MenuText; + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/MenuResource.cs b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/MenuResource.cs new file mode 100644 index 00000000..f1782150 --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/MenuResource.cs @@ -0,0 +1,22 @@ +namespace SabreTools.Serialization.Models.PortableExecutable.Resource.Entries +{ + /// + /// A menu resource consists of a MENUHEADER structure followed by one or more + /// NORMALMENUITEM or POPUPMENUITEM structures, one for each menu item in the menu + /// template. The MENUEX_TEMPLATE_HEADER and the MENUEX_TEMPLATE_ITEM structures + /// describe the format of extended menu resources. + /// + /// + public sealed class MenuResource + { + /// + /// Menu header structure + /// + public MenuHeader? MenuHeader { get; set; } + + /// + /// Menu items + /// + public MenuItem[]? MenuItems { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/MessageResourceBlock.cs b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/MessageResourceBlock.cs new file mode 100644 index 00000000..facacb7e --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/MessageResourceBlock.cs @@ -0,0 +1,30 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.PortableExecutable.Resource.Entries +{ + /// + /// Contains information about message strings with identifiers in the range indicated + /// by the LowId and HighId members. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class MessageResourceBlock + { + /// + /// The lowest message identifier contained within this structure. + /// + public uint LowId; + + /// + /// The highest message identifier contained within this structure. + /// + public uint HighId; + + /// + /// The offset, in bytes, from the beginning of the MESSAGE_RESOURCE_DATA structure to the + /// MESSAGE_RESOURCE_ENTRY structures in this MESSAGE_RESOURCE_BLOCK. The MESSAGE_RESOURCE_ENTRY + /// structures contain the message strings. + /// + public uint OffsetToEntries; + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/MessageResourceData.cs b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/MessageResourceData.cs new file mode 100644 index 00000000..a009f25d --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/MessageResourceData.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; + +namespace SabreTools.Serialization.Models.PortableExecutable.Resource.Entries +{ + /// + /// Contains information about formatted text for display as an error message or in a message + /// box in a message table resource. + /// + /// + public sealed class MessageResourceData + { + /// + /// The number of MESSAGE_RESOURCE_BLOCK structures. + /// + public uint NumberOfBlocks { get; set; } + + /// + /// An array of structures. The array is the size indicated by the NumberOfBlocks member. + /// + public MessageResourceBlock[]? Blocks { get; set; } + + /// + /// Message resource entries + /// + public Dictionary? Entries { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/MessageResourceEntry.cs b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/MessageResourceEntry.cs new file mode 100644 index 00000000..26a34068 --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/MessageResourceEntry.cs @@ -0,0 +1,25 @@ +namespace SabreTools.Serialization.Models.PortableExecutable.Resource.Entries +{ + /// + /// Contains the error message or message box display text for a message table resource. + /// + /// + public sealed class MessageResourceEntry + { + /// + /// The length, in bytes, of the MESSAGE_RESOURCE_ENTRY structure. + /// + public ushort Length { get; set; } + + /// + /// Indicates that the string is encoded in Unicode, if equal to the value 0x0001. + /// Indicates that the string is encoded in ANSI, if equal to the value 0x0000. + /// + public ushort Flags { get; set; } + + /// + /// Pointer to an array that contains the error message or message box display text. + /// + public string? Text { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/NewHeader.cs b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/NewHeader.cs new file mode 100644 index 00000000..d105f43d --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/NewHeader.cs @@ -0,0 +1,31 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.PortableExecutable.Resource.Entries +{ + /// + /// Contains the number of icon or cursor components in a resource group. The + /// structure definition provided here is for explanation only; it is not present + /// in any standard header file. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class NewHeader + { + /// + /// Reserved; must be zero. + /// + public ushort Reserved; + + /// + /// The resource type. This member must have one of the following values. + /// - RES_ICON (1): Icon resource type. + /// - RES_CURSOR (2): Cursor resource type. + /// + public ushort ResType; + + /// + /// The number of icon or cursor components in the resource group. + /// + public ushort ResCount; + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/NormalMenuHeader.cs b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/NormalMenuHeader.cs new file mode 100644 index 00000000..6505ab6b --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/NormalMenuHeader.cs @@ -0,0 +1,25 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.PortableExecutable.Resource.Entries +{ + /// + /// Contains version information for the menu resource. The structure definition provided + /// here is for explanation only; it is not present in any standard header file. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class NormalMenuHeader: MenuHeader + { + /// + /// The version number of the menu template. This member must be equal to zero to indicate + /// that this is an RT_MENU created with a standard menu template. + /// + public ushort Version; + + /// + /// The size of the menu template header. This value is zero for menus you create with a + /// standard menu template. + /// + public ushort HeaderSize; + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/NormalMenuItem.cs b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/NormalMenuItem.cs new file mode 100644 index 00000000..4a5d4c21 --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/NormalMenuItem.cs @@ -0,0 +1,27 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.PortableExecutable.Resource.Entries +{ + /// + /// Contains information about each item in a menu resource that does not open a menu + /// or a submenu. The structure definition provided here is for explanation only; it + /// is not present in any standard header file. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class NormalMenuItem : MenuItem + { + /// + /// The type of menu item. + /// + [MarshalAs(UnmanagedType.U2)] + public MenuFlags NormalResInfo; + + /// + /// A null-terminated Unicode string that contains the text for this menu item. + /// There is no fixed limit on the size of this string. + /// + [MarshalAs(UnmanagedType.LPWStr)] + public string? NormalMenuText; + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/PopupMenuItem.cs b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/PopupMenuItem.cs new file mode 100644 index 00000000..d6507ff8 --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/PopupMenuItem.cs @@ -0,0 +1,45 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.PortableExecutable.Resource.Entries +{ + /// + /// Contains information about the menu items in a menu resource that open a menu + /// or a submenu. The structure definition provided here is for explanation only; + /// it is not present in any standard header file. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class PopupMenuItem : MenuItem + { + /// + /// Describes the menu item. + /// + [MarshalAs(UnmanagedType.U4)] + public MenuFlags PopupItemType; + + /// + /// Describes the menu item. + /// + [MarshalAs(UnmanagedType.U4)] + public MenuFlags PopupState; + + /// + /// A numeric expression that identifies the menu item that is passed in the + /// WM_COMMAND message. + /// + public uint PopupID; + + /// + /// A set of bit flags that specify the type of menu item. + /// + [MarshalAs(UnmanagedType.U4)] + public MenuFlags PopupResInfo; + + /// + /// A null-terminated Unicode string that contains the text for this menu item. + /// There is no fixed limit on the size of this string. + /// + [MarshalAs(UnmanagedType.LPWStr)] + public string? PopupMenuText; + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/StringData.cs b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/StringData.cs new file mode 100644 index 00000000..8c1d2853 --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/StringData.cs @@ -0,0 +1,79 @@ +namespace SabreTools.Serialization.Models.PortableExecutable.Resource.Entries +{ + /// + /// Represents the organization of data in a file-version resource. It contains a string + /// that describes a specific aspect of a file, for example, a file's version, its + /// copyright notices, or its trademarks. + /// + /// + public sealed class StringData + { + /// + /// The length, in bytes, of this String structure. + /// + public ushort Length { get; set; } + + /// + /// The size, in words, of the Value member. + /// + public ushort ValueLength { get; set; } + + /// + /// The type of data in the version resource. + /// + public VersionResourceType ResourceType { get; set; } + + /// + /// An arbitrary Unicode string. The Key member can be one or more of the following + /// values. These values are guidelines only. + /// - Comments: The Value member contains any additional information that should be + /// displayed for diagnostic purposes. This string can be an arbitrary length. + /// - CompanyName: The Value member identifies the company that produced the file. + /// For example, "Microsoft Corporation" or "Standard Microsystems Corporation, Inc." + /// - FileDescription: The Value member describes the file in such a way that it can be + /// presented to users. This string may be presented in a list box when the user is + /// choosing files to install. For example, "Keyboard driver for AT-style keyboards" + /// or "Microsoft Word for Windows". + /// - FileVersion: The Value member identifies the version of this file. For example, + /// Value could be "3.00A" or "5.00.RC2". + /// - InternalName: The Value member identifies the file's internal name, if one exists. + /// For example, this string could contain the module name for a DLL, a virtual device + /// name for a Windows virtual device, or a device name for a MS-DOS device driver. + /// - LegalCopyright: The Value member describes all copyright notices, trademarks, and + /// registered trademarks that apply to the file. This should include the full text of + /// all notices, legal symbols, copyright dates, trademark numbers, and so on. In + /// English, this string should be in the format "Copyright Microsoft Corp. 1990 1994". + /// - LegalTrademarks: The Value member describes all trademarks and registered trademarks + /// that apply to the file. This should include the full text of all notices, legal + /// symbols, trademark numbers, and so on. In English, this string should be in the + /// format "Windows is a trademark of Microsoft Corporation". + /// - OriginalFilename: The Value member identifies the original name of the file, not + /// including a path. This enables an application to determine whether a file has been + /// renamed by a user. This name may not be MS-DOS 8.3-format if the file is specific + /// to a non-FAT file system. + /// - PrivateBuild: The Value member describes by whom, where, and why this private version + /// of the file was built. This string should only be present if the VS_FF_PRIVATEBUILD + /// flag is set in the dwFileFlags member of the VS_FIXEDFILEINFO structure. For example, + /// Value could be "Built by OSCAR on \OSCAR2". + /// - ProductName: The Value member identifies the name of the product with which this file is + /// distributed. For example, this string could be "Microsoft Windows". + /// - ProductVersion: The Value member identifies the version of the product with which this + /// file is distributed. For example, Value could be "3.00A" or "5.00.RC2". + /// - SpecialBuild: The Value member describes how this version of the file differs from the + /// normal version. This entry should only be present if the VS_FF_SPECIALBUILD flag is + /// set in the dwFileFlags member of the VS_FIXEDFILEINFO structure. For example, Value + /// could be "Private build for Olivetti solving mouse problems on M250 and M250E computers". + /// + public string? Key { get; set; } + + /// + /// As many zero words as necessary to align the Value member on a 32-bit boundary. + /// + public ushort Padding { get; set; } + + /// + /// A zero-terminated string. See the szKey member description for more information. + /// + public string? Value { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/StringFileInfo.cs b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/StringFileInfo.cs new file mode 100644 index 00000000..f7098f02 --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/StringFileInfo.cs @@ -0,0 +1,43 @@ +namespace SabreTools.Serialization.Models.PortableExecutable.Resource.Entries +{ + /// + /// Represents the organization of data in a file-version resource. It contains version + /// information that can be displayed for a particular language and code page. + /// + /// + public sealed class StringFileInfo + { + /// + /// The length, in bytes, of the entire StringFileInfo block, including all + /// structures indicated by the Children member. + /// + public ushort Length { get; set; } + + /// + /// This member is always equal to zero. + /// + public ushort ValueLength { get; set; } + + /// + /// The type of data in the version resource. + /// + public VersionResourceType ResourceType { get; set; } + + /// + /// The Unicode string L"StringFileInfo". + /// + public string? Key { get; set; } + + /// + /// As many zero words as necessary to align the Children member on a 32-bit boundary. + /// + public ushort Padding { get; set; } + + /// + /// An array of one or more StringTable structures. Each StringTable structure's Key + /// member indicates the appropriate language and code page for displaying the text in + /// that StringTable structure. + /// + public StringTable[]? Children { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/StringTable.cs b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/StringTable.cs new file mode 100644 index 00000000..287c126c --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/StringTable.cs @@ -0,0 +1,46 @@ +namespace SabreTools.Serialization.Models.PortableExecutable.Resource.Entries +{ + /// + /// Represents the organization of data in a file-version resource. It contains language + /// and code page formatting information for the strings specified by the Children member. + /// A code page is an ordered character set. + /// + /// + public sealed class StringTable + { + /// + /// The length, in bytes, of this StringTable structure, including all structures + /// indicated by the Children member. + /// + public ushort Length { get; set; } + + /// + /// This member is always equal to zero. + /// + public ushort ValueLength { get; set; } + + /// + /// The type of data in the version resource. + /// + public VersionResourceType ResourceType { get; set; } + + /// + /// An 8-digit hexadecimal number stored as a Unicode string. The four most significant + /// digits represent the language identifier. The four least significant digits represent + /// the code page for which the data is formatted. Each Microsoft Standard Language + /// identifier contains two parts: the low-order 10 bits specify the major language, + /// and the high-order 6 bits specify the sublanguage. + /// + public string? Key { get; set; } + + /// + /// As many zero words as necessary to align the Children member on a 32-bit boundary. + /// + public ushort Padding { get; set; } + + /// + /// An array of one or more StringData structures. + /// + public StringData[]? Children { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/VarData.cs b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/VarData.cs new file mode 100644 index 00000000..48796951 --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/VarData.cs @@ -0,0 +1,50 @@ +namespace SabreTools.Serialization.Models.PortableExecutable.Resource.Entries +{ + /// + /// Represents the organization of data in a file-version resource. It typically contains a + /// list of language and code page identifier pairs that the version of the application or + /// DLL supports. + /// + /// + public sealed class VarData + { + /// + /// The length, in bytes, of the Var structure. + /// + public ushort Length { get; set; } + + /// + /// The size, in words, of the Value member. + /// + public ushort ValueLength { get; set; } + + /// + /// The type of data in the version resource. + /// + public VersionResourceType ResourceType { get; set; } + + /// + /// The Unicode string L"Translation". + /// + public string? Key { get; set; } + + /// + /// As many zero words as necessary to align the Value member on a 32-bit boundary. + /// + public ushort Padding { get; set; } + + /// + /// An array of one or more values that are language and code page identifier pairs. + /// + /// If you use the Var structure to list the languages your application or DLL supports + /// instead of using multiple version resources, use the Value member to contain an array + /// of DWORD values indicating the language and code page combinations supported by this + /// file. The low-order word of each DWORD must contain a Microsoft language identifier, + /// and the high-order word must contain the IBM code page number. Either high-order or + /// low-order word can be zero, indicating that the file is language or code page + /// independent. If the Var structure is omitted, the file will be interpreted as both + /// language and code page independent. + /// + public uint[]? Value { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/VarFileInfo.cs b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/VarFileInfo.cs new file mode 100644 index 00000000..e9fc0976 --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/VarFileInfo.cs @@ -0,0 +1,41 @@ +namespace SabreTools.Serialization.Models.PortableExecutable.Resource.Entries +{ + /// + /// Represents the organization of data in a file-version resource. It contains version + /// information not dependent on a particular language and code page combination. + /// + /// + public sealed class VarFileInfo + { + /// + /// The length, in bytes, of the entire VarFileInfo block, including all structures + /// indicated by the Children member. + /// + public ushort Length { get; set; } + + /// + /// This member is always equal to zero. + /// + public ushort ValueLength { get; set; } + + /// + /// The type of data in the version resource. + /// + public VersionResourceType ResourceType { get; set; } + + /// + /// The Unicode string L"VarFileInfo". + /// + public string? Key { get; set; } + + /// + /// As many zero words as necessary to align the Children member on a 32-bit boundary. + /// + public ushort Padding { get; set; } + + /// + /// Typically contains a list of languages that the application or DLL supports. + /// + public VarData[]? Children { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/VersionInfo.cs b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/VersionInfo.cs new file mode 100644 index 00000000..7262e9c7 --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Resource/Entries/VersionInfo.cs @@ -0,0 +1,61 @@ +namespace SabreTools.Serialization.Models.PortableExecutable.Resource.Entries +{ + /// + /// Represents the organization of data in a file-version resource. It is the root + /// structure that contains all other file-version information structures. + /// + /// + public sealed class VersionInfo + { + /// + /// The length, in bytes, of the VS_VERSIONINFO structure. This length does not + /// include any padding that aligns any subsequent version resource data on a + /// 32-bit boundary. + /// + public ushort Length { get; set; } + + /// + /// The length, in bytes, of the Value member. This value is zero if there is no + /// Value member associated with the current version structure. + /// + public ushort ValueLength { get; set; } + + /// + /// The type of data in the version resource. This member is 1 if the version resource + /// contains text data and 0 if the version resource contains binary data. + /// + public VersionResourceType ResourceType { get; set; } + + /// + /// The Unicode string L"VS_VERSION_INFO". + /// + public string? Key { get; set; } + + /// + /// Contains as many zero words as necessary to align the Value member on a 32-bit boundary. + /// + public ushort Padding1 { get; set; } + + /// + /// Arbitrary data associated with this VS_VERSIONINFO structure. The ValueLength member + /// specifies the length of this member; if ValueLength is zero, this member does not exist. + /// + public FixedFileInfo? Value { get; set; } + + /// + /// As many zero words as necessary to align the Children member on a 32-bit boundary. + /// These bytes are not included in wValueLength. This member is optional. + /// + public ushort Padding2 { get; set; } + + /// + /// The StringFileInfo structure to store user-defined string information data. + /// + public StringFileInfo? StringFileInfo { get; set; } + + /// + /// The VarFileInfo structure to store language information data. + /// + public VarFileInfo? VarFileInfo { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/Resource/ResourceHeader.cs b/SabreTools.Serialization/Models/PortableExecutable/Resource/ResourceHeader.cs new file mode 100644 index 00000000..00fcb9c1 --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/Resource/ResourceHeader.cs @@ -0,0 +1,99 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.PortableExecutable.Resource +{ + /// + /// Contains information about the resource header itself and the data specific to + /// this resource. This structure is not a true C-language structure, because it + /// contains variable-length members. The structure definition provided here is for + /// explanation only; it is not present in any standard header file. + /// + /// + [StructLayout(LayoutKind.Sequential)] + public sealed class ResourceHeader + { + /// + /// The size, in bytes, of the data that follows the resource header for this + /// particular resource. It does not include any file padding between this + /// resource and any resource that follows it in the resource file. + /// + public uint DataSize; + + /// + /// The size, in bytes, of the resource header data that follows. + /// + public uint HeaderSize; + + /// + /// The resource type. The TYPE member can either be a numeric value or a + /// null-terminated Unicode string that specifies the name of the type. See the + /// following Remarks section for a description of Name or Ordinal type members. + /// + /// If the TYPE member is a numeric value, it can specify either a standard or a + /// user-defined resource type. If the member is a string, then it is a + /// user-defined resource type. + /// + /// Values less than 256 are reserved for system use. + /// + [MarshalAs(UnmanagedType.U4)] + public ResourceType ResourceType; + + /// + /// A name that identifies the particular resource. The NAME member, like the TYPE + /// member, can either be a numeric value or a null-terminated Unicode string. + /// See the following Remarks section for a description of Name or Ordinal type + /// members. + /// + /// You do not need to add padding for DWORD alignment between the TYPE and NAME + /// members because they contain WORD data. However, you may need to add a WORD of + /// padding after the NAME member to align the rest of the header on DWORD boundaries. + /// + public uint Name; + + /// + /// A predefined resource data version. This will determine which version of the + /// resource data the application should use. + /// + public uint DataVersion; + + /// + /// A set of attribute flags that can describe the state of the resource. Modifiers + /// in the .RC script file assign these attributes to the resource. The script + /// identifiers can assign the following flag values. + /// + /// Applications do not use any of these attributes. The attributes are permitted + /// in the script for backward compatibility with existing scripts, but they are + /// ignored. Resources are loaded when the corresponding module is loaded, and are + /// freed when the module is unloaded. + /// + [MarshalAs(UnmanagedType.U2)] + public MemoryFlags MemoryFlags; + + /// + /// The language for the resource or set of resources. Set the value for this member + /// with the optional LANGUAGE resource definition statement. The parameters are + /// constants from the Winnt.h file. + /// + /// Each resource includes a language identifier so the system or application can + /// select a language appropriate for the current locale of the system. If there are + /// multiple resources of the same type and name that differ only in the language of + /// the strings within the resources, you will need to specify a LanguageId for each + /// one. + /// + public ushort LanguageId; + + /// + /// A user-defined version number for the resource data that tools can use to read and + /// write resource files. Set this value with the optional VERSION resource definition + /// statement. + /// + public uint Version; + + /// + /// Specifies user-defined information about the resource that tools can use to read and + /// write resource files. Set this value with the optional CHARACTERISTICS resource + /// definition statement. + /// + public uint Characteristics; + } +} diff --git a/SabreTools.Serialization/Models/PortableExecutable/TLS/Directory.cs b/SabreTools.Serialization/Models/PortableExecutable/TLS/Directory.cs new file mode 100644 index 00000000..ccded4e6 --- /dev/null +++ b/SabreTools.Serialization/Models/PortableExecutable/TLS/Directory.cs @@ -0,0 +1,55 @@ +namespace SabreTools.Serialization.Models.PortableExecutable.TLS +{ + /// + public sealed class Directory + { + /// + /// The starting address of the TLS template. The template is a block of data + /// that is used to initialize TLS data. The system copies all of this data + /// each time a thread is created, so it must not be corrupted. Note that this + /// address is not an RVA; it is an address for which there should be a base + /// relocation in the .reloc section. + /// + /// This value is 32-bit if PE32 and 64-bit if PE32+ + public ulong RawDataStartVA { get; set; } + + /// + /// The address of the last byte of the TLS, except for the zero fill. As + /// with the Raw Data Start VA field, this is a VA, not an RVA. + /// + /// This value is 32-bit if PE32 and 64-bit if PE32+ + public ulong RawDataEndVA { get; set; } + + /// + /// The location to receive the TLS index, which the loader assigns. This + /// location is in an ordinary data section, so it can be given a symbolic + /// name that is accessible to the program. + /// + /// This value is 32-bit if PE32 and 64-bit if PE32+ + public ulong AddressOfIndex { get; set; } + + /// + /// The pointer to an array of TLS callback functions. The array is + /// null-terminated, so if no callback function is supported, this field + /// points to 4 bytes set to zero. + /// + /// This value is 32-bit if PE32 and 64-bit if PE32+ + public ulong AddressOfCallbacks { get; set; } + + /// + /// The size in bytes of the template, beyond the initialized data delimited + /// by the Raw Data Start VA and Raw Data End VA fields. The total template + /// size should be the same as the total size of TLS data in the image file. + /// The zero fill is the amount of data that comes after the initialized + /// nonzero data. + /// + public uint SizeOfZeroFill { get; set; } + + /// + /// The four bits [23:20] describe alignment info. Possible values are those + /// defined as IMAGE_SCN_ALIGN_*, which are also used to describe alignment + /// of section in object files. The other 28 bits are reserved for future use. + /// + public uint Characteristics { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/SafeDisc/Constants.cs b/SabreTools.Serialization/Models/SafeDisc/Constants.cs new file mode 100644 index 00000000..1fa2bb6e --- /dev/null +++ b/SabreTools.Serialization/Models/SafeDisc/Constants.cs @@ -0,0 +1,9 @@ +namespace SabreTools.Serialization.Models.SafeDisc +{ + public static class Constants + { + public const uint EncryptedFileEntrySignature1 = 0xA8726B03; + + public const uint EncryptedFileEntrySignature2 = 0xEF01996C; + } +} diff --git a/SabreTools.Serialization/Models/SafeDisc/EncryptedFileEntry.cs b/SabreTools.Serialization/Models/SafeDisc/EncryptedFileEntry.cs new file mode 100644 index 00000000..e8fba1e2 --- /dev/null +++ b/SabreTools.Serialization/Models/SafeDisc/EncryptedFileEntry.cs @@ -0,0 +1,33 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.SafeDisc +{ + /// + [StructLayout(LayoutKind.Sequential)] + public class EncryptedFileEntry + { + /// + /// 0xA8726B03 + /// + public uint Signature1; + + /// + /// 0xEF01996C + /// + public uint Signature2; + + public uint FileNumber; + + public uint Offset1; + + public uint Offset2; + + public uint Unknown1; + + public uint Unknown2; + + /// 0x0D bytes + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x0D)] + public byte[]? Name; + } +} diff --git a/SabreTools.Serialization/Models/SecuROM/AddD.cs b/SabreTools.Serialization/Models/SecuROM/AddD.cs new file mode 100644 index 00000000..9723b921 --- /dev/null +++ b/SabreTools.Serialization/Models/SecuROM/AddD.cs @@ -0,0 +1,61 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.SecuROM +{ + /// + /// Overlay data associated with SecuROM executables + /// + /// + /// All information in this file has been researched in a clean room + /// environment by using sample from legally obtained software that + /// is protected by SecuROM. + /// + public sealed class AddD + { + /// + /// "AddD", Identifier? + /// + public uint Signature { get; set; } + + /// s + /// Unknown (Entry count?) + /// + /// + /// 3 in EXPUNGED, 3.17.00.0017, 3.17.00.0019 + /// 3 in 4.47.00.0039, 4.84.00.0054, 4.84.69.0037, 4.84.76.7966, 4.84.76.7968, 4.85.07.0009 + /// + public uint EntryCount { get; set; } + + /// + /// Version, always 8 bytes? + /// + [MarshalAs(UnmanagedType.LPStr)] + public string? Version; + + /// + /// Unknown (Build? Formatted as a string) + /// + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public char[]? Build; + + /// + /// Unknown (0x14h), Variable number of bytes before entry table + /// + /// + /// 44 bytes in EXPUNGED, 3.17.00.0017, 3.17.00.0019, 4.47.00.0039 + /// 112 bytes in 4.84.00.0054, 4.84.69.0037, 4.84.76.7966, 4.84.76.7968, 4.85.07.0009 + /// 112 byte range contains a fixed-length string at 0x2C, possibly a product ID? + /// "801400-001" in 4.84.00.0054 + /// "594130-001" in 4.84.69.0037 + /// "554900-001" in 4.84.76.7966 + /// "554900-001" in 4.84.76.7968 + /// "548520-001" in 4.85.07.0009 + /// + public byte[]? Unknown14h { get; set; } + + /// + /// Entry table + /// + public AddDEntry[]? Entries { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/SecuROM/AddDEntry.cs b/SabreTools.Serialization/Models/SecuROM/AddDEntry.cs new file mode 100644 index 00000000..8d497419 --- /dev/null +++ b/SabreTools.Serialization/Models/SecuROM/AddDEntry.cs @@ -0,0 +1,79 @@ +using System.Runtime.InteropServices; + +namespace SabreTools.Serialization.Models.SecuROM +{ + /// + /// Overlay data associated with SecuROM executables + /// + /// + /// All information in this file has been researched in a clean room + /// environment by using sample from legally obtained software that + /// is protected by SecuROM. + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public sealed class AddDEntry + { + /// + /// Physical offset of the embedded file + /// + public uint PhysicalOffset; + + /// + /// Length of the embedded file + /// + /// The last entry seems to be 4 bytes short in 4.47.00.0039 + public uint Length; + + /// + /// Unknown (0x08) + /// + /// 3149224 [3496, 48] in the sample (all 3 entries) in 4.47.00.0039 + public uint Unknown08h; + + /// + /// Unknown (0x0C) + /// + /// 3147176 [1448, 48] in the sample (all 3 entries) in 4.47.00.0039 + public uint Unknown0Ch; + + /// + /// Unknown (0x10) + /// + /// 3149224 [3496, 48] in the sample (all 3 entries) in 4.47.00.0039 + public uint Unknown10h; + + /// + /// Unknown (0x14) + /// + /// 1245044 [65396, 18] in the sample (all 3 entries) in 4.47.00.0039 + public uint Unknown14h; + + /// + /// Unknown (0x18) + /// + /// 4214725 [20421, 64] in the sample (all 3 entries) in 4.47.00.0039 + public uint Unknown18h; + + /// + /// Unknown (0x1C) + /// + /// 2 [2, 0] in the sample (all 3 entries) in 4.47.00.0039 + public uint Unknown1Ch; + + /// + /// Entry file name (null-terminated) + /// + /// 12 bytes long in the sample (all 3 entries) in 4.47.00.0039 + [MarshalAs(UnmanagedType.LPStr)] + public string? FileName; + + /// + /// Unknown (0x2C) + /// + /// + /// Offset based on consistent-sized filenames (12 bytes) in 4.47.00.0039 + /// 132 [132, 0] in the sample (all 3 entries) in 4.47.00.0039 + /// + public uint Unknown2Ch; + } +} diff --git a/SabreTools.Serialization/Models/SecuROM/Constants.cs b/SabreTools.Serialization/Models/SecuROM/Constants.cs new file mode 100644 index 00000000..fc2a941a --- /dev/null +++ b/SabreTools.Serialization/Models/SecuROM/Constants.cs @@ -0,0 +1,130 @@ + +namespace SabreTools.Serialization.Models.SecuROM +{ + public static class Constants + { + #region AddD + + public const string AddDMagicString = "AddD"; + + public static readonly byte[] AddDMagicBytes = [0x41, 0x64, 0x64, 0x44]; + + #endregion + + #region DFA + + public static readonly string DFAMagicString = "SDFA" + (char)0x04 + (char)0x00 + (char)0x00 + (char)0x00; + + public static readonly byte[] DFAMagicBytes = [0x53, 0x44, 0x46, 0x41, 0x04, 0x00, 0x00, 0x00]; + + #region Keys + + /// + /// 128-bit value, possibly a GUID + /// + public const string COID = "COID"; + + /// + /// 128-bit value, possibly a GUID + /// + /// Only a value of D0 A2 25 C7 16 20 B7 43 99 74 2A BB 39 6B C3 57 has been found + public const string CUID = "CUID"; + + /// + /// Encrypted data section + /// + public const string DATA = "DATA"; + + /// + /// Header version (?) + /// + /// Only a value of 0C 00 00 00 has been found + public const string HVER = "HVER"; + + /// + /// Unknown value + /// + public const string INVE = "INVE"; + + /// + /// Unknown key value + /// + public const string KEYB = "KEYB"; + + /// + /// Unknown key value + /// + public const string KEYL = "KEYL"; + + /// + /// MAC address (?) + /// + public const string MAC1 = "MAC1"; + + /// + /// MAC address (?) + /// + public const string MAC2 = "MAC2"; + + /// + /// Padding section + /// + /// Only a length of 832 has been found + public const string PAD1 = "PAD1"; + + /// + /// Private key ID (?) + /// + public const string PKID = "PKID"; + + /// + /// Private key name (?) + /// + /// Seemingly a UTF-16 string + public const string PKNA = "PKNA"; + + /// + /// Size of the decrypted executable + /// + public const string RAWS = "RAWS"; + + /// + /// 128-bit value, possibly a GUID + /// + /// Only a value of all zeroes has been found + public const string SCID = "SCID"; + + /// + /// Time stored in NTFS filetime + /// + /// + public const string TIME = "TIME"; + + /// + /// First URL to connect to + /// + public const string UR01 = "UR01"; + + /// + /// Second URL to connect to + /// + public const string UR02 = "UR02"; + + /// + /// Unknown value + /// + public const string XSPF = "XSPF"; + + #endregion + + #endregion + + #region Matroshka + + public const string MatroshkaMagicString = "MatR"; + + public static readonly byte[] MatroshkaMagicBytes = [0x4D, 0x61, 0x74, 0x52]; + + #endregion + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/SecuROM/DFAEntry.cs b/SabreTools.Serialization/Models/SecuROM/DFAEntry.cs new file mode 100644 index 00000000..bb49b585 --- /dev/null +++ b/SabreTools.Serialization/Models/SecuROM/DFAEntry.cs @@ -0,0 +1,24 @@ +namespace SabreTools.Serialization.Models.SecuROM +{ + /// + /// Represents a single key-length-value tuple in a + /// SecuROM DFA file + /// + public class DFAEntry + { + /// + /// Entry name, always 4 ASCII characters + /// + public string? Name { get; set; } + + /// + /// Length of the value in bytes + /// + public uint Length { get; set; } + + /// + /// Value of the entry whose length is given by + /// + public byte[]? Value { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/SecuROM/DFAFile.cs b/SabreTools.Serialization/Models/SecuROM/DFAFile.cs new file mode 100644 index 00000000..089ac4b9 --- /dev/null +++ b/SabreTools.Serialization/Models/SecuROM/DFAFile.cs @@ -0,0 +1,27 @@ +namespace SabreTools.Serialization.Models.SecuROM +{ + /// + /// Most DFA-protected files seem to also have additional encryption, + /// possibly SecuROM DFE. Only early RC-encrypted executables can be + /// parsed beyond the initial header. + /// + public class DFAFile + { + /// + /// "SDFA" 0x04 0x00 0x00 0x00 + /// + /// 8 bytes + public byte[]? Signature { get; set; } + + /// + /// Unknown value, possibly a block or header size + /// + /// Only a value of 0x400 has been found + public uint BlockOrHeaderSize { get; set; } + + /// + /// All entries in the file + /// + public DFAEntry[]? Entries { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/SecuROM/Enums.cs b/SabreTools.Serialization/Models/SecuROM/Enums.cs new file mode 100644 index 00000000..638b77a0 --- /dev/null +++ b/SabreTools.Serialization/Models/SecuROM/Enums.cs @@ -0,0 +1,36 @@ +namespace SabreTools.Serialization.Models.SecuROM +{ + public enum MatroshkaEntryType : uint + { + /// + /// Helper or activation executable + /// + Helper = 0x01, + + /// + /// Main executable, usually one of the following: + /// - RC-encrypted executable to be decrypted later + /// - Main game program executable + /// - Revoker executable + /// + /// Usually the second entry + Main = 0x02, + + /// + /// Required libraries for the main executable + /// + /// + /// Examples include: + /// - DFA.dll for RC-encrypted executables + /// - paul.dll for PA-protected games + /// - remover.exe for revocation + /// executables. + /// + Dependency = 0x04, + + /// + /// Similar use to + /// + Unknown0x08 = 0x08, + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/SecuROM/MatroshkaEntry.cs b/SabreTools.Serialization/Models/SecuROM/MatroshkaEntry.cs new file mode 100644 index 00000000..f1513f2b --- /dev/null +++ b/SabreTools.Serialization/Models/SecuROM/MatroshkaEntry.cs @@ -0,0 +1,65 @@ +namespace SabreTools.Serialization.Models.SecuROM +{ + public class MatroshkaEntry + { + /// + /// File entry path, either 256 or 512 bytes + /// + /// + /// Versions without a key prefix are 256 bytes. + /// Versions with key values either are 256 or 512 bytes. + /// Stored as a string as the rest of the 256/512 bytes are just padding. + /// + public string? Path { get; set; } + + /// + /// Type of the entry data + /// + public MatroshkaEntryType EntryType { get; set; } + + /// + /// Data size + /// + public uint Size { get; set; } + + /// + /// Data offset within the package + /// + public uint Offset { get; set; } + + /// + /// Unknown value only seen in later versions + /// + /// Does not indicate that the offset is or isn't a 64-bit value + public uint? Unknown { get; set; } + + /// + /// File modification time, stored in NTFS filetime. + /// + /// + public ulong ModifiedTime { get; set; } + + /// + /// File creation time, stored in NTFS filetime. + /// + /// + public ulong CreatedTime { get; set; } + + /// + /// File access time, stored in NTFS filetime. + /// + /// + public ulong AccessedTime { get; set; } + + /// + /// MD5 hash of the data + /// + /// 16 bytes + public byte[]? MD5 { get; set; } + + /// + /// The file data, stored as a byte array + /// + public byte[]? FileData { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/SecuROM/MatroshkaPackage.cs b/SabreTools.Serialization/Models/SecuROM/MatroshkaPackage.cs new file mode 100644 index 00000000..19eb3458 --- /dev/null +++ b/SabreTools.Serialization/Models/SecuROM/MatroshkaPackage.cs @@ -0,0 +1,86 @@ +namespace SabreTools.Serialization.Models.SecuROM +{ + /// + /// Securom Matroschka Package PE section + /// + /// + /// Offered by SecuROM, its main purpose seems to be managing some sort + /// of SecuROM-related operation involving multiple temporary files + /// contained within the package. Observed in Release Control executables, + /// Product Activation Revocation executables, and in some regular + /// Product-Activation-protected releases (such as the digital download + /// releases of Neverwinter Nights 2 and Test Drive Unlimited) where the + /// game executable, paul.dll and other PA-related files are stored in + /// the matroschka package. + /// + public class MatroshkaPackage + { + /// + /// "MatR" + /// + /// 4 bytes + public string? Signature { get; set; } + + /// + /// Number of internal entries + /// + public uint EntryCount { get; set; } + + #region Longer Header only + + // The combination of the 4 following values have only been seen in + // one of 4 distinct patterns. The meaning of these patterns is unknown. + // - 0 0 0 + // - 0 0 1 + // - 0 1 1 + // - 1 1 1 + // These values do not seem to have a link to whether the paths included + // in entries are 256- or 512-byte. There also do not seem to be any links + // between these values and the hex string values. + // There is one example of "0 0 0" which contains a key hex string of all + // 0x00 values and 256-byte paths. + + /// + /// One of four unknown values only observed on longer header matroschka sections + /// + /// Only values of 0 or 1 have been found + public uint? UnknownRCValue1 { get; set; } + + /// + /// One of four unknown values only observed on longer header matroschka sections + /// + /// Only values of 0 or 1 have been found + public uint? UnknownRCValue2 { get; set; } + + /// + /// One of four unknown values only observed on longer header matroschka sections + /// + /// Only values of 0 or 1 have been found + public uint? UnknownRCValue3 { get; set; } + + /// + /// 32-character hex string + /// + /// + /// This is all zeroes for all observed longer header non-RC matroschka sections. For RC sections, this is + /// always 630A411277DE8A4B9BB8DF2A14AC4C28, except for the executables for Crysis Wars and Crysis + /// Warhead, which are 9D2593B31A01E041AF6EDC15AEF5B969. Those two are noteworthy as they appear to be the + /// earliest known RC games, have a strange key in the encrypted executable, and are the only games that cannot + /// currently be manually unlocked (and thus, cannot be unlocked at all at the moment). So, this may indicate + /// something about version, functionality, or otherwise? + /// + public string? KeyHexString { get; set; } + + /// + /// Padding for alignment, always 0x00000000 + /// + public uint? Padding { get; set; } + + #endregion + + /// + /// Entries array whose length is given by + /// + public MatroshkaEntry[]? Entries { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/AddDirectoryToPath.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/AddDirectoryToPath.cs new file mode 100644 index 00000000..5d98776a --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/AddDirectoryToPath.cs @@ -0,0 +1,36 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Add Directory to PATH + /// + /// This action adds a directory to the PATH environment variable, as set in Autoexec.bat. + /// The directory is appended to every occurrence of the SET PATH statement that does not + /// already contain it. A SET PATH statement is added if none exists. The system restarts at + /// the end of installation so that the new PATH takes effect. + /// + /// + /// This action is called through Call DLL Function and is mapped to "f0". + /// + /// + public class AddDirectoryToPath : FunctionData + { + /// + /// Flags from the argument data + /// + /// + /// Encoded as a string, binary representation in script file. + /// Expected flags: + /// - Location to add [start of PATH or end of PATH] (unknown) + /// + No indication that this flag is respected, if it exists + /// - Add to all PATH variables (unknown) + /// + Only seems to apply to AUTOEXEC.BAT-based paths? + /// + public byte DataFlags { get; set; } + + /// + /// Directory name to add to path + /// + /// May contain a variable name + public string? Directory { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/AddTextToInstallLog.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/AddTextToInstallLog.cs new file mode 100644 index 00000000..186160c4 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/AddTextToInstallLog.cs @@ -0,0 +1,28 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Add Text to INSTALL.LOG + /// + /// This action adds commands to the installation log (Install.log). + /// + /// Use the Open/Close Install.log action to create the installation log. + /// + /// As the installation runs on the destination computer, each action it performs is logged in + /// the installation log (installation of files, additions or changes to registry, and so on). + /// Failures are listed also, with the reason for failure. The uninstall reverses each action + /// recorded in the Install.log, starting at the bottom of the log and going up. Typically, you + /// add commands to the Install.log to customize the uninstall process for an application. + /// + /// Because the log is written continuously during installation, the location of the text in the + /// log depends on where in the script you place the Add Text to Install.log script line. + /// + /// + /// + public class AddTextToInstallLog : MachineStateData + { + /// + /// Text + /// + public string? Text { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/AddToAutoexecBat.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/AddToAutoexecBat.cs new file mode 100644 index 00000000..3f03f9c4 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/AddToAutoexecBat.cs @@ -0,0 +1,62 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Add to AUTOEXEC.BAT + /// + /// This action edits Autoexec.bat, which is executed during startup, allowing you to add + /// commands that are executed before Windows loads. + /// + /// Insert commands at a particular line number, or search the file for specific text and + /// insert the new line before, after, or in place of the existing line. The destination + /// computer is restarted after installation to force the new commands to take effect. + /// + /// + /// This action is called through Call DLL Function and is mapped to "f1". + /// + /// + public class AddToAutoexecBat : FunctionData + { + /// + /// Flags from the argument data + /// + /// + /// Encoded as a string, binary representation in script file. + /// Expected flags: + /// - Case Sensitive (0x01) + /// - Insert Action (unknown) + /// - Match Criteria (unknown) + /// - Ignore White Space (unknown) + /// - Make Backup File (unknown) + /// + public byte DataFlags { get; set; } + + /// + /// Full path to the text file to edit + /// + /// + /// Ignored because structure is shared with both + /// and + /// + public string? FileToEdit { get; set; } + + /// + /// Text to insert into the file + /// + public string? TextToInsert { get; set; } + + /// + /// Search for Text + /// + public string? SearchForText { get; set; } + + /// + /// Comment Text + /// + public string? CommentText { get; set; } + + /// + /// Line number to insert text at, 0 for append to end + /// + public int LineNumber { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/AddToConfigSys.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/AddToConfigSys.cs new file mode 100644 index 00000000..d216adc0 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/AddToConfigSys.cs @@ -0,0 +1,60 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Add to CONFIG.SYS + /// + /// This action edits the Config.sys file to add new commands. Insert commands at a + /// particular line number, or search the file for specific text and insert the new line before, + /// after, or in place of the existing line. The destination computer is restarted automatically + /// to force the new commands to take effect. + /// + /// + /// This action is called through Call DLL Function and is mapped to "f2". + /// + /// + public class AddToConfigSys : FunctionData + { + /// + /// Flags from the argument data + /// + /// + /// Encoded as a string, binary representation in script file. + /// Expected flags: + /// - Case Sensitive (0x01) + /// - Insert Action (unknown) + /// - Match Criteria (unknown) + /// - Ignore White Space (unknown) + /// - Make Backup File (unknown) + /// + public byte DataFlags { get; set; } + + /// + /// Full path to the text file to edit + /// + /// + /// Ignored because structure is shared with both + /// and + /// + public string? FileToEdit { get; set; } + + /// + /// Text to insert into the file + /// + public string? TextToInsert { get; set; } + + /// + /// Search for Text + /// + public string? SearchForText { get; set; } + + /// + /// Comment Text + /// + public string? CommentText { get; set; } + + /// + /// Line number to insert text at, 0 for append to end + /// + public int LineNumber { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/AddToSystemIni.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/AddToSystemIni.cs new file mode 100644 index 00000000..36d41f06 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/AddToSystemIni.cs @@ -0,0 +1,24 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Add to SYSTEM.INI + /// + /// (Windows 3.1x or Windows 9x only) This action adds a device entry to the 386Enh + /// section of the System.ini file. The destination computer is restarted automatically to + /// force the new device driver to be loaded. + /// + /// Do not use this action to modify the display driver (display=xxx) or any other non- + /// device entry. Instead, use the Edit INI action. + /// + /// + /// This action is called through Call DLL Function and is mapped to "f3". + /// + /// + public class AddToSystemIni : FunctionData + { + /// + /// Full commandline for the device + /// + public string? DeviceName { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/CallDllFunction.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/CallDllFunction.cs new file mode 100644 index 00000000..f74f34cf --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/CallDllFunction.cs @@ -0,0 +1,61 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Call DLL Function + /// + /// This action calls a .DLL function from a .DLL on the destination computer. They can be + /// be .DLLs you have written, .DLLs developed for WiseScript, or Windows .DLLs. You can + /// branch the script based on the returned results of a .DLL by setting the Action to Start + /// Block if Return Value True or Start While Loop. + /// + /// + /// This acts like the start of a block if a flag is set. + /// + /// + /// + public class CallDllFunction : MachineStateData + { + /// + /// Flags, unknown mapping + /// + /// + /// Expected Values: + /// - Start block if function returns true (0x02 or 0x03) + /// - Loop while function returns true (0x02 or 0x03) + /// - Hide progress bar before calling function (0x04) + /// - Unknown (0x08) - Internal library call? + /// - Unknown (0x10) - Results in the flag being (^ 0x30) + /// - Unknown (0x20) - Checked for existence along with 0x08 + /// not existing to run a function. It also results + /// in the flag value being (^ 0x30) + /// + public byte Flags { get; set; } + + /// + /// DLL path/name or NULL for Wise internal + /// + public string? DllPath { get; set; } + + /// + /// Function name + /// + public string? FunctionName { get; set; } + + /// + /// Args? + /// + /// In older/trimmed scripts, this seems to be missing? + public string? Operand_4 { get; set; } + + /// + /// Return variable from an external call + /// + /// In older/trimmed scripts, this seems to be missing? + public string? ReturnVariable { get; set; } + + /// + /// One entry per language count + /// + public FunctionData[]? Entries { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/CheckConfiguration.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/CheckConfiguration.cs new file mode 100644 index 00000000..2096ccb7 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/CheckConfiguration.cs @@ -0,0 +1,42 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Check Configuration + /// + /// This action tests the hardware configuration, operating system, and other characteristics + /// of the destination computer. As a result of this check, the action can display a message, + /// halt the installation after displaying a message, or start a conditional block. + /// + /// + /// This action is called through Call DLL Function and is mapped to "f12". + /// This acts like the start of a block if a flag is set. + /// + /// + public class CheckConfiguration : FunctionData + { + /// + /// Flags from the argument data + /// + /// + /// Encoded as a string, binary representation in script file. + /// Expected flags: + /// - System (unknown) + /// - Display Message Only (unknown) + /// - Abort Installation (unknown) + /// - Start Block (unknown) + /// + public byte DataFlags { get; set; } + + /// + /// Appears in the body of the message dialog box. Leave this blank to prevent the + /// message from appearing. + /// + /// If fully numeric, it was probably called Flags2 in the source + public string? Message { get; set; } + + /// + /// Dialog box title + /// + public string? Title { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/CheckDiskSpace.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/CheckDiskSpace.cs new file mode 100644 index 00000000..e7b868d6 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/CheckDiskSpace.cs @@ -0,0 +1,44 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Check Disk Space + /// + /// This action determines if enough disk space is available for the installation, based on + /// files that are always installed. You would use this action only if the WiseScript contains + /// Install File(s) actions that install files permanently on the destination computer. + /// + /// You can leave all fields blank and the action checks disk space for all files. This action + /// takes the cluster size of the disk into account. + /// + /// + /// This action is called through Call DLL Function and is mapped to "f23". + /// + /// + public class CheckDiskSpace : FunctionData + { + /// + /// Flags from the argument data + /// + /// + /// Encoded as a string, binary representation in script file. + /// Expected flags: + /// - Do not cancel during silent installation (unknown) + /// + public byte DataFlags { get; set; } + + /// + /// Required disk space for up to 3 additional disks + /// + public string? ReserveSpace { get; set; } + + /// + /// Variable to store the result of the space check + /// + public string? StatusVariable { get; set; } + + /// + /// Component variables + /// + public string? ComponentVariables { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/CheckHttpConnection.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/CheckHttpConnection.cs new file mode 100644 index 00000000..3ba4ade6 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/CheckHttpConnection.cs @@ -0,0 +1,45 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Check HTTP Connection + /// + /// This action determines whether a given URL is valid by using WinSock.dll to try to + /// download the HTML page. + /// + /// If the installation is not true 32-bit, specify both Win16 and Win32 error variables. Then, + /// the Win32 WinSock.dll is used, followed by the Win16 WinSock.dll. Otherwise, only the + /// 32-bit version is used. + /// + /// + /// This action is called through Call DLL Function and is mapped to "f38". + /// + /// + public class CheckHttpConnection : FunctionData + { + /// + /// URL to check + /// + /// Includes http:// + public string? UrlToCheck { get; set; } + + /// + /// 32-bit windosck.dll error text return + /// + public string? Win32ErrorTextVariable { get; set; } + + /// + /// 32-bit winsock.dll error code return + /// + public string? Win32ErrorNumberVariable { get; set; } + + /// + /// 16-bit windosck.dll error text return + /// + public string? Win16ErrorTextVariable { get; set; } + + /// + /// 16-bit winsock.dll error code return + /// + public string? Win16ErrorNumberVariable { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/CheckIfFileDirExists.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/CheckIfFileDirExists.cs new file mode 100644 index 00000000..d049f650 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/CheckIfFileDirExists.cs @@ -0,0 +1,47 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Check If File/Dir Exists + /// + /// This action determines if a file or directory exists, whether a directory is writable, or if a + /// .DLL is loaded into memory. It can perform different actions based on the result of the + /// check. + /// + /// + /// This action is called through Call DLL Function and is mapped to "f19". + /// This acts like the start of a block if a flag is set. + /// + /// + public class CheckIfFileDirExists : FunctionData + { + /// + /// Flags from the argument data + /// + /// + /// Encoded as a string, binary representation in script file. + /// Expected flags: + /// - Display Message Only (unknown) + /// - Abort Installation (unknown) + /// - Start Block (unknown) + /// - Start While Loop (unknown) + /// - Perform loop at least once (unknown) + /// + public byte DataFlags { get; set; } + + /// + /// Pathname + /// + public string? Pathname { get; set; } + + /// + /// Appears in the body of the message dialog box. Leave this blank to prevent the + /// message from appearing. + /// + public string? Message { get; set; } + + /// + /// Dialog box title + /// + public string? Title { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/ConfigODBCDataSource.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/ConfigODBCDataSource.cs new file mode 100644 index 00000000..92df3dc9 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/ConfigODBCDataSource.cs @@ -0,0 +1,46 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Config ODBC Data Source + /// + /// This action configures an ODBC data source for use with an existing ODBC (Open + /// Database Connectivity) driver. + /// + /// + /// + public class ConfigODBCDataSource : MachineStateData + { + /// + /// Flags + /// + /// + /// Expected flags: + /// - System (unknown) + /// - Display Message Only (unknown) + /// - Abort Installation (unknown) + /// - Start Block (unknown) + /// + public byte Flags { get; set; } + + /// + /// File format string + /// + /// + /// Formatted like "File Description (*.ext)" + /// + public string? FileFormat { get; set; } + + /// + /// Connection string for the data source + /// + /// + /// Contains the following fields in order, separated + /// by 0x7F characters, similar to function calls: + /// - DSN=: Driver Name + /// - DSN=: Data Source Name + /// - DESCRIPTION=: Description of the data source + /// - DBQ=: Path to the database + /// + public string? ConnectionString { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/CopyLocalFile.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/CopyLocalFile.cs new file mode 100644 index 00000000..98624428 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/CopyLocalFile.cs @@ -0,0 +1,42 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Copy Local File + /// + /// This action copies uncompressed files from a floppy disk, CD, the destination computer, + /// or a network drive. + /// + /// + /// + public class CopyLocalFile : MachineStateData + { + /// + /// Unknown, 0x0C + /// + public ushort Flags { get; set; } // 0x00 - 0x01 + + /// + /// Padding + /// + /// + /// 40 bytes, padding because structure is internally + /// shared with + /// + public byte[]? Padding { get; set; } // 0x02 - 0x2A + + /// + /// Destination path + /// + public string? Destination { get; set; } // 0x2B - ? + + /// + /// Description, one per language + 1 + /// + public string[]? Description { get; set; } + + /// + /// Source file + /// + public string? Source { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/CreateDirectory.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/CreateDirectory.cs new file mode 100644 index 00000000..65efa21d --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/CreateDirectory.cs @@ -0,0 +1,23 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Create Directory + /// + /// Directories are created when files are installed to them. Use this action only to create an + /// empty directory on the destination computer. + /// + /// When a WiseScript is called by a Windows Installer installation, you also can create a + /// directory on the Features or Components tabs of Setup Editor in Windows Installer + /// Editor. + /// + /// + /// + public class CreateDirectory : MachineStateData + { + /// + /// Pathname of the directory to create + /// + /// Should start with a variable + public string? Pathname { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/CustomDialogSet.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/CustomDialogSet.cs new file mode 100644 index 00000000..1f84e9ac --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/CustomDialogSet.cs @@ -0,0 +1,38 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Custom Dialog + /// + /// Use this action to create your own dialog box or dialog box set. + /// + /// + /// + /// TODO: Document the decompressed file format + public class CustomDialogSet : MachineStateData + { + /// + /// Start of the deflated data + /// + public uint DeflateStart { get; set; } + + /// + /// End of the deflated data + /// + public uint DeflateEnd { get; set; } + + /// + /// Inflated data size + /// + public uint InflatedSize { get; set; } + + /// + /// Display variable name + /// + public string? DisplayVariable { get; set; } + + /// + /// Name + /// + public string? Name { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/DeflateEntry.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/DeflateEntry.cs new file mode 100644 index 00000000..6c00c6fe --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/DeflateEntry.cs @@ -0,0 +1,24 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Represents deflated file parameters + /// + /// + public class DeflateEntry + { + /// + /// Start of the deflated data + /// + public uint DeflateStart { get; set; } + + /// + /// End of the deflated data + /// + public uint DeflateEnd { get; set; } + + /// + /// Inflated data size + /// + public uint InflatedSize { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/DeleteFile.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/DeleteFile.cs new file mode 100644 index 00000000..47dc6693 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/DeleteFile.cs @@ -0,0 +1,30 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Delete File + /// + /// This action removes files from the destination computer. + /// + /// You do not need to delete temp files if you use the Get Temporary Filename action to + /// create them because they are deleted automatically. + /// + /// + /// + public class DeleteFile : MachineStateData + { + /// + /// Flags, unknown values + /// + /// + /// Expected flags: + /// - Include Sub-Directories (unknown) + /// - Remove Directory Containing Files (unknown) + /// + public byte Flags { get; set; } + + /// + /// Path name + /// + public string? Pathname { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/DisplayBillboard.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/DisplayBillboard.cs new file mode 100644 index 00000000..38cb5aa9 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/DisplayBillboard.cs @@ -0,0 +1,57 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Display Billboard + /// + /// This action displays a bitmap or .GRF file during installation if you have set the + /// background to display a gradient on the Screen page. Create .GRF files (scalable + /// bitmaps) with the Custom Billboard Editor. + /// + /// You can use up to 16 Display Billboard actions in the script. + /// + /// + /// + public class DisplayBillboard : MachineStateData + { + /// + /// Flags + /// + /// + /// Expected values: + /// - 0x3805 - Erase num?; Erase all? + /// - 0x4000 - Hide progress bar + /// + public ushort Flags { get; set; } // 0x01 - 0x02 + + /// + /// Flags(?) + /// + /// + /// Values from WISE0001.DLL + /// - >> 0x0F -> piVar3[10] + /// - & 0x4000 -> uVar8 = Operand_2 & 0x3FFF + /// - Unknown (0x8000) + /// + public ushort Operand_2 { get; set; } // 0x03 - 0x04 + + /// + /// Unknown + /// + /// + /// Values from WISE0001.DLL + /// - & 0x4000 -> uVar8 = Operand_3 & 0x3FFF + /// + public ushort Operand_3 { get; set; } // 0x05 - 0x06 + + /// + /// Deflate information + /// + /// One per language + public DeflateEntry[]? DeflateInfo { get; set; } // 0x07 - + + /// + /// Terminator? + /// + public byte Terminator { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/DisplayMessage.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/DisplayMessage.cs new file mode 100644 index 00000000..ea9c3fa2 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/DisplayMessage.cs @@ -0,0 +1,30 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Display Message + /// + /// This action displays a message dialog box and can optionally branch the script based on + /// the end user response. Without the branching option, this dialog box has an OK button, + /// which continues, and a Cancel button, which halts installation. + /// + /// + /// + public class DisplayMessage : MachineStateData + { + /// + /// Flags, unknown mapping + /// + /// + /// Expected flags: + /// - Message icon(?) + /// - Start If Block (0x01) + /// - No Cancel (unknown) + /// + public byte Flags { get; set; } + + /// + /// Strings, two per language (1 title and 1 message) + /// + public string[]? TitleText { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/EditIniFile.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/EditIniFile.cs new file mode 100644 index 00000000..4120e3a8 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/EditIniFile.cs @@ -0,0 +1,31 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Edit INI File + /// + /// This action edits an .INI file on the destination computer. To edit SYSTEM.INI, use the + /// Add to SYSTEM.INI action instead. + /// + /// + /// + public class EditIniFile : MachineStateData + { + /// + /// Path name to INI file + /// + /// Open for writing in append mode + public string? Pathname { get; set; } + + /// + /// INI section, represented by a Settings line + /// in the original script + /// + public string? Section { get; set; } + + /// + /// Multiline string containing values, each representing + /// a new Settings line in the original script + /// + public string? Values { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/EditRegistry.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/EditRegistry.cs new file mode 100644 index 00000000..6938eaf8 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/EditRegistry.cs @@ -0,0 +1,63 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Edit Registry + /// + /// This action adds, edits, or deletes registry keys or values. You can create registry entries + /// manually or import a registry file (.REG). + /// + /// + /// The documentation mentions that there are multiple options, including + /// deleting keys and values, updating values, and adding new key-value + /// pairs. As far as research has taken, this set of options does not + /// appear to be immediately mappable to the data below. + /// + /// + /// + public class EditRegistry : MachineStateData + { + /// + /// Flags and Root + /// + /// + /// To get the root value, do (FlagsAndRoot & 0x1F) + /// Flag values: + /// - 0x10 - Force backup of registry value (if 0x80 == 0) + /// + It overrides the values set by 0x24 and 0x25 + /// and then disables the flag after + /// - 0x40 - Delete? (If root is not 0?) + /// - 0x80 - Unknown + /// + public byte FlagsAndRoot { get; set; } + + /// + /// Data type, defaults to 0 if not defined + /// in source scripts + /// + public byte DataType { get; set; } + + /// + /// An unknown value that appears in some versions. + /// Its presence indicates to load an external DLL + /// for performing registry actions. Investigation + /// is needed on how to determine the script is the + /// version that uses this string or not. + /// + public string? UnknownFsllib { get; set; } + + /// + /// Key path + /// + public string? Key { get; set; } + + /// + /// New value + /// + public string? NewValue { get; set; } + + /// + /// Value name + /// + public string? ValueName { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/ElseIfStatement.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/ElseIfStatement.cs new file mode 100644 index 00000000..4fb6c896 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/ElseIfStatement.cs @@ -0,0 +1,30 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// ElseIf Statement + /// + /// This action is put inside an If block to check for another condition. It marks the + /// beginning of a block of code that is executed only if the condition checked by the If + /// Statement is false, all previous ElseIfs are false, and this ElseIf is true. You can use one + /// If Statement with multiple ElseIf Statements to check for multiple conditions. + /// + /// + /// + public class ElseIfStatement : MachineStateData + { + /// + /// Operator, values need to be mapped + /// + public byte Operator { get; set; } + + /// + /// Variable name + /// + public string? Variable { get; set; } + + /// + /// Value + /// + public string? Value { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/ElseStatement.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/ElseStatement.cs new file mode 100644 index 00000000..d0b6737b --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/ElseStatement.cs @@ -0,0 +1,20 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Else Statement + /// + /// This action marks the beginning of a section of instructions to be executed when the + /// condition specified in the matching If action is false. It takes no parameters, and + /// selecting it from the Actions list inserts it directly into the script with no further dialog + /// boxes or prompts. + /// + /// + /// This acts like the start of a block. + /// + /// + /// + public class ElseStatement : MachineStateData + { + // There is no data + } +} diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/EndBlockStatement.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/EndBlockStatement.cs new file mode 100644 index 00000000..fa617f9a --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/EndBlockStatement.cs @@ -0,0 +1,28 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// End Block / End Statement + /// + /// This action marks the end of an If block or a While loop. It takes no parameters, and + /// selecting it from the Action list inserts it directly into the script with no further dialog + /// boxes or prompts. + /// + /// + /// The documentation mentions that this statement should contain no data + /// but there is still an operand that is apparently present. It is unknown what + /// this value could map to. + /// + /// + /// + public class EndBlockStatement : MachineStateData + { + /// + /// Unknown, maybe flags? + /// + /// + /// 0x00 - ??? + /// 0x01 - ??? + /// + public byte Operand_1 { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/EndUserDefinedAction.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/EndUserDefinedAction.cs new file mode 100644 index 00000000..f97df616 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/EndUserDefinedAction.cs @@ -0,0 +1,19 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// End User-Defined Action + /// + /// You create a user-defined action by creating a separate WiseScript and saving it in the + /// Actions subdirectory of this product’s installation directory, or in the shared directory + /// that is specified in Preferences. + /// + /// + /// This acts like the end of a block. + /// + /// + /// + public class EndUserDefinedAction : MachineStateData + { + // There is no data + } +} diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/ExecuteProgram.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/ExecuteProgram.cs new file mode 100644 index 00000000..88e619c2 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/ExecuteProgram.cs @@ -0,0 +1,38 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Execute Program + /// + /// This action runs another .EXE. The .EXE can be a file that is already installed on the + /// destination computer, a file you installed as part of the installation, or a file you provide + /// on a separate disk. + /// + /// If the .EXE you plan to execute is coded to pass back a return value, the resulting return + /// value is put into the variables %INSTALL_RESULT% and %PROCEXITCODE%. If the + /// EXE passes back a return value, mark the Wait for Program to Exit check box. + /// + /// + /// + public class ExecuteProgram : MachineStateData + { + /// + /// Flags, unknown values + /// + public byte Flags { get; set; } + + /// + /// Path to the program to execute + /// + public string? Pathname { get; set; } + + /// + /// Command Line + /// + public string? CommandLine { get; set; } + + /// + /// Default directory name + /// + public string? DefaultDirectory { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/ExitInstallation.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/ExitInstallation.cs new file mode 100644 index 00000000..57d9b1da --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/ExitInstallation.cs @@ -0,0 +1,18 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Exit Installation + /// + /// This action exits the installation. + /// + /// No message appears unless you also set the RESTART variable. + /// + /// + /// This action is called through Call DLL Function and is mapped to "f28". + /// + /// + public class ExitInstallation : FunctionData + { + // There is no data + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/ExternalDllCall.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/ExternalDllCall.cs new file mode 100644 index 00000000..d42945da --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/ExternalDllCall.cs @@ -0,0 +1,20 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// External DLL Call + /// + /// This represents a call to an external DLL. + /// + /// + /// This action is called through Call DLL Function and is invoked when + /// the external DLL path is provided. + /// + /// + public class ExternalDllCall : FunctionData + { + /// + /// Arguments passed in from the Call DLL Function + /// + public string[]? Args { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/FindFileInPath.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/FindFileInPath.cs new file mode 100644 index 00000000..7ac82310 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/FindFileInPath.cs @@ -0,0 +1,55 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Find File in Path + /// + /// This action searches for a file on the destination computer. If more than one match + /// exists, only the first match is returned. + /// + /// + /// This action is called through Call DLL Function and is mapped to "f22". + /// This acts like the start of a block if the default value is omitted(?) + /// + /// + public class FindFileInPath : FunctionData + { + /// + /// Flags from the argument data + /// + /// + /// Encoded as a string, binary representation in script file. + /// Expected flags: + /// - Remove File Name (unknown) + /// + public byte DataFlags { get; set; } + + /// + /// Variable to store the path if it is found + /// + public string? VariableName { get; set; } + + /// + /// File name, not a full path + /// + /// Wildcard characters are not allowed + public string? FileName { get; set; } + + /// + /// Value to put in the variable if the file is not found + /// + /// Leave blank to evaluage to false for an if + public string? DefaultValue { get; set; } + + /// + /// Semicolon-delimited list of directories to search + /// + /// Variables are allowed. If blank, PATH is used. + public string? SearchDirectories { get; set; } + + /// + /// Optional description to display if the search takes longer than + /// 1.5 seconds to complete. + /// + public string? Description { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/FunctionData.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/FunctionData.cs new file mode 100644 index 00000000..92494c55 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/FunctionData.cs @@ -0,0 +1,7 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Base class for all function call data types + /// + public abstract class FunctionData { } +} diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/GetEnvironmentVariable.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/GetEnvironmentVariable.cs new file mode 100644 index 00000000..d8f39cb3 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/GetEnvironmentVariable.cs @@ -0,0 +1,40 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Get Environment Variable + /// + /// This action puts the value of a Windows environment variable into a WiseScript variable. + /// + /// + /// This action is called through Call DLL Function and is mapped to "f17". + /// + /// + public class GetEnvironmentVariable : FunctionData + { + /// + /// Flags from the argument data + /// + /// + /// Encoded as a string, binary representation in script file. + /// Expected flags: + /// - Remove File Name (non-zero value) + /// + public byte DataFlags { get; set; } + + /// + /// Variable name + /// + public string? Variable { get; set; } + + /// + /// Environment variable name + /// + public string? Environment { get; set; } + + /// + /// Optional default value used if environment variable + /// is not found + /// + public string? DefaultValue { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/GetRegistryKeyValue.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/GetRegistryKeyValue.cs new file mode 100644 index 00000000..a1a4b3b6 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/GetRegistryKeyValue.cs @@ -0,0 +1,51 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Get Registry Key Value + /// + /// This action puts the value of a registry key into a variable. Multi-line (MULTI_SZ) + /// registry values are read into a list format. + /// + /// + /// This action is called through Call DLL Function and is mapped to "f9". + /// + /// + public class GetRegistryKeyValue : FunctionData + { + /// + /// Flags from the argument data + /// + /// + /// Encoded as a string, binary representation in script file. + /// Expected flags: + /// - Remove File Name (unknown) + /// - Expand Environment Variables (unknown) + /// + public byte DataFlags { get; set; } + + /// + /// Variable name + /// + public string? Variable { get; set; } + + /// + /// Registry key + /// + public string? Key { get; set; } + + /// + /// Default value if not found + /// + public string? Default { get; set; } + + /// + /// Value name, blank for Win16 + /// + public string? ValueName { get; set; } + + /// + /// The root that contains the registry key. + /// + public string? Root { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/GetSystemInformation.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/GetSystemInformation.cs new file mode 100644 index 00000000..4e926aa5 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/GetSystemInformation.cs @@ -0,0 +1,57 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Get System Information + /// + /// This action retrieves information about the destination computer and puts it into a + /// variable. + /// + /// + /// + public class GetSystemInformation : MachineStateData + { + /// + /// Flags, values unknown + /// + /// + /// Expected flags: + /// - Retrieve Current Date/Time (unknown) + /// - Windows Version (unknown) + /// - DOS Version (unknown) + /// - K Bytes Physical Memory (unknown) + /// - File Date/Time Modified (unknown) + /// - File Version Number (unknown) + /// - Registered Owner Name (unknown) + /// - Registered Company Name (unknown) + /// - Drive Type for Pathname (unknown) + /// - First Network Drive (unknown) + /// - First CD-ROM Drive (unknown) + /// - Win32s Version (unknown) + /// - Full UNC Pathname + /// - Installer EXE Pathname + /// - File Size (Bytes) + /// - Volume Serial Number + /// - Volume Label + /// - Windows Logon Name + /// - Service Pack Number + /// - Current Date/Time (four-digit year) + /// - File Date/Time Modified (four-digit year) + /// - Disk Free Space (KBytes) + /// - Current Date/Time (Regional settings) + /// - UTC File Date/Time Modified + /// - Is OS 64 Bit + /// + public byte Flags { get; set; } + + /// + /// Variable name + /// + public string? Variable { get; set; } + + /// + /// Used only for operations that retrieve information + /// on files or directories + /// + public string? Pathname { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/GetTemporaryFilename.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/GetTemporaryFilename.cs new file mode 100644 index 00000000..1c4ec19b --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/GetTemporaryFilename.cs @@ -0,0 +1,21 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Get Temporary Filename + /// + /// This action generates a unique, temporary file name and stores it in a variable. Use the + /// temporary name when you need to install a file to the Windows Temp directory + /// (%TEMP%). Files that you create using this file name are deleted when the installation + /// finishes. Example: Use this to install a .DLL that is called during installation, and is then + /// no longer needed. + /// + /// + /// + public class GetTemporaryFilename : MachineStateData + { + /// + /// Variable to store the temporary file name + /// + public string? Variable { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/IfWhileStatement.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/IfWhileStatement.cs new file mode 100644 index 00000000..a63dfc6c --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/IfWhileStatement.cs @@ -0,0 +1,70 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// If Statement / While Statement + /// + /// This action marks the beginning of a conditional block of script, an If block. If the + /// condition specified in the If Statement is true, the lines inside the If block are executed. + /// The If block can also contain an Else or several ElseIf actions. + /// + /// This action begins a While loop. An End Statement must end the loop. As long as the + /// condition specified in the While Statement Settings dialog box is true, the script lines + /// inside the loop execute repeatedly. If the condition is not true, then the While loop is + /// exited, and the next script line is executed. + /// + /// + /// + public class IfWhileStatement : MachineStateData + { + /// + /// Flags, unknown values + /// + /// + /// Encoded as a string, binary representation in script file. + /// Expected flags: + /// - If or While loop (Possibly 0x10 == While, 0x20 == If) + /// - Perform While loop at least once (Possibly 0x40) + /// - Operation (Between 0x00 and 0x0F) + /// + Addition (unknown) + /// + Subtraction (unknown) + /// + Multiplication (unknown) + /// + Division (unknown) + /// + Left (unknown) + /// + Right (unknown) + /// + Mid (unknown) + /// + Concat (unknown) + /// + Instr (unknown) + /// + Before (unknown) + /// + After (unknown) + /// + Len (Possibly 0x0D) + /// + Lcase (unknown) + /// + Ucase (unknown) + /// + Ltrim (unknown) + /// + Rtrim (unknown) + /// + And (unknown) + /// + Or (unknown) + /// + Not (unknown) + /// + > (unknown) + /// + < (unknown) + /// + >= (unknown) + /// + <= (unknown) + /// + = (unknown) + /// + <> (unknown) + /// + /// If the Flags & 0x20 == 0 and Flags & 0x10 == 0, + /// the flag value in the stack is set back to + /// Flags ^ 0x60. + /// + public byte Flags { get; set; } + + /// + /// Variable name + /// + public string? Variable { get; set; } + + /// + /// Value + /// + public string? Value { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/IncludeScript.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/IncludeScript.cs new file mode 100644 index 00000000..5047abf5 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/IncludeScript.cs @@ -0,0 +1,25 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Include Script + /// + /// This action adds an additional script to the current installation script. During compile, + /// the include script is copied into the calling script at the location of the Include Script + /// action, resulting in a combination of the scripts. + /// + /// Include scripts can save time because you can develop a library of WiseScripts that + /// perform specific functions, like subroutines. You can re-use include scripts and share + /// them with colleagues. They typically contain just a few lines of code, such as calling an + /// .EXE or displaying a particular dialog box. Include scripts can be any size with the + /// limitation that the calling script plus include scripts cannot be more than 32,000 lines. + /// + /// + /// + public class IncludeScript : MachineStateData + { + /// + /// Count of sequential 0x1B bytes, excluding the original opcode + /// + public int Count { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/InsertLineIntoTextFile.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/InsertLineIntoTextFile.cs new file mode 100644 index 00000000..db8e9337 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/InsertLineIntoTextFile.cs @@ -0,0 +1,55 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Insert Line Into Text File + /// + /// This action edits a text file on the destination computer. Use it to edit configuration files + /// that cannot be edited by Edit INI File, Add Device to System.ini, Add Command to + /// Config.sys, or Add Command to Autoexec.bat. + /// + /// + /// This action is called through Call DLL Function and is mapped to "f25". + /// + /// + public class InsertLineIntoTextFile : FunctionData + { + /// + /// Flags from the argument data + /// + /// + /// Encoded as a string, binary representation in script file. + /// Expected flags: + /// - Case Sensitive (0x01) + /// - Insert Action (unknown) + /// - Match Criteria (unknown) + /// - Ignore White Space (unknown) + /// - Make Backup File (unknown) + /// + public byte DataFlags { get; set; } + + /// + /// Full path to the text file to edit + /// + public string? FileToEdit { get; set; } + + /// + /// Text to insert into the file + /// + public string? TextToInsert { get; set; } + + /// + /// Search for Text + /// + public string? SearchForText { get; set; } + + /// + /// Comment Text + /// + public string? CommentText { get; set; } + + /// + /// Line number to insert text at, 0 for append to end + /// + public int LineNumber { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/InstallDirectXComponents.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/InstallDirectXComponents.cs new file mode 100644 index 00000000..8dc0bb18 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/InstallDirectXComponents.cs @@ -0,0 +1,43 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Install DirectX Components + /// + /// Little is known about this function other than it seems to install any + /// local DirectX components, if necessary. No official documentation + /// is publicly available that contains a reference to this. + /// + /// + /// This action is called through Call DLL Function and is mapped to "f30". + /// + /// + public class InstallDirectXComponents : FunctionData + { + /// + /// Flags from the argument data + /// + /// + /// Encoded as a string, binary representation in script file. + /// Expected flags: + /// - 0x40 - Unsets itself and sets 0x200 if not already + /// - If final value & 0x3fffff7f == 0, return failure + /// + public byte DataFlags { get; set; } + + /// + /// Root path containing all DirectX components + /// + public string? RootPath { get; set; } + + /// + /// Path to the DSETUP.DLL to be used + /// + public string? LibraryPath { get; set; } + + /// + /// Unknown numeric value + /// + /// Not fully identified; replaces the flags if not 0? + public int SizeOrOffsetOrFlag { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/InstallFile.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/InstallFile.cs new file mode 100644 index 00000000..78d86da0 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/InstallFile.cs @@ -0,0 +1,102 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Install File + /// + /// This action installs files on the destination computer. Each file or directory to be installed + /// must have a separate Install File(s) action. + /// + /// + /// Multiple files can be included in the installer from + /// a single source Install File statement in the script. + /// Wildcards have been observed in a few examples to denote + /// entire directories or subdirectories being copied. + /// + /// + public class InstallFile : MachineStateData + { + /// + /// Values of 0x8000, 0x8100, 0x0000, 0x9800 0xA100 have been observed + /// + /// + /// Expected flags: + /// - Include Sub-Directories (unknown) + /// - Shared DLL Counter (unknown) + /// - No Progress Bar (unknown) + /// - Self-Register OCX/DLL/EXE/TLB (unknown) + /// - Replace Existing File [Always, Never, Check File [Doesn't Matter, Same or Older, Older]] (unknown) + /// - Retain Duplicates in Path (unknown) + /// + /// This is two separate fields in WISE0001.DLL (bVar1 and bVar2) + /// + /// if (bVar2 & 0x48) == 0 && (bVar1 & 0x40) == 0 + /// Checksum set? Verify the file if possible + /// if (bVar1 & 1) != 0 && action[0x13] != 0 + /// See Operand_7 + /// + public ushort Flags { get; set; } // 0x01 - 0x02 + + /// + /// Start of the deflated data + /// + public uint DeflateStart { get; set; } // 0x03 - 0x06 + + /// + /// End of the deflated data + /// + public uint DeflateEnd { get; set; } // 0x07 - 0x0A + + /// + /// MS-DOS date + /// + public ushort Date { get; set; } // 0x0B - 0x0C + + /// + /// MS-DOS time + /// + public ushort Time { get; set; } // 0x0D - 0x0E + + /// + /// Inflated data size + /// + public uint InflatedSize { get; set; } // 0x0F - 0x12 + + /// + /// Unknown, 20 * \0? Not seen in hl15of16.exe and hl1316.exe + /// + /// + /// 20 bytes + /// 0x13 (4 bytes) - if (bVar1 & 1) != 0 && [0x13] != 0 [BLOCK] + /// 0x13 (4 bytes) = local_70 + /// 0x17 (4 bytes) - local_6c + /// 0x1B (4 bytes) - local_68.PrivilegeCount + /// 0x1F (4 bytes) - local_68.Control + /// 0x23 (4 bytes) - local_68.Privilege[0].Luid.LowPart + /// + public byte[]? Operand_7 { get; set; } // 0x13 - 0x26 + + /// + /// CRC-32 checksum of the data + /// + /// Do not check when it is 0 + public uint Crc32 { get; set; } // 0x27 - 0x2A + + /// + /// Destination pathname + /// + public string? DestinationPathname { get; set; } // 0x2B - ? + + /// + /// One file text per language + /// + public string[]? Description { get; set; } + + /// + /// Source file + /// + /// + /// Unused because structure is internally shared with + /// + public string? Source { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/InvalidOperation.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/InvalidOperation.cs new file mode 100644 index 00000000..aa252d62 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/InvalidOperation.cs @@ -0,0 +1,15 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Invalid Operation + /// + /// This operation was found in WISE0001.DLL and appears to + /// abort installation with a return code of 0xfffffffe. + /// + /// + /// + public class InvalidOperation : MachineStateData + { + // There is no data + } +} diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/MachineStateData.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/MachineStateData.cs new file mode 100644 index 00000000..75730a7a --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/MachineStateData.cs @@ -0,0 +1,7 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Base class for all machine state data types + /// + public abstract class MachineStateData { } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/NewEvent.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/NewEvent.cs new file mode 100644 index 00000000..a59084b1 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/NewEvent.cs @@ -0,0 +1,38 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// New Event + /// + /// Event scripts handle events. (Example: The end user cancels the installation.) + /// + /// Mainline + /// + /// The primary script that’s executed during the normal installation process. It + /// contains placeholders for Cancel and Exit scripts. When you open a script, that script + /// is considered the “main installation script,” and is on the first tab below the + /// installation script. + /// + /// Exit + /// + /// The script that’s executed when the installation is complete, or when an Exit + /// Installation script command is executed. If you create a user-defined action, you + /// store its custom dialog box here. + /// + /// Cancel + /// + /// The script that’s executed when the end user cancels the installation. Because some + /// files might already be installed when the end user cancels, the Cancel script + /// contains the include script, rollback.wse, which returns the destination computer to + /// its pre-installation state. + /// + /// + /// + public class NewEvent : MachineStateData + { + /// + /// Padding bytes + /// + /// Either 0 or 6 bytes from samples + public byte[]? Padding { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/NoOp.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/NoOp.cs new file mode 100644 index 00000000..e9598d4a --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/NoOp.cs @@ -0,0 +1,15 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// No-op + /// + /// This operation was found in WISE0001.DLL and appears to + /// do nothing except move to the next operation. + /// + /// + /// + public class NoOp : MachineStateData + { + // There is no data + } +} diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/OpenCloseInstallLog.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/OpenCloseInstallLog.cs new file mode 100644 index 00000000..d040e116 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/OpenCloseInstallLog.cs @@ -0,0 +1,35 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Open/Close Install.log + /// + /// Use this action to create an installation log. + /// Normally, every file that is installed is recorded in the install.log. The uninstall works by + /// reading Install.log from bottom to top and reversing each recorded action. + /// + /// The Open/Close Install.log action lets you customize the uninstall, by turning logging off + /// and on at key points to prevent some actions from being recorded in the log. If you use + /// this action to stop logging, you must also use it to resume logging or no log file is + /// created. + /// + /// + /// + public class OpenCloseInstallLog : MachineStateData + { + /// + /// Flags, unknown values + /// + /// + /// Expected flags: + /// - Resume/Start writing entries into installation log (0x01/0x02?) + /// - Pause writing entries into installation log (0x00) + /// - Open new installation log (0x01/0x02?) + /// + public ushort Flags { get; set; } + + /// + /// Log name used when opening a new log + /// + public string? LogName { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/ParseString.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/ParseString.cs new file mode 100644 index 00000000..4f870d33 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/ParseString.cs @@ -0,0 +1,69 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Parse String + /// + /// This action splits a text string and places the results in two variables. + /// + /// You can split the string at a character or substring that you specify, which discards the + /// character or substring you specified. Example: If you split the string “ONE,TWO” at the + /// first occurrence of a comma, “ONE” is put into destination variable 1 and “TWO” is put + /// into the destination variable 2. If the character or substring is not found, the entire + /// string is put into destination variable 1, and nothing is put into destination variable 2. + /// The find is case-sensitive. + /// + /// You can also split a string at any arbitrary character position, which discards no + /// characters. Example: If you split the string “ONE,TWO” at character position four from + /// left, then “ONE,” is put into the destination variable 1 and “TWO” is put into the + /// destination variable 2. + /// + /// + /// This action is called through Call DLL Function and is mapped to "f27". + /// + /// + public class ParseString : FunctionData + { + /// + /// Flags from the argument data + /// + /// + /// Encoded as a string, binary representation in script file. + /// Expected flags: + /// - Operation (unknown) + /// - Trim Spaces (unknown) + /// - Ignore Case (unknown) + /// + public byte DataFlags { get; set; } + + /// + /// Source Value + /// + /// + /// You enter text and variables (examples: %MAINDIR% or %MAINDIR%\%PICTDIR%). + /// To include a literal percent (%) symbol, use %%. + /// + public string? Source { get; set; } + + /// + /// Pattern/Position at which to split + /// + /// + /// Character patterns are case-sensitive unless you mark Ignore Case. + /// To split at a pattern, enter any number of characters, including numbers, + /// and select one of the pattern options in Operation. To split a string + /// based on character position, enter the character position, where 1 is + /// the first character, and select one of the position options in Operation. + /// + public string? PatternPosition { get; set; } + + /// + /// Variable to store the first half of the string + /// + public string? DestinationVariable1 { get; set; } + + /// + /// Variable to store the second half of the string + /// + public string? DestinationVariable2 { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/PlayMultimediaFile.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/PlayMultimediaFile.cs new file mode 100644 index 00000000..828c200d --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/PlayMultimediaFile.cs @@ -0,0 +1,41 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Play Multimedia File + /// + /// This action plays an audio (.WAV) or video (.AVI) file during installation. Playback is + /// asynchronous, which means the sound or movie can play while the installation + /// continues. The multimedia file must be installed on the destination computer before this + /// action is called. It must be small enough to fit into the destination computer’s RAM for it + /// to play correctly, because the disk is heavily accessed by the installation process. To + /// produce sound, the destination computer must be properly equipped and configured. + /// + /// + /// + public class PlayMultimediaFile : MachineStateData + { + /// + /// Flags + /// + /// Values: + /// - Loop Continuously (0x01) + /// - File Type (WAV or AVI) (0x02 == AVI) + /// + public byte Flags { get; set; } + + /// + /// X Position on a 640 x 480 screen for AVI to play + /// + public ushort XPosition { get; set; } + + /// + /// Y Position on a 640 x 480 screen for AVI to play + /// + public ushort YPosition { get; set; } + + /// + /// Path to the .WAV or .AVI file + /// + public string? Pathname { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/PostToHttpServer.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/PostToHttpServer.cs new file mode 100644 index 00000000..c8872eed --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/PostToHttpServer.cs @@ -0,0 +1,45 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Post to HTTP Server + /// + /// This action posts information over the Internet to a Web server. (Example: Use it to + /// record user registration information or other data.) You must set up a CGI program or + /// Active Server Page (.ASP) on the server that accepts data sent by an HTTP POST + /// operation and deciphers encoded characters. + /// + /// The destination computer must have a valid Internet connection. If end users might not + /// have this capability, you can add a prompt on a dialog box asking the end user if they + /// have Internet connectivity. Then use the results from the prompt to run this action or + /// not. + /// + /// + /// This action is called through Call DLL Function and is mapped to "f34". + /// This acts like the start of a block if a flag is set. + /// + /// + public class PostToHttpServer : FunctionData + { + /// + /// Flags from the argument data + /// + /// + /// Encoded as a string, binary representation in script file. + /// Expected flags: + /// - Ignore Errors (unknown) + /// - Abort Installation (unknown) + /// - Start Block (unknown) + /// + public byte DataFlags { get; set; } + + /// + /// URL + /// + public string? URL { get; set; } + + /// + /// Text to post in "field=data" format + /// + public string? PostData { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/PromptForFilename.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/PromptForFilename.cs new file mode 100644 index 00000000..c5cce2a7 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/PromptForFilename.cs @@ -0,0 +1,61 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Prompt for Filename + /// + /// This action prompts the end user to select a file using a standard Open or Save dialog + /// box. The complete path of the file or directory is returned in a variable. (Example: Use + /// the returned directory to set the installation directory for a subset of files.) No file is + /// actually opened or saved by this action. This action is included to provide backward + /// compatibility for older WiseScripts. In new scripts, use custom dialog boxes or dialog + /// box controls to perform the same function. This action requires an End Statement, + /// because it begins a block of statements, similar to an If Statement. + /// + /// + /// This action is called through Call DLL Function and is mapped to "f35". + /// This acts like the start of a block. + /// + /// + public class PromptForFilename : FunctionData + { + /// + /// Flags from the argument data + /// + /// + /// Encoded as a string, binary representation in script file. + /// Expected flags: + /// - Dialog Type (unknown) + /// - Allow selection of multiple files (unknown) + /// - Prompt if file does not exist (unknown) + /// - File must exist (unknown) + /// - Pathname must exist (unknown) + /// - Skip write permissions test (unknown) + /// - Do not validate the pathname (unknown) + /// - Display prompt if overwriting existing file (unknown) + /// + public byte DataFlags { get; set; } + + /// + /// Destination variable for the selection + /// + public string? DestinationVariable { get; set; } + + /// + /// Default extension if one is not entered + /// + public string? DefaultExtension { get; set; } + + /// + /// Title for the dialog box + /// + public string? DialogTitle { get; set; } + + /// + /// File types to appear in the selction list + /// + /// + /// Formatted like "File Description (*.ext);*.ext" + /// + public string? FilterList { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/ReadIniValue.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/ReadIniValue.cs new file mode 100644 index 00000000..b6a9712f --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/ReadIniValue.cs @@ -0,0 +1,50 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Read INI Value + /// + /// This action reads an entry from an existing .INI file into a variable. Example: Obtain a + /// path to a file. + /// + /// + /// This action is called through Call DLL Function and is mapped to "f8". + /// + /// + public class ReadIniValue : FunctionData + { + /// + /// Flags from the argument data + /// + /// + /// Encoded as a string, binary representation in script file. + /// Expected flags: + /// - Remove File Name (nonzero value) + /// + public byte DataFlags { get; set; } + + /// + /// Variable name + /// + public string? Variable { get; set; } + + /// + /// Path to INI + /// + public string? Pathname { get; set; } + + /// + /// INI section + /// + public string? Section { get; set; } + + /// + /// Item key + /// + public string? Item { get; set; } + + /// + /// Default value + /// + public string? DefaultValue { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/ReadUpdateTextFile.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/ReadUpdateTextFile.cs new file mode 100644 index 00000000..7fc8e146 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/ReadUpdateTextFile.cs @@ -0,0 +1,46 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Read/Update Text File + /// + /// This action begins a loop that reads and, optionally, updates text in a text file. Each loop + /// puts the next line of text into a variable. You can put actions in the loop that change the + /// contents of the variable (example: Parse String). Optionally, the changed variable can + /// be written back to the file. The loop repeats for each line of the file. This action requires + /// an End Statement. + /// + /// + /// This action is called through Call DLL Function and is mapped to "f33". + /// This acts like the start of a block. + /// + /// + public class ReadUpdateTextFile : FunctionData + { + /// + /// Flags from the argument data + /// + /// + /// Encoded as a string, binary representation in script file. + /// Expected flags: + /// - Read lines of file into variable (unknown) + /// - Update file with new contents of variable (unknown) + /// - Make Backup File (unknown) + /// + public byte DataFlags { get; set; } + + /// + /// Variable to store each line of the text file + /// + public string? Variable { get; set; } + + /// + /// Full path to the text file to be edited + /// + public string? Pathname { get; set; } + + /// + /// Language Strings + /// + public string? LanguageStrings { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/ReadWriteBinaryFile.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/ReadWriteBinaryFile.cs new file mode 100644 index 00000000..f8d07d05 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/ReadWriteBinaryFile.cs @@ -0,0 +1,52 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Read/Write Binary File + /// + /// This action reads from a binary file to a variable, or writes from a variable to a binary + /// file. If you write to the file, the existing information in the file is not moved, it is + /// overwritten. + /// + /// This action does not support reading or writing non-ASCII characters (characters with + /// codes above 127). + /// + /// + /// This action is called through Call DLL Function and is mapped to "f15". + /// + /// + public class ReadWriteBinaryFile : FunctionData + { + /// + /// Flags from the argument data + /// + /// + /// Encoded as a string, binary representation in script file. + /// Expected flags: + /// - Transfer Direction [0x00 == Read, 0x01 == Write] + /// - Null Terminated (unknown) + /// + public byte DataFlags { get; set; } + + /// + /// Full path to the binary file + /// + public string? FilePathname { get; set; } + + /// + /// Name of the variable + /// + public string? VariableName { get; set; } + + /// + /// Offset in the file to start from + /// + /// Encoded as a string + public int FileOffset { get; set; } + + /// + /// Maximum number of bytes to process + /// + /// Encoded as a string + public int MaxLength { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/RegisterFont.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/RegisterFont.cs new file mode 100644 index 00000000..b3ad6147 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/RegisterFont.cs @@ -0,0 +1,25 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Register Font + /// + /// This action registers a new TrueType font (.TTF file) that has been copied into the + /// Windows font directory. + /// + /// + /// This action is called through Call DLL Function and is mapped to "f10". + /// + /// + public class RegisterFont : FunctionData + { + /// + /// TrueType font filename, not path + /// + public string? FontFileName { get; set; } + + /// + /// Full name of the font + /// + public string? FontName { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/RenameFileDirectory.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/RenameFileDirectory.cs new file mode 100644 index 00000000..5327feb5 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/RenameFileDirectory.cs @@ -0,0 +1,24 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Rename File/Directory + /// + /// This action renames a file or directory on the destination computer. This can be an + /// existing file or directory, or a file or directory that your installation installed. The file + /// must not be busy. + /// + /// + /// + public class RenameFileDirectory : MachineStateData + { + /// + /// Full path to the existing file or directory + /// + public string? OldPathname { get; set; } + + /// + /// New file or directory name + /// + public string? NewFileName { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/SearchForFile.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/SearchForFile.cs new file mode 100644 index 00000000..03b3928c --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/SearchForFile.cs @@ -0,0 +1,48 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Search for File + /// + /// This action searches for a file on local drives, network drives, or all drives, and returns + /// the full path to the file. + /// + /// + /// This action is called through Call DLL Function and is mapped to "f13". + /// + /// + public class SearchForFile : FunctionData + { + /// + /// Flags from the argument data + /// + /// + /// Encoded as a string, binary representation in script file. + /// Expected flags: + /// - Return Type (unknown) + /// - Drives to Search (local, network, both) (unknown) + /// - Search Depth (unknown) + /// - Remove File Name (unknown) + /// + public byte DataFlags { get; set; } + + /// + /// Variable to store the file path + /// + public string? Variable { get; set; } + + /// + /// Filename to search for + /// + public string? FileName { get; set; } + + /// + /// Default value if the file is not found + /// + public string? DefaultValue { get; set; } + + /// + /// Message to display during the search operation + /// + public string? MessageText { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/SelfRegisterOCXsDLLs.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/SelfRegisterOCXsDLLs.cs new file mode 100644 index 00000000..3178732d --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/SelfRegisterOCXsDLLs.cs @@ -0,0 +1,31 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Self-Register OCXs/DLLs + /// + /// Use this action to self-register all queued .OCX, .DLL, and .EXE files or to add an existing + /// file to the queue. + /// + /// + /// This action is called through Call DLL Function and is mapped to "f29". + /// + /// + public class SelfRegisterOCXsDLLs : FunctionData + { + /// + /// Flags from the argument data + /// + /// + /// Encoded as a string, binary representation in script file. + /// Expected flags: + /// - Register all pending OCXs/DLLs/EXEs (unknown) + /// - Queue existing file for self-registration + /// + public byte DataFlags { get; set; } + + /// + /// Description/Pathname + /// + public string? Description { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/SetFileAttributes.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/SetFileAttributes.cs new file mode 100644 index 00000000..f865c297 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/SetFileAttributes.cs @@ -0,0 +1,35 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Set File Attributes + /// + /// This action sets the attributes of one file or a group of files. + /// + /// + /// This action is called through Call DLL Function and is mapped to "f12". + /// This acts like the start of a block if a flag is set. + /// + /// + public class SetFileAttributes : FunctionData + { + /// + /// Flags from the argument data + /// + /// + /// Encoded as a string, binary representation in script file. + /// Expected flags: + /// - Read Only (Maybe 0x01) + /// - Hidden (Maybe 0x02) + /// - System (Maybe 0x04) + /// - Scan Directory Tree (unknown) + /// - Archive (unknown) + /// + public byte DataFlags { get; set; } + + /// + /// File to change + /// + /// Wildcards are allowed + public string? FilePathname { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/SetFilesBuffers.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/SetFilesBuffers.cs new file mode 100644 index 00000000..25d30a2a --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/SetFilesBuffers.cs @@ -0,0 +1,28 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Set Files/Buffers + /// + /// This action sets the FILES= and BUFFERS= lines in Config.sys. If either is currently + /// lower than the minimum specified in this action, it is increased to the specified value. If + /// either is already greater than the minimum specified in this action, it is not changed. + /// + /// + /// This action is called through Call DLL Function and is mapped to "f21". + /// + /// + public class SetFilesBuffers : FunctionData + { + /// + /// Minimum files to be specfied in FILES= in CONFIG.SYS + /// + /// Blank means leave unchanged + public string? MinimumFiles { get; set; } + + /// + /// Minimum buffers to be specfied in BUFFERS= in CONFIG.SYS + /// + /// Blank means leave unchanged + public string? MinimumBuffers { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/SetVariable.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/SetVariable.cs new file mode 100644 index 00000000..cd87aff3 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/SetVariable.cs @@ -0,0 +1,49 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Set Variable + /// + /// This action sets the value of a variable by providing a literal value, by modifying the + /// variable’s existing value, or by evaluating an expression. + /// + /// + /// This action is called through Call DLL Function and is mapped to "f16". + /// + /// + public class SetVariable : FunctionData + { + /// + /// Flags from the argument data + /// + /// + /// Encoded as a string, binary representation in script file. + /// Expected flags: + /// (flags >> 2 & 0x0F) + /// - Nothing (0x00) + /// - Increment (0x04) + /// - Decrement (0x08) + /// - Remove trailing backslashes (0x0C) + /// - Convert to long filename (0x10) + /// - Convert to short filename (0x14) + /// - Convert to uppercase (0x18) + /// - Convert to lowercase (0x1C) + /// + /// One of the following is case 0x20: + /// - Evaluate Expression (unknown) + /// - Append to Existing Value (unknown) + /// - Remove File Name (unknown) + /// - Read Variable From Values File (unknown) + /// + public byte DataFlags { get; set; } + + /// + /// Variable name + /// + public string? Variable { get; set; } + + /// + /// Value, optional + /// + public string? Value { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/StartStopService.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/StartStopService.cs new file mode 100644 index 00000000..5bfab8a8 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/StartStopService.cs @@ -0,0 +1,35 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Start/Stop Service + /// + /// This action lets you start or stop a service on the destination computer. It only applies to + /// operating systems that support services. + /// + /// When a WiseScript is called by a Windows Installer installation, you can also start and + /// stop services by using the Services page in Windows Installer Editor. + /// + /// After you try to stop a service, the script pauses to give the service time to stop. The + /// currently logged-in end user must have the appropriate privileges to start and stop + /// services. + /// + /// + /// This action is called through Call DLL Function and is mapped to "f36". + /// + /// + public class StartStopService : FunctionData + { + /// + /// Operation + /// + /// + /// Stop = 0, Start = 1 + /// + public byte Operation { get; set; } + + /// + /// Internal name of the service to start or stop + /// + public string? ServiceName { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/StartUserDefinedAction.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/StartUserDefinedAction.cs new file mode 100644 index 00000000..070cf2a8 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/StartUserDefinedAction.cs @@ -0,0 +1,19 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Start User-Defined Action + /// + /// You create a user-defined action by creating a separate WiseScript and saving it in the + /// Actions subdirectory of this product’s installation directory, or in the shared directory + /// that is specified in Preferences. + /// + /// + /// This acts like the start of a block. + /// + /// + /// + public class StartUserDefinedAction : MachineStateData + { + // There is no data + } +} diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/Unknown0x19.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/Unknown0x19.cs new file mode 100644 index 00000000..ec4e575b --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/Unknown0x19.cs @@ -0,0 +1,26 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + public class Unknown0x19 : MachineStateData + { + /// + /// Unknown + /// + public byte Operand_1 { get; set; } + + /// + /// Unknown + /// + public string? Operand_2 { get; set; } + + /// + /// Unknown + /// + public string? Operand_3 { get; set; } + + /// + /// Unknown + /// + public string? Operand_4 { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/Unknown0x24.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/Unknown0x24.cs new file mode 100644 index 00000000..83ee9eb9 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/Unknown0x24.cs @@ -0,0 +1,17 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Unknown + /// + /// + /// This action enables a flag that is used by this and . + /// It seems to only be referenced in contexts where there are registry + /// keys read and written, specifically about repair. + /// + /// + /// + public class Unknown0x24 : MachineStateData + { + // There is no data + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/Unknown0x25.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/Unknown0x25.cs new file mode 100644 index 00000000..112df7e8 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/Unknown0x25.cs @@ -0,0 +1,17 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Unknown + /// + /// + /// This action enables a flag that is used by this and . + /// It seems to only be referenced in contexts where there are registry + /// keys read and written, specifically about repair. + /// + /// + /// + public class Unknown0x25 : MachineStateData + { + // There is no data + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/UserDefinedActionStep.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/UserDefinedActionStep.cs new file mode 100644 index 00000000..17013c17 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/UserDefinedActionStep.cs @@ -0,0 +1,29 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// User-Defined Action Step + /// + /// You create a user-defined action by creating a separate WiseScript and saving it in the + /// Actions subdirectory of this product’s installation directory, or in the shared directory + /// that is specified in Preferences. + /// + /// + /// + public class UserDefinedActionStep : MachineStateData + { + /// + /// Flags for writing out + /// + /// + /// Values: + /// - 0x01 - Used as value appended to the end of the selected line + /// - 0x02 - Indicates if the string should be formatted(?) + /// + public byte Flags { get; set; } + + /// + /// Script lines + /// + public string[]? ScriptLines { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/Win32SystemDirectory.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/Win32SystemDirectory.cs new file mode 100644 index 00000000..ed5ae265 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/Win32SystemDirectory.cs @@ -0,0 +1,22 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Win32 System Directory + /// + /// This action puts the path to the operating system directory (%WIN%\System32) into a + /// variable. Alternatively, use the predefined variables %SYS% or %SYS32% to access the + /// system directory. This action is included to provide backward compatibility for older + /// WiseScripts. + /// + /// + /// This action is called through Call DLL Function and is mapped to "f11". + /// + /// + public class Win32SystemDirectory : FunctionData + { + /// + /// Variable name to store the value in + /// + public string? VariableName { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WiseInstaller/Actions/WizardBlockLoop.cs b/SabreTools.Serialization/Models/WiseInstaller/Actions/WizardBlockLoop.cs new file mode 100644 index 00000000..accd8a99 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Actions/WizardBlockLoop.cs @@ -0,0 +1,81 @@ +namespace SabreTools.Serialization.Models.WiseInstaller.Actions +{ + /// + /// Wizard Block / Wizard Loop + /// + /// This action precedes dialog boxes that make up the majority of the installation’s end + /// user interface. End users can move forward and backward through these dialog boxes. + /// The script continues executing inside the wizard loop until the last dialog box has been + /// completed and accepted. + /// + /// + /// This action is called through Call DLL Function and is mapped to "f31". + /// This acts like the start of a block if a flag is set(?). + /// + /// + public class WizardBlockLoop : FunctionData + { + /// + /// Flags from the argument data + /// + /// + /// Encoded as a string, binary representation in script file. + /// Expected flags: + /// - Skip Dialog (unknown) + /// + public byte DataFlags { get; set; } + + // TODO: Below is actually a list of dialog boxes + // TODO: Below should move to create dialog box + + /// + /// Direction variable name + /// + /// "B" == Previous, "N" == Next + public string? DirectionVariable { get; set; } + + /// + /// Display variable name + /// + public string? DisplayVariable { get; set; } + + /// + /// X Position + /// + public int? XPosition { get; set; } + + /// + /// Y Position, numeric + /// + public int? YPosition { get; set; } + + /// + /// Filler Color, numeric + /// + public int? FillerColor { get; set; } + + /// + /// Unknown, numeric + /// + public string? Operand_6 { get; set; } + + /// + /// Unknown, numeric + /// + public string? Operand_7 { get; set; } + + /// + /// Unknown, numeric + /// + public string? Operand_8 { get; set; } + + /// + /// Either just a dialog name or a combination of + /// Dialog, Variable, Value, and Compare values + /// that are `\t` separated. Dialog and Variable + /// are both strings, Value and Compare both seem + /// to be numeric + /// + public string? DialogVariableValueCompare { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WiseInstaller/Constants.cs b/SabreTools.Serialization/Models/WiseInstaller/Constants.cs new file mode 100644 index 00000000..7c678e0c --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Constants.cs @@ -0,0 +1,106 @@ +using System.Collections.Generic; + +namespace SabreTools.Serialization.Models.WiseInstaller +{ + public static class Constants + { + /// + /// Count of per-language strings for an Action + /// + /// Derived from WISE0001.DLL + public static readonly byte[] CountOfLanguageActionStrings = + [ + 0x01, 0x00, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ]; + + /// + /// Count of non-language strings for an Action + /// + /// + /// Derived from WISE0001.DLL + /// One variant of the DLL has action 0x06 have a + /// value of `0x01` instead of `0x00`. + /// One variant of the DLL has action 0x18 have a + /// value of `0x01` instead of `0x00`. + /// + public static readonly byte[] CountOfStaticActionStrings = + [ + 0x02, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x03, + 0x00, 0x04, 0x03, 0x01, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x03, 0x00, 0x02, 0x02, 0x01, 0x01, + 0x00, 0x03, 0x02, 0x00, 0x01, 0x02, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + ]; + + /// + /// Size of the invariant data for an Action + /// + /// + /// One variant of the DLL has action 0x18 have a + /// value of `0x06` instead of `0x01`. + /// + public static readonly byte[] SizeOfStaticActionData = + [ + 0x2B, 0x00, 0x02, 0x02, 0x02, 0x01, 0x13, 0x02, + 0x02, 0x02, 0x03, 0x02, 0x02, 0x01, 0x00, 0x01, + 0x01, 0x01, 0x2B, 0x00, 0x0D, 0x02, 0x01, 0x06, + 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, 0x00, 0x00, + ]; + + /// + /// "WIS" string for WiseSection 57, 49, 53 + /// + public static readonly byte[] WisString = + [0x57, 0x49, 0x53]; + + /// + /// List of currently observed offsets for the "WIS" string in WiseSection + /// + public static readonly int[] WisOffsets = + [32, 33, 41, 77, 78, 82]; + + /// + /// Size of the header for a WiseSection + /// + public static readonly Dictionary WiseSectionHeaderLengthDictionary = new Dictionary() + { + {32, 6}, + {33, 6}, + {41, 8}, + {77, 17}, + {78, 17}, + {82, 18}, + }; + + /// + /// Offset from "WIS" string to be used as length of version field. + /// + public static readonly Dictionary WiseSectionVersionOffsetDictionary = new Dictionary() + { + {32, 4}, + {33, 5}, + {41, 5}, + {77, 5}, + {78, 6}, + {82, 6}, + }; + + /// + /// Size of pre-string byte array, guessed to be correlated with "WIS" string offset. + /// + public static readonly Dictionary WiseSectionPreStringBytesSize = new Dictionary() + { + {32, 8}, + {33, 16}, + {41, 18}, + {77, 19}, + {78, 19}, + {82, 19}, + }; + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WiseInstaller/Enums.cs b/SabreTools.Serialization/Models/WiseInstaller/Enums.cs new file mode 100644 index 00000000..0f3074c0 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/Enums.cs @@ -0,0 +1,418 @@ +namespace SabreTools.Serialization.Models.WiseInstaller +{ + /// + /// The CharacterSet Enumeration defines the possible sets of + /// character glyphs that are defined in fonts for graphics output. + /// + /// + public enum CharacterSet : uint + { + ANSI_CHARSET = 0x00000000, + DEFAULT_CHARSET = 0x00000001, + SYMBOL_CHARSET = 0x00000002, + MAC_CHARSET = 0x0000004D, + SHIFTJIS_CHARSET = 0x00000080, + HANGUL_CHARSET = 0x00000081, + JOHAB_CHARSET = 0x00000082, + GB2312_CHARSET = 0x00000086, + CHINESEBIG5_CHARSET = 0x00000088, + GREEK_CHARSET = 0x000000A1, + TURKISH_CHARSET = 0x000000A2, + VIETNAMESE_CHARSET = 0x000000A3, + HEBREW_CHARSET = 0x000000B1, + ARABIC_CHARSET = 0x000000B2, + BALTIC_CHARSET = 0x000000BA, + RUSSIAN_CHARSET = 0x000000CC, + THAI_CHARSET = 0x000000DE, + EASTEUROPE_CHARSET = 0x000000EE, + OEM_CHARSET = 0x000000FF + } + + /// + /// Endianness of the file(?) + /// + /// + public enum Endianness : ushort + { + BigEndian = 0x0008, + LittleEndian = 0x0800, + } + + /// + /// Opcodes for the state machine + /// + /// + public enum OperationCode : byte + { + /// + /// Install a file + /// + InstallFile = 0x00, + + /// + /// Invalid case + /// + Invalid0x01 = 0x01, + + /// + /// No-op + /// + /// Empty case in WISE0001.DLL + NoOp = 0x02, + + /// + /// Display Message + /// + DisplayMessage = 0x03, + + /// + /// User-Defined Action Step + /// + UserDefinedActionStep = 0x04, + + /// + /// Edit INI File + /// + EditIniFile = 0x05, + + /// + /// Display billboard + /// + DisplayBillboard = 0x06, + + /// + /// Execute Program + /// + ExecuteProgram = 0x07, + + /// + /// End block + /// + EndBlock = 0x08, + + /// + /// Call DLL Function + /// + CallDllFunction = 0x09, + + /// + /// Edit Registry + /// + EditRegistry = 0x0A, + + /// + /// Delete File + /// + DeleteFile = 0x0B, + + /// + /// If/While Statement + /// + IfWhileStatement = 0x0C, + + /// + /// Else Statement + /// + ElseStatement = 0x0D, + + /// + /// Invalid case + /// + Invalid0x0E = 0x0E, + + /// + /// Start User-Defined Action + /// + StartUserDefinedAction = 0x0F, + + /// + /// End User-Defined Action + /// + EndUserDefinedAction = 0x10, + + /// + /// Create Directory + /// + CreateDirectory = 0x11, + + /// + /// Copy Local File + /// + CopyLocalFile = 0x12, + + /// + /// Invalid case + /// + Invalid0x13 = 0x13, + + /// + /// Custom Dialog Set + /// + CustomDialogSet = 0x14, + + /// + /// Get System Information + /// + GetSystemInformation = 0x15, + + /// + /// Get Temporary Filename + /// + GetTemporaryFilename = 0x16, + + /// + /// Play Multimedia File + /// + PlayMultimediaFile = 0x17, + + /// + /// New Event + /// + /// Returns 0xffffffff in WISE0001.DLL + NewEvent = 0x18, + + /// + /// Install ODBC Driver + /// + /// + /// Available documentation does not mention this action, + /// instead saying that the driver needs to be installed + /// before configuration. This may be a holdover from + /// older versions that required driver installation. + /// + InstallODBCDriver = 0x19, + + /// + /// Config ODBC Data Source + /// + ConfigODBCDataSource = 0x1A, + + /// + /// Include Script(?) + /// + /// + /// Acts like a no-op in the parsed script. Includes a + /// "Pathname" to the file to be included. + /// + /// In WISE0001.DLL, it seeks forward until it doesn't + /// find another 0x1B value again. Indicates that this + /// may not be "Include Script" as previously expected. + /// + IncludeScript = 0x1B, + + /// + /// Add Text to INSTALL.LOG + /// + AddTextToInstallLog = 0x1C, + + /// + /// Rename File/Directory + /// + RenameFileDirectory = 0x1D, + + /// + /// Open/Close Install.log + /// + OpenCloseInstallLog = 0x1E, + + /// + /// Invalid case + /// + Invalid0x1F = 0x1F, + + /// + /// Invalid case + /// + Invalid0x20 = 0x20, + + /// + /// Invalid case + /// + Invalid0x21 = 0x21, + + /// + /// Invalid case + /// + Invalid0x22 = 0x22, + + /// + /// ElseIf Statement + /// + ElseIfStatement = 0x23, + + /// + /// Enable repair? + /// + /// + /// The flag used by this and seems + /// to only be referenced in contexts where there are registry + /// keys read and written, specifically about repair. + /// + Unknown0x24 = 0x24, + + /// + /// Disable repair? + /// + /// + /// The flag used by this and seems + /// to only be referenced in contexts where there are registry + /// keys read and written, specifically about repair. + /// + Unknown0x25 = 0x25, + + // Check in WISE0001.DLL suggests that there could be up + // to opcode 0x3F. If the opcode is greater than 0x3F, + // then the installation aborts with 0xfffffffe. + // + // Opcode 0x3F returns a value of 0xffffffff. + } + + /// + /// Wise installer overlay header flags + /// + /// + public enum OverlayHeaderFlags : uint + { + /// + /// This value is checked for explicitly. If this value + /// and are both not + /// set, then it shows the commandline when silent mode + /// is disabled. + /// + /// If just this value is set, the bottom of the window + /// is adjusted by (MainWindowBottom * 3) / 4 and then + /// displays the window with the current size. + /// + WISE_FLAG_UNKNOWN_0 = 0x00000001, + + /// + /// This value is checked for explicitly. If this value + /// and not is set + /// and is set and + /// the silent mode flag is not enabled, it runs a + /// function. Maybe debug window? + /// + /// If this value and + /// are both not set, then it displays the window + /// maximized. + /// + /// If just this value is set and silent mode is enabled, + /// the position of the window is set to full screen + /// but the window is not shown. + /// + WISE_FLAG_UNKNOWN_1 = 0x00000002, + + WISE_FLAG_UNKNOWN_2 = 0x00000004, + + /// + /// Enable fullscreen installer + /// + /// + /// If this flag is enabled, it sets the following window flags: + /// WS_BORDER | WS_DLGFRAME | WS_SYSMENU | WS_MAXIMIZEBOX | WS_TILED + /// + /// If this flag is disabled, it sets the following window flags: + /// WS_POPUP | WS_SIZEBOX + /// + WISE_FLAG_FULLSCREEN = 0x00000008, + + /// + /// Seen in hluplink.exe, Swat 3 and glsetup.exe + /// + WISE_FLAG_UNKNOWN_4 = 0x00000010, + + WISE_FLAG_UNKNOWN_5 = 0x00000020, + + WISE_FLAG_UNKNOWN_6 = 0x00000040, + + /// + /// This value is checked for explicitly. If this value is + /// set and the commandline doesn't specify silent mode + /// and the first byte of the flags (f & 3 != 2), it runs + /// a function. Maybe debug window? + /// + WISE_FLAG_UNKNOWN_7 = 0x00000080, + + /// + /// Indicates that PKZIP containers are used + /// + WISE_FLAG_PK_ZIP = 0x00000100, + + WISE_FLAG_UNKNOWN_9 = 0x00000200, + + WISE_FLAG_UNKNOWN_10 = 0x00000400, + + /// + /// May be related to requireAdministrator + /// + WISE_FLAG_UNKNOWN_11 = 0x00000800, + + /// + /// This value is checked for explicitly + /// + WISE_FLAG_UNKNOWN_12 = 0x00001000, + + WISE_FLAG_UNKNOWN_13 = 0x00002000, + + WISE_FLAG_UNKNOWN_14 = 0x00004000, + + WISE_FLAG_UNKNOWN_15 = 0x00008000, + + /// + /// May be related to requireAdministrator + /// + WISE_FLAG_UNKNOWN_16 = 0x00010000, + + WISE_FLAG_UNKNOWN_17 = 0x00020000, + + WISE_FLAG_UNKNOWN_18 = 0x00040000, + + /// + /// Only seen set in Wild Wheels + /// + WISE_FLAG_UNKNOWN_19 = 0x00080000, + + WISE_FLAG_UNKNOWN_20 = 0x00100000, + + WISE_FLAG_UNKNOWN_21 = 0x00200000, + + /// + /// Only seen in glsetup.exe + /// + WISE_FLAG_UNKNOWN_22 = 0x00400000, + + WISE_FLAG_UNKNOWN_23 = 0x00800000, + + WISE_FLAG_UNKNOWN_24 = 0x01000000, + + WISE_FLAG_UNKNOWN_25 = 0x02000000, + + WISE_FLAG_UNKNOWN_26 = 0x04000000, + + WISE_FLAG_UNKNOWN_27 = 0x08000000, + + WISE_FLAG_UNKNOWN_28 = 0x10000000, + + WISE_FLAG_UNKNOWN_29 = 0x20000000, + + /// + /// If enabled, sets the same flag as /M4 commandline + /// + /// + /// The /M4 commandline parameter, this flag, and then + /// some value (DAT_00404270) being 0 all lead to the + /// same outcome. The set of installers that include + /// this flag need to be further analyzed to see what + /// possible files are omitted if this flag is set. + /// + /// Preliminary inspection of output files does not + /// show any notable missing files. It is very possible + /// that this represents a file that is not currently + /// extracted. + /// + WISE_FLAG_FORCE_M4 = 0x40000000, + + WISE_FLAG_UNKNOWN_31 = 0x80000000, + + } +} diff --git a/SabreTools.Serialization/Models/WiseInstaller/MachineState.cs b/SabreTools.Serialization/Models/WiseInstaller/MachineState.cs new file mode 100644 index 00000000..296330d0 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/MachineState.cs @@ -0,0 +1,22 @@ +using SabreTools.Serialization.Models.WiseInstaller.Actions; + +namespace SabreTools.Serialization.Models.WiseInstaller +{ + /// + /// Represents a single step in the state machine defined + /// in a Wise script file. + /// + public class MachineState + { + /// + /// Opcode + /// + public OperationCode Op { get; set; } + + /// + /// Data specific to the operation, may be null + /// + + public MachineStateData? Data { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WiseInstaller/OverlayHeader.cs b/SabreTools.Serialization/Models/WiseInstaller/OverlayHeader.cs new file mode 100644 index 00000000..38376fc8 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/OverlayHeader.cs @@ -0,0 +1,182 @@ +namespace SabreTools.Serialization.Models.WiseInstaller +{ + /// + /// Wise installer overlay data header + /// + /// + public class OverlayHeader + { + /// + /// DLL name length, if it exists + /// + public byte DllNameLen { get; set; } // 0x00 + + /// + /// DLL name, missing if is 0 + /// + public string? DllName { get; set; } // + + /// + /// DLL size, missing if is 0 + /// + public uint? DllSize { get; set; } // + + /// + /// Packing flags + /// + public OverlayHeaderFlags Flags { get; set; } // 0x01 - 0x04 + + /// + /// Graphics data + /// + /// + /// 12 bytes + /// + /// When the data is processed, it does the following: + /// + /// ushort[] colors = new ushort[3]; + /// int colorsPtr = 0; + /// + /// for (int i = 0; i < 3; i++) + /// { + /// uint color = (GraphicsData[i + 3] * ) / 0x5F + GraphicsData[i]; + /// colors[colorsPtr] = color; + /// if (color < 0) + /// colors[colorsPtr] = 0; + /// if (colors[colorsPtr] > 0xFF) + /// colors[colorsPtr] = 0xFF + /// + /// colorsPtr++; + /// } + /// + public byte[]? GraphicsData { get; set; } // 0x05 - 0x10 + + /// + /// Points to the Exit event in the script, if it exists + /// + public uint WiseScriptExitEventOffset { get; set; } // 0x11 - 0x14 + + /// + /// Points to the Cancel event in the script, if it exists + /// + public uint WiseScriptCancelEventOffset { get; set; } // 0x15 - 0x18 + + /// + /// Inflated size of the Wise installer script + /// + public uint WiseScriptInflatedSize { get; set; } // 0x19 - 0x1C + + /// + /// Deflated size of the Wise installer script + /// + public uint WiseScriptDeflatedSize { get; set; } // 0x1D - 0x20 + + /// + /// Deflated size of WISE0001.DLL + /// + public uint WiseDllDeflatedSize { get; set; } // 0x21 - 0x24 + + /// + /// Deflated size of CTL3D32.DLL + /// + public uint Ctl3d32DeflatedSize { get; set; } // 0x25 - 0x28 + + /// + /// Deflated size of unknown data + /// + public uint SomeData4DeflatedSize { get; set; } // 0x29 - 0x2C + + /// + /// Deflated size of Ocxreg32.EXE, + /// + public uint RegToolDeflatedSize { get; set; } // 0x2D - 0x30 + + /// + /// Deflated size of PROGRESS.DLL + /// + public uint ProgressDllDeflatedSize { get; set; } // 0x31 - 0x34 + + /// + /// Deflated size of unknown data + /// + public uint SomeData7DeflatedSize { get; set; } // 0x35 - 0x38 + + /// + /// Deflated size of unknown data + /// + public uint SomeData8DeflatedSize { get; set; } // 0x39 - 0x3C + + /// + /// Deflated size of unknown data + /// + /// Samples were MS-DOS executables + public uint SomeData9DeflatedSize { get; set; } // 0x3D - 0x40 + + /// + /// Deflated size of unknown data + /// + public uint SomeData10DeflatedSize { get; set; } // 0x41 - 0x44 + + /// + /// Deflated size of FILE000{n}.DAT + /// + public uint FinalFileDeflatedSize { get; set; } // 0x45 - 0x48 + + /// + /// Inflated size of FILE000{n}.DAT + /// + public uint FinalFileInflatedSize { get; set; } // 0x49 - 0x4C + + /// + /// On multi-disc installers this is set to 0x00000000, so it may + /// represent EOF instead of filesize? At least for now. Only compared + /// the two multi-disc installers listed in the README.md, need more + /// multi-disc installers to properly compare. On single file + /// installers this is this installer it's filesize. + /// + public uint EOF { get; set; } // 0x4D - 0x50 + + /// + /// Deflated size of the DIB + /// + /// First file + public uint DibDeflatedSize { get; set; } // 0x51 - 0x54 + + /// + /// Inflated size of the DIB + /// + /// First file + public uint DibInflatedSize { get; set; } // 0x55 - 0x58 + + /// + /// Deflated size of the install script + /// + /// Only present in later versions + public uint? InstallScriptDeflatedSize { get; set; } // 0x59 - 0x5C + + /// + /// Character set for the font + /// + /// + /// Only present in later versions. In the overlay reading code + /// present in those later versions, it is lumped in with the + /// rest of the sizes above. + /// + public CharacterSet? CharacterSet { get; set; } // 0x5D - 0x60 + + /// + /// Endianness of the file(?) + /// + public Endianness Endianness { get; set; } // 0x61 - 0x62 + + /// + /// Init text length + /// + public byte InitTextLen { get; set; } // 0x63 + + /// + /// Init text whose length is given by + /// + public string? InitText { get; set; } // 0x64 - + } +} diff --git a/SabreTools.Serialization/Models/WiseInstaller/ScriptFile.cs b/SabreTools.Serialization/Models/WiseInstaller/ScriptFile.cs new file mode 100644 index 00000000..31a96dac --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/ScriptFile.cs @@ -0,0 +1,19 @@ +namespace SabreTools.Serialization.Models.WiseInstaller +{ + /// + /// Wise script file + /// + /// + public class ScriptFile + { + /// + /// Script header + /// + public ScriptHeader? Header { get; set; } + + /// + /// States representing the state machine in order + /// + public MachineState[]? States { get; set; } + } +} \ No newline at end of file diff --git a/SabreTools.Serialization/Models/WiseInstaller/ScriptHeader.cs b/SabreTools.Serialization/Models/WiseInstaller/ScriptHeader.cs new file mode 100644 index 00000000..5884c3a1 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/ScriptHeader.cs @@ -0,0 +1,171 @@ +namespace SabreTools.Serialization.Models.WiseInstaller +{ + /// + /// Header for the Wise script + /// + /// + public class ScriptHeader + { + /// + /// Flags, unknown mapping + /// + /// + /// The high byte (0x01) being any value but 0x00 indicates + /// that a 32-bit library will be used. + /// + public ushort Flags { get; set; } + + /// + /// Unknown + /// + /// + /// Read in a loop with , possibly + /// an offset? It's read into an array. + /// + /// Both values are then used to build variable names if they're + /// non-zero. The variable names use "SYS" as the template. + /// The values are then seemingly read over? + /// + public ushort UnknownU16_1 { get; set; } + + /// + /// Unknown + /// + /// + /// Read in a loop with , possibly + /// an offset? It's read into an array. + /// + /// Both values are then used to build variable names if they're + /// non-zero. The variable names use "SYS" as the template. + /// The values are then seemingly read over? + /// + public ushort UnknownU16_2 { get; set; } + + /// + /// Total deflated size of OP 0x00 files? + /// + /// + /// This seems to match the offset we can do filesize - SomeOffset1 + /// to get to the script file deflate offset, but not on all + /// installers.. + /// + /// Values from WISE0001.DLL + /// - < 0 - Display abort installation message and return 1? + /// - 0x400 - Breaks a loop? + /// - 0x800 - Returns 0? + /// + public uint SomeOffset1 { get; set; } + + /// + /// Unknown + /// + /// + /// Used as a size to allocate memory in WISE0001.DLL + /// + public uint SomeOffset2 { get; set; } + + /// + /// Unknown + /// + /// + /// 4 bytes + /// + /// In WISE0001.DLL, the first byte of this array is checked + /// to be 0x00. If it's not 0x00, then it skips a string, ending + /// at the next null terminator. The string at that offset is + /// then comapred to ... + /// + public byte[]? UnknownBytes_2 { get; set; } + + /// + /// Creation of this WiseScript.bin since UNIX epoch + /// + public uint DateTime { get; set; } + + /// + /// Unknown + /// + /// + /// This is a variable-length area of data that hasn't been + /// properly mapped yet. There are currently 4 documented + /// lengths of data: + /// - 9 - Short header data, missing some fields + /// - 17 - Middle header data, missing some fields + /// - 22 - Normal header data, all fields present + /// - 31 - Long header data, all fields present + /// + public byte[]? VariableLengthData { get; set; } + + /// + /// FTP URL for online downloading + /// + public string? FTPURL { get; set; } + + /// + /// Log pathname + /// + public string? LogPathname { get; set; } + + /// + /// Message font + /// + public string? MessageFont { get; set; } + + /// + /// Font size for message fonts + /// + public uint FontSize { get; set; } + + /// + /// Unknown + /// + /// 2 bytes + public byte[]? Unknown_2 { get; set; } + + /// + /// if languageCount > 1: the total string count is larger, there + /// will be the language selection strings at top and the normal + /// strings (56) minus 1 (55) will be times the languageCount, plus 2. + /// + /// + /// Language selection strings example when there are 6 languages: + /// + /// "Select Language" ;; selection string 1 + /// "Please Select a Language" ;; selection string 2 + /// "U.S. English" ;; language name + /// "ENU" ;; language short + /// "Fran.ias" + /// "FRA" + /// "Deutsch" + /// "DEU" + /// "Portugu.s" + /// "PTG" + /// "Espa.ol" + /// "ESN" + /// "Italiano" + /// "ITA" + /// + /// The total string count seen with 6 languages is 434 and the + /// total string count seen with 1 language has been always 56, for a + /// languageCount of 5 the string count should be 287. As seen for now. + /// + /// if (languageCount > 1) { + /// stringCount = (55 * languageCount) + (languageCount * 2) + 2; + /// } + /// else { + /// stringCount = 56 = (55 * languageCount) + languageCount + /// } + /// + /// The container size (uint8_t) is a guess, because the neightbour + /// bytes are almost all 0x00 (as seen for now). So did you find a + /// installer with more then 255 languages? then FIXME :') + /// + public byte LanguageCount { get; set; } + + /// + /// All strings in the aheader + /// + /// See the remarks in + public string[]? HeaderStrings { get; set; } + } +} diff --git a/SabreTools.Serialization/Models/WiseInstaller/SectionHeader.cs b/SabreTools.Serialization/Models/WiseInstaller/SectionHeader.cs new file mode 100644 index 00000000..75627887 --- /dev/null +++ b/SabreTools.Serialization/Models/WiseInstaller/SectionHeader.cs @@ -0,0 +1,180 @@ +namespace SabreTools.Serialization.Models.WiseInstaller +{ + /// + /// .WISE sections seem to be present in what virustotal calls "Self Extracting Wise Installer"s. These sections + /// contain a header with anywhere from seven to nineteen 4-byte little-endian values, followed by what's possibly + /// a version number, then string data, and then the file entries. + /// + /// At some point in the header, there will be the characters "WIS" prepended by what seems to be a version number. + /// This possible version number will be referred to from here on as just "version number", as it would be overly + /// verbose to continue using "what is possibly a version number". + /// + /// The WIS characters do not always align with a specific offset if the header is broken up by 4-byte blocks, and + /// the version number seems to maintain this offset. It is currently unknown if the version number is 4 bytes long + /// or five bytes long, it seems to vary. + /// + /// Offsets of the "W" in the "WIS" string currently observed are 32, 33, 41, 77, 78, and 82. This seems to point to + /// 4-6 known header lengths, depending on the deal with the version number/WIS offset. + /// + /// Before the version number, there are anywhere from seven to nineteen 4-byte little-endian values depending on + /// the length of the pre-string part of the header. These values will be described indexed from zero (0-18). The + /// only one of these values that's ever guaranteed not to be all 0x00 is value 6. This is the size of the "main" + /// file in the file entry part of the section, which is the size of the file, plus 4 bytes for its following crc32. + /// This file seems to always be an msi installer that's extracted to the TEMP directory and ran to perform the + /// actual install. This file has been observed to be nameless (a randomly generated alphanumeric string + /// followed by .msi, with some examples including 2fbcb.msi and ddec.msi, serve as the filename. Name is random + /// even when re-running the same installer) thus far. In many installers, all other pre-version values are 0x00, + /// so this is the only guaranteed value. + /// + /// All values not explicitly mentioned to never have been observed have been observed in at least one installer + /// thus far. + /// + public class SectionHeader + { + /// + /// Unknown Data Size. + /// + public uint UnknownDataSize { get; set; } + + /// + /// Value 1, (possibly?) the size of the second file entry. This has thus far always been observed + /// with non-0x00 values for values 3 and 4, and usually, but not always, value 5 as well. Thus far always been + /// observed to be an executable, filename unknown. Likely assists with extraction. A few samples with a + /// non-0x00 value 1 seem to have value 5 as 0x00, meaning that it being observed as the second file may just be + /// coincidence, and values 1 and 5 may refer to files with a specific purpose/meaning. + /// + public uint SecondExecutableFileEntryLength { get; set; } + + /// + /// Unknown value 2. Currently unobserved in any samples. + /// + public uint UnknownValue2 { get; set; } + + /// + /// Unknown value 3. This has thus far always been observed with a non-0x00 value for value 4. + /// + public uint UnknownValue3 { get; set; } + + /// + /// Unknown value 4. This has thus far always been observed with a non-0x00 value for value 3. + /// + public uint UnknownValue4 { get; set; } + + /// + /// Value 5, the size of the first entry. This has thus far always been observed with + /// non-0x00 values for values 3 and 4, and guarantees the presence of one file before the main msi installer + /// file. Thus far always been observed to be an executable, filename unknown. Likely assists with extraction. + /// + public uint FirstExecutableFileEntryLength { get; set; } + + /// + /// Value 6, the size of the "main" msi installer file entry. Always at the end of the file entries. + /// + public uint MsiFileEntryLength { get; set; } + + /// + /// Unknown value 7. Currently unobserved in any samples. + /// + /// TODO: From this entry onward the values are not guaranteed + public uint UnknownValue7 { get; set; } + + /// + /// Unknown value 8. Currently unobserved in any samples. + /// + public uint UnknownValue8 { get; set; } + + /// + /// Value 9, the size of the third entry. + /// + public uint ThirdExecutableFileEntryLength { get; set; } + + /// + /// Unknown value 10. + /// + public uint UnknownValue10 { get; set; } + + /// + /// Unknown value 11. Currently unobserved in any samples. + /// + public uint UnknownValue11 { get; set; } + + /// + /// Unknown value 12. Currently unobserved in any samples. + /// + public uint UnknownValue12 { get; set; } + + /// + /// Unknown value 13. Currently unobserved in any samples. + /// + public uint UnknownValue13 { get; set; } + + /// + /// Unknown value 14. Currently unobserved in any samples. + /// + public uint UnknownValue14 { get; set; } + + /// + /// Unknown value 15. Currently unobserved in any samples. + /// + public uint UnknownValue15 { get; set; } + + /// + /// Unknown value 16. + /// + public uint UnknownValue16 { get; set; } + + /// + /// Unknown value 17. + /// + public uint UnknownValue17 { get; set; } + + /// + /// Unknown value 18. Currently unobserved in any samples. + /// + public uint UnknownValue18 { get; set; } + + /// + /// Byte array representing version. Byte array used due to unknown size and type for version. + /// + public byte[]? Version { get; set; } + + /// + /// String representing the WIS[etc].TMP string + /// + public string? TmpString { get; set; } + + /// + /// String representing the GUID string. + /// + public string? GuidString { get; set; } + + /// + /// String representing a version number. This isn't the version of the .WISE installer itself, as it is + /// entirely inconsistent even within the same week. Likely refers to a version for what's being installed + /// rather than the installer itself + /// + public string? NonWiseVersion { get; set; } + + /// + /// Unknown. May also refer to a non-value for pre-78-offset executables and only a value for 78-offset-onwards + /// ones. + /// + public byte[]? PreFontValue {get; set;} + + /// + /// Font size + /// + public int FontSize { get; set; } + + /// + /// Byte array representing string lengths and info. Individual strings not predefined since number of strings + /// will likely vary between many installers. + /// + public byte[]? PreStringValues { get; set; } + + /// + /// Strings for the section. Size and any breakup of strings currently unknown. + /// + public byte[][]? Strings { get; set; } + } +} diff --git a/SabreTools.Serialization/Printers/LinearExecutable.cs b/SabreTools.Serialization/Printers/LinearExecutable.cs index e2957127..8d44d221 100644 --- a/SabreTools.Serialization/Printers/LinearExecutable.cs +++ b/SabreTools.Serialization/Printers/LinearExecutable.cs @@ -1,6 +1,6 @@ using System.Text; -using SabreTools.Models.LinearExecutable; using SabreTools.Serialization.Interfaces; +using SabreTools.Serialization.Models.LinearExecutable; namespace SabreTools.Serialization.Printers { @@ -41,7 +41,7 @@ namespace SabreTools.Serialization.Printers Print(builder, executable.DebugInformation); } - private static void Print(StringBuilder builder, SabreTools.Models.MSDOS.ExecutableHeader? header) + private static void Print(StringBuilder builder, SabreTools.Serialization.Models.MSDOS.ExecutableHeader? header) { builder.AppendLine(" MS-DOS Stub Header Information:"); builder.AppendLine(" -------------------------"); diff --git a/SabreTools.Serialization/Printers/MSDOS.cs b/SabreTools.Serialization/Printers/MSDOS.cs index 2f393fbf..5acb8d98 100644 --- a/SabreTools.Serialization/Printers/MSDOS.cs +++ b/SabreTools.Serialization/Printers/MSDOS.cs @@ -1,6 +1,6 @@ using System.Text; -using SabreTools.Models.MSDOS; using SabreTools.Serialization.Interfaces; +using SabreTools.Serialization.Models.MSDOS; namespace SabreTools.Serialization.Printers { diff --git a/SabreTools.Serialization/Printers/NewExecutable.cs b/SabreTools.Serialization/Printers/NewExecutable.cs index f534636d..b702f9e8 100644 --- a/SabreTools.Serialization/Printers/NewExecutable.cs +++ b/SabreTools.Serialization/Printers/NewExecutable.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; using System.Text; -using SabreTools.Models.NewExecutable; using SabreTools.Serialization.Extensions; using SabreTools.Serialization.Interfaces; +using SabreTools.Serialization.Models.NewExecutable; namespace SabreTools.Serialization.Printers { @@ -34,7 +34,7 @@ namespace SabreTools.Serialization.Printers Print(builder, executable.NonResidentNameTable); } - private static void Print(StringBuilder builder, SabreTools.Models.MSDOS.ExecutableHeader? header) + private static void Print(StringBuilder builder, SabreTools.Serialization.Models.MSDOS.ExecutableHeader? header) { builder.AppendLine(" MS-DOS Stub Header Information:"); builder.AppendLine(" -------------------------"); @@ -243,7 +243,7 @@ namespace SabreTools.Serialization.Printers builder.AppendLine(); } - private static void Print(StringBuilder builder, ModuleReferenceTableEntry[]? entries, SabreTools.Models.MSDOS.ExecutableHeader? stub, ExecutableHeader? header) + private static void Print(StringBuilder builder, ModuleReferenceTableEntry[]? entries, SabreTools.Serialization.Models.MSDOS.ExecutableHeader? stub, ExecutableHeader? header) { builder.AppendLine(" Module-Reference Table Information:"); builder.AppendLine(" -------------------------"); diff --git a/SabreTools.Serialization/Printers/PortableExecutable.cs b/SabreTools.Serialization/Printers/PortableExecutable.cs index 6364b8b0..ba6f1728 100644 --- a/SabreTools.Serialization/Printers/PortableExecutable.cs +++ b/SabreTools.Serialization/Printers/PortableExecutable.cs @@ -3,12 +3,12 @@ using System.Collections.Generic; using System.Text; using System.Xml; using SabreTools.IO.Extensions; -using SabreTools.Models.COFF; -using SabreTools.Models.COFF.SymbolTableEntries; -using SabreTools.Models.PortableExecutable; -using SabreTools.Models.PortableExecutable.Resource.Entries; using SabreTools.Serialization.Extensions; using SabreTools.Serialization.Interfaces; +using SabreTools.Serialization.Models.COFF; +using SabreTools.Serialization.Models.COFF.SymbolTableEntries; +using SabreTools.Serialization.Models.PortableExecutable; +using SabreTools.Serialization.Models.PortableExecutable.Resource.Entries; namespace SabreTools.Serialization.Printers { @@ -60,7 +60,7 @@ namespace SabreTools.Serialization.Printers Print(builder, executable.DebugTable); } - private static void Print(StringBuilder builder, SabreTools.Models.MSDOS.ExecutableHeader? header) + private static void Print(StringBuilder builder, SabreTools.Serialization.Models.MSDOS.ExecutableHeader? header) { builder.AppendLine(" MS-DOS Stub Header Information:"); builder.AppendLine(" -------------------------"); @@ -119,7 +119,7 @@ namespace SabreTools.Serialization.Printers builder.AppendLine(); } - private static void Print(StringBuilder builder, SabreTools.Models.PortableExecutable.OptionalHeader? header, SectionHeader[]? table) + private static void Print(StringBuilder builder, SabreTools.Serialization.Models.PortableExecutable.OptionalHeader? header, SectionHeader[]? table) { builder.AppendLine(" Optional Header Information:"); builder.AppendLine(" -------------------------"); @@ -417,7 +417,7 @@ namespace SabreTools.Serialization.Printers builder.AppendLine(entry.Reserved2, " Reserved"); } - private static void Print(StringBuilder builder, SabreTools.Models.COFF.StringTable? stringTable) + private static void Print(StringBuilder builder, SabreTools.Serialization.Models.COFF.StringTable? stringTable) { builder.AppendLine(" String Table Information:"); builder.AppendLine(" -------------------------"); @@ -439,7 +439,7 @@ namespace SabreTools.Serialization.Printers builder.AppendLine(); } - private static void Print(StringBuilder builder, SabreTools.Models.PortableExecutable.AttributeCertificate.Entry[]? entries) + private static void Print(StringBuilder builder, SabreTools.Serialization.Models.PortableExecutable.AttributeCertificate.Entry[]? entries) { builder.AppendLine(" Attribute Certificate Table Information:"); builder.AppendLine(" -------------------------"); @@ -506,7 +506,7 @@ namespace SabreTools.Serialization.Printers } } - private static void Print(StringBuilder builder, SabreTools.Models.PortableExecutable.DelayLoad.DirectoryTable? table, SectionHeader[]? sections) + private static void Print(StringBuilder builder, SabreTools.Serialization.Models.PortableExecutable.DelayLoad.DirectoryTable? table, SectionHeader[]? sections) { builder.AppendLine(" Delay-Load Directory Table Information:"); builder.AppendLine(" -------------------------"); @@ -533,7 +533,7 @@ namespace SabreTools.Serialization.Printers builder.AppendLine(); } - private static void Print(StringBuilder builder, SabreTools.Models.PortableExecutable.BaseRelocation.Block[]? entries, SectionHeader[]? sections) + private static void Print(StringBuilder builder, SabreTools.Serialization.Models.PortableExecutable.BaseRelocation.Block[]? entries, SectionHeader[]? sections) { builder.AppendLine(" Base Relocation Table Information:"); builder.AppendLine(" -------------------------"); @@ -576,7 +576,7 @@ namespace SabreTools.Serialization.Printers builder.AppendLine(); } - private static void Print(StringBuilder builder, SabreTools.Models.PortableExecutable.DebugData.Table? table) + private static void Print(StringBuilder builder, SabreTools.Serialization.Models.PortableExecutable.DebugData.Table? table) { builder.AppendLine(" Debug Table Information:"); builder.AppendLine(" -------------------------"); @@ -605,7 +605,7 @@ namespace SabreTools.Serialization.Printers builder.AppendLine(); } - private static void Print(StringBuilder builder, SabreTools.Models.PortableExecutable.Export.DirectoryTable? table, SectionHeader[]? sections) + private static void Print(StringBuilder builder, SabreTools.Serialization.Models.PortableExecutable.Export.DirectoryTable? table, SectionHeader[]? sections) { builder.AppendLine(value: " Export Directory Table Information:"); builder.AppendLine(" -------------------------"); @@ -635,7 +635,7 @@ namespace SabreTools.Serialization.Printers builder.AppendLine(); } - private static void Print(StringBuilder builder, SabreTools.Models.PortableExecutable.Export.AddressTableEntry[]? table, SectionHeader[]? sections) + private static void Print(StringBuilder builder, SabreTools.Serialization.Models.PortableExecutable.Export.AddressTableEntry[]? table, SectionHeader[]? sections) { builder.AppendLine(" Export Address Table Information:"); builder.AppendLine(" -------------------------"); @@ -658,7 +658,7 @@ namespace SabreTools.Serialization.Printers builder.AppendLine(); } - private static void Print(StringBuilder builder, SabreTools.Models.PortableExecutable.Export.NamePointerTable? table) + private static void Print(StringBuilder builder, SabreTools.Serialization.Models.PortableExecutable.Export.NamePointerTable? table) { builder.AppendLine(" Export Name Pointer Table Information:"); builder.AppendLine(" -------------------------"); @@ -680,7 +680,7 @@ namespace SabreTools.Serialization.Printers builder.AppendLine(); } - private static void Print(StringBuilder builder, SabreTools.Models.PortableExecutable.Export.OrdinalTable? table) + private static void Print(StringBuilder builder, SabreTools.Serialization.Models.PortableExecutable.Export.OrdinalTable? table) { builder.AppendLine(" Export Ordinal Table Information:"); builder.AppendLine(" -------------------------"); @@ -702,7 +702,7 @@ namespace SabreTools.Serialization.Printers builder.AppendLine(); } - private static void Print(StringBuilder builder, SabreTools.Models.PortableExecutable.Export.NameTable? table) + private static void Print(StringBuilder builder, SabreTools.Serialization.Models.PortableExecutable.Export.NameTable? table) { builder.AppendLine(" Export Name Table Information:"); builder.AppendLine(" -------------------------"); @@ -724,7 +724,7 @@ namespace SabreTools.Serialization.Printers builder.AppendLine(); } - private static void Print(StringBuilder builder, SabreTools.Models.PortableExecutable.Import.DirectoryTableEntry[]? table, SectionHeader[]? sections) + private static void Print(StringBuilder builder, SabreTools.Serialization.Models.PortableExecutable.Import.DirectoryTableEntry[]? table, SectionHeader[]? sections) { builder.AppendLine(" Import Directory Table Information:"); builder.AppendLine(" -------------------------"); @@ -754,7 +754,7 @@ namespace SabreTools.Serialization.Printers builder.AppendLine(); } - private static void Print(StringBuilder builder, Dictionary? tables, SectionHeader[]? sections) + private static void Print(StringBuilder builder, Dictionary? tables, SectionHeader[]? sections) { builder.AppendLine(" Import Lookup Tables Information:"); builder.AppendLine(" -------------------------"); @@ -800,7 +800,7 @@ namespace SabreTools.Serialization.Printers builder.AppendLine(); } - private static void Print(StringBuilder builder, Dictionary? tables, SectionHeader[]? sections) + private static void Print(StringBuilder builder, Dictionary? tables, SectionHeader[]? sections) { builder.AppendLine(" Import Address Tables Information:"); builder.AppendLine(" -------------------------"); @@ -846,7 +846,7 @@ namespace SabreTools.Serialization.Printers builder.AppendLine(); } - private static void Print(StringBuilder builder, SabreTools.Models.PortableExecutable.Import.HintNameTableEntry[]? table) + private static void Print(StringBuilder builder, SabreTools.Serialization.Models.PortableExecutable.Import.HintNameTableEntry[]? table) { builder.AppendLine(" Import Hint/Name Table Information:"); builder.AppendLine(" -------------------------"); @@ -869,7 +869,7 @@ namespace SabreTools.Serialization.Printers builder.AppendLine(); } - private static void Print(StringBuilder builder, SabreTools.Models.PortableExecutable.Resource.DirectoryTable? table, SectionHeader[]? sections) + private static void Print(StringBuilder builder, SabreTools.Serialization.Models.PortableExecutable.Resource.DirectoryTable? table, SectionHeader[]? sections) { builder.AppendLine(" Resource Directory Table Information:"); builder.AppendLine(" -------------------------"); @@ -884,7 +884,7 @@ namespace SabreTools.Serialization.Printers builder.AppendLine(); } - private static void Print(StringBuilder builder, SabreTools.Models.PortableExecutable.Resource.DirectoryTable table, int level, List types, SectionHeader[]? sections) + private static void Print(StringBuilder builder, SabreTools.Serialization.Models.PortableExecutable.Resource.DirectoryTable table, int level, List types, SectionHeader[]? sections) { string padding = new(' ', (level + 1) * 2); @@ -924,7 +924,7 @@ namespace SabreTools.Serialization.Printers } } - private static void Print(StringBuilder builder, SabreTools.Models.PortableExecutable.Resource.DirectoryEntry entry, int level, List types, SectionHeader[]? sections) + private static void Print(StringBuilder builder, SabreTools.Serialization.Models.PortableExecutable.Resource.DirectoryEntry entry, int level, List types, SectionHeader[]? sections) { string padding = new(' ', (level + 1) * 2); @@ -945,7 +945,7 @@ namespace SabreTools.Serialization.Printers Print(builder, entry.Subdirectory, level: level + 1, types, sections); } - private static void Print(StringBuilder builder, SabreTools.Models.PortableExecutable.Resource.DataEntry entry, int level, List types, SectionHeader[]? sections) + private static void Print(StringBuilder builder, SabreTools.Serialization.Models.PortableExecutable.Resource.DataEntry entry, int level, List types, SectionHeader[]? sections) { string padding = new(' ', (level + 1) * 2); @@ -1041,25 +1041,25 @@ namespace SabreTools.Serialization.Printers builder.AppendLine(); } - private static void PrintResourceRT_CURSOR(SabreTools.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) + private static void PrintResourceRT_CURSOR(SabreTools.Serialization.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) { string padding = new(' ', (level + 1) * 2); builder.AppendLine($"{padding}Hardware-dependent cursor resource found, not parsed yet"); } - private static void PrintResourceRT_BITMAP(SabreTools.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) + private static void PrintResourceRT_BITMAP(SabreTools.Serialization.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) { string padding = new(' ', (level + 1) * 2); builder.AppendLine($"{padding}Bitmap resource found, not parsed yet"); } - private static void PrintResourceRT_ICON(SabreTools.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) + private static void PrintResourceRT_ICON(SabreTools.Serialization.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) { string padding = new(' ', (level + 1) * 2); builder.AppendLine($"{padding}Hardware-dependent icon resource found, not parsed yet"); } - private static void PrintResourceRT_MENU(SabreTools.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) + private static void PrintResourceRT_MENU(SabreTools.Serialization.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) { string padding = new(' ', (level + 1) * 2); @@ -1137,7 +1137,7 @@ namespace SabreTools.Serialization.Printers } } - private static void PrintResourceRT_DIALOG(SabreTools.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) + private static void PrintResourceRT_DIALOG(SabreTools.Serialization.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) { string padding = new(' ', (level + 1) * 2); @@ -1272,7 +1272,7 @@ namespace SabreTools.Serialization.Printers } } - private static void PrintResourceRT_STRING(SabreTools.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) + private static void PrintResourceRT_STRING(SabreTools.Serialization.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) { string padding = new(' ', (level + 1) * 2); @@ -1292,19 +1292,19 @@ namespace SabreTools.Serialization.Printers } } - private static void PrintResourceRT_FONTDIR(SabreTools.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) + private static void PrintResourceRT_FONTDIR(SabreTools.Serialization.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) { string padding = new(' ', (level + 1) * 2); builder.AppendLine($"{padding}Font directory resource found, not parsed yet"); } - private static void PrintResourceRT_FONT(SabreTools.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) + private static void PrintResourceRT_FONT(SabreTools.Serialization.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) { string padding = new(' ', (level + 1) * 2); builder.AppendLine($"{padding}Font resource found, not parsed yet"); } - private static void PrintResourceRT_ACCELERATOR(SabreTools.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) + private static void PrintResourceRT_ACCELERATOR(SabreTools.Serialization.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) { string padding = new(' ', (level + 1) * 2); @@ -1327,7 +1327,7 @@ namespace SabreTools.Serialization.Printers } } - private static void PrintResourceRT_RCDATA(SabreTools.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) + private static void PrintResourceRT_RCDATA(SabreTools.Serialization.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) { string padding = new(' ', (level + 1) * 2); builder.AppendLine($"{padding}Application-defined resource found, not parsed yet"); @@ -1386,7 +1386,7 @@ namespace SabreTools.Serialization.Printers } } - private static void PrintResourceRT_MESSAGETABLE(SabreTools.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) + private static void PrintResourceRT_MESSAGETABLE(SabreTools.Serialization.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) { string padding = new(' ', (level + 1) * 2); @@ -1453,19 +1453,19 @@ namespace SabreTools.Serialization.Printers } } - private static void PrintResourceRT_GROUP_CURSOR(SabreTools.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) + private static void PrintResourceRT_GROUP_CURSOR(SabreTools.Serialization.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) { string padding = new(' ', (level + 1) * 2); builder.AppendLine($"{padding}Hardware-independent cursor resource found, not parsed yet"); } - private static void PrintResourceRT_GROUP_ICON(SabreTools.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) + private static void PrintResourceRT_GROUP_ICON(SabreTools.Serialization.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) { string padding = new(' ', (level + 1) * 2); builder.AppendLine($"{padding}Hardware-independent icon resource found, not parsed yet"); } - private static void PrintResourceRT_VERSION(SabreTools.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) + private static void PrintResourceRT_VERSION(SabreTools.Serialization.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) { string padding = new(' ', (level + 1) * 2); @@ -1586,37 +1586,37 @@ namespace SabreTools.Serialization.Printers } } - private static void PrintResourceRT_DLGINCLUDE(SabreTools.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) + private static void PrintResourceRT_DLGINCLUDE(SabreTools.Serialization.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) { string padding = new(' ', (level + 1) * 2); builder.AppendLine($"{padding}External header resource found, not parsed yet"); } - private static void PrintResourceRT_PLUGPLAY(SabreTools.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) + private static void PrintResourceRT_PLUGPLAY(SabreTools.Serialization.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) { string padding = new(' ', (level + 1) * 2); builder.AppendLine($"{padding}Plug and Play resource found, not parsed yet"); } - private static void PrintResourceRT_VXD(SabreTools.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) + private static void PrintResourceRT_VXD(SabreTools.Serialization.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) { string padding = new(' ', (level + 1) * 2); builder.AppendLine($"{padding}VXD found, not parsed yet"); } - private static void PrintResourceRT_ANICURSOR(SabreTools.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) + private static void PrintResourceRT_ANICURSOR(SabreTools.Serialization.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) { string padding = new(' ', (level + 1) * 2); builder.AppendLine($"{padding}Animated cursor found, not parsed yet"); } - private static void PrintResourceRT_ANIICON(SabreTools.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) + private static void PrintResourceRT_ANIICON(SabreTools.Serialization.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) { string padding = new(' ', (level + 1) * 2); builder.AppendLine($"{padding}Animated icon found, not parsed yet"); } - private static void PrintResourceRT_HTML(SabreTools.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) + private static void PrintResourceRT_HTML(SabreTools.Serialization.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) { string padding = new(' ', (level + 1) * 2); builder.AppendLine($"{padding}HTML resource found, not parsed yet"); @@ -1629,7 +1629,7 @@ namespace SabreTools.Serialization.Printers // builder.AppendLine(Encoding.Unicode.GetString(entry.Data), $"{padding}Value (Unicode)"); } - private static void PrintResourceRT_MANIFEST(SabreTools.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) + private static void PrintResourceRT_MANIFEST(SabreTools.Serialization.Models.PortableExecutable.Resource.DataEntry entry, int level, StringBuilder builder) { string padding = new(' ', (level + 1) * 2); @@ -1806,7 +1806,7 @@ namespace SabreTools.Serialization.Printers } } - private static void PrintResourceUNKNOWN(SabreTools.Models.PortableExecutable.Resource.DataEntry entry, int level, object resourceType, StringBuilder builder) + private static void PrintResourceUNKNOWN(SabreTools.Serialization.Models.PortableExecutable.Resource.DataEntry entry, int level, object resourceType, StringBuilder builder) { string padding = new(' ', (level + 1) * 2); diff --git a/SabreTools.Serialization/Printers/SecuROMDFA.cs b/SabreTools.Serialization/Printers/SecuROMDFA.cs index 0b565d30..ebba93e2 100644 --- a/SabreTools.Serialization/Printers/SecuROMDFA.cs +++ b/SabreTools.Serialization/Printers/SecuROMDFA.cs @@ -1,6 +1,6 @@ using System.Text; -using SabreTools.Models.SecuROM; using SabreTools.Serialization.Interfaces; +using SabreTools.Serialization.Models.SecuROM; namespace SabreTools.Serialization.Printers { @@ -18,7 +18,7 @@ namespace SabreTools.Serialization.Printers builder.AppendLine(dfaFile.BlockOrHeaderSize, "Block or header size"); builder.AppendLine(); - + Print(builder, dfaFile.Entries); } diff --git a/SabreTools.Serialization/Printers/WiseOverlayHeader.cs b/SabreTools.Serialization/Printers/WiseOverlayHeader.cs index d2d00168..2aab8625 100644 --- a/SabreTools.Serialization/Printers/WiseOverlayHeader.cs +++ b/SabreTools.Serialization/Printers/WiseOverlayHeader.cs @@ -1,6 +1,6 @@ using System.Text; -using SabreTools.Models.WiseInstaller; using SabreTools.Serialization.Interfaces; +using SabreTools.Serialization.Models.WiseInstaller; namespace SabreTools.Serialization.Printers { diff --git a/SabreTools.Serialization/Printers/WiseScript.cs b/SabreTools.Serialization/Printers/WiseScript.cs index e78a8630..1e0162bc 100644 --- a/SabreTools.Serialization/Printers/WiseScript.cs +++ b/SabreTools.Serialization/Printers/WiseScript.cs @@ -1,8 +1,8 @@ using System.Text; -using SabreTools.Models.WiseInstaller; -using SabreTools.Models.WiseInstaller.Actions; using SabreTools.Serialization.Extensions; using SabreTools.Serialization.Interfaces; +using SabreTools.Serialization.Models.WiseInstaller; +using SabreTools.Serialization.Models.WiseInstaller.Actions; namespace SabreTools.Serialization.Printers { diff --git a/SabreTools.Serialization/Printers/WiseSectionHeader.cs b/SabreTools.Serialization/Printers/WiseSectionHeader.cs index bc56fe52..999ed426 100644 --- a/SabreTools.Serialization/Printers/WiseSectionHeader.cs +++ b/SabreTools.Serialization/Printers/WiseSectionHeader.cs @@ -1,6 +1,6 @@ using System.Text; -using SabreTools.Models.WiseInstaller; using SabreTools.Serialization.Interfaces; +using SabreTools.Serialization.Models.WiseInstaller; namespace SabreTools.Serialization.Printers { diff --git a/SabreTools.Serialization/SabreTools.Serialization.csproj b/SabreTools.Serialization/SabreTools.Serialization.csproj index d65eb653..13a36780 100644 --- a/SabreTools.Serialization/SabreTools.Serialization.csproj +++ b/SabreTools.Serialization/SabreTools.Serialization.csproj @@ -89,7 +89,6 @@ - diff --git a/SabreTools.Serialization/WrapperFactory.cs b/SabreTools.Serialization/WrapperFactory.cs index db3b0dc8..5d8dc026 100644 --- a/SabreTools.Serialization/WrapperFactory.cs +++ b/SabreTools.Serialization/WrapperFactory.cs @@ -97,22 +97,22 @@ namespace SabreTools.Serialization } // New Executable - else if (magic.StartsWith(SabreTools.Models.NewExecutable.Constants.SignatureBytes)) + else if (magic.StartsWith(SabreTools.Serialization.Models.NewExecutable.Constants.SignatureBytes)) { stream.Seek(initialOffset, SeekOrigin.Begin); return NewExecutable.Create(stream); } // Linear Executable - else if (magic.StartsWith(SabreTools.Models.LinearExecutable.Constants.LESignatureBytes) - || magic.StartsWith(SabreTools.Models.LinearExecutable.Constants.LXSignatureBytes)) + else if (magic.StartsWith(SabreTools.Serialization.Models.LinearExecutable.Constants.LESignatureBytes) + || magic.StartsWith(SabreTools.Serialization.Models.LinearExecutable.Constants.LXSignatureBytes)) { stream.Seek(initialOffset, SeekOrigin.Begin); return LinearExecutable.Create(stream); } // Portable Executable - else if (magic.StartsWith(SabreTools.Models.PortableExecutable.Constants.SignatureBytes)) + else if (magic.StartsWith(SabreTools.Serialization.Models.PortableExecutable.Constants.SignatureBytes)) { stream.Seek(initialOffset, SeekOrigin.Begin); return PortableExecutable.Create(stream); @@ -243,7 +243,7 @@ namespace SabreTools.Serialization #region Executable // DOS MZ executable file format (and descendants) - if (magic.StartsWith(SabreTools.Models.MSDOS.Constants.SignatureBytes)) + if (magic.StartsWith(SabreTools.Serialization.Models.MSDOS.Constants.SignatureBytes)) return WrapperType.Executable; // None of the following are supported yet @@ -617,7 +617,7 @@ namespace SabreTools.Serialization #region SecuROM DFA - if (magic.StartsWith(SabreTools.Models.SecuROM.Constants.DFAMagicBytes)) + if (magic.StartsWith(SabreTools.Serialization.Models.SecuROM.Constants.DFAMagicBytes)) return WrapperType.SecuROMDFA; #endregion diff --git a/SabreTools.Serialization/Wrappers/LinearExecutable.cs b/SabreTools.Serialization/Wrappers/LinearExecutable.cs index db80b83e..f21f4b97 100644 --- a/SabreTools.Serialization/Wrappers/LinearExecutable.cs +++ b/SabreTools.Serialization/Wrappers/LinearExecutable.cs @@ -1,7 +1,7 @@ using System; using System.IO; using SabreTools.IO.Extensions; -using SabreTools.Models.LinearExecutable; +using SabreTools.Serialization.Models.LinearExecutable; namespace SabreTools.Serialization.Wrappers { @@ -26,7 +26,7 @@ namespace SabreTools.Serialization.Wrappers public ResourceTableEntry[]? ResourceTable => Model.ResourceTable; /// - public SabreTools.Models.MSDOS.Executable? Stub => Model.Stub; + public SabreTools.Serialization.Models.MSDOS.Executable? Stub => Model.Stub; #endregion diff --git a/SabreTools.Serialization/Wrappers/MSDOS.cs b/SabreTools.Serialization/Wrappers/MSDOS.cs index 395f0d6d..8774c65c 100644 --- a/SabreTools.Serialization/Wrappers/MSDOS.cs +++ b/SabreTools.Serialization/Wrappers/MSDOS.cs @@ -1,5 +1,5 @@ using System.IO; -using SabreTools.Models.MSDOS; +using SabreTools.Serialization.Models.MSDOS; namespace SabreTools.Serialization.Wrappers { diff --git a/SabreTools.Serialization/Wrappers/NewExecutable.Extraction.cs b/SabreTools.Serialization/Wrappers/NewExecutable.Extraction.cs index 885f7c90..29ba81ac 100644 --- a/SabreTools.Serialization/Wrappers/NewExecutable.Extraction.cs +++ b/SabreTools.Serialization/Wrappers/NewExecutable.Extraction.cs @@ -138,7 +138,7 @@ namespace SabreTools.Serialization.Wrappers extension = "xz"; break; } - else if (overlaySample.StartsWith(SabreTools.Models.MSDOS.Constants.SignatureBytes)) + else if (overlaySample.StartsWith(SabreTools.Serialization.Models.MSDOS.Constants.SignatureBytes)) { extension = "bin"; // exe/dll break; diff --git a/SabreTools.Serialization/Wrappers/NewExecutable.cs b/SabreTools.Serialization/Wrappers/NewExecutable.cs index 9d8f49ce..a97c88bf 100644 --- a/SabreTools.Serialization/Wrappers/NewExecutable.cs +++ b/SabreTools.Serialization/Wrappers/NewExecutable.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.IO; using SabreTools.IO.Extensions; -using SabreTools.Models.NewExecutable; +using SabreTools.Serialization.Models.NewExecutable; namespace SabreTools.Serialization.Wrappers { @@ -261,7 +261,7 @@ namespace SabreTools.Serialization.Wrappers public SegmentTableEntry[]? SegmentTable => Model.SegmentTable; /// - public SabreTools.Models.MSDOS.Executable? Stub => Model.Stub; + public SabreTools.Serialization.Models.MSDOS.Executable? Stub => Model.Stub; /// /// Stub executable data, if it exists diff --git a/SabreTools.Serialization/Wrappers/PortableExecutable.Extraction.cs b/SabreTools.Serialization/Wrappers/PortableExecutable.Extraction.cs index 63f5b60b..dbb91139 100644 --- a/SabreTools.Serialization/Wrappers/PortableExecutable.Extraction.cs +++ b/SabreTools.Serialization/Wrappers/PortableExecutable.Extraction.cs @@ -199,7 +199,7 @@ namespace SabreTools.Serialization.Wrappers extension = "xz"; break; } - else if (overlaySample.StartsWith(SabreTools.Models.MSDOS.Constants.SignatureBytes)) + else if (overlaySample.StartsWith(SabreTools.Serialization.Models.MSDOS.Constants.SignatureBytes)) { extension = "bin"; // exe/dll break; @@ -402,7 +402,7 @@ namespace SabreTools.Serialization.Wrappers extension = "xz"; break; } - else if (resourceSample.StartsWith(SabreTools.Models.MSDOS.Constants.SignatureBytes)) + else if (resourceSample.StartsWith(SabreTools.Serialization.Models.MSDOS.Constants.SignatureBytes)) { extension = "bin"; // exe/dll break; diff --git a/SabreTools.Serialization/Wrappers/PortableExecutable.cs b/SabreTools.Serialization/Wrappers/PortableExecutable.cs index e3b89c71..ad3629fb 100644 --- a/SabreTools.Serialization/Wrappers/PortableExecutable.cs +++ b/SabreTools.Serialization/Wrappers/PortableExecutable.cs @@ -3,10 +3,10 @@ using System.Collections.Generic; using System.IO; using System.Text; using SabreTools.IO.Extensions; -using SabreTools.Models.COFF; -using SabreTools.Models.PortableExecutable; -using SabreTools.Models.PortableExecutable.Resource.Entries; using SabreTools.Serialization.Extensions; +using SabreTools.Serialization.Models.COFF; +using SabreTools.Serialization.Models.PortableExecutable; +using SabreTools.Serialization.Models.PortableExecutable.Resource.Entries; namespace SabreTools.Serialization.Wrappers { @@ -49,7 +49,7 @@ namespace SabreTools.Serialization.Wrappers } /// - public SabreTools.Models.PortableExecutable.DebugData.Entry[]? DebugDirectoryTable + public SabreTools.Serialization.Models.PortableExecutable.DebugData.Entry[]? DebugDirectoryTable => Model.DebugTable?.DebugDirectoryTable; /// @@ -104,19 +104,19 @@ namespace SabreTools.Serialization.Wrappers } /// - public SabreTools.Models.PortableExecutable.Export.AddressTableEntry[]? ExportTable => Model.ExportAddressTable; + public SabreTools.Serialization.Models.PortableExecutable.Export.AddressTableEntry[]? ExportTable => Model.ExportAddressTable; /// - public SabreTools.Models.PortableExecutable.Export.DirectoryTable? ExportDirectoryTable => Model.ExportDirectoryTable; + public SabreTools.Serialization.Models.PortableExecutable.Export.DirectoryTable? ExportDirectoryTable => Model.ExportDirectoryTable; /// - public SabreTools.Models.PortableExecutable.Export.NamePointerTable? ExportNamePointerTable => Model.NamePointerTable; + public SabreTools.Serialization.Models.PortableExecutable.Export.NamePointerTable? ExportNamePointerTable => Model.NamePointerTable; /// - public SabreTools.Models.PortableExecutable.Export.NameTable? ExportNameTable => Model.ExportNameTable; + public SabreTools.Serialization.Models.PortableExecutable.Export.NameTable? ExportNameTable => Model.ExportNameTable; /// - public SabreTools.Models.PortableExecutable.Export.OrdinalTable? ExportOrdinalTable => Model.OrdinalTable; + public SabreTools.Serialization.Models.PortableExecutable.Export.OrdinalTable? ExportOrdinalTable => Model.OrdinalTable; /// /// Header padding data, if it exists @@ -197,16 +197,16 @@ namespace SabreTools.Serialization.Wrappers } /// - public Dictionary? ImportAddressTables => Model.ImportAddressTables; + public Dictionary? ImportAddressTables => Model.ImportAddressTables; /// - public SabreTools.Models.PortableExecutable.Import.DirectoryTableEntry[]? ImportDirectoryTable => Model.ImportDirectoryTable; + public SabreTools.Serialization.Models.PortableExecutable.Import.DirectoryTableEntry[]? ImportDirectoryTable => Model.ImportDirectoryTable; /// - public SabreTools.Models.PortableExecutable.Import.HintNameTableEntry[]? ImportHintNameTable => Model.HintNameTable; + public SabreTools.Serialization.Models.PortableExecutable.Import.HintNameTableEntry[]? ImportHintNameTable => Model.HintNameTable; /// - public Dictionary? ImportLookupTables => Model.ImportLookupTables; + public Dictionary? ImportLookupTables => Model.ImportLookupTables; /// /// SecuROM Matroschka package wrapper, if it exists @@ -287,7 +287,7 @@ namespace SabreTools.Serialization.Wrappers } /// - public SabreTools.Models.PortableExecutable.OptionalHeader? OptionalHeader => Model.OptionalHeader; + public SabreTools.Serialization.Models.PortableExecutable.OptionalHeader? OptionalHeader => Model.OptionalHeader; /// /// Address of the overlay, if it exists @@ -501,7 +501,7 @@ namespace SabreTools.Serialization.Wrappers } /// - public SabreTools.Models.PortableExecutable.Resource.DirectoryTable? ResourceDirectoryTable => Model.ResourceDirectoryTable; + public SabreTools.Serialization.Models.PortableExecutable.Resource.DirectoryTable? ResourceDirectoryTable => Model.ResourceDirectoryTable; /// /// Sanitized section names @@ -590,7 +590,7 @@ namespace SabreTools.Serialization.Wrappers } /// - public SabreTools.Models.MSDOS.Executable? Stub => Model.Stub; + public SabreTools.Serialization.Models.MSDOS.Executable? Stub => Model.Stub; /// /// Stub executable data, if it exists @@ -1265,14 +1265,14 @@ namespace SabreTools.Serialization.Wrappers if (data == null) continue; - if (data is SabreTools.Models.PortableExecutable.DebugData.NB10ProgramDatabase n) + if (data is SabreTools.Serialization.Models.PortableExecutable.DebugData.NB10ProgramDatabase n) { if (n.PdbFileName == null || !n.PdbFileName.Contains(path)) continue; debugFound.Add(n); } - else if (data is SabreTools.Models.PortableExecutable.DebugData.RSDSProgramDatabase r) + else if (data is SabreTools.Serialization.Models.PortableExecutable.DebugData.RSDSProgramDatabase r) { if (r.PathAndFileName == null || !r.PathAndFileName.Contains(path)) continue; @@ -1672,7 +1672,7 @@ namespace SabreTools.Serialization.Wrappers { if (kvp.Value == null || kvp.Value is not byte[] ba) continue; - if (!ba.StartsWith(SabreTools.Models.MSDOS.Constants.SignatureBytes)) + if (!ba.StartsWith(SabreTools.Serialization.Models.MSDOS.Constants.SignatureBytes)) continue; exeResources = true; @@ -1696,7 +1696,7 @@ namespace SabreTools.Serialization.Wrappers while (_dataSource.Position < resourceTableOffset + OptionalHeader.ResourceTable.Size && _dataSource.Position < _dataSource.Length) { ushort possibleSignature = _dataSource.ReadUInt16(); - if (possibleSignature == SabreTools.Models.MSDOS.Constants.SignatureUInt16) + if (possibleSignature == SabreTools.Serialization.Models.MSDOS.Constants.SignatureUInt16) { resourceOffset = _dataSource.Position - 2; break; @@ -1726,7 +1726,7 @@ namespace SabreTools.Serialization.Wrappers /// /// Parse the resource directory table information /// - private void ParseResourceDirectoryTable(SabreTools.Models.PortableExecutable.Resource.DirectoryTable table, List types) + private void ParseResourceDirectoryTable(SabreTools.Serialization.Models.PortableExecutable.Resource.DirectoryTable table, List types) { if (table?.Entries == null) return; @@ -1748,7 +1748,7 @@ namespace SabreTools.Serialization.Wrappers /// /// Parse the name resource directory entry information /// - private void ParseResourceDirectoryEntry(SabreTools.Models.PortableExecutable.Resource.DirectoryEntry entry, List types) + private void ParseResourceDirectoryEntry(SabreTools.Serialization.Models.PortableExecutable.Resource.DirectoryEntry entry, List types) { if (entry.DataEntry != null) ParseResourceDataEntry(entry.DataEntry, types); @@ -1764,7 +1764,7 @@ namespace SabreTools.Serialization.Wrappers /// of those resources in the entire exectuable. This means that only the last found version or manifest will /// ever be cached. /// - private void ParseResourceDataEntry(SabreTools.Models.PortableExecutable.Resource.DataEntry entry, List types) + private void ParseResourceDataEntry(SabreTools.Serialization.Models.PortableExecutable.Resource.DataEntry entry, List types) { // Create the key and value objects string key = types == null diff --git a/SabreTools.Serialization/Wrappers/SecuROMDFA.cs b/SabreTools.Serialization/Wrappers/SecuROMDFA.cs index 4ea3b7ab..9b603ab6 100644 --- a/SabreTools.Serialization/Wrappers/SecuROMDFA.cs +++ b/SabreTools.Serialization/Wrappers/SecuROMDFA.cs @@ -1,5 +1,5 @@ using System.IO; -using SabreTools.Models.SecuROM; +using SabreTools.Serialization.Models.SecuROM; namespace SabreTools.Serialization.Wrappers { diff --git a/SabreTools.Serialization/Wrappers/SecuROMMatroschkaPackage.Extraction.cs b/SabreTools.Serialization/Wrappers/SecuROMMatroschkaPackage.Extraction.cs index c4401914..aeed6fb5 100644 --- a/SabreTools.Serialization/Wrappers/SecuROMMatroschkaPackage.Extraction.cs +++ b/SabreTools.Serialization/Wrappers/SecuROMMatroschkaPackage.Extraction.cs @@ -2,8 +2,8 @@ using System; using System.IO; using System.Text; using SabreTools.Hashing; -using SabreTools.Models.SecuROM; using SabreTools.Serialization.Interfaces; +using SabreTools.Serialization.Models.SecuROM; namespace SabreTools.Serialization.Wrappers { diff --git a/SabreTools.Serialization/Wrappers/SecuROMMatroschkaPackage.cs b/SabreTools.Serialization/Wrappers/SecuROMMatroschkaPackage.cs index 39233943..eef6f87a 100644 --- a/SabreTools.Serialization/Wrappers/SecuROMMatroschkaPackage.cs +++ b/SabreTools.Serialization/Wrappers/SecuROMMatroschkaPackage.cs @@ -1,5 +1,5 @@ using System.IO; -using SabreTools.Models.SecuROM; +using SabreTools.Serialization.Models.SecuROM; namespace SabreTools.Serialization.Wrappers { @@ -112,7 +112,7 @@ namespace SabreTools.Serialization.Wrappers return null; } } - + #endregion } } diff --git a/SabreTools.Serialization/Wrappers/WiseOverlayHeader.Extraction.cs b/SabreTools.Serialization/Wrappers/WiseOverlayHeader.Extraction.cs index 6747cc38..5f2b48fa 100644 --- a/SabreTools.Serialization/Wrappers/WiseOverlayHeader.Extraction.cs +++ b/SabreTools.Serialization/Wrappers/WiseOverlayHeader.Extraction.cs @@ -2,7 +2,7 @@ using System; using System.IO; using SabreTools.IO.Compression.Deflate; using SabreTools.IO.Streams; -using SabreTools.Models.WiseInstaller.Actions; +using SabreTools.Serialization.Models.WiseInstaller.Actions; namespace SabreTools.Serialization.Wrappers { diff --git a/SabreTools.Serialization/Wrappers/WiseOverlayHeader.cs b/SabreTools.Serialization/Wrappers/WiseOverlayHeader.cs index 734d7bea..e3d276d1 100644 --- a/SabreTools.Serialization/Wrappers/WiseOverlayHeader.cs +++ b/SabreTools.Serialization/Wrappers/WiseOverlayHeader.cs @@ -1,5 +1,5 @@ using System.IO; -using SabreTools.Models.WiseInstaller; +using SabreTools.Serialization.Models.WiseInstaller; namespace SabreTools.Serialization.Wrappers { diff --git a/SabreTools.Serialization/Wrappers/WiseScript.cs b/SabreTools.Serialization/Wrappers/WiseScript.cs index 698287fa..953d873a 100644 --- a/SabreTools.Serialization/Wrappers/WiseScript.cs +++ b/SabreTools.Serialization/Wrappers/WiseScript.cs @@ -5,8 +5,8 @@ using System.Text; #if NETFRAMEWORK || NETSTANDARD using SabreTools.IO.Extensions; #endif -using SabreTools.Models.WiseInstaller; -using SabreTools.Models.WiseInstaller.Actions; +using SabreTools.Serialization.Models.WiseInstaller; +using SabreTools.Serialization.Models.WiseInstaller.Actions; namespace SabreTools.Serialization.Wrappers { diff --git a/SabreTools.Serialization/Wrappers/WiseSectionHeader.cs b/SabreTools.Serialization/Wrappers/WiseSectionHeader.cs index 84d2ea8c..f0a569a9 100644 --- a/SabreTools.Serialization/Wrappers/WiseSectionHeader.cs +++ b/SabreTools.Serialization/Wrappers/WiseSectionHeader.cs @@ -1,5 +1,5 @@ using System.IO; -using SabreTools.Models.WiseInstaller; +using SabreTools.Serialization.Models.WiseInstaller; namespace SabreTools.Serialization.Wrappers {