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.

1103 lines
26 KiB

  1. #include "mpio.h"
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. /*++
  5. Routine Description:
  6. Arguments:
  7. Return Value:
  8. --*/
  9. NTSTATUS
  10. MPIOStopDevice(
  11. IN PDEVICE_OBJECT DeviceObject,
  12. IN PIRP Irp
  13. )
  14. /*++
  15. Routine Description:
  16. This routine handles PnP Stop irps for the FDO (Control).
  17. Currently, it only sets status and forwards the Irp.
  18. Arguments:
  19. DeviceObject
  20. Irp
  21. Return Value:
  22. NTSTATUS
  23. --*/
  24. {
  25. //
  26. // TODO: Any stop stuff.
  27. //
  28. Irp->IoStatus.Status = STATUS_SUCCESS;
  29. return MPIOForwardRequest(DeviceObject, Irp);
  30. }
  31. NTSTATUS
  32. MPIOStartDevice(
  33. IN PDEVICE_OBJECT DeviceObject,
  34. IN PIRP Irp
  35. )
  36. /*++
  37. Routine Description:
  38. This routine handles PnP Start requests for the FDO
  39. Arguments:
  40. DeviceObject,
  41. Irp
  42. Return Value:
  43. --*/
  44. {
  45. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  46. KEVENT event;
  47. NTSTATUS status;
  48. //
  49. // The above minor functions need status set to success, set a completion routine,
  50. // send to the next driver, and wait. Once the event is signaled, complete the request.
  51. //
  52. KeInitializeEvent(&event, NotificationEvent, FALSE);
  53. //
  54. // Setup the initial status of the request.
  55. //
  56. Irp->IoStatus.Status = STATUS_SUCCESS;
  57. //
  58. // Clone the stack location.
  59. //
  60. IoCopyCurrentIrpStackLocationToNext(Irp);
  61. //
  62. // Set the completion routine.
  63. //
  64. IoSetCompletionRoutine(Irp,
  65. MPIOSyncCompletion,
  66. &event,
  67. TRUE,
  68. TRUE,
  69. TRUE);
  70. //
  71. // Call down.
  72. //
  73. status = IoCallDriver(deviceExtension->LowerDevice, Irp);
  74. if (status == STATUS_PENDING) {
  75. KeWaitForSingleObject(&event,
  76. Executive,
  77. KernelMode,
  78. FALSE,
  79. NULL);
  80. status = Irp->IoStatus.Status;
  81. }
  82. if (status == STATUS_SUCCESS) {
  83. //
  84. // TODO: Other 'start' stuff.
  85. //
  86. MPDebugPrint((2,
  87. "MPIOStartDevice: Successful start on (%x)\n",
  88. DeviceObject));
  89. status = Irp->IoStatus.Status;
  90. } else {
  91. MPDebugPrint((2,
  92. "MPIOStartDevice: Failure (%x) start on (%x)\n",
  93. status,
  94. DeviceObject));
  95. }
  96. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  97. return status;
  98. }
  99. NTSTATUS
  100. MPIOQDR(
  101. IN PDEVICE_OBJECT DeviceObject,
  102. IN PIRP Irp
  103. )
  104. {
  105. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  106. PCONTROL_EXTENSION controlExtension = deviceExtension->TypeExtension;
  107. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  108. PDEVICE_RELATIONS deviceRelations;
  109. PLIST_ENTRY entry;
  110. PDISK_ENTRY diskEntry;
  111. NTSTATUS status;
  112. ULONG allocationLength;
  113. ULONG i;
  114. if (irpStack->Parameters.QueryDeviceRelations.Type == BusRelations) {
  115. //
  116. // Allocate enough memory for NumberDevices.
  117. //
  118. allocationLength = (controlExtension->NumberDevices - 1) * sizeof(PDEVICE_OBJECT);
  119. allocationLength += sizeof(DEVICE_RELATIONS);
  120. deviceRelations = ExAllocatePool(PagedPool, allocationLength);
  121. if (deviceRelations == NULL) {
  122. Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  123. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  124. return STATUS_INSUFFICIENT_RESOURCES;
  125. }
  126. RtlZeroMemory(deviceRelations, allocationLength);
  127. //
  128. // Fill in the structure.
  129. //
  130. deviceRelations->Count = controlExtension->NumberDevices;
  131. for (i = 0; i < controlExtension->NumberDevices; i++) {
  132. diskEntry = MPIOGetDiskEntry(DeviceObject,
  133. i);
  134. ASSERT(diskEntry);
  135. deviceRelations->Objects[i] = diskEntry->PdoObject;
  136. ObReferenceObject(deviceRelations->Objects[i]);
  137. }
  138. //
  139. // Link it in and set status.
  140. //
  141. Irp->IoStatus.Information = (ULONG_PTR)deviceRelations;
  142. Irp->IoStatus.Status = STATUS_SUCCESS;
  143. MPDebugPrint((2,
  144. "MPIOQDR: Returned %x children. List %x\n",
  145. controlExtension->NumberDevices,
  146. deviceRelations));
  147. }
  148. //
  149. // Send it down.
  150. //
  151. return MPIOForwardRequest(DeviceObject, Irp);
  152. }
  153. NTSTATUS
  154. MPIOQueryId(
  155. IN PDEVICE_OBJECT DeviceObject,
  156. IN PIRP Irp
  157. )
  158. /*++
  159. Routine Description:
  160. This routine handles QueryId irps for the FDO (Control).
  161. Used by PnP to determine the id's used to locate the inf.
  162. Arguments:
  163. DeviceObject
  164. Irp
  165. Return Value:
  166. NTSTATUS
  167. --*/
  168. {
  169. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  170. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  171. NTSTATUS status;
  172. PWCHAR idString;
  173. PWCHAR returnString;
  174. ULONG length;
  175. ULONG size;
  176. switch (irpStack->Parameters.QueryId.IdType) {
  177. case BusQueryHardwareIDs:
  178. idString = L"ROOT\\MPIO";
  179. break;
  180. case BusQueryDeviceID:
  181. idString = L"ROOT\\MPIO";
  182. break;
  183. case BusQueryInstanceID:
  184. idString = L"0000";
  185. break;
  186. default:
  187. IoSkipCurrentIrpStackLocation(Irp);
  188. return IoCallDriver(deviceExtension->LowerDevice, Irp);
  189. }
  190. status = STATUS_SUCCESS;
  191. length = wcslen(idString);
  192. size = (length + 2) * sizeof(WCHAR);
  193. //
  194. // Allocate storage for the id string
  195. //
  196. returnString = ExAllocatePool(PagedPool, size);
  197. if (returnString == NULL) {
  198. status = STATUS_INSUFFICIENT_RESOURCES;
  199. } else {
  200. //
  201. // Copy it over
  202. //
  203. RtlZeroMemory(returnString, size);
  204. wcscpy(returnString, idString);
  205. //
  206. // Link it in, set status and send it down.
  207. //
  208. Irp->IoStatus.Status = STATUS_SUCCESS;
  209. Irp->IoStatus.Information = (ULONG_PTR)returnString;
  210. }
  211. Irp->IoStatus.Status = status;
  212. IoSkipCurrentIrpStackLocation(Irp);
  213. return IoCallDriver(deviceExtension->LowerDevice, Irp);
  214. }
  215. NTSTATUS
  216. MPIOFdoPnP(
  217. IN PDEVICE_OBJECT DeviceObject,
  218. IN PIRP Irp
  219. )
  220. /*++
  221. Routine Description:
  222. This routine handles PnP irps for the FDO (Control).
  223. Arguments:
  224. DeviceObject
  225. Irp
  226. Return Value:
  227. NTSTATUS
  228. --*/
  229. {
  230. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  231. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  232. KEVENT event;
  233. NTSTATUS status;
  234. switch (irpStack->MinorFunction) {
  235. case IRP_MN_STOP_DEVICE:
  236. //
  237. // Call the Stop handler.
  238. //
  239. return MPIOStopDevice(DeviceObject,
  240. Irp);
  241. case IRP_MN_START_DEVICE:
  242. //
  243. // 'Start' the FDO.
  244. //
  245. return MPIOStartDevice(DeviceObject,
  246. Irp);
  247. case IRP_MN_QUERY_DEVICE_RELATIONS:
  248. //
  249. // Build the list of children based on the current state of the world.
  250. //
  251. return MPIOQDR(DeviceObject,
  252. Irp);
  253. case IRP_MN_QUERY_ID:
  254. //
  255. // Call the QueryId routine. It will handle completion
  256. // of the request.
  257. //
  258. return MPIOQueryId(DeviceObject,
  259. Irp);
  260. case IRP_MN_QUERY_DEVICE_TEXT:
  261. MPDebugPrint((2,
  262. "Got QueryDeviceText\n"));
  263. default:
  264. MPDebugPrint((2,
  265. "MPIOFdoPnP: Default handler for Control (%x)\n",
  266. irpStack->MinorFunction));
  267. return MPIOForwardRequest(DeviceObject, Irp);
  268. }
  269. }
  270. NTSTATUS
  271. MPIOFdoPower(
  272. IN PDEVICE_OBJECT DeviceObject,
  273. IN PIRP Irp
  274. )
  275. /*++
  276. Routine Description:
  277. This routine handles Power irps for the FDO (Control). It'm main
  278. function is to sync up state with the adapter filter drivers.
  279. Arguments:
  280. DeviceObject
  281. Irp
  282. Return Value:
  283. NTSTATUS
  284. --*/
  285. {
  286. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  287. NTSTATUS status;
  288. //
  289. // TODO: Everything.
  290. //
  291. PoStartNextPowerIrp(Irp);
  292. IoSkipCurrentIrpStackLocation(Irp);
  293. status = PoCallDriver(deviceExtension->LowerDevice, Irp);
  294. return status;
  295. }
  296. NTSTATUS
  297. MPIOQueryPdo(
  298. IN PDEVICE_OBJECT ControlObject,
  299. IN PIRP Irp
  300. )
  301. /*++
  302. Routine Description:
  303. This routine determines whether the D.O. passed in the system buffer
  304. is one that mpctl created, or a real scsiport pdo.
  305. Arguments:
  306. DeviceObject
  307. Irp
  308. Return Value:
  309. STATUS_SUCCESS - if the D.O. is a child of mpctl
  310. --*/
  311. {
  312. PDEVICE_EXTENSION deviceExtension = ControlObject->DeviceExtension;
  313. PCONTROL_EXTENSION controlExtension = deviceExtension->TypeExtension;
  314. PMPIO_PDO_QUERY pdoQuery = Irp->AssociatedIrp.SystemBuffer;
  315. PDISK_ENTRY diskEntry;
  316. ULONG i;
  317. //
  318. // Run the disk list to see whether this one is real
  319. // or one of ours.
  320. //
  321. for (i = 0; i < controlExtension->NumberDevices; i++) {
  322. //
  323. // Get the next diskEntry.
  324. //
  325. diskEntry = MPIOGetDiskEntry(ControlObject,
  326. i);
  327. MPDebugPrint((2,
  328. "MPIOQueryPdo: Checking (%x) against QueryObject (%x)",
  329. diskEntry->PdoObject,
  330. pdoQuery->DeviceObject));
  331. //
  332. // The PdoObject is the D.O. for an MPDisk,
  333. // if the D.O. passed in from mpdev is the same, then
  334. // the filter should not load on this. Indicate the 'failure'
  335. // as success.
  336. //
  337. if (diskEntry->PdoObject == pdoQuery->DeviceObject) {
  338. MPDebugPrint((2,
  339. " -> Matched. Returning SUCCESS\n"));
  340. return STATUS_UNSUCCESSFUL;
  341. } else {
  342. MPDebugPrint((2,
  343. " -> No Match\n"));
  344. }
  345. }
  346. return STATUS_SUCCESS;
  347. }
  348. NTSTATUS
  349. MPIODeviceRegistration(
  350. IN PDEVICE_OBJECT DeviceObject,
  351. IN PIRP Irp
  352. )
  353. /*++
  354. Routine Description:
  355. This routine handles the initial registration of a device filter
  356. by matching up scsiport pdo, with MPDisk PDO.
  357. Arguments:
  358. DeviceObject
  359. Irp
  360. Return Value:
  361. STATUS_SUCCESS - if the LowerDevice was found in a MPDisk PDO's internal
  362. structures.
  363. --*/
  364. {
  365. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  366. PCONTROL_EXTENSION controlExtension = deviceExtension->TypeExtension;
  367. PMPIO_REG_INFO deviceReg = Irp->AssociatedIrp.SystemBuffer;
  368. PMPIO_REG_INFO regInfo = Irp->AssociatedIrp.SystemBuffer;
  369. PDEVICE_OBJECT lowerDevice;
  370. PDEVICE_OBJECT targetDevice;
  371. PDISK_ENTRY diskEntry;
  372. NTSTATUS status;
  373. ULONG i;
  374. BOOLEAN found = FALSE;
  375. lowerDevice = deviceReg->LowerDevice;
  376. targetDevice = deviceReg->FilterObject;
  377. //
  378. // Find the corresponding MPDisk for the 'LowerDevice'.
  379. // Call the magic routine with each of the MP PDO's, along with LowerDevice
  380. // It will return TRUE is the MP PDO controls it.
  381. //
  382. for (i = 0; i < controlExtension->NumberDevices; i++) {
  383. //
  384. // Get the next diskEntry.
  385. //
  386. diskEntry = MPIOGetDiskEntry(DeviceObject,
  387. i);
  388. //
  389. // Attempt to find a match for the newly arrived DO.
  390. //
  391. found = MPIOFindLowerDevice(diskEntry->PdoObject,
  392. lowerDevice);
  393. if (found == TRUE) {
  394. //
  395. // Indicate to the dev filter the MPDisk that
  396. // it talks to.
  397. //
  398. regInfo->MPDiskObject = diskEntry->PdoObject;
  399. break;
  400. }
  401. }
  402. if (found == FALSE) {
  403. status = STATUS_NO_SUCH_DEVICE;
  404. } else {
  405. status = STATUS_SUCCESS;
  406. //
  407. // Fill in the rest.
  408. // Defined in pdo.c
  409. //
  410. regInfo->DevicePdoRegister = MPIOPdoRegistration;
  411. Irp->IoStatus.Information = sizeof(MPIO_REG_INFO);
  412. }
  413. //
  414. // The caller will fill in status and complete the request.
  415. //
  416. return status;
  417. }
  418. NTSTATUS
  419. MPIOAdpPnpNotify(
  420. IN PDEVICE_OBJECT ControlObject,
  421. IN PDEVICE_OBJECT FilterObject,
  422. IN PIRP Irp
  423. )
  424. /*++
  425. Routine Description:
  426. This routine handles PnP notifications that originate from the Adapter Filter.
  427. It checks the Minor function and notifies the filter(s) on what action to take
  428. Arguments:
  429. ControlObject - Mpctl's D.O.
  430. FilterObject - The filter D.O.
  431. Irp - The pnp irp sent to FilterObject
  432. Return Value:
  433. --*/
  434. {
  435. //
  436. // TODO: Determine how best to handle this.
  437. //
  438. return STATUS_SUCCESS;
  439. }
  440. NTSTATUS
  441. MPIOAdpPowerNotify(
  442. IN PDEVICE_OBJECT ControlObject,
  443. IN PDEVICE_OBJECT FilterObject,
  444. IN PIRP Irp
  445. )
  446. /*++
  447. Routine Description:
  448. This routine handles Power notifications that originate from the Adapter Filter.
  449. It checks the Minor function and notifies the filter(s) on what action to take
  450. Arguments:
  451. ControlObject - Mpctl's D.O.
  452. FilterObject - The filter D.O.
  453. Irp - The power irp sent to FilterObject
  454. Return Value:
  455. status of the helper routines.
  456. --*/
  457. {
  458. //
  459. // TODO: Determine how best to handle this.
  460. //
  461. return STATUS_SUCCESS;
  462. }
  463. PDEVICE_RELATIONS
  464. MPIOBuildRelations(
  465. IN PADP_DEVICE_LIST DeviceList
  466. )
  467. {
  468. PDEVICE_RELATIONS relations;
  469. ULONG relationsSize;
  470. ULONG i;
  471. ULONG numberDevices = DeviceList->NumberDevices;
  472. //
  473. // Determine the size needed.
  474. //
  475. relationsSize = sizeof(DEVICE_RELATIONS);
  476. relationsSize += (sizeof(PDEVICE_OBJECT) * numberDevices - 1);
  477. relations = ExAllocatePool(NonPagedPool, relationsSize);
  478. RtlZeroMemory(relations, relationsSize);
  479. //
  480. // Copy over the D.O.s
  481. //
  482. relations->Count = DeviceList->NumberDevices;
  483. for (i = 0; i < numberDevices; i++) {
  484. relations->Objects[i] = DeviceList->DeviceList[i].DeviceObject;
  485. }
  486. return relations;
  487. }
  488. BOOLEAN
  489. MPIODetermineDeviceArrival(
  490. IN PADP_DEVICE_LIST DeviceList,
  491. IN PDEVICE_RELATIONS CachedRelations,
  492. IN PDEVICE_RELATIONS NewCachedRelations
  493. )
  494. {
  495. ULONG oldCount;
  496. ULONG newCount;
  497. ULONG i;
  498. oldCount = CachedRelations->Count;
  499. newCount = NewCachedRelations->Count;
  500. if (newCount > oldCount) {
  501. //
  502. // This always indicates a new device(s).
  503. //
  504. return TRUE;
  505. }
  506. //
  507. // Check the weird case where the objects are differnet,
  508. // but count remains the same (or is less).
  509. // TODO
  510. //
  511. return FALSE;
  512. }
  513. NTSTATUS
  514. MPIOAdpDeviceNotify(
  515. IN PDEVICE_OBJECT ControlObject,
  516. IN PDEVICE_OBJECT FilterObject,
  517. IN PDEVICE_OBJECT PortObject,
  518. IN PADP_DEVICE_LIST DeviceList
  519. )
  520. /*++
  521. Routine Description:
  522. This routine is called by the FilterObject when a QDR has occurred. It passes in a list
  523. of disk PDO's for processing.
  524. Arguments:
  525. ControlObject - The Mpctl DO
  526. FilterObject - The adapter filter's DO
  527. DeviceList - List of PDO's and associated structs.
  528. Return Value:
  529. --*/
  530. {
  531. PDEVICE_EXTENSION deviceExtension = ControlObject->DeviceExtension;
  532. PCONTROL_EXTENSION controlExtension = deviceExtension->TypeExtension;
  533. PDSM_ENTRY entry;
  534. PDISK_ENTRY diskEntry;
  535. NTSTATUS status;
  536. PVOID dsmExtension;
  537. PFLTR_ENTRY fltrEntry;
  538. ULONG numberDevices = DeviceList->NumberDevices;
  539. PDEVICE_RELATIONS cachedRelations;
  540. PDEVICE_RELATIONS newCachedRelations;
  541. BOOLEAN newList = FALSE;
  542. BOOLEAN added = FALSE;
  543. //
  544. // First, run through the lists and find out if any devices
  545. // have been removed.
  546. // Round One will be handling a removed path - ALL devices are gone.
  547. //
  548. //
  549. // Get the cached info, to see whether something has been removed.
  550. //
  551. fltrEntry = MPIOGetFltrEntry(ControlObject,
  552. PortObject,
  553. NULL);
  554. ASSERT(fltrEntry);
  555. //
  556. // See whether there is already a relations struct.
  557. //
  558. cachedRelations = fltrEntry->CachedRelations;
  559. if (cachedRelations == NULL) {
  560. cachedRelations = MPIOBuildRelations(DeviceList);
  561. //
  562. // Update the filter entry with the relations.
  563. //
  564. fltrEntry->CachedRelations = cachedRelations;
  565. newCachedRelations = cachedRelations;
  566. //
  567. // Indicate that this is the 'original' list.
  568. //
  569. newList = TRUE;
  570. added = TRUE;
  571. } else {
  572. //
  573. // Determine if any devices need to be removed.
  574. // If so, this routine will handle it.
  575. //
  576. newCachedRelations = MPIOHandleDeviceRemovals(ControlObject,
  577. DeviceList,
  578. cachedRelations);
  579. //
  580. // Update the cachedRelations to reflect the new state.
  581. //
  582. fltrEntry->CachedRelations = newCachedRelations;
  583. //
  584. // This is an update.
  585. //
  586. newList = FALSE;
  587. //
  588. // Determine whether any devices have been added.
  589. //
  590. added = MPIODetermineDeviceArrival(DeviceList,
  591. cachedRelations,
  592. newCachedRelations);
  593. }
  594. if (added) {
  595. if (fltrEntry->Flags & FLTR_FLAGS_NEED_RESCAN) {
  596. //
  597. // Indicate that the rescan is complete.
  598. //
  599. fltrEntry->Flags &= ~FLTR_FLAGS_RESCANNING;
  600. //
  601. // Clear the complete flags. The timer will handle
  602. // setting it.
  603. //
  604. fltrEntry->Flags &= ~FLTR_FLAGS_QDR_COMPLETE;
  605. //
  606. // Indicate that this adapter had a QDR.
  607. //
  608. fltrEntry->Flags |= FLTR_FLAGS_QDR;
  609. MPDebugPrint((0,
  610. "DeviceNotify: Flags (%x) on (%x)\n",
  611. fltrEntry->Flags,
  612. fltrEntry));
  613. }
  614. //
  615. // Handle dealing with any new objects.
  616. //
  617. status = MPIOHandleDeviceArrivals(ControlObject,
  618. DeviceList,
  619. cachedRelations,
  620. newCachedRelations,
  621. PortObject,
  622. FilterObject,
  623. newList);
  624. }
  625. if (newList == FALSE) {
  626. //
  627. // Free the old stuff.
  628. //
  629. ExFreePool(cachedRelations);
  630. }
  631. return STATUS_SUCCESS;
  632. }
  633. NTSTATUS
  634. MPIOAdapterRegistration(
  635. IN PDEVICE_OBJECT DeviceObject,
  636. IN PIRP Irp
  637. )
  638. /*++
  639. Routine Description:
  640. This routine is the main dispatch routine for Internal Device Controls sent
  641. to the FDO (Control). The control codes are those known to the device and adapter
  642. filters and to the DSMs.
  643. Arguments:
  644. DeviceObject
  645. Irp
  646. Return Value:
  647. status of the helper routines.
  648. --*/
  649. {
  650. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  651. PCONTROL_EXTENSION controlExtension = deviceExtension->TypeExtension;
  652. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  653. PADAPTER_REGISTER adapterReg = Irp->AssociatedIrp.SystemBuffer;
  654. PFLTR_ENTRY fltrEntry;
  655. //
  656. // Allocate an entry for this filter.
  657. //
  658. fltrEntry = ExAllocatePool(NonPagedPool, sizeof(FLTR_ENTRY));
  659. if (fltrEntry == NULL) {
  660. return STATUS_INSUFFICIENT_RESOURCES;
  661. }
  662. RtlZeroMemory(fltrEntry, sizeof(FLTR_ENTRY));
  663. fltrEntry->FilterObject = adapterReg->FilterObject;
  664. fltrEntry->PortFdo = adapterReg->PortFdo;
  665. fltrEntry->FltrGetDeviceList = adapterReg->FltrGetDeviceList;
  666. //
  667. // Add it to the list
  668. //
  669. ExInterlockedInsertTailList(&controlExtension->FilterList,
  670. &fltrEntry->ListEntry,
  671. &controlExtension->SpinLock);
  672. InterlockedIncrement(&controlExtension->NumberFilters);
  673. //
  674. // Fill in the entry points for the filter
  675. //
  676. adapterReg->PnPNotify = MPIOAdpPnpNotify;
  677. adapterReg->PowerNotify = MPIOAdpPowerNotify;
  678. adapterReg->DeviceNotify = MPIOAdpDeviceNotify;
  679. //
  680. // set Information
  681. //
  682. Irp->IoStatus.Information = sizeof(ADAPTER_REGISTER);
  683. Irp->IoStatus.Status = STATUS_SUCCESS;
  684. return STATUS_SUCCESS;
  685. }
  686. NTSTATUS
  687. MPIODsmRegistration(
  688. IN PDEVICE_OBJECT DeviceObject,
  689. IN PIRP Irp
  690. )
  691. {
  692. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  693. PCONTROL_EXTENSION controlExtension = deviceExtension->TypeExtension;
  694. PDSM_INIT_DATA initData = Irp->AssociatedIrp.SystemBuffer;
  695. PDSM_MPIO_CONTEXT context = Irp->AssociatedIrp.SystemBuffer;
  696. PDSM_ENTRY dsmEntry;
  697. PLIST_ENTRY oldEntry;
  698. PDSM_ENTRY oldDsm;
  699. WCHAR buffer[64];
  700. ASSERT(initData->InitDataSize == sizeof(DSM_INIT_DATA));
  701. //
  702. // Allocate an entry for the DSM Info.
  703. //
  704. dsmEntry = ExAllocatePool(NonPagedPool, sizeof(DSM_ENTRY));
  705. if (dsmEntry == NULL) {
  706. return STATUS_INSUFFICIENT_RESOURCES;
  707. }
  708. RtlZeroMemory(dsmEntry, sizeof(DSM_ENTRY));
  709. //
  710. // Extract the info from the DSM's buffer.
  711. //
  712. dsmEntry->InquireDriver = initData->DsmInquireDriver;
  713. dsmEntry->CompareDevices = initData->DsmCompareDevices;
  714. dsmEntry->SetDeviceInfo = initData->DsmSetDeviceInfo;
  715. dsmEntry->GetControllerInfo = initData->DsmGetControllerInfo;
  716. dsmEntry->IsPathActive = initData->DsmIsPathActive;
  717. dsmEntry->InvalidatePath = initData->DsmInvalidatePath;
  718. dsmEntry->PathVerify = initData->DsmPathVerify;
  719. dsmEntry->RemovePending = initData->DsmRemovePending;
  720. dsmEntry->RemoveDevice = initData->DsmRemoveDevice;
  721. dsmEntry->RemovePath = initData->DsmRemovePath;
  722. dsmEntry->SrbDeviceControl = initData->DsmSrbDeviceControl;
  723. dsmEntry->ReenablePath = initData->DsmReenablePath;
  724. dsmEntry->GetPath = initData->DsmLBGetPath;
  725. dsmEntry->InterpretError = initData->DsmInterpretError;
  726. dsmEntry->Unload = initData->DsmUnload;
  727. dsmEntry->SetCompletion = initData->DsmSetCompletion;
  728. dsmEntry->CategorizeRequest = initData->DsmCategorizeRequest;
  729. dsmEntry->BroadcastSrb = initData->DsmBroadcastSrb;
  730. RtlCopyMemory(&dsmEntry->WmiContext,
  731. &initData->DsmWmiInfo,
  732. sizeof(DSM_WMILIB_CONTEXT));
  733. dsmEntry->DsmContext = initData->DsmContext;
  734. //
  735. // Build the Name string.
  736. //
  737. dsmEntry->DisplayName.Buffer = ExAllocatePool(NonPagedPool,
  738. initData->DisplayName.MaximumLength);
  739. RtlZeroMemory(dsmEntry->DisplayName.Buffer,
  740. initData->DisplayName.MaximumLength);
  741. dsmEntry->DisplayName.Length = initData->DisplayName.Length;
  742. dsmEntry->DisplayName.MaximumLength = initData->DisplayName.MaximumLength;
  743. RtlCopyUnicodeString(&dsmEntry->DisplayName,
  744. &initData->DisplayName);
  745. //
  746. // Add it to the list
  747. //
  748. if (initData->Reserved == (ULONG)-1) {
  749. //
  750. // Gendsm goes to the end of the list.
  751. //
  752. oldEntry = ExInterlockedInsertTailList(&controlExtension->DsmList,
  753. &dsmEntry->ListEntry,
  754. &controlExtension->SpinLock);
  755. MPDebugPrint((1,
  756. "Loading it Last. dsmEntry was (%x)\n",
  757. CONTAINING_RECORD(oldEntry, DSM_ENTRY, ListEntry)));
  758. } else {
  759. oldEntry = ExInterlockedInsertHeadList(&controlExtension->DsmList,
  760. &dsmEntry->ListEntry,
  761. &controlExtension->SpinLock);
  762. MPDebugPrint((1,
  763. "Loading it first. dsmEntry was (%x)\n",
  764. CONTAINING_RECORD(oldEntry, DSM_ENTRY, ListEntry)));
  765. }
  766. //
  767. // Update the list count.
  768. //
  769. InterlockedIncrement(&controlExtension->NumberDSMs);
  770. //
  771. // Set-up the return buffer
  772. //
  773. context->MPIOContext = DeviceObject;
  774. //
  775. // Set Information
  776. //
  777. Irp->IoStatus.Information = sizeof(DSM_MPIO_CONTEXT);
  778. swprintf(buffer, L"DSM %ws, registered.", dsmEntry->DisplayName.Buffer);
  779. MPIOFireEvent(DeviceObject,
  780. L"MPIO",
  781. buffer,
  782. MPIO_INFORMATION);
  783. return STATUS_SUCCESS;
  784. }
  785. NTSTATUS
  786. MPIOFdoInternalDeviceControl(
  787. IN PDEVICE_OBJECT DeviceObject,
  788. IN PIRP Irp
  789. )
  790. /*++
  791. Routine Description:
  792. This routine is the main dispatch routine for Internal Device Controls sent
  793. to the FDO (Control). The control codes are those known to the device and adapter
  794. filters and to the DSMs.
  795. Arguments:
  796. DeviceObject
  797. Irp
  798. Return Value:
  799. status of the helper routines.
  800. --*/
  801. {
  802. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  803. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  804. NTSTATUS status;
  805. switch (irpStack->Parameters.DeviceIoControl.IoControlCode) {
  806. case IOCTL_MPDEV_QUERY_PDO:
  807. //
  808. // Mpdev sends this request to determine if the PDO given it
  809. // in it's AddDevice is a real D.O., or an MPDisk.
  810. //
  811. status = MPIOQueryPdo(DeviceObject,
  812. Irp);
  813. break;
  814. case IOCTL_MPDEV_REGISTER:
  815. //
  816. // Mpdev sends this on an AddDevice to notify that
  817. // an instatiation of the filter has arrived.
  818. //
  819. status = MPIODeviceRegistration(DeviceObject,
  820. Irp);
  821. break;
  822. case IOCTL_MPADAPTER_REGISTER:
  823. //
  824. // Mpspfltr sens this on it's AddDevice to notify that
  825. // it has arrived.
  826. //
  827. status = MPIOAdapterRegistration(DeviceObject,
  828. Irp);
  829. break;
  830. case IOCTL_MPDSM_REGISTER:
  831. //
  832. // A DSM has loaded. Handle getting it's entry point info.
  833. //
  834. status = MPIODsmRegistration(DeviceObject,
  835. Irp);
  836. break;
  837. default:
  838. status = STATUS_INVALID_DEVICE_REQUEST;
  839. break;
  840. }
  841. Irp->IoStatus.Status = status;
  842. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  843. return status;
  844. }