Introduction
This source code shows how to dump the file reading its sectors directly from the disk using logical offsets. It heavily uses FSCTL_GET_RETRIEVAL_POINTERS
IO control code. The full description of FSCTL_GET_RETRIEVAL_POINTERS
IO control code can be found in Mark Roddy's article "Adventures in Luserland: Finding Disk Sectors Associated with File Records" and on MSDN.
Background
Recently I found Windows registry format specification and wanted to explore "raw" Windows registry files. However I discovered that some of them are locked by the system (OS) itself. I wanted to dump these files without restarting the system and booting from other OS and searched for a solution. I found some samples on the internet on using FSCTL_GET_RETRIEVAL_POINTERS
IO control code to get volume logical offsets, but no one had FAT support plus no one had correct error handling. I wanted an "all-in-one" solution, so I wrote my own implementation of dumping a file, using several articles as a starting point, which supports all file systems used by Windows.
Using the Code
Several APIs are provided to the user to ease his/her work in dumping file sectors. The call order should be as follows:
FsGetFileInfo()
FsGetVolumeInfo()
FsGetFileExtents()
FsFreeFileInfo()
FsFreeVolumeInfo()
If you don't want to use these APIs, there is an already implemented function that does everything you need - FsSectorCopy()
, which calls the above mentioned APIs. Short documentation on the function:
STDAPI_( BOOL )
FsSectorCopy(
IN LPCTSTR pszSrcFileName,
IN LPCTSTR pszDstFileName,
IN FS_CALLBACK_DATA* pCallbackData
);
Function parameters:
pszSrcFileName
- Source file path which is to be dumped pszDstFileName
- Destination file path to dump file sectors to pCallbackData
- Callback data (optional)
Callback data structure (pCallbackData)
is declared as follows:
typedef struct _FS_CALLBACK_DATA
{
PFNFS_PROGRESS_CALLBACK pfnFsProgress;
HANDLE hEventBreak;
LPCVOID lpUserParam;
} FS_CALLBACK_DATA;
Callback data structure's members:
pfnFsProgress
- Pointer to progress callback function called during the execution of the FsSectorCopy()
to indicate its progress. hEventBreak
- Event which can be set to stop the execution of the FsSectorCopy()
function. This variable must be initialized before FsSectorCopy()
call. lpUserParam
- User parameter which is passed to progress callback function (pfnFsProgress)
.
Note that progress callback function (pfnFsProgress
) can be called multiple times depending on the operation type and the overall percent complete value. Progress callback function (pfnFsProgress
) declaration is as follows:
typedef BOOL ( CALLBACK* PFNFS_PROGRESS_CALLBACK )
(
IN LPCVOID lpUserParam,
IN DWORD dwJobType,
IN BOOL bJobDone,
IN LPCVOID lpJobContext,
IN DWORD dwPercentComplete
);
Callback function parameters:
lpUserParam
- User parameter passed to FsSectorCopy()
in callback data structure's lpUserParam
member. dwJobType
- Type of operation currently performed. Types of operations and their contexts are listed in the next section. bJobDone
- Boolean value indicating operation success or failure. In case of operation failure, you can lookup the last error description in the system's message table. lpJobContext
- Operation context, its type depends on dwJobType
. Types of operations and their contexts are listed in the next section. dwPercentComplete
- Overall operation percent complete value.
Operation types and their context passed to progress callback function:
FS_JOB_GET_SRC_VOLUME_INFO
- Progress callback function is called once with this operation type to indicate that the FsSectorCopy()
function is getting source volume information. lpJobContext
parameter of the progress function is a pointer to FS_VOLUME_INFO
structure. Structure declaration is not presented here and should be looked up in the source code. dwPercentComplete
is 0. FS_JOB_GET_SRC_FILE_INFO
- Progress callback function is called once with this operation type to indicate that FsSectorCopy()
function is getting source file information. lpJobContext
parameter of the progress function is a pointer to FS_FILE_INFO
structure. Structure declaration is not presented here and should be looked up in the source code. dwPercentComplete
is 0. FS_JOB_GET_SRC_FILE_EXTENTS
- Progress callback function is called once with this operation type to indicate that FsSectorCopy()
function is getting source file extents. lpJobContext
parameter of the progress function is empty. dwPercentComplete
is 0. FS_JOB_GET_SRC_FILE_MFT
- Progress callback function is called once with this operation type to indicate that FsSectorCopy()
function is getting source file from MFT (if it is too small to occupy a whole cluster). lpJobContext
parameter of the progress function is empty. dwPercentComplete
is 0. FS_JOB_CREATE_FILE_DST
- Progress callback function is called once with this operation type to indicate that FsSectorCopy()
function is creating destination file. lpJobContext
parameter of the progress function is empty. dwPercentComplete
is 0. FS_JOB_COPY_DATA_FROM_MFT
- Progress callback function is called once with this operation type to indicate that FsSectorCopy()
function is dumping file data from MFT to destination file. lpJobContext
parameter of the progress function is empty. dwPercentComplete
is 0. FS_JOB_COPY_DATA_FROM_DISK
- With this operation type progress callback function is called multiple times to indicate that FsSectorCopy()
function is dumping source file sectors to destination file. lpJobContext
parameter of the progress function is LCN (Logical Cluster) number. dwPercentComplete
is increasing from 0 to 100 accordingly to progress of sectors copied.
For more information, please review the source code.
System Requirements
- Platforms supported: Windows 2000 Workstation/Servers and higher (XP/2003 Servers, Vista/2008 Servers).
- User privileges required: User must start an application as an administrator in order to use it.
- File systems supported: Currently application supports FAT12/16/32 and NTFS. There is also a new file system called exFAT created by Microsoft for flash drives. It was introduced with Microsoft Windows Vista SP1 (and maybe with Windows 2008). Unfortunately I was unable to find any exFAT specification so the application lacks its support.
- Non-trivial disks: Application is expected to work on striped and mirrored disks (personally tested on my SATAII RAID0 stripe). In case of errors, please report for me to improve the application behaviour.
- Large files support: I personally dumped large image files about 5Gb in size and compared with the original ones. However errors may happen with large files (while they shouldn't), please report them.
Known Limitations
- Currently the compressed volumes, compressed and sparsed files are not supported.
- exFAT file system is not supported.
- The program compiles for 64 bit platforms. However I haven't tested it on Windows x64.
IMPORTANT: If any one has useful information or a solution for the above mentioned issues, please share it.
- Direct Copy Method by Napalm (sounds like some hacker name)
- "Translating logical offsets into physical offsets" by Omri Shaked
- FAT32 File System Specification by Microsoft Corporation
- "Adventures in Luserland: Finding Disk Sectors Associated with File Records" by Mark Roddy
- DOSFS Embedded FAT-Compatible Filesystem by Andreas R. Fugl
- FSCTL_GET_RETRIEVAL_POINTERS Control Code on MSDN
History
- 01 September 2008
- Initial release of the application
- 22 October 2008
- Final release of the application
- 27 December 2008
- Submitted the article to The Code Project
- 05 January 2009
- Two small bug fixes (thanks to marcosvelasco)