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.

460 lines
12 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Module: gn.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 gcGraphRecursion = 0;
  30. //---------------------------------------------------------------------------
  31. //---------------------------------------------------------------------------
  32. CGraphNode::CGraphNode(
  33. PDEVICE_NODE pDeviceNode,
  34. ULONG ulFlags
  35. )
  36. {
  37. Assert(pDeviceNode);
  38. this->pDeviceNode = pDeviceNode;
  39. this->ulFlags = ulFlags;
  40. AddList(&pDeviceNode->lstGraphNode);
  41. DPF2(80, "CGraphNode %08x, DN: %08x", this, pDeviceNode);
  42. }
  43. CGraphNode::~CGraphNode(
  44. )
  45. {
  46. DPF1(80, "~CGraphNode: %08x", this);
  47. Assert(this);
  48. RemoveList();
  49. }
  50. NTSTATUS
  51. CGraphNode::Create(
  52. )
  53. {
  54. PGRAPH_NODE_INSTANCE pGraphNodeInstance;
  55. PLOGICAL_FILTER_NODE pLogicalFilterNode;
  56. NTSTATUS Status = STATUS_SUCCESS;
  57. DPF3(80, "CGraphNode::Create: GN %08x F %08x %s",
  58. this,
  59. this->ulFlags,
  60. pDeviceNode->DumpName());
  61. FOR_EACH_LIST_ITEM(&pDeviceNode->lstLogicalFilterNode, pLogicalFilterNode) {
  62. Status = Create(pLogicalFilterNode);
  63. if(!NT_SUCCESS(Status)) {
  64. Trap();
  65. goto exit;
  66. }
  67. } END_EACH_LIST_ITEM
  68. if(!lstLogicalFilterNodeNoBypass.IsLstEmpty()) {
  69. lstStartNode.EnumerateList(CStartNode::RemoveBypassPaths, this);
  70. }
  71. if(this->ulFlags & FLAGS_MIXER_TOPOLOGY) {
  72. lstStartNode.EnumerateList(CStartNode::RemoveConnectedStartNode, this);
  73. }
  74. lstStartInfo.EnumerateList(CStartInfo::CreatePinInfoConnection, this);
  75. pGraphNodeInstance = new GRAPH_NODE_INSTANCE(this);
  76. if(pGraphNodeInstance == NULL) {
  77. Status = STATUS_INSUFFICIENT_RESOURCES;
  78. Trap();
  79. goto exit;
  80. }
  81. Status = pGraphNodeInstance->Create();
  82. if(!NT_SUCCESS(Status)) {
  83. Trap();
  84. goto exit;
  85. }
  86. //
  87. // The "ulSysaudioNodeNumber" field in the topology node isn't
  88. // valid until CGraphNodeInstance::Create and they are only valid
  89. // for this pGraphNode.
  90. //
  91. lstStartInfo.EnumerateList(CStartInfo::EnumStartInfo);
  92. delete pGraphNodeInstance;
  93. exit:
  94. return(Status);
  95. }
  96. NTSTATUS
  97. CGraphNode::Create(
  98. PLOGICAL_FILTER_NODE pLogicalFilterNode
  99. )
  100. {
  101. NTSTATUS Status = STATUS_SUCCESS;
  102. ULONG ulFlagsCurrent;
  103. PPIN_NODE pPinNode;
  104. DPF2(80, "CGraphNode::Create: LFN %08x %s",
  105. pLogicalFilterNode,
  106. pLogicalFilterNode->pFilterNode->DumpName());
  107. Assert(pLogicalFilterNode);
  108. FOR_EACH_LIST_ITEM(&pLogicalFilterNode->lstPinNode, pPinNode) {
  109. Assert(pPinNode);
  110. Assert(pPinNode->pPinInfo);
  111. ASSERT(
  112. (pLogicalFilterNode->GetFlags() & LFN_FLAGS_REFLECT_DATARANGE) == 0);
  113. gcGraphRecursion = 0;
  114. ulFlagsCurrent = 0;
  115. // Determine whether it is an input stream or output stream
  116. if(pPinNode->pPinInfo->DataFlow == KSPIN_DATAFLOW_IN) {
  117. ulFlagsCurrent |= LFN_FLAGS_CONNECT_RENDER;
  118. }
  119. if(pPinNode->pPinInfo->DataFlow == KSPIN_DATAFLOW_OUT) {
  120. ulFlagsCurrent |= LFN_FLAGS_CONNECT_CAPTURE;
  121. }
  122. // Determine the kind of graph to build
  123. if(this->ulFlags & FLAGS_MIXER_TOPOLOGY) {
  124. ulFlagsCurrent |= LFN_FLAGS_CONNECT_MIXER_TOPOLOGY;
  125. }
  126. else {
  127. ulFlagsCurrent |= LFN_FLAGS_CONNECT_NORMAL_TOPOLOGY;
  128. }
  129. Status = CreateGraph(
  130. pPinNode,
  131. NULL,
  132. pLogicalFilterNode,
  133. NULL,
  134. ulFlagsCurrent,
  135. pPinNode->GetOverhead() + pLogicalFilterNode->GetOverhead());
  136. if(!NT_SUCCESS(Status)) {
  137. Trap();
  138. goto exit;
  139. }
  140. } END_EACH_LIST_ITEM
  141. exit:
  142. return(Status);
  143. }
  144. NTSTATUS
  145. CGraphNode::CreateGraph(
  146. PPIN_NODE pPinNode,
  147. PCONNECT_NODE pConnectNodePrevious,
  148. PLOGICAL_FILTER_NODE pLogicalFilterNodePrevious,
  149. PGRAPH_PIN_INFO pGraphPinInfoPrevious,
  150. ULONG ulFlagsCurrent,
  151. ULONG ulOverhead
  152. )
  153. {
  154. PLOGICAL_FILTER_NODE pLogicalFilterNode;
  155. PGRAPH_PIN_INFO pGraphPinInfo = NULL;
  156. NTSTATUS Status = STATUS_SUCCESS;
  157. Assert(this);
  158. Assert(pPinNode);
  159. Assert(pPinNode->pPinInfo);
  160. Assert(pLogicalFilterNodePrevious);
  161. if(pConnectNodePrevious != NULL) {
  162. Assert(pConnectNodePrevious);
  163. }
  164. ASSERT(pPinNode->pLogicalFilterNode == pLogicalFilterNodePrevious);
  165. //
  166. // Don't allow unlimited nesting, allow graphs number of LFNs deep
  167. //
  168. if(gcGraphRecursion++ > (gcLogicalFilterNodes + 8)) {
  169. DPF(10, "CreateGraph: recursion too deep");
  170. Status = STATUS_STACK_OVERFLOW;
  171. goto exit;
  172. }
  173. if(pGraphPinInfoPrevious == NULL) {
  174. Status = CGraphPinInfo::Create(
  175. &pGraphPinInfo,
  176. pPinNode->pPinInfo,
  177. 0,
  178. this);
  179. if(!NT_SUCCESS(Status)) {
  180. Trap();
  181. goto exit;
  182. }
  183. pGraphPinInfoPrevious = pGraphPinInfo;
  184. }
  185. FOR_EACH_LIST_ITEM(gplstLogicalFilterNode, pLogicalFilterNode) {
  186. ULONG ulFlagsDiff;
  187. ASSERT(pLogicalFilterNode->GetOverhead() != OVERHEAD_NONE);
  188. //ASSERT(pLogicalFilterNode->GetOrder() != ORDER_NONE);
  189. DPF5(100, "CreateGraph: %s F %x LFN %08x F %x T %x",
  190. pLogicalFilterNode->pFilterNode->DumpName(),
  191. ulFlagsCurrent,
  192. pLogicalFilterNode,
  193. pLogicalFilterNode->GetFlags(),
  194. pLogicalFilterNode->GetType());
  195. //
  196. // Rule: don't allow the same filter be connected twice
  197. //
  198. if(pLogicalFilterNode == pLogicalFilterNodePrevious) {
  199. DPF1(100, "CreateGraph: same LFN: %08x", pLogicalFilterNode);
  200. continue;
  201. }
  202. ulFlagsDiff = ~(ulFlagsCurrent ^ pLogicalFilterNode->GetFlags());
  203. if((ulFlagsDiff &
  204. (LFN_FLAGS_CONNECT_CAPTURE |
  205. LFN_FLAGS_CONNECT_RENDER)) == 0) {
  206. DPF1(100, "CreateGraph: i/o no match: LFN %08x",
  207. pLogicalFilterNode);
  208. continue;
  209. }
  210. if((ulFlagsDiff & LFN_FLAGS_CONNECT_NORMAL_TOPOLOGY) == 0) {
  211. DPF1(100, "CreateGraph: norm no match: LFN %08x",
  212. pLogicalFilterNode);
  213. continue;
  214. }
  215. if((ulFlagsDiff & LFN_FLAGS_CONNECT_MIXER_TOPOLOGY) == 0) {
  216. DPF1(100, "CreateGraph: mixer no match: LFN %08x",
  217. pLogicalFilterNode);
  218. continue;
  219. }
  220. if(pLogicalFilterNode->GetOrder() <
  221. pLogicalFilterNodePrevious->GetOrder()) {
  222. DPF2(100, "CreateGraph: ulOrder(%x) < Previous Order (%x)",
  223. pLogicalFilterNode->GetOrder(),
  224. pLogicalFilterNodePrevious->GetOrder());
  225. continue;
  226. }
  227. #ifndef CONNECT_DIRECT_TO_HW
  228. if(pLogicalFilterNode->GetType() & FILTER_TYPE_PRE_MIXER) {
  229. if(pLogicalFilterNodePrevious->GetOrder() < ORDER_MIXER) {
  230. if(gcMixers > 0) {
  231. // 100
  232. DPF2(50,
  233. "CreateGraph: previous order (%x) < ORDER_MIXER LFN %08x",
  234. pLogicalFilterNodePrevious->GetOrder(),
  235. pLogicalFilterNode);
  236. continue;
  237. }
  238. }
  239. }
  240. #endif
  241. if(!pLogicalFilterNode->pFilterNode->IsDeviceInterfaceMatch(
  242. pDeviceNode)) {
  243. DPF1(100, "CreateGraph: no dev interface match DN %08x",
  244. pDeviceNode);
  245. continue;
  246. }
  247. //
  248. // Enumerate each "To" pin on the LFN to see if it matchs the input pin
  249. //
  250. Status = CreateGraphToPin(
  251. pPinNode,
  252. pConnectNodePrevious,
  253. pLogicalFilterNode,
  254. pGraphPinInfoPrevious,
  255. ulFlagsCurrent,
  256. ulOverhead);
  257. if(!NT_SUCCESS(Status)) {
  258. Trap();
  259. goto exit;
  260. }
  261. } END_EACH_LIST_ITEM // end each LFN
  262. Status = CStartNode::Create(
  263. pPinNode,
  264. pConnectNodePrevious,
  265. pGraphPinInfoPrevious,
  266. ulFlagsCurrent,
  267. ulOverhead,
  268. this);
  269. if(!NT_SUCCESS(Status)) {
  270. Trap();
  271. goto exit;
  272. }
  273. exit:
  274. //
  275. // Remove the GPI if it doesn't have any other references from SIs or CIs
  276. //
  277. if (pGraphPinInfo) {
  278. pGraphPinInfo->Destroy();
  279. }
  280. gcGraphRecursion--;
  281. return(Status);
  282. }
  283. NTSTATUS
  284. CGraphNode::CreateGraphToPin(
  285. PPIN_NODE pPinNode,
  286. PCONNECT_NODE pConnectNodePrevious,
  287. PLOGICAL_FILTER_NODE pLogicalFilterNode,
  288. PGRAPH_PIN_INFO pGraphPinInfo,
  289. ULONG ulFlagsCurrent,
  290. ULONG ulOverhead
  291. )
  292. {
  293. PCONNECT_NODE pConnectNode = NULL;
  294. NTSTATUS Status = STATUS_SUCCESS;
  295. PPIN_NODE pPinNodeTo;
  296. Assert(this);
  297. Assert(pPinNode);
  298. Assert(pPinNode->pPinInfo);
  299. Assert(pLogicalFilterNode);
  300. FOR_EACH_LIST_ITEM(&pLogicalFilterNode->lstPinNode, pPinNodeTo) {
  301. Assert(pPinNodeTo);
  302. Assert(pPinNodeTo->pPinInfo);
  303. ASSERT(pPinNodeTo->pLogicalFilterNode == pLogicalFilterNode);
  304. //
  305. // The dataflow, communication, interface, medium and data
  306. // formats must be compatible.
  307. //
  308. if(!pPinNode->ComparePins(pPinNodeTo)) {
  309. DPF2(100, "CreateGraph: pins mis: PN %08x PNTo %08x",
  310. pPinNode,
  311. pPinNodeTo);
  312. continue;
  313. }
  314. Status = CConnectNode::Create(
  315. &pConnectNode,
  316. pLogicalFilterNode,
  317. pConnectNodePrevious,
  318. pGraphPinInfo,
  319. pPinNode,
  320. pPinNodeTo,
  321. ulFlagsCurrent,
  322. this);
  323. if(!NT_SUCCESS(Status)) {
  324. Trap();
  325. goto exit;
  326. }
  327. //
  328. // Enumerate each "from" pin on the LFN and recurse building the graph
  329. //
  330. Status = CreateGraphFromPin(
  331. pPinNode,
  332. pPinNodeTo,
  333. pConnectNode,
  334. pLogicalFilterNode,
  335. pConnectNode->IsPinInstanceReserved() ? NULL : pGraphPinInfo,
  336. ulFlagsCurrent,
  337. ulOverhead);
  338. if(!NT_SUCCESS(Status)) {
  339. Trap();
  340. goto exit;
  341. }
  342. //
  343. // Remove CN if it doesn't have any other refs from other CNs or SNs.
  344. //
  345. pConnectNode->Destroy();
  346. pConnectNode = NULL;
  347. } END_EACH_LIST_ITEM // end each LFN node "to" pin node
  348. exit:
  349. if(!NT_SUCCESS(Status)) {
  350. //
  351. // Clean up the last CN created if error
  352. //
  353. Trap();
  354. pConnectNode->Destroy();
  355. }
  356. return(Status);
  357. }
  358. NTSTATUS
  359. CGraphNode::CreateGraphFromPin(
  360. PPIN_NODE pPinNode,
  361. PPIN_NODE pPinNodeTo,
  362. PCONNECT_NODE pConnectNode,
  363. PLOGICAL_FILTER_NODE pLogicalFilterNode,
  364. PGRAPH_PIN_INFO pGraphPinInfo,
  365. ULONG ulFlagsCurrent,
  366. ULONG ulOverhead
  367. )
  368. {
  369. NTSTATUS Status = STATUS_SUCCESS;
  370. PPIN_NODE pPinNodeFrom;
  371. Assert(this);
  372. Assert(pPinNode);
  373. Assert(pPinNodeTo);
  374. Assert(pPinNodeTo->pPinInfo);
  375. Assert(pLogicalFilterNode);
  376. FOR_EACH_LIST_ITEM(&pLogicalFilterNode->lstPinNode, pPinNodeFrom) {
  377. ASSERT(pPinNodeFrom->pLogicalFilterNode == pLogicalFilterNode);
  378. if(pPinNodeTo->pPinInfo == pPinNodeFrom->pPinInfo) {
  379. continue;
  380. }
  381. if(pLogicalFilterNode->GetFlags() & LFN_FLAGS_REFLECT_DATARANGE) {
  382. pPinNodeFrom = new PIN_NODE(this, pPinNodeFrom);
  383. if(pPinNodeFrom == NULL) {
  384. Status = STATUS_INSUFFICIENT_RESOURCES;
  385. Trap();
  386. goto exit;
  387. }
  388. pPinNodeFrom->pDataRange = pPinNode->pDataRange;
  389. }
  390. //
  391. // Recurse building the graph
  392. //
  393. Status = CreateGraph(
  394. pPinNodeFrom,
  395. pConnectNode,
  396. pLogicalFilterNode,
  397. pGraphPinInfo,
  398. ulFlagsCurrent,
  399. ulOverhead +
  400. pPinNodeFrom->GetOverhead() +
  401. pLogicalFilterNode->GetOverhead());
  402. if(!NT_SUCCESS(Status)) {
  403. Trap();
  404. goto exit;
  405. }
  406. } END_EACH_LIST_ITEM // end each LFN "from" pin node
  407. exit:
  408. return(Status);
  409. }
  410. //---------------------------------------------------------------------------