예제 #1
0
// Terminates a log file related code.
_Use_decl_annotations_ static void LogpFinalizeBufferInfo(LogBufferInfo *info) {
  PAGED_CODE();
  NT_ASSERT(info);

  // Closing the log buffer flush thread.
  if (info->buffer_flush_thread_handle) {
    info->buffer_flush_thread_should_be_alive = false;
    auto status =
        ZwWaitForSingleObject(info->buffer_flush_thread_handle, FALSE, nullptr);
    if (!NT_SUCCESS(status)) {
      LogpDbgBreak();
    }
    ZwClose(info->buffer_flush_thread_handle);
    info->buffer_flush_thread_handle = nullptr;
  }

  // Cleaning up other things.
  if (info->log_file_handle) {
    ZwClose(info->log_file_handle);
    info->log_file_handle = nullptr;
  }
  if (info->log_buffer2) {
    ExFreePoolWithTag(info->log_buffer2, kLogpPoolTag);
    info->log_buffer2 = nullptr;
  }
  if (info->log_buffer1) {
    ExFreePoolWithTag(info->log_buffer1, kLogpPoolTag);
    info->log_buffer1 = nullptr;
  }

  if (info->resource_initialized) {
    ExDeleteResourceLite(&info->resource);
    info->resource_initialized = false;
  }
}
예제 #2
0
/// <summary>
/// Create new thread in the target process
/// Must be running in target process context
/// </summary>
/// <param name="pBaseAddress">Thread start address</param>
/// <param name="pParam">Thread argument</param>
/// <param name="flags">Thread creation flags</param>
/// <param name="wait">If set to TRUE - wait for thread completion</param>
/// <param name="pExitStatus">Thread exit status</param>
/// <returns>Status code</returns>
NTSTATUS BBExecuteInNewThread(
    IN PVOID pBaseAddress,
    IN PVOID pParam,
    IN ULONG flags,
    IN BOOLEAN wait,
    OUT PNTSTATUS pExitStatus
    )
{
    HANDLE hThread = NULL;
    OBJECT_ATTRIBUTES ob = { 0 };

    InitializeObjectAttributes( &ob, NULL, OBJ_KERNEL_HANDLE, NULL, NULL );

    NTSTATUS status = ZwCreateThreadEx(
        &hThread, THREAD_QUERY_LIMITED_INFORMATION, &ob,
        ZwCurrentProcess(), pBaseAddress, pParam, flags,
        0, 0x1000, 0x100000, NULL
        );

    // Wait for completion
    if (NT_SUCCESS( status ) && wait != FALSE)
    {
        // Force 60 sec timeout
        LARGE_INTEGER timeout = { 0 };
        timeout.QuadPart = -(60ll * 10 * 1000 * 1000);

        status = ZwWaitForSingleObject( hThread, TRUE, &timeout );
        if (NT_SUCCESS( status ))
        {
            THREAD_BASIC_INFORMATION info = { 0 };
            ULONG bytes = 0;

            status = ZwQueryInformationThread( hThread, ThreadBasicInformation, &info, sizeof( info ), &bytes );
            if (NT_SUCCESS( status ) && pExitStatus)
            {
                *pExitStatus = info.ExitStatus;
            }
            else if (!NT_SUCCESS( status ))
            {
                DPRINT( "BlackBone: %s: ZwQueryInformationThread failed with status 0x%X\n", __FUNCTION__, status );
            }
        }
        else
            DPRINT( "BlackBone: %s: ZwWaitForSingleObject failed with status 0x%X\n", __FUNCTION__, status );
    }
    else
        DPRINT( "BlackBone: %s: ZwCreateThreadEx failed with status 0x%X\n", __FUNCTION__, status );

    if (hThread)
        ZwClose( hThread );

    return status;
}
예제 #3
0
static
NTSTATUS
QueryFileInfo(
    _In_ HANDLE FileHandle,
    _Out_ PVOID *Info,
    _Inout_ PSIZE_T Length,
    _In_ FILE_INFORMATION_CLASS FileInformationClass)
{
    NTSTATUS Status;
    IO_STATUS_BLOCK IoStatus;
    PVOID Buffer;

    *Info = NULL;
    if (*Length)
    {
        Buffer = KmtAllocateGuarded(*Length);
        if (skip(Buffer != NULL, "Failed to allocate %Iu bytes\n", *Length))
            return STATUS_INSUFFICIENT_RESOURCES;
    }
    else
    {
        Buffer = NULL;
    }
    RtlFillMemory(Buffer, *Length, 0xDD);
    RtlFillMemory(&IoStatus, sizeof(IoStatus), 0x55);
    _SEH2_TRY
    {
        Status = ZwQueryInformationFile(FileHandle,
                                        &IoStatus,
                                        Buffer,
                                        *Length,
                                        FileInformationClass);
    }
    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
    {
        Status = _SEH2_GetExceptionCode();
        ok(0, "Exception %lx querying class %d with length %Iu\n",
           Status, FileInformationClass, *Length);
    }
    _SEH2_END;
    if (Status == STATUS_PENDING)
    {
        Status = ZwWaitForSingleObject(FileHandle, FALSE, NULL);
        ok_eq_hex(Status, STATUS_SUCCESS);
        Status = IoStatus.Status;
    }
    *Length = IoStatus.Information;
    *Info = Buffer;
    return Status;
}
예제 #4
0
파일: eopmon.cpp 프로젝트: tandasat/EopMon
// Terminates a given process as well as its child process, and wait for
// terminatation of the given process
_Use_decl_annotations_ static NTSTATUS EopmonpTerminateProcessTree(
    HANDLE process_handle, HANDLE pid) {
  PAGED_CODE();

  auto status = ZwTerminateProcess(process_handle, 0);
  HYPERPLATFORM_LOG_DEBUG(
      "Exploitation detected. Process %Iu is being terminated (status = %08x).",
      pid, status);
  if (status == STATUS_PROCESS_IS_TERMINATING) {
    return status;
  }
  status = EopmonpForEachProcess(EopmonpTerminateProcessIfChild, pid);
  NT_VERIFY(NT_SUCCESS(status));
  status = ZwWaitForSingleObject(process_handle, FALSE, nullptr);
  NT_VERIFY(NT_SUCCESS(status));
  return status;
}
예제 #5
0
void cp_free_fast_crypt()
{
	int i;

	/* disable thread pool */
	if (lock_xchg(&pool_enabled, 0) == 0) {
		return;
	}
	/* stop all threads */
	for (i = 0; i < MAX_CPU_COUNT; i++)
	{
		if (pool_threads[i] != NULL) {
			KeSetEvent(&pool_signal_event, IO_NO_INCREMENT, FALSE);
			ZwWaitForSingleObject(pool_threads[i], FALSE, NULL);
			ZwClose(pool_threads[i]);
		}
	}
	/* free memory */
	memset(&pool_threads, 0, sizeof(pool_threads));
	ExDeleteNPagedLookasideList(&pool_req_mem);
}
예제 #6
0
EXTERN_C static void LogpFinalizeBufferInfo(
    _In_opt_ PDEVICE_OBJECT DeviceObject, _In_ LogBufferInfo *Info) {
  PAGED_CODE();
  NT_ASSERT(Info);

  // Closing the log buffer flush thread.
  if (Info->BufferFlushThreadHandle) {
    Info->BufferFlushThreadShouldBeAlive = false;
    auto status =
        ZwWaitForSingleObject(Info->BufferFlushThreadHandle, FALSE, nullptr);
    if (!NT_SUCCESS(status)) {
      DBG_BREAK();
    }
    ZwClose(Info->BufferFlushThreadHandle);
    Info->BufferFlushThreadHandle = nullptr;
  }

  // Cleaning up other things.
  if (Info->LogFileHandle) {
    ZwClose(Info->LogFileHandle);
    Info->LogFileHandle = nullptr;
  }
  if (Info->LogBuffer2) {
    ExFreePoolWithTag(Info->LogBuffer2, LOGP_POOL_TAG_NAME);
    Info->LogBuffer2 = nullptr;
  }
  if (Info->LogBuffer1) {
    ExFreePoolWithTag(Info->LogBuffer1, LOGP_POOL_TAG_NAME);
    Info->LogBuffer1 = nullptr;
  }

  if (DeviceObject) {
    IoUnregisterShutdownNotification(DeviceObject);
  }
  if (Info->ResourceInitialized) {
  ExDeleteResourceLite(&Info->Resource);
    Info->ResourceInitialized = false;
  }
}
예제 #7
0
파일: Fetch.c 프로젝트: aleksk/LazyCopy
static
_Check_return_
NTSTATUS
LcFetchFileByChunks (
    _In_  PCFLT_RELATED_OBJECTS FltObjects,
    _In_  HANDLE                SourceFileHandle,
    _In_  PLARGE_INTEGER        SourceFileSize,
    _Out_ PLARGE_INTEGER        BytesCopied
    )
