| 613 | } |
| 614 | |
| 615 | NTSTATUS BackupFile(_In_ PUNICODE_STRING FileName) { |
| 616 | NTSTATUS status = STATUS_SUCCESS; |
| 617 | FileManager mgrS,mgrT; |
| 618 | void* buffer = nullptr; |
| 619 | IO_STATUS_BLOCK ioStatus; |
| 620 | |
| 621 | do |
| 622 | { |
| 623 | // open source file |
| 624 | status = mgrS.Open(FileName, FileAccessMask::Read | FileAccessMask::Synchronize); |
| 625 | if (!NT_SUCCESS(status)) |
| 626 | break; |
| 627 | |
| 628 | // get source file size |
| 629 | LARGE_INTEGER fileSize; |
| 630 | status = mgrS.GetFileSize(&fileSize); |
| 631 | if (!NT_SUCCESS(status) || fileSize.QuadPart == 0) |
| 632 | break; |
| 633 | |
| 634 | // open target file |
| 635 | UNICODE_STRING targetFileName; |
| 636 | auto sysName = wcsrchr(FileName->Buffer, L'\\') + 1; |
| 637 | if (sysName == nullptr) { |
| 638 | status = STATUS_INVALID_PARAMETER; |
| 639 | break; |
| 640 | } |
| 641 | USHORT len = wcslen(sysName); |
| 642 | const WCHAR backupStream[] = L"_backup.sys"; |
| 643 | |
| 644 | targetFileName.MaximumLength = g_BackupDir.Length + len * sizeof(WCHAR)+ sizeof(backupStream); |
| 645 | targetFileName.Buffer = (WCHAR*)ExAllocatePoolWithTag(PagedPool, targetFileName.MaximumLength, 'kuab'); |
| 646 | if (targetFileName.Buffer == nullptr){ |
| 647 | status = STATUS_INSUFFICIENT_RESOURCES; |
| 648 | break; |
| 649 | } |
| 650 | |
| 651 | RtlCopyUnicodeString(&targetFileName, &g_BackupDir); |
| 652 | RtlAppendUnicodeToString(&targetFileName, sysName); |
| 653 | RtlAppendUnicodeToString(&targetFileName, backupStream); |
| 654 | |
| 655 | status = mgrT.Open(&targetFileName, FileAccessMask::Write | FileAccessMask::Synchronize); |
| 656 | ExFreePool(targetFileName.Buffer); |
| 657 | |
| 658 | if (!NT_SUCCESS(status)) |
| 659 | break; |
| 660 | |
| 661 | // allocate buffer for copying purpose |
| 662 | ULONG size = 1 << 21; // 2 MB |
| 663 | buffer = ExAllocatePoolWithTag(PagedPool, size, 'kcab'); |
| 664 | if (!buffer) { |
| 665 | status = STATUS_INSUFFICIENT_RESOURCES; |
| 666 | break; |
| 667 | } |
| 668 | |
| 669 | // loop - read from source,write to target |
| 670 | LARGE_INTEGER offset = { 0 }; // read |
| 671 | LARGE_INTEGER writeOffset = { 0 }; // write |
| 672 |
no test coverage detected