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.

473 lines
12 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. validate.c
  5. Abstract: USB lower filter driver
  6. Author:
  7. Kenneth D. Ray
  8. Environment:
  9. Kernel mode
  10. Revision History:
  11. --*/
  12. #include <WDM.H>
  13. #include "valueadd.H"
  14. #include "local.h"
  15. struct _VA_GLOBALS Global;
  16. NTSTATUS DriverEntry (PDRIVER_OBJECT, PUNICODE_STRING);
  17. #ifdef ALLOC_PRAGMA
  18. #pragma alloc_text (INIT, DriverEntry)
  19. #pragma alloc_text (PAGE, VA_CreateClose)
  20. #pragma alloc_text (PAGE, VA_AddDevice)
  21. #pragma alloc_text (PAGE, VA_Unload)
  22. #endif
  23. NTSTATUS
  24. DriverEntry(
  25. IN PDRIVER_OBJECT DriverObject,
  26. IN PUNICODE_STRING RegistryPath
  27. )
  28. /*++
  29. Routine Description:
  30. Installable driver initialization entry point.
  31. This entry point is called directly by the I/O system.
  32. Arguments:
  33. DriverObject - pointer to the driver object
  34. registryPath - pointer to a unicode string representing the path,
  35. to driver-specific key in the registry.
  36. Return Value:
  37. STATUS_SUCCESS if successful,
  38. STATUS_UNSUCCESSFUL otherwise
  39. --*/
  40. {
  41. NTSTATUS status = STATUS_SUCCESS;
  42. PDEVICE_OBJECT deviceObject;
  43. UNICODE_STRING uniNtNameString;
  44. UNICODE_STRING uniWin32NameString;
  45. PVA_CONTROL_DATA deviceData;
  46. ULONG i;
  47. PDRIVER_DISPATCH * dispatch;
  48. UNREFERENCED_PARAMETER (RegistryPath);
  49. VA_KdPrint (("Entered the Driver Entry\n"));
  50. RtlInitUnicodeString (&uniNtNameString, VA_FILTER_NTNAME);
  51. //
  52. // Create a controling device object. All control commands to the
  53. // filter driver come via IOCTL's to this device object. It lives
  54. // for the lifetime of the filter driver.
  55. //
  56. status = IoCreateDevice (
  57. DriverObject,
  58. sizeof (VA_CONTROL_DATA),
  59. &uniNtNameString,
  60. FILE_DEVICE_UNKNOWN,
  61. 0, // No standard device characteristics
  62. FALSE, // This isn't an exclusive device
  63. &deviceObject
  64. );
  65. if(!NT_SUCCESS (status)) {
  66. VA_KdPrint (("Couldn't create the device\n"));
  67. return status;
  68. }
  69. //
  70. // Create W32 symbolic link name
  71. //
  72. RtlInitUnicodeString (&uniWin32NameString, VA_FILTER_SYMNAME);
  73. status = IoCreateSymbolicLink (&uniWin32NameString, &uniNtNameString);
  74. if (!NT_SUCCESS(status)) {
  75. VA_KdPrint (("Couldn't create the symbolic link\n"));
  76. IoDeleteDevice (DriverObject->DeviceObject);
  77. return status;
  78. }
  79. VA_KdPrint (("Initializing\n"));
  80. deviceData = (PVA_CONTROL_DATA) deviceObject->DeviceExtension;
  81. InitializeListHead (&deviceData->UsbDevices);
  82. KeInitializeSpinLock (&deviceData->Spin);
  83. deviceData->NumUsbDevices = 0;
  84. Global.ControlObject = deviceObject;
  85. //
  86. // Create dispatch points
  87. //
  88. for (i=0, dispatch = DriverObject->MajorFunction;
  89. i <= IRP_MJ_MAXIMUM_FUNCTION;
  90. i++, dispatch++) {
  91. *dispatch = VA_Pass;
  92. }
  93. DriverObject->MajorFunction[IRP_MJ_CREATE] = VA_CreateClose;
  94. DriverObject->MajorFunction[IRP_MJ_CLOSE] = VA_CreateClose;
  95. DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = VA_FilterURB;
  96. DriverObject->MajorFunction[IRP_MJ_PNP] = VA_PnP;
  97. DriverObject->MajorFunction[IRP_MJ_POWER] = VA_Power;
  98. DriverObject->DriverExtension->AddDevice = VA_AddDevice;
  99. DriverObject->DriverUnload = VA_Unload;
  100. return status;
  101. }
  102. NTSTATUS
  103. VA_Pass (
  104. IN PDEVICE_OBJECT DeviceObject,
  105. IN PIRP Irp
  106. )
  107. /*++
  108. Routine Description:
  109. The default dispatch routine. If this filter does not recognize the
  110. IRP, then it should send it down, unmodified.
  111. No completion routine is required.
  112. As we have NO idea which function we are happily passing on, we can make
  113. NO assumptions about whether or not it will be called at raised IRQL.
  114. For this reason, this function must be in put into non-paged pool
  115. (aka the default location).
  116. Arguments:
  117. DeviceObject - pointer to a device object.
  118. Irp - pointer to an I/O Request Packet.
  119. Return Value:
  120. NT status code
  121. --*/
  122. {
  123. PVA_USB_DATA usbData;
  124. NTSTATUS status;
  125. usbData = (PVA_USB_DATA) DeviceObject->DeviceExtension;
  126. if(DeviceObject == Global.ControlObject) {
  127. //
  128. // This irp was sent to the control device object, which knows not
  129. // how to deal with this IRP. It is therefore an error.
  130. //
  131. Irp->IoStatus.Information = 0;
  132. Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  133. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  134. return STATUS_NOT_SUPPORTED;
  135. }
  136. //
  137. // This IRP was sent to the filter driver.
  138. // Since we do not know what to do with the IRP, we should pass
  139. // it on along down the stack.
  140. //
  141. InterlockedIncrement (&usbData->OutstandingIO);
  142. if (usbData->Removed) {
  143. status = STATUS_DELETE_PENDING;
  144. Irp->IoStatus.Information = 0;
  145. Irp->IoStatus.Status = status;
  146. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  147. } else {
  148. IoSkipCurrentIrpStackLocation (Irp);
  149. status = IoCallDriver (usbData->TopOfStack, Irp);
  150. }
  151. if (0 == InterlockedDecrement (&usbData->OutstandingIO)) {
  152. KeSetEvent (&usbData->RemoveEvent, 0, FALSE);
  153. }
  154. return status;
  155. }
  156. NTSTATUS
  157. VA_CreateClose (
  158. IN PDEVICE_OBJECT DeviceObject,
  159. IN PIRP Irp
  160. )
  161. /*++
  162. Routine Description:
  163. Process the Create and close IRPs sent to this device.
  164. Arguments:
  165. DeviceObject - pointer to a device object.
  166. Irp - pointer to an I/O Request Packet.
  167. Return Value:
  168. NT status code
  169. --*/
  170. {
  171. PIO_STACK_LOCATION stack;
  172. NTSTATUS status = STATUS_SUCCESS;
  173. PVA_USB_DATA usbData;
  174. PAGED_CODE ();
  175. TRAP ();
  176. VA_KdPrint (("Create\n"));
  177. stack = IoGetCurrentIrpStackLocation (Irp);
  178. usbData = (PVA_USB_DATA) DeviceObject->DeviceExtension;
  179. if (DeviceObject == Global.ControlObject) {
  180. //
  181. // We allow people to blindly access our control object.
  182. //
  183. Irp->IoStatus.Information = 0;
  184. Irp->IoStatus.Status = status;
  185. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  186. }
  187. //
  188. // Call the next driver in the routine. We have no value add
  189. // for start and stop.
  190. //
  191. InterlockedIncrement (&usbData->OutstandingIO);
  192. if (usbData->Removed) {
  193. status = (IRP_MJ_CREATE == stack->MajorFunction) ?
  194. STATUS_DELETE_PENDING:
  195. STATUS_SUCCESS; // aka a close
  196. Irp->IoStatus.Information = 0;
  197. Irp->IoStatus.Status = status;
  198. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  199. } else {
  200. IoSkipCurrentIrpStackLocation (Irp);
  201. status = IoCallDriver (usbData->TopOfStack, Irp);
  202. }
  203. if (0 == InterlockedDecrement (&usbData->OutstandingIO)) {
  204. KeSetEvent (&usbData->RemoveEvent, 0, FALSE);
  205. }
  206. return status;
  207. }
  208. NTSTATUS
  209. VA_AddDevice(
  210. IN PDRIVER_OBJECT DriverObject,
  211. IN PDEVICE_OBJECT PhysicalDeviceObject
  212. )
  213. /*++
  214. Routine Description:
  215. The PlugPlay subsystem is handing us a brand new PDO, for which we
  216. (by means of INF registration) have been asked to filter.
  217. We need to determine if we should attach or not.
  218. Create a filter device object to attach to the stack
  219. Initialize that device object
  220. Return status success.
  221. Remember: we can NOT actually send ANY non pnp IRPS to the given driver
  222. stack, UNTIL we have received an IRP_MN_START_DEVICE.
  223. Arguments:
  224. DeviceObject - pointer to a device object.
  225. PhysicalDeviceObject - pointer to a device object pointer created by the
  226. underlying bus driver.
  227. Return Value:
  228. NT status code.
  229. --*/
  230. {
  231. NTSTATUS status = STATUS_SUCCESS;
  232. PDEVICE_OBJECT deviceObject = NULL;
  233. PVA_USB_DATA usbData;
  234. PVA_CONTROL_DATA controlData;
  235. #define IS_THIS_OUR_DEVICE(DO) TRUE
  236. PAGED_CODE ();
  237. VA_KdPrint (("AddDevice\n"));
  238. controlData = (PVA_CONTROL_DATA) Global.ControlObject->DeviceExtension;
  239. //
  240. // Inquire about this device to see if we really want to filter.
  241. // Usually this test will not be performed by filter drivers since
  242. // they will not have registered via INF to load unless they wanted
  243. // to actually filter the PDO.
  244. //
  245. // Remember that you CANNOT send an IRP to the PDO because it has not
  246. // been started as of yet, but you can make PlugPlay queries to find
  247. // out things like hardware, compatible ID's, etc.
  248. // (IoGetDeviceProperty)
  249. //
  250. if (!IS_THIS_OUR_DEVICE(deviceObject)) {
  251. //
  252. // This is not a device we want to filter. (Maybe we placed a general
  253. // entry in the inf file and we are more picky here.)
  254. //
  255. // In this case we do not create a device object,
  256. // and we do not attach.
  257. //
  258. // We DO still return status success, otherwise the device node will
  259. // fail and the device being attached will not function.
  260. //
  261. // We must return STATUS_SUCCESS, otherwise this particular device
  262. // cannot be used by the system
  263. //
  264. return STATUS_SUCCESS;
  265. }
  266. //
  267. // Create a filter device object.
  268. //
  269. status = IoCreateDevice (DriverObject,
  270. sizeof (VA_USB_DATA),
  271. NULL, // No Name
  272. FILE_DEVICE_UNKNOWN,
  273. 0,
  274. FALSE,
  275. &deviceObject);
  276. //
  277. // It is important that you choose correctly the file type for this
  278. // device object. Here we use FILE_DEVICE_UNKNOWN because this is
  279. // a generic filter, however as will all filters, the creator needs
  280. // to understand to which stack this filter is attaching.
  281. // E.G. if you are writing a CD filter driver you need to use
  282. // FILE_DEVICE_CD_ROM. IoCreateDevice actually creates device object
  283. // with different properties dependent on this field.
  284. //
  285. if (!NT_SUCCESS (status)) {
  286. //
  287. // returning failure here prevents the entire stack from functioning,
  288. // but most likely the rest of the stack will not be able to create
  289. // device objects either, so it is still OK.
  290. //
  291. return status;
  292. }
  293. //
  294. // Initialize the the device extension.
  295. //
  296. usbData = (PVA_USB_DATA) deviceObject->DeviceExtension;
  297. usbData->Started = usbData->Removed = FALSE;
  298. usbData->Self = deviceObject;
  299. usbData->PDO = PhysicalDeviceObject;
  300. usbData->TopOfStack = NULL;
  301. usbData->PrintMask = VA_PRINT_ALL;
  302. ExInterlockedInsertHeadList (&controlData->UsbDevices,
  303. &usbData->List,
  304. &controlData->Spin);
  305. InterlockedIncrement (&controlData->NumUsbDevices);
  306. KeInitializeEvent(&usbData->RemoveEvent, SynchronizationEvent, FALSE);
  307. usbData->OutstandingIO = 1; // biassed to 1. Transition to zero during
  308. // remove device means IO is finished.
  309. deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  310. //
  311. // Attach our filter driver to the device stack.
  312. // the return value of IoAttachDeviceToDeviceStack is the top of the
  313. // attachment chain. This is where all the IRPs should be routed.
  314. //
  315. // Our filter will send IRPs to the top of the stack and use the PDO
  316. // for all PlugPlay functions.
  317. //
  318. usbData->TopOfStack = IoAttachDeviceToDeviceStack (deviceObject,
  319. PhysicalDeviceObject);
  320. //
  321. // if this attachment fails then top of stack will be null.
  322. // failure for attachment is an indication of a broken plug play system.
  323. //
  324. ASSERT (NULL != usbData->TopOfStack);
  325. return STATUS_SUCCESS;
  326. #undef IS_THIS_OUR_DEVICE
  327. }
  328. VOID
  329. VA_Unload(
  330. IN PDRIVER_OBJECT DriverObject
  331. )
  332. /*++
  333. Routine Description:
  334. Free all the allocated resources, etc.
  335. Arguments:
  336. DriverObject - pointer to a driver object.
  337. Return Value:
  338. VOID.
  339. --*/
  340. {
  341. UNICODE_STRING uniWin32NameString;
  342. PAGED_CODE ();
  343. //
  344. // We should not be unloaded until all the PDOs have been removed from
  345. // our queue. The control device object should be the only thing left.
  346. //
  347. ASSERT (Global.ControlObject == DriverObject->DeviceObject);
  348. ASSERT (NULL == Global.ControlObject->NextDevice);
  349. VA_KdPrint (("unload\n"));
  350. //
  351. // Get rid of our control device object.
  352. //
  353. RtlInitUnicodeString (&uniWin32NameString, VA_FILTER_SYMNAME);
  354. IoDeleteSymbolicLink (&uniWin32NameString);
  355. IoDeleteDevice (DriverObject->DeviceObject);
  356. }