summaryrefslogtreecommitdiffstats
path: root/vendor/windows-metadata/src/writer/imp/file.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/windows-metadata/src/writer/imp/file.rs')
-rw-r--r--vendor/windows-metadata/src/writer/imp/file.rs138
1 files changed, 138 insertions, 0 deletions
diff --git a/vendor/windows-metadata/src/writer/imp/file.rs b/vendor/windows-metadata/src/writer/imp/file.rs
new file mode 100644
index 000000000..2f25f942b
--- /dev/null
+++ b/vendor/windows-metadata/src/writer/imp/file.rs
@@ -0,0 +1,138 @@
+use super::*;
+use std::mem::*;
+
+pub fn write(tables: Tables, strings: StagedStrings, blobs: StagedBlobs) -> Vec<u8> {
+ unsafe {
+ let mut tables = tables.stream();
+ let mut strings = strings.stream();
+ let mut blobs = blobs.stream();
+ let mut guids = vec![0; 16]; // zero guid
+ let size_of_streams = tables.len() + guids.len() + strings.len() + blobs.len();
+
+ let mut dos: IMAGE_DOS_HEADER = zeroed();
+ dos.e_magic = IMAGE_DOS_SIGNATURE as _;
+ dos.e_lfarlc = 64;
+ dos.e_lfanew = size_of::<IMAGE_DOS_HEADER>() as _;
+
+ let mut file: IMAGE_FILE_HEADER = zeroed();
+ file.Machine = IMAGE_FILE_MACHINE_I386;
+ file.NumberOfSections = 1;
+ file.SizeOfOptionalHeader = size_of::<IMAGE_OPTIONAL_HEADER32>() as _;
+ file.Characteristics = IMAGE_FILE_DLL | IMAGE_FILE_32BIT_MACHINE | IMAGE_FILE_EXECUTABLE_IMAGE;
+
+ let mut optional: IMAGE_OPTIONAL_HEADER32 = zeroed();
+ optional.Magic = IMAGE_NT_OPTIONAL_HDR32_MAGIC;
+ optional.MajorLinkerVersion = 11;
+ optional.SizeOfInitializedData = 1024;
+ optional.ImageBase = 0x400000;
+ optional.SectionAlignment = SECTION_ALIGNMENT;
+ optional.FileAlignment = 512;
+ optional.MajorOperatingSystemVersion = 6;
+ optional.MinorOperatingSystemVersion = 2;
+ optional.MajorSubsystemVersion = 6;
+ optional.MinorSubsystemVersion = 2;
+ optional.SizeOfHeaders = 512;
+ optional.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
+ optional.DllCharacteristics = IMAGE_DLLCHARACTERISTICS_NX_COMPAT | IMAGE_DLLCHARACTERISTICS_NO_SEH | IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE;
+ optional.SizeOfStackReserve = 0x100000;
+ optional.SizeOfHeapReserve = 4096;
+ optional.LoaderFlags = 0x100000;
+ optional.NumberOfRvaAndSizes = 16;
+
+ let mut section: IMAGE_SECTION_HEADER = zeroed();
+ section.Name = *b".text\0\0\0";
+ section.Characteristics = 0x4000_0020;
+ section.VirtualAddress = SECTION_ALIGNMENT;
+
+ let mut clr: IMAGE_COR20_HEADER = zeroed();
+ clr.cb = size_of::<IMAGE_COR20_HEADER>() as _;
+ clr.MajorRuntimeVersion = 2;
+ clr.MinorRuntimeVersion = 5;
+ clr.Flags = 1;
+
+ let metadata = METADATA_HEADER {
+ signature: METADATA_SIGNATURE,
+ major_version: 1,
+ minor_version: 1,
+ length: 20,
+ version: *b"WindowsRuntime\0\0\0\0\0\0",
+ streams: 4,
+ ..Default::default()
+ };
+
+ type TablesHeader = StreamHeader<4>;
+ type StringsHeader = StreamHeader<12>;
+ type GuidsHeader = StreamHeader<8>;
+ type BlobsHeader = StreamHeader<8>;
+
+ let size_of_stream_headers = size_of::<TablesHeader>() + size_of::<StringsHeader>() + size_of::<GuidsHeader>() + size_of::<BlobsHeader>();
+ let size_of_image = optional.FileAlignment as usize + size_of::<IMAGE_COR20_HEADER>() + size_of::<METADATA_HEADER>() + size_of_stream_headers + size_of_streams;
+
+ optional.SizeOfImage = round(size_of_image, optional.SectionAlignment as _) as _;
+ section.Misc.VirtualSize = size_of_image as u32 - optional.FileAlignment;
+ section.SizeOfRawData = round(section.Misc.VirtualSize as _, optional.FileAlignment as _) as _;
+
+ optional.DataDirectory[14] = IMAGE_DATA_DIRECTORY { VirtualAddress: SECTION_ALIGNMENT, Size: size_of::<IMAGE_COR20_HEADER>() as _ };
+ section.PointerToRawData = optional.FileAlignment;
+ clr.MetaData.VirtualAddress = SECTION_ALIGNMENT + size_of::<IMAGE_COR20_HEADER>() as u32;
+ clr.MetaData.Size = section.Misc.VirtualSize - size_of::<IMAGE_COR20_HEADER>() as u32;
+
+ let mut buffer = Vec::<u8>::new();
+
+ buffer.write_header(&dos);
+ buffer.write_u32(IMAGE_NT_SIGNATURE);
+ buffer.write_header(&file);
+ buffer.write_header(&optional);
+ buffer.write_header(&section);
+ debug_assert!(buffer.len() < optional.FileAlignment as _);
+ buffer.resize(optional.FileAlignment as _, 0);
+ buffer.write_header(&clr);
+ let metadata_offset = buffer.len();
+ buffer.write_header(&metadata);
+
+ let stream_offset = buffer.len() - metadata_offset + size_of_stream_headers;
+ let tables_header = TablesHeader::new(stream_offset as _, tables.len() as _, b"#~\0\0");
+ let strings_header = StringsHeader::new(tables_header.next_offset(), strings.len() as _, b"#Strings\0\0\0\0");
+ let guids_header = GuidsHeader::new(strings_header.next_offset(), guids.len() as _, b"#GUID\0\0\0");
+ let blobs_header = BlobsHeader::new(guids_header.next_offset(), blobs.len() as _, b"#Blob\0\0\0");
+
+ buffer.write_header(&tables_header);
+ buffer.write_header(&strings_header);
+ buffer.write_header(&guids_header);
+ buffer.write_header(&blobs_header);
+
+ buffer.append(&mut tables);
+ buffer.append(&mut strings);
+ buffer.append(&mut guids);
+ buffer.append(&mut blobs);
+
+ assert_eq!(clr.MetaData.Size as usize, buffer.len() - metadata_offset);
+ assert_eq!(size_of_image, buffer.len());
+
+ buffer
+ }
+}
+
+const SECTION_ALIGNMENT: u32 = 4096;
+
+#[repr(C)]
+struct StreamHeader<const LEN: usize> {
+ offset: u32,
+ size: u32,
+ name: [u8; LEN],
+}
+
+impl<const LEN: usize> StreamHeader<LEN> {
+ fn new(offset: u32, size: u32, name: &[u8; LEN]) -> Self {
+ Self { offset, size, name: *name }
+ }
+ fn next_offset(&self) -> u32 {
+ self.offset + self.size
+ }
+}
+
+fn guid_stream() -> Vec<u8> {
+ let mut buffer = Vec::new();
+ buffer.resize(16, 0); // zero guid
+ buffer
+}