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.

1697 lines
45 KiB

  1. #include <wdm.h>
  2. #include <wmistr.h>
  3. #include <wmiguid.h>
  4. #include <wmilib.h>
  5. #include "mpio.h"
  6. #include "wmi.h"
  7. #include "pdowmi.h"
  8. #include <stdio.h>
  9. #define USE_BINARY_MOF_QUERY
  10. UCHAR MPIOBinaryMofData[] =
  11. {
  12. #include "wmi.x"
  13. };
  14. UCHAR PdoBinaryMofData[] =
  15. {
  16. #include "pdowmi.x"
  17. };
  18. //
  19. // Guid Index Symbolic Names.
  20. //
  21. #define MPIO_DISK_INFOGuidIndex 0
  22. #define MPIO_PATH_INFORMATIONGuidIndex 1
  23. #define MPIO_CONTROLLER_CONFIGURATIONGuidIndex 2
  24. #define MPIO_EventEntryGuidIndex 3
  25. #define MPIO_WmiBinaryMofGuidIndex 4
  26. //
  27. // Guid Index for Pdos
  28. //
  29. #define MPIO_GET_DESCRIPTORGuidIndex 0
  30. #define BinaryMofGuidIndex 1
  31. //
  32. // List of supported Guids.
  33. //
  34. GUID MPIO_DISK_INFOGUID = MPIO_DISK_INFOGuid;
  35. GUID MPIO_PATH_INFORMATIONGUID = MPIO_PATH_INFORMATIONGuid;
  36. GUID MPIO_CONTROLLER_CONFIGURATIONGUID = MPIO_CONTROLLER_CONFIGURATIONGuid;
  37. GUID MPIO_EventEntryGUID = MPIO_EventEntryGuid;
  38. GUID MPIOWmiBinaryMofGUID = BINARY_MOF_GUID;
  39. WMIGUIDREGINFO MPIOWmiGuidList[] =
  40. {
  41. {
  42. &MPIO_DISK_INFOGUID,
  43. 1,
  44. 0
  45. },
  46. {
  47. &MPIO_PATH_INFORMATIONGUID,
  48. 1,
  49. 0
  50. },
  51. {
  52. &MPIO_CONTROLLER_CONFIGURATIONGUID,
  53. 1,
  54. 0
  55. },
  56. {
  57. &MPIO_EventEntryGUID,
  58. 1,
  59. 0
  60. },
  61. {
  62. &MPIOWmiBinaryMofGUID,
  63. 1,
  64. 0
  65. }
  66. };
  67. #define MPIO_GUID_COUNT (sizeof(MPIOWmiGuidList) / sizeof(WMIGUIDREGINFO))
  68. GUID MPIO_GET_DESCRIPTORGUID = MPIO_GET_DESCRIPTORGuid;
  69. GUID PdowmiBinaryMofGUID = BINARY_MOF_GUID;
  70. WMIGUIDREGINFO PdowmiGuidList[] =
  71. {
  72. {
  73. &MPIO_GET_DESCRIPTORGUID,
  74. 1,
  75. 0
  76. },
  77. {
  78. &PdowmiBinaryMofGUID,
  79. 1,
  80. 0
  81. }
  82. };
  83. #define PdowmiGuidCount (sizeof(PdowmiGuidList) / sizeof(WMIGUIDREGINFO))
  84. NTSTATUS
  85. MPIOQueryRegInfo(
  86. IN PDEVICE_OBJECT DeviceObject,
  87. OUT PULONG RegFlags,
  88. OUT PUNICODE_STRING InstanceName,
  89. OUT PUNICODE_STRING *RegistryPath,
  90. OUT PUNICODE_STRING MofResourceName,
  91. OUT PDEVICE_OBJECT *Pdo
  92. )
  93. {
  94. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  95. UNICODE_STRING nameString;
  96. ANSI_STRING ansiString;
  97. UCHAR instanceName[] = "Multi-Path Disk";
  98. //
  99. // Return a pointer to the reg. path. Wmi needs this for some reason.
  100. //
  101. *RegistryPath = &deviceExtension->RegistryPath;
  102. if (FALSE) { //deviceExtension->Type == MPIO_MPDISK) {
  103. RtlInitAnsiString(&ansiString, instanceName);
  104. RtlAnsiStringToUnicodeString(InstanceName, &ansiString, TRUE);
  105. *RegFlags = WMIREG_FLAG_INSTANCE_BASENAME;
  106. } else {
  107. //
  108. // Indicate that instance names should be auto-generated.
  109. //
  110. *RegFlags = WMIREG_FLAG_INSTANCE_PDO;
  111. //
  112. // Set the PDO.
  113. //
  114. *Pdo = deviceExtension->Pdo;
  115. }
  116. return STATUS_SUCCESS;
  117. }
  118. ULONG
  119. MPIOGetDriveInfoSize(
  120. IN PDEVICE_OBJECT DeviceObject
  121. )
  122. {
  123. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  124. PMPDISK_EXTENSION diskExtension = deviceExtension->TypeExtension;
  125. PDSM_ENTRY dsm = &diskExtension->DsmInfo;
  126. ULONG length;
  127. WCHAR buffer[64];
  128. PUCHAR serialNumber;
  129. ULONG serialNumberLength;
  130. //
  131. // Determine name length.
  132. // \Device\MPIODisk(N)
  133. //
  134. swprintf(buffer, L"MPIO Disk%0d", diskExtension->DeviceOrdinal);
  135. length = wcslen(buffer) + 1;
  136. length *= sizeof(WCHAR);
  137. //
  138. // Add in a USHORT to account for the 'Length' field.
  139. //
  140. length += sizeof(USHORT);
  141. //
  142. // Add a ULONG size. (NumberPaths)
  143. //
  144. length += sizeof(ULONG);
  145. //
  146. // Determine SN size.
  147. //
  148. serialNumber = (PUCHAR)diskExtension->DeviceDescriptor;
  149. (ULONG_PTR)serialNumber += diskExtension->DeviceDescriptor->SerialNumberOffset;
  150. serialNumberLength = strlen(serialNumber) + 1;
  151. //
  152. // Length of the buffer.
  153. //
  154. length += (serialNumberLength * sizeof(WCHAR));
  155. //
  156. // Length of the 'length' field.
  157. //
  158. length += sizeof(USHORT);
  159. //
  160. // Get the DSM Name.
  161. //
  162. length += dsm->DisplayName.Length;
  163. length += sizeof(USHORT);
  164. length += sizeof(UNICODE_NULL);
  165. if (length & 3) {
  166. length += sizeof(ULONG);
  167. length &= ~(sizeof(ULONG) - 1);
  168. }
  169. return length;
  170. }
  171. ULONG
  172. MPIOBuildDriveInfo(
  173. IN PDEVICE_OBJECT DeviceObject,
  174. IN OUT PWCHAR Buffer
  175. )
  176. {
  177. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  178. PMPDISK_EXTENSION diskExtension = deviceExtension->TypeExtension;
  179. PDSM_ENTRY dsm = &diskExtension->DsmInfo;
  180. PREAL_DEV_INFO targetInfo;
  181. WCHAR nameBuffer[64];
  182. PWCHAR buffer;
  183. PUCHAR serialNumber;
  184. ANSI_STRING ansiSerialNumber;
  185. UNICODE_STRING unicodeString;
  186. ULONG i;
  187. ULONG stringLength;
  188. ULONG totalLength;
  189. BOOLEAN freeBuffer = FALSE;
  190. buffer = Buffer;
  191. *((PULONG)buffer) = diskExtension->DsmIdList.Count;
  192. totalLength = sizeof(ULONG);
  193. (PUCHAR)buffer += sizeof(ULONG);
  194. //
  195. // Build the string locally.
  196. //
  197. swprintf(nameBuffer, L"MPIO Disk%0d", diskExtension->DeviceOrdinal);
  198. //
  199. // Get the number of characters + 1 (for the terminating NULL).
  200. //
  201. stringLength = wcslen(nameBuffer) + 1;
  202. //
  203. // Convert length to WCHAR sized.
  204. //
  205. stringLength *= sizeof(WCHAR);
  206. //
  207. // The WMI strings are sort-of unicode strings. They have a length, but not
  208. // maximum length.
  209. // Indicate the Length.
  210. //
  211. *((PUSHORT)buffer) = (USHORT)stringLength;
  212. (PUCHAR)buffer += sizeof(USHORT);
  213. MPDebugPrint((0,
  214. "Buffer (%x) Length (%x)\n", buffer, stringLength));
  215. //
  216. // Copy the string.
  217. //
  218. RtlCopyMemory(buffer,
  219. nameBuffer,
  220. stringLength);
  221. //
  222. // Return the length of the string (plus NULL term.) + the USHORT length field.
  223. //
  224. totalLength += stringLength + sizeof(USHORT);
  225. //
  226. // Build the serial Number.
  227. //
  228. (PUCHAR)buffer += stringLength;
  229. if (diskExtension->DeviceDescriptor->SerialNumberOffset == (ULONG)-1) {
  230. *((PUSHORT)Buffer) = 0;
  231. unicodeString.Length = sizeof(USHORT);
  232. //
  233. // No buffer to free.
  234. //
  235. freeBuffer = FALSE;
  236. } else {
  237. serialNumber = (PUCHAR)diskExtension->DeviceDescriptor;
  238. (ULONG_PTR)serialNumber += diskExtension->DeviceDescriptor->SerialNumberOffset;
  239. RtlInitAnsiString(&ansiSerialNumber, serialNumber);
  240. RtlAnsiStringToUnicodeString(&unicodeString, &ansiSerialNumber, TRUE);
  241. //
  242. // Set the serial Number Length, and move the pointer
  243. // to the string location.
  244. //
  245. *((PUSHORT)buffer) = unicodeString.Length + sizeof(UNICODE_NULL);
  246. (PUCHAR)buffer += sizeof(USHORT);
  247. MPDebugPrint((0,
  248. "Buffer (%x) Length (%x)\n", buffer, unicodeString.Length));
  249. //
  250. // Copy the serialNumber.
  251. //
  252. RtlCopyMemory(buffer,
  253. unicodeString.Buffer,
  254. unicodeString.Length);
  255. totalLength += unicodeString.Length + sizeof(USHORT);
  256. totalLength += sizeof(UNICODE_NULL);
  257. //
  258. // Indicate that the unicode buffer was actually allocated.
  259. //
  260. freeBuffer = TRUE;
  261. }
  262. //
  263. // Push the buffer to the next string location.
  264. //
  265. // CHUCKP - just added the sizeof(UNICOE_NULL)...
  266. //
  267. (PUCHAR)buffer += unicodeString.Length;
  268. (PUCHAR)buffer += sizeof(UNICODE_NULL);
  269. //
  270. // Free up the Unicode string, as it's no longer needed.
  271. //
  272. if (freeBuffer) {
  273. RtlFreeUnicodeString(&unicodeString);
  274. }
  275. MPDebugPrint((0,
  276. "Buffer (%x) Length (%x)\n", buffer, dsm->DisplayName.Length));
  277. //
  278. // Set the size of the DSM's name.
  279. //
  280. *((PUSHORT)buffer) = dsm->DisplayName.Length + sizeof(UNICODE_NULL);
  281. (PUCHAR)buffer += sizeof(USHORT);
  282. RtlCopyMemory(buffer,
  283. dsm->DisplayName.Buffer,
  284. dsm->DisplayName.Length);
  285. //
  286. // Need to account for a NULL at the end of this.
  287. //
  288. totalLength += sizeof(UNICODE_NULL);
  289. //
  290. // update the returned length for the Length field and
  291. // the string itself.
  292. //
  293. totalLength += dsm->DisplayName.Length + sizeof(USHORT);
  294. return totalLength;
  295. }
  296. MPIOGetPathInfoSize(
  297. IN PDEVICE_OBJECT DeviceObject
  298. )
  299. {
  300. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  301. PCONTROL_EXTENSION controlExtension = deviceExtension->TypeExtension;
  302. PLIST_ENTRY entry;
  303. PID_ENTRY id;
  304. ULONG dataLength;
  305. ULONG stringLength;
  306. ULONG i;
  307. dataLength = sizeof(ULONG);
  308. entry = controlExtension->IdList.Flink;
  309. for (i = 0; i < controlExtension->NumberPaths; i++) {
  310. if (dataLength & 7) {
  311. dataLength += sizeof(LONGLONG);
  312. dataLength &= ~(sizeof(LONGLONG) - 1);
  313. }
  314. dataLength += sizeof(LONGLONG);
  315. dataLength += sizeof(UCHAR) * 4;
  316. id = CONTAINING_RECORD(entry, ID_ENTRY, ListEntry);
  317. stringLength = id->AdapterName.Length + sizeof(USHORT);
  318. if (stringLength & 3) {
  319. stringLength += sizeof(ULONG);
  320. stringLength &= ~(sizeof(ULONG) -1);
  321. }
  322. dataLength += stringLength;
  323. }
  324. return dataLength;
  325. }
  326. NTSTATUS
  327. MPIOBuildPathInfo(
  328. IN PDEVICE_OBJECT DeviceObject,
  329. IN PUCHAR Buffer
  330. )
  331. {
  332. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  333. PCONTROL_EXTENSION controlExtension = deviceExtension->TypeExtension;
  334. ULONG dataLength;
  335. PLIST_ENTRY entry;
  336. PID_ENTRY id;
  337. ULONG i;
  338. USHORT stringLength;
  339. PUCHAR buffer = Buffer;
  340. *((PULONG)buffer) = controlExtension->NumberPaths;
  341. buffer += sizeof(ULONG);
  342. entry = controlExtension->IdList.Flink;
  343. for (i = 0; i < controlExtension->NumberPaths; i++) {
  344. if ((ULONG_PTR)buffer & 7) {
  345. (ULONG_PTR)buffer += sizeof(LONGLONG);
  346. (ULONG_PTR)buffer &= ~(sizeof(LONGLONG) - 1);
  347. }
  348. id = CONTAINING_RECORD(entry, ID_ENTRY, ListEntry);
  349. if (id->UIDValid == FALSE) {
  350. id->UID = MPIOCreateUID(DeviceObject,
  351. id->PathID);
  352. }
  353. *((PLONGLONG)buffer) = id->UID;
  354. //
  355. // Need the adapter location.
  356. // The Bus Number.
  357. //
  358. (ULONG_PTR)buffer += sizeof(LONGLONG);
  359. *buffer = id->Address.Bus;
  360. //
  361. // The device.
  362. //
  363. (ULONG_PTR)buffer += 1;
  364. *buffer = id->Address.Device;
  365. //
  366. // The function.
  367. //
  368. (ULONG_PTR)buffer += 1;
  369. *buffer = id->Address.Function;
  370. //
  371. // Zero the padding byte.
  372. //
  373. (ULONG_PTR)buffer += 1;
  374. *buffer = 0;
  375. (ULONG_PTR)buffer += 1;
  376. //
  377. // Need the adapter friendly name...
  378. //
  379. stringLength = id->AdapterName.Length;
  380. *((PUSHORT)buffer) = stringLength;
  381. (ULONG_PTR)buffer += sizeof(USHORT);
  382. RtlCopyMemory(buffer,
  383. id->AdapterName.Buffer,
  384. id->AdapterName.Length);
  385. (ULONG_PTR)buffer += stringLength;
  386. //
  387. // Get the next path struct.
  388. //
  389. entry = entry->Flink;
  390. }
  391. return STATUS_SUCCESS;
  392. }
  393. ULONG
  394. MPIOGetControllerInfoSize(
  395. IN PDEVICE_OBJECT DeviceObject
  396. )
  397. {
  398. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  399. PCONTROL_EXTENSION controlExtension = deviceExtension->TypeExtension;
  400. PLIST_ENTRY entry;
  401. PCONTROLLER_ENTRY controller;
  402. ULONG dataLength;
  403. ULONG stringLength;
  404. ULONG i;
  405. dataLength = sizeof(ULONG);
  406. entry = controlExtension->ControllerList.Flink;
  407. for (i = 0; i < controlExtension->NumberControllers; i++) {
  408. //
  409. // ControllerId.
  410. //
  411. if (dataLength & 7) {
  412. dataLength += sizeof(LONGLONG);
  413. dataLength &= ~(sizeof(LONGLONG) - 1);
  414. }
  415. dataLength += sizeof(LONGLONG);
  416. //
  417. // ControllerSate.
  418. //
  419. dataLength += sizeof(ULONG);
  420. controller = CONTAINING_RECORD(entry, CONTROLLER_ENTRY, ListEntry);
  421. stringLength = controller->Dsm->DisplayName.Length + sizeof(USHORT);
  422. if (stringLength & 3) {
  423. stringLength += sizeof(ULONG);
  424. stringLength &= ~(sizeof(ULONG) -1);
  425. }
  426. dataLength += stringLength;
  427. entry = entry->Flink;
  428. }
  429. return dataLength;
  430. }
  431. NTSTATUS
  432. MPIOGetControllerInfo(
  433. IN PDEVICE_OBJECT DeviceObject,
  434. IN PUCHAR Buffer
  435. )
  436. {
  437. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  438. PCONTROL_EXTENSION controlExtension = deviceExtension->TypeExtension;
  439. ULONG dataLength;
  440. PLIST_ENTRY entry;
  441. PCONTROLLER_ENTRY controller;
  442. ULONG i;
  443. USHORT stringLength;
  444. PUCHAR buffer = Buffer;
  445. *((PULONG)buffer) = controlExtension->NumberControllers;
  446. buffer += sizeof(ULONG);
  447. entry = controlExtension->ControllerList.Flink;
  448. for (i = 0; i < controlExtension->NumberControllers; i++) {
  449. if ((ULONG_PTR)buffer & 7) {
  450. (ULONG_PTR)buffer += sizeof(LONGLONG);
  451. (ULONG_PTR)buffer &= ~(sizeof(LONGLONG) - 1);
  452. }
  453. controller = CONTAINING_RECORD(entry, CONTROLLER_ENTRY, ListEntry);
  454. *((PLONGLONG)buffer) = controller->ControllerInfo->ControllerIdentifier;
  455. (ULONG_PTR)buffer += sizeof(LONGLONG);
  456. *((PULONG)buffer) = controller->ControllerInfo->State;
  457. (ULONG_PTR)buffer += sizeof(ULONG);
  458. //
  459. // Build the dsm name.
  460. //
  461. stringLength = controller->Dsm->DisplayName.Length;
  462. *((PUSHORT)buffer) = stringLength;
  463. (ULONG_PTR)buffer += sizeof(USHORT);
  464. RtlCopyMemory(buffer,
  465. controller->Dsm->DisplayName.Buffer,
  466. controller->Dsm->DisplayName.Length);
  467. (ULONG_PTR)buffer += stringLength;
  468. //
  469. // Get the next path struct.
  470. //
  471. entry = entry->Flink;
  472. }
  473. return STATUS_SUCCESS;
  474. }
  475. NTSTATUS
  476. MPIOQueryDataBlock(
  477. IN PDEVICE_OBJECT DeviceObject,
  478. IN PIRP Irp,
  479. IN ULONG GuidIndex,
  480. IN ULONG InstanceIndex,
  481. IN ULONG InstanceCount,
  482. IN OUT PULONG InstanceLengthArray,
  483. IN ULONG BufferAvailable,
  484. OUT PUCHAR Buffer
  485. )
  486. {
  487. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  488. PCONTROL_EXTENSION controlExtension = deviceExtension->TypeExtension;
  489. NTSTATUS status;
  490. ULONG dataLength;
  491. ULONG i;
  492. PDISK_ENTRY diskEntry;
  493. switch (GuidIndex) {
  494. case MPIO_DISK_INFOGuidIndex: {
  495. PCONTROL_EXTENSION controlExtension = deviceExtension->TypeExtension;
  496. PMPIO_DISK_INFO diskInfo;
  497. LARGE_INTEGER systemTime;
  498. ULONG stringLength;
  499. ULONG driveInfoLength;
  500. ULONG length2;
  501. //
  502. // Check data length to ensure buffer is large enough.
  503. //
  504. dataLength = sizeof(ULONG);
  505. //
  506. // Add the length to handle the DRIVE_INFO structs for each
  507. // MPDisk.
  508. //
  509. for (i = 0; i < controlExtension->NumberDevices; i++) {
  510. diskEntry = MPIOGetDiskEntry(DeviceObject, i);
  511. driveInfoLength = MPIOGetDriveInfoSize(diskEntry->PdoObject);
  512. MPDebugPrint((0,
  513. "QueryDataBlock: DriveInfoLength (%x)\n",
  514. driveInfoLength));
  515. dataLength += driveInfoLength;
  516. }
  517. MPDebugPrint((0,
  518. "MPIOQueryDataBlock: Length is (%x)\n", dataLength));
  519. if (dataLength > BufferAvailable) {
  520. //
  521. // It's not. Report the size needed back to WMI.
  522. //
  523. status = STATUS_BUFFER_TOO_SMALL;
  524. } else {
  525. PWCHAR buffer;
  526. ULONG length;
  527. RtlZeroMemory(Buffer, dataLength);
  528. //
  529. // Indicate the number of PDO's we've created.
  530. //
  531. diskInfo = (PMPIO_DISK_INFO)Buffer;
  532. diskInfo->NumberDrives = controlExtension->NumberDevices;
  533. buffer = (PWCHAR)diskInfo->DriveInfo;
  534. for (i = 0; i < controlExtension->NumberDevices; i++) {
  535. diskEntry = MPIOGetDiskEntry(DeviceObject, i);
  536. length = MPIOBuildDriveInfo(diskEntry->PdoObject,
  537. buffer);
  538. MPDebugPrint((0,
  539. "BuildDriveInfo Length (%x) buffer (%x)\n", length, buffer));
  540. (PUCHAR)buffer += length;
  541. if ((ULONG_PTR)buffer & 3) {
  542. (ULONG_PTR)buffer += sizeof(ULONG);
  543. (ULONG_PTR)buffer &= ~(sizeof(ULONG) - 1);
  544. }
  545. MPDebugPrint((0,
  546. "After fixup buffer (%x)\n",buffer));
  547. }
  548. *InstanceLengthArray = dataLength;
  549. status = STATUS_SUCCESS;
  550. }
  551. break;
  552. }
  553. case MPIO_PATH_INFORMATIONGuidIndex: {
  554. dataLength = MPIOGetPathInfoSize(DeviceObject);
  555. if (dataLength > BufferAvailable) {
  556. status = STATUS_BUFFER_TOO_SMALL;
  557. } else {
  558. status = MPIOBuildPathInfo(DeviceObject,
  559. Buffer);
  560. *InstanceLengthArray = dataLength;
  561. }
  562. break;
  563. }
  564. case MPIO_CONTROLLER_CONFIGURATIONGuidIndex: {
  565. //
  566. // Determine the buffer size needed.
  567. //
  568. dataLength = MPIOGetControllerInfoSize(DeviceObject);
  569. if (dataLength > BufferAvailable) {
  570. status = STATUS_BUFFER_TOO_SMALL;
  571. } else {
  572. status = MPIOGetControllerInfo(DeviceObject,
  573. Buffer);
  574. *InstanceLengthArray = dataLength;
  575. }
  576. break;
  577. }
  578. case MPIO_EventEntryGuidIndex:
  579. //
  580. // This is an event. Set zero info and
  581. // return.
  582. //
  583. *InstanceLengthArray = 0;
  584. status = STATUS_SUCCESS;
  585. break;
  586. case MPIO_WmiBinaryMofGuidIndex:
  587. //
  588. // Need to copy over the mof data.
  589. //
  590. dataLength = sizeof(MPIOBinaryMofData);
  591. //
  592. // Ensure that the buffer is large enough.
  593. //
  594. if (dataLength > BufferAvailable) {
  595. //
  596. // dataLength is passed back to the WmiLib
  597. // so it can adjust.
  598. //
  599. status = STATUS_BUFFER_TOO_SMALL;
  600. } else {
  601. RtlCopyMemory(Buffer, MPIOBinaryMofData, dataLength);
  602. *InstanceLengthArray = dataLength;
  603. status = STATUS_SUCCESS;
  604. }
  605. break;
  606. default:
  607. status = STATUS_WMI_GUID_NOT_FOUND;
  608. break;
  609. }
  610. //
  611. // Complete the request.
  612. //
  613. status = WmiCompleteRequest(DeviceObject,
  614. Irp,
  615. status,
  616. dataLength,
  617. IO_NO_INCREMENT);
  618. return status;
  619. }
  620. NTSTATUS
  621. MPIOWmiControl(
  622. IN PDEVICE_OBJECT DeviceObject,
  623. IN PIRP Irp,
  624. IN ULONG GuidIndex,
  625. IN WMIENABLEDISABLECONTROL Function,
  626. IN BOOLEAN Enable
  627. )
  628. {
  629. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  630. NTSTATUS status;
  631. switch (GuidIndex) {
  632. case MPIO_EventEntryGuidIndex:
  633. if (Enable) {
  634. //
  635. // Indicate that it's OK to fire the Log event.
  636. //
  637. deviceExtension->FireLogEvent = TRUE;
  638. } else {
  639. //
  640. // Turn off firing the logger.
  641. //
  642. deviceExtension->FireLogEvent = FALSE;
  643. }
  644. MPDebugPrint((0,
  645. "MPIOWmiControl: Turning the Logger (%s) on (%x)\n",
  646. Enable ? "ON" : "OFF",
  647. DeviceObject));
  648. break;
  649. default:
  650. status = STATUS_WMI_GUID_NOT_FOUND;
  651. break;
  652. }
  653. status = WmiCompleteRequest(DeviceObject,
  654. Irp,
  655. status,
  656. 0,
  657. IO_NO_INCREMENT);
  658. return status;
  659. }
  660. //
  661. // PDO Call-Backs.
  662. //
  663. ULONG
  664. MPIOGetDescriptorSize(
  665. IN PDEVICE_OBJECT DeviceObject
  666. )
  667. {
  668. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  669. PMPDISK_EXTENSION diskExtension = deviceExtension->TypeExtension;
  670. PREAL_DEV_INFO targetInfo = diskExtension->TargetInfo;
  671. ULONG dataLength = 0;
  672. NTSTATUS status;
  673. ULONG i;
  674. ULONG stringLength;
  675. ULONG bytesRequired;
  676. //
  677. // NumberPdos
  678. //
  679. dataLength = sizeof(ULONG);
  680. if (diskExtension->HasName == FALSE) {
  681. //
  682. // Get the name of the first PortPdo - being as it's
  683. // the same device, the name remains the same for all.
  684. //
  685. status = IoGetDeviceProperty(targetInfo->PortPdo,
  686. DevicePropertyFriendlyName,
  687. diskExtension->PdoName.MaximumLength,
  688. diskExtension->PdoName.Buffer,
  689. &bytesRequired);
  690. if (status == STATUS_SUCCESS) {
  691. MPDebugPrint((0,
  692. "GetDescriptor: size of name is (%x)\n",
  693. bytesRequired));
  694. //
  695. // The buffer is NULL terminated. Reduce it.
  696. //
  697. bytesRequired -= sizeof(UNICODE_NULL);
  698. stringLength = sizeof(USHORT);
  699. stringLength += bytesRequired;
  700. diskExtension->HasName = TRUE;
  701. //
  702. // Align the buffer size.
  703. //
  704. if (stringLength & 3) {
  705. MPDebugPrint((0,
  706. "GetDescriptor: Need to align (%x\n",
  707. stringLength));
  708. stringLength += sizeof(ULONG);
  709. stringLength &= ~(sizeof(ULONG) -1);
  710. }
  711. MPDebugPrint((0,
  712. "GetDescriptor: size of name is now (%x). StrLeng (%x)\n",
  713. bytesRequired,
  714. stringLength));
  715. diskExtension->PdoName.Length = (USHORT)bytesRequired;
  716. } else {
  717. MPDebugPrint((0,
  718. "MPIOGetDescriptor: Buffer not large enough (%lu)\n",
  719. bytesRequired));
  720. }
  721. } else {
  722. stringLength = sizeof(USHORT);
  723. stringLength += diskExtension->PdoName.Length;
  724. if (stringLength & 3) {
  725. stringLength += sizeof(ULONG);
  726. stringLength &= ~(sizeof(ULONG) -1);
  727. }
  728. }
  729. //
  730. // Length of the string + the size field.
  731. //
  732. dataLength += stringLength;
  733. for (i = 0; i < diskExtension->DsmIdList.Count; i++) {
  734. //
  735. // Length of the scsi address.
  736. //
  737. dataLength += sizeof(SCSI_ADDR);
  738. //
  739. // Path Identifier.
  740. //
  741. dataLength += sizeof(LONGLONG);
  742. //
  743. // Controller ID.
  744. //
  745. dataLength += sizeof(ULONGLONG);
  746. if (dataLength & 7) {
  747. dataLength += sizeof(LONGLONG);
  748. dataLength &= ~(sizeof(LONGLONG) - 1);
  749. }
  750. //
  751. // Get the next targetInfo.
  752. //
  753. targetInfo++;
  754. }
  755. MPDebugPrint((0,
  756. "GetDescriptor: Total Length (%x)\n",
  757. dataLength));
  758. return dataLength;
  759. }
  760. NTSTATUS
  761. MPIOBuildDescriptor(
  762. IN PDEVICE_OBJECT DeviceObject,
  763. IN PUCHAR Buffer
  764. )
  765. {
  766. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  767. PMPDISK_EXTENSION diskExtension = deviceExtension->TypeExtension;
  768. PREAL_DEV_INFO targetInfo = diskExtension->TargetInfo;
  769. PMPIO_GET_DESCRIPTOR descriptor = (PMPIO_GET_DESCRIPTOR)Buffer;
  770. NTSTATUS status;
  771. PUCHAR buffer;
  772. ULONG i;
  773. PSCSI_ADDR scsiAddress;
  774. descriptor->NumberPdos = diskExtension->DsmIdList.Count;
  775. buffer = Buffer;
  776. buffer += sizeof(ULONG);
  777. //
  778. // Set the string length.
  779. //
  780. *((PUSHORT)buffer) = diskExtension->PdoName.Length;
  781. buffer += sizeof(USHORT);
  782. //
  783. // Copy it over.
  784. //
  785. RtlCopyMemory(buffer,
  786. diskExtension->PdoName.Buffer,
  787. diskExtension->PdoName.Length);
  788. //
  789. // Push it to the end of the string.
  790. //
  791. buffer += diskExtension->PdoName.Length;
  792. //
  793. // ULONG align.
  794. //
  795. if ((ULONG_PTR)buffer & 3) {
  796. (ULONG_PTR)buffer += sizeof(ULONG);
  797. (ULONG_PTR)buffer &= ~(sizeof(ULONG) - 1);
  798. }
  799. for (i = 0; i < diskExtension->DsmIdList.Count; i++) {
  800. scsiAddress = (PSCSI_ADDR)buffer;
  801. scsiAddress->PortNumber = targetInfo->ScsiAddress.PortNumber;
  802. scsiAddress->ScsiPathId = targetInfo->ScsiAddress.PathId;
  803. scsiAddress->TargetId = targetInfo->ScsiAddress.TargetId;
  804. scsiAddress->Lun = targetInfo->ScsiAddress.Lun;
  805. buffer += sizeof(SCSI_ADDR);
  806. if (targetInfo->PathUIDValue == FALSE) {
  807. targetInfo->Identifier = MPIOCreateUID(diskExtension->ControlObject,
  808. targetInfo->PathId);
  809. ASSERT(targetInfo->Identifier != 0);
  810. targetInfo->PathUIDValue = TRUE;
  811. }
  812. //
  813. // Align the buffer
  814. //
  815. if ((ULONG_PTR)buffer & 7) {
  816. (ULONG_PTR)buffer += sizeof(LONGLONG);
  817. (ULONG_PTR)buffer &= ~(sizeof(LONGLONG) - 1);
  818. }
  819. *((PLONGLONG)buffer) = targetInfo->Identifier;
  820. buffer += sizeof(LONGLONG);
  821. //
  822. // Get the controllerID.
  823. //
  824. *((PULONGLONG)buffer) = targetInfo->ControllerId;
  825. buffer += sizeof(ULONGLONG);
  826. //
  827. // Handle the next device.
  828. //
  829. targetInfo++;
  830. }
  831. return STATUS_SUCCESS;
  832. }
  833. NTSTATUS
  834. MPIOPdoQueryDataBlock(
  835. IN PDEVICE_OBJECT DeviceObject,
  836. IN PIRP Irp,
  837. IN ULONG GuidIndex,
  838. IN ULONG InstanceIndex,
  839. IN ULONG InstanceCount,
  840. IN OUT PULONG InstanceLengthArray,
  841. IN ULONG BufferAvailable,
  842. OUT PUCHAR Buffer
  843. )
  844. {
  845. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  846. PMPDISK_EXTENSION diskExtension = deviceExtension->TypeExtension;
  847. PDSM_ENTRY dsm = &diskExtension->DsmInfo;
  848. NTSTATUS status;
  849. ULONG dataLength;
  850. switch(GuidIndex) {
  851. case MPIO_GET_DESCRIPTORGuidIndex: {
  852. dataLength = MPIOGetDescriptorSize(DeviceObject);
  853. if (dataLength > BufferAvailable) {
  854. status = STATUS_BUFFER_TOO_SMALL;
  855. } else {
  856. RtlZeroMemory(Buffer, dataLength);
  857. status = MPIOBuildDescriptor(DeviceObject,
  858. Buffer);
  859. *InstanceLengthArray = dataLength;
  860. status = STATUS_SUCCESS;
  861. }
  862. break;
  863. }
  864. case BinaryMofGuidIndex: {
  865. //
  866. // TODO: If the driver supports reporting MOF dynamically,
  867. // change this code to handle multiple instances of the
  868. // binary mof guid and return only those instances that
  869. // should be reported to the schema
  870. //
  871. dataLength = sizeof(PdoBinaryMofData);
  872. if (BufferAvailable < dataLength)
  873. {
  874. status = STATUS_BUFFER_TOO_SMALL;
  875. } else {
  876. RtlCopyMemory(Buffer, PdoBinaryMofData, dataLength);
  877. *InstanceLengthArray = dataLength;
  878. status = STATUS_SUCCESS;
  879. }
  880. break;
  881. }
  882. default: {
  883. status = STATUS_WMI_GUID_NOT_FOUND;
  884. break;
  885. }
  886. }
  887. //
  888. // Complete the request.
  889. //
  890. status = WmiCompleteRequest(DeviceObject,
  891. Irp,
  892. status,
  893. dataLength,
  894. IO_NO_INCREMENT);
  895. return status;
  896. }
  897. NTSTATUS
  898. MPIOGetDiskDescriptorSize(
  899. IN PDEVICE_OBJECT DeviceObject
  900. )
  901. {
  902. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  903. PMPDISK_EXTENSION diskExtension = deviceExtension->TypeExtension;
  904. ULONG dataLength;
  905. NTSTATUS status;
  906. ULONG i;
  907. //
  908. // Length is ULONG (NumberDisks) + sizeof(MPDISK_DESCRIPTOR)
  909. //
  910. dataLength = sizeof(ULONG);
  911. //
  912. // For the string length field.
  913. //
  914. dataLength += sizeof(USHORT);
  915. //
  916. // Length of the product/vendor/rev string
  917. // (8 + 16+ 4 + 2 (spaces between vendor/product/rev) + 1 (trailing NULL)) * sizeof(WCHAR)
  918. //
  919. dataLength += 0x3C;
  920. //
  921. // Ensure that the start of each array entry is ULONG aligned.
  922. //
  923. dataLength += sizeof(ULONG);
  924. dataLength &= ~(sizeof(ULONG) - 1);
  925. for (i = 0; i < diskExtension->DsmIdList.Count; i++) {
  926. //
  927. // SCSI_ADDR (almost like SCSI_ADDRESS, but without the length field)
  928. //
  929. dataLength += sizeof(SCSI_ADDR);
  930. }
  931. return dataLength;
  932. }
  933. NTSTATUS
  934. MPIOGetDiskDescriptor(
  935. IN PDEVICE_OBJECT DeviceObject,
  936. IN PUCHAR Buffer,
  937. IN ULONG BufferLength
  938. )
  939. {
  940. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  941. PMPDISK_EXTENSION diskExtension = deviceExtension->TypeExtension;
  942. PUCHAR buffer = Buffer;
  943. PREAL_DEV_INFO targetInfo;
  944. PSTORAGE_DEVICE_DESCRIPTOR deviceDescriptor;
  945. PUCHAR inquiryField;
  946. PUCHAR index;
  947. UCHAR inquiryData[32];
  948. ANSI_STRING ansiInquiry;
  949. UNICODE_STRING unicodeString;
  950. PSCSI_ADDR scsiAddress;
  951. ULONG i;
  952. NTSTATUS status;
  953. RtlZeroMemory(Buffer, BufferLength);
  954. *((PULONG)buffer) = diskExtension->DsmIdList.Count;
  955. targetInfo = diskExtension->TargetInfo;
  956. //
  957. // Set the number of drives underlying this mpdisk.
  958. //
  959. (ULONG_PTR)buffer += sizeof(ULONG);
  960. //
  961. // Preload the inquiry buffer with spaces and a null-terminator.
  962. //
  963. for (i = 0; i < 32; i++) {
  964. inquiryData[i] = ' ';
  965. }
  966. inquiryData[30] = '\0';
  967. inquiryData[31] = '\0';
  968. //
  969. // Merge the ascii inquiry data into one long string.
  970. //
  971. deviceDescriptor = diskExtension->DeviceDescriptor;
  972. inquiryField = (PUCHAR)deviceDescriptor;
  973. (ULONG_PTR)inquiryField += deviceDescriptor->VendorIdOffset;
  974. index = inquiryData;
  975. //
  976. // Copy the vendorId.
  977. //
  978. RtlCopyMemory(index, inquiryField, 8);
  979. //
  980. // Account for vendorId + a space.
  981. //
  982. index += 9;
  983. inquiryField = (PUCHAR)deviceDescriptor;
  984. (ULONG_PTR)inquiryField += deviceDescriptor->ProductIdOffset;
  985. //
  986. // Copy ProductId.
  987. //
  988. RtlCopyMemory(index, inquiryField, 16);
  989. //
  990. // Account for product + space.
  991. //
  992. index += 17;
  993. inquiryField = (PUCHAR)deviceDescriptor;
  994. (ULONG_PTR)inquiryField += deviceDescriptor->ProductRevisionOffset;
  995. RtlCopyMemory(index, inquiryField, 4);
  996. //
  997. // Convert to WCHAR.
  998. //
  999. RtlInitAnsiString(&ansiInquiry, inquiryData);
  1000. RtlAnsiStringToUnicodeString(&unicodeString, &ansiInquiry, TRUE);
  1001. //
  1002. // Build the name string. First is the length.
  1003. //
  1004. // BUGBUG: Note the hack of +2
  1005. //
  1006. *((PUSHORT)buffer) = unicodeString.Length + 2;
  1007. (ULONG_PTR)buffer += sizeof(USHORT);
  1008. //
  1009. // Copy the serialNumber.
  1010. //
  1011. RtlCopyMemory(buffer,
  1012. unicodeString.Buffer,
  1013. unicodeString.Length);
  1014. //
  1015. // Advance the pointer past the inquiry string.
  1016. //
  1017. (ULONG_PTR)buffer += unicodeString.Length;
  1018. RtlFreeUnicodeString(&unicodeString);
  1019. //
  1020. // ULONG align it.
  1021. //
  1022. (ULONG_PTR)buffer += sizeof(ULONG);
  1023. (ULONG_PTR)buffer &= ~(sizeof(ULONG) - 1);
  1024. for (i = 0; i < diskExtension->DsmIdList.Count; i++) {
  1025. scsiAddress = (PSCSI_ADDR)buffer;
  1026. scsiAddress->PortNumber = targetInfo->ScsiAddress.PortNumber;
  1027. scsiAddress->ScsiPathId = targetInfo->ScsiAddress.PathId;
  1028. scsiAddress->TargetId = targetInfo->ScsiAddress.TargetId;
  1029. scsiAddress->Lun = targetInfo->ScsiAddress.Lun;
  1030. targetInfo++;
  1031. (ULONG_PTR)buffer += sizeof(SCSI_ADDR);
  1032. #if 0
  1033. //
  1034. // Fake the WWN.
  1035. // TODO get the real stuff.
  1036. //
  1037. *((PLONGLONG)buffer) = 0;
  1038. (ULONG_PTR)buffer += sizeof(LONGLONG);
  1039. #endif
  1040. }
  1041. return STATUS_SUCCESS;
  1042. }
  1043. NTSTATUS
  1044. MPIOExecuteMethod(
  1045. IN PDEVICE_OBJECT DeviceObject,
  1046. IN PIRP Irp,
  1047. IN ULONG GuidIndex,
  1048. IN ULONG InstanceIndex,
  1049. IN ULONG MethodId,
  1050. IN ULONG InBufferSize,
  1051. IN ULONG OutBufferSize,
  1052. IN PUCHAR Buffer
  1053. )
  1054. /*++
  1055. Routine Description:
  1056. Arguments:
  1057. 'aReturn Value:
  1058. status
  1059. --*/
  1060. {
  1061. ULONG dataLength = 0;
  1062. ULONG ordinal;
  1063. PDISK_ENTRY diskEntry;
  1064. NTSTATUS status;
  1065. switch(GuidIndex) {
  1066. #if 0
  1067. case MPIO_GET_DESCRIPTORSGuidIndex: {
  1068. switch(MethodId) {
  1069. case MPIOGetMPIODiskDescriptor: {
  1070. //
  1071. // Check the input buffer size.
  1072. //
  1073. if (InBufferSize != sizeof(ULONG)) {
  1074. status = STATUS_INVALID_PARAMETER;
  1075. dataLength = 0;
  1076. break;
  1077. }
  1078. //
  1079. // The input buffer is the ordinal of the device in which
  1080. // the caller has interest.
  1081. //
  1082. ordinal = *((PULONG)Buffer);
  1083. //
  1084. // Ensure that ordinal is with-in range.
  1085. // TODO
  1086. diskEntry = MPIOGetDiskEntry(DeviceObject,
  1087. ordinal);
  1088. //
  1089. // Get the size of the return info.
  1090. //
  1091. dataLength = MPIOGetDiskDescriptorSize(diskEntry->PdoObject);
  1092. if (dataLength > OutBufferSize) {
  1093. status = STATUS_BUFFER_TOO_SMALL;
  1094. break;
  1095. }
  1096. //
  1097. //
  1098. status = MPIOGetDiskDescriptor(diskEntry->PdoObject,
  1099. Buffer,
  1100. OutBufferSize);
  1101. break;
  1102. }
  1103. default: {
  1104. status = STATUS_WMI_ITEMID_NOT_FOUND;
  1105. break;
  1106. }
  1107. }
  1108. break;
  1109. }
  1110. #endif
  1111. default: {
  1112. status = STATUS_WMI_GUID_NOT_FOUND;
  1113. }
  1114. }
  1115. status = WmiCompleteRequest(DeviceObject,
  1116. Irp,
  1117. status,
  1118. dataLength,
  1119. IO_NO_INCREMENT);
  1120. return(status);
  1121. }
  1122. NTSTATUS
  1123. MPIOPdoWmiControl(
  1124. IN PDEVICE_OBJECT DeviceObject,
  1125. IN PIRP Irp,
  1126. IN ULONG GuidIndex,
  1127. IN WMIENABLEDISABLECONTROL Function,
  1128. IN BOOLEAN Enable
  1129. )
  1130. {
  1131. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  1132. NTSTATUS status;
  1133. switch (GuidIndex) {
  1134. case MPIO_EventEntryGuidIndex:
  1135. if (Enable) {
  1136. //
  1137. // Indicate that it's OK to fire the Log event.
  1138. //
  1139. deviceExtension->FireLogEvent = TRUE;
  1140. } else {
  1141. //
  1142. // Turn off firing the logger.
  1143. //
  1144. deviceExtension->FireLogEvent = FALSE;
  1145. }
  1146. MPDebugPrint((0,
  1147. "MPIOWmiControl: Turning the Logger (%s) on (%x)\n",
  1148. Enable ? "ON" : "OFF",
  1149. DeviceObject));
  1150. break;
  1151. default:
  1152. status = STATUS_WMI_GUID_NOT_FOUND;
  1153. break;
  1154. }
  1155. status = WmiCompleteRequest(DeviceObject,
  1156. Irp,
  1157. status,
  1158. 0,
  1159. IO_NO_INCREMENT);
  1160. return status;
  1161. }
  1162. VOID
  1163. MPIOSetupWmi(
  1164. IN PDEVICE_OBJECT DeviceObject
  1165. )
  1166. {
  1167. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  1168. PMPDISK_EXTENSION diskExtension;
  1169. PWMILIB_CONTEXT wmiLibContext = &deviceExtension->WmiLib;
  1170. NTSTATUS status;
  1171. PDSM_ENTRY dsm;
  1172. PDSM_WMILIB_CONTEXT wmiContext;
  1173. ULONG guids;
  1174. ULONG guidListSize;
  1175. PUCHAR index;
  1176. //
  1177. // This simply jams in all the fields of the wmilib context for
  1178. // use by WmiSystemControl.
  1179. //
  1180. if (deviceExtension->Type == MPIO_MPDISK) {
  1181. //
  1182. // TODO: Revisit piggybacking off of the PDO. It may be
  1183. // better to use the FDO.
  1184. //
  1185. diskExtension = deviceExtension->TypeExtension;
  1186. dsm = &diskExtension->DsmInfo;
  1187. //
  1188. // Get the DSM's Wmi Info and append it to ours.
  1189. //
  1190. //wmiContext = &dsm->WmiContext;
  1191. //
  1192. // Currently, there are no PDO associated GUIDs. As soon as they are in place
  1193. // this needs to be updated accordingly.
  1194. //
  1195. #if 0
  1196. guids = wmiContext->GuidCount + MPIO_PDO_GUID_COUNT;
  1197. guidListSize = sizeof(MPIOPdoGuidList) + sizeof(wmiContext->GuidList);
  1198. guidListSize = sizeof(wmiContext->GuidList);
  1199. deviceExtension->WmiLib.GuidList = ExAllocatePool(NonPagedPool,guidListSize);
  1200. RtlZeroMemory(deviceExtension->WmiLib.GuidList, guidListSize);
  1201. //
  1202. // Copy over the pdo's list.
  1203. //
  1204. index = (PUCHAR)deviceExtension->WmiLib.GuidList;
  1205. RtlCopyMemory(index,
  1206. MPIOPdoGuidList,
  1207. sizeof(MPIOPdoGuidList));
  1208. index += sizeof(MPIOPdoGuidList);
  1209. wmiLibContext->GuidCount = guids;
  1210. //
  1211. // copy over the DSM's.
  1212. //
  1213. RtlCopyMemory(index,
  1214. wmiContext->GuidList,
  1215. sizeof(wmiContext->GuidList));
  1216. #endif
  1217. wmiLibContext->GuidCount = PdowmiGuidCount;
  1218. wmiLibContext->GuidList = PdowmiGuidList;
  1219. wmiLibContext->QueryWmiRegInfo = MPIOQueryRegInfo;
  1220. wmiLibContext->QueryWmiDataBlock = MPIOPdoQueryDataBlock;
  1221. //wmiLibContext->SetWmiDataBlock = MPIOPdoSetDataBlock;
  1222. //wmiLibContext->SetWmiDataItem = MPIOPdoSetDataItem;
  1223. //wmiLibContext->ExecuteWmiMethod = MPIOPdoExecuteMethod;
  1224. //wmiLibContext->WmiFunctionControl = MPIOPdoWmiControl;
  1225. } else {
  1226. wmiLibContext->GuidCount = MPIO_GUID_COUNT;
  1227. wmiLibContext->GuidList = MPIOWmiGuidList;
  1228. wmiLibContext->QueryWmiRegInfo = MPIOQueryRegInfo;
  1229. wmiLibContext->QueryWmiDataBlock = MPIOQueryDataBlock;
  1230. //wmiLibContext->SetWmiDataBlock = MPIOSetDataBlock;
  1231. //wmiLibContext->SetWmiDataItem = MPIOSetDataItem;
  1232. wmiLibContext->ExecuteWmiMethod = MPIOExecuteMethod;
  1233. wmiLibContext->WmiFunctionControl = MPIOWmiControl;
  1234. }
  1235. return;
  1236. }
  1237. NTSTATUS
  1238. MPIOPdoWmi(
  1239. IN PDEVICE_OBJECT DeviceObject,
  1240. IN PIRP Irp
  1241. )
  1242. {
  1243. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  1244. PMPDISK_EXTENSION diskExtension = deviceExtension->TypeExtension;
  1245. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  1246. SYSCTL_IRP_DISPOSITION disposition;
  1247. NTSTATUS status;
  1248. //
  1249. // Using the WMI Library, so call it with the request.
  1250. // This will call the appropriate DpWmi function.
  1251. //
  1252. status = WmiSystemControl(&deviceExtension->WmiLib,
  1253. DeviceObject,
  1254. Irp,
  1255. &disposition);
  1256. switch (disposition) {
  1257. case IrpProcessed:
  1258. //
  1259. // Already handled by one of the DpWmi call-backs.
  1260. //
  1261. break;
  1262. case IrpNotCompleted:
  1263. //
  1264. // Probably an error, or the IRP_MN_REGINFO
  1265. //
  1266. MPDebugPrint((0,
  1267. "MPIOrPdoWmi: Irp (%x) Mn (%x) Status (%x)\n",
  1268. Irp,
  1269. irpStack->MinorFunction,
  1270. status));
  1271. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1272. break;
  1273. case IrpNotWmi:
  1274. case IrpForward:
  1275. default:
  1276. //
  1277. // Forward this irp.
  1278. //
  1279. status = MPIOForwardRequest(DeviceObject, Irp);
  1280. break;
  1281. }
  1282. return status;
  1283. }
  1284. NTSTATUS
  1285. MPIOFdoWmi(
  1286. IN PDEVICE_OBJECT DeviceObject,
  1287. IN PIRP Irp
  1288. )
  1289. {
  1290. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  1291. PCONTROL_EXTENSION controlExtension = deviceExtension->TypeExtension;
  1292. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  1293. SYSCTL_IRP_DISPOSITION disposition;
  1294. NTSTATUS status;
  1295. //
  1296. // Using the WMI Library, so call it with the request.
  1297. // This will call the appropriate DpWmi function.
  1298. //
  1299. status = WmiSystemControl(&deviceExtension->WmiLib,
  1300. DeviceObject,
  1301. Irp,
  1302. &disposition);
  1303. switch (disposition) {
  1304. case IrpProcessed:
  1305. //
  1306. // Already handled by one of the DpWmi call-backs.
  1307. //
  1308. break;
  1309. case IrpNotCompleted:
  1310. //
  1311. // Probably an error, or the IRP_MN_REGINFO
  1312. //
  1313. MPDebugPrint((0,
  1314. "MPIOFdoWmi: Irp (%x) Mn (%x) Status (%x)\n",
  1315. Irp,
  1316. irpStack->MinorFunction,
  1317. status));
  1318. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1319. break;
  1320. case IrpNotWmi:
  1321. case IrpForward:
  1322. default:
  1323. //
  1324. // Forward this irp.
  1325. //
  1326. status = MPIOForwardRequest(DeviceObject, Irp);
  1327. break;
  1328. }
  1329. return status;
  1330. }
  1331. NTSTATUS
  1332. MPIOFireEvent(
  1333. IN PDEVICE_OBJECT DeviceObject,
  1334. IN PWCHAR ComponentName,
  1335. IN PWCHAR EventDescription,
  1336. IN ULONG Severity
  1337. )
  1338. {
  1339. PMPIO_EventEntry eventEntry;
  1340. ULONG dataLength;
  1341. PWCHAR nameString;
  1342. LARGE_INTEGER systemTime;
  1343. NTSTATUS status;
  1344. USHORT componentLength;
  1345. USHORT eventLength;
  1346. PUCHAR index;
  1347. //
  1348. // Determine the total allocation length based on the
  1349. // structure and string lengths.
  1350. //
  1351. componentLength = wcslen(ComponentName) * sizeof(WCHAR);
  1352. componentLength += sizeof(UNICODE_NULL);
  1353. eventLength = wcslen(EventDescription) * sizeof(WCHAR);
  1354. eventLength += sizeof(UNICODE_NULL);
  1355. if ((componentLength > MPIO_STRING_LENGTH) ||
  1356. (eventLength > MPIO_STRING_LENGTH)) {
  1357. return STATUS_INVALID_PARAMETER;
  1358. }
  1359. dataLength = sizeof(MPIO_EventEntry);
  1360. //
  1361. // Allocate the EventData.
  1362. //
  1363. eventEntry = ExAllocatePool(NonPagedPool, dataLength);
  1364. if (eventEntry == NULL) {
  1365. return STATUS_INSUFFICIENT_RESOURCES;
  1366. }
  1367. RtlZeroMemory(eventEntry, dataLength);
  1368. //
  1369. // Set the severity of the event.
  1370. //
  1371. eventEntry->Severity = Severity;
  1372. KeQuerySystemTime(&systemTime);
  1373. eventEntry->TimeStamp = systemTime.QuadPart;
  1374. //
  1375. // Copy the Component Name.
  1376. //
  1377. nameString = eventEntry->Component;
  1378. *((PUSHORT)nameString) = componentLength;
  1379. nameString++;
  1380. wcscpy(nameString, ComponentName);
  1381. MPDebugPrint((0,
  1382. "NameString (%x). Length (%d)\n",
  1383. nameString,
  1384. componentLength));
  1385. //
  1386. // Copy over the Object name.
  1387. //
  1388. nameString = eventEntry->EventDescription;
  1389. *((PUSHORT)nameString) = eventLength;
  1390. nameString++;
  1391. wcscpy(nameString, EventDescription);
  1392. //
  1393. // Send the event.
  1394. //
  1395. status = WmiFireEvent(DeviceObject,
  1396. &MPIO_EventEntryGUID,
  1397. 0,
  1398. dataLength,
  1399. eventEntry);
  1400. if (status != STATUS_SUCCESS) {
  1401. MPDebugPrint((0,
  1402. "MPIOFireEvent: Status (%x)\n",
  1403. status));
  1404. //
  1405. // TODO: Queue these for when we get the Enable request.
  1406. //
  1407. ExFreePool(eventEntry);
  1408. }
  1409. return status;
  1410. }