ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

NTSTATUS NTAPI NtQueryDirectoryObject ( IN HANDLE  DirectoryHandle,
OUT PVOID  Buffer,
IN ULONG  BufferLength,
IN BOOLEAN  ReturnSingleEntry,
IN BOOLEAN  RestartScan,
IN OUT PULONG  Context,
OUT PULONG ReturnLength  OPTIONAL 
)

Definition at line 456 of file obdir.c.

Referenced by QueryDosDeviceW(), ScmCheckDriver(), ScmGetDriverStatus(), SmpTranslateSystemPartitionInformation(), and xHalpGetRDiskCount().

{
    POBJECT_DIRECTORY Directory;
    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
    ULONG SkipEntries = 0;
    NTSTATUS Status;
    PVOID LocalBuffer;
    POBJECT_DIRECTORY_INFORMATION DirectoryInfo;
    ULONG Length, TotalLength;
    ULONG Count, CurrentEntry;
    ULONG Hash;
    POBJECT_DIRECTORY_ENTRY Entry;
    POBJECT_HEADER ObjectHeader;
    POBJECT_HEADER_NAME_INFO ObjectNameInfo;
    UNICODE_STRING Name;
    PWSTR p;
    OBP_LOOKUP_CONTEXT LookupContext;
    PAGED_CODE();

    /* Initialize lookup */
    ObpInitializeLookupContext(&LookupContext);

    /* Check if we need to do any probing */
    if (PreviousMode != KernelMode)
    {
        _SEH2_TRY
        {
            /* Probe the buffer (assuming it will hold Unicode characters) */
            ProbeForWrite(Buffer, BufferLength, sizeof(WCHAR));

            /* Probe the context and copy it unless scan-restart was requested */
            ProbeForWriteUlong(Context);
            if (!RestartScan) SkipEntries = *Context;

            /* Probe the return length if the caller specified one */
            if (ReturnLength) ProbeForWriteUlong(ReturnLength);
        }
        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
        {
            /* Return the exception code */
            _SEH2_YIELD(return _SEH2_GetExceptionCode());
        }
        _SEH2_END;
    }
    else if (!RestartScan)
    {
        /* This is kernel mode, save the context without probing, if needed */
        SkipEntries = *Context;
    }

    /* Allocate a buffer */
    LocalBuffer = ExAllocatePoolWithTag(PagedPool,
                                        sizeof(OBJECT_DIRECTORY_INFORMATION) +
                                        BufferLength,
                                        OB_NAME_TAG);
    if (!LocalBuffer) return STATUS_INSUFFICIENT_RESOURCES;
    RtlZeroMemory(LocalBuffer, BufferLength);

    /* Get a reference to directory */
    Status = ObReferenceObjectByHandle(DirectoryHandle,
                                       DIRECTORY_QUERY,
                                       ObDirectoryType,
                                       PreviousMode,
                                       (PVOID*)&Directory,
                                       NULL);
    if (!NT_SUCCESS(Status))
    {
        /* Free the buffer and fail */
        ExFreePoolWithTag(LocalBuffer, OB_NAME_TAG);
        return Status;
    }

    /* Lock directory in shared mode */
    ObpAcquireDirectoryLockShared(Directory, &LookupContext);

    /* Start at position 0 */
    DirectoryInfo = (POBJECT_DIRECTORY_INFORMATION)LocalBuffer;
    TotalLength = sizeof(OBJECT_DIRECTORY_INFORMATION);

    /* Start with 0 entries */
    Count = 0;
    CurrentEntry = 0;

    /* Set default status and start looping */
    Status = STATUS_NO_MORE_ENTRIES;
    for (Hash = 0; Hash < 37; Hash++)
    {
        /* Get this entry and loop all of them */
        Entry = Directory->HashBuckets[Hash];
        while (Entry)
        {
            /* Check if we should process this entry */
            if (SkipEntries == CurrentEntry++)
            {
                /* Get the header data */
                ObjectHeader = OBJECT_TO_OBJECT_HEADER(Entry->Object);
                ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);

                /* Get the object name */
                if (ObjectNameInfo)
                {
                    /* Use the one we have */
                    Name = ObjectNameInfo->Name;
                }
                else
                {
                    /* Otherwise, use an empty one */
                    RtlInitEmptyUnicodeString(&Name, NULL, 0);
                }

                /* Calculate the length for this entry */
                Length = sizeof(OBJECT_DIRECTORY_INFORMATION) +
                         Name.Length + sizeof(UNICODE_NULL) +
                         ObjectHeader->Type->Name.Length + sizeof(UNICODE_NULL);

                /* Make sure this entry won't overflow */
                if ((TotalLength + Length) > BufferLength)
                {
                    /* Check if the caller wanted only an entry */
                    if (ReturnSingleEntry)
                    {
                        /* Then we'll fail and ask for more buffer */
                        TotalLength += Length;
                        Status = STATUS_BUFFER_TOO_SMALL;
                    }
                    else
                    {
                        /* Otherwise, we'll say we're done for now */
                        Status = STATUS_MORE_ENTRIES;
                    }

                    /* Decrease the entry since we didn't process */
                    CurrentEntry--;
                    goto Quickie;
                }

                /* Now fill in the buffer */
                DirectoryInfo->Name.Length = Name.Length;
                DirectoryInfo->Name.MaximumLength = Name.Length +
                                                    sizeof(UNICODE_NULL);
                DirectoryInfo->Name.Buffer = Name.Buffer;
                DirectoryInfo->TypeName.Length = ObjectHeader->
                                                 Type->Name.Length;
                DirectoryInfo->TypeName.MaximumLength = ObjectHeader->
                                                        Type->Name.Length +
                                                        sizeof(UNICODE_NULL);
                DirectoryInfo->TypeName.Buffer = ObjectHeader->
                                                 Type->Name.Buffer;

                /* Set success */
                Status = STATUS_SUCCESS;

                /* Increase statistics */
                TotalLength += Length;
                DirectoryInfo++;
                Count++;

                /* If the caller only wanted an entry, bail out */
                if (ReturnSingleEntry) goto Quickie;

                /* Increase the key by one */
                SkipEntries++;
            }

            /* Move to the next directory */
            Entry = Entry->ChainLink;
        }
    }

