Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412/* * 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 *****************************************************************/
VOIDNTAPIBeepDPC(IN PKDPC Dpc, IN PDEVICE_OBJECT DeviceObject, IN PVOID SystemArgument1, IN PVOID SystemArgument2){ PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
UNREFERENCED_PARAMETER(Dpc); UNREFERENCED_PARAMETER(SystemArgument1); UNREFERENCED_PARAMETER(SystemArgument2);
/* Stop the beep */ HalMakeBeep(0);
/* Disable the timer */ InterlockedDecrement(&DeviceExtension->TimerActive);}
DRIVER_DISPATCH BeepCreate;NTSTATUSNTAPIBeepCreate(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;NTSTATUSNTAPIBeepClose(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;VOIDNTAPIBeepCancel(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 release 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;NTSTATUSNTAPIBeepCleanup(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;NTSTATUSNTAPIBeepDeviceControl(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 immediately */ 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;VOIDNTAPIBeepUnload(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;VOIDNTAPIBeepStartIo(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 * -10000LL; 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);}
NTSTATUSNTAPIDriverEntry(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;
UNREFERENCED_PARAMETER(RegistryPath);
/* 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 */