注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

熊猫正正的博客

熊猫正正的天空

 
 
 

日志

 
 

ReactOS操作系统-驱动篇  

2011-03-10 20:53:18|  分类: window驱动学习 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

第一个很简单的驱动~~Beep.sys驱动,代码如下:

/*
 * PROJECT:         ReactOS Kernel
 * LICENSE:         GPL - See COPYING in the top level directory
 * FILE:            drivers/base/beep/beep.c
 * PURPOSE:         Beep Device Driver
 * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
 *                  Eric Kohl
 */

/* INCLUDES ******************************************************************/

#include <ntddk.h>
#include <ntddbeep.h>
#ifndef NDEBUG
#define NDEBUG
#endif
#include <debug.h>

/* TYPES *********************************************************************/

typedef struct _BEEP_DEVICE_EXTENSION
{
    LONG ReferenceCount;
    FAST_MUTEX Mutex;
    KTIMER Timer;
    LONG TimerActive;
    PVOID SectionHandle;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

/* FUNCTIONS *****************************************************************/

VOID
NTAPI
BeepDPC(IN PKDPC Dpc,
        IN PDEVICE_OBJECT DeviceObject,
        IN PVOID SystemArgument1,
        IN PVOID SystemArgument2)
{
    PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;

    /* Stop the beep */
    HalMakeBeep(0);

    /* Disable the timer */
    InterlockedDecrement(&DeviceExtension->TimerActive);
}

DRIVER_DISPATCH BeepCreate;
NTSTATUS
NTAPI
BeepCreate(IN PDEVICE_OBJECT DeviceObject,
           IN PIRP Irp)
{
    PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;

    /* Acquire the mutex and increase reference count */
    ExAcquireFastMutex(&DeviceExtension->Mutex);
    if (++DeviceExtension->ReferenceCount == 1)
    {
        /* First reference, lock the data section */
        DeviceExtension->SectionHandle = MmLockPagableDataSection(BeepCreate);
    }

    /* Release it */
    ExReleaseFastMutex(&DeviceExtension->Mutex);

    /* Complete the request */
    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;
}

DRIVER_DISPATCH BeepClose;
NTSTATUS
NTAPI
BeepClose(IN PDEVICE_OBJECT DeviceObject,
          IN PIRP Irp)
{
    PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;

    /* Acquire the mutex and decrease reference count */
    ExAcquireFastMutex(&DeviceExtension->Mutex);
    if (!(--DeviceExtension->ReferenceCount))
    {
        /* Check for active timer */
        if (DeviceExtension->TimerActive)
        {
            /* Cancel it */
            if (KeCancelTimer(&DeviceExtension->Timer))
            {
                /* Mark it as cancelled */
                InterlockedDecrement(&DeviceExtension->TimerActive);
            }
        }

        /* Page the driver */
        MmUnlockPagableImageSection(DeviceExtension->SectionHandle);
    }

    /* Release the lock */
    ExReleaseFastMutex(&DeviceExtension->Mutex);

    /* Complete the request */
    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;
}

DRIVER_CANCEL BeepCancel;
VOID
NTAPI
BeepCancel(IN PDEVICE_OBJECT DeviceObject,
           IN PIRP Irp)
{
    /* Check if this is the current request */
    if (Irp == DeviceObject->CurrentIrp)
    {
        /* Clear it */
        DeviceObject->CurrentIrp = NULL;

        /* Release the cancel lock and start the next packet */
        IoReleaseCancelSpinLock(Irp->CancelIrql);
        IoStartNextPacket(DeviceObject, TRUE);
    }
    else
    {
        /* Otherwise, remove the packet from the queue and relelase the lock */
        KeRemoveEntryDeviceQueue(&DeviceObject->DeviceQueue,
                                 &Irp->Tail.Overlay.DeviceQueueEntry);
        IoReleaseCancelSpinLock(Irp->CancelIrql);
    }

    /* Complete the request */
    Irp->IoStatus.Status = STATUS_CANCELLED;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest (Irp, IO_NO_INCREMENT);
}

DRIVER_DISPATCH BeepCleanup;
NTSTATUS
NTAPI
BeepCleanup(IN PDEVICE_OBJECT DeviceObject,
            IN PIRP Irp)
{
    KIRQL OldIrql, CancelIrql;
    PKDEVICE_QUEUE_ENTRY Packet;
    PIRP CurrentIrp;

    /* Raise IRQL and acquire the cancel lock */
    KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
    IoAcquireCancelSpinLock(&CancelIrql);

    /* Get the current IRP */
    CurrentIrp = DeviceObject->CurrentIrp;
    DeviceObject->CurrentIrp = NULL;
    while (CurrentIrp)
    {
        /* Clear its cancel routine */
        (VOID)IoSetCancelRoutine(CurrentIrp, NULL);

        /* Cancel the IRP */
        CurrentIrp->IoStatus.Status = STATUS_CANCELLED;
        CurrentIrp->IoStatus.Information = 0;

        /* Release the cancel lock and complete it */
        IoReleaseCancelSpinLock(CancelIrql);
        IoCompleteRequest(CurrentIrp, IO_NO_INCREMENT);

        /* Reacquire the lock and get the next queue packet */
        IoAcquireCancelSpinLock(&CancelIrql);
        Packet = KeRemoveDeviceQueue(&DeviceObject->DeviceQueue);
        if (Packet)
        {
            /* Get the IRP */
            CurrentIrp = CONTAINING_RECORD(Packet,
                                           IRP,
                                           Tail.Overlay.DeviceQueueEntry);
        }
        else
        {
            /* No more IRPs */
            CurrentIrp = NULL;
        }
    }

    /* Release lock and go back to low IRQL */
    IoReleaseCancelSpinLock(CancelIrql);
    KeLowerIrql(OldIrql);

    /* Complete the IRP */
    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    /* Stop and beep and return */
    HalMakeBeep(0);
    return STATUS_SUCCESS;
}

DRIVER_DISPATCH BeepDeviceControl;
NTSTATUS
NTAPI
BeepDeviceControl(IN PDEVICE_OBJECT DeviceObject,
                  IN PIRP Irp)
{
    PIO_STACK_LOCATION Stack;
    PBEEP_SET_PARAMETERS BeepParam;
    NTSTATUS Status;

    /* Get the stack location and parameters */
    Stack = IoGetCurrentIrpStackLocation(Irp);
    BeepParam = (PBEEP_SET_PARAMETERS)Irp->AssociatedIrp.SystemBuffer;

    /* We only support one IOCTL */
    if (Stack->Parameters.DeviceIoControl.IoControlCode != IOCTL_BEEP_SET)
    {
        /* Unsupported command */
        Status = STATUS_NOT_IMPLEMENTED;
    }
    else
    {
        /* Validate the input buffer length */
        if (Stack->Parameters.DeviceIoControl.InputBufferLength <
            sizeof(BEEP_SET_PARAMETERS))
        {
            /* Invalid buffer */
            Status = STATUS_INVALID_PARAMETER;
        }
        else if ((BeepParam->Frequency != 0) && !(BeepParam->Duration))
        {
            /* No duration, return imemdiately */
            Status = STATUS_SUCCESS;
        }
        else
        {
            /* We'll queue this request */
            Status = STATUS_PENDING;
        }
    }

    /* Set packet information */
    Irp->IoStatus.Status = Status;
    Irp->IoStatus.Information = 0;

    /* Check if we're completing or queuing a packet */
    if (Status == STATUS_PENDING)
    {
        /* Start the queue */
        IoMarkIrpPending(Irp);
        IoStartPacket(DeviceObject, Irp, NULL, BeepCancel);
    }
    else
    {
        /* Complete the request */
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
    }

    /* Return */
    return Status;
}

DRIVER_UNLOAD BeepUnload;
VOID
NTAPI
BeepUnload(IN PDRIVER_OBJECT DriverObject)
{
    PDEVICE_EXTENSION DeviceExtension;
    PDEVICE_OBJECT DeviceObject;

    /* Get DO and DE */
    DeviceObject = DriverObject->DeviceObject;
    DeviceExtension = DeviceObject->DeviceExtension;

    /* Check if the timer is active */
    if (DeviceExtension->TimerActive)
    {
        /* Cancel it */
        if (KeCancelTimer(&DeviceExtension->Timer))
        {
            /* All done */
            InterlockedDecrement(&DeviceExtension->TimerActive);
        }
    }

    /* Delete the object */
    IoDeleteDevice(DeviceObject);
}

DRIVER_STARTIO BeepStartIo;
VOID
NTAPI
BeepStartIo(IN PDEVICE_OBJECT DeviceObject,
            IN PIRP Irp)
{
    PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
    KIRQL CancelIrql;
    PIO_STACK_LOCATION IoStack;
    PBEEP_SET_PARAMETERS BeepParam;
    LARGE_INTEGER DueTime;
    NTSTATUS Status;

    /* Acquire the cancel lock and make sure the IRP is valid */
    IoAcquireCancelSpinLock(&CancelIrql);
    if (!Irp)
    {
        /* It's not, release the lock and quit */
        IoReleaseCancelSpinLock(CancelIrql);
        return;
    }

    /* Remove the cancel routine and release the lock */
    (VOID)IoSetCancelRoutine(Irp, NULL);
    IoReleaseCancelSpinLock(CancelIrql);

    /* Get the I/O Stack and make sure the request is valid */
    BeepParam = (PBEEP_SET_PARAMETERS)Irp->AssociatedIrp.SystemBuffer;
    IoStack = IoGetCurrentIrpStackLocation(Irp);
    if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_BEEP_SET)
    {
        /* Check if we have an active timer */
        if (DeviceExtension->TimerActive)
        {
            /* Cancel it */
            if (KeCancelTimer(&DeviceExtension->Timer))
            {
                /* Set the state */
                InterlockedDecrement(&DeviceExtension->TimerActive);
            }
        }

        /* Make the beep */
        if (HalMakeBeep(BeepParam->Frequency))
        {
            /* Beep successful, queue a DPC to stop it */
            Status = STATUS_SUCCESS;
            DueTime.QuadPart = BeepParam->Duration * -10000;
            InterlockedIncrement(&DeviceExtension->TimerActive);
            KeSetTimer(&DeviceExtension->Timer, DueTime, &DeviceObject->Dpc);
        }
        else
        {
            /* Beep has failed */
            Status = STATUS_INVALID_PARAMETER;
        }
    }
    else
    {
        /* Invalid request */
        Status = STATUS_INVALID_PARAMETER;
    }

    /* Complete the request and start the next packet */
    Irp->IoStatus.Status = Status;
    Irp->IoStatus.Information = 0;
    IoStartNextPacket(DeviceObject, TRUE);
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
}