/*++

Summary:

    This function copies the original file from the 'SourceFileHandle' to the currently opened
    file ('FltObjects->FileObject') by chunks.

    It maintains its own list of chunks, and extends it, if there are no chunks available to read into.
    Write operation goes from one chunk to another in a sequential order. If the next chunk is empty,
    write waits for the read to be completed, and proceeds.

    There are simple rules for chunks allocation:
    1. Up to two chunks are initially allocated:
       a) If the file is smaller than the 'ChunkSize', only one chunk is allocated with buffer
          that is equal to the file size.
       b) If the file is larger than the 'ChunkSize', two chunks are allocated, taking the
          file size into account for the second chunk size.
    2. If all chunks currently allocated are full and awaiting to be written to a disk, and
       the current amount of chunks is lesser than 'MaxChunks', an additional chunk is allocated.

    There is a corner case, when the actual file size differs from the reported one. In this case
    one of the chunks in the list will be smaller than the 'ChunkSize'.
    For example, 'MaxChunks' is 3, ChunkSize is '10', file size reported is '12', and actual file
    size is '25'.
    Two chunks will be initially allocated: [1] 10b; [2] (12-10)=2b.
    Later on, when all of them will be filled in with the data, and EOF will not be received,
    because the actual size is 25b, another chunk [3] of size 10b (ChunkSize) will be allocated.
    In total, there will be three chunks: 10b, 2b, and 10b.
    We don't reallocate the 2nd chunk, because this driver is supposed to be used with a proper
    filesystems, but making this modification might be a valuable TODO item.

    Let's look at how chunks work.
    All chunks are stored in the doubly-linked list. [Head] node doesn't contain any buffer to
    store data in. Refer to the 'FILE_CHUNK' structure for details.
    MSDN about lists: http://msdn.microsoft.com/en-us/library/windows/hardware/ff563802(v=vs.85).aspx

    For large files we will have two chunks from the beginning.
    [Head] <-> [1] <-> [2] <-> [Head]

    There are pointers for [R]ead and [W]rite.

    When the first chunk is being read, the list will look like the following:
    [Head] <-> [1] <-> [2] <-> [Head]
      [W]      [R]

    [W] is awaiting for the [1] to be filled in with the data before writing it to the disk.

    When the [1] chunk is filled with the data:
    [Head] <-> [1*] <-> [2] <-> [Head]
                [W]     [R]

    [1] is full and is being written to a disk, and we're reading into chunk [2].
    Let's also assume that the reads are faster then writes. When the [2] chunk is
    full, there are no free chunks available:
    [Head] <-> [1*] <-> [2*] <-> [Head]
                [W]      [R]

    If the current amount of chunks is lesser than the 'MaxChunks' value, a new chunk will be
    allocated before the next [R] node. In this case it will be added before [Head] to the end
    of the list, and read will continue:
    [Head] <-> [1*] <-> [2*] <-> [3] <-> [Head]
                [W]              [R]

    Then [W] and [R] finish, and [W] moves to the [2] chunk.
    [Head] <-> [1] <-> [2*] <-> [3*] <-> [Head]
                        [W]      [R]

    [R] sees that [1] chunk is available, and reads into it:
    [Head] <-> [1] <-> [2*] <-> [3*] <-> [Head]
               [R]      [W]

    After [R] finishes reading, there are no free chunks again:
    [Head] <-> [1*] <-> [2*] <-> [3*] <-> [Head]
               [R]       [W]

    A new chunk can be allocated again before the [2]:
    [Head] <-> [1*] <-> [4] <-> [2*] <-> [3*] <-> [Head]
                        [R]      [W]

    With this approach, [R] will fill chunks [1]->[2]->[3]->[1]->[4], and write will
    write them in the same order.
    I.e. allocating a new chunk before the next filled chunk (if the amount of chunks
    is lesser than the 'MaxChunks') makes sure that the data is written sequentially,
    and there is no need to constantly seek in the file.

Arguments:

    FltObjects       - Pointer to the 'FLT_RELATED_OBJECTS' data structure containing
                       opaque handles to this filter, instance, its associated volume and
                       file object.

    SourceFileHandle - Handle to the source file to copy content from.

    SourceFileSize   - Size of the source file.

    BytesCopied      - Pointer to the LARGE_INTEGER structure that receives the amount
                       of bytes copied.

Return Value:

    The return value is the status of the operation.

--*/
{
    NTSTATUS               status                = STATUS_SUCCESS;

    LIST_ENTRY             chunksListHead        = { 0 };
    ULONG                  chunkListLength       = 0;

    // State of the R/W operations.
    BOOLEAN                readComplete          = FALSE;
    BOOLEAN                writeComplete         = FALSE;
    PFILE_CHUNK            readChunk             = NULL;
    PFILE_CHUNK            writeChunk            = NULL;
    BOOLEAN                eof                   = FALSE;
    BOOLEAN                waitingForRead        = FALSE;
    KEVENT                 writeEvent            = { 0 };

    WRITE_CALLBACK_CONTEXT writeCallbackContext  = { 0 };

    LARGE_INTEGER          waitTimeout           = { 0 };
    LARGE_INTEGER          zeroTimeout           = { 0 };

    IO_STATUS_BLOCK        statusBlock           = { 0 };

    LARGE_INTEGER          remainingBytes        = { 0 };
    LARGE_INTEGER          totalBytesRead        = { 0 };
    LARGE_INTEGER          totalBytesWritten     = { 0 };
    LARGE_INTEGER          sourceFileOffset      = { 0 };
    LARGE_INTEGER          destinationFileOffset = { 0 };

    PAGED_CODE();

    FLT_ASSERT(FltObjects          != NULL);
    FLT_ASSERT(SourceFileHandle    != NULL);
    FLT_ASSERT(SourceFileSize      != NULL);
    FLT_ASSERT(SourceFileSize->QuadPart > 0);
    FLT_ASSERT(BytesCopied         != NULL);
    FLT_ASSERT(KeGetCurrentIrql()  == PASSIVE_LEVEL);

    *BytesCopied = RtlConvertLongToLargeInteger(0);

    __try
    {
        // Set the relative timeout (1 stands for 100 nanoseconds).
        waitTimeout           = RtlConvertLongToLargeInteger(-10000);
        waitTimeout.QuadPart *= TimeoutMilliseconds;

        KeInitializeEvent(&writeEvent, NotificationEvent, TRUE);
        writeCallbackContext.Event = &writeEvent;

        remainingBytes.QuadPart = SourceFileSize->QuadPart;

        NT_IF_FAIL_LEAVE(LcInitializeChunksList(FltObjects->Instance, &chunksListHead, remainingBytes, &chunkListLength));

        for (;;)
        {
            if (waitingForRead)
            {
                // Wait for the read operation to finish.
                NT_IF_FAIL_LEAVE(ZwWaitForSingleObject(SourceFileHandle, FALSE, &waitTimeout));
                readComplete = TRUE;
            }
            else
            {
                readComplete = ZwWaitForSingleObject(SourceFileHandle, FALSE, &zeroTimeout) == STATUS_SUCCESS;
            }

            writeComplete = KeReadStateEvent(&writeEvent) != 0;

            if (!eof && readComplete)
            {
                // If it's not the first read, update status of the current chunk.
                if (readChunk != NULL)
                {
                    status = statusBlock.Status;

                    if (NT_SUCCESS(status) || status == STATUS_END_OF_FILE)
                    {
                        ULONG bytesRead = (ULONG)statusBlock.Information;

                        readChunk->BytesInBuffer   = bytesRead;

                        remainingBytes.QuadPart   -= bytesRead;
                        totalBytesRead.QuadPart   += bytesRead;
                        sourceFileOffset.QuadPart += bytesRead;

                        if (status == STATUS_END_OF_FILE || bytesRead < readChunk->BufferSize)
                        {
                            eof    = TRUE;
                            status = STATUS_SUCCESS;

                            // Will not be used later in this case, only to have the proper data here.
                            remainingBytes.QuadPart = 0;
                        }
                    }

                    NT_IF_FAIL_LEAVE(status);
                }

                // Move to the next available chunk and schedule read.
                if (!eof)
                {
                    // If the remote file system returned an invalid file size, when we started reading it,
                    // this value might be negative. Set it to the default, so the newly allocated chunk
                    // will have the maximum allowed size.
                    if (remainingBytes.QuadPart <= 0)
                    {
                        remainingBytes.QuadPart = ChunkSize;
                    }

                    NT_IF_FAIL_LEAVE(LcGetNextAvailableChunk(
                        FltObjects->Instance,
                        &chunksListHead,
                        &readChunk,
                        &chunkListLength,
                        TRUE,              // Read operation.
                        &remainingBytes,
                        &writeEvent,
                        &waitTimeout));

                    // Schedule read operation for the current chunk.
                    status = ZwReadFile(
                        SourceFileHandle,
                        NULL,
                        NULL,
                        NULL,
                        &statusBlock,
                        readChunk->Buffer,
                        readChunk->BufferSize,
                        &sourceFileOffset,
                        NULL);

                    NT_IF_FALSE_LEAVE(status == STATUS_PENDING || status == STATUS_SUCCESS, status);
                }
            }

            if (writeComplete)
            {
                if (!waitingForRead)
                {
                    // If it's not the first write, update status of the current chunk.
                    if (writeChunk != NULL)
                    {
                        NT_IF_FAIL_LEAVE(writeCallbackContext.Status);

                        writeChunk->BytesInBuffer       = 0;
                        totalBytesWritten.QuadPart     += writeCallbackContext.BytesWritten;
                        destinationFileOffset.QuadPart += writeCallbackContext.BytesWritten;
                    }

                    NT_IF_FAIL_LEAVE(LcGetNextAvailableChunk(
                        FltObjects->Instance,
                        &chunksListHead,
                        &writeChunk,
                        &chunkListLength,
                        FALSE,             // Write operation.
                        NULL,
                        NULL,
                        NULL));
                }

                waitingForRead = FALSE;

                // If we don't have any data in the current chunk, restart from the beginning of the loop.
                if (writeChunk->BytesInBuffer == 0)
                {
                    if (eof)
                    {
                        // We're done!
                        break;
                    }
                    else
                    {
                        // Since we're waiting for the read to complete for the current chunk,
                        // don't change the chunk position on next iteration.
                        waitingForRead = TRUE;

                        continue;
                    }
                }

                KeClearEvent(&writeEvent);

                NT_IF_FAIL_LEAVE(FltWriteFile(
                    FltObjects->Instance,
                    FltObjects->FileObject,
                    &destinationFileOffset,
                    writeChunk->BytesInBuffer,
                    writeChunk->Buffer,
                    FLTFL_IO_OPERATION_DO_NOT_UPDATE_BYTE_OFFSET,
                    NULL,
                    (PFLT_COMPLETED_ASYNC_IO_CALLBACK)&LcWriteCallback,
                    &writeCallbackContext));
            }
        }

        *BytesCopied = totalBytesWritten;
    }
    __finally
    {
        LcClearChunksList(FltObjects->Instance, &chunksListHead);
    }

    return status;
}
예제 #8
0
static
VOID
TestAllInformation(VOID)
{
    NTSTATUS Status;
    UNICODE_STRING FileName = RTL_CONSTANT_STRING(L"\\SystemRoot\\system32\\ntoskrnl.exe");
    UNICODE_STRING Ntoskrnl = RTL_CONSTANT_STRING(L"ntoskrnl.exe");
    OBJECT_ATTRIBUTES ObjectAttributes;
    HANDLE FileHandle;
    IO_STATUS_BLOCK IoStatus;
    PFILE_ALL_INFORMATION FileAllInfo;
    SIZE_T Length;
    ULONG NameLength;
    PWCHAR Name = NULL;
    UNICODE_STRING NamePart;

    InitializeObjectAttributes(&ObjectAttributes,
                               &FileName,
                               OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
                               NULL,
                               NULL);
    Status = ZwOpenFile(&FileHandle,
                        SYNCHRONIZE | FILE_READ_ATTRIBUTES,
                        &ObjectAttributes,
                        &IoStatus,
                        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
                        FILE_NON_DIRECTORY_FILE);
    if (Status == STATUS_PENDING)
    {
        Status = ZwWaitForSingleObject(FileHandle, FALSE, NULL);
        ok_eq_hex(Status, STATUS_SUCCESS);
        Status = IoStatus.Status;
    }
    ok_eq_hex(Status, STATUS_SUCCESS);
    if (skip(NT_SUCCESS(Status), "No file handle, %lx\n", Status))
        return;

    /* NtQueryInformationFile doesn't do length checks for kernel callers in a free build */
    if (KmtIsCheckedBuild)
    {
    /* Zero length */
    Length = 0;
    Status = QueryFileInfo(FileHandle, (PVOID*)&FileAllInfo, &Length, FileAllInformation);
    ok_eq_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
    ok_eq_size(Length, (ULONG_PTR)0x5555555555555555);
    if (FileAllInfo)
        KmtFreeGuarded(FileAllInfo);

    /* One less than the minimum */
    Length = FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) - 1;
    Status = QueryFileInfo(FileHandle, (PVOID*)&FileAllInfo, &Length, FileAllInformation);
    ok_eq_hex(Status, STATUS_INFO_LENGTH_MISMATCH);
    ok_eq_size(Length, (ULONG_PTR)0x5555555555555555);
    if (FileAllInfo)
        KmtFreeGuarded(FileAllInfo);
    }

    /* The minimum allowed */
    Length = FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName);
    Status = QueryFileInfo(FileHandle, (PVOID*)&FileAllInfo, &Length, FileAllInformation);
    ok_eq_hex(Status, STATUS_BUFFER_OVERFLOW);
    ok_eq_size(Length, FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName));
    if (FileAllInfo)
        KmtFreeGuarded(FileAllInfo);

    /* Plenty of space -- determine NameLength and copy the name */
    Length = FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + MAX_PATH * sizeof(WCHAR);
    Status = QueryFileInfo(FileHandle, (PVOID*)&FileAllInfo, &Length, FileAllInformation);
    ok_eq_hex(Status, STATUS_SUCCESS);
    if (!skip(NT_SUCCESS(Status) && FileAllInfo != NULL, "No info\n"))
    {
        NameLength = FileAllInfo->NameInformation.FileNameLength;
        ok_eq_size(Length, FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength);
        Name = ExAllocatePoolWithTag(PagedPool, NameLength + sizeof(UNICODE_NULL), 'sFmK');
        if (!skip(Name != NULL, "Could not allocate %lu bytes\n", NameLength + (ULONG)sizeof(UNICODE_NULL)))
        {
            RtlCopyMemory(Name,
                          FileAllInfo->NameInformation.FileName,
                          NameLength);
            Name[NameLength / sizeof(WCHAR)] = UNICODE_NULL;
            ok(Name[0] == L'\\', "Name is %ls, expected first char to be \\\n", Name);
            ok(NameLength >= Ntoskrnl.Length + sizeof(WCHAR), "NameLength %lu too short\n", NameLength);
            if (NameLength >= Ntoskrnl.Length)
            {
                NamePart.Buffer = Name + (NameLength - Ntoskrnl.Length) / sizeof(WCHAR);
                NamePart.Length = Ntoskrnl.Length;
                NamePart.MaximumLength = NamePart.Length;
                ok(RtlEqualUnicodeString(&NamePart, &Ntoskrnl, TRUE),
                   "Name ends in '%wZ', expected %wZ\n", &NamePart, &Ntoskrnl);
            }
        }
        ok(FileAllInfo->NameInformation.FileName[NameLength / sizeof(WCHAR)] == 0xdddd,
           "Char past FileName is %x\n",
           FileAllInfo->NameInformation.FileName[NameLength / sizeof(WCHAR)]);
    }
    if (FileAllInfo)
        KmtFreeGuarded(FileAllInfo);

    /* One char less than needed */
    Length = FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength - sizeof(WCHAR);
    Status = QueryFileInfo(FileHandle, (PVOID*)&FileAllInfo, &Length, FileAllInformation);
    ok_eq_hex(Status, STATUS_BUFFER_OVERFLOW);
    ok_eq_size(Length, FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength - sizeof(WCHAR));
    if (FileAllInfo)
        KmtFreeGuarded(FileAllInfo);

    /* One byte less than needed */
    Length = FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength - 1;
    Status = QueryFileInfo(FileHandle, (PVOID*)&FileAllInfo, &Length, FileAllInformation);
    ok_eq_hex(Status, STATUS_BUFFER_OVERFLOW);
    ok_eq_size(Length, FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength - 1);
    if (FileAllInfo)
        KmtFreeGuarded(FileAllInfo);

    /* Exactly the required size */
    Length = FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength;
    Status = QueryFileInfo(FileHandle, (PVOID*)&FileAllInfo, &Length, FileAllInformation);
    ok_eq_hex(Status, STATUS_SUCCESS);
    ok_eq_size(Length, FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength);
    if (FileAllInfo)
        KmtFreeGuarded(FileAllInfo);

    /* One byte more than needed */
    Length = FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength + 1;
    Status = QueryFileInfo(FileHandle, (PVOID*)&FileAllInfo, &Length, FileAllInformation);
    ok_eq_hex(Status, STATUS_SUCCESS);
    ok_eq_size(Length, FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength);
    if (FileAllInfo)
        KmtFreeGuarded(FileAllInfo);

    /* One char more than needed */
    Length = FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength + sizeof(WCHAR);
    Status = QueryFileInfo(FileHandle, (PVOID*)&FileAllInfo, &Length, FileAllInformation);
    ok_eq_hex(Status, STATUS_SUCCESS);
    ok_eq_size(Length, FIELD_OFFSET(FILE_ALL_INFORMATION, NameInformation.FileName) + NameLength);
    if (FileAllInfo)
        KmtFreeGuarded(FileAllInfo);

    ExFreePoolWithTag(Name, 'sFmK');

    Status = ObCloseHandle(FileHandle, KernelMode);
    ok_eq_hex(Status, STATUS_SUCCESS);
}
NTSTATUS
ImScsiGetDiskSize(
__in HANDLE FileHandle,
__out __deref PIO_STATUS_BLOCK IoStatus,
__inout __deref PLARGE_INTEGER DiskSize)
{
    NTSTATUS status;

    {
        FILE_STANDARD_INFORMATION file_standard;

        status = ZwQueryInformationFile(FileHandle,
            IoStatus,
            &file_standard,
            sizeof(FILE_STANDARD_INFORMATION),
            FileStandardInformation);

        if (NT_SUCCESS(status))
        {
            *DiskSize = file_standard.EndOfFile;
            return status;
        }

        KdPrint(("PhDskMnt::FileStandardInformation not supported for "
            "target device. %#x\n", status));
    }

    // Retry with IOCTL_DISK_GET_LENGTH_INFO instead
    {
        GET_LENGTH_INFORMATION part_info = { 0 };

        status =
            ZwDeviceIoControlFile(FileHandle,
            NULL,
            NULL,
            NULL,
            IoStatus,
            IOCTL_DISK_GET_LENGTH_INFO,
            NULL,
            0,
            &part_info,
            sizeof(part_info));

        if (status == STATUS_PENDING)
        {
            ZwWaitForSingleObject(FileHandle, FALSE, NULL);
            status = IoStatus->Status;
        }

        if (NT_SUCCESS(status))
        {
            *DiskSize = part_info.Length;
            return status;
        }

        KdPrint(("PhDskMnt::IOCTL_DISK_GET_LENGTH_INFO not supported "
            "for target device. %#x\n", status));
    }

    // Retry with IOCTL_DISK_GET_PARTITION_INFO instead
    {
        PARTITION_INFORMATION part_info = { 0 };

        status =
            ZwDeviceIoControlFile(FileHandle,
            NULL,
            NULL,
            NULL,
            IoStatus,
            IOCTL_DISK_GET_PARTITION_INFO,
            NULL,
            0,
            &part_info,
            sizeof(part_info));

        if (status == STATUS_PENDING)
        {
            ZwWaitForSingleObject(FileHandle, FALSE, NULL);
            status = IoStatus->Status;
        }

        if (NT_SUCCESS(status))
        {
            *DiskSize = part_info.PartitionLength;
            return status;
        }

        KdPrint(("PhDskMnt::IOCTL_DISK_GET_PARTITION_INFO not supported "
            "for target device. %#x\n", status));
    }

    return status;
}
ULONG
MpHwFindAdapter(
__in       PVOID                           DeviceExtension,
__in       PVOID                           pReservedArg1,
__in       PVOID                           pReservedArg2,
#ifdef USE_STORPORT
__in       PVOID                           pReservedArg3,
#endif
__in       PCHAR                           ArgumentString,
__inout __deref PPORT_CONFIGURATION_INFORMATION pConfigInfo,
__out      PBOOLEAN                        pBAgain
)
{
    ULONG              i,
        len,
        status = SP_RETURN_FOUND;
    PCHAR              pChar;
    pHW_HBA_EXT        pHBAExt = (pHW_HBA_EXT)DeviceExtension;
    NTSTATUS           ntstatus;
    KLOCK_QUEUE_HANDLE LockHandle;
    KIRQL              lowest_assumed_irql = PASSIVE_LEVEL;

    UNREFERENCED_PARAMETER(pReservedArg1);
    UNREFERENCED_PARAMETER(pReservedArg2);
#ifdef USE_STORPORT
    UNREFERENCED_PARAMETER(pReservedArg3);
#endif
    UNREFERENCED_PARAMETER(ArgumentString);

    KdPrint(("PhDskMnt::MpHwFindAdapter: Arg=%s%s%s, pHBAExt = 0x%p, pConfigInfo = 0x%p, IRQL=%i\n",
        ArgumentString != NULL ? "\"" : "(",
        ArgumentString != NULL ? ArgumentString : "null",
        ArgumentString != NULL ? "\"" : ")",
        pHBAExt,
        pConfigInfo,
        KeGetCurrentIrql()));

#if VERBOSE_DEBUG_TRACE > 0

    if (!KD_DEBUGGER_NOT_PRESENT)
        DbgBreakPoint();

#endif

    if (pMPDrvInfoGlobal->GlobalsInitialized)
    {
        LARGE_INTEGER wait_time;

        DbgPrint("PhDskMnt::MpHwFindAdapter: Already initialized.\n");

        wait_time.QuadPart = -1000000;
        KeDelayExecutionThread(KernelMode, FALSE, &wait_time);
    }

    KeInitializeSpinLock(&pHBAExt->LUListLock);
    InitializeListHead(&pHBAExt->LUList);

    pHBAExt->HostTargetId = (UCHAR)pMPDrvInfoGlobal->MPRegInfo.InitiatorID;

    pConfigInfo->WmiDataProvider = FALSE;                       // Indicate WMI provider.

    pConfigInfo->Master = TRUE;

    pConfigInfo->NumberOfPhysicalBreaks = 4096;

    pConfigInfo->MaximumTransferLength = 8 << 20;                     // 8 MB.

#ifdef USE_STORPORT

    pConfigInfo->VirtualDevice = TRUE;                        // Indicate no real hardware.
    pConfigInfo->SynchronizationModel = StorSynchronizeFullDuplex;

    if (pConfigInfo->Dma64BitAddresses == SCSI_DMA64_SYSTEM_SUPPORTED)
        pConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_FULL64BIT_SUPPORTED;

#endif
#ifdef USE_SCSIPORT

    //if (pConfigInfo->NumberOfPhysicalBreaks == SP_UNINITIALIZED_VALUE)
    //    pConfigInfo->NumberOfPhysicalBreaks     = 4096;

    //if (pConfigInfo->MaximumTransferLength > (64 << 10))
    //    pConfigInfo->MaximumTransferLength      = 64 << 10;                     // 64 KB.

    pConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_SUPPORTED;

#endif

    pConfigInfo->AlignmentMask = 0x3;                         // Indicate DWORD alignment.
    pConfigInfo->CachesData = FALSE;                       // Indicate miniport wants flush and shutdown notification.
    pConfigInfo->MaximumNumberOfTargets = SCSI_MAXIMUM_TARGETS;        // Indicate maximum targets.
    pConfigInfo->NumberOfBuses =
        (UCHAR)pMPDrvInfoGlobal->MPRegInfo.NumberOfBuses;                     // Indicate number of buses.
    pConfigInfo->ScatterGather = TRUE;                        // Indicate scatter-gather (explicit setting needed for Win2003 at least).
    pConfigInfo->AutoRequestSense = TRUE;
    pConfigInfo->TaggedQueuing = TRUE;
    pConfigInfo->MultipleRequestPerLu = TRUE;

    // Save Vendor Id, Product Id, Revision in device extension.

    pChar = (PCHAR)pMPDrvInfoGlobal->MPRegInfo.VendorId.Buffer;
    len = min(8, (pMPDrvInfoGlobal->MPRegInfo.VendorId.Length / 2));
    for (i = 0; i < len; i++, pChar += 2)
        pHBAExt->VendorId[i] = *pChar;

    pChar = (PCHAR)pMPDrvInfoGlobal->MPRegInfo.ProductId.Buffer;
    len = min(16, (pMPDrvInfoGlobal->MPRegInfo.ProductId.Length / 2));
    for (i = 0; i < len; i++, pChar += 2)
        pHBAExt->ProductId[i] = *pChar;

    pChar = (PCHAR)pMPDrvInfoGlobal->MPRegInfo.ProductRevision.Buffer;
    len = min(4, (pMPDrvInfoGlobal->MPRegInfo.ProductRevision.Length / 2));
    for (i = 0; i < len; i++, pChar += 2)
        pHBAExt->ProductRevision[i] = *pChar;

    // Add HBA extension to master driver object's linked list.

    ImScsiAcquireLock(&pMPDrvInfoGlobal->DrvInfoLock, &LockHandle, lowest_assumed_irql);

    InsertTailList(&pMPDrvInfoGlobal->ListMPHBAObj, &pHBAExt->List);

    pMPDrvInfoGlobal->DrvInfoNbrMPHBAObj++;

    ImScsiReleaseLock(&LockHandle, &lowest_assumed_irql);

    if (!pMPDrvInfoGlobal->GlobalsInitialized)
    {
        HANDLE thread_handle;
        OBJECT_ATTRIBUTES object_attributes;

        KeInitializeSpinLock(&pMPDrvInfoGlobal->RequestListLock);
        InitializeListHead(&pMPDrvInfoGlobal->RequestList);
        KeInitializeEvent(&pMPDrvInfoGlobal->RequestEvent, SynchronizationEvent, FALSE);

#ifdef USE_SCSIPORT
        KeInitializeSpinLock(&pMPDrvInfoGlobal->ResponseListLock);
        KeInitializeEvent(&pMPDrvInfoGlobal->ResponseEvent, SynchronizationEvent, FALSE);
        InitializeListHead(&pMPDrvInfoGlobal->ResponseList);
#endif

        KeInitializeEvent(&pMPDrvInfoGlobal->StopWorker, NotificationEvent, FALSE);

        pMPDrvInfoGlobal->GlobalsInitialized = TRUE;

        InitializeObjectAttributes(&object_attributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);

        ntstatus = PsCreateSystemThread(
            &thread_handle,
            (ACCESS_MASK)0L,
            &object_attributes,
            NULL,
            NULL,
            ImScsiWorkerThread,
            NULL);

        if (!NT_SUCCESS(ntstatus))
        {
            DbgPrint("PhDskMnt::ScsiGetLUExtension: Cannot create worker thread. (%#x)\n", ntstatus);

            status = SP_RETURN_ERROR;
        }
        else
        {
            ntstatus = ObReferenceObjectByHandle(
                thread_handle,
                FILE_READ_ATTRIBUTES | SYNCHRONIZE,
                *PsThreadType,
                KernelMode,
                (PVOID*)&pMPDrvInfoGlobal->WorkerThread,
                NULL
                );

            if (!NT_SUCCESS(ntstatus))
            {
                DbgPrint("PhDskMnt::ScsiGetLUExtension: Cannot reference worker thread. (%#x)\n", ntstatus);
                KeSetEvent(&pMPDrvInfoGlobal->StopWorker, (KPRIORITY)0, FALSE);
                ZwWaitForSingleObject(thread_handle, FALSE, NULL);

                status = SP_RETURN_ERROR;
            }

            ZwClose(thread_handle);
        }
    }

    //Done:
    *pBAgain = FALSE;

    KdPrint(("PhDskMnt::MpHwFindAdapter: End, status = 0x%X\n", status));

    return status;
}                                                     // End MpHwFindAdapter().
예제 #11
0
파일: rmmain.c 프로젝트: conioh/os-design
BOOLEAN
SepRmCommandServerThreadInit(
    VOID
    )

