Beispiel #1
0
NTSTATUS
NTAPI
NtCreateIoCompletion(OUT PHANDLE IoCompletionHandle,
                     IN ACCESS_MASK DesiredAccess,
                     IN POBJECT_ATTRIBUTES ObjectAttributes,
                     IN ULONG NumberOfConcurrentThreads)
{
    PKQUEUE Queue;
    HANDLE hIoCompletionHandle;
    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
    NTSTATUS Status;
    PAGED_CODE();

    /* Check if this was a user-mode call */
    if (PreviousMode != KernelMode)
    {
        /* Wrap probing in SEH */
        _SEH2_TRY
        {
            /* Probe the handle */
            ProbeForWriteHandle(IoCompletionHandle);
        }
        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
        {
            /* Return the exception code */
            _SEH2_YIELD(return _SEH2_GetExceptionCode());
        }
        _SEH2_END;
    }
Beispiel #2
0
/*
 * @implemented
 */
NTSTATUS
NTAPI
NtCreateEvent(OUT PHANDLE EventHandle,
              IN ACCESS_MASK DesiredAccess,
              IN POBJECT_ATTRIBUTES ObjectAttributes  OPTIONAL,
              IN EVENT_TYPE EventType,
              IN BOOLEAN InitialState)
{
    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
    PKEVENT Event;
    HANDLE hEvent;
    NTSTATUS Status;
    PAGED_CODE();
    DPRINT("NtCreateEvent(0x%p, 0x%x, 0x%p)\n",
            EventHandle, DesiredAccess, ObjectAttributes);

    /* Check if we were called from user-mode */
    if (PreviousMode != KernelMode)
    {
        /* Enter SEH Block */
        _SEH2_TRY
        {
            /* Check handle pointer */
            ProbeForWriteHandle(EventHandle);
        }
        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
        {
            /* Return the exception code */
            _SEH2_YIELD(return _SEH2_GetExceptionCode());
        }
        _SEH2_END;
    }
Beispiel #3
0
/*
 * @unimplemented
 */
NTSTATUS
NTAPI
NtCreateJobObject (
    PHANDLE JobHandle,
    ACCESS_MASK DesiredAccess,
    POBJECT_ATTRIBUTES ObjectAttributes )
{
    HANDLE hJob;
    PEJOB Job;
    KPROCESSOR_MODE PreviousMode;
    PEPROCESS CurrentProcess;
    NTSTATUS Status;

    PAGED_CODE();

    PreviousMode = ExGetPreviousMode();
    CurrentProcess = PsGetCurrentProcess();

    /* check for valid buffers */
    if (PreviousMode != KernelMode)
    {
        _SEH2_TRY
        {
            ProbeForWriteHandle(JobHandle);
        }
        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
        {
            _SEH2_YIELD(return _SEH2_GetExceptionCode());
        }
        _SEH2_END;
    }
Beispiel #4
0
/*
 * @implemented
 */
NTSTATUS
NTAPI
NtOpenProcessTokenEx(IN HANDLE ProcessHandle,
                     IN ACCESS_MASK DesiredAccess,
                     IN ULONG HandleAttributes,
                     OUT PHANDLE TokenHandle)
{
    PACCESS_TOKEN Token;
    HANDLE hToken;
    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
    NTSTATUS Status;
    PAGED_CODE();
    PSTRACE(PS_SECURITY_DEBUG,
            "Process: %p DesiredAccess: %lx\n", ProcessHandle, DesiredAccess);

    /* Check if caller was user-mode */
    if (PreviousMode != KernelMode)
    {
        /* Enter SEH for probing */
        _SEH2_TRY
        {
            /* Probe the token handle */
            ProbeForWriteHandle(TokenHandle);
        }
        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
        {
            /* Return the exception code */
            _SEH2_YIELD(return _SEH2_GetExceptionCode());
        }
        _SEH2_END;
    }
Beispiel #5
0
NTSTATUS
NTAPI
NtCreateEventPair(OUT PHANDLE EventPairHandle,
                  IN ACCESS_MASK DesiredAccess,
                  IN POBJECT_ATTRIBUTES ObjectAttributes)
{
    PKEVENT_PAIR EventPair;
    HANDLE hEventPair;
    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
    NTSTATUS Status;
    PAGED_CODE();
    DPRINT("NtCreateEventPair: 0x%p\n", EventPairHandle);

    /* Check if we were called from user-mode */
    if (PreviousMode != KernelMode)
    {
        /* Enter SEH Block */
        _SEH2_TRY
        {
            /* Check handle pointer */
            ProbeForWriteHandle(EventPairHandle);
        }
        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
        {
            /* Return the exception code */
            _SEH2_YIELD(return _SEH2_GetExceptionCode());
        }
        _SEH2_END;
    }
Beispiel #6
0
/*
 * @implemented
 */
NTSTATUS
NTAPI
NtCreateSemaphore(OUT PHANDLE SemaphoreHandle,
                  IN ACCESS_MASK DesiredAccess,
                  IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
                  IN LONG InitialCount,
                  IN LONG MaximumCount)
{
    PKSEMAPHORE Semaphore;
    HANDLE hSemaphore;
    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
    NTSTATUS Status;
    PAGED_CODE();

    /* Check if we were called from user-mode */
    if (PreviousMode != KernelMode)
    {
        /* Enter SEH Block */
        _SEH2_TRY
        {
            /* Check handle pointer */
            ProbeForWriteHandle(SemaphoreHandle);
        }
        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
        {
            /* Return the exception code */
            _SEH2_YIELD(return _SEH2_GetExceptionCode());
        }
        _SEH2_END;
    }
Beispiel #7
0
NTSTATUS
NtAcceptConnectPort (
    OUT PHANDLE PortHandle,
    IN PVOID PortContext OPTIONAL,
    IN PPORT_MESSAGE ConnectionRequest,
    IN BOOLEAN AcceptConnection,
    IN OUT PPORT_VIEW ServerView OPTIONAL,
    OUT PREMOTE_PORT_VIEW ClientView OPTIONAL
    )

/*++

Routine Description:

    A server process can accept or reject a client connection request
    using the NtAcceptConnectPort service.

    The ConnectionRequest parameter must specify a connection request
    returned by a previous call to the NtListenPort service.  This
    service will either complete the connection if the AcceptConnection
    parameter is TRUE, or reject the connection request if the
    AcceptConnection parameter is FALSE.

    In either case, the contents of the data portion of the connection
    request is the data to return to the caller of NtConnectPort.

    If the connection request is accepted, then two communication port
    objects will be created and connected together.  One will be
    inserted in the client process' handle table and returned to the
    client via the PortHandle parameter it specified on the
    NtConnectPort service.  The other will be inserted in the server
    process' handle table and returned via the PortHandle parameter
    specified on the NtCompleteConnectPort service.  In addition the
    two communication ports (client and server) will be linked together.

    If the connection request is accepted, and the ServerView parameter
    was specified, then the section handle is examined.  If it is valid,
    then the portion of the section described by the SectionOffset and
    ViewSize fields will be mapped into both the client and server
    process address spaces.  The address in server's address space will
    be returned in the ViewBase field.  The address in the client's
    address space will be returned in the ViewRemoteBase field.  The
    actual offset and size used to map the section will be returned in
    the SectionOffset and ViewSize fields.

    Communication port objects are temporary objects that have no names
    and cannot be inherited.  When either the client or server process
    calls the !f NtClose service for a communication port, the port will
    be deleted since there can never be more than one outstanding handle
    for each communication port.  The port object type specific delete
    procedure will then be invoked.  This delete procedure will examine
    the communication port, and if it is connected to another
    communication port, it will queue an LPC_PORT_CLOSED datagram to
    that port's message queue.  This will allow both the client and
    server processes to notice when a port becomes disconnected, either
    because of an explicit call to NtClose or an implicit call due to
    process termination.  In addition, the delete procedure will scan
    the message queue of the port being closed and for each message
    still in the queue, it will return an ERROR_PORT_CLOSED status to
    any thread that is waiting for a reply to the message.

Arguments:

    PortHandle - A pointer to a variable that will receive the server
        communication port object handle value.

    PortContext - An uninterpreted pointer that is stored in the
        server communication port.  This pointer is returned whenever
        a message is received for this port.

    ConnectionRequest - A pointer to a structure that describes the
        connection request being accepted or rejected:

        The ConnectionRequest structure

        ULONG Length - Specifies the size of this data structure in
            bytes.

        CLIENT_ID ClientId - Specifies a structure that contains the
            client identifier (CLIENT_ID) of the thread that sent the
            request.

        The ClientId Structure

            ULONG UniqueProcessId - A unique value for each process
                in the system.

            ULONG UniqueThreadId - A unique value for each thread in the
                system.

        ULONG MessageId - A unique value that identifies the connection
            request being completed.

        ULONG PortAttributes - This field has no meaning for this service.

        ULONG ClientViewSize - This field has no meaning for this service.

    AcceptConnection - Specifies a boolean value which indicates where
        the connection request is being accepted or rejected.  A value
        of TRUE means that the connection request is accepted and a
        server communication port handle will be created and connected
        to the client's communication port handle.  A value of FALSE
        means that the connection request is not accepted.

    ServerView - A pointer to a structure that specifies the section that
        the server process will use to send messages back to the client
        process connected to this port.

        The ServerView Structure

        ULONG Length - Specifies the size of this data structure in
            bytes.

        HANDLE SectionHandle - Specifies an open handle to a section
            object.

        ULONG SectionOffset - Specifies a field that will receive the
            actual offset, in bytes, from the start of the section.  The
            initial value of this parameter specifies the byte offset
            within the section that the client's view is based.  The
            value is rounded down to the next host page size boundary.

        ULONG ViewSize - Specifies the size of the view, in bytes.

        PVOID ViewBase - Specifies a field that will receive the base
            address of the port memory in the server's address space.

        PVOID ViewRemoteBase - Specifies a field that will receive
            the base address of the server port's memory in the client's
            address space.  Used to generate pointers that are
            meaningful to the client.

    ClientView - An optional pointer to a structure that will receive
        information about the client process' view in the server's
        address space.  The server process can use this information
        to validate pointers it receives from the client process.

        The ClientView Structure

        ULONG Length - Specifies the size of this data structure in
            bytes.

        PVOID ViewBase - Specifies a field that will receive the base
            address of the client port's memory in the server's address
            space.

        ULONG ViewSize - Specifies a field that will receive the
            size, in bytes, of the client's view in the server's address
            space.  If this field is zero, then client has no view in
            the server's address space.

Return Value:

    NTSTATUS - An appropriate status value.

--*/

{
    PLPCP_PORT_OBJECT ConnectionPort;
    PLPCP_PORT_OBJECT ServerPort;
    PLPCP_PORT_OBJECT ClientPort;
    PVOID ClientSectionToMap;
    HANDLE Handle;
    KPROCESSOR_MODE PreviousMode;
    NTSTATUS Status;
    ULONG ConnectionInfoLength;
    PLPCP_MESSAGE Msg;
    PLPCP_CONNECTION_MESSAGE ConnectMsg;
    PORT_MESSAGE CapturedReplyMessage;
    PVOID SectionToMap;
    LARGE_INTEGER SectionOffset;
    SIZE_T ViewSize;
    PEPROCESS ClientProcess;
    PETHREAD ClientThread;
    PORT_VIEW CapturedServerView;

    PAGED_CODE();

    //
    //  Get previous processor mode and probe output arguments if necessary.
    //

    PreviousMode = KeGetPreviousMode();

    if (PreviousMode != KernelMode) {

        try {

            ProbeForWriteHandle( PortHandle );

            ProbeForRead( ConnectionRequest,
                          sizeof( *ConnectionRequest ),
                          sizeof( ULONG ));

            CapturedReplyMessage = *ConnectionRequest;

            if (ARGUMENT_PRESENT( ServerView )) {

                CapturedServerView = ProbeAndReadStructure( ServerView, PORT_VIEW );

                if (CapturedServerView.Length != sizeof( *ServerView )) {

                    return STATUS_INVALID_PARAMETER;
                }

                ProbeForWrite( ServerView,
                               sizeof( *ServerView ),
                               sizeof( ULONG ));
            }

            if (ARGUMENT_PRESENT( ClientView )) {

                if (ProbeAndReadUlong( &ClientView->Length ) != sizeof( *ClientView )) {

                    return STATUS_INVALID_PARAMETER;
                }

                ProbeForWrite( ClientView,
                               sizeof( *ClientView ),
                               sizeof( ULONG ));
            }

        } except( EXCEPTION_EXECUTE_HANDLER ) {

            return GetExceptionCode();
        }

    } else {
Beispiel #8
0
NTSTATUS
NtCreateTimer (
    OUT PHANDLE TimerHandle,
    IN ACCESS_MASK DesiredAccess,
    IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
    IN TIMER_TYPE TimerType
    )

/*++

Routine Description:

    This function creates an timer object and opens a handle to the object with
    the specified desired access.

Arguments:

    TimerHandle - Supplies a pointer to a variable that will receive the
        timer object handle.

    DesiredAccess - Supplies the desired types of access for the timer object.

    ObjectAttributes - Supplies a pointer to an object attributes structure.

    TimerType - Supplies the type of the timer (autoclearing or notification).

Return Value:

    TBS

--*/

{

    PETIMER ExTimer;
    HANDLE Handle;
    KPROCESSOR_MODE PreviousMode;
    NTSTATUS Status;

    //
    // Establish an exception handler, probe the output handle address, and
    // attempt to create a timer object. If the probe fails, then return the
    // exception code as the service status. Otherwise return the status value
    // returned by the object insertion routine.
    //

    try {

        //
        // Get previous processor mode and probe output handle address if
        // necessary.
        //

        PreviousMode = KeGetPreviousMode();
        if (PreviousMode != KernelMode) {
            ProbeForWriteHandle(TimerHandle);
        }

        //
        // Check argument validity.
        //

        if ((TimerType != NotificationTimer) &&
            (TimerType != SynchronizationTimer)) {
            return STATUS_INVALID_PARAMETER_4;
        }

        //
        // Allocate timer object.
        //

        Status = ObCreateObject(PreviousMode,
                                ExTimerObjectType,
                                ObjectAttributes,
                                PreviousMode,
                                NULL,
                                sizeof(ETIMER),
                                0,
                                0,
                                (PVOID *)&ExTimer);

        //
        // If the timer object was successfully allocated, then initialize the
        // timer object and attempt to insert the time object in the current
        // process' handle table.
        //

        if (NT_SUCCESS(Status)) {
            KeInitializeDpc(&ExTimer->TimerDpc,
                            ExpTimerDpcRoutine,
                            (PVOID)ExTimer);

            KeInitializeTimerEx(&ExTimer->KeTimer, TimerType);
            KeInitializeSpinLock(&ExTimer->Lock);
            ExTimer->ApcAssociated = FALSE;
            ExTimer->WakeTimer = FALSE;
            ExTimer->WakeTimerListEntry.Flink = NULL;
            Status = ObInsertObject((PVOID)ExTimer,
                                    NULL,
                                    DesiredAccess,
                                    0,
                                    (PVOID *)NULL,
                                    &Handle);

            //
            // If the timer object was successfully inserted in the current
            // process' handle table, then attempt to write the timer object
            // handle value. If the write attempt fails, then do not report
            // an error. When the caller attempts to access the handle value,
            // an access violation will occur.
            //

            if (NT_SUCCESS(Status)) {
                try {
                    *TimerHandle = Handle;
                 } except(ExSystemExceptionFilter()) {
                 }
            }
        }

    //
    // If an exception occurs during the probe of the output handle address,
    // then always handle the exception and return the exception code as the
    // status value.
    //

    } except(ExSystemExceptionFilter()) {
        return GetExceptionCode();
    }

    //
    // Return service status.
    //

    return Status;
}
Beispiel #9
0
/*
 * @implemented
 */
NTSTATUS
NTAPI
NtAcceptConnectPort(OUT PHANDLE PortHandle,
                    IN PVOID PortContext OPTIONAL,
                    IN PPORT_MESSAGE ReplyMessage,
                    IN BOOLEAN AcceptConnection,
                    IN PPORT_VIEW ServerView,
                    IN PREMOTE_PORT_VIEW ClientView)
{
    PLPCP_PORT_OBJECT ConnectionPort, ServerPort, ClientPort;
    PVOID ClientSectionToMap = NULL;
    HANDLE Handle;
    KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
    NTSTATUS Status;
    ULONG ConnectionInfoLength;
    PLPCP_MESSAGE Message;
    PLPCP_CONNECTION_MESSAGE ConnectMessage;
    PEPROCESS ClientProcess;
    PETHREAD ClientThread;
    LARGE_INTEGER SectionOffset;
    CLIENT_ID ClientId;
    ULONG MessageId;
    PAGED_CODE();
    LPCTRACE(LPC_COMPLETE_DEBUG,
             "Context: %p. Message: %p. Accept: %lx. Views: %p/%p\n",
             PortContext,
             ReplyMessage,
             AcceptConnection,
             ClientView,
             ServerView);

    /* Check if the call comes from user mode */
    if (PreviousMode != KernelMode)
    {
        /* Enter SEH for probing the parameters */
        _SEH2_TRY
        {
            ProbeForWriteHandle(PortHandle);

            /* Probe the basic ReplyMessage structure */
            ProbeForRead(ReplyMessage, sizeof(PORT_MESSAGE), sizeof(ULONG));

            /* Grab some values */
            ClientId = ReplyMessage->ClientId;
            MessageId = ReplyMessage->MessageId;
            ConnectionInfoLength = ReplyMessage->u1.s1.DataLength;

            /* Probe the connection info */
            ProbeForRead(ReplyMessage + 1, ConnectionInfoLength, 1);

            /* The following parameters are optional */
            if (ServerView != NULL)
            {
                ProbeForWrite(ServerView, sizeof(PORT_VIEW), sizeof(ULONG));

                /* Validate the size of the server view */
                if (ServerView->Length != sizeof(PORT_VIEW))
                {
                    /* Invalid size */
                    _SEH2_YIELD(return STATUS_INVALID_PARAMETER);
                }
            }
Beispiel #10
0
NTSTATUS
NtOpenProcessToken(
    IN HANDLE ProcessHandle,
    IN ACCESS_MASK DesiredAccess,
    OUT PHANDLE TokenHandle
    )

/*++

Routine Description:

    Open a token object associated with a process and return a handle
    that may be used to access that token.

Arguments:

    ProcessHandle - Specifies the process whose token is to be
        opened.

    DesiredAccess - Is an access mask indicating which access types
        are desired to the token.  These access types are reconciled
        with the Discretionary Access Control list of the token to
        determine whether the accesses will be granted or denied.

    TokenHandle - Receives the handle of the newly opened token.

Return Value:

    STATUS_SUCCESS - Indicates the operation was successful.

--*/
{

    PVOID Token;
    KPROCESSOR_MODE PreviousMode;
    NTSTATUS Status;

    HANDLE LocalHandle;

    PAGED_CODE();

    PreviousMode = KeGetPreviousMode();

    //
    //  Probe parameters
    //

    if (PreviousMode != KernelMode) {

        try {

            ProbeForWriteHandle(TokenHandle);

        } except(EXCEPTION_EXECUTE_HANDLER) {
            return GetExceptionCode();
        }  // end_try

    } //end_if


    //
    // Valdiate access to the process and obtain a pointer to the
    // process's token.  If successful, this will cause the token's
    // reference count to be incremented.
    //

    Status = PsOpenTokenOfProcess( ProcessHandle, ((PACCESS_TOKEN *)&Token));

    if (!NT_SUCCESS(Status)) {
        return Status;
    }

    //
    //  Now try to open the token for the specified desired access
    //

    Status = ObOpenObjectByPointer(
                 (PVOID)Token,         // Object
                 0,                    // HandleAttributes
                 NULL,                 // AccessState
                 DesiredAccess,        // DesiredAccess
                 SepTokenObjectType,   // ObjectType
                 PreviousMode,         // AccessMode
                 &LocalHandle          // Handle
                 );

    //
    //  And decrement the reference count of the token to counter
    //  the action performed by PsOpenTokenOfProcess().  If the open
    //  was successful, the handle will have caused the token's
    //  reference count to have been incremented.
    //

    ObDereferenceObject( Token );

    //
    //  Return the new handle
    //

    if (NT_SUCCESS(Status)) {

        try {

            *TokenHandle = LocalHandle;

        } except(EXCEPTION_EXECUTE_HANDLER) {

            return GetExceptionCode();

        }
    }

    return Status;

}
Beispiel #11
0
NTSTATUS
NtCreateMutant (
    OUT PHANDLE MutantHandle,
    IN ACCESS_MASK DesiredAccess,
    IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
    IN BOOLEAN InitialOwner
    )

/*++

Routine Description:

    This function creates a mutant object, sets its initial count to one
    (signaled), and opens a handle to the object with the specified desired
    access.

Arguments:

    MutantHandle - Supplies a pointer to a variable that will receive the
        mutant object handle.

    DesiredAccess - Supplies the desired types of access for the mutant
        object.

    ObjectAttributes - Supplies a pointer to an object attributes structure.

    InitialOwner - Supplies a boolean value that determines whether the
        creator of the object desires immediate ownership of the object.

Return Value:

    TBS

--*/

{

    HANDLE Handle;
    PVOID Mutant;
    KPROCESSOR_MODE PreviousMode;
    NTSTATUS Status;

    //
    // Establish an exception handler, probe the output handle address, and
    // attempt to create a mutant object. If the probe fails, then return the
    // exception code as the service status. Otherwise return the status value
    // returned by the object insertion routine.
    //

    try {

        //
        // Get previous processor mode and probe output handle address if
        // necessary.
        //

        PreviousMode = KeGetPreviousMode();
        if (PreviousMode != KernelMode) {
            ProbeForWriteHandle(MutantHandle);
        }

        //
        // Allocate mutant object.
        //

        Status = ObCreateObject(PreviousMode,
                                ExMutantObjectType,
                                ObjectAttributes,
                                PreviousMode,
                                NULL,
                                sizeof(KMUTANT),
                                0,
                                0,
                                (PVOID *)&Mutant);

        //
        // If the mutant object was successfully allocated, then initialize
        // the mutant object and attempt to insert the mutant object in the
        // current process' handle table.
        //

        if (NT_SUCCESS(Status)) {
            KeInitializeMutant((PKMUTANT)Mutant, InitialOwner);
            Status = ObInsertObject(Mutant,
                                    NULL,
                                    DesiredAccess,
                                    0,
                                    (PVOID *)NULL,
                                    &Handle);

            //
            // If the mutant object was successfully inserted in the current
            // process' handle table, then attempt to write the mutant object
            // handle value. If the write attempt fails, then do not report
            // an error. When the caller attempts to access the handle value,
            // an access violation will occur.
            //

            if (NT_SUCCESS(Status)) {
                try {
                    *MutantHandle = Handle;

                } except(ExSystemExceptionFilter()) {
                }
            }
        }

    //
    // If an exception occurs during the probe of the output handle address,
    // then always handle the exception and return the exception code as the
    // status value.
    //

    } except(ExSystemExceptionFilter()) {
        return GetExceptionCode();
    }

    //
    // Return service status.
    //

    return Status;
}
Beispiel #12
0
NTSTATUS
NtOpenProcess (
    __out PHANDLE ProcessHandle,
    __in ACCESS_MASK DesiredAccess,
    __in POBJECT_ATTRIBUTES ObjectAttributes,
    __in_opt PCLIENT_ID ClientId
    )

/*++

Routine Description:

    This function opens a handle to a process object with the specified
    desired access.

    The object is located either by name, or by locating a thread whose
    Client ID matches the specified Client ID and then opening that thread's
    process.

Arguments:

    ProcessHandle - Supplies a pointer to a variable that will receive
        the process object handle.

    DesiredAccess - Supplies the desired types of access for the process
        object.

    ObjectAttributes - Supplies a pointer to an object attributes structure.
        If the ObjectName field is specified, then ClientId must not be
        specified.

    ClientId - Supplies a pointer to a ClientId that if supplied
        specifies the thread whose process is to be opened. If this
        argument is specified, then ObjectName field of the ObjectAttributes
        structure must not be specified.

Return Value:

    NTSTATUS - Status of call

--*/

{

    HANDLE Handle;
    KPROCESSOR_MODE PreviousMode;
    NTSTATUS Status;
    PEPROCESS Process;
    PETHREAD Thread;
    CLIENT_ID CapturedCid={0};
    BOOLEAN ObjectNamePresent;
    BOOLEAN ClientIdPresent;
    ACCESS_STATE AccessState;
    AUX_ACCESS_DATA AuxData;
    ULONG Attributes;

    PAGED_CODE();

    //
    // Make sure that only one of either ClientId or ObjectName is
    // present.
    //

    PreviousMode = KeGetPreviousMode();
    if (PreviousMode != KernelMode) {

        //
        // Since we need to look at the ObjectName field, probe
        // ObjectAttributes and capture object name present indicator.
        //

        try {

            ProbeForWriteHandle (ProcessHandle);

            ProbeForReadSmallStructure (ObjectAttributes,
                                        sizeof(OBJECT_ATTRIBUTES),
                                        sizeof(ULONG));
            ObjectNamePresent = (BOOLEAN)ARGUMENT_PRESENT (ObjectAttributes->ObjectName);
            Attributes = ObSanitizeHandleAttributes (ObjectAttributes->Attributes, UserMode);

            if (ARGUMENT_PRESENT (ClientId)) {
                ProbeForReadSmallStructure (ClientId, sizeof (CLIENT_ID), sizeof (ULONG));
                CapturedCid = *ClientId;
                ClientIdPresent = TRUE;
            } else {
                ClientIdPresent = FALSE;
            }
        } except (EXCEPTION_EXECUTE_HANDLER) {
            return GetExceptionCode();
        }
    } else {
Beispiel #13
0
NTSTATUS
NtCreateSemaphore (
    __out PHANDLE SemaphoreHandle,
    __in ACCESS_MASK DesiredAccess,
    __in_opt POBJECT_ATTRIBUTES ObjectAttributes,
    __in LONG InitialCount,
    __in LONG MaximumCount
    )

/*++

Routine Description:

    This function creates a semaphore object, sets its initial count to the
    specified value, sets its maximum count to the specified value, and opens
    a handle to the object with the specified desired access.

Arguments:

    SemaphoreHandle - Supplies a pointer to a variable that will receive the
        semaphore object handle.

    DesiredAccess - Supplies the desired types of access for the semaphore
        object.

    ObjectAttributes - Supplies a pointer to an object attributes structure.

    InitialCount - Supplies the initial count of the semaphore object.

    MaximumCount - Supplies the maximum count of the semaphore object.

Return Value:

    NTSTATUS.

--*/

{

    HANDLE Handle;
    KPROCESSOR_MODE PreviousMode;
    PVOID Semaphore;
    NTSTATUS Status;

    //
    // Get previous processor mode and probe output handle address if
    // necessary.
    //

    PreviousMode = KeGetPreviousMode();
    if (PreviousMode != KernelMode) {
        try {
            ProbeForWriteHandle(SemaphoreHandle);

        } except(EXCEPTION_EXECUTE_HANDLER) {
            return GetExceptionCode();
        }
    }

    //
    // Check argument validity.
    //

    if ((MaximumCount <= 0) || (InitialCount < 0) ||
       (InitialCount > MaximumCount)) {

        return STATUS_INVALID_PARAMETER;
    }

    //
    // Allocate semaphore object.
    //

    Status = ObCreateObject(PreviousMode,
                            ExSemaphoreObjectType,
                            ObjectAttributes,
                            PreviousMode,
                            NULL,
                            sizeof(KSEMAPHORE),
                            0,
                            0,
                            &Semaphore);

    //
    // If the semaphore object was successfully allocated, then initialize
    // the semaphore object and attempt to insert the semaphore object in
    // the current process' handle table.
    //

    if (NT_SUCCESS(Status)) {
        KeInitializeSemaphore((PKSEMAPHORE)Semaphore,
                              InitialCount,
                              MaximumCount);

        Status = ObInsertObject(Semaphore,
                                NULL,
                                DesiredAccess,
                                0,
                                NULL,
                                &Handle);

        //
        // If the semaphore object was successfully inserted in the current
        // process' handle table, then attempt to write the semaphore handle
        // value. If the write attempt fails, then do not report an error.
        // When the caller attempts to access the handle value, an access
        // violation will occur.
        //

        if (NT_SUCCESS(Status)) {
            if (PreviousMode != KernelMode) {
                try {
                    *SemaphoreHandle = Handle;

                } except(EXCEPTION_EXECUTE_HANDLER) {
                    NOTHING;
                }

            } else {
                *SemaphoreHandle = Handle;
            }
        }
    }
Beispiel #14
0
NTSTATUS
NtConnectPort(
    OUT PHANDLE PortHandle,
    IN PUNICODE_STRING PortName,
    IN PSECURITY_QUALITY_OF_SERVICE SecurityQos,
    IN OUT PPORT_VIEW ClientView OPTIONAL,
    OUT PREMOTE_PORT_VIEW ServerView OPTIONAL,
    OUT PULONG MaxMessageLength OPTIONAL,
    IN OUT PVOID ConnectionInformation OPTIONAL,
    IN OUT PULONG ConnectionInformationLength OPTIONAL
    )

/*++

Routine Description:

    A client process can connect to a server process by name using the
    NtConnectPort service.

    The PortName parameter specifies the name of the server port to
    connect to.  It must correspond to an object name specified on a
    call to NtCreatePort.  The service sends a connection request to the
    server thread that is listening for them with the NtListenPort
    service.  The client thread then blocks until a server thread
    receives the connection request and responds with a call to the
    NtCompleteConnectPort service.  The server thread receives the ID of
    the client thread, along with any information passed via the
    ConnectionInformation parameter.  The server thread then decides to
    either accept or reject the connection request.

    The server communicates the acceptance or rejection with the
    NtCompleteConnectPort service.  The server can pass back data to the
    client about the acceptance or rejection via the
    ConnectionInformation data block.

    If the server accepts the connection request, then the client
    receives a communication port object in the location pointed to by
    the PortHandle parameter.  This object handle has no name associated
    with it and is private to the client process (i.e.  it cannot be
    inherited by a child process).  The client uses the handle to send
    and receive messages to/from the server process using the
    NtRequestWaitReplyPort service.

    If the ClientView parameter was specified, then the section handle
    is examined.  If it is a valid section handle, then the portion of
    the section described by the SectionOffset and ViewSize fields will
    be mapped into both the client and server process' address spaces.
    The address in client address space will be returned in the ViewBase
    field.  The address in the server address space will be returned in
    the ViewRemoteBase field.  The actual offset and size used to map
    the section will be returned in the SectionOffset and ViewSize
    fields.

    If the server rejects the connection request, then no communication
    port object handle is returned, and the return status indicates an
    error occurred.  The server may optionally return information in the
    ConnectionInformation data block giving the reason the connection
    requests was rejected.

    If the PortName does not exist, or the client process does not have
    sufficient access rights then the returned status will indicate that
    the port was not found.

Arguments:

    PortHandle - A pointer to a variable that will receive the client
        communication port object handle value.

    !f PortName - A pointer to a port name string.  The form of the name
        is [\name...\name]\port_name.

    !f SecurityQos - A pointer to security quality of service information
        to be applied to the server on the client's behalf.

    ClientView - An optional pointer to a structure that specifies the
        section that all client threads will use to send messages to the
        server.

    !b !u ClientView Structure

        ULONG !f Length - Specifies the size of this data structure in
            bytes.

        HANDLE !f SectionHandle - Specifies an open handle to a section
            object.

        ULONG !f SectionOffset - Specifies a field that will receive the
            actual offset, in bytes, from the start of the section.  The
            initial value of this parameter specifies the byte offset
            within the section that the client's view is based.  The
            value is rounded down to the next host page size boundary.

        ULONG !f ViewSize - Specifies a field that will receive the
            actual size, in bytes, of the view.  If the value of this
            parameter is zero, then the client's view of the section
            will be mapped starting at the specified section offset and
            continuing to the end of the section.  Otherwise, the
            initial value of this parameter specifies the size, in
            bytes, of the client's view and is rounded up to the next
            host page size boundary.

        PVOID !f ViewBase - Specifies a field that will receive the base
            address of the section in the client's address space.

        PVOID !f ViewRemoteBase - Specifies a field that will receive
            the base address of the client's section in the server's
            address space.  Used to generate pointers that are
            meaningful to the server.

    ServerView - An optional pointer to a structure that will receive
        information about the server process' view in the client's
        address space.  The client process can use this information
        to validate pointers it receives from the server process.

    !b !u ServerView Structure

        ULONG !f Length - Specifies the size of this data structure in
            bytes.

        PVOID !f ViewBase - Specifies a field that will receive the base
            address of the server's section in the client's address
            space.

        ULONG !f ViewSize - Specifies a field that will receive the
            size, in bytes, of the server's view in the client's address
            space.  If this field is zero, then server has no view in
            the client's address space.

    MaxMessageLength - An optional pointer to a variable that will
        receive maximum length of messages that can be sent to the
        server.  The value of this parameter will not exceed
        MAX_PORTMSG_LENGTH bytes.

    ConnectionInformation - An optional pointer to uninterpreted data.
        This data is intended for clients to pass package, version and
        protocol identification information to the server to allow the
        server to determine if it can satisify the client before
        accepting the connection.  Upon return to the client, the
        ConnectionInformation data block contains any information passed
        back from the server by its call to the NtCompleteConnectPort
        service.  The output data overwrites the input data.

    ConnectionInformationLength - Pointer to the length of the
        ConnectionInformation data block.  The output value is the
        length of the data stored in the ConnectionInformation data
        block by the server's call to the NtCompleteConnectPort
        service.  This parameter is OPTIONAL only if the
        ConnectionInformation parameter is null, otherwise it is
        required.

Return Value:

    return-value - Description of conditions needed to return value. - or -
    None.

--*/

{
    PLPCP_PORT_OBJECT ConnectionPort;
    PLPCP_PORT_OBJECT ClientPort;
    HANDLE Handle;
    KPROCESSOR_MODE PreviousMode;
    NTSTATUS Status;
    ULONG ConnectionInfoLength;
    PVOID SectionToMap;
    PLPCP_MESSAGE Msg;
    PLPCP_CONNECTION_MESSAGE ConnectMsg;
    PETHREAD CurrentThread = PsGetCurrentThread();
    LARGE_INTEGER SectionOffset;
    PORT_VIEW CapturedClientView;
    SECURITY_QUALITY_OF_SERVICE CapturedQos;

    PAGED_CODE();

    //
    // Get previous processor mode and probe output arguments if necessary.
    //

    PreviousMode = KeGetPreviousMode();
    ConnectionInfoLength = 0;
    if (PreviousMode != KernelMode) {
        try {
            ProbeForWriteHandle( PortHandle );

            if (ARGUMENT_PRESENT( ClientView )) {
                if (ClientView->Length != sizeof( *ClientView )) {
                    return( STATUS_INVALID_PARAMETER );
                    }

                CapturedClientView = *ClientView;
                ProbeForWrite( ClientView,
                               sizeof( *ClientView ),
                               sizeof( ULONG )
                             );
                }

            if (ARGUMENT_PRESENT( ServerView )) {
                if (ServerView->Length != sizeof( *ServerView )) {
                    return( STATUS_INVALID_PARAMETER );
                    }

                ProbeForWrite( ServerView,
                               sizeof( *ServerView ),
                               sizeof( ULONG )
                             );
                }

            if (ARGUMENT_PRESENT( MaxMessageLength )) {
                ProbeForWriteUlong( MaxMessageLength );
                }

            if (ARGUMENT_PRESENT( ConnectionInformationLength )) {
                ProbeForWriteUlong( ConnectionInformationLength );
                ConnectionInfoLength = *ConnectionInformationLength;
                }

            if (ARGUMENT_PRESENT( ConnectionInformation )) {
                ProbeForWrite( ConnectionInformation,
                               ConnectionInfoLength,
                               sizeof( UCHAR )
                             );
                }

            ProbeForRead( SecurityQos,
                          sizeof( SECURITY_QUALITY_OF_SERVICE ),
                          sizeof( ULONG )
                          );
            CapturedQos = *SecurityQos;

            }
        except( EXCEPTION_EXECUTE_HANDLER ) {
            return( GetExceptionCode() );
            }
        }
    else {
        if (ARGUMENT_PRESENT( ClientView )) {
Beispiel #15
0
NTSTATUS
NtCreateEvent (
    OUT PHANDLE EventHandle,
    IN ACCESS_MASK DesiredAccess,
    IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
    IN EVENT_TYPE EventType,
    IN BOOLEAN InitialState
)

/*++

Routine Description:

    This function creates an event object, sets it initial state to the
    specified value, and opens a handle to the object with the specified
    desired access.

Arguments:

    EventHandle - Supplies a pointer to a variable that will receive the
        event object handle.

    DesiredAccess - Supplies the desired types of access for the event object.

    ObjectAttributes - Supplies a pointer to an object attributes structure.

    EventType - Supplies the type of the event (autoclearing or notification).

    InitialState - Supplies the initial state of the event object.

Return Value:

    TBS

--*/

{

    PVOID Event;
    HANDLE Handle;
    KPROCESSOR_MODE PreviousMode;
    NTSTATUS Status;

    //
    // Establish an exception handler, probe the output handle address, and
    // attempt to create an event object. If the probe fails, then return the
    // exception code as the service status. Otherwise return the status value
    // returned by the object insertion routine.
    //

    try {

        //
        // Get previous processor mode and probe output handle address if
        // necessary.
        //

        PreviousMode = KeGetPreviousMode();
        if (PreviousMode != KernelMode) {
            ProbeForWriteHandle(EventHandle);
        }

        //
        // Check argument validity.
        //

        if ((EventType != NotificationEvent) && (EventType != SynchronizationEvent)) {
            return STATUS_INVALID_PARAMETER;
        }

        //
        // Allocate event object.
        //

        Status = ObCreateObject(PreviousMode,
                                ExEventObjectType,
                                ObjectAttributes,
                                PreviousMode,
                                NULL,
                                sizeof(KEVENT),
                                0,
                                0,
                                (PVOID *)&Event);

        //
        // If the event object was successfully allocated, then initialize the
        // event object and attempt to insert the event object in the current
        // process' handle table.
        //

        if (NT_SUCCESS(Status)) {
            KeInitializeEvent((PKEVENT)Event, EventType, InitialState);
            Status = ObInsertObject(Event,
                                    NULL,
                                    DesiredAccess,
                                    0,
                                    (PVOID *)NULL,
                                    &Handle);

            //
            // If the event object was successfully inserted in the current
            // process' handle table, then attempt to write the event object
            // handle value. If the write attempt fails, then do not report
            // an error. When the caller attempts to access the handle value,
            // an access violation will occur.
            //

            if (NT_SUCCESS(Status)) {
                try {
                    *EventHandle = Handle;

                }
                except(ExSystemExceptionFilter()) {
                }
            }
        }

        //
        // If an exception occurs during the probe of the output handle address,
        // then always handle the exception and return the exception code as the
        // status value.
        //

    } except(ExSystemExceptionFilter()) {
        return GetExceptionCode();
    }

    //
    // Return service status.
    //

    return Status;
}
Beispiel #16
0
NTSTATUS
NtOpenEvent (
    OUT PHANDLE EventHandle,
    IN ACCESS_MASK DesiredAccess,
    IN POBJECT_ATTRIBUTES ObjectAttributes
)

/*++

Routine Description:

    This function opens a handle to an event object with the specified
    desired access.

Arguments:

    EventHandle - Supplies a pointer to a variable that will receive the
        event object handle.

    DesiredAccess - Supplies the desired types of access for the event object.

    ObjectAttributes - Supplies a pointer to an object attributes structure.

Return Value:

    TBS

--*/

{

    HANDLE Handle;
    KPROCESSOR_MODE PreviousMode;
    NTSTATUS Status;


    //
    // Establish an exception handler, probe the output handle address, and
    // attempt to open the event object. If the probe fails, then return the
    // exception code as the service status. Otherwise return the status value
    // returned by the object open routine.
    //

    try {

        //
        // Get previous processor mode and probe output handle address
        // if necessary.
        //

        PreviousMode = KeGetPreviousMode();
        if (PreviousMode != KernelMode) {
            ProbeForWriteHandle(EventHandle);
        }

        //
        // Open handle to the event object with the specified desired access.
        //

        Status = ObOpenObjectByName(ObjectAttributes,
                                    ExEventObjectType,
                                    PreviousMode,
                                    NULL,
                                    DesiredAccess,
                                    NULL,
                                    &Handle);

        //
        // If the open was successful, then attempt to write the event object
        // handle value. If the write attempt fails, then do not report an
        // error. When the caller attempts to access the handle value, an
        // access violation will occur.
        //

        if (NT_SUCCESS(Status)) {
            try {
                *EventHandle = Handle;

            }
            except(ExSystemExceptionFilter()) {
            }
        }

        //
        // If an exception occurs during the probe of the output event handle,
        // then always handle the exception and return the exception code as the
        // status value.
        //

    } except(ExSystemExceptionFilter()) {
        return GetExceptionCode();
    }

    //
    // Return service status.
    //

    return Status;
}
Beispiel #17
0
NTSTATUS
NtOpenThreadToken(
    IN HANDLE ThreadHandle,
    IN ACCESS_MASK DesiredAccess,
    IN BOOLEAN OpenAsSelf,
    OUT PHANDLE TokenHandle
    )

/*++


Routine Description:

Open a token object associated with a thread and return a handle that
may be used to access that token.

Arguments:

    ThreadHandle - Specifies the thread whose token is to be opened.

    DesiredAccess - Is an access mask indicating which access types
        are desired to the token.  These access types are reconciled
        with the Discretionary Access Control list of the token to
        determine whether the accesses will be granted or denied.

    OpenAsSelf - Is a boolean value indicating whether the access should
        be made using the calling thread's current security context, which
        may be that of a client if impersonating, or using the caller's
        process-level security context.  A value of FALSE indicates the
        caller's current context should be used un-modified.  A value of
        TRUE indicates the request should be fulfilled using the process
        level security context.

        This parameter is necessary to allow a server process to open
        a client's token when the client specified IDENTIFICATION level
        impersonation.  In this case, the caller would not be able to
        open the client's token using the client's context (because you
        can't create executive level objects using IDENTIFICATION level
        impersonation).

    TokenHandle - Receives the handle of the newly opened token.

Return Value:

    STATUS_SUCCESS - Indicates the operation was successful.

    STATUS_NO_TOKEN - Indicates an attempt has been made to open a
        token associated with a thread that is not currently
        impersonating a client.

    STATUS_CANT_OPEN_ANONYMOUS - Indicates the client requested anonymous
        impersonation level.  An anonymous token can not be openned.

--*/
{

    KPROCESSOR_MODE PreviousMode;
    NTSTATUS Status;

    PVOID Token;
    PTOKEN NewToken = NULL;
    BOOLEAN CopyOnOpen;
    BOOLEAN EffectiveOnly;
    SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
    SE_IMPERSONATION_STATE DisabledImpersonationState;
    BOOLEAN RestoreImpersonationState = FALSE;

    HANDLE LocalHandle;
    SECURITY_DESCRIPTOR SecurityDescriptor;
    OBJECT_ATTRIBUTES ObjectAttributes;
    PACL NewAcl = NULL;
    PETHREAD Thread;
    PETHREAD OriginalThread = NULL;
    PACCESS_TOKEN PrimaryToken;
    SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;

    PAGED_CODE();

    PreviousMode = KeGetPreviousMode();

    //
    //  Probe parameters
    //

    if (PreviousMode != KernelMode) {

        try {

            ProbeForWriteHandle(TokenHandle);

        } except(EXCEPTION_EXECUTE_HANDLER) {
            return GetExceptionCode();
        }  // end_try

    } //end_if

    //
    // Valdiate access to the thread and obtain a pointer to the
    // thread's token (if there is one).  If successful, this will
    // cause the token's reference count to be incremented.
    //
    // This routine disabled impersonation as necessary to properly
    // honor the OpenAsSelf flag.
    //

    Status = SepOpenTokenOfThread( ThreadHandle,
                                  OpenAsSelf,
                                  ((PACCESS_TOKEN *)&Token),
                                  &OriginalThread,
                                  &CopyOnOpen,
                                  &EffectiveOnly,
                                  &ImpersonationLevel
                                  );

    if (!NT_SUCCESS(Status)) {
        return Status;
    }


    //
    //  The token was successfully referenced.
    //

    //
    // We need to create and/or open a token object, so disable impersonation
    // if necessary.
    //

    if (OpenAsSelf) {
         RestoreImpersonationState = PsDisableImpersonation(
                                         PsGetCurrentThread(),
                                         &DisabledImpersonationState
                                         );
    }

    //
    //  If the CopyOnOpen flag is not set, then the token can be
    //  opened directly.  Otherwise, the token must be duplicated,
    //  and a handle to the duplicate returned.
    //

    if (CopyOnOpen) {

        //
        // Create the new security descriptor for the token.
        //
        // We must obtain the correct SID to put into the Dacl.  Do this
        // by finding the process associated with the passed thread
        // and grabbing the User SID out of that process's token.
        // If we just use the current SubjectContext, we'll get the
        // SID of whoever is calling us, which isn't what we want.
        //

        Status = ObReferenceObjectByHandle(
                     ThreadHandle,
                     THREAD_ALL_ACCESS,
                     PsThreadType,
                     KernelMode,
                     (PVOID)&Thread,
                     NULL
                     );

        //
        // Verify that the handle is still pointer to the same thread\
        // BUGBUG: wrong error code.
        //

        if (NT_SUCCESS(Status) && (Thread != OriginalThread)) {
            Status = STATUS_OBJECT_TYPE_MISMATCH;
        }

        if (NT_SUCCESS(Status)) {

            PrimaryToken = PsReferencePrimaryToken(Thread->ThreadsProcess);

            Status = SepCreateImpersonationTokenDacl(
                         (PTOKEN)Token,
                         PrimaryToken,
                         &NewAcl
                         );

            PsDereferencePrimaryToken( PrimaryToken );

            if (NT_SUCCESS( Status )) {

                if (NewAcl != NULL) {

                    //
                    // There exist tokens that either do not have security descriptors at all,
                    // or have security descriptors, but do not have DACLs.  In either case, do
                    // nothing.
                    //

                    Status = RtlCreateSecurityDescriptor ( &SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION );
                    ASSERT( NT_SUCCESS( Status ));

                    Status = RtlSetDaclSecurityDescriptor (
                                 &SecurityDescriptor,
                                 TRUE,
                                 NewAcl,
                                 FALSE
                                 );

                    ASSERT( NT_SUCCESS( Status ));
                }

                InitializeObjectAttributes(
                    &ObjectAttributes,
                    NULL,
                    0L,
                    NULL,
                    NewAcl == NULL ? NULL : &SecurityDescriptor
                    );

                //
                // Open a copy of the token
                //

                Status = SepDuplicateToken(
                             (PTOKEN)Token,        // ExistingToken
                             &ObjectAttributes,    // ObjectAttributes
                             EffectiveOnly,        // EffectiveOnly
                             TokenImpersonation,   // TokenType
                             ImpersonationLevel,   // ImpersonationLevel
                             KernelMode,           // RequestorMode must be kernel mode
                             &NewToken
                             );

                if (NT_SUCCESS( Status )) {

                    //
                    // Reference the token so it doesn't go away
                    //

                    ObReferenceObject(NewToken);

                    //
                    //  Insert the new token
                    //

                    Status = ObInsertObject( NewToken,
                                             NULL,
                                             DesiredAccess,
                                             0,
                                             (PVOID *)NULL,
                                             &LocalHandle
                                             );
                }
            }
        }


    } else {

        //
        // We do not have to modify the security on the token in the static case,
        // because in all the places in the system where impersonation takes place
        // over a secure transport (e.g., LPC), CopyOnOpen is set.  The only reason
        // we'be be here is if the impersonation is taking place because someone did
        // an NtSetInformationThread and passed in a token.
        //
        // In that case, we absolutely do not want to give the caller guaranteed
        // access, because that would allow anyone who has access to a thread to
        // impersonate any of that thread's clients for any access.
        //

        //
        //  Open the existing token
        //

        Status = ObOpenObjectByPointer(
                     (PVOID)Token,         // Object
                     0,                    // HandleAttributes
                     NULL,                 // AccessState
                     DesiredAccess,        // DesiredAccess
                     SepTokenObjectType,   // ObjectType
                     PreviousMode,         // AccessMode
                     &LocalHandle          // Handle
                     );
    }

    if (NewAcl != NULL) {
        ExFreePool( NewAcl );
    }

    if (RestoreImpersonationState) {
        PsRestoreImpersonation(
            PsGetCurrentThread(),
            &DisabledImpersonationState
            );
    }

    //
    //  And decrement the reference count of the existing token to counter
    //  the action performed by PsOpenTokenOfThread.  If the open
    //  was successful, the handle will have caused the token's
    //  reference count to have been incremented.
    //

    ObDereferenceObject( Token );

    if (NT_SUCCESS( Status ) && CopyOnOpen) {

        //
        // Assign the newly duplicated token to the thread.
        //

        PsImpersonateClient( Thread,
                             NewToken,
                             FALSE,  // turn off CopyOnOpen flag
                             EffectiveOnly,
                             ImpersonationLevel
                             );

    }

    //
    // We've impersonated the token so let go of oure reference
    //

    if (NewToken != NULL) {
        ObDereferenceObject( NewToken );
    }

    if (CopyOnOpen && (Thread != NULL)) {

        ObDereferenceObject( Thread );
    }

    if (OriginalThread != NULL) {
        ObDereferenceObject(OriginalThread);
    }

    //
    //  Return the new handle
    //

    if (NT_SUCCESS(Status)) {
        try { *TokenHandle = LocalHandle; }
            except(EXCEPTION_EXECUTE_HANDLER) { return GetExceptionCode(); }
    }

    return Status;

}
Beispiel #18
0
NTSTATUS
NtCreateEvent (
    __out PHANDLE EventHandle,
    __in ACCESS_MASK DesiredAccess,
    __in_opt POBJECT_ATTRIBUTES ObjectAttributes,
    __in EVENT_TYPE EventType,
    __in BOOLEAN InitialState
    )

/*++

Routine Description:

    This function creates an event object, sets it initial state to the
    specified value, and opens a handle to the object with the specified
    desired access.

Arguments:

    EventHandle - Supplies a pointer to a variable that will receive the
        event object handle.

    DesiredAccess - Supplies the desired types of access for the event object.

    ObjectAttributes - Supplies a pointer to an object attributes structure.

    EventType - Supplies the type of the event (autoclearing or notification).

    InitialState - Supplies the initial state of the event object.

Return Value:

    NTSTATUS.

--*/

{

    PVOID Event;
    HANDLE Handle;
    KPROCESSOR_MODE PreviousMode;
    NTSTATUS Status;

    //
    // Get previous processor mode and probe output handle address if
    // necessary.
    //

    PreviousMode = KeGetPreviousMode();
    if (PreviousMode != KernelMode) {
        try {
            ProbeForWriteHandle(EventHandle);

        } except(EXCEPTION_EXECUTE_HANDLER) {
            return GetExceptionCode();
        }
    }

    //
    // Check argument validity.
    //

    if ((EventType != NotificationEvent) && (EventType != SynchronizationEvent)) {
        return STATUS_INVALID_PARAMETER;
    }

    //
    // Allocate event object.
    //

    Status = ObCreateObject(PreviousMode,
                            ExEventObjectType,
                            ObjectAttributes,
                            PreviousMode,
                            NULL,
                            sizeof(KEVENT),
                            0,
                            0,
                            &Event);

    //
    // If the event object was successfully allocated, then initialize the
    // event object and attempt to insert the event object in the current
    // process' handle table.
    //

    if (NT_SUCCESS(Status)) {
        KeInitializeEvent((PKEVENT)Event, EventType, InitialState);
        Status = ObInsertObject(Event,
                                NULL,
                                DesiredAccess,
                                0,
                                NULL,
                                &Handle);

        //
        // If the event object was successfully inserted in the current
        // process' handle table, then attempt to write the event object
        // handle value. If the write attempt fails, then do not report
        // an error. When the caller attempts to access the handle value,
        // an access violation will occur.
        //

        if (NT_SUCCESS(Status)) {
            if (PreviousMode != KernelMode) {
                try {
                    *EventHandle = Handle;

                } except(EXCEPTION_EXECUTE_HANDLER) {
                    NOTHING;
                }

            } else {
                *EventHandle = Handle;
            }
        }
    }
Beispiel #19
0
NTSTATUS
NtOpenIoCompletion (
    __out PHANDLE IoCompletionHandle,
    __in ACCESS_MASK DesiredAccess,
    __in POBJECT_ATTRIBUTES ObjectAttributes
    )

/*++

Routine Description:

    This function opens a handle to an I/O completion object with the
    specified desired access.

Arguments:

    IoCompletionHandle - Supplies a pointer to a variable that receives
        the completion object handle.

    DesiredAccess - Supplies the desired types of access for the I/O
        completion object.

    ObjectAttributes - Supplies a pointer to an object attributes structure.

Return Value:

    STATUS_SUCCESS is returned if the function is success. Otherwise, an
    error status is returned.

--*/

{

    HANDLE Handle;
    KPROCESSOR_MODE PreviousMode;
    NTSTATUS Status;

    //
    // Establish an exception handler, probe the output handle address,
    // and attempt to open an I/O completion object. If the probe fails,
    // then return the exception code as the service status. Otherwise,
    // return the status value returned by the object open routine.
    //

    try {

        //
        // Get previous processor mode and probe output handle address if
        // necessary.
        //

        PreviousMode = KeGetPreviousMode();
        if (PreviousMode != KernelMode) {
            ProbeForWriteHandle(IoCompletionHandle);
        }

        //
        // Open handle to the completion object with the specified desired
        // access.
        //

        Status = ObOpenObjectByName(ObjectAttributes,
                                    IoCompletionObjectType,
                                    PreviousMode,
                                    NULL,
                                    DesiredAccess,
                                    NULL,
                                    &Handle);

        //
        // If the open was successful, then attempt to write the I/O
        // completion object handle value. If the write attempt fails,
        // then do not report an error. When the caller attempts to
        // access the handle value, an access violation will occur.
        //

        if (NT_SUCCESS(Status)) {
            try {
                *IoCompletionHandle = Handle;

            } except(ExSystemExceptionFilter()) {
                NOTHING;
            }
        }

    //
    // If an exception occurs during the probe of the output handle address,
    // then always handle the exception and return the exception code as the
    // status value.
    //

    } except(ExSystemExceptionFilter()) {
        Status = GetExceptionCode();
    }


    //
    // Return service status.
    //

    return Status;
}
Beispiel #20
0
NTSTATUS
NtCreateIoCompletion (
    __out PHANDLE IoCompletionHandle,
    __in ACCESS_MASK DesiredAccess,
    __in_opt POBJECT_ATTRIBUTES ObjectAttributes,
    __in ULONG Count OPTIONAL
    )

/*++

Routine Description:

    This function creates an I/O completion object, sets the maximum
    target concurrent thread count to the specified value, and opens
    a handle to the object with the specified desired access.

Arguments:

    IoCompletionHandle - Supplies a pointer to a variable that receives
        the I/O completion object handle.

    DesiredAccess - Supplies the desired types of access for the I/O
        completion object.

    ObjectAttributes - Supplies a pointer to an object attributes structure.

    Count - Supplies the target maximum  number of threads that should
        be concurrently active. If this parameter is not specified, then
        the number of processors is used.

Return Value:

    STATUS_SUCCESS is returned if the function is success. Otherwise, an
    error status is returned.

--*/

{

    HANDLE Handle;
    KPROCESSOR_MODE PreviousMode;
    PVOID IoCompletion;
    NTSTATUS Status;

    //
    // Establish an exception handler, probe the output handle address, and
    // attempt to create an I/O completion object. If the probe fails, then
    // return the exception code as the service status. Otherwise, return the
    // status value returned by the object insertion routine.
    //

    try {

        //
        // Get previous processor mode and probe output handle address if
        // necessary.
        //

        PreviousMode = KeGetPreviousMode();
        if (PreviousMode != KernelMode) {
            ProbeForWriteHandle(IoCompletionHandle);
        }

        //
        // Allocate I/O completion object.
        //

        Status = ObCreateObject(PreviousMode,
                                IoCompletionObjectType,
                                ObjectAttributes,
                                PreviousMode,
                                NULL,
                                sizeof(KQUEUE),
                                0,
                                0,
                                (PVOID *)&IoCompletion);

        //
        // If the I/O completion object was successfully allocated, then
        // initialize the object and attempt to insert it in the handle
        // table of the current process.
        //

        if (NT_SUCCESS(Status)) {
            KeInitializeQueue((PKQUEUE)IoCompletion, Count);
            Status = ObInsertObject(IoCompletion,
                                    NULL,
                                    DesiredAccess,
                                    0,
                                    (PVOID *)NULL,
                                    &Handle);

            //
            // If the I/O completion object was successfully inserted in
            // the handle table of the current process, then attempt to
            // write the handle value. If the write attempt fails, then
            // do not report an error. When the caller attempts to access
            // the handle value, an access violation will occur.
            //

            if (NT_SUCCESS(Status)) {
                try {
                    *IoCompletionHandle = Handle;

                } except(ExSystemExceptionFilter()) {
                    NOTHING;
                }
            }
        }

    //
    // If an exception occurs during the probe of the output handle address,
    // then always handle the exception and return the exception code as the
    // status value.
    //

    } except(ExSystemExceptionFilter()) {
        Status = GetExceptionCode();
    }

    //
    // Return service status.
    //

    return Status;
}
Beispiel #21
0
NTSTATUS
NtCreateSymbolicLinkObject(
    OUT PHANDLE LinkHandle,
    IN ACCESS_MASK DesiredAccess,
    IN POBJECT_ATTRIBUTES ObjectAttributes,
    IN PUNICODE_STRING LinkTarget
    )
/*++

Routine Description:

    This function creates a symbolic link object, sets it initial value to
    value specified in the LinkTarget parameter, and opens a handle to the
    object with the specified desired access.

Arguments:

    LinkHandle - Supplies a pointer to a variable that will receive the
        symbolic link object handle.

    DesiredAccess - Supplies the desired types of access for the symbolic link
        object.

    ObjectAttributes - Supplies a pointer to an object attributes structure.

    LinkTarget - Supplies the target name for the symbolic link object.


Return Value:

    TBS

--*/

{
    KPROCESSOR_MODE PreviousMode;
    NTSTATUS Status;
    POBJECT_SYMBOLIC_LINK SymbolicLink;
    PVOID Object;
    HANDLE Handle;
    UNICODE_STRING CapturedLinkTarget;
    UNICODE_STRING CapturedLinkName;
    ULONG CapturedAttributes;

    PAGED_CODE();

    //
    // Get previous processor mode and probe output arguments if necessary.
    //

    PreviousMode = KeGetPreviousMode();
    if (PreviousMode != KernelMode) {
        try {
            CapturedAttributes = ObjectAttributes->Attributes;
            CapturedLinkName = *(ObjectAttributes->ObjectName);
            ProbeForRead( LinkTarget, sizeof( *LinkTarget ), sizeof( UCHAR ) );
            CapturedLinkTarget = *LinkTarget;
            ProbeForRead( CapturedLinkTarget.Buffer,
                          CapturedLinkTarget.MaximumLength,
                          sizeof( UCHAR )
                        );

            ProbeForWriteHandle( LinkHandle );
            }
        except( EXCEPTION_EXECUTE_HANDLER ) {
            return( GetExceptionCode() );
            }

        }
    else {