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.

400 lines
11 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Module: sn.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. NTSTATUS
  30. CStartNode::Create(
  31. PPIN_NODE pPinNode,
  32. PCONNECT_NODE pConnectNode,
  33. PGRAPH_PIN_INFO pGraphPinInfo,
  34. ULONG ulFlagsCurrent,
  35. ULONG ulOverhead,
  36. PGRAPH_NODE pGraphNode
  37. )
  38. {
  39. PTOPOLOGY_CONNECTION pTopologyConnection;
  40. NTSTATUS Status = STATUS_SUCCESS;
  41. PSTART_NODE pStartNode = NULL;
  42. Assert(pPinNode);
  43. Assert(pGraphNode);
  44. if((pPinNode->pPinInfo->Communication == KSPIN_COMMUNICATION_SOURCE)) {
  45. ASSERT(NT_SUCCESS(Status));
  46. ASSERT(pStartNode == NULL);
  47. goto exit;
  48. }
  49. if(pPinNode->pPinInfo->Communication == KSPIN_COMMUNICATION_SINK ||
  50. pPinNode->pPinInfo->Communication == KSPIN_COMMUNICATION_BOTH) {
  51. // Don't create a sysaudio pin if OUT/RENDER or IN/CAPTURER
  52. if(pPinNode->pPinInfo->DataFlow == KSPIN_DATAFLOW_OUT &&
  53. ulFlagsCurrent & LFN_FLAGS_CONNECT_RENDER) {
  54. DPF1(50, "CStartNode::Create PN %08x - out/render", pPinNode);
  55. ASSERT(NT_SUCCESS(Status));
  56. ASSERT(pStartNode == NULL);
  57. goto exit;
  58. }
  59. if(pPinNode->pPinInfo->DataFlow == KSPIN_DATAFLOW_IN &&
  60. ulFlagsCurrent & LFN_FLAGS_CONNECT_CAPTURE) {
  61. DPF1(50, "CStartNode::Create PN %08x - in/capturer", pPinNode);
  62. ASSERT(NT_SUCCESS(Status));
  63. ASSERT(pStartNode == NULL);
  64. goto exit;
  65. }
  66. }
  67. FOR_EACH_LIST_ITEM(
  68. &pPinNode->pPinInfo->lstTopologyConnection,
  69. pTopologyConnection) {
  70. // Only check physical connections
  71. if(!IS_CONNECTION_TYPE(pTopologyConnection, PHYSICAL)) {
  72. continue;
  73. }
  74. // If there is one connection that is valid for this GraphNode
  75. if(pTopologyConnection->IsTopologyConnectionOnGraphNode(pGraphNode)) {
  76. // Don't create a sysaudio pin
  77. DPF4(80, "CStartNode::Create %s PN %08x TC %08x GN %08x connected",
  78. pPinNode->pPinInfo->pFilterNode->DumpName(),
  79. pPinNode,
  80. pTopologyConnection,
  81. pGraphNode);
  82. ASSERT(NT_SUCCESS(Status));
  83. ASSERT(pStartNode == NULL);
  84. goto exit;
  85. }
  86. } END_EACH_LIST_ITEM
  87. pStartNode = new START_NODE(
  88. pPinNode,
  89. pConnectNode,
  90. ulOverhead,
  91. pGraphNode);
  92. if(pStartNode == NULL) {
  93. Status = STATUS_INSUFFICIENT_RESOURCES;
  94. goto exit;
  95. }
  96. Status = CStartInfo::Create(
  97. pStartNode,
  98. pConnectNode->GetConnectInfo(),
  99. pGraphPinInfo,
  100. pGraphNode);
  101. if(!NT_SUCCESS(Status)) {
  102. Trap();
  103. goto exit;
  104. }
  105. DPF3(80, "CStartNode::Create %08x PN %08x O %08x",
  106. pStartNode,
  107. pPinNode,
  108. pStartNode->ulOverhead);
  109. //
  110. // For capture graphs only.
  111. //
  112. if (pStartNode->pPinNode->pPinInfo->DataFlow == KSPIN_DATAFLOW_OUT) {
  113. pStartNode->SetSpecialFlags();
  114. }
  115. exit:
  116. if(!NT_SUCCESS(Status)) {
  117. if (pStartNode) {
  118. pStartNode->Destroy();
  119. }
  120. }
  121. return(Status);
  122. }
  123. CStartNode::CStartNode(
  124. PPIN_NODE pPinNode,
  125. PCONNECT_NODE pConnectNode,
  126. ULONG ulOverhead,
  127. PGRAPH_NODE pGraphNode
  128. )
  129. {
  130. Assert(pPinNode);
  131. Assert(pGraphNode);
  132. this->pPinNode = pPinNode;
  133. this->ulOverhead = ulOverhead + pPinNode->GetOverhead();
  134. this->pConnectNodeHead = pConnectNode;
  135. this->ulFlags = 0;
  136. this->fRender = (pPinNode->pPinInfo->DataFlow == KSPIN_DATAFLOW_IN);
  137. this->ulSpecialFlags = STARTNODE_SPECIALFLAG_NONE;
  138. pConnectNode->AddRef();
  139. if(pPinNode->GetType() & FILTER_TYPE_VIRTUAL) {
  140. AddListEnd(&pGraphNode->lstStartNode);
  141. }
  142. else {
  143. AddList(&pGraphNode->lstStartNode);
  144. }
  145. DPF3(80, "CStartNode: %08x PN %08x O %08x", this, pPinNode, ulOverhead);
  146. }
  147. CStartNode::~CStartNode(
  148. )
  149. {
  150. DPF1(80, "~CStartNode: %08x", this);
  151. Assert(this);
  152. RemoveList();
  153. pStartInfo->Destroy();
  154. pConnectNodeHead->Destroy();
  155. }
  156. void
  157. CStartNode::SetSpecialFlags()
  158. {
  159. //
  160. // STARTNODE_SPECIALFLAG_STRICT
  161. // Get the last ConnectNode in connection list and check if the
  162. // source pin is splitter.
  163. // Also the first pin should be splitter pin.
  164. //
  165. //
  166. // STARTNODE_SPECIALFLAG_AEC
  167. // If the StartNode contains Aec mark the StartNode with this flag.
  168. //
  169. //
  170. // ISSUE-2001/03/09-alpers
  171. // In the future two splitters in the graph will not work
  172. // with this logic.
  173. // We need a way of knowing if a filter does SRC upfront.
  174. //
  175. if (pConnectNodeHead)
  176. {
  177. PCONNECT_NODE pConnectNode;
  178. for(pConnectNode = pConnectNodeHead;
  179. pConnectNode->GetNextConnectNode() != NULL;
  180. pConnectNode = pConnectNode->GetNextConnectNode()) {
  181. if (pConnectNode->pPinNodeSource->pLogicalFilterNode->
  182. pFilterNode->GetType() & FILTER_TYPE_AEC) {
  183. ulSpecialFlags |= STARTNODE_SPECIALFLAG_AEC;
  184. }
  185. }
  186. ulSpecialFlags |=
  187. (pConnectNode->pPinNodeSource->pPinInfo->
  188. pFilterNode->GetType() & FILTER_TYPE_SPLITTER) &&
  189. (pPinNode->pPinInfo->pFilterNode->GetType() & FILTER_TYPE_SPLITTER) ?
  190. STARTNODE_SPECIALFLAG_STRICT :
  191. STARTNODE_SPECIALFLAG_NONE;
  192. }
  193. DPF3(50, "CStartNode: %08x %s SpecialFlags %X", this,
  194. DbgUnicode2Sz(pPinNode->pPinInfo->pFilterNode->GetFriendlyName()),
  195. ulSpecialFlags);
  196. }
  197. ENUMFUNC
  198. CStartNode::RemoveBypassPaths(
  199. PVOID pReference
  200. )
  201. {
  202. PGRAPH_NODE pGraphNode = PGRAPH_NODE(pReference);
  203. PLOGICAL_FILTER_NODE pLogicalFilterNode;
  204. PCONNECT_NODE pConnectNode;
  205. ULONG cLfnNoBypassTotal = 0;
  206. ULONG cLfnNoBypass = 0;
  207. ULONG ulFlags;
  208. ULONG cAecFilterCount = 0;
  209. BOOL fDestroy;
  210. Assert(this);
  211. Assert(pGraphNode);
  212. if(pPinNode->pPinInfo->Communication == KSPIN_COMMUNICATION_NONE ||
  213. pPinNode->pPinInfo->Communication == KSPIN_COMMUNICATION_BRIDGE ||
  214. pPinNode->pPinInfo->Communication == KSPIN_COMMUNICATION_SOURCE) {
  215. return(STATUS_CONTINUE);
  216. }
  217. if(pPinNode->pPinInfo->DataFlow == KSPIN_DATAFLOW_IN) {
  218. ulFlags = LFN_FLAGS_CONNECT_RENDER;
  219. DPF(60,"RBP - for Render");
  220. }
  221. else {
  222. ASSERT(pPinNode->pPinInfo->DataFlow == KSPIN_DATAFLOW_OUT);
  223. ulFlags = LFN_FLAGS_CONNECT_CAPTURE;
  224. DPF(60,"RBP - for Capture");
  225. }
  226. FOR_EACH_LIST_ITEM(
  227. &pGraphNode->lstLogicalFilterNodeNoBypass,
  228. pLogicalFilterNode) {
  229. if(pLogicalFilterNode->GetFlags() & ulFlags) {
  230. ++cLfnNoBypassTotal;
  231. }
  232. } END_EACH_LIST_ITEM
  233. DPF1(60,"RBP:NoBypassTotal = %08x", cLfnNoBypassTotal);
  234. for(pConnectNode = GetFirstConnectNode();
  235. pConnectNode != NULL;
  236. pConnectNode = pConnectNode->GetNextConnectNode()) {
  237. Assert(pConnectNode);
  238. FOR_EACH_LIST_ITEM(
  239. &pGraphNode->lstLogicalFilterNodeNoBypass,
  240. pLogicalFilterNode) {
  241. if(pLogicalFilterNode->GetFlags() & ulFlags) {
  242. Assert(pConnectNode->pPinNodeSource);
  243. Assert(pConnectNode->pPinNodeSource->pLogicalFilterNode);
  244. if(pConnectNode->pPinNodeSource->pLogicalFilterNode ==
  245. pLogicalFilterNode) {
  246. cLfnNoBypass++;
  247. }
  248. }
  249. } END_EACH_LIST_ITEM
  250. DPF1(60,"RBP:FilterInPath = %s",
  251. DbgUnicode2Sz(pConnectNode->pPinNodeSource->pLogicalFilterNode->pFilterNode->GetFriendlyName()));
  252. //
  253. // In capture paths count AEC filters to avoid conflict with GFXes
  254. //
  255. if((ulFlags & LFN_FLAGS_CONNECT_CAPTURE) &&
  256. (pConnectNode->pPinNodeSource->pLogicalFilterNode->pFilterNode->GetType() & FILTER_TYPE_AEC)) {
  257. ++cAecFilterCount;
  258. }
  259. }
  260. ASSERT(cAecFilterCount < 2);
  261. DPF2(60,"RBP:NBPCount=%08x, AECCount=%08x", cLfnNoBypass, cAecFilterCount);
  262. //
  263. // Mark all the paths with NO Gfx as second pass candidates
  264. // We do this to support the following sequence of capture pin creations
  265. // 1. Client installs GFX(es) on a capture device
  266. // 2. Client creates a pin with AEC
  267. // This would result in creating a Capture->Splitter->AEC path
  268. // 3. Client tries to create a regular capture pin (with GFX)
  269. // In this case we want to create a regular path (but since no GFX
  270. // hooked up between capture and splitter. We create a capture->splitter->[kmixer] path
  271. // These special paths are marked as secondpass. And we try these paths
  272. // only if all the primary start nodes failed to instantiate a pin.
  273. // (look in pins.cpp - PinDispatchCreateKP()
  274. //
  275. if(cLfnNoBypassTotal != 0) {
  276. if(cLfnNoBypass == 0) {
  277. this->ulFlags |= STARTNODE_FLAGS_SECONDPASS;
  278. }
  279. }
  280. //
  281. // Assume that this path is going to be OK
  282. //
  283. fDestroy = FALSE;
  284. if (cAecFilterCount == 0) {
  285. //
  286. // There is no AEC in this path
  287. // We have to make sure that we have all the necessary
  288. // GFXs loaded in this path. (Else destroy the path)
  289. //
  290. if(cLfnNoBypass != cLfnNoBypassTotal) {
  291. fDestroy = TRUE;
  292. }
  293. }
  294. else {
  295. //
  296. // There is an AEC in this path
  297. // No GFXs should be there in this path. If there is even one GFX
  298. // destroy the path
  299. //
  300. if ((cLfnNoBypass != 0) || (cAecFilterCount > 1)) {
  301. fDestroy = TRUE;
  302. }
  303. }
  304. if ((fDestroy) && ((this->ulFlags & STARTNODE_FLAGS_SECONDPASS) == 0)) {
  305. Destroy();
  306. DPF(60,"RBP:PathDestroyed");
  307. }
  308. DPF(60,"RBP:Done");
  309. return(STATUS_CONTINUE);
  310. }
  311. ENUMFUNC
  312. CStartNode::RemoveConnectedStartNode(
  313. PVOID pReference
  314. )
  315. {
  316. PGRAPH_NODE pGraphNode = PGRAPH_NODE(pReference);
  317. PCONNECT_NODE pConnectNode;
  318. PSTART_NODE pStartNode;
  319. Assert(this);
  320. Assert(pGraphNode);
  321. FOR_EACH_LIST_ITEM(&pGraphNode->lstStartNode, pStartNode) {
  322. if(this == pStartNode) {
  323. continue;
  324. }
  325. for(pConnectNode = pStartNode->GetFirstConnectNode();
  326. pConnectNode != NULL;
  327. pConnectNode = pConnectNode->GetNextConnectNode()) {
  328. if(this->pPinNode == pConnectNode->pPinNodeSink) {
  329. DPF3(50, "CStartNode::RemoveConnectedSN %08x GN %08x %s",
  330. this,
  331. pGraphNode,
  332. pPinNode->pPinInfo->pFilterNode->DumpName());
  333. Destroy();
  334. return(STATUS_CONTINUE);
  335. }
  336. }
  337. } END_EACH_LIST_ITEM
  338. return(STATUS_CONTINUE);
  339. }
  340. //---------------------------------------------------------------------------