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.

340 lines
8.3 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Module: fni.cpp
  4. //
  5. // Description:
  6. //
  7. // Filter Node Instance
  8. //
  9. //@@BEGIN_MSINTERNAL
  10. // Development Team:
  11. // Mike McLaughlin
  12. //
  13. // History: Date Author Comment
  14. //
  15. // To Do: Date Author Comment
  16. //
  17. //@@END_MSINTERNAL
  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. CFilterNodeInstance::~CFilterNodeInstance(
  31. )
  32. {
  33. Assert(this);
  34. DPF1(95, "~CFilterNodeInstance: %08x", this);
  35. RemoveListCheck();
  36. UnregisterTargetDeviceChangeNotification();
  37. //
  38. // if hFilter == NULL && pFileObject != NULL
  39. // it means that this filter instance is for a GFX
  40. // do not try to dereference the file object in that case
  41. //
  42. if( (hFilter != NULL) && (pFileObject != NULL) ) {
  43. AssertFileObject(pFileObject);
  44. ObDereferenceObject(pFileObject);
  45. }
  46. if(hFilter != NULL) {
  47. AssertStatus(ZwClose(hFilter));
  48. }
  49. }
  50. NTSTATUS
  51. CFilterNodeInstance::Create(
  52. PFILTER_NODE_INSTANCE *ppFilterNodeInstance,
  53. PLOGICAL_FILTER_NODE pLogicalFilterNode,
  54. PDEVICE_NODE pDeviceNode,
  55. BOOL fReuseInstance
  56. )
  57. {
  58. PFILTER_NODE_INSTANCE pFilterNodeInstance = NULL;
  59. PLOGICAL_FILTER_NODE pLogicalFilterNode2;
  60. NTSTATUS Status = STATUS_SUCCESS;
  61. Assert(pLogicalFilterNode);
  62. Assert(pLogicalFilterNode->pFilterNode);
  63. if(pLogicalFilterNode->GetType() & FILTER_TYPE_AEC) {
  64. FOR_EACH_LIST_ITEM(
  65. &pLogicalFilterNode->pFilterNode->lstLogicalFilterNode,
  66. pLogicalFilterNode2) {
  67. FOR_EACH_LIST_ITEM(
  68. &pLogicalFilterNode2->lstFilterNodeInstance,
  69. pFilterNodeInstance) {
  70. pFilterNodeInstance->AddRef();
  71. ASSERT(NT_SUCCESS(Status));
  72. goto exit;
  73. } END_EACH_LIST_ITEM
  74. } END_EACH_LIST_ITEM
  75. }
  76. else {
  77. if(fReuseInstance) {
  78. FOR_EACH_LIST_ITEM(
  79. &pLogicalFilterNode->lstFilterNodeInstance,
  80. pFilterNodeInstance) {
  81. if(pDeviceNode == NULL ||
  82. pDeviceNode == pFilterNodeInstance->pDeviceNode) {
  83. pFilterNodeInstance->AddRef();
  84. ASSERT(NT_SUCCESS(Status));
  85. goto exit;
  86. }
  87. } END_EACH_LIST_ITEM
  88. }
  89. }
  90. Status = Create(&pFilterNodeInstance, pLogicalFilterNode->pFilterNode);
  91. if(!NT_SUCCESS(Status)) {
  92. goto exit;
  93. }
  94. pFilterNodeInstance->pDeviceNode = pDeviceNode;
  95. pFilterNodeInstance->AddList(&pLogicalFilterNode->lstFilterNodeInstance);
  96. exit:
  97. *ppFilterNodeInstance = pFilterNodeInstance;
  98. return(Status);
  99. }
  100. NTSTATUS
  101. CFilterNodeInstance::Create(
  102. PFILTER_NODE_INSTANCE *ppFilterNodeInstance,
  103. PFILTER_NODE pFilterNode
  104. )
  105. {
  106. PFILTER_NODE_INSTANCE pFilterNodeInstance = NULL;
  107. NTSTATUS Status = STATUS_SUCCESS;
  108. Assert(pFilterNode);
  109. pFilterNodeInstance = new FILTER_NODE_INSTANCE;
  110. if(pFilterNodeInstance == NULL) {
  111. Status = STATUS_INSUFFICIENT_RESOURCES;
  112. goto exit;
  113. }
  114. pFilterNodeInstance->pFilterNode = pFilterNode;
  115. pFilterNodeInstance->AddRef();
  116. if(pFilterNode->GetType() & FILTER_TYPE_GFX) {
  117. //
  118. // if it is a GFX do not try to open the device, just re-use
  119. // the file object which we cached during AddGfx
  120. //
  121. pFilterNodeInstance->pFileObject = pFilterNode->GetFileObject();
  122. pFilterNodeInstance->hFilter = NULL;
  123. Status = STATUS_SUCCESS;
  124. }
  125. else {
  126. //
  127. // if it is not a GFX go ahead and open the device.
  128. //
  129. Status = pFilterNode->OpenDevice(&pFilterNodeInstance->hFilter);
  130. }
  131. if(!NT_SUCCESS(Status)) {
  132. DPF2(10, "CFilterNodeInstance::Create OpenDevice Failed: %08x FN: %08x",
  133. Status,
  134. pFilterNode);
  135. pFilterNodeInstance->hFilter = NULL;
  136. goto exit;
  137. }
  138. if (pFilterNodeInstance->hFilter) {
  139. Status = ObReferenceObjectByHandle(
  140. pFilterNodeInstance->hFilter,
  141. GENERIC_READ | GENERIC_WRITE,
  142. NULL,
  143. KernelMode,
  144. (PVOID*)&pFilterNodeInstance->pFileObject,
  145. NULL);
  146. }
  147. if(!NT_SUCCESS(Status)) {
  148. Trap();
  149. pFilterNodeInstance->pFileObject = NULL;
  150. goto exit;
  151. }
  152. AssertFileObject(pFilterNodeInstance->pFileObject);
  153. Status = pFilterNodeInstance->RegisterTargetDeviceChangeNotification();
  154. if(!NT_SUCCESS(Status)) {
  155. goto exit;
  156. }
  157. DPF2(95, "CFilterNodeInstance::Create %08x FN: %08x",
  158. pFilterNodeInstance,
  159. pFilterNode);
  160. exit:
  161. if(!NT_SUCCESS(Status)) {
  162. if (pFilterNodeInstance) {
  163. pFilterNodeInstance->Destroy();
  164. }
  165. pFilterNodeInstance = NULL;
  166. }
  167. *ppFilterNodeInstance = pFilterNodeInstance;
  168. return(Status);
  169. }
  170. //---------------------------------------------------------------------------
  171. NTSTATUS
  172. CFilterNodeInstance::RegisterTargetDeviceChangeNotification(
  173. )
  174. {
  175. NTSTATUS Status;
  176. ASSERT(gpDeviceInstance != NULL);
  177. ASSERT(gpDeviceInstance->pPhysicalDeviceObject != NULL);
  178. ASSERT(pNotificationHandle == NULL);
  179. Status = IoRegisterPlugPlayNotification(
  180. EventCategoryTargetDeviceChange,
  181. 0,
  182. pFileObject,
  183. gpDeviceInstance->pPhysicalDeviceObject->DriverObject,
  184. (NTSTATUS (*)(PVOID, PVOID))
  185. CFilterNodeInstance::TargetDeviceChangeNotification,
  186. this,
  187. &pNotificationHandle);
  188. if(!NT_SUCCESS(Status)) {
  189. if(Status != STATUS_NOT_IMPLEMENTED) {
  190. goto exit;
  191. }
  192. Status = STATUS_SUCCESS;
  193. }
  194. DPF2(100, "RegisterTargetDeviceChangeNotification: FNI: %08x PFO: %08x",
  195. this,
  196. this->pFileObject);
  197. exit:
  198. return(Status);
  199. }
  200. VOID
  201. CFilterNodeInstance::UnregisterTargetDeviceChangeNotification(
  202. )
  203. {
  204. HANDLE hNotification;
  205. DPF1(100, "UnregisterTargetDeviceChangeNotification: FNI: %08x", this);
  206. hNotification = pNotificationHandle;
  207. if(hNotification != NULL) {
  208. pNotificationHandle = NULL;
  209. IoUnregisterPlugPlayNotification(hNotification);
  210. }
  211. }
  212. NTSTATUS
  213. CFilterNodeInstance::DeviceQueryRemove(
  214. )
  215. {
  216. PGRAPH_NODE_INSTANCE pGraphNodeInstance;
  217. PDEVICE_NODE pDeviceNode;
  218. PGRAPH_NODE pGraphNode;
  219. FOR_EACH_LIST_ITEM(gplstDeviceNode, pDeviceNode) {
  220. FOR_EACH_LIST_ITEM(&pDeviceNode->lstGraphNode, pGraphNode) {
  221. FOR_EACH_LIST_ITEM(
  222. &pGraphNode->lstGraphNodeInstance,
  223. pGraphNodeInstance) {
  224. for(ULONG n = 0;
  225. n < pGraphNodeInstance->Topology.TopologyNodesCount;
  226. n++) {
  227. pGraphNodeInstance->
  228. papFilterNodeInstanceTopologyTable[n]->Destroy();
  229. pGraphNodeInstance->
  230. papFilterNodeInstanceTopologyTable[n] = NULL;
  231. }
  232. } END_EACH_LIST_ITEM
  233. } END_EACH_LIST_ITEM
  234. } END_EACH_LIST_ITEM
  235. return(STATUS_SUCCESS);
  236. }
  237. NTSTATUS
  238. CFilterNodeInstance::TargetDeviceChangeNotification(
  239. IN PTARGET_DEVICE_REMOVAL_NOTIFICATION pNotification,
  240. IN PFILTER_NODE_INSTANCE pFilterNodeInstance
  241. )
  242. {
  243. DPF3(5, "TargetDeviceChangeNotification: FNI: %08x PFO: %08x %s",
  244. pFilterNodeInstance,
  245. pNotification->FileObject,
  246. DbgGuid2Sz(&pNotification->Event));
  247. if(IsEqualGUID(
  248. &pNotification->Event,
  249. &GUID_TARGET_DEVICE_REMOVE_COMPLETE) ||
  250. IsEqualGUID(
  251. &pNotification->Event,
  252. &GUID_TARGET_DEVICE_QUERY_REMOVE)) {
  253. NTSTATUS Status = STATUS_SUCCESS;
  254. LARGE_INTEGER li = {0, 10000}; // wait for 1 ms
  255. Status = KeWaitForMutexObject(
  256. &gMutex,
  257. Executive,
  258. KernelMode,
  259. FALSE,
  260. &li);
  261. if(Status != STATUS_TIMEOUT) {
  262. DeviceQueryRemove();
  263. ReleaseMutex();
  264. }
  265. else {
  266. DPF1(5, "TargetDeviceChangeNotification: FAILED %08x", Status);
  267. }
  268. }
  269. return(STATUS_SUCCESS);
  270. }
  271. //---------------------------------------------------------------------------
  272. #ifdef DEBUG
  273. ENUMFUNC
  274. CFilterNodeInstance::Dump(
  275. )
  276. {
  277. if(this == NULL) {
  278. return(STATUS_CONTINUE);
  279. }
  280. if(ulDebugFlags & (DEBUG_FLAGS_VERBOSE | DEBUG_FLAGS_OBJECT)) {
  281. dprintf("FNI: %08x cRef %02x FO %08x H %08x DN %08x FN %08x NH %08x\n",
  282. this,
  283. cReference,
  284. pFileObject,
  285. hFilter,
  286. pDeviceNode,
  287. pFilterNode,
  288. pNotificationHandle);
  289. dprintf(" %s\n", pFilterNode->DumpName());
  290. }
  291. return(STATUS_CONTINUE);
  292. }
  293. #endif
  294. //---------------------------------------------------------------------------