Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

147 lines
3.9 KiB

  1. /*
  2. ********************************************************************************
  3. *
  4. * WRITE.C
  5. *
  6. *
  7. * VXDCLNT - Sample Ring-0 HID device mapper for Memphis
  8. *
  9. * Copyright 1997 Microsoft Corp.
  10. *
  11. * (ep)
  12. *
  13. ********************************************************************************
  14. */
  15. #include "vxdclnt.h"
  16. writeReport *NewWriteReport(PUCHAR report, ULONG reportLen)
  17. {
  18. writeReport *newReport;
  19. newReport = _HeapAllocate(sizeof(writeReport), 0);
  20. if (newReport){
  21. newReport->report = _HeapAllocate(reportLen, 0);
  22. if (newReport->report){
  23. RtlCopyMemory(newReport->report, report, reportLen);
  24. newReport->reportLen = reportLen;
  25. newReport->next = NULL;
  26. }
  27. else {
  28. _HeapFree(newReport, 0);
  29. newReport = NULL;
  30. }
  31. }
  32. return newReport;
  33. }
  34. VOID DestroyWriteReport(writeReport *oldReport)
  35. {
  36. _HeapFree(oldReport->report, 0);
  37. _HeapFree(oldReport, 0);
  38. }
  39. VOID WorkItemCallback_Write(PVOID context)
  40. {
  41. deviceContext *device = (deviceContext *)context;
  42. Wait_Semaphore(device->writeReportQueueSemaphore, 0);
  43. while (device->writeReportQueue){
  44. writeReport *thisReport = device->writeReportQueue;
  45. LARGE_INTEGER actualLengthWritten;
  46. actualLengthWritten.LowPart = actualLengthWritten.HighPart = 0;
  47. /*
  48. * Write one report
  49. */
  50. _NtKernWriteFile( device->devHandle,
  51. NULL,
  52. NULL,
  53. 0,
  54. (PIO_STATUS_BLOCK)&device->ioStatusBlock,
  55. (PVOID)thisReport->report,
  56. thisReport->reportLen,
  57. &actualLengthWritten,
  58. NULL);
  59. device->writeReportQueue = thisReport->next;
  60. DestroyWriteReport(thisReport);
  61. }
  62. Signal_Semaphore_No_Switch(device->writeReportQueueSemaphore);
  63. }
  64. /*
  65. * SendReportFromClient
  66. *
  67. * This function is a hypothetical entry-point into this HID mapper.
  68. * It sends a report from some unknown client to the HID device.
  69. * In an actual HID mapper driver, this interface might be exposed as a VxD service
  70. * or might be passed to another driver as an entrypoint during initialization.
  71. *
  72. *
  73. * <<COMPLETE>>
  74. * Note: If you are creating your own reports,
  75. * use HidP_SetUsages() (see prototype in vxdclnt.h).
  76. *
  77. */
  78. NTSTATUS SendReportFromClient(deviceContext *device, PUCHAR report, ULONG reportLen)
  79. {
  80. writeReport *newReport;
  81. NTSTATUS status;
  82. DBGOUT(("==> SendReportFromClient()"));
  83. /*
  84. * Enqueue this report and queue a work item to do the actual write.
  85. */
  86. newReport = NewWriteReport(report, reportLen);
  87. if (newReport){
  88. Wait_Semaphore(device->writeReportQueueSemaphore, 0);
  89. if (device->writeReportQueue){
  90. writeReport *item;
  91. for (item = device->writeReportQueue; item->next; item = item->next){ }
  92. item->next = newReport;
  93. }
  94. else {
  95. device->writeReportQueue = newReport;
  96. }
  97. Signal_Semaphore_No_Switch(device->writeReportQueueSemaphore);
  98. /*
  99. * Queue a work item to do the read; this way we'll be on a worker thread
  100. * instead of (possibly) the NTKERN thread when we call NtWriteFile().
  101. * This prevents a contention bug.
  102. */
  103. _NtKernQueueWorkItem(&device->workItemWrite, DelayedWorkQueue);
  104. /*
  105. * In this sample driver, this function always returns success although the write
  106. * is actually pending; an actual driver might provide a richer interface with
  107. * a callback or something.
  108. */
  109. status = STATUS_SUCCESS;
  110. }
  111. else {
  112. status = STATUS_INSUFFICIENT_RESOURCES;
  113. }
  114. DBGOUT(("<== SendReportFromClient()"));
  115. return status;
  116. }