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.

457 lines
12 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. VfIrpLogDeleteDeviceLogs(DeviceObject);
  93. }
  94. VOID
  95. VfDevObjPreAddDevice(
  96. IN PDEVICE_OBJECT PhysicalDeviceObject,
  97. IN PDRIVER_OBJECT DriverObject,
  98. IN PDRIVER_ADD_DEVICE AddDeviceFunction,
  99. IN VF_DEVOBJ_TYPE DevObjType
  100. )
  101. /*++
  102. Description:
  103. This routine is called before the specified driver's AddDevice has been
  104. invoked.
  105. Arguments:
  106. PhysicalDeviceObject - Device object at the bottom of the PnP stack.
  107. DriverObject - Driver object of the driver who's AddDevice has been
  108. invoked.
  109. AddDeviceFunction - Address of the AddDevice routine.
  110. DevObjType - Type of device object (lower device filter, FDO, etc.)
  111. Return Value:
  112. None.
  113. --*/
  114. {
  115. VF_DEVOBJ_TYPE objType;
  116. UNREFERENCED_PARAMETER(AddDeviceFunction);
  117. if (!MmIsDriverVerifying(DriverObject)) {
  118. return;
  119. }
  120. if (VfSettingsIsOptionEnabled(NULL, VERIFIER_OPTION_INSERT_WDM_FILTERS)) {
  121. if (DevObjType == VF_DEVOBJ_FDO) {
  122. //
  123. // If we are calling AddDevice for the FDO, first attempt to attach
  124. // a lower class filter.
  125. //
  126. objType = VF_DEVOBJ_LOWER_CLASS_FILTER;
  127. } else {
  128. objType = DevObjType;
  129. }
  130. //
  131. // Attach a filter, cause pain.
  132. //
  133. VfFilterAttach(PhysicalDeviceObject, objType);
  134. }
  135. }
  136. VOID
  137. VfDevObjPostAddDevice(
  138. IN PDEVICE_OBJECT PhysicalDeviceObject,
  139. IN PDRIVER_OBJECT DriverObject,
  140. IN PDRIVER_ADD_DEVICE AddDeviceFunction,
  141. IN VF_DEVOBJ_TYPE DevObjType,
  142. IN NTSTATUS Result
  143. )
  144. /*++
  145. Description:
  146. This routine is called after the specified driver's AddDevice has been
  147. invoked.
  148. Arguments:
  149. PhysicalDeviceObject - Device object at the bottom of the PnP stack.
  150. DriverObject - Driver object of the driver who's AddDevice has been
  151. invoked.
  152. AddDeviceFunction - Address of the AddDevice routine.
  153. DevObjType - Type of device object (lower device filter, FDO, etc.)
  154. Result - Result returned by the AddDevice Routine
  155. Return Value:
  156. None.
  157. --*/
  158. {
  159. PDEVICE_OBJECT deviceAbove, deviceBelow;
  160. BOOLEAN powerFailure;
  161. VF_DEVOBJ_TYPE objType;
  162. UNREFERENCED_PARAMETER(DriverObject);
  163. if (NT_SUCCESS(Result) &&
  164. VfSettingsIsOptionEnabled(NULL, VERIFIER_OPTION_INSERT_WDM_FILTERS) &&
  165. MmIsDriverVerifying(DriverObject)) {
  166. if (DevObjType == VF_DEVOBJ_FDO) {
  167. //
  168. // If we've just attached an FDO, try to add a upper device filter
  169. // on top of it.
  170. //
  171. objType = VF_DEVOBJ_UPPER_DEVICE_FILTER;
  172. } else {
  173. objType = DevObjType;
  174. }
  175. //
  176. // Attach filter, cause pain.
  177. //
  178. VfFilterAttach(PhysicalDeviceObject, objType);
  179. }
  180. if (!VfSettingsIsOptionEnabled(NULL, VERIFIER_OPTION_VERIFY_DO_FLAGS)) {
  181. return;
  182. }
  183. //
  184. // Take this opportunity to check the PDO.
  185. //
  186. if (!IovUtilIsDeviceObjectMarked(PhysicalDeviceObject, MARKTYPE_DEVICE_CHECKED)) {
  187. if ((PhysicalDeviceObject->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO)) ==
  188. (DO_BUFFERED_IO | DO_DIRECT_IO)) {
  189. //
  190. // Both direct I/O and buffered I/O are set. These are mutually
  191. // exclusive.
  192. //
  193. WDM_FAIL_ROUTINE((
  194. DCERROR_INCONSISTANT_DO_FLAGS,
  195. DCPARAM_ROUTINE + DCPARAM_DEVOBJ,
  196. PhysicalDeviceObject->DriverObject->DriverExtension->AddDevice,
  197. PhysicalDeviceObject
  198. ));
  199. }
  200. //
  201. // No need to check DO_DEVICE_INITIALIZING as PDO's get them cleared
  202. // automagically.
  203. //
  204. IovUtilMarkDeviceObject(PhysicalDeviceObject, MARKTYPE_DEVICE_CHECKED);
  205. }
  206. powerFailure = FALSE;
  207. deviceBelow = PhysicalDeviceObject;
  208. ObReferenceObject(deviceBelow);
  209. while(1) {
  210. IovUtilGetUpperDeviceObject(deviceBelow, &deviceAbove);
  211. if (deviceAbove == NULL) {
  212. ObDereferenceObject(deviceBelow);
  213. break;
  214. }
  215. if (!IovUtilIsDeviceObjectMarked(deviceAbove, MARKTYPE_DEVICE_CHECKED)) {
  216. if ((deviceAbove->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO)) ==
  217. (DO_BUFFERED_IO | DO_DIRECT_IO)) {
  218. //
  219. // Both direct I/O and buffered I/O are set. These are mutually
  220. // exclusive.
  221. //
  222. WDM_FAIL_ROUTINE((
  223. DCERROR_INCONSISTANT_DO_FLAGS,
  224. DCPARAM_ROUTINE + DCPARAM_DEVOBJ,
  225. AddDeviceFunction,
  226. deviceAbove
  227. ));
  228. }
  229. if (deviceAbove->Flags & DO_DEVICE_INITIALIZING) {
  230. //
  231. // A device didn't clear the DO_DEVICE_INITIALIZING flag during
  232. // AddDevice. Fail it now.
  233. //
  234. WDM_FAIL_ROUTINE((
  235. DCERROR_DO_INITIALIZING_NOT_CLEARED,
  236. DCPARAM_ROUTINE + DCPARAM_DEVOBJ,
  237. AddDeviceFunction,
  238. deviceAbove
  239. ));
  240. //
  241. // Clean up the mess.
  242. //
  243. deviceAbove->Flags &= ~DO_DEVICE_INITIALIZING;
  244. }
  245. if ((deviceBelow->Flags & DO_POWER_PAGABLE) &&
  246. (!(deviceAbove->Flags & DO_POWER_PAGABLE))) {
  247. if (!powerFailure) {
  248. //
  249. // We have caught a driver bug. deviceAbove didn't inherit the
  250. // DO_POWER_PAGABLE flag.
  251. //
  252. WDM_FAIL_ROUTINE((
  253. DCERROR_POWER_PAGABLE_NOT_INHERITED,
  254. DCPARAM_ROUTINE + DCPARAM_DEVOBJ,
  255. AddDeviceFunction,
  256. deviceAbove
  257. ));
  258. //
  259. // Don't blame anyone else.
  260. //
  261. powerFailure = TRUE;
  262. }
  263. deviceAbove->Flags |= DO_POWER_PAGABLE;
  264. }
  265. if ((deviceBelow->Flags & DO_BUFFERED_IO) &&
  266. (!(deviceAbove->Flags & DO_BUFFERED_IO))) {
  267. //
  268. // Buffered I/O flag not copied. Broken filter!
  269. //
  270. WDM_FAIL_ROUTINE((
  271. DCERROR_DO_FLAG_NOT_COPIED,
  272. DCPARAM_ROUTINE + DCPARAM_DEVOBJ,
  273. AddDeviceFunction,
  274. deviceAbove
  275. ));
  276. }
  277. if ((deviceBelow->Flags & DO_DIRECT_IO) &&
  278. (!(deviceAbove->Flags & DO_DIRECT_IO))) {
  279. //
  280. // Direct I/O flag not copied. Broken filter!
  281. //
  282. WDM_FAIL_ROUTINE((
  283. DCERROR_DO_FLAG_NOT_COPIED,
  284. DCPARAM_ROUTINE + DCPARAM_DEVOBJ,
  285. AddDeviceFunction,
  286. deviceAbove
  287. ));
  288. }
  289. if ((deviceBelow->DeviceType != FILE_DEVICE_UNKNOWN) &&
  290. (deviceAbove->DeviceType == FILE_DEVICE_UNKNOWN)) {
  291. //
  292. // The device type wasn't copied by a filter!
  293. //
  294. WDM_FAIL_ROUTINE((
  295. DCERROR_DEVICE_TYPE_NOT_COPIED,
  296. DCPARAM_ROUTINE + DCPARAM_DEVOBJ,
  297. AddDeviceFunction,
  298. deviceAbove
  299. ));
  300. }
  301. //
  302. // Characteristics don't have to be checked because PnP takes care
  303. // of propogating them appropriately.
  304. //
  305. }
  306. IovUtilMarkDeviceObject(deviceAbove, MARKTYPE_DEVICE_CHECKED);
  307. ObDereferenceObject(deviceBelow);
  308. deviceBelow = deviceAbove;
  309. }
  310. }
  311. VOID
  312. VfDevObjAdjustFdoForVerifierFilters(
  313. IN OUT PDEVICE_OBJECT *FunctionalDeviceObject
  314. )
  315. /*++
  316. Description:
  317. This routine adjusts the designated FDO to take into account any verifier
  318. filter DO's added by this file.
  319. Arguments:
  320. FunctionalDeviceObject - On input, contains FDO. Adjusted to point to the
  321. correct FDO if verifier added a filter.
  322. Return Value:
  323. None.
  324. --*/
  325. {
  326. PDEVICE_OBJECT fdo;
  327. fdo = *FunctionalDeviceObject;
  328. if (VfFilterIsVerifierFilterObject(fdo)) {
  329. fdo = fdo->AttachedDevice;
  330. ASSERT(fdo);
  331. *FunctionalDeviceObject = fdo;
  332. }
  333. }