Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

629 lines
19 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Module: tc.cpp
  4. //
  5. // Description:
  6. //
  7. // Topology Connection Class
  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. ULONG gcTopologyConnections = 0;
  30. //---------------------------------------------------------------------------
  31. //---------------------------------------------------------------------------
  32. CTopologyConnection::CTopologyConnection(
  33. PTOPOLOGY_PIN pTopologyPinFrom,
  34. PTOPOLOGY_PIN pTopologyPinTo,
  35. PPIN_INFO pPinInfoFrom,
  36. PPIN_INFO pPinInfoTo
  37. )
  38. {
  39. DPF4(110,
  40. "CTopologyConnection: PIF: %08x PIT: %08x TPF: %08x TPT: %08x",
  41. pPinInfoFrom,
  42. pPinInfoTo,
  43. pTopologyPinFrom,
  44. pTopologyPinTo);
  45. this->pTopologyPinFrom = pTopologyPinFrom;
  46. this->pTopologyPinTo = pTopologyPinTo;
  47. this->pPinInfoFrom = pPinInfoFrom;
  48. this->pPinInfoTo = pPinInfoTo;
  49. ASSERT(TOPC_FLAGS_FILTER_CONNECTION_TYPE == 0);
  50. ++gcTopologyConnections;
  51. DPF1(70, "CTopologyConnection: %08x", this);
  52. }
  53. CTopologyConnection::~CTopologyConnection(
  54. )
  55. {
  56. Assert(this);
  57. DPF1(70, "~CTopologyConnection: %08x", this);
  58. --gcTopologyConnections;
  59. }
  60. NTSTATUS
  61. CTopologyConnection::Create(
  62. PTOPOLOGY_CONNECTION *ppTopologyConnection,
  63. PFILTER_NODE pFilterNode,
  64. PGRAPH_NODE pGraphNode,
  65. PTOPOLOGY_PIN pTopologyPinFrom,
  66. PTOPOLOGY_PIN pTopologyPinTo,
  67. PPIN_INFO pPinInfoFrom,
  68. PPIN_INFO pPinInfoTo
  69. )
  70. {
  71. NTSTATUS Status = STATUS_SUCCESS;
  72. PTOPOLOGY_CONNECTION pTopologyConnection;
  73. PLIST_DESTROY_TOPOLOGY_CONNECTION plstTopologyConnection;
  74. PFILTER_NODE pFilterNodeNext;
  75. DPF4(110,
  76. "CTopologyConnection::Create: PIF: %08x PIT: %08x TPF: %08x TPT: %08x",
  77. pPinInfoFrom,
  78. pPinInfoTo,
  79. pTopologyPinFrom,
  80. pTopologyPinTo);
  81. ASSERT(pFilterNode != NULL || pGraphNode != NULL);
  82. pTopologyConnection = new TOPOLOGY_CONNECTION(
  83. pTopologyPinFrom,
  84. pTopologyPinTo,
  85. pPinInfoFrom,
  86. pPinInfoTo
  87. );
  88. if(pTopologyConnection == NULL) {
  89. Status = STATUS_INSUFFICIENT_RESOURCES;
  90. Trap();
  91. goto exit;
  92. }
  93. *ppTopologyConnection = pTopologyConnection;
  94. if(pFilterNode != NULL) {
  95. Assert(pFilterNode);
  96. ASSERT(pGraphNode == NULL);
  97. // Adding connection to filter connection list
  98. plstTopologyConnection = &pFilterNode->lstTopologyConnection;
  99. // Check if duplicate connection on filter list
  100. FOR_EACH_LIST_ITEM(
  101. &pFilterNode->lstConnectedFilterNode,
  102. pFilterNodeNext) {
  103. if(pFilterNodeNext->lstTopologyConnection.EnumerateList(
  104. CTopologyConnection::CheckDuplicate,
  105. ppTopologyConnection) == STATUS_SUCCESS) {
  106. ASSERT(NT_SUCCESS(Status));
  107. DPF(70, "CTopologyConnection::Create: Duplicate 1");
  108. delete pTopologyConnection;
  109. goto exit;
  110. }
  111. } END_EACH_LIST_ITEM
  112. }
  113. if(pGraphNode != NULL) {
  114. PLOGICAL_FILTER_NODE pLogicalFilterNode;
  115. Assert(pGraphNode);
  116. ASSERT(pFilterNode == NULL);
  117. // Adding connection to GraphNode connection list
  118. plstTopologyConnection = &pGraphNode->lstTopologyConnection;
  119. // Check if duplicate on GraphNode's logical filter list
  120. FOR_EACH_LIST_ITEM(
  121. &pGraphNode->pDeviceNode->lstLogicalFilterNode,
  122. pLogicalFilterNode) {
  123. if(pLogicalFilterNode->lstTopologyConnection.EnumerateList(
  124. CTopologyConnection::CheckDuplicate,
  125. ppTopologyConnection) == STATUS_SUCCESS) {
  126. ASSERT(NT_SUCCESS(Status));
  127. DPF(70, "CTopologyConnection::Create: Duplicate 2");
  128. delete pTopologyConnection;
  129. goto exit;
  130. }
  131. } END_EACH_LIST_ITEM
  132. // Check if duplicate on GraphNode's connected filter list
  133. FOR_EACH_LIST_ITEM(
  134. &pGraphNode->lstLogicalFilterNode,
  135. pLogicalFilterNode) {
  136. if(pLogicalFilterNode->lstTopologyConnection.EnumerateList(
  137. CTopologyConnection::CheckDuplicate,
  138. ppTopologyConnection) == STATUS_SUCCESS) {
  139. ASSERT(NT_SUCCESS(Status));
  140. DPF(70, "CTopologyConnection::Create: Duplicate 3");
  141. delete pTopologyConnection;
  142. goto exit;
  143. }
  144. } END_EACH_LIST_ITEM
  145. pTopologyConnection->ulFlags = TOPC_FLAGS_GRAPH_CONNECTION_TYPE;
  146. }
  147. // Check for duplicate topology connections
  148. if(plstTopologyConnection->EnumerateList(
  149. CTopologyConnection::CheckDuplicate,
  150. ppTopologyConnection) == STATUS_SUCCESS) {
  151. DPF(70, "CTopologyConnection::Create: Duplicate 4");
  152. ASSERT(NT_SUCCESS(Status));
  153. delete pTopologyConnection;
  154. goto exit;
  155. }
  156. if(pTopologyPinFrom != NULL) {
  157. Assert(pTopologyConnection);
  158. Status = pTopologyConnection->AddListEnd(
  159. &pTopologyPinFrom->lstTopologyConnection);
  160. if(!NT_SUCCESS(Status)) {
  161. Trap();
  162. goto exit;
  163. }
  164. }
  165. if(pTopologyPinTo != NULL) {
  166. Assert(pTopologyConnection);
  167. Status = pTopologyConnection->AddListEnd(
  168. &pTopologyPinTo->lstTopologyConnection);
  169. if(!NT_SUCCESS(Status)) {
  170. Trap();
  171. goto exit;
  172. }
  173. }
  174. if(pPinInfoFrom != NULL) {
  175. Assert(pTopologyConnection);
  176. Status = pTopologyConnection->AddListEnd(
  177. &pPinInfoFrom->lstTopologyConnection);
  178. if(!NT_SUCCESS(Status)) {
  179. Trap();
  180. goto exit;
  181. }
  182. }
  183. if(pPinInfoTo != NULL) {
  184. Assert(pTopologyConnection);
  185. Status = pTopologyConnection->AddListEnd(
  186. &pPinInfoTo->lstTopologyConnection);
  187. if(!NT_SUCCESS(Status)) {
  188. Trap();
  189. goto exit;
  190. }
  191. }
  192. Status = pTopologyConnection->AddListEnd(plstTopologyConnection);
  193. if(!NT_SUCCESS(Status)) {
  194. Trap();
  195. goto exit;
  196. }
  197. exit:
  198. DPF3(70, "CTopologyConnection::Create: %08x, FN: %08x GN: %08x",
  199. *ppTopologyConnection,
  200. pFilterNode,
  201. pGraphNode);
  202. return(Status);
  203. }
  204. ENUMFUNC
  205. CTopologyConnection::CheckDuplicate(
  206. PVOID pReference
  207. )
  208. {
  209. PTOPOLOGY_CONNECTION *ppTopologyConnection =
  210. (PTOPOLOGY_CONNECTION*)pReference;
  211. if((this->pTopologyPinFrom == (*ppTopologyConnection)->pTopologyPinFrom) &&
  212. (this->pTopologyPinTo == (*ppTopologyConnection)->pTopologyPinTo) &&
  213. (this->pPinInfoFrom == (*ppTopologyConnection)->pPinInfoFrom) &&
  214. (this->pPinInfoTo == (*ppTopologyConnection)->pPinInfoTo)) {
  215. *ppTopologyConnection = this;
  216. return(STATUS_SUCCESS);
  217. }
  218. return(STATUS_CONTINUE);
  219. }
  220. BOOL
  221. CTopologyConnection::IsTopologyConnectionOnGraphNode(
  222. PGRAPH_NODE pGraphNode
  223. )
  224. {
  225. PLOGICAL_FILTER_NODE pLogicalFilterNodeFrom;
  226. PLOGICAL_FILTER_NODE pLogicalFilterNodeTo;
  227. PLOGICAL_FILTER_NODE pLogicalFilterNode;
  228. BOOL fStatusFrom = FALSE;
  229. BOOL fStatusTo = FALSE;
  230. Assert(pGraphNode);
  231. if(pPinInfoFrom != NULL || pPinInfoTo != NULL) {
  232. return(TRUE);
  233. }
  234. if(pTopologyPinFrom == NULL || pTopologyPinTo == NULL) {
  235. return(FALSE);
  236. }
  237. Assert(pTopologyPinFrom);
  238. Assert(pTopologyPinTo);
  239. FOR_EACH_LIST_ITEM(
  240. &pTopologyPinFrom->pTopologyNode->lstLogicalFilterNode,
  241. pLogicalFilterNodeFrom) {
  242. Assert(pLogicalFilterNodeFrom);
  243. FOR_EACH_LIST_ITEM(
  244. &pTopologyPinTo->pTopologyNode->lstLogicalFilterNode,
  245. pLogicalFilterNodeTo) {
  246. FOR_EACH_LIST_ITEM(
  247. &pGraphNode->pDeviceNode->lstLogicalFilterNode,
  248. pLogicalFilterNode) {
  249. Assert(pLogicalFilterNode);
  250. if(pLogicalFilterNode == pLogicalFilterNodeFrom) {
  251. fStatusFrom = TRUE;
  252. }
  253. if(pLogicalFilterNode == pLogicalFilterNodeTo) {
  254. fStatusTo = TRUE;
  255. }
  256. } END_EACH_LIST_ITEM
  257. if(fStatusFrom && fStatusTo) {
  258. goto exit;
  259. }
  260. FOR_EACH_LIST_ITEM(
  261. &pGraphNode->lstLogicalFilterNode,
  262. pLogicalFilterNode) {
  263. Assert(pLogicalFilterNode);
  264. if(pLogicalFilterNode == pLogicalFilterNodeFrom) {
  265. fStatusFrom = TRUE;
  266. }
  267. if(pLogicalFilterNode == pLogicalFilterNodeTo) {
  268. fStatusTo = TRUE;
  269. }
  270. } END_EACH_LIST_ITEM
  271. if(fStatusFrom && fStatusTo) {
  272. goto exit;
  273. }
  274. } END_EACH_LIST_ITEM
  275. } END_EACH_LIST_ITEM
  276. exit:
  277. return(fStatusFrom && fStatusTo);
  278. }
  279. NTSTATUS
  280. AddPinToFilterNode(
  281. PTOPOLOGY_PIN pTopologyPin,
  282. PFILTER_NODE pFilterNode
  283. )
  284. {
  285. NTSTATUS Status = STATUS_SUCCESS;
  286. PFILTER_NODE pFilterNodeNext;
  287. Assert(pFilterNode);
  288. Assert(pTopologyPin);
  289. Assert(pTopologyPin->pTopologyNode->pFilterNode);
  290. //
  291. // Add the filter node to connected filter node list
  292. //
  293. if(pFilterNode != pTopologyPin->pTopologyNode->pFilterNode) {
  294. Status = pFilterNode->lstConnectedFilterNode.AddList(
  295. pTopologyPin->pTopologyNode->pFilterNode);
  296. if(!NT_SUCCESS(Status)) {
  297. Trap();
  298. goto exit;
  299. }
  300. // Hack for ds1wdm dmus synth topology (adds dmus to wave FN lst)
  301. if((pFilterNode->GetType() & FILTER_TYPE_ENDPOINT) == 0) {
  302. DPF2(50, "AddPinToFilterNode: (from) FN: %08x %s",
  303. pFilterNode,
  304. pFilterNode->DumpName());
  305. FOR_EACH_LIST_ITEM(
  306. &pTopologyPin->pTopologyNode->pFilterNode->lstConnectedFilterNode,
  307. pFilterNodeNext) {
  308. if(pFilterNodeNext == pFilterNode ||
  309. pFilterNodeNext == pTopologyPin->pTopologyNode->pFilterNode) {
  310. continue;
  311. }
  312. DPF2(50, "AddPinToFilterNode: (to) FN: %08x %s",
  313. pFilterNodeNext,
  314. pFilterNodeNext->DumpName());
  315. Status = pFilterNodeNext->lstConnectedFilterNode.AddList(
  316. pFilterNode);
  317. if(!NT_SUCCESS(Status)) {
  318. Trap();
  319. goto exit;
  320. }
  321. } END_EACH_LIST_ITEM
  322. }
  323. //
  324. // This fixes the bug with capture only devices. The topology for
  325. // capture only devices was not built properly, due to the missing
  326. // link between wave filter and topology filter.
  327. // Add the topology filter to wave filter ConnectedFilterNode list.
  328. // The AddList function does not allow duplicate entries.
  329. //
  330. if ((pFilterNode->GetType() & FILTER_TYPE_TOPOLOGY) &&
  331. (pTopologyPin->pTopologyNode->pFilterNode->GetType() & (FILTER_TYPE_CAPTURER))) {
  332. Status = pTopologyPin->pTopologyNode->pFilterNode->lstConnectedFilterNode.AddList(
  333. pFilterNode);
  334. DPF3(20, "AddPinToFilterNode: (CAPTURE ONLY) FN: %08x FN: %08x %s",
  335. pTopologyPin->pTopologyNode->pFilterNode,
  336. pFilterNode,
  337. pFilterNode->DumpName());
  338. }
  339. }
  340. exit:
  341. return(Status);
  342. }
  343. NTSTATUS
  344. AddPinToGraphNode(
  345. PTOPOLOGY_PIN pTopologyPin,
  346. PGRAPH_NODE pGraphNode,
  347. PTOPOLOGY_CONNECTION pTopologyConnection
  348. )
  349. {
  350. PLOGICAL_FILTER_NODE pLogicalFilterNode2;
  351. PLOGICAL_FILTER_NODE pLogicalFilterNode;
  352. PTOPOLOGY_CONNECTION pTopologyConnection2;
  353. NTSTATUS Status = STATUS_SUCCESS;
  354. BOOL fAddLogicalFilterNode;
  355. Assert(pTopologyPin);
  356. Assert(pTopologyPin->pTopologyNode);
  357. Assert(pGraphNode);
  358. FOR_EACH_LIST_ITEM(
  359. &pTopologyPin->pTopologyNode->lstLogicalFilterNode,
  360. pLogicalFilterNode) {
  361. fAddLogicalFilterNode = FALSE;
  362. FOR_EACH_LIST_ITEM(
  363. &pLogicalFilterNode->lstTopologyConnection,
  364. pTopologyConnection2) {
  365. Assert(pTopologyConnection2);
  366. if(pTopologyPin == pTopologyConnection2->pTopologyPinFrom ||
  367. pTopologyPin == pTopologyConnection2->pTopologyPinTo) {
  368. fAddLogicalFilterNode = TRUE;
  369. break;
  370. }
  371. } END_EACH_LIST_ITEM
  372. if(fAddLogicalFilterNode) {
  373. FOR_EACH_LIST_ITEM(
  374. &pGraphNode->pDeviceNode->lstLogicalFilterNode,
  375. pLogicalFilterNode2) {
  376. Assert(pLogicalFilterNode2);
  377. if(pLogicalFilterNode == pLogicalFilterNode2) {
  378. fAddLogicalFilterNode = FALSE;
  379. break;
  380. }
  381. } END_EACH_LIST_ITEM
  382. }
  383. if(fAddLogicalFilterNode) {
  384. Status = pGraphNode->lstLogicalFilterNode.AddList(
  385. pLogicalFilterNode,
  386. pTopologyConnection);
  387. if(!NT_SUCCESS(Status)) {
  388. Trap();
  389. goto exit;
  390. }
  391. }
  392. } END_EACH_LIST_ITEM
  393. exit:
  394. return(Status);
  395. }
  396. NTSTATUS
  397. CreatePinInfoConnection(
  398. PTOPOLOGY_CONNECTION *ppTopologyConnection,
  399. PFILTER_NODE pFilterNode,
  400. PGRAPH_NODE pGraphNode,
  401. PPIN_INFO pPinInfoSource,
  402. PPIN_INFO pPinInfoSink
  403. )
  404. {
  405. PTOPOLOGY_CONNECTION pTopologyConnectionSource;
  406. PTOPOLOGY_CONNECTION pTopologyConnectionSink;
  407. PTOPOLOGY_PIN pTopologyPinFrom;
  408. PTOPOLOGY_PIN pTopologyPinTo;
  409. NTSTATUS Status = STATUS_SUCCESS;
  410. Assert(pPinInfoSource);
  411. Assert(pPinInfoSink);
  412. ASSERT(pPinInfoSource != pPinInfoSink);
  413. FOR_EACH_LIST_ITEM(
  414. &pPinInfoSource->lstTopologyConnection,
  415. pTopologyConnectionSource) {
  416. Assert(pTopologyConnectionSource);
  417. if(!IS_CONNECTION_TYPE(pTopologyConnectionSource, FILTER)) {
  418. continue;
  419. }
  420. pTopologyPinFrom = NULL;
  421. pTopologyPinTo = NULL;
  422. if(pTopologyConnectionSource->pTopologyPinFrom != NULL) {
  423. ASSERT(pTopologyConnectionSource->pPinInfoTo == pPinInfoSource);
  424. ASSERT(pTopologyConnectionSource->pPinInfoFrom == NULL);
  425. ASSERT(pTopologyConnectionSource->pTopologyPinTo == NULL);
  426. pTopologyPinFrom = pTopologyConnectionSource->pTopologyPinFrom;
  427. }
  428. if(pTopologyConnectionSource->pTopologyPinTo != NULL) {
  429. ASSERT(pTopologyConnectionSource->pPinInfoFrom == pPinInfoSource);
  430. ASSERT(pTopologyConnectionSource->pPinInfoTo == NULL);
  431. ASSERT(pTopologyConnectionSource->pTopologyPinFrom == NULL);
  432. pTopologyPinTo = pTopologyConnectionSource->pTopologyPinTo;
  433. }
  434. FOR_EACH_LIST_ITEM(
  435. &pPinInfoSink->lstTopologyConnection,
  436. pTopologyConnectionSink) {
  437. Assert(pTopologyConnectionSink);
  438. if(!IS_CONNECTION_TYPE(pTopologyConnectionSink, FILTER)) {
  439. continue;
  440. }
  441. if(pTopologyConnectionSink->pTopologyPinFrom != NULL) {
  442. ASSERT(pTopologyConnectionSink->pPinInfoTo == pPinInfoSink);
  443. ASSERT(pTopologyConnectionSink->pPinInfoFrom == NULL);
  444. ASSERT(pTopologyConnectionSink->pTopologyPinTo == NULL);
  445. pTopologyPinFrom = pTopologyConnectionSink->pTopologyPinFrom;
  446. }
  447. if(pTopologyConnectionSink->pTopologyPinTo != NULL) {
  448. ASSERT(pTopologyConnectionSink->pPinInfoFrom == pPinInfoSink);
  449. ASSERT(pTopologyConnectionSink->pPinInfoTo == NULL);
  450. ASSERT(pTopologyConnectionSink->pTopologyPinFrom == NULL);
  451. pTopologyPinTo = pTopologyConnectionSink->pTopologyPinTo;
  452. }
  453. ASSERT(pTopologyPinFrom != NULL);
  454. ASSERT(pTopologyPinTo != NULL);
  455. Status = CTopologyConnection::Create(
  456. ppTopologyConnection,
  457. pFilterNode,
  458. pGraphNode,
  459. pTopologyPinFrom, // DataFlow == OUT, Pin #0
  460. pTopologyPinTo, // DataFlow == IN, Pin #1 - n
  461. NULL,
  462. NULL);
  463. if(!NT_SUCCESS(Status)) {
  464. Trap();
  465. goto exit;
  466. }
  467. // Add the connections to the PinInfos
  468. Assert(*ppTopologyConnection);
  469. Status = (*ppTopologyConnection)->AddListEnd(
  470. &pPinInfoSource->lstTopologyConnection);
  471. if(!NT_SUCCESS(Status)) {
  472. Trap();
  473. goto exit;
  474. }
  475. Status = (*ppTopologyConnection)->AddListEnd(
  476. &pPinInfoSink->lstTopologyConnection);
  477. if(!NT_SUCCESS(Status)) {
  478. Trap();
  479. goto exit;
  480. }
  481. if(pFilterNode != NULL) {
  482. Assert(pFilterNode);
  483. Status = AddPinToFilterNode(pTopologyPinFrom, pFilterNode);
  484. if(!NT_SUCCESS(Status)) {
  485. Trap();
  486. goto exit;
  487. }
  488. Status = AddPinToFilterNode(pTopologyPinTo, pFilterNode);
  489. if(!NT_SUCCESS(Status)) {
  490. Trap();
  491. goto exit;
  492. }
  493. // Change the connection type to physical
  494. (*ppTopologyConnection)->ulFlags =
  495. TOPC_FLAGS_PHYSICAL_CONNECTION_TYPE;
  496. }
  497. if(pGraphNode != NULL) {
  498. Assert(pGraphNode);
  499. Status = AddPinToGraphNode(
  500. pTopologyPinFrom,
  501. pGraphNode,
  502. *ppTopologyConnection);
  503. if(!NT_SUCCESS(Status)) {
  504. Trap();
  505. goto exit;
  506. }
  507. Status = AddPinToGraphNode(
  508. pTopologyPinTo,
  509. pGraphNode,
  510. *ppTopologyConnection);
  511. if(!NT_SUCCESS(Status)) {
  512. Trap();
  513. goto exit;
  514. }
  515. ASSERT(IS_CONNECTION_TYPE(*ppTopologyConnection, GRAPH));
  516. }
  517. } END_EACH_LIST_ITEM
  518. } END_EACH_LIST_ITEM
  519. exit:
  520. return(Status);
  521. }
  522. //---------------------------------------------------------------------------