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