Task 707: .SWM File Format

Task 707: .SWM File Format

1. List of Properties of the .SWM File Format Intrinsic to Its File System

The .SWM file format is a split variant of the Windows Imaging Format (WIM), used for dividing large WIM files into smaller parts for storage on media with file size limitations (e.g., FAT32). The format is essentially the same as WIM, with the header indicating spanning via flags and part numbers. The intrinsic properties are derived from the file header structure (WIMHEADER_V1_PACKED, typically 208 bytes), which defines the format's core metadata. These properties describe the image's structure, compression, spanning, and resource locations. The list below includes all key properties from the header:

  • Magic Number (Image Tag): An 8-byte string "MSWIM\0\0\0" (hex: 4D 53 57 49 4D 00 00 00) at offset 0, identifying the file as WIM/SWM.
  • Header Size: A 4-byte unsigned integer at offset 8, typically 208 (0xD0) for version 1 headers.
  • Version: A 4-byte unsigned integer at offset 12, indicating the format version (commonly 0x00010000 for standard WIM).
  • Flags: A 4-byte unsigned integer at offset 16, bit flags defining behaviors (e.g., 0x00000002 for compression, 0x00000008 for spanned/split, 0x00000004 for read-only).
  • Compression Chunk Size: A 4-byte unsigned integer at offset 20, specifying the chunk size for compressed resources (e.g., 32768 for XPRESS; 0 if uncompressed).
  • GUID: A 16-byte globally unique identifier at offset 24, unique to the WIM set.
  • Part Number: A 2-byte unsigned integer at offset 40, indicating the current part in a split set (starts at 1).
  • Total Parts: A 2-byte unsigned integer at offset 42, indicating the total number of parts in the split set (1 for non-split).
  • Image Count: A 4-byte unsigned integer at offset 44, number of disk images stored in the WIM.
  • Lookup Table Resource Header: A 24-byte structure at offset 48 (8-byte offset, 8-byte size, 8-byte flags), pointing to the resource lookup table.
  • XML Data Resource Header: A 24-byte structure at offset 72, pointing to XML metadata about images.
  • Boot Metadata Resource Header: A 24-byte structure at offset 96, pointing to boot-related metadata (may be zero if not bootable).
  • Boot Index: A 4-byte unsigned integer at offset 120, index of the bootable image (0 if none).
  • Integrity Table Resource Header: A 24-byte structure at offset 124, pointing to the optional integrity checksum table.
  • Unused Bytes: 60 bytes at offset 148, reserved and typically zero-filled.

In split .SWM files, the lookup table and resources are distributed across parts, with metadata and XML usually in the first part. The file system inside (e.g., NTFS structure) is captured as resources, but the properties above are the core format-level ones.

After extensive searching, finding safe, public, and direct downloads for .SWM files is challenging as they are typically large and part of proprietary Windows images. However, here are two direct links to sample .SWM files from legitimate sources (these are small test files or parts from open recovery images; verify before downloading):

(Note: If these links are invalid, .SWM files can be generated using DISM /Split-Image on a WIM file, as they are not commonly hosted due to size.)

3. Ghost Blog Embedded HTML JavaScript for Drag-and-Drop .SWM Property Dump

Here's the embedded HTML/JavaScript code for a Ghost blog post. It creates a drag-and-drop zone that reads the .SWM file, parses the header, and dumps the properties to the screen. Paste this into a Ghost code injection or custom HTML card.

Drag and drop a .SWM file here

4. Python Class for .SWM File Handling

Here's a Python class that can open, decode (read), write (modify), and print the properties from a .SWM file.

import struct
import uuid

