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.

577 lines
17 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Module: lfn.cpp
  4. //
  5. // Description:
  6. //
  7. //
  8. //@@BEGIN_MSINTERNAL
  9. // Development Team:
  10. // Mike McLaughlin
  11. //
  12. // History: Date Author Comment
  13. //
  14. // To Do: Date Author Comment
  15. //
  16. //@@END_MSINTERNAL
  17. //
  18. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  19. // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  20. // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  21. // PURPOSE.
  22. //
  23. // Copyright (c) 1996-1999 Microsoft Corporation. All Rights Reserved.
  24. //
  25. //---------------------------------------------------------------------------
  26. #include "common.h"
  27. //---------------------------------------------------------------------------
  28. //---------------------------------------------------------------------------
  29. ULONG gcMixers = 0;
  30. ULONG gcSplitters = 0;
  31. ULONG gcLogicalFilterNodes = 0;
  32. //---------------------------------------------------------------------------
  33. //---------------------------------------------------------------------------
  34. NTSTATUS
  35. CLogicalFilterNode::Create(
  36. OUT PLOGICAL_FILTER_NODE *ppLogicalFilterNode,
  37. IN PFILTER_NODE pFilterNode
  38. )
  39. {
  40. PLOGICAL_FILTER_NODE pLogicalFilterNode;
  41. NTSTATUS Status;
  42. pLogicalFilterNode = new LOGICAL_FILTER_NODE(pFilterNode);
  43. if(pLogicalFilterNode == NULL) {
  44. Status = STATUS_INSUFFICIENT_RESOURCES;
  45. Trap();
  46. goto exit;
  47. }
  48. Status = pLogicalFilterNode->AddList(&pFilterNode->lstLogicalFilterNode);
  49. if(!NT_SUCCESS(Status)) {
  50. Trap();
  51. delete pLogicalFilterNode;
  52. pLogicalFilterNode = NULL;
  53. goto exit;
  54. }
  55. if(pLogicalFilterNode->GetType() & FILTER_TYPE_LOGICAL_FILTER) {
  56. Status = pLogicalFilterNode->AddListOrdered(
  57. gplstLogicalFilterNode,
  58. FIELD_OFFSET(LOGICAL_FILTER_NODE, ulOrder));
  59. if(!NT_SUCCESS(Status)) {
  60. Trap();
  61. goto exit;
  62. }
  63. }
  64. exit:
  65. *ppLogicalFilterNode = pLogicalFilterNode;
  66. return(Status);
  67. }
  68. CLogicalFilterNode::CLogicalFilterNode(
  69. PFILTER_NODE pFilterNode
  70. )
  71. {
  72. Assert(pFilterNode);
  73. this->pFilterNode = pFilterNode;
  74. // The type/order is the same as filter node
  75. SetType(pFilterNode->GetType());
  76. // Determine the overhead here, default to software (higher)
  77. ulOverhead = OVERHEAD_SOFTWARE;
  78. if(GetType() & FILTER_TYPE_ENDPOINT) {
  79. ulOverhead = OVERHEAD_HARDWARE;
  80. }
  81. // Count the mixers, splitters and lfns
  82. if(GetType() & FILTER_TYPE_MIXER) {
  83. ++gcMixers;
  84. }
  85. if(GetType() & FILTER_TYPE_SPLITTER) {
  86. ++gcSplitters;
  87. }
  88. ++gcLogicalFilterNodes;
  89. DPF3(60, "CLogicalFilterNode: %08x FN: %08x %s",
  90. this,
  91. pFilterNode,
  92. pFilterNode->DumpName());
  93. }
  94. CLogicalFilterNode::~CLogicalFilterNode(
  95. )
  96. {
  97. PLOGICAL_FILTER_NODE pLogicalFilterNode;
  98. PDEVICE_NODE pDeviceNode;
  99. PGRAPH_NODE pGraphNode;
  100. PPIN_NODE pPinNode;
  101. BOOL fDestroy;
  102. Assert(this);
  103. DPF2(60, "~CLogicalFilterNode: %08x %s", this, pFilterNode->DumpName());
  104. //
  105. // Need to NULL the pPinNode's LFN field because it is used in AddPinNodes
  106. // to indicate that this PN hasn't been assigned a LFN yet.
  107. //
  108. FOR_EACH_LIST_ITEM(&lstPinNode, pPinNode) {
  109. Assert(pPinNode);
  110. if(pPinNode->pLogicalFilterNode == this) {
  111. pPinNode->pLogicalFilterNode = NULL;
  112. }
  113. } END_EACH_LIST_ITEM
  114. FOR_EACH_LIST_ITEM(gplstDeviceNode, pDeviceNode) {
  115. fDestroy = FALSE;
  116. FOR_EACH_LIST_ITEM(
  117. &pDeviceNode->lstLogicalFilterNode,
  118. pLogicalFilterNode) {
  119. if(pLogicalFilterNode == this) {
  120. DPF2(50, "~CLogicalFilterNode: %08x GN %08x Destroy",
  121. pLogicalFilterNode,
  122. pGraphNode);
  123. fDestroy = TRUE;
  124. break;
  125. }
  126. } END_EACH_LIST_ITEM
  127. if(!fDestroy) {
  128. FOR_EACH_LIST_ITEM(&pDeviceNode->lstGraphNode, pGraphNode) {
  129. FOR_EACH_LIST_ITEM(
  130. &pGraphNode->lstLogicalFilterNode,
  131. pLogicalFilterNode) {
  132. if(pLogicalFilterNode == this) {
  133. DPF2(50, "~CLogicalFilterNode: %08x GN %08x Destroy",
  134. pLogicalFilterNode,
  135. pGraphNode);
  136. fDestroy = TRUE;
  137. break;
  138. }
  139. } END_EACH_LIST_ITEM
  140. } END_EACH_LIST_ITEM
  141. }
  142. if(fDestroy) {
  143. pDeviceNode->lstGraphNode.DestroyList();
  144. }
  145. } END_EACH_LIST_ITEM
  146. if(GetType() & FILTER_TYPE_MIXER) {
  147. --gcMixers;
  148. }
  149. if(GetType() & FILTER_TYPE_SPLITTER) {
  150. --gcSplitters;
  151. }
  152. --gcLogicalFilterNodes;
  153. }
  154. VOID
  155. CLogicalFilterNode::SetType(
  156. ULONG fulType
  157. )
  158. {
  159. pFilterNode->SetType(fulType);
  160. SetOrder(pFilterNode->GetOrder());
  161. ulFlags = 0;
  162. if(GetType() & FILTER_TYPE_RENDER) {
  163. ulFlags |= LFN_FLAGS_CONNECT_RENDER;
  164. }
  165. if(GetType() & FILTER_TYPE_CAPTURE) {
  166. ulFlags |= LFN_FLAGS_CONNECT_CAPTURE;
  167. }
  168. if(GetType() & FILTER_TYPE_NORMAL_TOPOLOGY) {
  169. ulFlags |= LFN_FLAGS_CONNECT_NORMAL_TOPOLOGY;
  170. }
  171. if(GetType() & FILTER_TYPE_MIXER_TOPOLOGY) {
  172. ulFlags |= LFN_FLAGS_CONNECT_MIXER_TOPOLOGY;
  173. }
  174. if(GetType() & FILTER_TYPE_NO_BYPASS) {
  175. ulFlags |= LFN_FLAGS_NO_BYPASS;
  176. }
  177. if(GetType() & FILTER_TYPE_NOT_SELECT) {
  178. ulFlags |= LFN_FLAGS_NOT_SELECT;
  179. }
  180. if(pFilterNode->GetFlags() & FN_FLAGS_RENDER) {
  181. ulFlags |= LFN_FLAGS_CONNECT_RENDER;
  182. }
  183. if(pFilterNode->GetFlags() & FN_FLAGS_NO_RENDER) {
  184. ulFlags &= ~LFN_FLAGS_CONNECT_RENDER;
  185. }
  186. if(pFilterNode->GetFlags() & FN_FLAGS_CAPTURE) {
  187. ulFlags |= LFN_FLAGS_CONNECT_CAPTURE;
  188. }
  189. if(pFilterNode->GetFlags() & FN_FLAGS_NO_CAPTURE) {
  190. ulFlags &= ~LFN_FLAGS_CONNECT_CAPTURE;
  191. }
  192. }
  193. NTSTATUS
  194. SwitchLogicalFilterNodes(
  195. IN PLOGICAL_FILTER_NODE pLogicalFilterNode,
  196. IN OUT PLOGICAL_FILTER_NODE *ppLogicalFilterNode
  197. )
  198. {
  199. NTSTATUS Status = STATUS_SUCCESS;
  200. PTOPOLOGY_NODE pTopologyNode;
  201. PPIN_NODE pPinNode;
  202. Assert(pLogicalFilterNode);
  203. Assert(*ppLogicalFilterNode);
  204. if(pLogicalFilterNode != *ppLogicalFilterNode) {
  205. FOR_EACH_LIST_ITEM(&(*ppLogicalFilterNode)->lstPinNode, pPinNode) {
  206. Assert(pPinNode);
  207. pPinNode->pLogicalFilterNode = pLogicalFilterNode;
  208. } END_EACH_LIST_ITEM
  209. pLogicalFilterNode->lstPinNode.JoinList(
  210. &(*ppLogicalFilterNode)->lstPinNode);
  211. FOR_EACH_LIST_ITEM(
  212. &(*ppLogicalFilterNode)->lstTopologyNode,
  213. pTopologyNode) {
  214. Assert(pTopologyNode);
  215. (*ppLogicalFilterNode)->RemoveList(
  216. &pTopologyNode->lstLogicalFilterNode);
  217. Status = pLogicalFilterNode->AddList(
  218. &pTopologyNode->lstLogicalFilterNode);
  219. if(!NT_SUCCESS(Status)) {
  220. Trap();
  221. goto exit;
  222. }
  223. Status = pLogicalFilterNode->lstTopologyNode.AddList(pTopologyNode);
  224. if(!NT_SUCCESS(Status)) {
  225. Trap();
  226. goto exit;
  227. }
  228. } END_EACH_LIST_ITEM
  229. pLogicalFilterNode->lstTopologyConnection.JoinList(
  230. &(*ppLogicalFilterNode)->lstTopologyConnection);
  231. delete *ppLogicalFilterNode;
  232. *ppLogicalFilterNode = pLogicalFilterNode;
  233. }
  234. exit:
  235. return(Status);
  236. }
  237. NTSTATUS
  238. AddPinNodes(
  239. IN PPIN_INFO pPinInfo,
  240. IN OUT PLOGICAL_FILTER_NODE *ppLogicalFilterNode
  241. )
  242. {
  243. NTSTATUS Status = STATUS_SUCCESS;
  244. PPIN_NODE pPinNode;
  245. Assert(pPinInfo);
  246. Assert(*ppLogicalFilterNode);
  247. FOR_EACH_LIST_ITEM(&pPinInfo->lstPinNode, pPinNode) {
  248. if(pPinNode->pLogicalFilterNode == NULL) {
  249. pPinNode->pLogicalFilterNode = *ppLogicalFilterNode;
  250. }
  251. else {
  252. Status = SwitchLogicalFilterNodes(
  253. pPinNode->pLogicalFilterNode,
  254. ppLogicalFilterNode);
  255. if(!NT_SUCCESS(Status)) {
  256. Trap();
  257. goto exit;
  258. }
  259. }
  260. Status = (*ppLogicalFilterNode)->lstPinNode.AddList(pPinNode);
  261. if(!NT_SUCCESS(Status)) {
  262. Trap();
  263. goto exit;
  264. }
  265. DPF2(100, "AddPinNodes: add PN %08x LFN %08x",
  266. pPinNode,
  267. *ppLogicalFilterNode);
  268. } END_EACH_LIST_ITEM
  269. exit:
  270. return(Status);
  271. }
  272. NTSTATUS
  273. CLogicalFilterNode::EnumerateFilterTopology(
  274. IN PTOPOLOGY_CONNECTION pTopologyConnection,
  275. IN BOOL fToDirection,
  276. IN OUT PLOGICAL_FILTER_NODE *ppLogicalFilterNode
  277. )
  278. {
  279. PTOPOLOGY_NODE pTopologyNode;
  280. NTSTATUS Status;
  281. Assert(pTopologyConnection);
  282. DPF5(100, "EFT: PIF %08x PIT %08x TPF %08x TPT %08x f %x",
  283. pTopologyConnection->pPinInfoFrom,
  284. pTopologyConnection->pPinInfoTo,
  285. pTopologyConnection->pTopologyPinFrom,
  286. pTopologyConnection->pTopologyPinTo,
  287. fToDirection);
  288. if(!fToDirection) {
  289. Status = STATUS_DEAD_END;
  290. goto exit;
  291. }
  292. if(IS_CONNECTION_TYPE(pTopologyConnection, FILTER)) {
  293. if(pTopologyConnection->pPinInfoFrom != NULL) {
  294. Assert(pTopologyConnection->pPinInfoFrom);
  295. if(*ppLogicalFilterNode == NULL) {
  296. Status = CLogicalFilterNode::Create(
  297. ppLogicalFilterNode,
  298. pTopologyConnection->pPinInfoFrom->pFilterNode);
  299. if(!NT_SUCCESS(Status)) {
  300. Trap();
  301. goto exit;
  302. }
  303. }
  304. Status = AddPinNodes(
  305. pTopologyConnection->pPinInfoFrom,
  306. ppLogicalFilterNode);
  307. if(!NT_SUCCESS(Status)) {
  308. Trap();
  309. goto exit;
  310. }
  311. DPF2(100, "EFT: add from PI %08x LFN %08x",
  312. pTopologyConnection->pPinInfoFrom,
  313. *ppLogicalFilterNode);
  314. }
  315. ASSERT(*ppLogicalFilterNode != NULL);
  316. Assert(*ppLogicalFilterNode);
  317. if(pTopologyConnection->pPinInfoTo != NULL) {
  318. Status = AddPinNodes(
  319. pTopologyConnection->pPinInfoTo,
  320. ppLogicalFilterNode);
  321. if(!NT_SUCCESS(Status)) {
  322. Trap();
  323. goto exit;
  324. }
  325. DPF2(100, "EFT: add to PI %08x LFN %08x",
  326. pTopologyConnection->pPinInfoTo,
  327. *ppLogicalFilterNode);
  328. }
  329. if(pTopologyConnection->pTopologyPinTo != NULL) {
  330. Assert(pTopologyConnection->pTopologyPinTo);
  331. pTopologyNode = pTopologyConnection->pTopologyPinTo->pTopologyNode;
  332. Assert(pTopologyNode);
  333. Status = (*ppLogicalFilterNode)->lstTopologyNode.AddList(
  334. pTopologyNode);
  335. if(!NT_SUCCESS(Status)) {
  336. Trap();
  337. goto exit;
  338. }
  339. if(IsEqualGUID(
  340. &KSNODETYPE_ACOUSTIC_ECHO_CANCEL,
  341. pTopologyNode->pguidType)) {
  342. Assert(*ppLogicalFilterNode);
  343. (*ppLogicalFilterNode)->SetType(FILTER_TYPE_AEC);
  344. if(pTopologyConnection->pTopologyPinTo->ulPinNumber ==
  345. KSNODEPIN_AEC_RENDER_IN) {
  346. (*ppLogicalFilterNode)->SetRenderOnly();
  347. }
  348. else {
  349. ASSERT(
  350. pTopologyConnection->pTopologyPinTo->ulPinNumber ==
  351. KSNODEPIN_AEC_CAPTURE_IN);
  352. (*ppLogicalFilterNode)->SetCaptureOnly();
  353. }
  354. Status = (*ppLogicalFilterNode)->AddList(
  355. &pTopologyNode->lstLogicalFilterNode);
  356. if(!NT_SUCCESS(Status)) {
  357. Trap();
  358. goto exit;
  359. }
  360. }
  361. else {
  362. if(pTopologyNode->lstLogicalFilterNode.IsLstEmpty()) {
  363. Assert(*ppLogicalFilterNode);
  364. Status = (*ppLogicalFilterNode)->AddList(
  365. &pTopologyNode->lstLogicalFilterNode);
  366. if(!NT_SUCCESS(Status)) {
  367. Trap();
  368. goto exit;
  369. }
  370. }
  371. else {
  372. Status = SwitchLogicalFilterNodes(
  373. (PLOGICAL_FILTER_NODE)
  374. pTopologyNode->lstLogicalFilterNode.GetListFirstData(),
  375. ppLogicalFilterNode);
  376. if(!NT_SUCCESS(Status)) {
  377. Trap();
  378. goto exit;
  379. }
  380. }
  381. }
  382. DPF2(100, "EFT: add to PI %08x LFN %08x",
  383. pTopologyConnection->pPinInfoTo,
  384. *ppLogicalFilterNode);
  385. }
  386. }
  387. Status = pTopologyConnection->AddList(
  388. &(*ppLogicalFilterNode)->lstTopologyConnection);
  389. if(!NT_SUCCESS(Status)) {
  390. Trap();
  391. goto exit;
  392. }
  393. if(IS_CONNECTION_TYPE(pTopologyConnection, FILTER)) {
  394. Status = STATUS_CONTINUE;
  395. }
  396. else {
  397. Status = STATUS_DEAD_END;
  398. }
  399. exit:
  400. return(Status);
  401. }
  402. NTSTATUS
  403. CLogicalFilterNode::CreateAll(
  404. PFILTER_NODE pFilterNode
  405. )
  406. {
  407. PLOGICAL_FILTER_NODE pLogicalFilterNode;
  408. NTSTATUS Status = STATUS_SUCCESS;
  409. PPIN_INFO pPinInfo;
  410. PPIN_NODE pPinNode;
  411. DPF2(100, "CLFN::CreateAll: FN %08x %s",
  412. pFilterNode,
  413. pFilterNode->DumpName());
  414. //
  415. // Split up the filter into logical filter nodes.
  416. //
  417. FOR_EACH_LIST_ITEM(&pFilterNode->lstPinInfo, pPinInfo) {
  418. pLogicalFilterNode = NULL;
  419. Status = EnumerateTopology(
  420. pPinInfo,
  421. (TOP_PFN)EnumerateFilterTopology,
  422. &pLogicalFilterNode);
  423. if(Status == STATUS_CONTINUE) {
  424. Status = STATUS_SUCCESS;
  425. }
  426. else {
  427. if(!NT_SUCCESS(Status)) {
  428. goto exit;
  429. }
  430. }
  431. } END_EACH_LIST_ITEM
  432. //
  433. // Look at the pins of each LFN and determine if it could possibly
  434. // be a capture or render filter (or both).
  435. //
  436. FOR_EACH_LIST_ITEM(
  437. &pFilterNode->lstLogicalFilterNode,
  438. pLogicalFilterNode) {
  439. ULONG ulPossibleFlags;
  440. ulPossibleFlags = 0;
  441. pLogicalFilterNode->ulFlags |= LFN_FLAGS_REFLECT_DATARANGE;
  442. FOR_EACH_LIST_ITEM(&pLogicalFilterNode->lstPinNode, pPinNode) {
  443. // Don't care about the major format
  444. if(!IsEqualGUID(
  445. &pPinNode->pDataRange->SubFormat,
  446. &KSDATAFORMAT_SUBTYPE_WILDCARD) ||
  447. !IsEqualGUID(
  448. &pPinNode->pDataRange->Specifier,
  449. &KSDATAFORMAT_SPECIFIER_WILDCARD)) {
  450. pLogicalFilterNode->ulFlags &= ~LFN_FLAGS_REFLECT_DATARANGE;
  451. }
  452. switch(pPinNode->pPinInfo->Communication) {
  453. case KSPIN_COMMUNICATION_BOTH:
  454. ulPossibleFlags |=
  455. LFN_FLAGS_CONNECT_CAPTURE | LFN_FLAGS_CONNECT_RENDER;
  456. break;
  457. case KSPIN_COMMUNICATION_SOURCE:
  458. switch(pPinNode->pPinInfo->DataFlow) {
  459. case KSPIN_DATAFLOW_IN:
  460. ulPossibleFlags |= LFN_FLAGS_CONNECT_CAPTURE;
  461. break;
  462. case KSPIN_DATAFLOW_OUT:
  463. ulPossibleFlags |= LFN_FLAGS_CONNECT_RENDER;
  464. break;
  465. }
  466. break;
  467. case KSPIN_COMMUNICATION_SINK:
  468. switch(pPinNode->pPinInfo->DataFlow) {
  469. case KSPIN_DATAFLOW_IN:
  470. ulPossibleFlags |= LFN_FLAGS_CONNECT_RENDER;
  471. break;
  472. case KSPIN_DATAFLOW_OUT:
  473. ulPossibleFlags |= LFN_FLAGS_CONNECT_CAPTURE;
  474. break;
  475. }
  476. break;
  477. }
  478. if(ulPossibleFlags ==
  479. (LFN_FLAGS_CONNECT_CAPTURE | LFN_FLAGS_CONNECT_RENDER)) {
  480. break;
  481. }
  482. } END_EACH_LIST_ITEM
  483. pLogicalFilterNode->ulFlags =
  484. (ulPossibleFlags & pLogicalFilterNode->GetFlags()) |
  485. (pLogicalFilterNode->GetFlags() &
  486. ~(LFN_FLAGS_CONNECT_CAPTURE | LFN_FLAGS_CONNECT_RENDER));
  487. } END_EACH_LIST_ITEM
  488. exit:
  489. return(Status);
  490. }
  491. //---------------------------------------------------------------------------