windows-nt/Source/XPSP1/NT/drivers/wdm/input/samples/vxdclnt/write.c
2020-09-26 16:20:57 +08:00

148 lines
3.9 KiB
C

/*
********************************************************************************
*
* WRITE.C
*
*
* VXDCLNT - Sample Ring-0 HID device mapper for Memphis
*
* Copyright 1997 Microsoft Corp.
*
* (ep)
*
********************************************************************************
*/
#include "vxdclnt.h"
writeReport *NewWriteReport(PUCHAR report, ULONG reportLen)
{
writeReport *newReport;
newReport = _HeapAllocate(sizeof(writeReport), 0);
if (newReport){
newReport->report = _HeapAllocate(reportLen, 0);
if (newReport->report){
RtlCopyMemory(newReport->report, report, reportLen);
newReport->reportLen = reportLen;
newReport->next = NULL;
}
else {
_HeapFree(newReport, 0);
newReport = NULL;
}
}
return newReport;
}
VOID DestroyWriteReport(writeReport *oldReport)
{
_HeapFree(oldReport->report, 0);
_HeapFree(oldReport, 0);
}
VOID WorkItemCallback_Write(PVOID context)
{
deviceContext *device = (deviceContext *)context;
Wait_Semaphore(device->writeReportQueueSemaphore, 0);
while (device->writeReportQueue){
writeReport *thisReport = device->writeReportQueue;
LARGE_INTEGER actualLengthWritten;
actualLengthWritten.LowPart = actualLengthWritten.HighPart = 0;
/*
* Write one report
*/
_NtKernWriteFile( device->devHandle,
NULL,
NULL,
0,
(PIO_STATUS_BLOCK)&device->ioStatusBlock,
(PVOID)thisReport->report,
thisReport->reportLen,
&actualLengthWritten,
NULL);
device->writeReportQueue = thisReport->next;
DestroyWriteReport(thisReport);
}
Signal_Semaphore_No_Switch(device->writeReportQueueSemaphore);
}
/*
* SendReportFromClient
*
* This function is a hypothetical entry-point into this HID mapper.
* It sends a report from some unknown client to the HID device.
* In an actual HID mapper driver, this interface might be exposed as a VxD service
* or might be passed to another driver as an entrypoint during initialization.
*
*
* <<COMPLETE>>
* Note: If you are creating your own reports,
* use HidP_SetUsages() (see prototype in vxdclnt.h).
*
*/
NTSTATUS SendReportFromClient(deviceContext *device, PUCHAR report, ULONG reportLen)
{
writeReport *newReport;
NTSTATUS status;
DBGOUT(("==> SendReportFromClient()"));
/*
* Enqueue this report and queue a work item to do the actual write.
*/
newReport = NewWriteReport(report, reportLen);
if (newReport){
Wait_Semaphore(device->writeReportQueueSemaphore, 0);
if (device->writeReportQueue){
writeReport *item;
for (item = device->writeReportQueue; item->next; item = item->next){ }
item->next = newReport;
}
else {
device->writeReportQueue = newReport;
}
Signal_Semaphore_No_Switch(device->writeReportQueueSemaphore);
/*
* Queue a work item to do the read; this way we'll be on a worker thread
* instead of (possibly) the NTKERN thread when we call NtWriteFile().
* This prevents a contention bug.
*/
_NtKernQueueWorkItem(&device->workItemWrite, DelayedWorkQueue);
/*
* In this sample driver, this function always returns success although the write
* is actually pending; an actual driver might provide a richer interface with
* a callback or something.
*/
status = STATUS_SUCCESS;
}
else {
status = STATUS_INSUFFICIENT_RESOURCES;
}
DBGOUT(("<== SendReportFromClient()"));
return status;
}