Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- FLT_PREOP_CALLBACK_STATUS
- RWBPreCreate(
- _Inout_ PFLT_CALLBACK_DATA Data,
- _In_ PCFLT_RELATED_OBJECTS FltObjects,
- _Flt_CompletionContext_Outptr_ PVOID *CompletionContext
- ){
- NTSTATUS status; // Operation status
- PFLT_FILE_NAME_INFORMATION pFileNameInfo = NULL; // File name information for file being opened
- UNICODE_STRING backupPath; // String to hold the backup file
- HANDLE originalHandle = NULL, // Original file handle
- backupHandle = NULL; // Backup file handle
- PFILE_OBJECT pOriginalFileObject = NULL, // Pointer to original file object TODO: check if it must be de-allocated
- pBackupFileObject = NULL; // Pointer to backup file object TODO: check if it must be de-allocated
- OBJECT_ATTRIBUTES oaOriginal, // Object attributes for original file
- oaBackup; // Object attributes for backup file
- IO_STATUS_BLOCK iosbOriginal, // IO Status block for original file
- iosbBackup; // IO Status block for backup file
- FILE_BASIC_INFORMATION fileInfo; // Basic file information
- // CODE EXECUTED IF THE FILE HAS .txt EXTENSION AND IF IT IS OPENED IN WRITE OR DELETE MODE
- #pragma region OpenOriginalFile
- // Initialize file attributes for original file
- InitializeObjectAttributes(
- &oaOriginal,
- &pFileNameInfo->Name,
- OBJ_KERNEL_HANDLE,
- NULL,
- NULL
- );
- // Open original file
- status = FltCreateFileEx(
- Globals.Filter,
- FltObjects->Instance,
- &originalHandle,
- &pOriginalFileObject,
- FILE_READ_DATA | FILE_READ_ATTRIBUTES,
- &oaOriginal,
- &iosbOriginal,
- NULL,
- FILE_ATTRIBUTE_READONLY,
- (ULONG)0,
- FILE_OPEN,
- FILE_NON_DIRECTORY_FILE | FILE_SEQUENTIAL_ONLY | FILE_OPEN_FOR_BACKUP_INTENT,
- NULL,
- (ULONG)0,
- IO_IGNORE_SHARE_ACCESS_CHECK
- );
- // If the original object name was not found, the file does not exists and it's
- // being created. This is not an error
- if (status == STATUS_OBJECT_NAME_NOT_FOUND){
- [...]
- goto RWBPreCreateCleanup;
- }
- if (!NT_SUCCESS(status)){
- [...]
- goto RWBPreCreateCleanup;
- }
- #pragma endregion Open the original file
- // Initialize object attributes for the backup file
- InitializeObjectAttributes(
- &oaBackup,
- &backupPath,
- OBJ_KERNEL_HANDLE,
- NULL,
- NULL
- );
- // Try to open backup file (if it already exists)
- status = FltCreateFileEx(
- Globals.Filter,
- FltObjects->Instance,
- &backupHandle,
- &pBackupFileObject,
- FILE_READ_DATA,
- &oaBackup,
- &iosbBackup,
- NULL,
- FILE_ATTRIBUTE_NORMAL,
- (ULONG)0,
- FILE_OPEN,
- FILE_NON_DIRECTORY_FILE,
- NULL,
- (ULONG)0,
- IO_IGNORE_SHARE_ACCESS_CHECK
- );
- // If the file was opened without problems, it means that it already existed and we have to check when it was created
- if (status == STATUS_SUCCESS){
- LARGE_INTEGER currentTime;
- PT_DBG_PRINT(PTDBG_TRACE_OPERATION_STATUS,
- ("[RWB]: RWBPreCreate -> Backup file already exists. Checking attributes"));
- status = FltQueryInformationFile(
- FltObjects->Instance,
- pBackupFileObject,
- &fileInfo,
- sizeof(fileInfo),
- FileBasicInformation,
- NULL
- );
- if (!NT_SUCCESS(status)){
- [...]
- goto RWBPreCreateCleanup;
- }
- KeQuerySystemTime(¤tTime);
- LONGLONG deltaBackup = (currentTime.QuadPart - fileInfo.ChangeTime.QuadPart) / 10000000;
- // If the last backup was made less than BACKUP_INTERVAL_SECONDS ago, we don't back it up again.
- // Since times are expressed as number of 100-nanoseconds intervals since the start of the year 1601
- // we do the appropriate computation. If we have to create the new file because the backup is too old,
- // we close the old handle and open a new one is write mode
- if ( deltaBackup < BACKUP_INTERVAL_SECONDS){
- PT_DBG_PRINT(PTDBG_TRACE_OPERATION_STATUS,
- ("[RWB]: RWBPreCreate -> Backup file not old enough. Won't backup again (Cbd = %p, FileObject = %p)\n",
- Data,
- FltObjects->FileObject));
- goto RWBPreCreateCleanup;
- }
- else{
- FltClose(backupHandle);
- status = FltCreateFileEx(
- Globals.Filter,
- FltObjects->Instance,
- &backupHandle,
- &pBackupFileObject,
- FILE_WRITE_DATA,
- &oaBackup,
- &iosbBackup,
- NULL,
- FILE_ATTRIBUTE_NORMAL,
- (ULONG)0,
- FILE_OVERWRITE,
- FILE_NON_DIRECTORY_FILE,
- NULL,
- (ULONG)0,
- IO_IGNORE_SHARE_ACCESS_CHECK
- );
- if (!NT_SUCCESS(status)){
- PT_DBG_PRINT(PTDBG_TRACE_OPERATION_STATUS,
- ("[RWB]: RWBPreCreate -> Failed to overwrite backup file (Cbd = %p, FileObject = %p)\n",
- Data,
- FltObjects->FileObject));
- goto RWBPreCreateCleanup;
- }
- }
- }
- // If the creation fails with error STATUS_OBJECT_PATH_NOT_FOUND this means that the
- // folder does not exists. Create the folder
- else if (status == STATUS_OBJECT_PATH_NOT_FOUND){
- UNICODE_STRING previousFolder;
- // Creates a new string to hold the path without the final component
- previousFolder.MaximumLength = backupPath.Length - pFileNameInfo->FinalComponent.Length - sizeof(WCHAR);
- RWBAllocateUnicodeString(&previousFolder);
- RtlCopyMemory(
- previousFolder.Buffer,
- backupPath.Buffer,
- previousFolder.MaximumLength
- );
- previousFolder.Length = previousFolder.MaximumLength;
- // Creates the previous folders
- RWBRollPath(
- previousFolder,
- Globals.Filter,
- FltObjects->Instance
- );
- RWBFreeUnicodeString(&previousFolder);
- // Create backup file. This time should not fail
- status = FltCreateFileEx(
- Globals.Filter,
- FltObjects->Instance,
- &backupHandle,
- &pBackupFileObject,
- FILE_WRITE_DATA,
- &oaBackup,
- &iosbBackup,
- NULL,
- FILE_ATTRIBUTE_NORMAL,
- (ULONG)0,
- FILE_CREATE,
- FILE_NON_DIRECTORY_FILE,
- NULL,
- (ULONG)0,
- IO_IGNORE_SHARE_ACCESS_CHECK
- );
- }
- if (!NT_SUCCESS(status)){
- PT_DBG_PRINT(PTDBG_TRACE_OPERATION_STATUS,
- ("[RWB]: RWBPreCreate -> Failed to create backup file (Cbd = %p, FileObject = %p)\n",
- Data,
- FltObjects->FileObject));
- goto RWBPreCreateCleanup;
- }
- #pragma endregion Create the backup file
- #pragma region CopyContent
- // At this point, both the original handle and the backup handle must be valid
- NT_ASSERT(originalHandle != NULL && backupHandle != NULL);
- NT_ASSERT(pOriginalFileObject != NULL && pBackupFileObject != NULL);
- status = RWBCopyContent(
- FltObjects->Instance,
- pOriginalFileObject,
- pBackupFileObject
- );
- if (!NT_SUCCESS(status)){
- [...]
- goto RWBPreCreateCleanup;
- }
- #pragma endregion Copy the content from the original file to the backup one
- RWBPreCreateCleanup:
- if (originalHandle != NULL)
- status = FltClose(originalHandle);
- if (backupHandle != NULL)
- status = FltClose(backupHandle);
- if (pFileNameInfo != NULL)
- FltReleaseFileNameInformation(pFileNameInfo);
- RWBFreeUnicodeString(&backupPath);
- // TODO: Check for object attributes release
- return FLT_PREOP_SUCCESS_WITH_CALLBACK;
- }
- }
- NTSTATUS
- RWBRollPath(
- _In_ UNICODE_STRING Path,
- _In_ PFLT_FILTER Filter,
- _In_ PFLT_INSTANCE Instance
- )
- /*
- Routine Description:
- This routine creates the directory specified as input
- Arguments:
- Path - The path to create
- Return Value:
- STATUS_SUCCESS - success
- */
- {
- NTSTATUS status = STATUS_SUCCESS;
- HANDLE directoryHandle = NULL;
- OBJECT_ATTRIBUTES objectAttributes;
- IO_STATUS_BLOCK ioStatusBlock;
- UNICODE_STRING previousFolder;
- // Initialize object attributes to set the path
- InitializeObjectAttributes(
- &objectAttributes,
- &Path,
- OBJ_CASE_INSENSITIVE,
- NULL,
- NULL
- );
- // Tries to create the directory.
- status = FltCreateFile(
- Filter,
- Instance,
- &directoryHandle,
- FILE_LIST_DIRECTORY | FILE_TRAVERSE,
- &objectAttributes,
- &ioStatusBlock,
- NULL,
- FILE_ATTRIBUTE_NORMAL,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- FILE_OPEN_IF,
- FILE_DIRECTORY_FILE,
- NULL,
- (ULONG) 0,
- IO_IGNORE_SHARE_ACCESS_CHECK
- );
- // If the directory already exists or it have been created, returns STATUS_SUCCESS
- if (ioStatusBlock.Information == FILE_OPENED || ioStatusBlock.Information == FILE_CREATED){
- status = STATUS_SUCCESS;
- goto RWBRollPathCleanup;
- }
- // If the create failed, it means that we have to create the previous directories and then try again to create this directory
- if (!NT_SUCCESS(status)){
- UNICODE_STRING finalComponent;
- // Get the final component of the name and creates a new string without
- // it in order to create the previous folder
- FltParseFileName(&Path,
- NULL,
- NULL,
- &finalComponent
- );
- previousFolder.MaximumLength = Path.Length - finalComponent.Length - sizeof(WCHAR);
- RWBAllocateUnicodeString(&previousFolder);
- RtlCopyMemory(
- previousFolder.Buffer,
- Path.Buffer,
- previousFolder.MaximumLength
- );
- previousFolder.Length = previousFolder.MaximumLength;
- // Creates the previous folders
- RWBRollPath(
- previousFolder,
- Filter,
- Instance
- );
- // TODO: check status
- // Tries to create the directory again. This time should not fail since the previous folder have been created
- status = FltCreateFile(
- Filter,
- Instance,
- &directoryHandle,
- FILE_LIST_DIRECTORY | FILE_TRAVERSE,
- &objectAttributes,
- &ioStatusBlock,
- NULL,
- FILE_ATTRIBUTE_NORMAL,
- FILE_SHARE_READ | FILE_SHARE_WRITE,
- FILE_OPEN_IF,
- FILE_DIRECTORY_FILE,
- NULL,
- (ULONG)0,
- IO_IGNORE_SHARE_ACCESS_CHECK
- );
- RWBFreeUnicodeString(&previousFolder);
- }
- RWBRollPathCleanup:
- if (directoryHandle != NULL)
- status = FltClose(directoryHandle);
- return status;
- }
- NTSTATUS
- RWBCopyContent(
- PFLT_INSTANCE Instance,
- PFILE_OBJECT pSourceObject,
- PFILE_OBJECT pDestinationObject
- )
- /*
- Routine Description :
- This routine copy the content of a file to another
- Arguments:
- Instance - The initiating instance
- SourceObject - Source file object
- DestinationObject - Destination file object
- Return Value
- STATUS_SUCCESS if the operation have been completed, otherwise the status that generated the error
- */
- {
- NTSTATUS status;
- ULONG bytesRead; // Bytes read
- UCHAR buffer[COPY_READ_SIZE]; // Buffer to hold read content during copy
- LARGE_INTEGER readOffset, writeOffset; // Offset for read operation
- // Initialize offset for read and write operation
- readOffset.QuadPart = 0;
- // Initialize offset for read and write operation
- writeOffset.QuadPart = 0;
- // Read content
- status = FltReadFile(
- Instance,
- pSourceObject,
- &readOffset,
- (ULONG)COPY_READ_SIZE,
- buffer,
- FLTFL_IO_OPERATION_NON_CACHED,
- &bytesRead,
- NULL,
- NULL
- );
- readOffset.QuadPart += bytesRead;
- while (status != STATUS_END_OF_FILE){
- // Write content
- status = FltWriteFile(
- Instance,
- pDestinationObject,
- &writeOffset,
- bytesRead,
- buffer,
- FLTFL_IO_OPERATION_NON_CACHED,
- &bytesRead,
- NULL,
- NULL
- );
- writeOffset.QuadPart += bytesRead;
- if (!NT_SUCCESS(status)){
- PT_DBG_PRINT(PTDBG_TRACE_OPERATION_STATUS,
- ("[RWB]: RWBCopyContent -> Write failed with error %llx", status));
- }
- // Read new content content
- status = FltReadFile(
- Instance,
- pSourceObject,
- &readOffset,
- (ULONG)COPY_READ_SIZE,
- buffer,
- FLTFL_IO_OPERATION_NON_CACHED,
- &bytesRead,
- NULL,
- NULL
- );
- readOffset.QuadPart += bytesRead;
- }
- if (status == STATUS_END_OF_FILE)
- return STATUS_SUCCESS;
- else
- return status;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement