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.

1498 lines
39 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Module: gni.cpp
  4. //
  5. // Description:
  6. //
  7. // Graph Node Instance
  8. //
  9. //@@BEGIN_MSINTERNAL
  10. // Development Team:
  11. // Mike McLaughlin
  12. //
  13. // History: Date Author Comment
  14. //
  15. // To Do: Date Author Comment
  16. //
  17. //@@END_MSINTERNAL
  18. //
  19. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  20. // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  21. // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  22. // PURPOSE.
  23. //
  24. // Copyright (c) 1996-1999 Microsoft Corporation. All Rights Reserved.
  25. //
  26. //---------------------------------------------------------------------------
  27. #include "common.h"
  28. //---------------------------------------------------------------------------
  29. GUID aguidSysAudioCategories[] = {
  30. STATICGUIDOF(KSCATEGORY_SYSAUDIO)
  31. };
  32. //---------------------------------------------------------------------------
  33. //---------------------------------------------------------------------------
  34. CGraphNodeInstance::CGraphNodeInstance(
  35. PGRAPH_NODE pGraphNode,
  36. PFILTER_INSTANCE pFilterInstance
  37. )
  38. {
  39. Assert(pGraphNode);
  40. Assert(pFilterInstance);
  41. this->pFilterInstance = pFilterInstance;
  42. this->ulFlags = pFilterInstance->ulFlags;
  43. this->pGraphNode = pGraphNode;
  44. AddList(&pGraphNode->lstGraphNodeInstance);
  45. }
  46. CGraphNodeInstance::CGraphNodeInstance(
  47. PGRAPH_NODE pGraphNode
  48. )
  49. {
  50. Assert(pGraphNode);
  51. this->ulFlags = pGraphNode->ulFlags;
  52. this->pGraphNode = pGraphNode;
  53. AddList(&pGraphNode->lstGraphNodeInstance);
  54. }
  55. CGraphNodeInstance::~CGraphNodeInstance(
  56. )
  57. {
  58. Assert(this);
  59. RemoveList();
  60. if(pFilterInstance != NULL) {
  61. Assert(pFilterInstance);
  62. pFilterInstance->pGraphNodeInstance = NULL;
  63. pFilterInstance->ParentInstance.Invalidate();
  64. }
  65. DestroyPinDescriptors();
  66. DestroySysAudioTopology();
  67. delete[] paulNodeNumber;
  68. }
  69. NTSTATUS
  70. CGraphNodeInstance::Create(
  71. )
  72. {
  73. NTSTATUS Status = STATUS_SUCCESS;
  74. ULONG i, n;
  75. if(this == NULL) {
  76. Status = STATUS_NO_SUCH_DEVICE;
  77. goto exit;
  78. }
  79. Assert(this);
  80. Assert(pGraphNode);
  81. Status = CreatePinDescriptors();
  82. if(!NT_SUCCESS(Status)) {
  83. goto exit;
  84. }
  85. Status = CreateSysAudioTopology();
  86. if(!NT_SUCCESS(Status)) {
  87. goto exit;
  88. }
  89. if(gcVirtualSources != 0) {
  90. paulNodeNumber = new ULONG[gcVirtualSources];
  91. if(paulNodeNumber == NULL) {
  92. Trap();
  93. Status = STATUS_INSUFFICIENT_RESOURCES;
  94. goto exit;
  95. }
  96. for(i = 0; i < gcVirtualSources; i++) {
  97. for(n = 0; n < cTopologyNodes; n++) {
  98. if(pGraphNode->pDeviceNode->papVirtualSourceData[i]->
  99. pTopologyNode == papTopologyNode[n]) {
  100. paulNodeNumber[i] = n;
  101. break;
  102. }
  103. }
  104. }
  105. }
  106. exit:
  107. return(Status);
  108. }
  109. //---------------------------------------------------------------------------
  110. NTSTATUS
  111. CGraphNodeInstance::GetTopologyNodeFileObject(
  112. OUT PFILE_OBJECT *ppFileObject,
  113. IN ULONG NodeId
  114. )
  115. {
  116. NTSTATUS Status = STATUS_SUCCESS;
  117. if(this == NULL) {
  118. Status = STATUS_NO_SUCH_DEVICE;
  119. goto exit;
  120. }
  121. Assert(this);
  122. if(NodeId >= cTopologyNodes) {
  123. DPF2(100,
  124. "GetTopologyNodeFileObject: NodeId(%d) >= cTopologyNodes(%d)",
  125. NodeId,
  126. cTopologyNodes);
  127. Status = STATUS_INVALID_DEVICE_REQUEST;
  128. goto exit;
  129. }
  130. // If virtual topology node, return error
  131. if(papTopologyNode[NodeId]->ulRealNodeNumber == MAXULONG) {
  132. DPF(100, "GetTopologyNodeFileObject: ulRealNodeNumber == MAXULONG");
  133. Status = STATUS_INVALID_DEVICE_REQUEST;
  134. goto exit;
  135. }
  136. if(papFilterNodeInstanceTopologyTable == NULL) {
  137. Trap();
  138. Status = STATUS_INVALID_DEVICE_REQUEST;
  139. goto exit;
  140. }
  141. if(papFilterNodeInstanceTopologyTable[NodeId] == NULL) {
  142. Status = CFilterNodeInstance::Create(
  143. &papFilterNodeInstanceTopologyTable[NodeId],
  144. papTopologyNode[NodeId]->lstLogicalFilterNode.GetListFirstData(),
  145. pGraphNode->pDeviceNode,
  146. TRUE); // Reuse an instance
  147. if(!NT_SUCCESS(Status)) {
  148. goto exit;
  149. }
  150. }
  151. Assert(papFilterNodeInstanceTopologyTable[NodeId]);
  152. *ppFileObject = papFilterNodeInstanceTopologyTable[NodeId]->pFileObject;
  153. DPF1(110,
  154. "GetToplogyNodeFileObject: using filter for node: %d\n",
  155. NodeId);
  156. exit:
  157. return(Status);
  158. }
  159. //---------------------------------------------------------------------------
  160. NTSTATUS
  161. CGraphNodeInstance::CreateSysAudioTopology(
  162. )
  163. {
  164. NTSTATUS Status = STATUS_SUCCESS;
  165. Assert(this);
  166. ASSERT(Topology.TopologyNodes == NULL);
  167. ASSERT(Topology.TopologyConnections == NULL);
  168. ASSERT(papFilterNodeInstanceTopologyTable == NULL);
  169. Topology.CategoriesCount = SIZEOF_ARRAY(aguidSysAudioCategories);
  170. Topology.Categories = aguidSysAudioCategories;
  171. CreateTopologyTables();
  172. if(cTopologyNodes != 0) {
  173. Topology.TopologyNodes = new GUID[cTopologyNodes];
  174. if(Topology.TopologyNodes == NULL) {
  175. Status = STATUS_INSUFFICIENT_RESOURCES;
  176. goto exit;
  177. }
  178. papFilterNodeInstanceTopologyTable =
  179. new PFILTER_NODE_INSTANCE[cTopologyNodes];
  180. if(papFilterNodeInstanceTopologyTable == NULL) {
  181. Status = STATUS_INSUFFICIENT_RESOURCES;
  182. goto exit;
  183. }
  184. papTopologyNode = new PTOPOLOGY_NODE[cTopologyNodes];
  185. if(papTopologyNode == NULL) {
  186. Status = STATUS_INSUFFICIENT_RESOURCES;
  187. goto exit;
  188. }
  189. }
  190. if(cTopologyConnections != 0) {
  191. Topology.TopologyConnections =
  192. new KSTOPOLOGY_CONNECTION[cTopologyConnections];
  193. if(Topology.TopologyConnections == NULL) {
  194. Status = STATUS_INSUFFICIENT_RESOURCES;
  195. goto exit;
  196. }
  197. }
  198. CreateTopologyTables();
  199. exit:
  200. if(!NT_SUCCESS(Status)) {
  201. DestroySysAudioTopology();
  202. }
  203. return(Status);
  204. }
  205. VOID
  206. CGraphNodeInstance::DestroySysAudioTopology(
  207. )
  208. {
  209. ULONG n;
  210. delete[] (PVOID)Topology.TopologyNodes;
  211. Topology.TopologyNodes = NULL;
  212. delete[] (PVOID)Topology.TopologyConnections;
  213. Topology.TopologyConnections = NULL;
  214. delete[] papTopologyNode;
  215. papTopologyNode = NULL;
  216. if(papFilterNodeInstanceTopologyTable != NULL) {
  217. for(n = 0; n < cTopologyNodes; n++) {
  218. papFilterNodeInstanceTopologyTable[n]->Destroy();
  219. }
  220. delete[] papFilterNodeInstanceTopologyTable;
  221. papFilterNodeInstanceTopologyTable = NULL;
  222. }
  223. }
  224. typedef ENUMFUNC (CTopologyNode::*CLIST_TN_PFN2)(PVOID, PVOID);
  225. VOID
  226. CGraphNodeInstance::CreateTopologyTables(
  227. )
  228. {
  229. Assert(this);
  230. Assert(pGraphNode);
  231. cTopologyNodes = 0;
  232. cTopologyConnections = 0;
  233. // Initialize the "ulSysaudioNodeNumber" field in the TopologyNodes first
  234. ProcessLogicalFilterNodeTopologyNode(
  235. &pGraphNode->pDeviceNode->lstLogicalFilterNode,
  236. CTopologyNode::InitializeTopologyNode);
  237. ProcessLogicalFilterNodeTopologyNode(
  238. &pGraphNode->lstLogicalFilterNode,
  239. CTopologyNode::InitializeTopologyNode);
  240. // All the nodes need to be processed first so the ulSysaudioNodeNumber in
  241. // the TopologyNode is correct before any connections are processed.
  242. ProcessLogicalFilterNodeTopologyNode(
  243. &pGraphNode->pDeviceNode->lstLogicalFilterNode,
  244. CTopologyNode::AddTopologyNode);
  245. ProcessLogicalFilterNodeTopologyNode(
  246. &pGraphNode->lstLogicalFilterNode,
  247. CTopologyNode::AddTopologyNode);
  248. // Now process all the topology connection lists
  249. ProcessLogicalFilterNodeTopologyConnection(
  250. &pGraphNode->pDeviceNode->lstLogicalFilterNode,
  251. CTopologyConnection::ProcessTopologyConnection);
  252. ProcessLogicalFilterNodeTopologyConnection(
  253. &pGraphNode->lstLogicalFilterNode,
  254. CTopologyConnection::ProcessTopologyConnection);
  255. pGraphNode->lstTopologyConnection.EnumerateList(
  256. CTopologyConnection::ProcessTopologyConnection,
  257. (PVOID)this);
  258. }
  259. VOID
  260. CGraphNodeInstance::ProcessLogicalFilterNodeTopologyNode(
  261. PLIST_MULTI_LOGICAL_FILTER_NODE plstLogicalFilterNode,
  262. NTSTATUS (CTopologyNode::*Function)(
  263. PVOID pGraphNodeInstance
  264. )
  265. )
  266. {
  267. PLOGICAL_FILTER_NODE pLogicalFilterNode;
  268. FOR_EACH_LIST_ITEM(
  269. plstLogicalFilterNode,
  270. pLogicalFilterNode) {
  271. Assert(pLogicalFilterNode);
  272. pLogicalFilterNode->lstTopologyNode.EnumerateList(Function, this);
  273. } END_EACH_LIST_ITEM
  274. }
  275. VOID
  276. CGraphNodeInstance::ProcessLogicalFilterNodeTopologyConnection(
  277. PLIST_MULTI_LOGICAL_FILTER_NODE plstLogicalFilterNode,
  278. NTSTATUS (CTopologyConnection::*Function)(
  279. PVOID pGraphNodeInstance
  280. )
  281. )
  282. {
  283. PLOGICAL_FILTER_NODE pLogicalFilterNode;
  284. FOR_EACH_LIST_ITEM(
  285. plstLogicalFilterNode,
  286. pLogicalFilterNode) {
  287. Assert(pLogicalFilterNode);
  288. pLogicalFilterNode->lstTopologyConnection.EnumerateList(Function, this);
  289. } END_EACH_LIST_ITEM
  290. }
  291. ENUMFUNC
  292. CTopologyConnection::ProcessTopologyConnection(
  293. PVOID pReference
  294. )
  295. {
  296. PGRAPH_NODE_INSTANCE pGraphNodeInstance = (PGRAPH_NODE_INSTANCE)pReference;
  297. PSTART_NODE pStartNode;
  298. ULONG ulFromPin;
  299. ULONG ulFromNode;
  300. ULONG ulToPin;
  301. ULONG ulToNode;
  302. ULONG PinId;
  303. Assert(this);
  304. Assert(pGraphNodeInstance);
  305. ulFromPin = MAXULONG;
  306. ulToPin = MAXULONG;
  307. #ifdef DEBUG
  308. ulFromNode = MAXULONG;
  309. ulToNode = MAXULONG;
  310. #endif
  311. // If the connection doesn't connect LFNs on this GraphNode, skip connection
  312. if(!IsTopologyConnectionOnGraphNode(pGraphNodeInstance->pGraphNode)) {
  313. DPF3(100, "ProcessTC: %s TC %08x GN %08x - skip TC",
  314. pGraphNodeInstance->pGraphNode->pDeviceNode->DumpName(),
  315. this,
  316. pGraphNodeInstance->pGraphNode);
  317. goto exit;
  318. }
  319. if(pTopologyPinFrom != NULL) {
  320. ulFromNode = pTopologyPinFrom->pTopologyNode->ulSysaudioNodeNumber;
  321. ulFromPin = pTopologyPinFrom->ulPinNumber;
  322. ASSERT(pPinInfoFrom == NULL);
  323. ASSERT(ulFromNode != MAXULONG);
  324. ASSERT(ulFromPin != MAXULONG);
  325. }
  326. if(pTopologyPinTo != NULL) {
  327. ulToNode = pTopologyPinTo->pTopologyNode->ulSysaudioNodeNumber;
  328. ulToPin = pTopologyPinTo->ulPinNumber;
  329. ASSERT(pPinInfoTo == NULL);
  330. ASSERT(ulToNode != MAXULONG);
  331. ASSERT(ulToPin != MAXULONG);
  332. }
  333. if(pGraphNodeInstance->aplstStartNode != NULL) {
  334. for(PinId = 0; PinId < pGraphNodeInstance->cPins; PinId++) {
  335. FOR_EACH_LIST_ITEM(
  336. pGraphNodeInstance->aplstStartNode[PinId],
  337. pStartNode) {
  338. Assert(pStartNode);
  339. if(pPinInfoFrom != NULL) {
  340. ASSERT(pTopologyPinFrom == NULL);
  341. if(pStartNode->pPinNode->pPinInfo == pPinInfoFrom) {
  342. // This code assumes that a filter's pininfo will show
  343. // up in one SAD pin. If a filter exposes more than one
  344. // major format on the same pin, that pininfo show on
  345. // two different SAD pins.
  346. ASSERT(ulFromNode == KSFILTER_NODE);
  347. ASSERT(ulFromPin == MAXULONG || ulFromPin == PinId);
  348. pStartNode->GetStartInfo()->
  349. ulTopologyConnectionTableIndex =
  350. pGraphNodeInstance->cTopologyConnections;
  351. ulFromNode = KSFILTER_NODE;
  352. ulFromPin = PinId;
  353. }
  354. }
  355. if(pPinInfoTo != NULL) {
  356. ASSERT(pTopologyPinTo == NULL);
  357. if(pStartNode->pPinNode->pPinInfo == pPinInfoTo) {
  358. // See above.
  359. ASSERT(ulToNode == KSFILTER_NODE);
  360. ASSERT(ulToPin == MAXULONG || ulToPin == PinId);
  361. pStartNode->GetStartInfo()->
  362. ulTopologyConnectionTableIndex =
  363. pGraphNodeInstance->cTopologyConnections;
  364. ulToNode = KSFILTER_NODE;
  365. ulToPin = PinId;
  366. }
  367. }
  368. } END_EACH_LIST_ITEM
  369. }
  370. }
  371. if(ulFromPin != MAXULONG && ulToPin != MAXULONG) {
  372. pGraphNodeInstance->AddTopologyConnection(
  373. ulFromNode,
  374. ulFromPin,
  375. ulToNode,
  376. ulToPin);
  377. }
  378. exit:
  379. return(STATUS_CONTINUE);
  380. }
  381. ENUMFUNC
  382. CTopologyNode::InitializeTopologyNode(
  383. PVOID pReference
  384. )
  385. {
  386. PGRAPH_NODE_INSTANCE pGraphNodeInstance = (PGRAPH_NODE_INSTANCE)pReference;
  387. Assert(this);
  388. Assert(pGraphNodeInstance);
  389. ulSysaudioNodeNumber = MAXULONG;
  390. return(STATUS_CONTINUE);
  391. }
  392. ENUMFUNC
  393. CTopologyNode::AddTopologyNode(
  394. PVOID pReference
  395. )
  396. {
  397. PGRAPH_NODE_INSTANCE pGraphNodeInstance = (PGRAPH_NODE_INSTANCE)pReference;
  398. Assert(this);
  399. Assert(pGraphNodeInstance);
  400. // Skip duplicate TopologyNodes
  401. if(ulSysaudioNodeNumber != MAXULONG) {
  402. DPF1(100, "AddTopologyNode: dup TN: %08x", this);
  403. goto exit;
  404. }
  405. ulSysaudioNodeNumber = pGraphNodeInstance->cTopologyNodes;
  406. if(pGraphNodeInstance->papTopologyNode != NULL) {
  407. pGraphNodeInstance->papTopologyNode[
  408. pGraphNodeInstance->cTopologyNodes] = this;
  409. }
  410. if(pGraphNodeInstance->Topology.TopologyNodes != NULL) {
  411. ((GUID *)(pGraphNodeInstance->Topology.TopologyNodes))[
  412. pGraphNodeInstance->cTopologyNodes] = *pguidType;
  413. }
  414. DPF3(115, "AddTopologyNode: %02x GNI: %08x TN: %08x",
  415. pGraphNodeInstance->cTopologyNodes,
  416. pGraphNodeInstance,
  417. this);
  418. ++pGraphNodeInstance->cTopologyNodes;
  419. exit:
  420. return(STATUS_CONTINUE);
  421. }
  422. VOID
  423. CGraphNodeInstance::AddTopologyConnection(
  424. ULONG ulFromNode,
  425. ULONG ulFromPin,
  426. ULONG ulToNode,
  427. ULONG ulToPin
  428. )
  429. {
  430. Assert(this);
  431. if(Topology.TopologyConnections != NULL) {
  432. PKSTOPOLOGY_CONNECTION pKSTopologyConnection =
  433. (PKSTOPOLOGY_CONNECTION)&Topology.TopologyConnections[
  434. cTopologyConnections];
  435. pKSTopologyConnection->FromNode = ulFromNode;
  436. pKSTopologyConnection->FromNodePin = ulFromPin;
  437. pKSTopologyConnection->ToNode = ulToNode;
  438. pKSTopologyConnection->ToNodePin = ulToPin;
  439. }
  440. ++cTopologyConnections;
  441. DPF4(115, "AddTopologyConnection: FN:%02x FNP:%02x TN:%02x TNP:%02x",
  442. ulFromNode,
  443. ulFromPin,
  444. ulToNode,
  445. ulToPin);
  446. }
  447. //---------------------------------------------------------------------------
  448. NTSTATUS
  449. CGraphNodeInstance::CreatePinDescriptors(
  450. )
  451. {
  452. NTSTATUS Status = STATUS_SUCCESS;
  453. ListDataAssertLess<LIST_DATA_START_NODE> lstStartNodeLists;
  454. ListDataAssertLess<KSDATARANGE> lstDataRange;
  455. PLIST_DATA_START_NODE plstStartNodeOrdered;
  456. PSTART_NODE pStartNodeSorted;
  457. PSTART_NODE pStartNode;
  458. BOOL fSorted;
  459. ULONG PinId;
  460. Assert(this);
  461. Assert(pGraphNode);
  462. ASSERT(paPinDescriptors == NULL);
  463. ASSERT(aplstStartNode == NULL);
  464. ASSERT(palstTopologyNodeSelect == NULL);
  465. ASSERT(palstTopologyNodeNotSelect == NULL);
  466. ASSERT(pacPinInstances == NULL);
  467. ASSERT(pulPinFlags == NULL);
  468. ASSERT(cPins == 0);
  469. #ifdef REGISTRY_PREFERRED_DEVICE
  470. // Clear the graph node preferred device type bits
  471. pGraphNode->ulFlags &= ~GN_FLAGS_PREFERRED_MASK;
  472. #endif
  473. // Sort StartNodes by Communication, DataFlow and Major Format GUID
  474. FOR_EACH_LIST_ITEM(&pGraphNode->lstStartNode, pStartNode) {
  475. Assert(pStartNode->pPinNode);
  476. Assert(pStartNode->pPinNode->pPinInfo);
  477. // Skip any start nodes with no data range
  478. if(pStartNode->pPinNode->pDataRange == NULL) {
  479. Trap();
  480. continue;
  481. }
  482. // Skip any start nodes with no instances left on the pin
  483. if(ulFlags & FLAGS_COMBINE_PINS) {
  484. if(pStartNode->pPinNode->pPinInfo->Communication ==
  485. KSPIN_COMMUNICATION_SINK ||
  486. pStartNode->pPinNode->pPinInfo->Communication ==
  487. KSPIN_COMMUNICATION_SOURCE ||
  488. pStartNode->pPinNode->pPinInfo->Communication ==
  489. KSPIN_COMMUNICATION_BOTH) {
  490. if(!pStartNode->IsPossibleInstances()) {
  491. continue;
  492. }
  493. }
  494. }
  495. fSorted = FALSE;
  496. FOR_EACH_LIST_ITEM(&lstStartNodeLists, plstStartNodeOrdered) {
  497. FOR_EACH_LIST_ITEM(plstStartNodeOrdered, pStartNodeSorted) {
  498. Assert(pStartNodeSorted);
  499. Assert(pStartNodeSorted->pPinNode);
  500. Assert(pStartNodeSorted->pPinNode->pPinInfo);
  501. // If the same actual pin, combine the pin nodes
  502. if((pStartNode->pPinNode->pPinInfo ==
  503. pStartNodeSorted->pPinNode->pPinInfo) ||
  504. // Combine only if client wants it that way
  505. (ulFlags & FLAGS_COMBINE_PINS) &&
  506. // Combine only AUDIO major formats
  507. IsEqualGUID(
  508. &pStartNode->pPinNode->pDataRange->MajorFormat,
  509. &KSDATAFORMAT_TYPE_AUDIO) &&
  510. // Only combine SINK, SOURCE, BOTH StartNodes; keep
  511. // NONE and BRIDGE as separate SAD pins
  512. ((pStartNode->pPinNode->pPinInfo->Communication ==
  513. KSPIN_COMMUNICATION_SINK) ||
  514. (pStartNode->pPinNode->pPinInfo->Communication ==
  515. KSPIN_COMMUNICATION_SOURCE) ||
  516. (pStartNode->pPinNode->pPinInfo->Communication ==
  517. KSPIN_COMMUNICATION_BOTH)) &&
  518. // Combine if same data flow
  519. (pStartNode->pPinNode->pPinInfo->DataFlow ==
  520. pStartNodeSorted->pPinNode->pPinInfo->DataFlow) &&
  521. // Combine if same communication type OR
  522. ((pStartNode->pPinNode->pPinInfo->Communication ==
  523. pStartNodeSorted->pPinNode->pPinInfo->Communication) ||
  524. // Combine a SINK and a BOTH
  525. ((pStartNode->pPinNode->pPinInfo->Communication ==
  526. KSPIN_COMMUNICATION_SINK) &&
  527. (pStartNodeSorted->pPinNode->pPinInfo->Communication ==
  528. KSPIN_COMMUNICATION_BOTH)) ||
  529. // Combine a BOTH and a SINK
  530. ((pStartNode->pPinNode->pPinInfo->Communication ==
  531. KSPIN_COMMUNICATION_BOTH) &&
  532. (pStartNodeSorted->pPinNode->pPinInfo->Communication ==
  533. KSPIN_COMMUNICATION_SINK)) ||
  534. // Combine a SOURCE and a BOTH
  535. ((pStartNode->pPinNode->pPinInfo->Communication ==
  536. KSPIN_COMMUNICATION_SOURCE) &&
  537. (pStartNodeSorted->pPinNode->pPinInfo->Communication ==
  538. KSPIN_COMMUNICATION_BOTH)) ||
  539. // Combine a BOTH and a SOURCE
  540. ((pStartNode->pPinNode->pPinInfo->Communication ==
  541. KSPIN_COMMUNICATION_BOTH) &&
  542. (pStartNodeSorted->pPinNode->pPinInfo->Communication ==
  543. KSPIN_COMMUNICATION_SOURCE))) &&
  544. // Combine if major format is the same
  545. IsEqualGUID(
  546. &pStartNode->pPinNode->pDataRange->MajorFormat,
  547. &pStartNodeSorted->pPinNode->pDataRange->MajorFormat)) {
  548. Status = plstStartNodeOrdered->AddListOrdered(
  549. pStartNode,
  550. FIELD_OFFSET(START_NODE, ulOverhead));
  551. if(!NT_SUCCESS(Status)) {
  552. goto exit;
  553. }
  554. fSorted = TRUE;
  555. break;
  556. }
  557. } END_EACH_LIST_ITEM
  558. if(fSorted) {
  559. break;
  560. }
  561. } END_EACH_LIST_ITEM
  562. if(!fSorted) {
  563. plstStartNodeOrdered = new LIST_DATA_START_NODE;
  564. if(plstStartNodeOrdered == NULL) {
  565. Status = STATUS_INSUFFICIENT_RESOURCES;
  566. goto exit;
  567. }
  568. Status = plstStartNodeOrdered->AddListOrdered(
  569. pStartNode,
  570. FIELD_OFFSET(START_NODE, ulOverhead));
  571. if(!NT_SUCCESS(Status)) {
  572. goto exit;
  573. }
  574. Status = lstStartNodeLists.AddList(plstStartNodeOrdered);
  575. if(!NT_SUCCESS(Status)) {
  576. goto exit;
  577. }
  578. }
  579. } END_EACH_LIST_ITEM
  580. // Allocate the pin descriptors, pin instance and start node arrays
  581. cPins = lstStartNodeLists.CountList();
  582. // if there are no pins, exit
  583. if(cPins == 0) {
  584. goto exit;
  585. }
  586. paPinDescriptors = new KSPIN_DESCRIPTOR[cPins];
  587. if(paPinDescriptors == NULL) {
  588. Status = STATUS_INSUFFICIENT_RESOURCES;
  589. goto exit;
  590. }
  591. aplstStartNode = new PLIST_DATA_START_NODE[cPins];
  592. if(aplstStartNode == NULL) {
  593. Status = STATUS_INSUFFICIENT_RESOURCES;
  594. goto exit;
  595. }
  596. DPF1(100, "CreatePinDescriptors: cPins %d", cPins);
  597. // For each pin, create a list of interfaces, mediums and dataranges
  598. PinId = 0;
  599. FOR_EACH_LIST_ITEM(&lstStartNodeLists, plstStartNodeOrdered) {
  600. PKSDATARANGE pDataRange, *apDataRanges;
  601. BOOL fBoth = TRUE;
  602. ASSERT(PinId < cPins);
  603. ASSERT(!plstStartNodeOrdered->IsLstEmpty());
  604. aplstStartNode[PinId] = plstStartNodeOrdered;
  605. FOR_EACH_LIST_ITEM(plstStartNodeOrdered, pStartNode) {
  606. Assert(pStartNode);
  607. Assert(pStartNode->pPinNode);
  608. Assert(pStartNode->pPinNode->pPinInfo);
  609. paPinDescriptors[PinId].DataFlow =
  610. pStartNode->pPinNode->pPinInfo->DataFlow;
  611. if(pStartNode->pPinNode->pPinInfo->Communication !=
  612. KSPIN_COMMUNICATION_BOTH) {
  613. fBoth = FALSE;
  614. paPinDescriptors[PinId].Communication =
  615. pStartNode->pPinNode->pPinInfo->Communication;
  616. }
  617. if(paPinDescriptors[PinId].Category == NULL ||
  618. IsEqualGUID(
  619. paPinDescriptors[PinId].Category,
  620. &GUID_NULL)) {
  621. paPinDescriptors[PinId].Category =
  622. pStartNode->pPinNode->pPinInfo->pguidCategory;
  623. paPinDescriptors[PinId].Name =
  624. pStartNode->pPinNode->pPinInfo->pguidName;
  625. }
  626. } END_EACH_LIST_ITEM
  627. if(fBoth) {
  628. paPinDescriptors[PinId].Communication = KSPIN_COMMUNICATION_SINK;
  629. }
  630. // Make a list of all the DataRanges this pin will support
  631. Status = plstStartNodeOrdered->CreateUniqueList(
  632. &lstDataRange,
  633. (UNIQUE_LIST_PFN)GetStartNodeDataRange,
  634. (UNIQUE_LIST_PFN2)CompareDataRangeExact);
  635. if(!NT_SUCCESS(Status)) {
  636. goto exit;
  637. }
  638. // Put the number of data ranges into the pin descriptor
  639. paPinDescriptors[PinId].DataRangesCount = lstDataRange.CountList();
  640. if(paPinDescriptors[PinId].DataRangesCount != 0) {
  641. // Allocate the array of ptrs to DataRanges; put it into the desc
  642. paPinDescriptors[PinId].DataRanges = new PKSDATARANGE[
  643. paPinDescriptors[PinId].DataRangesCount];
  644. if(paPinDescriptors[PinId].DataRanges == NULL) {
  645. Status = STATUS_INSUFFICIENT_RESOURCES;
  646. goto exit;
  647. }
  648. // Put each data range pointer into the array
  649. apDataRanges = (PKSDATARANGE *)paPinDescriptors[PinId].DataRanges;
  650. FOR_EACH_LIST_ITEM(&lstDataRange, pDataRange) {
  651. #ifdef REGISTRY_PREFERRED_DEVICE
  652. if(IsEqualGUID(
  653. &pDataRange->MajorFormat,
  654. &KSDATAFORMAT_TYPE_AUDIO) &&
  655. IsEqualGUID(
  656. &pDataRange->SubFormat,
  657. &KSDATAFORMAT_SUBTYPE_PCM)) {
  658. if(paPinDescriptors[PinId].DataFlow == KSPIN_DATAFLOW_IN) {
  659. pGraphNode->ulFlags |= GN_FLAGS_PLAYBACK;
  660. }
  661. else {
  662. pGraphNode->ulFlags |= GN_FLAGS_RECORD;
  663. }
  664. }
  665. if(IsEqualGUID(
  666. &pDataRange->MajorFormat,
  667. &KSDATAFORMAT_TYPE_MUSIC) &&
  668. IsEqualGUID(
  669. &pDataRange->SubFormat,
  670. &KSDATAFORMAT_SUBTYPE_MIDI)) {
  671. if(paPinDescriptors[PinId].DataFlow == KSPIN_DATAFLOW_IN) {
  672. pGraphNode->ulFlags |= GN_FLAGS_MIDI;
  673. }
  674. }
  675. #endif
  676. *apDataRanges = pDataRange;
  677. apDataRanges++;
  678. } END_EACH_LIST_ITEM
  679. }
  680. // Destroy the data range list
  681. lstDataRange.DestroyList();
  682. // Create the interface array for the pin descriptor
  683. Status = CreateIdentifierArray(
  684. plstStartNodeOrdered,
  685. &paPinDescriptors[PinId].InterfacesCount,
  686. (PKSIDENTIFIER *)&paPinDescriptors[PinId].Interfaces,
  687. GetStartNodeInterface);
  688. if(!NT_SUCCESS(Status)) {
  689. goto exit;
  690. }
  691. // Create the medium array for the pin descriptor
  692. Status = CreateIdentifierArray(
  693. plstStartNodeOrdered,
  694. &paPinDescriptors[PinId].MediumsCount,
  695. (PKSIDENTIFIER *)&paPinDescriptors[PinId].Mediums,
  696. GetStartNodeMedium);
  697. if(!NT_SUCCESS(Status)) {
  698. goto exit;
  699. }
  700. DPF6(100, "PinId %d DataFlow %d cD %d cI %d cM %d cSN %d",
  701. PinId,
  702. paPinDescriptors[PinId].DataFlow,
  703. paPinDescriptors[PinId].DataRangesCount,
  704. paPinDescriptors[PinId].InterfacesCount,
  705. paPinDescriptors[PinId].MediumsCount,
  706. aplstStartNode[PinId]->CountList());
  707. // Next pin number
  708. PinId++;
  709. } END_EACH_LIST_ITEM
  710. if((ulFlags & FLAGS_MIXER_TOPOLOGY) == 0) {
  711. palstTopologyNodeSelect = new LIST_DATA_TOPOLOGY_NODE[cPins];
  712. if(palstTopologyNodeSelect == NULL) {
  713. Status = STATUS_INSUFFICIENT_RESOURCES;
  714. goto exit;
  715. }
  716. palstTopologyNodeNotSelect = new LIST_DATA_TOPOLOGY_NODE[cPins];
  717. if(palstTopologyNodeNotSelect == NULL) {
  718. Status = STATUS_INSUFFICIENT_RESOURCES;
  719. goto exit;
  720. }
  721. PLOGICAL_FILTER_NODE pLogicalFilterNode;
  722. PTOPOLOGY_NODE pTopologyNode;
  723. FOR_EACH_LIST_ITEM(
  724. &pGraphNode->lstLogicalFilterNode,
  725. pLogicalFilterNode) {
  726. if(pLogicalFilterNode->GetFlags() & LFN_FLAGS_NOT_SELECT) {
  727. FOR_EACH_LIST_ITEM(
  728. &pLogicalFilterNode->lstTopologyNode,
  729. pTopologyNode) {
  730. for(PinId = 0; PinId < cPins; PinId++) {
  731. Status = palstTopologyNodeNotSelect[PinId].AddList(
  732. pTopologyNode);
  733. if(!NT_SUCCESS(Status)) {
  734. goto exit;
  735. }
  736. }
  737. } END_EACH_LIST_ITEM
  738. }
  739. } END_EACH_LIST_ITEM
  740. }
  741. pacPinInstances = new KSPIN_CINSTANCES[cPins];
  742. if(pacPinInstances == NULL) {
  743. Status = STATUS_INSUFFICIENT_RESOURCES;
  744. goto exit;
  745. }
  746. pulPinFlags = new ULONG[cPins];
  747. if (NULL == pulPinFlags) {
  748. Status = STATUS_INSUFFICIENT_RESOURCES;
  749. goto exit;
  750. }
  751. for(PinId = 0; PinId < cPins; PinId++) {
  752. LIST_DATA_GRAPH_PIN_INFO lstGraphPinInfo;
  753. PSTART_NODE pStartNode2;
  754. PPIN_INFO pPinInfo;
  755. BOOL fHWRender = TRUE;
  756. FOR_EACH_LIST_ITEM(aplstStartNode[PinId], pStartNode2) {
  757. PGRAPH_PIN_INFO pGraphPinInfo;
  758. pGraphPinInfo = pStartNode2->GetGraphPinInfo();
  759. Assert(pGraphPinInfo);
  760. //
  761. // Set pin type.
  762. // If all startnodes are connected directly to renderer.
  763. //
  764. pPinInfo = pGraphPinInfo->GetPinInfo();
  765. ASSERT(pPinInfo);
  766. if ((!(pPinInfo->pFilterNode->GetType() & FILTER_TYPE_RENDERER)) ||
  767. (KSPIN_DATAFLOW_IN != pPinInfo->DataFlow) ||
  768. (KSPIN_COMMUNICATION_SINK != pPinInfo->Communication)) {
  769. fHWRender = FALSE;
  770. }
  771. if(lstGraphPinInfo.CheckDupList(pGraphPinInfo)) {
  772. continue;
  773. }
  774. Status = lstGraphPinInfo.AddList(pGraphPinInfo);
  775. if(!NT_SUCCESS(Status)) {
  776. goto exit;
  777. }
  778. //
  779. // Set cinstances.
  780. //
  781. if(pGraphPinInfo->IsPinReserved()) {
  782. pacPinInstances[PinId].CurrentCount = 1;
  783. }
  784. if(pGraphPinInfo->GetPinInstances()->PossibleCount == MAXULONG) {
  785. pacPinInstances[PinId].PossibleCount = MAXULONG;
  786. break;
  787. }
  788. pacPinInstances[PinId].PossibleCount +=
  789. pGraphPinInfo->GetPinInstances()->PossibleCount;
  790. if (fHWRender) {
  791. fHWRender = (1 < pGraphPinInfo->GetPinInstances()->PossibleCount);
  792. }
  793. } END_EACH_LIST_ITEM
  794. pulPinFlags[PinId] = fHWRender;
  795. lstGraphPinInfo.DestroyList();
  796. }
  797. exit:
  798. if(!NT_SUCCESS(Status)) {
  799. DestroyPinDescriptors();
  800. }
  801. return(Status);
  802. }
  803. VOID
  804. CGraphNodeInstance::DestroyPinDescriptors(
  805. )
  806. {
  807. ULONG PinId;
  808. Assert(this);
  809. for(PinId = 0; PinId < cPins; PinId++) {
  810. if(paPinDescriptors != NULL) {
  811. delete (PVOID)paPinDescriptors[PinId].DataRanges;
  812. if(paPinDescriptors[PinId].InterfacesCount > 1) {
  813. delete (PVOID)paPinDescriptors[PinId].Interfaces;
  814. }
  815. if(paPinDescriptors[PinId].MediumsCount > 1) {
  816. delete (PVOID)paPinDescriptors[PinId].Mediums;
  817. }
  818. }
  819. if(aplstStartNode != NULL) {
  820. delete aplstStartNode[PinId];
  821. }
  822. }
  823. delete[cPins] aplstStartNode;
  824. aplstStartNode = NULL;
  825. delete[cPins] paPinDescriptors;
  826. paPinDescriptors = NULL;
  827. delete[cPins] palstTopologyNodeSelect;
  828. palstTopologyNodeSelect = NULL;
  829. delete[cPins] palstTopologyNodeNotSelect;
  830. palstTopologyNodeNotSelect = NULL;
  831. delete[cPins] pacPinInstances;
  832. pacPinInstances = NULL;
  833. delete[cPins] pulPinFlags;
  834. pulPinFlags = NULL;
  835. }
  836. NTSTATUS
  837. CreateIdentifierArray(
  838. PLIST_DATA_START_NODE plstStartNode,
  839. PULONG pulCount,
  840. PKSIDENTIFIER *ppIdentifier,
  841. PKSIDENTIFIER (*GetFunction)(
  842. PSTART_NODE pStartNode
  843. )
  844. )
  845. {
  846. NTSTATUS Status = STATUS_SUCCESS;
  847. KSIDENTIFIER *pIdentifier1, *pIdentifier2;
  848. ListDataAssertLess<KSIDENTIFIER> lstIdentifier;
  849. Status = plstStartNode->CreateUniqueList(
  850. &lstIdentifier,
  851. (UNIQUE_LIST_PFN)GetFunction,
  852. (UNIQUE_LIST_PFN2)CompareIdentifier);
  853. if(!NT_SUCCESS(Status)) {
  854. goto exit;
  855. }
  856. if((*pulCount = lstIdentifier.CountList()) == 0) {
  857. *ppIdentifier = NULL;
  858. }
  859. else {
  860. if(*pulCount == 1) {
  861. *ppIdentifier = lstIdentifier.GetListFirstData();
  862. }
  863. else {
  864. *ppIdentifier = new KSIDENTIFIER[*pulCount];
  865. if(*ppIdentifier == NULL) {
  866. Status = STATUS_INSUFFICIENT_RESOURCES;
  867. goto exit;
  868. }
  869. pIdentifier1 = *ppIdentifier;
  870. AssertAligned(pIdentifier1);
  871. FOR_EACH_LIST_ITEM(&lstIdentifier, pIdentifier2) {
  872. AssertAligned(pIdentifier1);
  873. AssertAligned(pIdentifier2);
  874. RtlCopyMemory(pIdentifier1, pIdentifier2, sizeof(KSIDENTIFIER));
  875. pIdentifier1++;
  876. } END_EACH_LIST_ITEM
  877. }
  878. }
  879. exit:
  880. return(Status);
  881. }
  882. PKSDATARANGE
  883. GetStartNodeDataRange(
  884. PSTART_NODE pStartNode
  885. )
  886. {
  887. return(pStartNode->pPinNode->pDataRange);
  888. }
  889. PKSIDENTIFIER
  890. GetStartNodeInterface(
  891. PSTART_NODE pStartNode
  892. )
  893. {
  894. return(pStartNode->pPinNode->pInterface);
  895. }
  896. PKSIDENTIFIER
  897. GetStartNodeMedium(
  898. PSTART_NODE pStartNode
  899. )
  900. {
  901. return(pStartNode->pPinNode->pMedium);
  902. }
  903. //---------------------------------------------------------------------------
  904. ENUMFUNC
  905. FindTopologyNode(
  906. IN PTOPOLOGY_CONNECTION pTopologyConnection,
  907. IN BOOL fToDirection,
  908. IN PTOPOLOGY_NODE pTopologyNode
  909. )
  910. {
  911. Assert(pTopologyConnection);
  912. if(IS_CONNECTION_TYPE(pTopologyConnection, GRAPH)) {
  913. return(STATUS_DEAD_END);
  914. }
  915. if(fToDirection) {
  916. if(pTopologyConnection->pTopologyPinTo != NULL) {
  917. if(pTopologyNode ==
  918. pTopologyConnection->pTopologyPinTo->pTopologyNode) {
  919. return(STATUS_SUCCESS);
  920. }
  921. }
  922. }
  923. else {
  924. if(pTopologyConnection->pTopologyPinFrom != NULL) {
  925. if(pTopologyNode ==
  926. pTopologyConnection->pTopologyPinFrom->pTopologyNode) {
  927. return(STATUS_SUCCESS);
  928. }
  929. }
  930. }
  931. return(STATUS_CONTINUE);
  932. }
  933. BOOL
  934. CGraphNodeInstance::IsGraphValid(
  935. PSTART_NODE pStartNode,
  936. ULONG PinId
  937. )
  938. {
  939. PFILTER_INSTANCE pFilterInstance;
  940. PTOPOLOGY_NODE pTopologyNode;
  941. BOOL fCheck;
  942. Assert(this);
  943. Assert(pGraphNode);
  944. Assert(pStartNode);
  945. Assert(pStartNode->pPinNode);
  946. Assert(pStartNode->pPinNode->pPinInfo);
  947. Assert(pGraphNode->pDeviceNode);
  948. ASSERT(PinId < cPins);
  949. if(pStartNode->pPinNode->pPinInfo->DataFlow == KSPIN_DATAFLOW_IN) {
  950. FOR_EACH_LIST_ITEM(
  951. &pGraphNode->pDeviceNode->lstFilterInstance,
  952. pFilterInstance) {
  953. if(pFilterInstance->pGraphNodeInstance == NULL) {
  954. continue;
  955. }
  956. Assert(pFilterInstance->pGraphNodeInstance);
  957. FOR_EACH_LIST_ITEM(
  958. &pFilterInstance->pGraphNodeInstance->lstTopologyNodeGlobalSelect,
  959. pTopologyNode) {
  960. if(EnumerateGraphTopology(
  961. pStartNode->GetStartInfo(),
  962. (TOP_PFN)FindTopologyNode,
  963. pTopologyNode) == STATUS_CONTINUE) {
  964. DPF2(80,
  965. "IsGraphValid: TN %08x SN %08x not found Global",
  966. pTopologyNode,
  967. pStartNode);
  968. return(FALSE);
  969. }
  970. } END_EACH_LIST_ITEM
  971. } END_EACH_LIST_ITEM
  972. }
  973. if (palstTopologyNodeSelect) {
  974. FOR_EACH_LIST_ITEM(&palstTopologyNodeSelect[PinId], pTopologyNode) {
  975. if(EnumerateGraphTopology(
  976. pStartNode->GetStartInfo(),
  977. (TOP_PFN)FindTopologyNode,
  978. pTopologyNode) == STATUS_CONTINUE) {
  979. DPF2(80, "IsGraphValid: TN %08x SN %08x not found Select",
  980. pTopologyNode,
  981. pStartNode);
  982. return(FALSE);
  983. }
  984. } END_EACH_LIST_ITEM
  985. }
  986. // If a NotSelectNode is in the GlobalSelectList of another FilterInstance,
  987. // don't consider this as an invalid Graph.
  988. // This behaves like an implicit SelectGraph.
  989. //
  990. if (palstTopologyNodeNotSelect) {
  991. FOR_EACH_LIST_ITEM(&palstTopologyNodeNotSelect[PinId], pTopologyNode) {
  992. fCheck = TRUE;
  993. if(pStartNode->pPinNode->pPinInfo->DataFlow == KSPIN_DATAFLOW_IN) {
  994. FOR_EACH_LIST_ITEM(
  995. &pGraphNode->pDeviceNode->lstFilterInstance,
  996. pFilterInstance) {
  997. if(pFilterInstance->pGraphNodeInstance == NULL) {
  998. continue;
  999. }
  1000. Assert(pFilterInstance->pGraphNodeInstance);
  1001. // Is this NotSelectNode in the GlobalSelectList of
  1002. // another FilterInstance.
  1003. // Remove it from NotSelectList and add it to
  1004. // GlobalSelectList for this filter as well.
  1005. //
  1006. if(pFilterInstance->pGraphNodeInstance->
  1007. lstTopologyNodeGlobalSelect.EnumerateList(
  1008. CTopologyNode::MatchTopologyNode,
  1009. pTopologyNode) == STATUS_SUCCESS) {
  1010. if (NT_SUCCESS(lstTopologyNodeGlobalSelect.
  1011. AddListDup(pTopologyNode))) {
  1012. palstTopologyNodeNotSelect[PinId].
  1013. RemoveList(pTopologyNode);
  1014. DPF2(50, "Removing TN %X %s",
  1015. pTopologyNode,
  1016. pTopologyNode->pFilterNode->DumpName());
  1017. }
  1018. else {
  1019. DPF2(4, "Failed to add TN %X to GNI %X GlobalSelectList",
  1020. pTopologyNode,
  1021. this);
  1022. Trap();
  1023. }
  1024. fCheck = FALSE;
  1025. break;
  1026. }
  1027. } END_EACH_LIST_ITEM
  1028. }
  1029. if(fCheck) {
  1030. if(EnumerateGraphTopology(
  1031. pStartNode->GetStartInfo(),
  1032. (TOP_PFN)FindTopologyNode,
  1033. pTopologyNode) == STATUS_SUCCESS) {
  1034. DPF2(80, "IsGraphValid: TN %08x SN %08x found NotSelect",
  1035. pTopologyNode,
  1036. pStartNode);
  1037. return(FALSE);
  1038. }
  1039. }
  1040. } END_EACH_LIST_ITEM
  1041. }
  1042. return(TRUE);
  1043. }
  1044. NTSTATUS
  1045. CGraphNodeInstance::GetPinInstances(
  1046. PIRP pIrp,
  1047. PKSP_PIN pPin,
  1048. PKSPIN_CINSTANCES pcInstances
  1049. )
  1050. {
  1051. NTSTATUS Status;
  1052. ULONG ulPinId = pPin->PinId;
  1053. //
  1054. // For HW Accelerated pins, send the request to HW filter.
  1055. //
  1056. if (pulPinFlags[ulPinId]) {
  1057. PSTART_NODE pStartNode;
  1058. PPIN_INFO pPinInfo;
  1059. ULONG BytesReturned;
  1060. PIO_STACK_LOCATION pIrpStack;
  1061. PFILTER_NODE_INSTANCE pFilterNodeInstance = NULL;
  1062. pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  1063. pStartNode = aplstStartNode[ulPinId]->GetListFirstData();
  1064. pPinInfo = pStartNode->pPinNode->pPinInfo;
  1065. Status = CFilterNodeInstance::Create(
  1066. &pFilterNodeInstance,
  1067. pStartNode->pPinNode->pLogicalFilterNode,
  1068. pGraphNode->pDeviceNode,
  1069. TRUE);
  1070. if(NT_SUCCESS(Status)) {
  1071. pPin->PinId = pPinInfo->PinId;
  1072. pPin->Property.Id = KSPROPERTY_PIN_CINSTANCES;
  1073. AssertFileObject(pFilterNodeInstance->pFileObject);
  1074. Status = KsSynchronousIoControlDevice(
  1075. pFilterNodeInstance->pFileObject,
  1076. KernelMode,
  1077. IOCTL_KS_PROPERTY,
  1078. pPin,
  1079. pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
  1080. pcInstances,
  1081. pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
  1082. &BytesReturned);
  1083. if(NT_SUCCESS(Status)) {
  1084. pIrp->IoStatus.Information = BytesReturned;
  1085. }
  1086. if (pFilterNodeInstance) {
  1087. pFilterNodeInstance->Destroy();
  1088. }
  1089. }
  1090. else {
  1091. DPF2(10, "GetPinInstances FAILS %08x %s",
  1092. Status,
  1093. pPinInfo->pFilterNode->DumpName());
  1094. }
  1095. }
  1096. //
  1097. // For other pins use the cached instances
  1098. //
  1099. else {
  1100. Status = STATUS_SUCCESS;
  1101. *pcInstances = pacPinInstances[ulPinId];
  1102. }
  1103. return Status;
  1104. } // GetPinInstances
  1105. BOOL
  1106. CGraphNodeInstance::IsPinInstances(
  1107. ULONG ulPinId)
  1108. {
  1109. //
  1110. // For HW Accelerated pins, always allow further operations.
  1111. //
  1112. if (pulPinFlags[ulPinId]) {
  1113. return TRUE;
  1114. }
  1115. //
  1116. // For other pins check cached instances.
  1117. //
  1118. else
  1119. {
  1120. if(pacPinInstances[ulPinId].CurrentCount >=
  1121. pacPinInstances[ulPinId].PossibleCount) {
  1122. return FALSE;
  1123. }
  1124. }
  1125. return TRUE;
  1126. } // IsPinInstances
  1127. //---------------------------------------------------------------------------
  1128. #ifdef DEBUG
  1129. ENUMFUNC
  1130. CGraphNodeInstance::Dump()
  1131. {
  1132. // .siv
  1133. if(ulDebugFlags & (DEBUG_FLAGS_VERBOSE | DEBUG_FLAGS_OBJECT)) {
  1134. dprintf("GNI: %08x GN %08x FI %08x cPins %u cTN %u cTC %u paulNN ",
  1135. this,
  1136. pGraphNode,
  1137. pFilterInstance,
  1138. cPins,
  1139. cTopologyNodes,
  1140. cTopologyConnections);
  1141. for(ULONG i = 0; i < gcVirtualSources; i++) {
  1142. dprintf("%02x ", paulNodeNumber[i]);
  1143. }
  1144. dprintf("\n paPinDesc: %08x papTN %08x ulFlags %08x ",
  1145. paPinDescriptors,
  1146. papTopologyNode,
  1147. ulFlags);
  1148. if(ulFlags & FLAGS_COMBINE_PINS) {
  1149. dprintf("COMBINE_PINS ");
  1150. }
  1151. if(ulFlags & FLAGS_MIXER_TOPOLOGY) {
  1152. dprintf("MIXER_TOPOLOGY ");
  1153. }
  1154. dprintf("\n aplstSN: %08x papFNI %08x palstTN %08x !%08x\n",
  1155. aplstStartNode,
  1156. papFilterNodeInstanceTopologyTable,
  1157. palstTopologyNodeSelect,
  1158. palstTopologyNodeNotSelect);
  1159. dprintf(" pacPI: %08x ", pacPinInstances);
  1160. for(ULONG p = 0; p < cPins; p++) {
  1161. dprintf("[C%dP%d]",
  1162. pacPinInstances[p].CurrentCount,
  1163. pacPinInstances[p].PossibleCount);
  1164. }
  1165. dprintf("\n lstTNGlobalSelect:");
  1166. lstTopologyNodeGlobalSelect.DumpAddress();
  1167. dprintf("\n lstSNI:");
  1168. // .sivx
  1169. if(ulDebugFlags & DEBUG_FLAGS_DETAILS) {
  1170. dprintf("\n");
  1171. lstStartNodeInstance.Dump();
  1172. }
  1173. else {
  1174. lstStartNodeInstance.DumpAddress();
  1175. dprintf("\n");
  1176. }
  1177. }
  1178. // .sit
  1179. if(ulDebugFlags & DEBUG_FLAGS_TOPOLOGY) {
  1180. dprintf("GNI: %08x\n", this);
  1181. for(ULONG i = 0; i < cTopologyNodes; i++) {
  1182. if(papFilterNodeInstanceTopologyTable[i] != NULL) {
  1183. dprintf(" %02x FNI %08x %s\n",
  1184. i,
  1185. papFilterNodeInstanceTopologyTable[i],
  1186. papTopologyNode[i]->pFilterNode->DumpName());
  1187. }
  1188. }
  1189. }
  1190. // .sip
  1191. if(ulDebugFlags & DEBUG_FLAGS_PIN) {
  1192. dprintf("GNI: %08x\n", this);
  1193. DumpPinDescriptors();
  1194. }
  1195. return(STATUS_CONTINUE);
  1196. }
  1197. extern PSZ apszDataFlow[];
  1198. extern PSZ apszCommunication[];
  1199. VOID
  1200. CGraphNodeInstance::DumpPinDescriptors(
  1201. )
  1202. {
  1203. ULONG p, i, m, d;
  1204. Assert(this);
  1205. for(p = 0; p < cPins; p++) {
  1206. dprintf(
  1207. "PinId: %d DataFlow %08x %s Comm %08x %s cPossible %d cCurrent %d\n",
  1208. p,
  1209. paPinDescriptors[p].DataFlow,
  1210. apszDataFlow[paPinDescriptors[p].DataFlow],
  1211. paPinDescriptors[p].Communication,
  1212. apszCommunication[paPinDescriptors[p].Communication],
  1213. pacPinInstances[p].CurrentCount,
  1214. pacPinInstances[p].PossibleCount);
  1215. dprintf(" Category: %s\n",
  1216. DbgGuid2Sz((GUID*)paPinDescriptors[p].Category));
  1217. dprintf(" Name: %s\n",
  1218. DbgGuid2Sz((GUID*)paPinDescriptors[p].Name));
  1219. dprintf(" palstTNSelect:");
  1220. palstTopologyNodeSelect[p].DumpAddress();
  1221. dprintf("\n");
  1222. dprintf(" palstTNNot:");
  1223. palstTopologyNodeNotSelect[p].DumpAddress();
  1224. dprintf("\n");
  1225. // .sipv
  1226. if(ulDebugFlags & DEBUG_FLAGS_VERBOSE) {
  1227. for(i = 0;
  1228. i < paPinDescriptors[p].InterfacesCount;
  1229. i++) {
  1230. dprintf(" Interface %u: %s\n",
  1231. i,
  1232. DbgIdentifier2Sz((PKSIDENTIFIER)
  1233. &paPinDescriptors[p].Interfaces[i]));
  1234. }
  1235. for(m = 0; m < paPinDescriptors[p].MediumsCount; m++) {
  1236. dprintf(" Medium %u: %s\n",
  1237. m,
  1238. DbgIdentifier2Sz((PKSIDENTIFIER)
  1239. &paPinDescriptors[p].Mediums[m]));
  1240. }
  1241. for(d = 0; d < paPinDescriptors[p].DataRangesCount; d++) {
  1242. dprintf(" DataRange %u:\n", d);
  1243. dprintf(" MajorFormat: %s\n",
  1244. DbgGuid2Sz(&paPinDescriptors[p].DataRanges[d]->MajorFormat));
  1245. dprintf(" SubFormat: %s\n",
  1246. DbgGuid2Sz(&paPinDescriptors[p].DataRanges[d]->SubFormat));
  1247. dprintf(" Specifier: %s\n",
  1248. DbgGuid2Sz(&paPinDescriptors[p].DataRanges[d]->Specifier));
  1249. dprintf(" ");
  1250. DumpDataRangeAudio((PKSDATARANGE_AUDIO)
  1251. paPinDescriptors[p].DataRanges[d]);
  1252. }
  1253. }
  1254. // .sipx
  1255. if(ulDebugFlags & DEBUG_FLAGS_DETAILS) {
  1256. if(ulDebugFlags & DEBUG_FLAGS_VERBOSE) {
  1257. dprintf(" aplstSN:\n");
  1258. }
  1259. aplstStartNode[p]->Dump();
  1260. }
  1261. dprintf("\n");
  1262. }
  1263. }
  1264. #endif
  1265. //---------------------------------------------------------------------------