class SWMFile:
    def __init__(self, filename):
        self.filename = filename
        self.header = None
        self.read_header()

    def read_header(self):
        with open(self.filename, 'rb') as f:
            header_data = f.read(208)
            if len(header_data) < 208:
                raise ValueError("File too small for SWM header")
            self.header = self.parse_header(header_data)

    def parse_header(self, data):
        magic = data[0:8].decode('ascii', errors='ignore')
        header_size, version, flags, compression_chunk_size = struct.unpack('<IIII', data[8:24])
        guid_bytes = data[24:40]
        guid = uuid.UUID(bytes_le=guid_bytes)
        part_number, total_parts = struct.unpack('<HH', data[40:44])
        image_count = struct.unpack('<I', data[44:48])[0]
        lookup_table = self.parse_resource_header(data[48:72])
        xml_data = self.parse_resource_header(data[72:96])
        boot_metadata = self.parse_resource_header(data[96:120])
        boot_index = struct.unpack('<I', data[120:124])[0]
        integrity_table = self.parse_resource_header(data[124:148])
        return {
            'magic': magic,
            'header_size': header_size,
            'version': version,
            'flags': flags,
            'compression_chunk_size': compression_chunk_size,
            'guid': str(guid),
            'part_number': part_number,
            'total_parts': total_parts,
            'image_count': image_count,
            'lookup_table': lookup_table,
            'xml_data': xml_data,
            'boot_metadata': boot_metadata,
            'boot_index': boot_index,
            'integrity_table': integrity_table,
        }

    def parse_resource_header(self, data):
        offset, size, flags = struct.unpack('<QQQ', data)
        return {'offset': offset, 'size': size, 'flags': flags}

    def print_properties(self):
        if not self.header:
            print("No header loaded")
            return
        for key, value in self.header.items():
            print(f"{key}: {value}")

    def write_header(self, new_header=None):
        if new_header:
            self.header = new_header
        with open(self.filename, 'r+b') as f:
            packed_data = self.pack_header()
            f.seek(0)
            f.write(packed_data)

    def pack_header(self):
        h = self.header
        data = bytearray(208)
        data[0:8] = h['magic'].encode('ascii')
        struct.pack_into('<IIII', data, 8, h['header_size'], h['version'], h['flags'], h['compression_chunk_size'])
        guid_bytes = uuid.UUID(h['guid']).bytes_le
        data[24:40] = guid_bytes
        struct.pack_into('<HH', data, 40, h['part_number'], h['total_parts'])
        struct.pack_into('<I', data, 44, h['image_count'])
        self.pack_resource_header(data, 48, h['lookup_table'])
        self.pack_resource_header(data, 72, h['xml_data'])
        self.pack_resource_header(data, 96, h['boot_metadata'])
        struct.pack_into('<I', data, 120, h['boot_index'])
        self.pack_resource_header(data, 124, h['integrity_table'])
        # Unused 60 bytes remain zero
        return data

    def pack_resource_header(self, data, offset, res):
        struct.pack_into('<QQQ', data, offset, res['offset'], res['size'], res['flags'])

# Example usage:
# swm = SWMFile('example.swm')
# swm.print_properties()
# swm.header['part_number'] = 2
# swm.write_header()

5. Java Class for .SWM File Handling

Here's a Java class that can open, decode, read, write, and print the properties from a .SWM file.

import java.io.RandomAccessFile;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.UUID;

public class SWMFile {
    private String filename;
    private ByteBuffer header;
    
    public SWMFile(String filename) {
        this.filename = filename;
        readHeader();
    }
    
    private void readHeader() {
        try (RandomAccessFile file = new RandomAccessFile(filename, "r")) {
            byte[] data = new byte[208];
            if (file.read(data) < 208) {
                throw new IOException("File too small for SWM header");
            }
            header = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN);
        } catch (IOException e) {
            e.printStack();
        }
    }
    
    public void printProperties() {
        if (header == null) {
            System.out.println("No header loaded");
            return;
        }
        header.position(0);
        byte[] magicBytes = new byte[8];
        header.get(magicBytes);
        System.out.println("magic: " + new String(magicBytes));
        System.out.println("header_size: " + header.getInt());
        System.out.println("version: " + header.getInt());
        System.out.println("flags: " + header.getInt());
        System.out.println("compression_chunk_size: " + header.getInt());
        byte[] guidBytes = new byte[16];
        header.get(guidBytes);
        UUID guid = UUID.fromString(String.format("%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
            guidBytes[3], guidBytes[2], guidBytes[1], guidBytes[0], guidBytes[5], guidBytes[4], guidBytes[7], guidBytes[6],
            guidBytes[8], guidBytes[9], guidBytes[10], guidBytes[11], guidBytes[12], guidBytes[13], guidBytes[14], guidBytes[15]));
        System.out.println("guid: " + guid);
        System.out.println("part_number: " + Short.toUnsignedInt(header.getShort()));
        System.out.println("total_parts: " + Short.toUnsignedInt(header.getShort()));
        System.out.println("image_count: " + header.getInt());
        System.out.println("lookup_table: " + getResourceHeader());
        System.out.println("xml_data: " + getResourceHeader());
        System.out.println("boot_metadata: " + getResourceHeader());
        System.out.println("boot_index: " + header.getInt());
        System.out.println("integrity_table: " + getResourceHeader());
    }
    
    private String getResourceHeader() {
        return "{offset: " + header.getLong() + ", size: " + header.getLong() + ", flags: " + header.getLong() + "}";
    }
    
    public void writeHeader() throws IOException {
        try (RandomAccessFile file = new RandomAccessFile(filename, "rw")) {
            file.write(header.array());
        }
    }
    
    // Example to modify: swm.header.putInt(40, newPartNumber); then writeHeader()
    
    public static void main(String[] args) {
        SWMFile swm = new SWMFile("example.swm");
        swm.printProperties();
    }
}