NTSTATUS
NTAPI
DriverEntry(IN PDRIVER_OBJECT DriverObject,
            IN PUNICODE_STRING RegistryPath)
{
    PDEVICE_EXTENSION DeviceExtension;
    PDEVICE_OBJECT DeviceObject;
    UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\Beep");
    NTSTATUS Status;

    /* Create the device */
    Status = IoCreateDevice(DriverObject,
                            sizeof(DEVICE_EXTENSION),
                            &DeviceName,
                            FILE_DEVICE_BEEP,
                            0,
                            FALSE,
                            &DeviceObject);
    if (!NT_SUCCESS(Status)) return Status;

    /* Make it use buffered I/O */
    DeviceObject->Flags |= DO_BUFFERED_IO;

    /* Setup the Driver Object */
    DriverObject->MajorFunction[IRP_MJ_CREATE] = BeepCreate;
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = BeepClose;
    DriverObject->MajorFunction[IRP_MJ_CLEANUP] = BeepCleanup;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = BeepDeviceControl;
    DriverObject->DriverUnload = BeepUnload;
    DriverObject->DriverStartIo = BeepStartIo;

    /* Set up device extension */
    DeviceExtension = DeviceObject->DeviceExtension;
    DeviceExtension->ReferenceCount = 0;
    DeviceExtension->TimerActive = FALSE;
    IoInitializeDpcRequest(DeviceObject, (PIO_DPC_ROUTINE)BeepDPC);
    KeInitializeTimer(&DeviceExtension->Timer);
    ExInitializeFastMutex(&DeviceExtension->Mutex);

    /* Page the entire driver */
    MmPageEntireDriver(DriverEntry);
    return STATUS_SUCCESS;
}

/* EOF */

  评论这张
 
阅读(230)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017