Beispiel #1
0
NTSTATUS
FsRtlRegisterUncProvider(
    __inout PHANDLE MupHandle,
    __in PUNICODE_STRING RedirDevName,
    __in BOOLEAN MailslotsSupported
    )
/*++

Routine Description:

    This routine registers a redir as a UNC provider.

Arguments:

    Handle - Pointer to a handle.  The handle is returned by the routine
        to be used when calling FsRtlDeregisterUncProvider.
        It is valid only if the routines returns STATUS_SUCCESS.

    RedirDevName - The device name of the redir.

    MailslotsSupported - If TRUE, this redir supports mailslots.

Return Value:

    NTSTATUS - The status of the operation.

--*/
{
    NTSTATUS status;
    HANDLE mupHandle = (HANDLE)-1;
    UNICODE_STRING mupDriverName;
    BOOLEAN dfsEnabled;

    PAGED_CODE();

    KeWaitForSingleObject(&FsRtlpUncSemaphore, Executive, KernelMode, FALSE, NULL );

    if (FsRtlpRedirs == 0) {

        dfsEnabled = FsRtlpIsDfsEnabled();

        if (dfsEnabled) {
            FsRtlpRedirs = 1;
            RtlZeroMemory((PVOID) &FsRtlpDRD, sizeof(FsRtlpDRD));
        }

    }

    switch( FsRtlpRedirs ) {
    case 0:
        //
        // Ok, the MUP isn't there and we don't need to use the
        //   MUP for the first redir.
        //
        // We need to return a handle, but we're not really using the MUP yet.
        //   And we may never use it (if there's only 1 redir).  Return
        //   a handle to the NULL device object, since we're committed to returning
        //   a handle to our caller.  Our caller isn't supposed to do anything with
        //   the handle except to call FsRtlDeregisterUncProvider() with it.
        //
        status = FsRtlpOpenDev( &mupHandle, DevNull );

        if( !NT_SUCCESS( status ) )
            break;

        //
        // Save up enough state to allow us to call the MUP later with
        // this registration info if necessary.
        //
        FsRtlpDRD.RedirDevName.Buffer = ExAllocatePoolWithTag( NonPagedPool, 
                                                               RedirDevName->MaximumLength, 
                                                               MODULE_POOL_TAG );

        if( FsRtlpDRD.RedirDevName.Buffer == NULL ) {
            status =  STATUS_INSUFFICIENT_RESOURCES;
            break;
        }

        FsRtlpDRD.RedirDevName.Length = RedirDevName->Length;
        FsRtlpDRD.RedirDevName.MaximumLength = RedirDevName->MaximumLength;

        RtlCopyMemory(
                (PCHAR)FsRtlpDRD.RedirDevName.Buffer,
                RedirDevName->Buffer,
                RedirDevName->MaximumLength
        );

        FsRtlpDRD.MailslotsSupported = MailslotsSupported;
        FsRtlpDRD.ReturnedHandle = mupHandle;
        FsRtlpDRD.MupHandle = (HANDLE)-1;

        //
        // Set the UNC symbolic link to point to the redir we just loaded
        //
        FsRtlpSetSymbolicLink( RedirDevName );

        break;

    default:
        //
        // This is the second or later redir load -- MUST use the MUP
        //
        status = FsRtlpOpenDev( &mupHandle, DevMup );

        if( !NT_SUCCESS( status ) ) {

            RtlInitUnicodeString( &mupDriverName, MupRegKey );

            (VOID)ZwLoadDriver( &mupDriverName );

            status = FsRtlpOpenDev( &mupHandle, DevMup );
            if( !NT_SUCCESS( status ) )
                break;
        }

        //
        // See if we need to tell the MUP about the first redir that registered
        //
        if( FsRtlpDRD.RedirDevName.Buffer ) {

            status = FsRtlpRegisterProviderWithMUP( mupHandle,
                    &FsRtlpDRD.RedirDevName,
                    FsRtlpDRD.MailslotsSupported );

            if( !NT_SUCCESS( status ) )
                break;

            FsRtlpDRD.MupHandle = mupHandle;

            ExFreePool( FsRtlpDRD.RedirDevName.Buffer );
            FsRtlpDRD.RedirDevName.Buffer = NULL;

            //
            // Set the UNC symbolic link to point to the MUP
            //
            RtlInitUnicodeString(  &mupDriverName, DevMup );
            FsRtlpSetSymbolicLink( &mupDriverName );

            status = FsRtlpOpenDev( &mupHandle, DevMup );

            if( !NT_SUCCESS( status ) )
                break;
        }

        //
        //  Pass the request to the MUP for this redir
        //
        status = FsRtlpRegisterProviderWithMUP( mupHandle,
                        RedirDevName,
                        MailslotsSupported );
        break;

    }

    if( NT_SUCCESS( status ) ) {
        FsRtlpRedirs++;
        *MupHandle = mupHandle;

    } else {
        if( mupHandle != (HANDLE)-1 && mupHandle != NULL ) {
            ZwClose( mupHandle );
        }

        *MupHandle = (HANDLE)-1;
    }

    KeReleaseSemaphore(&FsRtlpUncSemaphore, 0, 1, FALSE );
    return status;
}
Beispiel #2
0
/*++
 * @name FsRtlRegisterUncProvider
 * @implemented
 *
 * FILLME
 *
 * @param Handle
 *        FILLME
 *
 * @param RedirectorDeviceName
 *        FILLME
 *
 * @param MailslotsSupported
 *        FILLME
 *
 * @return None
 *
 * @remarks None
 *
 *--*/
