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

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