Leaked source code of windows server 2003
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.

386 lines
14 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1998 - 1999
  3. Module Name:
  4. audclass.cpp
  5. Abstract:
  6. This module contains audio class code.
  7. Author:
  8. Paul England (pengland) from the AUDIO.sys ks2 sample code
  9. Dale Sather (DaleSat) 31-Jul-1998
  10. --*/
  11. #include "private.h"
  12. #ifdef ALLOC_PRAGMA
  13. #pragma code_seg("PAGE")
  14. #endif // ALLOC_PRAGMA
  15. #ifdef ALLOC_DATA_PRAGMA
  16. #pragma const_seg("PAGECONST")
  17. #endif // ALLOC_DATA_PRAGMA
  18. NTSTATUS
  19. DRMAudioIntersectHandlerInPin(
  20. IN PVOID Filter,
  21. IN PIRP Irp,
  22. IN PKSP_PIN PinInstance,
  23. IN PKSDATARANGE CallerDataRange,
  24. IN PKSDATARANGE DescriptorDataRange,
  25. IN ULONG BufferSize,
  26. OUT PVOID Data OPTIONAL,
  27. OUT PULONG DataSize
  28. )
  29. /*++
  30. Routine Description:
  31. This routine handles pin intersection queries by determining the
  32. intersection between two data ranges.
  33. Arguments:
  34. Filter -
  35. Contains a void pointer to the filter structure.
  36. Irp -
  37. Contains a pointer to the data intersection property request.
  38. PinInstance -
  39. Contains a pointer to a structure indicating the pin in question.
  40. CallerDataRange -
  41. Contains a pointer to one of the data ranges supplied by the client
  42. in the data intersection request. The format type, subtype and
  43. specifier are compatible with the DescriptorDataRange.
  44. DescriptorDataRange -
  45. Contains a pointer to one of the data ranges from the pin descriptor
  46. for the pin in question. The format type, subtype and specifier are
  47. compatible with the CallerDataRange.
  48. BufferSize -
  49. Contains the size in bytes of the buffer pointed to by the Data
  50. argument. For size queries, this value will be zero.
  51. Data -
  52. Optionally contains a pointer to the buffer to contain the data format
  53. structure representing the best format in the intersection of the
  54. two data ranges. For size queries, this pointer will be NULL.
  55. DataSize -
  56. Contains a pointer to the location at which to deposit the size of the
  57. data format. This information is supplied by the function when the
  58. format is actually delivered and in response to size queries.
  59. Return Value:
  60. STATUS_SUCCESS if there is an intersection and it fits in the supplied
  61. buffer, STATUS_BUFFER_OVERFLOW for successful size queries, STATUS_NO_MATCH
  62. if the intersection is empty, or STATUS_BUFFER_TOO_SMALL if the supplied
  63. buffer is too small.
  64. --*/
  65. /*++
  66. DRMK Routine description
  67. In-pin intersection handler accepts any WAVE_FORMAT_DRM format. The output pin format
  68. is modified to correspond to the input pin DRM-encapsulated format.
  69. --*/
  70. {
  71. _DbgPrintF(DEBUGLVL_VERBOSE,("[DRMAudioIntersectHandler - IN]"));
  72. PAGED_CODE();
  73. ASSERT(Filter);
  74. ASSERT(Irp);
  75. ASSERT(PinInstance);
  76. ASSERT(CallerDataRange);
  77. ASSERT(DescriptorDataRange);
  78. ASSERT(DataSize);
  79. //
  80. // Descriptor data range must be WAVEFORMATEX or DSOUND
  81. //
  82. ASSERT(IsEqualGUIDAligned(DescriptorDataRange->Specifier,KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) ||
  83. IsEqualGUIDAligned(DescriptorDataRange->Specifier,KSDATAFORMAT_SPECIFIER_DSOUND ));
  84. PKSDATARANGE_AUDIO descriptorDataRange = PKSDATARANGE_AUDIO(DescriptorDataRange);
  85. //
  86. // Caller data range may be wildcard or WAVEFORMATEX or DSOUND
  87. //
  88. PKSDATARANGE_AUDIO callerDataRange;
  89. if (IsEqualGUIDAligned(CallerDataRange->Specifier,KSDATAFORMAT_SPECIFIER_WILDCARD)) {
  90. //
  91. // Wildcard. Do not try to look at the specifier.
  92. //
  93. callerDataRange = NULL;
  94. } else {
  95. //
  96. // WAVEFORMATEX or DSOUND. Validate the specifier ranges.
  97. //
  98. ASSERT(IsEqualGUIDAligned(CallerDataRange->Specifier,KSDATAFORMAT_SPECIFIER_WAVEFORMATEX) ||
  99. IsEqualGUIDAligned(CallerDataRange->Specifier,KSDATAFORMAT_SPECIFIER_DSOUND ));
  100. callerDataRange = PKSDATARANGE_AUDIO(CallerDataRange);
  101. if ((CallerDataRange->FormatSize != sizeof(*callerDataRange)) ||
  102. (callerDataRange->MaximumSampleFrequency <
  103. descriptorDataRange->MinimumSampleFrequency) ||
  104. (descriptorDataRange->MaximumSampleFrequency <
  105. callerDataRange->MinimumSampleFrequency) ||
  106. (callerDataRange->MaximumBitsPerSample <
  107. descriptorDataRange->MinimumBitsPerSample) ||
  108. (descriptorDataRange->MaximumBitsPerSample <
  109. callerDataRange->MinimumBitsPerSample)) {
  110. _DbgPrintF(DEBUGLVL_VERBOSE,("[DRMINSCT PinIntersectHandler IN] STATUS_NO_MATCH"));
  111. return STATUS_NO_MATCH;
  112. }
  113. }
  114. SIZE_T cbDataFormat;
  115. if (!callerDataRange || IsEqualGUIDAligned(callerDataRange->DataRange.Specifier,KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)) {
  116. cbDataFormat = sizeof(KSDATAFORMAT_WAVEFORMATEX) + sizeof(DRMWAVEFORMAT) - sizeof(WAVEFORMATEX);
  117. } else {
  118. ASSERT(IsEqualGUIDAligned(callerDataRange->DataRange.Specifier,KSDATAFORMAT_SPECIFIER_DSOUND));
  119. cbDataFormat = sizeof(KSDATAFORMAT_DSOUND) + sizeof(DRMWAVEFORMAT) - sizeof(WAVEFORMATEX);
  120. }
  121. if (BufferSize == 0) {
  122. // Size query - return the size.
  123. *DataSize = (ULONG)cbDataFormat;
  124. _DbgPrintF(DEBUGLVL_VERBOSE,("[DRMINSCT PinIntersectHandler IN] STATUS_BUFFER_OVERFLOW"));
  125. return STATUS_BUFFER_OVERFLOW;
  126. }
  127. PKSDATAFORMAT dataFormat = PKSDATAFORMAT(Data);
  128. ASSERT(dataFormat);
  129. if (BufferSize < cbDataFormat) {
  130. // Buffer is too small.
  131. _DbgPrintF(DEBUGLVL_VERBOSE,("[DRMINSCT PinIntersectHandler IN] STATUS_BUFFER_TOO_SMALL"));
  132. return STATUS_BUFFER_TOO_SMALL;
  133. }
  134. //
  135. // Gotta build the format.
  136. //
  137. *DataSize = (ULONG)cbDataFormat;
  138. RtlZeroMemory(dataFormat, cbDataFormat);
  139. PDRMWAVEFORMAT drmFormat;
  140. if (!callerDataRange || IsEqualGUIDAligned(callerDataRange->DataRange.Specifier,KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)) {
  141. drmFormat = (PDRMWAVEFORMAT)&PKSDATAFORMAT_WAVEFORMATEX(dataFormat)->WaveFormatEx;
  142. } else {
  143. // Note dataFormat->BufferDesc.Flags and Control are memset to 0 above
  144. drmFormat = (PDRMWAVEFORMAT)&PKSDATAFORMAT_DSOUND(dataFormat)->BufferDesc.WaveFormatEx;
  145. }
  146. // First let's fill out the wfxSecure format based on the data intersection
  147. // Without more info, all we can do is propose PCM as the secure format
  148. drmFormat->wfxSecure.wFormatTag = WAVE_FORMAT_PCM;
  149. if (callerDataRange) {
  150. drmFormat->wfxSecure.nChannels = (USHORT) min(callerDataRange->MaximumChannels,descriptorDataRange->MaximumChannels);
  151. drmFormat->wfxSecure.nSamplesPerSec = min(callerDataRange->MaximumSampleFrequency,descriptorDataRange->MaximumSampleFrequency);
  152. drmFormat->wfxSecure.wBitsPerSample = (USHORT) min(callerDataRange->MaximumBitsPerSample,descriptorDataRange->MaximumBitsPerSample);
  153. } else {
  154. drmFormat->wfxSecure.nChannels = (USHORT) descriptorDataRange->MaximumChannels;
  155. drmFormat->wfxSecure.nSamplesPerSec = descriptorDataRange->MaximumSampleFrequency;
  156. drmFormat->wfxSecure.wBitsPerSample = (USHORT) descriptorDataRange->MaximumBitsPerSample;
  157. }
  158. drmFormat->wfxSecure.nBlockAlign = (drmFormat->wfxSecure.wBitsPerSample * drmFormat->wfxSecure.nChannels) / 8;
  159. drmFormat->wfxSecure.nAvgBytesPerSec = drmFormat->wfxSecure.nBlockAlign * drmFormat->wfxSecure.nSamplesPerSec;
  160. drmFormat->wfxSecure.cbSize = 0;
  161. // Now fill out the drm waveformat. If we someday frame the scrambled data, then
  162. // we should update this to reflect the framing
  163. drmFormat->wfx.wFormatTag = WAVE_FORMAT_DRM;
  164. drmFormat->wfx.nChannels = drmFormat->wfxSecure.nChannels;
  165. drmFormat->wfx.nSamplesPerSec = drmFormat->wfxSecure.nSamplesPerSec;
  166. drmFormat->wfx.wBitsPerSample = drmFormat->wfxSecure.wBitsPerSample;
  167. drmFormat->wfx.nBlockAlign = drmFormat->wfxSecure.nBlockAlign;
  168. drmFormat->wfx.nAvgBytesPerSec = drmFormat->wfxSecure.nAvgBytesPerSec;
  169. drmFormat->wfx.cbSize = sizeof(*drmFormat) - sizeof(WAVEFORMATEX);
  170. // Now finish off some of the fields in the base KSDATAFORMAT_WAVE structure
  171. // Note all the guids are in the descriptor's data range.
  172. RtlCopyMemory(dataFormat,DescriptorDataRange,sizeof(*dataFormat));
  173. dataFormat->FormatSize = (ULONG)cbDataFormat;
  174. dataFormat->SampleSize = drmFormat->wfx.nBlockAlign;
  175. _DbgPrintF(DEBUGLVL_VERBOSE,("[DRMINSCT PinIntersectHandler(in)] DONE OK\n"));
  176. return STATUS_SUCCESS;
  177. }
  178. //-------------------------------------------------------------------------------------
  179. // OUT
  180. NTSTATUS
  181. DRMAudioIntersectHandlerOutPin(
  182. IN PVOID Filter,
  183. IN PIRP Irp,
  184. IN PKSP_PIN PinInstance,
  185. IN PKSDATARANGE CallerDataRange,
  186. IN PKSDATARANGE DescriptorDataRange,
  187. IN ULONG BufferSize,
  188. OUT PVOID Data OPTIONAL,
  189. OUT PULONG DataSize
  190. )
  191. /*++
  192. Routine Description:
  193. This routine handles pin intersection queries by determining the
  194. intersection between two data ranges.
  195. Arguments:
  196. Filter -
  197. Contains a void pointer to the filter structure.
  198. Irp -
  199. Contains a pointer to the data intersection property request.
  200. PinInstance -
  201. Contains a pointer to a structure indicating the pin in question.
  202. CallerDataRange -
  203. Contains a pointer to one of the data ranges supplied by the client
  204. in the data intersection request. The format type, subtype and
  205. specifier are compatible with the DescriptorDataRange.
  206. DescriptorDataRange -
  207. Contains a pointer to one of the data ranges from the pin descriptor
  208. for the pin in question. The format type, subtype and specifier are
  209. compatible with the CallerDataRange.
  210. BufferSize -
  211. Contains the size in bytes of the buffer pointed to by the Data
  212. argument. For size queries, this value will be zero.
  213. Data -
  214. Optionally contains a pointer to the buffer to contain the data format
  215. structure representing the best format in the intersection of the
  216. two data ranges. For size queries, this pointer will be NULL.
  217. DataSize -
  218. Contains a pointer to the location at which to deposit the size of the
  219. data format. This information is supplied by the function when the
  220. format is actually delivered and in response to size queries.
  221. Return Value:
  222. STATUS_SUCCESS if there is an intersection and it fits in the supplied
  223. buffer, STATUS_BUFFER_OVERFLOW for successful size queries, STATUS_NO_MATCH
  224. if the intersection is empty, or STATUS_BUFFER_TOO_SMALL if the supplied
  225. buffer is too small.
  226. --*/
  227. /*++
  228. DRMK Routine description
  229. Out-pin intersection handler specifies the exact encapsulated data format passed to the
  230. input pin.
  231. --*/
  232. {
  233. _DbgPrintF(DEBUGLVL_VERBOSE,("[DRMAudioIntersectHandler]"));
  234. PAGED_CODE();
  235. ASSERT(Filter);
  236. ASSERT(Irp);
  237. ASSERT(PinInstance);
  238. ASSERT(CallerDataRange);
  239. ASSERT(DescriptorDataRange);
  240. ASSERT(DataSize);
  241. // Must negotiate InPin before OutPin
  242. PKSFILTER filter = (PKSFILTER) Filter;
  243. FilterInstance* instance=(FilterInstance*) filter->Context;
  244. if (!KsFilterGetFirstChildPin(filter,PIN_ID_INPUT)) {
  245. _DbgPrintF(DEBUGLVL_VERBOSE,("[DRMINSCT Must connect IN before OUT] - STATUS_NO_MATCH"));
  246. return STATUS_NO_MATCH;
  247. };
  248. //
  249. // If we edited the output data range properly, then KS should not
  250. // ask us to intersect a specifier that doesn't match our required
  251. // output format specifier
  252. //
  253. ASSERT(IsEqualGUIDAligned(DescriptorDataRange->Specifier,instance->OutDataFormat->Specifier));
  254. PKSDATARANGE_AUDIO descriptorDataRange = PKSDATARANGE_AUDIO(DescriptorDataRange);
  255. //
  256. // Caller data range may be wildcard or WAVEFORMATEX or DSOUND
  257. //
  258. PKSDATARANGE_AUDIO callerDataRange;
  259. if (IsEqualGUIDAligned(CallerDataRange->Specifier,KSDATAFORMAT_SPECIFIER_WILDCARD)) {
  260. //
  261. // Wildcard. Do not try to look at the specifier.
  262. //
  263. callerDataRange = NULL;
  264. } else {
  265. //
  266. // Not a wild card, so KS should not ask us to intersect a specifier that
  267. // does not match our required output format specifier (is this true)?
  268. //
  269. ASSERT(IsEqualGUIDAligned(CallerDataRange->Specifier,instance->OutDataFormat->Specifier));
  270. callerDataRange = PKSDATARANGE_AUDIO(CallerDataRange);
  271. if ((CallerDataRange->FormatSize != sizeof(*callerDataRange)) ||
  272. (callerDataRange->MaximumSampleFrequency <
  273. descriptorDataRange->MinimumSampleFrequency) ||
  274. (descriptorDataRange->MaximumSampleFrequency <
  275. callerDataRange->MinimumSampleFrequency) ||
  276. (callerDataRange->MaximumBitsPerSample <
  277. descriptorDataRange->MinimumBitsPerSample) ||
  278. (descriptorDataRange->MaximumBitsPerSample <
  279. callerDataRange->MinimumBitsPerSample)) {
  280. _DbgPrintF(DEBUGLVL_VERBOSE,("[DRMINSCT PinIntersectHandler OUT] STATUS_NO_MATCH"));
  281. return STATUS_NO_MATCH;
  282. }
  283. }
  284. if (BufferSize == 0) {
  285. // Size query - return the size.
  286. *DataSize = instance->OutDataFormat->FormatSize;
  287. _DbgPrintF(DEBUGLVL_VERBOSE,("[DRMINSCT PinIntersectHandler OUT] STATUS_BUFFER_OVERFLOW"));
  288. return STATUS_BUFFER_OVERFLOW;
  289. }
  290. PKSDATAFORMAT dataFormat = (PKSDATAFORMAT)Data;
  291. ASSERT(dataFormat);
  292. if (BufferSize < instance->OutDataFormat->FormatSize) {
  293. // Buffer is too small.
  294. _DbgPrintF(DEBUGLVL_VERBOSE,("[DRMINSCT PinIntersectHandler OUT] STATUS_BUFFER_TOO_SMALL"));
  295. return STATUS_BUFFER_TOO_SMALL;
  296. }
  297. // Input PinCreate builds the required output format in the filter-context, derived from the
  298. // secure audio format that it encapsulated in the DRMWAVEFORMAT. Just copy it.
  299. *DataSize = instance->OutDataFormat->FormatSize;
  300. RtlCopyMemory(dataFormat, instance->OutDataFormat, instance->OutDataFormat->FormatSize);
  301. _DbgPrintF(DEBUGLVL_VERBOSE,("[DRMINSCT PinIntersectHandler(out)] DONE OK\n"));
  302. return STATUS_SUCCESS;
  303. }