mirror of
https://github.com/reactos/reactos.git
synced 2025-08-04 16:26:02 +00:00
- Don't load NT4 audio drivers by default anymore.
- Don't load beep.sys in non-setup mode. - Improve beep driver by making it use device queues instead of instantly completing beep requests, and make it cancel-safe, unloadable, and thread-safe in regards to timers. Also reduce memory footprint by making the entire driver pageable and dynamically locking/unlocking the image section by keeping a reference count of opens. svn path=/trunk/; revision=26254
This commit is contained in:
parent
295322ab9b
commit
ca95775748
2 changed files with 347 additions and 233 deletions
|
@ -490,7 +490,7 @@ HKLM,"SYSTEM\CurrentControlSet\Services\Beep","Type",0x00010001,0x00000001
|
||||||
HKLM,"SYSTEM\CurrentControlSet\Services\Blue","ErrorControl",0x00010001,0x00000000
|
HKLM,"SYSTEM\CurrentControlSet\Services\Blue","ErrorControl",0x00010001,0x00000000
|
||||||
HKLM,"SYSTEM\CurrentControlSet\Services\Blue","Group",0x00000000,"Video Init"
|
HKLM,"SYSTEM\CurrentControlSet\Services\Blue","Group",0x00000000,"Video Init"
|
||||||
HKLM,"SYSTEM\CurrentControlSet\Services\Blue","ImagePath",0x00020000,"system32\drivers\blue.sys"
|
HKLM,"SYSTEM\CurrentControlSet\Services\Blue","ImagePath",0x00020000,"system32\drivers\blue.sys"
|
||||||
HKLM,"SYSTEM\CurrentControlSet\Services\Blue","Start",0x00010001,0x00000001
|
HKLM,"SYSTEM\CurrentControlSet\Services\Blue","Start",0x00010001,0x00000004
|
||||||
HKLM,"SYSTEM\CurrentControlSet\Services\Blue","Type",0x00010001,0x00000001
|
HKLM,"SYSTEM\CurrentControlSet\Services\Blue","Type",0x00010001,0x00000001
|
||||||
|
|
||||||
; Cdfs (ISO96660) filesystem driver
|
; Cdfs (ISO96660) filesystem driver
|
||||||
|
@ -593,7 +593,7 @@ HKLM,"SYSTEM\CurrentControlSet\Control\Class\{4D36E96B-E325-11CE-BFC1-08002BE103
|
||||||
HKLM,"SYSTEM\CurrentControlSet\Services\sndblst","Group",0x00000000,"Base"
|
HKLM,"SYSTEM\CurrentControlSet\Services\sndblst","Group",0x00000000,"Base"
|
||||||
HKLM,"SYSTEM\CurrentControlSet\Services\sndblst","ServiceType",0x00010001,0x00000001
|
HKLM,"SYSTEM\CurrentControlSet\Services\sndblst","ServiceType",0x00010001,0x00000001
|
||||||
HKLM,"SYSTEM\CurrentControlSet\Services\sndblst","Type",0x00010001,0x00000001
|
HKLM,"SYSTEM\CurrentControlSet\Services\sndblst","Type",0x00010001,0x00000001
|
||||||
HKLM,"SYSTEM\CurrentControlSet\Services\sndblst","Start",0x00010001,0x00000001
|
HKLM,"SYSTEM\CurrentControlSet\Services\sndblst","Start",0x00010001,0x00000004
|
||||||
HKLM,"SYSTEM\CurrentControlSet\Services\sndblst","ErrorControl",0x00010001,0x00000001
|
HKLM,"SYSTEM\CurrentControlSet\Services\sndblst","ErrorControl",0x00010001,0x00000001
|
||||||
HKLM,"SYSTEM\CurrentControlSet\Services\sndblst","ImagePath",0x00020000,"system32\drivers\sndblst.sys"
|
HKLM,"SYSTEM\CurrentControlSet\Services\sndblst","ImagePath",0x00020000,"system32\drivers\sndblst.sys"
|
||||||
;HKLM,"SYSTEM\CurrentControlSet\Services\sndblst\Parameters\Device0","DmaChannel",0x00010001,0x00000001
|
;HKLM,"SYSTEM\CurrentControlSet\Services\sndblst\Parameters\Device0","DmaChannel",0x00010001,0x00000001
|
||||||
|
@ -608,7 +608,7 @@ HKLM,"SYSTEM\CurrentControlSet\Services\sndblst\Parameters\Device0\Devices","SBW
|
||||||
HKLM,"SYSTEM\CurrentControlSet\Services\mpu401","Group",0x00000000,"Base"
|
HKLM,"SYSTEM\CurrentControlSet\Services\mpu401","Group",0x00000000,"Base"
|
||||||
HKLM,"SYSTEM\CurrentControlSet\Services\mpu401","ServiceType",0x00010001,0x00000001
|
HKLM,"SYSTEM\CurrentControlSet\Services\mpu401","ServiceType",0x00010001,0x00000001
|
||||||
HKLM,"SYSTEM\CurrentControlSet\Services\mpu401","Type",0x00010001,0x00000001
|
HKLM,"SYSTEM\CurrentControlSet\Services\mpu401","Type",0x00010001,0x00000001
|
||||||
HKLM,"SYSTEM\CurrentControlSet\Services\mpu401","Start",0x00010001,0x00000001
|
HKLM,"SYSTEM\CurrentControlSet\Services\mpu401","Start",0x00010001,0x00000004
|
||||||
HKLM,"SYSTEM\CurrentControlSet\Services\mpu401","ErrorControl",0x00010001,0x00000001
|
HKLM,"SYSTEM\CurrentControlSet\Services\mpu401","ErrorControl",0x00010001,0x00000001
|
||||||
HKLM,"SYSTEM\CurrentControlSet\Services\mpu401","ImagePath",0x00020000,"system32\drivers\mpu401.sys"
|
HKLM,"SYSTEM\CurrentControlSet\Services\mpu401","ImagePath",0x00020000,"system32\drivers\mpu401.sys"
|
||||||
|
|
||||||
|
|
|
@ -1,282 +1,396 @@
|
||||||
/* $Id$
|
/*
|
||||||
*
|
* PROJECT: ReactOS Kernel
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* LICENSE: GPL - See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* FILE: drivers/base/beep/beep.c
|
||||||
* FILE: services/dd/beep/beep.c
|
* PURPOSE: Beep Device Driver
|
||||||
* PURPOSE: BEEP device driver
|
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
|
||||||
* PROGRAMMER: Eric Kohl (ekohl@rz-online.de)
|
* Eric Kohl (ekohl@rz-online.de)
|
||||||
* UPDATE HISTORY:
|
|
||||||
* 30/01/99 Created
|
|
||||||
* 16/10/99 Minor fixes
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES ****************************************************************/
|
/* INCLUDES ******************************************************************/
|
||||||
|
|
||||||
#include <ntddk.h>
|
#include <ntddk.h>
|
||||||
#include <ntddbeep.h>
|
#include <ntddbeep.h>
|
||||||
|
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
/* TYPES *********************************************************************/
|
||||||
DriverEntry(PDRIVER_OBJECT DriverObject,
|
|
||||||
PUNICODE_STRING RegistryPath);
|
|
||||||
|
|
||||||
/* TYEPEDEFS ***************************************************************/
|
|
||||||
|
|
||||||
typedef struct _BEEP_DEVICE_EXTENSION
|
typedef struct _BEEP_DEVICE_EXTENSION
|
||||||
{
|
{
|
||||||
KDPC Dpc;
|
LONG ReferenceCount;
|
||||||
KTIMER Timer;
|
FAST_MUTEX Mutex;
|
||||||
KEVENT Event;
|
KTIMER Timer;
|
||||||
BOOLEAN BeepOn;
|
LONG TimerActive;
|
||||||
|
PVOID SectionHandle;
|
||||||
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
|
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
|
||||||
|
|
||||||
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
/* FUNCTIONS ***************************************************************/
|
VOID
|
||||||
|
NTAPI
|
||||||
static VOID STDCALL
|
BeepDPC(IN PKDPC Dpc,
|
||||||
BeepDPC(PKDPC Dpc,
|
IN PDEVICE_OBJECT DeviceObject,
|
||||||
PVOID DeferredContext,
|
IN PVOID SystemArgument1,
|
||||||
PVOID SystemArgument1,
|
IN PVOID SystemArgument2)
|
||||||
PVOID SystemArgument2)
|
|
||||||
{
|
{
|
||||||
PDEVICE_EXTENSION DeviceExtension = DeferredContext;
|
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
DPRINT("BeepDPC() called!\n");
|
/* Stop the beep */
|
||||||
|
HalMakeBeep(0);
|
||||||
|
|
||||||
HalMakeBeep(0);
|
/* Disable the timer */
|
||||||
DeviceExtension->BeepOn = FALSE;
|
InterlockedDecrement(&DeviceExtension->TimerActive);
|
||||||
KeSetEvent(&DeviceExtension->Event,
|
|
||||||
0,
|
|
||||||
FALSE);
|
|
||||||
|
|
||||||
DPRINT("BeepDPC() finished!\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
static NTSTATUS STDCALL
|
NTAPI
|
||||||
BeepCreate(
|
BeepCreate(IN PDEVICE_OBJECT DeviceObject,
|
||||||
PDEVICE_OBJECT DeviceObject,
|
IN PIRP Irp)
|
||||||
PIRP Irp)
|
|
||||||
/*
|
|
||||||
* FUNCTION: Handles user mode requests
|
|
||||||
* ARGUMENTS:
|
|
||||||
* DeviceObject = Device for request
|
|
||||||
* Irp = I/O request packet describing request
|
|
||||||
* RETURNS: Success or failure
|
|
||||||
*/
|
|
||||||
{
|
{
|
||||||
DPRINT("BeepCreate() called!\n");
|
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
/* Acquire the mutex and increase reference count */
|
||||||
Irp->IoStatus.Information = 0;
|
ExAcquireFastMutex(&DeviceExtension->Mutex);
|
||||||
IoCompleteRequest(Irp,
|
if (++DeviceExtension->ReferenceCount == 1)
|
||||||
IO_NO_INCREMENT);
|
|
||||||
|
|
||||||
return(STATUS_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static NTSTATUS STDCALL
|
|
||||||
BeepClose(PDEVICE_OBJECT DeviceObject,
|
|
||||||
PIRP Irp)
|
|
||||||
/*
|
|
||||||
* FUNCTION: Handles user mode requests
|
|
||||||
* ARGUMENTS:
|
|
||||||
* DeviceObject = Device for request
|
|
||||||
* Irp = I/O request packet describing request
|
|
||||||
* RETURNS: Success or failure
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
PDEVICE_EXTENSION DeviceExtension;
|
|
||||||
NTSTATUS Status;
|
|
||||||
|
|
||||||
DPRINT("BeepClose() called!\n");
|
|
||||||
|
|
||||||
DeviceExtension = DeviceObject->DeviceExtension;
|
|
||||||
if (DeviceExtension->BeepOn == TRUE)
|
|
||||||
{
|
{
|
||||||
HalMakeBeep(0);
|
/* First reference, lock the data section */
|
||||||
DeviceExtension->BeepOn = FALSE;
|
DeviceExtension->SectionHandle = MmLockPagableDataSection(BeepCreate);
|
||||||
KeCancelTimer(&DeviceExtension->Timer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = STATUS_SUCCESS;
|
/* Release it */
|
||||||
|
ExReleaseFastMutex(&DeviceExtension->Mutex);
|
||||||
|
|
||||||
Irp->IoStatus.Status = Status;
|
/* Complete the request */
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
IoCompleteRequest(Irp,
|
Irp->IoStatus.Information = 0;
|
||||||
IO_NO_INCREMENT);
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
return(Status);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
static NTSTATUS STDCALL
|
NTAPI
|
||||||
BeepCleanup(PDEVICE_OBJECT DeviceObject,
|
BeepClose(IN PDEVICE_OBJECT DeviceObject,
|
||||||
PIRP Irp)
|
IN PIRP Irp)
|
||||||
/*
|
|
||||||
* FUNCTION: Handles user mode requests
|
|
||||||
* ARGUMENTS:
|
|
||||||
* DeviceObject = Device for request
|
|
||||||
* Irp = I/O request packet describing request
|
|
||||||
* RETURNS: Success or failure
|
|
||||||
*/
|
|
||||||
{
|
{
|
||||||
DPRINT("BeepCleanup() called!\n");
|
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
|
||||||
|
|
||||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
/* Acquire the mutex and decrease reference count */
|
||||||
Irp->IoStatus.Information = 0;
|
ExAcquireFastMutex(&DeviceExtension->Mutex);
|
||||||
IoCompleteRequest(Irp,
|
if (!(--DeviceExtension->ReferenceCount))
|
||||||
IO_NO_INCREMENT);
|
{
|
||||||
|
/* Check for active timer */
|
||||||
|
if (DeviceExtension->TimerActive)
|
||||||
|
{
|
||||||
|
/* Cancel it */
|
||||||
|
if (KeCancelTimer(&DeviceExtension->Timer))
|
||||||
|
{
|
||||||
|
/* Mark it as cancelled */
|
||||||
|
InterlockedDecrement(&DeviceExtension->TimerActive);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return(STATUS_SUCCESS);
|
/* 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
static NTSTATUS STDCALL
|
NTAPI
|
||||||
BeepDeviceControl(PDEVICE_OBJECT DeviceObject,
|
BeepCancel(IN PDEVICE_OBJECT DeviceObject,
|
||||||
PIRP Irp)
|
IN PIRP Irp)
|
||||||
/*
|
|
||||||
* FUNCTION: Handles user mode requests
|
|
||||||
* ARGUMENTS:
|
|
||||||
* DeviceObject = Device for request
|
|
||||||
* Irp = I/O request packet describing request
|
|
||||||
* RETURNS: Success or failure
|
|
||||||
*/
|
|
||||||
{
|
{
|
||||||
PIO_STACK_LOCATION Stack;
|
/* Check if this is the current request */
|
||||||
PDEVICE_EXTENSION DeviceExtension;
|
if (Irp == DeviceObject->CurrentIrp)
|
||||||
PBEEP_SET_PARAMETERS BeepParam;
|
|
||||||
LARGE_INTEGER DueTime;
|
|
||||||
|
|
||||||
DPRINT("BeepDeviceControl() called!\n");
|
|
||||||
|
|
||||||
DeviceExtension = DeviceObject->DeviceExtension;
|
|
||||||
Stack = IoGetCurrentIrpStackLocation(Irp);
|
|
||||||
BeepParam = (PBEEP_SET_PARAMETERS)Irp->AssociatedIrp.SystemBuffer;
|
|
||||||
|
|
||||||
Irp->IoStatus.Information = 0;
|
|
||||||
|
|
||||||
if (Stack->Parameters.DeviceIoControl.IoControlCode != IOCTL_BEEP_SET)
|
|
||||||
{
|
{
|
||||||
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
|
/* Clear it */
|
||||||
IoCompleteRequest(Irp,
|
DeviceObject->CurrentIrp = NULL;
|
||||||
IO_NO_INCREMENT);
|
|
||||||
return(STATUS_NOT_IMPLEMENTED);
|
/* 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((Stack->Parameters.DeviceIoControl.InputBufferLength != sizeof(BEEP_SET_PARAMETERS))
|
/* Complete the request */
|
||||||
|| (BeepParam->Frequency < BEEP_FREQUENCY_MINIMUM)
|
Irp->IoStatus.Status = STATUS_CANCELLED;
|
||||||
|| (BeepParam->Frequency > BEEP_FREQUENCY_MAXIMUM))
|
Irp->IoStatus.Information = 0;
|
||||||
{
|
IoCompleteRequest (Irp, IO_NO_INCREMENT);
|
||||||
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
|
|
||||||
IoCompleteRequest(Irp,
|
|
||||||
IO_NO_INCREMENT);
|
|
||||||
return(STATUS_INVALID_PARAMETER);
|
|
||||||
}
|
|
||||||
|
|
||||||
DueTime.QuadPart = 0;
|
|
||||||
|
|
||||||
/* do the beep!! */
|
|
||||||
DPRINT("Beep:\n Freq: %lu Hz\n Dur: %lu ms\n",
|
|
||||||
BeepParam->Frequency,
|
|
||||||
BeepParam->Duration);
|
|
||||||
if (BeepParam->Duration > 0)
|
|
||||||
{
|
|
||||||
DueTime.QuadPart = (LONGLONG)BeepParam->Duration * -10000;
|
|
||||||
|
|
||||||
KeSetTimer(&DeviceExtension->Timer,
|
|
||||||
DueTime,
|
|
||||||
&DeviceExtension->Dpc);
|
|
||||||
|
|
||||||
HalMakeBeep(BeepParam->Frequency);
|
|
||||||
DeviceExtension->BeepOn = TRUE;
|
|
||||||
KeWaitForSingleObject(&DeviceExtension->Event,
|
|
||||||
Executive,
|
|
||||||
KernelMode,
|
|
||||||
FALSE,
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
else if (BeepParam->Duration == MAXULONG)
|
|
||||||
{
|
|
||||||
if (DeviceExtension->BeepOn == TRUE)
|
|
||||||
{
|
|
||||||
HalMakeBeep(0);
|
|
||||||
DeviceExtension->BeepOn = FALSE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HalMakeBeep(BeepParam->Frequency);
|
|
||||||
DeviceExtension->BeepOn = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DPRINT("Did the beep!\n");
|
|
||||||
|
|
||||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
||||||
IoCompleteRequest(Irp,
|
|
||||||
IO_NO_INCREMENT);
|
|
||||||
return(STATUS_SUCCESS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
static VOID STDCALL
|
NTAPI
|
||||||
BeepUnload(PDRIVER_OBJECT DriverObject)
|
BeepCleanup(IN PDEVICE_OBJECT DeviceObject,
|
||||||
|
IN PIRP Irp)
|
||||||
{
|
{
|
||||||
DPRINT("BeepUnload() called!\n");
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
NTSTATUS STDCALL
|
NTAPI
|
||||||
DriverEntry(PDRIVER_OBJECT DriverObject,
|
BeepDeviceControl(IN PDEVICE_OBJECT DeviceObject,
|
||||||
PUNICODE_STRING RegistryPath)
|
IN PIRP Irp)
|
||||||
/*
|
|
||||||
* FUNCTION: Called by the system to initalize the driver
|
|
||||||
* ARGUMENTS:
|
|
||||||
* DriverObject = object describing this driver
|
|
||||||
* RegistryPath = path to our configuration entries
|
|
||||||
* RETURNS: Success or failure
|
|
||||||
*/
|
|
||||||
{
|
{
|
||||||
PDEVICE_EXTENSION DeviceExtension;
|
PIO_STACK_LOCATION Stack;
|
||||||
PDEVICE_OBJECT DeviceObject;
|
PBEEP_SET_PARAMETERS BeepParam;
|
||||||
UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\Beep");
|
NTSTATUS Status;
|
||||||
NTSTATUS Status;
|
|
||||||
|
|
||||||
DPRINT("Beep Device Driver 0.0.3\n");
|
/* Get the stack location and parameters */
|
||||||
|
Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
BeepParam = (PBEEP_SET_PARAMETERS)Irp->AssociatedIrp.SystemBuffer;
|
||||||
|
|
||||||
DriverObject->Flags = 0;
|
/* We only support one IOCTL */
|
||||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = BeepCreate;
|
if (Stack->Parameters.DeviceIoControl.IoControlCode != IOCTL_BEEP_SET)
|
||||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = BeepClose;
|
{
|
||||||
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = BeepCleanup;
|
/* Unsupported command */
|
||||||
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = BeepDeviceControl;
|
Status = STATUS_NOT_IMPLEMENTED;
|
||||||
DriverObject->DriverUnload = BeepUnload;
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Status = IoCreateDevice(DriverObject,
|
/* Set packet information */
|
||||||
sizeof(DEVICE_EXTENSION),
|
Irp->IoStatus.Status = Status;
|
||||||
&DeviceName,
|
Irp->IoStatus.Information = 0;
|
||||||
FILE_DEVICE_BEEP,
|
|
||||||
0,
|
/* Check if we're completing or queuing a packet */
|
||||||
FALSE,
|
if (Status == STATUS_PENDING)
|
||||||
&DeviceObject);
|
{
|
||||||
if (!NT_SUCCESS(Status))
|
/* Start the queue */
|
||||||
|
IoMarkIrpPending(Irp);
|
||||||
|
IoStartPacket(DeviceObject, Irp, NULL, BeepCancel);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Complete the request */
|
||||||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return */
|
||||||
return Status;
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
/* set up device extension */
|
VOID
|
||||||
DeviceExtension = DeviceObject->DeviceExtension;
|
NTAPI
|
||||||
DeviceExtension->BeepOn = FALSE;
|
BeepUnload(IN PDRIVER_OBJECT DriverObject)
|
||||||
|
{
|
||||||
|
PDEVICE_EXTENSION DeviceExtension;
|
||||||
|
PDEVICE_OBJECT DeviceObject;
|
||||||
|
|
||||||
KeInitializeDpc(&DeviceExtension->Dpc,
|
/* Get DO and DE */
|
||||||
BeepDPC,
|
DeviceObject = DriverObject->DeviceObject;
|
||||||
DeviceExtension);
|
DeviceExtension = DeviceObject->DeviceExtension;
|
||||||
KeInitializeTimer(&DeviceExtension->Timer);
|
|
||||||
KeInitializeEvent(&DeviceExtension->Event,
|
|
||||||
SynchronizationEvent,
|
|
||||||
FALSE);
|
|
||||||
|
|
||||||
return(STATUS_SUCCESS);
|
/* 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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, BeepDPC);
|
||||||
|
KeInitializeTimer(&DeviceExtension->Timer);
|
||||||
|
ExInitializeFastMutex(&DeviceExtension->Mutex);
|
||||||
|
|
||||||
|
/* Page the entire driver */
|
||||||
|
MmPageEntireDriver(DriverEntry);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue