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.

4254 lines
109 KiB

  1. //==========================================================================;
  2. //
  3. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4. // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5. // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6. // PURPOSE.
  7. //
  8. // Copyright (c) 1992 - 1998 Microsoft Corporation. All Rights Reserved.
  9. //
  10. //==========================================================================;
  11. #include <wdm.h>
  12. #include <limits.h>
  13. #include <unknown.h>
  14. #include <ks.h>
  15. #include <ksmedia.h>
  16. #include <bdatypes.h>
  17. #include <bdamedia.h>
  18. #include <bdasup.h>
  19. #include "bdasupi.h"
  20. /*
  21. - DriverEntry
  22. -
  23. * This the the required DriverEntry for the BDA Support Driver.
  24. * Though required, it is never actually called.
  25. *
  26. */
  27. NTSTATUS
  28. DriverEntry (
  29. IN PDRIVER_OBJECT pDriverObject,
  30. IN PUNICODE_STRING pszuRegistryPath
  31. )
  32. //////////////////////////////////////////////////////////////////////////////////////
  33. {
  34. //$BUGBUG This entry point is required but never called.
  35. return STATUS_SUCCESS;
  36. }
  37. STDMETHODIMP_(NTSTATUS)
  38. BdaFindContextEntry(
  39. PBDA_CONTEXT_LIST pContextList,
  40. PVOID pvReference,
  41. PVOID * ppvContext
  42. )
  43. {
  44. NTSTATUS status = STATUS_SUCCESS;
  45. ULONG uliEntry;
  46. KIRQL oldIrql;
  47. ASSERT( pContextList);
  48. ASSERT( ppvContext);
  49. if (!pContextList->fInitialized)
  50. {
  51. status = STATUS_NOT_FOUND;
  52. goto errExit;
  53. }
  54. // NULL pvReference is not valid.
  55. //
  56. if (!pvReference)
  57. {
  58. status = STATUS_INVALID_PARAMETER;
  59. *ppvContext = NULL;
  60. goto errExit;
  61. }
  62. // Lock down the list while we search it.
  63. //
  64. KeAcquireSpinLock( &(pContextList->lock), &oldIrql);
  65. // Find a list entry with a matching pvReference
  66. //
  67. for (uliEntry = 0; uliEntry < pContextList->ulcListEntries; uliEntry++)
  68. {
  69. if (pContextList->pListEntries[uliEntry].pvReference == pvReference)
  70. {
  71. break;
  72. }
  73. }
  74. if (uliEntry >= pContextList->ulcListEntries)
  75. {
  76. // No matching entry was found so return error.
  77. //
  78. status = STATUS_NOT_FOUND;
  79. *ppvContext = NULL;
  80. }
  81. else
  82. {
  83. // Return the pvContext corresponding to the matching pvReference.
  84. //
  85. *ppvContext = pContextList->pListEntries[uliEntry].pvContext;
  86. }
  87. KeReleaseSpinLock( &(pContextList->lock), oldIrql);
  88. errExit:
  89. return status;
  90. }
  91. STDMETHODIMP_(NTSTATUS)
  92. BdaCreateContextEntry(
  93. PBDA_CONTEXT_LIST pContextList,
  94. PVOID pvReference,
  95. ULONG ulcbContext,
  96. PVOID * ppvContext
  97. )
  98. {
  99. NTSTATUS status = STATUS_SUCCESS;
  100. ULONG uliEntry;
  101. KIRQL oldIrql;
  102. ASSERT( pContextList);
  103. ASSERT( ppvContext);
  104. if (!pContextList->fInitialized)
  105. {
  106. KeInitializeSpinLock ( &(pContextList->lock));
  107. pContextList->fInitialized = TRUE;
  108. }
  109. // See if a list entry has already been created.
  110. //
  111. status = BdaFindContextEntry( pContextList, pvReference, ppvContext);
  112. if (status != STATUS_NOT_FOUND)
  113. {
  114. goto errExit;
  115. }
  116. status = STATUS_SUCCESS;
  117. KeAcquireSpinLock( &(pContextList->lock), &oldIrql);
  118. // If the current block of context entries is full, allocate
  119. // a bigger block to put the new entry into.
  120. //
  121. if (pContextList->ulcListEntries >= pContextList->ulcMaxListEntries)
  122. {
  123. ULONG ulcEntriesToAllocate;
  124. PBDA_CONTEXT_ENTRY pNewList;
  125. ulcEntriesToAllocate = pContextList->ulcMaxListEntries
  126. + pContextList->ulcListEntriesPerBlock;
  127. pNewList = (PBDA_CONTEXT_ENTRY) ExAllocatePool(
  128. NonPagedPool,
  129. ulcEntriesToAllocate * sizeof( BDA_CONTEXT_ENTRY)
  130. );
  131. if (!pNewList)
  132. {
  133. status = STATUS_NO_MEMORY;
  134. KeReleaseSpinLock( &(pContextList->lock), oldIrql);
  135. goto errExit;
  136. }
  137. RtlZeroMemory( pNewList,
  138. ulcEntriesToAllocate * sizeof( BDA_CONTEXT_ENTRY)
  139. );
  140. if (pContextList->pListEntries)
  141. {
  142. // pNewList and pContextList->pListEntries are big enough (allocated in this file)
  143. RtlMoveMemory( pNewList,
  144. pContextList->pListEntries,
  145. pContextList->ulcMaxListEntries
  146. * sizeof( BDA_CONTEXT_ENTRY)
  147. );
  148. ExFreePool( pContextList->pListEntries);
  149. }
  150. pContextList->pListEntries = pNewList;
  151. pContextList->ulcMaxListEntries = ulcEntriesToAllocate;
  152. }
  153. #ifdef SORTED_CONTEXT_ENTRIES
  154. // Find the proper place to insert the new entry into the list.
  155. //
  156. for (uliEntry = 0; uliEntry < pContextList->ulcListEntries; uliEntry++)
  157. {
  158. if (pContextList->pListEntries[uliEntry].pvReference > pvReference)
  159. {
  160. break;
  161. }
  162. }
  163. #else
  164. uliEntry = pContextList->ulcListEntries;
  165. #endif // SORTED_CONTEXT_ENTRIES
  166. // Allocate a new context entry
  167. //
  168. *ppvContext = ExAllocatePool( NonPagedPool, ulcbContext);
  169. if (!*ppvContext)
  170. {
  171. status = STATUS_NO_MEMORY;
  172. KeReleaseSpinLock( &(pContextList->lock), oldIrql);
  173. goto errExit;
  174. }
  175. #ifdef SORTED_CONTEXT_ENTRIES
  176. // If the new entry is in the middle of the list, then create
  177. // a whole for it by moving the end of the list down.
  178. //
  179. if (uliEntry < pContextList->ulcListEntries)
  180. {
  181. // NOTE! RtlMoveMemory handles overlapped source and destination.
  182. //
  183. RtlMoveMemory( &(pContextList->pListEntries[uliEntry + 1]),
  184. &(pContextList->pListEntries[uliEntry]),
  185. (pContextList->ulcListEntries - uliEntry)
  186. * sizeof( BDA_CONTEXT_ENTRY)
  187. );
  188. }
  189. #endif // SORTED_CONTEXT_ENTRIES
  190. RtlZeroMemory( *ppvContext, ulcbContext);
  191. pContextList->pListEntries[uliEntry].pvContext = *ppvContext;
  192. pContextList->pListEntries[uliEntry].ulcbContext = ulcbContext;
  193. pContextList->pListEntries[uliEntry].pvReference = pvReference;
  194. pContextList->ulcListEntries++;
  195. KeReleaseSpinLock( &(pContextList->lock), oldIrql);
  196. errExit:
  197. return status;
  198. }
  199. STDMETHODIMP_(NTSTATUS)
  200. BdaDeleteContextEntry(
  201. PBDA_CONTEXT_LIST pContextList,
  202. PVOID pvReference
  203. )
  204. {
  205. NTSTATUS status = STATUS_SUCCESS;
  206. ULONG uliEntry;
  207. KIRQL oldIrql;
  208. PVOID pvContext;
  209. ULONG ulcbContext;
  210. ASSERT( pContextList);
  211. ASSERT( pvReference);
  212. ASSERT( pContextList->fInitialized);
  213. if (!pContextList->fInitialized)
  214. {
  215. goto errExit;
  216. }
  217. KeAcquireSpinLock( &(pContextList->lock), &oldIrql);
  218. // Find the Context Entry in the list
  219. //
  220. for (uliEntry = 0; uliEntry < pContextList->ulcListEntries; uliEntry++)
  221. {
  222. if (pContextList->pListEntries[uliEntry].pvReference == pvReference)
  223. {
  224. break;
  225. }
  226. }
  227. if (uliEntry >= pContextList->ulcListEntries)
  228. {
  229. status = STATUS_NOT_FOUND;
  230. KeReleaseSpinLock( &(pContextList->lock), oldIrql);
  231. goto errExit;
  232. }
  233. pvContext = pContextList->pListEntries[uliEntry].pvContext;
  234. ulcbContext = pContextList->pListEntries[uliEntry].ulcbContext;
  235. pContextList->pListEntries[uliEntry].pvContext = NULL;
  236. pContextList->pListEntries[uliEntry].pvReference = NULL;
  237. RtlZeroMemory( pvContext, ulcbContext);
  238. ExFreePool( pvContext);
  239. pContextList->ulcListEntries -= 1;
  240. if (uliEntry < pContextList->ulcListEntries)
  241. {
  242. // NOTE! RtlMoveMemory handles overlapped source and destination.
  243. //
  244. // pContextList->pListEntries is big enough (with index uliEntry(+1) as well)
  245. RtlMoveMemory( &(pContextList->pListEntries[uliEntry]),
  246. &(pContextList->pListEntries[uliEntry + 1]),
  247. (pContextList->ulcListEntries - uliEntry)
  248. * sizeof( BDA_CONTEXT_ENTRY)
  249. );
  250. }
  251. KeReleaseSpinLock( &(pContextList->lock), oldIrql);
  252. errExit:
  253. return status;
  254. }
  255. STDMETHODIMP_(NTSTATUS)
  256. BdaDeleteContextEntryByValue(
  257. PBDA_CONTEXT_LIST pContextList,
  258. PVOID pvContext
  259. )
  260. {
  261. NTSTATUS status = STATUS_SUCCESS;
  262. ULONG uliEntry;
  263. KIRQL oldIrql;
  264. ULONG ulcbContext;
  265. ASSERT( pContextList);
  266. ASSERT( pvContext);
  267. ASSERT( pContextList->fInitialized);
  268. if (!pContextList->fInitialized)
  269. {
  270. goto errExit;
  271. }
  272. KeAcquireSpinLock( &(pContextList->lock), &oldIrql);
  273. // Find the Context Entry in the list
  274. //
  275. for (uliEntry = 0; uliEntry < pContextList->ulcListEntries; uliEntry++)
  276. {
  277. if (pContextList->pListEntries[uliEntry].pvContext == pvContext)
  278. {
  279. break;
  280. }
  281. }
  282. if (uliEntry >= pContextList->ulcListEntries)
  283. {
  284. status = STATUS_NOT_FOUND;
  285. KeReleaseSpinLock( &(pContextList->lock), oldIrql);
  286. goto errExit;
  287. }
  288. ulcbContext = pContextList->pListEntries[uliEntry].ulcbContext;
  289. pContextList->pListEntries[uliEntry].pvContext = NULL;
  290. pContextList->pListEntries[uliEntry].pvReference = NULL;
  291. RtlZeroMemory( pvContext, ulcbContext);
  292. ExFreePool( pvContext);
  293. pContextList->ulcListEntries -= 1;
  294. if (uliEntry < pContextList->ulcListEntries)
  295. {
  296. // NOTE! RtlMoveMemory handles overlapped source and destination.
  297. //
  298. // pContextList->pListEntries is big enough (allocated in this file)
  299. RtlMoveMemory( &(pContextList->pListEntries[uliEntry]),
  300. &(pContextList->pListEntries[uliEntry + 1]),
  301. (pContextList->ulcListEntries - uliEntry)
  302. * sizeof( BDA_CONTEXT_ENTRY)
  303. );
  304. }
  305. KeReleaseSpinLock( &(pContextList->lock), oldIrql);
  306. errExit:
  307. return status;
  308. }
  309. /*
  310. ** BdaDeleteFilterFactoryContextByValue()
  311. **
  312. ** Finds the given BDA Filter Factory Context in the FilterFactory
  313. ** context list and removes it.
  314. **
  315. ** This function is provided as a callback when the Filter Facotry Context
  316. ** is added to the KSFilterFactory's Object Bag. This allows KS to clean
  317. ** up the context when the filter factory is unexpectedly closed.
  318. **
  319. ** Arguments:
  320. **
  321. **
  322. ** Returns:
  323. **
  324. **
  325. **
  326. ** Side Effects: none
  327. */
  328. BDA_CONTEXT_LIST FilterFactoryContextList = { 0, 0, 4, NULL, 0, FALSE};
  329. STDMETHODIMP_(VOID)
  330. BdaDeleteFilterFactoryContextByValue(
  331. PVOID pFilterFactoryCtx
  332. )
  333. {
  334. BdaDeleteContextEntryByValue( &FilterFactoryContextList,
  335. pFilterFactoryCtx
  336. );
  337. }
  338. /*
  339. ** BdaCreateFilterFactoryContext()
  340. **
  341. ** Finds or creates a BDA Filter Factory Context that corresponds
  342. ** to the given KS Filter Factory.
  343. **
  344. ** Arguments:
  345. **
  346. **
  347. ** Returns:
  348. **
  349. **
  350. **
  351. ** Side Effects: none
  352. */
  353. STDMETHODIMP_(NTSTATUS)
  354. BdaCreateFilterFactoryContext(
  355. PKSFILTERFACTORY pKSFilterFactory,
  356. PBDA_FILTER_FACTORY_CONTEXT * ppFilterFactoryCtx
  357. )
  358. {
  359. NTSTATUS status = STATUS_SUCCESS;
  360. status = BdaCreateContextEntry( &FilterFactoryContextList,
  361. pKSFilterFactory,
  362. sizeof( BDA_FILTER_FACTORY_CONTEXT),
  363. (PVOID *) ppFilterFactoryCtx
  364. );
  365. if (!NT_SUCCESS( status))
  366. {
  367. goto errExit;
  368. }
  369. status = KsAddItemToObjectBag( pKSFilterFactory->Bag,
  370. *ppFilterFactoryCtx,
  371. BdaDeleteFilterFactoryContextByValue
  372. );
  373. errExit:
  374. return status;
  375. }
  376. /*
  377. ** BdaDestructFilterContext()
  378. **
  379. ** Finds the given BDA Filter Context in the Filter
  380. ** context list and removes it.
  381. **
  382. ** This function is provided as a callback when the Filter Context is
  383. ** added to the KSFilter's Object Bag. This allows KS to clean up the
  384. ** context when the filter is unexpectedly closed.
  385. **
  386. ** Arguments:
  387. **
  388. **
  389. ** Returns:
  390. **
  391. **
  392. **
  393. ** Side Effects: none
  394. */
  395. STDMETHODIMP_(VOID)
  396. BdaDestructFilterContext(
  397. PBDA_FILTER_CONTEXT pFilterCtx
  398. )
  399. {
  400. ULONG uliPath;
  401. ASSERT( pFilterCtx);
  402. if (!pFilterCtx || !pFilterCtx->argpPathInfo)
  403. {
  404. goto exit;
  405. }
  406. // Delete the path information.
  407. //
  408. for ( uliPath = 0; uliPath < pFilterCtx->ulcPathInfo; uliPath++)
  409. {
  410. if (pFilterCtx->argpPathInfo[uliPath])
  411. {
  412. ExFreePool( pFilterCtx->argpPathInfo[uliPath]);
  413. pFilterCtx->argpPathInfo[uliPath] = NULL;
  414. }
  415. }
  416. ExFreePool( pFilterCtx->argpPathInfo);
  417. pFilterCtx->argpPathInfo = NULL;
  418. pFilterCtx->ulcPathInfo = 0;
  419. exit:
  420. return;
  421. }
  422. /*
  423. ** BdaDeleteFilterContextByValue()
  424. **
  425. ** Finds the given BDA Filter Context in the Filter
  426. ** context list and removes it.
  427. **
  428. ** This function is provided as a callback when the Filter Context is
  429. ** added to the KSFilter's Object Bag. This allows KS to clean up the
  430. ** context when the filter is unexpectedly closed.
  431. **
  432. ** Arguments:
  433. **
  434. **
  435. ** Returns:
  436. **
  437. **
  438. **
  439. ** Side Effects: none
  440. */
  441. BDA_CONTEXT_LIST FilterContextList = { 0, 0, 4, NULL, 0, FALSE};
  442. STDMETHODIMP_(VOID)
  443. BdaDeleteFilterContextByValue(
  444. PVOID pFilterCtx
  445. )
  446. {
  447. BdaDestructFilterContext( (PBDA_FILTER_CONTEXT) pFilterCtx);
  448. BdaDeleteContextEntryByValue( &FilterContextList,
  449. pFilterCtx
  450. );
  451. }
  452. /*
  453. ** BdaCreateFilterContext()
  454. **
  455. ** Finds or creates a BDA Filter Context that corresponds
  456. ** to the given KS Filter.
  457. **
  458. ** Arguments:
  459. **
  460. **
  461. ** Returns:
  462. **
  463. **
  464. **
  465. ** Side Effects: none
  466. */
  467. STDMETHODIMP_(NTSTATUS)
  468. BdaCreateFilterContext(
  469. PKSFILTER pKSFilter,
  470. PBDA_FILTER_CONTEXT * ppFilterCtx
  471. )
  472. {
  473. NTSTATUS status = STATUS_SUCCESS;
  474. status = BdaCreateContextEntry( &FilterContextList,
  475. pKSFilter,
  476. sizeof( BDA_FILTER_CONTEXT),
  477. (PVOID *) ppFilterCtx
  478. );
  479. if (!NT_SUCCESS( status))
  480. {
  481. goto errExit;
  482. }
  483. status = KsAddItemToObjectBag( pKSFilter->Bag,
  484. *ppFilterCtx,
  485. BdaDeleteFilterContextByValue
  486. );
  487. (*ppFilterCtx)->pKSFilter = pKSFilter;
  488. errExit:
  489. return status;
  490. }
  491. /*
  492. ** BdaGetFilterContext()
  493. **
  494. ** Finds a BDA Filter Context that corresponds
  495. ** to the given KS Filter Instance.
  496. **
  497. ** Arguments:
  498. **
  499. **
  500. ** Returns:
  501. **
  502. **
  503. **
  504. ** Side Effects: none
  505. */
  506. STDMETHODIMP_(NTSTATUS)
  507. BdaGetFilterContext(
  508. PKSFILTER pKSFilter,
  509. PBDA_FILTER_CONTEXT * ppFilterCtx
  510. )
  511. {
  512. NTSTATUS status = STATUS_SUCCESS;
  513. status = BdaFindContextEntry( &FilterContextList,
  514. pKSFilter,
  515. (PVOID *) ppFilterCtx
  516. );
  517. return status;
  518. }
  519. /*
  520. ** BdaDeleteFilterContext()
  521. **
  522. ** Deletes a BDA Filter Context.
  523. **
  524. ** Arguments:
  525. **
  526. **
  527. ** Returns:
  528. **
  529. **
  530. **
  531. ** Side Effects: none
  532. */
  533. STDMETHODIMP_(NTSTATUS)
  534. BdaDeleteFilterContext(
  535. PVOID pvReference
  536. )
  537. {
  538. NTSTATUS status = STATUS_SUCCESS;
  539. ULONG uliPath;
  540. PBDA_FILTER_CONTEXT pFilterCtx;
  541. status = BdaGetFilterContext( (PKSFILTER) pvReference, &pFilterCtx);
  542. if (status == STATUS_SUCCESS)
  543. {
  544. BdaDestructFilterContext( pFilterCtx);
  545. }
  546. status = BdaDeleteContextEntry( &FilterContextList,
  547. pvReference
  548. );
  549. return status;
  550. }
  551. /*
  552. ** BdaGetControllingPinType()
  553. **
  554. **
  555. **
  556. ** Arguments:
  557. **
  558. **
  559. ** Returns:
  560. **
  561. **
  562. **
  563. ** Side Effects: none
  564. */
  565. STDMETHODIMP_(NTSTATUS)
  566. BdaGetControllingPinType(
  567. ULONG ulNodeType,
  568. ULONG ulInputPinType,
  569. ULONG ulOutputPinType,
  570. PBDA_FILTER_CONTEXT pFilterCtx,
  571. PULONG pulControllingPinType
  572. )
  573. {
  574. NTSTATUS status = STATUS_NOT_FOUND;
  575. ULONG ulControllingPinType;
  576. ULONG uliPath;
  577. const KSFILTER_DESCRIPTOR * pKSFilterDescriptor;
  578. ASSERT( pFilterCtx);
  579. ASSERT( pFilterCtx->pBdaFilterTemplate);
  580. ASSERT( pFilterCtx->pBdaFilterTemplate->pFilterDescriptor);
  581. if ( !pFilterCtx
  582. || !pFilterCtx->pBdaFilterTemplate
  583. || !pFilterCtx->pBdaFilterTemplate->pFilterDescriptor
  584. )
  585. {
  586. status = STATUS_INVALID_PARAMETER;
  587. goto errExit;
  588. }
  589. if ( !pFilterCtx->ulcPathInfo
  590. || !pFilterCtx->argpPathInfo
  591. || !pFilterCtx->pBdaFilterTemplate->pFilterDescriptor->Connections
  592. )
  593. {
  594. goto errExit;
  595. }
  596. pKSFilterDescriptor = pFilterCtx->pBdaFilterTemplate->pFilterDescriptor;
  597. for (uliPath = 0; uliPath < pFilterCtx->ulcPathInfo; uliPath++)
  598. {
  599. PBDA_PATH_INFO pPathInfo;
  600. ULONG uliPathEntry;
  601. pPathInfo = pFilterCtx->argpPathInfo[uliPath];
  602. if ( !pPathInfo
  603. || (pPathInfo->ulInputPin != ulInputPinType)
  604. || (pPathInfo->ulOutputPin != ulOutputPinType)
  605. )
  606. {
  607. // This is not the path for this pin pair.
  608. //
  609. continue;
  610. }
  611. // Search the Path for the given node type.
  612. //
  613. ulControllingPinType = ulInputPinType;
  614. for ( uliPathEntry = 0
  615. ; uliPathEntry < pPathInfo->ulcPathEntries
  616. ; uliPathEntry++
  617. )
  618. {
  619. ULONG uliConnection;
  620. // If we encounter topology joint then switch the controlling
  621. // pin to be the output pin.
  622. //
  623. if (pPathInfo->rgPathEntries[uliPathEntry].fJoint)
  624. {
  625. ulControllingPinType = ulOutputPinType;
  626. }
  627. uliConnection = pPathInfo->rgPathEntries[uliPathEntry].uliConnection;
  628. if (pKSFilterDescriptor->Connections[uliConnection].ToNode == ulNodeType)
  629. {
  630. // We found the controlling pin type for the node type.
  631. // Indicate success and set the output parameter.
  632. //
  633. status = STATUS_SUCCESS;
  634. *pulControllingPinType = ulControllingPinType;
  635. break;
  636. }
  637. }
  638. if (uliPathEntry < pPathInfo->ulcPathEntries)
  639. {
  640. // We found the controlling pin type for the node type.
  641. //
  642. break;
  643. }
  644. }
  645. errExit:
  646. return status;
  647. }
  648. /*
  649. ** BdaFilterInitTopologyData()
  650. **
  651. ** Initializes the common BDA filter context's topology info.
  652. **
  653. ** Arguments:
  654. **
  655. **
  656. ** Returns:
  657. **
  658. **
  659. **
  660. ** Side Effects: none
  661. */
  662. STDMETHODIMP_(NTSTATUS)
  663. BdaFilterInitTopologyData(
  664. PBDA_FILTER_CONTEXT pFilterCtx
  665. )
  666. {
  667. NTSTATUS status = STATUS_SUCCESS;
  668. ULONG ulcTemplateNodes;
  669. PBDA_NODE_CONTROL_INFO pNodeControlInfo = NULL;
  670. ASSERT( pFilterCtx);
  671. ASSERT( pFilterCtx->pKSFilter);
  672. ASSERT( pFilterCtx->pBdaFilterTemplate);
  673. ASSERT( pFilterCtx->pBdaFilterTemplate->pFilterDescriptor);
  674. if ( !pFilterCtx
  675. || !pFilterCtx->pBdaFilterTemplate
  676. || !pFilterCtx->pBdaFilterTemplate->pFilterDescriptor
  677. || !pFilterCtx->pKSFilter
  678. )
  679. {
  680. status = STATUS_INVALID_PARAMETER;
  681. goto errExit;
  682. }
  683. #ifdef REMOVE
  684. ulcTemplateNodes
  685. = pFilterCtx->pBdaFilterTemplate->pFilterDescriptor->NodeDescriptorsCount;
  686. if (ulcTemplateNodes)
  687. {
  688. PKSNODE_DESCRIPTOR pCurNode;
  689. ULONG uliNode;
  690. ASSERT( pFilterCtx->pBdaFilterTemplate->pFilterDescriptor->NodeDescriptors);
  691. ASSERT( pFilterCtx->pBdaFilterTemplate->pFilterDescriptor->NodeDescriptorSize);
  692. // Allocate an array of node control info structures
  693. //
  694. pNodeControlInfo = ExAllocatePool(
  695. NonPagedPool,
  696. ulcTemplateNodes * sizeof( BDA_NODE_CONTROL_INFO)
  697. );
  698. if (!pNodeControlInfo)
  699. {
  700. status = STATUS_NO_MEMORY;
  701. goto errExit;
  702. }
  703. RtlZeroMemory( pNodeControlInfo,
  704. ulcTemplateNodes * sizeof( BDA_NODE_CONTROL_INFO)
  705. );
  706. // Add the allocation to the KS Filter's object bag so that it
  707. // will be freed on filter destruction.
  708. //
  709. status = KsAddItemToObjectBag( pFilterCtx->pKSFilter->Bag,
  710. pNodeControlInfo,
  711. NULL
  712. );
  713. // Point the BDA Filter Context at the node control info.
  714. //
  715. pFilterCtx->argNodeControlInfo = pNodeControlInfo;
  716. // Determine the contolling pin type for each node type and fill
  717. // it in to the node control array
  718. //
  719. for ( uliNode = 0
  720. ; uliNode < ulcTemplateNodes
  721. ; uliNode++, pNodeControlInfo++
  722. )
  723. {
  724. // BdaSup.sys always uses the index of the node descriptor as
  725. // the node type.
  726. //
  727. pNodeControlInfo->ulNodeType = uliNode;
  728. // Determine which template pin type controls this node type.
  729. //
  730. status = BdaGetControllingPinType(
  731. uliNode,
  732. pFilterCtx->pBdaFilterTemplate,
  733. &pNodeControlInfo->ulControllingPinType
  734. );
  735. if (status != STATUS_SUCCESS)
  736. {
  737. goto errExit;
  738. }
  739. // Add the node control info as we determine it.
  740. //
  741. pFilterCtx->ulcNodeControlInfo++;
  742. }
  743. }
  744. #endif // REMOVE
  745. errExit:
  746. return status;
  747. }
  748. /*
  749. ** BdaAddPinFactoryContext()
  750. **
  751. ** Adds pin factory information to the array of pin factory context
  752. ** structures for this filter instance. It will enlarge the array
  753. ** if necessary.
  754. ** NOTE! Since the array is an array of structure NOT pointers to
  755. ** structures, AND since the array can be moved, one should NOT keep
  756. ** pointers to the pin factory context entries.
  757. **
  758. ** Arguments:
  759. **
  760. **
  761. ** Returns:
  762. **
  763. **
  764. **
  765. ** Side Effects: none
  766. */
  767. STDMETHODIMP_(NTSTATUS)
  768. BdaCreatePinFactoryContext(
  769. PKSFILTER pKSFilter,
  770. PBDA_FILTER_CONTEXT pFilterCtx,
  771. ULONG uliPinId,
  772. ULONG ulPinType
  773. )
  774. {
  775. NTSTATUS status = STATUS_SUCCESS;
  776. // Add the Pin Factory info to the filter context.
  777. //
  778. if (uliPinId >= pFilterCtx->ulcPinFactoriesMax)
  779. {
  780. // If there isn't enough room then add more.
  781. //
  782. PBDA_PIN_FACTORY_CONTEXT argNewPinCtx = NULL;
  783. PVOID pvTemp;
  784. ULONG ulcPinFactoriesMax;
  785. ulcPinFactoriesMax = uliPinId + BDA_PIN_STORAGE_INCREMENT;
  786. argNewPinCtx = ExAllocatePool(
  787. NonPagedPool,
  788. ulcPinFactoriesMax * sizeof(BDA_PIN_FACTORY_CONTEXT)
  789. );
  790. if (!argNewPinCtx)
  791. {
  792. status = STATUS_NO_MEMORY;
  793. goto errExit;
  794. }
  795. if (pFilterCtx->argPinFactoryCtx)
  796. {
  797. // argNewPinCtx, pFilterCtx->argPinFactoryCtx are big enough (allocated in this file)
  798. RtlMoveMemory( argNewPinCtx,
  799. pFilterCtx->argPinFactoryCtx,
  800. pFilterCtx->ulcPinFactoriesMax * sizeof(BDA_PIN_FACTORY_CONTEXT)
  801. );
  802. }
  803. KsAddItemToObjectBag( pKSFilter->Bag,
  804. argNewPinCtx,
  805. NULL
  806. );
  807. pvTemp = pFilterCtx->argPinFactoryCtx;
  808. pFilterCtx->argPinFactoryCtx = argNewPinCtx;
  809. pFilterCtx->ulcPinFactoriesMax = ulcPinFactoriesMax;
  810. KsRemoveItemFromObjectBag( pKSFilter->Bag,
  811. pvTemp,
  812. TRUE
  813. );
  814. }
  815. // Fill in the pin factory context information.
  816. //
  817. pFilterCtx->argPinFactoryCtx[uliPinId].ulPinType = ulPinType;
  818. pFilterCtx->argPinFactoryCtx[uliPinId].ulPinFactoryId = uliPinId;
  819. if (uliPinId >= pFilterCtx->ulcPinFactories)
  820. {
  821. pFilterCtx->ulcPinFactories = uliPinId + 1;
  822. }
  823. errExit:
  824. return status;
  825. }
  826. /*
  827. ** BdaInitFilter()
  828. **
  829. ** Creates a BDA filter context for use by BdaCreatePinFactory etc.
  830. **
  831. ** Arguments:
  832. **
  833. **
  834. ** Returns:
  835. **
  836. **
  837. **
  838. ** Side Effects: none
  839. */
  840. STDMETHODIMP_(NTSTATUS)
  841. BdaInitFilter(
  842. PKSFILTER pKSFilter,
  843. const BDA_FILTER_TEMPLATE * pBdaFilterTemplate
  844. )
  845. {
  846. NTSTATUS status = STATUS_SUCCESS;
  847. PBDA_FILTER_FACTORY_CONTEXT pFilterFactoryCtx = NULL;
  848. PBDA_FILTER_CONTEXT pFilterCtx = NULL;
  849. PKSFILTERFACTORY pKSFilterFactory = NULL;
  850. ULONG ulcPinFactoriesMax;
  851. const KSFILTER_DESCRIPTOR * pInitialFilterDescriptor = NULL;
  852. status = BdaFindContextEntry( &FilterContextList,
  853. pKSFilter,
  854. (PVOID *) &pFilterCtx
  855. );
  856. if (NT_SUCCESS( status))
  857. {
  858. status = STATUS_SHARING_VIOLATION;
  859. goto errExit;
  860. }
  861. if (status != STATUS_NOT_FOUND)
  862. {
  863. goto errExit;
  864. }
  865. // Get the filter factory context so that we can determine
  866. // the initial pin list.
  867. //
  868. pKSFilterFactory = KsFilterGetParentFilterFactory( pKSFilter);
  869. ASSERT( pKSFilterFactory);
  870. if (!pKSFilterFactory)
  871. {
  872. status = STATUS_INVALID_DEVICE_STATE;
  873. goto errExit;
  874. }
  875. status = BdaFindContextEntry( &FilterFactoryContextList,
  876. pKSFilterFactory,
  877. (PVOID *) &pFilterFactoryCtx
  878. );
  879. if (!NT_SUCCESS( status))
  880. {
  881. goto errExit;
  882. }
  883. if (!pFilterFactoryCtx)
  884. {
  885. status = STATUS_INVALID_DEVICE_STATE;
  886. goto errExit;
  887. }
  888. pInitialFilterDescriptor = pFilterFactoryCtx->pInitialFilterDescriptor;
  889. // Create a BDA filter context and put it in the list so we can
  890. // find it when BDA calls are made relative to the filter.
  891. //
  892. status = BdaCreateFilterContext( pKSFilter, &pFilterCtx);
  893. if (status != STATUS_SUCCESS)
  894. {
  895. goto errExit;
  896. }
  897. // Point the BDA filter context at the template topology for the
  898. // filter.
  899. //
  900. if (pBdaFilterTemplate)
  901. {
  902. pFilterCtx->pBdaFilterTemplate = pBdaFilterTemplate;
  903. }
  904. else
  905. {
  906. pFilterCtx->pBdaFilterTemplate
  907. = pFilterFactoryCtx->pBdaFilterTemplate;
  908. }
  909. // Expand the template topology information into a list
  910. // of paths keyed by the input-output pin type pair.
  911. //
  912. status = BdaCreateTemplatePaths( pFilterCtx->pBdaFilterTemplate,
  913. &pFilterCtx->ulcPathInfo,
  914. &pFilterCtx->argpPathInfo
  915. );
  916. if (!NT_SUCCESS( status))
  917. {
  918. goto errExit;
  919. }
  920. //$REVIEW - Should we allow filters with no input-output paths?
  921. //
  922. ASSERT( pFilterCtx->ulcPathInfo);
  923. ASSERT( pFilterCtx->argpPathInfo);
  924. // Allocate space for the Pin Factory context information
  925. //
  926. ulcPinFactoriesMax = pBdaFilterTemplate->pFilterDescriptor->PinDescriptorsCount;
  927. ulcPinFactoriesMax += BDA_PIN_STORAGE_INCREMENT;
  928. pFilterCtx->argPinFactoryCtx
  929. = ExAllocatePool( NonPagedPool,
  930. ulcPinFactoriesMax * sizeof( BDA_PIN_FACTORY_CONTEXT)
  931. );
  932. if (!pFilterCtx->argPinFactoryCtx)
  933. {
  934. status = STATUS_NO_MEMORY;
  935. goto errExit;
  936. }
  937. pFilterCtx->ulcPinFactories = 0;
  938. pFilterCtx->ulcPinFactoriesMax = ulcPinFactoriesMax;
  939. // Loop through each initial pin descriptor and fill in the pin
  940. // context info.
  941. //
  942. if (pInitialFilterDescriptor && pInitialFilterDescriptor->PinDescriptors)
  943. {
  944. ULONG ulcbPinDescriptor;
  945. ULONG uliPinType;
  946. if (pInitialFilterDescriptor->PinDescriptorsCount > pFilterCtx->ulcPinFactoriesMax)
  947. {
  948. status = STATUS_INVALID_DEVICE_STATE;
  949. goto errExit;
  950. }
  951. ulcbPinDescriptor = pInitialFilterDescriptor->PinDescriptorSize;
  952. for ( uliPinType = 0
  953. ; uliPinType < pInitialFilterDescriptor->PinDescriptorsCount
  954. ; uliPinType++
  955. )
  956. {
  957. ULONG ulPinId;
  958. // It is a BDA requirement that the index of all pins listed in the initial
  959. // filter descriptor correspond to the index of its pin type
  960. // in the BDA Template Descriptor.
  961. //
  962. status = BdaCreatePin( pKSFilter,
  963. uliPinType,
  964. &ulPinId
  965. );
  966. if (status != STATUS_SUCCESS)
  967. {
  968. goto errExit;
  969. }
  970. //
  971. // We do not "CreateTopology" on the initial pins. The
  972. // initial pins are usually only input pins. The Network
  973. // Provider will create output pins and "CreateTopology".
  974. //
  975. }
  976. }
  977. errExit:
  978. return status;
  979. }
  980. /*
  981. ** BdaUninitFilter()
  982. **
  983. ** Deletes the BDA filter context for use by BdaCreatePinFactory etc.
  984. **
  985. ** Arguments:
  986. **
  987. **
  988. ** Returns:
  989. **
  990. **
  991. **
  992. ** Side Effects: none
  993. */
  994. STDMETHODIMP_(NTSTATUS)
  995. BdaUninitFilter(
  996. PKSFILTER pKSFilter
  997. )
  998. {
  999. NTSTATUS status = STATUS_SUCCESS;
  1000. #ifdef NO_KS_OBJECT_BAG
  1001. status = BdaDeleteContextEntry( &FilterContextList,
  1002. pKSFilter
  1003. );
  1004. if (!NT_SUCCESS( status))
  1005. {
  1006. goto errExit;
  1007. }
  1008. errExit:
  1009. #endif // def NO_KS_OBJECT_BAG
  1010. return status;
  1011. }
  1012. /*
  1013. ** BdaCreateFilterFactoryEx()
  1014. **
  1015. ** Initializes the common BDA filter context.
  1016. **
  1017. ** Arguments:
  1018. **
  1019. **
  1020. ** Returns:
  1021. **
  1022. **
  1023. **
  1024. ** Side Effects: none
  1025. */
  1026. STDMETHODIMP_(NTSTATUS)
  1027. BdaCreateFilterFactoryEx(
  1028. PKSDEVICE pKSDevice,
  1029. const KSFILTER_DESCRIPTOR * pInitialFilterDescriptor,
  1030. const BDA_FILTER_TEMPLATE * pBdaFilterTemplate,
  1031. PKSFILTERFACTORY * ppKSFilterFactory
  1032. )
  1033. {
  1034. NTSTATUS status = STATUS_SUCCESS;
  1035. PBDA_FILTER_FACTORY_CONTEXT pFilterFactoryCtx = NULL;
  1036. PKSFILTERFACTORY pKSFilterFactory = NULL;
  1037. PKSFILTER_DESCRIPTOR pFilterDescriptor = NULL;
  1038. PKSAUTOMATION_TABLE pNewAutomationTable = NULL;
  1039. ASSERT( pKSDevice);
  1040. if (!pKSDevice)
  1041. {
  1042. status = STATUS_INVALID_PARAMETER;
  1043. goto errExit;
  1044. }
  1045. ASSERT( pInitialFilterDescriptor);
  1046. if (!pInitialFilterDescriptor)
  1047. {
  1048. status = STATUS_INVALID_PARAMETER;
  1049. goto errExit;
  1050. }
  1051. ASSERT( pBdaFilterTemplate);
  1052. if (!pBdaFilterTemplate)
  1053. {
  1054. status = STATUS_INVALID_PARAMETER;
  1055. goto errExit;
  1056. }
  1057. // Create a copy of the filter factory descriptor information and
  1058. // remove any pins and connections. These will be added when
  1059. // the filter is initialized by BDAInitFilter.
  1060. //
  1061. pFilterDescriptor = ExAllocatePool( NonPagedPool,
  1062. sizeof( KSFILTER_DESCRIPTOR)
  1063. );
  1064. if (!pFilterDescriptor)
  1065. {
  1066. status = STATUS_NO_MEMORY;
  1067. goto errExit;
  1068. }
  1069. *pFilterDescriptor = *pInitialFilterDescriptor;
  1070. pFilterDescriptor->PinDescriptorsCount = 0;
  1071. pFilterDescriptor->PinDescriptors = NULL;
  1072. pFilterDescriptor->NodeDescriptorsCount = 0;
  1073. pFilterDescriptor->NodeDescriptors = NULL;
  1074. pFilterDescriptor->ConnectionsCount = 0;
  1075. pFilterDescriptor->Connections = NULL;
  1076. status = KsMergeAutomationTables(
  1077. &pNewAutomationTable,
  1078. (PKSAUTOMATION_TABLE) (pFilterDescriptor->AutomationTable),
  1079. (PKSAUTOMATION_TABLE) &BdaDefaultFilterAutomation,
  1080. NULL
  1081. );
  1082. if (status != STATUS_SUCCESS)
  1083. {
  1084. goto errExit;
  1085. }
  1086. if (!pNewAutomationTable)
  1087. {
  1088. status = STATUS_NO_MEMORY;
  1089. goto errExit;
  1090. }
  1091. pFilterDescriptor->AutomationTable = pNewAutomationTable;
  1092. //$BUG - Check Filter Factory Dispatch for Filter Close. If none
  1093. //$BUG - we must add BdaDeleteFilterFactory to clean up.
  1094. // Create the KSFilterFactory
  1095. //
  1096. status = KsCreateFilterFactory(
  1097. pKSDevice->FunctionalDeviceObject,
  1098. pFilterDescriptor,
  1099. NULL, // RefString
  1100. NULL, // SecurityDescriptor
  1101. 0, // CreateItemFlags
  1102. NULL, // SleepCallback
  1103. NULL, // WakeCallback
  1104. &pKSFilterFactory
  1105. );
  1106. if ((status != STATUS_SUCCESS) || !pKSFilterFactory)
  1107. {
  1108. goto errExit;
  1109. }
  1110. // Add our copy of the Filter Factory's new automation table to the
  1111. // KSFilterFactory's object bag. This insures the memory will
  1112. // be freed when the filter factory is destroyed.
  1113. //
  1114. if ( pNewAutomationTable
  1115. && (pNewAutomationTable != &BdaDefaultFilterAutomation)
  1116. )
  1117. {
  1118. KsAddItemToObjectBag( pKSFilterFactory->Bag,
  1119. pNewAutomationTable,
  1120. NULL
  1121. );
  1122. }
  1123. pNewAutomationTable = NULL;
  1124. // Add our copy of the Filter Factory's descriptor to the
  1125. // KSFilterFactory's object bag. This insures the memory will
  1126. // be freed when the filter factory is destroyed.
  1127. //
  1128. KsAddItemToObjectBag( pKSFilterFactory->Bag,
  1129. pFilterDescriptor,
  1130. NULL
  1131. );
  1132. pFilterDescriptor = NULL;
  1133. // Merge our default filter automation table onto the filter
  1134. // factory descriptor
  1135. //
  1136. status = KsEdit( pKSFilterFactory,
  1137. &(pKSFilterFactory->FilterDescriptor->AutomationTable),
  1138. 'SadB'
  1139. );
  1140. if (status != STATUS_SUCCESS)
  1141. {
  1142. goto errExit;
  1143. }
  1144. // Create a filter factory context for BdaSup to use.
  1145. //
  1146. status = BdaCreateFilterFactoryContext( pKSFilterFactory,
  1147. &pFilterFactoryCtx
  1148. );
  1149. if ((status != STATUS_SUCCESS) || !pFilterFactoryCtx)
  1150. {
  1151. KsDeleteFilterFactory( pKSFilterFactory);
  1152. goto errExit;
  1153. }
  1154. // Allow for the filter factory to use a default filter template
  1155. // topology when it creates a filter
  1156. //
  1157. //$REVIEW
  1158. pFilterFactoryCtx->pInitialFilterDescriptor = pInitialFilterDescriptor;
  1159. pFilterFactoryCtx->pBdaFilterTemplate = pBdaFilterTemplate;
  1160. pFilterFactoryCtx->pKSFilterFactory = pKSFilterFactory;
  1161. if (ppKSFilterFactory)
  1162. {
  1163. *ppKSFilterFactory = pKSFilterFactory;
  1164. }
  1165. errExit:
  1166. if (pFilterDescriptor)
  1167. {
  1168. ExFreePool( pFilterDescriptor);
  1169. pFilterDescriptor = NULL;
  1170. }
  1171. if ( pNewAutomationTable
  1172. && (pNewAutomationTable != &BdaDefaultFilterAutomation)
  1173. )
  1174. {
  1175. ExFreePool( pNewAutomationTable);
  1176. pNewAutomationTable = NULL;
  1177. }
  1178. return status;
  1179. }
  1180. /*
  1181. ** BdaCreateFilterFactory()
  1182. **
  1183. ** Initializes the common BDA filter context.
  1184. **
  1185. ** Arguments:
  1186. **
  1187. **
  1188. ** Returns:
  1189. **
  1190. **
  1191. **
  1192. ** Side Effects: none
  1193. */
  1194. STDMETHODIMP_(NTSTATUS)
  1195. BdaCreateFilterFactory(
  1196. PKSDEVICE pKSDevice,
  1197. const KSFILTER_DESCRIPTOR * pInitialFilterDescriptor,
  1198. const BDA_FILTER_TEMPLATE * pBdaFilterTemplate
  1199. )
  1200. {
  1201. NTSTATUS Status = STATUS_SUCCESS;
  1202. Status = BdaCreateFilterFactoryEx( pKSDevice,
  1203. pInitialFilterDescriptor,
  1204. pBdaFilterTemplate,
  1205. NULL
  1206. );
  1207. return Status;
  1208. }
  1209. /*
  1210. ** BdaFilterFactoryUpdateCacheData()
  1211. **
  1212. ** Updates the pin data cache for the given filter factory.
  1213. ** The function will update the cached information for all pin factories
  1214. ** exposed by the given filter factory.
  1215. **
  1216. ** If the option filter descriptor is given, the function will update
  1217. ** the pin data cache for all pins listed in the given filter descriptor
  1218. ** instead of those in the filter factory.
  1219. **
  1220. ** Drivers will call this to update the pin data cache for all
  1221. ** pins that may be exposed by the filter factory. The driver will
  1222. ** provide a filter descriptor listing pins that are not initially exposed
  1223. ** by the filter factory (this is usually the same as the template filter
  1224. ** descriptor).
  1225. **
  1226. ** Arguments:
  1227. **
  1228. **
  1229. ** Returns:
  1230. **
  1231. **
  1232. **
  1233. ** Side Effects: none
  1234. */
  1235. STDMETHODIMP_(NTSTATUS)
  1236. BdaFilterFactoryUpdateCacheData(
  1237. IN PKSFILTERFACTORY pFilterFactory,
  1238. IN const KSFILTER_DESCRIPTOR * pFilterDescriptor OPTIONAL
  1239. )
  1240. {
  1241. NTSTATUS Status = STATUS_SUCCESS;
  1242. Status = KsFilterFactoryUpdateCacheData( pFilterFactory,
  1243. pFilterDescriptor
  1244. );
  1245. return Status;
  1246. }
  1247. /*
  1248. ** BdaSyncTopology()
  1249. **
  1250. ** This routine updates the existing topology to complete all
  1251. ** Pending topology changes.
  1252. **
  1253. ** Arguments:
  1254. **
  1255. **
  1256. ** Returns:
  1257. **
  1258. **
  1259. **
  1260. ** Side Effects: none
  1261. */
  1262. STDMETHODIMP_(NTSTATUS)
  1263. BdaSyncTopology(
  1264. PKSFILTER pKSFilter
  1265. )
  1266. {
  1267. NTSTATUS Status = STATUS_SUCCESS;
  1268. //$BUG Implement topology sync.
  1269. return STATUS_NOT_IMPLEMENTED;
  1270. }
  1271. // -------------------------------------------------------------------
  1272. // BDA Filter Global Property Set functions
  1273. // -------------------------------------------------------------------
  1274. /*
  1275. ** BdaPropertyNodeTypes ()
  1276. **
  1277. ** Returns a list of ULONGS.
  1278. **
  1279. ** Arguments:
  1280. **
  1281. **
  1282. ** Returns:
  1283. **
  1284. ** Side Effects: none
  1285. */
  1286. STDMETHODIMP_(NTSTATUS)
  1287. BdaPropertyNodeTypes(
  1288. IN PIRP Irp,
  1289. IN PKSPROPERTY Property,
  1290. OUT ULONG * pulProperty
  1291. )
  1292. {
  1293. NTSTATUS status = STATUS_SUCCESS;
  1294. PKSFILTER pKSFilter;
  1295. PBDA_FILTER_CONTEXT pFilterCtx;
  1296. const KSFILTER_DESCRIPTOR * pTemplateDesc;
  1297. ASSERT( Irp);
  1298. if (!Irp)
  1299. {
  1300. status = STATUS_INVALID_PARAMETER;
  1301. goto errExit;
  1302. }
  1303. ASSERT( Property);
  1304. if (!Property)
  1305. {
  1306. status = STATUS_INVALID_PARAMETER;
  1307. goto errExit;
  1308. }
  1309. pKSFilter = KsGetFilterFromIrp( Irp);
  1310. status = BdaGetFilterContext( pKSFilter, &pFilterCtx);
  1311. if (status != STATUS_SUCCESS)
  1312. {
  1313. goto errExit;
  1314. }
  1315. ASSERT( pFilterCtx);
  1316. ASSERT( pFilterCtx->pBdaFilterTemplate);
  1317. pTemplateDesc = pFilterCtx->pBdaFilterTemplate->pFilterDescriptor;
  1318. ASSERT( pTemplateDesc);
  1319. ASSERT( pTemplateDesc->NodeDescriptorSize == sizeof( KSNODE_DESCRIPTOR));
  1320. if (pulProperty)
  1321. {
  1322. ULONG uliNodeDesc;
  1323. if (OutputBufferLenFromIrp(Irp) < pTemplateDesc->NodeDescriptorsCount * sizeof(ULONG))
  1324. return STATUS_BUFFER_TOO_SMALL;
  1325. for ( uliNodeDesc = 0
  1326. ; uliNodeDesc < pTemplateDesc->NodeDescriptorsCount
  1327. ; uliNodeDesc++, pulProperty++
  1328. )
  1329. {
  1330. // For this implementation, the NodeType is just the
  1331. // index into the NodeDescriptor table.
  1332. //
  1333. *pulProperty = uliNodeDesc;
  1334. }
  1335. Irp->IoStatus.Information = uliNodeDesc * sizeof( ULONG);
  1336. }
  1337. else
  1338. {
  1339. status = STATUS_MORE_ENTRIES;
  1340. // If there is no place to put the property then just
  1341. // return the data size.
  1342. //
  1343. Irp->IoStatus.Information
  1344. = pTemplateDesc->NodeDescriptorsCount * sizeof( ULONG);
  1345. }
  1346. errExit:
  1347. return status;
  1348. }
  1349. /*
  1350. ** BdaPropertyNodeDescriptors ()
  1351. **
  1352. ** Returns a list of GUIDS. The index of the GUID in the list
  1353. ** corresponds to the Node type.
  1354. **
  1355. ** Arguments:
  1356. **
  1357. **
  1358. ** Returns:
  1359. **
  1360. ** Side Effects: none
  1361. */
  1362. STDMETHODIMP_(NTSTATUS)
  1363. BdaPropertyNodeDescriptors(
  1364. IN PIRP Irp,
  1365. IN PKSPROPERTY Property,
  1366. OUT BDANODE_DESCRIPTOR * pNodeDescripterProperty
  1367. )
  1368. {
  1369. NTSTATUS status = STATUS_SUCCESS;
  1370. PKSFILTER pKSFilter;
  1371. PBDA_FILTER_CONTEXT pFilterCtx;
  1372. const KSFILTER_DESCRIPTOR * pTemplateDesc;
  1373. ULONG ulcPropertyEntries;
  1374. ULONG ulcNodes;
  1375. ASSERT( Irp);
  1376. if (!Irp)
  1377. {
  1378. status = STATUS_INVALID_PARAMETER;
  1379. goto errExit;
  1380. }
  1381. ASSERT( Property);
  1382. if (!Property)
  1383. {
  1384. status = STATUS_INVALID_PARAMETER;
  1385. goto errExit;
  1386. }
  1387. // Determine how many entries the input buffer can hold.
  1388. //
  1389. ulcPropertyEntries = OutputBufferLenFromIrp( Irp);
  1390. ulcPropertyEntries = ulcPropertyEntries / sizeof( BDANODE_DESCRIPTOR);
  1391. pKSFilter = KsGetFilterFromIrp( Irp);
  1392. status = BdaGetFilterContext( pKSFilter, &pFilterCtx);
  1393. if (status != STATUS_SUCCESS)
  1394. {
  1395. goto errExit;
  1396. }
  1397. ASSERT( pFilterCtx);
  1398. if ( !pFilterCtx
  1399. || !pFilterCtx->pBdaFilterTemplate
  1400. )
  1401. {
  1402. status = STATUS_INVALID_DEVICE_STATE;
  1403. goto errExit;
  1404. }
  1405. pTemplateDesc = pFilterCtx->pBdaFilterTemplate->pFilterDescriptor;
  1406. ASSERT( pTemplateDesc);
  1407. if (!pTemplateDesc)
  1408. {
  1409. status = STATUS_INVALID_DEVICE_STATE;
  1410. goto errExit;
  1411. }
  1412. ASSERT( pTemplateDesc->NodeDescriptorSize == sizeof( KSNODE_DESCRIPTOR));
  1413. // Handle the case of a NULL NodeDesriptor array as 0 nodes.
  1414. //
  1415. if (!pTemplateDesc->NodeDescriptors)
  1416. {
  1417. ulcNodes = 0;
  1418. }
  1419. else
  1420. {
  1421. ulcNodes = pTemplateDesc->NodeDescriptorsCount;
  1422. }
  1423. if (!pNodeDescripterProperty || (ulcPropertyEntries < ulcNodes))
  1424. {
  1425. status = STATUS_MORE_ENTRIES;
  1426. // If there is no place to put the property then just
  1427. // return the data size.
  1428. //
  1429. }
  1430. else
  1431. {
  1432. const KSNODE_DESCRIPTOR * pNodeDesc;
  1433. ULONG uliNodeDesc;
  1434. pNodeDesc = pTemplateDesc->NodeDescriptors;
  1435. if (pNodeDesc)
  1436. {
  1437. if (OutputBufferLenFromIrp(Irp) < ulcNodes * sizeof(BDANODE_DESCRIPTOR))
  1438. return STATUS_BUFFER_TOO_SMALL;
  1439. for ( uliNodeDesc = 0
  1440. ; uliNodeDesc < ulcNodes
  1441. ; uliNodeDesc++, pNodeDescripterProperty++
  1442. )
  1443. {
  1444. // For this implementation, the NodeType is just the
  1445. // index into the NodeDescriptor table.
  1446. //
  1447. pNodeDescripterProperty->ulBdaNodeType = uliNodeDesc;
  1448. // Fill in the function GUID for the node type.
  1449. //
  1450. if (pNodeDesc->Type)
  1451. {
  1452. pNodeDescripterProperty->guidFunction = *pNodeDesc->Type;
  1453. }
  1454. else
  1455. {
  1456. pNodeDescripterProperty->guidFunction = GUID_NULL;
  1457. }
  1458. // Fill in the GUID that represents a displayable name
  1459. // for the node type.
  1460. if (pNodeDesc->Name)
  1461. {
  1462. pNodeDescripterProperty->guidName = *pNodeDesc->Name;
  1463. }
  1464. else
  1465. {
  1466. pNodeDescripterProperty->guidName = GUID_NULL;
  1467. }
  1468. // Point at the next node descriptor
  1469. //
  1470. pNodeDesc = (const KSNODE_DESCRIPTOR *)
  1471. ((BYTE *) pNodeDesc + pTemplateDesc->NodeDescriptorSize);
  1472. }
  1473. }
  1474. }
  1475. Irp->IoStatus.Information = ulcNodes * sizeof( BDANODE_DESCRIPTOR);
  1476. errExit:
  1477. return status;
  1478. }
  1479. /*
  1480. ** BdaPropertyNodeProperties ()
  1481. **
  1482. ** Returns a list of GUIDS. The guid for each property set
  1483. ** supported by the specified node is included in the list.
  1484. **
  1485. ** Arguments:
  1486. **
  1487. **
  1488. ** Returns:
  1489. **
  1490. ** Side Effects: none
  1491. */
  1492. STDMETHODIMP_(NTSTATUS)
  1493. BdaPropertyNodeProperties(
  1494. IN PIRP Irp,
  1495. IN PKSP_NODE Property,
  1496. OUT GUID * pguidProperty
  1497. )
  1498. {
  1499. NTSTATUS status = STATUS_SUCCESS;
  1500. PKSFILTER pKSFilter;
  1501. PBDA_FILTER_CONTEXT pFilterCtx;
  1502. const KSFILTER_DESCRIPTOR * pTemplateDesc;
  1503. const KSNODE_DESCRIPTOR * pNodeDesc;
  1504. const KSAUTOMATION_TABLE* pAutomationTable;
  1505. ULONG uliNodeDesc;
  1506. ULONG ulcInterfaces;
  1507. ULONG ulcPropertyEntries;
  1508. ASSERT( Irp);
  1509. if (!Irp)
  1510. {
  1511. status = STATUS_INVALID_PARAMETER;
  1512. goto errExit;
  1513. }
  1514. ASSERT( Property);
  1515. if (!Property)
  1516. {
  1517. status = STATUS_INVALID_PARAMETER;
  1518. goto errExit;
  1519. }
  1520. // Determine how many entries the input buffer can hold.
  1521. //
  1522. ulcPropertyEntries = OutputBufferLenFromIrp( Irp);
  1523. ulcPropertyEntries = ulcPropertyEntries / sizeof( GUID);
  1524. pKSFilter = KsGetFilterFromIrp( Irp);
  1525. if (!pKSFilter)
  1526. {
  1527. status = STATUS_INVALID_PARAMETER;
  1528. goto errExit;
  1529. }
  1530. status = BdaGetFilterContext( pKSFilter, &pFilterCtx);
  1531. if (status != STATUS_SUCCESS)
  1532. {
  1533. goto errExit;
  1534. }
  1535. ASSERT( pFilterCtx);
  1536. ASSERT( pFilterCtx->pBdaFilterTemplate);
  1537. if (!pFilterCtx->pBdaFilterTemplate)
  1538. {
  1539. status = STATUS_INVALID_DEVICE_STATE;
  1540. goto errExit;
  1541. }
  1542. pTemplateDesc = pFilterCtx->pBdaFilterTemplate->pFilterDescriptor;
  1543. ASSERT( pTemplateDesc);
  1544. if (!pTemplateDesc)
  1545. {
  1546. status = STATUS_INVALID_DEVICE_STATE;
  1547. goto errExit;
  1548. }
  1549. ASSERT( pTemplateDesc->NodeDescriptorSize == sizeof( KSNODE_DESCRIPTOR));
  1550. uliNodeDesc = Property->NodeId;
  1551. if (uliNodeDesc >= pTemplateDesc->NodeDescriptorsCount)
  1552. {
  1553. status = STATUS_INVALID_PARAMETER;
  1554. goto errExit;
  1555. }
  1556. pNodeDesc = pTemplateDesc->NodeDescriptors;
  1557. ASSERT( pNodeDesc);
  1558. if (!pNodeDesc)
  1559. {
  1560. status = STATUS_INVALID_DEVICE_STATE;
  1561. goto errExit;
  1562. }
  1563. ASSERT( pTemplateDesc->NodeDescriptorSize);
  1564. pNodeDesc = (const KSNODE_DESCRIPTOR *)
  1565. ((BYTE *) pNodeDesc + uliNodeDesc * pTemplateDesc->NodeDescriptorSize);
  1566. if ( !pNodeDesc->AutomationTable
  1567. || !pNodeDesc->AutomationTable->PropertySets
  1568. )
  1569. {
  1570. ulcInterfaces = 0;
  1571. }
  1572. else
  1573. {
  1574. ulcInterfaces = pNodeDesc->AutomationTable->PropertySetsCount;
  1575. }
  1576. if (!pguidProperty || (ulcPropertyEntries < ulcInterfaces))
  1577. {
  1578. status = STATUS_MORE_ENTRIES;
  1579. // If there is no place to put the property then just
  1580. // return the data size.
  1581. //
  1582. }
  1583. else
  1584. {
  1585. ULONG uliSet;
  1586. const KSPROPERTY_SET * pPropertySet;
  1587. GUID * pguidOut;
  1588. pguidOut = pguidProperty;
  1589. pPropertySet = pNodeDesc->AutomationTable->PropertySets;
  1590. if (pPropertySet)
  1591. {
  1592. if (OutputBufferLenFromIrp(Irp) < ulcInterfaces * sizeof(GUID))
  1593. return STATUS_BUFFER_TOO_SMALL;
  1594. for ( uliSet = 0
  1595. ; uliSet < ulcInterfaces
  1596. ; uliSet++
  1597. )
  1598. {
  1599. RtlMoveMemory( pguidOut,
  1600. pPropertySet->Set,
  1601. sizeof( GUID)
  1602. );
  1603. pguidOut += 1;
  1604. pPropertySet += 1;
  1605. }
  1606. }
  1607. }
  1608. Irp->IoStatus.Information = ulcInterfaces * sizeof( GUID);
  1609. errExit:
  1610. return status;
  1611. }
  1612. /*
  1613. ** BdaPropertyNodeMethods ()
  1614. **
  1615. ** Returns a list of GUIDS. The guid for each property set
  1616. ** supported by the specified node is included in the list.
  1617. **
  1618. ** Arguments:
  1619. **
  1620. **
  1621. ** Returns:
  1622. **
  1623. ** Side Effects: none
  1624. */
  1625. STDMETHODIMP_(NTSTATUS)
  1626. BdaPropertyNodeMethods(
  1627. IN PIRP Irp,
  1628. IN PKSP_NODE Property,
  1629. OUT GUID * pguidProperty
  1630. )
  1631. {
  1632. NTSTATUS status = STATUS_SUCCESS;
  1633. PKSFILTER pKSFilter;
  1634. PBDA_FILTER_CONTEXT pFilterCtx;
  1635. const KSFILTER_DESCRIPTOR * pTemplateDesc;
  1636. const KSNODE_DESCRIPTOR * pNodeDesc;
  1637. const KSAUTOMATION_TABLE* pAutomationTable;
  1638. ULONG uliNodeDesc;
  1639. ULONG ulcInterfaces;
  1640. ASSERT( Irp);
  1641. if (!Irp)
  1642. {
  1643. status = STATUS_INVALID_PARAMETER;
  1644. goto errExit;
  1645. }
  1646. ASSERT( Property);
  1647. if (!Property)
  1648. {
  1649. status = STATUS_INVALID_PARAMETER;
  1650. goto errExit;
  1651. }
  1652. pKSFilter = KsGetFilterFromIrp( Irp);
  1653. status = BdaGetFilterContext( pKSFilter, &pFilterCtx);
  1654. if (status != STATUS_SUCCESS)
  1655. {
  1656. goto errExit;
  1657. }
  1658. ASSERT( pFilterCtx);
  1659. ASSERT( pFilterCtx->pBdaFilterTemplate);
  1660. pTemplateDesc = pFilterCtx->pBdaFilterTemplate->pFilterDescriptor;
  1661. ASSERT( pTemplateDesc);
  1662. ASSERT( pTemplateDesc->NodeDescriptorSize == sizeof( KSNODE_DESCRIPTOR));
  1663. uliNodeDesc = Property->NodeId;
  1664. if (uliNodeDesc >= pTemplateDesc->NodeDescriptorsCount)
  1665. {
  1666. status = STATUS_INVALID_PARAMETER;
  1667. goto errExit;
  1668. }
  1669. pNodeDesc = pTemplateDesc->NodeDescriptors;
  1670. ASSERT( pTemplateDesc->NodeDescriptorSize);
  1671. pNodeDesc = (const KSNODE_DESCRIPTOR *)
  1672. ((BYTE *) pNodeDesc + uliNodeDesc * pTemplateDesc->NodeDescriptorSize);
  1673. ulcInterfaces = pNodeDesc->AutomationTable->PropertySetsCount;
  1674. if (pguidProperty)
  1675. {
  1676. ULONG uliSet;
  1677. const KSMETHOD_SET * pMethodSet;
  1678. GUID * pguidOut;
  1679. pguidOut = pguidProperty;
  1680. ulcInterfaces = 0;
  1681. pMethodSet = pNodeDesc->AutomationTable->MethodSets;
  1682. if (pMethodSet)
  1683. {
  1684. if (OutputBufferLenFromIrp(Irp) < pNodeDesc->AutomationTable->MethodSetsCount * sizeof(GUID))
  1685. return STATUS_BUFFER_TOO_SMALL;
  1686. for ( uliSet = 0
  1687. ; uliSet < pNodeDesc->AutomationTable->MethodSetsCount
  1688. ; uliSet++
  1689. )
  1690. {
  1691. RtlMoveMemory( pguidOut,
  1692. pMethodSet->Set,
  1693. sizeof( GUID)
  1694. );
  1695. pguidOut += 1;
  1696. pMethodSet += 1;
  1697. ulcInterfaces += 1;
  1698. }
  1699. }
  1700. Irp->IoStatus.Information = ulcInterfaces * sizeof( GUID);
  1701. }
  1702. else
  1703. {
  1704. status = STATUS_MORE_ENTRIES;
  1705. // If there is no place to put the property then just
  1706. // return the data size.
  1707. //
  1708. Irp->IoStatus.Information = ulcInterfaces * sizeof( GUID);
  1709. }
  1710. errExit:
  1711. return status;
  1712. }
  1713. /*
  1714. ** BdaPropertyNodeEvents ()
  1715. **
  1716. ** Returns a list of GUIDS. The guid for each event set
  1717. ** supported by the specified node is included in the list.
  1718. **
  1719. ** Arguments:
  1720. **
  1721. **
  1722. ** Returns:
  1723. **
  1724. ** Side Effects: none
  1725. */
  1726. STDMETHODIMP_(NTSTATUS)
  1727. BdaPropertyNodeEvents(
  1728. IN PIRP Irp,
  1729. IN PKSP_NODE Property,
  1730. OUT GUID * pguidProperty
  1731. )
  1732. {
  1733. NTSTATUS status = STATUS_SUCCESS;
  1734. PKSFILTER pKSFilter;
  1735. PBDA_FILTER_CONTEXT pFilterCtx;
  1736. const KSFILTER_DESCRIPTOR * pTemplateDesc;
  1737. const KSNODE_DESCRIPTOR * pNodeDesc;
  1738. const KSAUTOMATION_TABLE* pAutomationTable;
  1739. ULONG uliNodeDesc;
  1740. ULONG ulcInterfaces;
  1741. ASSERT( Irp);
  1742. if (!Irp)
  1743. {
  1744. status = STATUS_INVALID_PARAMETER;
  1745. goto errExit;
  1746. }
  1747. ASSERT( Property);
  1748. if (!Property)
  1749. {
  1750. status = STATUS_INVALID_PARAMETER;
  1751. goto errExit;
  1752. }
  1753. pKSFilter = KsGetFilterFromIrp( Irp);
  1754. status = BdaGetFilterContext( pKSFilter, &pFilterCtx);
  1755. if (status != STATUS_SUCCESS)
  1756. {
  1757. goto errExit;
  1758. }
  1759. ASSERT( pFilterCtx);
  1760. ASSERT( pFilterCtx->pBdaFilterTemplate);
  1761. pTemplateDesc = pFilterCtx->pBdaFilterTemplate->pFilterDescriptor;
  1762. ASSERT( pTemplateDesc);
  1763. ASSERT( pTemplateDesc->NodeDescriptorSize == sizeof( KSNODE_DESCRIPTOR));
  1764. uliNodeDesc = Property->NodeId;
  1765. if (uliNodeDesc >= pTemplateDesc->NodeDescriptorsCount)
  1766. {
  1767. status = STATUS_INVALID_PARAMETER;
  1768. goto errExit;
  1769. }
  1770. pNodeDesc = pTemplateDesc->NodeDescriptors;
  1771. ASSERT( pTemplateDesc->NodeDescriptorSize);
  1772. pNodeDesc = (const KSNODE_DESCRIPTOR *)
  1773. ((BYTE *) pNodeDesc + uliNodeDesc * pTemplateDesc->NodeDescriptorSize);
  1774. ulcInterfaces = pNodeDesc->AutomationTable->PropertySetsCount;
  1775. if (pguidProperty)
  1776. {
  1777. ULONG uliSet;
  1778. const KSEVENT_SET * pEventSet;
  1779. GUID * pguidOut;
  1780. pguidOut = pguidProperty;
  1781. ulcInterfaces = 0;
  1782. pEventSet = pNodeDesc->AutomationTable->EventSets;
  1783. if (pEventSet)
  1784. {
  1785. if (OutputBufferLenFromIrp(Irp) < pNodeDesc->AutomationTable->EventSetsCount * sizeof(GUID))
  1786. return STATUS_BUFFER_TOO_SMALL;
  1787. for ( uliSet = 0
  1788. ; uliSet < pNodeDesc->AutomationTable->EventSetsCount
  1789. ; uliSet++
  1790. )
  1791. {
  1792. RtlMoveMemory( pguidOut,
  1793. pEventSet->Set,
  1794. sizeof( GUID)
  1795. );
  1796. pguidOut += 1;
  1797. pEventSet += 1;
  1798. ulcInterfaces += 1;
  1799. }
  1800. }
  1801. Irp->IoStatus.Information = ulcInterfaces * sizeof( GUID);
  1802. }
  1803. else
  1804. {
  1805. status = STATUS_MORE_ENTRIES;
  1806. // If there is no place to put the property then just
  1807. // return the data size.
  1808. //
  1809. Irp->IoStatus.Information = ulcInterfaces * sizeof( GUID);
  1810. }
  1811. errExit:
  1812. return status;
  1813. }
  1814. /*
  1815. ** BdaPropertyPinTypes ()
  1816. **
  1817. ** Returns a list of GUIDS. The index of the GUID in the list
  1818. ** corresponds to the Node type.
  1819. **
  1820. ** Arguments:
  1821. **
  1822. **
  1823. ** Returns:
  1824. **
  1825. ** Side Effects: none
  1826. */
  1827. STDMETHODIMP_(NTSTATUS)
  1828. BdaPropertyPinTypes(
  1829. IN PIRP Irp,
  1830. IN PKSPROPERTY Property,
  1831. OUT ULONG * pulProperty
  1832. )
  1833. {
  1834. NTSTATUS status = STATUS_SUCCESS;
  1835. PKSFILTER pKSFilter;
  1836. PBDA_FILTER_CONTEXT pFilterCtx;
  1837. const KSFILTER_DESCRIPTOR * pTemplateDesc;
  1838. const KSPIN_DESCRIPTOR_EX * pPinDesc;
  1839. ULONG uliPinDesc;
  1840. ASSERT( Irp);
  1841. if (!Irp)
  1842. {
  1843. status = STATUS_INVALID_PARAMETER;
  1844. goto errExit;
  1845. }
  1846. ASSERT( Property);
  1847. if (!Property)
  1848. {
  1849. status = STATUS_INVALID_PARAMETER;
  1850. goto errExit;
  1851. }
  1852. pKSFilter = KsGetFilterFromIrp( Irp);
  1853. status = BdaGetFilterContext( pKSFilter, &pFilterCtx);
  1854. if (status != STATUS_SUCCESS)
  1855. {
  1856. goto errExit;
  1857. }
  1858. ASSERT( pFilterCtx);
  1859. ASSERT( pFilterCtx->pBdaFilterTemplate);
  1860. pTemplateDesc = pFilterCtx->pBdaFilterTemplate->pFilterDescriptor;
  1861. ASSERT( pTemplateDesc);
  1862. ASSERT( pTemplateDesc->PinDescriptorSize == sizeof( KSPIN_DESCRIPTOR_EX));
  1863. if (pulProperty)
  1864. {
  1865. if (OutputBufferLenFromIrp(Irp) < pTemplateDesc->PinDescriptorsCount * sizeof(ULONG))
  1866. return STATUS_BUFFER_TOO_SMALL;
  1867. for ( uliPinDesc = 0
  1868. ; uliPinDesc < pTemplateDesc->PinDescriptorsCount
  1869. ; uliPinDesc++, pulProperty++
  1870. )
  1871. {
  1872. // For this implementation, the PinType is just the
  1873. // index into the PinDescriptor table.
  1874. //
  1875. *pulProperty = uliPinDesc;
  1876. }
  1877. Irp->IoStatus.Information = uliPinDesc * sizeof( ULONG);
  1878. }
  1879. else
  1880. {
  1881. status = STATUS_BUFFER_OVERFLOW;
  1882. // If there is no place to put the property then just
  1883. // return the data size.
  1884. //
  1885. Irp->IoStatus.Information
  1886. = pTemplateDesc->PinDescriptorsCount * sizeof( ULONG);
  1887. }
  1888. errExit:
  1889. return status;
  1890. }
  1891. /*
  1892. ** BdaPropertyTemplateConnections ()
  1893. **
  1894. ** Returns a list of KSTOPOLOGY_CONNECTIONS. The list of connections
  1895. ** describs how pin types and node types are connected in the template
  1896. ** topology
  1897. **
  1898. ** Arguments:
  1899. **
  1900. **
  1901. ** Returns:
  1902. **
  1903. ** Side Effects: none
  1904. */
  1905. STDMETHODIMP_(NTSTATUS)
  1906. BdaPropertyTemplateConnections(
  1907. IN PIRP Irp,
  1908. IN PKSPROPERTY Property,
  1909. OUT PKSTOPOLOGY_CONNECTION pConnectionProperty
  1910. )
  1911. {
  1912. NTSTATUS status = STATUS_SUCCESS;
  1913. PKSFILTER pKSFilter;
  1914. PBDA_FILTER_CONTEXT pFilterCtx;
  1915. const KSFILTER_DESCRIPTOR * pTemplateDesc;
  1916. const KSTOPOLOGY_CONNECTION * pConnection;
  1917. ULONG uliConnection;
  1918. ASSERT( Irp);
  1919. if (!Irp)
  1920. {
  1921. status = STATUS_INVALID_PARAMETER;
  1922. goto errExit;
  1923. }
  1924. ASSERT( Property);
  1925. if (!Property)
  1926. {
  1927. status = STATUS_INVALID_PARAMETER;
  1928. goto errExit;
  1929. }
  1930. pKSFilter = KsGetFilterFromIrp( Irp);
  1931. status = BdaGetFilterContext( pKSFilter, &pFilterCtx);
  1932. if (status != STATUS_SUCCESS)
  1933. {
  1934. goto errExit;
  1935. }
  1936. ASSERT( pFilterCtx);
  1937. ASSERT( pFilterCtx->pBdaFilterTemplate);
  1938. pTemplateDesc = pFilterCtx->pBdaFilterTemplate->pFilterDescriptor;
  1939. ASSERT( pTemplateDesc);
  1940. if (pConnectionProperty)
  1941. {
  1942. for ( uliConnection = 0, pConnection = pTemplateDesc->Connections
  1943. ; uliConnection < pTemplateDesc->ConnectionsCount
  1944. ; uliConnection++, pConnection++, pConnectionProperty++
  1945. )
  1946. {
  1947. *pConnectionProperty = *pConnection;
  1948. }
  1949. Irp->IoStatus.Information
  1950. = uliConnection * sizeof( KSTOPOLOGY_CONNECTION);
  1951. }
  1952. else
  1953. {
  1954. status = STATUS_BUFFER_OVERFLOW;
  1955. // If there is no place to put the property then just
  1956. // return the data size.
  1957. //
  1958. Irp->IoStatus.Information
  1959. = pTemplateDesc->ConnectionsCount * sizeof( KSTOPOLOGY_CONNECTION);
  1960. }
  1961. errExit:
  1962. return status;
  1963. }
  1964. /*
  1965. ** BdaPinTypeFromPinId()
  1966. **
  1967. ** Gets the ID of the pin on which to submit node properties, methods
  1968. ** and events.
  1969. **
  1970. ** Arguments:
  1971. **
  1972. **
  1973. ** Returns:
  1974. **
  1975. ** Side Effects: none
  1976. */
  1977. STDMETHODIMP_(NTSTATUS)
  1978. BdaPinTypeFromPinId(
  1979. PBDA_FILTER_CONTEXT pFilterCtx,
  1980. ULONG ulPinId,
  1981. PULONG pulPinType
  1982. )
  1983. {
  1984. NTSTATUS status = STATUS_SUCCESS;
  1985. if ( !pFilterCtx
  1986. || !pFilterCtx->argPinFactoryCtx
  1987. || (ulPinId >= pFilterCtx->ulcPinFactories)
  1988. )
  1989. {
  1990. status = STATUS_INVALID_PARAMETER;
  1991. goto errExit;
  1992. }
  1993. if (pFilterCtx->argPinFactoryCtx[ulPinId].ulPinFactoryId != ulPinId)
  1994. {
  1995. status = STATUS_NOT_FOUND;
  1996. goto errExit;
  1997. }
  1998. *pulPinType = pFilterCtx->argPinFactoryCtx[ulPinId].ulPinType;
  1999. errExit:
  2000. return status;
  2001. }
  2002. /*
  2003. ** BdaGetControllingPinId ()
  2004. **
  2005. ** Gets the ID of the pin on which to submit node properties, methods
  2006. ** and events.
  2007. **
  2008. ** Arguments:
  2009. **
  2010. **
  2011. ** Returns:
  2012. **
  2013. ** Side Effects: none
  2014. */
  2015. STDMETHODIMP_(NTSTATUS)
  2016. BdaGetControllingPinId(
  2017. PBDA_FILTER_CONTEXT pFilterCtx,
  2018. ULONG ulInputPinId,
  2019. ULONG ulOutputPinId,
  2020. ULONG ulNodeType,
  2021. PULONG pulControllingPinId
  2022. )
  2023. {
  2024. NTSTATUS status = STATUS_SUCCESS;
  2025. ULONG ulInputPinType = 0;
  2026. ULONG ulOutputPinType = -1;
  2027. ULONG ulControllingPinType = -1;
  2028. // Get the input pin type.
  2029. //
  2030. status = BdaPinTypeFromPinId( pFilterCtx,
  2031. ulInputPinId,
  2032. &ulInputPinType
  2033. );
  2034. if (status != STATUS_SUCCESS)
  2035. {
  2036. goto errExit;
  2037. }
  2038. // Get the output pin type.
  2039. //
  2040. status = BdaPinTypeFromPinId( pFilterCtx,
  2041. ulOutputPinId,
  2042. &ulOutputPinType
  2043. );
  2044. if (status != STATUS_SUCCESS)
  2045. {
  2046. goto errExit;
  2047. }
  2048. // Determine the cotnrolling pin type.
  2049. //
  2050. status = BdaGetControllingPinType( ulNodeType,
  2051. ulInputPinType,
  2052. ulOutputPinType,
  2053. pFilterCtx,
  2054. &ulControllingPinType
  2055. );
  2056. if (status != STATUS_SUCCESS)
  2057. {
  2058. goto errExit;
  2059. }
  2060. // Map the controlling pin type to the controlling pin ID.
  2061. //
  2062. if (ulControllingPinType == ulInputPinType)
  2063. {
  2064. *pulControllingPinId = ulInputPinId;
  2065. }
  2066. else if (ulControllingPinType == ulOutputPinType)
  2067. {
  2068. *pulControllingPinId = ulOutputPinId;
  2069. }
  2070. else
  2071. {
  2072. status = STATUS_NOT_FOUND;
  2073. }
  2074. errExit:
  2075. return status;
  2076. }
  2077. /*
  2078. ** BdaPropertyGetControllingPinId ()
  2079. **
  2080. ** Gets the ID of the pin on which to submit node properties, methods
  2081. ** and events.
  2082. **
  2083. ** Arguments:
  2084. **
  2085. **
  2086. ** Returns:
  2087. **
  2088. ** Side Effects: none
  2089. */
  2090. STDMETHODIMP_(NTSTATUS)
  2091. BdaPropertyGetControllingPinId(
  2092. IN PIRP Irp,
  2093. IN PKSP_BDA_NODE_PIN Property,
  2094. OUT PULONG pulControllingPinId
  2095. )
  2096. {
  2097. NTSTATUS status = STATUS_SUCCESS;
  2098. PKSFILTER pKSFilter;
  2099. PBDA_FILTER_CONTEXT pFilterCtx;
  2100. ASSERT( Irp);
  2101. if (!Irp)
  2102. {
  2103. status = STATUS_INVALID_PARAMETER;
  2104. goto errExit;
  2105. }
  2106. ASSERT( Property);
  2107. if (!Property)
  2108. {
  2109. status = STATUS_INVALID_PARAMETER;
  2110. goto errExit;
  2111. }
  2112. pKSFilter = KsGetFilterFromIrp( Irp);
  2113. status = BdaGetFilterContext( pKSFilter, &pFilterCtx);
  2114. if (status != STATUS_SUCCESS)
  2115. {
  2116. goto errExit;
  2117. }
  2118. ASSERT( pFilterCtx);
  2119. if (!pFilterCtx)
  2120. {
  2121. status = STATUS_INVALID_PARAMETER;
  2122. goto errExit;
  2123. }
  2124. if (pulControllingPinId)
  2125. {
  2126. if (OutputBufferLenFromIrp(Irp) < sizeof(ULONG))
  2127. return STATUS_BUFFER_TOO_SMALL;
  2128. status = BdaGetControllingPinId(
  2129. pFilterCtx,
  2130. Property->ulInputPinId,
  2131. Property->ulOutputPinId,
  2132. Property->ulNodeType,
  2133. pulControllingPinId
  2134. );
  2135. if (status == STATUS_NOT_FOUND)
  2136. {
  2137. // See if the pins were part of a static filter configuration.
  2138. //
  2139. //$BUG - Pins that are configured without template type information
  2140. // should always be controlled by the output pin.
  2141. //
  2142. if (Property->ulNodeType == 0)
  2143. {
  2144. *pulControllingPinId = Property->ulInputPinId;
  2145. }
  2146. else
  2147. {
  2148. *pulControllingPinId = Property->ulOutputPinId;
  2149. }
  2150. status = STATUS_SUCCESS;
  2151. }
  2152. Irp->IoStatus.Information = sizeof( ULONG);
  2153. }
  2154. else
  2155. {
  2156. status = STATUS_BUFFER_OVERFLOW;
  2157. // If there is no place to put the property then just
  2158. // return the data size.
  2159. //
  2160. Irp->IoStatus.Information = sizeof( ULONG);
  2161. }
  2162. errExit:
  2163. return status;
  2164. }
  2165. /*
  2166. ** BdaStartChanges ()
  2167. **
  2168. ** Puts the filter into change state. All changes to BDA topology
  2169. ** and properties changed after this will be in effect only after
  2170. ** CommitChanges.
  2171. **
  2172. ** Arguments:
  2173. **
  2174. **
  2175. ** Returns:
  2176. **
  2177. ** Side Effects: none
  2178. */
  2179. STDMETHODIMP_(NTSTATUS)
  2180. BdaStartChanges(
  2181. IN PIRP pIrp
  2182. )
  2183. {
  2184. ASSERT( pIrp);
  2185. if (!pIrp)
  2186. {
  2187. return STATUS_INVALID_PARAMETER;
  2188. }
  2189. return STATUS_SUCCESS;
  2190. }
  2191. /*
  2192. ** BdaCheckChanges ()
  2193. **
  2194. ** Checks the changes to BDA interfaces that have occured since the
  2195. ** last StartChanges. Returns the result that would have occurred if
  2196. ** CommitChanges had been called.
  2197. **
  2198. ** Arguments:
  2199. **
  2200. **
  2201. ** Returns:
  2202. **
  2203. ** Side Effects: none
  2204. */
  2205. STDMETHODIMP_(NTSTATUS)
  2206. BdaCheckChanges(
  2207. IN PIRP pIrp
  2208. )
  2209. {
  2210. ASSERT( pIrp);
  2211. if (!pIrp)
  2212. {
  2213. return STATUS_INVALID_PARAMETER;
  2214. }
  2215. return STATUS_SUCCESS;
  2216. }
  2217. /*
  2218. ** BdaCommitChanges ()
  2219. **
  2220. ** Checks the changes to BDA interfaces that have occured since the
  2221. ** last StartChanges.
  2222. **
  2223. ** Arguments:
  2224. **
  2225. **
  2226. ** Returns:
  2227. **
  2228. ** Side Effects: none
  2229. */
  2230. STDMETHODIMP_(NTSTATUS)
  2231. BdaCommitChanges(
  2232. IN PIRP pIrp
  2233. )
  2234. {
  2235. ASSERT( pIrp);
  2236. if (!pIrp)
  2237. {
  2238. return STATUS_INVALID_PARAMETER;
  2239. }
  2240. return STATUS_SUCCESS;
  2241. }
  2242. /*
  2243. ** BdaGetChangeState ()
  2244. **
  2245. ** Checks the changes to BDA interfaces that have occured since the
  2246. ** last StartChanges.
  2247. **
  2248. ** Arguments:
  2249. **
  2250. **
  2251. ** Returns:
  2252. **
  2253. ** Side Effects: none
  2254. */
  2255. STDMETHODIMP_(NTSTATUS)
  2256. BdaGetChangeState(
  2257. IN PIRP pIrp,
  2258. PBDA_CHANGE_STATE pChangeState
  2259. )
  2260. {
  2261. ASSERT( pIrp);
  2262. if (!pIrp)
  2263. {
  2264. return STATUS_INVALID_PARAMETER;
  2265. }
  2266. ASSERT( pChangeState);
  2267. if (!pChangeState)
  2268. {
  2269. return STATUS_INVALID_PARAMETER;
  2270. }
  2271. *pChangeState = BDA_CHANGES_COMPLETE;
  2272. return STATUS_SUCCESS;
  2273. }
  2274. /*
  2275. ** BdaMethodCreatePin ()
  2276. **
  2277. ** Creates a new pin factory for the given pin type.
  2278. **
  2279. ** Arguments:
  2280. **
  2281. **
  2282. ** Returns:
  2283. **
  2284. ** Side Effects: none
  2285. */
  2286. STDMETHODIMP_(NTSTATUS)
  2287. BdaMethodCreatePin(
  2288. IN PIRP pIrp,
  2289. IN PKSMETHOD pKSMethod,
  2290. OUT PULONG pulPinFactoryID
  2291. )
  2292. {
  2293. NTSTATUS status = STATUS_SUCCESS;
  2294. ASSERT(pIrp);
  2295. if (pIrp)
  2296. {
  2297. PKSFILTER pKSFilter;
  2298. PKSM_BDA_PIN pKSPinMethod;
  2299. ULONG ulPinId;
  2300. if (OutputBufferLenFromIrp(pIrp) < sizeof(ULONG))
  2301. return STATUS_BUFFER_TOO_SMALL;
  2302. pKSPinMethod = (PKSM_BDA_PIN) pKSMethod;
  2303. pKSFilter = KsGetFilterFromIrp( pIrp);
  2304. if (pKSFilter && pKSPinMethod)
  2305. {
  2306. status = BdaCreatePin( pKSFilter,
  2307. pKSPinMethod->PinType,
  2308. pulPinFactoryID
  2309. );
  2310. }
  2311. }
  2312. else
  2313. {
  2314. status = STATUS_INVALID_PARAMETER;
  2315. }
  2316. return status;
  2317. }
  2318. /*
  2319. ** BdaMethodDeletePin ()
  2320. **
  2321. ** Deletes the given pin factory
  2322. **
  2323. ** Arguments:
  2324. **
  2325. **
  2326. ** Returns:
  2327. **
  2328. ** Side Effects: none
  2329. */
  2330. STDMETHODIMP_(NTSTATUS)
  2331. BdaMethodDeletePin(
  2332. IN PIRP Irp,
  2333. IN PKSMETHOD Method,
  2334. OPTIONAL PVOID pvIgnored
  2335. )
  2336. {
  2337. ASSERT( Irp);
  2338. if (!Irp)
  2339. {
  2340. return STATUS_INVALID_PARAMETER;
  2341. }
  2342. return STATUS_SUCCESS;
  2343. }
  2344. /*
  2345. ** BdaPropertyGetPinControl ()
  2346. **
  2347. ** Returns a the BDA ID or BDA Template Type of the Pin.
  2348. **
  2349. ** Arguments:
  2350. **
  2351. **
  2352. ** Returns:
  2353. **
  2354. ** Side Effects: none
  2355. */
  2356. STDMETHODIMP_(NTSTATUS)
  2357. BdaPropertyGetPinControl(
  2358. IN PIRP Irp,
  2359. IN PKSPROPERTY Property,
  2360. OUT ULONG * pulProperty
  2361. )
  2362. {
  2363. NTSTATUS status = STATUS_SUCCESS;
  2364. PKSPIN pKSPin;
  2365. BDA_PIN_FACTORY_CONTEXT pinCtx;
  2366. ASSERT( Irp);
  2367. if (!Irp)
  2368. {
  2369. status = STATUS_INVALID_PARAMETER;
  2370. goto errExit;
  2371. }
  2372. ASSERT( Property);
  2373. if (!Property)
  2374. {
  2375. status = STATUS_INVALID_PARAMETER;
  2376. goto errExit;
  2377. }
  2378. pKSPin = KsGetPinFromIrp( Irp);
  2379. status = BdaGetPinFactoryContext( pKSPin, &pinCtx);
  2380. if (status != STATUS_SUCCESS)
  2381. {
  2382. goto errExit;
  2383. }
  2384. if (pulProperty)
  2385. {
  2386. Irp->IoStatus.Information = sizeof( ULONG);
  2387. switch (Property->Id)
  2388. {
  2389. case KSPROPERTY_BDA_PIN_ID:
  2390. // Return the BDA ID of this pin
  2391. //
  2392. *pulProperty = pinCtx.ulPinFactoryId;
  2393. break;
  2394. case KSPROPERTY_BDA_PIN_TYPE:
  2395. // Return the BDA Type of this pin
  2396. //
  2397. *pulProperty = pinCtx.ulPinType;
  2398. break;
  2399. default:
  2400. Irp->IoStatus.Information = 0;
  2401. status = STATUS_INVALID_PARAMETER;
  2402. ASSERT( FALSE);
  2403. }
  2404. }
  2405. else
  2406. {
  2407. status = STATUS_MORE_ENTRIES;
  2408. // If there is no place to put the property then just
  2409. // return the data size.
  2410. //
  2411. Irp->IoStatus.Information = sizeof( ULONG);
  2412. }
  2413. errExit:
  2414. return status;
  2415. }
  2416. /*
  2417. ** BdaValidateNodeProperty ()
  2418. **
  2419. ** Validates that the IRP is for a Pin and that
  2420. ** the property belongs to a node associated with that
  2421. ** Pin.
  2422. **
  2423. ** Arguments:
  2424. **
  2425. **
  2426. ** Returns:
  2427. **
  2428. ** Side Effects: none
  2429. */
  2430. STDMETHODIMP_(NTSTATUS)
  2431. BdaValidateNodeProperty(
  2432. IN PIRP pIrp,
  2433. IN PKSMETHOD pKSProperty
  2434. )
  2435. {
  2436. ASSERT( pIrp);
  2437. if (!pIrp)
  2438. {
  2439. return STATUS_INVALID_PARAMETER;
  2440. }
  2441. ASSERT( pKSProperty);
  2442. if (!pKSProperty)
  2443. {
  2444. return STATUS_INVALID_PARAMETER;
  2445. }
  2446. return STATUS_SUCCESS;
  2447. }
  2448. /*
  2449. ** BdaMethodCreateTopology ()
  2450. **
  2451. ** Creates the topology between the two given pin factories.
  2452. **
  2453. ** Arguments:
  2454. **
  2455. **
  2456. ** Returns:
  2457. **
  2458. ** Side Effects: none
  2459. */
  2460. STDMETHODIMP_(NTSTATUS)
  2461. BdaMethodCreateTopology(
  2462. IN PIRP pIrp,
  2463. IN PKSMETHOD pKSMethod,
  2464. OPTIONAL PVOID pvIgnored
  2465. )
  2466. {
  2467. NTSTATUS status = STATUS_SUCCESS;
  2468. PKSFILTER pKSFilter;
  2469. PKSM_BDA_PIN_PAIR pKSPinPairMethod;
  2470. ULONG ulPinId;
  2471. if (pIrp)
  2472. {
  2473. pKSPinPairMethod = (PKSM_BDA_PIN_PAIR) pKSMethod;
  2474. pKSFilter = KsGetFilterFromIrp( pIrp);
  2475. if (pKSFilter && pKSPinPairMethod)
  2476. {
  2477. // Obtain the KS Filter Mutex
  2478. //
  2479. //$BUG - Obtain the KS Filter Mutex
  2480. status = BdaCreateTopology( pKSFilter,
  2481. pKSPinPairMethod->InputPinId,
  2482. pKSPinPairMethod->OutputPinId
  2483. );
  2484. // Release the KS Filter Mutex
  2485. //
  2486. //$BUG - Obtain the KS Filter Mutex
  2487. }
  2488. else
  2489. {
  2490. status = STATUS_INVALID_PARAMETER;
  2491. }
  2492. }
  2493. else
  2494. {
  2495. status = STATUS_INVALID_PARAMETER;
  2496. }
  2497. return status;
  2498. }
  2499. /*
  2500. ** BdaFindPinPair()
  2501. **
  2502. ** Returns a pointer to the BDA_PIN_PAIRING that corresponds
  2503. ** to the given input and output pins.
  2504. **
  2505. ** Arguments:
  2506. **
  2507. ** pTopology Pointer to the BDA topology that contains the
  2508. ** pin pairing.
  2509. **
  2510. ** InputPinId Id of the input Pin to match
  2511. **
  2512. ** OutputPinId Id of the output Pin to match
  2513. **
  2514. ** Returns:
  2515. **
  2516. ** pPinPairing Pointer to a valid BDA Pin Pairing structure
  2517. **
  2518. ** NULL If no valid pin pairing exists with the
  2519. ** given input and output pins.
  2520. **
  2521. ** Side Effects: none
  2522. */
  2523. PBDA_PIN_PAIRING
  2524. BdaFindPinPair(
  2525. PBDA_FILTER_TEMPLATE pFilterTemplate,
  2526. ULONG InputPinId,
  2527. ULONG OutputPinId
  2528. )
  2529. {
  2530. return NULL;
  2531. }
  2532. /*
  2533. ** BdaGetPinFactoryContext()
  2534. **
  2535. ** Finds a BDA PinFactory Context that corresponds
  2536. ** to the given KS Pin Instance.
  2537. **
  2538. ** Arguments:
  2539. **
  2540. **
  2541. ** Returns:
  2542. **
  2543. **
  2544. **
  2545. ** Side Effects: none
  2546. */
  2547. STDMETHODIMP_(NTSTATUS)
  2548. BdaGetPinFactoryContext(
  2549. PKSPIN pKSPin,
  2550. PBDA_PIN_FACTORY_CONTEXT pPinFactoryCtx
  2551. )
  2552. {
  2553. NTSTATUS status = STATUS_SUCCESS;
  2554. PKSFILTER pKSFilter;
  2555. PBDA_FILTER_CONTEXT pFilterCtx = NULL;
  2556. if (!pKSPin || !pPinFactoryCtx)
  2557. {
  2558. status = STATUS_INVALID_PARAMETER;
  2559. goto errExit;
  2560. }
  2561. pKSFilter = KsPinGetParentFilter( pKSPin);
  2562. if (!pKSFilter)
  2563. {
  2564. status = STATUS_INVALID_PARAMETER;
  2565. goto errExit;
  2566. }
  2567. // Find our Filter Context so that we can look up the pin type
  2568. // in the Template Topology.
  2569. //
  2570. status = BdaGetFilterContext( pKSFilter, &pFilterCtx);
  2571. if (status != STATUS_SUCCESS)
  2572. {
  2573. goto errExit;
  2574. }
  2575. ASSERT( pFilterCtx);
  2576. if (pKSPin->Id >= pFilterCtx->ulcPinFactories)
  2577. {
  2578. status = STATUS_INVALID_PARAMETER;
  2579. goto errExit;
  2580. }
  2581. *pPinFactoryCtx = pFilterCtx->argPinFactoryCtx[pKSPin->Id];
  2582. errExit:
  2583. return status;
  2584. }
  2585. /*
  2586. ** BdaCreatePin()
  2587. **
  2588. ** Utility function creates a new pin in the given filter instance.
  2589. **
  2590. **
  2591. ** Arguments:
  2592. **
  2593. **
  2594. **
  2595. ** PinType Pin type to create.
  2596. **
  2597. ** pPinId Id of the Pin that was created.
  2598. **
  2599. ** Returns:
  2600. **
  2601. **
  2602. ** Side Effects: none
  2603. */
  2604. STDMETHODIMP_(NTSTATUS)
  2605. BdaCreatePin(
  2606. PKSFILTER pKSFilter,
  2607. ULONG ulPinType,
  2608. PULONG pulPinId
  2609. )
  2610. {
  2611. NTSTATUS status = STATUS_SUCCESS;
  2612. PBDA_FILTER_CONTEXT pFilterCtx;
  2613. PBDA_PIN_FACTORY_CONTEXT pPinFactoryCtx;
  2614. KSPIN_DESCRIPTOR_EX myKSPinDescriptorEx;
  2615. KSAUTOMATION_TABLE * pNewAutomationTable = NULL;
  2616. const KSPIN_DESCRIPTOR_EX * pKSPinDescriptorEx;
  2617. const BDA_FILTER_TEMPLATE * pBdaFilterTemplate;
  2618. const KSFILTER_DESCRIPTOR * pFilterDescriptor;
  2619. ASSERT( pulPinId);
  2620. if (!pulPinId)
  2621. {
  2622. status = STATUS_INVALID_PARAMETER;
  2623. goto errExit;
  2624. }
  2625. // Find our Filter Context so that we can look up the pin type
  2626. // in the Template Topology.
  2627. //
  2628. status = BdaGetFilterContext( pKSFilter, &pFilterCtx);
  2629. if (status != STATUS_SUCCESS)
  2630. {
  2631. goto errExit;
  2632. }
  2633. ASSERT( pFilterCtx);
  2634. // Locate this filter's Template Topology
  2635. //
  2636. if ( !pFilterCtx
  2637. || !pFilterCtx->pBdaFilterTemplate
  2638. || !pFilterCtx->pBdaFilterTemplate->pFilterDescriptor
  2639. )
  2640. {
  2641. status = STATUS_INVALID_PARAMETER;
  2642. goto errExit;
  2643. }
  2644. pFilterDescriptor = pFilterCtx->pBdaFilterTemplate->pFilterDescriptor;
  2645. // Locate the Pin Type in this filter's Template Topology
  2646. //
  2647. if (pFilterDescriptor->PinDescriptorsCount <= ulPinType)
  2648. {
  2649. status = STATUS_INVALID_PARAMETER;
  2650. goto errExit;
  2651. }
  2652. // Get the KSPIN_DESCRIPTOR_EX for this pin type
  2653. //
  2654. pKSPinDescriptorEx = pFilterDescriptor->PinDescriptors;
  2655. ASSERT( pKSPinDescriptorEx);
  2656. ASSERT( pFilterDescriptor->PinDescriptorSize);
  2657. pKSPinDescriptorEx = (const KSPIN_DESCRIPTOR_EX *)
  2658. ( (BYTE *) pKSPinDescriptorEx
  2659. + ulPinType * pFilterDescriptor->PinDescriptorSize
  2660. );
  2661. // Create a new copy of the pin descriptor so that it is easier to
  2662. // modify
  2663. //
  2664. myKSPinDescriptorEx = *pKSPinDescriptorEx;
  2665. myKSPinDescriptorEx.AutomationTable = NULL;
  2666. status = BdaAddNodeAutomationToPin( pFilterCtx,
  2667. ulPinType,
  2668. pKSFilter->Bag,
  2669. pKSPinDescriptorEx->AutomationTable,
  2670. &pNewAutomationTable
  2671. );
  2672. if (status != STATUS_SUCCESS)
  2673. {
  2674. goto errExit;
  2675. }
  2676. // Merge required properties for which BdaSup.sys provides a default
  2677. // implementation.
  2678. //
  2679. status = KsMergeAutomationTables(
  2680. &((PKSAUTOMATION_TABLE)(myKSPinDescriptorEx.AutomationTable)),
  2681. pNewAutomationTable,
  2682. (PKSAUTOMATION_TABLE) &BdaDefaultPinAutomation,
  2683. pKSFilter->Bag
  2684. );
  2685. if (status != STATUS_SUCCESS)
  2686. {
  2687. goto errExit;
  2688. }
  2689. status = KsFilterCreatePinFactory ( pKSFilter,
  2690. &myKSPinDescriptorEx,
  2691. pulPinId
  2692. );
  2693. if (status != STATUS_SUCCESS)
  2694. {
  2695. goto errExit;
  2696. }
  2697. status = BdaCreatePinFactoryContext( pKSFilter,
  2698. pFilterCtx,
  2699. *pulPinId,
  2700. ulPinType
  2701. );
  2702. errExit:
  2703. return status;
  2704. }
  2705. /*
  2706. ** BdaAddNodeAutomationToPin()
  2707. **
  2708. ** Merges the automation tables for each node type that is controlled
  2709. ** by the pin type being created into the automation table for the
  2710. ** the pin factory. This is how the automation tables for BDA
  2711. ** control nodes get linked to the controlling pin. Otherwise the
  2712. ** nodes would not be accesable.
  2713. **
  2714. **
  2715. ** Arguments:
  2716. **
  2717. **
  2718. ** pFilterCtx The BDA filter context to which the pin factory
  2719. ** belongs. Must have this to get at the template
  2720. ** topology.
  2721. **
  2722. ** ulPinType BDA Pin Type of the pin being created. Need this
  2723. ** to figure out which nodes are controlled by the
  2724. ** pin.
  2725. **
  2726. ** Returns:
  2727. ** Always returns a resulting automation table, even on error.
  2728. **
  2729. **
  2730. ** Side Effects: none
  2731. */
  2732. STDMETHODIMP_(NTSTATUS)
  2733. BdaAddNodeAutomationToPin(
  2734. PBDA_FILTER_CONTEXT pFilterCtx,
  2735. ULONG ulControllingPinType,
  2736. KSOBJECT_BAG ObjectBag,
  2737. const KSAUTOMATION_TABLE * pOriginalAutomationTable,
  2738. PKSAUTOMATION_TABLE * ppNewAutomationTable
  2739. )
  2740. {
  2741. NTSTATUS status = STATUS_SUCCESS;
  2742. const KSFILTER_DESCRIPTOR * pFilterDescriptor;
  2743. KSAUTOMATION_TABLE * pNewAutomationTable = NULL;
  2744. ULONG uliPath;
  2745. ULONG ulcNodes;
  2746. ULONG ulcbNodeDescriptor;
  2747. // Check for required parameters
  2748. //
  2749. if (!pFilterCtx || !ObjectBag)
  2750. {
  2751. status = STATUS_INVALID_PARAMETER;
  2752. goto exit;
  2753. }
  2754. if ( !pFilterCtx->ulcPathInfo
  2755. || !pFilterCtx->pBdaFilterTemplate
  2756. || !pFilterCtx->pBdaFilterTemplate->pFilterDescriptor
  2757. || !pFilterCtx->pBdaFilterTemplate->pFilterDescriptor->NodeDescriptorsCount
  2758. || !pFilterCtx->pBdaFilterTemplate->pFilterDescriptor->NodeDescriptors
  2759. )
  2760. {
  2761. goto exit;
  2762. }
  2763. pFilterDescriptor = pFilterCtx->pBdaFilterTemplate->pFilterDescriptor;
  2764. // If ulcNodeControlInfo is not zero the that array of control info
  2765. // structures must exist
  2766. //
  2767. ASSERT( pFilterCtx->argpPathInfo);
  2768. if (!pFilterCtx->argpPathInfo)
  2769. {
  2770. status = STATUS_INVALID_DEVICE_STATE;
  2771. goto exit;
  2772. }
  2773. // Initial variables used to step through the list of node descriptors
  2774. // for the filter to which this pin type belongs.
  2775. //
  2776. ulcNodes = pFilterDescriptor->NodeDescriptorsCount;
  2777. ulcbNodeDescriptor = pFilterDescriptor->NodeDescriptorSize;
  2778. // Step through each template node descriptor and, if it is controlled,
  2779. // by the given pin type, add its automation table to resulting table.
  2780. //
  2781. for ( uliPath = 0
  2782. ; uliPath < pFilterCtx->ulcPathInfo
  2783. ; uliPath++
  2784. )
  2785. {
  2786. PBDA_PATH_INFO pPathInfo;
  2787. ULONG uliPathEntry;
  2788. BOOLEAN fMergeNode = FALSE;
  2789. pPathInfo = pFilterCtx->argpPathInfo[uliPath];
  2790. // Skip paths that don't include this pin type.
  2791. //
  2792. if (pPathInfo->ulInputPin == ulControllingPinType)
  2793. {
  2794. // If the controlling pin is an input pin then we
  2795. // will start merging nodes right away and quit when
  2796. // we find a topology joint.
  2797. //
  2798. fMergeNode = TRUE;
  2799. }
  2800. else if (pPathInfo->ulOutputPin == ulControllingPinType)
  2801. {
  2802. // If the controlling pin is an output pin then we
  2803. // will not merge nodes until we find a topology
  2804. // joint.
  2805. //
  2806. fMergeNode = FALSE;
  2807. }
  2808. else
  2809. {
  2810. // The pin we're interested in isn't part of this path.
  2811. continue;
  2812. }
  2813. // Loop through each connection in the path to see if it points
  2814. // to a node whose automation table needs to be merged to the
  2815. // pin.
  2816. //
  2817. for ( uliPathEntry = 0
  2818. ; uliPathEntry < pPathInfo->ulcPathEntries
  2819. ; uliPathEntry++
  2820. )
  2821. {
  2822. const KSTOPOLOGY_CONNECTION * pConnection;
  2823. ULONG uliConnection;
  2824. const KSNODE_DESCRIPTOR * pNodeDescriptor;
  2825. ULONG uliNode;
  2826. if (pPathInfo->rgPathEntries[uliPathEntry].fJoint)
  2827. {
  2828. // Switch the merge state on a topology joint.
  2829. //
  2830. fMergeNode = !fMergeNode;
  2831. if (!fMergeNode)
  2832. {
  2833. // If we were merging input side nodes then we're done
  2834. //
  2835. break;
  2836. }
  2837. }
  2838. if (!fMergeNode)
  2839. {
  2840. continue;
  2841. }
  2842. // Get the "ToNode" from this connection and, if it is not
  2843. // an output pin, merge its automation table.
  2844. //
  2845. uliConnection = pPathInfo->rgPathEntries[uliPathEntry].uliConnection;
  2846. pConnection = &(pFilterDescriptor->Connections[uliConnection]);
  2847. uliNode = pConnection->ToNode;
  2848. if ( (uliNode == -1)
  2849. || (uliNode >= pFilterDescriptor->NodeDescriptorsCount)
  2850. )
  2851. {
  2852. // This connection's "ToNode" is an output pin so
  2853. // skip it.
  2854. //
  2855. continue;
  2856. }
  2857. // Find the Node Descriptor for the node type
  2858. //
  2859. pNodeDescriptor = pFilterDescriptor->NodeDescriptors;
  2860. pNodeDescriptor = (const KSNODE_DESCRIPTOR *)
  2861. ( (const BYTE *) (pNodeDescriptor)
  2862. + (ulcbNodeDescriptor * uliNode)
  2863. );
  2864. // Merge the nodes automation table into the resulting automation
  2865. // table.
  2866. //
  2867. //$BUGBUG - KsMergeAutomationTables should take const xxx *
  2868. //
  2869. if (!pOriginalAutomationTable)
  2870. {
  2871. pOriginalAutomationTable
  2872. = (PKSAUTOMATION_TABLE) (pNodeDescriptor->AutomationTable);
  2873. }
  2874. else
  2875. {
  2876. status = KsMergeAutomationTables(
  2877. &pNewAutomationTable,
  2878. (PKSAUTOMATION_TABLE) pOriginalAutomationTable,
  2879. (PKSAUTOMATION_TABLE) (pNodeDescriptor->AutomationTable),
  2880. ObjectBag
  2881. );
  2882. if (status != STATUS_SUCCESS)
  2883. {
  2884. goto exit;
  2885. }
  2886. ASSERT( pNewAutomationTable);
  2887. pOriginalAutomationTable = pNewAutomationTable;
  2888. pNewAutomationTable = NULL;
  2889. }
  2890. }
  2891. }
  2892. exit:
  2893. *ppNewAutomationTable = (PKSAUTOMATION_TABLE) pOriginalAutomationTable;
  2894. return status;
  2895. }
  2896. /*
  2897. ** BdaDeletePin()
  2898. **
  2899. ** Utility function deletes a pin from the given filter instance.
  2900. **
  2901. **
  2902. ** Arguments:
  2903. **
  2904. **
  2905. ** PinType Pin type to create.
  2906. **
  2907. ** pPinId Id of the Pin that was created.
  2908. **
  2909. ** Returns:
  2910. **
  2911. **
  2912. ** Side Effects: none
  2913. */
  2914. STDMETHODIMP_(NTSTATUS)
  2915. BdaDeletePin(
  2916. PKSFILTER pKSFilter,
  2917. PULONG pulPinId
  2918. )
  2919. {
  2920. NTSTATUS status = STATUS_SUCCESS;
  2921. PBDA_FILTER_CONTEXT pFilterCtx;
  2922. status = BdaGetFilterContext( pKSFilter, &pFilterCtx);
  2923. if (status != STATUS_SUCCESS)
  2924. {
  2925. goto errExit;
  2926. }
  2927. ASSERT( pFilterCtx);
  2928. errExit:
  2929. return status;
  2930. }
  2931. /*
  2932. ** BdaPathExists()
  2933. **
  2934. ** Utility function checks if there is a path between the input and
  2935. ** the output.
  2936. **
  2937. **
  2938. ** Arguments:
  2939. **
  2940. ** InputPinId
  2941. **
  2942. ** OutPutPinId
  2943. **
  2944. ** Returns:
  2945. **
  2946. ** TRUE If a path exists.
  2947. ** FALSE If no path exists.
  2948. **
  2949. ** Side Effects: none
  2950. */
  2951. STDMETHODIMP_(BOOLEAN)
  2952. BdaPathExists(
  2953. const KSFILTER_DESCRIPTOR * pFilterDescriptor,
  2954. ULONG ulInputPinId,
  2955. ULONG ulOutputPinId
  2956. )
  2957. {
  2958. const KSTOPOLOGY_CONNECTION * pConnection;
  2959. ULONG ulcConnections;
  2960. ULONG uliConnection;
  2961. if ( !pFilterDescriptor
  2962. || !pFilterDescriptor->ConnectionsCount
  2963. || !pFilterDescriptor->Connections
  2964. )
  2965. {
  2966. return FALSE;
  2967. }
  2968. //$REVIEW - Assume only DShow style internal connections.
  2969. //$REVIEW (ie connections between pins with no intervening nodes)
  2970. //
  2971. ulcConnections = pFilterDescriptor->ConnectionsCount;
  2972. pConnection = pFilterDescriptor->Connections;
  2973. for (uliConnection = 0; uliConnection < ulcConnections; uliConnection++)
  2974. {
  2975. if ( (pConnection[uliConnection].FromNode == -1)
  2976. && (pConnection[uliConnection].FromNodePin == ulInputPinId)
  2977. && (pConnection[uliConnection].ToNode == -1)
  2978. && (pConnection[uliConnection].ToNodePin == ulOutputPinId)
  2979. )
  2980. {
  2981. break;
  2982. }
  2983. }
  2984. return (uliConnection < ulcConnections);
  2985. }
  2986. /*
  2987. ** BdaCreateTopology()
  2988. **
  2989. ** Utility function creates the topology between two pins.
  2990. **
  2991. **
  2992. ** Arguments:
  2993. **
  2994. **
  2995. ** InputPinId
  2996. **
  2997. ** OutPutPinId
  2998. **
  2999. ** Returns:
  3000. **
  3001. ** NULL If no valid pin pairing exists with the
  3002. ** given input and output pins.
  3003. **
  3004. ** Side Effects: none
  3005. */
  3006. STDMETHODIMP_(NTSTATUS)
  3007. BdaCreateTopology(
  3008. PKSFILTER pKSFilter,
  3009. ULONG ulInputPinId,
  3010. ULONG ulOutputPinId
  3011. )
  3012. {
  3013. NTSTATUS status = STATUS_SUCCESS;
  3014. PBDA_FILTER_CONTEXT pFilterCtx = NULL;
  3015. const KSFILTER_DESCRIPTOR * pFilterDesc;
  3016. ULONG uliPinPair;
  3017. ULONG ulcPinPairs;
  3018. const BDA_PIN_PAIRING * pPinPairs;
  3019. ULONG ulInputPinType;
  3020. ULONG ulOutputPinType;
  3021. if (!pKSFilter)
  3022. {
  3023. status = STATUS_INVALID_PARAMETER;
  3024. goto errExit;
  3025. }
  3026. status = BdaGetFilterContext( pKSFilter, &pFilterCtx);
  3027. if (status != STATUS_SUCCESS)
  3028. {
  3029. goto errExit;
  3030. }
  3031. ASSERT( pFilterCtx);
  3032. if (!pFilterCtx)
  3033. {
  3034. status = STATUS_INVALID_DEVICE_STATE;
  3035. goto errExit;
  3036. }
  3037. ASSERT( pFilterCtx->pBdaFilterTemplate);
  3038. if (!pFilterCtx->pBdaFilterTemplate)
  3039. {
  3040. status = STATUS_INVALID_DEVICE_STATE;
  3041. goto errExit;
  3042. }
  3043. pPinPairs = pFilterCtx->pBdaFilterTemplate->pPinPairs;
  3044. ulcPinPairs = pFilterCtx->pBdaFilterTemplate->ulcPinPairs;
  3045. pFilterDesc = pKSFilter->Descriptor;
  3046. if ( !pFilterDesc
  3047. || (ulInputPinId >= pFilterDesc->PinDescriptorsCount)
  3048. || (ulOutputPinId >= pFilterDesc->PinDescriptorsCount)
  3049. )
  3050. {
  3051. status = STATUS_INVALID_PARAMETER;
  3052. goto errExit;
  3053. }
  3054. if (BdaPathExists( pFilterDesc, ulInputPinId, ulOutputPinId))
  3055. {
  3056. goto errExit;
  3057. }
  3058. // Get the input pin type.
  3059. //
  3060. status = BdaPinTypeFromPinId( pFilterCtx,
  3061. ulInputPinId,
  3062. &ulInputPinType
  3063. );
  3064. if (status != STATUS_SUCCESS)
  3065. {
  3066. goto errExit;
  3067. }
  3068. // Get the output pin type.
  3069. //
  3070. status = BdaPinTypeFromPinId( pFilterCtx,
  3071. ulOutputPinId,
  3072. &ulOutputPinType
  3073. );
  3074. if (status != STATUS_SUCCESS)
  3075. {
  3076. goto errExit;
  3077. }
  3078. // See if there is a pin pairing to match the requested topology.
  3079. //
  3080. for (uliPinPair = 0; uliPinPair < ulcPinPairs; uliPinPair++)
  3081. {
  3082. if ( (pPinPairs[uliPinPair].ulInputPin == ulInputPinType)
  3083. && (pPinPairs[uliPinPair].ulOutputPin == ulOutputPinType)
  3084. )
  3085. {
  3086. break;
  3087. }
  3088. }
  3089. if (uliPinPair >= ulcPinPairs)
  3090. {
  3091. status = STATUS_INVALID_DEVICE_REQUEST;
  3092. goto errExit;
  3093. }
  3094. {
  3095. KSTOPOLOGY_CONNECTION ksConnection;
  3096. // Add a path between the pins to the filter descriptor
  3097. //
  3098. ksConnection.FromNode = -1;
  3099. ksConnection.FromNodePin = ulInputPinId;
  3100. ksConnection.ToNode = -1;
  3101. ksConnection.ToNodePin = ulOutputPinId;
  3102. status = KsFilterAddTopologyConnections ( pKSFilter,
  3103. 1,
  3104. &ksConnection
  3105. );
  3106. }
  3107. errExit:
  3108. return status;
  3109. }
  3110. /*
  3111. ** BdaInitFilterFactoryContext()
  3112. **
  3113. ** Initializes a BDA Filter Factory Context based on the filter's
  3114. ** template descriptor.
  3115. **
  3116. **
  3117. ** Arguments:
  3118. **
  3119. **
  3120. ** pFilterFactoryCtx
  3121. **
  3122. ** Returns:
  3123. **
  3124. ** NULL If no valid pin pairing exists with the
  3125. ** given input and output pins.
  3126. **
  3127. ** Side Effects: none
  3128. */
  3129. STDMETHODIMP_(NTSTATUS)
  3130. BdaInitFilterFactoryContext(
  3131. PBDA_FILTER_FACTORY_CONTEXT pFilterFactoryCtx
  3132. )
  3133. {
  3134. NTSTATUS status = STATUS_SUCCESS;
  3135. ASSERT( pFilterFactoryCtx);
  3136. if (!pFilterFactoryCtx)
  3137. {
  3138. status = STATUS_INVALID_PARAMETER;
  3139. goto errExit;
  3140. }
  3141. if (!pFilterFactoryCtx->pBdaFilterTemplate)
  3142. {
  3143. goto errExit;
  3144. }
  3145. errExit:
  3146. return status;
  3147. }
  3148. /*
  3149. ** BdaPushNextPathHop()
  3150. **
  3151. ** Recursively pushes connections onto the connection stack until
  3152. ** (starting with the input pin of the pin pair) until either the
  3153. ** output pin is found or there are no connections that can be pushed.
  3154. **
  3155. **
  3156. ** Arguments:
  3157. **
  3158. **
  3159. ** pFilterFactoryCtx
  3160. **
  3161. ** Returns:
  3162. **
  3163. ** NULL If no valid pin pairing exists with the
  3164. ** given input and output pins.
  3165. **
  3166. ** Side Effects: none
  3167. */
  3168. STDMETHODIMP_(NTSTATUS)
  3169. BdaPushNextPathHop(
  3170. PULONG puliPathStack,
  3171. PBDA_PATH_STACK_ENTRY pPathStack,
  3172. ULONG ulcConnections,
  3173. const KSTOPOLOGY_CONNECTION * pConnections,
  3174. const BDA_PIN_PAIRING * pPinPair
  3175. )
  3176. {
  3177. NTSTATUS status = STATUS_SUCCESS;
  3178. ULONG ulHop;
  3179. ULONG ulFromNode;
  3180. ULONG ulFromNodePin;
  3181. ULONG uliConnection;
  3182. // Determine which node we are currently finding connection to.
  3183. //
  3184. if (!*puliPathStack)
  3185. {
  3186. // We are pushing the first hop.
  3187. //
  3188. ulHop = 0;
  3189. // Hop 0 is always the input pin
  3190. //
  3191. ulFromNode = -1;
  3192. ulFromNodePin = pPinPair->ulInputPin;
  3193. }
  3194. else
  3195. {
  3196. // We are pushing the next hop.
  3197. //
  3198. ulHop = pPathStack[*puliPathStack - 1].ulHop + 1;
  3199. // We will be looking for connections from the "ToNode" of the
  3200. // connection at the top of the stack.
  3201. //
  3202. uliConnection = pPathStack[*puliPathStack - 1].uliConnection;
  3203. ulFromNode = pConnections[uliConnection].ToNode;
  3204. ulFromNodePin = pConnections[uliConnection].ToNodePin;
  3205. }
  3206. // GO through each connection in the filter factories connection
  3207. // and push any connection to ulFromNode onto the connections stack.
  3208. // If a connection from ulFromNode to the output pin of the given
  3209. // pin pair is found then we have found a complete path for the
  3210. // pin pair.
  3211. //
  3212. for ( uliConnection = 0
  3213. ; uliConnection < ulcConnections
  3214. ; uliConnection++
  3215. )
  3216. {
  3217. ULONG uliJoints;
  3218. const ULONG * pJoints;
  3219. if (pConnections[uliConnection].FromNode != ulFromNode)
  3220. {
  3221. // Connection is not from the node at the top of the stack.
  3222. //
  3223. continue;
  3224. }
  3225. if ( (pConnections[uliConnection].FromNode == -1)
  3226. && (pConnections[uliConnection].FromNodePin != ulFromNodePin)
  3227. )
  3228. {
  3229. // The input pin is at the top of the stack and this connection
  3230. // is not from the input pin of the pin pair.
  3231. //
  3232. continue;
  3233. }
  3234. //
  3235. // This connection is from the node that was on top of the stack
  3236. // when this function was called. Push it onto the stack.
  3237. //
  3238. if (*puliPathStack >= ulcConnections)
  3239. {
  3240. // Stack overflow
  3241. // Can only occur when the BDA topology contains
  3242. // cirular references.
  3243. //
  3244. status = STATUS_INVALID_PARAMETER;
  3245. goto errExit;
  3246. }
  3247. // Write the connection info to the next stack entry.
  3248. //
  3249. pPathStack[*puliPathStack].ulHop = ulHop;
  3250. pPathStack[*puliPathStack].uliConnection = uliConnection;
  3251. pPathStack[*puliPathStack].fJoint = FALSE;
  3252. // See if this connection is also a topology joint.
  3253. //
  3254. for ( uliJoints = 0, pJoints = pPinPair->pTopologyJoints
  3255. ; (uliJoints < pPinPair->ulcTopologyJoints) && pJoints
  3256. ; uliJoints++
  3257. )
  3258. {
  3259. if (pJoints[uliJoints] == uliConnection)
  3260. {
  3261. pPathStack[*puliPathStack].fJoint = TRUE;
  3262. break;
  3263. }
  3264. }
  3265. // Increment the stack pointer
  3266. //
  3267. *puliPathStack += 1;
  3268. // Now that the connection has been pushed on the stack. See if it
  3269. // completes a path between the input and output pin pair.
  3270. //
  3271. if ( (pConnections[uliConnection].ToNode == -1)
  3272. && (pConnections[uliConnection].ToNodePin == pPinPair->ulOutputPin)
  3273. )
  3274. {
  3275. // If this connection completes the path, then complete
  3276. // now so that the caller will find the end of the path
  3277. // at the top of the stack.
  3278. //
  3279. break;
  3280. }
  3281. }
  3282. errExit:
  3283. return status;
  3284. }
  3285. /*
  3286. ** BdaPopPathSegment()
  3287. **
  3288. ** Pops the stack back to the next path segment to try.
  3289. **
  3290. **
  3291. ** Arguments:
  3292. **
  3293. **
  3294. ** Returns:
  3295. **
  3296. **
  3297. ** Side Effects: none
  3298. */
  3299. BdaPopPathSegment(
  3300. PULONG puliPathStack,
  3301. PBDA_PATH_STACK_ENTRY pPathStack
  3302. )
  3303. {
  3304. NTSTATUS status = STATUS_SUCCESS;
  3305. ULONG ulCurHop;
  3306. ULONG ulNewHop;
  3307. ulCurHop = pPathStack[*puliPathStack].ulHop;
  3308. while (*puliPathStack)
  3309. {
  3310. *puliPathStack -= 1;
  3311. if (!*puliPathStack)
  3312. {
  3313. // Empty Stack
  3314. //
  3315. break;
  3316. }
  3317. if (pPathStack[(*puliPathStack) - 1].ulHop == ulCurHop)
  3318. {
  3319. // Stop here if there is another entry on the stack at
  3320. // the current hop count.
  3321. //
  3322. break;
  3323. }
  3324. // We've popped back to a new hop count, so set the current
  3325. // hop count and pop off another entry.
  3326. //
  3327. ulCurHop = pPathStack[(*puliPathStack) - 1].ulHop;
  3328. }
  3329. return status;
  3330. }
  3331. /*
  3332. ** BdaPathInfoFromPathStack()
  3333. **
  3334. ** Builds a connection path between the input and output pins of
  3335. ** a pin pair.
  3336. **
  3337. **
  3338. ** Arguments:
  3339. **
  3340. **
  3341. ** Returns:
  3342. **
  3343. **
  3344. ** Side Effects: none
  3345. */
  3346. STDMETHODIMP_(NTSTATUS)
  3347. BdaPathInfoFromPathStack(
  3348. ULONG uliPathStack,
  3349. PBDA_PATH_STACK_ENTRY pPathStack,
  3350. ULONG ulcConnections,
  3351. const KSTOPOLOGY_CONNECTION * pConnections,
  3352. const BDA_PIN_PAIRING * pPinPair,
  3353. PBDA_PATH_INFO * ppPathInfo
  3354. )
  3355. {
  3356. NTSTATUS status = STATUS_SUCCESS;
  3357. PBDA_PATH_INFO pPathInfo = NULL;
  3358. ULONG uliConnection;
  3359. ULONG ulHop;
  3360. ASSERT( uliPathStack);
  3361. ASSERT( pPathStack);
  3362. ASSERT( uliPathStack <= ulcConnections);
  3363. ASSERT( ulcConnections);
  3364. ASSERT( pConnections);
  3365. ASSERT( ppPathInfo);
  3366. ASSERT( pPinPair);
  3367. if ( !ppPathInfo
  3368. || !pConnections
  3369. || !pPathStack
  3370. || !pPinPair
  3371. || !uliPathStack
  3372. || !ulcConnections
  3373. || (uliPathStack > ulcConnections)
  3374. )
  3375. {
  3376. status = STATUS_INVALID_PARAMETER;
  3377. goto errExit;
  3378. }
  3379. // Make sure the connection at the top of the path stack points
  3380. // to the output pin of the pin pair.
  3381. //
  3382. uliConnection = pPathStack[uliPathStack - 1].uliConnection;
  3383. if ( (pConnections[uliConnection].ToNode != -1)
  3384. || (pConnections[uliConnection].ToNodePin != pPinPair->ulOutputPin)
  3385. )
  3386. {
  3387. status = STATUS_INVALID_PARAMETER;
  3388. goto errExit;
  3389. }
  3390. // Start filling in from the node at the last hop. If the last
  3391. // hop == 0 then there was only one connection between the input
  3392. // and output pins with no intervening nodes.
  3393. //
  3394. ulHop = pPathStack[uliPathStack - 1].ulHop;
  3395. // Allocate enough space for the node path structure and all
  3396. // nodes in the path.
  3397. //
  3398. pPathInfo = ExAllocatePool(
  3399. NonPagedPool,
  3400. sizeof( BDA_PATH_INFO)
  3401. + (ulHop + 1) * sizeof( BDA_PATH_STACK_ENTRY)
  3402. );
  3403. if (!pPathInfo)
  3404. {
  3405. status = STATUS_NO_MEMORY;
  3406. goto errExit;
  3407. }
  3408. pPathInfo->ulInputPin = pPinPair->ulInputPin;
  3409. pPathInfo->ulOutputPin = pPinPair->ulOutputPin;
  3410. pPathInfo->ulcPathEntries = ulHop + 1;
  3411. while (uliPathStack)
  3412. {
  3413. // Enter the Connection info into the path connection list
  3414. //
  3415. //
  3416. pPathInfo->rgPathEntries[ulHop] = pPathStack[uliPathStack - 1];
  3417. // Pop the path stack up to the top entry of the next lower hop.
  3418. // If exhaust the path stack then we are either done or the path
  3419. // stack didn't reflect a complete path from input pin to
  3420. // output pin.
  3421. //
  3422. ulHop -= 1;
  3423. while ( uliPathStack
  3424. && (pPathStack[uliPathStack - 1].ulHop != ulHop)
  3425. )
  3426. {
  3427. uliPathStack -= 1;
  3428. }
  3429. }
  3430. // We should alway end up pointing to a connection between the input
  3431. // pin and the first node of the path to the output pin.
  3432. //
  3433. ASSERT( ulHop == -1);
  3434. if (ulHop != -1)
  3435. {
  3436. status = STATUS_INVALID_DEVICE_STATE;
  3437. goto errExit;
  3438. }
  3439. // Make sure the last connection points back to the input pin.
  3440. //
  3441. uliConnection = pPathInfo->rgPathEntries[0].uliConnection;
  3442. if ( (pConnections[uliConnection].FromNode != -1)
  3443. || (pConnections[uliConnection].FromNodePin != pPinPair->ulInputPin)
  3444. )
  3445. {
  3446. status = STATUS_INVALID_PARAMETER;
  3447. goto errExit;
  3448. }
  3449. exit:
  3450. *ppPathInfo = pPathInfo;
  3451. pPathInfo = NULL;
  3452. return status;
  3453. errExit:
  3454. if (pPathInfo)
  3455. {
  3456. ExFreePool( pPathInfo);
  3457. pPathInfo = NULL;
  3458. }
  3459. goto exit;
  3460. }
  3461. /*
  3462. ** BdaBuildPath()
  3463. **
  3464. ** Builds a connection path between the input and output pins of
  3465. ** a pin pair.
  3466. **
  3467. **
  3468. ** Arguments:
  3469. **
  3470. **
  3471. ** Returns:
  3472. **
  3473. **
  3474. ** Side Effects: none
  3475. */
  3476. STDMETHODIMP_(NTSTATUS)
  3477. BdaBuildPath(
  3478. ULONG ulcConnections,
  3479. const KSTOPOLOGY_CONNECTION * pConnections,
  3480. const BDA_PIN_PAIRING * pPinPair,
  3481. PBDA_PATH_INFO * ppPathInfo
  3482. )
  3483. {
  3484. NTSTATUS status = STATUS_SUCCESS;
  3485. ULONG uliStackPointer;
  3486. PBDA_PATH_STACK_ENTRY pPathStack = NULL;
  3487. ULONG ulcAttempts;
  3488. ULONG uliConnection;
  3489. // Allocate a stack on which to put unfollowed connections to a path.
  3490. //
  3491. pPathStack = ExAllocatePool(
  3492. NonPagedPool,
  3493. ulcConnections * sizeof( BDA_PATH_STACK_ENTRY)
  3494. );
  3495. if (!pPathStack)
  3496. {
  3497. status = STATUS_NO_MEMORY;
  3498. goto errExit;
  3499. }
  3500. // Initialize the unfollowed connection stack
  3501. //
  3502. uliStackPointer = 0;
  3503. // Build a path stack by pushing each connection that connects from
  3504. // the previous hop.
  3505. //
  3506. // It isn't possible to attempt to push the next hop more times than
  3507. // there are connections. If this happens then there is an illegal
  3508. // circular path in the connection list.
  3509. //
  3510. for (ulcAttempts = 0; ulcAttempts < ulcConnections; ulcAttempts++)
  3511. {
  3512. ULONG uliPrevStackPointer;
  3513. uliPrevStackPointer = uliStackPointer;
  3514. status = BdaPushNextPathHop( &uliStackPointer,
  3515. pPathStack,
  3516. ulcConnections,
  3517. pConnections,
  3518. pPinPair
  3519. );
  3520. if (!uliStackPointer)
  3521. {
  3522. // If the stack is empty at this point then there is
  3523. // no path from the input pin to the output pin.
  3524. //
  3525. break;
  3526. }
  3527. // See if the connection at the top of the stack connects to
  3528. // the output pin of the pin pair.
  3529. //
  3530. uliConnection = pPathStack[uliStackPointer - 1].uliConnection;
  3531. if ( (pConnections[uliConnection].ToNode == -1)
  3532. && (pConnections[uliConnection].ToNodePin == pPinPair->ulOutputPin)
  3533. )
  3534. {
  3535. // A path from the input pin to the output pin has been
  3536. // located.
  3537. //
  3538. break;
  3539. }
  3540. // If no hop could be pushed onto the connnection at the top of
  3541. // the stack then it is a dead end.
  3542. //
  3543. if (uliStackPointer <= uliPrevStackPointer)
  3544. {
  3545. // Pop connections from the stack until we reach a viable
  3546. // (new) candidate to attempt a path from.
  3547. //
  3548. BdaPopPathSegment( &uliStackPointer, pPathStack);
  3549. if (!uliStackPointer)
  3550. {
  3551. // If the stack is empty at this point then there is
  3552. // no path from the input pin to the output pin.
  3553. //
  3554. break;
  3555. }
  3556. }
  3557. }
  3558. if (!uliStackPointer || (ulcAttempts >= ulcConnections))
  3559. {
  3560. // Either there is no path from the input pin to the output pin
  3561. // or there is an illegal circular path in the connection list
  3562. //
  3563. status = STATUS_INVALID_PARAMETER;
  3564. goto errExit;
  3565. }
  3566. // Create a BDA node path structure from the Path Stack
  3567. //
  3568. //$REVIEW - Should we allow more than one path per pin pair
  3569. //
  3570. status = BdaPathInfoFromPathStack( uliStackPointer,
  3571. pPathStack,
  3572. ulcConnections,
  3573. pConnections,
  3574. pPinPair,
  3575. ppPathInfo
  3576. );
  3577. errExit:
  3578. if (pPathStack)
  3579. {
  3580. ExFreePool( pPathStack);
  3581. pPathStack = NULL;
  3582. }
  3583. return status;
  3584. }
  3585. /*
  3586. ** BdaCreateTemplatePaths()
  3587. **
  3588. ** Creates a list of all possible paths through the template filter.
  3589. ** Determines the controlling pin type for each node type in the
  3590. ** template filter.
  3591. **
  3592. **
  3593. ** Arguments:
  3594. **
  3595. **
  3596. ** pFilterFactoryCtx
  3597. **
  3598. ** Returns:
  3599. **
  3600. ** NULL If no valid pin pairing exists with the
  3601. ** given input and output pins.
  3602. **
  3603. ** Side Effects: none
  3604. */
  3605. STDMETHODIMP_(NTSTATUS)
  3606. BdaCreateTemplatePaths(
  3607. const BDA_FILTER_TEMPLATE * pBdaFilterTemplate,
  3608. PULONG pulcPathInfo,
  3609. PBDA_PATH_INFO ** pargpPathInfo
  3610. )
  3611. {
  3612. NTSTATUS status = STATUS_SUCCESS;
  3613. const BDA_FILTER_TEMPLATE * pFilterTemplate;
  3614. ULONG uliPinPair;
  3615. ULONG ulcPinPairs;
  3616. const BDA_PIN_PAIRING * pPinPairs;
  3617. ULONG ulcConnections;
  3618. const KSTOPOLOGY_CONNECTION * pConnections;
  3619. PBDA_PATH_INFO * argpPathInfo = NULL;
  3620. ASSERT( pBdaFilterTemplate);
  3621. ASSERT( pBdaFilterTemplate->pFilterDescriptor);
  3622. ASSERT( pBdaFilterTemplate->ulcPinPairs);
  3623. if ( !pBdaFilterTemplate
  3624. || !pBdaFilterTemplate->pFilterDescriptor
  3625. || !pBdaFilterTemplate->ulcPinPairs
  3626. )
  3627. {
  3628. goto errExit;
  3629. }
  3630. if ( !pBdaFilterTemplate->pFilterDescriptor->ConnectionsCount
  3631. || !pBdaFilterTemplate->pFilterDescriptor->Connections
  3632. || !pBdaFilterTemplate->pPinPairs
  3633. )
  3634. {
  3635. status = STATUS_INVALID_DEVICE_STATE;
  3636. goto errExit;
  3637. }
  3638. ulcPinPairs = pBdaFilterTemplate->ulcPinPairs;
  3639. pPinPairs = pBdaFilterTemplate->pPinPairs;
  3640. ulcConnections = pBdaFilterTemplate->pFilterDescriptor->ConnectionsCount;
  3641. pConnections = pBdaFilterTemplate->pFilterDescriptor->Connections;
  3642. // Allocate the node path list (one entry for each pin pairing).
  3643. //
  3644. //$REVIEW - Should we allow more than one path per pin pair
  3645. //
  3646. argpPathInfo = ExAllocatePool(
  3647. NonPagedPool,
  3648. ulcPinPairs * sizeof( PBDA_PATH_INFO)
  3649. );
  3650. if (!argpPathInfo)
  3651. {
  3652. status = STATUS_NO_MEMORY;
  3653. goto errExit;
  3654. }
  3655. for (uliPinPair = 0; uliPinPair < ulcPinPairs; uliPinPair++)
  3656. {
  3657. status = BdaBuildPath(
  3658. ulcConnections,
  3659. pConnections,
  3660. &(pPinPairs[uliPinPair]),
  3661. &(argpPathInfo[uliPinPair])
  3662. );
  3663. if (status != STATUS_SUCCESS)
  3664. {
  3665. goto errExit;
  3666. }
  3667. }
  3668. *pulcPathInfo = ulcPinPairs;
  3669. *pargpPathInfo = argpPathInfo;
  3670. argpPathInfo = NULL;
  3671. errExit:
  3672. if (argpPathInfo)
  3673. {
  3674. ExFreePool( argpPathInfo);
  3675. argpPathInfo = NULL;
  3676. }
  3677. return status;
  3678. }