Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

555 lines
15 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1999
  3. Module Name:
  4. mcdwmi.c
  5. Abstract:
  6. This is the changer class driver - WMI support routines.
  7. Environment:
  8. kernel mode only
  9. Revision History:
  10. --*/
  11. #include "mchgr.h"
  12. //
  13. // Internal routines
  14. //
  15. NTSTATUS
  16. ChangerWMIGetParameters(
  17. IN PDEVICE_OBJECT DeviceObject,
  18. OUT PGET_CHANGER_PARAMETERS changerParameters
  19. );
  20. //
  21. // List of WMI GUIDs
  22. //
  23. GUIDREGINFO ChangerWmiFdoGuidList[] =
  24. {
  25. {
  26. WMI_CHANGER_PARAMETERS_GUID,
  27. 1,
  28. 0
  29. },
  30. {
  31. WMI_CHANGER_PROBLEM_WARNING_GUID,
  32. 1,
  33. WMIREG_FLAG_EVENT_ONLY_GUID
  34. },
  35. {
  36. WMI_CHANGER_PROBLEM_DEVICE_ERROR_GUID,
  37. 1,
  38. WMIREG_FLAG_EXPENSIVE
  39. },
  40. };
  41. GUID ChangerDriveProblemEventGuid = WMI_CHANGER_PROBLEM_WARNING_GUID;
  42. //
  43. // GUID index. It should match the list defined above
  44. //
  45. #define ChangerParametersGuid 0
  46. #define ChangerProblemWarningGuid 1
  47. #define ChangerProblemDevErrorGuid 2
  48. //
  49. // ISSUE: 02/29/2000 - nramas : Should make wmi routines pagable
  50. //
  51. /*
  52. #ifdef ALLOC_PRAGMA
  53. #pragma alloc_text(PAGE,
  54. #endif
  55. */
  56. NTSTATUS
  57. ChangerFdoQueryWmiRegInfo(
  58. IN PDEVICE_OBJECT DeviceObject,
  59. OUT ULONG *RegFlags,
  60. OUT PUNICODE_STRING InstanceName
  61. )
  62. /*++
  63. Routine Description:
  64. This routine is a callback into the driver to retrieve the list of
  65. guids or data blocks that the driver wants to register with WMI. This
  66. routine may not pend or block. Driver should NOT call
  67. ClassWmiCompleteRequest.
  68. Arguments:
  69. DeviceObject is the device whose data block is being queried
  70. *RegFlags returns with a set of flags that describe the guids being
  71. registered for this device. If the device wants enable and disable
  72. collection callbacks before receiving queries for the registered
  73. guids then it should return the WMIREG_FLAG_EXPENSIVE flag. Also the
  74. returned flags may specify WMIREG_FLAG_INSTANCE_PDO in which case
  75. the instance name is determined from the PDO associated with the
  76. device object. Note that the PDO must have an associated devnode. If
  77. WMIREG_FLAG_INSTANCE_PDO is not set then Name must return a unique
  78. name for the device.
  79. InstanceName returns with the instance name for the guids if
  80. WMIREG_FLAG_INSTANCE_PDO is not set in the returned *RegFlags. The
  81. caller will call ExFreePool with the buffer returned.
  82. Return Value:
  83. status
  84. --*/
  85. {
  86. //
  87. // Use devnode for FDOs
  88. //
  89. *RegFlags = WMIREG_FLAG_INSTANCE_PDO;
  90. return STATUS_SUCCESS;
  91. }
  92. NTSTATUS
  93. ChangerFdoQueryWmiDataBlock(
  94. IN PDEVICE_OBJECT DeviceObject,
  95. IN PIRP Irp,
  96. IN ULONG GuidIndex,
  97. IN ULONG BufferAvail,
  98. OUT PUCHAR Buffer
  99. )
  100. /*++
  101. Routine Description:
  102. This routine is a callback into the driver to query for the contents of
  103. a data block. When the driver has finished filling the data block it
  104. must call ClassWmiCompleteRequest to complete the irp. The driver can
  105. return STATUS_PENDING if the irp cannot be completed immediately.
  106. Arguments:
  107. DeviceObject is the device whose data block is being queried
  108. Irp is the Irp that makes this request
  109. GuidIndex is the index into the list of guids provided when the
  110. device registered
  111. BufferAvail on has the maximum size available to write the data
  112. block.
  113. Buffer on return is filled with the returned data block
  114. Return Value:
  115. status
  116. --*/
  117. {
  118. NTSTATUS status = STATUS_SUCCESS;
  119. PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = DeviceObject->DeviceExtension;
  120. PMCD_INIT_DATA mcdInitData;
  121. ULONG sizeNeeded = 0;
  122. switch (GuidIndex) {
  123. case ChangerParametersGuid: {
  124. GET_CHANGER_PARAMETERS changerParameters;
  125. PWMI_CHANGER_PARAMETERS outBuffer;
  126. sizeNeeded = sizeof(WMI_CHANGER_PARAMETERS);
  127. if (BufferAvail < sizeNeeded) {
  128. status = STATUS_BUFFER_TOO_SMALL;
  129. break;
  130. }
  131. status = ChangerWMIGetParameters(DeviceObject,
  132. &changerParameters);
  133. if (NT_SUCCESS(status)) {
  134. outBuffer = (PWMI_CHANGER_PARAMETERS)Buffer;
  135. outBuffer->NumberOfSlots = changerParameters.NumberStorageElements;
  136. outBuffer->NumberOfDrives = changerParameters.NumberDataTransferElements;
  137. outBuffer->NumberOfIEPorts = changerParameters.NumberIEElements;
  138. outBuffer->NumberOfTransports = changerParameters.NumberTransportElements;
  139. outBuffer->NumberOfDoors = changerParameters.NumberOfDoors;
  140. outBuffer->MagazineSize = changerParameters.MagazineSize;
  141. outBuffer->NumberOfCleanerSlots = changerParameters.NumberCleanerSlots;
  142. }
  143. break;
  144. }
  145. case ChangerProblemDevErrorGuid: {
  146. PWMI_CHANGER_PROBLEM_DEVICE_ERROR changerDeviceError;
  147. mcdInitData = IoGetDriverObjectExtension(DeviceObject->DriverObject,
  148. ChangerClassInitialize);
  149. if (mcdInitData == NULL) {
  150. status = STATUS_NO_SUCH_DEVICE;
  151. break;
  152. }
  153. if (!(mcdInitData->ChangerPerformDiagnostics)) {
  154. status = STATUS_NOT_IMPLEMENTED;
  155. break;
  156. }
  157. sizeNeeded = sizeof(WMI_CHANGER_PROBLEM_DEVICE_ERROR);
  158. if (BufferAvail < sizeNeeded) {
  159. status = STATUS_BUFFER_TOO_SMALL;
  160. break;
  161. }
  162. changerDeviceError = (PWMI_CHANGER_PROBLEM_DEVICE_ERROR)Buffer;
  163. RtlZeroMemory(changerDeviceError,
  164. sizeof(WMI_CHANGER_PROBLEM_DEVICE_ERROR));
  165. status = mcdInitData->ChangerPerformDiagnostics(DeviceObject,
  166. changerDeviceError);
  167. break;
  168. }
  169. default: {
  170. sizeNeeded = 0;
  171. status = STATUS_WMI_GUID_NOT_FOUND;
  172. break;
  173. }
  174. } // switch (GuidIndex)
  175. status = ClassWmiCompleteRequest(DeviceObject,
  176. Irp,
  177. status,
  178. sizeNeeded,
  179. IO_NO_INCREMENT);
  180. return status;
  181. }
  182. NTSTATUS
  183. ChangerWMIGetParameters(
  184. IN PDEVICE_OBJECT DeviceObject,
  185. OUT PGET_CHANGER_PARAMETERS changerParameters
  186. )
  187. /*+++
  188. Routine Description:
  189. Sends the IOCTL to get the changer parameters
  190. Arguments :
  191. DeviceObject The changer device objcet
  192. ChangerParameters buffer in which the changer parameters is returned.
  193. Return value:
  194. NT Status.
  195. --*/
  196. {
  197. KEVENT event;
  198. PDEVICE_OBJECT topOfStack;
  199. PIRP irp = NULL;
  200. IO_STATUS_BLOCK ioStatus;
  201. NTSTATUS status;
  202. KeInitializeEvent(&event, SynchronizationEvent, FALSE);
  203. topOfStack = IoGetAttachedDeviceReference(DeviceObject);
  204. //
  205. // Send down irp to get the changer parameters
  206. //
  207. irp = IoBuildDeviceIoControlRequest(
  208. IOCTL_CHANGER_GET_PARAMETERS,
  209. topOfStack,
  210. NULL,
  211. 0,
  212. changerParameters,
  213. sizeof(GET_CHANGER_PARAMETERS),
  214. FALSE,
  215. &event,
  216. &ioStatus);
  217. if (irp != NULL) {
  218. status = IoCallDriver(topOfStack, irp);
  219. if (status == STATUS_PENDING) {
  220. KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
  221. status = ioStatus.Status;
  222. }
  223. } else {
  224. status = STATUS_INSUFFICIENT_RESOURCES;
  225. }
  226. ObDereferenceObject(topOfStack);
  227. return status;
  228. }
  229. NTSTATUS
  230. ChangerWmiFunctionControl(
  231. IN PDEVICE_OBJECT DeviceObject,
  232. IN PIRP Irp,
  233. IN ULONG GuidIndex,
  234. IN CLASSENABLEDISABLEFUNCTION Function,
  235. IN BOOLEAN Enable
  236. )
  237. /*++
  238. Routine Description:
  239. This routine is a callback into the driver to enabled or disable event
  240. generation or data block collection. A device should only expect a
  241. single enable when the first event or data consumer enables events or
  242. data collection and a single disable when the last event or data
  243. consumer disables events or data collection. Data blocks will only
  244. receive collection enable/disable if they were registered as requiring
  245. it.
  246. This function can be used to enable\disable datablock collection.
  247. Arguments:
  248. DeviceObject is the device whose data block is being queried
  249. GuidIndex is the index into the list of guids provided when the
  250. device registered
  251. Function specifies which functionality is being enabled or disabled
  252. Enable is TRUE then the function is being enabled else disabled
  253. Return Value:
  254. status
  255. --*/
  256. {
  257. NTSTATUS status;
  258. if (Function == DataBlockCollection) {
  259. DebugPrint((3,
  260. "ChangerWmiFunctionControl : Irp %p - %s DataBlockCollection",
  261. " for Device %p.\n",
  262. Irp, Enable ? "Enable " : "Disable ", DeviceObject));
  263. status = STATUS_SUCCESS;
  264. } else {
  265. //
  266. // ISSUE: 03/01/2000 - nramas
  267. // Need to handle EventGeneration. But now we don't do polling
  268. // of the changers to detect failure. So, for now disallow
  269. // EventGeneration
  270. //
  271. DebugPrint((1,
  272. "ChangerWmiFunctionControl : Unknown function %d for ",
  273. "Device %p, Irp %p\n",
  274. Function, DeviceObject, Irp));
  275. status = STATUS_INVALID_DEVICE_REQUEST;
  276. }
  277. status = ClassWmiCompleteRequest(DeviceObject,
  278. Irp,
  279. status,
  280. 0,
  281. IO_NO_INCREMENT);
  282. return status;
  283. }
  284. NTSTATUS
  285. ChangerFdoExecuteWmiMethod(
  286. IN PDEVICE_OBJECT DeviceObject,
  287. IN PIRP Irp,
  288. IN ULONG GuidIndex,
  289. IN ULONG MethodId,
  290. IN ULONG InBufferSize,
  291. IN ULONG OutBufferSize,
  292. IN PUCHAR Buffer
  293. )
  294. /*++
  295. Routine Description:
  296. This routine is a callback into the driver to execute a method. When the
  297. driver has finished filling the data block it must call
  298. ClassWmiCompleteRequest to complete the irp. The driver can
  299. return STATUS_PENDING if the irp cannot be completed immediately.
  300. Arguments:
  301. DeviceObject is the device whose data block is being queried
  302. Irp is the Irp that makes this request
  303. GuidIndex is the index into the list of guids provided when the
  304. device registered
  305. MethodId has the id of the method being called
  306. InBufferSize has the size of the data block passed in as the input to
  307. the method.
  308. OutBufferSize on entry has the maximum size available to write the
  309. returned data block.
  310. Buffer is filled with the returned data block
  311. Return Value:
  312. status
  313. --*/
  314. {
  315. NTSTATUS status = STATUS_SUCCESS;
  316. DebugPrint((3,
  317. "ChangerFdoExecuteMethod : Device %p, Irp %p, ",
  318. "GuidIndex %d\n",
  319. DeviceObject, Irp, GuidIndex));
  320. if (GuidIndex > ChangerProblemDevErrorGuid) {
  321. status = STATUS_WMI_GUID_NOT_FOUND;
  322. }
  323. status = ClassWmiCompleteRequest(DeviceObject,
  324. Irp,
  325. status,
  326. 0,
  327. IO_NO_INCREMENT);
  328. return status;
  329. }
  330. NTSTATUS
  331. ChangerFdoSetWmiDataBlock(
  332. IN PDEVICE_OBJECT DeviceObject,
  333. IN PIRP Irp,
  334. IN ULONG GuidIndex,
  335. IN ULONG BufferSize,
  336. IN PUCHAR Buffer
  337. )
  338. /*+
  339. Routine Description :
  340. This routine is called to set the contents of a datablock.
  341. When the driver is finished setting the buffer, it must call
  342. ClassWmiCompleteRequest to complete the irp. The driver can
  343. return STATUS_PENDING if the irp cannot be completed immediately.
  344. Arguments :
  345. Device object of the device being referred.
  346. Irp is the WMI Irp
  347. GuidIndex is the index of the guid for which the data is being set
  348. BufferSize is the size of the data block
  349. Buffer is the pointer to the data block
  350. Return valus :
  351. NTSTATUS returned by ClassWmiCompleteRequest
  352. STATUS_WMI_READ_ONLY if the datablock cannot be modified.
  353. STATUS_WMI_GUID_NOT_FOUND if an invalid guid index is passed
  354. -*/
  355. {
  356. NTSTATUS status = STATUS_WMI_READ_ONLY;
  357. DebugPrint((3,
  358. "ChangerWmiSetBlock : Device %p, Irp %p, ",
  359. "GuidIndex %d\n",
  360. DeviceObject, Irp, GuidIndex));
  361. if (GuidIndex > ChangerProblemDevErrorGuid) {
  362. status = STATUS_WMI_GUID_NOT_FOUND;
  363. }
  364. status = ClassWmiCompleteRequest(DeviceObject,
  365. Irp,
  366. status,
  367. 0,
  368. IO_NO_INCREMENT);
  369. DebugPrint((3, "ChangerSetWmiDataBlock : Device %p, Irp %p, returns %x\n",
  370. DeviceObject, Irp, status));
  371. return status;
  372. }
  373. NTSTATUS
  374. ChangerFdoSetWmiDataItem(
  375. IN PDEVICE_OBJECT DeviceObject,
  376. IN PIRP Irp,
  377. IN ULONG GuidIndex,
  378. IN ULONG DataItemId,
  379. IN ULONG BufferSize,
  380. IN PUCHAR Buffer
  381. )
  382. /*++
  383. Routine Description:
  384. This routine is a callback into the driver to query for the contents of
  385. a data block. When the driver has finished filling the data block it
  386. must call ClassWmiCompleteRequest to complete the irp. The driver can
  387. return STATUS_PENDING if the irp cannot be completed immediately.
  388. Arguments:
  389. DeviceObject is the device whose data block is being queried
  390. Irp is the Irp that makes this request
  391. GuidIndex is the index into the list of guids provided when the
  392. device registered
  393. DataItemId has the id of the data item being set
  394. BufferSize has the size of the data item passed
  395. Buffer has the new values for the data item
  396. Return Value:
  397. NTSTATUS returned by ClassWmiCompleteRequest
  398. STATUS_WMI_READ_ONLY if the datablock cannot be modified.
  399. STATUS_WMI_GUID_NOT_FOUND if an invalid guid index is passed
  400. -*/
  401. {
  402. NTSTATUS status = STATUS_WMI_READ_ONLY;
  403. DebugPrint((3,
  404. "TapeSetWmiDataItem, Device %p, Irp %p, GuiIndex %d",
  405. " BufferSize %#x Buffer %p\n",
  406. DeviceObject, Irp,
  407. GuidIndex, DataItemId,
  408. BufferSize, Buffer));
  409. if (GuidIndex > ChangerProblemDevErrorGuid) {
  410. status = STATUS_WMI_GUID_NOT_FOUND;
  411. }
  412. status = ClassWmiCompleteRequest(DeviceObject,
  413. Irp,
  414. status,
  415. 0,
  416. IO_NO_INCREMENT);
  417. DebugPrint((3, "TapeSetWmiDataItem Device %p, Irp %p returns %lx\n",
  418. DeviceObject, Irp, status));
  419. return status;
  420. }