Example #1
0
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;
}
Example #2
0
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;
}
Example #3
0
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);
}
Example #4
0
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;
}
Example #5
0
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;
}
Example #6
0
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;
}
Example #7
0
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( &currentTime );

			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;
}
Example #9
0
/*
   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;
}
Example #11
0
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;
}
Example #12
0
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;
}
Example #14
0
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;
}
Example #15
0
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;
}