NTSTATUS
NTAPI
FsRtlRegisterUncProvider(OUT PHANDLE Handle,
                         IN PCUNICODE_STRING RedirectorDeviceName,
                         IN BOOLEAN MailslotsSupported)
{
    NTSTATUS Status;
    HANDLE DeviceHandle;
    UNICODE_STRING MupString;

    PAGED_CODE();

    DPRINT1("FsRtlRegisterUncProvider(%p, %wZ, %u)\n", Handle, RedirectorDeviceName, MailslotsSupported);

    KeWaitForSingleObject(&FsRtlpUncSemaphore, Executive, KernelMode, FALSE, NULL);

    /* In case no provider was registered yet, check for DFS present.
     * If DFS is present, we need to go with MUP, whatever the case
     */
    if (FsRtlpRedirs == 0)
    {
        if (FsRtlpIsDfsEnabled())
        {
            DPRINT1("DFS is not disabled. Going through MUP\n");

            /* We've to go with MUP, make sure our internal structure doesn't
             * contain any leftover data and raise redirs to one, to make sure
             * we use MUP.
             */
            RtlZeroMemory(&FsRtlpDRD, sizeof(FsRtlpDRD));
            FsRtlpRedirs = 1;
        }
    }

    /* In case no UNC provider was already registered,
     * We'll proceed without MUP and directly redirect
     * UNC to the provider.
     */
    if (FsRtlpRedirs == 0)
    {
        /* As we don't provide MUP, just give a handle to NULL device */
        Status = FsRtlpOpenDev(&DeviceHandle, L"\\Device\\Null");
        if (!NT_SUCCESS(Status))
        {
            goto Cleanup;
        }

        /* Allocate a buffer big enough to keep a local copy of UNC provider device */
        FsRtlpDRD.RedirectorDeviceName.Buffer = ExAllocatePoolWithTag(NonPagedPool, RedirectorDeviceName->MaximumLength, TAG_UNC);
        if (FsRtlpDRD.RedirectorDeviceName.Buffer == NULL)
        {
            Status = STATUS_INSUFFICIENT_RESOURCES;
            goto Cleanup;
        }

        FsRtlpDRD.RedirectorDeviceName.Length = RedirectorDeviceName->Length;
        FsRtlpDRD.RedirectorDeviceName.MaximumLength = RedirectorDeviceName->MaximumLength;
        RtlCopyMemory(FsRtlpDRD.RedirectorDeviceName.Buffer, RedirectorDeviceName->Buffer, RedirectorDeviceName->MaximumLength);

        /* We don't have MUP, and copy provider information */
        FsRtlpDRD.MupHandle = INVALID_HANDLE_VALUE;
        FsRtlpDRD.MailslotsSupported = MailslotsSupported;
        FsRtlpDRD.NullHandle = DeviceHandle;

        /* Set DOS device UNC to use provider device */
        FsRtlpSetSymbolicLink(RedirectorDeviceName);
    }
    else
    {
        /* We (will) have several providers, MUP is required */
        Status = FsRtlpOpenDev(&DeviceHandle, L"\\Device\\Mup");
        if (!NT_SUCCESS(Status))
        {
            /* Opening MUP may have failed because the driver was not loaded, so load it and retry */
            RtlInitUnicodeString(&MupString, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Mup");
            ZwLoadDriver(&MupString);
            Status = FsRtlpOpenDev(&DeviceHandle, L"\\Device\\Mup");
            if (!NT_SUCCESS(Status))
            {
                goto Cleanup;
            }
        }

        /* In case we had a single provider till now, we have to forward the old provider to MUP
         * And then, register the new one to MUP as well
         */
        if (FsRtlpDRD.RedirectorDeviceName.Buffer != NULL)
        {
            /* We will only continue if we can register previous provider in MUP */
            Status = FsRtlpRegisterProviderWithMUP(DeviceHandle, &FsRtlpDRD.RedirectorDeviceName, FsRtlpDRD.MailslotsSupported);
            if (!NT_SUCCESS(Status))
            {
                goto Cleanup;
            }

            /* Save our Mup handle for later usage */
            FsRtlpDRD.MupHandle = DeviceHandle;

            /* Release information about previous provider */
            ExFreePoolWithTag(FsRtlpDRD.RedirectorDeviceName.Buffer, TAG_UNC);
            FsRtlpDRD.RedirectorDeviceName.Buffer = NULL;

            /* Re-open MUP to have a handle to give back to the user */
            Status = FsRtlpOpenDev(&DeviceHandle, L"\\Device\\Mup");
            if (!NT_SUCCESS(Status))
            {
                goto Cleanup;
            }
        }

        /* Redirect UNC DOS device to MUP */
        RtlInitUnicodeString(&MupString, L"\\Device\\Mup");
        FsRtlpSetSymbolicLink(&MupString);

        /* Register new provider */
        Status = FsRtlpRegisterProviderWithMUP(DeviceHandle, RedirectorDeviceName, MailslotsSupported);
    }

Cleanup:

    /* In case of success, increment number of providers and return handle
     * to the device pointed by UNC DOS device
     */
    if (NT_SUCCESS(Status))
    {
        ++FsRtlpRedirs;
        *Handle = DeviceHandle;
    }
    else
    {
        /* Cleanup in case of failure */
        if (DeviceHandle != INVALID_HANDLE_VALUE && DeviceHandle != 0)
        {
            ZwClose(DeviceHandle);
        }

        *Handle = INVALID_HANDLE_VALUE;
    }

    KeReleaseSemaphore(&FsRtlpUncSemaphore, IO_NO_INCREMENT, 1, FALSE);
    return Status;
}