V2 API Reference
The V2 API is the recommended surface for FEX.Core.dll. Every function
returns an int32 result code, every string crosses the boundary as UTF-8,
and every variable-sized output is a DLL-allocated buffer the caller frees
with FreeAllocatedBuffer.
This page documents one function at a time with the Pascal signature, the
canonical C# [DllImport], parameters, return codes, and a worked example.
For the underlying types, see types-and-constants.md.
For result-code diagnostics, see error-codes.md. For buffer
ownership rules, see memory-management.md. For the
column-windowed extraction surface used on huge datasets, see
v3-api.md.
- Concepts at a glance
- Lifecycle
- Image metadata
- File records
- File data
- File properties
- Buffer cleanup
- Handle-based streaming
Concepts at a glance
| Topic | Detail |
|---|---|
| Calling convention | cdecl |
| String encoding | UTF-8, both directions |
| Result type | int32 — 0 = RESULT_OK, negative = error, positive = function-specific (e.g. OpenImage returns image ID) |
| V2 buffer pattern | DLL allocates; caller frees with FreeAllocatedBuffer(IntPtr) |
| Thread safety | Full — concurrent calls against the same ImageID are safe |
| Library load | FEX.Core.dll (Windows), libFEX.Core.so (Linux), libFEX.Core.dylib (macOS) |
The C# bindings shown below are the canonical pattern used by the FexViewer
example. They use [DllImport("FEX.Core.dll", CallingConvention = CallingConvention.Cdecl)]
on every entry point and [MarshalAs(UnmanagedType.LPStr)] for UTF-8 string
inputs.
Lifecycle
InitLibrary
Verifies the license key and unlocks the rest of the API. Must be called exactly once per process before any other export.
Pascal signature:
function InitLibrary(licenseKey: PAnsiChar): int32; cdecl;
C# binding:
[DllImport("FEX.Core.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int InitLibrary([MarshalAs(UnmanagedType.LPStr)] string? licenseKey);
Parameters:
| Name | Type | Dir | Purpose |
|---|---|---|---|
licenseKey |
UTF-8 string | in | GetData license key (FEX2-…). Pass null to read from the FEX_LICENSE_KEY environment variable. |
Returns: RESULT_OK (0) on success, RESULT_INVALIDKEY (-20) if rejected.
Example:
string? key = Environment.GetEnvironmentVariable("FEX_LICENSE_KEY");
int rc = NativeMethods.InitLibrary(key);
if (rc != NativeMethods.RESULT_OK)
{
Console.Error.WriteLine($"License initialization failed (code {rc}).");
Environment.Exit(2);
}
Pass the license key issued by GetData (the FEX2-… string). Contact
sales@getdata.com for evaluation keys; see
License Keys for installation guidance.
OpenImage
Opens a forensic image and returns an image-session ID for use in subsequent calls.
Pascal signature:
function OpenImage(filename: PAnsiChar; optionsString: PAnsiChar;
callback: TCallbackFunction; userData: Pointer): int32; cdecl;
C# binding:
[DllImport("FEX.Core.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int OpenImage(
[MarshalAs(UnmanagedType.LPStr)] string filename,
[MarshalAs(UnmanagedType.LPStr)] string? optionsString,
IntPtr callback,
IntPtr userData);
Parameters:
| Name | Type | Dir | Purpose |
|---|---|---|---|
filename |
UTF-8 string | in | Absolute path to the first image segment (.E01, .001, .dd, etc.). Multi-segment images are auto-detected from this path. |
optionsString |
UTF-8 JSON or null | in | JSON options object — currently used to pass passwords. Pass null for unencrypted images. |
callback |
function pointer | in | Optional progress callback (TCallbackFunction). Pass IntPtr.Zero to disable. |
userData |
pointer | in | Opaque value forwarded to the callback. Pass IntPtr.Zero if unused. |
Returns: Positive integer image-session ID on success. Negative on failure — most commonly:
| Code | Meaning |
|---|---|
RESULT_NOFILEFOUND (-3) |
File doesn't exist |
RESULT_IMAGENOTSUPPORTED (-4) |
Format not recognised |
RESULT_COULDNOTOPENIMAGE (-6) |
Generic open failure (corrupt / locked) |
RESULT_PASSWORD_REQUIRED (-31) |
Encrypted image, password not supplied |
RESULT_PASSWORD_INCORRECT (-32) |
Password supplied but wrong |
optionsString JSON shape:
{
"Password": "MyVolumePassword"
}
For BitLocker recovery-key files, pass the path to the .bek file in
Password — the DLL detects key-file format. Multiple credentials can be
tried by closing and re-opening; the FexViewer manifest format wraps this
loop and is documented in sdk/examples/csharp/README.md.
Example:
int imageId = NativeMethods.OpenImage(
@"C:\evidence\disk.E01",
optionsString: null,
callback: IntPtr.Zero,
userData: IntPtr.Zero);
if (imageId < 0)
throw new FexCoreException($"OpenImage failed", imageId);
try
{
// ... use imageId for queries ...
}
finally
{
NativeMethods.CloseImage(imageId);
}
When OpenImage returns RESULT_PASSWORD_REQUIRED or
RESULT_PASSWORD_INCORRECT, no session is allocated — do not call
CloseImage. Retry with optionsString set instead.
CloseImage
Releases the resources associated with an image-session ID. Safe to call while reads are still in flight on other threads — destruction is deferred until the last reader returns.
Pascal signature:
function CloseImage(ImageID: int32): int32; cdecl;
C# binding:
[DllImport("FEX.Core.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int CloseImage(int imageId);
Parameters:
| Name | Type | Dir | Purpose |
|---|---|---|---|
imageId |
int32 |
in | ID returned by OpenImage. |
Returns: RESULT_OK on success, RESULT_IMAGEIDNOTFOUND (-5) if the ID
is unknown.
Example:
int rc = NativeMethods.CloseImage(imageId);
if (rc != NativeMethods.RESULT_OK)
Console.Error.WriteLine($"CloseImage warned: {rc}");
A close failure is informational — the session is gone either way.
CloseAllImages
Closes every open image session in the current process. Useful at shutdown or on a process-wide reset.
Pascal signature:
function CloseAllImages: int32; cdecl;
C# binding:
[DllImport("FEX.Core.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int CloseAllImages();
Returns: RESULT_OK.
ReadFileSystem
Parses the filesystem of an open image and reports the discovered file
count. Must be called once before GetFileSystemRecords_V2,
GetFileSystemRecordsCustom_V2, GetFileSystemRecordsCustom_V3, or any
indexed read like ReadFileData.
Pascal signature:
function ReadFileSystem(ImageID: int32; out FileCount: uint32): int32; cdecl;
C# binding:
[DllImport("FEX.Core.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int ReadFileSystem(int imageId, out uint fileCount);
Parameters:
| Name | Type | Dir | Purpose |
|---|---|---|---|
imageId |
int32 |
in | Image-session ID. |
fileCount |
uint32 |
out | Total number of filesystem records discovered. |
Returns: RESULT_OK, RESULT_IMAGEIDNOTFOUND, RESULT_NOFILESYSTEM,
RESULT_UNSUPPORTED_FILESYSTEM, RESULT_CORRUPTED_FILESYSTEM.
Example:
int rc = NativeMethods.ReadFileSystem(imageId, out uint count);
if (rc != NativeMethods.RESULT_OK)
throw new FexCoreException("ReadFileSystem", rc);
Console.WriteLine($"Discovered {count} filesystem records.");
Image metadata
GetVersionAsJSON
Returns DLL version information as a UTF-8 JSON document.
Pascal signature:
function GetVersionAsJSON(out Buffer: PByte; out BufferSize: uint32): int32; cdecl;
C# binding:
[DllImport("FEX.Core.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int GetVersionAsJSON(out IntPtr buffer, out uint bufferSize);
Parameters:
| Name | Type | Dir | Purpose |
|---|---|---|---|
buffer |
IntPtr |
out | DLL-allocated UTF-8 string. Caller must free with FreeAllocatedBuffer. |
bufferSize |
uint32 |
out | Byte count including the null terminator. |
Returns: RESULT_OK, RESULT_ERROR, RESULT_BUFFER_OVERFLOW.
JSON output:
{
"App Author": "GetData Forensics",
"App Name": "FEXCore",
"OEM App Name": "",
"Major": 1,
"Minor": 4,
"ReleaseNo": 0,
"BuildNo": 1234,
"Flags": 0,
"OEMFlags": 0
}
The version JSON uses descriptive labels rather than the camelCase keys seen elsewhere in the SDK; this output is informational and intended for display rather than programmatic parsing.
Example:
IntPtr buffer = IntPtr.Zero;
try
{
int rc = NativeMethods.GetVersionAsJSON(out buffer, out uint size);
if (rc != NativeMethods.RESULT_OK)
throw new FexCoreException("GetVersionAsJSON", rc);
string json = Marshal.PtrToStringUTF8(buffer, (int)size)?.TrimEnd('\0') ?? "";
Console.WriteLine(json);
}
finally
{
if (buffer != IntPtr.Zero) NativeMethods.FreeAllocatedBuffer(buffer);
}
GetLicenseInfoAsJSON
Returns the active licence details — including the holder name, company, and
email embedded in newer keys — as a UTF-8 JSON document. Only valid after a
successful InitLibrary; before that it returns RESULT_INVALIDKEY.
Pascal signature:
function GetLicenseInfoAsJSON(out Buffer: PByte; out BufferSize: uint32): int32; cdecl;
C# binding:
[DllImport("FEX.Core.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int GetLicenseInfoAsJSON(out IntPtr buffer, out uint bufferSize);
Parameters:
| Name | Type | Dir | Purpose |
|---|---|---|---|
buffer |
IntPtr |
out | DLL-allocated UTF-8 string. Caller must free with FreeAllocatedBuffer. |
bufferSize |
uint32 |
out | Byte count including the null terminator. |
Returns: RESULT_OK, RESULT_INVALIDKEY (library not initialized), RESULT_ERROR.
JSON output:
{
"version": 3,
"cid": 110,
"name": "Jane Examiner",
"company": "Example Forensics Ltd",
"email": "jane@example.com",
"features": "0xFFFFFFFFFFFFFFFF",
"issued": "2026-06-04",
"expires": "2026-12-31",
"daysRemaining": 210
}
Keys issued before holder embedding return empty name, company, and
email strings (with "version": 2). features is a hex string to avoid
64-bit precision loss in JSON consumers; dates are yyyy-mm-dd.
Example:
IntPtr buffer = IntPtr.Zero;
try
{
int rc = NativeMethods.GetLicenseInfoAsJSON(out buffer, out uint size);
if (rc != NativeMethods.RESULT_OK)
throw new FexCoreException("GetLicenseInfoAsJSON", rc);
string json = Marshal.PtrToStringUTF8(buffer, (int)size)?.TrimEnd('\0') ?? "";
Console.WriteLine(json);
}
finally
{
if (buffer != IntPtr.Zero) NativeMethods.FreeAllocatedBuffer(buffer);
}
See License keys for the end-to-end licensing guide.
GetImageTypeByFilename
Returns the integer image-type code for a file based on extension and header sniffing. Cheap — does not open the image.
Pascal signature:
function GetImageTypeByFilename(filename: PAnsiChar; out ImageType: int32): int32; cdecl;
C# binding:
[DllImport("FEX.Core.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int GetImageTypeByFilename(
[MarshalAs(UnmanagedType.LPStr)] string filename,
out int imageType);
Parameters:
| Name | Type | Dir | Purpose |
|---|---|---|---|
filename |
UTF-8 string | in | Absolute path. |
imageType |
int32 |
out | Numeric type code. Pass to GetImageTypeAsString for the human-readable name. |
Returns: RESULT_OK on detection, RESULT_NOFILEFOUND,
RESULT_IMAGENOTSUPPORTED.
Example:
int rc = NativeMethods.GetImageTypeByFilename(@"C:\evidence\disk.E01", out int code);
if (rc == NativeMethods.RESULT_OK)
Console.WriteLine($"Type code: {code}");
GetImageTypeAsString
Translates an image-type code (from GetImageTypeByFilename) to a
human-readable name like "E01" or "DMG".
Pascal signature:
function GetImageTypeAsString(anImageType: int32; out Buffer: PByte;
out BufferSize: uint32): int32; cdecl;
C# binding:
[DllImport("FEX.Core.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int GetImageTypeAsString(
int imageType,
out IntPtr buffer,
out uint bufferSize);
Parameters:
| Name | Type | Dir | Purpose |
|---|---|---|---|
imageType |
int32 |
in | Code from GetImageTypeByFilename. |
buffer |
IntPtr |
out | DLL-allocated UTF-8 string. Free with FreeAllocatedBuffer. |
bufferSize |
uint32 |
out | Bytes including null. |
Returns: RESULT_OK, RESULT_ERROR, RESULT_BUFFER_OVERFLOW.
CheckImageTypeLogical
Tests whether a given image-type code represents a logical image (file-list container like L01 / Lx01 / AD1) versus a physical disk image (E01 / DD).
Pascal signature:
function CheckImageTypeLogical(anImageType: int32; out IsLogical: int32): int32; cdecl;
C# binding:
[DllImport("FEX.Core.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int CheckImageTypeLogical(int imageType, out int isLogical);
Parameters:
| Name | Type | Dir | Purpose |
|---|---|---|---|
imageType |
int32 |
in | Code from GetImageTypeByFilename. |
isLogical |
int32 |
out | 1 if logical, 0 if physical. |
Returns: RESULT_OK, RESULT_IMAGENOTSUPPORTED.
GetImageInfoByFilenameAsJSON
Returns image metadata as JSON without keeping the image open. Useful for fast inventory passes.
Pascal signature:
function GetImageInfoByFilenameAsJSON(filename: PUTF8Char;
out Buffer: PByte;
out BufferSize: uint32): int32; cdecl;
C# binding:
[DllImport("FEX.Core.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern int GetImageInfoByFilenameAsJSON(
[MarshalAs(UnmanagedType.LPStr)] string filename,
out IntPtr buffer,
out uint bufferSize);
Parameters:
| Name | Type | Dir | Purpose |
|---|---|---|---|
filename |
UTF-8 string | in | Absolute image path. |
buffer |
IntPtr |
out | DLL-allocated UTF-8 JSON. Free with FreeAllocatedBuffer. |
bufferSize |
uint32 |
out | Byte count incl. null. |
Returns: RESULT_OK, RESULT_NOFILEFOUND, RESULT_COULDNOTOPENIMAGE,
RESULT_INVALID_UTF8, RESULT_PATH_TRAVERSAL, RESULT_BUFFER_OVERFLOW,
RESULT_PASSWORD_REQUIRED, RESULT_PASSWORD_INCORRECT. The encryption
codes mean the format-recognition succeeded but the metadata block requires
a password — use OpenImage with credentials and switch to
GetImageInfoByIdAsJSON for those.
JSON shape (camelCase per current convention):
{
"deviceName": "Samsung SSD 860 EVO 250GB",
"deviceDescription": "Internal HDD #2",
"deviceSize": 250059350016,
"imageType": "E01",
"segmentCount": 12,
"isLogical": false,
"filename": "disk.E01",
"md5": "5d41402abc4b2a76b9719d911017c592",
"sha1": "aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d",
"encaseInformation": {
"caseName": "OPS-2026-001",
"evidenceNumber": "2",
"examiner": "L. Investigator"
}
}
Format-specific blocks like encaseInformation are present when the format
carries acquisition metadata; absent otherwise.
Example:
IntPtr buf = IntPtr.Zero;
try
{
int rc = NativeMethods.GetImageInfoByFilenameAsJSON(
@"C:\evidence\disk.E01", out buf, out uint size);
if (rc != NativeMethods.RESULT_OK)
throw new FexCoreException("GetImageInfoByFilenameAsJSON", rc);
string json = Marshal.PtrToStringUTF8(buf, (int)size)?.TrimEnd('\0') ?? "";
var meta = JsonSerializer.Deserialize<ImageMetadata>(json);
Console.WriteLine($"Device: {meta?.DeviceName}, size: {meta?.DeviceSize:N0} bytes");
}
finally
{
if (buf != IntPtr.Zero) NativeMethods.FreeAllocatedBuffer(buf);
}
GetImageInfoByIdAsJSON
Returns metadata for an already-opened image session. Equivalent JSON shape
to GetImageInfoByFilenameAsJSON, plus runtime-only fields populated after
parsing (e.g. confirmed filesystem type).
Pascal signature:
function GetImageInfoByIdAsJSON(ImageID: int32;
out Buffer: PByte;
out BufferSize: uint32): int32; cdecl;
C# binding:
[DllImport("FEX.Core.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern int GetImageInfoByIdAsJSON(int imageId, out IntPtr buffer, out uint bufferSize);
Parameters:
| Name | Type | Dir | Purpose |
|---|---|---|---|
imageId |
int32 |
in | Image-session ID. |
buffer |
IntPtr |
out | DLL-allocated UTF-8 JSON. Free with FreeAllocatedBuffer. |
bufferSize |
uint32 |
out | Bytes incl. null. |
Returns: RESULT_OK, RESULT_IMAGEIDNOTFOUND, RESULT_IMAGENODATA,
RESULT_BUFFER_OVERFLOW.
Use this in preference to GetImageInfoByFilenameAsJSON whenever you've
already opened the image — it skips re-parsing the headers.
GetPartitionInfoAsJSON
Returns a JSON array describing every partition in the image (location, size, partition-table style, filesystem type, VBR fingerprint).
Pascal signature:
function GetPartitionInfoAsJSON(ImageID: int32;
out Buffer: PByte;
out BufferSize: uint32): int32; cdecl;
C# binding:
[DllImport("FEX.Core.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int GetPartitionInfoAsJSON(int imageId, out IntPtr buffer, out uint bufferSize);
Parameters:
| Name | Type | Dir | Purpose |
|---|---|---|---|
imageId |
int32 |
in | Image-session ID. |
buffer |
IntPtr |
out | DLL-allocated UTF-8 JSON array. Free with FreeAllocatedBuffer. |
bufferSize |
uint32 |
out | Bytes incl. null. |
Returns: RESULT_OK, RESULT_IMAGEIDNOTFOUND, RESULT_IMAGENODATA,
RESULT_BUFFER_OVERFLOW.
GetImageSize
Returns the logical size of an opened image in bytes — i.e. the size of the acquired device, not the on-disk size of the segment files.
Pascal signature:
function GetImageSize(ImageID: int32; out Size: int64): int32; cdecl;
C# binding:
[DllImport("FEX.Core.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int GetImageSize(int imageId, out long size);
Returns: RESULT_OK, RESULT_IMAGEIDNOTFOUND.
File records
GetFileSystemRecords_V2
Returns every filesystem record in the image as a flat array of
TFileRecord structs. The single allocation owns all contained pointers
(filenames, children lists). Free with one call to FreeAllocatedBuffer.
Pascal signature:
function GetFileSystemRecords_V2(ImageID: int32;
out FileCount: uint32;
out Records: PFileRecord;
out RecordArraySize: uint32): int32; cdecl;
C# binding:
[DllImport("FEX.Core.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int GetFileSystemRecords_V2(
int imageId,
out uint fileCount,
out IntPtr records,
out uint recordArraySize);
Parameters:
| Name | Type | Dir | Purpose |
|---|---|---|---|
imageId |
int32 |
in | Image-session ID. Must already have had ReadFileSystem called. |
fileCount |
uint32 |
out | Number of records in the array. |
records |
IntPtr |
out | DLL-allocated array of TFileRecord. Free with FreeAllocatedBuffer. |
recordArraySize |
uint32 |
out | Total byte size of the array allocation. |
Returns: RESULT_OK, RESULT_IMAGEIDNOTFOUND, RESULT_OUT_OF_MEMORY,
RESULT_BUFFER_OVERFLOW (datasets so large that count × sizeof overflows
uint32 — switch to V3 in that case).
Example:
NativeMethods.ReadFileSystem(imageId, out _);
IntPtr records = IntPtr.Zero;
try
{
int rc = NativeMethods.GetFileSystemRecords_V2(
imageId, out uint count, out records, out _);
if (rc != NativeMethods.RESULT_OK)
throw new FexCoreException("GetFileSystemRecords_V2", rc);
int stride = Marshal.SizeOf<FileRecordNative>();
IntPtr cur = records;
for (int i = 0; i < count; i++)
{
var native = Marshal.PtrToStructure<FileRecordNative>(cur);
string name = native.filename != IntPtr.Zero
? Marshal.PtrToStringUTF8(native.filename) ?? ""
: "";
bool isFolder = (native.status & StatusFlags.FILESTATUS_FOLDER) != 0;
bool isDeleted = (native.status & StatusFlags.FILESTATUS_DELETED) != 0;
Console.WriteLine($"{native.fileBatesId,8} {(isFolder ? "D" : "F")}{(isDeleted ? "x" : " ")} {native.logicalSize,12:N0} {name}");
cur = IntPtr.Add(cur, stride);
}
}
finally
{
if (records != IntPtr.Zero) NativeMethods.FreeAllocatedBuffer(records);
}
FileRecordNative and StatusFlags are defined in
types-and-constants.md. Resolve every filename
to a managed string before you call FreeAllocatedBuffer — the
pointers are dangling after the free.
GetFilePath
Returns the full hierarchical path of a single record by walking parent pointers from the root.
Pascal signature:
function GetFilePath(ImageID: int32; FileIndex: int32;
out Buffer: PByte; out BufferSize: uint32): int32; cdecl;
C# binding:
[DllImport("FEX.Core.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int GetFilePath(
int imageId, int fileIndex, out IntPtr buffer, out uint bufferSize);
Parameters:
| Name | Type | Dir | Purpose |
|---|---|---|---|
imageId |
int32 |
in | Image-session ID. |
fileIndex |
int32 |
in | Index into the record array (matches parentIndex semantics). |
buffer |
IntPtr |
out | DLL-allocated UTF-8 path string. Free with FreeAllocatedBuffer. |
bufferSize |
uint32 |
out | Bytes incl. null. |
Returns: RESULT_OK, RESULT_IMAGEIDNOTFOUND, RESULT_FILEINDEXNOTFOUND,
RESULT_BUFFER_OVERFLOW.
For most use cases it's faster to reconstruct paths in C# from the flat
record array rather than calling GetFilePath per record. See the
PathBuilder class in sdk/examples/csharp/Models/ for the pattern.
GetItemInfo
Returns metadata for a single record as JSON, with selectable detail level.
Pascal signature:
function GetItemInfo(ImageID: int32; FileIndex: int32; InfoType: int32;
out Buffer: PByte; out BufferSize: uint32): int32; cdecl;
C# binding:
[DllImport("FEX.Core.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int GetItemInfo(
int imageId, int fileIndex, int infoType,
out IntPtr buffer, out uint bufferSize);
Parameters:
| Name | Type | Dir | Purpose |
|---|---|---|---|
imageId |
int32 |
in | Image-session ID. |
fileIndex |
int32 |
in | Index into the record array. |
infoType |
int32 |
in | 0 = full (dates + hashes), 1 = basic (dates only), 2 = minimal (id / size / status). |
buffer |
IntPtr |
out | DLL-allocated UTF-8 JSON. Free with FreeAllocatedBuffer. |
bufferSize |
uint32 |
out | Bytes incl. null. |
Returns: RESULT_OK, RESULT_IMAGEIDNOTFOUND, RESULT_FILEINDEXNOTFOUND,
RESULT_NOFILESYSTEM, RESULT_BUFFER_OVERFLOW.
File data
GetFileSize
Returns the size of a single file in the filesystem. Note: this returns the
physical size (cluster-rounded). For logical size use the logicalSize
field on the record.
Pascal signature:
function GetFileSize(ImageID: int32; FileIndex: int32; out Size: uint64): int32; cdecl;
C# binding:
[DllImport("FEX.Core.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int GetFileSize(int imageId, int fileIndex, out ulong fileSize);
Returns: RESULT_OK, RESULT_IMAGEIDNOTFOUND, RESULT_FILEINDEXNOTFOUND,
RESULT_FILENOSIZE.
When extracting files, always truncate writes to the logicalSize from the
record; otherwise you will write cluster-slack bytes past the end of the
real content.
ReadFileData
Reads a range of bytes from a single filesystem entry into a caller-allocated
buffer. This is a caller-allocated function (Pattern 3 in
memory-management.md) — there's no
FreeAllocatedBuffer here.
Pascal signature:
function ReadFileData(ImageID: int32; FileIndex: int32; Offset: int64;
Buffer: Pointer; BufferSize: int32;
out BytesRead: int32): int32; cdecl;
C# binding:
[DllImport("FEX.Core.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int ReadFileData(
int imageId, int fileIndex, long offset,
IntPtr buffer, int bufferSize, out int bytesRead);
Parameters:
| Name | Type | Dir | Purpose |
|---|---|---|---|
imageId |
int32 |
in | Image-session ID. |
fileIndex |
int32 |
in | Record index. |
offset |
int64 |
in | Byte offset within the file. |
buffer |
IntPtr |
in/out | Caller-allocated unmanaged buffer. |
bufferSize |
int32 |
in | Capacity of buffer in bytes. |
bytesRead |
int32 |
out | Bytes actually read (may be less than bufferSize near EOF). |
Returns: RESULT_OK plus partial read possible, RESULT_INCOMPLETEREAD
near EOF, RESULT_FILEINDEXNOTFOUND, RESULT_FILENOSIZE,
RESULT_ENCRYPTED_DATA.
Example (1 MB chunked extraction):
const int CHUNK = 1024 * 1024;
IntPtr scratch = Marshal.AllocHGlobal(CHUNK);
try
{
long offset = 0;
while (offset < logicalSize)
{
int want = (int)Math.Min(CHUNK, logicalSize - offset);
int rc = NativeMethods.ReadFileData(
imageId, fileIndex, offset, scratch, want, out int got);
if (rc != NativeMethods.RESULT_OK || got <= 0) break;
var slice = new byte[got];
Marshal.Copy(scratch, slice, 0, got);
outputStream.Write(slice, 0, got);
offset += got;
}
}
finally
{
Marshal.FreeHGlobal(scratch);
}
ReadImageData
Reads raw bytes from anywhere in the underlying image (not a single file). Useful for low-level analysis — partition tables, filesystem boot sectors, unallocated space.
Pascal signature:
function ReadImageData(ImageID: int32; Offset: int64;
Buffer: Pointer; BufferSize: int32;
out BytesRead: int32): int32; cdecl;
C# binding:
[DllImport("FEX.Core.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int ReadImageData(
int imageId, long offset,
IntPtr buffer, int bufferSize,
out int bytesRead);
Parameters:
| Name | Type | Dir | Purpose |
|---|---|---|---|
imageId |
int32 |
in | Image-session ID. |
offset |
int64 |
in | Byte offset within the image. |
buffer |
IntPtr |
in/out | Caller-allocated buffer. |
bufferSize |
int32 |
in | Capacity. |
bytesRead |
int32 |
out | Actual bytes read. |
Returns: RESULT_OK, RESULT_INCOMPLETEREAD, RESULT_IMAGEIDNOTFOUND,
RESULT_ENCRYPTED_DATA.
File properties
The properties API exposes the rich format-specific metadata that file-type drivers extract — JPEG EXIF tags, PDF metadata, ZIP entry lists, etc.
GetAvailableProperties
Returns the set of properties available for each filesystem record. Use this to discover what column names are valid for V3 custom extraction.
Pascal signature:
function GetAvailableProperties(out Buffer: PByte; out BufferSize: uint32): int32; cdecl;
C# binding:
[DllImport("FEX.Core.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int GetAvailableProperties(out IntPtr buffer, out uint bufferSize);
Parameters:
| Name | Type | Dir | Purpose |
|---|---|---|---|
buffer |
IntPtr |
out | DLL-allocated UTF-8 JSON array. Free with FreeAllocatedBuffer. |
bufferSize |
uint32 |
out | Bytes incl. null. |
Returns: RESULT_OK, RESULT_BUFFER_OVERFLOW.
JSON shape:
[
{"name": "EntryName", "type": "String", "typeKind": "tkUString"},
{"name": "LogicalSize", "type": "Int64", "typeKind": "tkInt64"},
{"name": "Modified", "type": "DateTime", "typeKind": "tkFloat"},
...
]
GetFilePropertiesFromPathAsJSON
Inspects a file on the host filesystem (not inside an image) using the DLL's file-type drivers. Returns the property tree as JSON.
Pascal signature:
function GetFilePropertiesFromPathAsJSON(Filename: PUTF8Char;
out Buffer: PByte;
out BufferSize: uint32): int32; cdecl;
C# binding:
[DllImport("FEX.Core.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern int GetFilePropertiesFromPathAsJSON(
[MarshalAs(UnmanagedType.LPStr)] string filename,
out IntPtr buffer, out uint bufferSize);
Returns: RESULT_OK, RESULT_INVALID_UTF8, RESULT_PATH_TRAVERSAL,
RESULT_NOFILEFOUND, RESULT_IMAGENOTSUPPORTED (no driver matched the
extension), RESULT_BUFFER_OVERFLOW.
GetFilePropertiesAsJSON
Same as the path variant, but for a file inside an opened image session.
Pascal signature:
function GetFilePropertiesAsJSON(ImageID: int32; FileIndex: int32;
out Buffer: PByte;
out BufferSize: uint32): int32; cdecl;
C# binding:
[DllImport("FEX.Core.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int GetFilePropertiesAsJSON(
int imageId, int fileIndex,
out IntPtr buffer, out uint bufferSize);
Returns: RESULT_OK, RESULT_IMAGEIDNOTFOUND, RESULT_FILEINDEXNOTFOUND,
RESULT_NOFILESYSTEM, RESULT_IMAGENOTSUPPORTED,
RESULT_COULDNOTOPENIMAGE, RESULT_BUFFER_OVERFLOW.
Buffer cleanup
FreeAllocatedBuffer
Releases any V2 buffer the DLL allocated for the caller. Safe to call with
IntPtr.Zero — it returns RESULT_OK without doing anything.
Pascal signature:
function FreeAllocatedBuffer(Buffer: PByte): int32; cdecl;
C# binding:
[DllImport("FEX.Core.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int FreeAllocatedBuffer(IntPtr buffer);
Returns: RESULT_OK, RESULT_ERROR (only if the underlying free
itself raised an exception).
Pair this with every V2 export that has an out IntPtr Buffer parameter.
For V3 spec arrays use FreePropertySpecArray instead — see
v3-api.md.
Handle-based streaming
A separate streaming surface exists for callers that want to read very large files without per-call setup overhead:
RequestFileStream(imageId, fileIndex, out streamHandle)ReadFileStream(streamHandle, offset, buffer, bufferSize, out bytesRead)ReleaseFileStream(streamHandle)
This is functionally equivalent to ReadFileData but caches the underlying
stream object across reads. Most callers should start with ReadFileData
and only adopt the handle-based variant if profiling shows per-call
overhead is a bottleneck. Documentation for these will be expanded in a
future release.