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.

455 lines
11 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. vfdevobj.c
  5. Abstract:
  6. This module verifies drivers properly manage device objects.
  7. Author:
  8. Adrian J. Oney (adriao) 09-May-1998
  9. Environment:
  10. Kernel mode
  11. Revision History:
  12. AdriaO 05/02/2000 - Seperated out from ntos\io\trackirp.c
  13. --*/
  14. //
  15. // Disable W4 level warnings generated by public headers.
  16. //
  17. #include "vfpragma.h"
  18. #include "..\io\iop.h" // Includes vfdef.h
  19. #if (( defined(_X86_) ) && ( FPO ))
  20. #pragma optimize( "y", off ) // disable FPO for consistent stack traces
  21. #endif
  22. #ifdef ALLOC_PRAGMA
  23. #pragma alloc_text(PAGEVRFY, VerifierIoAttachDeviceToDeviceStack)
  24. #pragma alloc_text(PAGEVRFY, VerifierIoDetachDevice)
  25. #pragma alloc_text(PAGEVRFY, VerifierIoDeleteDevice)
  26. #pragma alloc_text(PAGEVRFY, VfDevObjPreAddDevice)
  27. #pragma alloc_text(PAGEVRFY, VfDevObjPostAddDevice)
  28. #pragma alloc_text(PAGEVRFY, VfDevObjAdjustFdoForVerifierFilters)
  29. #endif
  30. VOID
  31. VerifierIoAttachDeviceToDeviceStack(
  32. IN PDEVICE_OBJECT NewDevice,
  33. IN PDEVICE_OBJECT ExistingDevice
  34. )
  35. {
  36. UNREFERENCED_PARAMETER (NewDevice);
  37. IovUtilFlushStackCache(ExistingDevice, DATABASELOCKSTATE_HELD);
  38. }
  39. VOID
  40. VerifierIoDetachDevice(
  41. IN PDEVICE_OBJECT LowerDevice
  42. )
  43. {
  44. PVOID callerAddress;
  45. ULONG stackHash;
  46. if (LowerDevice->AttachedDevice == NULL) {
  47. if (RtlCaptureStackBackTrace(2, 1, &callerAddress, &stackHash) != 1) {
  48. callerAddress = NULL;
  49. }
  50. WDM_FAIL_ROUTINE((
  51. DCERROR_DETACH_NOT_ATTACHED,
  52. DCPARAM_ROUTINE + DCPARAM_DEVOBJ,
  53. callerAddress,
  54. LowerDevice
  55. ));
  56. }
  57. IovUtilFlushStackCache(LowerDevice, DATABASELOCKSTATE_HELD);
  58. }
  59. VOID
  60. VerifierIoDeleteDevice(
  61. IN PDEVICE_OBJECT DeviceObject
  62. )
  63. {
  64. PDEVICE_OBJECT deviceBelow;
  65. PVOID callerAddress;
  66. ULONG stackHash;
  67. if (RtlCaptureStackBackTrace(2, 1, &callerAddress, &stackHash) != 1) {
  68. callerAddress = NULL;
  69. }
  70. //
  71. // ADRIAO N.B. 06/16/2000 - A good thing to do here would be to send a
  72. // second remove IRP to every deleted device object that was a member
  73. // of a WDM device stack. Just to check.
  74. //
  75. if (IovUtilIsDeviceObjectMarked(DeviceObject, MARKTYPE_DELETED)) {
  76. WDM_FAIL_ROUTINE((
  77. DCERROR_DOUBLE_DELETION,
  78. DCPARAM_ROUTINE,
  79. callerAddress
  80. ));
  81. }
  82. IovUtilMarkDeviceObject(DeviceObject, MARKTYPE_DELETED);
  83. IovUtilGetLowerDeviceObject(DeviceObject, &deviceBelow);
  84. if (deviceBelow) {
  85. WDM_FAIL_ROUTINE((
  86. DCERROR_DELETE_WHILE_ATTACHED,
  87. DCPARAM_ROUTINE,
  88. callerAddress
  89. ));
  90. ObDereferenceObject(deviceBelow);
  91. }
  92. }
  93. VOID
  94. VfDevObjPreAddDevice(
  95. IN PDEVICE_OBJECT PhysicalDeviceObject,
  96. IN PDRIVER_OBJECT DriverObject,
  97. IN PDRIVER_ADD_DEVICE AddDeviceFunction,
  98. IN VF_DEVOBJ_TYPE DevObjType
  99. )
  100. /*++
  101. Description:
  102. This routine is called before the specified driver's AddDevice has been
  103. invoked.
  104. Arguments:
  105. PhysicalDeviceObject - Device object at the bottom of the PnP stack.
  106. DriverObject - Driver object of the driver who's AddDevice has been
  107. invoked.
  108. AddDeviceFunction - Address of the AddDevice routine.
  109. DevObjType - Type of device object (lower device filter, FDO, etc.)
  110. Return Value:
  111. None.
  112. --*/
  113. {
  114. VF_DEVOBJ_TYPE objType;
  115. UNREFERENCED_PARAMETER(AddDeviceFunction);
  116. if (!MmIsDriverVerifying(DriverObject)) {
  117. return;
  118. }
  119. if (VfSettingsIsOptionEnabled(NULL, VERIFIER_OPTION_INSERT_WDM_FILTERS)) {
  120. if (DevObjType == VF_DEVOBJ_FDO) {
  121. //
  122. // If we are calling AddDevice for the FDO, first attempt to attach
  123. // a lower class filter.
  124. //
  125. objType = VF_DEVOBJ_LOWER_CLASS_FILTER;
  126. } else {
  127. objType = DevObjType;
  128. }
  129. //
  130. // Attach a filter, cause pain.
  131. //
  132. VfDriverAttachFilter(PhysicalDeviceObject, objType);
  133. }
  134. }
  135. VOID
  136. VfDevObjPostAddDevice(
  137. IN PDEVICE_OBJECT PhysicalDeviceObject,
  138. IN PDRIVER_OBJECT DriverObject,
  139. IN PDRIVER_ADD_DEVICE AddDeviceFunction,
  140. IN VF_DEVOBJ_TYPE DevObjType,
  141. IN NTSTATUS Result
  142. )
  143. /*++
  144. Description:
  145. This routine is called after the specified driver's AddDevice has been
  146. invoked.
  147. Arguments:
  148. PhysicalDeviceObject - Device object at the bottom of the PnP stack.
  149. DriverObject - Driver object of the driver who's AddDevice has been
  150. invoked.
  151. AddDeviceFunction - Address of the AddDevice routine.
  152. DevObjType - Type of device object (lower device filter, FDO, etc.)
  153. Result - Result returned by the AddDevice Routine
  154. Return Value:
  155. None.
  156. --*/
  157. {
  158. PDEVICE_OBJECT deviceAbove, deviceBelow;
  159. BOOLEAN powerFailure;
  160. VF_DEVOBJ_TYPE objType;
  161. UNREFERENCED_PARAMETER(DriverObject);
  162. if (NT_SUCCESS(Result) &&
  163. VfSettingsIsOptionEnabled(NULL, VERIFIER_OPTION_INSERT_WDM_FILTERS) &&
  164. MmIsDriverVerifying(DriverObject)) {
  165. if (DevObjType == VF_DEVOBJ_FDO) {
  166. //
  167. // If we've just attached an FDO, try to add a upper device filter
  168. // on top of it.
  169. //
  170. objType = VF_DEVOBJ_UPPER_DEVICE_FILTER;
  171. } else {
  172. objType = DevObjType;
  173. }
  174. //
  175. // Attach filter, cause pain.
  176. //
  177. VfDriverAttachFilter(PhysicalDeviceObject, objType);
  178. }
  179. if (!VfSettingsIsOptionEnabled(NULL, VERIFIER_OPTION_VERIFY_DO_FLAGS)) {
  180. return;
  181. }
  182. //
  183. // Take this opportunity to check the PDO.
  184. //
  185. if (!IovUtilIsDeviceObjectMarked(PhysicalDeviceObject, MARKTYPE_DEVICE_CHECKED)) {
  186. if ((PhysicalDeviceObject->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO)) ==
  187. (DO_BUFFERED_IO | DO_DIRECT_IO)) {
  188. //
  189. // Both direct I/O and buffered I/O are set. These are mutually
  190. // exclusive.
  191. //
  192. WDM_FAIL_ROUTINE((
  193. DCERROR_INCONSISTANT_DO_FLAGS,
  194. DCPARAM_ROUTINE + DCPARAM_DEVOBJ,
  195. PhysicalDeviceObject->DriverObject->DriverExtension->AddDevice,
  196. PhysicalDeviceObject
  197. ));
  198. }
  199. //
  200. // No need to check DO_DEVICE_INITIALIZING as PDO's get them cleared
  201. // automagically.
  202. //
  203. IovUtilMarkDeviceObject(PhysicalDeviceObject, MARKTYPE_DEVICE_CHECKED);
  204. }
  205. powerFailure = FALSE;
  206. deviceBelow = PhysicalDeviceObject;
  207. ObReferenceObject(deviceBelow);
  208. while(1) {
  209. IovUtilGetUpperDeviceObject(deviceBelow, &deviceAbove);
  210. if (deviceAbove == NULL) {
  211. ObDereferenceObject(deviceBelow);
  212. break;
  213. }
  214. if (!IovUtilIsDeviceObjectMarked(deviceAbove, MARKTYPE_DEVICE_CHECKED)) {
  215. if ((deviceAbove->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO)) ==
  216. (DO_BUFFERED_IO | DO_DIRECT_IO)) {
  217. //
  218. // Both direct I/O and buffered I/O are set. These are mutually
  219. // exclusive.
  220. //
  221. WDM_FAIL_ROUTINE((
  222. DCERROR_INCONSISTANT_DO_FLAGS,
  223. DCPARAM_ROUTINE + DCPARAM_DEVOBJ,
  224. AddDeviceFunction,
  225. deviceAbove
  226. ));
  227. }
  228. if (deviceAbove->Flags & DO_DEVICE_INITIALIZING) {
  229. //
  230. // A device didn't clear the DO_DEVICE_INITIALIZING flag during
  231. // AddDevice. Fail it now.
  232. //
  233. WDM_FAIL_ROUTINE((
  234. DCERROR_DO_INITIALIZING_NOT_CLEARED,
  235. DCPARAM_ROUTINE + DCPARAM_DEVOBJ,
  236. AddDeviceFunction,
  237. deviceAbove
  238. ));
  239. //
  240. // Clean up the mess.
  241. //
  242. deviceAbove->Flags &= ~DO_DEVICE_INITIALIZING;
  243. }
  244. if ((deviceBelow->Flags & DO_POWER_PAGABLE) &&
  245. (!(deviceAbove->Flags & DO_POWER_PAGABLE))) {
  246. if (!powerFailure) {
  247. //
  248. // We have caught a driver bug. deviceAbove didn't inherit the
  249. // DO_POWER_PAGABLE flag.
  250. //
  251. WDM_FAIL_ROUTINE((
  252. DCERROR_POWER_PAGABLE_NOT_INHERITED,
  253. DCPARAM_ROUTINE + DCPARAM_DEVOBJ,
  254. AddDeviceFunction,
  255. deviceAbove
  256. ));
  257. //
  258. // Don't blame anyone else.
  259. //
  260. powerFailure = TRUE;
  261. }
  262. deviceAbove->Flags |= DO_POWER_PAGABLE;
  263. }
  264. if ((deviceBelow->Flags & DO_BUFFERED_IO) &&
  265. (!(deviceAbove->Flags & DO_BUFFERED_IO))) {
  266. //
  267. // Buffered I/O flag not copied. Broken filter!
  268. //
  269. WDM_FAIL_ROUTINE((
  270. DCERROR_DO_FLAG_NOT_COPIED,
  271. DCPARAM_ROUTINE + DCPARAM_DEVOBJ,
  272. AddDeviceFunction,
  273. deviceAbove
  274. ));
  275. }
  276. if ((deviceBelow->Flags & DO_DIRECT_IO) &&
  277. (!(deviceAbove->Flags & DO_DIRECT_IO))) {
  278. //
  279. // Direct I/O flag not copied. Broken filter!
  280. //
  281. WDM_FAIL_ROUTINE((
  282. DCERROR_DO_FLAG_NOT_COPIED,
  283. DCPARAM_ROUTINE + DCPARAM_DEVOBJ,
  284. AddDeviceFunction,
  285. deviceAbove
  286. ));
  287. }
  288. if ((deviceBelow->DeviceType != FILE_DEVICE_UNKNOWN) &&
  289. (deviceAbove->DeviceType == FILE_DEVICE_UNKNOWN)) {
  290. //
  291. // The device type wasn't copied by a filter!
  292. //
  293. WDM_FAIL_ROUTINE((
  294. DCERROR_DEVICE_TYPE_NOT_COPIED,
  295. DCPARAM_ROUTINE + DCPARAM_DEVOBJ,
  296. AddDeviceFunction,
  297. deviceAbove
  298. ));
  299. }
  300. //
  301. // Characteristics don't have to be checked because PnP takes care
  302. // of propogating them appropriately.
  303. //
  304. }
  305. IovUtilMarkDeviceObject(deviceAbove, MARKTYPE_DEVICE_CHECKED);
  306. ObDereferenceObject(deviceBelow);
  307. deviceBelow = deviceAbove;
  308. }
  309. }
  310. VOID
  311. VfDevObjAdjustFdoForVerifierFilters(
  312. IN OUT PDEVICE_OBJECT *FunctionalDeviceObject
  313. )
  314. /*++
  315. Description:
  316. This routine adjusts the designated FDO to take into account any verifier
  317. filter DO's added by this file.
  318. Arguments:
  319. FunctionalDeviceObject - On input, contains FDO. Adjusted to point to the
  320. correct FDO if verifier added a filter.
  321. Return Value:
  322. None.
  323. --*/
  324. {
  325. PDEVICE_OBJECT fdo;
  326. fdo = *FunctionalDeviceObject;
  327. if (VfDriverIsVerifierFilterObject(fdo)) {
  328. fdo = fdo->AttachedDevice;
  329. ASSERT(fdo);
  330. *FunctionalDeviceObject = fdo;
  331. }
  332. }