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.

443 lines
12 KiB

  1. /*++
  2. Copyright (c) 1991 - 2001 Microsoft Corporation
  3. Module Name:
  4. ##### ## # ##### #### ##### #####
  5. ## ## ### # ## ## ## # ## ## ## ##
  6. ## ## #### # ## ## ## ## ## ## ##
  7. ## ## # #### ## ## ## ## ## ## ##
  8. ##### # ### ##### ## ##### #####
  9. ## # ## ## ## ## # ## ##
  10. ## # # ## ## #### ## ##
  11. Abstract:
  12. This module process all plug and play IRPs.
  13. Author:
  14. Wesley Witt (wesw) 1-Oct-2001
  15. Environment:
  16. Kernel mode only.
  17. Notes:
  18. --*/
  19. #include "internal.h"
  20. #ifdef ALLOC_PRAGMA
  21. #pragma alloc_text(PAGE,WdAddDevice)
  22. #pragma alloc_text(PAGE,WdPnp)
  23. #endif
  24. NTSTATUS
  25. WdAddDevice(
  26. IN PDRIVER_OBJECT DriverObject,
  27. IN OUT PDEVICE_OBJECT PhysicalDeviceObject
  28. )
  29. /*++
  30. Routine Description:
  31. This routine is the driver's pnp add device entry point. It is
  32. called by the pnp manager to initialize the driver.
  33. Add device creates and initializes a device object for this FDO and
  34. attaches to the underlying PDO.
  35. Arguments:
  36. DriverObject - a pointer to the object that represents this device driver.
  37. PhysicalDeviceObject - a pointer to the underlying PDO to which this new device will attach.
  38. Return Value:
  39. If we successfully create a device object, STATUS_SUCCESS is
  40. returned. Otherwise, return the appropriate error code.
  41. Notes:
  42. --*/
  43. {
  44. NTSTATUS status = STATUS_SUCCESS;
  45. PDEVICE_EXTENSION DeviceExtension = NULL;
  46. PDEVICE_OBJECT deviceObject = NULL;
  47. WCHAR DeviceNameBuffer[64];
  48. UNICODE_STRING DeviceName;
  49. __try {
  50. //
  51. // Establish the device name
  52. //
  53. DeviceName.MaximumLength = sizeof(DeviceNameBuffer);
  54. DeviceName.Buffer = DeviceNameBuffer;
  55. wcscpy( DeviceName.Buffer, L"\\Device\\Watchdog" );
  56. DeviceName.Length = wcslen(DeviceName.Buffer) * sizeof(WCHAR);
  57. //
  58. // Create the device
  59. //
  60. status = IoCreateDevice(
  61. DriverObject,
  62. sizeof(DEVICE_EXTENSION),
  63. &DeviceName,
  64. FILE_DEVICE_CONTROLLER,
  65. FILE_DEVICE_SECURE_OPEN,
  66. FALSE,
  67. &deviceObject
  68. );
  69. if (!NT_SUCCESS(status)) {
  70. ERROR_RETURN( "IoCreateDevice", status );
  71. }
  72. DeviceExtension = (PDEVICE_EXTENSION) deviceObject->DeviceExtension;
  73. RtlZeroMemory( DeviceExtension, sizeof(DEVICE_EXTENSION) );
  74. DeviceExtension->DeviceObject = deviceObject;
  75. DeviceExtension->DriverObject = DriverObject;
  76. DeviceExtension->Pdo = PhysicalDeviceObject;
  77. DeviceExtension->TargetObject = IoAttachDeviceToDeviceStack( deviceObject, PhysicalDeviceObject );
  78. if (DeviceExtension->TargetObject == NULL) {
  79. status = STATUS_NO_SUCH_DEVICE;
  80. ERROR_RETURN( "IoAttachDeviceToDeviceStack", status );
  81. }
  82. //
  83. // Register with the I/O manager for shutdown notification
  84. //
  85. status = IoRegisterShutdownNotification( deviceObject );
  86. if (!NT_SUCCESS(status)) {
  87. ERROR_RETURN( "IoRegisterShutdownNotification", status );
  88. }
  89. IoInitializeRemoveLock( &DeviceExtension->RemoveLock, WD_POOL_TAG, 0, 0 );
  90. KeInitializeSpinLock( &DeviceExtension->DeviceLock );
  91. //
  92. // Set the device object flags
  93. //
  94. deviceObject->Flags |= DO_DIRECT_IO;
  95. deviceObject->Flags |= DO_POWER_PAGABLE;
  96. deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  97. } __finally {
  98. //
  99. // In the failure case un-do everything
  100. //
  101. if (!NT_SUCCESS(status)) {
  102. if (deviceObject) {
  103. if (DeviceExtension && DeviceExtension->TargetObject) {
  104. IoDetachDevice( DeviceExtension->TargetObject );
  105. }
  106. IoDeleteDevice( deviceObject );
  107. }
  108. }
  109. }
  110. return status;
  111. }
  112. NTSTATUS
  113. WdPnpStartDevice(
  114. IN PDEVICE_OBJECT DeviceObject,
  115. IN PIRP Irp
  116. )
  117. /*++
  118. Routine Description:
  119. This routine is the PNP handler for the IRP_MN_START_DEVICE request.
  120. Arguments:
  121. DeviceObject - Pointer to the object that represents the device that I/O is to be done on.
  122. Irp - I/O Request Packet for this request.
  123. IrpSp - IRP stack location for this request
  124. DeviceExtension - Device extension
  125. Return Value:
  126. NT status code.
  127. --*/
  128. {
  129. NTSTATUS Status = STATUS_SUCCESS;
  130. PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  131. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
  132. SYSTEM_WATCHDOG_HANDLER_INFORMATION WdHandlerInfo;
  133. if (DeviceExtension->IsStarted) {
  134. return ForwardRequest( Irp, DeviceExtension->TargetObject );
  135. }
  136. __try {
  137. if (IrpSp->Parameters.StartDevice.AllocatedResourcesTranslated != NULL) {
  138. Status = STATUS_UNSUCCESSFUL;
  139. ERROR_RETURN( "Resource list is empty", Status );
  140. }
  141. DeviceExtension->ControlRegisterAddress = (PULONG) MmMapIoSpace(
  142. WdTable->ControlRegisterAddress.Address,
  143. WdTable->ControlRegisterAddress.BitWidth>>3,
  144. MmNonCached
  145. );
  146. if (DeviceExtension->ControlRegisterAddress == NULL) {
  147. Status = STATUS_UNSUCCESSFUL ;
  148. ERROR_RETURN( "MmMapIoSpace failed", Status );
  149. }
  150. DeviceExtension->CountRegisterAddress = (PULONG) MmMapIoSpace(
  151. WdTable->CountRegisterAddress.Address,
  152. WdTable->CountRegisterAddress.BitWidth>>3,
  153. MmNonCached
  154. );
  155. if (DeviceExtension->CountRegisterAddress == NULL) {
  156. Status = STATUS_UNSUCCESSFUL ;
  157. ERROR_RETURN( "MmMapIoSpace failed", Status );
  158. }
  159. //
  160. // Setup & start the hardware timer
  161. //
  162. //
  163. // First query the state of the hardware
  164. //
  165. DeviceExtension->WdState = WdHandlerQueryState( DeviceExtension, TRUE );
  166. DeviceExtension->Units = WdTable->Units;
  167. DeviceExtension->MaxCount = WdTable->MaxCount;
  168. if (RunningCountTime > 0) {
  169. DeviceExtension->HardwareTimeout = RunningCountTime;
  170. } else {
  171. DeviceExtension->HardwareTimeout = DeviceExtension->MaxCount;
  172. }
  173. WdHandlerSetTimeoutValue( DeviceExtension, DeviceExtension->HardwareTimeout, FALSE );
  174. //
  175. // Everything is good and the device is now started
  176. // The last thing to do is register with the executive
  177. // so that we can service watchdog requests.
  178. //
  179. WdHandlerInfo.WdHandler = WdHandlerFunction;
  180. WdHandlerInfo.Context = (PVOID) DeviceExtension;
  181. Status = ZwSetSystemInformation( SystemWatchdogTimerHandler, &WdHandlerInfo, sizeof(SYSTEM_WATCHDOG_HANDLER_INFORMATION) );
  182. if (!NT_SUCCESS(Status)) {
  183. REPORT_ERROR( "Failed to set the executive watchdog handler, ec=%08x", Status );
  184. }
  185. //
  186. // Check to see if the timer triggered previous to this boot
  187. //
  188. if (DeviceExtension->WdState & WDSTATE_FIRED) {
  189. Status = WriteEventLogEntry( DeviceExtension, WD_TIMER_WAS_TRIGGERED, NULL, 0, NULL, 0 );
  190. if (!NT_SUCCESS(Status)) {
  191. REPORT_ERROR( "WriteEventLogEntry failed, ec=%08x", Status );
  192. }
  193. WdHandlerResetFired( DeviceExtension );
  194. }
  195. //
  196. // Mark the device as started
  197. //
  198. DeviceExtension->IsStarted = TRUE;
  199. Status = WdInitializeSoftwareTimer( DeviceExtension );
  200. if (!NT_SUCCESS(Status)) {
  201. REPORT_ERROR( "Failed to start the software watchdog timer, ec=%08x", Status );
  202. }
  203. WdHandlerStartTimer( DeviceExtension );
  204. } __finally {
  205. }
  206. Irp->IoStatus.Status = Status;
  207. return ForwardRequest( Irp, DeviceExtension->TargetObject );
  208. }
  209. NTSTATUS
  210. WdPnpQueryCapabilities(
  211. IN PDEVICE_OBJECT DeviceObject,
  212. IN PIRP Irp
  213. )
  214. /*++
  215. Routine Description:
  216. This routine is the PNP handler for the IRP_MN_QUERY_CAPABILITIES request.
  217. Arguments:
  218. DeviceObject - Pointer to the object that represents the device that I/O is to be done on.
  219. Irp - I/O Request Packet for this request.
  220. IrpSp - IRP stack location for this request
  221. DeviceExtension - Device extension
  222. Return Value:
  223. NT status code.
  224. --*/
  225. {
  226. NTSTATUS Status;
  227. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
  228. PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  229. PDEVICE_CAPABILITIES Capabilities = IrpSp->Parameters.DeviceCapabilities.Capabilities;
  230. Status = CallLowerDriverAndWait( Irp, DeviceExtension->TargetObject );
  231. Capabilities->SilentInstall = 1;
  232. Capabilities->RawDeviceOK = 1;
  233. return CompleteRequest( Irp, Status, Irp->IoStatus.Information );
  234. }
  235. NTSTATUS
  236. WdPnpQueryDeviceState(
  237. IN PDEVICE_OBJECT DeviceObject,
  238. IN PIRP Irp
  239. )
  240. /*++
  241. Routine Description:
  242. This routine is the PNP handler for the IRP_MN_QUERY_PNP_DEVICE_STATE request.
  243. Arguments:
  244. DeviceObject - Pointer to the object that represents the device that I/O is to be done on.
  245. Irp - I/O Request Packet for this request.
  246. IrpSp - IRP stack location for this request
  247. DeviceExtension - Device extension
  248. Return Value:
  249. NT status code.
  250. --*/
  251. {
  252. NTSTATUS Status;
  253. PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  254. Status = CallLowerDriverAndWait( Irp, DeviceExtension->TargetObject );
  255. if (!NT_SUCCESS(Status)) {
  256. REPORT_ERROR( "IRP_MN_QUERY_PNP_DEVICE_STATE", Status );
  257. Irp->IoStatus.Information = 0;
  258. }
  259. return CompleteRequest( Irp, STATUS_SUCCESS, Irp->IoStatus.Information );
  260. }
  261. NTSTATUS
  262. WdPnp(
  263. IN PDEVICE_OBJECT DeviceObject,
  264. IN PIRP Irp
  265. )
  266. /*++
  267. Routine Description:
  268. Main PNP irp dispatch routine
  269. Arguments:
  270. DeviceObject - a pointer to the object that represents the device
  271. that I/O is to be done on.
  272. Irp - a pointer to the I/O Request Packet for this request.
  273. Return Value:
  274. status
  275. --*/
  276. {
  277. NTSTATUS status;
  278. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
  279. PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  280. DebugPrint(( WD_DEBUG_INFO_LEVEL, "PNP - Func [0x%02x %s]\n",
  281. irpSp->MinorFunction,
  282. PnPMinorFunctionString(irpSp->MinorFunction)
  283. ));
  284. if (DeviceExtension->IsRemoved) {
  285. return CompleteRequest( Irp, STATUS_DELETE_PENDING, 0 );
  286. }
  287. status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, Irp );
  288. if (!NT_SUCCESS(status)) {
  289. REPORT_ERROR( "WdPnp could not acquire the remove lock", status );
  290. return CompleteRequest( Irp, status, 0 );
  291. }
  292. switch (irpSp->MinorFunction) {
  293. case IRP_MN_START_DEVICE:
  294. status = WdPnpStartDevice( DeviceObject, Irp );
  295. break;
  296. case IRP_MN_QUERY_CAPABILITIES:
  297. status = WdPnpQueryCapabilities( DeviceObject, Irp );
  298. break;
  299. case IRP_MN_QUERY_PNP_DEVICE_STATE:
  300. status = WdPnpQueryDeviceState( DeviceObject, Irp );
  301. break;
  302. default:
  303. status = ForwardRequest( Irp, DeviceExtension->TargetObject );
  304. break;
  305. }
  306. IoReleaseRemoveLock( &DeviceExtension->RemoveLock, Irp );
  307. return status;
  308. }