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.

901 lines
25 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Module: property.c
  4. //
  5. // Description:
  6. //
  7. //
  8. //@@BEGIN_MSINTERNAL
  9. // Development Team:
  10. // Andy Nicholson
  11. //
  12. // History: Date Author Comment
  13. //
  14. // To Do: Date Author Comment
  15. //
  16. //@@END_MSINTERNAL
  17. //---------------------------------------------------------------------------
  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. //---------------------------------------------------------------------------
  30. #define IsTopologyProperty(x) (x & KSPROPERTY_TYPE_TOPOLOGY)
  31. //---------------------------------------------------------------------------
  32. //
  33. // Copy pwstrString to pData.
  34. // Assumptions
  35. // - pIrp has already been verified. input buffer is probed and double
  36. // buffered.
  37. //
  38. NTSTATUS
  39. PropertyReturnString(
  40. IN PIRP pIrp,
  41. IN PWSTR pwstrString,
  42. IN ULONG cbString,
  43. OUT PVOID pData
  44. )
  45. {
  46. NTSTATUS Status = STATUS_SUCCESS;
  47. PIO_STACK_LOCATION pIrpStack;
  48. ULONG cbNameBuffer;
  49. ULONG cbToCopy;
  50. pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  51. cbNameBuffer = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
  52. //
  53. // If the size of the passed buffer is 0, then the
  54. // requestor wants to know the length of the string.
  55. //
  56. if (cbNameBuffer == 0)
  57. {
  58. pIrp->IoStatus.Information = cbString;
  59. Status = STATUS_BUFFER_OVERFLOW;
  60. }
  61. //
  62. // If the size of the passed buffer is a ULONG, then infer the
  63. // requestor wants to know the length of the string.
  64. //
  65. else if (cbNameBuffer == sizeof(ULONG))
  66. {
  67. pIrp->IoStatus.Information = sizeof(ULONG);
  68. *((PULONG)pData) = cbString;
  69. }
  70. //
  71. // The buffer is too small, return error-code.
  72. //
  73. else if (cbNameBuffer < sizeof(ULONG))
  74. {
  75. pIrp->IoStatus.Information = 0;
  76. Status = STATUS_BUFFER_TOO_SMALL;
  77. }
  78. else
  79. {
  80. //
  81. // Note that we don't check for zero-length buffer because ks handler
  82. // function should have done that already.
  83. // Even though we are getting back the length of the string (as though
  84. // it were a unicode string) it is being handed up as a double-byte
  85. // string, so this code assumes there is a null at the end. There
  86. // will be a bug here if there is no null.
  87. //
  88. // round down to whole wchar's
  89. cbNameBuffer &= ~(sizeof(WCHAR) - 1);
  90. cbToCopy = min(cbString, cbNameBuffer);
  91. RtlCopyMemory(pData, pwstrString, cbToCopy);
  92. // Ensure there is a null at the end
  93. ((PWCHAR)pData)[cbToCopy/sizeof(WCHAR) - 1] = (WCHAR)0;
  94. pIrp->IoStatus.Information = cbToCopy;
  95. }
  96. return(Status);
  97. }
  98. //---------------------------------------------------------------------------
  99. NTSTATUS
  100. GetDeviceNodeFromDeviceIndex(
  101. IN PFILTER_INSTANCE pFilterInstance,
  102. IN ULONG ulDeviceIndex,
  103. OUT PDEVICE_NODE *ppDeviceNode
  104. )
  105. {
  106. NTSTATUS Status = STATUS_SUCCESS;
  107. PDEVICE_NODE pDeviceNode;
  108. ASSERT(ppDeviceNode);
  109. ASSERT(pFilterInstance);
  110. *ppDeviceNode = NULL;
  111. if(ulDeviceIndex == MAXULONG) {
  112. pDeviceNode = pFilterInstance->GetDeviceNode();
  113. if(pDeviceNode == NULL) {
  114. Status = STATUS_INVALID_PARAMETER;
  115. goto exit;
  116. }
  117. }
  118. else {
  119. Status = GetDeviceByIndex(ulDeviceIndex, &pDeviceNode);
  120. if(!NT_SUCCESS(Status)) {
  121. goto exit;
  122. }
  123. }
  124. if (NT_SUCCESS(Status)) {
  125. Assert(pDeviceNode);
  126. }
  127. *ppDeviceNode = pDeviceNode;
  128. exit:
  129. return Status;
  130. } // GetDeviceNodeFromDeviceIndex
  131. //---------------------------------------------------------------------------
  132. NTSTATUS
  133. SetPreferredDevice(
  134. IN PIRP pIrp,
  135. IN PSYSAUDIO_PREFERRED_DEVICE pPreferred,
  136. IN PULONG pulDevice
  137. )
  138. {
  139. PFILTER_INSTANCE pFilterInstance;
  140. NTSTATUS Status = STATUS_SUCCESS;
  141. PIO_STACK_LOCATION pIrpStack;
  142. PDEVICE_NODE pDeviceNode,OldDeviceNode;
  143. if (IsTopologyProperty(pPreferred->Property.Flags)) {
  144. Status = STATUS_INVALID_PARAMETER;
  145. goto exit;
  146. }
  147. pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  148. pFilterInstance = (PFILTER_INSTANCE)pIrpStack->FileObject->FsContext;
  149. Assert(pFilterInstance);
  150. //
  151. // Validate input buffer.
  152. //
  153. if(pPreferred->Flags & ~SYSAUDIO_FLAGS_CLEAR_PREFERRED) {
  154. Status = STATUS_INVALID_PARAMETER;
  155. goto exit;
  156. }
  157. if(pPreferred->Index >= MAX_SYSAUDIO_DEFAULT_TYPE) {
  158. Trap();
  159. Status = STATUS_INVALID_PARAMETER;
  160. goto exit;
  161. }
  162. if(pPreferred->Flags & SYSAUDIO_FLAGS_CLEAR_PREFERRED) {
  163. OldDeviceNode = apShingleInstance[pPreferred->Index]->GetDeviceNode();
  164. if (OldDeviceNode) {
  165. OldDeviceNode->SetPreferredStatus(
  166. (KSPROPERTY_SYSAUDIO_DEFAULT_TYPE)pPreferred->Index,
  167. FALSE);
  168. }
  169. apShingleInstance[pPreferred->Index]->SetDeviceNode(NULL);
  170. DPF1(60, "SetPreferredDevice: CLEAR %d", pPreferred->Index);
  171. }
  172. else {
  173. Status = GetDeviceNodeFromDeviceIndex(
  174. pFilterInstance,
  175. *pulDevice,
  176. &pDeviceNode);
  177. if (!NT_SUCCESS(Status)) {
  178. goto exit;
  179. }
  180. OldDeviceNode = apShingleInstance[pPreferred->Index]->GetDeviceNode();
  181. if (OldDeviceNode) {
  182. OldDeviceNode->SetPreferredStatus(
  183. (KSPROPERTY_SYSAUDIO_DEFAULT_TYPE)pPreferred->Index,
  184. FALSE);
  185. }
  186. apShingleInstance[pPreferred->Index]->SetDeviceNode(pDeviceNode);
  187. pDeviceNode->SetPreferredStatus(
  188. (KSPROPERTY_SYSAUDIO_DEFAULT_TYPE)pPreferred->Index,
  189. TRUE);
  190. DPF3(60, "SetPreferredDevice: %d SAD %d %s",
  191. pPreferred->Index,
  192. *pulDevice,
  193. pDeviceNode->DumpName());
  194. }
  195. exit:
  196. return(Status);
  197. }
  198. NTSTATUS
  199. GetComponentIdProperty(
  200. IN PIRP pIrp,
  201. IN PKSPROPERTY pRequest,
  202. IN OUT PVOID pData
  203. )
  204. {
  205. NTSTATUS Status = STATUS_SUCCESS;
  206. PFILTER_INSTANCE pFilterInstance;
  207. PIO_STACK_LOCATION pIrpStack;
  208. PDEVICE_NODE pDeviceNode;
  209. ULONG DeviceIndex = *(PULONG)(pRequest + 1);
  210. if (IsTopologyProperty(pRequest->Flags)) {
  211. Status = STATUS_INVALID_PARAMETER;
  212. goto exit;
  213. }
  214. pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  215. pFilterInstance = (PFILTER_INSTANCE)pIrpStack->FileObject->FsContext;
  216. Assert(pFilterInstance);
  217. Status = GetDeviceNodeFromDeviceIndex(
  218. pFilterInstance,
  219. DeviceIndex,
  220. &pDeviceNode);
  221. if (!NT_SUCCESS(Status)) {
  222. goto exit;
  223. }
  224. if(pDeviceNode->GetComponentId() == NULL) {
  225. // This should be STATUS_NOT_FOUND but returning this causes
  226. // FilterDispatchIoControl call ForwardIrpNode which asserts that this
  227. // is not a KSPROPSETID_Sysaudio property.
  228. Status = STATUS_INVALID_DEVICE_REQUEST;
  229. goto exit;
  230. }
  231. RtlCopyMemory(
  232. pData,
  233. pDeviceNode->GetComponentId(),
  234. sizeof(KSCOMPONENTID));
  235. pIrp->IoStatus.Information = sizeof(KSCOMPONENTID);
  236. exit:
  237. return(Status);
  238. }
  239. NTSTATUS
  240. GetFriendlyNameProperty(
  241. IN PIRP pIrp,
  242. IN PKSPROPERTY pRequest,
  243. IN OUT PVOID pData
  244. )
  245. {
  246. NTSTATUS Status = STATUS_SUCCESS;
  247. PFILTER_INSTANCE pFilterInstance;
  248. PIO_STACK_LOCATION pIrpStack;
  249. PDEVICE_NODE pDeviceNode;
  250. ULONG DeviceIndex = *(PULONG)(pRequest + 1);
  251. if (IsTopologyProperty(pRequest->Flags)) {
  252. Status = STATUS_INVALID_PARAMETER;
  253. goto exit;
  254. }
  255. pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  256. pFilterInstance = (PFILTER_INSTANCE)pIrpStack->FileObject->FsContext;
  257. Assert(pFilterInstance);
  258. Status = GetDeviceNodeFromDeviceIndex(
  259. pFilterInstance,
  260. DeviceIndex,
  261. &pDeviceNode);
  262. if (!NT_SUCCESS(Status)) {
  263. goto exit;
  264. }
  265. if(pDeviceNode->GetFriendlyName() == NULL) {
  266. Status = STATUS_INVALID_DEVICE_REQUEST;
  267. goto exit;
  268. }
  269. Status = PropertyReturnString(
  270. pIrp,
  271. pDeviceNode->GetFriendlyName(),
  272. (wcslen(pDeviceNode->GetFriendlyName()) *
  273. sizeof(WCHAR)) + sizeof(UNICODE_NULL),
  274. pData);
  275. if(!NT_SUCCESS(Status)) {
  276. goto exit;
  277. }
  278. exit:
  279. return(Status);
  280. }
  281. NTSTATUS
  282. GetDeviceCount(
  283. IN PIRP pIrp,
  284. IN PKSPROPERTY pRequest,
  285. IN OUT PVOID pData
  286. )
  287. {
  288. if (IsTopologyProperty(pRequest->Flags)) {
  289. return STATUS_INVALID_PARAMETER;
  290. }
  291. if(gplstDeviceNode == NULL) {
  292. *(PULONG)pData = 0;
  293. }
  294. else {
  295. *(PULONG)pData = gplstDeviceNode->CountList();
  296. }
  297. pIrp->IoStatus.Information = sizeof(ULONG);
  298. return(STATUS_SUCCESS);
  299. }
  300. NTSTATUS
  301. GetInstanceDevice(
  302. IN PIRP pIrp,
  303. IN PKSPROPERTY pRequest,
  304. IN OUT PVOID pData
  305. )
  306. {
  307. NTSTATUS Status = STATUS_SUCCESS;
  308. PIO_STACK_LOCATION pIrpStack;
  309. PFILTER_INSTANCE pFilterInstance;
  310. PDEVICE_NODE pDeviceNode;
  311. ULONG Index;
  312. if (IsTopologyProperty(pRequest->Flags)) {
  313. Status = STATUS_INVALID_PARAMETER;
  314. goto exit;
  315. }
  316. pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  317. pFilterInstance = (PFILTER_INSTANCE)pIrpStack->FileObject->FsContext;
  318. Assert(pFilterInstance);
  319. pDeviceNode = pFilterInstance->GetDeviceNode();
  320. if(pDeviceNode == NULL) {
  321. Status = STATUS_INVALID_PARAMETER;
  322. goto exit;
  323. }
  324. Status = pDeviceNode->GetIndexByDevice(&Index);
  325. if(NT_SUCCESS(Status)) {
  326. *(PULONG)pData = Index;
  327. pIrp->IoStatus.Information = sizeof(ULONG);
  328. }
  329. exit:
  330. return(Status);
  331. }
  332. NTSTATUS
  333. SetInstanceDevice(
  334. IN PIRP Irp,
  335. IN PKSPROPERTY Request,
  336. IN OUT PVOID Data
  337. )
  338. {
  339. NTSTATUS Status = STATUS_SUCCESS;
  340. PFILTER_INSTANCE pFilterInstance;
  341. PIO_STACK_LOCATION pIrpStack;
  342. PDEVICE_NODE pDeviceNode;
  343. if (IsTopologyProperty(Request->Flags)) {
  344. Status = STATUS_INVALID_PARAMETER;
  345. goto exit;
  346. }
  347. pIrpStack = IoGetCurrentIrpStackLocation(Irp);
  348. pFilterInstance = (PFILTER_INSTANCE)pIrpStack->FileObject->FsContext;
  349. Assert(pFilterInstance);
  350. if(!pFilterInstance->IsChildInstance()) {
  351. DPF(5, "SetInstanceDevice: FAILED - open pin instances");
  352. Status = STATUS_INVALID_DEVICE_REQUEST;
  353. goto exit;
  354. }
  355. Status = GetDeviceByIndex(*(PULONG)Data, &pDeviceNode);
  356. if(NT_SUCCESS(Status)) {
  357. Status = pFilterInstance->SetDeviceNode(pDeviceNode);
  358. if(!NT_SUCCESS(Status)) {
  359. goto exit;
  360. }
  361. }
  362. exit:
  363. return(Status);
  364. }
  365. NTSTATUS
  366. SetInstanceInfo(
  367. IN PIRP Irp,
  368. IN PSYSAUDIO_INSTANCE_INFO pInstanceInfo,
  369. IN OUT PVOID Data
  370. )
  371. {
  372. NTSTATUS Status = STATUS_SUCCESS;
  373. PFILTER_INSTANCE pFilterInstance;
  374. PIO_STACK_LOCATION pIrpStack;
  375. PDEVICE_NODE pDeviceNode;
  376. if (IsTopologyProperty(pInstanceInfo->Property.Flags)) {
  377. Status = STATUS_INVALID_PARAMETER;
  378. goto exit;
  379. }
  380. pIrpStack = IoGetCurrentIrpStackLocation(Irp);
  381. pFilterInstance = (PFILTER_INSTANCE)pIrpStack->FileObject->FsContext;
  382. Assert(pFilterInstance);
  383. if(pInstanceInfo->Flags & ~SYSAUDIO_FLAGS_DONT_COMBINE_PINS) {
  384. Status = STATUS_INVALID_PARAMETER;
  385. goto exit;
  386. }
  387. if(!pFilterInstance->IsChildInstance()) {
  388. Trap();
  389. DPF(5, "SetInstanceInfo: FAILED - open pin instances");
  390. Status = STATUS_INVALID_DEVICE_REQUEST;
  391. goto exit;
  392. }
  393. Status = GetDeviceByIndex(pInstanceInfo->DeviceNumber, &pDeviceNode);
  394. if(!NT_SUCCESS(Status)) {
  395. goto exit;
  396. }
  397. Assert(pDeviceNode);
  398. pFilterInstance->ulFlags |= FLAGS_COMBINE_PINS;
  399. if(pInstanceInfo->Flags & SYSAUDIO_FLAGS_DONT_COMBINE_PINS) {
  400. pFilterInstance->ulFlags &= ~FLAGS_COMBINE_PINS;
  401. }
  402. Status = pFilterInstance->SetDeviceNode(pDeviceNode);
  403. if(!NT_SUCCESS(Status)) {
  404. goto exit;
  405. }
  406. exit:
  407. return(Status);
  408. }
  409. NTSTATUS
  410. SetDeviceDefault(
  411. IN PIRP pIrp,
  412. IN PKSPROPERTY pRequest,
  413. IN OUT PULONG pData
  414. )
  415. {
  416. NTSTATUS Status = STATUS_SUCCESS;
  417. PFILTER_INSTANCE pFilterInstance;
  418. PIO_STACK_LOCATION pIrpStack;
  419. if (IsTopologyProperty(pRequest->Flags)) {
  420. Status = STATUS_INVALID_PARAMETER;
  421. goto exit;
  422. }
  423. pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  424. pFilterInstance = (PFILTER_INSTANCE)pIrpStack->FileObject->FsContext;
  425. Assert(pFilterInstance);
  426. if(*pData >= MAX_SYSAUDIO_DEFAULT_TYPE) {
  427. Status = STATUS_INVALID_DEVICE_REQUEST;
  428. goto exit;
  429. }
  430. if(!pFilterInstance->IsChildInstance()) {
  431. Trap();
  432. DPF(5, "SetDeviceDefault: FAILED - open pin instances");
  433. Status = STATUS_INVALID_DEVICE_REQUEST;
  434. goto exit;
  435. }
  436. Status = pFilterInstance->SetShingleInstance(apShingleInstance[*pData]);
  437. if(!NT_SUCCESS(Status)) {
  438. goto exit;
  439. }
  440. exit:
  441. return(Status);
  442. }
  443. NTSTATUS
  444. GetDeviceInterfaceName(
  445. IN PIRP pIrp,
  446. IN PKSPROPERTY pRequest,
  447. IN OUT PVOID pData
  448. )
  449. {
  450. PIO_STACK_LOCATION pIrpStack;
  451. PFILTER_INSTANCE pFilterInstance;
  452. NTSTATUS Status = STATUS_SUCCESS;
  453. PDEVICE_NODE pDeviceNode;
  454. ULONG DeviceIndex = *(PULONG)(pRequest + 1);
  455. if (IsTopologyProperty(pRequest->Flags)) {
  456. Status = STATUS_INVALID_PARAMETER;
  457. goto exit;
  458. }
  459. pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  460. pFilterInstance = (PFILTER_INSTANCE)pIrpStack->FileObject->FsContext;
  461. Assert(pFilterInstance);
  462. Status = GetDeviceNodeFromDeviceIndex(
  463. pFilterInstance,
  464. DeviceIndex,
  465. &pDeviceNode);
  466. if (!NT_SUCCESS(Status)) {
  467. goto exit;
  468. }
  469. if(pDeviceNode->GetDeviceInterface() == NULL) {
  470. Status = STATUS_INVALID_DEVICE_REQUEST;
  471. goto exit;
  472. }
  473. Status = PropertyReturnString(
  474. pIrp,
  475. pDeviceNode->GetDeviceInterface(),
  476. (wcslen(pDeviceNode->GetDeviceInterface()) *
  477. sizeof(WCHAR)) + sizeof(UNICODE_NULL),
  478. pData);
  479. if(!NT_SUCCESS(Status)) {
  480. goto exit;
  481. }
  482. exit:
  483. return(Status);
  484. }
  485. NTSTATUS
  486. SelectGraph(
  487. IN PIRP pIrp,
  488. PSYSAUDIO_SELECT_GRAPH pSelectGraph,
  489. IN OUT PVOID pData
  490. )
  491. {
  492. PGRAPH_NODE_INSTANCE pGraphNodeInstance;
  493. PTOPOLOGY_NODE pTopologyNode2;
  494. PTOPOLOGY_NODE pTopologyNode;
  495. PSTART_NODE pStartNode;
  496. NTSTATUS Status;
  497. if (IsTopologyProperty(pSelectGraph->Property.Flags)) {
  498. Status = STATUS_INVALID_PARAMETER;
  499. goto exit2;
  500. }
  501. Status = ::GetGraphNodeInstance(pIrp, &pGraphNodeInstance);
  502. if(!NT_SUCCESS(Status)) {
  503. goto exit2;
  504. }
  505. Assert(pGraphNodeInstance);
  506. //
  507. // Parameter and state validation.
  508. //
  509. if(pGraphNodeInstance->palstTopologyNodeSelect == NULL ||
  510. pGraphNodeInstance->palstTopologyNodeNotSelect == NULL) {
  511. DPF(5, "SelectGraph: palstTopologyNodeSelect == NULL");
  512. Status = STATUS_INVALID_DEVICE_REQUEST;
  513. goto exit2;
  514. }
  515. if(pSelectGraph->Flags != 0 || pSelectGraph->Reserved != 0) {
  516. DPF(5, "SelectGraph: invalid flags or reserved field");
  517. Status = STATUS_INVALID_PARAMETER;
  518. goto exit2;
  519. }
  520. if(pSelectGraph->PinId >= pGraphNodeInstance->cPins) {
  521. DPF(5, "SelectGraph: invalid pin id");
  522. Status = STATUS_INVALID_PARAMETER;
  523. goto exit2;
  524. }
  525. if(pSelectGraph->NodeId >=
  526. pGraphNodeInstance->Topology.TopologyNodesCount) {
  527. DPF(5, "SelectGraph: invalid node id");
  528. Status = STATUS_INVALID_PARAMETER;
  529. goto exit2;
  530. }
  531. pTopologyNode = pGraphNodeInstance->papTopologyNode[pSelectGraph->NodeId];
  532. Assert(pTopologyNode);
  533. Assert(pGraphNodeInstance->pGraphNode);
  534. Assert(pGraphNodeInstance->pGraphNode->pDeviceNode);
  535. //
  536. // SECURITY NOTE:
  537. // SelectGraph is a very flexible property call that can change global
  538. // behavior.
  539. // Therefore we are limiting the usage explicitly for AecNodes.
  540. //
  541. if (!IsEqualGUID(pTopologyNode->pguidType, &KSNODETYPE_ACOUSTIC_ECHO_CANCEL) &&
  542. !IsEqualGUID(pTopologyNode->pguidType, &KSNODETYPE_NOISE_SUPPRESS) &&
  543. !IsEqualGUID(pTopologyNode->pguidType, &KSNODETYPE_AGC) &&
  544. !IsEqualGUID(pTopologyNode->pguidType, &KSNODETYPE_MICROPHONE_ARRAY) &&
  545. !IsEqualGUID(pTopologyNode->pguidType, &KSNODETYPE_MICROPHONE_ARRAY_PROCESSOR)) {
  546. DPF(5, "SelectGraph: None Aec node is selected");
  547. Status = STATUS_INVALID_PARAMETER;
  548. goto exit2;
  549. }
  550. DPF2(90, "SelectGraph GNI %08X TN %08X", pGraphNodeInstance, pTopologyNode);
  551. //
  552. // A global select type of filter needs to be inserted to all
  553. // instances.
  554. // So if the client is trying to insert a global_select node and if
  555. // there are graph instances that do not have the node, the request will
  556. // fail.
  557. //
  558. if(pTopologyNode->pFilterNode->GetType() & FILTER_TYPE_GLOBAL_SELECT &&
  559. pGraphNodeInstance->paPinDescriptors[pSelectGraph->PinId].DataFlow ==
  560. KSPIN_DATAFLOW_IN) {
  561. PSTART_NODE_INSTANCE pStartNodeInstance;
  562. PFILTER_INSTANCE pFilterInstance;
  563. FOR_EACH_LIST_ITEM(
  564. &pGraphNodeInstance->pGraphNode->pDeviceNode->lstFilterInstance,
  565. pFilterInstance) {
  566. if(pFilterInstance->pGraphNodeInstance == NULL) {
  567. continue;
  568. }
  569. Assert(pFilterInstance->pGraphNodeInstance);
  570. FOR_EACH_LIST_ITEM(
  571. &pFilterInstance->pGraphNodeInstance->lstStartNodeInstance,
  572. pStartNodeInstance) {
  573. if(EnumerateGraphTopology(
  574. pStartNodeInstance->pStartNode->GetStartInfo(),
  575. (TOP_PFN)FindTopologyNode,
  576. pTopologyNode) == STATUS_CONTINUE) {
  577. DPF2(5, "SelectGraph: TN %08x not found on SNI %08x",
  578. pTopologyNode,
  579. pStartNodeInstance);
  580. Status = STATUS_INVALID_DEVICE_REQUEST;
  581. goto exit;
  582. }
  583. } END_EACH_LIST_ITEM
  584. } END_EACH_LIST_ITEM
  585. Status = pGraphNodeInstance->
  586. lstTopologyNodeGlobalSelect.AddListDup(pTopologyNode);
  587. if(!NT_SUCCESS(Status)) {
  588. Trap();
  589. goto exit;
  590. }
  591. }
  592. else {
  593. Status = pGraphNodeInstance->
  594. palstTopologyNodeSelect[pSelectGraph->PinId].AddList(pTopologyNode);
  595. if(!NT_SUCCESS(Status)) {
  596. Trap();
  597. goto exit;
  598. }
  599. }
  600. //
  601. // If this is a "not select" type filter like AEC or Mic Array, then all
  602. // the nodes in the filter have to be remove from the not select list,
  603. // otherwise IsGraphValid will never find a valid graph.
  604. //
  605. if(pTopologyNode->pFilterNode->GetType() & FILTER_TYPE_NOT_SELECT) {
  606. FOR_EACH_LIST_ITEM(
  607. &pTopologyNode->pFilterNode->lstTopologyNode,
  608. pTopologyNode2) {
  609. pGraphNodeInstance->palstTopologyNodeNotSelect[
  610. pSelectGraph->PinId].RemoveList(pTopologyNode2);
  611. DPF2(50, " Removing %s NodeId %d",\
  612. pTopologyNode2->pFilterNode->DumpName(),
  613. pTopologyNode2->ulSysaudioNodeNumber);
  614. } END_EACH_LIST_ITEM
  615. }
  616. //
  617. // Validate that there is a valid path though the graph after updating
  618. // the various global, select and not select lists.
  619. //
  620. DPF(90, "SelectGraph: Validating Graph");
  621. FOR_EACH_LIST_ITEM(
  622. pGraphNodeInstance->aplstStartNode[pSelectGraph->PinId],
  623. pStartNode) {
  624. DPF2(90, " SN: %X %s",
  625. pStartNode,
  626. pStartNode->GetStartInfo()->GetPinInfo()->pFilterNode->DumpName());
  627. Assert(pStartNode);
  628. if(pGraphNodeInstance->IsGraphValid(
  629. pStartNode,
  630. pSelectGraph->PinId)) {
  631. Status = STATUS_SUCCESS;
  632. goto exit;
  633. }
  634. else {
  635. DPF(90, " IsGraphValid failed");
  636. }
  637. } END_EACH_LIST_ITEM
  638. //
  639. // The select graph failed so restore the not select list back to normal
  640. //
  641. if(pTopologyNode->pFilterNode->GetType() & FILTER_TYPE_NOT_SELECT) {
  642. FOR_EACH_LIST_ITEM(
  643. &pTopologyNode->pFilterNode->lstTopologyNode,
  644. pTopologyNode2) {
  645. pGraphNodeInstance->palstTopologyNodeNotSelect[
  646. pSelectGraph->PinId].AddList(pTopologyNode2);
  647. } END_EACH_LIST_ITEM
  648. }
  649. Status = STATUS_INVALID_DEVICE_REQUEST;
  650. exit:
  651. if(!NT_SUCCESS(Status)) {
  652. pGraphNodeInstance->
  653. palstTopologyNodeSelect[pSelectGraph->PinId].RemoveList(pTopologyNode);
  654. pGraphNodeInstance->
  655. lstTopologyNodeGlobalSelect.RemoveList(pTopologyNode);
  656. }
  657. exit2:
  658. return(Status);
  659. }
  660. //---------------------------------------------------------------------------
  661. NTSTATUS
  662. GetTopologyConnectionIndex(
  663. IN PIRP pIrp,
  664. IN PKSPROPERTY pProperty,
  665. OUT PULONG pulIndex
  666. )
  667. {
  668. PSTART_NODE_INSTANCE pStartNodeInstance;
  669. NTSTATUS Status = STATUS_SUCCESS;
  670. if (IsTopologyProperty(pProperty->Flags)) {
  671. Status = STATUS_INVALID_PARAMETER;
  672. goto exit;
  673. }
  674. Status = ::GetStartNodeInstance(pIrp, &pStartNodeInstance);
  675. if(!NT_SUCCESS(Status)) {
  676. Trap();
  677. goto exit;
  678. }
  679. Assert(pStartNodeInstance);
  680. Assert(pStartNodeInstance->pStartNode);
  681. Assert(pStartNodeInstance->pStartNode->GetStartInfo());
  682. *pulIndex = pStartNodeInstance->pStartNode->GetStartInfo()->
  683. ulTopologyConnectionTableIndex;
  684. pIrp->IoStatus.Information = sizeof(ULONG);
  685. exit:
  686. return(Status);
  687. }
  688. NTSTATUS
  689. GetPinVolumeNode(
  690. IN PIRP pIrp,
  691. IN PKSPROPERTY pProperty,
  692. OUT PULONG pulNode
  693. )
  694. {
  695. PIO_STACK_LOCATION pIrpStack;
  696. PPIN_INSTANCE pPinInstance;
  697. NTSTATUS Status;
  698. if (IsTopologyProperty(pProperty->Flags)) {
  699. Status = STATUS_INVALID_PARAMETER;
  700. goto exit;
  701. }
  702. pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  703. pPinInstance = (PPIN_INSTANCE)pIrpStack->FileObject->FsContext;
  704. Assert(pPinInstance);
  705. Status = GetVolumeNodeNumber(pPinInstance, NULL);
  706. if(!NT_SUCCESS(Status)) {
  707. Trap();
  708. goto exit;
  709. }
  710. if(pPinInstance->ulVolumeNodeNumber == MAXULONG) {
  711. DPF(5, "GetPinVolumeNode: no volume node found");
  712. Status = STATUS_INVALID_DEVICE_REQUEST;
  713. goto exit;
  714. }
  715. *pulNode = pPinInstance->ulVolumeNodeNumber;
  716. pIrp->IoStatus.Information = sizeof(ULONG);
  717. exit:
  718. return(Status);
  719. }
  720. NTSTATUS
  721. AddRemoveGfx(
  722. IN PIRP pIrp,
  723. IN PKSPROPERTY pProperty,
  724. IN PSYSAUDIO_GFX pSysaudioGfx
  725. )
  726. {
  727. NTSTATUS Status = STATUS_SUCCESS;
  728. PIO_STACK_LOCATION pIrpStack;
  729. ULONG cbMaxLength;
  730. if (IsTopologyProperty(pProperty->Flags))
  731. {
  732. return STATUS_INVALID_PARAMETER;
  733. }
  734. //
  735. // Make sure that this is bufferred IO.
  736. // The rest of this function assumes bufferred IO.
  737. //
  738. if (NULL == pIrp->AssociatedIrp.SystemBuffer)
  739. {
  740. DPF(5, "AddRemoveGFX: Only Bufferred IO");
  741. return STATUS_INVALID_PARAMETER;
  742. }
  743. //
  744. // Parameter validation for SYSAUDIO_GFX.
  745. //
  746. if (pSysaudioGfx->ulType != GFX_DEVICETYPE_RENDER &&
  747. pSysaudioGfx->ulType != GFX_DEVICETYPE_CAPTURE)
  748. {
  749. DPF(5, "AddRemoveGFX: Invalid GFX type");
  750. return STATUS_INVALID_PARAMETER;
  751. }
  752. //
  753. // Make sure that the offsets are within the range.
  754. //
  755. pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  756. cbMaxLength =
  757. pIrpStack->Parameters.DeviceIoControl.OutputBufferLength - sizeof(SYSAUDIO_GFX);
  758. if (pIrpStack->Parameters.DeviceIoControl.OutputBufferLength < pSysaudioGfx->ulDeviceNameOffset ||
  759. pIrpStack->Parameters.DeviceIoControl.OutputBufferLength < pSysaudioGfx->ulDeviceNameOffset)
  760. {
  761. DPF2(5, "AddRemoveGFX: Invalid NameOffset %d %d", pSysaudioGfx->ulDeviceNameOffset, pSysaudioGfx->ulDeviceNameOffset);
  762. return STATUS_INVALID_PARAMETER;
  763. }
  764. if(pSysaudioGfx->Enable)
  765. {
  766. Status = AddGfx(pSysaudioGfx, cbMaxLength);
  767. }
  768. else
  769. {
  770. Status = RemoveGfx(pSysaudioGfx, cbMaxLength);
  771. }
  772. return(Status);
  773. }