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.

368 lines
9.8 KiB

  1. /*++
  2. Copyright (C) 1991-5 Microsoft Corporation
  3. Module Name:
  4. ftwmireg.cxx
  5. Abstract:
  6. This file contains routines to register for and response to WMI queries.
  7. Author:
  8. Bruce Worthington 26-Oct-1998
  9. Environment:
  10. kernel mode only
  11. Notes:
  12. Revision History:
  13. --*/
  14. extern "C" {
  15. #include <ntddk.h>
  16. #include <mountmgr.h>
  17. }
  18. #include <ftdisk.h>
  19. extern "C" {
  20. #define INITGUID
  21. #include "wmistr.h"
  22. #include "wmiguid.h"
  23. #include "ntdddisk.h"
  24. NTSTATUS FtRegisterDevice(
  25. IN PDEVICE_OBJECT DeviceObject
  26. );
  27. NTSTATUS
  28. FtQueryWmiRegInfo(
  29. IN PDEVICE_OBJECT DeviceObject,
  30. OUT ULONG *RegFlags,
  31. OUT PUNICODE_STRING InstanceName,
  32. OUT PUNICODE_STRING *RegistryPath,
  33. OUT PUNICODE_STRING MofResourceName,
  34. OUT PDEVICE_OBJECT *Pdo
  35. );
  36. NTSTATUS
  37. FtQueryWmiDataBlock(
  38. IN PDEVICE_OBJECT DeviceObject,
  39. IN PIRP Irp,
  40. IN ULONG GuidIndex,
  41. IN ULONG InstanceIndex,
  42. IN ULONG InstanceCount,
  43. IN OUT PULONG InstanceLengthArray,
  44. IN ULONG BufferAvail,
  45. OUT PUCHAR Buffer
  46. );
  47. BOOLEAN
  48. FtQueryEnableAlways(
  49. IN PDEVICE_OBJECT DeviceObject
  50. );
  51. WMIGUIDREGINFO DiskperfGuidList[] =
  52. {
  53. { &DiskPerfGuid,
  54. 1,
  55. 0
  56. }
  57. };
  58. ULONG DiskperfGuidCount = (sizeof(DiskperfGuidList) / sizeof(WMIGUIDREGINFO));
  59. }
  60. #ifdef ALLOC_PRAGMA
  61. #pragma code_seg("PAGE")
  62. #endif
  63. NTSTATUS
  64. FtRegisterDevice(
  65. IN PDEVICE_OBJECT DeviceObject
  66. )
  67. /*++
  68. Routine Description:
  69. Routine to initialize a proper name for the device object, and
  70. register it with WMI
  71. Arguments:
  72. DeviceObject - pointer to a device object to be initialized.
  73. Return Value:
  74. Status of the initialization. NOTE: If the registration fails,
  75. the device name in the DeviceExtension will be left as empty.
  76. --*/
  77. {
  78. NTSTATUS status;
  79. PVOLUME_EXTENSION deviceExtension;
  80. KEVENT event;
  81. PIRP irp;
  82. IO_STATUS_BLOCK ioStatus;
  83. PAGED_CODE();
  84. deviceExtension = (PVOLUME_EXTENSION) DeviceObject->DeviceExtension;
  85. status = IoWMIRegistrationControl(DeviceObject, WMIREG_ACTION_REGISTER);
  86. if (NT_SUCCESS(status) && (deviceExtension->Root->PmWmiCounterLibContext.PmWmiCounterEnable != NULL)) {
  87. deviceExtension->Root->PmWmiCounterLibContext.PmWmiCounterEnable(&deviceExtension->PmWmiCounterContext);
  88. deviceExtension->Root->PmWmiCounterLibContext.PmWmiCounterDisable(&deviceExtension->PmWmiCounterContext,FALSE,FALSE);
  89. }
  90. return status;
  91. }
  92. NTSTATUS
  93. FtQueryWmiRegInfo(
  94. IN PDEVICE_OBJECT DeviceObject,
  95. OUT ULONG *RegFlags,
  96. OUT PUNICODE_STRING InstanceName,
  97. OUT PUNICODE_STRING *RegistryPath,
  98. OUT PUNICODE_STRING MofResourceName,
  99. OUT PDEVICE_OBJECT *Pdo
  100. )
  101. /*++
  102. Routine Description:
  103. This routine is a callback into the driver to retrieve information about
  104. the guids being registered.
  105. Implementations of this routine may be in paged memory
  106. Arguments:
  107. DeviceObject is the device whose registration information is needed
  108. *RegFlags returns with a set of flags that describe all of the guids being
  109. registered for this device. If the device wants enable and disable
  110. collection callbacks before receiving queries for the registered
  111. guids then it should return the WMIREG_FLAG_EXPENSIVE flag. Also the
  112. returned flags may specify WMIREG_FLAG_INSTANCE_PDO in which case
  113. the instance name is determined from the PDO associated with the
  114. device object. Note that the PDO must have an associated devnode. If
  115. WMIREG_FLAG_INSTANCE_PDO is not set then Name must return a unique
  116. name for the device. These flags are ORed into the flags specified
  117. by the GUIDREGINFO for each guid.
  118. InstanceName returns with the instance name for the guids if
  119. WMIREG_FLAG_INSTANCE_PDO is not set in the returned *RegFlags. The
  120. caller will call ExFreePool with the buffer returned.
  121. *RegistryPath returns with the registry path of the driver. This is
  122. required
  123. MofResourceName returns with the name of the MOF resource attached to
  124. the binary file. If the driver does not have a mof resource attached
  125. then this can be returned unmodified. If a value is returned then
  126. it is NOT freed.
  127. The MOF file is assumed to be already included in wmicore.mof
  128. *Pdo returns with the device object for the PDO associated with this
  129. device if the WMIREG_FLAG_INSTANCE_PDO flag is retured in
  130. *RegFlags.
  131. Return Value:
  132. status
  133. --*/
  134. {
  135. NTSTATUS status;
  136. PVOLUME_EXTENSION deviceExtension;
  137. deviceExtension = (PVOLUME_EXTENSION) DeviceObject->DeviceExtension;
  138. PAGED_CODE();
  139. InstanceName->Buffer = (PWSTR) NULL;
  140. *RegistryPath = &deviceExtension->Root->DiskPerfRegistryPath;
  141. *RegFlags = WMIREG_FLAG_INSTANCE_PDO | WMIREG_FLAG_EXPENSIVE;
  142. *Pdo = DeviceObject;
  143. status = STATUS_SUCCESS;
  144. return(status);
  145. }
  146. NTSTATUS
  147. FtQueryWmiDataBlock(
  148. IN PDEVICE_OBJECT DeviceObject,
  149. IN PIRP Irp,
  150. IN ULONG GuidIndex,
  151. IN ULONG InstanceIndex,
  152. IN ULONG InstanceCount,
  153. IN OUT PULONG InstanceLengthArray,
  154. IN ULONG BufferAvail,
  155. OUT PUCHAR Buffer
  156. )
  157. /*++
  158. Routine Description:
  159. This routine is a callback into the driver to query for the contents of
  160. all instances of a data block. When the driver has finished filling the
  161. data block it must call WmiCompleteRequest to complete the irp. The
  162. driver can return STATUS_PENDING if the irp cannot be completed
  163. immediately.
  164. Arguments:
  165. DeviceObject is the device whose data block is being queried
  166. Irp is the Irp that makes this request
  167. GuidIndex is the index into the list of guids provided when the
  168. device registered
  169. InstanceCount is the number of instances expected to be returned for
  170. the data block.
  171. InstanceLengthArray is a pointer to an array of ULONG that returns the
  172. lengths of each instance of the data block. If this is NULL then
  173. there was not enough space in the output buffer to fufill the request
  174. so the irp should be completed with the buffer needed.
  175. BufferAvail on entry has the maximum size available to write the data
  176. blocks.
  177. Buffer on return is filled with the returned data blocks. Note that each
  178. instance of the data block must be aligned on a 8 byte boundry.
  179. Return Value:
  180. status
  181. --*/
  182. {
  183. NTSTATUS status;
  184. PVOLUME_EXTENSION deviceExtension;
  185. ULONG sizeNeeded = 0;
  186. KIRQL currentIrql;
  187. WCHAR stringBuffer[40];
  188. USHORT stringSize;
  189. PWCHAR diskNamePtr;
  190. PAGED_CODE();
  191. deviceExtension = (PVOLUME_EXTENSION) DeviceObject->DeviceExtension;
  192. if (GuidIndex == 0)
  193. {
  194. if (!(deviceExtension->CountersEnabled)) {
  195. status = STATUS_UNSUCCESSFUL;
  196. } else {
  197. swprintf(stringBuffer, L"\\Device\\HarddiskVolume%d",
  198. deviceExtension->VolumeNumber);
  199. stringSize = (USHORT) (wcslen(stringBuffer) * sizeof(WCHAR));
  200. sizeNeeded = ((sizeof(DISK_PERFORMANCE) + 1) & ~1)
  201. + stringSize + sizeof(UNICODE_NULL);
  202. if (BufferAvail >= sizeNeeded) {
  203. deviceExtension->Root->PmWmiCounterLibContext.
  204. PmWmiCounterQuery(deviceExtension->PmWmiCounterContext,
  205. (PDISK_PERFORMANCE) Buffer,
  206. L"FTDISK ",
  207. deviceExtension->VolumeNumber);
  208. diskNamePtr = (PWCHAR)(Buffer +
  209. ((sizeof(DISK_PERFORMANCE) + 1) & ~1));
  210. *diskNamePtr++ = stringSize;
  211. RtlCopyMemory(diskNamePtr,
  212. stringBuffer,
  213. stringSize);
  214. *InstanceLengthArray = sizeNeeded;
  215. status = STATUS_SUCCESS;
  216. } else {
  217. status = STATUS_BUFFER_TOO_SMALL;
  218. }
  219. }
  220. } else {
  221. status = STATUS_WMI_GUID_NOT_FOUND;
  222. }
  223. status = WmiCompleteRequest( DeviceObject, Irp, status, sizeNeeded,
  224. IO_NO_INCREMENT);
  225. return status;
  226. }
  227. BOOLEAN
  228. FtQueryEnableAlways(
  229. IN PDEVICE_OBJECT DeviceObject
  230. )
  231. {
  232. NTSTATUS status;
  233. UNICODE_STRING uString;
  234. OBJECT_ATTRIBUTES objAttributes;
  235. PKEY_VALUE_PARTIAL_INFORMATION keyValue;
  236. ULONG Buffer[4]; // sizeof keyValue + ULONG
  237. ULONG enableAlways = 0;
  238. PVOLUME_EXTENSION extension = (PVOLUME_EXTENSION) DeviceObject->DeviceExtension;
  239. HANDLE keyHandle;
  240. ULONG returnLength;
  241. PAGED_CODE();
  242. RtlInitUnicodeString(&uString, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Partmgr");
  243. InitializeObjectAttributes(
  244. &objAttributes,
  245. &uString,
  246. OBJ_CASE_INSENSITIVE,
  247. NULL,
  248. NULL
  249. );
  250. status = ZwOpenKey(&keyHandle, KEY_READ, &objAttributes);
  251. if (NT_SUCCESS(status)) {
  252. RtlInitUnicodeString(&uString, L"EnableCounterForIoctl");
  253. status = ZwQueryValueKey(keyHandle, &uString,
  254. KeyValuePartialInformation,
  255. Buffer,
  256. sizeof(Buffer),
  257. &returnLength);
  258. keyValue = (PKEY_VALUE_PARTIAL_INFORMATION) &Buffer[0];
  259. if (NT_SUCCESS(status) && (keyValue->DataLength == sizeof(ULONG))) {
  260. enableAlways = *((PULONG) keyValue->Data);
  261. }
  262. ZwClose(keyHandle);
  263. }
  264. if (enableAlways == 1) {
  265. if (InterlockedCompareExchange(&extension->EnableAlways, 1, 0) == 0) {
  266. status = extension->Root->PmWmiCounterLibContext.
  267. PmWmiCounterEnable(&extension->PmWmiCounterContext);
  268. if (NT_SUCCESS(status)) {
  269. extension->CountersEnabled = TRUE;
  270. return TRUE;
  271. }
  272. else {
  273. InterlockedExchange(&extension->EnableAlways, 0);
  274. }
  275. }
  276. }
  277. return FALSE;
  278. }