Source code of Windows XP (NT5)
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.

934 lines
27 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Module: pins.c
  4. //
  5. // Description:
  6. //
  7. //
  8. //@@BEGIN_MSINTERNAL
  9. // Development Team:
  10. // S.Mohanraj
  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. static const WCHAR AllocatorTypeName[] = KSSTRING_Allocator;
  30. static const WCHAR ClockTypeName[] = KSSTRING_Clock;
  31. DEFINE_KSCREATE_DISPATCH_TABLE(PinCreateItems)
  32. {
  33. DEFINE_KSCREATE_ITEM(AllocatorDispatchCreate, AllocatorTypeName, 0),
  34. DEFINE_KSCREATE_ITEM(CClockInstance::ClockDispatchCreate, ClockTypeName, 0),
  35. };
  36. DEFINE_KSDISPATCH_TABLE(
  37. PinDispatchTable,
  38. CPinInstance::PinDispatchIoControl, // Ioctl
  39. DispatchInvalidDeviceRequest, // Read
  40. CInstance::DispatchForwardIrp, // Write
  41. DispatchInvalidDeviceRequest, // Flush
  42. CPinInstance::PinDispatchClose, // Close
  43. DispatchInvalidDeviceRequest, // QuerySecurity
  44. DispatchInvalidDeviceRequest, // SetSeturity
  45. DispatchFastIoDeviceControlFailure, // FastDeviceIoControl
  46. DispatchFastReadFailure, // FastRead
  47. DispatchFastWriteFailure // FastWrite
  48. );
  49. DEFINE_KSPROPERTY_TABLE(SysaudioPinPropertyHandlers) {
  50. DEFINE_KSPROPERTY_ITEM(
  51. KSPROPERTY_SYSAUDIO_TOPOLOGY_CONNECTION_INDEX, // idProperty
  52. GetTopologyConnectionIndex, // pfnGetHandler
  53. sizeof(KSPROPERTY), // cbMinGetPropertyInput
  54. sizeof(ULONG), // cbMinGetDataInput
  55. NULL, // pfnSetHandler
  56. NULL, // Values
  57. 0, // RelationsCount
  58. NULL, // Relations
  59. NULL, // SupportHandler
  60. 0 // SerializedSize
  61. ),
  62. DEFINE_KSPROPERTY_ITEM(
  63. KSPROPERTY_SYSAUDIO_ATTACH_VIRTUAL_SOURCE, // idProperty
  64. NULL, // pfnGetHandler
  65. sizeof(SYSAUDIO_ATTACH_VIRTUAL_SOURCE), // cbMinGetPropertyInput
  66. 0, // cbMinGetDataInput
  67. AttachVirtualSource, // pfnSetHandler
  68. NULL, // Values
  69. 0, // RelationsCount
  70. NULL, // Relations
  71. NULL, // SupportHandler
  72. 0 // SerializedSize
  73. ),
  74. DEFINE_KSPROPERTY_ITEM(
  75. KSPROPERTY_SYSAUDIO_PIN_VOLUME_NODE, // idProperty
  76. GetPinVolumeNode, // pfnGetHandler
  77. sizeof(KSPROPERTY), // cbMinGetPropertyInput
  78. sizeof(ULONG), // cbMinGetDataInput
  79. NULL, // pfnSetHandler
  80. NULL, // Values
  81. 0, // RelationsCount
  82. NULL, // Relations
  83. NULL, // SupportHandler
  84. 0 // SerializedSize
  85. ),
  86. };
  87. DEFINE_KSPROPERTY_TABLE(PinConnectionHandlers) {
  88. DEFINE_KSPROPERTY_ITEM(
  89. KSPROPERTY_CONNECTION_STATE, // idProperty
  90. CPinInstance::PinStateHandler, // pfnGetHandler
  91. sizeof(KSPROPERTY), // cbMinGetPropertyInput
  92. sizeof(ULONG), // cbMinGetDataInput
  93. CPinInstance::PinStateHandler, // pfnSetHandler
  94. NULL, // Values
  95. 0, // RelationsCount
  96. NULL, // Relations
  97. NULL, // SupportHandler
  98. 0 // SerializedSize
  99. )
  100. };
  101. DEFINE_KSPROPERTY_TABLE (AudioPinPropertyHandlers)
  102. {
  103. DEFINE_KSPROPERTY_ITEM(
  104. KSPROPERTY_AUDIO_VOLUMELEVEL,
  105. PinVirtualPropertyHandler,
  106. sizeof(KSNODEPROPERTY_AUDIO_CHANNEL),
  107. sizeof(LONG),
  108. PinVirtualPropertyHandler,
  109. &PropertyValuesVolume,
  110. 0,
  111. NULL,
  112. (PFNKSHANDLER)PinVirtualPropertySupportHandler,
  113. 0
  114. )
  115. };
  116. DEFINE_KSPROPERTY_SET_TABLE(PinPropertySet)
  117. {
  118. DEFINE_KSPROPERTY_SET(
  119. &KSPROPSETID_Connection, // Set
  120. SIZEOF_ARRAY(PinConnectionHandlers), // PropertiesCount
  121. PinConnectionHandlers, // PropertyItem
  122. 0, // FastIoCount
  123. NULL // FastIoTable
  124. ),
  125. DEFINE_KSPROPERTY_SET(
  126. &KSPROPSETID_Sysaudio_Pin, // Set
  127. SIZEOF_ARRAY(SysaudioPinPropertyHandlers), // PropertiesCount
  128. SysaudioPinPropertyHandlers, // PropertyItem
  129. 0, // FastIoCount
  130. NULL // FastIoTable
  131. ),
  132. DEFINE_KSPROPERTY_SET(
  133. &KSPROPSETID_Audio, // Set
  134. SIZEOF_ARRAY(AudioPinPropertyHandlers), // PropertiesCount
  135. AudioPinPropertyHandlers, // PropertyItem
  136. 0, // FastIoCount
  137. NULL // FastIoTable
  138. )
  139. };
  140. //---------------------------------------------------------------------------
  141. //---------------------------------------------------------------------------
  142. CPinInstance::CPinInstance(
  143. IN PPARENT_INSTANCE pParentInstance
  144. ) : CInstance(pParentInstance)
  145. {
  146. }
  147. CPinInstance::~CPinInstance(
  148. )
  149. {
  150. PGRAPH_NODE_INSTANCE pGraphNodeInstance;
  151. Assert(this);
  152. Assert(pFilterInstance);
  153. DPF1(100, "~CPinInstance: %08x", this);
  154. if(pStartNodeInstance != NULL) {
  155. pGraphNodeInstance = pFilterInstance->pGraphNodeInstance;
  156. if(pGraphNodeInstance != NULL) {
  157. Assert(pGraphNodeInstance);
  158. ASSERT(PinId < pGraphNodeInstance->cPins);
  159. ASSERT(pGraphNodeInstance->pacPinInstances != NULL);
  160. ASSERT(pGraphNodeInstance->pacPinInstances[PinId].CurrentCount > 0);
  161. pGraphNodeInstance->pacPinInstances[PinId].CurrentCount--;
  162. }
  163. else {
  164. DPF2(10, "~CPinInstance PI %08x FI %08x no GNI",
  165. this,
  166. pFilterInstance);
  167. }
  168. pStartNodeInstance->Destroy();
  169. }
  170. else {
  171. DPF2(10, "~CPinInstance PI %08x FI %08x no SNI",
  172. this,
  173. pFilterInstance);
  174. }
  175. }
  176. NTSTATUS
  177. CPinInstance::PinDispatchCreate(
  178. IN PDEVICE_OBJECT pDeviceObject,
  179. IN PIRP pIrp
  180. )
  181. {
  182. PGRAPH_NODE_INSTANCE pGraphNodeInstance;
  183. PPIN_INSTANCE pPinInstance = NULL;
  184. PKSPIN_CONNECT pPinConnect = NULL;
  185. NTSTATUS Status;
  186. ::GrabMutex();
  187. Status = GetRelatedGraphNodeInstance(pIrp, &pGraphNodeInstance);
  188. if(!NT_SUCCESS(Status)) {
  189. goto exit;
  190. }
  191. Assert(pGraphNodeInstance);
  192. ASSERT(pGraphNodeInstance->pacPinInstances != NULL);
  193. ASSERT(pGraphNodeInstance->paPinDescriptors != NULL);
  194. //
  195. // Get the PinConnect structure from KS.
  196. // This function will copy creation parameters to pPinConnect.
  197. // Also do a basic connectibility testing by comparing KSDATAFORMAT of
  198. // pin descriptors and the request.
  199. //
  200. Status = KsValidateConnectRequest(
  201. pIrp,
  202. pGraphNodeInstance->cPins,
  203. pGraphNodeInstance->paPinDescriptors,
  204. &pPinConnect);
  205. if(!NT_SUCCESS(Status)) {
  206. #ifdef DEBUG
  207. DPF1(60, "PinDispatchCreate: KsValidateConnectReq FAILED %08x", Status);
  208. if(pPinConnect != NULL) {
  209. DumpPinConnect(60, pPinConnect);
  210. }
  211. #endif
  212. goto exit;
  213. }
  214. ASSERT(pPinConnect->PinId < pGraphNodeInstance->cPins);
  215. #ifdef DEBUG
  216. DPF(60, "PinDispatchCreate:");
  217. DumpPinConnect(60, pPinConnect);
  218. #endif
  219. // Check the pin instance count
  220. if(!pGraphNodeInstance->IsPinInstances(pPinConnect->PinId)) {
  221. DPF4(60, "PinDispatchCreate: not enough ins GNI %08x #%d C %d P %d",
  222. pGraphNodeInstance,
  223. pPinConnect->PinId,
  224. pGraphNodeInstance->pacPinInstances[pPinConnect->PinId].CurrentCount,
  225. pGraphNodeInstance->pacPinInstances[pPinConnect->PinId].PossibleCount);
  226. Status = STATUS_DEVICE_BUSY;
  227. goto exit;
  228. }
  229. // Allocate per pin instance data
  230. pPinInstance = new PIN_INSTANCE(
  231. &pGraphNodeInstance->pFilterInstance->ParentInstance);
  232. if(pPinInstance == NULL) {
  233. Status = STATUS_INSUFFICIENT_RESOURCES;
  234. goto exit;
  235. }
  236. // Setup the pin's instance data
  237. pPinInstance->ulVolumeNodeNumber = MAXULONG;
  238. pPinInstance->pFilterInstance = pGraphNodeInstance->pFilterInstance;
  239. pPinInstance->PinId = pPinConnect->PinId;
  240. Status = pPinInstance->DispatchCreate(
  241. pIrp,
  242. (UTIL_PFN)PinDispatchCreateKP,
  243. pPinConnect,
  244. SIZEOF_ARRAY(PinCreateItems),
  245. PinCreateItems,
  246. &PinDispatchTable);
  247. pPinConnect->PinId = pPinInstance->PinId;
  248. if(!NT_SUCCESS(Status)) {
  249. #ifdef DEBUG
  250. DPF1(60, "PinDispatchCreate: FAILED: %08x ", Status);
  251. DumpPinConnect(60, pPinConnect);
  252. #endif
  253. goto exit;
  254. }
  255. // Increment the reference count on this pin
  256. ASSERT(pPinInstance->pStartNodeInstance != NULL);
  257. ASSERT(pGraphNodeInstance->pacPinInstances != NULL);
  258. pGraphNodeInstance->pacPinInstances[pPinInstance->PinId].CurrentCount++;
  259. exit:
  260. if(!NT_SUCCESS(Status)) {
  261. delete pPinInstance;
  262. }
  263. ::ReleaseMutex();
  264. pIrp->IoStatus.Status = Status;
  265. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  266. return Status;
  267. }
  268. NTSTATUS
  269. CPinInstance::PinDispatchCreateKP(
  270. PPIN_INSTANCE pPinInstance,
  271. PKSPIN_CONNECT pPinConnect
  272. )
  273. {
  274. PWAVEFORMATEX pWaveFormatExRequested = NULL;
  275. PFILTER_INSTANCE pFilterInstance;
  276. PSTART_NODE pStartNode;
  277. NTSTATUS Status;
  278. Assert(pPinInstance);
  279. pFilterInstance = pPinInstance->pFilterInstance;
  280. Assert(pFilterInstance);
  281. ASSERT(pPinInstance->PinId < pFilterInstance->pGraphNodeInstance->cPins);
  282. ASSERT(pPinConnect->PinId < pFilterInstance->pGraphNodeInstance->cPins);
  283. if(IsEqualGUID(
  284. &PKSDATAFORMAT(pPinConnect + 1)->Specifier,
  285. &KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)) {
  286. pWaveFormatExRequested =
  287. &PKSDATAFORMAT_WAVEFORMATEX(pPinConnect + 1)->WaveFormatEx;
  288. }
  289. else if(IsEqualGUID(
  290. &PKSDATAFORMAT(pPinConnect + 1)->Specifier,
  291. &KSDATAFORMAT_SPECIFIER_DSOUND)) {
  292. pWaveFormatExRequested =
  293. &PKSDATAFORMAT_DSOUND(pPinConnect + 1)->BufferDesc.WaveFormatEx;
  294. }
  295. if(pWaveFormatExRequested != NULL) {
  296. // Fix SampleSize if zero
  297. if(PKSDATAFORMAT(pPinConnect + 1)->SampleSize == 0) {
  298. PKSDATAFORMAT(pPinConnect + 1)->SampleSize =
  299. pWaveFormatExRequested->nBlockAlign;
  300. }
  301. }
  302. //
  303. // Try each start node until success
  304. //
  305. Status = STATUS_INVALID_DEVICE_REQUEST;
  306. //
  307. // First loop through all the start nodes which are not marked SECONDPASS
  308. // and try to create a StartNodeInstance
  309. //
  310. FOR_EACH_LIST_ITEM(
  311. pFilterInstance->pGraphNodeInstance->aplstStartNode[pPinInstance->PinId],
  312. pStartNode) {
  313. Assert(pStartNode);
  314. Assert(pFilterInstance);
  315. if(pStartNode->ulFlags & STARTNODE_FLAGS_SECONDPASS) {
  316. continue;
  317. }
  318. if(pFilterInstance->pGraphNodeInstance->IsGraphValid(
  319. pStartNode,
  320. pPinInstance->PinId)) {
  321. Status = CStartNodeInstance::Create(
  322. pPinInstance,
  323. pStartNode,
  324. pPinConnect,
  325. pWaveFormatExRequested,
  326. NULL);
  327. if(NT_SUCCESS(Status)) {
  328. break;
  329. }
  330. }
  331. } END_EACH_LIST_ITEM
  332. if(!NT_SUCCESS(Status)) {
  333. //
  334. // If first pass failed to create an instance try all the second pass
  335. // StartNodes in the list. This is being done for creating paths with no GFX
  336. // because we created a path with AEC and no GFX earlier.
  337. //
  338. FOR_EACH_LIST_ITEM(
  339. pFilterInstance->pGraphNodeInstance->aplstStartNode[pPinInstance->PinId],
  340. pStartNode) {
  341. Assert(pStartNode);
  342. Assert(pFilterInstance);
  343. if((pStartNode->ulFlags & STARTNODE_FLAGS_SECONDPASS) == 0) {
  344. continue;
  345. }
  346. if(pFilterInstance->pGraphNodeInstance->IsGraphValid(
  347. pStartNode,
  348. pPinInstance->PinId)) {
  349. Status = CStartNodeInstance::Create(
  350. pPinInstance,
  351. pStartNode,
  352. pPinConnect,
  353. pWaveFormatExRequested,
  354. NULL);
  355. if(NT_SUCCESS(Status)) {
  356. break;
  357. }
  358. }
  359. } END_EACH_LIST_ITEM
  360. if(!NT_SUCCESS(Status)) {
  361. goto exit;
  362. }
  363. }
  364. Status = pPinInstance->SetNextFileObject(
  365. pPinInstance->pStartNodeInstance->pPinNodeInstance->hPin);
  366. if(!NT_SUCCESS(Status)) {
  367. Trap();
  368. goto exit;
  369. }
  370. exit:
  371. return(Status);
  372. }
  373. NTSTATUS
  374. CPinInstance::PinDispatchClose(
  375. IN PDEVICE_OBJECT pDeviceObject,
  376. IN PIRP pIrp
  377. )
  378. {
  379. PIO_STACK_LOCATION pIrpStack;
  380. PPIN_INSTANCE pPinInstance;
  381. ::GrabMutex();
  382. pIrpStack = IoGetCurrentIrpStackLocation( pIrp );
  383. pPinInstance = (PPIN_INSTANCE)pIrpStack->FileObject->FsContext;
  384. Assert(pPinInstance);
  385. pIrpStack->FileObject->FsContext = NULL;
  386. delete pPinInstance;
  387. ::ReleaseMutex();
  388. pIrp->IoStatus.Status = STATUS_SUCCESS;
  389. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  390. return STATUS_SUCCESS;
  391. }
  392. NTSTATUS
  393. CPinInstance::PinDispatchIoControl(
  394. IN PDEVICE_OBJECT pDeviceObject,
  395. IN PIRP pIrp
  396. )
  397. {
  398. NTSTATUS Status = STATUS_INVALID_DEVICE_REQUEST;
  399. PSTART_NODE_INSTANCE pStartNodeInstance;
  400. PIO_STACK_LOCATION pIrpStack;
  401. PKSPROPERTY pProperty = NULL;
  402. PPIN_INSTANCE pPinInstance;
  403. BOOL fProperty = FALSE;
  404. ULONG ulFlags = 0;
  405. #ifdef DEBUG
  406. DumpIoctl(pIrp, "Pin");
  407. #endif
  408. pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  409. switch(pIrpStack->Parameters.DeviceIoControl.IoControlCode) {
  410. case IOCTL_KS_PROPERTY:
  411. fProperty = TRUE;
  412. break;
  413. case IOCTL_KS_ENABLE_EVENT:
  414. case IOCTL_KS_DISABLE_EVENT:
  415. case IOCTL_KS_METHOD:
  416. break;
  417. default:
  418. return(DispatchForwardIrp(pDeviceObject, pIrp));
  419. }
  420. ::GrabMutex();
  421. pPinInstance = (PPIN_INSTANCE)pIrpStack->FileObject->FsContext;
  422. Status = pPinInstance->GetStartNodeInstance(&pStartNodeInstance);
  423. if(!NT_SUCCESS(Status)) {
  424. goto exit;
  425. }
  426. Assert(pPinInstance->pFilterInstance);
  427. Assert(pPinInstance->pFilterInstance->pGraphNodeInstance);
  428. if(pIrpStack->Parameters.DeviceIoControl.InputBufferLength >=
  429. sizeof(KSPROPERTY)) {
  430. __try {
  431. if(pIrp->AssociatedIrp.SystemBuffer == NULL) {
  432. pProperty = (PKSPROPERTY)
  433. (pIrpStack->Parameters.DeviceIoControl.Type3InputBuffer);
  434. // Validate the pointers if the client is not trusted.
  435. if(pIrp->RequestorMode != KernelMode) {
  436. ProbeForWrite(
  437. pProperty,
  438. pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
  439. sizeof(BYTE));
  440. }
  441. }
  442. else {
  443. pProperty =
  444. (PKSPROPERTY)((PUCHAR)pIrp->AssociatedIrp.SystemBuffer +
  445. ((pIrpStack->Parameters.DeviceIoControl.OutputBufferLength +
  446. FILE_QUAD_ALIGNMENT) & ~FILE_QUAD_ALIGNMENT));
  447. }
  448. ulFlags = pProperty->Flags;
  449. }
  450. __except (EXCEPTION_EXECUTE_HANDLER) {
  451. Trap();
  452. Status = GetExceptionCode();
  453. DPF1(5, "PinDispatchIoControl: Exception %08x", Status);
  454. goto exit;
  455. }
  456. //
  457. // This check allows the actual node or filter return the set's
  458. // supported, etc. instead of always return only the sets sysaudio
  459. // supports.
  460. //
  461. if(ulFlags & KSPROPERTY_TYPE_TOPOLOGY) {
  462. if(fProperty) {
  463. if((ulFlags & (KSPROPERTY_TYPE_GET |
  464. KSPROPERTY_TYPE_SET |
  465. KSPROPERTY_TYPE_BASICSUPPORT)) == 0) {
  466. // NOTE: ForwardIrpNode releases gMutex
  467. return(ForwardIrpNode(
  468. pIrp,
  469. pProperty,
  470. pPinInstance->pFilterInstance,
  471. pPinInstance));
  472. }
  473. }
  474. else {
  475. // NOTE: ForwardIrpNode releases gMutex
  476. return(ForwardIrpNode(
  477. pIrp,
  478. pProperty,
  479. pPinInstance->pFilterInstance,
  480. pPinInstance));
  481. }
  482. }
  483. }
  484. switch(pIrpStack->Parameters.DeviceIoControl.IoControlCode) {
  485. case IOCTL_KS_PROPERTY:
  486. Status = KsPropertyHandler(
  487. pIrp,
  488. SIZEOF_ARRAY(PinPropertySet),
  489. (PKSPROPERTY_SET)PinPropertySet);
  490. if(Status != STATUS_NOT_FOUND &&
  491. Status != STATUS_PROPSET_NOT_FOUND) {
  492. break;
  493. }
  494. // Fall through if property not found
  495. case IOCTL_KS_ENABLE_EVENT:
  496. case IOCTL_KS_DISABLE_EVENT:
  497. case IOCTL_KS_METHOD:
  498. // NOTE: ForwardIrpNode releases gMutex
  499. return(ForwardIrpNode(
  500. pIrp,
  501. NULL,
  502. pPinInstance->pFilterInstance,
  503. pPinInstance));
  504. default:
  505. ASSERT(FALSE); // Can't happen because of above switch
  506. }
  507. exit:
  508. ::ReleaseMutex();
  509. pIrp->IoStatus.Status = Status;
  510. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  511. return(Status);
  512. }
  513. NTSTATUS
  514. CPinInstance::PinStateHandler
  515. (
  516. IN PIRP pIrp,
  517. IN PKSPROPERTY pProperty,
  518. IN OUT PKSSTATE pState
  519. )
  520. {
  521. PSTART_NODE_INSTANCE pStartNodeInstance;
  522. NTSTATUS Status = STATUS_SUCCESS;
  523. #ifdef DEBUG
  524. extern PSZ apszStates[];
  525. #endif
  526. Status = ::GetStartNodeInstance(pIrp, &pStartNodeInstance);
  527. if(!NT_SUCCESS(Status)) {
  528. Trap();
  529. goto exit;
  530. }
  531. if(pProperty->Flags & KSPROPERTY_TYPE_GET) {
  532. *pState = pStartNodeInstance->CurrentState;
  533. pIrp->IoStatus.Information = sizeof(KSSTATE);
  534. if(*pState == KSSTATE_PAUSE) {
  535. if(pStartNodeInstance->pPinNodeInstance->
  536. pPinNode->pPinInfo->DataFlow == KSPIN_DATAFLOW_OUT) {
  537. Status = STATUS_NO_DATA_DETECTED;
  538. }
  539. }
  540. }
  541. else {
  542. ASSERT(pProperty->Flags & KSPROPERTY_TYPE_SET);
  543. DPF3(90, "PinStateHandler from %s to %s - SNI: %08x",
  544. apszStates[pStartNodeInstance->CurrentState],
  545. apszStates[*pState],
  546. pStartNodeInstance);
  547. Status = pStartNodeInstance->SetState(*pState, 0);
  548. if(!NT_SUCCESS(Status)) {
  549. DPF1(90, "PinStateHandler FAILED: %08x", Status);
  550. goto exit;
  551. }
  552. }
  553. exit:
  554. return(Status);
  555. }
  556. NTSTATUS
  557. GetRelatedStartNodeInstance(
  558. IN PIRP pIrp,
  559. OUT PSTART_NODE_INSTANCE *ppStartNodeInstance
  560. )
  561. {
  562. return(((PPIN_INSTANCE)IoGetCurrentIrpStackLocation(pIrp)->FileObject->
  563. RelatedFileObject->FsContext)->GetStartNodeInstance(ppStartNodeInstance));
  564. }
  565. NTSTATUS
  566. GetStartNodeInstance(
  567. IN PIRP pIrp,
  568. OUT PSTART_NODE_INSTANCE *ppStartNodeInstance
  569. )
  570. {
  571. return(((PPIN_INSTANCE)IoGetCurrentIrpStackLocation(pIrp)->FileObject->
  572. FsContext)->GetStartNodeInstance(ppStartNodeInstance));
  573. }
  574. NTSTATUS
  575. CPinInstance::GetStartNodeInstance(
  576. OUT PSTART_NODE_INSTANCE *ppStartNodeInstance
  577. )
  578. {
  579. NTSTATUS Status = STATUS_SUCCESS;
  580. if(this == NULL || pStartNodeInstance == NULL) {
  581. DPF(60, "GetStartNodeInstance: pStartNodeInstance == NULL");
  582. Status = STATUS_NO_SUCH_DEVICE;
  583. goto exit;
  584. }
  585. Assert(this);
  586. *ppStartNodeInstance = pStartNodeInstance;
  587. exit:
  588. return(Status);
  589. }
  590. #pragma LOCKED_CODE
  591. #pragma LOCKED_DATA
  592. // NOTE: ForwardIrpNode releases gMutex
  593. NTSTATUS
  594. ForwardIrpNode(
  595. IN PIRP pIrp,
  596. IN OPTIONAL PKSPROPERTY pProperty, // already validated or NULL
  597. IN PFILTER_INSTANCE pFilterInstance,
  598. IN OPTIONAL PPIN_INSTANCE pPinInstance
  599. )
  600. {
  601. PGRAPH_NODE_INSTANCE pGraphNodeInstance;
  602. PFILE_OBJECT pFileObject = NULL;
  603. PIO_STACK_LOCATION pIrpStack;
  604. PKSEVENTDATA pEventData;
  605. ULONG OriginalNodeId;
  606. NTSTATUS Status;
  607. Assert(pFilterInstance);
  608. pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  609. Status = pFilterInstance->GetGraphNodeInstance(&pGraphNodeInstance);
  610. if(!NT_SUCCESS(Status)) {
  611. goto exit;
  612. }
  613. Assert(pGraphNodeInstance);
  614. if(pPinInstance != NULL) {
  615. pFileObject = pPinInstance->GetNextFileObject();
  616. }
  617. __try {
  618. if(pIrpStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(KSNODEPROPERTY) &&
  619. pIrpStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_DISABLE_EVENT) {
  620. if(pProperty == NULL) {
  621. if(pIrp->AssociatedIrp.SystemBuffer == NULL) {
  622. Trap();
  623. pProperty = (PKSPROPERTY)
  624. (pIrpStack->Parameters.DeviceIoControl.Type3InputBuffer);
  625. // Validate the pointers if the client is not trusted.
  626. if(pIrp->RequestorMode != KernelMode) {
  627. ProbeForWrite(
  628. pProperty,
  629. pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
  630. sizeof(BYTE));
  631. }
  632. }
  633. else {
  634. pProperty = (PKSPROPERTY)
  635. ((PUCHAR)pIrp->AssociatedIrp.SystemBuffer +
  636. ((pIrpStack->Parameters.DeviceIoControl.OutputBufferLength +
  637. FILE_QUAD_ALIGNMENT) & ~FILE_QUAD_ALIGNMENT));
  638. }
  639. }
  640. ASSERT(!IsEqualGUID(&pProperty->Set, &KSPROPSETID_Sysaudio));
  641. ASSERT(!IsEqualGUID(&pProperty->Set, &KSEVENTSETID_Sysaudio));
  642. if(pProperty->Flags & KSPROPERTY_TYPE_TOPOLOGY) {
  643. OriginalNodeId = ((PKSNODEPROPERTY)pProperty)->NodeId;
  644. if(pPinInstance == NULL) {
  645. Status = pGraphNodeInstance->
  646. GetTopologyNodeFileObject(
  647. &pFileObject,
  648. OriginalNodeId);
  649. }
  650. else {
  651. Status = pPinInstance->pStartNodeInstance->
  652. GetTopologyNodeFileObject(
  653. &pFileObject,
  654. OriginalNodeId);
  655. }
  656. if(!NT_SUCCESS(Status)) {
  657. DPF1(100,
  658. "ForwardIrpNode: GetTopologyNodeFileObject FAILED %08x",
  659. Status);
  660. goto exit;
  661. }
  662. // Put real node number in input buffer
  663. ((PKSNODEPROPERTY)pProperty)->NodeId = pGraphNodeInstance->
  664. papTopologyNode[OriginalNodeId]->ulRealNodeNumber;
  665. }
  666. }
  667. else {
  668. //
  669. // If it is DisableEvent && if it is of type DPC. We look into the
  670. // Reserved field of KSEVENTDATA to extract the original node on
  671. // which the event was enabled (The high bit is set if we ever
  672. // stashed a NodeId in there).
  673. //
  674. if(pIrpStack->Parameters.DeviceIoControl.IoControlCode ==
  675. IOCTL_KS_DISABLE_EVENT) {
  676. if(pIrpStack->Parameters.DeviceIoControl.InputBufferLength >=
  677. sizeof(KSEVENTDATA)) {
  678. pEventData = (PKSEVENTDATA)
  679. pIrpStack->Parameters.DeviceIoControl.Type3InputBuffer;
  680. if(pIrp->RequestorMode != KernelMode) {
  681. ProbeForWrite(
  682. pEventData,
  683. pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
  684. sizeof (BYTE));
  685. }
  686. OriginalNodeId = ULONG(pEventData->Dpc.Reserved);
  687. if((pEventData->NotificationType == KSEVENTF_DPC) &&
  688. (OriginalNodeId & 0x80000000)) {
  689. OriginalNodeId = OriginalNodeId & 0x7fffffff;
  690. if(pPinInstance == NULL) {
  691. Status = pGraphNodeInstance->
  692. GetTopologyNodeFileObject(
  693. &pFileObject,
  694. OriginalNodeId);
  695. }
  696. else {
  697. Status = pPinInstance->pStartNodeInstance->
  698. GetTopologyNodeFileObject(
  699. &pFileObject,
  700. OriginalNodeId);
  701. }
  702. if(!NT_SUCCESS(Status)) {
  703. DPF1(100,
  704. "ForwardIrpNode: GetTopologyNodeFileObject FAILED %08x",
  705. Status);
  706. goto exit;
  707. }
  708. }
  709. }
  710. }
  711. }
  712. } __except (EXCEPTION_EXECUTE_HANDLER) {
  713. Trap();
  714. Status = GetExceptionCode();
  715. DPF1(5, "ForwardIrpNode: Exception %08x", Status);
  716. goto exit;
  717. }
  718. if(pFileObject == NULL) {
  719. Status = STATUS_NOT_FOUND;
  720. DPF1(100, "ForwardIrpNode: Property not forwarded: %08x", pProperty);
  721. goto exit;
  722. }
  723. pIrpStack->FileObject = pFileObject;
  724. //
  725. // If it was EnableEvent we stash away pointer to KSEVENTDATA, so that we
  726. // can stash the NodeID into it after we call the next driver on the stack
  727. //
  728. KPROCESSOR_MODE RequestorMode;
  729. if((pProperty != NULL) &&
  730. (pIrpStack->Parameters.DeviceIoControl.IoControlCode ==
  731. IOCTL_KS_ENABLE_EVENT) &&
  732. !(pProperty->Flags & KSEVENT_TYPE_BASICSUPPORT) &&
  733. (pProperty->Flags & KSPROPERTY_TYPE_TOPOLOGY) &&
  734. (pProperty->Flags & KSEVENT_TYPE_ENABLE)) {
  735. pEventData = (PKSEVENTDATA) pIrp->UserBuffer;
  736. RequestorMode = pIrp->RequestorMode;
  737. }
  738. else {
  739. pEventData = NULL;
  740. }
  741. IoSkipCurrentIrpStackLocation(pIrp);
  742. AssertFileObject(pIrpStack->FileObject);
  743. Status = IoCallDriver(IoGetRelatedDeviceObject(pFileObject), pIrp);
  744. //
  745. // Stash away the Node id in EventData
  746. //
  747. __try {
  748. if (pEventData != NULL) {
  749. if (RequestorMode == UserMode) {
  750. ProbeForWrite(pEventData, sizeof(KSEVENTDATA), sizeof(BYTE));
  751. }
  752. if (pEventData->NotificationType == KSEVENTF_DPC) {
  753. pEventData->Dpc.Reserved = OriginalNodeId | 0x80000000;
  754. }
  755. }
  756. } __except (EXCEPTION_EXECUTE_HANDLER) {
  757. Trap();
  758. Status = GetExceptionCode();
  759. DPF1(5, "ForwardIrpNode: Exception %08x", Status);
  760. }
  761. if(!NT_SUCCESS(Status)) {
  762. DPF1(100, "ForwardIrpNode: Status %08x", Status);
  763. }
  764. ::ReleaseMutex();
  765. return(Status);
  766. exit:
  767. ::ReleaseMutex();
  768. pIrp->IoStatus.Status = Status;
  769. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  770. return(Status);
  771. }
  772. //---------------------------------------------------------------------------
  773. #ifdef DEBUG
  774. extern PSZ apszStates[];
  775. ENUMFUNC
  776. CPinInstance::Dump(
  777. )
  778. {
  779. Assert(this);
  780. // .siv
  781. if(ulDebugFlags & (DEBUG_FLAGS_VERBOSE | DEBUG_FLAGS_OBJECT)) {
  782. dprintf("PI: %08x FI %08x SNI %08x ulVNN %08x PinId %d\n",
  783. this,
  784. pFilterInstance,
  785. pStartNodeInstance,
  786. ulVolumeNodeNumber,
  787. PinId);
  788. CInstance::Dump();
  789. ParentInstance.Dump();
  790. }
  791. else {
  792. dprintf(" Fr: Sysaudio\n PinId: %d\n", PinId);
  793. }
  794. if(ulDebugFlags & DEBUG_FLAGS_INSTANCE) {
  795. if(pStartNodeInstance != NULL) {
  796. pStartNodeInstance->Dump();
  797. }
  798. }
  799. return(STATUS_CONTINUE);
  800. }
  801. ENUMFUNC
  802. CPinInstance::DumpAddress(
  803. )
  804. {
  805. if(this != NULL) {
  806. Assert(this);
  807. dprintf(" %08x", this);
  808. }
  809. return(STATUS_CONTINUE);
  810. }
  811. #endif
  812. //---------------------------------------------------------------------------
  813. // End of File: pins.c
  814. //---------------------------------------------------------------------------