File:  [WindowsNT SDKs] / ntddk / src / mmedia / soundlib / dispatch.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Thu Aug 9 18:31:12 2018 UTC (7 years, 9 months ago) by root
Branches: msft, MAIN
CVS tags: ntddk-nov-1993, HEAD
Microsoft Windows NT Build 511 (DDK SDK) 11-01-1993

/*++

Copyright (c) 1992  Microsoft Corporation

Module Name:

    dispatch.c

Abstract:

    This module contains code for the function dispatcher.

Author:

    Robin Speed (RobinSp) 22-Oct-1992

Environment:

    Kernel mode

Revision History:

    Robin Speed (RobinSp) 29-Jan-1992 - Add extra IOCTLs and access control

--*/

#include <string.h>
#include <soundlib.h>          // Definition of what's in here

/**************************************************************************
 *
 *
 *    Function dispatch
 *
 *
 **************************************************************************/


NTSTATUS
SoundSetShareAccess(
    IN OUT PLOCAL_DEVICE_INFO pLDI,
    IN     PIO_STACK_LOCATION IrpStack
)
/*++

Routine Description:

    Tests if access is allowed to the device on the basis of the sharing
    requested.

    Also sets the PreventVolumeSetting flag up in the local device info

    If write access required and the device is already in use we return
    STATUS_DEVICE_BUSY.

    If shared write was requested set the flag to say that others can
    set the volume

Arguments:

    pLDI - Local device info
    pIrp - Pointer to IO request packet
    IrpStack - stack location info

Return Value:

    Return status from dispatched routine

--*/
{
    NTSTATUS Status;

    //
    // Get the system to update the file object access flags
    //
    {
        SHARE_ACCESS ShareAccess;
        IoSetShareAccess(IrpStack->Parameters.Create.SecurityContext->DesiredAccess,
                         (ULONG)IrpStack->Parameters.Create.ShareAccess,
                         IrpStack->FileObject,
                         &ShareAccess);
    }
    //
    // Always allow non-write access.  For neatness we'll require
    // that read access was requested
    //
    if (IrpStack->Parameters.Create.SecurityContext->DesiredAccess & FILE_READ_DATA) {
        if (IrpStack->Parameters.Create.SecurityContext->DesiredAccess & FILE_WRITE_DATA) {
            ASSERT(IrpStack->FileObject->WriteAccess);
            dprintf2(("Trying to open device %4.4s for write",
                     (char *)&pLDI->Key));

            if (!(*pLDI->DeviceInit->ExclusionRoutine)(
                      pLDI, SoundExcludeOpen)) {
                Status = STATUS_DEVICE_BUSY;
            } else {
                Status = STATUS_SUCCESS;
            }

            //
            // Note that if share for write is given this is a way
            // of saying that others can set our volume with just read
            // access
            //
            pLDI->PreventVolumeSetting = FALSE;
            if (NT_SUCCESS(Status)) {
                if (IrpStack->FileObject->SharedWrite) {
                } else {
                    pLDI->PreventVolumeSetting = TRUE;
                }
            }
        } else {
            Status = STATUS_SUCCESS;
        }
    } else {
        Status = STATUS_ACCESS_DENIED;
    }

    return Status;
}


NTSTATUS
SoundDispatch(
    IN    PDEVICE_OBJECT pDO,
    IN    PIRP pIrp
)
/*++

Routine Description:

    Driver function dispatch routine

Arguments:

    pDO - Pointer to device object
    pIrp - Pointer to IO request packet

Return Value:

    Return status from dispatched routine

--*/
{
    PLOCAL_DEVICE_INFO pLDI;
    PIO_STACK_LOCATION pIrpStack;
    NTSTATUS Status;

    Status = STATUS_SUCCESS;

    //
    // Initialize the irp information field.
    //

    pIrp->IoStatus.Information = 0;

    //
    // get the address of the local info structure in the device extension
    //

    pLDI = (PLOCAL_DEVICE_INFO)pDO->DeviceExtension;

    //
    // Acquire the device mutant - we need to do this for some
    // devices anyway because we have to execute waits for slow
    // operations to complete
    //

    if (!(*pLDI->DeviceInit->ExclusionRoutine)(pLDI, SoundExcludeEnter)) {
        Status = STATUS_DEVICE_BUSY;
    } else {
        //
        // Dispatch the function based on the major function code
        //

        pIrpStack = IoGetCurrentIrpStackLocation(pIrp);

#ifdef VOLUME_NOTIFY

       /**********************************************************************
        *
        *   Do general volume stuff here
        *
        **********************************************************************/

        //
        // Free anyone waiting for the volume to change
        //

        if (pIrpStack->MajorFunction == IRP_MJ_CLEANUP) {

            int i;
            KIRQL OldIrql;

            //
            // Free anyone waiting for the volume to change whose file object
            // is the one about to be closed.
            //

            PLIST_ENTRY ListEntry, Next;

            //
            // Our list is cancellable so do this under the cancel spin
            // lock
            //

            IoAcquireCancelSpinLock(&OldIrql);

            for (ListEntry = pLDI->VolumeQueue.Flink;
                 ListEntry != &pLDI->VolumeQueue;
                 ListEntry = Next) {

                PIRP IrpList;
                IrpList = CONTAINING_RECORD(ListEntry, IRP, Tail.Overlay.ListEntry);

                Next = ListEntry->Flink;

                ASSERT(IoGetCurrentIrpStackLocation(IrpList)->MajorFunction ==
                           IRP_MJ_DEVICE_CONTROL &&
                       IoGetCurrentIrpStackLocation(IrpList)->
                           Parameters.DeviceIoControl.IoControlCode ==
                           IOCTL_SOUND_GET_CHANGED_VOLUME);

                if (pIrpStack->FileObject ==
                        IoGetCurrentIrpStackLocation(IrpList)->FileObject) {

                    RemoveEntryList(ListEntry);

                    //
                    // Make sure our cancel routine doesn't get in!
                    //

                    IoSetCancelRoutine(IrpList, NULL);


                    //
                    // Free the spin lock in case IoCompleteRequest doesn't
                    // like us to hold it
                    //

                    IoReleaseCancelSpinLock(OldIrql);

                    IrpList->IoStatus.Status = STATUS_SUCCESS;
                    IoCompleteRequest(IrpList, IO_NO_INCREMENT);

                    IoAcquireCancelSpinLock(&OldIrql);

                    //
                    // The world may have changed so restart
                    //

                    Next = pLDI->VolumeQueue.Flink;
                }
            }

            IoReleaseCancelSpinLock(OldIrql);
        }

#endif // VOLUME_NOTIFY

        //
        // Call the real device code
        //

        if (NT_SUCCESS(Status)) {
            Status = (*pLDI->DeviceInit->DispatchRoutine)(pLDI, pIrp, pIrpStack);
        }

        //
        // Free the device
        //

        (*pLDI->DeviceInit->ExclusionRoutine)(pLDI, SoundExcludeLeave);
    }

    //
    // Tell the IO subsystem we're done.  If the Irp is pending we
    // don't touch it as it could be being processed by another
    // processor (or may even be complete already !).
    //

    if (Status != STATUS_PENDING) {
        pIrp->IoStatus.Status = Status;
        IoCompleteRequest(pIrp, IO_SOUND_INCREMENT );
    }

    return Status;
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.