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.

558 lines
18 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1996 - 1996
  3. Module Name:
  4. msmpu401.c
  5. Abstract:
  6. Pin property sets.
  7. --*/
  8. #include "common.h"
  9. #ifdef ALLOC_PRAGMA
  10. #pragma alloc_text(PAGE, PropertyConnectionGetState)
  11. #pragma alloc_text(PAGE, PropertyConnectionGetPriority)
  12. #pragma alloc_text(PAGE, PropertyConnectionSetPriority)
  13. #pragma alloc_text(PAGE, PropertyConnectionGetDataFormat)
  14. #pragma alloc_text(PAGE, MethodConnectionCancelIo)
  15. #pragma alloc_text(PAGE, PinDispatchClose)
  16. #pragma alloc_text(PAGE, PinDispatchCreate)
  17. #pragma alloc_text(PAGE, PinDispatchIoControl)
  18. #endif // ALLOC_PRAGMA
  19. #ifdef ALLOC_DATA_PRAGMA
  20. #pragma data_seg("PAGEDATA")
  21. #endif // ALLOC_DATA_PRAGMA
  22. static const KSDISPATCH_TABLE PinDispatchTable = {
  23. 0,
  24. NULL,
  25. PinDispatchIoControl,
  26. NULL,
  27. NULL,
  28. PinDispatchClose
  29. };
  30. static const KSPROPERTY_ITEM ConnectionPropertyHandlers[] = {
  31. {
  32. KSPROPERTY_CONNECTION_STATE,
  33. (PFNKSPROPERTYHANDLER)PropertyConnectionGetState,
  34. sizeof(KSPROPERTY),
  35. sizeof(KSSTATE),
  36. (PFNKSPROPERTYHANDLER)PropertyConnectionSetState,
  37. sizeof(KSPROPERTY),
  38. sizeof(KSSTATE),
  39. NULL, 0, NULL, NULL
  40. },
  41. {
  42. KSPROPERTY_CONNECTION_PRIORITY,
  43. (PFNKSPROPERTYHANDLER)PropertyConnectionGetPriority,
  44. sizeof(KSPROPERTY),
  45. sizeof(KSPRIORITY),
  46. (PFNKSPROPERTYHANDLER)PropertyConnectionSetPriority,
  47. sizeof(KSPROPERTY),
  48. sizeof(KSPRIORITY),
  49. NULL, 0, NULL, NULL
  50. },
  51. {
  52. KSPROPERTY_CONNECTION_DATAFORMAT,
  53. (PFNKSPROPERTYHANDLER)PropertyConnectionGetDataFormat,
  54. sizeof(KSPROPERTY),
  55. sizeof(KSDATAFORMAT),
  56. NULL, 0, 0, NULL, 0, NULL, NULL
  57. }
  58. };
  59. static const KSPROPERTY_ITEM LinearPropertyHandlers[] = {
  60. {
  61. KSPROPERTY_LINEAR_POSITION,
  62. (PFNKSPROPERTYHANDLER)PropertyLinearGetPosition,
  63. sizeof(KSPROPERTY),
  64. sizeof(ULONGLONG),
  65. NULL, 0, 0, NULL, 0, NULL, NULL
  66. }
  67. };
  68. static const KSPROPERTY_SET PinPropertySets[] = {
  69. {
  70. &KSPROPSETID_Connection,
  71. SIZEOF_ARRAY(ConnectionPropertyHandlers),
  72. (PKSPROPERTY_ITEM)ConnectionPropertyHandlers,
  73. 0, NULL, 0, 0
  74. },
  75. {
  76. &KSPROPSETID_Linear,
  77. SIZEOF_ARRAY(LinearPropertyHandlers),
  78. (PKSPROPERTY_ITEM)LinearPropertyHandlers,
  79. 0, NULL, 0, 0
  80. }
  81. };
  82. static const KSEVENT_ITEM ConnectionEventItems[] = {
  83. {
  84. KSEVENT_CONNECTION_POSITIONUPDATE,
  85. sizeof(KSEVENTDATA),
  86. 0, NULL, NULL, NULL
  87. }
  88. };
  89. static const KSEVENT_SET EventSets[] = {
  90. {
  91. &KSEVENTSETID_Connection,
  92. SIZEOF_ARRAY(ConnectionEventItems),
  93. (PKSEVENT_ITEM)ConnectionEventItems
  94. }
  95. };
  96. static const KSMETHOD_ITEM ConnectionMethodItems[] = {
  97. {
  98. KSMETHOD_CONNECTION_CANCELIO + KSMETHOD_TYPE_NONE,
  99. MethodConnectionCancelIo,
  100. sizeof(KSMETHOD),
  101. 0, NULL
  102. },
  103. };
  104. static const KSMETHOD_SET MethodSets[] = {
  105. {
  106. &KSMETHODSETID_Connection,
  107. SIZEOF_ARRAY(ConnectionMethodItems),
  108. (PVOID)ConnectionMethodItems,
  109. 0, NULL, 0, 0
  110. },
  111. };
  112. #ifdef ALLOC_DATA_PRAGMA
  113. #pragma data_seg()
  114. #endif // ALLOC_DATA_PRAGMA
  115. VOID
  116. PinGenerateEvent(
  117. IN PPIN_INSTANCE PinInstance,
  118. IN REFGUID EventSet,
  119. IN ULONG EventId
  120. )
  121. {
  122. PLIST_ENTRY ListEntry;
  123. for (ListEntry = PinInstance->EventQueue.Flink; ListEntry != &PinInstance->EventQueue; ListEntry = ListEntry->Flink) {
  124. PKSEVENT_ENTRY EventEntry;
  125. EventEntry = (PKSEVENT_ENTRY)CONTAINING_RECORD(ListEntry, KSEVENT_ENTRY, ListEntry);
  126. if (IsEqualGUIDAligned(EventSet, EventEntry->EventSet->Set))
  127. if (EventId == EventEntry->EventItem->EventId)
  128. switch (EventId) {
  129. case KSEVENT_CONNECTION_POSITIONUPDATE:
  130. KsEventGenerate(EventEntry);
  131. break;
  132. }
  133. }
  134. }
  135. static
  136. BOOLEAN
  137. DpcCountSynchronize(
  138. IN PDEVICE_INSTANCE DeviceInstance
  139. )
  140. {
  141. return !DeviceInstance->DpcCount;
  142. }
  143. static
  144. VOID
  145. RundownProcessing(
  146. IN PDEVICE_INSTANCE DeviceInstance,
  147. IN PPIN_INSTANCE PinInstance
  148. )
  149. {
  150. switch (PinInstance->PinId) {
  151. case ID_MUSICCAPTURE_PIN:
  152. while (!KeSynchronizeExecution(DeviceInstance->InterruptInfo.Interrupt, DpcCountSynchronize, DeviceInstance))
  153. KeStallExecutionProcessor(1);
  154. break;
  155. case ID_MUSICPLAYBACK_PIN:
  156. if (KeCancelTimer(&PinInstance->QueueTimer))
  157. InterlockedDecrement(&PinInstance->TimerCount);
  158. while (PinInstance->TimerCount)
  159. KeStallExecutionProcessor(1);
  160. break;
  161. }
  162. }
  163. static
  164. NTSTATUS
  165. SetState(
  166. IN PPIN_INSTANCE PinInstance,
  167. IN KSSTATE State
  168. )
  169. {
  170. ULONGLONG Time;
  171. PDEVICE_INSTANCE DeviceInstance;
  172. if (PinInstance->State == State)
  173. return STATUS_SUCCESS;
  174. DeviceInstance = (PDEVICE_INSTANCE)IoGetRelatedDeviceObject(PinInstance->FilterFileObject)->DeviceExtension;
  175. switch (State) {
  176. case KSSTATE_STOP:
  177. InterlockedExchange((PLONG)&PinInstance->State, (LONG)KSSTATE_STOP);
  178. RundownProcessing(DeviceInstance, PinInstance);
  179. PinInstance->TimeBase = 0;
  180. PinInstance->ByteIo = 0;
  181. break;
  182. case KSSTATE_PAUSE:
  183. if (PinInstance->State == KSSTATE_RUN) {
  184. InterlockedExchange((PLONG)&PinInstance->State, (LONG)KSSTATE_PAUSE);
  185. RundownProcessing(DeviceInstance, PinInstance);
  186. PinInstance->TimeBase = KeQueryPerformanceCounter(NULL).QuadPart - PinInstance->TimeBase;
  187. } else
  188. InterlockedExchange((PLONG)&PinInstance->State, (LONG)KSSTATE_PAUSE);
  189. break;
  190. case KSSTATE_RUN:
  191. Time = KeQueryPerformanceCounter(NULL).QuadPart;
  192. if (PinInstance->State == KSSTATE_STOP)
  193. PinInstance->TimeBase = Time;
  194. else
  195. PinInstance->TimeBase = Time - PinInstance->TimeBase;
  196. InterlockedExchange((PLONG)&PinInstance->State, (LONG)KSSTATE_RUN);
  197. Time = 0;
  198. if (!PinInstance->QueueTimer.Header.Inserted && !KeSetTimerEx(&PinInstance->QueueTimer, *(PLARGE_INTEGER)&Time, 0, &PinInstance->QueueDpc))
  199. InterlockedIncrement(&PinInstance->TimerCount);
  200. break;
  201. }
  202. return STATUS_SUCCESS;
  203. }
  204. NTSTATUS
  205. PropertyConnectionGetState(
  206. IN PIRP Irp,
  207. IN PKSPROPERTY Property,
  208. OUT PKSSTATE State
  209. )
  210. {
  211. *State = ((PPIN_INSTANCE)IoGetCurrentIrpStackLocation(Irp)->FileObject->FsContext)->State;
  212. Irp->IoStatus.Information = sizeof(KSSTATE);
  213. return STATUS_SUCCESS;
  214. }
  215. NTSTATUS
  216. PropertyConnectionSetState(
  217. IN PIRP Irp,
  218. IN PKSPROPERTY Property,
  219. IN PKSSTATE State
  220. )
  221. {
  222. NTSTATUS Status;
  223. PPIN_INSTANCE PinInstance;
  224. KIRQL IrqlOld;
  225. PinInstance = (PPIN_INSTANCE)IoGetCurrentIrpStackLocation(Irp)->FileObject->FsContext;
  226. KeAcquireSpinLock(&PinInstance->StateLock, &IrqlOld);
  227. Status = SetState(PinInstance, *State);
  228. KeReleaseSpinLock(&PinInstance->StateLock, IrqlOld);
  229. return Status;
  230. }
  231. NTSTATUS
  232. PropertyConnectionGetPriority(
  233. IN PIRP Irp,
  234. IN PKSPROPERTY Property,
  235. OUT PKSPRIORITY Priority
  236. )
  237. {
  238. *Priority = ((PPIN_INSTANCE)IoGetCurrentIrpStackLocation(Irp)->FileObject->FsContext)->Priority;
  239. Irp->IoStatus.Information = sizeof(KSPRIORITY);
  240. return STATUS_SUCCESS;
  241. }
  242. NTSTATUS
  243. PropertyConnectionSetPriority(
  244. IN PIRP Irp,
  245. IN PKSPROPERTY Property,
  246. IN PKSPRIORITY Priority
  247. )
  248. {
  249. ((PPIN_INSTANCE)IoGetCurrentIrpStackLocation(Irp)->FileObject->FsContext)->Priority = *Priority;
  250. return STATUS_SUCCESS;
  251. }
  252. NTSTATUS
  253. PropertyConnectionGetDataFormat(
  254. IN PIRP Irp,
  255. IN PKSPROPERTY Property,
  256. OUT PKSDATAFORMAT DataFormat
  257. )
  258. {
  259. DataFormat->MajorFormat = KSDATAFORMAT_TYPE_MUSIC;
  260. DataFormat->SubFormat = KSDATAFORMAT_SUBTYPE_MIDI;
  261. DataFormat->Specifier = KSDATAFORMAT_FORMAT_NONE;
  262. DataFormat->FormatSize = sizeof(KSDATAFORMAT);
  263. Irp->IoStatus.Information = sizeof(KSDATAFORMAT);
  264. return STATUS_SUCCESS;
  265. }
  266. NTSTATUS
  267. PropertyLinearGetPosition(
  268. IN PIRP Irp,
  269. IN PKSPROPERTY Property,
  270. OUT PULONGLONG Position
  271. )
  272. {
  273. KIRQL IrqlOld;
  274. IoAcquireCancelSpinLock(&IrqlOld);
  275. *Position = ((PPIN_INSTANCE)IoGetCurrentIrpStackLocation(Irp)->FileObject->FsContext)->ByteIo;
  276. IoReleaseCancelSpinLock(IrqlOld);
  277. Irp->IoStatus.Information = sizeof(ULONGLONG);
  278. return STATUS_SUCCESS;
  279. }
  280. #if 0
  281. NTSTATUS
  282. propTimeBase(
  283. IN PIRP Irp,
  284. IN PKSPROPERTY Property,
  285. IN OUT PVOID Data
  286. )
  287. {
  288. PPIN_INSTANCE PinInstance;
  289. KIRQL IrqlOld;
  290. PinInstance = (PPIN_INSTANCE)IoGetCurrentIrpStackLocation(Irp)->FileObject->FsContext;
  291. KeAcquireSpinLock(&PinInstance->StateLock, &IrqlOld);
  292. switch (PinInstance->State) {
  293. case KSSTATE_STOP:
  294. case KSSTATE_PAUSE:
  295. *(PULONGLONG)Data = KeQueryPerformanceCounter(NULL).QuadPart - pci->TimeBase;
  296. break;
  297. case KSSTATE_RUN:
  298. *(PULONGLONG)Data = pci->TimeBase;
  299. break;
  300. }
  301. KeReleaseSpinLock(&PinInstance->StateLock, IrqlOld);
  302. Irp->IoStatus.Information = sizeof(ULONGLONG);
  303. return STATUS_SUCCESS;
  304. }
  305. #endif // 0
  306. NTSTATUS
  307. MethodConnectionCancelIo(
  308. IN PIRP Irp,
  309. IN PKSMETHOD Method,
  310. IN OUT PVOID Data
  311. )
  312. {
  313. KsCancelIo(&((PPIN_INSTANCE)IoGetCurrentIrpStackLocation(Irp)->FileObject->FsContext)->IoQueue);
  314. return STATUS_SUCCESS;
  315. }
  316. NTSTATUS PinDispatchClose(
  317. IN PDEVICE_OBJECT pDeviceObject,
  318. IN PIRP Irp)
  319. {
  320. PIO_STACK_LOCATION IrpStack;
  321. PDEVICE_INSTANCE DeviceInstance;
  322. PPIN_INSTANCE PinInstance;
  323. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  324. PinInstance = (PPIN_INSTANCE)IrpStack->FileObject->FsContext;
  325. SetState(PinInstance, KSSTATE_STOP);
  326. KsEventFreeList(Irp, &PinInstance->EventQueue, KSEVENTS_SPINLOCK, &PinInstance->EventQueueLock);
  327. DeviceInstance = (PDEVICE_INSTANCE)IrpStack->DeviceObject->DeviceExtension;
  328. DeviceInstance->PinFileObjects[PinInstance->PinId] = NULL;
  329. ObDereferenceObject(PinInstance->FilterFileObject);
  330. ExFreePool(PinInstance);
  331. Irp->IoStatus.Information = 0;
  332. Irp->IoStatus.Status = STATUS_SUCCESS;
  333. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  334. return STATUS_SUCCESS;
  335. }
  336. NTSTATUS
  337. PinDispatchCreate(
  338. IN PDEVICE_OBJECT DeviceObject,
  339. IN PIRP Irp
  340. )
  341. {
  342. PIO_STACK_LOCATION IrpStack;
  343. PKSPIN_CONNECT Connect;
  344. PFILE_OBJECT FilterFileObject;
  345. NTSTATUS Status;
  346. Irp->IoStatus.Information = 0;
  347. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  348. if (NT_SUCCESS(Status = KsValidateConnectRequest(Irp, SIZEOF_ARRAY(FilterPinDescriptors), (PKSPIN_DESCRIPTOR)FilterPinDescriptors, &Connect, &FilterFileObject))) {
  349. PDEVICE_INSTANCE DeviceInstance;
  350. DeviceInstance = (PDEVICE_INSTANCE)DeviceObject->DeviceExtension;
  351. ExAcquireFastMutexUnsafe(&DeviceInstance->ControlMutex);
  352. if (!DeviceInstance->PinFileObjects[Connect->PinId]) {
  353. PPIN_INSTANCE PinInstance;
  354. if (PinInstance = (PPIN_INSTANCE)ExAllocatePool(NonPagedPool, sizeof(PIN_INSTANCE))) {
  355. IrpStack->FileObject->FsContext = (PVOID)PinInstance;
  356. PinInstance->DispatchTable = (PKSDISPATCH_TABLE)&PinDispatchTable;
  357. KeQueryPerformanceCounter((PLARGE_INTEGER)&PinInstance->Frequency);
  358. PinInstance->State = KSSTATE_STOP;
  359. PinInstance->PinId = Connect->PinId;
  360. InitializeListHead(&PinInstance->IoQueue);
  361. InitializeListHead(&PinInstance->EventQueue);
  362. KeInitializeSpinLock(&PinInstance->EventQueueLock);
  363. PinInstance->TimeBase = 0;
  364. PinInstance->ByteIo = 0;
  365. KeInitializeSpinLock(&PinInstance->StateLock);
  366. if (Connect->PinId == ID_MUSICPLAYBACK_PIN) {
  367. KeInitializeTimerEx(&PinInstance->QueueTimer, NotificationTimer);
  368. KeInitializeDpc(&PinInstance->QueueDpc, (PKDEFERRED_ROUTINE)HwDeferredWrite, DeviceObject);
  369. PinInstance->TimerCount = 0;
  370. }
  371. PinInstance->FilterFileObject = FilterFileObject;
  372. ObReferenceObject(FilterFileObject);
  373. PinInstance->Priority = Connect->Priority;
  374. DeviceInstance->PinFileObjects[Connect->PinId] = IrpStack->FileObject;
  375. } else
  376. Status = STATUS_NO_MEMORY;
  377. } else
  378. Status = STATUS_CONNECTION_REFUSED;
  379. ExReleaseFastMutexUnsafe(&DeviceInstance->ControlMutex);
  380. }
  381. Irp->IoStatus.Status = Status;
  382. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  383. return Status;
  384. }
  385. static
  386. NTSTATUS
  387. WriteStream(
  388. IN PIRP Irp
  389. )
  390. {
  391. PIO_STACK_LOCATION IrpStack;
  392. NTSTATUS Status;
  393. PULONG UserBuffer;
  394. KIRQL IrqlOld;
  395. PPIN_INSTANCE PinInstance;
  396. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  397. Irp->IoStatus.Information = 0;
  398. if (!IrpStack->Parameters.DeviceIoControl.InputBufferLength)
  399. return STATUS_SUCCESS;
  400. if (!NT_SUCCESS(Status = KsProbeStreamIrp(Irp, KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK)))
  401. return Status;
  402. UserBuffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
  403. if ((ULONG)UserBuffer & FILE_LONG_ALIGNMENT)
  404. return STATUS_DATATYPE_MISALIGNMENT;
  405. if (((PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer)->DataSize < 2 * sizeof(ULONG) + sizeof(UCHAR))
  406. return STATUS_BUFFER_TOO_SMALL;
  407. Irp->Tail.Overlay.AuxiliaryBuffer = (PUCHAR)UserBuffer;
  408. Irp->IoStatus.Information = 2 * sizeof(ULONG);
  409. IoMarkIrpPending(Irp);
  410. Irp->IoStatus.Status = STATUS_PENDING;
  411. IoAcquireCancelSpinLock(&IrqlOld);
  412. IoSetCancelRoutine(Irp, HwCancelRoutine);
  413. PinInstance = (PPIN_INSTANCE)IrpStack->FileObject->FsContext;
  414. InsertTailList(&PinInstance->IoQueue, &Irp->Tail.Overlay.ListEntry);
  415. KeAcquireSpinLockAtDpcLevel(&PinInstance->StateLock);
  416. if ((PinInstance->State == KSSTATE_RUN) && !PinInstance->QueueTimer.Header.Inserted) {
  417. ULONGLONG CurrentTime;
  418. ULONGLONG NextTime;
  419. CurrentTime = (KeQueryPerformanceCounter(NULL).QuadPart - PinInstance->TimeBase) * 10000000 / PinInstance->Frequency;
  420. NextTime = ((PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer)->PresentationTime.Time + *UserBuffer * 10000;
  421. if (NextTime < CurrentTime)
  422. NextTime = 0;
  423. else
  424. NextTime = (ULONGLONG)-(LONGLONG)(NextTime - CurrentTime);
  425. if (!KeSetTimerEx(&PinInstance->QueueTimer, *(PLARGE_INTEGER)&NextTime, 0, &PinInstance->QueueDpc))
  426. InterlockedIncrement(&PinInstance->TimerCount);
  427. }
  428. KeReleaseSpinLockFromDpcLevel(&PinInstance->StateLock);
  429. IoReleaseCancelSpinLock(IrqlOld);
  430. return STATUS_PENDING;
  431. }
  432. static
  433. NTSTATUS
  434. ReadStream(
  435. IN PIRP Irp
  436. )
  437. {
  438. PIO_STACK_LOCATION IrpStack;
  439. NTSTATUS Status;
  440. PULONG UserBuffer;
  441. PKSSTREAM_HEADER StreamHdr;
  442. PPIN_INSTANCE PinInstance;
  443. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  444. if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < 2 * sizeof(ULONG) + sizeof(UCHAR))
  445. return STATUS_BUFFER_TOO_SMALL;
  446. if (!NT_SUCCESS(Status = KsProbeStreamIrp(Irp, KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK)))
  447. return Status;
  448. UserBuffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
  449. if ((ULONG)UserBuffer & FILE_LONG_ALIGNMENT)
  450. return STATUS_DATATYPE_MISALIGNMENT;
  451. MmGetSystemAddressForMdl(Irp->MdlAddress);
  452. Irp->IoStatus.Information = sizeof(KSSTREAM_HEADER);
  453. StreamHdr = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
  454. StreamHdr->PresentationTime.Time = 0;
  455. StreamHdr->PresentationTime.Numerator = 1;
  456. StreamHdr->PresentationTime.Denominator = 1;
  457. StreamHdr->DataSize = 0;
  458. StreamHdr->OptionsFlags = 0;
  459. PinInstance = (PPIN_INSTANCE)IrpStack->FileObject->FsContext;
  460. KsAddIrpToCancelableQueue(&PinInstance->IoQueue, Irp, FALSE, HwCancelRoutine);
  461. return STATUS_PENDING;
  462. }
  463. NTSTATUS
  464. PinDispatchIoControl(
  465. IN PDEVICE_OBJECT DeviceObject,
  466. IN PIRP Irp
  467. )
  468. {
  469. PIO_STACK_LOCATION IrpStack;
  470. NTSTATUS Status;
  471. PPIN_INSTANCE PinInstance;
  472. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  473. PinInstance = (PPIN_INSTANCE)IrpStack->FileObject->FsContext;
  474. switch (IrpStack->Parameters.DeviceIoControl.IoControlCode) {
  475. case IOCTL_KS_GET_PROPERTY:
  476. case IOCTL_KS_SET_PROPERTY:
  477. Status = KsPropertyHandler(Irp, SIZEOF_ARRAY(PinPropertySets), (PKSPROPERTY_SET)PinPropertySets);
  478. break;
  479. case IOCTL_KS_ENABLE_EVENT:
  480. Status = KsEventEnable(Irp, SIZEOF_ARRAY(EventSets), (PKSEVENT_SET)EventSets, &PinInstance->EventQueue, KSEVENTS_SPINLOCK, &PinInstance->EventQueueLock);
  481. break;
  482. case IOCTL_KS_DISABLE_EVENT:
  483. Status = KsEventDisable(Irp, &PinInstance->EventQueue, KSEVENTS_SPINLOCK, &PinInstance->EventQueueLock);
  484. break;
  485. case IOCTL_KS_METHOD:
  486. Status = KsMethodHandler(Irp, SIZEOF_ARRAY(MethodSets), (PKSMETHOD_SET)MethodSets);
  487. break;
  488. case IOCTL_KS_READ_STREAM:
  489. if (PinInstance->PinId == ID_MUSICCAPTURE_PIN)
  490. Status = ReadStream(Irp);
  491. else
  492. Status = STATUS_INVALID_DEVICE_REQUEST;
  493. break;
  494. case IOCTL_KS_WRITE_STREAM:
  495. if (PinInstance->PinId == ID_MUSICPLAYBACK_PIN)
  496. Status = WriteStream(Irp);
  497. else
  498. Status = STATUS_INVALID_DEVICE_REQUEST;
  499. break;
  500. default:
  501. Status = STATUS_INVALID_DEVICE_REQUEST;
  502. break;
  503. }
  504. if (Status != STATUS_PENDING) {
  505. Irp->IoStatus.Status = Status;
  506. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  507. }
  508. return Status;
  509. }