6. JavaScript Class for .SWM File Handling

Here's a JavaScript class (for Node.js) that can open, decode, read, write, and print the properties from a .SWM file.

const fs = require('fs');

class SWMFile {
  constructor(filename) {
    this.filename = filename;
    this.header = null;
    this.readHeader();
  }

  readHeader() {
    const data = fs.readSync(fs.openSync(this.filename, 'r'), Buffer.alloc(208), 0, 208, 0);
    this.header = this.parseHeader(data);
  }

  parseHeader(data) {
    const view = new DataView(data.buffer);
    return {
      magic: String.fromCharCode(...data.slice(0, 8)),
      headerSize: view.getUint32(8, true),
      version: view.getUint32(12, true),
      flags: view.getUint32(16, true),
      compressionChunkSize: view.getUint32(20, true),
      guid: Array.from(data.slice(24, 40)).map(b => b.toString(16).padStart(2, '0')).join(''),
      partNumber: view.getUint16(40, true),
      totalParts: view.getUint16(42, true),
      imageCount: view.getUint32(44, true),
      lookupTable: this.parseResource(view, 48),
      xmlData: this.parseResource(view, 72),
      bootMetadata: this.parseResource(view, 96),
      bootIndex: view.getUint32(120, true),
      integrityTable: this.parseResource(view, 124),
    };
  }

  parseResource(view, offset) {
    return {
      offset: Number(view.getBigUint64(offset, true)),
      size: Number(view.getBigUint64(offset + 8, true)),
      flags: Number(view.getBigUint64(offset + 16, true)),
    };
  }

  printProperties() {
    console.log(this.header);
  }

  writeHeader(newHeader = this.header) {
    const data = Buffer.alloc(208);
    const view = new DataView(data.buffer);
    data.write(newHeader.magic, 0, 8, 'ascii');
    view.setUint32(8, newHeader.headerSize, true);
    view.setUint32(12, newHeader.version, true);
    view.setUint32(16, newHeader.flags, true);
    view.setUint32(20, newHeader.compressionChunkSize, true);
    const guidBytes = newHeader.guid.match(/.{2}/g).map(hex => parseInt(hex, 16));
    data.set(Uint8Array.from(guidBytes), 24);
    view.setUint16(40, newHeader.partNumber, true);
    view.setUint16(42, newHeader.totalParts, true);
    view.setUint32(44, newHeader.imageCount, true);
    this.packResource(view, 48, newHeader.lookupTable);
    this.packResource(view, 72, newHeader.xmlData);
    this.packResource(view, 96, newHeader.bootMetadata);
    view.setUint32(120, newHeader.bootIndex, true);
    this.packResource(view, 124, newHeader.integrityTable);
    fs.writeFileSync(this.filename, data, {flag: 'r+'});
  }

  packResource(view, offset, res) {
    view.setBigUint64(offset, BigInt(res.offset), true);
    view.setBigUint64(offset + 8, BigInt(res.size), true);
    view.setBigUint64(offset + 16, BigInt(res.flags), true);
  }
}

// Example:
// const swm = new SWMFile('example.swm');
// swm.printProperties();
// swm.header.partNumber = 2;
// swm.writeHeader();

7. C Class (Using Struct and Functions) for .SWM File Handling

Since C doesn't have classes, here's a struct-based implementation with functions for open, decode, read, write, and print.

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <uuid/uuid.h>

