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.

387 lines
11 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Module: topology.c
  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. ENUMFUNC
  29. EnumerateTopology(
  30. IN PPIN_INFO pPinInfo,
  31. IN NTSTATUS (*Function)(
  32. IN PTOPOLOGY_CONNECTION pTopologyConnection,
  33. IN BOOL fToDirection,
  34. IN OUT PVOID pReference
  35. ),
  36. IN OUT PVOID pReference
  37. )
  38. {
  39. ENUM_TOPOLOGY EnumTopology;
  40. NTSTATUS Status;
  41. Assert(pPinInfo);
  42. EnumTopology.cTopologyRecursion = 0;
  43. EnumTopology.Function = Function;
  44. EnumTopology.fToDirection = (pPinInfo->DataFlow == KSPIN_DATAFLOW_IN);
  45. EnumTopology.pReference = pReference;
  46. Status = EnumeratePinInfoTopology(pPinInfo, &EnumTopology);
  47. return(Status);
  48. }
  49. ENUMFUNC
  50. EnumerateGraphTopology(
  51. IN PSTART_INFO pStartInfo,
  52. IN NTSTATUS (*Function)(
  53. IN PTOPOLOGY_CONNECTION pTopologyConnection,
  54. IN BOOL fToDirection,
  55. IN OUT PVOID pReference
  56. ),
  57. IN OUT PVOID pReference
  58. )
  59. {
  60. PCONNECT_INFO pConnectInfo;
  61. NTSTATUS Status;
  62. Assert(pStartInfo);
  63. Assert(pStartInfo->GetPinInfo());
  64. Status = EnumerateTopology(
  65. pStartInfo->GetPinInfo(),
  66. Function,
  67. pReference);
  68. if(Status != STATUS_CONTINUE) {
  69. goto exit;
  70. }
  71. for(pConnectInfo = pStartInfo->GetFirstConnectInfo();
  72. pConnectInfo != NULL;
  73. pConnectInfo = pConnectInfo->GetNextConnectInfo()) {
  74. Assert(pConnectInfo);
  75. Status = EnumerateTopology(
  76. pConnectInfo->pPinInfoSink,
  77. Function,
  78. pReference);
  79. if(Status != STATUS_CONTINUE) {
  80. goto exit;
  81. }
  82. }
  83. exit:
  84. return(Status);
  85. }
  86. ENUMFUNC
  87. EnumeratePinInfoTopology(
  88. IN PPIN_INFO pPinInfo,
  89. IN PENUM_TOPOLOGY pEnumTopology
  90. )
  91. {
  92. PTOPOLOGY_CONNECTION pTopologyConnection;
  93. NTSTATUS Status = STATUS_CONTINUE;
  94. Assert(pPinInfo);
  95. Assert(pEnumTopology);
  96. DPF2(110, "EnumerateTopologyPinInfo %08x #%x", pPinInfo, pPinInfo->PinId);
  97. FOR_EACH_LIST_ITEM(
  98. &pPinInfo->lstTopologyConnection,
  99. pTopologyConnection) {
  100. Assert(pTopologyConnection);
  101. if(pEnumTopology->fToDirection) {
  102. if(pTopologyConnection->pPinInfoFrom != pPinInfo) {
  103. continue;
  104. }
  105. ASSERT(pTopologyConnection->pPinInfoTo != pPinInfo);
  106. }
  107. else {
  108. if(pTopologyConnection->pPinInfoTo != pPinInfo) {
  109. continue;
  110. }
  111. ASSERT(pTopologyConnection->pPinInfoFrom != pPinInfo);
  112. }
  113. Status = EnumerateTopologyConnection(
  114. pTopologyConnection,
  115. pEnumTopology);
  116. if(Status != STATUS_CONTINUE) {
  117. goto exit;
  118. }
  119. } END_EACH_LIST_ITEM
  120. exit:
  121. return(Status);
  122. }
  123. ENUMFUNC
  124. EnumerateTopologyPin(
  125. IN PTOPOLOGY_PIN pTopologyPin,
  126. IN PENUM_TOPOLOGY pEnumTopology
  127. )
  128. {
  129. PTOPOLOGY_CONNECTION pTopologyConnection;
  130. PTOPOLOGY_PIN pTopologyPin2;
  131. NTSTATUS Status = STATUS_CONTINUE;
  132. BOOL fFromPinEqual = TRUE;
  133. ULONG ulFromPinNumber = MAXULONG;
  134. BOOL fToPinEqual = TRUE;
  135. ULONG ulToPinNumber = MAXULONG;
  136. BOOL fPinEqual;
  137. ULONG ulPinNumber;
  138. Assert(pTopologyPin);
  139. Assert(pEnumTopology);
  140. DPF3(110, "EnumerateTopologyPin %08x TP #%x TN #%x",
  141. pTopologyPin,
  142. pTopologyPin->ulPinNumber,
  143. pTopologyPin->pTopologyNode->ulRealNodeNumber);
  144. if(IsEqualGUID(
  145. &KSNODETYPE_ACOUSTIC_ECHO_CANCEL,
  146. pTopologyPin->pTopologyNode->pguidType)) {
  147. switch(pTopologyPin->ulPinNumber) {
  148. case KSNODEPIN_AEC_RENDER_OUT:
  149. ASSERT(!pEnumTopology->fToDirection);
  150. case KSNODEPIN_AEC_RENDER_IN:
  151. ulFromPinNumber = KSNODEPIN_AEC_RENDER_IN;
  152. ulToPinNumber = KSNODEPIN_AEC_RENDER_OUT;
  153. break;
  154. case KSNODEPIN_AEC_CAPTURE_OUT:
  155. ASSERT(!pEnumTopology->fToDirection);
  156. case KSNODEPIN_AEC_CAPTURE_IN:
  157. ulFromPinNumber = KSNODEPIN_AEC_CAPTURE_IN;
  158. ulToPinNumber = KSNODEPIN_AEC_CAPTURE_OUT;
  159. break;
  160. }
  161. }
  162. else if(IsEqualGUID(
  163. &KSNODETYPE_SUM,
  164. pTopologyPin->pTopologyNode->pguidType) ||
  165. IsEqualGUID(
  166. &KSNODETYPE_MUX,
  167. pTopologyPin->pTopologyNode->pguidType)) {
  168. ulFromPinNumber = KSNODEPIN_SUM_MUX_IN;
  169. fFromPinEqual = FALSE;
  170. ulToPinNumber = KSNODEPIN_SUM_MUX_OUT;
  171. }
  172. else if(IsEqualGUID(
  173. &KSNODETYPE_DEMUX,
  174. pTopologyPin->pTopologyNode->pguidType)) {
  175. ulFromPinNumber = KSNODEPIN_DEMUX_IN;
  176. ulToPinNumber = KSNODEPIN_DEMUX_OUT;
  177. fToPinEqual = FALSE;
  178. }
  179. else {
  180. ulFromPinNumber = KSNODEPIN_STANDARD_IN;
  181. ulToPinNumber = KSNODEPIN_STANDARD_OUT;
  182. }
  183. // Swap pin numbers and flags
  184. if(!pEnumTopology->fToDirection) {
  185. ulPinNumber = ulToPinNumber;
  186. ulToPinNumber = ulFromPinNumber;
  187. ulFromPinNumber = ulPinNumber;
  188. fPinEqual = fToPinEqual;
  189. fToPinEqual = fFromPinEqual;
  190. fFromPinEqual = fPinEqual;
  191. }
  192. ASSERT(ulToPinNumber != MAXULONG);
  193. ASSERT(ulFromPinNumber != MAXULONG);
  194. // Validate input/from pin(s)
  195. if(fFromPinEqual) {
  196. if(pTopologyPin->ulPinNumber != ulFromPinNumber) {
  197. DPF2(5, "EnumerateTopologyPin: %s bad 'from' pin number %08x",
  198. pTopologyPin->pTopologyNode->pFilterNode->DumpName(),
  199. pTopologyPin->ulPinNumber);
  200. Status = STATUS_INVALID_DEVICE_REQUEST;
  201. goto exit;
  202. }
  203. }
  204. else {
  205. if(pTopologyPin->ulPinNumber < ulFromPinNumber) {
  206. DPF2(5, "EnumerateTopologyPin: %s bad 'from' pin number %08x",
  207. pTopologyPin->pTopologyNode->pFilterNode->DumpName(),
  208. pTopologyPin->ulPinNumber);
  209. Status = STATUS_INVALID_DEVICE_REQUEST;
  210. goto exit;
  211. }
  212. }
  213. FOR_EACH_LIST_ITEM(
  214. &pTopologyPin->pTopologyNode->lstTopologyPin,
  215. pTopologyPin2) {
  216. if(pTopologyPin == pTopologyPin2) {
  217. continue;
  218. }
  219. // Pick the right output/to pin(s)
  220. if(fToPinEqual) {
  221. if(pTopologyPin2->ulPinNumber != ulToPinNumber) {
  222. continue;
  223. }
  224. }
  225. else {
  226. if(pTopologyPin2->ulPinNumber < ulToPinNumber) {
  227. continue;
  228. }
  229. }
  230. FOR_EACH_LIST_ITEM(
  231. &pTopologyPin2->lstTopologyConnection,
  232. pTopologyConnection) {
  233. Assert(pTopologyConnection);
  234. if(pEnumTopology->fToDirection) {
  235. if(pTopologyConnection->pTopologyPinFrom != pTopologyPin2) {
  236. continue;
  237. }
  238. ASSERT(pTopologyConnection->pTopologyPinTo != pTopologyPin2);
  239. }
  240. else {
  241. if(pTopologyConnection->pTopologyPinTo != pTopologyPin2) {
  242. continue;
  243. }
  244. ASSERT(pTopologyConnection->pTopologyPinFrom != pTopologyPin2);
  245. }
  246. Status = EnumerateTopologyConnection(
  247. pTopologyConnection,
  248. pEnumTopology);
  249. if(Status != STATUS_CONTINUE) {
  250. goto exit;
  251. }
  252. } END_EACH_LIST_ITEM
  253. } END_EACH_LIST_ITEM
  254. exit:
  255. return(Status);
  256. }
  257. ENUMFUNC
  258. EnumerateTopologyConnection(
  259. IN PTOPOLOGY_CONNECTION pTopologyConnection,
  260. IN PENUM_TOPOLOGY pEnumTopology
  261. )
  262. {
  263. PTOPOLOGY_PIN pTopologyPin;
  264. PPIN_INFO pPinInfo;
  265. NTSTATUS Status;
  266. Assert(pEnumTopology);
  267. Assert(pTopologyConnection);
  268. DPF1(110, "EnumerateTopologyConnection %08x", pTopologyConnection);
  269. if(pEnumTopology->cTopologyRecursion++ > (gcTopologyConnections + 16)) {
  270. Trap();
  271. DPF(5, "EnumerateTopologyConnection: recursion too deep");
  272. Status = STATUS_STACK_OVERFLOW;
  273. goto exit;
  274. }
  275. // Have we visited this topology connection already?
  276. Status = VisitedTopologyConnection(pTopologyConnection, pEnumTopology);
  277. if(Status != STATUS_CONTINUE) {
  278. if(Status == STATUS_DEAD_END) {
  279. Status = STATUS_CONTINUE;
  280. }
  281. goto exit;
  282. }
  283. Status = (*pEnumTopology->Function)(
  284. pTopologyConnection,
  285. pEnumTopology->fToDirection,
  286. pEnumTopology->pReference);
  287. if(Status != STATUS_CONTINUE) {
  288. if(Status == STATUS_DEAD_END) {
  289. Status = STATUS_CONTINUE;
  290. }
  291. goto exit;
  292. }
  293. if(pEnumTopology->fToDirection) {
  294. pTopologyPin = pTopologyConnection->pTopologyPinTo;
  295. pPinInfo = pTopologyConnection->pPinInfoTo;
  296. }
  297. else {
  298. pTopologyPin = pTopologyConnection->pTopologyPinFrom;
  299. pPinInfo = pTopologyConnection->pPinInfoFrom;
  300. }
  301. if(pTopologyPin != NULL) {
  302. Status = EnumerateTopologyPin(pTopologyPin, pEnumTopology);
  303. if(Status != STATUS_CONTINUE) {
  304. goto exit;
  305. }
  306. }
  307. if(pPinInfo != NULL) {
  308. Status = EnumeratePinInfoTopology(pPinInfo, pEnumTopology);
  309. if(Status != STATUS_CONTINUE) {
  310. goto exit;
  311. }
  312. }
  313. exit:
  314. pEnumTopology->cTopologyRecursion--;
  315. return(Status);
  316. }
  317. ENUMFUNC
  318. VisitedTopologyConnection(
  319. IN PTOPOLOGY_CONNECTION pTopologyConnection,
  320. IN PENUM_TOPOLOGY pEnumTopology
  321. )
  322. {
  323. NTSTATUS Status;
  324. Assert(pEnumTopology);
  325. Assert(pTopologyConnection);
  326. // Have we visited this topology connection already?
  327. if(pTopologyConnection->CheckDupList(
  328. &pEnumTopology->lstTopologyConnection)) {
  329. DPF1(100, "VisitedTopologyConnection: %08x already visited",
  330. pTopologyConnection);
  331. Status = STATUS_DEAD_END;
  332. goto exit; // yes, break cycle in topology
  333. }
  334. // Add topology pin to list of pin's visited
  335. Status = pTopologyConnection->AddList(
  336. &pEnumTopology->lstTopologyConnection);
  337. if(!NT_SUCCESS(Status)) {
  338. goto exit;
  339. }
  340. Status = STATUS_CONTINUE;
  341. exit:
  342. return(Status);
  343. }
  344. //---------------------------------------------------------------------------