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.

653 lines
20 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,SaPortAddDevice)
  22. #pragma alloc_text(PAGE,SaPortPnp)
  23. #endif
  24. //
  25. // Device names
  26. //
  27. PWSTR SaDeviceName[] =
  28. {
  29. { NULL }, // Bogus
  30. { SA_DEVICE_DISPLAY_NAME_STRING }, // SA_DEVICE_DISPLAY
  31. { SA_DEVICE_KEYPAD_NAME_STRING }, // SA_DEVICE_KEYPAD
  32. { SA_DEVICE_NVRAM_NAME_STRING }, // SA_DEVICE_NVRAM
  33. { SA_DEVICE_WATCHDOG_NAME_STRING } // SA_DEVICE_WATCHDOG
  34. };
  35. //
  36. // Prototypes
  37. //
  38. #define DECLARE_PNP_HANDLER(_NAME) \
  39. NTSTATUS \
  40. _NAME( \
  41. IN PDEVICE_OBJECT DeviceObject, \
  42. IN PIRP Irp, \
  43. IN PIO_STACK_LOCATION IrpSp, \
  44. IN PDEVICE_EXTENSION DeviceExtension \
  45. )
  46. DECLARE_PNP_HANDLER( DefaultPnpHandler );
  47. DECLARE_PNP_HANDLER( HandleStartDevice );
  48. DECLARE_PNP_HANDLER( HandleQueryCapabilities );
  49. DECLARE_PNP_HANDLER( HandleQueryDeviceState );
  50. //
  51. // PNP dispatch table
  52. //
  53. typedef NTSTATUS (*PPNP_DISPATCH_FUNC)(
  54. IN PDEVICE_OBJECT DeviceObject,
  55. IN PIRP Irp,
  56. IN PIO_STACK_LOCATION IrpSp,
  57. IN PDEVICE_EXTENSION DeviceExtension
  58. );
  59. PPNP_DISPATCH_FUNC PnpDispatchTable[] =
  60. {
  61. HandleStartDevice, // IRP_MN_START_DEVICE
  62. DefaultPnpHandler, // IRP_MN_QUERY_REMOVE_DEVICE
  63. DefaultPnpHandler, // IRP_MN_REMOVE_DEVICE
  64. DefaultPnpHandler, // IRP_MN_CANCEL_REMOVE_DEVICE
  65. DefaultPnpHandler, // IRP_MN_STOP_DEVICE
  66. DefaultPnpHandler, // IRP_MN_QUERY_STOP_DEVICE
  67. DefaultPnpHandler, // IRP_MN_CANCEL_STOP_DEVICE
  68. DefaultPnpHandler, // IRP_MN_QUERY_DEVICE_RELATIONS
  69. DefaultPnpHandler, // IRP_MN_QUERY_INTERFACE
  70. HandleQueryCapabilities, // IRP_MN_QUERY_CAPABILITIES
  71. DefaultPnpHandler, // IRP_MN_QUERY_RESOURCES
  72. DefaultPnpHandler, // IRP_MN_QUERY_RESOURCE_REQUIREMENTS
  73. DefaultPnpHandler, // IRP_MN_QUERY_DEVICE_TEXT
  74. DefaultPnpHandler, // IRP_MN_FILTER_RESOURCE_REQUIREMENTS
  75. DefaultPnpHandler, // *unused*
  76. DefaultPnpHandler, // IRP_MN_READ_CONFIG
  77. DefaultPnpHandler, // IRP_MN_WRITE_CONFIG
  78. DefaultPnpHandler, // IRP_MN_EJECT
  79. DefaultPnpHandler, // IRP_MN_SET_LOCK
  80. DefaultPnpHandler, // IRP_MN_QUERY_ID
  81. HandleQueryDeviceState, // IRP_MN_QUERY_PNP_DEVICE_STATE
  82. DefaultPnpHandler, // IRP_MN_QUERY_BUS_INFORMATION
  83. DefaultPnpHandler, // IRP_MN_DEVICE_USAGE_NOTIFICATION
  84. DefaultPnpHandler // IRP_MN_SURPRISE_REMOVAL
  85. };
  86. NTSTATUS
  87. SaPortAddDevice(
  88. IN PDRIVER_OBJECT DriverObject,
  89. IN OUT PDEVICE_OBJECT PhysicalDeviceObject
  90. )
  91. /*++
  92. Routine Description:
  93. This routine is the driver's pnp add device entry point. It is
  94. called by the pnp manager to initialize the driver.
  95. Add device creates and initializes a device object for this FDO and
  96. attaches to the underlying PDO.
  97. Arguments:
  98. DriverObject - a pointer to the object that represents this device driver.
  99. PhysicalDeviceObject - a pointer to the underlying PDO to which this new device will attach.
  100. Return Value:
  101. If we successfully create a device object, STATUS_SUCCESS is
  102. returned. Otherwise, return the appropriate error code.
  103. Notes:
  104. The device extension that is allocated for each server appliance
  105. miniport is really a concatination of several data structures.
  106. |------------------------------|
  107. | |
  108. | Port driver extension | This is the DEVICE_EXTENSION data structure
  109. | |
  110. |------------------------------|
  111. | |
  112. | Port driver device | This is the DISPLAY_DEVICE_EXTENSION, KEYPAD_DEVICE_EXTENSION,
  113. | specific data structure | NVRAM_DEVICE_EXTENSION, or the WATCHDOG_DEVICE_EXTENSION data structure.
  114. | |
  115. |------------------------------|
  116. | |
  117. | Size of the port driver | This is a single ULONG value and is used to back-compute the location of
  118. | portion of the extension | the port driver extension from the miniport device extension.
  119. | |
  120. |------------------------------|
  121. | |
  122. | Miniport device extension | This is owned by the miniport driver and can be anything. The size must be
  123. | | specified in the DeviceExtensionSize field of the SAPORT_INITIALIZATION_DATA structure.
  124. |------------------------------|
  125. --*/
  126. {
  127. NTSTATUS status = STATUS_SUCCESS;
  128. PSAPORT_DRIVER_EXTENSION DriverExtension;
  129. PDEVICE_EXTENSION DeviceExtension = NULL;
  130. PDEVICE_OBJECT deviceObject = NULL;
  131. ULONG DeviceExtensionSize;
  132. WCHAR DeviceNameBuffer[64];
  133. UNICODE_STRING DeviceName;
  134. UNICODE_STRING VmLinkName = {0};
  135. UNICODE_STRING SaLinkName = {0};
  136. __try {
  137. DriverExtension = (PSAPORT_DRIVER_EXTENSION) IoGetDriverObjectExtension( DriverObject, SaPortInitialize );
  138. if (DriverExtension == NULL) {
  139. status = STATUS_NO_SUCH_DEVICE;
  140. ERROR_RETURN( 0, "IoGetDriverObjectExtension", status );
  141. }
  142. DebugPrint(( DriverExtension->InitData.DeviceType, SAPORT_DEBUG_INFO_LEVEL, "SaPortAddDevice\n" ));
  143. DeviceExtensionSize = DriverExtension->InitData.DeviceExtensionSize + sizeof(ULONG);
  144. switch (DriverExtension->InitData.DeviceType) {
  145. case SA_DEVICE_DISPLAY:
  146. DeviceExtensionSize += sizeof(DISPLAY_DEVICE_EXTENSION);
  147. break;
  148. case SA_DEVICE_KEYPAD:
  149. DeviceExtensionSize += sizeof(KEYPAD_DEVICE_EXTENSION);
  150. break;
  151. case SA_DEVICE_NVRAM:
  152. DeviceExtensionSize += sizeof(NVRAM_DEVICE_EXTENSION);
  153. break;
  154. case SA_DEVICE_WATCHDOG:
  155. DeviceExtensionSize += sizeof(WATCHDOG_DEVICE_EXTENSION);
  156. break;
  157. default:
  158. DeviceExtensionSize += sizeof(DEVICE_EXTENSION);
  159. break;
  160. }
  161. //
  162. // Establish the device name
  163. //
  164. DeviceName.MaximumLength = sizeof(DeviceNameBuffer);
  165. DeviceName.Buffer = DeviceNameBuffer;
  166. wcscpy( DeviceName.Buffer, SaDeviceName[DriverExtension->InitData.DeviceType] );
  167. DeviceName.Length = wcslen(DeviceName.Buffer) * sizeof(WCHAR);
  168. //
  169. // Create the device
  170. //
  171. status = IoCreateDeviceSecure(
  172. DriverObject,
  173. DeviceExtensionSize,
  174. &DeviceName,
  175. FILE_DEVICE_CONTROLLER,
  176. FILE_DEVICE_SECURE_OPEN,
  177. FALSE,
  178. &SDDL_DEVOBJ_SYS_ALL_ADM_ALL,
  179. NULL,
  180. &deviceObject
  181. );
  182. if (!NT_SUCCESS(status)) {
  183. ERROR_RETURN( DriverExtension->InitData.DeviceType, "IoCreateDevice", status );
  184. }
  185. DeviceExtension = (PDEVICE_EXTENSION) deviceObject->DeviceExtension;
  186. RtlZeroMemory( DeviceExtension, DeviceExtensionSize );
  187. DeviceExtension->DeviceObject = deviceObject;
  188. DeviceExtension->DriverObject = DriverObject;
  189. DeviceExtension->Pdo = PhysicalDeviceObject;
  190. DeviceExtension->InitData = &DriverExtension->InitData;
  191. DeviceExtension->DriverExtension = DriverExtension;
  192. DeviceExtension->DeviceType = DriverExtension->InitData.DeviceType;
  193. DeviceExtension->MiniPortDeviceExtension =
  194. (PUCHAR)DeviceExtension + (DeviceExtensionSize - DriverExtension->InitData.DeviceExtensionSize);
  195. *(PULONG)((PUCHAR)DeviceExtension->MiniPortDeviceExtension - sizeof(ULONG)) = DeviceExtensionSize - DriverExtension->InitData.DeviceExtensionSize;
  196. IoInitializeRemoveLock( &DeviceExtension->RemoveLock, 0, 0, 0 );
  197. switch (DriverExtension->InitData.DeviceType) {
  198. case SA_DEVICE_DISPLAY:
  199. ((PDISPLAY_DEVICE_EXTENSION)DeviceExtension)->AllowWrites = TRUE;
  200. ExInitializeFastMutex( &((PDISPLAY_DEVICE_EXTENSION)DeviceExtension)->DisplayMutex );
  201. DeviceExtension->DeviceExtensionType = DEVICE_EXTENSION_DISPLAY;
  202. break;
  203. case SA_DEVICE_KEYPAD:
  204. DeviceExtension->DeviceExtensionType = DEVICE_EXTENSION_KEYPAD;
  205. break;
  206. case SA_DEVICE_NVRAM:
  207. DeviceExtension->DeviceExtensionType = DEVICE_EXTENSION_NVRAM;
  208. break;
  209. case SA_DEVICE_WATCHDOG:
  210. DeviceExtension->DeviceExtensionType = DEVICE_EXTENSION_WATCHDOG;
  211. break;
  212. }
  213. DeviceExtension->TargetObject = IoAttachDeviceToDeviceStack( deviceObject, PhysicalDeviceObject );
  214. if (DeviceExtension->TargetObject == NULL) {
  215. status = STATUS_NO_SUCH_DEVICE;
  216. ERROR_RETURN( DeviceExtension->DeviceType, "IoAttachDeviceToDeviceStack", status );
  217. }
  218. //
  219. // Register with the I/O manager for shutdown notification
  220. //
  221. status = IoRegisterShutdownNotification( deviceObject );
  222. if (!NT_SUCCESS(status)) {
  223. ERROR_RETURN( DeviceExtension->DeviceType, "IoRegisterShutdownNotification", status );
  224. }
  225. //
  226. // Set the device object flags
  227. //
  228. deviceObject->Flags |= DO_DIRECT_IO;
  229. deviceObject->Flags |= DO_POWER_PAGABLE;
  230. deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  231. } __finally {
  232. //
  233. // In the failure case un-do everything
  234. //
  235. if (!NT_SUCCESS(status)) {
  236. if (deviceObject) {
  237. IoDeleteSymbolicLink( &VmLinkName );
  238. IoDeleteSymbolicLink( &SaLinkName );
  239. if (DeviceExtension && DeviceExtension->TargetObject) {
  240. IoDetachDevice( DeviceExtension->TargetObject );
  241. }
  242. IoDeleteDevice( deviceObject );
  243. }
  244. }
  245. }
  246. return status;
  247. }
  248. DECLARE_PNP_HANDLER( DefaultPnpHandler )
  249. /*++
  250. Routine Description:
  251. This routine is the default PNP handler and simply calls the next lower device driver.
  252. Arguments:
  253. DeviceObject - Pointer to the object that represents the device that I/O is to be done on.
  254. Irp - I/O Request Packet for this request.
  255. IrpSp - IRP stack location for this request
  256. DeviceExtension - Device extension
  257. Return Value:
  258. NT status code.
  259. --*/
  260. {
  261. return ForwardRequest( Irp, DeviceExtension->TargetObject );
  262. }
  263. DECLARE_PNP_HANDLER( HandleStartDevice )
  264. /*++
  265. Routine Description:
  266. This routine is the PNP handler for the IRP_MN_START_DEVICE request.
  267. Arguments:
  268. DeviceObject - Pointer to the object that represents the device that I/O is to be done on.
  269. Irp - I/O Request Packet for this request.
  270. IrpSp - IRP stack location for this request
  271. DeviceExtension - Device extension
  272. Return Value:
  273. NT status code.
  274. --*/
  275. {
  276. NTSTATUS Status = STATUS_SUCCESS;
  277. PCM_RESOURCE_LIST ResourceList;
  278. PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResources;
  279. PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceInterrupt = NULL;
  280. ULONG PartialResourceCount;
  281. ULONG i;
  282. if (DeviceExtension->IsStarted) {
  283. return ForwardRequest( Irp, DeviceExtension->TargetObject );
  284. }
  285. __try {
  286. ResourceList = IrpSp->Parameters.StartDevice.AllocatedResourcesTranslated;
  287. if (ResourceList == NULL) {
  288. Status = DeviceExtension->DriverExtension->InitData.HwInitialize(
  289. DeviceObject,
  290. Irp,
  291. DeviceExtension->MiniPortDeviceExtension,
  292. NULL,
  293. 0
  294. );
  295. if (!NT_SUCCESS(Status)) {
  296. ERROR_RETURN( DeviceExtension->DeviceType, "Miniport HwInitialize", Status );
  297. }
  298. } else {
  299. PartialResources = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) &ResourceList->List[0].PartialResourceList.PartialDescriptors[0];
  300. PartialResourceCount = ResourceList->List[0].PartialResourceList.Count;
  301. if (ResourceList == NULL || ResourceList->Count != 1) {
  302. Status = STATUS_UNSUCCESSFUL ;
  303. ERROR_RETURN( DeviceExtension->DeviceType, "Resource list is empty", Status );
  304. }
  305. if (DeviceExtension->DriverExtension->InitData.InterruptServiceRoutine) {
  306. //
  307. // Find the IRQ resource
  308. //
  309. for (i=0; i<PartialResourceCount; i++) {
  310. if (PartialResources[i].Type == CmResourceTypeInterrupt) {
  311. ResourceInterrupt = &PartialResources[i];
  312. }
  313. }
  314. if (ResourceInterrupt) {
  315. //
  316. // There is an IRQ resource so now use it
  317. //
  318. if (DeviceExtension->DriverExtension->InitData.IsrForDpcRoutine) {
  319. //
  320. // Initialize the DPC routine
  321. //
  322. IoInitializeDpcRequest(
  323. DeviceExtension->DeviceObject,
  324. DeviceExtension->DriverExtension->InitData.IsrForDpcRoutine
  325. );
  326. }
  327. //
  328. // Connect up the ISR
  329. //
  330. Status = IoConnectInterrupt(
  331. &DeviceExtension->InterruptObject,
  332. DeviceExtension->DriverExtension->InitData.InterruptServiceRoutine,
  333. DeviceExtension->MiniPortDeviceExtension,
  334. NULL,
  335. ResourceInterrupt->u.Interrupt.Vector,
  336. (KIRQL)ResourceInterrupt->u.Interrupt.Level,
  337. (KIRQL)ResourceInterrupt->u.Interrupt.Level,
  338. LevelSensitive,
  339. TRUE,
  340. ResourceInterrupt->u.Interrupt.Affinity,
  341. FALSE
  342. );
  343. if (!NT_SUCCESS(Status)) {
  344. ERROR_RETURN( DeviceExtension->DeviceType, "IoConnectInterrupt", Status );
  345. }
  346. }
  347. }
  348. Status = DeviceExtension->DriverExtension->InitData.HwInitialize(
  349. DeviceObject,
  350. Irp,
  351. DeviceExtension->MiniPortDeviceExtension,
  352. (PCM_PARTIAL_RESOURCE_DESCRIPTOR) &ResourceList->List[0].PartialResourceList.PartialDescriptors[0],
  353. ResourceList->List[0].PartialResourceList.Count
  354. );
  355. if (!NT_SUCCESS(Status)) {
  356. ERROR_RETURN( DeviceExtension->DeviceType, "Miniport HwInitialize", Status );
  357. }
  358. }
  359. //
  360. // We must set this to TRUE temporarity here so that the
  361. // the device specific start device routine can be called.
  362. // If the call fails then IsStarted is set to FALSE
  363. //
  364. DeviceExtension->IsStarted = TRUE;
  365. switch (DeviceExtension->DriverExtension->InitData.DeviceType) {
  366. case SA_DEVICE_DISPLAY:
  367. Status = SaDisplayStartDevice( (PDISPLAY_DEVICE_EXTENSION)DeviceExtension );
  368. break;
  369. case SA_DEVICE_KEYPAD:
  370. Status = SaKeypadStartDevice( (PKEYPAD_DEVICE_EXTENSION)DeviceExtension );
  371. break;
  372. case SA_DEVICE_NVRAM:
  373. Status = SaNvramStartDevice( (PNVRAM_DEVICE_EXTENSION)DeviceExtension );
  374. break;
  375. case SA_DEVICE_WATCHDOG:
  376. Status = SaWatchdogStartDevice( (PWATCHDOG_DEVICE_EXTENSION)DeviceExtension );
  377. break;
  378. }
  379. if (!NT_SUCCESS(Status)) {
  380. DeviceExtension->IsStarted = FALSE;
  381. ERROR_RETURN( DeviceExtension->DeviceType, "Device specific start device", Status );
  382. }
  383. } __finally {
  384. }
  385. Irp->IoStatus.Status = Status;
  386. return ForwardRequest( Irp, DeviceExtension->TargetObject );
  387. }
  388. DECLARE_PNP_HANDLER( HandleQueryCapabilities )
  389. /*++
  390. Routine Description:
  391. This routine is the PNP handler for the IRP_MN_QUERY_CAPABILITIES request.
  392. Arguments:
  393. DeviceObject - Pointer to the object that represents the device that I/O is to be done on.
  394. Irp - I/O Request Packet for this request.
  395. IrpSp - IRP stack location for this request
  396. DeviceExtension - Device extension
  397. Return Value:
  398. NT status code.
  399. --*/
  400. {
  401. NTSTATUS Status;
  402. PDEVICE_CAPABILITIES Capabilities = IrpSp->Parameters.DeviceCapabilities.Capabilities;
  403. Status = CallLowerDriverAndWait( Irp, DeviceExtension->TargetObject );
  404. Capabilities->SilentInstall = 1;
  405. Capabilities->RawDeviceOK = 1;
  406. return CompleteRequest( Irp, Status, Irp->IoStatus.Information );
  407. }
  408. DECLARE_PNP_HANDLER( HandleQueryDeviceState )
  409. /*++
  410. Routine Description:
  411. This routine is the PNP handler for the IRP_MN_QUERY_PNP_DEVICE_STATE request.
  412. Arguments:
  413. DeviceObject - Pointer to the object that represents the device that I/O is to be done on.
  414. Irp - I/O Request Packet for this request.
  415. IrpSp - IRP stack location for this request
  416. DeviceExtension - Device extension
  417. Return Value:
  418. NT status code.
  419. --*/
  420. {
  421. NTSTATUS Status;
  422. Status = CallLowerDriverAndWait( Irp, DeviceExtension->TargetObject );
  423. if (!NT_SUCCESS(Status)) {
  424. REPORT_ERROR( DeviceExtension->DeviceType, "IRP_MN_QUERY_PNP_DEVICE_STATE", Status );
  425. Irp->IoStatus.Information = 0;
  426. }
  427. //Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
  428. #if MAKE_DEVICES_HIDDEN
  429. Irp->IoStatus.Information |= PNP_DEVICE_DONT_DISPLAY_IN_UI;
  430. #endif
  431. return CompleteRequest( Irp, STATUS_SUCCESS, Irp->IoStatus.Information );
  432. }
  433. NTSTATUS
  434. SaPortPnp(
  435. IN PDEVICE_OBJECT DeviceObject,
  436. IN PIRP Irp
  437. )
  438. /*++
  439. Routine Description:
  440. Main PNP irp dispatch routine
  441. Arguments:
  442. DeviceObject - a pointer to the object that represents the device
  443. that I/O is to be done on.
  444. Irp - a pointer to the I/O Request Packet for this request.
  445. Return Value:
  446. status
  447. --*/
  448. {
  449. NTSTATUS status;
  450. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
  451. PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  452. DebugPrint(( DeviceExtension->DeviceType, SAPORT_DEBUG_INFO_LEVEL, "PNP - Func [0x%02x %s]\n",
  453. irpSp->MinorFunction,
  454. PnPMinorFunctionString(irpSp->MinorFunction)
  455. ));
  456. if (DeviceExtension->IsRemoved) {
  457. return CompleteRequest( Irp, STATUS_DELETE_PENDING, 0 );
  458. }
  459. status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, Irp );
  460. if (!NT_SUCCESS(status)) {
  461. REPORT_ERROR( DeviceExtension->DeviceType, "SaPortPnp", status );
  462. return CompleteRequest( Irp, status, 0 );
  463. }
  464. if (irpSp->MinorFunction >= ARRAY_SZ(PnpDispatchTable)) {
  465. status = DefaultPnpHandler( DeviceObject, Irp, irpSp, DeviceExtension );
  466. } else {
  467. status = (*PnpDispatchTable[irpSp->MinorFunction])( DeviceObject, Irp, irpSp, DeviceExtension );
  468. }
  469. if (!NT_SUCCESS(status)) {
  470. REPORT_ERROR( DeviceExtension->DeviceType, "Pnp handler failed", status );
  471. }
  472. IoReleaseRemoveLock( &DeviceExtension->RemoveLock, Irp );
  473. return status;
  474. }