xref: /reactos/drivers/bluetooth/fbtusb/fbtwmi.c (revision c2c66aff)
1 // Copyright (c) 2004, Antony C. Roberts
2 
3 // Use of this file is subject to the terms
4 // described in the LICENSE.TXT file that
5 // accompanies this file.
6 //
7 // Your use of this file indicates your
8 // acceptance of the terms described in
9 // LICENSE.TXT.
10 //
11 // http://www.freebt.net
12 
13 #include "fbtusb.h"
14 #include "fbtpwr.h"
15 #include "fbtpnp.h"
16 #include "fbtdev.h"
17 #include "fbtrwr.h"
18 #include "fbtwmi.h"
19 
20 #include "fbtusr.h"
21 
22 #define MOFRESOURCENAME L"MofResourceName"
23 
24 #define WMI_FREEBT_DRIVER_INFORMATION 0
25 
26 DEFINE_GUID (FREEBT_WMI_STD_DATA_GUID, 0x871B1A60, 0xD3EA, 0x4f2f, 0x81, 0x7b, 0x46, 0x5e, 0x44, 0x86, 0x7b, 0xf5);
27 
28 WMIGUIDREGINFO FreeBTWmiGuidList[1] =
29 {
30 	{
31 		&FREEBT_WMI_STD_DATA_GUID, 1, 0 // driver information
32 
33     }
34 
35 };
36 
FreeBT_WmiRegistration(IN OUT PDEVICE_EXTENSION DeviceExtension)37 NTSTATUS NTAPI FreeBT_WmiRegistration(IN OUT PDEVICE_EXTENSION DeviceExtension)
38 {
39     NTSTATUS ntStatus;
40 
41     PAGED_CODE();
42 
43     DeviceExtension->WmiLibInfo.GuidCount = sizeof (FreeBTWmiGuidList) / sizeof (WMIGUIDREGINFO);
44     DeviceExtension->WmiLibInfo.GuidList           = FreeBTWmiGuidList;
45     DeviceExtension->WmiLibInfo.QueryWmiRegInfo    = FreeBT_QueryWmiRegInfo;
46     DeviceExtension->WmiLibInfo.QueryWmiDataBlock  = FreeBT_QueryWmiDataBlock;
47     DeviceExtension->WmiLibInfo.SetWmiDataBlock    = FreeBT_SetWmiDataBlock;
48     DeviceExtension->WmiLibInfo.SetWmiDataItem     = FreeBT_SetWmiDataItem;
49     DeviceExtension->WmiLibInfo.ExecuteWmiMethod   = NULL;
50     DeviceExtension->WmiLibInfo.WmiFunctionControl = NULL;
51 
52     // Register with WMI
53     ntStatus = IoWMIRegistrationControl(DeviceExtension->FunctionalDeviceObject, WMIREG_ACTION_REGISTER);
54 
55     return ntStatus;
56 
57 }
58 
FreeBT_WmiDeRegistration(IN OUT PDEVICE_EXTENSION DeviceExtension)59 NTSTATUS NTAPI FreeBT_WmiDeRegistration(IN OUT PDEVICE_EXTENSION DeviceExtension)
60 {
61     PAGED_CODE();
62     return IoWMIRegistrationControl(DeviceExtension->FunctionalDeviceObject, WMIREG_ACTION_DEREGISTER);
63 
64 }
65 
FreeBT_DispatchSysCtrl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)66 NTSTATUS NTAPI FreeBT_DispatchSysCtrl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
67 {
68     PDEVICE_EXTENSION       deviceExtension;
69     SYSCTL_IRP_DISPOSITION  disposition;
70     NTSTATUS                ntStatus;
71     PIO_STACK_LOCATION      irpStack;
72 
73     PAGED_CODE();
74 
75     irpStack = IoGetCurrentIrpStackLocation (Irp);
76     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
77 
78 	FreeBT_DbgPrint(3, ("FBTUSB: "));
79     FreeBT_DbgPrint(3, (WMIMinorFunctionString(irpStack->MinorFunction)));
80     if (Removed == deviceExtension->DeviceState)
81 	{
82         ntStatus = STATUS_DELETE_PENDING;
83 
84         Irp->IoStatus.Status = ntStatus;
85         Irp->IoStatus.Information = 0;
86         IoCompleteRequest(Irp, IO_NO_INCREMENT);
87 
88         return ntStatus;
89 
90     }
91 
92     FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchSysCtrl::"));
93     FreeBT_IoIncrement(deviceExtension);
94 
95     ntStatus = WmiSystemControl(&deviceExtension->WmiLibInfo,
96                                 DeviceObject,
97                                 Irp,
98                                 &disposition);
99 
100     switch(disposition)
101 	{
102         case IrpProcessed:
103         {
104             // This irp has been processed and may be completed or pending.
105             break;
106 
107         }
108 
109         case IrpNotCompleted:
110         {
111             // This irp has not been completed, but has been fully processed.
112             // we will complete it now
113             IoCompleteRequest(Irp, IO_NO_INCREMENT);
114             break;
115 
116         }
117 
118         case IrpForward:
119         case IrpNotWmi:
120         {
121             // This irp is either not a WMI irp or is a WMI irp targeted
122             // at a device lower in the stack.
123             IoSkipCurrentIrpStackLocation (Irp);
124             ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
125             break;
126         }
127 
128         default:
129         {
130             // We really should never get here, but if we do just forward....
131             ASSERT(FALSE);
132             IoSkipCurrentIrpStackLocation (Irp);
133             ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
134             break;
135 
136         }
137 
138     }
139 
140     FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_DispatchSysCtrl::"));
141     FreeBT_IoDecrement(deviceExtension);
142 
143     return ntStatus;
144 
145 }
146 
FreeBT_QueryWmiRegInfo(IN PDEVICE_OBJECT DeviceObject,OUT ULONG * RegFlags,OUT PUNICODE_STRING InstanceName,OUT PUNICODE_STRING * RegistryPath,OUT PUNICODE_STRING MofResourceName,OUT PDEVICE_OBJECT * Pdo)147 NTSTATUS NTAPI FreeBT_QueryWmiRegInfo(
148     IN  PDEVICE_OBJECT  DeviceObject,
149     OUT ULONG           *RegFlags,
150     OUT PUNICODE_STRING InstanceName,
151     OUT PUNICODE_STRING *RegistryPath,
152     OUT PUNICODE_STRING MofResourceName,
153     OUT PDEVICE_OBJECT  *Pdo
154     )
155 /*++
156 
157 Routine Description:
158 
159     This routine is a callback into the driver to retrieve the list of
160     guids or data blocks that the driver wants to register with WMI. This
161     routine may not pend or block. Driver should NOT call
162     WmiCompleteRequest.
163 
164 Arguments:
165 
166     DeviceObject is the device whose data block is being queried
167 
168     *RegFlags returns with a set of flags that describe the guids being
169         registered for this device. If the device wants enable and disable
170         collection callbacks before receiving queries for the registered
171         guids then it should return the WMIREG_FLAG_EXPENSIVE flag. Also the
172         returned flags may specify WMIREG_FLAG_INSTANCE_PDO in which case
173         the instance name is determined from the PDO associated with the
174         device object. Note that the PDO must have an associated devnode. If
175         WMIREG_FLAG_INSTANCE_PDO is not set then Name must return a unique
176         name for the device.
177 
178     InstanceName returns with the instance name for the guids if
179         WMIREG_FLAG_INSTANCE_PDO is not set in the returned *RegFlags. The
180         caller will call ExFreePool with the buffer returned.
181 
182     *RegistryPath returns with the registry path of the driver
183 
184     *MofResourceName returns with the name of the MOF resource attached to
185         the binary file. If the driver does not have a mof resource attached
186         then this can be returned as NULL.
187 
188     *Pdo returns with the device object for the PDO associated with this
189         device if the WMIREG_FLAG_INSTANCE_PDO flag is returned in
190         *RegFlags.
191 
192 Return Value:
193 
194     status
195 
196 --*/
197 {
198     PDEVICE_EXTENSION deviceExtension;
199 
200     PAGED_CODE();
201 
202     FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_QueryWmiRegInfo: Entered\n"));
203 
204     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
205 
206     *RegFlags     = WMIREG_FLAG_INSTANCE_PDO;
207     *RegistryPath = &Globals.FreeBT_RegistryPath;
208     *Pdo          = deviceExtension->PhysicalDeviceObject;
209     RtlInitUnicodeString(MofResourceName, MOFRESOURCENAME);
210 
211     FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_QueryWmiRegInfo: Leaving\n"));
212 
213     return STATUS_SUCCESS;
214 
215 }
216 
FreeBT_QueryWmiDataBlock(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN ULONG GuidIndex,IN ULONG InstanceIndex,IN ULONG InstanceCount,IN OUT PULONG InstanceLengthArray,IN ULONG OutBufferSize,OUT PUCHAR Buffer)217 NTSTATUS NTAPI FreeBT_QueryWmiDataBlock(
218     IN PDEVICE_OBJECT DeviceObject,
219     IN PIRP           Irp,
220     IN ULONG          GuidIndex,
221     IN ULONG          InstanceIndex,
222     IN ULONG          InstanceCount,
223     IN OUT PULONG     InstanceLengthArray,
224     IN ULONG          OutBufferSize,
225     OUT PUCHAR        Buffer
226     )
227 /*++
228 
229 Routine Description:
230 
231     This routine is a callback into the driver to query for the contents of
232     a data block. When the driver has finished filling the data block it
233     must call WmiCompleteRequest to complete the irp. The driver can
234     return STATUS_PENDING if the irp cannot be completed immediately.
235 
236 Arguments:
237 
238     DeviceObject is the device whose data block is being queried
239 
240     Irp is the Irp that makes this request
241 
242     GuidIndex is the index into the list of guids provided when the
243         device registered
244 
245     InstanceIndex is the index that denotes which instance of the data block
246         is being queried.
247 
248     InstanceCount is the number of instances expected to be returned for
249         the data block.
250 
251     InstanceLengthArray is a pointer to an array of ULONG that returns the
252         lengths of each instance of the data block. If this is NULL then
253         there was not enough space in the output buffer to fulfill the request
254         so the irp should be completed with the buffer needed.
255 
256     OutBufferSize has the maximum size available to write the data
257         block.
258 
259     Buffer on return is filled with the returned data block
260 
261 
262 Return Value:
263 
264     status
265 
266 --*/
267 {
268     PDEVICE_EXTENSION deviceExtension;
269     NTSTATUS          ntStatus;
270     ULONG             size;
271     WCHAR             modelName[] = L"Aishverya\0\0";
272     USHORT            modelNameLen;
273 
274     PAGED_CODE();
275 
276     FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_QueryWmiDataBlock: Entered\n"));
277 
278     size = 0;
279     modelNameLen = (wcslen(modelName) + 1) * sizeof(WCHAR);
280 
281     // Only ever registers 1 instance per guid
282     ASSERT((InstanceIndex == 0) && (InstanceCount == 1));
283 
284     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
285     switch (GuidIndex)
286 	{
287     case WMI_FREEBT_DRIVER_INFORMATION:
288         size = sizeof(ULONG) + modelNameLen + sizeof(USHORT);
289         if (OutBufferSize < size )
290 		{
291             FreeBT_DbgPrint(3, ("FBTUSB: OutBuffer too small\n"));
292             ntStatus = STATUS_BUFFER_TOO_SMALL;
293             break;
294 
295         }
296 
297         * (PULONG) Buffer = DebugLevel;
298         Buffer += sizeof(ULONG);
299 
300         // put length of string ahead of string
301         *((PUSHORT)Buffer) = modelNameLen;
302         Buffer = (PUCHAR)Buffer + sizeof(USHORT);
303         RtlCopyBytes((PVOID)Buffer, (PVOID)modelName, modelNameLen);
304         *InstanceLengthArray = size ;
305 
306         ntStatus = STATUS_SUCCESS;
307         break;
308 
309     default:
310         ntStatus = STATUS_WMI_GUID_NOT_FOUND;
311 
312     }
313 
314     ntStatus = WmiCompleteRequest(DeviceObject,
315                                 Irp,
316                                 ntStatus,
317                                 size,
318                                 IO_NO_INCREMENT);
319 
320     FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_QueryWmiDataBlock: Leaving\n"));
321 
322     return ntStatus;
323 
324 }
325 
326 
FreeBT_SetWmiDataItem(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN ULONG GuidIndex,IN ULONG InstanceIndex,IN ULONG DataItemId,IN ULONG BufferSize,IN PUCHAR Buffer)327 NTSTATUS NTAPI FreeBT_SetWmiDataItem(
328     IN PDEVICE_OBJECT DeviceObject,
329     IN PIRP           Irp,
330     IN ULONG          GuidIndex,
331     IN ULONG          InstanceIndex,
332     IN ULONG          DataItemId,
333     IN ULONG          BufferSize,
334     IN PUCHAR         Buffer
335     )
336 /*++
337 
338 Routine Description:
339 
340     This routine is a callback into the driver to set for the contents of
341     a data block. When the driver has finished filling the data block it
342     must call WmiCompleteRequest to complete the irp. The driver can
343     return STATUS_PENDING if the irp cannot be completed immediately.
344 
345 Arguments:
346 
347     DeviceObject is the device whose data block is being queried
348 
349     Irp is the Irp that makes this request
350 
351     GuidIndex is the index into the list of guids provided when the
352         device registered
353 
354     InstanceIndex is the index that denotes which instance of the data block
355         is being queried.
356 
357     DataItemId has the id of the data item being set
358 
359     BufferSize has the size of the data item passed
360 
361     Buffer has the new values for the data item
362 
363 
364 Return Value:
365 
366     status
367 
368 --*/
369 {
370     PDEVICE_EXTENSION deviceExtension;
371     NTSTATUS          ntStatus;
372     ULONG             info;
373 
374     PAGED_CODE();
375 
376     FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_SetWmiDataItem: Entered\n"));
377 
378     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
379     info = 0;
380 
381     switch(GuidIndex)
382 	{
383     case WMI_FREEBT_DRIVER_INFORMATION:
384         if(DataItemId == 1)
385 		{
386             if(BufferSize == sizeof(ULONG))
387 			{
388                 DebugLevel = *((PULONG)Buffer);
389                 ntStatus = STATUS_SUCCESS;
390                 info = sizeof(ULONG);
391 
392             }
393 
394             else
395 			{
396                 ntStatus = STATUS_INFO_LENGTH_MISMATCH;
397 
398             }
399 
400         }
401 
402         else
403 		{
404             ntStatus = STATUS_WMI_READ_ONLY;
405 
406         }
407 
408         break;
409 
410     default:
411         ntStatus = STATUS_WMI_GUID_NOT_FOUND;
412 
413     }
414 
415     ntStatus = WmiCompleteRequest(DeviceObject,
416                                 Irp,
417                                 ntStatus,
418                                 info,
419                                 IO_NO_INCREMENT);
420 
421     FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_SetWmiDataItem: Leaving\n"));
422 
423     return ntStatus;
424 
425 }
426 
FreeBT_SetWmiDataBlock(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN ULONG GuidIndex,IN ULONG InstanceIndex,IN ULONG BufferSize,IN PUCHAR Buffer)427 NTSTATUS NTAPI FreeBT_SetWmiDataBlock(
428     IN PDEVICE_OBJECT DeviceObject,
429     IN PIRP           Irp,
430     IN ULONG          GuidIndex,
431     IN ULONG          InstanceIndex,
432     IN ULONG          BufferSize,
433     IN PUCHAR         Buffer
434     )
435 /*++
436 
437 Routine Description:
438 
439     This routine is a callback into the driver to set the contents of
440     a data block. When the driver has finished filling the data block it
441     must call WmiCompleteRequest to complete the irp. The driver can
442     return STATUS_PENDING if the irp cannot be completed immediately.
443 
444 Arguments:
445 
446     DeviceObject is the device whose data block is being queried
447 
448     Irp is the Irp that makes this request
449 
450     GuidIndex is the index into the list of guids provided when the
451         device registered
452 
453     InstanceIndex is the index that denotes which instance of the data block
454         is being queried.
455 
456     BufferSize has the size of the data block passed
457 
458     Buffer has the new values for the data block
459 
460 --*/
461 {
462     PDEVICE_EXTENSION deviceExtension;
463     NTSTATUS          ntStatus;
464     ULONG             info;
465 
466     PAGED_CODE();
467 
468     FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_SetWmiDataBlock: Entered\n"));
469 
470     deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
471     info = 0;
472 
473     switch(GuidIndex)
474 	{
475     case WMI_FREEBT_DRIVER_INFORMATION:
476         if(BufferSize == sizeof(ULONG))
477 		{
478             DebugLevel = *(PULONG) Buffer;
479             ntStatus = STATUS_SUCCESS;
480             info = sizeof(ULONG);
481 
482         }
483 
484         else
485 		{
486             ntStatus = STATUS_INFO_LENGTH_MISMATCH;
487 
488         }
489 
490         break;
491 
492     default:
493         ntStatus = STATUS_WMI_GUID_NOT_FOUND;
494 
495     }
496 
497     ntStatus = WmiCompleteRequest(DeviceObject,
498                                 Irp,
499                                 ntStatus,
500                                 info,
501                                 IO_NO_INCREMENT);
502 
503     FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_SetWmiDataBlock: Leaving\n"));
504 
505     return ntStatus;
506 
507 }
508 
WMIMinorFunctionString(UCHAR MinorFunction)509 PCHAR NTAPI WMIMinorFunctionString(UCHAR MinorFunction)
510 {
511     switch (MinorFunction)
512 	{
513         case IRP_MN_CHANGE_SINGLE_INSTANCE:
514             return "IRP_MN_CHANGE_SINGLE_INSTANCE\n";
515 
516         case IRP_MN_CHANGE_SINGLE_ITEM:
517             return "IRP_MN_CHANGE_SINGLE_ITEM\n";
518 
519         case IRP_MN_DISABLE_COLLECTION:
520             return "IRP_MN_DISABLE_COLLECTION\n";
521 
522         case IRP_MN_DISABLE_EVENTS:
523             return "IRP_MN_DISABLE_EVENTS\n";
524 
525         case IRP_MN_ENABLE_COLLECTION:
526             return "IRP_MN_ENABLE_COLLECTION\n";
527 
528         case IRP_MN_ENABLE_EVENTS:
529             return "IRP_MN_ENABLE_EVENTS\n";
530 
531         case IRP_MN_EXECUTE_METHOD:
532             return "IRP_MN_EXECUTE_METHOD\n";
533 
534         case IRP_MN_QUERY_ALL_DATA:
535             return "IRP_MN_QUERY_ALL_DATA\n";
536 
537         case IRP_MN_QUERY_SINGLE_INSTANCE:
538             return "IRP_MN_QUERY_SINGLE_INSTANCE\n";
539 
540         case IRP_MN_REGINFO:
541             return "IRP_MN_REGINFO\n";
542 
543         default:
544             return "IRP_MN_?????\n";
545 
546     }
547 
548 }
549