typedef struct {
    char magic[8];
    uint32_t header_size;
    uint32_t version;
    uint32_t flags;
    uint32_t compression_chunk_size;
    uint8_t guid[16];
    uint16_t part_number;
    uint16_t total_parts;
    uint32_t image_count;
    struct { uint64_t offset, size, flags; } lookup_table;
    struct { uint64_t offset, size, flags; } xml_data;
    struct { uint64_t offset, size, flags; } boot_metadata;
    uint32_t boot_index;
    struct { uint64_t offset, size, flags; } integrity_table;
} SWMHeader;

void read_header(const char* filename, SWMHeader* h) {
    FILE* f = fopen(filename, "rb");
    if (f == NULL) {
        perror("fopen");
        exit(1);
    }
    uint8_t data[208];
    if (fread(data, 1, 208, f) < 208) {
        fprintf(stderr, "File too small\n");
        fclose(f);
        exit(1);
    }
    fclose(f);
    memcpy(h->magic, data, 8);
    memcpy(&h->header_size, data + 8, 4);
    memcpy(&h->version, data + 12, 4);
    memcpy(&h->flags, data + 16, 4);
    memcpy(&h->compression_chunk_size, data + 20, 4);
    memcpy(h->guid, data + 24, 16);
    memcpy(&h->part_number, data + 40, 2);
    memcpy(&h->total_parts, data + 42, 2);
    memcpy(&h->image_count, data + 44, 4);
    memcpy(&h->lookup_table, data + 48, 24);
    memcpy(&h->xml_data, data + 72, 24);
    memcpy(&h->boot_metadata, data + 96, 24);
    memcpy(&h->boot_index, data + 120, 4);
    memcpy(&h->integrity_table, data + 124, 24);
}

void print_properties(const SWMHeader* h) {
    printf("magic: %.8s\n", h->magic);
    printf("header_size: %u\n", h->header_size);
    printf("version: %u\n", h->version);
    printf("flags: %u\n", h->flags);
    printf("compression_chunk_size: %u\n", h->compression_chunk_size);
    printf("guid: ");
    for (int i = 0; i < 16; i++) printf("%02x", h->guid[i]);
    printf("\n");
    printf("part_number: %u\n", h->part_number);
    printf("total_parts: %u\n", h->total_parts);
    printf("image_count: %u\n", h->image_count);
    printf("lookup_table: {offset: %llu, size: %llu, flags: %llu}\n", h->lookup_table.offset, h->lookup_table.size, h->lookup_table.flags);
    printf("xml_data: {offset: %llu, size: %llu, flags: %llu}\n", h->xml_data.offset, h->xml_data.size, h->xml_data.flags);
    printf("boot_metadata: {offset: %llu, size: %llu, flags: %llu}\n", h->boot_metadata.offset, h->boot_metadata.size, h->boot_metadata.flags);
    printf("boot_index: %u\n", h->boot_index);
    printf("integrity_table: {offset: %llu, size: %llu, flags: %llu}\n", h->integrity_table.offset, h->integrity_table.size, h->integrity_table.flags);
}

void write_header(const char* filename, const SWMHeader* h) {
    FILE* f = fopen(filename, "rb+");
    if (f == NULL) {
        perror("fopen");
        exit(1);
    }
    uint8_t data[208] = {0};
    memcpy(data, h->magic, 8);
    memcpy(data + 8, &h->header_size, 4);
    memcpy(data + 12, &h->version, 4);
    memcpy(data + 16, &h->flags, 4);
    memcpy(data + 20, &h->compression_chunk_size, 4);
    memcpy(data + 24, h->guid, 16);
    memcpy(data + 40, &h->part_number, 2);
    memcpy(data + 42, &h->total_parts, 2);
    memcpy(data + 44, &h->image_count, 4);
    memcpy(data + 48, &h->lookup_table, 24);
    memcpy(data + 72, &h->xml_data, 24);
    memcpy(data + 96, &h->boot_metadata, 24);
    memcpy(data + 120, &h->boot_index, 4);
    memcpy(data + 124, &h->integrity_table, 24);
    fseek(f, 0, SEEK_SET);
    fwrite(data, 1, 208, f);
    fclose(f);
}

// Example usage:
// int main() {
//     SWMHeader h;
//     read_header("example.swm", &h);
//     print_properties(&h);
//     h.part_number = 2;
//     write_header("example.swm", &h);
//     return 0;
// }