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.

2963 lines
121 KiB

  1. /*++
  2. Copyright (c) 1995-1998 Microsoft Corporation
  3. Module Name:
  4. rcafltr.c
  5. Abstract:
  6. RCA Filter property sets.
  7. Author:
  8. Richard Machin (RMachin)
  9. Revision History:
  10. Who When What
  11. -------- -------- ----------------------------------------------
  12. RMachin 2-25-97 stolen/adapted from msfsread and mswaveio
  13. DChen 3-25-98 Clean up PinDispatchCreate and PinDispatchClose
  14. JameelH 4-18-98 Cleanup
  15. SPATHER 4-20-99 Cleanup. Separated NDIS parts from KS parts.
  16. Notes:
  17. --*/
  18. #include <precomp.h>
  19. #define MODULE_NUMBER MODULE_FLT
  20. #define _FILENUMBER 'RTLF'
  21. #define STREAM_BUFFER_SIZE 8000
  22. #define STREAM_BYTES_PER_SAMPLE 1
  23. NTSTATUS
  24. PinAllocatorFramingEx(
  25. IN PIRP Irp,
  26. IN PKSPROPERTY Property,
  27. IN OUT PKSALLOCATOR_FRAMING_EX Framing
  28. );
  29. NTSTATUS
  30. GetStreamAllocator(
  31. IN PIRP Irp,
  32. IN PKSPROPERTY Property,
  33. IN OUT PVOID * AllocatorHandle
  34. );
  35. NTSTATUS
  36. SetStreamAllocator(
  37. IN PIRP Irp,
  38. IN PKSPROPERTY Property,
  39. IN OUT PVOID * AllocatorHandle
  40. );
  41. NTSTATUS
  42. RCASetProposedDataFormat(
  43. IN PIRP Irp,
  44. IN PKSPROPERTY Property,
  45. IN PKSDATAFORMAT DataFormat
  46. );
  47. #pragma alloc_text(PAGE, PnpAddDevice)
  48. #pragma alloc_text(PAGE, FilterDispatchCreate)
  49. #pragma alloc_text(PAGE, PinDispatchCreate)
  50. #pragma alloc_text(PAGE, FilterDispatchClose)
  51. #pragma alloc_text(PAGE, FilterDispatchIoControl)
  52. #pragma alloc_text(PAGE, FilterTopologyProperty)
  53. #pragma alloc_text(PAGE, FilterPinProperty)
  54. #pragma alloc_text(PAGE, FilterPinInstances)
  55. #pragma alloc_text(PAGE, FilterPinIntersection)
  56. #ifdef ALLOC_DATA_PRAGMA
  57. #pragma data_seg("PAGEDATA")
  58. #endif // ALLOC_DATA_PRAGMA
  59. const KSDISPATCH_TABLE FilterDispatchTable =
  60. {
  61. FilterDispatchIoControl,
  62. KsDispatchInvalidDeviceRequest,
  63. KsDispatchInvalidDeviceRequest,
  64. KsDispatchInvalidDeviceRequest,
  65. FilterDispatchClose,
  66. NULL,
  67. NULL,
  68. NULL,
  69. NULL,
  70. NULL
  71. };
  72. //
  73. // Make these two a single table if there are no special dispatch funcs
  74. // for the devio PIN..
  75. //
  76. static DEFINE_KSDISPATCH_TABLE(
  77. PinDevIoDispatchTable,
  78. PinDispatchIoControl,
  79. KsDispatchInvalidDeviceRequest,
  80. KsDispatchInvalidDeviceRequest,
  81. KsDispatchInvalidDeviceRequest,
  82. PinDispatchClose,
  83. NULL,
  84. NULL,
  85. NULL,
  86. NULL,
  87. NULL);
  88. static DEFINE_KSDISPATCH_TABLE(
  89. PinFileIoDispatchTable,
  90. PinDispatchIoControl,
  91. KsDispatchInvalidDeviceRequest,
  92. KsDispatchInvalidDeviceRequest,
  93. KsDispatchInvalidDeviceRequest,
  94. PinDispatchClose,
  95. NULL,
  96. NULL,
  97. NULL,
  98. NULL,
  99. NULL);
  100. //
  101. // Bridge Pin Properties
  102. //
  103. DEFINE_KSPROPERTY_TABLE(BridgePinProperties)
  104. {
  105. DEFINE_KSPROPERTY_ITEM_PIN_PROPOSEDATAFORMAT(RCASetProposedDataFormat)
  106. };
  107. DEFINE_KSPROPERTY_TABLE(BridgeConnectionProperties)
  108. {
  109. DEFINE_KSPROPERTY_ITEM_CONNECTION_ALLOCATORFRAMING_EX(PinAllocatorFramingEx)
  110. };
  111. DEFINE_KSPROPERTY_SET_TABLE(BridgePropertySets)
  112. {
  113. DEFINE_KSPROPERTY_SET(&KSPROPSETID_Pin,
  114. SIZEOF_ARRAY(BridgePinProperties),
  115. BridgePinProperties,
  116. 0,
  117. NULL),
  118. DEFINE_KSPROPERTY_SET(&KSPROPSETID_Connection,
  119. SIZEOF_ARRAY(BridgeConnectionProperties),
  120. BridgeConnectionProperties,
  121. 0,
  122. NULL)
  123. };
  124. //
  125. // DevIo Pin Properties
  126. //
  127. #if AUDIO_SINK_FLAG
  128. DEFINE_KSPROPERTY_TABLE(DevIoStreamProperties)
  129. {
  130. // DEFINE_KSPROPERTY_ITEM_STREAM_INTERFACE(GetInterface),
  131. // DEFINE_KSPROPERTY_ITEM_STREAM_PRESENTATIONTIME(GetPresentationTime, SetPresentationTime),
  132. // DEFINE_KSPROPERTY_ITEM_STREAM_PRESENTATIONEXTENT(GetPresentationExtent)
  133. DEFINE_KSPROPERTY_ITEM_STREAM_ALLOCATOR(GetStreamAllocator,SetStreamAllocator)
  134. };
  135. #endif
  136. DEFINE_KSPROPERTY_TABLE(DevIoConnectionProperties)
  137. {
  138. DEFINE_KSPROPERTY_ITEM_CONNECTION_STATE(PinDeviceState,PinDeviceState ),
  139. DEFINE_KSPROPERTY_ITEM_CONNECTION_ALLOCATORFRAMING_EX(PinAllocatorFramingEx)
  140. };
  141. DEFINE_KSPROPERTY_SET_TABLE(DevIoPropertySets)
  142. {
  143. #if AUDIO_SINK_FLAG
  144. DEFINE_KSPROPERTY_SET(&KSPROPSETID_Stream,
  145. SIZEOF_ARRAY(DevIoStreamProperties),
  146. DevIoStreamProperties,
  147. 0,
  148. NULL),
  149. #endif
  150. DEFINE_KSPROPERTY_SET(&KSPROPSETID_Connection,
  151. SIZEOF_ARRAY(DevIoConnectionProperties),
  152. DevIoConnectionProperties,
  153. 0,
  154. NULL)
  155. };
  156. DEFINE_KSEVENT_TABLE(ConnectionItems)
  157. {
  158. DEFINE_KSEVENT_ITEM(KSEVENT_CONNECTION_ENDOFSTREAM,
  159. sizeof(KSEVENTDATA),
  160. 0,
  161. NULL,
  162. NULL,
  163. NULL)
  164. };
  165. DEFINE_KSEVENT_SET_TABLE(EventSets)
  166. {
  167. DEFINE_KSEVENT_SET(&KSEVENTSETID_Connection,
  168. SIZEOF_ARRAY(ConnectionItems),
  169. ConnectionItems)
  170. };
  171. // defined in KS.H
  172. static const WCHAR DeviceTypeName[] = KSSTRING_Filter;
  173. //
  174. // The following structures build hierarchically into table of filter properties
  175. // used by the KS library.
  176. //
  177. // "The KSDISPATCH_TABLE structure is used for dispatching IRPs to various
  178. // types of objects contained under a single DRIVER_OBJECT."
  179. //
  180. static DEFINE_KSCREATE_DISPATCH_TABLE(DeviceCreateItems)
  181. {
  182. DEFINE_KSCREATE_ITEM(FilterDispatchCreate, DeviceTypeName, 0)
  183. };
  184. // 'node' is basically not PINS -- i.e. functional blocks of the filter
  185. static GUID Nodes[] =
  186. {
  187. STATICGUIDOF(KSCATEGORY_MEDIUMTRANSFORM)
  188. };
  189. //
  190. // Topology = Pins+Nodes. We have one filter node to which two Pins connect.
  191. // Note each of our Pins is half-duplex. (If a Pin were full-duplex, there would be two
  192. // connections to the filter node). KSFILTER_NODE is the filter itself, i.e. node -1. From
  193. // the doc:
  194. // "The simplest filter (2 pins) would contain just one connection, which would be from
  195. // Node -1, Pin 0, to Node -1, Pin 1."
  196. //
  197. static const KSTOPOLOGY_CONNECTION RenderConnections[] =
  198. {
  199. { KSFILTER_NODE, ID_DEVIO_PIN, 0, 0},
  200. { 0, 1, KSFILTER_NODE, ID_BRIDGE_PIN}
  201. };
  202. static const KSTOPOLOGY_CONNECTION CaptureConnections[] =
  203. {
  204. { KSFILTER_NODE, ID_BRIDGE_PIN, 0, 0},
  205. { 0, 1, KSFILTER_NODE, ID_DEVIO_PIN}
  206. };
  207. // what this filter does -- in our case, transform devio stream to net bridge
  208. static GUID TopologyNodes[] =
  209. {
  210. STATICGUIDOF(KSCATEGORY_RENDER),
  211. STATICGUIDOF(KSCATEGORY_BRIDGE),
  212. STATICGUIDOF(KSCATEGORY_CAPTURE)
  213. };
  214. // this is the composite filter topology, defining the above Pins, Nodes and Connections
  215. const KSTOPOLOGY RenderTopology =
  216. {
  217. 0,//2, // Functional category render, bridge
  218. NULL, //(GUID*) &TopologyNodes[ 0 ],
  219. 2,
  220. (GUID*) &TopologyNodes[0], // Nodes
  221. SIZEOF_ARRAY( RenderConnections ),
  222. RenderConnections
  223. };
  224. const KSTOPOLOGY CaptureTopology =
  225. {
  226. 0,//2, // Functional category bridge, capture
  227. NULL, //(GUID*) &TopologyNodes[ 1 ],
  228. 2,
  229. (GUID*) &TopologyNodes[1], // Nodes
  230. SIZEOF_ARRAY( CaptureConnections ),
  231. CaptureConnections
  232. };
  233. //
  234. // "The DEFINE_KSPROPERTY_PINSET macro allows easier definition of a pin
  235. // property set, as only a few parameters actually change from set to set."
  236. // Used by KS to route PIN queries
  237. //
  238. static DEFINE_KSPROPERTY_PINSET(
  239. FilterPinProperties, // name of the set
  240. FilterPinProperty, // handler
  241. FilterPinInstances, // instances query handler
  242. FilterPinIntersection); // intersection query handler
  243. // Used by KS to route Topology queries
  244. static DEFINE_KSPROPERTY_TOPOLOGYSET(
  245. FilterTopologyProperties, // name of the set
  246. FilterTopologyProperty); // topology query handler
  247. // A table of property sets for Topology and Pins.
  248. static DEFINE_KSPROPERTY_SET_TABLE(FilterPropertySets)
  249. {
  250. DEFINE_KSPROPERTY_SET(&KSPROPSETID_Pin,
  251. SIZEOF_ARRAY(FilterPinProperties),
  252. FilterPinProperties,
  253. 0,
  254. NULL),
  255. DEFINE_KSPROPERTY_SET(&KSPROPSETID_Topology,
  256. SIZEOF_ARRAY(FilterTopologyProperties),
  257. FilterTopologyProperties,
  258. 0,
  259. NULL)
  260. };
  261. //
  262. // a table of interfaces describing Pin interfaces. In our case,
  263. // all Pins have standard byte-position based streaming interface.
  264. //
  265. static DEFINE_KSPIN_INTERFACE_TABLE(PinInterfaces)
  266. {
  267. DEFINE_KSPIN_INTERFACE_ITEM(KSINTERFACESETID_Standard, // standard streaming
  268. KSINTERFACE_STANDARD_STREAMING) // based on byte- rather than time-position
  269. };
  270. //
  271. // 'Medium' for Pin communications -- standard IRP-based device-io
  272. //
  273. static DEFINE_KSPIN_MEDIUM_TABLE(PinMedia)
  274. {
  275. DEFINE_KSPIN_MEDIUM_ITEM(KSMEDIUMSETID_Standard,
  276. KSMEDIUM_TYPE_ANYINSTANCE)
  277. };
  278. //
  279. // Data ranges = collective formats supported on our Pins.
  280. //
  281. //
  282. // Define the wildcard data format.
  283. //
  284. const KSDATARANGE WildcardDataFormat =
  285. {
  286. sizeof( KSDATARANGE ),
  287. 0, // ULONG Flags
  288. 0, // ULONG SampleSize
  289. 0, // ULONG Reserved
  290. STATICGUIDOF( KSDATAFORMAT_TYPE_STREAM ), //STREAM
  291. STATICGUIDOF( KSDATAFORMAT_SUBTYPE_WILDCARD ),
  292. STATICGUIDOF( KSDATAFORMAT_SPECIFIER_NONE ) //NONE
  293. };
  294. const KSDATARANGE SuperWildcardDataFormat =
  295. {
  296. sizeof(KSDATARANGE),
  297. 0,
  298. 0,
  299. 0,
  300. STATICGUIDOF( KSDATAFORMAT_TYPE_WILDCARD ), //STREAM
  301. STATICGUIDOF( KSDATAFORMAT_SUBTYPE_WILDCARD ),
  302. STATICGUIDOF( KSDATAFORMAT_SPECIFIER_WILDCARD ) //NONE
  303. };
  304. #if AUDIO_SINK_FLAG
  305. //
  306. // Data ranges = collective formats supported on our Pins.
  307. // In our case, streams of unknown data
  308. //typedef struct {
  309. // KSDATARANGE DataRange;
  310. // ULONG MaximumChannels;
  311. // ULONG MinimumBitsPerSample;
  312. // ULONG MaximumBitsPerSample;
  313. // ULONG MinimumSampleFrequency;
  314. // ULONG MaximumSampleFrequency;
  315. //} KSDATARANGE_AUDIO, *PKSDATARANGE_AUDIO;
  316. const KSDATARANGE_AUDIO AudioDataFormat =
  317. {
  318. {
  319. sizeof(KSDATARANGE_AUDIO), // (KSDATARANGE_AUDIO),
  320. 0,
  321. 0,
  322. 0,
  323. STATIC_KSDATAFORMAT_TYPE_AUDIO, // major format
  324. STATIC_KSDATAFORMAT_SUBTYPE_PCM, // sub format (WILDCARD?)
  325. STATIC_KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
  326. },
  327. 1, // 1 channels
  328. 8,
  329. 8,
  330. 8000, // 22050,
  331. 8000 // 22050
  332. };
  333. #endif
  334. //
  335. // Array of above (only one for us).
  336. // TBS: we should split this out into an array of specific types when we get more
  337. // sophisticated in identifying the type of stream handled by the VC via CallParams
  338. // -- e.g. audio, video with subformats of compression types. Eventually, we should
  339. // create a bridge PIN of format corresponding to callparams info, then expose the
  340. // full range of these types via the PIN factory. The PinDispatchCreate handler
  341. // would look for a bridge PIN of the corresponding type.
  342. //
  343. PKSDATARANGE PinDevIoRanges[] =
  344. {
  345. #if AUDIO_SINK_FLAG
  346. //(PKSDATARANGE)&AudioDataFormat
  347. (PKSDATARANGE)&SuperWildcardDataFormat
  348. #else
  349. (PKSDATARANGE)&WildcardDataFormat
  350. #endif
  351. };
  352. static const KSDATARANGE PinFileIoRange =
  353. {
  354. sizeof(KSDATARANGE),
  355. 0,
  356. 0,
  357. 0,
  358. STATICGUIDOF( KSDATAFORMAT_TYPE_STREAM ),
  359. STATICGUIDOF( KSDATAFORMAT_SUBTYPE_NONE ),
  360. STATICGUIDOF( KSDATAFORMAT_SPECIFIER_VC_ID ) //KSDATAFORMAT_SPECIFIER_FILENAME
  361. };
  362. //
  363. // Array of above (only one for us).
  364. // TBS: we should split this out into an array of specific types when we get more
  365. // sophisticated in identifying the type of stream handled by the VC via CallParams
  366. // -- e.g. audio, video with subformats of compression types. Eventually, we should
  367. // create a bridge PIN of format corresponding to callparams info, then expose the
  368. // full range of these types via the PIN factory. The PinDispatchCreate handler
  369. // would look for a bridge PIN of the corresponding type.
  370. //
  371. static const PKSDATARANGE PinFileIoRanges[] =
  372. {
  373. (PKSDATARANGE)&PinFileIoRange
  374. };
  375. //
  376. // "The KSPIN_DESCRIPTOR structure contains the more dynamic information
  377. // which a device would keep on a pin when using the built-in handlers
  378. // for dealing with the Pin property set, and connections in general."
  379. //
  380. // We pass this to KS in our FilterPinPropertyHandler when KS wants to know what
  381. // we look like, and let KS pick the bones out of it.
  382. //
  383. DEFINE_KSPIN_DESCRIPTOR_TABLE(CapturePinDescriptors)
  384. {
  385. DEFINE_KSPIN_DESCRIPTOR_ITEMEX( // PIN 0 bridge
  386. SIZEOF_ARRAY(PinInterfaces),
  387. PinInterfaces,
  388. SIZEOF_ARRAY(PinMedia),
  389. PinMedia,
  390. SIZEOF_ARRAY(PinFileIoRanges),
  391. (PKSDATARANGE*)PinFileIoRanges,
  392. KSPIN_DATAFLOW_IN,
  393. KSPIN_COMMUNICATION_BRIDGE,
  394. (GUID*) &TopologyNodes[1],
  395. (GUID*) &TopologyNodes[1]), // no CSA connections to this PIN
  396. DEFINE_KSPIN_DESCRIPTOR_ITEMEX( // PIN 1 output
  397. SIZEOF_ARRAY(PinInterfaces),
  398. PinInterfaces,
  399. SIZEOF_ARRAY(PinMedia),
  400. PinMedia,
  401. SIZEOF_ARRAY(PinDevIoRanges),
  402. (PKSDATARANGE*)PinDevIoRanges,
  403. KSPIN_DATAFLOW_OUT,
  404. KSPIN_COMMUNICATION_BOTH, // SOURCE+SINK
  405. (GUID*) &TopologyNodes[2],
  406. (GUID*) &TopologyNodes[2])
  407. };
  408. DEFINE_KSPIN_DESCRIPTOR_TABLE(RenderPinDescriptors)
  409. {
  410. DEFINE_KSPIN_DESCRIPTOR_ITEMEX( // PIN 0 bridge
  411. SIZEOF_ARRAY(PinInterfaces),
  412. PinInterfaces,
  413. SIZEOF_ARRAY(PinMedia),
  414. PinMedia,
  415. SIZEOF_ARRAY(PinFileIoRanges),
  416. (PKSDATARANGE*)PinFileIoRanges,
  417. KSPIN_DATAFLOW_OUT,
  418. KSPIN_COMMUNICATION_BRIDGE,
  419. (GUID*) &TopologyNodes[1],
  420. (GUID*) &TopologyNodes[1]), // no CSA connections to this PIN
  421. DEFINE_KSPIN_DESCRIPTOR_ITEMEX( // PIN 1 input
  422. SIZEOF_ARRAY(PinInterfaces),
  423. PinInterfaces,
  424. SIZEOF_ARRAY(PinMedia),
  425. PinMedia,
  426. SIZEOF_ARRAY(PinDevIoRanges),
  427. (PKSDATARANGE*)PinDevIoRanges,
  428. KSPIN_DATAFLOW_IN,
  429. KSPIN_COMMUNICATION_SINK,
  430. (GUID*) &TopologyNodes[0],
  431. (GUID*) &TopologyNodes[0]) // we receive IRPs, not produce them
  432. };
  433. // How many instances of a Pin we can have, one entry for each Pin.
  434. const KSPIN_CINSTANCES PinInstances[ MAXNUM_PIN_TYPES ] =
  435. {
  436. // Indeterminate number of possible connections.
  437. {
  438. 1, 0
  439. },
  440. {
  441. 1, 0
  442. }
  443. };
  444. //
  445. // Now the Pin dispatch info
  446. //
  447. static const WCHAR PinTypeName[] = KSSTRING_Pin; // in KS.h
  448. static DEFINE_KSCREATE_DISPATCH_TABLE(FilterObjectCreateDispatch)
  449. {
  450. DEFINE_KSCREATE_ITEM(PinDispatchCreate, PinTypeName, 0)
  451. };
  452. #ifdef ALLOC_DATA_PRAGMA
  453. #pragma data_seg()
  454. #endif // ALLOC_DATA_PRAGMA
  455. NTSTATUS
  456. PnpAddDevice(
  457. IN PDRIVER_OBJECT DriverObject,
  458. IN PDEVICE_OBJECT PhysicalDeviceObject
  459. )
  460. /*++
  461. Routine Description:
  462. When a new device is detected, PnP calls this entry point with the
  463. new PhysicalDeviceObject (PDO). The driver creates an associated
  464. FunctionalDeviceObject (FDO).
  465. Note that we keep global device info in a global structure, RcaGlobal.
  466. This info is common to all devices on this driver object (such as NDIS inititaliztion
  467. info, adapter queue etc). Since we get called here for EACH interface (capture, render) we
  468. can't keep global ingfo in the FDO device extension.
  469. Arguments:
  470. DriverObject -
  471. Pointer to the driver object.
  472. PhysicalDeviceObject -
  473. Pointer to the new physical device object.
  474. Return Values:
  475. STATUS_SUCCESS or an appropriate error condition.
  476. --*/
  477. {
  478. PDEVICE_OBJECT FunctionalDeviceObject = NULL, PnpDeviceObject = NULL;
  479. NTSTATUS Status = STATUS_SUCCESS;
  480. RCADEBUGP(RCA_INFO, ("PnPAddDevice: Enter\n"));
  481. do
  482. {
  483. Status = IoCreateDevice(DriverObject,
  484. sizeof(DEVICE_INSTANCE),
  485. NULL,
  486. FILE_DEVICE_KS,
  487. 0,
  488. FALSE,
  489. &FunctionalDeviceObject);
  490. if (!NT_SUCCESS(Status)) {
  491. RCADEBUGP(RCA_ERROR, ("PnpAddDevice: "
  492. "IoCreateDevice() failed - Status == 0x%x\n", Status));
  493. break;
  494. }
  495. DeviceExtension = (PDEVICE_INSTANCE)FunctionalDeviceObject->DeviceExtension;
  496. RtlCopyMemory(DeviceExtension->PinInstances,
  497. PinInstances,
  498. sizeof(PinInstances));
  499. RcaGlobal.FilterCreateItems[ FilterTypeRender ].Create = FilterDispatchCreate;
  500. RcaGlobal.FilterCreateItems[ FilterTypeRender ].Context = (PVOID) FilterTypeRender;
  501. RtlStringFromGUID(&KSCATEGORY_RENDER,
  502. &RcaGlobal.FilterCreateItems[ FilterTypeRender ].ObjectClass);
  503. RcaGlobal.FilterCreateItems[ FilterTypeRender ].SecurityDescriptor = NULL;
  504. RcaGlobal.FilterCreateItems[ FilterTypeRender ].Flags = 0;
  505. RcaGlobal.FilterCreateItems[ FilterTypeCapture ].Create = FilterDispatchCreate;
  506. RcaGlobal.FilterCreateItems[ FilterTypeCapture ].Context = (PVOID) FilterTypeCapture;
  507. RtlStringFromGUID(&KSCATEGORY_CAPTURE,
  508. &RcaGlobal.FilterCreateItems[ FilterTypeCapture ].ObjectClass);
  509. RcaGlobal.FilterCreateItems[ FilterTypeCapture ].SecurityDescriptor = NULL;
  510. RcaGlobal.FilterCreateItems[ FilterTypeCapture ].Flags = 0;
  511. //
  512. // This object uses KS to perform access through the DeviceCreateItems.
  513. //
  514. Status = KsAllocateDeviceHeader(&DeviceExtension->Header,
  515. SIZEOF_ARRAY(RcaGlobal.FilterCreateItems),
  516. RcaGlobal.FilterCreateItems);
  517. if (!NT_SUCCESS(Status)) {
  518. RCADEBUGP(RCA_ERROR, ("PnpAddDevice: "
  519. "KsAllocateDeviceHeader() failed - Status == 0x%x\n", Status));
  520. break;
  521. }
  522. PnpDeviceObject = IoAttachDeviceToDeviceStack(FunctionalDeviceObject, PhysicalDeviceObject);
  523. if (PnpDeviceObject == NULL) {
  524. RCADEBUGP(RCA_ERROR, ("PnpAddDevice: "
  525. "Could not attach our FDO to the device stack\n"));
  526. break;
  527. }
  528. KsSetDevicePnpAndBaseObject(DeviceExtension->Header,
  529. PnpDeviceObject,
  530. FunctionalDeviceObject);
  531. FunctionalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  532. FunctionalDeviceObject->Flags |= DO_POWER_PAGABLE;
  533. //
  534. // Finally, initialize as a Co-NDIS client.
  535. //
  536. if (RcaGlobal.bProtocolInitialized == FALSE) {
  537. RCA_CO_NDIS_HANDLERS Handlers;
  538. Handlers.ReceiveCallback = RCAReceiveCallback;
  539. Handlers.SendCompleteCallback = RCASendCompleteCallback;
  540. Handlers.VcCloseCallback = RCAVcCloseCallback;
  541. Status = RCACoNdisInitialize(&Handlers, RCA_SAP_REG_TIMEOUT);
  542. if (!NT_SUCCESS(Status)) {
  543. RCADEBUGP(RCA_ERROR, ("PnpAddDevice: "
  544. "Failed to initialize as a Co-Ndis client - Status == 0x%x\n",
  545. Status));
  546. break;
  547. }
  548. RcaGlobal.bProtocolInitialized = TRUE;
  549. }
  550. } while (FALSE);
  551. if (!NT_SUCCESS(Status))
  552. {
  553. RCADEBUGP(RCA_ERROR, ("PnpAddDevice: "
  554. "Bad Status (0x%x) - calling IoDeleteDevice() on FDO\n", Status));
  555. if (PnpDeviceObject)
  556. IoDetachDevice(PnpDeviceObject);
  557. if (FunctionalDeviceObject)
  558. IoDeleteDevice(FunctionalDeviceObject);
  559. }
  560. RCADEBUGP(RCA_INFO, ("PnpAddDevice: "
  561. "Exit - Returning Status == 0x%x\n", Status));
  562. return(Status);
  563. }
  564. NTSTATUS
  565. FilterDispatchClose(
  566. IN PDEVICE_OBJECT DeviceObject,
  567. IN PIRP Irp
  568. )
  569. /*++
  570. Routine Description:
  571. Closes a previously opened Filter instance. This can only occur after the Pins have been
  572. closed, as they reference the Filter object when created. This also implies that all the
  573. resources the Pins use have been released or cleaned up.
  574. Arguments:
  575. DeviceObject -
  576. Device object on which the close is occuring.
  577. Irp -
  578. Close Irp.
  579. Return Values:
  580. Returns STATUS_SUCCESS.
  581. --*/
  582. {
  583. PFILTER_INSTANCE FilterInstance;
  584. #if DBG
  585. KIRQL EntryIrql;
  586. #endif
  587. RCA_GET_ENTRY_IRQL(EntryIrql);
  588. RCADEBUGP(RCA_INFO, ("FilterDispatchClose: Enter\n"));
  589. FilterInstance = (PFILTER_INSTANCE)IoGetCurrentIrpStackLocation(Irp)->FileObject->FsContext;
  590. //
  591. // Notify the software bus that the device has been closed.
  592. //
  593. KsDereferenceSoftwareBusObject(((PDEVICE_INSTANCE)DeviceObject->DeviceExtension)->Header);
  594. //
  595. // These were allocated during the creation of the Filter instance.
  596. //
  597. KsFreeObjectHeader(FilterInstance->Header);
  598. RCAFreeMem(FilterInstance);
  599. Irp->IoStatus.Status = STATUS_SUCCESS;
  600. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  601. RCA_CHECK_EXIT_IRQL(EntryIrql);
  602. RCADEBUGP(RCA_INFO, ("FilterDispatchClose: "
  603. "Exit - Returning STATUS_SUCCESS\n"));
  604. return(STATUS_SUCCESS);
  605. }
  606. NTSTATUS
  607. FilterDispatchIoControl(
  608. IN PDEVICE_OBJECT DeviceObject,
  609. IN PIRP Irp
  610. )
  611. /*++
  612. Routine Description:
  613. Dispatches property requests on a Filter instance. These are enumerated in the
  614. FilterPropertySets list.
  615. Arguments:
  616. DeviceObject -
  617. Device object on which the device control is occuring.
  618. Irp -
  619. Device control Irp.
  620. Return Values:
  621. Returns STATUS_SUCCESS if the property was successfully manipulated, else an error.
  622. --*/
  623. {
  624. PIO_STACK_LOCATION IrpStack;
  625. NTSTATUS Status;
  626. RCADEBUGP(RCA_INFO, ("FilterDispatchIoControl: Enter\n"));
  627. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  628. switch(IrpStack->Parameters.DeviceIoControl.IoControlCode) {
  629. case IOCTL_KS_PROPERTY:
  630. RCADEBUGP(RCA_INFO, ("FilterDispatchIoControl: KsPropertyHandler\n"));
  631. Status = KsPropertyHandler(Irp, SIZEOF_ARRAY(FilterPropertySets), FilterPropertySets);
  632. break;
  633. default:
  634. RCADEBUGP(RCA_WARNING, ("FilterDispatchIoControl: "
  635. "Invalid Device Request - Io Control Code 0x%x\n",
  636. IrpStack->Parameters.DeviceIoControl.IoControlCode));
  637. Status = KsDefaultDeviceIoCompletion(DeviceObject, Irp);
  638. RCADEBUGP(RCA_WARNING, ("FilterDispatchIoControl: "
  639. "Returning Status == 0x%x\n", Status));
  640. return Status;
  641. }
  642. Irp->IoStatus.Status = Status;
  643. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  644. RCADEBUGP(RCA_INFO, ("FilterDispatchIoControl: "
  645. "Exit - Returning Status == 0x%x\n", Status));
  646. return Status;
  647. }
  648. NTSTATUS
  649. FilterTopologyProperty(
  650. IN PIRP Irp,
  651. IN PKSPROPERTY Property,
  652. IN OUT PVOID Data
  653. )
  654. /*++
  655. Routine Description:
  656. This is the general handler for all Topology property requests, and is used to route
  657. the request to the KsTopologyPropertyHandler using the FilterTopology information.
  658. This request would have been routed through FilterDispatchIoControl, then
  659. KsPropertyHandler, which would have then called the handler for the property item,
  660. which is this function.
  661. Arguments:
  662. Irp -
  663. Device control Irp.
  664. Property -
  665. Specific property request.
  666. Data -
  667. Property data.
  668. Return Values:
  669. Returns STATUS_SUCCESS if the property was successfully manipulated, else an error.
  670. --*/
  671. {
  672. PFILTER_INSTANCE FilterInstance;
  673. PIO_STACK_LOCATION irpSp;
  674. NTSTATUS Status = 0;
  675. RCADEBUGP(RCA_INFO, ("FilterTopologyProperty: Enter\n"));
  676. irpSp = IoGetCurrentIrpStackLocation( Irp );
  677. FilterInstance = (PFILTER_INSTANCE)irpSp->FileObject->FsContext;
  678. if (FilterInstance->FilterType == FilterTypeRender) {
  679. Status = KsTopologyPropertyHandler( Irp, Property, Data, &RenderTopology);
  680. RCADEBUGP(RCA_INFO, ("FilterTopologyProperty: "
  681. "Render device - Returning Status == 0x%x\n", Status));
  682. return Status;
  683. } else {
  684. Status = KsTopologyPropertyHandler( Irp, Property, Data, &CaptureTopology);
  685. RCADEBUGP(RCA_INFO, ("FilterTopologyProperty: "
  686. "Capture device - Returning Status == 0x%x\n", Status));
  687. return Status;
  688. }
  689. }
  690. NTSTATUS
  691. FilterPinProperty(
  692. IN PIRP Irp,
  693. IN PKSPROPERTY Property,
  694. IN OUT PVOID Data
  695. )
  696. /*++
  697. Routine Description:
  698. This is the general handler for most Pin property requests, and is used to route
  699. the request to the KsPinPropertyHandler using the PinDescriptors information.
  700. This request would have been routed through FilterDispatchIoControl, then
  701. KsPropertyHandler, which would have then called the handler for the property item,
  702. which is this function.
  703. Arguments:
  704. Irp -
  705. Device control Irp.
  706. Property -
  707. Specific property request. This actually contains a PKSP_PIN pointer in
  708. most cases.
  709. Data -
  710. Property data.
  711. Return Values:
  712. Returns STATUS_SUCCESS if the property was successfully manipulated, else an error.
  713. --*/
  714. {
  715. PFILTER_INSTANCE FilterInstance;
  716. PIO_STACK_LOCATION IrpStack;
  717. NTSTATUS Status = 0;
  718. RCADEBUGP(RCA_INFO,("FilterPinProperty: Enter\n"));
  719. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  720. FilterInstance = (PFILTER_INSTANCE)IrpStack->FileObject->FsContext;
  721. RCADEBUGP(RCA_LOUD, ("FilterPinProperty: "
  722. "FilterInstance == 0x%x, Type == 0x%x, Property == 0x%x, Property Id == 0x%x\n",
  723. FilterInstance, FilterInstance->FilterType, Property, Property->Id));
  724. Status = KsPinPropertyHandler(Irp,
  725. Property,
  726. Data,
  727. SIZEOF_ARRAY(RenderPinDescriptors), // same size both cases
  728. (FilterInstance->FilterType == FilterTypeRender ?
  729. RenderPinDescriptors : CapturePinDescriptors));
  730. RCADEBUGP(RCA_INFO, ("FilterPinProperty: "
  731. "Exit - Returning Status == 0x%x, Data == 0x%x, "
  732. "Irp->IoStatus.Information == 0x%x\n",
  733. Status, Data, Irp->IoStatus.Information));
  734. return Status;
  735. }
  736. NTSTATUS
  737. FilterPinInstances(
  738. IN PIRP Irp,
  739. IN PKSP_PIN pPin,
  740. OUT PKSPIN_CINSTANCES pCInstances
  741. )
  742. /*++
  743. Routine Description:
  744. Handles the KSPROPERTY_PIN_CINSTANCES property in the Pin property set. Returns the
  745. total possible and current number of Pin instances available for a Pin factory.
  746. Arguments:
  747. Irp -
  748. Device control Irp.
  749. Pin -
  750. Specific property request followed by Pin factory identifier.
  751. Instances -
  752. The place in which to return the instance information of the specified Pin factory.
  753. Return Values:
  754. returns STATUS_SUCCESS, else STATUS_INVALID_PARAMETER.
  755. --*/
  756. {
  757. PIO_STACK_LOCATION irpSp;
  758. PFILTER_INSTANCE FilterInstance;
  759. RCADEBUGP(RCA_INFO, ("FilterPinInstances: Enter - "
  760. "Pin ID == 0x%x\n", pPin->PinId));
  761. irpSp = IoGetCurrentIrpStackLocation(Irp);
  762. FilterInstance = (PFILTER_INSTANCE)irpSp->FileObject->FsContext;
  763. //
  764. // This count maintanied by KS
  765. //
  766. *pCInstances = FilterInstance->PinInstances[pPin->PinId];
  767. RCADEBUGP(RCA_LOUD, ("FilterPinInstances: "
  768. "Pin Instance == 0x%x\n", DeviceExtension->PinInstances[pPin->PinId]));
  769. Irp->IoStatus.Information = sizeof( KSPIN_CINSTANCES );
  770. RCADEBUGP(RCA_INFO, ("FilterPinInstances: Exit - "
  771. "pCInstances == 0x%x, Irp->IoStatus.Information == 0x%x, "
  772. "Returning STATUS_SUCCESS\n", pCInstances, Irp->IoStatus.Information));
  773. return STATUS_SUCCESS;
  774. }
  775. //
  776. // DEBUG - For debugging only - START
  777. KSDATAFORMAT_WAVEFORMATEX MyWaveFormatPCM = {
  778. {
  779. sizeof(KSDATAFORMAT_WAVEFORMATEX),
  780. 0,
  781. 0,
  782. 0,
  783. STATIC_KSDATAFORMAT_TYPE_AUDIO,
  784. STATIC_KSDATAFORMAT_SUBTYPE_PCM,
  785. STATIC_KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
  786. },
  787. {
  788. WAVE_FORMAT_PCM,
  789. 1,
  790. 8000,
  791. 8000,
  792. 1,
  793. 8,
  794. 0
  795. }
  796. };
  797. KSDATAFORMAT_WAVEFORMATEX MyWaveFormatMULAW = {
  798. {
  799. sizeof(KSDATAFORMAT_WAVEFORMATEX),
  800. 0,
  801. 0,
  802. 0,
  803. STATIC_KSDATAFORMAT_TYPE_AUDIO,
  804. STATIC_KSDATAFORMAT_SUBTYPE_MULAW,
  805. STATIC_KSDATAFORMAT_SPECIFIER_WAVEFORMATEX
  806. },
  807. {
  808. WAVE_FORMAT_MULAW,
  809. 1,
  810. 8000,
  811. 8000,
  812. 1,
  813. 8,
  814. 0
  815. }
  816. };
  817. // DEBUG - For debugging only - END
  818. //
  819. NTSTATUS
  820. RCAGenericIntersection(
  821. IN PIRP Irp,
  822. IN PKSDATARANGE DataRange,
  823. IN ULONG OutputBufferLength,
  824. OUT PVOID Data
  825. )
  826. /*++
  827. Routine Description:
  828. This routine computes the intersection of a given data range with the data format
  829. specified by the app via the PIN_PROPOSEDATAFORMAT property.
  830. Arguments:
  831. Irp -
  832. Device control Irp.
  833. DataRange -
  834. Contains a specific data range to validate.
  835. OutputBufferLength -
  836. Length of the data buffer pointed to by "Data".
  837. Data -
  838. The place in which to return the data format selected as the first intersection
  839. between the list of data ranges passed, and the acceptable formats.
  840. Return Values:
  841. returns STATUS_SUCCESS or STATUS_NO_MATCH, else STATUS_INVALID_PARAMETER,
  842. STATUS_BUFFER_TOO_SMALL, or STATUS_INVALID_BUFFER_SIZE.
  843. --*/
  844. {
  845. BOOL bWCardFormat;
  846. PIO_STACK_LOCATION irpSp;
  847. PFILTER_INSTANCE pFilterInstance;
  848. PPIN_INSTANCE_BRIDGE pBridgePin;
  849. PKSDATARANGE DataRangeSource = NULL;
  850. BOOL bNeedReleaseLock = FALSE;
  851. NTSTATUS Status = STATUS_SUCCESS;
  852. RCADEBUGP(RCA_INFO, ("RCAGenericIntersection: Enter\n"));
  853. irpSp = IoGetCurrentIrpStackLocation(Irp);
  854. pFilterInstance = (PFILTER_INSTANCE)irpSp->FileObject->FsContext;
  855. pBridgePin = pFilterInstance->BridgePin;
  856. bWCardFormat = IsEqualGUIDAligned(&DataRange->SubFormat, &SuperWildcardDataFormat.SubFormat) &&
  857. IsEqualGUIDAligned(&DataRange->Specifier, &SuperWildcardDataFormat.Specifier);
  858. RCADEBUGP(RCA_LOUD, ("RCAGenericIntersection: "
  859. "bWCardFormat == 0x%x\n", bWCardFormat));
  860. do {
  861. if (pBridgePin) {
  862. RCA_ACQUIRE_BRIDGE_PIN_LOCK(pBridgePin);
  863. RCADEBUGP(RCA_LOUD, ("RCAGenericIntersection: Acquired Bridge Pin Lock\n"));
  864. bNeedReleaseLock = TRUE;
  865. if ((DataRangeSource = (PKSDATARANGE)pBridgePin->pDataFormat) == NULL) {
  866. RCA_RELEASE_BRIDGE_PIN_LOCK(pBridgePin);
  867. RCADEBUGP(RCA_LOUD, ("RCAGenericIntersection: Released Bridge Pin Lock\n"));
  868. bNeedReleaseLock = FALSE;
  869. }
  870. //
  871. // DEBUG - FOR DEBUGGING ONLY - Start
  872. if (g_ulHardcodeDataFormat == 1) {
  873. DataRangeSource = (PKSDATARANGE)&MyWaveFormatPCM;
  874. } else if (g_ulHardcodeDataFormat == 2) {
  875. DataRangeSource = (PKSDATARANGE)&MyWaveFormatMULAW;
  876. }
  877. // DEBUG - FOR DEBUGGING ONLY - End
  878. //
  879. }
  880. if (DataRangeSource == NULL) {
  881. if (bWCardFormat) {
  882. RCADEBUGP(RCA_ERROR, ("RCAGenericIntersection: "
  883. "Input data format was wildcard and we have no format "
  884. "set - Setting Status == STATUS_NO_MATCH\n"));
  885. Status = STATUS_NO_MATCH;
  886. break;
  887. } else {
  888. DataRangeSource = DataRange;
  889. }
  890. }
  891. if (OutputBufferLength == 0) {
  892. Irp->IoStatus.Information = DataRangeSource->FormatSize;
  893. RCADEBUGP(RCA_INFO, ("RCAGenericIntersection: "
  894. "Output buffer length was zero, placing size of "
  895. "data range (0x%x) into Irp->IoStatus.Information, "
  896. "Setting Status == STATUS_BUFFER_OVERFLOW\n", DataRangeSource->FormatSize));
  897. Status = STATUS_BUFFER_OVERFLOW;
  898. break;
  899. }
  900. if (OutputBufferLength == sizeof(ULONG)) {
  901. *(PULONG)Data = DataRangeSource->FormatSize;
  902. Irp->IoStatus.Information = sizeof(ULONG);
  903. RCADEBUGP(RCA_LOUD, ("RCAGenericIntersection: "
  904. "Output buffer is one ULONG big, placing size of "
  905. "data range (0x%x) in output buffer, "
  906. "Setting Status == STATUS_SUCCESS\n", DataRangeSource->FormatSize));
  907. Status = STATUS_SUCCESS;
  908. break;
  909. }
  910. if (OutputBufferLength < DataRangeSource->FormatSize) {
  911. RCADEBUGP(RCA_ERROR, ("RCAGenericIntersection: "
  912. "Output buffer too small, Setting Status == STATUS_BUFFER_TOO_SMALL\n"));
  913. Status = STATUS_BUFFER_TOO_SMALL;
  914. break;
  915. }
  916. } while(FALSE);
  917. if (Status == STATUS_SUCCESS) {
  918. Irp->IoStatus.Information = DataRangeSource->FormatSize;
  919. RtlCopyMemory(Data, DataRangeSource, DataRangeSource->FormatSize);
  920. RCADEBUGP(RCA_LOUD, ("RCAGenericIntersection: "
  921. "Copied data range to output, Leaving Status == STATUS_SUCCESS\n"));
  922. }
  923. if (bNeedReleaseLock) {
  924. RCA_RELEASE_BRIDGE_PIN_LOCK(pBridgePin);
  925. RCADEBUGP(RCA_LOUD, ("RCAGenericIntersection: Released Bridge Pin Lock\n"));
  926. bNeedReleaseLock = FALSE;
  927. }
  928. RCADEBUGP(RCA_INFO, ("RCAGenericIntersection: Exit - Returning Status == 0x%x\n", Status));
  929. return Status;
  930. }
  931. NTSTATUS
  932. RCAIntersect(
  933. IN PIRP Irp,
  934. IN PKSP_PIN Pin,
  935. IN PKSDATARANGE DataRange,
  936. OUT PVOID Data
  937. )
  938. /*++
  939. Routine Description:
  940. This is the data range callback for KsPinDataIntersection, which is called by
  941. FilterPinIntersection to enumerate the given list of data ranges, looking for
  942. an acceptable match. If a data range is acceptable, a data format is copied
  943. into the return buffer. A STATUS_NO_MATCH continues the enumeration.
  944. Arguments:
  945. Irp -
  946. Device control Irp.
  947. Pin -
  948. Specific property request followed by Pin factory identifier, followed by a
  949. KSMULTIPLE_ITEM structure. This is followed by zero or more data range structures.
  950. \This enumeration callback does not need to look at any of this though. It need
  951. only look at the specific pin identifier.
  952. DataRange -
  953. Contains a specific data range to validate.
  954. Data -
  955. The place in which to return the data format selected as the first intersection
  956. between the list of data ranges passed, and the acceptable formats.
  957. Return Values:
  958. returns STATUS_SUCCESS or STATUS_NO_MATCH, else STATUS_INVALID_PARAMETER,
  959. STATUS_BUFFER_TOO_SMALL, or STATUS_INVALID_BUFFER_SIZE.
  960. --*/
  961. {
  962. NTSTATUS Status = STATUS_SUCCESS;
  963. PFILTER_INSTANCE FilterInstance;
  964. PIO_STACK_LOCATION irpSp;
  965. ULONG OutputBufferLength;
  966. GUID SubFormat;
  967. BOOL SubFormatSet;
  968. BOOL CorrectAudioFormat = FALSE, WCardFormat = FALSE;
  969. RCADEBUGP(RCA_INFO, ("RCAIntersect: Enter - "
  970. "DataRange size == %d\n", DataRange->FormatSize));
  971. irpSp = IoGetCurrentIrpStackLocation(Irp);
  972. FilterInstance = (PFILTER_INSTANCE)irpSp->FileObject->FsContext;
  973. OutputBufferLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
  974. RCADEBUGP(RCA_LOUD, ("RCAIntersect: OutputBufferLength == %d\n", OutputBufferLength));
  975. //
  976. // All the major/sub/specifier checking has been done by the handler.
  977. //
  978. if (DataRange->FormatSize < sizeof( KSDATAFORMAT )) {
  979. RCADEBUGP(RCA_ERROR, ("RCAIntersect: "
  980. "Format size is less than size of KSDATAFORMAT - "
  981. "Returning STATUS_NO_MATCH\n"));
  982. return STATUS_NO_MATCH;
  983. }
  984. RCADEBUGP(RCA_LOUD, ("RCAIntersect: DataRange->FormatSize == 0x%08x\n"
  985. "RCAIntersect: DataRange->Flags == 0x%08x\n"
  986. "RCAIntersect: DataRange->SampleSize == 0x%08x\n"
  987. "RCAIntersect: DataRange->Reserved == 0x%08x\n",
  988. DataRange->FormatSize,
  989. DataRange->Flags,
  990. DataRange->SampleSize,
  991. DataRange->Reserved));
  992. RCADEBUGP(RCA_LOUD, ("RCAIntersect: DataRange->MajorFormat == "));
  993. RCADumpGUID(RCA_LOUD, &DataRange->MajorFormat);
  994. RCADEBUGP(RCA_LOUD, ("\n"
  995. "RCAIntersect: DataRange->SubFormat == "));
  996. RCADumpGUID(RCA_LOUD, &DataRange->SubFormat);
  997. RCADEBUGP(RCA_LOUD, ("\n"
  998. "RCAIntersect: DataRange->Specifier == "));
  999. RCADumpGUID(RCA_LOUD, &DataRange->Specifier);
  1000. RCADEBUGP(RCA_LOUD, ("\n"));
  1001. RCADEBUGP(RCA_LOUD, ("RCAIntersect: DataRange->FormatSize == 0x%08x\n"
  1002. "RCAIntersect: DataRange->Flags == 0x%08x\n"
  1003. "RCAIntersect: DataRange->SampleSize == 0x%08x\n"
  1004. "RCAIntersect: DataRange->Reserved == 0x%08x\n"
  1005. "RCAIntersect: DataRange->MajorFormat == %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n"
  1006. "RCAIntersect: DataRange->SubFormat == %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n"
  1007. "RCAIntersect: DataRange->Specifier == %08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
  1008. DataRange->FormatSize,
  1009. DataRange->Flags,
  1010. DataRange->SampleSize,
  1011. DataRange->Reserved,
  1012. DataRange->MajorFormat.Data1, DataRange->MajorFormat.Data2,
  1013. DataRange->MajorFormat.Data3, DataRange->MajorFormat.Data4[0],
  1014. DataRange->MajorFormat.Data4[1], DataRange->MajorFormat.Data4[2],
  1015. DataRange->MajorFormat.Data4[3], DataRange->MajorFormat.Data4[4],
  1016. DataRange->MajorFormat.Data4[5], DataRange->MajorFormat.Data4[6],
  1017. DataRange->MajorFormat.Data4[7],
  1018. DataRange->SubFormat.Data1, DataRange->SubFormat.Data2,
  1019. DataRange->SubFormat.Data3, DataRange->SubFormat.Data4[0],
  1020. DataRange->SubFormat.Data4[1], DataRange->SubFormat.Data4[2],
  1021. DataRange->SubFormat.Data4[3], DataRange->SubFormat.Data4[4],
  1022. DataRange->SubFormat.Data4[5], DataRange->SubFormat.Data4[6],
  1023. DataRange->SubFormat.Data4[7],
  1024. DataRange->Specifier.Data1, DataRange->Specifier.Data2,
  1025. DataRange->Specifier.Data3, DataRange->Specifier.Data4[0],
  1026. DataRange->Specifier.Data4[1], DataRange->Specifier.Data4[2],
  1027. DataRange->Specifier.Data4[3], DataRange->Specifier.Data4[4],
  1028. DataRange->Specifier.Data4[5], DataRange->Specifier.Data4[6],
  1029. DataRange->Specifier.Data4[7]));
  1030. if (Pin->PinId == ID_DEVIO_PIN) {
  1031. Status = RCAGenericIntersection(Irp, DataRange, OutputBufferLength, Data);
  1032. } else {
  1033. RCADEBUGP(RCA_LOUD, ("RCAIntersect: BRIDGE Pin\n"));
  1034. if (OutputBufferLength == 0) {
  1035. Irp->IoStatus.Information = DataRange->FormatSize;
  1036. RCADEBUGP(RCA_INFO, ("RCAIntersect: "
  1037. "Output buffer length was zero, placing size 0x%x "
  1038. "in Irp->IoStatus.Information, "
  1039. "Returning STATUS_BUFFER_OVERFLOW\n", DataRange->FormatSize));
  1040. return STATUS_BUFFER_OVERFLOW;
  1041. }
  1042. if (OutputBufferLength == sizeof(ULONG)) {
  1043. *(PULONG)Data = DataRange->FormatSize;
  1044. Irp->IoStatus.Information = sizeof(ULONG);
  1045. RCADEBUGP(RCA_LOUD, ("RCAIntersect: "
  1046. "Output buffer is one ULONG big, placing size 0x%x "
  1047. "in output buffer, "
  1048. "Returning STATUS_SUCCESS\n", DataRange->FormatSize));
  1049. return STATUS_SUCCESS;
  1050. }
  1051. if (OutputBufferLength < DataRange->FormatSize) {
  1052. RCADEBUGP(RCA_ERROR, ("RCAIntersect: "
  1053. "Output buffer too small, returning STATUS_BUFFER_TOO_SMALL\n"));
  1054. return STATUS_BUFFER_TOO_SMALL;
  1055. }
  1056. Irp->IoStatus.Information = DataRange->FormatSize;
  1057. RtlCopyMemory(Data, DataRange, DataRange->FormatSize);
  1058. }
  1059. RCADEBUGP(RCA_INFO, ("RCAIntersect: Exit - "
  1060. "Returning Status == 0x%x\n", Status));
  1061. return Status;
  1062. }
  1063. VOID
  1064. LinkPinInstanceToVcContext(
  1065. IN PVOID VcContext,
  1066. IN PPIN_INSTANCE_BRIDGE pPinInstance
  1067. )
  1068. /*++
  1069. Routine Description:
  1070. Sets the pointers to link a pin instance to its VC context (placed in
  1071. separate function to allow PinDispatchCreate() to remain pageable, since
  1072. this operation requires a spin lock).
  1073. Arguments:
  1074. VcContext - Vc context we obtained when we referenced the VC
  1075. pPinInstance - Pointer to the PIN_INSTANCE_BRIDGE structure
  1076. Return value:
  1077. -none-
  1078. --*/
  1079. {
  1080. RCA_ACQUIRE_BRIDGE_PIN_LOCK(pPinInstance);
  1081. pPinInstance->VcContext = VcContext;
  1082. RCA_RELEASE_BRIDGE_PIN_LOCK(pPinInstance);
  1083. }
  1084. VOID
  1085. LinkPinInstanceToFilterInstance(
  1086. IN PFILTER_INSTANCE pFilterInstance,
  1087. IN PPIN_INSTANCE_BRIDGE pPinInstance
  1088. )
  1089. /*++
  1090. Routine Description:
  1091. Sets the pointers to link a pin instance to its filter instance (placed in
  1092. separate function to allow PinDispatchCreate() to remain pageable, since
  1093. this operation requires a spin lock).
  1094. Arguments:
  1095. VcContext - Vc context we obtained when we referenced the VC
  1096. pPinInstance - Pointer to the PIN_INSTANCE_BRIDGE structure
  1097. Return value:
  1098. -none-
  1099. --*/
  1100. {
  1101. RCA_ACQUIRE_BRIDGE_PIN_LOCK(pPinInstance);
  1102. pPinInstance->FilterInstance = pFilterInstance; // FIXME: This really needs to be protected by some filter-specific lock
  1103. RCA_RELEASE_BRIDGE_PIN_LOCK(pPinInstance);
  1104. }
  1105. NTSTATUS
  1106. PinDispatchCreate(
  1107. IN PDEVICE_OBJECT DeviceObject,
  1108. IN PIRP Irp
  1109. )
  1110. /*++
  1111. Routine Description:
  1112. Dispatches the creation of a Pin instance. Allocates the object header and initializes
  1113. the data for this Pin instance.
  1114. Arguments:
  1115. DeviceObject -
  1116. Device object on which the creation is occuring.
  1117. Irp -
  1118. Creation Irp.
  1119. Return Values:
  1120. Returns STATUS_SUCCESS on success, or an error.
  1121. --*/
  1122. {
  1123. PIO_STACK_LOCATION IrpStack;
  1124. PKSPIN_CONNECT Connect;
  1125. NTSTATUS Status = 0;
  1126. PKSDATAFORMAT DataFormat;
  1127. PFILTER_INSTANCE FilterInstance;
  1128. ULONG OppositePin;
  1129. RCADEBUGP(RCA_INFO, ("PinDispatchCreate: Enter\n"));
  1130. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  1131. //
  1132. // Determine if this request is being sent to a valid Pin factory with valid
  1133. // connection parameters.
  1134. //
  1135. //
  1136. // get hold of our filter instance in the RELATED context (context will be the new PIN instance)
  1137. //
  1138. FilterInstance = (PFILTER_INSTANCE)IrpStack->FileObject->RelatedFileObject->FsContext;
  1139. RCADEBUGP(RCA_LOUD, ("PinDispatchCreate: "
  1140. "FilterInstance == 0x%x\n", FilterInstance));
  1141. Status = KsValidateConnectRequest(Irp,
  1142. SIZEOF_ARRAY(PinDescriptors),
  1143. (FilterInstance->FilterType == FilterTypeRender ? RenderPinDescriptors : CapturePinDescriptors),
  1144. &Connect);
  1145. if (STATUS_SUCCESS != Status)
  1146. {
  1147. Irp->IoStatus.Status = Status;
  1148. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1149. RCADEBUGP(RCA_ERROR, ("PinDispatchCreate: "
  1150. "KsValidateConnectRequest failure. "
  1151. "Setting Irp->IoStatus.Status and returing Status == 0x%x\n", Status));
  1152. return Status;
  1153. }
  1154. RCADEBUGP(RCA_VERY_LOUD, ("PinDispatchCreate: FilterType == %lu\n", (ULONG)FilterInstance->FilterType));
  1155. RCADEBUGP(RCA_VERY_LOUD, ("PinDispatchCreate: Connect->PinId == %lu\n", (ULONG)Connect->PinId));
  1156. RCADEBUGP(RCA_VERY_LOUD, ("PinDispatchCreate: &Connect == %x\n", &Connect));
  1157. OppositePin = Connect->PinId ^ 0x00000001;
  1158. DataFormat = (PKSDATAFORMAT)(Connect + 1);
  1159. RCADEBUGP(RCA_LOUD, ("PinDispatchCreate: DataFormat->FormatSize == 0x%08x\n"
  1160. "PinDispatchCreate: DataFormat->Flags == 0x%08x\n"
  1161. "PinDispatchCreate: DataFormat->SampleSize == 0x%08x\n"
  1162. "PinDispatchCreate: DataFormat->Reserved == 0x%08x\n",
  1163. DataFormat->FormatSize,
  1164. DataFormat->Flags,
  1165. DataFormat->SampleSize,
  1166. DataFormat->Reserved));
  1167. RCADEBUGP(RCA_LOUD, ("PinDispatchCreate: DataFormat->MajorFormat == "));
  1168. RCADumpGUID(RCA_LOUD, &DataFormat->MajorFormat);
  1169. RCADEBUGP(RCA_LOUD, ("\n"
  1170. "PinDispatchCreate: DataFormat->SubFormat == "));
  1171. RCADumpGUID(RCA_LOUD, &DataFormat->SubFormat);
  1172. RCADEBUGP(RCA_LOUD, ("\n"
  1173. "PinDispatchCreate: DataFormat->Specifier == "));
  1174. RCADumpGUID(RCA_LOUD, &DataFormat->Specifier);
  1175. RCADEBUGP(RCA_LOUD, ("\n"));
  1176. // Exclude other Pin creation at this point.
  1177. KeWaitForMutexObject(&FilterInstance->ControlMutex,
  1178. Executive,
  1179. KernelMode,
  1180. FALSE,
  1181. NULL);
  1182. RCADEBUGP(RCA_LOUD, ("PinDispatchCreate: Acquired filter instance control mutex\n"));
  1183. do {
  1184. //
  1185. // Make sure this Pin ID isn't already connected
  1186. //
  1187. if (FilterInstance->PinFileObjects[Connect->PinId]) {
  1188. RCADEBUGP(RCA_ERROR, ("PinDispatchCreate: "
  1189. "Pin ID %lu is already connected, "
  1190. "setting Status = STATUS_NOT_FOUND\n", Status));
  1191. Status = STATUS_NOT_FOUND;
  1192. break;
  1193. }
  1194. if (Connect->PinId == ID_BRIDGE_PIN) {
  1195. // We're creating a 'bridge' pin to the network. TAPI has set up
  1196. // a connection and returned the NDIS VC identifier, which
  1197. // must be in the connect structure.
  1198. //
  1199. PWSTR pwstrNdisVcString = 0;
  1200. PPIN_INSTANCE_BRIDGE PinInstance;
  1201. PVOID VcContext;
  1202. NDIS_STRING UniString;
  1203. ULONG_PTR ulHexVcId;
  1204. NDIS_REQUEST Request;
  1205. RCADEBUGP(RCA_LOUD, ("PinDispatchCreate: Creating a bridge pin\n"));
  1206. RCADEBUGP(RCA_VERY_LOUD, ("PinDispatchCreate: Connect == 0x%x\n", Connect));
  1207. //
  1208. // Create the instance information.
  1209. //
  1210. RCAAllocMem( PinInstance, PIN_INSTANCE_BRIDGE, sizeof(PIN_INSTANCE_BRIDGE));
  1211. if (!PinInstance) {
  1212. RCADEBUGP(RCA_ERROR, ("PinDispatchCreate: "
  1213. "Could not allocate memory for pin instance, "
  1214. "Setting Status = STATUS_INSUFFICIENT_RESOURCES\n"));
  1215. Status = STATUS_INSUFFICIENT_RESOURCES;
  1216. break;
  1217. }
  1218. RCAMemSet(PinInstance, 0, sizeof(PIN_INSTANCE_BRIDGE));
  1219. KeInitializeSpinLock(&PinInstance->SpinLock);
  1220. //
  1221. // Initialize the block structure if we are on a capture filter.
  1222. //
  1223. if (FilterInstance->FilterType == FilterTypeCapture) {
  1224. RCAInitBlockStruc(&PinInstance->Block);
  1225. }
  1226. //
  1227. // This object uses KS to perform access through the PinFileIoDispatchTable. There
  1228. // are no create items attached to this object because it does not support a
  1229. // clock or allocator.
  1230. //
  1231. Status = KsAllocateObjectHeader(&PinInstance->InstanceHdr.Header,
  1232. 0,
  1233. NULL,
  1234. Irp,
  1235. &PinFileIoDispatchTable);
  1236. if (!NT_SUCCESS(Status)) {
  1237. RCADEBUGP(RCA_ERROR, ("PinDispatchCreate: "
  1238. "KsAllocateObjectHeader failed with Status == 0x%x, "
  1239. "Setting Status = STATUS_INVALID_PARAMETER\n", Status));
  1240. Status = STATUS_INVALID_PARAMETER;
  1241. RCAFreeMem(PinInstance);
  1242. break;
  1243. }
  1244. if (FilterInstance->FilterType == FilterTypeCapture) {
  1245. InitializeListHead(&(PinInstance->WorkQueue));
  1246. }
  1247. //
  1248. // Crosslink PIN instance and filter instance
  1249. //
  1250. LinkPinInstanceToFilterInstance(FilterInstance, PinInstance);
  1251. //
  1252. // Obtain VC context for the VC handle we were given.
  1253. //
  1254. pwstrNdisVcString = (PWSTR)(DataFormat + 1);
  1255. NdisInitUnicodeString (&UniString, pwstrNdisVcString);
  1256. if (FilterInstance->FilterType == FilterTypeRender) {
  1257. Status = RCACoNdisGetVcContextForSend(UniString,
  1258. (PVOID) PinInstance,
  1259. &VcContext);
  1260. } else {
  1261. Status = RCACoNdisGetVcContextForReceive(UniString,
  1262. (PVOID) PinInstance,
  1263. &VcContext);
  1264. }
  1265. if (Status != NDIS_STATUS_SUCCESS) {
  1266. Status = STATUS_INVALID_PARAMETER;
  1267. RCAFreeMem(PinInstance);
  1268. break;
  1269. }
  1270. //
  1271. // Crosslink PIN instance and VC
  1272. //
  1273. LinkPinInstanceToVcContext(VcContext, PinInstance);
  1274. //
  1275. // KS expects that the object data is in FsContext.
  1276. //
  1277. IoGetCurrentIrpStackLocation(Irp)->FileObject->FsContext = PinInstance;
  1278. RCADEBUGP(RCA_LOUD, ("PinDispatchCreate: Address of File Object == 0x%x\n",
  1279. IoGetCurrentIrpStackLocation(Irp)->FileObject));
  1280. RCADEBUGP(RCA_LOUD, ("PinDispatchCreate: FsContext == 0x%x\n",
  1281. IoGetCurrentIrpStackLocation(Irp)->FileObject->FsContext));
  1282. FilterInstance->BridgePin = PinInstance;
  1283. Status = STATUS_SUCCESS;
  1284. } else if (Connect->PinId == ID_DEVIO_PIN) {
  1285. RCADEBUGP(RCA_LOUD, ("PinDispatchCreate: Creating a devio pin\n"));
  1286. #if DUMP_CONNECT_FORMAT
  1287. //
  1288. // Print out the data format information.
  1289. //
  1290. if (IsEqualGUIDAligned(&DataFormat->Specifier,
  1291. &KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)) {
  1292. PKSDATAFORMAT_WAVEFORMATEX pWaveFormat;
  1293. pWaveFormat = (PKSDATAFORMAT_WAVEFORMATEX)DataFormat;
  1294. RCADEBUGP(RCA_INFO, ("PinDispatchCreate: wFormatTag == 0x%x\n"
  1295. "PinDispatchCreate: nChannels == 0x%x\n"
  1296. "PinDispatchCreate: nSamplesPerSec == 0x%x\n"
  1297. "PinDispatchCreate: nAvgBytesPerSec == 0x%x\n"
  1298. "PinDispatchCreate: nBlockAlign == 0x%x\n"
  1299. "PinDispatchCreate: wBitsPerSample == 0x%x\n"
  1300. "PinDispatchCreate: cbSize == 0x%x\n",
  1301. pWaveFormat->WaveFormatEx.wFormatTag,
  1302. pWaveFormat->WaveFormatEx.nChannels,
  1303. pWaveFormat->WaveFormatEx.nSamplesPerSec,
  1304. pWaveFormat->WaveFormatEx.nAvgBytesPerSec,
  1305. pWaveFormat->WaveFormatEx.nBlockAlign,
  1306. pWaveFormat->WaveFormatEx.wBitsPerSample,
  1307. pWaveFormat->WaveFormatEx.cbSize));
  1308. } else {
  1309. RCADEBUGP(RCA_ERROR, ("PinDispatchCreate: Data Format was not WAVEFORMATEX, don't know what to do\n"));
  1310. RCADEBUGP(RCA_ERROR, ("PinDispatchCreate: The specifier was: "));
  1311. RCADumpGUID(RCA_ERROR, &DataFormat->Specifier);
  1312. RCADEBUGP(RCA_ERROR, ("\n"));
  1313. }
  1314. #endif
  1315. //
  1316. // Check for RENDER or CAPTURE
  1317. //
  1318. if (FilterInstance->FilterType == FilterTypeRender) {
  1319. RCADEBUGP(RCA_VERY_LOUD, ("PinDispatchCreate: RENDER: Connect = 0x%x\n",
  1320. Connect));
  1321. Status = InitializeDevIoPin(Irp, 0, FilterInstance, DataFormat);
  1322. } else {
  1323. //
  1324. // Capture device; streans data from the net; IRP source.
  1325. // Get the connectong filter's file handle so we can stream to it.
  1326. //
  1327. if (Connect->PinToHandle) {
  1328. RCADEBUGP(RCA_LOUD, ("PinDispatchCreate: Creating a Source Pin\n"));
  1329. Status = ObReferenceObjectByHandle(Connect->PinToHandle, // other filter's PIN
  1330. FILE_WRITE_DATA,
  1331. NULL,
  1332. ExGetPreviousMode(),
  1333. &FilterInstance->NextFileObject, // &FilterInstance->NextFileObjects[Connect->PinId], // this is other file object
  1334. NULL);
  1335. if (!NT_SUCCESS(Status)) {
  1336. RCADEBUGP(RCA_ERROR, ("PinDispatchCreate: "
  1337. "ObReferenceObjectByHandle failed with "
  1338. "Status == 0x%x\n", Status));
  1339. //
  1340. // Get out of while loop (releases mutex and returns status)
  1341. //
  1342. break;
  1343. }
  1344. } else {
  1345. RCADEBUGP(RCA_LOUD, ("PinDispatchCreate: Creating a Sink Pin\n"));
  1346. FilterInstance->NextFileObject = NULL;
  1347. }
  1348. Status = InitializeDevIoPin(Irp, 1, FilterInstance, DataFormat);
  1349. //
  1350. // Add the pin's target to the list of targets for
  1351. // recalculating IRP stack depth.
  1352. //
  1353. if (FilterInstance->NextFileObject != NULL) {
  1354. if (NT_SUCCESS(Status)) {
  1355. KsSetTargetDeviceObject(FilterInstance->Header,
  1356. IoGetRelatedDeviceObject(FilterInstance->NextFileObject));
  1357. } else {
  1358. ObDereferenceObject(FilterInstance->NextFileObject);
  1359. FilterInstance->NextFileObject = NULL;
  1360. }
  1361. }
  1362. }
  1363. RtlCopyMemory(&FilterInstance->DataFormat, DataFormat, sizeof(KSDATAFORMAT));
  1364. } else {
  1365. RCADEBUGP(RCA_ERROR, ("PinDispatchCreate: Not creating a bridge or a devio pin, "
  1366. "Setting Status == STATUS_NOT_FOUND\n"));
  1367. Status = STATUS_NOT_FOUND;
  1368. }
  1369. if (NT_SUCCESS(Status)) {
  1370. PPIN_INSTANCE_HEADER PinInstance;
  1371. //
  1372. // Store the common Pin information and increment the reference
  1373. // count on the parent Filter.
  1374. // The newly created PIN can subsequently be retreived from the filter instance
  1375. // header by specifying its type to PinFileObjects[Connect->PinId]..
  1376. //
  1377. PinInstance = (PPIN_INSTANCE_HEADER)IrpStack->FileObject->FsContext;
  1378. PinInstance->PinId = Connect->PinId;
  1379. ObReferenceObject(IrpStack->FileObject->RelatedFileObject); // refs the FILTER object
  1380. //
  1381. // Set up Pin instance for retrieval later
  1382. //
  1383. FilterInstance->PinFileObjects[Connect->PinId] = IrpStack->FileObject;
  1384. RCADEBUGP(RCA_LOUD, ("PinDispatchCreate: "
  1385. "Pin Created Successfully, Status == 0x%x\n", Status));
  1386. } else {
  1387. RCADEBUGP(RCA_ERROR, ("PinDispatchCreate: Failure, Status == 0x%x\n", Status));
  1388. }
  1389. } while(FALSE);
  1390. KeReleaseMutex(&FilterInstance->ControlMutex, FALSE);
  1391. RCADEBUGP(RCA_LOUD, ("PinDispatchCreate: Released filter instance control mutex\n"));
  1392. Irp->IoStatus.Status = Status;
  1393. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1394. RCADEBUGP(RCA_INFO, ("PinDispatchCreate: Exit - "
  1395. "Setting Irp->IoStatus.Status and returing Status == 0x%x\n", Status));
  1396. return Status;
  1397. }
  1398. NTSTATUS
  1399. InitializeDevIoPin(
  1400. IN PIRP Irp,
  1401. IN BOOLEAN Read,
  1402. IN PFILTER_INSTANCE FilterInstance,
  1403. IN PKSDATAFORMAT DataFormat
  1404. )
  1405. /*++
  1406. Routine Description:
  1407. Allocates the Dev I/O Pin specific structure and initializes it.
  1408. Arguments:
  1409. Irp - Creation Irp.
  1410. Read - Read/Write boolean. Read = 1.
  1411. DataFormat -
  1412. The proposed data format.
  1413. Return Values:
  1414. Returns STATUS_SUCCESS if everything could be allocated and opened, else an error.
  1415. --*/
  1416. {
  1417. PFILE_OBJECT FileObject;
  1418. PPIN_INSTANCE_BRIDGE BridgePinInstance = NULL;
  1419. PPIN_INSTANCE_DEVIO PinInstance = NULL;
  1420. PIO_STACK_LOCATION IrpStack;
  1421. NTSTATUS Status;
  1422. RCADEBUGP(RCA_INFO, ("InitializeDevIoPin: Enter - DataFormat == 0x%x\n", DataFormat));
  1423. //
  1424. // The rest of the data format has already been verified by KsValidateConnectRequest,
  1425. // however the FormatSize should be at least as big as the base format size.
  1426. //
  1427. if (DataFormat->FormatSize < sizeof(KSDATAFORMAT)) {
  1428. RCADEBUGP(RCA_ERROR, ("InitializeDevIoPin: "
  1429. "Data format size (0x%x) is less than size of KSDATAFORMAT\n",
  1430. DataFormat->FormatSize));
  1431. return STATUS_CONNECTION_REFUSED;
  1432. }
  1433. //
  1434. // check we have a bridge PIN on this filter instance supporting this data format.
  1435. // The function locks the parent filter instance and looks for a conected FILEIO Pin.
  1436. //
  1437. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  1438. if (!(BridgePinInstance = FilterInstance->BridgePin)) {
  1439. RCADEBUGP(RCA_ERROR, ("InitializeDevIoPin: "
  1440. "Bridge pin is not yet connected, "
  1441. "returning STATUS_CONNECTION_REFUSED\n"));
  1442. return STATUS_CONNECTION_REFUSED;
  1443. }
  1444. // Create the instance information. This contains the Pin factory identifier, and
  1445. // event queue information.
  1446. //
  1447. RCAAllocMem( PinInstance, PIN_INSTANCE_DEVIO, sizeof(PIN_INSTANCE_DEVIO));
  1448. if (PinInstance) {
  1449. RCAMemSet(PinInstance, 0, sizeof(PIN_INSTANCE_DEVIO));
  1450. //
  1451. // This object uses KS to perform access through the PinDevIoDispatchTable. There
  1452. // are no create items attached to this object because it does not support a
  1453. // clock or allocator.
  1454. //
  1455. Status = KsAllocateObjectHeader(&PinInstance->InstanceHdr.Header,
  1456. 0,
  1457. NULL,
  1458. Irp,
  1459. &PinDevIoDispatchTable);
  1460. if (NT_SUCCESS(Status)) {
  1461. InitializeListHead(&PinInstance->EventQueue);
  1462. ExInitializeFastMutex(&PinInstance->EventQueueLock);
  1463. if (Read) {
  1464. #if AUDIO_SINK_FLAG
  1465. if (FilterInstance->NextFileObject == NULL) {
  1466. InitializeListHead(&PinInstance->ActiveQueue);
  1467. KeInitializeSpinLock(&PinInstance->QueueLock);
  1468. PinInstance->ConnectedAsSink = TRUE;
  1469. RCADEBUGP(RCA_LOUD, ("InitializeDevIoPin: "
  1470. "Set ConnectedAsSink == TRUE\n"));
  1471. } else {
  1472. PinInstance->ConnectedAsSink = FALSE;
  1473. RCADEBUGP(RCA_LOUD, ("InitializeDevIoPin: "
  1474. "Set ConnectedAsSink == FALSE\n"));
  1475. }
  1476. #endif
  1477. } else { // end of CAPTURE pin (from the net)
  1478. // This might be a bit misleading. On the render filter, the devio pin is
  1479. // always a sink. But the ConnectedAsSink flag applies only to the capture side.
  1480. PinInstance->ConnectedAsSink = FALSE;
  1481. RCADEBUGP(RCA_LOUD, ("InitializeDevIoPin: "
  1482. "Set ConnectedAsSink == FALSE\n"));
  1483. }
  1484. if (!NT_SUCCESS(Status)) {
  1485. KsFreeObjectHeader (PinInstance->InstanceHdr.Header);
  1486. RCAFreeMem(PinInstance);
  1487. return Status;
  1488. }
  1489. //
  1490. // Point DEVIO Pin at VC
  1491. //
  1492. RCA_ACQUIRE_BRIDGE_PIN_LOCK(BridgePinInstance);
  1493. PinInstance->VcContext = BridgePinInstance->VcContext;
  1494. RCA_RELEASE_BRIDGE_PIN_LOCK(BridgePinInstance);
  1495. FilterInstance->DevIoPin = PinInstance;
  1496. PinInstance->FilterInstance = FilterInstance;
  1497. //
  1498. // KS expects that the object data is in FsContext.
  1499. //
  1500. IoGetCurrentIrpStackLocation(Irp)->FileObject->FsContext = PinInstance;
  1501. return STATUS_SUCCESS;
  1502. } else {
  1503. RCADEBUGP(RCA_ERROR, ("InitializeDevIoPin: KsAllocateObjectHeader failed with "
  1504. "Status == 0x%x\n", Status));
  1505. }
  1506. RCAFreeMem(PinInstance);
  1507. } else {
  1508. //
  1509. // Couldn't allocate PIN
  1510. //
  1511. RCADEBUGP(RCA_ERROR, ("InitializeDevIoPin: "
  1512. "Could not allocate memory for pin, "
  1513. "Setting Status = STATUS_INSUFFICIENT_RESOURCES\n"));
  1514. Status = STATUS_INSUFFICIENT_RESOURCES;
  1515. }
  1516. RCADEBUGP(RCA_INFO, ("InitializeDevIoPin: Exit - "
  1517. "Returning Status == 0x%x\n", Status));
  1518. return Status;
  1519. }
  1520. NTSTATUS
  1521. PinDispatchIoControl(
  1522. IN PDEVICE_OBJECT DeviceObject,
  1523. IN PIRP Irp
  1524. )
  1525. /*++
  1526. Routine Description:
  1527. Dispatches property, event, and streaming requests on the Dev I/O Pin instance.
  1528. Arguments:
  1529. DeviceObject -
  1530. Device object on which the device control is occuring.
  1531. Irp -
  1532. Device control Irp.
  1533. Return Values:
  1534. Returns STATUS_SUCCESS if the property was successfully manipulated, else an error.
  1535. --*/
  1536. {
  1537. PIO_STACK_LOCATION IrpStack;
  1538. NTSTATUS Status;
  1539. CCHAR PriorityBoost;
  1540. PPIN_INSTANCE_HEADER PinInstanceHeader;
  1541. UINT PendTheIrp = 0;
  1542. RCADEBUGP(RCA_INFO, ("PinDispatchIoControl: Enter\n"));
  1543. PriorityBoost = IO_NO_INCREMENT;
  1544. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  1545. Irp->IoStatus.Status = STATUS_PENDING;
  1546. IoMarkIrpPending (Irp);
  1547. RCADEBUGP(RCA_VERY_LOUD, ("PinDispatchIoControl: Marked IRP Pending\n"));
  1548. PinInstanceHeader = (PPIN_INSTANCE_HEADER)IrpStack->FileObject->FsContext;
  1549. if (PinInstanceHeader->PinId == ID_DEVIO_PIN) {
  1550. PPIN_INSTANCE_DEVIO PinInstanceDevIo;
  1551. RCADEBUGP(RCA_LOUD, ("PinDispatchIoControl: DEVIO pin\n"));
  1552. PinInstanceDevIo = (PPIN_INSTANCE_DEVIO)IrpStack->FileObject->FsContext;
  1553. switch(IrpStack->Parameters.DeviceIoControl.IoControlCode) {
  1554. case IOCTL_KS_PROPERTY:
  1555. RCADEBUGP(RCA_LOUD, ("PinDispatchIoControl: IOCTL_KS_PROPERTY\n"));
  1556. Status = KsPropertyHandler(Irp,
  1557. SIZEOF_ARRAY(DevIoPropertySets),
  1558. DevIoPropertySets);
  1559. break;
  1560. case IOCTL_KS_ENABLE_EVENT:
  1561. RCADEBUGP(RCA_LOUD, ("PinDispatchIoControl: IOCTL_KS_ENABLE_EVENT\n"));
  1562. Status = KsEnableEvent(Irp,
  1563. SIZEOF_ARRAY(EventSets),
  1564. EventSets,
  1565. &PinInstanceDevIo->EventQueue,
  1566. KSEVENTS_FMUTEXUNSAFE,
  1567. &PinInstanceDevIo->EventQueueLock);
  1568. break;
  1569. case IOCTL_KS_DISABLE_EVENT:
  1570. RCADEBUGP(RCA_LOUD, ("PinDispatchIoControl: IOCTL_KS_DISABLE_EVENT\n"));
  1571. Status = KsDisableEvent(Irp,
  1572. &PinInstanceDevIo->EventQueue,
  1573. KSEVENTS_FMUTEXUNSAFE,
  1574. &PinInstanceDevIo->EventQueueLock);
  1575. break;
  1576. case IOCTL_KS_READ_STREAM:
  1577. RCADEBUGP(RCA_LOUD, ("PinDispatchIoControl: IOCTL_KS_READ_STREAM\n"));
  1578. if (NT_SUCCESS(Status = ReadStream(Irp, PinInstanceDevIo)))
  1579. {
  1580. PriorityBoost = IO_DISK_INCREMENT;
  1581. } else {
  1582. RCADEBUGP(RCA_ERROR, ("PinDispatchIoControl: "
  1583. "ReadStream failed, Status == 0x%x\n", Status));
  1584. }
  1585. break;
  1586. case IOCTL_KS_WRITE_STREAM:
  1587. RCADEBUGP(RCA_LOUD, ("PinDispatchIoControl: IOCTL_KS_WRITE_STREAM\n"));
  1588. Status = WriteStream(Irp, PinInstanceDevIo );
  1589. break;
  1590. default:
  1591. RCADEBUGP(RCA_WARNING, ("PinDispatchIoControl: "
  1592. "Unknown IOCTL: 0x%x\n",
  1593. IrpStack->Parameters.DeviceIoControl.IoControlCode));
  1594. Status = KsDefaultDeviceIoCompletion( DeviceObject, Irp );
  1595. RCADEBUGP(RCA_INFO, ("PinDispatchIoControl: "
  1596. "Returning result of KsDefaultDeviceIoCompletion: 0x%x\n", Status));
  1597. return Status;
  1598. }
  1599. } else {
  1600. PPIN_INSTANCE_BRIDGE PinInstanceBridge;
  1601. RCADEBUGP(RCA_LOUD, ("PinDispatchIoControl: BRIDGE pin\n"));
  1602. PinInstanceBridge = (PPIN_INSTANCE_BRIDGE)IrpStack->FileObject->FsContext;
  1603. switch(IrpStack->Parameters.DeviceIoControl.IoControlCode) {
  1604. case IOCTL_KS_PROPERTY:
  1605. RCADEBUGP(RCA_LOUD, ("PinDispatchIoControl: IOCTL_KS_PROPERTY\n"));
  1606. RCADumpKsPropertyInfo(RCA_LOUD, Irp);
  1607. Status = KsPropertyHandler(Irp,
  1608. SIZEOF_ARRAY(BridgePropertySets),
  1609. BridgePropertySets);
  1610. RCADEBUGP(RCA_INFO, ("PinDispatchIoControl: "
  1611. "Returning result of KsPropertyHandler: 0x%x\n",
  1612. Status));
  1613. break;
  1614. case IOCTL_KS_ENABLE_EVENT:
  1615. RCADEBUGP(RCA_LOUD,("PinDispatchIoControl: IOCTL_KS_ENABLE_EVENT\n"));
  1616. Status = KsEnableEvent(Irp,
  1617. SIZEOF_ARRAY(EventSets),
  1618. EventSets,
  1619. &PinInstanceBridge->EventQueue,
  1620. KSEVENTS_FMUTEXUNSAFE,
  1621. &PinInstanceBridge->EventQueueLock);
  1622. break;
  1623. case IOCTL_KS_DISABLE_EVENT:
  1624. RCADEBUGP(RCA_LOUD,("PinDispatchIoControl: IOCTL_KS_DISABLE_EVENT\n"));
  1625. Status = KsDisableEvent(Irp,
  1626. &PinInstanceBridge->EventQueue,
  1627. KSEVENTS_FMUTEXUNSAFE,
  1628. &PinInstanceBridge->EventQueueLock);
  1629. break;
  1630. case IOCTL_KS_READ_STREAM:
  1631. RCADEBUGP(RCA_LOUD, ("PinDispatchIoControl: IOCTL_KS_READ_STREAM\n"));
  1632. Status = KsDefaultDeviceIoCompletion(DeviceObject, Irp);
  1633. RCADEBUGP(RCA_INFO, ("PinDispatchIoControl: "
  1634. "Returning result of KsDefaultDeviceIoCompletion: 0x%x\n",
  1635. Status));
  1636. return Status;
  1637. case IOCTL_KS_WRITE_STREAM:
  1638. RCADEBUGP(RCA_LOUD, ("PinDispatchIoControl: IOCTL_KS_WRITE_STREAM\n"));
  1639. Status = KsDefaultDeviceIoCompletion(DeviceObject, Irp);
  1640. RCADEBUGP(RCA_INFO, ("PinDispatchIoControl: "
  1641. "Returning result of KsDefaultDeviceIoCompletion: 0x%x\n",
  1642. Status));
  1643. return Status;
  1644. default:
  1645. RCADEBUGP(RCA_WARNING, ("PinDispatchIoControl: "
  1646. "Unknown IOCTL: 0x%x\n",
  1647. IrpStack->Parameters.DeviceIoControl.IoControlCode));
  1648. Status = KsDefaultDeviceIoCompletion(DeviceObject, Irp);
  1649. RCADEBUGP(RCA_INFO, ("PinDispatchIoControl: "
  1650. "Returning result of KsDefaultDeviceIoCompletion: 0x%x\n",
  1651. Status));
  1652. return Status;
  1653. }
  1654. }
  1655. if (Status != STATUS_PENDING) {
  1656. Irp->IoStatus.Status = Status;
  1657. IoCompleteRequest( Irp, PriorityBoost );
  1658. RCADEBUGP(RCA_VERY_LOUD, ("PinDispatchIoControl: Completed IRP\n"));
  1659. }
  1660. RCADEBUGP(RCA_INFO, ("PinDispatchIoControl: Exit - "
  1661. "Returning Status == 0x%x\n", Status));
  1662. return Status;
  1663. }
  1664. NTSTATUS
  1665. PinDispatchClose(
  1666. IN PDEVICE_OBJECT DeviceObject,
  1667. IN PIRP Irp
  1668. )
  1669. /*++
  1670. Routine Description:
  1671. Closes a previously opened Pin instance. This can occur at any time in any order.
  1672. If this is a FILEIO (BRIDGE) Pin, just clear up the Pin. THe associated VC stays around
  1673. until it gets cleared up via NDIS.
  1674. Arguments:
  1675. DeviceObject -
  1676. Device object on which the close is occuring.
  1677. Irp -
  1678. Close Irp.
  1679. Return Values:
  1680. Returns STATUS_SUCCESS.
  1681. --*/
  1682. {
  1683. PIO_STACK_LOCATION IrpStack;
  1684. PFILTER_INSTANCE FilterInstance;
  1685. PPIN_INSTANCE_HEADER PinInstance;
  1686. NDIS_STATUS CloseCallStatus = NDIS_STATUS_PENDING;
  1687. RCADEBUGP(RCA_INFO,("PinDispatchIoClose: Enter\n"));
  1688. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  1689. PinInstance = (PPIN_INSTANCE_HEADER)IrpStack->FileObject->FsContext;
  1690. FilterInstance = (PFILTER_INSTANCE)IrpStack->FileObject->RelatedFileObject->FsContext;
  1691. // The closing of the File I/O Pin instance must be synchronized with any access to
  1692. // that object.
  1693. KeWaitForMutexObject(&FilterInstance->ControlMutex,
  1694. Executive,
  1695. KernelMode,
  1696. FALSE,
  1697. NULL);
  1698. RCADEBUGP(RCA_LOUD, ("PinDispatchClose: Acquired filter instance control mutex\n"));
  1699. //
  1700. // These were allocated during the creation of the Pin instance.
  1701. //
  1702. KsFreeObjectHeader(PinInstance->Header);
  1703. FilterInstance->PinFileObjects[PinInstance->PinId] = NULL;
  1704. // If DEVIO, clear up event list.
  1705. if (ID_DEVIO_PIN == PinInstance->PinId) {
  1706. RCADEBUGP(RCA_LOUD, ("PinDispatchClose: DEVIO pin\n"));
  1707. if (FilterInstance->FilterType == FilterTypeCapture) {
  1708. PPIN_INSTANCE_BRIDGE pBridgePinInstance = FilterInstance->BridgePin;
  1709. NDIS_STATUS LocalStatus;
  1710. if (pBridgePinInstance != NULL) {
  1711. RCA_ACQUIRE_BRIDGE_PIN_LOCK(pBridgePinInstance);
  1712. pBridgePinInstance->SignalMe = pBridgePinInstance->bWorkItemQueued;
  1713. RCA_RELEASE_BRIDGE_PIN_LOCK(pBridgePinInstance);
  1714. if (pBridgePinInstance->SignalMe) {
  1715. RCADEBUGP(RCA_LOUD, ("PinDispatchClose: "
  1716. "Waiting for worker threads\n"));
  1717. RCABlock(&pBridgePinInstance->Block, &LocalStatus);
  1718. }
  1719. }
  1720. if (FilterInstance->NextFileObject != NULL) {
  1721. ObDereferenceObject(FilterInstance->NextFileObject);
  1722. FilterInstance->NextFileObject = NULL;
  1723. RCADEBUGP(RCA_LOUD, ("PinDispatchClose: "
  1724. "Set FilterInstance->NextFileObject = NULL\n"));
  1725. }
  1726. }
  1727. if (((PPIN_INSTANCE_DEVIO)PinInstance)->AllocatorObject) {
  1728. ObDereferenceObject(((PPIN_INSTANCE_DEVIO)PinInstance)->AllocatorObject);
  1729. }
  1730. //
  1731. // Clean up the event list of anything still outstanding.
  1732. //
  1733. // KsFreeEventList(// IrpStack->FileObject,
  1734. // &((PPIN_INSTANCE_DEVIO)PinInstance)->EventQueue,
  1735. // KSEVENTS_FMUTEXUNSAFE,
  1736. // &((PPIN_INSTANCE_DEVIO)PinInstance)->EventQueueLock);
  1737. RCAFreeMem((PPIN_INSTANCE_DEVIO)PinInstance);
  1738. FilterInstance->DevIoPin = NULL;
  1739. RCADEBUGP(RCA_LOUD, ("PinDispatchClose: "
  1740. "Set FilterInstance->DevIoPin = NULL\n"));
  1741. } else {
  1742. PPIN_INSTANCE_BRIDGE pBridgePinInstance;
  1743. RCADEBUGP(RCA_WARNING,("PinDispatchIoClose: BRIDGE pin\n"));
  1744. pBridgePinInstance = (PPIN_INSTANCE_BRIDGE)IrpStack->FileObject->FsContext;
  1745. RCA_ACQUIRE_BRIDGE_PIN_LOCK(pBridgePinInstance);
  1746. if (pBridgePinInstance->VcContext) {
  1747. RCA_RELEASE_BRIDGE_PIN_LOCK(pBridgePinInstance);
  1748. RCACoNdisCloseCallOnVc(pBridgePinInstance->VcContext);
  1749. RCA_ACQUIRE_BRIDGE_PIN_LOCK(pBridgePinInstance);
  1750. if (FilterInstance->FilterType == FilterTypeRender) {
  1751. RCACoNdisReleaseSendVcContext(pBridgePinInstance->VcContext);
  1752. } else {
  1753. RCACoNdisReleaseReceiveVcContext(pBridgePinInstance->VcContext);
  1754. }
  1755. pBridgePinInstance->VcContext = NULL;
  1756. if (pBridgePinInstance->FilterInstance->DevIoPin)
  1757. pBridgePinInstance->FilterInstance->DevIoPin->VcContext = NULL;
  1758. RCA_RELEASE_BRIDGE_PIN_LOCK(pBridgePinInstance);
  1759. } else {
  1760. RCA_RELEASE_BRIDGE_PIN_LOCK(pBridgePinInstance);
  1761. }
  1762. if (FilterInstance->FilterType == FilterTypeCapture) {
  1763. NDIS_STATUS LocalStatus;
  1764. RCA_ACQUIRE_BRIDGE_PIN_LOCK(pBridgePinInstance);
  1765. pBridgePinInstance->SignalMe = pBridgePinInstance->bWorkItemQueued;
  1766. RCA_RELEASE_BRIDGE_PIN_LOCK(pBridgePinInstance);
  1767. if (pBridgePinInstance->SignalMe) {
  1768. RCADEBUGP(RCA_LOUD, ("PinDispatchClose: "
  1769. "Waiting for worker threads\n"));
  1770. RCABlock(&pBridgePinInstance->Block, &LocalStatus);
  1771. }
  1772. }
  1773. RCA_ACQUIRE_BRIDGE_PIN_LOCK(pBridgePinInstance);
  1774. if (pBridgePinInstance->pDataFormat) {
  1775. RCAFreeMem(pBridgePinInstance->pDataFormat);
  1776. }
  1777. RCA_RELEASE_BRIDGE_PIN_LOCK(pBridgePinInstance);
  1778. RCAFreeMem((PPIN_INSTANCE_BRIDGE)PinInstance);
  1779. FilterInstance->BridgePin = NULL;
  1780. RCADEBUGP(RCA_LOUD, ("PinDispatchClose: "
  1781. "Set FilterInstance->BridgePin = NULL\n"));
  1782. }
  1783. KeReleaseMutex(&FilterInstance->ControlMutex, FALSE );
  1784. RCADEBUGP(RCA_LOUD, ("PinDispatchClose: Released filter instance control mutex\n"));
  1785. //
  1786. // All Pins are created with a root file object, which is the Filter, and was
  1787. // previously referenced during creation.
  1788. //
  1789. RCADEBUGP(RCA_WARNING,("PinDispatchClose: ObDereferenceObject\n"));
  1790. ObDereferenceObject(IrpStack->FileObject->RelatedFileObject);
  1791. Irp->IoStatus.Status = STATUS_SUCCESS;
  1792. Irp->IoStatus.Information = 0;
  1793. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1794. RCADEBUGP(RCA_LOUD, ("PinDispatchClose: Completed IRP\n"));
  1795. RCADEBUGP(RCA_INFO, ("PinDispatchClose: Exit - Returning STATUS_SUCCESS"));
  1796. return STATUS_SUCCESS;
  1797. }
  1798. NTSTATUS
  1799. FilterDispatchCreate(
  1800. IN PDEVICE_OBJECT DeviceObject,
  1801. IN PIRP Irp
  1802. )
  1803. /*++
  1804. Routine Description:
  1805. Dispatches the creation of a Filter instance. Allocates the object header and initializes
  1806. the data for this Filter instance.
  1807. Arguments:
  1808. DeviceObject -
  1809. Device object on which the creation is occuring.
  1810. Irp -
  1811. Creation Irp.
  1812. Return Values:
  1813. Returns STATUS_SUCCESS on success, STATUS_INSUFFICIENT_RESOURCES or some related error
  1814. on failure.
  1815. --*/
  1816. {
  1817. PIO_STACK_LOCATION irpSp;
  1818. PKSOBJECT_CREATE_ITEM CreateItem;
  1819. NTSTATUS Status;
  1820. RCADEBUGP(RCA_INFO, ("FilterDispatchCreate: Enter\n"));
  1821. //
  1822. // Notify the software bus that this device is in use.
  1823. //
  1824. Status = KsReferenceSoftwareBusObject(((PDEVICE_INSTANCE)DeviceObject->DeviceExtension)->Header);
  1825. if (!NT_SUCCESS(Status)) {
  1826. RCADEBUGP(RCA_ERROR, ("FilterDispatchCreate: "
  1827. "KsReferenceSoftwareBusObject failed, Status == 0x%x\n", Status));
  1828. } else {
  1829. PFILTER_INSTANCE FilterInstance;
  1830. irpSp = IoGetCurrentIrpStackLocation( Irp );
  1831. CreateItem = KSCREATE_ITEM_IRP_STORAGE( Irp );
  1832. //
  1833. // Create the instance information. This contains the list of current Pins, and
  1834. // the mutex used when modifying pins.
  1835. //
  1836. RCAAllocMem( FilterInstance, FILTER_INSTANCE, sizeof(FILTER_INSTANCE));
  1837. if (FilterInstance)
  1838. {
  1839. RCAMemSet((PUCHAR)FilterInstance, 0, sizeof(FILTER_INSTANCE));
  1840. //
  1841. // Render or Capture?
  1842. //
  1843. FilterInstance->FilterType = (FILTER_TYPE) CreateItem->Context;
  1844. RCADEBUGP(RCA_LOUD, ("FilterDispatchCreate: "
  1845. "Creating filter of type 0x%x\n", FilterInstance->FilterType));
  1846. //
  1847. // This object uses KS to perform access through the FilterCreateItems and
  1848. // FilterDispatchTable.
  1849. //
  1850. Status = KsAllocateObjectHeader(&FilterInstance->Header,
  1851. SIZEOF_ARRAY(FilterObjectCreateDispatch),
  1852. (PKSOBJECT_CREATE_ITEM)FilterObjectCreateDispatch,
  1853. Irp,
  1854. (PKSDISPATCH_TABLE)&FilterDispatchTable);
  1855. if (!NT_SUCCESS(Status)) {
  1856. RCADEBUGP(RCA_ERROR, ("FilterDispatchCreate: "
  1857. "KsAllocateObjectHeader failed, Status == 0x%x\n",
  1858. Status));
  1859. } else {
  1860. ULONG PinCount;
  1861. RtlCopyMemory(FilterInstance->PinInstances,
  1862. PinInstances,
  1863. sizeof(PinInstances));
  1864. KeInitializeMutex( &FilterInstance->ControlMutex, 1 );
  1865. //
  1866. // Initialize the list of Pins on this Filter to an unconnected state.
  1867. //
  1868. for (PinCount = SIZEOF_ARRAY(FilterInstance->PinFileObjects);
  1869. PinCount;
  1870. NOTHING)
  1871. {
  1872. FilterInstance->PinFileObjects[--PinCount] = NULL;
  1873. }
  1874. //
  1875. // No audio data format set up yet for this filter instance. Wildcard it.
  1876. //
  1877. //RtlCopyMemory (&FilterInstance->DataFormat, &PinFileIoRange, sizeof (KSDATAFORMAT));
  1878. //
  1879. // KS expects that the filter object data is in FsContext.
  1880. //
  1881. IoGetCurrentIrpStackLocation(Irp)->FileObject->FsContext = FilterInstance;
  1882. }
  1883. } else {
  1884. RCADEBUGP (RCA_ERROR, ("FilterDispatchCreate: "
  1885. "Could not allocate memory for filter instance, "
  1886. "Setting Status == STATUS_INSUFFICIENT_RESOURCES\n"));
  1887. KsDereferenceSoftwareBusObject(
  1888. ((PDEVICE_INSTANCE)DeviceObject->DeviceExtension)->Header );
  1889. Status = STATUS_INSUFFICIENT_RESOURCES;
  1890. }
  1891. }
  1892. Irp->IoStatus.Status = Status;
  1893. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1894. RCADEBUGP(RCA_LOUD, ("FilterDispatchCreate: Completed IRP\n"));
  1895. RCADEBUGP(RCA_INFO, ("FilterDispatchCreate: Exit - "
  1896. "Setting Irp->IoStatus.Status and Returning 0x%x\n", Status));
  1897. return Status;
  1898. }
  1899. NTSTATUS
  1900. FilterPinIntersection(
  1901. IN PIRP Irp,
  1902. IN PKSP_PIN Pin,
  1903. OUT PVOID Data
  1904. )
  1905. /*++
  1906. Routine Description:
  1907. Handles the KSPROPERTY_PIN_DATAINTERSECTION property in the Pin property set.
  1908. Returns the first acceptable data format given a list of data ranges for a specified
  1909. Pin factory.
  1910. Arguments:
  1911. Irp -
  1912. Device control Irp.
  1913. Pin -
  1914. Specific property request followed by Pin factory identifier, followed by a
  1915. KSMULTIPLE_ITEM structure. This is followed by zero or more data range structures.
  1916. Data -
  1917. The place in which to return the data format selected as the first intersection
  1918. between the list of data ranges passed, and the acceptable formats.
  1919. Return Values:
  1920. returns STATUS_SUCCESS, else STATUS_INVALID_PARAMETER or STATUS_BUFFER_TOO_SMALL.
  1921. --*/
  1922. {
  1923. PFILTER_INSTANCE FilterInstance;
  1924. PIO_STACK_LOCATION IrpStack;
  1925. NTSTATUS Status = 0;
  1926. RCADEBUGP(RCA_INFO, ("FilterPinIntersection: Enter\n"));
  1927. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  1928. FilterInstance = (PFILTER_INSTANCE)IrpStack->FileObject->FsContext;
  1929. RCADEBUGP(RCA_LOUD, ("FilterPinIntersection: FilterInstance == 0x%x\n", FilterInstance));
  1930. Status = KsPinDataIntersection(Irp,
  1931. Pin,
  1932. Data,
  1933. SIZEOF_ARRAY(PinDescriptors),
  1934. (FilterInstance->FilterType == FilterTypeRender ?
  1935. RenderPinDescriptors : CapturePinDescriptors),
  1936. RCAIntersect);
  1937. RCADEBUGP(RCA_INFO, ("FilterPinIntersection: Exit - "
  1938. "Returning Status == 0x%x\n", Status));
  1939. return Status;
  1940. }
  1941. NTSTATUS
  1942. PinDeviceState(
  1943. IN PIRP Irp,
  1944. IN PKSPROPERTY Property,
  1945. IN OUT PKSSTATE DeviceState
  1946. )
  1947. /*++
  1948. Routine Description:
  1949. Arguments:
  1950. IN PIRP Irp -
  1951. pointer to I/O request packet
  1952. IN PKSPROPERTY Property -
  1953. pointer to the property structure
  1954. IN OUT PKSSTATE DeviceState -
  1955. pointer to a KSSTATE, filled on GET otherwise contains
  1956. the new state to set the pin
  1957. Return:
  1958. STATUS_SUCCESS or an appropriate error code
  1959. --*/
  1960. {
  1961. NTSTATUS Status = STATUS_SUCCESS;
  1962. PFILE_OBJECT FileObject;
  1963. PIO_STACK_LOCATION irpSp;
  1964. PFILTER_INSTANCE FilterInstance;
  1965. PPIN_INSTANCE_DEVIO PinInstance;
  1966. PPIN_INSTANCE_BRIDGE pBridgePinInstance;
  1967. RCADEBUGP(RCA_INFO, ("PinDeviceState: Enter\n"));
  1968. irpSp = IoGetCurrentIrpStackLocation( Irp );
  1969. FilterInstance = (PFILTER_INSTANCE) irpSp->FileObject->RelatedFileObject->FsContext;
  1970. PinInstance = (PPIN_INSTANCE_DEVIO) irpSp->FileObject->FsContext;
  1971. pBridgePinInstance = FilterInstance->BridgePin;
  1972. ASSERT((PinInstance->InstanceHdr).PinId == ID_DEVIO_PIN);
  1973. //
  1974. // Both sides of the connection must exist.
  1975. //
  1976. if (!(FileObject = FilterInstance->PinFileObjects[ID_BRIDGE_PIN]))
  1977. {
  1978. RCADEBUGP(RCA_ERROR, ("PinDeviceState: "
  1979. "Bridge pin file object is NULL, "
  1980. "returning STATUS_DEVICE_NOT_CONNECTED\n"));
  1981. return STATUS_DEVICE_NOT_CONNECTED;
  1982. }
  1983. //
  1984. // Synchronize pin state changes
  1985. //
  1986. KeWaitForMutexObject(&FilterInstance->ControlMutex,
  1987. Executive,
  1988. KernelMode,
  1989. FALSE,
  1990. NULL);
  1991. RCADEBUGP(RCA_LOUD, ("PinDeviceState: Acquired Filter instance control mutex\n"));
  1992. if (Property->Flags & KSPROPERTY_TYPE_GET)
  1993. {
  1994. if((PinInstance->DeviceState == KSSTATE_PAUSE) &&
  1995. (FilterInstance->FilterType == FilterTypeCapture))
  1996. {
  1997. RCADEBUGP(RCA_ERROR, ("PinDeviceState: Capture device is paused, "
  1998. "setting Status = STATUS_NO_DATA_DETECTED\n"));
  1999. Status = STATUS_NO_DATA_DETECTED;
  2000. }
  2001. *DeviceState = PinInstance->DeviceState;
  2002. KeReleaseMutex( &FilterInstance->ControlMutex, FALSE );
  2003. Irp->IoStatus.Information = sizeof( KSSTATE );
  2004. RCADEBUGP(RCA_INFO, ("PinDeviceState: "
  2005. "Returning DeviceState == 0x%x, Status == 0x%x\n",
  2006. *DeviceState, Status));
  2007. return Status;
  2008. }
  2009. Irp->IoStatus.Information = 0;
  2010. if (PinInstance->DeviceState == *DeviceState)
  2011. {
  2012. KeReleaseMutex( &FilterInstance->ControlMutex, FALSE );
  2013. RCADEBUGP(RCA_LOUD, ("PinDeviceState: Released Filter instance control mutex\n"));
  2014. RCADEBUGP(RCA_INFO, ("PinDeviceState: State is unchanged, returning STATUS_SUCCESS\n"));
  2015. return STATUS_SUCCESS;
  2016. }
  2017. switch(*DeviceState)
  2018. {
  2019. case KSSTATE_ACQUIRE:
  2020. RCADEBUGP(RCA_INFO, ("PinDeviceState: Going to set state to ACQUIRE\n"));
  2021. break;
  2022. case KSSTATE_RUN:
  2023. RCADEBUGP(RCA_INFO, ("PinDeviceState: Going to set state to RUN\n"));
  2024. break;
  2025. case KSSTATE_PAUSE:
  2026. RCADEBUGP(RCA_INFO, ("PinDeviceState: Going to set state to PAUSE\n"));
  2027. break;
  2028. case KSSTATE_STOP:
  2029. RCADEBUGP(RCA_INFO, ("PinDeviceState: Going to set state to STOP\n"));
  2030. #if AUDIO_SINK_FLAG
  2031. if ((FilterInstance->FilterType == FilterTypeCapture) && (PinInstance->ConnectedAsSink))
  2032. {
  2033. // Cancel all the pending IRPs on the ActiveQueue
  2034. KsCancelIo(&PinInstance->ActiveQueue, &PinInstance->QueueLock);
  2035. RCADEBUGP(RCA_LOUD, ("PinDeviceState: Cancelled I/O\n"));
  2036. }
  2037. #endif
  2038. if (FilterInstance->FilterType == FilterTypeCapture) {
  2039. if (pBridgePinInstance != NULL) {
  2040. NDIS_STATUS LocalStatus;
  2041. RCA_ACQUIRE_BRIDGE_PIN_LOCK(pBridgePinInstance);
  2042. pBridgePinInstance->SignalMe = pBridgePinInstance->bWorkItemQueued;
  2043. RCA_RELEASE_BRIDGE_PIN_LOCK(pBridgePinInstance);
  2044. if (pBridgePinInstance->SignalMe) {
  2045. RCADEBUGP(RCA_LOUD, ("PinDeviceState: "
  2046. "Waiting for worker threads\n"));
  2047. RCABlock(&pBridgePinInstance->Block, &LocalStatus);
  2048. }
  2049. }
  2050. }
  2051. KsRecalculateStackDepth(((PDEVICE_INSTANCE)irpSp->DeviceObject->DeviceExtension)->Header,
  2052. FALSE );
  2053. break;
  2054. }
  2055. PinInstance->DeviceState = *DeviceState;
  2056. KeReleaseMutex(&FilterInstance->ControlMutex, FALSE);
  2057. RCADEBUGP(RCA_LOUD, ("PinDeviceState: Released Filter instance control mutex\n"));
  2058. RCADEBUGP(RCA_INFO, ("PinDeviceState: Exit - Returning STATUS_SUCCESS\n"));
  2059. return STATUS_SUCCESS;
  2060. }
  2061. NTSTATUS
  2062. PinAllocatorFramingEx(
  2063. IN PIRP Irp,
  2064. IN PKSPROPERTY Property,
  2065. IN OUT PKSALLOCATOR_FRAMING_EX FramingEx
  2066. )
  2067. {
  2068. NTSTATUS Status;
  2069. PIO_STACK_LOCATION pIrpSp;
  2070. PPIN_INSTANCE_HEADER pPin;
  2071. FILTER_TYPE FilterType;
  2072. PVOID VcContext;
  2073. ULONG ulFrameSize;
  2074. RCADEBUGP(RCA_INFO, ("PinAllocatorFramingEx: Enter\n"));
  2075. pIrpSp = IoGetCurrentIrpStackLocation(Irp);
  2076. pPin = (PPIN_INSTANCE_HEADER) pIrpSp->FileObject->FsContext;
  2077. if (pPin->PinId == ID_DEVIO_PIN) {
  2078. PPIN_INSTANCE_DEVIO pDevioPin;
  2079. pDevioPin = (PPIN_INSTANCE_DEVIO) pPin;
  2080. FilterType = pDevioPin->FilterInstance->FilterType;
  2081. RCA_ACQUIRE_BRIDGE_PIN_LOCK(pDevioPin->FilterInstance->BridgePin);
  2082. VcContext = pDevioPin->VcContext;
  2083. RCA_RELEASE_BRIDGE_PIN_LOCK(pDevioPin->FilterInstance->BridgePin);
  2084. } else if (pPin->PinId == ID_BRIDGE_PIN) {
  2085. PPIN_INSTANCE_BRIDGE pBridgePin;
  2086. pBridgePin = (PPIN_INSTANCE_BRIDGE) pPin;
  2087. FilterType = pBridgePin->FilterInstance->FilterType;
  2088. RCA_ACQUIRE_BRIDGE_PIN_LOCK(pBridgePin);
  2089. VcContext = pBridgePin->VcContext;
  2090. RCA_RELEASE_BRIDGE_PIN_LOCK(pBridgePin);
  2091. } else {
  2092. RCADEBUGP(RCA_FATAL, ("PinAllocatorFramingEx: Got an unkown pin ID 0x%d - returning STATUS_UNSUCCESSFUL\n",
  2093. pPin->PinId));
  2094. Irp->IoStatus.Information = 0;
  2095. return STATUS_UNSUCCESSFUL;
  2096. }
  2097. if (VcContext == NULL) {
  2098. RCADEBUGP(RCA_ERROR,
  2099. ("PinAllocatorFramingEx: Cannot determine max SDU sizes because we have no VC Context"
  2100. " - returning STATUS_UNSUCCESSFUL\n"));
  2101. Irp->IoStatus.Information = 0;
  2102. return STATUS_UNSUCCESSFUL;
  2103. }
  2104. //
  2105. // FIXME: The VC could go away between the time when we release the bridge
  2106. // pin lock and here, so we could be handling a bogus vc context now.
  2107. // Let's see if this causes any problems.
  2108. //
  2109. if (FilterType == FilterTypeRender) {
  2110. RCACoNdisGetMaxSduSizes(VcContext,
  2111. NULL,
  2112. &ulFrameSize);
  2113. } else {
  2114. RCACoNdisGetMaxSduSizes(VcContext,
  2115. &ulFrameSize,
  2116. NULL);
  2117. }
  2118. //
  2119. // For debugging only.
  2120. //
  2121. if (g_ulBufferSize > 0) {
  2122. RCADEBUGP(RCA_ERROR, ("PinAllocatorFramingEx: Hardcoded buffer size to 0x%x\n", g_ulBufferSize));
  2123. ulFrameSize = g_ulBufferSize;
  2124. }
  2125. RCADEBUGP(RCA_LOUD, ("PinAllocatorFramingEx: Frame size set to 0x%x\n", ulFrameSize));
  2126. INITIALIZE_SIMPLE_FRAMING_EX(FramingEx,
  2127. KSMEMORY_TYPE_KERNEL_PAGED,
  2128. KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY, // Note: you don't set the KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY here, so KsProxy thinks that you insist on your framing.
  2129. 8, // number of frames
  2130. FILE_QUAD_ALIGNMENT,
  2131. ulFrameSize, // min. requested frame size
  2132. ulFrameSize // max requested frame size
  2133. );
  2134. Irp->IoStatus.Information=sizeof(KSALLOCATOR_FRAMING_EX);
  2135. RCADEBUGP(RCA_INFO, ("PinAllocatorFramingEx: Exit - Returning STATUS_SUCCESS\n"));
  2136. return STATUS_SUCCESS;
  2137. }
  2138. NTSTATUS
  2139. GetStreamAllocator(
  2140. IN PIRP Irp,
  2141. IN PKSPROPERTY Property,
  2142. IN OUT PVOID * AllocatorHandle
  2143. )
  2144. {
  2145. PIO_STACK_LOCATION irpSp;
  2146. PPIN_INSTANCE_DEVIO PinInstance;
  2147. RCADEBUGP(RCA_INFO,("GetStreamAllocator: enter\n"));
  2148. irpSp = IoGetCurrentIrpStackLocation( Irp );
  2149. PinInstance = (PPIN_INSTANCE_DEVIO) irpSp->FileObject->FsContext;
  2150. *AllocatorHandle=(PVOID)NULL;
  2151. Irp->IoStatus.Information=sizeof(PVOID);
  2152. RCADEBUGP(RCA_INFO, ("GetStreamAllocator: Exit - Returning Status == STATUS_SUCCESS\n"));
  2153. return STATUS_SUCCESS;
  2154. }
  2155. NTSTATUS
  2156. SetStreamAllocator(
  2157. IN PIRP Irp,
  2158. IN PKSPROPERTY Property,
  2159. IN OUT PVOID * AllocatorHandle
  2160. )
  2161. {
  2162. PIO_STACK_LOCATION irpSp;
  2163. PPIN_INSTANCE_DEVIO PinInstance;
  2164. RCADEBUGP(RCA_INFO,("SetStreamAllocator: enter\n"));
  2165. irpSp = IoGetCurrentIrpStackLocation( Irp );
  2166. PinInstance = (PPIN_INSTANCE_DEVIO) irpSp->FileObject->FsContext;
  2167. if (AllocatorHandle != NULL) {
  2168. if (PinInstance->AllocatorObject) {
  2169. //
  2170. // If we've already got an allocator object, get rid of it.
  2171. //
  2172. ObDereferenceObject(PinInstance->AllocatorObject);
  2173. }
  2174. ObReferenceObjectByHandle((HANDLE)*AllocatorHandle,
  2175. 0,
  2176. NULL,
  2177. KernelMode,
  2178. &PinInstance->AllocatorObject,
  2179. NULL);
  2180. }
  2181. Irp->IoStatus.Information=sizeof(ULONG);
  2182. RCADEBUGP(RCA_INFO, ("SetStreamAllocator: Exit - Returning Status == STATUS_SUCCESS\n"));
  2183. return STATUS_SUCCESS;
  2184. }
  2185. NTSTATUS
  2186. RCASetProposedDataFormat(
  2187. IN PIRP Irp,
  2188. IN PKSPROPERTY Property,
  2189. IN PKSDATAFORMAT DataFormat
  2190. )
  2191. /*++
  2192. Routine Description:
  2193. This is the handler for setting the write only property
  2194. KSPROPERTY_PIN_PROPOSEDATAFORMAT. It simply makes a copy
  2195. of whatever data format is passed in. This copy will be
  2196. the data format returned in all future data range
  2197. intersection requests.
  2198. Arguments:
  2199. IN PIRP Irp -
  2200. Pointer to I/O request packet
  2201. IN PKSPROPERTY Property -
  2202. Pointer to the property structure
  2203. IN DataFormat -
  2204. Pointer to the data format to copy
  2205. Return:
  2206. STATUS_SUCCESS or an appropriate error code
  2207. --*/
  2208. {
  2209. NTSTATUS Status = STATUS_SUCCESS;
  2210. PIO_STACK_LOCATION irpSp;
  2211. PPIN_INSTANCE_BRIDGE pBridgePin;
  2212. RCADEBUGP(RCA_INFO, ("RCASetProposedDataFormat: Enter\n"));
  2213. irpSp = IoGetCurrentIrpStackLocation(Irp);
  2214. pBridgePin = (PPIN_INSTANCE_BRIDGE) irpSp->FileObject->FsContext;
  2215. do {
  2216. RCA_ACQUIRE_BRIDGE_PIN_LOCK(pBridgePin);
  2217. if (pBridgePin->pDataFormat) {
  2218. //
  2219. // If a data format was set by a previous call to this
  2220. // routine, free the memory used by that data format.
  2221. //
  2222. RCAFreeMem(pBridgePin->pDataFormat);
  2223. }
  2224. RCAAllocMem(pBridgePin->pDataFormat, KSDATAFORMAT, DataFormat->FormatSize);
  2225. if (pBridgePin->pDataFormat) {
  2226. RtlCopyMemory(pBridgePin->pDataFormat, DataFormat, DataFormat->FormatSize);
  2227. } else {
  2228. RCADEBUGP(RCA_ERROR, ("RCASetProposedDataFormat: "
  2229. "Failed to allocate memory for data format storage, setting "
  2230. "Status = STATUS_INSUFFICIENT_RESOURCES\n"));
  2231. Status = STATUS_INSUFFICIENT_RESOURCES;
  2232. }
  2233. RCA_RELEASE_BRIDGE_PIN_LOCK(pBridgePin);
  2234. } while(FALSE);
  2235. RCADEBUGP(RCA_INFO, ("RCASetProposedDataFormat: Exit - Returning Status == 0x%x\n",
  2236. Status));
  2237. return Status;
  2238. }