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.

863 lines
24 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Module: notify.cpp
  4. //
  5. // Description:
  6. //
  7. //
  8. //@@BEGIN_MSINTERNAL
  9. // Development Team:
  10. // Mike McLaughlin
  11. //
  12. // History: Date Author Comment
  13. //
  14. // To Do: Date Author Comment
  15. //
  16. //@@END_MSINTERNAL
  17. //
  18. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  19. // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  20. // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  21. // PURPOSE.
  22. //
  23. // Copyright (c) 1996-1999 Microsoft Corporation. All Rights Reserved.
  24. //
  25. //---------------------------------------------------------------------------
  26. #include "common.h"
  27. //---------------------------------------------------------------------------
  28. //---------------------------------------------------------------------------
  29. CONST GUID *apguidCategories[] = {
  30. &KSCATEGORY_AUDIO,
  31. &KSCATEGORY_AUDIO_GFX,
  32. &KSCATEGORY_TOPOLOGY,
  33. &KSCATEGORY_BRIDGE,
  34. &KSCATEGORY_RENDER,
  35. &KSCATEGORY_CAPTURE,
  36. &KSCATEGORY_MIXER,
  37. &KSCATEGORY_DATATRANSFORM,
  38. &KSCATEGORY_ACOUSTIC_ECHO_CANCEL,
  39. &KSCATEGORY_INTERFACETRANSFORM,
  40. &KSCATEGORY_MEDIUMTRANSFORM,
  41. &KSCATEGORY_DATACOMPRESSOR,
  42. &KSCATEGORY_DATADECOMPRESSOR,
  43. &KSCATEGORY_COMMUNICATIONSTRANSFORM,
  44. &KSCATEGORY_SPLITTER,
  45. &KSCATEGORY_AUDIO_SPLITTER,
  46. &KSCATEGORY_SYNTHESIZER,
  47. #ifdef KSCATEGORY_DRM_DESCRAMBLE
  48. &KSCATEGORY_DRM_DESCRAMBLE,
  49. #endif
  50. #ifdef KSCATEGORY_MICROPHONE_ARRAY_PROCESSOR
  51. &KSCATEGORY_MICROPHONE_ARRAY_PROCESSOR,
  52. #endif
  53. };
  54. ULONG aulFilterType[] = {
  55. FILTER_TYPE_AUDIO,
  56. FILTER_TYPE_GFX,
  57. FILTER_TYPE_TOPOLOGY,
  58. FILTER_TYPE_BRIDGE,
  59. FILTER_TYPE_RENDERER,
  60. FILTER_TYPE_CAPTURER,
  61. FILTER_TYPE_MIXER,
  62. FILTER_TYPE_DATA_TRANSFORM,
  63. FILTER_TYPE_AEC,
  64. FILTER_TYPE_INTERFACE_TRANSFORM,
  65. FILTER_TYPE_MEDIUM_TRANSFORM,
  66. FILTER_TYPE_DATA_TRANSFORM,
  67. FILTER_TYPE_DATA_TRANSFORM,
  68. FILTER_TYPE_COMMUNICATION_TRANSFORM,
  69. FILTER_TYPE_SPLITTER,
  70. FILTER_TYPE_SPLITTER,
  71. FILTER_TYPE_SYNTHESIZER,
  72. #ifdef KSCATEGORY_DRM_DESCRAMBLE
  73. FILTER_TYPE_DRM_DESCRAMBLE,
  74. #endif
  75. #ifdef KSCATEGORY_MICROPHONE_ARRAY_PROCESSOR
  76. FILTER_TYPE_MIC_ARRAY_PROCESSOR,
  77. #endif
  78. };
  79. PVOID pNotificationHandle = NULL;
  80. PVOID pNotificationHandle2 = NULL;
  81. //---------------------------------------------------------------------------
  82. //---------------------------------------------------------------------------
  83. NTSTATUS
  84. RegisterForPlugPlayNotifications(
  85. )
  86. {
  87. NTSTATUS Status;
  88. DPF(50, "RegisterForPlugPlayNotifications");
  89. ASSERT(gpDeviceInstance != NULL);
  90. ASSERT(gpDeviceInstance->pPhysicalDeviceObject != NULL);
  91. Status = IoRegisterPlugPlayNotification(
  92. EventCategoryDeviceInterfaceChange,
  93. PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES,
  94. (LPGUID)&KSCATEGORY_AUDIO,
  95. gpDeviceInstance->pPhysicalDeviceObject->DriverObject,
  96. (NTSTATUS (*)(PVOID, PVOID))AudioDeviceInterfaceNotification,
  97. NULL,
  98. &pNotificationHandle);
  99. if(!NT_SUCCESS(Status)) {
  100. Trap();
  101. goto exit;
  102. }
  103. //
  104. // For compatibility with Intel AEC which isn't registered in the AUDIO
  105. // category, sysaudio needs to hook the AEC category.
  106. //
  107. Status = IoRegisterPlugPlayNotification(
  108. EventCategoryDeviceInterfaceChange,
  109. PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES,
  110. (LPGUID)&KSCATEGORY_ACOUSTIC_ECHO_CANCEL,
  111. gpDeviceInstance->pPhysicalDeviceObject->DriverObject,
  112. (NTSTATUS (*)(PVOID, PVOID))AudioDeviceInterfaceNotification,
  113. NULL,
  114. &pNotificationHandle2);
  115. if(!NT_SUCCESS(Status)) {
  116. Trap();
  117. goto exit;
  118. }
  119. exit:
  120. return(Status);
  121. }
  122. VOID
  123. UnregisterForPlugPlayNotifications(
  124. )
  125. {
  126. if(pNotificationHandle != NULL) {
  127. IoUnregisterPlugPlayNotification(pNotificationHandle);
  128. }
  129. if(pNotificationHandle2 != NULL) {
  130. IoUnregisterPlugPlayNotification(pNotificationHandle2);
  131. }
  132. }
  133. VOID
  134. DecrementAddRemoveCount(
  135. )
  136. {
  137. if(InterlockedDecrement(&glPendingAddDelete) == 0) {
  138. DPF(50, "DecrementAddRemoveCount: sending event");
  139. KsGenerateEventList(
  140. NULL,
  141. KSEVENT_SYSAUDIO_ADDREMOVE_DEVICE,
  142. &gEventQueue,
  143. KSEVENTS_SPINLOCK,
  144. &gEventLock);
  145. }
  146. }
  147. NTSTATUS
  148. AddFilterWorker(
  149. PWSTR pwstrDeviceInterface,
  150. PVOID pReference
  151. )
  152. {
  153. AddFilter(pwstrDeviceInterface, NULL);
  154. ExFreePool(pwstrDeviceInterface);
  155. DecrementAddRemoveCount();
  156. // Dereference sysaudio FDO.
  157. ObDereferenceObject(gpDeviceInstance->pFunctionalDeviceObject);
  158. return(STATUS_SUCCESS);
  159. }
  160. NTSTATUS
  161. DeleteFilterWorker(
  162. PWSTR pwstrDeviceInterface,
  163. PVOID pReference
  164. )
  165. {
  166. DeleteFilter(pwstrDeviceInterface);
  167. ExFreePool(pwstrDeviceInterface);
  168. DecrementAddRemoveCount();
  169. // Dereference sysaudio FDO.
  170. ObDereferenceObject(gpDeviceInstance->pFunctionalDeviceObject);
  171. return(STATUS_SUCCESS);
  172. }
  173. NTSTATUS
  174. AudioDeviceInterfaceNotification(
  175. IN PDEVICE_INTERFACE_CHANGE_NOTIFICATION pNotification,
  176. IN PVOID Context
  177. )
  178. {
  179. NTSTATUS Status = STATUS_SUCCESS;
  180. PWSTR pwstrDeviceInterface;
  181. DPF1(50, "AudioDeviceInterfaceNotification: (%s)",
  182. DbgUnicode2Sz(pNotification->SymbolicLinkName->Buffer));
  183. //
  184. // SECURITY NOTE:
  185. // We trust the Buffer, because it is passed to us as part of notification
  186. // from PnP subsystem.
  187. //
  188. pwstrDeviceInterface = (PWSTR)
  189. ExAllocatePoolWithTag(
  190. PagedPool,
  191. (wcslen(pNotification->SymbolicLinkName->Buffer) + 1) * sizeof(WCHAR),
  192. 'ASYS');
  193. if(pwstrDeviceInterface == NULL) {
  194. Status = STATUS_INSUFFICIENT_RESOURCES;
  195. goto exit;
  196. }
  197. // The notification sends null terminated unicode strings
  198. wcscpy(pwstrDeviceInterface, pNotification->SymbolicLinkName->Buffer);
  199. if(IsEqualGUID(&pNotification->Event, &GUID_DEVICE_INTERFACE_ARRIVAL)) {
  200. //
  201. // Keep a reference so that PnP does not REMOVE the device
  202. // when the Worker thread is running.
  203. // If the thread is scheduled successfully, it will remove the reference
  204. // when exiting.
  205. //
  206. ObReferenceObject(gpDeviceInstance->pFunctionalDeviceObject);
  207. InterlockedIncrement(&glPendingAddDelete);
  208. Status = QueueWorkList(
  209. (UTIL_PFN)AddFilterWorker,
  210. pwstrDeviceInterface,
  211. NULL);
  212. if (!NT_SUCCESS(Status)) {
  213. ObDereferenceObject(gpDeviceInstance->pFunctionalDeviceObject);
  214. }
  215. }
  216. else if(IsEqualGUID(&pNotification->Event, &GUID_DEVICE_INTERFACE_REMOVAL)) {
  217. //
  218. // Keep a reference so that PnP does not REMOVE the device
  219. // when the Worker thread is running.
  220. // If the thread is scheduled successfully, it will remove the reference
  221. // when exiting.
  222. //
  223. ObReferenceObject(gpDeviceInstance->pFunctionalDeviceObject);
  224. InterlockedIncrement(&glPendingAddDelete);
  225. Status = QueueWorkList(
  226. (UTIL_PFN)DeleteFilterWorker,
  227. pwstrDeviceInterface,
  228. NULL);
  229. if (!NT_SUCCESS(Status)) {
  230. ObDereferenceObject(gpDeviceInstance->pFunctionalDeviceObject);
  231. }
  232. }
  233. else {
  234. //
  235. // SECURITY NOTE:
  236. // Sysaudio is registering only for EventCategoryDeviceInterfaceChange.
  237. // This should send ARRIVAL and REMOVAL.
  238. // If anything else comes up, we will return SUCCESS.
  239. // However we are making sure that pwstrDeviceInterface is not leaked.
  240. //
  241. ExFreePool(pwstrDeviceInterface);
  242. }
  243. exit:
  244. if (!NT_SUCCESS(Status))
  245. {
  246. ExFreePool(pwstrDeviceInterface);
  247. }
  248. return(Status);
  249. }
  250. NTSTATUS
  251. AddFilter(
  252. PWSTR pwstrDeviceInterface,
  253. PFILTER_NODE *ppFilterNode // if !NULL, physical connection addfilter
  254. )
  255. {
  256. PFILTER_NODE pFilterNodeDuplicate = NULL;
  257. PFILTER_NODE pFilterNode = NULL;
  258. UNICODE_STRING ustrFilterName;
  259. UNICODE_STRING ustrAliasName;
  260. UNICODE_STRING ustrName;
  261. NTSTATUS Status;
  262. ULONG fulType;
  263. int i;
  264. DPF1(50, "AddFilter: (%s)", DbgUnicode2Sz(pwstrDeviceInterface));
  265. fulType = 0;
  266. RtlInitUnicodeString(&ustrFilterName, pwstrDeviceInterface);
  267. //
  268. // For each Interface in apguidCategories, get interface alias of
  269. // the new device. Check for duplicate interfaces.
  270. //
  271. for(i = 0; i < SIZEOF_ARRAY(apguidCategories); i++) {
  272. Status = IoGetDeviceInterfaceAlias(
  273. &ustrFilterName,
  274. apguidCategories[i],
  275. &ustrAliasName);
  276. if(NT_SUCCESS(Status)) {
  277. HANDLE hAlias;
  278. Status = OpenDevice(ustrAliasName.Buffer, &hAlias);
  279. if(NT_SUCCESS(Status)) {
  280. DPF2(100, "AddFilter: alias (%s) aulFilterType %08x",
  281. DbgUnicode2Sz(ustrAliasName.Buffer),
  282. aulFilterType[i]);
  283. fulType |= aulFilterType[i];
  284. ZwClose(hAlias);
  285. if(pFilterNodeDuplicate == NULL) {
  286. FOR_EACH_LIST_ITEM(gplstFilterNode, pFilterNode) {
  287. if(pFilterNode->GetDeviceInterface() == NULL) {
  288. continue;
  289. }
  290. RtlInitUnicodeString(
  291. &ustrName,
  292. pFilterNode->GetDeviceInterface());
  293. if(RtlEqualUnicodeString(
  294. &ustrAliasName,
  295. &ustrName,
  296. TRUE)) {
  297. DPF(50, "AddFilter: dup");
  298. pFilterNodeDuplicate = pFilterNode;
  299. break;
  300. }
  301. } END_EACH_LIST_ITEM
  302. }
  303. }
  304. else {
  305. DPF1(10, "AddFilter: OpenDevice FAILED on alias (%s)",
  306. DbgUnicode2Sz(ustrAliasName.Buffer));
  307. }
  308. RtlFreeUnicodeString(&ustrAliasName);
  309. }
  310. }
  311. pFilterNode = pFilterNodeDuplicate;
  312. Status = STATUS_SUCCESS;
  313. //
  314. // Create a new Filter_Node if this is not a duplicate.
  315. //
  316. if(pFilterNodeDuplicate == NULL) {
  317. pFilterNode = new FILTER_NODE(fulType);
  318. if(pFilterNode == NULL) {
  319. Status = STATUS_INSUFFICIENT_RESOURCES;
  320. Trap();
  321. goto exit;
  322. }
  323. Status = pFilterNode->Create(pwstrDeviceInterface);
  324. if(!NT_SUCCESS(Status)) {
  325. goto exit;
  326. }
  327. Status = pFilterNode->DuplicateForCapture();
  328. if(!NT_SUCCESS(Status)) {
  329. goto exit;
  330. }
  331. DPF1(50, "AddFilter: new CFilterNode fulType %08x", fulType);
  332. }
  333. //
  334. // If this is called from Interface Notification Callback,
  335. // create a new DeviceNode for the new FilterNode.
  336. //
  337. if(ppFilterNode == NULL) {
  338. if(pFilterNode->GetType() & FILTER_TYPE_ENDPOINT) {
  339. //
  340. // Check if a DeviceNode has already been created for
  341. // this FilterNode.
  342. //
  343. if (NULL != pFilterNodeDuplicate &&
  344. NULL != pFilterNodeDuplicate->pDeviceNode) {
  345. DPF1(5, "Duplicate FilterNode %X. Skip DeviceNode Create",
  346. pFilterNode);
  347. }
  348. else {
  349. pFilterNode->pDeviceNode = new DEVICE_NODE;
  350. if(pFilterNode->pDeviceNode == NULL) {
  351. Status = STATUS_INSUFFICIENT_RESOURCES;
  352. Trap();
  353. goto exit;
  354. }
  355. Status = pFilterNode->pDeviceNode->Create(pFilterNode);
  356. if(!NT_SUCCESS(Status)) {
  357. goto exit;
  358. }
  359. }
  360. }
  361. else {
  362. DPF(50, "AddFilter: DestroyAllGraphs");
  363. DestroyAllGraphs();
  364. }
  365. }
  366. exit:
  367. if(!NT_SUCCESS(Status)) {
  368. DPF2(5, "AddFilter: FAILED (%s) %08x",
  369. DbgUnicode2Sz(pwstrDeviceInterface),
  370. Status);
  371. if(pFilterNode != NULL && pFilterNodeDuplicate == NULL) {
  372. delete pFilterNode;
  373. pFilterNode = NULL;
  374. }
  375. }
  376. if(ppFilterNode != NULL) {
  377. *ppFilterNode = pFilterNode;
  378. }
  379. return(Status);
  380. }
  381. NTSTATUS
  382. DeleteFilter(
  383. PWSTR pwstrDeviceInterface
  384. )
  385. {
  386. UNICODE_STRING ustrFilterName;
  387. UNICODE_STRING ustrAliasName;
  388. UNICODE_STRING ustrName;
  389. PFILTER_NODE pFilterNode;
  390. NTSTATUS Status;
  391. int i;
  392. DPF1(50, "DeleteFilter: (%s)", DbgUnicode2Sz(pwstrDeviceInterface));
  393. RtlInitUnicodeString(&ustrFilterName, pwstrDeviceInterface);
  394. //
  395. // First delete all filter nodes which have the device interface which is
  396. // going away
  397. //
  398. FOR_EACH_LIST_ITEM_DELETE(gplstFilterNode, pFilterNode) {
  399. if(pFilterNode->GetDeviceInterface() == NULL) {
  400. continue;
  401. }
  402. RtlInitUnicodeString(
  403. &ustrName,
  404. pFilterNode->GetDeviceInterface());
  405. if(RtlEqualUnicodeString(
  406. &ustrFilterName,
  407. &ustrName,
  408. TRUE)) {
  409. delete pFilterNode;
  410. DELETE_LIST_ITEM(gplstFilterNode);
  411. }
  412. } END_EACH_LIST_ITEM
  413. for(i = 0; i < SIZEOF_ARRAY(apguidCategories); i++) {
  414. //
  415. // According to PnP group, it is perfectly safe to ask for aliases
  416. // during removal. The interface itself will be enabled or disabled. But
  417. // we will still get the correct aliases.
  418. //
  419. Status = IoGetDeviceInterfaceAlias(
  420. &ustrFilterName,
  421. apguidCategories[i],
  422. &ustrAliasName);
  423. if(NT_SUCCESS(Status)) {
  424. FOR_EACH_LIST_ITEM_DELETE(gplstFilterNode, pFilterNode) {
  425. if(pFilterNode->GetDeviceInterface() == NULL) {
  426. continue;
  427. }
  428. RtlInitUnicodeString(
  429. &ustrName,
  430. pFilterNode->GetDeviceInterface());
  431. if(RtlEqualUnicodeString(
  432. &ustrAliasName,
  433. &ustrName,
  434. TRUE)) {
  435. delete pFilterNode;
  436. DELETE_LIST_ITEM(gplstFilterNode);
  437. }
  438. } END_EACH_LIST_ITEM
  439. RtlFreeUnicodeString(&ustrAliasName);
  440. }
  441. }
  442. return(STATUS_SUCCESS);
  443. }
  444. #define GFX_VERBOSE_LEVEL 50
  445. NTSTATUS AddGfx(
  446. PSYSAUDIO_GFX pSysaudioGfx
  447. )
  448. {
  449. NTSTATUS Status;
  450. PFILE_OBJECT pFileObject;
  451. PFILTER_NODE pFilterNode;
  452. ULONG Flags;
  453. PWSTR pwstrDeviceName;
  454. ULONG Length;
  455. ULONG GfxOrderBase, GfxOrderCeiling;
  456. pFileObject = NULL;
  457. pwstrDeviceName = NULL;
  458. pFilterNode = NULL;
  459. GfxOrderBase = GfxOrderCeiling = 0;
  460. DPF1(GFX_VERBOSE_LEVEL, "AddGfx :: Request to add Gfx %x", pSysaudioGfx);
  461. DPF1(GFX_VERBOSE_LEVEL, " hGfx = %x", pSysaudioGfx->hGfx);
  462. DPF1(GFX_VERBOSE_LEVEL, " ulOrder = %x", pSysaudioGfx->ulOrder);
  463. DPF1(GFX_VERBOSE_LEVEL, " ulType = %x", pSysaudioGfx->ulType);
  464. DPF1(GFX_VERBOSE_LEVEL, " Flags = %x", pSysaudioGfx->ulFlags);
  465. //
  466. // validate type to be Capture or Render (use public include file!!!)
  467. //
  468. if ((pSysaudioGfx->ulType != GFX_DEVICETYPE_RENDER) && (pSysaudioGfx->ulType != GFX_DEVICETYPE_CAPTURE)) {
  469. Trap();
  470. Status = STATUS_INVALID_PARAMETER;
  471. goto exit;
  472. }
  473. //
  474. // Setup GFX Order's base & ceiling for future usage
  475. //
  476. if (pSysaudioGfx->ulType == GFX_DEVICETYPE_RENDER) {
  477. GfxOrderBase = ORDER_RENDER_GFX_FIRST;
  478. GfxOrderCeiling = ORDER_RENDER_GFX_LAST;
  479. }
  480. if (pSysaudioGfx->ulType == GFX_DEVICETYPE_CAPTURE) {
  481. GfxOrderBase = ORDER_CAPTURE_GFX_FIRST;
  482. GfxOrderCeiling = ORDER_CAPTURE_GFX_LAST;
  483. }
  484. ASSERT(GfxOrderBase);
  485. ASSERT(GfxOrderCeiling);
  486. //
  487. // validate that order is within range
  488. //
  489. if (pSysaudioGfx->ulOrder >= (GfxOrderCeiling - GfxOrderBase)) {
  490. Status = STATUS_INVALID_PARAMETER;
  491. Trap();
  492. goto exit;
  493. }
  494. //
  495. // Allocate a Filter Node for the new GFX
  496. //
  497. pFilterNode = new FILTER_NODE(FILTER_TYPE_GFX);
  498. if(pFilterNode == NULL) {
  499. Trap();
  500. Status = STATUS_INSUFFICIENT_RESOURCES;
  501. goto exit;
  502. }
  503. pFilterNode->SetRenderCaptureFlags(pSysaudioGfx->ulType);
  504. //
  505. // Copy the Device Name (on which the gfx needs to be attached) into a local copy for our own use
  506. //
  507. Status = SafeCopyStringFromOffset(pSysaudioGfx, pSysaudioGfx->ulDeviceNameOffset, &pwstrDeviceName);
  508. if (!NT_SUCCESS(Status)) {
  509. goto exit;
  510. }
  511. DPF1(GFX_VERBOSE_LEVEL, " On DI = %s", DbgUnicode2Sz(pwstrDeviceName));
  512. //
  513. // Make sure that there are no other GFXes with the same order on this device
  514. //
  515. if ((FindGfx(pFilterNode,
  516. 0, // wild card for handle
  517. pwstrDeviceName,
  518. pSysaudioGfx->ulOrder+GfxOrderBase))) {
  519. delete pwstrDeviceName;
  520. Status = STATUS_INVALID_PARAMETER;
  521. goto exit;
  522. }
  523. //
  524. // Get the FileObject of the GFX for future use
  525. //
  526. Status = ObReferenceObjectByHandle(
  527. pSysaudioGfx->hGfx,
  528. GENERIC_READ | GENERIC_WRITE,
  529. NULL,
  530. KernelMode,
  531. (PVOID*)&pFileObject,
  532. NULL);
  533. if (!NT_SUCCESS(Status)) {
  534. delete pwstrDeviceName;
  535. goto exit;
  536. }
  537. //
  538. // Add the device name string to global memory to be freed
  539. //
  540. Status = pFilterNode->lstFreeMem.AddList(pwstrDeviceName);
  541. if(!NT_SUCCESS(Status)) {
  542. Trap();
  543. delete pwstrDeviceName;
  544. goto exit;
  545. }
  546. //
  547. // Indicate that this Gfx needs be loaded only on the device pointed to be pwstrDeviceName
  548. //
  549. Status = pFilterNode->AddDeviceInterfaceMatch(pwstrDeviceName);
  550. if(!NT_SUCCESS(Status)) {
  551. Trap();
  552. goto exit;
  553. }
  554. //
  555. // Set the Gfx order in the filter node
  556. //
  557. pFilterNode->SetOrder(pSysaudioGfx->ulOrder+GfxOrderBase);
  558. //
  559. // Profile the GFX and create pin infos, logical filter nodes etc
  560. //
  561. Status = pFilterNode->ProfileFilter(pFileObject);
  562. if(!NT_SUCCESS(Status)) {
  563. Trap();
  564. goto exit;
  565. }
  566. //
  567. // Fix the GFX glitching problem. Send the property blindly to GFX
  568. // filter. KS will handle the property.
  569. // Failures are not important, ignore them.
  570. //
  571. SetKsFrameHolding(pFileObject);
  572. exit:
  573. if(!NT_SUCCESS(Status)) {
  574. DPF1(GFX_VERBOSE_LEVEL, "AddGfx :: Failed, Status = %x", Status);
  575. if(pFilterNode != NULL) {
  576. delete pFilterNode;
  577. pFilterNode = NULL;
  578. }
  579. if(pFileObject != NULL) {
  580. ObDereferenceObject(pFileObject);
  581. }
  582. }
  583. else {
  584. DPF1(GFX_VERBOSE_LEVEL, "AddGfx :: Added GFX FilterNode %x", pFilterNode);
  585. DPF1(GFX_VERBOSE_LEVEL, " order = %x", pFilterNode->GetOrder());
  586. DPF1(GFX_VERBOSE_LEVEL, " type = %x", pFilterNode->GetType());
  587. DPF1(GFX_VERBOSE_LEVEL, " flags = %x", pFilterNode->GetFlags());
  588. //
  589. // Setup file handle details for later use of
  590. // the user mode handle passed in
  591. //
  592. pFilterNode->SetFileDetails(pSysaudioGfx->hGfx,
  593. pFileObject,
  594. PsGetCurrentProcess());
  595. //
  596. // Force a rebuild of graph nodes
  597. //
  598. DestroyAllGraphs();
  599. }
  600. return(Status);
  601. }
  602. NTSTATUS RemoveGfx(
  603. PSYSAUDIO_GFX pSysaudioGfx
  604. )
  605. {
  606. NTSTATUS Status;
  607. PFILE_OBJECT pFileObject=NULL;
  608. PFILTER_NODE pFilterNode;
  609. ULONG Flags;
  610. PWSTR pwstrDeviceName;
  611. ULONG Length;
  612. ULONG GfxOrderBase, GfxOrderCeiling;
  613. GfxOrderBase = GfxOrderCeiling = 0;
  614. pwstrDeviceName = NULL;
  615. DPF1(GFX_VERBOSE_LEVEL, "RemoveGfx :: Request to remove Gfx %x", pSysaudioGfx);
  616. DPF1(GFX_VERBOSE_LEVEL, " hGfx = %x", pSysaudioGfx->hGfx);
  617. DPF1(GFX_VERBOSE_LEVEL, " ulOrder = %x", pSysaudioGfx->ulOrder);
  618. DPF1(GFX_VERBOSE_LEVEL, " ulType = %x", pSysaudioGfx->ulType);
  619. DPF1(GFX_VERBOSE_LEVEL, " Flags = %x", pSysaudioGfx->ulFlags);
  620. //
  621. // validate type to be Capture or Render (use public include file!!!)
  622. //
  623. if ((pSysaudioGfx->ulType != GFX_DEVICETYPE_RENDER) && (pSysaudioGfx->ulType != GFX_DEVICETYPE_CAPTURE)) {
  624. Trap();
  625. Status = STATUS_INVALID_PARAMETER;
  626. goto exit;
  627. }
  628. //
  629. // Setup GFX Order's base & ceiling for future usage
  630. //
  631. if (pSysaudioGfx->ulType == GFX_DEVICETYPE_RENDER) {
  632. GfxOrderBase = ORDER_RENDER_GFX_FIRST;
  633. GfxOrderCeiling = ORDER_RENDER_GFX_LAST;
  634. }
  635. if (pSysaudioGfx->ulType == GFX_DEVICETYPE_CAPTURE ) {
  636. GfxOrderBase = ORDER_CAPTURE_GFX_FIRST;
  637. GfxOrderCeiling = ORDER_CAPTURE_GFX_LAST;
  638. }
  639. ASSERT(GfxOrderBase);
  640. ASSERT(GfxOrderCeiling);
  641. //
  642. // Copy the Device Name (on which the gfx needs to be attached) into a local copy for our own use
  643. //
  644. Status = SafeCopyStringFromOffset(pSysaudioGfx, pSysaudioGfx->ulDeviceNameOffset, &pwstrDeviceName);
  645. if (!NT_SUCCESS(Status)) {
  646. goto exit;
  647. }
  648. DPF1(GFX_VERBOSE_LEVEL, " On DI = %s", DbgUnicode2Sz(pwstrDeviceName));
  649. //
  650. // Find the FilterNode for the Gfx
  651. //
  652. if ((pFilterNode = FindGfx(NULL,
  653. pSysaudioGfx->hGfx,
  654. pwstrDeviceName,
  655. pSysaudioGfx->ulOrder+GfxOrderBase)) == NULL) {
  656. Status = STATUS_INVALID_PARAMETER;
  657. goto exit;
  658. }
  659. //
  660. // Should we validate the FileHandle Value?
  661. //
  662. //
  663. // Dereference the file object
  664. //
  665. Status = pFilterNode->ClearFileDetails();
  666. exit:
  667. if(!NT_SUCCESS(Status)) {
  668. DPF1(GFX_VERBOSE_LEVEL, "RemoveGfx :: Failed, Status = %x", Status);
  669. Trap();
  670. }
  671. else {
  672. delete pFilterNode;
  673. }
  674. delete pwstrDeviceName;
  675. return(Status);
  676. }
  677. PFILTER_NODE
  678. FindGfx(
  679. PFILTER_NODE pnewFilterNode,
  680. HANDLE hGfx,
  681. PWSTR pwstrDeviceName,
  682. ULONG GfxOrder
  683. )
  684. {
  685. PFILTER_NODE pFilterNode;
  686. ULONG DeviceCount;
  687. UNICODE_STRING usInDevice, usfnDevice;
  688. PWSTR pwstr;
  689. DPF2(90, "FindGfx:: Looking for GFX with order = %x attached to %s)", GfxOrder, DbgUnicode2Sz(pwstrDeviceName));
  690. FOR_EACH_LIST_ITEM(gplstFilterNode, pFilterNode) {
  691. //
  692. // Skip the one we just added
  693. //
  694. if (pFilterNode == pnewFilterNode) {
  695. continue;
  696. }
  697. //
  698. // Check whether this pFilterNode matches the Gfx we are looking for
  699. //
  700. if (pFilterNode->DoesGfxMatch(hGfx, pwstrDeviceName, GfxOrder)) {
  701. return (pFilterNode);
  702. }
  703. } END_EACH_LIST_ITEM
  704. return(NULL);
  705. }
  706. NTSTATUS
  707. SafeCopyStringFromOffset(
  708. PVOID pBasePointer,
  709. ULONG Offset,
  710. PWSTR *String
  711. )
  712. {
  713. ULONG Length;
  714. PWSTR pwstrString = NULL;
  715. *String = NULL;
  716. __try {
  717. Length = wcslen( (PWSTR)(((CHAR *)pBasePointer)+Offset)) + 1;
  718. pwstrString = new(WCHAR[Length]) ;
  719. if(pwstrString == NULL) {
  720. return(STATUS_INSUFFICIENT_RESOURCES);
  721. }
  722. wcscpy(pwstrString,(PWSTR)(((CHAR *)pBasePointer)+Offset));
  723. } __except (EXCEPTION_EXECUTE_HANDLER) {
  724. Trap();
  725. delete [] pwstrString;
  726. return(STATUS_INVALID_PARAMETER);
  727. }
  728. *String = pwstrString;
  729. return(STATUS_SUCCESS);
  730. }
  731. NTSTATUS
  732. GetFilterTypeFromGuid(
  733. IN LPGUID pguid,
  734. OUT PULONG pfulType
  735. )
  736. {
  737. int i;
  738. for(i = 0; i < SIZEOF_ARRAY(apguidCategories); i++) {
  739. if (memcmp (apguidCategories[i], pguid, sizeof(GUID)) == 0) {
  740. *pfulType |= aulFilterType[i];
  741. return(STATUS_SUCCESS);
  742. }
  743. }
  744. return(STATUS_INVALID_DEVICE_REQUEST);
  745. }
  746. //---------------------------------------------------------------------------
  747. // End of File: notify.cpp
  748. //---------------------------------------------------------------------------