LONG
XT_Init( DWORD nVersion, DWORD nFlags, HANDLE hMainWnd, struct LicenseInfo* pLicInfo ); #pragma pack(2) struct LicenseInfo { DWORD nSize, DWORD nLicFlags, DWORD nUsers, FILETIME nExpDate, BYTE nLicID[16] }; |
Mandatory to export. Will be called before anything else happens, before the X-Tension does its actual job, among other things to inform the DLL of the version of X-Ways Forensics that is loading the DLL, already when the X-Tension is selected by the user in X-Ways Forensics. You may return -1 to prevent further use of the DLL, for example if certain functions that you require are not present (i.e. exported only by a newer version of X-Ways Forensics) or if you detect an environment in which your DLL is not meant or licensed to run. Otherwise you must return either flag 0x01 or 0x02 and more flags optionally:
0x01: Your X-Tension is ready for use, but not thread-safe. nVersion: The higher word specifies the version number. For example 2140 means v21.4. The third highest byte specified the service release number. The lowest byte specifies the current language of the user interface of the calling program. nFlags: hMainWnd: Handle of the main window in case you need it, for example as a parent window for a message box. pLicInfo: Points to a structure that contains information about the license. Provided by v18.1 and later. NULL in older releases. nSize is the size of the structure provided. nLicFlags: nUsers: Specifies how many different users may use the same license file/dongle simultaneously. For BYOD this is currently always 1. 0 means unknown. nExpDate: Indicates the date when either access to updates will end or has ended (for a perpetual license) or when the ability to use the software will end (for a non-perpetual license). nLicID: A hash value that uniquely identifies the dongle or BYOD license. You could license your X-Tension based on that ID and only allow users to run your X-Tension if the ID matches your expectations (if the ID is in your unlock list, if they have a key file for that ID etc.). Since v20.5, users can find this ID if they first click the version number in the upper right corner and then the button labeled "nLicID", in hex ASCII notation. This could be useful if the purchase of a license for your X-Tension requires that ID. Please note that the actual dongle ID or BYOD license ID cannot be derived from nLicID. |
LONG
XT_Done( PVOID lpReserved ); |
If exported (optional), will be called just before the DLL is unloaded to give you a chance to release any allocated memory, save certain usage data permanently for the next time your X-Tension is run, thank the user for choosing your product, or do other crazy stuff. You should return 0. nReserved: Currently always NULL. |
For ordinary X-Tensions |
|
---|---|
LONG
XT_About( HANDLE hParentWnd PVOID lpReserved ); |
If exported (optional), will be called when the user requests to see information about the DLL. You can display copyright notices, a version number, a brief description of the exported functionality, extensive help on how to use it, from where in X-Ways Forensics to call it with what settings etc. etc. You could even display a dialog window where the user can change settings for this X-Tension, which you store in the Windows registry or in a permanent file. You should return 0. nReserved: Currently always NULL. |
LONG
XT_Prepare( HANDLE hVolume, HANDLE hEvidence, DWORD nOpType, PVOID lpReserved ); |
If exported (optional), will be called immediately for a volume when volume snapshot refinement or some other action starts, before items or search hits in that volume are processed individually, or simply when the user runs your X-Tension from the main menu or command line or applies it to selected files directly. Your X-Tension can do its actual job when responding to a call of this function or any of the other below functions. The nOpType parameter tells you in which context exactly your X-Tension is running.
Possible negative return values: 0 is the default return value, if you just want XT_Finalize() to be called. Will also be assumed if you do not export XT_Prepare().
Positive return values are a combination of these flags:
XT_PREPARE_CALLPI: Set this flag if you
want X-Ways Forensics to call your implementation of XT_ProcessItem[Ex]() (whichever is exported) for each
item this volume snapshot (not if the volume snapshot is not targeted, e.g. in
case of XT_ACTION_RUN). hVolume: Typically a handle to the volume that the X-Tension is applied to. 0 (i.e. not a valid handle) if run from the main menu or command line with no data window open, i.e. when not applied to anything. A handle to a file if run from the main window if the active data window represents a single file opened via File | Open. To make sure that a non-zero handle is a handle to a volume, you can call XWF_GetVolumeInformation and check that lpBytesPerSector retrieves a value unequal to zero. Or, if your X-Tension is intended to be applied to a file opened that way, verify that lpBytesPerSector retrieves zero. hEvidence: From v17.5 SR-2, a handle to an evidence object if hVolume represents an evidence object, otherwise 0. nOpType: An integer value that
indicates how the X-Tension is executed within X-Ways Forensics can be found
in the lowest byte. In addition to that, flags may be set
within the same DWORD since v21.3, but only if the X-Tension's XT_Init
function has signaled that it understands this. 1 Run from the directory
browser context menu, an X-Tension is applied to selected files. This may
occur in the case root window, not for just one particular volume!
XT_ProcessItem() is not necessarily called for the selected items in the order
in which they are listed in the directory browser. nReserved: Currently always NULL. |
LONG
XT_Finalize( HANDLE hVolume, HANDLE hEvidence, DWORD nOpType, PVOID lpReserved ); |
If exported (optional), will be called when volume snapshot refinement or another operation that involves the X-Tension has completed. Return 0 or a combination of flags: 0x01 (supported in v17.6 and later) if the current directory listing in the directory browser of the active data window has to be refreshed after XT_ACTION_DBC (usually not necessary, perhaps when adding new files to the directory), 0x02 (has an effect only in v21.3 and later) if the volume snapshot of the specified volume should be saved because the X-Tension has applied changes to it (not really necessary and currently ignored when run as part of volume snapshot refinement, but still recommended for consistency). hEvidence: From v17.6, a handle to an evidence object if the hVolume represents an evidence object, otherwise 0. nOpType: Repeats the parameter already provided to XT_Prepare() in v20.8 SR-9, v20.9 SR-11, v21.0 SR-8, v21.1 SR-4 and later versions. nReserved: Currently always NULL. |
LONG
XT_ProcessItem( LONG nItemID, PVOID lpReserved ); |
If exported (optional) and if wanted by XT_Prepare(), will be called for each file in the volume snapshot that is targeted for refinement or selected and targeted with the directory browser context menu. Implement and export this function if you merely need to retrieve information about the file and don't need to read its data. There is a slight performance benefit if the user does not select other refinement operations that need to read the file's data, i.e. you save a little bit time if a file does not need to opened for reading. By calling XWF_OpenItem(), you can still open the file to read its data if needed on a case-by-case basis. Return -1 if you want X-Ways Forensics to stop the current operation (e.g. volume snapshot refinement), -2 if you want X-Ways Forensics to skip its own volume snapshot refinement operations for this file (e.g. to save time if you have determined a file to be of no interest, possible only if it is not a "late" call triggered by XT_PREPARE_CALLPILATE), otherwise 0. Since v21.4, to leave it up to the user whether files that you consider ignorable should be not further processed, you could set the ignorable flag via XWF_SetItemInformation() in an early call of this function. nReserved: Currently always NULL. |
LONG
XT_ProcessItemEx( LONG nItemID, HANDLE hItem, PVOID lpReserved ); |
If exported (optional) and if wanted by XT_Prepare(), will be called for each item (file or directory) in the volume snapshot that is targeted for refinement or selected and targeted with the directory browser context menu. A file will be opened for reading prior to the function call. Implement and export this function if you need to read the item's data, which you can do by calling the XWF_Read() function, to which you supply the hItem parameter. Return -1 if you want X-Ways Forensics to stop the current operation (e.g. volume snapshot refinement), otherwise 0. nReserved: Currently always NULL. |
LONG
XT_PrepareSearch( struct PrepareSearchInfo* pPSInfo struct CodePages* CPages ); #pragma pack(2) struct PrepareSearchInfo { DWORD nSize, LPWSTR lpSearchTerms, DWORD nBufLen, DWORD nFlags }; #pragma pack(2) |
If exported (optional), will be called by v16.9 and later if an X-Tension is loaded for use with a simultaneous search, so that the X-Tension can enter predefined search terms into the dialog window for use with the search. The X-Tension can also learn about the current search settings (the active code pages and some other settings through the flags field) and could inform the user of necessary adjustments for the search to work as intended by the X-Tension. Return 1 if you have made adjustments to the search terms, or 0 if not, or -1 if you are not happy with the current settings at all and want the X-Tension to be unselected. Adjustments to the pointer, to the buffer size, to the flags or the code pages are currently ignored. lpSearchTerms: Null-terminated. Delimited by line breaks. Points to a buffer that specifies the currently entered search terms, which you can manipulate, replace or complete within the limits of the buffer. nBufLen: Size of the buffer that lpSearchTerms points to in Unicode characters. Currently always 32768, but subject to change in future versions.
nFlags: CPages: Indicates code pages currently selected for the search. See this web page for possible code page identifiers. 0 means unused code page. |
LONG
XT_ProcessSearchHit( struct SearchHitInfo* pInfo ); #pragma pack(2) struct SearchHitInfo { DWORD nSize; LONG nItemID; INT64 nRelOfs; INT64 nAbsOfs; PVOID lpOptionalHitPtr; WORD nSearchTermID; WORD nLength; WORD nCodePage; WORD nFlags; HANDLE hOptionalItemOrVolume }; |
If exported (optional), this function will be called for each search hit when it is found (or in a future version of X-Ways Forensics perhaps later if selected by the user in a search hit list). Return 0, except if you want X-Ways Forensics to abort the search (return -1) or if you want X-Ways Forensics to stop calling you (return -2). This function is not called if the search was initiated by the X-Tension itself (via XWF_Search). nSize: Size of the record. The record is packed. In future versions of the API the record may be larger if more fields are provided. But even then you can still address the record components as you know them. nRelOfs: Relative offset of the search hit within its respective file, if applicable, otherwise -1. You may change the offset if that helps to improve the quality of the search hit. nAbsOfs: Absolute offset of the search hit from the point of the volume, if available, otherwise a negative value. You may change the offset if that helps to improve the quality of the search hit. lpFlags:
Flags that define the properties of the search hit. You may change the flags, for example to mark a hit as
notable or to discard it. lpOptionalHitPtr: Pointer to the search hit in a memory buffer with the original data that was searched. Provided only if XT_ProcessSearchHit() is called during a search, not necessarily when later applied to an existing search hit, and only for search hits of the simultaneous search, not for index searches. NULL if not provided. Do not make any assumption about how many bytes before or after the search hit can be read in memory. nSearchTermID: You may assign a search hit to a different search term by changing this ID. nLength: Size of the search hit in bytes. You may change that size if that helps to improve the quality of the search hit. nCodePage: See this web page for possible code page identifiers. hItemOrVolume: Part of the structure in v16.5 and later. Specifies the item (for a logical search) or volume (for a physical search) in which a search hit was found. Useful if you wish to read more data from this item. Provided only if XT_ProcessSearchHit() is called during a search, only for search hits of simultaneous search. 0 for index searches, 0 when later applied to an existing search hit. If you call XWF_SelectVolumeSnapshot() while responding to a call to XT_ProcessSearchHit(), you have to call it again to undo the change before returning control. |
For Viewer X-Tensions (only supported by X-Ways Forensics, not WinHex Lab Edition) |
|
PVOID
XT_View( HANDLE hItem, LONG nItemID, HANDLE hVolume, HANDLE hEvidence, PVOID lpReserved, PINT64 lpResSize ); |
If an X-Tension exports this function (optional), the X-Tension may be used by v17.6 and later as a "Viewer X-Tension". The function is called for each file that is to be viewed in a separate window or in Preview mode or that is included in a case report. The X-Tension can provide a human-readable representation of a binary file for example as plain text or HTML, or by converting special graphics file formats to BMP/JPEG/PNG etc., or using any other file format understood by the viewer component. This representation should be written into a buffer that is allocated by the X-Tension itself using a function of its own choice (e.g. VirtualAlloc, GlobalAlloc, HeapAlloc, malloc, GetMem, ...). Return the address of that buffer, or NULL to signal failure. X-Ways Forensics will call XT_ReleaseMem() at a later point in time to make the X-Tension free up the allocated memory when the buffer no longer needed. Please note that if you return HTML code in UTF-16, it needs to be prepended with a byte-order mark (0xFF 0xFE) for the viewer component to treat it like HTML. The integer variable pointed to by lpResSize must be set by this function. It should be set to -1 if you just do not want to be responsible for providing a representation of this file (in most instances because your X-Tension supports very specific file types only). It should be set to -2 if you wish to indicate that an error occurred that needs to be reported, 0 to signal that the file should be represented as no data, or a positive value to signal success and indicate the size of the data in the buffer that you supply. You may use the hItem handle to query the size of the file (via XWF_GetSize) and to read from it (using XWF_Read, for example first to merely check the signature of the file, to see whether you support that particular file type). You may use nItemID for the volume snapshot item property functions for example if you require more file system level metadata about the file such as the filename, or if you require more data from the volume snapshot such as the detected type of the file. You may use the hVolume handle if you require more information about the volume that the file resides in, and the hEvidence handle if you require more information about the evidence object that the volume represents (if any). You should ignore the lpReserved parameter. Note that if/when the user loads your X-Tension in X-Ways Forensics for viewing purposes (as a Viewer X-Tension), XT_Prepare(), XT_Finalize(), XT_ProcessItem(), XT_ProcessItemEx(), XT_PrepareSearch(), and XT_ProcessSearchHit() will not be called even if exported. XT_View() will not be called in your X-Tension even if loaded and selected by the user if a Viewer X-Tension higher in the list of Viewer X-Tensions signals that it does provide a view of that particular file already. In v18.2 and later, a button labelled "XT" is shown in the user interface when viewer X-Tensions are available (loaded), next to the "Raw" button. That button allows the user to conveniently change the preview to the representation provided by the first viewer X-Tension that feels responsible for the type of the selected file. Or back to the regular preview if not helpful, in both directions with a single mouse click. The user may also combine Raw and XT submodes of Preview mode, for example for debugging purposes, if you are programming a viewer X-Tension of your own and have it return HTML code that you wish to conveniently check right within X-Ways Forensics. If you wish to be able to have complete control of what is displays, it is suggested to return an empty buffer (just a NULL byte) so that the viewer component does not show anything, and you get yourself a handle to the viewer component's preview window by calling XWF_GetWindow() with nWndIndex 6, and then you can create windows and controls within the preview window with the preview windows as the parent window, on top of that window so that only your own windows/controls are visible. |
BOOL
XT_ReleaseMem( PVOID lpBuffer ); |
If an X-Tension exports this function (mandatory if XT_View() is exported), it will be called by X-Ways Forensics v17.6 and later to free up memory allocated by a previous call of XT_View(). If you have created any windows or controls with the viewer component's preview window as the parent, it's now time to destroy them. The return value is currently ignored, but you should signal success or failure of the release of the memory buffer. |
For Data Source X-Tensions |
|
For Disk I/O X-Tensions |
|
DWORD
XT_SectorIOInit( struct DriveInfo* pDInfo ); #pragma pack(2) |
If an X-Tension exports this function (optional), it will be called by X-Ways Forensics 18.4 and later when opening a disk or image or partition or volume or reconstructed RAID to see whether the X-Tension wishes to act as an additional abstraction layer for disk I/O. In particular that allows the X-Tension to decrypt data on encrypted disks/partitions/... (FDE, full disk encryption) on the fly when needed by X-Ways Forensics, so that X-Ways Forensics will only get to see the decrypted data. Such an X-Tension will likely check first whether the disk/partition/... contains any supported kind of encryption and may have to prompt the user for a decryption key or a key file (using a dialog window of its own) and/or read some sectors by calling the XWF_DiskIO function to make the final decision. The X-Tension should return flags: 0x01 if it wishes to be responsible for read access to the disk/partition/... and receive XT_SectorIO() calls, 0x02 if it wishes to be responsible for write access (not currently supported), 0x04 to enforce read-only mode otherwise if direct writing (not through the X-Tension) must be prevented to avoid corruption. 0x10 should be returned if the X-Tension wishes to be responsible for reading data at the file level by getting its XT_FileIO() function called. The function should return 0 if the X-Tension does not feel responsible for handling that particular disk/partition/... at all, for example because it found an unknown or unsupported type of encryption. nSize is the size of the structure. The structure might grow in future versions of X-Ways Forensics, but the elements at the beginning of the structure remain the same. nDrive may be a negative number (in case of a physical, partitioned disk or image or hardware RAID) or a positive number (in case of a partition or volume on a disk or in an image or RAID). This parameter identifies the data source and must be used for any calls to XWF_DriveIO. lpPrivate is initially a pointer to an initialized Unicode buffer that you may fill with an error message in case your function returns 0. The buffer may hold up to 255 characters. If however you signal success, then you may change this pointer to any private value or other pointer for your own use. You will be provided with the same value/pointer again when responding to calls for XT_SectorIO() and XT_SectorIODone(). The value/pointer may help you to reference your own dynamically allocated data about the encryption or to identify the disk. nSectorCount is not only provided to you, but you may also change that value. For example if you provide access to an encrypted volume that is contained in the designated partition, but does not occupy the entire space of that partition because of a reserved header area, you reduce the sector count accordingly to prevent X-Ways Forensics from accessing sectors that do not exist in your volume. In such a case of a reserved header area of n sectors, that also means that when you respond to calls for XT_SectorIO() to read sector x, you will actually read sector x+n using XWF_SectorIO and then (probably after decrypting it) return that data. nParentDrive, nParentSectorCount, and nStartSectorOnParent are provided in case you need metadata from outside of the partition to properly interpret the data in the partition. You may read data from the parent disk using XWF_SectorIO, specifying nParentDrive as the drive to read from. If nParentDrive is zero, there is no parent. |
DWORD
XT_SectorIO( LPVOID lpPrivate, LONG nDrive, INT64 nSector, DWORD nCount, LPVOID lpBuffer, DWORD nFlags ); |
An X-Tension must export this function if its XT_SectorIOInit() function ever returns the flag 0x01. If the flag is returned, X-Ways Forensics 18.4 and later will call XT_SectorIO() for any internally triggered I/O sector-wise operations on storage media or partitions/volumes when caching is not enabled, X-Ways Forensics 19.6 and later also with caching enable (see Options | General). It is your resonsibility to fill the buffer and return the number of transferred sectors. You can retrieve the original sector contents by calling XWF_SectorIO(), alter the data as necessary (e.g. decrypt), and then pass it back to the caller. You may read from the same sector number or translate the external sector number to a different internal sector number and read from that sector instead, for example to skip a header with encryption metadata. nFlags, nCount, nSector, lpBuffer have the same meaning as in XWF_SectorIO() and may be simply passed on to that function. |
INT64
XT_FileIO( LPVOID lpPrivate, LONG nDrive, HANDLE hVolume, HANDLE hItem, LONG nItemID, INT64 nOffset, LPVOID lpBuffer, INT64 nNumberOfBytes, DWORD nFlags ); |
An X-Tension must export this function if its XT_SectorIOInit() function ever returns the flag 0x10. If the flag is returned, X-Ways Forensics 19.2 and later will call XT_FileIO() for any internally triggered file read operations on the same volume, but only for files that are defined in the file system (e.g. not carved files, files embedded in other files, files in archives, e-mails extracted from e-mail archives, stills extracted from videos, etc.). It is your responsibility to fill the buffer. You can, for example, retrieve the original file contents by calling XWF_Read for that file (item) using hItem, alter the data as necessary (e.g. decrypt), and then pass it back to the caller. Or, you can locate the storage location of the file contents on the volume yourself and read from the volume sector-wise by calling XWF_SectorIO using the nDrive parameter, or you can read from the volume with random access by calling XWF_Read for that volume using hVolume. This function is also used to signal when a file is opened (access to it is initialized) or when it is closed (access to it has ended and allocated resources need to be freed), i.e. before the first actual I/O happens and after the last I/O happens. nNumberOfBytesToRead will be 0 in those cases, lpBuffer will be NULL, and nOffset will be -1 to signal that initialization is required and -2 to signal that clean-up is due. Whether these calls actually need any action at all depends on the inner working of the X-Tension. In these special situations you return 0 unless during initialization you decide that you do not wish to be responsible for I/O for that file, in which case you return -1. Calls with negative values of nOffset other than -1 and -2 must be ignored.
nFlags may be one of these values: If nOffset is greater than or equal to 0, return the number of bytes filled into the buffer / that were successfully read. 0 mean nothing was read, for example because the requested read offset is past the end of the available date. -1 means complete failure, for example if it was not even possible any more to access the unterlying volume. -2 may be returned if (and only if) the 0x40 flag was set, in order to signal that the entire requested portion of the file is considered sparse, so that the caller will know it can ignore the data and doesn't have to do anything with it. Useful for performance reasons. You don't need to fill the buffer in that case. Observing the 0x40 flag and specially treating and signaling sparse areas is optional. |
DWORD
XT_SectorIODone( LPVOID lpPrivate, LPVOID lpReserved ); |
If an X-Tension exports this function (mandatory if XT_SectorIOInit() is exported), it will be called by X-Ways Forensics 18.4 and later, only if an X-Tension returned 0x01 or 0x10 for a previous call for XT_SectorIOInit(). Gives the X-Tension the opportunity to free any resources when the disk/partition/... is about to be closed, in particular memory on the heap that you may have allocated before and this is pointed to by lpPrivate. Return 0. |