Introduction | The X-Ways Forensics Image I/O API is a programming interface that allows you to extend the array of disk image file formats supported by the computer software products X-Ways Forensics, X-Ways Investigator and WinHex Lab Edition. This API is available in v19.5 and later. It is meant for physical sector-wise images of storage devices, i.e. not logical collections of individual files (to support those kinds of images, you could use the X-Tensions API instead). You just need to compile a DLL and export three specific functions to add support for another image file format. The DLL has to match the filename mask “Image*.dll” (it is suggested to name it „ImageIO XYZ.dll”, where XYZ is the typical filename extension of the images that you support), and it has to be placed directly into the installation directory of X-Ways Forensics (in the \x64 subdirectory if it's a 64-bit DLL). If a user adds such a DLL from a trusted source to the installation directory, that signifies consent to get it executed by X-Ways Forensics. One DLL can implement support for one or multiple image types. Up to two such DLLs in the installation directory are currently supported. Once loaded, the DLL remains in memory until the X-Ways Forensics session ends. The DLL is loaded with the so-called alternate search order / altered search path strategy as described here and here. In essence it means that if your DLL statically links further dependent DLLs, those will be found if they are contained in the same directory as the main DLL. FYI, all exported functions have to use stdcall calling conventions under 32 bit. You have to export all functions with undecorated names, or else they will not be found by X-Ways Forensics! This concept is described for example here and here. In Microsoft Visual Studio that might mean that you should not declare your functions with __declspec(dllexport), but extern "C" __declspec(dllexport) instead. To check the actual exported function names, you can view your own DLL in X-Ways Forensics with the viewer component. Demo DLLs (32-bit and 64-bit, with Delphi source code) Documentation last updated on Oct 17, 2017. Related API: X-Ways Forensics X-Tensions API |
Preparation |
|
---|---|
PVOID
IIO_Init( HANDLE hMainWnd, LPWSTR lpFilePath, PVOID pHeaderBuf, DWORD nHeaderBufSize, struct ImageInfo* pImgInfo, PVOID pReserved ); #pragma pack(2) struct ImageInfo { DWORD nSize, INT64 nSectorCount, DWORD nSectorSize, DWORD nFlags, LPWSTR lpTextualDescr }; |
Will be called when X-Ways Forensics is about to interpret a presumed image file. You are given a pointer to a null-terminated file path in UTF-16 Unicode (lpFilePath) and a pointer to a buffer (lpFilePath) with the first few (nHeaderBufSize) bytes of the file contents. You can deduct directly from the filename or filename extension and/or those few bytes or indirectly (by reading more from the file contents or looking for other files in the same directory) whether your DLL supports this kind of image. If so, you return a pointer to a private structure of yours, by which you identify that image in future function calls, plus you have to fill the structure pointed to by pImgInfo to give the caller some information about the image so that it can be treated correctly. If you do not support the specified file type, you simply return NULL. In that case the structure pointed to by pImgInfo will be ignored, and X-Ways Forensics will try to interpret the image without your DLL being involved. If you return a non-NULL pointer, but the caller is not happy with how you filled the ImageInfo structure (for example, unsupported value of nSize returned or flag IIO_INIT_READ mysteriously not set), you can still expect a quick call of your IIO_Done function so that you can at least tidy up after yourself, but you will not be actually called for any I/O work for that image. The ImageInfo structure is initially guaranteed to be zeroed except for the nSize part. If you open a file handle to the image file, you have to choose a sharing mode for that, not an exclusive mode. hMainWnd: Handle of the main application window in case you need it, for example as a parent window for a message box or dialog box that asks the user for preferences or credentials etc. nSize: The size of the ImageInfo structure. This (and only this) member variable is already set by the caller, and its value is currently 4+8+4+4+8=28 bytes in x64 (4+8+4+4+4=24 in x86), but it may be larger in future versions of X-Ways Forensics. You do not currently have to check the value (only if you are curious), but you have to overwrite it with the size that you support. Should a future version of X-Ways Forensics work with a larger structure, the original part remains the same and newly added member variables are appended, but the caller will not expect you to have filled them if the nSize that you set is still the smaller size of older versions of this API. nSectorCount: The number of sectors represented by the image. nSectorSize: Size of one sector in bytes. Currently supported sector sizes in X-Way Forensics are 512, 1024, 2048, 4096, and 8192 bytes. nFlags: A combination of the below
flags. It is OK to set neither IIO_INIT_DISK not IIO_INIT_VOLUME if you do not know what kind of image it is. In that case X-Ways Forensics will make its own determination or might prompt the user. lpTextualDescr: Optional. Either a null-terminated string that contains textual metadata about the image, such as who created it, how and when, using which tool, with which compression option, etc., or (if the flag IIO_INIT_ERROR_GIVE_UP is set) an error message for the user to see. You can allocate that buffer in memory with any compiler-specific memory allocation function or Windows API function of your choice. You will be asked to release it when your IIO_Done() function is called. nAvailSectorCount: Not part of the structure, just a hypothetical extension. Do not use. The actually available/readable number of sectors in the image counted from the first sector. Usually should be the same as nSectorCount, but could be smaller if you detect that the image is incomplete (e.g. some file segments missing) or corrupt. |
Reading/Writing |
|
INT64
IIO_Work( PVOID lpImage, INT64 nOfs, INT64 nSize, PVOID lpBuffer, PBYTE pFlags ); |
This function is called to read nSize bytes from offset nOfs in the image identified by your own pointer lpImage, i.e. the result of IIO_Init(), into the memory buffer pointed to by lpBuffer. It might also be called to write that many bytes at the specified offset, provided that you have signaled write capability in IIO_Init().
pFlags: Some flags are set by the caller, some
may be
set by the callee. Do not alter the flags except as described here. In a simple implementation, if you did not signal write
capability and do not provide sparse support, you can simply ignore this
flags field altogether. Please return the number of successfully read/written bytes. IIO_SPARSE_DETECTED should not be returned if IIO_CHECK_FOR_SPARSE was not set. If IIO_CHECK_FOR_SPARSE was set and you return IIO_CHECK_FOR_SPARSE, you don't have to fill the buffer at all, but you are still supposed to return the total number of bytes covered/requested. The caller takes the IIO_CHECK_FOR_SPARSE flag as a hint that the data in the requested range is ignorable and will save time by not processing it. |
Cleaning Up |
|
DWORD
IIO_Done( PVOID lpImage, LPWSTR lpTextualDescr ); |
When the image is closed/no further I/O is required, X-Ways Forensics calls this function to give you a chance to free up any resources (such as file handle), that you were keeping open since the Init function was called. You are given the pointer that your IIO_Init() function had returned, and you are also asked to release the buffer for the textual description if you had provided one. When done, please return 1. |