NTSTATUS Log_CompressFile(HANDLE FileHandle) { NTSTATUS Status = STATUS_SUCCESS; IO_STATUS_BLOCK StatusBlock = { 0 }; USHORT InputBuffer = COMPRESSION_FORMAT_DEFAULT; Status = ZwFsControlFile(FileHandle, NULL, NULL, NULL, &StatusBlock, FSCTL_SET_COMPRESSION, &InputBuffer, sizeof(InputBuffer), NULL, 0); return Status; }
NTSTATUS GetFileClusterList( IN HANDLE hFile, OUT PRETRIEVAL_POINTERS_BUFFER *FileClusters) { NTSTATUS status; IO_STATUS_BLOCK iosb; LARGE_INTEGER StartVcn; PRETRIEVAL_POINTERS_BUFFER pVcnPairs; ULONG ulOutPutSize; ULONG uCounts; PAGED_CODE(); ASSERT(FileClusters != NULL); //FSCTL_GET_NTFS_FILE_RECORD uCounts = 0; StartVcn.QuadPart=0; do { uCounts+=200; pVcnPairs = NULL; ulOutPutSize = sizeof(RETRIEVAL_POINTERS_BUFFER) + uCounts* sizeof(pVcnPairs->Extents); pVcnPairs = (PRETRIEVAL_POINTERS_BUFFER)ExAllocatePoolWithTag(PagedPool, ulOutPutSize, 'FVCN'); if(pVcnPairs == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } status = ZwFsControlFile( hFile,NULL, NULL, 0, &iosb, FSCTL_GET_RETRIEVAL_POINTERS, &StartVcn, sizeof(StartVcn), pVcnPairs, ulOutPutSize ); if (!NT_SUCCESS(status)) { ExFreePool(pVcnPairs); KdPrint(("SYS:GetFileClusterList:ZwFsControlFile(size=%d) Failed(0x%08x)\n", ulOutPutSize, status)); } else { *FileClusters = pVcnPairs; } } while (status == STATUS_BUFFER_OVERFLOW); return status; }
static VOID NTAPI TestSymlinks(VOID) { HANDLE ReparseHandle; NTSTATUS Status; IO_STATUS_BLOCK IoStatusBlock; OBJECT_ATTRIBUTES ObjectAttributes; PREPARSE_DATA_BUFFER Reparse; FILE_DISPOSITION_INFORMATION ToDelete; PFILE_OBJECT FileObject; UNICODE_STRING SysDir, Foobar, Regedit; ULONG Size; /* Get Windows/ReactOS directory */ InitializeObjectAttributes(&ObjectAttributes, &SystemRoot, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = ZwOpenFile(&ReparseHandle, FILE_READ_DATA, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_DIRECTORY_FILE); if (skip(NT_SUCCESS(Status), "Opening \\SystemRoot failed: %lx\n", Status)) { return; } Status = ObReferenceObjectByHandle(ReparseHandle, FILE_READ_DATA, *IoFileObjectType, UserMode, (PVOID *)&FileObject, NULL); if (skip(NT_SUCCESS(Status), "Querying name failed: %lx\n", Status)) { ZwClose(ReparseHandle); return; } SysDir.Buffer = ExAllocatePool(NonPagedPool, FileObject->FileName.Length + sizeof(L"\\??\\C:")); if (skip(SysDir.Buffer != NULL, "Allocating memory failed\n")) { ObDereferenceObject(FileObject); ZwClose(ReparseHandle); return; } SysDir.Length = sizeof(L"\\??\\C:") - sizeof(UNICODE_NULL); SysDir.MaximumLength = FileObject->FileName.Length + sizeof(L"\\??\\C:"); RtlCopyMemory(SysDir.Buffer, L"\\??\\C:", sizeof(L"\\??\\C:") - sizeof(UNICODE_NULL)); RtlAppendUnicodeStringToString(&SysDir, &FileObject->FileName); Foobar.Buffer = ExAllocatePool(NonPagedPool, FileObject->FileName.Length + sizeof(L"\\foobar.exe")); if (skip(Foobar.Buffer != NULL, "Allocating memory failed\n")) { ExFreePool(SysDir.Buffer); ObDereferenceObject(FileObject); ZwClose(ReparseHandle); return; } Foobar.Length = 0; Foobar.MaximumLength = FileObject->FileName.Length + sizeof(L"\\foobar.exe"); RtlCopyUnicodeString(&Foobar, &FileObject->FileName); RtlCopyMemory(&Foobar.Buffer[Foobar.Length / sizeof(WCHAR)], L"\\foobar.exe", sizeof(L"\\foobar.exe") - sizeof(UNICODE_NULL)); Foobar.Length += (sizeof(L"\\foobar.exe") - sizeof(UNICODE_NULL)); Regedit.Buffer = ExAllocatePool(NonPagedPool, FileObject->FileName.Length + sizeof(L"\\regedit.exe")); if (skip(Regedit.Buffer != NULL, "Allocating memory failed\n")) { ExFreePool(Foobar.Buffer); ExFreePool(SysDir.Buffer); ObDereferenceObject(FileObject); ZwClose(ReparseHandle); return; } Regedit.Length = 0; Regedit.MaximumLength = FileObject->FileName.Length + sizeof(L"\\regedit.exe"); RtlCopyUnicodeString(&Regedit, &FileObject->FileName); RtlCopyMemory(&Regedit.Buffer[Regedit.Length / sizeof(WCHAR)], L"\\regedit.exe", sizeof(L"\\regedit.exe") - sizeof(UNICODE_NULL)); Regedit.Length += (sizeof(L"\\regedit.exe") - sizeof(UNICODE_NULL)); ObDereferenceObject(FileObject); ZwClose(ReparseHandle); ToDelete.DeleteFile = TRUE; Size = FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + SysDir.Length * 2 + sizeof(L"\\regedit.exe") * 2 - sizeof(L"\\??\\") - sizeof(UNICODE_NULL); InitializeObjectAttributes(&ObjectAttributes, &SystemRootFoobar, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = ZwCreateFile(&ReparseHandle, GENERIC_READ | GENERIC_WRITE | DELETE, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_SUPERSEDE, FILE_NON_DIRECTORY_FILE, NULL, 0); ok_eq_hex(Status, STATUS_SUCCESS); if (skip(NT_SUCCESS(Status), "Creating file failed: %lx\n", Status)) { ExFreePool(Regedit.Buffer); ExFreePool(Foobar.Buffer); ExFreePool(SysDir.Buffer); return; } Reparse = ExAllocatePool(NonPagedPool, Size); RtlZeroMemory(Reparse, Size); Reparse->ReparseTag = IO_REPARSE_TAG_SYMLINK; Reparse->ReparseDataLength = 12 + SysDir.Length * 2 + sizeof(L"\\regedit.exe") * 2 - sizeof(L"\\??\\") - sizeof(UNICODE_NULL); Reparse->SymbolicLinkReparseBuffer.SubstituteNameLength = SysDir.Length + sizeof(L"\\regedit.exe") - sizeof(UNICODE_NULL); Reparse->SymbolicLinkReparseBuffer.PrintNameLength = SysDir.Length + sizeof(L"\\regedit.exe") - sizeof(L"\\??\\"); Reparse->SymbolicLinkReparseBuffer.SubstituteNameOffset = Reparse->SymbolicLinkReparseBuffer.PrintNameLength; RtlCopyMemory(Reparse->SymbolicLinkReparseBuffer.PathBuffer, (WCHAR *)((ULONG_PTR)SysDir.Buffer + sizeof(L"\\??\\") - sizeof(UNICODE_NULL)), SysDir.Length - sizeof(L"\\??\\") + sizeof(UNICODE_NULL)); RtlCopyMemory((WCHAR *)((ULONG_PTR)Reparse->SymbolicLinkReparseBuffer.PathBuffer + SysDir.Length - sizeof(L"\\??\\") + sizeof(UNICODE_NULL)), L"\\regedit.exe", sizeof(L"\\regedit.exe") - sizeof(UNICODE_NULL)); RtlCopyMemory((WCHAR *)((ULONG_PTR)Reparse->SymbolicLinkReparseBuffer.PathBuffer + Reparse->SymbolicLinkReparseBuffer.SubstituteNameOffset), SysDir.Buffer, SysDir.Length); RtlCopyMemory((WCHAR *)((ULONG_PTR)Reparse->SymbolicLinkReparseBuffer.PathBuffer + Reparse->SymbolicLinkReparseBuffer.SubstituteNameOffset + SysDir.Length), L"\\regedit.exe", sizeof(L"\\regedit.exe") - sizeof(UNICODE_NULL)); Status = ZwFsControlFile(ReparseHandle, NULL, NULL, NULL, &IoStatusBlock, FSCTL_SET_REPARSE_POINT, Reparse, Size, NULL, 0); ok_eq_hex(Status, STATUS_SUCCESS); if (!NT_SUCCESS(Status)) { ZwClose(ReparseHandle); Status = ZwCreateFile(&ReparseHandle, FILE_WRITE_ATTRIBUTES | DELETE | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_SUPERSEDE, FILE_NON_DIRECTORY_FILE | FILE_OPEN_REPARSE_POINT | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT, NULL, 0); if (skip(NT_SUCCESS(Status), "Creating symlink failed: %lx\n", Status)) { Status = ZwOpenFile(&ReparseHandle, DELETE, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_DELETE, FILE_NON_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE); ok_eq_hex(Status, STATUS_SUCCESS); ZwClose(ReparseHandle); ExFreePool(Regedit.Buffer); ExFreePool(Foobar.Buffer); ExFreePool(SysDir.Buffer); ExFreePool(Reparse); return; } Status = ZwFsControlFile(ReparseHandle, NULL, NULL, NULL, &IoStatusBlock, FSCTL_SET_REPARSE_POINT, Reparse, Size, NULL, 0); } if (skip(NT_SUCCESS(Status), "Creating symlink failed: %lx\n", Status)) { ZwSetInformationFile(ReparseHandle, &IoStatusBlock, &ToDelete, sizeof(ToDelete), FileDispositionInformation); ZwClose(ReparseHandle); ExFreePool(Regedit.Buffer); ExFreePool(Foobar.Buffer); ExFreePool(SysDir.Buffer); ExFreePool(Reparse); return; } ZwClose(ReparseHandle); Status = ZwCreateFile(&ReparseHandle, GENERIC_READ, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL, 0); ok(Status == STATUS_SUCCESS || /* Windows Vista+ */ Status == STATUS_IO_REPARSE_TAG_NOT_HANDLED, /* Windows 2003 (SP1, SP2) */ "ZwCreateFile returned unexpected status: %lx\n", Status); if (NT_SUCCESS(Status)) { Status = ObReferenceObjectByHandle(ReparseHandle, FILE_READ_DATA, *IoFileObjectType, UserMode, (PVOID *)&FileObject, NULL); ok_eq_hex(Status, STATUS_SUCCESS); if (NT_SUCCESS(Status)) { ok(RtlCompareUnicodeString(&Regedit, &FileObject->FileName, TRUE) == 0, "Expected: %wZ. Opened: %wZ\n", &Regedit, &FileObject->FileName); ObDereferenceObject(FileObject); } ZwClose(ReparseHandle); } ExFreePool(Regedit.Buffer); Status = IoCreateFile(&ReparseHandle, GENERIC_READ, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL, 0, CreateFileTypeNone, NULL, IO_NO_PARAMETER_CHECKING | IO_STOP_ON_SYMLINK); ok(Status == STATUS_STOPPED_ON_SYMLINK || /* Windows Vista+ */ Status == STATUS_IO_REPARSE_TAG_NOT_HANDLED, /* Windows 2003 (SP1, SP2) */ "ZwCreateFile returned unexpected status: %lx\n", Status); if (NT_SUCCESS(Status)) { ZwClose(ReparseHandle); } Status = ZwCreateFile(&ReparseHandle, GENERIC_READ | GENERIC_WRITE | DELETE, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_OPEN_REPARSE_POINT | FILE_OPEN_FOR_BACKUP_INTENT, NULL, 0); if (skip(NT_SUCCESS(Status), "Creating opening reparse point: %lx\n", Status)) { Status = ZwOpenFile(&ReparseHandle, DELETE, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_DELETE, FILE_NON_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE); ok_eq_hex(Status, STATUS_SUCCESS); ZwClose(ReparseHandle); ExFreePool(Foobar.Buffer); ExFreePool(SysDir.Buffer); ExFreePool(Reparse); return; } Status = ObReferenceObjectByHandle(ReparseHandle, FILE_READ_DATA, *IoFileObjectType, UserMode, (PVOID *)&FileObject, NULL); ok_eq_hex(Status, STATUS_SUCCESS); if (NT_SUCCESS(Status)) { ok(RtlCompareUnicodeString(&Foobar, &FileObject->FileName, TRUE) == 0, "Expected: %wZ. Opened: %wZ\n", &Foobar, &FileObject->FileName); ObDereferenceObject(FileObject); } ExFreePool(Foobar.Buffer); RtlZeroMemory(Reparse, Size); Status = ZwFsControlFile(ReparseHandle, NULL, NULL, NULL, &IoStatusBlock, FSCTL_GET_REPARSE_POINT, NULL, 0, Reparse, Size); ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_hex(IoStatusBlock.Information, Size); if (NT_SUCCESS(Status)) { PWSTR Buffer; UNICODE_STRING ReparsePath, FullPath; ok_eq_hex(Reparse->ReparseTag, IO_REPARSE_TAG_SYMLINK); ok_eq_hex(Reparse->ReparseDataLength, 12 + SysDir.Length * 2 + sizeof(L"\\regedit.exe") * 2 - sizeof(L"\\??\\") - sizeof(UNICODE_NULL)); ok_eq_hex(Reparse->SymbolicLinkReparseBuffer.Flags, 0); FullPath.Length = 0; FullPath.MaximumLength = SysDir.Length + sizeof(L"\\regedit.exe") - sizeof(UNICODE_NULL); Buffer = FullPath.Buffer = ExAllocatePool(NonPagedPool, FullPath.MaximumLength); if (!skip(Buffer != NULL, "Memory allocation failed!\n")) { RtlCopyUnicodeString(&FullPath, &SysDir); RtlCopyMemory(&FullPath.Buffer[FullPath.Length / sizeof(WCHAR)], L"\\regedit.exe", sizeof(L"\\regedit.exe") - sizeof(UNICODE_NULL)); FullPath.Length += (sizeof(L"\\regedit.exe") - sizeof(UNICODE_NULL)); ReparsePath.Buffer = (PWSTR)((ULONG_PTR)Reparse->SymbolicLinkReparseBuffer.PathBuffer + Reparse->SymbolicLinkReparseBuffer.SubstituteNameOffset); ReparsePath.Length = ReparsePath.MaximumLength = Reparse->SymbolicLinkReparseBuffer.SubstituteNameLength; ok(RtlCompareUnicodeString(&ReparsePath, &FullPath, TRUE) == 0, "Expected: %wZ. Got: %wZ\n", &ReparsePath, &FullPath); FullPath.Length -= (sizeof(L"\\??\\") - sizeof(UNICODE_NULL)); FullPath.MaximumLength -= (sizeof(L"\\??\\") - sizeof(UNICODE_NULL)); FullPath.Buffer = (PWSTR)((ULONG_PTR)Buffer + sizeof(L"\\??\\") - sizeof(UNICODE_NULL)); ReparsePath.Buffer = (PWSTR)((ULONG_PTR)Reparse->SymbolicLinkReparseBuffer.PathBuffer + Reparse->SymbolicLinkReparseBuffer.PrintNameOffset); ReparsePath.Length = ReparsePath.MaximumLength = Reparse->SymbolicLinkReparseBuffer.PrintNameLength; ok(RtlCompareUnicodeString(&ReparsePath, &FullPath, TRUE) == 0, "Expected: %wZ. Got: %wZ\n", &ReparsePath, &FullPath); ExFreePool(Buffer); } } ExFreePool(SysDir.Buffer); ExFreePool(Reparse); ZwSetInformationFile(ReparseHandle, &IoStatusBlock, &ToDelete, sizeof(ToDelete), FileDispositionInformation); ZwClose(ReparseHandle); }
NTSTATUS NTAPI CmpOpenHiveFiles(IN PCUNICODE_STRING BaseName, IN PCWSTR Extension OPTIONAL, OUT PHANDLE Primary, OUT PHANDLE Log, OUT PULONG PrimaryDisposition, OUT PULONG LogDisposition, IN BOOLEAN CreateAllowed, IN BOOLEAN MarkAsSystemHive, IN BOOLEAN NoBuffering, OUT PULONG ClusterSize OPTIONAL) { HANDLE EventHandle; PKEVENT Event; NTSTATUS Status; UNICODE_STRING FullName, ExtensionName; PWCHAR NameBuffer; USHORT Length; OBJECT_ATTRIBUTES ObjectAttributes; IO_STATUS_BLOCK IoStatusBlock; ULONG AttributeFlags, ShareMode, DesiredAccess, CreateDisposition, IoFlags; USHORT CompressionState; FILE_STANDARD_INFORMATION FileInformation; FILE_FS_SIZE_INFORMATION FsSizeInformation; /* Create event */ Status = CmpCreateEvent(NotificationEvent, &EventHandle, &Event); if (!NT_SUCCESS(Status)) return Status; /* Initialize the full name */ RtlInitEmptyUnicodeString(&FullName, NULL, 0); Length = BaseName->Length; /* Check if we have an extension */ if (Extension) { /* Update the name length */ Length += (USHORT)wcslen(Extension) * sizeof(WCHAR) + sizeof(UNICODE_NULL); /* Allocate the buffer for the full name */ NameBuffer = ExAllocatePoolWithTag(PagedPool, Length, TAG_CM); if (!NameBuffer) { /* Fail */ ObDereferenceObject(Event); ZwClose(EventHandle); return STATUS_NO_MEMORY; } /* Build the full name */ FullName.Buffer = NameBuffer; FullName.MaximumLength = Length; RtlAppendUnicodeStringToString(&FullName, BaseName); } else { /* The base name is the full name */ FullName = *BaseName; NameBuffer = NULL; } /* Initialize the attributes */ InitializeObjectAttributes(&ObjectAttributes, &FullName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); /* Check if we can create the hive */ if ((CreateAllowed) && !(CmpShareSystemHives)) { /* Open only or create */ CreateDisposition = FILE_OPEN_IF; } else { /* Open only */ CreateDisposition = FILE_OPEN; } /* Setup the flags */ // FIXME : FILE_OPEN_FOR_BACKUP_INTENT is unimplemented and breaks 3rd stage boot IoFlags = //FILE_OPEN_FOR_BACKUP_INTENT | FILE_NO_COMPRESSION | FILE_RANDOM_ACCESS | (NoBuffering ? FILE_NO_INTERMEDIATE_BUFFERING : 0); /* Set share and access modes */ if ((CmpMiniNTBoot) && (CmpShareSystemHives)) { /* We're on Live CD or otherwise sharing */ DesiredAccess = FILE_READ_DATA; ShareMode = FILE_SHARE_READ; } else { /* We want to write exclusively */ ShareMode = 0; DesiredAccess = FILE_READ_DATA | FILE_WRITE_DATA; } /* Default attributes */ AttributeFlags = FILE_ATTRIBUTE_NORMAL; /* Now create the file */ Status = ZwCreateFile(Primary, DesiredAccess | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, AttributeFlags, ShareMode, CreateDisposition, FILE_SYNCHRONOUS_IO_NONALERT | IoFlags, NULL, 0); /* Check if anything failed until now */ if (!NT_SUCCESS(Status)) { /* Close handles and free buffers */ if (NameBuffer) ExFreePoolWithTag(NameBuffer, TAG_CM); ObDereferenceObject(Event); ZwClose(EventHandle); DPRINT1("ZwCreateFile failed : %lx.\n", Status); *Primary = NULL; return Status; } if (MarkAsSystemHive) { /* We opened it, mark it as a system hive */ Status = ZwFsControlFile(*Primary, EventHandle, NULL, NULL, &IoStatusBlock, FSCTL_MARK_AS_SYSTEM_HIVE, NULL, 0, NULL, 0); if (Status == STATUS_PENDING) { /* Wait for completion */ KeWaitForSingleObject(Event, Executive, KernelMode, FALSE, NULL); Status = IoStatusBlock.Status; } /* If we don't support it, ignore the failure */ if (Status == STATUS_INVALID_DEVICE_REQUEST) Status = STATUS_SUCCESS; if (!NT_SUCCESS(Status)) { /* Close handles and free buffers */ if (NameBuffer) ExFreePoolWithTag(NameBuffer, TAG_CM); ObDereferenceObject(Event); ZwClose(EventHandle); ZwClose(*Primary); *Primary = NULL; return Status; } } /* Disable compression */ CompressionState = 0; Status = ZwFsControlFile(*Primary, EventHandle, NULL, NULL, &IoStatusBlock, FSCTL_SET_COMPRESSION, &CompressionState, sizeof(CompressionState), NULL, 0); if (Status == STATUS_PENDING) { /* Wait for completion */ KeWaitForSingleObject(Event, Executive, KernelMode, FALSE, NULL); } /* Get the disposition */ *PrimaryDisposition = (ULONG)IoStatusBlock.Information; if (IoStatusBlock.Information != FILE_CREATED) { /* Check how large the file is */ Status = ZwQueryInformationFile(*Primary, &IoStatusBlock, &FileInformation, sizeof(FileInformation), FileStandardInformation); if (NT_SUCCESS(Status)) { /* Check if it's 0 bytes */ if (!FileInformation.EndOfFile.QuadPart) { /* Assume it's a new file */ *PrimaryDisposition = FILE_CREATED; } } } /* Check if the caller wants cluster size returned */ if (ClusterSize) { /* Query it */ Status = ZwQueryVolumeInformationFile(*Primary, &IoStatusBlock, &FsSizeInformation, sizeof(FsSizeInformation), FileFsSizeInformation); if (!NT_SUCCESS(Status)) { /* Close handles and free buffers */ if (NameBuffer) ExFreePoolWithTag(NameBuffer, TAG_CM); ObDereferenceObject(Event); ZwClose(EventHandle); return Status; } /* Check if the sector size is invalid */ if (FsSizeInformation.BytesPerSector > HBLOCK_SIZE) { /* Close handles and free buffers */ if (NameBuffer) ExFreePoolWithTag(NameBuffer, TAG_CM); ObDereferenceObject(Event); ZwClose(EventHandle); return STATUS_CANNOT_LOAD_REGISTRY_FILE; } /* Return cluster size */ *ClusterSize = max(1, FsSizeInformation.BytesPerSector / HSECTOR_SIZE); } /* Check if we don't need to create a log file */ if (!Extension) { /* We're done, close handles */ ObDereferenceObject(Event); ZwClose(EventHandle); return STATUS_SUCCESS; } /* Check if we can create the hive */ CreateDisposition = CmpShareSystemHives ? FILE_OPEN : FILE_OPEN_IF; if (*PrimaryDisposition == FILE_CREATED) { /* Over-write the existing log file, since this is a new hive */ CreateDisposition = FILE_SUPERSEDE; } /* Setup the name */ RtlInitUnicodeString(&ExtensionName, Extension); RtlAppendUnicodeStringToString(&FullName, &ExtensionName); /* Initialize the attributes */ InitializeObjectAttributes(&ObjectAttributes, &FullName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); /* Setup the flags */ IoFlags = FILE_NO_COMPRESSION | FILE_NO_INTERMEDIATE_BUFFERING; /* Check if this is a log file */ if (!_wcsnicmp(Extension, L".log", 4)) { /* Hide log files */ AttributeFlags |= FILE_ATTRIBUTE_HIDDEN; } /* Now create the file */ Status = ZwCreateFile(Log, DesiredAccess, &ObjectAttributes, &IoStatusBlock, NULL, AttributeFlags, ShareMode, CreateDisposition, IoFlags, NULL, 0); if ((NT_SUCCESS(Status)) && (MarkAsSystemHive)) { /* We opened it, mark it as a system hive */ Status = ZwFsControlFile(*Log, EventHandle, NULL, NULL, &IoStatusBlock, FSCTL_MARK_AS_SYSTEM_HIVE, NULL, 0, NULL, 0); if (Status == STATUS_PENDING) { /* Wait for completion */ KeWaitForSingleObject(Event, Executive, KernelMode, FALSE, NULL); Status = IoStatusBlock.Status; } /* If we don't support it, ignore the failure */ if (Status == STATUS_INVALID_DEVICE_REQUEST) Status = STATUS_SUCCESS; /* If we failed, close the handle */ if (!NT_SUCCESS(Status)) ZwClose(*Log); } /* Check if anything failed until now */ if (!NT_SUCCESS(Status)) { /* Clear the handle */ *Log = NULL; } else { /* Disable compression */ Status = ZwFsControlFile(*Log, EventHandle, NULL, NULL, &IoStatusBlock, FSCTL_SET_COMPRESSION, &CompressionState, sizeof(CompressionState), NULL, 0); if (Status == STATUS_PENDING) { /* Wait for completion */ KeWaitForSingleObject(Event, Executive, KernelMode, FALSE, NULL); } /* Return the disposition */ *LogDisposition = (ULONG)IoStatusBlock.Information; } /* We're done, close handles and free buffers */ if (NameBuffer) ExFreePoolWithTag(NameBuffer, TAG_CM); ObDereferenceObject(Event); ZwClose(EventHandle); return STATUS_SUCCESS; }
NTSTATUS GetNextReparseVolumePath( IN HANDLE Handle, OUT PUNICODE_STRING Path ) /*++ Routine Description: This routine queries the reparse index for the next volume mount point. Arguments: Handle - Supplies the handle. Path - Returns the path. Return Value: NTSTATUS --*/ { NTSTATUS status; IO_STATUS_BLOCK ioStatus; FILE_REPARSE_POINT_INFORMATION reparseInfo; UNICODE_STRING fileId; OBJECT_ATTRIBUTES oa; HANDLE h; PREPARSE_DATA_BUFFER reparse; UNICODE_STRING volumeName; ULONG nameInfoSize; PFILE_NAME_INFORMATION nameInfo; for (;;) { status = ZwQueryDirectoryFile(Handle, NULL, NULL, NULL, &ioStatus, &reparseInfo, sizeof(reparseInfo), FileReparsePointInformation, TRUE, NULL, FALSE); if (!NT_SUCCESS(status)) { return status; } if (reparseInfo.Tag != IO_REPARSE_TAG_MOUNT_POINT) { continue; } fileId.Length = sizeof(reparseInfo.FileReference); fileId.MaximumLength = fileId.Length; fileId.Buffer = (PWSTR) &reparseInfo.FileReference; InitializeObjectAttributes(&oa, &fileId, 0, Handle, NULL); status = ZwOpenFile(&h, SYNCHRONIZE | FILE_GENERIC_READ, &oa, &ioStatus, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN_BY_FILE_ID | FILE_OPEN_REPARSE_POINT | FILE_SYNCHRONOUS_IO_ALERT); if (!NT_SUCCESS(status)) { continue; } reparse = ExAllocatePool(PagedPool, MAXIMUM_REPARSE_DATA_BUFFER_SIZE); if (!reparse) { ZwClose(h); return STATUS_INSUFFICIENT_RESOURCES; } status = ZwFsControlFile(h, NULL, NULL, NULL, &ioStatus, FSCTL_GET_REPARSE_POINT, NULL, 0, reparse, MAXIMUM_REPARSE_DATA_BUFFER_SIZE); if (!NT_SUCCESS(status)) { ExFreePool(reparse); ZwClose(h); continue; } volumeName.Length = reparse->MountPointReparseBuffer.SubstituteNameLength - sizeof(WCHAR); volumeName.MaximumLength = volumeName.Length + sizeof(WCHAR); volumeName.Buffer = (PWCHAR) ((PCHAR) reparse->MountPointReparseBuffer.PathBuffer + reparse->MountPointReparseBuffer.SubstituteNameOffset); volumeName.Buffer[volumeName.Length/sizeof(WCHAR)] = 0; if (!IsVolumeName(&volumeName)) { ExFreePool(reparse); ZwClose(h); continue; } ExFreePool(reparse); nameInfoSize = 1024; nameInfo = ExAllocatePool(PagedPool, nameInfoSize); if (!nameInfo) { ZwClose(h); continue; } status = ZwQueryInformationFile(h, &ioStatus, nameInfo, nameInfoSize, FileNameInformation); ZwClose(h); if (!NT_SUCCESS(status)) { continue; } Path->Length = (USHORT) nameInfo->FileNameLength; Path->MaximumLength = Path->Length + sizeof(WCHAR); Path->Buffer = ExAllocatePool(PagedPool, Path->MaximumLength); if (!Path->Buffer) { ExFreePool(nameInfo); continue; } RtlCopyMemory(Path->Buffer, nameInfo->FileName, Path->Length); Path->Buffer[Path->Length/sizeof(WCHAR)] = 0; ExFreePool(nameInfo); break; } return status; }
NTSTATUS QueryDeviceNameForPath( IN PUNICODE_STRING Path, OUT PUNICODE_STRING DeviceName ) /*++ Routine Description: This routine returns the device name for the given path. It first checks to see if the path is a symbolic link and then checks to see if it is a volume reparse point. Arguments: Path - Supplies the path. DeviceName - Returns the device name. Return Value: NTSTATUS --*/ { NTSTATUS status; OBJECT_ATTRIBUTES oa; HANDLE h; IO_STATUS_BLOCK ioStatus; PREPARSE_DATA_BUFFER reparse; UNICODE_STRING volumeName; status = QuerySymbolicLink(Path, DeviceName); if (NT_SUCCESS(status)) { return status; } InitializeObjectAttributes(&oa, Path, OBJ_CASE_INSENSITIVE, 0, 0); status = ZwOpenFile(&h, SYNCHRONIZE | FILE_GENERIC_READ, &oa, &ioStatus, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN_REPARSE_POINT | FILE_SYNCHRONOUS_IO_ALERT); if (!NT_SUCCESS(status)) { return status; } reparse = ExAllocatePool(PagedPool, MAXIMUM_REPARSE_DATA_BUFFER_SIZE); if (!reparse) { ZwClose(h); return STATUS_INSUFFICIENT_RESOURCES; } status = ZwFsControlFile(h, NULL, NULL, NULL, &ioStatus, FSCTL_GET_REPARSE_POINT, NULL, 0, reparse, MAXIMUM_REPARSE_DATA_BUFFER_SIZE); ZwClose(h); if (!NT_SUCCESS(status)) { ExFreePool(reparse); return status; } volumeName.Length = reparse->MountPointReparseBuffer.SubstituteNameLength - sizeof(WCHAR); volumeName.MaximumLength = volumeName.Length + sizeof(WCHAR); volumeName.Buffer = (PWCHAR) ((PCHAR) reparse->MountPointReparseBuffer.PathBuffer + reparse->MountPointReparseBuffer.SubstituteNameOffset); volumeName.Buffer[volumeName.Length/sizeof(WCHAR)] = 0; status = QuerySymbolicLink(&volumeName, DeviceName); ExFreePool(reparse); return status; }
VOID VolDoThreadProc ( IN PVOLUME_DEVICE_OBJECT VolDo ) { BOOLEAN volDoThreadTerminate = FALSE; DebugTrace( 0, Dbg2, ("VolDoThreadProc: Start VolDo = %p\n", VolDo) ); VolDo_Reference( VolDo ); VolDo->Thread.Flags = VOLDO_THREAD_FLAG_INITIALIZING; ExAcquireFastMutex( &VolDo->FastMutex ); ClearFlag( VolDo->Thread.Flags, VOLDO_THREAD_FLAG_INITIALIZING ); SetFlag( VolDo->Thread.Flags, VOLDO_THREAD_FLAG_START ); ExReleaseFastMutex( &VolDo->FastMutex ); KeSetEvent( &VolDo->ReadyEvent, IO_DISK_INCREMENT, FALSE ); volDoThreadTerminate = FALSE; while (volDoThreadTerminate == FALSE) { PKEVENT events[2]; LONG eventCount; NTSTATUS eventStatus; LARGE_INTEGER timeOut; ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL ); eventCount = 0; events[eventCount++] = &VolDo->RequestEvent; timeOut.QuadPart = -NDNTFS_VOLDO_THREAD_FLAG_TIME_OUT; eventStatus = KeWaitForMultipleObjects( eventCount, events, WaitAny, Executive, KernelMode, TRUE, &timeOut, NULL ); if (eventStatus == STATUS_TIMEOUT) { LARGE_INTEGER currentTime; KeQuerySystemTime( ¤tTime ); if (FlagOn(VolDo->NdasNtfsFlags, NDAS_NTFS_DEVICE_FLAG_SHUTDOWN) || !(FlagOn(VolDo->NdasNtfsFlags, NDAS_NTFS_DEVICE_FLAG_MOUNTED) /*&& !FlagOn(LfsDeviceExt->Flags, LFS_DEVICE_STOP)*/)) { continue; } if ((VolDo->NetdiskEnableMode == NETDISK_READ_ONLY && (VolDo->TryFlushOrPurgeTime.QuadPart > currentTime.QuadPart || (currentTime.QuadPart - VolDo->TryFlushOrPurgeTime.QuadPart) >= NDNTFS_TRY_PURGE_DURATION)) || (VolDo->ReceiveWriteCommand == TRUE && (VolDo->TryFlushOrPurgeTime.QuadPart > currentTime.QuadPart || (currentTime.QuadPart - VolDo->TryFlushOrPurgeTime.QuadPart) >= NDNTFS_TRY_FLUSH_DURATION))) { if (VolDo->NetdiskEnableMode != NETDISK_READ_ONLY && (currentTime.QuadPart - VolDo->CommandReceiveTime.QuadPart) <= NDNTFS_TRY_FLUSH_DURATION /*&& (currentTime.QuadPart - VolDo->TryFlushOrPurgeTime.QuadPart) <= (100*NDNTFS_TRY_FLUSH_OR_PURGE_DURATION)*/) { continue; } do { HANDLE eventHandle = NULL; HANDLE fileHandle = NULL; ACCESS_MASK desiredAccess; ULONG attributes; OBJECT_ATTRIBUTES objectAttributes; IO_STATUS_BLOCK ioStatusBlock; LARGE_INTEGER allocationSize; ULONG fileAttributes; ULONG shareAccess; ULONG createDisposition; ULONG createOptions; PVOID eaBuffer; ULONG eaLength; NTSTATUS createStatus; NTSTATUS fileSystemControlStatus; PIRP topLevelIrp; PRIMARY_REQUEST_INFO primaryRequestInfo; ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL ); if (VolDo->NetdiskEnableMode == NETDISK_SECONDARY) { break; } DebugTrace( 0, Dbg2, ("VolDoThreadProc: VolDo = %p, VolDo->NetdiskPartitionInformation.VolumeName = %wZ\n", VolDo, &VolDo->NetdiskPartitionInformation.VolumeName) ); desiredAccess = SYNCHRONIZE | READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | FILE_WRITE_EA | FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_READ_EA; ASSERT( desiredAccess == 0x0012019F ); attributes = OBJ_KERNEL_HANDLE; attributes |= OBJ_CASE_INSENSITIVE; InitializeObjectAttributes( &objectAttributes, &VolDo->NetdiskPartitionInformation.VolumeName, attributes, NULL, NULL ); allocationSize.LowPart = 0; allocationSize.HighPart = 0; fileAttributes = 0; shareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE; createDisposition = FILE_OPEN; createOptions = FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE; eaBuffer = NULL; eaLength = 0; RtlZeroMemory( &ioStatusBlock, sizeof(ioStatusBlock) ); createStatus = ZwCreateFile( &fileHandle, desiredAccess, &objectAttributes, &ioStatusBlock, &allocationSize, fileAttributes, shareAccess, createDisposition, createOptions, eaBuffer, eaLength ); if (createStatus != STATUS_SUCCESS) break; ASSERT( ioStatusBlock.Information == FILE_OPENED); createStatus = ZwCreateEvent( &eventHandle, GENERIC_READ, NULL, SynchronizationEvent, FALSE ); if (createStatus != STATUS_SUCCESS) { ASSERT( NDASNTFS_UNEXPECTED ); ZwClose( fileHandle ); break; } primaryRequestInfo.PrimaryTag = 0xe2027482; primaryRequestInfo.PrimarySessionId = NDASNTFS_LOCAL_PRMARY_SESSION_ID; primaryRequestInfo.PrimarySession = NULL; primaryRequestInfo.NdfsWinxpRequestHeader = NULL; topLevelIrp = IoGetTopLevelIrp(); ASSERT( topLevelIrp == NULL ); IoSetTopLevelIrp( (PIRP)&primaryRequestInfo ); RtlZeroMemory( &ioStatusBlock, sizeof(ioStatusBlock) ); fileSystemControlStatus = ZwFsControlFile( fileHandle, NULL, //&eventHandle, NULL, NULL, &ioStatusBlock, (VolDo->NetdiskEnableMode == NETDISK_READ_ONLY) ? FSCTL_NDAS_FS_PURGE : FSCTL_NDAS_FS_FLUSH, NULL, 0, NULL, 0 ); DebugTrace( 0, Dbg2, ("VolDoThreadProc: VolDo = %p, createStatus = %x, ioStatusBlock = %x\n", VolDo, fileSystemControlStatus, ioStatusBlock.Information) ); if (fileSystemControlStatus == STATUS_PENDING) { LARGE_INTEGER timeOut; timeOut.QuadPart = -3*NANO100_PER_SEC; ASSERT( FALSE ); //fileSystemControlStatus = ZwWaitForSingleObject( eventHandle, TRUE,NULL /*, &timeOut*/ ); } IoSetTopLevelIrp( topLevelIrp ); if (fileSystemControlStatus != STATUS_SUCCESS) DebugTrace( 0, Dbg2, ("VolDoThreadProc: VolDo = %p, fileSystemControlStatus = %x, ioStatusBlock = %x\n", VolDo, fileSystemControlStatus, ioStatusBlock.Information) ); ZwClose( eventHandle ); ZwClose( fileHandle ); break; } while (0); KeQuerySystemTime( &VolDo->TryFlushOrPurgeTime ); VolDo->ReceiveWriteCommand = FALSE; } continue; } ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL ); ASSERT( eventCount < THREAD_WAIT_OBJECTS ); if (!NT_SUCCESS( eventStatus ) || eventStatus >= eventCount) { ASSERT( NDASNTFS_UNEXPECTED ); SetFlag( VolDo->Thread.Flags, VOLDO_THREAD_FLAG_ERROR ); volDoThreadTerminate = TRUE; continue; } KeClearEvent( events[eventStatus] ); if (eventStatus == 0) { volDoThreadTerminate = TRUE; break; } else { NDAS_ASSERT( NDASNTFS_BUG ); } } ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL ); ExAcquireFastMutex( &VolDo->FastMutex ); SetFlag( VolDo->Thread.Flags, VOLDO_THREAD_FLAG_STOPED ); ExReleaseFastMutex( &VolDo->FastMutex ); DebugTrace( 0, Dbg2, ("VolDoThreadProc: PsTerminateSystemThread VolDo = %p\n", VolDo) ); ExAcquireFastMutex( &VolDo->FastMutex ); SetFlag( VolDo->Thread.Flags, VOLDO_THREAD_FLAG_TERMINATED ); ExReleaseFastMutex( &VolDo->FastMutex ); VolDo_Dereference( VolDo ); ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL ); PsTerminateSystemThread( STATUS_SUCCESS ); }
typedef struct _OC_CR_SECTION_VIEW{ // // the start and end adress in the system process // ULONG_PTR BaseAddress; ULONG_PTR EndAddress; // // where the mapped view starts in a file // ULARGE_INTEGER ViewStartInFile; // // where the mapped view ends in a file // ULARGE_INTEGER ViewEndInFile; // // the current pointer // ULONG_PTR CurrentPointer; // // a referenced section object // POC_CR_MAPPED_FILE_SECTION FileSectionObject; } //-------------------------------------------------- NTSTATUS OcCrCreateShadowFile( IN PUNICODE_STRING FileName, IN PULARGE_INTEGER ThresholdFileSize, IN PKEVENT ReferencedServiceEvent OPTIONAL, IN PKEVENT ReferencedEventToSetWhenReleasingFile OPTIONAL, IN PULARGE_INTEGER MaximumSizeDueToQuota OPTIONAL ) { NTSTATUS RC = STATUS_SUCCESS; OBJECT_ATTRIBUTES ObjectAttributes; IO_STATUS_BLOCK IoStatus; HANDLE FileHandle = NULL; PFILE_OBJECT FileObject = NULL; USHORT usCompressionFormat = COMPRESSION_FORMAT_NONE; HANDLE EventHandle; PKEVENT EventObject; BOOLEAN UseCache = FALSE; ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL ); // // align the maximum size to the page boundary, this restriction // is imposed by our proprietary cache // if( NULL != MaximumSizeDueToQuota ){ MaximumSizeDueToQuota->LowPart = MaximumSizeDueToQuota->LowPart & ~( PAGE_SIZE - 0x1 ); } // // always use fast write! // UseCache = TRUE;//!( g_ShadowLevel > ShadowLevelBase ); //RtlInitUnicodeString( &uFileName, L"\\DosDevices\\C:\\shadow_pio.dat" ); InitializeObjectAttributes( &ObjectAttributes, FileName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL ); // // TO DO - Protect file from changing attributes and other file information. // RC = ZwCreateFile( &FileHandle, GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, &ObjectAttributes, &IoStatus, NULL, FILE_ATTRIBUTE_NORMAL, 0x0,// sharing is disabled FILE_SUPERSEDE,// replace the file if exist, because we must be the first and the last file owner FILE_NON_DIRECTORY_FILE | FILE_RANDOM_ACCESS | FILE_NO_COMPRESSION | ( UseCache ? 0x0 : FILE_NO_INTERMEDIATE_BUFFERING ), NULL, 0 ); ASSERT( RC != STATUS_PENDING ); if( !NT_SUCCESS( RC ) ) goto __exit; EventObject = IoCreateSynchronizationEvent( NULL, &EventHandle ); if( NULL != EventObject ){ // // Event is created in the signal state // KeResetEvent( EventObject ); // // disable the compression // RC = ZwFsControlFile( FileHandle, EventHandle,//Event NULL,//Apc NULL,//Apc Context &IoStatus, FSCTL_SET_COMPRESSION, &usCompressionFormat, sizeof( usCompressionFormat ), NULL, 0 ); if( STATUS_PENDING == RC ){ KeWaitForSingleObject( EventObject, Executive, KernelMode, FALSE, NULL ); }//if( STATUS_PENDING == RC ) ZwClose( EventHandle ); }//if( NULL != EventObject ){ // // the FSD may not support the compression set request // or the event creation failed, in any case I set // FILE_NO_COMPRESSION attribute, hope this is enough. // RC = STATUS_SUCCESS; RC = ObReferenceObjectByHandle( FileHandle, FILE_ANY_ACCESS, *IoFileObjectType, KernelMode, //to avoid a security check set mode to Kernel (PVOID *)&FileObject, NULL ); ASSERT( NT_SUCCESS( RC ) ); if( !NT_SUCCESS( RC ) ) goto __exit; RC = DldSetNewBuffersFile( FileHandle, FileObject, ThresholdFileSize, ReferencedServiceEvent, ReferencedEventToSetWhenReleasingFile, MaximumSizeDueToQuota ); // // Set file handle to NULL, because it has been grabed by // the DldSetNewBuffersFile and will be closed // when it is no longer needed. // FileHandle = NULL; if( !NT_SUCCESS( RC ) ) goto __exit; __exit: ASSERT( NT_SUCCESS( RC ) ); if( !NT_SUCCESS( RC ) ){ if( NULL != FileObject ){ ObDereferenceObject( FileObject ); } if( NULL != FileHandle ){ ZwClose( FileHandle ); } } else { ASSERT( NULL == FileHandle ); ASSERT( FileObject ); ObDereferenceObject( FileObject ); } return RC; }
/* this routine process unmounting the device unmount options: UM_NOFSCTL - unmount without reporting to FS UM_FORCE - force unmounting */ int dc_process_unmount(dev_hook *hook, int opt) { IO_STATUS_BLOCK iosb; NTSTATUS status; HANDLE h_dev = NULL; int locked = 0; int resl; DbgMsg("dc_process_unmount, dev=%ws\n", hook->dev_name); if ((hook->flags & F_ENABLED) == 0) { return ST_NO_MOUNT; } wait_object_infinity(&hook->busy_lock); if ((hook->flags & F_ENABLED) == 0) { resl = ST_NO_MOUNT; goto cleanup; } do { if (hook->flags & F_FORMATTING) { dc_format_done(hook->dev_name); } if ( !(hook->flags & F_SYSTEM) && !(opt & MF_NOFSCTL) ) { h_dev = io_open_device(hook->dev_name); if ( (h_dev == NULL) && !(opt & MF_FORCE) ) { resl = ST_LOCK_ERR; break; } if (h_dev != NULL) { status = ZwFsControlFile(h_dev, NULL, NULL, NULL, &iosb, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0); if ( (NT_SUCCESS(status) == FALSE) && !(opt & MF_FORCE) ) { resl = ST_LOCK_ERR; break; } locked = (NT_SUCCESS(status) != FALSE); ZwFsControlFile(h_dev, NULL, NULL, NULL, &iosb, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0); } } if ((opt & MF_NOSYNC) == 0) { // temporary disable IRP processing hook->flags |= F_DISABLE; // wait for pending IRPs completion if ((opt & MF_NOWAIT_IO) == 0) { while (hook->remove_lock.Common.IoCount > 1) dc_delay(20); } if (hook->flags & F_SYNC) { // send signal to syncronous mode thread dc_send_sync_packet(hook->dev_name, S_OP_FINALIZE, 0); } } hook->flags &= ~F_CLEAR_ON_UNMOUNT; hook->use_size = hook->dsk_size; hook->tmp_size = 0; hook->mnt_flags = 0; resl = ST_OK; // increment mount changes counter lock_inc(&hook->chg_mount); // free encryption key if (hook->dsk_key != NULL) { mm_secure_free(hook->dsk_key); hook->dsk_key = NULL; } if ( !(opt & MF_NOSYNC) ) { /* enable IRP processing */ hook->flags &= ~F_DISABLE; } } while (0); if (h_dev != NULL) { if (locked != 0) { ZwFsControlFile(h_dev, NULL, NULL, NULL, &iosb, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0); } ZwClose(h_dev); } cleanup: KeReleaseMutex(&hook->busy_lock, FALSE); return resl; }
NTSTATUS GetVolumeInformation ( IN PPRIMARY_SESSION PrimarySession, IN PUNICODE_STRING VolumeName ) { HANDLE volumeHandle = NULL; ACCESS_MASK desiredAccess; ULONG attributes; OBJECT_ATTRIBUTES objectAttributes; IO_STATUS_BLOCK ioStatusBlock; LARGE_INTEGER allocationSize; ULONG fileAttributes; ULONG shareAccess; ULONG createDisposition; ULONG createOptions; PVOID eaBuffer; ULONG eaLength; NTSTATUS createStatus; NTSTATUS fsControlStatus; NTFS_VOLUME_DATA_BUFFER ntfsVolumeDataBuffer; #if DBG #else UNREFERENCED_PARAMETER( PrimarySession ); #endif desiredAccess = SYNCHRONIZE | READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | FILE_WRITE_EA | FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_READ_EA; ASSERT( desiredAccess == 0x0012019F ); attributes = OBJ_KERNEL_HANDLE; attributes |= OBJ_CASE_INSENSITIVE; InitializeObjectAttributes( &objectAttributes, VolumeName, attributes, NULL, NULL ); allocationSize.LowPart = 0; allocationSize.HighPart = 0; fileAttributes = 0; shareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE; createDisposition = FILE_OPEN; createOptions = FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE; eaBuffer = NULL; eaLength = 0; RtlZeroMemory(&ioStatusBlock, sizeof(ioStatusBlock)); SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE, ("GetVolumeInformation: PrimarySession = %p\n", PrimarySession) ); createStatus = ZwCreateFile( &volumeHandle, desiredAccess, &objectAttributes, &ioStatusBlock, &allocationSize, fileAttributes, shareAccess, createDisposition, createOptions, eaBuffer, eaLength ); SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE, ("GetVolumeInformation: PrimarySession = %p ZwCreateFile volumeHandle =%p, createStatus = %X, ioStatusBlock = %X\n", PrimarySession, volumeHandle, createStatus, ioStatusBlock.Information) ); if (!(createStatus == STATUS_SUCCESS)) { return STATUS_UNSUCCESSFUL; } else { ASSERT( ioStatusBlock.Information == FILE_OPENED ); } RtlZeroMemory( &ioStatusBlock, sizeof(ioStatusBlock) ); fsControlStatus = ZwFsControlFile( volumeHandle, NULL, NULL, NULL, &ioStatusBlock, FSCTL_GET_NTFS_VOLUME_DATA, NULL, 0, &ntfsVolumeDataBuffer, sizeof(ntfsVolumeDataBuffer) ); SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE, ("GetFileRecordSegmentHeader: FSCTL_GET_NTFS_VOLUME_DATA: volumeHandle %p, fsControlStatus = %x, ioStatusBlock.Status = %x, ioStatusBlock.Information = %d\n", volumeHandle, fsControlStatus, ioStatusBlock.Status, ioStatusBlock.Information) ); if (NT_SUCCESS(fsControlStatus)) { ASSERT( fsControlStatus == STATUS_SUCCESS ); ASSERT( fsControlStatus == ioStatusBlock.Status ); } if (fsControlStatus == STATUS_BUFFER_OVERFLOW) ASSERT( ioStatusBlock.Information == sizeof(ntfsVolumeDataBuffer) ); if (!(fsControlStatus == STATUS_SUCCESS || fsControlStatus == STATUS_BUFFER_OVERFLOW)) { ioStatusBlock.Information = 0; ASSERT(ioStatusBlock.Information == 0); } if (!NT_SUCCESS(fsControlStatus)) { PrimarySession->Thread.BytesPerFileRecordSegment = 0; PrimarySession->Thread.BytesPerSector = 0; PrimarySession->Thread.BytesPerCluster = 0; ZwClose(volumeHandle); return STATUS_SUCCESS; } SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE, ("ntfsVolumeDataBuffer->VolumeSerialNumber.QuadPart = %I64u\n", ntfsVolumeDataBuffer.VolumeSerialNumber.QuadPart) ); SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE, ("ntfsVolumeDataBuffer->NumberSectors.QuadPart = %I64u\n", ntfsVolumeDataBuffer.NumberSectors.QuadPart) ); SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE, ("ntfsVolumeDataBuffer->TotalClusters.QuadPart = %I64u\n", ntfsVolumeDataBuffer.TotalClusters.QuadPart) ); SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE, ("ntfsVolumeDataBuffer->FreeClusters.QuadPart = %I64u\n", ntfsVolumeDataBuffer.FreeClusters.QuadPart) ); SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE, ("ntfsVolumeDataBuffer->TotalReserved.QuadPart = %I64u\n", ntfsVolumeDataBuffer.TotalReserved.QuadPart) ); SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE, ("ntfsVolumeDataBuffer->BytesPerSector = %u\n", ntfsVolumeDataBuffer.BytesPerSector) ); SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE, ("ntfsVolumeDataBuffer->BytesPerCluster = %u\n", ntfsVolumeDataBuffer.BytesPerCluster) ); SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE, ("ntfsVolumeDataBuffer->BytesPerFileRecordSegment = %u\n", ntfsVolumeDataBuffer.BytesPerFileRecordSegment) ); SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE, ("ntfsVolumeDataBuffer->ClustersPerFileRecordSegment = %u\n", ntfsVolumeDataBuffer.ClustersPerFileRecordSegment) ); SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE, ("ntfsVolumeDataBuffer->MftValidDataLength.QuadPart = %I64u\n", ntfsVolumeDataBuffer.MftValidDataLength.QuadPart) ); SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE, ("ntfsVolumeDataBuffer->MftStartLcn.QuadPart = %I64u\n", ntfsVolumeDataBuffer.MftStartLcn.QuadPart) ); SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE, ("ntfsVolumeDataBuffer->MftZoneStart.QuadPart = %I64u\n", ntfsVolumeDataBuffer.MftZoneStart.QuadPart) ); SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE, ("ntfsVolumeDataBuffer->MftZoneEnd.QuadPart = %I64u\n", ntfsVolumeDataBuffer.MftZoneEnd.QuadPart) ); PrimarySession->Thread.BytesPerFileRecordSegment = ntfsVolumeDataBuffer.BytesPerFileRecordSegment; PrimarySession->Thread.BytesPerSector = ntfsVolumeDataBuffer.BytesPerSector; PrimarySession->Thread.BytesPerCluster = ntfsVolumeDataBuffer.BytesPerCluster; ZwClose( volumeHandle ); return STATUS_SUCCESS; }
NTSTATUS ReadonlyDismountVolume ( IN PLFS_DEVICE_EXTENSION LfsDeviceExt ) { NTSTATUS status; HANDLE eventHandle; HANDLE fileHandle = NULL; ACCESS_MASK desiredAccess; ULONG attributes; OBJECT_ATTRIBUTES objectAttributes; IO_STATUS_BLOCK ioStatusBlock; LARGE_INTEGER allocationSize; ULONG fileAttributes; ULONG shareAccess; ULONG createDisposition; ULONG createOptions; PVOID eaBuffer; ULONG eaLength; PIRP topLevelIrp; READONLY_REDIRECT_REQUEST readonlyRedirectRequest; ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL ); SPY_LOG_PRINT( LFS_DEBUG_READONLY_INFO, ("ReadonlyDismountVolume: LfsDeviceExt = %p, LfsDeviceExt->FileSystemType = %d LfsDeviceExt->Vpb->ReferenceCount = %d\n", LfsDeviceExt, LfsDeviceExt->FileSystemType, LfsDeviceExt->Vpb->ReferenceCount) ); desiredAccess = SYNCHRONIZE | READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES; desiredAccess |= FILE_WRITE_EA | FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_READ_EA; ASSERT( desiredAccess == 0x0012019F ); attributes = OBJ_KERNEL_HANDLE; attributes |= OBJ_CASE_INSENSITIVE; InitializeObjectAttributes( &objectAttributes, &LfsDeviceExt->NetdiskPartitionInformation.VolumeName, attributes, NULL, NULL ); allocationSize.LowPart = 0; allocationSize.HighPart = 0; fileAttributes = 0; shareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE; createDisposition = FILE_OPEN; createOptions = FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE; eaBuffer = NULL; eaLength = 0; RtlZeroMemory( &ioStatusBlock, sizeof(ioStatusBlock) ); topLevelIrp = IoGetTopLevelIrp(); ASSERT( topLevelIrp == NULL ); readonlyRedirectRequest.Tag = READONLY_REDIRECT_REQUEST_TAG; #if DBG readonlyRedirectRequest.DebugTag = READONLY_REDIRECT_REQUEST_TAG; #endif readonlyRedirectRequest.DevExt = CONTAINING_RECORD( LfsDeviceExt, FILESPY_DEVICE_EXTENSION, LfsDeviceExt ); readonlyRedirectRequest.OriginalTopLevelIrp = topLevelIrp; readonlyRedirectRequest.ReadonlyDismount = 1; IoSetTopLevelIrp( (PIRP)&readonlyRedirectRequest ); status = ZwCreateFile( &fileHandle, desiredAccess, &objectAttributes, &ioStatusBlock, &allocationSize, fileAttributes, shareAccess, createDisposition, createOptions, eaBuffer, eaLength ); ASSERT( readonlyRedirectRequest.DebugTag == (READONLY_REDIRECT_REQUEST_TAG - 4) ); IoSetTopLevelIrp( topLevelIrp ); SPY_LOG_PRINT( LFS_DEBUG_READONLY_TRACE, ("ReadonlyDismountVolume: LfsDeviceExt = %p ZwCreateFile fileHandle =%p, status = %X, ioStatusBlock = %X\n", LfsDeviceExt, fileHandle, status, ioStatusBlock.Information) ); if (status != STATUS_SUCCESS) { return status; } else { ASSERT( ioStatusBlock.Information == FILE_OPENED ); } do { status = ZwCreateEvent( &eventHandle, GENERIC_READ, NULL, SynchronizationEvent, FALSE ); if (status != STATUS_SUCCESS) { ASSERT( LFS_UNEXPECTED ); break; } RtlZeroMemory( &ioStatusBlock, sizeof(ioStatusBlock) ); topLevelIrp = IoGetTopLevelIrp(); ASSERT( topLevelIrp == NULL ); readonlyRedirectRequest.Tag = READONLY_REDIRECT_REQUEST_TAG; #if DBG readonlyRedirectRequest.DebugTag = READONLY_REDIRECT_REQUEST_TAG; #endif readonlyRedirectRequest.DevExt = CONTAINING_RECORD( LfsDeviceExt, FILESPY_DEVICE_EXTENSION, LfsDeviceExt ); readonlyRedirectRequest.OriginalTopLevelIrp = topLevelIrp; readonlyRedirectRequest.ReadonlyDismount = 1; IoSetTopLevelIrp( (PIRP)&readonlyRedirectRequest ); status = ZwFsControlFile( fileHandle, eventHandle, NULL, NULL, &ioStatusBlock, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0 ); if (status == STATUS_PENDING) { status = ZwWaitForSingleObject( eventHandle, TRUE, NULL ); if (status != STATUS_SUCCESS) { NDAS_ASSERT( FALSE ); } else { status = ioStatusBlock.Status; } } ASSERT( readonlyRedirectRequest.DebugTag == (READONLY_REDIRECT_REQUEST_TAG - 4) ); IoSetTopLevelIrp( topLevelIrp ); ZwClose( eventHandle ); if (status != STATUS_SUCCESS) { SPY_LOG_PRINT( LFS_DEBUG_READONLY_INFO, ("ReadonlyDismountVolume: LfsDeviceExt = %p ZwFsControlFile FSCTL_LOCK_VOLUME fileHandle =%p, status = %X, ioStatusBlock = %X\n", LfsDeviceExt, fileHandle, status, ioStatusBlock.Information) ); #if 0 status = ZwCreateEvent( &eventHandle, GENERIC_READ, NULL, SynchronizationEvent, FALSE ); if (status != STATUS_SUCCESS) { ASSERT( LFS_UNEXPECTED ); break; } RtlZeroMemory( &ioStatusBlock, sizeof(ioStatusBlock) ); status = ZwFsControlFile( fileHandle, eventHandle, NULL, NULL, &ioStatusBlock, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0 ); if (status == STATUS_PENDING) { status = ZwWaitForSingleObject( eventHandle, TRUE, NULL ); if (status != STATUS_SUCCESS) NDAS_ASSERT( FALSE ); else status = ioStatusBlock.Status; } ZwClose( eventHandle ); SPY_LOG_PRINT( LFS_DEBUG_READONLY_INFO, ("ReadonlyDismountVolume: LfsDeviceExt = %p ZwFsControlFile FSCTL_DISMOUNT_VOLUME fileHandle =%p, status = %X, ioStatusBlock = %X\n", LfsDeviceExt, fileHandle, status, ioStatusBlock.Information) ); if (status != STATUS_SUCCESS) { break; } break; #endif break; } status = ZwCreateEvent( &eventHandle, GENERIC_READ, NULL, SynchronizationEvent, FALSE ); if (status != STATUS_SUCCESS) { ASSERT( LFS_UNEXPECTED ); break; } RtlZeroMemory( &ioStatusBlock, sizeof(ioStatusBlock) ); readonlyRedirectRequest.Tag = READONLY_REDIRECT_REQUEST_TAG; #if DBG readonlyRedirectRequest.DebugTag = READONLY_REDIRECT_REQUEST_TAG; #endif readonlyRedirectRequest.DevExt = CONTAINING_RECORD( LfsDeviceExt, FILESPY_DEVICE_EXTENSION, LfsDeviceExt ); readonlyRedirectRequest.OriginalTopLevelIrp = topLevelIrp; readonlyRedirectRequest.ReadonlyDismount = 1; IoSetTopLevelIrp( (PIRP)&readonlyRedirectRequest ); status = ZwFsControlFile( fileHandle, eventHandle, NULL, NULL, &ioStatusBlock, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0 ); if (status == STATUS_PENDING) { status = ZwWaitForSingleObject( eventHandle, TRUE, NULL ); if (status != STATUS_SUCCESS) { NDAS_ASSERT( FALSE ); break; } status = ioStatusBlock.Status; } ASSERT( readonlyRedirectRequest.DebugTag == (READONLY_REDIRECT_REQUEST_TAG - 4) ); IoSetTopLevelIrp( topLevelIrp ); ZwClose( eventHandle ); if (status != STATUS_SUCCESS) { SPY_LOG_PRINT( LFS_DEBUG_READONLY_TRACE, ("ReadonlyDismountVolume: LfsDeviceExt = %p ZwFsControlFile FSCTL_UNLOCK_VOLUME fileHandle =%p, status = %X, ioStatusBlock = %X\n", LfsDeviceExt, fileHandle, status, ioStatusBlock.Information) ); break; } } while(0); ZwClose( fileHandle ); SPY_LOG_PRINT( LFS_DEBUG_READONLY_INFO, ("ReadonlyDismountVolume: LfsDeviceExt = %p status = %X\n", LfsDeviceExt, status) ); if (status != STATUS_SUCCESS) return status; #if 0 do { UNICODE_STRING fileName; PWCHAR fileNameBuffer; fileNameBuffer = ExAllocatePool(PagedPool,NDFS_MAX_PATH); if(GlobalLfs.ShutdownOccured == TRUE) break; RtlInitEmptyUnicodeString( &fileName, fileNameBuffer, NDFS_MAX_PATH ); RtlCopyUnicodeString( &fileName, &LfsDeviceExt->NetdiskPartitionInformation.VolumeName ); ioStatusBlock.Information = 0; status = RtlAppendUnicodeToString( &fileName, REMOUNT_VOLUME_FILE_NAME ); if (status != STATUS_SUCCESS) { ExFreePool( fileNameBuffer ); ASSERT( LFS_UNEXPECTED ); status = STATUS_SUCCESS; break; } desiredAccess = SYNCHRONIZE | READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | FILE_WRITE_EA; desiredAccess |= FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_READ_EA; ASSERT( desiredAccess == 0x0012019F ); attributes = OBJ_KERNEL_HANDLE; attributes |= OBJ_CASE_INSENSITIVE; InitializeObjectAttributes( &objectAttributes, &fileName, attributes, NULL, NULL ); allocationSize.LowPart = 0; allocationSize.HighPart = 0; fileAttributes = 0; shareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE; createDisposition = FILE_OPEN; createOptions = FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE; eaBuffer = NULL; eaLength = 0; status = ZwCreateFile( &fileHandle, desiredAccess, &objectAttributes, &ioStatusBlock, NULL, fileAttributes, shareAccess, createDisposition, createOptions, NULL, 0 ); SPY_LOG_PRINT( LFS_DEBUG_READONLY_TRACE, ("ReadonlyDismountVolume: New Volume Create %p %wZ, status = %x, ioStatusBlock.Information = %d\n", LfsDeviceExt, &LfsDeviceExt->NetdiskPartitionInformation.VolumeName, status, ioStatusBlock.Information) ); if (status == STATUS_SUCCESS) { ASSERT( ioStatusBlock.Information == FILE_OPENED ); ZwClose( fileHandle ); } else { NDAS_ASSERT( FALSE ); } status = STATUS_SUCCESS; ExFreePool( fileNameBuffer ); } while(0); #endif return status; }
NTSTATUS FileDiskCreateDataFile( __in PFILEDISK_EXTENSION FileDiskExtension, __in PUNICODE_STRING DataFilePath, __in PBOOLEAN NewDataFileCreated) { NTSTATUS status; OBJECT_ATTRIBUTES fileAttributes; HANDLE fileHandle; IO_STATUS_BLOCK ioStatus; LARGE_INTEGER allocationSize; FILE_END_OF_FILE_INFORMATION eof; PAGED_CODE(); InitializeObjectAttributes( &fileAttributes, DataFilePath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); allocationSize.QuadPart = 1; // initial size // // Open the existing file if any // status = ZwCreateFile( &fileHandle, GENERIC_ALL, &fileAttributes, &ioStatus, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN_IF, FILE_RANDOM_ACCESS | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if (!NT_SUCCESS(status)) { NdasPortTrace(FILEDISK_INIT, TRACE_LEVEL_ERROR, "ZwCreateFile(%wZ) failed: Status=%08X\n", DataFilePath, status); goto error1; } *NewDataFileCreated = (ioStatus.Information == FILE_CREATED); // // Set sparse file // if (FileDiskExtension->FileDiskFlags & FILEDISK_FLAG_USE_SPARSE_FILE) { status = ZwFsControlFile( fileHandle, NULL, NULL, NULL, &ioStatus, FSCTL_SET_SPARSE, NULL, 0, NULL, 0); if (!NT_SUCCESS(status)) { NdasPortTrace(FILEDISK_INIT, TRACE_LEVEL_ERROR, "FSCTL_SET_SPARSE failed, Status=%08X\n, IoStatus.Information=%X", status, (ULONG)ioStatus.Information); goto error2; } ZwWaitForSingleObject(fileHandle, FALSE, NULL); } // // Set the data file size (truncate or extend) // eof.EndOfFile.QuadPart = (FileDiskExtension->LogicalBlockAddress.QuadPart + 1) * FileDiskExtension->BytesPerBlock; status = ZwSetInformationFile( fileHandle, NULL, &eof, sizeof(FILE_END_OF_FILE_INFORMATION), FileEndOfFileInformation); if (!NT_SUCCESS(status)) { NdasPortTrace(FILEDISK_INIT, TRACE_LEVEL_ERROR, "ZwSetInformationFile failed, Status=%08X\n", status); goto error2; } FileDiskExtension->FileHandle = fileHandle; ObReferenceObjectByHandle( fileHandle, GENERIC_ALL, NULL, KernelMode, (PVOID*)&FileDiskExtension->FileObject, NULL); NdasPortTrace(FILEDISK_INIT, TRACE_LEVEL_INFORMATION, "FileDisk Data File %wZ created.\n", DataFilePath); return STATUS_SUCCESS; error2: ZwClose(fileHandle); if (*NewDataFileCreated) { FileDiskDeleteDataFile(DataFilePath); } error1: return status; }
NTSTATUS ImScsiSetFlagsDevice( __in pHW_HBA_EXT pHBAExt, __inout __deref PSRB_IMSCSI_SET_DEVICE_FLAGS device_flags, __inout __deref PKIRQL LowestAssumedIrql ) { NTSTATUS ntstatus = STATUS_SUCCESS; UCHAR status; pHW_LU_EXTENSION device_extension; status = ScsiGetLUExtension( pHBAExt, &device_extension, device_flags->DeviceNumber.PathId, device_flags->DeviceNumber.TargetId, device_flags->DeviceNumber.Lun, LowestAssumedIrql ); if ((status != SRB_STATUS_SUCCESS) | (device_extension == NULL)) return STATUS_OBJECT_NAME_NOT_FOUND; // It is not possible to make a file- or proxy virtual disk // writable on the fly. (A physical image file or the proxy // comm channel might not be opened for writing.) if (IMSCSI_READONLY(device_flags->FlagsToChange) && (device_extension->DeviceType != READ_ONLY_DIRECT_ACCESS_DEVICE) && device_extension->VMDisk) { device_extension->ReadOnly = FALSE; device_flags->FlagsToChange &= ~IMSCSI_OPTION_RO; } if (IMSCSI_REMOVABLE(device_flags->FlagsToChange) && (device_extension->DeviceType != READ_ONLY_DIRECT_ACCESS_DEVICE)) { if (IMSCSI_REMOVABLE(device_flags->FlagValues)) device_extension->RemovableMedia = TRUE; else device_extension->RemovableMedia = FALSE; device_flags->FlagsToChange &= ~IMSCSI_OPTION_REMOVABLE; } if (device_flags->FlagsToChange & IMSCSI_IMAGE_MODIFIED) { if (device_flags->FlagValues & IMSCSI_IMAGE_MODIFIED) device_extension->Modified = TRUE; else device_extension->Modified = FALSE; device_flags->FlagsToChange &= ~IMSCSI_IMAGE_MODIFIED; } if (KeGetCurrentIrql() == PASSIVE_LEVEL) { if (IMSCSI_SPARSE_FILE(device_flags->FlagsToChange) && IMSCSI_SPARSE_FILE(device_flags->FlagValues) && (!device_extension->UseProxy) && (!device_extension->VMDisk)) { IO_STATUS_BLOCK io_status; ntstatus = ZwFsControlFile( device_extension->ImageFile, NULL, NULL, NULL, &io_status, FSCTL_SET_SPARSE, NULL, 0, NULL, 0 ); if (NT_SUCCESS(ntstatus)) device_flags->FlagsToChange &= ~IMSCSI_OPTION_SPARSE_FILE; } } if (device_flags->FlagsToChange == 0) { ntstatus = STATUS_SUCCESS; StoragePortNotification(BusChangeDetected, pHBAExt, device_flags->DeviceNumber.PathId); } else if (NT_SUCCESS(ntstatus)) ntstatus = STATUS_INVALID_DEVICE_REQUEST; return ntstatus; }
int dc_format_start(wchar_t *dev_name, dc_pass *password, crypt_info *crypt) { IO_STATUS_BLOCK iosb; NTSTATUS status; dc_header *header = NULL; dev_hook *hook = NULL; xts_key *tmp_key = NULL; HANDLE h_dev = NULL; u8 *buff = NULL; int w_init = 0; u8 key_buf[32]; int resl; DbgMsg("dc_format_start\n"); do { if ( (hook = dc_find_hook(dev_name)) == NULL ) { resl = ST_NF_DEVICE; break; } wait_object_infinity(&hook->busy_lock); if (hook->flags & (F_ENABLED | F_UNSUPRT | F_DISABLE | F_CDROM)) { resl = ST_ERROR; break; } /* verify encryption info */ if ( (crypt->cipher_id >= CF_CIPHERS_NUM) || (crypt->wp_mode >= WP_NUM) ) { resl = ST_ERROR; break; } /* get device params */ if ( (resl = dc_fill_disk_info(hook)) != ST_OK ) { break; } if ( (header = mm_alloc(sizeof(dc_header), MEM_SECURE)) == NULL ) { resl = ST_NOMEM; break; } if ( (buff = mm_alloc(ENC_BLOCK_SIZE, 0)) == NULL ) { resl = ST_NOMEM; break; } if ( (tmp_key = mm_alloc(sizeof(xts_key), MEM_SECURE)) == NULL ) { resl = ST_NOMEM; break; } /* temporary disable automounting */ hook->flags |= F_NO_AUTO_MOUNT; /* open volume device */ if ( (h_dev = io_open_device(hook->dev_name)) == NULL ) { resl = ST_LOCK_ERR; break; } /* lock volume */ status = ZwFsControlFile( h_dev, NULL, NULL, NULL, &iosb, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0); if (NT_SUCCESS(status) == FALSE) { resl = ST_LOCK_ERR; break; } /* enable automounting */ hook->flags &= ~F_NO_AUTO_MOUNT; /* set encryption info */ hook->crypt = *crypt; /* init data wiping */ resl = dc_wipe_init( &hook->wp_ctx, hook, ENC_BLOCK_SIZE, crypt->wp_mode, crypt->cipher_id); if (resl == ST_OK) { w_init = 1; } else break; /* wipe first sectors */ dc_wipe_process(&hook->wp_ctx, 0, hook->head_len); /* create random temporary key */ cp_rand_bytes(key_buf, sizeof(key_buf)); xts_set_key(key_buf, crypt->cipher_id, tmp_key); /* create volume header */ memset(header, 0, sizeof(dc_header)); cp_rand_bytes(pv(header->salt), PKCS5_SALT_SIZE); cp_rand_bytes(pv(&header->disk_id), sizeof(u32)); cp_rand_bytes(pv(header->key_1), DISKKEY_SIZE); header->sign = DC_VOLM_SIGN; header->version = DC_HDR_VERSION; header->alg_1 = crypt->cipher_id; /* write volume header */ if ( (resl = io_write_header(hook, header, NULL, password)) != ST_OK ) { break; } /* mount device */ if ( (resl = dc_mount_device(dev_name, password, 0)) != ST_OK ) { break; } /* set hook fields */ hook->flags |= F_FORMATTING; hook->tmp_size = hook->head_len; hook->tmp_buff = buff; hook->tmp_key = tmp_key; } while (0); if ( (resl != ST_OK) ) { if (w_init != 0) { dc_wipe_free(&hook->wp_ctx); } if (buff != NULL) { mm_free(buff); } if (tmp_key != NULL) { mm_free(tmp_key); } } if (header != NULL) { mm_free(header); } if (hook != NULL) { KeReleaseMutex(&hook->busy_lock, FALSE); dc_deref_hook(hook); } /* prevent leaks */ burn(key_buf, sizeof(key_buf)); if (h_dev != NULL) { if (resl != ST_LOCK_ERR) { /* dismount volume */ ZwFsControlFile( h_dev, NULL, NULL, NULL, &iosb, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0); /* unlock volume */ ZwFsControlFile( h_dev, NULL, NULL, NULL, &iosb, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0); } /* close device */ ZwClose(h_dev); } return resl; }
VOID DPReinitializationRoutine( IN PDRIVER_OBJECT DriverObject, IN PVOID Context, IN ULONG Count ) { //返回值 NTSTATUS ntStatus; //D盘的缓冲文件名 WCHAR SparseFilename[] = L"\\??\\E:\\temp.dat"; UNICODE_STRING SparseFilenameUni; //建立文件时的io操作状态值 IO_STATUS_BLOCK ios = { 0 }; //建立文件时的对象属性变量 OBJECT_ATTRIBUTES ObjAttr = { 0 }; //设置文件大小的时候使用的文件结尾描述符 FILE_END_OF_FILE_INFORMATION FileEndInfo = { 0 }; //打开我们将要用来做转储的文件 //初始化要打开的文件名 RtlInitUnicodeString(&SparseFilenameUni,SparseFilename); //初始化文件名对应的对象名,这里需要将其初始化为内核对象,并且大小写不敏感 InitializeObjectAttributes( &ObjAttr, &SparseFilenameUni, OBJ_KERNEL_HANDLE|OBJ_CASE_INSENSITIVE, NULL, NULL); //建立文件,这里需要注意的是,要加入FILE_NO_INTERMEDIATE_BUFFERING选项,避免文件系统再缓存这个文件 ntStatus = ZwCreateFile( &gProtectDevExt->TempFile, GENERIC_READ | GENERIC_WRITE, &ObjAttr, &ios, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF, FILE_NON_DIRECTORY_FILE | FILE_RANDOM_ACCESS | FILE_SYNCHRONOUS_IO_NONALERT | FILE_NO_INTERMEDIATE_BUFFERING, NULL, 0); if(!NT_SUCCESS(ntStatus)) { goto ERROUT; } //设置这个文件为稀疏文件 ntStatus = ZwFsControlFile( gProtectDevExt->TempFile, NULL, NULL, NULL, &ios, FSCTL_SET_SPARSE, NULL, 0, NULL, 0); if(!NT_SUCCESS(ntStatus)) { goto ERROUT; } //设置这个文件的大小为"D"盘的大小并且留出10m的保护空间 FileEndInfo.EndOfFile.QuadPart = gProtectDevExt->TotalSizeInByte.QuadPart + 10*1024*1024; ntStatus = ZwSetInformationFile( gProtectDevExt->TempFile, &ios, &FileEndInfo, sizeof(FILE_END_OF_FILE_INFORMATION), FileEndOfFileInformation ); if (!NT_SUCCESS(ntStatus)) { goto ERROUT; } //如果成功初始化就将这个卷的保护标志设置为在保护状态 gProtectDevExt->Protect = TRUE; return; ERROUT: KdPrint(("error create temp file!\n")); return; }