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.

550 lines
16 KiB

  1. #include "mpath.h"
  2. #include <wmistr.h>
  3. #include <wmidata.h>
  4. #include <stdio.h>
  5. #ifdef USE_BINARY_MOF_QUERY
  6. //
  7. // MOF data can be reported by a device driver via a resource attached to
  8. // the device drivers image file or in response to a query on the binary
  9. // mof data guid. Here we define global variables containing the binary mof
  10. // data to return in response to a binary mof guid query. Note that this
  11. // data is defined to be in a PAGED data segment since it does not need to
  12. // be in nonpaged memory. Note that instead of a single large mof file
  13. // we could have broken it into multiple individual files. Each file would
  14. // have its own binary mof data buffer and get reported via a different
  15. // instance of the binary mof guid. By mixing and matching the different
  16. // sets of binary mof data buffers a "dynamic" composite mof would be created.
  17. #ifdef ALLOC_DATA_PRAGMA
  18. #pragma data_seg("PAGED")
  19. #endif
  20. #pragma message ("USE_BINARY defined ChuckP")
  21. UCHAR MPathBinaryMofData[] =
  22. {
  23. #include "mpathwmi.x"
  24. };
  25. #ifdef ALLOC_DATA_PRAGMA
  26. #pragma data_seg()
  27. #endif
  28. #endif
  29. WMIGUIDREGINFO MPathWmiGuidList[] = {
  30. {
  31. &MPath_Disk_Info_GUID,
  32. 1,
  33. 0
  34. },
  35. {
  36. &MPath_Test_GUID,
  37. 1,
  38. 0
  39. },
  40. {
  41. &MSWmi_MofData_GUID,
  42. 1,
  43. #ifdef USE_BINARY_MOF_QUERY
  44. 0
  45. #else
  46. WMIREG_FLAG_REMOVE_GUID
  47. #endif
  48. }
  49. };
  50. #define DiskInformation 0
  51. #define MPathTest 1
  52. #define BinaryMofGuid 2
  53. #define MPathGuidCount (sizeof(MPathWmiGuidList) / sizeof(WMIGUIDREGINFO))
  54. //#define MPATH_GUID_PDISK_INFO 0
  55. //#define MPATH_BINARY_MOF 1
  56. //#define MPATH_GUID_FAILOVER_INFO 1
  57. //#define MPATH_GUID_CONFIG_INFO 2
  58. //#define MPATH_GUID_DSM_NAME 3
  59. //#define MPATH_GUID_PATH_MAINTENACE 4
  60. //
  61. // Always update this for any guid additions.
  62. // This indicates the dividing line between our and DSM
  63. // guids.
  64. //
  65. //#define MPATH_MAX_GUID_INDEX MPATH_BINARY_MOF
  66. //
  67. NTSTATUS
  68. MPathFdoWmi(
  69. IN PDEVICE_OBJECT DeviceObject,
  70. IN PIRP Irp
  71. )
  72. {
  73. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  74. IoSkipCurrentIrpStackLocation(Irp);
  75. return IoCallDriver(deviceExtension->TargetObject, Irp);
  76. }
  77. NTSTATUS
  78. MPathQueryWmiRegInfo(
  79. IN PDEVICE_OBJECT DeviceObject,
  80. OUT PULONG RegFlags,
  81. OUT PUNICODE_STRING InstanceName,
  82. OUT PUNICODE_STRING *RegistryPath,
  83. OUT PUNICODE_STRING MofResourceName,
  84. OUT PDEVICE_OBJECT *Pdo
  85. )
  86. {
  87. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  88. *RegFlags = WMIREG_FLAG_INSTANCE_PDO;
  89. *RegistryPath = &deviceExtension->RegistryPath;
  90. *Pdo = deviceExtension->DeviceObject;
  91. MPDebugPrint((0,
  92. "MPathQueryWmiRegInfo: *Pdo (%x), DeviceObject (%x)\n",
  93. *Pdo,
  94. DeviceObject));
  95. #ifndef USE_BINARY_MOF_QUERY
  96. #pragma message ("BIN NOT - ChuckP")
  97. //
  98. // Return the name specified in the .rc file of the resource which
  99. // contains the bianry mof data. By default WMI will look for this
  100. // resource in the driver image (.sys) file, however if the value
  101. // MofImagePath is specified in the driver's registry key
  102. // then WMI will look for the resource in the file specified there.
  103. RtlInitUnicodeString(MofResourceName, L"MofResourceName");
  104. #endif
  105. return STATUS_SUCCESS;
  106. }
  107. NTSTATUS
  108. MPathQueryWmiDataBlock(
  109. IN PDEVICE_OBJECT DeviceObject,
  110. IN PIRP Irp,
  111. IN ULONG GuidIndex,
  112. IN ULONG InstanceIndex,
  113. IN ULONG InstanceCount,
  114. IN OUT PULONG InstanceLengthArray,
  115. IN ULONG BufferAvail,
  116. OUT PUCHAR Buffer
  117. )
  118. {
  119. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  120. PPSEUDO_DISK_EXTENSION diskExtension = &deviceExtension->PseudoDiskExtension;
  121. NTSTATUS status;
  122. ULONG i;
  123. ULONG bytesReturned = 0;
  124. if (TRUE) { //(GuidIndex <= MPATH_MAX_GUID_INDEX) {
  125. //
  126. // This is for the pdisk
  127. // Ensure that this is a QUERY_SINGLE_INSTANCE, as these data blocks
  128. // are defined as having only one instance.
  129. //
  130. if (InstanceIndex != 0 || InstanceCount != 1) {
  131. status = STATUS_INVALID_DEVICE_REQUEST;
  132. } else {
  133. switch (GuidIndex) {
  134. case MPathTest:
  135. bytesReturned = sizeof(ULONG);
  136. if (bytesReturned > BufferAvail) {
  137. status = STATUS_BUFFER_TOO_SMALL;
  138. } else {
  139. ULONG theValue = 0xaa55aa55;
  140. RtlCopyMemory(Buffer,
  141. &theValue,
  142. sizeof(ULONG));
  143. status = STATUS_SUCCESS;
  144. }
  145. break;
  146. case DiskInformation: {
  147. PMPath_Disk_Info diskInfo = (PMPath_Disk_Info)Buffer;
  148. PSTORAGE_DEVICE_DESCRIPTOR storageDescriptor;
  149. ULONG serialNumberLength;
  150. ULONG totalStringLength;
  151. PUCHAR serialNumber;
  152. ANSI_STRING ansiSerialNumber;
  153. UNICODE_STRING unicodeString;
  154. bytesReturned = sizeof(MPath_Disk_Info);
  155. //
  156. // Determine the serial number length.
  157. //
  158. storageDescriptor =
  159. diskExtension->DeviceDescriptors[0].StorageDescriptor;
  160. serialNumber = (PUCHAR)storageDescriptor;
  161. //
  162. // Move serialNumber to the correct position in RawData.
  163. //
  164. (ULONG_PTR)serialNumber += storageDescriptor->SerialNumberOffset;
  165. //
  166. // Get it's length.
  167. //
  168. serialNumberLength = strlen(serialNumber);
  169. totalStringLength = serialNumberLength * sizeof(WCHAR);
  170. totalStringLength += sizeof(USHORT);
  171. totalStringLength *= diskExtension->NumberPhysicalPaths;
  172. bytesReturned += totalStringLength;
  173. bytesReturned += (diskExtension->NumberPhysicalPaths - 1) *
  174. sizeof(PHYSICAL_DISK_INFO);
  175. if (bytesReturned > BufferAvail) {
  176. status = STATUS_BUFFER_TOO_SMALL;
  177. } else {
  178. PWCHAR index;
  179. PDEVICE_DESCRIPTOR deviceDescriptor;
  180. PPHYSICAL_DISK_INFO deviceInfo = diskInfo->DeviceInfo;
  181. diskInfo->NumberDrives = diskExtension->NumberPhysicalPaths;
  182. diskInfo->IsLoadBalance = FALSE;
  183. RtlInitAnsiString(&ansiSerialNumber, serialNumber);
  184. RtlAnsiStringToUnicodeString(&unicodeString, &ansiSerialNumber, TRUE);
  185. for (i = 0; i < diskExtension->NumberPhysicalPaths; i++) {
  186. deviceDescriptor =
  187. &diskExtension->DeviceDescriptors[i];
  188. deviceInfo->BusType = 1;
  189. deviceInfo->PortNumber =
  190. deviceDescriptor->ScsiAddress->PortNumber;
  191. deviceInfo->TargetId =
  192. deviceDescriptor->ScsiAddress->TargetId;
  193. deviceInfo->Lun =
  194. deviceDescriptor->ScsiAddress->Lun;
  195. deviceInfo->CorrespondingPathId =
  196. (ULONG)deviceDescriptor->PhysicalPath->PhysicalPathId;
  197. index = (PWCHAR)deviceInfo->VariableData;
  198. *index++ = unicodeString.Length;
  199. RtlCopyMemory(index,
  200. unicodeString.Buffer,
  201. unicodeString.Length);
  202. (ULONG_PTR)deviceInfo +=
  203. sizeof(PHYSICAL_DISK_INFO) + unicodeString.Length;
  204. }
  205. status = STATUS_SUCCESS;
  206. }
  207. break;
  208. }
  209. #ifdef USE_BINARY_MOF_QUERY
  210. case BinaryMofGuid:
  211. {
  212. bytesReturned = sizeof(MPathBinaryMofData);
  213. MPDebugPrint((0,
  214. "MPathQueryDataBlock: BinaryMofGuid\n"));
  215. DbgBreakPoint();
  216. if (BufferAvail < bytesReturned)
  217. {
  218. status = STATUS_BUFFER_TOO_SMALL;
  219. } else {
  220. RtlCopyMemory(Buffer, MPathBinaryMofData, bytesReturned);
  221. status = STATUS_SUCCESS;
  222. }
  223. break;
  224. }
  225. #endif
  226. default:
  227. status = STATUS_WMI_GUID_NOT_FOUND;
  228. break;
  229. }
  230. }
  231. } else {
  232. //
  233. // This is for the DSM
  234. //
  235. status = STATUS_WMI_GUID_NOT_FOUND;
  236. }
  237. MPDebugPrint((0,
  238. "MpathQueryDataBlock: Buffer (%x) BytesReturned (%x). Status (%x)\n",
  239. Buffer,
  240. bytesReturned,
  241. status));
  242. //
  243. // Indicate the data length.
  244. //
  245. *InstanceLengthArray = bytesReturned;
  246. status = WmiCompleteRequest(DeviceObject,
  247. Irp,
  248. status,
  249. bytesReturned,
  250. IO_NO_INCREMENT);
  251. return status;
  252. }
  253. NTSTATUS
  254. MPathSetWmiDataBlock(
  255. IN PDEVICE_OBJECT DeviceObject,
  256. IN PIRP Irp,
  257. IN ULONG GuidIndex,
  258. IN ULONG InstanceIndex,
  259. IN ULONG BufferSize,
  260. IN PUCHAR Buffer
  261. )
  262. {
  263. NTSTATUS status;
  264. ULONG bytesReturned = 0;
  265. if (FALSE) { // (GuidIndex <= MPATH_MAX_GUID_INDEX) {
  266. status = STATUS_WMI_READ_ONLY;
  267. } else {
  268. //
  269. // DSM Guid
  270. // If there is a GUID match, call the dsm. It will have to call
  271. // DsmCompleteWMIRequest to finish the request.
  272. // DONOT complete it here, rather return the status from the DSM routine
  273. // TODO
  274. status = STATUS_WMI_GUID_NOT_FOUND;
  275. }
  276. status = WmiCompleteRequest(DeviceObject,
  277. Irp,
  278. status,
  279. bytesReturned,
  280. IO_NO_INCREMENT);
  281. return status;
  282. }
  283. NTSTATUS
  284. MPathSetWmiDataItem(
  285. IN PDEVICE_OBJECT DeviceObject,
  286. IN PIRP Irp,
  287. IN ULONG GuidIndex,
  288. IN ULONG InstanceIndex,
  289. IN ULONG DataItemId,
  290. IN ULONG BufferSize,
  291. IN PUCHAR Buffer
  292. )
  293. {
  294. NTSTATUS status;
  295. ULONG bytesReturned = 0;
  296. if (TRUE) { // (GuidIndex <= MPATH_MAX_GUID_INDEX) {
  297. status = STATUS_WMI_READ_ONLY;
  298. } else {
  299. //
  300. // DSM Guid
  301. // TODO
  302. status = STATUS_WMI_GUID_NOT_FOUND;
  303. }
  304. status = WmiCompleteRequest(DeviceObject,
  305. Irp,
  306. status,
  307. bytesReturned,
  308. IO_NO_INCREMENT);
  309. return status;
  310. }
  311. NTSTATUS
  312. MPathExecuteWmiMethod(
  313. IN PDEVICE_OBJECT DeviceObject,
  314. IN PIRP Irp,
  315. IN ULONG GuidIndex,
  316. IN ULONG InstanceIndex,
  317. IN ULONG MethodId,
  318. IN ULONG InBuffersize,
  319. IN ULONG OutBufferSize,
  320. IN OUT PUCHAR Buffer
  321. )
  322. {
  323. NTSTATUS status;
  324. ULONG bytesReturned = 0;
  325. if (TRUE) { //(GuidIndex <= MPATH_MAX_GUID_INDEX ) {
  326. switch (GuidIndex) {
  327. //case MPATH_GUID_PATH_MAINTENACE: {
  328. //
  329. // Need to verify the parameters.
  330. // TODO: Need data block that lists adapter
  331. // (path) ids.
  332. //
  333. //status = MPathFailOver(id1, id2);
  334. // status = STATUS_WMI_ITEMID_NOT_FOUND;
  335. // }
  336. // break;
  337. default:
  338. status = STATUS_WMI_ITEMID_NOT_FOUND;
  339. break;
  340. }
  341. } else {
  342. status = STATUS_WMI_ITEMID_NOT_FOUND;
  343. }
  344. status = WmiCompleteRequest(DeviceObject,
  345. Irp,
  346. status,
  347. bytesReturned,
  348. IO_NO_INCREMENT);
  349. return status;
  350. }
  351. NTSTATUS
  352. MPathWmiFunctionControl(
  353. IN PDEVICE_OBJECT DeviceObject,
  354. IN PIRP Irp,
  355. IN ULONG GuidIndex,
  356. IN WMIENABLEDISABLECONTROL Function,
  357. IN BOOLEAN Enable
  358. )
  359. {
  360. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  361. PPSEUDO_DISK_EXTENSION diskExtension = &deviceExtension->PseudoDiskExtension;
  362. NTSTATUS status;
  363. //
  364. // Handle the enabling/disabling of the datablocks/events
  365. //
  366. #if 0
  367. if (GuidIndex == MPATH_GUID_FAILOVER_INFO) {
  368. if (Enable) {
  369. diskExtension->WmiEventsEnabled = TRUE;
  370. } else {
  371. diskExtension->WmiEventsEnabled = FALSE;
  372. }
  373. } else {
  374. #endif
  375. status = STATUS_WMI_GUID_NOT_FOUND;
  376. //}
  377. status = WmiCompleteRequest(DeviceObject,
  378. Irp,
  379. status,
  380. 0,
  381. IO_NO_INCREMENT);
  382. return status;
  383. }
  384. VOID
  385. MPathSetupWmi(
  386. IN PDEVICE_EXTENSION DeviceExtension
  387. )
  388. {
  389. if (DeviceExtension->Type == DEV_MPATH_CONTROL) {
  390. MPDebugPrint((0,
  391. "MPathSetWmi: Control Object\n"));
  392. DbgBreakPoint();
  393. } else {
  394. PPSEUDO_DISK_EXTENSION diskExtension = &DeviceExtension->PseudoDiskExtension;
  395. diskExtension->WmiInfo.GuidCount = MPathGuidCount;
  396. diskExtension->WmiInfo.GuidList = MPathWmiGuidList;
  397. diskExtension->WmiInfo.QueryWmiRegInfo = MPathQueryWmiRegInfo;
  398. diskExtension->WmiInfo.QueryWmiDataBlock = MPathQueryWmiDataBlock;
  399. diskExtension->WmiInfo.SetWmiDataBlock = MPathSetWmiDataBlock;
  400. diskExtension->WmiInfo.SetWmiDataItem = MPathSetWmiDataItem;
  401. diskExtension->WmiInfo.ExecuteWmiMethod = MPathExecuteWmiMethod;
  402. diskExtension->WmiInfo.WmiFunctionControl = MPathWmiFunctionControl;
  403. }
  404. }
  405. NTSTATUS
  406. MPathWmi(
  407. IN PDEVICE_OBJECT DeviceObject,
  408. IN PIRP Irp
  409. )
  410. {
  411. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  412. PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
  413. PUCHAR wmiBuffer = irpStack->Parameters.WMI.Buffer;
  414. ULONG bufferSize = irpStack->Parameters.WMI.BufferSize;
  415. ULONG savedLength = Irp->IoStatus.Information;
  416. PPSEUDO_DISK_EXTENSION diskExtension;
  417. SYSCTL_IRP_DISPOSITION disposition;
  418. NTSTATUS status;
  419. MPDebugPrint((0,
  420. "MPathWmi: Irp (%x), MJ (%x), MN (%x)",
  421. Irp,
  422. irpStack->MajorFunction,
  423. irpStack->MinorFunction));
  424. diskExtension = &deviceExtension->PseudoDiskExtension;
  425. status = WmiSystemControl(&diskExtension->WmiInfo,
  426. DeviceObject,
  427. Irp,
  428. &disposition);
  429. MPDebugPrint((0,
  430. "Disposition is (%x). Status (%x)\n",
  431. disposition,
  432. status));
  433. switch (disposition) {
  434. case IrpProcessed:
  435. //
  436. // Already processed and the DpWmiXXX routines specified in WmiInfo will
  437. // complete it.
  438. //
  439. break;
  440. case IrpNotCompleted:
  441. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  442. break;
  443. case IrpNotWmi:
  444. case IrpForward:
  445. default:
  446. //
  447. // Need to ensure this is the pseudodisk
  448. //
  449. if (deviceExtension->Type == DEV_MPATH_CONTROL) {
  450. MPDebugPrint((0,
  451. " for Control\n"));
  452. //
  453. // Call the 'control' (FDO) handler.
  454. //
  455. return MPathFdoWmi(DeviceObject, Irp);
  456. } else {
  457. //
  458. // This is the PDO, so just complete it without touching anything.
  459. //
  460. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  461. }
  462. break;
  463. }
  464. return status;
  465. }