/*++

Routine Description:

    This function performs initialization of the Reference Monitor Server
    thread.  The following steps are performed.

    o  Wait on the LSA signalling the event.  When the event is signalled,
       the LSA has already created the LSA Command Server LPC Port
    o  Close the LSA Init Event Handle.  The event is not used again.
    o  Listen for the LSA to connect to the Port
    o  Accept the connection.
    o  Connect to the LSA Command Server LPC Port

Arguments:

    None.

Return Value:

--*/

{
    NTSTATUS Status;
    UNICODE_STRING LsaCommandPortName;
    PORT_MESSAGE ConnectionRequest;
    SECURITY_QUALITY_OF_SERVICE DynamicQos;
    OBJECT_ATTRIBUTES ObjectAttributes;
    PORT_VIEW ClientView;
    REMOTE_PORT_VIEW LsaClientView;
    BOOLEAN BooleanStatus = TRUE;

    PAGED_CODE();

    //
    // Save a pointer to our process so we can get back into this process
    // to send commands to the LSA (using a handle to an LPC port created
    // below).
    //

    SepRmLsaCallProcess = PsGetCurrentProcess();

    ObReferenceObject(SepRmLsaCallProcess);

    //
    // Wait on the LSA signalling the event.  This means that the LSA
    // has created its command port, not that LSA initialization is
    // complete.
    //

    Status = ZwWaitForSingleObject(
                 SepRmState.LsaInitEventHandle,
                 FALSE,
                 NULL);

    if ( !NT_SUCCESS(Status) ) {

        KdPrint(("Security Rm Init: Waiting for LSA Init Event failed 0x%lx\n", Status));
        goto RmCommandServerThreadInitError;
    }

    //
    // Close the LSA Init Event Handle.  The event is not used again.
    //

    ZwClose(SepRmState.LsaInitEventHandle);

    //
    // Listen for a connection to be made by the LSA to the Reference Monitor
    // Command Port.  This connection will be made by the LSA process.
    //

    ConnectionRequest.u1.s1.TotalLength = sizeof(ConnectionRequest);
    ConnectionRequest.u1.s1.DataLength = (CSHORT)0;
    Status = ZwListenPort(
                 SepRmState.RmCommandPortHandle,
                 &ConnectionRequest
                 );

    if (!NT_SUCCESS(Status)) {

        KdPrint(("Security Rm Init: Listen to Command Port failed 0x%lx\n",
            Status));
        goto RmCommandServerThreadInitError;
    }

    //
    // Obtain a handle to the LSA process for use when auditing.
    //

    InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );

    Status = ZwOpenProcess(
                 &SepLsaHandle,
                 PROCESS_VM_OPERATION | PROCESS_VM_WRITE,
                 &ObjectAttributes,
                 &ConnectionRequest.ClientId
                 );

    if (!NT_SUCCESS(Status)) {

        KdPrint(("Security Rm Init: Open Listen to Command Port failed 0x%lx\n",
            Status));
        goto RmCommandServerThreadInitError;
    }

    //
    // Accept the connection made by the LSA process.
    //

    LsaClientView.Length = sizeof(LsaClientView);

    Status = ZwAcceptConnectPort(
                 &SepRmState.RmCommandPortHandle,
                 NULL,
                 &ConnectionRequest,
                 TRUE,
                 NULL,
                 &LsaClientView
                 );

    if (!NT_SUCCESS(Status)) {

        KdPrint(("Security Rm Init: Accept Connect to Command Port failed 0x%lx\n",
                Status));

        goto RmCommandServerThreadInitError;
    }

    //
    // Complete the connection.
    //

    Status = ZwCompleteConnectPort(SepRmState.RmCommandPortHandle);

    if (!NT_SUCCESS(Status)) {

        KdPrint(("Security Rm Init: Complete Connect to Command Port failed 0x%lx\n",
                Status));
        goto RmCommandServerThreadInitError;
    }

    //
    // Set up the security quality of service parameters to use over the
    // Lsa Command LPC port.  Use the most efficient (least overhead) - which
    // is dynamic rather than static tracking.
    //

    DynamicQos.ImpersonationLevel = SecurityImpersonation;
    DynamicQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
    DynamicQos.EffectiveOnly = TRUE;

    //
    // Create the section to be used as unnamed shared memory for
    // communication between the RM and LSA.
    //

    SepRmState.LsaCommandPortSectionSize.LowPart = PAGE_SIZE;
    SepRmState.LsaCommandPortSectionSize.HighPart = 0;

    Status = ZwCreateSection(
                 &SepRmState.LsaCommandPortSectionHandle,
                 SECTION_ALL_ACCESS,
                 NULL,                           // ObjectAttributes
                 &SepRmState.LsaCommandPortSectionSize,
                 PAGE_READWRITE,
                 SEC_COMMIT,
                 NULL                            // FileHandle
                 );

    if (!NT_SUCCESS(Status)) {

        KdPrint(("Security Rm Init: Create Memory Section for LSA port failed: %X\n", Status));
        goto RmCommandServerThreadInitError;
    }

    //
    // Set up for a call to NtConnectPort and connect to the LSA port.
    // This setup includes a description of the port memory section so that
    // the LPC connection logic can make the section visible to both the
    // client and server processes.
    //

    ClientView.Length = sizeof(ClientView);
    ClientView.SectionHandle = SepRmState.LsaCommandPortSectionHandle;
    ClientView.SectionOffset = 0;
    ClientView.ViewSize = SepRmState.LsaCommandPortSectionSize.LowPart;
    ClientView.ViewBase = 0;
    ClientView.ViewRemoteBase = 0;

    //
    // Set up the security quality of service parameters to use over the
    // port.  Use dynamic tracking so that XACTSRV will impersonate the
    // user that we are impersonating when we call NtRequestWaitReplyPort.
    // If we used static tracking, XACTSRV would impersonate the context
    // when the connection is made.
    //

    DynamicQos.ImpersonationLevel = SecurityImpersonation;
    DynamicQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
    DynamicQos.EffectiveOnly = TRUE;

    //
    // Connect to the Lsa Command LPC Port.  This port is used to send
    // commands from the RM to the LSA.
    //

    RtlInitUnicodeString( &LsaCommandPortName, L"\\SeLsaCommandPort" );

    Status = ZwConnectPort(
                 &SepRmState.LsaCommandPortHandle,
                 &LsaCommandPortName,
                 &DynamicQos,
                 &ClientView,
                 NULL,                           // ServerView
                 NULL,                           // MaxMessageLength
                 NULL,                           // ConnectionInformation
                 NULL                            // ConnectionInformationLength
                 );

    if (!NT_SUCCESS(Status)) {

        KdPrint(("Security Rm Init: Connect to LSA Port failed 0x%lx\n", Status));
        goto RmCommandServerThreadInitError;
    }

    //
    // Store information about the section so that we can create pointers
    // meaningful to LSA.
    //

    SepRmState.RmViewPortMemory = ClientView.ViewBase;
    SepRmState.LsaCommandPortMemoryDelta =
        (LONG)((ULONG_PTR)ClientView.ViewRemoteBase - (ULONG_PTR) ClientView.ViewBase );
    SepRmState.LsaViewPortMemory = ClientView.ViewRemoteBase;

