mirror of
https://github.com/Elpisdev/unsegaREBORN.git
synced 2026-09-22 22:28:11 +03:00
280 lines
6.8 KiB
C
280 lines
6.8 KiB
C
#ifndef NTFS_H
|
|
#define NTFS_H
|
|
|
|
#include "lib.h"
|
|
#include "common.h"
|
|
#include "stream.h"
|
|
|
|
#define VHD_FOOTER_SIZE 512
|
|
#define VHD_SECTOR_SIZE 512
|
|
#define VHD_BAT_ENTRY_RESERVED 0xFFFFFFFF
|
|
#define NTFS_RECORD_SIZE 1024
|
|
#define MFT_RECORD_MAGIC "FILE"
|
|
#define VHD_COOKIE "conectix"
|
|
#define VHD_DYNAMIC_COOKIE "cxsparse"
|
|
#define VHD_TYPE_FIXED 2
|
|
#define VHD_TYPE_DYNAMIC 3
|
|
#define VHD_TYPE_DIFFERENCING 4
|
|
#define VHD_MAX_CHAIN_DEPTH 8
|
|
#define FILE_NAME_ATTR 0x30
|
|
#define DATA_ATTR 0x80
|
|
#define INDEX_ROOT_ATTR 0x90
|
|
#define INDEX_ALLOCATION_ATTR 0xA0
|
|
#define NTFS_SIGNATURE "NTFS "
|
|
#define NTFS_PARTITION_TYPE 0x07
|
|
#define MFT_RECORD_IN_USE 0x0001
|
|
#define MFT_RECORD_IS_DIRECTORY 0x0002
|
|
#define DIR_CACHE_INITIAL_SIZE 2048
|
|
#define NTFS_MAX_RECURSION_DEPTH 64
|
|
|
|
typedef struct {
|
|
uint64_t ref_number;
|
|
char path[MAX_PATH_LENGTH];
|
|
bool occupied;
|
|
} DirectoryEntry;
|
|
|
|
typedef struct {
|
|
DirectoryEntry* entries;
|
|
size_t capacity;
|
|
size_t count;
|
|
} DirectoryCache;
|
|
|
|
#pragma pack(push, 1)
|
|
|
|
typedef struct {
|
|
char cookie[8];
|
|
uint32_t features;
|
|
uint32_t version;
|
|
uint64_t data_offset;
|
|
uint32_t timestamp;
|
|
uint32_t creator_app;
|
|
uint32_t creator_ver;
|
|
uint32_t creator_os;
|
|
uint64_t original_size;
|
|
uint64_t current_size;
|
|
uint16_t cylinder;
|
|
uint8_t heads;
|
|
uint8_t sectors;
|
|
uint32_t disk_type;
|
|
uint32_t checksum;
|
|
uint8_t unique_id[16];
|
|
uint8_t saved_state;
|
|
uint8_t reserved[427];
|
|
} VHDFooter;
|
|
|
|
typedef struct {
|
|
uint32_t platform_code;
|
|
uint32_t platform_data_space;
|
|
uint32_t platform_data_length;
|
|
uint32_t reserved;
|
|
uint64_t platform_data_offset;
|
|
} VHDParentLocator;
|
|
|
|
typedef struct {
|
|
char cookie[8];
|
|
uint64_t data_offset;
|
|
uint64_t bat_offset;
|
|
uint32_t head_vers;
|
|
uint32_t max_bat_entries;
|
|
uint32_t block_size;
|
|
uint32_t checksum;
|
|
uint8_t parent_id[16];
|
|
uint32_t parent_timestamp;
|
|
uint32_t reserved1;
|
|
uint16_t parent_name[256];
|
|
VHDParentLocator parent_loc[8];
|
|
uint8_t reserved2[256];
|
|
} VHDDynamicHeader;
|
|
|
|
typedef struct {
|
|
uint8_t jump[3];
|
|
uint8_t signature[8];
|
|
uint16_t bytes_per_sector;
|
|
uint8_t sectors_per_cluster;
|
|
uint16_t reserved_sectors;
|
|
uint8_t always_zero1[3];
|
|
uint16_t not_used1;
|
|
uint8_t media_descriptor;
|
|
uint16_t always_zero2;
|
|
uint16_t sectors_per_track;
|
|
uint16_t number_of_heads;
|
|
uint32_t hidden_sectors;
|
|
uint32_t not_used2;
|
|
uint32_t not_used3;
|
|
uint64_t total_sectors;
|
|
uint64_t mft_cluster_number;
|
|
uint64_t mft_mirror_cluster_number;
|
|
int8_t clusters_per_mft_record;
|
|
uint8_t not_used4[3];
|
|
int8_t clusters_per_index_record;
|
|
uint8_t not_used5[3];
|
|
uint64_t volume_serial_number;
|
|
uint32_t checksum;
|
|
} NTFSBootSector;
|
|
|
|
typedef struct {
|
|
char magic[4];
|
|
uint16_t usa_offset;
|
|
uint16_t usa_count;
|
|
uint64_t lsn;
|
|
uint16_t sequence_number;
|
|
uint16_t link_count;
|
|
uint16_t attrs_offset;
|
|
uint16_t flags;
|
|
uint32_t bytes_used;
|
|
uint32_t bytes_allocated;
|
|
uint64_t base_ref;
|
|
uint16_t next_attr_id;
|
|
uint16_t record_number;
|
|
uint16_t usa_value;
|
|
} MFTRecordHeader;
|
|
|
|
typedef struct {
|
|
uint32_t type;
|
|
uint32_t length;
|
|
uint8_t non_resident;
|
|
uint8_t name_length;
|
|
uint16_t name_offset;
|
|
uint16_t flags;
|
|
uint16_t attribute_id;
|
|
union {
|
|
struct {
|
|
uint32_t value_length;
|
|
uint16_t value_offset;
|
|
uint16_t flags;
|
|
} resident;
|
|
struct {
|
|
uint64_t lowest_vcn;
|
|
uint64_t highest_vcn;
|
|
uint16_t mapping_pairs_offset;
|
|
uint16_t compression_unit;
|
|
uint32_t padding;
|
|
uint64_t allocated_size;
|
|
uint64_t data_size;
|
|
uint64_t initialized_size;
|
|
uint64_t compressed_size;
|
|
} non_resident;
|
|
} data;
|
|
} AttributeHeader;
|
|
|
|
typedef struct {
|
|
uint64_t parent_directory;
|
|
uint64_t creation_time;
|
|
uint64_t modification_time;
|
|
uint64_t mft_modification_time;
|
|
uint64_t access_time;
|
|
uint64_t allocated_size;
|
|
uint64_t real_size;
|
|
uint32_t flags;
|
|
uint32_t reparse_value;
|
|
uint8_t name_length;
|
|
uint8_t namespace;
|
|
uint16_t name[256];
|
|
} FileNameAttribute;
|
|
|
|
#pragma pack(pop)
|
|
|
|
typedef struct VHDRunSource {
|
|
void* ntfs_ctx;
|
|
DataRun runs[MAX_DATA_RUNS];
|
|
int run_count;
|
|
uint64_t file_size;
|
|
uint64_t data_start_offset;
|
|
uint32_t bytes_per_cluster;
|
|
} VHDRunSource;
|
|
|
|
typedef struct VHDContext {
|
|
FILE* fp;
|
|
VHDRunSource* run_source;
|
|
VHDFooter footer;
|
|
VHDDynamicHeader dyn_header;
|
|
uint32_t* bat;
|
|
uint32_t sector_bitmap_size;
|
|
uint8_t* sector_bitmap;
|
|
uint8_t* block_buffer;
|
|
uint32_t cached_block_idx;
|
|
bool block_cached;
|
|
struct VHDContext* parent;
|
|
uint32_t depth;
|
|
char base_dir[MAX_PATH_LENGTH];
|
|
uint64_t file_pos;
|
|
} VHDContext;
|
|
|
|
typedef struct {
|
|
char name[MAX_FILENAME_LENGTH];
|
|
uint64_t parent_ref;
|
|
bool is_directory;
|
|
bool valid;
|
|
} FileInfo;
|
|
|
|
typedef struct {
|
|
FILE* fp;
|
|
} RawNTFSContext;
|
|
|
|
#define MAX_PENDING_VHDS 16
|
|
#define MAX_PENDING_OPTS 16
|
|
|
|
typedef struct {
|
|
DataRun runs[MAX_DATA_RUNS];
|
|
int run_count;
|
|
uint64_t file_size;
|
|
int vhd_number;
|
|
} PendingVHD;
|
|
|
|
typedef struct {
|
|
DataRun runs[MAX_DATA_RUNS];
|
|
int run_count;
|
|
uint64_t file_size;
|
|
uint64_t data_offset;
|
|
char filename[MAX_FILENAME_LENGTH];
|
|
} PendingOpt;
|
|
|
|
typedef struct {
|
|
union {
|
|
VHDContext vhd;
|
|
RawNTFSContext raw;
|
|
};
|
|
bool is_vhd;
|
|
NTFSBootSector boot;
|
|
uint16_t bytes_per_sector;
|
|
uint32_t bytes_per_cluster;
|
|
uint64_t mft_offset;
|
|
uint32_t mft_record_size;
|
|
uint64_t mft_data_size;
|
|
uint64_t total_mft_records;
|
|
char base_path[MAX_PATH_LENGTH];
|
|
DirectoryCache dir_cache;
|
|
uint64_t data_start_offset;
|
|
bool silent;
|
|
bool verbose;
|
|
uint64_t total_bytes;
|
|
uint64_t extracted_bytes;
|
|
uint64_t files_extracted;
|
|
void* progress;
|
|
uint64_t raw_file_pos;
|
|
DecryptStream* stream;
|
|
PendingVHD pending_vhds[MAX_PENDING_VHDS];
|
|
int pending_vhd_count;
|
|
PendingOpt pending_opts[MAX_PENDING_OPTS];
|
|
int pending_opt_count;
|
|
uint8_t* lookup_buffer;
|
|
bool apm3_decrypt;
|
|
uint8_t apm3_key[16];
|
|
uint8_t apm3_iv[16];
|
|
uint8_t* file_buffer;
|
|
char last_dir[MAX_PATH_LENGTH];
|
|
void* deferred_dirs;
|
|
uint32_t deferred_count;
|
|
uint32_t deferred_capacity;
|
|
} NTFSContext;
|
|
|
|
bool ntfs_init(NTFSContext* ctx, const char* vhd_path, const char* extract_path);
|
|
bool ntfs_init_stream(NTFSContext* ctx, DecryptStream* stream, const char* extract_path);
|
|
int ntfs_detect_vhd_type(NTFSContext* ctx);
|
|
bool ntfs_extract_all(NTFSContext* ctx);
|
|
bool ntfs_extract_pending_vhds(NTFSContext* ctx, bool silent, bool verbose, bool* is_orphan);
|
|
int ntfs_get_pending_opt_count(NTFSContext* ctx);
|
|
const PendingOpt* ntfs_get_pending_opt(NTFSContext* ctx, int index);
|
|
void ntfs_close(NTFSContext* ctx);
|
|
|
|
#endif |