Quickie:
    /* Make sure we got success */
    if (NT_SUCCESS(Status))
    {
        /* Clear the current pointer and set it */
        RtlZeroMemory(DirectoryInfo, sizeof(OBJECT_DIRECTORY_INFORMATION));
        DirectoryInfo++;

        /* Set the buffer here now and loop entries */
        p = (PWSTR)DirectoryInfo;
        DirectoryInfo = LocalBuffer;
        while (Count--)
        {
            /* Copy the name buffer */
            RtlCopyMemory(p,
                          DirectoryInfo->Name.Buffer,
                          DirectoryInfo->Name.Length);

            /* Now fixup the pointers */
            DirectoryInfo->Name.Buffer = (PVOID)((ULONG_PTR)Buffer +
                                                 ((ULONG_PTR)p -
                                                  (ULONG_PTR)LocalBuffer));

            /* Advance in buffer and NULL-terminate */
            p = (PVOID)((ULONG_PTR)p + DirectoryInfo->Name.Length);
            *p++ = UNICODE_NULL;

            /* Now copy the type name buffer */
            RtlCopyMemory(p,
                          DirectoryInfo->TypeName.Buffer,
                          DirectoryInfo->TypeName.Length);

            /* Now fixup the pointers */
            DirectoryInfo->TypeName.Buffer = (PVOID)((ULONG_PTR)Buffer +
                                                     ((ULONG_PTR)p -
                                                     (ULONG_PTR)LocalBuffer));

            /* Advance in buffer and NULL-terminate */
            p = (PVOID)((ULONG_PTR)p + DirectoryInfo->TypeName.Length);
            *p++ = UNICODE_NULL;

            /* Move to the next entry */
            DirectoryInfo++;
        }

        /* Set the key */
        *Context = CurrentEntry;
    }

    _SEH2_TRY
    {
        /* Copy the buffer */
        RtlCopyMemory(Buffer,
                      LocalBuffer,
                      (TotalLength <= BufferLength) ?
                      TotalLength : BufferLength);

        /* Check if the caller requested the return length and return it*/
        if (ReturnLength) *ReturnLength = TotalLength;
    }
    _SEH2_EXCEPT(ExSystemExceptionFilter())
    {
        /* Get the exception code */
        Status = _SEH2_GetExceptionCode();
    }
    _SEH2_END;

    /* Unlock the directory */
    ObpReleaseDirectoryLock(Directory, &LookupContext);

    /* Dereference the directory and free our buffer */
    ObDereferenceObject(Directory);
    ExFreePoolWithTag(LocalBuffer, OB_NAME_TAG);

    /* Return status to caller */
    return Status;
}

Generated on Sat May 26 2012 06:07:42 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.