/* BugWarning - ScottBi - probably don't need the resource

    //
    // Create the resource serializing access to the port.  This
    // resource prevents the port and the shared memory from being
    // deleted while worker threads are processing requests.
    //

    if ( !SepRmState.LsaCommandPortResourceInitialized ) {

        ExInitializeResource( &SepRmState.LsaCommandPortResource );
        SepRmState.LsaCommandPortResourceInitialized = TRUE;
    }

    SepRmState.LsaCommandPortActive = TRUE;

*/

RmCommandServerThreadInitFinish:

    //
    // Dont need this section handle any more, even if returning
    // success.
    //

    if ( SepRmState.LsaCommandPortSectionHandle != NULL ) {

       NtClose( SepRmState.LsaCommandPortSectionHandle );
       SepRmState.LsaCommandPortSectionHandle = NULL;
    }

    //
    // The Reference Monitor Thread has successfully initialized.
    //

    return BooleanStatus;

RmCommandServerThreadInitError:

    if ( SepRmState.LsaCommandPortHandle != NULL ) {

       NtClose( SepRmState.LsaCommandPortHandle );
       SepRmState.LsaCommandPortHandle = NULL;
    }

    BooleanStatus = FALSE;
    goto RmCommandServerThreadInitFinish;
}
예제 #12
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;
}
예제 #13
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;
}