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.

1224 lines
35 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. DEFINE_KSDISPATCH_TABLE(
  30. PinDispatchTable,
  31. CPinInstance::PinDispatchIoControl, // Ioctl
  32. CInstance::DispatchForwardIrp, // Read
  33. CInstance::DispatchForwardIrp, // Write
  34. DispatchInvalidDeviceRequest, // Flush
  35. CPinInstance::PinDispatchClose, // Close
  36. DispatchInvalidDeviceRequest, // QuerySecurity
  37. DispatchInvalidDeviceRequest, // SetSeturity
  38. DispatchFastIoDeviceControlFailure, // FastDeviceIoControl
  39. DispatchFastReadFailure, // FastRead
  40. DispatchFastWriteFailure // FastWrite
  41. );
  42. DEFINE_KSPROPERTY_TABLE(SysaudioPinPropertyHandlers) {
  43. DEFINE_KSPROPERTY_ITEM(
  44. KSPROPERTY_SYSAUDIO_TOPOLOGY_CONNECTION_INDEX, // idProperty
  45. GetTopologyConnectionIndex, // pfnGetHandler
  46. sizeof(KSPROPERTY), // cbMinGetPropertyInput
  47. sizeof(ULONG), // cbMinGetDataInput
  48. NULL, // pfnSetHandler
  49. NULL, // Values
  50. 0, // RelationsCount
  51. NULL, // Relations
  52. NULL, // SupportHandler
  53. 0 // SerializedSize
  54. ),
  55. DEFINE_KSPROPERTY_ITEM(
  56. KSPROPERTY_SYSAUDIO_ATTACH_VIRTUAL_SOURCE, // idProperty
  57. NULL, // pfnGetHandler
  58. sizeof(SYSAUDIO_ATTACH_VIRTUAL_SOURCE), // cbMinGetPropertyInput
  59. 0, // cbMinGetDataInput
  60. AttachVirtualSource, // pfnSetHandler
  61. NULL, // Values
  62. 0, // RelationsCount
  63. NULL, // Relations
  64. NULL, // SupportHandler
  65. 0 // SerializedSize
  66. ),
  67. DEFINE_KSPROPERTY_ITEM(
  68. KSPROPERTY_SYSAUDIO_PIN_VOLUME_NODE, // idProperty
  69. GetPinVolumeNode, // pfnGetHandler
  70. sizeof(KSPROPERTY), // cbMinGetPropertyInput
  71. sizeof(ULONG), // cbMinGetDataInput
  72. NULL, // pfnSetHandler
  73. NULL, // Values
  74. 0, // RelationsCount
  75. NULL, // Relations
  76. NULL, // SupportHandler
  77. 0 // SerializedSize
  78. ),
  79. };
  80. DEFINE_KSPROPERTY_TABLE(PinConnectionHandlers) {
  81. DEFINE_KSPROPERTY_ITEM(
  82. KSPROPERTY_CONNECTION_STATE, // idProperty
  83. CPinInstance::PinStateHandler, // pfnGetHandler
  84. sizeof(KSPROPERTY), // cbMinGetPropertyInput
  85. sizeof(ULONG), // cbMinGetDataInput
  86. CPinInstance::PinStateHandler, // pfnSetHandler
  87. NULL, // Values
  88. 0, // RelationsCount
  89. NULL, // Relations
  90. NULL, // SupportHandler
  91. 0 // SerializedSize
  92. )
  93. };
  94. DEFINE_KSPROPERTY_TABLE (AudioPinPropertyHandlers)
  95. {
  96. DEFINE_KSPROPERTY_ITEM(
  97. KSPROPERTY_AUDIO_VOLUMELEVEL,
  98. PinVirtualPropertyHandler,
  99. sizeof(KSNODEPROPERTY_AUDIO_CHANNEL),
  100. sizeof(LONG),
  101. PinVirtualPropertyHandler,
  102. &PropertyValuesVolume,
  103. 0,
  104. NULL,
  105. (PFNKSHANDLER)PinVirtualPropertySupportHandler,
  106. 0
  107. )
  108. };
  109. DEFINE_KSPROPERTY_SET_TABLE(PinPropertySet)
  110. {
  111. DEFINE_KSPROPERTY_SET(
  112. &KSPROPSETID_Connection, // Set
  113. SIZEOF_ARRAY(PinConnectionHandlers), // PropertiesCount
  114. PinConnectionHandlers, // PropertyItem
  115. 0, // FastIoCount
  116. NULL // FastIoTable
  117. ),
  118. DEFINE_KSPROPERTY_SET(
  119. &KSPROPSETID_Sysaudio_Pin, // Set
  120. SIZEOF_ARRAY(SysaudioPinPropertyHandlers), // PropertiesCount
  121. SysaudioPinPropertyHandlers, // PropertyItem
  122. 0, // FastIoCount
  123. NULL // FastIoTable
  124. ),
  125. DEFINE_KSPROPERTY_SET(
  126. &KSPROPSETID_Audio, // Set
  127. SIZEOF_ARRAY(AudioPinPropertyHandlers), // PropertiesCount
  128. AudioPinPropertyHandlers, // PropertyItem
  129. 0, // FastIoCount
  130. NULL // FastIoTable
  131. )
  132. };
  133. //---------------------------------------------------------------------------
  134. //---------------------------------------------------------------------------
  135. CPinInstance::CPinInstance(
  136. IN PPARENT_INSTANCE pParentInstance
  137. ) : CInstance(pParentInstance)
  138. {
  139. }
  140. CPinInstance::~CPinInstance(
  141. )
  142. {
  143. PGRAPH_NODE_INSTANCE pGraphNodeInstance;
  144. Assert(this);
  145. Assert(pFilterInstance);
  146. DPF1(100, "~CPinInstance: %08x", this);
  147. if(pStartNodeInstance != NULL) {
  148. pGraphNodeInstance = pFilterInstance->pGraphNodeInstance;
  149. if(pGraphNodeInstance != NULL) {
  150. Assert(pGraphNodeInstance);
  151. ASSERT(PinId < pGraphNodeInstance->cPins);
  152. ASSERT(pGraphNodeInstance->pacPinInstances != NULL);
  153. ASSERT(pGraphNodeInstance->pacPinInstances[PinId].CurrentCount > 0);
  154. pGraphNodeInstance->pacPinInstances[PinId].CurrentCount--;
  155. }
  156. else {
  157. DPF2(10, "~CPinInstance PI %08x FI %08x no GNI",
  158. this,
  159. pFilterInstance);
  160. }
  161. pStartNodeInstance->Destroy();
  162. }
  163. else {
  164. DPF2(10, "~CPinInstance PI %08x FI %08x no SNI",
  165. this,
  166. pFilterInstance);
  167. }
  168. }
  169. NTSTATUS
  170. CPinInstance::PinDispatchCreate(
  171. IN PDEVICE_OBJECT pDeviceObject,
  172. IN PIRP pIrp
  173. )
  174. {
  175. PGRAPH_NODE_INSTANCE pGraphNodeInstance;
  176. PPIN_INSTANCE pPinInstance = NULL;
  177. PKSPIN_CONNECT pPinConnect = NULL;
  178. NTSTATUS Status;
  179. ::GrabMutex();
  180. Status = GetRelatedGraphNodeInstance(pIrp, &pGraphNodeInstance);
  181. if(!NT_SUCCESS(Status)) {
  182. goto exit;
  183. }
  184. Assert(pGraphNodeInstance);
  185. ASSERT(pGraphNodeInstance->pacPinInstances != NULL);
  186. ASSERT(pGraphNodeInstance->paPinDescriptors != NULL);
  187. //
  188. // Get the PinConnect structure from KS.
  189. // This function will copy creation parameters to pPinConnect.
  190. // Also do a basic connectibility testing by comparing KSDATAFORMAT of
  191. // pin descriptors and the request.
  192. //
  193. Status = KsValidateConnectRequest(
  194. pIrp,
  195. pGraphNodeInstance->cPins,
  196. pGraphNodeInstance->paPinDescriptors,
  197. &pPinConnect);
  198. if(!NT_SUCCESS(Status)) {
  199. #ifdef DEBUG
  200. DPF1(60, "PinDispatchCreate: KsValidateConnectReq FAILED %08x", Status);
  201. if(pPinConnect != NULL) {
  202. DumpPinConnect(60, pPinConnect);
  203. }
  204. #endif
  205. goto exit;
  206. }
  207. ASSERT(pPinConnect->PinId < pGraphNodeInstance->cPins);
  208. //
  209. // Validate the integrity of AudioDataFormat.
  210. // Note that IO subsystem and KS will make sure that pPinConnect is
  211. // at least sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT). Also they make
  212. // sure that it is probed and buffered properly.
  213. //
  214. // Note that Midi formats are OK because they do not have a specifier.
  215. //
  216. Status = ValidateDataFormat((PKSDATAFORMAT) pPinConnect + 1);
  217. if (!NT_SUCCESS(Status))
  218. {
  219. goto exit;
  220. }
  221. #ifdef DEBUG
  222. DPF(60, "PinDispatchCreate:");
  223. DumpPinConnect(60, pPinConnect);
  224. #endif
  225. // Check the pin instance count
  226. if(!pGraphNodeInstance->IsPinInstances(pPinConnect->PinId)) {
  227. DPF4(60, "PinDispatchCreate: not enough ins GNI %08x #%d C %d P %d",
  228. pGraphNodeInstance,
  229. pPinConnect->PinId,
  230. pGraphNodeInstance->pacPinInstances[pPinConnect->PinId].CurrentCount,
  231. pGraphNodeInstance->pacPinInstances[pPinConnect->PinId].PossibleCount);
  232. Status = STATUS_DEVICE_BUSY;
  233. goto exit;
  234. }
  235. // Allocate per pin instance data
  236. pPinInstance = new PIN_INSTANCE(
  237. &pGraphNodeInstance->pFilterInstance->ParentInstance);
  238. if(pPinInstance == NULL) {
  239. Status = STATUS_INSUFFICIENT_RESOURCES;
  240. goto exit;
  241. }
  242. // Setup the pin's instance data
  243. pPinInstance->ulVolumeNodeNumber = MAXULONG;
  244. pPinInstance->pFilterInstance = pGraphNodeInstance->pFilterInstance;
  245. pPinInstance->PinId = pPinConnect->PinId;
  246. Status = pPinInstance->DispatchCreate(
  247. pIrp,
  248. (UTIL_PFN)PinDispatchCreateKP,
  249. pPinConnect,
  250. 0,
  251. NULL,
  252. &PinDispatchTable);
  253. pPinConnect->PinId = pPinInstance->PinId;
  254. if(!NT_SUCCESS(Status)) {
  255. #ifdef DEBUG
  256. DPF1(60, "PinDispatchCreate: FAILED: %08x ", Status);
  257. DumpPinConnect(60, pPinConnect);
  258. #endif
  259. goto exit;
  260. }
  261. // Increment the reference count on this pin
  262. ASSERT(pPinInstance->pStartNodeInstance != NULL);
  263. ASSERT(pGraphNodeInstance->pacPinInstances != NULL);
  264. pGraphNodeInstance->pacPinInstances[pPinInstance->PinId].CurrentCount++;
  265. exit:
  266. if(!NT_SUCCESS(Status)) {
  267. delete pPinInstance;
  268. }
  269. ::ReleaseMutex();
  270. pIrp->IoStatus.Status = Status;
  271. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  272. return Status;
  273. }
  274. NTSTATUS
  275. CPinInstance::PinDispatchCreateKP(
  276. PPIN_INSTANCE pPinInstance,
  277. PKSPIN_CONNECT pPinConnect
  278. )
  279. {
  280. PWAVEFORMATEX pWaveFormatExRequested = NULL;
  281. PFILTER_INSTANCE pFilterInstance;
  282. PSTART_NODE pStartNode;
  283. NTSTATUS Status;
  284. Assert(pPinInstance);
  285. pFilterInstance = pPinInstance->pFilterInstance;
  286. Assert(pFilterInstance);
  287. ASSERT(pPinInstance->PinId < pFilterInstance->pGraphNodeInstance->cPins);
  288. ASSERT(pPinConnect->PinId < pFilterInstance->pGraphNodeInstance->cPins);
  289. //
  290. // SECURITY NOTE:
  291. // pPinConnect and following buffer is fully validated at this point.
  292. // So it is totally safe to call GetWaveFormatExFromKsDataFormat.
  293. //
  294. pWaveFormatExRequested =
  295. GetWaveFormatExFromKsDataFormat(PKSDATAFORMAT(pPinConnect + 1), NULL);
  296. if(pWaveFormatExRequested != NULL) {
  297. // Fix SampleSize if zero
  298. if(PKSDATAFORMAT(pPinConnect + 1)->SampleSize == 0) {
  299. PKSDATAFORMAT(pPinConnect + 1)->SampleSize =
  300. pWaveFormatExRequested->nBlockAlign;
  301. }
  302. }
  303. //
  304. // Try each start node until success
  305. //
  306. Status = STATUS_INVALID_DEVICE_REQUEST;
  307. //
  308. // First loop through all the start nodes which are not marked SECONDPASS
  309. // and try to create a StartNodeInstance
  310. //
  311. FOR_EACH_LIST_ITEM(
  312. pFilterInstance->pGraphNodeInstance->aplstStartNode[pPinInstance->PinId],
  313. pStartNode) {
  314. Assert(pStartNode);
  315. Assert(pFilterInstance);
  316. if(pStartNode->ulFlags & STARTNODE_FLAGS_SECONDPASS) {
  317. continue;
  318. }
  319. if(pFilterInstance->pGraphNodeInstance->IsGraphValid(
  320. pStartNode,
  321. pPinInstance->PinId)) {
  322. Status = CStartNodeInstance::Create(
  323. pPinInstance,
  324. pStartNode,
  325. pPinConnect,
  326. pWaveFormatExRequested);
  327. if(NT_SUCCESS(Status)) {
  328. break;
  329. }
  330. }
  331. } END_EACH_LIST_ITEM
  332. //
  333. // If first pass failed to create an instance try all the second pass
  334. // StartNodes in the list. This is being done for creating paths with no GFX
  335. // because we created a path with AEC and no GFX earlier.
  336. //
  337. if(!NT_SUCCESS(Status)) {
  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. if(NT_SUCCESS(Status)) {
  355. break;
  356. }
  357. }
  358. } END_EACH_LIST_ITEM
  359. if(!NT_SUCCESS(Status)) {
  360. goto exit;
  361. }
  362. }
  363. Status = pPinInstance->SetNextFileObject(
  364. pPinInstance->pStartNodeInstance->pPinNodeInstance->hPin);
  365. if(!NT_SUCCESS(Status)) {
  366. Trap();
  367. goto exit;
  368. }
  369. exit:
  370. return(Status);
  371. }
  372. NTSTATUS
  373. CPinInstance::PinDispatchClose(
  374. IN PDEVICE_OBJECT pDeviceObject,
  375. IN PIRP pIrp
  376. )
  377. {
  378. PIO_STACK_LOCATION pIrpStack;
  379. PPIN_INSTANCE pPinInstance;
  380. ::GrabMutex();
  381. pIrpStack = IoGetCurrentIrpStackLocation( pIrp );
  382. pPinInstance = (PPIN_INSTANCE)pIrpStack->FileObject->FsContext;
  383. Assert(pPinInstance);
  384. pIrpStack->FileObject->FsContext = NULL;
  385. delete pPinInstance;
  386. ::ReleaseMutex();
  387. pIrp->IoStatus.Status = STATUS_SUCCESS;
  388. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  389. return STATUS_SUCCESS;
  390. }
  391. NTSTATUS
  392. CPinInstance::PinDispatchIoControl(
  393. IN PDEVICE_OBJECT pDeviceObject,
  394. IN PIRP pIrp
  395. )
  396. {
  397. NTSTATUS Status;
  398. PSTART_NODE_INSTANCE pStartNodeInstance;
  399. PIO_STACK_LOCATION pIrpStack;
  400. PKSIDENTIFIER pKsIdentifier;
  401. PPIN_INSTANCE pPinInstance;
  402. BOOL fIsAllocated;
  403. #ifdef DEBUG
  404. DumpIoctl(pIrp, "Pin", DBG_IOCTL_LOG);
  405. #endif
  406. pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  407. fIsAllocated = FALSE;
  408. pKsIdentifier = NULL;
  409. //
  410. // If sysaudio is not interested with this IOCTL code then forward
  411. // the request.
  412. //
  413. if (!IsSysaudioIoctlCode(pIrpStack->Parameters.DeviceIoControl.IoControlCode))
  414. {
  415. return DispatchForwardIrp(pDeviceObject, pIrp);
  416. }
  417. //
  418. // Validate input/output buffers. From this point on we can assume
  419. // that all parameters are validated and copied to kernel mode.
  420. // Irp->AssociatedIrp->SystemBuffer should now contain both
  421. // input and output buffers.
  422. //
  423. Status = ValidateDeviceIoControl(pIrp);
  424. if (!NT_SUCCESS(Status))
  425. {
  426. goto exit1;
  427. }
  428. ::GrabMutex();
  429. pPinInstance = (PPIN_INSTANCE)pIrpStack->FileObject->FsContext;
  430. Status = pPinInstance->GetStartNodeInstance(&pStartNodeInstance);
  431. if (!NT_SUCCESS(Status))
  432. {
  433. goto exit;
  434. }
  435. Assert(pPinInstance->pFilterInstance);
  436. Assert(pPinInstance->pFilterInstance->pGraphNodeInstance);
  437. //
  438. // Extract the Identifier from the Irp. Only known error codes will cause a
  439. // real failure.
  440. //
  441. Status = GetKsIdentifierFromIrp(pIrp, &pKsIdentifier, &fIsAllocated);
  442. if (!NT_SUCCESS(Status))
  443. {
  444. goto exit;
  445. }
  446. //
  447. // This check allows the actual node or filter return the set's
  448. // supported, etc. instead of always return only the sets sysaudio
  449. // supports.
  450. //
  451. if (pKsIdentifier)
  452. {
  453. if (IsIoctlForTopologyNode(
  454. pIrpStack->Parameters.DeviceIoControl.IoControlCode,
  455. pKsIdentifier->Flags))
  456. {
  457. Status = ForwardIrpNode(
  458. pIrp,
  459. pKsIdentifier,
  460. pPinInstance->pFilterInstance,
  461. pPinInstance);
  462. goto exit2;
  463. }
  464. }
  465. //
  466. // Handle the request.
  467. //
  468. switch(pIrpStack->Parameters.DeviceIoControl.IoControlCode)
  469. {
  470. case IOCTL_KS_PROPERTY:
  471. Status = KsPropertyHandler(
  472. pIrp,
  473. SIZEOF_ARRAY(PinPropertySet),
  474. (PKSPROPERTY_SET)PinPropertySet);
  475. if(Status != STATUS_NOT_FOUND &&
  476. Status != STATUS_PROPSET_NOT_FOUND)
  477. {
  478. break;
  479. }
  480. // Fall through if property not found
  481. case IOCTL_KS_ENABLE_EVENT:
  482. case IOCTL_KS_DISABLE_EVENT:
  483. case IOCTL_KS_METHOD:
  484. // NOTE: ForwardIrpNode releases gMutex
  485. Status = ForwardIrpNode(
  486. pIrp,
  487. pKsIdentifier,
  488. pPinInstance->pFilterInstance,
  489. pPinInstance);
  490. goto exit2;
  491. default:
  492. Status = STATUS_UNSUCCESSFUL;
  493. ASSERT(FALSE); // Can't happen because of IsSysaudioIoctlCode
  494. }
  495. exit:
  496. ::ReleaseMutex();
  497. exit1:
  498. pIrp->IoStatus.Status = Status;
  499. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  500. exit2:
  501. if (fIsAllocated)
  502. {
  503. delete [] pKsIdentifier;
  504. }
  505. return(Status);
  506. }
  507. NTSTATUS
  508. CPinInstance::PinStateHandler
  509. (
  510. IN PIRP pIrp,
  511. IN PKSPROPERTY pProperty,
  512. IN OUT PKSSTATE pState
  513. )
  514. {
  515. PSTART_NODE_INSTANCE pStartNodeInstance;
  516. NTSTATUS Status = STATUS_SUCCESS;
  517. #ifdef DEBUG
  518. extern PSZ apszStates[];
  519. #endif
  520. Status = ::GetStartNodeInstance(pIrp, &pStartNodeInstance);
  521. if(!NT_SUCCESS(Status)) {
  522. Trap();
  523. goto exit;
  524. }
  525. if(pProperty->Flags & KSPROPERTY_TYPE_GET) {
  526. *pState = pStartNodeInstance->CurrentState;
  527. pIrp->IoStatus.Information = sizeof(KSSTATE);
  528. if(*pState == KSSTATE_PAUSE) {
  529. if(pStartNodeInstance->pPinNodeInstance->
  530. pPinNode->pPinInfo->DataFlow == KSPIN_DATAFLOW_OUT) {
  531. Status = STATUS_NO_DATA_DETECTED;
  532. }
  533. }
  534. }
  535. else {
  536. ASSERT(pProperty->Flags & KSPROPERTY_TYPE_SET);
  537. DPF3(90, "PinStateHandler from %s to %s - SNI: %08x",
  538. apszStates[pStartNodeInstance->CurrentState],
  539. apszStates[*pState],
  540. pStartNodeInstance);
  541. Status = pStartNodeInstance->SetState(*pState, 0);
  542. if(!NT_SUCCESS(Status)) {
  543. DPF1(90, "PinStateHandler FAILED: %08x", Status);
  544. goto exit;
  545. }
  546. }
  547. exit:
  548. return(Status);
  549. }
  550. NTSTATUS
  551. GetRelatedStartNodeInstance(
  552. IN PIRP pIrp,
  553. OUT PSTART_NODE_INSTANCE *ppStartNodeInstance
  554. )
  555. {
  556. ASSERT(ppStartNodeInstance);
  557. PPIN_INSTANCE pPinInstance =
  558. (PPIN_INSTANCE) IoGetCurrentIrpStackLocation(pIrp)->FileObject->
  559. RelatedFileObject->FsContext;
  560. if (NULL != pPinInstance) {
  561. return pPinInstance->GetStartNodeInstance(ppStartNodeInstance);
  562. }
  563. //
  564. // SECURITY NOTE:
  565. // This is in critical code path. Nearly all dispatch functions call this
  566. // routine.
  567. // So be a little defensive for cases where FsContext is not valid.
  568. //
  569. DPF(5, "GetRelatedStartNodeInstance : FsContext is NULL");
  570. return STATUS_UNSUCCESSFUL;
  571. }
  572. NTSTATUS
  573. GetStartNodeInstance(
  574. IN PIRP pIrp,
  575. OUT PSTART_NODE_INSTANCE *ppStartNodeInstance
  576. )
  577. {
  578. ASSERT(ppStartNodeInstance);
  579. PPIN_INSTANCE pPinInstance =
  580. (PPIN_INSTANCE) IoGetCurrentIrpStackLocation(pIrp)->
  581. FileObject->FsContext;
  582. if (NULL != pPinInstance) {
  583. return pPinInstance->GetStartNodeInstance(ppStartNodeInstance);
  584. }
  585. //
  586. // SECURITY NOTE:
  587. // This is in critical code path. Nearly all dispatch functions call this
  588. // routine.
  589. // So be a little defensive for cases where FsContext is not valid.
  590. //
  591. DPF(5, "GetStartNodeInstance : FsContext is NULL");
  592. return STATUS_UNSUCCESSFUL;
  593. }
  594. NTSTATUS
  595. CPinInstance::GetStartNodeInstance(
  596. OUT PSTART_NODE_INSTANCE *ppStartNodeInstance
  597. )
  598. {
  599. NTSTATUS Status = STATUS_SUCCESS;
  600. ASSERT(ppStartNodeInstance);
  601. if(this == NULL || pStartNodeInstance == NULL) {
  602. DPF(60, "GetStartNodeInstance: pStartNodeInstance == NULL");
  603. Status = STATUS_NO_SUCH_DEVICE;
  604. goto exit;
  605. }
  606. Assert(this);
  607. *ppStartNodeInstance = pStartNodeInstance;
  608. exit:
  609. return(Status);
  610. }
  611. //---------------------------------------------------------------------------
  612. //
  613. // Extracts the KsIdentifier from the Irp.
  614. // This should be called with only DEVICE_CONTROL requests.
  615. //
  616. NTSTATUS
  617. GetKsIdentifierFromIrp(
  618. PIRP pIrp,
  619. PKSIDENTIFIER *ppKsIdentifier,
  620. PBOOL pfIsAllocated
  621. )
  622. {
  623. NTSTATUS Status;
  624. PIO_STACK_LOCATION pIrpStack;
  625. PKSIDENTIFIER pKsIdentifier;
  626. BOOL fIsAllocated;
  627. ULONG cbInput;
  628. ASSERT(ppKsIdentifier);
  629. ASSERT(pfIsAllocated);
  630. Status = STATUS_SUCCESS;
  631. pKsIdentifier = NULL;
  632. fIsAllocated = FALSE;
  633. pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  634. cbInput = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
  635. *ppKsIdentifier = NULL;
  636. *pfIsAllocated = FALSE;
  637. //
  638. // Reject if the buffer is too small.
  639. //
  640. if (cbInput < sizeof(KSIDENTIFIER))
  641. {
  642. return STATUS_SUCCESS;
  643. }
  644. //
  645. // Reject DISABLE_EVENT requests. These buffers are handled seperately.
  646. //
  647. if (IOCTL_KS_DISABLE_EVENT == pIrpStack->Parameters.DeviceIoControl.IoControlCode)
  648. {
  649. return STATUS_SUCCESS;
  650. }
  651. //
  652. // SystemBuffer is not Set. We are still depending on Type3InputBuffer.
  653. //
  654. if (NULL == pIrp->AssociatedIrp.SystemBuffer)
  655. {
  656. //
  657. // If the request is coming from KernelMode, we can use it directly.
  658. // Note that there might be some synchronization issues here.
  659. //
  660. if (KernelMode == pIrp->RequestorMode)
  661. {
  662. pKsIdentifier = (PKSIDENTIFIER)
  663. pIrpStack->Parameters.DeviceIoControl.Type3InputBuffer;
  664. }
  665. //
  666. // If the request is coming from UserMode, we need to buffer it.
  667. //
  668. else
  669. {
  670. pKsIdentifier = (PKSIDENTIFIER) new BYTE[cbInput];
  671. if (NULL == pKsIdentifier)
  672. {
  673. DPF(5, "GetKsIdentifierFromIrp: Memory allocation failed");
  674. Status = STATUS_INSUFFICIENT_RESOURCES;
  675. }
  676. else
  677. {
  678. __try
  679. {
  680. ProbeForWrite(
  681. pIrpStack->Parameters.DeviceIoControl.Type3InputBuffer,
  682. cbInput,
  683. sizeof(BYTE));
  684. RtlCopyMemory(
  685. pKsIdentifier,
  686. pIrpStack->Parameters.DeviceIoControl.Type3InputBuffer,
  687. cbInput);
  688. fIsAllocated = TRUE;
  689. }
  690. __except(EXCEPTION_EXECUTE_HANDLER)
  691. {
  692. Status = STATUS_UNSUCCESSFUL;
  693. DPF1(5, "GetKsIdentifierFromIrp: Exception %08x", GetExceptionCode());
  694. delete [] pKsIdentifier;
  695. pKsIdentifier = NULL;
  696. }
  697. }
  698. }
  699. }
  700. //
  701. // If SystemBuffer is already set, ValidateDeviceIoControl must
  702. // have converted the request to BUFFERRED.
  703. //
  704. else
  705. {
  706. pKsIdentifier = (PKSIDENTIFIER)
  707. ((PUCHAR)pIrp->AssociatedIrp.SystemBuffer +
  708. ((pIrpStack->Parameters.DeviceIoControl.OutputBufferLength +
  709. FILE_QUAD_ALIGNMENT) & ~FILE_QUAD_ALIGNMENT));
  710. }
  711. *ppKsIdentifier = pKsIdentifier;
  712. *pfIsAllocated = fIsAllocated;
  713. return Status;
  714. } // GetKsIdentifierFromIrp
  715. #pragma LOCKED_CODE
  716. #pragma LOCKED_DATA
  717. BOOL
  718. IsIoctlForTopologyNode(
  719. ULONG IoControlCode,
  720. ULONG Flags
  721. )
  722. {
  723. if (Flags & KSPROPERTY_TYPE_TOPOLOGY)
  724. {
  725. if (IOCTL_KS_PROPERTY == IoControlCode)
  726. {
  727. if ((Flags & (KSPROPERTY_TYPE_GET |
  728. KSPROPERTY_TYPE_SET |
  729. KSPROPERTY_TYPE_BASICSUPPORT)) == 0)
  730. {
  731. return TRUE;
  732. }
  733. }
  734. else
  735. {
  736. return TRUE;
  737. }
  738. }
  739. return FALSE;
  740. } // IsIoctlForTopologyNode
  741. //---------------------------------------------------------------------------
  742. //
  743. // Get the FileObject for the filter that owns this node.
  744. //
  745. NTSTATUS
  746. GetFileObjectFromNodeId(
  747. IN PPIN_INSTANCE pPinInstance,
  748. IN PGRAPH_NODE_INSTANCE pGraphNodeInstance,
  749. IN ULONG NodeId,
  750. OUT PFILE_OBJECT *ppFileObject
  751. )
  752. {
  753. NTSTATUS Status;
  754. ASSERT(ppFileObject);
  755. if (pPinInstance == NULL)
  756. {
  757. Status = pGraphNodeInstance->GetTopologyNodeFileObject(
  758. ppFileObject,
  759. NodeId);
  760. }
  761. else
  762. {
  763. Status = pPinInstance->pStartNodeInstance->GetTopologyNodeFileObject(
  764. ppFileObject,
  765. NodeId);
  766. }
  767. return Status;
  768. }// GetFileObjectFromNodeId
  769. //---------------------------------------------------------------------------
  770. //
  771. // Extracts the event data from Irp. Caller must free the EventData
  772. // depending on fIsAllocated.
  773. //
  774. NTSTATUS
  775. GetEventDataFromIrp(
  776. IN PIRP pIrp,
  777. OUT PKSEVENTDATA *ppEventData,
  778. OUT BOOL *pfIsAllocated
  779. )
  780. {
  781. NTSTATUS Status;
  782. PIO_STACK_LOCATION pIrpStack;
  783. PKSEVENTDATA pEventData;
  784. BOOL fIsAllocated;
  785. ULONG cbInput;
  786. ASSERT(pIrp);
  787. ASSERT(ppEventData);
  788. ASSERT(pfIsAllocated);
  789. Status = STATUS_SUCCESS;
  790. pEventData = NULL;
  791. fIsAllocated = FALSE;
  792. pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  793. cbInput = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
  794. *ppEventData = NULL;
  795. *pfIsAllocated = FALSE;
  796. if (cbInput < sizeof(KSEVENTDATA))
  797. {
  798. DPF1(5, "GetEventDataFromIrp: InputBuffer too small %d", cbInput);
  799. return STATUS_BUFFER_TOO_SMALL;
  800. }
  801. //
  802. // SystemBuffer is not Set. We are still depending on Type3InputBuffer.
  803. //
  804. if (NULL == pIrp->AssociatedIrp.SystemBuffer)
  805. {
  806. //
  807. // If the request is coming from KernelMode, we can use it directly.
  808. // Note that there might be some synchronization issues here.
  809. //
  810. if (KernelMode == pIrp->RequestorMode)
  811. {
  812. pEventData = (PKSEVENTDATA)
  813. pIrpStack->Parameters.DeviceIoControl.Type3InputBuffer;
  814. }
  815. //
  816. // If the request is coming from UserMode, we need to buffer it.
  817. //
  818. else
  819. {
  820. pEventData = (PKSEVENTDATA) ExAllocatePoolWithTag(
  821. NonPagedPool,
  822. cbInput,
  823. POOLTAG_SYSA);
  824. if (NULL == pEventData)
  825. {
  826. DPF(5, "GetEventDataFromIrp: Memory allocation failed");
  827. Status = STATUS_INSUFFICIENT_RESOURCES;
  828. }
  829. else
  830. {
  831. __try
  832. {
  833. ProbeForWrite(
  834. pIrpStack->Parameters.DeviceIoControl.Type3InputBuffer,
  835. cbInput,
  836. sizeof(BYTE));
  837. RtlCopyMemory(
  838. pEventData,
  839. pIrpStack->Parameters.DeviceIoControl.Type3InputBuffer,
  840. cbInput);
  841. fIsAllocated = TRUE;
  842. }
  843. __except(EXCEPTION_EXECUTE_HANDLER)
  844. {
  845. Status = STATUS_UNSUCCESSFUL;
  846. DPF1(5, "GetEventDataFromIrp: Exception %08x", GetExceptionCode());
  847. ExFreePool(pEventData);
  848. pEventData = NULL;
  849. }
  850. }
  851. }
  852. }
  853. //
  854. // If SystemBuffer is already set, ValidateDeviceIoControl must
  855. // have converted the request to BUFFERRED.
  856. //
  857. else
  858. {
  859. pEventData = (PKSEVENTDATA)
  860. ((PUCHAR)pIrp->AssociatedIrp.SystemBuffer +
  861. ((pIrpStack->Parameters.DeviceIoControl.OutputBufferLength +
  862. FILE_QUAD_ALIGNMENT) & ~FILE_QUAD_ALIGNMENT));
  863. }
  864. *ppEventData = pEventData;
  865. *pfIsAllocated = fIsAllocated;
  866. return Status;
  867. } // GetEventDataFromIrp
  868. //---------------------------------------------------------------------------
  869. //
  870. // Get the FileObject from DISABLE_EVENT request.
  871. // This function should not touch ppFileObject incase of a failure.
  872. //
  873. NTSTATUS
  874. GetFileObjectFromEvent(
  875. IN PIRP pIrp,
  876. IN PPIN_INSTANCE pPinInstance,
  877. IN PGRAPH_NODE_INSTANCE pGraphNodeInstance,
  878. OUT PFILE_OBJECT *ppFileObject
  879. )
  880. {
  881. NTSTATUS Status;
  882. PIO_STACK_LOCATION pIrpStack;
  883. PKSEVENTDATA pEventData;
  884. BOOL fIsAllocated;
  885. ULONG cbInput;
  886. ULONG OriginalNodeId;
  887. ASSERT(pIrp);
  888. ASSERT(pGraphNodeInstance);
  889. ASSERT(ppFileObject);
  890. pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  891. cbInput = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
  892. //
  893. // Get KSEVENTDATA from the Irp safely.
  894. //
  895. Status = GetEventDataFromIrp(
  896. pIrp,
  897. &pEventData,
  898. &fIsAllocated);
  899. if (NT_SUCCESS(Status))
  900. {
  901. //
  902. // Extract the NodeId and FileObject.
  903. //
  904. OriginalNodeId = ULONG(pEventData->Dpc.Reserved);
  905. if ((pEventData->NotificationType == KSEVENTF_DPC) &&
  906. (OriginalNodeId & 0x80000000))
  907. {
  908. OriginalNodeId = OriginalNodeId & 0x7fffffff;
  909. Status = GetFileObjectFromNodeId(
  910. pPinInstance,
  911. pGraphNodeInstance,
  912. OriginalNodeId,
  913. ppFileObject);
  914. if(!NT_SUCCESS(Status))
  915. {
  916. DPF1(5, "GetFileObjectFromEvent: GetTopologyNodeFileObject FAILED %08x", Status);
  917. goto exit;
  918. }
  919. }
  920. }
  921. //
  922. // No else here. We are succeeding in all other cases.
  923. //
  924. exit:
  925. if (fIsAllocated)
  926. {
  927. ExFreePool(pEventData);
  928. }
  929. return Status;
  930. } // GetFileObjectFromEvent
  931. //=============================================================================
  932. //
  933. // ForwardIrpNode
  934. //
  935. // NOTE: ForwardIrpNode releases gMutex
  936. //
  937. NTSTATUS
  938. ForwardIrpNode(
  939. IN PIRP pIrp,
  940. IN PKSIDENTIFIER pKsIdentifier,
  941. IN PFILTER_INSTANCE pFilterInstance,
  942. IN OPTIONAL PPIN_INSTANCE pPinInstance
  943. )
  944. {
  945. PGRAPH_NODE_INSTANCE pGraphNodeInstance;
  946. PFILE_OBJECT pFileObject = NULL;
  947. PIO_STACK_LOCATION pIrpStack;
  948. ULONG OriginalNodeId;
  949. NTSTATUS Status;
  950. Assert(pFilterInstance);
  951. pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  952. Status = pFilterInstance->GetGraphNodeInstance(&pGraphNodeInstance);
  953. if (!NT_SUCCESS(Status))
  954. {
  955. goto exit;
  956. }
  957. Assert(pGraphNodeInstance);
  958. if (pPinInstance != NULL)
  959. {
  960. pFileObject = pPinInstance->GetNextFileObject();
  961. }
  962. //
  963. // if InputBufferLength is more than KSNODEPROPERTY the callers
  964. // must have already set the identifier.
  965. //
  966. if (pIrpStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(KSNODEPROPERTY) &&
  967. pIrpStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_DISABLE_EVENT)
  968. {
  969. ASSERT(pKsIdentifier);
  970. if (pKsIdentifier->Flags & KSPROPERTY_TYPE_TOPOLOGY)
  971. {
  972. PKSNODEPROPERTY pNodeProperty;
  973. pNodeProperty = (PKSNODEPROPERTY) pKsIdentifier;
  974. OriginalNodeId = pNodeProperty->NodeId;
  975. Status = GetFileObjectFromNodeId(
  976. pPinInstance,
  977. pGraphNodeInstance,
  978. OriginalNodeId,
  979. &pFileObject);
  980. if (!NT_SUCCESS(Status))
  981. {
  982. DPF1(100,
  983. "ForwardIrpNode: GetTopologyNodeFileObject FAILED %08x",
  984. Status);
  985. goto exit;
  986. }
  987. // Put real node number in input buffer
  988. pNodeProperty->NodeId = pGraphNodeInstance->
  989. papTopologyNode[OriginalNodeId]->ulRealNodeNumber;
  990. }
  991. }
  992. //
  993. // If it is DisableEvent && if it is of type DPC. We look into the
  994. // Reserved field of KSEVENTDATA to extract the original node on
  995. // which the event was enabled (The high bit is set if we ever
  996. // stashed a NodeId in there).
  997. //
  998. else
  999. {
  1000. if (pIrpStack->Parameters.DeviceIoControl.IoControlCode ==
  1001. IOCTL_KS_DISABLE_EVENT)
  1002. {
  1003. ASSERT(NULL == pKsIdentifier);
  1004. Status = GetFileObjectFromEvent(
  1005. pIrp,
  1006. pPinInstance,
  1007. pGraphNodeInstance,
  1008. &pFileObject);
  1009. if (!NT_SUCCESS(Status))
  1010. {
  1011. goto exit;
  1012. }
  1013. }
  1014. }
  1015. if (pFileObject == NULL)
  1016. {
  1017. Status = STATUS_NOT_FOUND;
  1018. DPF1(6, "ForwardIrpNode: Property not forwarded: %08x", pKsIdentifier);
  1019. goto exit;
  1020. }
  1021. pIrpStack->FileObject = pFileObject;
  1022. //
  1023. // If it was EnableEvent we stash away pointer to KSEVENTDATA, so that we
  1024. // can stash the NodeID into it after we call the next driver on the stack
  1025. //
  1026. PKSEVENTDATA pEventData;
  1027. KPROCESSOR_MODE RequestorMode;
  1028. if ((pKsIdentifier != NULL) &&
  1029. (pIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT) &&
  1030. !(pKsIdentifier->Flags & KSEVENT_TYPE_BASICSUPPORT) &&
  1031. (pKsIdentifier->Flags & KSPROPERTY_TYPE_TOPOLOGY) &&
  1032. (pKsIdentifier->Flags & KSEVENT_TYPE_ENABLE))
  1033. {
  1034. pEventData = (PKSEVENTDATA) pIrp->UserBuffer;
  1035. RequestorMode = pIrp->RequestorMode;
  1036. }
  1037. else
  1038. {
  1039. pEventData = NULL;
  1040. }
  1041. //
  1042. // Forward request to the top of audio graph.
  1043. // There is no problem as long as the target device stack size is
  1044. // less than SYSTEM_LARGE_IRP_LOCATIONS
  1045. //
  1046. IoSkipCurrentIrpStackLocation(pIrp);
  1047. AssertFileObject(pIrpStack->FileObject);
  1048. Status = IoCallDriver(IoGetRelatedDeviceObject(pFileObject), pIrp);
  1049. //
  1050. // ISSUE: ALPERS 05/29/2002
  1051. // This logic is completely broken. Now the IRP is completed, how
  1052. // can we make sure that UserData is still available.
  1053. //
  1054. //
  1055. // Stash away the Node id in EventData
  1056. //
  1057. __try
  1058. {
  1059. if (pEventData != NULL)
  1060. {
  1061. if (UserMode == RequestorMode)
  1062. {
  1063. ProbeForWrite(pEventData, sizeof(KSEVENTDATA), 1);
  1064. }
  1065. if (KSEVENTF_DPC == pEventData->NotificationType)
  1066. {
  1067. pEventData->Dpc.Reserved = OriginalNodeId | 0x80000000;
  1068. }
  1069. }
  1070. }
  1071. __except (EXCEPTION_EXECUTE_HANDLER)
  1072. {
  1073. Trap();
  1074. Status = GetExceptionCode();
  1075. DPF1(5, "ForwardIrpNode: Exception %08x", Status);
  1076. }
  1077. if(!NT_SUCCESS(Status))
  1078. {
  1079. DPF1(100, "ForwardIrpNode: Status %08x", Status);
  1080. }
  1081. ::ReleaseMutex();
  1082. return(Status);
  1083. exit:
  1084. ::ReleaseMutex();
  1085. pIrp->IoStatus.Status = Status;
  1086. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  1087. return(Status);
  1088. }
  1089. //---------------------------------------------------------------------------
  1090. // End of File: pins.c
  1091. //---------------------------------------------------------------------------